Anish commited on
Commit
ee7c0fb
·
1 Parent(s): 825fa02

[UI/UX] More changes to the Frontend

Browse files
backend/app/services/email_service.py CHANGED
@@ -58,7 +58,7 @@ async def send_verification_email(email_to: str, raw_token: str):
58
 
59
  html_content = f"""
60
  <div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; color: #333;">
61
- <h2>Welcome to AI Detector!</h2>
62
  <p>Please confirm your email address to activate your account.</p>
63
  <p>Click the button below to verify. <strong>This link will expire in 24 hours.</strong></p>
64
  <div style="text-align: center; margin: 30px 0;">
 
58
 
59
  html_content = f"""
60
  <div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; color: #333;">
61
+ <h2>Welcome to Spotix!</h2>
62
  <p>Please confirm your email address to activate your account.</p>
63
  <p>Click the button below to verify. <strong>This link will expire in 24 hours.</strong></p>
64
  <div style="text-align: center; margin: 30px 0;">
backend/main.py CHANGED
@@ -24,7 +24,7 @@ async def lifespan(app: FastAPI):
24
  yield
25
 
26
  app = FastAPI(
27
- title="AI Detection Platform",
28
  lifespan=lifespan
29
  )
30
 
 
24
  yield
25
 
26
  app = FastAPI(
27
+ title="Spotix",
28
  lifespan=lifespan
29
  )
30
 
frontend/app/dashboard/page.tsx CHANGED
@@ -20,8 +20,8 @@ export default function DashboardPage() {
20
 
21
  // Filter & Sort States
22
  const [searchQuery, setSearchQuery] = useState("");
23
- const [sortBy, setSortBy] = useState<'newest'|'confidence'>('newest');
24
- const [resultFilter, setResultFilter] = useState<'All'|'AI'|'Real'|'Suspicious'>('All');
25
 
26
  // Fetch Files & Guard
27
  useEffect(() => {
@@ -87,8 +87,8 @@ export default function DashboardPage() {
87
  // 3. Sort
88
  result.sort((a, b) => {
89
  if (sortBy === 'newest' || sortBy === 'date') {
90
- const dateA = a.uploaded_at ? new Date(a.uploaded_at).getTime() : 0;
91
- const dateB = b.uploaded_at ? new Date(b.uploaded_at).getTime() : 0;
92
  return dateB - dateA; // Both map to newest first logic
93
  } else {
94
  const confA = a.confidence || 0;
 
20
 
21
  // Filter & Sort States
22
  const [searchQuery, setSearchQuery] = useState("");
23
+ const [sortBy, setSortBy] = useState<'newest'|'confidence'|'date'>('newest');
24
+ const [resultFilter, setResultFilter] = useState<'All'|'AI'|'Real'|'Suspicious'|'Videos'|'Images'>('All');
25
 
26
  // Fetch Files & Guard
27
  useEffect(() => {
 
87
  // 3. Sort
88
  result.sort((a, b) => {
89
  if (sortBy === 'newest' || sortBy === 'date') {
90
+ const dateA = a.uploaded_at ? new Date(a.uploaded_at.endsWith('Z') ? a.uploaded_at : a.uploaded_at + 'Z').getTime() : 0;
91
+ const dateB = b.uploaded_at ? new Date(b.uploaded_at.endsWith('Z') ? b.uploaded_at : b.uploaded_at + 'Z').getTime() : 0;
92
  return dateB - dateA; // Both map to newest first logic
93
  } else {
94
  const confA = a.confidence || 0;
frontend/app/learn-more/page.tsx ADDED
@@ -0,0 +1,144 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use client";
2
+
3
+ import React, { useEffect } from "react";
4
+ import { useRouter } from "next/navigation";
5
+ import { ArrowLeft, Upload, Shield, Activity, Database } from "lucide-react";
6
+ import Navbar from "@/components/shared/Navbar";
7
+
8
+ export default function LearnMorePage() {
9
+ const router = useRouter();
10
+
11
+ useEffect(() => {
12
+ // Scroll reveal logic
13
+ const observer = new IntersectionObserver((entries) => {
14
+ entries.forEach(entry => {
15
+ if (entry.isIntersecting) {
16
+ entry.target.classList.add('visible');
17
+ }
18
+ });
19
+ }, { threshold: 0.1 });
20
+
21
+ document.querySelectorAll('.scroll-reveal').forEach((el) => observer.observe(el));
22
+ return () => observer.disconnect();
23
+ }, []);
24
+
25
+ return (
26
+ <div className="min-h-screen bg-[var(--theme-bg)] text-[var(--theme-text)] font-sans relative overflow-x-hidden selection:bg-[var(--theme-text)] selection:text-[var(--theme-bg)]">
27
+ {/* Global Theme & Cursor overrides if needed */}
28
+ <style dangerouslySetInnerHTML={{
29
+ __html: `
30
+ html, body, a, button, [role="button"], input, select, textarea, .cursor-pointer {
31
+ cursor: none !important;
32
+ }
33
+ body {
34
+ background-color: var(--theme-bg);
35
+ }
36
+
37
+ .scroll-reveal {
38
+ opacity: 0;
39
+ transform: translateY(30px);
40
+ transition: all 1s cubic-bezier(0.23, 1, 0.32, 1);
41
+ }
42
+ .scroll-reveal.visible {
43
+ opacity: 1;
44
+ transform: translateY(0);
45
+ }
46
+ `
47
+ }} />
48
+
49
+ {/* Background Effects */}
50
+ <div className="absolute inset-0 bg-[var(--theme-bg)] z-0"></div>
51
+ <div className="absolute inset-0 opacity-40 pointer-events-none bg-[radial-gradient(circle_at_50%_50%,_#11141d_0%,_var(--theme-bg)_100%)] z-[1]"></div>
52
+ <div className="absolute inset-0 z-[2] opacity-[0.03] pointer-events-none" style={{ backgroundImage: `url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.90' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E")` }}></div>
53
+
54
+ <Navbar />
55
+
56
+ <div className="relative z-10 max-w-4xl mx-auto px-6 py-40">
57
+ {/* Header */}
58
+ <div className="mb-20 text-center scroll-reveal">
59
+ <label className="uppercase tracking-[0.4em] text-[#d0c4bb] mb-6 block text-xs">Platform Guide</label>
60
+ <h1 className="text-5xl md:text-7xl font-black tracking-tight text-[var(--theme-text)] mb-6">
61
+ Master the Engine
62
+ </h1>
63
+ <p className="text-lg md:text-xl text-[var(--theme-text)]/70 font-light leading-relaxed max-w-2xl mx-auto">
64
+ Welcome to Spotix. Learn how to utilize our neural architecture to detect synthetic and AI-generated media with absolute precision.
65
+ </p>
66
+ </div>
67
+
68
+ {/* Steps */}
69
+ <div className="space-y-12">
70
+ {/* Step 1 */}
71
+ <div className="flex flex-col md:flex-row gap-8 items-start bg-[var(--theme-text)]/5 p-8 md:p-12 rounded-[2rem] border border-[var(--theme-border)] backdrop-blur-md scroll-reveal hover:bg-[var(--theme-text)]/10 transition-colors">
72
+ <div className="w-16 h-16 shrink-0 rounded-2xl bg-[var(--theme-text)]/10 flex items-center justify-center border border-[var(--theme-border)]">
73
+ <Upload className="w-8 h-8 text-[var(--theme-text)]" />
74
+ </div>
75
+ <div>
76
+ <h2 className="text-2xl font-bold mb-4">1. Uploading Media</h2>
77
+ <p className="text-[var(--theme-text)]/70 leading-relaxed text-lg">
78
+ Click the <strong className="text-[var(--theme-text)]">Analyze Media</strong> button on the top right of the navigation bar, or from the Landing Page. A secure uplink zone will appear. You can drag and drop your images or videos (MP4, WEBM, JPG, PNG) directly into this zone.
79
+ </p>
80
+ </div>
81
+ </div>
82
+
83
+ {/* Step 2 */}
84
+ <div className="flex flex-col md:flex-row gap-8 items-start bg-[var(--theme-text)]/5 p-8 md:p-12 rounded-[2rem] border border-[var(--theme-border)] backdrop-blur-md scroll-reveal hover:bg-[var(--theme-text)]/10 transition-colors">
85
+ <div className="w-16 h-16 shrink-0 rounded-2xl bg-[var(--theme-text)]/10 flex items-center justify-center border border-[var(--theme-border)]">
86
+ <Activity className="w-8 h-8 text-[var(--theme-text)]" />
87
+ </div>
88
+ <div>
89
+ <h2 className="text-2xl font-bold mb-4">2. The Analysis Phase</h2>
90
+ <p className="text-[var(--theme-text)]/70 leading-relaxed text-lg">
91
+ Once uploaded, the Spotix engine dissects the file through multiple neural pathways. We check for temporal inconsistencies, latent space noise patterns, and structural artifacts that generative AI models leave behind.
92
+ </p>
93
+ </div>
94
+ </div>
95
+
96
+ {/* Step 3 */}
97
+ <div className="flex flex-col md:flex-row gap-8 items-start bg-[var(--theme-text)]/5 p-8 md:p-12 rounded-[2rem] border border-[var(--theme-border)] backdrop-blur-md scroll-reveal hover:bg-[var(--theme-text)]/10 transition-colors">
98
+ <div className="w-16 h-16 shrink-0 rounded-2xl bg-[var(--theme-text)]/10 flex items-center justify-center border border-[var(--theme-border)]">
99
+ <Shield className="w-8 h-8 text-[var(--theme-text)]" />
100
+ </div>
101
+ <div>
102
+ <h2 className="text-2xl font-bold mb-4">3. Deciphering the Results</h2>
103
+ <p className="text-[var(--theme-text)]/70 leading-relaxed text-lg">
104
+ You will be routed to the Results Terminal. Here, you'll see a confidence score and a verdict (Authentic, Suspicious, or AI Detected). A heatmap visualizes exactly where the neural anomalies were found in the media.
105
+ </p>
106
+ </div>
107
+ </div>
108
+
109
+ {/* Step 4 */}
110
+ <div className="flex flex-col md:flex-row gap-8 items-start bg-[var(--theme-text)]/5 p-8 md:p-12 rounded-[2rem] border border-[var(--theme-border)] backdrop-blur-md scroll-reveal hover:bg-[var(--theme-text)]/10 transition-colors">
111
+ <div className="w-16 h-16 shrink-0 rounded-2xl bg-[var(--theme-text)]/10 flex items-center justify-center border border-[var(--theme-border)]">
112
+ <Database className="w-8 h-8 text-[var(--theme-text)]" />
113
+ </div>
114
+ <div>
115
+ <h2 className="text-2xl font-bold mb-4">4. Managing Your Dashboard</h2>
116
+ <p className="text-[var(--theme-text)]/70 leading-relaxed text-lg">
117
+ Access your Dashboard to view a complete history of all your analyses. You can filter by file type, sort by confidence or date, and delete historical data to maintain your privacy.
118
+ </p>
119
+ </div>
120
+ </div>
121
+ </div>
122
+
123
+ {/* Back Button */}
124
+ <div className="mt-20 flex justify-center scroll-reveal">
125
+ <button
126
+ onClick={() => router.push('/')}
127
+ className="group relative overflow-hidden rounded-full bg-[var(--theme-text)] text-[var(--theme-bg)] px-10 py-4 font-bold tracking-widest text-sm uppercase transition-all duration-300 hover:shadow-[0_0_40px_rgba(253,232,214,0.3)] hover:scale-105 flex items-center gap-3 !cursor-none"
128
+ >
129
+ <ArrowLeft className="w-5 h-5 transition-transform duration-300 group-hover:-translate-x-1" />
130
+ <span>Return to Gateway</span>
131
+ </button>
132
+ </div>
133
+ </div>
134
+
135
+ {/* Footer */}
136
+ <footer className="bg-[var(--theme-bg)] w-full border-t border-[var(--theme-border)] relative z-10">
137
+ <div className="flex flex-col items-center justify-center py-12 max-w-5xl mx-auto">
138
+ <div className="text-xl font-black text-[var(--theme-text)] uppercase mb-2">SPOTIX</div>
139
+ <div className="font-['Inter'] uppercase tracking-[0.15em] text-[9px] text-[#d0c4bb] opacity-60">© 2026 SPOTIX KINETIC. ENGINEERED FOR THE ETHEREAL.</div>
140
+ </div>
141
+ </footer>
142
+ </div>
143
+ );
144
+ }
frontend/app/login/page.tsx CHANGED
@@ -128,7 +128,7 @@ export default function LoginPage() {
128
  <div className="fixed top-12 left-6 md:left-12 z-40">
129
  <button onClick={() => router.push("/")} className="group flex items-center gap-3 text-[#d0c4bb] hover:text-[var(--theme-text)] transition-colors !cursor-none text-sm font-semibold tracking-wider hover-scale">
130
  <ArrowLeft className="w-5 h-5 transition-transform group-hover:-translate-x-1 !cursor-none" />
131
- RETURN TO PLATFORM
132
  </button>
133
  </div>
134
 
@@ -137,9 +137,9 @@ export default function LoginPage() {
137
  <div className="absolute -top-40 -right-40 w-80 h-80 bg-theme-text/5 rounded-full blur-[80px] pointer-events-none"></div>
138
 
139
  <h1 className="text-3xl tracking-widest font-bold mb-2 font-sans uppercase">
140
- Neural<span className="text-[var(--theme-text)]/50"> Vault</span> Access
141
  </h1>
142
- <p className="text-[#d0c4bb]/60 text-sm mb-6">Authenticate to seamlessly vault and analyze.</p>
143
 
144
  {error && (
145
  <div className="bg-red-500/10 border border-red-500/20 text-red-400 text-sm p-3 rounded-lg mb-4">
@@ -186,7 +186,7 @@ export default function LoginPage() {
186
  required={mode === 'signup'}
187
  value={email}
188
  onChange={(e) => setEmail(e.target.value)}
189
- placeholder="Neural Identity (Email)"
190
  className="w-full bg-theme-text/5 border border-theme-border rounded-xl py-4 pl-12 pr-4 text-[var(--theme-text)] placeholder-[#d0c4bb]/40 focus:outline-none focus:border-theme-border/50 focus:bg-theme-text/10 transition-all font-mono text-sm"
191
  />
192
  </div>
@@ -198,7 +198,7 @@ export default function LoginPage() {
198
  required
199
  value={password}
200
  onChange={(e) => setPassword(e.target.value)}
201
- placeholder="Passkey"
202
  className="w-full bg-theme-text/5 border border-theme-border rounded-xl py-4 pl-12 pr-4 text-[var(--theme-text)] placeholder-[#d0c4bb]/40 focus:outline-none focus:border-theme-border/50 focus:bg-theme-text/10 transition-all font-mono text-sm"
203
  />
204
  </div>
@@ -209,7 +209,7 @@ export default function LoginPage() {
209
  className="w-full mt-2 py-4 rounded-xl relative overflow-hidden group dash-border bg-theme-text/5 hover:bg-theme-text/10 transition"
210
  >
211
  <span className="relative z-10 font-bold tracking-widest text-sm uppercase flex items-center justify-center gap-2">
212
- {loading && mode === 'login' ? 'Authorizing...' : loading && mode === 'signup' ? 'Registering...' : mode === 'login' ? 'Initialize Session' : 'Create Vault'}
213
  <ArrowRight className={`w-4 h-4 transition-transform group-hover:translate-x-1 ${loading ? 'hidden' : ''}`} />
214
  </span>
215
  </button>
@@ -220,7 +220,7 @@ export default function LoginPage() {
220
  onClick={() => setMode(mode === 'login' ? 'signup' : 'login')}
221
  className="text-xs text-[#d0c4bb]/60 hover:text-[var(--theme-text)] transition uppercase tracking-widest cursor-pointer"
222
  >
223
- {mode === 'login' ? "Don't have a vault? Build one." : "Already have a vault? Initialize."}
224
  </button>
225
  </div>
226
 
 
128
  <div className="fixed top-12 left-6 md:left-12 z-40">
129
  <button onClick={() => router.push("/")} className="group flex items-center gap-3 text-[#d0c4bb] hover:text-[var(--theme-text)] transition-colors !cursor-none text-sm font-semibold tracking-wider hover-scale">
130
  <ArrowLeft className="w-5 h-5 transition-transform group-hover:-translate-x-1 !cursor-none" />
131
+ RETURN TO SPOTIX
132
  </button>
133
  </div>
134
 
 
137
  <div className="absolute -top-40 -right-40 w-80 h-80 bg-theme-text/5 rounded-full blur-[80px] pointer-events-none"></div>
138
 
139
  <h1 className="text-3xl tracking-widest font-bold mb-2 font-sans uppercase">
140
+ Spotix<span className="text-[var(--theme-text)]/50"> Vault</span> Access
141
  </h1>
142
+ <p className="text-[#d0c4bb]/60 text-sm mb-6">Authenticate to seamlessly store and analyze.</p>
143
 
144
  {error && (
145
  <div className="bg-red-500/10 border border-red-500/20 text-red-400 text-sm p-3 rounded-lg mb-4">
 
186
  required={mode === 'signup'}
187
  value={email}
188
  onChange={(e) => setEmail(e.target.value)}
189
+ placeholder="Email"
190
  className="w-full bg-theme-text/5 border border-theme-border rounded-xl py-4 pl-12 pr-4 text-[var(--theme-text)] placeholder-[#d0c4bb]/40 focus:outline-none focus:border-theme-border/50 focus:bg-theme-text/10 transition-all font-mono text-sm"
191
  />
192
  </div>
 
198
  required
199
  value={password}
200
  onChange={(e) => setPassword(e.target.value)}
201
+ placeholder="Password"
202
  className="w-full bg-theme-text/5 border border-theme-border rounded-xl py-4 pl-12 pr-4 text-[var(--theme-text)] placeholder-[#d0c4bb]/40 focus:outline-none focus:border-theme-border/50 focus:bg-theme-text/10 transition-all font-mono text-sm"
203
  />
204
  </div>
 
209
  className="w-full mt-2 py-4 rounded-xl relative overflow-hidden group dash-border bg-theme-text/5 hover:bg-theme-text/10 transition"
210
  >
211
  <span className="relative z-10 font-bold tracking-widest text-sm uppercase flex items-center justify-center gap-2">
212
+ {loading && mode === 'login' ? 'Authorizing...' : loading && mode === 'signup' ? 'Registering...' : mode === 'login' ? 'Login' : 'Register'}
213
  <ArrowRight className={`w-4 h-4 transition-transform group-hover:translate-x-1 ${loading ? 'hidden' : ''}`} />
214
  </span>
215
  </button>
 
220
  onClick={() => setMode(mode === 'login' ? 'signup' : 'login')}
221
  className="text-xs text-[#d0c4bb]/60 hover:text-[var(--theme-text)] transition uppercase tracking-widest cursor-pointer"
222
  >
223
+ {mode === 'login' ? "Don't have an Account? Create one." : "Already have an Account? Login."}
224
  </button>
225
  </div>
226
 
frontend/app/page.tsx CHANGED
@@ -12,6 +12,13 @@ export default function LandingPage() {
12
 
13
  const [isUploadModalOpen, setIsUploadModalOpen] = useState(false);
14
 
 
 
 
 
 
 
 
15
  // --- React State for Loader ---
16
  const [loadProgress, setLoadProgress] = useState(0);
17
  const [isLoaded, setIsLoaded] = useState(false);
@@ -301,7 +308,7 @@ export default function LandingPage() {
301
 
302
  <div className="absolute inset-0 bg-[var(--theme-bg)] z-0"></div>
303
  <div className="absolute inset-0 opacity-40 pointer-events-none bg-[radial-gradient(circle_at_50%_50%,_#11141d_0%,_var(--theme-bg)_100%)] z-[1]" id="hero-bg"></div>
304
- <div className="absolute inset-0 z-[2] opacity-[0.03] pointer-events-none" style={{ backgroundImage: `url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E")` }}></div>
305
  <div className="absolute inset-0 pointer-events-none" id="hero-grid"></div>
306
  <div className="absolute inset-0 pointer-events-none" id="hero-glow"></div>
307
 
@@ -310,11 +317,11 @@ export default function LandingPage() {
310
  {/* Main Hero Content */}
311
  <div className={`w-full transition-all duration-1000 ease-[cubic-bezier(0.23,1,0.32,1)] ${isUploadModalOpen ? 'blur-sm opacity-50 pointer-events-none' : ''}`} id="hero-main-content">
312
  <div className="reveal-wrap mb-6">
313
- <label className="reveal-text uppercase tracking-[0.3em] text-[var(--theme-text)] block text-xs font-medium opacity-80;" style={{ transitionDelay: '0.1s' }}>Next-Gen Media Intelligence</label>
314
  </div>
315
  <div className="reveal-wrap mb-8">
316
  <h1 className="reveal-text text-5xl md:text-8xl lg:text-9xl font-black tracking-[-0.04em] leading-[0.95] text-[var(--theme-text)]" style={{ transitionDelay: '0.3s' }}>
317
- Ethereal Intelligence.<br />
318
  <span className="text-outline">Engineered for Truth.</span>
319
  </h1>
320
  </div>
@@ -329,7 +336,7 @@ export default function LandingPage() {
329
  <span className="transition-transform duration-300 group-hover:-translate-x-2">Analyze Media</span>
330
  <ArrowRight className="w-5 h-5 ml-2 opacity-0 -translate-x-4 group-hover:opacity-100 group-hover:translate-x-0 transition-all duration-500 ease-[cubic-bezier(0.23,1,0.32,1)] absolute right-8 arrow-animate" />
331
  </button>
332
- <button className="bg-[var(--theme-text)]/5 backdrop-blur-md text-[var(--theme-text)] px-10 py-5 rounded-full text-sm font-semibold hover:bg-[var(--theme-text)]/10 transition-all border-none hover-scale relative z-20">
333
  Learn More
334
  </button>
335
  </div>
@@ -361,16 +368,20 @@ export default function LandingPage() {
361
  <div className="max-w-[1920px] mx-auto scroll-reveal">
362
  <div className="grid grid-cols-1 lg:grid-cols-12 gap-16 md:gap-24 items-center">
363
  <div className="lg:col-span-5">
364
- <h2 className="text-4xl md:text-5xl font-bold tracking-tight mb-8 text-[var(--theme-text)]">Real-time Latent Diagnostics</h2>
365
- <p className="text-[#d0c4bb] mb-10 leading-relaxed text-lg">Experience the precision of the Obsidian Engine. Our live diagnostic interface provides instantaneous metadata readouts and structural integrity mapping.</p>
366
  <div className="space-y-6">
367
  <div className="flex items-center gap-4 text-sm text-[var(--theme-text)]/70">
368
  <CheckCircle className="w-5 h-5 text-[var(--theme-text)]" strokeWidth={1.5} />
369
- <span className="uppercase tracking-widest font-medium">99.8% Detection Rate</span>
370
  </div>
371
  <div className="flex items-center gap-4 text-sm text-[var(--theme-text)]/70">
372
  <CheckCircle className="w-5 h-5 text-[var(--theme-text)]" strokeWidth={1.5} />
373
- <span className="uppercase tracking-widest font-medium">Sub-200ms Latency</span>
 
 
 
 
374
  </div>
375
  </div>
376
  </div>
@@ -382,23 +393,20 @@ export default function LandingPage() {
382
  <div className="bg-[var(--theme-bg)]/80 backdrop-blur-md px-5 py-2.5 rounded-full border border-theme-border">
383
  <span className="text-[10px] font-mono text-[var(--theme-text)] uppercase tracking-tighter">Status: Scanning_Buffer_04</span>
384
  </div>
385
- <div className="font-mono text-[10px] text-[#d0c4bb] text-right">
386
- COORD: 34.0522° N<br />TIMESTAMP: 12:44:09:22
387
- </div>
388
  </div>
389
  <div className="absolute top-1/2 left-0 w-full h-[2px] bg-[var(--theme-text)]/40 shadow-[0_0_20px_rgba(253,232,214,0.5)] animate-pulse"></div>
390
  <div className="mt-auto grid grid-cols-3 gap-3 md:gap-6">
391
  <div className="bg-[var(--theme-bg)]/90 backdrop-blur-md p-5 rounded-2xl border border-theme-border">
392
- <div className="text-[9px] text-[#d0c4bb] uppercase tracking-widest mb-2">Authenticity</div>
393
- <div className="text-xl md:text-3xl font-bold text-[var(--theme-text)]">94.2%</div>
394
  </div>
395
  <div className="bg-[var(--theme-bg)]/90 backdrop-blur-md p-5 rounded-2xl border border-theme-border">
396
- <div className="text-[9px] text-[#d0c4bb] uppercase tracking-widest mb-2">Noise Delta</div>
397
- <div className="text-xl md:text-3xl font-bold text-[var(--theme-text)]">0.024</div>
398
  </div>
399
  <div className="bg-[var(--theme-bg)]/90 backdrop-blur-md p-5 rounded-2xl border border-theme-border">
400
- <div className="text-[9px] text-[#d0c4bb] uppercase tracking-widest mb-2">Neural Rank</div>
401
- <div className="text-xl md:text-3xl font-bold text-[var(--theme-text)]">A-IV</div>
402
  </div>
403
  </div>
404
  </div>
@@ -420,22 +428,22 @@ export default function LandingPage() {
420
  <div className="mb-6 md:mb-8 lg:mb-10 inline-block p-5 rounded-2xl bg-theme-text/5 text-[var(--theme-text)] transition-transform group-hover:scale-110 duration-500">
421
  <Fingerprint className="w-10 h-10 text-[var(--theme-text)]" strokeWidth={1.5} />
422
  </div>
423
- <h3 className="text-xl md:text-2xl font-bold mb-6 text-[var(--theme-text)] transition-colors">Neural Fingerprinting</h3>
424
- <p className="text-[#d0c4bb] leading-relaxed text-base md:text-lg">Extracting deep-layer artifacts invisible to the human eye, identifying the unique synthetic signature of generative models.</p>
425
  </div>
426
  <div className="glow-card dash-border group relative p-8 md:p-10 lg:p-12 bg-theme-text/5 backdrop-blur-sm border border-theme-border rounded-3xl transition-all duration-700 hover:bg-theme-text/10 hover:-translate-y-[10px] hover:shadow-[0_30px_60px_-15px_rgba(0,0,0,0.3)] scroll-reveal tilt-card">
427
  <div className="mb-6 md:mb-8 lg:mb-10 inline-block p-5 rounded-2xl bg-theme-text/5 text-[var(--theme-text)] transition-transform group-hover:scale-110 duration-500">
428
  <Activity className="w-10 h-10 text-[var(--theme-text)]" strokeWidth={1.5} />
429
  </div>
430
- <h3 className="text-xl md:text-2xl font-bold mb-6 text-[var(--theme-text)] transition-colors">Temporal Consistency</h3>
431
- <p className="text-[#d0c4bb] leading-relaxed text-base md:text-lg">Analyzing frame-to-frame variance to detect temporal anomalies and fluid-logic errors in synthetic video generation.</p>
432
  </div>
433
  <div className="glow-card dash-border group relative p-8 md:p-10 lg:p-12 bg-theme-text/5 backdrop-blur-sm border border-theme-border rounded-3xl transition-all duration-700 hover:bg-theme-text/10 hover:-translate-y-[10px] hover:shadow-[0_30px_60px_-15px_rgba(0,0,0,0.3)] scroll-reveal tilt-card">
434
  <div className="mb-6 md:mb-8 lg:mb-10 inline-block p-5 rounded-2xl bg-theme-text/5 text-[var(--theme-text)] transition-transform group-hover:scale-110 duration-500">
435
  <Network className="w-10 h-10 text-[var(--theme-text)]" strokeWidth={1.5} />
436
  </div>
437
- <h3 className="text-xl md:text-2xl font-bold mb-6 text-[var(--theme-text)] transition-colors">Latent Space Analysis</h3>
438
- <p className="text-[#d0c4bb] leading-relaxed text-base md:text-lg">Mapping content against known latent space distributions to identify cross-model similarities and structural patterns.</p>
439
  </div>
440
  </div>
441
  </section>
@@ -459,16 +467,16 @@ export default function LandingPage() {
459
  </div>
460
  <div className="lg:w-1/2 order-1 lg:order-2">
461
  <label className="uppercase tracking-[0.4em] text-[#d0c4bb] mb-8 block text-xs">Transparent Logic</label>
462
- <h2 className="text-6xl md:text-8xl font-black tracking-tighter mb-10 leading-[0.95] text-[var(--theme-text)]">Heatmap<br />Explainability</h2>
463
- <p className="text-[#d0c4bb] text-xl leading-relaxed mb-12">We don't just provide a score. Our engine maps the specific regions of concern, visualizing the neural pathways activated during analysis for absolute clarity.</p>
464
  <div className="grid grid-cols-2 gap-12">
465
  <div>
466
- <div className="text-[var(--theme-text)] text-3xl font-bold mb-3">0.98</div>
467
  <div className="text-[10px] uppercase tracking-[0.2em] text-[#d0c4bb] font-semibold">Confidence Threshold</div>
468
  </div>
469
  <div>
470
- <div className="text-[var(--theme-text)] text-3xl font-bold mb-3">Linear</div>
471
- <div className="text-[10px] uppercase tracking-[0.2em] text-[#d0c4bb] font-semibold">Decision Logic</div>
472
  </div>
473
  </div>
474
  </div>
@@ -480,11 +488,10 @@ export default function LandingPage() {
480
  <footer className="bg-[var(--theme-bg)] w-full border-t border-theme-border relative z-10">
481
  <div className="flex flex-col md:flex-row justify-between items-center px-12 py-24 gap-12 max-w-[1920px] mx-auto">
482
  <div className="flex flex-col items-center md:items-start gap-4">
483
- <div className="text-2xl font-black text-[var(--theme-text)] uppercase">OBSIDIAN</div>
484
- <div className="font-['Inter'] uppercase tracking-[0.15em] text-[9px] text-[#d0c4bb] opacity-60">© 2026 OBSIDIAN KINETIC. ENGINEERED FOR THE ETHEREAL.</div>
485
  </div>
486
  <div className="flex flex-wrap justify-center gap-x-12 gap-y-6 items-center">
487
- <a className="font-['Inter'] uppercase tracking-[0.2em] text-[10px] text-[#d0c4bb] hover:text-[var(--theme-text)] transition-colors duration-300" href="#">Documentation</a>
488
  <a className="font-['Inter'] uppercase tracking-[0.2em] text-[10px] text-[#d0c4bb] transition-all duration-300 flex items-center gap-2 group hover:text-green-400 hover:drop-shadow-[0_0_8px_rgba(74,222,128,0.5)] cursor-pointer" href="#">
489
  <span>System Status</span>
490
  <span className="text-[9px] bg-[var(--theme-text)]/5 px-2 py-0.5 rounded-full border border-[var(--theme-text)]/10 group-hover:border-green-500/30 group-hover:bg-green-500/10 flex items-center gap-1.5 transition-colors">
 
12
 
13
  const [isUploadModalOpen, setIsUploadModalOpen] = useState(false);
14
 
15
+ // --- Footer Copyright and Dynamic Date ---
16
+ const [year, setYear] = useState(new Date().getFullYear());
17
+
18
+ useEffect(() =>{
19
+ setYear(new Date().getFullYear());
20
+ }, []);
21
+
22
  // --- React State for Loader ---
23
  const [loadProgress, setLoadProgress] = useState(0);
24
  const [isLoaded, setIsLoaded] = useState(false);
 
308
 
309
  <div className="absolute inset-0 bg-[var(--theme-bg)] z-0"></div>
310
  <div className="absolute inset-0 opacity-40 pointer-events-none bg-[radial-gradient(circle_at_50%_50%,_#11141d_0%,_var(--theme-bg)_100%)] z-[1]" id="hero-bg"></div>
311
+ <div className="absolute inset-0 z-[2] opacity-[0.03] pointer-events-none" style={{ backgroundImage: `url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.90' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E")` }}></div>
312
  <div className="absolute inset-0 pointer-events-none" id="hero-grid"></div>
313
  <div className="absolute inset-0 pointer-events-none" id="hero-glow"></div>
314
 
 
317
  {/* Main Hero Content */}
318
  <div className={`w-full transition-all duration-1000 ease-[cubic-bezier(0.23,1,0.32,1)] ${isUploadModalOpen ? 'blur-sm opacity-50 pointer-events-none' : ''}`} id="hero-main-content">
319
  <div className="reveal-wrap mb-6">
320
+ <label className="reveal-text uppercase tracking-[0.3em] text-[var(--theme-text)] block text-xs font-medium opacity-80;" style={{ transitionDelay: '0.1s' }}>Next-Gen Media Analyzer</label>
321
  </div>
322
  <div className="reveal-wrap mb-8">
323
  <h1 className="reveal-text text-5xl md:text-8xl lg:text-9xl font-black tracking-[-0.04em] leading-[0.95] text-[var(--theme-text)]" style={{ transitionDelay: '0.3s' }}>
324
+ Spotix Intelligence.<br />
325
  <span className="text-outline">Engineered for Truth.</span>
326
  </h1>
327
  </div>
 
336
  <span className="transition-transform duration-300 group-hover:-translate-x-2">Analyze Media</span>
337
  <ArrowRight className="w-5 h-5 ml-2 opacity-0 -translate-x-4 group-hover:opacity-100 group-hover:translate-x-0 transition-all duration-500 ease-[cubic-bezier(0.23,1,0.32,1)] absolute right-8 arrow-animate" />
338
  </button>
339
+ <button className="bg-[var(--theme-text)]/5 backdrop-blur-md text-[var(--theme-text)] px-10 py-5 rounded-full text-sm font-semibold hover:bg-[var(--theme-text)]/10 transition-all border-none hover-scale relative z-20" onClick={() => router.push('/learn-more')}>
340
  Learn More
341
  </button>
342
  </div>
 
368
  <div className="max-w-[1920px] mx-auto scroll-reveal">
369
  <div className="grid grid-cols-1 lg:grid-cols-12 gap-16 md:gap-24 items-center">
370
  <div className="lg:col-span-5">
371
+ <h2 className="text-4xl md:text-5xl font-bold tracking-tight mb-8 text-[var(--theme-text)]">AI Media Authenticity Analysis</h2>
372
+ <p className="text-[#d0c4bb] mb-10 leading-relaxed text-lg">Analyze images and videos using multi-signal detection. Spotix evaluates structural patterns, noise characteristics, and temporal consistency to estimate authenticity.</p>
373
  <div className="space-y-6">
374
  <div className="flex items-center gap-4 text-sm text-[var(--theme-text)]/70">
375
  <CheckCircle className="w-5 h-5 text-[var(--theme-text)]" strokeWidth={1.5} />
376
+ <span className="uppercase tracking-widest font-medium">Noise & Frequency Analysis</span>
377
  </div>
378
  <div className="flex items-center gap-4 text-sm text-[var(--theme-text)]/70">
379
  <CheckCircle className="w-5 h-5 text-[var(--theme-text)]" strokeWidth={1.5} />
380
+ <span className="uppercase tracking-widest font-medium">Temporal Consistency Checks</span>
381
+ </div>
382
+ <div className="flex items-center gap-4 text-sm text-[var(--theme-text)]/70">
383
+ <CheckCircle className="w-5 h-5 text-[var(--theme-text)]" strokeWidth={1.5} />
384
+ <span className="uppercase tracking-widest font-medium">Explainable Results</span>
385
  </div>
386
  </div>
387
  </div>
 
393
  <div className="bg-[var(--theme-bg)]/80 backdrop-blur-md px-5 py-2.5 rounded-full border border-theme-border">
394
  <span className="text-[10px] font-mono text-[var(--theme-text)] uppercase tracking-tighter">Status: Scanning_Buffer_04</span>
395
  </div>
 
 
 
396
  </div>
397
  <div className="absolute top-1/2 left-0 w-full h-[2px] bg-[var(--theme-text)]/40 shadow-[0_0_20px_rgba(253,232,214,0.5)] animate-pulse"></div>
398
  <div className="mt-auto grid grid-cols-3 gap-3 md:gap-6">
399
  <div className="bg-[var(--theme-bg)]/90 backdrop-blur-md p-5 rounded-2xl border border-theme-border">
400
+ <div className="text-[9px] text-[#d0c4bb] uppercase tracking-widest mb-2">Authenticity Score</div>
401
+ <div className="text-xl md:text-3xl font-bold text-[var(--theme-text)]">94%</div>
402
  </div>
403
  <div className="bg-[var(--theme-bg)]/90 backdrop-blur-md p-5 rounded-2xl border border-theme-border">
404
+ <div className="text-[9px] text-[#d0c4bb] uppercase tracking-widest mb-2">Noise Consistency</div>
405
+ <div className="text-xl md:text-3xl font-bold text-[var(--theme-text)]">0.62</div>
406
  </div>
407
  <div className="bg-[var(--theme-bg)]/90 backdrop-blur-md p-5 rounded-2xl border border-theme-border">
408
+ <div className="text-[9px] text-[#d0c4bb] uppercase tracking-widest mb-2">Detection Confidence</div>
409
+ <div className="text-xl md:text-3xl font-bold text-[var(--theme-text)]">High</div>
410
  </div>
411
  </div>
412
  </div>
 
428
  <div className="mb-6 md:mb-8 lg:mb-10 inline-block p-5 rounded-2xl bg-theme-text/5 text-[var(--theme-text)] transition-transform group-hover:scale-110 duration-500">
429
  <Fingerprint className="w-10 h-10 text-[var(--theme-text)]" strokeWidth={1.5} />
430
  </div>
431
+ <h3 className="text-xl md:text-2xl font-bold mb-6 text-[var(--theme-text)] transition-colors">Noise & Residual Analysis</h3>
432
+ <p className="text-[#d0c4bb] leading-relaxed text-base md:text-lg">Examines pixel-level noise patterns and residual signals to identify inconsistencies typical of synthetic generation.</p>
433
  </div>
434
  <div className="glow-card dash-border group relative p-8 md:p-10 lg:p-12 bg-theme-text/5 backdrop-blur-sm border border-theme-border rounded-3xl transition-all duration-700 hover:bg-theme-text/10 hover:-translate-y-[10px] hover:shadow-[0_30px_60px_-15px_rgba(0,0,0,0.3)] scroll-reveal tilt-card">
435
  <div className="mb-6 md:mb-8 lg:mb-10 inline-block p-5 rounded-2xl bg-theme-text/5 text-[var(--theme-text)] transition-transform group-hover:scale-110 duration-500">
436
  <Activity className="w-10 h-10 text-[var(--theme-text)]" strokeWidth={1.5} />
437
  </div>
438
+ <h3 className="text-xl md:text-2xl font-bold mb-6 text-[var(--theme-text)] transition-colors">Temporal Consistency (Video)</h3>
439
+ <p className="text-[#d0c4bb] leading-relaxed text-base md:text-lg">Analyzes frame-to-frame variation to detect unnatural motion, interpolation artifacts, and structural drift.</p>
440
  </div>
441
  <div className="glow-card dash-border group relative p-8 md:p-10 lg:p-12 bg-theme-text/5 backdrop-blur-sm border border-theme-border rounded-3xl transition-all duration-700 hover:bg-theme-text/10 hover:-translate-y-[10px] hover:shadow-[0_30px_60px_-15px_rgba(0,0,0,0.3)] scroll-reveal tilt-card">
442
  <div className="mb-6 md:mb-8 lg:mb-10 inline-block p-5 rounded-2xl bg-theme-text/5 text-[var(--theme-text)] transition-transform group-hover:scale-110 duration-500">
443
  <Network className="w-10 h-10 text-[var(--theme-text)]" strokeWidth={1.5} />
444
  </div>
445
+ <h3 className="text-xl md:text-2xl font-bold mb-6 text-[var(--theme-text)] transition-colors">Frequency Domain Analysis</h3>
446
+ <p className="text-[#d0c4bb] leading-relaxed text-base md:text-lg">Uses Fourier-based features to detect unnatural frequency distributions and over-smooth textures common in AI-generated media.</p>
447
  </div>
448
  </div>
449
  </section>
 
467
  </div>
468
  <div className="lg:w-1/2 order-1 lg:order-2">
469
  <label className="uppercase tracking-[0.4em] text-[#d0c4bb] mb-8 block text-xs">Transparent Logic</label>
470
+ <h2 className="text-6xl md:text-8xl font-black tracking-tighter mb-10 leading-[0.95] text-[var(--theme-text)]">Explainable<br />Detection</h2>
471
+ <p className="text-[#d0c4bb] text-xl leading-relaxed mb-12">Spotix highlights regions that contribute most to the detection score, allowing users to visually understand why a sample is flagged.</p>
472
  <div className="grid grid-cols-2 gap-12">
473
  <div>
474
+ <div className="text-[var(--theme-text)] text-3xl font-bold mb-3">0.85</div>
475
  <div className="text-[10px] uppercase tracking-[0.2em] text-[#d0c4bb] font-semibold">Confidence Threshold</div>
476
  </div>
477
  <div>
478
+ <div className="text-[var(--theme-text)] text-3xl font-bold mb-3">Multi-signal Fusion</div>
479
+ <div className="text-[10px] uppercase tracking-[0.2em] text-[#d0c4bb] font-semibold">Decision Model</div>
480
  </div>
481
  </div>
482
  </div>
 
488
  <footer className="bg-[var(--theme-bg)] w-full border-t border-theme-border relative z-10">
489
  <div className="flex flex-col md:flex-row justify-between items-center px-12 py-24 gap-12 max-w-[1920px] mx-auto">
490
  <div className="flex flex-col items-center md:items-start gap-4">
491
+ <div className="text-2xl font-black text-[var(--theme-text)] uppercase">SPOTIX</div>
492
+ <div className="font-['Inter'] uppercase tracking-[0.15em] text-[9px] text-[#d0c4bb] opacity-60">&copy; {year} SPOTIX KINETIC. ENGINEERED FOR THE ETHEREAL.</div>
493
  </div>
494
  <div className="flex flex-wrap justify-center gap-x-12 gap-y-6 items-center">
 
495
  <a className="font-['Inter'] uppercase tracking-[0.2em] text-[10px] text-[#d0c4bb] transition-all duration-300 flex items-center gap-2 group hover:text-green-400 hover:drop-shadow-[0_0_8px_rgba(74,222,128,0.5)] cursor-pointer" href="#">
496
  <span>System Status</span>
497
  <span className="text-[9px] bg-[var(--theme-text)]/5 px-2 py-0.5 rounded-full border border-[var(--theme-text)]/10 group-hover:border-green-500/30 group-hover:bg-green-500/10 flex items-center gap-1.5 transition-colors">
frontend/components/dashboard/HistoryGrid.tsx CHANGED
@@ -95,7 +95,7 @@ export default function HistoryGrid({ files, onDeleteFile }: { files: any[], onD
95
  <div className="flex-1 min-w-0 !cursor-none">
96
  <p className="text-[var(--theme-text)] text-sm font-medium truncate group-hover:text-[var(--theme-text)]/80 transition-colors !cursor-none">{file.filename || `Analysis_${file.id.substring(0,6)}`}</p>
97
  <p className="text-[var(--theme-text)]/30 text-xs font-mono mt-1 !cursor-none">
98
- {file.uploaded_at ? new Date(file.uploaded_at.endsWith('Z') ? file.uploaded_at : file.uploaded_at + 'Z').toLocaleString('en-US', { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' }) : 'Unknown Date'}
99
  </p>
100
  </div>
101
  </div>
 
95
  <div className="flex-1 min-w-0 !cursor-none">
96
  <p className="text-[var(--theme-text)] text-sm font-medium truncate group-hover:text-[var(--theme-text)]/80 transition-colors !cursor-none">{file.filename || `Analysis_${file.id.substring(0,6)}`}</p>
97
  <p className="text-[var(--theme-text)]/30 text-xs font-mono mt-1 !cursor-none">
98
+ {file.uploaded_at ? new Date(file.uploaded_at.endsWith('Z') ? file.uploaded_at : file.uploaded_at + 'Z').toLocaleString(undefined, { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' }) : 'Unknown Date'}
99
  </p>
100
  </div>
101
  </div>