aikenml commited on
Commit
32ad221
Β·
1 Parent(s): cf902d2

added CHOOSE FILE and CLEAR

Browse files
.DS_Store ADDED
Binary file (6.15 kB). View file
 
app/chains/__pycache__/detectors.cpython-310.pyc CHANGED
Binary files a/app/chains/__pycache__/detectors.cpython-310.pyc and b/app/chains/__pycache__/detectors.cpython-310.pyc differ
 
app/chains/detectors.py CHANGED
@@ -18,7 +18,7 @@ def detect_ai(text):
18
  },
19
  {
20
  "name": "Another Detector",
21
- "probability": 0.5 # 85% AI probability
22
  },
23
  {
24
  "name": "Another Detector ",
 
18
  },
19
  {
20
  "name": "Another Detector",
21
+ "probability": 0.96 # 85% AI probability
22
  },
23
  {
24
  "name": "Another Detector ",
app/static/anothercode.txt DELETED
@@ -1,429 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <title>AI Text Humanizer</title>
6
- <style>
7
- * {
8
- margin: 0;
9
- padding: 0;
10
- box-sizing: border-box;
11
- }
12
-
13
- html, body {
14
- height: 100%;
15
- }
16
-
17
- body {
18
- font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
19
- background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 50%, #ec4899 100%);
20
- color: #1f2937;
21
- overflow: hidden; /* Prevent full-page scrolling */
22
- }
23
-
24
- .container {
25
- height: 100%;
26
- max-width: 1400px;
27
- margin: 0 auto;
28
- display: flex;
29
- flex-direction: column;
30
- padding: 16px;
31
- }
32
-
33
- /* ===== HEADER (Title + Subtitle) ===== */
34
- .header {
35
- text-align: center;
36
- margin-bottom: 16px; /* Reduced bottom margin so header sits higher */
37
- }
38
-
39
- h1 {
40
- font-size: 2.0em; /* Slightly smaller */
41
- font-weight: 800;
42
- background: linear-gradient(135deg, #ffffff 0%, #f8fafc 100%);
43
- -webkit-background-clip: text;
44
- -webkit-text-fill-color: transparent;
45
- background-clip: text;
46
- margin-bottom: 6px;
47
- text-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
48
- }
49
-
50
- p.description {
51
- color: rgba(255, 255, 255, 0.9);
52
- font-size: 1.2em;
53
- font-weight: 300;
54
- }
55
-
56
- /* ===== MAIN GRID (Input + Output Panels) ===== */
57
- .main-content {
58
- flex: 1;
59
- display: grid;
60
- grid-template-columns: 1fr 1fr;
61
- gap: 24px;
62
- height: calc(100% - 64px); /* Subtract header’s height */
63
- }
64
-
65
- @media (max-width: 1200px) {
66
- .main-content {
67
- grid-template-columns: 1fr;
68
- grid-template-rows: 1fr 1fr;
69
- gap: 20px;
70
- }
71
- h1 {
72
- font-size: 1.8em;
73
- }
74
- }
75
-
76
- @media (max-width: 768px) {
77
- .container {
78
- padding: 12px;
79
- }
80
- .panel {
81
- padding: 16px;
82
- }
83
- h1 {
84
- font-size: 1.6em;
85
- }
86
- p.description {
87
- font-size: 1em;
88
- }
89
- }
90
-
91
- /* ===== PANEL BASE STYLES ===== */
92
- .panel {
93
- background: rgba(255, 255, 255, 0.95);
94
- backdrop-filter: blur(20px);
95
- border-radius: 20px;
96
- box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
97
- border: 1px solid rgba(255, 255, 255, 0.2);
98
-
99
- display: flex;
100
- flex-direction: column;
101
- height: 100%;
102
- overflow: hidden;
103
- padding: 24px;
104
- }
105
-
106
- .input-panel {
107
- background: rgba(255, 255, 255, 0.98);
108
- }
109
-
110
- .output-panel {
111
- background: rgba(248, 250, 252, 0.98);
112
- }
113
-
114
- /* ===== PANEL HEADER (Title + Subtitle inside each panel) ===== */
115
- .panel-header {
116
- margin-bottom: 16px;
117
- padding-bottom: 12px;
118
- border-bottom: 2px solid rgba(99, 102, 241, 0.1);
119
- }
120
-
121
- .panel-title {
122
- font-size: 1.3em;
123
- font-weight: 600;
124
- color: #374151;
125
- margin-bottom: 6px;
126
- }
127
-
128
- .panel-subtitle {
129
- color: #6b7280;
130
- font-size: 0.9em;
131
- }
132
-
133
- /* ===== INPUT PANEL CONTROLS ===== */
134
- textarea {
135
- flex: 1; /* Takes all available vertical space */
136
- font-size: 15px;
137
- padding: 16px;
138
- border: 2px solid #e5e7eb;
139
- border-radius: 12px;
140
- resize: none;
141
- transition: all 0.3s ease;
142
- font-family: inherit;
143
- line-height: 1.6;
144
- background: #fafafa;
145
- overflow-y: auto;
146
- }
147
-
148
- textarea:focus {
149
- outline: none;
150
- border-color: #6366f1;
151
- box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);
152
- background: white;
153
- }
154
-
155
- textarea::placeholder {
156
- color: #9ca3af;
157
- }
158
-
159
- /* ===== BUTTON STYLES ===== */
160
- button {
161
- background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);
162
- color: white;
163
- padding: 14px 28px;
164
- font-size: 15px;
165
- font-weight: 600;
166
- border: none;
167
- border-radius: 12px;
168
- cursor: pointer;
169
- transition: all 0.3s ease;
170
- box-shadow: 0 4px 15px rgba(99, 102, 241, 0.3);
171
- }
172
-
173
- button:hover {
174
- transform: translateY(-2px);
175
- box-shadow: 0 8px 25px rgba(99, 102, 241, 0.4);
176
- }
177
-
178
- button:active {
179
- transform: translateY(0);
180
- }
181
-
182
- .copy-button {
183
- background: linear-gradient(135deg, #10b981 0%, #059669 100%);
184
- box-shadow: 0 4px 15px rgba(16, 185, 129, 0.3);
185
- margin-top: 0;
186
- flex-shrink: 0;
187
- width: 100%;
188
- }
189
-
190
- .copy-button:hover {
191
- box-shadow: 0 8px 25px rgba(16, 185, 129, 0.4);
192
- }
193
-
194
- .copy-button.copied {
195
- background: linear-gradient(135deg, #22c55e 0%, #16a34a 100%);
196
- }
197
-
198
- /* ===== OUTPUT CONTENT (scrollable) ===== */
199
- .output-content {
200
- flex: 1; /* Fill vertical space between header and bottom button */
201
- padding: 16px;
202
- background: #f8fafc;
203
- border: 2px solid #e2e8f0;
204
- border-radius: 12px;
205
- font-size: 15px;
206
- line-height: 1.7;
207
- white-space: pre-wrap;
208
- overflow-y: auto; /* Only this area scrolls */
209
- color: #334155;
210
- }
211
-
212
- /* ===== BOTTOM BUTTON CONTAINER (fixed height) ===== */
213
- .panel-bottom {
214
- margin-top: 16px;
215
- height: 48px; /* Same in both panels β†’ Y-coordinate alignment */
216
- display: flex;
217
- align-items: center;
218
- }
219
-
220
- /* ===== LOADING & ERROR STATES ===== */
221
- .loading {
222
- color: #64748b;
223
- font-style: italic;
224
- text-align: center;
225
- padding: 40px 20px;
226
- display: flex;
227
- align-items: center;
228
- justify-content: center;
229
- gap: 8px;
230
- }
231
-
232
- .loading::before {
233
- content: "✨";
234
- animation: pulse 1.5s infinite;
235
- }
236
-
237
- @keyframes pulse {
238
- 0%, 100% {
239
- opacity: 1;
240
- }
241
- 50% {
242
- opacity: 0.5;
243
- }
244
- }
245
-
246
- .error {
247
- color: #ef4444;
248
- font-weight: 500;
249
- text-align: center;
250
- padding: 24px 16px;
251
- background: rgba(239, 68, 68, 0.05);
252
- border-radius: 8px;
253
- }
254
-
255
- /* ===== CUSTOM SCROLLBAR for output ===== */
256
- .output-content::-webkit-scrollbar {
257
- width: 6px;
258
- }
259
- .output-content::-webkit-scrollbar-track {
260
- background: #f1f5f9;
261
- border-radius: 3px;
262
- }
263
- .output-content::-webkit-scrollbar-thumb {
264
- background: #cbd5e1;
265
- border-radius: 3px;
266
- }
267
- .output-content::-webkit-scrollbar-thumb:hover {
268
- background: #94a3b8;
269
- }
270
- </style>
271
- </head>
272
- <body>
273
- <div class="container">
274
- <!-- ===== HEADER ===== -->
275
- <div class="header">
276
- <h1>🌟 AI Text Humanizer</h1>
277
- <p class="description">Transform AI text into natural, human-like language</p>
278
- </div>
279
-
280
- <!-- ===== MAIN PANELS ===== -->
281
- <div class="main-content">
282
- <!-- ==================== INPUT PANEL ==================== -->
283
- <div class="panel input-panel">
284
- <div class="panel-header">
285
- <div class="panel-title">πŸ“ Input Text</div>
286
- <div class="panel-subtitle">Paste your AI-generated content here</div>
287
- </div>
288
-
289
- <!-- Removed the β€œSelect Tone / Audience” dropdown entirely -->
290
- <textarea
291
- id="inputText"
292
- placeholder="Paste your AI-generated text here and watch the magic happen..."
293
- ></textarea>
294
-
295
- <div class="panel-bottom">
296
- <!-- β€œHumanize Text” button, pinned to bottom of input panel -->
297
- <button type="button" onclick="humanize()">πŸš€ Humanize Text</button>
298
- </div>
299
- </div>
300
-
301
- <!-- ==================== OUTPUT PANEL ==================== -->
302
- <div class="panel output-panel">
303
- <div class="panel-header">
304
- <div class="panel-title">✨ Humanized Result</div>
305
- <div class="panel-subtitle">Your transformed, natural text</div>
306
- </div>
307
-
308
- <!-- #result holds loading / error / final text; scrollable -->
309
- <div id="result" class="output-content">
310
- <div class="loading">Your humanized text will appear here...</div>
311
- </div>
312
-
313
- <div class="panel-bottom">
314
- <!-- Copy button hidden until text arrives -->
315
- <button
316
- id="copyBtn"
317
- type="button"
318
- class="copy-button"
319
- style="display: none;"
320
- onclick="copyText()"
321
- >
322
- πŸ“‹ Copy Text
323
- </button>
324
- </div>
325
- </div>
326
- </div>
327
- </div>
328
-
329
- <!-- ===== JAVASCRIPT ===== -->
330
- <script>
331
- async function humanize() {
332
- const textArea = document.getElementById("inputText");
333
- const outputDiv = document.getElementById("result");
334
- const copyBtn = document.getElementById("copyBtn");
335
-
336
- const text = textArea.value.trim();
337
-
338
- if (!text) {
339
- alert("Please enter some text first!");
340
- return;
341
- }
342
-
343
- // Show β€œloading” inside outputDiv
344
- outputDiv.textContent = "";
345
- const spinner = document.createElement("div");
346
- spinner.className = "loading";
347
- spinner.textContent = "Processing your text...";
348
- outputDiv.appendChild(spinner);
349
-
350
- // Hide copy button until we have a successful response
351
- copyBtn.style.display = "none";
352
-
353
- try {
354
- const response = await fetch("/humanize", {
355
- method: "POST",
356
- headers: {
357
- "Content-Type": "application/json",
358
- },
359
- // Now we only send { text }, since we dropped β€œaudience”
360
- body: JSON.stringify({ text }),
361
- });
362
-
363
- if (!response.ok) {
364
- throw new Error(`Server responded with status ${response.status}`);
365
- }
366
-
367
- const data = await response.json();
368
-
369
- // Replace spinner with the actual humanized text
370
- outputDiv.textContent = data.humanized;
371
- // Show copy button
372
- copyBtn.style.display = "block";
373
- } catch (error) {
374
- outputDiv.textContent = "";
375
- const errDiv = document.createElement("div");
376
- errDiv.className = "error";
377
- errDiv.textContent = `❌ Error: ${error.message}`;
378
- outputDiv.appendChild(errDiv);
379
- console.error("Error:", error);
380
- }
381
- }
382
-
383
- async function copyText() {
384
- const outputDiv = document.getElementById("result");
385
- const copyBtn = document.getElementById("copyBtn");
386
- const textToCopy = outputDiv.textContent || outputDiv.innerText;
387
-
388
- try {
389
- await navigator.clipboard.writeText(textToCopy);
390
-
391
- // Instant feedback on the button
392
- const original = copyBtn.innerHTML;
393
- copyBtn.innerHTML = "βœ… Copied!";
394
- copyBtn.classList.add("copied");
395
- setTimeout(() => {
396
- copyBtn.innerHTML = original;
397
- copyBtn.classList.remove("copied");
398
- }, 2000);
399
- } catch {
400
- // Fallback for older browsers
401
- const tmp = document.createElement("textarea");
402
- tmp.value = textToCopy;
403
- document.body.appendChild(tmp);
404
- tmp.select();
405
- document.execCommand("copy");
406
- document.body.removeChild(tmp);
407
-
408
- copyBtn.innerHTML = "βœ… Copied!";
409
- setTimeout(() => {
410
- copyBtn.innerHTML = "πŸ“‹ Copy Text";
411
- }, 2000);
412
- }
413
- }
414
-
415
- // Ctrl+Enter = humanize
416
- document.addEventListener("keydown", (e) => {
417
- if (e.ctrlKey && e.key === "Enter") {
418
- humanize();
419
- }
420
- });
421
-
422
- // Auto-resize the input textarea as you type
423
- document.getElementById("inputText").addEventListener("input", function () {
424
- this.style.height = "auto";
425
- this.style.height = this.scrollHeight + "px";
426
- });
427
- </script>
428
- </body>
429
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/static/code.txt DELETED
@@ -1,468 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <title>AI Text Humanizer</title>
6
- <style>
7
- * {
8
- margin: 0;
9
- padding: 0;
10
- box-sizing: border-box;
11
- }
12
-
13
- html, body {
14
- height: 100%;
15
- }
16
-
17
- body {
18
- font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
19
- background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 50%, #ec4899 100%);
20
- color: #1f2937;
21
- overflow: hidden; /* prevent whole‐page scrolling */
22
- }
23
-
24
- .container {
25
- height: 100%;
26
- max-width: 1400px;
27
- margin: 0 auto;
28
- display: flex;
29
- flex-direction: column;
30
- padding: 16px; /* slightly reduced padding */
31
- }
32
-
33
- /* ===== HEADER (Title + Subtitle) ===== */
34
- .header {
35
- text-align: center;
36
- margin-bottom: 16px;
37
- /* Removed extra top/bottom padding so it sits β€œhigher.” */
38
- }
39
-
40
- /* Make the <h1> a bit smaller so it sits above the panels */
41
- h1 {
42
- font-size: 2.0em; /* was 2.2em; now even a tad smaller */
43
- font-weight: 800;
44
- background: linear-gradient(135deg, #ffffff 0%, #f8fafc 100%);
45
- -webkit-background-clip: text;
46
- -webkit-text-fill-color: transparent;
47
- background-clip: text;
48
- margin-bottom: 6px;
49
- text-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
50
- }
51
-
52
- p.description {
53
- color: rgba(255, 255, 255, 0.9);
54
- font-size: 1.2em; /* slightly smaller */
55
- font-weight: 300;
56
- }
57
-
58
- /* ===== MAIN CONTENT GRID ===== */
59
- .main-content {
60
- flex: 1;
61
- display: grid;
62
- grid-template-columns: 1fr 1fr;
63
- gap: 24px;
64
- height: calc(100% - 64px); /* subtract header area (~64px) */
65
- }
66
-
67
- @media (max-width: 1200px) {
68
- .main-content {
69
- grid-template-columns: 1fr;
70
- grid-template-rows: 1fr 1fr;
71
- gap: 20px;
72
- }
73
- h1 {
74
- font-size: 1.8em;
75
- }
76
- }
77
-
78
- @media (max-width: 768px) {
79
- .container {
80
- padding: 12px;
81
- }
82
- .panel {
83
- padding: 16px;
84
- }
85
- h1 {
86
- font-size: 1.6em;
87
- }
88
- p.description {
89
- font-size: 1em;
90
- }
91
- }
92
-
93
- /* ===== PANELS ===== */
94
- .panel {
95
- background: rgba(255, 255, 255, 0.95);
96
- backdrop-filter: blur(20px);
97
- border-radius: 20px;
98
- box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
99
- border: 1px solid rgba(255, 255, 255, 0.2);
100
-
101
- /* Make each panel occupy its full grid‐cell height */
102
- display: flex;
103
- flex-direction: column;
104
- height: 100%;
105
- overflow: hidden;
106
- padding: 24px; /* unified padding */
107
- }
108
-
109
- .input-panel {
110
- background: rgba(255, 255, 255, 0.98);
111
- }
112
-
113
- .output-panel {
114
- background: rgba(248, 250, 252, 0.98);
115
- }
116
-
117
- /* ===== PANEL HEADER (Title + Subtitle inside each panel) ===== */
118
- .panel-header {
119
- margin-bottom: 16px;
120
- padding-bottom: 12px;
121
- border-bottom: 2px solid rgba(99, 102, 241, 0.1);
122
- }
123
-
124
- .panel-title {
125
- font-size: 1.3em;
126
- font-weight: 600;
127
- color: #374151;
128
- margin-bottom: 6px;
129
- }
130
-
131
- .panel-subtitle {
132
- color: #6b7280;
133
- font-size: 0.9em;
134
- }
135
-
136
- /* ===== FORM CONTROLS ===== */
137
- label {
138
- font-weight: 600;
139
- display: block;
140
- margin-bottom: 8px;
141
- color: #374151;
142
- font-size: 1em;
143
- }
144
-
145
- select {
146
- width: 100%;
147
- font-size: 15px;
148
- padding: 10px 14px;
149
- border: 2px solid #e5e7eb;
150
- border-radius: 12px;
151
- background: white;
152
- color: #374151;
153
- transition: all 0.3s ease;
154
- margin-bottom: 16px;
155
- }
156
-
157
- select:focus {
158
- outline: none;
159
- border-color: #6366f1;
160
- box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);
161
- }
162
-
163
- textarea {
164
- flex: 1; /* take all remaining vertical space */
165
- font-size: 15px;
166
- padding: 16px;
167
- border: 2px solid #e5e7eb;
168
- border-radius: 12px;
169
- resize: none;
170
- transition: all 0.3s ease;
171
- font-family: inherit;
172
- line-height: 1.6;
173
- background: #fafafa;
174
- overflow-y: auto;
175
- }
176
-
177
- textarea:focus {
178
- outline: none;
179
- border-color: #6366f1;
180
- box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);
181
- background: white;
182
- }
183
-
184
- textarea::placeholder {
185
- color: #9ca3af;
186
- }
187
-
188
- /* ===== BUTTONS ===== */
189
- button {
190
- background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);
191
- color: white;
192
- padding: 14px 28px;
193
- font-size: 15px;
194
- font-weight: 600;
195
- border: none;
196
- border-radius: 12px;
197
- cursor: pointer;
198
- transition: all 0.3s ease;
199
- box-shadow: 0 4px 15px rgba(99, 102, 241, 0.3);
200
- }
201
-
202
- button:hover {
203
- transform: translateY(-2px);
204
- box-shadow: 0 8px 25px rgba(99, 102, 241, 0.4);
205
- }
206
-
207
- button:active {
208
- transform: translateY(0);
209
- }
210
-
211
- .copy-button {
212
- background: linear-gradient(135deg, #10b981 0%, #059669 100%);
213
- box-shadow: 0 4px 15px rgba(16, 185, 129, 0.3);
214
- margin-top: 0;
215
- flex-shrink: 0;
216
- width: 100%;
217
- }
218
-
219
- .copy-button:hover {
220
- box-shadow: 0 8px 25px rgba(16, 185, 129, 0.4);
221
- }
222
-
223
- .copy-button.copied {
224
- background: linear-gradient(135deg, #22c55e 0%, #16a34a 100%);
225
- }
226
-
227
- /* ===== OUTPUT CONTENT (scrollable) ===== */
228
- .output-content {
229
- flex: 1; /* fill vertical space between header and bottom button */
230
- padding: 16px;
231
- background: #f8fafc;
232
- border: 2px solid #e2e8f0;
233
- border-radius: 12px;
234
- font-size: 15px;
235
- line-height: 1.7;
236
- white-space: pre-wrap;
237
- overflow-y: auto; /* ONLY this area scrolls */
238
- color: #334155;
239
- }
240
-
241
- /* ===== PANEL BOTTOM (holds the button) ===== */
242
- .panel-bottom {
243
- margin-top: 16px;
244
- /* Fixed height so that buttons in both panels sit on same Y axis */
245
- height: 48px;
246
- display: flex;
247
- align-items: center;
248
- }
249
-
250
- /* ===== LOADING & ERROR STATES ===== */
251
- .loading {
252
- color: #64748b;
253
- font-style: italic;
254
- text-align: center;
255
- padding: 40px 20px;
256
- display: flex;
257
- align-items: center;
258
- justify-content: center;
259
- gap: 8px;
260
- }
261
-
262
- .loading::before {
263
- content: "✨";
264
- animation: pulse 1.5s infinite;
265
- }
266
-
267
- @keyframes pulse {
268
- 0%, 100% {
269
- opacity: 1;
270
- }
271
- 50% {
272
- opacity: 0.5;
273
- }
274
- }
275
-
276
- .error {
277
- color: #ef4444;
278
- font-weight: 500;
279
- text-align: center;
280
- padding: 24px 16px;
281
- background: rgba(239, 68, 68, 0.05);
282
- border-radius: 8px;
283
- }
284
-
285
- /* ===== CUSTOM SCROLLBAR for output ===== */
286
- .output-content::-webkit-scrollbar {
287
- width: 6px;
288
- }
289
- .output-content::-webkit-scrollbar-track {
290
- background: #f1f5f9;
291
- border-radius: 3px;
292
- }
293
- .output-content::-webkit-scrollbar-thumb {
294
- background: #cbd5e1;
295
- border-radius: 3px;
296
- }
297
- .output-content::-webkit-scrollbar-thumb:hover {
298
- background: #94a3b8;
299
- }
300
-
301
- </style>
302
- </head>
303
- <body>
304
- <div class="container">
305
- <!-- ===== HEADER ===== -->
306
- <div class="header">
307
- <h1>🌟 AI Text Humanizer</h1>
308
- <p class="description">Transform AI text into natural, human-like language</p>
309
- </div>
310
-
311
- <!-- ===== MAIN GRID (Input + Output) ===== -->
312
- <div class="main-content">
313
- <!-- ==================== INPUT PANEL ==================== -->
314
- <div class="panel input-panel">
315
- <div class="panel-header">
316
- <div class="panel-title">πŸ“ Input Text</div>
317
- <div class="panel-subtitle">Paste your AI-generated content here</div>
318
- </div>
319
-
320
- <label for="audience">Select Tone / Audience:</label>
321
- <select id="audience">
322
- <option value="default">Default (Natural &amp; Human)</option>
323
- <option value="business">Business Professional</option>
324
- <option value="academic">Academic &amp; Formal</option>
325
- <option value="gen_z">Gen Z &amp; Casual</option>
326
- </select>
327
-
328
- <textarea
329
- id="inputText"
330
- placeholder="Paste your AI-generated text here and watch the magic happen..."
331
- ></textarea>
332
-
333
- <div class="panel-bottom">
334
- <!-- β€œHumanize Text” button, fixed at bottom of input‐panel -->
335
- <button type="button" onclick="humanize()">πŸš€ Humanize Text</button>
336
- </div>
337
- </div>
338
-
339
- <!-- ==================== OUTPUT PANEL ==================== -->
340
- <div class="panel output-panel">
341
- <div class="panel-header">
342
- <div class="panel-title">✨ Humanized Result</div>
343
- <div class="panel-subtitle">Your transformed, natural text</div>
344
- </div>
345
-
346
- <!-- #result holds loading / error / final text; this area scrolls -->
347
- <div id="result" class="output-content">
348
- <div class="loading">Your humanized text will appear here...</div>
349
- </div>
350
-
351
- <div class="panel-bottom">
352
- <!-- Copy button initially hidden; will be shown after we get a response -->
353
- <button
354
- id="copyBtn"
355
- type="button"
356
- class="copy-button"
357
- style="display: none;"
358
- onclick="copyText()"
359
- >
360
- πŸ“‹ Copy Text
361
- </button>
362
- </div>
363
- </div>
364
- </div>
365
- </div>
366
-
367
- <!-- ===== JAVASCRIPT ===== -->
368
- <script>
369
- async function humanize() {
370
- const textArea = document.getElementById("inputText");
371
- const audienceSelect = document.getElementById("audience");
372
- const outputDiv = document.getElementById("result");
373
- const copyBtn = document.getElementById("copyBtn");
374
-
375
- const text = textArea.value.trim();
376
- const audience = audienceSelect.value;
377
-
378
- if (!text) {
379
- alert("Please enter some text first!");
380
- return;
381
- }
382
-
383
- // Show β€œloading” inside outputDiv
384
- outputDiv.textContent = "";
385
- const spinner = document.createElement("div");
386
- spinner.className = "loading";
387
- spinner.textContent = "Processing your text...";
388
- outputDiv.appendChild(spinner);
389
-
390
- // Hide copy button until we have a successful response
391
- copyBtn.style.display = "none";
392
-
393
- try {
394
- const response = await fetch("/humanize", {
395
- method: "POST",
396
- headers: {
397
- "Content-Type": "application/json",
398
- },
399
- body: JSON.stringify({ text, audience }),
400
- });
401
-
402
- if (!response.ok) {
403
- throw new Error(`Server responded with status ${response.status}`);
404
- }
405
-
406
- const data = await response.json();
407
-
408
- // Replace spinner with the actual humanized text
409
- outputDiv.textContent = data.humanized;
410
- // Show copy button
411
- copyBtn.style.display = "block";
412
- } catch (error) {
413
- outputDiv.textContent = "";
414
- const errDiv = document.createElement("div");
415
- errDiv.className = "error";
416
- errDiv.textContent = `❌ Error: ${error.message}`;
417
- outputDiv.appendChild(errDiv);
418
- console.error("Error:", error);
419
- }
420
- }
421
-
422
- async function copyText() {
423
- const outputDiv = document.getElementById("result");
424
- const copyBtn = document.getElementById("copyBtn");
425
- const textToCopy = outputDiv.textContent || outputDiv.innerText;
426
-
427
- try {
428
- await navigator.clipboard.writeText(textToCopy);
429
-
430
- // Instant feedback on the button
431
- const original = copyBtn.innerHTML;
432
- copyBtn.innerHTML = "βœ… Copied!";
433
- copyBtn.classList.add("copied");
434
- setTimeout(() => {
435
- copyBtn.innerHTML = original;
436
- copyBtn.classList.remove("copied");
437
- }, 2000);
438
- } catch {
439
- // Fallback for older browsers
440
- const tmp = document.createElement("textarea");
441
- tmp.value = textToCopy;
442
- document.body.appendChild(tmp);
443
- tmp.select();
444
- document.execCommand("copy");
445
- document.body.removeChild(tmp);
446
-
447
- copyBtn.innerHTML = "βœ… Copied!";
448
- setTimeout(() => {
449
- copyBtn.innerHTML = "πŸ“‹ Copy Text";
450
- }, 2000);
451
- }
452
- }
453
-
454
- // Ctrl+Enter = humanize
455
- document.addEventListener("keydown", (e) => {
456
- if (e.ctrlKey && e.key === "Enter") {
457
- humanize();
458
- }
459
- });
460
-
461
- // Auto‐resize the input textarea as you type
462
- document.getElementById("inputText").addEventListener("input", function () {
463
- this.style.height = "auto";
464
- this.style.height = this.scrollHeight + "px";
465
- });
466
- </script>
467
- </body>
468
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/static/index copy 2.html DELETED
@@ -1,641 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <title>AI Text Humanizer</title>
6
- <style>
7
- * {
8
- margin: 0;
9
- padding: 0;
10
- box-sizing: border-box;
11
- }
12
-
13
- html, body {
14
- height: 100%;
15
- }
16
-
17
- body {
18
- font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
19
- background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 50%, #ec4899 100%);
20
- color: #1f2937;
21
- overflow: hidden; /* Prevent full-page scrolling */
22
- }
23
-
24
- .container {
25
- height: 100%;
26
- max-width: 1400px;
27
- margin: 0 auto;
28
- display: flex;
29
- flex-direction: column;
30
- padding: 16px;
31
- }
32
-
33
- /* ===== HEADER (Title + Subtitle) ===== */
34
- .header {
35
- text-align: center;
36
- margin-bottom: 16px; /* Reduced bottom margin so header sits higher */
37
- }
38
-
39
- h1 {
40
- font-size: 2.0em; /* Slightly smaller */
41
- font-weight: 800;
42
- background: linear-gradient(135deg, #ffffff 0%, #f8fafc 100%);
43
- -webkit-background-clip: text;
44
- -webkit-text-fill-color: transparent;
45
- background-clip: text;
46
- margin-bottom: 6px;
47
- text-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
48
- }
49
-
50
- p.description {
51
- color: rgba(255, 255, 255, 0.9);
52
- font-size: 1.2em;
53
- font-weight: 300;
54
- }
55
-
56
- /* ===== MAIN GRID (Input + Output Panels) ===== */
57
- .main-content {
58
- flex: 1;
59
- display: grid;
60
- grid-template-columns: 1fr 1fr;
61
- gap: 24px;
62
- height: calc(100% - 64px); /* Subtract header's height */
63
- }
64
-
65
- @media (max-width: 1200px) {
66
- .main-content {
67
- grid-template-columns: 1fr;
68
- grid-template-rows: 1fr 1fr;
69
- gap: 20px;
70
- }
71
- h1 {
72
- font-size: 1.8em;
73
- }
74
- }
75
-
76
- @media (max-width: 768px) {
77
- .container {
78
- padding: 12px;
79
- }
80
- .panel {
81
- padding: 16px;
82
- }
83
- h1 {
84
- font-size: 1.6em;
85
- }
86
- p.description {
87
- font-size: 1em;
88
- }
89
- }
90
-
91
- /* ===== PANEL BASE STYLES ===== */
92
- .panel {
93
- background: rgba(255, 255, 255, 0.95);
94
- backdrop-filter: blur(20px);
95
- border-radius: 20px;
96
- box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
97
- border: 1px solid rgba(255, 255, 255, 0.2);
98
-
99
- display: flex;
100
- flex-direction: column;
101
- height: 100%;
102
- overflow: hidden;
103
- padding: 24px;
104
- }
105
-
106
- .input-panel {
107
- background: rgba(255, 255, 255, 0.98);
108
- }
109
-
110
- .output-panel {
111
- background: rgba(248, 250, 252, 0.98);
112
- }
113
-
114
- /* ===== PANEL HEADER (Title + Subtitle inside each panel) ===== */
115
- .panel-header {
116
- margin-bottom: 16px;
117
- padding-bottom: 12px;
118
- border-bottom: 2px solid rgba(99, 102, 241, 0.1);
119
- }
120
-
121
- .panel-title {
122
- font-size: 1.3em;
123
- font-weight: 600;
124
- color: #374151;
125
- margin-bottom: 6px;
126
- }
127
-
128
- .panel-subtitle {
129
- color: #6b7280;
130
- font-size: 0.9em;
131
- }
132
-
133
- /* ===== INPUT PANEL CONTROLS ===== */
134
- textarea {
135
- flex: 1; /* Takes all available vertical space */
136
- font-size: 15px;
137
- padding: 16px;
138
- border: 2px solid #e5e7eb;
139
- border-radius: 12px;
140
- resize: none;
141
- transition: all 0.3s ease;
142
- font-family: inherit;
143
- line-height: 1.6;
144
- background: #fafafa;
145
- overflow-y: auto;
146
- }
147
-
148
- textarea:focus {
149
- outline: none;
150
- border-color: #6366f1;
151
- box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);
152
- background: white;
153
- }
154
-
155
- textarea::placeholder {
156
- color: #9ca3af;
157
- }
158
-
159
- /* ===== BUTTON STYLES ===== */
160
- button {
161
- background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);
162
- color: white;
163
- padding: 14px 28px;
164
- font-size: 15px;
165
- font-weight: 600;
166
- border: none;
167
- border-radius: 12px;
168
- cursor: pointer;
169
- transition: all 0.3s ease;
170
- box-shadow: 0 4px 15px rgba(99, 102, 241, 0.3);
171
- }
172
-
173
- button:hover {
174
- transform: translateY(-2px);
175
- box-shadow: 0 8px 25px rgba(99, 102, 241, 0.4);
176
- }
177
-
178
- button:active {
179
- transform: translateY(0);
180
- }
181
-
182
- .copy-button {
183
- background: linear-gradient(135deg, #10b981 0%, #059669 100%);
184
- box-shadow: 0 4px 15px rgba(16, 185, 129, 0.3);
185
- margin-top: 0;
186
- flex-shrink: 0;
187
- width: 100%;
188
- }
189
-
190
- .copy-button:hover {
191
- box-shadow: 0 8px 25px rgba(16, 185, 129, 0.4);
192
- }
193
-
194
- .copy-button.copied {
195
- background: linear-gradient(135deg, #22c55e 0%, #16a34a 100%);
196
- }
197
-
198
- .detector-button {
199
- background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
200
- box-shadow: 0 4px 15px rgba(245, 158, 11, 0.3);
201
- margin-top: 8px;
202
- flex-shrink: 0;
203
- width: 100%;
204
- }
205
-
206
- .detector-button:hover {
207
- box-shadow: 0 8px 25px rgba(245, 158, 11, 0.4);
208
- }
209
-
210
- /* ===== OUTPUT CONTENT (scrollable) ===== */
211
- .output-content {
212
- flex: 1; /* Fill vertical space between header and bottom button */
213
- padding: 16px;
214
- background: #f8fafc;
215
- border: 2px solid #e2e8f0;
216
- border-radius: 12px;
217
- font-size: 15px;
218
- line-height: 1.7;
219
- white-space: pre-wrap;
220
- overflow-y: auto; /* Only this area scrolls */
221
- color: #334155;
222
- }
223
-
224
- /* ===== BOTTOM BUTTON CONTAINER (flexible height) ===== */
225
- .panel-bottom {
226
- margin-top: 16px;
227
- display: flex;
228
- flex-direction: column;
229
- gap: 8px;
230
- }
231
-
232
- /* ===== AI DETECTOR TABLE STYLES ===== */
233
- .detector-results {
234
- margin-top: 20px;
235
- padding: 16px;
236
- background: #ffffff;
237
- border: 2px solid #e2e8f0;
238
- border-radius: 12px;
239
- }
240
-
241
- .detector-table-title {
242
- font-size: 1.1em;
243
- font-weight: 600;
244
- color: #374151;
245
- margin-bottom: 12px;
246
- text-align: center;
247
- }
248
-
249
- .detector-table {
250
- width: 100%;
251
- border-collapse: collapse;
252
- font-size: 14px;
253
- }
254
-
255
- .detector-table th {
256
- background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);
257
- color: white;
258
- padding: 12px 8px;
259
- text-align: left;
260
- font-weight: 600;
261
- border-radius: 8px 8px 0 0;
262
- }
263
-
264
- .detector-table th:first-child {
265
- border-radius: 8px 0 0 0;
266
- }
267
-
268
- .detector-table th:last-child {
269
- border-radius: 0 8px 0 0;
270
- }
271
-
272
- .detector-table td {
273
- padding: 10px 8px;
274
- border-bottom: 1px solid #e5e7eb;
275
- }
276
-
277
- .detector-table tr:nth-child(even) {
278
- background-color: #f8fafc;
279
- }
280
-
281
- .detector-table tr:hover {
282
- background-color: #f1f5f9;
283
- }
284
-
285
- .ai-percentage {
286
- font-weight: 600;
287
- color: #ef4444;
288
- }
289
-
290
- .ai-percentage.low {
291
- color: #10b981;
292
- }
293
-
294
- .ai-percentage.medium {
295
- color: #f59e0b;
296
- }
297
-
298
- .ai-percentage.high {
299
- color: #ef4444;
300
- }
301
-
302
- /* ===== LOADING & ERROR STATES ===== */
303
- .loading {
304
- color: #64748b;
305
- font-style: italic;
306
- text-align: center;
307
- padding: 40px 20px;
308
- display: flex;
309
- align-items: center;
310
- justify-content: center;
311
- gap: 8px;
312
- }
313
-
314
- .loading::before {
315
- content: "✨";
316
- animation: pulse 1.5s infinite;
317
- }
318
-
319
- .detector-loading {
320
- color: #64748b;
321
- font-style: italic;
322
- text-align: center;
323
- padding: 20px;
324
- display: flex;
325
- align-items: center;
326
- justify-content: center;
327
- gap: 8px;
328
- }
329
-
330
- .detector-loading::before {
331
- content: "πŸ”";
332
- animation: pulse 1.5s infinite;
333
- }
334
-
335
- @keyframes pulse {
336
- 0%, 100% {
337
- opacity: 1;
338
- }
339
- 50% {
340
- opacity: 0.5;
341
- }
342
- }
343
-
344
- .error {
345
- color: #ef4444;
346
- font-weight: 500;
347
- text-align: center;
348
- padding: 24px 16px;
349
- background: rgba(239, 68, 68, 0.05);
350
- border-radius: 8px;
351
- }
352
-
353
- /* ===== CUSTOM SCROLLBAR for output ===== */
354
- .output-content::-webkit-scrollbar {
355
- width: 6px;
356
- }
357
- .output-content::-webkit-scrollbar-track {
358
- background: #f1f5f9;
359
- border-radius: 3px;
360
- }
361
- .output-content::-webkit-scrollbar-thumb {
362
- background: #cbd5e1;
363
- border-radius: 3px;
364
- }
365
- .output-content::-webkit-scrollbar-thumb:hover {
366
- background: #94a3b8;
367
- }
368
- </style>
369
- </head>
370
- <body>
371
- <div class="container">
372
- <!-- ===== HEADER ===== -->
373
- <div class="header">
374
- <h1>🌟 AI Text Humanizer</h1>
375
- <p class="description">Transform AI text into natural, human-like language</p>
376
- </div>
377
-
378
- <!-- ===== MAIN PANELS ===== -->
379
- <div class="main-content">
380
- <!-- ==================== INPUT PANEL ==================== -->
381
- <div class="panel input-panel">
382
- <div class="panel-header">
383
- <div class="panel-title">πŸ“ Input Text</div>
384
- <div class="panel-subtitle">Paste your AI-generated content here</div>
385
- </div>
386
-
387
- <!-- Removed the "Select Tone / Audience" dropdown entirely -->
388
- <textarea
389
- id="inputText"
390
- placeholder="Paste your AI-generated text here and watch the magic happen..."
391
- ></textarea>
392
-
393
- <div class="panel-bottom">
394
- <!-- "Humanize Text" button, pinned to bottom of input panel -->
395
- <button type="button" onclick="humanize()">πŸš€ Humanize Text</button>
396
- </div>
397
- </div>
398
-
399
- <!-- ==================== OUTPUT PANEL ==================== -->
400
- <div class="panel output-panel">
401
- <div class="panel-header">
402
- <div class="panel-title">✨ Humanized Result</div>
403
- <div class="panel-subtitle">Your transformed, natural text</div>
404
- </div>
405
-
406
- <!-- #result holds loading / error / final text; scrollable -->
407
- <div id="result" class="output-content">
408
- <div class="loading">Your humanized text will appear here...</div>
409
-
410
- <!-- AI Detector Results will be appended here -->
411
- <div id="detectorResults" style="display: none;"></div>
412
- </div>
413
-
414
- <div class="panel-bottom">
415
- <!-- Copy button hidden until text arrives -->
416
- <button
417
- id="copyBtn"
418
- type="button"
419
- class="copy-button"
420
- style="display: none;"
421
- onclick="copyText()"
422
- >
423
- πŸ“‹ Copy Text
424
- </button>
425
-
426
- <!-- AI Detector button hidden until text arrives -->
427
- <button
428
- id="detectorBtn"
429
- type="button"
430
- class="detector-button"
431
- style="display: none;"
432
- onclick="runDetector()"
433
- >
434
- πŸ” AI Detector Results
435
- </button>
436
- </div>
437
- </div>
438
- </div>
439
- </div>
440
-
441
- <!-- ===== JAVASCRIPT ===== -->
442
- <script>
443
- let currentHumanizedText = '';
444
-
445
- async function humanize() {
446
- const textArea = document.getElementById("inputText");
447
- const outputDiv = document.getElementById("result");
448
- const copyBtn = document.getElementById("copyBtn");
449
- const detectorBtn = document.getElementById("detectorBtn");
450
- const detectorResults = document.getElementById("detectorResults");
451
-
452
- const text = textArea.value.trim();
453
-
454
- if (!text) {
455
- alert("Please enter some text first!");
456
- return;
457
- }
458
-
459
- // Show "loading" inside outputDiv
460
- outputDiv.innerHTML = "";
461
- const spinner = document.createElement("div");
462
- spinner.className = "loading";
463
- spinner.textContent = "Processing your text...";
464
- outputDiv.appendChild(spinner);
465
-
466
- // Hide buttons and detector results until we have a successful response
467
- copyBtn.style.display = "none";
468
- detectorBtn.style.display = "none";
469
- detectorResults.style.display = "none";
470
-
471
- try {
472
- const response = await fetch("/humanize", {
473
- method: "POST",
474
- headers: {
475
- "Content-Type": "application/json",
476
- },
477
- // Now we only send { text }, since we dropped "audience"
478
- body: JSON.stringify({ text }),
479
- });
480
-
481
- if (!response.ok) {
482
- throw new Error(`Server responded with status ${response.status}`);
483
- }
484
-
485
- const data = await response.json();
486
-
487
- // Store the humanized text for detector
488
- currentHumanizedText = data.humanized;
489
-
490
- // Replace spinner with the actual humanized text
491
- outputDiv.innerHTML = "";
492
- const textNode = document.createTextNode(data.humanized);
493
- outputDiv.appendChild(textNode);
494
-
495
- // Show buttons
496
- copyBtn.style.display = "block";
497
- detectorBtn.style.display = "block";
498
- } catch (error) {
499
- outputDiv.innerHTML = "";
500
- const errDiv = document.createElement("div");
501
- errDiv.className = "error";
502
- errDiv.textContent = `❌ Error: ${error.message}`;
503
- outputDiv.appendChild(errDiv);
504
- console.error("Error:", error);
505
- }
506
- }
507
-
508
- async function runDetector() {
509
- console.log("111111111111");
510
- if (!currentHumanizedText) {
511
- alert("No humanized text available for detection!");
512
- return;
513
- }
514
- console.log("22222222222");
515
-
516
- const detectorResults = document.getElementById("detectorResult");
517
- const detectorBtn = document.getElementById("detectorBtn");
518
-
519
- // Show loading state
520
- detectorResults.innerHTML = "";
521
- const spinner = document.createElement("div");
522
- spinner.className = "detector-loading";
523
- spinner.textContent = "Running AI detection...";
524
- detectorResults.appendChild(spinner);
525
- detectorResults.style.display = "block";
526
-
527
- // Disable button during processing
528
- detectorBtn.disabled = true;
529
- detectorBtn.textContent = "πŸ” Analyzing...";
530
- console.log("333333333333");
531
-
532
- try {
533
- const response = await fetch("/detect", {
534
- method: "POST",
535
- headers: {
536
- "Content-Type": "application/json",
537
- },
538
- body: JSON.stringify({ text: currentHumanizedText }),
539
- });
540
- console.log("4444444444");
541
-
542
- if (!response.ok) {
543
- throw new Error(`Server responded with status ${response.status}`);
544
- }
545
- console.log("555555555");
546
-
547
- const data = await response.json();
548
- console.log("66666666");
549
- console.log("data: " + data)
550
-
551
- // Create the detector results table
552
- detectorResults.innerHTML = `
553
- <div class="detector-results">
554
- <div class="detector-table-title">πŸ” AI Detector Tool Results</div>
555
- <table class="detector-table">
556
- <thead>
557
- <tr>
558
- <th>AI Detector Tool</th>
559
- <th>AI Probability</th>
560
- </tr>
561
- </thead>
562
- <tbody>
563
- ${data.results.map(result => {
564
- const percentage = Math.round(result.ai_probability * 100);
565
- let colorClass = 'high';
566
- if (percentage < 30) colorClass = 'low';
567
- else if (percentage < 70) colorClass = 'medium';
568
-
569
- return `
570
- <tr>
571
- <td>${result.detector_name}</td>
572
- <td class="ai-percentage ${colorClass}">${percentage}% AI written</td>
573
- </tr>
574
- `;
575
- }).join('')}
576
- </tbody>
577
- </table>
578
- </div>
579
- `;
580
-
581
- } catch (error) {
582
- detectorResults.innerHTML = "";
583
- const errDiv = document.createElement("div");
584
- errDiv.className = "error";
585
- errDiv.textContent = `❌ Detection Error: ${error.message}`;
586
- detectorResults.appendChild(errDiv);
587
- console.error("Detection Error:", error);
588
- } finally {
589
- // Re-enable button
590
- detectorBtn.disabled = false;
591
- detectorBtn.textContent = "πŸ” AI Detector Results";
592
- }
593
- }
594
-
595
- async function copyText() {
596
- const outputDiv = document.getElementById("result");
597
- const copyBtn = document.getElementById("copyBtn");
598
- const textToCopy = currentHumanizedText || outputDiv.textContent || outputDiv.innerText;
599
-
600
- try {
601
- await navigator.clipboard.writeText(textToCopy);
602
-
603
- // Instant feedback on the button
604
- const original = copyBtn.innerHTML;
605
- copyBtn.innerHTML = "βœ… Copied!";
606
- copyBtn.classList.add("copied");
607
- setTimeout(() => {
608
- copyBtn.innerHTML = original;
609
- copyBtn.classList.remove("copied");
610
- }, 2000);
611
- } catch {
612
- // Fallback for older browsers
613
- const tmp = document.createElement("textarea");
614
- tmp.value = textToCopy;
615
- document.body.appendChild(tmp);
616
- tmp.select();
617
- document.execCommand("copy");
618
- document.body.removeChild(tmp);
619
-
620
- copyBtn.innerHTML = "βœ… Copied!";
621
- setTimeout(() => {
622
- copyBtn.innerHTML = "πŸ“‹ Copy Text";
623
- }, 2000);
624
- }
625
- }
626
-
627
- // Ctrl+Enter = humanize
628
- document.addEventListener("keydown", (e) => {
629
- if (e.ctrlKey && e.key === "Enter") {
630
- humanize();
631
- }
632
- });
633
-
634
- // Auto-resize the input textarea as you type
635
- document.getElementById("inputText").addEventListener("input", function () {
636
- this.style.height = "auto";
637
- this.style.height = this.scrollHeight + "px";
638
- });
639
- </script>
640
- </body>
641
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/static/index copy.html CHANGED
@@ -18,11 +18,12 @@
18
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
19
  background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 50%, #ec4899 100%);
20
  color: #1f2937;
21
- overflow: hidden; /* Prevent full-page scrolling */
 
22
  }
23
 
24
  .container {
25
- height: 100%;
26
  max-width: 1400px;
27
  margin: 0 auto;
28
  display: flex;
@@ -55,11 +56,11 @@
55
 
56
  /* ===== MAIN GRID (Input + Output Panels) ===== */
57
  .main-content {
58
- flex: 1;
59
  display: grid;
60
  grid-template-columns: 1fr 1fr;
61
  gap: 24px;
62
- height: calc(100% - 64px); /* Subtract header’s height */
 
63
  }
64
 
65
  @media (max-width: 1200px) {
@@ -195,6 +196,26 @@
195
  background: linear-gradient(135deg, #22c55e 0%, #16a34a 100%);
196
  }
197
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
198
  /* ===== OUTPUT CONTENT (scrollable) ===== */
199
  .output-content {
200
  flex: 1; /* Fill vertical space between header and bottom button */
@@ -207,14 +228,109 @@
207
  white-space: pre-wrap;
208
  overflow-y: auto; /* Only this area scrolls */
209
  color: #334155;
 
 
210
  }
211
 
212
- /* ===== BOTTOM BUTTON CONTAINER (fixed height) ===== */
213
  .panel-bottom {
214
  margin-top: 16px;
215
- height: 48px; /* Same in both panels β†’ Y-coordinate alignment */
216
  display: flex;
217
- align-items: center;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
218
  }
219
 
220
  /* ===== LOADING & ERROR STATES ===== */
@@ -234,6 +350,22 @@
234
  animation: pulse 1.5s infinite;
235
  }
236
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
237
  @keyframes pulse {
238
  0%, 100% {
239
  opacity: 1;
@@ -254,23 +386,40 @@
254
 
255
  /* ===== CUSTOM SCROLLBAR for output ===== */
256
  .output-content::-webkit-scrollbar {
257
- width: 6px;
258
  }
259
  .output-content::-webkit-scrollbar-track {
260
  background: #f1f5f9;
261
- border-radius: 3px;
262
  }
263
  .output-content::-webkit-scrollbar-thumb {
264
  background: #cbd5e1;
265
- border-radius: 3px;
266
  }
267
  .output-content::-webkit-scrollbar-thumb:hover {
268
  background: #94a3b8;
269
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
270
  </style>
271
  </head>
272
  <body>
273
  <div class="container">
 
 
 
274
  <!-- ===== HEADER ===== -->
275
  <div class="header">
276
  <h1>🌟 AI Text Humanizer</h1>
@@ -286,14 +435,12 @@
286
  <div class="panel-subtitle">Paste your AI-generated content here</div>
287
  </div>
288
 
289
- <!-- Removed the β€œSelect Tone / Audience” dropdown entirely -->
290
  <textarea
291
  id="inputText"
292
  placeholder="Paste your AI-generated text here and watch the magic happen..."
293
  ></textarea>
294
 
295
  <div class="panel-bottom">
296
- <!-- β€œHumanize Text” button, pinned to bottom of input panel -->
297
  <button type="button" onclick="humanize()">πŸš€ Humanize Text</button>
298
  </div>
299
  </div>
@@ -305,9 +452,11 @@
305
  <div class="panel-subtitle">Your transformed, natural text</div>
306
  </div>
307
 
308
- <!-- #result holds loading / error / final text; scrollable -->
309
- <div id="result" class="output-content">
310
- <div class="loading">Your humanized text will appear here...</div>
 
 
311
  </div>
312
 
313
  <div class="panel-bottom">
@@ -321,17 +470,61 @@
321
  >
322
  πŸ“‹ Copy Text
323
  </button>
 
 
 
 
 
 
 
 
 
 
 
324
  </div>
325
  </div>
326
  </div>
 
 
 
 
 
 
 
 
 
327
  </div>
328
 
329
  <!-- ===== JAVASCRIPT ===== -->
330
  <script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
331
  async function humanize() {
332
  const textArea = document.getElementById("inputText");
333
  const outputDiv = document.getElementById("result");
334
  const copyBtn = document.getElementById("copyBtn");
 
335
 
336
  const text = textArea.value.trim();
337
 
@@ -340,38 +533,58 @@
340
  return;
341
  }
342
 
343
- // Show β€œloading” inside outputDiv
344
- outputDiv.textContent = "";
 
 
 
 
345
  const spinner = document.createElement("div");
346
  spinner.className = "loading";
347
  spinner.textContent = "Processing your text...";
348
  outputDiv.appendChild(spinner);
349
 
350
- // Hide copy button until we have a successful response
351
  copyBtn.style.display = "none";
 
352
 
353
  try {
 
 
354
  const response = await fetch("/humanize", {
355
  method: "POST",
356
  headers: {
357
  "Content-Type": "application/json",
358
  },
359
- // Now we only send { text }, since we dropped β€œaudience”
360
  body: JSON.stringify({ text }),
361
  });
362
 
 
 
363
  if (!response.ok) {
364
  throw new Error(`Server responded with status ${response.status}`);
365
  }
366
 
367
  const data = await response.json();
 
 
 
 
368
 
369
  // Replace spinner with the actual humanized text
370
- outputDiv.textContent = data.humanized;
371
- // Show copy button
 
 
 
372
  copyBtn.style.display = "block";
 
 
 
373
  } catch (error) {
374
- outputDiv.textContent = "";
 
 
375
  const errDiv = document.createElement("div");
376
  errDiv.className = "error";
377
  errDiv.textContent = `❌ Error: ${error.message}`;
@@ -380,10 +593,113 @@
380
  }
381
  }
382
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
383
  async function copyText() {
384
- const outputDiv = document.getElementById("result");
385
  const copyBtn = document.getElementById("copyBtn");
386
- const textToCopy = outputDiv.textContent || outputDiv.innerText;
 
 
 
 
 
387
 
388
  try {
389
  await navigator.clipboard.writeText(textToCopy);
@@ -426,4 +742,4 @@
426
  });
427
  </script>
428
  </body>
429
- </html>
 
18
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
19
  background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 50%, #ec4899 100%);
20
  color: #1f2937;
21
+ overflow-y: auto; /* Allow page scrolling */
22
+ min-height: 100vh;
23
  }
24
 
25
  .container {
26
+ min-height: 100vh;
27
  max-width: 1400px;
28
  margin: 0 auto;
29
  display: flex;
 
56
 
57
  /* ===== MAIN GRID (Input + Output Panels) ===== */
58
  .main-content {
 
59
  display: grid;
60
  grid-template-columns: 1fr 1fr;
61
  gap: 24px;
62
+ min-height: 70vh; /* Fixed height for the main panels */
63
+ margin-bottom: 24px;
64
  }
65
 
66
  @media (max-width: 1200px) {
 
196
  background: linear-gradient(135deg, #22c55e 0%, #16a34a 100%);
197
  }
198
 
199
+ .detector-button {
200
+ background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
201
+ box-shadow: 0 4px 15px rgba(245, 158, 11, 0.3);
202
+ margin-top: 8px;
203
+ flex-shrink: 0;
204
+ width: 100%;
205
+ }
206
+
207
+ .detector-button:hover {
208
+ box-shadow: 0 8px 25px rgba(245, 158, 11, 0.4);
209
+ }
210
+
211
+ /* ===== OUTPUT CONTENT CONTAINER ===== */
212
+ .output-container {
213
+ display: flex;
214
+ flex-direction: column;
215
+ height: 400px; /* Fixed height for the container */
216
+ overflow: hidden; /* Prevent container from expanding */
217
+ }
218
+
219
  /* ===== OUTPUT CONTENT (scrollable) ===== */
220
  .output-content {
221
  flex: 1; /* Fill vertical space between header and bottom button */
 
228
  white-space: pre-wrap;
229
  overflow-y: auto; /* Only this area scrolls */
230
  color: #334155;
231
+ height: 400px; /* Fixed height instead of min-height */
232
+ max-height: 400px; /* Prevent expansion */
233
  }
234
 
235
+ /* ===== BOTTOM BUTTON CONTAINER (flexible height) ===== */
236
  .panel-bottom {
237
  margin-top: 16px;
 
238
  display: flex;
239
+ flex-direction: column;
240
+ gap: 8px;
241
+ flex-shrink: 0; /* Prevent buttons from shrinking */
242
+ }
243
+
244
+ /* ===== AI DETECTOR SECTION STYLES ===== */
245
+ .detector-section {
246
+ display: none; /* Hidden by default */
247
+ background: rgba(255, 255, 255, 0.95);
248
+ backdrop-filter: blur(20px);
249
+ border-radius: 20px;
250
+ box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
251
+ border: 1px solid rgba(255, 255, 255, 0.2);
252
+ padding: 24px;
253
+ margin-bottom: 24px;
254
+ animation: slideIn 0.5s ease-out;
255
+ }
256
+
257
+ @keyframes slideIn {
258
+ from {
259
+ opacity: 0;
260
+ transform: translateY(20px);
261
+ }
262
+ to {
263
+ opacity: 1;
264
+ transform: translateY(0);
265
+ }
266
+ }
267
+
268
+ .detector-results {
269
+ padding: 16px;
270
+ background: #ffffff;
271
+ border: 2px solid #e2e8f0;
272
+ border-radius: 12px;
273
+ }
274
+
275
+ .detector-table-title {
276
+ font-size: 1.1em;
277
+ font-weight: 600;
278
+ color: #374151;
279
+ margin-bottom: 12px;
280
+ text-align: center;
281
+ }
282
+
283
+ .detector-table {
284
+ width: 100%;
285
+ border-collapse: collapse;
286
+ font-size: 14px;
287
+ }
288
+
289
+ .detector-table th {
290
+ background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);
291
+ color: white;
292
+ padding: 12px 8px;
293
+ text-align: left;
294
+ font-weight: 600;
295
+ border-radius: 8px 8px 0 0;
296
+ }
297
+
298
+ .detector-table th:first-child {
299
+ border-radius: 8px 0 0 0;
300
+ }
301
+
302
+ .detector-table th:last-child {
303
+ border-radius: 0 8px 0 0;
304
+ }
305
+
306
+ .detector-table td {
307
+ padding: 10px 8px;
308
+ border-bottom: 1px solid #e5e7eb;
309
+ }
310
+
311
+ .detector-table tr:nth-child(even) {
312
+ background-color: #f8fafc;
313
+ }
314
+
315
+ .detector-table tr:hover {
316
+ background-color: #f1f5f9;
317
+ }
318
+
319
+ .ai-percentage {
320
+ font-weight: 600;
321
+ color: #ef4444;
322
+ }
323
+
324
+ .ai-percentage.low {
325
+ color: #10b981;
326
+ }
327
+
328
+ .ai-percentage.medium {
329
+ color: #f59e0b;
330
+ }
331
+
332
+ .ai-percentage.high {
333
+ color: #ef4444;
334
  }
335
 
336
  /* ===== LOADING & ERROR STATES ===== */
 
350
  animation: pulse 1.5s infinite;
351
  }
352
 
353
+ .detector-loading {
354
+ color: #64748b;
355
+ font-style: italic;
356
+ text-align: center;
357
+ padding: 20px;
358
+ display: flex;
359
+ align-items: center;
360
+ justify-content: center;
361
+ gap: 8px;
362
+ }
363
+
364
+ .detector-loading::before {
365
+ content: "πŸ”";
366
+ animation: pulse 1.5s infinite;
367
+ }
368
+
369
  @keyframes pulse {
370
  0%, 100% {
371
  opacity: 1;
 
386
 
387
  /* ===== CUSTOM SCROLLBAR for output ===== */
388
  .output-content::-webkit-scrollbar {
389
+ width: 8px;
390
  }
391
  .output-content::-webkit-scrollbar-track {
392
  background: #f1f5f9;
393
+ border-radius: 4px;
394
  }
395
  .output-content::-webkit-scrollbar-thumb {
396
  background: #cbd5e1;
397
+ border-radius: 4px;
398
  }
399
  .output-content::-webkit-scrollbar-thumb:hover {
400
  background: #94a3b8;
401
  }
402
+
403
+ /* ===== DEBUG STYLES (temporary - remove in production) ===== */
404
+ .debug-info {
405
+ position: fixed;
406
+ top: 10px;
407
+ right: 10px;
408
+ background: rgba(0, 0, 0, 0.8);
409
+ color: white;
410
+ padding: 10px;
411
+ border-radius: 5px;
412
+ font-size: 12px;
413
+ z-index: 1000;
414
+ display: none; /* Hidden by default */
415
+ }
416
  </style>
417
  </head>
418
  <body>
419
  <div class="container">
420
+ <!-- Debug info (remove in production) -->
421
+ <div id="debugInfo" class="debug-info"></div>
422
+
423
  <!-- ===== HEADER ===== -->
424
  <div class="header">
425
  <h1>🌟 AI Text Humanizer</h1>
 
435
  <div class="panel-subtitle">Paste your AI-generated content here</div>
436
  </div>
437
 
 
438
  <textarea
439
  id="inputText"
440
  placeholder="Paste your AI-generated text here and watch the magic happen..."
441
  ></textarea>
442
 
443
  <div class="panel-bottom">
 
444
  <button type="button" onclick="humanize()">πŸš€ Humanize Text</button>
445
  </div>
446
  </div>
 
452
  <div class="panel-subtitle">Your transformed, natural text</div>
453
  </div>
454
 
455
+ <div class="output-container">
456
+ <!-- #result holds loading / error / final text; scrollable -->
457
+ <div id="result" class="output-content">
458
+ <div class="loading">Your humanized text will appear here...</div>
459
+ </div>
460
  </div>
461
 
462
  <div class="panel-bottom">
 
470
  >
471
  πŸ“‹ Copy Text
472
  </button>
473
+
474
+ <!-- AI Detector button hidden until text arrives -->
475
+ <button
476
+ id="detectorBtn"
477
+ type="button"
478
+ class="detector-button"
479
+ style="display: none;"
480
+ onclick="runDetector()"
481
+ >
482
+ πŸ” AI Detector Results
483
+ </button>
484
  </div>
485
  </div>
486
  </div>
487
+
488
+ <!-- ===== AI DETECTOR SECTION (appears at bottom) ===== -->
489
+ <div id="detectorSection" class="detector-section">
490
+ <div class="panel-header">
491
+ <div class="panel-title">πŸ” AI Detector Analysis</div>
492
+ <div class="panel-subtitle">Detailed analysis of your humanized text</div>
493
+ </div>
494
+ <div id="detectorResults"></div>
495
+ </div>
496
  </div>
497
 
498
  <!-- ===== JAVASCRIPT ===== -->
499
  <script>
500
+ let currentHumanizedText = '';
501
+ let debugMode = false; // Set to true for debugging
502
+
503
+ // Debug function
504
+ function updateDebugInfo(message) {
505
+ if (!debugMode) return;
506
+ const debugEl = document.getElementById('debugInfo');
507
+ debugEl.textContent = message;
508
+ debugEl.style.display = 'block';
509
+ console.log('DEBUG:', message);
510
+ }
511
+
512
+ // Toggle debug mode with Ctrl+D
513
+ document.addEventListener('keydown', (e) => {
514
+ if (e.ctrlKey && e.key === 'd') {
515
+ e.preventDefault();
516
+ debugMode = !debugMode;
517
+ const debugEl = document.getElementById('debugInfo');
518
+ debugEl.style.display = debugMode ? 'block' : 'none';
519
+ updateDebugInfo('Debug mode: ' + (debugMode ? 'ON' : 'OFF'));
520
+ }
521
+ });
522
+
523
  async function humanize() {
524
  const textArea = document.getElementById("inputText");
525
  const outputDiv = document.getElementById("result");
526
  const copyBtn = document.getElementById("copyBtn");
527
+ const detectorBtn = document.getElementById("detectorBtn");
528
 
529
  const text = textArea.value.trim();
530
 
 
533
  return;
534
  }
535
 
536
+ updateDebugInfo('Starting humanize process...');
537
+
538
+ // Clear previous results completely
539
+ outputDiv.innerHTML = "";
540
+
541
+ // Show loading spinner
542
  const spinner = document.createElement("div");
543
  spinner.className = "loading";
544
  spinner.textContent = "Processing your text...";
545
  outputDiv.appendChild(spinner);
546
 
547
+ // Hide buttons until we have a successful response
548
  copyBtn.style.display = "none";
549
+ detectorBtn.style.display = "none";
550
 
551
  try {
552
+ updateDebugInfo('Sending request to /humanize...');
553
+
554
  const response = await fetch("/humanize", {
555
  method: "POST",
556
  headers: {
557
  "Content-Type": "application/json",
558
  },
 
559
  body: JSON.stringify({ text }),
560
  });
561
 
562
+ updateDebugInfo(`Response status: ${response.status}`);
563
+
564
  if (!response.ok) {
565
  throw new Error(`Server responded with status ${response.status}`);
566
  }
567
 
568
  const data = await response.json();
569
+ updateDebugInfo('Received humanized text, length: ' + data.humanized.length);
570
+
571
+ // Store the humanized text for detector
572
+ currentHumanizedText = data.humanized;
573
 
574
  // Replace spinner with the actual humanized text
575
+ outputDiv.innerHTML = "";
576
+ const textNode = document.createTextNode(data.humanized);
577
+ outputDiv.appendChild(textNode);
578
+
579
+ // Show buttons
580
  copyBtn.style.display = "block";
581
+ detectorBtn.style.display = "block";
582
+
583
+ updateDebugInfo('Humanize completed successfully');
584
  } catch (error) {
585
+ updateDebugInfo('Error in humanize: ' + error.message);
586
+
587
+ outputDiv.innerHTML = "";
588
  const errDiv = document.createElement("div");
589
  errDiv.className = "error";
590
  errDiv.textContent = `❌ Error: ${error.message}`;
 
593
  }
594
  }
595
 
596
+ async function runDetector() {
597
+ if (!currentHumanizedText) {
598
+ alert("No humanized text available for detection!");
599
+ return;
600
+ }
601
+
602
+ updateDebugInfo('Starting detector process...');
603
+
604
+ const detectorSection = document.getElementById("detectorSection");
605
+ const detectorResults = document.getElementById("detectorResults");
606
+ const detectorBtn = document.getElementById("detectorBtn");
607
+
608
+ // Show the detector section and scroll to it
609
+ detectorSection.style.display = "block";
610
+ setTimeout(() => {
611
+ detectorSection.scrollIntoView({ behavior: 'smooth', block: 'start' });
612
+ }, 100);
613
+
614
+ // Show loading state in the detector results area
615
+ detectorResults.innerHTML = "";
616
+ const spinner = document.createElement("div");
617
+ spinner.className = "detector-loading";
618
+ spinner.textContent = "Running AI detection...";
619
+ detectorResults.appendChild(spinner);
620
+
621
+ // Disable button during processing
622
+ detectorBtn.disabled = true;
623
+ detectorBtn.textContent = "πŸ” Analyzing...";
624
+
625
+ try {
626
+ updateDebugInfo('Sending request to /detect...');
627
+
628
+ const response = await fetch("/detect", {
629
+ method: "POST",
630
+ headers: {
631
+ "Content-Type": "application/json",
632
+ },
633
+ body: JSON.stringify({ text: currentHumanizedText }),
634
+ });
635
+
636
+ updateDebugInfo(`Detect response status: ${response.status}`);
637
+
638
+ if (!response.ok) {
639
+ throw new Error(`Server responded with status ${response.status}`);
640
+ }
641
+
642
+ const data = await response.json();
643
+ updateDebugInfo('Received detector results, count: ' + data.results.length);
644
+
645
+ // Create the detector results table
646
+ detectorResults.innerHTML = `
647
+ <div class="detector-results">
648
+ <div class="detector-table-title">πŸ” AI Detector Tool Results</div>
649
+ <table class="detector-table">
650
+ <thead>
651
+ <tr>
652
+ <th>AI Detector Tool</th>
653
+ <th>AI Probability</th>
654
+ </tr>
655
+ </thead>
656
+ <tbody>
657
+ ${data.results.map(result => {
658
+ const percentage = Math.round(result.ai_probability * 100);
659
+ let colorClass = 'high';
660
+ if (percentage < 30) colorClass = 'low';
661
+ else if (percentage < 70) colorClass = 'medium';
662
+
663
+ return `
664
+ <tr>
665
+ <td>${result.detector_name}</td>
666
+ <td class="ai-percentage ${colorClass}">${percentage}% AI written</td>
667
+ </tr>
668
+ `;
669
+ }).join('')}
670
+ </tbody>
671
+ </table>
672
+ </div>
673
+ `;
674
+
675
+ updateDebugInfo('Detector results displayed successfully');
676
+
677
+ } catch (error) {
678
+ updateDebugInfo('Error in detector: ' + error.message);
679
+
680
+ // Add error message
681
+ detectorResults.innerHTML = "";
682
+ const errDiv = document.createElement("div");
683
+ errDiv.className = "error";
684
+ errDiv.textContent = `❌ Detection Error: ${error.message}`;
685
+ detectorResults.appendChild(errDiv);
686
+
687
+ console.error("Detection Error:", error);
688
+ } finally {
689
+ // Re-enable button
690
+ detectorBtn.disabled = false;
691
+ detectorBtn.textContent = "πŸ” AI Detector Results";
692
+ }
693
+ }
694
+
695
  async function copyText() {
 
696
  const copyBtn = document.getElementById("copyBtn");
697
+ const textToCopy = currentHumanizedText;
698
+
699
+ if (!textToCopy) {
700
+ alert("No text to copy!");
701
+ return;
702
+ }
703
 
704
  try {
705
  await navigator.clipboard.writeText(textToCopy);
 
742
  });
743
  </script>
744
  </body>
745
+ </html>
app/static/index.html CHANGED
@@ -161,19 +161,20 @@
161
  button {
162
  background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);
163
  color: white;
164
- padding: 14px 28px;
165
- font-size: 15px;
166
  font-weight: 600;
167
  border: none;
168
- border-radius: 12px;
169
  cursor: pointer;
170
  transition: all 0.3s ease;
171
- box-shadow: 0 4px 15px rgba(99, 102, 241, 0.3);
 
172
  }
173
 
174
  button:hover {
175
- transform: translateY(-2px);
176
- box-shadow: 0 8px 25px rgba(99, 102, 241, 0.4);
177
  }
178
 
179
  button:active {
@@ -182,14 +183,15 @@
182
 
183
  .copy-button {
184
  background: linear-gradient(135deg, #10b981 0%, #059669 100%);
185
- box-shadow: 0 4px 15px rgba(16, 185, 129, 0.3);
186
  margin-top: 0;
187
  flex-shrink: 0;
188
  width: 100%;
 
189
  }
190
 
191
  .copy-button:hover {
192
- box-shadow: 0 8px 25px rgba(16, 185, 129, 0.4);
193
  }
194
 
195
  .copy-button.copied {
@@ -198,14 +200,85 @@
198
 
199
  .detector-button {
200
  background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
201
- box-shadow: 0 4px 15px rgba(245, 158, 11, 0.3);
202
  margin-top: 8px;
203
  flex-shrink: 0;
204
  width: 100%;
 
205
  }
206
 
207
  .detector-button:hover {
208
- box-shadow: 0 8px 25px rgba(245, 158, 11, 0.4);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
209
  }
210
 
211
  /* ===== OUTPUT CONTENT CONTAINER ===== */
@@ -432,7 +505,7 @@
432
  <div class="panel input-panel">
433
  <div class="panel-header">
434
  <div class="panel-title">πŸ“ Input Text</div>
435
- <div class="panel-subtitle">Paste your AI-generated content here</div>
436
  </div>
437
 
438
  <textarea
@@ -441,7 +514,21 @@
441
  ></textarea>
442
 
443
  <div class="panel-bottom">
444
- <button type="button" onclick="humanize()">πŸš€ Humanize Text</button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
445
  </div>
446
  </div>
447
 
@@ -520,11 +607,96 @@
520
  }
521
  });
522
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
523
  async function humanize() {
524
  const textArea = document.getElementById("inputText");
525
  const outputDiv = document.getElementById("result");
526
  const copyBtn = document.getElementById("copyBtn");
527
  const detectorBtn = document.getElementById("detectorBtn");
 
528
 
529
  const text = textArea.value.trim();
530
 
@@ -535,6 +707,9 @@
535
 
536
  updateDebugInfo('Starting humanize process...');
537
 
 
 
 
538
  // Clear previous results completely
539
  outputDiv.innerHTML = "";
540
 
 
161
  button {
162
  background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);
163
  color: white;
164
+ padding: 8px 16px; /* Further reduced */
165
+ font-size: 13px; /* Further reduced */
166
  font-weight: 600;
167
  border: none;
168
+ border-radius: 8px; /* Smaller radius */
169
  cursor: pointer;
170
  transition: all 0.3s ease;
171
+ box-shadow: 0 2px 8px rgba(99, 102, 241, 0.3);
172
+ max-width: 200px; /* Limit button width */
173
  }
174
 
175
  button:hover {
176
+ transform: translateY(-1px);
177
+ box-shadow: 0 4px 12px rgba(99, 102, 241, 0.4);
178
  }
179
 
180
  button:active {
 
183
 
184
  .copy-button {
185
  background: linear-gradient(135deg, #10b981 0%, #059669 100%);
186
+ box-shadow: 0 2px 8px rgba(16, 185, 129, 0.3);
187
  margin-top: 0;
188
  flex-shrink: 0;
189
  width: 100%;
190
+ max-width: none; /* Allow full width for output buttons */
191
  }
192
 
193
  .copy-button:hover {
194
+ box-shadow: 0 4px 12px rgba(16, 185, 129, 0.4);
195
  }
196
 
197
  .copy-button.copied {
 
200
 
201
  .detector-button {
202
  background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
203
+ box-shadow: 0 2px 8px rgba(245, 158, 11, 0.3);
204
  margin-top: 8px;
205
  flex-shrink: 0;
206
  width: 100%;
207
+ max-width: none; /* Allow full width for output buttons */
208
  }
209
 
210
  .detector-button:hover {
211
+ box-shadow: 0 4px 12px rgba(245, 158, 11, 0.4);
212
+ }
213
+
214
+ /* ===== FILE UPLOAD STYLES ===== */
215
+ .file-upload-area {
216
+ margin-top: 12px;
217
+ display: flex;
218
+ gap: 8px;
219
+ align-items: center;
220
+ justify-content: center;
221
+ }
222
+
223
+ .buttons-row {
224
+ display: flex;
225
+ gap: 8px;
226
+ align-items: center;
227
+ justify-content: center;
228
+ flex-wrap: wrap;
229
+ }
230
+
231
+ .file-input-wrapper {
232
+ position: relative;
233
+ }
234
+
235
+ .file-input {
236
+ position: absolute;
237
+ opacity: 0;
238
+ width: 100%;
239
+ height: 100%;
240
+ cursor: pointer;
241
+ }
242
+
243
+ .file-input-label {
244
+ display: flex;
245
+ align-items: center;
246
+ justify-content: center;
247
+ padding: 8px 16px;
248
+ background: linear-gradient(135deg, #8b5cf6 0%, #a855f7 100%);
249
+ color: white;
250
+ border-radius: 8px;
251
+ cursor: pointer;
252
+ transition: all 0.3s ease;
253
+ font-size: 13px;
254
+ font-weight: 600;
255
+ box-shadow: 0 2px 8px rgba(139, 92, 246, 0.3);
256
+ min-height: 32px;
257
+ max-width: 140px; /* Limit width */
258
+ }
259
+
260
+ .file-input-label:hover {
261
+ transform: translateY(-1px);
262
+ box-shadow: 0 4px 12px rgba(139, 92, 246, 0.4);
263
+ }
264
+
265
+ .clear-button {
266
+ background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
267
+ box-shadow: 0 2px 8px rgba(239, 68, 68, 0.3);
268
+ padding: 8px 16px;
269
+ max-width: 100px; /* Limit width */
270
+ }
271
+
272
+ .clear-button:hover {
273
+ box-shadow: 0 4px 12px rgba(239, 68, 68, 0.4);
274
+ }
275
+
276
+ .file-info {
277
+ font-size: 12px;
278
+ color: #6b7280;
279
+ margin-top: 8px;
280
+ padding: 0 4px;
281
+ text-align: center;
282
  }
283
 
284
  /* ===== OUTPUT CONTENT CONTAINER ===== */
 
505
  <div class="panel input-panel">
506
  <div class="panel-header">
507
  <div class="panel-title">πŸ“ Input Text</div>
508
+ <div class="panel-subtitle">Paste your AI-generated content here or upload a file</div>
509
  </div>
510
 
511
  <textarea
 
514
  ></textarea>
515
 
516
  <div class="panel-bottom">
517
+ <!-- All buttons in one row -->
518
+ <div class="buttons-row">
519
+ <button type="button" onclick="humanize()">πŸš€ Humanize Text</button>
520
+
521
+ <div class="file-input-wrapper">
522
+ <input type="file" id="fileInput" class="file-input" accept=".txt,.doc,.docx,.pdf" onchange="handleFileUpload(event)">
523
+ <label for="fileInput" class="file-input-label">
524
+ πŸ“ Choose File
525
+ </label>
526
+ </div>
527
+
528
+ <button type="button" class="clear-button" onclick="clearText()">πŸ—‘οΈ Clear</button>
529
+ </div>
530
+
531
+ <div id="fileInfo" class="file-info" style="display: none;"></div>
532
  </div>
533
  </div>
534
 
 
607
  }
608
  });
609
 
610
+ // File upload handler
611
+ async function handleFileUpload(event) {
612
+ const file = event.target.files[0];
613
+ if (!file) return;
614
+
615
+ updateDebugInfo('File selected: ' + file.name);
616
+
617
+ const fileInfo = document.getElementById('fileInfo');
618
+ const textArea = document.getElementById('inputText');
619
+
620
+ // Show file info
621
+ fileInfo.textContent = `πŸ“„ ${file.name} (${(file.size / 1024).toFixed(1)} KB)`;
622
+ fileInfo.style.display = 'block';
623
+
624
+ try {
625
+ let text = '';
626
+
627
+ if (file.type === 'text/plain' || file.name.endsWith('.txt')) {
628
+ // Handle plain text files
629
+ text = await file.text();
630
+ } else if (file.name.endsWith('.docx')) {
631
+ // For DOCX files, show a message since mammoth requires external library
632
+ textArea.value = '⚠️ DOCX files are not yet supported. Please copy and paste the text manually or use a .txt file.';
633
+ fileInfo.textContent += ' - DOCX support coming soon!';
634
+ return;
635
+ } else if (file.name.endsWith('.pdf')) {
636
+ // For PDF files, show a message since PDF parsing is complex
637
+ textArea.value = '⚠️ PDF files are not yet supported. Please copy and paste the text manually or use a .txt file.';
638
+ fileInfo.textContent += ' - PDF support coming soon!';
639
+ return;
640
+ } else {
641
+ // Try to read as text for other formats
642
+ text = await file.text();
643
+ }
644
+
645
+ // Set the text in the textarea
646
+ textArea.value = text;
647
+
648
+ // Trigger the auto-resize
649
+ textArea.style.height = 'auto';
650
+ textArea.style.height = textArea.scrollHeight + 'px';
651
+
652
+ updateDebugInfo('File loaded successfully, text length: ' + text.length);
653
+ fileInfo.textContent += ' - βœ… Loaded successfully!';
654
+
655
+ } catch (error) {
656
+ updateDebugInfo('Error reading file: ' + error.message);
657
+ fileInfo.textContent = `❌ Error reading ${file.name}: ${error.message}`;
658
+ fileInfo.style.color = '#ef4444';
659
+ console.error('File reading error:', error);
660
+ }
661
+ }
662
+
663
+ // Clear text and file
664
+ function clearText() {
665
+ const textArea = document.getElementById('inputText');
666
+ const fileInput = document.getElementById('fileInput');
667
+ const fileInfo = document.getElementById('fileInfo');
668
+ const outputDiv = document.getElementById('result');
669
+ const copyBtn = document.getElementById('copyBtn');
670
+ const detectorBtn = document.getElementById('detectorBtn');
671
+ const detectorSection = document.getElementById('detectorSection');
672
+
673
+ // Clear all inputs and outputs
674
+ textArea.value = '';
675
+ fileInput.value = '';
676
+ fileInfo.style.display = 'none';
677
+ fileInfo.style.color = '#6b7280'; // Reset color
678
+
679
+ // Reset output area
680
+ outputDiv.innerHTML = '<div class="loading">Your humanized text will appear here...</div>';
681
+ copyBtn.style.display = 'none';
682
+ detectorBtn.style.display = 'none';
683
+ detectorSection.style.display = 'none';
684
+
685
+ // Reset stored text
686
+ currentHumanizedText = '';
687
+
688
+ // Reset textarea height
689
+ textArea.style.height = 'auto';
690
+
691
+ updateDebugInfo('All content cleared');
692
+ }
693
+
694
  async function humanize() {
695
  const textArea = document.getElementById("inputText");
696
  const outputDiv = document.getElementById("result");
697
  const copyBtn = document.getElementById("copyBtn");
698
  const detectorBtn = document.getElementById("detectorBtn");
699
+ const detectorSection = document.getElementById("detectorSection");
700
 
701
  const text = textArea.value.trim();
702
 
 
707
 
708
  updateDebugInfo('Starting humanize process...');
709
 
710
+ // Hide detector section when starting new humanization
711
+ detectorSection.style.display = "none";
712
+
713
  // Clear previous results completely
714
  outputDiv.innerHTML = "";
715