// app.jsx — root composition + scroll reveals + cursor + tweaks

const { useEffect, useRef, useState } = React;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "grain": true,
  "cursor": true,
  "contrast": "high",
  "heroStyle": "marquee",
  "photo": "muted",
  "scheme": "ash"
}/*EDITMODE-END*/;

const SCHEMES = [
  { id: "ash",       label: "Ash",       swatches: ["#050402", "#4a4438", "#bbb3a3", "#f6f3ee"] },
  { id: "bone",      label: "Bone",      swatches: ["#060402", "#463b2c", "#ad9c80", "#f4ece0"] },
  { id: "oxblood",   label: "Oxblood",   swatches: ["#060201", "#421b18", "#a66e68", "#f3e8e6"] },
  { id: "verdigris", label: "Verdigris", swatches: ["#030604", "#1f3328", "#76907f", "#e8efea"] },
  { id: "indigo",    label: "Indigo",    swatches: ["#020308", "#18213e", "#6f7aa0", "#e8eaf2"] },
  { id: "sepia",     label: "Sepia",     swatches: ["#050302", "#3e2f17", "#ad8a4f", "#f6ead4"] },
  { id: "glacier",   label: "Glacier",   swatches: ["#030405", "#252e35", "#828e96", "#eef1f3"] }
];

const CONTRASTS = [
  { id: "low",  label: "Low",  ramp: ["#3a3530", "#6d655a", "#a39988", "#d3ccbf"] },
  { id: "high", label: "High", ramp: ["#050402", "#4a4438", "#bbb3a3", "#f6f3ee"] },
  { id: "max",  label: "Max",  ramp: ["#000000", "#333333", "#bdbdbd", "#ffffff"] }
];

const TREATMENTS = [
  { id: "color",     label: "Color",     ramp: ["#3b2418", "#7a4a2e", "#c69270", "#f3d9c0"] },
  { id: "muted",     label: "Muted",     ramp: ["#1f1c18", "#4a4438", "#8a8276", "#c8c1b3"] },
  { id: "grayscale", label: "Grayscale", ramp: ["#0a0a0a", "#3d3d3d", "#8a8a8a", "#dedede"] }
];

function useReveal() {
  useEffect(() => {
    const els = document.querySelectorAll(".reveal, .reveal-stagger");
    const io = new IntersectionObserver((entries) => {
      entries.forEach((e) => {
        if (e.isIntersecting) {
          e.target.classList.add("is-in");
          io.unobserve(e.target);
        }
      });
    }, { threshold: 0.12, rootMargin: "0px 0px -8% 0px" });
    els.forEach((el) => io.observe(el));
    return () => io.disconnect();
  }, []);
}

function useParallax() {
  useEffect(() => {
    const els = document.querySelectorAll("[data-parallax]");
    const onScroll = () => {
      els.forEach((el) => {
        const r = el.getBoundingClientRect();
        const c = (r.top + r.height / 2) - window.innerHeight / 2;
        const k = parseFloat(el.dataset.parallax || "0.15");
        const inner = el.querySelector(".ph");
        if (inner) inner.style.transform = `translate3d(0, ${(-c * k).toFixed(1)}px, 0)`;
      });
    };
    onScroll();
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, []);
}

function useCustomCursor(enabled) {
  useEffect(() => {
    if (!enabled) {
      document.body.classList.remove("has-cursor");
      return;
    }
    document.body.classList.add("has-cursor");
    const cur = document.createElement("div");
    cur.className = "cursor";
    document.body.appendChild(cur);

    const onMove = (e) => {
      cur.style.left = e.clientX + "px";
      cur.style.top  = e.clientY + "px";
    };
    const onOver = (e) => {
      const t = e.target;
      if (t.closest && t.closest("a,button,.gallery__item,.chip")) cur.classList.add("is-large");
      else cur.classList.remove("is-large");
    };
    window.addEventListener("mousemove", onMove);
    window.addEventListener("mouseover", onOver);
    return () => {
      window.removeEventListener("mousemove", onMove);
      window.removeEventListener("mouseover", onOver);
      cur.remove();
      document.body.classList.remove("has-cursor");
    };
  }, [enabled]);
}

function Nav() {
  return (
    <nav className="nav">
      <a href="#hero" className="nav__mark" onClick={(e) => {
        e.preventDefault();
        const el = document.getElementById("hero");
        if (el) el.scrollIntoView({ behavior: "smooth", block: "start" });
      }}>S<span style={{fontStyle:"italic", color:"var(--ink-300)"}}>&amp;</span>A</a>
    </nav>
  );
}

function NavLinks() {
  const onClick = (id) => (e) => {
    e.preventDefault();
    const el = document.getElementById(id);
    if (el) el.scrollIntoView({ behavior: "smooth", block: "start" });
  };
  return (
    <div className="ctrl-bar__links">
      <a href="#gallery"  onClick={onClick("gallery")}>Work</a>
      <a href="#about"    onClick={onClick("about")}>Studio</a>
      <a href="#pricing"  onClick={onClick("pricing")}>Rates</a>
      <a href="#booking"  onClick={onClick("booking")}>Booking</a>
    </div>
  );
}

function Foot() {
  return (
    <footer className="foot" data-screen-label="06 Footer">
      <div className="foot__big reveal">
        Until<br/>
        <em>then.</em>
      </div>
      <div className="foot__rows">
        <div className="foot__col">
          <h5>Studio</h5>
          <a>Slate &amp; Ash</a>
          <a>742 Inkwell Lane · Suite 3B</a>
          <a>Brooklyn, NY 11216</a>
        </div>
        <div className="foot__col">
          <h5>Hours</h5>
          <a>Tues — Sat</a>
          <a>11.00 — 19.00</a>
          <a>By appointment</a>
        </div>
        <div className="foot__col">
          <h5>Reach</h5>
          <a>hello@slateandash.studio</a>
          <a>+1 (925) 555 0140</a>
          <a>@slateandash</a>
        </div>
        <div className="foot__col">
          <h5>Index</h5>
          <a href="#gallery">Work</a>
          <a href="#about">Studio</a>
          <a href="#pricing">Rates</a>
          <a href="#booking">Booking</a>
        </div>
      </div>
      <div className="foot__bottom">
        <span>© MMXXVI · Slate &amp; Ash</span>
        <span>A studio of one · est. MMXIX</span>
        <span>Site by <a href="https://computerrabbit.com" target="_blank" rel="noopener noreferrer">computerrabbit.com</a></span>
      </div>
    </footer>
  );
}

function OptionDropdown({ kind, eyebrow, current, options, onChange }) {
  const [open, setOpen] = useState(false);
  const ref = useRef(null);

  useEffect(() => {
    if (!open) return;
    const onDoc = (e) => {
      if (ref.current && !ref.current.contains(e.target)) setOpen(false);
    };
    const onKey = (e) => { if (e.key === "Escape") setOpen(false); };
    document.addEventListener("mousedown", onDoc);
    document.addEventListener("keydown", onKey);
    return () => {
      document.removeEventListener("mousedown", onDoc);
      document.removeEventListener("keydown", onKey);
    };
  }, [open]);

  const active = options.find((o) => o.id === current) || options[0];
  const swatches = active.swatches || active.ramp;

  return (
    <div className={"scheme-dd scheme-dd--" + kind + " " + (open ? "is-open" : "")} ref={ref}>
      <button
        type="button"
        className="scheme-dd__trigger"
        onClick={() => setOpen((v) => !v)}
        aria-haspopup="menu"
        aria-expanded={open}
      >
        <span className="scheme-dd__dot" style={{ background: swatches[2] }} aria-hidden="true" />
        <span className="scheme-dd__label">
          <span className="scheme-dd__eyebrow">{eyebrow}</span>
          <span className="scheme-dd__name">{active.label}</span>
        </span>
        <span className="scheme-dd__chev" aria-hidden="true">▾</span>
      </button>

      {open && (
        <div className="scheme-dd__menu" role="menu">
          {options.map((s) => {
            const sw = s.swatches || s.ramp;
            return (
              <button
                key={s.id}
                role="menuitemradio"
                aria-checked={s.id === current}
                className={"scheme-dd__item " + (s.id === current ? "is-on" : "")}
                onClick={() => { onChange(s.id); setOpen(false); }}
              >
                <span className="scheme-dd__strip" aria-hidden="true">
                  {sw.map((c, i) => (
                    <span key={i} style={{ background: c }} />
                  ))}
                </span>
                <span className="scheme-dd__name">{s.label}</span>
              </button>
            );
          })}
        </div>
      )}
    </div>
  );
}

function App() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const [loaded, setLoaded] = useState(false);

  useEffect(() => {
    const id = setTimeout(() => setLoaded(true), 2400);
    return () => clearTimeout(id);
  }, []);

  useEffect(() => {
    if (loaded) {
      window.postMessage({ slideIndexChanged: 0 }, "*");
    }
  }, [loaded]);

  useReveal();
  useParallax();
  useCustomCursor(t.cursor);

  // contrast variations — scheme-aware (uses scheme's ink vars rather than hard-coded hex)
  useEffect(() => {
    const root = document.documentElement;
    if (t.contrast === "low") {
      root.style.setProperty("--bg", "var(--ink-800)");
      root.style.setProperty("--fg", "var(--ink-100)");
    } else if (t.contrast === "max") {
      root.style.setProperty("--bg", "#000000");
      root.style.setProperty("--fg", "#ffffff");
    } else {
      root.style.setProperty("--bg", "var(--ink-black)");
      root.style.setProperty("--fg", "var(--ink-000)");
    }
  }, [t.contrast]);

  // color scheme — toggle data-scheme on <html>; default "ash" leaves it unset
  useEffect(() => {
    const html = document.documentElement;
    if (!t.scheme || t.scheme === "ash") {
      html.removeAttribute("data-scheme");
    } else {
      html.setAttribute("data-scheme", t.scheme);
    }
  }, [t.scheme]);

  // photo treatment
  useEffect(() => {
    document.body.dataset.photo = t.photo || "muted";
  }, [t.photo]);

  return (
    <>
      <Loader done={loaded} />
      {t.grain && <div className="grain" />}
      <Nav />
      <div className="ctrl-bar">
        <NavLinks />
        <OptionDropdown
          kind="palette"
          eyebrow="Palette"
          current={t.scheme || "ash"}
          options={SCHEMES}
          onChange={(v) => setTweak("scheme", v)}
        />
        <OptionDropdown
          kind="contrast"
          eyebrow="Contrast"
          current={t.contrast}
          options={CONTRASTS}
          onChange={(v) => setTweak("contrast", v)}
        />
        <OptionDropdown
          kind="treatment"
          eyebrow="Treatment"
          current={t.photo}
          options={TREATMENTS}
          onChange={(v) => setTweak("photo", v)}
        />
      </div>
      <Hero />
      <Gallery />
      <Philosophy />
      <Pricing />
      <Booking />
      <Foot />

      <TweaksPanel>
        <TweakSection label="Atmosphere" />
        <TweakToggle label="Film grain"   value={t.grain}  onChange={(v) => setTweak("grain", v)} />
        <TweakToggle label="Custom cursor" value={t.cursor} onChange={(v) => setTweak("cursor", v)} />
        <TweakSection label="Tone" />
        <TweakRadio
          label="Contrast"
          value={t.contrast}
          options={["low", "high", "max"]}
          onChange={(v) => setTweak("contrast", v)}
        />
        <TweakSection label="Photography" />
        <TweakRadio
          label="Treatment"
          value={t.photo}
          options={["color", "muted", "grayscale"]}
          onChange={(v) => setTweak("photo", v)}
        />
        <TweakSection label="Color scheme" />
        <TweakSelect
          label="Palette"
          value={t.scheme || "ash"}
          options={SCHEMES.map(s => s.id)}
          onChange={(v) => setTweak("scheme", v)}
        />
      </TweaksPanel>
    </>
  );
}

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