video-benchmark / styles.css
CarolinePascal
fix: restrict depth params to implemented set; responsive filters layout
112044f unverified
Raw
History Blame Contribute Delete
58.3 kB
/* Video Benchmark β€” custom styling layered on top of the Gradio theme.
*
* Strategy: Gradio's theme handles buttons, inputs, tabs, dataframes,
* plots. This file owns only the non-Gradio pieces β€” the HF-branded hero,
* About-page prose, parameter cards β€” plus a few overrides so Gradio
* widgets inherit HF spacing / typography.
*
* All HF brand tokens live at the top as CSS variables so anything below
* can reference them without pulling an extra stylesheet. */
:root {
/* Brand core */
--hf-yellow: #FFD21E;
--hf-yellow-deep: #FFBD59;
--hf-orange: #FF9D00;
--hf-blue: #496EF0;
--hf-blue-deep: #353E60;
--hf-red: #DB3328;
--hf-green: #009B3A;
--hf-purple: #9747FF;
/* Neutrals */
--hf-gray-900: #1B1B1D;
--hf-gray-800: #32343D;
--hf-gray-700: #475169;
--hf-gray-600: #6A768F;
--hf-gray-500: #9BA3AF;
--hf-gray-300: #E5E7EB;
--hf-gray-200: #EEEFF2;
--hf-gray-100: #F5F6F8;
--hf-white: #FFFFFF;
/* Warm backgrounds */
--hf-cream: #FFF8DE;
/* Semantic */
--fg-1: var(--hf-gray-900);
--fg-2: var(--hf-gray-700);
--fg-3: var(--hf-gray-600);
--bg-1: var(--hf-white);
--bg-2: var(--hf-gray-100);
--bg-3: var(--hf-gray-200);
--border-1: var(--hf-gray-200);
--border-2: var(--hf-gray-300);
/* Spacing + radii */
--space-2: 8px;
--space-3: 12px;
--space-4: 16px;
--space-5: 20px;
--space-6: 24px;
--space-8: 32px;
--space-10: 40px;
--radius-sm: 6px;
--radius-md: 8px;
--radius-lg: 12px;
--radius-2xl: 24px;
--radius-pill: 999px;
/* Type scale */
--fs-xs: 12px;
--fs-sm: 14px;
--fs-md: 18px;
--fs-lg: 20px;
--fs-xl: 24px;
--fs-2xl: 30px;
--fs-4xl: 48px;
--lh-4xl: 56px;
--fw-medium: 500;
--fw-semibold: 600;
--fw-bold: 700;
--fw-black: 900;
}
/* Dark-mode semantic tokens. Flipping the `--fg-*` / `--bg-*` / `--border-*`
* scale in one place keeps typography consistent across every tab β€” any rule
* that reads these tokens (prose, param cards, chips, tables, leaderboard
* cards, tab strip) automatically picks up the dark palette without needing
* its own `.dark` override. Covers both Gradio's `.dark` root class and the
* OS-level `prefers-color-scheme` fallback. */
.dark,
body.dark {
--fg-1: var(--hf-gray-100);
--fg-2: var(--hf-gray-300);
--fg-3: var(--hf-gray-500);
--bg-1: #1E2233;
--bg-2: rgba(255, 255, 255, 0.04);
--bg-3: rgba(255, 255, 255, 0.07);
--border-1: rgba(255, 255, 255, 0.08);
--border-2: rgba(255, 255, 255, 0.18);
}
@media (prefers-color-scheme: dark) {
:root:not(.light) {
--fg-1: var(--hf-gray-100);
--fg-2: var(--hf-gray-300);
--fg-3: var(--hf-gray-500);
--bg-1: #1E2233;
--bg-2: rgba(255, 255, 255, 0.04);
--bg-3: rgba(255, 255, 255, 0.07);
--border-1: rgba(255, 255, 255, 0.08);
--border-2: rgba(255, 255, 255, 0.18);
}
}
/* --- Hero ---
* The hero is now a plain `gr.Row` of two `gr.Column`s (copy + mascot). Since
* Gradio owns layout and widths, CSS here only paints β€” no escape-hatch
* positioning, no viewport-unit math.
*
* Colors are driven by local CSS variables so dark mode can flip the whole
* hero in one place (see the `.dark .hero` block at the bottom of this
* section). Gradio applies `.dark` to the root when the dark theme is on,
* and the `prefers-color-scheme` fallback covers cases where Gradio's theme
* isn't overriding the OS preference. */
.hero {
--hero-bg: var(--hf-cream);
--hero-title: var(--hf-blue-deep);
--hero-text: var(--hf-gray-800);
--hero-tag-bg: var(--hf-white);
--hero-tag-fg: var(--hf-blue-deep);
--hero-tag-border: rgba(53, 62, 96, 0.12);
--hero-stat-v: var(--hf-blue-deep);
background: var(--hero-bg);
border-radius: var(--radius-2xl);
padding: var(--space-8) var(--space-10);
margin-bottom: var(--space-6);
align-items: center;
}
.hero .hero-copy h1 {
font-size: var(--fs-4xl);
line-height: var(--lh-4xl);
font-weight: var(--fw-black);
letter-spacing: -0.025em;
margin: var(--space-2) 0 var(--space-3);
color: var(--hero-title);
}
.hero .hero-copy p {
font-size: var(--fs-md);
color: var(--hero-text);
max-width: 620px;
line-height: 1.5;
margin: 0;
}
.hero .hero-copy strong:first-child {
display: inline-block;
font-size: var(--fs-xs);
font-weight: var(--fw-semibold);
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--hero-tag-fg);
background: var(--hero-tag-bg);
border: 1px solid var(--hero-tag-border);
border-radius: var(--radius-pill);
padding: 4px 10px;
}
/* Dark-mode palette: keep the HF feel (yellow accent pill on deep navy)
* while staying legible on a dark theme. Cover both Gradio's `.dark` root
* class and the OS-level `prefers-color-scheme` media query. */
.dark .hero,
body.dark .hero {
--hero-bg: #1E2233;
--hero-title: #FFFFFF;
--hero-text: #C7CCD6;
--hero-tag-bg: rgba(255, 209, 30, 0.16);
--hero-tag-fg: var(--hf-yellow);
--hero-tag-border: rgba(255, 209, 30, 0.3);
--hero-stat-v: var(--hf-yellow);
}
@media (prefers-color-scheme: dark) {
.hero:not(.light *) {
--hero-bg: #1E2233;
--hero-title: #FFFFFF;
--hero-text: #C7CCD6;
--hero-tag-bg: rgba(255, 209, 30, 0.16);
--hero-tag-fg: var(--hf-yellow);
--hero-tag-border: rgba(255, 209, 30, 0.3);
--hero-stat-v: var(--hf-yellow);
}
}
/* Stats are rendered as a 4-column markdown table β€” header row = numbers
* (big, blue), body row = labels (small caps). The negative top margin pulls
* the table up tight against the subtitle above it (Gradio adds its own
* sibling-block gap which we don't want here). */
.hero .hero-stats {
margin-top: var(--space-2) !important;
padding-top: 0 !important;
}
.hero .hero-stats table,
.hero .hero-stats thead,
.hero .hero-stats tbody,
.hero .hero-stats tr,
.hero .hero-stats th,
.hero .hero-stats td {
border: 0 !important;
background: transparent !important;
box-shadow: none !important;
}
.hero .hero-stats table {
border-collapse: collapse;
width: auto;
}
.hero .hero-stats th,
.hero .hero-stats td {
padding: 0 var(--space-6) 0 0;
text-align: left;
vertical-align: top;
white-space: nowrap;
}
.hero .hero-stats th:last-child,
.hero .hero-stats td:last-child {
padding-right: 0;
}
.hero .hero-stats th {
font-family: "IBM Plex Mono", ui-monospace, monospace;
font-size: var(--fs-2xl);
font-weight: var(--fw-semibold);
color: var(--hero-stat-v);
letter-spacing: -0.01em;
padding-bottom: 2px;
}
.hero .hero-stats td {
font-size: var(--fs-xs);
color: var(--hero-text);
text-transform: uppercase;
letter-spacing: 0.08em;
font-weight: var(--fw-semibold);
}
.hero .hero-mascot,
.hero .hero-mascot img {
max-width: 220px;
margin-left: auto;
}
.hero .hero-mascot img {
filter: drop-shadow(0 8px 24px rgba(53, 62, 96, 0.18));
}
/* Gradio's `<gradio-html>` custom element defaults to `display: inline`,
* which makes any flex/grid child collapse to its intrinsic width. Force
* the About-tab wrappers (prose + parameters grid) to behave as blocks
* so they each use the full tab width instead of shrinking to content. */
gradio-html:has(.params-page),
gradio-html:has(.prose) {
display: block;
width: 100%;
}
/* --- Parameters page ---
*
* Rendered at the bottom of the About tab after ``schema.ABOUT_HTML``,
* so the top margin separates the parameter reference from the prose
* and draws a visible yellow rule β€” the same ``.tab-intro`` treatment
* used elsewhere β€” to introduce the new section. */
.params-page {
display: flex;
flex-direction: column;
gap: var(--space-6);
/* Gradio renders `gr.HTML` inside a `<gradio-html>` custom element
* that defaults to `display: inline`, so the flex/grid children
* collapse to their intrinsic width and the cards wrap long before
* the window edge. Force the tree to span the full tab width. */
width: 100%;
margin-top: var(--space-6);
}
.param-group {
width: 100%;
}
.param-group-head {
margin-bottom: var(--space-4);
}
.param-group-head h3 {
font-size: var(--fs-md);
font-weight: var(--fw-semibold);
margin: 0 0 4px;
padding-bottom: 6px;
border-bottom: 2px solid var(--hf-yellow);
display: inline-block;
}
.param-group-head p {
margin: 8px 0 0;
color: var(--fg-2);
font-size: var(--fs-sm);
max-width: 760px;
}
.param-cards {
/* Fixed 4-column grid: parameters read as a comparison table at a
* glance, so equal track widths are more useful than ``auto-fit``
* here. ``minmax(0, 1fr)`` is what stops long descriptions from
* blowing past their column (grid items default to ``min-width:
* auto``, which uses the *content* min as the lower bound). The
* narrower-viewport fallbacks below collapse the grid gracefully
* before the cards become unreadable. */
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: var(--space-3);
/* Explicit full width so the grid fills the Gradio tab content area
* instead of shrinking to its intrinsic width inside the inline
* `<gradio-html>` wrapper, which would otherwise make the cards wrap
* mid-window. */
width: 100%;
}
@media (max-width: 1100px) {
.param-cards {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
}
@media (max-width: 820px) {
.param-cards {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media (max-width: 540px) {
.param-cards {
grid-template-columns: 1fr;
}
}
.param-card {
--param-card-bg: var(--hf-white);
--param-key-bg: var(--hf-cream);
--param-key-fg: var(--hf-blue-deep);
min-width: 0;
background: var(--param-card-bg);
border: 1px solid var(--border-1);
border-radius: var(--radius-lg);
padding: var(--space-4);
transition: border-color 120ms cubic-bezier(0.16, 1, 0.3, 1);
}
.param-card:hover {
border-color: var(--hf-yellow-deep);
}
.param-card-head {
display: flex;
align-items: baseline;
gap: 10px;
flex-wrap: wrap;
margin-bottom: 8px;
}
.param-card-head .param-key {
font-family: "IBM Plex Mono", ui-monospace, monospace;
font-size: var(--fs-xs);
background: var(--param-key-bg);
color: var(--param-key-fg);
padding: 2px 8px;
border-radius: var(--radius-sm);
font-weight: var(--fw-semibold);
}
/* Dark-mode palette for param cards β€” drop the HF cream/blue chip
* (which is a light-mode-only brand accent) and borrow the generic
* `--bg-2` / `--bg-3` / `--fg-1` tokens so the pill matches `.prose
* code` on the About tab exactly. Cover both Gradio's `.dark` root
* class and the OS-level `prefers-color-scheme` media query. */
.dark .param-card,
body.dark .param-card {
--param-card-bg: var(--bg-1);
--param-key-bg: var(--bg-3);
--param-key-fg: var(--fg-1);
}
@media (prefers-color-scheme: dark) {
.param-card:not(.light *) {
--param-card-bg: var(--bg-1);
--param-key-bg: var(--bg-3);
--param-key-fg: var(--fg-1);
}
}
.param-card-head .param-label {
font-size: var(--fs-sm);
font-weight: var(--fw-semibold);
color: var(--fg-1);
}
.param-card p {
margin: 0;
color: var(--fg-2);
font-size: var(--fs-sm);
line-height: 1.55;
}
/* --- About ---
* No ``max-width`` on the prose wrapper: the About tab intentionally
* spans the full tab width so it lines up with the Parameters card grid
* below it. Per-element line length is kept readable by the smaller
* font-size + generous line-height instead. */
.prose {
font-size: 15px;
line-height: 1.6;
color: var(--fg-1);
width: 100%;
}
.prose h3 {
font-size: var(--fs-lg);
font-weight: var(--fw-semibold);
margin: var(--space-6) 0 var(--space-2);
}
.prose h3:first-child {
margin-top: 0;
}
.prose p {
margin: 0 0 var(--space-3);
}
.prose ul {
margin: 0 0 var(--space-3);
padding-left: 20px;
}
.prose li {
margin-bottom: 4px;
}
.prose code {
/* Both `--bg-3` and `--fg-1` flip at the root in dark mode, so the
* inline-code chip picks up the right palette automatically β€” no
* per-element dark override needed. */
background: var(--bg-3);
color: var(--fg-1);
padding: 1px 6px;
border-radius: 4px;
font-family: "IBM Plex Mono", ui-monospace, monospace;
font-size: 0.88em;
}
/* --- Results-tab accordions (Filters / Visible columns) ---
* Both panels are `gr.Accordion(elem_classes="results-accordion")` so
* the header chrome is identical β€” a small uppercase title with Gradio's
* chevron on the right. Filters starts open, Visible columns starts
* closed, but the card border / typography / padding all match. */
.results-accordion {
margin-bottom: var(--space-3);
}
.results-accordion > .label-wrap {
padding: 4px var(--space-2) !important;
gap: var(--space-2);
}
.results-accordion > .label-wrap > span,
.results-accordion > .label-wrap span.label {
padding-left: 0 !important;
margin-left: 0 !important;
font-size: var(--fs-sm);
font-weight: var(--fw-semibold);
letter-spacing: 0.06em;
text-transform: uppercase;
color: var(--fg-3);
}
.results-accordion[open] > .label-wrap {
border-bottom: 1px solid var(--border-1);
}
/* Inset the accordion body so its contents aren't flush against the card
* border. `.label-wrap ~ *` targets every sibling after the header,
* which in Gradio's accordion is the single content div. */
.gradio-container .results-accordion > .label-wrap ~ * {
padding: 2px var(--space-2) 4px !important;
box-sizing: border-box;
}
.gradio-container .results-accordion:not(.filters-accordion) > .label-wrap ~ * {
padding-bottom: 0 !important;
}
.gradio-container .results-accordion:not(.filters-accordion) > .label-wrap ~ * *:last-child {
margin-bottom: 0 !important;
padding-bottom: 0 !important;
}
/* Kill any bottom margin on the last content element in either accordion
* body, so the visible gap between last row and the card bottom border
* is identical in Filters and Visible columns (driven purely by the
* body's own 12px bottom padding above). */
.gradio-container .results-accordion > .label-wrap ~ * > *:last-child,
.gradio-container .results-accordion > .label-wrap ~ * > * > *:last-child {
margin-bottom: 0 !important;
}
/* Strip every inner wrapper background + border inside both results
* accordions, so filter chips and column checkboxes sit flat on the
* accordion's own card β€” no nested "inner window" compartments.
* Per-category color still applies because it's driven by checkbox /
* label styling, not by wrapper backgrounds. */
.gradio-container .results-accordion .form,
.gradio-container .results-accordion .block,
.gradio-container .results-accordion .wrap,
.gradio-container .results-accordion .gr-group,
.gradio-container .results-accordion .gr-form {
background: transparent !important;
border: 0 !important;
box-shadow: none !important;
}
/* --- Filter chips (toggle-button CheckboxGroup) ---
* Each value in a `.filter-chips` CheckboxGroup renders as a pill button.
* The underlying native checkbox is hidden; the whole label is the click
* target. Checked state is detected with `:has(input:checked)` so Gradio's
* own state management still works β€” we just restyle the presentation.
*
* All filters share the HF deep-navy selected color; we strip the
* CheckboxGroup's own background + border so the chips sit directly on
* the accordion's card instead of inside a nested "inner window". */
.filter-chips {
--chip-color: var(--hf-yellow);
--chip-color-text: var(--hf-gray-900);
background: transparent !important;
border: 0 !important;
box-shadow: none !important;
padding: 0 !important;
min-width: 0 !important;
overflow: visible;
}
/* Filters row: flex-wrap row so the five filter groups sit on one line
* when there's room, and gracefully wrap to a second line when there
* isn't. Each group asks for 20% of the row but is allowed to shrink
* (min-width: 0) so its chips wrap inside it, and is allowed to grow
* into the full width on narrow viewports. */
.filters-accordion,
.filters-accordion * {
box-sizing: border-box;
}
.filters-row {
display: flex !important;
flex-direction: row !important;
flex-wrap: wrap !important;
align-items: flex-start !important;
gap: var(--space-5) var(--space-6) !important;
width: 100% !important;
}
/* All 5 groups share the row equally (flex: 1 1 0). Inter-group
* spacing is added inside each group via a transparent spacer on the
* label+option wrapper, because Gradio reliably overrides outer `gap`
* / `margin` / `padding` on our CheckboxGroup root. */
.filter-chips {
box-sizing: border-box !important;
}
.filters-accordion .filter-chips {
flex: 1 1 132px !important;
min-width: 132px !important;
max-width: 100% !important;
}
/* Target whichever container Gradio wraps its CheckboxGroup options in
* (class name varies between versions) by matching any direct child of
* `.filter-chips` that itself contains at least one checkbox label. */
.filter-chips > *:has(> label input[type="checkbox"]) {
display: flex !important;
flex-direction: row !important;
flex-wrap: wrap !important;
gap: 6px !important;
align-items: flex-start;
width: 100% !important;
min-width: 0 !important;
max-width: 100% !important;
}
/* Labels must be allowed to shrink below their content width so the
* container can wrap them aggressively instead of letting a long pill
* push the row wider than its column. */
.filter-chips label {
flex: 0 0 auto;
max-width: 100%;
}
.filter-chips label {
display: inline-flex;
align-items: center;
justify-content: center;
text-align: center;
gap: 0 !important;
min-width: 56px;
padding: 6px 12px;
border: 1px solid var(--border-2);
border-radius: var(--radius-pill);
background: var(--bg-1);
color: var(--fg-2);
font-size: var(--fs-sm);
font-weight: var(--fw-medium);
font-family: "IBM Plex Mono", ui-monospace, monospace;
cursor: pointer;
transition: background 120ms ease, color 120ms ease, border-color 120ms ease;
user-select: none;
}
.filter-chips label > * {
margin: 0 !important;
}
.filter-chips label:hover {
border-color: var(--fg-3);
color: var(--fg-1);
}
.filter-chips label input[type="checkbox"] {
position: absolute !important;
opacity: 0 !important;
width: 0 !important;
height: 0 !important;
margin: 0 !important;
pointer-events: none !important;
}
.filter-chips label:has(input:checked),
.filter-chips label.selected,
.filter-chips label[aria-checked="true"] {
background: var(--chip-color) !important;
border-color: var(--chip-color) !important;
color: var(--chip-color-text) !important;
}
.filter-chips label:has(input:checked):hover,
.filter-chips label.selected:hover,
.filter-chips label[aria-checked="true"]:hover {
filter: brightness(0.94);
}
/* Click feedback β€” flash the pill yellow on press for tactile feedback,
* independent of its checked state. */
.filter-chips label:active {
background: var(--chip-color) !important;
border-color: var(--chip-color) !important;
color: var(--chip-color-text) !important;
}
/* Filter category labels (Codec, Pixel format, Backend, GOP, CRF) reuse
* the same font treatment as the Visible-columns category headers
* (`.col-cat-master label > span:last-child`) so the two accordions read
* as one visual system. We keep the neutral `--fg-3` color (no per-
* category tint) and drop the weight one notch from semibold β†’ medium
* so the labels sit visually behind the chip pills below them. */
.filter-chips > .block-label,
.filter-chips > label > span:first-child {
font-size: var(--fs-sm);
font-weight: var(--fw-medium);
letter-spacing: 0.02em;
text-transform: uppercase;
color: #ffffff;
margin-bottom: 2px;
}
/* Codec / Pixel format / Backend filter labels mirror the typography
* of the `.col-cat-master` Visible-columns category headers (uppercase
* + small + slight letter-spacing) but stay one weight step thinner
* (medium instead of semibold) and keep the inherited neutral `--fg-3`
* color so the labels don't compete visually with the category-colored
* headers in the Visible-columns accordion. Descendant combinators
* (not `>`) are used so the rule matches regardless of any wrapper
* Gradio inserts between the CheckboxGroup root and its label
* element β€” the pre-existing `.filter-chips > .block-label` rule uses
* `>` and doesn't match in current Gradio versions, which is why these
* `!important` declarations are needed to take effect. */
.filter-cat .block-label,
.filter-cat label > span:first-child,
.filter-cat span[data-testid="block-info"] {
font-size: var(--fs-sm) !important;
font-weight: var(--fw-medium) !important;
letter-spacing: 0.02em !important;
text-transform: uppercase !important;
color: #ffffff !important;
white-space: normal !important;
overflow: visible !important;
text-overflow: clip !important;
/* Nudge the category label (Codec, Pixel format, …) a touch right so
* it sits visually inset from the accordion edge instead of crowding
* the chevron / left rail. */
padding-left: 8px !important;
}
/* Category-tinted checkboxes β€” each `CheckboxGroup` inside the Visible-
* columns accordion gets a brand color applied through Gradio's own
* checkbox CSS variables. Overriding the variables (not the `input`
* itself) means the hover / focus / disabled states still track
* Gradio's theme; we just recolor the selected chip.
*
* Colors are pulled from the leaderboard ``PODIUM_COLORS`` palette in
* ``src/schema.py`` β€” chromatic neighbours of the brand hues, pulled
* 20–30% toward gray. Using the same desaturated set across the column
* picker and the leaderboard radar / cards keeps the page reading as
* one visual system instead of two competing palettes (the saturated
* HF brand colors fight the muted heatmap chips in the table below).
*
* Config Β· dusty blue (#6B8EBF)
* Compression Β· warm sand (#D99B5A)
* Speed Β· sage (#7FA97E)
* Quality Β· muted lavender (#A98FBF)
*/
.col-cat {
--cat-color: #6B8EBF;
}
.col-cat-config { --cat-color: #6B8EBF; }
.col-cat-compression { --cat-color: #D99B5A; }
.col-cat-speed { --cat-color: #7FA97E; }
.col-cat-quality { --cat-color: #A98FBF; }
.col-cat {
--checkbox-background-color-selected: var(--cat-color);
--checkbox-border-color-selected: var(--cat-color);
--checkbox-background-color-focus: var(--cat-color);
--checkbox-border-color-focus: var(--cat-color);
}
.col-cat input[type="checkbox"] {
accent-color: var(--cat-color);
}
.col-cat input[type="checkbox"]:checked {
background-color: var(--cat-color) !important;
border-color: var(--cat-color) !important;
}
.col-cat > .block-label,
.col-cat > label > span:first-child,
.col-cat span[data-testid="block-info"] {
color: var(--cat-color) !important;
font-weight: var(--fw-semibold);
}
/* Strip the default pill / border Gradio renders around each
* CheckboxGroup option so the category picker reads as a flat list of
* checkbox + label rows, not buttons. Forcing zero left padding on
* every wrapper ensures the first sub-checkbox of each row aligns
* vertically with the master checkbox above it. */
.col-cat,
.col-cat > *,
.col-cat .wrap {
padding-left: 0 !important;
margin-left: 0 !important;
}
.col-cat .wrap {
gap: 6px 28px !important;
padding: 0 !important;
}
.col-cat label {
padding: 0 !important;
margin-left: 0 !important;
background: transparent !important;
border: 0 !important;
box-shadow: none !important;
gap: 6px;
min-height: 0;
}
.col-cat-master,
.col-cat-master > *,
.col-cat-master label {
padding-left: 0 !important;
margin-left: 0 !important;
}
/* Master "toggle all" checkbox sitting above each category group. Uses
* the same per-category color variable, but renders bolder/bigger so it
* reads as the category header rather than another option. It's aligned
* flush-left with the option checkboxes below by zeroing its padding. */
.col-cat-master {
padding: 0 !important;
margin: 0 0 6px !important;
background: transparent !important;
border: 0 !important;
}
.col-cat-master label {
padding: 0 !important;
gap: 6px !important;
background: transparent !important;
border: 0 !important;
display: inline-flex !important;
align-items: center !important;
}
.col-cat-master,
.col-cat-master > *,
.col-cat-master label,
.col-cat-master label > span,
.col-cat,
.col-cat > *,
.col-cat .wrap,
.col-cat label,
.col-cat label > span {
overflow: visible !important;
}
.col-cat-master label,
.col-cat label {
padding: 4px 0 !important;
line-height: 1.6 !important;
min-height: 28px !important;
align-items: center !important;
}
.col-cat-master input[type="checkbox"],
.col-cat input[type="checkbox"] {
width: 18px !important;
height: 18px !important;
min-width: 18px !important;
min-height: 18px !important;
flex: 0 0 18px !important;
margin: 0 !important;
padding: 0 !important;
border-radius: 4px !important;
box-sizing: border-box !important;
overflow: visible !important;
display: inline-block !important;
vertical-align: middle !important;
}
.col-cat-master label > span:last-child,
.col-cat-master span[data-testid="block-info"] {
font-size: var(--fs-sm);
font-weight: var(--fw-semibold);
letter-spacing: 0.02em;
color: var(--cat-color) !important;
text-transform: uppercase;
}
.col-cat-master input[type="checkbox"] {
accent-color: var(--cat-color);
}
.col-cat-master input[type="checkbox"]:checked {
background-color: var(--cat-color) !important;
border-color: var(--cat-color) !important;
}
/* --- Results table ---
* Each metric cell carries an inline `style="--chip-bg: rgb(...)"` set by
* the Python renderer (see ``_chip_style`` in app.py), which Gradio
* applies to the outer `<div class="body-cell">` wrapper through the
* ``metadata.styling`` channel. We let that variable cascade down into
* the inner span and paint a content-sized pill there β€” full-cell
* backgrounds (the default for ``cell_style``) would flood the whole
* column track since the body-cell is a fixed-width grid slot.
*
* Going through ``metadata.styling`` (instead of baking the chip into
* the cell as raw HTML) is what lets the metric columns keep
* ``datatype="number"`` and sort by the underlying value rather than
* by the ``<span style="background:rgb(...)">`` HTML prefix.
*
* We kill the default Gradio row / column separators and lighten the
* header so the colored chips carry the visual weight. */
.gradio-container .table-wrap {
--table-head-bg: var(--bg-2);
--table-head-fg: var(--fg-1);
--table-head-border: var(--border-1);
}
/* Results table: column widths come from ``column_widths`` in Python
* (see ``_column_widths_for`` in app.py), which Gradio's JS applies to
* both header cells and body cells at once β€” keeping them in sync.
*
* The rules below are purely cosmetic: they let header labels wrap onto
* a second line inside the (data-sized, capped) column track instead of
* overflowing or being clipped.
*
* 1. ``height: auto`` on the th lets the header row grow when a label
* needs two lines.
* 2. ``display: block`` on ``.cell-wrap`` converts it from a flex
* container to a block box, so ``.header-content`` fills the full
* column width and gives the text a bounded width to wrap against.
* (While cell-wrap is flex, header-content is a flex item sized to
* its own content width β€” not the column width β€” so text never
* wraps.)
* 3. ``white-space: normal`` on all descendants overrides Gradio's
* scoped ``span { white-space: nowrap }`` so the label text flows
* onto a second line. */
.results-table .table-wrap thead .header-cell {
height: auto !important;
}
.results-table .table-wrap thead .cell-wrap {
display: block !important;
height: auto !important;
}
.results-table .table-wrap thead .header-content {
overflow: visible !important;
}
.results-table .table-wrap thead .header-cell * {
white-space: normal !important;
overflow: visible !important;
text-overflow: clip !important;
}
.gradio-container .table-wrap thead th {
border: 0 !important;
box-shadow: none !important;
border-bottom: 1px solid var(--table-head-border) !important;
background: var(--table-head-bg) !important;
color: var(--table-head-fg) !important;
}
/* Heatmap chip painted via the ``--chip-bg`` CSS variable that the
* Python renderer sets on each metric cell's wrapper through
* ``metadata.styling`` (see ``_chip_style`` in app.py). The cell wrapper
* itself stays unpainted β€” only the inner `<span>` that holds the value
* is collapsed to its content width and tinted with the rdylgn color,
* so each cell reads as "small colored pill behind the number" instead
* of a full-cell color flood.
*
* EditableCell.svelte ships the value span with ``display: block;
* width: 100%; flex: 1 1 0%; white-space: nowrap; overflow: hidden``
* (Svelte-scoped ``span`` selector). Those defaults outweigh any plain
* declaration we add, so every property below uses ``!important`` to
* win β€” including ``overflow: visible``, otherwise the chip's
* ``border-radius`` is clipped at the cell's edges.
*
* The attribute selector ``[style*="--chip-bg"]`` only fires on cells
* whose inline ``style=`` actually carries the variable, so non-metric
* cells (and metric cells with null values, where ``_chip_style`` is
* skipped) keep their plain text rendering. */
.results-table .body-cell[style*="--chip-bg"] .cell-wrap > span {
display: inline-block !important;
flex: 0 0 auto !important;
width: fit-content !important;
background: var(--chip-bg);
color: var(--hf-gray-900);
padding: 2px 8px;
border-radius: var(--radius-sm);
white-space: nowrap !important;
overflow: visible !important;
text-overflow: clip !important;
font-variant-numeric: tabular-nums;
line-height: 1.4;
}
/* Row-count caption sits below the table as a quiet, right-aligned
* annotation so it reads as metadata about the table above rather than
* a heading. */
.results-count {
margin-top: var(--space-2) !important;
text-align: right;
color: var(--fg-3);
font-size: var(--fs-xs);
letter-spacing: 0.04em;
}
/* Dark mode: flip the header to a deep slate with light text so the
* column names stay legible against Gradio's dark table surface.
* Cover both the `.dark` root class Gradio sets on theme toggle and the
* OS-level `prefers-color-scheme` fallback. */
.dark .gradio-container .table-wrap,
body.dark .gradio-container .table-wrap {
--table-head-bg: #2A2E3E;
--table-head-fg: #F5F6F8;
--table-head-border: rgba(255, 255, 255, 0.08);
}
@media (prefers-color-scheme: dark) {
.gradio-container .table-wrap:not(.light *) {
--table-head-bg: #2A2E3E;
--table-head-fg: #F5F6F8;
--table-head-border: rgba(255, 255, 255, 0.08);
}
}
/* --- Leaderboards tab ---
* Two-column layout: a Plotly radar on the left, a stack of "podium"
* cards on the right. The card color (rank badge + left accent bar)
* maps 1:1 to its polygon in the radar via schema.PODIUM_COLORS, so
* users can trace any shape back to its config at a glance.
*
* Controls row uses a gr.Radio restyled into pill buttons for the
* Ranking selector (Overall / Quality / Encoding / Decoding); the
* pattern mirrors .filter-chips but in single-select semantics. */
/* One-card header: promote .lb-controls from a multi-column Row of card
* surfaces to a single flat surface, then strip the background / border /
* shadow from every nested wrapper Gradio inserts between the row and the
* actual controls. The three columns (Access pattern / Top N / Ranking)
* sit on one unified card with the dropdown + slider on the left and the
* access-pattern pill buttons aligned to the right. */
.lb-controls {
gap: var(--space-6) !important;
align-items: start !important;
margin-bottom: var(--space-4);
padding: var(--space-3) var(--space-4);
background: var(--bg-1);
border: 1px solid var(--border-1);
border-radius: var(--radius-lg);
overflow: visible !important;
}
/* Gradio's slider renders its number-input + reset overlay above the
* trough; keep the column non-clipping so its rounded corners stay
* visible inside .lb-controls' padded card. */
.lb-controls,
.lb-controls > *,
.lb-controls .block,
.lb-controls .form,
.lb-controls .gr-form {
overflow: visible !important;
}
/* All three columns of the controls card align to the top of the row
* (driven by ``align-items: start`` on ``.lb-controls`` above). Each
* column then lays out its label + control naturally from the top,
* so the three column labels β€” "Access pattern", "Top N configs",
* "Ranking" (visually replaced by the pills since
* ``show_label=False``) β€” sit on a shared baseline. */
.lb-controls .lb-topn-col {
display: flex !important;
flex-direction: column !important;
align-items: center !important;
justify-content: flex-start !important;
}
.lb-controls .lb-topn-col .lb-topn {
width: 100%;
max-width: 360px;
}
/* Right-align the ranking pills horizontally so they hug the right edge
* of the controls card, and vertically center the whole column within
* the row using ``align-self: center`` (which overrides the parent's
* ``align-items: start``). The dropdown column is taller, so the row's
* height is driven by it; the shorter pills column then sits in the
* vertical middle while the dropdown / slider keep their top-aligned
* labels. */
.lb-controls .lb-cats-col {
display: flex !important;
flex-direction: column !important;
align-items: flex-end !important;
align-self: center !important;
}
.lb-controls > .gr-column,
.lb-controls .gr-form,
.lb-controls .form,
.lb-controls .block,
.lb-controls > * > .block,
.lb-controls > * > .form {
background: transparent !important;
border: 0 !important;
box-shadow: none !important;
padding: 0 !important;
}
/* Dark-mode surface: every "window" in the app (controls bar, podium
* cards, compare-controls strip, param cards) shares one background
* token (``--bg-1``) so the page reads as a consistent visual system
* instead of a stack of subtly-different gray slabs. ``--bg-1`` already
* flips between light (white) and dark (#1E2233), so per-theme
* overrides only need to soften the border. */
.dark .lb-controls,
body.dark .lb-controls {
border-color: rgba(255, 255, 255, 0.08);
}
@media (prefers-color-scheme: dark) {
.lb-controls:not(.light *) {
border-color: rgba(255, 255, 255, 0.08);
}
}
/* Ranking pills β€” restyled gr.Radio. Gradio's default renders each
* option as a stacked radio+label row; we hide the native input and
* paint the wrapping label as a pill, using :has(input:checked) to
* pick up the current selection. */
.ranking-pills,
.ranking-pills > *,
.ranking-pills .wrap {
background: transparent !important;
border: 0 !important;
box-shadow: none !important;
padding: 0 !important;
}
.ranking-pills .wrap {
display: flex !important;
flex-direction: row !important;
flex-wrap: wrap !important;
justify-content: flex-end !important;
gap: 6px !important;
}
.ranking-pills > .block-label,
.ranking-pills > label > span:first-child {
font-size: var(--fs-xs);
font-weight: var(--fw-semibold);
letter-spacing: 0.06em;
text-transform: uppercase;
color: var(--fg-3);
margin-bottom: var(--space-2);
}
.ranking-pills label {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 0 !important;
padding: 6px 14px;
min-width: 72px;
border: 1px solid var(--border-2);
border-radius: var(--radius-pill);
background: var(--bg-1);
color: var(--fg-2);
font-size: var(--fs-sm);
font-weight: var(--fw-medium);
cursor: pointer;
transition: background 120ms ease, color 120ms ease, border-color 120ms ease;
user-select: none;
}
.ranking-pills label > * {
margin: 0 !important;
}
.ranking-pills label:hover {
border-color: var(--fg-3);
color: var(--fg-1);
}
.ranking-pills label input[type="radio"] {
position: absolute !important;
opacity: 0 !important;
width: 0 !important;
height: 0 !important;
margin: 0 !important;
pointer-events: none !important;
}
.ranking-pills label:has(input:checked),
.ranking-pills label[aria-checked="true"] {
background: var(--hf-gray-900) !important;
border-color: var(--hf-gray-900) !important;
color: var(--hf-white) !important;
}
.dark .ranking-pills label:has(input:checked),
.dark .ranking-pills label[aria-checked="true"] {
background: var(--hf-yellow) !important;
border-color: var(--hf-yellow) !important;
color: var(--hf-gray-900) !important;
}
/* Main row: radar plot | cards. Kill the plot's own card chrome so the
* radar floats inside the same surface as the controls above it. */
.lb-main {
gap: var(--space-4) !important;
align-items: stretch !important;
}
.lb-radar .plot-container,
.lb-cards-wrap {
background: transparent;
}
/* Card list β€” sized to match the 520px radar plot on the left so both
* columns share the same bottom edge. When the Top-N slider produces
* more cards than fit in that height, the column scrolls internally
* instead of pushing the whole tab taller. The header is `position:
* sticky` so the "Top configurations" title stays visible while the
* reader scrolls through the podium. */
.lb-cards-wrap {
width: 100%;
max-height: 520px;
overflow-y: auto;
scrollbar-width: thin;
scrollbar-color: var(--border-2) transparent;
}
.lb-cards-wrap::-webkit-scrollbar {
width: 8px;
}
.lb-cards-wrap::-webkit-scrollbar-track {
background: transparent;
}
.lb-cards-wrap::-webkit-scrollbar-thumb {
background: var(--border-2);
border-radius: var(--radius-pill);
}
.lb-cards-wrap::-webkit-scrollbar-thumb:hover {
background: var(--fg-3);
}
.lb-cards {
display: flex;
flex-direction: column;
gap: var(--space-3);
padding-right: var(--space-2);
}
/* Per-tab section heading rendered by ``_tab_intro`` in app.py. The
* <h2> is visually matched to the Parameters page's <h3>s: yellow
* underline, semibold, inline-block so the bar only stretches under
* the title text. The muted subtitle paragraph sits below, capped at
* a comfortable reading width. */
.tab-intro-wrap {
margin-top: var(--space-2);
margin-bottom: var(--space-4);
}
.tab-intro {
display: flex;
flex-direction: column;
gap: 4px;
}
.tab-intro h2 {
font-size: var(--fs-xl);
font-weight: var(--fw-bold);
margin: 0;
padding-bottom: 6px;
border-bottom: 2px solid var(--hf-yellow);
display: inline-block;
align-self: flex-start;
color: var(--fg-1);
letter-spacing: -0.01em;
}
.tab-intro p {
margin: 0;
color: var(--fg-3);
font-size: var(--fs-sm);
line-height: 1.5;
max-width: 760px;
}
.dark .tab-intro h2,
body.dark .tab-intro h2 {
color: var(--hf-white);
}
.dark .tab-intro p,
body.dark .tab-intro p {
color: var(--hf-gray-500);
}
@media (prefers-color-scheme: dark) {
.tab-intro h2:not(.light *) { color: var(--hf-white); }
.tab-intro p:not(.light *) { color: var(--hf-gray-500); }
}
.lb-empty {
padding: var(--space-5);
text-align: center;
color: var(--fg-3);
border: 1px dashed var(--border-2);
border-radius: var(--radius-lg);
}
.lb-card {
position: relative;
display: flex;
align-items: stretch;
gap: var(--space-3);
padding: var(--space-3) var(--space-4) var(--space-3) calc(var(--space-4) + 6px);
background: var(--bg-1);
border: 1px solid var(--border-1);
border-radius: var(--radius-lg);
transition: transform 120ms ease, box-shadow 120ms ease, border-color 120ms ease;
}
.lb-card::before {
/* Left accent strip keyed to the polygon color β€” lets users eyeball
* "which card goes with which shape" even before reading the badge. */
content: "";
position: absolute;
left: 0; top: 10px; bottom: 10px;
width: 4px;
background: var(--rank-color, var(--hf-gray-300));
border-radius: 0 4px 4px 0;
}
.lb-card:hover {
border-color: var(--border-2);
box-shadow: 0 2px 8px rgba(27, 27, 29, 0.06);
}
.lb-badge {
flex: 0 0 auto;
display: inline-flex;
align-items: center;
justify-content: center;
width: 34px; height: 34px;
border-radius: 999px;
background: var(--rank-color, var(--hf-gray-500));
color: var(--hf-white);
font-family: "IBM Plex Mono", ui-monospace, monospace;
font-size: var(--fs-sm);
font-weight: var(--fw-bold);
line-height: 1;
align-self: center;
box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.9) inset;
}
.lb-card-body {
flex: 1 1 auto;
min-width: 0;
display: flex;
flex-direction: column;
gap: var(--space-2);
}
.lb-card-head {
display: flex;
align-items: center;
gap: var(--space-2);
flex-wrap: wrap;
}
.lb-codec {
display: inline-flex;
align-items: center;
padding: 2px 0;
color: var(--fg-1);
font-family: "IBM Plex Mono", ui-monospace, monospace;
font-size: var(--fs-xs);
font-weight: var(--fw-semibold);
letter-spacing: 0.02em;
}
.lb-config {
color: var(--fg-2);
font-size: var(--fs-sm);
}
.lb-config code {
background: var(--bg-3);
color: var(--fg-1);
padding: 1px 6px;
border-radius: 4px;
font-family: "IBM Plex Mono", ui-monospace, monospace;
font-size: 0.88em;
}
.lb-metrics {
display: flex;
flex-wrap: wrap;
gap: 6px;
}
.lb-metric {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 3px 8px;
border-radius: var(--radius-sm);
background: var(--bg-2);
border: 1px solid var(--border-1);
font-size: var(--fs-xs);
white-space: nowrap;
}
.lb-metric-k {
color: var(--fg-3);
text-transform: uppercase;
letter-spacing: 0.06em;
font-weight: var(--fw-semibold);
font-size: 10px;
}
.lb-metric-v {
color: var(--fg-1);
font-family: "IBM Plex Mono", ui-monospace, monospace;
font-weight: var(--fw-semibold);
font-variant-numeric: tabular-nums;
}
/* Dark-mode tweaks β€” cards need a slightly lifted background and
* lighter metric chips so they don't disappear into the tab surface. */
.dark .lb-card,
body.dark .lb-card {
border-color: rgba(255, 255, 255, 0.08);
}
.dark .lb-card:hover,
body.dark .lb-card:hover {
border-color: rgba(255, 255, 255, 0.18);
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.25);
}
.dark .lb-metric,
body.dark .lb-metric {
background: rgba(255, 255, 255, 0.05);
border-color: rgba(255, 255, 255, 0.08);
}
.dark .lb-metric-v,
body.dark .lb-metric-v {
color: var(--hf-gray-100);
}
.dark .lb-metric-k,
body.dark .lb-metric-k {
color: var(--hf-gray-500);
}
.dark .lb-config,
body.dark .lb-config {
color: var(--hf-gray-300);
}
.dark .lb-config code,
body.dark .lb-config code {
background: rgba(255, 255, 255, 0.07);
color: var(--hf-gray-100);
}
.dark .lb-badge,
body.dark .lb-badge {
box-shadow: 0 0 0 3px rgba(27, 27, 29, 0.9) inset;
}
@media (prefers-color-scheme: dark) {
.lb-card:not(.light *) {
border-color: rgba(255, 255, 255, 0.08);
}
.lb-metric:not(.light *) {
background: rgba(255, 255, 255, 0.05);
border-color: rgba(255, 255, 255, 0.08);
}
}
/* "Selected configurations" section heading sits under the radar/card
* row and introduces the dataframe. Match the prose scale used in the
* params page so the tab reads as header β†’ content β†’ header β†’ content. */
.lb-table-head {
margin-top: var(--space-6) !important;
margin-bottom: var(--space-2) !important;
}
.lb-table-head h3 {
font-size: var(--fs-lg);
font-weight: var(--fw-semibold);
margin: 0;
padding-bottom: 6px;
border-bottom: 2px solid var(--hf-yellow);
display: inline-block;
color: var(--fg-1);
}
.dark .lb-table-head h3,
body.dark .lb-table-head h3 {
color: var(--hf-white);
}
/* Kill the dataframe's outer card so the table reads as part of the
* tab (matching the Results table treatment), and bump the Score
* column to monospace tabular numerals for quick top-down scanning.
* Rank is now a colored badge (rendered as HTML inside the cell), so
* the span's monospace font handles alignment β€” no need to restyle
* the td. */
.lb-table .table-wrap {
border: 0 !important;
box-shadow: none !important;
background: transparent !important;
}
.lb-table .table-wrap tbody td:last-child {
font-family: "IBM Plex Mono", ui-monospace, monospace;
font-variant-numeric: tabular-nums;
font-weight: var(--fw-semibold);
}
/* Center header labels in the leaderboard table. Gradio nests the label
* text inside ``.cell-wrap`` > ``.header-content`` flex wrappers, so we
* also need to neutralize their ``justify-content`` (defaults to
* ``flex-start``) β€” otherwise ``text-align: center`` on the ``th``
* alone is overridden by the inner flex layout. */
.lb-table .table-wrap thead th,
.lb-table .table-wrap thead th * {
text-align: center !important;
justify-content: center !important;
}
/* Inline rank badge used inside the table's Rank column. Same visual
* as the card badge, just smaller and without the inset ring that
* makes sense only on the card's white surface. */
.lb-badge-inline {
width: 26px;
height: 26px;
font-size: var(--fs-xs);
box-shadow: none;
}
/* --- Compare tab plots ---
* Plotly renders text via SVG `<text>` with a `fill=...` attribute
* set server-side (see `_PLOTLY_FG` in app.py). That baked-in color
* is a single mid-slate for both themes, which works but leaves
* titles / legends a bit washed-out. CSS `fill` overrides the SVG
* attribute, so we swap in theme-aware tokens (`--fg-1` / `--fg-2`)
* only for Compare plots β€” the Leaderboards radar keeps its muted
* gray on purpose, to avoid stealing attention from the polygons. */
.compare-plot .gtitle,
.compare-plot .g-gtitle {
fill: var(--fg-1) !important;
font-weight: var(--fw-semibold) !important;
}
.compare-plot .xtitle,
.compare-plot .ytitle,
.compare-plot .legendtitletext {
fill: var(--fg-1) !important;
}
.compare-plot .legendtext,
.compare-plot .xtick > text,
.compare-plot .ytick > text,
.compare-plot .annotation-text {
fill: var(--fg-2) !important;
}
/* Axis spines + grid lines: use the neutral border token so they
* stay visible on dark without turning harsh on light. */
.compare-plot .xaxislayer-above path.domain,
.compare-plot .yaxislayer-above path.domain,
.compare-plot .zerolinelayer path {
stroke: var(--border-2) !important;
}
.compare-plot .gridlayer path {
stroke: var(--border-1) !important;
}
/* The caption sits above each bar plot and explains the current
* selection; keep it readable but subordinate to the plot title. */
.compare-caption {
color: var(--fg-2) !important;
font-size: var(--fs-sm) !important;
margin: var(--space-1) 0 var(--space-2) !important;
}
/* Per-chart titles ("Metric averages by configuration axis", "Quality
* vs. compression", "Decoding latency by codec and access pattern")
* render as ``<h3>`` from the Markdown ``###`` prefix. The default
* Gradio prose h3 is too loud for these section headers β€” shrink one
* step from `--fs-lg` (20px) to `--fs-md` (18px) and tighten the gap
* between the title and the description paragraph below it. */
.compare-caption h3 {
font-size: var(--fs-md) !important;
margin: 0 0 4px !important;
line-height: 1.3 !important;
}
/* The configurable bar chart + its title + its dropdowns live in one
* `.compare-panel` group so they read as a single unit. The panel
* itself is the outer "card": one border + radius wraps the header
* strip and the chart together, with extra bottom padding so the
* chart breathes inside the card. The `.compare-controls` strip on
* top keeps its own tinted `--bg-1` background (its previous color),
* so the header reads as a distinct band against the chart area
* (which sits on the page background) without breaking the shared
* card outline. */
.compare-panel {
margin-bottom: var(--space-4);
background: transparent !important;
border: 1px solid var(--border-1) !important;
border-radius: var(--radius-lg);
box-shadow: none !important;
padding: 0 !important;
overflow: hidden;
}
/* Gradio wraps every `gr.Group` / `gr.Column` child in its own `.block`
* container that ships a default 1px border + box-shadow. Without this
* reset those inner borders paint a second / third outline at the
* bottom of the panel, stacking under the `.compare-panel` border and
* reading as two parallel lines. Strip chrome on every wrapper so only
* the panel's own border is visible. */
.compare-panel > div,
.compare-panel > div > div,
.compare-panel .block,
.compare-panel .form {
background: transparent !important;
border: 0 !important;
box-shadow: none !important;
}
/* Header strip uses the shared `--bg-1` surface token β€” same shade as
* every other "window" in the app (leaderboard controls card, param
* cards, podium cards). The selector is scoped under `.compare-panel`
* so its specificity (2 classes) matches the generic `.compare-panel
* .block` reset earlier and this rule wins β€” otherwise Gradio tags
* the gr.Column with both `.compare-controls` and `.block`, and the
* reset's higher specificity would force the header to `transparent`
* and the strip would vanish. */
.compare-panel .compare-controls {
background: var(--bg-1) !important;
border: 0 !important;
border-bottom: 1px solid var(--border-1) !important;
padding: var(--space-4) !important;
margin: 0 !important;
border-radius: 0;
}
.compare-controls .compare-caption {
margin-top: 0 !important;
margin-bottom: 0 !important;
}
.compare-controls .compare-caption p:last-child {
margin-bottom: 0 !important;
}
/* Control-label treatment for the Leaderboards "Top N configs" slider
* and the Compare-tab "Metric" / "Group by" dropdowns β€” small uppercase
* semibold cap in ``--fg-3`` so they all match the ``.filter-chips`` /
* ``.ranking-pills`` label family. */
.lb-topn > .block-label,
.lb-topn > label > span:first-child,
.lb-topn span[data-testid="block-info"],
.cmp-control > .block-label,
.cmp-control > label > span:first-child,
.cmp-control span[data-testid="block-info"] {
font-size: var(--fs-xs);
font-weight: var(--fw-semibold);
letter-spacing: 0.06em;
text-transform: uppercase;
color: var(--fg-3);
margin-bottom: var(--space-2);
}
/* Chart area sits below the `.compare-controls` header inside the
* shared `.compare-panel` card. It picks up the same `--bg-1` surface
* token as the controls strip above it so the whole panel reads as
* one continuous tinted card β€” the bottom border on `.compare-controls`
* is the only visual divider between header and chart. Plotly itself
* paints transparent (`paper_bgcolor` / `plot_bgcolor` are
* `rgba(0,0,0,0)`; see `_PLOTLY_*` in app.py), so the container's
* background shows through cleanly; we just have to strip every nested
* Gradio + plotly wrapper so nothing paints a contrasting band over it. */
.compare-plot {
background: var(--bg-1) !important;
border: 0 !important;
box-shadow: none !important;
padding: var(--space-3) var(--space-3) 0 !important;
}
.compare-plot > div,
.compare-plot .plot-container,
.compare-plot .plotly,
.compare-plot .svg-container,
.compare-plot .tabs,
.compare-plot .tab-nav,
.compare-plot .tab-nav button,
.compare-plot .tabitem,
.compare-plot .modebar,
.compare-plot .modebar-container,
.compare-plot .modebar-group {
background: transparent !important;
border: 0 !important;
box-shadow: none !important;
}
/* --- Submit-tab group labels ---
* The Submit tab stacks parameter CheckboxGroups ("Dataset", "Codec",
* "Pixel format", "GOP", "CRF", "Access pattern", "Backend") β€” each one
* titles its row of checkboxes. Match the per-chart section titles in
* the Compare tab (`.compare-caption h3`): `--fs-md` / semibold /
* default text color so the sweep builder reads as a sequence of real
* section headings, consistent with the rest of the app. */
.submit-checks > .block-label,
.submit-checks > label > span:first-child,
.submit-checks span[data-testid="block-info"] {
font-size: var(--fs-md);
font-weight: var(--fw-semibold);
letter-spacing: normal;
text-transform: none;
color: var(--fg-1);
line-height: 1.3;
margin: 0 0 4px;
}
/* --- Submit-tab parameter cards ---
* Each parameter group (Datasets, Codecs, Pixel formats, GOP, CRF,
* Access patterns, Backends, Run settings) is wrapped in its own
* `.submit-section` card so the form reads as a list of distinct
* knobs rather than one monolithic slab. The card paints in `--bg-1`
* with a 1px border + rounded corners β€” same surface treatment as
* the Compare tab's `.compare-panel` cards β€” and strips the wrapping
* `.block` / `.form` chrome Gradio bakes around every gr.Row /
* gr.Column / gr.Group child so the card surface shows through
* uniformly between the actual interactive inputs (textboxes,
* sliders, checkbox groups), which keep their own surfaces. */
.submit-section {
margin-bottom: var(--space-2);
background: var(--bg-1) !important;
border: 1px solid var(--border-1) !important;
border-radius: var(--radius-lg);
box-shadow: none !important;
padding: var(--space-3) var(--space-4) !important;
}
/* Strip every wrapping `.block` / `.form` chrome Gradio paints around
* the CheckboxGroup / Textbox / Slider children so the card surface
* shows through and the children sit flush against the card padding
* (no double-padding, no nested borders, no gradio default gap). The
* actual interactive controls (checkbox pills, textbox input, slider
* track) keep their own surfaces because they're matched by more
* specific selectors below. */
.submit-section > div,
.submit-section > div > div,
.submit-section .block,
.submit-section .form {
background: transparent !important;
border: 0 !important;
box-shadow: none !important;
padding: 0 !important;
margin: 0 !important;
gap: var(--space-2) !important;
}
/* The CheckboxGroup's own internal padding + label margin add a chunk
* of dead space above the pills; collapse it so the label sits right
* above the checkboxes. */
.submit-section .submit-checks {
padding: 0 !important;
}
.submit-section .submit-checks > .block-label,
.submit-section .submit-checks > label > span:first-child {
margin-bottom: 4px !important;
}
.submit-section label > .wrap {
padding: 0 !important;
}
/* --- Submit-tab right-column ---
* The action rail (total count / estimate / Submit CTA / queue) sits
* directly on the page background with no enclosing card so it reads
* as a quiet sidebar against the bordered parameter cards on the left.
* A bit of left padding pulls it off the gutter between the columns. */
.submit-right {
padding-left: var(--space-3);
gap: var(--space-2) !important;
}
/* Total-configs line above the Submit CTA β€” centered headline that
* makes the count the visual anchor of the right column: the number
* itself reads as a big HF-yellow display figure, with a small muted
* "total configs" caption beneath it so the user always sees exactly
* what the yellow button is about to commit. */
.submit-right .submit-summary {
text-align: center;
margin: 0;
line-height: 1.1;
}
.submit-right .submit-summary p {
margin: 0;
font-size: var(--fs-xs, 11px);
font-weight: var(--fw-semibold);
text-transform: uppercase;
letter-spacing: 0.08em;
color: var(--fg-3);
}
.submit-right .submit-summary strong {
display: block;
font-size: 36px;
font-weight: 700;
color: var(--hf-yellow);
letter-spacing: -0.02em;
margin-bottom: 2px;
font-variant-numeric: tabular-nums;
}
/* "Recent submissions" label above the queue table β€” small, muted,
* centered uppercase eyebrow so it reads as a discreet section
* marker rather than a heading competing with the Submit CTA above. */
.submit-queue-label {
font-size: var(--fs-sm, 13px);
font-weight: var(--fw-semibold);
text-transform: uppercase;
letter-spacing: 0.07em;
color: var(--fg-3);
text-align: center;
margin: var(--space-2) 0 0;
}
/* Pull the dataframe up snug under the label β€” the gradio dataframe
* ships with a toolbar row (copy / fullscreen icons) that already
* adds its own top breathing room, so the label's bottom margin +
* the column gap stack to a visible gulf if we don't collapse them. */
.submit-right .submit-queue {
margin-top: calc(-1 * var(--space-2)) !important;
}
/* Yellow "Submit sweep" CTA β€” full-width, HF brand yellow with dark
* text, matching the reference Space. Overrides Gradio's default
* primary-button gradient. */
.submit-cta {
width: 100% !important;
background: var(--hf-yellow) !important;
border-color: var(--hf-yellow) !important;
color: var(--hf-gray-900) !important;
font-weight: var(--fw-semibold) !important;
margin: 0 0 var(--space-4) !important;
}
.submit-cta:hover {
background: var(--hf-yellow-deep) !important;
border-color: var(--hf-yellow-deep) !important;
}
/* --- Gradio component tweaks to tighten the HF look --- */
/* Slightly softer tabs bar β€” default Gradio tabs ship a heavy underline. */
.tab-nav button,
.tabs > .tab-nav button,
button[role="tab"] {
font-size: 16px !important;
}
.tab-nav button.selected {
border-bottom-color: var(--hf-yellow) !important;
color: var(--hf-blue-deep) !important;
font-weight: var(--fw-semibold);
}
/* Give plot cards the same card radius as the param cards. */
.gradio-container .plot-container {
border-radius: var(--radius-lg);
}
/* The whole layout β€” hero and every tab β€” shares one wide column that tracks
* the window. Using `100%` (not the Gradio default `1440px` cap) means the
* hero always occupies most of the window. */
.gradio-container {
max-width: 100% !important;
width: 100% !important;
margin: 0 auto !important;
padding: var(--space-6) var(--space-8) !important;
box-sizing: border-box;
}
@media (max-width: 820px) {
.hero {
padding: var(--space-6);
}
.hero .hero-mascot,
.hero .hero-mascot img {
max-width: 140px;
}
.hero .hero-stats {
gap: var(--space-4);
}
}
/* Footer row hosting the "Refresh from Hub" button. Sits flush against
* the bottom of the page, right-aligned so the action reads as ambient
* tooling rather than a primary CTA, with a soft top border separating
* it from the last tab's content. */
.refresh-footer {
margin-top: var(--space-6);
padding-top: var(--space-4);
border-top: 1px solid var(--border-1);
align-items: center;
justify-content: flex-end;
gap: var(--space-4);
}
.refresh-footer .footer-version {
flex: 0 0 auto;
color: var(--fg-3);
font-size: 13px;
}
.refresh-footer .refresh-status {
flex: 1 1 auto;
color: var(--fg-3);
font-size: 13px;
}
.refresh-footer button {
flex: 0 0 auto;
}