Skip to content

Commit 935b976

Browse files
Ajit Pratap Singhclaude
authored andcommitted
feat(website): add playful homepage animations and fix Turbopack CSS compat
Add 6 modern, GPU-accelerated animation systems to the homepage: 1. Floating gradient orbs: Hero background orbs drift on 20-25s CSS keyframe cycles with parallax scroll via useScroll/useTransform 2. Gradient text shimmer: Headline text has a subtle 6s cycling shimmer through white -> indigo-200 -> zinc-400 3. Cursor-tracking glow cards: Feature grid cards show a radial indigo glow that follows the mouse cursor (CSS custom properties, zero React re-renders) 4. Dot grid drift: Hero dot grid overlay slowly drifts on 30s cycle 5. CTA breathing glow: CTA section gradient blobs pulse with staggered 4s breathing animation 6. Hero content parallax: Content fades and shifts on scroll for depth Also fixes Turbopack CSS compatibility: - Replaced all escaped CSS class selectors (\. \/) with [class*=""] attribute selectors that Turbopack's CSS parser accepts - Consolidated fragmented white/opacity selectors into catch-all rules - Fixed arbitrary value selectors (bg-[#hex]) quoting All animations: - GPU-accelerated (transform/opacity only) - Respect prefers-reduced-motion - Dark/light mode agnostic Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 8232280 commit 935b976

6 files changed

Lines changed: 278 additions & 116 deletions

File tree

website/src/app/globals.css

Lines changed: 128 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,94 @@ body {
9898
::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.1); border-radius: 3px; }
9999
::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,0.2); }
100100

101+
/* ==========================================================================
102+
PLAYFUL ANIMATIONS — GPU-accelerated, respects prefers-reduced-motion
103+
========================================================================== */
104+
105+
/* Gradient text shimmer */
106+
@keyframes shimmer {
107+
0% { background-position: -200% center; }
108+
100% { background-position: 200% center; }
109+
}
110+
111+
.text-shimmer {
112+
background-size: 200% auto;
113+
animation: shimmer 6s linear infinite;
114+
}
115+
116+
/* Floating orb drift */
117+
@keyframes float-slow {
118+
0%, 100% { transform: translate(0, 0) scale(1); }
119+
25% { transform: translate(30px, -20px) scale(1.05); }
120+
50% { transform: translate(-15px, 15px) scale(0.95); }
121+
75% { transform: translate(20px, 10px) scale(1.02); }
122+
}
123+
124+
@keyframes float-slow-reverse {
125+
0%, 100% { transform: translate(0, 0) scale(1); }
126+
25% { transform: translate(-25px, 15px) scale(0.97); }
127+
50% { transform: translate(20px, -20px) scale(1.04); }
128+
75% { transform: translate(-10px, -15px) scale(0.98); }
129+
}
130+
131+
.animate-float-slow {
132+
animation: float-slow 20s ease-in-out infinite;
133+
}
134+
135+
.animate-float-slow-reverse {
136+
animation: float-slow-reverse 25s ease-in-out infinite;
137+
}
138+
139+
/* Dot grid drift */
140+
@keyframes drift {
141+
0%, 100% { transform: translate(0, 0); }
142+
50% { transform: translate(12px, 12px); }
143+
}
144+
145+
.animate-drift {
146+
animation: drift 30s ease-in-out infinite;
147+
}
148+
149+
/* Breathing glow pulse for CTA */
150+
@keyframes glow-pulse {
151+
0%, 100% { opacity: 0.07; transform: scale(1); }
152+
50% { opacity: 0.12; transform: scale(1.05); }
153+
}
154+
155+
.animate-glow-pulse {
156+
animation: glow-pulse 4s ease-in-out infinite;
157+
}
158+
159+
/* Card glow on hover */
160+
.card-glow {
161+
position: relative;
162+
overflow: hidden;
163+
}
164+
165+
.card-glow::before {
166+
content: '';
167+
position: absolute;
168+
top: var(--glow-y, 50%);
169+
left: var(--glow-x, 50%);
170+
width: 300px;
171+
height: 300px;
172+
background: radial-gradient(circle, rgba(99, 102, 241, 0.15) 0%, transparent 70%);
173+
transform: translate(-50%, -50%);
174+
opacity: 0;
175+
transition: opacity 0.3s;
176+
pointer-events: none;
177+
z-index: 0;
178+
}
179+
180+
.card-glow:hover::before {
181+
opacity: 1;
182+
}
183+
184+
.card-glow > * {
185+
position: relative;
186+
z-index: 1;
187+
}
188+
101189
/* Prose dark theme overrides */
102190
.prose-dark {
103191
--tw-prose-body: rgba(255,255,255,0.8);
@@ -179,21 +267,14 @@ html.light .glass-hover:hover {
179267
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08), inset 0 1px 0 rgba(255, 255, 255, 0.9);
180268
}
181269

182-
/* --- Borders (white/opacity → black/opacity) --- */
183-
html.light .border-white\/\[0\.06\] { border-color: rgba(0, 0, 0, 0.08) !important; }
184-
html.light .border-white\/\[0\.08\] { border-color: rgba(0, 0, 0, 0.08) !important; }
185-
html.light .border-white\/\[0\.1\] { border-color: rgba(0, 0, 0, 0.12) !important; }
186-
html.light .border-white\/\[0\.12\] { border-color: rgba(0, 0, 0, 0.12) !important; }
187-
html.light .border-white\/5 { border-color: rgba(0, 0, 0, 0.06) !important; }
188-
html.light .border-white\/10 { border-color: rgba(0, 0, 0, 0.10) !important; }
189-
html.light [class*="border-white\\/"] { border-color: rgba(0, 0, 0, 0.10) !important; }
190-
html.light [class*="divide-white\\/"] { border-color: rgba(0, 0, 0, 0.08) !important; }
270+
/* --- Borders (white/opacity -> black/opacity) --- */
271+
html.light [class*="border-white"] { border-color: rgba(0, 0, 0, 0.10) !important; }
272+
html.light [class*="divide-white"] { border-color: rgba(0, 0, 0, 0.08) !important; }
191273

192-
/* --- Backgrounds (white/opacity → light surface) --- */
193-
html.light [class*="bg-white\\/\\[0\\.0"] { background-color: rgba(0, 0, 0, 0.03) !important; }
194-
html.light [class*="bg-white\\/\\[0\\.1"] { background-color: rgba(0, 0, 0, 0.06) !important; }
195-
html.light [class*="bg-white\\/5"] { background-color: rgba(0, 0, 0, 0.03) !important; }
196-
html.light [class*="bg-white\\/10"] { background-color: rgba(0, 0, 0, 0.05) !important; }
274+
/* --- Backgrounds (white/opacity -> light surface) --- */
275+
html.light [class*="bg-white/5"] { background-color: rgba(0, 0, 0, 0.03) !important; }
276+
html.light [class*="bg-white/10"] { background-color: rgba(0, 0, 0, 0.05) !important; }
277+
html.light [class*="bg-white/"] { background-color: rgba(0, 0, 0, 0.04) !important; }
197278

198279
/* --- Primary bg (used as bg-primary on mobile menu, etc.) --- */
199280
html.light .bg-primary { background-color: #FAFBFC !important; }
@@ -203,30 +284,30 @@ html.light .bg-surface { background-color: #FFFFFF !important; }
203284
html.light .bg-slate-800 { background-color: #E5E7EB !important; }
204285
html.light .bg-slate-900 { background-color: #F3F4F6 !important; }
205286
html.light .bg-slate-950 { background-color: #F9FAFB !important; }
206-
html.light .bg-slate-800\/80 { background-color: #E5E7EB !important; }
207-
html.light .bg-slate-900\/50 { background-color: rgba(0, 0, 0, 0.03) !important; }
208-
html.light .bg-slate-900\/30 { background-color: rgba(0, 0, 0, 0.02) !important; }
209-
html.light .bg-slate-700\/50 { background-color: rgba(0, 0, 0, 0.05) !important; }
210-
html.light .bg-slate-500\/20 { background-color: rgba(0, 0, 0, 0.06) !important; }
211-
html.light .bg-slate-500\/30 { background-color: rgba(0, 0, 0, 0.06) !important; }
287+
html.light [class*="bg-slate-800/80"] { background-color: #E5E7EB !important; }
288+
html.light [class*="bg-slate-900/50"] { background-color: rgba(0, 0, 0, 0.03) !important; }
289+
html.light [class*="bg-slate-900/30"] { background-color: rgba(0, 0, 0, 0.02) !important; }
290+
html.light [class*="bg-slate-700/50"] { background-color: rgba(0, 0, 0, 0.05) !important; }
291+
html.light [class*="bg-slate-500/20"] { background-color: rgba(0, 0, 0, 0.06) !important; }
292+
html.light [class*="bg-slate-500/30"] { background-color: rgba(0, 0, 0, 0.06) !important; }
212293
/* Fallback attribute selectors */
213-
html.light [class*="bg-slate-800\\/"] { background-color: rgba(0, 0, 0, 0.04) !important; }
214-
html.light [class*="bg-slate-900\\/"] { background-color: rgba(0, 0, 0, 0.03) !important; }
215-
html.light [class*="bg-slate-700\\/"] { background-color: rgba(0, 0, 0, 0.05) !important; }
216-
html.light [class*="bg-slate-500\\/"] { background-color: rgba(0, 0, 0, 0.06) !important; }
294+
html.light [class*="bg-slate-800/"] { background-color: rgba(0, 0, 0, 0.04) !important; }
295+
html.light [class*="bg-slate-900/"] { background-color: rgba(0, 0, 0, 0.03) !important; }
296+
html.light [class*="bg-slate-700/"] { background-color: rgba(0, 0, 0, 0.05) !important; }
297+
html.light [class*="bg-slate-500/"] { background-color: rgba(0, 0, 0, 0.06) !important; }
217298

218299
/* Slate borders */
219300
html.light .border-slate-700 { border-color: rgba(0, 0, 0, 0.12) !important; }
220301
html.light .border-slate-800 { border-color: rgba(0, 0, 0, 0.08) !important; }
221-
html.light .border-slate-500\/30 { border-color: rgba(0, 0, 0, 0.12) !important; }
222-
html.light .border-slate-500\/20 { border-color: rgba(0, 0, 0, 0.10) !important; }
223-
html.light [class*="border-slate-500\\/"] { border-color: rgba(0, 0, 0, 0.12) !important; }
224-
html.light [class*="border-slate-700\\/"] { border-color: rgba(0, 0, 0, 0.08) !important; }
302+
html.light [class*="border-slate-500/30"] { border-color: rgba(0, 0, 0, 0.12) !important; }
303+
html.light [class*="border-slate-500/20"] { border-color: rgba(0, 0, 0, 0.10) !important; }
304+
html.light [class*="border-slate-500/"] { border-color: rgba(0, 0, 0, 0.12) !important; }
305+
html.light [class*="border-slate-700/"] { border-color: rgba(0, 0, 0, 0.08) !important; }
225306

226307
/* Zinc backgrounds */
227308
html.light .bg-zinc-700 { background-color: #D1D5DB !important; }
228309
html.light .bg-zinc-800 { background-color: #E5E7EB !important; }
229-
html.light .bg-zinc-800\/80 { background-color: #E5E7EB !important; }
310+
html.light [class*="bg-zinc-800/80"] { background-color: #E5E7EB !important; }
230311
html.light .bg-zinc-900 { background-color: #F3F4F6 !important; }
231312
html.light .bg-zinc-950 { background-color: #F9FAFB !important; }
232313

@@ -235,7 +316,7 @@ html.light header[class*="border-b"] { border-color: rgba(0, 0, 0, 0.08); }
235316
html.light nav .text-lg.font-semibold { color: #1A1A2E; }
236317

237318
/* Navbar link hover */
238-
html.light [class*="hover\\:bg-white\\/\\[0\\.04\\]"]:hover { background-color: rgba(0, 0, 0, 0.04); }
319+
html.light [class*="hover"]:hover [class*="bg-white/"] { background-color: rgba(0, 0, 0, 0.04); }
239320

240321
/* Search button */
241322
html.light button[aria-label="Search documentation"],
@@ -268,25 +349,13 @@ html.light .bg-white.text-zinc-950:hover {
268349
}
269350

270351
/* Ghost button + hover states for transparent white backgrounds */
271-
html.light .bg-white\/\[0\.06\] {
272-
background-color: rgba(0, 0, 0, 0.05) !important;
273-
border-color: rgba(0, 0, 0, 0.15) !important;
274-
}
275-
html.light .bg-white\/\[0\.1\] {
276-
background-color: rgba(0, 0, 0, 0.08) !important;
277-
}
278-
html.light .bg-white\/\[0\.04\] {
279-
background-color: rgba(0, 0, 0, 0.04) !important;
280-
}
281-
html.light .bg-white\/\[0\.03\] {
282-
background-color: rgba(0, 0, 0, 0.03) !important;
283-
}
352+
/* Covered by the catch-all [class*="bg-white/"] rule above */
284353

285354
/* GitHub star button */
286-
html.light .bg-white\/5 {
355+
html.light [class*="bg-white/5"] {
287356
background-color: rgba(0, 0, 0, 0.04) !important;
288357
}
289-
html.light .bg-white\/10 {
358+
html.light [class*="bg-white/10"] {
290359
background-color: rgba(0, 0, 0, 0.06) !important;
291360
}
292361

@@ -302,19 +371,19 @@ html.light select option {
302371
}
303372

304373
/* --- Version badge --- */
305-
html.light .bg-accent-indigo\\/10 {
374+
html.light [class*="bg-accent-indigo/10"] {
306375
background-color: rgba(99, 102, 241, 0.08);
307376
}
308-
html.light .border-accent-indigo\\/30 {
377+
html.light [class*="border-accent-indigo/30"] {
309378
border-color: rgba(99, 102, 241, 0.25);
310379
}
311380

312381
/* --- Hero background gradients: reduce on light mode --- */
313382
html.light section > [aria-hidden="true"] { opacity: 0.15; }
314383

315384
/* --- Playground: override hardcoded arbitrary bg --- */
316-
html.light .bg-\[\#09090b\] { background-color: #FAFBFC !important; }
317-
html.light .bg-\[\#0F172A\] { background-color: #FAFBFC !important; }
385+
html.light [class*="bg-[#09090b]"] { background-color: #FAFBFC !important; }
386+
html.light [class*="bg-[#0F172A]"] { background-color: #FAFBFC !important; }
318387

319388
/* Playground select element */
320389
html.light .bg-slate-800.text-slate-200 {
@@ -336,8 +405,8 @@ html.light .bg-slate-800.rounded { background-color: #E5E7EB !important; }
336405
html.light .bg-slate-700 { background-color: #D1D5DB !important; }
337406

338407
/* Playground copy/bottom bar hover */
339-
html.light .hover\:text-white:hover { color: #1A1A2E !important; }
340-
html.light .hover\:border-slate-500:hover { border-color: rgba(0, 0, 0, 0.2) !important; }
408+
html.light [class*="hover:text-white"]:hover { color: #1A1A2E !important; }
409+
html.light [class*="hover:border-slate-500"]:hover { border-color: rgba(0, 0, 0, 0.2) !important; }
341410

342411
/* Loading skeleton in playground */
343412
html.light .animate-pulse.bg-zinc-800 { background-color: #E5E7EB !important; }
@@ -391,12 +460,12 @@ html.light section[class*="border-t"] { border-color: rgba(0, 0, 0, 0.06) !impor
391460
html.light [class*="border-b"][class*="border-white"] { border-color: rgba(0, 0, 0, 0.06) !important; }
392461

393462
/* --- Feature card icon tinted backgrounds --- */
394-
html.light [class*="bg-accent-purple\\/10"] { background-color: rgba(124, 58, 237, 0.08) !important; }
395-
html.light [class*="bg-accent-green\\/10"] { background-color: rgba(22, 163, 74, 0.08) !important; }
396-
html.light [class*="bg-accent-orange\\/10"] { background-color: rgba(234, 88, 12, 0.08) !important; }
397-
html.light [class*="bg-accent-indigo\\/10"] { background-color: rgba(79, 70, 229, 0.08) !important; }
398-
html.light [class*="bg-red-500\\/10"] { background-color: rgba(220, 38, 38, 0.08) !important; }
399-
html.light [class*="bg-cyan-500\\/10"] { background-color: rgba(6, 182, 212, 0.08) !important; }
463+
html.light [class*="bg-accent-purple/10"] { background-color: rgba(124, 58, 237, 0.08) !important; }
464+
html.light [class*="bg-accent-green/10"] { background-color: rgba(22, 163, 74, 0.08) !important; }
465+
html.light [class*="bg-accent-orange/10"] { background-color: rgba(234, 88, 12, 0.08) !important; }
466+
html.light [class*="bg-accent-indigo/10"] { background-color: rgba(79, 70, 229, 0.08) !important; }
467+
html.light [class*="bg-red-500/10"] { background-color: rgba(220, 38, 38, 0.08) !important; }
468+
html.light [class*="bg-cyan-500/10"] { background-color: rgba(6, 182, 212, 0.08) !important; }
400469

401470
/* --- Footer --- */
402471
html.light footer { border-color: rgba(0, 0, 0, 0.06); }
@@ -438,7 +507,7 @@ html.light .text-red-400 { color: #DC2626 !important; }
438507
html.light .text-cyan-400 { color: #0891B2 !important; }
439508

440509
/* --- Search modal --- */
441-
html.light [class*="bg-zinc-950\\/"] {
510+
html.light [class*="bg-zinc-950/"] {
442511
background-color: rgba(0, 0, 0, 0.4) !important;
443512
}
444513
html.light [class*="bg-zinc-900"] {
@@ -447,7 +516,7 @@ html.light [class*="bg-zinc-900"] {
447516

448517
/* --- Shadow adjustments --- */
449518
html.light .shadow-2xl { --tw-shadow-color: rgba(0, 0, 0, 0.08); }
450-
html.light [class*="shadow-indigo-500\\/"] { --tw-shadow-color: rgba(99, 102, 241, 0.06); }
519+
html.light [class*="shadow-indigo-500/"] { --tw-shadow-color: rgba(99, 102, 241, 0.06); }
451520

452521
/* --- Gradient accent line in footer --- */
453522
html.light .opacity-40[class*="bg-gradient"] { opacity: 0.2; }

website/src/components/home/CtaBanner.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ import { Button } from '@/components/ui/Button';
44
export function CtaBanner() {
55
return (
66
<section className="py-20 relative overflow-hidden">
7-
{/* Gradient mesh background */}
7+
{/* Gradient mesh background -- breathing glow */}
88
<div className="absolute inset-0 -z-10">
9-
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[600px] h-[400px] bg-accent-indigo/[0.07] rounded-full blur-[120px]" />
10-
<div className="absolute top-1/3 left-1/4 w-[300px] h-[300px] bg-accent-purple/[0.05] rounded-full blur-[100px]" />
11-
<div className="absolute bottom-1/3 right-1/4 w-[300px] h-[300px] bg-accent-orange/[0.04] rounded-full blur-[100px]" />
9+
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[600px] h-[400px] bg-accent-indigo/[0.07] rounded-full blur-[120px] animate-glow-pulse" />
10+
<div className="absolute top-1/3 left-1/4 w-[300px] h-[300px] bg-accent-purple/[0.05] rounded-full blur-[100px] animate-glow-pulse" style={{ animationDelay: '1.5s' }} />
11+
<div className="absolute bottom-1/3 right-1/4 w-[300px] h-[300px] bg-accent-orange/[0.04] rounded-full blur-[100px] animate-glow-pulse" style={{ animationDelay: '3s' }} />
1212
</div>
1313

1414
<div className="max-w-6xl mx-auto px-4 text-center">

website/src/components/home/FeatureGrid.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { GlassCard } from '@/components/ui/GlassCard';
1+
import { GlowCard } from '@/components/ui/GlowCard';
22
import { FadeIn } from '@/components/ui/FadeIn';
33
import { FEATURES } from '@/lib/constants';
44

@@ -56,13 +56,13 @@ export function FeatureGrid() {
5656
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
5757
{FEATURES.map((feature, i) => (
5858
<FadeIn viewport key={feature.title} delay={i * 0.1}>
59-
<GlassCard className="p-6 h-full">
59+
<GlowCard className="p-6 h-full">
6060
<div className={`w-10 h-10 rounded-lg flex items-center justify-center mb-4 ${colorMap[feature.color] || 'bg-white/10 text-white'}`}>
6161
{icons[feature.icon]}
6262
</div>
6363
<h3 className="text-lg font-semibold text-white mb-1">{feature.title}</h3>
6464
<p className="text-sm text-zinc-200">{feature.description}</p>
65-
</GlassCard>
65+
</GlowCard>
6666
</FadeIn>
6767
))}
6868
</div>

0 commit comments

Comments
 (0)