Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
CarolinePascal
fix: restrict depth params to implemented set; responsive filters layout
112044f unverified | /* 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) ; | |
| padding-top: 0 ; | |
| } | |
| .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 ; | |
| background: transparent ; | |
| box-shadow: none ; | |
| } | |
| .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) ; | |
| gap: var(--space-2); | |
| } | |
| .results-accordion > .label-wrap > span, | |
| .results-accordion > .label-wrap span.label { | |
| padding-left: 0 ; | |
| margin-left: 0 ; | |
| 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 ; | |
| box-sizing: border-box; | |
| } | |
| .gradio-container .results-accordion:not(.filters-accordion) > .label-wrap ~ * { | |
| padding-bottom: 0 ; | |
| } | |
| .gradio-container .results-accordion:not(.filters-accordion) > .label-wrap ~ * *:last-child { | |
| margin-bottom: 0 ; | |
| padding-bottom: 0 ; | |
| } | |
| /* 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 ; | |
| } | |
| /* 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 ; | |
| border: 0 ; | |
| box-shadow: none ; | |
| } | |
| /* --- 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 ; | |
| border: 0 ; | |
| box-shadow: none ; | |
| padding: 0 ; | |
| min-width: 0 ; | |
| 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 ; | |
| flex-direction: row ; | |
| flex-wrap: wrap ; | |
| align-items: flex-start ; | |
| gap: var(--space-5) var(--space-6) ; | |
| width: 100% ; | |
| } | |
| /* 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 ; | |
| } | |
| .filters-accordion .filter-chips { | |
| flex: 1 1 132px ; | |
| min-width: 132px ; | |
| max-width: 100% ; | |
| } | |
| /* 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 ; | |
| flex-direction: row ; | |
| flex-wrap: wrap ; | |
| gap: 6px ; | |
| align-items: flex-start; | |
| width: 100% ; | |
| min-width: 0 ; | |
| max-width: 100% ; | |
| } | |
| /* 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 ; | |
| 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 ; | |
| } | |
| .filter-chips label:hover { | |
| border-color: var(--fg-3); | |
| color: var(--fg-1); | |
| } | |
| .filter-chips label input[type="checkbox"] { | |
| position: absolute ; | |
| opacity: 0 ; | |
| width: 0 ; | |
| height: 0 ; | |
| margin: 0 ; | |
| pointer-events: none ; | |
| } | |
| .filter-chips label:has(input:checked), | |
| .filter-chips label.selected, | |
| .filter-chips label[aria-checked="true"] { | |
| background: var(--chip-color) ; | |
| border-color: var(--chip-color) ; | |
| color: var(--chip-color-text) ; | |
| } | |
| .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) ; | |
| border-color: var(--chip-color) ; | |
| color: var(--chip-color-text) ; | |
| } | |
| /* 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) ; | |
| font-weight: var(--fw-medium) ; | |
| letter-spacing: 0.02em ; | |
| text-transform: uppercase ; | |
| color: #ffffff ; | |
| white-space: normal ; | |
| overflow: visible ; | |
| text-overflow: clip ; | |
| /* 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 ; | |
| } | |
| /* 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) ; | |
| border-color: var(--cat-color) ; | |
| } | |
| .col-cat > .block-label, | |
| .col-cat > label > span:first-child, | |
| .col-cat span[data-testid="block-info"] { | |
| color: var(--cat-color) ; | |
| 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 ; | |
| margin-left: 0 ; | |
| } | |
| .col-cat .wrap { | |
| gap: 6px 28px ; | |
| padding: 0 ; | |
| } | |
| .col-cat label { | |
| padding: 0 ; | |
| margin-left: 0 ; | |
| background: transparent ; | |
| border: 0 ; | |
| box-shadow: none ; | |
| gap: 6px; | |
| min-height: 0; | |
| } | |
| .col-cat-master, | |
| .col-cat-master > *, | |
| .col-cat-master label { | |
| padding-left: 0 ; | |
| margin-left: 0 ; | |
| } | |
| /* 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 ; | |
| margin: 0 0 6px ; | |
| background: transparent ; | |
| border: 0 ; | |
| } | |
| .col-cat-master label { | |
| padding: 0 ; | |
| gap: 6px ; | |
| background: transparent ; | |
| border: 0 ; | |
| display: inline-flex ; | |
| align-items: center ; | |
| } | |
| .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 ; | |
| } | |
| .col-cat-master label, | |
| .col-cat label { | |
| padding: 4px 0 ; | |
| line-height: 1.6 ; | |
| min-height: 28px ; | |
| align-items: center ; | |
| } | |
| .col-cat-master input[type="checkbox"], | |
| .col-cat input[type="checkbox"] { | |
| width: 18px ; | |
| height: 18px ; | |
| min-width: 18px ; | |
| min-height: 18px ; | |
| flex: 0 0 18px ; | |
| margin: 0 ; | |
| padding: 0 ; | |
| border-radius: 4px ; | |
| box-sizing: border-box ; | |
| overflow: visible ; | |
| display: inline-block ; | |
| vertical-align: middle ; | |
| } | |
| .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) ; | |
| 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) ; | |
| border-color: var(--cat-color) ; | |
| } | |
| /* --- 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 ; | |
| } | |
| .results-table .table-wrap thead .cell-wrap { | |
| display: block ; | |
| height: auto ; | |
| } | |
| .results-table .table-wrap thead .header-content { | |
| overflow: visible ; | |
| } | |
| .results-table .table-wrap thead .header-cell * { | |
| white-space: normal ; | |
| overflow: visible ; | |
| text-overflow: clip ; | |
| } | |
| .gradio-container .table-wrap thead th { | |
| border: 0 ; | |
| box-shadow: none ; | |
| border-bottom: 1px solid var(--table-head-border) ; | |
| background: var(--table-head-bg) ; | |
| color: var(--table-head-fg) ; | |
| } | |
| /* 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 ; | |
| flex: 0 0 auto ; | |
| width: fit-content ; | |
| background: var(--chip-bg); | |
| color: var(--hf-gray-900); | |
| padding: 2px 8px; | |
| border-radius: var(--radius-sm); | |
| white-space: nowrap ; | |
| overflow: visible ; | |
| text-overflow: clip ; | |
| 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) ; | |
| 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) ; | |
| align-items: start ; | |
| 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 ; | |
| } | |
| /* 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 ; | |
| } | |
| /* 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 ; | |
| flex-direction: column ; | |
| align-items: center ; | |
| justify-content: flex-start ; | |
| } | |
| .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 ; | |
| flex-direction: column ; | |
| align-items: flex-end ; | |
| align-self: center ; | |
| } | |
| .lb-controls > .gr-column, | |
| .lb-controls .gr-form, | |
| .lb-controls .form, | |
| .lb-controls .block, | |
| .lb-controls > * > .block, | |
| .lb-controls > * > .form { | |
| background: transparent ; | |
| border: 0 ; | |
| box-shadow: none ; | |
| padding: 0 ; | |
| } | |
| /* 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 ; | |
| border: 0 ; | |
| box-shadow: none ; | |
| padding: 0 ; | |
| } | |
| .ranking-pills .wrap { | |
| display: flex ; | |
| flex-direction: row ; | |
| flex-wrap: wrap ; | |
| justify-content: flex-end ; | |
| gap: 6px ; | |
| } | |
| .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 ; | |
| 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 ; | |
| } | |
| .ranking-pills label:hover { | |
| border-color: var(--fg-3); | |
| color: var(--fg-1); | |
| } | |
| .ranking-pills label input[type="radio"] { | |
| position: absolute ; | |
| opacity: 0 ; | |
| width: 0 ; | |
| height: 0 ; | |
| margin: 0 ; | |
| pointer-events: none ; | |
| } | |
| .ranking-pills label:has(input:checked), | |
| .ranking-pills label[aria-checked="true"] { | |
| background: var(--hf-gray-900) ; | |
| border-color: var(--hf-gray-900) ; | |
| color: var(--hf-white) ; | |
| } | |
| .dark .ranking-pills label:has(input:checked), | |
| .dark .ranking-pills label[aria-checked="true"] { | |
| background: var(--hf-yellow) ; | |
| border-color: var(--hf-yellow) ; | |
| color: var(--hf-gray-900) ; | |
| } | |
| /* 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) ; | |
| align-items: stretch ; | |
| } | |
| .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) ; | |
| margin-bottom: var(--space-2) ; | |
| } | |
| .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 ; | |
| box-shadow: none ; | |
| background: transparent ; | |
| } | |
| .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 ; | |
| justify-content: center ; | |
| } | |
| /* 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) ; | |
| font-weight: var(--fw-semibold) ; | |
| } | |
| .compare-plot .xtitle, | |
| .compare-plot .ytitle, | |
| .compare-plot .legendtitletext { | |
| fill: var(--fg-1) ; | |
| } | |
| .compare-plot .legendtext, | |
| .compare-plot .xtick > text, | |
| .compare-plot .ytick > text, | |
| .compare-plot .annotation-text { | |
| fill: var(--fg-2) ; | |
| } | |
| /* 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) ; | |
| } | |
| .compare-plot .gridlayer path { | |
| stroke: var(--border-1) ; | |
| } | |
| /* 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) ; | |
| font-size: var(--fs-sm) ; | |
| margin: var(--space-1) 0 var(--space-2) ; | |
| } | |
| /* 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) ; | |
| margin: 0 0 4px ; | |
| line-height: 1.3 ; | |
| } | |
| /* 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 ; | |
| border: 1px solid var(--border-1) ; | |
| border-radius: var(--radius-lg); | |
| box-shadow: none ; | |
| padding: 0 ; | |
| 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 ; | |
| border: 0 ; | |
| box-shadow: none ; | |
| } | |
| /* 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) ; | |
| border: 0 ; | |
| border-bottom: 1px solid var(--border-1) ; | |
| padding: var(--space-4) ; | |
| margin: 0 ; | |
| border-radius: 0; | |
| } | |
| .compare-controls .compare-caption { | |
| margin-top: 0 ; | |
| margin-bottom: 0 ; | |
| } | |
| .compare-controls .compare-caption p:last-child { | |
| margin-bottom: 0 ; | |
| } | |
| /* 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) ; | |
| border: 0 ; | |
| box-shadow: none ; | |
| padding: var(--space-3) var(--space-3) 0 ; | |
| } | |
| .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 ; | |
| border: 0 ; | |
| box-shadow: none ; | |
| } | |
| /* --- 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) ; | |
| border: 1px solid var(--border-1) ; | |
| border-radius: var(--radius-lg); | |
| box-shadow: none ; | |
| padding: var(--space-3) var(--space-4) ; | |
| } | |
| /* 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 ; | |
| border: 0 ; | |
| box-shadow: none ; | |
| padding: 0 ; | |
| margin: 0 ; | |
| gap: var(--space-2) ; | |
| } | |
| /* 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 ; | |
| } | |
| .submit-section .submit-checks > .block-label, | |
| .submit-section .submit-checks > label > span:first-child { | |
| margin-bottom: 4px ; | |
| } | |
| .submit-section label > .wrap { | |
| padding: 0 ; | |
| } | |
| /* --- 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) ; | |
| } | |
| /* 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)) ; | |
| } | |
| /* 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% ; | |
| background: var(--hf-yellow) ; | |
| border-color: var(--hf-yellow) ; | |
| color: var(--hf-gray-900) ; | |
| font-weight: var(--fw-semibold) ; | |
| margin: 0 0 var(--space-4) ; | |
| } | |
| .submit-cta:hover { | |
| background: var(--hf-yellow-deep) ; | |
| border-color: var(--hf-yellow-deep) ; | |
| } | |
| /* --- 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 ; | |
| } | |
| .tab-nav button.selected { | |
| border-bottom-color: var(--hf-yellow) ; | |
| color: var(--hf-blue-deep) ; | |
| 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% ; | |
| width: 100% ; | |
| margin: 0 auto ; | |
| padding: var(--space-6) var(--space-8) ; | |
| 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; | |
| } | |