/* Main app shell — cursor trail, tape measure, reveals */

const InkTrail = () => {
  const svgRef = React.useRef<SVGSVGElement | null>(null);
  const last = React.useRef<Nullable<{ x: number; y: number }>>(null);

  React.useEffect(() => {
    const handler = (e: PointerEvent) => {
      const p = { x: e.clientX, y: e.clientY };
      if (last.current) {
        const svg = svgRef.current;
        if (!svg) return;
        const dx = p.x - last.current.x;
        const dy = p.y - last.current.y;
        const dist = Math.hypot(dx, dy);
        if (dist > 3) {
          const line = document.createElementNS("http://www.w3.org/2000/svg", "line");
          line.setAttribute("x1", String(last.current.x));
          line.setAttribute("y1", String(last.current.y));
          line.setAttribute("x2", String(p.x));
          line.setAttribute("y2", String(p.y));
          line.setAttribute("stroke", "var(--ochre-deep)");
          line.setAttribute("stroke-width", String(1.5 + Math.min(3, dist / 10)));
          line.setAttribute("stroke-linecap", "round");
          line.setAttribute("opacity", "0.6");
          svg.appendChild(line);
          // fade and remove
          let op = 0.6;
          const fade = () => {
            op -= 0.015;
            if (op <= 0) { line.remove(); return; }
            line.setAttribute("opacity", String(op));
            requestAnimationFrame(fade);
          };
          setTimeout(() => requestAnimationFrame(fade), 400);
          last.current = p;
        }
      } else {
        last.current = p;
      }
    };
    window.addEventListener("pointermove", handler);
    return () => window.removeEventListener("pointermove", handler);
  }, []);

  return <svg className="ink-trail" ref={svgRef} />;
};

const Nav = () => (
  <nav className="nav">
    <div className="nav-brand">
      <span className="dot" />
      <span>AT · STUDIO/01</span>
    </div>
    <div className="nav-links">
      <a href="#services">Services</a>
      <a href="#process">Process</a>
      <a href="#work">Work</a>
      <a href="#wow">Wow</a>
      <a href="#stack">Stack</a>
      <a href="#play">Playground</a>
      <a href="#brief">Brief me</a>
    </div>
    <a href="#brief" className="nav-cta">
      <span className="pulse" /> Brief me · 60s
    </a>
  </nav>
);

const TapeMeasure = () => {
  const [y, setY] = React.useState(0);
  const [label, setLabel] = React.useState("§01");

  React.useEffect(() => {
    const handler = () => {
      setY(window.scrollY % window.innerHeight);
      // detect which section
      const sections = document.querySelectorAll("[data-screen-label]");
      let curr = "§01 HERO";
      sections.forEach((s) => {
        const r = s.getBoundingClientRect();
        if (r.top < window.innerHeight * 0.4) {
          curr = (s as HTMLElement).dataset.screenLabel?.toUpperCase() ?? curr;
        }
      });
      setLabel(curr);
    };
    window.addEventListener("scroll", handler, { passive: true });
    handler();
    return () => window.removeEventListener("scroll", handler);
  }, []);

  return (
    <div className="tape">
      <div className="ticks" />
      <div className="label">SCROLL · PAPER</div>
      <div className="marker" style={{ top: `${(y / window.innerHeight) * 100}%` }}>
        <div className="line" />
        <div className="mm">{label}</div>
      </div>
    </div>
  );
};

const App = () => {
  // scroll-triggered reveals
  React.useEffect(() => {
    const revealAll = () => {
      document.querySelectorAll(".reveal, .scrib-under, .scrib-circle").forEach((el) => {
        const r = el.getBoundingClientRect();
        if (r.top < window.innerHeight && r.bottom > 0) {
          el.classList.add("in");
        }
      });
    };
    revealAll();
    requestAnimationFrame(revealAll);
    const t1 = setTimeout(revealAll, 100);
    const t2 = setTimeout(revealAll, 500);

    const io = new IntersectionObserver((entries) => {
      entries.forEach((e) => {
        if (e.isIntersecting) {
          e.target.classList.add("in");
        }
      });
    }, { threshold: 0, rootMargin: "0px 0px -10% 0px" });
    document.querySelectorAll(".reveal, .scrib-under, .scrib-circle").forEach((el) => io.observe(el));

    const onScroll = () => revealAll();
    window.addEventListener("scroll", onScroll, { passive: true });

    return () => {
      io.disconnect();
      clearTimeout(t1); clearTimeout(t2);
      window.removeEventListener("scroll", onScroll);
    };
  }, []);

  return (
    <>
      <Nav />
      <TapeMeasure />
      <InkTrail />
      <main>
        <Hero />
        <Services />
        <Process />
        <Cases />
        <Stack />
        <WallOfWow />
        <BriefBuilder />
        <Playground />
        <CTA />
      </main>
    </>
  );
};

/* Tweaks */
type PortfolioTweaks = {
  accent: string;
  accentDeep: string;
  paper: string;
  fontBody: string;
  fontDisplay: string;
  scribbleDensity: number;
};

const TWEAK_DEFAULTS: PortfolioTweaks = /*EDITMODE-BEGIN*/{
  "accent": "#d9a441",
  "accentDeep": "#b5821f",
  "paper": "#f6f0e3",
  "fontBody": "Space Grotesk",
  "fontDisplay": "Space Grotesk",
  "scribbleDensity": 1
}/*EDITMODE-END*/;

const Tweaks = () => {
  const [tw, setTw] = useTweaks(TWEAK_DEFAULTS);
  React.useEffect(() => {
    const r = document.documentElement.style;
    r.setProperty("--ochre", tw.accent);
    r.setProperty("--ochre-deep", tw.accentDeep);
    r.setProperty("--paper", tw.paper);
    r.setProperty("--font-display", `"${tw.fontDisplay}", system-ui, sans-serif`);
    r.setProperty("--font-body", `"${tw.fontBody}", system-ui, sans-serif`);
    r.setProperty("--scribble-density", String(tw.scribbleDensity));
  }, [tw]);

  const palettes = [
    { label: "Ochre (default)", accent: "#d9a441", accentDeep: "#b5821f" },
    { label: "Brick", accent: "#c94a3f", accentDeep: "#8a2e25" },
    { label: "Moss", accent: "#6b8e4e", accentDeep: "#4a6a2e" },
    { label: "Slate", accent: "#4a6fa5", accentDeep: "#2e4a7a" },
    { label: "Plum", accent: "#7a4a7a", accentDeep: "#5a2e5a" },
  ];
  const papers = [
    { label: "Cream", val: "#f6f0e3" },
    { label: "Bone", val: "#f4ede0" },
    { label: "Oat", val: "#ebe2cd" },
    { label: "Snow", val: "#faf7f0" },
  ];
  const fonts = ["Space Grotesk", "Inter Tight", "Bricolage Grotesque", "Libre Caslon Text", "IBM Plex Sans"];

  return (
    <TweaksPanel title="Tweaks">
      <TweakSection title="Accent">
        {palettes.map((p) => (
          <button key={p.label}
            onClick={() => setTw({ accent: p.accent, accentDeep: p.accentDeep })}
            style={{
              display: "flex", alignItems: "center", gap: 10, width: "100%",
              padding: "8px 10px", marginBottom: 4,
              border: "1.5px solid rgb(206, 167, 26)",
              background: "#fff", cursor: "pointer", borderRadius: 6, fontFamily: "inherit", fontSize: 13,
            }}>
            <span style={{ width: 18, height: 18, borderRadius: 4, background: p.accent, border: "1px solid #000" }} />
            {p.label}
          </button>
        ))}
      </TweakSection>

      <TweakSection title="Paper">
        <div style={{ display: "grid", gridTemplateColumns: "repeat(4,1fr)", gap: 6 }}>
          {papers.map((p) => (
            <button key={p.label}
              onClick={() => setTw({ paper: p.val })}
              title={p.label}
              style={{
                aspectRatio: 1, background: p.val, cursor: "pointer",
                border: tw.paper === p.val ? "2px solid #1a1814" : "1px solid #ccc", borderRadius: 4,
              }} />
          ))}
        </div>
      </TweakSection>

      <TweakSection title="Display font">
        <TweakSelect
          value={tw.fontDisplay}
          options={fonts}
          onChange={(v) => setTw({ fontDisplay: v })}
        />
      </TweakSection>

      <TweakSection title="Body font">
        <TweakSelect
          value={tw.fontBody}
          options={fonts}
          onChange={(v) => setTw({ fontBody: v })}
        />
      </TweakSection>

      <TweakSection title="Scribble density">
        <TweakSlider
          value={tw.scribbleDensity}
          min={0} max={2} step={0.1}
          onChange={(v) => setTw({ scribbleDensity: v })}
        />
      </TweakSection>
    </TweaksPanel>
  );
};

/* Mount */
const rootNode = document.getElementById("root");
if (!rootNode) throw new Error("Missing #root element");
const root = ReactDOM.createRoot(rootNode);
root.render(<><App /><Tweaks /></>);
