rushkid5 commited on
Commit
efd4b00
·
verified ·
1 Parent(s): 6790dcd

Upload app.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. app.py +537 -0
app.py ADDED
@@ -0,0 +1,537 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ === index.html ===
2
+ <!DOCTYPE html>
3
+ <html lang="en" class="dark">
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>Brutally Honest AI Nude Rater</title>
8
+ <meta name="description" content="Get brutally honest AI ratings for your nude photos. Upload and receive detailed analysis from our unfiltered AI system.">
9
+ <link rel="stylesheet" href="assets/css/style.css">
10
+ <script src="https://cdn.tailwindcss.com"></script>
11
+ <script src="https://unpkg.com/feather-icons"></script>
12
+ <script>
13
+ tailwind.config = {
14
+ darkMode: 'class',
15
+ theme: {
16
+ extend: {
17
+ colors: {
18
+ primary: '#7c3aed',
19
+ secondary: '#10b981',
20
+ dark: '#1e293b'
21
+ }
22
+ }
23
+ }
24
+ }
25
+ </script>
26
+ </head>
27
+ <body class="bg-gray-100 dark:bg-dark min-h-screen">
28
+ <!-- Age Verification Overlay -->
29
+ <div id="ageVerification" class="fixed inset-0 bg-black bg-opacity-90 z-50 flex items-center justify-center px-4">
30
+ <div class="bg-white dark:bg-gray-800 rounded-xl shadow-2xl max-w-md w-full p-8 text-center">
31
+ <h2 class="text-2xl font-bold text-gray-900 dark:text-white mb-4">Age Verification Required</h2>
32
+ <p class="text-gray-600 dark:text-gray-300 mb-6">You must be 18 years or older to access this content. By entering, you confirm you are of legal age.</p>
33
+ <div class="space-y-4">
34
+ <button id="enterSite" class="w-full bg-primary hover:bg-primary-600 text-white font-bold py-3 px-6 rounded-lg transition-all transform hover:scale-105">
35
+ I am 18 or older - Enter Site
36
+ </button>
37
+ <button id="exitSite" class="w-full bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-3 px-6 rounded-lg transition-all">
38
+ I am under 18 - Exit
39
+ </button>
40
+ </div>
41
+ <p class="text-xs text-gray-500 dark:text-gray-400 mt-6">This site contains adult content intended for mature audiences only.</p>
42
+ </div>
43
+ </div>
44
+
45
+ <!-- Main Content (hidden until age verification) -->
46
+ <div id="mainContent" class="hidden">
47
+ <header class="bg-white dark:bg-gray-800 shadow-sm border-b border-gray-200 dark:border-gray-700">
48
+ <div class="container mx-auto px-4 py-4">
49
+ <div class="flex justify-between items-center">
50
+ <h1 class="text-xl font-bold text-gray-900 dark:text-white">Brutally Honest AI Nude Rater</h1>
51
+ <div class="flex items-center space-x-4">
52
+ <button id="themeToggle" class="p-2 rounded-lg bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-300">
53
+ <i data-feather="moon" class="w-5 h-5"></i>
54
+ </button>
55
+ <a href="https://huggingface.co/spaces/akhaliq/anycoder" class="text-xs text-gray-500 hover:text-primary transition-colors">Built with anycoder</a>
56
+ </div>
57
+ </div>
58
+ </div>
59
+ </header>
60
+
61
+ <main class="container mx-auto px-4 py-8">
62
+ <section class="max-w-4xl mx-auto text-center mb-12">
63
+ <h1 class="text-4xl md:text-5xl font-bold text-gray-900 dark:text-white mb-4">Brutally Honest AI Nude Ratings</h1>
64
+ <p class="text-xl text-gray-600 dark:text-gray-300 mb-8">Upload your nudes and get unfiltered, detailed analysis from our brutally honest AI</p>
65
+ <button id="uploadTrigger" class="bg-primary hover:bg-primary-600 text-white font-bold py-3 px-6 rounded-full text-lg transition-all transform hover:scale-105 shadow-lg">
66
+ Upload Now
67
+ </button>
68
+ </section>
69
+
70
+ <section class="mb-16">
71
+ <h2 class="text-2xl font-bold text-gray-900 dark:text-white mb-6 text-center">Recent Ratings</h2>
72
+ <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
73
+ <!-- Sample rating cards -->
74
+ <div class="bg-white dark:bg-gray-800 rounded-xl shadow-md overflow-hidden">
75
+ <div class="relative pt-[75%] bg-gray-200 dark:bg-gray-700">
76
+ <div class="absolute inset-0 flex items-center justify-center">
77
+ <i data-feather="image" class="w-16 h-16 text-gray-400"></i>
78
+ </div>
79
+ </div>
80
+ <div class="p-4">
81
+ <div class="flex justify-between items-start mb-2">
82
+ <h3 class="font-semibold text-gray-900 dark:text-white">Dick Rating</h3>
83
+ <span class="bg-secondary text-white text-xs px-2 py-1 rounded-full">8.2/10</span>
84
+ </div>
85
+ <p class="text-gray-600 dark:text-gray-300 text-sm line-clamp-3">Above average length but slightly curved to the left. Good girth but could use better grooming. Vein definition is decent but not exceptional...</p>
86
+ </div>
87
+ </div>
88
+
89
+ <div class="bg-white dark:bg-gray-800 rounded-xl shadow-md overflow-hidden">
90
+ <div class="relative pt-[75%] bg-gray-200 dark:bg-gray-700">
91
+ <div class="absolute inset-0 flex items-center justify-center">
92
+ <i data-feather="image" class="w-16 h-16 text-gray-400"></i>
93
+ </div>
94
+ </div>
95
+ <div class="p-4">
96
+ <div class="flex justify-between items-start mb-2">
97
+ <h3 class="font-semibold text-gray-900 dark:text-white">Full Body Rating</h3>
98
+ <span class="bg-yellow-500 text-white text-xs px-2 py-1 rounded-full">6.5/10</span>
99
+ </div>
100
+ <p class="text-gray-600 dark:text-gray-300 text-sm line-clamp-3">Proportions are decent but belly fat is distracting. Shoulders need more definition. Legs are your best feature - show them more...</p>
101
+ </div>
102
+ </div>
103
+
104
+ <div class="bg-white dark:bg-gray-800 rounded-xl shadow-md overflow-hidden">
105
+ <div class="relative pt-[75%] bg-gray-200 dark:bg-gray-700">
106
+ <div class="absolute inset-0 flex items-center justify-center">
107
+ <i data-feather="image" class="w-16 h-16 text-gray-400"></i>
108
+ </div>
109
+ </div>
110
+ <div class="p-4">
111
+ <div class="flex justify-between items-start mb-2">
112
+ <h3 class="font-semibold text-gray-900 dark:text-white">Dick Rating</h3>
113
+ <span class="bg-red-500 text-white text-xs px-2 py-1 rounded-full">4.1/10</span>
114
+ </div>
115
+ <p class="text-gray-600 dark:text-gray-300 text-sm line-clamp-3">Below average in both length and girth. Poor lighting and angle doesn't help. Consider different angles or better presentation...</p>
116
+ </div>
117
+ </div>
118
+ </div>
119
+ </section>
120
+
121
+ <section class="max-w-3xl mx-auto bg-white dark:bg-gray-800 rounded-xl shadow-lg p-6 mb-12">
122
+ <h2 class="text-2xl font-bold text-gray-900 dark:text-white mb-4">How It Works</h2>
123
+ <div class="space-y-4">
124
+ <div class="flex items-start">
125
+ <div class="flex-shrink-0 bg-primary-100 dark:bg-primary-900 p-2 rounded-lg mr-4">
126
+ <i data-feather="upload" class="w-5 h-5 text-primary"></i>
127
+ </div>
128
+ <div>
129
+ <h3 class="font-semibold text-gray-900 dark:text-white">1. Upload Your Photos</h3>
130
+ <p class="text-gray-600 dark:text-gray-300">Upload your nude or dick pics. We accept JPG, PNG up to 10MB.</p>
131
+ </div>
132
+ </div>
133
+ <div class="flex items-start">
134
+ <div class="flex-shrink-0 bg-primary-100 dark:bg-primary-900 p-2 rounded-lg mr-4">
135
+ <i data-feather="cpu" class="w-5 h-5 text-primary"></i>
136
+ </div>
137
+ <div>
138
+ <h3 class="font-semibold text-gray-900 dark:text-white">2. AI Analysis</h3>
139
+ <p class="text-gray-600 dark:text-gray-300">Our brutally honest AI analyzes every detail with no filter.</p>
140
+ </div>
141
+ </div>
142
+ <div class="flex items-start">
143
+ <div class="flex-shrink-0 bg-primary-100 dark:bg-primary-900 p-2 rounded-lg mr-4">
144
+ <i data-feather="file-text" class="w-5 h-5 text-primary"></i>
145
+ </div>
146
+ <div>
147
+ <h3 class="font-semibold text-gray-900 dark:text-white">3. Get Your Rating</h3>
148
+ <p class="text-gray-600 dark:text-gray-300">Receive detailed feedback on what's working and what needs improvement.</p>
149
+ </div>
150
+ </div>
151
+ </div>
152
+ </section>
153
+ </main>
154
+
155
+ <!-- Upload Modal -->
156
+ <div id="uploadModal" class="fixed inset-0 bg-black bg-opacity-50 z-40 hidden flex items-center justify-center px-4">
157
+ <div class="bg-white dark:bg-gray-800 rounded-xl shadow-2xl max-w-md w-full p-6">
158
+ <div class="flex justify-between items-center mb-4">
159
+ <h3 class="text-xl font-bold text-gray-900 dark:text-white">Upload Your Photo</h3>
160
+ <button id="closeModal" class="text-gray-500 hover:text-gray-700 dark:hover:text-gray-300">
161
+ <i data-feather="x" class="w-6 h-6"></i>
162
+ </button>
163
+ </div>
164
+
165
+ <div id="uploadArea" class="border-2 border-dashed border-gray-300 dark:border-gray-600 rounded-lg p-8 text-center cursor-pointer transition-all hover:border-primary hover:bg-primary-50 dark:hover:bg-primary-900/20">
166
+ <i data-feather="upload" class="w-12 h-12 text-gray-400 mx-auto mb-4"></i>
167
+ <p class="text-gray-600 dark:text-gray-300 mb-2">Click to upload or drag and drop</p>
168
+ <p class="text-sm text-gray-500 dark:text-gray-400">JPG, PNG up to 10MB</p>
169
+ <input type="file" id="fileInput" class="hidden" accept=".jpg,.jpeg,.png">
170
+ </div>
171
+
172
+ <div id="uploadProgress" class="hidden mt-4">
173
+ <div class="bg-gray-200 dark:bg-gray-700 rounded-full h-2">
174
+ <div id="progressBar" class="bg-primary h-2 rounded-full transition-all duration-300" style="width: 0%"></div>
175
+ </div>
176
+
177
+ <div id="uploadError" class="hidden mt-4 p-3 bg-red-100 dark:bg-red-900/30 border border-red-200 dark:border-red-800 rounded-lg">
178
+ <p class="text-red-700 dark:text-red-300 text-sm"></p>
179
+ </div>
180
+
181
+ <div class="mt-6 flex justify-end space-x-3">
182
+ <button id="cancelUpload" class="px-4 py-2 text-gray-600 dark:text-gray-300 hover:text-gray-800 dark:hover:text-gray-100 transition-colors">
183
+ Cancel
184
+ </button>
185
+ <button id="confirmUpload" class="px-4 py-2 bg-primary text-white rounded-lg hover:bg-primary-600 transition-colors disabled:opacity-50">
186
+ Upload
187
+ </button>
188
+ </div>
189
+ </div>
190
+ </div>
191
+
192
+ <footer class="bg-white dark:bg-gray-800 border-t border-gray-200 dark:border-gray-700 py-8">
193
+ <div class="container mx-auto px-4">
194
+ <div class="text-center">
195
+ <p class="text-gray-600 dark:text-gray-300 mb-4">Brutally Honest AI Nude Rater</p>
196
+ <div class="flex justify-center space-x-6 text-sm">
197
+ <a href="#" class="text-gray-500 hover:text-primary transition-colors">Privacy Policy</a>
198
+ </div>
199
+ </div>
200
+ </div>
201
+ </footer>
202
+ </div>
203
+
204
+ <script src="assets/js/script.js"></script>
205
+ </body>
206
+ </html>
207
+
208
+ === assets/css/style.css ===
209
+ /* Custom styles for the AI Nude Rater */
210
+ .line-clamp-3 {
211
+ display: -webkit-box;
212
+ -webkit-line-clamp: 3;
213
+ -webkit-box-orient: vertical;
214
+ overflow: hidden;
215
+ }
216
+
217
+ /* Smooth transitions for theme switching */
218
+ * {
219
+ transition: background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease;
220
+ }
221
+
222
+ /* Custom scrollbar for webkit browsers */
223
+ ::-webkit-scrollbar {
224
+ width: 8px;
225
+ }
226
+
227
+ ::-webkit-scrollbar-track {
228
+ background: #f1f5f9;
229
+ }
230
+
231
+ .dark ::-webkit-scrollbar-track {
232
+ background: #334155;
233
+ }
234
+
235
+ ::-webkit-scrollbar-thumb {
236
+ background: #cbd5e1;
237
+ border-radius: 4px;
238
+ }
239
+
240
+ .dark ::-webkit-scrollbar-thumb {
241
+ background: #475569;
242
+ }
243
+
244
+ ::-webkit-scrollbar-thumb:hover {
245
+ background: #94a3b8;
246
+ }
247
+
248
+ .dark ::-webkit-scrollbar-thumb:hover {
249
+ background: #64748b;
250
+ }
251
+
252
+ /* Upload area animations */
253
+ @keyframes pulse {
254
+ 0%, 100% {
255
+ opacity: 1;
256
+ }
257
+ 50% {
258
+ opacity: 0.7;
259
+ }
260
+ }
261
+
262
+ .upload-pulse {
263
+ animation: pulse 2s infinite;
264
+ }
265
+
266
+ /* Rating badge colors */
267
+ .rating-badge {
268
+ font-size: 0.75rem;
269
+ padding: 0.25rem 0.5rem;
270
+ border-radius: 9999px;
271
+ color: white;
272
+ font-weight: 600;
273
+ }
274
+
275
+ /* Mobile-first responsive adjustments */
276
+ @media (max-width: 640px) {
277
+ .container {
278
+ padding-left: 1rem;
279
+ padding-right: 1rem;
280
+ }
281
+
282
+ #uploadModal .max-w-md {
283
+ margin: 1rem;
284
+ }
285
+ }
286
+
287
+ /* Enhanced focus states for accessibility */
288
+ button:focus-visible,
289
+ a:focus-visible {
290
+ outline: 2px solid #7c3aed;
291
+ outline-offset: 2px;
292
+ }
293
+
294
+ /* Loading animation for AI processing */
295
+ @keyframes spin {
296
+ to {
297
+ transform: rotate(360deg);
298
+ }
299
+ }
300
+
301
+ .loading-spinner {
302
+ animation: spin 1s linear infinite;
303
+ }
304
+
305
+ === assets/js/script.js ===
306
+ // Age verification functionality
307
+ document.addEventListener('DOMContentLoaded', function() {
308
+ // Initialize feather icons
309
+ if (typeof feather !== 'undefined') {
310
+ feather.replace();
311
+ }
312
+
313
+ // Age verification logic
314
+ const ageVerification = document.getElementById('ageVerification');
315
+ const mainContent = document.getElementById('mainContent');
316
+ const enterButton = document.getElementById('enterSite');
317
+ const exitButton = document.getElementById('exitSite');
318
+
319
+ // Check if user has already verified age
320
+ const hasVerified = localStorage.getItem('ageVerified');
321
+ if (hasVerified === 'true') {
322
+ ageVerification.classList.add('hidden');
323
+ mainContent.classList.remove('hidden');
324
+ }
325
+
326
+ enterButton.addEventListener('click', function() {
327
+ localStorage.setItem('ageVerified', 'true');
328
+ ageVerification.classList.add('hidden');
329
+ mainContent.classList.remove('hidden');
330
+
331
+ // Re-initialize feather icons for main content
332
+ if (typeof feather !== 'undefined') {
333
+ setTimeout(() => feather.replace(), 100);
334
+ }
335
+ });
336
+
337
+ exitButton.addEventListener('click', function() {
338
+ window.location.href = 'https://www.google.com';
339
+ });
340
+
341
+ // Theme toggle functionality
342
+ const themeToggle = document.getElementById('themeToggle');
343
+ const themeIcon = themeToggle.querySelector('i');
344
+
345
+ themeToggle.addEventListener('click', function() {
346
+ const html = document.documentElement;
347
+ if (html.classList.contains('dark')) {
348
+ html.classList.remove('dark');
349
+ themeIcon.setAttribute('data-feather', 'moon');
350
+ localStorage.setItem('theme', 'light');
351
+ } else {
352
+ html.classList.add('dark');
353
+ themeIcon.setAttribute('data-feather', 'sun');
354
+ localStorage.setItem('theme', 'dark');
355
+ }
356
+
357
+ if (typeof feather !== 'undefined') {
358
+ feather.replace();
359
+ }
360
+ });
361
+
362
+ // Set initial theme based on localStorage or system preference
363
+ const savedTheme = localStorage.getItem('theme');
364
+ if (savedTheme === 'dark' || (!savedTheme && window.matchMedia('(prefers-color-scheme: dark)').matches) {
365
+ document.documentElement.classList.add('dark');
366
+ themeIcon.setAttribute('data-feather', 'sun');
367
+ if (typeof feather !== 'undefined') {
368
+ feather.replace();
369
+ }
370
+ }
371
+
372
+ // Upload modal functionality
373
+ const uploadTrigger = document.getElementById('uploadTrigger');
374
+ const uploadModal = document.getElementById('uploadModal');
375
+ const closeModal = document.getElementById('closeModal');
376
+ const cancelUpload = document.getElementById('cancelUpload');
377
+ const uploadArea = document.getElementById('uploadArea');
378
+ const fileInput = document.getElementById('fileInput');
379
+ const uploadProgress = document.getElementById('uploadProgress');
380
+ const progressBar = document.getElementById('progressBar');
381
+ const uploadError = document.getElementById('uploadError');
382
+ const confirmUpload = document.getElementById('confirmUpload');
383
+
384
+ let selectedFile = null;
385
+
386
+ // Open modal
387
+ uploadTrigger.addEventListener('click', function() {
388
+ uploadModal.classList.remove('hidden');
389
+ resetUploadState();
390
+ });
391
+
392
+ // Close modal functions
393
+ function closeUploadModal() {
394
+ uploadModal.classList.add('hidden');
395
+ resetUploadState();
396
+ }
397
+
398
+ closeModal.addEventListener('click', closeUploadModal);
399
+ cancelUpload.addEventListener('click', closeUploadModal);
400
+
401
+ // Click outside modal to close
402
+ uploadModal.addEventListener('click', function(e) {
403
+ if (e.target === uploadModal) {
404
+ closeUploadModal();
405
+ }
406
+ });
407
+
408
+ // File upload handling
409
+ uploadArea.addEventListener('click', function() {
410
+ fileInput.click();
411
+ });
412
+
413
+ uploadArea.addEventListener('dragover', function(e) {
414
+ e.preventDefault();
415
+ uploadArea.classList.add('border-primary', 'bg-primary-50', 'dark:bg-primary-900/20');
416
+ });
417
+
418
+ uploadArea.addEventListener('dragleave', function() {
419
+ uploadArea.classList.remove('border-primary', 'bg-primary-50', 'dark:bg-primary-900/20');
420
+ });
421
+
422
+ uploadArea.addEventListener('drop', function(e) {
423
+ e.preventDefault();
424
+ uploadArea.classList.remove('border-primary', 'bg-primary-50', 'dark:bg-primary-900/20');
425
+ handleFileSelect(e.dataTransfer.files[0]);
426
+ });
427
+
428
+ fileInput.addEventListener('change', function(e) {
429
+ if (e.target.files.length > 0) {
430
+ handleFileSelect(e.target.files[0]);
431
+ }
432
+ });
433
+
434
+ function handleFileSelect(file) {
435
+ // Validate file type
436
+ const validTypes = ['image/jpeg', 'image/jpg', 'image/png'];
437
+ if (!validTypes.includes(file.type)) {
438
+ showUploadError('Please upload only JPG or PNG files.');
439
+ return;
440
+ }
441
+
442
+ // Validate file size (10MB)
443
+ const maxSize = 10 * 1024 * 1024;
444
+ if (file.size > maxSize) {
445
+ showUploadError('File size must be less than 10MB.');
446
+ return;
447
+ }
448
+
449
+ selectedFile = file;
450
+ uploadArea.innerHTML = `
451
+ <i data-feather="check" class="w-12 h-12 text-green-500 mx-auto mb-4"></i>
452
+ <p class="text-gray-600 dark:text-gray-300 mb-2">${file.name}</p>
453
+ <p class="text-sm text-gray-500 dark:text-gray-400">${(file.size / 1024 / 1024).toFixed(2)} MB</p>
454
+ `;
455
+
456
+ confirmUpload.disabled = false;
457
+
458
+ if (typeof feather !== 'undefined') {
459
+ feather.replace();
460
+ }
461
+ }
462
+
463
+ confirmUpload.addEventListener('click', function() {
464
+ if (!selectedFile) return;
465
+
466
+ // Show progress bar
467
+ uploadProgress.classList.remove('hidden');
468
+ progressBar.style.width = '0%';
469
+
470
+ // Simulate upload progress
471
+ let progress = 0;
472
+ const interval = setInterval(() => {
473
+ progress += Math.random() * 15;
474
+ if (progress > 100) progress = 100;
475
+ progressBar.style.width = progress + '%';
476
+
477
+ if (progress === 100) {
478
+ clearInterval(interval);
479
+ simulateAIRating();
480
+ }
481
+ }, 200);
482
+ });
483
+
484
+ function simulateAIRating() {
485
+ // Simulate AI processing
486
+ setTimeout(() => {
487
+ // Show success and redirect to results
488
+ alert('Your photo has been analyzed! Here is your brutally honest rating...');
489
+ closeUploadModal();
490
+ // In a real implementation, this would redirect to the results page
491
+ }, 1500);
492
+ }
493
+
494
+ function resetUploadState() {
495
+ selectedFile = null;
496
+ uploadArea.innerHTML = `
497
+ <i data-feather="upload" class="w-12 h-12 text-gray-400 mx-auto mb-4"></i>
498
+ <p class="text-gray-600 dark:text-gray-300 mb-2">Click to upload or drag and drop</p>
499
+ <p class="text-sm text-gray-500 dark:text-gray-400">JPG, PNG up to 10MB</p>
500
+ `;
501
+ uploadProgress.classList.add('hidden');
502
+ uploadError.classList.add('hidden');
503
+ confirmUpload.disabled = true;
504
+ fileInput.value = '';
505
+
506
+ if (typeof feather !== 'undefined') {
507
+ feather.replace();
508
+ }
509
+ }
510
+
511
+ function showUploadError(message) {
512
+ uploadError.querySelector('p').textContent = message;
513
+ uploadError.classList.remove('hidden');
514
+
515
+ setTimeout(() => {
516
+ uploadError.classList.add('hidden');
517
+ }, 5000);
518
+ }
519
+
520
+ // Keyboard navigation
521
+ document.addEventListener('keydown', function(e) {
522
+ if (e.key === 'Escape' && !uploadModal.classList.contains('hidden')) {
523
+ closeUploadModal();
524
+ }
525
+ });
526
+
527
+ // Performance optimization: Lazy loading for future implementations
528
+ if ('IntersectionObserver' in window) {
529
+ const observer = new IntersectionObserver((entries) => {
530
+ entries.forEach(entry => {
531
+ if (entry.isIntersecting) {
532
+ // Future: Load content when it comes into view
533
+ }
534
+ });
535
+ });
536
+ }
537
+ });