@frontpanel/css 0.1.0 → 0.3.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/components.css CHANGED
@@ -49,6 +49,7 @@
49
49
 
50
50
  /** The page behind the device: quiet blue-grey with a faint Y2K grid. */
51
51
  .fp-device-backdrop {
52
+ color-scheme: var(--fp-scheme);
52
53
  background-color: var(--fp-color-backdrop);
53
54
  background-image:
54
55
  linear-gradient(var(--fp-color-grid) 1px, transparent 1px),
@@ -64,6 +65,7 @@
64
65
 
65
66
  /** Liquid-chrome ring around the device body. Diagonal so the reflection band crosses the corners. */
66
67
  .fp-device-rim {
68
+ color-scheme: var(--fp-scheme);
67
69
  border-radius: 36px;
68
70
  padding: 10px;
69
71
  background-image: linear-gradient(
@@ -89,10 +91,16 @@
89
91
  overflow: clip;
90
92
  border-radius: 26px;
91
93
  }
94
+
95
+ /* Forced colours drop the chrome: an outline keeps the device's edge. */
96
+ @media (forced-colors: active) {
97
+ outline: 1px solid CanvasText;
98
+ }
92
99
  }
93
100
 
94
101
  /** Molded body plastic the modules sit on. */
95
102
  .fp-device-body {
103
+ color-scheme: var(--fp-scheme);
96
104
  background-image: linear-gradient(180deg, var(--fp-color-shell-hi), var(--fp-color-shell) 240px);
97
105
  box-shadow:
98
106
  inset 1px 1px 0 var(--fp-color-bevel-hi),
@@ -192,6 +200,35 @@
192
200
  &:disabled {
193
201
  opacity: 0.45;
194
202
  }
203
+
204
+ /*
205
+ * Forced colours drop the chrome and its shadows: an outline keeps the button's edge, the system's
206
+ * selected colours show it pressed, and GrayText, not a fade, shows it disabled.
207
+ */
208
+ @media (forced-colors: active) {
209
+ outline: 1px solid ButtonText;
210
+ outline-offset: -1px;
211
+
212
+ &[aria-pressed="true"],
213
+ &[aria-expanded="true"],
214
+ &[aria-current="page"] {
215
+ forced-color-adjust: none;
216
+ background: SelectedItem;
217
+ box-shadow: none;
218
+ color: SelectedItemText;
219
+
220
+ /* Opted out, its focus ring would keep the skin's colour: the system's text colour shows on any ground. */
221
+ &:focus-visible {
222
+ outline-color: CanvasText;
223
+ }
224
+ }
225
+
226
+ &:disabled {
227
+ opacity: 1;
228
+ color: GrayText;
229
+ outline-color: GrayText;
230
+ }
231
+ }
195
232
  }
196
233
 
197
234
  /**
@@ -255,6 +292,18 @@
255
292
  &:disabled {
256
293
  opacity: 0.45;
257
294
  }
295
+
296
+ /* Forced colours drop the gel and its shadows: an outline keeps its edge, and GrayText, not a fade, shows it disabled. */
297
+ @media (forced-colors: active) {
298
+ outline: 1px solid ButtonText;
299
+ outline-offset: -1px;
300
+
301
+ &:disabled {
302
+ opacity: 1;
303
+ color: GrayText;
304
+ outline-color: GrayText;
305
+ }
306
+ }
258
307
  }
259
308
 
260
309
  /**
@@ -327,6 +376,34 @@
327
376
  &:disabled {
328
377
  opacity: 0.5;
329
378
  }
379
+
380
+ /*
381
+ * Forced colours drop the plastic and its ring: an outline keeps the cap's edge, the system's
382
+ * selected colours show it selected, and GrayText, not a fade, shows it disabled.
383
+ */
384
+ @media (forced-colors: active) {
385
+ outline: 1px solid ButtonText;
386
+ outline-offset: -1px;
387
+
388
+ &[aria-pressed="true"],
389
+ &[aria-checked="true"] {
390
+ forced-color-adjust: none;
391
+ background: SelectedItem;
392
+ box-shadow: none;
393
+ color: SelectedItemText;
394
+
395
+ /* Opted out, its focus ring would keep the skin's colour: the system's text colour shows on any ground. */
396
+ &:focus-visible {
397
+ outline-color: CanvasText;
398
+ }
399
+ }
400
+
401
+ &:disabled {
402
+ opacity: 1;
403
+ color: GrayText;
404
+ outline-color: GrayText;
405
+ }
406
+ }
330
407
  }
331
408
 
332
409
  /** Blue plastic for an fp-cap, with its own label colour. */
@@ -353,8 +430,879 @@
353
430
  --fp-cap-ink: var(--fp-color-cap-berry-ink);
354
431
  }
355
432
 
433
+ /**
434
+ * A control with its silkscreen label under it: a knob, fader, meter or switch and then an fp-silk.
435
+ * With `data-label-placement="start"` the label sits level with the control, before it in the
436
+ * line. A length set here, such as `--fp-fader-length`, reaches the control inside.
437
+ */
438
+ .fp-unit {
439
+ display: inline-flex;
440
+ flex-direction: column;
441
+ align-items: center;
442
+ gap: 0.375rem;
443
+
444
+ /* Reversed, so the markup stays control then label either way. */
445
+ &[data-label-placement="start"] {
446
+ flex-direction: row-reverse;
447
+ gap: 0.5rem;
448
+ }
449
+ }
450
+
451
+ /**
452
+ * Rotary knob: a knurled chrome skirt round a domed cap. The cap is lit from the top left and stays
453
+ * still; only its fp-knob-mark turns, by `rotate`, through 270 degrees. 48 px, 40 px with a mouse,
454
+ * trackpad or pen.
455
+ */
456
+ .fp-knob {
457
+ position: relative;
458
+ display: inline-block;
459
+ flex-shrink: 0;
460
+ width: 3rem;
461
+ height: 3rem;
462
+ border-radius: 50%;
463
+ background-image: repeating-conic-gradient(var(--fp-color-chrome-100) 0deg 5deg, var(--fp-color-chrome-300) 5deg 10deg);
464
+ box-shadow:
465
+ 0 0 0 1px var(--fp-color-edge),
466
+ inset 1px 1px 0 var(--fp-color-bevel-hi),
467
+ inset -1px -1px 0 var(--fp-color-bevel-lo),
468
+ 1px 2px 0 var(--fp-color-cast);
469
+ cursor: ns-resize;
470
+ touch-action: none;
471
+ user-select: none;
472
+
473
+ @media (pointer: fine) {
474
+ width: 2.5rem;
475
+ height: 2.5rem;
476
+ }
477
+
478
+ &::before {
479
+ content: "";
480
+ position: absolute;
481
+ inset: 16%;
482
+ border-radius: 50%;
483
+ background-image: radial-gradient(
484
+ circle at 30% 25%,
485
+ color-mix(in srgb, var(--fp-color-chrome-hi) 60%, var(--fp-color-chrome-100)) 0%,
486
+ var(--fp-color-chrome-100) 45%,
487
+ var(--fp-color-chrome-300) 100%
488
+ );
489
+ box-shadow:
490
+ 0 0 0 1px var(--fp-color-edge),
491
+ inset 1px 1px 0 var(--fp-color-bevel-hi),
492
+ inset -1px -1px 0 var(--fp-color-bevel-lo),
493
+ 1px 1px 2px var(--fp-color-cast);
494
+ }
495
+
496
+ /* A solid ring with a glow outside it: the glow alone fails non-text contrast on light chrome. */
497
+ &:focus-visible {
498
+ outline: 2px solid var(--fp-color-focus-ring);
499
+ outline-offset: 2px;
500
+ filter: drop-shadow(0 0 3px var(--fp-color-focus));
501
+ }
502
+
503
+ &[aria-disabled="true"] {
504
+ opacity: 0.45;
505
+ cursor: not-allowed;
506
+ }
507
+
508
+ /* Forced colours drop the knurling, the dome and their shadows: outlines draw the skirt and the cap. */
509
+ @media (forced-colors: active) {
510
+ outline: 1px solid CanvasText;
511
+
512
+ &::before {
513
+ outline: 1px solid CanvasText;
514
+ }
515
+ }
516
+ }
517
+
518
+ /** The pointer line on a knob's cap. Turn it with `rotate`: -135deg at the minimum, 135deg at the maximum. */
519
+ .fp-knob-mark {
520
+ position: absolute;
521
+ inset: 0;
522
+ pointer-events: none;
523
+
524
+ &::after {
525
+ content: "";
526
+ position: absolute;
527
+ top: 21%;
528
+ left: 50%;
529
+ width: 3px;
530
+ height: 24%;
531
+ translate: -50% 0;
532
+ border-radius: 2px;
533
+ background-color: var(--fp-color-ink);
534
+ }
535
+
536
+ /* Forced colours would paint the line in the page colour, on the page colour. */
537
+ @media (forced-colors: active) {
538
+ &::after {
539
+ forced-color-adjust: none;
540
+ background-color: CanvasText;
541
+ }
542
+ }
543
+ }
544
+
545
+ /**
546
+ * Fader: a chrome cap on a recessed slot. It stands up by default and lies on its side with
547
+ * `data-orientation="horizontal"`; `--fp-fader-length` sets how far it travels (8rem). 44 px
548
+ * across, 36 px with a mouse, trackpad or pen. Pressing the slot moves the cap there.
549
+ */
550
+ .fp-fader {
551
+ position: relative;
552
+ display: inline-block;
553
+ flex-shrink: 0;
554
+ width: 2.75rem;
555
+ height: var(--fp-fader-length, 8rem);
556
+ cursor: ns-resize;
557
+ touch-action: none;
558
+ user-select: none;
559
+
560
+ @media (pointer: fine) {
561
+ width: 2.25rem;
562
+ }
563
+
564
+ &[data-orientation="horizontal"] {
565
+ width: var(--fp-fader-length, 8rem);
566
+ height: 2.75rem;
567
+ cursor: ew-resize;
568
+
569
+ @media (pointer: fine) {
570
+ height: 2.25rem;
571
+ }
572
+ }
573
+
574
+ &[data-disabled] {
575
+ opacity: 0.45;
576
+ cursor: not-allowed;
577
+ }
578
+ }
579
+
580
+ /** The slot a fader's cap rides in, cut into the panel: shaded on its top and left inside edges. */
581
+ .fp-fader-slot {
582
+ position: absolute;
583
+ inset: 0.5rem auto;
584
+ left: 50%;
585
+ width: 6px;
586
+ translate: -50% 0;
587
+ border-radius: 3px;
588
+ background-color: var(--fp-color-housing);
589
+ box-shadow:
590
+ inset 1px 1px 2px rgb(0 0 0 / 0.5),
591
+ 1px 1px 0 var(--fp-color-bevel-hi);
592
+
593
+ &[data-orientation="horizontal"] {
594
+ inset: 50% 0.5rem auto;
595
+ width: auto;
596
+ height: 6px;
597
+ translate: 0 -50%;
598
+ }
599
+
600
+ /* Forced colours: the slot as a solid line, so the cap's travel shows. */
601
+ @media (forced-colors: active) {
602
+ forced-color-adjust: none;
603
+ background-color: CanvasText;
604
+ box-shadow: none;
605
+ }
606
+ }
607
+
608
+ /**
609
+ * A fader's cap: brushed chrome lit from the top left, with an ink grip line that marks the value.
610
+ * Place it along the slot with `bottom` (or `left` on its side, with `data-orientation="horizontal"`
611
+ * on the slot and cap as well as the fader).
612
+ */
613
+ .fp-fader-cap {
614
+ position: absolute;
615
+ inset-inline: 0;
616
+ height: 1.5rem;
617
+ border-radius: 4px;
618
+ background-image: linear-gradient(
619
+ 180deg,
620
+ color-mix(in srgb, var(--fp-color-chrome-hi) 60%, var(--fp-color-chrome-100)) 0%,
621
+ var(--fp-color-chrome-100) 45%,
622
+ var(--fp-color-chrome-300) 100%
623
+ );
624
+ box-shadow:
625
+ 0 0 0 1px var(--fp-color-edge),
626
+ inset 1px 1px 0 var(--fp-color-bevel-hi),
627
+ inset -1px -1px 0 var(--fp-color-bevel-lo),
628
+ 1px 2px 0 var(--fp-color-cast);
629
+
630
+ @media (pointer: fine) {
631
+ height: 1.25rem;
632
+ }
633
+
634
+ &::after {
635
+ content: "";
636
+ position: absolute;
637
+ inset: 50% 20% auto;
638
+ height: 2px;
639
+ translate: 0 -50%;
640
+ border-radius: 1px;
641
+ background-color: var(--fp-color-ink);
642
+ }
643
+
644
+ &[data-orientation="horizontal"] {
645
+ inset-inline: auto;
646
+ inset-block: 0;
647
+ width: 1.5rem;
648
+ height: auto;
649
+
650
+ @media (pointer: fine) {
651
+ width: 1.25rem;
652
+ }
653
+
654
+ &::after {
655
+ inset: 20% auto 20% 50%;
656
+ width: 2px;
657
+ height: auto;
658
+ translate: -50% 0;
659
+ }
660
+ }
661
+
662
+ /* A solid ring with a glow outside it: the glow alone fails non-text contrast on light chrome. */
663
+ &:focus-visible {
664
+ outline: 2px solid var(--fp-color-focus-ring);
665
+ outline-offset: 2px;
666
+ filter: drop-shadow(0 0 3px var(--fp-color-focus));
667
+ }
668
+
669
+ /* Forced colours: a cap in the page colour hides the slot under it; an outline and the grip draw it. */
670
+ @media (forced-colors: active) {
671
+ background-color: Canvas;
672
+ outline: 1px solid CanvasText;
673
+ outline-offset: -1px;
674
+
675
+ &::after {
676
+ forced-color-adjust: none;
677
+ background-color: CanvasText;
678
+ }
679
+ }
680
+ }
681
+
682
+ /**
683
+ * Illuminated rocker switch: a lamp-lit paddle in a dark bezel, marked I at the top and O at the
684
+ * bottom. Off, the O half is pressed in; on, the I half is, and the lamp behind the lens lights.
685
+ * Put it on a button with `role="switch"` and `aria-checked`, holding an fp-switch-rocker. The
686
+ * lamp is red; colour it with fp-led-green or fp-led-amber. 44 x 56 px, 36 x 46 px with a mouse,
687
+ * trackpad or pen. With `data-orientation="horizontal"` it lies on its side, 56 x 44 px (46 x 36),
688
+ * O on the left and I on the right. After an illuminated rocker pen by ykadosh (CodePen, MIT), rebuilt on the kit's
689
+ * tokens.
690
+ */
691
+ .fp-switch {
692
+ --fp-switch-lamp: var(--fp-led, var(--fp-color-led-red));
693
+ position: relative;
694
+ display: inline-block;
695
+ flex-shrink: 0;
696
+ width: 2.75rem;
697
+ height: 3.5rem;
698
+ padding: 5px;
699
+ border: 0;
700
+ border-radius: 4px;
701
+ background-color: color-mix(in srgb, var(--fp-color-housing) 40%, black);
702
+ box-shadow:
703
+ 0 0 0 1px var(--fp-color-edge),
704
+ inset 1px 1px 0 rgb(255 255 255 / 0.25),
705
+ inset 0 0 1px 3px var(--fp-color-housing),
706
+ inset 0 0 1px 5px color-mix(in srgb, var(--fp-color-housing) 40%, black),
707
+ 1px 2px 0 var(--fp-color-cast);
708
+ perspective: 216px;
709
+ cursor: pointer;
710
+
711
+ @media (pointer: fine) {
712
+ width: 2.25rem;
713
+ height: 2.875rem;
714
+ padding: 4px;
715
+ }
716
+
717
+ /* On: the I half goes in, the shine comes up, the shading goes, and the lamp lights as it lands. */
718
+ &[aria-checked="true"] .fp-switch-rocker {
719
+ transform: translateZ(6px) rotateX(25deg);
720
+ box-shadow: 0 -3px 6px var(--fp-switch-lamp);
721
+ }
722
+
723
+ &[aria-checked="true"] .fp-switch-face::before {
724
+ opacity: 1;
725
+ }
726
+
727
+ &[aria-checked="true"] .fp-switch-face::after {
728
+ opacity: 0;
729
+ }
730
+
731
+ &[aria-checked="true"] .fp-switch-lamp {
732
+ opacity: 1;
733
+ transition-duration: 60ms;
734
+ transition-timing-function: linear;
735
+ transition-delay: 250ms;
736
+ }
737
+
738
+ /*
739
+ * On its side the paddle tips across instead, and the marks stay upright. With the light at the
740
+ * top left, the right end is now the one in shade that casts the shadow, and the left end is lit.
741
+ */
742
+ &[data-orientation="horizontal"] {
743
+ width: 3.5rem;
744
+ height: 2.75rem;
745
+
746
+ @media (pointer: fine) {
747
+ width: 2.875rem;
748
+ height: 2.25rem;
749
+ }
750
+
751
+ & .fp-switch-rocker {
752
+ transform: translateZ(6px) rotateY(-25deg);
753
+ background: linear-gradient(
754
+ 90deg,
755
+ color-mix(in srgb, var(--fp-switch-lamp) 60%, black) 0%,
756
+ color-mix(in srgb, var(--fp-switch-lamp) 44%, black) 30%,
757
+ color-mix(in srgb, var(--fp-switch-lamp) 44%, black) 70%,
758
+ color-mix(in srgb, var(--fp-switch-lamp) 60%, black) 100%
759
+ );
760
+ }
761
+
762
+ /* The right end, in shade, with the shadow the paddle casts into the bezel. */
763
+ & .fp-switch-rocker::before {
764
+ left: auto;
765
+ right: 0;
766
+ width: 15px;
767
+ height: 100%;
768
+ transform-origin: right;
769
+ transform: rotateY(-90deg);
770
+ background: linear-gradient(
771
+ 270deg,
772
+ color-mix(in srgb, var(--fp-switch-lamp) 40%, black),
773
+ color-mix(in srgb, var(--fp-switch-lamp) 20%, black)
774
+ );
775
+ box-shadow:
776
+ -15px 0 3px 0 black,
777
+ -24px 0 6px 0 rgb(0 0 0 / 0.5);
778
+ }
779
+
780
+ /* The left end, lit from the left while it stands proud. */
781
+ & .fp-switch-rocker::after {
782
+ top: 0;
783
+ bottom: auto;
784
+ width: 15px;
785
+ height: 100%;
786
+ transform-origin: right;
787
+ transform: translateX(-15px) rotateY(-90deg);
788
+ background:
789
+ linear-gradient(
790
+ 270deg,
791
+ rgb(255 255 255 / 0.8) 10%,
792
+ rgb(255 255 255 / 0.3) 30%,
793
+ color-mix(in srgb, var(--fp-switch-lamp) 40%, black) 75%,
794
+ color-mix(in srgb, var(--fp-switch-lamp) 20%, black)
795
+ )
796
+ 50% 50% / 97% 97% no-repeat,
797
+ color-mix(in srgb, var(--fp-switch-lamp) 70%, black);
798
+ box-shadow: none;
799
+ }
800
+
801
+ & .fp-switch-face {
802
+ background:
803
+ linear-gradient(#fff, #fff) 78% 50% / max(2px, 4%) 28% no-repeat,
804
+ radial-gradient(circle, transparent 50%, #fff 52%, #fff 70%, transparent 72%) 22% 50% / 25% 33% no-repeat,
805
+ radial-gradient(transparent 30%, color-mix(in srgb, color-mix(in srgb, var(--fp-switch-lamp) 40%, black) 70%, transparent) 70%) 0 0 / 3px 3px;
806
+ }
807
+
808
+ & .fp-switch-face::before {
809
+ background:
810
+ linear-gradient(#fff, transparent 3%) 50% 50% / 97% 97% no-repeat,
811
+ linear-gradient(270deg, rgb(255 255 255 / 0.5), transparent 50%, transparent 80%, rgb(255 255 255 / 0.5)) 50% 50% / 97% 97% no-repeat;
812
+ }
813
+
814
+ & .fp-switch-face::after {
815
+ background-image: linear-gradient(270deg, transparent 70%, rgb(0 0 0 / 0.8));
816
+ }
817
+
818
+ &[aria-checked="true"] .fp-switch-rocker {
819
+ transform: translateZ(6px) rotateY(25deg);
820
+ box-shadow: 3px 0 6px var(--fp-switch-lamp);
821
+ }
822
+ }
823
+
824
+ /* A solid ring with a glow outside it: the glow alone fails non-text contrast on light chrome. */
825
+ &:focus-visible {
826
+ outline: 2px solid var(--fp-color-focus-ring);
827
+ outline-offset: 2px;
828
+ filter: drop-shadow(0 0 3px var(--fp-color-focus));
829
+ }
830
+
831
+ &:disabled,
832
+ &[aria-disabled="true"] {
833
+ opacity: 0.45;
834
+ cursor: not-allowed;
835
+ }
836
+
837
+ /*
838
+ * Forced colours drop the paddle's paint: an outline keeps the bezel's edge, and the rocker fills
839
+ * when on, as a lit LED does, so the state reads by shape as well as by the tilt.
840
+ */
841
+ @media (forced-colors: active) {
842
+ outline: 1px solid ButtonText;
843
+
844
+ &[data-orientation="horizontal"] .fp-switch-rocker {
845
+ background: Canvas;
846
+ }
847
+
848
+ &[aria-checked="true"] .fp-switch-rocker,
849
+ &[data-orientation="horizontal"][aria-checked="true"] .fp-switch-rocker {
850
+ background: CanvasText;
851
+ box-shadow: none;
852
+ }
853
+
854
+ &:disabled,
855
+ &[aria-disabled="true"] {
856
+ opacity: 1;
857
+ outline-color: GrayText;
858
+ }
859
+ }
860
+ }
861
+
862
+ /**
863
+ * The paddle of an fp-switch, tilted in 3D. It holds an fp-switch-lamp and then an fp-switch-face;
864
+ * its top and bottom ends show as it tips.
865
+ */
866
+ .fp-switch-rocker {
867
+ position: relative;
868
+ display: block;
869
+ width: 100%;
870
+ height: 100%;
871
+ transform-origin: 50% 50% -6px;
872
+ transform: translateZ(6px) rotateX(-25deg);
873
+ transform-style: preserve-3d;
874
+ background: linear-gradient(
875
+ color-mix(in srgb, var(--fp-switch-lamp) 60%, black) 0%,
876
+ color-mix(in srgb, var(--fp-switch-lamp) 44%, black) 30%,
877
+ color-mix(in srgb, var(--fp-switch-lamp) 44%, black) 70%,
878
+ color-mix(in srgb, var(--fp-switch-lamp) 60%, black) 100%
879
+ );
880
+
881
+ /* Snaps over at the end of its travel, as a rocker's spring does. */
882
+ transition: transform 300ms cubic-bezier(1, 0, 1, 1), box-shadow 300ms cubic-bezier(1, 0, 1, 1);
883
+
884
+ @media (prefers-reduced-motion: reduce) {
885
+ transition-duration: 0ms;
886
+ }
887
+
888
+ /* The top end, lit from above while it stands proud. */
889
+ &::before {
890
+ content: "";
891
+ position: absolute;
892
+ top: 0;
893
+ left: 0;
894
+ width: 100%;
895
+ height: 15px;
896
+ transform-origin: top;
897
+ transform: rotateX(-90deg);
898
+ background:
899
+ linear-gradient(
900
+ rgb(255 255 255 / 0.8) 10%,
901
+ rgb(255 255 255 / 0.3) 30%,
902
+ color-mix(in srgb, var(--fp-switch-lamp) 40%, black) 75%,
903
+ color-mix(in srgb, var(--fp-switch-lamp) 20%, black)
904
+ )
905
+ 50% 50% / 97% 97% no-repeat,
906
+ color-mix(in srgb, var(--fp-switch-lamp) 70%, black);
907
+ }
908
+
909
+ /* The bottom end, in shadow, with the shadow the paddle casts into the bezel. */
910
+ &::after {
911
+ content: "";
912
+ position: absolute;
913
+ bottom: 0;
914
+ left: 0;
915
+ width: 100%;
916
+ height: 15px;
917
+ transform-origin: top;
918
+ transform: translateY(15px) rotateX(-90deg);
919
+ background-image: linear-gradient(
920
+ color-mix(in srgb, var(--fp-switch-lamp) 40%, black),
921
+ color-mix(in srgb, var(--fp-switch-lamp) 20%, black)
922
+ );
923
+ box-shadow:
924
+ 0 15px 3px 0 black,
925
+ 0 24px 6px 0 rgb(0 0 0 / 0.5);
926
+ }
927
+
928
+ /* Forced colours: a plain paddle in the system's colours; fp-switch fills it when on. */
929
+ @media (forced-colors: active) {
930
+ forced-color-adjust: none;
931
+ background: Canvas;
932
+ outline: 1px solid CanvasText;
933
+ outline-offset: -1px;
934
+
935
+ &::before,
936
+ &::after {
937
+ content: none;
938
+ }
939
+ }
940
+ }
941
+
942
+ /** The lamp behind an fp-switch's lens: lit when the switch is on, and slow to fade, like a filament cooling. */
943
+ .fp-switch-lamp {
944
+ position: absolute;
945
+ inset: 0;
946
+ opacity: 0;
947
+ background-image: radial-gradient(
948
+ color-mix(in srgb, var(--fp-switch-lamp) 35%, #fff2c8),
949
+ var(--fp-switch-lamp) 40%,
950
+ transparent 70%
951
+ );
952
+ transition: opacity 600ms ease-out;
953
+
954
+ @media (prefers-reduced-motion: reduce) {
955
+ transition-duration: 0ms;
956
+ }
957
+
958
+ /* Forced colours: the rocker's fill shows the state instead. */
959
+ @media (forced-colors: active) {
960
+ display: none;
961
+ }
962
+ }
963
+
964
+ /**
965
+ * The front of an fp-switch's paddle: the dotted lens over the lamp, the I and O marks, and the
966
+ * shine that comes up on the pressed-in half. Decorative; the switch says its state.
967
+ */
968
+ .fp-switch-face {
969
+ position: absolute;
970
+ inset: 0;
971
+ background:
972
+ linear-gradient(#fff, #fff) 50% 20% / max(2px, 5%) 20% no-repeat,
973
+ radial-gradient(circle, transparent 50%, #fff 52%, #fff 70%, transparent 72%) 50% 80% / 33% 25% no-repeat,
974
+ radial-gradient(transparent 30%, color-mix(in srgb, color-mix(in srgb, var(--fp-switch-lamp) 40%, black) 70%, transparent) 70%) 0 0 / 3px 3px;
975
+
976
+ /* The shine: faint while the I half stands out, full once it is pressed in. */
977
+ &::before,
978
+ &::after {
979
+ content: "";
980
+ position: absolute;
981
+ inset: 0;
982
+ transition: opacity 300ms cubic-bezier(1, 0, 1, 1);
983
+
984
+ @media (prefers-reduced-motion: reduce) {
985
+ transition-duration: 0ms;
986
+ }
987
+ }
988
+
989
+ &::before {
990
+ opacity: 0.3;
991
+ background:
992
+ linear-gradient(#fff, transparent 3%) 50% 50% / 97% 97% no-repeat,
993
+ linear-gradient(rgb(255 255 255 / 0.5), transparent 50%, transparent 80%, rgb(255 255 255 / 0.5)) 50% 50% / 97% 97% no-repeat;
994
+ }
995
+
996
+ /* The shading on the O half while it is pressed in. */
997
+ &::after {
998
+ opacity: 1;
999
+ background-image: linear-gradient(transparent 70%, rgb(0 0 0 / 0.8));
1000
+ }
1001
+
1002
+ /* Forced colours: no lens or marks; the rocker's fill shows the state. */
1003
+ @media (forced-colors: active) {
1004
+ display: none;
1005
+ }
1006
+ }
1007
+
1008
+ /**
1009
+ * Level meter: a strip of LED segments in a dark housing, lit green, then amber, then red. Set
1010
+ * `--fp-meter-level` (0 to 1, in whole segments), `--fp-meter-segments` (12), and where amber and
1011
+ * red begin, `--fp-meter-amber` (8/12) and `--fp-meter-red` (11/12), as shares of the strip on
1012
+ * segment edges, or a segment lights in two colours. It stands
1013
+ * up by default and lies on its side with `data-orientation="horizontal"`; `--fp-meter-length`
1014
+ * sets how long it is (8rem). Give it `role="meter"` and its values, or `aria-hidden` beside a
1015
+ * readout that says the same.
1016
+ */
1017
+ .fp-meter {
1018
+ --fp-meter-zones: linear-gradient(
1019
+ to top,
1020
+ var(--fp-color-led-on) 0 calc(var(--fp-meter-amber, calc(8 / 12)) * 100%),
1021
+ var(--fp-color-led-amber) 0 calc(var(--fp-meter-red, calc(11 / 12)) * 100%),
1022
+ var(--fp-color-led-red) 0
1023
+ );
1024
+ --fp-meter-gaps: repeating-linear-gradient(
1025
+ to top,
1026
+ #000 0 calc(100% / var(--fp-meter-segments, 12) - 2px),
1027
+ transparent 0 calc(100% / var(--fp-meter-segments, 12))
1028
+ );
1029
+
1030
+ /* Lit segments spill a little light into the gaps beside them: the lens's glow. */
1031
+ --fp-meter-lit-gaps: repeating-linear-gradient(
1032
+ to top,
1033
+ #000 0 calc(100% / var(--fp-meter-segments, 12) - 2px),
1034
+ rgb(0 0 0 / calc(0.18 * var(--fp-led-glow, 1))) 0 calc(100% / var(--fp-meter-segments, 12))
1035
+ );
1036
+ --fp-meter-cell: 100% calc(100% / var(--fp-meter-segments, 12));
1037
+ position: relative;
1038
+ display: inline-block;
1039
+ flex-shrink: 0;
1040
+ width: 0.75rem;
1041
+ height: var(--fp-meter-length, 8rem);
1042
+ border-radius: 3px;
1043
+ background-color: var(--fp-color-housing);
1044
+ box-shadow:
1045
+ inset 1px 1px 2px rgb(0 0 0 / 0.5),
1046
+ 1px 1px 0 var(--fp-color-bevel-hi);
1047
+
1048
+ /* Each segment's gap sits at its far end, so the strip's own inset at that end is the gap. */
1049
+ &::before,
1050
+ &::after {
1051
+ content: "";
1052
+ position: absolute;
1053
+ inset: 0 2px 2px;
1054
+ background-image: var(--fp-meter-zones);
1055
+ mask-image: var(--fp-meter-gaps);
1056
+ }
1057
+
1058
+ /* Unlit segments are the LED's off colour with a trace of their zone's, so the zones show. */
1059
+ &::before {
1060
+ background-image:
1061
+ linear-gradient(color-mix(in srgb, var(--fp-color-led-off) 75%, transparent) 0 0),
1062
+ var(--fp-meter-zones);
1063
+ }
1064
+
1065
+ /*
1066
+ * A lit segment is brightest over its chip, in the middle, by the lens. The cut sits 1 px into the
1067
+ * gap below the next segment, so rounding never lights a sliver of it.
1068
+ */
1069
+ &::after {
1070
+ background-image:
1071
+ radial-gradient(closest-side, rgb(255 255 255 / var(--fp-led-core, 0.3)), transparent),
1072
+ var(--fp-meter-zones);
1073
+ background-position: left bottom;
1074
+ background-size: var(--fp-meter-cell), auto;
1075
+ mask-image: var(--fp-meter-lit-gaps);
1076
+ clip-path: inset(calc((1 - var(--fp-meter-level, 0)) * 100% + 1px) 0 0 0);
1077
+ }
1078
+
1079
+ /* Forced colours: the strip as an outline and the lit segments in CanvasText, so the level shows. */
1080
+ @media (forced-colors: active) {
1081
+ outline: 1px solid CanvasText;
1082
+
1083
+ &::before {
1084
+ content: none;
1085
+ }
1086
+
1087
+ &::after {
1088
+ forced-color-adjust: none;
1089
+ background: CanvasText;
1090
+ mask-image: var(--fp-meter-gaps);
1091
+ }
1092
+ }
1093
+
1094
+ &[data-orientation="horizontal"] {
1095
+ --fp-meter-zones: linear-gradient(
1096
+ to right,
1097
+ var(--fp-color-led-on) 0 calc(var(--fp-meter-amber, calc(8 / 12)) * 100%),
1098
+ var(--fp-color-led-amber) 0 calc(var(--fp-meter-red, calc(11 / 12)) * 100%),
1099
+ var(--fp-color-led-red) 0
1100
+ );
1101
+ --fp-meter-gaps: repeating-linear-gradient(
1102
+ to right,
1103
+ #000 0 calc(100% / var(--fp-meter-segments, 12) - 2px),
1104
+ transparent 0 calc(100% / var(--fp-meter-segments, 12))
1105
+ );
1106
+ --fp-meter-lit-gaps: repeating-linear-gradient(
1107
+ to right,
1108
+ #000 0 calc(100% / var(--fp-meter-segments, 12) - 2px),
1109
+ rgb(0 0 0 / calc(0.18 * var(--fp-led-glow, 1))) 0 calc(100% / var(--fp-meter-segments, 12))
1110
+ );
1111
+ --fp-meter-cell: calc(100% / var(--fp-meter-segments, 12)) 100%;
1112
+ width: var(--fp-meter-length, 8rem);
1113
+ height: 0.75rem;
1114
+
1115
+ &::before,
1116
+ &::after {
1117
+ inset: 2px 0 2px 2px;
1118
+ }
1119
+
1120
+ &::after {
1121
+ clip-path: inset(0 calc((1 - var(--fp-meter-level, 0)) * 100% + 1px) 0 0);
1122
+ }
1123
+ }
1124
+ }
1125
+
1126
+ /**
1127
+ * Seven-segment readout: LED digits on a near-black face, set in the housing. Each character is an
1128
+ * fp-readout-cell, and the value is said in an fp-readout-text inside. Green by default; colour it
1129
+ * with fp-led-amber or fp-led-red. Lit digits pass as text on the face at any size.
1130
+ */
1131
+ .fp-readout {
1132
+ position: relative;
1133
+ display: inline-flex;
1134
+ align-items: center;
1135
+ gap: 0.1875rem;
1136
+ padding: 0.3125rem 0.4375rem;
1137
+ border: 3px solid var(--fp-color-housing);
1138
+ border-radius: 5px;
1139
+ background-color: color-mix(in srgb, var(--fp-color-led-off) 70%, black);
1140
+ box-shadow:
1141
+ inset 1px 1px 3px rgb(0 0 0 / 0.8),
1142
+ 0 1px 0 var(--fp-color-bevel-hi);
1143
+ }
1144
+
1145
+ /**
1146
+ * One character of an fp-readout, leaning a little like a real display. It shows its unlit
1147
+ * segments itself, a figure eight and a point, faintly in the lit colour; put the lit ones in an
1148
+ * fp-readout-lit inside. With `data-colon` it is a narrow colon cell. `--fp-readout-height` sets
1149
+ * its height (2rem). Give it aria-hidden="true".
1150
+ */
1151
+ .fp-readout-cell {
1152
+ position: relative;
1153
+ flex-shrink: 0;
1154
+ height: var(--fp-readout-height, 2rem);
1155
+ aspect-ratio: 15 / 22;
1156
+ transform: skewX(-6deg);
1157
+
1158
+ &::before {
1159
+ content: "";
1160
+ position: absolute;
1161
+ inset: 0;
1162
+ background-color: color-mix(in srgb, var(--fp-color-led-off) 75%, var(--fp-led, var(--fp-color-led-on)));
1163
+ 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;
1164
+ }
1165
+
1166
+ &[data-colon] {
1167
+ aspect-ratio: 5 / 22;
1168
+
1169
+ &::before {
1170
+ content: none;
1171
+ }
1172
+ }
1173
+
1174
+ /* With forced colours, only the lit digits show: a ghost in a system colour blurs into them. */
1175
+ @media (forced-colors: active) {
1176
+ &::before {
1177
+ content: none;
1178
+ }
1179
+ }
1180
+ }
1181
+
1182
+ /**
1183
+ * The lit segments of an fp-readout-cell: an element for each, named by `data-segment`, `a` to `g`
1184
+ * (top, then clockwise, then the middle), `dp`, or a colon's `colon-upper` and `colon-lower`. Each
1185
+ * is brightest over its chip, in the middle, and they glow onto the face, both by the lens.
1186
+ */
1187
+ .fp-readout-lit {
1188
+ position: absolute;
1189
+ inset: 0;
1190
+ filter: drop-shadow(
1191
+ 0 0 calc(var(--fp-readout-height, 2rem) * 0.06 * var(--fp-led-glow, 1))
1192
+ color-mix(in srgb, var(--fp-led, var(--fp-color-led-on)) 70%, transparent)
1193
+ );
1194
+
1195
+ & > [data-segment] {
1196
+ position: absolute;
1197
+ background-color: var(--fp-led, var(--fp-color-led-on));
1198
+ background-image: radial-gradient(
1199
+ closest-side,
1200
+ color-mix(in srgb, var(--fp-led, var(--fp-color-led-on)) calc((1 - var(--fp-led-core, 0.3)) * 100%), white),
1201
+ var(--fp-led, var(--fp-color-led-on))
1202
+ );
1203
+ }
1204
+
1205
+ /* The bars, on the cell's 15 x 22 grid: 9 long and 2 thick, pointed at both ends. */
1206
+ & > [data-segment="a"],
1207
+ & > [data-segment="d"],
1208
+ & > [data-segment="g"] {
1209
+ left: 10%;
1210
+ width: 60%;
1211
+ height: 9.0909%;
1212
+ clip-path: polygon(0 50%, 11.1111% 0, 88.8889% 0, 100% 50%, 88.8889% 100%, 11.1111% 100%);
1213
+ }
1214
+
1215
+ & > [data-segment="b"],
1216
+ & > [data-segment="c"],
1217
+ & > [data-segment="e"],
1218
+ & > [data-segment="f"] {
1219
+ width: 13.3333%;
1220
+ height: 40.9091%;
1221
+ clip-path: polygon(50% 0, 100% 11.1111%, 100% 88.8889%, 50% 100%, 0 88.8889%, 0 11.1111%);
1222
+ }
1223
+
1224
+ & > [data-segment="a"] {
1225
+ top: 0;
1226
+ }
1227
+
1228
+ & > [data-segment="g"] {
1229
+ top: 45.4545%;
1230
+ }
1231
+
1232
+ & > [data-segment="d"] {
1233
+ top: 90.9091%;
1234
+ }
1235
+
1236
+ & > [data-segment="b"],
1237
+ & > [data-segment="c"] {
1238
+ left: 66.6667%;
1239
+ }
1240
+
1241
+ & > [data-segment="e"],
1242
+ & > [data-segment="f"] {
1243
+ left: 0;
1244
+ }
1245
+
1246
+ & > [data-segment="b"],
1247
+ & > [data-segment="f"] {
1248
+ top: 6.8182%;
1249
+ }
1250
+
1251
+ & > [data-segment="c"],
1252
+ & > [data-segment="e"] {
1253
+ top: 52.2727%;
1254
+ }
1255
+
1256
+ & > [data-segment="dp"],
1257
+ & > [data-segment="colon-upper"],
1258
+ & > [data-segment="colon-lower"] {
1259
+ aspect-ratio: 1;
1260
+ border-radius: 50%;
1261
+ }
1262
+
1263
+ & > [data-segment="dp"] {
1264
+ top: 90%;
1265
+ left: 82%;
1266
+ width: 16%;
1267
+ }
1268
+
1269
+ & > [data-segment="colon-upper"],
1270
+ & > [data-segment="colon-lower"] {
1271
+ left: 26%;
1272
+ width: 48%;
1273
+ }
1274
+
1275
+ & > [data-segment="colon-upper"] {
1276
+ top: 26.3636%;
1277
+ }
1278
+
1279
+ & > [data-segment="colon-lower"] {
1280
+ top: 62.7273%;
1281
+ }
1282
+
1283
+ @media (forced-colors: active) {
1284
+ filter: none;
1285
+
1286
+ & > [data-segment] {
1287
+ forced-color-adjust: none;
1288
+ background: CanvasText;
1289
+ }
1290
+ }
1291
+ }
1292
+
1293
+ /** An fp-readout's value as text, for screen readers: hidden from view, read in place of the digits. */
1294
+ .fp-readout-text {
1295
+ position: absolute;
1296
+ width: 1px;
1297
+ height: 1px;
1298
+ overflow: hidden;
1299
+ clip-path: inset(50%);
1300
+ white-space: nowrap;
1301
+ }
1302
+
356
1303
  /** Matte content panel. This is where reading happens: no gloss, a 1 px bevel and a short hard shadow. */
357
1304
  .fp-module {
1305
+ color-scheme: var(--fp-scheme);
358
1306
  border-radius: 10px;
359
1307
  background-color: var(--fp-color-shell-matte);
360
1308
  box-shadow:
@@ -362,6 +1310,11 @@
362
1310
  inset 1px 1px 0 var(--fp-color-bevel-hi),
363
1311
  inset -1px -1px 0 var(--fp-color-bevel-lo),
364
1312
  2px 3px 0 var(--fp-color-cast);
1313
+
1314
+ /* Forced colours drop the shadow that draws its edge: an outline keeps it. */
1315
+ @media (forced-colors: active) {
1316
+ outline: 1px solid CanvasText;
1317
+ }
365
1318
  }
366
1319
 
367
1320
  /** A module's own little title bar, in brushed chrome. */
@@ -418,11 +1371,17 @@
418
1371
 
419
1372
  /** Recessed well inside a matte panel, for secondary content or an empty slot. */
420
1373
  .fp-well {
1374
+ color-scheme: var(--fp-scheme);
421
1375
  border-radius: 6px;
422
1376
  background-color: var(--fp-color-well);
423
1377
  box-shadow:
424
1378
  inset 1px 1px 2px var(--fp-color-bevel-lo),
425
1379
  inset -1px -1px 0 var(--fp-color-bevel-hi);
1380
+
1381
+ /* Forced colours drop the shading that recesses it: an outline keeps an empty well in view. */
1382
+ @media (forced-colors: active) {
1383
+ outline: 1px solid CanvasText;
1384
+ }
426
1385
  }
427
1386
 
428
1387
  /** Silkscreened hardware label. */
@@ -445,6 +1404,11 @@
445
1404
  0 0 0 2px var(--fp-color-chrome-800),
446
1405
  inset 2px 2px 4px rgb(0 0 0 / 0.35),
447
1406
  inset -1px -1px 0 rgb(255 255 255 / 0.2);
1407
+
1408
+ /* Forced colours drop the chrome bezel: an outline frames the glass. */
1409
+ @media (forced-colors: active) {
1410
+ outline: 2px solid CanvasText;
1411
+ }
448
1412
  }
449
1413
 
450
1414
  /** One line of LCD text. Cells of fp-lcd-ghost stacked behind it show the unlit segments, as on real glass. */
@@ -462,6 +1426,11 @@
462
1426
  /** The unlit segments behind an LCD line. Decorative: give it aria-hidden="true". */
463
1427
  .fp-lcd-ghost {
464
1428
  color: var(--fp-color-lcd-ghost);
1429
+
1430
+ /* Forced colours would draw the unlit segments as solid as the text over them. */
1431
+ @media (forced-colors: active) {
1432
+ visibility: hidden;
1433
+ }
465
1434
  }
466
1435
 
467
1436
  /** Dark housing that LEDs and small readouts sit in. */
@@ -478,6 +1447,11 @@
478
1447
  box-shadow:
479
1448
  inset 1px 1px 2px rgb(0 0 0 / 0.5),
480
1449
  0 1px 0 var(--fp-color-bevel-hi);
1450
+
1451
+ /* Forced colours turn the dark housing into the page colour: an outline keeps it in view. */
1452
+ @media (forced-colors: active) {
1453
+ outline: 1px solid CanvasText;
1454
+ }
481
1455
  }
482
1456
 
483
1457
  /** An LED with its own dark bezel ring, so a lit one reads on light chrome too. Unlit by default. */
@@ -491,30 +1465,76 @@
491
1465
  box-shadow:
492
1466
  0 0 0 2px var(--fp-color-housing),
493
1467
  inset 0 -1px 1px rgb(0 0 0 / 0.45);
1468
+
1469
+ /* Forced colours drop the fill and the ring: an outline keeps an unlit LED in view. */
1470
+ @media (forced-colors: active) {
1471
+ outline: 1px solid CanvasText;
1472
+ outline-offset: 1px;
1473
+ }
494
1474
  }
495
1475
 
496
- /** Green for an fp-led, the default. */
1476
+ /** Green for an fp-led or fp-readout, the default. */
497
1477
  .fp-led-green {
498
1478
  --fp-led: var(--fp-color-led-on);
499
1479
  }
500
1480
 
501
- /** Amber for an fp-led. */
1481
+ /** Amber for an fp-led or fp-readout. */
502
1482
  .fp-led-amber {
503
1483
  --fp-led: var(--fp-color-led-amber);
504
1484
  }
505
1485
 
506
- /** Red for an fp-led. */
1486
+ /** Red for an fp-led or fp-readout. */
507
1487
  .fp-led-red {
508
1488
  --fp-led: var(--fp-color-led-red);
509
1489
  }
510
1490
 
511
- /** Lights an fp-led in its colour, with a glow. Say what it means in text nearby, never by colour alone. */
1491
+ /**
1492
+ * Lights an fp-led in its colour, brightest over the chip in its middle, with a glow. The lens sets
1493
+ * how strong both are. Say what it means in text nearby, never by colour alone.
1494
+ */
512
1495
  .fp-led-lit {
513
1496
  background-color: var(--fp-led, var(--fp-color-led-on));
1497
+ background-image: radial-gradient(
1498
+ closest-side,
1499
+ color-mix(in srgb, var(--fp-led, var(--fp-color-led-on)) calc((1 - var(--fp-led-core, 0.3)) * 100%), white),
1500
+ var(--fp-led, var(--fp-color-led-on))
1501
+ );
514
1502
  box-shadow:
515
1503
  0 0 0 2px var(--fp-color-housing),
516
- 0 0 7px 2px color-mix(in srgb, var(--fp-led, var(--fp-color-led-on)) 65%, transparent),
1504
+ 0 0 calc(7px * var(--fp-led-glow, 1)) calc(2px * var(--fp-led-glow, 1))
1505
+ color-mix(in srgb, var(--fp-led, var(--fp-color-led-on)) 65%, transparent),
517
1506
  inset 0 -1px 1px rgb(0 0 0 / 0.2);
1507
+
1508
+ /* Lit is filled, so it reads apart from unlit by shape as well as colour. */
1509
+ @media (forced-colors: active) {
1510
+ forced-color-adjust: none;
1511
+ background: CanvasText;
1512
+ box-shadow: none;
1513
+ }
1514
+ }
1515
+
1516
+ /**
1517
+ * LED lens, flat: an even fill with no hot spot. A lens class works on an fp-led, fp-meter or
1518
+ * fp-readout, or on any element around them, such as a device body, to set every one inside.
1519
+ */
1520
+ .fp-lens-flat {
1521
+ --fp-led-core: 0;
1522
+ --fp-led-glow: 1;
1523
+ }
1524
+
1525
+ /**
1526
+ * LED lens, diffused, the default: like most real displays, each LED is a little brighter over its
1527
+ * chip, in the middle, with a soft glow.
1528
+ */
1529
+ .fp-lens-diffused {
1530
+ --fp-led-core: 0.3;
1531
+ --fp-led-glow: 1;
1532
+ }
1533
+
1534
+ /** LED lens, clear: a bright, pale core over each chip and a wider glow, like a water-clear lens. */
1535
+ .fp-lens-clear {
1536
+ --fp-led-core: 0.5;
1537
+ --fp-led-glow: 1.5;
518
1538
  }
519
1539
 
520
1540
  /** Decorative screw head. Give it aria-hidden="true". */
@@ -532,6 +1552,7 @@
532
1552
 
533
1553
  /** A scrolling panel, such as a list window, with a thin scrollbar that never pushes the layout. */
534
1554
  .fp-scroll-thin {
1555
+ color-scheme: var(--fp-scheme);
535
1556
  scrollbar-width: thin;
536
1557
  scrollbar-color: var(--fp-color-scroll-thumb) transparent;
537
1558
  }