Display v1.3: Color Horizon — cross-family design synthesis - #5
Conversation
Replace the v1.1 progress-bar layout with a full-panel gradient background, horizontal drain track, time/ends + countdown card row, and a four-state palette (normal/notice/warning/in_progress) driven by the existing notice_minutes/warn_minutes config. Countdown is right-anchored in its card via the firmware's align field (verified reliable on-device). Also fixes a stale-element overlap found during on-device verification: the draw endpoint upserts elements by id within an app rather than replacing the whole set, so switching between the upcoming and in-progress element sets without an explicit clear left old elements rendered underneath; run_once now tracks in_progress across polls and clears only at that transition.
Dated spec section with the element table, state palette table, design provenance (Codex layout structure, Gemini contrast/ legibility critique, Claude threshold synthesis), and the two on-device firmware findings (align=top_right reliability, draw upserts by id within an app). Updates the calendar README's display description and progress_window_minutes wording to match the new horizontal drain track.
run_once committed state["in_progress"] unconditionally after calling draw(), even when the draw failed to land (UNREACHABLE/REJECTED/ ERROR). That let a failed transition attempt be recorded as done, so no future poll would retry the clear+draw pair, leaving a stale element set behind indefinitely instead of just for one bounded timeout window. Now only commits when draw() returns DRAWN; clear()'s own return value stays intentionally unchecked (see the in-line comment) since gating on it too would make a persistently-failing clear() retry forever even once draws keep succeeding. Also: assert element draw order (not just id set) in the upcoming and in-progress shape tests, since z-order is load-bearing for layering and set-membership checks wouldn't catch a reorder; and use the previously-unused STATES tuple as the source of truth in the palette-completeness test instead of a hand-listed duplicate.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d1744b0aed
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| "x": 4, | ||
| "color": DIGIT_COLOR[state], | ||
| "align": "top_right", | ||
| "x": COUNTDOWN_ALIGN_X, |
There was a problem hiding this comment.
Keep two-digit-hour countdowns inside the card
When an event is at least 10 hours away—or an active event has that much time remaining—show_hours="when_non_zero" produces an HH:MM:SS countdown, but the right anchor was only verified for the 7-character H:MM:SS form. Since cd_card begins at x=36 and the measured one-digit form is already about 31 px wide, the additional digit extends the unbounded countdown into the divider/time card; this affects events within the default 12-hour lookahead. Reserve enough width for two-digit hours or constrain/format the countdown accordingly.
Useful? React with 👍 / 👎.
Operator-approved redesign synthesizing independent proposals from Codex (layout structure: state-themed backgrounds, numeral cards, full-width drain track, ENDS label) and Gemini (legibility and contrast critiques), on the measured-font baseline.
Tests: 63 passed (was 50). Spec doc updated with element/palette tables and design provenance.
🤖 Generated with Claude Code