seldon_demo / static /style.css
paulnovello-nk's picture
Claude Opus 5.5
Open the upload dialog around its button
14cd2c8
Raw History Blame Contribute Delete
20.6 kB
/* Neuralk look: dusk banner, violet gradient accents, mono labels. Dark under Gradio's
.dark class, which the page sets by default; light with ?__theme=light. The header
keeps the banner's dusk in both. */
:root {
--ink: #f7f3ef; /* page */
--panel: #ffffff;
--line: #e4ddd6;
--text: #16131f;
--muted: #6b6478;
--accent: #4e29ff; /* labels on the page */
--best: rgba(78, 41, 255, 0.10);
--off: 232, 160, 120; /* off-diagonal cells, as r, g, b */
--off-alpha: 0.45;
}
.dark {
--ink: #0c0b12;
--panel: #15131f;
--line: #2a2638;
--text: #f3ece6;
--muted: #a59db3;
--accent: #7f72fd;
--best: rgba(78, 41, 255, 0.28);
--off: 232, 183, 154;
--off-alpha: 0.55;
}
.gradio-container {
max-width: 1180px !important;
width: 100% !important;
min-width: 0 !important;
margin: 0 auto !important;
padding: 0 16px 48px !important;
}
/* Header */
.hero {
position: relative;
margin: 16px 0 28px;
padding: 40px 40px 44px;
border: 1px solid var(--line);
border-radius: 6px;
overflow: hidden;
background:
linear-gradient(90deg, rgba(12, 11, 18, 0.92) 0%, rgba(12, 11, 18, 0.65) 55%, rgba(12, 11, 18, 0.25) 100%),
url('/gradio_api/file=static/banner.jpg') 12% 65% / 150% auto no-repeat; /* crops the banner's own logo out */
background-color: #0c0b12;
}
.hero .logo { height: 26px; width: auto; display: block; margin-bottom: 36px; }
/* Dark / light toggle, on the banner in both modes: the sun leads to light, the moon to dark.
Level with the logo, below the badge Hugging Face lays over the top-right of the page. */
#theme-toggle {
position: absolute;
top: 34px;
right: 24px;
width: 38px;
height: 38px;
display: grid;
place-items: center;
padding: 0;
border: 1px solid rgba(243, 236, 230, 0.28);
border-radius: 50%;
background: rgba(12, 11, 18, 0.45);
color: #f3ece6;
cursor: pointer;
transition: background 0.15s, border-color 0.15s;
}
#theme-toggle:hover { background: rgba(78, 41, 255, 0.55); border-color: #7f72fd; }
#theme-toggle:focus-visible { outline: 2px solid #7f72fd; outline-offset: 2px; }
#theme-toggle svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; }
#theme-toggle .icon-sun { display: none; }
.dark #theme-toggle .icon-sun { display: block; }
.dark #theme-toggle .icon-moon { display: none; }
.hero .eyebrow,
.section,
.sub,
.shape p {
font-family: 'Geist Mono', ui-monospace, monospace !important;
text-transform: uppercase;
letter-spacing: 0.08em;
}
/* The header's text sits on the dark banner in both modes. !important: on the Space,
Gradio's text colours load after this file and would give it the light page's ink. */
.hero .eyebrow { color: #7f72fd !important; font-size: 12px; margin: 0 0 12px; }
.hero h1 {
font-size: clamp(30px, 4.5vw, 48px) !important;
font-weight: 500 !important;
line-height: 1.05 !important;
letter-spacing: -0.02em;
color: #f3ece6 !important;
margin: 0 0 14px !important;
max-width: 14em;
}
.hero .lede { color: #d8cfc8 !important; font-size: 16px; line-height: 1.5; margin: 0; max-width: 34em; }
/* Section labels. Text colours below the header are !important too: Gradio's
`.prose *` rule outranks a single class and would paint them all body-text colour. */
.section { color: var(--accent) !important; font-size: 20px; font-weight: 600; margin: 28px 0 10px; }
.sub { color: var(--muted) !important; font-size: 13px; font-weight: 500; margin: 12px 0 8px; }
.shape p { color: var(--muted) !important; font-size: 11px; margin: 0; }
/* Seldon vs AutoGluon */
.compare {
width: 100%;
border-collapse: separate !important;
border-spacing: 0;
border: 1px solid var(--line) !important;
border-radius: 6px;
overflow: hidden;
margin: 4px 0 0;
}
.compare th,
.compare td {
border: none !important;
border-bottom: 1px solid var(--line) !important;
padding: 14px 18px !important;
text-align: left;
background: var(--panel);
}
.compare tbody tr:last-child th,
.compare tbody tr:last-child td { border-bottom: none !important; }
.compare thead th,
.compare tbody th {
font-family: 'Geist Mono', ui-monospace, monospace;
font-size: 11px;
font-weight: 400;
text-transform: uppercase;
letter-spacing: 0.08em;
color: var(--muted) !important;
}
.compare thead th:nth-child(2) { color: var(--accent) !important; }
.compare td {
color: var(--text) !important;
font-size: 26px;
font-weight: 500;
font-variant-numeric: tabular-nums;
width: 38%;
}
.compare td.best {
background: linear-gradient(160deg, var(--best), var(--panel) 75%);
box-shadow: inset 3px 0 0 #4e29ff;
}
/* Section 02: one card per model, its name above its live stages, "vs" between them,
and the Run button under both */
.model-cards { gap: 16px !important; margin: 4px 0 16px; align-items: stretch; }
.model-card {
--model: #4e29ff; /* the model's colour, for its stages */
--model-soft: rgba(78, 41, 255, 0.22);
position: relative;
overflow: hidden;
justify-content: flex-start;
gap: 18px !important;
padding: 22px 22px 20px !important;
background: var(--panel) !important;
border: 1px solid var(--line) !important;
border-radius: 6px !important;
}
.model-card::before { /* the card's colour, a band along its top */
content: "";
position: absolute;
inset: 0 0 auto 0;
height: 3px;
}
.seldon-card { background: linear-gradient(160deg, var(--best), var(--panel) 65%) !important; }
.seldon-card::before { background: linear-gradient(100deg, #482ad8, #4e29ff 50%, #7f72fd); }
.autogluon-card::before { background: rgb(var(--off)); }
.model-card > .block { flex-grow: 0 !important; } /* the head, then the stages, from the top */
/* Side by side, the two cards share one grid: each card's head and live part are two
rows of it (subgrid), so both heads take the taller one's height and the two time
bars, at the top of the live parts, sit at the same level whatever the wrapping.
Stacked on a narrow screen, each card is a column again. */
@media (min-width: 720px) {
.model-cards {
display: grid !important;
grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
grid-template-rows: auto auto;
row-gap: 0 !important;
}
.model-card {
display: grid !important;
grid-row: 1 / span 2;
grid-template-rows: subgrid;
row-gap: 18px !important;
align-content: start;
}
.model-cards > .vs-wrap { grid-row: 1 / span 2; }
}
.model-head { display: flex; flex-direction: column; gap: 6px; }
.model-head p { margin: 0 !important; }
.model-eyebrow {
font-family: 'Geist Mono', ui-monospace, monospace !important;
text-transform: uppercase;
letter-spacing: 0.08em;
font-size: 11px;
color: var(--muted) !important;
}
.seldon-card .model-eyebrow { color: var(--accent) !important; }
.dark .seldon-card { --model: #7f72fd; --model-soft: rgba(127, 114, 253, 0.26); }
.autogluon-card { --model: rgb(var(--off)); --model-soft: rgba(var(--off), 0.28); }
.model-name {
color: var(--text) !important;
font-size: 30px;
font-weight: 600;
letter-spacing: -0.01em;
line-height: 1.1;
}
.model-line { color: var(--muted) !important; font-size: 13px; line-height: 1.5; max-width: 34em; }
.vs-wrap { flex: 0 0 auto !important; width: auto !important; min-width: 0 !important; align-self: center; }
.vs {
display: grid;
place-items: center;
width: 48px;
height: 48px;
border-radius: 50%;
border: 1px solid var(--line);
background:
linear-gradient(var(--panel), var(--panel)) padding-box,
linear-gradient(135deg, #4e29ff, #7f72fd 45%, rgb(var(--off))) border-box;
border-color: transparent;
}
.vs span {
font-family: 'Geist Mono', ui-monospace, monospace;
font-size: 12px;
text-transform: uppercase;
letter-spacing: 0.1em;
color: var(--text);
}
.run-row { justify-content: center; margin: 0 0 24px; }
.run-button {
flex: 0 1 420px !important;
max-width: 420px;
height: 56px !important;
font-size: 18px !important;
font-weight: 600 !important;
letter-spacing: 0.01em;
box-shadow: 0 10px 30px -12px rgba(78, 41, 255, 0.7);
}
.run-button:disabled { opacity: 0.6; cursor: progress; box-shadow: none; }
/* A model's stages, live while it runs. The looping animations take their phase from
--t, the seconds since the run began, which each redraw of the card sets: a redraw
every quarter second does not restart them. One-off animations run from their start
state to the element's own style, which reduced motion shows at once. Running
stages are in the model's colour (--model): violet for Seldon-Mini, orange for
AutoGluon. */
.live { display: flex; flex-direction: column; gap: 14px; --t: 0; }
.live p { margin: 0 !important; }
.stages { list-style: none; margin: 0 !important; padding: 0 !important; display: flex; flex-direction: column; gap: 2px; }
.stage {
display: grid;
grid-template-columns: 14px 1fr auto;
align-items: center;
gap: 12px;
padding: 7px 0;
margin: 0 !important;
border-bottom: 1px dashed var(--line);
}
.stage:last-child { border-bottom: none; }
.stage .dot {
position: relative;
width: 14px;
height: 14px;
border-radius: 50%;
border: 1.5px solid var(--line);
box-sizing: border-box;
}
.stage-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.stage-text b { color: var(--text) !important; font-size: 14px; font-weight: 500; }
.stage-text em { color: var(--muted) !important; font-size: 12px; font-style: normal; }
.stage-note,
.live-label,
.budget p,
.chip em,
.weight span,
.viz-col span {
font-family: 'Geist Mono', ui-monospace, monospace;
font-size: 11px;
text-transform: uppercase;
letter-spacing: 0.08em;
color: var(--muted) !important;
font-variant-numeric: tabular-nums;
}
.stage.is-pending .stage-text b { color: var(--muted) !important; }
.stage.is-running .dot {
border-color: var(--model);
background: var(--model);
animation: live-pulse 1.4s ease-out infinite;
animation-delay: calc(var(--t) * -1s);
}
.stage.is-running .stage-note { color: var(--model) !important; }
/* A done stage's dot fills: it swells in the model's colour, a ring bursts out of it and
a check draws in. The three take their phase from --ago, the seconds since the stage
ended, which each redraw sets: a redraw resumes them instead of playing them again,
and a stage that ended long ago shows its end state. Without animation (reduced
motion), the end state: filled, checked, no ring. */
.stage.is-done .dot {
border-color: var(--model);
background: var(--model);
animation: dot-fill 0.55s cubic-bezier(0.2, 0.8, 0.2, 1) both;
animation-delay: calc(var(--ago, 10) * -1s);
}
.stage.is-done .dot::before { /* the check */
content: "";
position: absolute;
left: 4.2px;
top: 1.6px;
width: 3px;
height: 6.5px;
border: solid #fff;
border-width: 0 1.6px 1.6px 0;
transform: rotate(45deg);
animation: dot-check 0.3s ease-out both;
animation-delay: calc(0.3s - var(--ago, 10) * 1s);
}
.stage.is-done .dot::after { /* the ring */
content: "";
position: absolute;
inset: -1.5px;
border-radius: 50%;
border: 2px solid var(--model);
opacity: 0;
animation: dot-ring 0.75s ease-out both;
animation-delay: calc(0.12s - var(--ago, 10) * 1s);
}
.stage.is-done .stage-note { color: var(--text) !important; }
.stage.is-failed .dot { border-color: #e5484d; background: #e5484d; }
.stage.is-failed .stage-note { color: #e5484d !important; }
.live-note { color: var(--muted) !important; font-size: 12px; line-height: 1.5; }
.live-note.is-error { color: #e5484d !important; }
.live-label { margin: 2px 0 -6px !important; }
@keyframes live-pulse {
0% { box-shadow: 0 0 0 0 var(--model-soft); }
70% { box-shadow: 0 0 0 7px transparent; }
100% { box-shadow: 0 0 0 0 transparent; }
}
@keyframes dot-fill {
0% { background: transparent; border-color: var(--line); transform: scale(0.7); }
55% { background: var(--model); border-color: var(--model); transform: scale(1.35); }
100% { transform: scale(1); }
}
@keyframes dot-ring {
0% { transform: scale(1); opacity: 0.85; }
100% { transform: scale(2.6); opacity: 0; }
}
@keyframes dot-check {
0% { opacity: 0; transform: rotate(45deg) scale(0.3); }
100% { opacity: 1; transform: rotate(45deg) scale(1); }
}
/* Seldon-Mini: the train rows flow into the context, then the test rows light up */
.seldon-viz {
display: grid;
grid-template-columns: 1fr auto 1fr;
align-items: center;
gap: 14px;
padding: 14px 16px 10px;
border: 1px solid var(--line);
border-radius: 6px;
background: var(--panel);
}
.viz-col { display: flex; flex-direction: column; align-items: center; gap: 8px; }
.viz-rows,
.viz-test { display: flex; flex-direction: column; gap: 3px; width: 100%; max-width: 120px; }
.viz-rows i,
.viz-test i { display: block; height: 4px; border-radius: 2px; background: var(--line); }
.viz-test i { height: 6px; }
.viz-context {
display: grid;
place-items: center;
width: 88px;
height: 52px;
border-radius: 6px;
border: 1px solid var(--line);
background: var(--ink);
}
.viz-context b {
font-family: 'Geist Mono', ui-monospace, monospace;
font-size: 10px;
font-weight: 500;
text-transform: uppercase;
letter-spacing: 0.1em;
color: var(--muted) !important;
}
.seldon-viz.is-running .viz-rows i {
animation: viz-wait 1.6s ease-in-out infinite;
animation-delay: calc(var(--i) * 0.12s - var(--t) * 1s);
}
.seldon-viz.is-running .viz-context { border-color: var(--model); }
.seldon-viz.is-done .viz-rows i {
background: var(--model-soft);
animation: viz-flow 0.5s ease-in both;
animation-delay: calc(var(--i) * 0.05s);
}
.seldon-viz.is-done .viz-context {
border-color: transparent;
background: linear-gradient(100deg, #482ad8, #4e29ff 50%, #7f72fd);
animation: viz-fill 0.45s ease-out 0.4s both;
}
.seldon-viz.is-done .viz-context b { color: #ffffff !important; }
.seldon-viz.is-done .viz-test i {
background: linear-gradient(90deg, #4e29ff, #7f72fd);
animation: viz-light 0.3s ease-out both;
animation-delay: calc(0.85s + var(--i) * 0.08s);
}
.seldon-viz.is-failed .viz-context { border-color: #e5484d; }
@keyframes viz-wait { 0%, 100% { background: var(--line); } 50% { background: var(--model-soft); } }
@keyframes viz-flow { from { transform: translateX(-18px); opacity: 0; background: var(--line); } }
@keyframes viz-fill { from { background: var(--ink); border-color: var(--model); } }
@keyframes viz-light { from { background: var(--line); transform: scaleX(0.6); } }
/* AutoGluon: its fit against its time limit, its models, its ensemble */
.budget { display: flex; flex-direction: column; gap: 6px; }
.budget-bar { height: 6px; border-radius: 3px; background: var(--line); overflow: hidden; }
.budget-bar span { display: block; height: 100%; border-radius: 3px; background: var(--model); }
.budget p { display: flex; justify-content: space-between; gap: 12px; }
.chips { display: flex; flex-wrap: wrap; gap: 6px; }
.chip {
display: inline-flex;
flex-direction: column;
gap: 2px;
padding: 6px 9px;
border-radius: 5px;
border: 1px solid var(--line);
background: var(--ink);
}
.chip b { color: var(--text) !important; font-size: 12px; font-weight: 500; }
.chip em { font-style: normal; font-size: 10px; min-height: 1.2em; }
.chip.is-pending b,
.chip.is-skipped b { color: var(--muted) !important; }
.chip.is-pending,
.chip.is-skipped { opacity: 0.6; }
.chip.is-skipped b { text-decoration: line-through; }
.chip.is-running {
border-color: var(--model);
background: linear-gradient(100deg, var(--ink) 30%, var(--model-soft) 50%, var(--ink) 70%) 0 0 / 300% 100%;
animation: chip-sheen 1.6s linear infinite;
animation-delay: calc(var(--t) * -1s);
}
.chip.is-running em { color: var(--model) !important; }
.chip.is-done em { color: var(--text) !important; }
.chip.is-failed { border-color: #e5484d; }
.chip.is-failed em { color: #e5484d !important; }
.chip.in-ensemble { border-color: var(--model); box-shadow: inset 3px 0 0 var(--model); }
@keyframes chip-sheen { from { background-position: 100% 0; } to { background-position: -50% 0; } }
.weights { display: flex; flex-direction: column; gap: 6px; }
.weight { display: grid; grid-template-columns: minmax(96px, auto) 1fr 40px; align-items: center; gap: 10px; }
.weight span:first-child { color: var(--text) !important; text-transform: none; letter-spacing: 0; font-size: 12px; }
.weight span:last-child { text-align: right; }
.weight-bar { height: 6px; border-radius: 3px; background: var(--line); overflow: hidden; }
.weight-bar i { display: block; height: 100%; background: var(--model); }
@media (prefers-reduced-motion: reduce) {
.live *, .live *::before, .live *::after { animation: none !important; transition: none !important; }
}
.compare td.na { color: var(--muted) !important; }
.meta { color: var(--muted) !important; font-size: 12px; margin: 8px 0 4px; }
.intro { color: var(--muted) !important; font-size: 13px; line-height: 1.5; margin: 0 0 12px; max-width: 60em; }
.intro a { color: var(--accent) !important; }
/* Confusion matrix */
.cm-grid { display: flex; flex-wrap: wrap; gap: 24px 40px; margin-top: 12px; }
.cm-block { min-width: 0; max-width: 100%; }
.cm-wrap { overflow-x: auto; }
/* !important on the layout too: Gradio's table styles for .prose would box every cell. */
.cm {
border-collapse: separate !important;
border-spacing: 4px !important;
border: none !important;
width: auto !important;
font-family: 'Geist Mono', ui-monospace, monospace;
font-size: 13px;
}
.cm th {
color: var(--muted) !important;
font-weight: 400 !important;
padding: 6px 8px !important;
text-align: center !important;
white-space: nowrap;
border: none !important;
background: none !important;
}
.cm tbody th { text-align: right !important; }
.cm-corner { font-size: 10px; text-transform: uppercase; letter-spacing: 0.06em; }
.cm td {
min-width: 64px;
height: 56px;
padding: 0 8px !important;
text-align: center !important;
vertical-align: middle;
border-radius: 4px;
color: var(--text) !important;
border: 1px solid var(--line) !important;
background: rgba(var(--off), calc(var(--share) * var(--off-alpha))) !important;
}
.cm td.diag { background: rgba(78, 41, 255, calc(0.12 + var(--share) * 0.88)) !important; border-color: #4e29ff !important; }
.cm td.strong { color: #ffffff !important; } /* on a deep violet cell */
.cm td span { font-size: 16px; }
/* Footer */
.footnote { color: var(--muted) !important; font-size: 12px; line-height: 1.5; margin-top: 24px; max-width: 60em; }
/* Wide tables scroll inside their column instead of widening the page. */
.gradio-container .row { flex-wrap: wrap !important; }
.gradio-container .column,
.gradio-container .block { min-width: 0; max-width: 100%; }
@media (max-width: 640px) {
.hero { padding: 28px 20px 30px; background-size: auto, cover; background-position: center, 30% center; }
#theme-toggle { top: 22px; right: 16px; }
.hero .logo { margin-bottom: 24px; }
.compare th, .compare td { padding: 12px 10px !important; }
.compare td { font-size: 20px; }
.cm td { min-width: 48px; height: 44px; }
.cm-corner { white-space: normal !important; }
.vs-wrap { flex-basis: 100% !important; }
.vs { margin: 0 auto; width: 40px; height: 40px; }
}
/* The upload dialog: a page-wide backdrop and a card at its centre */
.modal-backdrop {
position: fixed !important;
inset: 0;
z-index: 1000;
width: 100vw !important;
max-width: none !important;
height: 100vh;
margin: 0 !important;
padding: var(--upload-top, 15vh) 24px 24px !important; /* set on opening, by the button */
display: flex;
flex-direction: column !important; /* a Gradio column: the card, from the top down */
justify-content: flex-start !important;
align-items: center !important;
background: rgba(8, 7, 14, 0.62) !important;
backdrop-filter: blur(4px);
}
.modal-card {
flex: 0 0 auto !important;
width: min(520px, 100%) !important;
gap: 16px !important;
padding: 26px 24px 22px !important;
background: var(--panel) !important;
border: 1px solid var(--line) !important;
border-radius: 8px !important;
box-shadow: 0 24px 64px rgba(0, 0, 0, 0.45);
position: relative;
overflow: hidden;
}
.modal-card::before { /* the Seldon card's band */
content: "";
position: absolute;
inset: 0 0 auto 0;
height: 3px;
background: linear-gradient(100deg, #482ad8, #4e29ff 50%, #7f72fd);
}
.modal-card p { margin: 0 0 6px !important; }
.modal-title { color: var(--text) !important; font-size: 24px; font-weight: 600; letter-spacing: -0.01em; }
.upload-open { margin-top: -4px; }