(()=>{if(window.__EXAMSFIT_APP_LOADED)return;window.__EXAMSFIT_APP_LOADED=true;
 const base=(window.EF_BASE||'').replace(/\/$/,'');const root=document.documentElement;
 let prefs={};try{prefs=JSON.parse(localStorage.getItem('ef-prefs')||'{}')}catch{}
 delete prefs.contrast;delete prefs.focus;delete prefs.line;delete prefs.width;
 root.dataset.theme=prefs.theme||'light';root.dataset.contrast='';root.dataset.focus='';root.style.setProperty('--fs',(prefs.font||17)+'px');root.style.setProperty('--lh',1.65);root.style.setProperty('--measure','780px');
 const savePrefs=()=>localStorage.setItem('ef-prefs',JSON.stringify(prefs));
 savePrefs();
 document.querySelector('[data-theme]')?.addEventListener('click',()=>{const modes=['light','dark','sepia'];prefs.theme=modes[(modes.indexOf(root.dataset.theme)+1)%modes.length];root.dataset.theme=prefs.theme;savePrefs()});
 document.querySelectorAll('[data-font]').forEach(button=>button.addEventListener('click',()=>{prefs.font=Math.max(14,Math.min(24,(prefs.font||17)+(button.dataset.font==='up'?1:-1)));root.style.setProperty('--fs',prefs.font+'px');savePrefs()}));
 const prose=document.querySelector('.prose');
 if(prose){
  const headings=[...prose.querySelectorAll('h2,h3')];if(headings.length){const toc=document.createElement('nav');toc.className='toc';toc.setAttribute('aria-label','Table of contents');toc.innerHTML='<strong>On this page</strong><ol>'+headings.map((h,i)=>{h.id=h.id||'section-'+(i+1);return`<li><a href="#${h.id}">${escapeHtml(h.textContent)}</a></li>`}).join('')+'</ol>';prose.before(toc)}
  const words=prose.innerText.trim().split(/\s+/).filter(Boolean).length;document.querySelector('.byline')?.insertAdjacentHTML('beforeend',` · ${Math.max(1,Math.ceil(words/225))} min read`);
  const bar=document.createElement('div');bar.className='reading-progress';document.body.prepend(bar);addEventListener('scroll',()=>bar.style.width=Math.min(100,scrollY/Math.max(1,document.documentElement.scrollHeight-innerHeight)*100)+'%',{passive:true});
 }
 if('serviceWorker'in navigator)navigator.serviceWorker.register(base+'/service-worker.js',{scope:base+'/'}).then(reg=>reg.addEventListener('updatefound',()=>{const notice=document.createElement('button');notice.className='update';notice.textContent='Update available — reload';notice.addEventListener('click',()=>location.reload());document.body.append(notice)})).catch(()=>{});
 let installPrompt;addEventListener('beforeinstallprompt',event=>{event.preventDefault();installPrompt=event;const button=document.createElement('button');button.className='install-pwa';button.textContent='Install Exams.fit';button.addEventListener('click',()=>installPrompt.prompt());document.body.append(button)});
 const endpoint=base+'/api/analytics';const session=sessionStorage.getItem('ef-session')||(crypto.randomUUID?.()||Math.random().toString(36));sessionStorage.setItem('ef-session',session);
 function track(event,value=1,label=''){fetch(endpoint,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({event,path:location.pathname,value,label,session,device:innerWidth<768?'mobile':'desktop',browser:navigator.userAgent.slice(0,40),referrer:document.referrer}),keepalive:true}).catch(()=>{})}window.examfitTrack=track;track('pageview');
 let maxScroll=0;addEventListener('scroll',()=>maxScroll=Math.max(maxScroll,Math.round((scrollY+innerHeight)/Math.max(1,document.documentElement.scrollHeight)*100)),{passive:true});const started=Date.now();addEventListener('pagehide',()=>{track('engaged_time',Math.min(86400,Math.round((Date.now()-started)/1000)));track('scroll_depth',maxScroll)});
 document.querySelectorAll('[data-event]').forEach(node=>node.addEventListener('click',()=>track(node.dataset.event)));
 document.querySelector('[data-report]')?.addEventListener('submit',async event=>{event.preventDefault();const form=event.currentTarget,status=form.querySelector('[role=status]'),button=form.querySelector('button');button.disabled=true;status.textContent='Sending…';try{const response=await fetch(base+'/api/report',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({slug:form.dataset.slug,kind:form.kind.value,message:form.message.value,csrf:window.EF_CSRF})});if(!response.ok)throw Error(response.status===429?'Please wait before sending another report.':'Please check the details and try again.');form.reset();status.textContent='Thank you. The report is in the editorial review queue.';track('correction_report')}catch(error){status.textContent=error.message}finally{button.disabled=false}});
 function escapeHtml(value){const node=document.createElement('div');node.textContent=String(value??'');return node.innerHTML}
})();
