Wiuhh commited on
Commit
c551c9e
·
verified ·
1 Parent(s): 3e99e42

Create templates/index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +579 -0
templates/index.html ADDED
@@ -0,0 +1,579 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>AI Background Remover</title>
7
+ <style>
8
+ * {
9
+ margin: 0;
10
+ padding: 0;
11
+ box-sizing: border-box;
12
+ }
13
+
14
+ :root {
15
+ --bg-dark: hsl(240, 14%, 5%);
16
+ --bg-darker: hsl(240, 14%, 3%);
17
+ --bg-card: hsl(240, 10%, 7%);
18
+ --accent-purple: hsl(265, 100%, 61%);
19
+ --accent-pink: hsl(327, 100%, 72%);
20
+ --accent-blue: hsl(204, 100%, 72%);
21
+ --text-light: hsl(240, 5%, 90%);
22
+ --text-muted: hsl(240, 4%, 65%);
23
+ --text-error: hsl(0, 100%, 74%);
24
+ --border-accent: hsl(253, 100%, 72%, 0.15);
25
+ --gradient-purple-pink: linear-gradient(135deg, hsl(265, 100%, 61%), hsl(327, 100%, 72%));
26
+ --gradient-purple-blue: linear-gradient(135deg, hsl(265, 100%, 61%), hsl(204, 100%, 72%));
27
+ }
28
+
29
+ body {
30
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
31
+ background: var(--bg-dark);
32
+ color: var(--text-light);
33
+ min-height: 100vh;
34
+ display: flex;
35
+ flex-direction: column;
36
+ }
37
+
38
+ .container {
39
+ max-width: 1200px;
40
+ margin: 0 auto;
41
+ padding: 2rem;
42
+ flex: 1;
43
+ display: flex;
44
+ flex-direction: column;
45
+ gap: 2rem;
46
+ }
47
+
48
+ .header {
49
+ text-align: center;
50
+ margin-bottom: 2rem;
51
+ }
52
+
53
+ .header h1 {
54
+ font-size: clamp(2rem, 5vw, 3.5rem);
55
+ font-weight: 700;
56
+ background: var(--gradient-purple-pink);
57
+ -webkit-background-clip: text;
58
+ -webkit-text-fill-color: transparent;
59
+ background-clip: text;
60
+ margin-bottom: 1rem;
61
+ }
62
+
63
+ .header p {
64
+ font-size: clamp(1rem, 2.5vw, 1.25rem);
65
+ color: var(--text-muted);
66
+ max-width: 600px;
67
+ margin: 0 auto;
68
+ line-height: 1.6;
69
+ }
70
+
71
+ .upload-section {
72
+ background: var(--bg-card);
73
+ border: 2px dashed var(--border-accent);
74
+ border-radius: 20px;
75
+ padding: 3rem 2rem;
76
+ text-align: center;
77
+ transition: all 0.3s ease;
78
+ cursor: pointer;
79
+ position: relative;
80
+ overflow: hidden;
81
+ }
82
+
83
+ .upload-section:hover {
84
+ border-color: var(--accent-purple);
85
+ transform: translateY(-2px);
86
+ }
87
+
88
+ .upload-section::before {
89
+ content: '';
90
+ position: absolute;
91
+ top: 0;
92
+ left: 0;
93
+ right: 0;
94
+ bottom: 0;
95
+ background: var(--gradient-purple-pink);
96
+ opacity: 0;
97
+ transition: opacity 0.3s ease;
98
+ z-index: -1;
99
+ }
100
+
101
+ .upload-section:hover::before {
102
+ opacity: 0.05;
103
+ }
104
+
105
+ .upload-icon {
106
+ width: 80px;
107
+ height: 80px;
108
+ margin: 0 auto 1.5rem;
109
+ background: var(--gradient-purple-blue);
110
+ border-radius: 50%;
111
+ display: flex;
112
+ align-items: center;
113
+ justify-content: center;
114
+ font-size: 2rem;
115
+ }
116
+
117
+ .upload-text h3 {
118
+ font-size: 1.5rem;
119
+ margin-bottom: 0.5rem;
120
+ color: var(--text-light);
121
+ }
122
+
123
+ .upload-text p {
124
+ color: var(--text-muted);
125
+ margin-bottom: 1.5rem;
126
+ }
127
+
128
+ .file-input {
129
+ display: none;
130
+ }
131
+
132
+ .btn {
133
+ background: var(--gradient-purple-pink);
134
+ border: none;
135
+ padding: 1rem 2rem;
136
+ border-radius: 12px;
137
+ color: white;
138
+ font-weight: 600;
139
+ font-size: 1rem;
140
+ cursor: pointer;
141
+ transition: all 0.3s ease;
142
+ display: inline-flex;
143
+ align-items: center;
144
+ gap: 0.5rem;
145
+ text-decoration: none;
146
+ }
147
+
148
+ .btn:hover {
149
+ transform: translateY(-2px);
150
+ box-shadow: 0 10px 25px hsla(265, 100%, 61%, 0.3);
151
+ }
152
+
153
+ .btn:disabled {
154
+ opacity: 0.6;
155
+ cursor: not-allowed;
156
+ transform: none;
157
+ }
158
+
159
+ .processing-section {
160
+ display: none;
161
+ background: var(--bg-card);
162
+ border-radius: 20px;
163
+ padding: 2rem;
164
+ text-align: center;
165
+ border: 1px solid var(--border-accent);
166
+ }
167
+
168
+ .processing-section.active {
169
+ display: block;
170
+ }
171
+
172
+ .loading-spinner {
173
+ width: 60px;
174
+ height: 60px;
175
+ margin: 0 auto 1rem;
176
+ border: 4px solid var(--bg-dark);
177
+ border-top: 4px solid var(--accent-purple);
178
+ border-radius: 50%;
179
+ animation: spin 1s linear infinite;
180
+ }
181
+
182
+ @keyframes spin {
183
+ 0% { transform: rotate(0deg); }
184
+ 100% { transform: rotate(360deg); }
185
+ }
186
+
187
+ .result-section {
188
+ display: none;
189
+ background: var(--bg-card);
190
+ border-radius: 20px;
191
+ padding: 2rem;
192
+ border: 1px solid var(--border-accent);
193
+ }
194
+
195
+ .result-section.active {
196
+ display: block;
197
+ }
198
+
199
+ .image-comparison {
200
+ display: grid;
201
+ grid-template-columns: 1fr 1fr;
202
+ gap: 2rem;
203
+ margin-bottom: 2rem;
204
+ }
205
+
206
+ .image-container {
207
+ text-align: center;
208
+ }
209
+
210
+ .image-container h4 {
211
+ margin-bottom: 1rem;
212
+ color: var(--text-light);
213
+ }
214
+
215
+ .image-container img {
216
+ max-width: 100%;
217
+ max-height: 300px;
218
+ border-radius: 12px;
219
+ border: 1px solid var(--border-accent);
220
+ }
221
+
222
+ .download-section {
223
+ text-align: center;
224
+ padding-top: 1rem;
225
+ border-top: 1px solid var(--border-accent);
226
+ }
227
+
228
+ .error-message {
229
+ background: var(--bg-card);
230
+ border: 1px solid var(--text-error);
231
+ border-radius: 12px;
232
+ padding: 1rem;
233
+ color: var(--text-error);
234
+ margin-top: 1rem;
235
+ display: none;
236
+ }
237
+
238
+ .error-message.active {
239
+ display: block;
240
+ }
241
+
242
+ .features {
243
+ display: grid;
244
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
245
+ gap: 1.5rem;
246
+ margin-top: 3rem;
247
+ }
248
+
249
+ .feature-card {
250
+ background: var(--bg-card);
251
+ border: 1px solid var(--border-accent);
252
+ border-radius: 16px;
253
+ padding: 1.5rem;
254
+ text-align: center;
255
+ transition: transform 0.3s ease;
256
+ }
257
+
258
+ .feature-card:hover {
259
+ transform: translateY(-4px);
260
+ }
261
+
262
+ .feature-icon {
263
+ width: 50px;
264
+ height: 50px;
265
+ margin: 0 auto 1rem;
266
+ background: var(--gradient-purple-blue);
267
+ border-radius: 12px;
268
+ display: flex;
269
+ align-items: center;
270
+ justify-content: center;
271
+ font-size: 1.5rem;
272
+ }
273
+
274
+ .feature-card h4 {
275
+ margin-bottom: 0.5rem;
276
+ color: var(--text-light);
277
+ }
278
+
279
+ .feature-card p {
280
+ color: var(--text-muted);
281
+ font-size: 0.9rem;
282
+ line-height: 1.5;
283
+ }
284
+
285
+ /* Mobile Responsiveness */
286
+ @media (max-width: 768px) {
287
+ .container {
288
+ padding: 1rem;
289
+ gap: 1.5rem;
290
+ }
291
+
292
+ .upload-section {
293
+ padding: 2rem 1rem;
294
+ }
295
+
296
+ .upload-icon {
297
+ width: 60px;
298
+ height: 60px;
299
+ font-size: 1.5rem;
300
+ }
301
+
302
+ .image-comparison {
303
+ grid-template-columns: 1fr;
304
+ gap: 1rem;
305
+ }
306
+
307
+ .features {
308
+ grid-template-columns: 1fr;
309
+ gap: 1rem;
310
+ }
311
+
312
+ .btn {
313
+ padding: 0.875rem 1.5rem;
314
+ font-size: 0.9rem;
315
+ }
316
+ }
317
+
318
+ @media (max-width: 480px) {
319
+ .header h1 {
320
+ font-size: 2rem;
321
+ }
322
+
323
+ .header p {
324
+ font-size: 1rem;
325
+ }
326
+
327
+ .upload-section {
328
+ padding: 1.5rem 0.75rem;
329
+ }
330
+
331
+ .feature-card {
332
+ padding: 1rem;
333
+ }
334
+ }
335
+ </style>
336
+ </head>
337
+ <body>
338
+ <div class="container">
339
+ <header class="header">
340
+ <h1>AI Background Remover</h1>
341
+ </header>
342
+
343
+ <main>
344
+ <!-- Upload Section -->
345
+ <section class="upload-section" id="uploadSection">
346
+ <div class="upload-icon">
347
+ <svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
348
+ <path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"></path>
349
+ <circle cx="12" cy="13" r="4"></circle>
350
+ </svg>
351
+ </div>
352
+ <div class="upload-text">
353
+ <h3>Drop your image here</h3>
354
+ <p>or click to browse your files</p>
355
+ <button class="btn" onclick="document.getElementById('fileInput').click()">
356
+ Choose Image
357
+ </button>
358
+ </div>
359
+ <input type="file" id="fileInput" class="file-input" accept="image/*" onchange="handleFileSelect(event)">
360
+ </section>
361
+
362
+ <!-- Processing Section -->
363
+ <section class="processing-section" id="processingSectionElement">
364
+ <div class="loading-spinner"></div>
365
+ <h3>Processing your image...</h3>
366
+ <p>Our AI is removing the background. This usually takes a few seconds.</p>
367
+ </section>
368
+
369
+ <!-- Result Section -->
370
+ <section class="result-section" id="resultSection">
371
+ <div class="image-comparison">
372
+ <div class="image-container">
373
+ <h4>Original</h4>
374
+ <img id="originalImage" src="" alt="Original image">
375
+ </div>
376
+ <div class="image-container">
377
+ <h4>Background Removed</h4>
378
+ <img id="processedImage" src="" alt="Processed image">
379
+ </div>
380
+ </div>
381
+ <div class="download-section">
382
+ <button class="btn" id="downloadBtn">
383
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
384
+ <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
385
+ <polyline points="7,10 12,15 17,10"></polyline>
386
+ <line x1="12" y1="15" x2="12" y2="3"></line>
387
+ </svg>
388
+ Download Result
389
+ </button>
390
+ <button class="btn" onclick="resetApp()" style="background: var(--gradient-purple-blue); margin-left: 1rem;">
391
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
392
+ <polyline points="1,4 1,10 7,10"></polyline>
393
+ <path d="M3.51 15a9 9 0 1 0 2.13-9.36L1 10"></path>
394
+ </svg>
395
+ Process Another
396
+ </button>
397
+ </div>
398
+ </section>
399
+
400
+ <!-- Error Message -->
401
+ <div class="error-message" id="errorMessage">
402
+ <strong>Error:</strong> <span id="errorText"></span>
403
+ </div>
404
+ </main>
405
+
406
+ <!-- Features Section -->
407
+ <section class="features">
408
+ <div class="feature-card">
409
+ <div class="feature-icon">
410
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
411
+ <rect x="3" y="11" width="18" height="10" rx="2" ry="2"></rect>
412
+ <circle cx="12" cy="5" r="2"></circle>
413
+ <path d="M12 7v4"></path>
414
+ <line x1="8" y1="16" x2="8" y2="16"></line>
415
+ <line x1="16" y1="16" x2="16" y2="16"></line>
416
+ </svg>
417
+ </div>
418
+ <h4>AI-Powered</h4>
419
+ <p>Advanced machine learning automatically detects and removes backgrounds with precision</p>
420
+ </div>
421
+ <div class="feature-card">
422
+ <div class="feature-icon">
423
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
424
+ <polygon points="13,2 3,14 12,14 11,22 21,10 12,10 13,2"></polygon>
425
+ </svg>
426
+ </div>
427
+ <h4>Lightning Fast</h4>
428
+ <p>Process your images in seconds, not minutes. Perfect for bulk editing workflows</p>
429
+ </div>
430
+ <div class="feature-card">
431
+ <div class="feature-icon">
432
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
433
+ <rect x="5" y="2" width="14" height="20" rx="2" ry="2"></rect>
434
+ <line x1="12" y1="18" x2="12.01" y2="18"></line>
435
+ </svg>
436
+ </div>
437
+ <h4>Mobile Friendly</h4>
438
+ <p>Works seamlessly on all devices - desktop, tablet, and mobile</p>
439
+ </div>
440
+ <div class="feature-card">
441
+ <div class="feature-icon">
442
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
443
+ <path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"></path>
444
+ </svg>
445
+ </div>
446
+ <h4>High Quality</h4>
447
+ <p>Preserve image quality while achieving clean, professional background removal</p>
448
+ </div>
449
+ </section>
450
+ </div>
451
+
452
+ <script>
453
+ let currentFile = null;
454
+
455
+ function handleFileSelect(event) {
456
+ const file = event.target.files[0];
457
+ if (!file) return;
458
+
459
+ // Validate file type
460
+ if (!file.type.startsWith('image/')) {
461
+ showError('Please select a valid image file (JPG, PNG, BMP, TIFF, WebP)');
462
+ return;
463
+ }
464
+
465
+ // Validate file size (max 10MB)
466
+ if (file.size > 10 * 1024 * 1024) {
467
+ showError('File size must be less than 10MB');
468
+ return;
469
+ }
470
+
471
+ currentFile = file;
472
+ processImage(file);
473
+ }
474
+
475
+ async function processImage(file) {
476
+ hideError();
477
+ showProcessing();
478
+
479
+ const formData = new FormData();
480
+ formData.append('image', file);
481
+
482
+ try {
483
+ const response = await fetch('/remove-background', {
484
+ method: 'POST',
485
+ body: formData
486
+ });
487
+
488
+ const result = await response.json();
489
+
490
+ if (response.ok) {
491
+ showResult(file, result.output_url);
492
+ } else {
493
+ showError(result.error || 'Failed to process image');
494
+ }
495
+ } catch (error) {
496
+ showError('Network error: ' + error.message);
497
+ }
498
+ }
499
+
500
+ function showProcessing() {
501
+ document.getElementById('uploadSection').style.display = 'none';
502
+ document.getElementById('processingSectionElement').classList.add('active');
503
+ document.getElementById('resultSection').classList.remove('active');
504
+ }
505
+
506
+ function showResult(originalFile, outputUrl) {
507
+ document.getElementById('processingSectionElement').classList.remove('active');
508
+ document.getElementById('resultSection').classList.add('active');
509
+
510
+ // Show original image
511
+ const reader = new FileReader();
512
+ reader.onload = function(e) {
513
+ document.getElementById('originalImage').src = e.target.result;
514
+ };
515
+ reader.readAsDataURL(originalFile);
516
+
517
+ // Show processed image
518
+ document.getElementById('processedImage').src = outputUrl;
519
+
520
+ // Set up download
521
+ document.getElementById('downloadBtn').onclick = function() {
522
+ const link = document.createElement('a');
523
+ link.href = outputUrl;
524
+ link.download = `removed_bg_${originalFile.name.split('.')[0]}.png`;
525
+ link.click();
526
+ };
527
+ }
528
+
529
+ function showError(message) {
530
+ document.getElementById('errorText').textContent = message;
531
+ document.getElementById('errorMessage').classList.add('active');
532
+ document.getElementById('processingSectionElement').classList.remove('active');
533
+ // Restore upload section so users can retry
534
+ document.getElementById('uploadSection').style.display = 'block';
535
+ // Clear file input so users can retry with the same file
536
+ document.getElementById('fileInput').value = '';
537
+ currentFile = null;
538
+ }
539
+
540
+ function hideError() {
541
+ document.getElementById('errorMessage').classList.remove('active');
542
+ }
543
+
544
+ function resetApp() {
545
+ document.getElementById('uploadSection').style.display = 'block';
546
+ document.getElementById('processingSectionElement').classList.remove('active');
547
+ document.getElementById('resultSection').classList.remove('active');
548
+ document.getElementById('fileInput').value = '';
549
+ hideError();
550
+ currentFile = null;
551
+ }
552
+
553
+ // Drag and drop functionality
554
+ const uploadSection = document.getElementById('uploadSection');
555
+
556
+ uploadSection.addEventListener('dragover', function(e) {
557
+ e.preventDefault();
558
+ uploadSection.style.borderColor = 'var(--accent-purple)';
559
+ });
560
+
561
+ uploadSection.addEventListener('dragleave', function(e) {
562
+ e.preventDefault();
563
+ uploadSection.style.borderColor = 'var(--border-accent)';
564
+ });
565
+
566
+ uploadSection.addEventListener('drop', function(e) {
567
+ e.preventDefault();
568
+ uploadSection.style.borderColor = 'var(--border-accent)';
569
+
570
+ const files = e.dataTransfer.files;
571
+ if (files.length > 0) {
572
+ const file = files[0];
573
+ document.getElementById('fileInput').files = files;
574
+ handleFileSelect({ target: { files: [file] } });
575
+ }
576
+ });
577
+ </script>
578
+ </body>
579
+ </html>