<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/favicon.png" />
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300..800;1,300..800&display=swap" rel="stylesheet">
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Civil.GG Playbook Database</title>
    
    <!-- Hyros Tracking -->
    <script>
      var head = document.head;
      var script = document.createElement('script');
      script.type = 'text/javascript';
      script.src = "https://214063.t.hyros.com/v1/lst/universal-script?ph=7837dde81f7a1edf89968df203bb688bc224713787dacd723292b185236316ea&tag=!clicked&embed=true&ref_url=" + encodeURI(document.URL);
      head.appendChild(script);
    </script>

    <!-- Privacy-friendly analytics by Plausible -->
    <script async src="https://plausible.io/js/pa-kwANCMJz41rDSJyqhx4Ql.js"></script>
    <script>
      window.plausible=window.plausible||function(){(plausible.q=plausible.q||[]).push(arguments)},plausible.init=plausible.init||function(i){plausible.o=i||{}};
      plausible.init()
    </script>

    <!-- Microsoft Clarity Tracking -->
    <script type="text/javascript">
      (function(c,l,a,r,i,t,y){
        c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};
        t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;
        y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);
      })(window, document, "clarity", "script", "lu5jsl7yns");
    </script>

    <!-- FOXYCART Loader -->
    <script data-cfasync="false" src="https://cdn.foxycart.com/checkout.civil.gg/loader.js" async defer></script>
    
    <!-- Foxy Customer Portal -->

    <!-- Foxy Customer Portal Content Protection - Attributes v1.6 -->
    <script>
      var FC = FC || {};
      (function (FC) {
        // Script Settings
        let protectedPath = "/members",
          loginOrSignupPath = "/login",
          redirectIfNoActiveSubscriptions = true,
          useLatestTransactionOnly = false,
          ignoreSubscriptionsWithPastDue = true,
          removeElementsFromPage = false,
          webhookEndpointURL = "";

        // Dynamic Login Redirect Logic
        const redirectsByPath = {
          "/tournament-sign-up-members": "/tournament-sign-up-members",
        };
        const defaultLoginRedirect = "/members/dashboard";
        const currentPath = window.location.pathname;
        let loginRedirect = redirectsByPath[currentPath] ?? defaultLoginRedirect;

        let authenticated=!1,activeSubs=0,activeSubCodes=[],hasDynamicRedirect=!1;function clearLocalStorage(){localStorage.removeItem("fx.customer.attributes"),localStorage.removeItem("fx.customer.details"),localStorage.removeItem("fx.customer.firstName"),localStorage.removeItem("fx.customer.subs"),localStorage.removeItem("fx.customer.transactions"),authenticated=!1,activeSubs=0,activeSubCodes=[],pastDueAmount=0,transactionCodes=[],customerDetails={},customerAttributes={}}transactionCodes=[],pastDueAmount=0,customerDetails={},customerAttributes={},portal=document.getElementsByTagName("foxy-customer-portal")[0],portalSessionKey="session",attributeIfAuthenticated='[foxy-logic-authenticated="true"]',attributeIfAnonymous='[foxy-logic-authenticated="false"]',attributeIfSubscriber='[foxy-logic-subscribed="true"]',attributeIfNotSubscriber='[foxy-logic-subscribed="false"]',attributeIfSubscriberByCode="[foxy-logic-subscribed-to]",attributeIfNotSubscriberByCode="[foxy-logic-not-subscribed-to]",attributeIfTransactionByCode="[foxy-logic-transaction-includes]",attributeIfNotTransactionByCode="[foxy-logic-transaction-not-includes]",attributeIfAttributeByName="[foxy-logic-customer-attribute-includes]",attributeIfNotAttributeByName="[foxy-logic-customer-attribute-not-includes]",attributeIfSubscriberPastDue='[foxy-logic-subscriber-past-due="true"]',attributeIfNotSubscriberPastDue='[foxy-logic-subscriber-past-due="false"]',attributeSubscriberPastDueAmount='[foxy-logic-display="subscription-past-due-amount"]',attributeCustomerId='[foxy-logic-display="customer-id"]',attributeCustomerFirstName='[foxy-logic-display="customer-first-name"]',attributeCustomerLastName='[foxy-logic-display="customer-last-name"]',attributeCustomerEmail='[foxy-logic-display="customer-email-address"]',attributeIfAttributeFavorite="[foxy-logic-favorite-includes]",attributeIfAttributeNotFavorite="[foxy-logic-favorite-not-includes]",attributeItemFavoriteCode="[foxy-logic-favorite-code]",attributeCustomerFavorite='[foxy-logic-action="favorite"]',attributeCustomerUnfavorite='[foxy-logic-action="unfavorite"]',attributeCustomerLogout='[foxy-logic-action="logout"]',customElements.whenDefined("foxy-customer-portal").then((()=>{portal&&(portal.addEventListener("signin",(function(t){fetchCustomerData(!t.detail.forcePasswordReset)})),portal.addEventListener("passwordreset",(function(t){handleOnLogInRedirect()})),portal.addEventListener("signout",(function(){clearLocalStorage(),updatePage()})),checkAuthentication(),authenticated&&fetchCustomerData(!1))})),document.addEventListener("click",(async function(t){const e=t.target;if(t.target.matches(attributeCustomerLogout+","+attributeCustomerLogout+" *"))return localStorage.removeItem(portalSessionKey),clearLocalStorage(),void window.location.reload();(e.matches(attributeCustomerUnfavorite)||e.matches(attributeCustomerFavorite))&&await handleFavorites(t)}));let fetchCustomerData=async function(t=!0){let e=getSessionToken();if(e){const o=portal?.getAttribute("base")?.split("/s/")[0]??new URL(JSON.parse(localStorage.getItem("session")).sso).origin,r={"Content-Type":"application/json","FOXY-API-VERSION":"1",Authorization:"Bearer "+e},[a,s,n]=await Promise.all([fetch(o+"/s/customer",{headers:r}),fetch(o+"/s/customer/transactions?zoom=items,items:item_options",{headers:r}),fetch(o+"/s/customer/subscriptions?zoom=transaction_template,transaction_template:items,transaction_template:items:item_options",{headers:r})]),u=await a.json(),c=await s.json(),l=await n.json(),d=authenticated;if(checkAuthentication(),u){if(customerDetails={id:u.id,first_name:u.first_name,last_name:u.last_name,email:u.email,last_login_date:u.last_login_date},localStorage.setItem("fx.customer.details",JSON.stringify(customerDetails)),customerAttributes={},u._embedded?.["fx:attributes"]){let t=u._embedded["fx:attributes"];for(let e=0;e<t.length;e++){let o=t[e],r=o.name.replace(" ","_");customerAttributes[r]={id:o._links.self.href.split("/attributes/")[1],value:o.value}}}localStorage.setItem("fx.customer.attributes",JSON.stringify(customerAttributes))}if(transactionCodes=[],c._embedded?.["fx:transactions"]){let t=c._embedded["fx:transactions"];for(let e=0;e<t.length;e++){let o=t[e]?._embedded?.["fx:items"];if(o&&o.length){for(let t=0;t<o.length;t++)""!=o[t].code&&-1===transactionCodes.indexOf(o[t].code)&&transactionCodes.push(o[t].code);if(useLatestTransactionOnly&&0==i)break}}}if(localStorage.setItem("fx.customer.transactions",JSON.stringify({codes:transactionCodes})),activeSubCodes=[],pastDueAmount=0,l._embedded?.["fx:subscriptions"]){let t=l._embedded["fx:subscriptions"];for(let e=0;e<t.length;e++){let o=t[e];if(o.is_active){(!ignoreSubscriptionsWithPastDue||ignoreSubscriptionsWithPastDue&&0==o.past_due_amount)&&(activeSubs+=1),o.past_due_amount>0&&(pastDueAmount+=o.past_due_amount);let t=o._embedded["fx:transaction_template"]._embedded["fx:items"];for(let e=0;e<t.length;e++)""!=t[e].code&&-1===activeSubCodes.indexOf(t[e].code)&&activeSubCodes.push(t[e].code)}}}localStorage.setItem("fx.customer.subs",JSON.stringify({count:activeSubs,codes:activeSubCodes,past_due_amount:pastDueAmount}));const m=new Event("fx.fetch.done");window.dispatchEvent(m),checkForDynamicRedirect(),!d&&t&&handleOnLogInRedirect()}updatePage()},handleOnLogInRedirect=function(){""!=loginRedirect&&authenticated&&!window.location.pathname.match(new RegExp("^"+loginRedirect))&&window.location.assign(window.location.origin+loginRedirect)},updatePage=function(){""!=protectedPath&&window.location.pathname.match(new RegExp("^"+protectedPath))&&(!authenticated||!activeSubs&&redirectIfNoActiveSubscriptions)&&window.location.assign(window.location.origin+loginOrSignupPath),customerDetails.hasOwnProperty("id")&&Array.prototype.slice.call(document.querySelectorAll(attributeCustomerId)).forEach((t=>{t.innerHTML=customerDetails.id})),customerDetails.hasOwnProperty("first_name")&&Array.prototype.slice.call(document.querySelectorAll(attributeCustomerFirstName)).forEach((t=>{t.innerHTML=customerDetails.first_name})),customerDetails.hasOwnProperty("last_name")&&Array.prototype.slice.call(document.querySelectorAll(attributeCustomerLastName)).forEach((t=>{t.innerHTML=customerDetails.last_name})),customerDetails.hasOwnProperty("email")&&Array.prototype.slice.call(document.querySelectorAll(attributeCustomerEmail)).forEach((t=>{t.innerHTML=customerDetails.email})),pastDueAmount>0&&Array.prototype.slice.call(document.querySelectorAll(attributeSubscriberPastDueAmount)).forEach((t=>{t.innerHTML=pastDueAmount}));let t=[attributeIfSubscriberByCode,attributeIfTransactionByCode,attributeIfAttributeByName,attributeIfNotSubscriberByCode,attributeIfNotTransactionByCode,attributeIfNotAttributeByName,attributeIfAuthenticated,attributeIfSubscriber,attributeIfSubscriberPastDue,attributeIfAttributeFavorite,attributeIfAttributeNotFavorite],e=[],o=function(e){e=a(e),t.includes(e)||t.push(e)},r=function(o,r){o=a(o),r?e.includes(o)||e.push(o):t=t.filter((function(t){return t!=o}))},a=function(t){return t.replaceAll(/[^\-_a-z0-9="[\]]/gi,"\\$&")},i=function(t,e){return`${t.replace(/\]$/,`="${e}"]`)}`};authenticated?(o(attributeIfAnonymous),r(attributeIfAuthenticated)):(o(attributeIfAuthenticated),r(attributeIfAnonymous)),authenticated&&activeSubs?(o(attributeIfNotSubscriber),r(attributeIfSubscriber)):(o(attributeIfSubscriber),r(attributeIfNotSubscriber)),pastDueAmount?(o(attributeIfNotSubscriberPastDue),r(attributeIfSubscriberPastDue)):(o(attributeIfSubscriberPastDue),r(attributeIfNotSubscriberPastDue));let s=activeSubCodes.map((t=>{let e=i(attributeIfSubscriberByCode,t);return r(e,!0),e}));Array.prototype.slice.call(document.querySelectorAll(attributeIfNotSubscriberByCode)).forEach((t=>{let e=t.getAttribute(attributeIfNotSubscriberByCode.replace(/\[|\]/g,""));e&&s.includes(i(attributeIfSubscriberByCode,e))||r(i(attributeIfNotSubscriberByCode,e),!0)}));let n=transactionCodes.map((t=>{let e=i(attributeIfTransactionByCode,t);return r(e,!0),e}));Array.prototype.slice.call(document.querySelectorAll(attributeIfNotTransactionByCode)).forEach((t=>{let e=t.getAttribute(attributeIfNotTransactionByCode.replace(/\[|\]/g,""));e&&n.includes(i(attributeIfTransactionByCode,e))||r(i(attributeIfNotTransactionByCode,e),!0)}));let u=Object.keys(customerAttributes).map((t=>{let e=i(attributeIfAttributeByName,t);return t.includes("favorite-")&&(e=i(attributeIfAttributeFavorite,t.split("favorite-")[1])),r(e,!0),e}));Array.prototype.slice.call(document.querySelectorAll(attributeIfNotAttributeByName)).forEach((t=>{let e=t.getAttribute(attributeIfNotAttributeByName.replace(/\[|\]/g,""));e&&u.includes(i(attributeIfAttributeByName,e))||r(i(attributeIfNotAttributeByName,e),!0)})),Array.prototype.slice.call(document.querySelectorAll(attributeIfAttributeNotFavorite)).forEach((t=>{let e=t.getAttribute(attributeIfAttributeNotFavorite.replace(/\[|\]/g,""));e&&u.includes(i(attributeIfAttributeFavorite,e))||r(i(attributeIfAttributeNotFavorite,e),!0)}));let c=`\n            ${t.join(", ")} {\n                display: none !important;\n            }\n        `;e.length&&(c+=`\n                ${e.join(", ")} {\n                    display: revert !important;\n                }\n            `);let l=document.querySelector("[data-foxy-portal-style]");if(l)l.textContent=c;else{let t=document.createElement("style");t.textContent=c,t.setAttribute("data-foxy-portal-style",!0),document.head.appendChild(t)}if(!portal&&removeElementsFromPage)for(let o=0;o<t.length;o++){const r=t[o];e.includes(r)||document.querySelectorAll(r).forEach((t=>{const o=t.attributes;let r=!0;for(let t=0;t<o.length;t++){const a=o[t];if(e.includes(`[${a.name}="${a.value}"]`)){r=!1;break}}r&&t.remove()}))}},handleFavorites=async function(t){if(!webhookEndpointURL)return;const e=t.target;let o=getCustomerID(),r=t=>{e.style.setProperty("display","none","important"),t.style.setProperty("display","revert","important"),e.style.setProperty("pointer-events","none"),t.style.setProperty("pointer-events","none"),setTimeout((()=>{e.style.setProperty("pointer-events","auto"),t.style.setProperty("pointer-events","auto")}),2e3),setTimeout((()=>{e.style.setProperty("display","unset",""),t.style.setProperty("display","unset","")}),1e4)},a=async function(t=!1){const r=e?.closest(attributeItemFavoriteCode).getAttribute(attributeItemFavoriteCode.replace(/\[|\]/g,"")),a=customerAttributes[`favorite-${r}`]?.id;try{const e={"Content-Type":"application/json","FOXY-API-VERSION":"1"},i=JSON.stringify({customer_id:o,item_code:r,attribute_id:!t&&a}),s=await fetch(webhookEndpointURL,{headers:e,method:"POST",body:i});if(!s.ok){throw t?new Error(`There was an error adding favorite to product with ID ${r} `):new Error(`There was an error removing favorite from product with ID ${r} `)}const n=await s.json();if(!t&&!n.message.includes("successfully"))throw new Error(`There was an error removing favorite from product with ID ${r} `)}catch(t){console.log(t),console.log(t?.type)}};if(e.matches(attributeCustomerFavorite)&&o){return r(document.querySelector(attributeCustomerUnfavorite)),await a(!0),void await fetchCustomerData(!1)}if(e.matches(attributeCustomerUnfavorite)&&o){return r(document.querySelector(attributeCustomerFavorite)),await a(!1),void await fetchCustomerData(!1)}},init=function(){try{checkAuthentication();let t=JSON.parse(localStorage.getItem("fx.customer.subs"));t&&(activeSubs=parseInt(t.count),activeSubCodes=t.codes,pastDueAmount=t.past_due_amount);let e=JSON.parse(localStorage.getItem("fx.customer.transactions"));e&&e.hasOwnProperty("codes")?transactionCodes=e.codes:transactionCodes=e,transactionCodes||(transactionCodes=[]),customerAttributes=JSON.parse(localStorage.getItem("fx.customer.attributes")),customerAttributes||(customerAttributes={}),customerDetails=JSON.parse(localStorage.getItem("fx.customer.details")),customerDetails||(customerDetails={});const o=new Event("fx.fetch.done");window.dispatchEvent(o),authenticated&&fetchCustomerData(!1)}catch(t){console.log("Portal content protection initialization error:",t)}authenticated||clearLocalStorage(),updatePage()},parseJWT=function(t){let e=t.split(".")[1].replace(/-/g,"+").replace(/_/g,"/"),o=decodeURIComponent(atob(e).split("").map((function(t){return"%"+("00"+t.charCodeAt(0).toString(16)).slice(-2)})).join(""));return JSON.parse(o)},checkAuthentication=function(){let t=JSON.parse(localStorage.getItem(portalSessionKey));if(t&&t.hasOwnProperty("jwt")){let e=parseJWT(t.jwt),o=Math.floor(new Date(t.date_created).getTime()/1e3)+t.expires_in;authenticated=o>Math.floor(Date.now()/1e3)&&e.hasOwnProperty("customer_id")}},getSessionToken=function(){let t=JSON.parse(localStorage.getItem(portalSessionKey));return!(!t||!t.hasOwnProperty("session_token"))&&t.session_token},getCustomerID=function(){let t=JSON.parse(localStorage.getItem(portalSessionKey));return!(!t||!t.hasOwnProperty("sso"))&&new URL(t.sso).searchParams.get("fc_customer_id")},checkForDynamicRedirect=function(){const t=new URLSearchParams(window.location.search),e=window.location.hash,o=t.get("redirect");o?(loginRedirect=`${decodeURIComponent(o)}${e}`,hasDynamicRedirect=!0):hasDynamicRedirect=!1};FC.hasOwnProperty("custom")||(FC.custom={}),FC.custom.updatePage=updatePage,FC.custom.hasTransactionByCode=function(t){return transactionCodes.includes(t)},FC.custom.hasSubscriptionByCode=function(t){return activeSubCodes.includes(t)},FC.custom.hasAttributeByName=function(t,e){let o=customerAttributes.hasOwnProperty(t);return o&&e&&(o=customerAttributes[t]?.value==e),o},FC.custom.getAttributeByName=function(t){return!!customerAttributes.hasOwnProperty(t)&&customerAttributes[t]?.value},FC.custom.isAuthenticated=function(){return checkAuthentication(),authenticated},FC.custom.isSubscriber=function(){return checkAuthentication(),authenticated&&activeSubs>0},init();
      })(FC);
    </script>
    <script type="module" crossorigin src="/assets/index-DJ0byBH8.js"></script>
    <link rel="stylesheet" crossorigin href="/assets/index-BlgRFvv-.css">
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>
