atascioglu commited on
Commit
1b7d5af
Β·
verified Β·
1 Parent(s): e8eb0ce

Upload 10 files

Browse files
Files changed (7) hide show
  1. .gitattributes +1 -0
  2. app.py +18 -16
  3. background_bottom.png +0 -0
  4. background_mid.png +0 -0
  5. background_top.png +3 -0
  6. requirements.txt +1 -1
  7. style.css +247 -237
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ background_top.png filter=lfs diff=lfs merge=lfs -text
app.py CHANGED
@@ -415,31 +415,33 @@ def ai_chat(user_msg: str, history: list):
415
  return history, viz_img, viz_tbl
416
 
417
  # ─────────────────────────────────────────────
418
- # Gradio Theme & CSS
419
  # ─────────────────────────────────────────────
420
- theme = gr.themes.Soft(
421
- primary_hue=gr.themes.colors.blue,
422
- secondary_hue=gr.themes.colors.purple,
423
- font=("system-ui", "-apple-system", "Segoe UI", "sans-serif"),
424
- )
425
 
426
  def _load_css() -> str:
427
- """Load external CSS file if it exists."""
428
- css_path = Path(__file__).parent / "style.css"
429
- if css_path.exists():
430
- return css_path.read_text(encoding="utf-8")
431
- return ""
432
-
433
- CUSTOM_CSS = _load_css()
 
 
 
 
 
434
 
435
  # ─────────────────────────────────────────────
436
  # Build the Gradio UI
437
  # ─────────────────────────────────────────────
438
- with gr.Blocks(theme=theme, css=CUSTOM_CSS, title="AIBDM 2026 Dashboard") as demo:
439
 
440
  gr.Markdown(
441
  "# AIBDM 2026 — AI & Big Data Management Dashboard\n"
442
- "*ESCP Business School • Hugging Face Spaces*"
 
443
  )
444
 
445
  # ── Tab 1: Pipeline Runner ──────────────
@@ -588,4 +590,4 @@ with gr.Blocks(theme=theme, css=CUSTOM_CSS, title="AIBDM 2026 Dashboard") as dem
588
  # Launch (HF Spaces handles host/port)
589
  # ─────────────────────────────────────────────
590
  if __name__ == "__main__":
591
- demo.launch()
 
415
  return history, viz_img, viz_tbl
416
 
417
  # ─────────────────────────────────────────────
418
+ # CSS
419
  # ─────────────────────────────────────────────
420
+ BASE = Path(__file__).resolve().parent
 
 
 
 
421
 
422
  def _load_css() -> str:
423
+ """Load external CSS and inject background image paths as CSS variables."""
424
+ css_path = BASE / "style.css"
425
+ css = css_path.read_text(encoding="utf-8") if css_path.exists() else ""
426
+ # Inject CSS custom properties for background images (served via /file=)
427
+ bg_vars = (
428
+ ":root {\n"
429
+ f" --bg-top: url('/file={BASE / 'background_top.png'}');\n"
430
+ f" --bg-mid: url('/file={BASE / 'background_mid.png'}');\n"
431
+ f" --bg-bottom: url('/file={BASE / 'background_bottom.png'}');\n"
432
+ "}\n"
433
+ )
434
+ return bg_vars + css
435
 
436
  # ─────────────────────────────────────────────
437
  # Build the Gradio UI
438
  # ─────────────────────────────────────────────
439
+ with gr.Blocks(title="AIBDM 2026 Dashboard") as demo:
440
 
441
  gr.Markdown(
442
  "# AIBDM 2026 — AI & Big Data Management Dashboard\n"
443
+ "*ESCP Business School • Hugging Face Spaces*",
444
+ elem_id="escp_title",
445
  )
446
 
447
  # ── Tab 1: Pipeline Runner ──────────────
 
590
  # Launch (HF Spaces handles host/port)
591
  # ─────────────────────────────────────────────
592
  if __name__ == "__main__":
593
+ demo.launch(css=_load_css(), allowed_paths=[str(BASE)])
background_bottom.png ADDED
background_mid.png ADDED
background_top.png ADDED

Git LFS Details

  • SHA256: 27e963d20dbb7ae88368fb527d475c85ef0de3df63d8f0d7d5e2af7403a5b365
  • Pointer size: 131 Bytes
  • Size of remote file: 726 kB
requirements.txt CHANGED
@@ -1,4 +1,4 @@
1
- gradio>=5.0.0,<6.0.0
2
  papermill>=2.6.0
3
  pandas>=2.2.0
4
  numpy>=1.26.0
 
1
+ gradio>=6.0.0
2
  papermill>=2.6.0
3
  pandas>=2.2.0
4
  numpy>=1.26.0
style.css CHANGED
@@ -1,12 +1,15 @@
1
  /* ============================================================
2
  ESCP Business School β€” AI for Business Decision Making
3
- Gradio 5.x Custom Theme | Glass-Morphism Aurora
4
  ============================================================ */
5
 
6
  /* ---------- design tokens ---------- */
7
  :root {
8
- --bg: #f0ecff;
9
- --bg-card: rgba(255, 255, 255, 0.72);
 
 
 
10
  --lavender: #c5b4f0;
11
  --lavender-mid: #a48de8;
12
  --violet: #7c5cbf;
@@ -23,42 +26,73 @@
23
  --radius-md: 16px;
24
  --radius-lg: 20px;
25
  --radius-pill: 50px;
26
- --shadow-card: 0 4px 24px rgba(75, 45, 138, 0.08);
27
- --shadow-hover: 0 8px 32px rgba(75, 45, 138, 0.14);
28
  --transition: 0.2s ease;
29
  }
30
 
31
- /* ---------- aurora background ---------- */
32
- body, .gradio-container {
33
- background: var(--bg) !important;
34
- font-family: var(--font-sans) !important;
35
- color: var(--text) !important;
36
- }
37
-
38
- .gradio-container::before {
39
- content: '';
40
- position: fixed;
41
- inset: 0;
42
- z-index: -1;
43
- background:
44
- radial-gradient(ellipse 60% 50% at 15% 20%, rgba(197, 180, 240, 0.55) 0%, transparent 70%),
45
- radial-gradient(ellipse 50% 45% at 80% 15%, rgba(160, 200, 255, 0.45) 0%, transparent 65%),
46
- radial-gradient(ellipse 40% 40% at 70% 75%, rgba(110, 231, 199, 0.35) 0%, transparent 60%),
47
- radial-gradient(ellipse 35% 35% at 25% 80%, rgba(255, 179, 200, 0.30) 0%, transparent 60%),
48
- var(--bg);
49
- pointer-events: none;
50
- }
51
-
52
- /* ---------- container ---------- */
53
- .gradio-container > .main {
54
- max-width: 1520px !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  margin: 0 auto !important;
56
- padding: 1.5rem !important;
 
 
 
57
  }
58
 
59
  /* ---------- animations ---------- */
60
  @keyframes popIn {
61
- 0% { opacity: 0; transform: scale(0.92) translateY(12px); }
62
  100% { opacity: 1; transform: scale(1) translateY(0); }
63
  }
64
 
@@ -67,308 +101,284 @@ body, .gradio-container {
67
  100% { background-position: 200% center; }
68
  }
69
 
70
- /* ---------- cards / panels ---------- */
71
- .panel, .block, .form, .gradio-group,
72
- .gradio-accordion, .gradio-tabitem {
73
- background: var(--bg-card) !important;
74
- backdrop-filter: blur(18px) !important;
75
- -webkit-backdrop-filter: blur(18px) !important;
76
- border: 1px solid rgba(197, 180, 240, 0.30) !important;
77
- border-radius: var(--radius-lg) !important;
78
- box-shadow: var(--shadow-card) !important;
79
- animation: popIn 0.4s ease both;
80
- }
81
-
82
- /* ---------- header accent stripe ---------- */
83
- .gradio-container > .main > *:first-child::before {
84
- content: '';
85
- display: block;
86
- height: 4px;
87
- border-radius: 2px;
88
- margin-bottom: 1rem;
89
- background: linear-gradient(90deg, var(--violet-deep), var(--lavender-mid), var(--mint), var(--blush));
90
- background-size: 200% 100%;
91
- animation: shimmerSlide 4s linear infinite;
92
- }
93
-
94
- /* ---------- tabs ---------- */
95
- .tabs > .tab-nav {
96
- background: var(--bg-card) !important;
97
  backdrop-filter: blur(14px) !important;
98
  -webkit-backdrop-filter: blur(14px) !important;
99
- border-radius: var(--radius-pill) !important;
100
- padding: 5px !important;
101
- gap: 4px !important;
102
- border: 1px solid rgba(197, 180, 240, 0.25) !important;
103
- box-shadow: var(--shadow-card) !important;
104
  }
105
 
106
- .tabs > .tab-nav > button {
107
- border: none !important;
108
- border-radius: var(--radius-pill) !important;
109
- padding: 8px 22px !important;
110
  font-weight: 600 !important;
111
- font-size: 0.88rem !important;
112
- color: var(--text-mid) !important;
113
  background: transparent !important;
 
 
 
 
 
114
  transition: all var(--transition) !important;
115
- letter-spacing: 0.3px;
116
  }
117
 
118
- .tabs > .tab-nav > button:hover {
119
- background: rgba(197, 180, 240, 0.22) !important;
120
- color: var(--violet) !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
  }
122
 
123
- .tabs > .tab-nav > button.selected {
124
- background: linear-gradient(135deg, var(--violet), var(--violet-deep)) !important;
125
- color: #fff !important;
126
- box-shadow: 0 2px 12px rgba(124, 92, 191, 0.35) !important;
 
 
 
127
  }
128
 
129
- /* ---------- buttons: primary ---------- */
130
  .primary, button.primary,
131
  .gr-button-primary, .gr-button.primary {
132
- background: linear-gradient(135deg, var(--violet), var(--violet-deep)) !important;
133
- color: #fff !important;
134
  border: none !important;
135
- border-radius: var(--radius-pill) !important;
136
- padding: 10px 28px !important;
137
  font-weight: 600 !important;
138
- box-shadow: 0 3px 14px rgba(124, 92, 191, 0.30) !important;
139
  transition: all var(--transition) !important;
140
  }
141
 
142
- .primary:hover, button.primary:hover,
143
- .gr-button-primary:hover, .gr-button.primary:hover {
144
- transform: translateY(-2px) !important;
145
- box-shadow: var(--shadow-hover) !important;
146
- filter: brightness(1.06);
147
  }
148
 
149
  /* ---------- buttons: secondary ---------- */
150
  .secondary, button.secondary,
151
  .gr-button-secondary, .gr-button.secondary {
152
- background: var(--bg-card) !important;
153
- backdrop-filter: blur(10px) !important;
154
- color: var(--violet) !important;
155
- border: 1.5px solid var(--lavender) !important;
156
- border-radius: var(--radius-pill) !important;
157
- padding: 10px 28px !important;
158
  font-weight: 600 !important;
159
  transition: all var(--transition) !important;
160
  }
161
 
162
- .secondary:hover, button.secondary:hover,
163
- .gr-button-secondary:hover, .gr-button.secondary:hover {
164
- background: rgba(197, 180, 240, 0.18) !important;
165
- border-color: var(--lavender-mid) !important;
166
  transform: translateY(-1px) !important;
167
  }
168
 
169
  /* ---------- inputs / textareas ---------- */
170
- input[type="text"], input[type="number"], input[type="password"],
171
- textarea, .gr-input, .gr-text-input, select {
172
- background: var(--bg-card) !important;
173
- backdrop-filter: blur(8px) !important;
174
- border: 1.5px solid var(--lavender) !important;
175
- border-radius: var(--radius-sm) !important;
176
- color: var(--text) !important;
177
  font-family: var(--font-sans) !important;
 
178
  transition: all var(--transition) !important;
179
  }
180
 
181
- input:focus, textarea:focus, select:focus,
182
- .gr-input:focus, .gr-text-input:focus {
 
183
  outline: none !important;
184
  border-color: var(--lavender-mid) !important;
185
  box-shadow: 0 0 0 3px rgba(164, 141, 232, 0.25) !important;
186
  }
187
 
188
- /* ---------- pipeline log (terminal) ---------- */
189
- .pipeline-log, .log-output, [class*="log"],
190
- textarea[data-testid="textbox"].prose {
191
  background: #1a0e2e !important;
192
  color: var(--lavender) !important;
193
  font-family: var(--font-mono) !important;
194
  font-size: 0.82rem !important;
195
- line-height: 1.65 !important;
196
  border-radius: var(--radius-md) !important;
197
- padding: 1rem !important;
198
- border: 1px solid rgba(197, 180, 240, 0.15) !important;
199
- max-height: 360px !important;
200
- overflow-y: auto !important;
201
  }
202
 
203
  /* ---------- chatbot ---------- */
204
- .chatbot .message-row .user {
205
- background: linear-gradient(135deg, rgba(197, 180, 240, 0.28), rgba(197, 180, 240, 0.12)) !important;
206
- border: 1px solid rgba(197, 180, 240, 0.35) !important;
207
- border-radius: var(--radius-md) var(--radius-md) 4px var(--radius-md) !important;
208
- color: var(--text) !important;
209
- }
210
-
211
- .chatbot .message-row .bot {
212
- background: var(--bg-card) !important;
213
- border: 1px solid rgba(197, 180, 240, 0.18) !important;
214
- border-radius: var(--radius-md) var(--radius-md) var(--radius-md) 4px !important;
215
- box-shadow: 0 2px 10px rgba(75, 45, 138, 0.06) !important;
216
- color: var(--text) !important;
217
- }
218
-
219
- /* ---------- section labels ---------- */
220
- .gr-block-label, .gr-input-label, label span,
221
- .label-wrap > span {
222
- text-transform: uppercase !important;
223
- letter-spacing: 2.5px !important;
224
- font-size: 0.72rem !important;
225
- font-weight: 700 !important;
226
- color: var(--violet) !important;
227
  }
228
 
229
- .gr-block-label::after, .label-wrap > span::after {
230
- content: '';
231
- display: block;
232
- margin-top: 6px;
233
- height: 2px;
234
- width: 48px;
235
- border-radius: 1px;
236
- background: linear-gradient(90deg, var(--violet), var(--lavender), transparent);
237
  }
238
 
239
- /* ---------- scrollbars ---------- */
240
- * {
241
- scrollbar-width: thin;
242
- scrollbar-color: var(--lavender) transparent;
243
  }
244
 
245
- ::-webkit-scrollbar {
246
- width: 6px;
247
- height: 6px;
 
248
  }
249
 
250
- ::-webkit-scrollbar-track {
251
- background: transparent;
252
  }
253
 
254
- ::-webkit-scrollbar-thumb {
255
- background: linear-gradient(180deg, var(--lavender), var(--mint));
256
- border-radius: 3px;
 
257
  }
258
 
259
- /* ---------- plotly charts ---------- */
260
- .js-plotly-plot .plot-container,
261
- .js-plotly-plot .main-svg {
262
- background: transparent !important;
263
  }
264
 
265
- /* ---------- slider ---------- */
266
- input[type="range"] {
267
- accent-color: var(--violet) !important;
268
  }
269
 
270
- /* ---------- dropdown ---------- */
271
- .gr-dropdown, .dropdown-content {
272
- background: var(--bg-card) !important;
273
- backdrop-filter: blur(12px) !important;
274
- border: 1px solid var(--lavender) !important;
275
- border-radius: var(--radius-sm) !important;
 
276
  }
277
 
278
- /* ---------- status colors ---------- */
279
- .gr-status-success, .success { color: var(--mint) !important; }
280
- .gr-status-warning, .warning { color: var(--blush) !important; }
281
- .gr-status-error, .error { color: var(--red) !important; }
282
-
283
- /* ---------- dataframe / table ---------- */
284
- .dataframe, .gr-dataframe {
285
- border-radius: var(--radius-md) !important;
286
- overflow: hidden !important;
287
  }
288
 
289
- .dataframe th {
290
- background: linear-gradient(135deg, var(--violet), var(--violet-deep)) !important;
291
- color: #fff !important;
292
- font-weight: 600 !important;
293
- text-transform: uppercase !important;
294
- letter-spacing: 1px !important;
295
- font-size: 0.78rem !important;
296
  }
297
 
298
- .dataframe td {
299
- border-color: rgba(197, 180, 240, 0.18) !important;
 
 
 
300
  }
301
 
302
- .dataframe tr:hover td {
303
- background: rgba(197, 180, 240, 0.10) !important;
 
 
 
 
304
  }
305
 
306
- /* ---------- dark mode overrides (Gradio toggle) ---------- */
307
- .dark body, .dark .gradio-container {
308
- --bg: #12091f;
309
- --bg-card: rgba(30, 18, 52, 0.78);
310
- --text: #e8e0f6;
311
- --text-mid: #b8a8d8;
312
- --text-muted: #7a6a9e;
313
- background: var(--bg) !important;
314
- color: var(--text) !important;
315
  }
316
 
317
- .dark .gradio-container::before {
318
- background:
319
- radial-gradient(ellipse 60% 50% at 15% 20%, rgba(124, 92, 191, 0.25) 0%, transparent 70%),
320
- radial-gradient(ellipse 50% 45% at 80% 15%, rgba(80, 120, 200, 0.20) 0%, transparent 65%),
321
- radial-gradient(ellipse 40% 40% at 70% 75%, rgba(110, 231, 199, 0.12) 0%, transparent 60%),
322
- radial-gradient(ellipse 35% 35% at 25% 80%, rgba(255, 179, 200, 0.10) 0%, transparent 60%),
323
- var(--bg) !important;
324
  }
325
 
326
- .dark input[type="text"], .dark input[type="number"],
327
- .dark textarea, .dark select {
328
- background: rgba(30, 18, 52, 0.65) !important;
329
- color: var(--text) !important;
 
 
 
 
 
 
330
  }
331
 
332
  /* ---------- responsive ---------- */
333
  @media (max-width: 768px) {
334
- .gradio-container > .main {
335
- padding: 0.75rem !important;
 
 
336
  }
337
 
338
- .tabs > .tab-nav {
339
- flex-wrap: wrap !important;
340
- }
341
-
342
- .tabs > .tab-nav > button {
343
- padding: 6px 14px !important;
344
- font-size: 0.8rem !important;
345
- }
346
-
347
- .primary, button.primary,
348
- .secondary, button.secondary {
349
- padding: 8px 18px !important;
350
- font-size: 0.85rem !important;
351
  }
352
  }
353
 
354
  @media (max-width: 480px) {
355
- .gradio-container > .main {
356
- padding: 0.5rem !important;
357
- max-width: 100% !important;
358
  }
359
 
360
- .panel, .block, .form, .gradio-group {
361
- border-radius: var(--radius-md) !important;
362
- padding: 0.75rem !important;
363
  }
364
  }
365
 
366
- /* ---------- smooth transitions everywhere ---------- */
367
- *, *::before, *::after {
368
  transition-property: background, border-color, box-shadow, color, opacity, transform;
369
  transition-duration: 0.2s;
370
  transition-timing-function: ease;
371
  }
372
-
373
- /* don't transition layout-triggering properties on load */
374
- .gradio-container * { animation-fill-mode: both; }
 
1
  /* ============================================================
2
  ESCP Business School β€” AI for Business Decision Making
3
+ Gradio 5.x Custom Theme | ESCP Deep Purple + Glass Cards
4
  ============================================================ */
5
 
6
  /* ---------- design tokens ---------- */
7
  :root {
8
+ --escp-purple: rgb(40, 9, 109);
9
+ --escp-purple-light: rgb(60, 20, 140);
10
+ --escp-gold: rgb(242, 198, 55);
11
+ --bg-card: rgba(255, 255, 255, 0.95);
12
+ --bg-card-glass: rgba(255, 255, 255, 0.88);
13
  --lavender: #c5b4f0;
14
  --lavender-mid: #a48de8;
15
  --violet: #7c5cbf;
 
26
  --radius-md: 16px;
27
  --radius-lg: 20px;
28
  --radius-pill: 50px;
29
+ --shadow-card: 0 4px 24px rgba(0, 0, 0, 0.12);
30
+ --shadow-hover: 0 8px 32px rgba(0, 0, 0, 0.18);
31
  --transition: 0.2s ease;
32
  }
33
 
34
+ /* ---------- ESCP deep purple background (extends infinitely) ---------- */
35
+ html, body {
36
+ background-color: var(--escp-purple) !important;
37
+ margin: 0 !important;
38
+ padding: 0 !important;
39
+ min-height: 100vh !important;
40
+ }
41
+
42
+ /* Background images: top (once at top) + mid (repeats to fill all remaining space) */
43
+ /* NOTE: __BG_TOP__, __BG_MID__, __BG_BOTTOM__ are replaced at runtime by app.py
44
+ with the correct Gradio file-serving paths. */
45
+ gradio-app,
46
+ .gradio-app,
47
+ .main,
48
+ #app,
49
+ [data-testid="app"] {
50
+ background-color: var(--escp-purple) !important;
51
+ background-image:
52
+ var(--bg-top),
53
+ var(--bg-mid) !important;
54
+ background-position:
55
+ top center,
56
+ 0 913px !important;
57
+ background-repeat:
58
+ no-repeat,
59
+ repeat-y !important;
60
+ background-size:
61
+ 100% auto,
62
+ 100% auto !important;
63
+ min-height: 100vh !important;
64
+ }
65
+
66
+ /* Fixed bottom banner β€” stays pinned to viewport bottom */
67
+ body::after {
68
+ content: '' !important;
69
+ position: fixed !important;
70
+ bottom: 0 !important;
71
+ left: 0 !important;
72
+ right: 0 !important;
73
+ height: 130px !important;
74
+ background-image: var(--bg-bottom) !important;
75
+ background-size: 100% 100% !important;
76
+ background-repeat: no-repeat !important;
77
+ background-position: bottom center !important;
78
+ pointer-events: none !important;
79
+ z-index: 9999 !important;
80
+ }
81
+
82
+ /* ---------- container: transparent so purple shows through ---------- */
83
+ .gradio-container {
84
+ max-width: 1400px !important;
85
+ width: 94vw !important;
86
  margin: 0 auto !important;
87
+ padding-top: 200px !important;
88
+ padding-bottom: 160px !important;
89
+ background: transparent !important;
90
+ font-family: var(--font-sans) !important;
91
  }
92
 
93
  /* ---------- animations ---------- */
94
  @keyframes popIn {
95
+ 0% { opacity: 0; transform: scale(0.94) translateY(10px); }
96
  100% { opacity: 1; transform: scale(1) translateY(0); }
97
  }
98
 
 
101
  100% { background-position: 200% center; }
102
  }
103
 
104
+ /* ---------- title: ESCP gold ---------- */
105
+ #escp_title h1,
106
+ .gradio-container > .main > div:first-child h1 {
107
+ color: var(--escp-gold) !important;
108
+ font-size: 2.8rem !important;
109
+ font-weight: 800 !important;
110
+ text-align: center !important;
111
+ margin: 0 0 8px 0 !important;
112
+ text-shadow: 0 2px 12px rgba(0, 0, 0, 0.3);
113
+ }
114
+
115
+ /* subtitle / italic text */
116
+ #escp_title p, #escp_title em,
117
+ .gradio-container > .main > div:first-child p,
118
+ .gradio-container > .main > div:first-child em {
119
+ color: rgba(255, 255, 255, 0.85) !important;
120
+ text-align: center !important;
121
+ }
122
+
123
+ /* ---------- tab bar ---------- */
124
+ .tabs > .tab-nav,
125
+ .tab-nav,
126
+ div[role="tablist"] {
127
+ background: rgba(40, 9, 109, 0.6) !important;
 
 
 
128
  backdrop-filter: blur(14px) !important;
129
  -webkit-backdrop-filter: blur(14px) !important;
130
+ border-radius: var(--radius-sm) var(--radius-sm) 0 0 !important;
131
+ padding: 4px !important;
132
+ gap: 2px !important;
133
+ border: none !important;
 
134
  }
135
 
136
+ .tabs > .tab-nav > button,
137
+ .tab-nav button,
138
+ button[role="tab"] {
139
+ color: #ffffff !important;
140
  font-weight: 600 !important;
141
+ border: none !important;
 
142
  background: transparent !important;
143
+ padding: 10px 20px !important;
144
+ border-radius: 8px 8px 0 0 !important;
145
+ opacity: 1 !important;
146
+ font-family: var(--font-sans) !important;
147
+ font-size: 0.9rem !important;
148
  transition: all var(--transition) !important;
 
149
  }
150
 
151
+ .tabs > .tab-nav > button.selected,
152
+ .tab-nav button.selected,
153
+ button[role="tab"][aria-selected="true"] {
154
+ color: var(--escp-gold) !important;
155
+ background: rgba(255, 255, 255, 0.12) !important;
156
+ }
157
+
158
+ .tabs > .tab-nav > button:hover:not(.selected),
159
+ .tab-nav button:hover:not(.selected) {
160
+ background: rgba(255, 255, 255, 0.08) !important;
161
+ }
162
+
163
+ /* ---------- tab content area (white cards on purple) ---------- */
164
+ .tabitem, .gradio-tabitem {
165
+ background: var(--bg-card) !important;
166
+ border-radius: 0 0 var(--radius-sm) var(--radius-sm) !important;
167
+ padding: 20px !important;
168
+ animation: popIn 0.35s ease both;
169
+ border: none !important;
170
+ box-shadow: none !important;
171
  }
172
 
173
+ /* ---------- white card panels inside tabs ---------- */
174
+ .gradio-container .gr-block,
175
+ .gradio-container .gr-box,
176
+ .gradio-container .gr-panel,
177
+ .gradio-container .gr-group {
178
+ background: #ffffff !important;
179
+ border-radius: var(--radius-sm) !important;
180
  }
181
 
182
+ /* ---------- buttons: primary (ESCP purple) ---------- */
183
  .primary, button.primary,
184
  .gr-button-primary, .gr-button.primary {
185
+ background-color: var(--escp-purple) !important;
186
+ color: #ffffff !important;
187
  border: none !important;
188
+ border-radius: var(--radius-sm) !important;
189
+ padding: 10px 20px !important;
190
  font-weight: 600 !important;
191
+ box-shadow: 0 3px 12px rgba(40, 9, 109, 0.3) !important;
192
  transition: all var(--transition) !important;
193
  }
194
 
195
+ .primary:hover, button.primary:hover {
196
+ background-color: var(--escp-purple-light) !important;
197
+ transform: translateY(-1px) !important;
198
+ box-shadow: 0 5px 18px rgba(40, 9, 109, 0.4) !important;
 
199
  }
200
 
201
  /* ---------- buttons: secondary ---------- */
202
  .secondary, button.secondary,
203
  .gr-button-secondary, .gr-button.secondary {
204
+ background-color: #ffffff !important;
205
+ color: var(--escp-purple) !important;
206
+ border: 2px solid var(--escp-purple) !important;
207
+ border-radius: var(--radius-sm) !important;
208
+ padding: 10px 20px !important;
 
209
  font-weight: 600 !important;
210
  transition: all var(--transition) !important;
211
  }
212
 
213
+ .secondary:hover, button.secondary:hover {
214
+ background-color: rgb(240, 238, 250) !important;
 
 
215
  transform: translateY(-1px) !important;
216
  }
217
 
218
  /* ---------- inputs / textareas ---------- */
219
+ .gradio-container input,
220
+ .gradio-container textarea,
221
+ .gradio-container select {
222
+ background: #ffffff !important;
223
+ border: 1px solid #d1d5db !important;
224
+ border-radius: 8px !important;
 
225
  font-family: var(--font-sans) !important;
226
+ color: var(--text) !important;
227
  transition: all var(--transition) !important;
228
  }
229
 
230
+ .gradio-container input:focus,
231
+ .gradio-container textarea:focus,
232
+ .gradio-container select:focus {
233
  outline: none !important;
234
  border-color: var(--lavender-mid) !important;
235
  box-shadow: 0 0 0 3px rgba(164, 141, 232, 0.25) !important;
236
  }
237
 
238
+ /* ---------- pipeline log (dark terminal) ---------- */
239
+ #log-box textarea {
 
240
  background: #1a0e2e !important;
241
  color: var(--lavender) !important;
242
  font-family: var(--font-mono) !important;
243
  font-size: 0.82rem !important;
244
+ line-height: 1.7 !important;
245
  border-radius: var(--radius-md) !important;
246
+ border: 1px solid rgba(197, 180, 240, 0.2) !important;
247
+ box-shadow: inset 0 2px 12px rgba(0, 0, 0, 0.2) !important;
 
 
248
  }
249
 
250
  /* ---------- chatbot ---------- */
251
+ .gr-chatbot {
252
+ min-height: 380px !important;
253
+ background-color: #ffffff !important;
254
+ border-radius: 12px !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
255
  }
256
 
257
+ .gr-chatbot .message.user {
258
+ background-color: rgb(232, 225, 250) !important;
259
+ border-radius: 12px !important;
 
 
 
 
 
260
  }
261
 
262
+ .gr-chatbot .message.bot {
263
+ background-color: #f3f4f6 !important;
264
+ border-radius: 12px !important;
 
265
  }
266
 
267
+ /* ---------- headings inside tabs ---------- */
268
+ .tabitem h3, .gradio-tabitem h3 {
269
+ color: var(--escp-purple) !important;
270
+ font-weight: 700 !important;
271
  }
272
 
273
+ .tabitem h4, .gradio-tabitem h4 {
274
+ color: #374151 !important;
275
  }
276
 
277
+ /* ---------- gallery ---------- */
278
+ .gallery {
279
+ background: #ffffff !important;
280
+ border-radius: var(--radius-sm) !important;
281
  }
282
 
283
+ /* ---------- dataframe / table ---------- */
284
+ [data-testid="dataframe"] {
285
+ background-color: #ffffff !important;
286
+ border-radius: var(--radius-sm) !important;
287
  }
288
 
289
+ table {
290
+ font-size: 0.85rem !important;
 
291
  }
292
 
293
+ /* ---------- example prompts ---------- */
294
+ .examples-row button {
295
+ background: rgb(240, 238, 250) !important;
296
+ color: var(--escp-purple) !important;
297
+ border: 1px solid var(--escp-purple) !important;
298
+ border-radius: 8px !important;
299
+ font-size: 0.85rem !important;
300
  }
301
 
302
+ .examples-row button:hover {
303
+ background: rgb(232, 225, 250) !important;
 
 
 
 
 
 
 
304
  }
305
 
306
+ /* ---------- scrollbars ---------- */
307
+ * {
308
+ scrollbar-width: thin;
309
+ scrollbar-color: var(--lavender) transparent;
 
 
 
310
  }
311
 
312
+ ::-webkit-scrollbar { width: 6px; height: 6px; }
313
+ ::-webkit-scrollbar-track { background: transparent; }
314
+ ::-webkit-scrollbar-thumb {
315
+ background: linear-gradient(180deg, var(--lavender), var(--mint));
316
+ border-radius: 3px;
317
  }
318
 
319
+ /* ---------- plotly charts ---------- */
320
+ .js-plotly-plot .plot-container,
321
+ .js-plotly-plot .main-svg,
322
+ .js-plotly-plot .bg {
323
+ fill: transparent !important;
324
+ background: transparent !important;
325
  }
326
 
327
+ /* ---------- header / footer: transparent ---------- */
328
+ header, header *,
329
+ footer, footer * {
330
+ background: transparent !important;
331
+ box-shadow: none !important;
 
 
 
 
332
  }
333
 
334
+ footer a, footer button,
335
+ header a, header button {
336
+ background: transparent !important;
337
+ border: none !important;
338
+ box-shadow: none !important;
 
 
339
  }
340
 
341
+ section footer,
342
+ section footer button,
343
+ section footer a,
344
+ section footer button *,
345
+ section footer a * {
346
+ background: transparent !important;
347
+ background-color: transparent !important;
348
+ box-shadow: none !important;
349
+ border: none !important;
350
+ color: white !important;
351
  }
352
 
353
  /* ---------- responsive ---------- */
354
  @media (max-width: 768px) {
355
+ .gradio-container {
356
+ padding-top: 120px !important;
357
+ padding-bottom: 160px !important;
358
+ width: 98vw !important;
359
  }
360
 
361
+ .tabs > .tab-nav > button,
362
+ .tab-nav button {
363
+ padding: 8px 14px !important;
364
+ font-size: 0.82rem !important;
 
 
 
 
 
 
 
 
 
365
  }
366
  }
367
 
368
  @media (max-width: 480px) {
369
+ .gradio-container {
370
+ padding-top: 80px !important;
 
371
  }
372
 
373
+ #escp_title h1,
374
+ .gradio-container > .main > div:first-child h1 {
375
+ font-size: 1.8rem !important;
376
  }
377
  }
378
 
379
+ /* ---------- smooth transitions ---------- */
380
+ button, a, input, textarea, select {
381
  transition-property: background, border-color, box-shadow, color, opacity, transform;
382
  transition-duration: 0.2s;
383
  transition-timing-function: ease;
384
  }