<!DOCTYPE html><html lang="pt-BR"> <head><meta charset="UTF-8"><meta name="description" content="Sistema de gerenciamento de quadras de squash"><meta name="viewport" content="width=device-width, initial-scale=1.0"><!-- CSP must be set early to avoid warnings about script-src fallback --><meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline' 'unsafe-eval' https://static.cloudflareinsights.com https://challenges.cloudflare.com https://www.clarity.ms; script-src-elem 'self' 'unsafe-inline' https://static.cloudflareinsights.com https://challenges.cloudflare.com https://www.clarity.ms; default-src 'self'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' data: https://fonts.gstatic.com; img-src 'self' data: https:; frame-src 'self' https://challenges.cloudflare.com; connect-src 'self' https://api-play.calvin.com.br wss://api-play.calvin.com.br https://*.calvin.com.br https://static.cloudflareinsights.com https://cloudflareinsights.com https://challenges.cloudflare.com https://firebase.googleapis.com https://firebaseinstallations.googleapis.com https://fcm.googleapis.com https://fonts.googleapis.com https://fonts.gstatic.com https://accounts.google.com https://oauth2.googleapis.com https://www.clarity.ms https://*.clarity.ms;"><link rel="icon" type="image/svg+xml" href="/favicon.svg"><link rel="manifest" href="/manifest.json"><meta name="theme-color" content="#000000"><meta name="generator" content="Astro v4.16.19"><title>Squash Court Manager - Court Management Platform</title><meta name="astro-view-transitions-enabled" content="true"><meta name="astro-view-transitions-fallback" content="animate"><!-- Preconnect to Cloudflare Turnstile to improve performance --><link rel="preconnect" href="https://challenges.cloudflare.com" crossorigin><link rel="dns-prefetch" href="https://challenges.cloudflare.com"><!-- Set deploy ID for client-side components --><script>(function(){const deployId = "b99f274";

      window.__DEPLOY_ID__ = deployId;
    })();</script><!-- Cloudflare Insights SRI Fix - Must run before any other scripts --><script>
      // CRITICAL: This must run immediately to intercept Cloudflare Insights scripts
      // Cloudflare Pages injects scripts with invalid integrity attributes
      (function() {
        'use strict';
        
        // Layer 1: Intercept createElement BEFORE any scripts are created
        const originalCreateElement = document.createElement;
        document.createElement = function(tagName, options) {
          const element = originalCreateElement.call(this, tagName, options);
          if (tagName.toLowerCase() === 'script') {
            // Mark all scripts for potential Cloudflare Insights interception
            const originalSetAttribute = element.setAttribute;
            const originalSetAttributeNS = element.setAttributeNS;
            const originalRemoveAttribute = element.removeAttribute;
            
            // Track if this is a Cloudflare Insights script
            let isCloudflareInsights = false;
            
            element.setAttribute = function(name, value) {
              if (name === 'src' && typeof value === 'string' && value.includes('cloudflareinsights.com')) {
                isCloudflareInsights = true;
                // Immediately remove integrity if it exists
                if (this.hasAttribute('integrity')) {
                  originalRemoveAttribute.call(this, 'integrity');
                }
                if (this.hasAttribute('crossorigin')) {
                  originalRemoveAttribute.call(this, 'crossorigin');
                }
              }
              // Block integrity and crossorigin for Cloudflare Insights scripts
              if (isCloudflareInsights && (name === 'integrity' || name === 'crossorigin')) {
                return; // Silently ignore
              }
              return originalSetAttribute.call(this, name, value);
            };
            
            element.setAttributeNS = function(namespace, name, value) {
              if (isCloudflareInsights && (name === 'integrity' || name === 'crossorigin')) {
                return; // Silently ignore
              }
              return originalSetAttributeNS.call(this, namespace, name, value);
            };
            
            // Intercept src property setter
            try {
              const srcDescriptor = Object.getOwnPropertyDescriptor(HTMLScriptElement.prototype, 'src');
              if (srcDescriptor && srcDescriptor.set) {
                const originalSrcSetter = srcDescriptor.set;
                Object.defineProperty(element, 'src', {
                  set: function(value) {
                    if (typeof value === 'string' && value.includes('cloudflareinsights.com')) {
                      isCloudflareInsights = true;
                      // Remove integrity immediately
                      if (this.hasAttribute('integrity')) {
                        originalRemoveAttribute.call(this, 'integrity');
                      }
                      if (this.hasAttribute('crossorigin')) {
                        originalRemoveAttribute.call(this, 'crossorigin');
                      }
                    }
                    originalSrcSetter.call(this, value);
                  },
                  get: srcDescriptor.get,
                  configurable: true,
                  enumerable: true
                });
              }
            } catch (e) {
              // Ignore errors in property descriptor access
            }
          }
          return element;
        };
        
        // Layer 2: Remove integrity from scripts already in the DOM
        // This runs synchronously before the page continues parsing
        function removeIntegritySync() {
          try {
            // Check head
            if (document.head) {
              const headScripts = document.head.querySelectorAll('script[src*="cloudflareinsights.com"]');
              headScripts.forEach(function(script) {
                if (script.hasAttribute('integrity')) {
                  script.removeAttribute('integrity');
                }
                if (script.hasAttribute('crossorigin')) {
                  script.removeAttribute('crossorigin');
                }
              });
            }
            // Check body (may not exist yet)
            if (document.body) {
              const bodyScripts = document.body.querySelectorAll('script[src*="cloudflareinsights.com"]');
              bodyScripts.forEach(function(script) {
                if (script.hasAttribute('integrity')) {
                  script.removeAttribute('integrity');
                }
                if (script.hasAttribute('crossorigin')) {
                  script.removeAttribute('crossorigin');
                }
              });
            }
          } catch (e) {
            // Ignore errors
          }
        }
        
        // Run immediately
        removeIntegritySync();
        
        // Layer 3: MutationObserver with immediate callback
        const observer = new MutationObserver(function(mutations) {
          mutations.forEach(function(mutation) {
            // Handle new nodes
            mutation.addedNodes.forEach(function(node) {
              if (node.nodeType === Node.ELEMENT_NODE && node.nodeName === 'SCRIPT') {
                if (node.src && node.src.includes('cloudflareinsights.com')) {
                  node.removeAttribute('integrity');
                  node.removeAttribute('crossorigin');
                }
              }
            });
            
            // Handle attribute changes
            if (mutation.type === 'attributes') {
              const target = mutation.target;
              if (target.nodeName === 'SCRIPT' && target.src && target.src.includes('cloudflareinsights.com')) {
                if (mutation.attributeName === 'integrity' || mutation.attributeName === 'crossorigin') {
                  target.removeAttribute(mutation.attributeName);
                }
              }
            }
          });
        });
        
        // Start observing immediately
        const observeOptions = {
          childList: true,
          subtree: true,
          attributes: true,
          attributeFilter: ['integrity', 'crossorigin', 'src']
        };
        
        // Observe document element immediately
        if (document.documentElement) {
          observer.observe(document.documentElement, observeOptions);
        }
        if (document.head) {
          observer.observe(document.head, observeOptions);
        }
        // Body may not exist yet, observe when it's created
        if (document.body) {
          observer.observe(document.body, observeOptions);
        } else {
          const bodyObserver = new MutationObserver(function() {
            if (document.body) {
              observer.observe(document.body, observeOptions);
              bodyObserver.disconnect();
            }
          });
          if (document.documentElement) {
            bodyObserver.observe(document.documentElement, { childList: true });
          }
        }
        
        // Also run on DOMContentLoaded as fallback
        if (document.readyState === 'loading') {
          document.addEventListener('DOMContentLoaded', removeIntegritySync, { once: true });
        } else {
          removeIntegritySync();
        }
      })();
    </script><script>
      (function() {
        const THEME_STORAGE_KEY = 'squash-theme';
        const getStoredTheme = () => {
          try {
            return localStorage.getItem(THEME_STORAGE_KEY);
          } catch {
            return null;
          }
        };
        const getSystemTheme = () => {
          if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
            return 'dark';
          }
          return 'light';
        };
        const getEffectiveTheme = (theme) => {
          return theme === 'system' || !theme ? getSystemTheme() : theme;
        };
        const stored = getStoredTheme();
        const theme = stored || 'system';
        const effective = getEffectiveTheme(theme);
        if (effective === 'dark') {
          document.documentElement.classList.add('dark');
        }
      })();
    </script><!-- Microsoft Clarity Analytics --><script>
      (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", "ubv7bhkp7y");
    </script><style>.astro-route-announcer{position:absolute;left:0;top:0;clip:rect(0 0 0 0);clip-path:inset(50%);overflow:hidden;white-space:nowrap;width:1px;height:1px}
</style>
<link rel="stylesheet" href="/assets/_id_.OjO3YTbE.css"><script type="module" src="/assets/hoisted.CnRZTM6Q.js"></script>
<script type="module" src="/assets/page.CAEqpuDM.js"></script></head> <body class="min-h-screen bg-background flex flex-col"> <style>astro-island,astro-slot,astro-static-slot{display:contents}</style><script>(()=>{var e=async t=>{await(await t())()};(self.Astro||(self.Astro={})).load=e;window.dispatchEvent(new Event("astro:load"));})();;(()=>{var A=Object.defineProperty;var g=(i,o,a)=>o in i?A(i,o,{enumerable:!0,configurable:!0,writable:!0,value:a}):i[o]=a;var d=(i,o,a)=>g(i,typeof o!="symbol"?o+"":o,a);{let i={0:t=>m(t),1:t=>a(t),2:t=>new RegExp(t),3:t=>new Date(t),4:t=>new Map(a(t)),5:t=>new Set(a(t)),6:t=>BigInt(t),7:t=>new URL(t),8:t=>new Uint8Array(t),9:t=>new Uint16Array(t),10:t=>new Uint32Array(t),11:t=>1/0*t},o=t=>{let[l,e]=t;return l in i?i[l](e):void 0},a=t=>t.map(o),m=t=>typeof t!="object"||t===null?t:Object.fromEntries(Object.entries(t).map(([l,e])=>[l,o(e)]));class y extends HTMLElement{constructor(){super(...arguments);d(this,"Component");d(this,"hydrator");d(this,"hydrate",async()=>{var b;if(!this.hydrator||!this.isConnected)return;let e=(b=this.parentElement)==null?void 0:b.closest("astro-island[ssr]");if(e){e.addEventListener("astro:hydrate",this.hydrate,{once:!0});return}let c=this.querySelectorAll("astro-slot"),n={},h=this.querySelectorAll("template[data-astro-template]");for(let r of h){let s=r.closest(this.tagName);s!=null&&s.isSameNode(this)&&(n[r.getAttribute("data-astro-template")||"default"]=r.innerHTML,r.remove())}for(let r of c){let s=r.closest(this.tagName);s!=null&&s.isSameNode(this)&&(n[r.getAttribute("name")||"default"]=r.innerHTML)}let p;try{p=this.hasAttribute("props")?m(JSON.parse(this.getAttribute("props"))):{}}catch(r){let s=this.getAttribute("component-url")||"<unknown>",v=this.getAttribute("component-export");throw v&&(s+=` (export ${v})`),console.error(`[hydrate] Error parsing props for component ${s}`,this.getAttribute("props"),r),r}let u;await this.hydrator(this)(this.Component,p,n,{client:this.getAttribute("client")}),this.removeAttribute("ssr"),this.dispatchEvent(new CustomEvent("astro:hydrate"))});d(this,"unmount",()=>{this.isConnected||this.dispatchEvent(new CustomEvent("astro:unmount"))})}disconnectedCallback(){document.removeEventListener("astro:after-swap",this.unmount),document.addEventListener("astro:after-swap",this.unmount,{once:!0})}connectedCallback(){if(!this.hasAttribute("await-children")||document.readyState==="interactive"||document.readyState==="complete")this.childrenConnectedCallback();else{let e=()=>{document.removeEventListener("DOMContentLoaded",e),c.disconnect(),this.childrenConnectedCallback()},c=new MutationObserver(()=>{var n;((n=this.lastChild)==null?void 0:n.nodeType)===Node.COMMENT_NODE&&this.lastChild.nodeValue==="astro:end"&&(this.lastChild.remove(),e())});c.observe(this,{childList:!0}),document.addEventListener("DOMContentLoaded",e)}}async childrenConnectedCallback(){let e=this.getAttribute("before-hydration-url");e&&await import(e),this.start()}async start(){let e=JSON.parse(this.getAttribute("opts")),c=this.getAttribute("client");if(Astro[c]===void 0){window.addEventListener(`astro:${c}`,()=>this.start(),{once:!0});return}try{await Astro[c](async()=>{let n=this.getAttribute("renderer-url"),[h,{default:p}]=await Promise.all([import(this.getAttribute("component-url")),n?import(n):()=>()=>{}]),u=this.getAttribute("component-export")||"default";if(!u.includes("."))this.Component=h[u];else{this.Component=h;for(let f of u.split("."))this.Component=this.Component[f]}return this.hydrator=p,this.hydrate},e,this)}catch(n){console.error(`[astro-island] Error hydrating ${this.getAttribute("component-url")}`,n)}}attributeChangedCallback(){this.hydrate()}}d(y,"observedAttributes",["props"]),customElements.get("astro-island")||customElements.define("astro-island",y)}})();</script><astro-island uid="Z3Qmo4" prefix="r0" component-url="/assets/offline-indicator.CmKVcBur.js" component-export="OfflineIndicator" renderer-url="/assets/client.AWK8HcqT.js" props="{}" ssr="" client="load" opts="{&quot;name&quot;:&quot;OfflineIndicator&quot;,&quot;value&quot;:true}"></astro-island> <astro-island uid="Z1aS45U" prefix="r2" component-url="/assets/Navigation.CjL9eE0y.js" component-export="Navigation" renderer-url="/assets/client.AWK8HcqT.js" props="{}" ssr="" client="load" opts="{&quot;name&quot;:&quot;Navigation&quot;,&quot;value&quot;:true}"></astro-island> <main class="flex-1">   <astro-island uid="Z1pmfP" prefix="r1" component-url="/assets/DashboardRedirect.CNi0zUf7.js" component-export="DashboardRedirect" renderer-url="/assets/client.AWK8HcqT.js" props="{}" ssr="" client="load" opts="{&quot;name&quot;:&quot;DashboardRedirect&quot;,&quot;value&quot;:true}" await-children=""><div class="flex items-center justify-center min-h-screen"><div class="text-center"><div class="animate-spin rounded-full h-12 w-12 border-b-2 border-primary mx-auto mb-4"></div><p class="text-muted-foreground">Loading...</p></div></div><!--astro:end--></astro-island>  </main> <astro-island uid="1vuEP8" prefix="r3" component-url="/assets/Footer.ttAYtq_7.js" component-export="Footer" renderer-url="/assets/client.AWK8HcqT.js" props="{}" ssr="" client="load" opts="{&quot;name&quot;:&quot;Footer&quot;,&quot;value&quot;:true}" await-children=""><footer class="border-t bg-background/50 py-2 mt-auto"><div class="container mx-auto px-4"><div class="flex items-center justify-center gap-2 text-xs text-muted-foreground"><span class="font-mono">squash-web: <span class="text-foreground/70">local</span></span><span class="text-muted-foreground/50">/</span><span class="font-mono">squash-court-manager: <span class="text-foreground/70">...</span></span></div></div></footer><!--astro:end--></astro-island> <astro-island uid="ZfABo8" prefix="r4" component-url="/assets/BottomNav.rUmZBOme.js" component-export="BottomNav" renderer-url="/assets/client.AWK8HcqT.js" props="{}" ssr="" client="load" opts="{&quot;name&quot;:&quot;BottomNav&quot;,&quot;value&quot;:true}"></astro-island> <astro-island uid="x0Wig" prefix="r5" component-url="/assets/toaster.vppyd9ST.js" component-export="Toaster" renderer-url="/assets/client.AWK8HcqT.js" props="{}" ssr="" client="load" opts="{&quot;name&quot;:&quot;Toaster&quot;,&quot;value&quot;:true}" await-children=""><section aria-label="Notifications alt+T" tabindex="-1" aria-live="polite" aria-relevant="additions text" aria-atomic="false"></section><!--astro:end--></astro-island>  </body> </html>