diff --git a/index.html b/index.html
new file mode 100644
index 0000000..7222255
--- /dev/null
+++ b/index.html
@@ -0,0 +1,517 @@
+
+
+
+
+
+ Eduardbodak Animated Cards | Codegrid
+
+
+
+
+
+
+
+
+
+ Plan
+ 01
+
+
+ 01
+ Plan
+
+
+
+
+
+ Design
+ 02
+
+
+ 02
+ Design
+
+
+
+
+
+ Develop
+ 03
+
+
+ 03
+ Develop
+
+
+
+
+
+ Test
+ 04
+
+
+ 04
+ Test
+
+
+
+
+
+ Launch
+ 05
+
+
+ 05
+ Launch
+
+
+
+
+
+ Support
+ 06
+
+
+ 06
+ Support
+
+
+
+
+
+
+
+
+ Keep scrolling β it gets good
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Plan
+ 01
+
+
+ 01
+ Plan
+
+
+
+
+ Plan
+ 01
+
+
+
Discovery
+
Audit
+
User Flow
+
Site Map
+
Personas
+
Strategy
+
+
+ 01
+ Plan
+
+
+
+
+
+
+
+
+
+
+
+ Design
+ 02
+
+
+ 02
+ Design
+
+
+
+
+ Design
+ 02
+
+
+
Wireframes
+
UI Kits
+
Prototypes
+
Visual Style
+
Interaction
+
Design QA
+
+
+ 02
+ Design
+
+
+
+
+
+
+
+
+
+
+
+ Develop
+ 03
+
+
+ 03
+ Develop
+
+
+
+
+ Develop
+ 03
+
+
+
HTML/CSS/JS
+
CMS Build
+
GSAP Motion
+
Responsive
+
Optimization
+
Launch
+
+
+ 03
+ Develop
+
+
+
+
+
+
+
+
+
+
+
+ Test
+ 04
+
+
+ 04
+ Test
+
+
+
+
+ Test
+ 04
+
+
+
QA
+
Accessibility
+
Debugging
+
+
+ 04
+ Test
+
+
+
+
+
+
+
+
+
+
+
+ Launch
+ 05
+
+
+ 05
+ Launch
+
+
+
+
+ Launch
+ 05
+
+
+
Deploy
+
SEO
+
Analytics
+
+
+ 05
+ Launch
+
+
+
+
+
+
+
+
+
+
+
+ Support
+ 06
+
+
+ 06
+ Support
+
+
+
+
+ Support
+ 06
+
+
+
Maintenance
+
Updates
+
Monitoring
+
+
+ 06
+ Support
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Plan
+ 01
+
+
+ 01
+ Plan
+
+
+
+
+ Plan
+ 01
+
+
+
Discovery
+
Audit
+
User Flow
+
Site Map
+
Personas
+
Strategy
+
+
+ 01
+ Plan
+
+
+
+
+
+
+
+
+
+
+
+ Design
+ 02
+
+
+ 02
+ Design
+
+
+
+
+ Design
+ 02
+
+
+
Wireframes
+
UI Kits
+
Prototypes
+
Visual Style
+
Interaction
+
Design QA
+
+
+ 02
+ Design
+
+
+
+
+
+
+
+
+
+
+
+ Develop
+ 03
+
+
+ 03
+ Develop
+
+
+
+
+ Develop
+ 03
+
+
+
HTML/CSS/JS
+
CMS Build
+
GSAP Motion
+
Responsive
+
Optimization
+
Launch
+
+
+ 03
+ Develop
+
+
+
+
+
+
+
+
+
+
+
+ Test
+ 04
+
+
+ 04
+ Test
+
+
+
+
+ Test
+ 04
+
+
+
QA
+
Accessibility
+
Debugging
+
+
+ 04
+ Test
+
+
+
+
+
+
+
+
+
+
+
+ Launch
+ 05
+
+
+ 05
+ Launch
+
+
+
+
+ Launch
+ 05
+
+
+
Deploy
+
SEO
+
Analytics
+
+
+ 05
+ Launch
+
+
+
+
+
+
+
+
+
+
+
+ Support
+ 06
+
+
+ 06
+ Support
+
+
+
+
+ Support
+ 06
+
+
+
Maintenance
+
Updates
+
Monitoring
+
+
+ 06
+ Support
+
+
+
+
+
+
+
+
+
+ The story's not over yet
+
+
+
+
+
\ No newline at end of file
diff --git a/script.js b/script.js
new file mode 100644
index 0000000..7424985
--- /dev/null
+++ b/script.js
@@ -0,0 +1,223 @@
+import gsap from "gsap";
+import { ScrollTrigger } from "gsap/ScrollTrigger";
+import Lenis from "lenis";
+
+document.addEventListener("DOMContentLoaded", () => {
+ gsap.registerPlugin(ScrollTrigger);
+
+ const lenis = new Lenis();
+ lenis.on("scroll", ScrollTrigger.update);
+ gsap.ticker.add((time) => {
+ lenis.raf(time * 1000);
+ });
+ gsap.ticker.lagSmoothing(0);
+
+ const smoothStep = (p) => p * p * (3 - 2 * p);
+
+ if (window.innerWidth > 1000) {
+ ScrollTrigger.create({
+ trigger: ".hero",
+ start: "top top",
+ end: "75% top",
+ scrub: 1,
+ onUpdate: (self) => {
+ const progress = self.progress;
+
+ const heroCardsContainerOpacity = gsap.utils.interpolate(
+ 1,
+ 0.5,
+ smoothStep(progress)
+ );
+ gsap.set(".hero-cards", {
+ opacity: heroCardsContainerOpacity,
+ });
+
+ ["#hero-card-1", "#hero-card-2", "#hero-card-3", "#hero-card-4", "#hero-card-5","#hero-card-6"].forEach(
+ (cardId, index) => {
+ const delay = index * 0.9;
+ const cardProgress = gsap.utils.clamp(
+ 0,
+ 1,
+ (progress - delay * 0.1) / (1 - delay * 0.1)
+ );
+
+ const y = gsap.utils.interpolate(
+ "0%",
+ "350%",
+ smoothStep(cardProgress)
+ );
+ const scale = gsap.utils.interpolate(
+ 1,
+ 0.75,
+ smoothStep(cardProgress)
+ );
+
+ const spreadX = ["50%", "20%", "0%", "0%","-20%", "-50%"]; // π μΆκ°: μΉ΄λ μμ λ°λΌ μ’μ° μμΉ μ§μ
+ const spreadRotate = [-30, -20, -5, 5, 20, 30]; // π μΆκ°: μΉ΄λ μμ λ°λΌ νμ μ§μ
+
+ let x = gsap.utils.interpolate("0%", spreadX[index], smoothStep(cardProgress)); // π μμ ν¨
+ let rotation = gsap.utils.interpolate(0, spreadRotate[index], smoothStep(cardProgress));
+
+
+ gsap.set(cardId, {
+ y: y,
+ x: x,
+ rotation: rotation,
+ scale: scale,
+ });
+ }
+ );
+ },
+ });
+
+ ScrollTrigger.create({
+ trigger: ".services",
+ start: "top top",
+ end: `+=${window.innerHeight * 4}px`,
+ pin: ".services",
+ pinSpacing: true,
+ });
+
+ ScrollTrigger.create({
+ trigger: ".services",
+ start: "top top",
+ end: `+=${window.innerHeight * 4}px`,
+ onLeave: () => {
+ const servicesSection = document.querySelector(".services");
+ const servicesRect = servicesSection.getBoundingClientRect();
+ const servicesTop = window.pageYOffset + servicesRect.top;
+
+ gsap.set(".cards", {
+ position: "absolute",
+ top: servicesTop,
+ left: 0,
+ width: "100vw",
+ height: "100vh",
+ });
+ },
+ onEnterBack: () => {
+ gsap.set(".cards", {
+ position: "fixed",
+ top: 0,
+ left: 0,
+ width: "100vw",
+ height: "100vh",
+ });
+ },
+ });
+
+ ScrollTrigger.create({
+ trigger: ".services",
+ start: "top bottom",
+ end: `+=${window.innerHeight * 4}`,
+ scrub: 1,
+ onUpdate: (self) => {
+ const progress = self.progress;
+
+ const headerProgress = gsap.utils.clamp(0, 1, progress / 0.9);
+ const headerY = gsap.utils.interpolate(
+ "400%",
+ "0%",
+ smoothStep(headerProgress)
+ );
+ gsap.set(".services-header", {
+ y: headerY,
+ });
+
+ ["#card-1", "#card-2", "#card-3", "#card-4", "#card-5", "#card-6"].forEach((cardId, index) => {
+ // λμΉμ μΈ delay ν¨ν΄: μ€μμμ λ°κΉ₯μͺ½μΌλ‘ λνλκ² νκΈ°
+ const delayPattern = [2.5, 1.5, 0.5, 0, 1, 2]; // μΉ΄λ 3,4κ° λ¨Όμ , κ·Έ λ€μ 2,5, λ§μ§λ§μ 1,6
+ const delay = delayPattern[index];
+
+ const cardProgress = gsap.utils.clamp(
+ 0,
+ 1,
+ (progress - delay * 0.1) / (0.9 - delay * 0.1)
+ );
+
+ const innerCard = document.querySelector(
+ `${cardId} .flip-card-inner`
+ );
+
+ let y;
+ if (cardProgress < 0.4) {
+ const normalizedProgress = cardProgress / 0.4;
+ y = gsap.utils.interpolate(
+ "-100%",
+ "50%",
+ smoothStep(normalizedProgress)
+ );
+ } else if (cardProgress < 0.6) {
+ const normalizedProgress = (cardProgress - 0.4) / 0.2;
+ y = gsap.utils.interpolate(
+ "50%",
+ "0%",
+ smoothStep(normalizedProgress)
+ );
+ } else {
+ y = "0%";
+ }
+
+ let scale;
+ if (cardProgress < 0.4) {
+ const normalizedProgress = cardProgress / 0.4;
+ scale = gsap.utils.interpolate(
+ 0.25,
+ 0.75,
+ smoothStep(normalizedProgress)
+ );
+ } else if (cardProgress < 0.6) {
+ const normalizedProgress = (cardProgress - 0.4) / 0.2;
+ scale = gsap.utils.interpolate(
+ 0.75,
+ 1,
+ smoothStep(normalizedProgress)
+ );
+ } else {
+ scale = 1;
+ }
+
+ let opacity;
+ if (cardProgress < 0.2) {
+ const normalizedProgress = cardProgress / 0.2;
+ opacity = smoothStep(normalizedProgress);
+ } else {
+ opacity = 1;
+ }
+
+ const spreadX = ["200%", "100%", "50%", "-50%","-100%", "-200%"]; // μΉ΄λλ€μ΄ νΌμ³μ§ μμΉ
+ const spreadRotate = [-10, -6, 2, -2, 6, 10];
+
+
+ let x, rotate, rotationY;
+ if (cardProgress < 0.6) {
+ x = spreadX[index];
+ rotate = spreadRotate[index];
+ rotationY = 0;
+ } else if (cardProgress < 1) {
+ const normalized = smoothStep((cardProgress - 0.6) / 0.4);
+ x = gsap.utils.interpolate(spreadX[index], "0%", normalized);
+ rotate = gsap.utils.interpolate(spreadRotate[index], 0, normalized);
+ rotationY = normalized * 180;
+ } else {
+ x = "0%";
+ rotate = 0;
+ rotationY = 180;
+ }
+
+ gsap.set(cardId, {
+ opacity: opacity,
+ y: y,
+ x: x,
+ rotate: rotate,
+ scale: scale,
+ });
+
+ gsap.set(innerCard, {
+ rotationY: rotationY,
+ });
+ });
+ },
+ });
+ }
+});
\ No newline at end of file