(function(){ let enabled=false,overlay=null,badge=null; function init(){ if(document.getElementById('__vula_ov'))return; overlay=document.createElement('div'); overlay.id='__vula_ov'; overlay.style.cssText='position:fixed;pointer-events:none;border:2px solid #f97316;border-radius:3px;z-index:999999;transition:top .08s,left .08s,width .08s,height .08s;display:none;box-sizing:border-box;'; badge=document.createElement('div'); badge.id='__vula_badge'; badge.style.cssText='position:fixed;background:#f97316;color:#fff;font:bold 11px/1.4 monospace;padding:3px 8px;border-radius:3px;z-index:1000000;pointer-events:none;display:none;white-space:nowrap;'; document.body.appendChild(overlay); document.body.appendChild(badge); } function cap(s){return s.charAt(0).toUpperCase()+s.slice(1);} function classify(el){ let sec='',n=el; while(n&&n!==document.body){ // data-vula-section injected by AICodeValidator post-pass — most reliable source if(n.dataset&&n.dataset.vulaSection){sec=n.dataset.vulaSection;break;} const cls=(n.className||'').toString(),tag=n.tagName.toLowerCase(); if(/hero|about|services|contact|team|pricing|faq|gallery|testimonial|footer|header|navigation/i.test(cls)){ sec=cls.split(' ').find(c=>/hero|about|services|contact|team|pricing|faq|gallery|testimonial|footer|header|navigation/i.test(c))||tag;break; } if(['section','nav','header','footer'].includes(tag)){sec=tag;break;} n=n.parentElement; } const tag=el.tagName.toLowerCase(); let type='element',label=''; if(tag==='img'){type='image';label=el.alt||'Image';} else if(tag==='button'||(tag==='a'&&el.href)){type='button';label=(el.textContent||'').trim().slice(0,30)||'Button';} else if(/^h[1-4]$/.test(tag)){type='heading';label=(el.textContent||'').trim().slice(0,40)||'Heading';} else if(tag==='p'||tag==='span'){type='text';label=(el.textContent||'').trim().slice(0,40)||'Text';} else if(tag==='input'||tag==='textarea'){type='input';label=el.placeholder||el.name||'Input';} else{type='section';label=sec||tag;} return{section:sec,type,label,tag,className:(el.className||'').toString()}; } function hl(el){ if(!overlay)return; const r=el.getBoundingClientRect(); overlay.style.cssText=overlay.style.cssText; overlay.style.display='block'; overlay.style.top=(r.top-2)+'px';overlay.style.left=(r.left-2)+'px'; overlay.style.width=(r.width+4)+'px';overlay.style.height=(r.height+4)+'px'; const info=classify(el); badge.style.display='block'; badge.textContent=(info.section?cap(info.section)+' › ':'')+info.label; badge.style.top=Math.max(4,r.top-24)+'px';badge.style.left=r.left+'px'; } function over(e){if(!enabled)return;e.stopPropagation();init();hl(e.target);} function sendToParent(msg){ // Works in both iframe (window.parent) and new tab (window.opener) var t=window.parent!==window?window.parent:(window.opener||null); if(t)t.postMessage(msg,'*'); } function click(e){ if(!enabled)return;e.preventDefault();e.stopPropagation(); var info=classify(e.target); // Use elementType to avoid overwriting the message type field sendToParent({type:'vula:selected',elementType:info.type,section:info.section,label:info.label,tag:info.tag,className:info.className}); } function enable(){enabled=true;init();document.addEventListener('mouseover',over,true);document.addEventListener('click',click,true);document.body.style.cursor='crosshair';} function disable(){enabled=false;document.removeEventListener('mouseover',over,true);document.removeEventListener('click',click,true);document.body.style.cursor='';if(overlay){overlay.style.display='none';badge.style.display='none';}} window.addEventListener('message',function(e){ if(!e.data)return; if(e.data.type==='vula:enable')enable(); else if(e.data.type==='vula:disable')disable(); }); // Announce ready so IDE can re-send enable state after iframe reload function announceReady(){sendToParent({type:'vula:ready'});} if(document.readyState==='loading'){document.addEventListener('DOMContentLoaded',announceReady);} else{announceReady();} }());