// Chrome / shared UI

const { useState, useEffect, useRef, useCallback, useMemo } = React;

// ========== CURSOR ==========
function Cursor() {
  const ringRef = useRef(null);
  const dotRef = useRef(null);
  const [hidden, setHidden] = useState(false);
  useEffect(() => {
    let rx = 0, ry = 0, dx = 0, dy = 0, tx = 0, ty = 0;
    const onMove = (e) => { tx = e.clientX; ty = e.clientY; };
    const onLeave = () => setHidden(true);
    const onEnter = () => setHidden(false);
    document.addEventListener("mousemove", onMove);
    document.addEventListener("mouseleave", onLeave);
    document.addEventListener("mouseenter", onEnter);
    let raf;
    const tick = () => {
      rx += (tx - rx) * 0.22;
      ry += (ty - ry) * 0.22;
      dx += (tx - dx) * 0.5;
      dy += (ty - dy) * 0.5;
      if (ringRef.current) ringRef.current.style.transform = `translate(${rx}px, ${ry}px) translate(-50%, -50%)`;
      if (dotRef.current) dotRef.current.style.transform = `translate(${dx}px, ${dy}px) translate(-50%, -50%)`;
      raf = requestAnimationFrame(tick);
    };
    tick();
    return () => {
      cancelAnimationFrame(raf);
      document.removeEventListener("mousemove", onMove);
      document.removeEventListener("mouseleave", onLeave);
      document.removeEventListener("mouseenter", onEnter);
    };
  }, []);
  return (
    <>
      <div ref={ringRef} className="cursor" style={{ opacity: hidden ? 0 : 1, transform: "translate(-50%, -50%)" }} />
      <div ref={dotRef} className="cursor-dot" style={{ opacity: hidden ? 0 : 1, transform: "translate(-50%, -50%)" }} />
    </>
  );
}

// ========== GLITCH TEXT ==========
function Glitch({ children, as = "span", className = "", ...rest }) {
  const Tag = as;
  const text = typeof children === "string" ? children : "";
  return (
    <Tag className={`glitch ${className}`} data-text={text} {...rest}>
      {children}
    </Tag>
  );
}

// ========== MARQUEE ==========
function Marquee({ children, duration = 40, reverse = false, separator = "✦" }) {
  const items = React.Children.toArray(children);
  const renderRow = (k) => (
    <React.Fragment key={k}>
      {items.map((it, i) => (
        <React.Fragment key={`${k}-${i}`}>
          <span>{it}</span>
          <span className="text-pink" aria-hidden>{separator}</span>
        </React.Fragment>
      ))}
    </React.Fragment>
  );
  return (
    <div className="marquee">
      <div className={`marquee-track ${reverse ? "reverse" : ""}`} style={{ "--marquee-duration": `${duration}s` }}>
        {renderRow("a")}{renderRow("b")}
      </div>
    </div>
  );
}

// ========== NAV ==========
const PAGES = [
  { id: "home", label: "Home", code: "01" },
  { id: "nemesis", label: "Nemesis", code: "02" },
  { id: "signup", label: "Closed Test", code: "03" },
  { id: "devlog", label: "Devlog", code: "04" },
  { id: "about", label: "Studio", code: "05" },
  { id: "contact", label: "Contact", code: "06" },
];

function Logo({ small = false }) {
  return (
    <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
      <svg width={small ? 22 : 28} height={small ? 22 : 28} viewBox="0 0 32 32" fill="none">
        <rect x="2" y="2" width="28" height="28" stroke="currentColor" strokeWidth="1.5"/>
        <rect x="7" y="7" width="18" height="18" fill="var(--pink)"/>
        <rect x="11" y="11" width="10" height="10" fill="var(--bg-0)"/>
        <rect x="14" y="14" width="4" height="4" fill="var(--cyan)"/>
      </svg>
      <div style={{ lineHeight: 1 }}>
        <div style={{ fontFamily: "var(--display)", fontWeight: 700, fontSize: small ? 13 : 15, letterSpacing: "0.04em", textTransform: "uppercase" }}>
          Tiny Gang
        </div>
        <div className="mono-tag" style={{ color: "var(--ink-dim)", marginTop: 2, fontSize: 9 }}>STUDIOS / EST 2023</div>
      </div>
    </div>
  );
}

function Nav({ page, setPage }) {
  const [time, setTime] = useState("");
  useEffect(() => {
    const tick = () => {
      const d = new Date();
      const hh = String(d.getUTCHours()).padStart(2, "0");
      const mm = String(d.getUTCMinutes()).padStart(2, "0");
      const ss = String(d.getUTCSeconds()).padStart(2, "0");
      setTime(`${hh}:${mm}:${ss}`);
    };
    tick();
    const i = setInterval(tick, 1000);
    return () => clearInterval(i);
  }, []);

  return (
    <nav className="nav">
      <div className="container" style={{ display: "flex", alignItems: "center", gap: 24, padding: "18px 32px" }}>
        <button onClick={() => setPage("home")} style={{ all: "unset", cursor: "none" }} aria-label="Home">
          <Logo />
        </button>
        <div style={{ flex: 1 }} />
        <div style={{ display: "flex", gap: 0, alignItems: "stretch" }}>
          {PAGES.map((p, i) => {
            const active = p.id === page;
            return (
              <button
                key={p.id}
                onClick={() => setPage(p.id)}
                style={{
                  all: "unset",
                  cursor: "none",
                  padding: "10px 16px",
                  display: "flex", flexDirection: "column", alignItems: "flex-start",
                  borderLeft: i === 0 ? `1px solid var(--line)` : "none",
                  borderRight: `1px solid var(--line)`,
                  position: "relative",
                  background: active ? "oklch(0.14 0.03 270)" : "transparent",
                  color: active ? "var(--ink)" : "var(--ink-dim)",
                }}
                onMouseEnter={(e) => { e.currentTarget.style.color = "var(--ink)"; }}
                onMouseLeave={(e) => { e.currentTarget.style.color = active ? "var(--ink)" : "var(--ink-dim)"; }}
              >
                <span className="mono-tag" style={{ fontSize: 9, color: active ? "var(--pink)" : "var(--ink-faint)" }}>
                  / {p.code}
                </span>
                <span style={{ fontFamily: "var(--display)", fontSize: 13, fontWeight: 600, textTransform: "uppercase", letterSpacing: "0.04em", marginTop: 2 }}>
                  {p.label}
                </span>
                {active && (
                  <span style={{ position: "absolute", left: 8, right: 8, bottom: 6, height: 2, background: "var(--pink)", boxShadow: "0 0 12px var(--pink-glow)" }} />
                )}
              </button>
            );
          })}
        </div>
        <div style={{ display: "flex", flexDirection: "column", alignItems: "flex-end", gap: 4, marginLeft: 12 }}>
          <span className="pill text-cyan" style={{ borderColor: "var(--cyan)" }}>
            <span className="dot pulse-dot" /> UTC {time}
          </span>
          <span className="mono-tag" style={{ color: "var(--ink-faint)" }}>SYS // ONLINE</span>
        </div>
      </div>
    </nav>
  );
}

// ========== FOOTER ==========
function Footer({ setPage }) {
  return (
    <footer style={{ marginTop: 80, borderTop: "1px solid var(--line)", background: "oklch(0.06 0.02 270 / 0.6)" }}>
      <Marquee duration={50} separator="◣">
        <span className="display-md text-pink">Closed Test Open</span>
        <span className="display-md">Nemesis · Cyberpunk Idle Roguelike</span>
        <span className="display-md text-cyan">Now Recruiting Testers</span>
        <span className="display-md">Built by Tiny Gang</span>
      </Marquee>
      <div className="container" style={{ padding: "56px 32px 32px" }}>
        <div style={{ display: "grid", gridTemplateColumns: "1.5fr 1fr 1fr 1fr", gap: 48 }}>
          <div>
            <Logo />
            <p style={{ marginTop: 18, color: "var(--ink-dim)", maxWidth: 320, fontSize: 13 }}>
              A tiny studio building strange, systems-rich games.
              Currently shipping Nemesis — a cyberpunk idle RPG roguelike — in closed test on Google Play.
            </p>
            <div className="row gap-2" style={{ marginTop: 18 }}>
              <a href="https://discord.gg/BNuwAzDaxs" target="_blank" rel="noopener" className="pill text-cyan" style={{ borderColor: "var(--cyan)" }}>Discord ↗</a>
              <a href="mailto:contact@tinygang.dev" className="pill text-dim" style={{ borderColor: "var(--line)" }}>Email ↗</a>
            </div>
          </div>
          <div>
            <div className="mono-label" style={{ marginBottom: 14 }}>// Site</div>
            <div className="col gap-2">
              {PAGES.map(p => (
                <a key={p.id} onClick={() => setPage(p.id)} style={{ cursor: "none", fontFamily: "var(--display)", fontSize: 15, textTransform: "uppercase", letterSpacing: "0.04em" }} className="hover-glitch">
                  → {p.label}
                </a>
              ))}
            </div>
          </div>
          <div>
            <div className="mono-label" style={{ marginBottom: 14 }}>// Nemesis</div>
            <div className="col gap-2 text-dim" style={{ fontSize: 13 }}>
              <a onClick={() => setPage("signup")} style={{ cursor: "none" }}>Closed Test Signup</a>
              <a onClick={() => setPage("nemesis")} style={{ cursor: "none" }}>Game Page</a>
              <a onClick={() => setPage("devlog")} style={{ cursor: "none" }}>Devlog</a>
              <a href="https://discord.gg/BNuwAzDaxs" target="_blank" rel="noopener">Discord Community ↗</a>
            </div>
          </div>
          <div>
            <div className="mono-label" style={{ marginBottom: 14 }}>// Studio</div>
            <div className="col gap-2 text-dim" style={{ fontSize: 13 }}>
              <a href="mailto:contact@tinygang.dev">contact@tinygang.dev</a>
              <div className="hairline" style={{ marginTop: 10, paddingTop: 10 }}>tinygang.dev</div>
              <div>Closed test on Google Play</div>
              <div>Built in public</div>
            </div>
          </div>
        </div>
        <div className="hairline" style={{ marginTop: 48, paddingTop: 18, display: "flex", justifyContent: "space-between", color: "var(--ink-faint)", fontSize: 11 }}>
          <span className="mono-tag">© 2026 TINY GANG STUDIOS · tinygang.dev</span>
          <span className="mono-tag">NEMESIS · BUILD v0.39.0 · 101 RELEASES</span>
          <span className="mono-tag">NO TRACKERS · NO ADS · NO BS</span>
        </div>
      </div>
    </footer>
  );
}

// ========== BOOT ==========
function BootScreen({ onDone }) {
  const [lines, setLines] = useState([]);
  const [done, setDone] = useState(false);
  useEffect(() => {
    const seq = [
      "> tinygang.kernel v2.4.1 :: cold start",
      "> mounting /dev/neon ............... [ OK ]",
      "> handshaking with NEMESIS server ... [ OK ]",
      "> loading visual cortex ............. [ OK ]",
      "> calibrating CRT output ............ [ OK ]",
      "> injecting glitch routines ......... [ OK ]",
      "> ready.",
    ];
    let i = 0;
    const id = setInterval(() => {
      setLines(s => [...s, seq[i]]);
      i++;
      if (i >= seq.length) {
        clearInterval(id);
        setTimeout(() => setDone(true), 350);
        setTimeout(() => onDone(), 700);
      }
    }, 110);
    return () => clearInterval(id);
  }, [onDone]);
  return (
    <div className="boot" style={{ opacity: done ? 0 : 1, transition: "opacity 0.35s" }}>
      <pre style={{ marginBottom: 24 }}>
{`████████╗ ██████╗   //  TINY GANG
╚══██╔══╝██╔════╝   //  STUDIOS
   ██║   ██║  ███╗  //  est. 2023
   ██║   ██║   ██║
   ██║   ╚██████╔╝  cold-boot sequence
   ╚═╝    ╚═════╝   ─────────────────`}
      </pre>
      <pre>
        {lines.map((l, i) => <div key={i}>{l}</div>)}
        <span className="blink">▌</span>
      </pre>
    </div>
  );
}

// ========== PARTICLE STREAKS BG ==========
function NeonRain() {
  const ref = useRef(null);
  useEffect(() => {
    const c = ref.current;
    const ctx = c.getContext("2d");
    let w = c.width = window.innerWidth;
    let h = c.height = window.innerHeight;
    const drops = Array.from({ length: 60 }, () => ({
      x: Math.random() * w,
      y: Math.random() * h,
      l: 8 + Math.random() * 24,
      s: 1 + Math.random() * 4,
      hue: Math.random() > 0.5 ? 350 : 200,
    }));
    let raf;
    const tick = () => {
      ctx.clearRect(0, 0, w, h);
      drops.forEach(d => {
        const grad = ctx.createLinearGradient(d.x, d.y, d.x, d.y + d.l);
        grad.addColorStop(0, `oklch(0.85 0.2 ${d.hue} / 0)`);
        grad.addColorStop(1, `oklch(0.85 0.2 ${d.hue} / 0.55)`);
        ctx.strokeStyle = grad;
        ctx.lineWidth = 1;
        ctx.beginPath();
        ctx.moveTo(d.x, d.y);
        ctx.lineTo(d.x, d.y + d.l);
        ctx.stroke();
        d.y += d.s;
        if (d.y > h) { d.y = -d.l; d.x = Math.random() * w; }
      });
      raf = requestAnimationFrame(tick);
    };
    tick();
    const onResize = () => { w = c.width = window.innerWidth; h = c.height = window.innerHeight; };
    window.addEventListener("resize", onResize);
    return () => { cancelAnimationFrame(raf); window.removeEventListener("resize", onResize); };
  }, []);
  return <canvas ref={ref} style={{ position: "fixed", inset: 0, pointerEvents: "none", zIndex: 2, opacity: 0.35 }} />;
}

// ========== MODAL ==========
function Modal({ open, onClose, children }) {
  useEffect(() => {
    if (!open) return;
    const esc = (e) => e.key === "Escape" && onClose();
    document.addEventListener("keydown", esc);
    document.body.style.overflow = "hidden";
    return () => { document.removeEventListener("keydown", esc); document.body.style.overflow = ""; };
  }, [open, onClose]);
  if (!open) return null;
  return (
    <div style={{ position: "fixed", inset: 0, zIndex: 5000, display: "flex", alignItems: "center", justifyContent: "center", padding: 40 }}>
      <div onClick={onClose} style={{ position: "absolute", inset: 0, background: "oklch(0.04 0.02 270 / 0.85)", backdropFilter: "blur(8px)" }} />
      <div style={{ position: "relative", zIndex: 1, maxWidth: 1100, width: "100%" }}>
        {children}
      </div>
    </div>
  );
}

// Stat block
function Stat({ label, value, sub, accent }) {
  return (
    <div style={{ padding: "18px 20px", borderLeft: `2px solid ${accent || "var(--line)"}`, background: "oklch(0.08 0.02 270 / 0.5)" }}>
      <div className="mono-label" style={{ marginBottom: 8 }}>{label}</div>
      <div style={{ fontFamily: "var(--display)", fontSize: 32, fontWeight: 700, lineHeight: 1, letterSpacing: "-0.02em" }}>{value}</div>
      {sub && <div className="mono-tag text-dim" style={{ marginTop: 6 }}>{sub}</div>}
    </div>
  );
}

// Section header
function SectionHead({ code, title, kicker, right }) {
  return (
    <div style={{ display: "flex", alignItems: "flex-end", justifyContent: "space-between", borderBottom: "1px solid var(--line)", paddingBottom: 18, marginBottom: 32, gap: 24 }}>
      <div>
        <div className="mono-label" style={{ marginBottom: 12 }}>
          <span className="text-pink">//</span> {code} · {kicker}
        </div>
        <h2 className="display-lg hover-glitch">{title}</h2>
      </div>
      {right}
    </div>
  );
}

// SS placeholder helper
function ScreenshotSlot({ label, ratio = "16/9", style }) {
  return (
    <div className="ss-placeholder" style={{ aspectRatio: ratio, ...style }}>
      <div style={{ textAlign: "center", padding: 16 }}>
        <div style={{ fontSize: 22, marginBottom: 6, opacity: 0.5 }}>◢◤</div>
        <div>{label}</div>
        <div className="mono-tag text-faint" style={{ marginTop: 6 }}>// PLACEHOLDER</div>
      </div>
    </div>
  );
}

// Real image slot — uses cover by default, overlays a small mono caption.
function GameImage({ src, ratio = "16/9", alt = "", style, label, objectPosition = "center", overlay = true }) {
  return (
    <div style={{ aspectRatio: ratio, overflow: "hidden", position: "relative", border: "1px solid var(--line)", background: "var(--bg-1)", ...style }}>
      <img src={src} alt={alt} loading="lazy" style={{ width: "100%", height: "100%", objectFit: "cover", objectPosition, display: "block" }} />
      {overlay && (
        <div style={{ position: "absolute", inset: 0, pointerEvents: "none", background: "linear-gradient(to top, oklch(0 0 0 / 0.45), transparent 50%)" }} />
      )}
      {label && (
        <div style={{ position: "absolute", left: 12, bottom: 12, fontFamily: "var(--mono)", fontSize: 10, fontWeight: 600, letterSpacing: "0.18em", textTransform: "uppercase", color: "var(--ink)", background: "oklch(0.06 0.02 270 / 0.85)", padding: "5px 10px", border: "1px solid var(--cyan)" }}>{label}</div>
      )}
      {/* corner crops */}
      <span style={{ position: "absolute", top: 4, left: 4, width: 10, height: 10, borderTop: "1px solid var(--cyan)", borderLeft: "1px solid var(--cyan)" }} />
      <span style={{ position: "absolute", top: 4, right: 4, width: 10, height: 10, borderTop: "1px solid var(--cyan)", borderRight: "1px solid var(--cyan)" }} />
      <span style={{ position: "absolute", bottom: 4, left: 4, width: 10, height: 10, borderBottom: "1px solid var(--cyan)", borderLeft: "1px solid var(--cyan)" }} />
      <span style={{ position: "absolute", bottom: 4, right: 4, width: 10, height: 10, borderBottom: "1px solid var(--cyan)", borderRight: "1px solid var(--cyan)" }} />
    </div>
  );
}

Object.assign(window, {
  Cursor, Glitch, Marquee, Nav, Footer, BootScreen, NeonRain, Modal, Stat, SectionHead, ScreenshotSlot, GameImage, Logo, PAGES
});
