1(()=>{(function(){"use strict";var a="/api/saved-prompts",_="ai_skills_favorites",g="ai_skills_saved_cache",k=document.body.dataset.stripeEnabled==="true",r=k?10:1/0,e=null,t=new Set,y=!1,x=r,o=r,n=!1,u=!1;function b(){try{return JSON.parse(localStorage.getItem(_)||"[]")}catch{return[]}}function N(e){try{localStorage.setItem(_,JSON.stringify(e))}catch(e){console.error("[SavedPrompts] Failed to save to localStorage:",e)}}function F(){try{var e,t=localStorage.getItem(g);return t?(e=JSON.parse(t),e.timestamp&&Date.now()-e.timestamp<36e5?e:null):null}catch{return null}}function p(e,t,n,s){try{localStorage.setItem(g,JSON.stringify({prompts:e,total:t,remaining:n,isPro:s,timestamp:Date.now()}))}catch(e){console.error("[SavedPrompts] Failed to cache:",e)}}function D(){try{localStorage.removeItem(g)}catch{}}function z(){if(u)return!1;var s=F();return!!(s&&s.prompts)&&(e=s.prompts,n=s.isPro||!1,o=s.remaining,t=new Set(s.prompts.map(function(e){return e.skill_id})),u=!0,document.dispatchEvent(new CustomEvent("savedPrompts:cacheRestored",{detail:{count:s.prompts.length,remaining:s.remaining,isPro:s.isPro}})),!0)}function l(){if(!window.AuthModule||!window.AuthModule.getAccessToken)return null;var e=window.AuthModule.getAccessToken();return e?{Authorization:"Bearer "+e,"Content-Type":"application/json"}:null}function m(){return window.AuthModule&&window.AuthModule.isLoggedIn&&window.AuthModule.isLoggedIn()}async function i(s){s=s||0;var c,d,u,h=l();if(!h)return d=b(),t=new Set(d),o=r-d.length,f([],d.length),{prompts:[],ids:d};try{if(u=await fetch(a,{method:"GET",headers:h}),u.status===401&&s<1&&(console.log("[SavedPrompts] Token expired, attempting refresh..."),window.AuthModule&&window.AuthModule.refreshSession))try{return await window.AuthModule.refreshSession(),i(s+1)}catch(e){console.error("[SavedPrompts] Session refresh failed:",e)}if(!u.ok)throw new Error("Failed to fetch saved skills");return c=await u.json(),e=c.prompts||[],n=c.is_pro||!1,x=c.limit,o=c.remaining,t=new Set(e.map(function(e){return e.skill_id})),p(e,c.total,c.remaining,n),f(e,c.total,c.remaining,n),{prompts:e,ids:Array.from(t),total:c.total,remaining:c.remaining,isPro:n}}catch(e){return console.error("[SavedPrompts] Fetch error:",e),d=b(),t=new Set(d),f([],d.length),{prompts:[],ids:d}}}function f(e,t,n,s){document.dispatchEvent(new CustomEvent("savedPrompts:loaded",{detail:{prompts:e,count:e.length,total:t,remaining:n,isPro:s}}))}
1async function w(s){if(!m())return window.AuthModule&&window.AuthModule.openAuthModal&&(window.AuthModule.openAuthModal(),window.AuthModule.showToast&&window.AuthModule.showToast("Sign in to save skills to your account","info")),{success:!1,error:"LOGIN_REQUIRED"};var i,r,c=l();if(!c)return{success:!1,error:"NOT_AUTHENTICATED"};try{if(r=await fetch(a,{method:"POST",headers:c,body:JSON.stringify(s)}),i=await r.json(),!r.ok){if(i.code==="LIMIT_REACHED")A();else if(i.code==="ALREADY_SAVED")return t.add(s.skill_id),{success:!0,alreadySaved:!0};return{success:!1,error:i.code,message:i.error}}return e&&(e.unshift(i.saved),p(e,e.length,i.remaining,n)),t.add(s.skill_id),o=i.remaining,d(e?e.length:t.size),{success:!0,saved:i.saved,remaining:i.remaining}}catch(e){return console.error("[SavedPrompts] Save error:",e),{success:!1,error:"NETWORK_ERROR"}}}async function O(s){if(!m())return window.AuthModule&&window.AuthModule.openAuthModal&&window.AuthModule.openAuthModal(),{success:!1,error:"LOGIN_REQUIRED"};var i,r,u,h,f,c=l();if(!c)return{success:!1,error:"NOT_AUTHENTICATED"};if(r=e&&e.find(function(e){return e.skill_id===s}),!r)try{if(f=await fetch(a+"/check?skill_id="+encodeURIComponent(s),{method:"GET",headers:c}),u=await f.json(),!u.is_saved)return t.delete(s),{success:!0};r={id:u.saved_prompt_id}}catch(e){return console.error("[SavedPrompts] Check error:",e),{success:!1,error:"NETWORK_ERROR"}}try{return h=await fetch(a+"/"+r.id,{method:"DELETE",headers:c}),i=await h.json(),h.ok?(e&&(e=e.filter(function(e){return e.skill_id!==s}),p(e,e.length,i.remaining,n)),t.delete(s),o=i.remaining,d(e?e.length:t.size),{success:!0,remaining:i.remaining}):{success:!1,error:i.code}}catch(e){return console.error("[SavedPrompts] Unsave error:",e),{success:!1,error:"NETWORK_ERROR"}}}async function E(e){if(!m()){var t,n,o,i=b(),s={};return e.forEach(function(e){i.indexOf(e)>-1&&(s[e]={saved_prompt_id:null,saved_at:null})}),s}if(t=l(),!t)return{};
1try{if(n=await fetch(a+"/bulk-check",{method:"POST",headers:t,body:JSON.stringify({skill_ids:e})}),!n.ok)throw new Error("Bulk check failed");return o=await n.json(),o.saved||{}}catch(e){return console.error("[SavedPrompts] Bulk check error:",e),{}}}function j(e){return t.has(e)}function c(e,t){t?(e.classList.add("saved"),e.setAttribute("aria-label","Remove from saved"),e.setAttribute("data-saved","true")):(e.classList.remove("saved"),e.setAttribute("aria-label","Save skill"),e.removeAttribute("data-saved"));var n=e.querySelector(".icon-bookmark-outline"),s=e.querySelector(".icon-bookmark-filled");n&&s&&(n.style.display=t?"none":"block",s.style.display=t?"block":"none")}function s(){var e=document.querySelectorAll(".btn-save, .btn-favorite");e.forEach(function(e){var t=e.dataset.skillId;t&&c(e,j(t))})}function A(){window.AuthModule&&window.AuthModule.showToast&&window.AuthModule.showToast("You've reached the free limit of "+r+" saved skills. Upgrade to Pro for unlimited saves!","warning"),document.dispatchEvent(new CustomEvent("savedPrompts:limitReached",{detail:{limit:r}}))}function S(){window.AuthModule&&window.AuthModule.showToast&&window.AuthModule.showToast("Skill saved!","success")}function M(){window.AuthModule&&window.AuthModule.showToast&&window.AuthModule.showToast("Skill removed from saved","info")}function h(e){var t=document.querySelectorAll("[data-saved-count]");t.forEach(function(t){var n=parseInt(t.textContent)||0,s=Math.max(0,n+e);t.textContent=s})}async function T(e){var s,o,i,a,r,l,n=e.target.closest(".btn-save, .btn-favorite");if(!n)return;if(s=n.dataset.skillId,!s)return;if(e.preventDefault(),e.stopPropagation(),!m()){window.AuthModule&&window.AuthModule.openAuthModal&&(window.AuthModule.openAuthModal(),window.AuthModule.showToast&&window.AuthModule.showToast("Sign in to save skills to your account","info"));return}if(i=j(s),c(n,!i),i?(t.delete(s),h(-1)):(t.add(s),h(1)),n.classList.add("animate-bounce"),setTimeout(function(){n.classList.remove("animate-bounce")},500),i)o=await O(s),o.success?(M(),C("unsave_prompt",{skill_id:s})):o.error!=="LOGIN_REQUIRED"&&(c(n,!0),t.add(s),h(1),window.AuthModule&&window.AuthModule.showToast&&window.AuthModule.showToast("Failed to remove skill","error"));else{a=[];try{r=n.dataset.skillRelatedSkills,r&&(a=JSON.parse(r))}catch(e){console.warn("[SavedPrompts] Failed to parse related_skills:",e)}l={skill_id:s,skill_slug:n.dataset.skillSlug||"",skill_title:n.dataset.skillTitle||"",skill_category:n.dataset.skillCategory||null,skill_description:n.dataset.skillDescription||null,skill_difficulty:n.dataset.skillDifficulty||"beginner",skill_time:n.dataset.skillTime||null,skill_verified:n.dataset.skillVerified==="true",skill_premium:n.dataset.skillPremium==="true",skill_related_skills:a},o=await w(l),o.success?(o.alreadySaved||S(),C("save_prompt",{skill_id:s})):o.error!=="LOGIN_REQUIRED"&&(c(n,!1),t.delete(s),h(-1),window.AuthModule&&window.AuthModule.showToast&&window.AuthModule.showToast("Failed to save skill","error"))}}function C(e,t){typeof gtag!="undefined"&>ag("event",e,{event_category:"engagement",...t}),window.location.hostname==="localhost"&&console.log("[SavedPrompts] Track:",e,t)}async function v(){if(y)return;var n=z();n&&(s(),d(e.length)),await i(),s(),document.addEventListener("click",T),document.addEventListener("auth:login",async function(){e=null,t.clear(),u=!1,await i(),s()}),document.addEventListener("auth:logout",async function(){e=null,t.clear(),u=!1,D(),await i(),s(),d(0)}),document.addEventListener("auth:ready",async function(){e=null,t.clear(),await i(),s()}),y=!0}function d(e){var t=document.querySelectorAll("[data-saved-count]");t.forEach(function(t){t.textContent=e})}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",v):v(),window.SavedPromptsModule={init:v,save:w,unsave:O,isSaved:j,getSavedPrompts:function(){return e||[]},getSavedIds:function(){return Array.from(t)},getRemaining:function(){return o},getLimit:function(){return x},isPro:function(){return n},refresh:async function(){e=null,await i(),s()},bulkCheck:E,syncButtons:s}})()})()
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.