(function(){'use strict';var PROGRESS_KEY='rsc-exercise-hub-v1:'+location.pathname;var STREAK_KEY='rsc-streak-v1';var DAILY_KEY='rsc-daily-v1';var TIME_BY_DIFF={beginner:3,intermediate:5,advanced:7};var DOTS_BY_DIFF={beginner:1,intermediate:2,advanced:3};var XP_BY_DIFF={beginner:10,intermediate:25,advanced:50};function xpWeight(difficulty){return XP_BY_DIFF[String(difficulty||'').toLowerCase()]||10;} var COLLAPSE_DELAY=3400;var SETUP_ERR=/could not find function|object '[^']*' not found/i;var CHECK_SVG='';var STATUS_CONTENT={running:'Checking',pass:CHECK_SVG+'Success!',mismatch:'✗ Not a match',error:'⚠ Error'};var BACKFILL_FLAG_PREFIX='rsc-backfill-done-';var BACKFILL_BATCH_SIZE=200;var LOCALSTORAGE_HUB_PREFIX='rsc-exercise-hub-v1:';var authToken=null;var authedUserId=null;function pad2(n){return(n<10?'0':'')+n;} function escapeHtml(s){return String(s).replace(/[&<>"']/g,function(c){return({'&':'&','<':'<','>':'>','"':'"',"'":'''})[c];});} function todayStr(){return new Date().toISOString().slice(0,10);} function normalizeOutput(text){var t=String(text||'').replace(/×/g,'x').replace(/…/g,'...').replace(/ /g,' ');var rawLines=t.split('\n');var kept=[];var inWarning=false;for(var i=0;i\s?/,'');if(/^(?:Warning message|Warning messages|Warning in\b)/i.test(classifyable)){inWarning=true;continue;} if(inWarning){var preStripped=raw.replace(/^\s*#>\s?/,'');if(/^\s+\S/.test(preStripped)||/^\d+:\s+/.test(classifyable)||trimmed===''){continue;} inWarning=false;} kept.push(raw);} return kept.map(function(l){return l.replace(/^\s*#>\s?/,'').replace(/\s+/g,' ').trim();}).filter(function(l){return l.length;}).join('\n');} function firstDiffLine(a,b){var la=a.split('\n'),lb=b.split('\n');var n=Math.max(la.length,lb.length);for(var i=0;i=totalCount&&badgeEl)showBadge();}}).catch(function(){});} function collectLocalSolves(){var items=[];try{for(var i=0;i'+'

'+bodyText+'

'+'
'+'Create a free account'+ (variant==='win'?'':'I already have an account')+'
';if(variant==='win')card.section.after(el);else card.verdict.after(el);anonCardEl=el;var later=el.querySelector('button.xh-win-later');if(later){later.addEventListener('click',function(){try{sessionStorage.setItem(WIN_DISMISS_KEY,'1');}catch(e){} el.remove();if(anonCardEl===el)anonCardEl=null;gaEvent('win_card_dismiss',{});});} el.querySelector('.xh-win-cta').addEventListener('click',function(){gaEvent(variant==='win'?'win_card_cta':'gate_card_cta',{xp:xp});});try{localStorage.setItem('rs-signin-nudge-dismissed',String(Date.now()+864e5));}catch(e){} if(variant==='gate'){el.scrollIntoView({behavior:'smooth',block:'center'});} gaEvent(variant==='win'?'win_card_shown':'gate_card_shown',{xp:xp,hub:hubSlugFromPath()||''});} var meterState=null;var meterPillEl=null,meterWallEl=null,meterIntroEl=null;var METER_INTRO_KEY='rsc-meter-intro-v1';function meterWalled(){return!!(meterState&&meterState.metered&&meterState.hub_open===false);} function meterFetch(){if(!authToken)return;var hub=hubSlugFromPath();if(!hub)return;fetch('/api/me/meter?hub='+encodeURIComponent(hub),{headers:{'Authorization':'Bearer '+authToken,'Accept':'application/json'}}).then(function(r){return r.ok?r.json():null;}).then(function(body){if(body){meterState=body;meterRender();}}).catch(function(){});} function meterResetLabel(){var iso=meterState&&meterState.resets;if(!iso)return'the 1st';var d=new Date(iso+'T00:00:00Z');var M=['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];return M[d.getUTCMonth()]+' '+d.getUTCDate();} function meterRender(){var s=meterState;if(!s||!s.metered){if(meterPillEl){meterPillEl.remove();meterPillEl=null;} if(meterWallEl){meterWallEl.remove();meterWallEl=null;} document.documentElement.classList.remove('xh-meter-walled');return;} var head=document.querySelector('.xh-map-head');if(head){if(!meterPillEl){meterPillEl=document.createElement('span');head.insertBefore(meterPillEl,head.querySelector('.xh-map-count'));} if(s.hub_started){meterPillEl.className='xh-meter is-open';meterPillEl.innerHTML='This hub stays open until '+meterResetLabel();}else{meterPillEl.className='xh-meter'+(s.left<=5?' is-low':'');var segs='';for(var i=0;i<5;i++){var fill=Math.max(0,Math.min(5,s.left-i*5))/5;segs+='';} meterPillEl.innerHTML=''+''+s.left+' of '+s.limit+' left this month'+'resets '+meterResetLabel()+'';}} meterIntroRender();meterWallRender();} function meterIntroRender(){if(!meterState||!meterState.metered||meterWalled()||meterIntroEl)return;var seen=null;try{seen=localStorage.getItem(METER_INTRO_KEY);}catch(e){} if(seen)return;var anchor=mapEl||document.querySelector('section.exercise');if(!anchor||!anchor.parentElement)return;meterIntroEl=document.createElement('div');meterIntroEl.className='xh-meter-intro';meterIntroEl.innerHTML='
How free practice works'+'

You get 25 graded exercises a month. Any hub you start stays open until '+'the month ends, so you can always finish what you began.

'+'';meterIntroEl.querySelector('.xh-meter-intro-ok').addEventListener('click',function(){try{localStorage.setItem(METER_INTRO_KEY,'1');}catch(e){} meterIntroEl.remove();meterIntroEl=null;});anchor.parentElement.insertBefore(meterIntroEl,anchor);} function meterWallRender(){var walled=meterWalled();document.documentElement.classList.toggle('xh-meter-walled',walled);if(!walled){if(meterWallEl){meterWallEl.remove();meterWallEl=null;} return;} if(meterWallEl)return;var first=document.querySelector('section.exercise');if(!first||!first.parentElement)return;var s=meterState;var open=s.open_hubs||[];var openLine=open.length?'The '+open.length+' hub'+(open.length===1?'':'s')+' you started this month, until '+meterResetLabel():'Your reading position and streak, everywhere';meterWallEl=document.createElement('div');meterWallEl.className='xh-meter-wall';meterWallEl.setAttribute('role','status');meterWallEl.innerHTML='
'+'
That's all '+s.limit+' for this month
'+'
A full month of practice, done.
'+'
'+'
Still open right now
'+'
    '+'
  • '+openLine+'
  • '+'
  • Every lesson and every tutorial, always
  • '+'
  • A fresh '+s.limit+' on '+meterResetLabel()+'
'+''+'
Your streak and XP are safe either way.
'+'
';first.parentElement.insertBefore(meterWallEl,first);} function meterApply(m,card){if(!meterState)meterState={metered:true,resets:'',open_hubs:[]};meterState.metered=true;meterState.limit=m.limit;meterState.left=m.left;meterState.used=m.used;meterState.hub_started=true;meterState.hub_open=true;meterRender();if(m.left<=5&&card&&card.verdict){var vbody=card.verdict.querySelector('.xh-verdict-body');if(vbody&&!vbody.querySelector('.xh-meter-inline')){vbody.insertAdjacentHTML('beforeend',' · '+m.left+' of '+m.limit+' left this month');}}} document.addEventListener('auth-hydrated',onAuthHydrated);function updateStreak(){var s=STORE.loadStreak();var today=todayStr();if(s.lastVisit===today)return s.days||1;if(s.lastVisit){var gap=(new Date(today)-new Date(s.lastVisit))/86400000;s.days=(gap===1)?(s.days+1):1;}else{s.days=1;} s.lastVisit=today;STORE.saveStreak(s);return s.days;} function discoverNext(){var current=location.pathname.split('/').pop();var links=Array.prototype.slice.call(document.querySelectorAll('#nav a, .col-sm-3 a'));for(var i=0;i=0)){for(var j=i+1;j