// Shared data + hooks for all three landing-page directions.
const HUB_APPS = [
  {
    id: "boreholeai",
    name: "BoreholeAI",
    betaSup: true,
    tagline: "Extract structured ground profiles from any borehole-log PDF.",
    long: "An autonomous geotechnical AI agent that extracts ground profiles, test data, and metadata from any borehole log PDF — any template, any company. Visual grounding with full source traceability.",
    stack: "Next.js · LLM · OCR",
    inputs: ["PDF borehole logs"],
    outputs: ["Ground profiles", "Test data tables", "AGS / xlsx export"],
    status: "Live",
    statusKind: "live",
    version: "beta",
    code: "01",
    glyph: "AI",
    hue: "ai",
    external: true,
    url: "https://www.boreholeai.com/",
  },
  {
    id: "geotech-viz",
    name: "Geotechnical Data Visualisation",
    tagline: "Clean, mask, and visualise borehole + lab data on one canvas.",
    long: "Streamlit workspace for cleaning, masking, and visualising borehole and lab datasets — depth profiles, summaries, exportable figures.",
    stack: "Streamlit · Python",
    inputs: ["AGS / xlsx", "Lab tests", "Field logs"],
    outputs: ["Depth profiles", "Summary tables", "Figures"],
    status: "Live",
    statusKind: "live",
    version: "v5.1",
    code: "02",
    glyph: "Σ",
    hue: "earth",
  },
  {
    id: "geophysics",
    name: "Geophysics App",
    tagline: "Correlate seismic surveys with borehole logs along any chainage.",
    long: "Correlate S-/P-wave velocity profiles with lithology and lab data. Site-agnostic, browser-first, with an interactive study area and live parameter re-tuning.",
    stack: "Next.js · FastAPI · MapLibre",
    inputs: ["Geophysics CSV", "BH interpretation", "Lab summary"],
    outputs: ["Velocity ↔ depth", "Cross-section", "Bedrock estimate"],
    status: "Live",
    statusKind: "live",
    version: "v1.2",
    code: "03",
    glyph: "Vs",
    hue: "seismic",
  },
];

const HUB_AUTHOR = {
  name: "Quin Li",
  role: "Geotechnical Engineer & Digital / AI Specialist",
  org: "",
  email: "quin.li@eicactiv.com",
  linkedin: "https://www.linkedin.com/in/quin-li-706b5015b/",
  initials: "QL",
  brand: "Geotech Digital",
};

// Cursor spotlight hook — returns {x, y} relative to ref, with smooth lerp.
function useSpotlight(ref) {
  const [pos, setPos] = React.useState({ x: 0.5, y: 0.5, active: false });
  React.useEffect(() => {
    const el = ref.current;
    if (!el) return;
    let raf;
    let target = { x: 0.5, y: 0.5 };
    let current = { x: 0.5, y: 0.5 };
    const onMove = (e) => {
      const r = el.getBoundingClientRect();
      target = { x: (e.clientX - r.left) / r.width, y: (e.clientY - r.top) / r.height };
      setPos((p) => ({ ...p, active: true }));
    };
    const onLeave = () => setPos((p) => ({ ...p, active: false }));
    const tick = () => {
      current.x += (target.x - current.x) * 0.18;
      current.y += (target.y - current.y) * 0.18;
      setPos((p) => ({ x: current.x, y: current.y, active: p.active }));
      raf = requestAnimationFrame(tick);
    };
    el.addEventListener("mousemove", onMove);
    el.addEventListener("mouseleave", onLeave);
    raf = requestAnimationFrame(tick);
    return () => {
      el.removeEventListener("mousemove", onMove);
      el.removeEventListener("mouseleave", onLeave);
      cancelAnimationFrame(raf);
    };
  }, [ref]);
  return pos;
}

// Pulsing live-status dot.
function StatusPing({ kind = "live", color = "#10b981", label = "Live" }) {
  const c = kind === "live" ? color : kind === "beta" ? "#7c3aed" : kind === "dev" ? "#f59e0b" : "#71717a";
  return (
    <span style={{ display: "inline-flex", alignItems: "center", gap: 8, fontSize: 11, fontWeight: 600, letterSpacing: "0.14em", textTransform: "uppercase", color: "currentColor" }}>
      <span style={{ position: "relative", width: 8, height: 8 }}>
        <span style={{ position: "absolute", inset: 0, borderRadius: 999, background: c, opacity: 0.35, animation: "hubPing 1.8s ease-out infinite" }} />
        <span style={{ position: "absolute", inset: 1.5, borderRadius: 999, background: c, boxShadow: `0 0 8px ${c}` }} />
      </span>
      {label}
    </span>
  );
}

// Inject keyframes for ping animation once.
(function injectHubKeyframes() {
  if (document.getElementById("hub-keyframes")) return;
  const style = document.createElement("style");
  style.id = "hub-keyframes";
  style.textContent = `
    @keyframes hubPing {
      0% { transform: scale(0.6); opacity: 0.7; }
      80%, 100% { transform: scale(2.2); opacity: 0; }
    }
    @keyframes hubFadeUp {
      from { opacity: 0; transform: translateY(8px); }
      to { opacity: 1; transform: none; }
    }
    @keyframes hubMarquee {
      from { transform: translateX(0); }
      to { transform: translateX(-50%); }
    }
    @keyframes hubBlink {
      0%, 100% { opacity: 1; }
      50% { opacity: 0.2; }
    }
  `;
  document.head.appendChild(style);
})();

// Resolve accent color from tweaks setting.
const ACCENTS = {
  red: { name: "EIC Red", color: "#d71919", soft: "#fef3f3", deep: "#a11313" },
  ochre: { name: "Survey Ochre", color: "#c97a1a", soft: "#fdf3e6", deep: "#8a5212" },
  ink: { name: "Engineer Ink", color: "#1f2937", soft: "#eef2f7", deep: "#0f172a" },
  cobalt: { name: "Cobalt", color: "#1d4fd7", soft: "#eaf0ff", deep: "#0f3299" },
};

function getAccent(key) {
  return ACCENTS[key] || ACCENTS.red;
}

Object.assign(window, { HUB_APPS, HUB_AUTHOR, useSpotlight, StatusPing, ACCENTS, getAccent });
