/* =========================================================
   JETX LLC — Shared components (multi-page)
   ========================================================= */
const { useState, useEffect, useRef } = React;

/* ---------- counter that animates when triggered ---------- */
function useCountUp(target, options = {}) {
  const { duration = 1600, decimals = 0, trigger = true } = options;
  const [value, setValue] = useState(0);
  const startRef = useRef(null);
  const rafRef = useRef(null);
  useEffect(() => {
    if (!trigger) return;
    const step = (ts) => {
      if (!startRef.current) startRef.current = ts;
      const p = Math.min((ts - startRef.current) / duration, 1);
      const eased = 1 - Math.pow(1 - p, 5);
      setValue(target * eased);
      if (p < 1) rafRef.current = requestAnimationFrame(step);
    };
    rafRef.current = requestAnimationFrame(step);
    return () => rafRef.current && cancelAnimationFrame(rafRef.current);
  }, [target, duration, trigger]);
  return decimals === 0 ? Math.round(value) : value.toFixed(decimals);
}

/* ---------- Reveal on scroll ---------- */
function Reveal({ children, className = "", delay = 0, as = "div", ...rest }) {
  const ref = useRef(null);
  const [shown, setShown] = useState(false);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const io = new IntersectionObserver(
      (entries) => entries.forEach((e) => {
        if (e.isIntersecting) { setTimeout(() => setShown(true), delay); io.unobserve(el); }
      }),
      { threshold: 0.12, rootMargin: "0px 0px -60px 0px" }
    );
    io.observe(el);
    return () => io.disconnect();
  }, [delay]);
  const Tag = as;
  return <Tag ref={ref} className={`reveal ${shown ? "in" : ""} ${className}`} {...rest}>{children}</Tag>;
}

/* ---------- NAV ---------- */
const NAV_ITEMS = [
  { label: "Home", href: "index.html" },
  { label: "About", href: "about.html" },
  { label: "Technology", href: "projects.html" },
  { label: "Portfolio", href: "gallery.html" },
  { label: "News", href: "news.html" },
  { label: "Contact", href: "contactus.html" },
];

function Nav({ current }) {
  const [scrolled, setScrolled] = useState(false);
  const [open, setOpen] = useState(false);
  useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 40);
    onScroll();
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, []);
  const here = current || (location.pathname.split("/").pop() || "index.html");
  return (
    <header className={`nav ${scrolled ? "scrolled" : ""}`}>
      <a href="index.html" className="nav-brand" aria-label="JETX home">
        <img src="assets/logos/jetx-white.png" alt="JETX" className="nav-logo" />
      </a>
      <nav>
        <ul className="nav-links">
          {NAV_ITEMS.map((it) => (
            <li key={it.href}>
              <a href={it.href} className={here === it.href ? "active" : ""}>{it.label}</a>
            </li>
          ))}
        </ul>
      </nav>
      <div className="nav-right">
        <a href="contactus.html" className="nav-cta">
          <span>Get in touch</span><span className="arrow">→</span>
        </a>
        <button className="nav-burger" aria-label="Menu" onClick={() => setOpen((o) => !o)}>
          <span></span><span></span>
        </button>
      </div>
      {open && (
        <div className="nav-mobile">
          {NAV_ITEMS.map((it) => (
            <a key={it.href} href={it.href} className={here === it.href ? "active" : ""}>{it.label}</a>
          ))}
        </div>
      )}
    </header>
  );
}

/* ---------- SUBHERO (interior pages) ---------- */
function SubHero({ crumb, title, lede, image, flip, mirror }) {
  const [entered, setEntered] = useState(false);
  useEffect(() => { const id = setTimeout(() => setEntered(true), 60); return () => clearTimeout(id); }, []);
  return (
    <section className={`subhero ${entered ? "entered" : ""} ${image ? "has-render" : ""} ${flip ? "subhero-flip" : ""} ${mirror ? "subhero-mirror" : ""}`}>
      <div className="subhero-grid"></div>
      {image
        ? <div className="subhero-render"><img src={image} alt="" /><div className="subhero-render-scrim"></div></div>
        : <div className="subhero-ghost" aria-hidden="true">{title}</div>}
      <div className="subhero-content shell">
        <div className="crumb">
          <span className="bar"></span>
          <span className="eyebrow">{crumb}</span>
        </div>
        <h1 className="subhero-title">{title}</h1>
        {lede && <p className="subhero-lede">{lede}</p>}
      </div>
    </section>
  );
}

/* ---------- PARTNERS / PROGRAMS LOGO STRIP ---------- */
function PartnersStrip({ heading = "Validated with", note }) {
  const logos = [
    { src: "assets/logos/army-white.png", label: "U.S. Army" },
    { src: "assets/logos/usaf-white.png", label: "U.S. Air Force" },
    { src: "assets/logos/sbir-white.png", label: "SBIR · STTR" },
    { src: "assets/logos/xtech-white.png", label: "Army xTech" },
    { src: "assets/logos/ucf-white.png", label: "University of Central Florida" },
    { src: "assets/logos/ttu-white.png", label: "Tennessee Tech" },
    { src: "assets/logos/cymstar-white.png", label: "CymSTAR" },
  ];
  return (
    <Reveal className="partners-strip">
      <div className="partners-strip-head">
        <span className="eyebrow">{heading}</span>
        {note && <span className="partners-note">{note}</span>}
      </div>
      <div className="logo-wall">
        {logos.map((l) => (
          <div className="logo-chip" key={l.label} title={l.label}>
            <img src={l.src} alt={l.label} />
          </div>
        ))}
      </div>
    </Reveal>
  );
}

/* ---------- SOCIAL ICONS ---------- */
function SocialIcon({ name }) {
  const p = { width: 18, height: 18, viewBox: "0 0 24 24", fill: "currentColor" };
  if (name === "X") return (
    <svg {...p}><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24h-6.66l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25h6.83l4.713 6.231 5.447-6.231Zm-1.161 17.52h1.833L7.084 4.126H5.117L17.083 19.77Z"/></svg>
  );
  if (name === "LinkedIn") return (
    <svg {...p}><path d="M20.45 20.45h-3.56v-5.57c0-1.33-.02-3.04-1.85-3.04-1.85 0-2.13 1.45-2.13 2.94v5.67H9.35V9h3.42v1.56h.05c.48-.9 1.64-1.85 3.37-1.85 3.6 0 4.27 2.37 4.27 5.46v6.28ZM5.34 7.43a2.07 2.07 0 1 1 0-4.14 2.07 2.07 0 0 1 0 4.14ZM7.12 20.45H3.55V9h3.57v11.45ZM22.22 0H1.77C.8 0 0 .78 0 1.74v20.52C0 23.22.8 24 1.77 24h20.45c.98 0 1.78-.78 1.78-1.74V1.74C24 .78 23.2 0 22.22 0Z"/></svg>
  );
  if (name === "YouTube") return (
    <svg {...p}><path d="M23.5 6.2a3.02 3.02 0 0 0-2.12-2.14C19.5 3.55 12 3.55 12 3.55s-7.5 0-9.38.51A3.02 3.02 0 0 0 .5 6.2 31.6 31.6 0 0 0 0 12a31.6 31.6 0 0 0 .5 5.8 3.02 3.02 0 0 0 2.12 2.14C4.5 20.45 12 20.45 12 20.45s7.5 0 9.38-.51a3.02 3.02 0 0 0 2.12-2.14A31.6 31.6 0 0 0 24 12a31.6 31.6 0 0 0-.5-5.8ZM9.6 15.57V8.43L15.82 12 9.6 15.57Z"/></svg>
  );
  if (name === "Instagram") return (
    <svg {...p}><path d="M12 2.16c3.2 0 3.58.01 4.85.07 1.17.05 1.8.25 2.23.41.56.22.96.48 1.38.9.42.42.68.82.9 1.38.16.42.36 1.06.41 2.23.06 1.27.07 1.65.07 4.85s-.01 3.58-.07 4.85c-.05 1.17-.25 1.8-.41 2.23-.22.56-.48.96-.9 1.38-.42.42-.82.68-1.38.9-.42.16-1.06.36-2.23.41-1.27.06-1.65.07-4.85.07s-3.58-.01-4.85-.07c-1.17-.05-1.8-.25-2.23-.41a3.72 3.72 0 0 1-1.38-.9 3.72 3.72 0 0 1-.9-1.38c-.16-.42-.36-1.06-.41-2.23-.06-1.27-.07-1.65-.07-4.85s.01-3.58.07-4.85c.05-1.17.25-1.8.41-2.23.22-.56.48-.96.9-1.38.42-.42.82-.68 1.38-.9.42-.16 1.06-.36 2.23-.41C8.42 2.17 8.8 2.16 12 2.16ZM12 0C8.74 0 8.33.01 7.05.07c-1.28.06-2.15.26-2.91.56-.79.3-1.46.72-2.12 1.38A5.88 5.88 0 0 0 .63 4.14c-.3.76-.5 1.63-.56 2.91C.01 8.33 0 8.74 0 12s.01 3.67.07 4.95c.06 1.28.26 2.15.56 2.91.3.79.72 1.46 1.38 2.12.66.66 1.33 1.08 2.12 1.38.76.3 1.63.5 2.91.56C8.33 23.99 8.74 24 12 24s3.67-.01 4.95-.07c1.28-.06 2.15-.26 2.91-.56a5.88 5.88 0 0 0 2.12-1.38 5.88 5.88 0 0 0 1.38-2.12c.3-.76.5-1.63.56-2.91.06-1.28.07-1.69.07-4.95s-.01-3.67-.07-4.95c-.06-1.28-.26-2.15-.56-2.91a5.88 5.88 0 0 0-1.38-2.12A5.88 5.88 0 0 0 19.86.63c-.76-.3-1.63-.5-2.91-.56C15.67.01 15.26 0 12 0Zm0 5.84a6.16 6.16 0 1 0 0 12.32 6.16 6.16 0 0 0 0-12.32ZM12 16a4 4 0 1 1 0-8 4 4 0 0 1 0 8Zm6.41-10.85a1.44 1.44 0 1 0 0 2.88 1.44 1.44 0 0 0 0-2.88Z"/></svg>
  );
  return null;
}

/* ---------- FOOTER ---------- */
function Footer() {
  const socials = [
    { l: "X", href: "https://twitter.com/JETXAERO" },
    { l: "LinkedIn", href: "https://www.linkedin.com/company/jetxus/" },
    { l: "YouTube", href: "https://www.youtube.com/channel/UC3EqOdS30VVZnpXG4Lb_88Q" },
    { l: "Instagram", href: "https://www.instagram.com/jetx_us/" },
  ];
  return (
    <footer className="footer">
      <div className="footer-grid">
        <div>
          <img src="assets/logos/jetx-white.png" alt="JETX" className="footer-logo" />
          <div className="footer-tag">
            Sustainable, low-cost vector-thrust solutions for the Advanced Air Mobility
            ecosystem — civil and military.
          </div>
        </div>
        <div>
          <h5>Site</h5>
          <div className="footer-links">
            <a href="index.html">Home</a>
            <a href="about.html">About</a>
            <a href="projects.html">Technology</a>
            <a href="gallery.html">Portfolio</a>
            <a href="news.html">News</a>
          </div>
        </div>
        <div>
          <h5>Solutions</h5>
          <div className="footer-links">
            <a href="projects.html">Propulsion</a>
            <a href="projects.html">Aircraft Design</a>
            <a href="projects.html">Modular Platforms</a>
            <a href="projects.html">Autonomy</a>
          </div>
        </div>
        <div className="footer-connect">
          <h5>Connect</h5>
          <div className="footer-links">
            <a href="mailto:info@jetxus.com">info@jetxus.com</a>
            <a href="contactus.html">Contact</a>
          </div>
          <div className="footer-socials">
            {socials.map((s) => (
              <a key={s.l} href={s.href} aria-label={s.l} target="_blank" rel="noreferrer">
                <SocialIcon name={s.l} />
              </a>
            ))}
          </div>
        </div>
      </div>
      <div className="footer-bottom">
        <div>COPYRIGHT © 2020–{new Date().getFullYear()} JETX LLC · ORLANDO, FL · ALL RIGHTS RESERVED</div>
      </div>
    </footer>
  );
}

/* ---------- Investor CTA strip ---------- */
function InvestorCTA() {
  return (
    <section className="cta-strip">
      <div className="shell">
        <Reveal>
          <span className="eyebrow">Get in touch</span>
          <h2 style={{ marginTop: 24 }}>Let's<br />talk.</h2>
          <p>
            We'd love to hear from you — reach out and we'll get back to you.
          </p>
          <a className="btn btn-primary" href="contactus.html">
            <span>Contact us</span><span className="arrow">→</span>
          </a>
        </Reveal>
      </div>
    </section>
  );
}

/* ---------- Propulsion diagram (spinning EDF) ---------- */
function PropulsionDiagram() {
  return (
    <div className="propulsion-diagram" aria-label="Vector-thrust propulsion schematic">
      <svg viewBox="0 0 400 400" width="100%" height="100%" style={{ display: "block" }}>
        <defs>
          <radialGradient id="pglow" cx="50%" cy="50%" r="50%">
            <stop offset="0%" stopColor="rgba(255,255,255,0.18)" />
            <stop offset="60%" stopColor="rgba(255,255,255,0.02)" />
            <stop offset="100%" stopColor="rgba(255,255,255,0)" />
          </radialGradient>
        </defs>
        <circle cx="200" cy="200" r="180" fill="url(#pglow)" />
        {[60, 120, 180].map((r) => (
          <circle key={r} cx="200" cy="200" r={r} fill="none" stroke="rgba(255,255,255,0.10)" strokeWidth="1" />
        ))}
        <circle cx="200" cy="200" r="190" fill="none" stroke="rgba(255,255,255,0.20)" strokeWidth="1" strokeDasharray="2 6" />
        <g style={{ transformOrigin: "200px 200px", animation: "spin 6s linear infinite" }}>
          {[0, 60, 120, 180, 240, 300].map((deg) => (
            <g key={deg} transform={`rotate(${deg} 200 200)`}>
              <path d="M 200 200 L 215 110 Q 200 100 185 110 Z" fill="rgba(255,255,255,0.85)" />
            </g>
          ))}
          <circle cx="200" cy="200" r="22" fill="#000" stroke="rgba(255,255,255,0.6)" />
          <circle cx="200" cy="200" r="6" fill="rgba(255,255,255,0.7)" />
        </g>
        <g stroke="rgba(255,255,255,0.85)" strokeWidth="1.5" fill="none">
          <path d="M 280 200 L 360 200 M 350 192 L 360 200 L 350 208" />
          <path d="M 200 280 L 200 360 M 192 350 L 200 360 L 208 350" />
          <path d="M 120 200 L 40 200 M 50 192 L 40 200 L 50 208" />
        </g>
        <g fontFamily="JetBrains Mono, monospace" fontSize="9" fill="rgba(255,255,255,0.7)" letterSpacing="1.5">
          <text x="365" y="195" textAnchor="end">VECTOR</text>
          <text x="205" y="368">VENTRAL</text>
          <text x="35" y="195">VECTOR</text>
          <text x="200" y="38" textAnchor="middle">EDF · NON-TILTING</text>
          <text x="200" y="395" textAnchor="middle" fill="rgba(255,255,255,0.5)">FLUIDIC + FLAP VECTORING</text>
        </g>
        {[[20,20],[380,20],[20,380],[380,380]].map(([x,y]) => (
          <g key={`${x}-${y}`} stroke="rgba(255,255,255,0.5)" strokeWidth="1">
            <line x1={x-6} y1={y} x2={x+6} y2={y} />
            <line x1={x} y1={y-6} x2={x} y2={y+6} />
          </g>
        ))}
      </svg>
      <style>{`@keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }`}</style>
    </div>
  );
}

/* ---------- Propulsion hardware slider (auto-advancing) ---------- */
function PropulsionSlider() {
  const slides = [
    { src: "assets/concepts/prop-fan-cascade.png", k: "01", l: "Electric Ducted Fan + Cascade" },
    { src: "assets/concepts/prop-edf-cone.png", k: "02", l: "Embedded EDF Module" },
    { src: "assets/concepts/prop-twin-nozzle.png", k: "03", l: "Twin Fluidic Nozzle Unit" },
    { src: "assets/concepts/prop-twin-pods.png", k: "04", l: "Vectoring Thruster Pods" },
  ];
  const [i, setI] = useState(0);
  const [paused, setPaused] = useState(false);
  useEffect(() => {
    if (paused) return;
    const id = setInterval(() => setI((p) => (p + 1) % slides.length), 4200);
    return () => clearInterval(id);
  }, [paused, slides.length]);
  return (
    <div
      className="prop-slider"
      onMouseEnter={() => setPaused(true)}
      onMouseLeave={() => setPaused(false)}
      aria-label="JETX propulsion hardware"
    >
      <div className="prop-slider-stage">
        {slides.map((s, idx) => (
          <img
            key={s.src}
            src={s.src}
            alt={s.l}
            className={idx === i ? "is-active" : ""}
          />
        ))}
        <div className="prop-slider-grid" aria-hidden="true">
          {[[16,16],[null,16],[16,null],[null,null]].map(([x,y], n) => (
            <span key={n} style={{ top: y == null ? "auto" : y, bottom: y == null ? 16 : "auto", left: x == null ? "auto" : x, right: x == null ? 16 : "auto" }} />
          ))}
        </div>
      </div>
      <div className="prop-slider-bar">
        <div className="prop-slider-cap">
          <span className="k mono">{slides[i].k}</span>
          <span className="l">{slides[i].l}</span>
        </div>
        <div className="prop-slider-dots">
          {slides.map((s, idx) => (
            <button
              key={s.src}
              className={idx === i ? "is-active" : ""}
              onClick={() => setI(idx)}
              aria-label={`Show ${s.l}`}
            />
          ))}
        </div>
      </div>
    </div>
  );
}

/* ---------- Service-card image slider (auto-advancing) ---------- */
function ServiceSlider({ slides, fit = "cover" }) {
  const [i, setI] = useState(0);
  const [paused, setPaused] = useState(false);
  useEffect(() => {
    if (paused) return;
    const id = setInterval(() => setI((p) => (p + 1) % slides.length), 4000);
    return () => clearInterval(id);
  }, [paused, slides.length]);
  return (
    <div
      className="service-slider"
      onMouseEnter={() => setPaused(true)}
      onMouseLeave={() => setPaused(false)}
    >
      {slides.map((src, idx) => (
        <img
          key={src}
          src={src}
          alt=""
          className={idx === i ? "is-active" : ""}
          style={{ objectFit: fit }}
        />
      ))}
      <div className="service-slider-dots">
        {slides.map((src, idx) => (
          <button
            key={src}
            className={idx === i ? "is-active" : ""}
            onClick={() => setI(idx)}
            aria-label={`Show image ${idx + 1}`}
          />
        ))}
      </div>
    </div>
  );
}

/* ---------- Page shell: Nav + content + Footer + Tweaks ---------- */
const JETX_TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "accent": "#FFFFFF",
  "density": "comfort"
}/*EDITMODE-END*/;

function PageShell({ current, children }) {
  const [t, setTweak] = window.useTweaks(JETX_TWEAK_DEFAULTS);
  useEffect(() => {
    const map = { "#FFFFFF": "white", "#E40521": "red", "#1A66D6": "blue" };
    document.body.dataset.accent = map[t.accent] || "white";
    document.body.dataset.density = t.density === "tight" ? "tight" : "comfortable";
  }, [t]);
  return (
    <React.Fragment>
      <Nav current={current} />
      <main>{children}</main>
      <Footer />
      <window.TweaksPanel title="Tweaks">
        <window.TweakSection label="Identity" />
        <window.TweakColor label="Accent" value={t.accent} options={["#FFFFFF", "#E40521", "#1A66D6"]} onChange={(v) => setTweak("accent", v)} />
        <window.TweakSection label="Layout" />
        <window.TweakRadio label="Density" value={t.density} options={["comfort", "tight"]} onChange={(v) => setTweak("density", v)} />
      </window.TweaksPanel>
    </React.Fragment>
  );
}

function mountPage(current, Content) {
  ReactDOM.createRoot(document.getElementById("root")).render(
    <PageShell current={current}><Content /></PageShell>
  );
}

Object.assign(window, {
  useCountUp, Reveal, Nav, SubHero, PartnersStrip, Footer, InvestorCTA, PropulsionDiagram, PropulsionSlider, ServiceSlider, PageShell, mountPage,
});
