Spaces:
Running on Zero
Running on Zero
| """Stylesheet for the interface. | |
| Design notes, so future edits do not quietly undo the reasoning: | |
| * Aurora over void. A near-black indigo ground with three slow colour fields | |
| bleeding across it. Flat #111 with one grey border on everything is what | |
| made the earlier pass read as bland. | |
| * Panels are glass: translucent fill, blurred backdrop, a bright top hairline | |
| to catch the light. Depth comes from light, not from outlines. | |
| * Three saturated hues carry meaning and nothing else does - cyan is always | |
| Python, amber is always the compiled target, violet is the one action that | |
| costs something. Colour as a code, not decoration. | |
| * Timing rows are CSS grid with a dedicated numeral column and a separate unit | |
| column, so decimal points align down the stack. Right-aligning "24.739 s" | |
| against "337.20 ms" as whole strings makes the digits jitter. | |
| * Radii are generous and consistent: 22px panels, 16px controls, pills for | |
| buttons. | |
| """ | |
| CSS = """ | |
| :root { | |
| --void: #06040f; | |
| --ink: #0b0818; | |
| --glass: rgba(28, 24, 48, .55); | |
| --glass-2: rgba(38, 33, 64, .58); | |
| --glass-3: rgba(50, 44, 82, .5); | |
| --edge: rgba(160, 140, 255, .13); | |
| --edge-lit: rgba(190, 175, 255, .28); | |
| --text: #f0ecff; | |
| --text-dim: #a49dc4; | |
| --text-faint: #6f6892; | |
| --py: #22d3ee; | |
| --py-deep: #0e9bb8; | |
| --target: #fb923c; | |
| --target-deep: #ea6f18; | |
| --accent: #a855f7; | |
| --accent-2: #ec4899; | |
| --ok: #34d399; | |
| --warn: #fbbf24; | |
| --err: #fb7185; | |
| --r-xl: 24px; | |
| --r-lg: 18px; | |
| --r-md: 14px; | |
| --r-sm: 10px; | |
| } | |
| /* ---------- ground ---------- */ | |
| /* The platform paints the page behind the app. Without this the margins | |
| outside the container stay flat black while the container carries the | |
| gradient, leaving a visible seam down both edges. */ | |
| body, | |
| gradio-app, | |
| .gradio-container > .main { | |
| background: var(--void) !important; | |
| } | |
| .gradio-container { | |
| max-width: 1520px !important; | |
| margin: 0 auto !important; | |
| padding: 0 30px 60px !important; | |
| color: var(--text) !important; | |
| background: | |
| radial-gradient(1200px 620px at 8% -12%, rgba(34,211,238,.15), transparent 60%), | |
| radial-gradient(1000px 560px at 96% -4%, rgba(168,85,247,.18), transparent 58%), | |
| radial-gradient(1100px 700px at 52% 108%, rgba(236,72,153,.10), transparent 62%), | |
| linear-gradient(178deg, var(--ink), var(--void) 70%) !important; | |
| background-attachment: fixed !important; | |
| } | |
| .gradio-container .prose, | |
| .gradio-container .prose * { color: var(--text); } | |
| /* Neutralise Gradio's own block chrome; our panels carry the structure. */ | |
| .gradio-container .block, | |
| .gradio-container .form { | |
| background: transparent !important; | |
| border-color: var(--edge) !important; | |
| border-radius: var(--r-lg) !important; | |
| } | |
| /* ---------- masthead ---------- */ | |
| .masthead { padding: 44px 0 26px; } | |
| .masthead h1 { | |
| margin: 0 0 13px; | |
| font-size: clamp(1.75rem, 3.2vw, 2.45rem); | |
| font-weight: 800; | |
| letter-spacing: -0.035em; | |
| line-height: 1.08; | |
| } | |
| /* display:inline-block is required - an inline span has a fragmented | |
| background box, so background-clip:text clips against nothing and the | |
| transparent fill renders the word invisible. */ | |
| .masthead h1 .py, | |
| .masthead h1 .rs { | |
| display: inline-block; | |
| -webkit-background-clip: text; background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| color: var(--py); /* fallback if background-clip is unsupported */ | |
| } | |
| .masthead h1 .py { background-image: linear-gradient(92deg, #67e8f9, var(--py)); } | |
| .masthead h1 .rs { | |
| background-image: linear-gradient(92deg, var(--target), #f472b6); | |
| color: var(--target); | |
| } | |
| .masthead h1 .arrow { color: var(--text-faint); font-weight: 300; margin: 0 10px; } | |
| .masthead p { | |
| margin: 0; | |
| color: var(--text-dim); | |
| font-size: 1.03rem; | |
| max-width: 68ch; | |
| line-height: 1.62; | |
| } | |
| .masthead .links { margin-top: 20px; display: flex; gap: 10px; flex-wrap: wrap; } | |
| .masthead .links a { | |
| font-size: .84rem; | |
| font-weight: 500; | |
| color: var(--text-dim); | |
| text-decoration: none; | |
| border: 1px solid var(--edge); | |
| background: var(--glass); | |
| backdrop-filter: blur(12px); | |
| border-radius: 999px; | |
| padding: 8px 17px; | |
| transition: all .2s cubic-bezier(.22,1,.36,1); | |
| } | |
| .masthead .links a:hover { | |
| color: #fff; | |
| border-color: var(--edge-lit); | |
| background: rgba(168,85,247,.18); | |
| transform: translateY(-1px); | |
| box-shadow: 0 6px 20px -8px rgba(168,85,247,.7); | |
| } | |
| /* ---------- glass panel base ---------- */ | |
| /* NOTE: backdrop-filter must never be applied to an ancestor of a Gradio | |
| dropdown. Gradio renders the option list as position:fixed, and | |
| backdrop-filter (like filter and transform) makes the styled element the | |
| containing block for fixed descendants - so the menu gets positioned | |
| against the card instead of the viewport and lands off-screen | |
| (measured at y = -123px). The picker row is therefore excluded and uses a | |
| plain translucent fill instead. */ | |
| .verdict, | |
| .gradio-container .accordion, | |
| .gradio-container details { | |
| background: var(--glass) !important; | |
| backdrop-filter: blur(16px) saturate(140%); | |
| -webkit-backdrop-filter: blur(16px) saturate(140%); | |
| border: 1px solid var(--edge) !important; | |
| box-shadow: | |
| 0 1px 0 rgba(255,255,255,.07) inset, | |
| 0 24px 60px -34px rgba(0,0,0,.95); | |
| } | |
| .picker > * { | |
| background: var(--glass-2) !important; /* no backdrop-filter here - see above */ | |
| border: 1px solid var(--edge) !important; | |
| box-shadow: | |
| 0 1px 0 rgba(255,255,255,.07) inset, | |
| 0 24px 60px -34px rgba(0,0,0,.95); | |
| } | |
| /* ---------- verdict ---------- */ | |
| .verdict { | |
| border-radius: var(--r-xl) !important; | |
| padding: 24px 30px; | |
| margin-bottom: 22px; | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| /* a thin lit seam across the top edge */ | |
| .verdict::before { | |
| content: ""; | |
| position: absolute; inset: 0 0 auto 0; height: 1px; | |
| background: linear-gradient(90deg, transparent, var(--edge-lit) 22%, | |
| rgba(236,72,153,.4) 52%, var(--edge-lit) 78%, transparent); | |
| } | |
| .verdict:has(.idle) { padding: 17px 26px; } | |
| .verdict .idle { | |
| color: var(--text-faint); | |
| font-size: .9rem; | |
| margin: 0; | |
| text-align: center; | |
| } | |
| .verdict-grid { | |
| display: grid; | |
| grid-template-columns: auto minmax(280px, 1fr) auto; | |
| align-items: center; | |
| gap: 36px; | |
| } | |
| .speedup { | |
| font-size: clamp(2.6rem, 4.8vw, 3.5rem); | |
| font-weight: 900; | |
| line-height: .92; | |
| letter-spacing: -0.05em; | |
| background: linear-gradient(96deg, var(--target) 4%, var(--accent-2) 52%, var(--accent) 96%); | |
| -webkit-background-clip: text; background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| white-space: nowrap; | |
| filter: drop-shadow(0 4px 18px rgba(236,72,153,.35)); | |
| } | |
| .speedup-label { | |
| font-size: .68rem; | |
| text-transform: uppercase; | |
| letter-spacing: .15em; | |
| color: var(--text-faint); | |
| margin-top: 10px; | |
| -webkit-text-fill-color: var(--text-faint); | |
| } | |
| /* Grid, not flex - guarantees the digits line up between rows. */ | |
| .timing-row { | |
| display: grid; | |
| grid-template-columns: 66px 1fr 78px 30px; | |
| align-items: center; | |
| gap: 14px; | |
| margin-bottom: 12px; | |
| font-size: .87rem; | |
| } | |
| .timing-row:last-child { margin-bottom: 0; } | |
| .timing-row .name { color: var(--text-dim); } | |
| .timing-row .bar-track { | |
| display: block; /* spans are inline; height would be dropped */ | |
| height: 11px; | |
| background: rgba(255,255,255,.055); | |
| border-radius: 999px; | |
| overflow: hidden; | |
| box-shadow: 0 1px 2px rgba(0,0,0,.4) inset; | |
| } | |
| .timing-row .bar { | |
| display: block; /* same reason - the fill would never paint */ | |
| height: 100%; | |
| min-width: 5px; | |
| border-radius: 999px; | |
| transition: width .6s cubic-bezier(.22,1,.36,1); | |
| } | |
| .timing-row.py .bar { | |
| background: linear-gradient(90deg, var(--py-deep), var(--py)); | |
| box-shadow: 0 0 14px rgba(34,211,238,.55); | |
| } | |
| .timing-row.target .bar { | |
| background: linear-gradient(90deg, var(--target-deep), var(--target)); | |
| box-shadow: 0 0 14px rgba(251,146,60,.6); | |
| } | |
| .timing-row .num { | |
| text-align: right; | |
| font-variant-numeric: tabular-nums; | |
| font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; | |
| color: var(--text); | |
| } | |
| .timing-row .unit { | |
| text-align: left; | |
| font-size: .78rem; | |
| color: var(--text-faint); | |
| font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; | |
| } | |
| .badge { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 8px; | |
| font-size: .81rem; | |
| font-weight: 600; | |
| padding: 10px 18px; | |
| border-radius: 999px; | |
| white-space: nowrap; | |
| backdrop-filter: blur(8px); | |
| } | |
| .badge.match { | |
| background: rgba(52,211,153,.14); color: var(--ok); | |
| border: 1px solid rgba(52,211,153,.36); | |
| box-shadow: 0 0 22px -6px rgba(52,211,153,.5); | |
| } | |
| .badge.mismatch { | |
| background: rgba(251,113,133,.14); color: var(--err); | |
| border: 1px solid rgba(251,113,133,.36); | |
| box-shadow: 0 0 22px -6px rgba(251,113,133,.5); | |
| } | |
| .badge.unknown { | |
| background: rgba(251,191,36,.13); color: var(--warn); | |
| border: 1px solid rgba(251,191,36,.34); | |
| } | |
| /* ---------- picker row ---------- */ | |
| /* Gradio renders Row children flush, which reads as one bar sliced by seams. | |
| Separate cards are most of the difference between designed and default. */ | |
| .picker { gap: 15px !important; background: transparent !important; border: none !important; } | |
| .picker > * { | |
| border-radius: var(--r-lg) !important; | |
| padding: 6px 8px 8px !important; | |
| transition: border-color .2s ease, box-shadow .2s ease; | |
| } | |
| .picker > *:focus-within { | |
| border-color: rgba(168,85,247,.55) !important; | |
| box-shadow: 0 0 0 3px rgba(168,85,247,.13), 0 24px 60px -34px rgba(0,0,0,.95) !important; | |
| } | |
| .picker .block, .picker .form { | |
| background: transparent !important; border: none !important; box-shadow: none !important; | |
| } | |
| .picker input, .picker .wrap { border-radius: var(--r-md) !important; } | |
| .picker span[data-testid="block-info"], | |
| .picker label > span, | |
| .picker label span { | |
| font-size: .71rem !important; | |
| text-transform: uppercase !important; | |
| letter-spacing: .13em !important; | |
| color: var(--text-faint) !important; | |
| font-weight: 700 !important; | |
| } | |
| .status-line { font-size: .86rem; color: var(--text-dim); margin: 6px 0 18px; padding-left: 3px; } | |
| .status-line strong { color: var(--py); font-weight: 600; } | |
| /* ---------- code panes ---------- */ | |
| .pane .block { border-radius: var(--r-xl) !important; overflow: hidden; } | |
| .pane .cm-editor, .pane textarea { | |
| background: rgba(10,8,22,.72) !important; | |
| border-radius: var(--r-xl) !important; | |
| } | |
| .pane label span { font-weight: 600 !important; } | |
| /* ---------- outputs ---------- */ | |
| .out-box textarea { | |
| font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace !important; | |
| font-size: .845rem !important; | |
| line-height: 1.62 !important; | |
| border-radius: var(--r-lg) !important; | |
| background: rgba(10,8,22,.72) !important; | |
| backdrop-filter: blur(8px); | |
| } | |
| .py-out textarea { | |
| border: 1px solid rgba(34,211,238,.3) !important; | |
| color: #a5f3fc !important; | |
| box-shadow: 0 0 26px -12px rgba(34,211,238,.6) !important; | |
| } | |
| .rust-out textarea { | |
| border: 1px solid rgba(251,146,60,.3) !important; | |
| color: #fed7aa !important; | |
| box-shadow: 0 0 26px -12px rgba(251,146,60,.6) !important; | |
| } | |
| /* ---------- controls ---------- */ | |
| .controls { gap: 14px !important; align-items: stretch !important; margin: 8px 0 6px; } | |
| /* elem_classes lands on the <button> for Buttons but a wrapper <div> for most | |
| other components, so both are matched. */ | |
| .btn-convert, .btn-convert button { | |
| background-image: linear-gradient(96deg, var(--accent) 0%, var(--accent-2) 100%) !important; | |
| color: #fff !important; | |
| font-weight: 700 !important; | |
| border: none !important; | |
| border-radius: 999px !important; | |
| padding: 14px 24px !important; | |
| letter-spacing: .012em; | |
| box-shadow: 0 8px 28px -10px rgba(192,60,190,.9), | |
| 0 1px 0 rgba(255,255,255,.22) inset !important; | |
| transition: transform .18s cubic-bezier(.22,1,.36,1), box-shadow .18s ease, filter .18s ease; | |
| } | |
| .btn-convert:hover, .btn-convert button:hover { | |
| filter: brightness(1.12) saturate(1.1); | |
| transform: translateY(-2px); | |
| box-shadow: 0 14px 36px -10px rgba(192,60,190,1), | |
| 0 1px 0 rgba(255,255,255,.3) inset !important; | |
| } | |
| .btn-convert:active, .btn-convert button:active { transform: translateY(0); } | |
| .btn-run, .btn-run button { | |
| background: var(--glass-2) !important; | |
| background-image: none !important; | |
| backdrop-filter: blur(12px); | |
| color: var(--text) !important; | |
| border: 1px solid var(--edge) !important; | |
| border-radius: 999px !important; | |
| padding: 14px 24px !important; | |
| font-weight: 600 !important; | |
| transition: all .18s cubic-bezier(.22,1,.36,1); | |
| } | |
| .btn-run.py:hover, .btn-run.py button:hover { | |
| border-color: var(--py) !important; color: var(--py) !important; | |
| background: rgba(34,211,238,.13) !important; | |
| box-shadow: 0 8px 26px -12px rgba(34,211,238,.9) !important; | |
| transform: translateY(-2px); | |
| } | |
| .btn-run.rust:hover, .btn-run.rust button:hover { | |
| border-color: var(--target) !important; color: var(--target) !important; | |
| background: rgba(251,146,60,.13) !important; | |
| box-shadow: 0 8px 26px -12px rgba(251,146,60,.9) !important; | |
| transform: translateY(-2px); | |
| } | |
| .btn-run[disabled], .btn-run button[disabled] { | |
| opacity: .35 !important; cursor: not-allowed !important; transform: none !important; | |
| } | |
| /* ---------- key panel ---------- */ | |
| .gradio-container .accordion, | |
| .gradio-container details { border-radius: var(--r-lg) !important; } | |
| .keybox, .keybox input { | |
| border-radius: var(--r-md) !important; | |
| background: rgba(10,8,22,.6) !important; | |
| } | |
| .key-note { font-size: .855rem; color: var(--text-dim); line-height: 1.68; } | |
| .key-note strong { color: var(--text); } | |
| .key-note code { | |
| background: var(--glass-3); padding: 2px 7px; | |
| border-radius: var(--r-sm); font-size: .93em; | |
| } | |
| /* ---------- footer ---------- */ | |
| .footer { | |
| margin-top: 40px; padding-top: 26px; | |
| border-top: 1px solid var(--edge); | |
| color: var(--text-faint); | |
| font-size: .82rem; line-height: 1.78; | |
| } | |
| .footer strong { color: var(--text-dim); } | |
| .footer code { | |
| background: var(--glass-3); padding: 2px 7px; | |
| border-radius: var(--r-sm); color: var(--text-dim); | |
| } | |
| /* Gradio's own footer advertises Gradio; the project's footer replaces it. */ | |
| footer { display: none !important; } | |
| @media (prefers-reduced-motion: reduce) { | |
| * { transition: none !important; animation: none !important; } | |
| } | |
| @media (max-width: 980px) { | |
| .verdict-grid { grid-template-columns: 1fr; gap: 20px; } | |
| .badge-cell { justify-self: start; } | |
| } | |
| @media (max-width: 880px) { | |
| .gradio-container { padding: 0 15px 40px !important; } | |
| .verdict { padding: 20px; } | |
| .timing-row { grid-template-columns: 56px 1fr 66px 26px; gap: 10px; } | |
| } | |
| """ | |