fresh-normalize 0.0.0-semantic

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,1130 @@
1
+ /*! fresh-normalize v1.0.0 | MIT License | https://github.com/YOUR_USERNAME/fresh-normalize */
2
+
3
+ /*
4
+ * fresh-normalize — A modern CSS normalization library for 2026
5
+ *
6
+ * Philosophy:
7
+ * ✦ Target evergreen browsers only (Chrome 120+, Firefox 120+, Safari 17+, Edge 120+)
8
+ * ✦ No IE / legacy browser hacks
9
+ * ✦ Normalize browser inconsistencies — never impose design opinions
10
+ * ✦ Uses CSS custom properties for easy theming (all overridable)
11
+ * ✦ Respects prefers-reduced-motion and prefers-color-scheme
12
+ * ✦ Accessibility-first defaults
13
+ *
14
+ * Sections:
15
+ * 1. CSS Custom Properties (Design Tokens)
16
+ * 2. Box Model
17
+ * 3. Document & Root
18
+ * 4. Sections
19
+ * 5. Typography
20
+ * 6. Lists
21
+ * 7. Links
22
+ * 8. Embedded Content (Media)
23
+ * 9. Tables
24
+ * 10. Forms
25
+ * 11. Interactive
26
+ * 12. Accessibility
27
+ * 13. Scrollbar
28
+ * 14. Motion
29
+ * 15. Print
30
+ */
31
+
32
+ /* ==========================================================================
33
+ 1. CSS Custom Properties (Design Tokens)
34
+ ========================================================================== */
35
+
36
+ /**
37
+ * Global design tokens exposed as CSS custom properties.
38
+ * Override these in your :root to theme the normalizations.
39
+ */
40
+
41
+ :root {
42
+ /* Typography */
43
+ --fn-font-sans:
44
+ system-ui, ui-sans-serif, "Segoe UI", roboto, helvetica, arial, sans-serif,
45
+ "Apple Color Emoji", "Segoe UI Emoji";
46
+ --fn-font-mono:
47
+ ui-monospace, "Cascadia Code", "Source Code Pro", menlo, consolas, "DejaVu Sans Mono",
48
+ monospace;
49
+ --fn-font-serif: ui-serif, georgia, cambria, "Times New Roman", times, serif;
50
+
51
+ /* Sizing */
52
+ --fn-tab-size: 4;
53
+ --fn-line-height: 1.5;
54
+ --fn-heading-line-height: 1.2;
55
+
56
+ /* Focus */
57
+ --fn-focus-color: #005fcc;
58
+ --fn-focus-width: 3px;
59
+ --fn-focus-offset: 2px;
60
+
61
+ /* Color (light mode defaults) */
62
+ --fn-text-color: #1a1a1a;
63
+ --fn-bg-color: #fff;
64
+ --fn-link-color: #005fcc;
65
+ --fn-link-visited-color: #7c3aed;
66
+ --fn-border-color: #d1d5db;
67
+ --fn-mark-bg: #fef08a;
68
+ --fn-mark-color: #1a1a1a;
69
+ --fn-selection-bg: #bfdbfe;
70
+ --fn-selection-color: #1e3a5f;
71
+
72
+ /* Scrollbar */
73
+ --fn-scrollbar-width: thin;
74
+ --fn-scrollbar-track: #f1f5f9;
75
+ --fn-scrollbar-thumb: #94a3b8;
76
+ --fn-scrollbar-thumb-hover: #64748b;
77
+
78
+ /* Forms */
79
+ --fn-accent-color: #005fcc;
80
+ --fn-caret-color: #005fcc;
81
+ --fn-error-color: #dc2626;
82
+ --fn-success-color: #16a34a;
83
+ }
84
+
85
+ /* Dark mode tokens (auto-applied via prefers-color-scheme) */
86
+ @media (prefers-color-scheme: dark) {
87
+ :root {
88
+ --fn-text-color: #f1f5f9;
89
+ --fn-bg-color: #0f172a;
90
+ --fn-link-color: #60a5fa;
91
+ --fn-link-visited-color: #c084fc;
92
+ --fn-border-color: #334155;
93
+ --fn-mark-bg: #854d0e;
94
+ --fn-mark-color: #fef9c3;
95
+ --fn-selection-bg: #1e40af;
96
+ --fn-selection-color: #dbeafe;
97
+ --fn-scrollbar-track: #1e293b;
98
+ --fn-scrollbar-thumb: #475569;
99
+ --fn-scrollbar-thumb-hover: #64748b;
100
+ }
101
+ }
102
+
103
+ /* ==========================================================================
104
+ 2. Box Model
105
+ ========================================================================== */
106
+
107
+ /**
108
+ * Use border-box for all elements.
109
+ */
110
+
111
+ *,
112
+ ::before,
113
+ ::after {
114
+ box-sizing: border-box;
115
+ }
116
+
117
+ /* ==========================================================================
118
+ 3. Document & Root
119
+ ========================================================================== */
120
+
121
+ /**
122
+ * 1. Set font stack consistently across all browsers.
123
+ * 2. Set a sensible base line-height.
124
+ * 3. Prevent font size changes after orientation change on iOS.
125
+ * 4. Use a readable tab size.
126
+ * 5. Enable smooth scrolling unless the user prefers reduced motion.
127
+ * 6. Force scrollbar to prevent layout shifts.
128
+ * 7. Set text rendering for best legibility.
129
+ * 8. Enable CSS color-scheme for proper system color integration.
130
+ * 9. Remove mobile tap highlight.
131
+ * 10. Disable double-tap zoom.
132
+ * 11. Better punctuation handling at line starts/ends.
133
+ * 12. Better text wrapping algorithm (Safari 17+).
134
+ * 13. Prevent breaking words mid-word.
135
+ * 14. Prevent content overflow.
136
+ * 15. Set accent and caret colors globally.
137
+ */
138
+
139
+ html {
140
+ font-family: var(--fn-font-sans); /* 1 */
141
+ line-height: var(--fn-line-height); /* 2 */
142
+ -webkit-text-size-adjust: 100%; /* 3 */
143
+ -moz-text-size-adjust: 100%; /* 3 */
144
+ text-size-adjust: 100%; /* 3 */
145
+ tab-size: var(--fn-tab-size); /* 4 */
146
+ scroll-behavior: smooth; /* 5 */
147
+ scrollbar-gutter: stable; /* 6 */
148
+ text-rendering: optimizeLegibility; /* 7 */
149
+ -webkit-font-smoothing: antialiased; /* 7 */
150
+ -moz-osx-font-smoothing: grayscale; /* 7 */
151
+ color-scheme: light dark; /* 8 */
152
+ -webkit-tap-highlight-color: transparent; /* 9 */
153
+ touch-action: manipulation; /* 10 */
154
+ hanging-punctuation: first last; /* 11 */
155
+ text-wrap: pretty; /* 12 */
156
+ word-break: normal; /* 13 */
157
+ overflow-wrap: anywhere; /* 14 */
158
+ accent-color: var(--fn-accent-color); /* 15 */
159
+ caret-color: var(--fn-caret-color); /* 15 */
160
+ }
161
+
162
+ /* ==========================================================================
163
+ 4. Sections
164
+ ========================================================================== */
165
+
166
+ /**
167
+ * Remove the margin in all browsers.
168
+ */
169
+
170
+ body {
171
+ margin: 0;
172
+ color: var(--fn-text-color);
173
+ background-color: var(--fn-bg-color);
174
+ min-block-size: 100vh;
175
+ min-block-size: 100dvh;
176
+ text-underline-offset: 0.1em;
177
+ }
178
+
179
+ /**
180
+ * Correct the font size and margin on h1 elements within section/article contexts.
181
+ */
182
+
183
+ h1 {
184
+ font-size: 2em;
185
+ margin-block: 0.67em;
186
+ }
187
+
188
+ /**
189
+ * Consistent heading line heights.
190
+ */
191
+
192
+ h1,
193
+ h2,
194
+ h3,
195
+ h4,
196
+ h5,
197
+ h6 {
198
+ line-height: var(--fn-heading-line-height);
199
+ }
200
+
201
+ /* ==========================================================================
202
+ 5. Typography
203
+ ========================================================================== */
204
+
205
+ /**
206
+ * Add the correct font weight in all browsers.
207
+ */
208
+
209
+ b,
210
+ strong {
211
+ font-weight: bolder;
212
+ }
213
+
214
+ /**
215
+ * 1. Use a consistent monospace font stack.
216
+ * 2. Correct the odd em font sizing in all browsers.
217
+ */
218
+
219
+ code,
220
+ kbd,
221
+ samp,
222
+ pre {
223
+ font-family: var(--fn-font-mono); /* 1 */
224
+ font-size: 1em; /* 2 */
225
+ }
226
+
227
+ /**
228
+ * Add the correct font size in all browsers.
229
+ */
230
+
231
+ small {
232
+ font-size: 80%;
233
+ }
234
+
235
+ /**
236
+ * Prevent sub and sup elements from affecting the line height.
237
+ */
238
+
239
+ sub,
240
+ sup {
241
+ font-size: 75%;
242
+ line-height: 0;
243
+ position: relative;
244
+ vertical-align: baseline;
245
+ }
246
+
247
+ sub {
248
+ bottom: -0.25em;
249
+ }
250
+
251
+ sup {
252
+ top: -0.5em;
253
+ }
254
+
255
+ /**
256
+ * Correct the text decoration on abbreviations.
257
+ */
258
+
259
+ abbr[title] {
260
+ text-decoration: underline dotted;
261
+ cursor: help;
262
+ }
263
+
264
+ /**
265
+ * Quotes — let browser handle per language.
266
+ */
267
+
268
+ q {
269
+ quotes: auto;
270
+ }
271
+
272
+ /**
273
+ * Horizontal rule normalization.
274
+ */
275
+
276
+ hr {
277
+ border: none;
278
+ border-block-start: 1px solid var(--fn-border-color);
279
+ margin-block: 1em;
280
+ color: inherit;
281
+ height: 0;
282
+ }
283
+
284
+ /**
285
+ * Prevent overflow on long words in containers.
286
+ */
287
+
288
+ p,
289
+ h1,
290
+ h2,
291
+ h3,
292
+ h4,
293
+ h5,
294
+ h6 {
295
+ overflow-wrap: break-word;
296
+ }
297
+
298
+ /**
299
+ * Consistent text selection styling.
300
+ */
301
+
302
+ ::selection {
303
+ background-color: var(--fn-selection-bg, #bfdbfe);
304
+ color: var(--fn-selection-color, #1e3a5f);
305
+ text-shadow: none;
306
+ }
307
+
308
+ /**
309
+ * Mark/highlight element.
310
+ */
311
+
312
+ mark {
313
+ background-color: var(--fn-mark-bg, #fef08a);
314
+ color: var(--fn-mark-color, #1a1a1a);
315
+ padding-inline: 0.25em;
316
+ border-radius: 2px;
317
+ }
318
+
319
+ /**
320
+ * Definition element.
321
+ */
322
+
323
+ dfn {
324
+ font-style: italic;
325
+ font-weight: 500;
326
+ }
327
+
328
+ /**
329
+ * Address element — normalize margins.
330
+ */
331
+
332
+ address {
333
+ font-style: normal;
334
+ margin-block: 0;
335
+ }
336
+
337
+ /**
338
+ * Insertion and deletion elements.
339
+ */
340
+
341
+ ins {
342
+ text-decoration: none;
343
+ background-color: #bbf7d0;
344
+ color: #166534;
345
+ }
346
+
347
+ del {
348
+ text-decoration: line-through;
349
+ background-color: #fecaca;
350
+ color: #991b1b;
351
+ }
352
+
353
+ /**
354
+ * Bidirectional text isolation.
355
+ */
356
+
357
+ bdi {
358
+ unicode-bidi: isolate;
359
+ }
360
+
361
+ bdo {
362
+ unicode-bidi: bidi-override;
363
+ }
364
+
365
+ /* ==========================================================================
366
+ 6. Lists
367
+ ========================================================================== */
368
+
369
+ /**
370
+ * Remove default list styles for nav lists and role=list.
371
+ */
372
+
373
+ nav ol,
374
+ nav ul,
375
+ ol[role="list"],
376
+ ul[role="list"] {
377
+ list-style: none;
378
+ margin: 0;
379
+ padding: 0;
380
+ }
381
+
382
+ /* ==========================================================================
383
+ 7. Links
384
+ ========================================================================== */
385
+
386
+ /**
387
+ * 1. Remove the gray background on active links in older browsers.
388
+ * 2. Apply link color token.
389
+ */
390
+
391
+ a {
392
+ background-color: transparent; /* 1 */
393
+ color: var(--fn-link-color); /* 2 */
394
+ }
395
+
396
+ a:visited {
397
+ color: var(--fn-link-visited-color);
398
+ }
399
+
400
+ /**
401
+ * Improve focus visibility for keyboard users.
402
+ */
403
+
404
+ a:focus-visible {
405
+ outline: var(--fn-focus-width) solid var(--fn-focus-color);
406
+ outline-offset: var(--fn-focus-offset);
407
+ border-radius: 2px;
408
+ }
409
+
410
+ /* ==========================================================================
411
+ 8. Embedded Content (Media)
412
+ ========================================================================== */
413
+
414
+ /**
415
+ * 1. Remove the border on images inside links.
416
+ * 2. Remove the gap below images (inline → block).
417
+ * 3. Fix descender gap on inline media.
418
+ */
419
+
420
+ img,
421
+ svg,
422
+ video,
423
+ canvas,
424
+ audio,
425
+ iframe,
426
+ embed,
427
+ object {
428
+ display: inline-block; /* 2 */
429
+ vertical-align: middle; /* 3 */
430
+ }
431
+
432
+ /**
433
+ * Constrain media to their container widths (responsive defaults).
434
+ */
435
+
436
+ img,
437
+ video,
438
+ canvas {
439
+ max-inline-size: 100%;
440
+ block-size: auto;
441
+ }
442
+
443
+ /**
444
+ * Remove border on images.
445
+ */
446
+
447
+ img {
448
+ border-style: none; /* 1 */
449
+ }
450
+
451
+ /**
452
+ * Prevent SVG overflow in older browsers.
453
+ */
454
+
455
+ svg {
456
+ overflow: hidden;
457
+ }
458
+
459
+ /**
460
+ * Hide audio with no controls.
461
+ */
462
+
463
+ audio:not([controls]) {
464
+ display: none;
465
+ height: 0;
466
+ }
467
+
468
+ /**
469
+ * Figure and figcaption normalization.
470
+ */
471
+
472
+ figure {
473
+ margin: 0;
474
+ padding: 0;
475
+ }
476
+
477
+ figcaption {
478
+ font-size: 0.875em;
479
+ font-style: italic;
480
+ }
481
+
482
+ /**
483
+ * Picture element — maintain responsiveness.
484
+ */
485
+
486
+ picture {
487
+ display: contents;
488
+ }
489
+
490
+ /* ==========================================================================
491
+ 9. Tables
492
+ ========================================================================== */
493
+
494
+ /**
495
+ * 1. Correct table border color inheritance in Chrome and Safari.
496
+ * 2. Collapse borders by default.
497
+ * 3. Fix spacing inconsistencies.
498
+ */
499
+
500
+ table {
501
+ border-color: currentColor; /* 1 */
502
+ border-collapse: collapse; /* 2 */
503
+ border-spacing: 0; /* 3 */
504
+ }
505
+
506
+ /**
507
+ * Normalize table cell padding and alignment.
508
+ */
509
+
510
+ td,
511
+ th {
512
+ padding: 0;
513
+ text-align: left;
514
+ }
515
+
516
+ /* ==========================================================================
517
+ 10. Forms
518
+ ========================================================================== */
519
+
520
+ /**
521
+ * 1. Change font styles in all browsers.
522
+ * 2. Remove margin in Firefox and Safari.
523
+ * 3. Set a consistent line-height.
524
+ */
525
+
526
+ button,
527
+ input,
528
+ optgroup,
529
+ select,
530
+ textarea {
531
+ font-family: inherit; /* 1 */
532
+ font-size: 100%; /* 1 */
533
+ line-height: 1.15; /* 3 */
534
+ margin: 0; /* 2 */
535
+ color: inherit; /* 1 */
536
+ }
537
+
538
+ /**
539
+ * Correct the inability to style clickable types in iOS and Safari.
540
+ */
541
+
542
+ button,
543
+ [type="button"],
544
+ [type="reset"],
545
+ [type="submit"] {
546
+ -webkit-appearance: button;
547
+ appearance: auto;
548
+ cursor: pointer;
549
+ }
550
+
551
+ /**
552
+ * 1. Remove padding in fieldset.
553
+ * 2. Remove the default border.
554
+ */
555
+
556
+ fieldset {
557
+ border: 0; /* 2 */
558
+ margin: 0; /* 1 */
559
+ padding: 0; /* 1 */
560
+ }
561
+
562
+ /**
563
+ * Normalize legend.
564
+ */
565
+
566
+ legend {
567
+ padding: 0;
568
+ max-inline-size: 100%;
569
+ white-space: normal;
570
+ }
571
+
572
+ /**
573
+ * Add the correct vertical alignment in Chrome and Firefox.
574
+ */
575
+
576
+ progress {
577
+ vertical-align: baseline;
578
+ }
579
+
580
+ /**
581
+ * Correct the cursor style of spin buttons in Safari.
582
+ */
583
+
584
+ ::-webkit-inner-spin-button,
585
+ ::-webkit-outer-spin-button {
586
+ height: auto;
587
+ }
588
+
589
+ /**
590
+ * 1. Correct odd appearance in Chrome and Safari.
591
+ * 2. Correct outline style in Safari.
592
+ */
593
+
594
+ [type="search"] {
595
+ -webkit-appearance: textfield; /* 1 */
596
+ appearance: textfield; /* 1 */
597
+ outline-offset: -2px; /* 2 */
598
+ }
599
+
600
+ /**
601
+ * Remove inner padding in Chrome and Safari on macOS.
602
+ */
603
+
604
+ ::-webkit-search-decoration {
605
+ -webkit-appearance: none;
606
+ }
607
+
608
+ /**
609
+ * 1. Fix clickable types in iOS and Safari.
610
+ * 2. Change font properties to inherit in Safari.
611
+ */
612
+
613
+ ::-webkit-file-upload-button {
614
+ -webkit-appearance: button; /* 1 */
615
+ font: inherit; /* 2 */
616
+ }
617
+
618
+ /**
619
+ * Modern file input reset.
620
+ */
621
+
622
+ ::file-selector-button {
623
+ font: inherit;
624
+ -webkit-appearance: button;
625
+ appearance: auto;
626
+ }
627
+
628
+ /**
629
+ * Vertical resize only for textarea.
630
+ */
631
+
632
+ textarea {
633
+ resize: vertical;
634
+ overflow: auto;
635
+ }
636
+
637
+ /**
638
+ * Normalize placeholder opacity in Firefox.
639
+ */
640
+
641
+ ::placeholder {
642
+ opacity: 54%;
643
+ color: inherit;
644
+ }
645
+
646
+ /**
647
+ * Consistent color swatch sizing.
648
+ */
649
+
650
+ [type="color"] {
651
+ block-size: 2.5em;
652
+ inline-size: 2.5em;
653
+ cursor: pointer;
654
+ padding: 0;
655
+ border: 1px solid var(--fn-border-color);
656
+ border-radius: 4px;
657
+ }
658
+
659
+ /**
660
+ * Range input — consistent cross-browser styling.
661
+ */
662
+
663
+ input[type="range"] {
664
+ -webkit-appearance: none;
665
+ appearance: none;
666
+ background: transparent;
667
+ cursor: pointer;
668
+ inline-size: 100%;
669
+ }
670
+
671
+ input[type="range"]::-webkit-slider-runnable-track {
672
+ background: var(--fn-border-color);
673
+ block-size: 4px;
674
+ border-radius: 2px;
675
+ }
676
+
677
+ input[type="range"]::-webkit-slider-thumb {
678
+ -webkit-appearance: none;
679
+ appearance: none;
680
+ background: var(--fn-link-color);
681
+ block-size: 16px;
682
+ inline-size: 16px;
683
+ border-radius: 50%;
684
+ margin-block-start: -6px;
685
+ border: 2px solid var(--fn-bg-color);
686
+ }
687
+
688
+ input[type="range"]::-moz-range-track {
689
+ background: var(--fn-border-color);
690
+ block-size: 4px;
691
+ border-radius: 2px;
692
+ }
693
+
694
+ input[type="range"]::-moz-range-thumb {
695
+ background: var(--fn-link-color);
696
+ block-size: 16px;
697
+ inline-size: 16px;
698
+ border-radius: 50%;
699
+ border: 2px solid var(--fn-bg-color);
700
+ }
701
+
702
+ /**
703
+ * Date/time input normalization.
704
+ */
705
+
706
+ input[type="date"],
707
+ input[type="time"],
708
+ input[type="datetime-local"],
709
+ input[type="month"],
710
+ input[type="week"] {
711
+ -webkit-appearance: none;
712
+ appearance: none;
713
+ min-block-size: 2.5em;
714
+ }
715
+
716
+ /**
717
+ * Meter element normalization.
718
+ */
719
+
720
+ meter {
721
+ -webkit-appearance: none;
722
+ appearance: none;
723
+ inline-size: 100%;
724
+ block-size: 1em;
725
+ vertical-align: middle;
726
+ border-radius: 4px;
727
+ overflow: hidden;
728
+ }
729
+
730
+ meter::-webkit-meter-bar {
731
+ background: var(--fn-scrollbar-track);
732
+ border-radius: 4px;
733
+ }
734
+
735
+ meter::-webkit-meter-optimum-value {
736
+ background: #22c55e;
737
+ }
738
+
739
+ meter::-webkit-meter-suboptimum-value {
740
+ background: #eab308;
741
+ }
742
+
743
+ meter::-webkit-meter-even-less-good-value {
744
+ background: #ef4444;
745
+ }
746
+
747
+ meter::-moz-meter-bar {
748
+ background: #22c55e;
749
+ border-radius: 4px;
750
+ }
751
+
752
+ /**
753
+ * Output element normalization.
754
+ */
755
+
756
+ output {
757
+ display: inline-block;
758
+ font-family: var(--fn-font-mono);
759
+ font-size: 0.875em;
760
+ }
761
+
762
+ /**
763
+ * Disabled form elements.
764
+ */
765
+
766
+ input:disabled,
767
+ button:disabled,
768
+ select:disabled,
769
+ textarea:disabled,
770
+ optgroup:disabled {
771
+ cursor: not-allowed;
772
+ opacity: 60%;
773
+ }
774
+
775
+ /**
776
+ * Readonly form elements.
777
+ */
778
+
779
+ input:read-only,
780
+ textarea:read-only {
781
+ cursor: default;
782
+ }
783
+
784
+ /**
785
+ * Remove yellow/blue autofill background.
786
+ */
787
+
788
+ input:-webkit-autofill,
789
+ input:-webkit-autofill:hover,
790
+ input:-webkit-autofill:focus,
791
+ textarea:-webkit-autofill,
792
+ textarea:-webkit-autofill:hover,
793
+ textarea:-webkit-autofill:focus,
794
+ select:-webkit-autofill,
795
+ select:-webkit-autofill:hover,
796
+ select:-webkit-autofill:focus {
797
+ -webkit-box-shadow: 0 0 0 1000px var(--fn-bg-color) inset;
798
+ -webkit-text-fill-color: var(--fn-text-color);
799
+ caret-color: var(--fn-text-color);
800
+ transition: background-color 5000s ease-in-out 0s;
801
+ }
802
+
803
+ /**
804
+ * Form validation states.
805
+ */
806
+
807
+ input:user-invalid,
808
+ textarea:user-invalid,
809
+ select:user-invalid {
810
+ border-color: var(--fn-error-color);
811
+ }
812
+
813
+ input:user-valid,
814
+ textarea:user-valid,
815
+ select:user-valid {
816
+ border-color: var(--fn-success-color);
817
+ }
818
+
819
+ /* ==========================================================================
820
+ 11. Interactive
821
+ ========================================================================== */
822
+
823
+ /**
824
+ * Add the correct display in all browsers.
825
+ */
826
+
827
+ summary {
828
+ display: list-item;
829
+ cursor: pointer;
830
+ }
831
+
832
+ details {
833
+ display: block;
834
+ }
835
+
836
+ /**
837
+ * Add the correct display for template and hidden elements.
838
+ */
839
+
840
+ template,
841
+ [hidden] {
842
+ display: none;
843
+ }
844
+
845
+ /**
846
+ * Consistent dialog element styling.
847
+ */
848
+
849
+ dialog {
850
+ background-color: var(--fn-bg-color);
851
+ color: var(--fn-text-color);
852
+ border: 1px solid var(--fn-border-color);
853
+ border-radius: 8px;
854
+ padding: 1.5em;
855
+ max-inline-size: min(90vw, 560px);
856
+ }
857
+
858
+ dialog::backdrop {
859
+ background-color: rgb(0 0 0 / 50%);
860
+ backdrop-filter: blur(2px);
861
+ }
862
+
863
+ /**
864
+ * Normalize popover element (Chrome 114+, Firefox 125+, Safari 17+).
865
+ */
866
+
867
+ :is([popover]) {
868
+ border: 1px solid var(--fn-border-color);
869
+ border-radius: 8px;
870
+ padding: 1em;
871
+ background-color: var(--fn-bg-color);
872
+ color: var(--fn-text-color);
873
+ }
874
+
875
+ /* ==========================================================================
876
+ 12. Accessibility
877
+ ========================================================================== */
878
+
879
+ /**
880
+ * Consistent focus-visible outline for all interactive elements.
881
+ */
882
+
883
+ :focus-visible {
884
+ outline: var(--fn-focus-width) solid var(--fn-focus-color);
885
+ outline-offset: var(--fn-focus-offset);
886
+ }
887
+
888
+ /**
889
+ * Remove focus ring for mouse users.
890
+ */
891
+
892
+ :focus:not(:focus-visible) {
893
+ outline: none;
894
+ }
895
+
896
+ /**
897
+ * Visually hidden — accessible to screen readers only.
898
+ * Usage: <span class="sr-only">Screen reader only text</span>
899
+ */
900
+
901
+ .sr-only {
902
+ clip: rect(0, 0, 0, 0);
903
+ clip-path: inset(50%);
904
+ block-size: 1px;
905
+ inline-size: 1px;
906
+ overflow: hidden;
907
+ position: absolute;
908
+ white-space: nowrap;
909
+ }
910
+
911
+ /**
912
+ * Skip-to-content link for keyboard users.
913
+ * Usage: <a href="#main-content" class="skip-link">Skip to main content</a>
914
+ */
915
+
916
+ .skip-link {
917
+ clip: rect(0, 0, 0, 0);
918
+ clip-path: inset(50%);
919
+ block-size: 1px;
920
+ inline-size: 1px;
921
+ overflow: hidden;
922
+ position: absolute;
923
+ white-space: nowrap;
924
+ }
925
+
926
+ .skip-link:focus {
927
+ clip: auto;
928
+ clip-path: none;
929
+ block-size: auto;
930
+ inline-size: auto;
931
+ background-color: var(--fn-bg-color);
932
+ color: var(--fn-link-color);
933
+ font-weight: bold;
934
+ padding: 0.5em 1em;
935
+ position: fixed;
936
+ inset-block-start: 1em;
937
+ inset-inline-start: 1em;
938
+ z-index: 999;
939
+ border-radius: 4px;
940
+ border: 2px solid var(--fn-focus-color);
941
+ text-decoration: none;
942
+ }
943
+
944
+ /**
945
+ * High contrast mode support.
946
+ */
947
+
948
+ @media (prefers-contrast: more) {
949
+ :root {
950
+ --fn-text-color: #000;
951
+ --fn-bg-color: #fff;
952
+ --fn-border-color: #000;
953
+ --fn-link-color: #00e;
954
+ --fn-link-visited-color: #551a8b;
955
+ --fn-focus-color: #000;
956
+ }
957
+
958
+ ::selection {
959
+ background-color: #000;
960
+ color: #fff;
961
+ }
962
+
963
+ a:focus-visible,
964
+ :focus-visible {
965
+ outline: 3px solid #000;
966
+ outline-offset: 2px;
967
+ }
968
+ }
969
+
970
+ /**
971
+ * Forced colors mode (Windows High Contrast).
972
+ */
973
+
974
+ @media (forced-colors: active) {
975
+ :focus-visible {
976
+ outline: 3px solid CanvasText;
977
+ outline-offset: 2px;
978
+ }
979
+
980
+ .sr-only,
981
+ .skip-link {
982
+ clip: rect(0, 0, 0, 0);
983
+ position: absolute;
984
+ }
985
+
986
+ .skip-link:focus {
987
+ clip: auto;
988
+ position: fixed;
989
+ }
990
+
991
+ button,
992
+ [type="button"],
993
+ [type="reset"],
994
+ [type="submit"] {
995
+ border: 1px solid ButtonText;
996
+ }
997
+
998
+ input,
999
+ select,
1000
+ textarea {
1001
+ border: 1px solid ButtonText;
1002
+ }
1003
+
1004
+ input[type="checkbox"],
1005
+ input[type="radio"] {
1006
+ border: 2px solid ButtonText;
1007
+ }
1008
+
1009
+ mark {
1010
+ background-color: Highlight;
1011
+ color: HighlightText;
1012
+ }
1013
+ }
1014
+
1015
+ /**
1016
+ * RTL/LTR — logical direction support.
1017
+ */
1018
+
1019
+ [dir="rtl"] {
1020
+ text-align: right;
1021
+ }
1022
+
1023
+ [dir="ltr"] {
1024
+ text-align: left;
1025
+ }
1026
+
1027
+ /* ==========================================================================
1028
+ 13. Scrollbar
1029
+ ========================================================================== */
1030
+
1031
+ /**
1032
+ * Consistent scrollbar styling (Firefox 64+, Chrome 121+).
1033
+ */
1034
+
1035
+ * {
1036
+ scrollbar-width: var(--fn-scrollbar-width);
1037
+ scrollbar-color: var(--fn-scrollbar-thumb) var(--fn-scrollbar-track);
1038
+ }
1039
+
1040
+ ::-webkit-scrollbar {
1041
+ inline-size: 8px;
1042
+ block-size: 8px;
1043
+ }
1044
+
1045
+ ::-webkit-scrollbar-track {
1046
+ background: var(--fn-scrollbar-track);
1047
+ }
1048
+
1049
+ ::-webkit-scrollbar-thumb {
1050
+ background: var(--fn-scrollbar-thumb);
1051
+ border-radius: 4px;
1052
+ }
1053
+
1054
+ ::-webkit-scrollbar-thumb:hover {
1055
+ background: var(--fn-scrollbar-thumb-hover);
1056
+ }
1057
+
1058
+ /* ==========================================================================
1059
+ 14. Motion
1060
+ ========================================================================== */
1061
+
1062
+ /**
1063
+ * Disable animations for users who prefer reduced motion.
1064
+ */
1065
+
1066
+ @media (prefers-reduced-motion: reduce) {
1067
+ *,
1068
+ ::before,
1069
+ ::after {
1070
+ animation-duration: 0.01ms !important;
1071
+ animation-iteration-count: 1 !important;
1072
+ transition-duration: 0.01ms !important;
1073
+ scroll-behavior: auto !important;
1074
+ }
1075
+ }
1076
+
1077
+ /* ==========================================================================
1078
+ 15. Print
1079
+ ========================================================================== */
1080
+
1081
+ /**
1082
+ * Consistent, readable print styles.
1083
+ */
1084
+
1085
+ @media print {
1086
+ *,
1087
+ ::before,
1088
+ ::after {
1089
+ background: transparent !important;
1090
+ color: #000 !important;
1091
+ box-shadow: none !important;
1092
+ text-shadow: none !important;
1093
+ }
1094
+
1095
+ a,
1096
+ a:visited {
1097
+ text-decoration: underline;
1098
+ }
1099
+
1100
+ a[href]::after {
1101
+ content: " (" attr(href) ")";
1102
+ font-size: 0.8em;
1103
+ }
1104
+
1105
+ abbr[title]::after {
1106
+ content: " (" attr(title) ")";
1107
+ }
1108
+
1109
+ pre,
1110
+ blockquote,
1111
+ img,
1112
+ table,
1113
+ figure {
1114
+ break-inside: avoid;
1115
+ }
1116
+
1117
+ img {
1118
+ max-inline-size: 100% !important;
1119
+ }
1120
+
1121
+ h2,
1122
+ h3 {
1123
+ break-after: avoid;
1124
+ }
1125
+
1126
+ p {
1127
+ orphans: 3;
1128
+ widows: 3;
1129
+ }
1130
+ }