v6.8.0: light theme

The palette lived as ~620 hex literals in inline styles plus a few hundred more in
the stylesheets, so there was no single thing to change. It is now 113 custom
properties in src/styles/theme.css, in two blocks.

src/scripts/theme-boot.js decides the theme before first paint — blocking, in <head>,
above the stylesheet, because a deferred script paints dark first and corrects itself.
It stores the mode ('system' | 'light' | 'dark'), never the colour it resolved to, and
stamps data-theme so an explicit choice can beat the media query. The switcher in the
header is a view onto it.

A filled accent stays the brand colour in both themes — the ink on it is near-black
either way — while an accent used as text darkens to clear 4.5:1 on white. A colour
reaches a fill by four routes (a style property, a constant, a helper argument, an SVG
source string), and tests/theme-switching.test.mjs covers all four.

The dark theme is unchanged: every colour declaration the previous build produced comes
out of this one identically once the properties are resolved.

Also: the roadmap drops its status chips on mobile, and Roadmap.jsx no longer splits a
colour with parseInt at runtime, which a var() reference cannot survive.
This commit is contained in:
lockbitchat
2026-09-04 17:38:41 -04:00
parent 1c153b290a
commit 9e63cf65a4
109 changed files with 4320 additions and 1910 deletions
+6 -3
View File
@@ -162,9 +162,12 @@ function withTwoSessions() {
{
assert.equal(monoInitials('work laptop'), 'WL');
assert.equal(monoInitials('atlas'), 'AT');
assert.equal(statusDot('verified'), '#3ecf8e');
assert.equal(statusDot('connecting'), '#e3b341');
assert.equal(statusDot('disconnected'), '#e5727a');
// Custom properties rather than literals since the app gained a light theme: a dot
// is a mark, so it takes the -solid form of the accent, which is the brand colour in
// both themes. What is being asserted is unchanged — which state gets which colour.
assert.equal(statusDot('verified'), 'var(--sb-green-solid)');
assert.equal(statusDot('connecting'), 'var(--sb-yellow-2-solid)');
assert.equal(statusDot('disconnected'), 'var(--sb-red-solid)');
const entry = createSessionEntry({ id: 'a', peerLabel: 'work laptop' });
entry.unreadCount = 3;