swapit commited on
Commit
c4ead82
·
verified ·
1 Parent(s): 1475ba7

Add 3 files

Browse files
Files changed (3) hide show
  1. README.md +7 -5
  2. index.html +1410 -19
  3. prompts.txt +0 -0
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Best
3
- emoji: 📈
4
- colorFrom: purple
5
- colorTo: pink
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: best
3
+ emoji: 🐳
4
+ colorFrom: gray
5
+ colorTo: red
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,1410 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </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>AI Adult Content Creator | OnlyFans Toolkit</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
+ <script src="https://cdn.jsdelivr.net/npm/face-api.js"></script>
10
+ <style>
11
+ .editor-container {
12
+ background: linear-gradient(135deg, #2b2d42 0%, #1a1a2e 100%);
13
+ }
14
+ .tool-btn {
15
+ transition: all 0.3s ease;
16
+ }
17
+ .tool-btn:hover {
18
+ transform: translateY(-3px);
19
+ box-shadow: 0 10px 20px rgba(255, 20, 147, 0.3);
20
+ }
21
+ .preview-box {
22
+ box-shadow: 0 20px 25px -5px rgba(0,0,0,0.3), 0 10px 10px -5px rgba(0,0,0,0.1);
23
+ }
24
+ .slider-thumb::-webkit-slider-thumb {
25
+ -webkit-appearance: none;
26
+ appearance: none;
27
+ width: 20px;
28
+ height: 20px;
29
+ border-radius: 50%;
30
+ background: #ff1493;
31
+ cursor: pointer;
32
+ }
33
+ .tab-active {
34
+ border-bottom: 3px solid #ff1493;
35
+ }
36
+ .image-thumbnail {
37
+ transition: all 0.2s ease;
38
+ }
39
+ .image-thumbnail:hover {
40
+ transform: scale(1.05);
41
+ box-shadow: 0 4px 6px rgba(255, 20, 147, 0.3);
42
+ }
43
+ .image-thumbnail.active {
44
+ border: 2px solid #ff1493;
45
+ }
46
+ .prompt-box {
47
+ min-height: 100px;
48
+ resize: vertical;
49
+ }
50
+ .pose-preview {
51
+ background-size: contain;
52
+ background-repeat: no-repeat;
53
+ background-position: center;
54
+ }
55
+ .processing-overlay {
56
+ position: absolute;
57
+ top: 0;
58
+ left: 0;
59
+ right: 0;
60
+ bottom: 0;
61
+ background: rgba(0,0,0,0.8);
62
+ display: flex;
63
+ flex-direction: column;
64
+ align-items: center;
65
+ justify-content: center;
66
+ color: white;
67
+ z-index: 10;
68
+ }
69
+ .face-landmarks {
70
+ position: absolute;
71
+ width: 20px;
72
+ height: 20px;
73
+ background: rgba(255, 20, 147, 0.7);
74
+ border-radius: 50%;
75
+ transform: translate(-50%, -50%);
76
+ }
77
+ .selection-box {
78
+ position: absolute;
79
+ border: 2px dashed #ff1493;
80
+ background: rgba(255, 20, 147, 0.2);
81
+ z-index: 5;
82
+ }
83
+ .predictive-options {
84
+ position: absolute;
85
+ background: #2b2d42;
86
+ border-radius: 4px;
87
+ box-shadow: 0 2px 10px rgba(0,0,0,0.3);
88
+ z-index: 20;
89
+ padding: 5px;
90
+ border: 1px solid #ff1493;
91
+ }
92
+ .predictive-option {
93
+ padding: 8px 12px;
94
+ cursor: pointer;
95
+ border-radius: 3px;
96
+ color: white;
97
+ }
98
+ .predictive-option:hover {
99
+ background: #ff1493;
100
+ }
101
+ .effect-thumb {
102
+ background-size: cover;
103
+ background-position: center;
104
+ }
105
+ .nsfw-badge {
106
+ position: absolute;
107
+ top: 10px;
108
+ right: 10px;
109
+ background: #ff1493;
110
+ color: white;
111
+ padding: 2px 8px;
112
+ border-radius: 12px;
113
+ font-size: 10px;
114
+ font-weight: bold;
115
+ }
116
+ .category-tag {
117
+ display: inline-block;
118
+ background: rgba(255, 20, 147, 0.2);
119
+ color: #ff1493;
120
+ padding: 2px 8px;
121
+ border-radius: 12px;
122
+ font-size: 12px;
123
+ margin-right: 5px;
124
+ margin-bottom: 5px;
125
+ }
126
+ .face-detection-box {
127
+ position: absolute;
128
+ border: 2px solid #00ff00;
129
+ background: rgba(0, 255, 0, 0.1);
130
+ z-index: 5;
131
+ }
132
+ .face-swap-preview {
133
+ position: relative;
134
+ overflow: hidden;
135
+ }
136
+ .face-swap-canvas {
137
+ position: absolute;
138
+ top: 0;
139
+ left: 0;
140
+ }
141
+ </style>
142
+ </head>
143
+ <body class="bg-gray-900 text-gray-100">
144
+ <!-- Header -->
145
+ <header class="bg-gray-800 shadow-sm">
146
+ <div class="container mx-auto px-4 py-4 flex justify-between items-center">
147
+ <div class="flex items-center space-x-2">
148
+ <i class="fas fa-venus-mars text-pink-600 text-2xl"></i>
149
+ <h1 class="text-xl font-bold">AI Adult Content Creator</h1>
150
+ </div>
151
+ <nav class="hidden md:flex space-x-8">
152
+ <a href="#" class="text-gray-400 hover:text-pink-500 font-medium">Dashboard</a>
153
+ <a href="#" class="text-gray-400 hover:text-pink-500 font-medium">Templates</a>
154
+ <a href="#" class="text-gray-400 hover:text-pink-500 font-medium">Analytics</a>
155
+ <a href="#" class="text-gray-400 hover:text-pink-500 font-medium">Monetization</a>
156
+ </nav>
157
+ <div class="flex items-center space-x-4">
158
+ <button class="px-4 py-2 rounded-md text-gray-400 hover:bg-gray-700">
159
+ <i class="fas fa-bell text-xl"></i>
160
+ </button>
161
+ <button class="px-4 py-2 bg-pink-600 text-white rounded-md hover:bg-pink-700">
162
+ <i class="fas fa-rocket mr-2"></i> Premium
163
+ </button>
164
+ </div>
165
+ </div>
166
+ </header>
167
+
168
+ <!-- Main Content -->
169
+ <main class="container mx-auto px-4 py-8">
170
+ <div class="flex flex-col lg:flex-row gap-8">
171
+ <!-- Tools Panel -->
172
+ <div class="w-full lg:w-1/4 bg-gray-800 rounded-xl shadow-md p-6 h-fit">
173
+ <div class="flex border-b border-gray-700 mb-6">
174
+ <button id="image-tab" class="tab-active px-4 py-2 font-medium text-pink-500">Photo</button>
175
+ <button id="video-tab" class="px-4 py-2 font-medium text-gray-400 hover:text-pink-500">Video</button>
176
+ </div>
177
+
178
+ <div id="image-tools">
179
+ <!-- Multi Image Upload -->
180
+ <div class="mb-6">
181
+ <h3 class="font-medium text-gray-300 mb-3">Upload Content</h3>
182
+ <div class="border-2 border-dashed border-gray-700 rounded-lg p-4 text-center cursor-pointer hover:bg-gray-700 mb-3" id="upload-area">
183
+ <i class="fas fa-cloud-upload-alt text-3xl text-gray-500 mb-2"></i>
184
+ <p class="text-gray-400">Drag & drop NSFW content</p>
185
+ <p class="text-sm text-gray-500 mt-1">or click to browse</p>
186
+ <input type="file" id="file-upload" class="hidden" accept="image/*,video/*" multiple>
187
+ </div>
188
+ <div id="thumbnail-container" class="grid grid-cols-3 gap-2 mt-2 max-h-40 overflow-y-auto"></div>
189
+ </div>
190
+
191
+ <!-- AI Prompts -->
192
+ <div class="mb-6">
193
+ <h3 class="font-medium text-gray-300 mb-3">AI Enhancement Prompts</h3>
194
+ <div class="relative">
195
+ <textarea id="ai-prompt" class="w-full border border-gray-700 bg-gray-700 rounded-md p-2 text-sm prompt-box" placeholder="Describe your desired enhancements (e.g. 'make ass bigger', 'enhance curves', 'add toy')"></textarea>
196
+ <div class="absolute right-2 bottom-2 text-gray-400 text-xs">
197
+ <span id="char-count">0</span>/200
198
+ </div>
199
+ </div>
200
+ <div class="mt-2 grid grid-cols-2 gap-2">
201
+ <button onclick="applyPrompt('Enhance curves, make ass bigger, smooth skin, perfect lighting')" class="px-2 py-1 bg-gray-700 text-xs rounded hover:bg-pink-600 hover:text-white">Body Enhance</button>
202
+ <button onclick="applyPrompt('Add realistic dildo, perfect lighting, professional look')" class="px-2 py-1 bg-gray-700 text-xs rounded hover:bg-pink-600 hover:text-white">Add Toy</button>
203
+ <button onclick="showFaceSwapModal()" class="px-2 py-1 bg-gray-700 text-xs rounded hover:bg-pink-600 hover:text-white">Face Swap</button>
204
+ <button onclick="applyPrompt('Smooth skin, remove blemishes, perfect lighting, professional retouch')" class="px-2 py-1 bg-gray-700 text-xs rounded hover:bg-pink-600 hover:text-white">Skin Perfect</button>
205
+ </div>
206
+ </div>
207
+
208
+ <!-- Content Categories -->
209
+ <div class="mb-6">
210
+ <h3 class="font-medium text-gray-300 mb-3">Content Categories</h3>
211
+ <div class="flex flex-wrap">
212
+ <span class="category-tag cursor-pointer" onclick="applyPrompt('Solo female, teasing, implied nudity, perfect lighting')">Solo Tease</span>
213
+ <span class="category-tag cursor-pointer" onclick="applyPrompt('Explicit solo, legs spread, close-up, wet look')">Explicit Solo</span>
214
+ <span class="category-tag cursor-pointer" onclick="applyPrompt('Butt plug, anal play, bent over, high resolution')">Anal Play</span>
215
+ <span class="category-tag cursor-pointer" onclick="applyPrompt('Dildo play, penetration, wet look, professional lighting')">Toy Play</span>
216
+ <span class="category-tag cursor-pointer" onclick="applyPrompt('Lingerie, stockings, high heels, seductive pose')">Lingerie</span>
217
+ <span class="category-tag cursor-pointer" onclick="applyPrompt('Outdoor, risky, public flash, natural lighting')">Outdoor</span>
218
+ <span class="category-tag cursor-pointer" onclick="applyPrompt('BDSM, restraints, domination, professional setup')">BDSM</span>
219
+ <span class="category-tag cursor-pointer" onclick="applyPrompt('Cosplay, fantasy, roleplay, perfect costume')">Cosplay</span>
220
+ </div>
221
+ </div>
222
+
223
+ <!-- Body Tools -->
224
+ <div class="mb-6">
225
+ <h3 class="font-medium text-gray-300 mb-3">Body Enhancements</h3>
226
+ <div class="space-y-4">
227
+ <div>
228
+ <label class="block text-sm text-gray-400 mb-1">Breast Size <span class="text-pink-500" id="breast-value">0%</span></label>
229
+ <input type="range" class="w-full slider-thumb" id="breast-slider" min="-30" max="50" value="0" oninput="updateBodyParam('breast', this.value)">
230
+ <div class="flex justify-between text-xs text-gray-500">
231
+ <span>Smaller</span>
232
+ <span>Larger</span>
233
+ </div>
234
+ </div>
235
+ <div>
236
+ <label class="block text-sm text-gray-400 mb-1">Ass Size <span class="text-pink-500" id="ass-value">0%</span></label>
237
+ <input type="range" class="w-full slider-thumb" id="ass-slider" min="-20" max="60" value="0" oninput="updateBodyParam('ass', this.value)">
238
+ <div class="flex justify-between text-xs text-gray-500">
239
+ <span>Smaller</span>
240
+ <span>Bubble</span>
241
+ </div>
242
+ </div>
243
+ <div>
244
+ <label class="block text-sm text-gray-400 mb-1">Waist Slimness <span class="text-pink-500" id="waist-value">0%</span></label>
245
+ <input type="range" class="w-full slider-thumb" id="waist-slider" min="-30" max="40" value="0" oninput="updateBodyParam('waist', this.value)">
246
+ <div class="flex justify-between text-xs text-gray-500">
247
+ <span>Thicker</span>
248
+ <span>Slimmer</span>
249
+ </div>
250
+ </div>
251
+ <div>
252
+ <label class="block text-sm text-gray-400 mb-1">Pussy Plumpness <span class="text-pink-500" id="pussy-value">0%</span></label>
253
+ <input type="range" class="w-full slider-thumb" id="pussy-slider" min="-20" max="40" value="0" oninput="updateBodyParam('pussy', this.value)">
254
+ <div class="flex justify-between text-xs text-gray-500">
255
+ <span>Less</span>
256
+ <span>More</span>
257
+ </div>
258
+ </div>
259
+ </div>
260
+ </div>
261
+
262
+ <!-- Toy & Prop Tools -->
263
+ <div class="mb-6">
264
+ <h3 class="font-medium text-gray-300 mb-3">Toys & Props</h3>
265
+ <div class="grid grid-cols-3 gap-3">
266
+ <button class="tool-btn flex flex-col items-center p-3 bg-gray-700 rounded-lg hover:bg-pink-600 hover:text-white" onclick="applyPrompt('Add realistic pink dildo to scene, perfect lighting, professional look')">
267
+ <i class="fas fa-dildo text-pink-500 text-xl mb-1"></i>
268
+ <span class="text-xs">Dildo</span>
269
+ </button>
270
+ <button class="tool-btn flex flex-col items-center p-3 bg-gray-700 rounded-lg hover:bg-pink-600 hover:text-white" onclick="applyPrompt('Add jeweled butt plug, make it look realistic, perfect lighting')">
271
+ <i class="fas fa-gem text-pink-500 text-xl mb-1"></i>
272
+ <span class="text-xs">Butt Plug</span>
273
+ </button>
274
+ <button class="tool-btn flex flex-col items-center p-3 bg-gray-700 rounded-lg hover:bg-pink-600 hover:text-white" onclick="applyPrompt('Add vibrator to hand, make it look realistic, perfect lighting')">
275
+ <i class="fas fa-vibrate text-pink-500 text-xl mb-1"></i>
276
+ <span class="text-xs">Vibrator</span>
277
+ </button>
278
+ <button class="tool-btn flex flex-col items-center p-3 bg-gray-700 rounded-lg hover:bg-pink-600 hover:text-white" onclick="applyPrompt('Add realistic cum effect on body, perfect lighting, professional look')">
279
+ <i class="fas fa-tint text-pink-500 text-xl mb-1"></i>
280
+ <span class="text-xs">Cum Effect</span>
281
+ </button>
282
+ <button class="tool-btn flex flex-col items-center p-3 bg-gray-700 rounded-lg hover:bg-pink-600 hover:text-white" onclick="applyPrompt('Add rope bondage to wrists and ankles, realistic texture, perfect lighting')">
283
+ <i class="fas fa-hands-bound text-pink-500 text-xl mb-1"></i>
284
+ <span class="text-xs">Bondage</span>
285
+ </button>
286
+ <button class="tool-btn flex flex-col items-center p-3 bg-gray-700 rounded-lg hover:bg-pink-600 hover:text-white" onclick="applyPrompt('Add lace lingerie set, make it look realistic, perfect lighting')">
287
+ <i class="fas fa-tshirt text-pink-500 text-xl mb-1"></i>
288
+ <span class="text-xs">Lingerie</span>
289
+ </button>
290
+ </div>
291
+ </div>
292
+
293
+ <!-- Pose Maker -->
294
+ <div class="mb-6">
295
+ <h3 class="font-medium text-gray-300 mb-3">Pose Generator</h3>
296
+ <div class="grid grid-cols-3 gap-2 mb-3">
297
+ <div class="pose-preview h-16 bg-gray-700 rounded cursor-pointer hover:ring-2 hover:ring-pink-500" onclick="applyPose('bent-over')" style="background-image: url('https://i.imgur.com/JQlE0gP.png')"></div>
298
+ <div class="pose-preview h-16 bg-gray-700 rounded cursor-pointer hover:ring-2 hover:ring-pink-500" onclick="applyPose('legs-spread')" style="background-image: url('https://i.imgur.com/5XkJQqG.png')"></div>
299
+ <div class="pose-preview h-16 bg-gray-700 rounded cursor-pointer hover:ring-2 hover:ring-pink-500" onclick="applyPose('doggy')" style="background-image: url('https://i.imgur.com/8zJqWQk.png')"></div>
300
+ <div class="pose-preview h-16 bg-gray-700 rounded cursor-pointer hover:ring-2 hover:ring-pink-500" onclick="applyPose('missionary')" style="background-image: url('https://i.imgur.com/3mJQkqG.png')"></div>
301
+ <div class="pose-preview h-16 bg-gray-700 rounded cursor-pointer hover:ring-2 hover:ring-pink-500" onclick="applyPose('squat')" style="background-image: url('https://i.imgur.com/7XkJQqG.png')"></div>
302
+ <div class="pose-preview h-16 bg-gray-700 rounded cursor-pointer hover:ring-2 hover:ring-pink-500" onclick="applyPose('standing-tease')" style="background-image: url('https://i.imgur.com/9zJqWQk.png')"></div>
303
+ </div>
304
+ <button class="w-full py-2 bg-pink-900 text-pink-300 rounded-md text-sm hover:bg-pink-700 hover:text-white" onclick="showCustomPoseModal()">
305
+ <i class="fas fa-plus mr-1"></i> Custom Pose
306
+ </button>
307
+ </div>
308
+
309
+ <!-- Background Tools -->
310
+ <div class="mb-6">
311
+ <h3 class="font-medium text-gray-300 mb-3">Background</h3>
312
+ <div class="grid grid-cols-3 gap-3">
313
+ <button class="tool-btn flex flex-col items-center p-3 bg-gray-700 rounded-lg hover:bg-pink-600 hover:text-white" onclick="applyPrompt('Change background to luxury bedroom, perfect lighting, professional setup')">
314
+ <i class="fas fa-bed text-pink-500 text-xl mb-1"></i>
315
+ <span class="text-xs">Bedroom</span>
316
+ </button>
317
+ <button class="tool-btn flex flex-col items-center p-3 bg-gray-700 rounded-lg hover:bg-pink-600 hover:text-white" onclick="applyPrompt('Change background to hotel room, perfect lighting, professional setup')">
318
+ <i class="fas fa-hotel text-pink-500 text-xl mb-1"></i>
319
+ <span class="text-xs">Hotel</span>
320
+ </button>
321
+ <button class="tool-btn flex flex-col items-center p-3 bg-gray-700 rounded-lg hover:bg-pink-600 hover:text-white" onclick="applyPrompt('Change background to outdoor pool, perfect lighting, professional setup')">
322
+ <i class="fas fa-umbrella-beach text-pink-500 text-xl mb-1"></i>
323
+ <span class="text-xs">Outdoor</span>
324
+ </button>
325
+ </div>
326
+ </div>
327
+ </div>
328
+
329
+ <div id="video-tools" class="hidden">
330
+ <!-- Video tools content -->
331
+ <div class="text-center py-8 text-gray-500">
332
+ <i class="fas fa-video text-3xl mb-2"></i>
333
+ <p>Video editing coming soon!</p>
334
+ </div>
335
+ </div>
336
+ </div>
337
+
338
+ <!-- Editor Area -->
339
+ <div class="w-full lg:w-2/4 editor-container rounded-xl p-6">
340
+ <div class="preview-box bg-gray-800 rounded-lg overflow-hidden relative" style="height: 600px;">
341
+ <div class="absolute inset-0 flex items-center justify-center" id="placeholder">
342
+ <div class="text-center">
343
+ <i class="fas fa-image text-gray-600 text-5xl mb-3"></i>
344
+ <p class="text-gray-500">Upload NSFW content to start editing</p>
345
+ </div>
346
+ </div>
347
+ <div id="preview-container" class="relative w-full h-full hidden">
348
+ <img id="preview-image" src="" alt="" class="w-full h-full object-contain">
349
+ <video id="preview-video" controls class="hidden w-full h-full object-contain"></video>
350
+ <canvas id="face-swap-canvas" class="face-swap-canvas"></canvas>
351
+ </div>
352
+ <div id="processing-overlay" class="processing-overlay hidden">
353
+ <i class="fas fa-spinner fa-spin text-4xl mb-4 text-pink-500"></i>
354
+ <p id="processing-text" class="text-xl">Processing your content...</p>
355
+ <div class="w-full bg-gray-700 rounded-full h-2.5 mt-4 max-w-md">
356
+ <div id="progress-bar" class="bg-pink-500 h-2.5 rounded-full" style="width: 0%"></div>
357
+ </div>
358
+ <div id="ai-suggestions" class="mt-6 text-center max-w-md hidden">
359
+ <h4 class="font-medium mb-2">AI Suggestions</h4>
360
+ <div class="grid grid-cols-2 gap-2">
361
+ <button class="px-3 py-1 bg-pink-700 text-white rounded text-sm hover:bg-pink-600" onclick="applySuggestion('enhance-curves')">Enhance Curves</button>
362
+ <button class="px-3 py-1 bg-pink-700 text-white rounded text-sm hover:bg-pink-600" onclick="applySuggestion('add-toy')">Add Toy</button>
363
+ <button class="px-3 py-1 bg-pink-700 text-white rounded text-sm hover:bg-pink-600" onclick="applySuggestion('smooth-skin')">Smooth Skin</button>
364
+ <button class="px-3 py-1 bg-pink-700 text-white rounded text-sm hover:bg-pink-600" onclick="applySuggestion('sexier-pose')">Sexier Pose</button>
365
+ </div>
366
+ </div>
367
+ </div>
368
+ <div class="nsfw-badge hidden">NSFW</div>
369
+ </div>
370
+
371
+ <div class="mt-6 flex flex-wrap justify-center gap-3">
372
+ <button id="undo-btn" class="px-4 py-2 bg-gray-700 text-gray-300 rounded-md hover:bg-gray-600 disabled:opacity-50" disabled>
373
+ <i class="fas fa-undo mr-2"></i> Undo
374
+ </button>
375
+ <button id="redo-btn" class="px-4 py-2 bg-gray-700 text-gray-300 rounded-md hover:bg-gray-600 disabled:opacity-50" disabled>
376
+ <i class="fas fa-redo mr-2"></i> Redo
377
+ </button>
378
+ <button id="reset-btn" class="px-4 py-2 bg-gray-700 text-gray-300 rounded-md hover:bg-gray-600" onclick="resetEditor()">
379
+ <i class="fas fa-trash-alt mr-2"></i> Reset
380
+ </button>
381
+ <button id="auto-enhance-btn" class="px-6 py-2 bg-pink-800 text-pink-200 rounded-md hover:bg-pink-700 hover:text-white" onclick="autoEnhance()">
382
+ <i class="fas fa-magic mr-2"></i> Auto-Enhance
383
+ </button>
384
+ <button id="process-btn" class="px-6 py-2 bg-pink-600 text-white rounded-md hover:bg-pink-700" onclick="processImage()">
385
+ <i class="fas fa-cogs mr-2"></i> Process
386
+ </button>
387
+ <button id="save-btn" class="px-6 py-2 bg-purple-600 text-white rounded-md hover:bg-purple-700" onclick="saveImage()">
388
+ <i class="fas fa-download mr-2"></i> Save
389
+ </button>
390
+ </div>
391
+
392
+ <!-- Predictive AI Suggestions -->
393
+ <div id="predictive-suggestions" class="mt-6 bg-gray-800 rounded-lg p-4 hidden">
394
+ <h3 class="font-medium text-gray-300 mb-3 flex justify-between items-center">
395
+ <span>AI Suggestions</span>
396
+ <button onclick="hidePredictiveSuggestions()" class="text-gray-400 hover:text-white">
397
+ <i class="fas fa-times"></i>
398
+ </button>
399
+ </h3>
400
+ <div class="grid grid-cols-2 md:grid-cols-4 gap-3">
401
+ <button class="px-3 py-2 bg-gray-700 rounded text-sm hover:bg-pink-600 hover:text-white flex items-center" onclick="applySuggestion('enhance-curves')">
402
+ <i class="fas fa-venus mr-2"></i> Enhance Curves
403
+ </button>
404
+ <button class="px-3 py-2 bg-gray-700 rounded text-sm hover:bg-pink-600 hover:text-white flex items-center" onclick="applySuggestion('bigger-ass')">
405
+ <i class="fas fa-pepper-hot mr-2"></i> Bigger Ass
406
+ </button>
407
+ <button class="px-3 py-2 bg-gray-700 rounded text-sm hover:bg-pink-600 hover:text-white flex items-center" onclick="applySuggestion('add-toy')">
408
+ <i class="fas fa-dildo mr-2"></i> Add Toy
409
+ </button>
410
+ <button class="px-3 py-2 bg-gray-700 rounded text-sm hover:bg-pink-600 hover:text-white flex items-center" onclick="applySuggestion('sexier-pose')">
411
+ <i class="fas fa-fire mr-2"></i> Sexier Pose
412
+ </button>
413
+ <button class="px-3 py-2 bg-gray-700 rounded text-sm hover:bg-pink-600 hover:text-white flex items-center" onclick="applySuggestion('smooth-skin')">
414
+ <i class="fas fa-spa mr-2"></i> Smooth Skin
415
+ </button>
416
+ <button class="px-3 py-2 bg-gray-700 rounded text-sm hover:bg-pink-600 hover:text-white flex items-center" onclick="applySuggestion('better-lighting')">
417
+ <i class="fas fa-lightbulb mr-2"></i> Better Lighting
418
+ </button>
419
+ <button class="px-3 py-2 bg-gray-700 rounded text-sm hover:bg-pink-600 hover:text-white flex items-center" onclick="applySuggestion('add-lingerie')">
420
+ <i class="fas fa-tshirt mr-2"></i> Add Lingerie
421
+ </button>
422
+ <button class="px-3 py-2 bg-gray-700 rounded text-sm hover:bg-pink-600 hover:text-white flex items-center" onclick="applySuggestion('add-plug')">
423
+ <i class="fas fa-gem mr-2"></i> Add Plug
424
+ </button>
425
+ </div>
426
+ </div>
427
+ </div>
428
+
429
+ <!-- Layers Panel -->
430
+ <div class="w-full lg:w-1/4 bg-gray-800 rounded-xl shadow-md p-6 h-fit">
431
+ <div class="flex justify-between items-center mb-4">
432
+ <h3 class="font-medium text-gray-300">Content Library</h3>
433
+ <button class="text-pink-500 hover:text-pink-300" onclick="document.getElementById('file-upload').click()">
434
+ <i class="fas fa-plus"></i>
435
+ </button>
436
+ </div>
437
+
438
+ <div id="reference-container" class="space-y-3 max-h-64 overflow-y-auto">
439
+ <!-- Reference images will appear here -->
440
+ </div>
441
+
442
+ <div class="mt-6">
443
+ <h3 class="font-medium text-gray-300 mb-3">Quick Edits</h3>
444
+ <div class="grid grid-cols-2 gap-3">
445
+ <button class="px-3 py-2 bg-gray-700 rounded text-sm hover:bg-pink-600 hover:text-white" onclick="quickEdit('blur-background')">
446
+ <i class="fas fa-eye-slash mr-1"></i> Blur BG
447
+ </button>
448
+ <button class="px-3 py-2 bg-gray-700 rounded text-sm hover:bg-pink-600 hover:text-white" onclick="quickEdit('enhance-nipples')">
449
+ <i class="fas fa-dot-circle mr-1"></i> Enhance Nipples
450
+ </button>
451
+ <button class="px-3 py-2 bg-gray-700 rounded text-sm hover:bg-pink-600 hover:text-white" onclick="quickEdit('plump-lips')">
452
+ <i class="fas fa-lips mr-1"></i> Plump Lips
453
+ </button>
454
+ <button class="px-3 py-2 bg-gray-700 rounded text-sm hover:bg-pink-600 hover:text-white" onclick="quickEdit('smooth-skin')">
455
+ <i class="fas fa-spa mr-1"></i> Smooth Skin
456
+ </button>
457
+ </div>
458
+ </div>
459
+
460
+ <div class="mt-6">
461
+ <h3 class="font-medium text-gray-300 mb-3">OnlyFans Tools</h3>
462
+ <div class="space-y-3">
463
+ <button class="w-full py-2 bg-pink-700 text-white rounded-md text-sm hover:bg-pink-600 flex items-center justify-center" onclick="addWatermark()">
464
+ <i class="fas fa-copyright mr-2"></i> Add Watermark
465
+ </button>
466
+ <button class="w-full py-2 bg-purple-700 text-white rounded-md text-sm hover:bg-purple-600 flex items-center justify-center" onclick="generateTeaser()">
467
+ <i class="fas fa-lock-open mr-2"></i> Create Teaser
468
+ </button>
469
+ <button class="w-full py-2 bg-gray-700 text-white rounded-md text-sm hover:bg-gray-600 flex items-center justify-center" onclick="showSocialModal()">
470
+ <i class="fas fa-share-alt mr-2"></i> Social Preview
471
+ </button>
472
+ </div>
473
+ </div>
474
+
475
+ <div class="mt-6">
476
+ <h3 class="font-medium text-gray-300 mb-3">Export Options</h3>
477
+ <div class="space-y-3">
478
+ <div class="flex items-center">
479
+ <input type="radio" id="format-jpg" name="export-format" class="mr-2" checked>
480
+ <label for="format-jpg" class="text-sm">JPG (Recommended)</label>
481
+ </div>
482
+ <div class="flex items-center">
483
+ <input type="radio" id="format-png" name="export-format" class="mr-2">
484
+ <label for="format-png" class="text-sm">PNG (Lossless)</label>
485
+ </div>
486
+ <div class="flex items-center">
487
+ <input type="radio" id="format-webp" name="export-format" class="mr-2">
488
+ <label for="format-webp" class="text-sm">WebP (Smaller)</label>
489
+ </div>
490
+ </div>
491
+ <div class="mt-3">
492
+ <label class="block text-sm text-gray-400 mb-1">Quality</label>
493
+ <input type="range" id="export-quality" class="w-full slider-thumb" min="50" max="100" value="90">
494
+ <div class="flex justify-between text-xs text-gray-500">
495
+ <span>Low</span>
496
+ <span>High</span>
497
+ </div>
498
+ </div>
499
+ <div class="mt-3">
500
+ <label class="block text-sm text-gray-400 mb-1">Resolution</label>
501
+ <select id="export-resolution" class="w-full p-2 border border-gray-700 bg-gray-700 rounded-md text-sm">
502
+ <option value="original">Original</option>
503
+ <option value="1080">1080p (HD)</option>
504
+ <option value="720">720p</option>
505
+ <option value="4k">4K (UHD)</option>
506
+ </select>
507
+ </div>
508
+ </div>
509
+
510
+ <div class="mt-6">
511
+ <h3 class="font-medium text-gray-300 mb-3">Content Stats</h3>
512
+ <div class="bg-gray-700 rounded-md p-3 text-sm">
513
+ <div class="flex justify-between mb-1">
514
+ <span class="text-gray-400">Engagement Score:</span>
515
+ <span class="text-pink-400" id="engagement-score">--</span>
516
+ </div>
517
+ <div class="flex justify-between mb-1">
518
+ <span class="text-gray-400">Spicy Level:</span>
519
+ <span class="text-pink-400" id="spicy-level">--</span>
520
+ </div>
521
+ <div class="flex justify-between mb-1">
522
+ <span class="text-gray-400">Market Value:</span>
523
+ <span class="text-pink-400" id="market-value">--</span>
524
+ </div>
525
+ <div class="flex justify-between">
526
+ <span class="text-gray-400">AI Rating:</span>
527
+ <span class="text-pink-400" id="ai-rating">--</span>
528
+ </div>
529
+ </div>
530
+ </div>
531
+ </div>
532
+ </div>
533
+ </main>
534
+
535
+ <!-- Face Swap Modal -->
536
+ <div id="face-swap-modal" class="fixed inset-0 bg-black bg-opacity-70 flex items-center justify-center hidden z-50">
537
+ <div class="bg-gray-800 rounded-lg p-6 w-full max-w-2xl border border-pink-500">
538
+ <div class="flex justify-between items-center mb-4">
539
+ <h3 class="text-lg font-medium text-white">Face Swap</h3>
540
+ <button onclick="hideFaceSwapModal()" class="text-gray-400 hover:text-white">
541
+ <i class="fas fa-times"></i>
542
+ </button>
543
+ </div>
544
+ <div class="grid grid-cols-2 gap-4 mb-4">
545
+ <div>
546
+ <h4 class="text-sm font-medium mb-2 text-gray-300">Source Face</h4>
547
+ <select id="modal-source-face" class="w-full p-2 border border-gray-700 bg-gray-700 rounded-md text-sm mb-2 text-white" onchange="updateFacePreview('source')">
548
+ <option value="" class="text-gray-400">Select reference image</option>
549
+ </select>
550
+ <div class="border border-gray-700 rounded-md h-40 bg-gray-700 flex items-center justify-center relative face-swap-preview" id="source-face-preview">
551
+ <span class="text-gray-500">No image selected</span>
552
+ </div>
553
+ </div>
554
+ <div>
555
+ <h4 class="text-sm font-medium mb-2 text-gray-300">Target Face</h4>
556
+ <select id="modal-target-face" class="w-full p-2 border border-gray-700 bg-gray-700 rounded-md text-sm mb-2 text-white" onchange="updateFacePreview('target')">
557
+ <option value="" class="text-gray-400">Select reference image</option>
558
+ </select>
559
+ <div class="border border-gray-700 rounded-md h-40 bg-gray-700 flex items-center justify-center relative face-swap-preview" id="target-face-preview">
560
+ <span class="text-gray-500">No image selected</span>
561
+ </div>
562
+ </div>
563
+ </div>
564
+ <div class="mb-4">
565
+ <label class="block text-sm text-gray-400 mb-1">Face Alignment Strength</label>
566
+ <input type="range" id="face-align-strength" class="w-full slider-thumb" min="0" max="100" value="75">
567
+ </div>
568
+ <div class="mb-4">
569
+ <label class="block text-sm text-gray-400 mb-1">Skin Tone Matching</label>
570
+ <input type="range" id="skin-tone-match" class="w-full slider-thumb" min="0" max="100" value="50">
571
+ </div>
572
+ <div class="mb-4">
573
+ <label class="block text-sm text-gray-400 mb-1">Blending Intensity</label>
574
+ <input type="range" id="blend-intensity" class="w-full slider-thumb" min="0" max="100" value="80">
575
+ </div>
576
+ <div class="flex justify-end space-x-3">
577
+ <button onclick="hideFaceSwapModal()" class="px-4 py-2 bg-gray-700 text-gray-300 rounded-md hover:bg-gray-600">
578
+ Cancel
579
+ </button>
580
+ <button onclick="applyModalFaceSwap()" class="px-4 py-2 bg-pink-600 text-white rounded-md hover:bg-pink-700">
581
+ Apply Face Swap
582
+ </button>
583
+ </div>
584
+ </div>
585
+ </div>
586
+
587
+ <!-- Custom Pose Modal -->
588
+ <div id="custom-pose-modal" class="fixed inset-0 bg-black bg-opacity-70 flex items-center justify-center hidden z-50">
589
+ <div class="bg-gray-800 rounded-lg p-6 w-full max-w-2xl border border-pink-500">
590
+ <div class="flex justify-between items-center mb-4">
591
+ <h3 class="text-lg font-medium text-white">Create Custom Pose</h3>
592
+ <button onclick="hideCustomPoseModal()" class="text-gray-400 hover:text-white">
593
+ <i class="fas fa-times"></i>
594
+ </button>
595
+ </div>
596
+ <div class="mb-4">
597
+ <label class="block text-sm text-gray-400 mb-1">Pose Description</label>
598
+ <textarea id="pose-description" class="w-full border border-gray-700 bg-gray-700 rounded-md p-2 text-sm text-white" placeholder="Describe the pose you want (e.g. 'bent over, ass up, looking back')"></textarea>
599
+ </div>
600
+ <div class="mb-4">
601
+ <label class="block text-sm text-gray-400 mb-1">Pose Strength</label>
602
+ <input type="range" id="pose-strength" class="w-full slider-thumb" min="0" max="100" value="50">
603
+ </div>
604
+ <div class="mb-4">
605
+ <label class="block text-sm text-gray-400 mb-1">Suggestions</label>
606
+ <div class="grid grid-cols-2 gap-2">
607
+ <button class="px-2 py-1 bg-gray-700 text-xs rounded hover:bg-pink-600 hover:text-white" onclick="document.getElementById('pose-description').value = 'bent over, ass up, looking back'">Bent Over</button>
608
+ <button class="px-2 py-1 bg-gray-700 text-xs rounded hover:bg-pink-600 hover:text-white" onclick="document.getElementById('pose-description').value = 'legs spread, touching self'">Legs Spread</button>
609
+ <button class="px-2 py-1 bg-gray-700 text-xs rounded hover:bg-pink-600 hover:text-white" onclick="document.getElementById('pose-description').value = 'on knees, chest up, mouth open'">Kneeling</button>
610
+ <button class="px-2 py-1 bg-gray-700 text-xs rounded hover:bg-pink-600 hover:text-white" onclick="document.getElementById('pose-description').value = 'squatting, showing everything'">Squatting</button>
611
+ </div>
612
+ </div>
613
+ <div class="flex justify-end space-x-3">
614
+ <button onclick="hideCustomPoseModal()" class="px-4 py-2 bg-gray-700 text-gray-300 rounded-md hover:bg-gray-600">
615
+ Cancel
616
+ </button>
617
+ <button onclick="applyCustomPose()" class="px-4 py-2 bg-pink-600 text-white rounded-md hover:bg-pink-700">
618
+ Create Pose
619
+ </button>
620
+ </div>
621
+ </div>
622
+ </div>
623
+
624
+ <!-- Social Preview Modal -->
625
+ <div id="social-modal" class="fixed inset-0 bg-black bg-opacity-70 flex items-center justify-center hidden z-50">
626
+ <div class="bg-gray-800 rounded-lg p-6 w-full max-w-2xl border border-pink-500">
627
+ <div class="flex justify-between items-center mb-4">
628
+ <h3 class="text-lg font-medium text-white">Social Media Preview</h3>
629
+ <button onclick="hideSocialModal()" class="text-gray-400 hover:text-white">
630
+ <i class="fas fa-times"></i>
631
+ </button>
632
+ </div>
633
+ <div class="grid grid-cols-3 gap-4 mb-4">
634
+ <div class="bg-gray-900 p-2 rounded text-center">
635
+ <div class="h-32 bg-gray-700 rounded mb-2 flex items-center justify-center">
636
+ <i class="fas fa-instagram text-2xl text-pink-500"></i>
637
+ </div>
638
+ <p class="text-xs text-gray-400">Instagram</p>
639
+ </div>
640
+ <div class="bg-gray-900 p-2 rounded text-center">
641
+ <div class="h-32 bg-gray-700 rounded mb-2 flex items-center justify-center">
642
+ <i class="fas fa-twitter text-2xl text-blue-400"></i>
643
+ </div>
644
+ <p class="text-xs text-gray-400">Twitter</p>
645
+ </div>
646
+ <div class="bg-gray-900 p-2 rounded text-center">
647
+ <div class="h-32 bg-gray-700 rounded mb-2 flex items-center justify-center">
648
+ <i class="fas fa-tiktok text-2xl text-white"></i>
649
+ </div>
650
+ <p class="text-xs text-gray-400">TikTok</p>
651
+ </div>
652
+ </div>
653
+ <div class="mb-4">
654
+ <label class="block text-sm text-gray-400 mb-1">Preview Text</label>
655
+ <input type="text" class="w-full p-2 border border-gray-700 bg-gray-700 rounded-md text-sm text-white" value="New content coming soon! 🔥">
656
+ </div>
657
+ <div class="flex justify-end space-x-3">
658
+ <button onclick="hideSocialModal()" class="px-4 py-2 bg-gray-700 text-gray-300 rounded-md hover:bg-gray-600">
659
+ Close
660
+ </button>
661
+ <button onclick="copySocialPreview()" class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
662
+ Copy Preview
663
+ </button>
664
+ </div>
665
+ </div>
666
+ </div>
667
+
668
+ <script>
669
+ // Global variables
670
+ let uploadedImages = [];
671
+ let currentImageIndex = 0;
672
+ let editHistory = [];
673
+ let currentHistoryIndex = -1;
674
+ let bodyParams = {
675
+ breast: 0,
676
+ ass: 0,
677
+ waist: 0,
678
+ pussy: 0
679
+ };
680
+ let faceDetectionModelsLoaded = false;
681
+
682
+ // Initialize the editor
683
+ document.addEventListener('DOMContentLoaded', async function() {
684
+ // Set up character counter for prompt box
685
+ const promptBox = document.getElementById('ai-prompt');
686
+ const charCount = document.getElementById('char-count');
687
+
688
+ promptBox.addEventListener('input', function() {
689
+ charCount.textContent = this.value.length;
690
+
691
+ // Show predictive suggestions if typing
692
+ if(this.value.length > 10 && !this.value.includes('ass') && !this.value.includes('toy') && !this.value.includes('plug')) {
693
+ showPredictiveSuggestions();
694
+ }
695
+ });
696
+
697
+ // Initialize sliders with value displays
698
+ const sliders = ['breast', 'ass', 'waist', 'pussy'];
699
+ sliders.forEach(slider => {
700
+ const sliderElement = document.getElementById(`${slider}-slider`);
701
+ const valueElement = document.getElementById(`${slider}-value`);
702
+
703
+ sliderElement.addEventListener('input', function() {
704
+ valueElement.textContent = `${this.value}%`;
705
+ });
706
+ });
707
+
708
+ // Set up undo/redo buttons
709
+ document.getElementById('undo-btn').addEventListener('click', undo);
710
+ document.getElementById('redo-btn').addEventListener('click', redo);
711
+
712
+ // Load face detection models
713
+ await loadFaceDetectionModels();
714
+
715
+ // Auto-enhance after first upload
716
+ let firstUpload = true;
717
+ });
718
+
719
+ // Load face detection models
720
+ async function loadFaceDetectionModels() {
721
+ try {
722
+ await faceapi.nets.tinyFaceDetector.loadFromUri('/models');
723
+ await faceapi.nets.faceLandmark68Net.loadFromUri('/models');
724
+ await faceapi.nets.faceRecognitionNet.loadFromUri('/models');
725
+ faceDetectionModelsLoaded = true;
726
+ console.log('Face detection models loaded successfully');
727
+ } catch (error) {
728
+ console.error('Error loading face detection models:', error);
729
+ }
730
+ }
731
+
732
+ // File upload functionality
733
+ const fileUpload = document.getElementById('file-upload');
734
+ const uploadArea = document.getElementById('upload-area');
735
+ const thumbnailContainer = document.getElementById('thumbnail-container');
736
+ const referenceContainer = document.getElementById('reference-container');
737
+ const previewImage = document.getElementById('preview-image');
738
+ const previewVideo = document.getElementById('preview-video');
739
+ const placeholder = document.getElementById('placeholder');
740
+ const previewContainer = document.getElementById('preview-container');
741
+ const nsfwBadge = document.querySelector('.nsfw-badge');
742
+
743
+ // Handle drag and drop
744
+ uploadArea.addEventListener('dragover', (e) => {
745
+ e.preventDefault();
746
+ uploadArea.classList.add('bg-pink-900', 'border-pink-500');
747
+ });
748
+
749
+ uploadArea.addEventListener('dragleave', () => {
750
+ uploadArea.classList.remove('bg-pink-900', 'border-pink-500');
751
+ });
752
+
753
+ uploadArea.addEventListener('drop', (e) => {
754
+ e.preventDefault();
755
+ uploadArea.classList.remove('bg-pink-900', 'border-pink-500');
756
+ if (e.dataTransfer.files.length > 0) {
757
+ fileUpload.files = e.dataTransfer.files;
758
+ handleFileUpload();
759
+ }
760
+ });
761
+
762
+ uploadArea.addEventListener('click', () => fileUpload.click());
763
+
764
+ fileUpload.addEventListener('change', handleFileUpload);
765
+
766
+ function handleFileUpload() {
767
+ const files = fileUpload.files;
768
+ if (!files || files.length === 0) return;
769
+
770
+ for (let i = 0; i < files.length; i++) {
771
+ const file = files[i];
772
+ if (!file.type.startsWith('image/') && !file.type.startsWith('video/')) continue;
773
+
774
+ const reader = new FileReader();
775
+ reader.onload = function(event) {
776
+ const mediaData = {
777
+ id: Date.now() + i,
778
+ src: event.target.result,
779
+ name: file.name,
780
+ originalSrc: event.target.result,
781
+ type: file.type.startsWith('image/') ? 'image' : 'video'
782
+ };
783
+ uploadedImages.push(mediaData);
784
+
785
+ // Add to thumbnail container
786
+ const thumbnail = document.createElement('div');
787
+ thumbnail.className = `image-thumbnail relative ${uploadedImages.length === 1 ? 'active' : ''}`;
788
+ thumbnail.innerHTML = `
789
+ ${mediaData.type === 'image' ?
790
+ `<img src="${mediaData.src}" class="w-full h-full object-cover rounded">` :
791
+ `<video src="${mediaData.src}" class="w-full h-full object-cover rounded"></video>`}
792
+ <div class="absolute inset-0 flex items-center justify-center bg-black bg-opacity-0 hover:bg-opacity-30 transition-all duration-200">
793
+ <button onclick="setActiveImage(${mediaData.id})" class="text-white opacity-0 hover:opacity-100">
794
+ <i class="fas fa-check-circle text-xl"></i>
795
+ </button>
796
+ </div>
797
+ `;
798
+ thumbnailContainer.appendChild(thumbnail);
799
+
800
+ // Add to reference container
801
+ const referenceItem = document.createElement('div');
802
+ referenceItem.className = 'flex items-center p-2 bg-gray-700 rounded-md hover:bg-gray-600';
803
+ referenceItem.innerHTML = `
804
+ <div class="w-10 h-10 bg-gray-600 rounded-md mr-3 overflow-hidden">
805
+ ${mediaData.type === 'image' ?
806
+ `<img src="${mediaData.src}" class="w-full h-full object-cover">` :
807
+ `<video src="${mediaData.src}" class="w-full h-full object-cover"></video>`}
808
+ </div>
809
+ <div class="flex-1 truncate">
810
+ <p class="text-sm font-medium truncate">${file.name}</p>
811
+ <p class="text-xs text-gray-400">${(file.size / 1024).toFixed(1)} KB</p>
812
+ </div>
813
+ <button onclick="removeImage(${mediaData.id})" class="text-gray-400 hover:text-pink-500 ml-2">
814
+ <i class="fas fa-times"></i>
815
+ </button>
816
+ `;
817
+ referenceContainer.appendChild(referenceItem);
818
+
819
+ // Update select options
820
+ updateSelectOptions();
821
+
822
+ // Set first image as active
823
+ if (uploadedImages.length === 1) {
824
+ setActiveImage(mediaData.id);
825
+ nsfwBadge.classList.remove('hidden');
826
+
827
+ // Auto-enhance on first upload
828
+ setTimeout(() => {
829
+ autoEnhance();
830
+ }, 500);
831
+ }
832
+
833
+ // Analyze content for suggestions
834
+ setTimeout(() => {
835
+ analyzeContent();
836
+ }, 1000);
837
+ };
838
+ reader.readAsDataURL(file);
839
+ }
840
+ }
841
+
842
+ function setActiveImage(id) {
843
+ const imageData = uploadedImages.find(img => img.id === id);
844
+ if (!imageData) return;
845
+
846
+ currentImageIndex = uploadedImages.findIndex(img => img.id === id);
847
+
848
+ if (imageData.type === 'image') {
849
+ previewImage.src = imageData.src;
850
+ previewImage.classList.remove('hidden');
851
+ previewVideo.classList.add('hidden');
852
+ } else {
853
+ previewVideo.src = imageData.src;
854
+ previewVideo.classList.remove('hidden');
855
+ previewImage.classList.add('hidden');
856
+ }
857
+
858
+ previewContainer.classList.remove('hidden');
859
+ placeholder.classList.add('hidden');
860
+
861
+ // Update active thumbnail
862
+ document.querySelectorAll('.image-thumbnail').forEach((thumb, index) => {
863
+ if (index === currentImageIndex) {
864
+ thumb.classList.add('active');
865
+ } else {
866
+ thumb.classList.remove('active');
867
+ }
868
+ });
869
+
870
+ // Save to history
871
+ saveToHistory();
872
+
873
+ // Analyze content for suggestions
874
+ analyzeContent();
875
+ }
876
+
877
+ function removeImage(id) {
878
+ const index = uploadedImages.findIndex(img => img.id === id);
879
+ if (index === -1) return;
880
+
881
+ uploadedImages.splice(index, 1);
882
+
883
+ // Remove from thumbnail container
884
+ thumbnailContainer.children[index].remove();
885
+
886
+ // Remove from reference container
887
+ referenceContainer.children[index].remove();
888
+
889
+ // Update select options
890
+ updateSelectOptions();
891
+
892
+ // If we removed the active image
893
+ if (currentImageIndex === index) {
894
+ if (uploadedImages.length > 0) {
895
+ // Set next available image as active
896
+ const newIndex = Math.min(index, uploadedImages.length - 1);
897
+ setActiveImage(uploadedImages[newIndex].id);
898
+ } else {
899
+ // No images left
900
+ previewImage.src = '';
901
+ previewVideo.src = '';
902
+ previewContainer.classList.add('hidden');
903
+ placeholder.classList.remove('hidden');
904
+ nsfwBadge.classList.add('hidden');
905
+ }
906
+ } else if (currentImageIndex > index) {
907
+ currentImageIndex--;
908
+ }
909
+
910
+ saveToHistory();
911
+ }
912
+
913
+ function updateSelectOptions() {
914
+ const modalSourceFace = document.getElementById('modal-source-face');
915
+ const modalTargetFace = document.getElementById('modal-target-face');
916
+
917
+ // Clear existing options except first
918
+ [modalSourceFace, modalTargetFace].forEach(select => {
919
+ while (select.options.length > 1) {
920
+ select.remove(1);
921
+ }
922
+ });
923
+
924
+ // Add new options
925
+ uploadedImages.forEach((img, index) => {
926
+ const option = document.createElement('option');
927
+ option.value = img.id;
928
+ option.textContent = `Image ${index + 1}`;
929
+ option.className = 'text-white';
930
+
931
+ const option2 = option.cloneNode(true);
932
+
933
+ modalSourceFace.appendChild(option);
934
+ modalTargetFace.appendChild(option2);
935
+ });
936
+ }
937
+
938
+ // History management
939
+ function saveToHistory() {
940
+ if (uploadedImages.length === 0) return;
941
+
942
+ // Truncate history if we're not at the end
943
+ if (currentHistoryIndex < editHistory.length - 1) {
944
+ editHistory = editHistory.slice(0, currentHistoryIndex + 1);
945
+ }
946
+
947
+ // Save current state
948
+ const historyItem = {
949
+ imageSrc: uploadedImages[currentImageIndex].src,
950
+ bodyParams: {...bodyParams}
951
+ };
952
+
953
+ editHistory.push(historyItem);
954
+ currentHistoryIndex = editHistory.length - 1;
955
+
956
+ // Update undo/redo buttons
957
+ document.getElementById('undo-btn').disabled = currentHistoryIndex <= 0;
958
+ document.getElementById('redo-btn').disabled = currentHistoryIndex >= editHistory.length - 1;
959
+ }
960
+
961
+ function undo() {
962
+ if (currentHistoryIndex <= 0) return;
963
+
964
+ currentHistoryIndex--;
965
+ applyHistoryState();
966
+ }
967
+
968
+ function redo() {
969
+ if (currentHistoryIndex >= editHistory.length - 1) return;
970
+
971
+ currentHistoryIndex++;
972
+ applyHistoryState();
973
+ }
974
+
975
+ function applyHistoryState() {
976
+ const historyItem = editHistory[currentHistoryIndex];
977
+
978
+ // Update image
979
+ if (uploadedImages[currentImageIndex].type === 'image') {
980
+ previewImage.src = historyItem.imageSrc;
981
+ } else {
982
+ previewVideo.src = historyItem.imageSrc;
983
+ }
984
+ uploadedImages[currentImageIndex].src = historyItem.imageSrc;
985
+
986
+ // Update body params
987
+ bodyParams = {...historyItem.bodyParams};
988
+ document.getElementById('breast-slider').value = bodyParams.breast;
989
+ document.getElementById('ass-slider').value = bodyParams.ass;
990
+ document.getElementById('waist-slider').value = bodyParams.waist;
991
+ document.getElementById('pussy-slider').value = bodyParams.pussy;
992
+
993
+ // Update slider values
994
+ document.getElementById('breast-value').textContent = `${bodyParams.breast}%`;
995
+ document.getElementById('ass-value').textContent = `${bodyParams.ass}%`;
996
+ document.getElementById('waist-value').textContent = `${bodyParams.waist}%`;
997
+ document.getElementById('pussy-value').textContent = `${bodyParams.pussy}%`;
998
+
999
+ // Update buttons
1000
+ document.getElementById('undo-btn').disabled = currentHistoryIndex <= 0;
1001
+ document.getElementById('redo-btn').disabled = currentHistoryIndex >= editHistory.length - 1;
1002
+ }
1003
+
1004
+ // Reset button functionality
1005
+ function resetEditor() {
1006
+ if (uploadedImages.length === 0) return;
1007
+
1008
+ if (uploadedImages[currentImageIndex].type === 'image') {
1009
+ previewImage.src = uploadedImages[currentImageIndex].originalSrc;
1010
+ } else {
1011
+ previewVideo.src = uploadedImages[currentImageIndex].originalSrc;
1012
+ }
1013
+ uploadedImages[currentImageIndex].src = uploadedImages[currentImageIndex].originalSrc;
1014
+
1015
+ // Reset sliders
1016
+ document.getElementById('breast-slider').value = 0;
1017
+ document.getElementById('ass-slider').value = 0;
1018
+ document.getElementById('waist-slider').value = 0;
1019
+ document.getElementById('pussy-slider').value = 0;
1020
+ bodyParams = { breast: 0, ass: 0, waist: 0, pussy: 0 };
1021
+
1022
+ // Update slider values
1023
+ document.getElementById('breast-value').textContent = "0%";
1024
+ document.getElementById('ass-value').textContent = "0%";
1025
+ document.getElementById('waist-value').textContent = "0%";
1026
+ document.getElementById('pussy-value').textContent = "0%";
1027
+
1028
+ // Clear history
1029
+ editHistory = [];
1030
+ currentHistoryIndex = -1;
1031
+ document.getElementById('undo-btn').disabled = true;
1032
+ document.getElementById('redo-btn').disabled = true;
1033
+
1034
+ saveToHistory();
1035
+ }
1036
+
1037
+ // Process button functionality
1038
+ async function processImage() {
1039
+ if (!previewImage.src && !previewVideo.src) {
1040
+ alert('Please upload NSFW content first');
1041
+ return;
1042
+ }
1043
+
1044
+ const promptBox = document.getElementById('ai-prompt');
1045
+ const prompt = promptBox.value;
1046
+
1047
+ if (!prompt && Object.values(bodyParams).every(val => val === 0)) {
1048
+ alert('Please enter a prompt or adjust body parameters');
1049
+ return;
1050
+ }
1051
+
1052
+ // Show processing overlay
1053
+ const overlay = document.getElementById('processing-overlay');
1054
+ const progressBar = document.getElementById('progress-bar');
1055
+ const processingText = document.getElementById('processing-text');
1056
+ const aiSuggestions = document.getElementById('ai-suggestions');
1057
+
1058
+ overlay.classList.remove('hidden');
1059
+ processingText.textContent = 'Enhancing your content...';
1060
+ aiSuggestions.classList.add('hidden');
1061
+
1062
+ // Simulate processing with progress
1063
+ let progress = 0;
1064
+ const interval = setInterval(() => {
1065
+ progress += Math.random() * 10;
1066
+ if (progress > 100) progress = 100;
1067
+ progressBar.style.width = `${progress}%`;
1068
+
1069
+ if (progress === 100) {
1070
+ clearInterval(interval);
1071
+ processingText.textContent = 'Finalizing enhancements...';
1072
+
1073
+ setTimeout(() => {
1074
+ overlay.classList.add('hidden');
1075
+ progressBar.style.width = '0%';
1076
+
1077
+ // In a real app, this would call your AI processing API
1078
+ // For demo, we'll just modify the image slightly
1079
+ if (uploadedImages[currentImageIndex].type === 'image') {
1080
+ const canvas = document.createElement('canvas');
1081
+ const ctx = canvas.getContext('2d');
1082
+ const img = new Image();
1083
+ img.onload = function() {
1084
+ canvas.width = img.width;
1085
+ canvas.height = img.height;
1086
+ ctx.drawImage(img, 0, 0);
1087
+
1088
+ // Apply body enhancements based on sliders
1089
+ if (bodyParams.breast !== 0) {
1090
+ // Simulate breast enhancement
1091
+ ctx.fillStyle = 'rgba(255, 200, 200, 0.1)';
1092
+ ctx.beginPath();
1093
+ ctx.ellipse(canvas.width * 0.4, canvas.height * 0.4,
1094
+ canvas.width * 0.1 * (1 + bodyParams.breast/100),
1095
+ canvas.height * 0.15 * (1 + bodyParams.breast/100),
1096
+ 0, 0, Math.PI * 2);
1097
+ ctx.fill();
1098
+
1099
+ ctx.beginPath();
1100
+ ctx.ellipse(canvas.width * 0.6, canvas.height * 0.4,
1101
+ canvas.width * 0.1 * (1 + bodyParams.breast/100),
1102
+ canvas.height * 0.15 * (1 + bodyParams.breast/100),
1103
+ 0, 0, Math.PI * 2);
1104
+ ctx.fill();
1105
+ }
1106
+
1107
+ if (bodyParams.ass !== 0) {
1108
+ // Simulate ass enhancement
1109
+ ctx.fillStyle = 'rgba(200, 200, 255, 0.1)';
1110
+ ctx.beginPath();
1111
+ ctx.ellipse(canvas.width * 0.5, canvas.height * 0.6,
1112
+ canvas.width * 0.15 * (1 + bodyParams.ass/100),
1113
+ canvas.height * 0.1 * (1 + bodyParams.ass/100),
1114
+ 0, 0, Math.PI * 2);
1115
+ ctx.fill();
1116
+ }
1117
+
1118
+ if (bodyParams.waist !== 0) {
1119
+ // Simulate waist enhancement
1120
+ ctx.fillStyle = 'rgba(255, 255, 200, 0.1)';
1121
+ ctx.beginPath();
1122
+ ctx.ellipse(canvas.width * 0.5, canvas.height * 0.5,
1123
+ canvas.width * 0.1 * (1 - bodyParams.waist/200),
1124
+ canvas.height * 0.15 * (1 - bodyParams.waist/200),
1125
+ 0, 0, Math.PI * 2);
1126
+ ctx.fill();
1127
+ }
1128
+
1129
+ if (bodyParams.pussy !== 0) {
1130
+ // Simulate pussy enhancement
1131
+ ctx.fillStyle = 'rgba(255, 150, 200, 0.1)';
1132
+ ctx.beginPath();
1133
+ ctx.ellipse(canvas.width * 0.5, canvas.height * 0.7,
1134
+ canvas.width * 0.08 * (1 + bodyParams.pussy/100),
1135
+ canvas.height * 0.05 * (1 + bodyParams.pussy/100),
1136
+ 0, 0, Math.PI * 2);
1137
+ ctx.fill();
1138
+ }
1139
+
1140
+ // Apply effects based on prompt
1141
+ if (prompt.includes('smooth') || prompt.includes('skin')) {
1142
+ // Simulate skin smoothing
1143
+ ctx.filter = 'blur(1px)';
1144
+ ctx.drawImage(canvas, 0, 0);
1145
+ ctx.filter = 'none';
1146
+ }
1147
+
1148
+ if (prompt.includes('toy') || prompt.includes('dildo') || prompt.includes('vibrator')) {
1149
+ // Simulate adding a toy
1150
+ ctx.fillStyle = '#ff69b4';
1151
+ ctx.beginPath();
1152
+ ctx.ellipse(canvas.width * 0.5, canvas.height * 0.7,
1153
+ canvas.width * 0.05, canvas.height * 0.15,
1154
+ Math.PI/4, 0, Math.PI * 2);
1155
+ ctx.fill();
1156
+ }
1157
+
1158
+ if (prompt.includes('plug') || prompt.includes('anal')) {
1159
+ // Simulate adding a butt plug
1160
+ ctx.fillStyle = '#9370db';
1161
+ ctx.beginPath();
1162
+ ctx.ellipse(canvas.width * 0.5, canvas.height * 0.3,
1163
+ canvas.width * 0.03, canvas.height * 0.03,
1164
+ 0, 0, Math.PI * 2);
1165
+ ctx.fill();
1166
+
1167
+ // Add jewel to plug
1168
+ ctx.fillStyle = '#ffd700';
1169
+ ctx.beginPath();
1170
+ ctx.ellipse(canvas.width * 0.5, canvas.height * 0.28,
1171
+ canvas.width * 0.01, canvas.height * 0.01,
1172
+ 0, 0, Math.PI * 2);
1173
+ ctx.fill();
1174
+ }
1175
+
1176
+ // Update the image
1177
+ const newSrc = canvas.toDataURL('image/jpeg');
1178
+ previewImage.src = newSrc;
1179
+ uploadedImages[currentImageIndex].src = newSrc;
1180
+
1181
+ saveToHistory();
1182
+
1183
+ // Show AI suggestions
1184
+ setTimeout(() => {
1185
+ overlay.classList.remove('hidden');
1186
+ processingText.textContent = 'Enhancement complete!';
1187
+ aiSuggestions.classList.remove('hidden');
1188
+ progressBar.style.width = '0%';
1189
+
1190
+ // Hide after 5 seconds
1191
+ setTimeout(() => {
1192
+ overlay.classList.add('hidden');
1193
+ }, 5000);
1194
+ }, 500);
1195
+ };
1196
+ img.src = previewImage.src;
1197
+ }
1198
+ }, 500);
1199
+ }
1200
+ }, 100);
1201
+ }
1202
+
1203
+ // Auto-enhance function
1204
+ function autoEnhance() {
1205
+ if (!previewImage.src && !previewVideo.src) {
1206
+ alert('Please upload NSFW content first');
1207
+ return;
1208
+ }
1209
+
1210
+ // Set some default enhancements
1211
+ document.getElementById('breast-slider').value = 15;
1212
+ document.getElementById('ass-slider').value = 25;
1213
+ document.getElementById('waist-slider').value = 20;
1214
+ document.getElementById('pussy-slider').value = 10;
1215
+
1216
+ // Update displayed values
1217
+ document.getElementById('breast-value').textContent = "15%";
1218
+ document.getElementById('ass-value').textContent = "25%";
1219
+ document.getElementById('waist-value').textContent = "20%";
1220
+ document.getElementById('pussy-value').textContent = "10%";
1221
+
1222
+ // Update body params
1223
+ bodyParams.breast = 15;
1224
+ bodyParams.ass = 25;
1225
+ bodyParams.waist = 20;
1226
+ bodyParams.pussy = 10;
1227
+
1228
+ // Set a smart prompt
1229
+ document.getElementById('ai-prompt').value = "Enhance curves, smooth skin, perfect lighting, professional look";
1230
+
1231
+ // Process the image
1232
+ processImage();
1233
+ }
1234
+
1235
+ // Save button functionality
1236
+ function saveImage() {
1237
+ if (!previewImage.src && !previewVideo.src) {
1238
+ alert('Please upload NSFW content first');
1239
+ return;
1240
+ }
1241
+
1242
+ // Get selected format
1243
+ let format = 'jpg';
1244
+ if (document.getElementById('format-png').checked) format = 'png';
1245
+ if (document.getElementById('format-webp').checked) format = 'webp';
1246
+
1247
+ // Get quality
1248
+ const quality = document.getElementById('export-quality').value;
1249
+
1250
+ // Simulate download
1251
+ const link = document.createElement('a');
1252
+ if (previewImage.src) {
1253
+ link.href = previewImage.src;
1254
+ link.download = `onlyfans-content.${format}`;
1255
+ } else {
1256
+ link.href = previewVideo.src;
1257
+ link.download = 'onlyfans-video.mp4';
1258
+ }
1259
+ document.body.appendChild(link);
1260
+ link.click();
1261
+ document.body.removeChild(link);
1262
+
1263
+ // Show confirmation
1264
+ alert(`Content saved as ${format.toUpperCase()} at ${quality}% quality!`);
1265
+ }
1266
+
1267
+ // Body parameter updates
1268
+ function updateBodyParam(param, value) {
1269
+ bodyParams[param] = parseInt(value);
1270
+ document.getElementById(`${param}-value`).textContent = `${value}%`;
1271
+ saveToHistory();
1272
+ }
1273
+
1274
+ // AI Prompt functions
1275
+ function applyPrompt(prompt) {
1276
+ document.getElementById('ai-prompt').value = prompt;
1277
+ document.getElementById('char-count').textContent = prompt.length;
1278
+ processImage();
1279
+ }
1280
+
1281
+ // Face Swap Functions
1282
+ async function showFaceSwapModal() {
1283
+ if (uploadedImages.length < 2) {
1284
+ alert('You need at least 2 images to perform face swap');
1285
+ return;
1286
+ }
1287
+
1288
+ document.getElementById('face-swap-modal').classList.remove('hidden');
1289
+
1290
+ // Load face detection models if not already loaded
1291
+ if (!faceDetectionModelsLoaded) {
1292
+ await loadFaceDetectionModels();
1293
+ }
1294
+ }
1295
+
1296
+ function hideFaceSwapModal() {
1297
+ document.getElementById('face-swap-modal').classList.add('hidden');
1298
+ }
1299
+
1300
+ async function updateFacePreview(type) {
1301
+ const select = type === 'source' ?
1302
+ document.getElementById('modal-source-face') :
1303
+ document.getElementById('modal-target-face');
1304
+ const preview = document.getElementById(`${type}-face-preview`);
1305
+
1306
+ const selectedId = select.value;
1307
+ if (!selectedId) {
1308
+ preview.innerHTML = '<span class="text-gray-500">No image selected</span>';
1309
+ return;
1310
+ }
1311
+
1312
+ const imageData = uploadedImages.find(img => img.id == selectedId);
1313
+ if (!imageData) return;
1314
+
1315
+ // Clear previous preview
1316
+ preview.innerHTML = '';
1317
+
1318
+ // Add image to preview
1319
+ const img = document.createElement('img');
1320
+ img.src = imageData.src;
1321
+ img.className = 'w-full h-full object-contain';
1322
+ preview.appendChild(img);
1323
+
1324
+ // Detect faces and draw landmarks
1325
+ if (faceDetectionModelsLoaded) {
1326
+ const detections = await faceapi.detectAllFaces(img, new faceapi.TinyFaceDetectorOptions())
1327
+ .withFaceLandmarks()
1328
+ .withFaceDescriptors();
1329
+
1330
+ if (detections.length > 0) {
1331
+ // Draw face detection boxes
1332
+ detections.forEach(detection => {
1333
+ const box = detection.detection.box;
1334
+ const faceBox = document.createElement('div');
1335
+ faceBox.className = 'face-detection-box';
1336
+ faceBox.style.width = `${box.width}px`;
1337
+ faceBox.style.height = `${box.height}px`;
1338
+ faceBox.style.left = `${box.x}px`;
1339
+ faceBox.style.top = `${box.y}px`;
1340
+ preview.appendChild(faceBox);
1341
+ });
1342
+
1343
+ // Draw face landmarks
1344
+ detections.forEach(detection => {
1345
+ const landmarks = detection.landmarks;
1346
+ landmarks.positions.forEach(point => {
1347
+ const dot = document.createElement('div');
1348
+ dot.className = 'face-landmarks';
1349
+ dot.style.left = `${point.x}px`;
1350
+ dot.style.top = `${point.y}px`;
1351
+ preview.appendChild(dot);
1352
+ });
1353
+ });
1354
+ }
1355
+ }
1356
+ }
1357
+
1358
+ async function applyModalFaceSwap() {
1359
+ const sourceId = document.getElementById('modal-source-face').value;
1360
+ const targetId = document.getElementById('modal-target-face').value;
1361
+
1362
+ if (!sourceId || !targetId) {
1363
+ alert('Please select both source and target faces');
1364
+ return;
1365
+ }
1366
+
1367
+ if (sourceId === targetId) {
1368
+ alert('Source and target faces must be different');
1369
+ return;
1370
+ }
1371
+
1372
+ const strength = document.getElementById('face-align-strength').value;
1373
+ const skinTone = document.getElementById('skin-tone-match').value;
1374
+ const blendIntensity = document.getElementById('blend-intensity').value;
1375
+
1376
+ // Show processing
1377
+ const overlay = document.getElementById('processing-overlay');
1378
+ const progressBar = document.getElementById('progress-bar');
1379
+ const processingText = document.getElementById('processing-text');
1380
+
1381
+ overlay.classList.remove('hidden');
1382
+ processingText.textContent = 'Swapping faces...';
1383
+
1384
+ // Get the source and target images
1385
+ const sourceImg = uploadedImages.find(img => img.id == sourceId);
1386
+ const targetImg = uploadedImages.find(img => img.id == targetId);
1387
+
1388
+ // Create canvas elements for face swapping
1389
+ const sourceCanvas = document.createElement('canvas');
1390
+ const sourceCtx = sourceCanvas.getContext('2d');
1391
+ const targetCanvas = document.createElement('canvas');
1392
+ const targetCtx = targetCanvas.getContext('2d');
1393
+
1394
+ // Load source image
1395
+ const sourceImage = new Image();
1396
+ sourceImage.onload = async function() {
1397
+ sourceCanvas.width = sourceImage.width;
1398
+ sourceCanvas.height = sourceImage.height;
1399
+ sourceCtx.drawImage(sourceImage, 0, 0);
1400
+
1401
+ // Load target image
1402
+ const targetImage = new Image();
1403
+ targetImage.onload = async function() {
1404
+ targetCanvas.width = targetImage.width;
1405
+ targetCanvas.height = targetImage.height;
1406
+ targetCtx.drawImage(targetImage, 0, 0);
1407
+
1408
+ // Detect faces in both images
1409
+
1410
+ </html>
prompts.txt ADDED
File without changes