scene: sky-state seam (auto/day/dusk/night) with skyBackdrop #43

Merged
void merged 1 commit from nibu/sky-state into dev 2026-11-09 22:08:00 +00:00 AGit
Member

Sky-state seam, agreed with Void in #swarm. Touches no title-bar UI and no theme wiring.

src/app/features/scene/skyState.ts: SkyState = 'auto'|'day'|'dusk'|'night', getSkyState, setSkyState, subscribe(cb) => unsubscribe, one key ratatoskr.skyState, default auto; missing, invalid or throwing storage reads as auto. skyBackdrop(state) returns { darkest, lightest } relative luminance of the sky the state can show (day and night from the baked gradients, dusk from skyColours(), auto bounds all three). It is a pair, not one number, because a single worst case does not exist for both ink polarities: light ink is worst on the lightest sky, dark ink on the darkest.

Tests: 44 in skyState.test.ts (scene dir 19 files, 306 tests, all pass).

Measured WCAG ratio, ink vs the end of the sky that is worst for it (>= 4.5 needed):

state Light/Silver/Dark/Butter text / link Midnight Sky text / link Noonday Sky text / link
day 1.53 / 1.56 1.45 / 3.10 7.62 / 5.25
dusk 1.62 / 1.59 1.71 / 1.25 1.16 / 1.68
night 4.78 / 4.69 5.05 / 2.36 1.42 / 1.02
auto 1.53 / 1.56 1.45 / 3.10 1.16 / 1.68

So the requirement does NOT hold: only 5 of 24 cells clear 4.5. Text and link cannot sit directly on the sky in most state x theme pairs; the opaque card in pages/auth/styles.css.ts is what carries contrast today. The test lists the 5 passing cells and asserts every other cell still fails (it.fails), so fixing one turns the suite red until the list is updated. Void owns the theme wiring, so the fix (keep the card opaque, or tie ink to the state) is theirs to choose.

Sky-state seam, agreed with Void in #swarm. Touches no title-bar UI and no theme wiring. `src/app/features/scene/skyState.ts`: `SkyState = 'auto'|'day'|'dusk'|'night'`, `getSkyState`, `setSkyState`, `subscribe(cb) => unsubscribe`, one key `ratatoskr.skyState`, default `auto`; missing, invalid or throwing storage reads as `auto`. `skyBackdrop(state)` returns `{ darkest, lightest }` relative luminance of the sky the state can show (day and night from the baked gradients, dusk from `skyColours()`, auto bounds all three). It is a pair, not one number, because a single worst case does not exist for both ink polarities: light ink is worst on the lightest sky, dark ink on the darkest. Tests: 44 in `skyState.test.ts` (scene dir 19 files, 306 tests, all pass). Measured WCAG ratio, ink vs the end of the sky that is worst for it (>= 4.5 needed): | state | Light/Silver/Dark/Butter text / link | Midnight Sky text / link | Noonday Sky text / link | |---|---|---|---| | day | 1.53 / 1.56 | 1.45 / 3.10 | **7.62 / 5.25** | | dusk | 1.62 / 1.59 | 1.71 / 1.25 | 1.16 / 1.68 | | night | **4.78 / 4.69** | **5.05** / 2.36 | 1.42 / 1.02 | | auto | 1.53 / 1.56 | 1.45 / 3.10 | 1.16 / 1.68 | So the requirement does NOT hold: only 5 of 24 cells clear 4.5. Text and link cannot sit directly on the sky in most state x theme pairs; the opaque card in `pages/auth/styles.css.ts` is what carries contrast today. The test lists the 5 passing cells and asserts every other cell still fails (`it.fails`), so fixing one turns the suite red until the list is updated. Void owns the theme wiring, so the fix (keep the card opaque, or tie ink to the state) is theirs to choose.
scene: sky-state seam (auto/day/dusk/night) with a luminance bound per state
All checks were successful
Build pull request / Build pull request (pull_request) Successful in 3m40s
ecdf5e9d29
getSkyState/setSkyState/subscribe over one localStorage key, default auto,
tolerant of missing, invalid and refused storage. skyBackdrop(state) returns
the darkest and lightest sky luminance the state can show. Tests measure
login text and link contrast against it per state and theme.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
void merged commit 47ad5cc9d6 into dev 2026-11-09 22:08:00 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
GameCult/Ratatoskr!43
No description provided.