/* Refstudio hover overlay: + ADD button on web images. * v12 — stable one-click capture with captureId nonce. */ (function () { if (window.__muse_hover_v12) return; window.__muse_hover_v12 = true; // Remove old badge DOM left by previous injected versions. Anonymous old listeners // may still exist, but they cannot duplicate backend actions because v12 adds captureId // and Rust dedupes captureIds. try { var old = document.getElementById('__muse_add_badge'); if (old) old.remove(); } catch (_) {} var MIN = 90; var activeImg = null; var badge = null; var showTimer = 0; var hideTimer = 0; var capturing = false; function injectCSS() { if (document.getElementById('__muse_badge_css_v12')) return; var s = document.createElement('style'); s.id = '__muse_badge_css_v12'; s.textContent = '#__muse_add_badge{all:initial;position:fixed;z-index:2147483647;display:flex;align-items:center;gap:5px;padding:8px 16px;background:rgba(10,132,255,0.95);color:#fff;border-radius:999px;box-shadow:0 4px 20px rgba(0,0,0,0.4),0 0 0 1px rgba(255,255,255,0.1);font:700 12px/1 -apple-system,BlinkMacSystemFont,"Inter",sans-serif;cursor:pointer;opacity:0;transform:translateY(4px) scale(0.92);transition:opacity .2s,transform .2s,background .1s;pointer-events:auto;letter-spacing:0.01em;user-select:none}#__muse_add_badge.v{opacity:1;transform:none}#__muse_add_badge:hover{background:rgba(10,132,255,1);box-shadow:0 6px 28px rgba(10,132,255,0.4),0 0 0 1px rgba(255,255,255,0.2);transform:scale(1.06)}#__muse_add_badge:active{transform:scale(0.92);background:rgba(10,100,220,1)}#__muse_add_badge svg{width:14px;height:14px;stroke-width:2.5;pointer-events:none}#__mt7{all:initial;position:fixed;left:50%;bottom:24px;transform:translateX(-50%) translateY(8px);z-index:2147483647;padding:9px 16px;border-radius:999px;background:rgba(20,20,20,.97);border:1px solid rgba(255,255,255,.1);box-shadow:0 10px 36px rgba(0,0,0,.5);font:600 12px/1 -apple-system,sans-serif;color:#fff;opacity:0;transition:opacity .16s,transform .16s;pointer-events:none}#__mt7.s{opacity:1;transform:translateX(-50%) translateY(0)}'; (document.head || document.documentElement).appendChild(s); } function enc(v) { return encodeURIComponent(v == null ? '' : String(v)); } function absUrl(s) { try { return new URL(s || '', location.href).href; } catch (_) { return s || ''; } } function captureId() { return Date.now().toString(36) + '-' + Math.random().toString(36).slice(2); } function bestImageUrl(img) { var srcset = img.getAttribute('srcset') || ''; if (srcset) { var best='',bs=0; srcset.split(',').forEach(function(p){var b=p.trim().split(/\s+/),u=b[0],sc=1;if(b[1]){if(b[1].endsWith('w'))sc=parseInt(b[1],10)||1;else if(b[1].endsWith('x'))sc=(parseFloat(b[1])||1)*1000;}if(sc>bs){bs=sc;best=u;}}); if(best) return absUrl(best); } var u = img.getAttribute('data-full')||img.getAttribute('data-original')||img.getAttribute('data-src')||img.getAttribute('data-lazy-src')||img.currentSrc||img.src; u = absUrl(u); try { if(u.includes('pinimg.com')&&u.match(/\/\d+x\//))u=u.replace(/\/\d+x\//,'/originals/'); if(u.includes('artstation.com')&&u.includes('/medium/'))u=u.replace('/medium/','/large/'); } catch(_){} return u; } function toast(m) { var t=document.getElementById('__mt7'); if(!t){t=document.createElement('div');t.id='__mt7';document.documentElement.appendChild(t);} t.textContent=m;t.classList.add('s'); clearTimeout(t._t);t._t=setTimeout(function(){t.classList.remove('s');},2000); } function fireAction(url, title, w, h) { if (capturing) return; capturing = true; var id = captureId(); var u = 'muse-action://board?captureId='+enc(id)+'&url='+enc(url)+'&source='+enc(location.href)+'&title='+enc(title)+'&w='+enc(w)+'&h='+enc(h); window.location.href = u; setTimeout(function(){ capturing = false; }, 1000); } function clearHide(){clearTimeout(hideTimer);} function scheduleHide(){clearHide();hideTimer=setTimeout(hide,600);} function hide(){if(!badge)return;badge.classList.remove('v');activeImg=null;} function pos(el,img){var r=img.getBoundingClientRect();var x=r.right-80,y=r.top+10;if(xinnerWidth-90)x=innerWidth-90;if(y<4)y=4;if(y>innerHeight-40)y=innerHeight-40;el.style.left=x+'px';el.style.top=y+'px';} function show(img){ if(img===activeImg&&badge&&badge.classList.contains('v'))return; injectCSS(); activeImg=img; if(!badge){ badge=document.createElement('div');badge.id='__muse_add_badge'; badge.innerHTML='ADD'; badge.addEventListener('click',function(e){e.preventDefault();e.stopPropagation();e.stopImmediatePropagation();if(!activeImg)return;var url=bestImageUrl(activeImg);if(!url||url.startsWith('data:')||url.startsWith('blob:')){toast('Cannot capture');return;}fireAction(url,activeImg.alt||activeImg.title||document.title||'Reference',activeImg.naturalWidth||Math.round(activeImg.getBoundingClientRect().width),activeImg.naturalHeight||Math.round(activeImg.getBoundingClientRect().height));toast('✓ Added to Board');hide();},true); ['mousedown','mouseup','pointerdown','pointerup','touchstart','touchend'].forEach(function(ev){badge.addEventListener(ev,function(e){e.preventDefault();e.stopPropagation();e.stopImmediatePropagation();},true);}); badge.addEventListener('mouseenter',clearHide,true); badge.addEventListener('mouseleave',scheduleHide,true); document.documentElement.appendChild(badge); } pos(badge,activeImg);void badge.offsetHeight;badge.classList.add('v'); } function isValid(el){if(!el||el.tagName!=='IMG')return false;if(el===badge)return false;var r=el.getBoundingClientRect();return r.width>=MIN&&r.height>=MIN;} document.addEventListener('mouseover',function(e){var t=e.target;if(badge&&(t===badge||badge.contains(t))){clearHide();return;}if(!isValid(t))return;if(t===activeImg){clearHide();return;}clearHide();clearTimeout(showTimer);showTimer=setTimeout(function(){show(t);},150);},true); document.addEventListener('mouseout',function(e){var t=e.target;if(!t||t.tagName!=='IMG'||t!==activeImg)return;var rel=e.relatedTarget;if(badge&&rel&&(badge===rel||badge.contains(rel))){clearHide();return;}clearTimeout(showTimer);scheduleHide();},true); window.addEventListener('scroll',function(){if(!badge||!activeImg)return;var r=activeImg.getBoundingClientRect();if(r.bottom<-20||r.top>innerHeight+20)hide();else pos(badge,activeImg);},{passive:true,capture:true}); })();