@threadlabs/looma 0.13.6 → 0.14.1

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 (80) hide show
  1. package/components/ui-button/ui-button.html +2 -1
  2. package/components/ui-checkbox/ui-checkbox.html +35 -0
  3. package/components/ui-combobox/ui-combobox.html +38 -3
  4. package/components/ui-description-list/ui-description-list.html +54 -9
  5. package/components/ui-input/ui-input.html +27 -0
  6. package/components/ui-input-group/ui-input-group.html +15 -0
  7. package/components/ui-radio/ui-radio.html +35 -0
  8. package/components/ui-select/ui-select.html +29 -3
  9. package/components/ui-switch/ui-switch.html +36 -0
  10. package/components/ui-table/ui-table.html +131 -0
  11. package/components/ui-table/ui-table.js +55 -0
  12. package/components/ui-textarea/ui-textarea.html +20 -0
  13. package/dist/index.js +8 -7
  14. package/package.json +1 -1
  15. package/styles/ui-button.css +3 -1
  16. package/styles/ui-checkbox.css +38 -0
  17. package/styles/ui-combobox.css +38 -1
  18. package/styles/ui-description-list.css +52 -7
  19. package/styles/ui-input-group.css +20 -0
  20. package/styles/ui-input.css +29 -0
  21. package/styles/ui-radio.css +38 -0
  22. package/styles/ui-select.css +29 -3
  23. package/styles/ui-switch.css +41 -0
  24. package/styles/ui-table.css +134 -0
  25. package/styles/ui-textarea.css +21 -0
  26. package/vanilla/UiCheckbox.d.ts +1 -0
  27. package/vanilla/UiCheckbox.js +1 -1
  28. package/vanilla/UiCombobox.d.ts +1 -1
  29. package/vanilla/UiCombobox.js +1 -1
  30. package/vanilla/UiDescriptionList.d.ts +3 -1
  31. package/vanilla/UiDescriptionList.js +6 -2
  32. package/vanilla/UiInput.d.ts +1 -0
  33. package/vanilla/UiInput.js +1 -1
  34. package/vanilla/UiRadio.d.ts +1 -0
  35. package/vanilla/UiRadio.js +1 -1
  36. package/vanilla/UiSelect.d.ts +1 -0
  37. package/vanilla/UiSelect.js +1 -1
  38. package/vanilla/UiSwitch.d.ts +1 -0
  39. package/vanilla/UiSwitch.js +1 -1
  40. package/vanilla/UiTable.d.ts +15 -0
  41. package/vanilla/UiTable.js +30 -0
  42. package/vanilla/UiTextarea.d.ts +1 -0
  43. package/vanilla/UiTextarea.js +1 -1
  44. package/vanilla/index.js +1 -0
  45. package/vue/UiButton.vue +2 -1
  46. package/vue/UiCheckbox.d.ts +2 -0
  47. package/vue/UiCheckbox.vue +34 -0
  48. package/vue/UiCombobox.d.ts +2 -2
  49. package/vue/UiCombobox.vue +39 -2
  50. package/vue/UiDescriptionList.d.ts +5 -2
  51. package/vue/UiDescriptionList.vue +51 -7
  52. package/vue/UiInput.d.ts +2 -0
  53. package/vue/UiInput.vue +41 -0
  54. package/vue/UiInputGroup.vue +15 -0
  55. package/vue/UiList.d.ts +1 -1
  56. package/vue/UiRadio.d.ts +2 -0
  57. package/vue/UiRadio.vue +34 -0
  58. package/vue/UiSelect.d.ts +2 -0
  59. package/vue/UiSelect.vue +34 -3
  60. package/vue/UiSwitch.d.ts +2 -0
  61. package/vue/UiSwitch.vue +35 -0
  62. package/vue/UiTable.d.ts +20 -0
  63. package/vue/UiTable.js +2 -0
  64. package/vue/UiTable.vue +172 -0
  65. package/vue/UiTextarea.d.ts +2 -0
  66. package/vue/UiTextarea.vue +27 -0
  67. package/vue/chunks/UiButton.js +1 -1
  68. package/vue/chunks/UiCheckbox.js +3 -2
  69. package/vue/chunks/UiCombobox.js +1 -1
  70. package/vue/chunks/UiDescriptionList.js +11 -3
  71. package/vue/chunks/UiInput.js +7 -2
  72. package/vue/chunks/UiInputGroup.js +1 -1
  73. package/vue/chunks/UiRadio.js +3 -2
  74. package/vue/chunks/UiSelect.js +7 -2
  75. package/vue/chunks/UiSwitch.js +3 -2
  76. package/vue/chunks/UiTable.js +40 -0
  77. package/vue/chunks/UiTextarea.js +7 -2
  78. package/vue/components.css +522 -174
  79. package/vue/index.d.ts +1 -0
  80. package/vue/index.js +2 -1
@@ -554,7 +554,7 @@ ol[data-v-ee3145b6] {
554
554
  syntax: "*";
555
555
  inherits: false;
556
556
  }
557
- [data-component~="ui-button"][data-v-a45835c7] {
557
+ [data-component~="ui-button"][data-v-bd32a08d] {
558
558
  --_hue: var(--ui-accent);
559
559
  --_hue-hover: var(--ui-accent-hover);
560
560
  --_hue-active: var(--ui-accent-active);
@@ -573,15 +573,15 @@ ol[data-v-ee3145b6] {
573
573
  vertical-align: middle;
574
574
  color: var(--_tone-text);
575
575
  }
576
- [data-component~="ui-button"][data-ui-button-state~="align=start"][data-v-a45835c7] {
576
+ [data-component~="ui-button"][data-ui-button-state~="align=start"][data-v-bd32a08d] {
577
577
  justify-content: flex-start;
578
578
  text-align: start;
579
579
  }
580
- [data-component~="ui-button"][data-ui-button-state~="stretch"][data-v-a45835c7] {
580
+ [data-component~="ui-button"][data-ui-button-state~="stretch"][data-v-bd32a08d] {
581
581
  display: flex;
582
582
  inline-size: 100%;
583
583
  }
584
- [data-component~="ui-button"][data-v-a45835c7] {
584
+ [data-component~="ui-button"][data-v-bd32a08d] {
585
585
  appearance: none;
586
586
  min-block-size: var(--ui-button-min-block-size, var(--ui-control-size-md));
587
587
  border-style: solid;
@@ -606,17 +606,17 @@ ol[data-v-ee3145b6] {
606
606
  margin: 0;
607
607
  }
608
608
  @supports (text-box-trim: trim-both) {
609
- [data-component~="ui-button"][data-v-a45835c7] {
609
+ [data-component~="ui-button"][data-v-bd32a08d] {
610
610
  text-box-trim: trim-both;
611
611
  text-box-edge: cap alphabetic;
612
612
  }
613
613
  }
614
- [data-component~="ui-button"][data-ui-button-state~="size=sm"][data-v-a45835c7] {
614
+ [data-component~="ui-button"][data-ui-button-state~="size=sm"][data-v-bd32a08d] {
615
615
  min-block-size: var(--ui-control-size-sm);
616
616
  padding: var(--ui-space-1) var(--ui-space-2);
617
617
  font-size: var(--ui-font-size-sm);
618
618
  }
619
- [data-component~="ui-button"][data-ui-button-state~="size=lg"][data-v-a45835c7] {
619
+ [data-component~="ui-button"][data-ui-button-state~="size=lg"][data-v-bd32a08d] {
620
620
  min-block-size: var(--ui-control-size-lg);
621
621
  padding: var(--ui-space-3) var(--ui-space-4);
622
622
  font-size: var(--ui-font-size-md);
@@ -624,29 +624,29 @@ ol[data-v-ee3145b6] {
624
624
 
625
625
  /* A link is never :enabled, so interactive states test "not unavailable" instead: for a button that
626
626
  is exactly :enabled, at the same specificity, and it also matches a link that can be followed. */
627
- [data-component~="ui-button"][data-v-a45835c7]:hover:not(:disabled, [aria-disabled="true"]) {
627
+ [data-component~="ui-button"][data-v-bd32a08d]:hover:not(:disabled, [aria-disabled="true"]) {
628
628
  border-color: var(--ui-button-hover-border, var(--_tone-hover));
629
629
  background-color: var(--ui-button-hover-surface, oklch(from var(--_tone) l c h / 12%));
630
630
  }
631
631
 
632
632
  /* Pressed reads as pressed in: the highlight goes, and the shadow moves inside. */
633
- [data-component~="ui-button"][data-v-a45835c7]:active:not(:disabled, [aria-disabled="true"]) {
633
+ [data-component~="ui-button"][data-v-bd32a08d]:active:not(:disabled, [aria-disabled="true"]) {
634
634
  background-color: var(--ui-button-active-surface, oklch(from var(--_tone) l c h / 18%));
635
635
  background-image: none;
636
636
  box-shadow: var(--ui-pressed);
637
637
  }
638
- [data-component~="ui-button"][data-ui-button-state~="variant=solid"][data-v-a45835c7],
639
- [data-component~="ui-button"][data-ui-button-state~="variant=danger"][data-v-a45835c7] {
638
+ [data-component~="ui-button"][data-ui-button-state~="variant=solid"][data-v-bd32a08d],
639
+ [data-component~="ui-button"][data-ui-button-state~="variant=danger"][data-v-bd32a08d] {
640
640
  border-color: var(--_tone);
641
641
  background-color: var(--_tone);
642
642
  color: var(--_on-tone);
643
643
  box-shadow: var(--ui-button-solid-shadow, var(--ui-raised));
644
644
  }
645
- :is([data-component~="ui-button"][data-ui-button-state~="variant=solid"][data-v-a45835c7], [data-component~="ui-button"][data-ui-button-state~="variant=danger"][data-v-a45835c7]):hover:not(:disabled, [aria-disabled="true"]) {
645
+ :is([data-component~="ui-button"][data-ui-button-state~="variant=solid"][data-v-bd32a08d], [data-component~="ui-button"][data-ui-button-state~="variant=danger"][data-v-bd32a08d]):hover:not(:disabled, [aria-disabled="true"]) {
646
646
  background-color: var(--_tone-hover);
647
647
  border-color: var(--_tone-hover);
648
648
  }
649
- :is([data-component~="ui-button"][data-ui-button-state~="variant=solid"][data-v-a45835c7], [data-component~="ui-button"][data-ui-button-state~="variant=danger"][data-v-a45835c7]):active:not(:disabled, [aria-disabled="true"]) {
649
+ :is([data-component~="ui-button"][data-ui-button-state~="variant=solid"][data-v-bd32a08d], [data-component~="ui-button"][data-ui-button-state~="variant=danger"][data-v-bd32a08d]):active:not(:disabled, [aria-disabled="true"]) {
650
650
  background-color: var(--_tone-active);
651
651
  border-color: var(--_tone-active);
652
652
  background-image: none;
@@ -655,43 +655,43 @@ ol[data-v-ee3145b6] {
655
655
 
656
656
  /* Tone is the colour, variant is the volume. Every pairing works: a danger outline is a
657
657
  destructive secondary action, not a special case. */
658
- [data-component~="ui-button"][data-ui-button-state~="tone=neutral"][data-v-a45835c7] {
658
+ [data-component~="ui-button"][data-ui-button-state~="tone=neutral"][data-v-bd32a08d] {
659
659
  --_hue: var(--ui-text);
660
660
  --_hue-hover: var(--ui-text);
661
661
  --_hue-active: var(--ui-text);
662
662
  --_hue-text: var(--ui-text);
663
663
  --_on-hue: var(--ui-surface);
664
664
  }
665
- [data-component~="ui-button"][data-ui-button-state~="tone=danger"][data-v-a45835c7],
666
- [data-component~="ui-button"][data-ui-button-state~="variant=danger"][data-v-a45835c7] {
665
+ [data-component~="ui-button"][data-ui-button-state~="tone=danger"][data-v-bd32a08d],
666
+ [data-component~="ui-button"][data-ui-button-state~="variant=danger"][data-v-bd32a08d] {
667
667
  --_hue: var(--ui-danger);
668
668
  --_hue-hover: var(--ui-danger-hover);
669
669
  --_hue-active: var(--ui-danger-hover);
670
670
  --_hue-text: var(--ui-danger-hover);
671
671
  --_on-hue: var(--ui-on-danger);
672
672
  }
673
- [data-component~="ui-button"][data-ui-button-state~="tone=success"][data-v-a45835c7] {
673
+ [data-component~="ui-button"][data-ui-button-state~="tone=success"][data-v-bd32a08d] {
674
674
  --_hue: var(--ui-success);
675
675
  --_hue-hover: color-mix(in srgb, var(--ui-success) 85%, #000);
676
676
  --_hue-active: color-mix(in srgb, var(--ui-success) 75%, #000);
677
677
  --_hue-text: color-mix(in srgb, var(--ui-success) 85%, #000);
678
678
  --_on-hue: var(--ui-surface);
679
679
  }
680
- [data-component~="ui-button"][data-ui-button-state~="tone=warning"][data-v-a45835c7] {
680
+ [data-component~="ui-button"][data-ui-button-state~="tone=warning"][data-v-bd32a08d] {
681
681
  --_hue: var(--ui-warning);
682
682
  --_hue-hover: color-mix(in srgb, var(--ui-warning) 85%, #000);
683
683
  --_hue-active: color-mix(in srgb, var(--ui-warning) 75%, #000);
684
684
  --_hue-text: color-mix(in srgb, var(--ui-warning) 85%, #000);
685
685
  --_on-hue: var(--ui-surface);
686
686
  }
687
- [data-component~="ui-button"][data-ui-button-state~="tone=info"][data-v-a45835c7] {
687
+ [data-component~="ui-button"][data-ui-button-state~="tone=info"][data-v-bd32a08d] {
688
688
  --_hue: var(--ui-info);
689
689
  --_hue-hover: color-mix(in srgb, var(--ui-info) 85%, #000);
690
690
  --_hue-active: color-mix(in srgb, var(--ui-info) 75%, #000);
691
691
  --_hue-text: color-mix(in srgb, var(--ui-info) 85%, #000);
692
692
  --_on-hue: var(--ui-surface);
693
693
  }
694
- [data-component~="ui-button"][data-ui-button-state~="variant=ghost"][data-v-a45835c7] {
694
+ [data-component~="ui-button"][data-ui-button-state~="variant=ghost"][data-v-bd32a08d] {
695
695
  border-color: transparent;
696
696
  background: transparent;
697
697
  box-shadow: none;
@@ -699,24 +699,24 @@ ol[data-v-ee3145b6] {
699
699
  }
700
700
 
701
701
  /* Tints derive from the text colour, not a surface token, so hover and press show on any background. */
702
- [data-component~="ui-button"][data-ui-button-state~="variant=ghost"][data-v-a45835c7]:hover:not(:disabled, [aria-disabled="true"]) {
702
+ [data-component~="ui-button"][data-ui-button-state~="variant=ghost"][data-v-bd32a08d]:hover:not(:disabled, [aria-disabled="true"]) {
703
703
  background-color: var(--ui-button-ghost-hover-surface, oklch(from var(--_tone) l c h / 10%));
704
704
  border-color: transparent;
705
705
  }
706
- [data-component~="ui-button"][data-ui-button-state~="variant=ghost"][data-v-a45835c7]:active:not(:disabled, [aria-disabled="true"]) {
706
+ [data-component~="ui-button"][data-ui-button-state~="variant=ghost"][data-v-bd32a08d]:active:not(:disabled, [aria-disabled="true"]) {
707
707
  background-color: var(--ui-button-ghost-active-surface, oklch(from var(--_tone) l c h / 16%));
708
708
  border-color: transparent;
709
709
  box-shadow: var(--ui-pressed);
710
710
  }
711
711
 
712
712
  /* A soft halo that transitions in with the other box-shadow changes, layered on the raised shadow. */
713
- [data-component~="ui-button"][data-v-a45835c7]:focus-visible {
713
+ [data-component~="ui-button"][data-v-bd32a08d]:focus-visible {
714
714
  outline: none;
715
715
  box-shadow:
716
716
  var(--ui-button-shadow, var(--ui-raised)),
717
717
  var(--ui-focus-halo);
718
718
  }
719
- [data-component~="ui-button"][data-ui-button-state~="variant=solid"][data-v-a45835c7]:focus-visible {
719
+ [data-component~="ui-button"][data-ui-button-state~="variant=solid"][data-v-bd32a08d]:focus-visible {
720
720
  box-shadow:
721
721
  var(--ui-button-solid-shadow, var(--ui-raised)),
722
722
  var(--ui-focus-halo);
@@ -727,7 +727,7 @@ ol[data-v-ee3145b6] {
727
727
  fill, border, and text together (--ui-disabled-filter), and the theme decides which way is
728
728
  toward the page. The highlight and shadow go, because nothing that cannot be pressed should
729
729
  look raised. */
730
- [data-component~="ui-button"][data-v-a45835c7]:is(:disabled, [aria-disabled="true"]) {
730
+ [data-component~="ui-button"][data-v-bd32a08d]:is(:disabled, [aria-disabled="true"]) {
731
731
  filter: var(--ui-button-disabled-filter, var(--ui-disabled-filter));
732
732
  opacity: var(--ui-button-disabled-opacity, 1);
733
733
  cursor: not-allowed;
@@ -739,12 +739,14 @@ ol[data-v-ee3145b6] {
739
739
  it takes a surface rather than reading as plain text. The surface is a wash of the faded tone,
740
740
  the way hover washes the live one, so it stays light in every tone. An opaque mix toward the
741
741
  hue came out a mid-grey slab for neutral, whose hue is the ink: louder than the enabled button. */
742
- [data-component~="ui-button"][data-ui-button-state~="variant=ghost"][data-v-a45835c7]:is(:disabled, [aria-disabled="true"]) {
742
+ [data-component~="ui-button"][data-ui-button-state~="variant=ghost"][data-v-bd32a08d]:is(:disabled, [aria-disabled="true"]) {
743
743
  background-color: oklch(from var(--_tone) l c h / 14%);
744
744
  border-color: transparent;
745
745
  }
746
+
747
+ /* The size states outrank :host, so sm is named too, or a small button would stay small. */
746
748
  @media (pointer: coarse) {
747
- [data-component~="ui-button"][data-v-a45835c7] {
749
+ [data-component~="ui-button"][data-v-bd32a08d], [data-component~="ui-button"][data-ui-button-state~="size=sm"][data-v-bd32a08d] {
748
750
  min-block-size: var(--ui-control-min-block-size);
749
751
  }
750
752
  }
@@ -754,11 +756,11 @@ ol[data-v-ee3145b6] {
754
756
  a link-style one keeps its text size, so a standalone one ("See all" under a list) needs the
755
757
  area. Only the link needs it: a hit area on every button would reach over its neighbours. */
756
758
  html[data-ui-input-modality="touch"]
757
- [data-component~="ui-button"][data-ui-button-state~="variant=link"][data-v-a45835c7] {
759
+ [data-component~="ui-button"][data-ui-button-state~="variant=link"][data-v-bd32a08d] {
758
760
  position: relative;
759
761
  }
760
762
  html[data-ui-input-modality="touch"]
761
- [data-component~="ui-button"][data-ui-button-state~="variant=link"][data-v-a45835c7]::after {
763
+ [data-component~="ui-button"][data-ui-button-state~="variant=link"][data-v-bd32a08d]::after {
762
764
  position: absolute;
763
765
  inset: 50% auto auto 50%;
764
766
  inline-size: max(100%, var(--ui-control-min-block-size));
@@ -769,7 +771,7 @@ html[data-ui-input-modality="touch"]
769
771
 
770
772
  /* Link: an inline text action. No box, padding, or minimum height (inline targets are exempt under
771
773
  WCAG 2.5.8); the inherited font; an underline that strengthens on hover; a visible focus ring. */
772
- [data-component~="ui-button"][data-ui-button-state~="variant=link"][data-v-a45835c7] {
774
+ [data-component~="ui-button"][data-ui-button-state~="variant=link"][data-v-bd32a08d] {
773
775
  display: inline;
774
776
  min-block-size: 0;
775
777
  padding: 0;
@@ -787,21 +789,21 @@ html[data-ui-input-modality="touch"]
787
789
  color var(--ui-motion-fast) var(--ui-motion-ease),
788
790
  text-decoration-color var(--ui-motion-fast) var(--ui-motion-ease);
789
791
  }
790
- [data-component~="ui-button"][data-ui-button-state~="variant=link"][data-v-a45835c7]:hover:not(:disabled, [aria-disabled="true"]) {
792
+ [data-component~="ui-button"][data-ui-button-state~="variant=link"][data-v-bd32a08d]:hover:not(:disabled, [aria-disabled="true"]) {
791
793
  color: var(--ui-button-link-hover-text, var(--ui-text-primary));
792
794
  text-decoration-color: currentColor;
793
795
  background: none;
794
796
  transform: none;
795
797
  }
796
- [data-component~="ui-button"][data-ui-button-state~="variant=link"][data-v-a45835c7]:active:not(:disabled, [aria-disabled="true"]) {
798
+ [data-component~="ui-button"][data-ui-button-state~="variant=link"][data-v-bd32a08d]:active:not(:disabled, [aria-disabled="true"]) {
797
799
  background: none;
798
800
  transform: none;
799
801
  }
800
- [data-component~="ui-button"][data-ui-button-state~="variant=link"][data-v-a45835c7]:is(:disabled, [aria-disabled="true"]) {
802
+ [data-component~="ui-button"][data-ui-button-state~="variant=link"][data-v-bd32a08d]:is(:disabled, [aria-disabled="true"]) {
801
803
  background: none;
802
804
  border-color: transparent;
803
805
  }
804
- [data-component~="ui-button"][data-ui-button-state~="variant=link"][data-v-a45835c7]:focus-visible {
806
+ [data-component~="ui-button"][data-ui-button-state~="variant=link"][data-v-bd32a08d]:focus-visible {
805
807
  box-shadow: none;
806
808
  /* Fallback keeps the ring if the token is missing: an unresolved var() would void the outline. */
807
809
  outline: 2px solid var(--ui-focus-ring);
@@ -809,7 +811,7 @@ html[data-ui-input-modality="touch"]
809
811
  }
810
812
 
811
813
  /* A component that sets its display still honours the hidden attribute on its root. */
812
- [data-component~="ui-button"][hidden][data-v-a45835c7] {
814
+ [data-component~="ui-button"][hidden][data-v-bd32a08d] {
813
815
  display: none;
814
816
  }
815
817
 
@@ -984,7 +986,7 @@ html[data-ui-input-modality="touch"]
984
986
  syntax: "*";
985
987
  inherits: false;
986
988
  }
987
- [data-component~="ui-checkbox"][data-v-e122df08] {
989
+ [data-component~="ui-checkbox"][data-v-bfcc98e1] {
988
990
  /* Hooks do not inherit, so the parts below read them from the root. */
989
991
  --_ui-checkbox-size: var(--ui-checkbox-size);
990
992
 
@@ -997,25 +999,25 @@ html[data-ui-input-modality="touch"]
997
999
  }
998
1000
 
999
1001
  /* The label, and under it an optional line saying what the choice means. */
1000
- .text[data-v-e122df08] {
1002
+ .text[data-v-bfcc98e1] {
1001
1003
  display: flex;
1002
1004
  flex-direction: column;
1003
1005
  gap: var(--ui-space-1);
1004
1006
  min-inline-size: 0;
1005
1007
  }
1006
- .label[data-v-e122df08] {
1008
+ .label[data-v-bfcc98e1] {
1007
1009
  min-inline-size: 0;
1008
1010
  line-height: var(--ui-line-height-md);
1009
1011
  }
1010
- .description[data-v-e122df08] {
1012
+ .description[data-v-bfcc98e1] {
1011
1013
  color: var(--ui-text-secondary);
1012
1014
  font-size: var(--ui-font-size-sm);
1013
1015
  line-height: var(--ui-line-height);
1014
1016
  }
1015
- .description[data-v-e122df08]:empty {
1017
+ .description[data-v-bfcc98e1]:empty {
1016
1018
  display: none;
1017
1019
  }
1018
- input[data-v-e122df08] {
1020
+ input[data-v-bfcc98e1] {
1019
1021
  appearance: none;
1020
1022
  -webkit-appearance: none;
1021
1023
  position: relative;
@@ -1033,20 +1035,20 @@ input[data-v-e122df08] {
1033
1035
  border-color var(--ui-motion-fast) var(--ui-motion-ease),
1034
1036
  box-shadow var(--ui-motion-fast) var(--ui-motion-ease);
1035
1037
  }
1036
- input[data-v-e122df08]::after {
1038
+ input[data-v-bfcc98e1]::after {
1037
1039
  content: "";
1038
1040
  position: absolute;
1039
1041
  opacity: 0;
1040
1042
  }
1041
- input[data-v-e122df08]:checked,
1042
- input[data-v-e122df08]:indeterminate {
1043
+ input[data-v-bfcc98e1]:checked,
1044
+ input[data-v-bfcc98e1]:indeterminate {
1043
1045
  border-color: var(--ui-accent-solid);
1044
1046
  background: var(--ui-accent-solid);
1045
1047
  box-shadow: inset 0 1px 2px color-mix(in srgb, #000 16%, transparent);
1046
1048
  }
1047
1049
 
1048
1050
  /* Centre the tick's box, then lift it: a rotated L's ink sits ~0.11rem below its box centre. */
1049
- input[data-v-e122df08]:checked::after {
1051
+ input[data-v-bfcc98e1]:checked::after {
1050
1052
  inset: 0;
1051
1053
  margin: auto;
1052
1054
  inline-size: 0.32rem;
@@ -1059,7 +1061,7 @@ input[data-v-e122df08]:checked::after {
1059
1061
  opacity: 1;
1060
1062
  transform: translateY(-0.11rem) rotate(45deg);
1061
1063
  }
1062
- input[data-v-e122df08]:indeterminate::after {
1064
+ input[data-v-bfcc98e1]:indeterminate::after {
1063
1065
  inset: 50% 0.23rem auto;
1064
1066
  block-size: 0.125rem;
1065
1067
  border-radius: var(--ui-radius-round);
@@ -1067,25 +1069,52 @@ input[data-v-e122df08]:indeterminate::after {
1067
1069
  opacity: 1;
1068
1070
  transform: translateY(-50%);
1069
1071
  }
1070
- input[data-v-e122df08]:hover:enabled {
1072
+ input[data-v-bfcc98e1]:hover:enabled {
1071
1073
  border-color: var(--ui-accent-solid);
1072
1074
  }
1073
- input[data-v-e122df08]:focus-visible {
1075
+ input[data-v-bfcc98e1]:focus-visible {
1074
1076
  outline: 2px solid var(--ui-focus-ring, var(--ui-accent-solid));
1075
1077
  outline-offset: 2px;
1076
1078
  }
1077
- [data-component~="ui-checkbox"][data-ui-checkbox-state~="disabled"][data-v-e122df08] {
1079
+ [data-component~="ui-checkbox"][data-ui-checkbox-state~="disabled"][data-v-bfcc98e1] {
1078
1080
  color: var(--ui-disabled-text);
1079
1081
  cursor: not-allowed;
1080
1082
  }
1081
- [data-component~="ui-checkbox"][data-ui-checkbox-state~="disabled"] input[data-v-e122df08] {
1083
+ [data-component~="ui-checkbox"][data-ui-checkbox-state~="disabled"] input[data-v-bfcc98e1] {
1082
1084
  border-color: var(--ui-border-default);
1083
1085
  background: var(--ui-control-surface-disabled, var(--ui-surface-muted));
1084
1086
  cursor: not-allowed;
1085
1087
  }
1086
1088
 
1089
+ /* A sized choice keeps its box and aligns instead: the label takes that size's field type size,
1090
+ and the first line centres in that control height, so the label shares a row's baseline.
1091
+ Multi-line labels and descriptions still grow downward from that first line. */
1092
+ [data-component~="ui-checkbox"][data-ui-checkbox-state~="size=sm"][data-v-bfcc98e1] {
1093
+ --_font: var(--ui-font-size-sm);
1094
+ --_row: var(--ui-control-size-sm);
1095
+ }
1096
+ [data-component~="ui-checkbox"][data-ui-checkbox-state~="size=lg"][data-v-bfcc98e1] {
1097
+ --_font: var(--ui-font-size-md);
1098
+ --_row: var(--ui-control-size-lg);
1099
+ }
1100
+ [data-component~="ui-checkbox"][data-ui-checkbox-state~="size=sm"][data-v-bfcc98e1],
1101
+ [data-component~="ui-checkbox"][data-ui-checkbox-state~="size=lg"][data-v-bfcc98e1] {
1102
+ --_line: calc(var(--_font) * var(--ui-line-height-md));
1103
+ font-size: var(--_font);
1104
+ padding-block: calc((var(--_row) - var(--_line)) / 2);
1105
+ }
1106
+ [data-component~="ui-checkbox"][data-ui-checkbox-state~="size=sm"] input[data-v-bfcc98e1],
1107
+ [data-component~="ui-checkbox"][data-ui-checkbox-state~="size=lg"] input[data-v-bfcc98e1] {
1108
+ margin-top: calc((var(--_line) - var(--_ui-checkbox-size, 1.125rem)) / 2);
1109
+ }
1110
+ @media (pointer: coarse) {
1111
+ [data-component~="ui-checkbox"][data-ui-checkbox-state~="size=sm"][data-v-bfcc98e1] {
1112
+ --_row: var(--ui-control-min-block-size);
1113
+ }
1114
+ }
1115
+
1087
1116
  /* A component that sets its display still honours the hidden attribute on its root. */
1088
- [data-component~="ui-checkbox"][hidden][data-v-e122df08] {
1117
+ [data-component~="ui-checkbox"][hidden][data-v-bfcc98e1] {
1089
1118
  display: none;
1090
1119
  }
1091
1120
 
@@ -1327,7 +1356,7 @@ input[data-v-e122df08]:focus-visible {
1327
1356
  syntax: "*";
1328
1357
  inherits: false;
1329
1358
  }
1330
- [data-component~="ui-combobox"][data-v-1482f333] {
1359
+ [data-component~="ui-combobox"][data-v-fd4a871f] {
1331
1360
  /* Hooks do not inherit, so the parts below read them from the root. */
1332
1361
  --_ui-combobox-label-text: var(--ui-combobox-label-text);
1333
1362
  --_ui-combobox-label-font-size: var(--ui-combobox-label-font-size);
@@ -1346,20 +1375,20 @@ input[data-v-e122df08]:focus-visible {
1346
1375
  color: var(--ui-text-primary);
1347
1376
  font: inherit;
1348
1377
  }
1349
- label[data-v-1482f333] {
1378
+ label[data-v-fd4a871f] {
1350
1379
  color: var(--_ui-combobox-label-text, var(--ui-text-primary));
1351
1380
  font-size: var(--_ui-combobox-label-font-size, var(--ui-font-size-sm));
1352
1381
  font-weight: 500;
1353
1382
  }
1354
1383
  /* The field and anything that annotates it sit on one row; the help button is beside the box,
1355
1384
  not inside it, because a control's box holds its value. */
1356
- .control[data-v-1482f333] {
1385
+ .control[data-v-fd4a871f] {
1357
1386
  display: flex;
1358
1387
  align-items: center;
1359
1388
  gap: var(--ui-space-2);
1360
1389
  min-inline-size: 0;
1361
1390
  }
1362
- .field[data-v-1482f333] {
1391
+ .field[data-v-fd4a871f] {
1363
1392
  flex: 1 1 auto;
1364
1393
  display: flex;
1365
1394
  min-inline-size: 0;
@@ -1371,14 +1400,14 @@ label[data-v-1482f333] {
1371
1400
  border-color var(--ui-motion-fast) var(--ui-motion-ease),
1372
1401
  box-shadow var(--ui-motion-fast) var(--ui-motion-ease);
1373
1402
  }
1374
- .field[data-v-1482f333]:focus-within {
1403
+ .field[data-v-fd4a871f]:focus-within {
1375
1404
  border-color: var(--ui-control-focus, var(--ui-accent-solid));
1376
1405
  box-shadow:
1377
1406
  var(--ui-control-inset),
1378
1407
  var(--ui-control-focus-halo-shadow);
1379
1408
  }
1380
1409
  /* A ghost icon button: the affordance is the mark, not a box around it. */
1381
- .help[data-v-1482f333] {
1410
+ .help[data-v-fd4a871f] {
1382
1411
  flex: none;
1383
1412
  display: inline-flex;
1384
1413
  align-items: center;
@@ -1395,28 +1424,28 @@ label[data-v-1482f333] {
1395
1424
  background-color var(--ui-motion-fast) var(--ui-motion-ease),
1396
1425
  color var(--ui-motion-fast) var(--ui-motion-ease);
1397
1426
  }
1398
- .help[data-v-1482f333]:hover:enabled,
1399
- .help[aria-expanded="true"][data-v-1482f333] {
1427
+ .help[data-v-fd4a871f]:hover:enabled,
1428
+ .help[aria-expanded="true"][data-v-fd4a871f] {
1400
1429
  background: color-mix(in srgb, currentColor 8%, transparent);
1401
1430
  color: var(--ui-text-primary);
1402
1431
  }
1403
- .help[data-v-1482f333]:focus-visible {
1432
+ .help[data-v-fd4a871f]:focus-visible {
1404
1433
  outline: none;
1405
1434
  box-shadow: var(--ui-focus-halo);
1406
1435
  }
1407
- .help[data-v-1482f333]:disabled {
1436
+ .help[data-v-fd4a871f]:disabled {
1408
1437
  color: var(--ui-disabled-text);
1409
1438
  cursor: not-allowed;
1410
1439
  }
1411
- .help-icon[data-v-1482f333] {
1440
+ .help-icon[data-v-fd4a871f] {
1412
1441
  inline-size: var(--ui-icon-size-sm);
1413
1442
  block-size: var(--ui-icon-size-sm);
1414
1443
  }
1415
- input[data-v-1482f333]::selection {
1444
+ input[data-v-fd4a871f]::selection {
1416
1445
  background: color-mix(in srgb, var(--ui-accent-solid) 20%, transparent);
1417
1446
  color: inherit;
1418
1447
  }
1419
- input[data-v-1482f333] {
1448
+ input[data-v-fd4a871f] {
1420
1449
  appearance: none;
1421
1450
  width: 100%;
1422
1451
  min-inline-size: 0;
@@ -1432,11 +1461,20 @@ input[data-v-1482f333] {
1432
1461
  margin: 0;
1433
1462
  outline: none;
1434
1463
  }
1435
- [data-component~="ui-combobox"][data-ui-combobox-state~="size=sm"] input[data-v-1482f333] {
1436
- min-block-size: calc(var(--ui-control-size-sm) - 2px);
1464
+ [data-component~="ui-combobox"][data-ui-combobox-state~="size=sm"][data-v-fd4a871f] {
1465
+ --_row: var(--ui-control-size-sm);
1466
+ }
1467
+ [data-component~="ui-combobox"][data-ui-combobox-state~="size=sm"] input[data-v-fd4a871f] {
1468
+ min-block-size: calc(var(--_row) - 2px);
1437
1469
  padding: var(--ui-space-1) var(--ui-space-2);
1470
+ font-size: var(--ui-font-size-sm);
1438
1471
  }
1439
- button[data-v-1482f333] {
1472
+ [data-component~="ui-combobox"][data-ui-combobox-state~="size=lg"] input[data-v-fd4a871f] {
1473
+ min-block-size: calc(var(--ui-control-size-lg) - 2px);
1474
+ padding: var(--ui-space-3) var(--ui-space-4);
1475
+ font-size: var(--ui-font-size-md);
1476
+ }
1477
+ button[data-v-fd4a871f] {
1440
1478
  appearance: none;
1441
1479
  display: inline-grid;
1442
1480
  place-items: center;
@@ -1451,31 +1489,31 @@ button[data-v-1482f333] {
1451
1489
  padding: 0 var(--ui-space-1);
1452
1490
  cursor: pointer;
1453
1491
  }
1454
- .affordance-icon[data-v-1482f333] {
1492
+ .affordance-icon[data-v-fd4a871f] {
1455
1493
  display: block;
1456
1494
  inline-size: var(--ui-icon-size-sm);
1457
1495
  block-size: var(--ui-icon-size-sm);
1458
1496
  }
1459
- button[data-v-1482f333]:hover:enabled {
1497
+ button[data-v-fd4a871f]:hover:enabled {
1460
1498
  background: var(--ui-surface-muted);
1461
1499
  color: var(--ui-text-primary);
1462
1500
  }
1463
- button[data-v-1482f333]:focus-visible {
1501
+ button[data-v-fd4a871f]:focus-visible {
1464
1502
  outline: none;
1465
1503
  background: var(--ui-surface-muted);
1466
1504
  box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--ui-focus-ring) 45%, transparent);
1467
1505
  }
1468
- input[data-v-1482f333]:disabled, button[data-v-1482f333]:disabled {
1506
+ input[data-v-fd4a871f]:disabled, button[data-v-fd4a871f]:disabled {
1469
1507
  color: var(--ui-disabled-text);
1470
1508
  cursor: not-allowed;
1471
1509
  }
1472
- .field[data-v-1482f333]:has(input:disabled) {
1510
+ .field[data-v-fd4a871f]:has(input:disabled) {
1473
1511
  background: var(--ui-control-surface-disabled, var(--ui-surface-muted));
1474
1512
  }
1475
- [data-component~="ui-combobox"][data-ui-combobox-state~="validationStatus=error"] .field[data-v-1482f333] {
1513
+ [data-component~="ui-combobox"][data-ui-combobox-state~="validationStatus=error"] .field[data-v-fd4a871f] {
1476
1514
  border-color: var(--ui-danger-solid, var(--ui-accent-active));
1477
1515
  }
1478
- .popup[data-v-1482f333] {
1516
+ .popup[data-v-fd4a871f] {
1479
1517
  box-sizing: border-box;
1480
1518
  min-inline-size: 12rem;
1481
1519
  max-inline-size: calc(100vw - 1rem);
@@ -1489,40 +1527,40 @@ input[data-v-1482f333]:disabled, button[data-v-1482f333]:disabled {
1489
1527
  color: var(--ui-text-primary);
1490
1528
  box-shadow: var(--ui-elevation-overlay, var(--ui-shadow-lg));
1491
1529
  }
1492
- [hidden][data-v-1482f333] {
1530
+ [hidden][data-v-fd4a871f] {
1493
1531
  display: none;
1494
1532
  }
1495
- .option[data-v-1482f333] {
1533
+ .option[data-v-fd4a871f] {
1496
1534
  padding: var(--ui-space-2) var(--ui-space-3);
1497
1535
  border-radius: var(--ui-radius-sm);
1498
1536
  cursor: pointer;
1499
1537
  overflow-wrap: anywhere;
1500
1538
  }
1501
- .option[data-v-1482f333]:hover, .option.active[data-v-1482f333] {
1539
+ .option[data-v-fd4a871f]:hover, .option.active[data-v-fd4a871f] {
1502
1540
  background: var(--ui-surface-muted);
1503
1541
  outline: 1px solid var(--ui-focus-ring);
1504
1542
  outline-offset: -1px;
1505
1543
  }
1506
- .option[aria-disabled="true"][data-v-1482f333] {
1544
+ .option[aria-disabled="true"][data-v-fd4a871f] {
1507
1545
  color: var(--ui-disabled-text);
1508
1546
  cursor: not-allowed;
1509
1547
  }
1510
- .primary[data-v-1482f333] {
1548
+ .primary[data-v-fd4a871f] {
1511
1549
  display: block;
1512
1550
  color: var(--_ui-combobox-option-text, var(--ui-text-primary));
1513
1551
  font-weight: 500;
1514
1552
  }
1515
- .message[data-v-1482f333], .group[data-v-1482f333] {
1553
+ .message[data-v-fd4a871f], .group[data-v-fd4a871f] {
1516
1554
  color: var(--_ui-combobox-message-text, var(--ui-text-secondary));
1517
1555
  font-weight: 400;
1518
1556
  font-size: var(--ui-font-size-sm);
1519
1557
  line-height: var(--ui-line-height-md);
1520
1558
  overflow-wrap: anywhere;
1521
1559
  }
1522
- .group[data-v-1482f333], .popup .message[data-v-1482f333] {
1560
+ .group[data-v-fd4a871f], .popup .message[data-v-fd4a871f] {
1523
1561
  padding: var(--ui-space-2) var(--ui-space-3);
1524
1562
  }
1525
- .sr-only[data-v-1482f333] {
1563
+ .sr-only[data-v-fd4a871f] {
1526
1564
  position: absolute;
1527
1565
  inline-size: 1px;
1528
1566
  block-size: 1px;
@@ -1531,16 +1569,24 @@ input[data-v-1482f333]:disabled, button[data-v-1482f333]:disabled {
1531
1569
  white-space: nowrap;
1532
1570
  }
1533
1571
  @media (pointer: coarse) {
1534
- button[data-v-1482f333] {
1572
+ button[data-v-fd4a871f] {
1535
1573
  min-inline-size: 2.75rem;
1536
1574
  min-block-size: 2.75rem;
1575
+ }
1576
+ /* Under touch a small field is still a touch-sized target, as a small button is, and keeps
1577
+ body-size text: below 16px, iOS zooms the page into the focused field. */
1578
+ [data-component~="ui-combobox"][data-ui-combobox-state~="size=sm"][data-v-fd4a871f] {
1579
+ --_row: var(--ui-control-min-block-size);
1580
+ }
1581
+ [data-component~="ui-combobox"][data-ui-combobox-state~="size=sm"] input[data-v-fd4a871f] {
1582
+ font-size: inherit;
1537
1583
  }
1538
1584
  }
1539
1585
  @media (forced-colors: active) {
1540
- .field[data-v-1482f333], .popup[data-v-1482f333] {
1586
+ .field[data-v-fd4a871f], .popup[data-v-fd4a871f] {
1541
1587
  border-color: CanvasText;
1542
1588
  }
1543
- .option.active[data-v-1482f333] {
1589
+ .option.active[data-v-fd4a871f] {
1544
1590
  outline-color: Highlight;
1545
1591
  }
1546
1592
  }
@@ -1548,12 +1594,12 @@ button[data-v-1482f333] {
1548
1594
  /* Multiple mode: every option carries a checkbox, so a list that takes several answers says so
1549
1595
  before anything is picked. aria-selected is the state; this draws it.
1550
1596
  Longhands, not shorthands: lowering drops a shorthand that omits a component. */
1551
- [data-component~="ui-combobox"][data-ui-combobox-state~="multiple"] .option[data-v-1482f333] {
1597
+ [data-component~="ui-combobox"][data-ui-combobox-state~="multiple"] .option[data-v-fd4a871f] {
1552
1598
  display: flex;
1553
1599
  gap: var(--ui-space-2);
1554
1600
  align-items: center;
1555
1601
  }
1556
- [data-component~="ui-combobox"][data-ui-combobox-state~="multiple"] .option[data-v-1482f333]::before {
1602
+ [data-component~="ui-combobox"][data-ui-combobox-state~="multiple"] .option[data-v-fd4a871f]::before {
1557
1603
  content: "";
1558
1604
  flex: none;
1559
1605
  inline-size: 1.125rem;
@@ -1568,7 +1614,7 @@ button[data-v-1482f333] {
1568
1614
  background-size: 0.7rem;
1569
1615
  }
1570
1616
  [data-component~="ui-combobox"][data-ui-combobox-state~="multiple"]
1571
- .option[aria-selected="true"][data-v-1482f333]::before {
1617
+ .option[aria-selected="true"][data-v-fd4a871f]::before {
1572
1618
  border-color: var(--ui-accent-solid);
1573
1619
  background-color: var(--ui-accent-solid);
1574
1620
  background-image: var(
@@ -1578,20 +1624,40 @@ button[data-v-1482f333] {
1578
1624
  }
1579
1625
 
1580
1626
  /* Multiple mode: chips wrap before the cursor on one flexible field line. */
1581
- [data-component~="ui-combobox"][data-ui-combobox-state~="multiple"] .field[data-v-1482f333] {
1627
+ [data-component~="ui-combobox"][data-ui-combobox-state~="multiple"] .field[data-v-fd4a871f] {
1582
1628
  flex-wrap: wrap;
1583
1629
  align-items: center;
1584
1630
  gap: var(--ui-space-1);
1585
1631
  min-block-size: var(--_ui-combobox-item-min-block-size, 2.5rem);
1586
1632
  padding: var(--ui-space-1);
1587
1633
  }
1588
- [data-component~="ui-combobox"][data-ui-combobox-state~="multiple"] input[data-v-1482f333] {
1634
+ [data-component~="ui-combobox"][data-ui-combobox-state~="multiple"] input[data-v-fd4a871f] {
1589
1635
  flex: 1 0 var(--_ui-combobox-item-input-min-inline-size, 5rem);
1590
1636
  width: auto;
1591
1637
  min-block-size: 1.75rem;
1592
1638
  padding: var(--ui-space-0-5) var(--ui-space-1);
1593
1639
  }
1594
- .item[data-v-1482f333] {
1640
+ /* A small multiple field starts at the small control height; chosen items still wrap it taller. */
1641
+ [data-component~="ui-combobox"][data-ui-combobox-state~="multiple"][data-component~="ui-combobox"][data-ui-combobox-state~="size=sm"]
1642
+ .field[data-v-fd4a871f] {
1643
+ min-block-size: 0;
1644
+ padding: var(--ui-space-0-5);
1645
+ }
1646
+ [data-component~="ui-combobox"][data-ui-combobox-state~="multiple"][data-component~="ui-combobox"][data-ui-combobox-state~="size=sm"]
1647
+ input[data-v-fd4a871f] {
1648
+ min-block-size: calc(var(--_row) - 2px - 2 * var(--ui-space-0-5));
1649
+ padding: 0 var(--ui-space-1);
1650
+ }
1651
+ /* A large multiple field starts at the large control height, as sm starts at the small one. */
1652
+ [data-component~="ui-combobox"][data-ui-combobox-state~="multiple"][data-component~="ui-combobox"][data-ui-combobox-state~="size=lg"]
1653
+ .field[data-v-fd4a871f] {
1654
+ min-block-size: 0;
1655
+ }
1656
+ [data-component~="ui-combobox"][data-ui-combobox-state~="multiple"][data-component~="ui-combobox"][data-ui-combobox-state~="size=lg"]
1657
+ input[data-v-fd4a871f] {
1658
+ min-block-size: calc(var(--ui-control-size-lg) - 2px - 2 * var(--ui-space-1));
1659
+ }
1660
+ .item[data-v-fd4a871f] {
1595
1661
  appearance: none;
1596
1662
  display: inline-flex;
1597
1663
  min-inline-size: 0;
@@ -1605,16 +1671,16 @@ button[data-v-1482f333] {
1605
1671
  font: inherit;
1606
1672
  cursor: default;
1607
1673
  }
1608
- .item[data-v-1482f333]:focus-visible {
1674
+ .item[data-v-fd4a871f]:focus-visible {
1609
1675
  outline: 2px solid var(--ui-focus-ring);
1610
1676
  outline-offset: 1px;
1611
1677
  }
1612
- .item[data-v-1482f333]:disabled {
1678
+ .item[data-v-fd4a871f]:disabled {
1613
1679
  opacity: 0.6;
1614
1680
  }
1615
1681
 
1616
1682
  /* A component that sets its display still honours the hidden attribute on its root. */
1617
- [data-component~="ui-combobox"][hidden][data-v-1482f333] {
1683
+ [data-component~="ui-combobox"][hidden][data-v-fd4a871f] {
1618
1684
  display: none;
1619
1685
  }
1620
1686
 
@@ -1778,29 +1844,66 @@ dd[data-v-6e5b491d] {
1778
1844
 
1779
1845
  /* Named values: a term and what it is, for each item (ui-description-item). */
1780
1846
  /* Rows line every term up in one column and every value in the next, through subgrid. */
1781
- [data-component~="ui-description-list"][data-v-a4548235] {
1847
+ [data-component~="ui-description-list"][data-v-640c2332] {
1848
+ --_gap: var(--ui-space-2);
1849
+ --_gap-compact: var(--ui-space-1);
1850
+ --_column-gap: var(--ui-space-6);
1851
+ --_min: 10rem;
1852
+ --_track: var(--_min);
1853
+ --_tile-padding: var(--ui-space-3);
1782
1854
  display: grid;
1783
1855
  grid-template-columns: minmax(6rem, max-content) minmax(0, 1fr);
1784
- gap: var(--ui-space-2) var(--ui-space-6);
1856
+ gap: var(--_gap) var(--_column-gap);
1785
1857
  min-inline-size: 0;
1786
1858
  margin: 0;
1787
1859
  }
1788
1860
 
1789
- /* Tiles pass their shape to the items through private properties, which cross into each item. */
1790
- [data-component~="ui-description-list"][data-ui-description-list-state~="layout=tiles"][data-v-a4548235] {
1861
+ /* Stacked, grid, and tiles set each term above its value, passing the shape to the items through
1862
+ private properties, which cross into each item. */
1863
+ [data-component~="ui-description-list"][data-ui-description-list-state~="layout=stacked"][data-v-640c2332],
1864
+ [data-component~="ui-description-list"][data-ui-description-list-state~="layout=grid"][data-v-640c2332],
1865
+ [data-component~="ui-description-list"][data-ui-description-list-state~="layout=tiles"][data-v-640c2332] {
1791
1866
  --_ui-description-display: flex;
1792
1867
  --_ui-description-column: auto;
1868
+ --_ui-description-align: stretch;
1869
+ --_gap: var(--ui-space-4);
1870
+ --_gap-compact: var(--ui-space-2);
1871
+ grid-template-columns: minmax(0, 1fr);
1872
+ }
1873
+
1874
+ /* A column is at least --_min wide; with columns set, at least its share of the width, so no more
1875
+ than that many fit. */
1876
+ [data-component~="ui-description-list"][data-ui-description-list-state~="layout=grid"][data-v-640c2332],
1877
+ [data-component~="ui-description-list"][data-ui-description-list-state~="layout=tiles"][data-v-640c2332] {
1878
+ grid-template-columns: repeat(auto-fill, minmax(min(100%, var(--_track)), 1fr));
1879
+ }
1880
+ [data-component~="ui-description-list"][data-ui-description-list-state~="layout=tiles"][data-v-640c2332] {
1793
1881
  --_ui-description-align: flex-start;
1794
1882
  --_ui-description-value-size: var(--ui-font-size-lg);
1795
- --_ui-description-padding: var(--ui-space-3);
1883
+ --_ui-description-padding: var(--_tile-padding);
1796
1884
  --_ui-description-border-width: 1px;
1797
- display: grid;
1798
- grid-template-columns: repeat(auto-fill, minmax(min(100%, 10rem), 1fr));
1799
- gap: var(--ui-space-3);
1885
+ --_gap: var(--ui-space-3);
1886
+ --_gap-compact: var(--ui-space-2);
1887
+ --_column-gap: var(--_gap);
1888
+ }
1889
+ [data-component~="ui-description-list"][data-ui-description-list-state~="columns=2"][data-v-640c2332] {
1890
+ --_track: max(var(--_min), (100% - var(--_column-gap)) / 2);
1891
+ }
1892
+ [data-component~="ui-description-list"][data-ui-description-list-state~="columns=3"][data-v-640c2332] {
1893
+ --_track: max(var(--_min), (100% - 2 * var(--_column-gap)) / 3);
1894
+ }
1895
+ [data-component~="ui-description-list"][data-ui-description-list-state~="columns=4"][data-v-640c2332] {
1896
+ --_track: max(var(--_min), (100% - 3 * var(--_column-gap)) / 4);
1897
+ }
1898
+
1899
+ /* Compact takes each layout's closer spacing. */
1900
+ [data-component~="ui-description-list"][data-ui-description-list-state~="density=compact"][data-v-640c2332] {
1901
+ --_gap: var(--_gap-compact);
1902
+ --_tile-padding: var(--ui-space-2);
1800
1903
  }
1801
1904
 
1802
1905
  /* A component that sets its display still honours the hidden attribute on its root. */
1803
- [data-component~="ui-description-list"][hidden][data-v-a4548235] {
1906
+ [data-component~="ui-description-list"][hidden][data-v-640c2332] {
1804
1907
  display: none;
1805
1908
  }
1806
1909
 
@@ -3722,7 +3825,7 @@ svg[data-v-006fa1b2-s] {
3722
3825
  syntax: "*";
3723
3826
  inherits: false;
3724
3827
  }
3725
- [data-component~="ui-input"][data-v-e1edefb2] {
3828
+ [data-component~="ui-input"][data-v-4ba095d3] {
3726
3829
  box-sizing: border-box;
3727
3830
  display: inline-block;
3728
3831
  inline-size: 100%;
@@ -3754,22 +3857,52 @@ svg[data-v-006fa1b2-s] {
3754
3857
  background-color var(--ui-motion-fast) var(--ui-motion-ease);
3755
3858
  }
3756
3859
 
3860
+ /* Each size reads the hook and then an Input Group's default first, so a group, which draws the frame, can zero it. */
3861
+ [data-component~="ui-input"][data-ui-input-state~="size=sm"][data-v-4ba095d3] {
3862
+ min-block-size: var(
3863
+ --ui-input-min-block-size,
3864
+ var(--_ui-default-input-min-block-size, var(--ui-control-size-sm))
3865
+ );
3866
+ padding: var(--ui-space-1) var(--ui-space-2);
3867
+ font-size: var(--ui-font-size-sm);
3868
+ }
3869
+ [data-component~="ui-input"][data-ui-input-state~="size=lg"][data-v-4ba095d3] {
3870
+ min-block-size: var(
3871
+ --ui-input-min-block-size,
3872
+ var(--_ui-default-input-min-block-size, var(--ui-control-size-lg))
3873
+ );
3874
+ padding: var(--ui-space-3) var(--ui-space-4);
3875
+ font-size: var(--ui-font-size-md);
3876
+ }
3877
+
3878
+ /* Under touch a small field is still a touch-sized target, as a small button is, and keeps
3879
+ body-size text: below 16px, iOS zooms the page into the focused field. */
3880
+ @media (pointer: coarse) {
3881
+ [data-component~="ui-input"][data-ui-input-state~="size=sm"][data-v-4ba095d3] {
3882
+ min-block-size: var(
3883
+ --ui-input-min-block-size,
3884
+ var(--_ui-default-input-min-block-size, var(--ui-control-min-block-size))
3885
+ );
3886
+ font-size: inherit;
3887
+ }
3888
+ }
3889
+
3757
3890
  /* Tabbing into a field selects its text; tint that selection softly instead of the page highlight. */
3758
- [data-component~="ui-input"][data-v-e1edefb2]::selection {
3891
+ [data-component~="ui-input"][data-v-4ba095d3]::selection {
3759
3892
  background: color-mix(in srgb, var(--ui-accent-solid) 20%, transparent);
3760
3893
  color: inherit;
3761
3894
  }
3762
- [data-component~="ui-input"][data-v-e1edefb2]::placeholder {
3895
+ [data-component~="ui-input"][data-v-4ba095d3]::placeholder {
3763
3896
  color: var(--ui-control-placeholder, var(--ui-text-secondary));
3764
3897
  opacity: 1;
3765
3898
  }
3766
- [data-component~="ui-input"][data-v-e1edefb2]:hover:not(:focus):not(:disabled) {
3899
+ [data-component~="ui-input"][data-v-4ba095d3]:hover:not(:focus):not(:disabled) {
3767
3900
  border-color: var(
3768
3901
  --ui-input-border-hover,
3769
3902
  var(--_ui-default-input-border-hover, var(--ui-control-border-hover, var(--ui-text-secondary)))
3770
3903
  );
3771
3904
  }
3772
- [data-component~="ui-input"][data-v-e1edefb2]:focus-visible {
3905
+ [data-component~="ui-input"][data-v-4ba095d3]:focus-visible {
3773
3906
  border-color: var(
3774
3907
  --ui-input-focus-border,
3775
3908
  var(--_ui-default-input-focus-border, var(--ui-control-focus, var(--ui-accent-solid)))
@@ -3786,14 +3919,14 @@ svg[data-v-006fa1b2-s] {
3786
3919
  }
3787
3920
 
3788
3921
  /* The app's invalid flag, or the browser's own verdict once the user has left an invalid field. */
3789
- [data-component~="ui-input"][aria-invalid="true"][data-v-e1edefb2],
3790
- [data-component~="ui-input"][data-v-e1edefb2]:is(:user-invalid, [data-user-invalid]) {
3922
+ [data-component~="ui-input"][aria-invalid="true"][data-v-4ba095d3],
3923
+ [data-component~="ui-input"][data-v-4ba095d3]:is(:user-invalid, [data-user-invalid]) {
3791
3924
  border-color: var(
3792
3925
  --ui-input-invalid-border,
3793
3926
  var(--_ui-default-input-invalid-border, var(--ui-danger-solid))
3794
3927
  );
3795
3928
  }
3796
- [data-component~="ui-input"][data-v-e1edefb2]:is([aria-invalid="true"], :is(:user-invalid, [data-user-invalid])):focus-visible {
3929
+ [data-component~="ui-input"][data-v-4ba095d3]:is([aria-invalid="true"], :is(:user-invalid, [data-user-invalid])):focus-visible {
3797
3930
  box-shadow: var(
3798
3931
  --ui-input-invalid-focus-shadow,
3799
3932
  var(
@@ -3803,7 +3936,7 @@ svg[data-v-006fa1b2-s] {
3803
3936
  )
3804
3937
  );
3805
3938
  }
3806
- [data-component~="ui-input"][data-v-e1edefb2]:disabled {
3939
+ [data-component~="ui-input"][data-v-4ba095d3]:disabled {
3807
3940
  background: var(--ui-control-surface-disabled, var(--ui-surface-muted));
3808
3941
  color: var(--ui-disabled-text);
3809
3942
  box-shadow: none;
@@ -3812,7 +3945,7 @@ svg[data-v-006fa1b2-s] {
3812
3945
 
3813
3946
  /* Forced colors drop box shadows, so the focus ring becomes an outline. */
3814
3947
  @media (forced-colors: active) {
3815
- [data-component~="ui-input"][data-v-e1edefb2]:focus-visible {
3948
+ [data-component~="ui-input"][data-v-4ba095d3]:focus-visible {
3816
3949
  outline: var(
3817
3950
  --ui-input-focus-outline,
3818
3951
  var(--_ui-default-input-focus-outline, 2px solid Highlight)
@@ -3825,7 +3958,7 @@ svg[data-v-006fa1b2-s] {
3825
3958
  * scroll vertically inside the field. Native inputs already center their single line. */
3826
3959
 
3827
3960
  /* A component that sets its display still honours the hidden attribute on its root. */
3828
- [data-component~="ui-input"][hidden][data-v-e1edefb2] {
3961
+ [data-component~="ui-input"][hidden][data-v-4ba095d3] {
3829
3962
  display: none;
3830
3963
  }
3831
3964
 
@@ -3837,7 +3970,7 @@ svg[data-v-006fa1b2-s] {
3837
3970
  whole value is. The action slot takes one button at the end, inside the border, for the one
3838
3971
  thing the field is for ("Continue" after a site's address), so it reads as the field's action
3839
3972
  and not the form's. */
3840
- [data-component~="ui-input-group"][data-v-d57b2ead] {
3973
+ [data-component~="ui-input-group"][data-v-26a5b56d] {
3841
3974
  /* The group's own border and height stand for the input's, so the group is a lone Input's height.
3842
3975
  Hooks do not inherit, so these are defaults for the input; its own hooks still win. */
3843
3976
  --_ui-default-input-border-width: 0;
@@ -3871,22 +4004,35 @@ svg[data-v-006fa1b2-s] {
3871
4004
  border-color var(--ui-motion-fast) var(--ui-motion-ease),
3872
4005
  box-shadow var(--ui-motion-fast) var(--ui-motion-ease);
3873
4006
  }
3874
- [data-component~="ui-input-group"][data-v-d57b2ead]:hover:not(:has(input:focus, input:disabled)) {
4007
+
4008
+ /* The frame takes its input's size, so a small group lines up with small buttons and fields. */
4009
+ [data-component~="ui-input-group"][data-v-26a5b56d]:has(.field [data-ui-input-state~="size=sm"]) {
4010
+ min-block-size: var(--ui-control-size-sm);
4011
+ }
4012
+ [data-component~="ui-input-group"][data-v-26a5b56d]:has(.field [data-ui-input-state~="size=lg"]) {
4013
+ min-block-size: var(--ui-control-size-lg);
4014
+ }
4015
+ @media (pointer: coarse) {
4016
+ [data-component~="ui-input-group"][data-v-26a5b56d]:has(.field [data-ui-input-state~="size=sm"]) {
4017
+ min-block-size: var(--ui-control-min-block-size);
4018
+ }
4019
+ }
4020
+ [data-component~="ui-input-group"][data-v-26a5b56d]:hover:not(:has(input:focus, input:disabled)) {
3875
4021
  border-color: var(--ui-control-border-hover, var(--ui-text-secondary));
3876
4022
  }
3877
4023
 
3878
4024
  /* The ring shows when the field's input would show its own: when it is focus-visible, which a
3879
4025
  text input is for a pointer as well as a keyboard. A focused action button draws its own. */
3880
- [data-component~="ui-input-group"][data-v-d57b2ead]:has(.field input:focus-visible) {
4026
+ [data-component~="ui-input-group"][data-v-26a5b56d]:has(.field input:focus-visible) {
3881
4027
  border-color: var(--ui-control-focus, var(--ui-accent-solid));
3882
4028
  box-shadow:
3883
4029
  var(--ui-control-inset),
3884
4030
  var(--ui-control-focus-halo-shadow);
3885
4031
  }
3886
- [data-component~="ui-input-group"][data-v-d57b2ead]:has([aria-invalid="true"], :is(:user-invalid, [data-user-invalid])) {
4032
+ [data-component~="ui-input-group"][data-v-26a5b56d]:has([aria-invalid="true"], :is(:user-invalid, [data-user-invalid])) {
3887
4033
  border-color: var(--ui-danger-solid);
3888
4034
  }
3889
- [data-component~="ui-input-group"][data-v-d57b2ead]:has(input:is([aria-invalid="true"], :is(:user-invalid, [data-user-invalid])):focus-visible) {
4035
+ [data-component~="ui-input-group"][data-v-26a5b56d]:has(input:is([aria-invalid="true"], :is(:user-invalid, [data-user-invalid])):focus-visible) {
3890
4036
  box-shadow:
3891
4037
  var(--ui-control-inset),
3892
4038
  0 0 0 3px color-mix(in srgb, var(--ui-danger-solid) 22%, transparent);
@@ -3894,23 +4040,23 @@ svg[data-v-006fa1b2-s] {
3894
4040
 
3895
4041
  /* Forced colors drop box shadows, so the focus ring becomes an outline. */
3896
4042
  @media (forced-colors: active) {
3897
- [data-component~="ui-input-group"][data-v-d57b2ead]:has(input:focus-visible) {
4043
+ [data-component~="ui-input-group"][data-v-26a5b56d]:has(input:focus-visible) {
3898
4044
  outline: 2px solid Highlight;
3899
4045
  outline-offset: 1px;
3900
4046
  }
3901
4047
  }
3902
- [data-component~="ui-input-group"][data-ui-input-group-state~="disabled"][data-v-d57b2ead],
3903
- [data-component~="ui-input-group"][data-v-d57b2ead]:has(input:disabled) {
4048
+ [data-component~="ui-input-group"][data-ui-input-group-state~="disabled"][data-v-26a5b56d],
4049
+ [data-component~="ui-input-group"][data-v-26a5b56d]:has(input:disabled) {
3904
4050
  background: var(--ui-control-surface-disabled, var(--ui-surface-muted));
3905
4051
  box-shadow: none;
3906
4052
  cursor: not-allowed;
3907
4053
  }
3908
- .field[data-v-d57b2ead] {
4054
+ .field[data-v-26a5b56d] {
3909
4055
  display: flex;
3910
4056
  flex: 1;
3911
4057
  min-inline-size: 0;
3912
4058
  }
3913
- .affix[data-v-d57b2ead] {
4059
+ .affix[data-v-26a5b56d] {
3914
4060
  display: inline-flex;
3915
4061
  flex: none;
3916
4062
  align-items: center;
@@ -3923,19 +4069,19 @@ svg[data-v-006fa1b2-s] {
3923
4069
 
3924
4070
  /* Centred rather than padded above and below: the group is exactly a lone Input's height, so a
3925
4071
  small button sits inside it with the difference split evenly, and the field keeps its height. */
3926
- .action[data-v-d57b2ead] {
4072
+ .action[data-v-26a5b56d] {
3927
4073
  display: flex;
3928
4074
  flex: none;
3929
4075
  align-items: center;
3930
4076
  padding-inline: var(--ui-space-1);
3931
4077
  }
3932
- .affix[data-v-d57b2ead]:empty,
3933
- .action[data-v-d57b2ead]:empty {
4078
+ .affix[data-v-26a5b56d]:empty,
4079
+ .action[data-v-26a5b56d]:empty {
3934
4080
  display: none;
3935
4081
  }
3936
4082
 
3937
4083
  /* A component that sets its display still honours the hidden attribute on its root. */
3938
- [data-component~="ui-input-group"][hidden][data-v-d57b2ead] {
4084
+ [data-component~="ui-input-group"][hidden][data-v-26a5b56d] {
3939
4085
  display: none;
3940
4086
  }
3941
4087
 
@@ -4561,7 +4707,7 @@ svg[data-v-006fa1b2-s] {
4561
4707
  syntax: "*";
4562
4708
  inherits: false;
4563
4709
  }
4564
- [data-component~="ui-radio"][data-v-293c00d6] {
4710
+ [data-component~="ui-radio"][data-v-02111ebf] {
4565
4711
  /* Hooks do not inherit, so the parts below read them from the root. */
4566
4712
  --_ui-radio-size: var(--ui-radio-size);
4567
4713
 
@@ -4574,25 +4720,25 @@ svg[data-v-006fa1b2-s] {
4574
4720
  }
4575
4721
 
4576
4722
  /* The label, and under it an optional line saying what the choice means. */
4577
- .text[data-v-293c00d6] {
4723
+ .text[data-v-02111ebf] {
4578
4724
  display: flex;
4579
4725
  flex-direction: column;
4580
4726
  gap: var(--ui-space-1);
4581
4727
  min-inline-size: 0;
4582
4728
  }
4583
- .label[data-v-293c00d6] {
4729
+ .label[data-v-02111ebf] {
4584
4730
  min-inline-size: 0;
4585
4731
  line-height: var(--ui-line-height-md);
4586
4732
  }
4587
- .description[data-v-293c00d6] {
4733
+ .description[data-v-02111ebf] {
4588
4734
  color: var(--ui-text-secondary);
4589
4735
  font-size: var(--ui-font-size-sm);
4590
4736
  line-height: var(--ui-line-height);
4591
4737
  }
4592
- .description[data-v-293c00d6]:empty {
4738
+ .description[data-v-02111ebf]:empty {
4593
4739
  display: none;
4594
4740
  }
4595
- input[data-v-293c00d6] {
4741
+ input[data-v-02111ebf] {
4596
4742
  flex: 0 0 auto;
4597
4743
  inline-size: var(--_ui-radio-size, 1.125rem);
4598
4744
  block-size: var(--_ui-radio-size, 1.125rem);
@@ -4600,20 +4746,47 @@ input[data-v-293c00d6] {
4600
4746
  accent-color: var(--ui-accent-solid);
4601
4747
  cursor: pointer;
4602
4748
  }
4603
- input[data-v-293c00d6]:focus-visible {
4749
+ input[data-v-02111ebf]:focus-visible {
4604
4750
  outline: 2px solid var(--ui-focus-ring, var(--ui-accent-solid));
4605
4751
  outline-offset: 2px;
4606
4752
  }
4607
- [data-component~="ui-radio"][data-ui-radio-state~="disabled"][data-v-293c00d6] {
4753
+ [data-component~="ui-radio"][data-ui-radio-state~="disabled"][data-v-02111ebf] {
4608
4754
  color: var(--ui-disabled-text);
4609
4755
  cursor: not-allowed;
4610
4756
  }
4611
- [data-component~="ui-radio"][data-ui-radio-state~="disabled"] input[data-v-293c00d6] {
4757
+ [data-component~="ui-radio"][data-ui-radio-state~="disabled"] input[data-v-02111ebf] {
4612
4758
  cursor: not-allowed;
4613
4759
  }
4614
4760
 
4761
+ /* A sized choice keeps its box and aligns instead: the label takes that size's field type size,
4762
+ and the first line centres in that control height, so the label shares a row's baseline.
4763
+ Multi-line labels and descriptions still grow downward from that first line. */
4764
+ [data-component~="ui-radio"][data-ui-radio-state~="size=sm"][data-v-02111ebf] {
4765
+ --_font: var(--ui-font-size-sm);
4766
+ --_row: var(--ui-control-size-sm);
4767
+ }
4768
+ [data-component~="ui-radio"][data-ui-radio-state~="size=lg"][data-v-02111ebf] {
4769
+ --_font: var(--ui-font-size-md);
4770
+ --_row: var(--ui-control-size-lg);
4771
+ }
4772
+ [data-component~="ui-radio"][data-ui-radio-state~="size=sm"][data-v-02111ebf],
4773
+ [data-component~="ui-radio"][data-ui-radio-state~="size=lg"][data-v-02111ebf] {
4774
+ --_line: calc(var(--_font) * var(--ui-line-height-md));
4775
+ font-size: var(--_font);
4776
+ padding-block: calc((var(--_row) - var(--_line)) / 2);
4777
+ }
4778
+ [data-component~="ui-radio"][data-ui-radio-state~="size=sm"] input[data-v-02111ebf],
4779
+ [data-component~="ui-radio"][data-ui-radio-state~="size=lg"] input[data-v-02111ebf] {
4780
+ margin-top: calc((var(--_line) - var(--_ui-radio-size, 1.125rem)) / 2);
4781
+ }
4782
+ @media (pointer: coarse) {
4783
+ [data-component~="ui-radio"][data-ui-radio-state~="size=sm"][data-v-02111ebf] {
4784
+ --_row: var(--ui-control-min-block-size);
4785
+ }
4786
+ }
4787
+
4615
4788
  /* A component that sets its display still honours the hidden attribute on its root. */
4616
- [data-component~="ui-radio"][hidden][data-v-293c00d6] {
4789
+ [data-component~="ui-radio"][hidden][data-v-02111ebf] {
4617
4790
  display: none;
4618
4791
  }
4619
4792
 
@@ -5178,7 +5351,7 @@ dialog[data-v-40145d41] {
5178
5351
  syntax: "*";
5179
5352
  inherits: false;
5180
5353
  }
5181
- [data-component~="ui-select"][data-v-57618b8b] {
5354
+ [data-component~="ui-select"][data-v-c81ec3d9] {
5182
5355
  box-sizing: border-box;
5183
5356
  display: inline-block;
5184
5357
  inline-size: 100%;
@@ -5202,7 +5375,7 @@ dialog[data-v-40145d41] {
5202
5375
 
5203
5376
  /* The select draws its own chevron: the native caret cannot be inset or sized consistently.
5204
5377
  * The root stays a native <s-lect>, so the icon is a background image rather than an element. */
5205
- [data-component~="ui-select"][data-v-57618b8b] {
5378
+ [data-component~="ui-select"][data-v-c81ec3d9] {
5206
5379
  appearance: none;
5207
5380
  padding-inline-end: calc(var(--ui-space-3) + 1.5rem);
5208
5381
  background-image: var(
@@ -5213,10 +5386,10 @@ dialog[data-v-40145d41] {
5213
5386
  background-position: right var(--ui-space-3) center;
5214
5387
  background-size: 1.125rem 1.125rem;
5215
5388
  }
5216
- [data-component~="ui-select"][data-v-57618b8b]:hover:not(:focus):not(:disabled) {
5389
+ [data-component~="ui-select"][data-v-c81ec3d9]:hover:not(:focus):not(:disabled) {
5217
5390
  border-color: var(--ui-control-border-hover, var(--ui-text-secondary));
5218
5391
  }
5219
- [data-component~="ui-select"][data-v-57618b8b]:focus-visible {
5392
+ [data-component~="ui-select"][data-v-c81ec3d9]:focus-visible {
5220
5393
  border-color: var(--ui-control-focus, var(--ui-accent-solid));
5221
5394
  outline: none;
5222
5395
  box-shadow: var(
@@ -5227,28 +5400,48 @@ dialog[data-v-40145d41] {
5227
5400
  }
5228
5401
 
5229
5402
  /* The app's invalid flag, or the browser's own verdict once the user has left an invalid field. */
5230
- [data-component~="ui-select"][aria-invalid="true"][data-v-57618b8b],
5231
- [data-component~="ui-select"][data-v-57618b8b]:is(:user-invalid, [data-user-invalid]) {
5403
+ [data-component~="ui-select"][aria-invalid="true"][data-v-c81ec3d9],
5404
+ [data-component~="ui-select"][data-v-c81ec3d9]:is(:user-invalid, [data-user-invalid]) {
5232
5405
  border-color: var(--ui-danger-solid);
5233
5406
  }
5234
- [data-component~="ui-select"][data-v-57618b8b]:is([aria-invalid="true"], :is(:user-invalid, [data-user-invalid])):focus-visible {
5407
+ [data-component~="ui-select"][data-v-c81ec3d9]:is([aria-invalid="true"], :is(:user-invalid, [data-user-invalid])):focus-visible {
5235
5408
  box-shadow:
5236
5409
  var(--ui-control-inset),
5237
5410
  0 0 0 3px color-mix(in srgb, var(--ui-danger-solid) 22%, transparent);
5238
5411
  }
5239
- [data-component~="ui-select"][data-v-57618b8b]:disabled {
5412
+ [data-component~="ui-select"][data-v-c81ec3d9]:disabled {
5240
5413
  background-color: var(--ui-control-surface-disabled, var(--ui-surface-muted));
5241
5414
  color: var(--ui-disabled-text);
5242
5415
  box-shadow: none;
5243
5416
  cursor: not-allowed;
5244
5417
  }
5245
- [data-component~="ui-select"][size][data-v-57618b8b]:not([size="1"]) {
5246
- min-block-size: 7rem;
5247
- padding: var(--ui-space-2);
5418
+ [data-component~="ui-select"][data-ui-select-state~="size=sm"][data-v-c81ec3d9] {
5419
+ min-block-size: var(--ui-control-size-sm);
5420
+ padding: var(--ui-space-1) var(--ui-space-2);
5421
+ padding-inline-end: calc(var(--ui-space-2) + var(--ui-icon-size-sm) + var(--ui-space-1));
5422
+ background-position: right var(--ui-space-2) center;
5423
+ background-size: var(--ui-icon-size-sm) var(--ui-icon-size-sm);
5424
+ font-size: var(--ui-font-size-sm);
5425
+ }
5426
+ [data-component~="ui-select"][data-ui-select-state~="size=lg"][data-v-c81ec3d9] {
5427
+ min-block-size: var(--ui-control-size-lg);
5428
+ padding: var(--ui-space-3) var(--ui-space-4);
5429
+ padding-inline-end: calc(var(--ui-space-4) + 1.5rem);
5430
+ background-position: right var(--ui-space-4) center;
5431
+ font-size: var(--ui-font-size-md);
5432
+ }
5433
+
5434
+ /* Under touch a small field is still a touch-sized target, as a small button is, and keeps
5435
+ body-size text: below 16px, iOS zooms the page into the focused field. */
5436
+ @media (pointer: coarse) {
5437
+ [data-component~="ui-select"][data-ui-select-state~="size=sm"][data-v-c81ec3d9] {
5438
+ min-block-size: var(--ui-control-min-block-size);
5439
+ font-size: inherit;
5440
+ }
5248
5441
  }
5249
5442
 
5250
5443
  /* A component that sets its display still honours the hidden attribute on its root. */
5251
- [data-component~="ui-select"][hidden][data-v-57618b8b] {
5444
+ [data-component~="ui-select"][hidden][data-v-c81ec3d9] {
5252
5445
  display: none;
5253
5446
  }
5254
5447
 
@@ -5606,7 +5799,7 @@ to {
5606
5799
  syntax: "*";
5607
5800
  inherits: false;
5608
5801
  }
5609
- [data-component~="ui-switch"][data-v-98e06e1e] {
5802
+ [data-component~="ui-switch"][data-v-87fc218c] {
5610
5803
  /* Hooks do not inherit, so the parts below read them from the root. */
5611
5804
  --_ui-switch-track-width: var(--ui-switch-track-width);
5612
5805
  --_ui-switch-track-height: var(--ui-switch-track-height);
@@ -5620,25 +5813,25 @@ to {
5620
5813
  }
5621
5814
 
5622
5815
  /* The label, and under it an optional line saying what the choice means. */
5623
- .text[data-v-98e06e1e] {
5816
+ .text[data-v-87fc218c] {
5624
5817
  display: flex;
5625
5818
  flex-direction: column;
5626
5819
  gap: var(--ui-space-1);
5627
5820
  min-inline-size: 0;
5628
5821
  }
5629
- .label[data-v-98e06e1e] {
5822
+ .label[data-v-87fc218c] {
5630
5823
  min-inline-size: 0;
5631
5824
  line-height: var(--ui-line-height-md);
5632
5825
  }
5633
- .description[data-v-98e06e1e] {
5826
+ .description[data-v-87fc218c] {
5634
5827
  color: var(--ui-text-secondary);
5635
5828
  font-size: var(--ui-font-size-sm);
5636
5829
  line-height: var(--ui-line-height);
5637
5830
  }
5638
- .description[data-v-98e06e1e]:empty {
5831
+ .description[data-v-87fc218c]:empty {
5639
5832
  display: none;
5640
5833
  }
5641
- input[data-v-98e06e1e] {
5834
+ input[data-v-87fc218c] {
5642
5835
  appearance: none;
5643
5836
  -webkit-appearance: none;
5644
5837
  position: relative;
@@ -5656,7 +5849,7 @@ input[data-v-98e06e1e] {
5656
5849
  border-color var(--ui-motion-fast) var(--ui-motion-ease);
5657
5850
  margin: 0;
5658
5851
  }
5659
- input[data-v-98e06e1e]::after {
5852
+ input[data-v-87fc218c]::after {
5660
5853
  content: "";
5661
5854
  position: absolute;
5662
5855
  top: 3px;
@@ -5668,35 +5861,64 @@ input[data-v-98e06e1e]::after {
5668
5861
  box-shadow: var(--ui-shadow-xs);
5669
5862
  transition: transform var(--ui-motion-fast) var(--ui-motion-ease);
5670
5863
  }
5671
- input[data-v-98e06e1e]:checked {
5864
+ input[data-v-87fc218c]:checked {
5672
5865
  background: var(--ui-accent-solid);
5673
5866
  border-color: var(--ui-accent-solid);
5674
5867
  }
5675
- input[data-v-98e06e1e]:checked::after {
5868
+ input[data-v-87fc218c]:checked::after {
5676
5869
  transform: translateX(1rem);
5677
5870
  background: var(--ui-text-on-accent);
5678
5871
  }
5679
- input[data-v-98e06e1e]:focus-visible {
5872
+ input[data-v-87fc218c]:focus-visible {
5680
5873
  outline: 2px solid var(--ui-focus-ring, var(--ui-accent-solid));
5681
5874
  outline-offset: 2px;
5682
5875
  }
5683
- [data-component~="ui-switch"][data-ui-switch-state~="disabled"][data-v-98e06e1e] {
5876
+ [data-component~="ui-switch"][data-ui-switch-state~="disabled"][data-v-87fc218c] {
5684
5877
  color: var(--ui-disabled-text);
5685
5878
  cursor: not-allowed;
5686
5879
  }
5687
- [data-component~="ui-switch"][data-ui-switch-state~="disabled"] input[data-v-98e06e1e] {
5880
+ [data-component~="ui-switch"][data-ui-switch-state~="disabled"] input[data-v-87fc218c] {
5688
5881
  border-color: var(--ui-border-default);
5689
5882
  background: var(--ui-control-surface-disabled, var(--ui-surface-muted));
5690
5883
  cursor: not-allowed;
5691
5884
  }
5692
5885
  @media (prefers-reduced-motion: reduce) {
5693
- input[data-v-98e06e1e], input[data-v-98e06e1e]::after {
5886
+ input[data-v-87fc218c], input[data-v-87fc218c]::after {
5694
5887
  transition: none;
5695
5888
  }
5696
5889
  }
5697
5890
 
5891
+ /* A sized switch keeps its track and aligns instead: the label takes that size's field type size,
5892
+ and the first line centres in that control height, so the label shares a row's baseline.
5893
+ Multi-line labels and descriptions still grow downward from that first line. */
5894
+ [data-component~="ui-switch"][data-ui-switch-state~="size=sm"][data-v-87fc218c] {
5895
+ --_font: var(--ui-font-size-sm);
5896
+ --_row: var(--ui-control-size-sm);
5897
+ }
5898
+ [data-component~="ui-switch"][data-ui-switch-state~="size=lg"][data-v-87fc218c] {
5899
+ --_font: var(--ui-font-size-md);
5900
+ --_row: var(--ui-control-size-lg);
5901
+ }
5902
+ [data-component~="ui-switch"][data-ui-switch-state~="size=sm"][data-v-87fc218c],
5903
+ [data-component~="ui-switch"][data-ui-switch-state~="size=lg"][data-v-87fc218c] {
5904
+ --_line: calc(var(--_font) * var(--ui-line-height-md));
5905
+ font-size: var(--_font);
5906
+ padding-block: calc((var(--_row) - var(--ui-switch-track-height, 1.5rem)) / 2);
5907
+ }
5908
+
5909
+ /* The label centres on the track. */
5910
+ [data-component~="ui-switch"][data-ui-switch-state~="size=sm"] .text[data-v-87fc218c],
5911
+ [data-component~="ui-switch"][data-ui-switch-state~="size=lg"] .text[data-v-87fc218c] {
5912
+ margin-top: calc((var(--_ui-switch-track-height, 1.5rem) - var(--_line)) / 2);
5913
+ }
5914
+ @media (pointer: coarse) {
5915
+ [data-component~="ui-switch"][data-ui-switch-state~="size=sm"][data-v-87fc218c] {
5916
+ --_row: var(--ui-control-min-block-size);
5917
+ }
5918
+ }
5919
+
5698
5920
  /* A component that sets its display still honours the hidden attribute on its root. */
5699
- [data-component~="ui-switch"][hidden][data-v-98e06e1e] {
5921
+ [data-component~="ui-switch"][hidden][data-v-87fc218c] {
5700
5922
  display: none;
5701
5923
  }
5702
5924
 
@@ -5766,6 +5988,117 @@ input[data-v-98e06e1e], input[data-v-98e06e1e]::after {
5766
5988
  display: none;
5767
5989
  }
5768
5990
 
5991
+ /* Styles an authored <table> (caption, thead, tbody, th scope) without replacing it: the table is
5992
+ meaningful before JavaScript, and a screen reader reads it as a table. The root scrolls a table
5993
+ wider than it, or taller than a bounded height; while it does, the controller makes the root a named, focusable region so a
5994
+ keyboard can scroll it. A cell's data-ui-align (start, center, or end; start by default) sets its
5995
+ content along the row, such as end for a column of figures. */
5996
+ [data-component~="ui-table"][data-v-9980d203] {
5997
+ --_pad-block: var(--ui-space-1);
5998
+ --_pad-inline: var(--ui-space-3);
5999
+ --_row-size: var(--ui-control-size);
6000
+ display: block;
6001
+ box-sizing: border-box;
6002
+ max-inline-size: 100%;
6003
+ min-inline-size: 0;
6004
+ min-block-size: 0;
6005
+ overflow: auto;
6006
+ overscroll-behavior-inline: contain;
6007
+ /* The sideways scroll fade every Looma scroller uses (see ui-scroll-area). Only the inline edges
6008
+ fade, so a sticky header never fades. */
6009
+ --_ui-scroll-fade-direction: to right;
6010
+ --_ui-scroll-fade-size: var(--ui-scroll-fade-size, 24px);
6011
+ mask-image: linear-gradient(
6012
+ var(--_ui-scroll-fade-direction),
6013
+ transparent,
6014
+ #000 var(--_ui-scroll-fade-start),
6015
+ #000 calc(100% - var(--_ui-scroll-fade-end)),
6016
+ transparent
6017
+ );
6018
+ animation:
6019
+ ui-scroll-fade-start linear,
6020
+ ui-scroll-fade-start-hold linear,
6021
+ ui-scroll-fade-end-hold linear,
6022
+ ui-scroll-fade-end linear;
6023
+ animation-timeline: scroll(self inline);
6024
+ animation-range:
6025
+ 0 var(--_ui-scroll-fade-size),
6026
+ var(--_ui-scroll-fade-size) calc(100% + 1px),
6027
+ -1px calc(100% - var(--_ui-scroll-fade-size)),
6028
+ calc(100% - var(--_ui-scroll-fade-size)) 100%;
6029
+ }
6030
+ [data-component~="ui-table"][data-v-9980d203]:dir(rtl) {
6031
+ --_ui-scroll-fade-direction: to left;
6032
+ }
6033
+ [data-component~="ui-table"][data-v-9980d203]:focus-visible {
6034
+ outline: 2px solid var(--ui-focus-ring);
6035
+ outline-offset: -2px;
6036
+ }
6037
+ [data-component~="ui-table"][data-ui-table-state~="density=compact"][data-v-9980d203] {
6038
+ --_pad-block: var(--ui-space-0-5);
6039
+ --_pad-inline: var(--ui-space-2);
6040
+ --_row-size: var(--ui-control-size-sm);
6041
+ }
6042
+
6043
+ /* Separate borders stay on their cells when a sticky header scrolls; collapsed ones stay behind. */
6044
+ table[data-v-9980d203-s] {
6045
+ inline-size: 100%;
6046
+ border-collapse: separate;
6047
+ border-spacing: 0;
6048
+ color: var(--ui-text-primary);
6049
+ font-size: var(--ui-font-size-sm);
6050
+ line-height: var(--ui-line-height);
6051
+ font-variant-numeric: tabular-nums;
6052
+ }
6053
+ caption[data-v-9980d203-s] {
6054
+ padding-block-end: var(--ui-space-2);
6055
+ color: var(--ui-text-secondary);
6056
+ font-weight: var(--ui-font-medium);
6057
+ text-align: start;
6058
+ }
6059
+
6060
+ /* Every row is at least one control tall, so a row holding a checkbox, select, or input keeps the
6061
+ rhythm of the rows around it. A cell's height is its minimum. */
6062
+ th[data-v-9980d203-s],td[data-v-9980d203-s] {
6063
+ block-size: var(--_row-size);
6064
+ padding: var(--_pad-block) var(--_pad-inline);
6065
+ border-block-end: 1px solid var(--ui-border-subtle);
6066
+ text-align: start;
6067
+ vertical-align: middle;
6068
+ }
6069
+ thead th[data-v-9980d203-s] {
6070
+ block-size: auto;
6071
+ padding-block: var(--ui-space-2);
6072
+ border-block-end-color: var(--ui-border-default);
6073
+ background: var(--ui-surface);
6074
+ color: var(--ui-text-muted);
6075
+ font-weight: var(--ui-font-medium);
6076
+ white-space: nowrap;
6077
+ vertical-align: bottom;
6078
+ }
6079
+ tbody th[data-v-9980d203-s] {
6080
+ font-weight: var(--ui-font-medium);
6081
+ }
6082
+ tbody tr[data-v-9980d203-s]:last-child > * {
6083
+ border-block-end-width: 0;
6084
+ }
6085
+ [data-ui-align="center"][data-v-9980d203-s] {
6086
+ text-align: center;
6087
+ }
6088
+ [data-ui-align="end"][data-v-9980d203-s] {
6089
+ text-align: end;
6090
+ }
6091
+ [data-component~="ui-table"][data-ui-table-state~="stickyHeader"] thead th[data-v-9980d203-s] {
6092
+ position: sticky;
6093
+ inset-block-start: 0;
6094
+ z-index: 1;
6095
+ }
6096
+
6097
+ /* A component that sets its display still honours the hidden attribute on its root. */
6098
+ [data-component~="ui-table"][hidden][data-v-9980d203] {
6099
+ display: none;
6100
+ }
6101
+
5769
6102
  /* This component's hooks style the element they are set on, and never a nested one. */
5770
6103
  @property --ui-tabs-tab-min-block-size {
5771
6104
  syntax: "*";
@@ -5999,7 +6332,7 @@ input[data-v-98e06e1e], input[data-v-98e06e1e]::after {
5999
6332
  syntax: "*";
6000
6333
  inherits: false;
6001
6334
  }
6002
- [data-component~="ui-textarea"][data-v-73461aaf] {
6335
+ [data-component~="ui-textarea"][data-v-00f7b2fd] {
6003
6336
  box-sizing: border-box;
6004
6337
  display: inline-block;
6005
6338
  inline-size: 100%;
@@ -6023,18 +6356,18 @@ input[data-v-98e06e1e], input[data-v-98e06e1e]::after {
6023
6356
  }
6024
6357
 
6025
6358
  /* Tabbing into a field selects its text; tint that selection softly instead of the page highlight. */
6026
- [data-component~="ui-textarea"][data-v-73461aaf]::selection {
6359
+ [data-component~="ui-textarea"][data-v-00f7b2fd]::selection {
6027
6360
  background: color-mix(in srgb, var(--ui-accent-solid) 20%, transparent);
6028
6361
  color: inherit;
6029
6362
  }
6030
- [data-component~="ui-textarea"][data-v-73461aaf]::placeholder {
6363
+ [data-component~="ui-textarea"][data-v-00f7b2fd]::placeholder {
6031
6364
  color: var(--ui-control-placeholder, var(--ui-text-secondary));
6032
6365
  opacity: 1;
6033
6366
  }
6034
- [data-component~="ui-textarea"][data-v-73461aaf]:hover:not(:focus):not(:disabled) {
6367
+ [data-component~="ui-textarea"][data-v-00f7b2fd]:hover:not(:focus):not(:disabled) {
6035
6368
  border-color: var(--ui-control-border-hover, var(--ui-text-secondary));
6036
6369
  }
6037
- [data-component~="ui-textarea"][data-v-73461aaf]:focus-visible {
6370
+ [data-component~="ui-textarea"][data-v-00f7b2fd]:focus-visible {
6038
6371
  border-color: var(--ui-control-focus, var(--ui-accent-solid));
6039
6372
  outline: none;
6040
6373
  box-shadow: var(
@@ -6045,24 +6378,39 @@ input[data-v-98e06e1e], input[data-v-98e06e1e]::after {
6045
6378
  }
6046
6379
 
6047
6380
  /* The app's invalid flag, or the browser's own verdict once the user has left an invalid field. */
6048
- [data-component~="ui-textarea"][aria-invalid="true"][data-v-73461aaf],
6049
- [data-component~="ui-textarea"][data-v-73461aaf]:is(:user-invalid, [data-user-invalid]) {
6381
+ [data-component~="ui-textarea"][aria-invalid="true"][data-v-00f7b2fd],
6382
+ [data-component~="ui-textarea"][data-v-00f7b2fd]:is(:user-invalid, [data-user-invalid]) {
6050
6383
  border-color: var(--ui-danger-solid);
6051
6384
  }
6052
- [data-component~="ui-textarea"][data-v-73461aaf]:is([aria-invalid="true"], :is(:user-invalid, [data-user-invalid])):focus-visible {
6385
+ [data-component~="ui-textarea"][data-v-00f7b2fd]:is([aria-invalid="true"], :is(:user-invalid, [data-user-invalid])):focus-visible {
6053
6386
  box-shadow:
6054
6387
  var(--ui-control-inset),
6055
6388
  0 0 0 3px color-mix(in srgb, var(--ui-danger-solid) 22%, transparent);
6056
6389
  }
6057
- [data-component~="ui-textarea"][data-v-73461aaf]:disabled {
6390
+ [data-component~="ui-textarea"][data-v-00f7b2fd]:disabled {
6058
6391
  background: var(--ui-control-surface-disabled, var(--ui-surface-muted));
6059
6392
  color: var(--ui-disabled-text);
6060
6393
  box-shadow: none;
6061
6394
  cursor: not-allowed;
6062
6395
  }
6396
+ [data-component~="ui-textarea"][data-ui-textarea-state~="size=sm"][data-v-00f7b2fd] {
6397
+ padding: var(--ui-space-1) var(--ui-space-2);
6398
+ font-size: var(--ui-font-size-sm);
6399
+ }
6400
+ [data-component~="ui-textarea"][data-ui-textarea-state~="size=lg"][data-v-00f7b2fd] {
6401
+ padding: var(--ui-space-3) var(--ui-space-4);
6402
+ font-size: var(--ui-font-size-md);
6403
+ }
6404
+
6405
+ /* Below 16px, iOS zooms the page into the focused field, so touch keeps body-size text. */
6406
+ @media (pointer: coarse) {
6407
+ [data-component~="ui-textarea"][data-ui-textarea-state~="size=sm"][data-v-00f7b2fd] {
6408
+ font-size: inherit;
6409
+ }
6410
+ }
6063
6411
 
6064
6412
  /* A component that sets its display still honours the hidden attribute on its root. */
6065
- [data-component~="ui-textarea"][hidden][data-v-73461aaf] {
6413
+ [data-component~="ui-textarea"][hidden][data-v-00f7b2fd] {
6066
6414
  display: none;
6067
6415
  }
6068
6416