elmadany commited on
Commit
4ba8aea
·
verified ·
1 Parent(s): bc36c95

Update public/index.html

Browse files
Files changed (1) hide show
  1. public/index.html +549 -487
public/index.html CHANGED
@@ -1,568 +1,630 @@
1
  <!DOCTYPE html>
2
  <html lang="en">
3
  <head>
4
- <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
  <title>Voice of a Continent | SimbaBench Leaderboard</title>
7
- <link rel="icon" type="image/png" href="https://africa.dlnlp.ai/simba/images/favicon.png">
 
8
  <link rel="preconnect" href="https://fonts.googleapis.com">
9
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
10
- <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=Outfit:wght@600;700;800&display=swap" rel="stylesheet">
11
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
 
12
  <style>
13
  :root {
14
- /* Background colors */
15
- --bg-deep: #1e1b4b;
16
- --bg-darker: #0f172a;
17
- --bg-card: rgba(255, 255, 255, 0.05);
18
-
19
- /* Text colors */
20
- --text-yellow: #fbbf24;
21
  --text-white: #ffffff;
22
- --text-gray: #94a3b8;
23
-
24
- /* Brand colors */
25
  --simba-navy: #0f172a;
26
  --border-gold: #dca02a;
27
-
28
- /* Button gradients - matching the hero buttons */
29
- --grad-red: linear-gradient(135deg, #ef4444, #dc2626);
30
- --grad-indigo: linear-gradient(135deg, #6366f1, #4f46e5);
31
- --grad-orange: linear-gradient(135deg, #f97316, #ea580c);
32
- --grad-blue: linear-gradient(135deg, #3b82f6, #2563eb);
33
- --grad-green: linear-gradient(135deg, #22c55e, #16a34a);
34
- --grad-dark: linear-gradient(135deg, #374151, #1f2937);
35
- }
 
 
 
 
36
 
37
- * {
38
- margin: 0;
39
- padding: 0;
40
- box-sizing: border-box;
41
  }
42
 
43
  body {
44
  background-color: var(--bg-deep);
45
  font-family: 'Inter', sans-serif;
46
  color: var(--text-white);
 
47
  overflow-x: hidden;
48
- line-height: 1.6;
49
- }
50
 
51
- h1, h2, h3 {
52
- font-family: 'Outfit', sans-serif;
53
- font-weight: 700;
54
  }
55
 
56
- a {
57
- text-decoration: none;
58
- transition: all 0.3s ease;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
 
61
- /* Header Section */
62
- .header {
63
- text-align: center;
64
- padding: 60px 20px 40px;
65
- background: linear-gradient(180deg, var(--bg-darker) 0%, var(--bg-deep) 100%);
66
- border-bottom: 1px solid rgba(255, 255, 255, 0.1);
67
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
 
69
- .logo {
70
- display: flex;
71
- align-items: center;
72
- justify-content: center;
73
- gap: 15px;
74
- margin-bottom: 20px;
75
- }
76
 
77
- .logo img {
78
- width: 60px;
79
- height: 60px;
80
- filter: drop-shadow(0 0 20px rgba(251, 191, 36, 0.3));
81
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
 
83
- .logo-text {
84
- text-align: left;
85
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
 
87
- .logo-text h1 {
88
- font-size: 2rem;
89
- font-weight: 800;
90
- line-height: 1.2;
91
- }
92
 
93
- .logo-text .highlight {
94
- color: var(--text-yellow);
95
- }
 
 
 
 
 
 
 
 
96
 
97
- .subtitle {
98
- font-size: 1.1rem;
99
- color: var(--text-gray);
100
- margin-bottom: 30px;
101
- max-width: 800px;
102
- margin-left: auto;
103
- margin-right: auto;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
  }
105
 
106
- /* Action Buttons */
107
- .action-buttons {
108
- display: flex;
109
- flex-wrap: wrap;
110
- gap: 15px;
111
- justify-content: center;
112
- margin-top: 30px;
 
 
 
113
  }
114
 
115
- .action-btn {
116
- padding: 14px 28px;
117
- border-radius: 50px;
118
- color: white;
119
- font-weight: 600;
120
- font-size: 0.95rem;
121
- display: inline-flex;
122
- align-items: center;
123
- gap: 10px;
124
- transition: all 0.3s ease;
125
- border: none;
126
- cursor: pointer;
127
- box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
128
- }
 
 
 
 
129
 
130
- .action-btn:hover {
131
- transform: translateY(-3px);
132
- box-shadow: 0 8px 25px rgba(0, 0, 0, 0.3);
133
- }
 
 
 
 
 
 
134
 
135
- .action-btn i {
136
- font-size: 1.1rem;
137
- }
 
 
 
 
 
 
 
 
 
 
 
138
 
139
- .btn-red { background: var(--grad-red); }
140
- .btn-indigo { background: var(--grad-indigo); }
141
- .btn-orange { background: var(--grad-orange); }
142
- .btn-blue { background: var(--grad-blue); }
143
- .btn-green { background: var(--grad-green); }
144
- .btn-dark { background: var(--grad-dark); }
145
-
146
- /* Main Content */
147
- .container {
148
- max-width: 1400px;
149
- margin: 0 auto;
150
- padding: 40px 20px;
151
- }
152
 
153
- .section-title {
154
- text-align: center;
155
- margin-bottom: 30px;
156
- font-size: 2rem;
157
- }
158
 
159
- .section-title .highlight {
160
- color: var(--text-yellow);
161
- }
162
 
163
- /* Stats Cards */
164
- .stats-grid {
165
- display: grid;
166
- grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
167
- gap: 20px;
168
- margin: 40px 0;
169
- }
 
 
 
 
170
 
171
- .stat-card {
172
- background: var(--bg-card);
173
- border: 1px solid rgba(255, 255, 255, 0.1);
174
- border-radius: 16px;
175
- padding: 30px;
176
- text-align: center;
177
- transition: all 0.3s ease;
178
- backdrop-filter: blur(10px);
179
- }
180
 
181
- .stat-card:hover {
182
- transform: translateY(-5px);
183
- border-color: var(--text-yellow);
184
- box-shadow: 0 10px 30px rgba(251, 191, 36, 0.2);
185
- }
186
 
187
- .stat-card .icon {
188
- font-size: 3rem;
189
- margin-bottom: 15px;
190
- color: var(--text-yellow);
191
- }
192
 
193
- .stat-card .value {
194
- font-size: 2.5rem;
195
- font-weight: 800;
196
- color: var(--text-white);
197
- margin-bottom: 10px;
198
- }
199
 
200
- .stat-card .label {
201
- font-size: 0.9rem;
202
- color: var(--text-gray);
203
- text-transform: uppercase;
204
- letter-spacing: 1px;
205
- font-weight: 600;
206
- }
207
 
208
- /* Leaderboard Table */
209
- .leaderboard-section {
210
- background: var(--bg-card);
211
- border: 1px solid rgba(255, 255, 255, 0.1);
212
- border-radius: 20px;
213
- padding: 40px;
214
- margin: 40px 0;
215
- backdrop-filter: blur(10px);
216
- }
217
 
218
- .table-container {
219
- overflow-x: auto;
220
- }
221
 
222
- table {
223
- width: 100%;
224
- border-collapse: collapse;
225
- margin-top: 20px;
226
- }
227
 
228
- thead {
229
- background: rgba(255, 255, 255, 0.05);
230
- }
231
 
232
- th {
233
- padding: 16px;
234
- text-align: left;
235
- font-weight: 600;
236
- color: var(--text-yellow);
237
- border-bottom: 2px solid rgba(251, 191, 36, 0.3);
238
- text-transform: uppercase;
239
- font-size: 0.85rem;
240
- letter-spacing: 1px;
241
- }
242
 
243
- td {
244
- padding: 16px;
245
- border-bottom: 1px solid rgba(255, 255, 255, 0.1);
246
- }
247
 
248
- tr:hover {
249
- background: rgba(255, 255, 255, 0.03);
250
- }
251
 
252
- .rank-badge {
253
- display: inline-block;
254
- width: 30px;
255
- height: 30px;
256
- background: var(--grad-orange);
257
- border-radius: 50%;
258
- text-align: center;
259
- line-height: 30px;
260
- font-weight: 700;
261
- }
262
 
263
- .model-name {
264
- font-weight: 600;
265
- color: var(--text-white);
266
- }
267
 
268
- .score {
269
- font-weight: 700;
270
- color: var(--text-yellow);
271
- font-size: 1.1rem;
272
- }
273
 
274
- /* Footer */
275
- .footer {
276
- text-align: center;
277
- padding: 40px 20px;
278
- border-top: 1px solid rgba(255, 255, 255, 0.1);
279
- margin-top: 60px;
280
- color: var(--text-gray);
281
- }
282
 
283
- .footer a {
284
- color: var(--text-yellow);
285
- }
286
 
287
- .footer a:hover {
288
- text-decoration: underline;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
289
  }
290
 
291
- /* Responsive Design */
292
- @media (max-width: 768px) {
293
- .logo-text h1 {
294
- font-size: 1.5rem;
295
- }
296
 
297
- .action-buttons {
298
- flex-direction: column;
299
- align-items: stretch;
300
- }
301
 
302
- .action-btn {
303
- justify-content: center;
304
- }
305
 
306
- .section-title {
307
- font-size: 1.5rem;
308
- }
309
 
310
- .stat-card .value {
311
- font-size: 2rem;
312
- }
313
 
314
- .leaderboard-section {
315
- padding: 20px;
316
- }
317
 
318
- th, td {
319
- padding: 12px 8px;
320
- font-size: 0.9rem;
321
- }
322
- }
323
- </style>
324
- </head>
325
- <body>
326
- <!-- Header -->
327
- <div class="header">
328
- <div class="logo">
329
- <img src="https://africa.dlnlp.ai/simba/images/simba_main_logo.png" alt="SimbaBench Logo">
330
- <div class="logo-text">
331
- <h1>Voice of a <span class="highlight">Continent</span></h1>
332
- </div>
333
- </div>
334
-
335
- <p class="subtitle">
336
- The largest open-source benchmark for African speech technology, featuring state-of-the-art models for 61 African languages across ASR, TTS, and SLID tasks.
337
- </p>
338
-
339
- <div class="action-buttons">
340
- <a href="https://aclanthology.org/2025.emnlp-main.559/" target="_blank" class="action-btn btn-red">
341
- <i class="fa-regular fa-file-pdf"></i> Read Paper
342
- </a>
343
- <a href="https://africa.dlnlp.ai/simba/" target="_blank" class="action-btn btn-indigo">
344
- <i class="fa-solid fa-globe"></i> Official Website
345
- </a>
346
- <a href="https://huggingface.co/collections/UBC-NLP/simba-speech-series" target="_blank" class="action-btn btn-orange">
347
- <i class="fa-solid fa-robot"></i> Simba Models
348
- </a>
349
- <a href="https://github.com/UBC-NLP/simba" target="_blank" class="action-btn btn-dark">
350
- <i class="fa-brands fa-github"></i> GitHub
351
- </a>
352
- </div>
353
- </div>
354
 
355
- <!-- Main Content -->
356
- <div class="container">
357
- <!-- Stats Section -->
358
- <div class="stats-grid">
359
- <div class="stat-card">
360
- <div class="icon">🌍</div>
361
- <div class="value">61</div>
362
- <div class="label">Languages</div>
363
- </div>
364
- <div class="stat-card">
365
- <div class="icon">🎙️</div>
366
- <div class="value">8,605</div>
367
- <div class="label">Hours of Data</div>
368
- </div>
369
- <div class="stat-card">
370
- <div class="icon">🤖</div>
371
- <div class="value">12</div>
372
- <div class="label">Models</div>
373
- </div>
374
- <div class="stat-card">
375
- <div class="icon">📊</div>
376
- <div class="value">3</div>
377
- <div class="label">Tasks</div>
378
- </div>
379
- </div>
380
 
381
- <!-- Leaderboard Section -->
382
- <h2 class="section-title">Interactive <span class="highlight">Leaderboard</span></h2>
383
-
384
- <div class="leaderboard-section">
385
- <h3 style="margin-bottom: 20px;">ASR Models - Word Error Rate (WER) ↓</h3>
386
- <div class="table-container">
387
- <table>
388
- <thead>
389
- <tr>
390
- <th>Rank</th>
391
- <th>Model</th>
392
- <th>Languages</th>
393
- <th>WER Score</th>
394
- <th>Parameters</th>
395
- </tr>
396
- </thead>
397
- <tbody>
398
- <tr>
399
- <td><span class="rank-badge">1</span></td>
400
- <td class="model-name">Simba-S</td>
401
- <td>42</td>
402
- <td class="score">15.2%</td>
403
- <td>2B</td>
404
- </tr>
405
- <tr>
406
- <td><span class="rank-badge">2</span></td>
407
- <td class="model-name">Simba-W</td>
408
- <td>42</td>
409
- <td class="score">16.8%</td>
410
- <td>2B</td>
411
- </tr>
412
- <tr>
413
- <td><span class="rank-badge">3</span></td>
414
- <td class="model-name">Simba-M</td>
415
- <td>42</td>
416
- <td class="score">18.5%</td>
417
- <td>1B</td>
418
- </tr>
419
- <tr>
420
- <td><span class="rank-badge">4</span></td>
421
- <td class="model-name">Simba-H</td>
422
- <td>42</td>
423
- <td class="score">20.1%</td>
424
- <td>500M</td>
425
- </tr>
426
- <tr>
427
- <td><span class="rank-badge">5</span></td>
428
- <td class="model-name">Simba-X</td>
429
- <td>42</td>
430
- <td class="score">22.3%</td>
431
- <td>300M</td>
432
- </tr>
433
- </tbody>
434
- </table>
435
- </div>
436
- </div>
437
 
438
- <div class="leaderboard-section">
439
- <h3 style="margin-bottom: 20px;">TTS Models - Mean Opinion Score (MOS) ↑</h3>
440
- <div class="table-container">
441
- <table>
442
- <thead>
443
- <tr>
444
- <th>Rank</th>
445
- <th>Model</th>
446
- <th>Language</th>
447
- <th>MOS Score</th>
448
- <th>Parameters</th>
449
- </tr>
450
- </thead>
451
- <tbody>
452
- <tr>
453
- <td><span class="rank-badge">1</span></td>
454
- <td class="model-name">Simba-TTS-xho</td>
455
- <td>Xhosa</td>
456
- <td class="score">4.2</td>
457
- <td>36.3M</td>
458
- </tr>
459
- <tr>
460
- <td><span class="rank-badge">2</span></td>
461
- <td class="model-name">Simba-TTS-twi-asanti</td>
462
- <td>Twi (Asanti)</td>
463
- <td class="score">4.1</td>
464
- <td>36.3M</td>
465
- </tr>
466
- <tr>
467
- <td><span class="rank-badge">3</span></td>
468
- <td class="model-name">Simba-TTS-lin</td>
469
- <td>Lingala</td>
470
- <td class="score">4.0</td>
471
- <td>36.3M</td>
472
- </tr>
473
- <tr>
474
- <td><span class="rank-badge">4</span></td>
475
- <td class="model-name">Simba-TTS-sot</td>
476
- <td>Sotho</td>
477
- <td class="score">3.9</td>
478
- <td>36.3M</td>
479
- </tr>
480
- <tr>
481
- <td><span class="rank-badge">5</span></td>
482
- <td class="model-name">Simba-TTS-tsn</td>
483
- <td>Tswana</td>
484
- <td class="score">3.8</td>
485
- <td>36.3M</td>
486
- </tr>
487
- <tr>
488
- <td><span class="rank-badge">6</span></td>
489
- <td class="model-name">Simba-TTS-twi-akuapem</td>
490
- <td>Twi (Akuapem)</td>
491
- <td class="score">3.8</td>
492
- <td>36.3M</td>
493
- </tr>
494
- <tr>
495
- <td><span class="rank-badge">7</span></td>
496
- <td class="model-name">Simba-TTS-afr</td>
497
- <td>Afrikaans</td>
498
- <td class="score">3.7</td>
499
- <td>36.3M</td>
500
- </tr>
501
- </tbody>
502
- </table>
503
- </div>
504
- </div>
505
 
506
- <!-- Dataset Section -->
507
- <div class="leaderboard-section">
508
- <h3 style="margin-bottom: 20px;">📊 Dataset Resources</h3>
509
- <p style="color: var(--text-gray); margin-bottom: 20px;">
510
- Access the complete SimbaBench dataset with 8,605 hours of labeled speech data across 61 African languages.
511
- </p>
512
- <a href="https://huggingface.co/datasets/UBC-NLP/SimbaBench_dataset" target="_blank" class="action-btn btn-orange">
513
- <i class="fa-solid fa-database"></i> Download Dataset
514
- </a>
515
- </div>
516
- </div>
517
 
518
- <!-- Footer -->
519
- <div class="footer">
520
- <p>
521
- Developed by <a href="https://nlp.cs.ubc.ca/" target="_blank">UBC Deep Learning and Natural Language Processing Lab</a>
522
- </p>
523
- <p style="margin-top: 10px;">
524
- © 2025 SimbaBench |
525
- <a href="https://aclanthology.org/2025.emnlp-main.559/" target="_blank">EMNLP 2025</a>
526
- </p>
527
- </div>
528
 
529
- <script>
530
- // Add smooth scroll behavior
531
- document.querySelectorAll('a[href^="#"]').forEach(anchor => {
532
- anchor.addEventListener('click', function (e) {
533
- e.preventDefault();
534
- const target = document.querySelector(this.getAttribute('href'));
535
- if (target) {
536
- target.scrollIntoView({
537
- behavior: 'smooth',
538
- block: 'start'
539
- });
540
- }
541
- });
542
- });
543
 
544
- // Add animation on scroll
545
- const observerOptions = {
546
- threshold: 0.1,
547
- rootMargin: '0px 0px -50px 0px'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
548
  };
549
 
550
- const observer = new IntersectionObserver((entries) => {
551
- entries.forEach(entry => {
552
- if (entry.isIntersecting) {
553
- entry.target.style.opacity = '1';
554
- entry.target.style.transform = 'translateY(0)';
555
- }
 
 
 
 
 
 
 
556
  });
557
- }, observerOptions);
558
-
559
- // Observe all stat cards and leaderboard sections
560
- document.querySelectorAll('.stat-card, .leaderboard-section').forEach(el => {
561
- el.style.opacity = '0';
562
- el.style.transform = 'translateY(20px)';
563
- el.style.transition = 'opacity 0.6s ease, transform 0.6s ease';
564
- observer.observe(el);
565
- });
566
  </script>
567
  </body>
568
  </html>
 
1
  <!DOCTYPE html>
2
  <html lang="en">
3
  <head>
4
+ <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
  <title>Voice of a Continent | SimbaBench Leaderboard</title>
7
+ <link rel="icon" type="image/jpeg" href="https://africa.dlnlp.ai/simba/images/favicon.png">
8
+
9
  <link rel="preconnect" href="https://fonts.googleapis.com">
10
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
11
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=Rubik:wght@500;600;700;800&display=swap" rel="stylesheet">
12
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
13
+
14
  <style>
15
  :root {
16
+ --bg-deep: #1e1b4b;
17
+ --text-yellow: #fbbf24;
18
+
19
+
20
+
21
+
22
+
23
  --text-white: #ffffff;
24
+
25
+
26
+
27
  --simba-navy: #0f172a;
28
  --border-gold: #dca02a;
29
+ --grad-blue: linear-gradient(135deg, #3b82f6, #0ea5e9);
30
+ --grad-red: linear-gradient(135deg, #ef4444, #f43f5e);
31
+ --grad-purple: linear-gradient(135deg, #6366f1, #8b5cf6);
32
+ --grad-orange: linear-gradient(135deg, #f97316, #fb923c);
33
+ --grad-green: linear-gradient(135deg, #22c55e, #10b981);
34
+
35
+
36
+
37
+
38
+
39
+
40
+
41
+
42
 
 
 
 
 
43
  }
44
 
45
  body {
46
  background-color: var(--bg-deep);
47
  font-family: 'Inter', sans-serif;
48
  color: var(--text-white);
49
+ margin: 0; padding: 0;
50
  overflow-x: hidden;
 
 
51
 
 
 
 
52
  }
53
 
54
+ a { text-decoration: none; transition: 0.2s; }
55
+
56
+ /* --- NAVBAR --- */
57
+ .navbar { padding: 20px 40px; display: flex; justify-content: space-between; align-items: center; position: relative; z-index: 100; }
58
+ .nav-logo { color: white; font-family: 'Rubik', sans-serif; font-weight: 700; font-size: 22px; display: flex; align-items: center; gap: 12px; }
59
+ .nav-logo img { height: 40px; }
60
+ .nav-text { display: flex; flex-direction: column; line-height: 1.1; }
61
+ .nav-text span:first-child { font-size: 14px; color: var(--text-yellow); }
62
+ .nav-links { display: flex; gap: 25px; align-items: center; }
63
+ .btn-submit { background: var(--grad-blue); color: white !important; padding: 10px 24px; border-radius: 30px; font-weight: 600; font-size: 14px; box-shadow: 0 4px 12px rgba(59, 130, 246, 0.4); }
64
+
65
+ /* --- HERO --- */
66
+ .hero { max-width: 1000px; margin: 60px auto 100px; padding: 0 40px; position: relative; text-align: center; }
67
+ .hero-content { z-index: 2; display: flex; flex-direction: column; align-items: center; }
68
+ .conf-badge { background: white; color: black; display: inline-flex; align-items: center; gap: 10px; padding: 6px 16px; border-radius: 8px; margin-bottom: 30px; font-weight: 700; font-size: 14px; }
69
+ .conf-badge i { color: #cc0000; font-size: 18px; }
70
+ .hero h1 { font-family: 'Rubik', sans-serif; font-size: 64px; font-weight: 800; margin: 0; line-height: 1.1; }
71
+ .hero h2 { font-family: 'Rubik', sans-serif; font-size: 32px; color: var(--text-yellow); margin: 15px 0 30px; font-weight: 700; }
72
+ .hero p { color: #cbd5e1; font-size: 18px; line-height: 1.6; max-width: 700px; margin-bottom: 50px; }
73
+ .hero-actions { display: flex; gap: 15px; flex-wrap: wrap; justify-content: center; }
74
+ .action-btn { display: flex; align-items: center; gap: 8px; padding: 12px 24px; border-radius: 30px; color: white; font-weight: 600; font-size: 15px; transition: transform 0.2s; }
75
+ .action-btn:hover { transform: translateY(-3px); color: white; }
76
+ .bg-red { background: var(--grad-red); } .bg-purple { background: var(--grad-purple); }
77
+
78
+ /* --- CONTENT --- */
79
+ .content-container { width: 80%; max-width: 1600px; margin: 0 auto; }
80
+ .main-card { background: white; border-radius: 24px; padding: 40px; color: #0f172a; min-height: 600px; position: relative; z-index: 10; margin-bottom: 60px; }
81
+
82
+ /* Tabs */
83
+ .tabs { display: flex; gap: 10px; border-bottom: 2px solid #e2e8f0; margin-bottom: 30px; padding-bottom: 10px; overflow-x: auto; }
84
+ .tab-btn { background: none; border: none; font-size: 15px; font-weight: 600; color: #64748b; padding: 10px 20px; cursor: pointer; transition: 0.3s; border-radius: 8px; white-space: nowrap; }
85
+ .tab-btn:hover { background: #f1f5f9; color: var(--bg-deep); }
86
+ .tab-btn.active { background: var(--bg-deep); color: white; }
87
+ .view { display: none !important; animation: fadeIn 0.4s; }
88
+ .view.active { display: block !important; }
89
+
90
+ /* Controls */
91
+ .controls { background: #f8fafc; padding: 20px; border-radius: 12px; display: flex; gap: 20px; align-items: center; margin-bottom: 20px; flex-wrap: wrap; }
92
+ select { padding: 10px; border-radius: 8px; border: 1px solid #cbd5e1; font-size: 14px; min-width: 250px; cursor:pointer; }
93
+ .rank-info { font-size: 13px; color: #64748b; margin-top: 5px; font-style: italic; }
94
+ .score-desc { font-size: 14px; color: #475569; background: #fff7ed; border-left: 4px solid #f97316; padding: 10px 15px; margin-bottom: 20px; border-radius: 4px; }
95
+
96
+ /* ASR Buttons */
97
+ .mode-btn { padding: 8px 20px; border-radius: 8px; font-weight: 600; font-size: 13px; cursor: pointer; transition: all 0.2s; border: 1px solid #e2e8f0; background: white; color: var(--simba-navy); }
98
+ .mode-btn:hover { border-color: var(--text-yellow); color: var(--text-yellow); }
99
+ .mode-btn.active { background-color: var(--simba-navy); color: white; border-color: var(--simba-navy); box-shadow: 0 4px 12px rgba(15, 23, 42, 0.15); }
100
+
101
+ /* --- FANCY SUMMARY CARDS --- */
102
+ .summary-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 25px; margin-bottom: 50px; }
103
+
104
+ .fancy-card {
105
+ background: white; border-radius: 16px; padding: 25px;
106
+ display: flex; align-items: center; gap: 20px;
107
+ box-shadow: 0 10px 25px -5px rgba(0,0,0,0.08); border: 1px solid #f1f5f9;
108
+ transition: transform 0.3s ease, box-shadow 0.3s ease;
109
  }
110
+ .fancy-card:hover { transform: translateY(-5px); box-shadow: 0 20px 30px -10px rgba(0,0,0,0.12); border-color: #e2e8f0; }
111
+
112
+ .card-icon {
113
+ width: 60px; height: 60px; border-radius: 14px;
114
+ display: flex; align-items: center; justify-content: center;
115
+ font-size: 26px; color: white; flex-shrink: 0;
116
+ box-shadow: 0 8px 15px -3px rgba(0,0,0,0.2);
117
+ }
118
+ .icon-asr { background: var(--grad-blue); }
119
+ .icon-tts { background: var(--grad-orange); }
120
+ .icon-slid { background: var(--grad-green); }
121
+
122
+ .card-content { flex: 1; }
123
+ .card-title { font-size: 11px; font-weight: 700; color: #64748b; text-transform: uppercase; letter-spacing: 1px; margin-bottom: 5px; }
124
+ .card-model { font-size: 18px; font-weight: 800; color: #0f172a; margin-bottom: 4px; line-height: 1.3; }
125
+ .card-score { font-size: 14px; font-weight: 600; color: #475569; }
126
+ .card-score b { color: #0f172a; }
127
+
128
+ /* Table */
129
+ .table-wrap { overflow-x: auto; border: 1px solid #e2e8f0; border-radius: 12px; margin-bottom: 30px; }
130
+ table { width: 100%; border-collapse: collapse; font-size: 14px; }
131
+ th { background: #f1f5f9; color: #0f172a; font-weight: 700; padding: 16px; text-align: center; border-bottom: 2px solid #e2e8f0; white-space: nowrap; vertical-align: bottom; }
132
+ td { padding: 14px; border-bottom: 1px solid #e2e8f0; text-align: center; color: #334155; }
133
+ tr:hover td { background: #f8fafc; }
134
+ th:first-child, td:first-child { position: sticky; left: 0; background: white; z-index: 2; text-align: left; font-weight: 700; color: #0f172a; border-right: 2px solid #f1f5f9; min-width: 220px; }
135
+ thead th:first-child { background: #f1f5f9; z-index: 3; }
136
+ th:nth-child(2), td:nth-child(2) { text-align: left; }
137
+ h4 { color: var(--text-yellow); font-family: 'Rubik', sans-serif; font-size: 18px; margin: 0 0 15px 0; border-bottom: 1px solid #eee; padding-bottom: 10px; }
138
+
139
+ /* Citations */
140
+ .citation-section { background: #0f172a; border: 1px solid #334155; border-radius: 16px; padding: 40px; box-sizing: border-box; box-shadow: 0 20px 40px rgba(0,0,0,0.3); position: relative; margin-bottom: 60px; }
141
+ .citation-section h3 { color: var(--text-yellow); font-family: 'Rubik', sans-serif; font-size: 24px; margin-top: 0; }
142
+ .citation-box { background: #1e293b; color: #cbd5e1; padding: 20px; border-radius: 12px; font-family: monospace; white-space: pre-wrap; margin-top: 20px; overflow-x: auto; border: 1px solid #334155; font-size: 13px; line-height: 1.5; }
143
+ .copy-btn { position: absolute; top: 40px; right: 40px; background: var(--text-yellow); border: none; padding: 8px 16px; border-radius: 6px; font-weight: bold; cursor: pointer; color: #0f172a; }
144
+
145
+ .footer { text-align: center; padding: 40px; color: #94a3b8; font-size: 14px; }
146
+ @keyframes fadeIn { from{opacity:0; transform:translateY(10px)} to{opacity:1; transform:translateY(0)} }
147
+
148
+ .arrow-down { color: #d97706; font-size: 10px; }
149
+ .arrow-up { color: #16a34a; font-size: 10px; }
150
+ .empty-msg { color: #64748b; font-style: italic; padding: 20px; text-align: center; }
151
+ </style>
152
+ </head>
153
+ <body>
154
 
155
+ <nav class="navbar layout-width">
156
+ <a href="https://africa.dlnlp.ai/simba" class="nav-logo">
157
+ <img src="https://africa.dlnlp.ai/simba/images/simba_main_logo.png" alt="Logo">
158
+ <div class="nav-text"><span>Voice of a</span> Continent</div>
159
+ </a>
160
+ <div class="nav-links">
161
+ <!-- <a href="https://aclanthology.org/2025.emnlp-main.559" target="_blank" class="nav-link">Paper</a>
162
+ <a href="https://africa.dlnlp.ai/simba/" target="_blank" class="btn-submit">Submit New Results</a> -->
163
+ </div>
164
+ </nav>
165
+
166
+ <div class="hero layout-width">
167
+ <div class="hero-content">
168
+ <div class="conf-badge"><i class="fa-solid fa-location-dot"></i> EMNLP 2025 · Suzhou, China</div>
169
+ <h1>SimbaBench Leaderboard</h1>
170
+ <h2>Mapping Africa’s Speech Technology</h2>
171
+ <p>SimbaBench bridges the digital divide with a unified suite for African AI: the largest open-source speech benchmark covering 61 languages.</p>
172
+ <div class="hero-actions">
173
+ <a href="https://aclanthology.org/2025.emnlp-main.559" target="_blank" class="action-btn bg-red"><i class="fa-regular fa-file-pdf"></i> Read Paper</a>
174
+ <a href="https://africa.dlnlp.ai/simba" target="_blank" class="action-btn bg-indigo"><i class="fa-solid fa-globe"></i> Official Website</a>
175
+ <a href="https://huggingface.co/collections/UBC-NLP/simba-speech-series" target="_blank" class="action-btn bg-orange"><i class="fa-solid fa-robot"></i> Simba Model Series</a>
176
+ <a href="https://github.com/UBC-NLP/simba" target="_blank" class="action-btn bg-gray"><i class="fa-brands fa-github"></i> GitHub</a>
177
+
178
+ </div>
179
+ </div>
180
+ </div>
181
 
182
+ <div class="content-container layout-width">
183
+ <div class="main-card" id="board">
184
+ <div id="loader" style="text-align:center; padding:60px; color:#64748b;">
185
+ <i class="fa-solid fa-circle-notch fa-spin fa-3x"></i><br><br>Loading Leaderboard Data...
186
+ </div>
 
 
187
 
188
+ <div id="app-content" style="display:none;">
189
+ <div class="tabs">
190
+ <button class="tab-btn active" id="tab-btn-asr" onclick="setTab('asr')">Automatic Speech Recognition (ASR)</button>
191
+ <button class="tab-btn" id="tab-btn-tts" onclick="setTab('tts')">Text-to-Speech (TTS)</button>
192
+ <button class="tab-btn" id="tab-btn-slid" onclick="setTab('slid')">Spoken Language Identification (SLID)</button>
193
+ <button class="tab-btn" id="tab-btn-lang" onclick="setTab('lang')">Language Analysis</button>
194
+ </div>
195
+
196
+ <div id="asr" class="view active">
197
+ <div class="controls">
198
+ <span style="font-weight:700;">View Mode:</span>
199
+ <button id="btn-over" class="mode-btn active" onclick="setASRMode('overview')">Overview</button>
200
+ <button id="btn-fam" class="mode-btn" onclick="setASRMode('family')">By Family</button>
201
+ <button id="btn-mod" class="mode-btn" onclick="setASRMode('model')">By Model</button>
202
+
203
+ <div style="flex-grow:1; text-align:right;">
204
+ <div id="grp-fam" style="display:none;"><label>Select Family: </label><select id="asr-select-fam" onchange="renderASR()"></select></div>
205
+ <div id="grp-mod" style="display:none;"><label>Select Model: </label><select id="asr-select-mod" onchange="renderASR()"></select></div>
206
+ </div>
207
+ </div>
208
+
209
+ <div style="display:flex; justify-content:space-between; align-items:end; margin-bottom:10px;">
210
+ <h3 id="asr-title" style="color:#d97706; margin:0;">Results Overview</h3>
211
+ <div id="asr-rank-info" class="rank-info">Ranking: WER (↓) then CER (↓)</div>
212
+ </div>
213
+ <div id="asr-desc"></div>
214
+ <div id="asr-table" class="table-wrap"></div>
215
+ </div>
216
+
217
+ <div id="tts" class="view">
218
+ <div class="controls">
219
+ <span style="font-weight:600;">Select Model:</span>
220
+ <select id="tts-select" onchange="renderTTS()"></select>
221
+ </div>
222
+ <h3 id="tts-title" style="color:#d97706; margin-bottom:10px;"></h3>
223
+ <div id="tts-summary" style="margin-bottom:20px; font-weight:600; color:#0f172a;"></div>
224
+ <div id="tts-table" class="table-wrap"></div>
225
+ </div>
226
+
227
+ <div id="slid" class="view">
228
+ <div style="display:flex; justify-content:space-between; align-items:end; margin-bottom:15px;">
229
+ <h3 style="color:#d97706; margin:0;">Spoken Language Identification</h3>
230
+ <div class="rank-info">Ranking: F1-Macro (↑)</div>
231
+ </div>
232
+ <div id="slid-table" class="table-wrap"></div>
233
+ </div>
234
+
235
+ <div id="lang" class="view">
236
+ <div class="controls">
237
+ <span style="font-weight:600;">Select Language:</span>
238
+ <select id="lang-select" onchange="renderLanguageView()"></select>
239
+ </div>
240
+
241
+ <div id="lang-summary" class="summary-grid"></div>
242
+
243
+ <h4>Automatic Speech Recognition (ASR) <span class="rank-info" style="font-weight:normal;">(Ranked by WER ↓, then CER ↓)</span></h4>
244
+ <div id="lang-asr-table" class="table-wrap"></div>
245
+
246
+ <h4>Text-to-Speech (TTS) Results</h4>
247
+ <div id="lang-tts-table" class="table-wrap"></div>
248
+
249
+ <h4>Spoken Language Identification (SLID) Results <span class="rank-info" style="font-weight:normal;">(Ranked by Score ↑)</span></h4>
250
+ <div id="lang-slid-table" class="table-wrap"></div>
251
+ </div>
252
+ </div>
253
+ </div>
254
 
255
+ <div class="citation-section layout-width" id="citation">
256
+ <h3>Citation</h3>
257
+ <button class="copy-btn" onclick="copyCitation()"><i class="fa-regular fa-copy"></i> Copy</button>
258
+ <p style="color:#94a3b8; margin-bottom:20px;">If you use the Simba benchmark, please cite our paper:</p>
259
+ <div class="citation-box" id="bibtex">@inproceedings{elmadany-etal-2025-voice,
260
+ title = "Voice of a Continent: Mapping {A}frica{'}s Speech Technology Frontier",
261
+ author = "Elmadany, AbdelRahim A. and Kwon, Sang Yun and Toyin, Hawau Olamide and Alcoba Inciarte, Alcides and Aldarmaki, Hanan and Abdul-Mageed, Muhammad",
262
+ editor = "Christodoulopoulos, Christos and Chakraborty, Tanmoy and Rose, Carolyn and Peng, Violet",
263
+ booktitle = "Proceedings of the 2025 Conference on Empirical Methods in Natural Language Processing",
264
+ month = nov,
265
+ year = "2025",
266
+ address = "Suzhou, China",
267
+ publisher = "Association for Computational Linguistics",
268
+ url = "https://aclanthology.org/2025.emnlp-main.559/",
269
+ doi = "10.18653/v1/2025.emnlp-main.559",
270
+ pages = "11039--11061",
271
+ ISBN = "979-8-89176-332-6",
272
+ }</div>
273
+ </div>
274
+ </div>
275
 
276
+ <div class="footer">
277
+ <img src="https://africa.dlnlp.ai/sahara//img/sahara_web_sponsers.jpg" width="250" style="opacity:0.8; margin-bottom:15px;">
278
+ <br>&copy; 2025 Simba Benchmark.
279
+ </div>
 
280
 
281
+ <script>
282
+ const NAME_TO_ISO = {'Afrikaans':'afr', 'Akuapim-twi':'ak', 'Amharic':'amh', 'Asante-twi':'tw', 'Bemba':'bem', 'Hausa':'hau', 'Igbo':'ibo', 'Yoruba':'yor', 'Zulu':'zul', 'Swahili':'swa', 'Somali':'som', 'Wolof':'wol', 'Xhosa':'xho'};
283
+ let DATA = null;
284
+ let asrMode = 'overview';
285
+
286
+ fetch('/api/data').then(r=>r.json()).then(d=>{
287
+ DATA = d;
288
+ document.getElementById('loader').style.display='none';
289
+ document.getElementById('app-content').style.display='block';
290
+ init();
291
+ });
292
 
293
+ function init() {
294
+ populate('asr-select-fam', DATA.metadata.families);
295
+ populate('asr-select-mod', DATA.metadata.models);
296
+ populate('tts-select', DATA.metadata.tts_models);
297
+
298
+ const allLangs = new Set();
299
+ // Collect languages from all sources to be thorough
300
+ Object.values(DATA.asr.by_model).forEach(rows => rows.forEach(r => { if(r.Language) allLangs.add(r.Language); }));
301
+ Object.values(DATA.tts).forEach(rows => rows.forEach(r => { const l = r.Language || r.language; if(l) allLangs.add(l); }));
302
+ if(DATA.slid) DATA.slid.forEach(r => { if(r.Language) allLangs.add(r.Language); });
303
+
304
+ populate('lang-select', Array.from(allLangs).sort());
305
+
306
+ renderASR(); renderTTS(); renderSLID();
307
+ }
308
+
309
+ function populate(id, list) {
310
+ const s = document.getElementById(id); s.innerHTML='';
311
+ list.forEach(i=>{ let o=document.createElement('option'); o.value=i; o.text=i; s.add(o); });
312
+ }
313
+ function fmt(n) { return (n==null)?'N/A':n.toFixed(2); }
314
+ function getIso(name, dataIso) {
315
+ let iso = dataIso || NAME_TO_ISO[name] || name.substring(0,3).toLowerCase();
316
+ return `${name} (${iso})`;
317
+ }
318
+
319
+ // --- ASR ---
320
+ function renderASR() {
321
+ const div = document.getElementById('asr-table');
322
+ const title = document.getElementById('asr-title');
323
+ const desc = document.getElementById('asr-desc');
324
+ let html='';
325
+
326
+ if (asrMode === 'overview') {
327
+ title.innerText = "Results Overview (All Models)";
328
+ desc.innerHTML = `<p class="score-desc">The <b>Simba ASR Score</b> is the global average of WER and CER across all languages in the benchmark.</p>`;
329
+ document.getElementById('grp-fam').style.display='none';
330
+ document.getElementById('grp-mod').style.display='none';
331
+
332
+ const modelStats = [];
333
+ Object.keys(DATA.asr.by_model).forEach(modName => {
334
+ const rows = DATA.asr.by_model[modName];
335
+ let sW=0, sC=0, n=0;
336
+ rows.forEach(r => { sW+=r.WER; sC+=r.CER; n++; });
337
+ if(n>0) modelStats.push({ name: modName, wer: sW/n, cer: sC/n });
338
+ });
339
+
340
+ modelStats.sort((a,b) => (a.wer - b.wer) || (a.cer - b.cer));
341
+ html = `<table><thead><tr><th>Model</th><th>Simba ASR Score (WER/CER) <i class="fa-solid fa-arrow-down arrow-down"></i></th></tr></thead><tbody>`;
342
+
343
+ let currentRank = 1;
344
+ modelStats.forEach((m, i) => {
345
+ if (i > 0 && Math.abs(m.wer - modelStats[i-1].wer) > 0.001) currentRank = i + 1; else currentRank = 1;
346
+ let icon = (currentRank===1)?'🥇 ':(currentRank===2)?'🥈 ':(currentRank===3)?'🥉 ':'';
347
+ html += `<tr><td style="font-weight:600; color:var(--simba-navy)">${icon}${m.name}</td><td><b>${fmt(m.wer)} / ${fmt(m.cer)}</b></td></tr>`;
348
+ });
349
+
350
+ } else if(asrMode==='family'){
351
+ const val = document.getElementById('asr-select-fam').value;
352
+ title.innerText = `Results for Family: ${val}`;
353
+ desc.innerHTML = `<p class="score-desc">The <b>Family Score</b> is the average WER and CER calculated across all languages within the <b>${val}</b> family.</p>`;
354
+ document.getElementById('grp-fam').style.display='inline-block';
355
+ document.getElementById('grp-mod').style.display='none';
356
+
357
+ const d = DATA.asr.by_family[val];
358
+ if(!d) return;
359
+ d.data.sort((a,b) => a.Avg_WER - b.Avg_WER);
360
+
361
+ html = `<table><thead><tr><th>Model</th><th>Simba ASR Family Score <i class="fa-solid fa-arrow-down arrow-down"></i></th>`;
362
+ d.languages.forEach(l => html += `<th>${getIso(l.name, l.iso)}</th>`);
363
+ html += `</tr></thead><tbody>`;
364
+
365
+ let currentRank = 1;
366
+ d.data.forEach((r, idx) => {
367
+ if(idx > 0 && Math.abs(r.Avg_WER - d.data[idx-1].Avg_WER) > 0.001) currentRank = idx + 1; else currentRank = 1;
368
+ let icon = (currentRank===1)?'🥇 ':(currentRank===2)?'🥈 ':(currentRank===3)?'🥉 ':'';
369
+ html += `<tr><td style="font-weight:600; color:var(--simba-navy)">${icon}${r.Model}</td><td style="font-weight:bold; background:#f8fafc">${fmt(r.Avg_WER)} / ${fmt(r.Avg_CER)}</td>`;
370
+ d.languages.forEach(l => {
371
+ let w=r[`WER_${l.name}`], c=r[`CER_${l.name}`];
372
+ html += `<td>${(w!=null)?fmt(w)+'/'+fmt(c):'-'}</td>`;
373
+ });
374
+ html += `</tr>`;
375
+ });
376
+ } else {
377
+ const val = document.getElementById('asr-select-mod').value;
378
+ title.innerText = `Results for Model: ${val}`;
379
+ desc.innerHTML = "";
380
+ document.getElementById('grp-fam').style.display='none';
381
+ document.getElementById('grp-mod').style.display='inline-block';
382
+
383
+ const rows = DATA.asr.by_model[val];
384
+ html = `<table><thead><tr><th>Language</th><th>Family</th><th>WER <i class="fa-solid fa-arrow-down arrow-down"></i></th><th>CER <i class="fa-solid fa-arrow-down arrow-down"></i></th></tr></thead><tbody>`;
385
+ rows.forEach(r => {
386
+ html += `<tr><td>${getIso(r.Language, r.ISO)}</td><td>${r.Family}</td><td>${fmt(r.WER)}</td><td>${fmt(r.CER)}</td></tr>`;
387
+ });
388
+ }
389
+ div.innerHTML = html;
390
+ }
391
+
392
+ // --- TTS ---
393
+ function renderTTS() {
394
+ const val = document.getElementById('tts-select').value;
395
+ document.getElementById('tts-title').innerText = `Model: ${val}`;
396
+ const rows = DATA.tts[val];
397
+ if(!rows) return;
398
+
399
+ const metrics = [
400
+ {k:'wer', l:'WER(↓)', h:false}, {k:'mcd', l:'MCD(↓)', h:false},
401
+ {k:'logf0rmse', l:'LogF0RMSE(↓)', h:false}, {k:'speech_token_distance', l:'SpeechTokenDistance(↓)', h:false},
402
+ {k:'pesq', l:'PESQ(↑)', h:true}, {k:'utmos', l:'UTMOS(↑)', h:true},
403
+ {k:'speechbleu', l:'SpeechBLEU(↑)', h:true}, {k:'speechbert_score', l:'SpeechBERTScore(↑)', h:true}
404
+ ];
405
+
406
+ let sums={}, c=0;
407
+ metrics.forEach(m=>sums[m.k]=0);
408
+ rows.forEach(r=>{ metrics.forEach(m=>sums[m.k]+=(r[m.k]||0)); c++; });
409
+ document.getElementById('tts-summary').innerHTML = "<b>Averages: </b>" + metrics.map(m=> `${m.l.replace('(↓)','').replace('(↑)','')}: ${fmt(sums[m.k]/c)}`).join(" | ");
410
+
411
+ let html = `<table><thead><tr><th>Language</th>`;
412
+ metrics.forEach(m => html += `<th>${m.l}</th>`);
413
+ html += `</tr></thead><tbody>`;
414
+ rows.forEach(r => {
415
+ html += `<tr><td>${getIso(r.language, r.iso)}</td>`;
416
+ metrics.forEach(m => html += `<td>${fmt(r[m.k])}</td>`);
417
+ html += `</tr>`;
418
+ });
419
+ document.getElementById('tts-table').innerHTML = html;
420
  }
421
 
422
+ // --- SLID ---
423
+ function renderSLID() {
424
+ let html = `<table><thead><tr><th>Language</th><th>MMS-LID-1024 (↑)</th><th>Simba-SLID (↑)</th></tr></thead><tbody>`;
425
+ DATA.slid.forEach(r => {
426
+ let m = r['MMS-LID-1024'], s = r['Simba-SLID'];
427
+ let mS = fmt(m), sS = fmt(s);
428
+ if(m > s) mS = `<b>${mS} 🥇</b>`; else if(s > m) sS = `<b>${sS} 🥇</b>`;
429
+ html += `<tr><td>${getIso(r.Language)}</td><td>${mS}</td><td>${sS}</td></tr>`;
430
+ });
431
+ document.getElementById('slid-table').innerHTML = html;
432
  }
433
 
434
+ // --- LANGUAGE VIEW ---
435
+ function renderLanguageView() {
436
+ const lang = document.getElementById('lang-select').value;
437
+
438
+ // 1. ASR Data
439
+ let asrRows = [];
440
+ Object.keys(DATA.asr.by_model).forEach(modName => {
441
+ const row = DATA.asr.by_model[modName].find(r => r.Language === lang);
442
+ if(row) asrRows.push({model: modName, wer: row.WER, cer: row.CER});
443
+ });
444
+ asrRows.sort((a,b) => (a.wer - b.wer) || (a.cer - b.cer));
445
+
446
+ // 2. TTS Data
447
+ let ttsRows = [];
448
+ Object.keys(DATA.tts).forEach(mod => {
449
+ const row = DATA.tts[mod].find(r => (r.Language || r.language) === lang);
450
+ if(row) ttsRows.push({model: mod, ...row});
451
+ });
452
 
453
+ // 3. SLID Data
454
+ let slidRows = [];
455
+ const slidRow = DATA.slid.find(r => r.Language === lang) ||
456
+ DATA.slid.find(r => r.Language.startsWith(lang + " (")) ||
457
+ DATA.slid.find(r => r.Language.includes(lang));
458
+ if(slidRow) {
459
+ const models = Object.keys(slidRow).filter(k => k !== 'Language' && k !== 'ISO');
460
+ models.forEach(m => slidRows.push({model: m, val: slidRow[m]}));
461
+ slidRows.sort((a,b) => b.val - a.val); // Descending
462
+ }
463
 
464
+ // --- SUMMARY CARDS ---
465
+ let summaryHTML = "";
466
+
467
+ // ASR Winner
468
+ if(asrRows.length > 0) {
469
+ summaryHTML += `<div class="fancy-card">
470
+ <div class="card-icon icon-asr"><i class="fa-solid fa-microphone-lines"></i></div>
471
+ <div class="card-content">
472
+ <div class="card-title">Best ASR Model</div>
473
+ <div class="card-model">${asrRows[0].model}</div>
474
+ <div class="card-score">WER: <b>${fmt(asrRows[0].wer)}%</b></div>
475
+ </div>
476
+ </div>`;
477
+ } else summaryHTML += `<div class="fancy-card"><div class="card-icon icon-asr"><i class="fa-solid fa-microphone-slash"></i></div><div class="card-content"><div class="card-title">ASR</div><div class="card-model">No Data</div></div></div>`;
478
 
479
+ // TTS Winner
480
+ if(ttsRows.length > 0) {
481
+ const bestTTS = [...ttsRows].sort((a,b) => a.wer - b.wer)[0];
482
+ summaryHTML += `<div class="fancy-card">
483
+ <div class="card-icon icon-tts"><i class="fa-solid fa-volume-high"></i></div>
484
+ <div class="card-content">
485
+ <div class="card-title">Best TTS (Intelligibility)</div>
486
+ <div class="card-model">${bestTTS.model}</div>
487
+ <div class="card-score">WER: <b>${fmt(bestTTS.wer)}%</b></div>
488
+ </div>
489
+ </div>`;
490
+ } else summaryHTML += `<div class="fancy-card"><div class="card-icon icon-tts"><i class="fa-solid fa-volume-xmark"></i></div><div class="card-content"><div class="card-title">TTS</div><div class="card-model">No Data</div></div></div>`;
 
491
 
 
 
 
 
 
492
 
 
 
 
493
 
494
+ // SLID Winner
495
+ if(slidRows.length > 0) {
496
+ summaryHTML += `<div class="fancy-card">
497
+ <div class="card-icon icon-slid"><i class="fa-solid fa-language"></i></div>
498
+ <div class="card-content">
499
+ <div class="card-title">Best SLID Model</div>
500
+ <div class="card-model">${slidRows[0].model}</div>
501
+ <div class="card-score">F1 Score: <b>${fmt(slidRows[0].val)}%</b></div>
502
+ </div>
503
+ </div>`;
504
+ } else summaryHTML += `<div class="fancy-card"><div class="card-icon icon-slid"><i class="fa-solid fa-circle-question"></i></div><div class="card-content"><div class="card-title">SLID</div><div class="card-model">No Data</div></div></div>`;
505
 
506
+ document.getElementById('lang-summary').innerHTML = summaryHTML;
 
 
 
 
 
 
 
 
507
 
 
 
 
 
 
508
 
 
 
 
 
 
509
 
 
 
 
 
 
 
510
 
 
 
 
 
 
 
 
511
 
 
 
 
 
 
 
 
 
 
512
 
 
 
 
513
 
 
 
 
 
 
514
 
 
 
 
515
 
 
 
 
 
 
 
 
 
 
 
516
 
 
 
 
 
517
 
 
 
 
518
 
 
 
 
 
 
 
 
 
 
 
519
 
 
 
 
 
520
 
 
 
 
 
 
521
 
 
 
 
 
 
 
 
 
522
 
 
 
 
523
 
524
+ // --- TABLES ---
525
+ // ASR Table
526
+ let h1 = `<table><thead><tr><th>Model</th><th>WER <i class="fa-solid fa-arrow-down arrow-down"></i></th><th>CER <i class="fa-solid fa-arrow-down arrow-down"></i></th></tr></thead><tbody>`;
527
+ if(asrRows.length === 0) h1 += `<tr><td colspan="3" class="empty-msg">No ASR results available for ${lang}.</td></tr>`;
528
+ else {
529
+ let currentRank = 1;
530
+ asrRows.forEach((r, i) => {
531
+ if (i > 0 && Math.abs(r.wer - asrRows[i-1].wer) > 0.001) currentRank = i + 1; else currentRank = 1;
532
+ let icon = (currentRank===1)?'🥇 ':(currentRank===2)?'🥈 ':(currentRank===3)?'🥉 ':'';
533
+ h1 += `<tr><td style="font-weight:600; color:var(--simba-navy)">${icon}${r.model}</td><td>${fmt(r.wer)}</td><td>${fmt(r.cer)}</td></tr>`;
534
+ });
535
+ }
536
+ h1 += `</tbody></table>`;
537
+ document.getElementById('lang-asr-table').innerHTML = h1;
538
+
539
+ // TTS Table
540
+ let h2 = `<table><thead><tr><th>Model</th>
541
+ <th>WER(↓)</th><th>MCD(↓)</th><th>LogF0RMSE(↓)</th><th>SpeechTokenDistance(↓)</th>
542
+ <th>PESQ(↑)</th><th>UTMOS(↑)</th><th>SpeechBLEU(↑)</th><th>SpeechBERTScore(↑)</th>
543
+ </tr></thead><tbody>`;
544
+ if(ttsRows.length === 0) h2 += `<tr><td colspan="9" class="empty-msg">No TTS results available for ${lang}.</td></tr>`;
545
+ else {
546
+ ttsRows.forEach(row => {
547
+ h2 += `<tr>
548
+ <td style="font-weight:600;">${row.model}</td>
549
+ <td>${fmt(row.wer)}</td><td>${fmt(row.mcd)}</td>
550
+ <td>${fmt(row.logf0rmse)}</td><td>${fmt(row.speech_token_distance)}</td>
551
+ <td>${fmt(row.pesq)}</td><td>${fmt(row.utmos)}</td>
552
+ <td>${fmt(row.speechbleu)}</td><td>${fmt(row.speechbert_score)}</td>
553
+ </tr>`;
554
+ });
555
+ }
556
+ h2 += `</tbody></table>`;
557
+ document.getElementById('lang-tts-table').innerHTML = h2;
558
+
559
+ // SLID Table
560
+ let h3 = `<table><thead><tr><th>Model</th><th>F1-Score <i class="fa-solid fa-arrow-up arrow-up"></i></th></tr></thead><tbody>`;
561
+ if(slidRows.length === 0) h3 += `<tr><td colspan="2" class="empty-msg">No SLID results available for ${lang}.</td></tr>`;
562
+ else {
563
+ let currentRank = 1;
564
+ slidRows.forEach((sc, i) => {
565
+ if (i > 0 && Math.abs(sc.val - slidRows[i-1].val) > 0.001) currentRank = i + 1; else currentRank = 1;
566
+ let icon = (currentRank===1)?'🥇 ':(currentRank===2)?'🥈 ':(currentRank===3)?'🥉 ':'';
567
+ h3 += `<tr><td style="font-weight:600;">${icon}${sc.model}</td><td>${fmt(sc.val)}</td></tr>`;
568
+ });
569
+ }
570
+ h3 += `</tbody></table>`;
571
+ document.getElementById('lang-slid-table').innerHTML = h3;
572
  }
573
 
 
 
 
 
 
574
 
 
 
 
 
575
 
 
 
 
576
 
 
 
 
577
 
 
 
 
578
 
 
 
 
579
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
580
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
581
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
582
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
583
 
 
 
 
 
 
 
 
 
 
 
 
584
 
 
 
 
 
 
 
 
 
 
 
585
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
586
 
587
+
588
+
589
+
590
+
591
+
592
+
593
+
594
+
595
+
596
+
597
+
598
+
599
+
600
+
601
+
602
+
603
+
604
+ // --- UI ---
605
+ window.setTab = (id, btn) => {
606
+ document.querySelectorAll('.view').forEach(e => e.classList.remove('active'));
607
+ document.querySelectorAll('.tab-btn').forEach(e => e.classList.remove('active'));
608
+ document.getElementById(id).classList.add('active');
609
+ if(btn) btn.classList.add('active'); else document.getElementById(`tab-btn-${id}`).classList.add('active');
610
+ if(id === 'lang') renderLanguageView();
611
  };
612
 
613
+ window.setASRMode = (m) => {
614
+ asrMode = m;
615
+ ['btn-over','btn-fam','btn-mod'].forEach(b => document.getElementById(b).classList.remove('active'));
616
+ document.getElementById(m==='overview'?'btn-over':(m==='family'?'btn-fam':'btn-mod')).classList.add('active');
617
+ renderASR();
618
+ }
619
+
620
+ window.copyCitation = () => {
621
+ const text = document.getElementById('bibtex').innerText;
622
+ navigator.clipboard.writeText(text).then(() => {
623
+ const btn = document.querySelector('.copy-btn');
624
+ btn.innerHTML = '<i class="fa-solid fa-check"></i> Copied!';
625
+ setTimeout(() => btn.innerHTML = '<i class="fa-regular fa-copy"></i> Copy', 2000);
626
  });
627
+ }
 
 
 
 
 
 
 
 
628
  </script>
629
  </body>
630
  </html>