/* APP — root, nav, smooth scroll, language toggle, tweaks */

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "lang": "en",
  "motionLevel": 60,
  "palette": "slate",
  "displayFont": "fraunces"
}/*EDITMODE-END*/;

const PALETTES = {
  slate: {
    bone:      "oklch(0.965 0.008 80)",
    paper:     "oklch(0.945 0.012 80)",
    sand:      "oklch(0.895 0.018 80)",
    sandDeep:  "oklch(0.840 0.022 75)",
    line:      "oklch(0.78 0.012 75)",
    lineSoft:  "oklch(0.86 0.010 75)",
    slate:     "oklch(0.34 0.012 250)",
    slateDeep: "oklch(0.24 0.014 250)",
    slateInk:  "oklch(0.18 0.012 250)",
    slateBg:   "oklch(0.30 0.014 250)",
    muted:     "oklch(0.50 0.010 250)",
  },
  graphite: {
    bone:      "oklch(0.965 0.005 80)",
    paper:     "oklch(0.940 0.008 80)",
    sand:      "oklch(0.890 0.012 80)",
    sandDeep:  "oklch(0.830 0.014 75)",
    line:      "oklch(0.78 0.008 75)",
    lineSoft:  "oklch(0.86 0.006 75)",
    slate:     "oklch(0.34 0.005 270)",
    slateDeep: "oklch(0.22 0.006 270)",
    slateInk:  "oklch(0.16 0.006 270)",
    slateBg:   "oklch(0.28 0.006 270)",
    muted:     "oklch(0.50 0.005 270)",
  },
  ocean: {
    bone:      "oklch(0.965 0.008 80)",
    paper:     "oklch(0.945 0.012 80)",
    sand:      "oklch(0.895 0.018 80)",
    sandDeep:  "oklch(0.840 0.022 75)",
    line:      "oklch(0.78 0.012 75)",
    lineSoft:  "oklch(0.86 0.010 75)",
    slate:     "oklch(0.36 0.025 230)",
    slateDeep: "oklch(0.24 0.030 230)",
    slateInk:  "oklch(0.18 0.025 230)",
    slateBg:   "oklch(0.30 0.030 230)",
    muted:     "oklch(0.50 0.018 230)",
  },
  warm: {
    bone:      "oklch(0.960 0.012 75)",
    paper:     "oklch(0.935 0.018 75)",
    sand:      "oklch(0.885 0.025 70)",
    sandDeep:  "oklch(0.825 0.028 65)",
    line:      "oklch(0.76 0.018 70)",
    lineSoft:  "oklch(0.84 0.014 70)",
    slate:     "oklch(0.34 0.012 60)",
    slateDeep: "oklch(0.22 0.012 60)",
    slateInk:  "oklch(0.18 0.010 60)",
    slateBg:   "oklch(0.28 0.012 60)",
    muted:     "oklch(0.50 0.010 60)",
  },
};

const FONTS = {
  fraunces:  { display: '"Fraunces", "Cormorant Garamond", Georgia, serif',           serif: '"Fraunces", "Cormorant Garamond", Georgia, serif' },
  cormorant: { display: '"Cormorant Garamond", "Times New Roman", serif',             serif: '"Cormorant Garamond", "Times New Roman", serif' },
};

function App() {
  const { useTweaks } = window;
  const [tweaks, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const lang = tweaks.lang || "en";
  const t = window.COPY[lang];
  const motionLevel = tweaks.motionLevel ?? 60;

  const cursorRef = React.useRef(null);
  const [scrolled, setScrolled] = React.useState(false);

  React.useEffect(() => {
    const palette = PALETTES[tweaks.palette] || PALETTES.slate;
    const root = document.documentElement;
    root.style.setProperty("--bone",      palette.bone);
    root.style.setProperty("--paper",     palette.paper);
    root.style.setProperty("--sand",      palette.sand);
    root.style.setProperty("--sand-deep", palette.sandDeep);
    root.style.setProperty("--line",      palette.line);
    root.style.setProperty("--line-soft", palette.lineSoft);
    root.style.setProperty("--slate",     palette.slate);
    root.style.setProperty("--slate-deep", palette.slateDeep);
    root.style.setProperty("--slate-ink", palette.slateInk);
    root.style.setProperty("--slate-bg",  palette.slateBg);
    root.style.setProperty("--muted",     palette.muted);

    const f = FONTS[tweaks.displayFont] || FONTS.fraunces;
    root.style.setProperty("--display", f.display);
    root.style.setProperty("--serif", f.serif);
  }, [tweaks.palette, tweaks.displayFont]);

  // Lenis smooth scroll
  React.useEffect(() => {
    if (motionLevel < 20) return;
    const Lenis = window.Lenis;
    if (!Lenis) return;
    const lenis = new Lenis({
      duration: 1.2 + motionLevel / 200,
      easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)),
      smoothWheel: true,
    });
    function raf(time) {
      lenis.raf(time);
      requestAnimationFrame(raf);
    }
    const id = requestAnimationFrame(raf);
    return () => { lenis.destroy(); cancelAnimationFrame(id); };
  }, [motionLevel]);

  React.useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 80);
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, []);

  // Custom cursor
  React.useEffect(() => {
    const c = cursorRef.current;
    if (!c) return;
    let x = 0, y = 0, tx = 0, ty = 0;
    const onMove = (e) => { tx = e.clientX; ty = e.clientY; };
    window.addEventListener("mousemove", onMove);
    const onEnter = (e) => { if (e.target.closest && (e.target.closest("a, button, .s-tab, .g-item, .channel"))) c.classList.add("lg"); };
    const onLeave = () => { c.classList.remove("lg"); };
    document.addEventListener("mouseover", onEnter);
    document.addEventListener("mouseout", onLeave);
    let raf;
    const tick = () => {
      x += (tx - x) * 0.18;
      y += (ty - y) * 0.18;
      c.style.transform = `translate(${x}px, ${y}px) translate(-50%, -50%)`;
      raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => {
      window.removeEventListener("mousemove", onMove);
      document.removeEventListener("mouseover", onEnter);
      document.removeEventListener("mouseout", onLeave);
      cancelAnimationFrame(raf);
    };
  }, []);

  // Reveal observer
  React.useEffect(() => {
    const els = document.querySelectorAll(".reveal, .reveal-mask");
    const io = new IntersectionObserver((entries) => {
      entries.forEach((e) => { if (e.isIntersecting) e.target.classList.add("in"); });
    }, { threshold: 0.15 });
    els.forEach((el) => io.observe(el));
    return () => io.disconnect();
  }, [lang]);

  return (
    <>
      <div ref={cursorRef} className="cursor" />
      <Nav t={t} lang={lang} setLang={(v) => setTweak("lang", v)} scrolled={scrolled} />
      <main>
        <Hero t={t} motionLevel={motionLevel} />
        <Manifesto t={t} />
        <Services t={t} />
        <About t={t} />
        <Gallery t={t} />
        <Contact t={t} />
      </main>
    </>
  );
}

function Nav({ t, lang, setLang, scrolled }) {
  return (
    <nav className={`nav ${scrolled ? "scrolled" : ""}`}>
      <a href="#top" className="logo">
        <span className="logo-mark"></span>
        Hearthy <span style={{ fontStyle: "italic", color: "var(--slate)" }}>Coconut</span>
      </a>
      <div className="nav-links">
        <a href="#services">{t.nav.services}</a>
        <a href="#about">{t.nav.about}</a>
        <a href="#gallery">{t.nav.gallery}</a>
        <a href="#contact">{t.nav.contact}</a>
        <div className="lang-toggle">
          <button className={lang === "en" ? "on" : ""} onClick={() => setLang("en")}>EN</button>
          <button className={lang === "es" ? "on" : ""} onClick={() => setLang("es")}>ES</button>
        </div>
      </div>
    </nav>
  );
}

function Tweaks() {
  const { TweaksPanel, TweakSection, TweakSlider, TweakRadio, useTweaks } = window;
  const [tweaks, setTweak] = useTweaks(TWEAK_DEFAULTS);

  return (
    <TweaksPanel>
      <TweakSection label="Language" />
      <TweakRadio label="Lang" options={["en", "es"]} value={tweaks.lang} onChange={(v) => setTweak("lang", v)} />
      <TweakSection label="Palette" />
      <TweakRadio label="Tone" options={["slate", "graphite", "ocean", "warm"]} value={tweaks.palette} onChange={(v) => setTweak("palette", v)} />
      <TweakSection label="Display font" />
      <TweakRadio label="Font" options={["fraunces", "cormorant"]} value={tweaks.displayFont} onChange={(v) => setTweak("displayFont", v)} />
      <TweakSection label="Motion" />
      <TweakSlider label="Intensity" min={0} max={100} step={5} unit="%" value={tweaks.motionLevel} onChange={(v) => setTweak("motionLevel", v)} />
    </TweaksPanel>
  );
}

window.App = App;
window.Tweaks = Tweaks;
