ui: light theme by default (dark is opt-in)
Swaps the role of `:root` (now light) and the data-theme attribute (now `[data-theme="dark"]`) in cassandra.css, flips the localStorage fallback from 'dark' to 'light' in base/login/verify templates, and updates the theme-toggle label and the branding-consistency test selectors to match. Existing users with cassandra.theme=dark in localStorage still see dark — their explicit preference wins. Only first-time visitors and users with no stored preference shift to light. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
9e058144ec
commit
89632e9937
6 changed files with 42 additions and 39 deletions
|
|
@ -16,10 +16,11 @@ detection test (`tests/test_branding_consistency.py`) parses
|
|||
`cassandra.css` and asserts every variable matches. Update both or
|
||||
neither.
|
||||
|
||||
The light theme is the *default* in emails — mail clients can't read
|
||||
`localStorage`, so we can't replicate the dashboard's user-toggled
|
||||
theme. Clients that honour `prefers-color-scheme` get the dark palette
|
||||
via media query.
|
||||
The light theme is the *default* everywhere — dashboard `:root` block,
|
||||
auth pages, and emails. Dark is opt-in via the in-app toggle (which
|
||||
sets `data-theme="dark"` on `<html>` and persists in `localStorage`).
|
||||
Mail clients that honour `prefers-color-scheme: dark` get the dark
|
||||
palette via media query.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
|
|
|
|||
|
|
@ -2,23 +2,7 @@
|
|||
* Mono for data, headers, terminal feel; sans for prose surfaces (log + chat). */
|
||||
|
||||
:root {
|
||||
/* Dark theme (default) */
|
||||
--bg: #0a0e14;
|
||||
--surface: #11151c;
|
||||
--surface-2: #161b25;
|
||||
--border: #2a3142;
|
||||
--text: #d4dae8; /* lifted from #c0caf5 for readability */
|
||||
--muted: #8189a1; /* lifted from #565f89 — was unreadably dim */
|
||||
--dim: #565f89;
|
||||
--accent: #00d9ff;
|
||||
--positive: #50fa7b;
|
||||
--negative: #ff5b5b;
|
||||
--alert: #ff8a4a;
|
||||
--warning: #f1fa8c;
|
||||
--user-bubble-bg: rgba(0, 217, 255, 0.08);
|
||||
}
|
||||
|
||||
[data-theme="light"] {
|
||||
/* Light theme (default) */
|
||||
--bg: #f5f3ec; /* warm off-white, easier on the eyes than pure white */
|
||||
--surface: #ffffff;
|
||||
--surface-2: #efece3;
|
||||
|
|
@ -34,6 +18,22 @@
|
|||
--user-bubble-bg: rgba(14, 116, 144, 0.07);
|
||||
}
|
||||
|
||||
[data-theme="dark"] {
|
||||
--bg: #0a0e14;
|
||||
--surface: #11151c;
|
||||
--surface-2: #161b25;
|
||||
--border: #2a3142;
|
||||
--text: #d4dae8; /* lifted from #c0caf5 for readability */
|
||||
--muted: #8189a1; /* lifted from #565f89 — was unreadably dim */
|
||||
--dim: #565f89;
|
||||
--accent: #00d9ff;
|
||||
--positive: #50fa7b;
|
||||
--negative: #ff5b5b;
|
||||
--alert: #ff8a4a;
|
||||
--warning: #f1fa8c;
|
||||
--user-bubble-bg: rgba(0, 217, 255, 0.08);
|
||||
}
|
||||
|
||||
/* Font stacks. Mono for terminal feel; sans for reading. */
|
||||
:root {
|
||||
--font-mono: 'JetBrains Mono', 'IBM Plex Mono', 'Fira Code', ui-monospace, monospace;
|
||||
|
|
@ -104,8 +104,8 @@ a:hover { text-decoration: underline; }
|
|||
text-transform: lowercase;
|
||||
}
|
||||
.theme-toggle:hover { color: var(--accent); border-color: var(--accent); }
|
||||
.theme-toggle__label::before { content: "◐ dark"; }
|
||||
[data-theme="light"] .theme-toggle__label::before { content: "◐ light"; }
|
||||
.theme-toggle__label::before { content: "◐ light"; }
|
||||
[data-theme="dark"] .theme-toggle__label::before { content: "◐ dark"; }
|
||||
|
||||
/* Tone toggle (segmented control: Novice | Intermediate) */
|
||||
.tone-toggle {
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@
|
|||
<script>
|
||||
(function() {
|
||||
try {
|
||||
var t = localStorage.getItem('cassandra.theme') || 'dark';
|
||||
var t = localStorage.getItem('cassandra.theme') || 'light';
|
||||
document.documentElement.dataset.theme = t;
|
||||
} catch (e) { document.documentElement.dataset.theme = 'dark'; }
|
||||
} catch (e) { document.documentElement.dataset.theme = 'light'; }
|
||||
})();
|
||||
</script>
|
||||
<link rel="stylesheet" href="{{ url_for('static', path='/css/cassandra.css') }}" />
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@
|
|||
<title>{{ BRAND_NAME }} · Sign in</title>
|
||||
<script>
|
||||
(function() {
|
||||
try { document.documentElement.dataset.theme = localStorage.getItem('cassandra.theme') || 'dark'; }
|
||||
catch (e) { document.documentElement.dataset.theme = 'dark'; }
|
||||
try { document.documentElement.dataset.theme = localStorage.getItem('cassandra.theme') || 'light'; }
|
||||
catch (e) { document.documentElement.dataset.theme = 'light'; }
|
||||
})();
|
||||
</script>
|
||||
<link rel="stylesheet" href="{{ url_for('static', path='/css/cassandra.css') }}" />
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@
|
|||
<title>{{ BRAND_NAME }} · Verify email</title>
|
||||
<script>
|
||||
(function() {
|
||||
try { document.documentElement.dataset.theme = localStorage.getItem('cassandra.theme') || 'dark'; }
|
||||
catch (e) { document.documentElement.dataset.theme = 'dark'; }
|
||||
try { document.documentElement.dataset.theme = localStorage.getItem('cassandra.theme') || 'light'; }
|
||||
catch (e) { document.documentElement.dataset.theme = 'light'; }
|
||||
})();
|
||||
</script>
|
||||
<link rel="stylesheet" href="{{ url_for('static', path='/css/cassandra.css') }}" />
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue