elmadany commited on
Commit
0289280
·
verified ·
1 Parent(s): b27609b

Update public/index.html

Browse files
Files changed (1) hide show
  1. public/index.html +322 -325
public/index.html CHANGED
@@ -3,389 +3,394 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Simba Benchmark 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&display=swap" rel="stylesheet">
12
-
13
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
14
 
15
  <style>
16
  :root {
17
- /* Simba Brand Colors */
18
- --simba-navy: #0f172a; /* Deep Slate Navy */
19
- --simba-blue: #1e293b; /* Lighter Navy for Cards */
20
- --simba-gold: #d97706; /* Primary Action Color */
21
- --simba-gold-light: #f59e0b; /* Hover State */
22
- --bg-cream: #f8fafc; /* Very Light Grey/Cream for body */
23
- --text-main: #334155;
24
- --text-dark: #0f172a;
25
- --border-color: #e2e8f0;
 
 
 
 
 
 
 
 
26
  }
27
 
28
  body {
29
- background-color: var(--bg-cream);
30
  font-family: 'Inter', sans-serif;
31
  color: var(--text-main);
32
  margin: 0;
33
- padding-top: 80px; /* Space for fixed navbar */
 
34
  }
35
 
36
- /* --- NAVIGATION BAR --- */
37
- .navbar {
38
- background-color: var(--simba-navy);
39
- position: fixed;
40
- top: 0;
41
  width: 100%;
42
- z-index: 1000;
43
- box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  }
45
 
46
- .nav-container {
47
- max-width: 1280px;
48
- margin: 0 auto;
49
- padding: 0 20px;
50
- height: 70px;
51
  display: flex;
52
- align-items: center;
53
  justify-content: space-between;
 
 
 
54
  }
55
-
56
  .nav-logo {
57
  color: white;
58
  font-family: 'Rubik', sans-serif;
59
  font-weight: 700;
60
- font-size: 24px;
61
- text-decoration: none;
62
  display: flex;
63
  align-items: center;
64
  gap: 10px;
 
65
  }
 
66
 
67
- .nav-logo img { height: 40px; border-radius: 5px; }
68
-
69
- .nav-links { display: flex; gap: 25px; }
70
-
71
- .nav-link {
72
  color: #cbd5e1;
73
  text-decoration: none;
 
74
  font-weight: 500;
75
- font-size: 15px;
76
  transition: color 0.2s;
77
  }
78
-
79
- .nav-link:hover, .nav-link.active { color: var(--simba-gold); }
80
 
81
- .nav-btn {
82
- background-color: var(--simba-gold);
 
 
83
  color: white !important;
84
- padding: 8px 16px;
85
- border-radius: 9999px; /* Pill shape */
86
- transition: background-color 0.2s;
 
 
 
 
 
 
 
87
  }
88
- .nav-btn:hover { background-color: var(--simba-gold-light); }
89
 
90
  /* --- HERO SECTION --- */
91
  .hero {
92
- text-align: center;
93
- padding: 40px 20px;
94
- background: white;
95
- border-bottom: 1px solid var(--border-color);
96
- margin-bottom: 40px;
97
- }
98
- .hero img { max-width: 600px; width: 90%; height: auto; }
99
- .hero h1 {
100
- font-family: 'Rubik', sans-serif;
101
- color: var(--simba-navy);
102
- margin-top: 20px;
103
- font-size: 32px;
104
  }
105
 
106
- /* --- MAIN CONTAINER --- */
107
- .container { max-width: 1280px; margin: 0 auto; padding: 0 20px 60px; }
108
-
109
- /* --- CARDS --- */
110
- .card {
111
  background: white;
112
- border-radius: 16px;
113
- border: 1px solid var(--border-color);
114
- padding: 30px;
115
- box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05);
116
- margin-bottom: 30px;
117
- }
118
-
119
- h2 {
120
- font-family: 'Rubik', sans-serif;
121
- color: var(--simba-navy);
122
- font-size: 24px;
123
- margin-top: 0;
124
- border-bottom: 2px solid var(--simba-gold);
125
  display: inline-block;
126
- padding-bottom: 8px;
 
127
  margin-bottom: 20px;
128
  }
 
129
 
130
- /* --- TABS --- */
131
- .tabs {
132
- display: flex;
133
- gap: 10px;
134
- margin-bottom: 25px;
135
- background: #f1f5f9;
136
- padding: 5px;
137
- border-radius: 12px;
138
- width: fit-content;
139
  }
140
 
141
- .tab-btn {
142
- background: transparent;
143
- border: none;
144
- padding: 10px 20px;
145
- font-family: 'Inter', sans-serif;
146
- font-weight: 600;
147
- color: #64748b;
148
- cursor: pointer;
149
- border-radius: 8px;
150
- transition: all 0.2s ease;
151
  }
152
 
153
- .tab-btn:hover { color: var(--simba-navy); }
154
-
155
- .tab-btn.active {
156
- background-color: white;
157
- color: var(--simba-gold);
158
- box-shadow: 0 1px 3px rgba(0,0,0,0.1);
159
  }
160
 
161
- .view { display: none; animation: fadeIn 0.3s; }
162
- .view.active { display: block; }
163
-
164
- /* --- CONTROLS --- */
165
- .controls-bar {
166
  display: flex;
167
- justify-content: space-between;
168
- align-items: center;
169
- background: #f8fafc;
170
- padding: 15px;
171
- border-radius: 10px;
172
- border: 1px solid var(--border-color);
173
- margin-bottom: 20px;
174
  flex-wrap: wrap;
175
  gap: 15px;
176
  }
177
 
178
- .btn-group { display: flex; gap: 10px; }
179
-
180
- .btn {
181
- padding: 8px 20px;
182
- border-radius: 8px;
 
183
  font-weight: 600;
184
  font-size: 14px;
185
- cursor: pointer;
186
- border: 1px solid transparent;
187
- transition: all 0.2s;
 
188
  }
189
-
190
- .btn-primary {
191
- background-color: var(--simba-navy);
192
- color: white;
 
 
 
 
 
 
 
 
 
 
 
 
193
  }
194
- .btn-primary:hover { background-color: #334155; }
195
-
196
- .btn-secondary {
197
- background-color: white;
198
- color: var(--simba-navy);
199
- border: 1px solid #cbd5e1;
200
  }
201
- .btn-secondary:hover { border-color: var(--simba-navy); }
202
 
203
- select {
204
- padding: 8px 32px 8px 12px;
205
- border-radius: 8px;
206
- border: 1px solid #cbd5e1;
207
- background-color: white;
208
- font-size: 14px;
209
- min-width: 220px;
210
- cursor: pointer;
211
  }
212
-
213
- /* --- TABLES --- */
214
- .table-wrap { overflow-x: auto; border-radius: 8px; border: 1px solid var(--border-color); }
215
 
216
- table {
217
- width: 100%;
218
- border-collapse: collapse;
219
- font-size: 14px;
220
- background: white;
221
- }
222
-
223
- thead { background-color: #f8fafc; }
224
 
225
- th {
226
- text-align: center;
227
- padding: 16px 12px;
228
- font-weight: 600;
229
- color: var(--simba-navy);
230
- border-bottom: 2px solid #e2e8f0;
231
- white-space: nowrap;
232
- }
233
-
234
- td {
235
- padding: 12px;
236
- border-bottom: 1px solid #e2e8f0;
237
- text-align: center;
238
- color: #475569;
239
  }
240
 
241
- tr:last-child td { border-bottom: none; }
242
- tr:hover td { background-color: #f8fafc; }
243
-
244
- /* Sticky Columns */
245
- th:first-child, td:first-child {
246
- position: sticky;
247
- left: 0;
248
- background-color: inherit;
249
- z-index: 1;
250
- text-align: left;
251
- font-weight: 600;
252
- color: var(--simba-navy);
253
- border-right: 2px solid #e2e8f0;
254
  }
255
- thead th:first-child { z-index: 2; background-color: #f8fafc; }
256
-
257
- /* Left Align Text */
 
 
 
 
 
258
  th:nth-child(2), td:nth-child(2) { text-align: left; }
259
-
260
- /* Metrics & Arrows */
261
- .metric-good { color: #16a34a; font-weight: 600; } /* Green */
262
- .metric-neutral { color: #d97706; } /* Orange */
263
- .val { white-space: nowrap; }
264
 
265
- /* Rotated Headers Override */
266
- .vertical-head { font-size: 12px; color: #64748b; }
267
 
268
- /* --- FOOTER --- */
269
- .footer { text-align: center; margin-top: 40px; color: #64748b; font-size: 14px; }
270
- .footer a { color: var(--simba-gold); text-decoration: none; }
271
 
272
- @keyframes fadeIn { from { opacity: 0; transform: translateY(5px); } to { opacity: 1; transform: translateY(0); } }
273
-
274
- /* Loading */
275
- #loader { padding: 60px; text-align: center; font-size: 18px; color: var(--simba-navy); font-weight: 500; }
 
 
 
276
  </style>
277
  </head>
278
  <body>
279
 
280
  <nav class="navbar">
281
- <div class="nav-container">
282
- <a href="https://africa.dlnlp.ai/simba/" class="nav-logo">
283
- <i class="fa-solid fa-paw" style="color: var(--simba-gold);"></i>
284
- SimbaBench
285
- </a>
286
- <div class="nav-links">
287
- <a href="https://africa.dlnlp.ai/simba/" class="nav-link">Home</a>
288
- <a href="https://arxiv.org/abs/2510.17998" class="nav-link" target="_blank">Paper</a>
289
- <a href="https://github.com/UBC-NLP/simba" class="nav-link" target="_blank">Code</a>
290
- <a href="https://huggingface.co/datasets/UBC-NLP/simba" class="nav-link" target="_blank">Dataset</a>
291
- <a href="#" class="nav-link active nav-btn">Leaderboard</a>
292
- </div>
 
293
  </div>
294
  </nav>
295
 
296
  <div class="hero">
297
- <img src="https://africa.dlnlp.ai/simba/images/simbabench_header.png" alt="Simba Header">
298
- <h1>Official Benchmark Leaderboard</h1>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
299
  </div>
300
 
301
- <div class="container">
302
-
303
- <div class="card">
304
- <div id="loader"><i class="fa-solid fa-circle-notch fa-spin"></i> Loading Leaderboard Data...</div>
305
 
306
- <div id="content" style="display:none;">
307
-
308
- <div class="tabs">
309
- <button class="tab-btn active" onclick="setTab('asr', this)">
310
- <i class="fa-solid fa-microphone-lines"></i> ASR
311
- </button>
312
- <button class="tab-btn" onclick="setTab('tts', this)">
313
- <i class="fa-solid fa-volume-high"></i> TTS
314
- </button>
315
- <button class="tab-btn" onclick="setTab('slid', this)">
316
- <i class="fa-solid fa-language"></i> SLID
317
- </button>
318
  </div>
319
 
320
- <div id="asr" class="view active">
321
- <div class="controls-bar">
322
- <div class="btn-group">
323
- <button id="btn-fam" class="btn btn-primary" onclick="setASRMode('family')">By Language Family</button>
324
- <button id="btn-mod" class="btn btn-secondary" onclick="setASRMode('model')">By Model</button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
325
  </div>
326
 
327
- <div id="grp-fam">
328
- <span style="font-weight: 600; margin-right: 10px; color: var(--simba-navy);">Select Family:</span>
329
- <select id="asr-select-fam" onchange="renderASR()"></select>
330
- </div>
331
- <div id="grp-mod" style="display:none;">
332
- <span style="font-weight: 600; margin-right: 10px; color: var(--simba-navy);">Select Model:</span>
333
- <select id="asr-select-mod" onchange="renderASR()"></select>
334
- </div>
335
  </div>
336
-
337
- <div id="asr-legend" style="margin-bottom: 15px; font-size: 13px; color: #64748b; background: #f8fafc; padding: 10px; border-radius: 6px; display:none;"></div>
338
- <div id="asr-table" class="table-wrap"></div>
339
- </div>
340
 
341
- <div id="tts" class="view">
342
- <div class="controls-bar">
343
- <div>
344
- <span style="font-weight: 600; margin-right: 10px; color: var(--simba-navy);">Select Model:</span>
345
- <select id="tts-select" onchange="renderTTS()"></select>
346
  </div>
 
 
 
347
  </div>
348
- <div id="tts-summary" style="margin-bottom: 15px; font-weight:500; color:var(--simba-navy);"></div>
349
- <div id="tts-table" class="table-wrap"></div>
350
- </div>
351
 
352
- <div id="slid" class="view">
353
- <h3 style="color:var(--simba-navy); font-size:18px; margin-top:0;">Spoken Language Identification</h3>
354
- <div id="slid-table" class="table-wrap"></div>
355
- </div>
356
 
 
357
  </div>
358
- </div>
359
 
360
- <div class="card" style="text-align: center;">
361
- <h2>Citation</h2>
362
- <p style="color: #64748b; line-height: 1.6;">
363
- If you use the Simba benchmark for your scientific publication, please cite our
364
- <a href='https://africa.dlnlp.ai/sahara/' style="color:var(--simba-gold); font-weight:bold;">ACL2025 paper</a>.
365
- </p>
366
- <div class="citation-block" style="background:#1e293b; color:#cbd5e1; padding:15px; border-radius:8px; text-align:left; font-family:monospace; margin-top:20px; font-size:12px; overflow-x:auto;">
367
- @inproceedings{simba2025,
368
- title={Simba: A Unified Benchmark for Speech Tasks in African Languages},
369
- author={Put Authors Here},
370
- booktitle={ACL},
371
- year={2025}
372
- }
373
  </div>
374
- </div>
375
 
376
- <div class="footer">
377
- <img src="https://africa.dlnlp.ai/sahara//img/sahara_web_sponsers.jpg" width="300px" style="opacity: 0.8;">
378
- <p>&copy; 2025 Simba Benchmark Team</p>
379
  </div>
380
  </div>
381
 
382
  <script>
383
- // --- DATA LOGIC ---
384
  const NAME_TO_ISO = {
385
  'Afrikaans': 'afr', 'Akuapim-twi': 'ak', 'Amharic': 'amh', 'Asante-twi': 'tw',
386
  'Bemba': 'bem', 'Hausa': 'hau', 'Igbo': 'ibo', 'Yoruba': 'yor', 'Zulu': 'zul',
387
  'Swahili': 'swa', 'Somali': 'som', 'Wolof': 'wol', 'Xhosa': 'xho'
388
- // Add remaining ISO mappings here as needed
389
  };
390
 
391
  let DATA = null;
@@ -397,8 +402,7 @@
397
  document.getElementById('content').style.display='block';
398
  init();
399
  }).catch(e=>{
400
- document.getElementById('loader').innerHTML = `<span style="color:red">Error loading data. Please refresh.</span>`;
401
- console.error(e);
402
  });
403
 
404
  function init() {
@@ -412,68 +416,59 @@
412
  const s = document.getElementById(id); s.innerHTML='';
413
  list.forEach(i=>{ let o=document.createElement('option'); o.value=i; o.text=i; s.add(o); });
414
  }
415
-
416
  function fmt(n) { return (n==null)?'N/A':n.toFixed(2); }
417
- function getIso(name) { return NAME_TO_ISO[name] || name.substring(0,3).toLowerCase(); }
418
 
419
- // --- RENDER ASR ---
420
  function renderASR() {
421
  const div = document.getElementById('asr-table');
422
  const legend = document.getElementById('asr-legend');
423
  let html='';
424
 
425
- if(asrMode === 'family'){
426
  const val = document.getElementById('asr-select-fam').value;
 
 
427
  const d = DATA.asr.by_family[val];
428
  if(!d) return;
429
 
430
  // Legend
431
  legend.style.display = 'block';
432
- legend.innerHTML = `<b>Languages in ${val}:</b> ` + d.languages.map(l => `<span style="margin-left:10px; color:var(--simba-navy)"><b>${getIso(l)}</b>: ${l}</span>`).join("");
433
 
434
  // Table
435
- html = `<table><thead><tr><th>Model</th><th>Avg WER/CER <i class="fa-solid fa-arrow-down" style="font-size:10px"></i></th>`;
436
  d.languages.forEach(l => html += `<th>${getIso(l)}</th>`);
437
  html += `</tr></thead><tbody>`;
438
 
439
  d.data.forEach(r => {
440
- html += `<tr>
441
- <td style="font-weight:600; color:var(--simba-navy)">${r.Model}</td>
442
- <td style="background:#f1f5f9; font-weight:bold;">${fmt(r.Avg_WER)} / ${fmt(r.Avg_CER)}</td>`;
443
  d.languages.forEach(l => {
444
- let w = r[`WER_${l}`], c = r[`CER_${l}`];
445
  html += `<td>${(w!=null)?fmt(w)+'/'+fmt(c):'-'}</td>`;
446
  });
447
  html += `</tr>`;
448
  });
449
  } else {
450
  const val = document.getElementById('asr-select-mod').value;
 
451
  legend.style.display = 'none';
452
- const rows = DATA.asr.by_model[val];
453
-
454
- html = `<table><thead><tr>
455
- <th>Language</th>
456
- <th>Family</th>
457
- <th>WER (%) <i class="fa-solid fa-arrow-down" style="font-size:10px"></i></th>
458
- <th>CER (%) <i class="fa-solid fa-arrow-down" style="font-size:10px"></i></th>
459
- </tr></thead><tbody>`;
460
 
 
 
461
  rows.forEach(r => {
462
- html += `<tr>
463
- <td style="font-weight:600;">${r.Language}</td>
464
- <td>${r.Family}</td>
465
- <td>${fmt(r.WER)}</td>
466
- <td>${fmt(r.CER)}</td>
467
- </tr>`;
468
  });
469
  }
470
  html += `</tbody></table>`;
471
  div.innerHTML = html;
472
  }
473
 
474
- // --- RENDER TTS ---
475
  function renderTTS() {
476
  const val = document.getElementById('tts-select').value;
 
 
477
  const rows = DATA.tts[val];
478
  if(!rows) return;
479
 
@@ -485,24 +480,23 @@
485
  ];
486
 
487
  // Averages
488
- let sums = {}, count = 0;
489
- metrics.forEach(m => sums[m.k] = 0);
490
- rows.forEach(r => { metrics.forEach(m => sums[m.k] += (r[m.k]||0)); count++; });
491
-
492
- let sumHtml = metrics.map(m => `<span style="margin-right:15px">${m.l}: <b>${fmt(sums[m.k]/count)}</b></span>`).join("");
493
- document.getElementById('tts-summary').innerHTML = sumHtml;
494
 
495
  // Table
496
  let html = `<table><thead><tr><th>Language</th>`;
497
  metrics.forEach(m => {
498
  let icon = m.h ? 'up' : 'down';
499
- let color = m.h ? 'green' : 'orange';
500
- html += `<th>${m.l} <i class="fa-solid fa-arrow-${icon}" style="color:${color}; font-size:10px"></i></th>`;
501
  });
502
  html += `</tr></thead><tbody>`;
503
-
504
  rows.forEach(r => {
505
- html += `<tr><td style="font-weight:600;">${r.language}</td>`;
506
  metrics.forEach(m => html += `<td>${fmt(r[m.k])}</td>`);
507
  html += `</tr>`;
508
  });
@@ -510,26 +504,20 @@
510
  document.getElementById('tts-table').innerHTML = html;
511
  }
512
 
513
- // --- RENDER SLID ---
514
  function renderSLID() {
515
- let html = `<table><thead><tr>
516
- <th>Language</th>
517
- <th>MMS-LID-1024 <i class="fa-solid fa-arrow-up" style="color:green; font-size:10px"></i></th>
518
- <th>Simba-SLID <i class="fa-solid fa-arrow-up" style="color:green; font-size:10px"></i></th>
519
- </tr></thead><tbody>`;
520
-
521
  DATA.slid.forEach(r => {
522
  let m = r['MMS-LID-1024'], s = r['Simba-SLID'];
523
  let mS = fmt(m), sS = fmt(s);
524
- if(m > s) mS = `<b style="color:green">${mS}</b>`;
525
- else if(s > m) sS = `<b style="color:green">${sS}</b>`;
526
- html += `<tr><td style="font-weight:600;">${r.Language}</td><td>${mS}</td><td>${sS}</td></tr>`;
527
  });
528
  html += `</tbody></table>`;
529
  document.getElementById('slid-table').innerHTML = html;
530
  }
531
 
532
- // --- INTERACTION ---
533
  window.setTab = (id, btn) => {
534
  document.querySelectorAll('.view').forEach(e => e.classList.remove('active'));
535
  document.querySelectorAll('.tab-btn').forEach(e => e.classList.remove('active'));
@@ -539,10 +527,19 @@
539
 
540
  window.setASRMode = (m) => {
541
  asrMode = m;
542
- document.getElementById('btn-fam').className = m==='family'?'btn btn-primary':'btn btn-secondary';
543
- document.getElementById('btn-mod').className = m==='model'?'btn btn-primary':'btn btn-secondary';
544
- document.getElementById('grp-fam').style.display = m==='family'?'block':'none';
545
- document.getElementById('grp-mod').style.display = m==='model'?'block':'none';
 
 
 
 
 
 
 
 
 
546
  renderASR();
547
  }
548
  </script>
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>SimbaBench - Voice of a Continent</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
+ /* Brand Colors from Image */
17
+ --bg-deep: #1e1b4b; /* Deep Navy Background */
18
+ --text-yellow: #fbbf24; /* "Mapping Africa" text */
19
+ --text-white: #ffffff;
20
+ --text-mute: #94a3b8; /* Description text */
21
+
22
+ /* Button Gradients */
23
+ --grad-red: linear-gradient(135deg, #ef4444, #f43f5e);
24
+ --grad-purple: linear-gradient(135deg, #6366f1, #8b5cf6);
25
+ --grad-orange: linear-gradient(135deg, #f97316, #fb923c);
26
+ --grad-blue: linear-gradient(135deg, #3b82f6, #0ea5e9);
27
+ --grad-green: linear-gradient(135deg, #22c55e, #10b981);
28
+
29
+ /* Layout Colors */
30
+ --card-bg: #ffffff;
31
+ --simba-navy: #0f172a;
32
+ --border-gold: #dca02a;
33
  }
34
 
35
  body {
36
+ background-color: var(--bg-deep);
37
  font-family: 'Inter', sans-serif;
38
  color: var(--text-main);
39
  margin: 0;
40
+ padding: 0;
41
+ overflow-x: hidden;
42
  }
43
 
44
+ /* --- BACKGROUND WAVE ANIMATION --- */
45
+ .wave-bg {
46
+ position: absolute;
47
+ top: 150px;
48
+ left: 0;
49
  width: 100%;
50
+ height: 300px;
51
+ background: repeating-linear-gradient(
52
+ 90deg,
53
+ transparent,
54
+ transparent 10px,
55
+ rgba(255, 255, 255, 0.05) 10px,
56
+ rgba(255, 255, 255, 0.05) 12px
57
+ );
58
+ mask-image: linear-gradient(to right, transparent, black 20%, black 80%, transparent);
59
+ z-index: 0;
60
+ pointer-events: none;
61
+ }
62
+
63
+ .wave-bar {
64
+ position: absolute;
65
+ bottom: 0;
66
+ width: 4px;
67
+ background: rgba(255,255,255,0.1);
68
+ border-radius: 4px;
69
+ animation: bounce 2s infinite ease-in-out;
70
  }
71
 
72
+ /* --- NAVBAR --- */
73
+ .navbar {
74
+ padding: 20px 40px;
 
 
75
  display: flex;
 
76
  justify-content: space-between;
77
+ align-items: center;
78
+ z-index: 10;
79
+ position: relative;
80
  }
 
81
  .nav-logo {
82
  color: white;
83
  font-family: 'Rubik', sans-serif;
84
  font-weight: 700;
85
+ font-size: 20px;
 
86
  display: flex;
87
  align-items: center;
88
  gap: 10px;
89
+ text-decoration: none;
90
  }
91
+ .nav-logo img { height: 35px; }
92
 
93
+ .nav-links { display: flex; gap: 30px; align-items: center; }
94
+ .nav-links a {
 
 
 
95
  color: #cbd5e1;
96
  text-decoration: none;
97
+ font-size: 14px;
98
  font-weight: 500;
 
99
  transition: color 0.2s;
100
  }
101
+ .nav-links a:hover { color: white; }
 
102
 
103
+ .nav-btn-action {
104
+ background: var(--grad-blue);
105
+ padding: 8px 20px;
106
+ border-radius: 20px;
107
  color: white !important;
108
+ font-weight: 600;
109
+ box-shadow: 0 4px 10px rgba(59, 130, 246, 0.3);
110
+ }
111
+
112
+ .login-btn {
113
+ background: var(--text-yellow);
114
+ color: var(--bg-deep) !important;
115
+ padding: 8px 20px;
116
+ border-radius: 20px;
117
+ font-weight: 700;
118
  }
 
119
 
120
  /* --- HERO SECTION --- */
121
  .hero {
122
+ display: flex;
123
+ align-items: center;
124
+ justify-content: space-between;
125
+ max-width: 1300px;
126
+ margin: 40px auto 80px;
127
+ padding: 0 40px;
128
+ position: relative;
129
+ z-index: 2;
 
 
 
 
130
  }
131
 
132
+ .hero-content { flex: 1; max-width: 650px; }
133
+
134
+ .conference-tag {
 
 
135
  background: white;
 
 
 
 
 
 
 
 
 
 
 
 
 
136
  display: inline-block;
137
+ padding: 5px 15px;
138
+ border-radius: 8px;
139
  margin-bottom: 20px;
140
  }
141
+ .conference-tag img { height: 25px; }
142
 
143
+ .hero h1 {
144
+ font-family: 'Rubik', sans-serif;
145
+ font-size: 56px;
146
+ font-weight: 800;
147
+ color: white;
148
+ margin: 0;
149
+ line-height: 1.1;
 
 
150
  }
151
 
152
+ .hero h2 {
153
+ font-family: 'Rubik', sans-serif;
154
+ font-size: 28px;
155
+ font-weight: 700;
156
+ color: var(--text-yellow);
157
+ margin: 10px 0 20px;
158
+ letter-spacing: 1px;
 
 
 
159
  }
160
 
161
+ .hero p {
162
+ color: var(--text-mute);
163
+ font-size: 16px;
164
+ line-height: 1.6;
165
+ margin-bottom: 40px;
166
+ max-width: 90%;
167
  }
168
 
169
+ /* --- HERO BUTTONS --- */
170
+ .hero-buttons {
 
 
 
171
  display: flex;
 
 
 
 
 
 
 
172
  flex-wrap: wrap;
173
  gap: 15px;
174
  }
175
 
176
+ .h-btn {
177
+ text-decoration: none;
178
+ color: white;
179
+ padding: 12px 24px;
180
+ border-radius: 30px;
181
+ font-family: 'Rubik', sans-serif;
182
  font-weight: 600;
183
  font-size: 14px;
184
+ display: flex;
185
+ align-items: center;
186
+ gap: 8px;
187
+ transition: transform 0.2s, box-shadow 0.2s;
188
  }
189
+
190
+ .h-btn:hover { transform: translateY(-2px); filter: brightness(1.1); }
191
+ .h-btn i { font-size: 16px; }
192
+
193
+ .btn-paper { background: var(--grad-red); box-shadow: 0 4px 15px rgba(239, 68, 68, 0.4); }
194
+ .btn-pipeline { background: var(--grad-purple); box-shadow: 0 4px 15px rgba(99, 102, 241, 0.4); }
195
+ .btn-dataset { background: var(--grad-orange); box-shadow: 0 4px 15px rgba(249, 115, 22, 0.4); }
196
+ .btn-models { background: var(--grad-blue); box-shadow: 0 4px 15px rgba(59, 130, 246, 0.4); }
197
+ .btn-leaderboard { background: var(--grad-green); box-shadow: 0 4px 15px rgba(34, 197, 94, 0.4); }
198
+
199
+ /* --- HERO IMAGE (Map) --- */
200
+ .hero-visual {
201
+ flex: 1;
202
+ display: flex;
203
+ justify-content: flex-end;
204
+ position: relative;
205
  }
206
+ .hero-visual img {
207
+ max-width: 100%;
208
+ height: auto;
209
+ /* Simple fade animation */
210
+ animation: fadeIn 1.5s ease-out;
 
211
  }
 
212
 
213
+ /* --- LEADERBOARD SECTION --- */
214
+ .leaderboard-section {
215
+ background: #f8fafc;
216
+ border-radius: 24px 24px 0 0;
217
+ padding: 60px 40px;
218
+ min-height: 100vh;
 
 
219
  }
 
 
 
220
 
221
+ .lb-container { max-width: 1300px; margin: 0 auto; }
 
 
 
 
 
 
 
222
 
223
+ .content-card {
224
+ background: white;
225
+ border-radius: 16px;
226
+ padding: 30px;
227
+ box-shadow: 0 10px 30px rgba(0,0,0,0.05);
228
+ margin-bottom: 40px;
 
 
 
 
 
 
 
 
229
  }
230
 
231
+ /* Controls & Tables (Reusing refined styles) */
232
+ .controls { display: flex; gap: 15px; margin-bottom: 20px; align-items: center; flex-wrap: wrap; background: #f1f5f9; padding: 15px; border-radius: 12px; }
233
+ .tabs { display: flex; gap: 10px; margin-bottom: 25px; }
234
+ .tab-btn {
235
+ padding: 10px 20px; border-radius: 8px; border: none; background: transparent;
236
+ font-weight: 600; color: #64748b; cursor: pointer; transition: 0.2s;
 
 
 
 
 
 
 
237
  }
238
+ .tab-btn.active { background: var(--simba-navy); color: white; box-shadow: 0 4px 10px rgba(15, 23, 42, 0.2); }
239
+
240
+ /* Table Styles */
241
+ .table-wrap { overflow-x: auto; }
242
+ table { width: 100%; border-collapse: collapse; font-size: 14px; }
243
+ th { text-align: center; padding: 15px; color: var(--simba-navy); border-bottom: 2px solid #e2e8f0; vertical-align: bottom; }
244
+ td { text-align: center; padding: 12px; border-bottom: 1px solid #f1f5f9; color: #334155; }
245
+ th:first-child, td:first-child { text-align: left; font-weight: 700; position: sticky; left: 0; background: white; z-index: 2; }
246
  th:nth-child(2), td:nth-child(2) { text-align: left; }
 
 
 
 
 
247
 
248
+ .arrow-up { color: #16a34a; } .arrow-down { color: #d97706; }
249
+ .val { white-space: nowrap; }
250
 
251
+ /* Animations */
252
+ @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
253
+ @keyframes bounce { 0%, 100% { height: 10px; } 50% { height: 40px; } }
254
 
255
+ /* Mobile */
256
+ @media (max-width: 900px) {
257
+ .hero { flex-direction: column; text-align: center; }
258
+ .hero-visual { margin-top: 40px; justify-content: center; }
259
+ .hero-buttons { justify-content: center; }
260
+ .nav-links { display: none; } /* Simplified for mobile */
261
+ }
262
  </style>
263
  </head>
264
  <body>
265
 
266
  <nav class="navbar">
267
+ <a href="#" class="nav-logo">
268
+ <img src="https://africa.dlnlp.ai/simba/images/favicon.png" alt="Logo">
269
+ Voice of a Continent
270
+ </a>
271
+ <div class="nav-links">
272
+ <a href="https://arxiv.org/abs/2510.17998">Paper</a>
273
+ <a href="https://github.com/UBC-NLP/simba">Pipeline</a>
274
+ <a href="https://huggingface.co/datasets/UBC-NLP/simba">Dataset</a>
275
+ <a href="#">Models</a>
276
+ <a href="#">Leaderboard</a>
277
+ <a href="#">Citation</a>
278
+ <a href="#" class="nav-btn-action">Submit New Results</a>
279
+ <a href="#" class="login-btn">Login</a>
280
  </div>
281
  </nav>
282
 
283
  <div class="hero">
284
+ <div class="wave-bg"></div>
285
+
286
+ <div class="hero-content">
287
+ <div class="conference-tag">
288
+ <span style="font-weight:800; color:#cc0000;">EMNLP 2025</span>
289
+ <span style="font-size:12px; color:#555;">Suzhou, China</span>
290
+ </div>
291
+
292
+ <h1>Voice of a Continent</h1>
293
+ <h2>Mapping Africa’s Speech Technology</h2>
294
+
295
+ <p>
296
+ SimbaBench bridges the digital divide with a unified suite for African AI: the largest
297
+ open-source speech benchmark covering 61 languages, best-in-class multilingual models,
298
+ and an interactive leaderboard driving the future of speech technology.
299
+ </p>
300
+
301
+ <div class="hero-buttons">
302
+ <a href="https://arxiv.org/abs/2510.17998" target="_blank" class="h-btn btn-paper">
303
+ <i class="fa-regular fa-file-pdf"></i> Read Paper
304
+ </a>
305
+ <a href="https://github.com/UBC-NLP/simba" target="_blank" class="h-btn btn-pipeline">
306
+ <i class="fa-solid fa-code-branch"></i> Pipeline
307
+ </a>
308
+ <a href="https://huggingface.co/datasets/UBC-NLP/simba" target="_blank" class="h-btn btn-dataset">
309
+ <i class="fa-solid fa-database"></i> Dataset
310
+ </a>
311
+ <a href="#" class="h-btn btn-models">
312
+ <i class="fa-solid fa-bolt"></i> Models
313
+ </a>
314
+ <a href="#leaderboard-anchor" class="h-btn btn-leaderboard">
315
+ <i class="fa-solid fa-trophy"></i> Leaderboard
316
+ </a>
317
+ </div>
318
+ </div>
319
+
320
+ <div class="hero-visual">
321
+ <img src="https://africa.dlnlp.ai/simba/images/simbabench_header.png" alt="Africa Map Graphic">
322
+ </div>
323
  </div>
324
 
325
+ <div class="leaderboard-section" id="leaderboard-anchor">
326
+ <div class="lb-container">
 
 
327
 
328
+ <div class="content-card">
329
+ <div id="loader" style="text-align:center; padding:40px; color:#64748b;">
330
+ <i class="fa-solid fa-circle-notch fa-spin fa-2x"></i><br><br>Loading Leaderboard Data...
 
 
 
 
 
 
 
 
 
331
  </div>
332
 
333
+ <div id="content" style="display:none;">
334
+
335
+ <div class="tabs">
336
+ <button class="tab-btn active" onclick="setTab('asr', this)">Automatic Speech Recognition (ASR)</button>
337
+ <button class="tab-btn" onclick="setTab('tts', this)">Text-to-Speech (TTS)</button>
338
+ <button class="tab-btn" onclick="setTab('slid', this)">Spoken Language Identification (SLID)</button>
339
+ </div>
340
+
341
+ <div id="asr" class="view active">
342
+ <div class="controls">
343
+ <span style="font-weight:600; color:#0f172a;">View Mode:</span>
344
+ <button id="btn-fam" class="h-btn btn-models" style="padding:6px 15px; font-size:12px;" onclick="setASRMode('family')">By Family</button>
345
+ <button id="btn-mod" class="h-btn" style="background:#cbd5e1; color:#334155; padding:6px 15px; font-size:12px;" onclick="setASRMode('model')">By Model</button>
346
+
347
+ <div style="flex-grow:1; text-align:right;">
348
+ <div id="grp-fam" style="display:inline-block;">
349
+ <label>Select Family: </label>
350
+ <select id="asr-select-fam" onchange="renderASR()" style="padding:6px; border-radius:6px;"></select>
351
+ </div>
352
+ <div id="grp-mod" style="display:none;">
353
+ <label>Select Model: </label>
354
+ <select id="asr-select-mod" onchange="renderASR()" style="padding:6px; border-radius:6px;"></select>
355
+ </div>
356
+ </div>
357
  </div>
358
 
359
+ <h3 id="asr-title" style="color:#d97706; font-size:18px;"></h3>
360
+ <div id="asr-legend" style="background:#f1f5f9; padding:10px; font-size:13px; border-radius:6px; margin-bottom:15px; display:none;"></div>
361
+ <div id="asr-table" class="table-wrap"></div>
 
 
 
 
 
362
  </div>
 
 
 
 
363
 
364
+ <div id="tts" class="view">
365
+ <div class="controls">
366
+ <label>Select Model: </label>
367
+ <select id="tts-select" onchange="renderTTS()" style="padding:6px; border-radius:6px; min-width:250px;"></select>
 
368
  </div>
369
+ <h3 id="tts-title" style="color:#d97706; font-size:18px;"></h3>
370
+ <div id="tts-summary" style="margin-bottom:15px; font-weight:500;"></div>
371
+ <div id="tts-table" class="table-wrap"></div>
372
  </div>
 
 
 
373
 
374
+ <div id="slid" class="view">
375
+ <div id="slid-table" class="table-wrap"></div>
376
+ </div>
 
377
 
378
+ </div>
379
  </div>
 
380
 
381
+ <div style="text-align:center; color:#64748b; margin-top:40px;">
382
+ <p>&copy; 2025 Simba Benchmark. <a href="https://africa.dlnlp.ai/simba/" style="color:#d97706;">Official Website</a></p>
 
 
 
 
 
 
 
 
 
 
 
383
  </div>
 
384
 
 
 
 
385
  </div>
386
  </div>
387
 
388
  <script>
389
+ // --- DATA & LOGIC ---
390
  const NAME_TO_ISO = {
391
  'Afrikaans': 'afr', 'Akuapim-twi': 'ak', 'Amharic': 'amh', 'Asante-twi': 'tw',
392
  'Bemba': 'bem', 'Hausa': 'hau', 'Igbo': 'ibo', 'Yoruba': 'yor', 'Zulu': 'zul',
393
  'Swahili': 'swa', 'Somali': 'som', 'Wolof': 'wol', 'Xhosa': 'xho'
 
394
  };
395
 
396
  let DATA = null;
 
402
  document.getElementById('content').style.display='block';
403
  init();
404
  }).catch(e=>{
405
+ document.getElementById('loader').innerHTML = `<span style="color:red">Failed to load data.</span>`;
 
406
  });
407
 
408
  function init() {
 
416
  const s = document.getElementById(id); s.innerHTML='';
417
  list.forEach(i=>{ let o=document.createElement('option'); o.value=i; o.text=i; s.add(o); });
418
  }
 
419
  function fmt(n) { return (n==null)?'N/A':n.toFixed(2); }
420
+ function getIso(name) { return NAME_TO_ISO[name] || name.substring(0,3); }
421
 
422
+ // --- ASR ---
423
  function renderASR() {
424
  const div = document.getElementById('asr-table');
425
  const legend = document.getElementById('asr-legend');
426
  let html='';
427
 
428
+ if(asrMode==='family'){
429
  const val = document.getElementById('asr-select-fam').value;
430
+ document.getElementById('asr-title').innerText = `Results for Family: ${val}`;
431
+
432
  const d = DATA.asr.by_family[val];
433
  if(!d) return;
434
 
435
  // Legend
436
  legend.style.display = 'block';
437
+ legend.innerHTML = `<b>Codes:</b> ` + d.languages.map(l => `<span style="margin-right:10px"><b>${getIso(l)}</b>=${l}</span>`).join("");
438
 
439
  // Table
440
+ html = `<table><thead><tr><th>Model</th><th>Avg WER/CER <i class="fa-solid fa-arrow-down arrow-down"></i></th>`;
441
  d.languages.forEach(l => html += `<th>${getIso(l)}</th>`);
442
  html += `</tr></thead><tbody>`;
443
 
444
  d.data.forEach(r => {
445
+ html += `<tr><td>${r.Model}</td><td style="font-weight:bold; background:#f8fafc">${fmt(r.Avg_WER)} / ${fmt(r.Avg_CER)}</td>`;
 
 
446
  d.languages.forEach(l => {
447
+ let w=r[`WER_${l}`], c=r[`CER_${l}`];
448
  html += `<td>${(w!=null)?fmt(w)+'/'+fmt(c):'-'}</td>`;
449
  });
450
  html += `</tr>`;
451
  });
452
  } else {
453
  const val = document.getElementById('asr-select-mod').value;
454
+ document.getElementById('asr-title').innerText = `Results for Model: ${val}`;
455
  legend.style.display = 'none';
 
 
 
 
 
 
 
 
456
 
457
+ const rows = DATA.asr.by_model[val];
458
+ 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>`;
459
  rows.forEach(r => {
460
+ html += `<tr><td>${r.Language}</td><td>${r.Family}</td><td>${fmt(r.WER)}</td><td>${fmt(r.CER)}</td></tr>`;
 
 
 
 
 
461
  });
462
  }
463
  html += `</tbody></table>`;
464
  div.innerHTML = html;
465
  }
466
 
467
+ // --- TTS ---
468
  function renderTTS() {
469
  const val = document.getElementById('tts-select').value;
470
+ document.getElementById('tts-title').innerText = `Results for Model: ${val}`;
471
+
472
  const rows = DATA.tts[val];
473
  if(!rows) return;
474
 
 
480
  ];
481
 
482
  // Averages
483
+ let sums={}, c=0;
484
+ metrics.forEach(m=>sums[m.k]=0);
485
+ rows.forEach(r=>{ metrics.forEach(m=>sums[m.k]+=(r[m.k]||0)); c++; });
486
+
487
+ let sumHTML = metrics.map(m => `<span>${m.l}: <b>${fmt(sums[m.k]/c)}</b></span>`).join(" | ");
488
+ document.getElementById('tts-summary').innerHTML = "<b>Averages: </b>" + sumHTML;
489
 
490
  // Table
491
  let html = `<table><thead><tr><th>Language</th>`;
492
  metrics.forEach(m => {
493
  let icon = m.h ? 'up' : 'down';
494
+ let col = m.h ? 'green' : '#d97706';
495
+ html += `<th>${m.l} <i class="fa-solid fa-arrow-${icon}" style="color:${col}"></i></th>`;
496
  });
497
  html += `</tr></thead><tbody>`;
 
498
  rows.forEach(r => {
499
+ html += `<tr><td>${r.language}</td>`;
500
  metrics.forEach(m => html += `<td>${fmt(r[m.k])}</td>`);
501
  html += `</tr>`;
502
  });
 
504
  document.getElementById('tts-table').innerHTML = html;
505
  }
506
 
507
+ // --- SLID ---
508
  function renderSLID() {
509
+ let html = `<table><thead><tr><th>Language</th><th>MMS <i class="fa-solid fa-arrow-up arrow-up"></i></th><th>Simba <i class="fa-solid fa-arrow-up arrow-up"></i></th></tr></thead><tbody>`;
 
 
 
 
 
510
  DATA.slid.forEach(r => {
511
  let m = r['MMS-LID-1024'], s = r['Simba-SLID'];
512
  let mS = fmt(m), sS = fmt(s);
513
+ if(m > s) mS = `<b style="color:green">${mS}</b>`; else if(s > m) sS = `<b style="color:green">${sS}</b>`;
514
+ html += `<tr><td>${r.Language}</td><td>${mS}</td><td>${sS}</td></tr>`;
 
515
  });
516
  html += `</tbody></table>`;
517
  document.getElementById('slid-table').innerHTML = html;
518
  }
519
 
520
+ // --- UI ---
521
  window.setTab = (id, btn) => {
522
  document.querySelectorAll('.view').forEach(e => e.classList.remove('active'));
523
  document.querySelectorAll('.tab-btn').forEach(e => e.classList.remove('active'));
 
527
 
528
  window.setASRMode = (m) => {
529
  asrMode = m;
530
+ document.getElementById('grp-fam').style.display = m==='family'?'inline-block':'none';
531
+ document.getElementById('grp-mod').style.display = m==='model'?'inline-block':'none';
532
+
533
+ // Update button styles
534
+ const b1 = document.getElementById('btn-fam');
535
+ const b2 = document.getElementById('btn-mod');
536
+ if(m==='family') {
537
+ b1.className = "h-btn btn-models"; b1.style.background = "var(--grad-blue)"; b1.style.color="white";
538
+ b2.className = "h-btn"; b2.style.background = "#cbd5e1"; b2.style.color="#334155";
539
+ } else {
540
+ b2.className = "h-btn btn-models"; b2.style.background = "var(--grad-blue)"; b2.style.color="white";
541
+ b1.className = "h-btn"; b1.style.background = "#cbd5e1"; b1.style.color="#334155";
542
+ }
543
  renderASR();
544
  }
545
  </script>