From e8b5e5c2edaf6200e4fcd951ca90e66241b983dc Mon Sep 17 00:00:00 2001 From: Inferencebot Date: Tue, 29 Sep 2026 21:26:35 -0600 Subject: [PATCH] Theme v3: stop remapping Tailwind tokens; tint surfaces only, key off html.dark class, explicit text contrast backstops --- chat-theme/openwebui-custom.css | 231 ++++++++------------------------ 1 file changed, 59 insertions(+), 172 deletions(-) diff --git a/chat-theme/openwebui-custom.css b/chat-theme/openwebui-custom.css index b906b8f..7ef54c7 100644 --- a/chat-theme/openwebui-custom.css +++ b/chat-theme/openwebui-custom.css @@ -1,9 +1,16 @@ -/* Inference Cooperative theme for Open WebUI +/* Inference Cooperative theme for Open WebUI — v3 House style: cream #faf8f5, ink #2d3327, greens #5b8c5a/#6ba86b/#7ab87a, - bronze #a97a4a, earthy red #b3543a. Figtree via co-op-hosted fonts. - Loaded via /static/custom.css (native Open WebUI hook). */ + bronze #a97a4a, earthy red #b3543a. Figtree served same-origin. -/* ---------- Font (served same-origin from the chat app, no CORS needed) ---------- */ + v3 approach: STOP remapping Tailwind's gray tokens wholesale (v1/v2 broke + text contrast in both modes). Instead: + - Key everything off the app's OWN class strategy (html.dark), not + prefers-color-scheme, so the app's theme toggle stays authoritative. + - Tint only large surfaces (app background, sidebar, message bubbles). + - Leave ALL text tokens alone; add explicit high-contrast rules only where + Open WebUI's own defaults are too faint. */ + +/* ---------- Font (same-origin, no CORS needed) ---------- */ @font-face { font-family: 'Figtree'; font-style: normal; @@ -33,147 +40,72 @@ src: url('/static/fonts/figtree-700.woff2') format('woff2'); } -:root { - --coop-cream: #faf8f5; - --coop-cream-2: #f1ede5; - --coop-ink: #2d3327; - --coop-muted: #6b7a62; - --coop-green-deep: #5b8c5a; - --coop-green-mid: #6ba86b; - --coop-green-soft: #7ab87a; - --coop-bronze: #a97a4a; - --coop-earth: #b3543a; - --coop-border: #e4e0d8; -} - -/* Light mode base. - NOTE: base text colors stay near-Tailwind defaults for contrast; we tint - surfaces (backgrounds, borders) rather than pushing text colors around, - because remapping the whole gray scale made body text and placeholders - hard to read (gray-400/500 shifted too far toward olive). */ html, body { font-family: 'Figtree', -apple-system, 'Segoe UI', system-ui, sans-serif !important; } -/* ---------- Light theme: warm surfaces, readable text ---------- */ -@media (prefers-color-scheme: light), (prefers-color-scheme: no-preference) { - html:not(.dark) { - /* App background: cream. Text: unchanged (dark slate) for max contrast. */ - --color-gray-50: #faf8f5; - --color-gray-75: #f6f3ee; - --color-gray-100: #f1ede5; - --color-gray-200: #e4e0d8; - --color-gray-300: #d4cfc3; - --color-gray-400: #9c978b; /* placeholders — darker than before, still muted */ - --color-gray-500: #75705f; - /* gray-600 through 950 UNTOUCHED: body text keeps Tailwind's near-black - contrast instead of olive drift */ - } +/* ---------- Light mode (no .dark class): cream surfaces ---------- */ +html:not(.dark) body { + background-color: #faf8f5 !important; } -/* Dark mode: warm-tinted greens instead of pure gray. - Keep text-side tokens (600+) bright enough for contrast. */ -html.dark { - --color-gray-50: #262b21; - --color-gray-75: #2d3327; - --color-gray-100: #333a2d; - --color-gray-200: #3e4636; - --color-gray-300: #545e4a; - --color-gray-400: #7d8875; - --color-gray-500: #97a28e; - --color-gray-600: #b2bca9; - --color-gray-700: #ccd3c3; - --color-gray-800: #e3e7db; - --color-gray-850: #eef1e7; - --color-gray-900: #f5f7ef; - --color-gray-950: #faf8f5; +html:not(.dark) #sidebar { + background: linear-gradient(180deg, #f6f3ee 0%, #f1ede5 100%) !important; + border-right: 1px solid #e4e0d8 !important; } -/* ---------- Accent color: co-op green ---------- */ -:root, html.dark { - --color-green-300: #7ab87a; - --color-green-400: #6ba86b; - --color-green-500: #5b8c5a; - --color-green-600: #4e7a4d; +/* Chat text: near-black, explicitly (defense in depth — Open WebUI's own + text tokens are untouched, this only backstops) */ +html:not(.dark) .markdown-prose { + color: #262b21; } -/* Primary buttons */ -.btn-primary, button.bg-black, button.bg-emerald-600, .bg-emerald-600 { +/* ---------- Dark mode (.dark class): warm greens, bright text ---------- */ +html.dark body { + background-color: #1f241b !important; +} + +html.dark #sidebar { + background: linear-gradient(180deg, #262b21 0%, #1f241b 100%) !important; + border-right: 1px solid #3e4636 !important; +} + +html.dark .markdown-prose { + color: #f0f3ea; +} + +/* ---------- Accent: co-op green (emerald token family) ---------- */ +:root { + --color-emerald-300: #7ab87a; + --color-emerald-400: #6ba86b; + --color-emerald-500: #5b8c5a; + --color-emerald-600: #4e7a4d; +} + +/* Primary buttons (submit arrow, CTAs) */ +button.bg-black, .btn-primary { background-color: #5b8c5a !important; + color: #fff !important; } -.btn-primary:hover, button.bg-emerald-600:hover { +button.bg-black:hover, .btn-primary:hover { background-color: #4e7a4d !important; } -/* Selected states, toggles, focus rings */ -.bg-emerald-500, .peer:checked ~ .bg-emerald-500 { +/* Toggles / selected states */ +.peer:checked ~ .bg-emerald-500, +.bg-emerald-500 { background-color: #6ba86b !important; } -.ring-emerald-500, .focus\:ring-emerald-500:focus, .border-emerald-500 { - --tw-ring-color: #6ba86b; - border-color: #6ba86b; -} -.text-emerald-500, .text-emerald-400, .text-emerald-300 { - color: #5b8c5a !important; -} -html.dark .text-emerald-500, html.dark .text-emerald-400, html.dark .text-emerald-300 { - color: #7ab87a !important; -} -/* ---------- Sidebar ---------- */ -#sidebar { - background: linear-gradient(180deg, #f6f3ee 0%, #f1ede5 100%) !important; - border-right: 1px solid #e4e0d8; -} -html.dark #sidebar { - background: linear-gradient(180deg, #262b21 0%, #1f241b 100%) !important; - border-right: 1px solid #3e4636; -} - -/* Sidebar: active conversation */ -#sidebar a[id^="chat-item"].active { +/* User message bubble: soft green tint (matches Open WebUI's gray-100 bubble) */ +html:not(.dark) div.bg-gray-100[class*="rounded"] { background-color: #eaf3ea !important; - border-left: 3px solid #5b8c5a; } -html.dark #sidebar a[id^="chat-item"].active { +html.dark div.bg-gray-100[class*="rounded"] { background-color: #333a2d !important; } -/* ---------- Chat area ---------- */ -/* User message bubble: soft green tint */ -.user-message .message, .chat-user .message, div[class*="user-message"] { - background-color: #eaf3ea !important; - border-radius: 14px; -} -html.dark .user-message .message, html.dark div[class*="user-message"] { - background-color: #333a2d !important; -} - -/* Assistant message: cream card */ -.assistant-message .message, div[class*="assistant-message"] { - border-radius: 14px; -} - -/* ---------- Composer ---------- */ -#chat-input, textarea[name="prompt"], .scrollbar-hidden.relative { - border-radius: 14px !important; -} -button[type="submit"].bg-black { - background-color: #5b8c5a !important; -} - -/* ---------- Model selector chip ---------- */ -button[aria-label="Select a model"], #model-selector { - border-color: #d4cfc3; -} -html.dark button[aria-label="Select a model"], html.dark #model-selector { - border-color: #545e4a; -} - /* ---------- Code blocks ---------- */ -pre, code, .language-python, .hljs { - font-family: ui-monospace, 'SF Mono', 'Cascadia Code', Menlo, monospace; -} .codeblock { border-radius: 12px !important; border: 1px solid #e4e0d8; @@ -181,8 +113,11 @@ pre, code, .language-python, .hljs { html.dark .codeblock { border-color: #3e4636; } +pre, code { + font-family: ui-monospace, 'SF Mono', 'Cascadia Code', Menlo, monospace !important; +} -/* ---------- Scrollbars: thin, green ---------- */ +/* ---------- Scrollbars ---------- */ ::-webkit-scrollbar { width: 8px; height: 8px; } ::-webkit-scrollbar-thumb { background: #c9d3c5; border-radius: 8px; } ::-webkit-scrollbar-thumb:hover { background: #6ba86b; } @@ -195,53 +130,5 @@ html.dark ::-webkit-scrollbar-thumb:hover { background: #6ba86b; } html.dark ::selection { background: #3e5a3d; } /* ---------- Links ---------- */ -a:not(.no-underline):not([class*="btn"]) { - color: #3f6e3e; /* darkened for AA contrast on cream */ -} -html.dark a:not(.no-underline):not([class*="btn"]) { - color: #8fc98f; -} - -/* ---------- Text contrast fixes ---------- */ -/* Assistant reply text: near-black in light mode regardless of remapped tokens */ -.text-gray-800, .text-gray-900, div[id^="message-"] .markdown-prose { - color: #262b21; -} -html.dark .text-gray-800, html.dark .text-gray-900, html.dark div[id^="message-"] .markdown-prose { - color: #eef1e7; -} - -/* Placeholder + secondary text: readable, not ghostly */ -::placeholder, .placeholder\:text-gray-400::placeholder { - color: #8a8578 !important; - opacity: 1 !important; -} -html.dark ::placeholder { - color: #7d8875 !important; -} -.text-gray-400 { color: #75705f !important; } -html.dark .text-gray-400 { color: #97a28e !important; } -.text-gray-500 { color: #66604f !important; } -html.dark .text-gray-500 { color: #a5b09a !important; } - -/* Input borders slightly stronger so fields are visible on cream */ -input, textarea, select { - border-color: #d4cfc3 !important; -} -html.dark input, html.dark textarea, html.dark select { - border-color: #545e4a !important; -} - -/* ---------- Modal / dropdown polish ---------- */ -.modal, .dropdown-menu, [role="menu"] { - border-radius: 14px !important; - border: 1px solid #e4e0d8 !important; -} -html.dark .modal, html.dark .dropdown-menu, html.dark [role="menu"] { - border-color: #3e4636 !important; -} - -/* ---------- Small serif-free caps for section labels (subtle) ---------- */ -.settings-tab, [data-sidebar-label] { - letter-spacing: 0.02em; -} +html:not(.dark) a { color: #3f6e3e; } +html.dark a { color: #8fc98f; }