rastrillo / fiesta Public

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

Plain git — no account needed to clone.

Download

Download this file

1/* plain — the skeleton: greyscale, system type, almost no shape.
2 Structure lives in tokens.css; this file is colour, type and shape.
3
4 The look: nothing. plain is the theme you pick when you intend to
5 write your own — a working, accessible, entirely unstyled-looking app
6 that shows you the structure and none of the taste, so the first
7 colour you add is visibly yours. There is no accent hue: the accent
8 is near-black in light and near-white in dark, which is to say a link
9 reads as text with an underline on hover and a primary button reads as
10 a filled rectangle. That is deliberate. Add the hue.
11
12 Status still has to signal. A skeleton that renders an error the same
13 grey as a success is not minimal, it is broken, so the four tone
14 pairs keep conventional hues at very low chroma — a green you would
15 call grey-green, an ochre, a brick — each still clearing 4.5:1 on its
16 own tint. Colour is never the only channel (the pills carry words),
17 but it is not thrown away either.
18
19 Shadows are real and minimal. tokens.css paints with
20 var(--rst-shadow-*) unconditionally and a theme cannot opt out of a
21 property it must declare, so "no shadows" here means one hairline
22 layer at low alpha rather than a value the CSS parser would drop.
23 You get an edge, not a lift.
24
25 ── One block, both schemes ───────────────────────────────────────────
26 Every token is declared once, as light-dark(<light>, <dark>), under a
27 single :root that sets color-scheme: light dark. The two rules at the
28 bottom are the whole toggle: setting color-scheme on
29 :root[data-theme=…] re-resolves every light-dark() in the file at
30 once, in both directions. Tokens with one value in both schemes — the
31 font stack, the radii — are written plain.
32
33 light-dark() is a colour function: it may only stand where a <color>
34 is expected. So a shadow token wraps its colour in it and writes the
35 geometry once, outside the call — `0 8px 24px light-dark(a, b)`, never
36 `light-dark(0 8px 24px a, …)`, which no browser would accept as a
37 box-shadow.
38
39 ── WCAG 2.2 AA, measured ─────────────────────────────────────────────
40 Normal text needs 4.5:1; large text and UI component boundaries need
41 3:1. Every pair below was computed from these exact hex values, in
42 both schemes. If you change a token, recompute its rows.
43
44 LIGHT ratio requirement
45 --rst-text on --rst-surface 18.88 4.5:1 text
46 --rst-text on --rst-bg 18.88 4.5:1 text
47 --rst-text on --rst-surface-2 17.17 4.5:1 text
48 --rst-text on --rst-accent-soft 16.13 4.5:1 text
49 --rst-text-muted on --rst-surface 8.86 4.5:1 text
50 --rst-text-muted on --rst-bg 8.86 4.5:1 text
51 --rst-text-muted on --rst-surface-2 8.06 4.5:1 text
52 --rst-text-muted on --rst-accent-soft 7.57 4.5:1 text
53 --rst-text-faint on --rst-surface 6.01 4.5:1 text
54 --rst-text-faint on --rst-bg 6.01 4.5:1 text
55 --rst-text-faint on --rst-surface-2 5.46 4.5:1 text
56 --rst-text-faint on --rst-accent-soft 5.13 4.5:1 text
57 --rst-accent on --rst-surface 18.88 4.5:1 text + focus ring
58 --rst-accent on --rst-bg 18.88 4.5:1 text + focus ring
59 --rst-accent on --rst-surface-2 17.17 4.5:1 text
60 --rst-accent on --rst-accent-soft 16.13 4.5:1 text
61 --rst-on-accent on --rst-accent 18.88 4.5:1 button label
62 --rst-on-accent on --rst-accent-strong 21.00 4.5:1 button label, hover
63 --rst-line-strong on --rst-surface 4.54 3:1 control border
64 --rst-line-strong on --rst-bg 4.54 3:1 control border
65 --rst-line-strong on --rst-surface-2 4.13 3:1 control border
66 pill neutral fg on its own tint 8.75 4.5:1 text
67 pill positive fg on its own tint 6.46 4.5:1 text
68 pill warning fg on its own tint 6.09 4.5:1 text
69 pill negative fg on its own tint 7.55 4.5:1 text
70 --rst-on-accent on negative fg (fill) 9.44 4.5:1 danger button label
71 --rst-on-accent-fill on --rst-accent-fill 18.88 4.5:1 primary button label
72 --rst-on-accent-fill on --rst-accent-fill-hover 21.00 4.5:1 primary button label, hover
73 --rst-on-danger-fill on --rst-danger-fill 9.44 4.5:1 danger button label
74 --rst-on-danger-fill-hover on --rst-danger-fill-hover 9.44 4.5:1 danger button label, hover
75 --rst-text on --rst-row-tint-hover 17.17 4.5:1 list-row-action text, hovered
76 --rst-text on --rst-row-tint-press 17.17 4.5:1 list-row-action text, pressed
77 --rst-control-text-hover on --rst-control-face-hover 18.88 4.5:1 plain button label, hover
78 --rst-text-muted on --rst-control-face-hover 8.86 4.5:1 muted label on a hovered plain face
79 --rst-text on --rst-tint-hover 16.13 4.5:1 row text on the hover tint
80 --rst-text on --rst-tint-press 16.13 4.5:1 row text on the press tint
81 --rst-text-muted on --rst-tint-hover 7.57 4.5:1 muted cell on the hover tint
82 --rst-text-muted on --rst-tint-press 7.57 4.5:1 muted cell on the press tint
83 --rst-text-faint on --rst-tint-hover 5.13 4.5:1 faint cell on the hover tint
84 --rst-text-faint on --rst-tint-press 5.13 4.5:1 faint cell on the press tint
85 --rst-accent on --rst-tint-hover 16.13 4.5:1 a link on a hovered row
86 --rst-nav-current-fg on --rst-nav-current-bg 16.13 4.5:1 the current nav item
87 --rst-track-off on --rst-surface 4.54 3:1 switch off track (1.4.11 boundary)
88 --rst-track-off on --rst-bg 4.54 3:1 switch off track on the page
89 --rst-knob-shade on --rst-track-off 4.54 3:1 switch knob on the off track
90 --rst-knob-shade on --rst-accent-fill 18.88 3:1 switch knob on the on track
91
92 DARK ratio requirement
93 --rst-text on --rst-surface 16.01 4.5:1 text
94 --rst-text on --rst-bg 17.12 4.5:1 text
95 --rst-text on --rst-surface-2 16.60 4.5:1 text
96 --rst-text on --rst-accent-soft 13.87 4.5:1 text
97 --rst-text-muted on --rst-surface 8.55 4.5:1 text
98 --rst-text-muted on --rst-bg 9.14 4.5:1 text
99 --rst-text-muted on --rst-surface-2 8.86 4.5:1 text
100 --rst-text-muted on --rst-accent-soft 7.40 4.5:1 text
101 --rst-text-faint on --rst-surface 6.86 4.5:1 text
102 --rst-text-faint on --rst-bg 7.33 4.5:1 text
103 --rst-text-faint on --rst-surface-2 7.11 4.5:1 text
104 --rst-text-faint on --rst-accent-soft 5.94 4.5:1 text
105 --rst-accent on --rst-surface 16.01 4.5:1 text + focus ring
106 --rst-accent on --rst-bg 17.12 4.5:1 text + focus ring
107 --rst-accent on --rst-surface-2 16.60 4.5:1 text
108 --rst-accent on --rst-accent-soft 13.87 4.5:1 text
109 --rst-on-accent on --rst-accent 17.12 4.5:1 button label
110 --rst-on-accent on --rst-accent-strong 19.17 4.5:1 button label, hover
111 --rst-line-strong on --rst-surface 5.54 3:1 control border
112 --rst-line-strong on --rst-bg 5.93 3:1 control border
113 --rst-line-strong on --rst-surface-2 5.75 3:1 control border
114 pill neutral fg on its own tint 9.05 4.5:1 text
115 pill positive fg on its own tint 8.70 4.5:1 text
116 pill warning fg on its own tint 8.82 4.5:1 text
117 pill negative fg on its own tint 7.63 4.5:1 text
118 --rst-on-accent on negative fg (fill) 8.93 4.5:1 danger button label
119 --rst-on-accent-fill on --rst-accent-fill 17.12 4.5:1 primary button label
120 --rst-on-accent-fill on --rst-accent-fill-hover 19.17 4.5:1 primary button label, hover
121 --rst-on-danger-fill on --rst-danger-fill 8.93 4.5:1 danger button label
122 --rst-on-danger-fill-hover on --rst-danger-fill-hover 8.93 4.5:1 danger button label, hover
123 --rst-text on --rst-row-tint-hover 16.60 4.5:1 list-row-action text, hovered
124 --rst-text on --rst-row-tint-press 16.60 4.5:1 list-row-action text, pressed
125 --rst-control-text-hover on --rst-control-face-hover 16.01 4.5:1 plain button label, hover
126 --rst-text-muted on --rst-control-face-hover 8.55 4.5:1 muted label on a hovered plain face
127 --rst-text on --rst-tint-hover 13.87 4.5:1 row text on the hover tint
128 --rst-text on --rst-tint-press 13.87 4.5:1 row text on the press tint
129 --rst-text-muted on --rst-tint-hover 7.40 4.5:1 muted cell on the hover tint
130 --rst-text-muted on --rst-tint-press 7.40 4.5:1 muted cell on the press tint
131 --rst-text-faint on --rst-tint-hover 5.94 4.5:1 faint cell on the hover tint
132 --rst-text-faint on --rst-tint-press 5.94 4.5:1 faint cell on the press tint
133 --rst-accent on --rst-tint-hover 13.87 4.5:1 a link on a hovered row
134 --rst-nav-current-fg on --rst-nav-current-bg 13.87 4.5:1 the current nav item
135 --rst-track-off on --rst-surface 5.54 3:1 switch off track (1.4.11 boundary)
136 --rst-track-off on --rst-bg 5.93 3:1 switch off track on the page
137 --rst-knob-shade on --rst-track-off 5.54 3:1 switch knob on the off track
138 --rst-knob-shade on --rst-accent-fill 16.01 3:1 switch knob on the on track
139
140 The tightest pair in the set is --rst-text-faint on the accent tint —
141 5.13:1 in light, 5.94:1 in dark, against a 4.5:1 floor. Everything
142 else has room, which is what a greyscale palette buys you.
143
144 --rst-line is a hairline divider, not a control border, so 1.4.11's
145 3:1 does not apply to it. Control borders use --rst-line-strong.
146
147 --rst-header-rule is not in the table either, and deliberately so
148 (design doc §6-v2.2): the page header's rule is decoration, not
149 structure — the heading's size, weight and spacing carry the
150 structure — so no contrast floor applies to it and it is not in
151 ui/contrast_test.go's pair table. Do not argue it up to 3:1.
152
153 --rst-shadow-pop, --rst-shadow-knob, --rst-shadow-lift and
154 --rst-overlay are not in the table: they paint a translucent layer
155 over whatever sits underneath, not text over a fixed background, so a
156 contrast ratio does not apply.
157 ──────────────────────────────────────────────────────────────────── */
158
159:root {
160 color-scheme: light dark;
161
162 /* Type: whatever the machine already has. */
163 --rst-font: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
164
165 /* Shape: barely rounded. A corner you notice is a decision plain has
166 not made yet. */
167 --rst-radius: 4px;
168 --rst-radius-sm: 3px;
169 --rst-radius-pill: 999px;
170
171 /* Surfaces and lines */
172 --rst-bg: light-dark(#ffffff, #0f0f0f);
173 --rst-surface: light-dark(#ffffff, #171717);
174 --rst-surface-2: light-dark(#f4f4f4, #131313);
175 --rst-line: light-dark(#e0e0e0, #2b2b2b);
176 --rst-line-strong: light-dark(#767676, #8f8f8f);
177
178 /* The page header's rule. plain has no accent hue to fold in, so it
179 is the line and nothing else — the same derived token every theme
180 declares, resolving here to plain grey. Decorative: it carries no
181 contrast floor. */
182 --rst-header-rule: var(--rst-line);
183
184 /* Text */
185 --rst-text: light-dark(#111111, #f2f2f2);
186 --rst-text-muted: light-dark(#4a4a4a, #b3b3b3);
187 --rst-text-faint: light-dark(#636363, #a0a0a0);
188
189 /* Accent: none. The "accent" is the text colour, so a link is text
190 that underlines on hover and a primary button is a filled
191 rectangle. */
192 --rst-accent: light-dark(#111111, #f2f2f2);
193 --rst-accent-strong: light-dark(#000000, #ffffff);
194 --rst-accent-soft: light-dark(#ededed, #242424);
195 --rst-on-accent: light-dark(#ffffff, #0f0f0f);
196
197 /* Status tones: conventional hues held to very low chroma. Muted
198 enough to read as greyscale at a glance, separated enough that an
199 error is not a success. */
200 --rst-tone-neutral-fg: light-dark(#3f3f3f, #c8c8c8);
201 --rst-tone-neutral-bg: light-dark(#eaeaea, #262626);
202 --rst-tone-positive-fg: light-dark(#2e5b3e, #9fc8ac);
203 --rst-tone-positive-bg: light-dark(#e4ebe6, #1a231d);
204 --rst-tone-warning-fg: light-dark(#6a5320, #d3c08a);
205 --rst-tone-warning-bg: light-dark(#efeadd, #262218);
206 --rst-tone-negative-fg: light-dark(#7a2c2c, #dba3a3);
207 --rst-tone-negative-bg: light-dark(#f0e3e3, #2a1c1c);
208
209 /* Depth: one hairline layer. Real values, minimal effect. */
210 --rst-shadow-pop: 0 1px 3px light-dark(rgba(0, 0, 0, 0.14), rgba(0, 0, 0, 0.5));
211 --rst-shadow-knob: 0 1px 1px light-dark(rgba(0, 0, 0, 0.22), rgba(0, 0, 0, 0.4));
212 --rst-shadow-knob-hover: var(--rst-shadow-knob);
213 --rst-shadow-lift: 0 1px 1px light-dark(rgba(0, 0, 0, 0.07), rgba(0, 0, 0, 0.3));
214 --rst-overlay: light-dark(rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.6));
215
216 /* The depth axis, declared as the semantic tokens tokens.css read in
217 each place before the axis existed: the fills are the accent, the
218 faces the surface, the tints the soft accent, the linked rows the
219 second surface, the borders, the off track and the focused edge
220 the strong line, the rim the line, the danger fill the negative
221 tone; the highlights, shadows, sheen and press are transparent and
222 0. tokens.css reads every one of these, so a theme cannot leave
223 them out; it can only turn them off or point them back, which is
224 what this does, so this theme renders as it did, and an app's
225 override of --rst-accent, --rst-surface or --rst-line on :root
226 still reaches the controls it reached before (Astra A2). */
227 --rst-accent-fill: var(--rst-accent);
228 --rst-accent-fill-hover: var(--rst-accent-strong);
229 --rst-accent-fill-edge: var(--rst-accent);
230 --rst-accent-fill-edge-hover: var(--rst-accent-strong);
231 --rst-on-accent-fill: var(--rst-on-accent);
232 --rst-danger-fill: var(--rst-tone-negative-fg);
233 --rst-danger-fill-hover: var(--rst-tone-negative-fg);
234 --rst-danger-fill-edge: var(--rst-tone-negative-fg);
235 --rst-danger-fill-edge-hover: var(--rst-tone-negative-fg);
236 --rst-on-danger-fill: var(--rst-on-accent);
237 --rst-on-danger-fill-hover: var(--rst-on-accent);
238 --rst-danger-hover-filter: brightness(0.9);
239 --rst-control-face: var(--rst-surface);
240 --rst-control-face-hover: var(--rst-surface);
241 --rst-control-face-press: transparent;
242 --rst-control-border: var(--rst-line-strong);
243 --rst-control-border-hover: var(--rst-accent);
244 --rst-control-text-hover: var(--rst-accent);
245 --rst-ghost-edge: var(--rst-line-strong);
246 --rst-ghost-face-hover: transparent;
247 --rst-ghost-edge-hover: var(--rst-line-strong);
248 --rst-summary-face: transparent;
249 --rst-summary-face-hover: transparent;
250 --rst-summary-edge: transparent;
251 --rst-summary-edge-hover: transparent;
252 --rst-summary-radius: 0;
253 --rst-depth-hl: transparent;
254 --rst-depth-contact: transparent;
255 --rst-depth-ambient: transparent;
256 --rst-depth-face: 0;
257 --rst-press-drop: 0px;
258 --rst-knob: var(--rst-surface);
259 --rst-knob-shade: var(--rst-surface);
260 --rst-track-off: var(--rst-line-strong);
261 /* The switch's one size, under a mouse and a finger alike: today's. */
262 --rst-switch-w: 34px;
263 --rst-switch-h: 19px;
264 --rst-switch-knob: 15px;
265 --rst-switch-touch-w: 34px;
266 --rst-switch-touch-h: 19px;
267 --rst-switch-touch-knob: 15px;
268 --rst-tint-hover: var(--rst-accent-soft);
269 --rst-tint-press: var(--rst-accent-soft);
270 --rst-tint-tap: transparent;
271 --rst-tint-card-hover: transparent;
272 --rst-tint-tile-hover: var(--rst-surface);
273 --rst-tint-tile-press: var(--rst-surface);
274 --rst-tint-group-hover: transparent;
275 --rst-row-tint-hover: var(--rst-surface-2);
276 --rst-row-tint-press: var(--rst-surface-2);
277 --rst-focus-edge: var(--rst-line-strong);
278 --rst-focus-halo: transparent;
279 --rst-sheen-fill: transparent;
280 --rst-sheen-plain: transparent;
281 --rst-light-rim: var(--rst-line);
282 --rst-light-wash: transparent;
283 --rst-press-wash: 0;
284 --rst-press-spot: 0;
285 --rst-press-wash-plain: 0;
286 --rst-press-spot-plain: 0;
287 --rst-title-size: 1.375rem;
288 --rst-title-weight: 600;
289 --rst-title-track: -0.015em;
290 --rst-heading-size: var(--rst-fs-base);
291 --rst-label-case: uppercase;
292 --rst-label-track: 0.06em;
293 --rst-rail-bg: var(--rst-surface);
294 --rst-nav-current-bg: var(--rst-accent-soft);
295 --rst-nav-current-fg: var(--rst-accent);
296}
297
298/* The whole toggle. Setting color-scheme re-resolves every light-dark()
299 above, so an explicit choice beats the OS in both directions without
300 restating a colour. */
301:root[data-theme="light"] { color-scheme: light; }
302:root[data-theme="dark"] { color-scheme: dark; }
303