// components.jsx — shared primitives for KVB 2.0
const { useState, useEffect, useRef } = React;

/* ---------------- Icons (clean line set) ---------------- */
const I = {
  bolt:  "M13 2 4 14h6l-1 8 9-12h-6l1-8z",
  shield:"M12 3 5 6v5c0 4.4 3 7.6 7 9 4-1.4 7-4.6 7-9V6l-7-3z",
  eye:   "M2 12s3.6-7 10-7 10 7 10 7-3.6 7-10 7S2 12 2 12z",
  chart: "M4 20V10M10 20V4M16 20v-7M22 20H2",
  chat:  "M4 5h16v11H9l-5 4V5z",
  users: "M16 19v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2M9 9a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM22 19v-2a4 4 0 0 0-3-3.9M16 3.1A4 4 0 0 1 16 11",
  check: "M20 6 9 17l-5-5",
  arrow: "M5 12h14M13 6l6 6-6 6",
  play:  "M7 4v16l13-8z",
  lock:  "M6 10V7a6 6 0 1 1 12 0v3M5 10h14v11H5z",
  globe: "M12 3a9 9 0 1 0 0 18 9 9 0 0 0 0-18zM3 12h18M12 3c2.5 2.5 4 6 4 9s-1.5 6.5-4 9c-2.5-2.5-4-6-4-9s1.5-6.5 4-9z",
  spark: "M12 3v4M12 17v4M3 12h4M17 12h4M6.3 6.3l2.4 2.4M15.3 15.3l2.4 2.4M17.7 6.3l-2.4 2.4M8.7 15.3l-2.4 2.4",
  rocket:"M5 15c-1 1-2 5-2 5s4-1 5-2M9 12l3 3M14 4c4 1 6 3 7 7-3 3-7 4-10 3-1.5-2.5-1.5-7 3-10zM9 12c-1.5 0-3 .5-4 2",
  gauge: "M12 14a2 2 0 1 0 0-4 2 2 0 0 0 0 4zM12 12l4-4M5 19a8 8 0 1 1 14 0",
  card:  "M3 6h18v12H3zM3 10h18",
  grid:  "M4 4h7v7H4zM13 4h7v7h-7zM13 13h7v7h-7zM4 13h7v7H4z",
  cpu:   "M6 6h12v12H6zM9 9h6v6H9zM9 2v3M15 2v3M9 19v3M15 19v3M2 9h3M2 15h3M19 9h3M19 15h3",
  signal:"M4 18v-3M9 18v-7M14 18v-11M19 18V4",
  headset:"M4 14v-2a8 8 0 0 1 16 0v2M4 14a2 2 0 0 0 2 2h1v-5H6a2 2 0 0 0-2 2zM20 14a2 2 0 0 1-2 2h-1v-5h1a2 2 0 0 1 2 2zM18 16v1a4 4 0 0 1-4 4h-2",
  refresh:"M3 12a9 9 0 0 1 15-6.7L21 8M21 3v5h-5M21 12a9 9 0 0 1-15 6.7L3 16M3 21v-5h5",
  video: "M3 6h12v12H3zM15 10l6-3v10l-6-3",
  code:  "M9 8l-4 4 4 4M15 8l4 4-4 4",
  phone: "M6 3h12v18H6zM10 18h4",
  poll: "M5 21V9M12 21V3M19 21v-7",
  scissors: "M6 9a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM6 21a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM8.5 8.5 20 18M8.5 15.5 20 6M12 12l2 1.5",
  zap: "M11 2 4 13h6l-1 9 8-12h-6l1-8z",
  clock: "M12 3a9 9 0 1 0 0 18 9 9 0 0 0 0-18zM12 7v5l3 2",
  star: "M12 3l2.6 5.6 6.1.7-4.5 4.2 1.2 6-5.4-3-5.4 3 1.2-6L3.3 9.3l6.1-.7z",
  heart: "M12 20s-7-4.5-9.5-9C1 8 2.5 4.5 6 4.5c2 0 3.2 1.2 4 2.3.8-1.1 2-2.3 4-2.3 3.5 0 5 3.5 3.5 6.5C19 15.5 12 20 12 20z",
  trophy: "M7 4h10v4a5 5 0 0 1-10 0V4zM7 6H4v1a3 3 0 0 0 3 3M17 6h3v1a3 3 0 0 1-3 3M9 16h6M8 21h8M12 18v3",
  calendar: "M4 6h16v15H4zM4 10h16M8 3v4M16 3v4",
  flag: "M5 21V4M5 4h11l-2 4 2 4H5",
  book: "M5 4h11a3 3 0 0 1 3 3v13a2 2 0 0 0-2-2H5zM5 4v14",
  plus: "M12 5v14M5 12h14",
  target: "M12 3a9 9 0 1 0 0 18 9 9 0 0 0 0-18zM12 8a4 4 0 1 0 0 8 4 4 0 0 0 0-8zM12 11a1 1 0 1 0 0 2 1 1 0 0 0 0-2z",
  message: "M21 12a8 8 0 0 1-11.5 7.2L3 21l1.8-6.5A8 8 0 1 1 21 12z",
  mic: "M12 3a3 3 0 0 1 3 3v6a3 3 0 0 1-6 0V6a3 3 0 0 1 3-3zM5 11a7 7 0 0 0 14 0M12 18v3",
};
function Icon({ name, size = 22, stroke = 1.8, fill = false, style }) {
  const d = I[name] || I.spark;
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill={fill ? "currentColor" : "none"}
      stroke={fill ? "none" : "currentColor"} strokeWidth={stroke} strokeLinecap="round"
      strokeLinejoin="round" style={style} aria-hidden="true">
      {d.split("M").filter(Boolean).map((seg, i) => <path key={i} d={"M" + seg} />)}
    </svg>
  );
}

/* ---------------- Logo (KVB.GG wordmark) ---------------- */
function Logo({ size = 30, onClick }) {
  // `size` = rendered height in px; width follows the 131:37 aspect ratio.
  const h = Math.round(size * 0.84);
  return (
    <div onClick={onClick} style={{ display: "inline-flex", alignItems: "center", cursor: onClick ? "pointer" : "default" }}>
      <svg height={h} viewBox="0 0 131 37" fill="none" xmlns="http://www.w3.org/2000/svg" style={{ display: "block", width: "auto" }} role="img" aria-label="KVB.GG">
        <path d="M0 35.3901V0.257324H11.7114V8.07991H15.6227V4.16862H19.5115V0.257324H31.2229V11.9687H27.3341V15.88H23.4228V19.7913H27.3341V23.6801H31.2229V35.3915H19.5115V31.5027H15.6227V27.5914H11.7114V35.3915H0V35.3901Z" fill="var(--accent)"></path>
        <path d="M42.9329 35.3901V27.5901H39.0441V19.79H35.1328V0.257324H46.8442V15.88H54.6443V0.257324H66.3557V19.7913H62.4669V27.5914H58.5556V35.3915H42.9329V35.3901Z" fill="var(--accent)"></path>
        <path d="M70.2676 35.3901V0.257324H93.6904V4.16862H97.6017V15.88H93.6904V19.7913H97.6017V31.5027H93.6904V35.3915H70.2676V35.3901ZM85.8903 11.9687V8.07991H81.979V11.9687H85.8903ZM85.8903 27.5914V23.6801H81.979V27.5914H85.8903Z" fill="var(--accent)"></path>
        <path d="M101.418 35.3903V32.1064H104.702V35.3903H101.418Z" fill="#fff"></path>
        <path d="M107.996 35.3901V33.7527H106.35V22.2452H107.996V20.5986H117.857V25.5291H111.28V30.4596H112.927V27.1757H117.857V35.3901H107.996Z" fill="#fff"></path>
        <path d="M121.141 35.3901V33.7527H119.494V22.2452H121.141V20.5986H131.002V25.5291H124.425V30.4596H126.071V27.1757H131.002V35.3901H121.141Z" fill="#fff"></path>
      </svg>
    </div>
  );
}

/* ---------------- Reveal ----------------
   Passthrough wrapper: content is always rendered fully visible. We
   deliberately avoid opacity/transform entrance animations because the
   preview/runtime can freeze CSS animations at their first keyframe,
   which would strand content at opacity:0. Layout-only wrapper. */
function Reveal({ children, delay = 0, as: Tag = "div", style, className = "" }) {
  return <Tag className={className} style={style}>{children}</Tag>;
}

/* ---------------- Top nav (floating glass) ---------------- */
// ---- ONE nav for the whole public site -------------------------------------
// Targets: "#id" = a section on the landing page, ">route" = a real page.
// Both TopNav (landing) and PageHeader (sub-pages) render THIS list, so the nav never
// changes identity as you move around.
const SITE_LINKS = [
  ["Features", "#features"],
  ["Pricing", "#pricing"],
  ["AI Chatbot", ">ai-chatbot"],
  ["KCIP Fix", ">kcip"],
  ["FAQ", "#faq"],
  ["Support", ">discord"],
];

// Shared click handler. A section link works from ANY page: if we're not on the landing
// page we route there first, then scroll once React has painted it.
function siteNavGo(target, route, onNav, closeMenu) {
  return (e) => {
    if (e && e.preventDefault) e.preventDefault();
    if (closeMenu) closeMenu();
    if (target.charAt(0) === ">") { onNav(target.slice(1)); return; }
    const id = target.slice(1);
    const scroll = () => document.getElementById(id)?.scrollIntoView({ behavior: "smooth", block: "start" });
    if (route === "landing") { scroll(); return; }
    onNav("landing");
    // onNav jumps to the top; wait for the landing tree to mount before scrolling.
    setTimeout(scroll, 140);
  };
}

function siteNavActive(target, route) {
  return target.charAt(0) === ">" && target.slice(1) === route;
}

function TopNav({ onNav, onLogin, route }) {
  const [scrolled, setScrolled] = useState(false);
  const [menuOpen, setMenuOpen] = useState(false);
  useEffect(() => {
    const fn = () => setScrolled(window.scrollY > 24);
    window.addEventListener("scroll", fn, { passive: true }); fn();
    return () => window.removeEventListener("scroll", fn);
  }, []);
  const links = SITE_LINKS;
  const go = (target) => siteNavGo(target, route, onNav, () => setMenuOpen(false));
  return (
    <div style={{ position: "fixed", top: 0, left: 0, right: 0, zIndex: 50, display: "flex", flexDirection: "column", alignItems: "center", padding: scrolled ? "12px 16px" : "20px 16px", transition: "padding .3s" }}>
      <div className="glass" style={{
        width: "100%", maxWidth: "var(--maxw)", display: "flex", alignItems: "center", justifyContent: "space-between",
        padding: "10px 12px 10px 18px", borderRadius: 999,
        boxShadow: scrolled ? "var(--shadow-2)" : "var(--shadow-1)",
        transition: "box-shadow .3s",
      }}>
        <Logo size={26} onClick={() => onNav("landing")} />
        <nav style={{ display: "flex", gap: 4, position: "absolute", left: "50%", transform: "translateX(-50%)" }} className="nav-links">
          {links.map(([label, target]) => (
            <a key={target} href={target.charAt(0) === ">" ? "#" : target} onClick={go(target)} style={{
              padding: "8px 14px", borderRadius: 999, fontSize: 14, fontWeight: 500, color: "var(--ink-2)",
              transition: "color .2s, background .2s",
            }}
              onMouseEnter={(e) => { e.currentTarget.style.color = "var(--ink)"; e.currentTarget.style.background = "var(--glass-fill)"; }}
              onMouseLeave={(e) => { e.currentTarget.style.color = "var(--ink-2)"; e.currentTarget.style.background = "transparent"; }}>
              {label}
            </a>
          ))}
        </nav>
        <div className="nav-actions-desktop" style={{ display: "flex", gap: 8, alignItems: "center" }}>
          <button className="btn btn-ghost btn-sm" onClick={onLogin} style={{ borderRadius: 999 }}>Log in</button>
          <button className="btn btn-primary btn-sm" onClick={() => onNav("signup")}>
            Get KVB <Icon name="arrow" size={15} />
          </button>
        </div>
        <button className="nav-burger" aria-label="Menu" onClick={() => setMenuOpen(o => !o)} style={{
          display: "none", width: 40, height: 40, borderRadius: 999, border: "1px solid var(--glass-border)",
          background: "var(--glass-fill)", color: "var(--ink)", cursor: "pointer", alignItems: "center", justifyContent: "center", flexDirection: "column", gap: 4,
        }}>
          <span style={{ width: 16, height: 2, background: "currentColor", borderRadius: 2, transition: "transform .25s", transform: menuOpen ? "translateY(3px) rotate(45deg)" : "none" }} />
          <span style={{ width: 16, height: 2, background: "currentColor", borderRadius: 2, transition: "transform .25s", transform: menuOpen ? "translateY(-3px) rotate(-45deg)" : "none" }} />
        </button>
      </div>

      {/* Mobile dropdown */}
      <div className="nav-mobile-menu" style={{
        display: "none", width: "100%", maxWidth: "var(--maxw)", marginTop: 8,
        maxHeight: menuOpen ? 360 : 0, opacity: menuOpen ? 1 : 0, overflow: "hidden",
        transition: "max-height .3s cubic-bezier(.2,.7,.3,1), opacity .25s",
      }}>
        <div className="glass" style={{ borderRadius: "var(--radius)", padding: 12, boxShadow: "var(--shadow-2)" }}>
          <div className="stack" style={{ gap: 2 }}>
            {links.map(([label, target]) => (
              <a key={target} href={target.charAt(0) === ">" ? "#" : target} onClick={go(target)} style={{ padding: "12px 14px", borderRadius: 12, fontSize: 15, fontWeight: 500, color: "var(--ink)" }}>{label}</a>
            ))}
          </div>
          <hr className="divider" style={{ margin: "10px 0" }} />
          <div style={{ display: "flex", gap: 8 }}>
            <button className="btn btn-ghost" onClick={() => { setMenuOpen(false); onLogin(); }} style={{ flex: 1, justifyContent: "center" }}>Log in</button>
            <button className="btn btn-primary" onClick={() => { setMenuOpen(false); onNav("signup"); }} style={{ flex: 1, justifyContent: "center" }}>Get KVB</button>
          </div>
        </div>
      </div>

      <style>{`@media (max-width: 860px){
        .nav-links{ display:none !important; }
        .nav-actions-desktop{ display:none !important; }
        .nav-burger{ display:flex !important; }
        .nav-mobile-menu{ display:block !important; }
      }`}</style>
    </div>
  );
}

/* ---------------- Footer ---------------- */
const FOOTER_ROUTES = {
  "Features": { id: "features" }, "Performance": { id: "perf" }, "Pricing": { id: "pricing" },
  "Dashboard": { route: "dashboard" }, "AI Chatbot": { route: "ai-chatbot" },
  "About": { route: "about" }, "Support": { route: "discord" }, "Status": { route: "status" }, "Changelog": { route: "changelog" },
  "Privacy Policy": { route: "privacy" }, "Refund Policy": { route: "refund" }, "Terms of Service": { route: "terms" },
};
// The footer badge sits on EVERY page, so a hardcoded "All systems operational" is the site's
// most-seen claim. It reads the same feed as the status page (30s server-side cache, so this is
// cheap) and says nothing at all until it has an answer — a neutral label beats a confident lie.
function FooterStatusChip({ onNav }) {
  const [s, setS] = React.useState(null);
  React.useEffect(() => {
    let alive = true;
    fetch("/app/api/status.php", { cache: "no-store" })
      .then(r => (r.ok ? r.json() : null))
      .then(j => { if (alive && j && j.services) setS(j); })
      .catch(() => { /* leave the neutral label */ });
    return () => { alive = false; };
  }, []);
  const label = !s
    ? "System status"
    : s.all_ok ? "All systems operational" : `${s.operational} of ${s.total} systems operational`;
  const tone = !s || s.all_ok
    ? null
    : ((s.services || []).some(x => x.status === "outage") ? "oklch(0.65 0.20 25)" : "oklch(0.82 0.15 75)");
  return (
    <button className="chip" onClick={() => onNav("status")} title="View full system status"
      style={{ marginTop: 18, cursor: "pointer", border: "1px solid var(--glass-border-soft)" }}>
      <span className="dot" style={tone ? { background: tone, boxShadow: "none" } : undefined} /> {label}
    </button>
  );
}

function Footer({ onNav }) {
  const cols = [
    ["Product", ["Features", "AI Chatbot", "Pricing", "Dashboard"]],
    ["Company", ["About", "Support", "Status", "Changelog"]],
    ["Legal", ["Privacy Policy", "Refund Policy", "Terms of Service"]],
  ];
  const handle = (x) => (e) => {
    e.preventDefault();
    const t = FOOTER_ROUTES[x];
    if (!t) return;
    if (t.route) onNav(t.route);
    else if (t.id) { onNav("landing"); setTimeout(() => document.getElementById(t.id)?.scrollIntoView({ behavior: "smooth", block: "start" }), 60); }
  };
  return (
    <footer className="section" style={{ paddingTop: 80, paddingBottom: 40 }}>
      <div className="wrap">
        <div className="glass" style={{ borderRadius: "var(--radius-lg)", padding: "44px clamp(24px,4vw,56px)" }}>
          <div style={{ display: "grid", gridTemplateColumns: "1.6fr repeat(3, 1fr)", gap: 40 }} className="footgrid">
            <div>
              <Logo size={30} onClick={() => onNav("landing")} />
              <p className="body" style={{ marginTop: 16, maxWidth: 280, fontSize: 14.5 }}>
                KVB is the best view bot on the market in terms of both price and performance. We strive to bring our customers the highest quality with the lowest prices.
              </p>
              <FooterStatusChip onNav={onNav} />
            </div>
            {cols.map(([h, items]) => (
              <div key={h}>
                <div className="cap" style={{ fontWeight: 600, color: "var(--ink-2)", marginBottom: 14 }}>{h}</div>
                <div className="stack" style={{ gap: 11, alignItems: "flex-start" }}>
                  {items.map(x => <a key={x} href="#" onClick={handle(x)} style={{ fontSize: 14, color: "var(--ink-3)", transition: "color .2s", cursor: "pointer" }}
                    onMouseEnter={e => e.currentTarget.style.color = "var(--ink)"} onMouseLeave={e => e.currentTarget.style.color = "var(--ink-3)"}>{x}</a>)}
                </div>
              </div>
            ))}
          </div>
          <hr className="divider" style={{ margin: "34px 0 22px" }} />
          <div style={{ display: "flex", justifyContent: "space-between", flexWrap: "wrap", gap: 12 }}>
            <span className="cap">© 2026 KVB · All rights reserved</span>
            <span className="cap">Made for Creators who move at the speed of Light.</span>
          </div>
        </div>
      </div>
      <style>{`@media (max-width: 760px){ .footgrid{ grid-template-columns: 1fr 1fr !important; } }`}</style>
    </footer>
  );
}

/* ---------------- Stat counter ---------------- */
function Stat({ value, suffix = "", label, decimals = 0 }) {
  const ref = useRef(null);
  const [n, setN] = useState(0);
  useEffect(() => {
    const el = ref.current; if (!el) return;
    const io = new IntersectionObserver(([e]) => {
      if (!e.isIntersecting) return; io.disconnect();
      const dur = 1400, t0 = performance.now();
      const tick = (t) => {
        const p = Math.min(1, (t - t0) / dur);
        const e2 = 1 - Math.pow(1 - p, 3);
        setN(value * e2);
        if (p < 1) requestAnimationFrame(tick);
      };
      requestAnimationFrame(tick);
    }, { threshold: 0.4 });
    io.observe(el); return () => io.disconnect();
  }, [value]);
  const disp = decimals ? n.toFixed(decimals) : Math.round(n).toLocaleString();
  return (
    <div ref={ref}>
      <div className="h1 gradient-text" style={{ fontWeight: 700 }}>{disp}{suffix}</div>
      <div className="cap" style={{ marginTop: 6 }}>{label}</div>
    </div>
  );
}

Object.assign(window, { Icon, Logo, Reveal, TopNav, Footer, Stat, SITE_LINKS, siteNavGo, siteNavActive });
