// The Trading Vault, Mentorship: sticky nav + cinematic hero

function Nav() {
  const { Button } = TTV;
  const [scrolled, setScrolled] = React.useState(false);
  React.useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 12);
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, []);
  const links = [
    ["De Methode", "#method"],
    ["Fases", "#phases"],
    ["Resultaten", "#proof"],
    ["Over Wesley", "#founder"],
    ["FAQ", "#faq"],
  ];
  return (
    <header
      style={{
        position: "sticky",
        top: 0,
        zIndex: 50,
        display: "flex",
        alignItems: "center",
        justifyContent: "space-between",
        gap: 24,
        padding: "15px clamp(20px, 6vw, 64px)",
        background: scrolled ? "rgba(8,8,10,.78)" : "rgba(8,8,10,.30)",
        backdropFilter: "blur(14px)",
        WebkitBackdropFilter: "blur(14px)",
        borderBottom: `1px solid ${scrolled ? "var(--vault-line-soft)" : "transparent"}`,
        transition: "background .3s, border-color .3s",
      }}
    >
      <a href="#top" style={{ display: "flex", alignItems: "center" }}>
        <img src="assets/tv-wordmark-white.png" alt="The Trading Vault" style={{ height: 32, display: "block" }} />
      </a>
      <nav style={{ display: "flex", gap: 30 }} className="ttv-navlinks">
        {links.map(([l, href]) => (
          <a
            key={l}
            href={href}
            style={{
              fontFamily: "var(--font-sans)",
              fontWeight: 600,
              fontSize: 11.5,
              letterSpacing: "0.16em",
              textTransform: "uppercase",
              color: "var(--vault-ink-3)",
              textDecoration: "none",
              transition: "color .18s",
            }}
            onMouseEnter={(e) => (e.currentTarget.style.color = "var(--vault-ink)")}
            onMouseLeave={(e) => (e.currentTarget.style.color = "var(--vault-ink-3)")}
          >
            {l}
          </a>
        ))}
      </nav>
      <a href="#who" style={{ textDecoration: "none" }}>
        <Button variant="primary" size="sm">Meld Je Aan</Button>
      </a>
    </header>
  );
}

/* Attempts video.play(); if the browser rejects it (autoplay policy), retries
   on the first user interaction anywhere on the page, and keeps retrying on an
   interval as a last resort so playback is never left permanently stalled. */
function persistentPlay(video) {
  if (!video) return;
  const tryPlay = () => video.play().catch(() => {});
  tryPlay();
  const onInteract = () => { tryPlay(); };
  ["pointerdown", "touchstart", "keydown", "scroll"].forEach((evt) =>
    window.addEventListener(evt, onInteract, { once: true, passive: true })
  );
  const interval = setInterval(() => {
    if (video.paused) tryPlay();
    else clearInterval(interval);
  }, 800);
  // Stop retrying once truly playing.
  video.addEventListener("playing", () => clearInterval(interval), { once: true });
}

/* Seamless crossfade-looping background video: two synced <video> instances,
   swap opacity ~1s before the natural end so the loop restart is never visible.
   A real still-frame poster shows instantly; the video fades in once playable. */
function CrossfadeVideo({ src, poster, className, style }) {
  const reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
  const vidARef = React.useRef(null);
  const vidBRef = React.useRef(null);
  const [activeA, setActiveA] = React.useState(true);
  const [ready, setReady] = React.useState(false);
  const [videoIn, setVideoIn] = React.useState(false);
  const CROSSFADE_S = 1;
  const activeARef = React.useRef(true);
  React.useEffect(() => { activeARef.current = activeA; }, [activeA]);

  React.useEffect(() => {
    if (reduce) return;
    const a = vidARef.current, b = vidBRef.current;
    if (!a || !b) return;
    let switching = false;
    let raf;

    const keepAlive = (v) => { if (v.paused) persistentPlay(v); };

    const tick = () => {
      const front = activeARef.current ? a : b;
      const back = activeARef.current ? b : a;
      // Defensively keep the front video playing — never let it stall/pause on its own.
      keepAlive(front);
      if (front.duration && !switching && front.currentTime >= front.duration - CROSSFADE_S) {
        switching = true;
        back.currentTime = 0;
        persistentPlay(back);
        setActiveA((prev) => !prev);
        setTimeout(() => {
          front.currentTime = 0;
          switching = false;
        }, CROSSFADE_S * 1000 + 50);
      }
      raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [reduce]);

  React.useEffect(() => {
    if (reduce) return;
    const a = vidARef.current, b = vidBRef.current;
    if (!a || !b) return;
    // Front video only needs to be playable (metadata + first segment) to start,
    // not fully preloaded — avoids downloading the whole file before render.
    let frontReady = false;
    const onFrontReady = () => {
      if (frontReady) return;
      frontReady = true;
      setReady(true);
      persistentPlay(a);
      requestAnimationFrame(() => requestAnimationFrame(() => setVideoIn(true)));
      // Only start loading the second instance once the first is already playing.
      b.preload = "auto";
      b.load();
    };
    a.addEventListener("canplay", onFrontReady, { once: true });
    a.load();
    return () => { a.removeEventListener("canplay", onFrontReady); };
  }, [reduce]);

  if (reduce) {
    return (
      <div
        aria-hidden="true"
        className={className}
        style={{ ...style, background: `center / cover no-repeat url(${poster})` }}
      />
    );
  }

  return (
    <div aria-hidden="true" className={className} style={{ ...style, background: `#000 center / cover no-repeat url(${poster})` }}>
      <video
        ref={vidARef}
        muted
        playsInline
        preload="metadata"
        style={{ position: "absolute", inset: 0, width: "100%", height: "100%", objectFit: "cover", opacity: videoIn ? (activeA ? 1 : 0) : 0, transition: activeA ? `opacity 400ms ease-out, opacity ${CROSSFADE_S}s linear` : `opacity ${CROSSFADE_S}s linear` }}
      >
        <source src={src} type="video/mp4" />
      </video>
      <video
        ref={vidBRef}
        muted
        playsInline
        preload="none"
        style={{ position: "absolute", inset: 0, width: "100%", height: "100%", objectFit: "cover", opacity: videoIn ? (activeA ? 0 : 1) : 0, transition: !activeA ? `opacity 400ms ease-out, opacity ${CROSSFADE_S}s linear` : `opacity ${CROSSFADE_S}s linear` }}
      >
        <source src={src} type="video/mp4" />
      </video>
    </div>
  );
}

/* Mobile hero background: single video layer behind all content, poster visible
   until the video is actually playing, then it fades in. No visual card, no
   second image — matches the desktop background's role, just simpler. */
function MobileHeroBgVideo({ src, poster, className }) {
  const reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
  const ref = React.useRef(null);
  const [videoIn, setVideoIn] = React.useState(false);

  React.useEffect(() => {
    if (reduce) return;
    const v = ref.current;
    if (!v) return;
    const onPlaying = () => setVideoIn(true);
    v.addEventListener("playing", onPlaying);
    persistentPlay(v);
    return () => { v.removeEventListener("playing", onPlaying); };
  }, [reduce]);

  return (
    <div
      aria-hidden="true"
      className={className}
      style={{ position: "absolute", inset: 0, width: "100%", height: "100%", zIndex: 0, pointerEvents: "none", background: `#000 center / cover no-repeat url(${poster})` }}
    >
      {!reduce && (
        <video
          ref={ref}
          muted
          autoPlay
          loop
          playsInline
          preload="auto"
          poster={poster}
          onLoadedMetadata={(e) => persistentPlay(e.currentTarget)}
          style={{ position: "absolute", inset: 0, width: "100%", height: "100%", objectFit: "cover", opacity: videoIn ? 1 : 0, transition: "opacity 400ms ease-out" }}
        >
          <source src={src} type="video/mp4" />
        </video>
      )}
    </div>
  );
}

function Hero() {
  const { Button, Badge, Eyebrow } = TTV;
  return (
    <section
      id="top"
      className="tv-beam"
      data-screen-label="Hero"
      style={{
        position: "relative",
        minHeight: "92vh",
        display: "flex",
        alignItems: "center",
        padding: "clamp(80px,12vh,140px) var(--section-pad-x) clamp(64px,9vh,110px)",
        background:
          "radial-gradient(130% 80% at 50% -15%, rgba(255,255,255,.07), transparent 54%), var(--vault-void)",
        overflow: "hidden",
      }}
    >
      {/* full-bleed cinematic video background, seamless crossfade loop (desktop),
          plain mobile background video with poster-then-video fade shown below */}
      <CrossfadeVideo
        src="uploads/SteezyWes_A_dramatic_dark_cinematic_YouTube_thumbnail_backgro_667e5075-8da3-439d-906a-f81dca8aca42_2.mp4"
        poster="uploads/hero-bg-poster.jpg"
        className="ttv-hero-bg-desktop"
        style={{ position: "absolute", inset: 0, width: "100%", height: "100%", zIndex: 0, pointerEvents: "none" }}
      />
      <MobileHeroBgVideo
        src="uploads/SteezyWes_A_dramatic_dark_cinematic_YouTube_thumbnail_backgro_667e5075-8da3-439d-906a-f81dca8aca42_2.mp4"
        poster="uploads/hero-bg-poster.jpg"
        className="ttv-hero-bg-mobile"
      />
      {/* legibility scrim, darken left/bottom where copy sits */}
      <div
        aria-hidden="true"
        style={{
          position: "absolute",
          inset: 0,
          zIndex: 0,
          background:
            "linear-gradient(90deg, rgba(8,8,10,.92) 0%, rgba(8,8,10,.72) 38%, rgba(8,8,10,.32) 70%, rgba(8,8,10,.45) 100%)," +
            "linear-gradient(0deg, rgba(8,8,10,.85) 0%, transparent 45%)",
          pointerEvents: "none",
        }}
      />

      {/* floating dust in the beam */}
      <Dust />

      {/* faint ghost market structure low in the frame */}
      <div
        aria-hidden="true"
        style={{
          position: "absolute",
          left: 0,
          right: 0,
          bottom: 0,
          height: "38%",
          display: "flex",
          alignItems: "flex-end",
          justifyContent: "center",
          gap: 9,
          opacity: 0.12,
          pointerEvents: "none",
          maskImage: "linear-gradient(to top, #000, transparent)",
          WebkitMaskImage: "linear-gradient(to top, #000, transparent)",
        }}
      >
        {[30, 52, 44, 70, 48, 82, 60, 95, 72, 58, 88, 66, 40, 76, 54, 84].map((h, i) => (
          <div key={i} style={{ width: 9, height: h + "%", background: "var(--vault-ink-4)", borderRadius: 1 }} />
        ))}
      </div>

      <div
        style={{
          position: "relative",
          zIndex: 3,
          maxWidth: 1200,
          margin: "0 auto",
          width: "100%",
          display: "grid",
          gridTemplateColumns: "minmax(0,1.15fr) minmax(0,0.85fr)",
          gap: "clamp(40px,6vw,88px)",
          alignItems: "center",
        }}
        className="ttv-hero-grid"
      >
        {/* Left, copy */}
        <div style={{ display: "flex", flexDirection: "column", alignItems: "flex-start", gap: 28 }}>
          <Reveal>
            <Eyebrow>Mentorship Op Basis Van Aanmelding</Eyebrow>
          </Reveal>
          <Reveal delay={70}>
            <h1
              style={{
                margin: 0,
                fontFamily: "var(--font-display)",
                fontWeight: 800,
                fontSize: "clamp(42px, 6.4vw, 84px)",
                lineHeight: 0.98,
                letterSpacing: "-0.035em",
                color: "var(--vault-ink)",
                textWrap: "balance",
              }}
            >
              Van Chaos<br />Naar Structuur.
            </h1>
          </Reveal>
          <Reveal delay={140}>
            <p
              style={{
                margin: 0,
                maxWidth: 480,
                fontFamily: "var(--font-sans)",
                fontSize: "clamp(16px,1.4vw,18px)",
                lineHeight: 1.65,
                color: "var(--vault-ink-2)",
                textWrap: "pretty",
              }}
            >
              Een persoonlijke 1-op-1 price-action mentorship voor traders die klaar zijn met het volgen van signalen.
              Bouw de vaardigheden om zelf charts te lezen, beslissingen te nemen en consequent volgens één duidelijke aanpak te traden.
            </p>
          </Reveal>
          <Reveal delay={210}>
            <div style={{ display: "flex", gap: 14, flexWrap: "wrap", alignItems: "center" }}>
              <a href={APPLY_URL} onClick={(e) => { e.preventDefault(); window.__ttvOpenVSL(e.currentTarget); }} style={{ textDecoration: "none" }}>
                <Button variant="primary" size="lg">Meld Je Aan Voor The Vault</Button>
              </a>
              <a href="#method" style={{ textDecoration: "none" }}>
                <Button size="lg">Bekijk De Methode</Button>
              </a>
            </div>
          </Reveal>
          <Reveal delay={245} style={{ width: "100%" }}>
            <div
              className="ttv-mobile-wesley-video"
              style={{
                display: "none",
                position: "relative",
                width: "100%",
                aspectRatio: "4 / 5",
                borderRadius: "var(--radius-xs)",
                overflow: "hidden",
                border: "1px solid var(--vault-line)",
              }}
            >
              <video
                aria-hidden="true"
                autoPlay
                muted
                loop
                playsInline
                poster="uploads/wesley-mobile-poster.jpg"
                ref={(el) => { if (el) persistentPlay(el); }}
                style={{ position: "absolute", inset: 0, width: "100%", height: "100%", objectFit: "cover", objectPosition: "50% 20%" }}
              >
                <source src="uploads/SteezyWes_httpss.mj.runk0hEtLaY79Q_Animate_this_image_with_ve_27bc7cbe-be35-4e6e-95a2-701baf8b152e_0.mp4" type="video/mp4" />
              </video>
            </div>
          </Reveal>
          <Reveal delay={280}>
            <div style={{ display: "flex", gap: 9, flexWrap: "wrap" }}>
              <Badge>Pure Prijsactie</Badge>
              <Badge>Privé 1-Op-1</Badge>
              <Badge>Alleen Op Aanmelding</Badge>
              <Badge tone="strong">Procesgericht</Badge>
            </div>
          </Reveal>
        </div>

        {/* Right, hero portrait video (in the media slot frame) */}
        <Reveal delay={160} style={{ width: "100%" }}>
          <div
            style={{
              position: "relative",
              width: "100%",
              aspectRatio: "3 / 4",
              borderRadius: "var(--radius-md)",
              overflow: "hidden",
              border: "1px solid var(--vault-line)",
              boxShadow: "var(--shadow-md), inset 0 1px 0 rgba(255,255,255,.045)",
            }}
          >
            <video
              aria-hidden="true"
              autoPlay
              muted
              loop
              playsInline
              ref={(el) => { if (el) persistentPlay(el); }}
              style={{ position: "absolute", inset: 0, width: "100%", height: "100%", objectFit: "cover" }}
            >
              <source src="uploads/SteezyWes_httpss.mj.runk0hEtLaY79Q_Animate_this_image_with_ve_27bc7cbe-be35-4e6e-95a2-701baf8b152e_0.mp4" type="video/mp4" />
            </video>
          </div>
        </Reveal>
      </div>
    </section>
  );
}

/* Floating dust particles inside the beam, quiet, slow */
function Dust() {
  const dots = React.useMemo(
    () =>
      Array.from({ length: 26 }, () => ({
        left: 36 + Math.random() * 28,
        top: Math.random() * 88,
        size: Math.random() * 2 + 0.6,
        dur: 9 + Math.random() * 12,
        delay: -Math.random() * 16,
        op: Math.random() * 0.4 + 0.08,
      })),
    []
  );
  return (
    <div aria-hidden="true" style={{ position: "absolute", inset: 0, pointerEvents: "none", zIndex: 1, overflow: "hidden" }}>
      {dots.map((d, i) => (
        <span
          key={i}
          style={{
            position: "absolute",
            left: d.left + "%",
            top: d.top + "%",
            width: d.size,
            height: d.size,
            borderRadius: "50%",
            background: "#fff",
            opacity: d.op,
            filter: "blur(.3px)",
            animation: `ttvDrift ${d.dur}s linear ${d.delay}s infinite`,
          }}
        />
      ))}
    </div>
  );
}

Object.assign(window, { Nav, Hero, persistentPlay });
