@camp.dev/bones 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.
@@ -0,0 +1,1092 @@
1
+ @import "./bones.css";
2
+
3
+ /* ---------------------------------------------------------------------------
4
+ auto.css — skeletonize unmarked markup under [aria-busy="true"].
5
+
6
+ data-bone marks shape, aria-busy marks state; this layer keys on state so a
7
+ page with zero data-bone attributes still gets skeletons. Escape hatches:
8
+ [data-bones-auto="off"] exempts a subtree, and explicit [data-bone] markup
9
+ is always left to bones.css. Every rule lives in @layer bones-auto so page
10
+ CSS outranks it without !important.
11
+ --------------------------------------------------------------------------- */
12
+
13
+ @layer bones-auto {
14
+ /* Text default: any element with no child elements, minus exemptions and
15
+ the replaced/control elements that get block treatment below. Same bar
16
+ geometry as [data-bone="text"] in bones.css — restated because CSS cannot
17
+ alias an attribute selector; the test suite pins both copies. */
18
+ [aria-busy="true"]
19
+ :not(:has(*)):not(
20
+ [data-bone],
21
+ [data-bone] *,
22
+ [data-bones-auto="off"],
23
+ [data-bones-auto="off"] *
24
+ ):not(
25
+ img,
26
+ svg,
27
+ video,
28
+ canvas,
29
+ picture,
30
+ iframe,
31
+ embed,
32
+ object,
33
+ audio,
34
+ button,
35
+ input,
36
+ select,
37
+ textarea,
38
+ progress,
39
+ meter,
40
+ hr,
41
+ br,
42
+ svg *,
43
+ picture *,
44
+ select *,
45
+ object *
46
+ ) {
47
+ color: transparent;
48
+ position: relative;
49
+ min-width: 4ch;
50
+ min-height: 1lh;
51
+ }
52
+
53
+ [aria-busy="true"]
54
+ :not(:has(*)):not(
55
+ [data-bone],
56
+ [data-bone] *,
57
+ [data-bones-auto="off"],
58
+ [data-bones-auto="off"] *
59
+ ):not(
60
+ img,
61
+ svg,
62
+ video,
63
+ canvas,
64
+ picture,
65
+ iframe,
66
+ embed,
67
+ object,
68
+ audio,
69
+ button,
70
+ input,
71
+ select,
72
+ textarea,
73
+ progress,
74
+ meter,
75
+ hr,
76
+ br,
77
+ svg *,
78
+ picture *,
79
+ select *,
80
+ object *
81
+ )::before {
82
+ content: "\200b";
83
+ }
84
+
85
+ [aria-busy="true"]
86
+ :not(:has(*)):not(
87
+ [data-bone],
88
+ [data-bone] *,
89
+ [data-bones-auto="off"],
90
+ [data-bones-auto="off"] *
91
+ ):not(
92
+ img,
93
+ svg,
94
+ video,
95
+ canvas,
96
+ picture,
97
+ iframe,
98
+ embed,
99
+ object,
100
+ audio,
101
+ button,
102
+ input,
103
+ select,
104
+ textarea,
105
+ progress,
106
+ meter,
107
+ hr,
108
+ br,
109
+ svg *,
110
+ picture *,
111
+ select *,
112
+ object *
113
+ )::after {
114
+ content: "";
115
+ position: absolute;
116
+ inset-inline: 0;
117
+ top: calc((1lh + 1cap) / 2 - 1ex);
118
+ height: 1ex;
119
+ background-color: var(--bone-base);
120
+ border-radius: var(--bone-radius);
121
+ pointer-events: none;
122
+ }
123
+ }
124
+
125
+ @layer bones-auto {
126
+ /* Block override: replaced elements and form controls fill their own box.
127
+ A text bar across an avatar or a button looks wrong. Leafness is not
128
+ required — svg and select routinely have element children. */
129
+ [aria-busy="true"]
130
+ :is(
131
+ img,
132
+ svg,
133
+ video,
134
+ canvas,
135
+ picture,
136
+ iframe,
137
+ embed,
138
+ object,
139
+ audio,
140
+ button,
141
+ input,
142
+ select,
143
+ textarea,
144
+ progress,
145
+ meter
146
+ ):not([data-bone], [data-bone] *, [data-bones-auto="off"], [data-bones-auto="off"] *) {
147
+ color: transparent;
148
+ background-color: var(--bone-base);
149
+ border-radius: var(--bone-radius);
150
+ border-color: transparent;
151
+ }
152
+
153
+ /* Width variance: text leaves cycle 85 / 100 / 92 / 60 so runs of lines
154
+ look organic. Takes effect on block-level leaves; inline leaves keep
155
+ their content-derived width, which already varies. */
156
+ [aria-busy="true"]
157
+ :not(:has(*)):not(
158
+ [data-bone],
159
+ [data-bone] *,
160
+ [data-bones-auto="off"],
161
+ [data-bones-auto="off"] *
162
+ ):not(
163
+ img,
164
+ svg,
165
+ video,
166
+ canvas,
167
+ picture,
168
+ iframe,
169
+ embed,
170
+ object,
171
+ audio,
172
+ button,
173
+ input,
174
+ select,
175
+ textarea,
176
+ progress,
177
+ meter,
178
+ hr,
179
+ br,
180
+ svg *,
181
+ picture *,
182
+ select *,
183
+ object *
184
+ ):nth-child(4n + 1) {
185
+ width: 85%;
186
+ }
187
+
188
+ [aria-busy="true"]
189
+ :not(:has(*)):not(
190
+ [data-bone],
191
+ [data-bone] *,
192
+ [data-bones-auto="off"],
193
+ [data-bones-auto="off"] *
194
+ ):not(
195
+ img,
196
+ svg,
197
+ video,
198
+ canvas,
199
+ picture,
200
+ iframe,
201
+ embed,
202
+ object,
203
+ audio,
204
+ button,
205
+ input,
206
+ select,
207
+ textarea,
208
+ progress,
209
+ meter,
210
+ hr,
211
+ br,
212
+ svg *,
213
+ picture *,
214
+ select *,
215
+ object *
216
+ ):nth-child(4n + 2) {
217
+ width: 100%;
218
+ }
219
+
220
+ [aria-busy="true"]
221
+ :not(:has(*)):not(
222
+ [data-bone],
223
+ [data-bone] *,
224
+ [data-bones-auto="off"],
225
+ [data-bones-auto="off"] *
226
+ ):not(
227
+ img,
228
+ svg,
229
+ video,
230
+ canvas,
231
+ picture,
232
+ iframe,
233
+ embed,
234
+ object,
235
+ audio,
236
+ button,
237
+ input,
238
+ select,
239
+ textarea,
240
+ progress,
241
+ meter,
242
+ hr,
243
+ br,
244
+ svg *,
245
+ picture *,
246
+ select *,
247
+ object *
248
+ ):nth-child(4n + 3) {
249
+ width: 92%;
250
+ }
251
+
252
+ [aria-busy="true"]
253
+ :not(:has(*)):not(
254
+ [data-bone],
255
+ [data-bone] *,
256
+ [data-bones-auto="off"],
257
+ [data-bones-auto="off"] *
258
+ ):not(
259
+ img,
260
+ svg,
261
+ video,
262
+ canvas,
263
+ picture,
264
+ iframe,
265
+ embed,
266
+ object,
267
+ audio,
268
+ button,
269
+ input,
270
+ select,
271
+ textarea,
272
+ progress,
273
+ meter,
274
+ hr,
275
+ br,
276
+ svg *,
277
+ picture *,
278
+ select *,
279
+ object *
280
+ ):nth-child(4n) {
281
+ width: 60%;
282
+ }
283
+ }
284
+
285
+ @layer bones-auto {
286
+ /* Auto bones default to shimmer. bones.css only animates inside a
287
+ [data-bone-animate] scope; a zero-markup page has no such attribute, so
288
+ the default lives here and the scopes below mirror bones.css for pages
289
+ that do set it. */
290
+ [aria-busy="true"]
291
+ :not(:has(*)):not(
292
+ [data-bone],
293
+ [data-bone] *,
294
+ [data-bones-auto="off"],
295
+ [data-bones-auto="off"] *
296
+ ):not(
297
+ img,
298
+ svg,
299
+ video,
300
+ canvas,
301
+ picture,
302
+ iframe,
303
+ embed,
304
+ object,
305
+ audio,
306
+ button,
307
+ input,
308
+ select,
309
+ textarea,
310
+ progress,
311
+ meter,
312
+ hr,
313
+ br,
314
+ svg *,
315
+ picture *,
316
+ select *,
317
+ object *
318
+ )::before,
319
+ [aria-busy="true"]
320
+ :not(:has(*)):not(
321
+ [data-bone],
322
+ [data-bone] *,
323
+ [data-bones-auto="off"],
324
+ [data-bones-auto="off"] *
325
+ ):not(
326
+ img,
327
+ svg,
328
+ video,
329
+ canvas,
330
+ picture,
331
+ iframe,
332
+ embed,
333
+ object,
334
+ audio,
335
+ button,
336
+ input,
337
+ select,
338
+ textarea,
339
+ progress,
340
+ meter,
341
+ hr,
342
+ br,
343
+ svg *,
344
+ picture *,
345
+ select *,
346
+ object *
347
+ )::after,
348
+ [aria-busy="true"]
349
+ :is(
350
+ img,
351
+ svg,
352
+ video,
353
+ canvas,
354
+ picture,
355
+ iframe,
356
+ embed,
357
+ object,
358
+ audio,
359
+ button,
360
+ input,
361
+ select,
362
+ textarea,
363
+ progress,
364
+ meter
365
+ ):not([data-bone], [data-bone] *, [data-bones-auto="off"], [data-bones-auto="off"] *) {
366
+ animation: bone-shimmer var(--bone-duration) ease-in-out infinite;
367
+ background: linear-gradient(
368
+ 90deg,
369
+ var(--bone-base) 25%,
370
+ var(--bone-highlight) 50%,
371
+ var(--bone-base) 75%
372
+ );
373
+ background-size: 200% 100%;
374
+ }
375
+
376
+ @scope ([data-bone-animate="shimmer"]) to ([data-bone-animate]:not([data-bone-animate="shimmer"])) {
377
+ [aria-busy="true"]
378
+ :not(:has(*)):not(
379
+ [data-bone],
380
+ [data-bone] *,
381
+ [data-bones-auto="off"],
382
+ [data-bones-auto="off"] *
383
+ ):not(
384
+ img,
385
+ svg,
386
+ video,
387
+ canvas,
388
+ picture,
389
+ iframe,
390
+ embed,
391
+ object,
392
+ audio,
393
+ button,
394
+ input,
395
+ select,
396
+ textarea,
397
+ progress,
398
+ meter,
399
+ hr,
400
+ br,
401
+ svg *,
402
+ picture *,
403
+ select *,
404
+ object *
405
+ )::before,
406
+ [aria-busy="true"]
407
+ :not(:has(*)):not(
408
+ [data-bone],
409
+ [data-bone] *,
410
+ [data-bones-auto="off"],
411
+ [data-bones-auto="off"] *
412
+ ):not(
413
+ img,
414
+ svg,
415
+ video,
416
+ canvas,
417
+ picture,
418
+ iframe,
419
+ embed,
420
+ object,
421
+ audio,
422
+ button,
423
+ input,
424
+ select,
425
+ textarea,
426
+ progress,
427
+ meter,
428
+ hr,
429
+ br,
430
+ svg *,
431
+ picture *,
432
+ select *,
433
+ object *
434
+ )::after,
435
+ [aria-busy="true"]
436
+ :is(
437
+ img,
438
+ svg,
439
+ video,
440
+ canvas,
441
+ picture,
442
+ iframe,
443
+ embed,
444
+ object,
445
+ audio,
446
+ button,
447
+ input,
448
+ select,
449
+ textarea,
450
+ progress,
451
+ meter
452
+ ):not([data-bone], [data-bone] *, [data-bones-auto="off"], [data-bones-auto="off"] *) {
453
+ animation: bone-shimmer var(--bone-duration) ease-in-out infinite;
454
+ background: linear-gradient(
455
+ 90deg,
456
+ var(--bone-base) 25%,
457
+ var(--bone-highlight) 50%,
458
+ var(--bone-base) 75%
459
+ );
460
+ background-size: 200% 100%;
461
+ }
462
+
463
+ @media (prefers-reduced-motion: reduce) {
464
+ [aria-busy="true"]
465
+ :not(:has(*)):not(
466
+ [data-bone],
467
+ [data-bone] *,
468
+ [data-bones-auto="off"],
469
+ [data-bones-auto="off"] *
470
+ ):not(
471
+ img,
472
+ svg,
473
+ video,
474
+ canvas,
475
+ picture,
476
+ iframe,
477
+ embed,
478
+ object,
479
+ audio,
480
+ button,
481
+ input,
482
+ select,
483
+ textarea,
484
+ progress,
485
+ meter,
486
+ hr,
487
+ br,
488
+ svg *,
489
+ picture *,
490
+ select *,
491
+ object *
492
+ )::before,
493
+ [aria-busy="true"]
494
+ :not(:has(*)):not(
495
+ [data-bone],
496
+ [data-bone] *,
497
+ [data-bones-auto="off"],
498
+ [data-bones-auto="off"] *
499
+ ):not(
500
+ img,
501
+ svg,
502
+ video,
503
+ canvas,
504
+ picture,
505
+ iframe,
506
+ embed,
507
+ object,
508
+ audio,
509
+ button,
510
+ input,
511
+ select,
512
+ textarea,
513
+ progress,
514
+ meter,
515
+ hr,
516
+ br,
517
+ svg *,
518
+ picture *,
519
+ select *,
520
+ object *
521
+ )::after,
522
+ [aria-busy="true"]
523
+ :is(
524
+ img,
525
+ svg,
526
+ video,
527
+ canvas,
528
+ picture,
529
+ iframe,
530
+ embed,
531
+ object,
532
+ audio,
533
+ button,
534
+ input,
535
+ select,
536
+ textarea,
537
+ progress,
538
+ meter
539
+ ):not([data-bone], [data-bone] *, [data-bones-auto="off"], [data-bones-auto="off"] *) {
540
+ animation: bone-pulse 2s ease-in-out infinite;
541
+ background: var(--bone-base);
542
+ background-size: auto;
543
+ }
544
+ }
545
+
546
+ @media (forced-colors: active) {
547
+ [aria-busy="true"]
548
+ :not(:has(*)):not(
549
+ [data-bone],
550
+ [data-bone] *,
551
+ [data-bones-auto="off"],
552
+ [data-bones-auto="off"] *
553
+ ):not(
554
+ img,
555
+ svg,
556
+ video,
557
+ canvas,
558
+ picture,
559
+ iframe,
560
+ embed,
561
+ object,
562
+ audio,
563
+ button,
564
+ input,
565
+ select,
566
+ textarea,
567
+ progress,
568
+ meter,
569
+ hr,
570
+ br,
571
+ svg *,
572
+ picture *,
573
+ select *,
574
+ object *
575
+ )::after,
576
+ [aria-busy="true"]
577
+ :is(
578
+ img,
579
+ svg,
580
+ video,
581
+ canvas,
582
+ picture,
583
+ iframe,
584
+ embed,
585
+ object,
586
+ audio,
587
+ button,
588
+ input,
589
+ select,
590
+ textarea,
591
+ progress,
592
+ meter
593
+ ):not([data-bone], [data-bone] *, [data-bones-auto="off"], [data-bones-auto="off"] *) {
594
+ background-color: GrayText;
595
+ forced-color-adjust: none;
596
+ }
597
+ }
598
+ }
599
+
600
+ @scope ([data-bone-animate="pulse"]) to ([data-bone-animate]:not([data-bone-animate="pulse"])) {
601
+ [aria-busy="true"]
602
+ :not(:has(*)):not(
603
+ [data-bone],
604
+ [data-bone] *,
605
+ [data-bones-auto="off"],
606
+ [data-bones-auto="off"] *
607
+ ):not(
608
+ img,
609
+ svg,
610
+ video,
611
+ canvas,
612
+ picture,
613
+ iframe,
614
+ embed,
615
+ object,
616
+ audio,
617
+ button,
618
+ input,
619
+ select,
620
+ textarea,
621
+ progress,
622
+ meter,
623
+ hr,
624
+ br,
625
+ svg *,
626
+ picture *,
627
+ select *,
628
+ object *
629
+ )::before,
630
+ [aria-busy="true"]
631
+ :not(:has(*)):not(
632
+ [data-bone],
633
+ [data-bone] *,
634
+ [data-bones-auto="off"],
635
+ [data-bones-auto="off"] *
636
+ ):not(
637
+ img,
638
+ svg,
639
+ video,
640
+ canvas,
641
+ picture,
642
+ iframe,
643
+ embed,
644
+ object,
645
+ audio,
646
+ button,
647
+ input,
648
+ select,
649
+ textarea,
650
+ progress,
651
+ meter,
652
+ hr,
653
+ br,
654
+ svg *,
655
+ picture *,
656
+ select *,
657
+ object *
658
+ )::after,
659
+ [aria-busy="true"]
660
+ :is(
661
+ img,
662
+ svg,
663
+ video,
664
+ canvas,
665
+ picture,
666
+ iframe,
667
+ embed,
668
+ object,
669
+ audio,
670
+ button,
671
+ input,
672
+ select,
673
+ textarea,
674
+ progress,
675
+ meter
676
+ ):not([data-bone], [data-bone] *, [data-bones-auto="off"], [data-bones-auto="off"] *) {
677
+ animation: bone-pulse var(--bone-duration) ease-in-out infinite;
678
+ background: var(--bone-base);
679
+ background-size: auto;
680
+ }
681
+
682
+ @media (prefers-reduced-motion: reduce) {
683
+ [aria-busy="true"]
684
+ :not(:has(*)):not(
685
+ [data-bone],
686
+ [data-bone] *,
687
+ [data-bones-auto="off"],
688
+ [data-bones-auto="off"] *
689
+ ):not(
690
+ img,
691
+ svg,
692
+ video,
693
+ canvas,
694
+ picture,
695
+ iframe,
696
+ embed,
697
+ object,
698
+ audio,
699
+ button,
700
+ input,
701
+ select,
702
+ textarea,
703
+ progress,
704
+ meter,
705
+ hr,
706
+ br,
707
+ svg *,
708
+ picture *,
709
+ select *,
710
+ object *
711
+ )::before,
712
+ [aria-busy="true"]
713
+ :not(:has(*)):not(
714
+ [data-bone],
715
+ [data-bone] *,
716
+ [data-bones-auto="off"],
717
+ [data-bones-auto="off"] *
718
+ ):not(
719
+ img,
720
+ svg,
721
+ video,
722
+ canvas,
723
+ picture,
724
+ iframe,
725
+ embed,
726
+ object,
727
+ audio,
728
+ button,
729
+ input,
730
+ select,
731
+ textarea,
732
+ progress,
733
+ meter,
734
+ hr,
735
+ br,
736
+ svg *,
737
+ picture *,
738
+ select *,
739
+ object *
740
+ )::after,
741
+ [aria-busy="true"]
742
+ :is(
743
+ img,
744
+ svg,
745
+ video,
746
+ canvas,
747
+ picture,
748
+ iframe,
749
+ embed,
750
+ object,
751
+ audio,
752
+ button,
753
+ input,
754
+ select,
755
+ textarea,
756
+ progress,
757
+ meter
758
+ ):not([data-bone], [data-bone] *, [data-bones-auto="off"], [data-bones-auto="off"] *) {
759
+ animation: bone-pulse 2s ease-in-out infinite;
760
+ background: var(--bone-base);
761
+ background-size: auto;
762
+ }
763
+ }
764
+
765
+ @media (forced-colors: active) {
766
+ [aria-busy="true"]
767
+ :not(:has(*)):not(
768
+ [data-bone],
769
+ [data-bone] *,
770
+ [data-bones-auto="off"],
771
+ [data-bones-auto="off"] *
772
+ ):not(
773
+ img,
774
+ svg,
775
+ video,
776
+ canvas,
777
+ picture,
778
+ iframe,
779
+ embed,
780
+ object,
781
+ audio,
782
+ button,
783
+ input,
784
+ select,
785
+ textarea,
786
+ progress,
787
+ meter,
788
+ hr,
789
+ br,
790
+ svg *,
791
+ picture *,
792
+ select *,
793
+ object *
794
+ )::after,
795
+ [aria-busy="true"]
796
+ :is(
797
+ img,
798
+ svg,
799
+ video,
800
+ canvas,
801
+ picture,
802
+ iframe,
803
+ embed,
804
+ object,
805
+ audio,
806
+ button,
807
+ input,
808
+ select,
809
+ textarea,
810
+ progress,
811
+ meter
812
+ ):not([data-bone], [data-bone] *, [data-bones-auto="off"], [data-bones-auto="off"] *) {
813
+ background-color: GrayText;
814
+ forced-color-adjust: none;
815
+ }
816
+ }
817
+ }
818
+
819
+ @scope ([data-bone-animate="none"]) to ([data-bone-animate]:not([data-bone-animate="none"])) {
820
+ [aria-busy="true"]
821
+ :not(:has(*)):not(
822
+ [data-bone],
823
+ [data-bone] *,
824
+ [data-bones-auto="off"],
825
+ [data-bones-auto="off"] *
826
+ ):not(
827
+ img,
828
+ svg,
829
+ video,
830
+ canvas,
831
+ picture,
832
+ iframe,
833
+ embed,
834
+ object,
835
+ audio,
836
+ button,
837
+ input,
838
+ select,
839
+ textarea,
840
+ progress,
841
+ meter,
842
+ hr,
843
+ br,
844
+ svg *,
845
+ picture *,
846
+ select *,
847
+ object *
848
+ )::before,
849
+ [aria-busy="true"]
850
+ :not(:has(*)):not(
851
+ [data-bone],
852
+ [data-bone] *,
853
+ [data-bones-auto="off"],
854
+ [data-bones-auto="off"] *
855
+ ):not(
856
+ img,
857
+ svg,
858
+ video,
859
+ canvas,
860
+ picture,
861
+ iframe,
862
+ embed,
863
+ object,
864
+ audio,
865
+ button,
866
+ input,
867
+ select,
868
+ textarea,
869
+ progress,
870
+ meter,
871
+ hr,
872
+ br,
873
+ svg *,
874
+ picture *,
875
+ select *,
876
+ object *
877
+ )::after,
878
+ [aria-busy="true"]
879
+ :is(
880
+ img,
881
+ svg,
882
+ video,
883
+ canvas,
884
+ picture,
885
+ iframe,
886
+ embed,
887
+ object,
888
+ audio,
889
+ button,
890
+ input,
891
+ select,
892
+ textarea,
893
+ progress,
894
+ meter
895
+ ):not([data-bone], [data-bone] *, [data-bones-auto="off"], [data-bones-auto="off"] *) {
896
+ animation: none;
897
+ background: var(--bone-base);
898
+ background-size: auto;
899
+ }
900
+
901
+ @media (forced-colors: active) {
902
+ [aria-busy="true"]
903
+ :not(:has(*)):not(
904
+ [data-bone],
905
+ [data-bone] *,
906
+ [data-bones-auto="off"],
907
+ [data-bones-auto="off"] *
908
+ ):not(
909
+ img,
910
+ svg,
911
+ video,
912
+ canvas,
913
+ picture,
914
+ iframe,
915
+ embed,
916
+ object,
917
+ audio,
918
+ button,
919
+ input,
920
+ select,
921
+ textarea,
922
+ progress,
923
+ meter,
924
+ hr,
925
+ br,
926
+ svg *,
927
+ picture *,
928
+ select *,
929
+ object *
930
+ )::after,
931
+ [aria-busy="true"]
932
+ :is(
933
+ img,
934
+ svg,
935
+ video,
936
+ canvas,
937
+ picture,
938
+ iframe,
939
+ embed,
940
+ object,
941
+ audio,
942
+ button,
943
+ input,
944
+ select,
945
+ textarea,
946
+ progress,
947
+ meter
948
+ ):not([data-bone], [data-bone] *, [data-bones-auto="off"], [data-bones-auto="off"] *) {
949
+ background-color: GrayText;
950
+ forced-color-adjust: none;
951
+ }
952
+ }
953
+ }
954
+
955
+ @media (prefers-reduced-motion: reduce) {
956
+ [aria-busy="true"]
957
+ :not(:has(*)):not(
958
+ [data-bone],
959
+ [data-bone] *,
960
+ [data-bones-auto="off"],
961
+ [data-bones-auto="off"] *
962
+ ):not(
963
+ img,
964
+ svg,
965
+ video,
966
+ canvas,
967
+ picture,
968
+ iframe,
969
+ embed,
970
+ object,
971
+ audio,
972
+ button,
973
+ input,
974
+ select,
975
+ textarea,
976
+ progress,
977
+ meter,
978
+ hr,
979
+ br,
980
+ svg *,
981
+ picture *,
982
+ select *,
983
+ object *
984
+ )::before,
985
+ [aria-busy="true"]
986
+ :not(:has(*)):not(
987
+ [data-bone],
988
+ [data-bone] *,
989
+ [data-bones-auto="off"],
990
+ [data-bones-auto="off"] *
991
+ ):not(
992
+ img,
993
+ svg,
994
+ video,
995
+ canvas,
996
+ picture,
997
+ iframe,
998
+ embed,
999
+ object,
1000
+ audio,
1001
+ button,
1002
+ input,
1003
+ select,
1004
+ textarea,
1005
+ progress,
1006
+ meter,
1007
+ hr,
1008
+ br,
1009
+ svg *,
1010
+ picture *,
1011
+ select *,
1012
+ object *
1013
+ )::after,
1014
+ [aria-busy="true"]
1015
+ :is(
1016
+ img,
1017
+ svg,
1018
+ video,
1019
+ canvas,
1020
+ picture,
1021
+ iframe,
1022
+ embed,
1023
+ object,
1024
+ audio,
1025
+ button,
1026
+ input,
1027
+ select,
1028
+ textarea,
1029
+ progress,
1030
+ meter
1031
+ ):not([data-bone], [data-bone] *, [data-bones-auto="off"], [data-bones-auto="off"] *) {
1032
+ animation: bone-pulse 2s ease-in-out infinite;
1033
+ background: var(--bone-base);
1034
+ background-size: auto;
1035
+ }
1036
+ }
1037
+
1038
+ /* High-contrast modes strip author backgrounds; keep bones visible with a
1039
+ system color and opt the surfaces out of forced-color adjustment. */
1040
+ @media (forced-colors: active) {
1041
+ [aria-busy="true"]
1042
+ :not(:has(*)):not(
1043
+ [data-bone],
1044
+ [data-bone] *,
1045
+ [data-bones-auto="off"],
1046
+ [data-bones-auto="off"] *
1047
+ ):not(
1048
+ img,
1049
+ svg,
1050
+ video,
1051
+ canvas,
1052
+ picture,
1053
+ iframe,
1054
+ embed,
1055
+ object,
1056
+ audio,
1057
+ button,
1058
+ input,
1059
+ select,
1060
+ textarea,
1061
+ progress,
1062
+ meter,
1063
+ hr,
1064
+ br,
1065
+ svg *,
1066
+ picture *,
1067
+ select *,
1068
+ object *
1069
+ )::after,
1070
+ [aria-busy="true"]
1071
+ :is(
1072
+ img,
1073
+ svg,
1074
+ video,
1075
+ canvas,
1076
+ picture,
1077
+ iframe,
1078
+ embed,
1079
+ object,
1080
+ audio,
1081
+ button,
1082
+ input,
1083
+ select,
1084
+ textarea,
1085
+ progress,
1086
+ meter
1087
+ ):not([data-bone], [data-bone] *, [data-bones-auto="off"], [data-bones-auto="off"] *) {
1088
+ background-color: GrayText;
1089
+ forced-color-adjust: none;
1090
+ }
1091
+ }
1092
+ }