feat: enhance 3D floating particles and geometric shapes; improve background animations and parallax effects
This commit is contained in:
469
src/App.tsx
469
src/App.tsx
@@ -143,32 +143,87 @@ function ParallaxContainer({ children, depth = 1, className = '' }: ParallaxCont
|
||||
)
|
||||
}
|
||||
|
||||
// Floating Particles Background
|
||||
// Enhanced 3D Floating Particles Background
|
||||
function FloatingParticles() {
|
||||
const particles = Array.from({ length: 50 }, (_, i) => i)
|
||||
const particles = Array.from({ length: 30 }, (_, i) => i)
|
||||
|
||||
return (
|
||||
<div className="absolute inset-0 overflow-hidden pointer-events-none">
|
||||
{particles.map((i) => (
|
||||
{particles.map((i) => {
|
||||
const size = Math.random() * 3 + 1
|
||||
const depth = Math.random() * 4 + 1
|
||||
return (
|
||||
<motion.div
|
||||
key={i}
|
||||
className="absolute rounded-full bg-gradient-to-br from-primary-400/10 to-secondary-400/10 backdrop-blur-sm"
|
||||
style={{
|
||||
width: `${size}px`,
|
||||
height: `${size}px`,
|
||||
left: `${Math.random() * 100}%`,
|
||||
top: `${Math.random() * 100}%`,
|
||||
transformStyle: 'preserve-3d'
|
||||
}}
|
||||
animate={{
|
||||
y: [-30, -120, -30],
|
||||
x: [-15, 15, -15],
|
||||
z: [0, depth * 20, 0],
|
||||
opacity: [0.3, 0.8, 0.3],
|
||||
scale: [0.8, 1.2, 0.8]
|
||||
}}
|
||||
transition={{
|
||||
duration: Math.random() * 15 + 8,
|
||||
repeat: Infinity,
|
||||
delay: Math.random() * 3,
|
||||
ease: "easeInOut"
|
||||
}}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// 3D Geometric Shapes Component
|
||||
function Floating3DShapes() {
|
||||
const shapes = [
|
||||
{ type: 'cube', color: 'from-primary-500/15 to-primary-600/15', size: 12 },
|
||||
{ type: 'sphere', color: 'from-secondary-500/15 to-secondary-600/15', size: 16 },
|
||||
{ type: 'pyramid', color: 'from-primary-400/15 to-secondary-500/15', size: 14 },
|
||||
]
|
||||
|
||||
return (
|
||||
<div className="absolute inset-0 overflow-hidden pointer-events-none">
|
||||
{shapes.map((shape, i) => Array.from({ length: 3 }, (_, j) => (
|
||||
<motion.div
|
||||
key={i}
|
||||
className="absolute w-1 h-1 bg-primary-400/20 rounded-full"
|
||||
key={`${shape.type}-${i}-${j}`}
|
||||
className={`absolute bg-gradient-to-br ${shape.color} backdrop-blur-sm ${
|
||||
shape.type === 'cube' ? 'rounded-sm' :
|
||||
shape.type === 'sphere' ? 'rounded-full' : 'rounded-sm'
|
||||
}`}
|
||||
style={{
|
||||
left: `${Math.random() * 100}%`,
|
||||
top: `${Math.random() * 100}%`,
|
||||
width: `${shape.size}px`,
|
||||
height: `${shape.size}px`,
|
||||
left: `${(i * 30 + j * 15 + 10) % 90}%`,
|
||||
top: `${(i * 25 + j * 20 + 15) % 80}%`,
|
||||
transformStyle: 'preserve-3d',
|
||||
filter: 'blur(0.5px)'
|
||||
}}
|
||||
animate={{
|
||||
y: [-20, -100, -20],
|
||||
x: [-10, 10, -10],
|
||||
opacity: [0, 1, 0],
|
||||
rotateX: [0, 360],
|
||||
rotateY: [0, 360],
|
||||
rotateZ: shape.type === 'pyramid' ? [0, 180, 360] : 0,
|
||||
z: [0, 60, 0],
|
||||
y: [-20, 20, -20]
|
||||
}}
|
||||
transition={{
|
||||
duration: Math.random() * 10 + 5,
|
||||
duration: 20 + i * 5,
|
||||
repeat: Infinity,
|
||||
delay: Math.random() * 2,
|
||||
delay: j * 2,
|
||||
ease: "linear"
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -466,12 +521,32 @@ function Hero() {
|
||||
|
||||
return (
|
||||
<section ref={containerRef} className="relative isolate overflow-hidden min-h-screen flex items-center">
|
||||
{/* 3D Background Layer */}
|
||||
{/* Enhanced 3D Background Layers */}
|
||||
<motion.div
|
||||
className="absolute inset-0 bg-gradient-to-br from-primary-50/50 via-white to-secondary-50/50 dark:from-gray-900/50 dark:via-gray-800/50 dark:to-gray-900/50"
|
||||
className="absolute inset-0 bg-gradient-to-br from-primary-50/30 via-white to-secondary-50/30 dark:from-gray-900/30 dark:via-gray-800/30 dark:to-gray-900/30"
|
||||
style={{ y: backgroundY }}
|
||||
>
|
||||
<FloatingParticles />
|
||||
|
||||
{/* Animated depth gradient */}
|
||||
<motion.div
|
||||
className="absolute inset-0 opacity-20"
|
||||
animate={{
|
||||
background: [
|
||||
"radial-gradient(800px 400px at 20% 30%, rgba(147, 51, 234, 0.1), transparent)",
|
||||
"radial-gradient(600px 300px at 80% 60%, rgba(59, 130, 246, 0.1), transparent)",
|
||||
"radial-gradient(700px 350px at 50% 20%, rgba(147, 51, 234, 0.1), transparent)"
|
||||
]
|
||||
}}
|
||||
transition={{ duration: 15, repeat: Infinity, ease: "easeInOut" }}
|
||||
/>
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
className="absolute inset-0"
|
||||
style={{ y: useTransform(scrollYProgress, [0, 1], ['0%', '30%']) }}
|
||||
>
|
||||
<Floating3DShapes />
|
||||
</motion.div>
|
||||
|
||||
{/* Content Layer with Parallax */}
|
||||
@@ -519,43 +594,135 @@ function Hero() {
|
||||
</ParallaxContainer>
|
||||
</motion.div>
|
||||
|
||||
{/* 3D Floating Elements */}
|
||||
<div className="absolute inset-0 pointer-events-none">
|
||||
{/* 3D Scroll Indicator */}
|
||||
<motion.div
|
||||
className="absolute bottom-8 left-1/2 -translate-x-1/2 hidden lg:block"
|
||||
animate={{
|
||||
y: [0, 10, 0],
|
||||
rotateX: [0, 15, 0]
|
||||
}}
|
||||
transition={{ duration: 2, repeat: Infinity, ease: "easeInOut" }}
|
||||
style={{ transformStyle: 'preserve-3d' }}
|
||||
>
|
||||
<div className="flex flex-col items-center gap-2 text-neutral-400 dark:text-neutral-500">
|
||||
<span className="text-sm font-medium">Scroll to explore</span>
|
||||
<motion.div
|
||||
animate={{ y: [0, 5, 0] }}
|
||||
transition={{ duration: 1.5, repeat: Infinity, ease: "easeInOut" }}
|
||||
>
|
||||
<ArrowRight className="h-5 w-5 rotate-90" />
|
||||
</motion.div>
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
{/* Enhanced 3D Icon Elements with More Visibility */}
|
||||
<div className="absolute inset-0 pointer-events-none z-0">
|
||||
{/* Top layer - more visible and engaging */}
|
||||
<motion.div
|
||||
className="absolute top-20 left-10 text-primary-300 dark:text-primary-600"
|
||||
className="absolute top-1/4 left-[8%] text-primary-400/80 dark:text-primary-500/80 hidden lg:block"
|
||||
animate={{
|
||||
y: [-10, 10, -10],
|
||||
y: [-15, 15, -15],
|
||||
rotateY: [0, 360],
|
||||
z: [0, 50, 0]
|
||||
z: [0, 50, 0],
|
||||
scale: [0.8, 1.2, 0.8]
|
||||
}}
|
||||
transition={{ duration: 6, repeat: Infinity, ease: "easeInOut" }}
|
||||
style={{ transformStyle: 'preserve-3d' }}
|
||||
style={{
|
||||
transformStyle: 'preserve-3d',
|
||||
filter: 'drop-shadow(0 4px 8px rgba(0,0,0,0.1))'
|
||||
}}
|
||||
>
|
||||
<Heart className="h-8 w-8" />
|
||||
</motion.div>
|
||||
|
||||
{/* Additional floating heart */}
|
||||
<motion.div
|
||||
className="absolute top-32 right-20 text-secondary-300 dark:text-secondary-600"
|
||||
className="absolute top-1/3 right-1/4 text-rose-300/70 dark:text-rose-400/70 hidden xl:block"
|
||||
animate={{
|
||||
y: [10, -10, 10],
|
||||
rotateX: [0, 180, 360],
|
||||
z: [0, 30, 0]
|
||||
rotateZ: [-15, 15, -15],
|
||||
scale: [1, 1.3, 1]
|
||||
}}
|
||||
transition={{ duration: 4, repeat: Infinity, ease: "easeInOut", delay: 1 }}
|
||||
style={{ transformStyle: 'preserve-3d' }}
|
||||
>
|
||||
<Sparkles className="h-6 w-6" />
|
||||
<Heart className="h-5 w-5" />
|
||||
</motion.div>
|
||||
|
||||
{/* Right side - more prominent sparkles */}
|
||||
<motion.div
|
||||
className="absolute bottom-32 left-20 text-primary-300 dark:text-primary-600"
|
||||
className="absolute top-1/3 right-[12%] text-secondary-400/80 dark:text-secondary-500/80 hidden xl:block"
|
||||
animate={{
|
||||
y: [-8, 8, -8],
|
||||
rotateZ: [0, 180, 360],
|
||||
z: [0, 40, 0]
|
||||
y: [20, -20, 20],
|
||||
rotateX: [0, 180, 360],
|
||||
z: [0, 40, 0],
|
||||
scale: [0.9, 1.4, 0.9]
|
||||
}}
|
||||
transition={{ duration: 8, repeat: Infinity, ease: "easeInOut", delay: 2 }}
|
||||
transition={{ duration: 5, repeat: Infinity, ease: "easeInOut", delay: 1.5 }}
|
||||
style={{
|
||||
transformStyle: 'preserve-3d',
|
||||
filter: 'drop-shadow(0 2px 4px rgba(0,0,0,0.1))'
|
||||
}}
|
||||
>
|
||||
<Sparkles className="h-7 w-7" />
|
||||
</motion.div>
|
||||
|
||||
{/* Additional floating sparkle */}
|
||||
<motion.div
|
||||
className="absolute top-1/2 right-[20%] text-yellow-300/60 dark:text-yellow-400/60 hidden lg:block"
|
||||
animate={{
|
||||
rotate: [0, 360],
|
||||
y: [-8, 8, -8],
|
||||
scale: [0.7, 1.1, 0.7]
|
||||
}}
|
||||
transition={{ duration: 8, repeat: Infinity, ease: "easeInOut", delay: 3 }}
|
||||
>
|
||||
<Sparkles className="h-4 w-4" />
|
||||
</motion.div>
|
||||
|
||||
{/* Bottom area - enhanced users icon */}
|
||||
<motion.div
|
||||
className="absolute bottom-1/4 left-[15%] text-primary-400/70 dark:text-primary-500/70 hidden lg:block"
|
||||
animate={{
|
||||
y: [-12, 12, -12],
|
||||
rotateZ: [0, 180, 360],
|
||||
z: [0, 45, 0],
|
||||
scale: [0.8, 1.2, 0.8]
|
||||
}}
|
||||
transition={{ duration: 7, repeat: Infinity, ease: "easeInOut", delay: 3 }}
|
||||
style={{
|
||||
transformStyle: 'preserve-3d',
|
||||
filter: 'drop-shadow(0 3px 6px rgba(0,0,0,0.1))'
|
||||
}}
|
||||
>
|
||||
<Users className="h-6 w-6" />
|
||||
</motion.div>
|
||||
|
||||
{/* Additional community icon */}
|
||||
<motion.div
|
||||
className="absolute bottom-1/3 right-[8%] text-blue-300/60 dark:text-blue-400/60 hidden xl:block"
|
||||
animate={{
|
||||
x: [-5, 5, -5],
|
||||
y: [8, -8, 8],
|
||||
rotateY: [0, 180, 360]
|
||||
}}
|
||||
transition={{ duration: 9, repeat: Infinity, ease: "easeInOut", delay: 4.5 }}
|
||||
>
|
||||
<Users className="h-4 w-4" />
|
||||
</motion.div>
|
||||
|
||||
{/* Additional subtle elements */}
|
||||
<motion.div
|
||||
className="absolute top-1/2 right-[8%] text-primary-100/40 dark:text-primary-800/40 hidden xl:block"
|
||||
animate={{
|
||||
rotate: [0, 360],
|
||||
scale: [0.8, 1.2, 0.8],
|
||||
z: [0, 20, 0]
|
||||
}}
|
||||
transition={{ duration: 12, repeat: Infinity, ease: "easeInOut", delay: 4 }}
|
||||
style={{ transformStyle: 'preserve-3d' }}
|
||||
>
|
||||
<Users className="h-7 w-7" />
|
||||
<Star className="h-4 w-4" />
|
||||
</motion.div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -647,12 +814,38 @@ function Programs() {
|
||||
]
|
||||
|
||||
return (
|
||||
<section id="programs" className="relative py-20">
|
||||
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||
<SectionHeader eyebrow="What we do" title="Practical, student-first programs" subtitle="Flexible help that meets families where they are." />
|
||||
<section id="programs" className="relative py-20 overflow-hidden">
|
||||
{/* Background 3D Elements */}
|
||||
<div className="absolute inset-0 pointer-events-none">
|
||||
<motion.div
|
||||
className="absolute top-10 right-10 w-32 h-32 bg-gradient-to-br from-primary-100/20 to-secondary-100/20 rounded-full blur-xl"
|
||||
animate={{
|
||||
y: [-20, 20, -20],
|
||||
x: [-10, 10, -10],
|
||||
scale: [0.8, 1.1, 0.8]
|
||||
}}
|
||||
transition={{ duration: 15, repeat: Infinity, ease: "easeInOut" }}
|
||||
/>
|
||||
<motion.div
|
||||
className="absolute bottom-20 left-10 w-24 h-24 bg-gradient-to-br from-secondary-100/20 to-primary-100/20 rounded-full blur-xl"
|
||||
animate={{
|
||||
y: [15, -15, 15],
|
||||
x: [8, -8, 8],
|
||||
scale: [1, 0.9, 1]
|
||||
}}
|
||||
transition={{ duration: 12, repeat: Infinity, ease: "easeInOut", delay: 2 }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 relative z-10">
|
||||
<ParallaxContainer depth={0.2}>
|
||||
<SectionHeader eyebrow="What we do" title="Practical, student-first programs" subtitle="Flexible help that meets families where they are." />
|
||||
</ParallaxContainer>
|
||||
<div className="mt-10 grid gap-6 md:grid-cols-3">
|
||||
{items.map((i, idx) => (
|
||||
<FeatureCard key={idx} icon={i.icon} title={i.title} body={i.body} />
|
||||
<ParallaxContainer key={idx} depth={0.3 + idx * 0.1}>
|
||||
<FeatureCard icon={i.icon} title={i.title} body={i.body} />
|
||||
</ParallaxContainer>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
@@ -688,23 +881,48 @@ function Impact() {
|
||||
|
||||
return (
|
||||
<section id="impact" className="relative py-24 overflow-hidden">
|
||||
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||
<ParallaxContainer depth={0.3}>
|
||||
{/* Enhanced Background Elements */}
|
||||
<div className="absolute inset-0 pointer-events-none">
|
||||
<motion.div
|
||||
className="absolute top-1/4 left-0 w-40 h-40 bg-gradient-to-br from-primary-200/10 via-secondary-200/10 to-primary-300/10 rounded-full blur-2xl"
|
||||
animate={{
|
||||
x: [-50, 50, -50],
|
||||
y: [-25, 25, -25],
|
||||
scale: [0.8, 1.2, 0.8],
|
||||
rotate: [0, 180, 360]
|
||||
}}
|
||||
transition={{ duration: 20, repeat: Infinity, ease: "easeInOut" }}
|
||||
/>
|
||||
<motion.div
|
||||
className="absolute bottom-1/4 right-0 w-56 h-56 bg-gradient-to-bl from-secondary-200/10 via-primary-200/10 to-secondary-300/10 rounded-full blur-2xl"
|
||||
animate={{
|
||||
x: [30, -30, 30],
|
||||
y: [20, -20, 20],
|
||||
scale: [1, 0.9, 1],
|
||||
rotate: [360, 180, 0]
|
||||
}}
|
||||
transition={{ duration: 25, repeat: Infinity, ease: "easeInOut", delay: 3 }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 relative z-10">
|
||||
<ParallaxContainer depth={0.2}>
|
||||
<SectionHeader eyebrow="Impact" title="Every gift moves a student forward" subtitle="Transparent, measurable outcomes powered by local partnerships." />
|
||||
</ParallaxContainer>
|
||||
|
||||
<div className="mt-12 grid gap-6 sm:grid-cols-2 lg:grid-cols-4">
|
||||
{stats.map((s, i) => (
|
||||
<ParallaxContainer key={i} depth={0.4 + i * 0.1}>
|
||||
<ParallaxContainer key={i} depth={0.3 + i * 0.05}>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
initial={{ opacity: 0, y: 30, rotateX: -15 }}
|
||||
whileInView={{ opacity: 1, y: 0, rotateX: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.6, delay: i * 0.1 }}
|
||||
transition={{ duration: 0.8, delay: i * 0.15 }}
|
||||
whileHover={{
|
||||
scale: 1.05,
|
||||
rotateY: 5,
|
||||
z: 50
|
||||
rotateY: 8,
|
||||
z: 60,
|
||||
boxShadow: "0 25px 50px -12px rgba(0, 0, 0, 0.25)"
|
||||
}}
|
||||
style={{ transformStyle: 'preserve-3d' }}
|
||||
>
|
||||
@@ -767,38 +985,143 @@ function HowItWorks() {
|
||||
]
|
||||
|
||||
return (
|
||||
<section id="how" className="relative py-24">
|
||||
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||
<SectionHeader eyebrow="How it works" title="Simple process, real results" subtitle="Designed with counselors, optimized for speed and dignity." />
|
||||
<section id="how" className="relative py-24 overflow-hidden">
|
||||
{/* Animated Background Elements */}
|
||||
<div className="absolute inset-0 pointer-events-none">
|
||||
<motion.div
|
||||
className="absolute top-16 right-1/4 w-3 h-3 bg-primary-300/40 dark:bg-primary-600/40 rounded-full"
|
||||
animate={{
|
||||
y: [-30, 30, -30],
|
||||
x: [-15, 15, -15],
|
||||
scale: [0.5, 1.5, 0.5],
|
||||
opacity: [0.3, 0.8, 0.3]
|
||||
}}
|
||||
transition={{ duration: 8, repeat: Infinity, ease: "easeInOut" }}
|
||||
/>
|
||||
<motion.div
|
||||
className="absolute bottom-20 left-1/3 w-2 h-2 bg-secondary-300/40 dark:bg-secondary-600/40 rounded-full"
|
||||
animate={{
|
||||
y: [20, -20, 20],
|
||||
x: [10, -10, 10],
|
||||
scale: [0.8, 1.2, 0.8],
|
||||
opacity: [0.4, 0.9, 0.4]
|
||||
}}
|
||||
transition={{ duration: 6, repeat: Infinity, ease: "easeInOut", delay: 2 }}
|
||||
/>
|
||||
<motion.div
|
||||
className="absolute top-1/3 left-1/5 w-4 h-4 bg-gradient-to-br from-primary-200/30 to-secondary-200/30 rounded-full blur-sm"
|
||||
animate={{
|
||||
rotate: [0, 360],
|
||||
scale: [0.6, 1.1, 0.6],
|
||||
y: [-10, 10, -10]
|
||||
}}
|
||||
transition={{ duration: 12, repeat: Infinity, ease: "easeInOut", delay: 4 }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 relative z-10">
|
||||
<ParallaxContainer depth={0.2}>
|
||||
<SectionHeader eyebrow="How it works" title="Simple process, real results" subtitle="Designed with counselors, optimized for speed and dignity." />
|
||||
</ParallaxContainer>
|
||||
<div className="mt-10 grid gap-6 md:grid-cols-2">
|
||||
<div className="card">
|
||||
<ol className="relative space-y-6">
|
||||
{steps.map((s, i) => (
|
||||
<li key={i} className="relative pl-8">
|
||||
<div className="absolute left-0 top-1 grid h-6 w-6 place-items-center rounded-full bg-gradient-to-br from-primary-500 to-secondary-600 text-white shadow text-xs">
|
||||
{i + 1}
|
||||
</div>
|
||||
<div className="font-medium">{s.title}</div>
|
||||
<p className="text-sm text-neutral-700 dark:text-neutral-300">{s.body}</p>
|
||||
</li>
|
||||
))}
|
||||
</ol>
|
||||
</div>
|
||||
<ParallaxContainer depth={0.3}>
|
||||
<motion.div
|
||||
className="card"
|
||||
initial={{ opacity: 0, rotateY: -15 }}
|
||||
whileInView={{ opacity: 1, rotateY: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.8 }}
|
||||
style={{ transformStyle: 'preserve-3d' }}
|
||||
>
|
||||
<ol className="relative space-y-6">
|
||||
{steps.map((s, i) => (
|
||||
<motion.li
|
||||
key={i}
|
||||
className="relative pl-8"
|
||||
initial={{ opacity: 0, x: -20 }}
|
||||
whileInView={{ opacity: 1, x: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.6, delay: i * 0.15 }}
|
||||
whileHover={{
|
||||
x: 5,
|
||||
transition: { duration: 0.2 }
|
||||
}}
|
||||
>
|
||||
<motion.div
|
||||
className="absolute left-0 top-1 grid h-6 w-6 place-items-center rounded-full bg-gradient-to-br from-primary-500 to-secondary-600 text-white shadow text-xs"
|
||||
whileHover={{
|
||||
scale: 1.1,
|
||||
rotateY: 180,
|
||||
boxShadow: "0 4px 8px rgba(0,0,0,0.2)"
|
||||
}}
|
||||
style={{ transformStyle: 'preserve-3d' }}
|
||||
>
|
||||
{i + 1}
|
||||
</motion.div>
|
||||
<div className="font-medium">{s.title}</div>
|
||||
<p className="text-sm text-neutral-700 dark:text-neutral-300">{s.body}</p>
|
||||
</motion.li>
|
||||
))}
|
||||
</ol>
|
||||
</motion.div>
|
||||
</ParallaxContainer>
|
||||
<div className="grid gap-6">
|
||||
<div className="rounded-2xl border border-emerald-500/20 bg-emerald-500/10 p-6">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="grid h-10 w-10 place-items-center rounded-xl bg-emerald-500 text-white"><Heart className="h-5 w-5"/></div>
|
||||
<div className="font-semibold tracking-tight">Donor promise</div>
|
||||
</div>
|
||||
<p className="mt-2 text-sm text-emerald-900 dark:text-emerald-100">Your gift funds direct student needs first. We publish anonymized impact and receipts for transparency.</p>
|
||||
</div>
|
||||
<div className="rounded-2xl border border-secondary-500/20 bg-secondary-500/10 p-6">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="grid h-10 w-10 place-items-center rounded-xl bg-secondary-500 text-white"><Users className="h-5 w-5"/></div>
|
||||
<div className="font-semibold tracking-tight">For counselors</div>
|
||||
</div>
|
||||
<p className="mt-2 text-sm text-secondary-950 dark:text-secondary-100">One-page referral. No uploads required. We do the running so students don't miss class.</p>
|
||||
</div>
|
||||
<ParallaxContainer depth={0.4}>
|
||||
<motion.div
|
||||
className="rounded-2xl border border-emerald-500/20 bg-emerald-500/10 p-6"
|
||||
initial={{ opacity: 0, rotateX: 15, y: 20 }}
|
||||
whileInView={{ opacity: 1, rotateX: 0, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.7, delay: 0.2 }}
|
||||
whileHover={{
|
||||
scale: 1.02,
|
||||
rotateY: 3,
|
||||
z: 20,
|
||||
boxShadow: "0 8px 25px rgba(16, 185, 129, 0.15)"
|
||||
}}
|
||||
style={{ transformStyle: 'preserve-3d' }}
|
||||
>
|
||||
<div className="flex items-center gap-3">
|
||||
<motion.div
|
||||
className="grid h-10 w-10 place-items-center rounded-xl bg-emerald-500 text-white"
|
||||
whileHover={{ rotateY: 180, scale: 1.1 }}
|
||||
style={{ transformStyle: 'preserve-3d' }}
|
||||
>
|
||||
<Heart className="h-5 w-5"/>
|
||||
</motion.div>
|
||||
<div className="font-semibold tracking-tight">Donor promise</div>
|
||||
</div>
|
||||
<p className="mt-2 text-sm text-emerald-900 dark:text-emerald-100">Your gift funds direct student needs first. We publish anonymized impact and receipts for transparency.</p>
|
||||
</motion.div>
|
||||
</ParallaxContainer>
|
||||
<ParallaxContainer depth={0.5}>
|
||||
<motion.div
|
||||
className="rounded-2xl border border-secondary-500/20 bg-secondary-500/10 p-6"
|
||||
initial={{ opacity: 0, rotateX: -15, y: 20 }}
|
||||
whileInView={{ opacity: 1, rotateX: 0, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.7, delay: 0.4 }}
|
||||
whileHover={{
|
||||
scale: 1.02,
|
||||
rotateY: -3,
|
||||
z: 20,
|
||||
boxShadow: "0 8px 25px rgba(147, 51, 234, 0.15)"
|
||||
}}
|
||||
style={{ transformStyle: 'preserve-3d' }}
|
||||
>
|
||||
<div className="flex items-center gap-3">
|
||||
<motion.div
|
||||
className="grid h-10 w-10 place-items-center rounded-xl bg-secondary-500 text-white"
|
||||
whileHover={{ rotateY: 180, scale: 1.1 }}
|
||||
style={{ transformStyle: 'preserve-3d' }}
|
||||
>
|
||||
<Users className="h-5 w-5"/>
|
||||
</motion.div>
|
||||
<div className="font-semibold tracking-tight">For counselors</div>
|
||||
</div>
|
||||
<p className="mt-2 text-sm text-secondary-950 dark:text-secondary-100">One-page referral. No uploads required. We do the running so students don't miss class.</p>
|
||||
</motion.div>
|
||||
</ParallaxContainer>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user