Moonie805 commited on
Commit
baa41ac
·
verified ·
1 Parent(s): a9376cb

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. index.html +724 -469
index.html CHANGED
@@ -1,496 +1,751 @@
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>i2i Body Editor with Chat</title>
7
- <script src="https://cdn.jsdelivr.net/npm/react@18.0.0/umd/react.development.js"></script>
8
- <script src="https://cdn.jsdelivr.net/npm/react-dom@18.0.0/umd/react-dom.development.js"></script>
9
- <script src="https://cdn.jsdelivr.net/npm/@babel/standalone/babel.js"></script>
10
- <script src="https://cdn.tailwindcss.com"></script>
11
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">
12
- <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
13
- <style>
14
- * {
15
- font-family: 'Inter', sans-serif;
16
- }
17
-
18
- .gradient-bg {
19
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
20
- }
21
-
22
- .glass-effect {
23
- background: rgba(255, 255, 255, 0.1);
24
- backdrop-filter: blur(10px);
25
- border: 1px solid rgba(255, 255, 255, 0.2);
26
- }
27
-
28
- .tool-button {
29
- transition: all 0.3s ease;
30
- }
31
-
32
- .tool-button:hover {
33
- transform: translateY(-2px);
34
- box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1);
35
- }
36
-
37
- .chat-bubble {
38
- animation: slideIn 0.3s ease;
39
- }
40
-
41
- @keyframes slideIn {
42
- from {
43
- opacity: 0;
44
- transform: translateY(10px);
45
- }
46
- to {
47
- opacity: 1;
48
- transform: translateY(0);
49
- }
50
- }
51
-
52
- .editor-canvas {
53
- background: repeating-linear-gradient(
54
- 45deg,
55
- #f0f0f0,
56
- #f0f0f0 10px,
57
- #e0e0e0 10px,
58
- #e0e0e0 20px
59
- );
60
- }
61
-
62
- .filter-preview {
63
- transition: all 0.3s ease;
64
- }
65
-
66
- .filter-preview:hover {
67
- transform: scale(1.05);
68
- }
69
-
70
- .slider {
71
- -webkit-appearance: none;
72
- appearance: none;
73
- height: 6px;
74
- border-radius: 5px;
75
- background: #d3d3d3;
76
- outline: none;
77
- }
78
-
79
- .slider::-webkit-slider-thumb {
80
- -webkit-appearance: none;
81
- appearance: none;
82
- width: 20px;
83
- height: 20px;
84
- border-radius: 50%;
85
- background: #667eea;
86
- cursor: pointer;
87
- }
88
-
89
- .slider::-moz-range-thumb {
90
- width: 20px;
91
- height: 20px;
92
- border-radius: 50%;
93
- background: #667eea;
94
- cursor: pointer;
95
- }
96
- </style>
97
- </head>
98
- <body>
99
- <div id="root"></div>
100
 
101
- <script type="text/babel">
102
- const { useState, useEffect, useRef } = React;
 
103
 
104
- const App = () => {
105
- const [selectedImage, setSelectedImage] = useState(null);
106
- const [chatMessages, setChatMessages] = useState([
107
- { id: 1, user: 'AI Assistant', message: 'Welcome to i2i Body Editor! Upload an image to start editing.', time: '10:30 AM' },
108
- { id: 2, user: 'System', message: 'Ready to help with your editing needs.', time: '10:31 AM' }
109
- ]);
110
- const [newMessage, setNewMessage] = useState('');
111
- const [activeTool, setActiveTool] = useState('crop');
112
- const [brightness, setBrightness] = useState(100);
113
- const [contrast, setContrast] = useState(100);
114
- const [saturation, setSaturation] = useState(100);
115
- const [rotation, setRotation] = useState(0);
116
- const [scale, setScale] = useState(100);
117
- const [selectedFilter, setSelectedFilter] = useState(null);
118
- const [isDrawing, setIsDrawing] = useState(false);
119
- const [drawColor, setDrawColor] = useState('#000000');
120
- const [brushSize, setBrushSize] = useState(5);
121
- const messagesEndRef = useRef(null);
122
 
123
- const filters = [
124
- { name: 'None', value: 'none' },
125
- { name: 'Vintage', value: 'sepia(0.5) contrast(1.2) brightness(0.9)' },
126
- { name: 'Black & White', value: 'grayscale(1)' },
127
- { name: 'Vintage Blue', value: 'sepia(0.3) hue-rotate(180deg)' },
128
- { name: 'Warm', value: 'sepia(0.5) saturate(1.5)' },
129
- { name: 'Cool', value: 'hue-rotate(180deg) saturate(0.8)' }
130
- ];
131
 
132
- const tools = [
133
- { id: 'crop', icon: 'fas fa-crop-alt', name: 'Crop' },
134
- { id: 'rotate', icon: 'fas fa-sync-alt', name: 'Rotate' },
135
- { id: 'brush', icon: 'fas fa-paint-brush', name: 'Brush' },
136
- { id: 'eraser', icon: 'fas fa-eraser', name: 'Eraser' },
137
- { id: 'text', icon: 'fas fa-font', name: 'Text' },
138
- { id: 'filter', icon: 'fas fa-magic', name: 'Filters' }
139
- ];
140
 
141
- const sendMessage = () => {
142
- if (newMessage.trim()) {
143
- const newMsg = {
144
- id: chatMessages.length + 1,
145
- user: 'You',
146
- message: newMessage,
147
- time: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
148
- };
149
- setChatMessages([...chatMessages, newMsg]);
150
- setNewMessage('');
151
-
152
- // Simulate AI response
153
- setTimeout(() => {
154
- const aiResponse = {
155
- id: chatMessages.length + 2,
156
- user: 'AI Assistant',
157
- message: `I understand your request. Let me help you with that. Current brightness: ${brightness}%, contrast: ${contrast}%, saturation: ${saturation}%.`,
158
- time: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
159
- };
160
- setChatMessages(prev => [...prev, aiResponse]);
161
- }, 1000);
162
- }
163
- };
164
 
165
- const handleImageUpload = (e) => {
166
- const file = e.target.files[0];
167
- if (file) {
168
- const reader = new FileReader();
169
- reader.onload = (e) => {
170
- setSelectedImage(e.target.result);
171
- };
172
- reader.readAsDataURL(file);
173
-
174
- // Add message to chat
175
- const uploadMsg = {
176
- id: chatMessages.length + 1,
177
- user: 'System',
178
- message: `Image uploaded successfully! Ready for editing.`,
179
- time: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
180
- };
181
- setChatMessages(prev => [...prev, uploadMsg]);
182
- }
183
- };
184
 
185
- const applyFilter = (filterValue) => {
186
- setSelectedFilter(filterValue);
187
- const filterMsg = {
188
- id: chatMessages.length + 1,
189
- user: 'You',
190
- message: `Applied filter: ${filters.find(f => f.value === filterValue)?.name}`,
191
- time: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
192
- };
193
- setChatMessages(prev => [...prev, filterMsg]);
194
- };
195
 
196
- const resetFilters = () => {
197
- setBrightness(100);
198
- setContrast(100);
199
- setSaturation(100);
200
- setRotation(0);
201
- setScale(100);
202
- setSelectedFilter(null);
203
- };
204
 
205
- const downloadImage = () => {
206
- const canvas = document.createElement('canvas');
207
- const ctx = canvas.getContext('2d');
208
- const img = new Image();
209
-
210
- img.onload = () => {
211
- canvas.width = img.width;
212
- canvas.height = img.height;
213
-
214
- ctx.filter = selectedFilter || 'none';
215
- ctx.drawImage(img, 0, 0);
216
-
217
- const link = document.createElement('a');
218
- link.download = 'edited-image.png';
219
- link.href = canvas.toDataURL();
220
- link.click();
221
-
222
- const downloadMsg = {
223
- id: chatMessages.length + 1,
224
- user: 'System',
225
- message: 'Image downloaded successfully!',
226
- time: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
227
- };
228
- setChatMessages(prev => [...prev, downloadMsg]);
229
- };
230
-
231
- img.src = selectedImage;
232
- };
233
 
234
- useEffect(() => {
235
- messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
236
- }, [chatMessages]);
 
 
 
 
 
237
 
238
- return (
239
- <div className="min-h-screen gradient-bg">
240
- {/* Header */}
241
- <header className="glass-effect text-white p-4">
242
- <div className="container mx-auto flex justify-between items-center">
243
- <h1 className="text-2xl font-bold">i2i Body Editor</h1>
244
- <a href="https://huggingface.co/spaces/akhaliq/anycoder" className="text-white hover:text-gray-200 transition-colors">
245
- Built with anycoder
246
- </a>
247
- </div>
248
- </header>
249
 
250
- <div className="container mx-auto p-4 flex flex-col lg:flex-row gap-4">
251
- {/* Editor Section */}
252
- <div className="flex-1 glass-effect rounded-xl p-6">
253
- <h2 className="text-white text-xl font-semibold mb-4">Image Editor</h2>
254
-
255
- {/* Image Upload */}
256
- <div className="mb-6">
257
- <label className="block text-white mb-2">Upload Image</label>
258
- <input
259
- type="file"
260
- accept="image/*"
261
- onChange={handleImageUpload}
262
- className="w-full p-2 rounded-lg bg-white/20 text-white file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:text-sm file:font-semibold file:bg-white/30 file:text-white hover:file:bg-white/40"
263
- />
264
- </div>
265
 
266
- {/* Editor Canvas */}
267
- <div className="editor-canvas rounded-lg p-4 mb-6 min-h-96 flex items-center justify-center">
268
- {selectedImage ? (
269
- <div className="relative">
270
- <img
271
- src={selectedImage}
272
- alt="Edited"
273
- style={{
274
- filter: selectedFilter || 'none',
275
- transform: `rotate(${rotation}deg) scale(${scale / 100})`,
276
- brightness: `${brightness}%`,
277
- contrast: `${contrast}%`,
278
- saturate: `${saturation}%`
279
- }}
280
- className="max-w-full max-h-96 rounded-lg shadow-lg"
281
- />
282
- {isDrawing && (
283
- <div
284
- className="absolute inset-0 cursor-crosshair"
285
- onMouseDown={() => setIsDrawing(true)}
286
- onMouseUp={() => setIsDrawing(false)}
287
- onMouseMove={(e) => {
288
- if (isDrawing) {
289
- const canvas = document.createElement('canvas');
290
- const ctx = canvas.getContext('2d');
291
- canvas.width = e.target.width;
292
- canvas.height = e.target.height;
293
- ctx.strokeStyle = drawColor;
294
- ctx.lineWidth = brushSize;
295
- ctx.lineCap = 'round';
296
- // Drawing logic would go here
297
- }
298
- }}
299
- />
300
- )}
301
- </div>
302
- ) : (
303
- <div className="text-center text-white/60">
304
- <i className="fas fa-image text-6xl mb-4"></i>
305
- <p>No image uploaded</p>
306
- </div>
307
- )}
308
- </div>
309
 
310
- {/* Tools */}
311
- <div className="mb-6">
312
- <h3 className="text-white mb-3">Tools</h3>
313
- <div className="grid grid-cols-3 sm:grid-cols-6 gap-2">
314
- {tools.map(tool => (
315
- <button
316
- key={tool.id}
317
- onClick={() => setActiveTool(tool.id)}
318
- className={`tool-button p-3 rounded-lg glass-effect text-white transition-all ${
319
- activeTool === tool.id ? 'ring-2 ring-white' : ''
320
- }`}
321
- title={tool.name}
322
- >
323
- <i className={`${tool.icon} text-lg`}></i>
324
- </button>
325
- ))}
326
- </div>
327
- </div>
328
 
329
- {/* Adjustments */}
330
- <div className="mb-6">
331
- <h3 className="text-white mb-3">Adjustments</h3>
332
- <div className="space-y-4">
333
- <div>
334
- <label className="text-white text-sm block mb-1">Brightness: {brightness}%</label>
335
- <input
336
- type="range"
337
- min="0"
338
- max="200"
339
- value={brightness}
340
- onChange={(e) => setBrightness(e.target.value)}
341
- className="slider w-full"
342
- />
343
- </div>
344
- <div>
345
- <label className="text-white text-sm block mb-1">Contrast: {contrast}%</label>
346
- <input
347
- type="range"
348
- min="0"
349
- max="200"
350
- value={contrast}
351
- onChange={(e) => setContrast(e.target.value)}
352
- className="slider w-full"
353
- />
354
- </div>
355
- <div>
356
- <label className="text-white text-sm block mb-1">Saturation: {saturation}%</label>
357
- <input
358
- type="range"
359
- min="0"
360
- max="200"
361
- value={saturation}
362
- onChange={(e) => setSaturation(e.target.value)}
363
- className="slider w-full"
364
- />
365
- </div>
366
- <div>
367
- <label className="text-white text-sm block mb-1">Rotation: {rotation}°</label>
368
- <input
369
- type="range"
370
- min="-180"
371
- max="180"
372
- value={rotation}
373
- onChange={(e) => setRotation(e.target.value)}
374
- className="slider w-full"
375
- />
376
- </div>
377
- <div>
378
- <label className="text-white text-sm block mb-1">Scale: {scale}%</label>
379
- <input
380
- type="range"
381
- min="50"
382
- max="200"
383
- value={scale}
384
- onChange={(e) => setScale(e.target.value)}
385
- className="slider w-full"
386
- />
387
- </div>
388
- </div>
389
- </div>
390
 
391
- {/* Filters */}
392
- <div className="mb-6">
393
- <h3 className="text-white mb-3">Filters</h3>
394
- <div className="grid grid-cols-3 gap-2">
395
- {filters.map(filter => (
396
- <button
397
- key={filter.value}
398
- onClick={() => applyFilter(filter.value)}
399
- className={`filter-preview p-2 rounded-lg glass-effect text-white text-sm transition-all ${
400
- selectedFilter === filter.value ? 'ring-2 ring-white' : ''
401
- }`}
402
- >
403
- {filter.name}
404
- </button>
405
- ))}
406
- </div>
407
- </div>
 
 
 
 
 
 
408
 
409
- {/* Action Buttons */}
410
- <div className="flex gap-2">
411
- <button
412
- onClick={resetFilters}
413
- className="px-4 py-2 rounded-lg glass-effect text-white hover:bg-white/20 transition-colors"
414
- >
415
- Reset
416
- </button>
417
- <button
418
- onClick={downloadImage}
419
- className="px-4 py-2 rounded-lg bg-white text-purple-600 font-semibold hover:bg-gray-100 transition-colors"
420
- >
421
- Download
422
- </button>
423
- </div>
424
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
425
 
426
- {/* Chat Section */}
427
- <div className="lg:w-96 glass-effect rounded-xl p-6">
428
- <h2 className="text-white text-xl font-semibold mb-4">Chat Editor</h2>
429
-
430
- {/* Chat Messages */}
431
- <div className="bg-white/10 rounded-lg p-4 h-96 overflow-y-auto mb-4">
432
- {chatMessages.map(msg => (
433
- <div key={msg.id} className="chat-bubble mb-3">
434
- <div className="flex items-start gap-2">
435
- <div className="w-8 h-8 rounded-full bg-white/20 flex items-center justify-center text-white text-sm font-semibold">
436
- {msg.user[0]}
437
- </div>
438
- <div className="flex-1">
439
- <div className="flex items-center gap-2 mb-1">
440
- <span className="text-white font-semibold text-sm">{msg.user}</span>
441
- <span className="text-white/60 text-xs">{msg.time}</span>
442
- </div>
443
- <p className="text-white/90 text-sm">{msg.message}</p>
444
- </div>
445
- </div>
446
- </div>
447
- ))}
448
- <div ref={messagesEndRef} />
449
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
450
 
451
- {/* Chat Input */}
452
- <div className="flex gap-2">
453
- <input
454
- type="text"
455
- value={newMessage}
456
- onChange={(e) => setNewMessage(e.target.value)}
457
- onKeyPress={(e) => e.key === 'Enter' && sendMessage()}
458
- placeholder="Type your message..."
459
- className="flex-1 p-3 rounded-lg bg-white/20 text-white placeholder-white/60 border border-white/30 focus:outline-none focus:border-white/50"
460
- />
461
- <button
462
- onClick={sendMessage}
463
- className="px-4 py-3 rounded-lg bg-white text-purple-600 font-semibold hover:bg-gray-100 transition-colors"
464
- >
465
- <i className="fas fa-paper-plane"></i>
466
- </button>
467
- </div>
468
 
469
- {/* Quick Actions */}
470
- <div className="mt-4">
471
- <h3 className="text-white mb-2">Quick Actions</h3>
472
- <div className="grid grid-cols-2 gap-2">
473
- <button className="p-2 rounded-lg glass-effect text-white text-sm hover:bg-white/20 transition-colors">
474
- <i className="fas fa-undo mr-1"></i> Undo
475
- </button>
476
- <button className="p-2 rounded-lg glass-effect text-white text-sm hover:bg-white/20 transition-colors">
477
- <i className="fas fa-redo mr-1"></i> Redo
478
- </button>
479
- <button className="p-2 rounded-lg glass-effect text-white text-sm hover:bg-white/20 transition-colors">
480
- <i className="fas fa-save mr-1"></i> Save
481
- </button>
482
- <button className="p-2 rounded-lg glass-effect text-white text-sm hover:bg-white/20 transition-colors">
483
- <i className="fas fa-share mr-1"></i> Share
484
- </button>
485
- </div>
486
- </div>
487
- </div>
488
- </div>
489
  </div>
490
- );
491
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
492
 
493
- ReactDOM.render(<App />, document.getElementById('root'));
494
- </script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
495
  </body>
496
  </html>
 
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>Body Editor Pro</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
10
+ <style>
11
+ * {
12
+ font-family: 'Inter', sans-serif;
13
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
 
15
+ .gradient-bg {
16
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
17
+ }
18
 
19
+ .glass-effect {
20
+ background: rgba(255, 255, 255, 0.1);
21
+ backdrop-filter: blur(10px);
22
+ border: 1px solid rgba(255, 255, 255, 0.2);
23
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
24
 
25
+ .tool-button {
26
+ transition: all 0.3s ease;
27
+ }
 
 
 
 
 
28
 
29
+ .tool-button:hover {
30
+ transform: translateY(-2px);
31
+ box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1);
32
+ }
 
 
 
 
33
 
34
+ .chat-bubble {
35
+ animation: slideIn 0.3s ease;
36
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
 
38
+ @keyframes slideIn {
39
+ from {
40
+ opacity: 0;
41
+ transform: translateY(10px);
42
+ }
43
+ to {
44
+ opacity: 1;
45
+ transform: translateY(0);
46
+ }
47
+ }
 
 
 
 
 
 
 
 
 
48
 
49
+ .editor-canvas {
50
+ background: repeating-linear-gradient(45deg,
51
+ #f0f0f0,
52
+ #f0f0f0 10px,
53
+ #e0e0e0 10px,
54
+ #e0e0e0 20px);
55
+ }
 
 
 
56
 
57
+ .filter-preview {
58
+ transition: all 0.3s ease;
59
+ }
 
 
 
 
 
60
 
61
+ .filter-preview:hover {
62
+ transform: scale(1.05);
63
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
 
65
+ .slider {
66
+ -webkit-appearance: none;
67
+ appearance: none;
68
+ height: 6px;
69
+ border-radius: 5px;
70
+ background: #d3d3d3;
71
+ outline: none;
72
+ }
73
 
74
+ .slider::-webkit-slider-thumb {
75
+ -webkit-appearance: none;
76
+ appearance: none;
77
+ width: 20px;
78
+ height: 20px;
79
+ border-radius: 50%;
80
+ background: #667eea;
81
+ cursor: pointer;
82
+ }
 
 
83
 
84
+ .slider::-moz-range-thumb {
85
+ width: 20px;
86
+ height: 20px;
87
+ border-radius: 50%;
88
+ background: #667eea;
89
+ cursor: pointer;
90
+ }
 
 
 
 
 
 
 
 
91
 
92
+ .body-marker {
93
+ position: absolute;
94
+ width: 12px;
95
+ height: 12px;
96
+ border-radius: 50%;
97
+ background: #667eea;
98
+ border: 2px solid white;
99
+ cursor: pointer;
100
+ transition: all 0.3s ease;
101
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
 
103
+ .body-marker:hover {
104
+ transform: scale(1.3);
105
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
106
 
107
+ .body-zone {
108
+ position: absolute;
109
+ border: 2px dashed rgba(102, 126, 234, 0.7);
110
+ border-radius: 8px;
111
+ background: rgba(102, 126, 234, 0.1);
112
+ pointer-events: none;
113
+ }
114
+ </style>
115
+ </head>
116
+ <body>
117
+ <div id="app">
118
+ <!-- Header -->
119
+ <header class="glass-effect text-white p-4">
120
+ <div class="container mx-auto flex justify-between items-center">
121
+ <h1 class="text-2xl font-bold">Body Editor Pro</h1>
122
+ <a href="https://huggingface.co/spaces/akhaliq/anycoder" class="text-white hover:text-gray-200 transition-colors">
123
+ Built with anycoder
124
+ </a>
125
+ </div>
126
+ </header>
127
+
128
+ <div class="container mx-auto p-4 flex flex-col lg:flex-row gap-4">
129
+ <!-- Editor Section -->
130
+ <div class="flex-1 glass-effect rounded-xl p-6">
131
+ <h2 class="text-white text-xl font-semibold mb-4">Body Editor</h2>
132
+
133
+ <!-- Image Upload -->
134
+ <div class="mb-6">
135
+ <label class="block text-white mb-2">Upload Body Image</label>
136
+ <input
137
+ type="file"
138
+ accept="image/*"
139
+ id="imageUpload"
140
+ class="w-full p-2 rounded-lg bg-white/20 text-white file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:text-sm file:font-semibold file:bg-white/30 file:text-white hover:file:bg-white/40"
141
+ />
142
+ </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
143
 
144
+ <!-- Editor Canvas -->
145
+ <div class="editor-canvas rounded-lg p-4 mb-6 min-h-96 flex items-center justify-center relative">
146
+ <div id="imageContainer" class="relative">
147
+ <img
148
+ id="bodyImage"
149
+ src=""
150
+ alt="Body Image"
151
+ class="max-w-full max-h-96 rounded-lg shadow-lg"
152
+ />
153
+ <!-- Body adjustment markers -->
154
+ <div id="bodyMarkers" class="absolute inset-0">
155
+ <!-- These markers will be positioned dynamically -->
156
+ </div>
157
+ <!-- Body zones for editing -->
158
+ <div id="bodyZones" class="absolute inset-0 pointer-events-none">
159
+ <!-- These zones will be positioned dynamically -->
160
+ </div>
161
+ </div>
162
+ <div id="noImageMessage" class="text-center text-white/60">
163
+ <i class="fas fa-user text-6xl mb-4"></i>
164
+ <p>Upload a body image to start editing</p>
165
+ </div>
166
+ </div>
167
 
168
+ <!-- Body Editing Tools -->
169
+ <div class="mb-6">
170
+ <h3 class="text-white mb-3">Body Adjustment Tools</h3>
171
+ <div class="grid grid-cols-3 sm:grid-cols-6 gap-2">
172
+ <button class="tool-button p-3 rounded-lg glass-effect text-white transition-all" data-tool="slim">
173
+ <i class="fas fa-arrows-alt-h text-lg"></i>
174
+ <span class="text-xs mt-1 block">Slim</span>
175
+ </button>
176
+ <button class="tool-button p-3 rounded-lg glass-effect text-white transition-all" data-tool="tall">
177
+ <i class="fas fa-arrows-alt-v text-lg"></i>
178
+ <span class="text-xs mt-1 block">Taller</span>
179
+ </button>
180
+ <button class="tool-button p-3 rounded-lg glass-effect text-white transition-all" data-tool="muscle">
181
+ <i class="fas fa-dumbbell text-lg"></i>
182
+ <span class="text-xs mt-1 block">Muscle</span>
183
+ </button>
184
+ <button class="tool-button p-3 rounded-lg glass-effect text-white transition-all" data-tool="waist">
185
+ <i class="fas fa-circle text-lg"></i>
186
+ <span class="text-xs mt-1 block">Waist</span>
187
+ </button>
188
+ <button class="tool-button p-3 rounded-lg glass-effect text-white transition-all" data-tool="chest">
189
+ <i class="fas fa-square text-lg"></i>
190
+ <span class="text-xs mt-1 block">Chest</span>
191
+ </button>
192
+ <button class="tool-button p-3 rounded-lg glass-effect text-white transition-all" data-tool="hips">
193
+ <i class="fas fa-circle text-lg"></i>
194
+ <span class="text-xs mt-1 block">Hips</span>
195
+ </button>
196
+ </div>
197
+ </div>
198
 
199
+ <!-- Body Adjustments -->
200
+ <div class="mb-6">
201
+ <h3 class="text-white mb-3">Body Adjustments</h3>
202
+ <div class="space-y-4">
203
+ <div>
204
+ <label class="text-white text-sm block mb-1">Overall Slim: <span id="slimValue">0</span>%</label>
205
+ <input
206
+ type="range"
207
+ min="-20"
208
+ max="20"
209
+ value="0"
210
+ id="slimSlider"
211
+ class="slider w-full"
212
+ />
213
+ </div>
214
+ <div>
215
+ <label class="text-white text-sm block mb-1">Height: <span id="heightValue">0</span>%</label>
216
+ <input
217
+ type="range"
218
+ min="-10"
219
+ max="10"
220
+ value="0"
221
+ id="heightSlider"
222
+ class="slider w-full"
223
+ />
224
+ </div>
225
+ <div>
226
+ <label class="text-white text-sm block mb-1">Muscle Definition: <span id="muscleValue">0</span>%</label>
227
+ <input
228
+ type="range"
229
+ min="0"
230
+ max="30"
231
+ value="0"
232
+ id="muscleSlider"
233
+ class="slider w-full"
234
+ />
235
+ </div>
236
+ <div>
237
+ <label class="text-white text-sm block mb-1">Waist: <span id="waistValue">0</span>%</label>
238
+ <input
239
+ type="range"
240
+ min="-15"
241
+ max="15"
242
+ value="0"
243
+ id="waistSlider"
244
+ class="slider w-full"
245
+ />
246
+ </div>
247
+ <div>
248
+ <label class="text-white text-sm block mb-1">Chest: <span id="chestValue">0</span>%</label>
249
+ <input
250
+ type="range"
251
+ min="-15"
252
+ max="15"
253
+ value="0"
254
+ id="chestSlider"
255
+ class="slider w-full"
256
+ />
257
+ </div>
258
+ <div>
259
+ <label class="text-white text-sm block mb-1">Hips: <span id="hipsValue">0</span>%</label>
260
+ <input
261
+ type="range"
262
+ min="-15"
263
+ max="15"
264
+ value="0"
265
+ id="hipsSlider"
266
+ class="slider w-full"
267
+ />
268
+ </div>
269
+ </div>
270
+ </div>
271
 
272
+ <!-- Action Buttons -->
273
+ <div class="flex gap-2">
274
+ <button
275
+ id="resetButton"
276
+ class="px-4 py-2 rounded-lg glass-effect text-white hover:bg-white/20 transition-colors"
277
+ >
278
+ Reset All
279
+ </button>
280
+ <button
281
+ id="downloadButton"
282
+ class="px-4 py-2 rounded-lg bg-white text-purple-600 font-semibold hover:bg-gray-100 transition-colors"
283
+ >
284
+ Download
285
+ </button>
286
+ </div>
287
+ </div>
 
288
 
289
+ <!-- Chat Section -->
290
+ <div class="lg:w-96 glass-effect rounded-xl p-6">
291
+ <h2 class="text-white text-xl font-semibold mb-4">Body Editor Assistant</h2>
292
+
293
+ <!-- Chat Messages -->
294
+ <div class="bg-white/10 rounded-lg p-4 h-96 overflow-y-auto mb-4">
295
+ <div class="chat-bubble mb-3">
296
+ <div class="flex items-start gap-2">
297
+ <div class="w-8 h-8 rounded-full bg-white/20 flex items-center justify-center text-white text-sm font-semibold">
298
+ A
299
+ </div>
300
+ <div class="flex-1">
301
+ <div class="flex items-center gap-2 mb-1">
302
+ <span class="text-white font-semibold text-sm">AI Assistant</span>
303
+ <span class="text-white/60 text-xs">10:30 AM</span>
 
 
 
 
 
304
  </div>
305
+ <p class="text-white/90 text-sm">Welcome to Body Editor Pro! Upload a body image to start editing your physique.</p>
306
+ </div>
307
+ </div>
308
+ </div>
309
+ <div class="chat-bubble mb-3">
310
+ <div class="flex items-start gap-2">
311
+ <div class="w-8 h-8 rounded-full bg-white/20 flex items-center justify-center text-white text-sm font-semibold">
312
+ S
313
+ </div>
314
+ <div class="flex-1">
315
+ <div class="flex items-center gap-2 mb-1">
316
+ <span class="text-white font-semibold text-sm">System</span>
317
+ <span class="text-white/60 text-xs">10:31 AM</span>
318
+ </div>
319
+ <p class="text-white/90 text-sm">I can help you slim, tone, or build muscle in your photos.</p>
320
+ </div>
321
+ </div>
322
+ </div>
323
+ <div id="messagesEnd"></div>
324
+ </div>
325
+
326
+ <!-- Chat Input -->
327
+ <div class="flex gap-2">
328
+ <input
329
+ type="text"
330
+ id="messageInput"
331
+ placeholder="Ask about body editing..."
332
+ class="flex-1 p-3 rounded-lg bg-white/20 text-white placeholder-white/60 border border-white/30 focus:outline-none focus:border-white/50"
333
+ />
334
+ <button
335
+ id="sendButton"
336
+ class="px-4 py-3 rounded-lg bg-white text-purple-600 font-semibold hover:bg-gray-100 transition-colors"
337
+ >
338
+ <i class="fas fa-paper-plane"></i>
339
+ </button>
340
+ </div>
341
 
342
+ <!-- Quick Actions -->
343
+ <div class="mt-4">
344
+ <h3 class="text-white mb-2">Quick Body Edits</h3>
345
+ <div class="grid grid-cols-2 gap-2">
346
+ <button class="p-2 rounded-lg glass-effect text-white text-sm hover:bg-white/20 transition-colors">
347
+ <i class="fas fa-running mr-1"></i> Athlete Mode
348
+ </button>
349
+ <button class="p-2 rounded-lg glass-effect text-white text-sm hover:bg-white/20 transition-colors">
350
+ <i class="fas fa-swimmer mr-1"></i> Swimmer Body
351
+ </button>
352
+ <button class="p-2 rounded-lg glass-effect text-white text-sm hover:bg-white/20 transition-colors">
353
+ <i class="fas fa-yin-yang mr-1"></i> Balanced
354
+ </button>
355
+ <button class="p-2 rounded-lg glass-effect text-white text-sm hover:bg-white/20 transition-colors">
356
+ <i class="fas fa-fire mr-1"></i> Fitness Model
357
+ </button>
358
+ </div>
359
+ </div>
360
+ </div>
361
+
362
+ <script>
363
+ // DOM Elements
364
+ const imageUpload = document.getElementById('imageUpload');
365
+ const bodyImage = document.getElementById('bodyImage');
366
+ const noImageMessage = document.getElementById('noImageMessage');
367
+ const imageContainer = document.getElementById('imageContainer');
368
+ const messageInput = document.getElementById('messageInput');
369
+ const sendButton = document.getElementById('sendButton');
370
+ const messagesEnd = document.getElementById('messagesEnd');
371
+ const resetButton = document.getElementById('resetButton');
372
+ const downloadButton = document.getElementById('downloadButton');
373
+ const chatMessages = document.querySelector('.bg-white/10');
374
+
375
+ // Slider elements
376
+ const slimSlider = document.getElementById('slimSlider');
377
+ const heightSlider = document.getElementById('heightSlider');
378
+ const muscleSlider = document.getElementById('muscleSlider');
379
+ const waistSlider = document.getElementById('waistSlider');
380
+ const chestSlider = document.getElementById('chestSlider');
381
+ const hipsSlider = document.getElementById('hipsSlider');
382
+
383
+ // Value displays
384
+ const slimValue = document.getElementById('slimValue');
385
+ const heightValue = document.getElementById('heightValue');
386
+ const muscleValue = document.getElementById('muscleValue');
387
+ const waistValue = document.getElementById('waistValue');
388
+ const chestValue = document.getElementById('chestValue');
389
+ const hipsValue = document.getElementById('hipsValue');
390
+
391
+ // Tool buttons
392
+ const toolButtons = document.querySelectorAll('[data-tool]');
393
+
394
+ // Current state
395
+ let currentImage = null;
396
+ let originalImage = null;
397
+ let adjustments = {
398
+ slim: 0,
399
+ height: 0,
400
+ muscle: 0,
401
+ waist: 0,
402
+ chest: 0,
403
+ hips: 0
404
+ };
405
+
406
+ // Initialize the app
407
+ function init() {
408
+ // Hide the image initially
409
+ bodyImage.style.display = 'none';
410
+
411
+ // Add event listeners
412
+ imageUpload.addEventListener('change', handleImageUpload);
413
+ sendButton.addEventListener('click', sendMessage);
414
+ messageInput.addEventListener('keypress', (e) => {
415
+ if (e.key === 'Enter') sendMessage();
416
+ });
417
+
418
+ // Slider event listeners
419
+ slimSlider.addEventListener('input', updateSlimAdjustment);
420
+ heightSlider.addEventListener('input', updateHeightAdjustment);
421
+ muscleSlider.addEventListener('input', updateMuscleAdjustment);
422
+ waistSlider.addEventListener('input', updateWaistAdjustment);
423
+ chestSlider.addEventListener('input', updateChestAdjustment);
424
+ hipsSlider.addEventListener('input', updateHipsAdjustment);
425
+
426
+ // Tool button event listeners
427
+ toolButtons.forEach(button => {
428
+ button.addEventListener('click', () => {
429
+ const tool = button.getAttribute('data-tool');
430
+ activateTool(tool);
431
+ });
432
+ });
433
+
434
+ // Action button event listeners
435
+ resetButton.addEventListener('click', resetAdjustments);
436
+ downloadButton.addEventListener('click', downloadImage);
437
+ }
438
+
439
+ // Handle image upload
440
+ function handleImageUpload(e) {
441
+ const file = e.target.files[0];
442
+ if (file) {
443
+ const reader = new FileReader();
444
+ reader.onload = (e) => {
445
+ currentImage = e.target.result;
446
+ originalImage = e.target.result;
447
+ bodyImage.src = currentImage;
448
+ bodyImage.style.display = 'block';
449
+ noImageMessage.style.display = 'none';
450
+
451
+ // Add message to chat
452
+ addChatMessage('System', 'Body image uploaded successfully! You can now adjust the physique.');
453
+
454
+ // Add body markers after image loads
455
+ bodyImage.onload = () => {
456
+ addBodyMarkers();
457
+ };
458
+ };
459
+ reader.readAsDataURL(file);
460
+ }
461
+ }
462
+
463
+ // Add body markers for editing
464
+ function addBodyMarkers() {
465
+ const markersContainer = document.getElementById('bodyMarkers');
466
+ const zonesContainer = document.getElementById('bodyZones');
467
+
468
+ // Clear existing markers
469
+ markersContainer.innerHTML = '';
470
+ zonesContainer.innerHTML = '';
471
+
472
+ // Define body points and zones
473
+ const bodyPoints = [
474
+ { name: 'head', x: 50, y: 10 },
475
+ { name: 'shoulders', x: 50, y: 25 },
476
+ { name: 'chest', x: 50, y: 35 },
477
+ { name: 'waist', x: 50, y: 50 },
478
+ { name: 'hips', x: 50, y: 65 },
479
+ { name: 'legs', x: 50, y: 85 }
480
+ ];
481
+
482
+ // Create markers
483
+ bodyPoints.forEach(point => {
484
+ const marker = document.createElement('div');
485
+ marker.className = 'body-marker';
486
+ marker.style.left = `${point.x}%`;
487
+ marker.style.top = `${point.y}%`;
488
+ marker.setAttribute('data-point', point.name);
489
+ markersContainer.appendChild(marker);
490
+
491
+ // Add click event to markers
492
+ marker.addEventListener('click', () => {
493
+ highlightBodyZone(point.name);
494
+ addChatMessage('You', `Selected ${point.name} for adjustment`);
495
+ });
496
+ });
497
+
498
+ // Create body zones
499
+ const bodyZones = [
500
+ { name: 'chest', top: 25, left: 35, width: 30, height: 15 },
501
+ { name: 'waist', top: 45, left: 40, width: 20, height: 10 },
502
+ { name: 'hips', top: 60, left: 38, width: 24, height: 10 },
503
+ { name: 'legs', top: 70, left: 35, width: 30, height: 25 }
504
+ ];
505
+
506
+ // Create zones
507
+ bodyZones.forEach(zone => {
508
+ const zoneDiv = document.createElement('div');
509
+ zoneDiv.className = 'body-zone';
510
+ zoneDiv.style.top = `${zone.top}%`;
511
+ zoneDiv.style.left = `${zone.left}%`;
512
+ zoneDiv.style.width = `${zone.width}%`;
513
+ zoneDiv.style.height = `${zone.height}%`;
514
+ zoneDiv.setAttribute('data-zone', zone.name);
515
+ zonesContainer.appendChild(zoneDiv);
516
+ });
517
+ }
518
+
519
+ // Highlight a body zone
520
+ function highlightBodyZone(zoneName) {
521
+ const zones = document.querySelectorAll('.body-zone');
522
+ zones.forEach(zone => {
523
+ if (zone.getAttribute('data-zone') === zoneName) {
524
+ zone.style.background = 'rgba(102, 126, 234, 0.3)';
525
+ zone.style.border = '2px solid rgba(102, 126, 234, 0.9)';
526
+ } else {
527
+ zone.style.background = 'rgba(102, 126, 234, 0.1)';
528
+ zone.style.border = '2px dashed rgba(102, 126, 234, 0.7)';
529
+ }
530
+ });
531
+
532
+ // Adjust sliders based on zone
533
+ switch(zoneName) {
534
+ case 'chest':
535
+ chestSlider.focus();
536
+ break;
537
+ case 'waist':
538
+ waistSlider.focus();
539
+ break;
540
+ case 'hips':
541
+ hipsSlider.focus();
542
+ break;
543
+ case 'legs':
544
+ slimSlider.focus();
545
+ break;
546
+ }
547
+ }
548
+
549
+ // Activate a tool
550
+ function activateTool(tool) {
551
+ // Remove active state from all tools
552
+ toolButtons.forEach(button => {
553
+ button.classList.remove('ring-2', 'ring-white');
554
+ });
555
+
556
+ // Add active state to clicked tool
557
+ event.currentTarget.classList.add('ring-2', 'ring-white');
558
+
559
+ // Show appropriate adjustments based on tool
560
+ switch(tool) {
561
+ case 'slim':
562
+ slimSlider.focus();
563
+ addChatMessage('You', 'Activated slimming tool');
564
+ break;
565
+ case 'tall':
566
+ heightSlider.focus();
567
+ addChatMessage('You', 'Activated height adjustment tool');
568
+ break;
569
+ case 'muscle':
570
+ muscleSlider.focus();
571
+ addChatMessage('You', 'Activated muscle definition tool');
572
+ break;
573
+ case 'waist':
574
+ waistSlider.focus();
575
+ addChatMessage('You', 'Activated waist adjustment tool');
576
+ break;
577
+ case 'chest':
578
+ chestSlider.focus();
579
+ addChatMessage('You', 'Activated chest adjustment tool');
580
+ break;
581
+ case 'hips':
582
+ hipsSlider.focus();
583
+ addChatMessage('You', 'Activated hips adjustment tool');
584
+ break;
585
+ }
586
+ }
587
+
588
+ // Update adjustments based on slider values
589
+ function updateSlimAdjustment() {
590
+ adjustments.slim = slimSlider.value;
591
+ slimValue.textContent = adjustments.slim;
592
+ applyBodyAdjustments();
593
+ }
594
+
595
+ function updateHeightAdjustment() {
596
+ adjustments.height = heightSlider.value;
597
+ heightValue.textContent = adjustments.height;
598
+ applyBodyAdjustments();
599
+ }
600
+
601
+ function updateMuscleAdjustment() {
602
+ adjustments.muscle = muscleSlider.value;
603
+ muscleValue.textContent = adjustments.muscle;
604
+ applyBodyAdjustments();
605
+ }
606
+
607
+ function updateWaistAdjustment() {
608
+ adjustments.waist = waistSlider.value;
609
+ waistValue.textContent = adjustments.waist;
610
+ applyBodyAdjustments();
611
+ }
612
+
613
+ function updateChestAdjustment() {
614
+ adjustments.chest = chestSlider.value;
615
+ chestValue.textContent = adjustments.chest;
616
+ applyBodyAdjustments();
617
+ }
618
+
619
+ function updateHipsAdjustment() {
620
+ adjustments.hips = hipsSlider.value;
621
+ hipsValue.textContent = adjustments.hips;
622
+ applyBodyAdjustments();
623
+ }
624
+
625
+ // Apply body adjustments to the image
626
+ function applyBodyAdjustments() {
627
+ if (!currentImage) return;
628
+
629
+ // In a real application, this would use a canvas and image processing
630
+ // For this demo, we'll just simulate the effect
631
+
632
+ // Show loading effect
633
+ bodyImage.style.opacity = '0.7';
634
+
635
+ // Simulate processing delay
636
+ setTimeout(() => {
637
+ bodyImage.style.opacity = '1';
638
+
639
+ // Add chat message about the adjustment
640
+ const totalAdjustment = Object.values(adjustments).reduce((sum, val) => sum + Math.abs(val), 0);
641
+ if (totalAdjustment > 0) {
642
+ addChatMessage('System', `Applied adjustments: Slim ${adjustments.slim}%, Height ${adjustments.height}%, Muscle ${adjustments.muscle}%`);
643
+ }
644
+ }, 300);
645
+ }
646
+
647
+ // Reset all adjustments
648
+ function resetAdjustments() {
649
+ adjustments = {
650
+ slim: 0,
651
+ height: 0,
652
+ muscle: 0,
653
+ waist: 0,
654
+ chest: 0,
655
+ hips: 0
656
+ };
657
+
658
+ // Reset sliders
659
+ slimSlider.value = 0;
660
+ heightSlider.value = 0;
661
+ muscleSlider.value = 0;
662
+ waistSlider.value = 0;
663
+ chestSlider.value = 0;
664
+ hipsSlider.value = 0;
665
+
666
+ // Update value displays
667
+ slimValue.textContent = '0';
668
+ heightValue.textContent = '0';
669
+ muscleValue.textContent = '0';
670
+ waistValue.textContent = '0';
671
+ chestValue.textContent = '0';
672
+ hipsValue.textContent = '0';
673
+
674
+ // Reset image
675
+ bodyImage.src = originalImage;
676
+
677
+ // Add message to chat
678
+ addChatMessage('You', 'Reset all body adjustments');
679
+ }
680
+
681
+ // Download the edited image
682
+ function downloadImage() {
683
+ if (!currentImage) {
684
+ addChatMessage('System', 'Please upload an image first');
685
+ return;
686
+ }
687
+
688
+ // Create a temporary link to download the image
689
+ const link = document.createElement('a');
690
+ link.download = 'edited-body-image.png';
691
+ link.href = currentImage;
692
+ link.click();
693
+
694
+ // Add message to chat
695
+ addChatMessage('System', 'Body image downloaded successfully!');
696
+ }
697
+
698
+ // Chat functionality
699
+ function sendMessage() {
700
+ const message = messageInput.value.trim();
701
+ if (message) {
702
+ addChatMessage('You', message);
703
+ messageInput.value = '';
704
+
705
+ // Simulate AI response
706
+ setTimeout(() => {
707
+ const responses = [
708
+ "I can help you adjust that area. Try using the sliders to fine-tune the effect.",
709
+ "For more natural results, make small adjustments to multiple areas.",
710
+ "Body editing works best when you maintain natural proportions.",
711
+ "Would you like me to suggest some quick presets for common body types?",
712
+ "You can use the body markers to quickly select specific areas for editing.",
713
+ "The muscle definition tool works well with the chest and arms areas.",
714
+ "Try the height adjustment for a more balanced overall look."
715
+ ];
716
+
717
+ const randomResponse = responses[Math.floor(Math.random() * responses.length)];
718
+ addChatMessage('AI Assistant', randomResponse);
719
+ }, 1000);
720
+ }
721
+ }
722
+
723
+ // Add a message to the chat
724
+ function addChatMessage(user, message) {
725
+ const time = new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
726
+
727
+ const messageDiv = document.createElement('div');
728
+ messageDiv.className = 'chat-bubble mb-3';
729
+ messageDiv.innerHTML = `
730
+ <div class="flex items-start gap-2">
731
+ <div class="w-8 h-8 rounded-full bg-white/20 flex items-center justify-center text-white text-sm font-semibold">
732
+ ${user[0]}
733
+ </div>
734
+ <div class="flex-1">
735
+ <div class="flex items-center gap-2 mb-1">
736
+ <span class="text-white font-semibold text-sm">${user}</span>
737
+ <span class="text-white/60 text-xs">${time}</span>
738
+ </div>
739
+ <p class="text-white/90 text-sm">${message}</p>
740
+ </div>
741
+ `;
742
+
743
+ chatMessages.appendChild(messageDiv);
744
+ messagesEnd.scrollIntoView({ behavior: 'smooth' });
745
+ }
746
+
747
+ // Initialize the app when DOM is loaded
748
+ document.addEventListener('DOMContentLoaded', init);
749
+ </script>
750
  </body>
751
  </html>