// site/shared.jsx — components used by both directions.
// Globals it exports onto window: Topbar, Footer, MotionLogo, CalendlyButton,
// EmailCapture, Reveal, useScrollProgress.

const { useState, useEffect, useRef, useMemo } = React;

// ── useIsMobile — true when viewport is at/under the breakpoint (default 768).
function useIsMobile(bp = 820) {
  const [m, setM] = useState(
    typeof window !== "undefined" ? window.innerWidth <= bp : false
  );
  useEffect(() => {
    const onR = () => setM(window.innerWidth <= bp);
    onR();
    window.addEventListener("resize", onR);
    return () => window.removeEventListener("resize", onR);
  }, [bp]);
  return m;
}

// ── useScrollProgress — returns 0..1 along window scroll (or a specific element)
function useScrollProgress(ref = null) {
  const [p, setP] = useState(0);
  useEffect(() => {
    const onScroll = () => {
      if (ref && ref.current) {
        const r = ref.current.getBoundingClientRect();
        const vh = window.innerHeight;
        // 0 when bottom of element enters viewport, 1 when top leaves
        const total = r.height + vh;
        const passed = vh - r.top;
        setP(Math.max(0, Math.min(1, passed / total)));
      } else {
        const total = document.documentElement.scrollHeight - window.innerHeight;
        setP(total > 0 ? Math.max(0, Math.min(1, window.scrollY / total)) : 0);
      }
    };
    onScroll();
    window.addEventListener("scroll", onScroll, { passive: true });
    window.addEventListener("resize", onScroll);
    return () => {
      window.removeEventListener("scroll", onScroll);
      window.removeEventListener("resize", onScroll);
    };
  }, [ref]);
  return p;
}

// ── Reveal — fades + slides children in once they enter the viewport.
// Drives opacity/translate directly via Web Animations API so it's robust
// across browsers and sandboxed iframes where CSS transitions occasionally
// stall (e.g. some headless capture environments).
function Reveal({ children, delay = 0, y = 24, once = true, style = {}, className = "" }) {
  const ref = useRef(null);
  const animatedRef = useRef(false);
  useEffect(() => {
    if (!ref.current) return;
    const el = ref.current;
    let raf = 0;
    let stopAt = performance.now() + 30_000;
    let done = false;

    const play = () => {
      if (animatedRef.current) return;
      animatedRef.current = true;
      try {
        el.animate(
          [
            { opacity: 0, transform: `translateY(${y}px)` },
            { opacity: 1, transform: "translateY(0)" },
          ],
          {
            duration: 900,
            delay,
            easing: "cubic-bezier(0.22,0.61,0.36,1)",
            fill: "forwards",
          }
        );
      } catch (_) {
        // Fallback: set styles directly
        el.style.opacity = "1";
        el.style.transform = "translateY(0)";
      }
    };

    const check = () => {
      if (!el.isConnected) return true;
      const r = el.getBoundingClientRect();
      const vh = window.innerHeight || document.documentElement.clientHeight;
      const visible = r.top < vh * 0.92 && r.bottom > vh * 0.08;
      if (visible) {
        play();
        return true;
      }
      return false;
    };

    const tick = () => {
      if (done) return;
      if (check() && once) { done = true; return; }
      if (performance.now() > stopAt) { done = true; return; }
      raf = requestAnimationFrame(tick);
    };

    raf = requestAnimationFrame(tick);

    let io;
    if ("IntersectionObserver" in window) {
      io = new IntersectionObserver((entries) => {
        entries.forEach((e) => {
          if (e.isIntersecting) {
            play();
            if (once && io) io.disconnect();
            done = true;
          }
        });
      }, { threshold: 0.15 });
      io.observe(el);
    }
    const onScroll = () => check();
    window.addEventListener("scroll", onScroll, { passive: true });
    window.addEventListener("resize", onScroll);

    return () => {
      done = true;
      if (raf) cancelAnimationFrame(raf);
      if (io) io.disconnect();
      window.removeEventListener("scroll", onScroll);
      window.removeEventListener("resize", onScroll);
    };
  }, [once, delay, y]);
  return (
    <div
      ref={ref}
      className={className}
      style={{
        opacity: 0,
        transform: `translateY(${y}px)`,
        willChange: "opacity, transform",
        ...style,
      }}
    >
      {children}
    </div>
  );
}

// ── MotionLogo — transparent PNG, blended cleanly. For "scroll" mode applies a
// gentle scroll-tied rotation as a signature gesture.
function MotionLogo({ size = 64, dark = false, mode = "loop", style = {} }) {
  const progress = useScrollProgress();
  const rot = mode === "scroll" ? progress * 540 : 0;
  const src = dark ? window.metisAsset('logoBone') : window.metisAsset('logoIndigo');
  return (
    <div style={{
      width: size,
      height: size,
      position: "relative",
      transform: mode === "scroll" ? `rotate(${rot.toFixed(2)}deg)` : "none",
      transition: mode === "scroll" ? "transform 80ms linear" : "transform 600ms var(--ease-out)",
      ...style,
    }}>
      <img
        src={src}
        alt=""
        draggable="false"
        style={{
          width: "100%",
          height: "100%",
          objectFit: "contain",
          display: "block",
          userSelect: "none",
          pointerEvents: "none",
        }}
      />
    </div>
  );
}

// ── CalendlyButton — opens the Calendly popup widget when the official
// embed script is loaded (window.Calendly), with a graceful fallback to
// opening Calendly in a new tab. Pages load the widget assets in <head>.
function CalendlyButton({ children = "Schedule a consultation", variant = "primary", to, className = "", style = {} }) {
  const url = to || window.METIS.LINKS.calendly;
  const onClick = (e) => {
    if (window.Calendly && typeof window.Calendly.initPopupWidget === "function") {
      e.preventDefault();
      window.Calendly.initPopupWidget({ url });
    }
    // else: let the anchor open the link normally
  };
  return (
    <a
      href={url}
      target="_blank"
      rel="noopener"
      onClick={onClick}
      className={`m-btn m-btn--${variant} ${className}`}
      style={style}
      onMouseEnter={(e) => e.currentTarget.setAttribute("data-hover", "true")}
      onMouseLeave={(e) => e.currentTarget.removeAttribute("data-hover")}
    >
      <span>{children}</span>
      <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" style={{ marginLeft: 10 }}>
        <line x1="5" y1="12" x2="19" y2="12" />
        <polyline points="13 6 19 12 13 18" />
      </svg>
    </a>
  );
}

// ── EmailCapture — non-functional form (the user's backend handles it).
// On submit, we shape it as if the visitor will receive a Google Form link.
function EmailCapture({ tone = "light", compact = false }) {
  const [email, setEmail] = useState("");
  const [sent, setSent] = useState(false);
  const onSubmit = (e) => {
    e.preventDefault();
    if (!email.match(/.+@.+\..+/)) return;
    setSent(true);
  };
  const isDark = tone === "dark";
  const placeholder = "your@work-email.com";
  if (sent) {
    return (
      <div style={{
        padding: compact ? "12px 16px" : "20px 24px",
        borderRadius: 10,
        background: isDark ? "rgba(246,244,242,0.06)" : "rgba(28,30,63,0.04)",
        border: `1px solid ${isDark ? "rgba(246,244,242,0.16)" : "rgba(28,30,63,0.10)"}`,
        color: isDark ? "var(--bone-200)" : "var(--metis-deep-indigo)",
        fontSize: 14,
        lineHeight: 1.55,
        fontWeight: 300,
      }}>
        <div style={{ fontWeight: 500, fontSize: 13, letterSpacing: "0.04em", textTransform: "uppercase", marginBottom: 6, color: isDark ? "var(--plum-300)" : "var(--metis-charred-plum)" }}>Received</div>
        We've sent a short intake form to <strong style={{ fontWeight: 500 }}>{email}</strong>. After you complete it, we'll schedule a 30-minute discovery call — your guide arrives once we know what to tailor it for.
      </div>
    );
  }
  return (
    <form
      onSubmit={onSubmit}
      style={{
        display: "flex",
        alignItems: "stretch",
        gap: 0,
        background: isDark ? "rgba(246,244,242,0.05)" : "var(--bone-100)",
        border: `1px solid ${isDark ? "rgba(246,244,242,0.16)" : "rgba(28,30,63,0.10)"}`,
        borderRadius: 10,
        overflow: "hidden",
        maxWidth: 520,
      }}
    >
      <input
        type="email"
        required
        value={email}
        onChange={(e) => setEmail(e.target.value)}
        placeholder={placeholder}
        style={{
          flex: 1,
          padding: compact ? "12px 16px" : "16px 20px",
          fontSize: compact ? 14 : 15,
          fontWeight: 300,
          fontFamily: "var(--font-sans)",
          color: isDark ? "var(--bone-200)" : "var(--metis-deep-indigo)",
          background: "transparent",
          border: 0,
          outline: "none",
          letterSpacing: "0.005em",
        }}
      />
      <button
        type="submit"
        style={{
          padding: compact ? "0 18px" : "0 22px",
          fontFamily: "var(--font-sans)",
          fontSize: compact ? 13 : 14,
          fontWeight: 500,
          letterSpacing: "0.02em",
          color: isDark ? "var(--metis-deep-indigo)" : "var(--bone-200)",
          background: isDark ? "var(--bone-200)" : "var(--metis-charred-plum)",
          border: 0,
          cursor: "pointer",
          whiteSpace: "nowrap",
          transition: "background 160ms var(--ease-out)",
        }}
      >
        Request the guide
      </button>
    </form>
  );
}

// ── Topbar — shared header
function Topbar({ dark = false }) {
  const [scrolled, setScrolled] = useState(false);
  const [menuOpen, setMenuOpen] = useState(false);
  const isMobile = useIsMobile();
  useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 12);
    onScroll();
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, []);
  // Close the drawer when leaving mobile
  useEffect(() => { if (!isMobile) setMenuOpen(false); }, [isMobile]);

  const fg = dark ? "var(--bone-200)" : "var(--metis-deep-indigo)";
  const drawerOpaque = dark ? "rgba(14,15,34,0.97)" : "rgba(246,244,242,0.98)";
  const bg = dark
    ? `rgba(14, 15, 34, ${scrolled || menuOpen ? 0.78 : 0})`
    : `rgba(246, 244, 242, ${scrolled || menuOpen ? 0.85 : 0})`;
  const border = scrolled
    ? (dark ? "rgba(246,244,242,0.08)" : "rgba(28,30,63,0.08)")
    : "transparent";

  return (
    <header
      style={{
        position: "fixed",
        top: 0, left: 0, right: 0,
        height: 72,
        display: "flex",
        alignItems: "center",
        padding: isMobile ? "0 20px" : "0 48px",
        background: bg,
        backdropFilter: (scrolled || menuOpen) ? "blur(14px) saturate(160%)" : "none",
        WebkitBackdropFilter: (scrolled || menuOpen) ? "blur(14px) saturate(160%)" : "none",
        borderBottom: `1px solid ${border}`,
        zIndex: 100,
        transition: "background 280ms var(--ease-out), border-color 280ms var(--ease-out)",
      }}
    >
      <a href="index.html" style={{ display: "flex", alignItems: "center", gap: 12, textDecoration: "none", border: 0, color: fg, flex: isMobile ? 1 : "0 0 auto" }}>
        <MotionLogo size={36} dark={dark} mode="loop" />
        <span style={{ fontFamily: "var(--font-sans)", fontWeight: 600, fontSize: isMobile ? 15 : 16, letterSpacing: "-0.005em" }}>Metis Advisory Group</span>
      </a>

      {!isMobile && <DesktopNav dark={dark} />}

      {!isMobile && (
        <CalendlyButton variant={dark ? "ghostDark" : "primary"} style={{ marginLeft: 18 }}>Schedule</CalendlyButton>
      )}

      {isMobile && (
        <button
          aria-label={menuOpen ? "Close menu" : "Open menu"}
          aria-expanded={menuOpen}
          onClick={() => setMenuOpen((v) => !v)}
          style={{
            appearance: "none", background: "transparent", border: 0, cursor: "pointer",
            width: 44, height: 44, marginRight: -10, display: "flex", flexDirection: "column",
            alignItems: "center", justifyContent: "center", gap: 5, color: fg,
          }}
        >
          <span style={{ width: 22, height: 1.5, background: "currentColor", borderRadius: 2, transition: "transform 240ms var(--ease-out), opacity 240ms", transform: menuOpen ? "translateY(6.5px) rotate(45deg)" : "none" }} />
          <span style={{ width: 22, height: 1.5, background: "currentColor", borderRadius: 2, transition: "opacity 200ms", opacity: menuOpen ? 0 : 1 }} />
          <span style={{ width: 22, height: 1.5, background: "currentColor", borderRadius: 2, transition: "transform 240ms var(--ease-out)", transform: menuOpen ? "translateY(-6.5px) rotate(-45deg)" : "none" }} />
        </button>
      )}

      {isMobile && (
        <div style={{
          position: "fixed", top: 72, left: 0, right: 0,
          background: drawerOpaque,
          backdropFilter: "blur(14px) saturate(160%)",
          WebkitBackdropFilter: "blur(14px) saturate(160%)",
          borderBottom: `1px solid ${dark ? "rgba(246,244,242,0.10)" : "rgba(28,30,63,0.10)"}`,
          padding: menuOpen ? "20px 20px 28px" : "0 20px",
          maxHeight: menuOpen ? 420 : 0,
          opacity: menuOpen ? 1 : 0,
          overflow: "hidden",
          pointerEvents: menuOpen ? "auto" : "none",
          transition: "max-height 360ms var(--ease-out), opacity 240ms var(--ease-out), padding 360ms var(--ease-out)",
          display: "flex", flexDirection: "column", gap: 4,
        }}>
          {window.METIS.NAV.map((n) => (
            <a key={n.label} href={n.href} onClick={() => setMenuOpen(false)} style={{
              fontSize: 18, fontWeight: 400, letterSpacing: "-0.005em",
              color: n.subdued ? (dark ? "var(--slate-400)" : "var(--slate-500)") : fg,
              opacity: n.subdued ? 0.7 : 1, textDecoration: "none", border: 0,
              padding: "12px 0", borderBottom: `1px solid ${dark ? "rgba(246,244,242,0.08)" : "rgba(28,30,63,0.07)"}`,
            }}>{n.label}{n.subdued && <sup style={{ fontSize: 10, marginLeft: 3, opacity: 0.7 }}>soon</sup>}</a>
          ))}
          <CalendlyButton variant={dark ? "ghostDark" : "primary"} style={{ marginTop: 16, justifyContent: "center" }}>Schedule a consultation</CalendlyButton>
        </div>
      )}
    </header>
  );
}

function DesktopNav({ dark }) {
  const fg = dark ? "var(--bone-200)" : "var(--metis-deep-indigo)";
  return (
    <nav style={{ display: "flex", gap: 28, marginLeft: 48, flex: 1, justifyContent: "flex-end", paddingRight: 8 }}>
      {window.METIS.NAV.map((n) => (
        <a key={n.label} href={n.href} style={{
          fontSize: 13,
          fontWeight: 400,
          letterSpacing: "0.005em",
          color: n.subdued ? (dark ? "var(--slate-400)" : "var(--slate-500)") : fg,
          opacity: n.subdued ? 0.7 : 1,
          textDecoration: "none",
          border: 0,
        }}>{n.label}{n.subdued && <sup style={{ fontSize: 9, marginLeft: 3, opacity: 0.7 }}>soon</sup>}</a>
      ))}
    </nav>
  );
}

// (direction switch removed — only the Stillness home renders now)

// ── Footer
function Footer({ dark = false }) {
  const fg = dark ? "var(--bone-200)" : "var(--metis-deep-indigo)";
  const fg2 = dark ? "var(--slate-300)" : "var(--slate-600)";
  const isMobile = useIsMobile();
  return (
    <footer style={{
      background: dark ? "var(--indigo-950)" : "var(--metis-deep-indigo)",
      color: "var(--bone-200)",
      padding: isMobile ? "64px 24px 32px" : "96px 48px 36px",
      marginTop: 0,
      position: "relative",
      overflow: "hidden",
    }}>
      {/* watermark mark */}
      <img src={window.metisAsset('logoBone')} alt="" style={{
        position: "absolute", right: -80, bottom: -80, height: isMobile ? 280 : 420, opacity: 0.06, pointerEvents: "none",
      }} />

      <div style={{ display: "grid", gridTemplateColumns: isMobile ? "1fr 1fr" : "2fr 1fr 1fr 1fr", gap: isMobile ? 36 : 48, alignItems: "start", position: "relative" }}>
        <div style={{ gridColumn: isMobile ? "1 / -1" : "auto" }}>
          <div style={{ fontFamily: "var(--font-display)", fontStyle: "italic", fontSize: isMobile ? 24 : 28, lineHeight: 1.25, fontWeight: 400, maxWidth: 360, color: "var(--bone-200)" }}>
            Wisdom at Work.<br/>Guided by Insight.<br/>Grounded in Humanity.
          </div>
          <div style={{ marginTop: 32, fontSize: 12, letterSpacing: "0.08em", textTransform: "uppercase", color: "var(--slate-400)" }}>
            Metis Advisory Group · {window.METIS.LINKS.domain}
          </div>
        </div>

        <FooterCol title="Site" links={[
          { label: "Approach", href: "approach.html" },
          { label: "Services", href: "services.html" },
          { label: "Writing — soon", href: "#" },
          { label: "Contact", href: "contact.html" },
        ]} />

        <FooterCol title="Services" links={[
          { label: "Executive coaching", href: "services.html#coaching" },
          { label: "Organizational consulting", href: "services.html#consulting" },
          { label: "AI workflow integration", href: "services.html#ai" },
          { label: "Workshops & keynotes", href: "services.html#workshops" },
        ]} />

        <FooterCol title="Begin" links={[
          { label: "Schedule a consultation", href: window.METIS.LINKS.calendly, external: true },
          { label: "Request the AI guide", href: "#ai-guide" },
          { label: window.METIS.LINKS.email, href: `mailto:${window.METIS.LINKS.email}` },
        ]} />
      </div>

      <div style={{ marginTop: isMobile ? 56 : 80, paddingTop: 24, borderTop: "1px solid rgba(246,244,242,0.10)", display: "flex", flexDirection: isMobile ? "column" : "row", gap: isMobile ? 12 : 0, justifyContent: "space-between", alignItems: isMobile ? "flex-start" : "center", fontSize: 11, color: "var(--slate-400)", letterSpacing: "0.04em" }}>
        <span>© {new Date().getFullYear()} Metis Advisory Group, LLC</span>
        <span style={{ fontStyle: "italic", fontFamily: "var(--font-display)" }}>Recognise · Discern · Recalibrate</span>
      </div>
    </footer>
  );
}

function FooterCol({ title, links }) {
  return (
    <div>
      <div style={{ fontSize: 10, letterSpacing: "0.18em", textTransform: "uppercase", fontWeight: 500, color: "var(--plum-300)", marginBottom: 16 }}>{title}</div>
      <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
        {links.map(l => (
          <a key={l.label} href={l.href} target={l.external ? "_blank" : undefined} rel={l.external ? "noopener" : undefined}
             style={{ fontSize: 14, fontWeight: 300, color: "var(--bone-200)", border: 0, textDecoration: "none", lineHeight: 1.4 }}>
            {l.label}
          </a>
        ))}
      </div>
    </div>
  );
}

// Eyebrow component
function Eyebrow({ children, dark = false }) {
  return (
    <div style={{
      fontSize: 11, fontWeight: 500, letterSpacing: "0.18em", textTransform: "uppercase",
      color: dark ? "var(--plum-300)" : "var(--metis-charred-plum)",
    }}>{children}</div>
  );
}

// ── publish
Object.assign(window, {
  Topbar, Footer, MotionLogo, CalendlyButton, EmailCapture, Reveal, Eyebrow, useScrollProgress, useIsMobile,
});
