@frontpanel/css 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/tailwind.css ADDED
@@ -0,0 +1,1158 @@
1
+ /* Generated by scripts/build.ts from src/. Do not edit; edit the source and run `pnpm build`. */
2
+ @import "./tokens.css" layer(theme);
3
+
4
+ @theme inline {
5
+ --color-fp-chrome-hi: var(--fp-color-chrome-hi);
6
+ --color-fp-chrome-100: var(--fp-color-chrome-100);
7
+ --color-fp-chrome-300: var(--fp-color-chrome-300);
8
+ --color-fp-chrome-500: var(--fp-color-chrome-500);
9
+ --color-fp-chrome-800: var(--fp-color-chrome-800);
10
+ --color-fp-chrome-tint: var(--fp-color-chrome-tint);
11
+ --color-fp-scroll-thumb: var(--fp-color-scroll-thumb);
12
+ --color-fp-shell: var(--fp-color-shell);
13
+ --color-fp-shell-hi: var(--fp-color-shell-hi);
14
+ --color-fp-shell-matte: var(--fp-color-shell-matte);
15
+ --color-fp-well: var(--fp-color-well);
16
+ --color-fp-field: var(--fp-color-field);
17
+ --color-fp-ink: var(--fp-color-ink);
18
+ --color-fp-ink-soft: var(--fp-color-ink-soft);
19
+ --color-fp-ink-dim: var(--fp-color-ink-dim);
20
+ --color-fp-bevel-hi: var(--fp-color-bevel-hi);
21
+ --color-fp-bevel-lo: var(--fp-color-bevel-lo);
22
+ --color-fp-edge: var(--fp-color-edge);
23
+ --color-fp-edge-strong: var(--fp-color-edge-strong);
24
+ --color-fp-cast: var(--fp-color-cast);
25
+ --color-fp-grid: var(--fp-color-grid);
26
+ --color-fp-lcd-bg: var(--fp-color-lcd-bg);
27
+ --color-fp-lcd-ink: var(--fp-color-lcd-ink);
28
+ --color-fp-lcd-ghost: var(--fp-color-lcd-ghost);
29
+ --color-fp-housing: var(--fp-color-housing);
30
+ --color-fp-housing-ink: var(--fp-color-housing-ink);
31
+ --color-fp-led-on: var(--fp-color-led-on);
32
+ --color-fp-led-amber: var(--fp-color-led-amber);
33
+ --color-fp-led-red: var(--fp-color-led-red);
34
+ --color-fp-led-off: var(--fp-color-led-off);
35
+ --color-fp-cap: var(--fp-color-cap);
36
+ --color-fp-cap-ink: var(--fp-color-cap-ink);
37
+ --color-fp-cap-blue: var(--fp-color-cap-blue);
38
+ --color-fp-cap-blue-ink: var(--fp-color-cap-blue-ink);
39
+ --color-fp-cap-amber: var(--fp-color-cap-amber);
40
+ --color-fp-cap-amber-ink: var(--fp-color-cap-amber-ink);
41
+ --color-fp-cap-graphite: var(--fp-color-cap-graphite);
42
+ --color-fp-cap-graphite-ink: var(--fp-color-cap-graphite-ink);
43
+ --color-fp-cap-berry: var(--fp-color-cap-berry);
44
+ --color-fp-cap-berry-ink: var(--fp-color-cap-berry-ink);
45
+ --color-fp-gel: var(--fp-color-gel);
46
+ --color-fp-gel-hi: var(--fp-color-gel-hi);
47
+ --color-fp-gel-lo: var(--fp-color-gel-lo);
48
+ --color-fp-gel-ink: var(--fp-color-gel-ink);
49
+ --color-fp-focus: var(--fp-color-focus);
50
+ --color-fp-focus-ring: var(--fp-color-focus-ring);
51
+ --color-fp-select: var(--fp-color-select);
52
+ --color-fp-error-text: var(--fp-color-error-text);
53
+ --color-fp-backdrop: var(--fp-color-backdrop);
54
+ --color-fp-backdrop-hi: var(--fp-color-backdrop-hi);
55
+ --font-fp-display: var(--fp-font-display);
56
+ --font-fp-lcd: var(--fp-font-lcd);
57
+ --font-fp-ui: var(--fp-font-ui);
58
+ }
59
+
60
+ @layer components {
61
+ /* An LCD line redrawing left to right; the fp-lcd-redraw class steps through it. */
62
+ @keyframes fp-lcd-redraw {
63
+ from {
64
+ clip-path: inset(0 100% 0 0);
65
+ }
66
+
67
+ to {
68
+ clip-path: inset(0 0 0 0);
69
+ }
70
+ }
71
+
72
+ /* Two blinks 400 ms apart, then steady. Nothing on the device blinks for longer. */
73
+ @keyframes fp-blink-twice {
74
+ 0%,
75
+ 100% {
76
+ opacity: 1;
77
+ }
78
+
79
+ 12.5%,
80
+ 37.5% {
81
+ opacity: 0;
82
+ }
83
+
84
+ 25%,
85
+ 50% {
86
+ opacity: 1;
87
+ }
88
+ }
89
+ }
90
+
91
+ /** Redraws an LCD line left to right in four steps, as when its value changes. */
92
+ @utility fp-lcd-redraw {
93
+ animation: fp-lcd-redraw 160ms steps(4, end);
94
+
95
+ @media (prefers-reduced-motion: reduce) {
96
+ animation: none;
97
+ }
98
+ }
99
+
100
+ /** Blinks twice, then holds: an LED confirming an action. */
101
+ @utility fp-blink-twice {
102
+ animation: fp-blink-twice 1.6s steps(1, end) 1;
103
+
104
+ @media (prefers-reduced-motion: reduce) {
105
+ animation: none;
106
+ }
107
+ }
108
+
109
+ /** The page behind the device: quiet blue-grey with a faint Y2K grid. */
110
+ @utility fp-device-backdrop {
111
+ color-scheme: var(--fp-scheme);
112
+ background-color: var(--fp-color-backdrop);
113
+ background-image:
114
+ linear-gradient(var(--fp-color-grid) 1px, transparent 1px),
115
+ linear-gradient(90deg, var(--fp-color-grid) 1px, transparent 1px),
116
+ radial-gradient(ellipse 80% 60% at 20% 0%, var(--fp-color-backdrop-hi), transparent 70%),
117
+ linear-gradient(180deg, var(--fp-color-backdrop-hi), var(--fp-color-backdrop));
118
+ background-size:
119
+ 32px 32px,
120
+ 32px 32px,
121
+ auto,
122
+ auto;
123
+ }
124
+
125
+ /** Liquid-chrome ring around the device body. Diagonal so the reflection band crosses the corners. */
126
+ @utility fp-device-rim {
127
+ color-scheme: var(--fp-scheme);
128
+ border-radius: 36px;
129
+ padding: 10px;
130
+ background-image: linear-gradient(
131
+ 160deg,
132
+ var(--fp-color-chrome-hi) 0%,
133
+ var(--fp-color-chrome-100) 14%,
134
+ var(--fp-color-chrome-tint) 38%,
135
+ var(--fp-color-chrome-500) 50%,
136
+ var(--fp-color-chrome-300) 70%,
137
+ var(--fp-color-chrome-100) 100%
138
+ );
139
+ box-shadow:
140
+ 0 0 0 1px var(--fp-color-chrome-800),
141
+ inset 0 1px 0 var(--fp-color-chrome-hi),
142
+ 0 4px 0 var(--fp-color-cast),
143
+ 0 14px 18px -10px var(--fp-color-cast);
144
+
145
+ /*
146
+ * A body set in the rim follows its curve (the rim's radius less its padding) and clips to it.
147
+ * No specificity, so a rim sized another way can give its body a matching radius with a class.
148
+ */
149
+ :where(& > .fp-device-body) {
150
+ overflow: clip;
151
+ border-radius: 26px;
152
+ }
153
+ }
154
+
155
+ /** Molded body plastic the modules sit on. */
156
+ @utility fp-device-body {
157
+ color-scheme: var(--fp-scheme);
158
+ background-image: linear-gradient(180deg, var(--fp-color-shell-hi), var(--fp-color-shell) 240px);
159
+ box-shadow:
160
+ inset 1px 1px 0 var(--fp-color-bevel-hi),
161
+ inset -1px -1px 0 var(--fp-color-bevel-lo);
162
+ }
163
+
164
+ /** Liquid chrome with a hard horizon, for title bars and other frames. Never behind text. */
165
+ @utility fp-chrome {
166
+ background-image: linear-gradient(
167
+ 180deg,
168
+ var(--fp-color-chrome-hi) 0%,
169
+ var(--fp-color-chrome-100) 18%,
170
+ var(--fp-color-chrome-tint) 45%,
171
+ var(--fp-color-chrome-500) 52%,
172
+ var(--fp-color-chrome-300) 75%,
173
+ var(--fp-color-chrome-100) 100%
174
+ );
175
+ box-shadow:
176
+ inset 0 1px 0 var(--fp-color-chrome-hi),
177
+ inset 0 -1px 0 var(--fp-color-edge);
178
+ }
179
+
180
+ /** Brushed chrome without the horizon, calm enough to print a label in the middle of it. */
181
+ @utility fp-chrome-soft {
182
+ background-image: linear-gradient(
183
+ 180deg,
184
+ color-mix(in srgb, var(--fp-color-chrome-hi) 60%, var(--fp-color-chrome-100)) 0%,
185
+ var(--fp-color-chrome-100) 40%,
186
+ var(--fp-color-chrome-300) 100%
187
+ );
188
+ }
189
+
190
+ /** Small hardware push button in brushed chrome. 44 px tall, 36 px with a mouse, trackpad or pen. */
191
+ @utility fp-chrome-btn {
192
+ display: inline-flex;
193
+ align-items: center;
194
+ justify-content: center;
195
+ gap: 0.375rem;
196
+ min-height: 2.75rem;
197
+ min-width: 2.75rem;
198
+ padding-inline: 0.625rem;
199
+ border-radius: 6px;
200
+ color: var(--fp-color-ink);
201
+ font-size: 13px;
202
+ font-weight: 700;
203
+ background-image: linear-gradient(
204
+ 180deg,
205
+ color-mix(in srgb, var(--fp-color-chrome-hi) 60%, var(--fp-color-chrome-100)) 0%,
206
+ var(--fp-color-chrome-100) 40%,
207
+ var(--fp-color-chrome-300) 100%
208
+ );
209
+ box-shadow:
210
+ 0 0 0 1px var(--fp-color-edge),
211
+ inset 1px 1px 0 var(--fp-color-bevel-hi),
212
+ inset -1px -1px 0 var(--fp-color-bevel-lo),
213
+ 1px 2px 0 var(--fp-color-cast);
214
+ transition-property: translate, box-shadow, filter;
215
+ transition-duration: 70ms;
216
+ transition-timing-function: linear;
217
+
218
+ @media (prefers-reduced-motion: reduce) {
219
+ transition-duration: 0ms;
220
+ }
221
+
222
+ @media (pointer: fine) {
223
+ min-height: 2.25rem;
224
+ min-width: 2.25rem;
225
+ }
226
+
227
+ &:hover:not(:disabled) {
228
+ filter: brightness(1.05);
229
+ }
230
+
231
+ &:active:not(:disabled),
232
+ &[aria-pressed="true"],
233
+ &[aria-expanded="true"],
234
+ &[aria-current="page"] {
235
+ translate: 0 1px;
236
+ box-shadow:
237
+ 0 0 0 1px var(--fp-color-edge),
238
+ inset 1px 1px 3px var(--fp-color-bevel-lo),
239
+ inset -1px -1px 0 var(--fp-color-bevel-hi);
240
+ }
241
+
242
+ /* A solid ring with a glow outside it: the glow alone fails non-text contrast on light chrome. */
243
+ &:focus-visible {
244
+ outline: 2px solid var(--fp-color-focus-ring);
245
+ outline-offset: 2px;
246
+ filter: drop-shadow(0 0 3px var(--fp-color-focus));
247
+ }
248
+
249
+ /* The hover filter outranks the focus rule, so a hovered control keeps its glow here. */
250
+ &:focus-visible:hover:not(:disabled) {
251
+ filter: brightness(1.05) drop-shadow(0 0 3px var(--fp-color-focus));
252
+ }
253
+
254
+ &:disabled {
255
+ opacity: 0.45;
256
+ }
257
+ }
258
+
259
+ /**
260
+ * Glossy gel pill for primary actions. Its white label sits on the base colour at mid-height,
261
+ * where the highlight ellipse has already faded out (7:1).
262
+ */
263
+ @utility fp-gel {
264
+ display: inline-flex;
265
+ align-items: center;
266
+ justify-content: center;
267
+ gap: 0.5rem;
268
+ min-height: 2.75rem;
269
+ padding-inline: 1rem;
270
+ border-radius: 9999px;
271
+ color: var(--fp-color-gel-ink);
272
+ font-size: 14px;
273
+ font-weight: 700;
274
+ text-shadow: 0 -1px 0 rgb(0 0 0 / 0.35);
275
+ background-image:
276
+ radial-gradient(ellipse 80% 45% at 50% 0%, rgb(255 255 255 / 0.7), rgb(255 255 255 / 0.08) 90%, transparent 100%),
277
+ linear-gradient(180deg, var(--fp-color-gel-hi) 0%, var(--fp-color-gel) 48%, var(--fp-color-gel-lo) 100%);
278
+ box-shadow:
279
+ 0 0 0 1px var(--fp-color-gel-lo),
280
+ inset 0 -3px 5px rgb(140 200 255 / 0.4),
281
+ 1px 2px 0 var(--fp-color-cast);
282
+ transition-property: translate, box-shadow, filter;
283
+ transition-duration: 70ms;
284
+ transition-timing-function: linear;
285
+
286
+ @media (prefers-reduced-motion: reduce) {
287
+ transition-duration: 0ms;
288
+ }
289
+
290
+ @media (pointer: fine) {
291
+ min-height: 2.5rem;
292
+ }
293
+
294
+ &:hover:not(:disabled) {
295
+ filter: brightness(1.08);
296
+ }
297
+
298
+ &:active:not(:disabled) {
299
+ translate: 0 1px;
300
+ box-shadow:
301
+ 0 0 0 1px var(--fp-color-gel-lo),
302
+ inset 0 2px 4px rgb(0 0 0 / 0.35);
303
+ }
304
+
305
+ /* A solid ring with a glow outside it: the glow alone fails non-text contrast on light chrome. */
306
+ &:focus-visible {
307
+ outline: 2px solid var(--fp-color-focus-ring);
308
+ outline-offset: 2px;
309
+ filter: drop-shadow(0 0 3px var(--fp-color-focus));
310
+ }
311
+
312
+ /* The hover filter outranks the focus rule, so a hovered control keeps its glow here. */
313
+ &:focus-visible:hover:not(:disabled) {
314
+ filter: brightness(1.08) drop-shadow(0 0 3px var(--fp-color-focus));
315
+ }
316
+
317
+ &:disabled {
318
+ opacity: 0.45;
319
+ }
320
+ }
321
+
322
+ /**
323
+ * Molded-plastic cap. The cap colour and its label colour come from the fp-cap-* classes
324
+ * (`--fp-cap`, `--fp-cap-ink`); a bare `fp-cap` is white plastic with a dark label. Selected caps
325
+ * stay pressed in and get a ring, so selection never depends on colour.
326
+ */
327
+ @utility fp-cap {
328
+ position: relative;
329
+ display: inline-flex;
330
+ align-items: center;
331
+ justify-content: center;
332
+ min-height: 2.75rem;
333
+ padding-inline: 0.5rem;
334
+ border-radius: 6px;
335
+ color: var(--fp-cap-ink, var(--fp-color-cap-ink));
336
+ font-weight: 700;
337
+ background-color: var(--fp-cap, var(--fp-color-cap));
338
+ background-image: radial-gradient(ellipse 110% 80% at 30% 10%, rgb(255 255 255 / 0.28), transparent 65%);
339
+ box-shadow:
340
+ 0 0 0 1px var(--fp-color-edge),
341
+ inset 0 2px 0 rgb(255 255 255 / 0.45),
342
+ inset 0 -2px 0 rgb(0 0 0 / 0.25),
343
+ 1px 2px 1px var(--fp-color-cast);
344
+ transition-property: translate, box-shadow, filter;
345
+ transition-duration: 70ms;
346
+ transition-timing-function: linear;
347
+
348
+ @media (prefers-reduced-motion: reduce) {
349
+ transition-duration: 0ms;
350
+ }
351
+
352
+ @media (pointer: fine) {
353
+ min-height: 2.25rem;
354
+ }
355
+
356
+ &:hover:not(:disabled) {
357
+ filter: brightness(1.05);
358
+ }
359
+
360
+ &:active:not(:disabled) {
361
+ translate: 0 1px;
362
+ box-shadow:
363
+ 0 0 0 1px var(--fp-color-edge),
364
+ inset 0 2px 3px rgb(0 0 0 / 0.35),
365
+ inset 0 -1px 0 rgb(255 255 255 / 0.3);
366
+ }
367
+
368
+ &[aria-pressed="true"],
369
+ &[aria-checked="true"] {
370
+ translate: 0 1px;
371
+ box-shadow:
372
+ 0 0 0 2px var(--fp-color-select),
373
+ inset 0 2px 3px rgb(0 0 0 / 0.35),
374
+ inset 0 -1px 0 rgb(255 255 255 / 0.3);
375
+ }
376
+
377
+ /* A solid ring with a glow outside it: the glow alone fails non-text contrast on light chrome. */
378
+ &:focus-visible {
379
+ outline: 2px solid var(--fp-color-focus-ring);
380
+ outline-offset: 2px;
381
+ filter: drop-shadow(0 0 3px var(--fp-color-focus));
382
+ }
383
+
384
+ /* The hover filter outranks the focus rule, so a hovered control keeps its glow here. */
385
+ &:focus-visible:hover:not(:disabled) {
386
+ filter: brightness(1.05) drop-shadow(0 0 3px var(--fp-color-focus));
387
+ }
388
+
389
+ &:disabled {
390
+ opacity: 0.5;
391
+ }
392
+ }
393
+
394
+ /** Blue plastic for an fp-cap, with its own label colour. */
395
+ @utility fp-cap-blue {
396
+ --fp-cap: var(--fp-color-cap-blue);
397
+ --fp-cap-ink: var(--fp-color-cap-blue-ink);
398
+ }
399
+
400
+ /** Amber plastic for an fp-cap, with its own label colour. */
401
+ @utility fp-cap-amber {
402
+ --fp-cap: var(--fp-color-cap-amber);
403
+ --fp-cap-ink: var(--fp-color-cap-amber-ink);
404
+ }
405
+
406
+ /** Graphite plastic for an fp-cap, with its own label colour. */
407
+ @utility fp-cap-graphite {
408
+ --fp-cap: var(--fp-color-cap-graphite);
409
+ --fp-cap-ink: var(--fp-color-cap-graphite-ink);
410
+ }
411
+
412
+ /** Berry plastic for an fp-cap, with its own label colour. */
413
+ @utility fp-cap-berry {
414
+ --fp-cap: var(--fp-color-cap-berry);
415
+ --fp-cap-ink: var(--fp-color-cap-berry-ink);
416
+ }
417
+
418
+ /**
419
+ * A control with its silkscreen label under it: a knob, fader or meter and an fp-silk. A length
420
+ * set here, such as `--fp-fader-length`, reaches the control inside.
421
+ */
422
+ @utility fp-unit {
423
+ display: inline-flex;
424
+ flex-direction: column;
425
+ align-items: center;
426
+ gap: 0.375rem;
427
+ }
428
+
429
+ /**
430
+ * Rotary knob: a knurled chrome skirt round a domed cap. The cap is lit from the top left and stays
431
+ * still; only its fp-knob-mark turns, by `rotate`, through 270 degrees. 48 px, 40 px with a mouse,
432
+ * trackpad or pen.
433
+ */
434
+ @utility fp-knob {
435
+ position: relative;
436
+ display: inline-block;
437
+ flex-shrink: 0;
438
+ width: 3rem;
439
+ height: 3rem;
440
+ border-radius: 50%;
441
+ background-image: repeating-conic-gradient(var(--fp-color-chrome-100) 0deg 5deg, var(--fp-color-chrome-300) 5deg 10deg);
442
+ box-shadow:
443
+ 0 0 0 1px var(--fp-color-edge),
444
+ inset 1px 1px 0 var(--fp-color-bevel-hi),
445
+ inset -1px -1px 0 var(--fp-color-bevel-lo),
446
+ 1px 2px 0 var(--fp-color-cast);
447
+ cursor: ns-resize;
448
+ touch-action: none;
449
+ user-select: none;
450
+
451
+ @media (pointer: fine) {
452
+ width: 2.5rem;
453
+ height: 2.5rem;
454
+ }
455
+
456
+ &::before {
457
+ content: "";
458
+ position: absolute;
459
+ inset: 16%;
460
+ border-radius: 50%;
461
+ background-image: radial-gradient(
462
+ circle at 30% 25%,
463
+ color-mix(in srgb, var(--fp-color-chrome-hi) 60%, var(--fp-color-chrome-100)) 0%,
464
+ var(--fp-color-chrome-100) 45%,
465
+ var(--fp-color-chrome-300) 100%
466
+ );
467
+ box-shadow:
468
+ 0 0 0 1px var(--fp-color-edge),
469
+ inset 1px 1px 0 var(--fp-color-bevel-hi),
470
+ inset -1px -1px 0 var(--fp-color-bevel-lo),
471
+ 1px 1px 2px var(--fp-color-cast);
472
+ }
473
+
474
+ /* A solid ring with a glow outside it: the glow alone fails non-text contrast on light chrome. */
475
+ &:focus-visible {
476
+ outline: 2px solid var(--fp-color-focus-ring);
477
+ outline-offset: 2px;
478
+ filter: drop-shadow(0 0 3px var(--fp-color-focus));
479
+ }
480
+
481
+ &[aria-disabled="true"] {
482
+ opacity: 0.45;
483
+ cursor: not-allowed;
484
+ }
485
+ }
486
+
487
+ /** The pointer line on a knob's cap. Turn it with `rotate`: -135deg at the minimum, 135deg at the maximum. */
488
+ @utility fp-knob-mark {
489
+ position: absolute;
490
+ inset: 0;
491
+ pointer-events: none;
492
+
493
+ &::after {
494
+ content: "";
495
+ position: absolute;
496
+ top: 21%;
497
+ left: 50%;
498
+ width: 3px;
499
+ height: 24%;
500
+ translate: -50% 0;
501
+ border-radius: 2px;
502
+ background-color: var(--fp-color-ink);
503
+ }
504
+ }
505
+
506
+ /**
507
+ * Fader: a chrome cap on a recessed slot. It stands up by default and lies on its side with
508
+ * `data-orientation="horizontal"`; `--fp-fader-length` sets how far it travels (8rem). 44 px
509
+ * across, 36 px with a mouse, trackpad or pen. Pressing the slot moves the cap there.
510
+ */
511
+ @utility fp-fader {
512
+ position: relative;
513
+ display: inline-block;
514
+ flex-shrink: 0;
515
+ width: 2.75rem;
516
+ height: var(--fp-fader-length, 8rem);
517
+ cursor: ns-resize;
518
+ touch-action: none;
519
+ user-select: none;
520
+
521
+ @media (pointer: fine) {
522
+ width: 2.25rem;
523
+ }
524
+
525
+ &[data-orientation="horizontal"] {
526
+ width: var(--fp-fader-length, 8rem);
527
+ height: 2.75rem;
528
+ cursor: ew-resize;
529
+
530
+ @media (pointer: fine) {
531
+ height: 2.25rem;
532
+ }
533
+ }
534
+
535
+ &[data-disabled] {
536
+ opacity: 0.45;
537
+ cursor: not-allowed;
538
+ }
539
+ }
540
+
541
+ /** The slot a fader's cap rides in, cut into the panel: shaded on its top and left inside edges. */
542
+ @utility fp-fader-slot {
543
+ position: absolute;
544
+ inset: 0.5rem auto;
545
+ left: 50%;
546
+ width: 6px;
547
+ translate: -50% 0;
548
+ border-radius: 3px;
549
+ background-color: var(--fp-color-housing);
550
+ box-shadow:
551
+ inset 1px 1px 2px rgb(0 0 0 / 0.5),
552
+ 1px 1px 0 var(--fp-color-bevel-hi);
553
+
554
+ &[data-orientation="horizontal"] {
555
+ inset: 50% 0.5rem auto;
556
+ width: auto;
557
+ height: 6px;
558
+ translate: 0 -50%;
559
+ }
560
+ }
561
+
562
+ /**
563
+ * A fader's cap: brushed chrome lit from the top left, with an ink grip line that marks the value.
564
+ * Place it along the slot with `bottom` (or `left` on its side, with `data-orientation="horizontal"`
565
+ * on the slot and cap as well as the fader).
566
+ */
567
+ @utility fp-fader-cap {
568
+ position: absolute;
569
+ inset-inline: 0;
570
+ height: 1.5rem;
571
+ border-radius: 4px;
572
+ background-image: linear-gradient(
573
+ 180deg,
574
+ color-mix(in srgb, var(--fp-color-chrome-hi) 60%, var(--fp-color-chrome-100)) 0%,
575
+ var(--fp-color-chrome-100) 45%,
576
+ var(--fp-color-chrome-300) 100%
577
+ );
578
+ box-shadow:
579
+ 0 0 0 1px var(--fp-color-edge),
580
+ inset 1px 1px 0 var(--fp-color-bevel-hi),
581
+ inset -1px -1px 0 var(--fp-color-bevel-lo),
582
+ 1px 2px 0 var(--fp-color-cast);
583
+
584
+ @media (pointer: fine) {
585
+ height: 1.25rem;
586
+ }
587
+
588
+ &::after {
589
+ content: "";
590
+ position: absolute;
591
+ inset: 50% 20% auto;
592
+ height: 2px;
593
+ translate: 0 -50%;
594
+ border-radius: 1px;
595
+ background-color: var(--fp-color-ink);
596
+ }
597
+
598
+ &[data-orientation="horizontal"] {
599
+ inset-inline: auto;
600
+ inset-block: 0;
601
+ width: 1.5rem;
602
+ height: auto;
603
+
604
+ @media (pointer: fine) {
605
+ width: 1.25rem;
606
+ }
607
+
608
+ &::after {
609
+ inset: 20% auto 20% 50%;
610
+ width: 2px;
611
+ height: auto;
612
+ translate: -50% 0;
613
+ }
614
+ }
615
+
616
+ /* A solid ring with a glow outside it: the glow alone fails non-text contrast on light chrome. */
617
+ &:focus-visible {
618
+ outline: 2px solid var(--fp-color-focus-ring);
619
+ outline-offset: 2px;
620
+ filter: drop-shadow(0 0 3px var(--fp-color-focus));
621
+ }
622
+ }
623
+
624
+ /**
625
+ * Level meter: a strip of LED segments in a dark housing, lit green, then amber, then red. Set
626
+ * `--fp-meter-level` (0 to 1, in whole segments), `--fp-meter-segments` (12), and where amber and
627
+ * red begin, `--fp-meter-amber` (8/12) and `--fp-meter-red` (11/12), as shares of the strip on
628
+ * segment edges, or a segment lights in two colours. It stands
629
+ * up by default and lies on its side with `data-orientation="horizontal"`; `--fp-meter-length`
630
+ * sets how long it is (8rem). Give it `role="meter"` and its values, or `aria-hidden` beside a
631
+ * readout that says the same.
632
+ */
633
+ @utility fp-meter {
634
+ --fp-meter-zones: linear-gradient(
635
+ to top,
636
+ var(--fp-color-led-on) 0 calc(var(--fp-meter-amber, calc(8 / 12)) * 100%),
637
+ var(--fp-color-led-amber) 0 calc(var(--fp-meter-red, calc(11 / 12)) * 100%),
638
+ var(--fp-color-led-red) 0
639
+ );
640
+ --fp-meter-gaps: repeating-linear-gradient(
641
+ to top,
642
+ #000 0 calc(100% / var(--fp-meter-segments, 12) - 2px),
643
+ transparent 0 calc(100% / var(--fp-meter-segments, 12))
644
+ );
645
+
646
+ /* Lit segments spill a little light into the gaps beside them: the lens's glow. */
647
+ --fp-meter-lit-gaps: repeating-linear-gradient(
648
+ to top,
649
+ #000 0 calc(100% / var(--fp-meter-segments, 12) - 2px),
650
+ rgb(0 0 0 / calc(0.18 * var(--fp-led-glow, 1))) 0 calc(100% / var(--fp-meter-segments, 12))
651
+ );
652
+ --fp-meter-cell: 100% calc(100% / var(--fp-meter-segments, 12));
653
+ position: relative;
654
+ display: inline-block;
655
+ flex-shrink: 0;
656
+ width: 0.75rem;
657
+ height: var(--fp-meter-length, 8rem);
658
+ border-radius: 3px;
659
+ background-color: var(--fp-color-housing);
660
+ box-shadow:
661
+ inset 1px 1px 2px rgb(0 0 0 / 0.5),
662
+ 1px 1px 0 var(--fp-color-bevel-hi);
663
+
664
+ /* Each segment's gap sits at its far end, so the strip's own inset at that end is the gap. */
665
+ &::before,
666
+ &::after {
667
+ content: "";
668
+ position: absolute;
669
+ inset: 0 2px 2px;
670
+ background-image: var(--fp-meter-zones);
671
+ mask-image: var(--fp-meter-gaps);
672
+ }
673
+
674
+ /* Unlit segments are the LED's off colour with a trace of their zone's, so the zones show. */
675
+ &::before {
676
+ background-image:
677
+ linear-gradient(color-mix(in srgb, var(--fp-color-led-off) 75%, transparent) 0 0),
678
+ var(--fp-meter-zones);
679
+ }
680
+
681
+ /*
682
+ * A lit segment is brightest over its chip, in the middle, by the lens. The cut sits 1 px into the
683
+ * gap below the next segment, so rounding never lights a sliver of it.
684
+ */
685
+ &::after {
686
+ background-image:
687
+ radial-gradient(closest-side, rgb(255 255 255 / var(--fp-led-core, 0.3)), transparent),
688
+ var(--fp-meter-zones);
689
+ background-position: left bottom;
690
+ background-size: var(--fp-meter-cell), auto;
691
+ mask-image: var(--fp-meter-lit-gaps);
692
+ clip-path: inset(calc((1 - var(--fp-meter-level, 0)) * 100% + 1px) 0 0 0);
693
+ }
694
+
695
+ /* Forced colours: the strip as an outline and the lit segments in CanvasText, so the level shows. */
696
+ @media (forced-colors: active) {
697
+ outline: 1px solid CanvasText;
698
+
699
+ &::before {
700
+ content: none;
701
+ }
702
+
703
+ &::after {
704
+ forced-color-adjust: none;
705
+ background: CanvasText;
706
+ mask-image: var(--fp-meter-gaps);
707
+ }
708
+ }
709
+
710
+ &[data-orientation="horizontal"] {
711
+ --fp-meter-zones: linear-gradient(
712
+ to right,
713
+ var(--fp-color-led-on) 0 calc(var(--fp-meter-amber, calc(8 / 12)) * 100%),
714
+ var(--fp-color-led-amber) 0 calc(var(--fp-meter-red, calc(11 / 12)) * 100%),
715
+ var(--fp-color-led-red) 0
716
+ );
717
+ --fp-meter-gaps: repeating-linear-gradient(
718
+ to right,
719
+ #000 0 calc(100% / var(--fp-meter-segments, 12) - 2px),
720
+ transparent 0 calc(100% / var(--fp-meter-segments, 12))
721
+ );
722
+ --fp-meter-lit-gaps: repeating-linear-gradient(
723
+ to right,
724
+ #000 0 calc(100% / var(--fp-meter-segments, 12) - 2px),
725
+ rgb(0 0 0 / calc(0.18 * var(--fp-led-glow, 1))) 0 calc(100% / var(--fp-meter-segments, 12))
726
+ );
727
+ --fp-meter-cell: calc(100% / var(--fp-meter-segments, 12)) 100%;
728
+ width: var(--fp-meter-length, 8rem);
729
+ height: 0.75rem;
730
+
731
+ &::before,
732
+ &::after {
733
+ inset: 2px 0 2px 2px;
734
+ }
735
+
736
+ &::after {
737
+ clip-path: inset(0 calc((1 - var(--fp-meter-level, 0)) * 100% + 1px) 0 0);
738
+ }
739
+ }
740
+ }
741
+
742
+ /**
743
+ * Seven-segment readout: LED digits on a near-black face, set in the housing. Each character is an
744
+ * fp-readout-cell, and the value is said in an fp-readout-text inside. Green by default; colour it
745
+ * with fp-led-amber or fp-led-red. Lit digits pass as text on the face at any size.
746
+ */
747
+ @utility fp-readout {
748
+ position: relative;
749
+ display: inline-flex;
750
+ align-items: center;
751
+ gap: 0.1875rem;
752
+ padding: 0.3125rem 0.4375rem;
753
+ border: 3px solid var(--fp-color-housing);
754
+ border-radius: 5px;
755
+ background-color: color-mix(in srgb, var(--fp-color-led-off) 70%, black);
756
+ box-shadow:
757
+ inset 1px 1px 3px rgb(0 0 0 / 0.8),
758
+ 0 1px 0 var(--fp-color-bevel-hi);
759
+ }
760
+
761
+ /**
762
+ * One character of an fp-readout, leaning a little like a real display. It shows its unlit
763
+ * segments itself, a figure eight and a point, faintly in the lit colour; put the lit ones in an
764
+ * fp-readout-lit inside. With `data-colon` it is a narrow colon cell. `--fp-readout-height` sets
765
+ * its height (2rem). Give it aria-hidden="true".
766
+ */
767
+ @utility fp-readout-cell {
768
+ position: relative;
769
+ flex-shrink: 0;
770
+ height: var(--fp-readout-height, 2rem);
771
+ aspect-ratio: 15 / 22;
772
+ transform: skewX(-6deg);
773
+
774
+ &::before {
775
+ content: "";
776
+ position: absolute;
777
+ inset: 0;
778
+ background-color: color-mix(in srgb, var(--fp-color-led-off) 75%, var(--fp-led, var(--fp-color-led-on)));
779
+ mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 15 22'%3E%3Cpolygon points='1.5,1 2.5,0 9.5,0 10.5,1 9.5,2 2.5,2'/%3E%3Cpolygon points='11,1.5 12,2.5 12,9.5 11,10.5 10,9.5 10,2.5'/%3E%3Cpolygon points='11,11.5 12,12.5 12,19.5 11,20.5 10,19.5 10,12.5'/%3E%3Cpolygon points='1.5,21 2.5,20 9.5,20 10.5,21 9.5,22 2.5,22'/%3E%3Cpolygon points='1,11.5 2,12.5 2,19.5 1,20.5 0,19.5 0,12.5'/%3E%3Cpolygon points='1,1.5 2,2.5 2,9.5 1,10.5 0,9.5 0,2.5'/%3E%3Cpolygon points='1.5,11 2.5,10 9.5,10 10.5,11 9.5,12 2.5,12'/%3E%3Ccircle cx='13.5' cy='21' r='1.2'/%3E%3C/svg%3E") 0 0 / 100% 100% no-repeat;
780
+ }
781
+
782
+ &[data-colon] {
783
+ aspect-ratio: 5 / 22;
784
+
785
+ &::before {
786
+ content: none;
787
+ }
788
+ }
789
+
790
+ /* With forced colours, only the lit digits show: a ghost in a system colour blurs into them. */
791
+ @media (forced-colors: active) {
792
+ &::before {
793
+ content: none;
794
+ }
795
+ }
796
+ }
797
+
798
+ /**
799
+ * The lit segments of an fp-readout-cell: an element for each, named by `data-segment`, `a` to `g`
800
+ * (top, then clockwise, then the middle), `dp`, or a colon's `colon-upper` and `colon-lower`. Each
801
+ * is brightest over its chip, in the middle, and they glow onto the face, both by the lens.
802
+ */
803
+ @utility fp-readout-lit {
804
+ position: absolute;
805
+ inset: 0;
806
+ filter: drop-shadow(
807
+ 0 0 calc(var(--fp-readout-height, 2rem) * 0.06 * var(--fp-led-glow, 1))
808
+ color-mix(in srgb, var(--fp-led, var(--fp-color-led-on)) 70%, transparent)
809
+ );
810
+
811
+ & > [data-segment] {
812
+ position: absolute;
813
+ background-color: var(--fp-led, var(--fp-color-led-on));
814
+ background-image: radial-gradient(
815
+ closest-side,
816
+ color-mix(in srgb, var(--fp-led, var(--fp-color-led-on)) calc((1 - var(--fp-led-core, 0.3)) * 100%), white),
817
+ var(--fp-led, var(--fp-color-led-on))
818
+ );
819
+ }
820
+
821
+ /* The bars, on the cell's 15 x 22 grid: 9 long and 2 thick, pointed at both ends. */
822
+ & > [data-segment="a"],
823
+ & > [data-segment="d"],
824
+ & > [data-segment="g"] {
825
+ left: 10%;
826
+ width: 60%;
827
+ height: 9.0909%;
828
+ clip-path: polygon(0 50%, 11.1111% 0, 88.8889% 0, 100% 50%, 88.8889% 100%, 11.1111% 100%);
829
+ }
830
+
831
+ & > [data-segment="b"],
832
+ & > [data-segment="c"],
833
+ & > [data-segment="e"],
834
+ & > [data-segment="f"] {
835
+ width: 13.3333%;
836
+ height: 40.9091%;
837
+ clip-path: polygon(50% 0, 100% 11.1111%, 100% 88.8889%, 50% 100%, 0 88.8889%, 0 11.1111%);
838
+ }
839
+
840
+ & > [data-segment="a"] {
841
+ top: 0;
842
+ }
843
+
844
+ & > [data-segment="g"] {
845
+ top: 45.4545%;
846
+ }
847
+
848
+ & > [data-segment="d"] {
849
+ top: 90.9091%;
850
+ }
851
+
852
+ & > [data-segment="b"],
853
+ & > [data-segment="c"] {
854
+ left: 66.6667%;
855
+ }
856
+
857
+ & > [data-segment="e"],
858
+ & > [data-segment="f"] {
859
+ left: 0;
860
+ }
861
+
862
+ & > [data-segment="b"],
863
+ & > [data-segment="f"] {
864
+ top: 6.8182%;
865
+ }
866
+
867
+ & > [data-segment="c"],
868
+ & > [data-segment="e"] {
869
+ top: 52.2727%;
870
+ }
871
+
872
+ & > [data-segment="dp"],
873
+ & > [data-segment="colon-upper"],
874
+ & > [data-segment="colon-lower"] {
875
+ aspect-ratio: 1;
876
+ border-radius: 50%;
877
+ }
878
+
879
+ & > [data-segment="dp"] {
880
+ top: 90%;
881
+ left: 82%;
882
+ width: 16%;
883
+ }
884
+
885
+ & > [data-segment="colon-upper"],
886
+ & > [data-segment="colon-lower"] {
887
+ left: 26%;
888
+ width: 48%;
889
+ }
890
+
891
+ & > [data-segment="colon-upper"] {
892
+ top: 26.3636%;
893
+ }
894
+
895
+ & > [data-segment="colon-lower"] {
896
+ top: 62.7273%;
897
+ }
898
+
899
+ @media (forced-colors: active) {
900
+ filter: none;
901
+
902
+ & > [data-segment] {
903
+ forced-color-adjust: none;
904
+ background: CanvasText;
905
+ }
906
+ }
907
+ }
908
+
909
+ /** An fp-readout's value as text, for screen readers: hidden from view, read in place of the digits. */
910
+ @utility fp-readout-text {
911
+ position: absolute;
912
+ width: 1px;
913
+ height: 1px;
914
+ overflow: hidden;
915
+ clip-path: inset(50%);
916
+ white-space: nowrap;
917
+ }
918
+
919
+ /** Matte content panel. This is where reading happens: no gloss, a 1 px bevel and a short hard shadow. */
920
+ @utility fp-module {
921
+ color-scheme: var(--fp-scheme);
922
+ border-radius: 10px;
923
+ background-color: var(--fp-color-shell-matte);
924
+ box-shadow:
925
+ 0 0 0 1px var(--fp-color-edge),
926
+ inset 1px 1px 0 var(--fp-color-bevel-hi),
927
+ inset -1px -1px 0 var(--fp-color-bevel-lo),
928
+ 2px 3px 0 var(--fp-color-cast);
929
+ }
930
+
931
+ /** A module's own little title bar, in brushed chrome. */
932
+ @utility fp-module-title {
933
+ display: flex;
934
+ align-items: center;
935
+ gap: 0.5rem;
936
+ min-height: 1.875rem;
937
+ padding: 0.25rem 0.625rem;
938
+ border-radius: 10px 10px 0 0;
939
+ border-bottom: 1px solid var(--fp-color-edge);
940
+ background-image: linear-gradient(
941
+ 180deg,
942
+ color-mix(in srgb, var(--fp-color-chrome-hi) 60%, var(--fp-color-chrome-100)) 0%,
943
+ var(--fp-color-chrome-100) 40%,
944
+ var(--fp-color-chrome-300) 100%
945
+ );
946
+ }
947
+
948
+ /**
949
+ * A window: a module (or, in the page extra, a sheet panel) whose fp-module-title stays in view
950
+ * while its body scrolls under it.
951
+ */
952
+ @utility fp-window {
953
+ /* Its top corners follow the window's, which differ between a module and a sheet. */
954
+ & > .fp-module-title {
955
+ position: sticky;
956
+ top: 0;
957
+ z-index: 1;
958
+ border-start-start-radius: inherit;
959
+ border-start-end-radius: inherit;
960
+ }
961
+
962
+ /* Title-bar buttons stay small with a precise pointer; touch keeps the 44 px target. */
963
+ @media (pointer: fine) {
964
+ & > .fp-module-title .fp-chrome-btn {
965
+ min-height: 1.75rem;
966
+ min-width: 1.75rem;
967
+ }
968
+ }
969
+ }
970
+
971
+ /** A window's name in its title bar. Pair it with fp-silk; it pushes the title-bar buttons to the far end. */
972
+ @utility fp-window-title {
973
+ margin: 0;
974
+ margin-inline-end: auto;
975
+ font-weight: 400;
976
+ }
977
+
978
+ /** The padded body under a window's title bar. */
979
+ @utility fp-window-body {
980
+ padding: 0.75rem;
981
+ }
982
+
983
+ /** Recessed well inside a matte panel, for secondary content or an empty slot. */
984
+ @utility fp-well {
985
+ color-scheme: var(--fp-scheme);
986
+ border-radius: 6px;
987
+ background-color: var(--fp-color-well);
988
+ box-shadow:
989
+ inset 1px 1px 2px var(--fp-color-bevel-lo),
990
+ inset -1px -1px 0 var(--fp-color-bevel-hi);
991
+ }
992
+
993
+ /** Silkscreened hardware label. */
994
+ @utility fp-silk {
995
+ font-family: var(--fp-font-display);
996
+ font-size: 11px;
997
+ line-height: 1.3;
998
+ letter-spacing: 0.08em;
999
+ text-transform: uppercase;
1000
+ color: var(--fp-color-ink-soft);
1001
+ }
1002
+
1003
+ /** LCD glass, recessed into the chrome. Text on it uses `--fp-font-lcd`; drawings use `--fp-color-lcd-ink`. */
1004
+ @utility fp-lcd {
1005
+ border-radius: 8px;
1006
+ color: var(--fp-color-lcd-ink);
1007
+ background-color: var(--fp-color-lcd-bg);
1008
+ background-image: repeating-linear-gradient(0deg, rgb(0 0 0 / 0.04) 0 1px, transparent 1px 3px);
1009
+ box-shadow:
1010
+ 0 0 0 2px var(--fp-color-chrome-800),
1011
+ inset 2px 2px 4px rgb(0 0 0 / 0.35),
1012
+ inset -1px -1px 0 rgb(255 255 255 / 0.2);
1013
+ }
1014
+
1015
+ /** One line of LCD text. Cells of fp-lcd-ghost stacked behind it show the unlit segments, as on real glass. */
1016
+ @utility fp-lcd-line {
1017
+ display: grid;
1018
+ margin: 0;
1019
+ font-family: var(--fp-font-lcd);
1020
+ white-space: pre;
1021
+
1022
+ & > * {
1023
+ grid-area: 1 / 1;
1024
+ }
1025
+ }
1026
+
1027
+ /** The unlit segments behind an LCD line. Decorative: give it aria-hidden="true". */
1028
+ @utility fp-lcd-ghost {
1029
+ color: var(--fp-color-lcd-ghost);
1030
+ }
1031
+
1032
+ /** Dark housing that LEDs and small readouts sit in. */
1033
+ @utility fp-housing {
1034
+ display: inline-flex;
1035
+ align-items: center;
1036
+ gap: 0.375rem;
1037
+ border-radius: 9999px;
1038
+ padding: 0.125rem 0.5rem;
1039
+ color: var(--fp-color-housing-ink);
1040
+ font-size: 12px;
1041
+ font-weight: 700;
1042
+ background-color: var(--fp-color-housing);
1043
+ box-shadow:
1044
+ inset 1px 1px 2px rgb(0 0 0 / 0.5),
1045
+ 0 1px 0 var(--fp-color-bevel-hi);
1046
+ }
1047
+
1048
+ /** An LED with its own dark bezel ring, so a lit one reads on light chrome too. Unlit by default. */
1049
+ @utility fp-led {
1050
+ display: inline-block;
1051
+ flex-shrink: 0;
1052
+ width: 0.5rem;
1053
+ height: 0.5rem;
1054
+ border-radius: 9999px;
1055
+ background-color: var(--fp-color-led-off);
1056
+ box-shadow:
1057
+ 0 0 0 2px var(--fp-color-housing),
1058
+ inset 0 -1px 1px rgb(0 0 0 / 0.45);
1059
+
1060
+ /* Forced colours drop the fill and the ring: an outline keeps an unlit LED in view. */
1061
+ @media (forced-colors: active) {
1062
+ outline: 1px solid CanvasText;
1063
+ outline-offset: 1px;
1064
+ }
1065
+ }
1066
+
1067
+ /** Green for an fp-led or fp-readout, the default. */
1068
+ @utility fp-led-green {
1069
+ --fp-led: var(--fp-color-led-on);
1070
+ }
1071
+
1072
+ /** Amber for an fp-led or fp-readout. */
1073
+ @utility fp-led-amber {
1074
+ --fp-led: var(--fp-color-led-amber);
1075
+ }
1076
+
1077
+ /** Red for an fp-led or fp-readout. */
1078
+ @utility fp-led-red {
1079
+ --fp-led: var(--fp-color-led-red);
1080
+ }
1081
+
1082
+ /**
1083
+ * Lights an fp-led in its colour, brightest over the chip in its middle, with a glow. The lens sets
1084
+ * how strong both are. Say what it means in text nearby, never by colour alone.
1085
+ */
1086
+ @utility fp-led-lit {
1087
+ background-color: var(--fp-led, var(--fp-color-led-on));
1088
+ background-image: radial-gradient(
1089
+ closest-side,
1090
+ color-mix(in srgb, var(--fp-led, var(--fp-color-led-on)) calc((1 - var(--fp-led-core, 0.3)) * 100%), white),
1091
+ var(--fp-led, var(--fp-color-led-on))
1092
+ );
1093
+ box-shadow:
1094
+ 0 0 0 2px var(--fp-color-housing),
1095
+ 0 0 calc(7px * var(--fp-led-glow, 1)) calc(2px * var(--fp-led-glow, 1))
1096
+ color-mix(in srgb, var(--fp-led, var(--fp-color-led-on)) 65%, transparent),
1097
+ inset 0 -1px 1px rgb(0 0 0 / 0.2);
1098
+
1099
+ /* Lit is filled, so it reads apart from unlit by shape as well as colour. */
1100
+ @media (forced-colors: active) {
1101
+ forced-color-adjust: none;
1102
+ background: CanvasText;
1103
+ box-shadow: none;
1104
+ }
1105
+ }
1106
+
1107
+ /**
1108
+ * LED lens, flat: an even fill with no hot spot. A lens class works on an fp-led, fp-meter or
1109
+ * fp-readout, or on any element around them, such as a device body, to set every one inside.
1110
+ */
1111
+ @utility fp-lens-flat {
1112
+ --fp-led-core: 0;
1113
+ --fp-led-glow: 1;
1114
+ }
1115
+
1116
+ /**
1117
+ * LED lens, diffused, the default: like most real displays, each LED is a little brighter over its
1118
+ * chip, in the middle, with a soft glow.
1119
+ */
1120
+ @utility fp-lens-diffused {
1121
+ --fp-led-core: 0.3;
1122
+ --fp-led-glow: 1;
1123
+ }
1124
+
1125
+ /** LED lens, clear: a bright, pale core over each chip and a wider glow, like a water-clear lens. */
1126
+ @utility fp-lens-clear {
1127
+ --fp-led-core: 0.5;
1128
+ --fp-led-glow: 1.5;
1129
+ }
1130
+
1131
+ /** Decorative screw head. Give it aria-hidden="true". */
1132
+ @utility fp-screw {
1133
+ display: inline-block;
1134
+ flex-shrink: 0;
1135
+ width: 10px;
1136
+ height: 10px;
1137
+ border-radius: 9999px;
1138
+ background-image:
1139
+ linear-gradient(135deg, transparent 44%, var(--fp-color-chrome-800) 44% 56%, transparent 56%),
1140
+ radial-gradient(circle at 35% 30%, var(--fp-color-chrome-hi), var(--fp-color-chrome-300) 60%, var(--fp-color-chrome-500));
1141
+ box-shadow: 0 0 0 1px var(--fp-color-edge);
1142
+ }
1143
+
1144
+ /** A scrolling panel, such as a list window, with a thin scrollbar that never pushes the layout. */
1145
+ @utility fp-scroll-thin {
1146
+ color-scheme: var(--fp-scheme);
1147
+ scrollbar-width: thin;
1148
+ scrollbar-color: var(--fp-color-scroll-thumb) transparent;
1149
+ }
1150
+
1151
+ /** A 16 px pixel icon. Size it in whole multiples of 16 px so its pixels stay crisp. */
1152
+ @utility fp-icon {
1153
+ flex-shrink: 0;
1154
+ width: 16px;
1155
+ height: 16px;
1156
+ fill: currentColor;
1157
+ shape-rendering: crispEdges;
1158
+ }