@digiko-npm/designsystem 0.5.0 → 0.7.2

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.
Files changed (55) hide show
  1. package/README.md +7 -7
  2. package/dist/designsystem.css +1284 -474
  3. package/dist/designsystem.min.css +2 -2
  4. package/package.json +6 -1
  5. package/src/base/typography.css +8 -8
  6. package/src/components/accordion.css +21 -14
  7. package/src/components/alert.css +25 -19
  8. package/src/components/avatar.css +16 -16
  9. package/src/components/bottom-nav.css +27 -21
  10. package/src/components/breadcrumb.css +7 -0
  11. package/src/components/button.css +10 -2
  12. package/src/components/card.css +6 -42
  13. package/src/components/chip.css +10 -3
  14. package/src/components/collapsible.css +116 -0
  15. package/src/components/command.css +17 -7
  16. package/src/components/custom-select.css +123 -7
  17. package/src/components/datepicker.css +9 -9
  18. package/src/components/description-list.css +98 -0
  19. package/src/components/divider.css +1 -1
  20. package/src/components/drawer.css +28 -19
  21. package/src/components/drop-zone.css +10 -3
  22. package/src/components/dropdown.css +17 -8
  23. package/src/components/empty-state.css +3 -3
  24. package/src/components/field.css +77 -0
  25. package/src/components/icon-btn.css +12 -6
  26. package/src/components/index.css +5 -0
  27. package/src/components/input.css +26 -16
  28. package/src/components/kbd.css +1 -1
  29. package/src/components/modal.css +13 -4
  30. package/src/components/nav.css +22 -11
  31. package/src/components/pagination.css +9 -0
  32. package/src/components/popover.css +10 -10
  33. package/src/components/progress.css +2 -2
  34. package/src/components/result.css +84 -0
  35. package/src/components/search.css +24 -26
  36. package/src/components/skeleton.css +4 -4
  37. package/src/components/slider.css +13 -6
  38. package/src/components/sortable.css +9 -0
  39. package/src/components/stat-card.css +41 -0
  40. package/src/components/table.css +3 -3
  41. package/src/components/tabs.css +26 -18
  42. package/src/components/tag.css +11 -3
  43. package/src/components/timeline.css +14 -14
  44. package/src/components/toast.css +19 -7
  45. package/src/components/toggle.css +10 -2
  46. package/src/components/toolbar.css +1 -1
  47. package/src/components/tooltip.css +34 -28
  48. package/src/index.css +6 -4
  49. package/src/tokens/colors.css +18 -6
  50. package/src/tokens/spacing.css +7 -0
  51. package/src/utilities/a11y.css +102 -0
  52. package/src/utilities/index.css +1 -0
  53. package/src/utilities/layout.css +26 -26
  54. package/src/utilities/spacing.css +52 -52
  55. package/src/utilities/text.css +8 -8
@@ -1,4 +1,4 @@
1
- /* @ds/designsystem v0.4.0 */
1
+ /* @ds/designsystem v0.7.1 */
2
2
  /* ==========================================================================
3
3
  @digiko-npm/designsystem
4
4
 
@@ -14,6 +14,9 @@
14
14
  Your values always win. Nothing breaks.
15
15
  ========================================================================== */
16
16
 
17
+ @layer tokens, base, components, utilities;
18
+
19
+ @layer tokens {
17
20
  /* ==========================================================================
18
21
  Design Tokens — All tokens in one import
19
22
 
@@ -40,7 +43,13 @@
40
43
  --ds-color-surface-hover: #fafafa;
41
44
  --ds-color-surface-active: #f4f4f5;
42
45
 
43
- /* --- Text — zinc hierarchy --- */
46
+ /* --- Text — zinc hierarchy ---
47
+ Contrast ratios on --ds-color-bg (#fafafa):
48
+ --text: #09090b → ~19.3:1 ✅ WCAG AAA
49
+ --text-secondary: #52525b → ~7.6:1 ✅ WCAG AAA
50
+ --text-tertiary: #a1a1aa → ~2.5:1 ⚠ Decorative/non-essential only (does not meet 4.5:1)
51
+ --text-disabled: #d4d4d8 → ~1.5:1 ⚠ Disabled state (exempt per WCAG 1.4.3)
52
+ --- */
44
53
  --ds-color-text: #09090b;
45
54
  --ds-color-text-secondary: #52525b;
46
55
  --ds-color-text-tertiary: #a1a1aa;
@@ -87,18 +96,24 @@
87
96
  }
88
97
 
89
98
  /* Dark theme */
90
- [data-theme="dark"], .dark {
99
+ [data-theme="dark"] {
91
100
  /* --- Backgrounds — deep, refined zinc-900 palette --- */
92
101
  --ds-color-bg: #09090b;
93
102
  --ds-color-bg-subtle: #0f0f11;
94
- --ds-color-bg-muted: #27272a;
95
- --ds-color-bg-elevated: #18181b;
103
+ --ds-color-bg-muted: #18181b;
104
+ --ds-color-bg-elevated: #1c1c20;
96
105
 
97
106
  --ds-color-surface: #0f0f11;
98
107
  --ds-color-surface-hover: #18181b;
99
108
  --ds-color-surface-active: #27272a;
100
109
 
101
- /* --- Text --- */
110
+ /* --- Text ---
111
+ Contrast ratios on --ds-color-bg (#09090b):
112
+ --text: #fafafa → ~19.3:1 ✅ WCAG AAA
113
+ --text-secondary: #a1a1aa → ~7.6:1 ✅ WCAG AAA
114
+ --text-tertiary: #71717a → ~3.8:1 ⚠ Decorative/non-essential only (does not meet 4.5:1)
115
+ --text-disabled: #3f3f46 → ~2.0:1 ⚠ Disabled state (exempt per WCAG 1.4.3)
116
+ --- */
102
117
  --ds-color-text: #fafafa;
103
118
  --ds-color-text-secondary: #a1a1aa;
104
119
  --ds-color-text-tertiary: #71717a;
@@ -185,7 +200,7 @@
185
200
  }
186
201
 
187
202
  /* Dark overrides for status/accent (brighter for contrast) */
188
- [data-theme="dark"], .dark {
203
+ [data-theme="dark"] {
189
204
  --ds-color-success: #4ade80;
190
205
  --ds-color-success-subtle: rgba(74, 222, 128, 0.1);
191
206
  --ds-color-success-border: rgba(74, 222, 128, 0.2);
@@ -275,6 +290,13 @@
275
290
  Generous whitespace, responsive sections.
276
291
  ========================================================================== */
277
292
 
293
+ /* Breakpoints (reference only — CSS cannot use vars in @media)
294
+ --ds-breakpoint-sm: 640px
295
+ --ds-breakpoint-md: 768px
296
+ --ds-breakpoint-lg: 1024px
297
+ --ds-breakpoint-xl: 1280px
298
+ */
299
+
278
300
  :root {
279
301
  /* --- Spacing Scale --- */
280
302
  --ds-space-0: 0;
@@ -395,6 +417,8 @@
395
417
  }
396
418
 
397
419
 
420
+ }
421
+ @layer base {
398
422
  /* ==========================================================================
399
423
  Base: Reset
400
424
  Clean, modern, antialiased.
@@ -538,7 +562,7 @@ p {
538
562
  }
539
563
 
540
564
  .ds-prose p + p {
541
- margin-top: var(--ds-space-4);
565
+ margin-block-start: var(--ds-space-4);
542
566
  }
543
567
 
544
568
  small {
@@ -595,7 +619,7 @@ strong, b {
595
619
  @media (min-width: 768px) {
596
620
  .ds-hero-title { font-size: var(--ds-text-6xl); }
597
621
  }
598
- @media (min-width: 1024px) {
622
+ @media (min-width: 1024px) /* --ds-breakpoint-lg */ {
599
623
  .ds-hero-title { font-size: var(--ds-text-7xl); }
600
624
  }
601
625
 
@@ -624,8 +648,8 @@ pre code {
624
648
  }
625
649
 
626
650
  blockquote {
627
- padding-left: var(--ds-space-4);
628
- border-left: 2px solid var(--ds-color-border-hover);
651
+ padding-inline-start: var(--ds-space-4);
652
+ border-inline-start: 2px solid var(--ds-color-border-hover);
629
653
  color: var(--ds-color-text-secondary);
630
654
  }
631
655
 
@@ -648,9 +672,9 @@ hr {
648
672
  }
649
673
 
650
674
  .ds-prose ul, .ds-prose ol {
651
- padding-left: var(--ds-space-6);
652
- margin-top: var(--ds-space-2);
653
- margin-bottom: var(--ds-space-2);
675
+ padding-inline-start: var(--ds-space-6);
676
+ margin-block-start: var(--ds-space-2);
677
+ margin-block-end: var(--ds-space-2);
654
678
  }
655
679
  .ds-prose ul { list-style-type: disc; }
656
680
  .ds-prose ol { list-style-type: decimal; }
@@ -660,7 +684,7 @@ hr {
660
684
  color: var(--ds-color-text-secondary);
661
685
  }
662
686
  .ds-prose li + li {
663
- margin-top: var(--ds-space-1);
687
+ margin-block-start: var(--ds-space-1);
664
688
  }
665
689
 
666
690
  /* Tabular figures for numbers */
@@ -678,10 +702,19 @@ hr {
678
702
  }
679
703
 
680
704
 
705
+ }
706
+ @layer components {
681
707
  /* === Core === */
682
708
  /* ==========================================================================
683
709
  Component: Button
684
710
  Inverted primary, rounded-full CTAs, refined sizing.
711
+
712
+ ARIA requirements (consumer responsibility):
713
+ - Use <button> or <a role="button"> elements
714
+ - Disabled: add aria-disabled="true" (supported by DS styles)
715
+ - Loading: add aria-busy="true" when --loading is applied
716
+ - Icon-only: add aria-label="[action]" for screen readers
717
+ - Button groups: wrap in role="group" with aria-label
685
718
  ========================================================================== */
686
719
 
687
720
  .ds-btn {
@@ -713,6 +746,7 @@ hr {
713
746
  .ds-btn:focus-visible {
714
747
  outline: none;
715
748
  box-shadow: 0 0 0 var(--ds-ring-width) var(--ds-ring-color);
749
+ scroll-margin-block: var(--ds-space-16, 4rem);
716
750
  }
717
751
 
718
752
  .ds-btn:disabled,
@@ -845,7 +879,7 @@ hr {
845
879
  .ds-btn-group .ds-btn { border-radius: 0; }
846
880
  .ds-btn-group .ds-btn:first-child { border-radius: var(--ds-radius-lg) 0 0 var(--ds-radius-lg); }
847
881
  .ds-btn-group .ds-btn:last-child { border-radius: 0 var(--ds-radius-lg) var(--ds-radius-lg) 0; }
848
- .ds-btn-group .ds-btn + .ds-btn { margin-left: -1px; }
882
+ .ds-btn-group .ds-btn + .ds-btn { margin-inline-start: -1px; }
849
883
 
850
884
  /* --- Loading spinner --- */
851
885
  .ds-btn--loading {
@@ -859,7 +893,7 @@ hr {
859
893
  width: 1em;
860
894
  height: 1em;
861
895
  border: 2px solid currentColor;
862
- border-right-color: transparent;
896
+ border-inline-end-color: transparent;
863
897
  border-radius: var(--ds-radius-full);
864
898
  animation: ds-btn-spin 0.6s linear infinite;
865
899
  color: var(--ds-color-on-inverted);
@@ -915,7 +949,7 @@ hr {
915
949
 
916
950
  .ds-card__header {
917
951
  padding: var(--ds-space-5);
918
- border-bottom: 1px solid var(--ds-color-border);
952
+ border-block-end: 1px solid var(--ds-color-border);
919
953
  }
920
954
 
921
955
  .ds-card__header h3,
@@ -930,7 +964,7 @@ hr {
930
964
  .ds-card__description {
931
965
  font-size: var(--ds-text-sm);
932
966
  color: var(--ds-color-text-tertiary);
933
- margin-top: var(--ds-space-1);
967
+ margin-block-start: var(--ds-space-1);
934
968
  }
935
969
 
936
970
  .ds-card__body {
@@ -939,7 +973,7 @@ hr {
939
973
 
940
974
  .ds-card__footer {
941
975
  padding: var(--ds-space-4) var(--ds-space-5);
942
- border-top: 1px solid var(--ds-color-border);
976
+ border-block-start: 1px solid var(--ds-color-border);
943
977
  display: flex;
944
978
  align-items: center;
945
979
  gap: var(--ds-space-2);
@@ -963,10 +997,16 @@ hr {
963
997
  }
964
998
 
965
999
  /* Flush — no internal dividers */
966
- .ds-card--flush .ds-card__header { border-bottom: none; }
967
- .ds-card--flush .ds-card__footer { border-top: none; }
1000
+ .ds-card--flush .ds-card__header { border-block-end: none; }
1001
+ .ds-card--flush .ds-card__footer { border-block-start: none; }
1002
+
1003
+ /* Stat card — extracted to stat-card.css */
1004
+
1005
+ /* ==========================================================================
1006
+ Component: Stat Card
1007
+ Compact metric display with label, value, detail, and optional icon.
1008
+ ========================================================================== */
968
1009
 
969
- /* Stat card (like StatCard component) */
970
1010
  .ds-stat-card {
971
1011
  background-color: var(--ds-color-surface);
972
1012
  border: 1px solid var(--ds-color-border);
@@ -984,13 +1024,13 @@ hr {
984
1024
  font-weight: var(--ds-font-display-weight);
985
1025
  font-size: var(--ds-text-2xl);
986
1026
  color: var(--ds-color-text);
987
- margin-top: var(--ds-space-1);
1027
+ margin-block-start: var(--ds-space-1);
988
1028
  }
989
1029
 
990
1030
  .ds-stat-card__detail {
991
1031
  font-size: var(--ds-text-xs);
992
1032
  color: var(--ds-color-text-tertiary);
993
- margin-top: var(--ds-space-0-5);
1033
+ margin-block-start: var(--ds-space-0-5);
994
1034
  }
995
1035
 
996
1036
  .ds-stat-card__icon {
@@ -1007,6 +1047,13 @@ hr {
1007
1047
  /* ==========================================================================
1008
1048
  Component: Form Inputs
1009
1049
  Surface bg, clean borders, focus ring.
1050
+
1051
+ ARIA requirements (consumer responsibility):
1052
+ - Input: associate with <label for="id"> or aria-label
1053
+ - Error state: add aria-invalid="true" + aria-describedby pointing to error msg
1054
+ - Required: add aria-required="true" or HTML required attribute
1055
+ - Input group: icon is decorative (pointer-events: none), no ARIA needed
1056
+ - Checkbox/radio: use native <input type="checkbox|radio"> inside <label>
1010
1057
  ========================================================================== */
1011
1058
 
1012
1059
  .ds-label {
@@ -1014,7 +1061,7 @@ hr {
1014
1061
  font-size: var(--ds-text-sm);
1015
1062
  font-weight: var(--ds-weight-medium);
1016
1063
  color: var(--ds-color-text-secondary);
1017
- margin-bottom: var(--ds-space-1-5);
1064
+ margin-block-end: var(--ds-space-1-5);
1018
1065
  }
1019
1066
 
1020
1067
  .ds-input,
@@ -1061,6 +1108,7 @@ hr {
1061
1108
  .ds-select:focus-visible {
1062
1109
  border-color: var(--ds-ring-color);
1063
1110
  box-shadow: 0 0 0 var(--ds-ring-width) var(--ds-ring-color);
1111
+ scroll-margin-block: var(--ds-space-16, 4rem);
1064
1112
  }
1065
1113
 
1066
1114
  .ds-input::placeholder,
@@ -1120,7 +1168,7 @@ hr {
1120
1168
  }
1121
1169
 
1122
1170
  .ds-select--lg {
1123
- padding-right: var(--ds-space-8);
1171
+ padding-inline-end: var(--ds-space-8);
1124
1172
  }
1125
1173
 
1126
1174
  /* Textarea */
@@ -1137,7 +1185,7 @@ hr {
1137
1185
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23a1a1aa' d='M2 4l4 4 4-4'/%3E%3C/svg%3E");
1138
1186
  background-repeat: no-repeat;
1139
1187
  background-position: right var(--ds-space-3) center;
1140
- padding-right: var(--ds-space-8);
1188
+ padding-inline-end: var(--ds-space-8);
1141
1189
  }
1142
1190
 
1143
1191
  /* --- Layout Modifiers ---
@@ -1176,35 +1224,35 @@ hr {
1176
1224
  /* --- Input Group: icon-right ---
1177
1225
  Move icon to the right side, flip input padding. */
1178
1226
  .ds-input-group--icon-right .ds-input-group__icon {
1179
- left: auto;
1180
- right: var(--ds-space-3);
1227
+ inset-inline-start: auto;
1228
+ inset-inline-end: var(--ds-space-3);
1181
1229
  }
1182
1230
  .ds-input-group--icon-right .ds-input {
1183
- padding-left: var(--ds-space-4);
1184
- padding-right: calc(var(--ds-space-3) + 1rem + var(--ds-space-2));
1231
+ padding-inline-start: var(--ds-space-4);
1232
+ padding-inline-end: calc(var(--ds-space-3) + 1rem + var(--ds-space-2));
1185
1233
  }
1186
1234
 
1187
1235
  /* Help text */
1188
1236
  .ds-help {
1189
1237
  font-size: var(--ds-text-xs);
1190
1238
  color: var(--ds-color-text-tertiary);
1191
- margin-top: var(--ds-space-1-5);
1239
+ margin-block-start: var(--ds-space-1-5);
1192
1240
  }
1193
1241
  .ds-help--error { color: var(--ds-color-error); }
1194
1242
 
1195
1243
  /* Form Group (legacy — prefer ds-form) */
1196
- .ds-form-group { margin-bottom: var(--ds-space-4); }
1244
+ .ds-form-group { margin-block-end: var(--ds-space-4); }
1197
1245
 
1198
1246
  /* --- Form Stack ---
1199
1247
  Vertical form layout: comfortable spacing between fields (24px),
1200
1248
  extra breathing room before the action area (32px).
1201
1249
  Use ds-form__actions on the button/submit wrapper. */
1202
1250
  .ds-form > * + * {
1203
- margin-top: var(--ds-space-6);
1251
+ margin-block-start: var(--ds-space-6);
1204
1252
  }
1205
1253
 
1206
1254
  .ds-form__actions {
1207
- margin-top: var(--ds-space-8);
1255
+ margin-block-start: var(--ds-space-8);
1208
1256
  }
1209
1257
 
1210
1258
  /* --- Input Group ---
@@ -1216,8 +1264,8 @@ hr {
1216
1264
 
1217
1265
  .ds-input-group__icon {
1218
1266
  position: absolute;
1219
- left: var(--ds-space-3);
1220
- top: 50%;
1267
+ inset-inline-start: var(--ds-space-3);
1268
+ inset-block-start: 50%;
1221
1269
  transform: translateY(-50%);
1222
1270
  display: flex;
1223
1271
  align-items: center;
@@ -1227,7 +1275,7 @@ hr {
1227
1275
  }
1228
1276
 
1229
1277
  .ds-input-group .ds-input {
1230
- padding-left: calc(var(--ds-space-3) + 1rem + var(--ds-space-2));
1278
+ padding-inline-start: calc(var(--ds-space-3) + 1rem + var(--ds-space-2));
1231
1279
  }
1232
1280
 
1233
1281
  /* Checkbox / Radio */
@@ -1243,8 +1291,88 @@ hr {
1243
1291
  .ds-checkbox input,
1244
1292
  .ds-radio input {
1245
1293
  accent-color: var(--ds-color-interactive);
1246
- width: 0.875rem;
1247
- height: 0.875rem;
1294
+ width: 1rem;
1295
+ height: 1rem;
1296
+ min-width: 1.5rem; /* WCAG 2.5.8: minimum 24px target */
1297
+ min-height: 1.5rem;
1298
+ }
1299
+
1300
+ /* ==========================================================================
1301
+ Component: Field
1302
+ Unified wrapper for form fields — label + input + hint + error.
1303
+ ========================================================================== */
1304
+
1305
+ /* ---------------------------------------------------------------------------
1306
+ Container
1307
+ --------------------------------------------------------------------------- */
1308
+
1309
+ .ds-field {
1310
+ display: flex;
1311
+ flex-direction: column;
1312
+ gap: var(--ds-space-1-5);
1313
+ }
1314
+
1315
+ /* ---------------------------------------------------------------------------
1316
+ Label
1317
+ --------------------------------------------------------------------------- */
1318
+
1319
+ .ds-field__label {
1320
+ font-family: var(--ds-font-sans);
1321
+ font-size: var(--ds-text-sm);
1322
+ font-weight: var(--ds-weight-medium);
1323
+ color: var(--ds-color-text);
1324
+ line-height: var(--ds-leading-normal);
1325
+ }
1326
+
1327
+ /* Required asterisk */
1328
+ .ds-field--required .ds-field__label::after {
1329
+ content: " *";
1330
+ color: var(--ds-color-error);
1331
+ }
1332
+
1333
+ /* ---------------------------------------------------------------------------
1334
+ Hint (help text below input)
1335
+ --------------------------------------------------------------------------- */
1336
+
1337
+ .ds-field__hint {
1338
+ font-size: var(--ds-text-xs);
1339
+ color: var(--ds-color-text-tertiary);
1340
+ line-height: var(--ds-leading-normal);
1341
+ }
1342
+
1343
+ /* ---------------------------------------------------------------------------
1344
+ Error message
1345
+ --------------------------------------------------------------------------- */
1346
+
1347
+ .ds-field__error {
1348
+ font-size: var(--ds-text-xs);
1349
+ color: var(--ds-color-error);
1350
+ line-height: var(--ds-leading-normal);
1351
+ }
1352
+
1353
+ /* ---------------------------------------------------------------------------
1354
+ Modifier: Horizontal layout (label left, input right)
1355
+ --------------------------------------------------------------------------- */
1356
+
1357
+ .ds-field--horizontal {
1358
+ flex-direction: row;
1359
+ align-items: flex-start;
1360
+ gap: var(--ds-space-4);
1361
+ }
1362
+
1363
+ .ds-field--horizontal .ds-field__label {
1364
+ flex-shrink: 0;
1365
+ min-width: 8rem;
1366
+ padding-block-start: var(--ds-space-2);
1367
+ }
1368
+
1369
+ /* ---------------------------------------------------------------------------
1370
+ Modifier: Disabled
1371
+ --------------------------------------------------------------------------- */
1372
+
1373
+ .ds-field--disabled {
1374
+ opacity: var(--ds-opacity-disabled);
1375
+ pointer-events: none;
1248
1376
  }
1249
1377
 
1250
1378
  /* ==========================================================================
@@ -1331,20 +1459,27 @@ hr {
1331
1459
  /* ==========================================================================
1332
1460
  Component: Navigation
1333
1461
  Fixed glass header, backdrop-blur, h-16. Clean links.
1462
+
1463
+ ARIA requirements (consumer responsibility):
1464
+ - Nav: <nav aria-label="Main navigation"> (or aria-label="Sidebar")
1465
+ - Active link: aria-current="page" on the current page link
1466
+ - Mobile menu: toggle aria-expanded on hamburger button
1467
+ - Mobile menu button: aria-label="Open menu" / "Close menu"
1468
+ - Skip nav: add ds-skip-link before nav to skip to main content
1334
1469
  ========================================================================== */
1335
1470
 
1336
1471
  .ds-nav {
1337
1472
  position: fixed;
1338
- top: 0;
1339
- left: 0;
1340
- right: 0;
1473
+ inset-block-start: 0;
1474
+ inset-inline-start: 0;
1475
+ inset-inline-end: 0;
1341
1476
  z-index: var(--ds-z-sticky);
1342
1477
  display: flex;
1343
1478
  align-items: center;
1344
1479
  justify-content: space-between;
1345
1480
  height: 4rem;
1346
1481
  background-color: var(--ds-color-nav-bg);
1347
- border-bottom: 1px solid var(--ds-color-nav-border);
1482
+ border-block-end: 1px solid var(--ds-color-nav-border);
1348
1483
  backdrop-filter: blur(var(--ds-blur-lg)) saturate(1.5);
1349
1484
  -webkit-backdrop-filter: blur(var(--ds-blur-lg)) saturate(1.5);
1350
1485
  }
@@ -1392,6 +1527,7 @@ hr {
1392
1527
  .ds-nav__link:focus-visible {
1393
1528
  outline: none;
1394
1529
  box-shadow: 0 0 0 var(--ds-ring-width) var(--ds-ring-color);
1530
+ scroll-margin-block: var(--ds-space-16, 4rem);
1395
1531
  }
1396
1532
 
1397
1533
  .ds-nav__link--active {
@@ -1426,13 +1562,14 @@ hr {
1426
1562
  .ds-nav__icon-btn:focus-visible {
1427
1563
  outline: none;
1428
1564
  box-shadow: 0 0 0 var(--ds-ring-width) var(--ds-ring-color);
1565
+ scroll-margin-block: var(--ds-space-16, 4rem);
1429
1566
  }
1430
1567
 
1431
1568
  /* --- Mobile nav overlay --- */
1432
1569
  .ds-nav__mobile {
1433
1570
  overflow: hidden;
1434
1571
  max-height: 0;
1435
- border-bottom: 0 solid var(--ds-color-nav-border);
1572
+ border-block-end: 0 solid var(--ds-color-nav-border);
1436
1573
  background-color: var(--ds-color-nav-bg);
1437
1574
  backdrop-filter: blur(var(--ds-blur-lg));
1438
1575
  transition: all var(--ds-duration-slow) var(--ds-ease-out-expo);
@@ -1440,7 +1577,7 @@ hr {
1440
1577
 
1441
1578
  .ds-nav__mobile--open {
1442
1579
  max-height: 16rem;
1443
- border-bottom-width: 1px;
1580
+ border-block-end-width: 1px;
1444
1581
  }
1445
1582
 
1446
1583
  .ds-nav__mobile-links {
@@ -1463,12 +1600,12 @@ hr {
1463
1600
  width: 16rem;
1464
1601
  padding: var(--ds-space-5);
1465
1602
  background-color: var(--ds-color-surface);
1466
- border-right: 1px solid var(--ds-color-border);
1603
+ border-inline-end: 1px solid var(--ds-color-border);
1467
1604
  height: 100%;
1468
1605
  }
1469
1606
 
1470
1607
  .ds-sidebar__section {
1471
- margin-bottom: var(--ds-space-6);
1608
+ margin-block-end: var(--ds-space-6);
1472
1609
  }
1473
1610
 
1474
1611
  .ds-sidebar__title {
@@ -1477,7 +1614,7 @@ hr {
1477
1614
  text-transform: uppercase;
1478
1615
  letter-spacing: var(--ds-tracking-wide);
1479
1616
  color: var(--ds-color-text-tertiary);
1480
- margin-bottom: var(--ds-space-3);
1617
+ margin-block-end: var(--ds-space-3);
1481
1618
  }
1482
1619
 
1483
1620
  .ds-sidebar__link {
@@ -1492,7 +1629,7 @@ hr {
1492
1629
  transition: all var(--ds-duration-normal) var(--ds-ease-default);
1493
1630
  }
1494
1631
  .ds-sidebar__link + .ds-sidebar__link {
1495
- margin-top: var(--ds-space-1);
1632
+ margin-block-start: var(--ds-space-1);
1496
1633
  }
1497
1634
 
1498
1635
  @media (hover: hover) {
@@ -1505,9 +1642,11 @@ hr {
1505
1642
  .ds-sidebar__link:focus-visible {
1506
1643
  outline: none;
1507
1644
  box-shadow: inset 0 0 0 var(--ds-ring-width) var(--ds-ring-color);
1645
+ scroll-margin-block: var(--ds-space-16, 4rem);
1508
1646
  }
1509
1647
 
1510
- .ds-sidebar__link--active {
1648
+ .ds-sidebar__link--active,
1649
+ .ds-sidebar__link--active:hover {
1511
1650
  color: var(--ds-color-text);
1512
1651
  background-color: var(--ds-color-bg-elevated);
1513
1652
  }
@@ -1515,6 +1654,14 @@ hr {
1515
1654
  /* ==========================================================================
1516
1655
  Component: Modal
1517
1656
  Backdrop blur, shadow-2xl, rounded-xl. Smooth scale transition.
1657
+
1658
+ ARIA requirements (consumer responsibility):
1659
+ - Container: role="dialog", aria-modal="true", aria-labelledby="[title-id]"
1660
+ - Close button: aria-label="Close"
1661
+ - Focus: trap focus inside modal when open
1662
+ - Keyboard: Escape closes modal
1663
+ - On open: move focus to first focusable element or close button
1664
+ - On close: return focus to the element that triggered the modal
1518
1665
  ========================================================================== */
1519
1666
 
1520
1667
  .ds-modal {
@@ -1566,7 +1713,7 @@ hr {
1566
1713
  align-items: flex-start;
1567
1714
  justify-content: space-between;
1568
1715
  padding: var(--ds-space-4) var(--ds-space-5);
1569
- border-bottom: 1px solid var(--ds-color-border);
1716
+ border-block-end: 1px solid var(--ds-color-border);
1570
1717
  }
1571
1718
 
1572
1719
  .ds-modal__header h3 {
@@ -1579,7 +1726,7 @@ hr {
1579
1726
  .ds-modal__header p {
1580
1727
  font-size: var(--ds-text-sm);
1581
1728
  color: var(--ds-color-text-tertiary);
1582
- margin-top: var(--ds-space-1);
1729
+ margin-block-start: var(--ds-space-1);
1583
1730
  }
1584
1731
 
1585
1732
  .ds-modal__close {
@@ -1599,6 +1746,7 @@ hr {
1599
1746
  .ds-modal__close:focus-visible {
1600
1747
  outline: none;
1601
1748
  box-shadow: 0 0 0 var(--ds-ring-width) var(--ds-ring-color);
1749
+ scroll-margin-block: var(--ds-space-16, 4rem);
1602
1750
  }
1603
1751
 
1604
1752
  .ds-modal__body {
@@ -1613,7 +1761,7 @@ hr {
1613
1761
  justify-content: flex-end;
1614
1762
  gap: var(--ds-space-2);
1615
1763
  padding: var(--ds-space-4) var(--ds-space-5);
1616
- border-top: 1px solid var(--ds-color-border);
1764
+ border-block-start: 1px solid var(--ds-color-border);
1617
1765
  }
1618
1766
 
1619
1767
  /* Size variants */
@@ -1621,7 +1769,7 @@ hr {
1621
1769
  .ds-modal--lg .ds-modal__content { max-width: var(--ds-container-lg); }
1622
1770
 
1623
1771
  /* Fullscreen on mobile */
1624
- @media (max-width: 1023px) {
1772
+ @media (max-width: 1023px) /* below --ds-breakpoint-lg */ {
1625
1773
  .ds-modal--fullscreen-mobile .ds-modal__content {
1626
1774
  max-width: none;
1627
1775
  max-height: none;
@@ -1640,6 +1788,12 @@ hr {
1640
1788
 
1641
1789
  /* ==========================================================================
1642
1790
  Component: Toast
1791
+
1792
+ ARIA requirements (consumer responsibility):
1793
+ - Container: role="status", aria-live="polite" (or role="alert" for errors)
1794
+ - Close button: aria-label="Dismiss notification"
1795
+ - Auto-dismiss: provide enough time (minimum 5s), or let user control
1796
+ - Toast region: wrap container in aria-label="Notifications"
1643
1797
  ========================================================================== */
1644
1798
 
1645
1799
  .ds-toast-container {
@@ -1652,10 +1806,10 @@ hr {
1652
1806
  pointer-events: none;
1653
1807
  }
1654
1808
 
1655
- .ds-toast-container--top-right { top: 0; right: 0; }
1656
- .ds-toast-container--bottom-right { bottom: 0; right: 0; }
1809
+ .ds-toast-container--top-right { inset-block-start: 0; inset-inline-end: 0; }
1810
+ .ds-toast-container--bottom-right { inset-block-end: 0; inset-inline-end: 0; }
1657
1811
  .ds-toast-container--bottom-center {
1658
- bottom: 0; left: 50%;
1812
+ inset-block-end: 0; inset-inline-start: 50%;
1659
1813
  transform: translateX(-50%);
1660
1814
  align-items: center;
1661
1815
  }
@@ -1675,10 +1829,10 @@ hr {
1675
1829
  animation: ds-toast-in var(--ds-duration-slow) var(--ds-ease-out-expo) forwards;
1676
1830
  }
1677
1831
 
1678
- .ds-toast--info { border-left: var(--ds-accent-border-width) solid var(--ds-color-info); }
1679
- .ds-toast--success { border-left: var(--ds-accent-border-width) solid var(--ds-color-success); }
1680
- .ds-toast--warning { border-left: var(--ds-accent-border-width) solid var(--ds-color-warning); }
1681
- .ds-toast--error { border-left: var(--ds-accent-border-width) solid var(--ds-color-error); }
1832
+ .ds-toast--info { border-inline-start: var(--ds-accent-border-width) solid var(--ds-color-info); }
1833
+ .ds-toast--success { border-inline-start: var(--ds-accent-border-width) solid var(--ds-color-success); }
1834
+ .ds-toast--warning { border-inline-start: var(--ds-accent-border-width) solid var(--ds-color-warning); }
1835
+ .ds-toast--error { border-inline-start: var(--ds-accent-border-width) solid var(--ds-color-error); }
1682
1836
 
1683
1837
  .ds-toast__message {
1684
1838
  flex: 1;
@@ -1695,9 +1849,15 @@ hr {
1695
1849
  .ds-toast__close:hover {
1696
1850
  color: var(--ds-color-text);
1697
1851
  }
1852
+ .ds-toast__close {
1853
+ min-width: 1.5rem; /* WCAG 2.5.8: minimum 24px target */
1854
+ min-height: 1.5rem;
1855
+ }
1856
+
1698
1857
  .ds-toast__close:focus-visible {
1699
1858
  outline: none;
1700
1859
  box-shadow: 0 0 0 var(--ds-ring-width) var(--ds-ring-color);
1860
+ scroll-margin-block: var(--ds-space-16, 4rem);
1701
1861
  }
1702
1862
 
1703
1863
  @keyframes ds-toast-in {
@@ -1724,7 +1884,7 @@ hr {
1724
1884
 
1725
1885
  .ds-table {
1726
1886
  width: 100%;
1727
- text-align: left;
1887
+ text-align: start;
1728
1888
  font-size: var(--ds-text-sm);
1729
1889
  }
1730
1890
 
@@ -1735,13 +1895,13 @@ hr {
1735
1895
  color: var(--ds-color-text-tertiary);
1736
1896
  text-transform: uppercase;
1737
1897
  letter-spacing: var(--ds-tracking-wide);
1738
- border-bottom: 1px solid var(--ds-color-border);
1898
+ border-block-end: 1px solid var(--ds-color-border);
1739
1899
  }
1740
1900
 
1741
1901
  .ds-table td {
1742
1902
  padding: var(--ds-space-3) var(--ds-space-4);
1743
1903
  color: var(--ds-color-text);
1744
- border-bottom: 1px solid var(--ds-color-border-subtle);
1904
+ border-block-end: 1px solid var(--ds-color-border-subtle);
1745
1905
  }
1746
1906
 
1747
1907
  .ds-table tbody tr {
@@ -1772,20 +1932,27 @@ hr {
1772
1932
  /* ==========================================================================
1773
1933
  Component: Tabs
1774
1934
  Horizontal/vertical tab navigation with pill, small, and full-width variants.
1935
+
1936
+ ARIA requirements (consumer responsibility):
1937
+ - Tab list: role="tablist", aria-label="[description]"
1938
+ - Tab: role="tab", aria-selected="true|false", aria-controls="[panel-id]"
1939
+ - Tab panel: role="tabpanel", id matching aria-controls, aria-labelledby="[tab-id]"
1940
+ - Keyboard: ArrowLeft/Right (horizontal) or ArrowUp/Down (vertical) to navigate
1941
+ - Active tab: only the active tab should be in tab order (tabindex="0"), others tabindex="-1"
1775
1942
  ========================================================================== */
1776
1943
 
1777
1944
  .ds-tabs {
1778
1945
  display: flex;
1779
1946
  flex-direction: row;
1780
1947
  align-items: stretch;
1781
- border-bottom: 1px solid var(--ds-color-border);
1948
+ border-block-end: 1px solid var(--ds-color-border);
1782
1949
  gap: var(--ds-space-0);
1783
1950
  }
1784
1951
 
1785
1952
  /* --- Pill variant --- */
1786
1953
 
1787
1954
  .ds-tabs--pills {
1788
- border-bottom: none;
1955
+ border-block-end: none;
1789
1956
  gap: var(--ds-space-1);
1790
1957
  background-color: var(--ds-color-bg-elevated);
1791
1958
  border-radius: var(--ds-radius-lg);
@@ -1793,7 +1960,7 @@ hr {
1793
1960
  }
1794
1961
 
1795
1962
  .ds-tabs--pills .ds-tab {
1796
- border-bottom: none;
1963
+ border-block-end: none;
1797
1964
  border-radius: var(--ds-radius-md);
1798
1965
  padding: var(--ds-space-1-5) var(--ds-space-3);
1799
1966
  }
@@ -1806,28 +1973,28 @@ hr {
1806
1973
  background-color: var(--ds-color-surface);
1807
1974
  color: var(--ds-color-text);
1808
1975
  box-shadow: var(--ds-shadow-sm);
1809
- border-bottom: none;
1976
+ border-block-end: none;
1810
1977
  }
1811
1978
 
1812
1979
  /* --- Vertical variant --- */
1813
1980
 
1814
1981
  .ds-tabs--vertical {
1815
1982
  flex-direction: column;
1816
- border-bottom: none;
1817
- border-right: 1px solid var(--ds-color-border);
1983
+ border-block-end: none;
1984
+ border-inline-end: 1px solid var(--ds-color-border);
1818
1985
  gap: var(--ds-space-0-5);
1819
1986
  }
1820
1987
 
1821
1988
  .ds-tabs--vertical .ds-tab {
1822
- border-bottom: none;
1823
- border-right: 2px solid transparent;
1989
+ border-block-end: none;
1990
+ border-inline-end: 2px solid transparent;
1824
1991
  padding: var(--ds-space-2) var(--ds-space-4);
1825
- text-align: left;
1992
+ text-align: start;
1826
1993
  }
1827
1994
 
1828
1995
  .ds-tabs--vertical .ds-tab--active {
1829
- border-bottom: none;
1830
- border-right-color: var(--ds-color-interactive);
1996
+ border-block-end: none;
1997
+ border-inline-end-color: var(--ds-color-interactive);
1831
1998
  color: var(--ds-color-text);
1832
1999
  }
1833
2000
 
@@ -1862,14 +2029,14 @@ hr {
1862
2029
  line-height: var(--ds-leading-snug);
1863
2030
  color: var(--ds-color-text-secondary);
1864
2031
  cursor: pointer;
1865
- border-bottom: 2px solid transparent;
2032
+ border-block-end: 2px solid transparent;
1866
2033
  background: none;
1867
- border-top: none;
1868
- border-left: none;
1869
- border-right: none;
2034
+ border-block-start: none;
2035
+ border-inline-start: none;
2036
+ border-inline-end: none;
1870
2037
  white-space: nowrap;
1871
2038
  transition: all var(--ds-duration-fast) var(--ds-ease-default);
1872
- margin-bottom: -1px;
2039
+ margin-block-end: -1px;
1873
2040
  }
1874
2041
 
1875
2042
  .ds-tab:hover {
@@ -1880,11 +2047,12 @@ hr {
1880
2047
  outline: none;
1881
2048
  box-shadow: 0 0 0 var(--ds-ring-width) var(--ds-ring-color);
1882
2049
  border-radius: var(--ds-radius-sm);
2050
+ scroll-margin-block: var(--ds-space-16, 4rem);
1883
2051
  }
1884
2052
 
1885
2053
  .ds-tab--active {
1886
2054
  color: var(--ds-color-text);
1887
- border-bottom-color: var(--ds-color-interactive);
2055
+ border-block-end-color: var(--ds-color-interactive);
1888
2056
  }
1889
2057
 
1890
2058
  .ds-tab:disabled,
@@ -1930,12 +2098,17 @@ hr {
1930
2098
  /* --- Tab Panel --- */
1931
2099
 
1932
2100
  .ds-tab-panel {
1933
- padding-top: var(--ds-space-5);
2101
+ padding-block-start: var(--ds-space-5);
1934
2102
  }
1935
2103
 
1936
2104
  /* ==========================================================================
1937
2105
  Component: Alert
1938
2106
  Contextual feedback banners with semantic variants and dismissibility.
2107
+
2108
+ ARIA requirements (consumer responsibility):
2109
+ - Container: role="alert" (for important messages) or role="status"
2110
+ - Dismissible: close button needs aria-label="Dismiss"
2111
+ - For non-urgent info, use role="status" instead of role="alert"
1939
2112
  ========================================================================== */
1940
2113
 
1941
2114
  .ds-alert {
@@ -1947,7 +2120,7 @@ hr {
1947
2120
  border: 1px solid var(--ds-color-border);
1948
2121
  border-radius: var(--ds-radius-lg);
1949
2122
  background-color: var(--ds-color-surface);
1950
- border-left: var(--ds-accent-border-width) solid var(--ds-color-border);
2123
+ border-inline-start: var(--ds-accent-border-width) solid var(--ds-color-border);
1951
2124
  }
1952
2125
 
1953
2126
  /* --- Semantic Variants --- */
@@ -1955,25 +2128,25 @@ hr {
1955
2128
  .ds-alert--info {
1956
2129
  background-color: var(--ds-color-info-subtle);
1957
2130
  border-color: var(--ds-color-info-border);
1958
- border-left-color: var(--ds-color-info);
2131
+ border-inline-start-color: var(--ds-color-info);
1959
2132
  }
1960
2133
 
1961
2134
  .ds-alert--success {
1962
2135
  background-color: var(--ds-color-success-subtle);
1963
2136
  border-color: var(--ds-color-success-border);
1964
- border-left-color: var(--ds-color-success);
2137
+ border-inline-start-color: var(--ds-color-success);
1965
2138
  }
1966
2139
 
1967
2140
  .ds-alert--warning {
1968
2141
  background-color: var(--ds-color-warning-subtle);
1969
2142
  border-color: var(--ds-color-warning-border);
1970
- border-left-color: var(--ds-color-warning);
2143
+ border-inline-start-color: var(--ds-color-warning);
1971
2144
  }
1972
2145
 
1973
2146
  .ds-alert--error {
1974
2147
  background-color: var(--ds-color-error-subtle);
1975
2148
  border-color: var(--ds-color-error-border);
1976
- border-left-color: var(--ds-color-error);
2149
+ border-inline-start-color: var(--ds-color-error);
1977
2150
  }
1978
2151
 
1979
2152
  /* --- Icon --- */
@@ -2012,11 +2185,11 @@ hr {
2012
2185
  font-size: var(--ds-text-sm);
2013
2186
  line-height: var(--ds-leading-normal);
2014
2187
  color: var(--ds-color-text-secondary);
2015
- margin-top: var(--ds-space-1);
2188
+ margin-block-start: var(--ds-space-1);
2016
2189
  }
2017
2190
 
2018
2191
  .ds-alert__title + .ds-alert__description {
2019
- margin-top: var(--ds-space-1);
2192
+ margin-block-start: var(--ds-space-1);
2020
2193
  }
2021
2194
 
2022
2195
  /* --- Close Button --- */
@@ -2044,6 +2217,7 @@ hr {
2044
2217
  .ds-alert__close:focus-visible {
2045
2218
  outline: none;
2046
2219
  box-shadow: 0 0 0 var(--ds-ring-width) var(--ds-ring-color);
2220
+ scroll-margin-block: var(--ds-space-16, 4rem);
2047
2221
  }
2048
2222
 
2049
2223
  /* --- Compact Variant --- */
@@ -2057,31 +2231,31 @@ hr {
2057
2231
 
2058
2232
  .ds-alert--banner {
2059
2233
  border-radius: var(--ds-radius-none);
2060
- border-left: none;
2061
- border-right: none;
2062
- border-top: 1px solid var(--ds-color-border);
2063
- border-bottom: 1px solid var(--ds-color-border);
2234
+ border-inline-start: none;
2235
+ border-inline-end: none;
2236
+ border-block-start: 1px solid var(--ds-color-border);
2237
+ border-block-end: 1px solid var(--ds-color-border);
2064
2238
  width: 100%;
2065
2239
  }
2066
2240
 
2067
2241
  .ds-alert--banner.ds-alert--info {
2068
- border-top-color: var(--ds-color-info-border);
2069
- border-bottom-color: var(--ds-color-info-border);
2242
+ border-block-start-color: var(--ds-color-info-border);
2243
+ border-block-end-color: var(--ds-color-info-border);
2070
2244
  }
2071
2245
 
2072
2246
  .ds-alert--banner.ds-alert--success {
2073
- border-top-color: var(--ds-color-success-border);
2074
- border-bottom-color: var(--ds-color-success-border);
2247
+ border-block-start-color: var(--ds-color-success-border);
2248
+ border-block-end-color: var(--ds-color-success-border);
2075
2249
  }
2076
2250
 
2077
2251
  .ds-alert--banner.ds-alert--warning {
2078
- border-top-color: var(--ds-color-warning-border);
2079
- border-bottom-color: var(--ds-color-warning-border);
2252
+ border-block-start-color: var(--ds-color-warning-border);
2253
+ border-block-end-color: var(--ds-color-warning-border);
2080
2254
  }
2081
2255
 
2082
2256
  .ds-alert--banner.ds-alert--error {
2083
- border-top-color: var(--ds-color-error-border);
2084
- border-bottom-color: var(--ds-color-error-border);
2257
+ border-block-start-color: var(--ds-color-error-border);
2258
+ border-block-end-color: var(--ds-color-error-border);
2085
2259
  }
2086
2260
 
2087
2261
  /* ==========================================================================
@@ -2100,7 +2274,7 @@ hr {
2100
2274
 
2101
2275
  .ds-divider--vertical {
2102
2276
  border-top: none;
2103
- border-left: 1px solid var(--ds-color-border);
2277
+ border-inline-start: 1px solid var(--ds-color-border);
2104
2278
  display: inline-block;
2105
2279
  width: auto;
2106
2280
  height: auto;
@@ -2154,6 +2328,14 @@ hr {
2154
2328
  /* ==========================================================================
2155
2329
  Component: Dropdown
2156
2330
  Floating menu with surface bg, scale transition, keyboard-friendly items.
2331
+
2332
+ ARIA requirements (consumer responsibility):
2333
+ - Trigger: aria-haspopup="true", aria-expanded="true|false"
2334
+ - Menu: role="menu"
2335
+ - Items: role="menuitem"
2336
+ - Keyboard: ArrowUp/Down to navigate, Enter to select, Escape to close
2337
+ - On open: move focus to first menu item
2338
+ - On close: return focus to trigger
2157
2339
  ========================================================================== */
2158
2340
 
2159
2341
  .ds-dropdown {
@@ -2170,8 +2352,8 @@ hr {
2170
2352
 
2171
2353
  .ds-dropdown__menu {
2172
2354
  position: absolute;
2173
- top: calc(100% + var(--ds-space-1));
2174
- left: 0;
2355
+ inset-block-start: calc(100% + var(--ds-space-1));
2356
+ inset-inline-start: 0;
2175
2357
  z-index: var(--ds-z-dropdown);
2176
2358
  min-width: 12rem;
2177
2359
  padding-block: var(--ds-space-1-5);
@@ -2201,14 +2383,14 @@ hr {
2201
2383
  /* --- Alignment variants --- */
2202
2384
 
2203
2385
  .ds-dropdown__menu--right {
2204
- left: auto;
2205
- right: 0;
2386
+ inset-inline-start: auto;
2387
+ inset-inline-end: 0;
2206
2388
  transform-origin: top right;
2207
2389
  }
2208
2390
 
2209
2391
  .ds-dropdown__menu--up {
2210
- top: auto;
2211
- bottom: calc(100% + var(--ds-space-1));
2392
+ inset-block-start: auto;
2393
+ inset-block-end: calc(100% + var(--ds-space-1));
2212
2394
  transform-origin: bottom left;
2213
2395
  }
2214
2396
 
@@ -2246,6 +2428,7 @@ hr {
2246
2428
  .ds-dropdown__item:focus-visible {
2247
2429
  outline: none;
2248
2430
  box-shadow: inset 0 0 0 var(--ds-ring-width) var(--ds-ring-color);
2431
+ scroll-margin-block: var(--ds-space-16, 4rem);
2249
2432
  }
2250
2433
 
2251
2434
  .ds-dropdown__item--active {
@@ -2275,7 +2458,7 @@ hr {
2275
2458
  }
2276
2459
 
2277
2460
  .ds-dropdown__item-shortcut {
2278
- margin-left: auto;
2461
+ margin-inline-start: auto;
2279
2462
  font-size: var(--ds-text-xs);
2280
2463
  color: var(--ds-color-text-tertiary);
2281
2464
  }
@@ -2285,7 +2468,7 @@ hr {
2285
2468
  .ds-dropdown__divider {
2286
2469
  margin-block: var(--ds-space-1);
2287
2470
  border: 0;
2288
- border-top: 1px solid var(--ds-color-border);
2471
+ border-block-start: 1px solid var(--ds-color-border);
2289
2472
  }
2290
2473
 
2291
2474
  /* --- Section header --- */
@@ -2304,6 +2487,12 @@ hr {
2304
2487
  Component: Tooltip
2305
2488
  Inverted bubble with arrow, positioned via modifier classes.
2306
2489
  Default placement: top.
2490
+
2491
+ ARIA requirements (consumer responsibility):
2492
+ - Tooltip content: role="tooltip", id="[tooltip-id]"
2493
+ - Trigger element: aria-describedby="[tooltip-id]"
2494
+ - Keyboard: tooltip should show on focus as well as hover (CSS handles this via :hover)
2495
+ - For focus support: also add :focus-within show logic if trigger is focusable
2307
2496
  ========================================================================== */
2308
2497
 
2309
2498
  .ds-tooltip {
@@ -2364,8 +2553,8 @@ hr {
2364
2553
 
2365
2554
  .ds-tooltip .ds-tooltip__content,
2366
2555
  .ds-tooltip--top .ds-tooltip__content {
2367
- bottom: calc(100% + var(--ds-offset-md));
2368
- left: 50%;
2556
+ inset-block-end: calc(100% + var(--ds-offset-md));
2557
+ inset-inline-start: 50%;
2369
2558
  transform: translateX(-50%) translateY(4px);
2370
2559
  }
2371
2560
 
@@ -2377,8 +2566,8 @@ hr {
2377
2566
  /* Arrow — points down */
2378
2567
  .ds-tooltip .ds-tooltip__content::after,
2379
2568
  .ds-tooltip--top .ds-tooltip__content::after {
2380
- top: 100%;
2381
- left: 50%;
2569
+ inset-block-start: 100%;
2570
+ inset-inline-start: 50%;
2382
2571
  transform: translateX(-50%);
2383
2572
  border-top-color: var(--ds-color-inverted);
2384
2573
  }
@@ -2388,9 +2577,9 @@ hr {
2388
2577
  ============================================= */
2389
2578
 
2390
2579
  .ds-tooltip--bottom .ds-tooltip__content {
2391
- top: calc(100% + var(--ds-offset-md));
2392
- bottom: auto;
2393
- left: 50%;
2580
+ inset-block-start: calc(100% + var(--ds-offset-md));
2581
+ inset-block-end: auto;
2582
+ inset-inline-start: 50%;
2394
2583
  transform: translateX(-50%) translateY(-4px);
2395
2584
  }
2396
2585
 
@@ -2400,9 +2589,9 @@ hr {
2400
2589
 
2401
2590
  /* Arrow — points up */
2402
2591
  .ds-tooltip--bottom .ds-tooltip__content::after {
2403
- bottom: 100%;
2404
- top: auto;
2405
- left: 50%;
2592
+ inset-block-end: 100%;
2593
+ inset-block-start: auto;
2594
+ inset-inline-start: 50%;
2406
2595
  transform: translateX(-50%);
2407
2596
  border-top-color: transparent;
2408
2597
  border-bottom-color: var(--ds-color-inverted);
@@ -2413,10 +2602,10 @@ hr {
2413
2602
  ============================================= */
2414
2603
 
2415
2604
  .ds-tooltip--left .ds-tooltip__content {
2416
- right: calc(100% + var(--ds-offset-md));
2417
- left: auto;
2418
- bottom: auto;
2419
- top: 50%;
2605
+ inset-inline-end: calc(100% + var(--ds-offset-md));
2606
+ inset-inline-start: auto;
2607
+ inset-block-end: auto;
2608
+ inset-block-start: 50%;
2420
2609
  transform: translateY(-50%) translateX(4px);
2421
2610
  }
2422
2611
 
@@ -2426,13 +2615,13 @@ hr {
2426
2615
 
2427
2616
  /* Arrow — points right */
2428
2617
  .ds-tooltip--left .ds-tooltip__content::after {
2429
- left: 100%;
2430
- top: 50%;
2431
- bottom: auto;
2432
- right: auto;
2618
+ inset-inline-start: 100%;
2619
+ inset-block-start: 50%;
2620
+ inset-block-end: auto;
2621
+ inset-inline-end: auto;
2433
2622
  transform: translateY(-50%);
2434
2623
  border-top-color: transparent;
2435
- border-left-color: var(--ds-color-inverted);
2624
+ border-inline-start-color: var(--ds-color-inverted);
2436
2625
  }
2437
2626
 
2438
2627
  /* =============================================
@@ -2440,10 +2629,10 @@ hr {
2440
2629
  ============================================= */
2441
2630
 
2442
2631
  .ds-tooltip--right .ds-tooltip__content {
2443
- left: calc(100% + var(--ds-offset-md));
2444
- right: auto;
2445
- bottom: auto;
2446
- top: 50%;
2632
+ inset-inline-start: calc(100% + var(--ds-offset-md));
2633
+ inset-inline-end: auto;
2634
+ inset-block-end: auto;
2635
+ inset-block-start: 50%;
2447
2636
  transform: translateY(-50%) translateX(-4px);
2448
2637
  }
2449
2638
 
@@ -2453,13 +2642,13 @@ hr {
2453
2642
 
2454
2643
  /* Arrow — points left */
2455
2644
  .ds-tooltip--right .ds-tooltip__content::after {
2456
- right: 100%;
2457
- left: auto;
2458
- top: 50%;
2459
- bottom: auto;
2645
+ inset-inline-end: 100%;
2646
+ inset-inline-start: auto;
2647
+ inset-block-start: 50%;
2648
+ inset-block-end: auto;
2460
2649
  transform: translateY(-50%);
2461
2650
  border-top-color: transparent;
2462
- border-right-color: var(--ds-color-inverted);
2651
+ border-inline-end-color: var(--ds-color-inverted);
2463
2652
  }
2464
2653
 
2465
2654
  /* ==========================================================================
@@ -2471,8 +2660,8 @@ hr {
2471
2660
  display: inline-flex;
2472
2661
  align-items: center;
2473
2662
  justify-content: center;
2474
- width: 2.5rem;
2475
- height: 2.5rem;
2663
+ width: var(--ds-size-3);
2664
+ height: var(--ds-size-3);
2476
2665
  border-radius: var(--ds-radius-full);
2477
2666
  background-color: var(--ds-color-bg-elevated);
2478
2667
  color: var(--ds-color-text-secondary);
@@ -2494,32 +2683,32 @@ hr {
2494
2683
  /* --- Sizes --- */
2495
2684
 
2496
2685
  .ds-avatar--xs {
2497
- width: 1.5rem;
2498
- height: 1.5rem;
2686
+ width: var(--ds-size-1);
2687
+ height: var(--ds-size-1);
2499
2688
  font-size: var(--ds-text-xs);
2500
2689
  }
2501
2690
 
2502
2691
  .ds-avatar--sm {
2503
- width: 2rem;
2504
- height: 2rem;
2692
+ width: var(--ds-size-2);
2693
+ height: var(--ds-size-2);
2505
2694
  font-size: var(--ds-text-xs);
2506
2695
  }
2507
2696
 
2508
2697
  .ds-avatar--md {
2509
- width: 2.5rem;
2510
- height: 2.5rem;
2698
+ width: var(--ds-size-3);
2699
+ height: var(--ds-size-3);
2511
2700
  font-size: var(--ds-text-sm);
2512
2701
  }
2513
2702
 
2514
2703
  .ds-avatar--lg {
2515
- width: 3rem;
2516
- height: 3rem;
2704
+ width: var(--ds-size-4);
2705
+ height: var(--ds-size-4);
2517
2706
  font-size: var(--ds-text-base);
2518
2707
  }
2519
2708
 
2520
2709
  .ds-avatar--xl {
2521
- width: 4rem;
2522
- height: 4rem;
2710
+ width: var(--ds-space-16);
2711
+ height: var(--ds-space-16);
2523
2712
  font-size: var(--ds-text-lg);
2524
2713
  }
2525
2714
 
@@ -2541,19 +2730,19 @@ hr {
2541
2730
  }
2542
2731
 
2543
2732
  .ds-avatar-group > .ds-avatar + .ds-avatar {
2544
- margin-left: -0.5rem;
2733
+ margin-inline-start: -0.5rem;
2545
2734
  }
2546
2735
 
2547
2736
  .ds-avatar-group--sm > .ds-avatar + .ds-avatar {
2548
- margin-left: -0.375rem;
2737
+ margin-inline-start: -0.375rem;
2549
2738
  }
2550
2739
 
2551
2740
  /* --- Status indicator --- */
2552
2741
 
2553
2742
  .ds-avatar__status {
2554
2743
  position: absolute;
2555
- bottom: 0;
2556
- right: 0;
2744
+ inset-block-end: 0;
2745
+ inset-inline-end: 0;
2557
2746
  width: 0.625rem;
2558
2747
  height: 0.625rem;
2559
2748
  border-radius: var(--ds-radius-full);
@@ -2590,28 +2779,28 @@ hr {
2590
2779
  height: 1rem;
2591
2780
  width: 100%;
2592
2781
  border-radius: var(--ds-radius-sm);
2593
- margin-bottom: var(--ds-space-2);
2782
+ margin-block-end: var(--ds-space-2);
2594
2783
  }
2595
2784
 
2596
2785
  .ds-skeleton--text-sm {
2597
2786
  height: 0.75rem;
2598
2787
  width: 100%;
2599
2788
  border-radius: var(--ds-radius-sm);
2600
- margin-bottom: var(--ds-space-2);
2789
+ margin-block-end: var(--ds-space-2);
2601
2790
  }
2602
2791
 
2603
2792
  .ds-skeleton--text-lg {
2604
2793
  height: 1.5rem;
2605
2794
  width: 100%;
2606
2795
  border-radius: var(--ds-radius-sm);
2607
- margin-bottom: var(--ds-space-2);
2796
+ margin-block-end: var(--ds-space-2);
2608
2797
  }
2609
2798
 
2610
2799
  .ds-skeleton--heading {
2611
2800
  height: 2rem;
2612
2801
  width: 60%;
2613
2802
  border-radius: var(--ds-radius-md);
2614
- margin-bottom: var(--ds-space-3);
2803
+ margin-block-end: var(--ds-space-3);
2615
2804
  }
2616
2805
 
2617
2806
  /* --- Shape variants --- */
@@ -2692,7 +2881,7 @@ hr {
2692
2881
  width: 3rem;
2693
2882
  height: 3rem;
2694
2883
  color: var(--ds-color-text-tertiary);
2695
- margin-bottom: var(--ds-space-2);
2884
+ margin-block-end: var(--ds-space-2);
2696
2885
  }
2697
2886
 
2698
2887
  .ds-empty-state__title {
@@ -2717,7 +2906,7 @@ hr {
2717
2906
  align-items: center;
2718
2907
  justify-content: center;
2719
2908
  gap: var(--ds-space-3);
2720
- margin-top: var(--ds-space-2);
2909
+ margin-block-start: var(--ds-space-2);
2721
2910
  }
2722
2911
 
2723
2912
  /* --- Compact variant --- */
@@ -2746,7 +2935,7 @@ hr {
2746
2935
  /* --- Left-aligned variant --- */
2747
2936
  .ds-empty-state--left {
2748
2937
  align-items: flex-start;
2749
- text-align: left;
2938
+ text-align: start;
2750
2939
  }
2751
2940
 
2752
2941
 
@@ -2819,8 +3008,8 @@ hr {
2819
3008
  .ds-datepicker__panel {
2820
3009
  position: absolute;
2821
3010
  z-index: var(--ds-z-dropdown);
2822
- top: calc(100% + var(--ds-offset-sm));
2823
- left: 0;
3011
+ inset-block-start: calc(100% + var(--ds-offset-sm));
3012
+ inset-inline-start: 0;
2824
3013
  background-color: var(--ds-color-surface);
2825
3014
  border: 1px solid var(--ds-color-border);
2826
3015
  border-radius: var(--ds-radius-xl);
@@ -2848,7 +3037,7 @@ hr {
2848
3037
  display: flex;
2849
3038
  align-items: center;
2850
3039
  justify-content: space-between;
2851
- margin-bottom: var(--ds-space-2);
3040
+ margin-block-end: var(--ds-space-2);
2852
3041
  }
2853
3042
 
2854
3043
  .ds-datepicker__title {
@@ -2886,7 +3075,7 @@ hr {
2886
3075
  .ds-datepicker__weekdays {
2887
3076
  display: grid;
2888
3077
  grid-template-columns: repeat(7, 1fr);
2889
- margin-bottom: var(--ds-space-1);
3078
+ margin-block-end: var(--ds-space-1);
2890
3079
  }
2891
3080
 
2892
3081
  .ds-datepicker__weekday {
@@ -2959,9 +3148,9 @@ hr {
2959
3148
  .ds-datepicker__footer {
2960
3149
  display: flex;
2961
3150
  justify-content: center;
2962
- margin-top: var(--ds-space-2);
2963
- padding-top: var(--ds-space-2);
2964
- border-top: 1px solid var(--ds-color-border);
3151
+ margin-block-start: var(--ds-space-2);
3152
+ padding-block-start: var(--ds-space-2);
3153
+ border-block-start: 1px solid var(--ds-color-border);
2965
3154
  }
2966
3155
 
2967
3156
  .ds-datepicker__today {
@@ -3043,8 +3232,8 @@ hr {
3043
3232
  }
3044
3233
 
3045
3234
  .ds-datepicker--compact .ds-datepicker__footer {
3046
- margin-top: var(--ds-space-1);
3047
- padding-top: var(--ds-space-1);
3235
+ margin-block-start: var(--ds-space-1);
3236
+ padding-block-start: var(--ds-space-1);
3048
3237
  }
3049
3238
 
3050
3239
  /* ==========================================================================
@@ -3053,6 +3242,12 @@ hr {
3053
3242
  A toggle (switch) control for binary on/off states.
3054
3243
  Supports aria-checked attribute and modifier-class driven states.
3055
3244
 
3245
+ ARIA requirements (consumer responsibility):
3246
+ - Element: <button role="switch" aria-checked="false|true">
3247
+ - Label: pair with visible label via aria-labelledby or wrap in <label>
3248
+ - Keyboard: Space toggles state (native <button> handles this)
3249
+ - State: update aria-checked on toggle
3250
+
3056
3251
  Usage:
3057
3252
  <button class="ds-toggle" role="switch" aria-checked="false"></button>
3058
3253
 
@@ -3089,8 +3284,8 @@ hr {
3089
3284
  .ds-toggle::after {
3090
3285
  content: "";
3091
3286
  position: absolute;
3092
- left: 2px;
3093
- top: 50%;
3287
+ inset-inline-start: 2px;
3288
+ inset-block-start: 50%;
3094
3289
  width: 1.25rem;
3095
3290
  height: 1.25rem;
3096
3291
  border-radius: var(--ds-radius-full);
@@ -3134,6 +3329,7 @@ hr {
3134
3329
  .ds-toggle:focus-visible {
3135
3330
  outline: none;
3136
3331
  box-shadow: 0 0 0 var(--ds-ring-width) var(--ds-ring-color);
3332
+ scroll-margin-block: var(--ds-space-16, 4rem);
3137
3333
  }
3138
3334
 
3139
3335
  /* ---------------------------------------------------------------------------
@@ -3154,6 +3350,7 @@ hr {
3154
3350
  .ds-toggle--sm {
3155
3351
  width: 2rem;
3156
3352
  height: 1.125rem;
3353
+ min-height: 1.5rem; /* WCAG 2.5.8: minimum 24px target */
3157
3354
  }
3158
3355
 
3159
3356
  .ds-toggle--sm::after {
@@ -3188,6 +3385,12 @@ hr {
3188
3385
  ==========================================================================
3189
3386
  A horizontal breadcrumb trail for hierarchical navigation.
3190
3387
 
3388
+ ARIA requirements (consumer responsibility):
3389
+ - Container: <nav aria-label="Breadcrumb">
3390
+ - Current page: aria-current="page" on the last item
3391
+ - Links: use <a> elements for navigation
3392
+ - Separator: decorative (generated via CSS ::after, not in DOM)
3393
+
3191
3394
  Usage:
3192
3395
  <nav class="ds-breadcrumb" aria-label="Breadcrumb">
3193
3396
  <span class="ds-breadcrumb__item">
@@ -3255,6 +3458,7 @@ hr {
3255
3458
  outline: none;
3256
3459
  box-shadow: 0 0 0 var(--ds-ring-width) var(--ds-ring-color);
3257
3460
  border-radius: var(--ds-radius-sm);
3461
+ scroll-margin-block: var(--ds-space-16, 4rem);
3258
3462
  }
3259
3463
 
3260
3464
  /* ---------------------------------------------------------------------------
@@ -3284,6 +3488,13 @@ hr {
3284
3488
  ==========================================================================
3285
3489
  A row of page-number controls for navigating multi-page content.
3286
3490
 
3491
+ ARIA requirements (consumer responsibility):
3492
+ - Container: <nav aria-label="Pagination">
3493
+ - Active page: aria-current="page"
3494
+ - Prev/Next: aria-label="Previous page" / "Next page"
3495
+ - Disabled: aria-disabled="true" on disabled prev/next buttons
3496
+ - Page items: aria-label="Page [N]" (optional, number is visible)
3497
+
3287
3498
  Usage:
3288
3499
  <nav class="ds-pagination" aria-label="Pagination">
3289
3500
  <button class="ds-pagination__prev" aria-label="Previous page">&lsaquo;</button>
@@ -3340,6 +3551,7 @@ hr {
3340
3551
  .ds-pagination__item:focus-visible {
3341
3552
  outline: none;
3342
3553
  box-shadow: 0 0 0 var(--ds-ring-width) var(--ds-ring-color);
3554
+ scroll-margin-block: var(--ds-space-16, 4rem);
3343
3555
  }
3344
3556
 
3345
3557
  /* ---------------------------------------------------------------------------
@@ -3399,6 +3611,7 @@ hr {
3399
3611
  .ds-pagination__next:focus-visible {
3400
3612
  outline: none;
3401
3613
  box-shadow: 0 0 0 var(--ds-ring-width) var(--ds-ring-color);
3614
+ scroll-margin-block: var(--ds-space-16, 4rem);
3402
3615
  }
3403
3616
 
3404
3617
  .ds-pagination__prev:disabled,
@@ -3451,6 +3664,11 @@ hr {
3451
3664
  ==========================================================================
3452
3665
  Interactive, optionally removable tag for categorisation and filtering.
3453
3666
 
3667
+ ARIA requirements (consumer responsibility):
3668
+ - Remove button: add aria-label="Remove [tag name]"
3669
+ - Selectable tags (as <button>): use aria-pressed="true|false"
3670
+ - Tag list: wrap in role="list" with aria-label
3671
+
3454
3672
  Usage:
3455
3673
  <span class="ds-tag">Default</span>
3456
3674
  <span class="ds-tag ds-tag--success">Approved</span>
@@ -3491,6 +3709,7 @@ hr {
3491
3709
  button.ds-tag:focus-visible {
3492
3710
  outline: none;
3493
3711
  box-shadow: 0 0 0 var(--ds-ring-width) var(--ds-ring-color);
3712
+ scroll-margin-block: var(--ds-space-16, 4rem);
3494
3713
  }
3495
3714
 
3496
3715
  /* ---------------------------------------------------------------------------
@@ -3538,7 +3757,7 @@ button.ds-tag:focus-visible {
3538
3757
  --------------------------------------------------------------------------- */
3539
3758
 
3540
3759
  .ds-tag--removable {
3541
- padding-right: var(--ds-space-1);
3760
+ padding-inline-end: var(--ds-space-1);
3542
3761
  }
3543
3762
 
3544
3763
  /* ---------------------------------------------------------------------------
@@ -3551,6 +3770,8 @@ button.ds-tag:focus-visible {
3551
3770
  justify-content: center;
3552
3771
  width: 1rem;
3553
3772
  height: 1rem;
3773
+ min-width: 1.5rem; /* WCAG 2.5.8: minimum 24px target */
3774
+ min-height: 1.5rem;
3554
3775
  padding: 0;
3555
3776
  border: none;
3556
3777
  border-radius: var(--ds-radius-full);
@@ -3596,7 +3817,7 @@ button.ds-tag:focus-visible {
3596
3817
  }
3597
3818
 
3598
3819
  .ds-tag--sm.ds-tag--removable {
3599
- padding-right: var(--ds-space-0-5, 0.125rem);
3820
+ padding-inline-end: var(--ds-space-0-5, 0.125rem);
3600
3821
  }
3601
3822
 
3602
3823
  /* ---------------------------------------------------------------------------
@@ -3609,7 +3830,7 @@ button.ds-tag:focus-visible {
3609
3830
  }
3610
3831
 
3611
3832
  .ds-tag--lg.ds-tag--removable {
3612
- padding-right: var(--ds-space-1-5, 0.375rem);
3833
+ padding-inline-end: var(--ds-space-1-5, 0.375rem);
3613
3834
  }
3614
3835
 
3615
3836
  /* ==========================================================================
@@ -3618,6 +3839,12 @@ button.ds-tag:focus-visible {
3618
3839
  A vertically stacked set of collapsible sections. Supports CSS-only
3619
3840
  open/close via the `.ds-accordion__item--open` modifier.
3620
3841
 
3842
+ ARIA requirements (consumer responsibility):
3843
+ - Trigger: <button> with aria-expanded="true|false"
3844
+ - Trigger: aria-controls="[content-panel-id]"
3845
+ - Content panel: id matching aria-controls, role="region", aria-labelledby="[trigger-id]"
3846
+ - Keyboard: Enter/Space toggles section (native <button> handles this)
3847
+
3621
3848
  Variants:
3622
3849
  --flush – borderless, full-bleed style
3623
3850
  --separated – visually detached items with individual borders
@@ -3625,8 +3852,8 @@ button.ds-tag:focus-visible {
3625
3852
  Usage:
3626
3853
  <div class="ds-accordion">
3627
3854
  <div class="ds-accordion__item ds-accordion__item--open">
3628
- <button class="ds-accordion__trigger">Section</button>
3629
- <div class="ds-accordion__content">
3855
+ <button class="ds-accordion__trigger" aria-expanded="true" aria-controls="panel-1">Section</button>
3856
+ <div class="ds-accordion__content" id="panel-1" role="region">
3630
3857
  <div class="ds-accordion__body">…</div>
3631
3858
  </div>
3632
3859
  </div>
@@ -3648,11 +3875,11 @@ button.ds-tag:focus-visible {
3648
3875
  --------------------------------------------------------------------------- */
3649
3876
 
3650
3877
  .ds-accordion__item {
3651
- border-top: 1px solid var(--ds-color-border);
3878
+ border-block-start: 1px solid var(--ds-color-border);
3652
3879
  }
3653
3880
 
3654
3881
  .ds-accordion__item:first-child {
3655
- border-top: 0;
3882
+ border-block-start: 0;
3656
3883
  }
3657
3884
 
3658
3885
  /* ---------------------------------------------------------------------------
@@ -3666,7 +3893,7 @@ button.ds-tag:focus-visible {
3666
3893
  align-items: center;
3667
3894
  width: 100%;
3668
3895
  padding: var(--ds-space-4);
3669
- text-align: left;
3896
+ text-align: start;
3670
3897
  font-family: var(--ds-font-sans);
3671
3898
  font-size: var(--ds-text-sm);
3672
3899
  font-weight: var(--ds-weight-medium);
@@ -3683,11 +3910,11 @@ button.ds-tag:focus-visible {
3683
3910
  display: inline-block;
3684
3911
  width: 0.5rem;
3685
3912
  height: 0.5rem;
3686
- border-right: 2px solid var(--ds-color-text-secondary);
3687
- border-bottom: 2px solid var(--ds-color-text-secondary);
3913
+ border-inline-end: 2px solid var(--ds-color-text-secondary);
3914
+ border-block-end: 2px solid var(--ds-color-text-secondary);
3688
3915
  transform: rotate(45deg);
3689
3916
  flex-shrink: 0;
3690
- margin-left: var(--ds-space-3);
3917
+ margin-inline-start: var(--ds-space-3);
3691
3918
  transition: transform var(--ds-duration-fast) var(--ds-ease-default);
3692
3919
  }
3693
3920
 
@@ -3697,6 +3924,7 @@ button.ds-tag:focus-visible {
3697
3924
  .ds-accordion__trigger:focus-visible {
3698
3925
  outline: none;
3699
3926
  box-shadow: 0 0 0 var(--ds-ring-width) var(--ds-ring-color);
3927
+ scroll-margin-block: var(--ds-space-16, 4rem);
3700
3928
  }
3701
3929
 
3702
3930
  /* Open state – rotate chevron */
@@ -3726,7 +3954,7 @@ button.ds-tag:focus-visible {
3726
3954
 
3727
3955
  .ds-accordion__body {
3728
3956
  padding: var(--ds-space-4);
3729
- padding-top: 0;
3957
+ padding-block-start: 0;
3730
3958
  font-size: var(--ds-text-sm);
3731
3959
  color: var(--ds-color-text-secondary);
3732
3960
  line-height: var(--ds-leading-relaxed);
@@ -3742,12 +3970,12 @@ button.ds-tag:focus-visible {
3742
3970
  }
3743
3971
 
3744
3972
  .ds-accordion--flush .ds-accordion__item {
3745
- border-top: 0;
3746
- border-bottom: 1px solid var(--ds-color-border);
3973
+ border-block-start: 0;
3974
+ border-block-end: 1px solid var(--ds-color-border);
3747
3975
  }
3748
3976
 
3749
3977
  .ds-accordion--flush .ds-accordion__item:last-child {
3750
- border-bottom: 0;
3978
+ border-block-end: 0;
3751
3979
  }
3752
3980
 
3753
3981
  /* ==========================================================================
@@ -3763,12 +3991,12 @@ button.ds-tag:focus-visible {
3763
3991
  .ds-accordion--separated .ds-accordion__item {
3764
3992
  border: 1px solid var(--ds-color-border);
3765
3993
  border-radius: var(--ds-radius-xl);
3766
- margin-bottom: var(--ds-space-3);
3994
+ margin-block-end: var(--ds-space-3);
3767
3995
  overflow: hidden;
3768
3996
  }
3769
3997
 
3770
3998
  .ds-accordion--separated .ds-accordion__item:last-child {
3771
- margin-bottom: 0;
3999
+ margin-block-end: 0;
3772
4000
  }
3773
4001
 
3774
4002
  /* ==========================================================================
@@ -3778,13 +4006,21 @@ button.ds-tag:focus-visible {
3778
4006
  Default direction is right; use `--left` or `--bottom` modifiers
3779
4007
  to change the slide origin.
3780
4008
 
4009
+ ARIA requirements (consumer responsibility):
4010
+ - Container: role="dialog", aria-modal="true", aria-labelledby="[title-id]"
4011
+ - Close button: aria-label="Close"
4012
+ - Focus: trap focus inside drawer when open
4013
+ - Keyboard: Escape closes drawer
4014
+ - On open: move focus to first focusable element or close button
4015
+ - On close: return focus to the element that triggered the drawer
4016
+
3781
4017
  Sizes:
3782
4018
  --sm 18 rem
3783
4019
  (default) 24 rem
3784
4020
  --lg 36 rem
3785
4021
 
3786
4022
  Usage:
3787
- <div class="ds-drawer ds-drawer--right ds-drawer--open">
4023
+ <div class="ds-drawer ds-drawer--right ds-drawer--open" role="dialog" aria-modal="true">
3788
4024
  <div class="ds-drawer__content">
3789
4025
  <div class="ds-drawer__header">
3790
4026
  <h3>Title</h3>
@@ -3837,12 +4073,12 @@ button.ds-tag:focus-visible {
3837
4073
 
3838
4074
  .ds-drawer__content,
3839
4075
  .ds-drawer--right .ds-drawer__content {
3840
- top: 0;
3841
- right: 0;
3842
- bottom: 0;
4076
+ inset-block-start: 0;
4077
+ inset-inline-end: 0;
4078
+ inset-block-end: 0;
3843
4079
  width: 24rem;
3844
4080
  max-width: 90vw;
3845
- border-left: 1px solid var(--ds-color-border);
4081
+ border-inline-start: 1px solid var(--ds-color-border);
3846
4082
  transform: translateX(100%);
3847
4083
  }
3848
4084
 
@@ -3856,14 +4092,14 @@ button.ds-tag:focus-visible {
3856
4092
  * ========================================================================== */
3857
4093
 
3858
4094
  .ds-drawer--left .ds-drawer__content {
3859
- left: 0;
3860
- top: 0;
3861
- bottom: 0;
3862
- right: auto;
4095
+ inset-inline-start: 0;
4096
+ inset-block-start: 0;
4097
+ inset-block-end: 0;
4098
+ inset-inline-end: auto;
3863
4099
  width: 24rem;
3864
4100
  max-width: 90vw;
3865
- border-left: 0;
3866
- border-right: 1px solid var(--ds-color-border);
4101
+ border-inline-start: 0;
4102
+ border-inline-end: 1px solid var(--ds-color-border);
3867
4103
  transform: translateX(-100%);
3868
4104
  }
3869
4105
 
@@ -3876,14 +4112,14 @@ button.ds-tag:focus-visible {
3876
4112
  * ========================================================================== */
3877
4113
 
3878
4114
  .ds-drawer--bottom .ds-drawer__content {
3879
- bottom: 0;
3880
- left: 0;
3881
- right: 0;
3882
- top: auto;
4115
+ inset-block-end: 0;
4116
+ inset-inline-start: 0;
4117
+ inset-inline-end: 0;
4118
+ inset-block-start: auto;
3883
4119
  width: auto;
3884
4120
  max-height: 90dvh;
3885
- border-left: 0;
3886
- border-top: 1px solid var(--ds-color-border);
4121
+ border-inline-start: 0;
4122
+ border-block-start: 1px solid var(--ds-color-border);
3887
4123
  border-radius: var(--ds-radius-xl) var(--ds-radius-xl) 0 0;
3888
4124
  transform: translateY(100%);
3889
4125
  }
@@ -3919,7 +4155,7 @@ button.ds-tag:focus-visible {
3919
4155
  justify-content: space-between;
3920
4156
  align-items: flex-start;
3921
4157
  padding: var(--ds-space-4) var(--ds-space-5);
3922
- border-bottom: 1px solid var(--ds-color-border);
4158
+ border-block-end: 1px solid var(--ds-color-border);
3923
4159
  }
3924
4160
 
3925
4161
  .ds-drawer__header h3 {
@@ -3961,6 +4197,7 @@ button.ds-tag:focus-visible {
3961
4197
  .ds-drawer__close:focus-visible {
3962
4198
  outline: none;
3963
4199
  box-shadow: 0 0 0 var(--ds-ring-width) var(--ds-ring-color);
4200
+ scroll-margin-block: var(--ds-space-16, 4rem);
3964
4201
  }
3965
4202
 
3966
4203
  /* ==========================================================================
@@ -3979,7 +4216,7 @@ button.ds-tag:focus-visible {
3979
4216
 
3980
4217
  .ds-drawer__footer {
3981
4218
  padding: var(--ds-space-4) var(--ds-space-5);
3982
- border-top: 1px solid var(--ds-color-border);
4219
+ border-block-start: 1px solid var(--ds-color-border);
3983
4220
  display: flex;
3984
4221
  align-items: center;
3985
4222
  justify-content: flex-end;
@@ -4031,7 +4268,7 @@ button.ds-tag:focus-visible {
4031
4268
  justify-content: space-between;
4032
4269
  font-size: var(--ds-text-xs);
4033
4270
  color: var(--ds-color-text-tertiary);
4034
- margin-bottom: var(--ds-space-1-5);
4271
+ margin-block-end: var(--ds-space-1-5);
4035
4272
  }
4036
4273
 
4037
4274
  /* Track */
@@ -4196,7 +4433,7 @@ button.ds-tag:focus-visible {
4196
4433
  height: 2rem;
4197
4434
  min-width: auto;
4198
4435
  margin-inline: 0;
4199
- margin-left: calc(1rem - 1px); /* center under the 2 rem indicator */
4436
+ margin-inline-start: calc(1rem - 1px); /* center under the 2 rem indicator */
4200
4437
  margin-block: var(--ds-space-1);
4201
4438
  background-color: var(--ds-color-border-subtle);
4202
4439
  }
@@ -4208,6 +4445,12 @@ button.ds-tag:focus-visible {
4208
4445
  /* ==========================================================================
4209
4446
  Component: Drop Zone
4210
4447
  Dashed-border upload area with icon, label, hint, and progress states.
4448
+
4449
+ ARIA requirements (consumer responsibility):
4450
+ - Container: role="button" if clickable, tabindex="0" for keyboard access
4451
+ - Label: aria-label="Upload files" or visible label via aria-labelledby
4452
+ - Drag state: announce via aria-live="polite" region
4453
+ - Progress: use aria-busy="true" during upload, aria-valuenow for progress
4211
4454
  ==========================================================================
4212
4455
 
4213
4456
  Usage:
@@ -4249,6 +4492,7 @@ button.ds-tag:focus-visible {
4249
4492
  .ds-drop-zone:focus-visible {
4250
4493
  outline: none;
4251
4494
  box-shadow: 0 0 0 var(--ds-ring-width) var(--ds-ring-color);
4495
+ scroll-margin-block: var(--ds-space-16, 4rem);
4252
4496
  }
4253
4497
 
4254
4498
  :root:not(.dark) .ds-drop-zone {
@@ -4285,7 +4529,7 @@ button.ds-tag:focus-visible {
4285
4529
  }
4286
4530
 
4287
4531
  .ds-drop-zone:hover .ds-drop-zone__icon {
4288
- color: var(--ds-color-text-primary);
4532
+ color: var(--ds-color-text);
4289
4533
  }
4290
4534
 
4291
4535
  /* ---------------------------------------------------------------------------
@@ -4295,13 +4539,13 @@ button.ds-tag:focus-visible {
4295
4539
  .ds-drop-zone__label {
4296
4540
  font-size: var(--ds-text-sm);
4297
4541
  font-weight: var(--ds-weight-medium);
4298
- color: var(--ds-color-text-primary);
4542
+ color: var(--ds-color-text);
4299
4543
  }
4300
4544
 
4301
4545
  .ds-drop-zone__hint {
4302
4546
  font-size: var(--ds-text-xs);
4303
4547
  color: var(--ds-color-text-tertiary);
4304
- margin-top: calc(-1 * var(--ds-space-1));
4548
+ margin-block-start: calc(-1 * var(--ds-space-1));
4305
4549
  }
4306
4550
 
4307
4551
  /* ---------------------------------------------------------------------------
@@ -4347,6 +4591,14 @@ button.ds-tag:focus-visible {
4347
4591
  Replaces native <select> with styled dropdown panel.
4348
4592
  Desktop: absolute positioned panel below trigger.
4349
4593
  Mobile: fullscreen overlay with header + search.
4594
+
4595
+ ARIA requirements (consumer responsibility):
4596
+ - Trigger: role="combobox", aria-expanded="true|false", aria-haspopup="listbox"
4597
+ - Trigger: aria-controls="[panel-list-id]", aria-labelledby="[label-id]"
4598
+ - Panel list: role="listbox", id matching aria-controls
4599
+ - Option: role="option", aria-selected="true|false"
4600
+ - Multi-select: add aria-multiselectable="true" on listbox
4601
+ - Keyboard: ArrowUp/Down to navigate, Enter/Space to select, Escape to close
4350
4602
  ========================================================================== */
4351
4603
 
4352
4604
  /* --- Wrapper --- */
@@ -4373,7 +4625,7 @@ button.ds-tag:focus-visible {
4373
4625
  border: 1px solid var(--ds-color-border);
4374
4626
  border-radius: var(--ds-radius-lg);
4375
4627
  cursor: pointer;
4376
- text-align: left;
4628
+ text-align: start;
4377
4629
  transition: all var(--ds-duration-fast) var(--ds-ease-default);
4378
4630
  }
4379
4631
 
@@ -4385,6 +4637,7 @@ button.ds-tag:focus-visible {
4385
4637
  border-color: var(--ds-color-border-active);
4386
4638
  outline: none;
4387
4639
  box-shadow: 0 0 0 var(--ds-ring-width) var(--ds-ring-color);
4640
+ scroll-margin-block: var(--ds-space-16, 4rem);
4388
4641
  }
4389
4642
 
4390
4643
  .ds-custom-select__trigger--open {
@@ -4414,7 +4667,7 @@ button.ds-tag:focus-visible {
4414
4667
  flex-shrink: 0;
4415
4668
  width: 1rem;
4416
4669
  height: 1rem;
4417
- margin-left: var(--ds-space-2);
4670
+ margin-inline-start: var(--ds-space-2);
4418
4671
  color: var(--ds-color-text-tertiary);
4419
4672
  transition: transform var(--ds-duration-fast) var(--ds-ease-default);
4420
4673
  }
@@ -4489,13 +4742,13 @@ button.ds-tag:focus-visible {
4489
4742
  .ds-custom-select__search {
4490
4743
  position: relative;
4491
4744
  padding: var(--ds-space-2) var(--ds-space-3);
4492
- border-bottom: 1px solid var(--ds-color-border);
4745
+ border-block-end: 1px solid var(--ds-color-border);
4493
4746
  }
4494
4747
 
4495
4748
  .ds-custom-select__search-icon {
4496
4749
  position: absolute;
4497
- left: calc(var(--ds-space-3) + var(--ds-space-2-5));
4498
- top: 50%;
4750
+ inset-inline-start: calc(var(--ds-space-3) + var(--ds-space-2-5));
4751
+ inset-block-start: 50%;
4499
4752
  transform: translateY(-50%);
4500
4753
  width: 1rem;
4501
4754
  height: 1rem;
@@ -4599,7 +4852,7 @@ button.ds-tag:focus-visible {
4599
4852
  .ds-custom-select__panel {
4600
4853
  position: fixed;
4601
4854
  inset: 0;
4602
- top: auto;
4855
+ inset-block-start: auto;
4603
4856
  z-index: var(--ds-z-modal);
4604
4857
  max-height: 85dvh;
4605
4858
  border-radius: var(--ds-radius-xl) var(--ds-radius-xl) 0 0;
@@ -4623,7 +4876,7 @@ button.ds-tag:focus-visible {
4623
4876
  align-items: center;
4624
4877
  justify-content: space-between;
4625
4878
  padding: var(--ds-space-4) var(--ds-space-4);
4626
- border-bottom: 1px solid var(--ds-color-border);
4879
+ border-block-end: 1px solid var(--ds-color-border);
4627
4880
  }
4628
4881
 
4629
4882
  .ds-custom-select__header-title {
@@ -4663,105 +4916,522 @@ button.ds-tag:focus-visible {
4663
4916
  }
4664
4917
  }
4665
4918
 
4666
- @media (prefers-reduced-motion: reduce) {
4667
- .ds-custom-select__panel {
4668
- animation: none;
4669
- opacity: 1;
4670
- transform: scale(1);
4671
- }
4672
- .ds-custom-select__backdrop { animation: none; opacity: 1; }
4673
- }
4674
-
4675
4919
  /* ==========================================================================
4676
- Component: Sortable
4677
- Optional drag-to-reorder styles for table rows or list items.
4678
- Provides grip handle, dragging states, and drop zone indicators.
4679
- Works with native HTML5 Drag API or any JS drag library.
4920
+ Multi-select mode
4680
4921
  ========================================================================== */
4681
4922
 
4682
- /* --- Grip handle: visible on row hover, grab cursor --- */
4683
- .ds-sortable__handle {
4923
+ /* --- Multi trigger: tags inside trigger --- */
4924
+
4925
+ .ds-custom-select--multi .ds-custom-select__trigger {
4926
+ height: auto;
4927
+ min-height: var(--ds-size-3);
4928
+ flex-wrap: wrap;
4929
+ padding: var(--ds-space-1) var(--ds-space-4) var(--ds-space-1) var(--ds-space-2);
4930
+ gap: var(--ds-space-1);
4931
+ }
4932
+
4933
+ /* --- Tags container --- */
4934
+
4935
+ .ds-custom-select__tags {
4684
4936
  display: flex;
4937
+ flex-wrap: wrap;
4938
+ gap: var(--ds-space-1);
4939
+ flex: 1;
4940
+ min-width: 0;
4941
+ }
4942
+
4943
+ /* --- Single tag (based on ds-tag styling) --- */
4944
+
4945
+ .ds-custom-select__tag {
4946
+ display: inline-flex;
4685
4947
  align-items: center;
4686
- justify-content: center;
4687
- padding: var(--ds-space-1);
4688
- color: var(--ds-color-text-tertiary);
4689
- cursor: grab;
4690
- border-radius: var(--ds-radius-sm);
4691
- opacity: 0;
4692
- transition:
4693
- opacity var(--ds-duration-fast) var(--ds-ease-default),
4694
- color var(--ds-duration-fast) var(--ds-ease-default);
4948
+ gap: var(--ds-space-1);
4949
+ padding: var(--ds-space-0-5) var(--ds-space-1) var(--ds-space-0-5) var(--ds-space-2);
4950
+ font-size: var(--ds-text-xs);
4951
+ font-weight: var(--ds-weight-medium);
4952
+ font-family: var(--ds-font-sans);
4953
+ line-height: var(--ds-leading-none);
4954
+ border-radius: var(--ds-radius-full);
4955
+ background-color: var(--ds-color-bg-elevated);
4956
+ border: 1px solid var(--ds-color-border);
4957
+ color: var(--ds-color-text-secondary);
4958
+ white-space: nowrap;
4695
4959
  }
4696
4960
 
4697
- .ds-sortable__handle:active {
4698
- cursor: grabbing;
4961
+ .ds-custom-select__tag-remove {
4962
+ display: inline-flex;
4963
+ align-items: center;
4964
+ justify-content: center;
4965
+ width: 1rem;
4966
+ height: 1rem;
4967
+ min-width: 1.5rem; /* WCAG 2.5.8: minimum 24px target */
4968
+ min-height: 1.5rem;
4969
+ padding: 0;
4970
+ border: none;
4971
+ border-radius: var(--ds-radius-full);
4972
+ background: transparent;
4973
+ color: currentColor;
4974
+ font-size: inherit;
4975
+ line-height: var(--ds-leading-none);
4976
+ opacity: 0.6;
4977
+ cursor: pointer;
4978
+ transition: opacity var(--ds-duration-fast) var(--ds-ease-out);
4979
+ -webkit-appearance: none;
4980
+ appearance: none;
4699
4981
  }
4700
4982
 
4701
- /* Show handle on row hover */
4702
- tr:hover .ds-sortable__handle,
4703
- .ds-sortable-row:hover .ds-sortable__handle,
4704
- .ds-sortable__handle:focus-visible {
4983
+ .ds-custom-select__tag-remove:hover {
4705
4984
  opacity: 1;
4706
4985
  }
4707
4986
 
4708
- .ds-sortable__handle:focus-visible {
4709
- outline: none;
4710
- box-shadow: 0 0 0 var(--ds-ring-width) var(--ds-ring-color);
4987
+ /* --- Multi option: checkbox style indicator --- */
4988
+
4989
+ .ds-custom-select--multi .ds-custom-select__option-check {
4990
+ width: 1rem;
4991
+ height: 1rem;
4992
+ border: 1px solid var(--ds-color-border);
4711
4993
  border-radius: var(--ds-radius-sm);
4994
+ flex-shrink: 0;
4995
+ display: flex;
4996
+ align-items: center;
4997
+ justify-content: center;
4998
+ transition:
4999
+ background-color var(--ds-duration-fast) var(--ds-ease-default),
5000
+ border-color var(--ds-duration-fast) var(--ds-ease-default);
4712
5001
  }
4713
5002
 
4714
- tr:hover .ds-sortable__handle,
4715
- .ds-sortable-row:hover .ds-sortable__handle {
4716
- color: var(--ds-color-text-secondary);
5003
+ .ds-custom-select--multi .ds-custom-select__option--selected .ds-custom-select__option-check {
5004
+ background-color: var(--ds-color-interactive);
5005
+ border-color: var(--ds-color-interactive);
5006
+ color: var(--ds-color-on-inverted);
4717
5007
  }
4718
5008
 
4719
- /* --- Dragging state: applied to the row being dragged --- */
4720
- .ds-sortable--dragging {
4721
- opacity: 0.5;
4722
- background-color: var(--ds-color-surface);
5009
+ /* --- Multi size variants --- */
5010
+
5011
+ .ds-custom-select--xs.ds-custom-select--multi .ds-custom-select__trigger {
5012
+ min-height: var(--ds-size-1);
5013
+ padding: var(--ds-space-0-5) var(--ds-space-1-5) var(--ds-space-0-5) var(--ds-space-1);
4723
5014
  }
4724
5015
 
4725
- /* --- Drop target: applied to the row being hovered over --- */
4726
- .ds-sortable--over {
4727
- box-shadow: inset 0 -2px 0 var(--ds-color-interactive);
5016
+ .ds-custom-select--sm.ds-custom-select--multi .ds-custom-select__trigger {
5017
+ min-height: var(--ds-size-2);
5018
+ padding: var(--ds-space-0-5) var(--ds-space-2) var(--ds-space-0-5) var(--ds-space-1-5);
4728
5019
  }
4729
5020
 
4730
- /* --- Always-visible handle variant --- */
4731
- .ds-sortable__handle--visible {
4732
- opacity: 1;
5021
+ .ds-custom-select--lg.ds-custom-select--multi .ds-custom-select__trigger {
5022
+ min-height: var(--ds-size-4);
5023
+ padding: var(--ds-space-1) var(--ds-space-4) var(--ds-space-1) var(--ds-space-2);
4733
5024
  }
4734
5025
 
5026
+ @media (prefers-reduced-motion: reduce) {
5027
+ .ds-custom-select__panel {
5028
+ animation: none;
5029
+ opacity: 1;
5030
+ transform: scale(1);
5031
+ }
5032
+ .ds-custom-select__backdrop { animation: none; opacity: 1; }
5033
+ }
4735
5034
 
4736
- /* === Tier 3 — Advanced === */
4737
5035
  /* ==========================================================================
4738
- Popover
4739
- ==========================================================================
4740
- Flexible popover component for displaying complex content anchored to a
4741
- trigger element. Supports four placement directions (top, bottom, left,
4742
- right) and multiple size variants. Default placement is bottom.
4743
-
4744
- Usage:
4745
- <div class="ds-popover ds-popover--open">
4746
- <button>Trigger</button>
4747
- <div class="ds-popover__content">...</div>
4748
- </div>
5036
+ Component: Collapsible
5037
+ Single collapsible section — a simplified, standalone accordion item.
4749
5038
 
4750
- Modifiers:
4751
- .ds-popover--open — Shows the popover content
4752
- .ds-popover--top — Places content above the trigger
4753
- .ds-popover--bottom — Places content below the trigger (default)
4754
- .ds-popover--left — Places content to the left of the trigger
4755
- .ds-popover--right — Places content to the right of the trigger
4756
- .ds-popover__content--sm — Smaller popover (12rem min-width)
4757
- .ds-popover__content--lg — Larger popover (24rem min-width)
5039
+ ARIA requirements (consumer responsibility):
5040
+ - Trigger: <button> with aria-expanded="true|false"
5041
+ - Trigger: aria-controls="[content-panel-id]"
5042
+ - Content: id matching aria-controls
4758
5043
  ========================================================================== */
4759
5044
 
4760
- .ds-popover {
4761
- position: relative;
4762
- display: inline-flex;
4763
- }
4764
-
5045
+ /* ---------------------------------------------------------------------------
5046
+ Container
5047
+ --------------------------------------------------------------------------- */
5048
+
5049
+ .ds-collapsible {
5050
+ border: 1px solid var(--ds-color-border);
5051
+ border-radius: var(--ds-radius-xl);
5052
+ overflow: hidden;
5053
+ }
5054
+
5055
+ /* ---------------------------------------------------------------------------
5056
+ Trigger (button)
5057
+ --------------------------------------------------------------------------- */
5058
+
5059
+ .ds-collapsible__trigger {
5060
+ display: flex;
5061
+ flex-direction: row;
5062
+ justify-content: space-between;
5063
+ align-items: center;
5064
+ width: 100%;
5065
+ padding: var(--ds-space-4);
5066
+ text-align: start;
5067
+ font-family: var(--ds-font-sans);
5068
+ font-size: var(--ds-text-sm);
5069
+ font-weight: var(--ds-weight-medium);
5070
+ color: var(--ds-color-text);
5071
+ background: transparent;
5072
+ border: 0;
5073
+ cursor: pointer;
5074
+ transition: background-color var(--ds-duration-fast) var(--ds-ease-default);
5075
+ }
5076
+
5077
+ .ds-collapsible__trigger:hover {
5078
+ background-color: var(--ds-color-overlay);
5079
+ }
5080
+
5081
+ .ds-collapsible__trigger:focus-visible {
5082
+ outline: none;
5083
+ box-shadow: 0 0 0 var(--ds-ring-width) var(--ds-ring-color);
5084
+ scroll-margin-block: var(--ds-space-16, 4rem);
5085
+ }
5086
+
5087
+ /* ---------------------------------------------------------------------------
5088
+ Chevron icon (CSS border-arrow)
5089
+ --------------------------------------------------------------------------- */
5090
+
5091
+ .ds-collapsible__icon {
5092
+ flex-shrink: 0;
5093
+ width: 0.5rem;
5094
+ height: 0.5rem;
5095
+ border-inline-end: 2px solid var(--ds-color-text-secondary);
5096
+ border-block-end: 2px solid var(--ds-color-text-secondary);
5097
+ transform: rotate(45deg);
5098
+ margin-inline-start: var(--ds-space-3);
5099
+ transition: transform var(--ds-duration-fast) var(--ds-ease-default);
5100
+ }
5101
+
5102
+ .ds-collapsible--open .ds-collapsible__icon {
5103
+ transform: rotate(225deg);
5104
+ }
5105
+
5106
+ /* ---------------------------------------------------------------------------
5107
+ Collapsible content
5108
+ --------------------------------------------------------------------------- */
5109
+
5110
+ .ds-collapsible__content {
5111
+ max-height: 0;
5112
+ overflow: hidden;
5113
+ transition:
5114
+ max-height var(--ds-duration-normal) var(--ds-ease-default),
5115
+ padding var(--ds-duration-normal) var(--ds-ease-default);
5116
+ }
5117
+
5118
+ .ds-collapsible--open .ds-collapsible__content {
5119
+ max-height: 80rem;
5120
+ }
5121
+
5122
+ /* ---------------------------------------------------------------------------
5123
+ Inner body
5124
+ --------------------------------------------------------------------------- */
5125
+
5126
+ .ds-collapsible__body {
5127
+ padding: var(--ds-space-4);
5128
+ padding-block-start: 0;
5129
+ font-size: var(--ds-text-sm);
5130
+ color: var(--ds-color-text-secondary);
5131
+ line-height: var(--ds-leading-relaxed);
5132
+ }
5133
+
5134
+ /* ---------------------------------------------------------------------------
5135
+ Variant: Flush (no border, no radius)
5136
+ --------------------------------------------------------------------------- */
5137
+
5138
+ .ds-collapsible--flush {
5139
+ border: 0;
5140
+ border-radius: 0;
5141
+ }
5142
+
5143
+ /* ---------------------------------------------------------------------------
5144
+ Variant: Ghost (no border, transparent bg)
5145
+ --------------------------------------------------------------------------- */
5146
+
5147
+ .ds-collapsible--ghost {
5148
+ border: 0;
5149
+ background: transparent;
5150
+ }
5151
+
5152
+ /* ==========================================================================
5153
+ Component: Description List
5154
+ Key-value pairs display with horizontal and vertical layouts.
5155
+ ========================================================================== */
5156
+
5157
+ /* ---------------------------------------------------------------------------
5158
+ Container
5159
+ --------------------------------------------------------------------------- */
5160
+
5161
+ .ds-description-list {
5162
+ display: flex;
5163
+ flex-direction: column;
5164
+ gap: 0;
5165
+ }
5166
+
5167
+ /* ---------------------------------------------------------------------------
5168
+ Item
5169
+ --------------------------------------------------------------------------- */
5170
+
5171
+ .ds-description-list__item {
5172
+ display: flex;
5173
+ flex-direction: column;
5174
+ gap: var(--ds-space-1);
5175
+ padding: var(--ds-space-3) 0;
5176
+ }
5177
+
5178
+ .ds-description-list__item:first-child {
5179
+ padding-block-start: 0;
5180
+ }
5181
+
5182
+ .ds-description-list__item:last-child {
5183
+ padding-block-end: 0;
5184
+ }
5185
+
5186
+ /* ---------------------------------------------------------------------------
5187
+ Term (key)
5188
+ --------------------------------------------------------------------------- */
5189
+
5190
+ .ds-description-list__term {
5191
+ font-family: var(--ds-font-sans);
5192
+ font-size: var(--ds-text-sm);
5193
+ font-weight: var(--ds-weight-medium);
5194
+ color: var(--ds-color-text-secondary);
5195
+ line-height: var(--ds-leading-normal);
5196
+ }
5197
+
5198
+ /* ---------------------------------------------------------------------------
5199
+ Detail (value)
5200
+ --------------------------------------------------------------------------- */
5201
+
5202
+ .ds-description-list__detail {
5203
+ font-family: var(--ds-font-sans);
5204
+ font-size: var(--ds-text-sm);
5205
+ color: var(--ds-color-text);
5206
+ line-height: var(--ds-leading-normal);
5207
+ }
5208
+
5209
+ /* ---------------------------------------------------------------------------
5210
+ Variant: Horizontal (term and detail on same row)
5211
+ --------------------------------------------------------------------------- */
5212
+
5213
+ .ds-description-list--horizontal .ds-description-list__item {
5214
+ flex-direction: row;
5215
+ align-items: flex-start;
5216
+ gap: var(--ds-space-4);
5217
+ }
5218
+
5219
+ .ds-description-list--horizontal .ds-description-list__term {
5220
+ flex-shrink: 0;
5221
+ min-width: 10rem;
5222
+ }
5223
+
5224
+ .ds-description-list--horizontal .ds-description-list__detail {
5225
+ flex: 1;
5226
+ min-width: 0;
5227
+ }
5228
+
5229
+ /* ---------------------------------------------------------------------------
5230
+ Variant: Bordered (separator between items)
5231
+ --------------------------------------------------------------------------- */
5232
+
5233
+ .ds-description-list--bordered .ds-description-list__item {
5234
+ border-block-end: 1px solid var(--ds-color-border);
5235
+ }
5236
+
5237
+ .ds-description-list--bordered .ds-description-list__item:last-child {
5238
+ border-block-end: 0;
5239
+ }
5240
+
5241
+ /* ---------------------------------------------------------------------------
5242
+ Variant: Striped (alternating background)
5243
+ --------------------------------------------------------------------------- */
5244
+
5245
+ .ds-description-list--striped .ds-description-list__item:nth-child(odd) {
5246
+ background-color: var(--ds-color-bg-subtle);
5247
+ padding-inline: var(--ds-space-3);
5248
+ border-radius: var(--ds-radius-md);
5249
+ }
5250
+
5251
+ /* ==========================================================================
5252
+ Component: Result
5253
+ Feedback page for success, error, 404, empty, etc.
5254
+ ========================================================================== */
5255
+
5256
+ /* ---------------------------------------------------------------------------
5257
+ Container
5258
+ --------------------------------------------------------------------------- */
5259
+
5260
+ .ds-result {
5261
+ display: flex;
5262
+ flex-direction: column;
5263
+ align-items: center;
5264
+ text-align: center;
5265
+ padding: var(--ds-space-12) var(--ds-space-6);
5266
+ max-width: 28rem;
5267
+ margin-inline: auto;
5268
+ }
5269
+
5270
+ /* ---------------------------------------------------------------------------
5271
+ Icon
5272
+ --------------------------------------------------------------------------- */
5273
+
5274
+ .ds-result__icon {
5275
+ width: 3rem;
5276
+ height: 3rem;
5277
+ margin-block-end: var(--ds-space-4);
5278
+ color: var(--ds-color-text-secondary);
5279
+ }
5280
+
5281
+ /* ---------------------------------------------------------------------------
5282
+ Title
5283
+ --------------------------------------------------------------------------- */
5284
+
5285
+ .ds-result__title {
5286
+ font-family: var(--ds-font-display);
5287
+ font-weight: var(--ds-weight-semibold);
5288
+ font-size: var(--ds-text-xl);
5289
+ color: var(--ds-color-text);
5290
+ line-height: var(--ds-leading-tight);
5291
+ }
5292
+
5293
+ /* ---------------------------------------------------------------------------
5294
+ Description
5295
+ --------------------------------------------------------------------------- */
5296
+
5297
+ .ds-result__description {
5298
+ font-size: var(--ds-text-sm);
5299
+ color: var(--ds-color-text-secondary);
5300
+ line-height: var(--ds-leading-relaxed);
5301
+ margin-block-start: var(--ds-space-2);
5302
+ }
5303
+
5304
+ /* ---------------------------------------------------------------------------
5305
+ Actions
5306
+ --------------------------------------------------------------------------- */
5307
+
5308
+ .ds-result__actions {
5309
+ display: flex;
5310
+ align-items: center;
5311
+ justify-content: center;
5312
+ gap: var(--ds-space-3);
5313
+ margin-block-start: var(--ds-space-6);
5314
+ }
5315
+
5316
+ /* ---------------------------------------------------------------------------
5317
+ Semantic variants — icon color
5318
+ --------------------------------------------------------------------------- */
5319
+
5320
+ .ds-result--success .ds-result__icon {
5321
+ color: var(--ds-color-success);
5322
+ }
5323
+
5324
+ .ds-result--warning .ds-result__icon {
5325
+ color: var(--ds-color-warning);
5326
+ }
5327
+
5328
+ .ds-result--error .ds-result__icon {
5329
+ color: var(--ds-color-error);
5330
+ }
5331
+
5332
+ .ds-result--info .ds-result__icon {
5333
+ color: var(--ds-color-info);
5334
+ }
5335
+
5336
+ /* ==========================================================================
5337
+ Component: Sortable
5338
+ Optional drag-to-reorder styles for table rows or list items.
5339
+ Provides grip handle, dragging states, and drop zone indicators.
5340
+ Works with native HTML5 Drag API or any JS drag library.
5341
+
5342
+ ARIA requirements (consumer responsibility):
5343
+ - Handle: aria-label="Reorder [item]", role="button"
5344
+ - Draggable row: aria-grabbed="true|false" (when using HTML5 DnD)
5345
+ - Drop target: aria-dropeffect="move"
5346
+ - Keyboard: handle should support ArrowUp/Down + Enter to move items
5347
+ ========================================================================== */
5348
+
5349
+ /* --- Grip handle: visible on row hover, grab cursor --- */
5350
+ .ds-sortable__handle {
5351
+ display: flex;
5352
+ align-items: center;
5353
+ justify-content: center;
5354
+ min-width: 1.5rem; /* WCAG 2.5.8: minimum 24px target */
5355
+ min-height: 1.5rem;
5356
+ padding: var(--ds-space-1);
5357
+ color: var(--ds-color-text-tertiary);
5358
+ cursor: grab;
5359
+ border-radius: var(--ds-radius-sm);
5360
+ opacity: 0;
5361
+ transition:
5362
+ opacity var(--ds-duration-fast) var(--ds-ease-default),
5363
+ color var(--ds-duration-fast) var(--ds-ease-default);
5364
+ }
5365
+
5366
+ .ds-sortable__handle:active {
5367
+ cursor: grabbing;
5368
+ }
5369
+
5370
+ /* Show handle on row hover */
5371
+ tr:hover .ds-sortable__handle,
5372
+ .ds-sortable-row:hover .ds-sortable__handle,
5373
+ .ds-sortable__handle:focus-visible {
5374
+ opacity: 1;
5375
+ }
5376
+
5377
+ .ds-sortable__handle:focus-visible {
5378
+ outline: none;
5379
+ box-shadow: 0 0 0 var(--ds-ring-width) var(--ds-ring-color);
5380
+ border-radius: var(--ds-radius-sm);
5381
+ scroll-margin-block: var(--ds-space-16, 4rem);
5382
+ }
5383
+
5384
+ tr:hover .ds-sortable__handle,
5385
+ .ds-sortable-row:hover .ds-sortable__handle {
5386
+ color: var(--ds-color-text-secondary);
5387
+ }
5388
+
5389
+ /* --- Dragging state: applied to the row being dragged --- */
5390
+ .ds-sortable--dragging {
5391
+ opacity: 0.5;
5392
+ background-color: var(--ds-color-surface);
5393
+ }
5394
+
5395
+ /* --- Drop target: applied to the row being hovered over --- */
5396
+ .ds-sortable--over {
5397
+ box-shadow: inset 0 -2px 0 var(--ds-color-interactive);
5398
+ }
5399
+
5400
+ /* --- Always-visible handle variant --- */
5401
+ .ds-sortable__handle--visible {
5402
+ opacity: 1;
5403
+ }
5404
+
5405
+
5406
+ /* === Tier 3 — Advanced === */
5407
+ /* ==========================================================================
5408
+ Popover
5409
+ ==========================================================================
5410
+ Flexible popover component for displaying complex content anchored to a
5411
+ trigger element. Supports four placement directions (top, bottom, left,
5412
+ right) and multiple size variants. Default placement is bottom.
5413
+
5414
+ Usage:
5415
+ <div class="ds-popover ds-popover--open">
5416
+ <button>Trigger</button>
5417
+ <div class="ds-popover__content">...</div>
5418
+ </div>
5419
+
5420
+ Modifiers:
5421
+ .ds-popover--open — Shows the popover content
5422
+ .ds-popover--top — Places content above the trigger
5423
+ .ds-popover--bottom — Places content below the trigger (default)
5424
+ .ds-popover--left — Places content to the left of the trigger
5425
+ .ds-popover--right — Places content to the right of the trigger
5426
+ .ds-popover__content--sm — Smaller popover (12rem min-width)
5427
+ .ds-popover__content--lg — Larger popover (24rem min-width)
5428
+ ========================================================================== */
5429
+
5430
+ .ds-popover {
5431
+ position: relative;
5432
+ display: inline-flex;
5433
+ }
5434
+
4765
5435
  .ds-popover__content {
4766
5436
  position: absolute;
4767
5437
  z-index: var(--ds-z-dropdown);
@@ -4790,8 +5460,8 @@ tr:hover .ds-sortable__handle,
4790
5460
  /* Placement: bottom (default) */
4791
5461
  .ds-popover__content,
4792
5462
  .ds-popover--bottom .ds-popover__content {
4793
- top: calc(100% + var(--ds-offset-md));
4794
- left: 50%;
5463
+ inset-block-start: calc(100% + var(--ds-offset-md));
5464
+ inset-inline-start: 50%;
4795
5465
  transform: translateX(-50%) scale(0.96);
4796
5466
  }
4797
5467
 
@@ -4802,9 +5472,9 @@ tr:hover .ds-sortable__handle,
4802
5472
 
4803
5473
  /* Placement: top */
4804
5474
  .ds-popover--top .ds-popover__content {
4805
- bottom: calc(100% + var(--ds-offset-md));
4806
- top: auto;
4807
- left: 50%;
5475
+ inset-block-end: calc(100% + var(--ds-offset-md));
5476
+ inset-block-start: auto;
5477
+ inset-inline-start: 50%;
4808
5478
  transform: translateX(-50%) scale(0.96);
4809
5479
  }
4810
5480
 
@@ -4814,9 +5484,9 @@ tr:hover .ds-sortable__handle,
4814
5484
 
4815
5485
  /* Placement: left */
4816
5486
  .ds-popover--left .ds-popover__content {
4817
- right: calc(100% + var(--ds-offset-md));
4818
- top: 50%;
4819
- left: auto;
5487
+ inset-inline-end: calc(100% + var(--ds-offset-md));
5488
+ inset-block-start: 50%;
5489
+ inset-inline-start: auto;
4820
5490
  transform: translateY(-50%) scale(0.96);
4821
5491
  }
4822
5492
 
@@ -4826,8 +5496,8 @@ tr:hover .ds-sortable__handle,
4826
5496
 
4827
5497
  /* Placement: right */
4828
5498
  .ds-popover--right .ds-popover__content {
4829
- left: calc(100% + var(--ds-offset-md));
4830
- top: 50%;
5499
+ inset-inline-start: calc(100% + var(--ds-offset-md));
5500
+ inset-block-start: 50%;
4831
5501
  transform: translateY(-50%) scale(0.96);
4832
5502
  }
4833
5503
 
@@ -4852,9 +5522,15 @@ tr:hover .ds-sortable__handle,
4852
5522
  Range slider input component with customizable thumb and track styling.
4853
5523
  Supports labels, value display, size variants, and disabled state.
4854
5524
 
5525
+ ARIA requirements (consumer responsibility):
5526
+ - Use native <input type="range"> (inherits slider role)
5527
+ - Add aria-label or aria-labelledby for context
5528
+ - Add aria-valuemin, aria-valuemax, aria-valuenow if using custom slider
5529
+ - Add aria-valuetext for human-readable value (e.g., "50%")
5530
+
4855
5531
  Usage:
4856
5532
  <div class="ds-slider">
4857
- <input type="range" min="0" max="100" value="50" />
5533
+ <input type="range" min="0" max="100" value="50" aria-label="Volume" />
4858
5534
  <div class="ds-slider__labels">
4859
5535
  <span>0</span>
4860
5536
  <span>100</span>
@@ -4887,8 +5563,8 @@ tr:hover .ds-sortable__handle,
4887
5563
  .ds-slider input[type="range"]::-webkit-slider-thumb {
4888
5564
  -webkit-appearance: none;
4889
5565
  appearance: none;
4890
- width: 1.25rem;
4891
- height: 1.25rem;
5566
+ width: 1.5rem; /* WCAG 2.5.8: minimum 24px target */
5567
+ height: 1.5rem;
4892
5568
  border-radius: var(--ds-radius-full);
4893
5569
  background-color: var(--ds-color-inverted);
4894
5570
  border: 2px solid var(--ds-color-surface);
@@ -4899,8 +5575,8 @@ tr:hover .ds-sortable__handle,
4899
5575
 
4900
5576
  /* Firefox thumb */
4901
5577
  .ds-slider input[type="range"]::-moz-range-thumb {
4902
- width: 1.25rem;
4903
- height: 1.25rem;
5578
+ width: 1.5rem; /* WCAG 2.5.8: minimum 24px target */
5579
+ height: 1.5rem;
4904
5580
  border-radius: var(--ds-radius-full);
4905
5581
  background-color: var(--ds-color-inverted);
4906
5582
  border: 2px solid var(--ds-color-surface);
@@ -4922,6 +5598,7 @@ tr:hover .ds-sortable__handle,
4922
5598
  .ds-slider input[type="range"]:focus-visible::-webkit-slider-thumb {
4923
5599
  outline: var(--ds-ring-width) solid var(--ds-ring-color);
4924
5600
  outline-offset: 0;
5601
+ scroll-margin-block: var(--ds-space-16, 4rem);
4925
5602
  }
4926
5603
 
4927
5604
  .ds-slider input[type="range"]:focus-visible::-moz-range-thumb {
@@ -4935,7 +5612,7 @@ tr:hover .ds-sortable__handle,
4935
5612
  justify-content: space-between;
4936
5613
  font-size: var(--ds-text-xs);
4937
5614
  color: var(--ds-color-text-tertiary);
4938
- margin-top: var(--ds-space-1);
5615
+ margin-block-start: var(--ds-space-1);
4939
5616
  }
4940
5617
 
4941
5618
  /* Current value display */
@@ -4999,16 +5676,16 @@ tr:hover .ds-sortable__handle,
4999
5676
 
5000
5677
  .ds-timeline {
5001
5678
  position: relative;
5002
- padding-left: var(--ds-space-8);
5679
+ padding-inline-start: var(--ds-space-8);
5003
5680
  }
5004
5681
 
5005
5682
  /* Vertical line */
5006
5683
  .ds-timeline::before {
5007
5684
  content: "";
5008
5685
  position: absolute;
5009
- left: 0.9rem;
5010
- top: 0;
5011
- bottom: 0;
5686
+ inset-inline-start: 0.9rem;
5687
+ inset-block-start: 0;
5688
+ inset-block-end: 0;
5012
5689
  width: 2px;
5013
5690
  background-color: var(--ds-color-border);
5014
5691
  }
@@ -5016,17 +5693,17 @@ tr:hover .ds-sortable__handle,
5016
5693
  /* Item */
5017
5694
  .ds-timeline__item {
5018
5695
  position: relative;
5019
- padding-bottom: var(--ds-space-6);
5696
+ padding-block-end: var(--ds-space-6);
5020
5697
  }
5021
5698
 
5022
5699
  .ds-timeline__item:last-child {
5023
- padding-bottom: 0;
5700
+ padding-block-end: 0;
5024
5701
  }
5025
5702
 
5026
5703
  /* Dot */
5027
5704
  .ds-timeline__dot {
5028
5705
  position: absolute;
5029
- left: calc(-1 * var(--ds-space-8) + 0.5rem);
5706
+ inset-inline-start: calc(-1 * var(--ds-space-8) + 0.5rem);
5030
5707
  width: 1rem;
5031
5708
  height: 1rem;
5032
5709
  border-radius: var(--ds-radius-full);
@@ -5069,35 +5746,35 @@ tr:hover .ds-sortable__handle,
5069
5746
  .ds-timeline__description {
5070
5747
  font-size: var(--ds-text-sm);
5071
5748
  color: var(--ds-color-text-secondary);
5072
- margin-top: var(--ds-space-1);
5749
+ margin-block-start: var(--ds-space-1);
5073
5750
  }
5074
5751
 
5075
5752
  /* Timestamp */
5076
5753
  .ds-timeline__time {
5077
5754
  font-size: var(--ds-text-xs);
5078
5755
  color: var(--ds-color-text-tertiary);
5079
- margin-top: var(--ds-space-0-5);
5756
+ margin-block-start: var(--ds-space-0-5);
5080
5757
  }
5081
5758
 
5082
5759
  /* Compact variant */
5083
5760
  .ds-timeline--compact {
5084
- padding-left: var(--ds-space-6);
5761
+ padding-inline-start: var(--ds-space-6);
5085
5762
  }
5086
5763
 
5087
5764
  .ds-timeline--compact::before {
5088
- left: 0.6rem;
5765
+ inset-inline-start: 0.6rem;
5089
5766
  }
5090
5767
 
5091
5768
  .ds-timeline--compact .ds-timeline__item {
5092
- padding-bottom: var(--ds-space-4);
5769
+ padding-block-end: var(--ds-space-4);
5093
5770
  }
5094
5771
 
5095
5772
  .ds-timeline--compact .ds-timeline__item:last-child {
5096
- padding-bottom: 0;
5773
+ padding-block-end: 0;
5097
5774
  }
5098
5775
 
5099
5776
  .ds-timeline--compact .ds-timeline__dot {
5100
- left: calc(-1 * var(--ds-space-6) + 0.25rem);
5777
+ inset-inline-start: calc(-1 * var(--ds-space-6) + 0.25rem);
5101
5778
  width: 0.75rem;
5102
5779
  height: 0.75rem;
5103
5780
  }
@@ -5131,7 +5808,7 @@ tr:hover .ds-sortable__handle,
5131
5808
  font-size: var(--ds-text-xs);
5132
5809
  background-color: var(--ds-color-bg-elevated);
5133
5810
  border: 1px solid var(--ds-color-border);
5134
- border-bottom-width: 2px;
5811
+ border-block-end-width: 2px;
5135
5812
  border-radius: var(--ds-radius-sm);
5136
5813
  color: var(--ds-color-text-secondary);
5137
5814
  line-height: 1;
@@ -5164,17 +5841,26 @@ tr:hover .ds-sortable__handle,
5164
5841
  full-screen overlay with a centered search dialog, grouped results,
5165
5842
  keyboard-navigable items, and a footer with shortcut hints.
5166
5843
 
5844
+ ARIA requirements (consumer responsibility):
5845
+ - Input: role="combobox", aria-expanded="true", aria-controls="[list-id]"
5846
+ - Input: aria-activedescendant="[active-item-id]" for keyboard nav
5847
+ - List: role="listbox", id matching aria-controls
5848
+ - Items: role="option", id for aria-activedescendant
5849
+ - Groups: role="group", aria-labelledby="[heading-id]"
5850
+ - Overlay: role="dialog", aria-modal="true", aria-label="Command palette"
5851
+ - Keyboard: ArrowUp/Down to navigate, Enter to select, Escape to close
5852
+
5167
5853
  Usage:
5168
- <div class="ds-command ds-command--open">
5854
+ <div class="ds-command ds-command--open" role="dialog" aria-modal="true" aria-label="Command palette">
5169
5855
  <div class="ds-command__content">
5170
5856
  <div class="ds-command__input-wrapper">
5171
5857
  <span class="ds-command__input-icon">...</span>
5172
- <input class="ds-command__input" placeholder="Search..." />
5858
+ <input class="ds-command__input" role="combobox" placeholder="Search..." />
5173
5859
  </div>
5174
- <div class="ds-command__list">
5860
+ <div class="ds-command__list" role="listbox">
5175
5861
  <div class="ds-command__group">
5176
5862
  <div class="ds-command__group-heading">Results</div>
5177
- <div class="ds-command__item ds-command__item--active">
5863
+ <div class="ds-command__item ds-command__item--active" role="option">
5178
5864
  <span class="ds-command__item-icon">...</span>
5179
5865
  <span class="ds-command__item-label">Item</span>
5180
5866
  <span class="ds-command__item-shortcut">Ctrl+N</span>
@@ -5198,7 +5884,7 @@ tr:hover .ds-sortable__handle,
5198
5884
  display: flex;
5199
5885
  align-items: flex-start;
5200
5886
  justify-content: center;
5201
- padding-top: 20vh;
5887
+ padding-block-start: 20vh;
5202
5888
  background-color: var(--ds-color-overlay);
5203
5889
  opacity: 0;
5204
5890
  visibility: hidden;
@@ -5237,7 +5923,7 @@ tr:hover .ds-sortable__handle,
5237
5923
  align-items: center;
5238
5924
  gap: var(--ds-space-3);
5239
5925
  padding: var(--ds-space-3) var(--ds-space-4);
5240
- border-bottom: 1px solid var(--ds-color-border);
5926
+ border-block-end: 1px solid var(--ds-color-border);
5241
5927
  }
5242
5928
 
5243
5929
  /* Search icon */
@@ -5307,6 +5993,7 @@ tr:hover .ds-sortable__handle,
5307
5993
  .ds-command__item:focus-visible {
5308
5994
  outline: none;
5309
5995
  box-shadow: inset 0 0 0 var(--ds-ring-width) var(--ds-ring-color);
5996
+ scroll-margin-block: var(--ds-space-16, 4rem);
5310
5997
  }
5311
5998
 
5312
5999
  /* Item icon */
@@ -5341,7 +6028,7 @@ tr:hover .ds-sortable__handle,
5341
6028
  align-items: center;
5342
6029
  gap: var(--ds-space-4);
5343
6030
  padding: var(--ds-space-2) var(--ds-space-3);
5344
- border-top: 1px solid var(--ds-color-border);
6031
+ border-block-start: 1px solid var(--ds-color-border);
5345
6032
  font-size: var(--ds-text-xs);
5346
6033
  color: var(--ds-color-text-tertiary);
5347
6034
  }
@@ -5351,25 +6038,20 @@ tr:hover .ds-sortable__handle,
5351
6038
  Inline search bar with dropdown results, keyboard navigation, and
5352
6039
  responsive mobile expansion. Distinct from ds-command (modal overlay).
5353
6040
 
6041
+ ARIA requirements (consumer responsibility):
6042
+ - Container: role="search" on wrapper or parent <form>
6043
+ - Input: role="combobox", aria-expanded="true|false", aria-controls="[list-id]"
6044
+ - Dropdown: role="listbox" with id matching aria-controls
6045
+ - Results: role="option", aria-selected="true" on active result
6046
+ - Clear button: aria-label="Clear search"
6047
+ - Keyboard: ArrowUp/Down to navigate, Enter to select, Escape to close
6048
+
5354
6049
  Usage:
5355
- <div class="ds-search">
6050
+ <div class="ds-search" role="search">
5356
6051
  <span class="ds-search__icon">...</span>
5357
6052
  <input class="ds-search__input" placeholder="Search..." />
5358
6053
  <kbd class="ds-search__shortcut">Ctrl+K</kbd>
5359
- <button class="ds-search__clear">...</button>
5360
- </div>
5361
- <div class="ds-search__dropdown">
5362
- <div class="ds-search__group">
5363
- <span class="ds-search__group-label">Pages</span>
5364
- <button class="ds-search__result ds-search__result--active">
5365
- <span class="ds-search__result-icon">...</span>
5366
- <div class="ds-search__result-content">
5367
- <span class="ds-search__result-title">Page name</span>
5368
- <span class="ds-search__result-meta">Database</span>
5369
- </div>
5370
- </button>
5371
- </div>
5372
- <div class="ds-search__empty">No results found.</div>
6054
+ <button class="ds-search__clear" aria-label="Clear search">...</button>
5373
6055
  </div>
5374
6056
 
5375
6057
  Modifiers:
@@ -5447,6 +6129,8 @@ tr:hover .ds-sortable__handle,
5447
6129
  flex-shrink: 0;
5448
6130
  width: 1.25rem;
5449
6131
  height: 1.25rem;
6132
+ min-width: 1.5rem; /* WCAG 2.5.8: minimum 24px target */
6133
+ min-height: 1.5rem;
5450
6134
  border: none;
5451
6135
  border-radius: var(--ds-radius-sm);
5452
6136
  background: transparent;
@@ -5481,7 +6165,7 @@ tr:hover .ds-sortable__handle,
5481
6165
  }
5482
6166
 
5483
6167
  .ds-search__group + .ds-search__group {
5484
- border-top: 1px solid var(--ds-color-border);
6168
+ border-block-start: 1px solid var(--ds-color-border);
5485
6169
  }
5486
6170
 
5487
6171
  .ds-search__group-label {
@@ -5506,7 +6190,7 @@ tr:hover .ds-sortable__handle,
5506
6190
  color: var(--ds-color-text);
5507
6191
  font-size: var(--ds-text-sm);
5508
6192
  font-family: inherit;
5509
- text-align: left;
6193
+ text-align: start;
5510
6194
  cursor: pointer;
5511
6195
  transition: background-color var(--ds-duration-fast) var(--ds-ease-default);
5512
6196
  }
@@ -5519,6 +6203,7 @@ tr:hover .ds-sortable__handle,
5519
6203
  .ds-search__result:focus-visible {
5520
6204
  outline: none;
5521
6205
  box-shadow: inset 0 0 0 var(--ds-ring-width) var(--ds-ring-color);
6206
+ scroll-margin-block: var(--ds-space-16, 4rem);
5522
6207
  }
5523
6208
 
5524
6209
  .ds-search__result-icon {
@@ -5607,7 +6292,7 @@ tr:hover .ds-sortable__handle,
5607
6292
  }
5608
6293
 
5609
6294
  /* Responsive: mobile */
5610
- @media (max-width: 1023px) {
6295
+ @media (max-width: 1023px) /* below --ds-breakpoint-lg */ {
5611
6296
  .ds-search__shortcut { display: none; }
5612
6297
  .ds-search-mobile-trigger { display: flex; }
5613
6298
  .ds-search { display: none; }
@@ -5615,13 +6300,13 @@ tr:hover .ds-sortable__handle,
5615
6300
  .ds-search--mobile-expanded {
5616
6301
  display: flex;
5617
6302
  position: fixed;
5618
- top: 0;
5619
- left: 0;
5620
- right: 0;
6303
+ inset-block-start: 0;
6304
+ inset-inline-start: 0;
6305
+ inset-inline-end: 0;
5621
6306
  height: var(--ds-search-bar-height, 3.5rem);
5622
6307
  z-index: var(--ds-z-dropdown);
5623
6308
  border: none;
5624
- border-bottom: 1px solid var(--ds-color-border);
6309
+ border-block-end: 1px solid var(--ds-color-border);
5625
6310
  border-radius: 0;
5626
6311
  padding: 0 var(--ds-space-3);
5627
6312
  background: var(--ds-color-nav-bg);
@@ -5630,12 +6315,12 @@ tr:hover .ds-sortable__handle,
5630
6315
  }
5631
6316
 
5632
6317
  .ds-search__dropdown--mobile {
5633
- left: 0 !important;
5634
- right: 0;
6318
+ inset-inline-start: 0 !important;
6319
+ inset-inline-end: 0;
5635
6320
  width: auto !important;
5636
6321
  border-radius: 0;
5637
- border-left: none;
5638
- border-right: none;
6322
+ border-inline-start: none;
6323
+ border-inline-end: none;
5639
6324
  max-height: calc(100dvh - var(--ds-search-bar-height, 3.5rem));
5640
6325
  background: var(--ds-color-surface);
5641
6326
  backdrop-filter: blur(20px) saturate(1.5);
@@ -5811,7 +6496,7 @@ tr:hover .ds-sortable__handle,
5811
6496
  }
5812
6497
 
5813
6498
  /* Responsive: mobile */
5814
- @media (max-width: 1023px) {
6499
+ @media (max-width: 1023px) /* below --ds-breakpoint-lg */ {
5815
6500
  .ds-toolbar__row {
5816
6501
  padding-inline: var(--ds-space-3);
5817
6502
  gap: var(--ds-space-2);
@@ -5838,10 +6523,15 @@ tr:hover .ds-sortable__handle,
5838
6523
  Interactive filter/sort chips with optional remove button. Distinct from
5839
6524
  ds-tag (which is a static label). Chips represent active filter state.
5840
6525
 
6526
+ ARIA requirements (consumer responsibility):
6527
+ - Remove button: add aria-label="Remove [filter name]"
6528
+ - Logic chip (AND/OR): use aria-pressed="true|false" on <button>
6529
+ - Chip group: wrap in role="group" with aria-label="Active filters"
6530
+
5841
6531
  Usage:
5842
6532
  <span class="ds-chip">
5843
6533
  Status: Active
5844
- <button class="ds-chip__remove">×</button>
6534
+ <button class="ds-chip__remove" aria-label="Remove Status filter">×</button>
5845
6535
  </span>
5846
6536
  <button class="ds-chip ds-chip--logic">AND</button>
5847
6537
  <span class="ds-chip ds-chip--sort">Date ↑</span>
@@ -5876,7 +6566,7 @@ tr:hover .ds-sortable__handle,
5876
6566
  }
5877
6567
 
5878
6568
  .ds-chip--logic:hover {
5879
- background: var(--ds-color-surface-hover);
6569
+ background: var(--ds-color-overlay-hover);
5880
6570
  }
5881
6571
 
5882
6572
  /* Sort chip (dashed border) */
@@ -5891,6 +6581,8 @@ tr:hover .ds-sortable__handle,
5891
6581
  justify-content: center;
5892
6582
  width: 14px;
5893
6583
  height: 14px;
6584
+ min-width: 1.5rem; /* WCAG 2.5.8: minimum 24px target */
6585
+ min-height: 1.5rem;
5894
6586
  border: none;
5895
6587
  border-radius: var(--ds-radius-full);
5896
6588
  background: transparent;
@@ -5903,7 +6595,7 @@ tr:hover .ds-sortable__handle,
5903
6595
 
5904
6596
  .ds-chip__remove:hover {
5905
6597
  color: var(--ds-color-text);
5906
- background: var(--ds-color-surface-hover);
6598
+ background: var(--ds-color-overlay-hover);
5907
6599
  }
5908
6600
 
5909
6601
  /* ==========================================================================
@@ -5911,12 +6603,17 @@ tr:hover .ds-sortable__handle,
5911
6603
  Standalone icon button for actions, toolbar items, and table rows.
5912
6604
  A minimal interactive element that wraps a single icon.
5913
6605
 
6606
+ ARIA requirements (consumer responsibility):
6607
+ - Always add aria-label="[action]" (e.g., aria-label="Delete")
6608
+ - Disabled: add aria-disabled="true"
6609
+ - Toggle: use aria-pressed="true|false" for toggle icon buttons
6610
+
5914
6611
  Usage:
5915
- <button class="ds-icon-btn">
6612
+ <button class="ds-icon-btn" aria-label="Delete">
5916
6613
  <svg>...</svg>
5917
6614
  </button>
5918
- <button class="ds-icon-btn ds-icon-btn--sm">...</button>
5919
- <button class="ds-icon-btn ds-icon-btn--danger">...</button>
6615
+ <button class="ds-icon-btn ds-icon-btn--sm" aria-label="Edit">...</button>
6616
+ <button class="ds-icon-btn ds-icon-btn--danger" aria-label="Remove">...</button>
5920
6617
 
5921
6618
  Sizes:
5922
6619
  .ds-icon-btn--xs — 24px (var(--ds-size-1))
@@ -5955,6 +6652,7 @@ tr:hover .ds-sortable__handle,
5955
6652
  .ds-icon-btn:focus-visible {
5956
6653
  outline: none;
5957
6654
  box-shadow: 0 0 0 var(--ds-ring-width) var(--ds-ring-color);
6655
+ scroll-margin-block: var(--ds-space-16, 4rem);
5958
6656
  }
5959
6657
 
5960
6658
  .ds-icon-btn:disabled,
@@ -5973,9 +6671,9 @@ tr:hover .ds-sortable__handle,
5973
6671
  }
5974
6672
 
5975
6673
  .ds-icon-btn--sm {
5976
- width: 1.75rem;
5977
- height: 1.75rem;
5978
- padding: var(--ds-space-1);
6674
+ width: var(--ds-size-2);
6675
+ height: var(--ds-size-2);
6676
+ padding: var(--ds-space-1-5);
5979
6677
  border-radius: var(--ds-radius-md);
5980
6678
  }
5981
6679
 
@@ -6008,16 +6706,22 @@ tr:hover .ds-sortable__handle,
6008
6706
  Mobile bottom navigation bar. Hidden on desktop, shown on mobile.
6009
6707
  Fixed to bottom with safe-area insets for notched devices.
6010
6708
 
6709
+ ARIA requirements (consumer responsibility):
6710
+ - Container: <nav aria-label="Bottom navigation">
6711
+ - Active item: aria-current="page" on the current tab
6712
+ - Badge: aria-label on badge parent (e.g., "Home, 3 notifications")
6713
+ - Create button: aria-label="Create new"
6714
+
6011
6715
  Usage:
6012
- <nav class="ds-bottom-nav">
6013
- <a href="/" class="ds-bottom-nav__item ds-bottom-nav__item--active">
6716
+ <nav class="ds-bottom-nav" aria-label="Bottom navigation">
6717
+ <a href="/" class="ds-bottom-nav__item ds-bottom-nav__item--active" aria-current="page">
6014
6718
  <span class="ds-bottom-nav__icon">
6015
6719
  <svg>...</svg>
6016
6720
  <span class="ds-bottom-nav__badge">3</span>
6017
6721
  </span>
6018
6722
  <span class="ds-bottom-nav__label">Home</span>
6019
6723
  </a>
6020
- <button class="ds-bottom-nav__item ds-bottom-nav__item--create">
6724
+ <button class="ds-bottom-nav__item ds-bottom-nav__item--create" aria-label="Create new">
6021
6725
  <span class="ds-bottom-nav__create-icon">+</span>
6022
6726
  <span class="ds-bottom-nav__label">New</span>
6023
6727
  </button>
@@ -6031,16 +6735,16 @@ tr:hover .ds-sortable__handle,
6031
6735
  .ds-bottom-nav {
6032
6736
  display: none;
6033
6737
  position: fixed;
6034
- bottom: 0;
6035
- left: 0;
6036
- right: 0;
6738
+ inset-block-end: 0;
6739
+ inset-inline-start: 0;
6740
+ inset-inline-end: 0;
6037
6741
  z-index: var(--ds-z-dropdown);
6038
6742
  background: var(--ds-color-surface);
6039
- border-top: 1px solid var(--ds-color-border);
6040
- padding-bottom: env(safe-area-inset-bottom, 0px);
6743
+ border-block-start: 1px solid var(--ds-color-border);
6744
+ padding-block-end: env(safe-area-inset-bottom, 0px);
6041
6745
  }
6042
6746
 
6043
- @media (max-width: 1023px) {
6747
+ @media (max-width: 1023px) /* below --ds-breakpoint-lg */ {
6044
6748
  .ds-bottom-nav {
6045
6749
  display: flex;
6046
6750
  justify-content: space-around;
@@ -6048,7 +6752,7 @@ tr:hover .ds-sortable__handle,
6048
6752
  }
6049
6753
  }
6050
6754
 
6051
- @media (min-width: 1024px) {
6755
+ @media (min-width: 1024px) /* --ds-breakpoint-lg */ {
6052
6756
  .ds-bottom-nav { display: none !important; }
6053
6757
  }
6054
6758
 
@@ -6086,25 +6790,25 @@ tr:hover .ds-sortable__handle,
6086
6790
  /* Notification badge */
6087
6791
  .ds-bottom-nav__badge {
6088
6792
  position: absolute;
6089
- top: -4px;
6090
- right: -8px;
6091
- min-width: 16px;
6092
- height: 16px;
6093
- padding: 0 4px;
6793
+ inset-block-start: calc(-1 * var(--ds-space-1));
6794
+ inset-inline-end: calc(-1 * var(--ds-space-2));
6795
+ min-width: var(--ds-space-4);
6796
+ height: var(--ds-space-4);
6797
+ padding: 0 var(--ds-space-1);
6094
6798
  border-radius: var(--ds-radius-full);
6095
6799
  background: var(--ds-color-error);
6096
- color: #fff;
6097
- font-size: 10px;
6098
- font-weight: 600;
6099
- line-height: 16px;
6800
+ color: var(--ds-color-on-inverted);
6801
+ font-size: var(--ds-text-2xs);
6802
+ font-weight: var(--ds-weight-semibold);
6803
+ line-height: var(--ds-space-4);
6100
6804
  text-align: center;
6101
6805
  }
6102
6806
 
6103
6807
  /* Label */
6104
6808
  .ds-bottom-nav__label {
6105
- font-size: 10px;
6809
+ font-size: var(--ds-text-2xs);
6106
6810
  font-weight: var(--ds-weight-medium);
6107
- letter-spacing: 0.02em;
6811
+ letter-spacing: var(--ds-tracking-wide);
6108
6812
  }
6109
6813
 
6110
6814
  /* Create button — elevated center icon */
@@ -6185,6 +6889,8 @@ tr:hover .ds-sortable__handle,
6185
6889
  }
6186
6890
 
6187
6891
 
6892
+ }
6893
+ @layer utilities {
6188
6894
  /* ==========================================================================
6189
6895
  Utilities: Layout
6190
6896
  Container with clamp padding, generous responsive grid.
@@ -6265,7 +6971,7 @@ tr:hover .ds-sortable__handle,
6265
6971
  .ds-md\:flex-row { flex-direction: row; }
6266
6972
  }
6267
6973
 
6268
- @media (min-width: 1024px) {
6974
+ @media (min-width: 1024px) /* --ds-breakpoint-lg */ {
6269
6975
  .ds-lg\:grid-cols-2 { grid-template-columns: repeat(2, 1fr); }
6270
6976
  .ds-lg\:grid-cols-3 { grid-template-columns: repeat(3, 1fr); }
6271
6977
  .ds-lg\:grid-cols-4 { grid-template-columns: repeat(4, 1fr); }
@@ -6304,7 +7010,7 @@ tr:hover .ds-sortable__handle,
6304
7010
  .ds-relative { position: relative; }
6305
7011
  .ds-absolute { position: absolute; }
6306
7012
  .ds-fixed { position: fixed; }
6307
- .ds-sticky { position: sticky; top: 0; }
7013
+ .ds-sticky { position: sticky; inset-block-start: 0; }
6308
7014
 
6309
7015
  /* --- Overflow --- */
6310
7016
  .ds-overflow-hidden { overflow: hidden; }
@@ -6320,14 +7026,14 @@ tr:hover .ds-sortable__handle,
6320
7026
  /* --- Stack (vertical spacing) ---
6321
7027
  :where() lowers specificity so ds-mt-* can override individual children. */
6322
7028
  :where(.ds-stack) > * + * {
6323
- margin-top: var(--ds-space-4);
7029
+ margin-block-start: var(--ds-space-4);
6324
7030
  }
6325
7031
 
6326
- :where(.ds-stack--sm) > * + * { margin-top: var(--ds-space-2); }
6327
- :where(.ds-stack--lg) > * + * { margin-top: var(--ds-space-8); }
6328
- :where(.ds-stack--xl) > * + * { margin-top: var(--ds-space-12); }
6329
- :where(.ds-stack--2xl) > * + * { margin-top: var(--ds-space-16); }
6330
- :where(.ds-stack--3xl) > * + * { margin-top: var(--ds-space-24); }
7032
+ :where(.ds-stack--sm) > * + * { margin-block-start: var(--ds-space-2); }
7033
+ :where(.ds-stack--lg) > * + * { margin-block-start: var(--ds-space-8); }
7034
+ :where(.ds-stack--xl) > * + * { margin-block-start: var(--ds-space-12); }
7035
+ :where(.ds-stack--2xl) > * + * { margin-block-start: var(--ds-space-16); }
7036
+ :where(.ds-stack--3xl) > * + * { margin-block-start: var(--ds-space-24); }
6331
7037
 
6332
7038
  /* --- Center content --- */
6333
7039
  .ds-center {
@@ -6380,22 +7086,22 @@ tr:hover .ds-sortable__handle,
6380
7086
 
6381
7087
  /* --- Inset / Position Values --- */
6382
7088
  .ds-inset-0 { inset: 0; }
6383
- .ds-inset-x-0 { left: 0; right: 0; }
6384
- .ds-inset-y-0 { top: 0; bottom: 0; }
6385
- .ds-top-0 { top: 0; }
6386
- .ds-top-full { top: 100%; }
6387
- .ds-right-0 { right: 0; }
6388
- .ds-bottom-0 { bottom: 0; }
6389
- .ds-bottom-full { bottom: 100%; }
6390
- .ds-left-0 { left: 0; }
6391
- .ds-top-2 { top: var(--ds-space-2); }
6392
- .ds-right-2 { right: var(--ds-space-2); }
6393
- .ds-left-2 { left: var(--ds-space-2); }
6394
- .ds-top-3 { top: var(--ds-space-3); }
6395
- .ds-right-3 { right: var(--ds-space-3); }
6396
- .ds-left-3 { left: var(--ds-space-3); }
6397
- .ds-top-1\/2 { top: 50%; }
6398
- .ds-left-1\/2 { left: 50%; }
7089
+ .ds-inset-x-0 { inset-inline-start: 0; inset-inline-end: 0; }
7090
+ .ds-inset-y-0 { inset-block-start: 0; inset-block-end: 0; }
7091
+ .ds-top-0 { inset-block-start: 0; }
7092
+ .ds-top-full { inset-block-start: 100%; }
7093
+ .ds-right-0 { inset-inline-end: 0; }
7094
+ .ds-bottom-0 { inset-block-end: 0; }
7095
+ .ds-bottom-full { inset-block-end: 100%; }
7096
+ .ds-left-0 { inset-inline-start: 0; }
7097
+ .ds-top-2 { inset-block-start: var(--ds-space-2); }
7098
+ .ds-right-2 { inset-inline-end: var(--ds-space-2); }
7099
+ .ds-left-2 { inset-inline-start: var(--ds-space-2); }
7100
+ .ds-top-3 { inset-block-start: var(--ds-space-3); }
7101
+ .ds-right-3 { inset-inline-end: var(--ds-space-3); }
7102
+ .ds-left-3 { inset-inline-start: var(--ds-space-3); }
7103
+ .ds-top-1\/2 { inset-block-start: 50%; }
7104
+ .ds-left-1\/2 { inset-inline-start: 50%; }
6399
7105
 
6400
7106
  /* --- Object Fit --- */
6401
7107
  .ds-object-cover { object-fit: cover; }
@@ -6413,7 +7119,7 @@ tr:hover .ds-sortable__handle,
6413
7119
  .ds-sm\:table-cell { display: table-cell; }
6414
7120
  }
6415
7121
 
6416
- @media (min-width: 1024px) {
7122
+ @media (min-width: 1024px) /* --ds-breakpoint-lg */ {
6417
7123
  .ds-lg\:hidden { display: none; }
6418
7124
  .ds-lg\:block { display: block; }
6419
7125
  .ds-lg\:flex { display: flex; }
@@ -6424,7 +7130,7 @@ tr:hover .ds-sortable__handle,
6424
7130
  .ds-sm\:grid-cols-4 { grid-template-columns: repeat(4, 1fr); }
6425
7131
  }
6426
7132
 
6427
- @media (min-width: 1024px) {
7133
+ @media (min-width: 1024px) /* --ds-breakpoint-lg */ {
6428
7134
  .ds-lg\:grid-cols-2 { grid-template-columns: repeat(2, 1fr); }
6429
7135
  .ds-lg\:grid-cols-5 { grid-template-columns: repeat(5, 1fr); }
6430
7136
  }
@@ -6476,15 +7182,15 @@ tr:hover .ds-sortable__handle,
6476
7182
  .ds-py-20 { padding-block: var(--ds-space-20); }
6477
7183
  .ds-py-24 { padding-block: var(--ds-space-24); }
6478
7184
 
6479
- .ds-pt-2 { padding-top: var(--ds-space-2); }
6480
- .ds-pt-4 { padding-top: var(--ds-space-4); }
6481
- .ds-pt-6 { padding-top: var(--ds-space-6); }
6482
- .ds-pt-8 { padding-top: var(--ds-space-8); }
6483
- .ds-pt-12 { padding-top: var(--ds-space-12); }
6484
- .ds-pt-16 { padding-top: var(--ds-space-16); }
7185
+ .ds-pt-2 { padding-block-start: var(--ds-space-2); }
7186
+ .ds-pt-4 { padding-block-start: var(--ds-space-4); }
7187
+ .ds-pt-6 { padding-block-start: var(--ds-space-6); }
7188
+ .ds-pt-8 { padding-block-start: var(--ds-space-8); }
7189
+ .ds-pt-12 { padding-block-start: var(--ds-space-12); }
7190
+ .ds-pt-16 { padding-block-start: var(--ds-space-16); }
6485
7191
 
6486
- .ds-pb-4 { padding-bottom: var(--ds-space-4); }
6487
- .ds-pb-8 { padding-bottom: var(--ds-space-8); }
7192
+ .ds-pb-4 { padding-block-end: var(--ds-space-4); }
7193
+ .ds-pb-8 { padding-block-end: var(--ds-space-8); }
6488
7194
 
6489
7195
  /* --- Margin --- */
6490
7196
  .ds-m-0 { margin: var(--ds-space-0); }
@@ -6500,33 +7206,33 @@ tr:hover .ds-sortable__handle,
6500
7206
  .ds-my-6 { margin-block: var(--ds-space-6); }
6501
7207
  .ds-my-8 { margin-block: var(--ds-space-8); }
6502
7208
 
6503
- .ds-mt-0 { margin-top: var(--ds-space-0); }
6504
- .ds-mt-1 { margin-top: var(--ds-space-1); }
6505
- .ds-mt-2 { margin-top: var(--ds-space-2); }
6506
- .ds-mt-4 { margin-top: var(--ds-space-4); }
6507
- .ds-mt-6 { margin-top: var(--ds-space-6); }
6508
- .ds-mt-8 { margin-top: var(--ds-space-8); }
6509
-
6510
- .ds-mb-0 { margin-bottom: var(--ds-space-0); }
6511
- .ds-mb-1 { margin-bottom: var(--ds-space-1); }
6512
- .ds-mb-2 { margin-bottom: var(--ds-space-2); }
6513
- .ds-mb-4 { margin-bottom: var(--ds-space-4); }
6514
- .ds-mb-6 { margin-bottom: var(--ds-space-6); }
6515
- .ds-mb-8 { margin-bottom: var(--ds-space-8); }
6516
-
6517
- .ds-mt-auto { margin-top: auto; }
6518
- .ds-mb-auto { margin-bottom: auto; }
6519
- .ds-ml-auto { margin-left: auto; }
6520
- .ds-mr-auto { margin-right: auto; }
6521
- .ds-ml-2 { margin-left: var(--ds-space-2); }
6522
- .ds-ml-4 { margin-left: var(--ds-space-4); }
6523
- .ds-mr-2 { margin-right: var(--ds-space-2); }
6524
- .ds-mr-4 { margin-right: var(--ds-space-4); }
6525
-
6526
- .ds-mt-0\.5 { margin-top: var(--ds-space-0-5); }
6527
- .ds-mt-3 { margin-top: var(--ds-space-3); }
6528
- .ds-mb-0\.5 { margin-bottom: var(--ds-space-0-5); }
6529
- .ds-mb-3 { margin-bottom: var(--ds-space-3); }
7209
+ .ds-mt-0 { margin-block-start: var(--ds-space-0); }
7210
+ .ds-mt-1 { margin-block-start: var(--ds-space-1); }
7211
+ .ds-mt-2 { margin-block-start: var(--ds-space-2); }
7212
+ .ds-mt-4 { margin-block-start: var(--ds-space-4); }
7213
+ .ds-mt-6 { margin-block-start: var(--ds-space-6); }
7214
+ .ds-mt-8 { margin-block-start: var(--ds-space-8); }
7215
+
7216
+ .ds-mb-0 { margin-block-end: var(--ds-space-0); }
7217
+ .ds-mb-1 { margin-block-end: var(--ds-space-1); }
7218
+ .ds-mb-2 { margin-block-end: var(--ds-space-2); }
7219
+ .ds-mb-4 { margin-block-end: var(--ds-space-4); }
7220
+ .ds-mb-6 { margin-block-end: var(--ds-space-6); }
7221
+ .ds-mb-8 { margin-block-end: var(--ds-space-8); }
7222
+
7223
+ .ds-mt-auto { margin-block-start: auto; }
7224
+ .ds-mb-auto { margin-block-end: auto; }
7225
+ .ds-ml-auto { margin-inline-start: auto; }
7226
+ .ds-mr-auto { margin-inline-end: auto; }
7227
+ .ds-ml-2 { margin-inline-start: var(--ds-space-2); }
7228
+ .ds-ml-4 { margin-inline-start: var(--ds-space-4); }
7229
+ .ds-mr-2 { margin-inline-end: var(--ds-space-2); }
7230
+ .ds-mr-4 { margin-inline-end: var(--ds-space-4); }
7231
+
7232
+ .ds-mt-0\.5 { margin-block-start: var(--ds-space-0-5); }
7233
+ .ds-mt-3 { margin-block-start: var(--ds-space-3); }
7234
+ .ds-mb-0\.5 { margin-block-end: var(--ds-space-0-5); }
7235
+ .ds-mb-3 { margin-block-end: var(--ds-space-3); }
6530
7236
 
6531
7237
  /* --- Padding (granular) --- */
6532
7238
  .ds-p-0\.5 { padding: var(--ds-space-0-5); }
@@ -6539,29 +7245,29 @@ tr:hover .ds-sortable__handle,
6539
7245
  .ds-py-1 { padding-block: var(--ds-space-1); }
6540
7246
  .ds-py-1\.5 { padding-block: var(--ds-space-1-5); }
6541
7247
 
6542
- .ds-pb-2 { padding-bottom: var(--ds-space-2); }
6543
- .ds-pb-6 { padding-bottom: var(--ds-space-6); }
7248
+ .ds-pb-2 { padding-block-end: var(--ds-space-2); }
7249
+ .ds-pb-6 { padding-block-end: var(--ds-space-6); }
6544
7250
 
6545
- .ds-pl-2 { padding-left: var(--ds-space-2); }
6546
- .ds-pl-3 { padding-left: var(--ds-space-3); }
6547
- .ds-pl-4 { padding-left: var(--ds-space-4); }
6548
- .ds-pr-2 { padding-right: var(--ds-space-2); }
6549
- .ds-pr-3 { padding-right: var(--ds-space-3); }
6550
- .ds-pr-4 { padding-right: var(--ds-space-4); }
6551
- .ds-pr-7 { padding-right: 1.75rem; }
6552
- .ds-pr-10 { padding-right: var(--ds-space-10); }
7251
+ .ds-pl-2 { padding-inline-start: var(--ds-space-2); }
7252
+ .ds-pl-3 { padding-inline-start: var(--ds-space-3); }
7253
+ .ds-pl-4 { padding-inline-start: var(--ds-space-4); }
7254
+ .ds-pr-2 { padding-inline-end: var(--ds-space-2); }
7255
+ .ds-pr-3 { padding-inline-end: var(--ds-space-3); }
7256
+ .ds-pr-4 { padding-inline-end: var(--ds-space-4); }
7257
+ .ds-pr-7 { padding-inline-end: 1.75rem; }
7258
+ .ds-pr-10 { padding-inline-end: var(--ds-space-10); }
6553
7259
 
6554
7260
  /* --- Gap (fractional) --- */
6555
7261
  .ds-gap-0\.5 { gap: var(--ds-space-0-5); }
6556
7262
  .ds-gap-1\.5 { gap: var(--ds-space-1-5); }
6557
7263
 
6558
7264
  /* --- Space-Y (owl selector) --- */
6559
- .ds-space-y-1 > * + * { margin-top: var(--ds-space-1); }
6560
- .ds-space-y-2 > * + * { margin-top: var(--ds-space-2); }
6561
- .ds-space-y-3 > * + * { margin-top: var(--ds-space-3); }
6562
- .ds-space-y-4 > * + * { margin-top: var(--ds-space-4); }
6563
- .ds-space-y-6 > * + * { margin-top: var(--ds-space-6); }
6564
- .ds-space-y-8 > * + * { margin-top: var(--ds-space-8); }
7265
+ .ds-space-y-1 > * + * { margin-block-start: var(--ds-space-1); }
7266
+ .ds-space-y-2 > * + * { margin-block-start: var(--ds-space-2); }
7267
+ .ds-space-y-3 > * + * { margin-block-start: var(--ds-space-3); }
7268
+ .ds-space-y-4 > * + * { margin-block-start: var(--ds-space-4); }
7269
+ .ds-space-y-6 > * + * { margin-block-start: var(--ds-space-6); }
7270
+ .ds-space-y-8 > * + * { margin-block-start: var(--ds-space-8); }
6565
7271
 
6566
7272
  /* --- Responsive: Padding --- */
6567
7273
  @media (min-width: 768px) {
@@ -6573,7 +7279,7 @@ tr:hover .ds-sortable__handle,
6573
7279
  .ds-md\:py-16 { padding-block: var(--ds-space-16); }
6574
7280
  }
6575
7281
 
6576
- @media (min-width: 1024px) {
7282
+ @media (min-width: 1024px) /* --ds-breakpoint-lg */ {
6577
7283
  .ds-lg\:px-6 { padding-inline: var(--ds-space-6); }
6578
7284
  .ds-lg\:px-8 { padding-inline: var(--ds-space-8); }
6579
7285
  .ds-lg\:py-16 { padding-block: var(--ds-space-16); }
@@ -6611,7 +7317,7 @@ tr:hover .ds-sortable__handle,
6611
7317
  .ds-md\:text-4xl { font-size: var(--ds-text-4xl); }
6612
7318
  .ds-md\:text-6xl { font-size: var(--ds-text-6xl); }
6613
7319
  }
6614
- @media (min-width: 1024px) {
7320
+ @media (min-width: 1024px) /* --ds-breakpoint-lg */ {
6615
7321
  .ds-lg\:text-xl { font-size: var(--ds-text-xl); }
6616
7322
  .ds-lg\:text-2xl { font-size: var(--ds-text-2xl); }
6617
7323
  .ds-lg\:text-3xl { font-size: var(--ds-text-3xl); }
@@ -6628,9 +7334,9 @@ tr:hover .ds-sortable__handle,
6628
7334
  .ds-font-bold { font-weight: var(--ds-weight-bold); }
6629
7335
 
6630
7336
  /* --- Text Alignment --- */
6631
- .ds-text-left { text-align: left; }
7337
+ .ds-text-left { text-align: start; }
6632
7338
  .ds-text-center { text-align: center; }
6633
- .ds-text-right { text-align: right; }
7339
+ .ds-text-right { text-align: end; }
6634
7340
  .ds-text-balance { text-wrap: balance; }
6635
7341
 
6636
7342
  /* --- Text Color --- */
@@ -6747,10 +7453,10 @@ tr:hover .ds-sortable__handle,
6747
7453
 
6748
7454
  /* --- Border --- */
6749
7455
  .ds-border { border: 1px solid var(--ds-color-border); }
6750
- .ds-border-t { border-top: 1px solid var(--ds-color-border); }
6751
- .ds-border-b { border-bottom: 1px solid var(--ds-color-border); }
6752
- .ds-border-l { border-left: 1px solid var(--ds-color-border); }
6753
- .ds-border-r { border-right: 1px solid var(--ds-color-border); }
7456
+ .ds-border-t { border-block-start: 1px solid var(--ds-color-border); }
7457
+ .ds-border-b { border-block-end: 1px solid var(--ds-color-border); }
7458
+ .ds-border-l { border-inline-start: 1px solid var(--ds-color-border); }
7459
+ .ds-border-r { border-inline-end: 1px solid var(--ds-color-border); }
6754
7460
  .ds-border-none { border: none; }
6755
7461
 
6756
7462
  /* --- Border Color --- */
@@ -6762,7 +7468,7 @@ tr:hover .ds-sortable__handle,
6762
7468
  .ds-border-nav { border-color: var(--ds-color-nav-border); }
6763
7469
 
6764
7470
  /* --- Divide --- */
6765
- .ds-divide-y > * + * { border-top: 1px solid var(--ds-color-border); }
7471
+ .ds-divide-y > * + * { border-block-start: 1px solid var(--ds-color-border); }
6766
7472
 
6767
7473
  /* --- Border Radius --- */
6768
7474
  .ds-rounded-none { border-radius: var(--ds-radius-none); }
@@ -7023,4 +7729,108 @@ tr:hover .ds-sortable__handle,
7023
7729
  color: var(--ds-color-text);
7024
7730
  }
7025
7731
 
7732
+ /* ==========================================================================
7733
+ Utilities: Accessibility
7734
+ Screen-reader helpers, skip links, focus utilities, and motion control.
7735
+ ========================================================================== */
7736
+
7737
+ /* ---------------------------------------------------------------------------
7738
+ Screen Reader Only — visually hidden, available to assistive technology
7739
+ --------------------------------------------------------------------------- */
7740
+
7741
+ .ds-sr-only {
7742
+ position: absolute;
7743
+ width: 1px;
7744
+ height: 1px;
7745
+ padding: 0;
7746
+ margin: -1px;
7747
+ overflow: hidden;
7748
+ clip: rect(0, 0, 0, 0);
7749
+ white-space: nowrap;
7750
+ border-width: 0;
7751
+ }
7752
+
7753
+ /* ---------------------------------------------------------------------------
7754
+ Not Screen Reader Only — reset ds-sr-only when needed (e.g., responsive)
7755
+ --------------------------------------------------------------------------- */
7026
7756
 
7757
+ .ds-not-sr-only {
7758
+ position: static;
7759
+ width: auto;
7760
+ height: auto;
7761
+ padding: 0;
7762
+ margin: 0;
7763
+ overflow: visible;
7764
+ clip: auto;
7765
+ white-space: normal;
7766
+ }
7767
+
7768
+ /* ---------------------------------------------------------------------------
7769
+ Focus Visible Only — invisible by default, shown on keyboard focus
7770
+ --------------------------------------------------------------------------- */
7771
+
7772
+ .ds-focus-visible-only {
7773
+ opacity: 0;
7774
+ pointer-events: none;
7775
+ }
7776
+
7777
+ .ds-focus-visible-only:focus-visible {
7778
+ opacity: 1;
7779
+ pointer-events: auto;
7780
+ }
7781
+
7782
+ /* ---------------------------------------------------------------------------
7783
+ Skip Link — skip to main content, visible only on focus
7784
+ --------------------------------------------------------------------------- */
7785
+
7786
+ .ds-skip-link {
7787
+ position: absolute;
7788
+ width: 1px;
7789
+ height: 1px;
7790
+ padding: 0;
7791
+ margin: -1px;
7792
+ overflow: hidden;
7793
+ clip: rect(0, 0, 0, 0);
7794
+ white-space: nowrap;
7795
+ border-width: 0;
7796
+ }
7797
+
7798
+ .ds-skip-link:focus-visible {
7799
+ position: fixed;
7800
+ inset-block-start: 0;
7801
+ inset-inline-start: 0;
7802
+ z-index: var(--ds-z-tooltip, 200);
7803
+ width: auto;
7804
+ height: auto;
7805
+ padding: var(--ds-space-3) var(--ds-space-5);
7806
+ margin: 0;
7807
+ overflow: visible;
7808
+ clip: auto;
7809
+ white-space: normal;
7810
+ background-color: var(--ds-color-inverted);
7811
+ color: var(--ds-color-on-inverted);
7812
+ font-family: var(--ds-font-sans);
7813
+ font-size: var(--ds-text-sm);
7814
+ font-weight: var(--ds-weight-medium);
7815
+ border-radius: 0 0 var(--ds-radius-lg) 0;
7816
+ box-shadow: var(--ds-shadow-lg);
7817
+ text-decoration: none;
7818
+ outline: none;
7819
+ }
7820
+
7821
+ /* ---------------------------------------------------------------------------
7822
+ Reduce Motion — force reduced motion on a specific element
7823
+ --------------------------------------------------------------------------- */
7824
+
7825
+ .ds-reduce-motion,
7826
+ .ds-reduce-motion *,
7827
+ .ds-reduce-motion *::before,
7828
+ .ds-reduce-motion *::after {
7829
+ animation-duration: 0.01ms !important;
7830
+ animation-iteration-count: 1 !important;
7831
+ transition-duration: 0.01ms !important;
7832
+ scroll-behavior: auto !important;
7833
+ }
7834
+
7835
+
7836
+ }