@threadlabs/looma 0.39.1 → 0.39.3

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 (50) hide show
  1. package/components/ui-button/ui-button.html +24 -3
  2. package/components/ui-checkbox/ui-checkbox.html +34 -18
  3. package/components/ui-combobox/ui-combobox.html +8 -3
  4. package/components/ui-combobox/ui-combobox.js +3 -2
  5. package/components/ui-dialog/ui-dialog.html +6 -52
  6. package/components/ui-input/ui-input.html +21 -3
  7. package/components/ui-input-group/ui-input-group.html +1 -0
  8. package/components/ui-light-editor/ui-light-editor.html +26 -25
  9. package/components/ui-select/ui-select.html +10 -3
  10. package/dist/index.js +1 -1
  11. package/docs/README.md +18 -7
  12. package/docs/catalog.json +2 -26
  13. package/docs/customizer-render.mjs +37 -33
  14. package/docs/customizer.js +82 -47
  15. package/docs/site.mjs +10 -6
  16. package/docs/theme-session.mjs +7 -8
  17. package/docs/theme.mjs +10 -22
  18. package/package.json +1 -1
  19. package/styles/ui-button.css +24 -1
  20. package/styles/ui-checkbox.css +39 -19
  21. package/styles/ui-combobox.css +16 -6
  22. package/styles/ui-dialog.css +6 -107
  23. package/styles/ui-input-group.css +1 -0
  24. package/styles/ui-input.css +24 -3
  25. package/styles/ui-light-editor.css +111 -0
  26. package/styles/ui-select.css +10 -3
  27. package/theme-system.css +4 -1
  28. package/tokens.css +9 -2
  29. package/vanilla/UiButton.js +14 -12
  30. package/vanilla/UiDialog.js +2 -2
  31. package/vanilla/UiLightEditor.js +2 -2
  32. package/vue/UiButton.vue +28 -7
  33. package/vue/UiCheckbox.vue +34 -19
  34. package/vue/UiCombobox.vue +22 -6
  35. package/vue/UiDialog.d.ts +3 -3
  36. package/vue/UiDialog.vue +18 -111
  37. package/vue/UiInput.vue +30 -3
  38. package/vue/UiInputGroup.vue +1 -0
  39. package/vue/UiLightEditor.vue +156 -40
  40. package/vue/UiSelect.vue +16 -3
  41. package/vue/chunks/UiButton.js +18 -10
  42. package/vue/chunks/UiCheckbox.js +1 -1
  43. package/vue/chunks/UiCombobox.js +1 -1
  44. package/vue/chunks/UiDialog.js +22 -14
  45. package/vue/chunks/UiInput.js +1 -1
  46. package/vue/chunks/UiInputGroup.js +1 -1
  47. package/vue/chunks/UiLightEditor.js +66 -58
  48. package/vue/chunks/UiSelect.js +1 -1
  49. package/vue/components.css +337 -160
  50. package/vue/editor/index.js +46 -36
@@ -1115,6 +1115,8 @@ svg,.arc {
1115
1115
  /* A count is an adornment, not another line of label text. Keep the standard control height
1116
1116
  with enough inset for a 24px mark; large content can still grow the button naturally. */
1117
1117
 
1118
+ /* Trim the text line itself: an anonymous flex item retains font-metric space in some fonts. */
1119
+
1118
1120
  /* Short numeric and icon actions share a minimum box; large values remain readable. */
1119
1121
 
1120
1122
  /* Card actions inherit Button's palette and behavior; only their shared layout changes.
@@ -1204,6 +1206,7 @@ svg,.arc {
1204
1206
  }
1205
1207
  :scope:where([data-hn-ui-button]) {
1206
1208
  --_button-square-size: var(--ui-button-min-block-size, var(--ui-control-size-md));
1209
+ box-sizing: border-box !important;
1207
1210
  appearance: none;
1208
1211
  min-block-size: var(--ui-button-min-block-size, var(--ui-control-size-md));
1209
1212
  border-style: solid;
@@ -1244,6 +1247,18 @@ svg,.arc {
1244
1247
  :scope:not([data-appearance="link"]):has(.badge:not(:empty)):where([data-hn-ui-button]) {
1245
1248
  padding-block: var(--ui-space-0-5) !important;
1246
1249
  }
1250
+ .label:where([data-hn-ui-button]) {
1251
+ display: block !important;
1252
+ align-content: center !important;
1253
+ min-inline-size: 0 !important;
1254
+ min-block-size: 1lh !important;
1255
+ }
1256
+ .label:has(svg):where([data-hn-ui-button]) {
1257
+ display: inline-flex !important;
1258
+ align-items: center !important;
1259
+ gap: var(--ui-space-2) !important;
1260
+ text-box-trim: none;
1261
+ }
1247
1262
  .badge:where([data-hn-ui-button]) {
1248
1263
  display: inline-flex !important;
1249
1264
  align-items: center !important;
@@ -1253,7 +1268,7 @@ svg,.arc {
1253
1268
  display: none !important;
1254
1269
  }
1255
1270
  @supports (text-box-trim: trim-both) {
1256
- :scope:where([data-hn-ui-button]) {
1271
+ .label:not(:has(svg)):where([data-hn-ui-button]) {
1257
1272
  text-box-trim: trim-both;
1258
1273
  text-box-edge: cap alphabetic;
1259
1274
  }
@@ -1545,6 +1560,10 @@ html[data-ui-input-modality="touch"]
1545
1560
  color var(--ui-motion-fast) var(--ui-motion-ease),
1546
1561
  text-decoration-color var(--ui-motion-fast) var(--ui-motion-ease);
1547
1562
  }
1563
+ :scope[data-appearance="link"] .label:where([data-hn-ui-button]) {
1564
+ display: inline !important;
1565
+ text-box-trim: none;
1566
+ }
1548
1567
  :scope[data-appearance="link"]:hover:not(:disabled, [aria-disabled="true"]):where([data-hn-ui-button]) {
1549
1568
  color: var(--ui-button-link-hover-text, var(--ui-text-primary));
1550
1569
  text-decoration-color: currentColor;
@@ -1908,19 +1927,20 @@ html[data-ui-input-modality="touch"]
1908
1927
 
1909
1928
  /* The label, and under it an optional line saying what the choice means. */
1910
1929
 
1911
- /* Centre the tick's box and lift it slightly for the rotated check shape. */
1912
- @keyframes ui-checkbox-check-d551a32f {
1930
+ /* The SVG's painted bounds are centred in its viewBox, including its round stroke.
1931
+ Centre that box directly; rotated border boxes do not centre the visible check. */
1932
+ @keyframes ui-checkbox-check-570a9f0b {
1913
1933
  from {
1914
1934
  opacity: 0;
1915
- transform: translateY(calc(var(--_ui-checkbox-size) * -0.09 / 1.125)) rotate(45deg) scale(0.55);
1935
+ scale: 0.55;
1916
1936
  }
1917
1937
  65% {
1918
1938
  opacity: 1;
1919
- transform: translateY(calc(var(--_ui-checkbox-size) * -0.09 / 1.125)) rotate(45deg) scale(1.12);
1939
+ scale: 1.12;
1920
1940
  }
1921
1941
  to {
1922
1942
  opacity: 1;
1923
- transform: translateY(calc(var(--_ui-checkbox-size) * -0.09 / 1.125)) rotate(45deg) scale(1);
1943
+ scale: 1;
1924
1944
  }
1925
1945
  }
1926
1946
 
@@ -2008,7 +2028,8 @@ input:where([data-hn-ui-checkbox]) {
2008
2028
  }
2009
2029
  input:where([data-hn-ui-checkbox])::after {
2010
2030
  content: "";
2011
- position: absolute;
2031
+ position: absolute !important;
2032
+ transform: none !important;
2012
2033
  opacity: 0;
2013
2034
  transition: opacity var(--ui-motion-fast) var(--ui-motion-ease);
2014
2035
  }
@@ -2019,27 +2040,26 @@ input:checked:where([data-hn-ui-checkbox]),input:indeterminate:where([data-hn-ui
2019
2040
  box-shadow: var(--ui-control-inset);
2020
2041
  }
2021
2042
  input:checked:where([data-hn-ui-checkbox])::after {
2022
- inset: 0;
2023
- margin: auto !important;
2024
- inline-size: calc(var(--_ui-checkbox-size) * 0.28 / 1.125);
2025
- block-size: calc(var(--_ui-checkbox-size) * 0.5 / 1.125);
2026
- /* Longhands, not `border: solid var(...)`: lowering drops a shorthand that omits a
2027
- component, which left the tick with no style and no colour. */
2028
- border-style: solid;
2029
- border-color: var(--ui-text-on-accent);
2030
- border-width: 0 calc(var(--_ui-checkbox-size) * 0.125 / 1.125)
2031
- calc(var(--_ui-checkbox-size) * 0.125 / 1.125) 0;
2043
+ inset: 50% auto auto 50% !important;
2044
+ inline-size: calc(var(--_ui-checkbox-size) * 0.7) !important;
2045
+ block-size: calc(var(--_ui-checkbox-size) * 0.7) !important;
2046
+ background: var(--ui-text-on-accent);
2047
+ mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 11.5 5 5 9-9'/%3E%3C/svg%3E")
2048
+ center / contain no-repeat;
2032
2049
  opacity: 1;
2033
- transform: translateY(calc(var(--_ui-checkbox-size) * -0.09 / 1.125)) rotate(45deg);
2034
- animation: ui-checkbox-check-d551a32f var(--ui-motion-base) var(--ui-motion-ease-out, cubic-bezier(0.16, 1, 0.3, 1)) both;
2050
+ translate: -50% -50% !important;
2051
+ animation: ui-checkbox-check-570a9f0b var(--ui-motion-base) var(--ui-motion-ease-out, cubic-bezier(0.16, 1, 0.3, 1)) both;
2035
2052
  }
2036
2053
  input:indeterminate:where([data-hn-ui-checkbox])::after {
2037
- inset: 50% calc(var(--_ui-checkbox-size) * 0.23 / 1.125) auto;
2038
- block-size: calc(var(--_ui-checkbox-size) * 0.125 / 1.125);
2054
+ mask: none;
2055
+ animation: none;
2056
+ inset: 50% calc(var(--_ui-checkbox-size) * 0.23 / 1.125) auto !important;
2057
+ inline-size: auto !important;
2058
+ block-size: calc(var(--_ui-checkbox-size) * 0.125 / 1.125) !important;
2039
2059
  border-radius: var(--ui-radius-round);
2040
2060
  background: var(--ui-text-on-accent);
2041
2061
  opacity: 1;
2042
- transform: translateY(-50%);
2062
+ translate: 0 -50% !important;
2043
2063
  }
2044
2064
  @media (prefers-reduced-motion: reduce) {
2045
2065
  input:where([data-hn-ui-checkbox])::after {
@@ -2047,6 +2067,17 @@ input:where([data-hn-ui-checkbox])::after {
2047
2067
  animation: none;
2048
2068
  }
2049
2069
  }
2070
+ @media (forced-colors: active) {
2071
+ input:checked:where([data-hn-ui-checkbox]),input:indeterminate:where([data-hn-ui-checkbox]) {
2072
+ forced-color-adjust: none;
2073
+ background: Highlight;
2074
+ border-color: Highlight;
2075
+ }
2076
+ input:checked:where([data-hn-ui-checkbox])::after,input:indeterminate:where([data-hn-ui-checkbox])::after {
2077
+ forced-color-adjust: none;
2078
+ background: HighlightText;
2079
+ }
2080
+ }
2050
2081
  input:hover:enabled:where([data-hn-ui-checkbox]) {
2051
2082
  border-color: var(--ui-accent-solid);
2052
2083
  }
@@ -2231,6 +2262,14 @@ input:focus-visible:where([data-hn-ui-checkbox]) {
2231
2262
  syntax: "*";
2232
2263
  inherits: false;
2233
2264
  }
2265
+ /* Normalize a unitless zero border to a length before the box calculation. */
2266
+ @property --_ui-input-stroke {
2267
+ syntax: "<length>";
2268
+ inherits: false;
2269
+ initial-value: 1px;
2270
+ }
2271
+
2272
+ /* Cap Safari's excess text metrics without changing native date, file, color or range widgets. */
2234
2273
 
2235
2274
  /* Each size reads the hook and then an Input Group's default first, so a group, which draws the frame, can zero it. */
2236
2275
 
@@ -2248,6 +2287,12 @@ input:focus-visible:where([data-hn-ui-checkbox]) {
2248
2287
  /* A component that sets its display still honours the hidden attribute on its root. */
2249
2288
  @scope (.ui-input) to ([data-hn]) {
2250
2289
  :scope {
2290
+ --_ui-input-size: var(--ui-control-size-md);
2291
+ --_ui-input-inset-block: var(--ui-control-inset-block-md, var(--ui-space-2));
2292
+ --_ui-input-stroke: var(
2293
+ --ui-input-border-width,
2294
+ var(--_ui-default-input-border-width, var(--ui-border-width))
2295
+ );
2251
2296
  box-sizing: border-box !important;
2252
2297
  display: inline-block !important;
2253
2298
  inline-size: var(--ui-input-inline-size, 100%);
@@ -2257,7 +2302,7 @@ input:focus-visible:where([data-hn-ui-checkbox]) {
2257
2302
  var(--_ui-default-input-min-block-size, var(--ui-control-size-md))
2258
2303
  );
2259
2304
  margin: 0 !important;
2260
- padding: var(--ui-control-inset-block-md, var(--ui-space-2)) var(--ui-space-3) !important;
2305
+ padding: var(--_ui-input-inset-block) var(--ui-space-3) !important;
2261
2306
  appearance: none;
2262
2307
  padding-inline-start: var(--_ui-default-input-padding-inline-start, var(--ui-space-3))
2263
2308
  !important;
@@ -2287,20 +2332,33 @@ input:focus-visible:where([data-hn-ui-checkbox]) {
2287
2332
  box-shadow var(--ui-motion-fast) var(--ui-motion-ease),
2288
2333
  background-color var(--ui-motion-fast) var(--ui-motion-ease);
2289
2334
  }
2335
+ :scope:is([type="text"], [type="search"], [type="tel"], [type="url"], [type="email"], [type="password"], [type="number"]) {
2336
+ max-block-size: max(
2337
+ calc(var(--_ui-input-size) - var(--_ui-default-input-frame-width, 0px)),
2338
+ calc(
2339
+ 1em * var(--ui-line-height-tight) + 2 * var(--_ui-input-inset-block) +
2340
+ 2 * var(--_ui-input-stroke)
2341
+ )
2342
+ );
2343
+ }
2290
2344
  :scope[data-ui-input-state~="size=sm"] {
2345
+ --_ui-input-size: var(--ui-control-size-sm);
2346
+ --_ui-input-inset-block: var(--ui-control-inset-block-sm, var(--ui-space-1));
2291
2347
  min-block-size: var(
2292
2348
  --ui-input-min-block-size,
2293
2349
  var(--_ui-default-input-min-block-size, var(--ui-control-size-sm))
2294
2350
  );
2295
- padding: var(--ui-control-inset-block-sm, var(--ui-space-1)) var(--ui-space-2) !important;
2351
+ padding: var(--_ui-input-inset-block) var(--ui-space-2) !important;
2296
2352
  font-size: var(--ui-font-size-sm);
2297
2353
  }
2298
2354
  :scope[data-ui-input-state~="size=lg"] {
2355
+ --_ui-input-size: var(--ui-control-size-lg);
2356
+ --_ui-input-inset-block: var(--ui-control-inset-block-lg, var(--ui-space-3));
2299
2357
  min-block-size: var(
2300
2358
  --ui-input-min-block-size,
2301
2359
  var(--_ui-default-input-min-block-size, var(--ui-control-size-lg))
2302
2360
  );
2303
- padding: var(--ui-control-inset-block-lg, var(--ui-space-3)) var(--ui-space-4) !important;
2361
+ padding: var(--_ui-input-inset-block) var(--ui-space-4) !important;
2304
2362
  font-size: var(--ui-font-size-md);
2305
2363
  }
2306
2364
  @media (pointer: coarse) {
@@ -2989,10 +3047,15 @@ input:where([data-hn-ui-combobox])::selection {
2989
3047
  color: inherit;
2990
3048
  }
2991
3049
  input:where([data-hn-ui-combobox]) {
3050
+ --_ui-combobox-inset-block: var(--ui-control-inset-block-md, var(--ui-space-2));
2992
3051
  appearance: none;
2993
3052
  width: 100%;
2994
3053
  min-inline-size: 0;
2995
3054
  min-block-size: calc(var(--_row) - 2 * var(--ui-border-width));
3055
+ max-block-size: max(
3056
+ calc(var(--_row) - 2 * var(--ui-border-width)),
3057
+ calc(1em * var(--ui-line-height-tight) + 2 * var(--_ui-combobox-inset-block))
3058
+ );
2996
3059
  box-sizing: border-box !important;
2997
3060
  border: 0;
2998
3061
  border-radius: inherit;
@@ -3000,7 +3063,7 @@ input:where([data-hn-ui-combobox]) {
3000
3063
  color: inherit;
3001
3064
  font: inherit;
3002
3065
  line-height: var(--ui-line-height-tight);
3003
- padding: var(--ui-control-inset-block-md, var(--ui-space-2)) var(--ui-space-3) !important;
3066
+ padding: var(--_ui-combobox-inset-block) var(--ui-space-3) !important;
3004
3067
  margin: 0 !important;
3005
3068
  outline: none;
3006
3069
  }
@@ -3008,14 +3071,16 @@ input:where([data-hn-ui-combobox]) {
3008
3071
  --_row: var(--ui-control-size-sm);
3009
3072
  }
3010
3073
  :scope[data-ui-combobox-state~="size=sm"] input:where([data-hn-ui-combobox]) {
3011
- padding: var(--ui-control-inset-block-sm, var(--ui-space-1)) var(--ui-space-2) !important;
3074
+ --_ui-combobox-inset-block: var(--ui-control-inset-block-sm, var(--ui-space-1));
3075
+ padding: var(--_ui-combobox-inset-block) var(--ui-space-2) !important;
3012
3076
  font-size: var(--ui-font-size-sm);
3013
3077
  }
3014
3078
  :scope[data-ui-combobox-state~="size=lg"]:where([data-hn-ui-combobox]) {
3015
3079
  --_row: var(--ui-control-size-lg);
3016
3080
  }
3017
3081
  :scope[data-ui-combobox-state~="size=lg"] input:where([data-hn-ui-combobox]) {
3018
- padding: var(--ui-control-inset-block-lg, var(--ui-space-3)) var(--ui-space-4) !important;
3082
+ --_ui-combobox-inset-block: var(--ui-control-inset-block-lg, var(--ui-space-3));
3083
+ padding: var(--_ui-combobox-inset-block) var(--ui-space-4) !important;
3019
3084
  font-size: var(--ui-font-size-md);
3020
3085
  }
3021
3086
  button:where([data-hn-ui-combobox]) {
@@ -3157,6 +3222,7 @@ input:disabled:where([data-hn-ui-combobox]),button:disabled:where([data-hn-ui-co
3157
3222
  display: none !important;
3158
3223
  }
3159
3224
  :scope[data-ui-combobox-state~="multiple"] input:where([data-hn-ui-combobox]) {
3225
+ max-block-size: none;
3160
3226
  flex: 1 0 var(--_ui-combobox-item-input-min-inline-size, 5rem);
3161
3227
  width: auto;
3162
3228
  min-block-size: 1.75rem;
@@ -3331,10 +3397,15 @@ input:where(:not([data-hn], [data-slotted]:not([data-slotted~="ui-combobox"]))):
3331
3397
  color: inherit;
3332
3398
  }
3333
3399
  input:where(:scope, :scope *):where([data-hn-ui-combobox]) {
3400
+ --_ui-combobox-inset-block: var(--ui-control-inset-block-md, var(--ui-space-2));
3334
3401
  appearance: none;
3335
3402
  width: 100%;
3336
3403
  min-inline-size: 0;
3337
3404
  min-block-size: calc(var(--_row) - 2 * var(--ui-border-width));
3405
+ max-block-size: max(
3406
+ calc(var(--_row) - 2 * var(--ui-border-width)),
3407
+ calc(1em * var(--ui-line-height-tight) + 2 * var(--_ui-combobox-inset-block))
3408
+ );
3338
3409
  box-sizing: border-box !important;
3339
3410
  border: 0;
3340
3411
  border-radius: inherit;
@@ -3342,7 +3413,7 @@ input:where(:scope, :scope *):where([data-hn-ui-combobox]) {
3342
3413
  color: inherit;
3343
3414
  font: inherit;
3344
3415
  line-height: var(--ui-line-height-tight);
3345
- padding: var(--ui-control-inset-block-md, var(--ui-space-2)) var(--ui-space-3) !important;
3416
+ padding: var(--_ui-combobox-inset-block) var(--ui-space-3) !important;
3346
3417
  margin: 0 !important;
3347
3418
  outline: none;
3348
3419
  }
@@ -3351,7 +3422,8 @@ input:where(:scope, :scope *):where([data-hn-ui-combobox]) {
3351
3422
  }
3352
3423
  :where(.ui-combobox)[data-ui-combobox-state~="size=sm"]
3353
3424
  input:where(:scope, :not([data-hn], [data-slotted]:not([data-slotted~="ui-combobox"]))):where([data-hn-ui-combobox]) {
3354
- padding: var(--ui-control-inset-block-sm, var(--ui-space-1)) var(--ui-space-2) !important;
3425
+ --_ui-combobox-inset-block: var(--ui-control-inset-block-sm, var(--ui-space-1));
3426
+ padding: var(--_ui-combobox-inset-block) var(--ui-space-2) !important;
3355
3427
  font-size: var(--ui-font-size-sm);
3356
3428
  }
3357
3429
  :where(.ui-combobox)[data-ui-combobox-state~="size=lg"]:where(:scope, :not([data-hn], [data-slotted]:not([data-slotted~="ui-combobox"]))):where([data-hn-ui-combobox]) {
@@ -3359,7 +3431,8 @@ input:where(:scope, :scope *):where([data-hn-ui-combobox]) {
3359
3431
  }
3360
3432
  :where(.ui-combobox)[data-ui-combobox-state~="size=lg"]
3361
3433
  input:where(:scope, :not([data-hn], [data-slotted]:not([data-slotted~="ui-combobox"]))):where([data-hn-ui-combobox]) {
3362
- padding: var(--ui-control-inset-block-lg, var(--ui-space-3)) var(--ui-space-4) !important;
3434
+ --_ui-combobox-inset-block: var(--ui-control-inset-block-lg, var(--ui-space-3));
3435
+ padding: var(--_ui-combobox-inset-block) var(--ui-space-4) !important;
3363
3436
  font-size: var(--ui-font-size-md);
3364
3437
  }
3365
3438
  button:where(:scope, :scope *):where([data-hn-ui-combobox]) {
@@ -3508,6 +3581,7 @@ input:disabled:where(:scope, :scope *):where([data-hn-ui-combobox]),button:disab
3508
3581
  }
3509
3582
  :where(.ui-combobox)[data-ui-combobox-state~="multiple"]
3510
3583
  input:where(:scope, :not([data-hn], [data-slotted]:not([data-slotted~="ui-combobox"]))):where([data-hn-ui-combobox]) {
3584
+ max-block-size: none;
3511
3585
  flex: 1 0 var(--_ui-combobox-item-input-min-inline-size, 5rem);
3512
3586
  width: auto;
3513
3587
  min-block-size: 1.75rem;
@@ -4616,17 +4690,13 @@ dd:where([data-hn-ui-description-item]) {
4616
4690
  /* Alerts have no close target to add height above the title. */
4617
4691
 
4618
4692
  /* :host-qualified so page heading rules that reach in cannot outrank the dialog chrome. */
4619
-
4620
- /* A CSS-drawn X. */
4621
-
4622
- /* A touch target, like Button on coarse pointers. */
4623
- @keyframes ui-dialog-enter-6cfda64d {
4693
+ @keyframes ui-dialog-enter-45428506 {
4624
4694
  from {
4625
4695
  opacity: 0;
4626
4696
  transform: scale(0.96);
4627
4697
  }
4628
4698
  }
4629
- @keyframes ui-dialog-backdrop-enter-6cfda64d {
4699
+ @keyframes ui-dialog-backdrop-enter-45428506 {
4630
4700
  from {
4631
4701
  background-color: transparent;
4632
4702
  }
@@ -4761,7 +4831,7 @@ from {
4761
4831
  pointer-events: auto;
4762
4832
  opacity: 1;
4763
4833
  transform: scale(1);
4764
- animation: ui-dialog-enter-6cfda64d var(--ui-dialog-duration, var(--ui-motion-base))
4834
+ animation: ui-dialog-enter-45428506 var(--ui-dialog-duration, var(--ui-motion-base))
4765
4835
  var(--ui-motion-ease);
4766
4836
  }
4767
4837
  :scope[data-ui-dialog-state~="size=sm"]:where([data-hn-ui-dialog]) {
@@ -4807,51 +4877,10 @@ header:where([data-hn-ui-dialog]) {
4807
4877
  line-height: var(--ui-line-height-tight);
4808
4878
  }
4809
4879
  .close:where([data-hn-ui-dialog]) {
4810
- display: inline-grid !important;
4811
- place-items: center;
4812
- flex: none;
4880
+ display: flex !important;
4881
+ align-items: center !important;
4882
+ flex: none !important;
4813
4883
  margin-inline-start: auto !important;
4814
- inline-size: var(--ui-control-size-sm);
4815
- block-size: var(--ui-control-size-sm);
4816
- padding: 0 !important;
4817
- border: 0;
4818
- border-radius: var(--ui-radius-round);
4819
- background: transparent;
4820
- color: var(--ui-text-secondary);
4821
- cursor: pointer;
4822
- transition:
4823
- background-color var(--ui-motion-fast) var(--ui-motion-ease),
4824
- color var(--ui-motion-fast) var(--ui-motion-ease);
4825
- }
4826
- .close:where([data-hn-ui-dialog])::before,.close:where([data-hn-ui-dialog])::after {
4827
- content: "";
4828
- grid-area: 1 / 1;
4829
- inline-size: 0.875rem;
4830
- block-size: 1.5px;
4831
- border-radius: 1px;
4832
- background: currentColor;
4833
- transform: rotate(45deg);
4834
- }
4835
- .close:where([data-hn-ui-dialog])::after {
4836
- transform: rotate(-45deg);
4837
- }
4838
- .close:hover:where([data-hn-ui-dialog]) {
4839
- background: var(--ui-surface-muted);
4840
- color: var(--ui-text-primary);
4841
- }
4842
- .close:focus-visible:where([data-hn-ui-dialog]) {
4843
- outline: var(--ui-focus-width) solid var(--ui-focus-ring);
4844
- outline-offset: var(--ui-focus-width);
4845
- }
4846
- @media (pointer: coarse) {
4847
- .close:where([data-hn-ui-dialog]) {
4848
- inline-size: var(--ui-control-min-block-size);
4849
- block-size: var(--ui-control-min-block-size);
4850
- }
4851
- }
4852
- html[data-ui-input-modality="touch"] :scope .close:where([data-hn-ui-dialog]) {
4853
- inline-size: var(--ui-control-min-block-size);
4854
- block-size: var(--ui-control-min-block-size);
4855
4884
  }
4856
4885
  .body:where([data-hn-ui-dialog]) {
4857
4886
  display: flex !important;
@@ -4882,7 +4911,7 @@ footer:empty:where([data-hn-ui-dialog]) {
4882
4911
  }
4883
4912
  :scope[open]:modal:where([data-hn-ui-dialog])::backdrop {
4884
4913
  background-color: var(--ui-overlay-backdrop);
4885
- animation: ui-dialog-backdrop-enter-6cfda64d var(--_ui-dialog-duration, var(--ui-motion-base))
4914
+ animation: ui-dialog-backdrop-enter-45428506 var(--_ui-dialog-duration, var(--ui-motion-base))
4886
4915
  var(--ui-motion-ease);
4887
4916
  }
4888
4917
  :scope[open][data-ui-backdrop-hidden]:where([data-hn-ui-dialog])::backdrop {
@@ -5021,7 +5050,7 @@ footer:empty:where([data-hn-ui-dialog]) {
5021
5050
  pointer-events: auto;
5022
5051
  opacity: 1;
5023
5052
  transform: scale(1);
5024
- animation: ui-dialog-enter-6cfda64d var(--ui-dialog-duration, var(--ui-motion-base))
5053
+ animation: ui-dialog-enter-45428506 var(--ui-dialog-duration, var(--ui-motion-base))
5025
5054
  var(--ui-motion-ease);
5026
5055
  }
5027
5056
  :where(.ui-dialog)[data-ui-dialog-state~="size=sm"]:where(:scope, :not([data-hn], [data-slotted]:not([data-slotted~="ui-dialog"]))):where([data-hn-ui-dialog]) {
@@ -5070,56 +5099,10 @@ header:where(:scope, :scope *):where([data-hn-ui-dialog]) {
5070
5099
  line-height: var(--ui-line-height-tight);
5071
5100
  }
5072
5101
  .close:where(:scope, :scope *):where([data-hn-ui-dialog]) {
5073
- display: inline-grid !important;
5074
- place-items: center;
5075
- flex: none;
5102
+ display: flex !important;
5103
+ align-items: center !important;
5104
+ flex: none !important;
5076
5105
  margin-inline-start: auto !important;
5077
- inline-size: var(--ui-control-size-sm);
5078
- block-size: var(--ui-control-size-sm);
5079
- padding: 0 !important;
5080
- border: 0;
5081
- border-radius: var(--ui-radius-round);
5082
- background: transparent;
5083
- color: var(--ui-text-secondary);
5084
- cursor: pointer;
5085
- transition:
5086
- background-color var(--ui-motion-fast) var(--ui-motion-ease),
5087
- color var(--ui-motion-fast) var(--ui-motion-ease);
5088
- }
5089
- .close:where(:not([data-hn], [data-slotted]:not([data-slotted~="ui-dialog"]))):where(:scope, :scope
5090
- *):where([data-hn-ui-dialog])::before,.close:where(:not([data-hn], [data-slotted]:not([data-slotted~="ui-dialog"]))):where(:scope, :scope
5091
- *):where([data-hn-ui-dialog])::after {
5092
- content: "";
5093
- grid-area: 1 / 1;
5094
- inline-size: 0.875rem;
5095
- block-size: 1.5px;
5096
- border-radius: 1px;
5097
- background: currentColor;
5098
- transform: rotate(45deg);
5099
- }
5100
- .close:where(:not([data-hn], [data-slotted]:not([data-slotted~="ui-dialog"]))):where(:scope, :scope
5101
- *):where([data-hn-ui-dialog])::after {
5102
- transform: rotate(-45deg);
5103
- }
5104
- .close:hover:where(:scope, :scope *):where([data-hn-ui-dialog]) {
5105
- background: var(--ui-surface-muted);
5106
- color: var(--ui-text-primary);
5107
- }
5108
- .close:focus-visible:where(:scope, :scope *):where([data-hn-ui-dialog]) {
5109
- outline: var(--ui-focus-width) solid var(--ui-focus-ring);
5110
- outline-offset: var(--ui-focus-width);
5111
- }
5112
- @media (pointer: coarse) {
5113
- .close:where(:scope, :scope *):where([data-hn-ui-dialog]) {
5114
- inline-size: var(--ui-control-min-block-size);
5115
- block-size: var(--ui-control-min-block-size);
5116
- }
5117
- }
5118
- html[data-ui-input-modality="touch"]
5119
- :where(.ui-dialog)
5120
- .close:where(:scope, :not([data-hn], [data-slotted]:not([data-slotted~="ui-dialog"]))):where([data-hn-ui-dialog]) {
5121
- inline-size: var(--ui-control-min-block-size);
5122
- block-size: var(--ui-control-min-block-size);
5123
5106
  }
5124
5107
  .body:where(:scope, :scope *):where([data-hn-ui-dialog]) {
5125
5108
  display: flex !important;
@@ -5150,7 +5133,7 @@ footer:empty:where(:scope, :scope *):where([data-hn-ui-dialog]) {
5150
5133
  }
5151
5134
  :where(.ui-dialog)[open]:modal:where(:scope, :not([data-hn], [data-slotted]:not([data-slotted~="ui-dialog"]))):where([data-hn-ui-dialog])::backdrop {
5152
5135
  background-color: var(--ui-overlay-backdrop);
5153
- animation: ui-dialog-backdrop-enter-6cfda64d var(--_ui-dialog-duration, var(--ui-motion-base))
5136
+ animation: ui-dialog-backdrop-enter-45428506 var(--_ui-dialog-duration, var(--ui-motion-base))
5154
5137
  var(--ui-motion-ease);
5155
5138
  }
5156
5139
  :where(.ui-dialog)[open][data-ui-backdrop-hidden]:where(:scope, :not([data-hn], [data-slotted]:not([data-slotted~="ui-dialog"]))):where([data-hn-ui-dialog])::backdrop {
@@ -6197,6 +6180,7 @@ legend.sr-only:where([data-hn-ui-radio-group]) {
6197
6180
  Hooks do not inherit, so these are defaults for the input; its own hooks still win. */
6198
6181
  --_ui-default-input-border-width: 0;
6199
6182
  --_ui-default-input-min-block-size: 0;
6183
+ --_ui-default-input-frame-width: calc(2 * var(--ui-border-width));
6200
6184
  --_ui-default-input-border: transparent;
6201
6185
  --_ui-default-input-border-hover: transparent;
6202
6186
  --_ui-default-input-focus-border: transparent;
@@ -8746,6 +8730,122 @@ path:where([data-hn-ui-light-editor]) {
8746
8730
  }
8747
8731
  }
8748
8732
  }
8733
+ @scope ([data-slotted~="ui-light-editor"]:not([data-hn])) to ([data-hn], [data-slotted]) {
8734
+ :where(.ui-light-editor):where(:scope, :not([data-hn], [data-slotted]:not([data-slotted~="ui-light-editor"]))):where([data-hn-ui-light-editor]) {
8735
+ display: grid !important;
8736
+ gap: var(--ui-space-3) !important;
8737
+ min-inline-size: 0;
8738
+ padding: 0 !important;
8739
+ margin: 0 !important;
8740
+ }
8741
+ .stage:where(:scope, :scope *):where([data-hn-ui-light-editor]) {
8742
+ box-sizing: border-box !important;
8743
+ display: block !important;
8744
+ block-size: 13rem;
8745
+ padding: calc(var(--ui-control-min-block-size) / 2) !important;
8746
+ border: var(--ui-border-width) solid var(--ui-control-border);
8747
+ border-radius: var(--ui-field-radius, var(--ui-radius-md));
8748
+ background: var(--ui-neutral-surface, var(--ui-surface));
8749
+ }
8750
+ .plane:where(:scope, :scope *):where([data-hn-ui-light-editor]) {
8751
+ position: relative;
8752
+ display: block !important;
8753
+ inline-size: 100%;
8754
+ block-size: 100%;
8755
+ }
8756
+ svg:where(:scope, :scope *):where([data-hn-ui-light-editor]) {
8757
+ inline-size: 100%;
8758
+ block-size: 100%;
8759
+ overflow: visible;
8760
+ }
8761
+ path:where(:scope, :scope *):where([data-hn-ui-light-editor]) {
8762
+ fill: none;
8763
+ stroke: var(--ui-border);
8764
+ stroke-width: 1;
8765
+ vector-effect: non-scaling-stroke;
8766
+ }
8767
+ .specimen:where(:scope, :scope *):where([data-hn-ui-light-editor]) {
8768
+ position: absolute;
8769
+ inset: 0;
8770
+ display: grid !important;
8771
+ place-items: center !important;
8772
+ }
8773
+ .source:where(:scope, :scope *):where([data-hn-ui-light-editor]) {
8774
+ position: absolute;
8775
+ left: 50%;
8776
+ top: 0;
8777
+ translate: -50% -50%;
8778
+ display: grid !important;
8779
+ place-items: center !important;
8780
+ inline-size: max(2rem, var(--ui-control-min-block-size));
8781
+ block-size: max(2rem, var(--ui-control-min-block-size));
8782
+ padding: 0 !important;
8783
+ margin: 0 !important;
8784
+ border: 0;
8785
+ border-radius: 50%;
8786
+ background: transparent;
8787
+ cursor: grab;
8788
+ touch-action: none;
8789
+ }
8790
+ .source-glyph:where(:scope, :scope *):where([data-hn-ui-light-editor]) {
8791
+ position: relative;
8792
+ z-index: 1;
8793
+ display: inline-flex !important;
8794
+ color: var(--ui-accent);
8795
+ font-size: var(--ui-font-size-lg);
8796
+ }
8797
+ .source:where(:not([data-hn], [data-slotted]:not([data-slotted~="ui-light-editor"]))):where(:scope, :scope
8798
+ *):where([data-hn-ui-light-editor])::after {
8799
+ content: "";
8800
+ position: absolute;
8801
+ inline-size: 2rem;
8802
+ block-size: 2rem;
8803
+ border: var(--ui-border-width) solid var(--ui-accent);
8804
+ border-radius: 50%;
8805
+ background: var(--ui-surface-raised);
8806
+ box-shadow:
8807
+ 0 0 0 var(--ui-space-2) color-mix(in srgb, var(--ui-accent) 12%, transparent),
8808
+ var(--ui-shadow-sm);
8809
+ }
8810
+ .source:active:where(:scope, :scope *):where([data-hn-ui-light-editor]) {
8811
+ cursor: grabbing;
8812
+ }
8813
+ .source:focus-visible:where(:scope, :scope *):where([data-hn-ui-light-editor]) {
8814
+ outline: var(--ui-focus-width) solid var(--ui-focus-ring);
8815
+ outline-offset: var(--ui-space-1);
8816
+ }
8817
+ .source:disabled:where(:scope, :scope *):where([data-hn-ui-light-editor]) {
8818
+ cursor: not-allowed;
8819
+ }
8820
+ .source:disabled:where(:not([data-hn], [data-slotted]:not([data-slotted~="ui-light-editor"]))):where(:scope, :scope
8821
+ *):where([data-hn-ui-light-editor])::after {
8822
+ background: var(--ui-disabled-surface);
8823
+ border-color: var(--ui-disabled-border);
8824
+ box-shadow: none;
8825
+ }
8826
+ .coordinates:where(:scope, :scope *):where([data-hn-ui-light-editor]) {
8827
+ display: grid !important;
8828
+ grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
8829
+ gap: var(--ui-space-2) !important;
8830
+ }
8831
+ .hint:where(:scope, :scope *):where([data-hn-ui-light-editor]) {
8832
+ font-size: var(--ui-font-size-sm);
8833
+ color: var(--ui-text-secondary);
8834
+ }
8835
+ @media (forced-colors: active) {
8836
+ .source-glyph:where(:scope, :scope *):where([data-hn-ui-light-editor]) {
8837
+ color: CanvasText;
8838
+ }
8839
+ .source:where(:not([data-hn], [data-slotted]:not([data-slotted~="ui-light-editor"]))):where(:scope, :scope
8840
+ *):where([data-hn-ui-light-editor])::after {
8841
+ background: Canvas;
8842
+ border-color: CanvasText;
8843
+ }
8844
+ .source:focus-visible:where(:scope, :scope *):where([data-hn-ui-light-editor]) {
8845
+ outline-color: Highlight;
8846
+ }
8847
+ }
8848
+ }
8749
8849
 
8750
8850
  /* This component's hooks style the element they are set on, and never a nested one. */
8751
8851
  @property --ui-list-gap {
@@ -10108,13 +10208,22 @@ dialog:where([data-hn-ui-search-shell]) {
10108
10208
  /* A component that sets its display still honours the hidden attribute on its root. */
10109
10209
  @scope (.ui-select) to ([data-hn]) {
10110
10210
  :scope:where([data-hn-ui-select]) {
10211
+ --_ui-select-size: var(--ui-control-size-md);
10212
+ --_ui-select-inset-block: var(--ui-control-inset-block-md, var(--ui-space-2));
10111
10213
  box-sizing: border-box !important;
10112
10214
  display: inline-block !important;
10113
10215
  inline-size: var(--ui-select-inline-size, 100%);
10114
10216
  min-inline-size: 0;
10217
+ max-block-size: max(
10218
+ var(--_ui-select-size),
10219
+ calc(
10220
+ 1em * var(--ui-line-height-tight) + 2 * var(--_ui-select-inset-block) +
10221
+ 2 * var(--ui-border-width)
10222
+ )
10223
+ );
10115
10224
  min-block-size: var(--ui-control-size-md);
10116
10225
  margin: 0 !important;
10117
- padding: var(--ui-control-inset-block-md, var(--ui-space-2)) var(--ui-space-3) !important;
10226
+ padding: var(--_ui-select-inset-block) var(--ui-space-3) !important;
10118
10227
  border: var(--ui-border-width) solid
10119
10228
  var(--ui-select-border, var(--ui-control-border, var(--ui-border-strong)));
10120
10229
  border-radius: var(--ui-select-radius, var(--ui-field-radius, var(--ui-radius-md)));
@@ -10190,8 +10299,10 @@ dialog:where([data-hn-ui-search-shell]) {
10190
10299
  cursor: not-allowed;
10191
10300
  }
10192
10301
  :scope[data-ui-select-state~="size=sm"]:where([data-hn-ui-select]) {
10302
+ --_ui-select-size: var(--ui-control-size-sm);
10303
+ --_ui-select-inset-block: var(--ui-control-inset-block-sm, var(--ui-space-1));
10193
10304
  min-block-size: var(--ui-control-size-sm);
10194
- padding: var(--ui-control-inset-block-sm, var(--ui-space-1)) var(--ui-space-2) !important;
10305
+ padding: var(--_ui-select-inset-block) var(--ui-space-2) !important;
10195
10306
  padding-inline-end: calc(var(--ui-space-2) + var(--ui-icon-size-sm) + var(--ui-space-1))
10196
10307
  !important;
10197
10308
  background-position: right var(--ui-space-2) center, center;
@@ -10201,8 +10312,10 @@ dialog:where([data-hn-ui-search-shell]) {
10201
10312
  font-size: var(--ui-font-size-sm);
10202
10313
  }
10203
10314
  :scope[data-ui-select-state~="size=lg"]:where([data-hn-ui-select]) {
10315
+ --_ui-select-size: var(--ui-control-size-lg);
10316
+ --_ui-select-inset-block: var(--ui-control-inset-block-lg, var(--ui-space-3));
10204
10317
  min-block-size: var(--ui-control-size-lg);
10205
- padding: var(--ui-control-inset-block-lg, var(--ui-space-3)) var(--ui-space-4) !important;
10318
+ padding: var(--_ui-select-inset-block) var(--ui-space-4) !important;
10206
10319
  padding-inline-end: calc(var(--ui-space-4) + 1.5rem) !important;
10207
10320
  background-position: right var(--ui-space-4) center, center;
10208
10321
  font-size: var(--ui-font-size-md);
@@ -13714,6 +13827,7 @@ html[data-ui-input-modality="touch"]
13714
13827
 
13715
13828
  :scope:where([data-component~="ui-button"]) {
13716
13829
  --_button-square-size: var(--ui-button-min-block-size, var(--ui-control-size-md));
13830
+ box-sizing: border-box !important;
13717
13831
  appearance: none;
13718
13832
  min-block-size: var(--ui-button-min-block-size, var(--ui-control-size-md));
13719
13833
  border-style: solid;
@@ -13760,6 +13874,21 @@ html[data-ui-input-modality="touch"]
13760
13874
  padding-block: var(--ui-space-0-5) !important;
13761
13875
  }
13762
13876
 
13877
+ /* Trim the text line itself: an anonymous flex item retains font-metric space in some fonts. */
13878
+ .label {
13879
+ display: block !important;
13880
+ align-content: center !important;
13881
+ min-inline-size: 0 !important;
13882
+ min-block-size: 1lh !important;
13883
+ }
13884
+
13885
+ .label:has(svg) {
13886
+ display: inline-flex !important;
13887
+ align-items: center !important;
13888
+ gap: var(--ui-space-2) !important;
13889
+ text-box-trim: none;
13890
+ }
13891
+
13763
13892
  .badge {
13764
13893
  display: inline-flex !important;
13765
13894
  align-items: center !important;
@@ -13771,7 +13900,7 @@ html[data-ui-input-modality="touch"]
13771
13900
  }
13772
13901
 
13773
13902
  @supports (text-box-trim: trim-both) {
13774
- :scope:where([data-component~="ui-button"]) {
13903
+ .label:not(:has(svg)) {
13775
13904
  text-box-trim: trim-both;
13776
13905
  text-box-edge: cap alphabetic;
13777
13906
  }
@@ -14099,6 +14228,11 @@ html[data-ui-input-modality="touch"]
14099
14228
  transition: color var(--ui-motion-fast) var(--ui-motion-ease), text-decoration-color var(--ui-motion-fast) var(--ui-motion-ease);
14100
14229
  }
14101
14230
 
14231
+ :scope:where([data-component~="ui-button"])[data-appearance="link"] .label {
14232
+ display: inline !important;
14233
+ text-box-trim: none;
14234
+ }
14235
+
14102
14236
  :scope:where([data-component~="ui-button"])[data-appearance="link"]:hover:not(:disabled, [aria-disabled="true"]) {
14103
14237
  color: var(--ui-button-link-hover-text, var(--ui-text-primary));
14104
14238
  text-decoration-color: currentColor;
@@ -14136,6 +14270,8 @@ html[data-ui-input-modality="touch"]
14136
14270
  /* A count is an adornment, not another line of label text. Keep the standard control height
14137
14271
  with enough inset for a 24px mark; large content can still grow the button naturally. */
14138
14272
 
14273
+ /* Trim the text line itself: an anonymous flex item retains font-metric space in some fonts. */
14274
+
14139
14275
  @supports (text-box-trim: trim-both) {
14140
14276
  }
14141
14277
 
@@ -16474,7 +16610,8 @@ html[data-ui-input-modality="touch"]
16474
16610
 
16475
16611
  input:where(:not([data-component], [data-slotted]))::after {
16476
16612
  content: "";
16477
- position: absolute;
16613
+ position: absolute !important;
16614
+ transform: none !important;
16478
16615
  opacity: 0;
16479
16616
  transition: opacity var(--ui-motion-fast) var(--ui-motion-ease);
16480
16617
  }
@@ -16487,43 +16624,44 @@ html[data-ui-input-modality="touch"]
16487
16624
  box-shadow: var(--ui-control-inset);
16488
16625
  }
16489
16626
 
16490
- /* Centre the tick's box and lift it slightly for the rotated check shape. */
16627
+ /* The SVG's painted bounds are centred in its viewBox, including its round stroke.
16628
+ Centre that box directly; rotated border boxes do not centre the visible check. */
16491
16629
  input:checked:where(:not([data-component], [data-slotted]))::after {
16492
- inset: 0;
16493
- margin: auto !important;
16494
- inline-size: calc(var(--_ui-checkbox-size) * 0.28 / 1.125);
16495
- block-size: calc(var(--_ui-checkbox-size) * 0.5 / 1.125);
16496
- /* Longhands, not `border: solid var(...)`: lowering drops a shorthand that omits a
16497
- component, which left the tick with no style and no colour. */
16498
- border-style: solid;
16499
- border-color: var(--ui-text-on-accent);
16500
- border-width: 0 calc(var(--_ui-checkbox-size) * 0.125 / 1.125) calc(var(--_ui-checkbox-size) * 0.125 / 1.125) 0;
16630
+ inset: 50% auto auto 50% !important;
16631
+ inline-size: calc(var(--_ui-checkbox-size) * 0.7) !important;
16632
+ block-size: calc(var(--_ui-checkbox-size) * 0.7) !important;
16633
+ background: var(--ui-text-on-accent);
16634
+ mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 11.5 5 5 9-9'/%3E%3C/svg%3E")
16635
+ center / contain no-repeat;
16501
16636
  opacity: 1;
16502
- transform: translateY(calc(var(--_ui-checkbox-size) * -0.09 / 1.125)) rotate(45deg);
16637
+ translate: -50% -50% !important;
16503
16638
  animation: ui-checkbox-check var(--ui-motion-base) var(--ui-motion-ease-out, cubic-bezier(0.16, 1, 0.3, 1)) both;
16504
16639
  }
16505
16640
 
16506
16641
  input:indeterminate:where(:not([data-component], [data-slotted]))::after {
16507
- inset: 50% calc(var(--_ui-checkbox-size) * 0.23 / 1.125) auto;
16508
- block-size: calc(var(--_ui-checkbox-size) * 0.125 / 1.125);
16642
+ mask: none;
16643
+ animation: none;
16644
+ inset: 50% calc(var(--_ui-checkbox-size) * 0.23 / 1.125) auto !important;
16645
+ inline-size: auto !important;
16646
+ block-size: calc(var(--_ui-checkbox-size) * 0.125 / 1.125) !important;
16509
16647
  border-radius: var(--ui-radius-round);
16510
16648
  background: var(--ui-text-on-accent);
16511
16649
  opacity: 1;
16512
- transform: translateY(-50%);
16650
+ translate: 0 -50% !important;
16513
16651
  }
16514
16652
 
16515
16653
  @keyframes ui-checkbox-check {
16516
16654
  from {
16517
16655
  opacity: 0;
16518
- transform: translateY(calc(var(--_ui-checkbox-size) * -0.09 / 1.125)) rotate(45deg) scale(0.55);
16656
+ scale: 0.55;
16519
16657
  }
16520
16658
  65% {
16521
16659
  opacity: 1;
16522
- transform: translateY(calc(var(--_ui-checkbox-size) * -0.09 / 1.125)) rotate(45deg) scale(1.12);
16660
+ scale: 1.12;
16523
16661
  }
16524
16662
  to {
16525
16663
  opacity: 1;
16526
- transform: translateY(calc(var(--_ui-checkbox-size) * -0.09 / 1.125)) rotate(45deg) scale(1);
16664
+ scale: 1;
16527
16665
  }
16528
16666
  }
16529
16667
 
@@ -16534,6 +16672,20 @@ html[data-ui-input-modality="touch"]
16534
16672
  }
16535
16673
  }
16536
16674
 
16675
+ @media (forced-colors: active) {
16676
+ input:checked,
16677
+ input:indeterminate {
16678
+ forced-color-adjust: none;
16679
+ background: Highlight;
16680
+ border-color: Highlight;
16681
+ }
16682
+ input:checked:where(:not([data-component], [data-slotted]))::after,
16683
+ input:indeterminate:where(:not([data-component], [data-slotted]))::after {
16684
+ forced-color-adjust: none;
16685
+ background: HighlightText;
16686
+ }
16687
+ }
16688
+
16537
16689
  input:hover:enabled {
16538
16690
  border-color: var(--ui-accent-solid);
16539
16691
  }
@@ -16591,11 +16743,15 @@ html[data-ui-input-modality="touch"]
16591
16743
 
16592
16744
  /* The label, and under it an optional line saying what the choice means. */
16593
16745
 
16594
- /* Centre the tick's box and lift it slightly for the rotated check shape. */
16746
+ /* The SVG's painted bounds are centred in its viewBox, including its round stroke.
16747
+ Centre that box directly; rotated border boxes do not centre the visible check. */
16595
16748
 
16596
16749
  @media (prefers-reduced-motion: reduce) {
16597
16750
  }
16598
16751
 
16752
+ @media (forced-colors: active) {
16753
+ }
16754
+
16599
16755
  /* A sized choice keeps its box and aligns instead: the label takes that size's field type size,
16600
16756
  and the first line centres in that control height, so the label shares a row's baseline.
16601
16757
  Multi-line labels and descriptions still grow downward from that first line. */
@@ -16889,15 +17045,24 @@ html[data-ui-input-modality="touch"]
16889
17045
  syntax: "*";
16890
17046
  inherits: false;
16891
17047
  }
17048
+ /* Normalize a unitless zero border to a length before the box calculation. */
17049
+ @property --_ui-input-stroke {
17050
+ syntax: "<length>";
17051
+ inherits: false;
17052
+ initial-value: 1px;
17053
+ }
16892
17054
 
16893
17055
  :scope:where([data-component~="ui-input"]) {
17056
+ --_ui-input-size: var(--ui-control-size-md);
17057
+ --_ui-input-inset-block: var(--ui-control-inset-block-md, var(--ui-space-2));
17058
+ --_ui-input-stroke: var(--ui-input-border-width, var(--_ui-default-input-border-width, var(--ui-border-width)));
16894
17059
  box-sizing: border-box !important;
16895
17060
  display: inline-block !important;
16896
17061
  inline-size: var(--ui-input-inline-size, 100%);
16897
17062
  min-inline-size: 0;
16898
17063
  min-block-size: var(--ui-input-min-block-size, var(--_ui-default-input-min-block-size, var(--ui-control-size-md)));
16899
17064
  margin: 0 !important;
16900
- padding: var(--ui-control-inset-block-md, var(--ui-space-2)) var(--ui-space-3) !important;
17065
+ padding: var(--_ui-input-inset-block) var(--ui-space-3) !important;
16901
17066
  appearance: none;
16902
17067
  padding-inline-start: var(--_ui-default-input-padding-inline-start, var(--ui-space-3)) !important;
16903
17068
  border: var(--ui-input-border-width, var(--_ui-default-input-border-width, var(--ui-border-width))) solid
@@ -16915,16 +17080,25 @@ html[data-ui-input-modality="touch"]
16915
17080
  background-color var(--ui-motion-fast) var(--ui-motion-ease);
16916
17081
  }
16917
17082
 
17083
+ /* Cap Safari's excess text metrics without changing native date, file, color or range widgets. */
17084
+ :scope:where([data-component~="ui-input"]):is([type="text"], [type="search"], [type="tel"], [type="url"], [type="email"], [type="password"], [type="number"]) {
17085
+ max-block-size: max(calc(var(--_ui-input-size) - var(--_ui-default-input-frame-width, 0px)), calc(1em * var(--ui-line-height-tight) + 2 * var(--_ui-input-inset-block) + 2 * var(--_ui-input-stroke)));
17086
+ }
17087
+
16918
17088
  /* Each size reads the hook and then an Input Group's default first, so a group, which draws the frame, can zero it. */
16919
17089
  :scope:where([data-component~="ui-input"])[data-ui-input-state~="size=sm"] {
17090
+ --_ui-input-size: var(--ui-control-size-sm);
17091
+ --_ui-input-inset-block: var(--ui-control-inset-block-sm, var(--ui-space-1));
16920
17092
  min-block-size: var(--ui-input-min-block-size, var(--_ui-default-input-min-block-size, var(--ui-control-size-sm)));
16921
- padding: var(--ui-control-inset-block-sm, var(--ui-space-1)) var(--ui-space-2) !important;
17093
+ padding: var(--_ui-input-inset-block) var(--ui-space-2) !important;
16922
17094
  font-size: var(--ui-font-size-sm);
16923
17095
  }
16924
17096
 
16925
17097
  :scope:where([data-component~="ui-input"])[data-ui-input-state~="size=lg"] {
17098
+ --_ui-input-size: var(--ui-control-size-lg);
17099
+ --_ui-input-inset-block: var(--ui-control-inset-block-lg, var(--ui-space-3));
16926
17100
  min-block-size: var(--ui-input-min-block-size, var(--_ui-default-input-min-block-size, var(--ui-control-size-lg)));
16927
- padding: var(--ui-control-inset-block-lg, var(--ui-space-3)) var(--ui-space-4) !important;
17101
+ padding: var(--_ui-input-inset-block) var(--ui-space-4) !important;
16928
17102
  font-size: var(--ui-font-size-md);
16929
17103
  }
16930
17104
 
@@ -17005,6 +17179,9 @@ html[data-ui-input-modality="touch"]
17005
17179
  @scope ([data-component~="ui-input"]) to ([data-component]) {
17006
17180
  /* This component's hooks style the element they are set on, and never a nested one. An Input
17007
17181
  Group sets --_ui-default-input-* for the input inside it, below the input's own hooks. */
17182
+ /* Normalize a unitless zero border to a length before the box calculation. */
17183
+
17184
+ /* Cap Safari's excess text metrics without changing native date, file, color or range widgets. */
17008
17185
 
17009
17186
  /* Each size reads the hook and then an Input Group's default first, so a group, which draws the frame, can zero it. */
17010
17187