wangruisi1 commited on
Commit
39b9fcf
·
1 Parent(s): bcd35c0

Add color to each columns, expand the columns

Browse files
Files changed (2) hide show
  1. app.py +16 -13
  2. src/display/css_html_js.py +110 -3
app.py CHANGED
@@ -10,7 +10,7 @@ from src.about import (
10
  LLM_BENCHMARKS_TEXT,
11
  TITLE,
12
  )
13
- from src.display.css_html_js import custom_css
14
 
15
 
16
  # ============================================================
@@ -23,11 +23,11 @@ COLUMN_GROUPS = OrderedDict([
23
  ("Overall by Category", [
24
  "Abst.(All)", "Know.(All)", "Perc.(All)", "Spat.(All)", "Trans.(All)",
25
  ]),
26
- ("In-Domain (ID)", ["ID"]),
27
  ("In-Domain by Category", [
28
  "Abst.(ID)", "Know.(ID)", "Perc.(ID)", "Spat.(ID)", "Trans.(ID)",
29
  ]),
30
- ("Out-of-Domain (OOD)", ["OOD"]),
31
  ("Out-of-Domain by Category", [
32
  "Abst.(OOD)", "Know.(OOD)", "Perc.(OOD)", "Spat.(OOD)", "Trans.(OOD)",
33
  ]),
@@ -72,7 +72,7 @@ MODELS_DATA = [
72
  {
73
  "Model": "Human",
74
  "Type": "👤 Reference",
75
- "Overall": 0.974, "ID": 0.960, "OOD": 0.988,
76
  "Abst.(All)": 0.947, "Know.(All)": 0.972, "Perc.(All)": 0.994, "Spat.(All)": 0.969, "Trans.(All)": 0.981,
77
  "Abst.(ID)": 0.919, "Know.(ID)": 0.956, "Perc.(ID)": 1.000, "Spat.(ID)": 0.950, "Trans.(ID)": 1.000,
78
  "Abst.(OOD)": 1.000, "Know.(OOD)": 1.000, "Perc.(OOD)": 0.990, "Spat.(OOD)": 1.000, "Trans.(OOD)": 0.970,
@@ -81,7 +81,7 @@ MODELS_DATA = [
81
  {
82
  "Model": "CogVideoX1.5-5B-I2V",
83
  "Type": "🟢 Open-source",
84
- "Overall": 0.2727, "ID": 0.2831, "OOD": 0.2623,
85
  "Abst.(All)": 0.2548, "Know.(All)": 0.2952, "Perc.(All)": 0.2525, "Spat.(All)": 0.2996, "Trans.(All)": 0.2903,
86
  "Abst.(ID)": 0.2408, "Know.(ID)": 0.3285, "Perc.(ID)": 0.2567, "Spat.(ID)": 0.3281, "Trans.(ID)": 0.3051,
87
  "Abst.(OOD)": 0.2809, "Know.(OOD)": 0.2352, "Perc.(OOD)": 0.2501, "Spat.(OOD)": 0.2539, "Trans.(OOD)": 0.2824,
@@ -89,7 +89,7 @@ MODELS_DATA = [
89
  {
90
  "Model": "HunyuanVideo-I2V",
91
  "Type": "🟢 Open-source",
92
- "Overall": 0.2726, "ID": 0.2799, "OOD": 0.2653,
93
  "Abst.(All)": 0.1956, "Know.(All)": 0.3614, "Perc.(All)": 0.2910, "Spat.(All)": 0.2698, "Trans.(All)": 0.2733,
94
  "Abst.(ID)": 0.2068, "Know.(ID)": 0.3573, "Perc.(ID)": 0.2933, "Spat.(ID)": 0.2802, "Trans.(ID)": 0.3160,
95
  "Abst.(OOD)": 0.1747, "Know.(OOD)": 0.3688, "Perc.(OOD)": 0.2897, "Spat.(OOD)": 0.2530, "Trans.(OOD)": 0.2502,
@@ -97,7 +97,7 @@ MODELS_DATA = [
97
  {
98
  "Model": "Wan2.2-I2V-A14B",
99
  "Type": "🟢 Open-source",
100
- "Overall": 0.3714, "ID": 0.4125, "OOD": 0.3287,
101
  "Abst.(All)": 0.4212, "Know.(All)": 0.3556, "Perc.(All)": 0.3710, "Spat.(All)": 0.3397, "Trans.(All)": 0.3465,
102
  "Abst.(ID)": 0.4301, "Know.(ID)": 0.3823, "Perc.(ID)": 0.4147, "Spat.(ID)": 0.4043, "Trans.(ID)": 0.4192,
103
  "Abst.(OOD)": 0.4046, "Know.(OOD)": 0.3077, "Perc.(OOD)": 0.3427, "Spat.(OOD)": 0.2364, "Trans.(OOD)": 0.3073,
@@ -105,7 +105,7 @@ MODELS_DATA = [
105
  {
106
  "Model": "LTX-2",
107
  "Type": "🟢 Open-source",
108
- "Overall": 0.3129, "ID": 0.3287, "OOD": 0.2971,
109
  "Abst.(All)": 0.2908, "Know.(All)": 0.3531, "Perc.(All)": 0.3200, "Spat.(All)": 0.2980, "Trans.(All)": 0.3093,
110
  "Abst.(ID)": 0.3156, "Know.(ID)": 0.3621, "Perc.(ID)": 0.3257, "Spat.(ID)": 0.3399, "Trans.(ID)": 0.3060,
111
  "Abst.(OOD)": 0.2444, "Know.(OOD)": 0.3369, "Perc.(OOD)": 0.3167, "Spat.(OOD)": 0.2308, "Trans.(OOD)": 0.3110,
@@ -114,7 +114,7 @@ MODELS_DATA = [
114
  {
115
  "Model": "Runway Gen-4 Turbo",
116
  "Type": "🔵 Proprietary",
117
- "Overall": 0.4031, "ID": 0.3920, "OOD": 0.4141,
118
  "Abst.(All)": 0.4370, "Know.(All)": 0.4165, "Perc.(All)": 0.4223, "Spat.(All)": 0.3357, "Trans.(All)": 0.3696,
119
  "Abst.(ID)": 0.3956, "Know.(ID)": 0.4094, "Perc.(ID)": 0.4288, "Spat.(ID)": 0.3409, "Trans.(ID)": 0.3629,
120
  "Abst.(OOD)": 0.5147, "Know.(OOD)": 0.4294, "Perc.(OOD)": 0.4185, "Spat.(OOD)": 0.3274, "Trans.(OOD)": 0.3733,
@@ -122,7 +122,7 @@ MODELS_DATA = [
122
  {
123
  "Model": "Sora 2",
124
  "Type": "🔵 Proprietary",
125
- "Overall": 0.5457, "ID": 0.5691, "OOD": 0.5225,
126
  "Abst.(All)": 0.5824, "Know.(All)": 0.4749, "Perc.(All)": 0.5458, "Spat.(All)": 0.5298, "Trans.(All)": 0.5640,
127
  "Abst.(ID)": 0.6023, "Know.(ID)": 0.4767, "Perc.(ID)": 0.5810, "Spat.(ID)": 0.5720, "Trans.(ID)": 0.5967,
128
  "Abst.(OOD)": 0.5462, "Know.(OOD)": 0.4715, "Perc.(OOD)": 0.5254, "Spat.(OOD)": 0.4623, "Trans.(OOD)": 0.5465,
@@ -130,7 +130,7 @@ MODELS_DATA = [
130
  {
131
  "Model": "Kling 2.6",
132
  "Type": "🔵 Proprietary",
133
- "Overall": 0.3691, "ID": 0.4082, "OOD": 0.3300,
134
  "Abst.(All)": 0.4866, "Know.(All)": 0.2556, "Perc.(All)": 0.3095, "Spat.(All)": 0.3504, "Trans.(All)": 0.4149,
135
  "Abst.(ID)": 0.4647, "Know.(ID)": 0.3225, "Perc.(ID)": 0.3749, "Spat.(ID)": 0.3471, "Trans.(ID)": 0.5193,
136
  "Abst.(OOD)": 0.5277, "Know.(OOD)": 0.1350, "Perc.(OOD)": 0.2717, "Spat.(OOD)": 0.3556, "Trans.(OOD)": 0.3588,
@@ -138,7 +138,7 @@ MODELS_DATA = [
138
  {
139
  "Model": "Veo 3.1",
140
  "Type": "🔵 Proprietary",
141
- "Overall": 0.4800, "ID": 0.5307, "OOD": 0.4288,
142
  "Abst.(All)": 0.5991, "Know.(All)": 0.4225, "Perc.(All)": 0.4568, "Spat.(All)": 0.4430, "Trans.(All)": 0.4413,
143
  "Abst.(ID)": 0.6109, "Know.(ID)": 0.5032, "Perc.(ID)": 0.5196, "Spat.(ID)": 0.4443, "Trans.(ID)": 0.5103,
144
  "Abst.(OOD)": 0.5770, "Know.(OOD)": 0.2772, "Perc.(OOD)": 0.4204, "Spat.(OOD)": 0.4406, "Trans.(OOD)": 0.4041,
@@ -147,7 +147,7 @@ MODELS_DATA = [
147
  {
148
  "Model": "VBVR-Wan2.2",
149
  "Type": "⭐ Strong Baseline",
150
- "Overall": 0.6848, "ID": 0.7599, "OOD": 0.6097,
151
  "Abst.(All)": 0.7394, "Know.(All)": 0.6864, "Perc.(All)": 0.6333, "Spat.(All)": 0.6960, "Trans.(All)": 0.6909,
152
  "Abst.(ID)": 0.7240, "Know.(ID)": 0.7500, "Perc.(ID)": 0.7817, "Spat.(ID)": 0.7446, "Trans.(ID)": 0.8327,
153
  "Abst.(OOD)": 0.7682, "Know.(OOD)": 0.5720, "Perc.(OOD)": 0.5474, "Spat.(OOD)": 0.6182, "Trans.(OOD)": 0.6145,
@@ -236,4 +236,7 @@ with demo:
236
  show_copy_button=True,
237
  )
238
 
 
 
 
239
  demo.queue(default_concurrency_limit=40).launch()
 
10
  LLM_BENCHMARKS_TEXT,
11
  TITLE,
12
  )
13
+ from src.display.css_html_js import custom_css, COLOR_COLUMNS_JS
14
 
15
 
16
  # ============================================================
 
23
  ("Overall by Category", [
24
  "Abst.(All)", "Know.(All)", "Perc.(All)", "Spat.(All)", "Trans.(All)",
25
  ]),
26
+ ("In-Domain (ID)", ["Overall(In-Domain)"]),
27
  ("In-Domain by Category", [
28
  "Abst.(ID)", "Know.(ID)", "Perc.(ID)", "Spat.(ID)", "Trans.(ID)",
29
  ]),
30
+ ("Out-of-Domain (OOD)", ["Overall(Out-of-Domain)"]),
31
  ("Out-of-Domain by Category", [
32
  "Abst.(OOD)", "Know.(OOD)", "Perc.(OOD)", "Spat.(OOD)", "Trans.(OOD)",
33
  ]),
 
72
  {
73
  "Model": "Human",
74
  "Type": "👤 Reference",
75
+ "Overall": 0.974, "Overall(In-Domain)": 0.960, "Overall(Out-of-Domain)": 0.988,
76
  "Abst.(All)": 0.947, "Know.(All)": 0.972, "Perc.(All)": 0.994, "Spat.(All)": 0.969, "Trans.(All)": 0.981,
77
  "Abst.(ID)": 0.919, "Know.(ID)": 0.956, "Perc.(ID)": 1.000, "Spat.(ID)": 0.950, "Trans.(ID)": 1.000,
78
  "Abst.(OOD)": 1.000, "Know.(OOD)": 1.000, "Perc.(OOD)": 0.990, "Spat.(OOD)": 1.000, "Trans.(OOD)": 0.970,
 
81
  {
82
  "Model": "CogVideoX1.5-5B-I2V",
83
  "Type": "🟢 Open-source",
84
+ "Overall": 0.2727, "Overall(In-Domain)": 0.2831, "Overall(Out-of-Domain)": 0.2623,
85
  "Abst.(All)": 0.2548, "Know.(All)": 0.2952, "Perc.(All)": 0.2525, "Spat.(All)": 0.2996, "Trans.(All)": 0.2903,
86
  "Abst.(ID)": 0.2408, "Know.(ID)": 0.3285, "Perc.(ID)": 0.2567, "Spat.(ID)": 0.3281, "Trans.(ID)": 0.3051,
87
  "Abst.(OOD)": 0.2809, "Know.(OOD)": 0.2352, "Perc.(OOD)": 0.2501, "Spat.(OOD)": 0.2539, "Trans.(OOD)": 0.2824,
 
89
  {
90
  "Model": "HunyuanVideo-I2V",
91
  "Type": "🟢 Open-source",
92
+ "Overall": 0.2726, "Overall(In-Domain)": 0.2799, "Overall(Out-of-Domain)": 0.2653,
93
  "Abst.(All)": 0.1956, "Know.(All)": 0.3614, "Perc.(All)": 0.2910, "Spat.(All)": 0.2698, "Trans.(All)": 0.2733,
94
  "Abst.(ID)": 0.2068, "Know.(ID)": 0.3573, "Perc.(ID)": 0.2933, "Spat.(ID)": 0.2802, "Trans.(ID)": 0.3160,
95
  "Abst.(OOD)": 0.1747, "Know.(OOD)": 0.3688, "Perc.(OOD)": 0.2897, "Spat.(OOD)": 0.2530, "Trans.(OOD)": 0.2502,
 
97
  {
98
  "Model": "Wan2.2-I2V-A14B",
99
  "Type": "🟢 Open-source",
100
+ "Overall": 0.3714, "Overall(In-Domain)": 0.4125, "Overall(Out-of-Domain)": 0.3287,
101
  "Abst.(All)": 0.4212, "Know.(All)": 0.3556, "Perc.(All)": 0.3710, "Spat.(All)": 0.3397, "Trans.(All)": 0.3465,
102
  "Abst.(ID)": 0.4301, "Know.(ID)": 0.3823, "Perc.(ID)": 0.4147, "Spat.(ID)": 0.4043, "Trans.(ID)": 0.4192,
103
  "Abst.(OOD)": 0.4046, "Know.(OOD)": 0.3077, "Perc.(OOD)": 0.3427, "Spat.(OOD)": 0.2364, "Trans.(OOD)": 0.3073,
 
105
  {
106
  "Model": "LTX-2",
107
  "Type": "🟢 Open-source",
108
+ "Overall": 0.3129, "Overall(In-Domain)": 0.3287, "Overall(Out-of-Domain)": 0.2971,
109
  "Abst.(All)": 0.2908, "Know.(All)": 0.3531, "Perc.(All)": 0.3200, "Spat.(All)": 0.2980, "Trans.(All)": 0.3093,
110
  "Abst.(ID)": 0.3156, "Know.(ID)": 0.3621, "Perc.(ID)": 0.3257, "Spat.(ID)": 0.3399, "Trans.(ID)": 0.3060,
111
  "Abst.(OOD)": 0.2444, "Know.(OOD)": 0.3369, "Perc.(OOD)": 0.3167, "Spat.(OOD)": 0.2308, "Trans.(OOD)": 0.3110,
 
114
  {
115
  "Model": "Runway Gen-4 Turbo",
116
  "Type": "🔵 Proprietary",
117
+ "Overall": 0.4031, "Overall(In-Domain)": 0.3920, "Overall(Out-of-Domain)": 0.4141,
118
  "Abst.(All)": 0.4370, "Know.(All)": 0.4165, "Perc.(All)": 0.4223, "Spat.(All)": 0.3357, "Trans.(All)": 0.3696,
119
  "Abst.(ID)": 0.3956, "Know.(ID)": 0.4094, "Perc.(ID)": 0.4288, "Spat.(ID)": 0.3409, "Trans.(ID)": 0.3629,
120
  "Abst.(OOD)": 0.5147, "Know.(OOD)": 0.4294, "Perc.(OOD)": 0.4185, "Spat.(OOD)": 0.3274, "Trans.(OOD)": 0.3733,
 
122
  {
123
  "Model": "Sora 2",
124
  "Type": "🔵 Proprietary",
125
+ "Overall": 0.5457, "Overall(In-Domain)": 0.5691, "Overall(Out-of-Domain)": 0.5225,
126
  "Abst.(All)": 0.5824, "Know.(All)": 0.4749, "Perc.(All)": 0.5458, "Spat.(All)": 0.5298, "Trans.(All)": 0.5640,
127
  "Abst.(ID)": 0.6023, "Know.(ID)": 0.4767, "Perc.(ID)": 0.5810, "Spat.(ID)": 0.5720, "Trans.(ID)": 0.5967,
128
  "Abst.(OOD)": 0.5462, "Know.(OOD)": 0.4715, "Perc.(OOD)": 0.5254, "Spat.(OOD)": 0.4623, "Trans.(OOD)": 0.5465,
 
130
  {
131
  "Model": "Kling 2.6",
132
  "Type": "🔵 Proprietary",
133
+ "Overall": 0.3691, "Overall(In-Domain)": 0.4082, "Overall(Out-of-Domain)": 0.3300,
134
  "Abst.(All)": 0.4866, "Know.(All)": 0.2556, "Perc.(All)": 0.3095, "Spat.(All)": 0.3504, "Trans.(All)": 0.4149,
135
  "Abst.(ID)": 0.4647, "Know.(ID)": 0.3225, "Perc.(ID)": 0.3749, "Spat.(ID)": 0.3471, "Trans.(ID)": 0.5193,
136
  "Abst.(OOD)": 0.5277, "Know.(OOD)": 0.1350, "Perc.(OOD)": 0.2717, "Spat.(OOD)": 0.3556, "Trans.(OOD)": 0.3588,
 
138
  {
139
  "Model": "Veo 3.1",
140
  "Type": "🔵 Proprietary",
141
+ "Overall": 0.4800, "Overall(In-Domain)": 0.5307, "Overall(Out-of-Domain)": 0.4288,
142
  "Abst.(All)": 0.5991, "Know.(All)": 0.4225, "Perc.(All)": 0.4568, "Spat.(All)": 0.4430, "Trans.(All)": 0.4413,
143
  "Abst.(ID)": 0.6109, "Know.(ID)": 0.5032, "Perc.(ID)": 0.5196, "Spat.(ID)": 0.4443, "Trans.(ID)": 0.5103,
144
  "Abst.(OOD)": 0.5770, "Know.(OOD)": 0.2772, "Perc.(OOD)": 0.4204, "Spat.(OOD)": 0.4406, "Trans.(OOD)": 0.4041,
 
147
  {
148
  "Model": "VBVR-Wan2.2",
149
  "Type": "⭐ Strong Baseline",
150
+ "Overall": 0.6848, "Overall(In-Domain)": 0.7599, "Overall(Out-of-Domain)": 0.6097,
151
  "Abst.(All)": 0.7394, "Know.(All)": 0.6864, "Perc.(All)": 0.6333, "Spat.(All)": 0.6960, "Trans.(All)": 0.6909,
152
  "Abst.(ID)": 0.7240, "Know.(ID)": 0.7500, "Perc.(ID)": 0.7817, "Spat.(ID)": 0.7446, "Trans.(ID)": 0.8327,
153
  "Abst.(OOD)": 0.7682, "Know.(OOD)": 0.5720, "Perc.(OOD)": 0.5474, "Spat.(OOD)": 0.6182, "Trans.(OOD)": 0.6145,
 
236
  show_copy_button=True,
237
  )
238
 
239
+ # Inject JS to dynamically color columns based on header text
240
+ gr.HTML(f"<script>{COLOR_COLUMNS_JS}</script>")
241
+
242
  demo.queue(default_concurrency_limit=40).launch()
src/display/css_html_js.py CHANGED
@@ -38,14 +38,31 @@ custom_css = """
38
  padding: 0px;
39
  }
40
 
41
- /* Limit the width of the first AutoEvalColumn so that names don't expand too much */
 
 
 
 
 
 
 
42
  #leaderboard-table td:nth-child(2),
43
  #leaderboard-table th:nth-child(2) {
44
- max-width: 400px;
45
- overflow: auto;
46
  white-space: nowrap;
47
  }
48
 
 
 
 
 
 
 
 
 
 
 
 
49
  .tab-buttons button {
50
  font-size: 20px;
51
  }
@@ -94,6 +111,37 @@ custom_css = """
94
  #box-filter > .form{
95
  border: 0
96
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97
  """
98
 
99
  get_window_url_params = """
@@ -103,3 +151,62 @@ get_window_url_params = """
103
  return url_params;
104
  }
105
  """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  padding: 0px;
39
  }
40
 
41
+ /* Model column wider to avoid truncation */
42
+ #leaderboard-table td:nth-child(1),
43
+ #leaderboard-table th:nth-child(1) {
44
+ min-width: 220px !important;
45
+ white-space: nowrap;
46
+ }
47
+
48
+ /* Type column — wider to avoid truncation */
49
  #leaderboard-table td:nth-child(2),
50
  #leaderboard-table th:nth-child(2) {
51
+ min-width: 170px !important;
 
52
  white-space: nowrap;
53
  }
54
 
55
+ /* Model links: underline + hover color */
56
+ #leaderboard-table td a {
57
+ color: #2563eb;
58
+ text-decoration: underline;
59
+ text-underline-offset: 2px;
60
+ transition: color 0.2s ease;
61
+ }
62
+ #leaderboard-table td a:hover {
63
+ color: #d97706;
64
+ }
65
+
66
  .tab-buttons button {
67
  font-size: 20px;
68
  }
 
111
  #box-filter > .form{
112
  border: 0
113
  }
114
+
115
+ /* ============================================================
116
+ Column group color coding for leaderboard table
117
+ Soft, harmonious palette with dark/light pairs per group.
118
+ Applied dynamically via JS based on column header text.
119
+ ============================================================ */
120
+
121
+ /* Overall (dark amber) */
122
+ #leaderboard-table .col-overall-dark {
123
+ background-color: rgba(232, 180, 58, 0.30) !important;
124
+ }
125
+ /* Overall by Category (light amber) */
126
+ #leaderboard-table .col-overall-light {
127
+ background-color: rgba(242, 200, 90, 0.15) !important;
128
+ }
129
+ /* In-Domain Overall (dark green) */
130
+ #leaderboard-table .col-id-dark {
131
+ background-color: rgba(82, 183, 120, 0.30) !important;
132
+ }
133
+ /* In-Domain by Category (light green) */
134
+ #leaderboard-table .col-id-light {
135
+ background-color: rgba(110, 200, 145, 0.15) !important;
136
+ }
137
+ /* Out-of-Domain Overall (dark blue) */
138
+ #leaderboard-table .col-ood-dark {
139
+ background-color: rgba(95, 150, 215, 0.30) !important;
140
+ }
141
+ /* Out-of-Domain by Category (light blue) */
142
+ #leaderboard-table .col-ood-light {
143
+ background-color: rgba(125, 175, 228, 0.15) !important;
144
+ }
145
  """
146
 
147
  get_window_url_params = """
 
151
  return url_params;
152
  }
153
  """
154
+
155
+ # JavaScript to dynamically color columns based on header text.
156
+ # Runs on load and re-runs via MutationObserver whenever the table updates.
157
+ COLOR_COLUMNS_JS = """
158
+ function colorLeaderboardColumns() {
159
+ const table = document.querySelector('#leaderboard-table table');
160
+ if (!table) return;
161
+
162
+ const headers = table.querySelectorAll('thead th');
163
+ if (!headers.length) return;
164
+
165
+ // Map header text -> color class
166
+ const colorMap = {};
167
+ headers.forEach((th, idx) => {
168
+ const text = th.textContent.trim();
169
+ let cls = '';
170
+ if (text === 'Overall') {
171
+ cls = 'col-overall-dark';
172
+ } else if (text.includes('(All)')) {
173
+ cls = 'col-overall-light';
174
+ } else if (text === 'Overall(In-Domain)') {
175
+ cls = 'col-id-dark';
176
+ } else if (text.includes('(ID)')) {
177
+ cls = 'col-id-light';
178
+ } else if (text === 'Overall(Out-of-Domain)') {
179
+ cls = 'col-ood-dark';
180
+ } else if (text.includes('(OOD)')) {
181
+ cls = 'col-ood-light';
182
+ }
183
+ colorMap[idx] = cls;
184
+
185
+ // Apply to header cell
186
+ th.classList.remove('col-overall-dark','col-overall-light','col-id-dark','col-id-light','col-ood-dark','col-ood-light');
187
+ if (cls) th.classList.add(cls);
188
+ });
189
+
190
+ // Apply to body cells
191
+ const rows = table.querySelectorAll('tbody tr');
192
+ rows.forEach(row => {
193
+ const cells = row.querySelectorAll('td');
194
+ cells.forEach((td, idx) => {
195
+ td.classList.remove('col-overall-dark','col-overall-light','col-id-dark','col-id-light','col-ood-dark','col-ood-light');
196
+ if (colorMap[idx]) td.classList.add(colorMap[idx]);
197
+ });
198
+ });
199
+ }
200
+
201
+ // Run on initial load
202
+ setTimeout(colorLeaderboardColumns, 500);
203
+
204
+ // Re-run when table changes (column toggle, etc.)
205
+ const observer = new MutationObserver(() => {
206
+ setTimeout(colorLeaderboardColumns, 100);
207
+ });
208
+ const target = document.querySelector('#leaderboard-table');
209
+ if (target) {
210
+ observer.observe(target, { childList: true, subtree: true });
211
+ }
212
+ """