111 lines
5.0 KiB
TypeScript
111 lines
5.0 KiB
TypeScript
import React, { useRef } from 'react';
|
|
import { motion, useScroll, useTransform } from 'framer-motion';
|
|
import { Dumbbell, Cpu, Utensils, TrendingUp } from 'lucide-react';
|
|
|
|
const STEPS = [
|
|
{
|
|
icon: Dumbbell,
|
|
title: "Input",
|
|
subtitle: "Log Training",
|
|
description: "You log your workout (e.g., Heavy Leg Day, 90 min).",
|
|
color: "bg-blue-500"
|
|
},
|
|
{
|
|
icon: Cpu,
|
|
title: "Process",
|
|
subtitle: "Analysis",
|
|
description: "The Co-Pilot analyzes your metabolic state and recovery needs.",
|
|
color: "bg-purple-500"
|
|
},
|
|
{
|
|
icon: Utensils,
|
|
title: "Output",
|
|
subtitle: "The Plan",
|
|
description: "You get a specific food target: 'Eat 60g Carbs + 40g Protein now.'",
|
|
color: "bg-primary-500"
|
|
},
|
|
{
|
|
icon: TrendingUp,
|
|
title: "Result",
|
|
subtitle: "Optimization",
|
|
description: "You wake up stronger, not fatter. Performance is prioritized.",
|
|
color: "bg-green-500"
|
|
}
|
|
];
|
|
|
|
export const Logic: React.FC = () => {
|
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
const { scrollYProgress } = useScroll({
|
|
target: containerRef,
|
|
offset: ["start end", "end start"]
|
|
});
|
|
|
|
const lineHeight = useTransform(scrollYProgress, [0, 0.8], ["0%", "100%"]);
|
|
|
|
return (
|
|
<section id="logic" className="py-32 bg-black relative overflow-hidden scroll-mt-32">
|
|
{/* Background Effects */}
|
|
<div className="absolute inset-0 bg-[radial-gradient(circle_at_top_right,_var(--tw-gradient-stops))] from-primary-900/10 via-black to-black pointer-events-none" />
|
|
|
|
<div className="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8 relative z-10">
|
|
<div className="text-center mb-20">
|
|
<h2 className="text-4xl md:text-6xl font-bold text-white mb-6 tracking-tighter">
|
|
The Logic
|
|
</h2>
|
|
<p className="text-xl text-gray-400 max-w-2xl mx-auto">
|
|
How FitMate turns your sweat into data, and data into direction.
|
|
</p>
|
|
</div>
|
|
|
|
<div ref={containerRef} className="relative">
|
|
{/* Connecting Line */}
|
|
<div className="absolute left-[28px] md:left-1/2 top-0 bottom-0 w-0.5 bg-white/10 md:-translate-x-1/2" />
|
|
<motion.div
|
|
style={{ height: lineHeight }}
|
|
className="absolute left-[28px] md:left-1/2 top-0 w-0.5 bg-gradient-to-b from-primary-500 via-purple-500 to-primary-500 md:-translate-x-1/2 shadow-[0_0_15px_rgba(34,211,238,0.5)]"
|
|
/>
|
|
|
|
<div className="space-y-12 md:space-y-24">
|
|
{STEPS.map((step, idx) => (
|
|
<motion.div
|
|
key={idx}
|
|
initial={{ opacity: 0, y: 50 }}
|
|
whileInView={{ opacity: 1, y: 0 }}
|
|
viewport={{ once: true, margin: "-100px" }}
|
|
transition={{ duration: 0.6, delay: idx * 0.1 }}
|
|
className={`relative flex flex-col md:flex-row gap-8 md:gap-16 items-start md:items-center ${idx % 2 === 0 ? 'md:flex-row-reverse' : ''}`}
|
|
>
|
|
{/* Content Card */}
|
|
<div className="flex-1 ml-16 md:ml-0 w-full md:w-auto">
|
|
<div className={`bg-surfaceHighlight/50 border border-white/10 p-6 rounded-2xl backdrop-blur-sm hover:border-primary-500/30 transition-colors duration-500 group w-full md:max-w-md ${idx % 2 === 0 ? 'mr-auto' : 'ml-auto'}`}>
|
|
<div className="flex items-center gap-3 mb-3">
|
|
<span className="text-xs font-mono text-gray-500 uppercase tracking-widest">Step 0{idx + 1}</span>
|
|
<span className="h-px flex-1 bg-white/10 group-hover:bg-primary-500/30 transition-colors" />
|
|
</div>
|
|
<h3 className="text-2xl font-bold text-white mb-1">{step.subtitle}</h3>
|
|
<h4 className="text-lg text-gray-400 mb-3">{step.title}</h4>
|
|
<p className="text-gray-400 leading-relaxed text-sm">
|
|
{step.description}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Icon Marker */}
|
|
<div className="absolute left-0 md:left-1/2 md:-translate-x-1/2 flex items-center justify-center w-14 h-14 rounded-full bg-black border-4 border-surface z-10">
|
|
<div className={`w-full h-full rounded-full flex items-center justify-center bg-surfaceHighlight border border-white/10 text-white relative overflow-hidden`}>
|
|
<div className={`absolute inset-0 opacity-20 ${step.color}`} />
|
|
<step.icon size={20} className="relative z-10" />
|
|
</div>
|
|
</div>
|
|
|
|
{/* Empty spacer for layout balance */}
|
|
<div className="hidden md:block flex-1" />
|
|
</motion.div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</section>
|
|
);
|
|
}; |