Planner Standalone Sunlight Pill Design
Date: 2026-07-16 Status: Proposed for implementation
1. Goal
Replace Planner table-integrated sunlight indicators with a standalone sunlight object: - Desktop/tablet: a long vertical pill placed immediately to the left of the Segment/Checkpoint table - Mobile: a horizontal mini-strip placed above the Segment/Checkpoint table
The pill is visual-only (no text labels on the pill itself) and uses blended color transitions across phase boundaries.
2. User-Approved Decisions
- Placement: standalone, left of Segment/Checkpoint table (not part of table columns)
- Height behavior (desktop/tablet): matches rendered table body height
- Label density: no labels on the pill itself (color-only)
- Mobile behavior: transform into horizontal mini-strip above table
3. UX Requirements
3.1 Desktop/Tablet
- Pill appears only when sunlight data is available and Segment/Checkpoint view is active.
- Pill is visually separate from table cells and borders.
- Pill spans table body height so phase progression aligns with table progression.
- Coloring smoothly blends between adjacent phase colors (no hard bands).
3.2 Mobile
- Pill becomes a compact horizontal strip above the table container.
- Strip uses the same phase progression and blended transitions.
- Strip should not force horizontal overflow or impair table usability.
3.4 Color Progression and Blending (Explicit)
- The pill must visually communicate this ordered progression when phases are present:
- Night -> Sunrise (pre-dawn twilight) -> Day -> Sunset (post-dusk twilight) -> Night
- Sunrise and Sunset sections should use twilight tones distinct from full Night and full Day.
- Transitions between adjacent phase sections must be blended (mixed/shaded), not hard color breaks.
- Blending must be visible in both orientations:
- Desktop/tablet vertical pill
- Mobile horizontal strip
3.3 Fallback Behavior
- If sunlight payload is missing/empty, hide standalone pill entirely.
- Existing summary card behavior remains unchanged.
4. Technical Design
4.1 DOM Structure Changes
In Planner segment/checkpoint area, wrap current table container in a layout container:
- sc-layout-shell (new): two-column layout on desktop/tablet
- sc-sunlight-pill-container (new): holds standalone pill object
- existing sc-table-container remains table host
On mobile breakpoints:
- sc-layout-shell collapses to one column
- sc-sunlight-pill-container moves visually above table and renders horizontal strip style
No table header or body columns for sunlight are retained.
4.2 Rendering Inputs
Use existing plan data already produced in Planner render flow:
- racePlan rows from current rendering logic
- currentPlan.sunlight.checkpoint_phases and start phase data
Construct a normalized ordered phase sequence aligned to displayed row progression: - checkpoint rows use row sunlight phase directly - segment rows inherit nearest checkpoint phase (same current behavior intent) - unknown/null phase falls back to day
4.3 Gradient Construction
For each row index in sequence, compute a blended stop segment using: - previous phase color - current phase color - next phase color
Blend rules: - Use weighted interpolation within each row slice so color gently shifts at boundaries. - Avoid abrupt transitions by reserving transition spans at both the start and end of each slice. - Preserve phase identity in the center of each slice (current phase remains dominant mid-slice).
Build a single CSS linear-gradient string from all row slices:
- Desktop/tablet orientation: 180deg
- Mobile orientation: 90deg
Color tokens:
- Night: var(--sun-night, #0f172a)
- Twilight: var(--sun-twilight, #64748b)
- Day: var(--sun-day, #facc15)
Phase-to-color mapping:
- night -> Night color
- pre_dawn_twilight -> Twilight color (sunrise section)
- day -> Day color
- post_dusk_twilight -> Twilight color (sunset section)
4.4 Height and Resize Sync
After Segment/Checkpoint table render completes:
- measure sc-segments-tbody rendered height
- set pill height to measured value (with sensible minimum)
Also update on: - table re-renders - tab changes affecting Segment/Checkpoint visibility - window resize (debounced)
4.5 Scope Boundaries
- Remove sunlight rail table column and related table-cell injection.
- Keep summary sunlight card and classic table behavior unchanged unless explicitly requested.
- Keep race-day page untouched.
5. Accessibility
- Standalone pill is decorative visual context, not essential text content.
- Add
aria-hidden="true"to decorative gradient element. - Keep semantic table structure clean (no sunlight-only utility column).
6. Error Handling
- Missing DOM nodes: fail silently for pill rendering (no console noise in production path).
- Missing sunlight data: hide pill container.
- Zero/very small table height: apply minimum visual height and safe gradient fallback.
7. Verification Plan
7.1 Functional Checks
- Calculate Plan with valid route/date/start time:
- summary card appears
- standalone vertical pill appears left of Segment/Checkpoint table
- Toggle table view tabs:
- pill only appears with Segment/Checkpoint view
- Mobile viewport:
- pill becomes horizontal strip above table
- Missing sunlight payload:
- no pill rendered, no layout break
7.2 Visual Checks
- Smooth transitions between night/twilight/day/twilight/night
- Ordered visual read should be interpretable as Night -> Sunrise -> Day -> Sunset -> Night
- Pill height tracks table body height after edits/recalculations
- No overlap/clipping with table container
7.3 Regression Checks
- Segment/Checkpoint click interactions unchanged
- Classic table rendering unchanged
- Race Day sunlight UI unchanged
8. Files Expected to Change
templates/index.htmlstatic/js/app.jsstatic/css/style.css
9. Non-Goals
- No new backend API fields
- No modification to sunlight calculation model
- No added labels/legend text on the standalone pill
- No changes to race-day screen