OpceanAI commited on
Commit
f938458
Β·
verified Β·
1 Parent(s): b4b4c19

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +809 -0
app.py ADDED
@@ -0,0 +1,809 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+
3
+ custom_css = """
4
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap');
5
+
6
+ /* ═══════════════════════════════════════════════════════════════
7
+ THEME SYSTEM - Vercel-Inspired Professional Design
8
+ ═══════════════════════════════════════════════════════════════ */
9
+
10
+ :root {
11
+ /* Light Theme (Default) */
12
+ --bg-primary: #ffffff;
13
+ --bg-secondary: #fafafa;
14
+ --bg-tertiary: #f4f4f5;
15
+ --bg-elevated: #ffffff;
16
+ --bg-hover: #f0f0f2;
17
+
18
+ --border-primary: #e4e4e7;
19
+ --border-secondary: #ebebef;
20
+ --border-subtle: #f0f0f2;
21
+
22
+ --text-primary: #09090b;
23
+ --text-secondary: #52525b;
24
+ --text-muted: #71717a;
25
+ --text-faint: #a1a1aa;
26
+
27
+ --accent-primary: #6366f1;
28
+ --accent-secondary: #818cf8;
29
+ --accent-subtle: rgba(99, 102, 241, 0.08);
30
+ --accent-hover: #4f46e5;
31
+
32
+ --user-bubble: linear-gradient(135deg, #18181b 0%, #27272a 100%);
33
+ --user-fg: #ffffff;
34
+ --bot-bubble: #f8f8fa;
35
+ --bot-fg: #18181b;
36
+ --bot-border: #e8e8ec;
37
+
38
+ --sidebar-bg: linear-gradient(180deg, #0a0a0b 0%, #111113 100%);
39
+ --sidebar-border: #1f1f23;
40
+ --sidebar-text: #fafafa;
41
+ --sidebar-muted: #a1a1aa;
42
+ --sidebar-hover: rgba(255, 255, 255, 0.06);
43
+
44
+ --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.04);
45
+ --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.06);
46
+ --shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.08);
47
+ --shadow-glow: 0 0 20px rgba(99, 102, 241, 0.15);
48
+
49
+ --radius-xs: 6px;
50
+ --radius-sm: 8px;
51
+ --radius-md: 12px;
52
+ --radius-lg: 16px;
53
+ --radius-xl: 20px;
54
+
55
+ --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
56
+ --font-mono: 'JetBrains Mono', 'Fira Code', 'Consolas', monospace;
57
+
58
+ --transition-fast: 0.15s cubic-bezier(0.4, 0, 0.2, 1);
59
+ --transition-base: 0.2s cubic-bezier(0.4, 0, 0.2, 1);
60
+ --transition-slow: 0.3s cubic-bezier(0.4, 0, 0.2, 1);
61
+
62
+ --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
63
+ --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
64
+ }
65
+
66
+ /* Dark Theme */
67
+ .dark {
68
+ --bg-primary: #09090b;
69
+ --bg-secondary: #0f0f11;
70
+ --bg-tertiary: #18181b;
71
+ --bg-elevated: #111113;
72
+ --bg-hover: #1c1c1f;
73
+
74
+ --border-primary: #27272a;
75
+ --border-secondary: #1f1f23;
76
+ --border-subtle: #18181b;
77
+
78
+ --text-primary: #fafafa;
79
+ --text-secondary: #a1a1aa;
80
+ --text-muted: #71717a;
81
+ --text-faint: #52525b;
82
+
83
+ --accent-primary: #818cf8;
84
+ --accent-secondary: #a5b4fc;
85
+ --accent-subtle: rgba(129, 140, 248, 0.12);
86
+ --accent-hover: #6366f1;
87
+
88
+ --user-bubble: linear-gradient(135deg, #6366f1 0%, #4f46e5 100%);
89
+ --user-fg: #ffffff;
90
+ --bot-bubble: #18181b;
91
+ --bot-fg: #e4e4e7;
92
+ --bot-border: #27272a;
93
+
94
+ --sidebar-bg: linear-gradient(180deg, #000000 0%, #09090b 100%);
95
+ --sidebar-border: #18181b;
96
+
97
+ --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.2);
98
+ --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.3);
99
+ --shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.4);
100
+ --shadow-glow: 0 0 30px rgba(99, 102, 241, 0.2);
101
+ }
102
+
103
+ /* ═══════════════════════════════════════════════════════════════
104
+ BASE RESET & GLOBAL STYLES
105
+ ═══════════════════════════════════════════════════════════════ */
106
+
107
+ *, *::before, *::after {
108
+ box-sizing: border-box;
109
+ margin: 0;
110
+ padding: 0;
111
+ }
112
+
113
+ html {
114
+ scroll-behavior: smooth;
115
+ }
116
+
117
+ body,
118
+ .gradio-container,
119
+ .gradio-container > .main,
120
+ .gradio-container > .main > .wrap {
121
+ background: var(--bg-primary) !important;
122
+ color: var(--text-primary) !important;
123
+ font-family: var(--font-sans) !important;
124
+ font-size: 14px !important;
125
+ line-height: 1.6 !important;
126
+ -webkit-font-smoothing: antialiased !important;
127
+ -moz-osx-font-smoothing: grayscale !important;
128
+ transition: background var(--transition-slow), color var(--transition-slow) !important;
129
+ }
130
+
131
+ /* ═══════════════════════════════════════════════════════════════
132
+ THEME TOGGLE BUTTON
133
+ ══════════════════���════════════════════════════════════════════ */
134
+
135
+ .theme-toggle-wrapper {
136
+ position: fixed !important;
137
+ top: 20px !important;
138
+ right: 20px !important;
139
+ z-index: 1000 !important;
140
+ }
141
+
142
+ .theme-toggle {
143
+ position: relative !important;
144
+ width: 52px !important;
145
+ height: 28px !important;
146
+ background: var(--bg-tertiary) !important;
147
+ border: 1px solid var(--border-primary) !important;
148
+ border-radius: 20px !important;
149
+ cursor: pointer !important;
150
+ transition: all var(--transition-base) !important;
151
+ display: flex !important;
152
+ align-items: center !important;
153
+ padding: 3px !important;
154
+ box-shadow: var(--shadow-sm) !important;
155
+ }
156
+
157
+ .theme-toggle:hover {
158
+ border-color: var(--accent-primary) !important;
159
+ box-shadow: var(--shadow-glow) !important;
160
+ }
161
+
162
+ .theme-toggle-thumb {
163
+ width: 20px !important;
164
+ height: 20px !important;
165
+ background: var(--bg-primary) !important;
166
+ border-radius: 50% !important;
167
+ transition: transform var(--transition-base) var(--ease-out-expo) !important;
168
+ display: flex !important;
169
+ align-items: center !important;
170
+ justify-content: center !important;
171
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1) !important;
172
+ }
173
+
174
+ .dark .theme-toggle-thumb {
175
+ transform: translateX(24px) !important;
176
+ background: var(--accent-primary) !important;
177
+ }
178
+
179
+ .theme-icon {
180
+ font-size: 12px !important;
181
+ transition: opacity var(--transition-fast) !important;
182
+ }
183
+
184
+ /* ═══════════════════════════════════════════════════════════════
185
+ SIDEBAR - Professional Dashboard Style
186
+ ═══════════════════════════════════════════════════════════════ */
187
+
188
+ .sidebar,
189
+ aside {
190
+ background: var(--sidebar-bg) !important;
191
+ border-right: 1px solid var(--sidebar-border) !important;
192
+ padding: 32px 24px !important;
193
+ min-width: 260px !important;
194
+ position: relative !important;
195
+ overflow: hidden !important;
196
+ }
197
+
198
+ /* Subtle gradient overlay for depth */
199
+ .sidebar::before,
200
+ aside::before {
201
+ content: '' !important;
202
+ position: absolute !important;
203
+ top: 0 !important;
204
+ left: 0 !important;
205
+ right: 0 !important;
206
+ height: 120px !important;
207
+ background: linear-gradient(180deg, rgba(99, 102, 241, 0.03) 0%, transparent 100%) !important;
208
+ pointer-events: none !important;
209
+ }
210
+
211
+ .sidebar *,
212
+ aside * {
213
+ color: var(--sidebar-text) !important;
214
+ position: relative !important;
215
+ }
216
+
217
+ /* Logo/Brand Title */
218
+ .sidebar h1,
219
+ aside h1 {
220
+ font-family: var(--font-sans) !important;
221
+ font-size: 18px !important;
222
+ font-weight: 700 !important;
223
+ letter-spacing: -0.025em !important;
224
+ color: #ffffff !important;
225
+ margin-bottom: 8px !important;
226
+ display: flex !important;
227
+ align-items: center !important;
228
+ gap: 10px !important;
229
+ }
230
+
231
+ .sidebar h1::before,
232
+ aside h1::before {
233
+ content: '' !important;
234
+ width: 8px !important;
235
+ height: 8px !important;
236
+ background: var(--accent-primary) !important;
237
+ border-radius: 2px !important;
238
+ box-shadow: 0 0 12px var(--accent-primary) !important;
239
+ animation: pulse-glow 2s ease-in-out infinite !important;
240
+ }
241
+
242
+ @keyframes pulse-glow {
243
+ 0%, 100% { opacity: 1; transform: scale(1); }
244
+ 50% { opacity: 0.7; transform: scale(0.95); }
245
+ }
246
+
247
+ /* Sidebar Description */
248
+ .sidebar p,
249
+ aside p {
250
+ font-size: 13px !important;
251
+ line-height: 1.7 !important;
252
+ color: var(--sidebar-muted) !important;
253
+ font-weight: 400 !important;
254
+ margin-bottom: 24px !important;
255
+ }
256
+
257
+ /* Login Button - Premium Style */
258
+ .sidebar button,
259
+ aside button {
260
+ display: flex !important;
261
+ align-items: center !important;
262
+ justify-content: center !important;
263
+ gap: 8px !important;
264
+ width: 100% !important;
265
+ margin-top: 24px !important;
266
+ padding: 12px 20px !important;
267
+ background: linear-gradient(135deg, var(--accent-primary) 0%, var(--accent-hover) 100%) !important;
268
+ color: #ffffff !important;
269
+ border: none !important;
270
+ border-radius: var(--radius-md) !important;
271
+ font-family: var(--font-sans) !important;
272
+ font-size: 14px !important;
273
+ font-weight: 600 !important;
274
+ letter-spacing: -0.01em !important;
275
+ cursor: pointer !important;
276
+ transition: all var(--transition-base) !important;
277
+ position: relative !important;
278
+ overflow: hidden !important;
279
+ box-shadow: 0 4px 14px rgba(99, 102, 241, 0.35) !important;
280
+ }
281
+
282
+ .sidebar button::before,
283
+ aside button::before {
284
+ content: '' !important;
285
+ position: absolute !important;
286
+ top: 0 !important;
287
+ left: -100% !important;
288
+ width: 100% !important;
289
+ height: 100% !important;
290
+ background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.15), transparent) !important;
291
+ transition: left 0.5s ease !important;
292
+ }
293
+
294
+ .sidebar button:hover::before,
295
+ aside button:hover::before {
296
+ left: 100% !important;
297
+ }
298
+
299
+ .sidebar button:hover,
300
+ aside button:hover {
301
+ transform: translateY(-2px) !important;
302
+ box-shadow: 0 6px 20px rgba(99, 102, 241, 0.4) !important;
303
+ }
304
+
305
+ .sidebar button:active,
306
+ aside button:active {
307
+ transform: translateY(0) !important;
308
+ }
309
+
310
+ /* ═══════════════════════════════════════════════════════════════
311
+ MAIN CHAT CONTAINER
312
+ ═══════════════════════════════════════════════════════════════ */
313
+
314
+ .contain,
315
+ .gap {
316
+ background: var(--bg-primary) !important;
317
+ }
318
+
319
+ .chatbot,
320
+ div[data-testid="chatbot"] {
321
+ background: var(--bg-primary) !important;
322
+ border: 1px solid var(--border-primary) !important;
323
+ border-radius: var(--radius-lg) !important;
324
+ box-shadow: var(--shadow-md) !important;
325
+ overflow: hidden !important;
326
+ transition: all var(--transition-base) !important;
327
+ }
328
+
329
+ .chatbot:hover,
330
+ div[data-testid="chatbot"]:hover {
331
+ box-shadow: var(--shadow-lg) !important;
332
+ }
333
+
334
+ /* Chat Header Label */
335
+ .chatbot label,
336
+ div[data-testid="chatbot"] > label {
337
+ font-family: var(--font-sans) !important;
338
+ font-size: 11px !important;
339
+ font-weight: 600 !important;
340
+ text-transform: uppercase !important;
341
+ letter-spacing: 0.1em !important;
342
+ color: var(--text-muted) !important;
343
+ padding: 14px 20px !important;
344
+ border-bottom: 1px solid var(--border-primary) !important;
345
+ background: var(--bg-secondary) !important;
346
+ display: flex !important;
347
+ align-items: center !important;
348
+ gap: 8px !important;
349
+ }
350
+
351
+ .chatbot label::before,
352
+ div[data-testid="chatbot"] > label::before {
353
+ content: '●' !important;
354
+ color: #22c55e !important;
355
+ font-size: 8px !important;
356
+ animation: blink 2s ease-in-out infinite !important;
357
+ }
358
+
359
+ @keyframes blink {
360
+ 0%, 100% { opacity: 1; }
361
+ 50% { opacity: 0.4; }
362
+ }
363
+
364
+ /* Messages Container */
365
+ .message-wrap,
366
+ .messages {
367
+ padding: 24px !important;
368
+ background: var(--bg-primary) !important;
369
+ min-height: 400px !important;
370
+ }
371
+
372
+ /* Individual Messages */
373
+ .message {
374
+ max-width: 75% !important;
375
+ padding: 14px 18px !important;
376
+ border-radius: var(--radius-lg) !important;
377
+ font-size: 14px !important;
378
+ line-height: 1.7 !important;
379
+ font-family: var(--font-sans) !important;
380
+ animation: message-in 0.3s var(--ease-out-expo) !important;
381
+ position: relative !important;
382
+ }
383
+
384
+ @keyframes message-in {
385
+ from {
386
+ opacity: 0;
387
+ transform: translateY(10px) scale(0.98);
388
+ }
389
+ to {
390
+ opacity: 1;
391
+ transform: translateY(0) scale(1);
392
+ }
393
+ }
394
+
395
+ /* User Messages */
396
+ .message.user,
397
+ .user.message {
398
+ background: var(--user-bubble) !important;
399
+ color: var(--user-fg) !important;
400
+ align-self: flex-end !important;
401
+ border-bottom-right-radius: var(--radius-xs) !important;
402
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15) !important;
403
+ margin-left: auto !important;
404
+ }
405
+
406
+ /* Bot Messages */
407
+ .message.bot,
408
+ .bot.message {
409
+ background: var(--bot-bubble) !important;
410
+ color: var(--bot-fg) !important;
411
+ align-self: flex-start !important;
412
+ border-bottom-left-radius: var(--radius-xs) !important;
413
+ border: 1px solid var(--bot-border) !important;
414
+ margin-right: auto !important;
415
+ }
416
+
417
+ /* Code blocks in messages */
418
+ .message code {
419
+ font-family: var(--font-mono) !important;
420
+ font-size: 13px !important;
421
+ background: rgba(0, 0, 0, 0.06) !important;
422
+ padding: 2px 6px !important;
423
+ border-radius: var(--radius-xs) !important;
424
+ }
425
+
426
+ .dark .message code {
427
+ background: rgba(255, 255, 255, 0.08) !important;
428
+ }
429
+
430
+ /* ═══════════════════════════════════════════════════════════════
431
+ INPUT AREA
432
+ ═══════════════════════════════════════════════════════════════ */
433
+
434
+ textarea,
435
+ input[type="text"],
436
+ .scroll-hide {
437
+ background: var(--bg-secondary) !important;
438
+ border: 1px solid var(--border-primary) !important;
439
+ border-radius: var(--radius-md) !important;
440
+ color: var(--text-primary) !important;
441
+ font-family: var(--font-sans) !important;
442
+ font-size: 14px !important;
443
+ line-height: 1.6 !important;
444
+ padding: 14px 18px !important;
445
+ resize: none !important;
446
+ transition: all var(--transition-base) !important;
447
+ caret-color: var(--accent-primary) !important;
448
+ }
449
+
450
+ textarea:focus,
451
+ input[type="text"]:focus {
452
+ border-color: var(--accent-primary) !important;
453
+ box-shadow: 0 0 0 4px var(--accent-subtle), var(--shadow-md) !important;
454
+ outline: none !important;
455
+ background: var(--bg-primary) !important;
456
+ }
457
+
458
+ textarea::placeholder,
459
+ input[type="text"]::placeholder {
460
+ color: var(--text-faint) !important;
461
+ font-style: normal !important;
462
+ }
463
+
464
+ /* ═══════════════════════════════════════════════════════════════
465
+ BUTTONS
466
+ ═══════════════════════════════════════════════════════════════ */
467
+
468
+ button[variant="primary"],
469
+ .submit-btn {
470
+ background: linear-gradient(135deg, var(--accent-primary) 0%, var(--accent-hover) 100%) !important;
471
+ color: #ffffff !important;
472
+ border: none !important;
473
+ border-radius: var(--radius-md) !important;
474
+ font-family: var(--font-sans) !important;
475
+ font-size: 14px !important;
476
+ font-weight: 600 !important;
477
+ padding: 12px 24px !important;
478
+ cursor: pointer !important;
479
+ transition: all var(--transition-base) !important;
480
+ position: relative !important;
481
+ overflow: hidden !important;
482
+ box-shadow: 0 4px 14px rgba(99, 102, 241, 0.3) !important;
483
+ }
484
+
485
+ button[variant="primary"]:hover,
486
+ .submit-btn:hover {
487
+ transform: translateY(-1px) !important;
488
+ box-shadow: 0 6px 20px rgba(99, 102, 241, 0.4) !important;
489
+ }
490
+
491
+ button[variant="primary"]:active,
492
+ .submit-btn:active {
493
+ transform: translateY(0) !important;
494
+ }
495
+
496
+ button[variant="secondary"] {
497
+ background: var(--bg-primary) !important;
498
+ color: var(--text-primary) !important;
499
+ border: 1px solid var(--border-primary) !important;
500
+ border-radius: var(--radius-md) !important;
501
+ font-family: var(--font-sans) !important;
502
+ font-size: 14px !important;
503
+ font-weight: 500 !important;
504
+ padding: 12px 20px !important;
505
+ transition: all var(--transition-base) !important;
506
+ cursor: pointer !important;
507
+ }
508
+
509
+ button[variant="secondary"]:hover {
510
+ background: var(--bg-hover) !important;
511
+ border-color: var(--accent-primary) !important;
512
+ }
513
+
514
+ /* ═══════════════════════════════════════════════════════════════
515
+ LABELS & TYPOGRAPHY
516
+ ═══════════════════════════════════════════════════════════════ */
517
+
518
+ label span,
519
+ .label-wrap span {
520
+ font-family: var(--font-sans) !important;
521
+ font-size: 12px !important;
522
+ font-weight: 600 !important;
523
+ letter-spacing: 0.04em !important;
524
+ color: var(--text-secondary) !important;
525
+ text-transform: uppercase !important;
526
+ }
527
+
528
+ .block,
529
+ .gr-block {
530
+ border-radius: var(--radius-lg) !important;
531
+ border-color: var(--border-primary) !important;
532
+ background: var(--bg-primary) !important;
533
+ transition: all var(--transition-base) !important;
534
+ }
535
+
536
+ /* ═══════════════════════════════════════════════════════════════
537
+ EXAMPLES TABLE
538
+ ═══════════════════════════════════════════════════════════════ */
539
+
540
+ .examples td {
541
+ border-color: var(--border-primary) !important;
542
+ background: var(--bg-secondary) !important;
543
+ font-family: var(--font-sans) !important;
544
+ font-size: 13px !important;
545
+ color: var(--text-secondary) !important;
546
+ border-radius: var(--radius-sm) !important;
547
+ padding: 12px 16px !important;
548
+ transition: all var(--transition-base) !important;
549
+ cursor: pointer !important;
550
+ }
551
+
552
+ .examples td:hover {
553
+ background: var(--accent-subtle) !important;
554
+ color: var(--accent-primary) !important;
555
+ border-color: var(--accent-primary) !important;
556
+ transform: translateY(-1px) !important;
557
+ }
558
+
559
+ /* ═══════════════════════════════════════════════════════════════
560
+ SCROLLBAR STYLING
561
+ ═══════════════════════════════════════════════════════════════ */
562
+
563
+ ::-webkit-scrollbar {
564
+ width: 6px !important;
565
+ height: 6px !important;
566
+ }
567
+
568
+ ::-webkit-scrollbar-track {
569
+ background: transparent !important;
570
+ }
571
+
572
+ ::-webkit-scrollbar-thumb {
573
+ background: var(--border-primary) !important;
574
+ border-radius: 10px !important;
575
+ transition: background var(--transition-fast) !important;
576
+ }
577
+
578
+ ::-webkit-scrollbar-thumb:hover {
579
+ background: var(--text-faint) !important;
580
+ }
581
+
582
+ /* Firefox scrollbar */
583
+ * {
584
+ scrollbar-width: thin !important;
585
+ scrollbar-color: var(--border-primary) transparent !important;
586
+ }
587
+
588
+ /* ═══════���═══════════════════════════════════════════════════════
589
+ LOADING STATES & ANIMATIONS
590
+ ═══════════════════════════════════════════════════════════════ */
591
+
592
+ .generating {
593
+ animation: shimmer 1.5s ease-in-out infinite !important;
594
+ }
595
+
596
+ @keyframes shimmer {
597
+ 0% { opacity: 1; }
598
+ 50% { opacity: 0.6; }
599
+ 100% { opacity: 1; }
600
+ }
601
+
602
+ /* Typing indicator */
603
+ .typing-indicator {
604
+ display: flex !important;
605
+ gap: 4px !important;
606
+ padding: 12px 16px !important;
607
+ }
608
+
609
+ .typing-indicator span {
610
+ width: 8px !important;
611
+ height: 8px !important;
612
+ background: var(--accent-primary) !important;
613
+ border-radius: 50% !important;
614
+ animation: typing-bounce 1.4s ease-in-out infinite !important;
615
+ }
616
+
617
+ .typing-indicator span:nth-child(2) { animation-delay: 0.2s; }
618
+ .typing-indicator span:nth-child(3) { animation-delay: 0.4s; }
619
+
620
+ @keyframes typing-bounce {
621
+ 0%, 60%, 100% { transform: translateY(0); }
622
+ 30% { transform: translateY(-6px); }
623
+ }
624
+
625
+ /* ═══════════════════════════════════════════════════════════════
626
+ FOOTER HIDE
627
+ ═══════════════════════════════════════════════════════════════ */
628
+
629
+ footer,
630
+ .footer,
631
+ .built-with {
632
+ display: none !important;
633
+ }
634
+
635
+ /* ═══════════════════════════════════════════════════════════════
636
+ RESPONSIVE ADJUSTMENTS
637
+ ═══════════════════════════════════════════════════════════════ */
638
+
639
+ @media (max-width: 768px) {
640
+ .sidebar,
641
+ aside {
642
+ min-width: 100% !important;
643
+ padding: 20px !important;
644
+ border-right: none !important;
645
+ border-bottom: 1px solid var(--sidebar-border) !important;
646
+ }
647
+
648
+ .message {
649
+ max-width: 90% !important;
650
+ }
651
+
652
+ .theme-toggle-wrapper {
653
+ top: 12px !important;
654
+ right: 12px !important;
655
+ }
656
+ }
657
+
658
+ /* ═══════════════════════════════════════════════════════════════
659
+ GLASS MORPHISM EFFECTS (Optional Premium Touch)
660
+ ═══════════════════════════════════════════════════════════════ */
661
+
662
+ .glass-effect {
663
+ background: rgba(255, 255, 255, 0.7) !important;
664
+ backdrop-filter: blur(12px) !important;
665
+ -webkit-backdrop-filter: blur(12px) !important;
666
+ border: 1px solid rgba(255, 255, 255, 0.2) !important;
667
+ }
668
+
669
+ .dark .glass-effect {
670
+ background: rgba(17, 17, 19, 0.8) !important;
671
+ border: 1px solid rgba(255, 255, 255, 0.05) !important;
672
+ }
673
+ """
674
+
675
+ # JavaScript for theme toggle functionality
676
+ theme_toggle_js = """
677
+ <script>
678
+ (function() {
679
+ // Check for saved theme preference or system preference
680
+ function getInitialTheme() {
681
+ const savedTheme = localStorage.getItem('theme');
682
+ if (savedTheme) return savedTheme;
683
+ return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
684
+ }
685
+
686
+ // Apply theme
687
+ function applyTheme(theme) {
688
+ if (theme === 'dark') {
689
+ document.documentElement.classList.add('dark');
690
+ } else {
691
+ document.documentElement.classList.remove('dark');
692
+ }
693
+ localStorage.setItem('theme', theme);
694
+ }
695
+
696
+ // Initialize theme
697
+ applyTheme(getInitialTheme());
698
+
699
+ // Create and inject theme toggle button
700
+ function createToggle() {
701
+ if (document.querySelector('.theme-toggle-wrapper')) return;
702
+
703
+ const wrapper = document.createElement('div');
704
+ wrapper.className = 'theme-toggle-wrapper';
705
+
706
+ const toggle = document.createElement('button');
707
+ toggle.className = 'theme-toggle';
708
+ toggle.setAttribute('aria-label', 'Toggle theme');
709
+ toggle.innerHTML = `
710
+ <span class="theme-toggle-thumb">
711
+ <span class="theme-icon">${document.documentElement.classList.contains('dark') ? 'πŸŒ™' : 'β˜€οΈ'}</span>
712
+ </span>
713
+ `;
714
+
715
+ toggle.addEventListener('click', () => {
716
+ const isDark = document.documentElement.classList.contains('dark');
717
+ const newTheme = isDark ? 'light' : 'dark';
718
+ applyTheme(newTheme);
719
+ toggle.querySelector('.theme-icon').textContent = newTheme === 'dark' ? 'πŸŒ™' : 'β˜€οΈ';
720
+ });
721
+
722
+ wrapper.appendChild(toggle);
723
+ document.body.appendChild(wrapper);
724
+ }
725
+
726
+ // Wait for DOM and inject toggle
727
+ if (document.readyState === 'loading') {
728
+ document.addEventListener('DOMContentLoaded', createToggle);
729
+ } else {
730
+ createToggle();
731
+ }
732
+
733
+ // Also run on Gradio updates
734
+ const observer = new MutationObserver(() => {
735
+ createToggle();
736
+ });
737
+ observer.observe(document.body, { childList: true, subtree: true });
738
+ })();
739
+ </script>
740
+ """
741
+
742
+ with gr.Blocks(
743
+ fill_height=True,
744
+ css=custom_css,
745
+ title="Yuuki-RxG | AI Assistant",
746
+ head=theme_toggle_js,
747
+ theme=gr.themes.Base(
748
+ primary_hue="indigo",
749
+ secondary_hue="slate",
750
+ neutral_hue="zinc",
751
+ font=gr.themes.GoogleFont("Inter"),
752
+ font_mono=gr.themes.GoogleFont("JetBrains Mono"),
753
+ radius_size=gr.themes.sizes.radius_lg,
754
+ spacing_size=gr.themes.sizes.spacing_md,
755
+ text_size=gr.themes.sizes.text_md,
756
+ ).set(
757
+ # Light mode base
758
+ body_background_fill="#ffffff",
759
+ body_text_color="#09090b",
760
+ background_fill_primary="#ffffff",
761
+ background_fill_secondary="#fafafa",
762
+
763
+ # Borders
764
+ border_color_primary="#e4e4e7",
765
+ border_color_accent="#6366f1",
766
+
767
+ # Accent colors
768
+ color_accent="#6366f1",
769
+ color_accent_soft="rgba(99, 102, 241, 0.08)",
770
+
771
+ # Buttons
772
+ button_primary_background_fill="linear-gradient(135deg, #6366f1 0%, #4f46e5 100%)",
773
+ button_primary_text_color="#ffffff",
774
+ button_primary_background_fill_hover="#4f46e5",
775
+ button_secondary_background_fill="#ffffff",
776
+ button_secondary_border_color="#e4e4e7",
777
+ button_secondary_text_color="#09090b",
778
+
779
+ # Blocks & inputs
780
+ block_border_color="#e4e4e7",
781
+ block_background_fill="#ffffff",
782
+ block_shadow="0 4px 12px rgba(0, 0, 0, 0.06)",
783
+ input_background_fill="#fafafa",
784
+ input_border_color="#e4e4e7",
785
+ input_border_color_focus="#6366f1",
786
+ input_shadow_focus="0 0 0 4px rgba(99, 102, 241, 0.1)",
787
+
788
+ # Shadows
789
+ shadow_drop="0 4px 12px rgba(0, 0, 0, 0.06)",
790
+ shadow_drop_lg="0 8px 24px rgba(0, 0, 0, 0.08)",
791
+ )
792
+ ) as demo:
793
+ with gr.Sidebar():
794
+ gr.Markdown("# Yuuki-RxG")
795
+ gr.Markdown(
796
+ """Modelo de IA avanzado servido mediante Featherless AI.
797
+
798
+ Inicia sesiΓ³n con tu cuenta de Hugging Face para acceder a la inferencia completa del modelo."""
799
+ )
800
+ button = gr.LoginButton("πŸ” Iniciar sesiΓ³n con Hugging Face")
801
+
802
+ gr.load(
803
+ "models/OpceanAI/Yuuki-RxG",
804
+ accept_token=button,
805
+ provider="featherless-ai",
806
+ )
807
+
808
+ if __name__ == "__main__":
809
+ demo.launch()