---
interface Props {
  title?: string;
  description?: string;
  ogImage?: string;
  canonical?: string;
  metadata?: {
    title?: string;
    description?: string;
    ogImage?: string;
    canonical?: string;
    ignoreTitleTemplate?: boolean;
  };
}

import Seo from "@/components/seo/Seo.astro";
import Schema from "@/components/seo/Schema.astro";
import Navbar from "@/components/layout/Navbar.astro";
import Footer from "@/components/layout/Footer.astro";
import { ClientRouter } from "astro:transitions";
import "@/styles/global.css";

import { siteConfig } from "@/config/site";

const { title, description, ogImage, canonical, metadata } = Astro.props;

const finalTitle = metadata?.title || title;
const finalDescription = metadata?.description || description;
const finalOgImage = metadata?.ogImage || ogImage;
const finalCanonical = metadata?.canonical || canonical;
const finalIgnoreTitleTemplate = metadata?.ignoreTitleTemplate || false;
---

<!doctype html>
<html lang={siteConfig.lang} class="scroll-smooth">
  <head>
    <Seo
      title={finalTitle}
      description={finalDescription}
      ogImage={finalOgImage}
      canonical={finalCanonical}
      ignoreTitleTemplate={finalIgnoreTitleTemplate}
    />
    <ClientRouter />
    <Schema type="WebSite" data={{}} />
    <slot name="head" />
    <script is:inline>
      const getTheme = () => {
        if (
          typeof localStorage !== "undefined" &&
          localStorage.getItem("theme")
        ) {
          return localStorage.getItem("theme");
        }
        if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
          return "dark";
        }
        return "light";
      };

      const setTheme = () => {
        const theme = getTheme();
        if (theme === "light") {
          document.documentElement.setAttribute("data-theme", "light");
        } else {
          document.documentElement.setAttribute("data-theme", "dark");
        }
        window.localStorage.setItem("theme", theme);
      };

      // Run immediately on first hard load
      setTheme();

      // Run before the new page renders during View Transitions
      document.addEventListener("astro:after-swap", setTheme);
    </script>
  </head>
  <body
    class="bg-background text-foreground antialiased selection:bg-blue-500/30 dark:selection:text-blue-200"
  >
    <a
      href="#main-content"
      class="sr-only focus:not-sr-only focus:absolute focus:top-4 focus:left-4 z-50 rounded-md bg-primary px-4 py-2 text-white shadow-lg ring-2 ring-white"
    >
      Skip to content
    </a>

    <div class="relative flex min-h-screen flex-col overflow-x-hidden">
      <!-- Background Glow -->
      <div class="pointer-events-none fixed inset-0 z-0 hidden md:block">
        <div
          class="absolute inset-0 bg-[radial-gradient(circle_at_top_left,rgba(59,130,246,0.15)_0%,transparent_50%)]"
        >
        </div>
        <div
          class="absolute inset-0 bg-[radial-gradient(circle_at_bottom_right,rgba(168,85,247,0.15)_0%,transparent_50%)]"
        >
        </div>
      </div>

      <Navbar />
      <main id="main-content" class="relative z-10 grow pt-18">
        <slot />
      </main>
      <Footer />
    </div>
    <script>
      // Keep a global reference to prevent duplicate observers during View Transitions
      let scrollObserver: IntersectionObserver | null = null;

      const setupAnimations = () => {
        // Disconnect previous observer if it exists (prevents ghost triggers)
        if (scrollObserver) {
          scrollObserver.disconnect();
        }

        // Instantly bypass scroll animations for elements already visible in viewport
        // This solves the Astro View Transitions "double bounce" issue completely
        document.querySelectorAll(".reveal:not(.active)").forEach((el) => {
          if (el.getBoundingClientRect().top < window.innerHeight) {
            // Temporarily disable transition during initial show
            el.setAttribute(
              "style",
              "transition: none !important; transform: none !important;",
            );
            el.classList.add("active");
            // Reactivate their explicit styles so CSS takes over next time
            requestAnimationFrame(() => {
              el.removeAttribute("style");
            });
          }
        });

        scrollObserver = new IntersectionObserver(
          (entries, observer) => {
            entries.forEach((entry) => {
              if (entry.isIntersecting) {
                // Add class synchronously to prevent frame delays
                entry.target.classList.add("active");
                observer.unobserve(entry.target);
              }
            });
          },
          {
            root: null,
            rootMargin: "0px",
            threshold: 0.1,
          },
        );

        const remainingElements = document.querySelectorAll(
          ".reveal:not(.active)",
        );
        remainingElements.forEach((el) => scrollObserver?.observe(el));
      };

      document.addEventListener("astro:page-load", setupAnimations);
      document.addEventListener("astro:after-swap", setupAnimations);
    </script>
  </body>
</html>
