// StoryCarousel.jsx — Split 3D carousel: Story · Wiggins · Why Now
// Ported from the CodePen split-3D pattern; jQuery replaced with vanilla JS.
// Images: drop your photos into  assets/carousel/  as story.jpg, wiggins.jpg, field.jpg

function CarouselStyles() {
  return (
    <style>{`
      /* ── Scroll-jail wrapper ──────────────────────────── */
      .lc-scroll-track {
        /* tall enough to give 40vh of scroll per slide */
        position: relative;
      }
      /* ── Wrap ─────────────────────────────────────────── */
      .lc-section {
        position: sticky;
        top: 0;
        height: 100vh;
        min-height: 600px;
        overflow: hidden;
        perspective: 50vw;
        perspective-origin: 50% 50%;
        background: #0d1921;
      }
      .lc-stage {
        position: absolute;
        inset: 0;
        transform-style: preserve-3d;
        transform: translateZ(-50vh);
      }
      .lc-no-transition * { transition: none !important; }

      /* ── Spinners ─────────────────────────────────────── */
      .lc-spinner {
        position: absolute;
        width: 50%; height: 100%;
        top: 0; left: 0; bottom: 0;
        transform-style: preserve-3d;
        transition: transform 1s ease;
        backface-visibility: hidden;
        transform-origin: 50% 50%;
        transform: rotateX(0);
      }
      .lc-spinner--right { right: 0; left: auto; }

      .js-spin-fwd  .lc-spinner           { transform: rotateX(-90deg); }
      .js-spin-bwd  .lc-spinner           { transform: rotateX(90deg);  }
      .js-spin-fwd  .lc-spinner--right    { transform: rotateX(90deg);  }
      .js-spin-bwd  .lc-spinner--right    { transform: rotateX(-90deg); }

      /* ── Faces ────────────────────────────────────────── */
      .lc-face {
        display: none;
        position: absolute;
        width: 100%; height: 100%;
        overflow: hidden;
      }
      .lc-face.js-active {
        display: block;
        transform: translateZ(50vh);
      }
      .lc-face.js-next {
        display: block;
        transform: rotateX(90deg) translateZ(50vh);
      }
      .lc-spinner--right .lc-face.js-next {
        transform: rotateX(270deg) translateZ(50vh);
      }
      .js-spin-bwd .lc-face.js-next {
        transform: rotateX(-90deg) translateZ(50vh);
      }
      .js-spin-bwd .lc-spinner--right .lc-face.js-next {
        transform: rotateX(-270deg) translateZ(50vh);
      }

      /* ── Content (200% wide — split between spinners) ─── */
      .lc-content {
        position: absolute;
        width: 200%; height: 100%;
        left: 0;
        display: flex;
      }
      .lc-spinner--right .lc-content { left: -100%; }

      /* ── Left panel: image ────────────────────────────── */
      .lc-left {
        width: 50%; height: 100%;
        flex-shrink: 0;
        position: relative;
        background-size: cover;
        background-position: center;
      }
      .lc-left__overlay {
        position: absolute; inset: 0;
        background: linear-gradient(135deg, rgba(13,25,33,0.65) 0%, rgba(13,25,33,0.15) 60%);
      }
      .lc-left__bottom {
        position: absolute;
        bottom: 48px; left: 48px; right: 48px;
        z-index: 1;
      }
      .lc-left__overline {
        font-family: var(--lin_font-family, Inter, sans-serif);
        font-size: 10px; font-weight: 600;
        letter-spacing: 0.18em; text-transform: uppercase;
        color: rgba(255,255,255,0.5);
        margin-bottom: 10px;
      }
      .lc-left__label {
        font-family: var(--lin_font-family, Inter, sans-serif);
        font-size: clamp(1.8rem, 3.5vw, 3rem);
        font-weight: 700;
        color: #fff;
        line-height: 1.1;
        letter-spacing: -0.03em;
        margin: 0;
      }
      .lc-left__sub {
        font-size: 0.75rem; color: rgba(255,255,255,0.4);
        margin-top: 8px; letter-spacing: 0.08em;
        font-family: var(--lin_font-family, Inter, sans-serif);
      }
      .lc-ghost-num {
        position: absolute;
        top: 24px; left: 32px;
        font-size: clamp(7rem, 16vw, 18rem);
        font-weight: 700;
        color: rgba(255,255,255,0.04);
        line-height: 1;
        letter-spacing: -0.05em;
        user-select: none; pointer-events: none;
        font-family: var(--lin_font-family, Inter, sans-serif);
      }

      /* ── Right panel: text ────────────────────────────── */
      .lc-right {
        width: 50%; height: 100%;
        flex-shrink: 0;
        display: flex; align-items: center; justify-content: center;
        padding: 48px;
        box-sizing: border-box;
      }
      .lc-right__inner {
        max-width: 460px;
        display: flex; flex-direction: column; gap: 18px;
      }
      .lc-right__overline {
        font-family: var(--lin_font-family, Inter, sans-serif);
        font-size: 10px; font-weight: 600;
        letter-spacing: 0.18em; text-transform: uppercase;
        color: #6399AF;
      }
      .lc-right__headline {
        font-family: var(--lin_font-family, Inter, sans-serif);
        font-size: clamp(1.6rem, 2.8vw, 2.2rem);
        font-weight: 700;
        color: #fff;
        line-height: 1.15;
        letter-spacing: -0.02em;
        margin: 0;
      }
      .lc-body-p {
        font-family: var(--lin_font-family, Inter, sans-serif);
        font-size: clamp(0.82rem, 1.1vw, 0.94rem);
        line-height: 1.78;
        color: #ffffff;
        margin: 0;
      }
      .lc-pullquote {
        border-left: 2px solid #6399AF;
        padding: 10px 0 10px 18px;
        margin-top: 2px;
      }
      .lc-pullquote__text {
        font-family: var(--lin_font-family, Inter, sans-serif);
        font-size: clamp(0.9rem, 1.2vw, 1.05rem);
        font-style: italic; font-weight: 500;
        color: #9CBECF; line-height: 1.45;
      }
      .lc-pullquote__sub {
        font-size: 0.72rem; color: rgba(255,255,255,0.3);
        margin-top: 5px; letter-spacing: 0.05em;
        font-family: var(--lin_font-family, Inter, sans-serif);
      }
      .lc-countdown-badge {
        display: inline-flex; align-items: center; gap: 6px;
        font-family: var(--lin_font-family, Inter, sans-serif);
        font-size: 0.78rem; color: #6399AF; font-weight: 500;
      }
      .lc-cta-btn {
        display: inline-block; align-self: flex-start;
        background: #6399AF; color: #fff; border: none;
        padding: 13px 28px; border-radius: 8px;
        font-family: var(--lin_font-family, Inter, sans-serif);
        font-size: 0.85rem; font-weight: 600;
        letter-spacing: 0.04em; cursor: pointer;
        transition: background 150ms ease;
        margin-top: 4px;
      }
      .lc-cta-btn:hover { background: #4A7A91; }

      /* ── Navigation ───────────────────────────────────── */
      .lc-nav {
        position: absolute;
        right: 0; top: 0; bottom: 0;
        width: 52px; z-index: 20;
        display: flex; flex-direction: column;
        align-items: center; justify-content: center;
        gap: 6px;
        background: rgba(13,25,33,0.45);
        backdrop-filter: none;
      }
      .lc-nav-btn {
        background: transparent;
        border: 1px solid rgba(255,255,255,0.12);
        border-radius: 50%;
        width: 32px; height: 32px;
        display: flex; align-items: center; justify-content: center;
        cursor: pointer; color: rgba(255,255,255,0.4);
        transition: all 150ms ease; padding: 0;
      }
      .lc-nav-btn:hover { border-color: rgba(255,255,255,0.35); color: #fff; }
      .lc-dots {
        display: flex; flex-direction: column; gap: 7px;
        margin: 6px 0;
      }
      .lc-dot {
        width: 6px; height: 6px;
        border-radius: 50%; background: rgba(255,255,255,0.18);
        border: none; cursor: pointer; padding: 0;
        transition: all 220ms ease;
      }
      .lc-dot.active { background: #6399AF; transform: scale(1.5); }

      /* ── Mobile ───────────────────────────────────────── */
      @media (max-width: 700px) {
        /* Section stays full-height; sticky scroll-track still works */
        .lc-section {
          height: 100vh;
          /* Own perspective so the single spinner rotates in 3D */
          perspective: 120vw;
          perspective-origin: 50% 50%;
          overflow: hidden;
        }
        /* Stage: no 3D transform of its own — spinner handles it */
        .lc-stage {
          position: absolute;
          inset: 0;
          transform: none !important;
          transform-style: preserve-3d;
        }
        /* Hide the duplicated right spinner */
        .lc-spinner--right { display: none; }
        /* Single spinner fills the full section, rotates on transition */
        .lc-spinner {
          width: 100% !important; height: 100%;
          position: absolute; inset: 0;
          transform-origin: 50% 50%;
          transform-style: preserve-3d;
          backface-visibility: hidden;
          transform: rotateX(0deg);
          transition: transform 0.72s cubic-bezier(0.76, 0, 0.24, 1);
          will-change: transform;
        }
        /* Suppress transition during class-reset (same trick as reference) */
        .lc-no-transition .lc-spinner { transition: none !important; }
        /* Spin forward: spinner tilts forward (top comes down) */
        .js-spin-fwd .lc-spinner  { transform: rotateX(90deg);  }
        /* Spin backward: spinner tilts backward (bottom comes up) */
        .js-spin-bwd .lc-spinner  { transform: rotateX(-90deg); }

        /* Faces positioned in 3D space on the spinner cube */
        .lc-face {
          display: none;
          position: absolute !important;
          inset: 0 !important;
          width: 100% !important; height: 100% !important;
          overflow: hidden;
          pointer-events: none;
        }
        .lc-face.js-active {
          display: block !important;
          pointer-events: auto;
          /* Sits on the front face of the cube */
          transform: translateZ(50vh) !important;
        }
        .lc-face.js-next {
          display: block !important;
          /* Top face of the cube — enters from above on forward spin */
          transform: rotateX(-90deg) translateZ(50vh) !important;
        }
        .js-spin-bwd .lc-face.js-next {
          /* Bottom face — enters from below on backward spin */
          transform: rotateX(90deg) translateZ(50vh) !important;
        }

        /* Content fills the face; image is the background */
        .lc-content {
          position: absolute; inset: 0;
          width: 100% !important; height: 100%;
          left: 0 !important;
          flex-direction: row;
        }
        /* Left panel: full-bleed background image, no text */
        .lc-left {
          position: absolute; inset: 0;
          width: 100% !important; height: 100%;
          flex-shrink: 0;
        }
        /* Hide all left-panel text elements */
        .lc-left__bottom,
        .lc-ghost-num { display: none !important; }
        /* Denser scrim so text is readable over photo */
        .lc-left__overlay {
          background: linear-gradient(
            to top,
            rgba(10,18,24,0.88) 0%,
            rgba(10,18,24,0.60) 45%,
            rgba(10,18,24,0.30) 100%
          );
        }
        /* Right panel: overlaid on the image, anchored to bottom — no bg of its own */
        .lc-right {
          position: absolute;
          bottom: 52px; left: 0; right: 0;
          width: 100% !important; height: auto;
          padding: 0 24px 28px;
          background: none !important;
          align-items: flex-end;
          justify-content: flex-start;
        }
        .lc-right__inner { max-width: 100%; gap: 12px; }
        .lc-right__headline { font-size: 1.55rem; }
        /* body text colour inherited from base rule (white) */
        /* Nav bar at very bottom */
        .lc-nav {
          right: 0; top: auto; bottom: 0;
          width: 100%; height: 52px;
          flex-direction: row;
          background: rgba(10,18,24,0.88);
        }
        .lc-dots { flex-direction: row; gap: 7px; margin: 0 8px; }
      }
    `}</style>
  );
}

// ── Slide data ─────────────────────────────────────────────────
const CAROUSEL_SLIDES = [
  {
    key: "story",
    leftLabel: "NICARAGUA",
    leftSub: "La Isla | 2004",
    image: "assets/IMG/NIC1303_1608.jpg",
    bg: "linear-gradient(155deg, #0d1921 0%, #1a4560 60%, #0d2535 100%)",
    overline: "THE STORY",
    headline: "The Island of Widows.",
    body: [
      "There is a community in Nicaragua where so many men have died of heat-driven kidney disease that the locals call it La Isla de Viudas, The Island of Widows. Over half the families were headed by women whose husbands, sons, and brothers had succumbed to the same disease, doing the same kind of work, in the same heat.",
      "That community is where La Isla Network started. Two decades later, our team has followed the same disease, chronic kidney disease driven by extreme heat and hard labor, across three continents. Tens of thousands of shade tents in Central America. Migrant workers in the Middle East. Now, increasingly, farmworkers in California and Texas, construction crews in Southern Europe.",
      "It is preventable. Water, shade, scheduled rest, training. We know exactly what works. Companies that have put our recommendations in place have seen heat-related hospitalizations drop by 80 percent, and productivity rise by 10 to 20 percent.",
      "What you can do this summer is reach the worksites we have not gotten to yet. That is what this campaign is for.",
    ],
    pullQuote: null,
  },
  {
    key: "wiggins",
    leftLabel: "TEXAS",
    leftSub: "June 2026",
    image: "assets/IMG/watermelon-in-texas.jpg",
    bg: "linear-gradient(155deg, #0f141e 0%, #171c29 55%, #0f1620 100%)",
    overline: "THE WIGGINS WATERMELON PROJECT",
    headline: "One farmer in Texas changed the calculus.",
    body: [
      "A few months ago, a watermelon farmer in Wiggins reached out. He had watched his crew struggle in the heat for years. He told us he would put up the money himself to do this right. He just needed a partner who knew the science, the field, and the workers.",
      "That partner is La Isla Network. And we cannot do this work without you. The Wiggins Watermelon Project starts this June. Our team will design the heat-safety program around his actual operation, train his supervisors, set up the water and rest schedule, and measure what changes.",
      "Your funds are what let us send a small communications team to the farm to interview workers, capture the story, and turn one farmer's commitment into a national case study. A grant cannot move fast enough to do that. You can.",
    ],
    pullQuote: { text: "The next farmer who writes to us is who your gift is for.", sub: null },
  },
  {
    key: "whynow",
    leftLabel: "IN THE FIELD",
    leftSub: "Right now.",
    image: "assets/IMG/_MG_1271xs.jpg",
    bg: "linear-gradient(155deg, #111820 0%, #1a3245 55%, #0d1a2a 100%)",
    overline: "WHY NOW",
    headline: "Why this summer.",
    body: [
      "Workers are in the field right now. The harvest does not wait. The climate is not slowing down.",
      "Your gift funds the parts of our work institutional grants cannot. Rapid response when a new community is identified. Materials translated into a new language. Field visits in the gap between major projects. The flexible dollars that decide whether protection reaches the next jobsite or stops at the last one.",
      "That is what your gift this summer does.",
    ],
    hasCountdown: true,
    hasCTA: true,
  },
];

// ── Component ──────────────────────────────────────────────────
function StoryCarousel({ onDonate }) {
  const containerRef = React.useRef(null);
  const dotsRef = React.useRef(null);

  // Countdown
  const days = Math.max(0, Math.ceil((new Date("2026-07-31T23:59:59") - new Date()) / 86400000));

  // ── Render faces (shared by both spinners) ───────────────────
  const Faces = () => CAROUSEL_SLIDES.map((slide, i) => (
    <div key={slide.key} className={`lc-face${i === 0 ? " js-active" : ""}`} data-index={i}>
      <div className="lc-content">

        {/* Left: image + atmospheric label */}
        <div className="lc-left" style={{
          background: slide.bg,
          backgroundImage: `url(${slide.image})`,
          backgroundSize: "cover",
          backgroundPosition: "center",
        }}>
          <div className="lc-left__overlay" />
          <div className="lc-ghost-num">0{i + 1}</div>
          <div className="lc-left__bottom">
            <div className="lc-left__overline">{slide.overline}</div>
            <h3 className="lc-left__label">{slide.leftLabel}</h3>
            {/* <div className="lc-left__sub">{slide.leftSub}</div> */}
          </div>
        </div>

        {/* Right: readable content */}
        <div className="lc-right" style={{ background: slide.bg }}>
          <div className="lc-right__inner">
            <div className="lc-right__overline">{slide.overline}</div>
            <h2 className="lc-right__headline">{slide.headline}</h2>
            {slide.body.map((p, j) => <p key={j} className="lc-body-p">{p}</p>)}
            {slide.pullQuote && (
              <div className="lc-pullquote">
                <div className="lc-pullquote__text">{slide.pullQuote.text}</div>
                {slide.pullQuote.sub && <div className="lc-pullquote__sub">{slide.pullQuote.sub}</div>}
              </div>
            )}
            {slide.hasCountdown && (
              <div className="lc-countdown-badge">
                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"><circle cx="12" cy="12" r="10" /><polyline points="12 6 12 12 16 14" /></svg>
                <span><strong>{days}</strong> days left in the campaign</span>
              </div>
            )}
            {slide.hasCTA && (
              <button className="lc-cta-btn" onClick={() => openGivebutter()}>Donate now</button>
            )}
          </div>
        </div>

      </div>
    </div>
  ));

  // ── Vanilla JS carousel logic ────────────────────────────────
  React.useEffect(() => {
    const container = containerRef.current;
    if (!container) return;
    const stage = container.querySelector(".lc-stage");
    const N = CAROUSEL_SLIDES.length;
    let activeIndex = 0;
    let disabled = false;
    let lastSpinTime = 0;
    const SPIN_DUR = 1000;
    const MOBILE_DUR = 720;
    const DWELL_VH = 60; // scroll distance (vh) per slide
    const isMobile = () => window.innerWidth <= 700;

    const getFaces = idx => container.querySelectorAll(`.lc-face[data-index="${idx}"]`);
    const getDots = () => dotsRef.current ? dotsRef.current.querySelectorAll(".lc-dot") : [];

    const spin = (inc = 1) => {
      if (disabled || !inc) return;
      // Clamp to ±1 — never jump multiple slides from a single scroll event
      const step = Math.sign(inc);
      const now = Date.now();
      const dur = isMobile() ? MOBILE_DUR : SPIN_DUR;
      // Cooldown: reject if previous animation hasn't finished
      if (now - lastSpinTime < dur + 50) return;
      lastSpinTime = now;
      disabled = true;
      activeIndex = ((activeIndex + step) % N + N) % N;

      getFaces(activeIndex).forEach(f => f.classList.add("js-next"));
      if (step > 0) stage.classList.add("js-spin-fwd");
      else stage.classList.add("js-spin-bwd");

      getDots().forEach((d, i) => d.classList.toggle("active", i === activeIndex));

      setTimeout(() => {
        container.querySelectorAll(".lc-face.js-active").forEach(f => f.classList.remove("js-active"));
        container.querySelectorAll(".lc-face.js-next").forEach(f => {
          f.classList.remove("js-next");
          f.classList.add("js-active");
        });
        stage.classList.add("lc-no-transition");
        stage.classList.remove("js-spin-fwd", "js-spin-bwd");
        setTimeout(() => {
          stage.classList.remove("lc-no-transition");
          disabled = false;
        }, 100);
      }, dur);
    };

    // Dot clicks — allow direct jump to any slide
    getDots().forEach(dot => {
      dot.addEventListener("click", e => {
        e.preventDefault();
        const target = parseInt(dot.getAttribute("data-index"), 10);
        if (target === activeIndex) return;
        // For dot clicks bypass the ±1 clamp — spin one step at a time instantly
        const step = Math.sign(target - activeIndex);
        spin(step);
      });
    });

    // Prev / Next buttons
    const prev = container.querySelector(".lc-prev");
    const next = container.querySelector(".lc-next");
    if (prev) prev.addEventListener("click", () => spin(-1));
    if (next) next.addEventListener("click", () => spin(1));

    // Keyboard (only when carousel is in view)
    const onKey = e => {
      const rect = container.getBoundingClientRect();
      const inView = rect.top < window.innerHeight && rect.bottom > 0;
      if (!inView) return;
      if (e.key === "ArrowUp" || e.key === "ArrowLeft") spin(-1);
      if (e.key === "ArrowDown" || e.key === "ArrowRight") spin(1);
    };
    document.addEventListener("keyup", onKey);

    // Touch swipe — 80px threshold + 120ms time gate to prevent tap misfires
    let ty0 = null;
    let touchTime = 0;
    const onTS = e => { ty0 = e.touches[0].clientY; touchTime = Date.now(); };
    const onTE = e => {
      if (ty0 === null) return;
      const elapsed = Date.now() - touchTime;
      const dy = ty0 - e.changedTouches[0].clientY;
      ty0 = null; // consume gesture
      if (elapsed < 120) return; // tap, not swipe
      if (Math.abs(dy) > 80) spin(dy > 0 ? 1 : -1);
    };
    container.addEventListener("touchstart", onTS, { passive: true });
    container.addEventListener("touchend", onTE, { passive: true });

    // ── Scroll-track: map page scroll to slide index ──────────────
    // Each slide gets DWELL_VH of scroll distance; last slide has an extra
    // DWELL_VH exit buffer before the section unsticks.
    const track = container.closest(".lc-scroll-track");
    const dwellPx = () => window.innerHeight * (DWELL_VH / 100);
    const trackTop = track
      ? track.getBoundingClientRect().top + window.scrollY
      : 0;

    const onScroll = () => {
      if (!track) return;
      const scrolledIntoTrack = window.scrollY - trackTop;
      const targetIndex = Math.min(
        N - 1,
        Math.max(0, Math.floor(scrolledIntoTrack / dwellPx()))
      );
      if (targetIndex !== activeIndex) spin(targetIndex - activeIndex);
    };
    window.addEventListener("scroll", onScroll, { passive: true });

    return () => {
      document.removeEventListener("keyup", onKey);
      container.removeEventListener("touchstart", onTS);
      container.removeEventListener("touchend", onTE);
      window.removeEventListener("scroll", onScroll);
    };
  }, []);

  // Each slide gets 60vh of scroll dwell; +60vh exit buffer holds the last slide
  // before the section unsticks and the next section appears.
  const DWELL_VH = 60;
  const trackHeight = `calc(${CAROUSEL_SLIDES.length + 1} * ${DWELL_VH}vh)`;

  return (
    <div id="story" data-component="StoryCarousel" className="lc-scroll-track" style={{ height: trackHeight }}>
      <CarouselStyles />
      <section className="lc-section">
        <div ref={containerRef} style={{ position: "absolute", inset: 0 }}>
          <div className="lc-stage">
            <div className="lc-spinner lc-spinner--left"><Faces /></div>
            <div className="lc-spinner lc-spinner--right"><Faces /></div>
          </div>

          {/* Nav: prev · dots · next */}
          <nav className="lc-nav">
            <button className="lc-nav-btn lc-prev" aria-label="Previous slide">
              <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"><polyline points="18 15 12 9 6 15" /></svg>
            </button>
            <div className="lc-dots" ref={dotsRef}>
              {CAROUSEL_SLIDES.map((_, i) => (
                <button key={i} className={`lc-dot${i === 0 ? " active" : ""}`} data-index={i} aria-label={`Slide ${i + 1}`} />
              ))}
            </div>
            <button className="lc-nav-btn lc-next" aria-label="Next slide">
              <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"><polyline points="6 9 12 15 18 9" /></svg>
            </button>
          </nav>
        </div>
      </section>
    </div>
  );
}

Object.assign(window, { StoryCarousel });
