/* App entry */
const TWEAK_DEFAULTS = {
  "palette": "pine",
  "density": "regular",
  "marqueeSpeed": 50,
  "theme": "light",
  "fontPair": "instrument-inter"
};

const PALETTES = {
  pine: { bg: "#FFFFFF", bg2: "#F3F7F0", ink: "#14281A", paper: "#FFFFFF", accent: "#1F6B3B", accentDeep: "#14512B" },
  slate: { bg: "#FFFFFF", bg2: "#F3F7F0", ink: "#14281A", paper: "#FFFFFF", accent: "#1F6B3B", accentDeep: "#14512B" }
};
const FONT_PAIRS = {
  "instrument-inter": { serif: '"Instrument Serif", Georgia, serif', sans: '"Inter Tight", "Helvetica Neue", Helvetica, Arial, sans-serif' },
  "fraunces-dm": { serif: '"Fraunces", Georgia, serif', sans: '"DM Sans", "Helvetica Neue", Helvetica, Arial, sans-serif' },
  "spectral-spaceg": { serif: '"Spectral", Georgia, serif', sans: '"Space Grotesk", "Helvetica Neue", Helvetica, Arial, sans-serif' }
};

function applyTweaks(t) {
  const r = document.documentElement;
  const p = PALETTES[t.palette] || PALETTES.slate;
  if (t.theme !== "dark") {
    r.style.setProperty("--bg", p.bg);
    r.style.setProperty("--bg-2", p.bg2);
    r.style.setProperty("--ink", p.ink);
    r.style.setProperty("--paper", p.paper);
    r.style.setProperty("--accent", p.accent);
    r.style.setProperty("--accent-deep", p.accentDeep);
  } else {
    r.style.removeProperty("--bg");
    r.style.removeProperty("--bg-2");
    r.style.removeProperty("--ink");
    r.style.removeProperty("--paper");
    r.style.removeProperty("--accent");
    r.style.removeProperty("--accent-deep");
  }
  document.body.dataset.theme = t.theme;
  r.style.setProperty("--density", t.density === "compact" ? 0.78 : t.density === "spacious" ? 1.18 : 1);
  r.style.setProperty("--marquee-speed", `${t.marqueeSpeed}s`);
  const fp = FONT_PAIRS[t.fontPair] || FONT_PAIRS["instrument-inter"];
  r.style.setProperty("--serif", fp.serif);
  r.style.setProperty("--sans", fp.sans);
}

const { motion } = window.Motion || { motion: {} };

const Reveal = ({ children, delay = 0, className = "" }) => {
  if (!window.Motion) return <div className={className}>{children}</div>;
  return (
    <motion.div
      initial={{ opacity: 0, y: 24 }}
      whileInView={{ opacity: 1, y: 0 }}
      viewport={{ once: true, margin: "-15% 0px" }}
      transition={{ duration: 0.7, delay, ease: [0.22, 1, 0.36, 1] }}
      className={className}
    >
      {children}
    </motion.div>
  );
};

const StatCount = ({ to, suffix = "", prefix = "", decimal = false }) => {
  if (!window.Motion) return <span>{prefix}{to}{suffix}</span>;
  const ref = React.useRef(null);
  const inView = window.Motion.useInView(ref, { once: true, margin: "-20%" });
  const [val, setVal] = React.useState(0);

  React.useEffect(() => {
    if (!inView) return;
    const controls = window.Motion.animate(0, to, {
      duration: 1.4,
      ease: [0.16, 1, 0.3, 1],
      onUpdate: (v) => setVal(v)
    });
    return () => controls.stop();
  }, [inView, to]);

  return <span ref={ref}>{prefix}{decimal ? val.toFixed(1) : Math.round(val)}{suffix}</span>;
};

Object.assign(window, { Reveal, motion, StatCount });

const App = () => {
  const [tweaks, setTweaks] = window.useTweaks(TWEAK_DEFAULTS);
  React.useEffect(() => { applyTweaks(tweaks); }, [tweaks]);

  // Setup Lenis Smooth Scroll
  React.useEffect(() => {
    if (!window.Lenis) return;
    if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;

    // Guard against a stray instance surviving a hot-reload / remount.
    if (window.lenis) { try { window.lenis.destroy(); } catch (e) { } window.lenis = null; }

    const isMobile = window.matchMedia('(max-width: 767px)').matches;

    // Note: when `lerp` is set, Lenis ignores `duration`; lerp governs the feel.
    // Lower lerp = softer/heavier; higher = snappier. Mobile keeps native touch
    // scrolling (syncTouch:false), so smoothing only applies to the wheel.
    //
    // 0.12 is roughly a 130ms time constant. Going one way that just reads as
    // "smooth", but on a reversal the position has to decelerate through zero
    // before it can head back — which is why the page felt like it lagged
    // behind the wheel specifically when scrolling up. 0.18 keeps the glide and
    // cuts the turnaround to something the hand reads as immediate. The wheel
    // multiplier goes back to 1: at 0.9 the page moved less than the input said
    // it should, which compounds the same "heavy" impression.
    const lenis = new window.Lenis({
      lerp: isMobile ? 0.2 : 0.18,
      smoothWheel: true,
      syncTouch: false,          // native, low-latency touch scrolling on mobile
      wheelMultiplier: 1,
      touchMultiplier: 1.1,
      infinite: false,
      autoResize: true
    });

    window.lenis = lenis;

    // Keep GSAP ScrollTrigger in sync with Lenis-driven scroll position.
    let onScroll;
    if (window.ScrollTrigger) {
      onScroll = () => window.ScrollTrigger.update();
      lenis.on('scroll', onScroll);
    }

    // Single RAF source of truth. Prefer GSAP's ticker (one shared loop);
    // fall back to a self-cancelling requestAnimationFrame loop otherwise.
    let rafId = 0;
    let tickerFn = null;
    if (window.gsap) {
      tickerFn = (time) => lenis.raf(time * 1000); // GSAP ticker time is in seconds
      window.gsap.ticker.add(tickerFn);
      window.gsap.ticker.lagSmoothing(0);
    } else {
      const raf = (time) => {
        lenis.raf(time);
        rafId = requestAnimationFrame(raf);
      };
      rafId = requestAnimationFrame(raf);
    }

    return () => {
      if (onScroll) lenis.off('scroll', onScroll);
      if (tickerFn && window.gsap) window.gsap.ticker.remove(tickerFn); // fixes the RAF leak
      if (rafId) cancelAnimationFrame(rafId);
      lenis.destroy();
      window.lenis = null;
    };
  }, []);

  // Handle clean URLs for anchor links
  React.useEffect(() => {
    window.__nav = (e, targetId) => {
      e.preventDefault();
      const targetEl = document.getElementById(targetId);

      if (window.lenis) {
        window.lenis.scrollTo(targetId === 'top' ? 0 : `#${targetId}`);
      } else {
        if (targetEl) {
          targetEl.scrollIntoView({ behavior: 'smooth' });
        } else if (targetId === 'top') {
          window.scrollTo({ top: 0, behavior: 'smooth' });
        }
      }
    };
  }, []);

  return (
    <>
      <Nav />
      <Hero />
      <Marquee />
      <IndustryGap />
      <Stats />
      <Vision />
      <Solutions />
      <Platforms />
      <Founders />
      <Seed />
      <Footer />
    </>
  );
};

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
