@threadlabs/looma 0.13.5 → 0.14.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 (65) 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-icon/ui-icon.html +67 -7
  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-textarea/ui-textarea.html +20 -0
  11. package/dist/index.js +17 -18
  12. package/package.json +1 -1
  13. package/styles/ui-button.css +3 -1
  14. package/styles/ui-checkbox.css +38 -0
  15. package/styles/ui-combobox.css +38 -1
  16. package/styles/ui-input-group.css +20 -0
  17. package/styles/ui-input.css +29 -0
  18. package/styles/ui-radio.css +38 -0
  19. package/styles/ui-select.css +29 -3
  20. package/styles/ui-switch.css +41 -0
  21. package/styles/ui-textarea.css +21 -0
  22. package/vanilla/UiCheckbox.d.ts +1 -0
  23. package/vanilla/UiCheckbox.js +1 -1
  24. package/vanilla/UiCombobox.d.ts +1 -1
  25. package/vanilla/UiCombobox.js +1 -1
  26. package/vanilla/UiIcon.js +1 -3
  27. package/vanilla/UiInput.d.ts +1 -0
  28. package/vanilla/UiInput.js +1 -1
  29. package/vanilla/UiRadio.d.ts +1 -0
  30. package/vanilla/UiRadio.js +1 -1
  31. package/vanilla/UiSelect.d.ts +1 -0
  32. package/vanilla/UiSelect.js +1 -1
  33. package/vanilla/UiSwitch.d.ts +1 -0
  34. package/vanilla/UiSwitch.js +1 -1
  35. package/vanilla/UiTextarea.d.ts +1 -0
  36. package/vanilla/UiTextarea.js +1 -1
  37. package/vue/UiButton.vue +2 -1
  38. package/vue/UiCheckbox.d.ts +2 -0
  39. package/vue/UiCheckbox.vue +34 -0
  40. package/vue/UiCombobox.d.ts +2 -2
  41. package/vue/UiCombobox.vue +39 -2
  42. package/vue/UiIcon.vue +337 -42
  43. package/vue/UiInput.d.ts +2 -0
  44. package/vue/UiInput.vue +41 -0
  45. package/vue/UiInputGroup.vue +15 -0
  46. package/vue/UiRadio.d.ts +2 -0
  47. package/vue/UiRadio.vue +34 -0
  48. package/vue/UiSelect.d.ts +2 -0
  49. package/vue/UiSelect.vue +34 -3
  50. package/vue/UiSwitch.d.ts +2 -0
  51. package/vue/UiSwitch.vue +35 -0
  52. package/vue/UiTextarea.d.ts +2 -0
  53. package/vue/UiTextarea.vue +27 -0
  54. package/vue/chunks/UiButton.js +1 -1
  55. package/vue/chunks/UiCheckbox.js +3 -2
  56. package/vue/chunks/UiCombobox.js +1 -1
  57. package/vue/chunks/UiIcon.js +950 -32
  58. package/vue/chunks/UiInput.js +7 -2
  59. package/vue/chunks/UiInputGroup.js +1 -1
  60. package/vue/chunks/UiRadio.js +3 -2
  61. package/vue/chunks/UiSelect.js +7 -2
  62. package/vue/chunks/UiSwitch.js +3 -2
  63. package/vue/chunks/UiTextarea.js +7 -2
  64. package/vue/components.css +368 -168
  65. package/components/ui-icon/ui-icon.js +0 -8
@@ -398,7 +398,7 @@
398
398
  syntax: "*";
399
399
  inherits: false;
400
400
  }
401
- [data-component~="ui-icon"][data-v-0a5aa1a0] {
401
+ [data-component~="ui-icon"][data-v-fdb8162b] {
402
402
  /* Hooks do not inherit, so the svg reads the stroke from the root. A Looma component that
403
403
  sizes the icons it renders sets --_ui-default-icon-*, which the icon's own hooks override. */
404
404
  --_ui-icon-stroke-width: var(--ui-icon-stroke-width, var(--_ui-default-icon-stroke-width));
@@ -408,14 +408,14 @@
408
408
  inline-size: var(--ui-icon-size, var(--_ui-default-icon-size, 1em));
409
409
  block-size: var(--ui-icon-size, var(--_ui-default-icon-size, 1em));
410
410
  }
411
- svg[data-v-0a5aa1a0] {
411
+ svg[data-v-fdb8162b] {
412
412
  inline-size: 100%;
413
413
  block-size: 100%;
414
414
  stroke-width: var(--_ui-icon-stroke-width, 2);
415
415
  }
416
416
 
417
417
  /* A component that sets its display still honours the hidden attribute on its root. */
418
- [data-component~="ui-icon"][hidden][data-v-0a5aa1a0] {
418
+ [data-component~="ui-icon"][hidden][data-v-fdb8162b] {
419
419
  display: none;
420
420
  }
421
421
 
@@ -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
 
@@ -3722,7 +3788,7 @@ svg[data-v-006fa1b2-s] {
3722
3788
  syntax: "*";
3723
3789
  inherits: false;
3724
3790
  }
3725
- [data-component~="ui-input"][data-v-e1edefb2] {
3791
+ [data-component~="ui-input"][data-v-4ba095d3] {
3726
3792
  box-sizing: border-box;
3727
3793
  display: inline-block;
3728
3794
  inline-size: 100%;
@@ -3754,22 +3820,52 @@ svg[data-v-006fa1b2-s] {
3754
3820
  background-color var(--ui-motion-fast) var(--ui-motion-ease);
3755
3821
  }
3756
3822
 
3823
+ /* Each size reads the hook and then an Input Group's default first, so a group, which draws the frame, can zero it. */
3824
+ [data-component~="ui-input"][data-ui-input-state~="size=sm"][data-v-4ba095d3] {
3825
+ min-block-size: var(
3826
+ --ui-input-min-block-size,
3827
+ var(--_ui-default-input-min-block-size, var(--ui-control-size-sm))
3828
+ );
3829
+ padding: var(--ui-space-1) var(--ui-space-2);
3830
+ font-size: var(--ui-font-size-sm);
3831
+ }
3832
+ [data-component~="ui-input"][data-ui-input-state~="size=lg"][data-v-4ba095d3] {
3833
+ min-block-size: var(
3834
+ --ui-input-min-block-size,
3835
+ var(--_ui-default-input-min-block-size, var(--ui-control-size-lg))
3836
+ );
3837
+ padding: var(--ui-space-3) var(--ui-space-4);
3838
+ font-size: var(--ui-font-size-md);
3839
+ }
3840
+
3841
+ /* Under touch a small field is still a touch-sized target, as a small button is, and keeps
3842
+ body-size text: below 16px, iOS zooms the page into the focused field. */
3843
+ @media (pointer: coarse) {
3844
+ [data-component~="ui-input"][data-ui-input-state~="size=sm"][data-v-4ba095d3] {
3845
+ min-block-size: var(
3846
+ --ui-input-min-block-size,
3847
+ var(--_ui-default-input-min-block-size, var(--ui-control-min-block-size))
3848
+ );
3849
+ font-size: inherit;
3850
+ }
3851
+ }
3852
+
3757
3853
  /* 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 {
3854
+ [data-component~="ui-input"][data-v-4ba095d3]::selection {
3759
3855
  background: color-mix(in srgb, var(--ui-accent-solid) 20%, transparent);
3760
3856
  color: inherit;
3761
3857
  }
3762
- [data-component~="ui-input"][data-v-e1edefb2]::placeholder {
3858
+ [data-component~="ui-input"][data-v-4ba095d3]::placeholder {
3763
3859
  color: var(--ui-control-placeholder, var(--ui-text-secondary));
3764
3860
  opacity: 1;
3765
3861
  }
3766
- [data-component~="ui-input"][data-v-e1edefb2]:hover:not(:focus):not(:disabled) {
3862
+ [data-component~="ui-input"][data-v-4ba095d3]:hover:not(:focus):not(:disabled) {
3767
3863
  border-color: var(
3768
3864
  --ui-input-border-hover,
3769
3865
  var(--_ui-default-input-border-hover, var(--ui-control-border-hover, var(--ui-text-secondary)))
3770
3866
  );
3771
3867
  }
3772
- [data-component~="ui-input"][data-v-e1edefb2]:focus-visible {
3868
+ [data-component~="ui-input"][data-v-4ba095d3]:focus-visible {
3773
3869
  border-color: var(
3774
3870
  --ui-input-focus-border,
3775
3871
  var(--_ui-default-input-focus-border, var(--ui-control-focus, var(--ui-accent-solid)))
@@ -3786,14 +3882,14 @@ svg[data-v-006fa1b2-s] {
3786
3882
  }
3787
3883
 
3788
3884
  /* 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]) {
3885
+ [data-component~="ui-input"][aria-invalid="true"][data-v-4ba095d3],
3886
+ [data-component~="ui-input"][data-v-4ba095d3]:is(:user-invalid, [data-user-invalid]) {
3791
3887
  border-color: var(
3792
3888
  --ui-input-invalid-border,
3793
3889
  var(--_ui-default-input-invalid-border, var(--ui-danger-solid))
3794
3890
  );
3795
3891
  }
3796
- [data-component~="ui-input"][data-v-e1edefb2]:is([aria-invalid="true"], :is(:user-invalid, [data-user-invalid])):focus-visible {
3892
+ [data-component~="ui-input"][data-v-4ba095d3]:is([aria-invalid="true"], :is(:user-invalid, [data-user-invalid])):focus-visible {
3797
3893
  box-shadow: var(
3798
3894
  --ui-input-invalid-focus-shadow,
3799
3895
  var(
@@ -3803,7 +3899,7 @@ svg[data-v-006fa1b2-s] {
3803
3899
  )
3804
3900
  );
3805
3901
  }
3806
- [data-component~="ui-input"][data-v-e1edefb2]:disabled {
3902
+ [data-component~="ui-input"][data-v-4ba095d3]:disabled {
3807
3903
  background: var(--ui-control-surface-disabled, var(--ui-surface-muted));
3808
3904
  color: var(--ui-disabled-text);
3809
3905
  box-shadow: none;
@@ -3812,7 +3908,7 @@ svg[data-v-006fa1b2-s] {
3812
3908
 
3813
3909
  /* Forced colors drop box shadows, so the focus ring becomes an outline. */
3814
3910
  @media (forced-colors: active) {
3815
- [data-component~="ui-input"][data-v-e1edefb2]:focus-visible {
3911
+ [data-component~="ui-input"][data-v-4ba095d3]:focus-visible {
3816
3912
  outline: var(
3817
3913
  --ui-input-focus-outline,
3818
3914
  var(--_ui-default-input-focus-outline, 2px solid Highlight)
@@ -3825,7 +3921,7 @@ svg[data-v-006fa1b2-s] {
3825
3921
  * scroll vertically inside the field. Native inputs already center their single line. */
3826
3922
 
3827
3923
  /* A component that sets its display still honours the hidden attribute on its root. */
3828
- [data-component~="ui-input"][hidden][data-v-e1edefb2] {
3924
+ [data-component~="ui-input"][hidden][data-v-4ba095d3] {
3829
3925
  display: none;
3830
3926
  }
3831
3927
 
@@ -3837,7 +3933,7 @@ svg[data-v-006fa1b2-s] {
3837
3933
  whole value is. The action slot takes one button at the end, inside the border, for the one
3838
3934
  thing the field is for ("Continue" after a site's address), so it reads as the field's action
3839
3935
  and not the form's. */
3840
- [data-component~="ui-input-group"][data-v-d57b2ead] {
3936
+ [data-component~="ui-input-group"][data-v-26a5b56d] {
3841
3937
  /* The group's own border and height stand for the input's, so the group is a lone Input's height.
3842
3938
  Hooks do not inherit, so these are defaults for the input; its own hooks still win. */
3843
3939
  --_ui-default-input-border-width: 0;
@@ -3871,22 +3967,35 @@ svg[data-v-006fa1b2-s] {
3871
3967
  border-color var(--ui-motion-fast) var(--ui-motion-ease),
3872
3968
  box-shadow var(--ui-motion-fast) var(--ui-motion-ease);
3873
3969
  }
3874
- [data-component~="ui-input-group"][data-v-d57b2ead]:hover:not(:has(input:focus, input:disabled)) {
3970
+
3971
+ /* The frame takes its input's size, so a small group lines up with small buttons and fields. */
3972
+ [data-component~="ui-input-group"][data-v-26a5b56d]:has(.field [data-ui-input-state~="size=sm"]) {
3973
+ min-block-size: var(--ui-control-size-sm);
3974
+ }
3975
+ [data-component~="ui-input-group"][data-v-26a5b56d]:has(.field [data-ui-input-state~="size=lg"]) {
3976
+ min-block-size: var(--ui-control-size-lg);
3977
+ }
3978
+ @media (pointer: coarse) {
3979
+ [data-component~="ui-input-group"][data-v-26a5b56d]:has(.field [data-ui-input-state~="size=sm"]) {
3980
+ min-block-size: var(--ui-control-min-block-size);
3981
+ }
3982
+ }
3983
+ [data-component~="ui-input-group"][data-v-26a5b56d]:hover:not(:has(input:focus, input:disabled)) {
3875
3984
  border-color: var(--ui-control-border-hover, var(--ui-text-secondary));
3876
3985
  }
3877
3986
 
3878
3987
  /* The ring shows when the field's input would show its own: when it is focus-visible, which a
3879
3988
  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) {
3989
+ [data-component~="ui-input-group"][data-v-26a5b56d]:has(.field input:focus-visible) {
3881
3990
  border-color: var(--ui-control-focus, var(--ui-accent-solid));
3882
3991
  box-shadow:
3883
3992
  var(--ui-control-inset),
3884
3993
  var(--ui-control-focus-halo-shadow);
3885
3994
  }
3886
- [data-component~="ui-input-group"][data-v-d57b2ead]:has([aria-invalid="true"], :is(:user-invalid, [data-user-invalid])) {
3995
+ [data-component~="ui-input-group"][data-v-26a5b56d]:has([aria-invalid="true"], :is(:user-invalid, [data-user-invalid])) {
3887
3996
  border-color: var(--ui-danger-solid);
3888
3997
  }
3889
- [data-component~="ui-input-group"][data-v-d57b2ead]:has(input:is([aria-invalid="true"], :is(:user-invalid, [data-user-invalid])):focus-visible) {
3998
+ [data-component~="ui-input-group"][data-v-26a5b56d]:has(input:is([aria-invalid="true"], :is(:user-invalid, [data-user-invalid])):focus-visible) {
3890
3999
  box-shadow:
3891
4000
  var(--ui-control-inset),
3892
4001
  0 0 0 3px color-mix(in srgb, var(--ui-danger-solid) 22%, transparent);
@@ -3894,23 +4003,23 @@ svg[data-v-006fa1b2-s] {
3894
4003
 
3895
4004
  /* Forced colors drop box shadows, so the focus ring becomes an outline. */
3896
4005
  @media (forced-colors: active) {
3897
- [data-component~="ui-input-group"][data-v-d57b2ead]:has(input:focus-visible) {
4006
+ [data-component~="ui-input-group"][data-v-26a5b56d]:has(input:focus-visible) {
3898
4007
  outline: 2px solid Highlight;
3899
4008
  outline-offset: 1px;
3900
4009
  }
3901
4010
  }
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) {
4011
+ [data-component~="ui-input-group"][data-ui-input-group-state~="disabled"][data-v-26a5b56d],
4012
+ [data-component~="ui-input-group"][data-v-26a5b56d]:has(input:disabled) {
3904
4013
  background: var(--ui-control-surface-disabled, var(--ui-surface-muted));
3905
4014
  box-shadow: none;
3906
4015
  cursor: not-allowed;
3907
4016
  }
3908
- .field[data-v-d57b2ead] {
4017
+ .field[data-v-26a5b56d] {
3909
4018
  display: flex;
3910
4019
  flex: 1;
3911
4020
  min-inline-size: 0;
3912
4021
  }
3913
- .affix[data-v-d57b2ead] {
4022
+ .affix[data-v-26a5b56d] {
3914
4023
  display: inline-flex;
3915
4024
  flex: none;
3916
4025
  align-items: center;
@@ -3923,19 +4032,19 @@ svg[data-v-006fa1b2-s] {
3923
4032
 
3924
4033
  /* Centred rather than padded above and below: the group is exactly a lone Input's height, so a
3925
4034
  small button sits inside it with the difference split evenly, and the field keeps its height. */
3926
- .action[data-v-d57b2ead] {
4035
+ .action[data-v-26a5b56d] {
3927
4036
  display: flex;
3928
4037
  flex: none;
3929
4038
  align-items: center;
3930
4039
  padding-inline: var(--ui-space-1);
3931
4040
  }
3932
- .affix[data-v-d57b2ead]:empty,
3933
- .action[data-v-d57b2ead]:empty {
4041
+ .affix[data-v-26a5b56d]:empty,
4042
+ .action[data-v-26a5b56d]:empty {
3934
4043
  display: none;
3935
4044
  }
3936
4045
 
3937
4046
  /* A component that sets its display still honours the hidden attribute on its root. */
3938
- [data-component~="ui-input-group"][hidden][data-v-d57b2ead] {
4047
+ [data-component~="ui-input-group"][hidden][data-v-26a5b56d] {
3939
4048
  display: none;
3940
4049
  }
3941
4050
 
@@ -4561,7 +4670,7 @@ svg[data-v-006fa1b2-s] {
4561
4670
  syntax: "*";
4562
4671
  inherits: false;
4563
4672
  }
4564
- [data-component~="ui-radio"][data-v-293c00d6] {
4673
+ [data-component~="ui-radio"][data-v-02111ebf] {
4565
4674
  /* Hooks do not inherit, so the parts below read them from the root. */
4566
4675
  --_ui-radio-size: var(--ui-radio-size);
4567
4676
 
@@ -4574,25 +4683,25 @@ svg[data-v-006fa1b2-s] {
4574
4683
  }
4575
4684
 
4576
4685
  /* The label, and under it an optional line saying what the choice means. */
4577
- .text[data-v-293c00d6] {
4686
+ .text[data-v-02111ebf] {
4578
4687
  display: flex;
4579
4688
  flex-direction: column;
4580
4689
  gap: var(--ui-space-1);
4581
4690
  min-inline-size: 0;
4582
4691
  }
4583
- .label[data-v-293c00d6] {
4692
+ .label[data-v-02111ebf] {
4584
4693
  min-inline-size: 0;
4585
4694
  line-height: var(--ui-line-height-md);
4586
4695
  }
4587
- .description[data-v-293c00d6] {
4696
+ .description[data-v-02111ebf] {
4588
4697
  color: var(--ui-text-secondary);
4589
4698
  font-size: var(--ui-font-size-sm);
4590
4699
  line-height: var(--ui-line-height);
4591
4700
  }
4592
- .description[data-v-293c00d6]:empty {
4701
+ .description[data-v-02111ebf]:empty {
4593
4702
  display: none;
4594
4703
  }
4595
- input[data-v-293c00d6] {
4704
+ input[data-v-02111ebf] {
4596
4705
  flex: 0 0 auto;
4597
4706
  inline-size: var(--_ui-radio-size, 1.125rem);
4598
4707
  block-size: var(--_ui-radio-size, 1.125rem);
@@ -4600,20 +4709,47 @@ input[data-v-293c00d6] {
4600
4709
  accent-color: var(--ui-accent-solid);
4601
4710
  cursor: pointer;
4602
4711
  }
4603
- input[data-v-293c00d6]:focus-visible {
4712
+ input[data-v-02111ebf]:focus-visible {
4604
4713
  outline: 2px solid var(--ui-focus-ring, var(--ui-accent-solid));
4605
4714
  outline-offset: 2px;
4606
4715
  }
4607
- [data-component~="ui-radio"][data-ui-radio-state~="disabled"][data-v-293c00d6] {
4716
+ [data-component~="ui-radio"][data-ui-radio-state~="disabled"][data-v-02111ebf] {
4608
4717
  color: var(--ui-disabled-text);
4609
4718
  cursor: not-allowed;
4610
4719
  }
4611
- [data-component~="ui-radio"][data-ui-radio-state~="disabled"] input[data-v-293c00d6] {
4720
+ [data-component~="ui-radio"][data-ui-radio-state~="disabled"] input[data-v-02111ebf] {
4612
4721
  cursor: not-allowed;
4613
4722
  }
4614
4723
 
4724
+ /* A sized choice keeps its box and aligns instead: the label takes that size's field type size,
4725
+ and the first line centres in that control height, so the label shares a row's baseline.
4726
+ Multi-line labels and descriptions still grow downward from that first line. */
4727
+ [data-component~="ui-radio"][data-ui-radio-state~="size=sm"][data-v-02111ebf] {
4728
+ --_font: var(--ui-font-size-sm);
4729
+ --_row: var(--ui-control-size-sm);
4730
+ }
4731
+ [data-component~="ui-radio"][data-ui-radio-state~="size=lg"][data-v-02111ebf] {
4732
+ --_font: var(--ui-font-size-md);
4733
+ --_row: var(--ui-control-size-lg);
4734
+ }
4735
+ [data-component~="ui-radio"][data-ui-radio-state~="size=sm"][data-v-02111ebf],
4736
+ [data-component~="ui-radio"][data-ui-radio-state~="size=lg"][data-v-02111ebf] {
4737
+ --_line: calc(var(--_font) * var(--ui-line-height-md));
4738
+ font-size: var(--_font);
4739
+ padding-block: calc((var(--_row) - var(--_line)) / 2);
4740
+ }
4741
+ [data-component~="ui-radio"][data-ui-radio-state~="size=sm"] input[data-v-02111ebf],
4742
+ [data-component~="ui-radio"][data-ui-radio-state~="size=lg"] input[data-v-02111ebf] {
4743
+ margin-top: calc((var(--_line) - var(--_ui-radio-size, 1.125rem)) / 2);
4744
+ }
4745
+ @media (pointer: coarse) {
4746
+ [data-component~="ui-radio"][data-ui-radio-state~="size=sm"][data-v-02111ebf] {
4747
+ --_row: var(--ui-control-min-block-size);
4748
+ }
4749
+ }
4750
+
4615
4751
  /* A component that sets its display still honours the hidden attribute on its root. */
4616
- [data-component~="ui-radio"][hidden][data-v-293c00d6] {
4752
+ [data-component~="ui-radio"][hidden][data-v-02111ebf] {
4617
4753
  display: none;
4618
4754
  }
4619
4755
 
@@ -5178,7 +5314,7 @@ dialog[data-v-40145d41] {
5178
5314
  syntax: "*";
5179
5315
  inherits: false;
5180
5316
  }
5181
- [data-component~="ui-select"][data-v-57618b8b] {
5317
+ [data-component~="ui-select"][data-v-c81ec3d9] {
5182
5318
  box-sizing: border-box;
5183
5319
  display: inline-block;
5184
5320
  inline-size: 100%;
@@ -5202,7 +5338,7 @@ dialog[data-v-40145d41] {
5202
5338
 
5203
5339
  /* The select draws its own chevron: the native caret cannot be inset or sized consistently.
5204
5340
  * 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] {
5341
+ [data-component~="ui-select"][data-v-c81ec3d9] {
5206
5342
  appearance: none;
5207
5343
  padding-inline-end: calc(var(--ui-space-3) + 1.5rem);
5208
5344
  background-image: var(
@@ -5213,10 +5349,10 @@ dialog[data-v-40145d41] {
5213
5349
  background-position: right var(--ui-space-3) center;
5214
5350
  background-size: 1.125rem 1.125rem;
5215
5351
  }
5216
- [data-component~="ui-select"][data-v-57618b8b]:hover:not(:focus):not(:disabled) {
5352
+ [data-component~="ui-select"][data-v-c81ec3d9]:hover:not(:focus):not(:disabled) {
5217
5353
  border-color: var(--ui-control-border-hover, var(--ui-text-secondary));
5218
5354
  }
5219
- [data-component~="ui-select"][data-v-57618b8b]:focus-visible {
5355
+ [data-component~="ui-select"][data-v-c81ec3d9]:focus-visible {
5220
5356
  border-color: var(--ui-control-focus, var(--ui-accent-solid));
5221
5357
  outline: none;
5222
5358
  box-shadow: var(
@@ -5227,28 +5363,48 @@ dialog[data-v-40145d41] {
5227
5363
  }
5228
5364
 
5229
5365
  /* 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]) {
5366
+ [data-component~="ui-select"][aria-invalid="true"][data-v-c81ec3d9],
5367
+ [data-component~="ui-select"][data-v-c81ec3d9]:is(:user-invalid, [data-user-invalid]) {
5232
5368
  border-color: var(--ui-danger-solid);
5233
5369
  }
5234
- [data-component~="ui-select"][data-v-57618b8b]:is([aria-invalid="true"], :is(:user-invalid, [data-user-invalid])):focus-visible {
5370
+ [data-component~="ui-select"][data-v-c81ec3d9]:is([aria-invalid="true"], :is(:user-invalid, [data-user-invalid])):focus-visible {
5235
5371
  box-shadow:
5236
5372
  var(--ui-control-inset),
5237
5373
  0 0 0 3px color-mix(in srgb, var(--ui-danger-solid) 22%, transparent);
5238
5374
  }
5239
- [data-component~="ui-select"][data-v-57618b8b]:disabled {
5375
+ [data-component~="ui-select"][data-v-c81ec3d9]:disabled {
5240
5376
  background-color: var(--ui-control-surface-disabled, var(--ui-surface-muted));
5241
5377
  color: var(--ui-disabled-text);
5242
5378
  box-shadow: none;
5243
5379
  cursor: not-allowed;
5244
5380
  }
5245
- [data-component~="ui-select"][size][data-v-57618b8b]:not([size="1"]) {
5246
- min-block-size: 7rem;
5247
- padding: var(--ui-space-2);
5381
+ [data-component~="ui-select"][data-ui-select-state~="size=sm"][data-v-c81ec3d9] {
5382
+ min-block-size: var(--ui-control-size-sm);
5383
+ padding: var(--ui-space-1) var(--ui-space-2);
5384
+ padding-inline-end: calc(var(--ui-space-2) + var(--ui-icon-size-sm) + var(--ui-space-1));
5385
+ background-position: right var(--ui-space-2) center;
5386
+ background-size: var(--ui-icon-size-sm) var(--ui-icon-size-sm);
5387
+ font-size: var(--ui-font-size-sm);
5388
+ }
5389
+ [data-component~="ui-select"][data-ui-select-state~="size=lg"][data-v-c81ec3d9] {
5390
+ min-block-size: var(--ui-control-size-lg);
5391
+ padding: var(--ui-space-3) var(--ui-space-4);
5392
+ padding-inline-end: calc(var(--ui-space-4) + 1.5rem);
5393
+ background-position: right var(--ui-space-4) center;
5394
+ font-size: var(--ui-font-size-md);
5395
+ }
5396
+
5397
+ /* Under touch a small field is still a touch-sized target, as a small button is, and keeps
5398
+ body-size text: below 16px, iOS zooms the page into the focused field. */
5399
+ @media (pointer: coarse) {
5400
+ [data-component~="ui-select"][data-ui-select-state~="size=sm"][data-v-c81ec3d9] {
5401
+ min-block-size: var(--ui-control-min-block-size);
5402
+ font-size: inherit;
5403
+ }
5248
5404
  }
5249
5405
 
5250
5406
  /* A component that sets its display still honours the hidden attribute on its root. */
5251
- [data-component~="ui-select"][hidden][data-v-57618b8b] {
5407
+ [data-component~="ui-select"][hidden][data-v-c81ec3d9] {
5252
5408
  display: none;
5253
5409
  }
5254
5410
 
@@ -5606,7 +5762,7 @@ to {
5606
5762
  syntax: "*";
5607
5763
  inherits: false;
5608
5764
  }
5609
- [data-component~="ui-switch"][data-v-98e06e1e] {
5765
+ [data-component~="ui-switch"][data-v-87fc218c] {
5610
5766
  /* Hooks do not inherit, so the parts below read them from the root. */
5611
5767
  --_ui-switch-track-width: var(--ui-switch-track-width);
5612
5768
  --_ui-switch-track-height: var(--ui-switch-track-height);
@@ -5620,25 +5776,25 @@ to {
5620
5776
  }
5621
5777
 
5622
5778
  /* The label, and under it an optional line saying what the choice means. */
5623
- .text[data-v-98e06e1e] {
5779
+ .text[data-v-87fc218c] {
5624
5780
  display: flex;
5625
5781
  flex-direction: column;
5626
5782
  gap: var(--ui-space-1);
5627
5783
  min-inline-size: 0;
5628
5784
  }
5629
- .label[data-v-98e06e1e] {
5785
+ .label[data-v-87fc218c] {
5630
5786
  min-inline-size: 0;
5631
5787
  line-height: var(--ui-line-height-md);
5632
5788
  }
5633
- .description[data-v-98e06e1e] {
5789
+ .description[data-v-87fc218c] {
5634
5790
  color: var(--ui-text-secondary);
5635
5791
  font-size: var(--ui-font-size-sm);
5636
5792
  line-height: var(--ui-line-height);
5637
5793
  }
5638
- .description[data-v-98e06e1e]:empty {
5794
+ .description[data-v-87fc218c]:empty {
5639
5795
  display: none;
5640
5796
  }
5641
- input[data-v-98e06e1e] {
5797
+ input[data-v-87fc218c] {
5642
5798
  appearance: none;
5643
5799
  -webkit-appearance: none;
5644
5800
  position: relative;
@@ -5656,7 +5812,7 @@ input[data-v-98e06e1e] {
5656
5812
  border-color var(--ui-motion-fast) var(--ui-motion-ease);
5657
5813
  margin: 0;
5658
5814
  }
5659
- input[data-v-98e06e1e]::after {
5815
+ input[data-v-87fc218c]::after {
5660
5816
  content: "";
5661
5817
  position: absolute;
5662
5818
  top: 3px;
@@ -5668,35 +5824,64 @@ input[data-v-98e06e1e]::after {
5668
5824
  box-shadow: var(--ui-shadow-xs);
5669
5825
  transition: transform var(--ui-motion-fast) var(--ui-motion-ease);
5670
5826
  }
5671
- input[data-v-98e06e1e]:checked {
5827
+ input[data-v-87fc218c]:checked {
5672
5828
  background: var(--ui-accent-solid);
5673
5829
  border-color: var(--ui-accent-solid);
5674
5830
  }
5675
- input[data-v-98e06e1e]:checked::after {
5831
+ input[data-v-87fc218c]:checked::after {
5676
5832
  transform: translateX(1rem);
5677
5833
  background: var(--ui-text-on-accent);
5678
5834
  }
5679
- input[data-v-98e06e1e]:focus-visible {
5835
+ input[data-v-87fc218c]:focus-visible {
5680
5836
  outline: 2px solid var(--ui-focus-ring, var(--ui-accent-solid));
5681
5837
  outline-offset: 2px;
5682
5838
  }
5683
- [data-component~="ui-switch"][data-ui-switch-state~="disabled"][data-v-98e06e1e] {
5839
+ [data-component~="ui-switch"][data-ui-switch-state~="disabled"][data-v-87fc218c] {
5684
5840
  color: var(--ui-disabled-text);
5685
5841
  cursor: not-allowed;
5686
5842
  }
5687
- [data-component~="ui-switch"][data-ui-switch-state~="disabled"] input[data-v-98e06e1e] {
5843
+ [data-component~="ui-switch"][data-ui-switch-state~="disabled"] input[data-v-87fc218c] {
5688
5844
  border-color: var(--ui-border-default);
5689
5845
  background: var(--ui-control-surface-disabled, var(--ui-surface-muted));
5690
5846
  cursor: not-allowed;
5691
5847
  }
5692
5848
  @media (prefers-reduced-motion: reduce) {
5693
- input[data-v-98e06e1e], input[data-v-98e06e1e]::after {
5849
+ input[data-v-87fc218c], input[data-v-87fc218c]::after {
5694
5850
  transition: none;
5695
5851
  }
5696
5852
  }
5697
5853
 
5854
+ /* A sized switch keeps its track and aligns instead: the label takes that size's field type size,
5855
+ and the first line centres in that control height, so the label shares a row's baseline.
5856
+ Multi-line labels and descriptions still grow downward from that first line. */
5857
+ [data-component~="ui-switch"][data-ui-switch-state~="size=sm"][data-v-87fc218c] {
5858
+ --_font: var(--ui-font-size-sm);
5859
+ --_row: var(--ui-control-size-sm);
5860
+ }
5861
+ [data-component~="ui-switch"][data-ui-switch-state~="size=lg"][data-v-87fc218c] {
5862
+ --_font: var(--ui-font-size-md);
5863
+ --_row: var(--ui-control-size-lg);
5864
+ }
5865
+ [data-component~="ui-switch"][data-ui-switch-state~="size=sm"][data-v-87fc218c],
5866
+ [data-component~="ui-switch"][data-ui-switch-state~="size=lg"][data-v-87fc218c] {
5867
+ --_line: calc(var(--_font) * var(--ui-line-height-md));
5868
+ font-size: var(--_font);
5869
+ padding-block: calc((var(--_row) - var(--ui-switch-track-height, 1.5rem)) / 2);
5870
+ }
5871
+
5872
+ /* The label centres on the track. */
5873
+ [data-component~="ui-switch"][data-ui-switch-state~="size=sm"] .text[data-v-87fc218c],
5874
+ [data-component~="ui-switch"][data-ui-switch-state~="size=lg"] .text[data-v-87fc218c] {
5875
+ margin-top: calc((var(--_ui-switch-track-height, 1.5rem) - var(--_line)) / 2);
5876
+ }
5877
+ @media (pointer: coarse) {
5878
+ [data-component~="ui-switch"][data-ui-switch-state~="size=sm"][data-v-87fc218c] {
5879
+ --_row: var(--ui-control-min-block-size);
5880
+ }
5881
+ }
5882
+
5698
5883
  /* A component that sets its display still honours the hidden attribute on its root. */
5699
- [data-component~="ui-switch"][hidden][data-v-98e06e1e] {
5884
+ [data-component~="ui-switch"][hidden][data-v-87fc218c] {
5700
5885
  display: none;
5701
5886
  }
5702
5887
 
@@ -5999,7 +6184,7 @@ input[data-v-98e06e1e], input[data-v-98e06e1e]::after {
5999
6184
  syntax: "*";
6000
6185
  inherits: false;
6001
6186
  }
6002
- [data-component~="ui-textarea"][data-v-73461aaf] {
6187
+ [data-component~="ui-textarea"][data-v-00f7b2fd] {
6003
6188
  box-sizing: border-box;
6004
6189
  display: inline-block;
6005
6190
  inline-size: 100%;
@@ -6023,18 +6208,18 @@ input[data-v-98e06e1e], input[data-v-98e06e1e]::after {
6023
6208
  }
6024
6209
 
6025
6210
  /* 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 {
6211
+ [data-component~="ui-textarea"][data-v-00f7b2fd]::selection {
6027
6212
  background: color-mix(in srgb, var(--ui-accent-solid) 20%, transparent);
6028
6213
  color: inherit;
6029
6214
  }
6030
- [data-component~="ui-textarea"][data-v-73461aaf]::placeholder {
6215
+ [data-component~="ui-textarea"][data-v-00f7b2fd]::placeholder {
6031
6216
  color: var(--ui-control-placeholder, var(--ui-text-secondary));
6032
6217
  opacity: 1;
6033
6218
  }
6034
- [data-component~="ui-textarea"][data-v-73461aaf]:hover:not(:focus):not(:disabled) {
6219
+ [data-component~="ui-textarea"][data-v-00f7b2fd]:hover:not(:focus):not(:disabled) {
6035
6220
  border-color: var(--ui-control-border-hover, var(--ui-text-secondary));
6036
6221
  }
6037
- [data-component~="ui-textarea"][data-v-73461aaf]:focus-visible {
6222
+ [data-component~="ui-textarea"][data-v-00f7b2fd]:focus-visible {
6038
6223
  border-color: var(--ui-control-focus, var(--ui-accent-solid));
6039
6224
  outline: none;
6040
6225
  box-shadow: var(
@@ -6045,24 +6230,39 @@ input[data-v-98e06e1e], input[data-v-98e06e1e]::after {
6045
6230
  }
6046
6231
 
6047
6232
  /* 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]) {
6233
+ [data-component~="ui-textarea"][aria-invalid="true"][data-v-00f7b2fd],
6234
+ [data-component~="ui-textarea"][data-v-00f7b2fd]:is(:user-invalid, [data-user-invalid]) {
6050
6235
  border-color: var(--ui-danger-solid);
6051
6236
  }
6052
- [data-component~="ui-textarea"][data-v-73461aaf]:is([aria-invalid="true"], :is(:user-invalid, [data-user-invalid])):focus-visible {
6237
+ [data-component~="ui-textarea"][data-v-00f7b2fd]:is([aria-invalid="true"], :is(:user-invalid, [data-user-invalid])):focus-visible {
6053
6238
  box-shadow:
6054
6239
  var(--ui-control-inset),
6055
6240
  0 0 0 3px color-mix(in srgb, var(--ui-danger-solid) 22%, transparent);
6056
6241
  }
6057
- [data-component~="ui-textarea"][data-v-73461aaf]:disabled {
6242
+ [data-component~="ui-textarea"][data-v-00f7b2fd]:disabled {
6058
6243
  background: var(--ui-control-surface-disabled, var(--ui-surface-muted));
6059
6244
  color: var(--ui-disabled-text);
6060
6245
  box-shadow: none;
6061
6246
  cursor: not-allowed;
6062
6247
  }
6248
+ [data-component~="ui-textarea"][data-ui-textarea-state~="size=sm"][data-v-00f7b2fd] {
6249
+ padding: var(--ui-space-1) var(--ui-space-2);
6250
+ font-size: var(--ui-font-size-sm);
6251
+ }
6252
+ [data-component~="ui-textarea"][data-ui-textarea-state~="size=lg"][data-v-00f7b2fd] {
6253
+ padding: var(--ui-space-3) var(--ui-space-4);
6254
+ font-size: var(--ui-font-size-md);
6255
+ }
6256
+
6257
+ /* Below 16px, iOS zooms the page into the focused field, so touch keeps body-size text. */
6258
+ @media (pointer: coarse) {
6259
+ [data-component~="ui-textarea"][data-ui-textarea-state~="size=sm"][data-v-00f7b2fd] {
6260
+ font-size: inherit;
6261
+ }
6262
+ }
6063
6263
 
6064
6264
  /* A component that sets its display still honours the hidden attribute on its root. */
6065
- [data-component~="ui-textarea"][hidden][data-v-73461aaf] {
6265
+ [data-component~="ui-textarea"][hidden][data-v-00f7b2fd] {
6066
6266
  display: none;
6067
6267
  }
6068
6268