{"title":"test","description":"\u003c!-- Modern smooth Customer Reviews widget (paste before \u003c\/body\u003e) --\u003e\n\u003cstyle\u003e\n  \/* FLOATING TAB - visible and compact *\/\n  .rv-tab {\n    position: fixed;\n    right: 12px;\n    top: 50%;\n    transform: translateY(-50%);\n    z-index: 2000;\n    display:flex;\n    gap:8px;\n    align-items:center;\n    background: linear-gradient(90deg,#111,#222);\n    color:#fff;\n    padding:10px 12px;\n    border-radius:999px;\n    box-shadow: 0 18px 40px rgba(0,0,0,0.22);\n    cursor:pointer;\n    font-weight:700;\n    font-family: \"Montserrat\",system-ui, -apple-system, \"Segoe UI\", Roboto, Arial;\n    transition: transform .18s ease, box-shadow .18s ease;\n  }\n  .rv-tab:hover{ transform: translateY(-50%) scale(1.02); box-shadow:0 26px 60px rgba(0,0,0,0.28); }\n  .rv-tab .rv-icon{ width:18px; height:18px; display:inline-flex; align-items:center; justify-content:center; font-size:14px; }\n  .rv-tab .rv-label{ font-size:13px; letter-spacing:.2px; white-space:nowrap; margin-right:4px; opacity:.95; }\n\n  \/* OVERLAY \u0026 CENTERED MODAL *\/\n  .rv-overlay {\n    position: fixed;\n    inset: 0;\n    display: none;\n    align-items: center;\n    justify-content: center;\n    z-index: 1999;\n    background: rgba(0,0,0,0.45);\n    backdrop-filter: blur(6px);\n  }\n  .rv-overlay.show { display:flex; animation: rv-fade .26s ease both; }\n  @keyframes rv-fade { from{opacity:0} to{opacity:1} }\n\n  .rv-modal {\n    width: 760px;\n    max-width: calc(100% - 48px);\n    background: #ffffff;\n    border-radius: 14px;\n    box-shadow: 0 40px 110px rgba(12,12,12,0.28);\n    overflow: hidden;\n    transform: translateY(10px) scale(.98);\n    opacity: 0;\n    transition: transform .36s cubic-bezier(.2,.9,.2,1), opacity .28s ease;\n    will-change: transform, opacity;\n    outline: none;\n  }\n  .rv-modal.show { transform: translateY(0) scale(1); opacity:1; }\n\n  \/* header *\/\n  .rv-head {\n    display:flex;\n    align-items:center;\n    justify-content:flex-end;\n    padding:10px 12px;\n    gap:8px;\n    border-bottom: 1px solid #f4f4f4;\n    background: linear-gradient(180deg,#fff,#fbfbfb);\n  }\n  .rv-close {\n    background:transparent;\n    border:1px solid #eee;\n    padding:8px 10px;\n    border-radius:10px;\n    cursor:pointer;\n    font-weight:700;\n  }\n\n  \/* main *\/\n  .rv-main {\n    display:flex;\n    align-items:center;\n    gap:18px;\n    padding:18px;\n    justify-content:center;\n  }\n  .rv-main .rv-image-wrap {\n    width:420px;\n    max-width:58%;\n    aspect-ratio: 1 \/ 1;\n    border-radius:12px;\n    overflow:hidden;\n    background:#fafafa;\n    box-shadow: 0 18px 40px rgba(10,10,10,0.06);\n    display:flex;\n    align-items:center;\n    justify-content:center;\n  }\n  .rv-main .rv-image-wrap img {\n    width:100%;\n    height:100%;\n    object-fit:cover;\n    display:block;\n  }\n\n  \/* thumbnails *\/\n  .rv-thumbs {\n    width: 28%;\n    max-width:220px;\n    display:flex;\n    flex-direction:column;\n    gap:10px;\n    align-items:center;\n  }\n  .rv-thumbs .mini {\n    width:100%;\n    aspect-ratio: 1 \/ 1;\n    border-radius:10px;\n    overflow:hidden;\n    cursor:pointer;\n    border:2px solid transparent;\n    box-shadow:0 10px 30px rgba(12,12,12,0.04);\n  }\n  .rv-thumbs .mini img{ width:100%; height:100%; object-fit:cover; display:block; }\n  .rv-thumbs .mini.active { border-color:#111; transform:scale(1.02); }\n\n  \/* controls below *\/\n  .rv-controls {\n    display:flex;\n    justify-content:space-between;\n    align-items:center;\n    gap:12px;\n    padding:12px 18px 18px;\n  }\n  .rv-controls .rv-btn {\n    background:#111;\n    color:#fff;\n    border:none;\n    padding:10px 14px;\n    border-radius:12px;\n    cursor:pointer;\n    font-weight:700;\n  }\n  .rv-counter { color:#777; font-weight:700; font-size:13px; }\n\n  \/* small screens *\/\n  @media(max-width:900px){\n    .rv-main { gap:12px; padding:14px; }\n    .rv-thumbs{ display:flex; flex-direction:row; width:100%; max-width:none; justify-content:center; overflow:auto; padding:6px 10px; }\n    .rv-thumbs .mini{ width:80px; flex:0 0 80px; }\n    .rv-main .rv-image-wrap{ width:100%; max-width:100%; aspect-ratio: 4 \/ 3; }\n    .rv-modal{ width: 94%; }\n  }\n  @media(max-width:520px){\n    .rv-tab { right:8px; padding:8px 10px; gap:6px; }\n    .rv-tab .rv-label{ display:none; }\n    .rv-thumbs .mini{ width:64px; flex:0 0 64px; }\n  }\n\u003c\/style\u003e\n\n\u003c!-- HTML --\u003e\n\u003cbutton id=\"rv-tab\" class=\"rv-tab\" aria-expanded=\"false\" aria-controls=\"rv-overlay\" aria-label=\"Open customer reviews\"\u003e\n  \u003cspan class=\"rv-icon\" aria-hidden=\"true\"\u003e⭐\u003c\/span\u003e\n  \u003cspan class=\"rv-label\"\u003eCustomer Reviews\u003c\/span\u003e\n\u003c\/button\u003e\n\n\u003cdiv id=\"rv-overlay\" class=\"rv-overlay\" role=\"dialog\" aria-modal=\"true\" aria-hidden=\"true\"\u003e\n  \u003cdiv id=\"rv-modal\" class=\"rv-modal\" role=\"document\" tabindex=\"-1\" aria-labelledby=\"rv-label\"\u003e\n    \u003cdiv class=\"rv-head\"\u003e\n      \u003cbutton id=\"rv-close\" class=\"rv-close\" aria-label=\"Close\"\u003e✕\u003c\/button\u003e\n    \u003c\/div\u003e\n\n    \u003cdiv class=\"rv-main\" role=\"region\"\u003e\n      \u003cdiv class=\"rv-image-wrap\" id=\"rv-big\"\u003e\n        \u003c!-- big image injected --\u003e\n      \u003c\/div\u003e\n\n      \u003cdiv class=\"rv-thumbs\" id=\"rv-thumbs\"\u003e\n        \u003c!-- minis injected --\u003e\n      \u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003cdiv class=\"rv-controls\"\u003e\n      \u003cdiv class=\"rv-counter\" id=\"rv-counter\"\u003e0 \/ 0\u003c\/div\u003e\n      \u003cdiv style=\"display:flex;gap:8px;\"\u003e\n        \u003cbutton id=\"rv-prev\" class=\"rv-btn\" aria-label=\"Previous\"\u003e‹\u003c\/button\u003e\n        \u003cbutton id=\"rv-next\" class=\"rv-btn\" aria-label=\"Next\"\u003e›\u003c\/button\u003e\n      \u003c\/div\u003e\n    \u003c\/div\u003e\n  \u003c\/div\u003e\n\u003c\/div\u003e\n\n\u003cscript\u003e\n(function(){\n  \/\/ ====== CONFIG: add \/ change images here (initial list) ======\n  const images = [\n    'https:\/\/cdn.shopify.com\/s\/files\/1\/0954\/9044\/1506\/files\/d6b753f5-56fd-4596-a19d-45e660e44db4.jpg?v=1762940125',\n    'https:\/\/cdn.shopify.com\/s\/files\/1\/0954\/9044\/1506\/files\/0bdf8257-4d49-4dc4-a256-c1e5de724055.jpg?v=1762940126',\n    'https:\/\/cdn.shopify.com\/s\/files\/1\/0954\/9044\/1506\/files\/56dbf269-22a0-4d0f-8ade-96bd2c7a69d1_4b45d9a7-eb07-438d-8dd4-7cb8e7517bb5.jpg?v=1762940125',\n    'https:\/\/cdn.shopify.com\/s\/files\/1\/0954\/9044\/1506\/files\/dea7b78b-668f-4ff1-88be-14325394d145.jpg?v=1762940125',\n    'https:\/\/cdn.shopify.com\/s\/files\/1\/0954\/9044\/1506\/files\/b0447b8f-b7e1-4e03-87b5-f3b7940bedf1.jpg?v=1762940125'\n  ];\n\n  \/\/ ELEMENTS\n  const tab = document.getElementById('rv-tab');\n  const overlay = document.getElementById('rv-overlay');\n  const modal = document.getElementById('rv-modal');\n  const big = document.getElementById('rv-big');\n  const thumbs = document.getElementById('rv-thumbs');\n  const prev = document.getElementById('rv-prev');\n  const next = document.getElementById('rv-next');\n  const closeBtn = document.getElementById('rv-close');\n  const counter = document.getElementById('rv-counter');\n\n  let idx = 0;\n\n  \/\/ build UI\n  function build(){\n    thumbs.innerHTML = '';\n    big.innerHTML = '';\n    images.forEach((src, i)=\u003e{\n      \/\/ mini\n      const btn = document.createElement('button');\n      btn.className = 'mini';\n      btn.setAttribute('data-index', i);\n      btn.innerHTML = `\u003cimg src=\"${src}\" alt=\"Review ${i+1}\" loading=\"lazy\" decoding=\"async\" \/\u003e`;\n      btn.addEventListener('click', ()=\u003e show(i, true));\n      thumbs.appendChild(btn);\n    });\n    \/\/ set big\n    if(images.length){\n      const img = document.createElement('img');\n      img.src = images[0];\n      img.alt = 'Review 1';\n      img.loading = 'eager';\n      img.style.maxWidth = '100%';\n      img.style.maxHeight = '100%';\n      img.decoding = 'async';\n      big.appendChild(img);\n      updateUI();\n    } else {\n      big.innerHTML = '\u003cdiv style=\"padding:36px;color:#777\"\u003eNo reviews yet\u003c\/div\u003e';\n    }\n  }\n\n  function show(n, focusThumb){\n    if(images.length === 0) return;\n    idx = ((n % images.length) + images.length) % images.length;\n    big.innerHTML = '';\n    const img = document.createElement('img');\n    img.src = images[idx];\n    img.alt = 'Review ' + (idx+1);\n    img.loading = 'eager';\n    img.style.maxWidth = '100%';\n    img.style.maxHeight = '100%';\n    img.decoding = 'async';\n    big.appendChild(img);\n    updateUI();\n    if(focusThumb){\n      const active = thumbs.querySelector('.mini.active');\n      if(active) active.scrollIntoView({behavior:'smooth', inline:'center', block:'nearest'});\n    }\n  }\n\n  function updateUI(){\n    counter.textContent = `${idx+1} \/ ${images.length}`;\n    thumbs.querySelectorAll('.mini').forEach((el,i)=\u003e{\n      el.classList.toggle('active', i === idx);\n    });\n  }\n\n  function open(){\n    overlay.classList.add('show');\n    modal.classList.add('show');\n    overlay.setAttribute('aria-hidden','false');\n    tab.setAttribute('aria-expanded','true');\n    \/\/ trap focus minimal\n    setTimeout(()=\u003e closeBtn.focus(), 50);\n    document.body.style.overflow = 'hidden';\n  }\n  function close(){\n    overlay.classList.remove('show');\n    modal.classList.remove('show');\n    overlay.setAttribute('aria-hidden','true');\n    tab.setAttribute('aria-expanded','false');\n    document.body.style.overflow = '';\n    tab.focus();\n  }\n\n  \/\/ listeners\n  tab.addEventListener('click', open);\n  closeBtn.addEventListener('click', close);\n  overlay.addEventListener('click', (e)=\u003e { if(e.target === overlay) close(); });\n  prev.addEventListener('click', ()=\u003e show(idx - 1, true));\n  next.addEventListener('click', ()=\u003e show(idx + 1, true));\n  document.addEventListener('keydown', (e)=\u003e{\n    if(overlay.classList.contains('show')){\n      if(e.key === 'Escape') close();\n      if(e.key === 'ArrowLeft') show(idx - 1, true);\n      if(e.key === 'ArrowRight') show(idx + 1, true);\n    }\n  });\n\n  \/\/ touch swipe support for big image\n  (function(){\n    let startX=0,delta=0,down=false;\n    big.addEventListener('touchstart', e=\u003e{ down=true; startX = e.touches[0].clientX; }, {passive:true});\n    big.addEventListener('touchmove', e=\u003e{ if(!down) return; delta = e.touches[0].clientX - startX; }, {passive:true});\n    big.addEventListener('touchend', ()=\u003e{ down=false; if(Math.abs(delta) \u003e 60){ if(delta\u003e0) show(idx-1,true); else show(idx+1,true); } delta=0; }, {passive:true});\n  })();\n\n  \/\/ public API to add images later without rebuilding page\n  window.ReviewsWidget = {\n    add: function(arr){\n      if(!Array.isArray(arr)) return;\n      arr.forEach(u=\u003e images.push(u));\n      build();\n      show(0);\n    },\n    open: open,\n    close: close\n  };\n\n  \/\/ init\n  build();\n  show(0);\n\n  \/\/ small accessibility: announce\n  overlay.addEventListener('transitionend', ()=\u003e {\n    if(overlay.classList.contains('show')){\n      overlay.setAttribute('aria-hidden','false');\n    } else {\n      overlay.setAttribute('aria-hidden','true');\n    }\n  });\n})();\n\u003c\/script\u003e\n","products":[],"url":"https:\/\/porto-femme.com\/collections\/test.oembed","provider":"PORTO FEMME","version":"1.0","type":"link"}