(function () {
  const reducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;

  // Theme handling
  const html = document.documentElement;
  const stored = localStorage.getItem("gridline-theme");
  const systemDark = window.matchMedia("(prefers-color-scheme: dark)").matches;

  function applyTheme(theme) {
    if (theme === "light") {
      html.classList.add("light");
      html.removeAttribute("data-theme-auto");
    } else if (theme === "dark") {
      html.classList.remove("light");
      html.removeAttribute("data-theme-auto");
    } else {
      // auto
      html.classList.toggle("light", !systemDark && window.matchMedia("(prefers-color-scheme: light)").matches);
      html.setAttribute("data-theme-auto", "");
    }
    updateToggleIcon();
  }

  function updateToggleIcon() {
    const suns = document.querySelectorAll(".theme-icon-sun");
    const moons = document.querySelectorAll(".theme-icon-moon");
    const isLight = html.classList.contains("light");
    suns.forEach((el) => el.classList.toggle("hidden", !isLight));
    moons.forEach((el) => el.classList.toggle("hidden", isLight));
  }

  applyTheme(stored);

  document.getElementById("theme-toggle")?.addEventListener("click", () => {
    const isLight = html.classList.contains("light");
    const next = isLight ? "dark" : "light";
    localStorage.setItem("gridline-theme", next);
    applyTheme(next);
  });

  window
    .matchMedia("(prefers-color-scheme: dark)")
    .addEventListener("change", () => {
      if (html.hasAttribute("data-theme-auto")) {
        applyTheme("auto");
      }
    });

  // OS-aware download buttons (nav + hero). Any element with [data-download]
  // gets the platform-specific download URL; labels are only rewritten when the
  // element does NOT opt out via a data-download-label attribute (nav keeps its
  // compact "Download" label, hero gets "Download for macOS" etc.).
  document.querySelectorAll("a[data-download]").forEach((downloadBtn) => {
    const platform = navigator.platform || "";
    const userAgent = navigator.userAgent || "";
    const isMac = /Mac/i.test(platform) && !/iPhone|iPad/i.test(userAgent);
    const isWin = /Win/i.test(platform);
    const isLinux = /Linux/i.test(platform) && !/Android/i.test(userAgent);
    const isMobile = /Mobi|Android|iPhone|iPad|iPod/i.test(userAgent);
    const keepLabel = downloadBtn.hasAttribute("data-download-label");

    const releasesUrl = "https://github.com/AdrianBonpin/gridline/releases";
    const version = "0.7.10";

    if (isMobile) {
      downloadBtn.href = releasesUrl;
      if (!keepLabel) downloadBtn.textContent = "Get it on GitHub";
    } else if (isMac) {
      downloadBtn.href = `${releasesUrl}/download/v${version}/Gridline_${version}_aarch64.dmg`;
      if (!keepLabel) downloadBtn.textContent = "Download for macOS";
      if (downloadBtn.id === "download") {
        document.getElementById("macos-hint")?.classList.remove("hidden");
      }
    } else if (isWin) {
      downloadBtn.href = `${releasesUrl}/download/v${version}/Gridline_${version}_x64-setup.exe`;
      if (!keepLabel) downloadBtn.textContent = "Download for Windows";
    } else if (isLinux) {
      downloadBtn.href = `${releasesUrl}/download/v${version}/Gridline-${version}-1.x86_64.rpm`;
      if (!keepLabel) downloadBtn.textContent = "Download for Linux";
    } else {
      downloadBtn.href = releasesUrl;
      if (!keepLabel) downloadBtn.textContent = "Download";
    }
  });

  document.getElementById("copy-quarantine")?.addEventListener("click", async () => {
    const command = "sudo xattr -dr com.apple.quarantine /Applications/Gridline.app";
    try {
      await navigator.clipboard.writeText(command);
      const btn = document.getElementById("copy-quarantine");
      if (!btn) return;
      const original = btn.textContent;
      btn.textContent = "Copied";
      setTimeout(() => (btn.textContent = original), 1500);
    } catch {}
  });

  // Nav scroll background
  const nav = document.getElementById("nav");
  function onScroll() {
    if (!nav) return;
    if (window.scrollY > 40) {
      nav.classList.add("bg-[var(--surface)]", "backdrop-blur-md", "border-b", "border-[var(--border)]");
    } else {
      nav.classList.remove("bg-[var(--surface)]", "backdrop-blur-md", "border-b", "border-[var(--border)]");
    }
  }
  window.addEventListener("scroll", onScroll, { passive: true });
  onScroll();

  // Anime.js animations
  let anime;
  try {
    anime = require ? null : window.anime;
  } catch {}

  function loadAnime(callback) {
    if (window.anime) {
      callback(window.anime);
      return;
    }
    const script = document.createElement("script");
    script.src = "/vendor/anime.min.js";
    script.onload = () => callback(window.anime);
    script.onerror = () => revealAnimatedContent();
    document.head.appendChild(script);
  }

  // Revert the entry-animation hiding (html.anime-ready CSS) so content is
  // always visible even if the animation library never loads.
  function revealAnimatedContent() {
    document.documentElement.classList.remove("anime-ready");
  }

  loadAnime((anime) => {
    // Hero entrance
    const hero = document.getElementById("hero");
    if (hero) {
      const eyebrow = hero.querySelector(".hero-animate > .font-mono");
      const h1 = hero.querySelector("h1");
      const subtitle = hero.querySelector(".hero-animate > p:nth-of-type(2)");
      const buttons = hero.querySelector(".hero-animate > div");
      const screenshot = hero.querySelector(".hero-screenshot");
      const macosHint = hero.querySelector("#macos-hint");

      if (reducedMotion) {
        // Reduced motion: reveal the hero immediately (CSS hides it at first
        // paint to avoid flicker, but the timeline below is skipped). Section
        // reveals below still run through the IntersectionObserver.
        anime.set([eyebrow, h1, subtitle, buttons, screenshot, macosHint], { opacity: 1, translateY: 0 });
      } else {
        const heroTl = anime.timeline({ easing: "easeOutExpo" });

        anime.set([eyebrow, h1, subtitle, buttons, screenshot, macosHint], { opacity: 0, translateY: 20 });
        anime.set(screenshot, { opacity: 0, scale: 0.96, translateY: 0 });

        if (eyebrow) heroTl.add({ targets: eyebrow, opacity: [0, 1], translateY: [15, 0] }, 0);
        if (h1) heroTl.add({ targets: h1, opacity: [0, 1], translateY: [30, 0], duration: 800 }, 100);
        if (subtitle) heroTl.add({ targets: subtitle, opacity: [0, 1], translateY: [20, 0] }, 250);
        if (buttons) heroTl.add({ targets: buttons, opacity: [0, 1], translateY: [20, 0] }, 350);
        if (macosHint) heroTl.add({ targets: macosHint, opacity: [0, 1], translateY: [20, 0] }, 400);
        if (screenshot) heroTl.add({ targets: screenshot, opacity: [0, 1], scale: [0.96, 1], duration: 900 }, 450);
      }
    }

    // Section scroll reveals
    const sections = document.querySelectorAll(".section-animate");
    const observer = new IntersectionObserver(
      (entries) => {
        entries.forEach((entry) => {
          if (!entry.isIntersecting) return;
          const children = entry.target.children;
          if (reducedMotion) {
            anime({ targets: children, opacity: [0, 1], duration: 400, easing: "linear" });
          } else {
            anime({
              targets: children,
              opacity: [0, 1],
              translateY: [40, 0],
              duration: 700,
              delay: anime.stagger(100),
              easing: "easeOutCubic",
            });
          }
          observer.unobserve(entry.target);
        });
      },
      { threshold: 0.15 }
    );
    sections.forEach((section) => observer.observe(section));
  });

  // FAQ smooth height animation via native details toggle + anime fallback
  document.querySelectorAll(".faq-item").forEach((item) => {
    const summary = item.querySelector(".faq-summary");
    const body = item.querySelector(".faq-body");
    if (!summary || !body) return;

    summary.addEventListener("click", (e) => {
      e.preventDefault();
      const isOpen = item.hasAttribute("open");
      if (isOpen) {
        if (window.anime && !reducedMotion) {
          window.anime({
            targets: body,
            height: [body.scrollHeight, 0],
            opacity: [1, 0],
            duration: 250,
            easing: "easeInQuad",
            complete: () => item.removeAttribute("open"),
          });
        } else {
          item.removeAttribute("open");
        }
      } else {
        item.setAttribute("open", "");
        if (window.anime && !reducedMotion) {
          window.anime({
            targets: body,
            height: [0, body.scrollHeight],
            opacity: [0, 1],
            duration: 300,
            easing: "easeOutQuad",
          });
        }
      }
    });
  });
})();
