Let a dayTintProvider send its own colour

Four tones cannot keep a twenty-stop trip's legs apart, which is most of
the point of colour-coding one. A contribution can now carry `#rrggbb`
alongside `tone`, per region or as a shorthand.

The split of control is: the plugin picks the hue, the host picks the
weight. A colour rides the same per-theme, per-region alphas as a tone,
and its OKLCH lightness is clamped into a per-theme band first, so no
contribution can hand a user a day card they can't read. The band
brackets the built-in tones rather than tightening around them, so an
ordinary colour passes through untouched and a hex equal to a tone
renders exactly like that tone. Hue and chroma are never touched - it
bounds a colour, it doesn't boost one, so a near-white grey still lands
as a faint tint.

Only `#rrggbb` survives normalization, and that is a security boundary
rather than tidying: the value ends up inside a `color-mix()` in an
inline `background`, a shorthand that takes a layer list, so a string
closing the paren early could append a `url(...)` and beacon everyone
viewing the trip.

A region gets exactly one paint instruction - what it names beats the
shorthand, a colour beats a tone at the same level - so the client never
has a tie to break. A region naming a colour the host can't use degrades
to `default` like a bogus tone already did.
This commit is contained in:
Renzo Beux
2026-07-30 15:37:20 -03:00
committed by Maurice
parent c89d2bf3a1
commit f718240ffc
12 changed files with 314 additions and 57 deletions
+19
View File
@@ -541,6 +541,19 @@ input[type="number"], input[type="time"], input[type="date"], input[type="dateti
--day-tint-header-hover: 14%;
--day-tint-activity: 6%;
/* The OKLCH lightness band a plugin's OWN colour is clamped into before it is mixed,
so "any hex" cannot mean "a day nobody can read". The band brackets the four tones
above (L 0.51–0.77) rather than tightening around them: an ordinary choice passes
through untouched, and a hex equal to a tone renders exactly like that tone. Only
the extremes move — here, a near-white that would otherwise wash out against the
sidebar's own near-white surfaces.
This bounds a colour, it does not boost one: hue and chroma are never touched, so a
near-white GREY still lands as a faint tint. That is the intended trade — the
failure this must prevent is an unreadable card, not an understated one. */
--day-tint-l-min: 0.40;
--day-tint-l-max: 0.78;
--fs-scale-title: 1;
--fs-scale-subtitle: 1;
--fs-scale-body: 1;
@@ -637,6 +650,12 @@ input[type="number"], input[type="time"], input[type="date"], input[type="dateti
--day-tint-header-hover: 20%;
--day-tint-activity: 10%;
/* Shifted up, and the reason the band is per theme at all: here the failure is a
near-BLACK tint disappearing into the dark sidebar, while a pale one reads fine.
Inherited by the mobile chips too — mobile.css sets only their alpha. */
--day-tint-l-min: 0.48;
--day-tint-l-max: 0.88;
--success: #22c55e; --success-soft: rgba(34, 197, 94, 0.15);
--danger: #ef4444; --danger-soft: rgba(239, 68, 68, 0.15);
--warning: #f59e0b; --warning-soft: rgba(245, 158, 11, 0.15);