hermes-hub/src/antigravity_provider/router/ui/theme.py

375 lines
12 KiB
Python

"""Hermes Hub — Centralized Design Tokens and Theme Definition (v3).
Source of Truth: Brand Guidelines & Brandbook
Primary Palette:
PRIMARY: #0F1510 (Obsidian Forest)
DARK: #1A2A1F (Deep Pine)
SECONDARY: #2F4A36 (Moss Slate)
LIGHT: #F7F1E3 (Warm Ivory)
ACCENT: #CDAA64 (Ancient Gold)
"""
from __future__ import annotations
class Theme:
# ── Core Brand Palette ──
PRIMARY = "#0F1510"
DARK = "#1A2A1F"
SECONDARY = "#2F4A36"
LIGHT = "#F7F1E3"
ACCENT = "#CDAA64"
# ── Surfaces & Backgrounds ──
BG_WINDOW = "#0F1510"
BG_SIDEBAR = "#142018"
BG_HEADER = "#16241B"
BG_STATUSBAR = "#121C15"
BG_MODAL_BACKDROP = "#080B08"
SURFACE = "#1D3123"
SURFACE_HOVER = "#274230"
SURFACE_ACTIVE = "#31543D"
SURFACE_SELECTED = "#284432"
SURFACE_MUTED = "#16251A"
# ── Borders ──
BORDER = "#2F4A36"
BORDER_SUBTLE = "#1F3526"
BORDER_ACCENT = "#CDAA64"
BORDER_HOVER = "#40644B"
# ── Typography Colors ──
TEXT_PRIMARY = "#F7F1E3"
TEXT_SECONDARY = "#C5BEAF"
TEXT_MUTED = "#8A9C8E"
TEXT_ON_ACCENT = "#0F1510"
TEXT_ACCENT = "#CDAA64"
TEXT_DISABLED = "#546457"
# ── Accent States ──
ACCENT_HOVER = "#DCBE7D"
ACCENT_PRESSED = "#BA954E"
ACCENT_DIM = "#3D3522"
ACCENT_GLOW = "#CDAA64"
DANGER_SURFACE = "#5A1E1E"
DANGER_SURFACE_HOVER = "#7A2828"
DANGER_BORDER = "#8A3333"
DANGER_TEXT = "#FFD6D6"
# ── Operational / Status Colors ──
STATUS_HEALTHY = "#2E7D32" # Vibrant Forest Green
STATUS_WARNING = "#D97706" # Amber Gold
STATUS_ERROR = "#DC2626" # Ruby Crimson
STATUS_INFO = "#2563EB" # Azure
STATUS_AUTH_REQUIRED = "#D97706"
STATUS_DISABLED = "#5A6B5D"
STATUS_FAILOVER = "#3B82F6"
STATUS_MAIN = "#CDAA64" # Gold Badge
STATUS_ORCHESTRATOR = "#E5C158" # Imperial Gold
# Semantic roles. Brand gold is intentionally not a health colour.
COLOR_POSITIVE = STATUS_HEALTHY
COLOR_CAUTION = STATUS_WARNING
COLOR_NEGATIVE = STATUS_ERROR
COLOR_NEUTRAL = STATUS_DISABLED
COLOR_BRAND = ACCENT
# ── Provider Specific Accent Colors ──
PROVIDER_ANTIGRAVITY = "#4285F4" # Google Blue
PROVIDER_CODEX = "#10A37F" # OpenAI Emerald
PROVIDER_OPENCODE = "#F97316" # OpenCode Orange
PROVIDER_CLAUDE = "#D97706"
PROVIDER_GROK = "#3B82F6"
PROVIDER_GENERIC = "#8B5CF6"
SCHEMES = ("dark", "hybrid", "light")
SCHEME_LABELS = {
"dark": "Тёмная",
"hybrid": "Средняя (гибрид)",
"light": "Светлая (бежевая)",
}
PALETTES = {
"dark": {
"PRIMARY": "#071A17",
"DARK": "#0B211D",
"SECONDARY": "#244B3C",
"LIGHT": "#F4EAD4",
"ACCENT": "#C89A2B",
"BG_WINDOW": "#061916",
"BG_SIDEBAR": "#08221E",
"BG_HEADER": "#071B18",
"BG_STATUSBAR": "#061512",
"BG_MODAL_BACKDROP": "#020B09",
"SURFACE": "#0B2520",
"SURFACE_HOVER": "#12342C",
"SURFACE_ACTIVE": "#194535",
"SURFACE_SELECTED": "#173B2E",
"SURFACE_MUTED": "#091E1A",
"BORDER": "#36513B",
"BORDER_SUBTLE": "#203A2D",
"BORDER_ACCENT": "#B78525",
"BORDER_HOVER": "#537456",
"TEXT_PRIMARY": "#F8F0DC",
"TEXT_SECONDARY": "#D1C7AE",
"TEXT_MUTED": "#8FA395",
"TEXT_ON_ACCENT": "#102018",
"TEXT_ACCENT": "#E0B84E",
"TEXT_DISABLED": "#617367",
"ACCENT_HOVER": "#E0B84E",
"ACCENT_PRESSED": "#A9781E",
"ACCENT_DIM": "#3D3218",
"ACCENT_GLOW": "#D9AA37",
"DANGER_SURFACE": "#4A2020",
"DANGER_SURFACE_HOVER": "#692A2A",
"DANGER_BORDER": "#8A3B36",
"DANGER_TEXT": "#FFD8D2",
"STATUS_HEALTHY": "#72C943",
"STATUS_WARNING": "#E1A62B",
"STATUS_ERROR": "#E45C4F",
"STATUS_INFO": "#4C8DD8",
"STATUS_AUTH_REQUIRED": "#E1A62B",
"STATUS_DISABLED": "#708078",
"STATUS_FAILOVER": "#4C8DD8",
"STATUS_MAIN": "#C89A2B",
"STATUS_ORCHESTRATOR": "#E0B84E",
"PROVIDER_ANTIGRAVITY": "#74A9FF",
"PROVIDER_CODEX": "#46BE8A",
"PROVIDER_OPENCODE": "#F39A50",
"PROVIDER_CLAUDE": "#DF9C63",
"PROVIDER_GROK": "#6DA6F2",
"PROVIDER_GENERIC": "#A99DD8",
"SIDEBAR_TEXT": "#F8F0DC",
"SIDEBAR_MUTED": "#8FA395",
"SIDEBAR_HOVER": "#12342C",
"SIDEBAR_SELECTED": "#173B2E",
},
"hybrid": {
"PRIMARY": "#F7F2E8",
"DARK": "#0A2721",
"SECONDARY": "#DCE6D7",
"LIGHT": "#FCF8F0",
"ACCENT": "#B98118",
"BG_WINDOW": "#F5F0E7",
"BG_SIDEBAR": "#08251F",
"BG_HEADER": "#FBF8F1",
"BG_STATUSBAR": "#EFE8DB",
"BG_MODAL_BACKDROP": "#E8E0D3",
"SURFACE": "#FBF8F1",
"SURFACE_HOVER": "#EEE8DA",
"SURFACE_ACTIVE": "#E1EAD9",
"SURFACE_SELECTED": "#E4EBD8",
"SURFACE_MUTED": "#F1EBE0",
"BORDER": "#D8CCB8",
"BORDER_SUBTLE": "#E7DDCE",
"BORDER_ACCENT": "#BD8B2F",
"BORDER_HOVER": "#AFA188",
"TEXT_PRIMARY": "#17241D",
"TEXT_SECONDARY": "#4C584F",
"TEXT_MUTED": "#7B817B",
"TEXT_ON_ACCENT": "#FFFFFF",
"TEXT_ACCENT": "#9B6C13",
"TEXT_DISABLED": "#A9AAA4",
"ACCENT_HOVER": "#CF9C39",
"ACCENT_PRESSED": "#936514",
"ACCENT_DIM": "#F0E4C8",
"ACCENT_GLOW": "#C59432",
"DANGER_SURFACE": "#F8E2DE",
"DANGER_SURFACE_HOVER": "#F1CBC5",
"DANGER_BORDER": "#C86155",
"DANGER_TEXT": "#812E28",
"STATUS_HEALTHY": "#397B35",
"STATUS_WARNING": "#BE7B13",
"STATUS_ERROR": "#C6473D",
"STATUS_INFO": "#326DAD",
"STATUS_AUTH_REQUIRED": "#BE7B13",
"STATUS_DISABLED": "#969B94",
"STATUS_FAILOVER": "#326DAD",
"STATUS_MAIN": "#B98118",
"STATUS_ORCHESTRATOR": "#A87817",
"PROVIDER_ANTIGRAVITY": "#326DAD",
"PROVIDER_CODEX": "#247A50",
"PROVIDER_OPENCODE": "#B96324",
"PROVIDER_CLAUDE": "#A55C2C",
"PROVIDER_GROK": "#326DAD",
"PROVIDER_GENERIC": "#7365A5",
"SIDEBAR_TEXT": "#F8F0DC",
"SIDEBAR_MUTED": "#98A89D",
"SIDEBAR_HOVER": "#12342C",
"SIDEBAR_SELECTED": "#173B2E",
},
"light": {
"PRIMARY": "#FFF9EE",
"DARK": "#FFF8EC",
"SECONDARY": "#E9DFC9",
"LIGHT": "#FFFDF8",
"ACCENT": "#A96F12",
"BG_WINDOW": "#FFF9EF",
"BG_SIDEBAR": "#FBF0DE",
"BG_HEADER": "#FFFDF8",
"BG_STATUSBAR": "#F7EDDE",
"BG_MODAL_BACKDROP": "#EDE2D2",
"SURFACE": "#FFFDF8",
"SURFACE_HOVER": "#F4E9D9",
"SURFACE_ACTIVE": "#DFE8D7",
"SURFACE_SELECTED": "#E7EEDC",
"SURFACE_MUTED": "#F8F0E5",
"BORDER": "#DDCFB9",
"BORDER_SUBTLE": "#EDE2D2",
"BORDER_ACCENT": "#B57A1C",
"BORDER_HOVER": "#B8A78D",
"TEXT_PRIMARY": "#1E281F",
"TEXT_SECONDARY": "#505A51",
"TEXT_MUTED": "#7E837C",
"TEXT_ON_ACCENT": "#FFFFFF",
"TEXT_ACCENT": "#90600F",
"TEXT_DISABLED": "#ADAEA7",
"ACCENT_HOVER": "#C58B2D",
"ACCENT_PRESSED": "#835609",
"ACCENT_DIM": "#F2E3C4",
"ACCENT_GLOW": "#BA8428",
"DANGER_SURFACE": "#F9E5E0",
"DANGER_SURFACE_HOVER": "#F3D0C9",
"DANGER_BORDER": "#C85A4E",
"DANGER_TEXT": "#812E28",
"STATUS_HEALTHY": "#367B36",
"STATUS_WARNING": "#B97612",
"STATUS_ERROR": "#C6473D",
"STATUS_INFO": "#326DAD",
"STATUS_AUTH_REQUIRED": "#B97612",
"STATUS_DISABLED": "#999D96",
"STATUS_FAILOVER": "#326DAD",
"STATUS_MAIN": "#A96F12",
"STATUS_ORCHESTRATOR": "#9D6810",
"PROVIDER_ANTIGRAVITY": "#326DAD",
"PROVIDER_CODEX": "#247A50",
"PROVIDER_OPENCODE": "#B96324",
"PROVIDER_CLAUDE": "#A55C2C",
"PROVIDER_GROK": "#326DAD",
"PROVIDER_GENERIC": "#7365A5",
"SIDEBAR_TEXT": "#283129",
"SIDEBAR_MUTED": "#767D76",
"SIDEBAR_HOVER": "#F0E3D0",
"SIDEBAR_SELECTED": "#E6EEDB",
},
}
current_scheme = "dark"
@classmethod
def apply_scheme(cls, scheme: str) -> str:
"""Activate a complete palette and return its normalized key."""
normalized = scheme if scheme in cls.PALETTES else "dark"
for token, value in cls.PALETTES[normalized].items():
setattr(cls, token, value)
cls.current_scheme = normalized
cls.COLOR_POSITIVE = cls.STATUS_HEALTHY
cls.COLOR_CAUTION = cls.STATUS_WARNING
cls.COLOR_NEGATIVE = cls.STATUS_ERROR
cls.COLOR_NEUTRAL = cls.STATUS_DISABLED
cls.COLOR_BRAND = cls.ACCENT
return normalized
# ── Spacing Scale (px) ──
SPACE_XS = 4
SPACE_SM = 8
SPACE_MD = 12
SPACE_LG = 16
SPACE_XL = 24
SPACE_2XL = 32
# Layout aliases used by views and reusable components.
PAGE_PAD_X = SPACE_LG
PAGE_PAD_Y = SPACE_MD
SECTION_GAP = SPACE_MD
CARD_PAD_X = SPACE_MD
CARD_PAD_Y = SPACE_MD
INLINE_GAP = SPACE_SM
# ── Corner Radius Scale (px) ──
RADIUS_SM = 6
RADIUS_MD = 10
RADIUS_LG = 14
RADIUS_PILL = 999
# ── Control Heights & Dimensions ──
HEIGHT_BTN_SM = 30
HEIGHT_BTN_MD = 38
HEIGHT_BTN_LG = 44
HEIGHT_NAV_ITEM = 34
HEIGHT_HEADER = 56
HEIGHT_STATUSBAR = 30
WIDTH_SIDEBAR = 190
HEIGHT_INPUT = 36
HEIGHT_BADGE = 24
ACCOUNT_CARD_MIN_HEIGHT = 188
ACCOUNT_CARD_COLUMNS = 3
# ── Fonts ──
FONT_FAMILY_TITLE = "Cinzel"
FONT_FAMILY_UI = "Segoe UI"
FONT_FAMILY_MONO = "Consolas"
@classmethod
def font_title_hero(cls):
return (cls.FONT_FAMILY_TITLE, 24, "bold")
@classmethod
def font_title_page(cls):
return (cls.FONT_FAMILY_UI, 20, "bold")
@classmethod
def font_title(cls):
"""Compatibility alias for the normalized page title."""
return cls.font_title_page()
@classmethod
def font_title_section(cls):
return (cls.FONT_FAMILY_UI, 17, "bold")
@classmethod
def font_heading(cls):
return (cls.FONT_FAMILY_UI, 15, "bold")
@classmethod
def font_subheading(cls):
return (cls.FONT_FAMILY_UI, 14, "bold")
@classmethod
def font_body(cls):
return (cls.FONT_FAMILY_UI, 13)
@classmethod
def font_body_bold(cls):
return (cls.FONT_FAMILY_UI, 13, "bold")
@classmethod
def font_caption(cls):
return (cls.FONT_FAMILY_UI, 11)
@classmethod
def font_micro(cls):
return (cls.FONT_FAMILY_UI, 10)
@classmethod
def font_mono(cls):
return (cls.FONT_FAMILY_MONO, 13)
@classmethod
def font_mono_sm(cls):
return (cls.FONT_FAMILY_MONO, 12)
@classmethod
def font_badge_bold(cls):
return (cls.FONT_FAMILY_UI, 10, "bold")
@classmethod
def font_icon(cls):
return (cls.FONT_FAMILY_UI, 15)
@classmethod
def font_metric(cls):
return (cls.FONT_FAMILY_UI, 24, "bold")
Theme.apply_scheme("dark")