Amazon Price Checker (FR, DE, ES, IT, BE, NL, UK, COM) + AliExpress

Maximize your savings by effortlessly comparing prices across Amazon.fr, .de, .es, .it, .be, .nl, .co.uk, and .com. Automatically detect coupons, enjoy fast dynamic result displays, access comprehensive price histories with CamelCamelCamel, convert prices to EUR based on current exchange rates, and find the best product alternatives on AliExpress with intelligent searches. Save more with every purchase!

// ==UserScript==
// @name         Amazon Price Checker (FR, DE, ES, IT, BE, NL, UK, COM) + AliExpress
// @namespace    http://tampermonkey.net/
// @version      3.11
// @description  Maximize your savings by effortlessly comparing prices across Amazon.fr, .de, .es, .it, .be, .nl, .co.uk, and .com. Automatically detect coupons, enjoy fast dynamic result displays, access comprehensive price histories with CamelCamelCamel, convert prices to EUR based on current exchange rates, and find the best product alternatives on AliExpress with intelligent searches. Save more with every purchase!
// @icon         https://i.ibb.co/qrjrcVy/amz-price-checker.png
// @match        https://www.amazon.fr/*
// @match        https://www.amazon.de/*
// @match        https://www.amazon.es/*
// @match        https://www.amazon.it/*
// @match        https://www.amazon.com.be/*
// @match        https://www.amazon.nl/*
// @match        https://www.amazon.co.uk/*
// @match        https://www.amazon.com/*
// @grant        GM_xmlhttpRequest
// @connect      amazon.fr
// @connect      amazon.de
// @connect      amazon.es
// @connect      amazon.it
// @connect      amazon.com.be
// @connect      amazon.nl
// @connect      amazon.co.uk
// @connect      amazon.com
// @connect      summarizer.mon-bnj.workers.dev
// @connect      api.frankfurter.app
// @license      All Rights Reserved
// @antifeature  referral-link
// @antifeature  tracking
// ==/UserScript==

(function(){
  'use strict';

  const ASIN_REGEX = /\/([A-Z0-9]{10})(?:[/?]|$)/;
  const PARTNER_IDS = {
    fr: 'bnjmazon-21',
    es: 'bnjmazon08-21',
    it: 'bnjmazon0d-21',
    de: 'geeksince190d-21',
    'com.be': 'geeksince1900',
    nl: 'bnjmazon-21',
    'co.uk': 'bnjmazon-UK-21',
    com: 'bnjmazon-20'
  };
  const amazonSites = [
    { name:'Amazon.fr',    country:'fr',     flag:'https://flagcdn.com/w20/fr.png', currency: 'EUR', needsConversion: false },
    { name:'Amazon.es',    country:'es',     flag:'https://flagcdn.com/w20/es.png', currency: 'EUR', needsConversion: false },
    { name:'Amazon.it',    country:'it',     flag:'https://flagcdn.com/w20/it.png', currency: 'EUR', needsConversion: false },
    { name:'Amazon.de',    country:'de',     flag:'https://flagcdn.com/w20/de.png', currency: 'EUR', needsConversion: false },
    { name:'Amazon.be',    country:'com.be', flag:'https://flagcdn.com/w20/be.png', currency: 'EUR', needsConversion: false },
    { name:'Amazon.nl',    country:'nl',     flag:'https://flagcdn.com/w20/nl.png', currency: 'EUR', needsConversion: false },
    { name:'Amazon.co.uk', country:'co.uk',  flag:'https://flagcdn.com/w20/gb.png', currency: 'GBP', needsConversion: true },
    { name:'Amazon.com',   country:'com',    flag:'https://flagcdn.com/w20/us.png', currency: 'USD', needsConversion: true }
  ];

  let asin, basePrice, selectedTimePeriod = 'all';
  let priceResults = [], requestCount = 0, firstPriceLoaded = false;
  let tableContainer, headerRow, priceContainer;
  let exchangeRates = null;
  let footerAdded = false;

  async function main(){
    if(!extractASIN() || !await getBasePrice()) return;
    injectStyles();
    createLoadingContainer();
    await fetchExchangeRates();
    fetchPricesFromOtherSites();
  }

  function extractASIN(){
    const m = window.location.href.match(ASIN_REGEX);
    if(!m) return false;
    asin = m[1];
    return true;
  }

  async function getBasePrice(){
    basePrice = getPriceFromDocument(document, getCurrentCountryCode());
    return basePrice !== null;
  }

  async function fetchExchangeRates(){
    const cachedRates = localStorage.getItem('exchangeRates');
    const cachedTime = localStorage.getItem('exchangeRatesTimestamp');
    const now = new Date().getTime();
    if(cachedRates && cachedTime && (now - cachedTime < 3600000)){
      exchangeRates = JSON.parse(cachedRates);
      console.log('Utilisation des taux de change mis en cache:', exchangeRates);
      return;
    }

    try{
      const response = await new Promise((resolve, reject) => {
        GM_xmlhttpRequest({
          method: 'GET',
          url: 'https://api.frankfurter.app/latest?from=EUR&to=USD,GBP,EUR',
          onload: (r) => resolve(r),
          onerror: () => reject(new Error('Échec de la récupération des taux de change'))
        });
      });
      if(response.status === 200){
        const data = JSON.parse(response.responseText);
        exchangeRates = data.rates;
        localStorage.setItem('exchangeRates', JSON.stringify(exchangeRates));
        localStorage.setItem('exchangeRatesTimestamp', now);
        console.log('Taux de change récupérés:', exchangeRates);
      } else {
        throw new Error('Réponse non 200');
      }
    } catch(e){
      console.error('Erreur lors de la récupération des taux de change:', e);
      exchangeRates = { USD: 0.90, GBP: 1.15, EUR: 1 };
    }
  }

  function getCouponFromDocument(doc, currentPrice) {
    let label = doc.querySelector('label[id^="couponText"]');
    if(!label) {
      label = doc.querySelector('label[id^="greenBadgepctch"]');
    }
    if(!label) return 0;

    let text = label.textContent || '';
    text = text.replace(/\u00A0/g,' ').toLowerCase().trim();

    let coupon = 0;

    const pctRegex = /(\d+(?:[.,]\d+)?)\s*%/;
    const mPct = pctRegex.exec(text);
    if(mPct){
      const pctVal = parseFloat(mPct[1].replace(',', '.'));
      if(!isNaN(pctVal) && pctVal>0 && pctVal<100){
        coupon = currentPrice * (pctVal / 100);
      }
    }

    const moneyRegex = /(?:€\s*(\d+(?:[.,]\d+)?)|(\d+(?:[.,]\d+))\s*€)/;
    const mMoney = moneyRegex.exec(text);
    if(mMoney){
      const valStr = (mMoney[1] || mMoney[2] || '').replace(',', '.');
      const val = parseFloat(valStr);
      if(!isNaN(val) && val>0 && val<=currentPrice){
        coupon = Math.max(coupon, val);
      }
    }
    return coupon;
  }

  function injectStyles(){
    const css=`
      #amazonPriceComparisonContainer {
        margin-top:20px;
        padding:10px;
        background:#f9f9f9;
        border:1px solid #ccc;
        border-radius:8px;
        position:relative;
        font-size:11px;
        text-align:center;
      }
      .comparison-row {
        cursor:pointer;
        display:flex;
        justify-content:space-between;
        padding:2px 0;
        border-bottom:1px solid #ccc;
      }
      .comparison-row:hover {
        background:#f1f1f1;
      }
      .comparison-row.header-row {
        border-bottom:2px solid #000;
        font-weight:bold;
        pointer-events:none;
      }
      .comparison-row > div {
        flex:1;
        margin:0 2px;
      }
      .first-col {
        min-width: 100px;
        flex: 0 0 100px;
        white-space: nowrap;
        text-align: left;
        overflow: hidden;
      }
      #loadingMessage {
        text-align:center;
        font-weight:bold;
        font-size:14px;
        display:flex;
        flex-direction:column;
        align-items:center;
        background-clip:text;
        color:transparent;
        background-image:linear-gradient(270deg,black 0%,black 20%,#FF9900 50%,black 80%,black 100%);
        background-size:200% 100%;
        animation:loadingAnimation 2s linear infinite;
      }
      @keyframes loadingAnimation {
        0%{background-position:100% 50%}
        100%{background-position:0 50%}
      }
      .price-difference-positive { color:green; }
      .price-difference-negative { color:red; }
      .controls-container {
        text-align:center;
        margin:10px;
        display:flex;
        justify-content:space-around;
        align-items:center;
      }
      .control-button {
        padding:5px 10px;
        border:1px solid #ccc;
        border-radius:4px;
        background:#fff;
        cursor:pointer;
        font-size:11px;
      }
      .control-button.active {
        background:#FF9900;
        color:#fff;
      }
      .checkbox-container {
        display:flex;
        align-items:center;
        margin-left:5px;
      }
      .checkbox-label {
        margin-left:2px;
        font-size:11px;
      }
      .aliexpress-container {
        margin-top:20px;
        padding:5px 10px;
        border:1px solid #ccc;
        border-radius:8px;
        text-align:center;
        max-width:200px;
        margin:20px auto;
        cursor:pointer;
        background:transparent;
        color:#ff5722;
        font-weight:bold;
        display:flex;
        align-items:center;
        justify-content:center;
      }
      .aliexpress-icon {
        width:24px;
        margin-right:8px;
      }
      .aliexpress-container:hover {
        background:#ffe6cc;
      }
      .loading-text {
        background-clip:text;
        color:transparent;
        background-image:linear-gradient(270deg,black 0%,black 20%,#FF9900 50%,black 80%,black 100%);
        background-size:200% 100%;
        animation:loadingAnimation 2s linear infinite;
      }
      .footer {
        text-align:right;
        font-size:.7em;
        color:#666;
        margin-top:10px;
      }
      .footer-logo {
        width:20px;
        height:20px;
        vertical-align:middle;
        margin-right:5px;
      }
      .chart-container {
        text-align:center;
        margin:20px 0;
      }
      .loader {
        position:relative;
        width:48px;
        height:48px;
        border-radius:50%;
        display:inline-block;
        border-top:4px solid #FFF;
        border-right:4px solid transparent;
        box-sizing:border-box;
        animation:rotation 1s linear infinite;
      }
      .loader::after {
        content:'';
        box-sizing:border-box;
        position:absolute;
        left:0;
        top:0;
        width:48px;
        height:48px;
        border-radius:50%;
        border-left:4px solid #FF3D00;
        border-bottom:4px solid transparent;
        animation:rotation .5s linear infinite reverse;
      }
      @keyframes rotation {
        0%{transform:rotate(0deg);}
        100%{transform:rotate(360deg);}
      }
      @keyframes fadeIn {
        from{opacity:0;}
        to{opacity:1;}
      }
      .fade-in {
        animation:fadeIn .4s ease-in-out;
      }
      .product-summary-encart {
        margin-top:20px;
        padding:10px;
        background:#eee;
        border:1px solid #ccc;
        border-radius:8px;
        text-align:left;
      }
      .product-summary-encart h3 {
        margin-top:0;
        font-size:1.2em;
        color:#0d47a1;
      }
      .product-summary-encart p {
        margin:5px 0;
        color:#333;
      }
      .exchange-info-icon {
        margin-left: 3px;
        cursor: help;
        font-size: 0.8em;
        vertical-align: middle;
      }
      ._Y3Itc_selected_2-xMA {
        font-weight: bold !important;
      }
      #cr-product-insights-cards * {
        font-size: 11px !important;
      }
    `;
    const st=document.createElement('style');
    st.type='text/css';
    st.innerText=css;
    document.head.appendChild(st);
  }

  function createLoadingContainer(){
    const priceElement = document.querySelector('.priceToPay,#priceblock_ourprice,#priceblock_dealprice,#priceblock_saleprice');
    if(priceElement && priceElement.parentNode){
      const c=document.createElement('div');
      c.id='amazonPriceComparisonContainer';
      c.innerHTML=`
      <div id="loadingMessage">
        <img src="https://i.ibb.co/qrjrcVy/amz-price-checker.png" style="width:50px;height:50px;margin-bottom:10px;">
        Checking other Amazon sites...
      </div>`;
      priceElement.parentNode.appendChild(c);
    }
  }

  function fetchPricesFromOtherSites(){
    amazonSites.forEach(s=>{
      const url=`https://www.amazon.${s.country}/dp/${asin}?tag=${PARTNER_IDS[s.country]}`;
      GM_xmlhttpRequest({
        method:'GET',
        url,
        headers:{'User-Agent':'Mozilla/5.0','Accept-Language':'en-US,en;q=0.5'},
        onload:r=>handleResponse(s,r),
        onerror:()=>handleResponse(s,null)
      });
    });
  }

  function handleResponse(site, response){
    requestCount++;
    if(response && response.status===200){
      const doc=new DOMParser().parseFromString(response.responseText,'text/html');
      const originalPrice = getPriceFromDocument(doc, site.country);
      const delivery = getDeliveryPriceFromDocument(doc);
      if(originalPrice !== null){
        const coupon = getCouponFromDocument(doc, originalPrice);
        const convertedPrice = convertToEUR(originalPrice, site.currency);
        const convertedDelivery = convertToEUR(delivery, getCurrencyByCountry(site.country));
        const convertedCoupon = convertToEUR(coupon, site.currency);
        if(!firstPriceLoaded){
          firstPriceLoaded=true;
          priceContainer = document.querySelector('#amazonPriceComparisonContainer');
          if(!priceContainer) return;
          priceContainer.innerHTML='';
          createComparisonTableSkeleton(priceContainer);
          addControls(priceContainer);
          addCamelCamelCamelChart(priceContainer);
          addAliExpressLink(priceContainer);
          addProductSummary(priceContainer);
          addFooterAfterProductSummary();
        }
        insertPriceRow({
          site,
          price: convertedPrice,
          delivery: convertedDelivery,
          coupon: convertedCoupon,
          originalCurrency: site.currency
        });
      }
    }
  }

  function createComparisonTableSkeleton(container){
    tableContainer = document.createElement('div');
    headerRow = document.createElement('div');
    headerRow.className = 'comparison-row header-row';
    ['Site','Price (EUR)','Coupon (EUR)','Delivery (EUR)','Total (EUR)','Difference'].forEach(h=>{
      headerRow.appendChild(createCell(h,true));
    });
    tableContainer.appendChild(headerRow);
    container.appendChild(tableContainer);
  }

  function insertPriceRow({site, price, delivery, coupon, originalCurrency}){
    const total = price - (coupon || 0) + (delivery || 0);
    const row = document.createElement('div');
    row.className = 'comparison-row fade-in';
    row.onclick = () => window.open(`https://www.amazon.${site.country}/dp/${asin}?tag=${PARTNER_IDS[site.country]}`, '_blank');

    const diff = total - basePrice;
    const perc = ((diff/basePrice)*100).toFixed(2);
    const diffClass = diff < 0 ? 'price-difference-positive' :
                      diff > 0 ? 'price-difference-negative' :
                      '';

    function createPriceContent(amount){
      if(site.needsConversion && exchangeRates[originalCurrency]){
        return `€${amount.toFixed(2)}<span class="exchange-info-icon" title="Exchange Rate: 1 EUR = ${exchangeRates[originalCurrency]} ${originalCurrency}">ℹ️</span>`;
      } else {
        return `€${amount.toFixed(2)}`;
      }
    }

    row.append(
      createCell(`
        <img src="${site.flag}"
             style="vertical-align:middle;margin-right:5px;width:20px;height:13px;">
        ${site.name}
      `, false, 'first-col'),
      createCell(createPriceContent(price)),
      createCell(
        coupon > 0
          ? `<img src="https://img.icons8.com/arcade/64/discount-ticket.png"
                   width="20"
                   style="vertical-align:middle;margin-right:5px;">
             €${coupon.toFixed(2)}${site.needsConversion ? `<span class="exchange-info-icon" title="Exchange Rate: 1 EUR = ${exchangeRates[originalCurrency]} ${originalCurrency}">ℹ️</span>` : ''}`
          : '-'
      ),
      createCell(
        delivery
          ? `<img src="https://img.icons8.com/arcade/64/in-transit.png"
                   width="20"
                   style="vertical-align:middle;margin-right:5px;">
             €${delivery.toFixed(2)}${site.needsConversion ? `<span class="exchange-info-icon" title="Exchange Rate: 1 EUR = ${exchangeRates[originalCurrency]} ${originalCurrency}">ℹ️</span>` : ''}`
          : '-'
      ),
      createCell(`€${total.toFixed(2)}${site.needsConversion ? `<span class="exchange-info-icon" title="Exchange Rate: 1 EUR = ${exchangeRates[originalCurrency]} ${originalCurrency}">ℹ️</span>` : ''}`),
      createCell(
        diff !== 0
          ? `<span class="${diffClass}">
               ${diff >= 0 ? '+' : ''}€${diff.toFixed(2)} (${perc}%)
             </span>`
          : '-'
      )
    );

    let inserted=false;
    const rows=[...tableContainer.querySelectorAll('.comparison-row:not(.header-row)')];
    for(let i=0;i<rows.length;i++){
      const cells=rows[i].querySelectorAll('div');
      const existingTotalText = cells[4].textContent.replace(/[^\d.,-]/g,'').replace(',','.');
      const existingTotal = parseFloat(existingTotalText) || 999999;
      if(total < existingTotal){
        tableContainer.insertBefore(row,rows[i]);
        inserted=true;
        break;
      }
    }
    if(!inserted) tableContainer.appendChild(row);
  }

  function createCell(content,isHeader=false,extraClass=''){
    const c=document.createElement('div');
    c.style.flex='1';
    c.innerHTML=content;
    if(isHeader) c.style.fontWeight='bold';
    if(extraClass) c.classList.add(extraClass);
    return c;
  }

  function addControls(container){
    const ctrls=document.createElement('div');
    ctrls.className='controls-container';
    const tps=[
      {id:'btn1M',label:'1 Month',val:'1m'},
      {id:'btn3M',label:'3 Months',val:'3m'},
      {id:'btn6M',label:'6 Months',val:'6m'},
      {id:'btn1Y',label:'1 Year',val:'1y'},
      {id:'btnAll',label:'All',val:'all'}
    ];
    tps.forEach(tp=>{
      const b=document.createElement('button');
      b.id=tp.id;
      b.textContent=tp.label;
      b.className=`control-button ${tp.val===selectedTimePeriod?'active':''}`;
      b.addEventListener('click',()=>{
        selectedTimePeriod=tp.val;
        document.querySelectorAll('.control-button').forEach(x=>x.classList.remove('active'));
        b.classList.add('active');
        updateChartUrl();
      });
      ctrls.appendChild(b);
    });

    const cbs=[
      {id:'checkboxAmazon', label:'Amazon', fn:'amazon', dis:true, chk:true},
      {id:'checkboxNew',    label:'New',    fn:'new',    chk:true},
      {id:'checkboxUsed',   label:'Used',   fn:'used',   chk:false}
    ];
    cbs.forEach(cb=>{
      const wrap=document.createElement('div');
      wrap.className='checkbox-container';
      const i=document.createElement('input');
      i.type='checkbox';
      i.id=cb.id;
      i.checked=cb.chk;
      if(cb.dis) i.disabled=true;
      i.addEventListener('change',updateChartUrl);

      const lbl=document.createElement('label');
      lbl.htmlFor=cb.id;
      lbl.textContent=cb.label;
      lbl.className='checkbox-label';

      wrap.append(i,lbl);
      ctrls.appendChild(wrap);
    });
    container.appendChild(ctrls);
  }

  function addCamelCamelCamelChart(container){
    const c=document.createElement('div');
    c.className='chart-container';
    const cc=getCurrentCountryCode();
    const url=getCamelChartUrl(cc,asin,selectedTimePeriod);
    const camelUrl=`https://${cc}.camelcamelcamel.com/product/${asin}`;

    const spin=document.createElement('div');
    spin.className='loader';
    const img=document.createElement('img');
    img.alt=`Price history for ${asin}`;
    img.className='chart-image';
    img.style.display='none';

    img.addEventListener('load',()=>{
      spin.style.display='none';
      img.style.display='block';
    });
    img.addEventListener('error',()=>{
      spin.style.display='none';
      img.style.display='block';
      img.src='https://dummyimage.com/600x200/ccc/000&text=Image+Unavailable';
    });
    img.src=url;

    const a=document.createElement('a');
    a.href=camelUrl;
    a.target='_blank';
    a.appendChild(img);

    c.append(spin,a);
    container.appendChild(c);
  }

  function getCamelChartUrl(cc, asin, tp){
    const f=getSelectedFilenames();
    const base=`https://charts.camelcamelcamel.com/${cc}/${asin}/${f}.png?force=1&zero=0&w=600&h=300&desired=false&legend=1&ilt=1&tp=${tp}&fo=0&lang=en`;
    return `https://camelcamelcamel.mon-bnj.workers.dev/?target=${encodeURIComponent(base)}`;
  }

  function getSelectedFilenames(){
    const cbs=[
      {id:'checkboxAmazon',fn:'amazon'},
      {id:'checkboxNew',   fn:'new'},
      {id:'checkboxUsed',  fn:'used'}
    ];
    return Array.from(document.querySelectorAll('input[type="checkbox"]:checked'))
      .map(x=>cbs.find(z=>z.id===x.id)?.fn)
      .filter(Boolean)
      .join('-');
  }

  function updateChartUrl(){
    const cc=getCurrentCountryCode();
    const url=getCamelChartUrl(cc,asin,selectedTimePeriod);
    const camelUrl=`https://${cc}.camelcamelcamel.com/product/${asin}`;
    const i=document.querySelector('#amazonPriceComparisonContainer img.chart-image');
    if(i){
      const spin=i.parentElement.parentElement.querySelector('.loader');
      if(spin) spin.style.display='inline-block';

      i.style.display='none';
      i.src=url;
      i.parentElement.href=camelUrl;
    }
  }

  function createAliExpressLink(title){
    const d=document.createElement('div');
    d.className='aliexpress-container';
    d.innerHTML=`
      <img src="https://img.icons8.com/color/48/aliexpress.png" class="aliexpress-icon">
      <span class="aliexpress-text">Check on AliExpress</span>`;
    d.addEventListener('click',()=>{
      const t=d.querySelector('.aliexpress-text');
      t.classList.add('loading-text');
      t.textContent='Loading...';
      GM_xmlhttpRequest({
        method:'GET',
        url:`https://summarizer.mon-bnj.workers.dev/?text=${encodeURIComponent(title)}`,
        onload:r=>handleAliExpressResponse(r,d),
        onerror:()=>{resetAliExpressButton(d);}
      });
    });
    return d;
  }

  function handleAliExpressResponse(r,c){
    try{
      const j=JSON.parse(r.responseText);
      if(j.summary){
        const u=`https://www.aliexpress.com/wholesale?SearchText=${encodeURIComponent(j.summary)}`;
        resetAliExpressButton(c);
        setTimeout(()=>{window.open(u,'_blank');},100);
      } else {
        throw new Error('No summary');
      }
    }catch(e){
      resetAliExpressButton(c);
    }
  }

  function resetAliExpressButton(c){
    const ic=c.querySelector('.aliexpress-icon');
    c.innerHTML='';
    c.appendChild(ic);
    const sp=document.createElement('span');
    sp.className='aliexpress-text';
    sp.textContent='Check on AliExpress';
    c.appendChild(sp);
  }

  function addAliExpressLink(c){
    const t=document.querySelector('#productTitle');
    const pt=t ? t.textContent.trim() : null;
    if(!pt) return;
    const ali=createAliExpressLink(pt);
    c.appendChild(ali);
  }

  function addFooterAfterProductSummary(){
    if(footerAdded) return;
    const summaryDiv = document.querySelector('#cr-product-insights-cards');
    if(summaryDiv){
      const footer=document.createElement('div');
      footer.className='footer';
      footer.innerHTML=`
        <img src="https://i.ibb.co/qrjrcVy/amz-price-checker.png" class="footer-logo">
        Amazon Price Checker v${GM_info.script.version}
      `;
      summaryDiv.parentNode.insertBefore(footer, summaryDiv.nextSibling);
      footerAdded = true;
    }
  }

  function getCurrentCountryCode(){
    const h=window.location.hostname;
    if(h.includes('amazon.com') && !h.includes('amazon.com.be') && !h.includes('amazon.co.uk')) return 'com';
    if(h.includes('amazon.de')) return 'de';
    if(h.includes('amazon.es')) return 'es';
    if(h.includes('amazon.it')) return 'it';
    if(h.includes('amazon.com.be')) return 'com.be';
    if(h.includes('amazon.nl')) return 'nl';
    if(h.includes('amazon.co.uk')) return 'co.uk';
    return 'fr';
  }

  function getCurrencyByCountry(country){
    const site = amazonSites.find(s => s.country === country);
    return site ? site.currency : 'EUR';
  }

  function convertToEUR(amount, currency){
    if(!exchangeRates) return amount;
    if(currency === 'EUR') return amount;
    const rate = exchangeRates[currency];
    if(!rate) return amount;
    return amount / rate;
  }

  function getPriceFromDocument(doc, country){
    const el=doc.querySelector('.priceToPay,#priceblock_ourprice,#priceblock_dealprice,#priceblock_saleprice');
    if(!el) return null;
    const rawPrice = parsePrice(el.textContent);
    const currency = getCurrencyByCountry(country);
    return convertToEUR(rawPrice, currency);
  }

  function parsePrice(t){
    if(!t) return null;
    const c=t.replace(/[^0-9,\.]/g,'').replace(',', '.');
    const p=parseFloat(c);
    return isNaN(p)?null:p;
  }

  function getDeliveryPriceFromDocument(doc){
    const m=doc.body.innerHTML.match(/data-csa-c-delivery-price="[^"]*?(\d+[.,]\d{2})/);
    if(m){
      const x=m[1].replace(',', '.');
      const p=parseFloat(x);
      return isNaN(p)?0:p;
    }
    return 0;
  }

  function addProductSummary(container){
    const summaryDiv = document.querySelector('#cr-product-insights-cards');
    if(summaryDiv){
      const summaryClone = summaryDiv.cloneNode(true);
      summaryClone.classList.add('product-summary-encart');
      summaryClone.querySelectorAll('i[id^="close-button-"]').forEach(icon => icon.remove());
      container.appendChild(summaryClone);
      addAspectButtonListeners(summaryClone);
    }
  }

  function addAspectButtonListeners(clonedSummary){
    const aspectButtons = clonedSummary.querySelectorAll('[id^="aspect-button-0-"]');
    aspectButtons.forEach(button => {
      button.addEventListener('click', () => {
        const buttonId = button.id;
        const parts = buttonId.split('-');
        const X = parts[3];
        const bottomSheet = document.getElementById(`aspect-bottom-sheet-0-${X}`);
        if(!bottomSheet){
          console.warn(`Feuille inférieure pour ${buttonId} non trouvée.`);
          return;
        }
        document.querySelectorAll('[id^="aspect-bottom-sheet-0-"]').forEach(sheet => sheet.style.display = 'none');
        bottomSheet.style.display = 'block';
        aspectButtons.forEach(btn => btn.classList.remove('_Y3Itc_selected_2-xMA'));
        button.classList.add('_Y3Itc_selected_2-xMA');
      });
    });
  }

  main();

})();