const PROJECTS = [
{
  num: '01',
  name: 'Your AI Videos Aren\'t Bad, Your System Is',
  category: 'Client',
  desc: 'Most creators fail with AI videos because they chase tools instead of building a workflow. This cinematic AI ad breaks down the real problem behind average AI content.',
  col1: [
  'https://images.higgs.ai/?default=1&output=webp&url=https%3A%2F%2Fd8j0ntlcm91z4.cloudfront.net%2Fuser_38xzZboKViGWJOttwIXH07lWA1P%2Fhf_20260412_055344_5eff02e0-87a5-41ce-b64f-eb08da8f33db.png&w=1280&q=85',
  'https://images.higgs.ai/?default=1&output=webp&url=https%3A%2F%2Fd8j0ntlcm91z4.cloudfront.net%2Fuser_38xzZboKViGWJOttwIXH07lWA1P%2Fhf_20260412_055431_11d841fd-8b41-46a5-82e4-b04f2407a7d8.png&w=1280&q=85'],

  col2: 'https://images.higgs.ai/?default=1&output=webp&url=https%3A%2F%2Fd8j0ntlcm91z4.cloudfront.net%2Fuser_38xzZboKViGWJOttwIXH07lWA1P%2Fhf_20260412_055451_e317bf2d-28d4-48cc-86b0-6f72f25b6327.png&w=1280&q=85'
},
{
  num: '02',
  name: 'I Built Everything… And Lost Us Doing It',
  category: 'Personal',
  desc: 'A cinematic emotional confrontation between ambition and love, where success slowly destroys the relationship it was meant to protect.',
  col1: [
  'https://images.higgs.ai/?default=1&output=webp&url=https%3A%2F%2Fd8j0ntlcm91z4.cloudfront.net%2Fuser_38xzZboKViGWJOttwIXH07lWA1P%2Fhf_20260412_055654_911201c5-36d9-4bc6-bac7-331adfce159f.png&w=1280&q=85',
  'https://images.higgs.ai/?default=1&output=webp&url=https%3A%2F%2Fd8j0ntlcm91z4.cloudfront.net%2Fuser_38xzZboKViGWJOttwIXH07lWA1P%2Fhf_20260412_055723_5ceda0b8-d9c2-4665-b2e3-83ba19ba76d1.png&w=1280&q=85'],

  col2: 'https://images.higgs.ai/?default=1&output=webp&url=https%3A%2F%2Fd8j0ntlcm91z4.cloudfront.net%2Fuser_38xzZboKViGWJOttwIXH07lWA1P%2Fhf_20260412_055753_adc5dcbd-a8e6-49c0-b43a-9b030d835cea.png&w=1280&q=85'
},
{
  num: '03',
  name: 'This Is What AI Looks Like in 2026',
  category: 'Personal',
  desc: 'AI is no longer robotic or fake-looking. This futuristic cinematic ad showcases how brands now generate premium campaigns through creativity, direction, and AI filmmaking.',
  col1: [
  'https://images.higgs.ai/?default=1&output=webp&url=https%3A%2F%2Fd8j0ntlcm91z4.cloudfront.net%2Fuser_38xzZboKViGWJOttwIXH07lWA1P%2Fhf_20260412_055759_963cfb0b-4bd1-4b0f-9d0a-09bd6cf95b2f.png&w=1280&q=85',
  'https://images.higgs.ai/?default=1&output=webp&url=https%3A%2F%2Fd8j0ntlcm91z4.cloudfront.net%2Fuser_38xzZboKViGWJOttwIXH07lWA1P%2Fhf_20260412_060108_438f781a-9846-4dcc-89ab-c4e6cb830f5b.png&w=1280&q=85'],

  col2: 'https://images.higgs.ai/?default=1&output=webp&url=https%3A%2F%2Fd8j0ntlcm91z4.cloudfront.net%2Fuser_38xzZboKViGWJOttwIXH07lWA1P%2Fhf_20260412_055818_9d062121-ad7e-46b9-999a-1a6a692ef1ee.png&w=1280&q=85'
},
{
  num: '04',
  name: 'She Took Care of Everyone Except Herself',
  category: 'Client',
  desc: 'A heartfelt Mother\'s Day AI commercial for BSLC, celebrating the women who give everything and deserve to finally feel cared for too.',
  col1: [
  'https://images.higgs.ai/?default=1&output=webp&url=https%3A%2F%2Fd8j0ntlcm91z4.cloudfront.net%2Fuser_38xzZboKViGWJOttwIXH07lWA1P%2Fhf_20260412_055344_5eff02e0-87a5-41ce-b64f-eb08da8f33db.png&w=1280&q=85',
  'https://images.higgs.ai/?default=1&output=webp&url=https%3A%2F%2Fd8j0ntlcm91z4.cloudfront.net%2Fuser_38xzZboKViGWJOttwIXH07lWA1P%2Fhf_20260412_055431_11d841fd-8b41-46a5-82e4-b04f2407a7d8.png&w=1280&q=85'],

  col2: 'https://images.higgs.ai/?default=1&output=webp&url=https%3A%2F%2Fd8j0ntlcm91z4.cloudfront.net%2Fuser_38xzZboKViGWJOttwIXH07lWA1P%2Fhf_20260412_055451_e317bf2d-28d4-48cc-86b0-6f72f25b6327.png&w=1280&q=85'
},
{
  num: '05',
  name: 'The KitKat Truck Theft That Became Marketing Genius',
  category: 'Client',
  desc: 'What if the biggest marketing campaigns didn\'t look like ads at all? This AI-generated storytelling piece explores the viral "stolen KitKat truck" phenomenon.',
  col1: [
  'https://images.higgs.ai/?default=1&output=webp&url=https%3A%2F%2Fd8j0ntlcm91z4.cloudfront.net%2Fuser_38xzZboKViGWJOttwIXH07lWA1P%2Fhf_20260412_055654_911201c5-36d9-4bc6-bac7-331adfce159f.png&w=1280&q=85',
  'https://images.higgs.ai/?default=1&output=webp&url=https%3A%2F%2Fd8j0ntlcm91z4.cloudfront.net%2Fuser_38xzZboKViGWJOttwIXH07lWA1P%2Fhf_20260412_055723_5ceda0b8-d9c2-4665-b2e3-83ba19ba76d1.png&w=1280&q=85'],

  col2: 'https://images.higgs.ai/?default=1&output=webp&url=https%3A%2F%2Fd8j0ntlcm91z4.cloudfront.net%2Fuser_38xzZboKViGWJOttwIXH07lWA1P%2Fhf_20260412_055753_adc5dcbd-a8e6-49c0-b43a-9b030d835cea.png&w=1280&q=85'
},
{
  num: '06',
  name: 'Your Treatments Are Tired of Your Expectations',
  category: 'Client',
  desc: 'A funny luxury-clinic AI commercial where aesthetic treatments talk back to impatient clients demanding instant perfection.',
  col1: [
  'https://images.higgs.ai/?default=1&output=webp&url=https%3A%2F%2Fd8j0ntlcm91z4.cloudfront.net%2Fuser_38xzZboKViGWJOttwIXH07lWA1P%2Fhf_20260412_055759_963cfb0b-4bd1-4b0f-9d0a-09bd6cf95b2f.png&w=1280&q=85',
  'https://images.higgs.ai/?default=1&output=webp&url=https%3A%2F%2Fd8j0ntlcm91z4.cloudfront.net%2Fuser_38xzZboKViGWJOttwIXH07lWA1P%2Fhf_20260412_060108_438f781a-9846-4dcc-89ab-c4e6cb830f5b.png&w=1280&q=85'],

  col2: 'https://images.higgs.ai/?default=1&output=webp&url=https%3A%2F%2Fd8j0ntlcm91z4.cloudfront.net%2Fuser_38xzZboKViGWJOttwIXH07lWA1P%2Fhf_20260412_055818_9d062121-ad7e-46b9-999a-1a6a692ef1ee.png&w=1280&q=85'
},
{
  num: '07',
  name: 'Ex Tag Challenge',
  category: 'Personal',
  desc: 'AI-generated video using subtle motion, dynamic effects, and trending audio to create an engaging short-form social media ad designed to boost retention and shares.',
  col1: [
  'https://images.higgs.ai/?default=1&output=webp&url=https%3A%2F%2Fd8j0ntlcm91z4.cloudfront.net%2Fuser_38xzZboKViGWJOttwIXH07lWA1P%2Fhf_20260412_055344_5eff02e0-87a5-41ce-b64f-eb08da8f33db.png&w=1280&q=85',
  'https://images.higgs.ai/?default=1&output=webp&url=https%3A%2F%2Fd8j0ntlcm91z4.cloudfront.net%2Fuser_38xzZboKViGWJOttwIXH07lWA1P%2Fhf_20260412_055654_911201c5-36d9-4bc6-bac7-331adfce159f.png&w=1280&q=85'],

  col2: 'https://images.higgs.ai/?default=1&output=webp&url=https%3A%2F%2Fd8j0ntlcm91z4.cloudfront.net%2Fuser_38xzZboKViGWJOttwIXH07lWA1P%2Fhf_20260412_055759_963cfb0b-4bd1-4b0f-9d0a-09bd6cf95b2f.png&w=1280&q=85'
},
{
  num: '08',
  name: 'I Thought My Pregnant Wife Was Cheating',
  category: 'Personal',
  desc: 'A dramatic AI-generated cinematic product ad built like a story filled with suspicion, heartbreak, and an emotional twist that changes everything.',
  col1: [
  'https://images.higgs.ai/?default=1&output=webp&url=https%3A%2F%2Fd8j0ntlcm91z4.cloudfront.net%2Fuser_38xzZboKViGWJOttwIXH07lWA1P%2Fhf_20260412_055431_11d841fd-8b41-46a5-82e4-b04f2407a7d8.png&w=1280&q=85',
  'https://images.higgs.ai/?default=1&output=webp&url=https%3A%2F%2Fd8j0ntlcm91z4.cloudfront.net%2Fuser_38xzZboKViGWJOttwIXH07lWA1P%2Fhf_20260412_055723_5ceda0b8-d9c2-4665-b2e3-83ba19ba76d1.png&w=1280&q=85'],

  col2: 'https://images.higgs.ai/?default=1&output=webp&url=https%3A%2F%2Fd8j0ntlcm91z4.cloudfront.net%2Fuser_38xzZboKViGWJOttwIXH07lWA1P%2Fhf_20260412_060108_438f781a-9846-4dcc-89ab-c4e6cb830f5b.png&w=1280&q=85'
}];


const TOTAL = PROJECTS.length;
const STACK_TOP = 'var(--project-stack-top)';
const STACK_GAP = 'var(--project-stack-gap)';

const getStackTop = (i) => {
  if (i === 0) return STACK_TOP;
  return `calc(${STACK_TOP} + ${Array.from({ length: i }, () => STACK_GAP).join(' + ')})`;
};

const VIDEO_SOURCES = {
  '1': { src: 'https://file.garden/agB6zAeEOEJL_pd7/1.mp4' },
  '2': { src: 'https://file.garden/agB6zAeEOEJL_pd7/2.mp4' },
  '3': { src: 'https://file.garden/agB6zAeEOEJL_pd7/3.mp4' },
  '4': { src: 'https://file.garden/agB6zAeEOEJL_pd7/4.mp4' },
  '5': { src: 'https://file.garden/agB6zAeEOEJL_pd7/5.mp4' },
  '6': { src: 'https://file.garden/agB6zAeEOEJL_pd7/6.mp4' },
  '7': { src: 'https://file.garden/agB6zAeEOEJL_pd7/7.mp4' },
  '8': { src: 'https://file.garden/agB6zAeEOEJL_pd7/8.mp4' },
};


const PlayButton = () => (
  <div style={{
    position: 'relative', zIndex: 1,
    width: 58, height: 58, borderRadius: '50%',
    background: 'rgba(255,255,255,0.14)',
    backdropFilter: 'blur(10px)',
    WebkitBackdropFilter: 'blur(10px)',
    border: '1.5px solid rgba(255,255,255,0.32)',
    boxShadow: '0 4px 24px rgba(0,0,0,0.35)',
    display: 'flex', alignItems: 'center', justifyContent: 'center'
  }}>
    <svg width="20" height="20" viewBox="0 0 24 24" fill="white" style={{ marginLeft: 3 }}>
      <polygon points="5,3 19,12 5,21" />
    </svg>
  </div>
);

function ProjectVideo({ num, radius }) {
  const source = VIDEO_SOURCES[String(parseInt(num))];
  const [playing, setPlaying] = useState(false);
  const [buffering, setBuffering] = useState(false);
  const [isMobile, setIsMobile] = useState(() => window.matchMedia('(max-width: 1279px)').matches);
  const videoRef = useRef(null);
  const wrapRef = useRef(null);

  useEffect(() => {
    const mq = window.matchMedia('(max-width: 1279px)');
    const update = () => setIsMobile(mq.matches);
    mq.addEventListener('change', update);
    return () => mq.removeEventListener('change', update);
  }, []);

  // Force buffering to start immediately on all devices.
  // Mobile browsers ignore preload="auto", but they DO buffer a muted video.
  useEffect(() => {
    const v = videoRef.current;
    if (!v) return;
    v.muted = true;
    v.play().then(() => v.pause()).catch(() => {});
  }, []);

  useEffect(() => {
    const el = wrapRef.current;
    if (!el) return;

    const stop = () => {
      if (!videoRef.current || videoRef.current.paused) return;
      videoRef.current.pause();
      setPlaying(false);
      setBuffering(false);
    };

    // Stop when scrolled out of viewport
    const observer = new IntersectionObserver(([entry]) => {
      if (!entry.isIntersecting) stop();
    }, { threshold: 0.2 });
    observer.observe(el);

    // Stop when another card stacks on top and covers this video
    const checkCovered = () => {
      if (!videoRef.current || videoRef.current.paused) return;
      const rect = el.getBoundingClientRect();
      const cx = rect.left + rect.width / 2;
      const cy = rect.top + rect.height / 2;
      if (cy < 0 || cy > window.innerHeight) return;
      const topEl = document.elementFromPoint(cx, cy);
      if (topEl && !el.contains(topEl)) stop();
    };
    window.addEventListener('scroll', checkCovered, { passive: true });

    return () => {
      observer.disconnect();
      window.removeEventListener('scroll', checkCovered);
    };
  }, []);

  useEffect(() => {
    const handleStop = (e) => {
      if (e.detail === num) return;
      if (videoRef.current) { videoRef.current.pause(); }
      setPlaying(false);
      setBuffering(false);
    };
    window.addEventListener('projectvideo:play', handleStop);
    return () => window.removeEventListener('projectvideo:play', handleStop);
  }, [num]);

  const handlePlay = () => {
    const v = videoRef.current;
    if (!v) return;
    v.muted = false;
    window.dispatchEvent(new CustomEvent('projectvideo:play', { detail: num }));
    setPlaying(true);
    setBuffering(true);
    v.play().catch(() => {});
  };

  const wrapStyle = { borderRadius: radius, border: '1.5px solid rgba(215, 226, 234, 0.35)', background: '#000' };

  const togglePlayback = () => {
    if (!videoRef.current) return;
    if (videoRef.current.paused) videoRef.current.play().catch(() => {});
    else videoRef.current.pause();
  };

  return (
    <div ref={wrapRef} className="w-full relative overflow-hidden aspect-video" style={wrapStyle}>
      <video
        ref={videoRef}
        src={source.src}
        preload="auto"
        playsInline
        controls={playing}
        onPlaying={() => setBuffering(false)}
        onWaiting={() => setBuffering(true)}
        className="absolute inset-0 w-full h-full"
        style={{ background: '#000' }}
      />
      {playing && isMobile && (
        <div
          className="absolute inset-x-0 top-0"
          style={{ bottom: 72, cursor: 'pointer', zIndex: 1 }}
          onClick={togglePlayback}
        />
      )}
      {!playing && (
        <div
          className="absolute inset-0 flex items-center justify-center"
          style={{ cursor: 'pointer', zIndex: 2 }}
          onClick={handlePlay}>
          <PlayButton />
        </div>
      )}
      {playing && buffering && (
        <div
          className="absolute inset-0 flex items-center justify-center"
          style={{ zIndex: 2, background: 'rgba(0,0,0,0.45)' }}>
          <div style={{
            width: 38, height: 38, borderRadius: '50%',
            border: '3px solid rgba(255,255,255,0.18)',
            borderTopColor: 'white',
            animation: 'projectvideo-spin 0.75s linear infinite'
          }} />
        </div>
      )}
    </div>
  );
}

function ProjectCard({ project, index, progress }) {
  const targetScale = 1 - (TOTAL - 1 - index) * 0.03;
  const scale = useTransform(progress, [index / TOTAL, 1], [1, targetScale]);
  const imgRadius = 'clamp(20px, 4vw, 60px)';

  return (
    <motion.div
      data-project-card
      style={{
        position: 'sticky',
        top: getStackTop(index),
        zIndex: index + 1,
        scale,
        transformOrigin: 'top center',
        background: '#0C0C0C',
        marginBottom: '1rem'
      }}
      className="w-full rounded-[40px] border-2 border-[#D7E2EA] p-4 md:p-6 xl:rounded-[60px] xl:p-8">
      
      <div className="project-card-header mb-4 xl:mb-6">
        <span className="project-card-number font-black">{project.num}</span>
        <div className="project-card-title-block flex flex-col gap-1">
          <span className="project-card-title font-medium uppercase">{project.name}</span>
        </div>
        <LiveProjectButton />
      </div>
      <div className="project-media-grid">
        <div className="project-side-column">
          <div className="project-description-card flex flex-col justify-center border border-[#D7E2EA]/30 p-4 xl:p-6" style={{ borderRadius: imgRadius, background: 'rgba(215, 226, 234, 0.04)' }}>
            <p className="project-description-copy font-light leading-relaxed" style={{ color: '#D7E2EA', opacity: 0.78, fontSize: 'clamp(0.78rem, 1.25vw, 1rem)' }}>{project.desc}</p>
          </div>
        </div>
        <div className="project-main-wrap">
          <ProjectVideo num={project.num} radius={imgRadius} />
        </div>
      </div>
    </motion.div>);

}

function ProjectsSection() {
  const containerRef = useRef(null);
  const { scrollYProgress } = useScroll({
    target: containerRef,
    offset: ['start start', 'end end']
  });

  useLayoutEffect(() => {
    const equalize = () => {
      const cards = containerRef.current?.querySelectorAll('[data-project-card]');
      if (!cards || !cards.length) return;
      cards.forEach(c => { c.style.minHeight = ''; });
      let max = 0;
      cards.forEach(c => { max = Math.max(max, c.offsetHeight); });
      cards.forEach(c => { c.style.minHeight = max + 'px'; });
    };
    equalize();
    const t = setTimeout(equalize, 300);
    window.addEventListener('resize', equalize);
    return () => {
      clearTimeout(t);
      window.removeEventListener('resize', equalize);
    };
  }, []);

  return (
    <section id="projects" className="project-stack-section rounded-t-[40px] -mt-10 z-10 relative px-5 pt-20 pb-32 xl:rounded-t-[60px] xl:-mt-14 xl:px-10 xl:pt-32" style={{ background: '#0C0C0C' }}>
      <FadeIn delay={0} y={40}>
        <h2 className="hero-heading font-black uppercase text-center leading-none tracking-tight mb-3" style={{ fontSize: 'clamp(3rem, 12vw, 160px)' }}>PROJECTS</h2>
        <p className="text-center font-light italic mb-16 xl:mb-28" style={{ color: '#D7E2EA', opacity: 0.38, fontSize: 'clamp(0.7rem, 1.1vw, 0.88rem)' }}>Compressed for preview</p>
      </FadeIn>
      <div ref={containerRef} className="project-scroll-track">
        {PROJECTS.map((p, i) =>
        <ProjectCard key={p.num} project={p} index={i} progress={scrollYProgress} />
        )}
      </div>
    </section>);

}

function BackToTopButton() {
  const [visible, setVisible] = React.useState(false);

  React.useEffect(() => {
    const onScroll = () => setVisible(window.scrollY > window.innerHeight * 0.6);
    onScroll();
    window.addEventListener('scroll', onScroll, { passive: true });
    return () => window.removeEventListener('scroll', onScroll);
  }, []);

  return (
    <button
      onClick={() => window.scrollTo({ top: 0, behavior: 'smooth' })}
      aria-label="Back to top"
      style={{
        position: 'fixed',
        right: 'clamp(16px, 3vw, 32px)',
        bottom: 'clamp(16px, 3vw, 32px)',
        width: 52,
        height: 52,
        borderRadius: '9999px',
        background: 'linear-gradient(123deg, #18011F 7%, #B600A8 37%, #7621B0 72%, #BE4C00 100%)',
        boxShadow: '0px 4px 16px rgba(181, 1, 167, 0.35), inset 4px 4px 12px #7721B1',
        outline: '2px solid white',
        outlineOffset: '-3px',
        border: 'none',
        cursor: 'pointer',
        color: 'white',
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center',
        opacity: visible ? 1 : 0,
        transform: visible ? 'translateY(0)' : 'translateY(16px)',
        pointerEvents: visible ? 'auto' : 'none',
        transition: 'opacity 0.35s ease, transform 0.35s ease',
        zIndex: 50,
        fontFamily: 'inherit'
      }}
      className="back-to-top-button hover:opacity-90">
      <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
        <path d="M12 19V5" />
        <path d="m5 12 7-7 7 7" />
      </svg>
    </button>);
}

function App() {
  return (
    <div style={{ background: '#0C0C0C', overflowX: 'clip' }}>
      <HeroSection />
      <MarqueeSection />
      <AboutSection />
      <ServicesSection />
      <ProjectsSection />
      <ContactSection />
      <BackToTopButton />
    </div>);

}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
