thox-zero-coder / thox_theme.py
tommytracx's picture
THOX ZeroGPU model Space
1a2024f verified
Raw
History Blame Contribute Delete
5.34 kB
"""THOX brand v2 Gradio theme -- the single source for every Space in this repo.
CANONICAL COPY. `ci/test_theme_parity.py` asserts every Space's copy is
byte-identical to this file. Edit here, then run `python build.py` (which
re-copies it) -- editing a Space's copy directly will fail CI.
WHY THIS FILE EXISTS
--------------------
Seven Spaces each carried their own inline theme. Two defects were present in
every one of them, measured on the live fleet:
1. The stylesheet forced `.gradio-container { background: #09090B !important }`
while Gradio still rendered its LIGHT palette. Loading `?__theme=light`
produced black body text on the forced near-black canvas:
#000000 on #09090B = 1.06:1
Invisible. Never pin one theme's colour; let the theme drive it.
2. Buttons and links were stock Gradio blue (`--color-accent` #3B82F6,
`--link-text-color` #2563EB), so nothing in the fleet's UI was actually THOX.
Fixing that in seven places would have drifted. It lives here instead.
CONTRAST -- from ttracx/thox-design-system (standards/brand-v2.md, ADR-0001)
---------------------------------------------------------------------------
The reflex pairing is wrong and must not be "fixed" back:
#FFFFFF on #05A451 = 3.26:1 FAILS WCAG AA
#000000 on #05A451 = 6.44:1 PASSES <- primary button, both themes
Light Dark
#03763B on #FFFFFF 5.74 #45e887 on #09090B 12.45 links
#52525B on #FFFFFF 7.73 #A1A1AA on #09090B 7.76 subdued text
#FFFFFF on #03763B 5.74 #000000 on #05A451 6.44 primary hover
Plain #05A451 is only 3.26:1 on white, so light-surface text uses brand.deep
(#03763B). Gradio's own `--body-text-color-subdued` default (#BBBBC2) is about
1.9:1 on white, so it is pinned in both modes here.
#10B981 / #34D399 are DEPRECATED v1 emeralds. Purple #A855F7 is MagStack-only
and neon #00FF88 is device-illumination-only -- neither belongs in UI chrome.
"""
from __future__ import annotations
import gradio as gr
THOX_GREEN = "#05A451" # brand.primary
THOX_ACCENT = "#45e887" # accent on dark
THOX_DEEP = "#03763B" # brand.deep -- accessible green on light surfaces
THOX_FOCUS = "#37C77A" # brand.light -- 9.11:1 on the dark canvas
THOX_HUE = gr.themes.Color(
c50="#E6F7EE", c100="#C2EBD6", c200="#8FDCB6", c300="#5CCB95",
c400=THOX_FOCUS, c500=THOX_GREEN, c600="#048A44", c700=THOX_DEEP,
c800="#026030", c900="#064E2E", c950="#04331E",
)
THOX_THEME = gr.themes.Base(
primary_hue=THOX_HUE,
neutral_hue=gr.themes.colors.zinc,
).set(
# Primary action: brand green with BLACK ink in both themes (6.44:1).
button_primary_background_fill=THOX_GREEN,
button_primary_background_fill_dark=THOX_GREEN,
button_primary_text_color="#000000",
button_primary_text_color_dark="#000000",
button_primary_background_fill_hover=THOX_DEEP,
button_primary_background_fill_hover_dark=THOX_ACCENT,
button_primary_text_color_hover="#FFFFFF", # on #03763B = 5.74:1
button_primary_text_color_hover_dark="#000000",
# Plain green is only 3.26:1 on white, so light links use brand.deep.
link_text_color=THOX_DEEP,
link_text_color_dark=THOX_ACCENT,
link_text_color_hover="#024F27",
link_text_color_hover_dark=THOX_GREEN,
# Gradio's default subdued grey fails AA on white; pin both modes.
body_text_color_subdued="#52525B", # 7.73:1 on white
body_text_color_subdued_dark="#A1A1AA", # 7.76:1 on #09090B
background_fill_primary_dark="#09090B",
background_fill_secondary_dark="#18181B",
border_color_primary_dark="#3F3F46",
)
# Shared chrome. Colour resolves through a Gradio variable or a per-theme
# override, so it follows the active theme instead of pinning one.
# `body.dark` is how Gradio 5 marks dark mode -- not html.dark, not data-theme.
THOX_CSS = f"""
:root {{
--thox-green: {THOX_GREEN}; --thox-accent: {THOX_ACCENT}; --thox-deep: {THOX_DEEP};
--thox-brand-ink: var(--thox-deep);
}}
.dark, body.dark {{ --thox-brand-ink: var(--thox-accent); }}
#thox-header {{
border-left: 3px solid var(--thox-green);
padding: 0.6rem 0 0.6rem 0.9rem; margin-bottom: 0.5rem;
}}
#thox-header h1 {{
color: var(--thox-brand-ink);
font-size: 1.15rem; margin: 0; letter-spacing: .02em;
}}
#thox-header p {{
color: var(--body-text-color-subdued);
font-size: .85rem; margin: .25rem 0 0;
}}
#thox-header code {{ color: var(--thox-brand-ink); }}
/* Amber is semantic, so it is pinned per theme rather than taken from a Gradio
variable -- the dark-mode #FBBF24 is only 1.7:1 on white. */
#thox-caveat {{
border-left: 3px solid #B45309; background: rgba(180,83,9,.07);
padding: .55rem .8rem; margin: .4rem 0 .6rem; border-radius: 4px;
color: #92400E; font-size: .82rem; line-height: 1.45;
}}
.dark #thox-caveat, body.dark #thox-caveat {{
border-left-color: #F59E0B; background: rgba(245,158,11,.08);
color: #FBBF24;
}}
:is(button, a, input, textarea, select):focus-visible {{
outline: 2px solid var(--thox-brand-ink); outline-offset: 2px;
}}
::selection {{ background: var(--thox-green); color: #000000; }}
@media (prefers-reduced-motion: reduce) {{
*, *::before, *::after {{
animation-duration: .01ms !important; transition-duration: .01ms !important;
}}
}}
"""