/* ============================================================================
   AaronMHampton.com UI Kit — shared components, data, atoms
   Exports to window for cross-file use (Babel scopes are per-script).
   ========================================================================== */

/* ---- Icon (Lucide, imperatively mounted so React never fights it) --------- */
function Icon({ name, size = 18, stroke = 1.75, className = "" }) {
  const ref = React.useRef(null);
  React.useEffect(() => {
    const el = ref.current;
    if (!el || !window.lucide) return;
    el.innerHTML = "";
    const pascal = name.split("-").map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join("");
    const node =
    window.lucide.icons && window.lucide.icons[pascal] || window.lucide[pascal];
    if (node && window.lucide.createElement) {
      const svg = window.lucide.createElement(node);
      svg.setAttribute("width", size);
      svg.setAttribute("height", size);
      svg.setAttribute("stroke-width", stroke);
      el.appendChild(svg);
    }
  });
  return (
    <span ref={ref} className={"lic " + className}
    style={{ display: "inline-flex", width: size, height: size, alignItems: "center", justifyContent: "center" }} />);

}

/* ---- Atoms ---------------------------------------------------------------- */
function Crosshair() {return <span className="crosshair" />;}

function Eyebrow({ idx, children }) {
  return (
    <span className="eyebrow">
      {idx && <span className="idx">{idx} —</span>}
      {children}
    </span>);

}

function Button({ variant = "primary", children, onClick, as = "button", href }) {
  const cls = "btn btn-" + variant;
  if (as === "a") return <a className={cls} href={href} onClick={onClick}>{children}</a>;
  return <button className={cls} onClick={onClick}>{children}</button>;
}

function Tag({ children, on, onClick }) {
  return <button className={"tag" + (on ? " on" : "")} onClick={onClick}>{children}</button>;
}

function Placeholder({ label = "Image", style }) {
  return (
    <div className="ph" style={style}>
      <span className="ph-label">{label}</span>
    </div>);

}

/* ---- Brand / Logo --------------------------------------------------------- */
function BrandMark() {
  return (
    <span className="brand-mark" style={{ margin: "0px", gap: "0px", width: "35px", padding: "0px", height: "30px" }}><b style={{ height: "11px", fontSize: "11px" }}>AMH</b></span>);

}
function Brand({ onClick }) {
  return (
    <a className="brand" onClick={onClick}>
      <BrandMark />
      <span className="brand-name">Aaron M. Hampton</span>
    </a>);

}

/* ---- Theme toggle (controlled by App) ------------------------------------- */
function ThemeToggle({ theme, onToggle }) {
  return (
    <button className="icon-btn" title="Toggle theme" aria-label="Toggle theme"
    onClick={onToggle}>
      <Icon name={theme === "dark" ? "sun" : "moon"} size={18} />
    </button>);

}

/* ---- Search trigger — the front door to ⌘K global search ------------------ */
function SearchTrigger({ onClick, compact }) {
  const mod = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform || "") ? "\u2318" : "Ctrl";
  if (compact) {
    return (
      <button className="icon-btn" title="Search" aria-label="Search" onClick={onClick}>
        <Icon name="search" size={18} />
      </button>);

  }
  return (
    <button className="search-trigger" onClick={onClick} aria-label="Open search">
      <Icon name="search" size={15} />
      <span className="st-label">Search</span>
      <kbd className="kbd">{mod} K</kbd>
    </button>);

}

/* ---- Nav data ------------------------------------------------------------- */
const NAV = [
{ id: "writing", label: "Writing" },
{ id: "projects", label: "Projects" },
{ id: "photos", label: "Photos" },
{ id: "about", label: "About" }];


/* ---- Top bar -------------------------------------------------------------- */
function TopBar({ route, go, theme, onToggleTheme, onSearch }) {
  const [open, setOpen] = React.useState(false);
  const navTo = (id) => {go(id);setOpen(false);};
  return (
    <header className="topbar">
      <div className="wrap">
        <div className="topbar-inner">
          <Brand onClick={() => navTo("home")} />
          <nav className="nav">
            {NAV.map((n) =>
            <a key={n.id}
            className={"nav-link" + (route === n.id ? " active" : "")}
            onClick={() => navTo(n.id)}>{n.label}</a>
            )}
            <SearchTrigger onClick={onSearch} />
            <ThemeToggle theme={theme} onToggle={onToggleTheme} />
            <Button variant="primary" onClick={() => navTo("subscribe")}>Subscribe →</Button>
          </nav>
          <div className="topbar-mobile-actions">
            <SearchTrigger onClick={onSearch} compact />
            <button className="icon-btn hamburger" onClick={() => setOpen((o) => !o)}>
              <Icon name={open ? "x" : "menu"} size={20} />
            </button>
          </div>
        </div>
        <div className={"mobile-menu" + (open ? " open" : "")}>
          {NAV.map((n) =>
          <a key={n.id} className={"nav-link" + (route === n.id ? " active" : "")}
          onClick={() => navTo(n.id)}>{n.label}</a>
          )}
          <a className="nav-link" onClick={() => navTo("subscribe")}>Subscribe →</a>
          <div style={{ marginTop: 8 }}><ThemeToggle theme={theme} onToggle={onToggleTheme} /></div>
        </div>
      </div>
    </header>);

}

/* ---- Footer --------------------------------------------------------------- */
function Footer({ go }) {
  return (
    <footer className="footer">
      <div className="wrap">
        <div className="footer-grid">
          <div>
            <Brand onClick={() => go("home")} />
            <p className="footer-tagline">A public notebook on science, philosophy, history, and the technology between them.</p>
          </div>
          <div>
            <h4>Site</h4>
            {NAV.map((n) => <a key={n.id} className="col-link" onClick={() => go(n.id)}>{n.label}</a>)}
          </div>
          <div>
            <h4>Elsewhere</h4>
            <a className="col-link" href="#"><Icon name="github" size={13} /> &nbsp;GitHub ↗</a>
            <a className="col-link" href="#"><Icon name="rss" size={13} /> &nbsp;RSS feed ↗</a>
            <a className="col-link" href="#">Email ↗</a>
          </div>
        </div>
        <div className="footer-base">
          <span>© 2026 Aaron M. Hampton</span>
          <span>Built with intent · Hedvig Letters Serif + General Sans</span>
        </div>
      </div>
    </footer>);

}

/* ---- Content data --------------------------------------------------------- */
const POSTS = [
{ id: "p1", num: "014", cat: "Essay", title: "Attention is the only scarce resource I have left",
  desc: "A short argument for treating focus as capital — and three habits I changed once I believed it.",
  date: "2026-05-12", read: "7 min", tags: ["philosophy", "technology"] },
{ id: "p2", num: "013", cat: "Note", title: "What the printing press actually changed",
  desc: "Less about literacy than we think, more about the economics of being wrong in public.",
  date: "2026-04-28", read: "5 min", tags: ["history"] },
{ id: "p3", num: "012", cat: "Essay", title: "A bias toward the legible",
  desc: "Why systems drift toward what's measurable, and what gets quietly deleted on the way.",
  date: "2026-04-09", read: "9 min", tags: ["politics", "science"] },
{ id: "p4", num: "011", cat: "Note", title: "Tools are arguments about how to live",
  desc: "Every interface encodes a theory of the person using it. Most of them are wrong about you.",
  date: "2026-03-22", read: "4 min", tags: ["technology", "philosophy"] },
{ id: "p5", num: "010", cat: "Essay", title: "On keeping a slow archive",
  desc: "I write to remember what I actually thought, not what I wish I had. Here's the system.",
  date: "2026-03-01", read: "6 min", tags: ["science"] }];


const PROJECTS = [
{ id: "j1", title: "Marginalia", tagline: "A reader that pulls your notes into the margin where they belong.", lang: "TypeScript", stars: "1.2k", year: "2026" },
{ id: "j2", title: "Plotpaper", tagline: "Minimal charting library for thinking in public. Hairlines, no chartjunk.", lang: "Rust · WASM", stars: "640", year: "2025" },
{ id: "j3", title: "Slowfeed", tagline: "An RSS reader that refuses to show you anything more than once a day.", lang: "Go", stars: "2.1k", year: "2025" },
{ id: "j4", title: "Index", tagline: "The engine behind this site. Markdown in, quiet HTML out.", lang: "TypeScript", stars: "310", year: "2024" }];


const PHOTOS = [
{ id: "ph1", cap: "Coastal range", meta: "35mm", ar: "3/4" },
{ id: "ph2", cap: "Reading desk", meta: "50mm", ar: "1/1" },
{ id: "ph3", cap: "Fog, early", meta: "35mm", ar: "4/5" },
{ id: "ph4", cap: "Library stacks", meta: "28mm", ar: "1/1" },
{ id: "ph5", cap: "Long exposure", meta: "35mm", ar: "3/4" },
{ id: "ph6", cap: "Train window", meta: "50mm", ar: "4/5" },
{ id: "ph7", cap: "Workbench", meta: "35mm", ar: "1/1" },
{ id: "ph8", cap: "Dusk field", meta: "28mm", ar: "3/4" },
{ id: "ph9", cap: "Notebook study", meta: "50mm", ar: "4/5" }];


Object.assign(window, {
  Icon, Crosshair, Eyebrow, Button, Tag, Placeholder,
  BrandMark, Brand, ThemeToggle, SearchTrigger, TopBar, Footer,
  NAV, POSTS, PROJECTS, PHOTOS
});