mihalykiss commited on
Commit
cd7ef38
·
verified ·
1 Parent(s): c1d5432

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +173 -71
app.py CHANGED
@@ -2,12 +2,13 @@ import gradio as gr
2
  import torch
3
  from transformers import AutoTokenizer, AutoModelForSequenceClassification
4
  import re
5
- from tokenizers import normalizers
6
  from tokenizers.normalizers import Sequence, Replace, Strip
7
- from tokenizers import Regex
8
  import os
9
 
10
 
 
11
  model1_path = "https://huggingface.co/spaces/SzegedAI/AI_Detector/resolve/main/modernbert.bin"
12
  model2_path = "https://huggingface.co/mihalykiss/modernbert_2/resolve/main/Model_groups_3class_seed12"
13
  model3_path = "https://huggingface.co/mihalykiss/modernbert_2/resolve/main/Model_groups_3class_seed22"
@@ -32,12 +33,7 @@ try:
32
 
33
  except Exception as e:
34
  print(f"Error during model loading: {e}")
35
- print("Please ensure all model paths are correct, dependencies are installed, and you have an internet connection for remote models.")
36
- # Handle the error, e.g., by exiting or displaying an error in the UI if Gradio is already running.
37
- # For simplicity, we'll let it potentially crash if models can't load before Gradio starts.
38
- # If Gradio is already running, you'd need a more sophisticated error display.
39
- # For now, we'll just make sure the Gradio interface doesn't try to use non-existent models.
40
- tokenizer = None # Prevent further errors if tokenizer failed
41
  model_1, model_2, model_3 = None, None, None
42
 
43
 
@@ -59,15 +55,31 @@ def clean_text(text: str) -> str:
59
  text = re.sub(r'\s+([,.;:?!])', r'\1', text)
60
  return text
61
 
62
- if tokenizer:
63
- newline_to_space = Replace(Regex(r'\s*\n\s*'), " ")
64
- join_hyphen_break = Replace(Regex(r'(\w+)[--]\s*\n\s*(\w+)'), r"\1\2")
65
- tokenizer.backend_tokenizer.normalizer = Sequence([
66
- tokenizer.backend_tokenizer.normalizer,
67
- join_hyphen_break,
68
- newline_to_space,
69
  Strip()
70
- ])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
 
72
 
73
  title_md = """
@@ -82,7 +94,7 @@ description = """
82
  <li><span class="icon">✅</span> <strong>Human Verification: </strong> Clearly identifies human-written content.</li>
83
  <li><span class="icon">🔍</span> <strong>Model Detection: </strong> Capable of identifying content from over 40 AI models.</li>
84
  <li><span class="icon">📈</span> <strong>Accuracy: </strong> Performs optimally with more extensive text inputs.</li>
85
- <li><span class="icon">📄</span> <strong>Read more: </strong> Our methodology is detailed in our research paper: &nbsp;
86
  <a href="https://aclanthology.org/2025.genaidetect-1.15/" target="_blank" class="learn-more-link"> <b> LINK </b></a>.
87
  </li>
88
  </ul>
@@ -104,21 +116,21 @@ def classify_text_interface(text):
104
  return "<p style='text-align: center; color: var(--ai-color);'><strong>Error: Models not loaded. Please check the console.</strong></p>"
105
 
106
  cleaned_text = clean_text(text)
107
- if not cleaned_text.strip():
108
  result_message = "<p style='text-align: center; color: var(--text-secondary);'>Please enter some text to analyze.</p>"
109
  return result_message
110
 
111
- inputs = tokenizer(cleaned_text, return_tensors="pt", truncation=True, padding=True, max_length=512).to(device) # Added max_length
112
-
113
  with torch.no_grad():
114
  logits_1 = model_1(**inputs).logits
115
  logits_2 = model_2(**inputs).logits
116
  logits_3 = model_3(**inputs).logits
117
-
118
  softmax_1 = torch.softmax(logits_1, dim=1)
119
  softmax_2 = torch.softmax(logits_2, dim=1)
120
  softmax_3 = torch.softmax(logits_3, dim=1)
121
-
122
  averaged_probabilities = (softmax_1 + softmax_2 + softmax_3) / 3
123
  probabilities = averaged_probabilities[0]
124
 
@@ -128,21 +140,21 @@ def classify_text_interface(text):
128
  if v.lower() == 'human':
129
  human_label_index = k
130
  break
131
-
132
  if human_label_index != -1:
133
- ai_probs[human_label_index] = 0
134
  human_prob_value = probabilities[human_label_index].item() * 100
135
- else:
136
- human_prob_value = 0
137
  print("Warning: 'human' label not found in label_mapping.")
138
 
139
  ai_total_prob = ai_probs.sum().item() * 100
140
 
141
-
142
- ai_argmax_index = torch.argmax(ai_probs).item()
143
  ai_argmax_model = label_mapping.get(ai_argmax_index, "Unknown AI")
144
 
145
- if human_prob_value > ai_total_prob :
146
  result_message = (
147
  f"<p><strong>The text is</strong> <span class='highlight-human'><strong>{human_prob_value:.2f}%</strong> likely <b>Human written</b>.</span></p>"
148
  )
@@ -156,33 +168,86 @@ def classify_text_interface(text):
156
  modern_css = """
157
  @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
158
 
 
159
  :root {
160
- --primary-bg: #F8F9FA;
161
  --app-bg: #FFFFFF;
162
  --text-primary: #2C3E50;
163
  --text-secondary: #7F8C8D;
164
  --accent-color: #1ABC9C;
165
  --accent-color-darker: #16A085;
166
- --border-color: #E0E0E0;
167
  --input-bg: #FFFFFF;
168
  --input-focus-border: var(--accent-color);
169
- --human-color: #2ECC71;
170
  --human-bg: rgba(46, 204, 113, 0.1);
171
  --ai-color: #E74C3C;
172
  --ai-bg: rgba(231, 76, 60, 0.1);
173
  --shadow-color: rgba(44, 62, 80, 0.1);
174
- --container-max-width: 800px;
175
  --border-radius-md: 8px;
176
  --border-radius-lg: 12px;
 
 
 
 
 
 
177
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
178
  .features-list strong::after {
179
  content: " ";
180
  display: inline-block;
181
- width: 0.2em;
182
  }
 
183
  body {
184
  font-family: 'Inter', sans-serif;
185
- background: linear-gradient(135deg, #f5f7fa 0%, #eef2f7 100%);
186
  color: var(--text-primary);
187
  margin: 0;
188
  padding: 20px;
@@ -192,6 +257,7 @@ body {
192
  min-height: 100vh;
193
  box-sizing: border-box;
194
  overflow-y: auto;
 
195
  }
196
 
197
  .gradio-container {
@@ -202,19 +268,21 @@ body {
202
  max-width: var(--container-max-width);
203
  width: 100%;
204
  margin: 20px auto;
205
- border: none;
 
206
  }
207
 
208
- .form.svelte-633qhp, .block.svelte-11xb1hd, .gradio-html .block {
209
  background: none !important;
210
  border: none !important;
211
  box-shadow: none !important;
212
  padding: 0 !important;
213
  }
214
 
215
- h1 {
 
216
  color: var(--text-primary);
217
- font-size: clamp(24px, 5vw, 30px);
218
  font-weight: 700;
219
  text-align: center;
220
  margin-bottom: 20px;
@@ -243,7 +311,7 @@ h1 {
243
 
244
  .features-list li {
245
  display: flex;
246
- align-items: center;
247
  font-size: clamp(14px, 2.5vw, 16px);
248
  color: var(--text-secondary);
249
  margin-bottom: 12px;
@@ -254,6 +322,7 @@ h1 {
254
  margin-right: 12px;
255
  font-size: 1.2em;
256
  color: var(--accent-color);
 
257
  }
258
 
259
  .learn-more-link, .learn-more-link b {
@@ -275,22 +344,23 @@ h1 {
275
  width: 100%;
276
  box-sizing: border-box;
277
  color: var(--text-primary);
278
- transition: border-color 0.3s ease, box-shadow 0.3s ease;
279
  min-height: 120px;
280
- box-shadow: 0 2px 4px rgba(0,0,0,0.05);
281
  }
282
 
283
  #text_input_box textarea::placeholder {
284
- color: #B0BEC5;
 
285
  }
286
 
287
  #text_input_box textarea:focus {
288
  border-color: var(--input-focus-border);
289
- box-shadow: 0 0 0 3px rgba(26, 188, 156, 0.2);
290
  outline: none;
291
  }
292
 
293
- #result_output_box {
294
  background-color: var(--input-bg);
295
  border: 1px solid var(--border-color);
296
  border-radius: var(--border-radius-md);
@@ -300,41 +370,46 @@ h1 {
300
  box-sizing: border-box;
301
  text-align: center;
302
  font-size: clamp(16px, 3vw, 17px);
303
- box-shadow: 0 4px 8px rgba(0,0,0,0.05);
304
- min-height: 80px;
305
- display: flex;
306
  flex-direction: column;
307
  justify-content: center;
 
308
  }
309
- #result_output_box p {
310
- margin-bottom: 8px;
311
  line-height: 1.6;
 
312
  }
313
  #result_output_box p:last-child {
314
  margin-bottom: 0;
315
  }
 
 
 
316
 
317
 
318
- .highlight-human, .highlight-ai {
319
  font-weight: 600;
320
- padding: 5px 10px;
321
  border-radius: var(--border-radius-md);
322
  display: inline-block;
323
- font-size: 1.05em;
 
324
  }
325
 
326
  .highlight-human {
327
  color: var(--human-color);
328
  background-color: var(--human-bg);
329
- /* border: 1px solid var(--human-color);
330
  }
331
 
332
  .highlight-ai {
333
  color: var(--ai-color);
334
  background-color: var(--ai-bg);
335
- /* border: 1px solid var(--ai-color);
336
  }
337
 
 
338
  .tabs > div:first-child button {
339
  background-color: transparent !important;
340
  color: var(--text-secondary) !important;
@@ -352,32 +427,56 @@ h1 {
352
  font-weight: 600 !important;
353
  }
354
 
355
- .gr-examples {
356
- padding: 15px !important;
357
- border: 1px solid var(--border-color) !important;
358
- border-radius: var(--border-radius-md) !important;
359
- background-color: #fdfdfd !important;
360
- margin-top: 10px;
 
 
 
361
  }
362
- .gr-sample-textbox {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
363
  border: 1px solid var(--border-color) !important;
364
  border-radius: var(--border-radius-md) !important;
365
  font-size: 14px !important;
 
 
 
366
  }
367
- .gr-accordion > .label-wrap button {
368
- font-weight: 500 !important;
369
- color: var(--text-primary) !important;
370
  }
371
 
372
 
373
  .footer-text, #bottom_text {
374
  text-align: center;
375
- margin-top: 40px;
376
  font-size: clamp(13px, 2vw, 14px);
377
  color: var(--text-secondary);
378
  }
379
-
380
- #bottom_text p {
381
  margin: 0;
382
  }
383
 
@@ -390,10 +489,11 @@ h1 {
390
  padding: 20px;
391
  margin: 10px;
392
  }
393
- h1 { font-size: 22px; } /* Adjust for custom title markdown */
394
  .app-description p, .features-list li { font-size: 14px; }
395
  #text_input_box textarea { font-size: 15px; min-height: 100px; }
396
  #result_output_box { font-size: 15px; padding: 15px; }
 
397
  }
398
  """
399
 
@@ -407,7 +507,7 @@ with iface:
407
  label="",
408
  placeholder="Type or paste your content here...",
409
  elem_id="text_input_box",
410
- lines=10
411
  )
412
  result_output = gr.HTML(elem_id="result_output_box")
413
 
@@ -421,13 +521,15 @@ with iface:
421
  examples=AI_texts,
422
  inputs=text_input,
423
  label="",
 
424
  )
425
 
426
  with gr.Accordion("Human Text Examples", open=False):
427
  gr.Examples(
428
  examples=Human_texts,
429
  inputs=text_input,
430
- label="",
 
431
  )
432
 
433
  gr.Markdown(bottom_text, elem_id="bottom_text")
 
2
  import torch
3
  from transformers import AutoTokenizer, AutoModelForSequenceClassification
4
  import re
5
+ from tokenizers import normalizers # For isinstance check
6
  from tokenizers.normalizers import Sequence, Replace, Strip
7
+ from tokenizers import Regex # For the Regex class
8
  import os
9
 
10
 
11
+ # --- Model & Tokenizer Configuration ---
12
  model1_path = "https://huggingface.co/spaces/SzegedAI/AI_Detector/resolve/main/modernbert.bin"
13
  model2_path = "https://huggingface.co/mihalykiss/modernbert_2/resolve/main/Model_groups_3class_seed12"
14
  model3_path = "https://huggingface.co/mihalykiss/modernbert_2/resolve/main/Model_groups_3class_seed22"
 
33
 
34
  except Exception as e:
35
  print(f"Error during model loading: {e}")
36
+ tokenizer = None
 
 
 
 
 
37
  model_1, model_2, model_3 = None, None, None
38
 
39
 
 
55
  text = re.sub(r'\s+([,.;:?!])', r'\1', text)
56
  return text
57
 
58
+ if tokenizer:
59
+ # Define the new normalizers to add
60
+ custom_normalizers_to_add = [
61
+ Replace(Regex(r'(\w+)[--]\s*\n\s*(\w+)'), r"\1\2"), # join_hyphen_break
62
+ Replace(Regex(r'\s*\n\s*'), " "), # newline_to_space
 
 
63
  Strip()
64
+ ]
65
+
66
+ # Get the current normalizer from the backend tokenizer
67
+ current_backend_normalizer = tokenizer.backend_tokenizer.normalizer
68
+
69
+ if current_backend_normalizer is None:
70
+ # If no existing normalizer, just use the new ones in a Sequence
71
+ tokenizer.backend_tokenizer.normalizer = Sequence(custom_normalizers_to_add)
72
+ elif isinstance(current_backend_normalizer, normalizers.Sequence):
73
+ # If existing is a Sequence, extend its list of normalizers
74
+ # The .normalizers attribute of a Sequence is a list, so we can extend it
75
+ current_backend_normalizer.normalizers.extend(custom_normalizers_to_add)
76
+ # Re-assign to ensure change is registered if Sequence behaves immutably (though it likely modifies in place)
77
+ tokenizer.backend_tokenizer.normalizer = Sequence(current_backend_normalizer.normalizers)
78
+ else:
79
+ # If existing is a single normalizer (not None and not a Sequence), create a new Sequence
80
+ tokenizer.backend_tokenizer.normalizer = Sequence([current_backend_normalizer] + custom_normalizers_to_add)
81
+
82
+ # --- End Model & Tokenizer Configuration ---
83
 
84
 
85
  title_md = """
 
94
  <li><span class="icon">✅</span> <strong>Human Verification: </strong> Clearly identifies human-written content.</li>
95
  <li><span class="icon">🔍</span> <strong>Model Detection: </strong> Capable of identifying content from over 40 AI models.</li>
96
  <li><span class="icon">📈</span> <strong>Accuracy: </strong> Performs optimally with more extensive text inputs.</li>
97
+ <li><span class="icon">📄</span> <strong>Read more: </strong> Our methodology is detailed in our research paper: &nbsp;
98
  <a href="https://aclanthology.org/2025.genaidetect-1.15/" target="_blank" class="learn-more-link"> <b> LINK </b></a>.
99
  </li>
100
  </ul>
 
116
  return "<p style='text-align: center; color: var(--ai-color);'><strong>Error: Models not loaded. Please check the console.</strong></p>"
117
 
118
  cleaned_text = clean_text(text)
119
+ if not cleaned_text.strip():
120
  result_message = "<p style='text-align: center; color: var(--text-secondary);'>Please enter some text to analyze.</p>"
121
  return result_message
122
 
123
+ inputs = tokenizer(cleaned_text, return_tensors="pt", truncation=True, padding=True, max_length=512).to(device)
124
+
125
  with torch.no_grad():
126
  logits_1 = model_1(**inputs).logits
127
  logits_2 = model_2(**inputs).logits
128
  logits_3 = model_3(**inputs).logits
129
+
130
  softmax_1 = torch.softmax(logits_1, dim=1)
131
  softmax_2 = torch.softmax(logits_2, dim=1)
132
  softmax_3 = torch.softmax(logits_3, dim=1)
133
+
134
  averaged_probabilities = (softmax_1 + softmax_2 + softmax_3) / 3
135
  probabilities = averaged_probabilities[0]
136
 
 
140
  if v.lower() == 'human':
141
  human_label_index = k
142
  break
143
+
144
  if human_label_index != -1:
145
+ ai_probs[human_label_index] = 0
146
  human_prob_value = probabilities[human_label_index].item() * 100
147
+ else:
148
+ human_prob_value = 0
149
  print("Warning: 'human' label not found in label_mapping.")
150
 
151
  ai_total_prob = ai_probs.sum().item() * 100
152
 
153
+
154
+ ai_argmax_index = torch.argmax(ai_probs).item()
155
  ai_argmax_model = label_mapping.get(ai_argmax_index, "Unknown AI")
156
 
157
+ if human_prob_value > ai_total_prob :
158
  result_message = (
159
  f"<p><strong>The text is</strong> <span class='highlight-human'><strong>{human_prob_value:.2f}%</strong> likely <b>Human written</b>.</span></p>"
160
  )
 
168
  modern_css = """
169
  @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
170
 
171
+ /* Light Theme (Default) */
172
  :root {
173
+ --primary-bg: #F4F7FC; /* Lighter body background */
174
  --app-bg: #FFFFFF;
175
  --text-primary: #2C3E50;
176
  --text-secondary: #7F8C8D;
177
  --accent-color: #1ABC9C;
178
  --accent-color-darker: #16A085;
179
+ --border-color: #E0E6ED; /* Slightly softer border */
180
  --input-bg: #FFFFFF;
181
  --input-focus-border: var(--accent-color);
182
+ --human-color: #2ECC71;
183
  --human-bg: rgba(46, 204, 113, 0.1);
184
  --ai-color: #E74C3C;
185
  --ai-bg: rgba(231, 76, 60, 0.1);
186
  --shadow-color: rgba(44, 62, 80, 0.1);
187
+ --container-max-width: 800px;
188
  --border-radius-md: 8px;
189
  --border-radius-lg: 12px;
190
+ --examples-bg: #F8F9FA; /* Light background for examples area */
191
+ --placeholder-color: #B0BEC5;
192
+ --accordion-label-color: var(--text-primary);
193
+ --accordion-bg: var(--app-bg); /* Accordion bg same as app-bg for seamless look */
194
+ --accordion-border: var(--border-color);
195
+ --sample-textbox-bg: var(--input-bg);
196
  }
197
+
198
+ /* Dark Theme Overrides */
199
+ @media (prefers-color-scheme: dark) {
200
+ :root {
201
+ --primary-bg: #1A1D2E; /* Dark Blue/Charcoal for body */
202
+ --app-bg: #252936; /* Slightly lighter dark for main container */
203
+ --text-primary: #EAEAF1; /* Off-white for primary text */
204
+ --text-secondary: #A0A3AF; /* Lighter gray for secondary text */
205
+ --accent-color: #1DE9B6; /* Brighter Teal for dark mode */
206
+ --accent-color-darker: #00BFA5;
207
+ --border-color: #3A3E4F; /* Darker, less prominent border */
208
+ --input-bg: #2C3040; /* Darker input background */
209
+ /* --input-focus-border: var(--accent-color); /* Can remain the same or use a brighter version */
210
+ --human-color: #69F0AE; /* Brighter Green */
211
+ --human-bg: rgba(105, 240, 174, 0.15); /* Slightly more opaque for dark bg */
212
+ --ai-color: #FF8A80; /* Brighter Red */
213
+ --ai-bg: rgba(255, 138, 128, 0.15); /* Slightly more opaque for dark bg */
214
+ --shadow-color: rgba(0, 0, 0, 0.25); /* Shadow on dark bg */
215
+ --examples-bg: #2A2E3B; /* Dark background for examples area */
216
+ --placeholder-color: #7A7D8A;
217
+ --accordion-label-color: var(--text-primary);
218
+ --accordion-bg: var(--app-bg); /* Keep accordion bg consistent with app */
219
+ --accordion-border: var(--border-color);
220
+ --sample-textbox-bg: var(--input-bg);
221
+ }
222
+
223
+ body { /* Ensure body background changes for dark mode */
224
+ background: var(--primary-bg);
225
+ }
226
+
227
+ /* Specific component adjustments for dark mode if needed */
228
+ #text_input_box textarea::placeholder {
229
+ color: var(--placeholder-color);
230
+ }
231
+ .gr-accordion > .label-wrap button {
232
+ color: var(--accordion-label-color) !important; /* Ensure it uses the dark mode text color */
233
+ }
234
+ .learn-more-link, .learn-more-link b { /* Ensure link color adapts */
235
+ color: var(--accent-color) !important;
236
+ }
237
+ .learn-more-link:hover, .learn-more-link:hover b {
238
+ color: var(--accent-color-darker) !important;
239
+ }
240
+ }
241
+
242
  .features-list strong::after {
243
  content: " ";
244
  display: inline-block;
245
+ width: 0.2em; /* Adds a small space after the bolded part like "Verification: " */
246
  }
247
+
248
  body {
249
  font-family: 'Inter', sans-serif;
250
+ background: var(--primary-bg); /* Use CSS variable */
251
  color: var(--text-primary);
252
  margin: 0;
253
  padding: 20px;
 
257
  min-height: 100vh;
258
  box-sizing: border-box;
259
  overflow-y: auto;
260
+ transition: background-color 0.3s ease, color 0.3s ease; /* Smooth theme transition */
261
  }
262
 
263
  .gradio-container {
 
268
  max-width: var(--container-max-width);
269
  width: 100%;
270
  margin: 20px auto;
271
+ border: none; /* Gradio might add its own border, ensure it's controlled or removed */
272
+ transition: background-color 0.3s ease, box-shadow 0.3s ease;
273
  }
274
 
275
+ .form.svelte-633qhp, .block.svelte-11xb1hd, .gradio-html .block {
276
  background: none !important;
277
  border: none !important;
278
  box-shadow: none !important;
279
  padding: 0 !important;
280
  }
281
 
282
+ /* Title and subtitle are handled by title_md */
283
+ h1 { /* Fallback or for other h1s if any */
284
  color: var(--text-primary);
285
+ font-size: clamp(24px, 5vw, 30px);
286
  font-weight: 700;
287
  text-align: center;
288
  margin-bottom: 20px;
 
311
 
312
  .features-list li {
313
  display: flex;
314
+ align-items: center; /* Align icon with the first line of text */
315
  font-size: clamp(14px, 2.5vw, 16px);
316
  color: var(--text-secondary);
317
  margin-bottom: 12px;
 
322
  margin-right: 12px;
323
  font-size: 1.2em;
324
  color: var(--accent-color);
325
+ flex-shrink: 0; /* Prevent icon from shrinking */
326
  }
327
 
328
  .learn-more-link, .learn-more-link b {
 
344
  width: 100%;
345
  box-sizing: border-box;
346
  color: var(--text-primary);
347
+ transition: background-color 0.3s ease, border-color 0.3s ease, box-shadow 0.3s ease, color 0.3s ease;
348
  min-height: 120px;
349
+ box-shadow: 0 2px 4px rgba(0,0,0,0.05); /* Subtle shadow for light mode */
350
  }
351
 
352
  #text_input_box textarea::placeholder {
353
+ color: var(--placeholder-color);
354
+ transition: color 0.3s ease;
355
  }
356
 
357
  #text_input_box textarea:focus {
358
  border-color: var(--input-focus-border);
359
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--input-focus-border) 25%, transparent); /* Use color-mix for focus shadow */
360
  outline: none;
361
  }
362
 
363
+ #result_output_box {
364
  background-color: var(--input-bg);
365
  border: 1px solid var(--border-color);
366
  border-radius: var(--border-radius-md);
 
370
  box-sizing: border-box;
371
  text-align: center;
372
  font-size: clamp(16px, 3vw, 17px);
373
+ box-shadow: 0 4px 8px rgba(0,0,0,0.05); /* Subtle shadow for light mode */
374
+ min-height: 80px;
375
+ display: flex;
376
  flex-direction: column;
377
  justify-content: center;
378
+ transition: background-color 0.3s ease, border-color 0.3s ease, color 0.3s ease;
379
  }
380
+ #result_output_box p {
381
+ margin-bottom: 8px;
382
  line-height: 1.6;
383
+ color: var(--text-primary); /* Ensure text inside result box also adapts */
384
  }
385
  #result_output_box p:last-child {
386
  margin-bottom: 0;
387
  }
388
+ #result_output_box strong { /* Ensure bold text also adapts color */
389
+ color: var(--text-primary);
390
+ }
391
 
392
 
393
+ .highlight-human, .highlight-ai { /* These are spans, color is set by their own var */
394
  font-weight: 600;
395
+ padding: 5px 10px;
396
  border-radius: var(--border-radius-md);
397
  display: inline-block;
398
+ font-size: 1.05em;
399
+ transition: background-color 0.3s ease, color 0.3s ease;
400
  }
401
 
402
  .highlight-human {
403
  color: var(--human-color);
404
  background-color: var(--human-bg);
 
405
  }
406
 
407
  .highlight-ai {
408
  color: var(--ai-color);
409
  background-color: var(--ai-bg);
 
410
  }
411
 
412
+ /* Gradio specific Tab styling (if you were to use Tabs) */
413
  .tabs > div:first-child button {
414
  background-color: transparent !important;
415
  color: var(--text-secondary) !important;
 
427
  font-weight: 600 !important;
428
  }
429
 
430
+ /* Accordion and Examples Styling */
431
+ .gr-accordion {
432
+ border: 1px solid var(--accordion-border) !important;
433
+ border-radius: var(--border-radius-lg) !important;
434
+ box-shadow: none !important;
435
+ padding: 0 15px 15px 15px !important;
436
+ margin-bottom: 20px !important; /* Increased space below each accordion */
437
+ background-color: var(--accordion-bg) !important; /* Use variable for accordion background */
438
+ transition: background-color 0.3s ease, border-color 0.3s ease;
439
  }
440
+
441
+ .gr-accordion > .label-wrap button {
442
+ font-weight: 600 !important;
443
+ color: var(--accordion-label-color) !important;
444
+ padding: 15px 0px !important; /* More padding for label */
445
+ font-size: 1.05em !important;
446
+ transition: color 0.3s ease;
447
+ }
448
+ .gr-accordion > .label-wrap { /* Remove default Gradio accordion label border */
449
+ border-bottom: none !important;
450
+ }
451
+
452
+
453
+ .gr-examples { /* Wrapper for the examples content */
454
+ padding: 15px 0px 0px 0px !important; /* Adjust padding, top padding handled by accordion */
455
+ border: none !important; /* Border is on accordion now */
456
+ border-radius: 0 !important; /* Rounded corners on accordion */
457
+ background-color: transparent !important; /* Examples area transparent, accordion has bg */
458
+ margin-top: 0px !important; /* No extra margin, accordion handles it */
459
+ }
460
+ .gr-sample-textbox { /* Individual example textboxes */
461
  border: 1px solid var(--border-color) !important;
462
  border-radius: var(--border-radius-md) !important;
463
  font-size: 14px !important;
464
+ background-color: var(--sample-textbox-bg) !important;
465
+ color: var(--text-primary) !important; /* Text color for example text */
466
+ transition: background-color 0.3s ease, border-color 0.3s ease, color 0.3s ease;
467
  }
468
+ .gr-sample-textbox:hover {
469
+ border-color: var(--accent-color) !important; /* Highlight on hover */
 
470
  }
471
 
472
 
473
  .footer-text, #bottom_text {
474
  text-align: center;
475
+ margin-top: 40px; /* Keep space above footer */
476
  font-size: clamp(13px, 2vw, 14px);
477
  color: var(--text-secondary);
478
  }
479
+ #bottom_text p {
 
480
  margin: 0;
481
  }
482
 
 
489
  padding: 20px;
490
  margin: 10px;
491
  }
492
+ h1 { font-size: 22px; }
493
  .app-description p, .features-list li { font-size: 14px; }
494
  #text_input_box textarea { font-size: 15px; min-height: 100px; }
495
  #result_output_box { font-size: 15px; padding: 15px; }
496
+ .gr-accordion > .label-wrap button { padding: 12px 0 !important; }
497
  }
498
  """
499
 
 
507
  label="",
508
  placeholder="Type or paste your content here...",
509
  elem_id="text_input_box",
510
+ lines=10
511
  )
512
  result_output = gr.HTML(elem_id="result_output_box")
513
 
 
521
  examples=AI_texts,
522
  inputs=text_input,
523
  label="",
524
+ elem_classes="gr-examples" # Added class for styling
525
  )
526
 
527
  with gr.Accordion("Human Text Examples", open=False):
528
  gr.Examples(
529
  examples=Human_texts,
530
  inputs=text_input,
531
+ label="",
532
+ elem_classes="gr-examples" # Added class for styling
533
  )
534
 
535
  gr.Markdown(bottom_text, elem_id="bottom_text")