/* =========================================================================
   Shared components & hooks
   ========================================================================= */
const { useState, useEffect, useRef, useCallback } = React;

/* ---- tiny inline icons (geometric only) ---- */
const Icon = {
  sun: (p) => (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" {...p}>
      <circle cx="12" cy="12" r="4.2"/>
      <path d="M12 2.6v2.4M12 19v2.4M2.6 12H5M19 12h2.4M5.2 5.2l1.7 1.7M17.1 17.1l1.7 1.7M18.8 5.2l-1.7 1.7M6.9 17.1l-1.7 1.7"/>
    </svg>
  ),
  moon: (p) => (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round" {...p}>
      <path d="M20 14.5A8 8 0 1 1 9.6 4a6.3 6.3 0 0 0 10.4 10.5z"/>
    </svg>
  ),
  arrowDown: (p) => (<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M12 5v14M6 13l6 6 6-6"/></svg>),
  arrowLeft: (p) => (<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M19 12H5M11 6l-6 6 6 6"/></svg>),
  arrowRight: (p) => (<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M5 12h14M13 6l6 6-6 6"/></svg>),
  chevron: (p) => (<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M6 9l6 6 6-6"/></svg>),
};

/* ---- Emblem image ---- */
function Emblem({ className = "", size, halo = false, style }) {
  const img = <img className={"emblem " + className} src="assets/emblem.png" alt="左锡宁 纹章 / emblem"
    style={{ width: size, height: size ? size : undefined, ...style }} draggable="false" />;
  if (!halo) return img;
  return <span className="emblem-halo">{img}</span>;
}

/* ---- Cosmos backdrop: faint nebula + starfield ---- */
function Cosmos() {
  const stars = useRef(null);
  if (!stars.current) {
    const arr = [];
    for (let i = 0; i < 80; i++) {
      const big = Math.random() > 0.86;
      arr.push({
        left: Math.random() * 100,
        top: Math.random() * 100,
        s: big ? 2.2 + Math.random() * 1.4 : 0.7 + Math.random() * 1.1,
        dur: 4 + Math.random() * 7,
        del: -Math.random() * 8,
        o: big ? 0.9 : 0.5,
      });
    }
    stars.current = arr;
  }
  return (
    <div className="cosmos" aria-hidden="true">
      <img className="cosmos__img" src="assets/nebula.jpg" alt="" />
      <div className="stars">
        {stars.current.map((s, i) => (
          <i key={i} style={{ left: s.left + "%", top: s.top + "%", width: s.s, height: s.s, "--dur": s.dur + "s", "--del": s.del + "s", maxOpacity: s.o }} />
        ))}
      </div>
      <div className="cosmos__veil" />
    </div>
  );
}

/* ---- Controls: language + theme ---- */
function LangToggle({ lang, onToggle, t }) {
  return (
    <button className="ctl" onClick={onToggle} aria-label="Switch language" title="中 / EN">
      <span style={{ color: "var(--ink)", fontWeight: 600 }}>{lang === "zh" ? "中" : "EN"}</span>
      <span style={{ opacity: .35 }}>/</span>
      <span>{lang === "zh" ? "EN" : "中"}</span>
    </button>
  );
}
function ThemeToggle({ theme, onToggle }) {
  return (
    <button className="ctl" onClick={onToggle} aria-label="Toggle theme"
      title={theme === "dark" ? "Light" : "Dark"}>
      {theme === "dark" ? <Icon.sun /> : <Icon.moon />}
    </button>
  );
}

/* ---- Reveal on scroll (scroll-driven, robust; content never stuck hidden) ---- */
function useReveal() {
  const ref = useRef(null);
  useEffect(() => {
    let raf = 0;
    const reveal = () => {
      raf = 0;
      const vh = window.innerHeight || 800;
      document.querySelectorAll(".rise:not(.in)").forEach((e) => {
        if (e.getBoundingClientRect().top < vh * 0.92) e.classList.add("in");
      });
    };
    const onScroll = () => { if (!raf) raf = requestAnimationFrame(reveal); };
    reveal();
    requestAnimationFrame(reveal);
    window.addEventListener("scroll", onScroll, { passive: true });
    window.addEventListener("resize", onScroll);
    const t = setTimeout(reveal, 350);
    return () => {
      window.removeEventListener("scroll", onScroll);
      window.removeEventListener("resize", onScroll);
      clearTimeout(t); cancelAnimationFrame(raf);
    };
  }, []);
  return ref;
}

/* ---- Section header ---- */
function SectionHead({ idx, title, cjk, en }) {
  return (
    <header className="sec-head rise">
      {idx && <span className="sec-head__idx">{idx}</span>}
      <h2 className="sec-head__title">{cjk ? <span className="cjk">{title}</span> : title}</h2>
      {en && <span className="sec-head__en">{en}</span>}
    </header>
  );
}

Object.assign(window, { Icon, Emblem, Cosmos, LangToggle, ThemeToggle, useReveal, SectionHead });
