-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcontent.js
More file actions
1 lines (1 loc) · 79.4 KB
/
Copy pathcontent.js
File metadata and controls
1 lines (1 loc) · 79.4 KB
1
const getTiers=()=>globalThis.EASYVIEW_TIERS||{PREMIUM:{fonts:["lexend","atkinson"],beamShapes:["line"]}};function clampSettings(e={}){if(state.isPremium)return e;const n={...e},t=getTiers().PREMIUM;let o=!1;return t.fonts&&t.fonts.includes(n.font)&&(n.font="default",o=!0,showToast("Premium font reverted to default (Subscription expired)")),t.beamShapes&&t.beamShapes.includes(n.beamShape)&&(n.beamShape="circle",o=!0),o&&chrome.storage.sync.set({dyslexiaFont:"default"===n.font?"opendyslexic":e.dyslexiaFont,lastVisualSettings:n}),n}let state={jargonEnabled:!1,sensoryEnabled:!1,dyslexiaEnabled:!1,ttsEnabled:!1,apiKey:null,jargonMap:[],animatedElements:[],selectionDecoderActive:!1,abortController:null,isGenerating:!1,dyslexiaSettings:{font:"opendyslexic",letterSpacing:0,lineHeight:1.5,wordSpacing:0,overlayColor:"none",bionicReading:!1,fontSize:100},ttsSettings:{speed:1,pauseOnPunctuation:!0,wordHighlight:!0},ttsState:{isPlaying:!1,isPaused:!1,currentUtterance:null,currentWordIndex:0,textContent:"",words:[],selectionRange:null,wordSpans:[],speechStartTime:0,highlightIntervalId:null,useTimeFallback:!1,boundaryFired:!1},lastTrustedInteractionTime:0,isPremium:!1,bionicObserver:null};const updateInteractionTime=e=>{e.isTrusted&&(state.lastTrustedInteractionTime=Date.now())};document.addEventListener("mousedown",updateInteractionTime,!0),document.addEventListener("keydown",updateInteractionTime,!0),document.addEventListener("touchstart",updateInteractionTime,!0),window.addEventListener("message",e=>{if(e.source===window&&chrome.runtime&&chrome.runtime.id){if("EASYVIEW_PAYMENT_SUCCESS"===e.data?.type)try{chrome.runtime.sendMessage({type:"SET_PREMIUM",isPremium:e.data.isPremium})}catch(e){}if("EASYVIEW_AUTH"===e.data?.type){const{userId:n,email:t,isPremium:o}=e.data;if(n)try{chrome.runtime.sendMessage({type:"SET_USER_PROFILE",userId:n,email:t,isPremium:o})}catch(e){}}}});let currentTheme="dark";function injectThemeVariables(e=!1){currentTheme=e?"light":"dark"}function initThemeSystem(){chrome.storage.sync.get(["theme"],e=>{injectThemeVariables("light"===e.theme)}),chrome.storage.onChanged.addListener((e,n)=>{if("sync"===n&&e.theme){injectThemeVariables("light"===e.theme.newValue)}})}function applyAllVisualSettingsFromStorage(){chrome.storage.sync.get(["lastVisualSettings","enableVisuals"],e=>{e&&!0===e.enableVisuals&&e.lastVisualSettings&&applyVisualAdjustments(e.lastVisualSettings)})}function applyVisualAdjustments(e){if(document.documentElement.classList.add("ev-visuals-active"),document.body.classList.add("ev-visuals-active"),!e||0===Object.keys(e).length)return void removeVisualAdjustments();const n=void 0!==e.brightness?e.brightness:100,t=void 0!==e.contrast?e.contrast:100,o=void 0!==e.sepia?e.sepia:0,i=void 0!==e.grayscale?e.grayscale:0;if(100===n&&100===t&&0===o&&0===i)document.body.style.filter="none";else{const e=`brightness(${n}%) contrast(${t}%) sepia(${o}%) grayscale(${i}%)`;document.body.style.filter=e}if(e.font){let n=e.font;getTiers().PREMIUM.fonts.includes(e.font)&&!state.isPremium&&(n="default",chrome.storage.sync.set({visualAdjustments:{...e,font:"default"}}),showToast("Premium font reverted to default (Subscription expired/downgraded)"));const t={opendyslexic:"'OpenDyslexicLocal', 'OpenDyslexic', sans-serif",lexend:"'LexendLocal', sans-serif",atkinson:"'AtkinsonLocal', sans-serif",times:"'Times New Roman', Times, serif",georgia:"Georgia, serif",garamond:"Garamond, serif",arial:"Arial, Helvetica, sans-serif",helvetica:"Helvetica, Arial, sans-serif",verdana:"Verdana, Geneva, sans-serif",tahoma:"Tahoma, Geneva, sans-serif",trebuchet:"'Trebuchet MS', Helvetica, sans-serif",comic:"'Comic Sans MS', 'Comic Sans', cursive",comic_neue:"'ComicNeueLocal', cursive",courier:"'Courier New', Courier, monospace",serif:"serif",sans:"sans-serif",monospace:"monospace"}[n]||n;"default"===t?(document.body.style.fontFamily="",document.body.style.removeProperty("--ev-visual-font")):(document.body.style.setProperty("--ev-visual-font",t),document.body.style.fontFamily=t)}void 0!==e.textStroke&&(document.body.style.setProperty("--ev-visual-text-stroke",e.textStroke),document.body.style.webkitTextStroke=e.textStroke>0?`${e.textStroke}px #000`:""),document.documentElement.classList.remove("ev-dark-mode","ev-light-mode");let a=e.mode;if(a||(a="light"),"dark"===a?(document.documentElement.classList.add("ev-dark-mode"),injectThemeVariables(!1)):(document.documentElement.classList.add("ev-light-mode"),injectThemeVariables(!0)),void 0!==e.letterSpacing&&(document.body.style.setProperty("--ev-visual-letter-spacing",e.letterSpacing+"px"),document.body.style.letterSpacing=e.letterSpacing+"px"),void 0!==e.lineHeight&&(document.body.style.setProperty("--ev-visual-line-height",e.lineHeight),document.body.style.lineHeight=e.lineHeight),void 0!==e.wordSpacing&&(document.body.style.setProperty("--ev-visual-word-spacing",e.wordSpacing+"px"),document.body.style.wordSpacing=e.wordSpacing+"px"),void 0!==e.fontSize&&100!==e.fontSize){const n=e.fontSize/100;document.body.style.setProperty("--ev-visual-font-size-factor",n),document.body.style.fontSize=e.fontSize+"%";injectCSS(`\n /* Broad targeting for all text-containing elements to ensure nothing is missed */\n p, li, td, th, blockquote, figcaption, span:not([class*="icon"]), a, \n button, input, select, textarea, label, summary {\n font-size: calc(1rem * ${n}) !important;\n }\n h1 { font-size: calc(2.2rem * ${n}) !important; }\n h2 { font-size: calc(1.8rem * ${n}) !important; }\n h3 { font-size: calc(1.5rem * ${n}) !important; }\n h4, h5, h6 { font-size: calc(1.2rem * ${n}) !important; }\n `,"ev-visual-styles")}else document.body.style.fontSize="",removeCSS("ev-visual-styles");if(removeCSS("ev-visual-overlay"),e.overlayColor&&"none"!==e.overlayColor){injectCSS(`\n body::before {\n content: '';\n position: fixed;\n top: 0;\n left: 0;\n width: 100vw;\n height: 100vh;\n background: ${{beige:"rgba(245, 222, 179, 0.3)",blue:"rgba(173, 216, 230, 0.3)",green:"rgba(144, 238, 144, 0.3)",yellow:"rgba(255, 255, 224, 0.3)"}[e.overlayColor]||"rgba(0,0,0,0)"};\n pointer-events: none;\n z-index: 999999;\n }\n `,"ev-visual-overlay")}e.bionicReading?"function"==typeof applyBionicReading&&applyBionicReading():"function"==typeof removeBionicReading&&removeBionicReading()}function removeVisualAdjustments(){document.documentElement.classList.remove("ev-visuals-active","ev-dark-mode","ev-light-mode"),document.body.classList.remove("ev-visuals-active"),document.body.style.filter="",document.body.style.fontFamily="",document.body.style.webkitTextStroke="",document.body.style.letterSpacing="",document.body.style.lineHeight="",document.body.style.wordSpacing="",document.body.style.fontSize="",document.body.style.removeProperty("--ev-visual-font-size-factor"),removeCSS("ev-visual-overlay"),removeCSS("ev-visual-styles"),"function"==typeof removeBionicReading&&removeBionicReading()}async function init(){const e=await chrome.storage.sync.get(["jargonEnabled","sensoryEnabled","dyslexiaEnabled","dyslexiaFont","letterSpacing","lineHeight","wordSpacing","overlayColor","bionicReading","dyslexiaFontSize","ttsEnabled","ttsSpeed","ttsPauseOnPunctuation","ttsWordHighlight","ttsVolume","ttsVoice","isPremium","premiumExpiresAt","licenseToken","userId"]);if(e.isPremium&&e.premiumExpiresAt&&new Date(e.premiumExpiresAt).getTime()<Date.now()&&(e.isPremium=!1),e.isPremium)if(e.licenseToken&&e.userId){await verifyHardwareLicense(e.licenseToken,e.userId)||(e.isPremium=!1)}else e.isPremium=!1;const{apiKey:n}=await chrome.storage.local.get("apiKey");if(e.apiKey=n,Object.assign(state,e),void 0!==e.dyslexiaFont&&(state.dyslexiaSettings={font:e.dyslexiaFont||"opendyslexic",letterSpacing:e.letterSpacing||0,lineHeight:e.lineHeight||1.5,wordSpacing:e.wordSpacing||0,overlayColor:e.overlayColor||"none",bionicReading:e.bionicReading||!1,fontSize:e.dyslexiaFontSize||100}),void 0!==e.ttsSpeed&&(state.ttsSettings={speed:e.ttsSpeed||1,pauseOnPunctuation:!1!==e.ttsPauseOnPunctuation,wordHighlight:!1!==e.ttsWordHighlight,volume:void 0!==e.ttsVolume?e.ttsVolume/100:.7,voice:e.ttsVoice||"auto"}),state.sensoryEnabled){const{sensoryMode:e}=await chrome.storage.local.get("sensoryMode").catch(()=>({})),n=await new Promise(e=>chrome.storage.sync.get("sensoryMode",n=>e(n.sensoryMode||"freeze")));activateSensoryShield(n)}state.dyslexiaEnabled&&activateDyslexiaMode(state.dyslexiaSettings),state.ttsEnabled&&activateTTSMode(state.ttsSettings),state.bionicReading&&applyBionicReading(),initSelectionDecoder()}async function handleMessage(e){const{action:n}=e;switch(n){case"toggleJargon":return state.jargonEnabled=e.enabled,e.enabled?await activateJargonDecoder():deactivateJargonDecoder(),{success:!0};case"toggleSensory":return state.sensoryEnabled=e.enabled,e.enabled?activateSensoryShield(e.mode||"freeze"):deactivateSensoryShield(),{success:!0};case"toggleDyslexia":return state.dyslexiaEnabled=e.enabled,e.enabled?activateDyslexiaMode(e.settings):deactivateDyslexiaMode(),{success:!0};case"updateDyslexia":return updateDyslexiaSettings(e.settings),{success:!0};case"toggleTTS":return state.ttsEnabled=e.enabled,e.enabled?activateTTSMode(e.settings):deactivateTTSMode(),{success:!0};case"updateTTS":return state.ttsEnabled&&updateTTSSettings(e.settings),{success:!0};case"ttsPlay":return playTTS(),{success:!0};case"ttsPause":return pauseTTS(),{success:!0};case"ttsStop":return stopTTS(),{success:!0};case"toggleBionic":return state.bionicReading=e.enabled,e.enabled?applyBionicReading():removeBionicReading(),{success:!0};default:return{success:!1,error:"Unknown action"}}}async function getAvailableApiConfig(){const{apiProvider:e}=await chrome.storage.sync.get("apiProvider"),n=e||"gemini",t=await chrome.storage.local.get(["apiKey","geminiKey"]),o=await chrome.storage.sync.get(["userId"]);let i=n,a="gemini"===i?t.geminiKey:t.apiKey;return a||(i="gemini"===n?"openrouter":"gemini",a="gemini"===i?t.geminiKey:t.apiKey),{provider:i,apiKey:a,hasKey:!!a,hasOwnKey:!!a,userId:o.userId||null}}function initSelectionDecoder(){const e=document.createElement("div");e.className="ev-selection-toolbar",e.style.display="none";const n=document.createElement("div");n.className="ev-selection-define-btn ev-toolbar-btn",n.innerHTML='\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\n <circle cx="12" cy="12" r="10"></circle>\n <line x1="12" y1="16" x2="12" y2="12"></line>\n <line x1="12" y1="8" x2="12.01" y2="8"></line>\n </svg>\n <span>Define</span>\n ';const t=document.createElement("div");t.className="ev-selection-decode-btn ev-toolbar-btn",t.innerHTML='\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\n <path d="M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H20v20H6.5a2.5 2.5 0 0 1 0-5H20"/>\n <path d="M8 7h6"/>\n <path d="M8 11h8"/>\n </svg>\n <span>Decode</span>\n ';const o=document.createElement("div");o.className="ev-selection-simplify-btn ev-toolbar-btn",o.innerHTML='\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\n <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>\n <polyline points="14 2 14 8 20 8"/>\n <line x1="16" y1="13" x2="8" y2="13"/>\n <line x1="16" y1="17" x2="8" y2="17"/>\n <polyline points="10 9 9 9 8 9"/>\n </svg>\n <span>Simplify</span>\n ';const i=document.createElement("div");i.className="ev-selection-toolbar-bookmark-btn ev-toolbar-btn",i.innerHTML='\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\n <path d="M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"></path>\n </svg>\n <span>Bookmark</span>\n ',e.appendChild(n),e.appendChild(t),e.appendChild(o),e.appendChild(i),document.body.appendChild(e),injectSelectionDecoderStyles();let a=null,r=null;function s(){e.classList.remove("ev-visible"),setTimeout(()=>{e.classList.contains("ev-visible")||(e.style.display="none")},200)}document.addEventListener("mouseup",l=>{l.target.closest(".ev-selection-toolbar")||setTimeout(()=>{const l=window.getSelection(),c=l.toString().trim();if(c.length>=3&&c.length<=5e3){a=c,r=l.getRangeAt(0).cloneRange();const s=l.getRangeAt(0).getBoundingClientRect();let d=395;c.trim().split(/\s+/).length<=2?(n.style.display="flex",i.style.display="flex",t.style.display="none",o.style.display="none",d=220):(n.style.display="none",i.style.display="flex",t.style.display="flex",o.style.display="flex",d=310);const p=44;let m=s.left+s.width/2-d/2,v=s.top-p-12+window.scrollY;m=Math.max(10,Math.min(m,window.innerWidth-d-10)),v<window.scrollY+10&&(v=s.bottom+12+window.scrollY),e.style.left=`${m}px`,e.style.top=`${v}px`,e.style.display="flex",e.classList.add("ev-visible")}else s()},10)}),document.addEventListener("mousedown",e=>{e.target.closest(".ev-selection-toolbar")||s()}),document.addEventListener("scroll",()=>{if(e.classList.contains("ev-visible")&&r){const e=r.getBoundingClientRect();(e.top<0||e.bottom>window.innerHeight)&&s()}},{passive:!0}),n.addEventListener("click",async()=>{a&&r&&(s(),await defineSelectedText(a,r))}),t.addEventListener("click",async()=>{a&&r&&(s(),await decodeSelectedText(a,r))}),o.addEventListener("click",async()=>{a&&r&&(s(),await simplifySelectedText(a,r))}),i.addEventListener("click",async()=>{if(a){const e=a.trim();s();try{const n=(await chrome.storage.local.get(["savedVocabulary"])).savedVocabulary||[],t=e.toLowerCase();if(n.some(e=>e.termKey===t))return void showNotification("Already in Notebook!","info");const o={termKey:t,jargon:e,simple:"Manual highlight",explanation:"Saved directly from web page.",category:"custom",timestamp:Date.now()};await chrome.storage.local.set({savedVocabulary:[o,...n]}),showNotification("Saved to Notebook!","success")}catch(e){showNotification("Error saving to Notebook","error")}}})}async function decodeSelectedText(e,n){const t=e?e.trim():"";if(!t)return;showProgressLoader("Decoding selection...","jargon"),updateProgress(10),state.abortController=new AbortController,state.isGenerating=!0;const o="sel_jargon_"+hashString(t.toLowerCase()),i=await getSelectionCache(o);if(i)return updateProgress(80),updateProgressText("Using cached results..."),0===i.length?(hideProgressLoader(),state.isGenerating=!1,state.abortController=null,void showNotification("No complex terms found in selection","info")):(applyJargonToSelection(i,n),updateProgress(100),hideProgressLoader(),state.isGenerating=!1,state.abortController=null,void await showSelectionDecodedPopup(i,n));const a=await getAvailableApiConfig();if(!a.hasOwnKey&&!a.userId)return hideProgressLoader(),state.isGenerating=!1,void showNotification("Sign in to EasyView to get 5 free uses/month, or add your own API key in Settings.","info");updateProgress(20);try{updateProgressText("Analyzing with AI..."),updateProgress(40);const t=await chrome.runtime.sendMessage({action:"detectJargon",pageText:e,apiKey:a.apiKey,abortSignal:state.abortController.signal.aborted});if(!t||!t.success){const e=t?.error||"AI decoding failed";return hideProgressLoader(),state.isGenerating=!1,void("QUOTA_EXCEEDED"===e?(showNotification("You've used all free Jargon Decoder uses this month. Upgrade to Pro for unlimited access.","error"),setTimeout(()=>{chrome.runtime.sendMessage({type:"SHOW_PREMIUM_MODAL",feature:"jargon"})},1500)):showNotification(e,"error"))}const i=t.data||[];if(!state.isGenerating||state.abortController.signal.aborted)return void hideProgressLoader();if(updateProgress(70),await setSelectionCache(o,i),0===i.length)return hideProgressLoader(),state.isGenerating=!1,state.abortController=null,void showNotification("No complex terms found in selection","info");updateProgressText("Applying simplifications..."),updateProgress(85),applyJargonToSelection(i,n),updateProgress(100),hideProgressLoader(),state.isGenerating=!1,state.abortController=null,await showSelectionDecodedPopup(i,n)}catch(e){hideProgressLoader(),state.isGenerating=!1,state.abortController=null,"AbortError"!==e.name&&showNotification("Error decoding selection","error")}}async function simplifySelectedText(e,n){const t=e?e.trim():"";if(!t)return;showProgressLoader("Simplifying text...","jargon"),updateProgress(10),state.abortController=new AbortController,state.isGenerating=!0;const o="sel_simplify_"+hashString(t.toLowerCase()),i=await getSelectionCache(o);if(i)return updateProgress(80),updateProgressText("Using cached results..."),i&&i.simplified?(updateProgress(100),hideProgressLoader(),state.isGenerating=!1,state.abortController=null,void await showSimplifiedTextPopup(e,i,n)):(hideProgressLoader(),state.isGenerating=!1,state.abortController=null,void showNotification("Could not simplify this text","info"));const a=await getAvailableApiConfig();if(!a.hasOwnKey&&!a.userId)return hideProgressLoader(),state.isGenerating=!1,void showNotification("Sign in to EasyView to get 5 free uses/month, or add your own API key in Settings.","info");updateProgress(20);try{updateProgressText("Simplifying with AI..."),updateProgress(40);const t=await chrome.runtime.sendMessage({action:"simplifyText",text:e,apiKey:a.apiKey,abortSignal:state.abortController.signal.aborted});if(!t||!t.success){const e=t?.error||"Simplification failed";return hideProgressLoader(),state.isGenerating=!1,void("QUOTA_EXCEEDED"===e?(showNotification("You've used all free uses this month. Upgrade to Pro for unlimited access.","error"),setTimeout(()=>{chrome.runtime.sendMessage({type:"SHOW_PREMIUM_MODAL",feature:"jargon"})},1500)):showNotification(e,"error"))}const i=t.data;if(!state.isGenerating||state.abortController.signal.aborted)return void hideProgressLoader();if(updateProgress(70),!t.success||!t.data||!t.data.simplified)return hideProgressLoader(),state.isGenerating=!1,state.abortController=null,void showNotification("Could not simplify this text","info");await setSelectionCache(o,i),updateProgressText("Done!"),updateProgress(100),hideProgressLoader(),state.isGenerating=!1,state.abortController=null,await showSimplifiedTextPopup(e,t.data,n)}catch(e){hideProgressLoader(),state.isGenerating=!1,state.abortController=null,"AbortError"!==e.name&&showNotification("Error simplifying text","error")}}function makeDraggable(e,n){const t=e.querySelector(n);if(!t)return;let o,i,a,r,s=!1;t.style.cursor="grab",t.style.userSelect="none";const l=n=>{if(!s)return;const t=n.clientX-o,l=n.clientY-i;let c=a+t,d=r+l;const p=e.getBoundingClientRect(),m=window.innerWidth-p.width,v=window.innerHeight-p.height;c=Math.max(0,Math.min(c,m)),d=Math.max(0,Math.min(d,v)),e.style.position="fixed",e.style.left=`${c}px`,e.style.top=`${d}px`,e.style.transform="none"},c=()=>{s=!1,t.style.cursor="grab",document.removeEventListener("mousemove",l),document.removeEventListener("mouseup",c)};t.addEventListener("mousedown",n=>{if(n.target.closest("button"))return;s=!0,t.style.cursor="grabbing";const d=e.getBoundingClientRect();a=d.left,r=d.top,o=n.clientX,i=n.clientY,n.preventDefault(),document.addEventListener("mousemove",l),document.addEventListener("mouseup",c)}),t.addEventListener("touchstart",n=>{if(n.target.closest("button"))return;s=!0;const t=n.touches[0],l=e.getBoundingClientRect();a=l.left,r=l.top,o=t.clientX,i=t.clientY},{passive:!0}),t.addEventListener("touchmove",n=>{if(!s)return;const t=n.touches[0],l=t.clientX-o,c=t.clientY-i;let d=a+l,p=r+c;const m=e.getBoundingClientRect(),v=window.innerWidth-m.width,u=window.innerHeight-m.height;d=Math.max(0,Math.min(d,v)),p=Math.max(0,Math.min(p,u)),e.style.position="fixed",e.style.left=`${d}px`,e.style.top=`${p}px`,e.style.transform="none"},{passive:!0}),t.addEventListener("touchend",()=>{s=!1})}async function showSimplifiedTextPopup(e,n,t){document.querySelector(".ev-simplify-popup")?.remove();const o=e.toLowerCase().trim();let i=!1;try{const e=await chrome.storage.local.get(["savedVocabulary"]);i=(e.savedVocabulary||[]).some(e=>e.termKey===o)}catch(e){}const a=t.getBoundingClientRect(),r=document.createElement("div");r.className="ev-simplify-popup",r.innerHTML=`\n <div class="ev-simplify-popup-header ev-draggable-header">\n <span class="ev-simplify-popup-title">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">\n <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>\n <polyline points="14 2 14 8 20 8"/>\n <line x1="16" y1="13" x2="8" y2="13"/>\n <line x1="16" y1="17" x2="8" y2="17"/>\n </svg>\n Simplified Version\n <span class="ev-drag-hint">⋮⋮</span>\n </span>\n <div class="ev-simplify-popup-actions">\n <button class="ev-simplify-copy" title="Copy simplified text">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <rect x="9" y="9" width="13" height="13" rx="2" ry="2"/>\n <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/>\n </svg>\n </button>\n <button class="ev-simplify-bookmark-btn ${i?"active":""}" title="${i?"Saved to Notebook":"Save to Notebook"}">\n <svg viewBox="0 0 24 24" fill="${i?"currentColor":"none"}" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round">\n <path d="M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"></path>\n </svg>\n </button>\n <button class="ev-simplify-popup-close">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <line x1="18" y1="6" x2="6" y2="18"/>\n <line x1="6" y1="6" x2="18" y2="18"/>\n </svg>\n </button>\n </div>\n </div>\n <div class="ev-simplify-popup-content">\n <div class="ev-simplify-text">${escapeHtml(n.simplified)}</div>\n <div class="ev-simplify-meta">\n <span class="ev-simplify-level">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"/>\n <path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/>\n </svg>\n Reading level: ${escapeHtml(n.readingLevel)}\n </span>\n </div>\n ${n.keyChanges&&n.keyChanges.length>0?`\n <div class="ev-simplify-changes">\n <div class="ev-simplify-changes-title">Key simplifications:</div>\n <ul>\n ${n.keyChanges.map(e=>`<li>${escapeHtml(e)}</li>`).join("")}\n </ul>\n </div>\n `:""}\n </div>\n <div class="ev-simplify-popup-footer">\n <button class="ev-simplify-replace">Replace on page</button>\n </div>\n `;let s=a.left+a.width/2-180,l=a.bottom+15+window.scrollY;s=Math.max(10,Math.min(s,window.innerWidth-370)),r.style.left=`${s}px`,r.style.top=`${l}px`,document.body.appendChild(r),makeDraggable(r,".ev-simplify-popup-header"),requestAnimationFrame(()=>{r.classList.add("ev-visible")}),r.querySelector(".ev-simplify-popup-close").addEventListener("click",()=>{r.classList.remove("ev-visible"),setTimeout(()=>r.remove(),200)});const c=r.querySelector(".ev-simplify-bookmark-btn");c&&c.addEventListener("click",async t=>{t.stopPropagation();const i=(await chrome.storage.local.get(["savedVocabulary"])).savedVocabulary||[];let a,r;if(i.some(e=>e.termKey===o))a=i.filter(e=>e.termKey!==o),r=!1;else{const t=n.keyChanges?n.keyChanges.join("; "):`Reading level: ${n.readingLevel}`;a=[{termKey:o,jargon:e.trim(),simple:n.simplified.trim(),explanation:t,category:"general",timestamp:Date.now()},...i],r=!0}await chrome.storage.local.set({savedVocabulary:a}),c.classList.toggle("active",r),c.title=r?"Saved to Notebook":"Save to Notebook";const s=c.querySelector("svg");s&&s.setAttribute("fill",r?"currentColor":"none"),c.style.transform="scale(1.2)",setTimeout(()=>c.style.transform="",150),showNotification(r?"Saved to Notebook!":"Removed from Notebook","success")}),r.querySelector(".ev-simplify-copy").addEventListener("click",async()=>{try{await navigator.clipboard.writeText(n.simplified),showNotification("Copied to clipboard!","success")}catch(e){showNotification("Failed to copy","error")}}),r.querySelector(".ev-simplify-replace").addEventListener("click",()=>{replaceSelectionWithSimplified(t,n.simplified),r.classList.remove("ev-visible"),setTimeout(()=>r.remove(),200),showNotification("Text replaced on page","success")}),setTimeout(()=>{document.body.contains(r)&&(r.classList.remove("ev-visible"),setTimeout(()=>r.remove(),200))},3e4)}function replaceSelectionWithSimplified(e,n){const t=e.commonAncestorContainer,o=t.nodeType===Node.TEXT_NODE?t.parentElement:t;if(!o)return;let i=o;if(o.nodeType===Node.ELEMENT_NODE){const e=o.querySelector("p, div, span, h1, h2, h3, h4, h5, h6");e&&(i=e)}const a=window.getComputedStyle(i),r=a.fontFamily,s=a.fontSize,l=a.lineHeight,c=a.fontWeight,d=a.color,p=a.letterSpacing,m=a.wordSpacing,v=document.createElement("span");v.className="ev-simplified-text",v.title="This text was simplified by EasyView",v.setAttribute("data-original-font",r),v.setAttribute("data-original-size",s),v.setAttribute("data-original-line-height",l),v.setAttribute("data-original-letter-spacing",p),v.setAttribute("data-original-word-spacing",m),v.style.fontFamily=r,v.style.fontSize=s,v.style.lineHeight=l,v.style.fontWeight=c,v.style.color=d,v.style.letterSpacing=p,v.style.wordSpacing=m,v.style.display="inline";const u=n.split("\n\n").filter(e=>e.trim());u.length>1?(v.style.display="block",v.innerHTML=u.map(e=>`<p style="margin: 0 0 1em 0; padding: 0; font-family: inherit; font-size: inherit; line-height: inherit; font-weight: inherit; color: inherit; letter-spacing: inherit; word-spacing: inherit;">${escapeHtml(e.trim())}</p>`).join("")):v.innerHTML=escapeHtml(n.replace(/\n/g," ").trim()),e.deleteContents(),e.insertNode(v),injectSimplifiedTextStyles()}function injectSimplifiedTextStyles(){injectCSS("\n .ev-simplified-text {\n background: rgba(34, 197, 94, 0.1);\n border-left: 2px solid #22c55e;\n padding: 2px 6px;\n border-radius: 4px;\n transition: background 0.2s;\n }\n \n .ev-simplified-text:hover {\n background: rgba(34, 197, 94, 0.15);\n }\n \n .ev-simplified-text p {\n margin: 0 0 1em 0;\n padding: 0;\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n letter-spacing: inherit;\n word-spacing: inherit;\n color: inherit;\n }\n \n .ev-simplified-text p:last-child {\n margin-bottom: 0;\n }\n ","ev-simplified-text-styles")}function applyJargonToSelection(e,n){const t=n.commonAncestorContainer,o=t.nodeType===Node.TEXT_NODE?t.parentElement:t;o&&(e.forEach(({jargon:e,simple:n,explanation:t,category:i,difficulty:a})=>{const r=new RegExp(`\\b${escapeRegex(e)}\\b`,"gi"),s=escapeHtml(n),l=escapeHtml(t||""),c=escapeHtml(i||"general"),d=document.createTreeWalker(o,NodeFilter.SHOW_TEXT,{acceptNode:e=>{const n=e.parentElement;if(!n)return NodeFilter.FILTER_SKIP;const t=n.tagName.toLowerCase();return["script","style","noscript"].includes(t)||n.classList.contains("ev-jargon-wrapper")||n.classList.contains("ev-jargon")?NodeFilter.FILTER_SKIP:e.textContent?.match(r)?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP}}),p=[];let m;for(;m=d.nextNode();)p.push(m);p.forEach(e=>{if(!e.parentElement)return;const n=e.textContent;let t=0;r.lastIndex=0;const o=document.createDocumentFragment();let i,d=!1;for(;null!==(i=r.exec(n));){d=!0,i.index>t&&o.appendChild(document.createTextNode(n.substring(t,i.index)));const e=document.createElement("span");e.className=`ev-jargon ev-jargon-selection ev-jargon-${c} ev-difficulty-${a||2}`,e.setAttribute("data-simple",s),e.setAttribute("data-explanation",l),e.setAttribute("data-category",c),e.setAttribute("data-original",i[0]),e.textContent=i[0],o.appendChild(e),t=r.lastIndex}if(!d)return;t<n.length&&o.appendChild(document.createTextNode(n.substring(t)));const p=document.createElement("span");p.className="ev-jargon-wrapper ev-selection-wrapper",p.appendChild(o),e.replaceWith(p)})}),injectJargonStyles())}async function showSelectionDecodedPopup(e,n){document.querySelector(".ev-selection-popup")?.remove();let t=[];try{const e=await chrome.storage.local.get(["savedVocabulary"]);t=e.savedVocabulary||[]}catch(e){}const o=n.getBoundingClientRect(),i=document.createElement("div");i.className="ev-selection-popup",i.innerHTML=`\n <div class="ev-selection-popup-header ev-draggable-header">\n <span class="ev-selection-popup-title">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">\n <path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/>\n <polyline points="22 4 12 14.01 9 11.01"/>\n </svg>\n Decoded ${e.length} term${e.length>1?"s":""}\n <span class="ev-drag-hint">⋮⋮</span>\n </span>\n <button class="ev-selection-popup-close">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <line x1="18" y1="6" x2="6" y2="18"/>\n <line x1="6" y1="6" x2="18" y2="18"/>\n </svg>\n </button>\n </div>\n <div class="ev-selection-popup-content">\n ${e.map(e=>{const n=(e=>{const n=e.toLowerCase().trim();return t.some(e=>e.termKey===n)})(e.jargon);return`\n <div class="ev-selection-popup-item" data-term="${escapeHtml(e.jargon.toLowerCase().trim())}">\n <div class="ev-selection-popup-term-row">\n <div class="ev-selection-popup-term">\n <span class="ev-term-original">${escapeHtml(e.jargon)}</span>\n <span class="ev-term-arrow">→</span>\n <span class="ev-term-simple">${escapeHtml(e.simple)}</span>\n </div>\n <button class="ev-selection-bookmark-btn ${n?"active":""}" aria-label="Save to Notebook" title="${n?"Saved":"Save to Notebook"}">\n <svg viewBox="0 0 24 24" fill="${n?"currentColor":"none"}" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round">\n <path d="M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"></path>\n </svg>\n </button>\n </div>\n ${e.explanation?`<div class="ev-selection-popup-explanation">${escapeHtml(e.explanation)}</div>`:""}\n </div>\n `}).join("")}\n </div>\n <div class="ev-selection-popup-footer">\n <button class="ev-selection-popup-clear">Clear highlights</button>\n </div>\n `;let a=o.left+o.width/2-160,r=o.bottom+15+window.scrollY;a=Math.max(10,Math.min(a,window.innerWidth-330)),i.style.left=`${a}px`,i.style.top=`${r}px`,document.body.appendChild(i),makeDraggable(i,".ev-selection-popup-header"),requestAnimationFrame(()=>{i.classList.add("ev-visible")}),i.querySelectorAll(".ev-selection-popup-item").forEach(n=>{const t=n.getAttribute("data-term"),o=e.find(e=>e.jargon.toLowerCase().trim()===t),i=n.querySelector(".ev-selection-bookmark-btn");i&&o&&i.addEventListener("click",async e=>{e.stopPropagation();const n=(await chrome.storage.local.get(["savedVocabulary"])).savedVocabulary||[];let a,r;if(n.some(e=>e.termKey===t))a=n.filter(e=>e.termKey!==t),r=!1;else{a=[{termKey:t,jargon:o.jargon,simple:o.simple,explanation:o.explanation||"",category:o.category||"general",timestamp:Date.now()},...n],r=!0}await chrome.storage.local.set({savedVocabulary:a}),i.classList.toggle("active",r),i.title=r?"Saved":"Save to Notebook";const s=i.querySelector("svg");s&&s.setAttribute("fill",r?"currentColor":"none"),i.style.transform="scale(1.25)",setTimeout(()=>i.style.transform="",150),showNotification(r?"Saved to Notebook!":"Removed from Notebook","success")})}),i.querySelector(".ev-selection-popup-close").addEventListener("click",()=>{i.classList.remove("ev-visible"),setTimeout(()=>i.remove(),200)}),i.querySelector(".ev-selection-popup-clear").addEventListener("click",()=>{document.querySelectorAll(".ev-selection-wrapper").forEach(e=>{e.replaceWith(e.textContent)}),i.classList.remove("ev-visible"),setTimeout(()=>i.remove(),200),showNotification("Selection highlights cleared","info")}),setTimeout(()=>{document.body.contains(i)&&(i.classList.remove("ev-visible"),setTimeout(()=>i.remove(),200))},3e5)}function injectSelectionDecoderStyles(){injectCSS("\n /* Selection Toolbar Container */\n .ev-selection-toolbar {\n position: absolute;\n display: none;\n align-items: center;\n flex-wrap: nowrap !important;\n white-space: nowrap !important;\n gap: 6px;\n padding: 6px;\n background: var(--ev-bg-primary);\n border: 1px solid var(--ev-border-hover);\n border-radius: 12px;\n z-index: 10000000;\n box-shadow: var(--ev-shadow-md);\n opacity: 0;\n transform: translateY(5px);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n user-select: none;\n }\n \n .ev-selection-toolbar.ev-visible {\n opacity: 1;\n transform: translateY(0);\n }\n \n /* Toolbar Buttons */\n .ev-toolbar-btn {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 14px;\n background: transparent;\n border: 1px solid transparent;\n border-radius: 8px;\n color: var(--ev-text-secondary);\n font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n }\n \n .ev-toolbar-btn:hover {\n background: var(--ev-bg-tertiary);\n border-color: var(--ev-border-hover);\n color: var(--ev-text-primary);\n }\n \n .ev-toolbar-btn svg {\n width: 16px;\n height: 16px;\n }\n \n .ev-selection-define-btn:hover {\n color: #a855f7;\n }\n\n .ev-selection-decode-btn:hover {\n color: #60a5fa;\n }\n \n .ev-selection-simplify-btn:hover {\n color: #22c55e;\n }\n\n .ev-selection-toolbar-bookmark-btn:hover {\n color: #f59e0b; /* Dynamic Amber gold for direct bookmarks */\n }\n \n /* Selection-specific jargon highlighting */\n .ev-jargon-selection {\n animation: ev-selection-highlight 0.5s ease-out;\n }\n \n @keyframes ev-selection-highlight {\n 0% { background: rgba(255, 255, 255, 0.3); }\n 100% { background: rgba(255, 255, 255, 0.06); }\n }\n \n /* Selection Decoded Popup */\n .ev-selection-popup {\n position: absolute;\n width: 320px;\n background: var(--ev-bg-primary);\n border: 1px solid var(--ev-border-color);\n border-radius: 14px;\n box-shadow: var(--ev-shadow-lg);\n z-index: 10000001;\n overflow: hidden;\n opacity: 0;\n transform: translateY(10px);\n transition: opacity 0.25s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.2s;\n }\n \n .ev-selection-popup.ev-visible {\n opacity: 1;\n transform: none;\n }\n \n /* Draggable header styles */\n .ev-draggable-header {\n cursor: grab;\n user-select: none;\n }\n \n .ev-draggable-header:active {\n cursor: grabbing;\n }\n \n .ev-drag-hint {\n font-size: 12px;\n color: var(--ev-text-muted);\n margin-left: 6px;\n letter-spacing: 2px;\n opacity: 0.6;\n transition: opacity 0.2s;\n }\n \n .ev-draggable-header:hover .ev-drag-hint {\n opacity: 1;\n }\n \n .ev-selection-popup-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 16px;\n background: var(--ev-bg-secondary);\n border-bottom: 1px solid var(--ev-border-color);\n }\n \n .ev-selection-popup-title {\n display: flex;\n align-items: center;\n gap: 10px;\n font-family: 'Inter', sans-serif;\n font-size: 14px;\n font-weight: 600;\n color: #22c55e;\n }\n \n .ev-selection-popup-title svg {\n width: 18px;\n height: 18px;\n }\n \n .ev-selection-popup-close {\n width: 28px;\n height: 28px;\n background: transparent;\n border: 1px solid var(--ev-border-hover);\n border-radius: 6px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s;\n }\n \n .ev-selection-popup-close:hover {\n background: var(--ev-bg-tertiary);\n }\n \n .ev-selection-popup-close svg {\n width: 14px;\n height: 14px;\n color: var(--ev-text-muted);\n }\n \n .ev-selection-popup-content {\n padding: 12px;\n max-height: 250px;\n overflow-y: auto;\n }\n \n .ev-selection-popup-item {\n padding: 10px 12px;\n background: var(--ev-bg-secondary);\n border: 1px solid var(--ev-bg-tertiary);\n border-radius: 8px;\n margin-bottom: 8px;\n }\n \n .ev-selection-popup-item:last-child {\n margin-bottom: 0;\n }\n \n .ev-selection-popup-term {\n display: flex;\n align-items: center;\n gap: 8px;\n flex-wrap: wrap;\n font-family: 'Inter', sans-serif;\n font-size: 13px;\n }\n \n .ev-term-original {\n color: var(--ev-text-secondary);\n text-decoration: line-through;\n text-decoration-color: #ef4444;\n }\n \n .ev-term-arrow {\n color: var(--ev-text-muted);\n font-size: 12px;\n }\n \n .ev-term-simple {\n color: #22c55e;\n font-weight: 600;\n }\n \n .ev-selection-popup-term-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 10px;\n margin-bottom: 4px;\n }\n \n .ev-selection-bookmark-btn {\n all: unset !important;\n box-sizing: border-box !important;\n width: 26px !important;\n height: 26px !important;\n border-radius: 6px !important;\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n cursor: pointer !important;\n color: var(--ev-text-muted) !important;\n border: 1.5px solid var(--ev-border-color) !important;\n background: var(--ev-bg-primary) !important;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1) !important;\n flex-shrink: 0 !important;\n }\n \n .ev-selection-bookmark-btn:hover {\n color: #f59e0b !important;\n border-color: rgba(245, 158, 11, 0.6) !important;\n background: rgba(245, 158, 11, 0.08) !important;\n transform: translateY(-1px) !important;\n }\n \n .ev-selection-bookmark-btn.active {\n color: #d97706 !important;\n background: rgba(245, 158, 11, 0.15) !important;\n border-color: #f59e0b !important;\n }\n \n .ev-selection-bookmark-btn svg {\n width: 13px !important;\n height: 13px !important;\n transition: transform 0.15s ease !important;\n }\n \n .ev-selection-popup-explanation {\n margin-top: 6px;\n font-family: 'Inter', sans-serif;\n font-size: 12px;\n color: var(--ev-text-muted);\n line-height: 1.5;\n }\n \n .ev-selection-popup-footer {\n padding: 12px 16px;\n border-top: 1px solid var(--ev-border-color);\n background: var(--ev-bg-primary);\n }\n \n .ev-selection-popup-clear {\n width: 100%;\n padding: 10px;\n background: transparent;\n border: 1px solid var(--ev-border-hover);\n border-radius: 8px;\n color: var(--ev-text-secondary);\n font-family: 'Inter', sans-serif;\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s;\n }\n \n .ev-selection-popup-clear:hover {\n background: var(--ev-bg-tertiary);\n color: var(--ev-text-primary);\n border-color: var(--ev-border-hover);\n }\n \n /* Popup scrollbar */\n .ev-selection-popup-content::-webkit-scrollbar {\n width: 5px;\n }\n \n .ev-selection-popup-content::-webkit-scrollbar-track {\n background: var(--ev-scrollbar-track);\n }\n \n .ev-selection-popup-content::-webkit-scrollbar-thumb {\n background: var(--ev-scrollbar-thumb);\n border-radius: 3px;\n }\n \n /* Simplify Popup */\n .ev-simplify-popup {\n position: absolute;\n width: 360px;\n background: var(--ev-bg-primary);\n border: 1px solid var(--ev-border-color);\n border-radius: 14px;\n box-shadow: var(--ev-shadow-lg);\n z-index: 10000001;\n overflow: hidden;\n opacity: 0;\n transform: translateY(10px);\n transition: opacity 0.25s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.2s;\n }\n \n .ev-simplify-popup.ev-visible {\n opacity: 1;\n transform: none;\n }\n \n .ev-simplify-popup-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 16px;\n background: var(--ev-bg-secondary);\n border-bottom: 1px solid var(--ev-border-color);\n }\n \n .ev-simplify-popup-title {\n display: flex;\n align-items: center;\n gap: 10px;\n font-family: 'Inter', sans-serif;\n font-size: 14px;\n font-weight: 600;\n color: #22c55e;\n }\n \n .ev-simplify-popup-title svg {\n width: 18px;\n height: 18px;\n }\n \n .ev-simplify-popup-actions {\n display: flex;\n align-items: center;\n gap: 6px;\n }\n \n .ev-simplify-copy,\n .ev-simplify-bookmark-btn,\n .ev-simplify-popup-close {\n width: 28px;\n height: 28px;\n background: transparent;\n border: 1px solid var(--ev-border-hover);\n border-radius: 6px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n color: var(--ev-text-muted);\n }\n \n .ev-simplify-copy:hover,\n .ev-simplify-bookmark-btn:hover,\n .ev-simplify-popup-close:hover {\n background: var(--ev-bg-tertiary);\n }\n \n .ev-simplify-bookmark-btn:hover {\n color: #f59e0b;\n border-color: rgba(245, 158, 11, 0.6);\n }\n \n .ev-simplify-bookmark-btn.active {\n color: #d97706;\n border-color: #f59e0b;\n }\n \n .ev-simplify-copy svg,\n .ev-simplify-bookmark-btn svg,\n .ev-simplify-popup-close svg {\n width: 14px;\n height: 14px;\n color: inherit;\n }\n \n .ev-simplify-popup-content {\n padding: 16px;\n max-height: 300px;\n overflow-y: auto;\n }\n \n .ev-simplify-text {\n font-family: 'Inter', sans-serif;\n font-size: 14px;\n line-height: 1.7;\n color: var(--ev-text-primary);\n white-space: pre-wrap;\n }\n \n .ev-simplify-meta {\n margin-top: 14px;\n padding-top: 12px;\n border-top: 1px solid var(--ev-border-color);\n }\n \n .ev-simplify-level {\n display: flex;\n align-items: center;\n gap: 8px;\n font-family: 'Inter', sans-serif;\n font-size: 12px;\n color: var(--ev-text-muted);\n }\n \n .ev-simplify-level svg {\n width: 14px;\n height: 14px;\n }\n \n .ev-simplify-changes {\n margin-top: 12px;\n padding: 10px 12px;\n background: var(--ev-bg-secondary);\n border: 1px solid var(--ev-bg-tertiary);\n border-radius: 8px;\n }\n \n .ev-simplify-changes-title {\n font-family: 'Inter', sans-serif;\n font-size: 11px;\n font-weight: 600;\n color: var(--ev-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 8px;\n }\n \n .ev-simplify-changes ul {\n margin: 0;\n padding-left: 16px;\n }\n \n .ev-simplify-changes li {\n font-family: 'Inter', sans-serif;\n font-size: 12px;\n color: var(--ev-text-secondary);\n line-height: 1.6;\n margin-bottom: 4px;\n }\n \n .ev-simplify-changes li:last-child {\n margin-bottom: 0;\n }\n \n .ev-simplify-popup-footer {\n padding: 12px 16px;\n border-top: 1px solid var(--ev-border-color);\n background: var(--ev-bg-primary);\n }\n \n .ev-simplify-replace {\n width: 100%;\n padding: 10px 16px;\n background: #22c55e;\n border: none;\n border-radius: 8px;\n color: white;\n font-family: 'Inter', sans-serif;\n font-size: 13px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s;\n }\n \n .ev-simplify-replace:hover {\n background: #16a34a;\n transform: translateY(-1px);\n }\n \n \n /* Simplify popup scrollbar */\n .ev-simplify-popup-content::-webkit-scrollbar {\n width: 5px;\n }\n \n .ev-simplify-popup-content::-webkit-scrollbar-track {\n background: var(--ev-scrollbar-track);\n }\n \n .ev-simplify-popup-content::-webkit-scrollbar-thumb {\n background: var(--ev-scrollbar-thumb);\n border-radius: 3px;\n }\n\n /* Definition Popup Specifics */\n .ev-definition-popup {\n position: absolute;\n width: 340px;\n background: var(--ev-bg-primary);\n border: 1px solid var(--ev-border-color);\n border-radius: 14px;\n box-shadow: var(--ev-shadow-lg);\n z-index: 10000001;\n overflow: hidden;\n opacity: 0;\n transform: translateY(10px);\n transition: opacity 0.25s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.2s;\n }\n \n .ev-definition-popup.ev-visible {\n opacity: 1;\n transform: none;\n }\n \n .ev-definition-popup-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 16px;\n background: var(--ev-bg-secondary);\n border-bottom: 1px solid var(--ev-border-color);\n }\n \n .ev-definition-popup-title {\n display: flex;\n align-items: center;\n gap: 8px;\n font-family: 'Inter', sans-serif;\n font-size: 14px;\n font-weight: 600;\n color: #a855f7;\n }\n \n .ev-definition-popup-title svg {\n width: 18px;\n height: 18px;\n }\n \n .ev-definition-popup-close {\n width: 28px;\n height: 28px;\n background: transparent;\n border: 1px solid var(--ev-border-hover);\n border-radius: 6px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s;\n color: var(--ev-text-muted);\n }\n \n .ev-definition-popup-close:hover {\n background: var(--ev-bg-tertiary);\n }\n \n .ev-definition-popup-content {\n padding: 16px;\n max-height: 300px;\n overflow-y: auto;\n }\n \n .ev-def-word-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 12px;\n }\n \n .ev-def-word-title {\n font-family: 'Inter', sans-serif;\n font-size: 20px;\n font-weight: 700;\n color: var(--ev-text-primary);\n text-transform: capitalize;\n }\n \n .ev-def-phonetic {\n font-family: 'Inter', sans-serif;\n font-size: 13px;\n color: var(--ev-text-muted);\n margin-left: 8px;\n font-weight: 400;\n }\n\n .ev-def-actions {\n display: flex !important;\n gap: 6px !important;\n align-items: center !important;\n }\n \n .ev-def-action-btn {\n all: unset !important;\n box-sizing: border-box !important;\n width: 28px !important;\n height: 28px !important;\n background: var(--ev-bg-secondary) !important;\n border: 1.5px solid var(--ev-border-color) !important;\n padding: 0 !important;\n cursor: pointer !important;\n color: var(--ev-text-muted) !important;\n border-radius: 8px !important;\n display: inline-flex !important;\n align-items: center !important;\n justify-content: center !important;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1) !important;\n flex-shrink: 0 !important;\n }\n \n .ev-def-action-btn:hover {\n color: var(--ev-text-primary) !important;\n border-color: var(--ev-border-hover) !important;\n background: var(--ev-bg-tertiary) !important;\n transform: translateY(-1px) !important;\n }\n \n .ev-def-action-btn.active {\n color: #d97706 !important;\n border-color: #f59e0b !important;\n background: rgba(245, 158, 11, 0.15) !important;\n }\n \n .ev-def-action-btn svg {\n width: 15px !important;\n height: 15px !important;\n transition: transform 0.15s ease !important;\n }\n \n .ev-def-meaning-group {\n margin-bottom: 16px;\n }\n \n .ev-def-meaning-group:last-child {\n margin-bottom: 0;\n }\n \n .ev-def-pos {\n font-family: 'Inter', sans-serif;\n font-size: 11px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: #a855f7;\n background: rgba(168, 85, 247, 0.1);\n padding: 2px 6px;\n border-radius: 4px;\n display: inline-block;\n margin-bottom: 8px;\n }\n \n .ev-def-text {\n font-family: 'Inter', sans-serif;\n font-size: 13.5px;\n line-height: 1.6;\n color: var(--ev-text-primary);\n margin-bottom: 6px;\n }\n \n .ev-def-example {\n font-family: 'Inter', sans-serif;\n font-size: 12.5px;\n font-style: italic;\n color: var(--ev-text-secondary);\n border-left: 2px solid var(--ev-border-hover);\n padding-left: 10px;\n margin-left: 4px;\n }\n \n .ev-def-source-badge {\n font-size: 10px;\n color: var(--ev-text-muted);\n background: var(--ev-bg-secondary);\n padding: 2px 6px;\n border-radius: 4px;\n display: inline-block;\n margin-top: 8px;\n }\n\n /* Definition Fallback AI Prompt Styles */\n .ev-def-fallback-container {\n display: flex !important;\n flex-direction: column !important;\n align-items: center !important;\n justify-content: center !important;\n text-align: center !important;\n padding: 20px 10px !important;\n }\n\n .ev-def-fallback-icon {\n width: 48px !important;\n height: 48px !important;\n color: #a855f7 !important;\n background: rgba(168, 85, 247, 0.1) !important;\n border-radius: 50% !important;\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n margin-bottom: 16px !important;\n }\n \n .ev-def-fallback-title {\n font-family: 'Inter', sans-serif !important;\n font-size: 16px !important;\n font-weight: 700 !important;\n color: var(--ev-text-primary) !important;\n margin-bottom: 8px !important;\n }\n \n .ev-def-fallback-desc {\n font-family: 'Inter', sans-serif !important;\n font-size: 12.5px !important;\n color: var(--ev-text-secondary) !important;\n line-height: 1.5 !important;\n margin-bottom: 20px !important;\n }\n \n .ev-def-fallback-btn {\n width: 100% !important;\n padding: 12px !important;\n background: linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%) !important;\n border: none !important;\n border-radius: 10px !important;\n color: white !important;\n font-family: 'Inter', sans-serif !important;\n font-size: 13.5px !important;\n font-weight: 600 !important;\n cursor: pointer !important;\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n gap: 8px !important;\n transition: all 0.25s ease !important;\n box-shadow: 0 4px 12px rgba(99, 102, 241, 0.3) !important;\n }\n \n .ev-def-fallback-btn:hover {\n transform: translateY(-2px) !important;\n box-shadow: 0 6px 16px rgba(99, 102, 241, 0.45) !important;\n filter: brightness(1.1) !important;\n }\n \n .ev-def-fallback-btn svg {\n width: 16px !important;\n height: 16px !important;\n }\n\n /* Definition Category - Flawlessly inherits Jargon Base layout (box style) */\n .ev-jargon-definition {\n border-color: rgba(168, 85, 247, 0.8) !important;\n color: inherit !important;\n }\n ","ev-selection-decoder-styles")}async function defineSelectedText(e,n){const t=e?e.trim().replace(/[.,\/#!$%\^&\*;:{}=\-_`~()?"']/g,""):"",o=t.split(/\s+/).length;if(!t||o>4)return void showNotification("Please select a single word or short phrase to define.","info");showProgressLoader("Looking up definition...","jargon"),updateProgress(20);const i="sel_def_"+hashString(t.toLowerCase()),a=await new Promise(e=>{chrome.storage.local.get(i,n=>e(n[i]||null))});if(a&&Date.now()-a.ts<6048e5)return updateProgress(100),hideProgressLoader(),void await showDefinitionPopup(t,a.data,n);const r=encodeURIComponent(t.toLowerCase());let s=null;try{const e=await fetch(`https://api.dictionaryapi.dev/api/v2/entries/en/${r}`);if(e.ok){const n=await e.json();if(Array.isArray(n)&&n.length>0){const e=n[0];s={word:e.word,phonetic:e.phonetic||e.phonetics&&e.phonetics.find(e=>e.text)?.text||"",audio:e.phonetics&&e.phonetics.find(e=>e.audio&&e.audio.trim())?.audio||null,meanings:e.meanings.map(e=>({partOfSpeech:e.partOfSpeech,definition:e.definitions[0]?.definition||"",example:e.definitions[0]?.example||null})).slice(0,3),source:"Free Dictionary"}}}if(!s){updateProgress(50);const e=await fetch(`https://en.wiktionary.org/api/rest_v1/page/definition/${r}`);if(e.ok){const n=await e.json();n&&n.en&&n.en.length>0&&(s={word:t,phonetic:"",audio:null,meanings:n.en.map(e=>{const n=(e.definitions[0]?.definition||"").replace(/<\/?[^>]+(>|$)/g,"");return{partOfSpeech:e.partOfSpeech,definition:n,example:null}}).slice(0,3),source:"Wiktionary"})}}if(!s)return hideProgressLoader(),void await showDefinitionFallbackPrompt(t,n);chrome.storage.local.set({[i]:{data:s,ts:Date.now()}}),updateProgress(100),hideProgressLoader(),await showDefinitionPopup(t,s,n)}catch(e){hideProgressLoader(),showNotification("Network error looking up definition.","error")}}async function showDefinitionPopup(e,n,t){document.querySelector(".ev-definition-popup")?.remove();const o=e.toLowerCase().trim();let i=!1;try{const e=await chrome.storage.local.get(["savedVocabulary"]);i=(e.savedVocabulary||[]).some(e=>e.termKey===o)}catch(e){}const a=t.getBoundingClientRect(),r=document.createElement("div");r.className="ev-definition-popup";const s=n.meanings.map(e=>`\n <div class="ev-def-meaning-group">\n <span class="ev-def-pos">${escapeHtml(e.partOfSpeech)}</span>\n <div class="ev-def-text">${escapeHtml(e.definition)}</div>\n ${e.example?`<div class="ev-def-example">"${escapeHtml(e.example)}"</div>`:""}\n </div>\n `).join("");r.innerHTML=`\n <div class="ev-definition-popup-header ev-draggable-header">\n <span class="ev-definition-popup-title">\n <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">\n <circle cx="12" cy="12" r="10"></circle>\n <line x1="12" y1="16" x2="12" y2="12"></line>\n <line x1="12" y1="8" x2="12.01" y2="8"></line>\n </svg>\n Quick Dictionary\n <span class="ev-drag-hint">⋮⋮</span>\n </span>\n <button class="ev-definition-popup-close">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <line x1="18" y1="6" x2="6" y2="18"/>\n <line x1="6" y1="6" x2="18" y2="18"/>\n </svg>\n </button>\n </div>\n <div class="ev-definition-popup-content">\n <div class="ev-def-word-header">\n <div>\n <span class="ev-def-word-title">${escapeHtml(n.word)}</span>\n ${n.phonetic?`<span class="ev-def-phonetic">${escapeHtml(n.phonetic)}</span>`:""}\n </div>\n <div class="ev-def-actions">\n <button class="ev-def-action-btn ev-def-audio-btn" title="Listen">\n <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\n <polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"></polygon>\n <path d="M19.07 4.93a10 10 0 0 1 0 14.14M15.54 8.46a5 5 0 0 1 0 7.07"></path>\n </svg>\n </button>\n <button class="ev-def-action-btn ev-def-bookmark-btn ${i?"active":""}" title="Save to Notebook">\n <svg viewBox="0 0 24 24" fill="${i?"currentColor":"none"}" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round">\n <path d="M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"></path>\n </svg>\n </button>\n </div>\n </div>\n <div class="ev-def-meanings">\n ${s}\n </div>\n <div class="ev-def-source-badge">via ${n.source}</div>\n </div>\n `;let l=a.left+a.width/2-170,c=a.bottom+15+window.scrollY;l=Math.max(10,Math.min(l,window.innerWidth-350)),r.style.left=`${l}px`,r.style.top=`${c}px`,document.body.appendChild(r),makeDraggable(r,".ev-definition-popup-header"),requestAnimationFrame(()=>{r.classList.add("ev-visible");try{const o=n.meanings[0]?.definition||"Word definition loaded.";applyJargonToSelection([{jargon:e.trim(),simple:o,explanation:`Source: ${n.source}`,category:"definition",difficulty:2}],t)}catch(e){}});const d=r.querySelector(".ev-def-audio-btn");function p(e){try{if("speechSynthesis"in window){window.speechSynthesis.cancel();const n=new SpeechSynthesisUtterance(e);n.rate=.9,window.speechSynthesis.speak(n)}}catch(e){}}d&&d.addEventListener("click",()=>{if(n.audio){new Audio(n.audio).play().catch(e=>{p(n.word)})}else p(n.word);d.style.transform="scale(1.2) translateY(-1px)",setTimeout(()=>d.style.transform="",150)});const m=r.querySelector(".ev-def-bookmark-btn");m.addEventListener("click",async t=>{t.stopPropagation();const i=(await chrome.storage.local.get(["savedVocabulary"])).savedVocabulary||[];let a,r;if(i.some(e=>e.termKey===o))a=i.filter(e=>e.termKey!==o),r=!1;else{const t=n.meanings[0];a=[{termKey:o,jargon:e.trim(),simple:t.definition.trim(),explanation:t.example?`Example: ${t.example}`:`Part of speech: ${t.partOfSpeech}`,category:"dictionary",timestamp:Date.now()},...i],r=!0}await chrome.storage.local.set({savedVocabulary:a}),m.classList.toggle("active",r);const s=m.querySelector("svg");s&&s.setAttribute("fill",r?"currentColor":"none"),m.style.transform="scale(1.2)",setTimeout(()=>m.style.transform="",150),showNotification(r?"Saved to Notebook!":"Removed from Notebook","success")}),r.querySelector(".ev-definition-popup-close").addEventListener("click",()=>{r.classList.remove("ev-visible"),setTimeout(()=>r.remove(),200)}),setTimeout(()=>{document.body.contains(r)&&(r.classList.remove("ev-visible"),setTimeout(()=>r.remove(),200))},3e4)}async function showDefinitionFallbackPrompt(e,n){document.querySelector(".ev-definition-popup")?.remove();const t=n.getBoundingClientRect(),o=document.createElement("div");o.className="ev-definition-popup",o.innerHTML=`\n <div class="ev-definition-popup-header ev-draggable-header">\n <span class="ev-definition-popup-title">\n <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">\n <circle cx="12" cy="12" r="10"></circle>\n <line x1="12" y1="16" x2="12" y2="12"></line>\n <line x1="12" y1="8" x2="12.01" y2="8"></line>\n </svg>\n Quick Dictionary\n <span class="ev-drag-hint">⋮⋮</span>\n </span>\n <button class="ev-definition-popup-close">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <line x1="18" y1="6" x2="6" y2="18"/>\n <line x1="6" y1="6" x2="18" y2="18"/>\n </svg>\n </button>\n </div>\n <div class="ev-definition-popup-content ev-def-fallback-container">\n <div class="ev-def-fallback-icon">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">\n <circle cx="11" cy="11" r="8"></circle>\n <line x1="21" y1="21" x2="16.65" y2="16.65"></line>\n <line x1="11" y1="8" x2="11" y2="14"></line>\n <line x1="8" y1="11" x2="14" y2="11"></line>\n </svg>\n </div>\n <div class="ev-def-fallback-title">Word Not Found</div>\n <div class="ev-def-fallback-desc">\n We couldn't find "${escapeHtml(e)}" in the basic dictionary. It might be modern slang, an abbreviation, or highly technical jargon.\n </div>\n <button class="ev-def-fallback-btn" id="ev-fallback-ai-btn">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">\n <path d="m12 3-1.912 5.813a2 2 0 0 1-1.275 1.275L3 12l5.813 1.912a2 2 0 0 1 1.275 1.275L12 21l1.912-5.813a2 2 0 0 1 1.275-1.275L21 12l-5.813-1.912a2 2 0 0 1-1.275-1.275L12 3Z"/>\n <path d="m5 3 1 2.5L8.5 6 6 7 5 9.5 4 7 1.5 6 4 5.5 5 3Z"/>\n <path d="m19 17 1 2.5 2.5.5-2.5 1-1 2.5-1-2.5-2.5-1 2.5-.5 1-2.5Z"/>\n </svg>\n <span>Decode with Evie AI</span>\n </button>\n </div>\n `;let i=t.left+t.width/2-170,a=t.bottom+15+window.scrollY;i=Math.max(10,Math.min(i,window.innerWidth-350)),o.style.left=`${i}px`,o.style.top=`${a}px`,document.body.appendChild(o),makeDraggable(o,".ev-definition-popup-header"),requestAnimationFrame(()=>{o.classList.add("ev-visible")});const r=o.querySelector("#ev-fallback-ai-btn");r&&r.addEventListener("click",async()=>{o.classList.remove("ev-visible"),setTimeout(()=>o.remove(),200),await decodeSelectedText(e,n)}),o.querySelector(".ev-definition-popup-close").addEventListener("click",()=>{o.classList.remove("ev-visible"),setTimeout(()=>o.remove(),200)})}function showProgressLoader(e="Processing...",n="jargon"){hideProgressLoader();const t=document.createElement("div");t.className="ev-progress-overlay",t.innerHTML='\n <div class="loader-wrapper">\n <span class="loader-letter">G</span>\n <span class="loader-letter">e</span>\n <span class="loader-letter">n</span>\n <span class="loader-letter">e</span>\n <span class="loader-letter">r</span>\n <span class="loader-letter">a</span>\n <span class="loader-letter">t</span>\n <span class="loader-letter">i</span>\n <span class="loader-letter">n</span>\n <span class="loader-letter">g</span>\n <div class="loader"></div>\n </div>\n <button class="ev-stop-button" id="ev-stop-generation">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">\n <rect x="6" y="6" width="12" height="12" rx="2"/>\n </svg>\n <span>Stop</span>\n </button>\n ';injectCSS("\n .ev-progress-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: var(--ev-overlay-bg);\n backdrop-filter: blur(10px);\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 28px;\n z-index: 10000000;\n animation: ev-overlay-in 0.4s ease-out;\n }\n \n @keyframes ev-overlay-in {\n from { opacity: 0; }\n to { opacity: 1; }\n }\n \n .loader-wrapper {\n position: relative;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 180px;\n height: 180px;\n font-family: \"Inter\", sans-serif;\n font-size: 1.2em;\n font-weight: 300;\n color: var(--ev-text-primary);\n border-radius: 50%;\n background-color: transparent;\n user-select: none;\n }\n \n .loader {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n aspect-ratio: 1 / 1;\n border-radius: 50%;\n background-color: transparent;\n animation: loader-rotate 2s linear infinite;\n z-index: 0;\n }\n \n @keyframes loader-rotate {\n 0% {\n transform: rotate(90deg);\n box-shadow:\n 0 10px 20px 0 #fff inset,\n 0 20px 30px 0 #ad5fff inset,\n 0 60px 60px 0 #471eec inset;\n }\n 50% {\n transform: rotate(270deg);\n box-shadow:\n 0 10px 20px 0 #fff inset,\n 0 20px 10px 0 #d60a47 inset,\n 0 40px 60px 0 #311e80 inset;\n }\n 100% {\n transform: rotate(450deg);\n box-shadow:\n 0 10px 20px 0 #fff inset,\n 0 20px 30px 0 #ad5fff inset,\n 0 60px 60px 0 #471eec inset;\n }\n }\n \n .loader-letter {\n display: inline-block;\n opacity: 0.4;\n transform: translateY(0);\n animation: loader-letter-anim 2s infinite;\n z-index: 1;\n border-radius: 50ch;\n border: none;\n }\n \n .loader-letter:nth-child(1) { animation-delay: 0s; }\n .loader-letter:nth-child(2) { animation-delay: 0.1s; }\n .loader-letter:nth-child(3) { animation-delay: 0.2s; }\n .loader-letter:nth-child(4) { animation-delay: 0.3s; }\n .loader-letter:nth-child(5) { animation-delay: 0.4s; }\n .loader-letter:nth-child(6) { animation-delay: 0.5s; }\n .loader-letter:nth-child(7) { animation-delay: 0.6s; }\n .loader-letter:nth-child(8) { animation-delay: 0.7s; }\n .loader-letter:nth-child(9) { animation-delay: 0.8s; }\n .loader-letter:nth-child(10) { animation-delay: 0.9s; }\n \n @keyframes loader-letter-anim {\n 0%, 100% {\n opacity: 0.4;\n transform: translateY(0);\n }\n 20% {\n opacity: 1;\n transform: scale(1.15);\n }\n 40% {\n opacity: 0.7;\n transform: translateY(0);\n }\n }\n \n .ev-loader-status {\n font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;\n font-size: 14px;\n font-weight: 400;\n color: var(--ev-text-secondary);\n letter-spacing: 0.3px;\n text-align: center;\n }\n \n .ev-stop-button {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px 24px;\n background: rgba(239, 68, 68, 0.1);\n border: 1px solid rgba(239, 68, 68, 0.3);\n border-radius: 12px;\n color: #ef4444;\n font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s ease;\n margin-top: 20px;\n }\n \n .ev-stop-button:hover {\n background: rgba(239, 68, 68, 0.2);\n border-color: rgba(239, 68, 68, 0.5);\n transform: translateY(-1px);\n box-shadow: 0 4px 12px rgba(239, 68, 68, 0.2);\n }\n \n .ev-stop-button:active {\n transform: translateY(0);\n }\n \n .ev-stop-button svg {\n width: 16px;\n height: 16px;\n }\n ","ev-progress-styles"),document.body.appendChild(t);const o=t.querySelector("#ev-stop-generation");o&&o.addEventListener("click",stopGeneration)}function updateProgress(e){}function updateProgressText(e){}function hideProgressLoader(){const e=document.querySelector(".ev-progress-overlay");if(e){e.style.animation="ev-overlay-out 0.3s ease-out forwards";injectCSS("\n @keyframes ev-overlay-out {\n from { opacity: 1; }\n to { opacity: 0; }\n }\n ","ev-progress-out-styles"),setTimeout(()=>{e.remove(),removeCSS("ev-progress-styles"),removeCSS("ev-progress-out-styles")},300)}}function stopGeneration(){state.abortController&&(state.abortController.abort(),state.abortController=null),state.isGenerating=!1,hideProgressLoader(),showNotification("Generation stopped","info")}function showNotification(e,n="info"){const t=document.querySelector(".ev-notification");t&&t.remove();const o={success:'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/></svg>',error:'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="15" y1="9" x2="9" y2="15"/><line x1="9" y1="9" x2="15" y2="15"/></svg>',info:'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg>'},i={success:{bg:"rgba(34, 197, 94, 0.1)",border:"rgba(34, 197, 94, 0.2)",text:"#22c55e"},error:{bg:"rgba(239, 68, 68, 0.1)",border:"rgba(239, 68, 68, 0.2)",text:"#ef4444"},info:{bg:"rgba(250, 250, 250, 0.1)",border:"rgba(250, 250, 250, 0.2)",text:"#fafafa"}},a=i[n]||i.info,r=document.createElement("div");r.className="ev-notification",r.innerHTML=`\n <div class="ev-notification-icon">${o[n]||o.info}</div>\n <span class="ev-notification-text">${e}</span>\n `;injectCSS(`\n .ev-notification {\n position: fixed;\n bottom: 24px;\n right: 24px;\n background: var(--ev-bg-secondary);\n border: 1px solid ${a.border};\n border-radius: 12px;\n padding: 14px 18px;\n display: flex;\n align-items: center;\n gap: 12px;\n box-shadow: var(--ev-shadow-md);\n z-index: 10000001;\n animation: ev-notif-in 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n max-width: 360px;\n }\n \n @keyframes ev-notif-in {\n from {\n opacity: 0;\n transform: translateY(20px) scale(0.95);\n }\n to {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n }\n \n .ev-notification-icon {\n width: 20px;\n height: 20px;\n flex-shrink: 0;\n }\n \n .ev-notification-icon svg {\n width: 100%;\n height: 100%;\n color: ${a.text};\n }\n \n .ev-notification-text {\n font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;\n font-size: 13px;\n font-weight: 500;\n color: ${a.text};\n letter-spacing: -0.2px;\n }\n `,"ev-notification-styles"),document.body.appendChild(r),setTimeout(()=>{r.style.animation="ev-notif-out 0.3s ease-out forwards";injectCSS("\n @keyframes ev-notif-out {\n from { opacity: 1; transform: translateY(0); }\n to { opacity: 0; transform: translateY(10px); }\n }\n ","ev-notification-out-styles"),setTimeout(()=>{r.remove(),removeCSS("ev-notification-styles"),removeCSS("ev-notification-out-styles")},300)},3e3)}function injectCSS(e,n){removeCSS(n);const t=document.createElement("style");t.id=`ev-style-${n}`,t.textContent=e,document.head.appendChild(t)}function removeCSS(e){const n=document.getElementById(`ev-style-${e}`);n&&n.remove()}function escapeHtml(e){if("string"!=typeof e)return"";const n=document.createElement("textarea");n.innerHTML=e;return n.value.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/`/g,"`")}initThemeSystem(),init(),chrome.runtime.onMessage.addListener((e,n,t)=>{if(e&&("APPLY_VISUALS"===e.type||"APPLY_VISUALS"===e.action)&&e.settings)return chrome.storage.sync.get(["enableVisuals"],n=>{!0===n.enableVisuals&&applyVisualAdjustments(e.settings)}),t&&t({success:!0}),!0}),applyAllVisualSettingsFromStorage(),chrome.storage.onChanged.addListener((e,n)=>{"sync"===n&&e.lastVisualSettings&&chrome.storage.sync.get(["enableVisuals"],n=>{!0===n.enableVisuals&&applyVisualAdjustments(e.lastVisualSettings.newValue)}),"sync"===n&&e.enableVisuals&&(!1===e.enableVisuals.newValue?removeVisualAdjustments():applyAllVisualSettingsFromStorage()),"sync"===n&&void 0!==e.isPremium&&(state.isPremium=e.isPremium.newValue,applyAllVisualSettingsFromStorage(),chrome.storage.sync.get(["sensoryEnabled","sensoryMode"],e=>{e.sensoryEnabled&&activateSensoryShield(e.sensoryMode)})),"sync"===n&&e.dyslexiaFont&&(state.dyslexiaSettings.font=e.dyslexiaFont.newValue||"opendyslexic",state.dyslexiaEnabled&&activateDyslexiaMode(state.dyslexiaSettings)),"sync"===n&&e.sensoryMode&&(state.sensoryEnabled||document.getElementById("ev-sensory-overlay"))&&activateSensoryShield(e.sensoryMode.newValue||"freeze")}),chrome.runtime.onMessage.addListener((e,n,t)=>(handleMessage(e).then(t).catch(e=>{t({success:!1,error:e.message})}),!0));const PUBLIC_VERIFICATION_KEY="MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEzxjPpRnw7R/dmWAZ/jVeX3a4tpHX1hl777DQ5IKCAt+sGVjx2pWcZSNQybVkcCRsCTYz8T7A/gYjtgh9bLekEA==";async function verifyHardwareLicense(e,n){if(!e||"string"!=typeof e||!e.includes("."))return!1;try{const[t,o]=e.split("."),i=atob(t),a=JSON.parse(i);if(a.u!==n||!a.p)return!1;if(a.e&&new Date(a.e).getTime()<Date.now())return!1;const r=Uint8Array.from(atob(o),e=>e.charCodeAt(0)),s=(new TextEncoder).encode(i),l=Uint8Array.from(atob(PUBLIC_VERIFICATION_KEY),e=>e.charCodeAt(0)),c=await crypto.subtle.importKey("spki",l,{name:"ECDSA",namedCurve:"P-256"},!1,["verify"]);return await crypto.subtle.verify({name:"ECDSA",hash:{name:"SHA-256"}},c,r,s)}catch(e){return!1}}function detectAnimations(){const e=[];return document.querySelectorAll("*").forEach(n=>{const t=window.getComputedStyle(n);"none"===t.animationName&&"none"===t.transition||e.push(n)}),e}function extractReadableContent(){const e=["main","article",'[role="main"]',".main-content","#content","#main",".content"];let n=null;for(const t of e)if(n=document.querySelector(t),n)break;n||(n=document.body);const t=[],o=document.createTreeWalker(n,NodeFilter.SHOW_TEXT,{acceptNode:e=>{const n=e.parentElement;if(!n)return NodeFilter.FILTER_REJECT;const t=n.tagName.toLowerCase();if(["script","style","noscript","iframe","object"].includes(t))return NodeFilter.FILTER_REJECT;const o=window.getComputedStyle(n);return"none"===o.display||"hidden"===o.visibility?NodeFilter.FILTER_REJECT:e.textContent.trim()?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_REJECT}});let i;for(;i=o.nextNode();)t.push(i.textContent);return t.join(" ").replace(/\s+/g," ").trim()}function showToast(e){const n=document.getElementById("ev-live-toast");n&&n.remove();const t=document.createElement("div");if(t.id="ev-live-toast",t.innerHTML=`\n <div class="ev-toast-icon">✨</div>\n <div class="ev-toast-content">${e}</div>\n `,!document.getElementById("ev-toast-styles")){const e=document.createElement("style");e.id="ev-toast-styles",e.textContent="\n #ev-live-toast {\n position: fixed;\n bottom: 30px;\n right: 30px;\n background: rgba(15, 23, 42, 0.9);\n backdrop-filter: blur(8px);\n color: #fff;\n padding: 12px 20px;\n border-radius: 12px;\n border: 1px solid rgba(255, 255, 255, 0.1);\n box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.3);\n display: flex;\n align-items: center;\n gap: 12px;\n z-index: 2147483647;\n font-family: system-ui, -apple-system, sans-serif;\n font-size: 14px;\n animation: ev-toast-slide-in 0.3s ease-out;\n }\n .ev-toast-icon {\n font-size: 18px;\n }\n @keyframes ev-toast-slide-in {\n from { transform: translateX(100%); opacity: 0; }\n to { transform: translateX(0); opacity: 1; }\n }\n ",document.head.appendChild(e)}document.body.appendChild(t),setTimeout(()=>{t.style.transition="opacity 0.5s ease-out",t.style.opacity="0",setTimeout(()=>t.remove(),500)},5e3)}function escapeRegex(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function hashString(e){let n=0;for(let t=0;t<e.length;t++){n=(n<<5)-n+e.charCodeAt(t),n&=n}return n.toString(36)}const SELECTION_CACHE_TTL=18e5;async function getSelectionCache(e){try{const n=(await chrome.storage.local.get(e))[e];return n&&Date.now()-n.ts<SELECTION_CACHE_TTL?n.data:null}catch{return null}}async function setSelectionCache(e,n){try{const t=await chrome.storage.local.get(null),o=Object.keys(t).filter(e=>e.startsWith("sel_jargon_")||e.startsWith("sel_simplify_")),i=o.filter(e=>Date.now()-(t[e]?.ts||0)>=SELECTION_CACHE_TTL);i.length>0&&await chrome.storage.local.remove(i);const a=o.filter(e=>!i.includes(e));if(a.length>=150){a.sort((e,n)=>(t[e]?.ts||0)-(t[n]?.ts||0));const e=a.slice(0,50);await chrome.storage.local.remove(e)}await chrome.storage.local.set({[e]:{data:n,ts:Date.now()}})}catch{}}