diff --git a/includes/functions/users/_user_data.php b/includes/functions/users/_user_data.php
index 93d477c2..893e509e 100644
--- a/includes/functions/users/_user_data.php
+++ b/includes/functions/users/_user_data.php
@@ -15,11 +15,8 @@ function fictioneer_after_logout_cleanup() {
{e.addEventListener("click",(e=>{fcn_purgeSchema(e.currentTarget.dataset.id)}))})),_$$(".button-delete-epub").forEach((e=>{e.addEventListener("click",(e=>{fcn_delete_epub(e.target.dataset.filename,e.target.dataset.id)}))})),(button=_$$$("fictioneer-button-og-upload"))&&button.addEventListener("click",fcn_ogMediaUpload),(button=_$$$("fictioneer-seo-title"))&&(fcn_update_seo_title_chars(),button.addEventListener("keyup",fcn_update_seo_title_chars)),(button=_$$$("fictioneer-button-seo-og-image-remove"))&&button.addEventListener("click",fcn_remove_seo_og_image),_$$(".confirm-dialog").forEach((e=>{e.addEventListener("click",(e=>{fcn_confirmIt(e)}))})),_$("#wp-admin-bar-logout a")?.addEventListener("click",(()=>{localStorage.removeItem("fcnProfileAvatar"),localStorage.removeItem("fcnUserData"),localStorage.removeItem("fcnLoginState"),localStorage.removeItem("fcnNonce"),localStorage.removeItem("fcnBookshelfContent"),localStorage.removeItem("fcnChapterBookmarks")})),_$(".fictioneer-settings")?.addEventListener("click",(e=>{const t=e.target.closest("[data-click]"),o=t?.dataset.click;if(o)switch(o){case"purge-all-epubs":case"purge-all-schemas":case"purge-all-meta":case"reset-post-relationship-registry":confirm(t.dataset.prompt)||e.preventDefault()}})),_$$("button[data-dialog-target]").forEach((e=>{e.addEventListener("click",(e=>{_$$$(e.currentTarget.dataset.dialogTarget)?.showModal()}))})),_$$('button[formmethod="dialog"][value="cancel"]').forEach((e=>{e.addEventListener("click",(e=>{e.preventDefault(),e.currentTarget.closest("dialog").close()}))}));
\ No newline at end of file
+function fcn_purgeSchema(e){jQuery.ajax({url:fictioneer_ajax.ajax_url,type:"post",data:{action:"fictioneer_ajax_purge_schema",nonce:document.getElementById("fictioneer_admin_nonce").value,id:e},dataType:"json",success:function(t){if(t.success){const t=_$$$(`schema-${e}`);t.querySelector(".text-blob").innerHTML=t.querySelector("summary").innerHTML,t.querySelector(".delete").remove(),t.querySelector(".no-schema-note").classList.remove("hidden")}}})}function fcn_delete_epub(e,t){jQuery.ajax({url:fictioneer_ajax.ajax_url,type:"post",data:{action:"fictioneer_ajax_delete_epub",nonce:document.getElementById("fictioneer_admin_nonce").value,name:e},dataType:"json",success:function(e){e.success&&document.getElementById(`epub-id-${t}`).remove()}})}function fcn_ogMediaUpload(e){e.preventDefault();var t=wp.media({multiple:!1,library:{type:"image"}}).open().on("select",(function(){const e=t.state().get("selection").first().toJSON();_$$$("fictioneer-seo-og-image").value=e.id,_$$$("fictioneer-seo-og-display").setAttribute("src",e.url),_$$$("fictioneer-button-seo-og-image-remove").classList.remove("hidden"),_$(".og-source").classList.add("hidden")}))}function fcn_update_seo_title_chars(){const e=_$$$("fictioneer-seo-title");"{{title}} – {{site}}"!=e.value?_$$$("fictioneer-seo-title-chars").innerHTML=`(${e.value.length}/70)`:_$$$("fictioneer-seo-title-chars").innerHTML=""}function fcn_remove_seo_og_image(e){e.preventDefault();const t=_$$$("fictioneer-seo-og-display").dataset.placeholder;_$$$("fictioneer-seo-og-image").value="",_$$$("fictioneer-seo-og-display").setAttribute("src",t),_$$$("fictioneer-button-seo-og-image-remove").classList.add("hidden")}function fcn_confirmIt(e){const t=e.currentTarget.dataset.dialogMessage,o=e.currentTarget.dataset.dialogConfirm;if(!t||!o)return;const a=prompt(t);a?a.toLowerCase()!=o.toLowerCase()&&e.preventDefault():e.preventDefault()}_$$(".button-purge-schema").forEach((e=>{e.addEventListener("click",(e=>{fcn_purgeSchema(e.currentTarget.dataset.id)}))})),_$$(".button-delete-epub").forEach((e=>{e.addEventListener("click",(e=>{fcn_delete_epub(e.target.dataset.filename,e.target.dataset.id)}))})),(button=_$$$("fictioneer-button-og-upload"))&&button.addEventListener("click",fcn_ogMediaUpload),(button=_$$$("fictioneer-seo-title"))&&(fcn_update_seo_title_chars(),button.addEventListener("keyup",fcn_update_seo_title_chars)),(button=_$$$("fictioneer-button-seo-og-image-remove"))&&button.addEventListener("click",fcn_remove_seo_og_image),_$$(".confirm-dialog").forEach((e=>{e.addEventListener("click",(e=>{fcn_confirmIt(e)}))})),_$("#wp-admin-bar-logout a")?.addEventListener("click",(()=>{localStorage.removeItem("fcnProfileAvatar"),localStorage.removeItem("fcnUserData"),localStorage.removeItem("fcnAuth"),localStorage.removeItem("fcnBookshelfContent"),localStorage.removeItem("fcnChapterBookmarks")})),_$(".fictioneer-settings")?.addEventListener("click",(e=>{const t=e.target.closest("[data-click]"),o=t?.dataset.click;if(o)switch(o){case"purge-all-epubs":case"purge-all-schemas":case"purge-all-meta":case"reset-post-relationship-registry":confirm(t.dataset.prompt)||e.preventDefault()}})),_$$("button[data-dialog-target]").forEach((e=>{e.addEventListener("click",(e=>{_$$$(e.currentTarget.dataset.dialogTarget)?.showModal()}))})),_$$('button[formmethod="dialog"][value="cancel"]').forEach((e=>{e.addEventListener("click",(e=>{e.preventDefault(),e.currentTarget.closest("dialog").close()}))}));
\ No newline at end of file
diff --git a/js/ajax-bookshelf.min.js b/js/ajax-bookshelf.min.js
index a7581da5..42271c26 100644
--- a/js/ajax-bookshelf.min.js
+++ b/js/ajax-bookshelf.min.js
@@ -1 +1 @@
-const fcn_bookshelfTarget=_$$$("ajax-bookshelf-target");function fcn_getBookshelfContent(){const e=localStorage.getItem("fcnBookshelfContent");return e&&fcn_isValidJSONString(e)?JSON.parse(e):{html:{},count:{}}}function fcn_updateBookshelfView(e=null,t=null,o=null,n=!1){let a=fcn_getBookshelfContent();const s=(e=e??fcn_bookshelfTarget.dataset.action)+(t=t??fcn_bookshelfTarget.dataset.page)+(o=o??fcn_bookshelfTarget.dataset.order);if(!a.hasOwnProperty("timestamp")||a.timestamp+6e4
{o.success?(s.timestamp=Date.now(),s.html[a]=o.data.html,s.count[e]=o.data.count,localStorage.setItem("fcnBookshelfContent",JSON.stringify(s)),fcn_bookshelfTarget.innerHTML=o.data.html,fcn_bookshelfTarget.dataset.page=t,_$(".item-number").innerHTML=`(${o.data.count})`):(fcn_bookshelfTarget.innerHTML="",fcn_bookshelfTarget.appendChild(fcn_buildErrorNotice(o.data.error)))})).catch((e=>{_$(".item-number").innerHTML="",fcn_bookshelfTarget.innerHTML="",fcn_bookshelfTarget.appendChild(fcn_buildErrorNotice(`${e.status}: ${e.statusText}`))})).then((()=>{fcn_bookshelfTarget.classList.remove("ajax-in-progress"),n&&_$$$("main").scrollIntoView({behavior:"smooth"})}))}fcn_theRoot.dataset.ajaxNonce&&!_$$$("fictioneer-ajax-nonce")?fcn_theRoot.addEventListener("nonceReady",(()=>{fcn_updateBookshelfView()})):fcn_updateBookshelfView(),_$(".bookshelf__list")?.addEventListener("click",(e=>{const t=e.target.closest(".page-numbers[data-page]");t&&fcn_browseBookshelfPage(t.dataset.page)}));
\ No newline at end of file
+const fcn_bookshelfTarget=_$$$("ajax-bookshelf-target");function fcn_getBookshelfContent(){return fcn_parseJSON(localStorage.getItem("fcnBookshelfContent"))??{html:{},count:{}}}function fcn_updateBookshelfView(e=null,t=null,o=null,n=!1){let a=fcn_getBookshelfContent();const s=(e=e??fcn_bookshelfTarget.dataset.action)+(t=t??fcn_bookshelfTarget.dataset.page)+(o=o??fcn_bookshelfTarget.dataset.order);if(!a.hasOwnProperty("timestamp")||a.timestamp+6e4{o.success?(s.timestamp=Date.now(),s.html[a]=o.data.html,s.count[e]=o.data.count,localStorage.setItem("fcnBookshelfContent",JSON.stringify(s)),fcn_bookshelfTarget.innerHTML=o.data.html,fcn_bookshelfTarget.dataset.page=t,_$(".item-number").innerHTML=`(${o.data.count})`):(fcn_bookshelfTarget.innerHTML="",fcn_bookshelfTarget.appendChild(fcn_buildErrorNotice(o.data.error)))})).catch((e=>{_$(".item-number").innerHTML="",fcn_bookshelfTarget.innerHTML="",fcn_bookshelfTarget.appendChild(fcn_buildErrorNotice(`${e.status}: ${e.statusText}`))})).then((()=>{fcn_bookshelfTarget.classList.remove("ajax-in-progress"),n&&_$$$("main").scrollIntoView({behavior:"smooth"})}))}fcn_theRoot.dataset.ajaxNonce?document.addEventListener("fcnAuthReady",(()=>{fcn_updateBookshelfView()})):fcn_updateBookshelfView(),_$(".bookshelf__list")?.addEventListener("click",(e=>{const t=e.target.closest(".page-numbers[data-page]");t&&fcn_browseBookshelfPage(t.dataset.page)}));
\ No newline at end of file
diff --git a/js/ajax-comments.min.js b/js/ajax-comments.min.js
index 903d90c8..ce067057 100644
--- a/js/ajax-comments.min.js
+++ b/js/ajax-comments.min.js
@@ -1 +1 @@
-const fcn_ajaxCommentsSection=_$$$("comments");var fct_commentsObserver,fcn_commentStack=[];function fcn_getCommentSection(e=null,n=null,t=!1){if(!fcn_ajaxCommentsSection)return;const o=_$$$("comments");let c,a="",m=_$$$("comment");if(m&&(a=m.value),fcn_ajaxCommentsSection.classList.contains("ajax-in-progress"))return;if(fcn_ajaxCommentsSection.classList.add("ajax-in-progress"),n||(n=fcn_urlParams.pg??1),!fcn_ajaxCommentsSection)return;const r={action:"fictioneer_ajax_get_comment_section",post_id:e??fcn_ajaxCommentsSection.dataset.postId,page:parseInt(n)};fcn_urlParams.commentcode&&(r.commentcode=fcn_urlParams.commentcode),fcn_ajaxGet(r).then((e=>{if(e.success){n=e.data.page;const c=document.createElement("div");if(c.innerHTML=e.data.html,c.querySelector("#comment_post_ID")){c.querySelector("#comment_post_ID").value=e.data.postId,c.querySelector("#cancel-comment-reply-link").href="#respond";const n=c.querySelector(".logout-link");n&&(n.href=_$$$("comments").dataset.logoutUrl)}o.innerHTML=c.innerHTML,c.remove(),m=_$$$("comment"),m&&(m.value=a,fcn_commentStack.forEach((e=>{m.value+=e}))),fcn_commentStack=[],m&&fcn_textareaAdjust(m),fcn_addModerationEvents(),fcn_addCommentMouseleaveEvents(),fcn_addTextareaEvents(),fcn_addCommentFormEvents(),fcn_addPrivateToggleEvents(),fcn_bindAJAXCommentSubmit(),fcn_addJSTrap(),fcn_revealEditButton(),fcn_revealDeleteButton();const r=location.hash.includes("#comment")?location.hash:".respond",s=document.querySelector(r)??_$$$("respond");t&&s.scrollIntoView({behavior:"smooth"});const i=window.location.protocol+"//"+window.location.host+window.location.pathname;let _="";fcn_urlParams.commentcode&&(_+=`?commentcode=${fcn_urlParams.commentcode}`),n>1&&(_+=_.length>1?`&pg=${n}`:`?pg=${n}`),window.history.pushState({path:i},"",i+_+location.hash)}else c=fcn_buildErrorNotice(e.data.error)})).catch((e=>{c=fcn_buildErrorNotice(e)})).then((()=>{fcn_ajaxCommentsSection.classList.remove("ajax-in-progress"),c&&(o.innerHTML="",o.appendChild(c))}))}function fcn_reloadCommentsPage(e=null){fcn_getCommentSection(null,e,!0)}function fcn_jumpToCommentPage(){const e=parseInt(window.prompt(_x("Enter page number:","Pagination jump prompt.","fictioneer")));e>0&&fcn_reloadCommentsPage(e)}function fcn_setupCommentObserver(){fct_commentsObserver=new IntersectionObserver((([e])=>{e.isIntersecting&&(fcn_getCommentSection(),fct_commentsObserver.disconnect())}),{rootMargin:"400px",threshold:1}),fcn_ajaxCommentsSection&&fct_commentsObserver.observe(fcn_ajaxCommentsSection)}function fcn_loadCommentEarly(){_$$$("comments")&&location.hash.includes("#comment")&&(_$$$("comment")||(fct_commentsObserver.disconnect(),fcn_reloadCommentsPage()))}fcn_theRoot.dataset.ajaxNonce&&!_$$$("fictioneer-ajax-nonce")?fcn_theRoot.addEventListener("nonceReady",(()=>{fcn_setupCommentObserver()})):fcn_setupCommentObserver(),fcn_theRoot.dataset.ajaxNonce&&!_$$$("fictioneer-ajax-nonce")?fcn_theRoot.addEventListener("nonceReady",(()=>{fcn_loadCommentEarly()})):fcn_loadCommentEarly(),_$(".fictioneer-comments")?.addEventListener("click",(e=>{if(e.target.closest("[data-page-jump]"))return void fcn_jumpToCommentPage();const n=e.target.closest("[data-page]");n&&fcn_reloadCommentsPage(n.dataset.page)}));
\ No newline at end of file
+const fcn_ajaxCommentsSection=_$$$("comments");var fct_commentsObserver,fcn_commentStack=[];function fcn_getCommentSection(e=null,n=null,t=!1){if(!fcn_ajaxCommentsSection)return;const o=_$$$("comments");let c,a="",m=_$$$("comment");if(m&&(a=m.value),fcn_ajaxCommentsSection.classList.contains("ajax-in-progress"))return;if(fcn_ajaxCommentsSection.classList.add("ajax-in-progress"),n||(n=fcn_urlParams.pg??1),!fcn_ajaxCommentsSection)return;const s={action:"fictioneer_ajax_get_comment_section",post_id:e??fcn_ajaxCommentsSection.dataset.postId,page:parseInt(n)};fcn_urlParams.commentcode&&(s.commentcode=fcn_urlParams.commentcode),fcn_ajaxGet(s).then((e=>{if(e.success){n=e.data.page;const c=document.createElement("div");if(c.innerHTML=e.data.html,c.querySelector("#comment_post_ID")){c.querySelector("#comment_post_ID").value=e.data.postId,c.querySelector("#cancel-comment-reply-link").href="#respond";const n=c.querySelector(".logout-link");n&&(n.href=_$$$("comments").dataset.logoutUrl)}o.innerHTML=c.innerHTML,c.remove(),m=_$$$("comment"),m&&(m.value=a,fcn_commentStack.forEach((e=>{m.value+=e}))),fcn_commentStack=[],m&&fcn_textareaAdjust(m),fcn_addModerationEvents(),fcn_addCommentMouseleaveEvents(),fcn_addTextareaEvents(),fcn_addCommentFormEvents(),fcn_addPrivateToggleEvents(),fcn_bindAJAXCommentSubmit(),fcn_addJSTrap(),fcn_revealEditButton(),fcn_revealDeleteButton();const s=location.hash.includes("#comment")?location.hash:".respond",r=document.querySelector(s)??_$$$("respond");t&&r.scrollIntoView({behavior:"smooth"});const i=window.location.protocol+"//"+window.location.host+window.location.pathname;let d="";fcn_urlParams.commentcode&&(d+=`?commentcode=${fcn_urlParams.commentcode}`),n>1&&(d+=d.length>1?`&pg=${n}`:`?pg=${n}`),window.history.pushState({path:i},"",i+d+location.hash)}else c=fcn_buildErrorNotice(e.data.error)})).catch((e=>{c=fcn_buildErrorNotice(e)})).then((()=>{fcn_ajaxCommentsSection.classList.remove("ajax-in-progress"),c&&(o.innerHTML="",o.appendChild(c))}))}function fcn_reloadCommentsPage(e=null){fcn_getCommentSection(null,e,!0)}function fcn_jumpToCommentPage(){const e=parseInt(window.prompt(_x("Enter page number:","Pagination jump prompt.","fictioneer")));e>0&&fcn_reloadCommentsPage(e)}function fcn_setupCommentObserver(){fct_commentsObserver=new IntersectionObserver((([e])=>{e.isIntersecting&&(fcn_getCommentSection(),fct_commentsObserver.disconnect())}),{rootMargin:"400px",threshold:1}),fcn_ajaxCommentsSection&&fct_commentsObserver.observe(fcn_ajaxCommentsSection)}function fcn_loadCommentEarly(){_$$$("comments")&&location.hash.includes("#comment")&&(_$$$("comment")||(fct_commentsObserver.disconnect(),fcn_reloadCommentsPage()))}fcn_theRoot.dataset.ajaxNonce?document.addEventListener("fcnAuthReady",(()=>{fcn_setupCommentObserver()})):fcn_setupCommentObserver(),fcn_theRoot.dataset.ajaxNonce?document.addEventListener("fcnAuthReady",(()=>{fcn_loadCommentEarly()})):fcn_loadCommentEarly(),_$(".fictioneer-comments")?.addEventListener("click",(e=>{if(e.target.closest("[data-page-jump]"))return void fcn_jumpToCommentPage();const n=e.target.closest("[data-page]");n&&fcn_reloadCommentsPage(n.dataset.page)}));
\ No newline at end of file
diff --git a/js/application.min.js b/js/application.min.js
index b6a85cad..2e15460f 100644
--- a/js/application.min.js
+++ b/js/application.min.js
@@ -1 +1 @@
-const fcn_theSite=_$$$("site"),fcn_theBody=_$("body"),fcn_theRoot=document.documentElement,fcn_inlineStorage=_$$$("inline-storage").dataset,fcn_mainNavigation=_$$$("full-navigation"),fcn_urlSearchParams=new URLSearchParams(window.location.search),fcn_urlParams=Object.fromEntries(fcn_urlSearchParams.entries()),fcn_pageLoadTimestamp=Date.now(),fcn_ajaxLimitThreshold=Date.now()-parseInt(fictioneer_ajax.ttl),fcn_eventNonceReady=new Event("nonceReady"),fcn_isAjaxAuth=fcn_theRoot.dataset.ajaxAuth;var fcn_viewportWidth,fcn_mediaMinTablet,fcn_cssVars=getComputedStyle(document.documentElement),fcn_isLoggedIn=fcn_theBody.classList.contains("logged-in"),fcn_chapterList=_$("#story-chapter-list > ul")?.cloneNode(!0);const{__:__,_x:_x,_n:_n,sprintf:sprintf}=wp.i18n;function fcn_cleanupWebStorage(e=!1){localStorage.removeItem("fcnProfileAvatar"),localStorage.removeItem("fcnUserData"),localStorage.removeItem("fcnLoginState"),localStorage.removeItem("fcnBookshelfContent"),e||localStorage.removeItem("fcnChapterBookmarks");let t=localStorage.getItem("fcnNonce");t=!(!t||!fcn_isValidJSONString(t))&&JSON.parse(t),t&&t.loggedIn&&localStorage.removeItem("fcnNonce")}function fcn_cleanupGuestView(){fcn_isLoggedIn=!1,fcn_theBody.classList.remove("logged-in","is-admin","is-moderator","is-editor","is-author"),_$$(".only-moderators, .only-admins, .only-authors, .only-editors, .chapter-group__list-item-checkmark").forEach((e=>{e.remove()}))}function fcn_fetchNonce(){let e=localStorage.getItem("fcnNonce");e=!(!e||!fcn_isValidJSONString(e))&&JSON.parse(e),e&&!e.loggedIn&&fcn_isLoggedIn&&(localStorage.removeItem("fcnNonce"),e=!1),e&&(fcn_addNonceAndAuth(e.nonceHtml),fcn_ajaxLimitThreshold{_$$$("fictioneer-ajax-nonce")?.remove(),e.success?(fcn_addNonceAndAuth(e.data.nonceHtml),localStorage.setItem("fcnNonce",JSON.stringify({lastLoaded:Date.now(),nonceHtml:e.data.nonceHtml,loggedIn:fcn_isLoggedIn}))):(_$$$("fictioneer-ajax-nonce")?.remove(),fcn_cleanupGuestView())})).catch((()=>{localStorage.removeItem("fcnNonce"),_$$$("fictioneer-ajax-nonce")?.remove(),fcn_cleanupGuestView()}))}function fcn_addNonceAndAuth(e){const t=document.createElement("div");t.innerHTML+=e,fcn_theBody.appendChild(t.firstChild),fcn_theRoot.dispatchEvent(fcn_eventNonceReady),!fcn_isLoggedIn&&fcn_isAjaxAuth&&fcn_fetchLoginState()}function fcn_fetchLoginState(){let e=localStorage.getItem("fcnLoginState");e=!(!e||!fcn_isValidJSONString(e))&&JSON.parse(e),e&&e.loggedIn&&(fcn_setLoggedInState(e,!1),Date.now()-fictioneer_ajax.login_ttl{t.success&&t.data.loggedIn?(fcn_setLoggedInState(t.data,!e.loggedIn),localStorage.setItem("fcnLoginState",JSON.stringify({lastLoaded:Date.now(),loggedIn:t.data.loggedIn,isAdmin:t.data.isAdmin,isModerator:t.data.isModerator,isAuthor:t.data.isAuthor,isEditor:t.data.isEditor}))):(fcn_cleanupWebStorage(!0),fcn_cleanupGuestView())})).catch((()=>{fcn_cleanupWebStorage(),fcn_cleanupGuestView()}))}function fcn_setLoggedInState(e,t=!0){fcn_isLoggedIn=e.loggedIn,fcn_theBody.classList.add("logged-in"),fcn_theBody.classList.toggle("is-admin",e.isAdmin),fcn_theBody.classList.toggle("is-moderator",e.isModerator),fcn_theBody.classList.toggle("is-author",e.isAuthor),fcn_theBody.classList.toggle("is-editor",e.isEditor),e.isAdmin||_$$(".only-admins").forEach((e=>{e.remove()})),e.isModerator||e.isAdmin||_$$(".only-moderators").forEach((e=>{e.remove()})),e.isAuthor||e.isAdmin||_$$(".only-authors").forEach((e=>{e.remove()})),e.isModerator||e.isAdmin||_$$(".only-editors").forEach((e=>{e.remove()})),_$$('label[for="modal-login-toggle"], #modal-login-toggle, #login-modal').forEach((e=>{e.remove()})),t&&fcn_getProfileImage()}function fcn_updateViewportVariables(){fcn_viewportWidth=Math.max(document.documentElement.clientWidth??0,window.innerWidth??0),fcn_mediaMinTablet=fcn_viewportWidth>=768}function fcn_loadEmbed(e){e.target.parentNode.querySelectorAll("iframe, script")[0].src=e.target.dataset.src,e.target.parentElement.querySelector(".embed-logo")?.remove(),e.target.remove()}fcn_chapterList&&_$("#story-chapter-list > ul").remove(),fcn_isLoggedIn||fcn_isAjaxAuth||(fcn_cleanupWebStorage(!0),_$$(".chapter-group__list-item-checkmark").forEach((e=>{e.remove()}))),"function"==typeof fcn_removeQueryArgs&&fcn_removeQueryArgs(),_$("#wp-admin-bar-logout a")?.addEventListener("click",(()=>{fcn_cleanupWebStorage()})),fcn_theRoot.dataset.ajaxNonce&&fcn_fetchNonce(),fcn_isLoggedIn||void 0===fcn_isAjaxAuth||fcn_theRoot.dataset.ajaxNonce||fcn_fetchLoginState(),fcn_bindEventToAnimationFrame("scroll","scroll.rAF"),fcn_bindEventToAnimationFrame("resize","resize.rAF"),fcn_updateViewportVariables(),window.addEventListener("resize.rAF",fcn_throttle(fcn_updateViewportVariables,125)),fcn_theBody.addEventListener("click",(e=>{const t=e.target.closest(".toggle-last-clicked");if(t&&(!["BUTTON","A","INPUT","SELECT"].includes(e.target.tagName)||e.target.classList.contains("toggle-last-clicked")))return"function"==typeof fcn_toggleLastClicked&&fcn_toggleLastClicked(t),"function"==typeof fcn_popupPosition&&fcn_popupPosition(),void e.stopPropagation();const n=e.target.closest(".page-numbers.dots:not(button)");if(n)return void fcn_jumpPage(n);const o=e.target.closest(".spoiler");if(o)return void("function"==typeof fct_spoiler&&fct_spoiler(o));const s=e.target.closest("[data-click]"),i=s?.dataset.click;if(i)switch(i){case"copy-to-clipboard":s.select(),fcn_copyToClipboard(s.value,s.dataset.message);break;case"reset-consent":fcn_deleteCookie("fcn_cookie_consent"),location.reload();break;case"clear-cookies":fcn_deleteAllCookies(),alert(s.dataset.message);break;case"logout":fcn_cleanupWebStorage();break;case"card-toggle-follow":fcn_isLoggedIn?fcn_toggleFollow(s.dataset.storyId):_$$$("modal-login-toggle")?.click();break;case"card-toggle-reminder":fcn_isLoggedIn?fcn_toggleReminder(s.dataset.storyId):_$$$("modal-login-toggle")?.click();break;case"card-toggle-checkmarks":fcn_isLoggedIn?(fcn_toggleCheckmark(parseInt(s.dataset.storyId),s.dataset.type,parseInt(s.dataset.chapterId),null,s.dataset.mode),fcn_updateCheckmarksView()):_$$$("modal-login-toggle")?.click();break;case"toggle-obfuscation":s.closest("[data-obfuscation-target]").classList.toggle("_obfuscated")}})),_$$(".iframe-consent, .twitter-consent").forEach((e=>{e.onclick=e=>{fcn_loadEmbed(e)}}));var fcn_lastScrollTop=0;function fcn_scrollDirection(){if(fcn_theSite.classList.contains("transformed-scroll"))return;const e=window.scrollY??document.documentElement.scrollTop;Math.abs(fcn_lastScrollTop-e)>=5&&(fcn_theBody.classList.toggle("scrolling-down",e>fcn_lastScrollTop),fcn_theBody.classList.toggle("scrolling-up",!(e>fcn_lastScrollTop)),fcn_lastScrollTop=Math.max(e,0))}window.addEventListener("scroll.rAF",fcn_throttle(fcn_scrollDirection,200));const fcn_mainObserver=new IntersectionObserver((([e])=>{fcn_theBody.classList.toggle("is-inside-main",e.intersectionRatio<1&&e.boundingClientRect.top<=0)}),{threshold:[1]});(observer=_$(".main-observer"))&&fcn_mainObserver.observe(observer);const fcn_endOfChapterObserver=new IntersectionObserver((([e])=>{fcn_theBody.classList.toggle("is-end-of-chapter",e.isIntersecting||e.boundingClientRect.top<0)}),{root:null,threshold:0});(observer=_$(".chapter-end"))&&fcn_endOfChapterObserver.observe(observer);const fct_navStickyObserver=new IntersectionObserver((([e])=>{fcn_mainNavigation.classList.toggle("is-sticky",e.intersectionRatio<1)}),{threshold:[1]});function fcn_dragElement(e){const t=e.querySelector(".drag-anchor")??e;let n,o;function s(t){t.preventDefault(),e.style.top=e.offsetTop-(o-t.clientY)+"px",e.style.left=e.offsetLeft-(n-t.clientX)+"px",n=t.clientX,o=t.clientY}function i(){t.onmouseup=null,t.onmousemove=null}t.onmousedown=function(e){e.preventDefault(),n=e.clientX,o=e.clientY,t.onmousemove=s,t.onmouseup=i}}function fcn_showNotification(e,t=3,n="base"){const o=_$("#notifications"),s=document.createElement("div");s.innerHTML=e,s.classList.add("notifications__message",`_${n}`),s.style.opacity=1,s.style.transitionDelay=`${t}s`,o.prepend(s),s.addEventListener("transitionend",(e=>{o.removeChild(e.target)})),s.addEventListener("click",(e=>{o.removeChild(e.currentTarget)})),setTimeout((()=>{s.style.opacity=0}),100)}if((observer=_$$$("nav-observer-sticky"))&&fct_navStickyObserver.observe(observer),setTimeout((()=>{fcn_theRoot.scrollTop>40&&fcn_mainNavigation?.classList.add("is-sticky")}),50),_$$(".modal__header.drag-anchor").forEach((e=>{fcn_dragElement(e.closest(".modal__wrapper"))})),"oauth_email_taken"===fcn_urlParams.failure&&fcn_showNotification(__("The associated email address is already taken. You can link additional accounts in your profile.","fictioneer"),5,"warning"),"oauth_already_linked"===fcn_urlParams.failure&&fcn_showNotification(__("Account already linked to another profile.","fictioneer"),5,"warning"),"oauth_new_subscriber"===fcn_urlParams.success&&fcn_showNotification(__("Your account has been successfully linked. Hint: You can change your display name in your profile and link additional accounts.","fictioneer"),10),fcn_urlParams.success?.includes("oauth_merged_")&&fcn_showNotification(__("Account has been successfully linked.","fictioneer"),3,"success"),fcn_urlParams["fictioneer-notice"]&&""!==fcn_urlParams["fictioneer-notice"]){let e="1"===fcn_urlParams.failure?"warning":"base";e="1"===fcn_urlParams.success?"success":e,fcn_showNotification(__(fcn_sanitizeHTML(fcn_urlParams["fictioneer-notice"]),"fictioneer"),3,e)}const fcn_settingMinimal=_$$$("site-setting-minimal"),fcn_settingChapterProgressBar=_$$$("site-setting-chapter-progress-bar"),fcn_settingHueRotateRange=_$$$("site-setting-hue-rotate-range"),fcn_settingHueRotateText=_$$$("site-setting-hue-rotate-text"),fcn_settingHueRotateReset=_$$$("site-setting-hue-rotate-reset"),fcn_settingDarkenRanges=_$$(".setting-darken-range"),fcn_settingDarkenTexts=_$$(".setting-darken-text"),fcn_settingDarkenResets=_$$(".setting-darken-reset"),fcn_settingSaturationRanges=_$$(".setting-saturation-range"),fcn_settingSaturationTexts=_$$(".setting-saturation-text"),fcn_settingSaturationResets=_$$(".setting-saturation-resets"),fcn_settingEvents=["nav-sticky","background-textures","polygons","covers","text-shadows","minimal","chapter-progress-bar"];var fcn_siteSettings=fcn_getSiteSettings();function fcn_updateSiteSetting(e,t,n){e.checked=n,fcn_siteSettings[t]=n,fcn_applySiteSettings(fcn_siteSettings)}function fcn_toggleLightMode(){fcn_setLightMode(!(localStorage.getItem("fcnLightmode")?"true"==localStorage.getItem("fcnLightmode"):"light"==fcn_theRoot.dataset.modeDefault))}function fcn_setLightMode(e,t=!1){localStorage.setItem("fcnLightmode",e),fcn_theRoot.dataset.mode=e?"light":"";const n=_$$$("reader-settings-lightmode-toggle");n&&(n.checked=e,n.closest("label").ariaChecked=e),_$$(".toggle-light-mode").forEach((t=>{t.ariaChecked=e})),t||fcn_updateThemeColor()}function fcn_updateFontWeight(){const e="default"!=fcn_siteSettings["font-weight"];_$$(".site-setting-font-weight").forEach((e=>{e.value=fcn_siteSettings["font-weight"]})),_$$(".font-weight-reset").forEach((t=>{t.classList.toggle("_modified",e)}))}function fcn_resetFontWeight(){fcn_siteSettings["font-weight"]="default",fcn_theRoot.dataset.fontWeight="default",fcn_applySiteSettings(fcn_siteSettings)}function fcn_updateHueRotate(e){e=fcn_clamp(0,360,e??0),fcn_settingHueRotateText.value=e,fcn_settingHueRotateRange.value=e,fcn_settingHueRotateReset.classList.toggle("_modified",0!=e),fcn_theRoot.style.setProperty("--hue-rotate",`${e}deg + var(--hue-offset)`),fcn_siteSettings["hue-rotate"]=e,fcn_setSiteSettings(),fcn_updateThemeColor()}function fcn_setHueRotate(){fcn_updateHueRotate(this.value)}function fcn_updateDarken(e=null){e=fcn_clamp(-1,1,e??fcn_siteSettings.darken),e=Math.round(100*(e+Number.EPSILON))/100,fcn_settingDarkenResets.forEach((t=>{t.classList.toggle("_modified",0!=e)})),fcn_settingDarkenRanges.forEach((t=>{t.value=e})),fcn_settingDarkenTexts.forEach((t=>{t.value=parseInt(100*e)}));const t=e>=0?1+Math.pow(e,2):1-Math.pow(e,2);fcn_theRoot.style.setProperty("--darken",`(${t} + var(--lightness-offset))`),fcn_siteSettings.darken=e,fcn_setSiteSettings(),fcn_updateThemeColor()}function fcn_setDarkenFromRange(){fcn_updateDarken(this.value)}function fcn_setDarkenFromText(){"-"!=this.value&&""!=this.value&&fcn_updateDarken((parseInt(this.value)??0)/100)}function fcn_updateSaturation(e=null){e=fcn_clamp(-1,1,e??fcn_siteSettings.saturation),fcn_settingSaturationResets.forEach((t=>{t.classList.toggle("_modified",0!=e)})),fcn_settingSaturationRanges.forEach((t=>{t.value=e})),fcn_settingSaturationTexts.forEach((t=>{t.value=parseInt(100*e)}));const t=e>=0?1+Math.pow(e,2):1-Math.pow(e,2);fcn_theRoot.style.setProperty("--saturation",`(${t} + var(--saturation-offset))`),fcn_siteSettings.saturation=e,fcn_setSiteSettings(),fcn_updateThemeColor()}function fcn_setSaturationFromRange(){fcn_updateSaturation(this.value)}function fcn_setSaturationFromText(){"-"!=this.value&&""!=this.value&&fcn_updateSaturation((parseInt(this.value)??0)/100)}function fcn_defaultSiteSettings(){return{"nav-sticky":!0,"background-textures":!0,polygons:!0,covers:!0,"text-shadows":!1,minimal:!1,"chapter-progress-bar":!0,"site-theme":"default","font-weight":"default",darken:0,saturation:0,"font-saturation":0,"hue-rotate":0}}function fcn_getSiteSettings(){let e=localStorage.getItem("fcnSiteSettings");return e=e&&fcn_isValidJSONString(e)?JSON.parse(e):fcn_defaultSiteSettings(),fcn_setSiteSettings(e),e}function fcn_setSiteSettings(e=null){"object"==typeof(e=e||fcn_siteSettings)&&(fcn_siteSettings=e,localStorage.setItem("fcnSiteSettings",JSON.stringify(e)))}function fcn_applySiteSettings(e){e="object"!=typeof e?fcn_defaultSiteSettings():e,Object.entries(e).forEach((e=>{const t=_$$$(`site-setting-${e[0]}`);switch(t&&(t.checked=e[1]),e[0]){case"minimal":fcn_theRoot.classList.toggle("minimal",e[1]);break;case"darken":fcn_updateDarken();break;case"saturation":fcn_updateSaturation();break;case"font-saturation":break;case"hue-rotate":fcn_updateHueRotate(e[1]);break;case"font-weight":fcn_updateFontWeight();break;default:fcn_theRoot.classList.toggle(`no-${e[0]}`,!e[1])}})),fcn_setSiteSettings(e)}function fcn_updateSiteTheme(e){fcn_siteSettings["site-theme"]=e,fcn_theRoot.dataset.theme=e,_$$$("site-setting-theme-reset").classList.toggle("_modified","default"!=e),fcn_applySiteSettings(fcn_siteSettings),fcn_updateThemeColor()}function fcn_resetSiteTheme(){fcn_updateSiteTheme("default"),_$$(".site-setting-site-theme").forEach((e=>{e.value="default"}))}function fcn_jumpPage(e){if(fcn_theRoot.dataset.disablePageJump)return;const t=parseInt(window.prompt(_x("Enter page number:","Pagination jump prompt.","fictioneer")));if(t>0){const n=e.nextElementSibling.getAttribute("href"),o=["page=","paged=","comment-page-","pg="];for(const e of o)if(n.includes(e))return void(window.location.href=n.replace(new RegExp(`${e}\\d+`),e+t));window.location.href=n.replace(/page\/\d+/,`page/${t}`)}}fcn_settingEvents.forEach((e=>{_$$$(`site-setting-${e}`).onchange=t=>{fcn_updateSiteSetting(t.currentTarget,e,t.currentTarget.checked)}})),fcn_setLightMode(localStorage.getItem("fcnLightmode")?"true"==localStorage.getItem("fcnLightmode"):"light"==fcn_theRoot.dataset.modeDefault,!0),_$$(".toggle-light-mode").forEach((e=>{e.onclick=()=>fcn_toggleLightMode()})),_$$(".font-weight-reset").forEach((e=>{e.addEventListener("click",fcn_resetFontWeight)})),_$$(".site-setting-font-weight").forEach((e=>{e.onchange=e=>{fcn_siteSettings["font-weight"]=e.target.value,fcn_theRoot.dataset.fontWeight=e.target.value,fcn_applySiteSettings(fcn_siteSettings),fcn_updateFontWeight()}})),fcn_settingHueRotateReset?.addEventListener("click",(()=>{fcn_updateHueRotate(0)})),fcn_settingHueRotateRange?.addEventListener("input",fcn_throttle(fcn_setHueRotate,1e3/24)),fcn_settingHueRotateText?.addEventListener("input",fcn_setHueRotate),fcn_settingDarkenResets.forEach((e=>{e.addEventListener("click",(()=>{fcn_updateDarken(0)}))})),fcn_settingDarkenRanges.forEach((e=>{e.addEventListener("input",fcn_throttle(fcn_setDarkenFromRange,1e3/24))})),fcn_settingDarkenTexts.forEach((e=>{e.addEventListener("input",fcn_setDarkenFromText)})),fcn_settingSaturationResets.forEach((e=>{e.addEventListener("click",(()=>{fcn_updateSaturation(0)}))})),fcn_settingSaturationRanges.forEach((e=>{e.addEventListener("input",fcn_throttle(fcn_setSaturationFromRange,1e3/24))})),fcn_settingSaturationTexts.forEach((e=>{e.addEventListener("input",fcn_setSaturationFromText)})),fcn_applySiteSettings(fcn_siteSettings),_$$(".site-setting-site-theme").forEach((e=>{e.value=fcn_siteSettings.hasOwnProperty("site-theme")?fcn_siteSettings["site-theme"]:"default",_$$$("site-setting-theme-reset").classList.toggle("_modified","default"!=e.value),e.addEventListener("change",(e=>{fcn_updateSiteTheme(e.target.value)}))})),_$$$("site-setting-theme-reset")?.addEventListener("click",fcn_resetSiteTheme),fcn_updateThemeColor();const fcn_cardLists=_$$(".card-list:not(._no-mutation-observer)");var fcn_cardListMutationObserver=new MutationObserver((e=>{e[0].addedNodes&&("function"==typeof fcn_updateFollowsView&&fcn_updateFollowsView(),"function"==typeof fcn_updateCheckmarksView&&fcn_updateCheckmarksView(),"function"==typeof fcn_updateRemindersView&&fcn_updateRemindersView())}));function fct_spoiler(e){e.classList.toggle("_open")}function fcn_revealCommentImage(e){const t=e.parentElement.querySelector("img");t.src=t.dataset.src,e.remove()}function fcn_contactFormSubmit(e){const t=e.closest("form"),n=new FormData(t),o={action:"fictioneer_ajax_submit_contact_form"};if(t.reportValidity()&&(e.disabled=!0,e.innerHTML=e.dataset.disabled,!(Date.now(){n.success?(t.querySelector("textarea").value="",e.innerHTML=e.dataset.done,fcn_showNotification(n.data.success,3,"success")):n.data.error&&(e.disabled=!1,e.innerHTML=e.dataset.enabled,fcn_showNotification(n.data.error,5,"warning"))})).catch((t=>{t.status&&t.statusText&&(fcn_showNotification(`${t.status}: ${t.statusText}`,5,"warning"),e.disabled=!1,e.innerHTML=e.dataset.enabled)})).then((()=>{t.classList.remove("ajax-in-progress")}))}}fcn_cardLists.length&&fcn_cardLists.forEach((e=>{fcn_cardListMutationObserver.observe(e,{childList:!0,subtree:!0})})),_$$(".chapter-group__name").forEach((e=>{e.addEventListener("click",(e=>{var t=e.currentTarget.closest(".chapter-group"),n=t.querySelector(".chapter-group__list"),o=!t.classList.contains("_closed");n.style.height=`${n.scrollHeight}px`,setTimeout((()=>{t.classList.toggle("_closed",o)}),10)})),e.closest(".chapter-group").querySelector(".chapter-group__list").addEventListener("transitionend",(e=>{const t=e.currentTarget.closest(".chapter-group"),n=t.querySelector(".chapter-group__list");n.style.height="",n.querySelectorAll("a, button, label, input:not([hidden])").forEach((e=>{e.tabIndex=t.classList.contains("_closed")?"-1":"0"}))}))})),_$(".fictioneer-comments")?.addEventListener("click",(e=>{e.target?.classList.contains("consent-button")&&fcn_revealCommentImage(e.target)})),_$$(".fcn-contact-form").forEach((e=>{e.querySelector(".fcn-contact-form__submit").addEventListener("click",(e=>{fcn_contactFormSubmit(e.currentTarget)}))})),fcn_theBody.querySelectorAll(".modal-toggle").forEach((e=>{e.addEventListener("change",(e=>{if(e.currentTarget.checked){const t=e.currentTarget.nextElementSibling.querySelector('[tabindex="0"]');t?.focus(),t?.blur()}else fcn_theBody.classList.contains("user-is-tabbing")&&fcn_theSite.querySelector(`label[for="${e.currentTarget.id}"]`)?.focus()}))})),fcn_theBody.addEventListener("keydown",(e=>{let t=document.activeElement.closest('[tabindex="0"]:not(a, input, button, select)');if(["BUTTON","A","INPUT","SELECT"].includes(document.activeElement.tagName)&&(t=null),t&&(32!=e.keyCode&&13!=e.keyCode||(e.preventDefault(),t.click())),27==e.keyCode){_$$(".modal-toggle:checked").forEach((e=>{e.checked=!1,e.dispatchEvent(new Event("change"))}));const e=_$(".lightbox.show");if(e)return void e.querySelector(".lightbox__close").click();const t=_$(".selected-paragraph #button-close-paragraph-tools");if(t)return void t.click();const n=_$("#tts-interface:not(.hidden)");if(n){if(n.classList.contains("playing")){const e=_$$$("button-tts-pause");e?.click(),e?.focus(),e?.blur()}else _$$$("button-tts-stop").click();return}}}));class FCN_KeywordInput{constructor(e){this.input=e,this.operator=e.closest(".keyword-input").querySelector(".keyword-input__operator input"),this.inputWrapper=e.closest(".keyword-input__input-wrapper"),this.block=e.closest(".keyword-input"),this.form=this.block.closest(".search-form"),this.collection=this.block.querySelector(".keyword-input__collection"),this.suggestionList=this.block.querySelector(".keyword-input__suggestion-list"),this.tabSuggestion=this.block.querySelector(".keyword-input__tab-suggestion"),this.allowText=this.form.querySelector(".allow-list")?.innerText??"{}",this.allowList=JSON.parse(this.allowText),this.hints=this.block.querySelector(".keyword-input__hints"),this.noHint=this.block.querySelector(".keyword-input__no-suggestions"),this.keywords=this.collection.value.length>0?this.collection.value.split(","):[],this.bindEvents(),this.resize(),this.filterSuggestions()}resize(){fcn_resizeInput(this.input,this.tabSuggestion.innerText.length>0?this.tabSuggestion.innerText.length:this.input.value.length)}reset(){this.keywords=[],this.block.querySelectorAll(".node").forEach((e=>{e.remove()})),this.block.querySelectorAll(".keyword-input__operator > input").forEach((e=>{e.checked=!1})),this.input.value="",this.updateCollection(),this.filterSuggestions(),this.resize()}encode(e){return encodeURIComponent(e.toLowerCase()).replace(/'/g,"%27")}filterSuggestions(){const e=this.input.value.toLowerCase();let t=0,n="";""==e?this.suggestionList.querySelectorAll(".keyword-button").forEach((e=>{e.hidden=!0})):this.suggestionList.querySelectorAll(".keyword-button").forEach((o=>{const s=o.innerText.toLowerCase();s.includes(e)&&this.keywords.indexOf(s)<0?(o.hidden=!1,t++,""==n&&s.startsWith(e)&&(n=s)):o.hidden=!0})),this.hints.querySelectorAll(".keyword-button").forEach((e=>{this.keywords.indexOf(e.value.toLowerCase())>-1?e.hidden=!0:e.hidden=!1})),this.tabSuggestion.innerHTML=n,this.hints.hidden=!(""==e),this.noHint.hidden=!(""!=e&&t<1)}addNode(e=null){const t=e??this.input.value.replace(",",""),n=this.allowList[this.encode(t)];if(!n||this.keywords.indexOf(n)>-1)return;this.keywords.push(n);const o=document.createElement("div");o.innerHTML=`${t}`,o.classList.add("node"),o.dataset.value=n,this.inputWrapper.parentNode.insertBefore(o,this.inputWrapper),this.input.value="",this.updateCollection(),this.filterSuggestions(),this.resize()}removeNodeByValue(e){this.block.querySelector(`[data-value="${e}"]`)?.remove(),this.keywords.splice(this.keywords.indexOf(e),1),this.updateCollection(),this.filterSuggestions(),this.resize()}updateCollection(){this.collection.value=this.keywords.join(","),this.block.classList.toggle("_empty",""===this.collection.value),this.form.querySelector(".search-form__current").innerHTML=""}bindEvents(){this.operator&&this.operator.addEventListener("change",(e=>{e.currentTarget.closest("label").ariaChecked=e.currentTarget.checked})),this.input.addEventListener("input",(e=>{e.currentTarget.value.includes(",")&&this.addNode(),this.block.classList.toggle("_empty",""===e.currentTarget.value),this.filterSuggestions(),this.resize()})),this.input.addEventListener("keydown",(e=>{9!=e.keyCode&&13!=e.keyCode||""!=this.tabSuggestion.innerText&&(e.preventDefault(),this.input.value=this.tabSuggestion.innerText,this.addNode()),27==e.keyCode&&(this.input.value="",this.tabSuggestion.innerHTML="",document.activeElement.blur()),8==e.keyCode&&""==this.input.value&&this.keywords.length>0&&this.removeNodeByValue(this.keywords.slice(-1))})),this.input.addEventListener("blur",(()=>{const e=this.allowList[this.encode(this.input.value)];this.blurTimeout=e?setTimeout((()=>{this.addNode()}),150):setTimeout((()=>{this.input.value="",this.tabSuggestion.innerHTML="",this.filterSuggestions(),this.resize()}),150)})),this.block.addEventListener("click",(e=>{e.target.closest(".node-delete")&&(e.preventDefault(),this.removeNodeByValue(e.target.closest(".node").dataset.value))})),this.block.querySelectorAll(".keyword-button").forEach((e=>{e.addEventListener("click",(e=>{clearTimeout(this.blurTimeout),this.addNode(e.currentTarget.innerText)}))}))}}function fcn_handleTabInput(e){9==e.keyCode&&(fcn_theBody.classList.add("user-is-tabbing"),window.removeEventListener("keydown",fcn_handleTabInput),window.addEventListener("mousedown",fcn_handleMouseInput))}function fcn_handleMouseInput(){fcn_theBody.classList.remove("user-is-tabbing"),window.removeEventListener("mousedown",fcn_handleMouseInput),window.addEventListener("keydown",fcn_handleTabInput)}function fcn_popupPosition(){_$$(".popup-menu-toggle.last-clicked .popup-menu:not(._fixed-position)").forEach((e=>{if("none"===window.getComputedStyle(e).display)return;const t=fcn_detectScreenCollision(e);t&&0===t.length||(t.includes("top")?(e.classList.remove("_top"),e.classList.add("_bottom")):t.includes("bottom")&&(e.classList.remove("_bottom"),e.classList.add("_top")))}))}function fcn_markCurrentMenuItem(){_$$(`.menu-item > [data-nav-object-id="${fcn_theBody.dataset.postId}"]`).forEach((e=>{e.setAttribute("aria-current","page"),e.closest(".menu-item").classList.add("current-menu-item")}))}_$$(".search-form").forEach((e=>{const t=[];e.classList.contains("_simple")||(e.querySelectorAll(".keyword-input__input").forEach((e=>{t.push(new FCN_KeywordInput(e))})),e.querySelector(".allow-list")?.remove(),e.addEventListener("change",(t=>{t.target.classList.contains("search-form__advanced-control")||t.target.classList.contains("search-form__string")||(e.querySelector(".search-form__current").innerHTML="")})),e.querySelectorAll(".reset").forEach((n=>{n.addEventListener("click",(o=>{t.forEach((e=>{e.reset()})),e.querySelector("input[name=s]").value="",e.querySelector("select[name=post_type]").value="any",e.querySelector("select[name=sentence]").value="0",e.querySelector("select[name=orderby]").value="modified",e.querySelector("select[name=order]").value="desc",e.querySelector(".search-form__current").innerHTML="",fcn_showNotification(n.dataset.reset,2)}))})))})),_$$(".search-form__advanced-toggle").forEach((e=>{e.addEventListener("click",(e=>{const t=e.currentTarget.closest("form");t.dataset.advanced="true"==t.dataset.advanced?"false":"true"}))})),window.addEventListener("keydown",fcn_handleTabInput),window.addEventListener("scroll.rAF",fcn_throttle(fcn_popupPosition,250)),_$$(".modal-toggle").forEach((e=>{e.addEventListener("change",(e=>{const t=_$$$(e.currentTarget.dataset.target);t.classList.toggle("_open",e.currentTarget.checked);const n=t.querySelector(".close");n?.focus(),n?.blur()}))})),fcn_theBody.addEventListener("click",(e=>{const t=e.target.closest("[href]"),n=t?.getAttribute("href");if(t&&"A"===t.tagName&&n.startsWith("#")&&n.length>1&&"#respond"!==n){const o=n.replace("#",""),s=_$$(`[name="${o}"], #${o}`)[0],i=t.closest(".comment._story-comment");if(i){const e=i.querySelector(".fictioneer-comment__link").href+n;e&&(window.location.href=e)}s&&(e.preventDefault(),s.scrollIntoView({behavior:"smooth",block:t.dataset?.block??"start"}))}})),fcn_markCurrentMenuItem();
\ No newline at end of file
+const fcn_theSite=_$$$("site"),fcn_theBody=_$("body"),fcn_theRoot=document.documentElement,fcn_inlineStorage=_$$$("inline-storage").dataset,fcn_mainNavigation=_$$$("full-navigation"),fcn_urlSearchParams=new URLSearchParams(window.location.search),fcn_urlParams=Object.fromEntries(fcn_urlSearchParams.entries()),fcn_pageLoadTimestamp=Date.now(),fcn_ajaxLimitThreshold=Date.now()-parseInt(fictioneer_ajax.ttl);var fcn_viewportWidth,fcn_mediaMinTablet,fcn_cssVars=getComputedStyle(document.documentElement),fcn_isLoggedIn=fcn_theBody.classList.contains("logged-in"),fcn_chapterList=_$("#story-chapter-list > ul")?.cloneNode(!0);const{__:__,_x:_x,_n:_n,sprintf:sprintf}=wp.i18n;function fcn_cleanupWebStorage(e=!1){localStorage.removeItem("fcnProfileAvatar"),localStorage.removeItem("fcnUserData"),localStorage.removeItem("fcnBookshelfContent"),e||localStorage.removeItem("fcnChapterBookmarks");fcn_parseJSON(localStorage.getItem("fcnAuth"))?.loggedIn&&localStorage.removeItem("fcnAuth")}function fcn_cleanupGuestView(){fcn_isLoggedIn=!1,fcn_theBody.classList.remove("logged-in","is-admin","is-moderator","is-editor","is-author"),_$$$("fictioneer-ajax-nonce")?.remove(),_$$(".only-moderators, .only-admins, .only-authors, .only-editors, .chapter-group__list-item-checkmark").forEach((e=>{e.remove()}))}function fcn_ajaxAuth(){let e=!1,t=fcn_parseJSON(localStorage.getItem("fcnAuth"))??!1;if(fcn_isLoggedIn&&!t?.loggedIn&&(localStorage.removeItem("fcnAuth"),t=!1),t){fcn_addNonceHTML(t.nonceHtml);const n=new CustomEvent("fcnAuthReady",{detail:{nonceHtml:t.nonceHtml,nonce:t.nonce,loggedIn:t.loggedIn,isAdmin:t.isAdmin,isModerator:t.isModerator,isAuthor:t.isAuthor,isEditor:t.isEditor},bubbles:!0,cancelable:!1});if(document.dispatchEvent(n),e=!0,fcn_ajaxLimitThreshold{if(t.success){fcn_addNonceHTML(t.data.nonceHtml);const n={lastLoaded:Date.now(),nonceHtml:t.data.nonceHtml,nonce:t.data.nonce,loggedIn:t.data.loggedIn,isAdmin:t.data.isAdmin,isModerator:t.data.isModerator,isAuthor:t.data.isAuthor,isEditor:t.data.isEditor};if(!e){const e=new CustomEvent("fcnAuthReady",{detail:n,bubbles:!0,cancelable:!1});document.dispatchEvent(e)}localStorage.setItem("fcnAuth",JSON.stringify(n))}else{fcn_cleanupGuestView();const e=new Event("fcnAuthFailed");document.dispatchEvent(e)}})).catch((()=>{localStorage.removeItem("fcnAuth"),fcn_cleanupGuestView();const e=new Event("fcnAuthError");document.dispatchEvent(e)}))}function fcn_addNonceHTML(e){_$$$("fictioneer-ajax-nonce")?.remove(),fcn_theBody.appendChild(fcn_html`${e}`)}function fcn_setLoggedInState(e){fcn_isLoggedIn=e.loggedIn,fcn_theBody.classList.add("logged-in"),fcn_theBody.classList.toggle("is-admin",e.isAdmin),fcn_theBody.classList.toggle("is-moderator",e.isModerator),fcn_theBody.classList.toggle("is-author",e.isAuthor),fcn_theBody.classList.toggle("is-editor",e.isEditor),e.isAdmin||_$$(".only-admins").forEach((e=>{e.remove()})),e.isModerator||e.isAdmin||_$$(".only-moderators").forEach((e=>{e.remove()})),e.isAuthor||e.isAdmin||_$$(".only-authors").forEach((e=>{e.remove()})),e.isModerator||e.isAdmin||_$$(".only-editors").forEach((e=>{e.remove()})),_$$('label[for="modal-login-toggle"], #modal-login-toggle, #login-modal').forEach((e=>{e.remove()})),fcn_initializeUserData(),fcn_getProfileImage()}function fcn_updateViewportVariables(){fcn_viewportWidth=Math.max(document.documentElement.clientWidth??0,window.innerWidth??0),fcn_mediaMinTablet=fcn_viewportWidth>=768}function fcn_loadEmbed(e){e.target.parentNode.querySelectorAll("iframe, script")[0].src=e.target.dataset.src,e.target.parentElement.querySelector(".embed-logo")?.remove(),e.target.remove()}fcn_chapterList&&_$("#story-chapter-list > ul").remove(),fcn_isLoggedIn||fcn_theRoot.dataset.ajaxAuth||(fcn_cleanupWebStorage(!0),fcn_cleanupGuestView()),"function"==typeof fcn_removeQueryArgs&&fcn_removeQueryArgs(),_$("#wp-admin-bar-logout a")?.addEventListener("click",(()=>{fcn_cleanupWebStorage()})),document.addEventListener("DOMContentLoaded",(()=>{fcn_theRoot.dataset.ajaxAuth&&fcn_ajaxAuth()})),!fcn_isLoggedIn&&fcn_theRoot.dataset.ajaxAuth&&document.addEventListener("fcnAuthReady",(e=>{e.detail.loggedIn?fcn_setLoggedInState(e.detail):(fcn_cleanupWebStorage(!0),fcn_cleanupGuestView())})),fcn_bindEventToAnimationFrame("scroll","scroll.rAF"),fcn_bindEventToAnimationFrame("resize","resize.rAF"),fcn_updateViewportVariables(),window.addEventListener("resize.rAF",fcn_throttle(fcn_updateViewportVariables,125)),fcn_theBody.addEventListener("click",(e=>{const t=e.target.closest(".toggle-last-clicked");if(t&&(!["BUTTON","A","INPUT","SELECT"].includes(e.target.tagName)||e.target.classList.contains("toggle-last-clicked")))return"function"==typeof fcn_toggleLastClicked&&fcn_toggleLastClicked(t),"function"==typeof fcn_popupPosition&&fcn_popupPosition(),void e.stopPropagation();const n=e.target.closest(".page-numbers.dots:not(button)");if(n)return void fcn_jumpPage(n);const o=e.target.closest(".spoiler");if(o)return void("function"==typeof fct_spoiler&&fct_spoiler(o));const s=e.target.closest("[data-click]"),i=s?.dataset.click;if(i)switch(i){case"copy-to-clipboard":s.select(),fcn_copyToClipboard(s.value,s.dataset.message);break;case"reset-consent":fcn_deleteCookie("fcn_cookie_consent"),location.reload();break;case"clear-cookies":fcn_deleteAllCookies(),alert(s.dataset.message);break;case"logout":fcn_cleanupWebStorage();break;case"card-toggle-follow":fcn_isLoggedIn?fcn_toggleFollow(s.dataset.storyId):_$$$("modal-login-toggle")?.click();break;case"card-toggle-reminder":fcn_isLoggedIn?fcn_toggleReminder(s.dataset.storyId):_$$$("modal-login-toggle")?.click();break;case"card-toggle-checkmarks":fcn_isLoggedIn?(fcn_toggleCheckmark(parseInt(s.dataset.storyId),s.dataset.type,parseInt(s.dataset.chapterId),null,s.dataset.mode),fcn_updateCheckmarksView()):_$$$("modal-login-toggle")?.click();break;case"toggle-obfuscation":s.closest("[data-obfuscation-target]").classList.toggle("_obfuscated")}})),_$$(".iframe-consent, .twitter-consent").forEach((e=>{e.onclick=e=>{fcn_loadEmbed(e)}}));var fcn_lastScrollTop=0;function fcn_scrollDirection(){if(fcn_theSite.classList.contains("transformed-scroll"))return;const e=window.scrollY??document.documentElement.scrollTop;Math.abs(fcn_lastScrollTop-e)>=5&&(fcn_theBody.classList.toggle("scrolling-down",e>fcn_lastScrollTop),fcn_theBody.classList.toggle("scrolling-up",!(e>fcn_lastScrollTop)),fcn_lastScrollTop=Math.max(e,0))}window.addEventListener("scroll.rAF",fcn_throttle(fcn_scrollDirection,200));const fcn_mainObserver=new IntersectionObserver((([e])=>{fcn_theBody.classList.toggle("is-inside-main",e.intersectionRatio<1&&e.boundingClientRect.top<=0)}),{threshold:[1]});(observer=_$(".main-observer"))&&fcn_mainObserver.observe(observer);const fcn_endOfChapterObserver=new IntersectionObserver((([e])=>{fcn_theBody.classList.toggle("is-end-of-chapter",e.isIntersecting||e.boundingClientRect.top<0)}),{root:null,threshold:0});(observer=_$(".chapter-end"))&&fcn_endOfChapterObserver.observe(observer);const fct_navStickyObserver=new IntersectionObserver((([e])=>{fcn_mainNavigation.classList.toggle("is-sticky",e.intersectionRatio<1)}),{threshold:[1]});function fcn_dragElement(e){const t=e.querySelector(".drag-anchor")??e;let n,o;function s(t){t.preventDefault(),e.style.top=e.offsetTop-(o-t.clientY)+"px",e.style.left=e.offsetLeft-(n-t.clientX)+"px",n=t.clientX,o=t.clientY}function i(){t.onmouseup=null,t.onmousemove=null}t.onmousedown=function(e){e.preventDefault(),n=e.clientX,o=e.clientY,t.onmousemove=s,t.onmouseup=i}}function fcn_showNotification(e,t=3,n="base"){const o=_$("#notifications"),s=document.createElement("div");s.innerHTML=e,s.classList.add("notifications__message",`_${n}`),s.style.opacity=1,s.style.transitionDelay=`${t}s`,o.prepend(s),s.addEventListener("transitionend",(e=>{o.removeChild(e.target)})),s.addEventListener("click",(e=>{o.removeChild(e.currentTarget)})),setTimeout((()=>{s.style.opacity=0}),100)}if((observer=_$$$("nav-observer-sticky"))&&fct_navStickyObserver.observe(observer),setTimeout((()=>{fcn_theRoot.scrollTop>40&&fcn_mainNavigation?.classList.add("is-sticky")}),50),_$$(".modal__header.drag-anchor").forEach((e=>{fcn_dragElement(e.closest(".modal__wrapper"))})),"oauth_email_taken"===fcn_urlParams.failure&&fcn_showNotification(__("The associated email address is already taken. You can link additional accounts in your profile.","fictioneer"),5,"warning"),"oauth_already_linked"===fcn_urlParams.failure&&fcn_showNotification(__("Account already linked to another profile.","fictioneer"),5,"warning"),"oauth_new_subscriber"===fcn_urlParams.success&&fcn_showNotification(__("Your account has been successfully linked. Hint: You can change your display name in your profile and link additional accounts.","fictioneer"),10),fcn_urlParams.success?.includes("oauth_merged_")&&fcn_showNotification(__("Account has been successfully linked.","fictioneer"),3,"success"),fcn_urlParams["fictioneer-notice"]&&""!==fcn_urlParams["fictioneer-notice"]){let e="1"===fcn_urlParams.failure?"warning":"base";e="1"===fcn_urlParams.success?"success":e,fcn_showNotification(__(fcn_sanitizeHTML(fcn_urlParams["fictioneer-notice"]),"fictioneer"),3,e)}const fcn_settingMinimal=_$$$("site-setting-minimal"),fcn_settingChapterProgressBar=_$$$("site-setting-chapter-progress-bar"),fcn_settingHueRotateRange=_$$$("site-setting-hue-rotate-range"),fcn_settingHueRotateText=_$$$("site-setting-hue-rotate-text"),fcn_settingHueRotateReset=_$$$("site-setting-hue-rotate-reset"),fcn_settingDarkenRanges=_$$(".setting-darken-range"),fcn_settingDarkenTexts=_$$(".setting-darken-text"),fcn_settingDarkenResets=_$$(".setting-darken-reset"),fcn_settingSaturationRanges=_$$(".setting-saturation-range"),fcn_settingSaturationTexts=_$$(".setting-saturation-text"),fcn_settingSaturationResets=_$$(".setting-saturation-resets"),fcn_settingEvents=["nav-sticky","background-textures","polygons","covers","text-shadows","minimal","chapter-progress-bar"];var fcn_siteSettings=fcn_getSiteSettings();function fcn_updateSiteSetting(e,t,n){e.checked=n,fcn_siteSettings[t]=n,fcn_applySiteSettings(fcn_siteSettings)}function fcn_toggleLightMode(){fcn_setLightMode(!(localStorage.getItem("fcnLightmode")?"true"==localStorage.getItem("fcnLightmode"):"light"==fcn_theRoot.dataset.modeDefault))}function fcn_setLightMode(e,t=!1){localStorage.setItem("fcnLightmode",e),fcn_theRoot.dataset.mode=e?"light":"";const n=_$$$("reader-settings-lightmode-toggle");n&&(n.checked=e,n.closest("label").ariaChecked=e),_$$(".toggle-light-mode").forEach((t=>{t.ariaChecked=e})),t||fcn_updateThemeColor()}function fcn_updateFontWeight(){const e="default"!=fcn_siteSettings["font-weight"];_$$(".site-setting-font-weight").forEach((e=>{e.value=fcn_siteSettings["font-weight"]})),_$$(".font-weight-reset").forEach((t=>{t.classList.toggle("_modified",e)}))}function fcn_resetFontWeight(){fcn_siteSettings["font-weight"]="default",fcn_theRoot.dataset.fontWeight="default",fcn_applySiteSettings(fcn_siteSettings)}function fcn_updateHueRotate(e){e=fcn_clamp(0,360,e??0),fcn_settingHueRotateText.value=e,fcn_settingHueRotateRange.value=e,fcn_settingHueRotateReset.classList.toggle("_modified",0!=e),fcn_theRoot.style.setProperty("--hue-rotate",`${e}deg + var(--hue-offset)`),fcn_siteSettings["hue-rotate"]=e,fcn_setSiteSettings(),fcn_updateThemeColor()}function fcn_setHueRotate(){fcn_updateHueRotate(this.value)}function fcn_updateDarken(e=null){e=fcn_clamp(-1,1,e??fcn_siteSettings.darken),e=Math.round(100*(e+Number.EPSILON))/100,fcn_settingDarkenResets.forEach((t=>{t.classList.toggle("_modified",0!=e)})),fcn_settingDarkenRanges.forEach((t=>{t.value=e})),fcn_settingDarkenTexts.forEach((t=>{t.value=parseInt(100*e)}));const t=e>=0?1+Math.pow(e,2):1-Math.pow(e,2);fcn_theRoot.style.setProperty("--darken",`(${t} + var(--lightness-offset))`),fcn_siteSettings.darken=e,fcn_setSiteSettings(),fcn_updateThemeColor()}function fcn_setDarkenFromRange(){fcn_updateDarken(this.value)}function fcn_setDarkenFromText(){"-"!=this.value&&""!=this.value&&fcn_updateDarken((parseInt(this.value)??0)/100)}function fcn_updateSaturation(e=null){e=fcn_clamp(-1,1,e??fcn_siteSettings.saturation),fcn_settingSaturationResets.forEach((t=>{t.classList.toggle("_modified",0!=e)})),fcn_settingSaturationRanges.forEach((t=>{t.value=e})),fcn_settingSaturationTexts.forEach((t=>{t.value=parseInt(100*e)}));const t=e>=0?1+Math.pow(e,2):1-Math.pow(e,2);fcn_theRoot.style.setProperty("--saturation",`(${t} + var(--saturation-offset))`),fcn_siteSettings.saturation=e,fcn_setSiteSettings(),fcn_updateThemeColor()}function fcn_setSaturationFromRange(){fcn_updateSaturation(this.value)}function fcn_setSaturationFromText(){"-"!=this.value&&""!=this.value&&fcn_updateSaturation((parseInt(this.value)??0)/100)}function fcn_defaultSiteSettings(){return{"nav-sticky":!0,"background-textures":!0,polygons:!0,covers:!0,"text-shadows":!1,minimal:!1,"chapter-progress-bar":!0,"site-theme":"default","font-weight":"default",darken:0,saturation:0,"font-saturation":0,"hue-rotate":0}}function fcn_getSiteSettings(){const e=fcn_parseJSON(localStorage.getItem("fcnSiteSettings"))??fcn_defaultSiteSettings();return fcn_setSiteSettings(e),e}function fcn_setSiteSettings(e=null){"object"==typeof(e=e||fcn_siteSettings)&&(fcn_siteSettings=e,localStorage.setItem("fcnSiteSettings",JSON.stringify(e)))}function fcn_applySiteSettings(e){e="object"!=typeof e?fcn_defaultSiteSettings():e,Object.entries(e).forEach((e=>{const t=_$$$(`site-setting-${e[0]}`);switch(t&&(t.checked=e[1]),e[0]){case"minimal":fcn_theRoot.classList.toggle("minimal",e[1]);break;case"darken":fcn_updateDarken();break;case"saturation":fcn_updateSaturation();break;case"font-saturation":break;case"hue-rotate":fcn_updateHueRotate(e[1]);break;case"font-weight":fcn_updateFontWeight();break;default:fcn_theRoot.classList.toggle(`no-${e[0]}`,!e[1])}})),fcn_setSiteSettings(e)}function fcn_updateSiteTheme(e){fcn_siteSettings["site-theme"]=e,fcn_theRoot.dataset.theme=e,_$$$("site-setting-theme-reset").classList.toggle("_modified","default"!=e),fcn_applySiteSettings(fcn_siteSettings),fcn_updateThemeColor()}function fcn_resetSiteTheme(){fcn_updateSiteTheme("default"),_$$(".site-setting-site-theme").forEach((e=>{e.value="default"}))}function fcn_jumpPage(e){if(fcn_theRoot.dataset.disablePageJump)return;const t=parseInt(window.prompt(_x("Enter page number:","Pagination jump prompt.","fictioneer")));if(t>0){const n=e.nextElementSibling.getAttribute("href"),o=["page=","paged=","comment-page-","pg="];for(const e of o)if(n.includes(e))return void(window.location.href=n.replace(new RegExp(`${e}\\d+`),e+t));window.location.href=n.replace(/page\/\d+/,`page/${t}`)}}fcn_settingEvents.forEach((e=>{_$$$(`site-setting-${e}`).onchange=t=>{fcn_updateSiteSetting(t.currentTarget,e,t.currentTarget.checked)}})),fcn_setLightMode(localStorage.getItem("fcnLightmode")?"true"==localStorage.getItem("fcnLightmode"):"light"==fcn_theRoot.dataset.modeDefault,!0),_$$(".toggle-light-mode").forEach((e=>{e.onclick=()=>fcn_toggleLightMode()})),_$$(".font-weight-reset").forEach((e=>{e.addEventListener("click",fcn_resetFontWeight)})),_$$(".site-setting-font-weight").forEach((e=>{e.onchange=e=>{fcn_siteSettings["font-weight"]=e.target.value,fcn_theRoot.dataset.fontWeight=e.target.value,fcn_applySiteSettings(fcn_siteSettings),fcn_updateFontWeight()}})),fcn_settingHueRotateReset?.addEventListener("click",(()=>{fcn_updateHueRotate(0)})),fcn_settingHueRotateRange?.addEventListener("input",fcn_throttle(fcn_setHueRotate,1e3/24)),fcn_settingHueRotateText?.addEventListener("input",fcn_setHueRotate),fcn_settingDarkenResets.forEach((e=>{e.addEventListener("click",(()=>{fcn_updateDarken(0)}))})),fcn_settingDarkenRanges.forEach((e=>{e.addEventListener("input",fcn_throttle(fcn_setDarkenFromRange,1e3/24))})),fcn_settingDarkenTexts.forEach((e=>{e.addEventListener("input",fcn_setDarkenFromText)})),fcn_settingSaturationResets.forEach((e=>{e.addEventListener("click",(()=>{fcn_updateSaturation(0)}))})),fcn_settingSaturationRanges.forEach((e=>{e.addEventListener("input",fcn_throttle(fcn_setSaturationFromRange,1e3/24))})),fcn_settingSaturationTexts.forEach((e=>{e.addEventListener("input",fcn_setSaturationFromText)})),fcn_applySiteSettings(fcn_siteSettings),_$$(".site-setting-site-theme").forEach((e=>{e.value=fcn_siteSettings.hasOwnProperty("site-theme")?fcn_siteSettings["site-theme"]:"default",_$$$("site-setting-theme-reset").classList.toggle("_modified","default"!=e.value),e.addEventListener("change",(e=>{fcn_updateSiteTheme(e.target.value)}))})),_$$$("site-setting-theme-reset")?.addEventListener("click",fcn_resetSiteTheme),fcn_updateThemeColor();const fcn_cardLists=_$$(".card-list:not(._no-mutation-observer)");var fcn_cardListMutationObserver=new MutationObserver((e=>{e[0].addedNodes&&("function"==typeof fcn_updateFollowsView&&fcn_updateFollowsView(),"function"==typeof fcn_updateCheckmarksView&&fcn_updateCheckmarksView(),"function"==typeof fcn_updateRemindersView&&fcn_updateRemindersView())}));function fct_spoiler(e){e.classList.toggle("_open")}function fcn_revealCommentImage(e){const t=e.parentElement.querySelector("img");t.src=t.dataset.src,e.remove()}function fcn_contactFormSubmit(e){const t=e.closest("form"),n=new FormData(t),o={action:"fictioneer_ajax_submit_contact_form"};if(t.reportValidity()&&(e.disabled=!0,e.innerHTML=e.dataset.disabled,!(Date.now(){n.success?(t.querySelector("textarea").value="",e.innerHTML=e.dataset.done,fcn_showNotification(n.data.success,3,"success")):n.data.error&&(e.disabled=!1,e.innerHTML=e.dataset.enabled,fcn_showNotification(n.data.error,5,"warning"))})).catch((t=>{t.status&&t.statusText&&(fcn_showNotification(`${t.status}: ${t.statusText}`,5,"warning"),e.disabled=!1,e.innerHTML=e.dataset.enabled)})).then((()=>{t.classList.remove("ajax-in-progress")}))}}fcn_cardLists.length&&fcn_cardLists.forEach((e=>{fcn_cardListMutationObserver.observe(e,{childList:!0,subtree:!0})})),_$$(".chapter-group__name").forEach((e=>{e.addEventListener("click",(e=>{var t=e.currentTarget.closest(".chapter-group"),n=t.querySelector(".chapter-group__list"),o=!t.classList.contains("_closed");n.style.height=`${n.scrollHeight}px`,setTimeout((()=>{t.classList.toggle("_closed",o)}),10)})),e.closest(".chapter-group").querySelector(".chapter-group__list").addEventListener("transitionend",(e=>{const t=e.currentTarget.closest(".chapter-group"),n=t.querySelector(".chapter-group__list");n.style.height="",n.querySelectorAll("a, button, label, input:not([hidden])").forEach((e=>{e.tabIndex=t.classList.contains("_closed")?"-1":"0"}))}))})),_$(".fictioneer-comments")?.addEventListener("click",(e=>{e.target?.classList.contains("consent-button")&&fcn_revealCommentImage(e.target)})),_$$(".fcn-contact-form").forEach((e=>{e.querySelector(".fcn-contact-form__submit").addEventListener("click",(e=>{fcn_contactFormSubmit(e.currentTarget)}))})),fcn_theBody.querySelectorAll(".modal-toggle").forEach((e=>{e.addEventListener("change",(e=>{if(e.currentTarget.checked){const t=e.currentTarget.nextElementSibling.querySelector('[tabindex="0"]');t?.focus(),t?.blur()}else fcn_theBody.classList.contains("user-is-tabbing")&&fcn_theSite.querySelector(`label[for="${e.currentTarget.id}"]`)?.focus()}))})),fcn_theBody.addEventListener("keydown",(e=>{let t=document.activeElement.closest('[tabindex="0"]:not(a, input, button, select)');if(["BUTTON","A","INPUT","SELECT"].includes(document.activeElement.tagName)&&(t=null),t&&(32!=e.keyCode&&13!=e.keyCode||(e.preventDefault(),t.click())),27==e.keyCode){_$$(".modal-toggle:checked").forEach((e=>{e.checked=!1,e.dispatchEvent(new Event("change"))}));const e=_$(".lightbox.show");if(e)return void e.querySelector(".lightbox__close").click();const t=_$(".selected-paragraph #button-close-paragraph-tools");if(t)return void t.click();const n=_$("#tts-interface:not(.hidden)");if(n){if(n.classList.contains("playing")){const e=_$$$("button-tts-pause");e?.click(),e?.focus(),e?.blur()}else _$$$("button-tts-stop").click();return}}}));class FCN_KeywordInput{constructor(e){this.input=e,this.operator=e.closest(".keyword-input").querySelector(".keyword-input__operator input"),this.inputWrapper=e.closest(".keyword-input__input-wrapper"),this.block=e.closest(".keyword-input"),this.form=this.block.closest(".search-form"),this.collection=this.block.querySelector(".keyword-input__collection"),this.suggestionList=this.block.querySelector(".keyword-input__suggestion-list"),this.tabSuggestion=this.block.querySelector(".keyword-input__tab-suggestion"),this.allowText=this.form.querySelector(".allow-list")?.innerText??"{}",this.allowList=JSON.parse(this.allowText),this.hints=this.block.querySelector(".keyword-input__hints"),this.noHint=this.block.querySelector(".keyword-input__no-suggestions"),this.keywords=this.collection.value.length>0?this.collection.value.split(","):[],this.bindEvents(),this.resize(),this.filterSuggestions()}resize(){fcn_resizeInput(this.input,this.tabSuggestion.innerText.length>0?this.tabSuggestion.innerText.length:this.input.value.length)}reset(){this.keywords=[],this.block.querySelectorAll(".node").forEach((e=>{e.remove()})),this.block.querySelectorAll(".keyword-input__operator > input").forEach((e=>{e.checked=!1})),this.input.value="",this.updateCollection(),this.filterSuggestions(),this.resize()}encode(e){return encodeURIComponent(e.toLowerCase()).replace(/'/g,"%27")}filterSuggestions(){const e=this.input.value.toLowerCase();let t=0,n="";""==e?this.suggestionList.querySelectorAll(".keyword-button").forEach((e=>{e.hidden=!0})):this.suggestionList.querySelectorAll(".keyword-button").forEach((o=>{const s=o.innerText.toLowerCase();s.includes(e)&&this.keywords.indexOf(s)<0?(o.hidden=!1,t++,""==n&&s.startsWith(e)&&(n=s)):o.hidden=!0})),this.hints.querySelectorAll(".keyword-button").forEach((e=>{this.keywords.indexOf(e.value.toLowerCase())>-1?e.hidden=!0:e.hidden=!1})),this.tabSuggestion.innerHTML=n,this.hints.hidden=!(""==e),this.noHint.hidden=!(""!=e&&t<1)}addNode(e=null){const t=e??this.input.value.replace(",",""),n=this.allowList[this.encode(t)];if(!n||this.keywords.indexOf(n)>-1)return;this.keywords.push(n);const o=document.createElement("div");o.innerHTML=`${t}`,o.classList.add("node"),o.dataset.value=n,this.inputWrapper.parentNode.insertBefore(o,this.inputWrapper),this.input.value="",this.updateCollection(),this.filterSuggestions(),this.resize()}removeNodeByValue(e){this.block.querySelector(`[data-value="${e}"]`)?.remove(),this.keywords.splice(this.keywords.indexOf(e),1),this.updateCollection(),this.filterSuggestions(),this.resize()}updateCollection(){this.collection.value=this.keywords.join(","),this.block.classList.toggle("_empty",""===this.collection.value),this.form.querySelector(".search-form__current").innerHTML=""}bindEvents(){this.operator&&this.operator.addEventListener("change",(e=>{e.currentTarget.closest("label").ariaChecked=e.currentTarget.checked})),this.input.addEventListener("input",(e=>{e.currentTarget.value.includes(",")&&this.addNode(),this.block.classList.toggle("_empty",""===e.currentTarget.value),this.filterSuggestions(),this.resize()})),this.input.addEventListener("keydown",(e=>{9!=e.keyCode&&13!=e.keyCode||""!=this.tabSuggestion.innerText&&(e.preventDefault(),this.input.value=this.tabSuggestion.innerText,this.addNode()),27==e.keyCode&&(this.input.value="",this.tabSuggestion.innerHTML="",document.activeElement.blur()),8==e.keyCode&&""==this.input.value&&this.keywords.length>0&&this.removeNodeByValue(this.keywords.slice(-1))})),this.input.addEventListener("blur",(()=>{const e=this.allowList[this.encode(this.input.value)];this.blurTimeout=e?setTimeout((()=>{this.addNode()}),150):setTimeout((()=>{this.input.value="",this.tabSuggestion.innerHTML="",this.filterSuggestions(),this.resize()}),150)})),this.block.addEventListener("click",(e=>{e.target.closest(".node-delete")&&(e.preventDefault(),this.removeNodeByValue(e.target.closest(".node").dataset.value))})),this.block.querySelectorAll(".keyword-button").forEach((e=>{e.addEventListener("click",(e=>{clearTimeout(this.blurTimeout),this.addNode(e.currentTarget.innerText)}))}))}}function fcn_handleTabInput(e){9==e.keyCode&&(fcn_theBody.classList.add("user-is-tabbing"),window.removeEventListener("keydown",fcn_handleTabInput),window.addEventListener("mousedown",fcn_handleMouseInput))}function fcn_handleMouseInput(){fcn_theBody.classList.remove("user-is-tabbing"),window.removeEventListener("mousedown",fcn_handleMouseInput),window.addEventListener("keydown",fcn_handleTabInput)}function fcn_popupPosition(){_$$(".popup-menu-toggle.last-clicked .popup-menu:not(._fixed-position)").forEach((e=>{if("none"===window.getComputedStyle(e).display)return;const t=fcn_detectScreenCollision(e);t&&0===t.length||(t.includes("top")?(e.classList.remove("_top"),e.classList.add("_bottom")):t.includes("bottom")&&(e.classList.remove("_bottom"),e.classList.add("_top")))}))}function fcn_markCurrentMenuItem(){_$$(`.menu-item > [data-nav-object-id="${fcn_theBody.dataset.postId}"]`).forEach((e=>{e.setAttribute("aria-current","page"),e.closest(".menu-item").classList.add("current-menu-item")}))}_$$(".search-form").forEach((e=>{const t=[];e.classList.contains("_simple")||(e.querySelectorAll(".keyword-input__input").forEach((e=>{t.push(new FCN_KeywordInput(e))})),e.querySelector(".allow-list")?.remove(),e.addEventListener("change",(t=>{t.target.classList.contains("search-form__advanced-control")||t.target.classList.contains("search-form__string")||(e.querySelector(".search-form__current").innerHTML="")})),e.querySelectorAll(".reset").forEach((n=>{n.addEventListener("click",(o=>{t.forEach((e=>{e.reset()})),e.querySelector("input[name=s]").value="",e.querySelector("select[name=post_type]").value="any",e.querySelector("select[name=sentence]").value="0",e.querySelector("select[name=orderby]").value="modified",e.querySelector("select[name=order]").value="desc",e.querySelector(".search-form__current").innerHTML="",fcn_showNotification(n.dataset.reset,2)}))})))})),_$$(".search-form__advanced-toggle").forEach((e=>{e.addEventListener("click",(e=>{const t=e.currentTarget.closest("form");t.dataset.advanced="true"==t.dataset.advanced?"false":"true"}))})),window.addEventListener("keydown",fcn_handleTabInput),window.addEventListener("scroll.rAF",fcn_throttle(fcn_popupPosition,250)),_$$(".modal-toggle").forEach((e=>{e.addEventListener("change",(e=>{const t=_$$$(e.currentTarget.dataset.target);t.classList.toggle("_open",e.currentTarget.checked);const n=t.querySelector(".close");n?.focus(),n?.blur()}))})),fcn_theBody.addEventListener("click",(e=>{const t=e.target.closest("[href]"),n=t?.getAttribute("href");if(t&&"A"===t.tagName&&n.startsWith("#")&&n.length>1&&"#respond"!==n){const o=n.replace("#",""),s=_$$(`[name="${o}"], #${o}`)[0],i=t.closest(".comment._story-comment");if(i){const e=i.querySelector(".fictioneer-comment__link").href+n;e&&(window.location.href=e)}s&&(e.preventDefault(),s.scrollIntoView({behavior:"smooth",block:t.dataset?.block??"start"}))}})),fcn_markCurrentMenuItem();
\ No newline at end of file
diff --git a/js/comments.min.js b/js/comments.min.js
index 3b84742a..eff0c75c 100644
--- a/js/comments.min.js
+++ b/js/comments.min.js
@@ -1,3 +1,3 @@
function fcn_addJSTrap(){const e=document.querySelector(".comment-form");e&&e.appendChild(fcn_html`
- `)}function fcn_moderateComment(e,t){const n=_$$$(`comment-${e}`),o=n.querySelector(".mod-menu-toggle-icon");n.classList.contains("ajax-in-progress")||(n.classList.add("ajax-in-progress"),"trash"!=t&&"spam"!=t||(n.style.height=n.clientHeight+"px"),fcn_ajaxPost({action:"fictioneer_ajax_moderate_comment",operation:t,id:e}).then((e=>{if(e.success)switch(e.data.operation){case"sticky":n.classList.add("_sticky");break;case"unsticky":n.classList.remove("_sticky");break;case"approve":n.classList.remove("_unapproved");break;case"unapprove":n.classList.add("_unapproved");break;case"open":n.classList.remove("_closed");break;case"close":n.classList.add("_closed");break;case"trash":case"spam":n.style.overflow="hidden",n.style.height="0",n.style.margin="0",n.style.opacity="0"}else o.classList="fa-solid fa-triangle-exclamation mod-menu-toggle-icon",o.style.color="var(--warning)",n.querySelector(".popup-menu-toggle").style.opacity="1",e.data.error&&fcn_showNotification(e.data.error,5,"warning")})).catch((e=>{o.classList="fa-solid fa-triangle-exclamation mod-menu-toggle-icon",o.style.color="var(--warning)",n.querySelector(".popup-menu-toggle").style.opacity="1",e.status&&e.statusText?fcn_showNotification(`${e.status}: ${e.statusText}`,5,"warning"):e&&fcn_showNotification(e,5,"warning")})).then((()=>{n.classList.remove("ajax-in-progress"),fcn_lastClicked&&fcn_lastClicked.classList.remove("last-clicked"),fcn_lastClicked=null})))}function fcn_addModerationEvents(){_$$(".button-ajax-moderate-comment").forEach((e=>{e.addEventListener("click",(e=>{fcn_moderateComment(e.currentTarget.dataset.id,e.currentTarget.dataset.action)}))}))}function fcn_addCommentMouseleaveEvents(){_$$(".fictioneer-comment__container").forEach((e=>{e.addEventListener("mouseleave",(e=>{fcn_lastClicked&&fcn_lastClicked.classList.remove("last-clicked"),fcn_lastClicked=null,e.stopPropagation()}))}))}function fcn_flagComment(e){if(!fcn_isLoggedIn)return;const t=e.closest(".fictioneer-comment"),n=t.querySelector(".fictioneer-report-comment-button");t.classList.contains("ajax-in-progress")||(t.classList.add("ajax-in-progress"),fcn_ajaxPost({action:"fictioneer_ajax_report_comment",id:t.dataset.id,dubious:n.classList.contains("_dubious")}).then((e=>{e.success?(n.classList.toggle("on",e.data.flagged),n.classList.remove("_dubious"),e.data.resync&&fcn_showNotification(e.data.resync)):e.data?.error&&fcn_showNotification(e.data.error,5,"warning")})).catch((e=>{e.status&&e.statusText&&fcn_showNotification(`${e.status}: ${e.statusText}`,5,"warning")})).then((()=>{t.classList.remove("ajax-in-progress")})))}function fcn_revealCommentFormInputs(e){e.closest("form").querySelectorAll(".fictioneer-respond__form-actions, .fictioneer-respond__form-bottom").forEach((e=>{e.classList.remove("hidden")})),e.removeAttribute("onclick")}function fcn_addCommentFormEvents(){_$$$("comment")?.addEventListener("focus",(e=>{fcn_revealCommentFormInputs(e.currentTarget)}),{once:!0})}function fcn_textareaAdjust(e){e.style.height="auto",e.style.height=e.scrollHeight+"px"}function fcn_addTextareaEvents(){_$$(".adaptive-textarea").forEach((e=>{e.addEventListener("input",(e=>{fcn_textareaAdjust(e.currentTarget)}))}))}function fcn_addPrivateToggleEvents(){_$$$("fictioneer-private-comment-toggle")?.addEventListener("change",(e=>{_$$$("respond")?.classList.toggle("_private",e.currentTarget.checked)}))}function fcn_wrapInTag(e,t,n={}){const o=n.href?' href="'+n.href+'" target="_blank" rel="nofollow noreferrer noopener"':"",c=n.shortcode?["[","]"]:["<",">"],a=e.selectionStart,i=e.selectionEnd,s=c[0]+t+o+c[1],r=c[0]+"/"+t+c[1],m=s+e.value.substring(a,i)+r;e.value=e.value.substring(0,a)+m+e.value.substring(i,e.value.length),e.setSelectionRange(a+s.length,i+s.length),e.focus()}function fcn_bindAJAXCommentSubmit(){fcn_theRoot.dataset.ajaxSubmit&&_$$$("commentform")?.addEventListener("submit",(e=>{if(e.preventDefault(),Date.now()1,o.classList.toggle("_error",!u),s&&(g=s.checked,s.classList.toggle("_error",!g)),a&&a.value.length>0&&(_=/\S+@\S+\.\S+/.test(a.value),a.classList.toggle("_error",!_)),!u||!g||!_)return!1;t.classList.add("ajax-in-progress"),n.disabled=!0,n.value=n.dataset.disabled;const p={action:"fictioneer_ajax_submit_comment",post_id:_$$$("comment_post_ID").value,content:o.value,private_comment:l?.checked??0,notification:f?.checked??0,cookie_consent:i?.checked??0,privacy_consent:s?.checked??0,unfiltered_html:_$$$("_wp_unfiltered_html_comment_disabled")?.value??"",depth:d?parseInt(d.dataset.depth)+1:1,fictioneer_comment_validator:r?.value??0};m&&(p.parent_id=m),a?.value&&(p.email=a?.value),c?.value&&(p.author=c?.value),fcn_ajaxPost(p).then((e=>{if(_$$$("comment-submit-error-notice")?.remove(),e.success&&e.data?.comment){let t=_$(".commentlist"),n="insertBefore";if(t&&!d&&t.firstElementChild){let e=null;if(t.firstElementChild.classList.contains("_sticky"))for(e=t.firstElementChild,t=e,n="insertAfter";e.nextElementSibling&&e.nextElementSibling.classList.contains("_sticky");)e=t.nextElementSibling,t=e}if(t||(t=document.createElement("ol"),t.classList="fictioneer-comments__list commentlist",_$$$("comments").appendChild(t),n="append"),d&&(t=d.querySelector(".children"),n="append",!t)){const e=document.createElement("ol");d.appendChild(e),t=e}let c=document.createElement("div");switch(c.innerHTML=e.data.comment,c=c.firstChild,n){case"append":t.appendChild(c);break;case"insertBefore":t.insertBefore(c,t.firstChild);break;case"insertAfter":t.nextSibling?t.parentNode.insertBefore(c,t.nextSibling):t.parentNode.appendChild(c)}fcn_addModerationEvents(),fcn_addCommentMouseleaveEvents(),"0"!=_$$$("comment_parent").value&&_$$$("cancel-comment-reply-link").click(),o.value="",o.style.height="";const a=window.location.protocol+"//"+window.location.host+window.location.pathname;let i="";e.data.commentcode&&(i+=`?commentcode=${e.data.commentcode}`),history.pushState({path:a},"",a+i+`#comment-${e.data.comment_id}`),c.scrollIntoView({behavior:"smooth"})}else t.insertBefore(fcn_buildErrorNotice(e.data?.error??__("Error","fictioneer"),"comment-submit-error-notice",!1),t.firstChild)})).catch((e=>{_$$$("comment-submit-error-notice")?.remove(),t.insertBefore(fcn_buildErrorNotice(`${e.status}: ${e.statusText}`,"comment-submit-error-notice"),t.firstChild)})).then((()=>{t.classList.remove("ajax-in-progress"),n.disabled=!1,n.value=n.dataset.enabled}))}))}fcn_addJSTrap(),fcn_addModerationEvents(),fcn_addCommentMouseleaveEvents(),fcn_addCommentFormEvents(),fcn_addTextareaEvents(),fcn_addPrivateToggleEvents(),_$(".comment-section")?.addEventListener("click",(e=>{const t=e.target.closest("[data-bbcode]");t&&fcn_wrapInTag(_$$$("comment"),t.dataset.bbcode,{shortcode:!0})})),_$(".comment-section")?.addEventListener("keydown",(e=>{if(_$(".fictioneer-comment-toolbar")&&"TEXTAREA"===document.activeElement.tagName&&(e.ctrlKey||e.metaKey)){const t=e.key.toLowerCase();if(["b","i","s","q","h","l"].includes(t)){e.preventDefault();const n={q:"quote",h:"spoiler",l:"link"};fcn_wrapInTag(document.activeElement,n[t]||t,{shortcode:!0})}}})),fcn_bindAJAXCommentSubmit();const fcn_commentEditActionsTemplate=_$(".comment-edit-actions-template");var fcn_commentEditUndos={};function fcn_triggerInlineCommentEdit(e){const t=e.closest(".fictioneer-comment");if(t){const e=t.querySelector(".fictioneer-comment__content"),n=t.querySelector(".fictioneer-comment__edit"),o=t.querySelector(".comment-inline-edit-content");n.appendChild(fcn_commentEditActionsTemplate.content.cloneNode(!0)),fcn_commentEditUndos[t.id]=o.value,t.classList.add("_editing"),e.hidden=!0,n.hidden=!1,o.style.height=o.scrollHeight+"px"}}function fcn_submitInlineCommentEdit(e){const t=e.closest(".fictioneer-comment"),n=t.querySelector(".fictioneer-comment__edit"),o=t.querySelector(".comment-inline-edit-content").value;let c=t.querySelector(".fictioneer-comment__edit-note");o!=fcn_commentEditUndos[t.id]?t&&(n.classList.add("ajax-in-progress"),e.innerHTML=e.dataset.disabled,e.disabled=!0,fcn_ajaxPost({action:"fictioneer_ajax_edit_comment",comment_id:t.id.replace("comment-",""),content:o}).then((e=>{if(e.success){const n=t.querySelector(".fictioneer-comment__content");n.innerHTML=e.data.content,fcn_restoreComment(t,!1,e.data.raw),c||(c=document.createElement("div")),c.classList.add("fictioneer-comment__edit-note"),c.innerHTML=e.data.edited,n.parentNode.appendChild(c)}else fcn_restoreComment(t,!0),e.data?.error&&fcn_showNotification(e.data.error,5,"warning")})).catch((e=>{fcn_restoreComment(t,!0),e.status&&e.statusText&&fcn_showNotification(`${e.status}: ${e.statusText}`,5,"warning")})).then((()=>{n.classList.remove("ajax-in-progress"),e.innerHTML=e.dataset.enabled,e.disabled=!1}))):fcn_restoreComment(t,!0)}function fcn_cancelInlineCommentEdit(e){const t=e.closest(".fictioneer-comment");t&&fcn_restoreComment(t,!0)}function fcn_restoreComment(e,t=!1,n=null){e.querySelector(".fictioneer-comment__content").hidden=!1,e.querySelector(".fictioneer-comment__edit").hidden=!0,e.querySelector(".fictioneer-comment__edit-actions")?.remove(),e.classList.remove("_editing"),t&&fcn_commentEditUndos[e.id]?e.querySelector(".comment-inline-edit-content").value=fcn_commentEditUndos[e.id]:n&&(e.querySelector(".comment-inline-edit-content").value=n)}function fcn_revealEditButton(){let e=parseInt(fcn_theRoot.dataset.editTime);e&&(e=e>0?6e4*e:e,_$$(".fictioneer-comment[data-fingerprint]").forEach((t=>{if(fcn_matchFingerprint(t.dataset.fingerprint)){if(e>0&&parseInt(t.dataset.timestamp)+e{if(fcn_matchFingerprint(e.dataset.fingerprint)){const t=e.querySelector(".fictioneer-comment__delete");t&&(t.hidden=!1)}}))}function fcn_deleteMyComment(e){if(!fcn_isLoggedIn)return;const t=prompt(e.dataset.dialogMessage);if(!t||t.toLowerCase()!=e.dataset.dialogConfirm.toLowerCase())return;const n=e.closest(".fictioneer-comment");n.classList.contains("ajax-in-progress")||(n.classList.add("ajax-in-progress"),fcn_ajaxPost(payload={action:"fictioneer_ajax_delete_my_comment",comment_id:n.dataset.id}).then((e=>{e.success?(n.classList.add("_deleted"),n.querySelector(".fictioneer-comment__container").innerHTML=e.data.html):e.data.error&&fcn_showNotification(e.data.error,5,"warning")})).catch((e=>{e.status&&e.statusText&&fcn_showNotification(`${e.status}: ${e.statusText}`,5,"warning")})).then((()=>{n.classList.remove("ajax-in-progress")})))}document.addEventListener("fcnUserDataReady",(()=>{fcn_revealEditButton()})),document.addEventListener("fcnUserDataReady",(()=>{fcn_revealDeleteButton()}));const fcn_ajaxCommentForm=_$$$("ajax-comment-form-target");function fcn_getCommentForm(){let e;fcn_ajaxGet({action:"fictioneer_ajax_get_comment_form",post_id:_$$$("comments").dataset.postId}).then((t=>{if(t.success){const e=document.createElement("div");e.innerHTML=t.data.html;const n=e.querySelector("#comment_post_ID"),o=e.querySelector("#cancel-comment-reply-link"),c=e.querySelector(".logout-link");n&&(n.value=t.data.postId),o&&(o.href="#respond"),c&&(c.href=_$$$("comments").dataset.logoutUrl),fcn_ajaxCommentForm.innerHTML=e.innerHTML,e.remove(),fcn_addTextareaEvents(),fcn_addCommentFormEvents(),fcn_addPrivateToggleEvents(),fcn_theRoot.dataset.ajaxSubmit&&fcn_bindAJAXCommentSubmit(),fcn_addJSTrap()}else e=fcn_buildErrorNotice(t.data.error)})).catch((t=>{e=fcn_buildErrorNotice(t)})).then((()=>{fcn_ajaxCommentForm.classList.remove("comments-skeleton"),e&&(fcn_ajaxCommentForm.innerHTML="",fcn_ajaxCommentForm.appendChild(e))}))}fcn_ajaxCommentForm&&(fcn_theRoot.dataset.ajaxNonce&&!_$$$("fictioneer-ajax-nonce")?fcn_theRoot.addEventListener("nonceReady",(()=>{fcn_getCommentForm()})):fcn_getCommentForm()),_$(".fictioneer-comments")?.addEventListener("click",(e=>{const t=e.target.closest("[data-click]"),n=t?.dataset.click;if(n)switch(n){case"submit-inline-comment-edit":fcn_submitInlineCommentEdit(t);break;case"cancel-inline-comment-edit":fcn_cancelInlineCommentEdit(t);break;case"trigger-inline-comment-edit":fcn_triggerInlineCommentEdit(t);break;case"delete-my-comment":fcn_deleteMyComment(t);break;case"flag-comment":fcn_flagComment(t)}}));
\ No newline at end of file
+ `)}function fcn_moderateComment(e,t){const n=_$$$(`comment-${e}`),o=n.querySelector(".mod-menu-toggle-icon");n.classList.contains("ajax-in-progress")||(n.classList.add("ajax-in-progress"),"trash"!=t&&"spam"!=t||(n.style.height=n.clientHeight+"px"),fcn_ajaxPost({action:"fictioneer_ajax_moderate_comment",operation:t,id:e}).then((e=>{if(e.success)switch(e.data.operation){case"sticky":n.classList.add("_sticky");break;case"unsticky":n.classList.remove("_sticky");break;case"approve":n.classList.remove("_unapproved");break;case"unapprove":n.classList.add("_unapproved");break;case"open":n.classList.remove("_closed");break;case"close":n.classList.add("_closed");break;case"trash":case"spam":n.style.overflow="hidden",n.style.height="0",n.style.margin="0",n.style.opacity="0"}else o.classList="fa-solid fa-triangle-exclamation mod-menu-toggle-icon",o.style.color="var(--warning)",n.querySelector(".popup-menu-toggle").style.opacity="1",e.data.error&&fcn_showNotification(e.data.error,5,"warning")})).catch((e=>{o.classList="fa-solid fa-triangle-exclamation mod-menu-toggle-icon",o.style.color="var(--warning)",n.querySelector(".popup-menu-toggle").style.opacity="1",e.status&&e.statusText?fcn_showNotification(`${e.status}: ${e.statusText}`,5,"warning"):e&&fcn_showNotification(e,5,"warning")})).then((()=>{n.classList.remove("ajax-in-progress"),fcn_lastClicked&&fcn_lastClicked.classList.remove("last-clicked"),fcn_lastClicked=null})))}function fcn_addModerationEvents(){_$$(".button-ajax-moderate-comment").forEach((e=>{e.addEventListener("click",(e=>{fcn_moderateComment(e.currentTarget.dataset.id,e.currentTarget.dataset.action)}))}))}function fcn_addCommentMouseleaveEvents(){_$$(".fictioneer-comment__container").forEach((e=>{e.addEventListener("mouseleave",(e=>{fcn_lastClicked&&fcn_lastClicked.classList.remove("last-clicked"),fcn_lastClicked=null,e.stopPropagation()}))}))}function fcn_flagComment(e){if(!fcn_isLoggedIn)return;const t=e.closest(".fictioneer-comment"),n=t.querySelector(".fictioneer-report-comment-button");t.classList.contains("ajax-in-progress")||(t.classList.add("ajax-in-progress"),fcn_ajaxPost({action:"fictioneer_ajax_report_comment",id:t.dataset.id,dubious:n.classList.contains("_dubious")}).then((e=>{e.success?(n.classList.toggle("on",e.data.flagged),n.classList.remove("_dubious"),e.data.resync&&fcn_showNotification(e.data.resync)):e.data?.error&&fcn_showNotification(e.data.error,5,"warning")})).catch((e=>{e.status&&e.statusText&&fcn_showNotification(`${e.status}: ${e.statusText}`,5,"warning")})).then((()=>{t.classList.remove("ajax-in-progress")})))}function fcn_revealCommentFormInputs(e){e.closest("form").querySelectorAll(".fictioneer-respond__form-actions, .fictioneer-respond__form-bottom").forEach((e=>{e.classList.remove("hidden")})),e.removeAttribute("onclick")}function fcn_addCommentFormEvents(){_$$$("comment")?.addEventListener("focus",(e=>{fcn_revealCommentFormInputs(e.currentTarget)}),{once:!0})}function fcn_textareaAdjust(e){e.style.height="auto",e.style.height=e.scrollHeight+"px"}function fcn_addTextareaEvents(){_$$(".adaptive-textarea").forEach((e=>{e.addEventListener("input",(e=>{fcn_textareaAdjust(e.currentTarget)}))}))}function fcn_addPrivateToggleEvents(){_$$$("fictioneer-private-comment-toggle")?.addEventListener("change",(e=>{_$$$("respond")?.classList.toggle("_private",e.currentTarget.checked)}))}function fcn_wrapInTag(e,t,n={}){const o=n.href?' href="'+n.href+'" target="_blank" rel="nofollow noreferrer noopener"':"",c=n.shortcode?["[","]"]:["<",">"],a=e.selectionStart,i=e.selectionEnd,s=c[0]+t+o+c[1],r=c[0]+"/"+t+c[1],m=s+e.value.substring(a,i)+r;e.value=e.value.substring(0,a)+m+e.value.substring(i,e.value.length),e.setSelectionRange(a+s.length,i+s.length),e.focus()}function fcn_bindAJAXCommentSubmit(){fcn_theRoot.dataset.ajaxSubmit&&_$$$("commentform")?.addEventListener("submit",(e=>{if(e.preventDefault(),Date.now()1,o.classList.toggle("_error",!u),s&&(g=s.checked,s.classList.toggle("_error",!g)),a&&a.value.length>0&&(_=/\S+@\S+\.\S+/.test(a.value),a.classList.toggle("_error",!_)),!u||!g||!_)return!1;t.classList.add("ajax-in-progress"),n.disabled=!0,n.value=n.dataset.disabled;const p={action:"fictioneer_ajax_submit_comment",post_id:_$$$("comment_post_ID").value,content:o.value,private_comment:l?.checked??0,notification:f?.checked??0,cookie_consent:i?.checked??0,privacy_consent:s?.checked??0,unfiltered_html:_$$$("_wp_unfiltered_html_comment_disabled")?.value??"",depth:d?parseInt(d.dataset.depth)+1:1,fictioneer_comment_validator:r?.value??0};m&&(p.parent_id=m),a?.value&&(p.email=a?.value),c?.value&&(p.author=c?.value),fcn_ajaxPost(p).then((e=>{if(_$$$("comment-submit-error-notice")?.remove(),e.success&&e.data?.comment){let t=_$(".commentlist"),n="insertBefore";if(t&&!d&&t.firstElementChild){let e=null;if(t.firstElementChild.classList.contains("_sticky"))for(e=t.firstElementChild,t=e,n="insertAfter";e.nextElementSibling&&e.nextElementSibling.classList.contains("_sticky");)e=t.nextElementSibling,t=e}if(t||(t=document.createElement("ol"),t.classList="fictioneer-comments__list commentlist",_$$$("comments").appendChild(t),n="append"),d&&(t=d.querySelector(".children"),n="append",!t)){const e=document.createElement("ol");d.appendChild(e),t=e}let c=document.createElement("div");switch(c.innerHTML=e.data.comment,c=c.firstChild,n){case"append":t.appendChild(c);break;case"insertBefore":t.insertBefore(c,t.firstChild);break;case"insertAfter":t.nextSibling?t.parentNode.insertBefore(c,t.nextSibling):t.parentNode.appendChild(c)}fcn_addModerationEvents(),fcn_addCommentMouseleaveEvents(),"0"!=_$$$("comment_parent").value&&_$$$("cancel-comment-reply-link").click(),o.value="",o.style.height="";const a=window.location.protocol+"//"+window.location.host+window.location.pathname;let i="";e.data.commentcode&&(i+=`?commentcode=${e.data.commentcode}`),history.pushState({path:a},"",a+i+`#comment-${e.data.comment_id}`),c.scrollIntoView({behavior:"smooth"})}else t.insertBefore(fcn_buildErrorNotice(e.data?.error??__("Error","fictioneer"),"comment-submit-error-notice",!1),t.firstChild)})).catch((e=>{_$$$("comment-submit-error-notice")?.remove(),t.insertBefore(fcn_buildErrorNotice(`${e.status}: ${e.statusText}`,"comment-submit-error-notice"),t.firstChild)})).then((()=>{t.classList.remove("ajax-in-progress"),n.disabled=!1,n.value=n.dataset.enabled}))}))}fcn_addJSTrap(),fcn_addModerationEvents(),fcn_addCommentMouseleaveEvents(),fcn_addCommentFormEvents(),fcn_addTextareaEvents(),fcn_addPrivateToggleEvents(),_$(".comment-section")?.addEventListener("click",(e=>{const t=e.target.closest("[data-bbcode]");t&&fcn_wrapInTag(_$$$("comment"),t.dataset.bbcode,{shortcode:!0})})),_$(".comment-section")?.addEventListener("keydown",(e=>{if(_$(".fictioneer-comment-toolbar")&&"TEXTAREA"===document.activeElement.tagName&&(e.ctrlKey||e.metaKey)){const t=e.key.toLowerCase();if(["b","i","s","q","h","l"].includes(t)){e.preventDefault();const n={q:"quote",h:"spoiler",l:"link"};fcn_wrapInTag(document.activeElement,n[t]||t,{shortcode:!0})}}})),fcn_bindAJAXCommentSubmit();const fcn_commentEditActionsTemplate=_$(".comment-edit-actions-template");var fcn_commentEditUndos={};function fcn_triggerInlineCommentEdit(e){const t=e.closest(".fictioneer-comment");if(t){const e=t.querySelector(".fictioneer-comment__content"),n=t.querySelector(".fictioneer-comment__edit"),o=t.querySelector(".comment-inline-edit-content");n.appendChild(fcn_commentEditActionsTemplate.content.cloneNode(!0)),fcn_commentEditUndos[t.id]=o.value,t.classList.add("_editing"),e.hidden=!0,n.hidden=!1,o.style.height=o.scrollHeight+"px"}}function fcn_submitInlineCommentEdit(e){const t=e.closest(".fictioneer-comment"),n=t.querySelector(".fictioneer-comment__edit"),o=t.querySelector(".comment-inline-edit-content").value;let c=t.querySelector(".fictioneer-comment__edit-note");o!=fcn_commentEditUndos[t.id]?t&&(n.classList.add("ajax-in-progress"),e.innerHTML=e.dataset.disabled,e.disabled=!0,fcn_ajaxPost({action:"fictioneer_ajax_edit_comment",comment_id:t.id.replace("comment-",""),content:o}).then((e=>{if(e.success){const n=t.querySelector(".fictioneer-comment__content");n.innerHTML=e.data.content,fcn_restoreComment(t,!1,e.data.raw),c||(c=document.createElement("div")),c.classList.add("fictioneer-comment__edit-note"),c.innerHTML=e.data.edited,n.parentNode.appendChild(c)}else fcn_restoreComment(t,!0),e.data?.error&&fcn_showNotification(e.data.error,5,"warning")})).catch((e=>{fcn_restoreComment(t,!0),e.status&&e.statusText&&fcn_showNotification(`${e.status}: ${e.statusText}`,5,"warning")})).then((()=>{n.classList.remove("ajax-in-progress"),e.innerHTML=e.dataset.enabled,e.disabled=!1}))):fcn_restoreComment(t,!0)}function fcn_cancelInlineCommentEdit(e){const t=e.closest(".fictioneer-comment");t&&fcn_restoreComment(t,!0)}function fcn_restoreComment(e,t=!1,n=null){e.querySelector(".fictioneer-comment__content").hidden=!1,e.querySelector(".fictioneer-comment__edit").hidden=!0,e.querySelector(".fictioneer-comment__edit-actions")?.remove(),e.classList.remove("_editing"),t&&fcn_commentEditUndos[e.id]?e.querySelector(".comment-inline-edit-content").value=fcn_commentEditUndos[e.id]:n&&(e.querySelector(".comment-inline-edit-content").value=n)}function fcn_revealEditButton(){let e=parseInt(fcn_theRoot.dataset.editTime);e&&(e=e>0?6e4*e:e,_$$(".fictioneer-comment[data-fingerprint]").forEach((t=>{if(fcn_matchFingerprint(t.dataset.fingerprint)){if(e>0&&parseInt(t.dataset.timestamp)+e{if(fcn_matchFingerprint(e.dataset.fingerprint)){const t=e.querySelector(".fictioneer-comment__delete");t&&(t.hidden=!1)}}))}function fcn_deleteMyComment(e){if(!fcn_isLoggedIn)return;const t=prompt(e.dataset.dialogMessage);if(!t||t.toLowerCase()!=e.dataset.dialogConfirm.toLowerCase())return;const n=e.closest(".fictioneer-comment");n.classList.contains("ajax-in-progress")||(n.classList.add("ajax-in-progress"),fcn_ajaxPost(payload={action:"fictioneer_ajax_delete_my_comment",comment_id:n.dataset.id}).then((e=>{e.success?(n.classList.add("_deleted"),n.querySelector(".fictioneer-comment__container").innerHTML=e.data.html):e.data.error&&fcn_showNotification(e.data.error,5,"warning")})).catch((e=>{e.status&&e.statusText&&fcn_showNotification(`${e.status}: ${e.statusText}`,5,"warning")})).then((()=>{n.classList.remove("ajax-in-progress")})))}document.addEventListener("fcnUserDataReady",(()=>{fcn_revealEditButton()})),document.addEventListener("fcnUserDataReady",(()=>{fcn_revealDeleteButton()}));const fcn_ajaxCommentForm=_$$$("ajax-comment-form-target");function fcn_getCommentForm(){let e;fcn_ajaxGet({action:"fictioneer_ajax_get_comment_form",post_id:_$$$("comments").dataset.postId}).then((t=>{if(t.success){const e=document.createElement("div");e.innerHTML=t.data.html;const n=e.querySelector("#comment_post_ID"),o=e.querySelector("#cancel-comment-reply-link"),c=e.querySelector(".logout-link");n&&(n.value=t.data.postId),o&&(o.href="#respond"),c&&(c.href=_$$$("comments").dataset.logoutUrl),fcn_ajaxCommentForm.innerHTML=e.innerHTML,e.remove(),fcn_addTextareaEvents(),fcn_addCommentFormEvents(),fcn_addPrivateToggleEvents(),fcn_theRoot.dataset.ajaxSubmit&&fcn_bindAJAXCommentSubmit(),fcn_addJSTrap()}else e=fcn_buildErrorNotice(t.data.error)})).catch((t=>{e=fcn_buildErrorNotice(t)})).then((()=>{fcn_ajaxCommentForm.classList.remove("comments-skeleton"),e&&(fcn_ajaxCommentForm.innerHTML="",fcn_ajaxCommentForm.appendChild(e))}))}fcn_ajaxCommentForm&&(fcn_theRoot.dataset.ajaxNonce?document.addEventListener("fcnAuthReady",(()=>{fcn_getCommentForm()})):fcn_getCommentForm()),_$(".fictioneer-comments")?.addEventListener("click",(e=>{const t=e.target.closest("[data-click]"),n=t?.dataset.click;if(n)switch(n){case"submit-inline-comment-edit":fcn_submitInlineCommentEdit(t);break;case"cancel-inline-comment-edit":fcn_cancelInlineCommentEdit(t);break;case"trigger-inline-comment-edit":fcn_triggerInlineCommentEdit(t);break;case"delete-my-comment":fcn_deleteMyComment(t);break;case"flag-comment":fcn_flagComment(t)}}));
\ No newline at end of file
diff --git a/js/follows.min.js b/js/follows.min.js
index f1006ad6..0abba13a 100644
--- a/js/follows.min.js
+++ b/js/follows.min.js
@@ -1 +1 @@
-const fcn_desktopFollowList=_$$$("follow-menu-scroll"),fcn_mobileFollowList=_$$$("mobile-menu-follows-list"),fcn_followsMenuItem=_$$$("follow-menu-button");var fcn_userFollowsTimeout,fcn_follows;function fcn_initializeFollows(o){const t=o.detail.data.follows;!1!==t&&(fcn_follows=t,fcn_updateFollowsView(),localStorage.removeItem("fcnBookshelfContent"))}function fcn_toggleFollow(o){const t=fcn_getUserData();if(fcn_follows&&t.follows){if(localStorage.removeItem("fcnBookshelfContent"),JSON.stringify(fcn_follows.data[o])!==JSON.stringify(t.follows.data[o]))return fcn_follows=t.follows,fcn_showNotification(__("Follows re-synchronized.","fictioneer")),void fcn_updateFollowsView();fcn_follows.data.hasOwnProperty(o)?delete fcn_follows.data[o]:fcn_follows.data[o]={story_id:parseInt(o),timestamp:Date.now()},t.follows.data[o]=fcn_follows.data[o],t.lastLoaded=0,fcn_setUserData(t),fcn_updateFollowsView(),clearTimeout(fcn_userFollowsTimeout),fcn_userFollowsTimeout=setTimeout((()=>{fcn_ajaxPost({action:"fictioneer_ajax_toggle_follow",fcn_fast_ajax:1,story_id:o,set:fcn_follows.data.hasOwnProperty(o)}).then((o=>{o.data.error&&fcn_showNotification(o.data.error,5,"warning")})).catch((o=>{o.status&&o.statusText&&fcn_showNotification(`${o.status}: ${o.statusText}`,5,"warning")}))}),fictioneer_ajax.post_debounce_rate)}}function fcn_updateFollowsView(){if(!fcn_getUserData().follows)return;_$$(".button-follow-story").forEach((o=>{o.classList.toggle("_followed",fcn_follows?.data.hasOwnProperty(o.dataset.storyId))})),_$$(".card").forEach((o=>{o.classList.toggle("has-follow",fcn_follows?.data.hasOwnProperty(o.dataset.storyId))}));const o=parseInt(fcn_follows.new)>0;_$$(".mark-follows-read, .follows-alert-number, .mobile-menu-button").forEach((t=>{t.classList.toggle("_new",o),o>0&&(t.dataset.newCount=fcn_follows.new)}))}function fcn_setupFollowsHTML(){fcn_followsMenuItem.classList.contains("_loaded")||fcn_ajaxGet({action:"fictioneer_ajax_get_follows_notifications",fcn_fast_ajax:1}).then((o=>{o.data.html&&(fcn_desktopFollowList.innerHTML=o.data.html,fcn_mobileFollowList.innerHTML=o.data.html)})).catch((o=>{o.status&&o.statusText&&fcn_showNotification(`${o.status}: ${o.statusText}`,5,"warning"),fcn_desktopFollowList.remove(),fcn_mobileFollowList.remove()})).then((()=>{fcn_followsMenuItem.classList.add("_loaded")}))}function fcn_markFollowsRead(){if(!fcn_followsMenuItem.classList.contains("_new")||!fcn_followsMenuItem.classList.contains("_loaded"))return;_$$(".mark-follows-read, .follows-alert-number, .follow-item, .mobile-menu-button").forEach((o=>{o.classList.remove("_new")}));const o=fcn_getUserData();o.new=0,o.lastLoaded=0,fcn_setUserData(o),fcn_ajaxPost({action:"fictioneer_ajax_mark_follows_read",fcn_fast_ajax:1}).catch((o=>{o.status&&o.statusText&&fcn_showNotification(`${o.status}: ${o.statusText}`,5,"warning")}))}document.addEventListener("fcnUserDataReady",(o=>{fcn_initializeFollows(o)})),fcn_followsMenuItem?.addEventListener("mouseover",(()=>{fcn_setupFollowsHTML()}),{once:!0}),fcn_followsMenuItem?.addEventListener("focus",(()=>{fcn_setupFollowsHTML()}),{once:!0}),_$('.mobile-menu__frame-button[data-frame-target="follows"]')?.addEventListener("click",(()=>{fcn_setupFollowsHTML()}),{once:!0}),_$$(".button-follow-story").forEach((o=>{o.addEventListener("click",(o=>{fcn_toggleFollow(o.currentTarget.dataset.storyId)}))})),_$$(".mark-follows-read").forEach((o=>{o.addEventListener("click",(()=>{fcn_markFollowsRead()}))}));
\ No newline at end of file
+const fcn_desktopFollowList=_$$$("follow-menu-scroll"),fcn_mobileFollowList=_$$$("mobile-menu-follows-list"),fcn_followsMenuItem=_$$$("follow-menu-button");var fcn_userFollowsTimeout,fcn_follows;function fcn_initializeFollows(o){const t=o.detail.data.follows;!1!==t&&(fcn_follows=t,fcn_updateFollowsView(),localStorage.removeItem("fcnBookshelfContent"))}function fcn_toggleFollow(o){const t=fcn_getUserData();if(fcn_follows&&t.follows){if(localStorage.removeItem("fcnBookshelfContent"),JSON.stringify(fcn_follows.data[o])!==JSON.stringify(t.follows.data[o]))return fcn_follows=t.follows,fcn_showNotification(__("Follows re-synchronized.","fictioneer")),void fcn_updateFollowsView();fcn_follows.data.hasOwnProperty(o)?delete fcn_follows.data[o]:fcn_follows.data[o]={story_id:parseInt(o),timestamp:Date.now()},t.follows.data[o]=fcn_follows.data[o],t.lastLoaded=0,fcn_setUserData(t),fcn_updateFollowsView(),clearTimeout(fcn_userFollowsTimeout),fcn_userFollowsTimeout=setTimeout((()=>{fcn_ajaxPost({action:"fictioneer_ajax_toggle_follow",fcn_fast_ajax:1,story_id:o,set:fcn_follows.data.hasOwnProperty(o)}).then((o=>{o.data.error&&fcn_showNotification(o.data.error,5,"warning")})).catch((o=>{o.status&&o.statusText&&fcn_showNotification(`${o.status}: ${o.statusText}`,5,"warning")}))}),fictioneer_ajax.post_debounce_rate)}}function fcn_updateFollowsView(){const o=fcn_getUserData();if(!fcn_follows||!o.follows)return;_$$(".button-follow-story").forEach((o=>{o.classList.toggle("_followed",fcn_follows?.data.hasOwnProperty(o.dataset.storyId))})),_$$(".card").forEach((o=>{o.classList.toggle("has-follow",fcn_follows?.data.hasOwnProperty(o.dataset.storyId))}));const t=parseInt(fcn_follows.new)>0;_$$(".mark-follows-read, .follows-alert-number, .mobile-menu-button").forEach((o=>{o.classList.toggle("_new",t),t>0&&(o.dataset.newCount=fcn_follows.new)}))}function fcn_setupFollowsHTML(){fcn_followsMenuItem.classList.contains("_loaded")||fcn_ajaxGet({action:"fictioneer_ajax_get_follows_notifications",fcn_fast_ajax:1}).then((o=>{o.data.html&&(fcn_desktopFollowList.innerHTML=o.data.html,fcn_mobileFollowList.innerHTML=o.data.html)})).catch((o=>{o.status&&o.statusText&&fcn_showNotification(`${o.status}: ${o.statusText}`,5,"warning"),fcn_desktopFollowList.remove(),fcn_mobileFollowList.remove()})).then((()=>{fcn_followsMenuItem.classList.add("_loaded")}))}function fcn_markFollowsRead(){if(!fcn_followsMenuItem.classList.contains("_new")||!fcn_followsMenuItem.classList.contains("_loaded"))return;_$$(".mark-follows-read, .follows-alert-number, .follow-item, .mobile-menu-button").forEach((o=>{o.classList.remove("_new")}));const o=fcn_getUserData();o.new=0,o.lastLoaded=0,fcn_setUserData(o),fcn_ajaxPost({action:"fictioneer_ajax_mark_follows_read",fcn_fast_ajax:1}).catch((o=>{o.status&&o.statusText&&fcn_showNotification(`${o.status}: ${o.statusText}`,5,"warning")}))}document.addEventListener("fcnUserDataReady",(o=>{fcn_initializeFollows(o)})),fcn_followsMenuItem?.addEventListener("mouseover",(()=>{fcn_setupFollowsHTML()}),{once:!0}),fcn_followsMenuItem?.addEventListener("focus",(()=>{fcn_setupFollowsHTML()}),{once:!0}),_$('.mobile-menu__frame-button[data-frame-target="follows"]')?.addEventListener("click",(()=>{fcn_setupFollowsHTML()}),{once:!0}),_$$(".button-follow-story").forEach((o=>{o.addEventListener("click",(o=>{fcn_toggleFollow(o.currentTarget.dataset.storyId)}))})),_$$(".mark-follows-read").forEach((o=>{o.addEventListener("click",(()=>{fcn_markFollowsRead()}))}));
\ No newline at end of file
diff --git a/js/reminders.min.js b/js/reminders.min.js
index fc64a750..89e016ae 100644
--- a/js/reminders.min.js
+++ b/js/reminders.min.js
@@ -1 +1 @@
-var fcn_userRemindersTimeout,fcn_reminders;function fcn_initializeReminders(e){const t=e.detail.data.reminders;!1!==t&&(fcn_reminders=t,fcn_updateRemindersView(),localStorage.removeItem("fcnBookshelfContent"))}function fcn_toggleReminder(e){const t=fcn_getUserData();if(fcn_reminders&&t.reminders){if(localStorage.removeItem("fcnBookshelfContent"),JSON.stringify(fcn_reminders.data[e])!==JSON.stringify(t.reminders.data[e]))return fcn_reminders=t.reminders,fcn_showNotification(__("Reminders re-synchronized.","fictioneer")),void fcn_updateRemindersView();fcn_reminders.data.hasOwnProperty(e)?delete fcn_reminders.data[e]:fcn_reminders.data[e]={story_id:parseInt(e),timestamp:Date.now()},t.reminders.data[e]=fcn_reminders.data[e],t.lastLoaded=0,fcn_setUserData(t),fcn_updateRemindersView(),clearTimeout(fcn_userRemindersTimeout),fcn_userRemindersTimeout=setTimeout((()=>{fcn_ajaxPost({action:"fictioneer_ajax_toggle_reminder",fcn_fast_ajax:1,story_id:e,set:fcn_reminders.data.hasOwnProperty(e)}).then((e=>{e.data.error&&fcn_showNotification(e.data.error,5,"warning")})).catch((e=>{e.status&&e.statusText&&fcn_showNotification(`${e.status}: ${e.statusText}`,5,"warning")}))}),fictioneer_ajax.post_debounce_rate)}}function fcn_updateRemindersView(){fcn_getUserData().reminders&&(_$$(".button-read-later").forEach((e=>{e.classList.toggle("_remembered",fcn_reminders.data.hasOwnProperty(e.dataset.storyId))})),_$$(".card").forEach((e=>{e.classList.toggle("has-reminder",fcn_reminders?.data.hasOwnProperty(e.dataset.storyId))})))}document.addEventListener("fcnUserDataReady",(e=>{fcn_initializeReminders(e)})),_$$(".button-read-later").forEach((e=>{e.addEventListener("click",(e=>{fcn_toggleReminder(e.currentTarget.dataset.storyId)}))}));
\ No newline at end of file
+var fcn_userRemindersTimeout,fcn_reminders;function fcn_initializeReminders(e){const t=e.detail.data.reminders;!1!==t&&(fcn_reminders=t,fcn_updateRemindersView(),localStorage.removeItem("fcnBookshelfContent"))}function fcn_toggleReminder(e){const t=fcn_getUserData();if(fcn_reminders&&t.reminders){if(localStorage.removeItem("fcnBookshelfContent"),JSON.stringify(fcn_reminders.data[e])!==JSON.stringify(t.reminders.data[e]))return fcn_reminders=t.reminders,fcn_showNotification(__("Reminders re-synchronized.","fictioneer")),void fcn_updateRemindersView();fcn_reminders.data.hasOwnProperty(e)?delete fcn_reminders.data[e]:fcn_reminders.data[e]={story_id:parseInt(e),timestamp:Date.now()},t.reminders.data[e]=fcn_reminders.data[e],t.lastLoaded=0,fcn_setUserData(t),fcn_updateRemindersView(),clearTimeout(fcn_userRemindersTimeout),fcn_userRemindersTimeout=setTimeout((()=>{fcn_ajaxPost({action:"fictioneer_ajax_toggle_reminder",fcn_fast_ajax:1,story_id:e,set:fcn_reminders.data.hasOwnProperty(e)}).then((e=>{e.data.error&&fcn_showNotification(e.data.error,5,"warning")})).catch((e=>{e.status&&e.statusText&&fcn_showNotification(`${e.status}: ${e.statusText}`,5,"warning")}))}),fictioneer_ajax.post_debounce_rate)}}function fcn_updateRemindersView(){const e=fcn_getUserData();fcn_reminders&&e.reminders&&(_$$(".button-read-later").forEach((e=>{e.classList.toggle("_remembered",fcn_reminders.data.hasOwnProperty(e.dataset.storyId))})),_$$(".card").forEach((e=>{e.classList.toggle("has-reminder",fcn_reminders?.data.hasOwnProperty(e.dataset.storyId))})))}document.addEventListener("fcnUserDataReady",(e=>{fcn_initializeReminders(e)})),_$$(".button-read-later").forEach((e=>{e.addEventListener("click",(e=>{fcn_toggleReminder(e.currentTarget.dataset.storyId)}))}));
\ No newline at end of file
diff --git a/js/user.min.js b/js/user.min.js
index d83b01b6..dedce96c 100644
--- a/js/user.min.js
+++ b/js/user.min.js
@@ -1 +1 @@
-function fcn_replaceProfileImage(e,a){const t=e.querySelector(".user-icon");if(t){const n=document.createElement("img");n.classList.add("user-profile-image"),n.src=a,t.remove(),e.appendChild(n)}}function fcn_setProfileImage(e,a=!0){e&&fcn_isValidUrl(e)&&(a&&localStorage.setItem("fcnProfileAvatar",e),_$$("a.subscriber-profile")?.forEach((a=>{fcn_replaceProfileImage(a,e)})))}function fcn_getProfileImage(){let e=localStorage.getItem("fcnProfileAvatar");fcn_isLoggedIn?(fcn_isValidUrl(e)||(e=!1),e?fcn_setProfileImage(e):fcn_getUserAvatar()):localStorage.removeItem("fcnProfileAvatar")}function fcn_getUserAvatar(){fcn_ajaxGet({action:"fictioneer_ajax_get_avatar",fcn_fast_ajax:1}).then((e=>{e.success&&fcn_setProfileImage(e.data.url)})).catch((()=>{fcn_theRoot.dataset.defaultAvatar&&fcn_setProfileImage(fcn_theRoot.dataset.defaultAvatar,!1)}))}var fcn_userData;function fcn_initializeUserData(){fcn_userData=fcn_getUserData(),fcn_fetchUserData()}function fcn_getUserData(){const e=localStorage.getItem("fcnUserData");return e&&fcn_isValidJSONString(e)?JSON.parse(e):{lastLoaded:0,timestamp:0,follows:!1,reminders:!1,checkmarks:!1,bookmarks:{},fingerprint:!1}}function fcn_setUserData(e){localStorage.setItem("fcnUserData",JSON.stringify(e))}function fcn_fetchUserData(){if(fcn_ajaxLimitThreshold{if(e.success){(fcn_userData=e.data).lastLoaded=Date.now();const a=new CustomEvent("fcnUserDataReady",{detail:{data:e.data,time:new Date},bubbles:!0,cancelable:!1});fcn_setUserData(fcn_userData),document.dispatchEvent(a)}else{localStorage.removeItem("fcnUserData"),fcn_userData=!1;const a=new CustomEvent("fcnUserDataFailed",{detail:{response:e,time:new Date},bubbles:!0,cancelable:!1});document.dispatchEvent(a)}})).catch((e=>{localStorage.removeItem("fcnUserData"),fcn_userData=!1;const a=new CustomEvent("fcnUserDataError",{detail:{error:e,time:new Date},bubbles:!0,cancelable:!1});document.dispatchEvent(a)}))}fcn_getProfileImage(),document.addEventListener("DOMContentLoaded",(()=>{fcn_isLoggedIn&&!fcn_userData&&fcn_initializeUserData()}));
\ No newline at end of file
+function fcn_replaceProfileImage(e,a){const t=e.querySelector(".user-icon");if(t){const n=document.createElement("img");n.classList.add("user-profile-image"),n.src=a,t.remove(),e.appendChild(n)}}function fcn_setProfileImage(e,a=!0){e&&fcn_isValidUrl(e)&&(a&&localStorage.setItem("fcnProfileAvatar",e),_$$("a.subscriber-profile")?.forEach((a=>{fcn_replaceProfileImage(a,e)})))}function fcn_getProfileImage(){let e=localStorage.getItem("fcnProfileAvatar");fcn_isLoggedIn?(fcn_isValidUrl(e)||(e=!1),e?fcn_setProfileImage(e):fcn_getUserAvatar()):localStorage.removeItem("fcnProfileAvatar")}function fcn_getUserAvatar(){fcn_ajaxGet({action:"fictioneer_ajax_get_avatar",fcn_fast_ajax:1}).then((e=>{e.success&&fcn_setProfileImage(e.data.url)})).catch((()=>{fcn_theRoot.dataset.defaultAvatar&&fcn_setProfileImage(fcn_theRoot.dataset.defaultAvatar,!1)}))}var fcn_userData;function fcn_initializeUserData(){fcn_userData=fcn_getUserData(),fcn_fetchUserData()}function fcn_getUserData(){return fcn_parseJSON(localStorage.getItem("fcnUserData"))??{lastLoaded:0,timestamp:0,follows:!1,reminders:!1,checkmarks:!1,bookmarks:{},fingerprint:!1}}function fcn_setUserData(e){localStorage.setItem("fcnUserData",JSON.stringify(e))}function fcn_fetchUserData(){if(fcn_ajaxLimitThreshold{if(e.success){(fcn_userData=e.data).lastLoaded=Date.now();const a=new CustomEvent("fcnUserDataReady",{detail:{data:e.data,time:new Date},bubbles:!0,cancelable:!1});fcn_setUserData(fcn_userData),document.dispatchEvent(a)}else{localStorage.removeItem("fcnUserData"),fcn_userData=!1;const a=new CustomEvent("fcnUserDataFailed",{detail:{response:e,time:new Date},bubbles:!0,cancelable:!1});document.dispatchEvent(a)}})).catch((e=>{localStorage.removeItem("fcnUserData"),fcn_userData=!1;const a=new CustomEvent("fcnUserDataError",{detail:{error:e,time:new Date},bubbles:!0,cancelable:!1});document.dispatchEvent(a)}))}!fcn_isLoggedIn&&fcn_theRoot.dataset.ajaxAuth||fcn_getProfileImage(),document.addEventListener("DOMContentLoaded",(()=>{(fcn_isLoggedIn&&!fcn_userData||!fcn_theRoot.dataset.ajaxAuth)&&fcn_initializeUserData()}));
\ No newline at end of file
diff --git a/js/utility.min.js b/js/utility.min.js
index cfc7a28b..f01960cf 100644
--- a/js/utility.min.js
+++ b/js/utility.min.js
@@ -1 +1 @@
-const _$=document.querySelector.bind(document),_$$=document.querySelectorAll.bind(document),_$$$=document.getElementById.bind(document);async function fcn_ajaxPost(e={},t=null,n={}){t&&!t.startsWith("http")&&(t=fictioneer_ajax.rest_url+t),t=t||fictioneer_ajax.ajax_url,final_headers={"Content-Type":"application/x-www-form-urlencoded","Cache-Control":"no-cache"},final_headers={...final_headers,...n},e={nonce:fcn_getNonce(),...e};const c=await fetch(t,{method:"POST",credentials:"same-origin",headers:final_headers,mode:"same-origin",body:new URLSearchParams(e)});return c.ok?c.json():Promise.reject(c)}async function fcn_ajaxGet(e={},t=null,n={}){t&&!t.startsWith("http")&&(t=fictioneer_ajax.rest_url+t),t=t||fictioneer_ajax.ajax_url,t=fcn_buildUrl(e={nonce:fcn_getNonce(),...e},t),final_headers={"Content-Type":"application/x-www-form-urlencoded","Cache-Control":"no-cache"},final_headers={...final_headers,...n};const c=await fetch(t,{method:"GET",credentials:"same-origin",headers:final_headers,mode:"same-origin"});return c.ok?c.json():Promise.reject(c)}function fcn_evaluateAsBoolean(e,t=!1){if("boolean"==typeof e)return e;if(void 0===e)return t;if(e instanceof HTMLInputElement&&"checkbox"===e.getAttribute("type"))return e.checked;e instanceof HTMLElement&&(e.hasAttribute("value")?e=e.value:e.hasAttribute("data-value")&&(e=e.dataset.value));const n=String(e),c=parseInt(e);return"true"===n||"1"===n||1===c||"false"!==n&&"0"!==n&&0!==c&&t}function fcn_copyToClipboard(e,t=!1){t=t||__("Copied to clipboard!","fictioneer"),navigator.clipboard&&(navigator.clipboard.writeText(e),t&&fcn_showNotification(t,2))}function fcn_isValidJSONString(e){if(null==e||"string"!=typeof e)return!1;try{JSON.parse(e)}catch(e){return!1}return!0}function fcn_parseJSON(e){if(null==e||"string"!=typeof e)return null;try{return JSON.parse(e)}catch(e){return null}}function fcn_removeItemOnce(e,t){var n=e.indexOf(t);return n>-1&&e.splice(n,1),e}function fcn_clamp(e,t,n){return Math.min(Math.max(n,e),t)}function fcn_updateThemeColor(e=!1){const t=fcn_siteSettings.darken?fcn_siteSettings.darken:0,n=fcn_siteSettings.saturation?fcn_siteSettings.saturation:0,c=fcn_siteSettings["hue-rotate"]?fcn_siteSettings["hue-rotate"]:0,o=t>=0?1+Math.pow(t,2):1-Math.pow(t,2),i=n>=0?1+Math.pow(n,2):1-Math.pow(n,2);let a=fcn_cssVars.getPropertyValue("--theme-color-base").trim().split(" ");a=`hsl(${(parseInt(a[0])+c)%360}deg ${(parseInt(a[1])*i).toFixed(2)}% ${(parseInt(a[2])*o).toFixed(2)}%)`,_$("meta[name=theme-color]").setAttribute("content",e||a)}function fcn_offset(e){const t=e.getBoundingClientRect();return{top:t.top+window.scrollY,left:t.left+window.scrollX}}function fcn_throttle(e,t,n){var c,o,i,a=null,r=0;n||(n={});var l=function(){r=!1===n.leading?0:Date.now(),a=null,i=e.apply(c,o),a||(c=o=null)};return function(){var s=Date.now();r||!1!==n.leading||(r=s);var u=t-(s-r);return c=this,o=arguments,u<=0||u>t?(a&&(clearTimeout(a),a=null),r=s,i=e.apply(c,o),a||(c=o=null)):a||!1===n.trailing||(a=setTimeout(l,u)),i}}var fcn_lastClicked,fcn_animFrameEvents=new Map;function fcn_bindEventToAnimationFrame(e,t,n=window){n.addEventListener(e,(function(){fcn_animFrameEvents.get(t)||(fcn_animFrameEvents.set(t,!0),requestAnimationFrame((()=>{n.dispatchEvent(new CustomEvent(t)),fcn_animFrameEvents.set(t,!1)})))}))}function fcn_toggleLastClicked(e){const t=!e.classList.contains("last-clicked");e.classList.toggle("last-clicked",t),e.closest(".watch-last-clicked")?.classList.toggle("has-last-clicked",t),fcn_lastClicked&&fcn_lastClicked!=e&&fcn_removeLastClick(fcn_lastClicked),fcn_lastClicked=e}function fcn_removeLastClick(e){e.closest(".watch-last-clicked")?.classList.remove("has-last-clicked"),e.classList.remove("last-clicked"),fcn_lastClicked=null}function fcn_cleanTextSelectionFromButtons(e){return e=(e=(e=(e=(e=(e=e.replace(/[\r\n]{2,}/g,"__$__")).replace(new RegExp("(__Bookmark|__Quote|__Link)","g"),"")).replace(new RegExp("(__Bookmark|__Quote|__TTS|__Link)","g"),"")).replace(new RegExp("(__Bookmark|__Quote|__Suggestion|__TTS|__Link)","g"),"")).replace(new RegExp("(__Bookmark|__Quote|__Suggestion|__Link)","g"),"")).replace(/[__$]{1,}/g,"\n\n").replace(/^[\r\n]+|[\r\n]+$/g,"")}function fcn_deleteCookie(e){document.cookie=e+"=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/"}function fcn_deleteAllCookies(){localStorage.clear(),document.cookie.split(";").forEach((e=>{document.cookie=e.replace(/^ +/,"").replace(/=.*/,"=;expires="+(new Date).toUTCString()+";path=/")}))}function fcn_setCookie(e,t,n=30){const c=new Date;c.setTime(c.getTime()+24*n*60*60*1e3);const o="expires="+c.toUTCString();document.cookie=e+"="+encodeURIComponent(t)+";"+o+";SameSite=Strict;path=/"}function fcn_getCookie(e){const t=e+"=",n=document.cookie.split(";");for(var c=0;c{!["BUTTON","A"].includes(e.target.tagName)&&e.target.closest(".toggle-last-clicked")||null!==e.target.closest(".escape-last-click")||fcn_lastClicked&&e.currentTarget!=fcn_lastClicked&&fcn_removeLastClick(fcn_lastClicked)})),_$("body").addEventListener("keydown",(e=>{27==e.keyCode&&fcn_lastClicked&&(fcn_removeLastClick(fcn_lastClicked),document.activeElement?.blur())}));var fcn_defaultNonce=_$$$("fictioneer-nonce")?.value??0;function fcn_getNonce(){return _$$$("fictioneer-ajax-nonce")?.value??fcn_defaultNonce}function fcn_matchFingerprint(e){const t=fcn_getUserData().fingerprint;return!!t&&t===e}function fcn_buildUrl(e={},t=null){return t=t?new URL(t):new URL(window.location.protocol+"//"+window.location.host+window.location.pathname),e&&Object.keys(e).forEach((n=>{t.searchParams.append(n,e[n])})),t}function fcn_buildErrorNotice(e,t=!1,n=!0){const c=document.createElement("div");let o=e;return t&&(c.id=t),c.classList="notice _warning","object"==typeof e&&(o="",e.status&&(o=`${e.status}: `),e.statusText&&(o+=e.statusText),o||(o="Unknown error.")),c.innerHTML=`${n?fcn_sanitizeHTML(o):o}
`,c}function fcn_sanitizeHTML(e){const t=document.createElement("div");return t.innerText=e instanceof HTMLElement?e.innerHTML:e,t.innerHTML}function fcn_resizeInput(e,t=null){t=t||e.value.length,e.style.width=.88*t+2+"ch"}function fcn_ariaCheckedUpdate(e){const t=e.closest('[role="checkbox"][aria-checked]');if(t){const n=fcn_evaluateAsBoolean(e);t.ariaChecked=n}}function fcn_detectScreenCollision(e){const t=e.getBoundingClientRect(),n=window.innerHeight??document.documentElement.clientHeight,c=(e.closest(".popup-menu-toggle")?.clientHeight??32)+16,o=n-t.bottom-e.clientHeight,i=t.top-e.clientHeight,a=[];return t.top<=50&&o>50+c&&a.push("top"),t.bottom>=n-50&&i>50+c&&a.push("bottom"),a}function fcn_scrollTo(e,t=64){window.scrollTo({top:e.getBoundingClientRect().top+window.scrollY-t,behavior:"smooth"})}function fcn_html(...e){const t=document.createElement("template");return t.innerHTML=String.raw(...e).trim(),t.content.firstChild}
\ No newline at end of file
+const _$=document.querySelector.bind(document),_$$=document.querySelectorAll.bind(document),_$$$=document.getElementById.bind(document);async function fcn_ajaxPost(e={},t=null,n={}){t&&!t.startsWith("http")&&(t=fictioneer_ajax.rest_url+t),t=t||fictioneer_ajax.ajax_url,final_headers={"Content-Type":"application/x-www-form-urlencoded","Cache-Control":"no-cache"},final_headers={...final_headers,...n},e={nonce:fcn_getNonce(),...e};const c=await fetch(t,{method:"POST",credentials:"same-origin",headers:final_headers,mode:"same-origin",body:new URLSearchParams(e)});return c.ok?c.json():Promise.reject(c)}async function fcn_ajaxGet(e={},t=null,n={}){t&&!t.startsWith("http")&&(t=fictioneer_ajax.rest_url+t),t=t||fictioneer_ajax.ajax_url,t=fcn_buildUrl(e={nonce:fcn_getNonce(),...e},t),final_headers={"Content-Type":"application/x-www-form-urlencoded","Cache-Control":"no-cache"},final_headers={...final_headers,...n};const c=await fetch(t,{method:"GET",credentials:"same-origin",headers:final_headers,mode:"same-origin"});return c.ok?c.json():Promise.reject(c)}function fcn_evaluateAsBoolean(e,t=!1){if("boolean"==typeof e)return e;if(void 0===e)return t;if(e instanceof HTMLInputElement&&"checkbox"===e.getAttribute("type"))return e.checked;e instanceof HTMLElement&&(e.hasAttribute("value")?e=e.value:e.hasAttribute("data-value")&&(e=e.dataset.value));const n=String(e),c=parseInt(e);return"true"===n||"1"===n||1===c||"false"!==n&&"0"!==n&&0!==c&&t}function fcn_copyToClipboard(e,t=!1){t=t||__("Copied to clipboard!","fictioneer"),navigator.clipboard&&(navigator.clipboard.writeText(e),t&&fcn_showNotification(t,2))}function fcn_parseJSON(e){if(null==e||"string"!=typeof e)return null;try{return JSON.parse(e)}catch(e){return null}}function fcn_removeItemOnce(e,t){var n=e.indexOf(t);return n>-1&&e.splice(n,1),e}function fcn_clamp(e,t,n){return Math.min(Math.max(n,e),t)}function fcn_updateThemeColor(e=!1){const t=fcn_siteSettings.darken?fcn_siteSettings.darken:0,n=fcn_siteSettings.saturation?fcn_siteSettings.saturation:0,c=fcn_siteSettings["hue-rotate"]?fcn_siteSettings["hue-rotate"]:0,o=t>=0?1+Math.pow(t,2):1-Math.pow(t,2),i=n>=0?1+Math.pow(n,2):1-Math.pow(n,2);let a=fcn_cssVars.getPropertyValue("--theme-color-base").trim().split(" ");a=`hsl(${(parseInt(a[0])+c)%360}deg ${(parseInt(a[1])*i).toFixed(2)}% ${(parseInt(a[2])*o).toFixed(2)}%)`,_$("meta[name=theme-color]").setAttribute("content",e||a)}function fcn_offset(e){const t=e.getBoundingClientRect();return{top:t.top+window.scrollY,left:t.left+window.scrollX}}function fcn_throttle(e,t,n){var c,o,i,a=null,r=0;n||(n={});var l=function(){r=!1===n.leading?0:Date.now(),a=null,i=e.apply(c,o),a||(c=o=null)};return function(){var s=Date.now();r||!1!==n.leading||(r=s);var u=t-(s-r);return c=this,o=arguments,u<=0||u>t?(a&&(clearTimeout(a),a=null),r=s,i=e.apply(c,o),a||(c=o=null)):a||!1===n.trailing||(a=setTimeout(l,u)),i}}var fcn_lastClicked,fcn_animFrameEvents=new Map;function fcn_bindEventToAnimationFrame(e,t,n=window){n.addEventListener(e,(function(){fcn_animFrameEvents.get(t)||(fcn_animFrameEvents.set(t,!0),requestAnimationFrame((()=>{n.dispatchEvent(new CustomEvent(t)),fcn_animFrameEvents.set(t,!1)})))}))}function fcn_toggleLastClicked(e){const t=!e.classList.contains("last-clicked");e.classList.toggle("last-clicked",t),e.closest(".watch-last-clicked")?.classList.toggle("has-last-clicked",t),fcn_lastClicked&&fcn_lastClicked!=e&&fcn_removeLastClick(fcn_lastClicked),fcn_lastClicked=e}function fcn_removeLastClick(e){e.closest(".watch-last-clicked")?.classList.remove("has-last-clicked"),e.classList.remove("last-clicked"),fcn_lastClicked=null}function fcn_cleanTextSelectionFromButtons(e){return e=(e=(e=(e=(e=(e=e.replace(/[\r\n]{2,}/g,"__$__")).replace(new RegExp("(__Bookmark|__Quote|__Link)","g"),"")).replace(new RegExp("(__Bookmark|__Quote|__TTS|__Link)","g"),"")).replace(new RegExp("(__Bookmark|__Quote|__Suggestion|__TTS|__Link)","g"),"")).replace(new RegExp("(__Bookmark|__Quote|__Suggestion|__Link)","g"),"")).replace(/[__$]{1,}/g,"\n\n").replace(/^[\r\n]+|[\r\n]+$/g,"")}function fcn_deleteCookie(e){document.cookie=e+"=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/"}function fcn_deleteAllCookies(){localStorage.clear(),document.cookie.split(";").forEach((e=>{document.cookie=e.replace(/^ +/,"").replace(/=.*/,"=;expires="+(new Date).toUTCString()+";path=/")}))}function fcn_setCookie(e,t,n=30){const c=new Date;c.setTime(c.getTime()+24*n*60*60*1e3);const o="expires="+c.toUTCString();document.cookie=e+"="+encodeURIComponent(t)+";"+o+";SameSite=Strict;path=/"}function fcn_getCookie(e){const t=e+"=",n=document.cookie.split(";");for(var c=0;c{!["BUTTON","A"].includes(e.target.tagName)&&e.target.closest(".toggle-last-clicked")||null!==e.target.closest(".escape-last-click")||fcn_lastClicked&&e.currentTarget!=fcn_lastClicked&&fcn_removeLastClick(fcn_lastClicked)})),_$("body").addEventListener("keydown",(e=>{27==e.keyCode&&fcn_lastClicked&&(fcn_removeLastClick(fcn_lastClicked),document.activeElement?.blur())}));var fcn_defaultNonce=_$$$("fictioneer-nonce")?.value??0;function fcn_getNonce(){return _$$$("fictioneer-ajax-nonce")?.value??fcn_defaultNonce}function fcn_matchFingerprint(e){const t=fcn_getUserData().fingerprint;return!!t&&t===e}function fcn_buildUrl(e={},t=null){return t=t?new URL(t):new URL(window.location.protocol+"//"+window.location.host+window.location.pathname),e&&Object.keys(e).forEach((n=>{t.searchParams.append(n,e[n])})),t}function fcn_buildErrorNotice(e,t=!1,n=!0){const c=document.createElement("div");let o=e;return t&&(c.id=t),c.classList="notice _warning","object"==typeof e&&(o="",e.status&&(o=`${e.status}: `),e.statusText&&(o+=e.statusText),o||(o="Unknown error.")),c.innerHTML=`${n?fcn_sanitizeHTML(o):o}
`,c}function fcn_sanitizeHTML(e){const t=document.createElement("div");return t.innerText=e instanceof HTMLElement?e.innerHTML:e,t.innerHTML}function fcn_resizeInput(e,t=null){t=t||e.value.length,e.style.width=.88*t+2+"ch"}function fcn_ariaCheckedUpdate(e){const t=e.closest('[role="checkbox"][aria-checked]');if(t){const n=fcn_evaluateAsBoolean(e);t.ariaChecked=n}}function fcn_detectScreenCollision(e){const t=e.getBoundingClientRect(),n=window.innerHeight??document.documentElement.clientHeight,c=(e.closest(".popup-menu-toggle")?.clientHeight??32)+16,o=n-t.bottom-e.clientHeight,i=t.top-e.clientHeight,a=[];return t.top<=50&&o>50+c&&a.push("top"),t.bottom>=n-50&&i>50+c&&a.push("bottom"),a}function fcn_scrollTo(e,t=64){window.scrollTo({top:e.getBoundingClientRect().top+window.scrollY-t,behavior:"smooth"})}function fcn_html(...e){const t=document.createElement("template");return t.innerHTML=String.raw(...e).trim(),t.content.firstChild}
\ No newline at end of file
diff --git a/src/js/admin.js b/src/js/admin.js
index b46c8705..aacbe07d 100644
--- a/src/js/admin.js
+++ b/src/js/admin.js
@@ -227,8 +227,7 @@ _$$('.confirm-dialog').forEach(element => {
_$('#wp-admin-bar-logout a')?.addEventListener('click', () => {
localStorage.removeItem('fcnProfileAvatar');
localStorage.removeItem('fcnUserData');
- localStorage.removeItem('fcnLoginState');
- localStorage.removeItem('fcnNonce');
+ localStorage.removeItem('fcnAuth');
localStorage.removeItem('fcnBookshelfContent');
localStorage.removeItem('fcnChapterBookmarks');
});
diff --git a/src/js/ajax-bookshelf.js b/src/js/ajax-bookshelf.js
index 54b35481..8b770ae9 100644
--- a/src/js/ajax-bookshelf.js
+++ b/src/js/ajax-bookshelf.js
@@ -5,8 +5,8 @@
const fcn_bookshelfTarget = _$$$('ajax-bookshelf-target');
// Initialize
-if (fcn_theRoot.dataset.ajaxNonce && !_$$$('fictioneer-ajax-nonce')) {
- fcn_theRoot.addEventListener('nonceReady', () => {
+if (fcn_theRoot.dataset.ajaxNonce) {
+ document.addEventListener('fcnAuthReady', () => {
fcn_updateBookshelfView();
});
} else {
@@ -21,15 +21,11 @@ if (fcn_theRoot.dataset.ajaxNonce && !_$$$('fictioneer-ajax-nonce')) {
* Get bookshelf content from web storage or create new JSON.
*
* @since 4.3
- * @see fcn_isValidJSONString()
+ * @see fcn_parseJSON()
*/
function fcn_getBookshelfContent() {
- // Get JSON string from web storage
- const c = localStorage.getItem('fcnBookshelfContent');
-
- // Parse and return JSON string if valid, otherwise return new JSON
- return (c && fcn_isValidJSONString(c)) ? JSON.parse(c) : { html: {}, count: {} };
+ return fcn_parseJSON(localStorage.getItem('fcnBookshelfContent')) ?? { html: {}, count: {} };
}
// =============================================================================
@@ -77,7 +73,10 @@ function fcn_updateBookshelfView(action = null, page = null, order = null, scrol
fcn_bookshelfTarget.classList.remove('ajax-in-progress');
fcn_bookshelfTarget.dataset.page = page;
_$('.item-number').innerHTML = `(${fcn_bookshelfStorage['count'][action]})`;
- if (scroll) _$$$('main').scrollIntoView({behavior: 'smooth'});
+
+ if (scroll) {
+ _$$$('main').scrollIntoView({ behavior: 'smooth' });
+ }
} else {
fcn_fetchBookshelfPart(action, page, order, scroll);
}
diff --git a/src/js/ajax-comments.js b/src/js/ajax-comments.js
index 6ad46d25..bfc5981d 100644
--- a/src/js/ajax-comments.js
+++ b/src/js/ajax-comments.js
@@ -198,9 +198,9 @@ function fcn_jumpToCommentPage() {
var /** @type {IntersectionObserver} */ fct_commentsObserver;
-// In case of nonce deferment
-if (fcn_theRoot.dataset.ajaxNonce && !_$$$('fictioneer-ajax-nonce')) {
- fcn_theRoot.addEventListener('nonceReady', () => {
+// In case of AJAx authentication...
+if (fcn_theRoot.dataset.ajaxNonce) {
+ document.addEventListener('fcnAuthReady', () => {
fcn_setupCommentObserver();
});
} else {
@@ -234,9 +234,9 @@ function fcn_setupCommentObserver() {
// SCROLL NEW COMMENT INTO VIEW SUBMITTING VIA RELOAD
// =============================================================================
-// In case of nonce deferment
-if (fcn_theRoot.dataset.ajaxNonce && !_$$$('fictioneer-ajax-nonce')) {
- fcn_theRoot.addEventListener('nonceReady', () => {
+// In case of AJAx authentication...
+if (fcn_theRoot.dataset.ajaxNonce) {
+ document.addEventListener('fcnAuthReady', () => {
fcn_loadCommentEarly();
});
} else {
diff --git a/src/js/application.js b/src/js/application.js
index f8e3cc95..ed178f3b 100644
--- a/src/js/application.js
+++ b/src/js/application.js
@@ -10,9 +10,7 @@ const /** @const {HTMLElement} */ fcn_theSite = _$$$('site'),
/** @const {URLSearchParams} */ fcn_urlSearchParams = new URLSearchParams(window.location.search),
/** @const {Object} */ fcn_urlParams = Object.fromEntries(fcn_urlSearchParams.entries()),
/** @const {Number} */ fcn_pageLoadTimestamp = Date.now(),
- /** @const {Number} */ fcn_ajaxLimitThreshold = Date.now() - parseInt(fictioneer_ajax.ttl), // Default: 60 seconds
- /** @const {Event} */ fcn_eventNonceReady = new Event('nonceReady'),
- /** @const {Boolean} */ fcn_isAjaxAuth = fcn_theRoot.dataset.ajaxAuth;
+ /** @const {Number} */ fcn_ajaxLimitThreshold = Date.now() - parseInt(fictioneer_ajax.ttl); // Default: 60 seconds
var /** @type {Object} */ fcn_cssVars = getComputedStyle(document.documentElement),
/** @type {Boolean} */ fcn_isLoggedIn = fcn_theBody.classList.contains('logged-in'),
@@ -33,14 +31,9 @@ if (fcn_chapterList) {
// =============================================================================
// Remove superfluous data and nodes if not logged in
-if (!fcn_isLoggedIn && !fcn_isAjaxAuth) {
+if (!fcn_isLoggedIn && !fcn_theRoot.dataset.ajaxAuth) {
fcn_cleanupWebStorage(true);
-
- // Since chapter lists on story pages are globally cached, the checkmarks are
- // always delivered if enabled regardless of log-in status
- _$$('.chapter-group__list-item-checkmark').forEach(element => {
- element.remove();
- });
+ fcn_cleanupGuestView();
}
// Remove query args (defined in _theme_setup.php)
@@ -63,19 +56,17 @@ if (typeof fcn_removeQueryArgs === 'function') {
function fcn_cleanupWebStorage(keepGuestData = false) {
localStorage.removeItem('fcnProfileAvatar');
localStorage.removeItem('fcnUserData');
- localStorage.removeItem('fcnLoginState');
localStorage.removeItem('fcnBookshelfContent');
if (!keepGuestData) {
localStorage.removeItem('fcnChapterBookmarks');
}
- // Clean up private nonce but keep public nonce
- let maybeNonce = localStorage.getItem('fcnNonce');
- maybeNonce = (maybeNonce && fcn_isValidJSONString(maybeNonce)) ? JSON.parse(maybeNonce) : false;
+ // Clean up private authentication data
+ const auth = fcn_parseJSON(localStorage.getItem('fcnAuth'));
- if (maybeNonce && maybeNonce['loggedIn']) {
- localStorage.removeItem('fcnNonce');
+ if (auth?.loggedIn) {
+ localStorage.removeItem('fcnAuth');
}
}
@@ -85,7 +76,7 @@ _$('#wp-admin-bar-logout a')?.addEventListener('click', () => {
});
// =============================================================================
-// VIEW CLEANUP
+// GUEST VIEW CLEANUP
// =============================================================================
/**
@@ -98,163 +89,155 @@ function fcn_cleanupGuestView() {
fcn_isLoggedIn = false;
fcn_theBody.classList.remove('logged-in', 'is-admin', 'is-moderator', 'is-editor', 'is-author');
+ _$$$('fictioneer-ajax-nonce')?.remove();
+
_$$('.only-moderators, .only-admins, .only-authors, .only-editors, .chapter-group__list-item-checkmark').forEach(element => {
element.remove()
});
}
// =============================================================================
-// LOAD NONCE VIA AJAX
+// AUTHENTICATE VIA AJAX
// =============================================================================
-if (fcn_theRoot.dataset.ajaxNonce) {
- fcn_fetchNonce();
-}
+// Initialize
+document.addEventListener('DOMContentLoaded', () => {
+ if (fcn_theRoot.dataset.ajaxAuth) {
+ fcn_ajaxAuth();
+ }
+});
/**
- * Fetch nonce via AJAX or web storage.
+ * Authenticate user via AJAX or from web storage
*
* @since 5.0
*/
-function fcn_fetchNonce() {
- // Look for recent state in web storage
- let storage = localStorage.getItem('fcnNonce');
+function fcn_ajaxAuth() {
+ let eventFired = false;
- storage = (storage && fcn_isValidJSONString(storage)) ? JSON.parse(storage) : false;
+ // Look for recent authentication in web storage
+ let localAuth = fcn_parseJSON(localStorage.getItem('fcnAuth')) ?? false;
- // Clear cached public nonce if any
- if (storage && !storage['loggedIn'] && fcn_isLoggedIn) {
- localStorage.removeItem('fcnNonce');
- storage = false;
+ // Clear left over guest authentication
+ if (fcn_isLoggedIn && !localAuth?.loggedIn) {
+ localStorage.removeItem('fcnAuth');
+ localAuth = false;
}
- // Only update from server after some time has passed (e.g. 60 seconds)
- if (storage) {
- // Add nonce to DOM
- fcn_addNonceAndAuth(storage['nonceHtml']);
+ // Authenticate from web storage (if set)...
+ if (localAuth) {
+ fcn_addNonceHTML(localAuth['nonceHtml']);
- // If not timed out, skip server request
- if (fcn_ajaxLimitThreshold < storage['lastLoaded']) {
+ // Fire fcnAuthReady event
+ const event = new CustomEvent('fcnAuthReady', {
+ detail: {
+ nonceHtml: localAuth['nonceHtml'],
+ nonce: localAuth['nonce'],
+ loggedIn: localAuth['loggedIn'],
+ isAdmin: localAuth['isAdmin'],
+ isModerator: localAuth['isModerator'],
+ isAuthor: localAuth['isAuthor'],
+ isEditor: localAuth['isEditor']
+ },
+ bubbles: true,
+ cancelable: false
+ });
+
+ document.dispatchEvent(event);
+ eventFired = true;
+
+ // ... but refresh from server after some time has passed (e.g. 60 seconds)
+ if (fcn_ajaxLimitThreshold < localAuth.lastLoaded) {
return;
}
}
- // Load from server
+ // Request nonce via AJAX
fcn_ajaxGet({
- 'action': 'fictioneer_ajax_get_nonce',
+ 'action': 'fictioneer_ajax_get_auth',
'fcn_fast_ajax': 1
- }).then((response) => {
- // Remove cached nonce
- _$$$('fictioneer-ajax-nonce')?.remove();
-
+ }).then(response => {
if (response.success) {
// Append hidden input with nonce to DOM
- fcn_addNonceAndAuth(response.data.nonceHtml);
+ fcn_addNonceHTML(response.data.nonceHtml);
+
+ // Unpack
+ const data = {
+ 'lastLoaded': Date.now(),
+ 'nonceHtml': response.data.nonceHtml,
+ 'nonce': response.data.nonce,
+ 'loggedIn': response.data.loggedIn,
+ 'isAdmin': response.data.isAdmin,
+ 'isModerator': response.data.isModerator,
+ 'isAuthor': response.data.isAuthor,
+ 'isEditor': response.data.isEditor
+ }
+
+ // Fire fcnAuthReady event (if not already done)
+ if (!eventFired) {
+ const event = new CustomEvent('fcnAuthReady', {
+ detail: data,
+ bubbles: true,
+ cancelable: false
+ });
+
+ document.dispatchEvent(event);
+ }
// Remember to avoid too many requests
localStorage.setItem(
- 'fcnNonce',
- JSON.stringify({ 'lastLoaded': Date.now(), 'nonceHtml': response.data.nonceHtml, 'loggedIn': fcn_isLoggedIn })
+ 'fcnAuth',
+ JSON.stringify(data)
);
} else {
// If unsuccessful, clear local data
- _$$$('fictioneer-ajax-nonce')?.remove();
fcn_cleanupGuestView();
+
+ // Fire fcnAuthFailed event
+ const event = new Event('fcnAuthFailed');
+ document.dispatchEvent(event);
}
})
.catch(() => {
// Most likely 403 after likely unsafe logout, clear local data
- localStorage.removeItem('fcnNonce');
- _$$$('fictioneer-ajax-nonce')?.remove();
+ localStorage.removeItem('fcnAuth');
fcn_cleanupGuestView();
+
+ // Fire fcnAuthError event
+ const event = new Event('fcnAuthError');
+ document.dispatchEvent(event);
});
}
/**
- * Append hidden input element with nonce to DOM and fetch login state.
+ * Append hidden input element with nonce to DOM.
*
* @since 5.0
* @param {String} nonceHtml - HTML for the hidden input with nonce value.
*/
-function fcn_addNonceAndAuth(nonceHtml) {
+function fcn_addNonceHTML(nonceHtml) {
+ // Remove old (if any)
+ _$$$('fictioneer-ajax-nonce')?.remove();
+
// Append hidden input with nonce to DOM
- const node = document.createElement('div');
- node.innerHTML += nonceHtml;
- fcn_theBody.appendChild(node.firstChild);
-
- // Fire nonceReady event
- fcn_theRoot.dispatchEvent(fcn_eventNonceReady);
-
- // Call to fetch login state (if necessary)
- if (!fcn_isLoggedIn && fcn_isAjaxAuth) {
- fcn_fetchLoginState();
- }
+ fcn_theBody.appendChild(fcn_html`${nonceHtml}`);
}
// =============================================================================
-// UPDATE LOGIN STATE VIA AJAX
+// UPDATE LOGIN STATE
// =============================================================================
-// Only if public caching compatibility mode is active and the nonce is not deferred
-if (!fcn_isLoggedIn && (typeof fcn_isAjaxAuth !== 'undefined') && !fcn_theRoot.dataset.ajaxNonce) {
- fcn_fetchLoginState();
-}
-
-/**
- * Fetch login state via AJAX or web storage.
- *
- * @since 5.0
- */
-
-function fcn_fetchLoginState() {
- // Look for recent state in web storage
- let storage = localStorage.getItem('fcnLoginState');
- storage = (storage && fcn_isValidJSONString(storage)) ? JSON.parse(storage) : false;
-
- // Update from cache to avoid delays but only cache for a short while
- if (storage && storage['loggedIn']) {
- // Set logged-in state and call setup functions
- fcn_setLoggedInState(storage, false); // Do not initialize (happens later in this case)
-
- // If not timed out, skip server request
- if (Date.now() - fictioneer_ajax.login_ttl < storage['lastLoaded']) {
- return;
- }
- }
-
- // Load from server
- fcn_ajaxGet({
- 'action': 'fictioneer_ajax_is_user_logged_in',
- 'fcn_fast_ajax': 1
- }).then((response) => {
- if (response.success && response.data.loggedIn) {
- // Update view to logged-in state (beware double initialize!)
- fcn_setLoggedInState(response.data, !storage['loggedIn']);
-
- // Remember to avoid too many requests
- localStorage.setItem(
- 'fcnLoginState',
- JSON.stringify({
- 'lastLoaded': Date.now(),
- 'loggedIn': response.data.loggedIn,
- 'isAdmin': response.data.isAdmin,
- 'isModerator': response.data.isModerator,
- 'isAuthor': response.data.isAuthor,
- 'isEditor': response.data.isEditor
- })
- );
+// Only if AJAX authentication is active
+if (!fcn_isLoggedIn && fcn_theRoot.dataset.ajaxAuth) {
+ document.addEventListener('fcnAuthReady', (event) => {
+ if (event.detail.loggedIn) {
+ fcn_setLoggedInState(event.detail);
} else {
- // Cleanup if not logged in (200)
fcn_cleanupWebStorage(true);
fcn_cleanupGuestView();
}
- })
- .catch(() => {
- // Most likely 403 after likely unsafe logout, clear local data
- fcn_cleanupWebStorage();
- fcn_cleanupGuestView();
});
}
@@ -263,10 +246,9 @@ function fcn_fetchLoginState() {
*
* @since 5.0
* @param {Object} state - Fetched/Cached login state.
- * @param {Boolean} initialize - Whether to call setup functions.
*/
-function fcn_setLoggedInState(state, initialize = true) {
+function fcn_setLoggedInState(state) {
// Update state and DOM
fcn_isLoggedIn = state.loggedIn;
fcn_theBody.classList.add('logged-in');
@@ -294,11 +276,9 @@ function fcn_setLoggedInState(state, initialize = true) {
_$$('label[for="modal-login-toggle"], #modal-login-toggle, #login-modal').forEach(element => { element.remove() });
- // Setup local user data, but only if the login state has not been added
- // synchronous from local storage (avoid double initialize).
- if (initialize) {
- fcn_getProfileImage();
- }
+ // Initialize
+ fcn_initializeUserData();
+ fcn_getProfileImage();
}
// =============================================================================
@@ -344,8 +324,14 @@ fcn_theBody.addEventListener('click', e => {
e.target.classList.contains('toggle-last-clicked')
)
) {
- if (typeof fcn_toggleLastClicked === 'function') fcn_toggleLastClicked(lastClickTarget);
- if (typeof fcn_popupPosition === 'function') fcn_popupPosition();
+ if (typeof fcn_toggleLastClicked === 'function') {
+ fcn_toggleLastClicked(lastClickTarget);
+ }
+
+ if (typeof fcn_popupPosition === 'function') {
+ fcn_popupPosition();
+ }
+
e.stopPropagation();
return;
}
@@ -731,7 +717,8 @@ function fcn_toggleLightMode() {
localStorage.getItem('fcnLightmode') ?
localStorage.getItem('fcnLightmode') == 'true' :
fcn_theRoot.dataset.modeDefault == 'light';
- fcn_setLightMode(!current);
+
+ fcn_setLightMode(!current);
}
/**
@@ -927,7 +914,10 @@ function fcn_setDarkenFromRange() {
*/
function fcn_setDarkenFromText() {
- if (this.value == '-' || this.value == '') return;
+ if (this.value == '-' || this.value == '') {
+ return;
+ }
+
fcn_updateDarken((parseInt(this.value) ?? 0) / 100);
}
@@ -1046,23 +1036,21 @@ function fcn_defaultSiteSettings() {
}
/**
- * Get site settings JSON from local storage or create new one.
+ * Get site settings JSON from web storage or create new one.
*
* @since 4.0
- * @see fcn_isValidJSONString()
+ * @see fcn_parseJSON()
* @see fcn_defaultSiteSettings()
* @return {Object} The site settings.
*/
function fcn_getSiteSettings() {
- // Look in local storage...
- let s = localStorage.getItem('fcnSiteSettings');
+ // Get settings from web storage or use defaults
+ const s = fcn_parseJSON(localStorage.getItem('fcnSiteSettings')) ?? fcn_defaultSiteSettings();
- // ... parse if found, set defaults otherwise
- s = (s && fcn_isValidJSONString(s)) ? JSON.parse(s) : fcn_defaultSiteSettings();
-
- // Update local storage and return
+ // Update web storage and return
fcn_setSiteSettings(s);
+
return s;
}
@@ -1078,7 +1066,9 @@ function fcn_setSiteSettings(value = null) {
value = value ? value : fcn_siteSettings;
// Simple validation
- if (typeof value !== 'object') return;
+ if (typeof value !== 'object') {
+ return;
+ }
// Keep global updated
fcn_siteSettings = value;
@@ -1216,9 +1206,17 @@ const /** @const {HTMLElement[]} */ fcn_cardLists = _$$('.card-list:not(._no-mut
var /** @type {MutationObserver} */ fcn_cardListMutationObserver = new MutationObserver((e) => {
if (e[0].addedNodes) {
// Update view
- if (typeof fcn_updateFollowsView === 'function') fcn_updateFollowsView();
- if (typeof fcn_updateCheckmarksView === 'function') fcn_updateCheckmarksView();
- if (typeof fcn_updateRemindersView === 'function') fcn_updateRemindersView();
+ if (typeof fcn_updateFollowsView === 'function') {
+ fcn_updateFollowsView();
+ }
+
+ if (typeof fcn_updateCheckmarksView === 'function') {
+ fcn_updateCheckmarksView();
+ }
+
+ if (typeof fcn_updateRemindersView === 'function') {
+ fcn_updateRemindersView();
+ }
}
});
diff --git a/src/js/comments.js b/src/js/comments.js
index bdecd8c2..46bb3e35 100644
--- a/src/js/comments.js
+++ b/src/js/comments.js
@@ -918,10 +918,10 @@ const /** @const {HTMLElement} */ fcn_ajaxCommentForm = _$$$('ajax-comment-form-
// Check whether form target exists...
if (fcn_ajaxCommentForm) {
- // Check for nonce deferment...
- if (fcn_theRoot.dataset.ajaxNonce && !_$$$('fictioneer-ajax-nonce')) {
+ // In case of AJAx authentication...
+ if (fcn_theRoot.dataset.ajaxNonce) {
// Load after nonce has been fetched
- fcn_theRoot.addEventListener('nonceReady', () => {
+ document.addEventListener('fcnAuthReady', () => {
fcn_getCommentForm();
});
} else {
diff --git a/src/js/follows.js b/src/js/follows.js
index 1de5d838..4ebb30ce 100644
--- a/src/js/follows.js
+++ b/src/js/follows.js
@@ -131,7 +131,7 @@ function fcn_updateFollowsView() {
// Get current data
const currentUserData = fcn_getUserData();
- if (!currentUserData.follows) {
+ if (!fcn_follows || !currentUserData.follows) {
return;
}
diff --git a/src/js/reminders.js b/src/js/reminders.js
index 1fb3522d..8048ed06 100644
--- a/src/js/reminders.js
+++ b/src/js/reminders.js
@@ -127,7 +127,7 @@ function fcn_updateRemindersView() {
// Get current data
const currentUserData = fcn_getUserData();
- if (!currentUserData.reminders) {
+ if (!fcn_reminders || !currentUserData.reminders) {
return;
}
diff --git a/src/js/user.js b/src/js/user.js
index 2815cdab..4124cfbf 100644
--- a/src/js/user.js
+++ b/src/js/user.js
@@ -117,7 +117,9 @@ function fcn_getUserAvatar() {
}
// Initialize
-fcn_getProfileImage();
+if (fcn_isLoggedIn || !fcn_theRoot.dataset.ajaxAuth) {
+ fcn_getProfileImage();
+}
// =============================================================================
// FETCH RELEVANT USER DATA
@@ -132,10 +134,10 @@ function fcn_initializeUserData() {
function fcn_getUserData() {
// Get JSON string from local storage
- const data = localStorage.getItem('fcnUserData');
+ const data = fcn_parseJSON(localStorage.getItem('fcnUserData'));
// Parse and return JSON string if valid, otherwise return new JSON
- return (data && fcn_isValidJSONString(data)) ? JSON.parse(data) :
+ return data ??
{
'lastLoaded': 0,
'timestamp': 0,
@@ -223,7 +225,7 @@ function fcn_fetchUserData() {
// Initialize
document.addEventListener('DOMContentLoaded', () => {
- if (fcn_isLoggedIn && !fcn_userData) {
+ if ((fcn_isLoggedIn && !fcn_userData) || !fcn_theRoot.dataset.ajaxAuth) {
fcn_initializeUserData();
}
});
diff --git a/src/js/utility.js b/src/js/utility.js
index 3c33e648..85d287f7 100644
--- a/src/js/utility.js
+++ b/src/js/utility.js
@@ -204,30 +204,9 @@ function fcn_copyToClipboard(text, message = false) {
}
// =============================================================================
-// JSONS
+// PARSE JSON
// =============================================================================
-/**
- * Is a string a valid JSON?
- *
- * @since 4.0
- * @param {String} str - The string to test.
- * @return {Boolean} True if valid, false of not.
- */
-
-function fcn_isValidJSONString(str) {
- if (str === null || typeof str === 'undefined' || typeof str !== 'string') {
- return false;
- }
-
- try {
- JSON.parse(str);
- } catch (e) {
- return false;
- }
- return true;
-}
-
/**
* Parse JSON and account for invalid strings
*
@@ -617,7 +596,10 @@ function fcn_getCookie(cname) {
*/
function fcn_isValidUrl(url) {
- if (!url) return false;
+ if (!url) {
+ return false;
+ }
+
return(url.match(/^(https?:\/\/)/) != null);
}
@@ -627,7 +609,7 @@ function fcn_isValidUrl(url) {
// This nonce is always included in the template file but may not be correct
// if caching is active. Some caching plugins can localize nonces if you add
-// them to a special list. Otherwise use nonce deferment in the options.
+// them to a special list. Otherwise enable AJAX user authentication.
var fcn_defaultNonce = _$$$('fictioneer-nonce')?.value ?? 0;
/**