Owner directives (verbatim): "show no upcoming appointments" when empty /
"days and times highlighted" when there are events; "properly stylize the
calendar to fit with each theme correctly"; "relatively small widget basically
about the size of the weather widget".
r1 judge blockers fixed:
- .mytheme literal rule replaced by UNIVERSAL theme handling: theme.js tags
<html> with the class `light-bg` (luminance-derived) for builtin AND user
themes; chip colors derive via color-mix toward white (dark surfaces, 80%)
or black (light surfaces, 28%) — no per-slug rules, arbitrarily-named user
themes covered. Objective WCAG contrast test computes the ratio for ALL 10
builtin themes from themes.css values: worst case 4.60:1 (ocean), all
>= 4.5:1.
- Event query now FOLLOWS THE VISIBLE MONTH: windowFor(viewMonth) =
[prev-month 1st .. current+2mo end]; loaded-range union with refetch when
grid navigation leaves the loaded window (navigate() -> fetchCalendar).
Contract test navigates twice and asserts the refetch window extends past
the initial 60 days.
- [data-theme] comment corrected (implementation uses html.light-bg class).
Also: smoke harness now at dashcaddy-api/.dc168-smoke.js (asserts empty chip
string, events chip, grid cell counts); contract suite 4 tests + 9 ns suite
= 13 calendar tests green; eslint 0 errors.
extractCalendarsAndEvents required a namespace prefix on <response>; Radicale
emits bare <response> (default DAV ns) so every entry was silently dropped —
REPORT 200, ok:true, 0 events, no error. Prefix is now optional in the split
and detection regexes.
Tests: 9 in the ns suite (extraction incl. mixed doc; empty multistatus;
namespace-aware fixture parse; undeclared element+attribute prefix rejection;
both quote styles; positive declared-attr case). Calendar-related suites: 52.
eslint clean.