diff --git a/benchmarks/perp-fees.yml b/benchmarks/perp-fees.yml
index 18e00cbd..c212e0f6 100644
--- a/benchmarks/perp-fees.yml
+++ b/benchmarks/perp-fees.yml
@@ -249,6 +249,7 @@ providers:
# paneled (it duplicates the headline) and $10k reads within noise of
# $1k on every venue, so the panels show the two sizes where the story
# changes: $100k and $1M.
+panel_main_label: All-in at $1k
metric_panels:
- id: all_in_100k
label: All-in at $100k
diff --git a/src/components/benchmark-body.tsx b/src/components/benchmark-body.tsx
index 57029a6b..560b0877 100644
--- a/src/components/benchmark-body.tsx
+++ b/src/components/benchmark-body.tsx
@@ -720,7 +720,7 @@ export function BenchmarkBody({
return tabPanels.length > 0 ? (
@@ -767,7 +767,7 @@ export function BenchmarkBody({
return tabPanels.length > 0 ? (
diff --git a/src/lib/spec-schema.ts b/src/lib/spec-schema.ts
index 9f73f760..423f7236 100644
--- a/src/lib/spec-schema.ts
+++ b/src/lib/spec-schema.ts
@@ -382,6 +382,10 @@ export const SpecSchema = z
* frontends bench to surface execution quality, outage signal, taker
* share, etc. without changing the main p50 headline.
*/
+ /* Label for the headline tab of the metric panel switcher. Defaults
+ * to `metric`; set it when the panels are size/window variants and
+ * the headline needs its variant spelled out (e.g. "All-in at $1k"). */
+ panel_main_label: z.string().min(1).max(80).optional(),
metric_panels: z
.array(
z.object({
diff --git a/src/types/benchmark.ts b/src/types/benchmark.ts
index 5cff01e3..aa616968 100644
--- a/src/types/benchmark.ts
+++ b/src/types/benchmark.ts
@@ -254,6 +254,7 @@ export type Benchmark = {
* below the main table. Populated by the spec loader from
* `metric_panels` in the YAML. */
metricPanels?: MetricPanel[];
+ panelMainLabel?: string;
/** Optional per-bench relabeling of the ledger's aggregate columns.
* Declared by benches whose unit has no percentile semantics (the
* p50/p90/p99/mean slots are repurposed, e.g. USD revenue leaderboards)