"use client"; import React, { useEffect, useRef, useState } from "react"; import Link from "next/link"; import { gsap } from "gsap"; import { ScrollTrigger } from "gsap/ScrollTrigger"; // Register GSAP plugins if (typeof window !== "undefined") { gsap.registerPlugin(ScrollTrigger); } // ───────────────────────────────────────────────────────────────────────────── // CINEMATIC HERO SECTION - APPLE-STYLE SCROLL-DRIVEN ANIMATIONS // ───────────────────────────────────────────────────────────────────────────── function scrollToContent() { const nextSection = document.getElementById("story"); if (nextSection) { nextSection.scrollIntoView({ behavior: "smooth" }); } } export default function HeroSection() { const containerRef = useRef(null); const heroRef = useRef(null); const contentRef = useRef(null); const [mounted, setMounted] = useState(false); const [scrollProgress, setScrollProgress] = useState(0); useEffect(() => { const timer = setTimeout(() => setMounted(true), 100); return () => clearTimeout(timer); }, []); // ─── GSAP SCROLL ANIMATIONS ──────────────────────────────────────────────── // Resilient: respects reduced-motion, safe GSAP target checks, reliable counter impl, proper scope useEffect(() => { if (!mounted || !heroRef.current || !contentRef.current) return; const prefersReducedMotion = typeof window !== "undefined" && window.matchMedia?.("(prefers-reduced-motion: reduce)").matches === true; // For reduced motion: show final states immediately (no scroll-driven anims to avoid jank/warnings) if (prefersReducedMotion) { const counterEls = document.querySelectorAll(".counter-animate"); counterEls.forEach((el) => { const targetStr = el.getAttribute("data-target") || "0"; const target = parseInt(targetStr, 10); el.textContent = target.toLocaleString(); }); // Still allow basic scroll progress bar if wanted, but skip all ScrollTrigger/GSAP heavy return; } const ctx = gsap.context(() => { // Scroll progress tracking ScrollTrigger.create({ trigger: heroRef.current, start: "top top", end: "bottom top", scrub: true, onUpdate: (self) => { setScrollProgress(self.progress); }, }); // Hero content pin - fade out on scroll gsap.to(contentRef.current, { y: -120, opacity: 0, scale: 0.95, ease: "power2.inOut", scrollTrigger: { trigger: heroRef.current, start: "top top", end: "40% top", scrub: 1.2, }, }); // Hero visual scale + parallax gsap.to(".hero-visual", { scale: 1.25, y: 80, ease: "power2.inOut", scrollTrigger: { trigger: heroRef.current, start: "top top", end: "50% top", scrub: 1.5, }, }); // Staggered entrance for content elements const contentElements = gsap.utils.toArray(".hero-reveal"); contentElements.forEach((el, i) => { gsap.fromTo( el, { opacity: 0, y: 50, scale: 0.95 }, { opacity: 1, y: 0, scale: 1, duration: 1.2, ease: "power3.out", delay: i * 0.15, scrollTrigger: { trigger: el, start: "top 90%", toggleActions: "play none none reverse", }, } ); }); // Parallax floating elements const floatElements = gsap.utils.toArray(".parallax-float"); floatElements.forEach((el, i) => { gsap.to(el, { y: -100 - i * 20, scrollTrigger: { trigger: el, start: "top bottom", end: "bottom top", scrub: 1, }, }); }); // Scroll indicator fade on scroll gsap.to(".scroll-indicator", { y: 20, opacity: 0, scrollTrigger: { trigger: heroRef.current, start: "10% top", end: "30% top", scrub: 1, }, }); // Staggered text reveal on scroll for other sections gsap.utils.toArray(".reveal-text").forEach((el) => { gsap.fromTo( el, { opacity: 0, y: 60, skewY: 3 }, { opacity: 1, y: 0, skewY: 0, duration: 1.2, ease: "power3.out", scrollTrigger: { trigger: el, start: "top 85%", end: "top 50%", toggleActions: "play none none reverse", }, } ); }); // Scale reveal for cards gsap.utils.toArray(".reveal-scale").forEach((el, i) => { gsap.fromTo( el, { opacity: 0, scale: 0.85, y: 50 }, { opacity: 1, scale: 1, y: 0, duration: 0.8, delay: i * 0.1, ease: "back.out(1.4)", scrollTrigger: { trigger: el, start: "top 85%", toggleActions: "play none none reverse", }, } ); }); // Counter animations - fixed: use reliable proxy object (avoids textContent tween pitfalls that left counters at 0) // + always scoped + fallback path (though reduced handled above) + !gsap guard per requirements const counterElements = gsap.utils.toArray(".counter-animate"); const hasGSAP = typeof gsap !== "undefined" && typeof gsap.to === "function"; counterElements.forEach((el) => { const targetStr = el.getAttribute("data-target") || "0"; const target = parseInt(targetStr, 10); el.textContent = "0"; // ensure start if (hasGSAP && gsap) { const obj = { val: 0 }; gsap.to(obj, { val: target, duration: 2.5, ease: "power2.out", scrollTrigger: { trigger: el, start: "top 85%", toggleActions: "play none none none", }, onUpdate: () => { if (el.textContent !== null) { el.textContent = Math.floor(obj.val).toLocaleString(); } }, }); } else { // pure fallback using IO + rAF (IntersectionObserver + requestAnimationFrame) if no GSAP const io = new IntersectionObserver((entries) => { if (entries[0]?.isIntersecting) { io.disconnect(); const startTime = Date.now(); const dur = 2000; const tick = () => { const p = Math.min((Date.now() - startTime) / dur, 1); const eased = 1 - Math.pow(1 - p, 3); const val = Math.floor(target * eased); el.textContent = val.toLocaleString(); if (p < 1) requestAnimationFrame(tick); else el.textContent = target.toLocaleString(); }; tick(); } }, { threshold: 0.3 }); io.observe(el); } }); }, containerRef); return () => ctx.revert(); }, [mounted]); return ( <> {/* ─── SCROLL PROGRESS BAR ──────────────────────────────────────────── */}
{/* ─── HERO SECTION - SCROLL-DRIVEN PIN ───────────────────────────── */} {/* containerRef wraps animated sections for proper GSAP context scope (fixes "Invalid scope" + missing targets) */}
{/* ─── PARALLAX BACKGROUND LAYERS ─────────────────────────────────────── */}
{/* Gradient orbs */}
{/* Grid pattern */}
{/* ─── HERO CONTENT ────────────────────────────────────────────────────── */}
{/* Left Column - Animated Content */}
{/* Animated Badge */}
Farm-Fresh Delivery Platform
{/* Main Headline - Apple-style reveal */}

From Field To Fresh

{/* Subtext */}

We connect produce farms with reliable distribution networks, ensuring your harvest reaches markets faster and fresher than ever.

{/* CTAs */}
{ e.currentTarget.style.transform = "translateY(-3px)"; e.currentTarget.style.boxShadow = "0 12px 40px rgba(26, 77, 46, 0.45), inset 0 1px 0 rgba(255, 255, 255, 0.2)"; }} onMouseLeave={(e) => { e.currentTarget.style.transform = "translateY(0)"; e.currentTarget.style.boxShadow = "0 8px 32px rgba(26, 77, 46, 0.35), inset 0 1px 0 rgba(255, 255, 255, 0.15)"; }} > Start Your Route { e.currentTarget.style.background = "#1a4d2e"; e.currentTarget.style.color = "white"; }} onMouseLeave={(e) => { e.currentTarget.style.background = "rgba(26, 77, 46, 0.03)"; e.currentTarget.style.color = "#1a4d2e"; }} > Browse Farms
{/* Stats */}
{[ { stat: "500+", label: "Farm Brands" }, { stat: "98%", label: "On-Time" }, { stat: "50K+", label: "Deliveries" }, ].map((item) => (
{item.stat}
{item.label}
))}
{/* Right Column - Hero Visual */}
{/* SVG Route Map Visual */} {/* Animated Route Path */} {/* Secondary Route */} {/* Farm Location - Animated Pulse */} {/* Hub Location */} {/* Stop Points */} {[ { x: 180, y: 280 }, { x: 360, y: 120 }, { x: 420, y: 90 }, ].map((stop, i) => ( ))} {/* Decorative Trees */} {[[60, 100], [440, 360], [50, 440], [450, 180]].map((coords, i) => ( ))} {/* Compass */} N {/* Floating Cards */}
2.4T
Miles Saved
12hrs
Avg Delivery
Live Tracking
{/* ─── SCROLL INDICATOR ────────────────────────────────────────────────── */} {/* Decorative leaves */}
{/* ─── STORY SECTION - SCROLL-DRIVEN REVEAL ──────────────────────────── */}
{/* Reduced from 300vh to avoid "long blank scroll regions" complaint while keeping cinematic sticky scroll effect */}
{/* Sticky Container */}
{/* Background gradient */}
The Challenge

Fresh produce should not
sit in transit for days

Traditional distribution means your harvest loses freshness, quality, and value before reaching customers.

{/* ─── FEATURES SECTION - PROGRESSIVE REVEAL ───────────────────────────── */}
{/* Parallax background elements */}
{/* Section Header */}
Platform Features

Everything You Need

{/* Feature Cards Grid */}
{[ { icon: ( ), title: "Product Catalogs", description: "Showcase seasonal produce with rich media galleries and real-time availability updates.", color: "#1a4d2e", }, { icon: ( ), title: "Route Planning", description: "Optimize delivery routes with intelligent mapping and real-time scheduling.", color: "#c97a3e", }, { icon: ( ), title: "Order Management", description: "Track orders from placement through delivery with automated status updates.", color: "#7a5c9e", }, { icon: ( ), title: "Wholesale Portal", description: "Give buyers a dedicated space to browse pricing and place bulk orders.", color: "#5c8a8f", }, { icon: ( ), title: "Harvest Reach", description: "Send email and SMS campaigns about seasonal availability and new harvests.", color: "#c97a3e", }, { icon: ( ), title: "Smart Analytics", description: "Uncover sales trends and operational insights with real-time dashboards.", color: "#6b8f71", }, ].map((feature) => (
{ e.currentTarget.style.transform = "translateY(-8px) scale(1.02)"; e.currentTarget.style.boxShadow = "0 20px 60px rgba(26, 77, 46, 0.12)"; e.currentTarget.style.borderColor = feature.color + "40"; }} onMouseLeave={(e) => { e.currentTarget.style.transform = "translateY(0) scale(1)"; e.currentTarget.style.boxShadow = "0 8px 32px rgba(0, 0, 0, 0.04)"; e.currentTarget.style.borderColor = "rgba(26, 77, 46, 0.08)"; }} > {/* Icon */}
{feature.icon}
{/* Content */}

{feature.title}

{feature.description}

{/* Hover Arrow */}
))}
{/* ─── STATS SECTION - SCROLL-TRIGGERED COUNTERS ──────────────────────── */}
{/* Parallax decorative elements */}
Our Impact
{/* Stats Grid */}
{[ { value: 500, suffix: "+", label: "Produce Brands" }, { value: 50000, suffix: "+", label: "Orders Delivered" }, { value: 98, suffix: "%", label: "On-Time Delivery" }, { value: 2000000, prefix: "$", suffix: "+", label: "Weekly Sales" }, ].map((stat, i) => (
{stat.prefix && {stat.prefix}} 0 {stat.suffix}

{stat.label}

))}
{/* ─── CTA SECTION - FINAL REVEAL ─────────────────────────────────────── */} {/* id="reviews" provides anchor for nav "Reviews" link (matches nav expectations; section contains final messaging) */}
{/* Parallax decorative orbs */}
{/* Label */}
Get Started Today
{/* Headline */}

Ready to Transform
Your Distribution?

{/* Subtext */}

Join hundreds of farms already using Route Commerce to deliver fresher produce faster.

{/* CTAs */}
Start Free Trial Contact Sales
{/* /containerRef for GSAP scope */} {/* (duplicate inline footer removed -- LandingPageWrapper