actual-css 0.1.0 → 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/CHANGELOG.md +53 -1
- package/README.md +2 -0
- package/dist/actual.css +356 -124
- package/dist/actual.js +2 -2
- package/dist/actual.js.map +13 -13
- package/dist/actual.min.css +1 -1
- package/docs/README.md +2 -0
- package/docs/components.md +2 -2
- package/docs/design-notes/browser-support.md +9 -0
- package/docs/design-notes/enhancement-contract.md +104 -0
- package/docs/design-notes/naming.md +1 -0
- package/docs/design-notes/widget-primitives.md +83 -0
- package/docs/forms.md +4 -4
- package/docs/javascript.md +104 -34
- package/docs/patterns.md +89 -0
- package/docs/ui.md +22 -30
- package/llms.txt +6 -0
- package/package.json +14 -8
- package/src/css/base.css +0 -4
- package/src/css/components/alert.css +88 -2
- package/src/css/components/badge.css +30 -7
- package/src/css/components/busy.css +1 -0
- package/src/css/components/button.css +6 -8
- package/src/css/components/flyout.css +0 -1
- package/src/css/components/join.css +1 -2
- package/src/css/components/scrollspy.css +2 -2
- package/src/css/components/spinner.css +4 -4
- package/src/css/components/status-bar.css +3 -4
- package/src/css/components/tab.css +1 -0
- package/src/css/focus.css +37 -0
- package/src/css/forms/choice-card.css +1 -2
- package/src/css/forms/choice.css +1 -2
- package/src/css/forms/control.css +1 -10
- package/src/css/forms/index.css +1 -0
- package/src/css/forms/native.css +8 -32
- package/src/css/forms/range.css +95 -0
- package/src/css/forms/switch.css +1 -2
- package/src/css/optional/scroller.css +6 -0
- package/src/css/theme.css +9 -9
- package/src/css/themes/edge.css +3 -27
- package/src/css/tokens.css +9 -3
- package/src/js/context-menu.js +21 -34
- package/src/js/enhance.js +26 -0
- package/src/js/flyout.js +12 -19
- package/src/js/menu.js +15 -14
- package/src/js/scrollspy.js +125 -62
- package/src/js/selectors.js +14 -24
- package/src/js/status.js +13 -13
- package/src/js/surface.js +57 -12
- package/src/js/tab.js +10 -13
- package/src/js/validation.js +11 -43
package/dist/actual.css
CHANGED
|
@@ -143,7 +143,8 @@ select {
|
|
|
143
143
|
/* Shape */
|
|
144
144
|
--border-width: 1px;
|
|
145
145
|
--radius-full: 9999px;
|
|
146
|
-
--shadow: 0
|
|
146
|
+
--shadow-xs: 0 1px 2px rgb(0 0 0 / 0.04);
|
|
147
|
+
--shadow: 0 1px 3px rgb(0 0 0 / 0.05), 0 4px 12px rgb(0 0 0 / 0.04);
|
|
147
148
|
--shadow-popout: 0 0.25rem 0.75rem rgb(0 0 0 / 0.15);
|
|
148
149
|
|
|
149
150
|
/* Motion — see reset.css for the prefers-reduced-motion hard reset.
|
|
@@ -157,8 +158,10 @@ select {
|
|
|
157
158
|
--ease: ease;
|
|
158
159
|
|
|
159
160
|
/* Focus ring — shared by every interactive component's :focus-visible */
|
|
160
|
-
--focus-outline:
|
|
161
|
+
--focus-outline-color: currentColor;
|
|
162
|
+
--focus-outline: calc(var(--border-width) * 2) solid var(--focus-outline-color);
|
|
161
163
|
--focus-outline-offset: 2px;
|
|
164
|
+
--focus-ring-width: 3px;
|
|
162
165
|
|
|
163
166
|
/* Status dot positioning — used by .avatar > .badge:empty. The offset is
|
|
164
167
|
the circle-aware inset (1 - 1/√2) / 2 ≈ 14.65%; the ring surrounds the
|
|
@@ -225,7 +228,10 @@ select {
|
|
|
225
228
|
|
|
226
229
|
@supports (color: color-mix(in oklch, red, white)) {
|
|
227
230
|
:root {
|
|
228
|
-
--shadow: 0
|
|
231
|
+
--shadow-xs: 0 1px 2px color-mix(in oklch, var(--shadow-color) 4%, transparent);
|
|
232
|
+
--shadow:
|
|
233
|
+
0 1px 3px color-mix(in oklch, var(--shadow-color) 5%, transparent),
|
|
234
|
+
0 4px 12px color-mix(in oklch, var(--shadow-color) 4%, transparent);
|
|
229
235
|
--shadow-popout: 0 0.25rem 0.75rem color-mix(in oklch, var(--shadow-color) 15%, transparent);
|
|
230
236
|
--backdrop-fill: color-mix(
|
|
231
237
|
in oklch,
|
|
@@ -298,11 +304,11 @@ select {
|
|
|
298
304
|
|
|
299
305
|
/* Lines and focus */
|
|
300
306
|
--border: hsl(260 15% 88%);
|
|
301
|
-
--focus: var(--
|
|
307
|
+
--focus: var(--neutral);
|
|
302
308
|
/* Pre-color-mix fallback only — superseded below by a derivation from
|
|
303
|
-
--focus so overriding --
|
|
304
|
-
--focus-ring: hsl(
|
|
305
|
-
--focus-ring-shadow: 0 0 0
|
|
309
|
+
--focus so overriding --neutral/--focus never leaves a stale ring. */
|
|
310
|
+
--focus-ring: hsl(258 7% 43% / 0.3);
|
|
311
|
+
--focus-ring-shadow: 0 0 0 var(--focus-ring-width) var(--focus-ring);
|
|
306
312
|
--hover-overlay: hsl(260 20% 10% / 0.04);
|
|
307
313
|
|
|
308
314
|
/* Radius scale — themes may override the whole scale (e.g. [data-theme="square"]) */
|
|
@@ -343,7 +349,7 @@ select {
|
|
|
343
349
|
:root,
|
|
344
350
|
[data-theme="light"],
|
|
345
351
|
[data-theme="dark"] {
|
|
346
|
-
--focus-ring: color-mix(in oklch, var(--focus)
|
|
352
|
+
--focus-ring: color-mix(in oklch, var(--focus) 30%, transparent);
|
|
347
353
|
}
|
|
348
354
|
}
|
|
349
355
|
|
|
@@ -383,7 +389,7 @@ select {
|
|
|
383
389
|
--text-subtle: light-dark(hsl(258 7% 57%), hsl(258 7% 54%));
|
|
384
390
|
|
|
385
391
|
--border: light-dark(hsl(260 15% 88%), hsl(262 12% 24%));
|
|
386
|
-
--focus-ring: light-dark(hsl(
|
|
392
|
+
--focus-ring: light-dark(hsl(258 7% 43% / 0.3), hsl(258 10% 72% / 0.28));
|
|
387
393
|
--hover-overlay: light-dark(hsl(260 20% 10% / 0.04), hsl(0 0% 100% / 0.06));
|
|
388
394
|
--shadow-color: light-dark(hsl(260 25% 10%), hsl(262 40% 2%));
|
|
389
395
|
}
|
|
@@ -393,7 +399,7 @@ select {
|
|
|
393
399
|
:root,
|
|
394
400
|
[data-theme="light"] {
|
|
395
401
|
--focus-ring: light-dark(
|
|
396
|
-
color-mix(in oklch, var(--focus)
|
|
402
|
+
color-mix(in oklch, var(--focus) 30%, transparent),
|
|
397
403
|
color-mix(in oklch, var(--focus) 28%, transparent)
|
|
398
404
|
);
|
|
399
405
|
}
|
|
@@ -403,7 +409,7 @@ select {
|
|
|
403
409
|
:root,
|
|
404
410
|
[data-theme="light"],
|
|
405
411
|
[data-theme="dark"] {
|
|
406
|
-
--focus-outline:
|
|
412
|
+
--focus-outline-color: Highlight;
|
|
407
413
|
--focus-ring-shadow: none;
|
|
408
414
|
|
|
409
415
|
--backdrop-fill: Canvas;
|
|
@@ -416,7 +422,7 @@ select {
|
|
|
416
422
|
[data-theme="dark"] {
|
|
417
423
|
--border-width: 2px;
|
|
418
424
|
--focus-outline-offset: 3px;
|
|
419
|
-
--focus-ring-
|
|
425
|
+
--focus-ring-width: 4px;
|
|
420
426
|
--text-muted: var(--text);
|
|
421
427
|
--text-subtle: var(--text);
|
|
422
428
|
}
|
|
@@ -441,10 +447,6 @@ a {
|
|
|
441
447
|
text-underline-offset: 0.18em;
|
|
442
448
|
}
|
|
443
449
|
|
|
444
|
-
a:focus-visible {
|
|
445
|
-
box-shadow: var(--focus-ring-shadow);
|
|
446
|
-
}
|
|
447
|
-
|
|
448
450
|
@media (hover: hover) {
|
|
449
451
|
a:hover {
|
|
450
452
|
text-decoration-thickness: 0.12em;
|
|
@@ -1047,7 +1049,6 @@ small {
|
|
|
1047
1049
|
--btn-border: var(--ui-border, var(--btn-default-border, transparent));
|
|
1048
1050
|
--btn-radius: var(--radius);
|
|
1049
1051
|
--btn-focus-color: var(--intent, var(--focus));
|
|
1050
|
-
--btn-focus-outline-width: calc(var(--border-width) * 2);
|
|
1051
1052
|
--btn-hover-bg: var(--ui-hover-bg, var(--btn-bg));
|
|
1052
1053
|
--btn-hover-overlay: var(--hover-overlay, rgb(0 0 0 / 0.08));
|
|
1053
1054
|
|
|
@@ -1055,7 +1056,7 @@ small {
|
|
|
1055
1056
|
display: inline-flex;
|
|
1056
1057
|
align-items: center;
|
|
1057
1058
|
justify-content: center;
|
|
1058
|
-
gap: 0.
|
|
1059
|
+
gap: 0.375em;
|
|
1059
1060
|
min-block-size: var(--btn-min-size);
|
|
1060
1061
|
padding-block: var(--space-2);
|
|
1061
1062
|
padding-block: max(var(--space-1), calc((var(--btn-min-size) - 1lh) / 2));
|
|
@@ -1071,7 +1072,7 @@ small {
|
|
|
1071
1072
|
color: var(--btn-fg);
|
|
1072
1073
|
font: inherit;
|
|
1073
1074
|
font-size: var(--btn-font-size);
|
|
1074
|
-
font-weight: var(--font-weight-
|
|
1075
|
+
font-weight: var(--font-weight-medium);
|
|
1075
1076
|
line-height: 1;
|
|
1076
1077
|
text-decoration: none;
|
|
1077
1078
|
cursor: pointer;
|
|
@@ -1147,14 +1148,14 @@ small {
|
|
|
1147
1148
|
}
|
|
1148
1149
|
|
|
1149
1150
|
.btn:focus-visible {
|
|
1150
|
-
outline:
|
|
1151
|
-
|
|
1152
|
-
box-shadow: 0 0 0 3px var(--btn-focus-ring-color, var(--focus-ring));
|
|
1151
|
+
outline: none;
|
|
1152
|
+
box-shadow: 0 0 0 var(--focus-ring-width) var(--btn-focus-ring-color, var(--focus-ring));
|
|
1153
1153
|
}
|
|
1154
1154
|
|
|
1155
1155
|
.btn.link:focus-visible {
|
|
1156
|
-
outline
|
|
1156
|
+
outline: var(--focus-outline);
|
|
1157
1157
|
outline-offset: 0.2em;
|
|
1158
|
+
box-shadow: none;
|
|
1158
1159
|
}
|
|
1159
1160
|
|
|
1160
1161
|
.btn:disabled {
|
|
@@ -1178,7 +1179,6 @@ a.btn[aria-disabled="true"] {
|
|
|
1178
1179
|
}
|
|
1179
1180
|
|
|
1180
1181
|
.btn[aria-busy="true"] > .spinner {
|
|
1181
|
-
--spinner-size: 1em;
|
|
1182
1182
|
--spinner-width: 0.15em;
|
|
1183
1183
|
}
|
|
1184
1184
|
|
|
@@ -1232,8 +1232,9 @@ a.btn[aria-disabled="true"] {
|
|
|
1232
1232
|
/*
|
|
1233
1233
|
* Badges for compact labels, counts, and state hints.
|
|
1234
1234
|
*
|
|
1235
|
-
*
|
|
1236
|
-
*
|
|
1235
|
+
* Soft by default. .solid for counters and notification badges. The dot
|
|
1236
|
+
* (.badge:empty) stays solid regardless — a soft dot is pointless.
|
|
1237
|
+
* Shared .outline variant stays available.
|
|
1237
1238
|
*/
|
|
1238
1239
|
/* Intent boundary — inherited intents do not tint this component.
|
|
1239
1240
|
Local intent classes still win because :where() has zero specificity. */
|
|
@@ -1253,9 +1254,9 @@ a.btn[aria-disabled="true"] {
|
|
|
1253
1254
|
--badge-pad-x: 0.55em;
|
|
1254
1255
|
--badge-font-size: var(--variant-compact-font-size, 0.8125rem);
|
|
1255
1256
|
--badge-dot-size: 0.5rem;
|
|
1256
|
-
--badge-bg: var(--ui-bg,
|
|
1257
|
-
--badge-fg: var(--ui-fg, var(--intent
|
|
1258
|
-
--badge-border: var(--ui-border,
|
|
1257
|
+
--badge-bg: var(--ui-bg, transparent);
|
|
1258
|
+
--badge-fg: var(--ui-fg, var(--intent, var(--text)));
|
|
1259
|
+
--badge-border: var(--ui-border, var(--intent, var(--border)));
|
|
1259
1260
|
--badge-radius: 999px;
|
|
1260
1261
|
|
|
1261
1262
|
display: inline-flex;
|
|
@@ -1280,8 +1281,31 @@ a.btn[aria-disabled="true"] {
|
|
|
1280
1281
|
box-shadow var(--duration);
|
|
1281
1282
|
}
|
|
1282
1283
|
|
|
1284
|
+
/* Soft by default — duplicated here with @sync markers for check-sync.js
|
|
1285
|
+
to guard, the same way alert.css guards its own soft recipe. */
|
|
1286
|
+
@supports (color: color-mix(in oklch, red, white)) {
|
|
1287
|
+
.badge:where(:not(.solid, .outline)) {
|
|
1288
|
+
/* @sync soft-recipe */
|
|
1289
|
+
--badge-bg: color-mix(
|
|
1290
|
+
in oklch,
|
|
1291
|
+
var(--surface) var(--soft-bg-mix),
|
|
1292
|
+
var(--intent, var(--neutral))
|
|
1293
|
+
);
|
|
1294
|
+
--badge-fg: var(--intent, var(--text));
|
|
1295
|
+
--badge-border: color-mix(
|
|
1296
|
+
in oklch,
|
|
1297
|
+
var(--surface) var(--soft-border-mix),
|
|
1298
|
+
var(--intent, var(--neutral))
|
|
1299
|
+
);
|
|
1300
|
+
/* @sync soft-recipe */
|
|
1301
|
+
}
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1283
1304
|
.badge:empty {
|
|
1284
1305
|
--badge-size: var(--badge-dot-size);
|
|
1306
|
+
--badge-bg: var(--intent, var(--neutral));
|
|
1307
|
+
--badge-fg: var(--intent-fg, var(--neutral-fg));
|
|
1308
|
+
--badge-border: transparent;
|
|
1285
1309
|
padding: 0;
|
|
1286
1310
|
border: 0;
|
|
1287
1311
|
inline-size: var(--badge-size);
|
|
@@ -1314,8 +1338,7 @@ a.btn[aria-disabled="true"] {
|
|
|
1314
1338
|
}
|
|
1315
1339
|
|
|
1316
1340
|
/* .solid/.soft/.outline are shared via variants.css, including the
|
|
1317
|
-
.soft/.outline hover recipe (--ui-hover-bg).
|
|
1318
|
-
.badge solid by default. */
|
|
1341
|
+
.soft/.outline hover recipe (--ui-hover-bg). */
|
|
1319
1342
|
@media (hover: hover) {
|
|
1320
1343
|
:where(a.badge, button.badge):not(:where(:disabled, [aria-disabled="true"])):hover {
|
|
1321
1344
|
background: var(--ui-hover-bg, var(--badge-bg));
|
|
@@ -1397,7 +1420,7 @@ a.badge[aria-disabled="true"] {
|
|
|
1397
1420
|
}
|
|
1398
1421
|
|
|
1399
1422
|
.alert {
|
|
1400
|
-
--alert-pad-block: var(--variant-pad-block, var(--space-
|
|
1423
|
+
--alert-pad-block: var(--variant-pad-block, var(--space-3));
|
|
1401
1424
|
--alert-pad-inline: var(--space-4);
|
|
1402
1425
|
--alert-font-size: var(--variant-font-size, var(--font-size-md));
|
|
1403
1426
|
--alert-icon-size: var(--variant-icon-size, 1.25rem);
|
|
@@ -1447,7 +1470,7 @@ a.badge[aria-disabled="true"] {
|
|
|
1447
1470
|
}
|
|
1448
1471
|
|
|
1449
1472
|
@supports (color: color-mix(in oklch, red, white)) {
|
|
1450
|
-
.alert:where(:not(.solid, .outline)) {
|
|
1473
|
+
.alert:where(:not(.solid, .outline, .callout)) {
|
|
1451
1474
|
/* @sync soft-recipe */
|
|
1452
1475
|
--ui-bg: color-mix(in oklch, var(--surface) var(--soft-bg-mix), var(--intent, var(--neutral)));
|
|
1453
1476
|
--ui-border: color-mix(
|
|
@@ -1511,6 +1534,92 @@ a.badge[aria-disabled="true"] {
|
|
|
1511
1534
|
Canvas backplate (unreadable) — so .solid intentionally falls back to the
|
|
1512
1535
|
default look. */
|
|
1513
1536
|
|
|
1537
|
+
/* Callout — neutral surface with an inset accent band on the leading edge.
|
|
1538
|
+
The ::before pseudo is absolutely positioned and inset to respect the
|
|
1539
|
+
outer border-radius, so it never needs its own radius. */
|
|
1540
|
+
.alert.callout {
|
|
1541
|
+
--alert-bg: var(--surface-subtle);
|
|
1542
|
+
--ui-bg: var(--alert-bg);
|
|
1543
|
+
--ui-fg: var(--text);
|
|
1544
|
+
--ui-border: var(--border);
|
|
1545
|
+
position: relative;
|
|
1546
|
+
padding-inline-start: calc(var(--alert-pad-inline) + var(--space-3));
|
|
1547
|
+
}
|
|
1548
|
+
|
|
1549
|
+
.alert.callout::before {
|
|
1550
|
+
content: "";
|
|
1551
|
+
position: absolute;
|
|
1552
|
+
inset-block: var(--space-2);
|
|
1553
|
+
inset-inline-start: var(--space-2);
|
|
1554
|
+
inline-size: 0.25rem;
|
|
1555
|
+
border-radius: var(--radius-full);
|
|
1556
|
+
background: var(--intent, var(--neutral));
|
|
1557
|
+
}
|
|
1558
|
+
|
|
1559
|
+
/* Admonition — structured title/body anatomy with a tinted title band.
|
|
1560
|
+
The root is layout-neutralized: no padding, no gap, no icon grid. */
|
|
1561
|
+
.alert.admonition {
|
|
1562
|
+
padding: 0;
|
|
1563
|
+
gap: 0;
|
|
1564
|
+
display: block;
|
|
1565
|
+
overflow: clip;
|
|
1566
|
+
}
|
|
1567
|
+
|
|
1568
|
+
.alert-title {
|
|
1569
|
+
padding-block: var(--alert-pad-block);
|
|
1570
|
+
padding-inline: var(--alert-pad-inline);
|
|
1571
|
+
|
|
1572
|
+
@supports (color: color-mix(in oklch, red, white)) {
|
|
1573
|
+
background: color-mix(
|
|
1574
|
+
in oklch,
|
|
1575
|
+
var(--surface) var(--soft-bg-mix),
|
|
1576
|
+
var(--intent, var(--neutral))
|
|
1577
|
+
);
|
|
1578
|
+
}
|
|
1579
|
+
|
|
1580
|
+
@supports not (color: color-mix(in oklch, red, white)) {
|
|
1581
|
+
background: var(--intent, var(--neutral));
|
|
1582
|
+
}
|
|
1583
|
+
|
|
1584
|
+
border-start-start-radius: calc(var(--radius-lg) - var(--border-width));
|
|
1585
|
+
border-start-end-radius: calc(var(--radius-lg) - var(--border-width));
|
|
1586
|
+
}
|
|
1587
|
+
|
|
1588
|
+
.alert-title:where(summary) {
|
|
1589
|
+
cursor: pointer;
|
|
1590
|
+
user-select: none;
|
|
1591
|
+
list-style: none;
|
|
1592
|
+
}
|
|
1593
|
+
|
|
1594
|
+
.alert-title:where(summary)::-webkit-details-marker {
|
|
1595
|
+
display: none;
|
|
1596
|
+
}
|
|
1597
|
+
|
|
1598
|
+
.alert-title[aria-hidden] {
|
|
1599
|
+
display: inline-flex;
|
|
1600
|
+
gap: var(--space-2);
|
|
1601
|
+
align-items: center;
|
|
1602
|
+
}
|
|
1603
|
+
|
|
1604
|
+
.alert-body {
|
|
1605
|
+
padding-block: var(--alert-pad-block);
|
|
1606
|
+
padding-inline: var(--alert-pad-inline);
|
|
1607
|
+
color: var(--text);
|
|
1608
|
+
}
|
|
1609
|
+
|
|
1610
|
+
.alert-body > :first-child {
|
|
1611
|
+
margin-block-start: 0;
|
|
1612
|
+
}
|
|
1613
|
+
|
|
1614
|
+
.alert-body > :last-child {
|
|
1615
|
+
margin-block-end: 0;
|
|
1616
|
+
}
|
|
1617
|
+
|
|
1618
|
+
details.alert.admonition[open] .alert-title {
|
|
1619
|
+
border-end-start-radius: 0;
|
|
1620
|
+
border-end-end-radius: 0;
|
|
1621
|
+
}
|
|
1622
|
+
|
|
1514
1623
|
/*
|
|
1515
1624
|
* Actions — a horizontal action-button cluster.
|
|
1516
1625
|
*
|
|
@@ -2201,7 +2310,6 @@ dialog.drawer nav {
|
|
|
2201
2310
|
background: var(--surface-subtle);
|
|
2202
2311
|
outline: var(--focus-outline);
|
|
2203
2312
|
outline-offset: var(--focus-outline-offset);
|
|
2204
|
-
box-shadow: var(--focus-ring-shadow);
|
|
2205
2313
|
}
|
|
2206
2314
|
|
|
2207
2315
|
:is(.flyout, .flyout :where(li))
|
|
@@ -2487,8 +2595,8 @@ dialog.drawer nav {
|
|
|
2487
2595
|
}
|
|
2488
2596
|
|
|
2489
2597
|
.spinner {
|
|
2490
|
-
--spinner-size:
|
|
2491
|
-
--spinner-width:
|
|
2598
|
+
--spinner-size: 1em;
|
|
2599
|
+
--spinner-width: 0.125em;
|
|
2492
2600
|
--spinner-track: currentColor;
|
|
2493
2601
|
--spinner-value: transparent;
|
|
2494
2602
|
|
|
@@ -2514,11 +2622,11 @@ dialog.drawer nav {
|
|
|
2514
2622
|
}
|
|
2515
2623
|
|
|
2516
2624
|
.spinner.sm {
|
|
2517
|
-
--spinner-size:
|
|
2625
|
+
--spinner-size: 0.75em;
|
|
2518
2626
|
}
|
|
2519
2627
|
|
|
2520
2628
|
.spinner.lg {
|
|
2521
|
-
--spinner-size:
|
|
2629
|
+
--spinner-size: 2rem;
|
|
2522
2630
|
--spinner-width: 3px;
|
|
2523
2631
|
}
|
|
2524
2632
|
|
|
@@ -2626,6 +2734,7 @@ dialog.drawer nav {
|
|
|
2626
2734
|
}
|
|
2627
2735
|
|
|
2628
2736
|
[aria-busy="true"]:not(.btn) > .spinner:last-child {
|
|
2737
|
+
--spinner-size: 2rem;
|
|
2629
2738
|
position: absolute;
|
|
2630
2739
|
inset: 0;
|
|
2631
2740
|
z-index: 2;
|
|
@@ -2780,10 +2889,9 @@ dialog.drawer nav {
|
|
|
2780
2889
|
* the coloring via --intent / --intent-fg. status.js applies these as plain
|
|
2781
2890
|
* classes on the target; it does not know their names or that they exist.
|
|
2782
2891
|
*
|
|
2783
|
-
*
|
|
2784
|
-
*
|
|
2785
|
-
*
|
|
2786
|
-
* that carry their own generic `data-status`.
|
|
2892
|
+
* CSS API: .status-bar
|
|
2893
|
+
* JS target contract: [data-status][role="status"]
|
|
2894
|
+
* Normally combined, but they describe separate concerns.
|
|
2787
2895
|
*/
|
|
2788
2896
|
|
|
2789
2897
|
/* Intent boundary — inherited intents do not tint this component.
|
|
@@ -3392,6 +3500,7 @@ a.avatar[aria-disabled="true"] {
|
|
|
3392
3500
|
|
|
3393
3501
|
.tab:focus-visible {
|
|
3394
3502
|
outline: var(--focus-outline);
|
|
3503
|
+
outline-color: var(--focus);
|
|
3395
3504
|
outline-offset: -2px;
|
|
3396
3505
|
border-radius: var(--radius-sm) var(--radius-sm) 0 0;
|
|
3397
3506
|
}
|
|
@@ -3460,8 +3569,8 @@ a.avatar[aria-disabled="true"] {
|
|
|
3460
3569
|
* Progressive enhancement: on browsers that support :target-current,
|
|
3461
3570
|
* this file enables the native target group and marks the active link.
|
|
3462
3571
|
*
|
|
3463
|
-
* Falls back gracefully: links still work when
|
|
3464
|
-
*
|
|
3572
|
+
* Falls back gracefully: links still work when :target-current is unavailable
|
|
3573
|
+
* and when the JavaScript enhancer is not loaded at all.
|
|
3465
3574
|
*/
|
|
3466
3575
|
|
|
3467
3576
|
@supports selector(.scrollspy a:target-current) {
|
|
@@ -3759,8 +3868,7 @@ a.avatar[aria-disabled="true"] {
|
|
|
3759
3868
|
.textarea:focus-visible,
|
|
3760
3869
|
.select:focus-visible {
|
|
3761
3870
|
--control-border: var(--focus);
|
|
3762
|
-
outline:
|
|
3763
|
-
outline-offset: var(--focus-outline-offset);
|
|
3871
|
+
outline: none;
|
|
3764
3872
|
box-shadow: var(--focus-ring-shadow);
|
|
3765
3873
|
}
|
|
3766
3874
|
|
|
@@ -3785,14 +3893,6 @@ a.avatar[aria-disabled="true"] {
|
|
|
3785
3893
|
color: var(--text-muted);
|
|
3786
3894
|
}
|
|
3787
3895
|
|
|
3788
|
-
@media (forced-colors: active) {
|
|
3789
|
-
.input:focus-visible,
|
|
3790
|
-
.textarea:focus-visible,
|
|
3791
|
-
.select:focus-visible {
|
|
3792
|
-
box-shadow: none;
|
|
3793
|
-
}
|
|
3794
|
-
}
|
|
3795
|
-
|
|
3796
3896
|
/*
|
|
3797
3897
|
* Input Icon — leading decorative icon inside a relative wrapper.
|
|
3798
3898
|
*
|
|
@@ -3988,8 +4088,7 @@ a.avatar[aria-disabled="true"] {
|
|
|
3988
4088
|
.check:focus-visible,
|
|
3989
4089
|
.radio:focus-visible {
|
|
3990
4090
|
--choice-border: var(--focus);
|
|
3991
|
-
outline:
|
|
3992
|
-
outline-offset: var(--focus-outline-offset);
|
|
4091
|
+
outline: none;
|
|
3993
4092
|
box-shadow: var(--focus-ring-shadow);
|
|
3994
4093
|
}
|
|
3995
4094
|
|
|
@@ -4030,9 +4129,15 @@ a.avatar[aria-disabled="true"] {
|
|
|
4030
4129
|
/*
|
|
4031
4130
|
* Choice cards — card-style radio and checkbox labels.
|
|
4032
4131
|
*
|
|
4033
|
-
* Each .choice-card is a <label>
|
|
4034
|
-
*
|
|
4035
|
-
*
|
|
4132
|
+
* Each .choice-card is a <label> wrapping a native radio or checkbox. When
|
|
4133
|
+
* :has() is supported the input is visually hidden and the card mirrors its
|
|
4134
|
+
* state: checked border and tint, checkmark badge (round for radio, rounded
|
|
4135
|
+
* square for checkbox), focus ring, disabled dimming. Without :has() the
|
|
4136
|
+
* native input stays visible so selection state never disappears.
|
|
4137
|
+
*
|
|
4138
|
+
* The badge overhangs the top-right corner by 0.375em; ancestors with
|
|
4139
|
+
* overflow: hidden will clip it. Pair with grid or flex utilities for group
|
|
4140
|
+
* layout.
|
|
4036
4141
|
*/
|
|
4037
4142
|
:where(.choice-card) {
|
|
4038
4143
|
/* @sync intent-boundary */
|
|
@@ -4055,7 +4160,7 @@ a.avatar[aria-disabled="true"] {
|
|
|
4055
4160
|
position: relative;
|
|
4056
4161
|
display: block;
|
|
4057
4162
|
padding: var(--choice-card-pad);
|
|
4058
|
-
border: var(--border-width) solid var(--choice-card-border);
|
|
4163
|
+
border: var(--border-width) solid var(--form-invalid-border, var(--choice-card-border));
|
|
4059
4164
|
border-radius: var(--choice-card-radius);
|
|
4060
4165
|
background: var(--choice-card-bg);
|
|
4061
4166
|
color: var(--text);
|
|
@@ -4067,23 +4172,26 @@ a.avatar[aria-disabled="true"] {
|
|
|
4067
4172
|
}
|
|
4068
4173
|
|
|
4069
4174
|
/* The native input is visually hidden but stays focusable and participates in
|
|
4070
|
-
form submission and keyboard navigation (sr-only pattern).
|
|
4071
|
-
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
|
|
4175
|
+
form submission and keyboard navigation (sr-only pattern). Guarded: without
|
|
4176
|
+
:has() the card cannot mirror the input's state, so the visible native
|
|
4177
|
+
control is the fallback affordance. */
|
|
4178
|
+
@supports selector(:has(*)) {
|
|
4179
|
+
.choice-card > :is(input[type="radio"], input[type="checkbox"]) {
|
|
4180
|
+
position: absolute;
|
|
4181
|
+
inline-size: 1px;
|
|
4182
|
+
block-size: 1px;
|
|
4183
|
+
padding: 0;
|
|
4184
|
+
margin: -1px;
|
|
4185
|
+
overflow: hidden;
|
|
4186
|
+
clip: rect(0, 0, 0, 0);
|
|
4187
|
+
white-space: nowrap;
|
|
4188
|
+
border: 0;
|
|
4189
|
+
}
|
|
4081
4190
|
}
|
|
4082
4191
|
|
|
4083
4192
|
/* Focus ring on the label follows the hidden input's focus. */
|
|
4084
4193
|
.choice-card:has(:focus-visible) {
|
|
4085
|
-
outline:
|
|
4086
|
-
outline-offset: var(--focus-outline-offset);
|
|
4194
|
+
outline: none;
|
|
4087
4195
|
box-shadow: var(--focus-ring-shadow);
|
|
4088
4196
|
}
|
|
4089
4197
|
|
|
@@ -4110,40 +4218,48 @@ a.avatar[aria-disabled="true"] {
|
|
|
4110
4218
|
}
|
|
4111
4219
|
}
|
|
4112
4220
|
|
|
4113
|
-
/* Checkmark badge —
|
|
4114
|
-
|
|
4221
|
+
/* Checkmark badge — always rendered at scale(0) and scaled in on check, so
|
|
4222
|
+
the entrance can transition (a pseudo created on :checked could not). */
|
|
4223
|
+
.choice-card::before,
|
|
4224
|
+
.choice-card::after {
|
|
4115
4225
|
content: "";
|
|
4116
4226
|
position: absolute;
|
|
4117
4227
|
inset-inline-end: -0.375em;
|
|
4118
4228
|
inset-block-start: -0.375em;
|
|
4119
4229
|
inline-size: var(--choice-card-check-size);
|
|
4120
4230
|
block-size: var(--choice-card-check-size);
|
|
4231
|
+
transform: scale(0);
|
|
4232
|
+
transition: transform var(--duration);
|
|
4233
|
+
}
|
|
4234
|
+
|
|
4235
|
+
/* Badge disc — circle for radio, rounded square for checkbox */
|
|
4236
|
+
.choice-card::before {
|
|
4121
4237
|
background: var(--intent, var(--primary));
|
|
4122
|
-
z-index: 1;
|
|
4123
4238
|
box-shadow: 0 0 0 2px var(--surface);
|
|
4239
|
+
z-index: 1;
|
|
4124
4240
|
}
|
|
4125
4241
|
|
|
4126
|
-
.choice-card:has(input[type="radio"]
|
|
4242
|
+
.choice-card:has(input[type="radio"])::before {
|
|
4127
4243
|
border-radius: var(--radius-full);
|
|
4128
4244
|
}
|
|
4129
4245
|
|
|
4130
|
-
.choice-card:has(input[type="checkbox"]
|
|
4246
|
+
.choice-card:has(input[type="checkbox"])::before {
|
|
4131
4247
|
border-radius: var(--radius-sm);
|
|
4132
4248
|
}
|
|
4133
4249
|
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
position: absolute;
|
|
4137
|
-
inset-inline-end: -0.375em;
|
|
4138
|
-
inset-block-start: -0.375em;
|
|
4139
|
-
inline-size: var(--choice-card-check-size);
|
|
4140
|
-
block-size: var(--choice-card-check-size);
|
|
4250
|
+
/* Check mark */
|
|
4251
|
+
.choice-card::after {
|
|
4141
4252
|
background: var(--intent-fg, var(--primary-fg));
|
|
4142
|
-
mask: var(--icon-check-mask) center / 60% no-repeat;
|
|
4143
4253
|
-webkit-mask: var(--icon-check-mask) center / 60% no-repeat;
|
|
4254
|
+
mask: var(--icon-check-mask) center / 60% no-repeat;
|
|
4144
4255
|
z-index: 2;
|
|
4145
4256
|
}
|
|
4146
4257
|
|
|
4258
|
+
.choice-card:has(:checked)::before,
|
|
4259
|
+
.choice-card:has(:checked)::after {
|
|
4260
|
+
transform: scale(1);
|
|
4261
|
+
}
|
|
4262
|
+
|
|
4147
4263
|
@media (forced-colors: active) {
|
|
4148
4264
|
.choice-card {
|
|
4149
4265
|
--choice-card-border: ButtonText;
|
|
@@ -4152,6 +4268,9 @@ a.avatar[aria-disabled="true"] {
|
|
|
4152
4268
|
|
|
4153
4269
|
.choice-card:has(:checked) {
|
|
4154
4270
|
--choice-card-border: Highlight;
|
|
4271
|
+
/* Pin the background: with forced-color-adjust: none the color-mix tint
|
|
4272
|
+
above would actually render, uncontrolled in high-contrast themes. */
|
|
4273
|
+
--choice-card-bg: Canvas;
|
|
4155
4274
|
forced-color-adjust: none;
|
|
4156
4275
|
}
|
|
4157
4276
|
|
|
@@ -4160,14 +4279,6 @@ a.avatar[aria-disabled="true"] {
|
|
|
4160
4279
|
box-shadow: 0 0 0 2px Canvas;
|
|
4161
4280
|
}
|
|
4162
4281
|
|
|
4163
|
-
.choice-card:has(input[type="radio"]:checked)::before {
|
|
4164
|
-
border-radius: var(--radius-full);
|
|
4165
|
-
}
|
|
4166
|
-
|
|
4167
|
-
.choice-card:has(input[type="checkbox"]:checked)::before {
|
|
4168
|
-
border-radius: var(--radius-sm);
|
|
4169
|
-
}
|
|
4170
|
-
|
|
4171
4282
|
.choice-card:has(:checked)::after {
|
|
4172
4283
|
background: HighlightText;
|
|
4173
4284
|
}
|
|
@@ -4305,23 +4416,13 @@ a.avatar[aria-disabled="true"] {
|
|
|
4305
4416
|
}
|
|
4306
4417
|
|
|
4307
4418
|
/*
|
|
4308
|
-
* Native-only control polish: file
|
|
4309
|
-
*
|
|
4310
|
-
*
|
|
4419
|
+
* Native-only control polish: file input that mostly defeats custom styling,
|
|
4420
|
+
* so the framework stays out of the way and just keeps it readable and
|
|
4421
|
+
* theme-aware.
|
|
4422
|
+
*
|
|
4423
|
+
* Range has its own custom-styled file (range.css) so the focus ring can
|
|
4424
|
+
* target the thumb pseudo-element rather than the rectangular CSS box.
|
|
4311
4425
|
*/
|
|
4312
|
-
/* Intent boundary — inherited intents do not tint this component.
|
|
4313
|
-
Local intent classes still win because :where() has zero specificity. */
|
|
4314
|
-
:where(.range) {
|
|
4315
|
-
/* @sync intent-boundary */
|
|
4316
|
-
--intent: initial;
|
|
4317
|
-
--intent-fg: initial;
|
|
4318
|
-
--ui-bg: initial;
|
|
4319
|
-
--ui-fg: initial;
|
|
4320
|
-
--ui-border: initial;
|
|
4321
|
-
--ui-hover-bg: initial;
|
|
4322
|
-
/* @sync intent-boundary */
|
|
4323
|
-
}
|
|
4324
|
-
|
|
4325
4426
|
.file {
|
|
4326
4427
|
color: var(--text-muted);
|
|
4327
4428
|
}
|
|
@@ -4354,23 +4455,105 @@ a.avatar[aria-disabled="true"] {
|
|
|
4354
4455
|
}
|
|
4355
4456
|
}
|
|
4356
4457
|
|
|
4458
|
+
.file:focus-visible {
|
|
4459
|
+
outline: none;
|
|
4460
|
+
box-shadow: var(--focus-ring-shadow);
|
|
4461
|
+
}
|
|
4462
|
+
|
|
4463
|
+
/*
|
|
4464
|
+
* Range slider — custom-styled so the focus ring always targets the
|
|
4465
|
+
* user-manipulated surface (the thumb) rather than the CSS box.
|
|
4466
|
+
*
|
|
4467
|
+
* appearance: none gives us full control over track and thumb; without it,
|
|
4468
|
+
* pseudo-element rules for ::-webkit-slider-thumb and ::-moz-range-thumb
|
|
4469
|
+
* are not reliably applied across browsers.
|
|
4470
|
+
*/
|
|
4471
|
+
|
|
4472
|
+
/* Intent boundary — inherited intents do not tint this component.
|
|
4473
|
+
Local intent classes still win because :where() has zero specificity. */
|
|
4474
|
+
:where(.range) {
|
|
4475
|
+
/* @sync intent-boundary */
|
|
4476
|
+
--intent: initial;
|
|
4477
|
+
--intent-fg: initial;
|
|
4478
|
+
--ui-bg: initial;
|
|
4479
|
+
--ui-fg: initial;
|
|
4480
|
+
--ui-border: initial;
|
|
4481
|
+
--ui-hover-bg: initial;
|
|
4482
|
+
/* @sync intent-boundary */
|
|
4483
|
+
}
|
|
4484
|
+
|
|
4357
4485
|
.range {
|
|
4486
|
+
--range-thumb-size: 1.25rem;
|
|
4487
|
+
--range-track-height: 0.25rem;
|
|
4488
|
+
--range-thumb-bg: var(--intent, var(--primary));
|
|
4489
|
+
--range-track-bg: var(--border);
|
|
4490
|
+
|
|
4491
|
+
appearance: none;
|
|
4358
4492
|
inline-size: 100%;
|
|
4359
|
-
|
|
4493
|
+
block-size: var(--range-thumb-size);
|
|
4494
|
+
background: transparent;
|
|
4495
|
+
cursor: pointer;
|
|
4496
|
+
}
|
|
4497
|
+
|
|
4498
|
+
.range::-webkit-slider-runnable-track {
|
|
4499
|
+
block-size: var(--range-track-height);
|
|
4500
|
+
border-radius: var(--radius-full);
|
|
4501
|
+
background: var(--range-track-bg);
|
|
4502
|
+
}
|
|
4503
|
+
|
|
4504
|
+
.range::-moz-range-track {
|
|
4505
|
+
block-size: var(--range-track-height);
|
|
4506
|
+
border-radius: var(--radius-full);
|
|
4507
|
+
background: var(--range-track-bg);
|
|
4508
|
+
}
|
|
4509
|
+
|
|
4510
|
+
.range::-webkit-slider-thumb {
|
|
4511
|
+
appearance: none;
|
|
4512
|
+
inline-size: var(--range-thumb-size);
|
|
4513
|
+
block-size: var(--range-thumb-size);
|
|
4514
|
+
border-radius: var(--radius-full);
|
|
4515
|
+
border: 0;
|
|
4516
|
+
background: var(--range-thumb-bg);
|
|
4517
|
+
margin-block-start: calc((var(--range-track-height) - var(--range-thumb-size)) / 2);
|
|
4518
|
+
cursor: inherit;
|
|
4519
|
+
transition: box-shadow var(--duration);
|
|
4520
|
+
}
|
|
4521
|
+
|
|
4522
|
+
.range::-moz-range-thumb {
|
|
4523
|
+
inline-size: var(--range-thumb-size);
|
|
4524
|
+
block-size: var(--range-thumb-size);
|
|
4525
|
+
border-radius: var(--radius-full);
|
|
4526
|
+
border: 0;
|
|
4527
|
+
background: var(--range-thumb-bg);
|
|
4528
|
+
cursor: inherit;
|
|
4529
|
+
transition: box-shadow var(--duration);
|
|
4360
4530
|
}
|
|
4361
4531
|
|
|
4362
|
-
.file:focus-visible,
|
|
4363
4532
|
.range:focus-visible {
|
|
4364
|
-
outline:
|
|
4365
|
-
outline-offset: var(--focus-outline-offset);
|
|
4366
|
-
box-shadow: var(--focus-ring-shadow);
|
|
4533
|
+
outline: none;
|
|
4367
4534
|
}
|
|
4368
4535
|
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
|
|
4372
|
-
|
|
4373
|
-
|
|
4536
|
+
/*
|
|
4537
|
+
* The 1px surface-coloured separator keeps the ring visually distinct from
|
|
4538
|
+
* the small, coloured thumb — unlike a full-size input where the same gap
|
|
4539
|
+
* would read as an unwanted void.
|
|
4540
|
+
*/
|
|
4541
|
+
.range:focus-visible::-webkit-slider-thumb {
|
|
4542
|
+
box-shadow:
|
|
4543
|
+
0 0 0 1px var(--surface),
|
|
4544
|
+
0 0 0 calc(1px + var(--focus-ring-width)) var(--focus-ring);
|
|
4545
|
+
}
|
|
4546
|
+
|
|
4547
|
+
.range:focus-visible::-moz-range-thumb {
|
|
4548
|
+
box-shadow:
|
|
4549
|
+
0 0 0 1px var(--surface),
|
|
4550
|
+
0 0 0 calc(1px + var(--focus-ring-width)) var(--focus-ring);
|
|
4551
|
+
}
|
|
4552
|
+
|
|
4553
|
+
.range:disabled {
|
|
4554
|
+
--range-thumb-bg: var(--text-subtle);
|
|
4555
|
+
cursor: not-allowed;
|
|
4556
|
+
opacity: var(--disabled-opacity);
|
|
4374
4557
|
}
|
|
4375
4558
|
|
|
4376
4559
|
/*
|
|
@@ -4461,8 +4644,7 @@ a.avatar[aria-disabled="true"] {
|
|
|
4461
4644
|
|
|
4462
4645
|
.switch:focus-visible {
|
|
4463
4646
|
--switch-border: var(--focus);
|
|
4464
|
-
outline:
|
|
4465
|
-
outline-offset: var(--focus-outline-offset);
|
|
4647
|
+
outline: none;
|
|
4466
4648
|
box-shadow: var(--focus-ring-shadow);
|
|
4467
4649
|
}
|
|
4468
4650
|
|
|
@@ -4539,6 +4721,16 @@ a.avatar[aria-disabled="true"] {
|
|
|
4539
4721
|
--switch-bg: var(--danger);
|
|
4540
4722
|
}
|
|
4541
4723
|
|
|
4724
|
+
/* Choice cards hide their native input, so invalid state must surface on the
|
|
4725
|
+
card itself. Sets the same --form-invalid-border hook the card's border
|
|
4726
|
+
consumes. */
|
|
4727
|
+
@supports selector(:has(*)) {
|
|
4728
|
+
.choice-card:has([aria-invalid="true"]),
|
|
4729
|
+
.needs-validation.was-validated .choice-card:has(:invalid) {
|
|
4730
|
+
--form-invalid-border: var(--danger);
|
|
4731
|
+
}
|
|
4732
|
+
}
|
|
4733
|
+
|
|
4542
4734
|
@supports selector(:user-invalid) {
|
|
4543
4735
|
.needs-validation :is(.input, .textarea, .select, .check, .radio, .switch):user-invalid {
|
|
4544
4736
|
--form-invalid-border: var(--danger);
|
|
@@ -4549,6 +4741,10 @@ a.avatar[aria-disabled="true"] {
|
|
|
4549
4741
|
.needs-validation .field:has(:user-invalid) > .field-error {
|
|
4550
4742
|
display: block;
|
|
4551
4743
|
}
|
|
4744
|
+
|
|
4745
|
+
.needs-validation .choice-card:has(:user-invalid) {
|
|
4746
|
+
--form-invalid-border: var(--danger);
|
|
4747
|
+
}
|
|
4552
4748
|
}
|
|
4553
4749
|
|
|
4554
4750
|
/*
|
|
@@ -4856,8 +5052,7 @@ a.avatar[aria-disabled="true"] {
|
|
|
4856
5052
|
focus, and unsupported :has() browsers retain the control's normal ring. */
|
|
4857
5053
|
.join:has(> :is(.input, .textarea, .select):focus-visible) {
|
|
4858
5054
|
border-radius: var(--join-radius);
|
|
4859
|
-
outline:
|
|
4860
|
-
outline-offset: var(--focus-outline-offset);
|
|
5055
|
+
outline: none;
|
|
4861
5056
|
box-shadow: var(--focus-ring-shadow);
|
|
4862
5057
|
}
|
|
4863
5058
|
|
|
@@ -4880,6 +5075,43 @@ a.avatar[aria-disabled="true"] {
|
|
|
4880
5075
|
}
|
|
4881
5076
|
}
|
|
4882
5077
|
|
|
5078
|
+
/*
|
|
5079
|
+
* Forced-colors focus — centralised so individual components do not need
|
|
5080
|
+
* their own fallback. The double :focus keeps specificity high enough
|
|
5081
|
+
* (0,0,2,0) to beat a single :focus-visible; against a class selector like
|
|
5082
|
+
* .input:focus-visible it ties, but this file loads last so it wins on
|
|
5083
|
+
* source order.
|
|
5084
|
+
*
|
|
5085
|
+
* .choice-card and .join receive focus indirectly (:has on a wrapper that
|
|
5086
|
+
* never matches :focus), so they are listed explicitly.
|
|
5087
|
+
*
|
|
5088
|
+
* .range is excluded from the rectangular fallback: its focus is drawn on
|
|
5089
|
+
* the thumb pseudo-element, which is the manipulated surface.
|
|
5090
|
+
*
|
|
5091
|
+
* box-shadow: none is redundant when forced-color-adjust is auto, but safe
|
|
5092
|
+
* when a component uses forced-color-adjust: none (e.g. checked switches /
|
|
5093
|
+
* checkboxes).
|
|
5094
|
+
*/
|
|
5095
|
+
@media (forced-colors: active) {
|
|
5096
|
+
:focus:focus-visible:not(.range),
|
|
5097
|
+
.choice-card:has(:focus-visible),
|
|
5098
|
+
.join:has(> :is(.input, .textarea, .select):focus-visible) {
|
|
5099
|
+
outline: var(--focus-outline);
|
|
5100
|
+
outline-offset: var(--focus-outline-offset);
|
|
5101
|
+
box-shadow: none;
|
|
5102
|
+
}
|
|
5103
|
+
|
|
5104
|
+
.range:focus-visible::-webkit-slider-thumb {
|
|
5105
|
+
outline: var(--focus-outline);
|
|
5106
|
+
outline-offset: var(--focus-outline-offset);
|
|
5107
|
+
}
|
|
5108
|
+
|
|
5109
|
+
.range:focus-visible::-moz-range-thumb {
|
|
5110
|
+
outline: var(--focus-outline);
|
|
5111
|
+
outline-offset: var(--focus-outline-offset);
|
|
5112
|
+
}
|
|
5113
|
+
}
|
|
5114
|
+
|
|
4883
5115
|
@media print {
|
|
4884
5116
|
:root,
|
|
4885
5117
|
body {
|