TriWorldBench commited on
Commit
f0a4442
·
verified ·
1 Parent(s): a0365a2

Update TriWorldBench web from desktop manager

Browse files
.gitattributes CHANGED
@@ -1,2 +1,3 @@
1
  *.mp4 filter=lfs diff=lfs merge=lfs -text
2
  *.pdf filter=lfs diff=lfs merge=lfs -text
 
 
1
  *.mp4 filter=lfs diff=lfs merge=lfs -text
2
  *.pdf filter=lfs diff=lfs merge=lfs -text
3
+ public/assets_common/photos/Group_Chat.jpg filter=lfs diff=lfs merge=lfs -text
Dockerfile CHANGED
@@ -16,4 +16,4 @@ ENV TRIWORLDBENCH_VIDEO_ROOT=/tmp/triworldbench/video-cases
16
 
17
  EXPOSE 7860
18
 
19
- CMD ["sh", "-c", "npm run hf:download-dataset && npm run hf:download-video-cases && npm run hf:restore-space-assets && npx next start -H 0.0.0.0 -p ${PORT:-7860}"]
 
16
 
17
  EXPOSE 7860
18
 
19
+ CMD ["sh", "-c", "npm run hf:download-dataset && npm run hf:sanitize-public-dataset && npm run hf:download-video-cases && npm run hf:restore-space-assets && npx next start -H 0.0.0.0 -p ${PORT:-7860}"]
deployment-manifest.json CHANGED
@@ -1,8 +1,8 @@
1
  {
2
  "schema": 2,
3
- "generated_at_utc": "2026-08-09T11:14:08.858574+00:00",
4
- "web_tree_sha256": "bd27feeb2178e767fb0e305cd25b8e7f0a8d934357c7a11424f75723e40576d5",
5
- "source_file_count": 89,
6
  "release_contract": {
7
  "web_source": "TriWorldBench/web",
8
  "local_database": "database/database.sqlite",
@@ -13,8 +13,8 @@
13
  },
14
  "database_release": {
15
  "dataset_file": "database.sqlite",
16
- "snapshot_sha256": "0c7da7bac39215ca55396839eab8fed6872bfbe782f6e908a021ea15464d3acd",
17
- "data_version": 264,
18
  "video_count": 24,
19
  "video_prefix": "video-cases"
20
  }
 
1
  {
2
  "schema": 2,
3
+ "generated_at_utc": "2026-08-14T12:00:38.227389+00:00",
4
+ "web_tree_sha256": "8c12cc89b824c4104f5cee92366b440fb716057cce0b1d09b6890b7baff3a818",
5
+ "source_file_count": 90,
6
  "release_contract": {
7
  "web_source": "TriWorldBench/web",
8
  "local_database": "database/database.sqlite",
 
13
  },
14
  "database_release": {
15
  "dataset_file": "database.sqlite",
16
+ "snapshot_sha256": "afc2a632e2c3df54014b0e2d0ea996b64427a53b31b0ad810e98cee6f0fcaa78",
17
+ "data_version": 275,
18
  "video_count": 24,
19
  "video_prefix": "video-cases"
20
  }
package.json CHANGED
@@ -8,6 +8,7 @@
8
  "build": "next build",
9
  "start": "next start",
10
  "hf:download-dataset": "node scripts/download-dataset.mjs",
 
11
  "hf:download-video-cases": "node scripts/download-video-cases.mjs",
12
  "hf:restore-space-assets": "node scripts/restore-space-assets.mjs"
13
  },
 
8
  "build": "next build",
9
  "start": "next start",
10
  "hf:download-dataset": "node scripts/download-dataset.mjs",
11
+ "hf:sanitize-public-dataset": "node scripts/sanitize-public-database.mjs",
12
  "hf:download-video-cases": "node scripts/download-video-cases.mjs",
13
  "hf:restore-space-assets": "node scripts/restore-space-assets.mjs"
14
  },
public/assets_common/photos/Group_Chat.jpg CHANGED

Git LFS Details

  • SHA256: f15b03eb0914f98df3169407e9e783f99680647dd9d9874bd5ffe2e47cc450b1
  • Pointer size: 131 Bytes
  • Size of remote file: 140 kB

Git LFS Details

  • SHA256: b6e5091783b3a4b675eeda50d734b0f300cffcd2125a9fd4caf2d7975a43520a
  • Pointer size: 131 Bytes
  • Size of remote file: 132 kB
scripts/sanitize-public-database.mjs ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import fs from "node:fs";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import { DatabaseSync } from "node:sqlite";
5
+
6
+ const targetPath = path.resolve(
7
+ process.env.TRIWORLDBENCH_DB_PATH || path.join(os.tmpdir(), "triworldbench", "database.sqlite")
8
+ );
9
+ const temporaryRoot = path.resolve(os.tmpdir());
10
+
11
+ if (process.env.TRIWORLDBENCH_PUBLIC_READONLY !== "1") {
12
+ throw new Error("Refusing to sanitize a database outside public read-only mode.");
13
+ }
14
+ if (targetPath !== temporaryRoot && !targetPath.startsWith(`${temporaryRoot}${path.sep}`)) {
15
+ throw new Error(`Refusing to sanitize a database outside the temporary directory: ${targetPath}`);
16
+ }
17
+ if (!fs.existsSync(targetPath)) {
18
+ throw new Error(`Downloaded public database was not found: ${targetPath}`);
19
+ }
20
+
21
+ const database = new DatabaseSync(targetPath);
22
+ try {
23
+ database.exec(`
24
+ BEGIN IMMEDIATE;
25
+ UPDATE teams
26
+ SET slug = 'public-team-' || id,
27
+ name = 'Private participant',
28
+ participant_email = 'private-' || id || '@invalid.local',
29
+ affiliation = NULL,
30
+ country_region = NULL,
31
+ strengths = NULL,
32
+ updated_at = CURRENT_TIMESTAMP;
33
+ UPDATE models
34
+ SET model_card_url = NULL,
35
+ brief_introduction = NULL;
36
+ UPDATE submissions
37
+ SET artifact_uri = NULL,
38
+ notes = NULL;
39
+ COMMIT;
40
+ PRAGMA wal_checkpoint(TRUNCATE);
41
+ `);
42
+ const integrity = database.prepare("PRAGMA integrity_check").get();
43
+ if (integrity.integrity_check !== "ok") {
44
+ throw new Error(`Public database integrity check failed: ${integrity.integrity_check}`);
45
+ }
46
+ } catch (error) {
47
+ try {
48
+ database.exec("ROLLBACK");
49
+ } catch {
50
+ // No active transaction remains after a successful commit.
51
+ }
52
+ throw error;
53
+ } finally {
54
+ database.close();
55
+ }
56
+
57
+ console.log("Public runtime database identity fields sanitized.");
src/app/(site)/page.tsx CHANGED
@@ -216,7 +216,6 @@ function toBoardEntries(entries: LeaderboardEntry[]): TriWorldBoardEntry[] {
216
  return {
217
  rank: entry.rank,
218
  modelName: entry.model.name,
219
- teamName: entry.team.name,
220
  score: entry.metrics[TRIWORLD_RANKING_CODE]?.rawValue ?? entry.score.rawValue ?? null,
221
  normalizedScore: entry.metrics[TRIWORLD_RANKING_CODE]?.rawValue ?? entry.score.rawValue ?? null,
222
  status: entry.statusLabel || entry.submission.status,
@@ -449,7 +448,6 @@ function LeaderboardTable({
449
  <tr key={row.modelName}>
450
  <td className="twb-model-col twb-sticky-col">
451
  <b>{row.modelName}</b>
452
- <small>{row.teamName}</small>
453
  </td>
454
  <td className="twb-col-rank twb-sticky-rank">
455
  <span className={`twb-rank-badge rank-${Math.min(row.rank, 4)}`}>
 
216
  return {
217
  rank: entry.rank,
218
  modelName: entry.model.name,
 
219
  score: entry.metrics[TRIWORLD_RANKING_CODE]?.rawValue ?? entry.score.rawValue ?? null,
220
  normalizedScore: entry.metrics[TRIWORLD_RANKING_CODE]?.rawValue ?? entry.score.rawValue ?? null,
221
  status: entry.statusLabel || entry.submission.status,
 
448
  <tr key={row.modelName}>
449
  <td className="twb-model-col twb-sticky-col">
450
  <b>{row.modelName}</b>
 
451
  </td>
452
  <td className="twb-col-rank twb-sticky-rank">
453
  <span className={`twb-rank-badge rank-${Math.min(row.rank, 4)}`}>
src/components/triworldbench/ClientSections.tsx CHANGED
@@ -429,7 +429,11 @@ function OverallRadar({
429
  style={{ "--c": color, "--dash": dashPattern } as React.CSSProperties}
430
  >
431
  <polygon className="twb-radar-area" points={points} />
432
- <polyline className="twb-radar-line" points={`${points} ${points.split(" ")[0]}`} />
 
 
 
 
433
  </g>
434
  );
435
  })}
 
429
  style={{ "--c": color, "--dash": dashPattern } as React.CSSProperties}
430
  >
431
  <polygon className="twb-radar-area" points={points} />
432
+ <polyline
433
+ className="twb-radar-line"
434
+ fill="none"
435
+ points={`${points} ${points.split(" ")[0]}`}
436
+ />
437
  </g>
438
  );
439
  })}
src/components/triworldbench/Leaderboard.tsx CHANGED
@@ -94,6 +94,7 @@ export function TriWorldLeaderboard({ rows, metricTexts, descriptionText }: Prop
94
  const [highlightedName, setHighlightedName] = useState<string | null>(null);
95
  const [message, setMessage] = useState("");
96
  const rangeMenuRef = useRef<HTMLDetailsElement>(null);
 
97
  const rowRefs = useRef(new Map<string, HTMLTableRowElement>());
98
 
99
  const ranges = useMemo(() => {
@@ -129,6 +130,24 @@ export function TriWorldLeaderboard({ rows, metricTexts, descriptionText }: Prop
129
  return ranksByMetric;
130
  }, [rows]);
131
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
132
  const locate = useCallback((name = query) => {
133
  const normalized = name.trim().toLocaleLowerCase();
134
  if (!normalized) {
@@ -147,9 +166,9 @@ export function TriWorldLeaderboard({ rows, metricTexts, descriptionText }: Prop
147
  setHighlightedName(matched.modelName);
148
  setMessage(`Located ${matched.modelName} at rank ${matched.rank}.`);
149
  window.requestAnimationFrame(() => {
150
- rowRefs.current.get(matched.modelName)?.scrollIntoView({ behavior: "smooth", block: "center", inline: "nearest" });
151
  });
152
- }, [query, rows]);
153
 
154
  const jumpToRange = (start: number) => {
155
  const row = rows[start];
@@ -158,7 +177,7 @@ export function TriWorldLeaderboard({ rows, metricTexts, descriptionText }: Prop
158
  setMessage("");
159
  rangeMenuRef.current?.removeAttribute("open");
160
  window.requestAnimationFrame(() => {
161
- rowRefs.current.get(row.modelName)?.scrollIntoView({ behavior: "smooth", block: "start", inline: "nearest" });
162
  });
163
  };
164
 
@@ -204,7 +223,7 @@ export function TriWorldLeaderboard({ rows, metricTexts, descriptionText }: Prop
204
  </div>
205
  {message ? <p className="twb-locator-message" role="status">{message}</p> : null}
206
 
207
- <div className="twb-table-wrap" tabIndex={0} aria-label="TriWorldBench leaderboard">
208
  <table
209
  className="twb-dense-table"
210
  style={{ "--twb-score-column-count": TRIWORLD_TABLE_METRICS.length } as React.CSSProperties}
@@ -246,7 +265,6 @@ export function TriWorldLeaderboard({ rows, metricTexts, descriptionText }: Prop
246
  >
247
  <td className="twb-model-col twb-sticky-col">
248
  <b>{row.modelName}</b>
249
- {row.teamName ? <small>{row.teamName}</small> : null}
250
  </td>
251
  <td className="twb-col-rank twb-sticky-rank">
252
  <span className={`twb-rank-badge rank-${row.rank <= 3 ? row.rank : "other"}`}>
 
94
  const [highlightedName, setHighlightedName] = useState<string | null>(null);
95
  const [message, setMessage] = useState("");
96
  const rangeMenuRef = useRef<HTMLDetailsElement>(null);
97
+ const tableWrapRef = useRef<HTMLDivElement>(null);
98
  const rowRefs = useRef(new Map<string, HTMLTableRowElement>());
99
 
100
  const ranges = useMemo(() => {
 
130
  return ranksByMetric;
131
  }, [rows]);
132
 
133
+ const scrollToRow = useCallback((modelName: string, block: "start" | "center") => {
134
+ const container = tableWrapRef.current;
135
+ const row = rowRefs.current.get(modelName);
136
+ if (!container || !row) return;
137
+
138
+ const containerRect = container.getBoundingClientRect();
139
+ const rowRect = row.getBoundingClientRect();
140
+ const headerHeight = container.querySelector("thead")?.getBoundingClientRect().height ?? 0;
141
+ const targetTop = block === "center"
142
+ ? container.scrollTop + rowRect.top - containerRect.top - (container.clientHeight - rowRect.height) / 2
143
+ : container.scrollTop + rowRect.top - containerRect.top - headerHeight;
144
+
145
+ container.scrollTo({
146
+ top: Math.max(0, targetTop),
147
+ behavior: "smooth",
148
+ });
149
+ }, []);
150
+
151
  const locate = useCallback((name = query) => {
152
  const normalized = name.trim().toLocaleLowerCase();
153
  if (!normalized) {
 
166
  setHighlightedName(matched.modelName);
167
  setMessage(`Located ${matched.modelName} at rank ${matched.rank}.`);
168
  window.requestAnimationFrame(() => {
169
+ scrollToRow(matched.modelName, "center");
170
  });
171
+ }, [query, rows, scrollToRow]);
172
 
173
  const jumpToRange = (start: number) => {
174
  const row = rows[start];
 
177
  setMessage("");
178
  rangeMenuRef.current?.removeAttribute("open");
179
  window.requestAnimationFrame(() => {
180
+ scrollToRow(row.modelName, "start");
181
  });
182
  };
183
 
 
223
  </div>
224
  {message ? <p className="twb-locator-message" role="status">{message}</p> : null}
225
 
226
+ <div ref={tableWrapRef} className="twb-table-wrap" tabIndex={0} aria-label="TriWorldBench leaderboard">
227
  <table
228
  className="twb-dense-table"
229
  style={{ "--twb-score-column-count": TRIWORLD_TABLE_METRICS.length } as React.CSSProperties}
 
265
  >
266
  <td className="twb-model-col twb-sticky-col">
267
  <b>{row.modelName}</b>
 
268
  </td>
269
  <td className="twb-col-rank twb-sticky-rank">
270
  <span className={`twb-rank-badge rank-${row.rank <= 3 ? row.rank : "other"}`}>
src/components/triworldbench/metrics.ts CHANGED
@@ -195,7 +195,6 @@ export type TriWorldMetricCode = string;
195
  export interface TriWorldBoardEntry {
196
  rank: number;
197
  modelName: string;
198
- teamName: string;
199
  score: number | null;
200
  normalizedScore: number | null;
201
  status: string;
 
195
  export interface TriWorldBoardEntry {
196
  rank: number;
197
  modelName: string;
 
198
  score: number | null;
199
  normalizedScore: number | null;
200
  status: string;
src/lib/data/leaderboard.ts CHANGED
@@ -13,18 +13,42 @@ export function latestSnapshot(snapshotParam?: string | null): LeaderboardSnapsh
13
  const db = getDb();
14
  if (snapshotParam && snapshotParam !== "latest") {
15
  return (
16
- dbGet<LeaderboardSnapshot>(db.prepare("SELECT * FROM leaderboard_snapshots WHERE id = ?"), snapshotParam) ||
17
- dbGet<LeaderboardSnapshot>(db.prepare("SELECT * FROM leaderboard_snapshots WHERE label = ?"), snapshotParam)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  );
19
  }
20
  return dbGet<LeaderboardSnapshot>(
21
- db.prepare("SELECT * FROM leaderboard_snapshots ORDER BY is_latest DESC, snapshot_time DESC, id DESC LIMIT 1")
 
 
 
 
 
22
  );
23
  }
24
 
25
  export function getSnapshotHistory(): LeaderboardSnapshot[] {
26
  return all<LeaderboardSnapshot>(
27
- getDb().prepare("SELECT * FROM leaderboard_snapshots ORDER BY snapshot_time DESC, id DESC")
 
 
 
 
 
28
  );
29
  }
30
 
@@ -43,14 +67,12 @@ export function getLeaderboard(
43
  const rawEntries = db
44
  .prepare(
45
  `SELECT e.rank, e.status_label, e.updated_label, e.submission_id,
46
- t.id AS team_id, t.slug AS team_slug, t.name AS team_name, t.affiliation, t.strengths,
47
  mo.id AS model_id, mo.slug AS model_slug, mo.name AS model_name,
48
  s.version_label, s.status AS submission_status, s.dataset_split, s.submitted_at,
49
  sr.normalized_value, sr.percentile, sr.raw_value
50
  FROM leaderboard_snapshot_entries e
51
  JOIN submissions s ON s.id = e.submission_id
52
  JOIN models mo ON mo.id = s.model_id
53
- JOIN teams t ON t.id = mo.team_id
54
  JOIN score_records sr ON sr.id = e.score_record_id
55
  WHERE e.snapshot_id = ? ORDER BY e.rank LIMIT ?`
56
  )
@@ -63,11 +85,6 @@ export function getLeaderboard(
63
  rank: entry.rank as number,
64
  statusLabel: entry.status_label as string | null,
65
  updatedLabel: entry.updated_label as string | null,
66
- team: {
67
- id: entry.team_id as number, slug: entry.team_slug as string,
68
- name: entry.team_name as string, affiliation: entry.affiliation as string | null,
69
- strengths: entry.strengths as string | null,
70
- },
71
  model: {
72
  id: entry.model_id as number, slug: entry.model_slug as string,
73
  name: entry.model_name as string,
@@ -95,7 +112,7 @@ export function getRadarData(
95
  const codes = metricCodes?.length ? metricCodes : DEFAULT_RADAR_METRICS;
96
  const board = getLeaderboard("latest");
97
  const entries = board.entries.slice(0, top).map((entry) => ({
98
- rank: entry.rank, model: entry.model, team: entry.team, score: entry.score,
99
  axes: codes.map((code) => {
100
  const metric = entry.metrics[code];
101
  return { code, label: metric ? metric.displayName : code, value: metric?.percentile ?? null };
@@ -129,14 +146,19 @@ export function getModelScores(modelId: string): {
129
  } {
130
  const db = getDb();
131
  const model = db.prepare(
132
- `SELECT mo.*, t.name AS team_name FROM models mo JOIN teams t ON t.id = mo.team_id WHERE mo.id = ? OR mo.slug = ?`
 
 
133
  ).get(modelId, modelId) as Record<string, unknown> | null;
134
 
135
  if (!model) return { model: null, submission: null, scores: [] };
136
 
137
  const modelIdNum = model.id as number;
138
  const submission = db.prepare(
139
- "SELECT * FROM submissions WHERE model_id = ? ORDER BY submitted_at DESC, id DESC LIMIT 1"
 
 
 
140
  ).get(modelIdNum) as Record<string, unknown> | null;
141
 
142
  if (!submission) return { model, submission: null, scores: [] };
 
13
  const db = getDb();
14
  if (snapshotParam && snapshotParam !== "latest") {
15
  return (
16
+ dbGet<LeaderboardSnapshot>(
17
+ db.prepare(
18
+ `SELECT id, label, snapshot_time, status, ranking_policy, NULL AS notes,
19
+ is_latest, created_at
20
+ FROM leaderboard_snapshots WHERE id = ?`
21
+ ),
22
+ snapshotParam
23
+ ) ||
24
+ dbGet<LeaderboardSnapshot>(
25
+ db.prepare(
26
+ `SELECT id, label, snapshot_time, status, ranking_policy, NULL AS notes,
27
+ is_latest, created_at
28
+ FROM leaderboard_snapshots WHERE label = ?`
29
+ ),
30
+ snapshotParam
31
+ )
32
  );
33
  }
34
  return dbGet<LeaderboardSnapshot>(
35
+ db.prepare(
36
+ `SELECT id, label, snapshot_time, status, ranking_policy, NULL AS notes,
37
+ is_latest, created_at
38
+ FROM leaderboard_snapshots
39
+ ORDER BY is_latest DESC, snapshot_time DESC, id DESC LIMIT 1`
40
+ )
41
  );
42
  }
43
 
44
  export function getSnapshotHistory(): LeaderboardSnapshot[] {
45
  return all<LeaderboardSnapshot>(
46
+ getDb().prepare(
47
+ `SELECT id, label, snapshot_time, status, ranking_policy, NULL AS notes,
48
+ is_latest, created_at
49
+ FROM leaderboard_snapshots
50
+ ORDER BY snapshot_time DESC, id DESC`
51
+ )
52
  );
53
  }
54
 
 
67
  const rawEntries = db
68
  .prepare(
69
  `SELECT e.rank, e.status_label, e.updated_label, e.submission_id,
 
70
  mo.id AS model_id, mo.slug AS model_slug, mo.name AS model_name,
71
  s.version_label, s.status AS submission_status, s.dataset_split, s.submitted_at,
72
  sr.normalized_value, sr.percentile, sr.raw_value
73
  FROM leaderboard_snapshot_entries e
74
  JOIN submissions s ON s.id = e.submission_id
75
  JOIN models mo ON mo.id = s.model_id
 
76
  JOIN score_records sr ON sr.id = e.score_record_id
77
  WHERE e.snapshot_id = ? ORDER BY e.rank LIMIT ?`
78
  )
 
85
  rank: entry.rank as number,
86
  statusLabel: entry.status_label as string | null,
87
  updatedLabel: entry.updated_label as string | null,
 
 
 
 
 
88
  model: {
89
  id: entry.model_id as number, slug: entry.model_slug as string,
90
  name: entry.model_name as string,
 
112
  const codes = metricCodes?.length ? metricCodes : DEFAULT_RADAR_METRICS;
113
  const board = getLeaderboard("latest");
114
  const entries = board.entries.slice(0, top).map((entry) => ({
115
+ rank: entry.rank, model: entry.model, score: entry.score,
116
  axes: codes.map((code) => {
117
  const metric = entry.metrics[code];
118
  return { code, label: metric ? metric.displayName : code, value: metric?.percentile ?? null };
 
146
  } {
147
  const db = getDb();
148
  const model = db.prepare(
149
+ `SELECT mo.id, mo.slug, mo.name
150
+ FROM models mo
151
+ WHERE mo.id = ? OR mo.slug = ?`
152
  ).get(modelId, modelId) as Record<string, unknown> | null;
153
 
154
  if (!model) return { model: null, submission: null, scores: [] };
155
 
156
  const modelIdNum = model.id as number;
157
  const submission = db.prepare(
158
+ `SELECT id, model_id, version_label, submitted_at, status, dataset_split
159
+ FROM submissions
160
+ WHERE model_id = ?
161
+ ORDER BY submitted_at DESC, id DESC LIMIT 1`
162
  ).get(modelIdNum) as Record<string, unknown> | null;
163
 
164
  if (!submission) return { model, submission: null, scores: [] };
src/lib/db/schema.ts CHANGED
@@ -354,13 +354,6 @@ export interface LeaderboardEntry {
354
  rank: number;
355
  statusLabel: string | null;
356
  updatedLabel: string | null;
357
- team: {
358
- id: number;
359
- slug: string;
360
- name: string;
361
- affiliation: string | null;
362
- strengths: string | null;
363
- };
364
  model: {
365
  id: number;
366
  slug: string;
@@ -384,7 +377,6 @@ export interface LeaderboardEntry {
384
  export interface RadarEntry {
385
  rank: number;
386
  model: { name: string; slug: string };
387
- team: { name: string };
388
  score: { percentile: number | null };
389
  axes: Array<{ code: string; label: string; value: number | null }>;
390
  }
 
354
  rank: number;
355
  statusLabel: string | null;
356
  updatedLabel: string | null;
 
 
 
 
 
 
 
357
  model: {
358
  id: number;
359
  slug: string;
 
377
  export interface RadarEntry {
378
  rank: number;
379
  model: { name: string; slug: string };
 
380
  score: { percentile: number | null };
381
  axes: Array<{ code: string; label: string; value: number | null }>;
382
  }
src/styles/triworldbench.css CHANGED
@@ -2062,8 +2062,8 @@ main,
2062
  width: 100%;
2063
  height: 100%;
2064
  object-fit: contain;
 
2065
  padding: 8px;
2066
- transform: translateY(24px);
2067
  }
2068
  .coming { border-radius: 4px; }
2069
  .citation-code,
@@ -2650,7 +2650,7 @@ body .twb-doc[data-page="triworldbench"] #contact .contact-card p span {
2650
  #leaderboard .twb-radar-scale, .visualization .twb-radar-scale { fill: currentColor; font-size: 9px; opacity: .55; }
2651
  .visualization .twb-radar-ring, .visualization .twb-radar-axis { fill: none; stroke: currentColor; opacity: .22; vector-effect: non-scaling-stroke; }
2652
  .visualization .twb-radar-label { fill: currentColor; font-size: 11px; font-weight: 800; text-anchor: middle; dominant-baseline: middle; }
2653
- .visualization .twb-radar-area { fill: var(--c); fill-opacity: .06; stroke: none; }
2654
  .visualization .twb-radar-line { fill: none; stroke: var(--c); stroke-width: 1.8; vector-effect: non-scaling-stroke; }
2655
 
2656
  /* per-metric split: bar list + radar */
@@ -2711,7 +2711,10 @@ body .twb-doc[data-page="triworldbench"] #contact .contact-card p span {
2711
  /* radar series highlight / dim states */
2712
  .visualization .twb-radar-series.is-dim { opacity: .14; }
2713
  .visualization .twb-radar-series.is-hl .twb-radar-line { stroke-width: 3.4; }
2714
- .visualization .twb-radar-series.is-hl .twb-radar-area { fill-opacity: .16; }
 
 
 
2715
  .visualization .twb-radar-spoke line { stroke: var(--c); stroke-width: 2.2; vector-effect: non-scaling-stroke; }
2716
  .visualization .twb-radar-spoke circle { fill: var(--c); }
2717
  .visualization .twb-radar-spoke.is-dim { opacity: .16; }
@@ -5645,6 +5648,20 @@ body .twb-doc[data-page="triworldbench"] #contact .contact-card * {
5645
  dominant-baseline: middle;
5646
  opacity: .68;
5647
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5648
  .twb-doc[data-page="triworldbench"] .twb-vis-top .twb-vis-models {
5649
  background: #f1f3f5;
5650
  border-color: #d5dadd;
 
2062
  width: 100%;
2063
  height: 100%;
2064
  object-fit: contain;
2065
+ object-position: center;
2066
  padding: 8px;
 
2067
  }
2068
  .coming { border-radius: 4px; }
2069
  .citation-code,
 
2650
  #leaderboard .twb-radar-scale, .visualization .twb-radar-scale { fill: currentColor; font-size: 9px; opacity: .55; }
2651
  .visualization .twb-radar-ring, .visualization .twb-radar-axis { fill: none; stroke: currentColor; opacity: .22; vector-effect: non-scaling-stroke; }
2652
  .visualization .twb-radar-label { fill: currentColor; font-size: 11px; font-weight: 800; text-anchor: middle; dominant-baseline: middle; }
2653
+ .visualization .twb-radar-area { fill: #6f7880; fill-opacity: .01; stroke: none; }
2654
  .visualization .twb-radar-line { fill: none; stroke: var(--c); stroke-width: 1.8; vector-effect: non-scaling-stroke; }
2655
 
2656
  /* per-metric split: bar list + radar */
 
2711
  /* radar series highlight / dim states */
2712
  .visualization .twb-radar-series.is-dim { opacity: .14; }
2713
  .visualization .twb-radar-series.is-hl .twb-radar-line { stroke-width: 3.4; }
2714
+ .visualization .twb-radar-series.is-hl .twb-radar-area {
2715
+ fill: #69737b;
2716
+ fill-opacity: .10;
2717
+ }
2718
  .visualization .twb-radar-spoke line { stroke: var(--c); stroke-width: 2.2; vector-effect: non-scaling-stroke; }
2719
  .visualization .twb-radar-spoke circle { fill: var(--c); }
2720
  .visualization .twb-radar-spoke.is-dim { opacity: .16; }
 
5648
  dominant-baseline: middle;
5649
  opacity: .68;
5650
  }
5651
+ .twb-doc[data-page="triworldbench"] .visualization .twb-radar-series .twb-radar-line,
5652
+ .twb-doc[data-page="triworldbench"] .visualization .twb-radar-series.is-hl .twb-radar-line {
5653
+ fill: none !important;
5654
+ fill-opacity: 0 !important;
5655
+ }
5656
+ .twb-doc[data-page="triworldbench"] .visualization .twb-radar-series .twb-radar-area {
5657
+ display: block !important;
5658
+ fill: #6f7880 !important;
5659
+ fill-opacity: .01 !important;
5660
+ }
5661
+ .twb-doc[data-page=triworldbench] .visualization .twb-radar-series.is-hl .twb-radar-area {
5662
+ fill: #69737b !important;
5663
+ fill-opacity: .10 !important;
5664
+ }
5665
  .twb-doc[data-page="triworldbench"] .twb-vis-top .twb-vis-models {
5666
  background: #f1f3f5;
5667
  border-color: #d5dadd;