python-to-rust-cpp / styles.py
YugJ's picture
Upload styles.py with huggingface_hub
97a0ef4 verified
Raw
History Blame Contribute Delete
14.6 kB
"""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; }
}
"""