diff --git a/Version 2 of Cinematic Agency Portfolio 2/App.tsx b/Version 2 of Cinematic Agency Portfolio 2/App.tsx
new file mode 100644
index 0000000..7703bf8
--- /dev/null
+++ b/Version 2 of Cinematic Agency Portfolio 2/App.tsx
@@ -0,0 +1,76 @@
+import React, { useEffect } from 'react';
+import Lenis from 'lenis';
+import gsap from 'gsap';
+import { ScrollTrigger } from 'gsap/ScrollTrigger';
+import { Navbar } from './components/Navbar';
+import { Hero } from './components/Hero';
+import { Features } from './components/Features';
+import { VisualSection } from './components/VisualSection';
+import { ProductCarousel } from './components/ProductCarousel';
+import { Footer } from './components/Footer';
+import { CallToAction } from './components/CallToAction';
+
+// Register GSAP plugin globally
+gsap.registerPlugin(ScrollTrigger);
+
+const App: React.FC = () => {
+ useEffect(() => {
+ // Initialize Lenis for smooth scrolling
+ const lenis = new Lenis({
+ duration: 1.2,
+ easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)),
+ direction: 'vertical',
+ gestureDirection: 'vertical',
+ smooth: true,
+ smoothTouch: false,
+ touchMultiplier: 2,
+ });
+
+ // Expose lenis to window for Navbar access
+ (window as any).lenis = lenis;
+
+ // Connect Lenis to GSAP ScrollTrigger
+ lenis.on('scroll', ScrollTrigger.update);
+
+ // GSAP ticker sync
+ gsap.ticker.add((time) => {
+ lenis.raf(time * 1000);
+ });
+
+ gsap.ticker.lagSmoothing(0);
+
+ return () => {
+ lenis.destroy();
+ (window as any).lenis = null;
+ gsap.ticker.remove((time) => lenis.raf(time * 1000));
+ };
+ }, []);
+
+ return (
+
+ );
+};
+
+export default App;
\ No newline at end of file
diff --git a/Version 2 of Cinematic Agency Portfolio 2/components/CallToAction.tsx b/Version 2 of Cinematic Agency Portfolio 2/components/CallToAction.tsx
new file mode 100644
index 0000000..b9ba143
--- /dev/null
+++ b/Version 2 of Cinematic Agency Portfolio 2/components/CallToAction.tsx
@@ -0,0 +1,43 @@
+import React, { useRef, useEffect } from 'react';
+import gsap from 'gsap';
+
+interface CallToActionProps {
+ id?: string;
+}
+
+export const CallToAction: React.FC = ({ id }) => {
+ const containerRef = useRef(null);
+ const textRef = useRef(null);
+
+ useEffect(() => {
+ // Reveal animation
+ gsap.fromTo(textRef.current,
+ { y: 100, opacity: 0 },
+ {
+ y: 0,
+ opacity: 1,
+ duration: 1.5,
+ ease: 'power4.out',
+ scrollTrigger: {
+ trigger: containerRef.current,
+ start: 'top 75%',
+ }
+ }
+ );
+ }, []);
+
+ return (
+
+
+
+
+
+ Ready to disrupt?
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/Version 2 of Cinematic Agency Portfolio 2/components/Features.tsx b/Version 2 of Cinematic Agency Portfolio 2/components/Features.tsx
new file mode 100644
index 0000000..f362808
--- /dev/null
+++ b/Version 2 of Cinematic Agency Portfolio 2/components/Features.tsx
@@ -0,0 +1,83 @@
+import React, { useEffect, useRef } from 'react';
+import gsap from 'gsap';
+import { SectionWrapper } from './SectionWrapper';
+import { Cpu, Globe, Zap, Shield } from 'lucide-react';
+
+interface FeaturesProps {
+ id?: string;
+}
+
+const featureList = [
+ {
+ icon: ,
+ title: "AI-Driven Core",
+ desc: "Our systems leverage the latest in neural processing to optimize user pathways in real-time."
+ },
+ {
+ icon: ,
+ title: "Global CDN",
+ desc: "Content delivered from the edge, ensuring millisecond latency regardless of user location."
+ },
+ {
+ icon: ,
+ title: "Instant State",
+ desc: "Optimistic UI updates and predictive pre-fetching make the interface feel instant."
+ },
+ {
+ icon: ,
+ title: "Enterprise Security",
+ desc: "Bank-grade encryption and compliance standards built into every layer of the stack."
+ }
+];
+
+export const Features: React.FC = ({ id }) => {
+ const gridRef = useRef(null);
+
+ useEffect(() => {
+ if (!gridRef.current) return;
+
+ const cards = gridRef.current.children;
+
+ gsap.fromTo(cards,
+ { opacity: 0, y: 40 },
+ {
+ opacity: 1,
+ y: 0,
+ duration: 1,
+ stagger: 0.2,
+ ease: 'power3.out',
+ scrollTrigger: {
+ trigger: gridRef.current,
+ start: 'top 80%',
+ }
+ }
+ );
+ }, []);
+
+ return (
+
+
+
+
+ Technical Superiority
+
+
+
+
+
+ {featureList.map((f, i) => (
+
+
+ {f.icon}
+
+
{f.title}
+
+ {f.desc}
+
+
+ ))}
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/Version 2 of Cinematic Agency Portfolio 2/components/Footer.tsx b/Version 2 of Cinematic Agency Portfolio 2/components/Footer.tsx
new file mode 100644
index 0000000..bbf4eb9
--- /dev/null
+++ b/Version 2 of Cinematic Agency Portfolio 2/components/Footer.tsx
@@ -0,0 +1,24 @@
+import React from 'react';
+
+export const Footer: React.FC = () => {
+ return (
+
+ );
+};
\ No newline at end of file
diff --git a/Version 2 of Cinematic Agency Portfolio 2/components/Hero.tsx b/Version 2 of Cinematic Agency Portfolio 2/components/Hero.tsx
new file mode 100644
index 0000000..0320fc1
--- /dev/null
+++ b/Version 2 of Cinematic Agency Portfolio 2/components/Hero.tsx
@@ -0,0 +1,66 @@
+import React, { useEffect, useRef } from 'react';
+import gsap from 'gsap';
+import { ArrowDown } from 'lucide-react';
+
+export const Hero: React.FC = () => {
+ const containerRef = useRef(null);
+ const headingRef = useRef(null);
+ const subRef = useRef(null);
+ const badgeRef = useRef(null);
+
+ useEffect(() => {
+ const tl = gsap.timeline();
+
+ tl.fromTo(
+ badgeRef.current,
+ { opacity: 0, y: 20 },
+ { opacity: 1, y: 0, duration: 0.8, ease: 'power3.out', delay: 0.2 }
+ )
+ .fromTo(
+ headingRef.current,
+ { opacity: 0, y: 60 },
+ { opacity: 1, y: 0, duration: 1.2, ease: 'power3.out' },
+ "-=0.4"
+ )
+ .fromTo(
+ subRef.current,
+ { opacity: 0, y: 40 },
+ { opacity: 1, y: 0, duration: 1, ease: 'power3.out' },
+ "-=0.8"
+ );
+
+ }, []);
+
+ return (
+
+ {/* Background Gradients */}
+
+
+
+
+ Next Generation Agency
+
+
+
+ ELEVATE
REALITY
+
+
+
+ We craft digital experiences that blur the line between the virtual and the tangible. Precision engineering meets cinematic design.
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/Version 2 of Cinematic Agency Portfolio 2/components/Navbar.tsx b/Version 2 of Cinematic Agency Portfolio 2/components/Navbar.tsx
new file mode 100644
index 0000000..085f431
--- /dev/null
+++ b/Version 2 of Cinematic Agency Portfolio 2/components/Navbar.tsx
@@ -0,0 +1,99 @@
+import React, { useEffect, useRef } from 'react';
+import gsap from 'gsap';
+import { Menu, X } from 'lucide-react';
+
+export const Navbar: React.FC = () => {
+ const navRef = useRef(null);
+ const [isOpen, setIsOpen] = React.useState(false);
+
+ useEffect(() => {
+ // Animate navbar in after a slight delay
+ gsap.fromTo(
+ navRef.current,
+ { y: -100, opacity: 0 },
+ { y: 0, opacity: 1, duration: 1, ease: 'power3.out', delay: 0.5 }
+ );
+ }, []);
+
+ const handleScroll = (e: React.MouseEvent, href: string) => {
+ e.preventDefault();
+ const targetId = href.replace('#', '');
+ const element = document.getElementById(targetId);
+
+ if (element) {
+ // Use globally exposed Lenis instance if available, otherwise fallback to native
+ const lenis = (window as any).lenis;
+ if (lenis) {
+ lenis.scrollTo(element, { duration: 1.5 });
+ } else {
+ element.scrollIntoView({ behavior: 'smooth' });
+ }
+ setIsOpen(false);
+ }
+ };
+
+ const navLinks = [
+ { name: 'Work', href: '#work' },
+ { name: 'Services', href: '#services' },
+ { name: 'About', href: '#about' },
+ { name: 'Contact', href: '#contact' },
+ ];
+
+ return (
+
+ );
+};
\ No newline at end of file
diff --git a/Version 2 of Cinematic Agency Portfolio 2/components/ProductCarousel.tsx b/Version 2 of Cinematic Agency Portfolio 2/components/ProductCarousel.tsx
new file mode 100644
index 0000000..1fdae8b
--- /dev/null
+++ b/Version 2 of Cinematic Agency Portfolio 2/components/ProductCarousel.tsx
@@ -0,0 +1,216 @@
+import React, { useState, useRef, useEffect } from 'react';
+import gsap from 'gsap';
+import { ArrowLeft, ArrowRight, ArrowUpRight } from 'lucide-react';
+
+interface ProductCarouselProps {
+ id?: string;
+}
+
+const products = [
+ {
+ id: 1,
+ category: "Hardware",
+ title: "Neuro-Core V1",
+ description: "The world's first biological processing unit designed for consumer-grade synthesis. Experience zero-latency computing.",
+ image: "https://images.unsplash.com/photo-1550751827-4bd374c3f58b?q=80&w=2070&auto=format&fit=crop"
+ },
+ {
+ id: 2,
+ category: "Interface",
+ title: "Haptic Suit Pro",
+ description: "Full-body sensory immersion. Feel the digital wind, the weight of data, and the texture of code in real-time.",
+ image: "https://images.unsplash.com/photo-1535378437327-b71280637040?q=80&w=2076&auto=format&fit=crop"
+ },
+ {
+ id: 3,
+ category: "Robotics",
+ title: "Sentinel Drone",
+ description: "Silent, efficient, and omnipresent. The ultimate tool for aerial data acquisition and environmental monitoring.",
+ image: "https://images.unsplash.com/photo-1473968512647-3e447244af8f?q=80&w=2070&auto=format&fit=crop"
+ }
+];
+
+export const ProductCarousel: React.FC = ({ id }) => {
+ const [currentIndex, setCurrentIndex] = useState(0);
+ const [isAnimating, setIsAnimating] = useState(false);
+
+ // Refs for animation targets
+ const slideRefs = useRef<(HTMLDivElement | null)[]>([]);
+ const textRefs = useRef<(HTMLDivElement | null)[]>([]);
+ const imageRefs = useRef<(HTMLImageElement | null)[]>([]);
+
+ useEffect(() => {
+ // Initial setup: Ensure only first slide is visible and set Z-indices
+ slideRefs.current.forEach((slide, index) => {
+ if (slide) {
+ gsap.set(slide, {
+ autoAlpha: index === 0 ? 1 : 0,
+ zIndex: index === 0 ? 10 : 0,
+ clipPath: 'none' // Reset any clips
+ });
+ }
+ });
+ }, []);
+
+ const goToSlide = (index: number, direction: 'next' | 'prev' = 'next') => {
+ if (isAnimating || index === currentIndex) return;
+ setIsAnimating(true);
+
+ const nextIndex = (index + products.length) % products.length;
+
+ const currentSlide = slideRefs.current[currentIndex];
+ const nextSlide = slideRefs.current[nextIndex];
+
+ const currentText = textRefs.current[currentIndex];
+ const nextText = textRefs.current[nextIndex];
+
+ const currentImage = imageRefs.current[currentIndex];
+ const nextImage = imageRefs.current[nextIndex];
+
+ if (!currentSlide || !nextSlide || !currentText || !nextText || !currentImage || !nextImage) return;
+
+ const tl = gsap.timeline({
+ onComplete: () => {
+ setCurrentIndex(nextIndex);
+ setIsAnimating(false);
+ // Clean up outgoing slide
+ gsap.set(currentSlide, { autoAlpha: 0, zIndex: 0, clipPath: 'none' });
+ }
+ });
+
+ // 1. Setup Z-Index to ensure next slide is on top
+ gsap.set(nextSlide, { autoAlpha: 1, zIndex: 20 });
+ gsap.set(currentSlide, { zIndex: 10 });
+
+ // 2. Define Clip Path Wipes (Cinematic Curtain Effect)
+ // Next: Wipe from Right to Left | Prev: Wipe from Left to Right
+ const clipRight = 'polygon(100% 0, 100% 0, 100% 100%, 100% 100%)';
+ const clipLeft = 'polygon(0 0, 0 0, 0 100%, 0 100%)';
+ const clipFull = 'polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)';
+
+ const initialClip = direction === 'next' ? clipRight : clipLeft;
+
+ gsap.set(nextSlide, { clipPath: initialClip });
+
+ // 3. Animate Outgoing Slide (Text Fade Out + Image Parallax)
+ const currentElements = Array.from(currentText.children);
+ tl.to(currentElements, {
+ y: -30,
+ opacity: 0,
+ stagger: 0.05,
+ duration: 0.5,
+ ease: "power2.in"
+ }, 0);
+
+ tl.to(currentImage, {
+ scale: 1.1,
+ filter: "brightness(0.4)", // Dim it down as it leaves
+ duration: 1.2,
+ ease: "power2.out"
+ }, 0);
+
+ // 4. Animate Incoming Slide (Wipe In + Image Scale Down)
+ tl.to(nextSlide, {
+ clipPath: clipFull,
+ duration: 1.2,
+ ease: "power4.inOut" // Smooth, dramatic easing
+ }, 0);
+
+ // Image scales down from 1.3 to 1 for a subtle "zoom out" feel
+ gsap.set(nextImage, { scale: 1.3, filter: "brightness(1)" });
+ tl.to(nextImage, {
+ scale: 1,
+ duration: 1.6,
+ ease: "power2.out"
+ }, 0);
+
+ // 5. Animate Incoming Text (Stagger In from bottom)
+ const nextElements = Array.from(nextText.children);
+ gsap.set(nextElements, { y: 60, opacity: 0 }); // Reset positions
+
+ tl.to(nextElements, {
+ y: 0,
+ opacity: 1,
+ stagger: 0.1,
+ duration: 1,
+ ease: "power3.out"
+ }, 0.5); // Start halfway through the wipe
+ };
+
+ const next = () => goToSlide(currentIndex + 1, 'next');
+ const prev = () => goToSlide(currentIndex - 1, 'prev');
+
+ const goToIndex = (idx: number) => {
+ if (idx === currentIndex) return;
+ const direction = idx > currentIndex ? 'next' : 'prev';
+ goToSlide(idx, direction);
+ };
+
+ return (
+
+ {products.map((product, index) => (
+ { slideRefs.current[index] = el; }}
+ className="absolute inset-0 w-full h-full"
+ >
+ {/* Image Background */}
+
+
![]()
{ imageRefs.current[index] = el; }}
+ src={product.image}
+ alt={product.title}
+ className="w-full h-full object-cover"
+ />
+
+ {/* Content Overlay */}
+
+
{ textRefs.current[index] = el; }} className="max-w-4xl">
+
+
+ {product.category}
+
+
+ {product.title}
+
+
+ {product.description}
+
+
+
+
+
+ ))}
+
+ {/* Navigation Controls */}
+
+
+ {/* Progress Indicators */}
+
+ {products.map((_, idx) => (
+
+
+ )
+};
\ No newline at end of file
diff --git a/Version 2 of Cinematic Agency Portfolio 2/components/SectionWrapper.tsx b/Version 2 of Cinematic Agency Portfolio 2/components/SectionWrapper.tsx
new file mode 100644
index 0000000..d6fec50
--- /dev/null
+++ b/Version 2 of Cinematic Agency Portfolio 2/components/SectionWrapper.tsx
@@ -0,0 +1,41 @@
+import React, { useEffect, useRef } from 'react';
+import gsap from 'gsap';
+
+interface SectionWrapperProps {
+ children: React.ReactNode;
+ className?: string;
+ delay?: number;
+}
+
+export const SectionWrapper: React.FC = ({ children, className = "", delay = 0 }) => {
+ const ref = useRef(null);
+
+ useEffect(() => {
+ const element = ref.current;
+ if (!element) return;
+
+ gsap.fromTo(
+ element,
+ { opacity: 0, y: 60, scale: 0.98 },
+ {
+ opacity: 1,
+ y: 0,
+ scale: 1,
+ duration: 1.2,
+ ease: 'power3.out',
+ delay,
+ scrollTrigger: {
+ trigger: element,
+ start: 'top 85%', // Starts animation when top of element hits 85% of viewport
+ toggleActions: 'play none none reverse',
+ },
+ }
+ );
+ }, [delay]);
+
+ return (
+
+ {children}
+
+ );
+};
\ No newline at end of file
diff --git a/Version 2 of Cinematic Agency Portfolio 2/components/VisualSection.tsx b/Version 2 of Cinematic Agency Portfolio 2/components/VisualSection.tsx
new file mode 100644
index 0000000..ed32c92
--- /dev/null
+++ b/Version 2 of Cinematic Agency Portfolio 2/components/VisualSection.tsx
@@ -0,0 +1,72 @@
+import React, { useRef, useEffect } from 'react';
+import gsap from 'gsap';
+import { SectionWrapper } from './SectionWrapper';
+
+interface VisualSectionProps {
+ id?: string;
+ title: string;
+ description: string;
+ image: string;
+ alignment: 'left' | 'right';
+}
+
+export const VisualSection: React.FC = ({ id, title, description, image, alignment }) => {
+ const imgRef = useRef(null);
+ const containerRef = useRef(null);
+
+ useEffect(() => {
+ if (!imgRef.current || !containerRef.current) return;
+
+ // Parallax effect on image
+ gsap.fromTo(imgRef.current,
+ { scale: 1.1 },
+ {
+ scale: 1,
+ ease: 'none',
+ scrollTrigger: {
+ trigger: containerRef.current,
+ start: 'top bottom',
+ end: 'bottom top',
+ scrub: true,
+ }
+ }
+ );
+ }, []);
+
+ return (
+
+
+
+
+
+
+

+
+
+
+
+
+
+ {title}
+
+
+ {description}
+
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/Version 2 of Cinematic Agency Portfolio 2/index.html b/Version 2 of Cinematic Agency Portfolio 2/index.html
new file mode 100644
index 0000000..99d055b
--- /dev/null
+++ b/Version 2 of Cinematic Agency Portfolio 2/index.html
@@ -0,0 +1,77 @@
+
+
+
+
+
+ Agency | Cinematic Experience
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Version 2 of Cinematic Agency Portfolio 2/index.tsx b/Version 2 of Cinematic Agency Portfolio 2/index.tsx
new file mode 100644
index 0000000..6ca5361
--- /dev/null
+++ b/Version 2 of Cinematic Agency Portfolio 2/index.tsx
@@ -0,0 +1,15 @@
+import React from 'react';
+import ReactDOM from 'react-dom/client';
+import App from './App';
+
+const rootElement = document.getElementById('root');
+if (!rootElement) {
+ throw new Error("Could not find root element to mount to");
+}
+
+const root = ReactDOM.createRoot(rootElement);
+root.render(
+
+
+
+);
\ No newline at end of file
diff --git a/Version 2 of Cinematic Agency Portfolio 2/metadata.json b/Version 2 of Cinematic Agency Portfolio 2/metadata.json
new file mode 100644
index 0000000..9ea6c17
--- /dev/null
+++ b/Version 2 of Cinematic Agency Portfolio 2/metadata.json
@@ -0,0 +1,5 @@
+{
+ "name": "Copy of Cinematic Agency Portfolio",
+ "description": "A high-performance, scroll-driven agency website featuring smooth Lenis scrolling, GSAP animations, and a cinematic dark aesthetic.",
+ "requestFramePermissions": []
+}
\ No newline at end of file