fix: uniform subtle minimal animations across all Pro tier and dashboard pages

This commit is contained in:
2026-10-23 16:56:49 +05:30
parent 43f23a9d92
commit eb3f4e719c
26 changed files with 62 additions and 49 deletions

View File

@@ -105,7 +105,7 @@ export default function AIComCBTDPPPage() {
return ( return (
<div className="p-6 md:p-8 space-y-6 max-w-6xl mx-auto min-h-screen"> <div className="p-6 md:p-8 space-y-6 max-w-6xl mx-auto min-h-screen">
{/* Top Header */} {/* Top Header */}
<div className="flex flex-col md:flex-row md:items-center justify-between gap-4 bg-secondary/20 border border-border p-6 rounded-3xl backdrop-blur-xl"> <div className="flex flex-col md:flex-row md:items-center justify-between gap-4 bg-secondary/20 border border-border p-6 rounded-3xl backdrop-blur-xl animate-section animate-section-1">
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
<Link href="/dashboard/dpp"> <Link href="/dashboard/dpp">
<Button variant="outline" size="icon" className="rounded-xl border-border hover:bg-secondary"> <Button variant="outline" size="icon" className="rounded-xl border-border hover:bg-secondary">
@@ -166,7 +166,7 @@ export default function AIComCBTDPPPage() {
)} )}
{/* Main CBT Grid */} {/* Main CBT Grid */}
<div className="grid grid-cols-1 lg:grid-cols-4 gap-6"> <div className="grid grid-cols-1 lg:grid-cols-4 gap-6 animate-section animate-section-2">
{/* Question Area */} {/* Question Area */}
<div className="lg:col-span-3"> <div className="lg:col-span-3">
<Card className="border-border bg-background/80 backdrop-blur-xl p-6 rounded-3xl shadow-xl space-y-6"> <Card className="border-border bg-background/80 backdrop-blur-xl p-6 rounded-3xl shadow-xl space-y-6">

View File

@@ -132,7 +132,7 @@ export default function DPPPage() {
const cleanTitle = (title: string) => title.replace(/\s*\(ExamEnum\.[^)]+\)/, ''); const cleanTitle = (title: string) => title.replace(/\s*\(ExamEnum\.[^)]+\)/, '');
return ( return (
<div className="p-8 space-y-6 animate-in fade-in zoom-in-95 origin-top duration-500 max-w-7xl mx-auto"> <div className="p-8 space-y-6 max-w-7xl mx-auto">
<div className="flex flex-col md:flex-row md:items-center justify-between p-8 bg-gradient-to-r from-secondary/50 to-background border border-border rounded-2xl shadow-sm gap-6"> <div className="flex flex-col md:flex-row md:items-center justify-between p-8 bg-gradient-to-r from-secondary/50 to-background border border-border rounded-2xl shadow-sm gap-6">
<div> <div>
<h1 className="text-3xl md:text-4xl font-black tracking-tight flex items-center gap-3 mb-2"> <h1 className="text-3xl md:text-4xl font-black tracking-tight flex items-center gap-3 mb-2">

View File

@@ -89,7 +89,7 @@ export default function CollegePredictorPage() {
const trendData = isDemo ? DEMO_TREND_DATA : ZERO_TREND_DATA const trendData = isDemo ? DEMO_TREND_DATA : ZERO_TREND_DATA
return ( return (
<div className="p-6 md:p-8 space-y-8 animate-in fade-in zoom-in-95 origin-top duration-500 max-w-7xl mx-auto min-h-screen"> <div className="p-6 md:p-8 space-y-8 max-w-7xl mx-auto min-h-screen">
{/* Page Header */} {/* Page Header */}
<div className="border-b border-border/50 pb-6 animate-section animate-section-1"> <div className="border-b border-border/50 pb-6 animate-section animate-section-1">
<div className="flex items-start justify-between gap-4 flex-wrap"> <div className="flex items-start justify-between gap-4 flex-wrap">

View File

@@ -35,7 +35,7 @@ export default function HeatmapPage() {
const criticalTopics = isDemo ? DEMO_CRITICAL_TOPICS : [] const criticalTopics = isDemo ? DEMO_CRITICAL_TOPICS : []
return ( return (
<div className="p-6 md:p-8 max-w-7xl mx-auto space-y-8 min-h-screen animate-in fade-in zoom-in-95 origin-top duration-500"> <div className="p-6 md:p-8 max-w-7xl mx-auto space-y-8 min-h-screen">
{/* Page Header */} {/* Page Header */}
<div className="border-b border-border/50 pb-6 animate-section animate-section-1"> <div className="border-b border-border/50 pb-6 animate-section animate-section-1">
<div className="flex items-start justify-between gap-4 flex-wrap"> <div className="flex items-start justify-between gap-4 flex-wrap">

View File

@@ -89,7 +89,7 @@ export default function AICoachDashboard() {
const currentStreakDays = `${user?.streak_count || (isDemo ? 12 : 1)} d` const currentStreakDays = `${user?.streak_count || (isDemo ? 12 : 1)} d`
return ( return (
<div className="p-6 max-w-6xl mx-auto space-y-8 animate-in fade-in zoom-in-95 origin-top duration-500"> <div className="p-6 max-w-6xl mx-auto space-y-8">
{/* ── METRICS BAR ── */} {/* ── METRICS BAR ── */}
<div className="flex flex-wrap items-center justify-end gap-2 pt-2 animate-section animate-section-1"> <div className="flex flex-wrap items-center justify-end gap-2 pt-2 animate-section animate-section-1">

View File

@@ -32,7 +32,7 @@ export default function ReadinessPage() {
const maxScore = Math.max(1, ...scoreHistory.map(d => d.score)) const maxScore = Math.max(1, ...scoreHistory.map(d => d.score))
return ( return (
<div className="p-6 md:p-8 space-y-8 animate-in fade-in zoom-in-95 origin-top duration-500 max-w-7xl mx-auto min-h-screen"> <div className="p-6 md:p-8 space-y-8 max-w-7xl mx-auto min-h-screen">
{/* Page Header */} {/* Page Header */}
<div className="border-b border-border/50 pb-6 animate-section animate-section-1"> <div className="border-b border-border/50 pb-6 animate-section animate-section-1">
<div className="flex items-start justify-between gap-4 flex-wrap"> <div className="flex items-start justify-between gap-4 flex-wrap">

View File

@@ -24,7 +24,7 @@ export default function StrategyPage() {
const negMarkingData = isDemo ? DEMO_NEG_MARKING_DATA : ZERO_NEG_MARKING_DATA const negMarkingData = isDemo ? DEMO_NEG_MARKING_DATA : ZERO_NEG_MARKING_DATA
return ( return (
<div className="p-6 md:p-8 space-y-8 animate-in fade-in zoom-in-95 origin-top duration-500 max-w-7xl mx-auto min-h-screen"> <div className="p-6 md:p-8 space-y-8 max-w-7xl mx-auto min-h-screen">
{/* Page Header */} {/* Page Header */}
<div className="border-b border-border/50 pb-6 animate-section animate-section-1"> <div className="border-b border-border/50 pb-6 animate-section animate-section-1">
<div className="flex items-start justify-between gap-4 flex-wrap"> <div className="flex items-start justify-between gap-4 flex-wrap">

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import { StudyPlanCard } from "@/components/AI/StudyPlanCard" import { StudyPlanCard } from "@/components/AI/StudyPlanCard"
import { WeeklyProgressReport } from "@/components/AI/WeeklyProgressReport" import { WeeklyProgressReport } from "@/components/AI/WeeklyProgressReport"
@@ -12,7 +12,7 @@ export default function StudyPlanPage() {
const streakCount = user?.streak_count || (isDemo ? 12 : 1) const streakCount = user?.streak_count || (isDemo ? 12 : 1)
return ( return (
<div className="p-6 md:p-8 space-y-8 animate-in fade-in zoom-in-95 origin-top duration-500 max-w-7xl mx-auto min-h-screen"> <div className="p-6 md:p-8 space-y-8 max-w-7xl mx-auto min-h-screen">
{/* Page Header */} {/* Page Header */}
<div className="border-b border-border/50 pb-6 animate-section animate-section-1"> <div className="border-b border-border/50 pb-6 animate-section animate-section-1">
<div className="flex items-start justify-between gap-4 flex-wrap"> <div className="flex items-start justify-between gap-4 flex-wrap">
@@ -34,7 +34,7 @@ export default function StudyPlanPage() {
</div> </div>
{/* KPI Strip */} {/* KPI Strip */}
<div className="grid grid-cols-2 md:grid-cols-4 gap-4 animate-section animate-section-1"> <div className="grid grid-cols-2 md:grid-cols-4 gap-4 animate-section animate-section-2">
{[ {[
{ label: "Tasks Today", value: isDemo ? "5" : "3", sub: isDemo ? "2 completed" : "0 completed", icon: <CheckCircle2 size={18} className="text-green-400" />, color: "border-green-400/20 bg-green-400/5" }, { label: "Tasks Today", value: isDemo ? "5" : "3", sub: isDemo ? "2 completed" : "0 completed", icon: <CheckCircle2 size={18} className="text-green-400" />, color: "border-green-400/20 bg-green-400/5" },
{ label: "Study Hours Today", value: isDemo ? "3.8 hrs" : "0.0 hrs", sub: "Target: 5 hrs", icon: <Clock size={18} className="text-[var(--cyan-ai)]" />, color: "border-[var(--cyan-ai-20)] bg-[var(--cyan-ai-10)]" }, { label: "Study Hours Today", value: isDemo ? "3.8 hrs" : "0.0 hrs", sub: "Target: 5 hrs", icon: <Clock size={18} className="text-[var(--cyan-ai)]" />, color: "border-[var(--cyan-ai-20)] bg-[var(--cyan-ai-10)]" },
@@ -52,7 +52,7 @@ export default function StudyPlanPage() {
))} ))}
</div> </div>
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8 animate-section animate-section-2"> <div className="grid grid-cols-1 lg:grid-cols-3 gap-8 animate-section animate-section-3">
<div className="lg:col-span-2 space-y-8"> <div className="lg:col-span-2 space-y-8">
{/* Today's Schedule */} {/* Today's Schedule */}
<div className="space-y-3"> <div className="space-y-3">

View File

@@ -69,7 +69,7 @@ export default function TimeOptimizationPage() {
] ]
return ( return (
<div className="p-6 md:p-8 max-w-7xl mx-auto space-y-8 min-h-screen animate-in fade-in zoom-in-95 origin-top duration-500"> <div className="p-6 md:p-8 max-w-7xl mx-auto space-y-8 min-h-screen">
{/* Page Header */} {/* Page Header */}
<div className="border-b border-border/50 pb-6 animate-section animate-section-1"> <div className="border-b border-border/50 pb-6 animate-section animate-section-1">
<div className="flex items-start justify-between gap-4 flex-wrap"> <div className="flex items-start justify-between gap-4 flex-wrap">

View File

@@ -1,12 +1,12 @@
"use client" "use client"
import { TutorChat } from "@/components/AI/TutorChat" import { TutorChat } from "@/components/AI/TutorChat"
import { BrainCircuit, Sparkles } from "lucide-react" import { BrainCircuit, Sparkles } from "lucide-react"
export default function TutorChatPage() { export default function TutorChatPage() {
return ( return (
<div className="h-[calc(100vh-100px)] w-full flex flex-col pt-4 max-w-7xl mx-auto px-4 gap-4 animate-in fade-in zoom-in-95 origin-top duration-500"> <div className="h-[calc(100vh-100px)] w-full flex flex-col pt-4 max-w-7xl mx-auto px-4 gap-4">
<div className="border-b border-border/50 pb-4"> <div className="border-b border-border/50 pb-4 animate-section animate-section-1">
<div className="flex items-start justify-between gap-4 flex-wrap"> <div className="flex items-start justify-between gap-4 flex-wrap">
<div> <div>
<h1 className="text-3xl md:text-4xl font-black tracking-tight flex items-center gap-3 mb-1"> <h1 className="text-3xl md:text-4xl font-black tracking-tight flex items-center gap-3 mb-1">
@@ -26,7 +26,7 @@ export default function TutorChatPage() {
</div> </div>
</div> </div>
</div> </div>
<div className="flex-1 rounded-3xl overflow-hidden border border-border/50 shadow-xl bg-background flex flex-col h-full"> <div className="flex-1 rounded-3xl overflow-hidden border border-border/50 shadow-xl bg-background flex flex-col h-full animate-section animate-section-2">
<TutorChat /> <TutorChat />
</div> </div>
</div> </div>

View File

@@ -41,7 +41,7 @@ export default function WeeklyProgressPage() {
const syllabusProgress = isDemo ? DEMO_SYLLABUS_PROGRESS : ZERO_SYLLABUS_PROGRESS const syllabusProgress = isDemo ? DEMO_SYLLABUS_PROGRESS : ZERO_SYLLABUS_PROGRESS
return ( return (
<div className="p-6 md:p-8 max-w-7xl mx-auto space-y-8 min-h-screen animate-in fade-in zoom-in-95 origin-top duration-500"> <div className="p-6 md:p-8 max-w-7xl mx-auto space-y-8 min-h-screen">
{/* Page Header */} {/* Page Header */}
<div className="border-b border-border/50 pb-6 animate-section animate-section-1"> <div className="border-b border-border/50 pb-6 animate-section animate-section-1">
<div className="flex items-start justify-between gap-4 flex-wrap"> <div className="flex items-start justify-between gap-4 flex-wrap">

View File

@@ -58,7 +58,7 @@ export default function AnalyticsPage() {
return ( return (
<PremiumGate featureKey="detailed-performance-analytics"> <PremiumGate featureKey="detailed-performance-analytics">
<div className="p-8 space-y-8 animate-in fade-in zoom-in-95 origin-top duration-500 max-w-7xl mx-auto"> <div className="p-8 space-y-8 max-w-7xl mx-auto">
<div className="flex flex-col md:flex-row md:items-end justify-between gap-4 animate-section animate-section-1"> <div className="flex flex-col md:flex-row md:items-end justify-between gap-4 animate-section animate-section-1">
<div> <div>
<h1 className="text-3xl md:text-4xl font-black tracking-tight flex items-center gap-3 mb-1"> <h1 className="text-3xl md:text-4xl font-black tracking-tight flex items-center gap-3 mb-1">

View File

@@ -88,12 +88,12 @@ export default function AttemptHistoryPage({ params }: { params: Promise<{ attem
const maxScore = attempt.total_questions * 4; const maxScore = attempt.total_questions * 4;
return ( return (
<div className="max-w-6xl mx-auto p-8 animate-in fade-in zoom-in-95 origin-top duration-500"> <div className="max-w-6xl mx-auto p-8">
<Link href={backRoute} className="inline-flex items-center text-sm text-muted-foreground hover:text-foreground mb-6 transition-colors"> <Link href={backRoute} className="inline-flex items-center text-sm text-muted-foreground hover:text-foreground mb-6 transition-colors">
<ArrowLeft size={16} className="mr-2" /> {test?.type === 'DPS' ? 'Back to PrepPilot AI' : 'Back to Tests'} <ArrowLeft size={16} className="mr-2" /> {test?.type === 'DPS' ? 'Back to PrepPilot AI' : 'Back to Tests'}
</Link> </Link>
<div className="flex flex-col md:flex-row gap-8 mb-10"> <div className="flex flex-col md:flex-row gap-8 mb-10 animate-section animate-section-1">
<div className="flex-1"> <div className="flex-1">
<h1 className="text-3xl font-bold tracking-tight mb-2">{test?.title || 'Practice Test'} Solutions</h1> <h1 className="text-3xl font-bold tracking-tight mb-2">{test?.title || 'Practice Test'} Solutions</h1>
<p className="text-muted-foreground">Review your performance, detailed solutions, and identify your weak spots.</p> <p className="text-muted-foreground">Review your performance, detailed solutions, and identify your weak spots.</p>
@@ -127,7 +127,7 @@ export default function AttemptHistoryPage({ params }: { params: Promise<{ attem
</div> </div>
</div> </div>
<div className="space-y-6"> <div className="space-y-6 animate-section animate-section-2">
<h2 className="text-xl font-bold border-b border-border pb-2">Answer Key & Explanations</h2> <h2 className="text-xl font-bold border-b border-border pb-2">Answer Key & Explanations</h2>
{attempt.answers.map((ans: any, idx: number) => { {attempt.answers.map((ans: any, idx: number) => {

View File

@@ -163,7 +163,7 @@ export default function CBTPage() {
return ( return (
<> <>
<div className="p-8 space-y-8 animate-in fade-in zoom-in-95 origin-top duration-500 max-w-7xl mx-auto"> <div className="p-8 space-y-8 max-w-7xl mx-auto">
<div className="flex flex-col md:flex-row md:items-end justify-between gap-4 animate-section animate-section-1"> <div className="flex flex-col md:flex-row md:items-end justify-between gap-4 animate-section animate-section-1">
<div> <div>
<h1 className="text-3xl md:text-4xl font-black tracking-tight flex items-center gap-3 mb-1"> <h1 className="text-3xl md:text-4xl font-black tracking-tight flex items-center gap-3 mb-1">

View File

@@ -115,7 +115,7 @@ export default function CommunityPage() {
return ( return (
<PremiumGate featureKey="doubt-resolution-community"> <PremiumGate featureKey="doubt-resolution-community">
<div className="p-8 space-y-6 animate-in fade-in zoom-in-95 origin-top duration-500 max-w-7xl mx-auto"> <div className="p-8 space-y-6 max-w-7xl mx-auto">
<div className="flex flex-col md:flex-row justify-between items-start md:items-end gap-4 animate-section animate-section-1"> <div className="flex flex-col md:flex-row justify-between items-start md:items-end gap-4 animate-section animate-section-1">
<div> <div>
<h1 className="text-3xl md:text-4xl font-black tracking-tight flex items-center gap-3 mb-1"> <h1 className="text-3xl md:text-4xl font-black tracking-tight flex items-center gap-3 mb-1">

View File

@@ -134,7 +134,7 @@ export default function AIDailyPracticePage() {
const cleanTitle = (title: string) => title.replace(/\s*\(ExamEnum\.[^)]+\)/, ''); const cleanTitle = (title: string) => title.replace(/\s*\(ExamEnum\.[^)]+\)/, '');
return ( return (
<div className="p-6 md:p-8 space-y-6 animate-in fade-in zoom-in-95 origin-top duration-500 max-w-7xl mx-auto"> <div className="p-6 md:p-8 space-y-6 max-w-7xl mx-auto">
{/* Page Header */} {/* Page Header */}
<div className="border-b border-border/50 pb-6 animate-section animate-section-1"> <div className="border-b border-border/50 pb-6 animate-section animate-section-1">
<div className="flex items-start justify-between gap-4 flex-wrap"> <div className="flex items-start justify-between gap-4 flex-wrap">

View File

@@ -430,7 +430,7 @@ export default function DashboardLayout({ children }: { children: ReactNode }) {
{/* Scrollable page body */} {/* Scrollable page body */}
<main className="flex-1 overflow-y-auto relative bg-background/50"> <main className="flex-1 overflow-y-auto relative bg-background/50">
<div key={pathname} className="w-full h-full animate-in fade-in zoom-in-95 origin-top duration-500"> <div key={pathname} className="w-full h-full animate-page-enter">
{children} {children}
</div> </div>
</main> </main>

View File

@@ -46,7 +46,7 @@ export default function LeaderboardPage() {
} }
return ( return (
<div className="p-8 space-y-8 animate-in fade-in zoom-in-95 origin-top duration-500 max-w-7xl mx-auto"> <div className="p-8 space-y-8 max-w-7xl mx-auto">
<div className="flex flex-col md:flex-row justify-between items-start md:items-end gap-4 animate-section animate-section-1"> <div className="flex flex-col md:flex-row justify-between items-start md:items-end gap-4 animate-section animate-section-1">
<div> <div>
<h1 className="text-3xl md:text-4xl font-black tracking-tight flex items-center gap-3 mb-1"> <h1 className="text-3xl md:text-4xl font-black tracking-tight flex items-center gap-3 mb-1">

View File

@@ -32,7 +32,7 @@ export default function MaterialsPage() {
}; };
return ( return (
<div className="p-8 space-y-8 animate-in fade-in zoom-in-95 origin-top duration-500 max-w-7xl mx-auto"> <div className="p-8 space-y-8 max-w-7xl mx-auto">
<div className="flex flex-col md:flex-row md:items-end justify-between gap-4 animate-section animate-section-1"> <div className="flex flex-col md:flex-row md:items-end justify-between gap-4 animate-section animate-section-1">
<div> <div>
<h1 className="text-3xl md:text-4xl font-black tracking-tight flex items-center gap-3 mb-1"> <h1 className="text-3xl md:text-4xl font-black tracking-tight flex items-center gap-3 mb-1">

View File

@@ -121,7 +121,7 @@ export default function DashboardPage() {
const isNeet = user?.target_exam === "NEET" const isNeet = user?.target_exam === "NEET"
return ( return (
<div className="p-8 max-w-7xl mx-auto space-y-10 animate-in fade-in zoom-in-95 origin-top duration-500"> <div className="p-8 max-w-7xl mx-auto space-y-10">
{/* Basic Performance Dashboard (F-05) */} {/* Basic Performance Dashboard (F-05) */}
<section className="animate-section animate-section-1"> <section className="animate-section animate-section-1">

View File

@@ -261,7 +261,7 @@ export default function ProgressTrackerPage() {
return ( return (
<PremiumGate featureKey="chapter-wise-progress-tracking"> <PremiumGate featureKey="chapter-wise-progress-tracking">
<div className="p-8 space-y-8 animate-in fade-in zoom-in-95 origin-top duration-500 max-w-7xl mx-auto"> <div className="p-8 space-y-8 max-w-7xl mx-auto">
<div className="flex flex-col md:flex-row md:items-end justify-between gap-4 animate-section animate-section-1"> <div className="flex flex-col md:flex-row md:items-end justify-between gap-4 animate-section animate-section-1">
<div> <div>
<h1 className="text-3xl md:text-4xl font-black tracking-tight flex items-center gap-3 mb-1"> <h1 className="text-3xl md:text-4xl font-black tracking-tight flex items-center gap-3 mb-1">

View File

@@ -72,10 +72,10 @@ export default function RankPredictorPage() {
] ]
return ( return (
<div className="p-6 md:p-8 space-y-8 animate-in fade-in zoom-in-95 origin-top duration-500 max-w-7xl mx-auto min-h-screen"> <div className="p-6 md:p-8 space-y-8 max-w-7xl mx-auto min-h-screen">
{/* Header */} {/* Header */}
<div className="text-center max-w-3xl mx-auto space-y-3"> <div className="text-center max-w-3xl mx-auto space-y-3 animate-section animate-section-1">
<div className="inline-flex items-center gap-2 px-4 py-1.5 bg-[var(--cyan-ai-10)] text-[var(--cyan-ai)] rounded-full border border-[var(--cyan-ai-30)] text-xs font-black tracking-widest uppercase shadow-[0_0_15px_rgba(12,96,96,0.15)]"> <div className="inline-flex items-center gap-2 px-4 py-1.5 bg-[var(--cyan-ai-10)] text-[var(--cyan-ai)] rounded-full border border-[var(--cyan-ai-30)] text-xs font-black tracking-widest uppercase shadow-[0_0_15px_rgba(12,96,96,0.15)]">
<Sparkles size={14} /> AI Neural Prediction Engine <Sparkles size={14} /> AI Neural Prediction Engine
</div> </div>
@@ -133,7 +133,7 @@ export default function RankPredictorPage() {
</div> </div>
{/* Main Grid */} {/* Main Grid */}
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8"> <div className="grid grid-cols-1 lg:grid-cols-3 gap-8 animate-section animate-section-2">
{/* Left Interactive Simulator */} {/* Left Interactive Simulator */}
<div className="lg:col-span-2 space-y-6"> <div className="lg:col-span-2 space-y-6">
@@ -240,7 +240,7 @@ export default function RankPredictorPage() {
{totalScore === 0 ? "AIR --" : `AIR ~${predictedRank.toLocaleString()}`} {totalScore === 0 ? "AIR --" : `AIR ~${predictedRank.toLocaleString()}`}
</div> </div>
<div className="inline-flex items-center gap-1.5 px-3 py-1 rounded-full bg-[var(--cyan-ai-20)] text-[var(--cyan-ai)] text-xs font-bold border border-[var(--cyan-ai-40)]"> <div className="inline-flex items-center gap-1.5 px-3 py-1 rounded-full bg-[var(--cyan-ai-20)] text-[var(--cyan-ai)] text-xs font-bold border border-[var(--cyan-ai-40)]">
<CheckCircle2 size={13} /> {totalScore === 0 ? "Calibrating · Adjust Sliders" : "High Accuracy Confidence"} <CheckCircle2 size={13} /> {totalScore === 0 ? "Calibrating <EFBFBD> Adjust Sliders" : "High Accuracy Confidence"}
</div> </div>
</Card> </Card>

View File

@@ -107,7 +107,7 @@ export default function SettingsPage() {
} }
return ( return (
<div className="p-8 space-y-8 animate-in fade-in zoom-in-95 origin-top duration-500 max-w-7xl mx-auto"> <div className="p-8 space-y-8 max-w-7xl mx-auto">
<div className="flex flex-col md:flex-row md:items-end justify-between gap-4 animate-section animate-section-1"> <div className="flex flex-col md:flex-row md:items-end justify-between gap-4 animate-section animate-section-1">
<div> <div>
<h1 className="text-3xl md:text-4xl font-black tracking-tight flex items-center gap-3 mb-1"> <h1 className="text-3xl md:text-4xl font-black tracking-tight flex items-center gap-3 mb-1">

View File

@@ -1,4 +1,4 @@
"use client"; "use client";
import { fetchWithAuth } from "@/lib/apiClient"; import { fetchWithAuth } from "@/lib/apiClient";
import { useState } from "react"; import { useState } from "react";
@@ -45,8 +45,8 @@ export default function PasswordPage() {
}; };
return ( return (
<div className="p-8 space-y-8 animate-in fade-in zoom-in-95 origin-top duration-500 max-w-3xl mx-auto"> <div className="p-8 space-y-8 max-w-3xl mx-auto">
<div className="flex flex-col md:flex-row md:items-end justify-between gap-4"> <div className="flex flex-col md:flex-row md:items-end justify-between gap-4 animate-section animate-section-1">
<div> <div>
<h1 className="text-3xl md:text-4xl font-black tracking-tight flex items-center gap-3 mb-1"> <h1 className="text-3xl md:text-4xl font-black tracking-tight flex items-center gap-3 mb-1">
<span className="p-2.5 rounded-xl bg-purple-50 dark:bg-[var(--cyan-ai-10)] border border-purple-300/60 dark:border-[var(--cyan-ai-20)]"> <span className="p-2.5 rounded-xl bg-purple-50 dark:bg-[var(--cyan-ai-10)] border border-purple-300/60 dark:border-[var(--cyan-ai-20)]">
@@ -60,7 +60,7 @@ export default function PasswordPage() {
</div> </div>
</div> </div>
<Card className="border-border bg-background shadow-sm"> <Card className="border-border bg-background shadow-sm animate-section animate-section-2">
<CardHeader> <CardHeader>
<CardTitle>Change Password</CardTitle> <CardTitle>Change Password</CardTitle>
<CardDescription>Update your account password</CardDescription> <CardDescription>Update your account password</CardDescription>

View File

@@ -46,7 +46,7 @@ export default function StreaksPage() {
]; ];
return ( return (
<div className="p-8 space-y-8 animate-in fade-in zoom-in-95 origin-top duration-500 max-w-7xl mx-auto"> <div className="p-8 space-y-8 max-w-7xl mx-auto">
<div className="flex flex-col md:flex-row md:items-end justify-between gap-4 animate-section animate-section-1"> <div className="flex flex-col md:flex-row md:items-end justify-between gap-4 animate-section animate-section-1">
<div> <div>
<h1 className="text-3xl md:text-4xl font-black tracking-tight flex items-center gap-3 mb-1"> <h1 className="text-3xl md:text-4xl font-black tracking-tight flex items-center gap-3 mb-1">

View File

@@ -121,17 +121,20 @@ body {
text-wrap: balance; text-wrap: balance;
} }
/* ─── Uniform staggered section entry animations ─── */ /* ─── Uniform staggered subtle page & section entry animations ─── */
/* Usage: add animate-section to each section/card group */ .animate-page-enter {
animation: pageFadeIn 0.25s cubic-bezier(0.16, 1, 0.3, 1) both;
}
.animate-section { .animate-section {
animation: sectionFadeUp 0.45s cubic-bezier(0.16, 1, 0.3, 1) both; animation: sectionFadeUp 0.32s cubic-bezier(0.16, 1, 0.3, 1) both;
} }
.animate-section-1 { animation-delay: 0ms; } .animate-section-1 { animation-delay: 0ms; }
.animate-section-2 { animation-delay: 80ms; } .animate-section-2 { animation-delay: 50ms; }
.animate-section-3 { animation-delay: 160ms; } .animate-section-3 { animation-delay: 100ms; }
.animate-section-4 { animation-delay: 240ms; } .animate-section-4 { animation-delay: 150ms; }
.animate-section-5 { animation-delay: 320ms; } .animate-section-5 { animation-delay: 200ms; }
.animate-section-6 { animation-delay: 400ms; } .animate-section-6 { animation-delay: 250ms; }
@@ -188,13 +191,23 @@ body {
background: var(--muted-foreground); background: var(--muted-foreground);
} }
@keyframes pageFadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes sectionFadeUp { @keyframes sectionFadeUp {
from { from {
opacity: 0; opacity: 0;
transform: translateY(18px); transform: translateY(8px);
} }
to { to {
opacity: 1; opacity: 1;
transform: translateY(0); transform: translateY(0);
} }
} }