rastrillo / fiesta Public

Clone
git clone https://amadan.net/rastrillo/fiesta

Plain git — no account needed to clone.

Download

Download this file

1/* day — rastrillo's default theme: an everyday blue on white and grey.
2 Structure lives in tokens.css; this file is colour, type and shape.
3 rastrillo new writes it once as static/theme.css.
4
5 The look: professional, with a point of view. Near-greyscale neutrals
6 with hairline borders, one cobalt that means "this does something",
7 crisp 6px and 4px corners, and natural depth: light comes from above,
8 cards rest on the page, controls press in. Status keeps the
9 conventional green, amber and red, so a pill is never mistaken for a
10 link.
11
12 ── One block, both schemes ───────────────────────────────────────────
13 Every token is declared once, as light-dark(<light>, <dark>), under a
14 single :root that sets color-scheme: light dark. The browser picks the
15 half that matches the resolved scheme, so there is no second copy of
16 the palette to keep in sync and no way to author dark half-done. The
17 two rules at the bottom are the whole toggle: setting color-scheme on
18 :root[data-theme=…] re-resolves every light-dark() in the file at
19 once, in both directions, which is why an explicit choice beats the OS
20 without restating a single colour.
21
22 Tokens with one value in both schemes — the font stack, the radii —
23 are written plain, because light-dark(x, x) says nothing twice.
24
25 light-dark() is a colour function: it may only stand where a <color>
26 is expected. So a shadow token wraps its colour in it and writes the
27 geometry once, outside the call — `0 8px 24px light-dark(a, b)`, never
28 `light-dark(0 8px 24px a, …)`, which no browser would accept as a
29 box-shadow.
30
31 ── The shape axis ────────────────────────────────────────────────────
32 Radius and shadow are the theme's now, not tokens.css's: a theme that
33 can only change colour cannot change how an app feels. day is crisp
34 and lit from above: 6px cards, 4px controls, a short contact shadow
35 where an object meets the page and soft ambient light around it, so
36 things rest on the page rather than float.
37
38 ── WCAG 2.2 AA, measured ─────────────────────────────────────────────
39 Normal text needs 4.5:1; large text and UI component boundaries need
40 3:1. Every pair below was computed from these exact hex values, in
41 both schemes. If you change a token, recompute its rows.
42
43 LIGHT ratio requirement
44 --rst-text on --rst-surface 17.72 4.5:1 text
45 --rst-text on --rst-bg 17.13 4.5:1 text
46 --rst-text on --rst-surface-2 15.99 4.5:1 text
47 --rst-text on --rst-accent-soft 15.65 4.5:1 text
48 --rst-text-muted on --rst-surface 7.72 4.5:1 text
49 --rst-text-muted on --rst-bg 7.46 4.5:1 text
50 --rst-text-muted on --rst-surface-2 6.97 4.5:1 text
51 --rst-text-muted on --rst-accent-soft 6.82 4.5:1 text
52 --rst-text-faint on --rst-surface 5.27 4.5:1 text
53 --rst-text-faint on --rst-bg 5.10 4.5:1 text
54 --rst-text-faint on --rst-surface-2 4.76 4.5:1 text
55 --rst-text-faint on --rst-accent-soft 4.65 4.5:1 text
56 --rst-accent on --rst-surface 6.25 4.5:1 text + focus ring
57 --rst-accent on --rst-bg 6.04 4.5:1 text + focus ring
58 --rst-accent on --rst-surface-2 5.64 4.5:1 text
59 --rst-accent on --rst-accent-soft 5.52 4.5:1 text
60 --rst-on-accent on --rst-accent 6.25 4.5:1 label where the accent itself fills
61 --rst-on-accent on --rst-accent-strong 8.47 4.5:1 the same, hover
62 --rst-line-strong on --rst-surface 3.60 3:1 control border
63 --rst-line-strong on --rst-bg 3.48 3:1 control border
64 --rst-line-strong on --rst-surface-2 3.25 3:1 control border
65 pill neutral fg on its own tint 9.02 4.5:1 text
66 pill positive fg on its own tint 6.49 4.5:1 text
67 pill warning fg on its own tint 6.15 4.5:1 text
68 pill negative fg on its own tint 5.30 4.5:1 text
69 --rst-tone-positive-fg on --rst-surface 7.13 4.5:1 a stat's rising delta
70 --rst-tone-negative-fg on --rst-surface 6.47 4.5:1 a stat's falling delta
71 --rst-on-accent on negative fg (fill) 6.47 4.5:1 danger label, old tokens.css
72 --rst-on-accent-fill on --rst-accent-fill 5.94 4.5:1 primary button label
73 --rst-on-accent-fill on --rst-accent-fill-hover 7.11 4.5:1 primary button label, hover
74 --rst-on-danger-fill on --rst-danger-fill 5.46 4.5:1 danger button label
75 --rst-on-danger-fill-hover on --rst-danger-fill-hover 6.52 4.5:1 danger button label, hover
76 --rst-text on --rst-row-tint-hover 16.54 4.5:1 list-row-action text, hovered
77 --rst-text on --rst-row-tint-press 15.65 4.5:1 list-row-action text, pressed
78 --rst-control-text-hover on --rst-control-face-hover 16.67 4.5:1 plain button label, hover
79 --rst-text-muted on --rst-control-face-hover 7.26 4.5:1 muted label, hovered plain face
80 --rst-text on --rst-tint-hover 16.54 4.5:1 row text, hovered
81 --rst-text on --rst-tint-press 15.65 4.5:1 row text, pressed
82 --rst-text-muted on --rst-tint-hover 7.21 4.5:1 muted cell, hovered row
83 --rst-text-muted on --rst-tint-press 6.82 4.5:1 muted cell, pressed row
84 --rst-text-faint on --rst-tint-hover 4.92 4.5:1 faint cell, hovered row
85 --rst-text-faint on --rst-tint-press 4.66 4.5:1 faint cell, pressed row
86 --rst-accent on --rst-tint-hover 5.83 4.5:1 a link on a hovered row
87 --rst-nav-current-fg on --rst-nav-current-bg 17.72 4.5:1 the current nav item
88 --rst-track-off on --rst-surface 3.41 3:1 switch off track
89 --rst-track-off on --rst-bg 3.30 3:1 switch off track on the page
90 --rst-knob-shade on --rst-track-off 3.07 3:1 knob on the off track
91 --rst-knob-shade on --rst-accent-fill 5.34 3:1 knob on the on track
92
93 DARK ratio requirement
94 --rst-text on --rst-surface 15.63 4.5:1 text
95 --rst-text on --rst-bg 16.64 4.5:1 text
96 --rst-text on --rst-surface-2 15.03 4.5:1 text
97 --rst-text on --rst-accent-soft 13.02 4.5:1 text
98 --rst-text-muted on --rst-surface 7.12 4.5:1 text
99 --rst-text-muted on --rst-bg 7.59 4.5:1 text
100 --rst-text-muted on --rst-surface-2 6.85 4.5:1 text
101 --rst-text-muted on --rst-accent-soft 5.94 4.5:1 text
102 --rst-text-faint on --rst-surface 5.48 4.5:1 text
103 --rst-text-faint on --rst-bg 5.84 4.5:1 text
104 --rst-text-faint on --rst-surface-2 5.27 4.5:1 text
105 --rst-text-faint on --rst-accent-soft 4.57 4.5:1 text
106 --rst-accent on --rst-surface 7.34 4.5:1 text + focus ring
107 --rst-accent on --rst-bg 7.81 4.5:1 text + focus ring
108 --rst-accent on --rst-surface-2 7.06 4.5:1 text
109 --rst-accent on --rst-accent-soft 6.11 4.5:1 text
110 --rst-on-accent on --rst-accent 7.81 4.5:1 label where the accent itself fills
111 --rst-on-accent on --rst-accent-strong 10.62 4.5:1 the same, hover
112 --rst-line-strong on --rst-surface 3.86 3:1 control border
113 --rst-line-strong on --rst-bg 4.12 3:1 control border
114 --rst-line-strong on --rst-surface-2 3.72 3:1 control border
115 pill neutral fg on its own tint 8.44 4.5:1 text
116 pill positive fg on its own tint 10.18 4.5:1 text
117 pill warning fg on its own tint 9.62 4.5:1 text
118 pill negative fg on its own tint 7.85 4.5:1 text
119 --rst-tone-positive-fg on --rst-surface 11.88 4.5:1 a stat's rising delta
120 --rst-tone-negative-fg on --rst-surface 8.77 4.5:1 a stat's falling delta
121 --rst-on-accent on negative fg (fill) 9.34 4.5:1 danger label, old tokens.css
122 --rst-on-accent-fill on --rst-accent-fill 5.26 4.5:1 primary button label
123 --rst-on-accent-fill on --rst-accent-fill-hover 6.32 4.5:1 primary button label, hover
124 --rst-on-danger-fill on --rst-danger-fill 5.46 4.5:1 danger button label
125 --rst-on-danger-fill-hover on --rst-danger-fill-hover 6.52 4.5:1 danger button label, hover
126 --rst-text on --rst-row-tint-hover 14.59 4.5:1 list-row-action text, hovered
127 --rst-text on --rst-row-tint-press 14.10 4.5:1 list-row-action text, pressed
128 --rst-control-text-hover on --rst-control-face-hover 14.43 4.5:1 plain button label, hover
129 --rst-text-muted on --rst-control-face-hover 6.58 4.5:1 muted label, hovered plain face
130 --rst-text on --rst-tint-hover 14.59 4.5:1 row text, hovered
131 --rst-text on --rst-tint-press 14.10 4.5:1 row text, pressed
132 --rst-text-muted on --rst-tint-hover 6.65 4.5:1 muted cell, hovered row
133 --rst-text-muted on --rst-tint-press 6.43 4.5:1 muted cell, pressed row
134 --rst-text-faint on --rst-tint-hover 5.12 4.5:1 faint cell, hovered row
135 --rst-text-faint on --rst-tint-press 4.95 4.5:1 faint cell, pressed row
136 --rst-accent on --rst-tint-hover 6.85 4.5:1 a link on a hovered row
137 --rst-nav-current-fg on --rst-nav-current-bg 15.63 4.5:1 the current nav item
138 --rst-track-off on --rst-surface 3.86 3:1 switch off track
139 --rst-track-off on --rst-bg 4.12 3:1 switch off track on the page
140 --rst-knob-shade on --rst-track-off 3.50 3:1 knob on the off track
141 --rst-knob-shade on --rst-accent-fill 3.90 3:1 knob on the on track
142
143 The tightest pair is --rst-knob-shade on --rst-track-off, 3.07:1 in
144 light against a 3:1 floor. --rst-control-border is below 3:1 by
145 design; see its comment. Put a token on a surface not listed above
146 and you are guessing; recompute first.
147
148 --rst-control-border is the one pair kept below the floor: 1.49:1 in
149 light and 1.56:1 in dark against --rst-surface. The label identifies
150 the button, so the boundary is decoration under WCAG 1.4.11 and
151 carries no 3:1 floor. Do not argue it up.
152
153 --rst-line is a hairline divider between rows, not a control border or
154 a meaningful graphic, so 1.4.11's 3:1 does not apply to it. Control
155 borders use --rst-line-strong, which does clear 3:1.
156
157 --rst-header-rule is not in the table either, and deliberately so
158 (design doc §6-v2.2): the page header's rule is decoration, not
159 structure — the heading's size, weight and spacing carry the
160 structure — so no contrast floor applies to it and it is not in
161 ui/contrast_test.go's pair table. Do not argue it up to 3:1.
162
163 Pagination chips are the one deliberate exception: they are bordered
164 with --rst-line rather than --rst-line-strong, because a page strip
165 ringed in hard outlines shouts louder than the list it belongs to.
166 1.4.11 is satisfied without that border — each chip's meaning is
167 carried by its text label at 4.5:1 or better, and the current page
168 adds a filled background, a heavier weight and aria-current on top.
169
170 --rst-shadow-pop, --rst-shadow-knob, --rst-shadow-knob-hover,
171 --rst-shadow-lift and
172 --rst-overlay are not in the table: they paint a translucent shadow or
173 scrim over whatever sits underneath, not text over a fixed
174 background, so a contrast ratio does not apply. The scrim deepens in
175 dark, matching --rst-shadow-pop's own jump: black reads lighter
176 against a dark backdrop, so the overlay needs more alpha to still
177 read as a dimming layer.
178 ──────────────────────────────────────────────────────────────────── */
179
180:root {
181 color-scheme: light dark;
182
183 /* Font */
184 --rst-font: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
185
186 /* Shape */
187 --rst-radius: 6px;
188 --rst-radius-sm: 4px;
189 --rst-radius-pill: 999px;
190
191 /* Surfaces and lines */
192 --rst-bg: light-dark(#fbfbfc, #0c0d0f);
193 --rst-surface: light-dark(#ffffff, #141518);
194 --rst-surface-2: light-dark(#f3f3f5, #18191d);
195 --rst-line: light-dark(#e6e6ea, #26282e);
196 /* Light's strong line is four steps darker than the mockup's #8a8a95:
197 the sign-in card's border has to clear 3:1 against the stage art
198 drawn over the page, and #8a8a95 measured 2.90:1 there. */
199 --rst-line-strong: light-dark(#868691, #71737c);
200 --rst-header-rule: var(--rst-line);
201
202 /* Text */
203 --rst-text: light-dark(#18181b, #ededf0);
204 --rst-text-muted: light-dark(#52525c, #a1a1aa);
205 --rst-text-faint: light-dark(#6b6b75, #8c8c96);
206
207 /* Accent. One colour an app sets; the rest follow it. The link hover,
208 the tints, the halo, the plain sheen and the rim fold the accent
209 into black, white, a surface or transparent with color-mix(in
210 srgb), every share a literal percentage: calc(var()) in a
211 color-mix() percentage invalidates the whole declaration in Safari
212 (A4). The four fills and the soft ground take the accent's hue at
213 day's own lightness, because in dark the accent is a light text
214 blue and no mix of it with black or a surface reaches a deep button
215 fill. Those five are declared here as day's cobalt and derived in
216 the @supports block after this one, which an engine without
217 relative colour skips. The fallback inside each var() applies only
218 when --rst-accent is unset or set to initial: a custom property
219 accepts any tokens, so a malformed override is valid as far as
220 var() can tell and blanks every derived colour. With the default
221 accent each derived value lands within two units per channel of the
222 hex it replaced, and the contrast table above is computed from the
223 resolved values. */
224 --rst-accent: light-dark(#1f56d6, #7aa2ff);
225 --rst-accent-strong: light-dark(color-mix(in srgb, var(--rst-accent, #1f56d6) 80%, #000000), color-mix(in srgb, var(--rst-accent, #7aa2ff) 68.5%, #ffffff));
226 --rst-accent-soft: light-dark(#ecf1ff, #16234a);
227 --rst-on-accent: light-dark(#ffffff, #0c0d0f);
228
229 /* Status tones */
230 --rst-tone-neutral-fg: light-dark(#374151, #c3c9d1);
231 --rst-tone-neutral-bg: light-dark(#eef0f2, #262c34);
232 --rst-tone-positive-fg: light-dark(#166534, #6ee7a8);
233 --rst-tone-positive-bg: light-dark(#dcfce7, #10281c);
234 --rst-tone-warning-fg: light-dark(#854d0e, #f0c46a);
235 --rst-tone-warning-bg: light-dark(#fef3c7, #2c2110);
236 --rst-tone-negative-fg: light-dark(#b91c1c, #f79aa0);
237 --rst-tone-negative-bg: light-dark(#fee2e2, #331819);
238
239 /* Depth */
240 --rst-shadow-pop: 0 2px 4px light-dark(rgba(16, 24, 40, 0.06), rgba(0, 0, 0, 0.35)), 0 8px 16px -4px light-dark(rgba(16, 24, 40, 0.1), rgba(0, 0, 0, 0.5));
241 /* The knob's dome: a soft drop and a hairline ring, and hovered a
242 longer drop, so the knob lifts as a button does. */
243 --rst-shadow-knob: 0 1px 2px light-dark(rgba(16, 24, 40, 0.22), rgba(0, 0, 0, 0.5)), 0 0 0 0.5px light-dark(rgba(16, 24, 40, 0.08), rgba(0, 0, 0, 0.3));
244 --rst-shadow-knob-hover: 0 1.5px 3px light-dark(rgba(16, 24, 40, 0.26), rgba(0, 0, 0, 0.58)), 0 0 0 0.5px light-dark(rgba(16, 24, 40, 0.08), rgba(0, 0, 0, 0.3));
245 --rst-shadow-lift: 0 1px 2px light-dark(rgba(16, 24, 40, 0.08), rgba(0, 0, 0, 0.3));
246 --rst-overlay: light-dark(rgba(0, 0, 0, 0.45), rgba(0, 0, 0, 0.6));
247
248 /* Filled controls have a fill, a hover fill and an edge of their own,
249 so a hover is never a filter and a dark label is never put on a
250 light accent. */
251 --rst-accent-fill: light-dark(#2257df, #2f61e8);
252 --rst-accent-fill-hover: light-dark(#1d4dc8, #2956d0);
253 --rst-accent-fill-edge: light-dark(#153ca0, #1f43a6);
254 --rst-accent-fill-edge-hover: light-dark(#12358f, #1a3b95);
255 --rst-on-accent-fill: #ffffff;
256 --rst-danger-fill: light-dark(#c62f2f, #c43232);
257 --rst-danger-fill-hover: light-dark(#b12929, #af2c2c);
258 --rst-danger-fill-edge: light-dark(#8d1f1f, #8c2121);
259 --rst-danger-fill-edge-hover: light-dark(#7e1a1a, #7d1d1d);
260 --rst-on-danger-fill: #ffffff;
261 --rst-on-danger-fill-hover: #ffffff;
262 --rst-danger-hover-filter: none;
263
264 /* Plain buttons and menu summaries: the face at rest, on hover and,
265 for a ghost button, pressed; the border, which is softer than
266 --rst-line-strong on purpose; and the hover border and label. The
267 label identifies the button, so the boundary is decoration under
268 WCAG 1.4.11 and carries no 3:1 floor. Do not argue it up. */
269 --rst-control-face: light-dark(#ffffff, #141518);
270 --rst-control-face-hover: light-dark(#f7f8fa, #1b1d22);
271 --rst-control-face-press: light-dark(#e6e9ee, #202329);
272 --rst-control-border: light-dark(#d0d4dc, #343843);
273 --rst-control-border-hover: light-dark(#8a8a95, #71737c);
274 --rst-control-text-hover: light-dark(#18181b, #ededf0);
275 --rst-ghost-edge: transparent;
276 --rst-ghost-face-hover: light-dark(#f3f3f5, #18191d);
277 --rst-ghost-edge-hover: transparent;
278 --rst-summary-face: light-dark(#ffffff, #141518);
279 --rst-summary-face-hover: light-dark(#f7f8fa, #1b1d22);
280 --rst-summary-edge: light-dark(#d0d4dc, #343843);
281 --rst-summary-edge-hover: light-dark(#8a8a95, #71737c);
282 /* A menu summary's corner: the small radius, as a token of its own,
283 because the focus ring follows the corner and a flat theme keeps
284 the square ring it had. */
285 --rst-summary-radius: var(--rst-radius-sm);
286
287 /* The light from above. A highlight along a raised edge, a short
288 contact shadow where an object meets the page, soft ambient light
289 around it, the fraction a filled face shades by, and how far a
290 pressed button drops. Set every one to transparent, 0 and 0px for
291 a flat theme. */
292 --rst-depth-hl: light-dark(rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.06));
293 --rst-depth-contact: light-dark(rgba(16, 24, 40, 0.1), rgba(0, 0, 0, 0.5));
294 --rst-depth-ambient: light-dark(rgba(16, 24, 40, 0.06), rgba(0, 0, 0, 0.35));
295 --rst-depth-face: 0.04;
296 --rst-press-drop: 1px;
297
298 /* The switch: a near-white knob in both schemes, so in dark it reads
299 as the thing you move rather than a hole; and the off track, a grey
300 dark enough to clear 3:1 against the surface and light enough for the
301 knob to clear 3:1 against it. */
302 --rst-knob: #ffffff;
303 --rst-knob-shade: light-dark(#f1f3f6, #d9dee8);
304 --rst-track-off: light-dark(#8a8a95, #71737c);
305 /* The switch's size: a 40x23 track with a 19px knob under a fine
306 pointer, 51x31 with a 27px knob on a touch screen (the iOS size).
307 The knob is inset 2px, so each height is its knob and 4. */
308 --rst-switch-w: 40px;
309 --rst-switch-h: 23px;
310 --rst-switch-knob: 19px;
311 --rst-switch-touch-w: 51px;
312 --rst-switch-touch-h: 31px;
313 --rst-switch-touch-knob: 27px;
314
315 /* Rows, menu items and sidebar items on hover and pressed: the accent
316 folded into the surface at 4.5% and 8.5% in light, and in dark into
317 the page at 10% and into black at 19%, the shares that land on the
318 hexes the design was measured with. Focus adds the accent as the
319 edge and the accent at 22% as the halo. */
320 --rst-tint-hover: light-dark(color-mix(in srgb, var(--rst-accent, #1f56d6) 4.5%, var(--rst-surface)), color-mix(in srgb, var(--rst-accent, #7aa2ff) 10%, var(--rst-bg)));
321 --rst-tint-press: light-dark(color-mix(in srgb, var(--rst-accent, #1f56d6) 8.5%, var(--rst-surface)), color-mix(in srgb, var(--rst-accent, #7aa2ff) 19%, #000000));
322 --rst-tint-tap: var(--rst-tint-press);
323 /* The topbar's phone card, hovered: the hover tint again, as a token
324 of its own, because the card had no hover before and a flat theme
325 keeps none. */
326 --rst-tint-card-hover: var(--rst-tint-hover);
327 /* A media tile, hovered and pressed: the hover and press tints
328 again, as a pair of its own, because the tile had no hover before
329 and a flat theme keeps its surface in both states. */
330 --rst-tint-tile-hover: var(--rst-tint-hover);
331 --rst-tint-tile-press: var(--rst-tint-press);
332 /* A menu group's summary, hovered: the hover tint again, as a token
333 of its own, because the summary had no hover before and a flat
334 theme keeps none. */
335 --rst-tint-group-hover: var(--rst-tint-hover);
336 --rst-row-tint-hover: var(--rst-tint-hover);
337 --rst-row-tint-press: var(--rst-tint-press);
338 --rst-focus-edge: var(--rst-accent, light-dark(#1f56d6, #7aa2ff));
339 --rst-focus-halo: color-mix(in srgb, var(--rst-accent, light-dark(#1f56d6, #7aa2ff)) 22%, transparent);
340
341 /* The light's colours at full strength: the sheen on a filled button,
342 the sheen on a plain one (an accent tint in light, because light
343 cannot brighten white), the rim a card catches, and the wash a dark
344 card lifts by. The sheen caps are measured: white on the light
345 danger fill, under the face shade, clears 4.5:1 at 0.08 and fails
346 at 0.10. The plain sheen is the fill at 9%. The rim is the accent
347 folded into the line in light and into a mid grey in dark, where no
348 neutral token sits at that value. */
349 --rst-sheen-fill: light-dark(rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0.04));
350 --rst-sheen-plain: light-dark(color-mix(in srgb, var(--rst-accent-fill) 9%, transparent), rgba(255, 255, 255, 0.04));
351 --rst-light-rim: light-dark(color-mix(in srgb, var(--rst-accent, #1f56d6) 23%, var(--rst-line)), color-mix(in srgb, var(--rst-accent, #7aa2ff) 31%, #505050));
352 --rst-light-wash: light-dark(rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.015));
353
354 /* The press: a whole-face wash and a spot under the pointer, as
355 fractions of black, filled and plain. Numbers, because light-dark()
356 takes colours only; the dark values are restated in the two blocks
357 at the end of the file. */
358 --rst-press-wash: 0.08;
359 --rst-press-spot: 0.16;
360 --rst-press-wash-plain: 0.04;
361 --rst-press-spot-plain: 0.07;
362
363 /* The type and rail choices this theme makes: a smaller page title,
364 a smaller box heading, stat labels in sentence case, the rail on the
365 page background, and the current nav item as a surface thumb. */
366 --rst-title-size: 1.25rem;
367 --rst-title-weight: 600;
368 --rst-title-track: -0.012em;
369 --rst-heading-size: 0.8125rem;
370 --rst-label-case: none;
371 --rst-label-track: 0;
372 --rst-rail-bg: var(--rst-bg);
373 --rst-nav-current-bg: light-dark(#ffffff, #141518);
374 --rst-nav-current-fg: light-dark(#18181b, #ededf0);
375}
376
377/* The five hue-derived tokens, redeclared where the engine has relative
378 colour syntax. oklch(from) needs Chrome 119, Safari 16.4 and Firefox
379 128, and Firefox 128 is above the floor (Chrome 123, Safari 17.5,
380 Firefox 121). Without this gate an older engine would resolve the
381 fill to nothing at the use site and paint a white label on a white
382 button; below it the :root values hold, day's cobalt, which an accent
383 override does not reach. The lightness is day's own. The chroma is
384 the accent's, scaled to day's and capped, so a grey accent gives a
385 grey fill rather than a vivid one at a powerless hue. The fill and
386 the hover fill lower their lightness around hue 170, yellow through
387 green to cyan: a colour of that lightness clipped to sRGB gains
388 luminance, and the label sits not on the fill but on the fill under
389 the face shade's 4% white and, hovered, under the sheen's white too,
390 so cyan's dark hover, 4.74:1 on the bare fill, was 4.15:1 on the
391 painted face (Astra A1). The drop is a cosine bump that is zero
392 beyond 85 degrees from 170, so the default cobalt, at hue 263, is
393 outside it and lands where it did; its depth is 0.05 and 0.045 in
394 light and 0.1 and 0.05 in dark, measured against the brightest pixel
395 of the photographed button for twelve hues, three greys and the
396 sRGB edges in TestAnyAccentKeepsTheFillLabelReadable. Every number
397 is a literal, and the only arithmetic is inside a channel, where
398 every engine with relative colour takes calc(), min(), max() and
399 cos(). */
400@supports (color: oklch(from red l c h)) {
401 :root {
402 --rst-accent-soft: light-dark(oklch(from var(--rst-accent, #1f56d6) 0.958 min(calc(c * 0.0878), 0.018) h), oklch(from var(--rst-accent, #7aa2ff) 0.268 min(calc(c * 0.5039), 0.072) h));
403 --rst-accent-fill: light-dark(oklch(from var(--rst-accent, #1f56d6) calc(0.513 - 0.05 * max(0, cos((h - 170) * 1deg) - 0.087)) min(calc(c * 1.0244), 0.21) h), oklch(from var(--rst-accent, #7aa2ff) calc(0.543 - 0.1 * max(0, cos((h - 170) * 1deg) - 0.087)) min(calc(c * 1.5045), 0.215) h));
404 --rst-accent-fill-hover: light-dark(oklch(from var(--rst-accent, #1f56d6) calc(0.472 - 0.045 * max(0, cos((h - 170) * 1deg) - 0.087)) min(calc(c * 0.9463), 0.194) h), oklch(from var(--rst-accent, #7aa2ff) calc(0.5 - 0.05 * max(0, cos((h - 170) * 1deg) - 0.087)) min(calc(c * 1.3786), 0.197) h));
405 --rst-accent-fill-edge: light-dark(oklch(from var(--rst-accent, #1f56d6) 0.401 min(calc(c * 0.8049), 0.165) h), oklch(from var(--rst-accent, #7aa2ff) 0.422 min(calc(c * 1.1617), 0.166) h));
406 --rst-accent-fill-edge-hover: light-dark(oklch(from var(--rst-accent, #1f56d6) 0.37 min(calc(c * 0.7366), 0.151) h), oklch(from var(--rst-accent, #7aa2ff) 0.389 min(calc(c * 1.0847), 0.155) h));
407 }
408}
409
410/* The whole toggle. Setting color-scheme re-resolves every light-dark()
411 above, so an explicit choice beats the OS in both directions without
412 restating a colour. */
413:root[data-theme="light"] { color-scheme: light; }
414:root[data-theme="dark"] { color-scheme: dark; }
415
416/* The dark press strengths. Two blocks, because a reader who chose Dark
417 has data-theme and a reader on System on a dark OS has only the media
418 query; one block alone would hand the other reader the light numbers.
419 Numbers only: every colour above is a light-dark() pair and stays
420 declared once. */
421:root[data-theme="dark"] { --rst-press-wash: 0.18; --rst-press-spot: 0.30; --rst-press-wash-plain: 0.18; --rst-press-spot-plain: 0.30; }
422@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) { --rst-press-wash: 0.18; --rst-press-spot: 0.30; --rst-press-wash-plain: 0.18; --rst-press-spot-plain: 0.30; } }
423