@capillaryjs/capillary-ui 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/CHANGELOG.md +109 -2
  2. package/README.md +177 -35
  3. package/colors/README.md +53 -3
  4. package/colors/gray/colors.css +4 -2
  5. package/colors/green/colors.css +4 -2
  6. package/colors/iceblue/colors.css +4 -2
  7. package/colors/ocean/colors.css +4 -2
  8. package/colors/orange/colors.css +4 -2
  9. package/colors/purple/colors.css +4 -2
  10. package/colors/red/colors.css +7 -3
  11. package/colors/yellow/colors.css +8 -4
  12. package/dist/Components/app/app.d.ts +3 -3
  13. package/dist/Components/app/app.d.ts.map +1 -1
  14. package/dist/Components/component.d.ts +13 -2
  15. package/dist/Components/component.d.ts.map +1 -1
  16. package/dist/Components/data/descriptionList.d.ts.map +1 -1
  17. package/dist/Components/data/listview/listview.d.ts.map +1 -1
  18. package/dist/Components/data/table/DataTable.d.ts +8 -0
  19. package/dist/Components/data/table/DataTable.d.ts.map +1 -1
  20. package/dist/Components/data/table/FilterPanel.d.ts.map +1 -1
  21. package/dist/Components/data/table/TableHeader.d.ts +2 -0
  22. package/dist/Components/data/table/TableHeader.d.ts.map +1 -1
  23. package/dist/Components/data/table/TableHeaderCell.d.ts +17 -0
  24. package/dist/Components/data/table/TableHeaderCell.d.ts.map +1 -1
  25. package/dist/Components/data/table/tableDataSource.d.ts +6 -0
  26. package/dist/Components/data/table/tableDataSource.d.ts.map +1 -1
  27. package/dist/Components/data/treeview/treeview.d.ts.map +1 -1
  28. package/dist/Components/layout/groupBox.d.ts.map +1 -1
  29. package/dist/Components/layout/header.d.ts.map +1 -1
  30. package/dist/Components/layout/layout.d.ts +2 -2
  31. package/dist/Components/layout/layout.d.ts.map +1 -1
  32. package/dist/Components/layout/layoutTraits.d.ts +6 -0
  33. package/dist/Components/layout/layoutTraits.d.ts.map +1 -1
  34. package/dist/Components/layout/optionGroup.d.ts.map +1 -1
  35. package/dist/Components/layout/optionsBox.d.ts +2 -1
  36. package/dist/Components/layout/optionsBox.d.ts.map +1 -1
  37. package/dist/Components/layout/splitView.d.ts +2 -0
  38. package/dist/Components/layout/splitView.d.ts.map +1 -1
  39. package/dist/Components/lineinputs/CheckableControl.d.ts +2 -2
  40. package/dist/Components/lineinputs/CheckableControl.d.ts.map +1 -1
  41. package/dist/Components/lineinputs/LabeledInputControl.d.ts +2 -2
  42. package/dist/Components/lineinputs/LabeledInputControl.d.ts.map +1 -1
  43. package/dist/Components/lineinputs/LineControl.d.ts +7 -0
  44. package/dist/Components/lineinputs/LineControl.d.ts.map +1 -0
  45. package/dist/Components/lineinputs/SelectControl.d.ts.map +1 -1
  46. package/dist/Components/lineinputs/checkbox/Checkbox.d.ts +9 -3
  47. package/dist/Components/lineinputs/checkbox/Checkbox.d.ts.map +1 -1
  48. package/dist/Components/lineinputs/checkbox/QuadCheckbox.d.ts +1 -0
  49. package/dist/Components/lineinputs/checkbox/QuadCheckbox.d.ts.map +1 -1
  50. package/dist/Components/lineinputs/checkbox/TriCheckbox.d.ts +1 -0
  51. package/dist/Components/lineinputs/checkbox/TriCheckbox.d.ts.map +1 -1
  52. package/dist/Components/lineinputs/datetime/TemporalInput.d.ts.map +1 -1
  53. package/dist/Components/lineinputs/dropdown.d.ts +4 -2
  54. package/dist/Components/lineinputs/dropdown.d.ts.map +1 -1
  55. package/dist/Components/lineinputs/radio.d.ts +9 -4
  56. package/dist/Components/lineinputs/radio.d.ts.map +1 -1
  57. package/dist/Components/lineinputs/requiredPresentation.d.ts +21 -0
  58. package/dist/Components/lineinputs/requiredPresentation.d.ts.map +1 -0
  59. package/dist/Components/lineinputs/textbox.d.ts.map +1 -1
  60. package/dist/Components/lineinputs/toggle.d.ts +4 -2
  61. package/dist/Components/lineinputs/toggle.d.ts.map +1 -1
  62. package/dist/Components/menu/button.d.ts +2 -2
  63. package/dist/Components/menu/button.d.ts.map +1 -1
  64. package/dist/Components/status/progressBar.d.ts +2 -2
  65. package/dist/Components/status/progressBar.d.ts.map +1 -1
  66. package/dist/Components/status/statusPresentation.d.ts.map +1 -1
  67. package/dist/Components/theme/stylesheetPicker.d.ts +2 -1
  68. package/dist/Components/theme/stylesheetPicker.d.ts.map +1 -1
  69. package/dist/index.d.ts +1 -1
  70. package/dist/index.d.ts.map +1 -1
  71. package/dist/index.js +2697 -2079
  72. package/dist/index.js.map +1 -1
  73. package/dist/jsx-dev-runtime.js +1 -1
  74. package/dist/{jsx-runtime-BD_q3rPg.js → jsx-runtime-Ba-uafjl.js} +595 -475
  75. package/dist/jsx-runtime-Ba-uafjl.js.map +1 -0
  76. package/dist/jsx-runtime.js +1 -1
  77. package/dist/localization.d.ts +1 -1
  78. package/dist/localization.d.ts.map +1 -1
  79. package/dist/routing/RouteOutlet.d.ts.map +1 -1
  80. package/dist/styling/theme.d.ts +1 -1
  81. package/dist/styling/theme.d.ts.map +1 -1
  82. package/docs/application-composition-guide.md +22 -5
  83. package/package.json +3 -3
  84. package/styles/structural.css +704 -158
  85. package/themes/README.md +9 -2
  86. package/themes/base.css +114 -18
  87. package/themes/capillary/theme.css +300 -0
  88. package/themes/shiny/theme.css +33 -15
  89. package/themes/soft/theme.css +37 -0
  90. package/themes/white/theme.css +52 -0
  91. package/dist/jsx-runtime-BD_q3rPg.js.map +0 -1
  92. package/themes/java/theme.css +0 -21
@@ -30,6 +30,7 @@
30
30
  align-items: stretch;
31
31
  min-inline-size: 0;
32
32
  min-block-size: 0;
33
+ gap: calc(var(--_cap-island-flow, 0) * var(--island-gap, 0px));
33
34
  }
34
35
 
35
36
  .cap-layout-horizontal {
@@ -51,11 +52,55 @@
51
52
  }
52
53
 
53
54
  .cap-scroll {
55
+ /* Move the clip into the surrounding gutter without moving the
56
+ * content. The inherited allowance is owned by the parent layout,
57
+ * so local gaps and nested scrollports do not add extra spacing. */
58
+ --_cap-scroll-gutter: calc(var(--_cap-island-flow, 0) * var(--_cap-island-gutter, 0px));
59
+ margin: calc(-1 * var(--_cap-scroll-gutter));
60
+ padding: var(--_cap-scroll-gutter);
54
61
  overflow: auto;
55
62
  min-inline-size: 0;
56
63
  min-block-size: 0;
57
64
  }
58
65
 
66
+ /* The mode crosses wrappers; each layout resolves its own public gap.
67
+ * Only the first enabled scope contributes a perimeter inset. */
68
+ .cap-island-layout {
69
+ --_cap-island-flow: 1;
70
+ --_cap-island-margin: 0px;
71
+ --_cap-island-separator-background: transparent;
72
+ box-sizing: border-box;
73
+ padding: var(--_cap-island-outer-inset, var(--island-inset, 0px));
74
+ gap: calc(var(--_cap-island-flow, 0) * var(--island-gap, 0px));
75
+ }
76
+
77
+ .cap-island-layout > * {
78
+ --_cap-island-outer-inset: 0px;
79
+ }
80
+
81
+ .cap-layout-horizontal > *,
82
+ .cap-layout-vertical > *,
83
+ .cap-island-layout > * {
84
+ --_cap-island-gutter: calc(var(--_cap-island-flow, 0) * var(--island-gap, 0px) / 2);
85
+ }
86
+
87
+ .cap-island-layout.cap-scroll {
88
+ padding: calc(var(--_cap-island-outer-inset, var(--island-inset, 0px))
89
+ + var(--_cap-scroll-gutter));
90
+ }
91
+
92
+ .cap-island-layout-off {
93
+ --_cap-island-flow: 0;
94
+ --_cap-island-margin: initial;
95
+ --_cap-island-separator-background: initial;
96
+ }
97
+
98
+ .cap-island-layout-off > *,
99
+ .island > * {
100
+ --_cap-island-outer-inset: initial;
101
+ --_cap-island-gutter: 0px;
102
+ }
103
+
59
104
  .colored {
60
105
  --colored-base-bg:
61
106
  linear-gradient(
@@ -73,10 +118,12 @@
73
118
 
74
119
  .app-footer.island,
75
120
  .island {
121
+ --_cap-island-flow: 0;
122
+ --_cap-island-separator-background: initial;
76
123
  box-sizing: border-box;
77
124
  min-width: 0;
78
125
  min-height: 0;
79
- margin: var(--island-margin);
126
+ margin: var(--_cap-island-margin, var(--island-margin));
80
127
  padding: var(--island-padding);
81
128
  background: var(--island-background);
82
129
  border: var(--island-border);
@@ -86,13 +133,13 @@
86
133
 
87
134
  .cap-fill-horizontal.island,
88
135
  .cap-fill-horizontal .island {
89
- max-width: calc(100% - (2 * var(--island-margin)));
136
+ max-width: calc(100% - (2 * var(--_cap-island-margin, var(--island-margin))));
90
137
  overflow-x: auto;
91
138
  }
92
139
 
93
140
  .cap-fill-vertical.island,
94
141
  .cap-fill-vertical .island {
95
- max-height: calc(100% - (2 * var(--island-margin)));
142
+ max-height: calc(100% - (2 * var(--_cap-island-margin, var(--island-margin))));
96
143
  overflow-y: auto;
97
144
  }
98
145
 
@@ -144,17 +191,40 @@ cap-breadcrumb {
144
191
  font-weight: var(--breadcrumb-current-font-weight, 600);
145
192
  }
146
193
 
194
+ cap-button,
195
+ cap-checkbox,
196
+ cap-dropdown,
197
+ cap-datepicker,
198
+ cap-datetimepicker,
199
+ cap-progressbar,
200
+ cap-quadcheckbox,
201
+ cap-radiobutton,
202
+ cap-textbox,
203
+ cap-timepicker,
204
+ cap-toggle,
205
+ cap-tricheckbox {
206
+ --_cap-control-row-min: var(--_cap-control-compact-min,
207
+ max(var(--control-min-height, 2em), var(--control-row-min-height, 0px)));
208
+ min-height: calc(var(--_cap-control-row-min)
209
+ + 2 * var(--control-row-padding-block, .25em));
210
+ padding-block: var(--control-row-padding-block, .25em);
211
+ box-sizing: border-box;
212
+ font-family: inherit;
213
+ font-size: var(--ui-font-size);
214
+ line-height: 1.2;
215
+ }
216
+
147
217
  cap-button > button {
148
218
  display: inline-flex;
149
219
  align-items: center;
150
220
  justify-content: center;
151
221
  min-height: var(--control-min-height, 2em);
152
222
  margin: 0;
153
- padding: 0 5px;
223
+ padding: var(--ui-control-padding);
154
224
  color: var(--button-color);
155
225
  background: var(--button-background);
156
226
  border: var(--button-border);
157
- border-radius: var(--radius-md);
227
+ border-radius: var(--ui-border-radius);
158
228
  box-shadow: var(--button-shadow);
159
229
  box-sizing: border-box;
160
230
  cursor: default;
@@ -169,9 +239,6 @@ cap-button > button {
169
239
  flex-flow: row wrap;
170
240
  align-items: center;
171
241
  align-content: center;
172
- font-family: inherit;
173
- font-size: var(--ui-font-size);
174
- line-height: 1.2;
175
242
  }
176
243
 
177
244
  cap-button > button:hover:not(:disabled, [aria-disabled="true"]) {
@@ -190,8 +257,8 @@ cap-button > button {
190
257
  box-shadow: var(--focus-ring);
191
258
  }
192
259
 
193
- cap-button > button:disabled,
194
- cap-button > button[aria-disabled="true"] {
260
+ cap-button > button:disabled:not([aria-busy="true"]),
261
+ cap-button > button[aria-disabled="true"]:not([aria-busy="true"]) {
195
262
  color: var(--input-color-disabled);
196
263
  background: var(--button-background-disabled);
197
264
  border-color: var(--button-border-disabled);
@@ -200,14 +267,17 @@ cap-button > button {
200
267
  }
201
268
 
202
269
  cap-button > button[aria-busy="true"]:not([aria-invalid="true"]) {
203
- background: var(--working-background-image), var(--button-background-disabled);
270
+ /* Busy is unavailable for activation, but remains a normal button
271
+ * surface with the loading texture layered on top. */
272
+ background: var(--working-background-image), var(--button-background);
204
273
  background-repeat: repeat, no-repeat;
205
274
  background-size: 2rem 2rem, 100% 100%;
206
275
  animation: cap-working-progress .55s linear infinite;
207
276
  }
208
277
 
209
278
  cap-button > button[aria-invalid="true"] {
210
- border-color: var(--error-color);
279
+ border-color: var(--error-control-border);
280
+ box-shadow: var(--error-control-shadow);
211
281
  }
212
282
 
213
283
  @media (prefers-reduced-motion: reduce) {
@@ -226,8 +296,8 @@ cap-button > button {
226
296
  cap-error {
227
297
  position: absolute;
228
298
  z-index: 1200;
229
- inset-block-start: -.35em;
230
- inset-inline-end: -.35em;
299
+ inset-block-start: -.5rem;
300
+ inset-inline-end: -.5rem;
231
301
  display: block;
232
302
  width: 1.25em;
233
303
  height: 1.25em;
@@ -241,18 +311,20 @@ cap-error {
241
311
 
242
312
  cap-error > cap-erroricon {
243
313
  position: absolute;
244
- inset: 0;
245
- display: grid;
246
- width: 1.25em;
247
- height: 1.25em;
314
+ display: flex;
315
+ width: 1rem;
316
+ height: 1rem;
317
+ font-size: .9rem;
248
318
  color: var(--error-contrast);
249
319
  background: var(--error-color);
250
- border: 1px solid var(--error-color);
320
+ border: var(--error-icon-border);
251
321
  border-radius: 50%;
322
+ box-shadow: var(--error-icon-shadow);
252
323
  box-sizing: border-box;
253
- font-weight: 700;
254
- line-height: 1;
255
- place-items: center;
324
+ font-weight: bold;
325
+ justify-content: center;
326
+ align-items: center;
327
+
256
328
  }
257
329
 
258
330
  cap-error > cap-erroricon::before {
@@ -271,8 +343,8 @@ cap-error {
271
343
  padding: var(--space-xs) var(--space-sm);
272
344
  color: var(--ui-color);
273
345
  background: var(--error-bg-neutral, var(--application-background));
274
- border: 1px solid var(--error-color);
275
- border-radius: var(--radius-md);
346
+ border: 1px solid var(--error-control-border);
347
+ border-radius: var(--ui-border-radius);
276
348
  box-shadow: var(--ui-shadow);
277
349
  opacity: 0;
278
350
  overflow-wrap: anywhere;
@@ -319,9 +391,14 @@ cap-tricheckbox {
319
391
  flex-flow: row wrap;
320
392
  align-items: center;
321
393
  align-content: center;
322
- font-family: inherit;
323
- font-size: var(--ui-font-size);
324
- line-height: 1.2;
394
+ --_cap-checkable-label-color: var(--ui-text-color);
395
+ --_cap-checkable-cursor: pointer;
396
+ --_cap-checkable-box-background: var(--checkbox-box-background,
397
+ var(--ui-input-bg, transparent));
398
+ --_cap-checkable-box-border: var(--checkbox-box-border,
399
+ var(--cbx-o-border, 1px solid currentColor));
400
+ --_cap-checkable-box-shadow: var(--checkbox-box-shadow);
401
+ --_cap-checkable-box-filter: none;
325
402
  }
326
403
 
327
404
  cap-checkbox > label,
@@ -331,14 +408,14 @@ cap-tricheckbox {
331
408
  display: flex;
332
409
  flex-flow: row nowrap;
333
410
  position: relative;
334
- min-height: 1.2em;
411
+ min-height: var(--_cap-control-row-min);
335
412
  margin: 0;
336
- color: var(--ui-text-color);
413
+ color: var(--_cap-checkable-label-color);
337
414
  border-radius: var(--ui-border-radius);
338
415
  box-sizing: border-box;
339
416
  align-items: center;
340
417
  gap: .3em;
341
- cursor: pointer;
418
+ cursor: var(--_cap-checkable-cursor);
342
419
  user-select: none;
343
420
  }
344
421
 
@@ -350,6 +427,18 @@ cap-tricheckbox {
350
427
  cursor: not-allowed;
351
428
  }
352
429
 
430
+ cap-checkbox > label:has(> input[aria-readonly="true"]:not(:disabled)),
431
+ cap-quadcheckbox > label:has(> input[aria-readonly="true"]:not(:disabled)),
432
+ cap-radiobutton > label:has(> input[aria-readonly="true"]:not(:disabled)),
433
+ cap-tricheckbox > label:has(> input[aria-readonly="true"]:not(:disabled)) {
434
+ --_cap-checkable-label-color: var(--checkable-label-color-readonly);
435
+ --_cap-checkable-cursor: default;
436
+ --_cap-checkable-box-background: var(--checkbox-box-background-readonly);
437
+ --_cap-checkable-box-border: var(--checkbox-box-border-readonly);
438
+ --_cap-checkable-box-shadow: var(--checkbox-box-shadow-readonly);
439
+ --_cap-checkable-box-filter: saturate(.78);
440
+ }
441
+
353
442
  cap-checkbox > label > input,
354
443
  cap-quadcheckbox > label > input,
355
444
  cap-radiobutton > label > input,
@@ -372,22 +461,25 @@ cap-tricheckbox {
372
461
  cap-radiobutton > label > input + cap-checkshell,
373
462
  cap-tricheckbox > label > input + cap-checkshell {
374
463
  position: relative;
375
- display: grid;
376
- width: 1em;
377
- height: 1em;
378
- flex: 0 0 1em;
464
+ display: flex;
465
+ align-items: center;
466
+ justify-content: center;
467
+ width: var(--checkbox-box-size, 1em);
468
+ height: var(--checkbox-box-size, 1em);
469
+ flex: 0 0 var(--checkbox-box-size, 1em);
379
470
  box-sizing: border-box;
380
471
  text-align: center;
381
472
  line-height: 1;
382
473
  color: var(--input-color, var(--ui-text-color, currentColor));
383
- background: var(--checkbox-box-background, var(--ui-input-bg, transparent));
384
- border: var(--checkbox-box-border, var(--cbx-o-border, 1px solid currentColor));
385
- border-radius: var(--cbx-border-radius, var(--radius-sm, 0.2rem));
386
- box-shadow: var(--checkbox-box-shadow);
474
+ background: var(--_cap-checkable-box-background);
475
+ border: var(--_cap-checkable-box-border);
476
+ border-radius: var(--checkbox-box-radius,
477
+ var(--cbx-border-radius, var(--radius-sm, 0.2rem)));
478
+ box-shadow: var(--_cap-checkable-box-shadow);
479
+ filter: var(--_cap-checkable-box-filter);
387
480
  font-family: inherit;
388
481
  font-size: 1em;
389
482
  user-select: none;
390
- place-items: center;
391
483
  }
392
484
 
393
485
  cap-checkbox > label > input:checked + cap-checkshell,
@@ -397,9 +489,58 @@ cap-tricheckbox {
397
489
  color: var(--checkbox-symbol-color, var(--selection-color, currentColor));
398
490
  background: var(--checkbox-box-background-checked,
399
491
  var(--selection-background, var(--ui-accent-color, Highlight)));
492
+ border: var(--checkbox-box-border-checked, var(--checkbox-box-border,
493
+ var(--cbx-o-border, 1px solid currentColor)));
400
494
  box-shadow: var(--checkbox-box-shadow-checked);
401
495
  }
402
496
 
497
+
498
+
499
+ cap-checkbox > label:has(> input:required:invalid:not(:disabled):not([aria-invalid="true"]))::before,
500
+ cap-quadcheckbox > label:has(> input:required:invalid:not(:disabled):not([aria-invalid="true"]))::before,
501
+ cap-radiobutton > label:has(> input:required:invalid:not(:disabled):not([aria-invalid="true"]))::before,
502
+ cap-tricheckbox > label:has(> input:required:invalid:not(:disabled):not([aria-invalid="true"]))::before {
503
+ content: "";
504
+ position: absolute;
505
+ z-index: 0;
506
+ inset-block: -4px;
507
+ inset-inline-start: -4px;
508
+ inset-inline-end: calc(-4px - 1em);
509
+ border: 1px dashed var(--required-color);
510
+ border-radius: inherit;
511
+ pointer-events: none;
512
+ }
513
+
514
+
515
+ cap-checkbox > label:has(> input:required:invalid:not(:disabled):not([aria-invalid="true"]))::after,
516
+ cap-quadcheckbox > label:has(> input:required:invalid:not(:disabled):not([aria-invalid="true"]))::after,
517
+ cap-radiobutton > label:has(> input:required:invalid:not(:disabled):not([aria-invalid="true"]))::after,
518
+ cap-tricheckbox > label:has(> input:required:invalid:not(:disabled):not([aria-invalid="true"]))::after {
519
+ content: "✲";
520
+ position: absolute;
521
+ z-index: 1;
522
+ inset-block-start: -.5em;
523
+ inset-inline-end: -1em;
524
+ display: flex;
525
+ inline-size: 1rem;
526
+ block-size: 1rem;
527
+ align-items: center;
528
+ justify-content: center;
529
+ color: var(--required-indicator-color);
530
+ background: var(--required-indicator-background);
531
+ font-size: .75rem;
532
+ font-weight: 700;
533
+ line-height: 1;
534
+ pointer-events: none;
535
+ }
536
+
537
+ cap-checkbox > label:has(> input[aria-invalid="true"]),
538
+ cap-quadcheckbox > label:has(> input[aria-invalid="true"]),
539
+ cap-radiobutton > label:has(> input[aria-invalid="true"]),
540
+ cap-tricheckbox > label:has(> input[aria-invalid="true"]) {
541
+ box-shadow: var(--error-control-shadow);
542
+ }
543
+
403
544
  cap-checkbox > label > input:focus-visible + cap-checkshell,
404
545
  cap-quadcheckbox > label > input:focus-visible + cap-checkshell,
405
546
  cap-radiobutton > label > input:focus-visible + cap-checkshell,
@@ -427,18 +568,12 @@ cap-tricheckbox {
427
568
  animation: cap-working-progress .55s linear infinite;
428
569
  }
429
570
 
430
- cap-checkbox > label:has(> input[aria-invalid="true"]),
431
- cap-quadcheckbox > label:has(> input[aria-invalid="true"]),
432
- cap-radiobutton > label:has(> input[aria-invalid="true"]),
433
- cap-tricheckbox > label:has(> input[aria-invalid="true"]) {
434
- color: var(--error-color);
435
- }
436
-
437
571
  cap-checkbox > label > input[aria-invalid="true"] + cap-checkshell,
438
572
  cap-quadcheckbox > label > input[aria-invalid="true"] + cap-checkshell,
439
573
  cap-radiobutton > label > input[aria-invalid="true"] + cap-checkshell,
440
574
  cap-tricheckbox > label > input[aria-invalid="true"] + cap-checkshell {
441
- border-color: var(--error-color);
575
+ border-color: var(--error-control-border);
576
+ box-shadow: none;
442
577
  }
443
578
 
444
579
  @media (prefers-reduced-motion: reduce) {
@@ -451,31 +586,15 @@ cap-tricheckbox {
451
586
  }
452
587
 
453
588
  @media (forced-colors: active) {
454
- cap-checkbox > label > input[aria-invalid="true"] + cap-checkshell,
455
- cap-quadcheckbox > label > input[aria-invalid="true"] + cap-checkshell,
456
- cap-radiobutton > label > input[aria-invalid="true"] + cap-checkshell,
457
- cap-tricheckbox > label > input[aria-invalid="true"] + cap-checkshell {
589
+ cap-checkbox > label:has(> input[aria-invalid="true"]),
590
+ cap-quadcheckbox > label:has(> input[aria-invalid="true"]),
591
+ cap-radiobutton > label:has(> input[aria-invalid="true"]),
592
+ cap-tricheckbox > label:has(> input[aria-invalid="true"]) {
458
593
  outline: 2px solid Mark;
459
594
  outline-offset: 1px;
460
595
  }
461
596
  }
462
597
 
463
- cap-checkbox > label > input[value="require"] + cap-checkshell,
464
- cap-quadcheckbox > label > input[value="require"] + cap-checkshell,
465
- cap-tricheckbox > label > input[value="require"] + cap-checkshell {
466
- color: var(--palette-contrast-light);
467
- background: var(--palette-green);
468
- box-shadow: var(--checkbox-box-shadow-checked);
469
- }
470
-
471
- cap-checkbox > label > input[value="deny"] + cap-checkshell,
472
- cap-quadcheckbox > label > input[value="deny"] + cap-checkshell,
473
- cap-tricheckbox > label > input[value="deny"] + cap-checkshell {
474
- color: var(--palette-contrast-light);
475
- background: var(--palette-red);
476
- box-shadow: var(--checkbox-box-shadow-checked);
477
- }
478
-
479
598
  cap-dropdown,
480
599
  cap-datepicker,
481
600
  cap-datetimepicker,
@@ -487,15 +606,40 @@ cap-toggle {
487
606
  position: relative;
488
607
  align-items: center;
489
608
  gap: .5em;
490
- min-height: var(--control-min-height, 2em);
491
609
  color: var(--ui-text-color);
492
- font-family: inherit;
493
- font-size: var(--ui-font-size);
494
- line-height: 1.2;
495
- box-sizing: border-box;
496
610
  user-select: none;
497
611
  }
498
612
 
613
+ /* GroupBox owns the ordinary body layout. Labeled controls fill its
614
+ direct body so their label/control row keeps labels left and native
615
+ input surfaces right; an explicitly nested Layout remains supported
616
+ for non-standard arrangements. */
617
+ cap-groupbox > cap-content > cap-dropdown,
618
+ /* GroupBox owns the ordinary body layout. Labeled controls fill its
619
+ direct body so their label/control row keeps labels left and native
620
+ input surfaces right; an explicitly nested Layout remains supported
621
+ for non-standard arrangements. */
622
+ cap-groupbox > cap-content > cap-datepicker,
623
+ /* GroupBox owns the ordinary body layout. Labeled controls fill its
624
+ direct body so their label/control row keeps labels left and native
625
+ input surfaces right; an explicitly nested Layout remains supported
626
+ for non-standard arrangements. */
627
+ cap-groupbox > cap-content > cap-datetimepicker,
628
+ /* GroupBox owns the ordinary body layout. Labeled controls fill its
629
+ direct body so their label/control row keeps labels left and native
630
+ input surfaces right; an explicitly nested Layout remains supported
631
+ for non-standard arrangements. */
632
+ cap-groupbox > cap-content > cap-textbox,
633
+ /* GroupBox owns the ordinary body layout. Labeled controls fill its
634
+ direct body so their label/control row keeps labels left and native
635
+ input surfaces right; an explicitly nested Layout remains supported
636
+ for non-standard arrangements. */
637
+ cap-groupbox > cap-content > cap-timepicker,
638
+ /* GroupBox owns the ordinary body layout. Labeled controls fill its
639
+ direct body so their label/control row keeps labels left and native
640
+ input surfaces right; an explicitly nested Layout remains supported
641
+ for non-standard arrangements. */
642
+ cap-groupbox > cap-content > cap-toggle,
499
643
  cap-groupbox > cap-content > cap-layout > cap-dropdown,
500
644
  cap-groupbox > cap-content > cap-layout > cap-datepicker,
501
645
  cap-groupbox > cap-content > cap-layout > cap-datetimepicker,
@@ -547,12 +691,12 @@ cap-dropdown {
547
691
  max-width: 100%;
548
692
  min-width: var(--input-min-width, 6rem);
549
693
  margin: 0;
550
- padding: 0 5px;
694
+ padding: var(--ui-control-padding);
551
695
  padding-inline-end: var(--dropdown-padding-inline-end);
552
696
  color: var(--input-color);
553
697
  background: var(--dropdown-select-background);
554
698
  border: var(--dropdown-select-border);
555
- border-radius: var(--radius-md);
699
+ border-radius: var(--ui-border-radius);
556
700
  box-shadow: var(--dropdown-select-shadow);
557
701
  box-sizing: border-box;
558
702
  font: inherit;
@@ -562,6 +706,11 @@ cap-dropdown {
562
706
  white-space: nowrap;
563
707
  }
564
708
 
709
+ cap-dropdown > cap-selectshell > select[aria-readonly="true"]:not(:disabled) {
710
+ color: var(--input-color-readonly);
711
+ cursor: default;
712
+ }
713
+
565
714
  cap-dropdown > cap-selectshell::after {
566
715
  content: var(--dropdown-underlay-content);
567
716
  position: absolute;
@@ -583,9 +732,10 @@ cap-dropdown {
583
732
  z-index: 2;
584
733
  inset-block: 0;
585
734
  inset-inline-end: 0;
586
- display: grid;
735
+ display: flex;
736
+ align-items: center;
737
+ justify-content: center;
587
738
  inline-size: var(--dropdown-trigger-width);
588
- place-items: center;
589
739
  color: var(--dropdown-trigger-color);
590
740
  background: var(--dropdown-trigger-background);
591
741
  border: var(--dropdown-trigger-border);
@@ -597,7 +747,7 @@ cap-dropdown {
597
747
  pointer-events: none;
598
748
  }
599
749
 
600
- cap-dropdown > cap-selectshell:has(> select:hover:not(:disabled))::before {
750
+ cap-dropdown > cap-selectshell:has(> select:hover:not(:disabled):not([aria-readonly="true"]))::before {
601
751
  background: var(--dropdown-trigger-background-hover);
602
752
  box-shadow: var(--dropdown-trigger-shadow-hover);
603
753
  }
@@ -613,6 +763,46 @@ cap-dropdown {
613
763
  border: var(--dropdown-underlay-border-disabled);
614
764
  }
615
765
 
766
+ cap-dropdown > cap-selectshell:has(> select[aria-readonly="true"]:not(:disabled))::before {
767
+ color: var(--dropdown-trigger-color-readonly);
768
+ background: var(--dropdown-trigger-background-readonly);
769
+ border: var(--dropdown-trigger-border-readonly);
770
+ box-shadow: var(--dropdown-trigger-shadow-readonly);
771
+ }
772
+
773
+ cap-dropdown > cap-selectshell:has(> select[aria-readonly="true"]:not(:disabled))::after {
774
+ background: var(--dropdown-underlay-background-readonly);
775
+ border: var(--dropdown-underlay-border-readonly);
776
+ box-shadow: var(--dropdown-underlay-shadow-readonly);
777
+ }
778
+
779
+
780
+
781
+ cap-dropdown > cap-selectshell:has(> select:required:invalid:not(:disabled):not([aria-invalid="true"])) {
782
+ outline: 1px dashed var(--required-color);
783
+ outline-offset: 3px;
784
+ }
785
+
786
+
787
+ cap-dropdown:has(> cap-selectshell > select:required:invalid:not(:disabled):not([aria-invalid="true"]))::after {
788
+ content: "✲";
789
+ position: absolute;
790
+ z-index: 3;
791
+ inset-block-start: max(calc(var(--control-row-padding-block, .25em) + .15em), .3em);
792
+ inset-inline-end: calc(var(--dropdown-trigger-width) + .5em);
793
+ display: flex;
794
+ inline-size: 1rem;
795
+ block-size: 1rem;
796
+ align-items: center;
797
+ justify-content: center;
798
+ color: var(--required-indicator-color);
799
+ background: var(--required-indicator-background);
800
+ font-size: .75rem;
801
+ font-weight: 700;
802
+ line-height: 1;
803
+ pointer-events: none;
804
+ }
805
+
616
806
  cap-dropdown > cap-selectshell > select:focus-visible {
617
807
  outline: 2px solid transparent;
618
808
  outline-offset: 1px;
@@ -633,10 +823,21 @@ cap-dropdown {
633
823
  animation: cap-working-progress .55s linear infinite;
634
824
  }
635
825
 
826
+ cap-dropdown > cap-selectshell:has(> select[aria-readonly="true"][aria-busy="true"]:not([aria-invalid="true"]))::after {
827
+ background: var(--working-background-image), var(--dropdown-underlay-background-readonly);
828
+ background-repeat: repeat, no-repeat;
829
+ background-size: 2rem 2rem, 100% 100%;
830
+ }
831
+
636
832
  cap-dropdown > cap-selectshell:has(> select[aria-invalid="true"])::before,
637
833
  cap-dropdown > cap-selectshell:has(> select[aria-invalid="true"])::after,
638
834
  cap-dropdown > cap-selectshell > select[aria-invalid="true"] {
639
- border-color: var(--error-color);
835
+ border-color: var(--error-control-border);
836
+ }
837
+
838
+ cap-dropdown > cap-selectshell:has(> select[aria-invalid="true"]) {
839
+ border-radius: var(--ui-border-radius);
840
+ box-shadow: var(--error-control-shadow);
640
841
  }
641
842
 
642
843
  @media (prefers-reduced-motion: reduce) {
@@ -682,6 +883,19 @@ cap-datatable {
682
883
  width: 100%;
683
884
  }
684
885
 
886
+ cap-datatable[data-cap-retained-loading]::after {
887
+ content: "";
888
+ position: absolute;
889
+ z-index: 3;
890
+ inset: 0;
891
+ opacity: 0.33;
892
+ animation: cap-working-progress .55s linear infinite;
893
+ background-image: var(--working-background-image);
894
+ background-repeat: repeat;
895
+ background-size: 2rem 2rem;
896
+ pointer-events: none;
897
+ }
898
+
685
899
  cap-datatable thead:has([aria-expanded="true"]) {
686
900
  position: relative;
687
901
  z-index: 1100;
@@ -741,6 +955,16 @@ cap-datatable {
741
955
  cap-datatable:has(> cap-error) {
742
956
  outline: 2px solid Mark;
743
957
  }
958
+
959
+ cap-datatable[data-cap-retained-loading]::after {
960
+ display: none;
961
+ }
962
+ }
963
+
964
+ @media (prefers-reduced-motion: reduce) {
965
+ cap-datatable[data-cap-retained-loading]::after {
966
+ animation: none !important;
967
+ }
744
968
  }
745
969
 
746
970
  cap-placeholder {
@@ -862,11 +1086,13 @@ cap-datatable > table > thead > tr > th[aria-sort] {
862
1086
 
863
1087
  cap-filterpanel {
864
1088
  position: absolute;
865
- background: white;
866
- border: 1px solid #ccc;
867
- padding: 8px;
868
- min-width: 180px;
869
- box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
1089
+ color: var(--filter-panel-color);
1090
+ background: var(--filter-panel-background);
1091
+ border: var(--filter-panel-border);
1092
+ border-radius: var(--filter-panel-radius);
1093
+ padding: var(--filter-panel-padding);
1094
+ min-width: var(--filter-panel-min-width);
1095
+ box-shadow: var(--filter-panel-shadow);
870
1096
  z-index: 1000;
871
1097
  display: flex;
872
1098
  flex-flow: column nowrap;
@@ -926,11 +1152,11 @@ cap-timepicker {
926
1152
  min-width: var(--input-min-width, 6rem);
927
1153
  margin: 0;
928
1154
  margin-left: auto;
929
- padding: 0 5px;
1155
+ padding: var(--ui-control-padding);
930
1156
  color: var(--input-color);
931
1157
  background: var(--input-background);
932
1158
  border: var(--input-border);
933
- border-radius: var(--radius-md);
1159
+ border-radius: var(--ui-border-radius);
934
1160
  box-shadow: var(--input-shadow);
935
1161
  box-sizing: border-box;
936
1162
  font: inherit;
@@ -938,16 +1164,54 @@ cap-timepicker {
938
1164
 
939
1165
  cap-datepicker > input:disabled,
940
1166
  cap-datetimepicker > input:disabled,
941
- cap-timepicker > input:disabled,
942
- cap-datepicker > input[readonly],
943
- cap-datetimepicker > input[readonly],
944
- cap-timepicker > input[readonly] {
1167
+ cap-timepicker > input:disabled {
945
1168
  color: var(--input-color-disabled);
946
1169
  background: var(--input-background-disabled);
947
1170
  border-color: var(--ui-input-border-disabled);
948
1171
  cursor: not-allowed;
949
1172
  }
950
1173
 
1174
+ cap-datepicker > input[readonly]:not(:disabled),
1175
+ cap-datetimepicker > input[readonly]:not(:disabled),
1176
+ cap-timepicker > input[readonly]:not(:disabled) {
1177
+ color: var(--input-color-readonly);
1178
+ background: var(--input-background-readonly);
1179
+ border: var(--input-border-readonly);
1180
+ box-shadow: var(--input-shadow-readonly);
1181
+ cursor: default;
1182
+ }
1183
+
1184
+
1185
+
1186
+ cap-datepicker > input:required:invalid:not(:disabled):not([readonly]):not([aria-invalid="true"]),
1187
+ cap-datetimepicker > input:required:invalid:not(:disabled):not([readonly]):not([aria-invalid="true"]),
1188
+ cap-timepicker > input:required:invalid:not(:disabled):not([readonly]):not([aria-invalid="true"]) {
1189
+ outline: 1px dashed var(--required-color);
1190
+ outline-offset: 3px;
1191
+ }
1192
+
1193
+
1194
+ cap-datepicker:has(> input:required:invalid:not(:disabled):not([readonly]):not([aria-invalid="true"]))::after,
1195
+ cap-datetimepicker:has(> input:required:invalid:not(:disabled):not([readonly]):not([aria-invalid="true"]))::after,
1196
+ cap-timepicker:has(> input:required:invalid:not(:disabled):not([readonly]):not([aria-invalid="true"]))::after {
1197
+ content: "✲";
1198
+ position: absolute;
1199
+ z-index: 3;
1200
+ inset-block-start: max(calc(var(--control-row-padding-block, .25em) + .15em), .3em);
1201
+ inset-inline-end: .35em;
1202
+ display: flex;
1203
+ inline-size: 1rem;
1204
+ block-size: 1rem;
1205
+ align-items: center;
1206
+ justify-content: center;
1207
+ color: var(--required-indicator-color);
1208
+ background: var(--required-indicator-background);
1209
+ font-size: .75rem;
1210
+ font-weight: 700;
1211
+ line-height: 1;
1212
+ pointer-events: none;
1213
+ }
1214
+
951
1215
  cap-datepicker > input:focus-visible,
952
1216
  cap-datetimepicker > input:focus-visible,
953
1217
  cap-timepicker > input:focus-visible {
@@ -973,10 +1237,19 @@ cap-timepicker {
973
1237
  background-size: 2rem 2rem, 100% 100%;
974
1238
  }
975
1239
 
1240
+ cap-datepicker > input[readonly]:not(:disabled)[aria-busy="true"]:not([aria-invalid="true"]),
1241
+ cap-datetimepicker > input[readonly]:not(:disabled)[aria-busy="true"]:not([aria-invalid="true"]),
1242
+ cap-timepicker > input[readonly]:not(:disabled)[aria-busy="true"]:not([aria-invalid="true"]) {
1243
+ background: var(--working-background-image), var(--input-background-readonly);
1244
+ background-repeat: repeat, no-repeat;
1245
+ background-size: 2rem 2rem, 100% 100%;
1246
+ }
1247
+
976
1248
  cap-datepicker > input[aria-invalid="true"],
977
1249
  cap-datetimepicker > input[aria-invalid="true"],
978
1250
  cap-timepicker > input[aria-invalid="true"] {
979
- border-color: var(--error-color);
1251
+ border-color: var(--error-control-border);
1252
+ box-shadow: var(--error-control-shadow);
980
1253
  }
981
1254
 
982
1255
  @media (prefers-reduced-motion: reduce) {
@@ -1002,7 +1275,8 @@ cap-descriptionlist {
1002
1275
  }
1003
1276
 
1004
1277
  cap-descriptionlist > dl {
1005
- display: grid;
1278
+ display: flex;
1279
+ flex-flow: column nowrap;
1006
1280
  margin: 0;
1007
1281
  }
1008
1282
 
@@ -1090,6 +1364,13 @@ cap-app {
1090
1364
  line-height: var(--line-height);
1091
1365
  }
1092
1366
 
1367
+ /* A direct shell header delegates content spacing to its navbar,
1368
+ * toolbar, and branding rows. Keep the inherited island token intact. */
1369
+ cap-app > header.island,
1370
+ cap-app > cap-header.island {
1371
+ padding: 0;
1372
+ }
1373
+
1093
1374
  cap-groupbox,
1094
1375
  cap-optionsbox {
1095
1376
  display: flex;
@@ -1131,22 +1412,18 @@ cap-optionsbox {
1131
1412
 
1132
1413
  cap-groupbox > cap-content,
1133
1414
  cap-optionsbox > cap-content {
1134
- display: block;
1415
+ display: flex;
1416
+ flex-flow: column nowrap;
1417
+ justify-content: flex-start;
1418
+ align-content: flex-start;
1419
+ align-items: flex-start;
1420
+ gap: var(--groupbox-content-gap, .5rem);
1135
1421
  min-width: 0;
1136
1422
  min-height: 0;
1137
1423
  margin-left: var(--cap-groupbox-content-margin, .25em);
1138
1424
  flex: 1 1 auto;
1139
1425
  }
1140
1426
 
1141
- cap-groupbox > cap-content > cap-layout,
1142
- cap-optionsbox > cap-content > cap-layout {
1143
- gap: .5rem;
1144
- justify-content: flex-start;
1145
- align-content: flex-start;
1146
- justify-items: flex-start;
1147
- align-items: flex-start;
1148
- }
1149
-
1150
1427
  /* Presentation contexts: each marker sets the complete context-sensitive
1151
1428
  property set, so the nearest marked ancestor wins through ordinary
1152
1429
  custom-property inheritance. Unmarked containers keep the control
@@ -1220,7 +1497,7 @@ cap-optionsbox {
1220
1497
  grid-column: 2;
1221
1498
  grid-row: 1;
1222
1499
  align-self: center;
1223
- border-block-start: 1px solid var(--ui-border-color);
1500
+ border-block-start: var(--groupbox-section-separator);
1224
1501
  }
1225
1502
 
1226
1503
  cap-groupbox.cap-groupbox-section > cap-header,
@@ -1234,7 +1511,7 @@ cap-optionsbox {
1234
1511
  min-height: 0;
1235
1512
  padding: 0 0.5rem 0 0;
1236
1513
  border-radius: 0;
1237
- color: var(--text-color);
1514
+ color: var(--groupbox-section-header-color);
1238
1515
  background: transparent;
1239
1516
  box-shadow: none;
1240
1517
  writing-mode: horizontal-tb;
@@ -1247,6 +1524,7 @@ cap-optionsbox {
1247
1524
  cap-optionsbox.cap-groupbox-section > cap-content {
1248
1525
  grid-column: 1 / -1;
1249
1526
  grid-row: 2;
1527
+ flex-flow: row nowrap;
1250
1528
  margin-left: 0;
1251
1529
  padding-block: 0.75rem;
1252
1530
  min-width: 0;
@@ -1265,7 +1543,7 @@ cap-optionsbox {
1265
1543
  justify-self: stretch;
1266
1544
  align-self: stretch;
1267
1545
  border-block-start: 0;
1268
- border-inline-end: 1px solid var(--ui-border-color);
1546
+ border-inline-end: var(--groupbox-section-separator);
1269
1547
  }
1270
1548
 
1271
1549
  .cap-layout-horizontal > cap-groupbox.cap-groupbox-section > cap-header,
@@ -1302,7 +1580,7 @@ cap-optionsbox {
1302
1580
  padding: 0;
1303
1581
  margin-block-end: 0.75rem;
1304
1582
  border-radius: 0;
1305
- color: var(--text-color);
1583
+ color: var(--groupbox-column-header-color);
1306
1584
  background: transparent;
1307
1585
  box-shadow: none;
1308
1586
  writing-mode: horizontal-tb;
@@ -1316,6 +1594,34 @@ cap-optionsbox {
1316
1594
  margin-left: 0;
1317
1595
  }
1318
1596
 
1597
+ /* A section's own content body is the ordinary horizontal column row.
1598
+ Preserve the same stretch, edge padding, and separators formerly
1599
+ provided when an application inserted a Layout just for that row. */
1600
+ cap-groupbox.cap-groupbox-section > cap-content > cap-groupbox.cap-groupbox-column,
1601
+ /* A section's own content body is the ordinary horizontal column row.
1602
+ Preserve the same stretch, edge padding, and separators formerly
1603
+ provided when an application inserted a Layout just for that row. */
1604
+ cap-optionsbox.cap-groupbox-section > cap-content > cap-groupbox.cap-groupbox-column {
1605
+ align-self: stretch;
1606
+ }
1607
+
1608
+ cap-groupbox.cap-groupbox-section > cap-content > cap-groupbox.cap-groupbox-column
1609
+ + cap-groupbox.cap-groupbox-column,
1610
+ cap-optionsbox.cap-groupbox-section > cap-content > cap-groupbox.cap-groupbox-column
1611
+ + cap-groupbox.cap-groupbox-column {
1612
+ border-inline-start: var(--groupbox-column-separator);
1613
+ }
1614
+
1615
+ cap-groupbox.cap-groupbox-section > cap-content > cap-groupbox.cap-groupbox-column:first-child,
1616
+ cap-optionsbox.cap-groupbox-section > cap-content > cap-groupbox.cap-groupbox-column:first-child {
1617
+ padding-inline-start: 0;
1618
+ }
1619
+
1620
+ cap-groupbox.cap-groupbox-section > cap-content > cap-groupbox.cap-groupbox-column:last-child,
1621
+ cap-optionsbox.cap-groupbox-section > cap-content > cap-groupbox.cap-groupbox-column:last-child {
1622
+ padding-inline-end: 0;
1623
+ }
1624
+
1319
1625
  .cap-layout-horizontal > cap-groupbox.cap-groupbox-column,
1320
1626
  .cap-layout-horizontal > cap-optionsbox.cap-groupbox-column,
1321
1627
  .cap-layout-vertical > cap-groupbox.cap-groupbox-column,
@@ -1325,7 +1631,7 @@ cap-optionsbox {
1325
1631
 
1326
1632
  .cap-layout-horizontal > cap-groupbox.cap-groupbox-column + cap-groupbox.cap-groupbox-column,
1327
1633
  .cap-layout-horizontal > cap-optionsbox.cap-groupbox-column + cap-optionsbox.cap-groupbox-column {
1328
- border-inline-start: 1px solid var(--ui-border-color);
1634
+ border-inline-start: var(--groupbox-column-separator);
1329
1635
  }
1330
1636
 
1331
1637
  .cap-layout-horizontal > cap-groupbox.cap-groupbox-column:first-child,
@@ -1346,7 +1652,7 @@ cap-optionsbox {
1346
1652
 
1347
1653
  .cap-layout-vertical > cap-groupbox.cap-groupbox-column + cap-groupbox.cap-groupbox-column,
1348
1654
  .cap-layout-vertical > cap-optionsbox.cap-groupbox-column + cap-optionsbox.cap-groupbox-column {
1349
- border-block-start: 1px solid var(--ui-border-color);
1655
+ border-block-start: var(--groupbox-column-separator);
1350
1656
  }
1351
1657
 
1352
1658
  .cap-layout-vertical > cap-groupbox.cap-groupbox-column:first-child,
@@ -1363,6 +1669,7 @@ cap-header {
1363
1669
  display: block;
1364
1670
  color: var(--section-header-color);
1365
1671
  font-size: var(--section-header-font-size);
1672
+ font-weight: var(--section-header-font-weight);
1366
1673
  border-radius: var(--ui-border-radius) var(--ui-border-radius) 0 0;
1367
1674
  padding: .25em;
1368
1675
  background: var(--section-header-background);
@@ -1440,6 +1747,19 @@ cap-listview {
1440
1747
  list-style: none;
1441
1748
  }
1442
1749
 
1750
+ cap-listview[data-cap-retained-loading]::after {
1751
+ content: "";
1752
+ position: absolute;
1753
+ z-index: 1;
1754
+ inset: 0;
1755
+ opacity: 0.33;
1756
+ animation: cap-working-progress .55s linear infinite;
1757
+ background-image: var(--working-background-image);
1758
+ background-repeat: repeat;
1759
+ background-size: 2rem 2rem;
1760
+ pointer-events: none;
1761
+ }
1762
+
1443
1763
  cap-listview > [role="listbox"] > [role="option"],
1444
1764
  cap-listview > ul[aria-hidden="true"] > li {
1445
1765
  display: flex;
@@ -1481,6 +1801,16 @@ cap-listview {
1481
1801
  outline: 2px solid Mark;
1482
1802
  outline-offset: -2px;
1483
1803
  }
1804
+
1805
+ cap-listview[data-cap-retained-loading]::after {
1806
+ display: none;
1807
+ }
1808
+ }
1809
+
1810
+ @media (prefers-reduced-motion: reduce) {
1811
+ cap-listview[data-cap-retained-loading]::after {
1812
+ animation: none !important;
1813
+ }
1484
1814
  }
1485
1815
 
1486
1816
  cap-navigationbar {
@@ -1606,8 +1936,9 @@ cap-optiongroup {
1606
1936
  }
1607
1937
 
1608
1938
  cap-optiongroup > fieldset[aria-invalid="true"] {
1609
- border: 1px solid var(--error-color);
1610
- border-radius: var(--radius-md);
1939
+ border: 1px solid var(--error-control-border);
1940
+ border-radius: var(--ui-border-radius);
1941
+ box-shadow: var(--error-control-shadow);
1611
1942
  }
1612
1943
 
1613
1944
  @media (prefers-reduced-motion: reduce) {
@@ -1623,15 +1954,20 @@ cap-optiongroup {
1623
1954
  }
1624
1955
  }
1625
1956
 
1626
- cap-optionsbox > cap-content {
1957
+ cap-optionsbox {
1958
+ --_cap-control-compact-min: 0px;
1959
+ --control-row-padding-block: 0px;
1960
+ }
1961
+
1962
+ cap-optionsbox > cap-content {
1627
1963
  display: flex;
1628
1964
  flex-direction: column;
1629
1965
  align-self: stretch;
1630
1966
  flex: 1 1 0;
1631
- gap: 1rem;
1967
+ gap: 2px;
1632
1968
  }
1633
1969
 
1634
- cap-optionsbox > cap-content * > fieldset > legend {
1970
+ cap-optionsbox > cap-content cap-optiongroup > fieldset > legend {
1635
1971
  display: flex;
1636
1972
  justify-content: space-between;
1637
1973
  align-items: center;
@@ -1640,23 +1976,30 @@ cap-optionsbox > cap-content {
1640
1976
  color: var(--palette-neutral-950);
1641
1977
  gap: 0.5rem;
1642
1978
  width: 100%;
1643
- padding: 0 0 0.25rem;
1644
- margin-bottom: 0.25rem;
1979
+ padding: 0 0 1px;
1980
+ margin-bottom: 1px;
1645
1981
  border-bottom: 1px solid var(--ui-border-color);
1646
1982
  user-select: none;
1647
1983
  }
1648
1984
 
1649
- cap-optionsbox > cap-content * > fieldset {
1985
+ cap-optionsbox > cap-content cap-optiongroup > fieldset {
1650
1986
  display: flex;
1651
- flex-flow: column;
1987
+ flex-flow: column nowrap;
1652
1988
  justify-content: stretch;
1653
1989
  justify-items: stretch;
1654
1990
  align-items: stretch;
1655
1991
  align-content: stretch;
1656
1992
  box-sizing: border-box;
1657
1993
  width: 100%;
1658
- gap: .33rem;
1659
- padding: .25em 0 .5em 0;
1994
+ gap: 2px;
1995
+ padding: 1px 0 2px;
1996
+ }
1997
+
1998
+ /* OptionsBox is deliberately a dense, vertical filter surface. Keep
1999
+ RadioGroup in the same rhythm as checkbox options, regardless of
2000
+ theme-level RadioGroup spacing. */
2001
+ cap-optionsbox > cap-content cap-radiogroup > fieldset {
2002
+ gap: 2px;
1660
2003
  }
1661
2004
 
1662
2005
  cap-panel {
@@ -1690,7 +2033,10 @@ cap-panel {
1690
2033
  }
1691
2034
 
1692
2035
  cap-progressbar {
1693
- display: block;
2036
+ display: flex;
2037
+ align-items: center;
2038
+ width: 100%;
2039
+ min-width: 0;
1694
2040
  }
1695
2041
 
1696
2042
  cap-progressbar > label,
@@ -1756,17 +2102,17 @@ cap-progressbar {
1756
2102
  white-space: nowrap;
1757
2103
  }
1758
2104
 
1759
- cap-progressbar:has(> progress:indeterminate) > cap-content > cap-progress {
2105
+ cap-progressbar:has(> progress:indeterminate[aria-busy="true"]) > cap-content > cap-progress {
1760
2106
  display: none;
1761
2107
  }
1762
2108
 
1763
- cap-progressbar:has(> progress:indeterminate) > cap-content > cap-label {
2109
+ cap-progressbar:has(> progress:indeterminate[aria-busy="true"]) > cap-content > cap-label {
1764
2110
  z-index: 2;
1765
2111
  }
1766
2112
 
1767
- cap-progressbar:has(> progress:indeterminate) > cap-content::after {
2113
+ cap-progressbar:has(> progress[aria-busy="true"]) > cap-content::after {
1768
2114
  position: absolute;
1769
- z-index: 1;
2115
+ z-index: 2;
1770
2116
  inset: 1px;
1771
2117
  content: "";
1772
2118
  border-radius: inherit;
@@ -1775,10 +2121,15 @@ cap-progressbar {
1775
2121
  background-size: 2rem 2rem;
1776
2122
  animation: cap-working-progress .55s linear infinite;
1777
2123
  opacity: .5;
2124
+ pointer-events: none;
2125
+ }
2126
+
2127
+ cap-progressbar:has(> progress[aria-busy="true"]) > cap-content > cap-label {
2128
+ z-index: 3;
1778
2129
  }
1779
2130
 
1780
2131
  @media (prefers-reduced-motion: reduce) {
1781
- cap-progressbar:has(> progress:indeterminate) > cap-content::after {
2132
+ cap-progressbar:has(> progress[aria-busy="true"]) > cap-content::after {
1782
2133
  animation: none !important;
1783
2134
  }
1784
2135
  }
@@ -1801,10 +2152,37 @@ cap-progressbar {
1801
2152
  }
1802
2153
  }
1803
2154
 
2155
+ cap-quadcheckbox > label > input[value="require"] + cap-checkshell,
2156
+ cap-tricheckbox > label > input[value="require"] + cap-checkshell {
2157
+ color: var(--checkbox-positive-color);
2158
+ background: var(--checkbox-positive-background);
2159
+ background-color: var(--palette-status-positive);
2160
+ border: var(--checkbox-positive-border);
2161
+ box-shadow: var(--checkbox-positive-shadow);
2162
+ }
2163
+
2164
+ cap-quadcheckbox > label > input[value="deny"] + cap-checkshell,
2165
+ cap-tricheckbox > label > input[value="deny"] + cap-checkshell {
2166
+ color: var(--checkbox-negative-color);
2167
+ background: var(--checkbox-negative-background);
2168
+ background-color: var(--palette-status-negative);
2169
+ border: var(--checkbox-negative-border);
2170
+ box-shadow: var(--checkbox-negative-shadow);
2171
+ }
2172
+
2173
+ cap-quadcheckbox > label > input[value="prefer"] + cap-checkshell,
2174
+ cap-tricheckbox > label > input[value="prefer"] + cap-checkshell {
2175
+ color: var(--checkbox-neutral-color);
2176
+ background: var(--checkbox-neutral-background);
2177
+ background-color: var(--palette-status-neutral);
2178
+ border: var(--checkbox-neutral-border);
2179
+ box-shadow: var(--checkbox-neutral-shadow);
2180
+ }
2181
+
1804
2182
  cap-radiogroup > fieldset {
1805
2183
  display: flex;
1806
2184
  flex-flow: column wrap;
1807
- gap: 0;
2185
+ gap: var(--radio-group-gap, 0px);
1808
2186
  margin: 0;
1809
2187
  padding: 0;
1810
2188
  min-inline-size: 0;
@@ -1824,11 +2202,19 @@ cap-radiogroup > fieldset {
1824
2202
  }
1825
2203
 
1826
2204
  cap-radiogroup > fieldset[aria-invalid="true"] cap-checkshell {
1827
- border-color: var(--error-color);
2205
+ border-color: var(--error-control-border);
2206
+ box-shadow: var(--error-control-shadow);
1828
2207
  }
1829
2208
 
1830
- cap-radiogroup > fieldset[aria-invalid="true"] cap-radiobutton > label {
1831
- color: var(--error-color);
2209
+ /* RadioGroup owns changes for its child buttons, so the readonly
2210
+ presentation is applied here rather than to each child input. */
2211
+ cap-radiogroup > fieldset[aria-readonly="true"] > cap-radiobutton {
2212
+ --_cap-checkable-label-color: var(--checkable-label-color-readonly);
2213
+ --_cap-checkable-cursor: default;
2214
+ --_cap-checkable-box-background: var(--checkbox-box-background-readonly);
2215
+ --_cap-checkable-box-border: var(--checkbox-box-border-readonly);
2216
+ --_cap-checkable-box-shadow: var(--checkbox-box-shadow-readonly);
2217
+ --_cap-checkable-box-filter: saturate(.78);
1832
2218
  }
1833
2219
 
1834
2220
  @media (forced-colors: active) {
@@ -1840,14 +2226,26 @@ cap-radiogroup > fieldset {
1840
2226
 
1841
2227
  cap-radiobutton > label > input[type="radio"] + cap-checkshell {
1842
2228
  border-radius: 50%;
2229
+ height: var(--checkbox-box-size, 1em);
2230
+ }
2231
+
2232
+ /* Radios may keep their neutral ring when selected and paint only the
2233
+ center dot; the generic checked checkbox treatment is the fallback. */
2234
+ cap-radiobutton > label > input[type="radio"]:checked + cap-checkshell {
2235
+ background: var(--radio-box-background-checked,
2236
+ var(--checkbox-box-background-checked));
2237
+ border: var(--radio-box-border-checked,
2238
+ var(--checkbox-box-border-checked));
2239
+ box-shadow: var(--radio-box-shadow-checked,
2240
+ var(--checkbox-box-shadow-checked));
1843
2241
  }
1844
2242
 
1845
2243
  cap-radiobutton > label > input[type="radio"]:checked + cap-checkshell::after {
1846
- width: .4em;
1847
- height: .4em;
2244
+ width: var(--radio-symbol-size, .4em);
2245
+ height: var(--radio-symbol-size, .4em);
1848
2246
  content: "";
1849
2247
  border-radius: 50%;
1850
- background: var(--checkbox-symbol-color);
2248
+ background: var(--radio-symbol-color, var(--checkbox-symbol-color));
1851
2249
  }
1852
2250
 
1853
2251
  cap-routeoutlet {
@@ -1856,16 +2254,10 @@ cap-routeoutlet {
1856
2254
  flex-direction: column;
1857
2255
  min-width: 0;
1858
2256
  min-height: 0;
1859
- overflow: hidden;
1860
2257
  }
1861
2258
 
1862
2259
  cap-routeoutlet > div {
1863
- display: flex;
1864
2260
  flex: 1 1 auto;
1865
- flex-direction: column;
1866
- min-width: 0;
1867
- min-height: 0;
1868
- overflow: auto;
1869
2261
  }
1870
2262
 
1871
2263
  cap-routeoutlet > div[hidden] {
@@ -1902,7 +2294,10 @@ cap-splitview {
1902
2294
  flex: 1 1 auto;
1903
2295
  min-width: 0;
1904
2296
  min-height: 0;
1905
- overflow: hidden;
2297
+ }
2298
+
2299
+ cap-splitview > * {
2300
+ --_cap-island-gutter: calc(var(--_cap-island-flow, 0) * var(--island-gap, 0px) / 2);
1906
2301
  }
1907
2302
 
1908
2303
  cap-splitview.horizontal {
@@ -1921,6 +2316,13 @@ cap-splitview {
1921
2316
  flex: 1 1 0;
1922
2317
  }
1923
2318
 
2319
+ /* Pane sizes describe content allocation. The compensated scrollport
2320
+ * padding must stay outside that size, even on an explicit islands scope. */
2321
+ cap-splitview > cap-primary.cap-scroll:not(.island),
2322
+ cap-splitview > cap-secondary.cap-scroll:not(.island) {
2323
+ box-sizing: content-box;
2324
+ }
2325
+
1924
2326
  cap-splitview.horizontal > cap-primary {
1925
2327
  min-inline-size: var(--split-primary-min-size, 96px);
1926
2328
  }
@@ -1941,9 +2343,17 @@ cap-splitview {
1941
2343
  position: relative;
1942
2344
  flex: none;
1943
2345
  box-sizing: border-box;
1944
- background: var(--ui-border-color);
2346
+ background: var(--_cap-island-separator-background, var(--ui-border-color));
1945
2347
  touch-action: none;
1946
2348
  user-select: none;
2349
+ z-index: 1;
2350
+ }
2351
+
2352
+ /* Keep a pointer target even when a flush theme gives the track zero
2353
+ * size. This area overlaps pane edges and never changes allocation. */
2354
+ cap-splitview > cap-separator::before {
2355
+ content: '';
2356
+ position: absolute;
1947
2357
  }
1948
2358
 
1949
2359
  cap-splitview > cap-separator::after {
@@ -1960,23 +2370,43 @@ cap-splitview {
1960
2370
  }
1961
2371
 
1962
2372
  cap-splitview.horizontal > cap-separator {
1963
- inline-size: .45rem;
2373
+ inline-size: calc((1 - var(--_cap-island-flow, 0)) * .45rem
2374
+ + var(--_cap-island-flow, 0) * var(--island-gap, 0px));
1964
2375
  cursor: col-resize;
1965
2376
  }
1966
2377
 
2378
+ cap-splitview.horizontal > cap-separator::before {
2379
+ inset-block: 0;
2380
+ left: 50%;
2381
+ width: max(100%, .45rem);
2382
+ transform: translateX(-50%);
2383
+ }
2384
+
1967
2385
  cap-splitview.horizontal > cap-separator::after {
1968
2386
  inset-block: 35%;
1969
- inset-inline: 1px;
2387
+ left: 50%;
2388
+ width: 3px;
2389
+ transform: translateX(-50%);
1970
2390
  }
1971
2391
 
1972
2392
  cap-splitview.vertical > cap-separator {
1973
- block-size: .45rem;
2393
+ block-size: calc((1 - var(--_cap-island-flow, 0)) * .45rem
2394
+ + var(--_cap-island-flow, 0) * var(--island-gap, 0px));
1974
2395
  cursor: row-resize;
1975
2396
  }
1976
2397
 
2398
+ cap-splitview.vertical > cap-separator::before {
2399
+ inset-inline: 0;
2400
+ top: 50%;
2401
+ height: max(100%, .45rem);
2402
+ transform: translateY(-50%);
2403
+ }
2404
+
1977
2405
  cap-splitview.vertical > cap-separator::after {
1978
2406
  inset-inline: 35%;
1979
- inset-block: 1px;
2407
+ top: 50%;
2408
+ height: 3px;
2409
+ transform: translateY(-50%);
1980
2410
  }
1981
2411
 
1982
2412
  cap-splitview[data-resizable="false"] > cap-separator {
@@ -2002,7 +2432,7 @@ cap-tabline {
2002
2432
  color: var(--button-color);
2003
2433
  background: var(--tab-button-background);
2004
2434
  border: none;
2005
- border-radius: var(--radius-md) var(--radius-md) 0 0;
2435
+ border-radius: var(--ui-border-radius) var(--ui-border-radius) 0 0;
2006
2436
  box-shadow: var(--tab-button-shadow);
2007
2437
  box-sizing: border-box;
2008
2438
  align-self: flex-end;
@@ -2092,11 +2522,11 @@ cap-textbox {
2092
2522
  max-width: 100%;
2093
2523
  min-width: var(--input-min-width, 6rem);
2094
2524
  margin: 0;
2095
- padding: 0 5px;
2525
+ padding: var(--ui-control-padding);
2096
2526
  color: var(--input-color);
2097
2527
  background: var(--input-background);
2098
2528
  border: var(--input-border);
2099
- border-radius: var(--radius-md);
2529
+ border-radius: var(--ui-border-radius);
2100
2530
  box-shadow: var(--input-shadow);
2101
2531
  box-sizing: border-box;
2102
2532
  font: inherit;
@@ -2115,6 +2545,41 @@ cap-textbox {
2115
2545
  cursor: not-allowed;
2116
2546
  }
2117
2547
 
2548
+ cap-textbox > input[readonly]:not(:disabled) {
2549
+ color: var(--input-color-readonly);
2550
+ background: var(--input-background-readonly);
2551
+ border: var(--input-border-readonly);
2552
+ box-shadow: var(--input-shadow-readonly);
2553
+ cursor: text;
2554
+ }
2555
+
2556
+
2557
+
2558
+ cap-textbox > input:required:invalid:not(:disabled):not([readonly]):not([aria-invalid="true"]) {
2559
+ outline: 1px dashed var(--required-color);
2560
+ outline-offset: 3px;
2561
+ }
2562
+
2563
+
2564
+ cap-textbox:has(> input:required:invalid:not(:disabled):not([readonly]):not([aria-invalid="true"]))::after {
2565
+ content: "✲";
2566
+ position: absolute;
2567
+ z-index: 3;
2568
+ inset-block-start: max(calc(var(--control-row-padding-block, .25em) + .15em), .3em);
2569
+ inset-inline-end: .35em;
2570
+ display: flex;
2571
+ inline-size: 1rem;
2572
+ block-size: 1rem;
2573
+ align-items: center;
2574
+ justify-content: center;
2575
+ color: var(--required-indicator-color);
2576
+ background: var(--required-indicator-background);
2577
+ font-size: .75rem;
2578
+ font-weight: 700;
2579
+ line-height: 1;
2580
+ pointer-events: none;
2581
+ }
2582
+
2118
2583
  cap-textbox > input:focus-visible {
2119
2584
  outline: 2px solid transparent;
2120
2585
  outline-offset: 1px;
@@ -2134,8 +2599,15 @@ cap-textbox {
2134
2599
  background-size: 2rem 2rem, 100% 100%;
2135
2600
  }
2136
2601
 
2602
+ cap-textbox > input[readonly]:not(:disabled)[aria-busy="true"]:not([aria-invalid="true"]) {
2603
+ background: var(--working-background-image), var(--input-background-readonly);
2604
+ background-repeat: repeat, no-repeat;
2605
+ background-size: 2rem 2rem, 100% 100%;
2606
+ }
2607
+
2137
2608
  cap-textbox > input[aria-invalid="true"] {
2138
- border-color: var(--error-color);
2609
+ border-color: var(--error-control-border);
2610
+ box-shadow: var(--error-control-shadow);
2139
2611
  }
2140
2612
 
2141
2613
  @media (prefers-reduced-motion: reduce) {
@@ -2152,7 +2624,6 @@ cap-textbox {
2152
2624
  }
2153
2625
 
2154
2626
  cap-toggle {
2155
- min-height: var(--control-min-height, 2em);
2156
2627
  display: flex;
2157
2628
  position: relative;
2158
2629
  flex-flow: row nowrap;
@@ -2171,7 +2642,7 @@ cap-toggle {
2171
2642
  cap-toggle > cap-options {
2172
2643
  display: flex;
2173
2644
  min-height: var(--control-min-height, 2em);
2174
- border-radius: var(--radius-md);
2645
+ border-radius: var(--ui-border-radius);
2175
2646
  box-shadow: var(--toggle-group-shadow);
2176
2647
  box-sizing: border-box;
2177
2648
  cursor: pointer;
@@ -2186,7 +2657,7 @@ cap-toggle {
2186
2657
  min-height: var(--control-min-height, 2em);
2187
2658
  min-width: 2em;
2188
2659
  margin: 0;
2189
- padding: 0 6px;
2660
+ padding: var(--ui-control-padding);
2190
2661
  position: relative;
2191
2662
  isolation: isolate;
2192
2663
  font: inherit;
@@ -2216,12 +2687,13 @@ cap-toggle {
2216
2687
  box-shadow: var(--toggle-button-shadow);
2217
2688
  }
2218
2689
 
2219
- cap-toggle > cap-options > button[role="radio"]:hover:not(:disabled)[aria-checked="false"]::before {
2690
+ cap-toggle > cap-options:not([aria-readonly="true"])
2691
+ > button[role="radio"]:hover:not(:disabled)[aria-checked="false"]::before {
2220
2692
  background: var(--button-background-hover);
2221
2693
  }
2222
2694
 
2223
2695
  cap-toggle > cap-options > button[role="radio"]:first-of-type {
2224
- border-radius: var(--radius-md) 0 0 var(--radius-md);
2696
+ border-radius: var(--ui-border-radius) 0 0 var(--ui-border-radius);
2225
2697
  }
2226
2698
 
2227
2699
  cap-toggle > cap-options > button[role="radio"]:first-of-type::before {
@@ -2230,11 +2702,11 @@ cap-toggle {
2230
2702
  }
2231
2703
 
2232
2704
  cap-toggle > cap-options > button[role="radio"]:last-of-type {
2233
- border-radius: 0 var(--radius-md) var(--radius-md) 0;
2705
+ border-radius: 0 var(--ui-border-radius) var(--ui-border-radius) 0;
2234
2706
  }
2235
2707
 
2236
2708
  cap-toggle > cap-options > button[role="radio"]:only-of-type {
2237
- border-radius: var(--radius-md);
2709
+ border-radius: var(--ui-border-radius);
2238
2710
  }
2239
2711
 
2240
2712
  cap-toggle > cap-options > button[role="radio"]:last-of-type::before {
@@ -2256,7 +2728,7 @@ cap-toggle {
2256
2728
  cap-toggle > cap-options > button[role="radio"][aria-checked="true"]::before {
2257
2729
  background: var(--toggle-button-background-checked);
2258
2730
  border: var(--toggle-button-border-checked);
2259
- box-shadow: none;
2731
+ box-shadow: var(--toggle-button-shadow-checked);
2260
2732
  inset-inline: var(--toggle-button-selected-inline-overlap);
2261
2733
  }
2262
2734
 
@@ -2270,6 +2742,51 @@ cap-toggle {
2270
2742
  border: var(--button-border-disabled);
2271
2743
  }
2272
2744
 
2745
+ cap-toggle > cap-options[aria-readonly="true"] > button[role="radio"]:not(:disabled) {
2746
+ cursor: default;
2747
+ }
2748
+
2749
+ cap-toggle > cap-options[aria-readonly="true"] > button[role="radio"]:not(:disabled)::before {
2750
+ filter: saturate(.78);
2751
+ }
2752
+
2753
+ cap-toggle > cap-options[aria-readonly="true"]
2754
+ > button[role="radio"][aria-checked="false"]
2755
+ + [role="radio"][aria-checked="false"]::before {
2756
+ border-inline-start: none;
2757
+ }
2758
+
2759
+ cap-toggle > cap-options[aria-readonly="true"]
2760
+ > button[role="radio"][aria-checked="false"]
2761
+ + [role="radio"][aria-checked="false"]::after {
2762
+ display: none;
2763
+ }
2764
+
2765
+ cap-toggle > cap-options[aria-readonly="true"]
2766
+ > button[role="radio"]:not(:disabled)[aria-checked="false"]::before {
2767
+ background: var(--toggle-button-background-readonly);
2768
+ border: var(--toggle-button-border-readonly);
2769
+ box-shadow: var(--toggle-button-shadow-readonly);
2770
+ }
2771
+
2772
+ /* A fixed choice is one contiguous surface. Retain the outer outline,
2773
+ but do not draw segment seams. This follows the inactive border
2774
+ rule so it also clears that rule's inline borders. */
2775
+ cap-toggle > cap-options[aria-readonly="true"]
2776
+ > button[role="radio"]:not(:disabled)[aria-checked]::before {
2777
+ border-inline: none;
2778
+ }
2779
+
2780
+ cap-toggle > cap-options[aria-readonly="true"]
2781
+ > button[role="radio"][aria-checked]:first-of-type::before {
2782
+ border-inline-start: var(--toggle-button-border-readonly);
2783
+ }
2784
+
2785
+ cap-toggle > cap-options[aria-readonly="true"]
2786
+ > button[role="radio"][aria-checked]:last-of-type::before {
2787
+ border-inline-end: var(--toggle-button-border-readonly);
2788
+ }
2789
+
2273
2790
  cap-toggle > cap-options[aria-busy="true"]:not([aria-invalid="true"])
2274
2791
  > button[role="radio"]::before {
2275
2792
  background: var(--working-background-image), var(--toggle-button-background);
@@ -2286,7 +2803,12 @@ cap-toggle {
2286
2803
  }
2287
2804
 
2288
2805
  cap-toggle > cap-options[aria-invalid="true"] > button[role="radio"]::before {
2289
- border-color: var(--error-color);
2806
+ border-color: var(--error-control-border);
2807
+ }
2808
+
2809
+ cap-toggle > cap-options[aria-invalid="true"] {
2810
+ border-radius: var(--ui-border-radius);
2811
+ box-shadow: var(--error-control-shadow);
2290
2812
  }
2291
2813
 
2292
2814
  cap-toggle > cap-options > button[role="radio"][aria-checked="false"]
@@ -2347,13 +2869,27 @@ cap-treeview {
2347
2869
 
2348
2870
  cap-treeview > [role="tree"],
2349
2871
  cap-treeview > ul[aria-hidden="true"] {
2350
- display: grid;
2351
- align-content: start;
2872
+ display: flex;
2873
+ flex-flow: column nowrap;
2874
+ align-items: stretch;
2352
2875
  margin: 0;
2353
2876
  padding: 0;
2354
2877
  list-style: none;
2355
2878
  }
2356
2879
 
2880
+ cap-treeview[data-cap-retained-loading]::after {
2881
+ content: "";
2882
+ position: absolute;
2883
+ z-index: 1;
2884
+ inset: 0;
2885
+ opacity: 0.33;
2886
+ animation: cap-working-progress .55s linear infinite;
2887
+ background-image: var(--working-background-image);
2888
+ background-repeat: repeat;
2889
+ background-size: 2rem 2rem;
2890
+ pointer-events: none;
2891
+ }
2892
+
2357
2893
  cap-treeview [role="treeitem"],
2358
2894
  cap-treeview > ul[aria-hidden="true"] > li {
2359
2895
  display: flex;
@@ -2422,4 +2958,14 @@ cap-treeview {
2422
2958
  cap-treeview:has(> cap-error) {
2423
2959
  outline: 2px solid Mark;
2424
2960
  }
2961
+
2962
+ cap-treeview[data-cap-retained-loading]::after {
2963
+ display: none;
2964
+ }
2965
+ }
2966
+
2967
+ @media (prefers-reduced-motion: reduce) {
2968
+ cap-treeview[data-cap-retained-loading]::after {
2969
+ animation: none !important;
2970
+ }
2425
2971
  }