Spaces:
Running on Zero
fix(ui): wireframe-fidelity polish — neutral palette, mobile single-row, tight chrome
Browse filesThree problems the user surfaced after manual testing:
1. The rendered UI had a bluish-grey tint that the wireframes do not.
Root cause: gr.themes.colors.gray maps to Tailwind slate-* not true
neutral — --neutral-900 is #111827, --neutral-950 is #0b0f19, both
visibly cool on phone displays. Override the --neutral-* scale at
:root with real neutral hex values (#141414 / #0A0A0A), plus pin
the background / block / input fill custom properties to the
Brutalist Mono palette via !important to defeat Gradio's defaults.
2. Mobile tab strip wrapped to two rows because each radio label still
had width:100% from desktop AND the flex container had no nowrap
directive. Add flex-wrap:nowrap to the strip + give each label a
proper pill background (border + bg + radius) so they read as tabs
instead of plain text. Hide scrollbar but keep horizontal scroll.
3. Inputs / textareas / number fields used Gradio defaults which felt
soft compared to the wireframe's crisp Brutalist boxes. Sharpen
them: 1px BORDER border, 4px radius, SURFACE_STRONG background,
PRIMARY border on focus. Scoped to .ams-content so .gr-Audio /
.gr-JSON in the output column keep their normal internal layout.
Verified at 1440 (desktop) + 360 (mobile) via Playwright + screenshot
compare against docs/superpowers/specs/mockups/01_generate_mobile_errors.html.
Theme L1 tests still pass (3/3); ruff clean.
Still intentionally absent vs the wireframe: LoRA accordion (M2),
Advanced / LM-planner / DCW accordions (M2-M4), Demucs stems grid
+ multi-format export row (M5). Those land in future milestones.
|
@@ -62,6 +62,35 @@ def build_theme() -> gr.themes.Base:
|
|
| 62 |
|
| 63 |
|
| 64 |
CSS = f"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 65 |
/* === Body chrome ======================================================= */
|
| 66 |
.ams-header {{
|
| 67 |
display:flex; justify-content:space-between; align-items:baseline;
|
|
@@ -199,6 +228,44 @@ CSS = f"""
|
|
| 199 |
/* === Hide Gradio footer ================================================ */
|
| 200 |
footer {{ display:none !important; }}
|
| 201 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 202 |
/* === Component labels — kill the white pill, make them inline muted ==== */
|
| 203 |
/* Gradio renders component labels (e.g. gr.Audio "Output", gr.Code
|
| 204 |
"Metadata") as elevated white-pill blocks by default. The Brutalist
|
|
@@ -258,15 +325,19 @@ footer {{ display:none !important; }}
|
|
| 258 |
/* Real options live in the second .wrap (Gradio renders an extra
|
| 259 |
hidden one first); both flex-row + overflow + nowrap.
|
| 260 |
CRITICAL: override the desktop label width:100% — that's what
|
| 261 |
-
makes labels stack vertically inside a flex-row container.
|
|
|
|
|
|
|
| 262 |
.ams-side-radio .wrap {{
|
| 263 |
flex-direction:row !important;
|
|
|
|
| 264 |
overflow-x:auto !important;
|
| 265 |
overflow-y:hidden !important;
|
| 266 |
-
gap:
|
| 267 |
padding-bottom:2px !important;
|
| 268 |
/* Hide scrollbar but keep scrolling */
|
| 269 |
scrollbar-width:none !important;
|
|
|
|
| 270 |
}}
|
| 271 |
.ams-side-radio .wrap::-webkit-scrollbar {{
|
| 272 |
display:none !important;
|
|
@@ -279,13 +350,18 @@ footer {{ display:none !important; }}
|
|
| 279 |
max-width:max-content !important;
|
| 280 |
flex:0 0 auto !important;
|
| 281 |
font-size:11px !important;
|
|
|
|
| 282 |
white-space:nowrap !important;
|
| 283 |
-
padding:
|
| 284 |
/* Bottom border instead of left border for the horizontal context */
|
| 285 |
border-left:none !important;
|
| 286 |
border-bottom:2px solid transparent !important;
|
| 287 |
border-radius:4px !important;
|
| 288 |
justify-content:center !important;
|
|
|
|
|
|
|
|
|
|
|
|
|
| 289 |
}}
|
| 290 |
.ams-side-radio label.selected,
|
| 291 |
.ams-side-radio label:has(input[type="radio"]:checked) {{
|
|
|
|
| 62 |
|
| 63 |
|
| 64 |
CSS = f"""
|
| 65 |
+
/* === Override Gradio's Tailwind-slate "neutral" palette ================
|
| 66 |
+
Gradio's gr.themes.colors.gray is actually Tailwind slate-* which has
|
| 67 |
+
a noticeable blue tint (--neutral-900 = #111827, --neutral-950 = #0b0f19).
|
| 68 |
+
On phone displays with cool color temperatures this reads as bluish-grey
|
| 69 |
+
and contradicts the Brutalist Mono spec. Force true-neutral hex values. */
|
| 70 |
+
:root, html.dark {{
|
| 71 |
+
--neutral-50: #FAFAFA !important;
|
| 72 |
+
--neutral-100: #F5F5F5 !important;
|
| 73 |
+
--neutral-200: #E5E5E5 !important;
|
| 74 |
+
--neutral-300: #D4D4D4 !important;
|
| 75 |
+
--neutral-400: #A3A3A3 !important;
|
| 76 |
+
--neutral-500: #737373 !important;
|
| 77 |
+
--neutral-600: #525252 !important;
|
| 78 |
+
--neutral-700: #404040 !important;
|
| 79 |
+
--neutral-800: #262626 !important;
|
| 80 |
+
--neutral-900: #141414 !important;
|
| 81 |
+
--neutral-950: #0A0A0A !important;
|
| 82 |
+
--body-background-fill: {BG} !important;
|
| 83 |
+
--background-fill-primary: {SURFACE} !important;
|
| 84 |
+
--background-fill-secondary: {SURFACE_STRONG} !important;
|
| 85 |
+
--block-background-fill: {SURFACE} !important;
|
| 86 |
+
--block-label-background-fill: transparent !important;
|
| 87 |
+
--block-title-background-fill: transparent !important;
|
| 88 |
+
--input-background-fill: {SURFACE_STRONG} !important;
|
| 89 |
+
--border-color-primary: {BORDER} !important;
|
| 90 |
+
--border-color-accent: {BORDER_STRONG} !important;
|
| 91 |
+
--color-accent: {PRIMARY} !important;
|
| 92 |
+
}}
|
| 93 |
+
|
| 94 |
/* === Body chrome ======================================================= */
|
| 95 |
.ams-header {{
|
| 96 |
display:flex; justify-content:space-between; align-items:baseline;
|
|
|
|
| 228 |
/* === Hide Gradio footer ================================================ */
|
| 229 |
footer {{ display:none !important; }}
|
| 230 |
|
| 231 |
+
/* === Tighten Gradio chrome (narrow scope to avoid breaking output) =====
|
| 232 |
+
Only sharpen the INPUT control surfaces (textareas, number inputs)
|
| 233 |
+
so they read as crisp Brutalist Mono panels. Do NOT touch generic
|
| 234 |
+
``.block`` padding — that collapses gr.Audio / gr.JSON which need
|
| 235 |
+
their own internal spacing. */
|
| 236 |
+
.ams-content textarea,
|
| 237 |
+
.ams-content input[type="text"],
|
| 238 |
+
.ams-content input[type="number"] {{
|
| 239 |
+
background:{SURFACE_STRONG} !important;
|
| 240 |
+
border:1px solid {BORDER} !important;
|
| 241 |
+
border-radius:4px !important;
|
| 242 |
+
color:{INK} !important;
|
| 243 |
+
padding:10px !important;
|
| 244 |
+
}}
|
| 245 |
+
.ams-content textarea:focus,
|
| 246 |
+
.ams-content input[type="text"]:focus,
|
| 247 |
+
.ams-content input[type="number"]:focus {{
|
| 248 |
+
outline:none !important;
|
| 249 |
+
border-color:{PRIMARY} !important;
|
| 250 |
+
}}
|
| 251 |
+
.ams-content input[type="range"] {{
|
| 252 |
+
accent-color:{PRIMARY} !important;
|
| 253 |
+
}}
|
| 254 |
+
/* Component labels — uppercase, muted, no shadow.
|
| 255 |
+
``.gradio-container .block .label`` already covers this from the
|
| 256 |
+
earlier component-label rule, but restating for the form blocks
|
| 257 |
+
specifically gives the wireframe a consistent label scale. */
|
| 258 |
+
.ams-content .label-wrap,
|
| 259 |
+
.ams-content [data-testid="block-label"] {{
|
| 260 |
+
font-size:10px !important;
|
| 261 |
+
letter-spacing:0.08em !important;
|
| 262 |
+
text-transform:uppercase !important;
|
| 263 |
+
color:{INK_MUTED} !important;
|
| 264 |
+
background:transparent !important;
|
| 265 |
+
border:none !important;
|
| 266 |
+
padding:0 0 4px 0 !important;
|
| 267 |
+
}}
|
| 268 |
+
|
| 269 |
/* === Component labels — kill the white pill, make them inline muted ==== */
|
| 270 |
/* Gradio renders component labels (e.g. gr.Audio "Output", gr.Code
|
| 271 |
"Metadata") as elevated white-pill blocks by default. The Brutalist
|
|
|
|
| 325 |
/* Real options live in the second .wrap (Gradio renders an extra
|
| 326 |
hidden one first); both flex-row + overflow + nowrap.
|
| 327 |
CRITICAL: override the desktop label width:100% — that's what
|
| 328 |
+
makes labels stack vertically inside a flex-row container.
|
| 329 |
+
flex-wrap:nowrap forces a single row + horizontal scroll instead
|
| 330 |
+
of wrapping to 2 rows. */
|
| 331 |
.ams-side-radio .wrap {{
|
| 332 |
flex-direction:row !important;
|
| 333 |
+
flex-wrap:nowrap !important;
|
| 334 |
overflow-x:auto !important;
|
| 335 |
overflow-y:hidden !important;
|
| 336 |
+
gap:6px !important;
|
| 337 |
padding-bottom:2px !important;
|
| 338 |
/* Hide scrollbar but keep scrolling */
|
| 339 |
scrollbar-width:none !important;
|
| 340 |
+
-ms-overflow-style:none !important;
|
| 341 |
}}
|
| 342 |
.ams-side-radio .wrap::-webkit-scrollbar {{
|
| 343 |
display:none !important;
|
|
|
|
| 350 |
max-width:max-content !important;
|
| 351 |
flex:0 0 auto !important;
|
| 352 |
font-size:11px !important;
|
| 353 |
+
font-weight:600 !important;
|
| 354 |
white-space:nowrap !important;
|
| 355 |
+
padding:8px 12px !important;
|
| 356 |
/* Bottom border instead of left border for the horizontal context */
|
| 357 |
border-left:none !important;
|
| 358 |
border-bottom:2px solid transparent !important;
|
| 359 |
border-radius:4px !important;
|
| 360 |
justify-content:center !important;
|
| 361 |
+
background:{SURFACE_STRONG} !important;
|
| 362 |
+
border-top:1px solid {BORDER} !important;
|
| 363 |
+
border-right:1px solid {BORDER} !important;
|
| 364 |
+
border-left:1px solid {BORDER} !important;
|
| 365 |
}}
|
| 366 |
.ams-side-radio label.selected,
|
| 367 |
.ams-side-radio label:has(input[type="radio"]:checked) {{
|