@threadlabs/looma 0.30.9 → 0.31.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (270) hide show
  1. package/components/shared/icons.js +1 -0
  2. package/components/ui-affordance-scope/ui-affordance-scope.html +1 -1
  3. package/components/ui-affordance-scope/ui-affordance-scope.js +1 -6
  4. package/components/ui-avatar/ui-avatar.html +1 -1
  5. package/components/ui-avatar/ui-avatar.js +1 -6
  6. package/components/ui-avatar-group/ui-avatar-group.html +1 -1
  7. package/components/ui-avatar-group/ui-avatar-group.js +1 -6
  8. package/components/ui-button/ui-button.html +1 -1
  9. package/components/ui-button/ui-button.js +1 -6
  10. package/components/ui-checkbox/ui-checkbox.html +1 -1
  11. package/components/ui-checkbox/ui-checkbox.js +1 -6
  12. package/components/ui-combobox/ui-combobox.html +1 -1
  13. package/components/ui-combobox/ui-combobox.js +1 -6
  14. package/components/ui-context-menu/ui-context-menu.html +1 -1
  15. package/components/ui-context-menu/ui-context-menu.js +1 -6
  16. package/components/ui-dialog/ui-dialog.html +1 -1
  17. package/components/ui-dialog/ui-dialog.js +1 -6
  18. package/components/ui-disclosure/ui-disclosure.html +1 -1
  19. package/components/ui-disclosure/ui-disclosure.js +1 -6
  20. package/components/ui-editable/ui-editable.html +1 -1
  21. package/components/ui-editable/ui-editable.js +1 -6
  22. package/components/ui-editor-block-actions/ui-editor-block-actions.html +1 -1
  23. package/components/ui-editor-block-actions/ui-editor-block-actions.js +1 -6
  24. package/components/ui-editor-chip-editor/ui-editor-chip-editor.html +1 -1
  25. package/components/ui-editor-chip-editor/ui-editor-chip-editor.js +1 -6
  26. package/components/ui-editor-code-language/ui-editor-code-language.html +1 -1
  27. package/components/ui-editor-code-language/ui-editor-code-language.js +1 -6
  28. package/components/ui-editor-footnote-editor/ui-editor-footnote-editor.html +57 -0
  29. package/components/ui-editor-footnote-editor/ui-editor-footnote-editor.js +38 -0
  30. package/components/ui-editor-image-toolbar/ui-editor-image-toolbar.html +1 -1
  31. package/components/ui-editor-image-toolbar/ui-editor-image-toolbar.js +1 -6
  32. package/components/ui-editor-insert-table-grid/ui-editor-insert-table-grid.html +1 -1
  33. package/components/ui-editor-insert-table-grid/ui-editor-insert-table-grid.js +1 -6
  34. package/components/ui-editor-link-card/ui-editor-link-card.html +1 -1
  35. package/components/ui-editor-link-card/ui-editor-link-card.js +1 -6
  36. package/components/ui-editor-link-form/ui-editor-link-form.html +1 -1
  37. package/components/ui-editor-link-form/ui-editor-link-form.js +1 -6
  38. package/components/ui-editor-mention-menu/ui-editor-mention-menu.html +1 -1
  39. package/components/ui-editor-mention-menu/ui-editor-mention-menu.js +1 -6
  40. package/components/ui-editor-slash-menu/ui-editor-slash-menu.html +1 -1
  41. package/components/ui-editor-slash-menu/ui-editor-slash-menu.js +1 -6
  42. package/components/ui-editor-table-context-menu/ui-editor-table-context-menu.html +1 -1
  43. package/components/ui-editor-table-context-menu/ui-editor-table-context-menu.js +1 -6
  44. package/components/ui-editor-table-overlay/ui-editor-table-overlay.html +1 -1
  45. package/components/ui-editor-table-overlay/ui-editor-table-overlay.js +1 -6
  46. package/components/ui-editor-table-toolbar/ui-editor-table-toolbar.html +1 -1
  47. package/components/ui-editor-table-toolbar/ui-editor-table-toolbar.js +1 -6
  48. package/components/ui-editor-toolbar/ui-editor-toolbar.html +1 -1
  49. package/components/ui-editor-toolbar/ui-editor-toolbar.js +1 -6
  50. package/components/ui-form-field/ui-form-field.html +1 -1
  51. package/components/ui-form-field/ui-form-field.js +1 -6
  52. package/components/ui-icon/ui-icon.html +1 -0
  53. package/components/ui-icon-button/ui-icon-button.html +1 -1
  54. package/components/ui-icon-button/ui-icon-button.js +1 -6
  55. package/components/ui-image/ui-image.html +1 -1
  56. package/components/ui-image/ui-image.js +1 -6
  57. package/components/ui-input/ui-input.html +1 -1
  58. package/components/ui-input/ui-input.js +1 -6
  59. package/components/ui-input-group/ui-input-group.html +1 -1
  60. package/components/ui-input-group/ui-input-group.js +1 -6
  61. package/components/ui-listbox/ui-listbox.html +1 -1
  62. package/components/ui-listbox/ui-listbox.js +1 -6
  63. package/components/ui-menu/ui-menu.html +1 -1
  64. package/components/ui-menu/ui-menu.js +1 -6
  65. package/components/ui-menu-item/ui-menu-item.html +1 -1
  66. package/components/ui-menu-item/ui-menu-item.js +1 -6
  67. package/components/ui-popover/ui-popover.html +1 -1
  68. package/components/ui-popover/ui-popover.js +1 -6
  69. package/components/ui-radio/ui-radio.html +1 -1
  70. package/components/ui-radio/ui-radio.js +1 -6
  71. package/components/ui-radio-group/ui-radio-group.html +1 -1
  72. package/components/ui-radio-group/ui-radio-group.js +1 -6
  73. package/components/ui-scroll-area/ui-scroll-area.html +1 -1
  74. package/components/ui-scroll-area/ui-scroll-area.js +1 -6
  75. package/components/ui-search-shell/ui-search-shell.html +1 -1
  76. package/components/ui-search-shell/ui-search-shell.js +1 -6
  77. package/components/ui-select/ui-select.html +1 -1
  78. package/components/ui-select/ui-select.js +1 -6
  79. package/components/ui-sidebar/ui-sidebar.html +1 -1
  80. package/components/ui-sidebar/ui-sidebar.js +1 -6
  81. package/components/ui-switch/ui-switch.html +1 -1
  82. package/components/ui-switch/ui-switch.js +1 -6
  83. package/components/ui-switcher/ui-switcher.html +1 -1
  84. package/components/ui-switcher/ui-switcher.js +1 -6
  85. package/components/ui-table/ui-table.html +1 -1
  86. package/components/ui-table/ui-table.js +1 -6
  87. package/components/ui-tabs/ui-tabs.html +1 -1
  88. package/components/ui-tabs/ui-tabs.js +1 -6
  89. package/components/ui-textarea/ui-textarea.html +1 -1
  90. package/components/ui-textarea/ui-textarea.js +1 -6
  91. package/components/ui-toast/ui-toast.html +1 -1
  92. package/components/ui-toast/ui-toast.js +1 -6
  93. package/components/ui-toast-region/ui-toast-region.html +1 -1
  94. package/components/ui-toast-region/ui-toast-region.js +1 -6
  95. package/components/ui-tooltip/ui-tooltip.html +1 -1
  96. package/components/ui-tooltip/ui-tooltip.js +1 -6
  97. package/components/ui-tree/ui-tree.html +1 -1
  98. package/components/ui-tree/ui-tree.js +1 -6
  99. package/components/ui-tree-item/ui-tree-item.html +1 -1
  100. package/components/ui-tree-item/ui-tree-item.js +1 -6
  101. package/dist/index.js +37 -36
  102. package/editor/chunks/extensions.js +342 -20
  103. package/editor/expressmark.js +1 -1
  104. package/editor/extensions/footnote.d.ts +40 -7
  105. package/editor/extensions/index.d.ts +1 -1
  106. package/editor/extensions/index.js +2 -2
  107. package/editor/footnote-editing.d.ts +46 -0
  108. package/editor/icons.d.ts +1 -0
  109. package/editor/index.js +4 -3
  110. package/package.json +1 -1
  111. package/styles/ui-editor-footnote-editor.css +1 -0
  112. package/vanilla/UiAffordanceScope.js +4 -4
  113. package/vanilla/UiAvatar.js +4 -4
  114. package/vanilla/UiAvatarGroup.js +4 -4
  115. package/vanilla/UiButton.js +4 -4
  116. package/vanilla/UiCheckbox.js +4 -4
  117. package/vanilla/UiCombobox.js +4 -4
  118. package/vanilla/UiContextMenu.js +4 -4
  119. package/vanilla/UiDialog.js +4 -4
  120. package/vanilla/UiDisclosure.js +4 -4
  121. package/vanilla/UiEditable.js +4 -4
  122. package/vanilla/UiEditorBlockActions.js +4 -4
  123. package/vanilla/UiEditorChipEditor.js +4 -4
  124. package/vanilla/UiEditorCodeLanguage.js +4 -4
  125. package/vanilla/UiEditorFootnoteEditor.d.ts +30 -0
  126. package/vanilla/UiEditorFootnoteEditor.js +101 -0
  127. package/vanilla/UiEditorImageToolbar.js +4 -4
  128. package/vanilla/UiEditorInsertTableGrid.js +4 -4
  129. package/vanilla/UiEditorLinkCard.js +4 -4
  130. package/vanilla/UiEditorLinkForm.js +4 -4
  131. package/vanilla/UiEditorMentionMenu.js +4 -4
  132. package/vanilla/UiEditorSlashMenu.js +4 -4
  133. package/vanilla/UiEditorTableContextMenu.js +4 -4
  134. package/vanilla/UiEditorTableOverlay.js +4 -4
  135. package/vanilla/UiEditorTableToolbar.js +4 -4
  136. package/vanilla/UiEditorToolbar.js +4 -4
  137. package/vanilla/UiFormField.js +4 -4
  138. package/vanilla/UiIcon.js +1 -1
  139. package/vanilla/UiIconButton.js +4 -4
  140. package/vanilla/UiImage.js +4 -4
  141. package/vanilla/UiInput.js +4 -4
  142. package/vanilla/UiInputGroup.js +4 -4
  143. package/vanilla/UiListbox.js +4 -4
  144. package/vanilla/UiMenu.js +4 -4
  145. package/vanilla/UiMenuItem.js +4 -4
  146. package/vanilla/UiPopover.js +4 -4
  147. package/vanilla/UiRadio.js +4 -4
  148. package/vanilla/UiRadioGroup.js +4 -4
  149. package/vanilla/UiScrollArea.js +4 -4
  150. package/vanilla/UiSearchShell.js +4 -4
  151. package/vanilla/UiSelect.js +4 -4
  152. package/vanilla/UiSidebar.js +4 -4
  153. package/vanilla/UiSwitch.js +4 -4
  154. package/vanilla/UiSwitcher.js +4 -4
  155. package/vanilla/UiTable.js +4 -4
  156. package/vanilla/UiTabs.js +4 -4
  157. package/vanilla/UiTextarea.js +4 -4
  158. package/vanilla/UiToast.js +4 -4
  159. package/vanilla/UiToastRegion.js +4 -4
  160. package/vanilla/UiTooltip.js +4 -4
  161. package/vanilla/UiTree.js +4 -4
  162. package/vanilla/UiTreeItem.js +4 -4
  163. package/vanilla/index.js +1 -0
  164. package/vue/UiAffordanceScope.vue +1 -0
  165. package/vue/UiAvatar.vue +1 -0
  166. package/vue/UiAvatarGroup.vue +1 -0
  167. package/vue/UiButton.vue +1 -0
  168. package/vue/UiCheckbox.vue +1 -0
  169. package/vue/UiCombobox.vue +1 -0
  170. package/vue/UiContextMenu.vue +1 -0
  171. package/vue/UiDialog.vue +1 -0
  172. package/vue/UiDisclosure.vue +1 -0
  173. package/vue/UiEditable.vue +1 -0
  174. package/vue/UiEditorBlockActions.vue +1 -0
  175. package/vue/UiEditorChipEditor.vue +1 -0
  176. package/vue/UiEditorCodeLanguage.vue +1 -0
  177. package/vue/UiEditorFootnoteEditor.d.ts +57 -0
  178. package/vue/UiEditorFootnoteEditor.js +2 -0
  179. package/vue/UiEditorFootnoteEditor.vue +304 -0
  180. package/vue/UiEditorImageToolbar.vue +1 -0
  181. package/vue/UiEditorInsertTableGrid.vue +1 -0
  182. package/vue/UiEditorLinkCard.vue +1 -0
  183. package/vue/UiEditorLinkForm.vue +1 -0
  184. package/vue/UiEditorMentionMenu.vue +1 -0
  185. package/vue/UiEditorSlashMenu.vue +1 -0
  186. package/vue/UiEditorTableContextMenu.vue +1 -0
  187. package/vue/UiEditorTableOverlay.vue +1 -0
  188. package/vue/UiEditorTableToolbar.vue +1 -0
  189. package/vue/UiEditorToolbar.vue +1 -0
  190. package/vue/UiFormField.vue +1 -0
  191. package/vue/UiIcon.vue +4 -0
  192. package/vue/UiIconButton.vue +1 -0
  193. package/vue/UiImage.vue +1 -0
  194. package/vue/UiInput.vue +1 -0
  195. package/vue/UiInputGroup.vue +1 -0
  196. package/vue/UiListbox.vue +1 -0
  197. package/vue/UiMenu.vue +1 -0
  198. package/vue/UiMenuItem.vue +1 -0
  199. package/vue/UiPopover.vue +1 -0
  200. package/vue/UiRadio.vue +1 -0
  201. package/vue/UiRadioGroup.vue +1 -0
  202. package/vue/UiScrollArea.vue +1 -0
  203. package/vue/UiSearchShell.vue +1 -0
  204. package/vue/UiSelect.vue +1 -0
  205. package/vue/UiSidebar.vue +1 -0
  206. package/vue/UiSwitch.vue +1 -0
  207. package/vue/UiSwitcher.vue +1 -0
  208. package/vue/UiTable.vue +1 -0
  209. package/vue/UiTabs.vue +1 -0
  210. package/vue/UiTextarea.vue +1 -0
  211. package/vue/UiToast.vue +1 -0
  212. package/vue/UiToastRegion.vue +1 -0
  213. package/vue/UiTooltip.vue +1 -0
  214. package/vue/UiTree.vue +1 -0
  215. package/vue/UiTreeItem.vue +1 -0
  216. package/vue/chunks/UiAffordanceScope.js +2 -1
  217. package/vue/chunks/UiAvatar.js +2 -1
  218. package/vue/chunks/UiAvatarGroup.js +2 -1
  219. package/vue/chunks/UiButton.js +2 -1
  220. package/vue/chunks/UiCheckbox.js +2 -1
  221. package/vue/chunks/UiCombobox.js +2 -1
  222. package/vue/chunks/UiContextMenu.js +2 -1
  223. package/vue/chunks/UiDialog.js +2 -1
  224. package/vue/chunks/UiDisclosure.js +2 -1
  225. package/vue/chunks/UiEditable.js +2 -1
  226. package/vue/chunks/UiEditorBlockActions.js +1 -0
  227. package/vue/chunks/UiEditorChipEditor.js +1 -0
  228. package/vue/chunks/UiEditorCodeLanguage.js +1 -0
  229. package/vue/chunks/UiEditorFootnoteEditor.js +306 -0
  230. package/vue/chunks/UiEditorImageToolbar.js +2 -1
  231. package/vue/chunks/UiEditorInsertTableGrid.js +2 -1
  232. package/vue/chunks/UiEditorLinkCard.js +1 -0
  233. package/vue/chunks/UiEditorLinkForm.js +2 -1
  234. package/vue/chunks/UiEditorMentionMenu.js +2 -1
  235. package/vue/chunks/UiEditorSlashMenu.js +2 -1
  236. package/vue/chunks/UiEditorTableContextMenu.js +2 -1
  237. package/vue/chunks/UiEditorTableOverlay.js +2 -1
  238. package/vue/chunks/UiEditorTableToolbar.js +2 -1
  239. package/vue/chunks/UiEditorToolbar.js +2 -1
  240. package/vue/chunks/UiFormField.js +2 -1
  241. package/vue/chunks/UiIcon.js +15 -1
  242. package/vue/chunks/UiIconButton.js +2 -1
  243. package/vue/chunks/UiImage.js +2 -1
  244. package/vue/chunks/UiInput.js +2 -1
  245. package/vue/chunks/UiInputGroup.js +2 -1
  246. package/vue/chunks/UiListbox.js +2 -1
  247. package/vue/chunks/UiMenu.js +2 -1
  248. package/vue/chunks/UiMenuItem.js +2 -1
  249. package/vue/chunks/UiPopover.js +2 -1
  250. package/vue/chunks/UiRadio.js +2 -1
  251. package/vue/chunks/UiRadioGroup.js +2 -1
  252. package/vue/chunks/UiScrollArea.js +2 -1
  253. package/vue/chunks/UiSearchShell.js +2 -1
  254. package/vue/chunks/UiSelect.js +2 -1
  255. package/vue/chunks/UiSidebar.js +2 -1
  256. package/vue/chunks/UiSwitch.js +2 -1
  257. package/vue/chunks/UiSwitcher.js +2 -1
  258. package/vue/chunks/UiTable.js +2 -1
  259. package/vue/chunks/UiTabs.js +2 -1
  260. package/vue/chunks/UiTextarea.js +2 -1
  261. package/vue/chunks/UiToast.js +2 -1
  262. package/vue/chunks/UiToastRegion.js +2 -1
  263. package/vue/chunks/UiTooltip.js +2 -1
  264. package/vue/chunks/UiTree.js +2 -1
  265. package/vue/chunks/UiTreeItem.js +2 -1
  266. package/vue/components.css +595 -595
  267. package/vue/editor/index.js +668 -80
  268. package/vue/editor/primitives.d.ts +3 -1
  269. package/vue/index.d.ts +1 -0
  270. package/vue/index.js +5 -4
@@ -1783,7 +1783,7 @@ html[data-ui-input-modality="touch"]
1783
1783
  /* The label, and under it an optional line saying what the choice means. */
1784
1784
 
1785
1785
  /* Centre the tick's box and lift it slightly for the rotated check shape. */
1786
- @keyframes ui-checkbox-check-b6776f7f {
1786
+ @keyframes ui-checkbox-check-aac88235 {
1787
1787
  from {
1788
1788
  opacity: 0;
1789
1789
  transform: translateY(-0.09rem) rotate(45deg) scale(0.55);
@@ -1878,7 +1878,7 @@ input:checked:where([data-hn-ui-checkbox])::after {
1878
1878
  border-width: 0 0.125rem 0.125rem 0;
1879
1879
  opacity: 1;
1880
1880
  transform: translateY(-0.09rem) rotate(45deg);
1881
- animation: ui-checkbox-check-b6776f7f 180ms var(--ui-motion-ease-out, cubic-bezier(0.16, 1, 0.3, 1))
1881
+ animation: ui-checkbox-check-aac88235 180ms var(--ui-motion-ease-out, cubic-bezier(0.16, 1, 0.3, 1))
1882
1882
  both;
1883
1883
  }
1884
1884
  input:indeterminate:where([data-hn-ui-checkbox])::after {
@@ -3042,13 +3042,13 @@ dd:where([data-hn-ui-description-item]) {
3042
3042
  /* A CSS-drawn X. */
3043
3043
 
3044
3044
  /* A touch target, like Button on coarse pointers. */
3045
- @keyframes ui-dialog-enter-f26be724 {
3045
+ @keyframes ui-dialog-enter-0e4bd8b5 {
3046
3046
  from {
3047
3047
  opacity: 0;
3048
3048
  transform: scale(0.96);
3049
3049
  }
3050
3050
  }
3051
- @keyframes ui-dialog-backdrop-enter-f26be724 {
3051
+ @keyframes ui-dialog-backdrop-enter-0e4bd8b5 {
3052
3052
  from {
3053
3053
  background-color: transparent;
3054
3054
  }
@@ -3096,7 +3096,7 @@ from {
3096
3096
  pointer-events: auto;
3097
3097
  opacity: 1;
3098
3098
  transform: scale(1);
3099
- animation: ui-dialog-enter-f26be724 var(--ui-dialog-duration, var(--ui-motion-base))
3099
+ animation: ui-dialog-enter-0e4bd8b5 var(--ui-dialog-duration, var(--ui-motion-base))
3100
3100
  var(--ui-motion-ease);
3101
3101
  }
3102
3102
  :scope[data-ui-dialog-state~="size=sm"]:where([data-hn-ui-dialog]) {
@@ -3217,7 +3217,7 @@ footer:empty:where([data-hn-ui-dialog]) {
3217
3217
  }
3218
3218
  :scope[open]:modal:where([data-hn-ui-dialog])::backdrop {
3219
3219
  background-color: var(--ui-overlay-backdrop);
3220
- animation: ui-dialog-backdrop-enter-f26be724 var(--_ui-dialog-duration, var(--ui-motion-base))
3220
+ animation: ui-dialog-backdrop-enter-0e4bd8b5 var(--_ui-dialog-duration, var(--ui-motion-base))
3221
3221
  var(--ui-motion-ease);
3222
3222
  }
3223
3223
  :scope[open][data-ui-backdrop-hidden]:where([data-hn-ui-dialog])::backdrop {
@@ -4243,6 +4243,530 @@ legend.sr-only:where([data-hn-ui-radio-group]) {
4243
4243
  }
4244
4244
  }
4245
4245
 
4246
+ /* This component's hooks style the element they are set on, and never a nested one. */
4247
+ @property --ui-form-field-danger {
4248
+ syntax: "*";
4249
+ inherits: false;
4250
+ }
4251
+ @property --ui-form-field-help-font-size {
4252
+ syntax: "*";
4253
+ inherits: false;
4254
+ }
4255
+ @property --ui-form-field-help-min-block-size {
4256
+ syntax: "*";
4257
+ inherits: false;
4258
+ }
4259
+ @property --ui-form-field-help-text {
4260
+ syntax: "*";
4261
+ inherits: false;
4262
+ }
4263
+ @property --ui-form-field-label-font-size {
4264
+ syntax: "*";
4265
+ inherits: false;
4266
+ }
4267
+ @property --ui-form-field-label-text {
4268
+ syntax: "*";
4269
+ inherits: false;
4270
+ }
4271
+ @property --ui-form-field-min-inline-size {
4272
+ syntax: "*";
4273
+ inherits: false;
4274
+ }
4275
+
4276
+ /* Each named region styles whatever fills it, however it was slotted (slot="…" in HTML, #label
4277
+ in Vue), and generates no box of its own, so an empty region adds no gap. */
4278
+
4279
+ /* A label action, such as a small help button, sits after the label text in a box one line
4280
+ tall, centred on the first line and overflowing it. A button taller than a line of label
4281
+ text then never makes this field's label row taller than its neighbours' in a grid row. */
4282
+
4283
+ /* An error reads in the danger colour, the one the invalid control's border takes. */
4284
+
4285
+ /* A component that sets its display still honours the hidden attribute on its root. */
4286
+ @scope (.ui-form-field) to ([data-hn]) {
4287
+ :scope:where([data-hn-ui-form-field]) {
4288
+ /* Hooks do not inherit, so the parts below read them from the root. */
4289
+ --_ui-form-field-danger: var(--ui-form-field-danger);
4290
+ --_ui-form-field-help-min-block-size: var(--ui-form-field-help-min-block-size);
4291
+ --_ui-form-field-label-text: var(--ui-form-field-label-text);
4292
+ --_ui-form-field-label-font-size: var(--ui-form-field-label-font-size);
4293
+ --_ui-form-field-help-text: var(--ui-form-field-help-text);
4294
+ --_ui-form-field-help-font-size: var(--ui-form-field-help-font-size);
4295
+
4296
+ display: grid;
4297
+ gap: var(--ui-space-2);
4298
+ min-inline-size: var(--ui-form-field-min-inline-size, 0);
4299
+ align-content: start;
4300
+ color: var(--ui-text-primary);
4301
+ }
4302
+ .label:where([data-hn-ui-form-field]),.help:where([data-hn-ui-form-field]),.error:where([data-hn-ui-form-field]) {
4303
+ display: contents;
4304
+ }
4305
+ .label:where([data-hn-ui-form-field]) {
4306
+ color: var(--_ui-form-field-label-text, var(--ui-text-secondary));
4307
+ font-size: var(--_ui-form-field-label-font-size, var(--ui-font-size-sm));
4308
+ }
4309
+ .label:has(> .label-action > *):where([data-hn-ui-form-field]) {
4310
+ display: flex;
4311
+ align-items: start;
4312
+ gap: var(--ui-space-1);
4313
+ }
4314
+ .label-action:where([data-hn-ui-form-field]) {
4315
+ display: flex;
4316
+ align-items: unsafe center;
4317
+ block-size: 1lh;
4318
+ }
4319
+ .label-action:not(:has(> *)):where([data-hn-ui-form-field]) {
4320
+ display: none;
4321
+ }
4322
+ .help:where([data-hn-ui-form-field]) {
4323
+ color: var(--_ui-form-field-help-text, var(--ui-text-muted));
4324
+ font-size: var(--_ui-form-field-help-font-size, var(--ui-font-size-sm));
4325
+ line-height: var(--ui-line-height-md);
4326
+ }
4327
+ .help > :where(:not([data-hn-ui-form-field])):is(*) {
4328
+ min-block-size: var(--_ui-form-field-help-min-block-size, 0);
4329
+ }
4330
+ .error:where([data-hn-ui-form-field]) {
4331
+ display: none;
4332
+ }
4333
+ :scope[data-ui-form-field-state~="invalid"] .error:where([data-hn-ui-form-field]) {
4334
+ display: contents;
4335
+ }
4336
+ .error:where([data-hn-ui-form-field]),:where(:not([data-hn-ui-form-field])):is([role="alert"]) {
4337
+ color: var(--_ui-form-field-danger, var(--ui-field-danger, var(--ui-danger)));
4338
+ font-size: var(--ui-font-size-sm);
4339
+ }
4340
+ :scope[hidden]:where([data-hn-ui-form-field]) {
4341
+ display: none;
4342
+ }
4343
+ }
4344
+
4345
+ @property --ui-input-group-radius {
4346
+ syntax: "*";
4347
+ inherits: false;
4348
+ }
4349
+ @property --ui-input-group-invalid-border {
4350
+ syntax: "*";
4351
+ inherits: false;
4352
+ }
4353
+ @property --ui-input-group-invalid-focus-shadow {
4354
+ syntax: "*";
4355
+ inherits: false;
4356
+ }
4357
+ /* An input with fixed text before or after it, such as a domain after a site's name
4358
+ ("acme" + ".example.com") or slashes around a path. The group draws the field's border and
4359
+ focus ring around the input and its affixes together; the input inside drops its own through
4360
+ its custom properties, so it is still the one ui-input, with its form behaviour intact. The
4361
+ affixes are plain text beside the input, so name the input with a label that says what the
4362
+ whole value is. The action slot takes one button at the end, inside the border, for the one
4363
+ thing the field is for ("Continue" after a site's address), so it reads as the field's action
4364
+ and not the form's. */
4365
+
4366
+ /* The frame takes its input's size, so a small group lines up with small buttons and fields. */
4367
+
4368
+ /* The ring shows when the field's input would show its own: when it is focus-visible, which a
4369
+ text input is for a pointer as well as a keyboard. A focused action button draws its own. */
4370
+
4371
+ /* Forced colors drop box shadows, so the focus ring becomes an outline. */
4372
+
4373
+ /* Fixed text is part of the value, but should not look editable. */
4374
+
4375
+ /* Centred rather than padded above and below: the group is exactly a lone Input's height, so a
4376
+ small button sits inside it with the difference split evenly, and the field keeps its height. */
4377
+
4378
+ /* Multiline text owns the first row; its action remains inside the same frame below it. */
4379
+
4380
+ /* The same textarea keeps its full resizeable box. Its text reserves the action's live width,
4381
+ so a translated label or pending indicator cannot cover what the person types. */
4382
+
4383
+ /* A component that sets its display still honours the hidden attribute on its root. */
4384
+ @scope (.ui-input-group) to ([data-hn]) {
4385
+ :scope:where([data-hn-ui-input-group]) {
4386
+ /* The group's own border and height stand for the input's, so the group is a lone Input's height.
4387
+ Hooks do not inherit, so these are defaults for the input; its own hooks still win. */
4388
+ --_ui-default-input-border-width: 0;
4389
+ --_ui-default-input-min-block-size: 0;
4390
+ --_ui-default-input-border: transparent;
4391
+ --_ui-default-input-border-hover: transparent;
4392
+ --_ui-default-input-focus-border: transparent;
4393
+ --_ui-default-input-invalid-border: transparent;
4394
+ --_ui-default-input-invalid-focus-shadow: none;
4395
+ --_ui-default-input-shadow: none;
4396
+ --_ui-default-input-focus-shadow: none;
4397
+ --_ui-default-input-focus-outline: none;
4398
+ --_ui-default-input-radius: 0;
4399
+ --_ui-default-input-surface: transparent;
4400
+ --_ui-default-textarea-border-width: 0;
4401
+ --_ui-default-textarea-border: transparent;
4402
+ --_ui-default-textarea-border-hover: transparent;
4403
+ --_ui-default-textarea-focus-border: transparent;
4404
+ --_ui-default-textarea-invalid-border: transparent;
4405
+ --_ui-default-textarea-invalid-focus-shadow: none;
4406
+ --_ui-default-textarea-shadow: none;
4407
+ --_ui-default-textarea-focus-shadow: none;
4408
+ --_ui-default-textarea-focus-outline: none;
4409
+ --_ui-default-textarea-radius: 0;
4410
+ --_ui-default-textarea-surface: transparent;
4411
+
4412
+ display: flex;
4413
+ align-items: stretch;
4414
+ box-sizing: border-box;
4415
+ inline-size: 100%;
4416
+ min-inline-size: 0;
4417
+ min-block-size: var(--ui-control-size-md);
4418
+ /* The frame reads the shared control tokens with a lone Input's fallbacks, so the two match. */
4419
+ border: var(--ui-border-width) solid var(--ui-control-border, var(--ui-border-strong));
4420
+ border-radius: var(--ui-input-group-radius, var(--ui-field-radius, var(--ui-radius-md)));
4421
+ background: var(--ui-control-surface, var(--ui-surface-elevated));
4422
+ box-shadow: var(--ui-control-inset);
4423
+ overflow: hidden;
4424
+ /* A press anywhere in the frame focuses the input. */
4425
+ cursor: text;
4426
+ transition:
4427
+ border-color var(--ui-motion-fast) var(--ui-motion-ease),
4428
+ box-shadow var(--ui-motion-fast) var(--ui-motion-ease);
4429
+ }
4430
+ :scope[data-ui-input-group-state~="variant=subtle"]:where([data-hn-ui-input-group]) {
4431
+ border-color: var(--ui-border);
4432
+ background: var(--ui-surface-muted);
4433
+ box-shadow: none;
4434
+ }
4435
+ :scope:has(.field [data-ui-input-state~="size=sm"]):where([data-hn-ui-input-group]) {
4436
+ min-block-size: var(--ui-control-size-sm);
4437
+ }
4438
+ :scope:has(.field [data-ui-input-state~="size=lg"]):where([data-hn-ui-input-group]) {
4439
+ min-block-size: var(--ui-control-size-lg);
4440
+ }
4441
+ @media (pointer: coarse) {
4442
+ :scope:where([data-hn-ui-input-group]) {
4443
+ min-block-size: max(var(--ui-control-size-md), var(--ui-control-min-block-size));
4444
+ }
4445
+ :scope:has(.field [data-ui-input-state~="size=sm"]):where([data-hn-ui-input-group]) {
4446
+ min-block-size: var(--ui-control-min-block-size);
4447
+ }
4448
+ }
4449
+ :scope:hover:not(:has(:is(input, textarea):focus, :is(input, textarea):disabled, :is(input, textarea):read-only, [aria-invalid="true"], :is(:user-invalid, [data-user-invalid]))):where([data-hn-ui-input-group]) {
4450
+ border-color: var(--ui-control-border-hover, var(--ui-text-secondary));
4451
+ }
4452
+ :scope:has(.field :is(input, textarea):focus-visible):where([data-hn-ui-input-group]) {
4453
+ border-color: var(--ui-control-focus, var(--ui-accent-solid));
4454
+ box-shadow:
4455
+ var(--ui-control-inset),
4456
+ var(--ui-control-focus-halo-shadow);
4457
+ }
4458
+ :scope:has([aria-invalid="true"], :is(:user-invalid, [data-user-invalid])):where([data-hn-ui-input-group]) {
4459
+ border-color: var(
4460
+ --ui-input-group-invalid-border,
4461
+ var(--ui-field-danger, var(--ui-danger-solid))
4462
+ );
4463
+ }
4464
+ :scope:has(:is(input, textarea):is([aria-invalid="true"], :is(:user-invalid, [data-user-invalid])):focus-visible):where([data-hn-ui-input-group]) {
4465
+ box-shadow: var(
4466
+ --ui-input-group-invalid-focus-shadow,
4467
+ var(--ui-control-inset),
4468
+ 0 0 0 calc(var(--ui-focus-width) * 1.5) color-mix(
4469
+ in srgb,
4470
+ var(--ui-input-group-invalid-border, var(--ui-field-danger, var(--ui-danger-solid))) 22%,
4471
+ transparent
4472
+ )
4473
+ );
4474
+ }
4475
+ @media (forced-colors: active) {
4476
+ :scope:has(:is(input, textarea):focus-visible):where([data-hn-ui-input-group]) {
4477
+ outline: var(--ui-focus-width) solid Highlight;
4478
+ outline-offset: var(--ui-border-width);
4479
+ }
4480
+ }
4481
+ :scope[data-ui-input-group-state~="disabled"]:where([data-hn-ui-input-group]),:scope:has(:is(input, textarea):disabled):where([data-hn-ui-input-group]) {
4482
+ background: var(--ui-control-surface-disabled, var(--ui-surface-muted));
4483
+ box-shadow: none;
4484
+ cursor: not-allowed;
4485
+ }
4486
+ .field:where([data-hn-ui-input-group]) {
4487
+ display: flex;
4488
+ flex: 1;
4489
+ min-inline-size: 0;
4490
+ }
4491
+ .affix:where([data-hn-ui-input-group]) {
4492
+ display: inline-flex;
4493
+ flex: none;
4494
+ align-items: center;
4495
+ padding-inline: var(--ui-space-2);
4496
+ color: var(--ui-text-muted);
4497
+ font-family: var(--ui-font-family-mono);
4498
+ font-size: var(--ui-font-size-sm);
4499
+ white-space: nowrap;
4500
+ }
4501
+ .affix:has([slot="prefix"]):where([data-hn-ui-input-group]),.affix:has([slot="suffix"]):where([data-hn-ui-input-group]) {
4502
+ background: var(--ui-surface-muted);
4503
+ }
4504
+ .affix:has([slot="prefix"]):where([data-hn-ui-input-group]) {
4505
+ border-inline-end: var(--ui-border-width) solid var(--ui-border-divider);
4506
+ }
4507
+ .affix:has([slot="suffix"]):where([data-hn-ui-input-group]) {
4508
+ border-inline-start: var(--ui-border-width) solid var(--ui-border-divider);
4509
+ }
4510
+ :scope[data-ui-input-group-state~="prefixKind=icon"]:where([data-hn-ui-input-group]) {
4511
+ --_ui-default-input-padding-inline-start: var(--ui-space-2);
4512
+ }
4513
+ :scope[data-ui-input-group-state~="prefixKind=icon"]
4514
+ .affix:first-child:where([data-hn-ui-input-group]) {
4515
+ padding-inline-end: 0;
4516
+ border-inline-end: 0;
4517
+ background: transparent;
4518
+ }
4519
+ .action:where([data-hn-ui-input-group]) {
4520
+ display: flex;
4521
+ flex: none;
4522
+ align-items: center;
4523
+ padding-inline: var(--ui-space-1);
4524
+ }
4525
+ :scope[data-ui-input-group-state~="multiline"]:where([data-hn-ui-input-group]) {
4526
+ display: grid;
4527
+ grid-template-columns: auto minmax(0, 1fr) auto;
4528
+ }
4529
+ :scope[data-ui-input-group-state~="multiline"] .field:where([data-hn-ui-input-group]) {
4530
+ grid-column: 2;
4531
+ }
4532
+ :scope[data-ui-input-group-state~="multiline"] .action:where([data-hn-ui-input-group]) {
4533
+ grid-column: 1 / -1;
4534
+ justify-content: end;
4535
+ padding: var(--ui-space-2);
4536
+ padding-block-start: 0;
4537
+ }
4538
+ :scope[data-ui-input-group-state~="multiline"][data-ui-input-group-state~="actionPosition=top-end"]:where([data-hn-ui-input-group]) {
4539
+ --_ui-default-textarea-padding-inline-end: calc(
4540
+ var(--_ui-input-group-action-inline-size, 7rem) + var(--ui-space-3)
4541
+ );
4542
+ }
4543
+ :scope[data-ui-input-group-state~="multiline"][data-ui-input-group-state~="actionPosition=top-end"]
4544
+ .field:where([data-hn-ui-input-group]) {
4545
+ grid-row: 1;
4546
+ }
4547
+ :scope[data-ui-input-group-state~="multiline"][data-ui-input-group-state~="actionPosition=top-end"]
4548
+ .action:where([data-hn-ui-input-group]) {
4549
+ grid-column: 2;
4550
+ grid-row: 1;
4551
+ align-self: start;
4552
+ justify-self: end;
4553
+ padding: var(--ui-space-2);
4554
+ }
4555
+ .affix:empty:where([data-hn-ui-input-group]),.action:empty:where([data-hn-ui-input-group]) {
4556
+ display: none;
4557
+ }
4558
+ :scope[hidden]:where([data-hn-ui-input-group]) {
4559
+ display: none;
4560
+ }
4561
+ }
4562
+
4563
+ /* This component's hooks style the element they are set on, and never a nested one. */
4564
+ @property --ui-textarea-border-width {
4565
+ syntax: "*";
4566
+ inherits: false;
4567
+ }
4568
+ @property --ui-textarea-border {
4569
+ syntax: "*";
4570
+ inherits: false;
4571
+ }
4572
+ @property --ui-textarea-border-hover {
4573
+ syntax: "*";
4574
+ inherits: false;
4575
+ }
4576
+ @property --ui-textarea-focus-border {
4577
+ syntax: "*";
4578
+ inherits: false;
4579
+ }
4580
+ @property --ui-textarea-focus-outline {
4581
+ syntax: "*";
4582
+ inherits: false;
4583
+ }
4584
+ @property --ui-textarea-surface {
4585
+ syntax: "*";
4586
+ inherits: false;
4587
+ }
4588
+ @property --ui-textarea-focus-shadow {
4589
+ syntax: "*";
4590
+ inherits: false;
4591
+ }
4592
+ @property --ui-textarea-invalid-border {
4593
+ syntax: "*";
4594
+ inherits: false;
4595
+ }
4596
+ @property --ui-textarea-invalid-focus-shadow {
4597
+ syntax: "*";
4598
+ inherits: false;
4599
+ }
4600
+ @property --ui-textarea-radius {
4601
+ syntax: "*";
4602
+ inherits: false;
4603
+ }
4604
+ @property --ui-textarea-shadow {
4605
+ syntax: "*";
4606
+ inherits: false;
4607
+ }
4608
+ @property --ui-textarea-padding-inline-end {
4609
+ syntax: "*";
4610
+ inherits: false;
4611
+ }
4612
+
4613
+ /* Tabbing into a field selects its text; tint that selection softly instead of the page highlight. */
4614
+
4615
+ /* The app's invalid flag, or the browser's own verdict once the user has left an invalid field. */
4616
+
4617
+ /* Below 16px, iOS zooms the page into the focused field, so touch keeps body-size text. */
4618
+
4619
+ /* A component that sets its display still honours the hidden attribute on its root. */
4620
+ @scope (.ui-textarea) to ([data-hn]) {
4621
+ :scope {
4622
+ box-sizing: border-box;
4623
+ display: inline-block;
4624
+ inline-size: 100%;
4625
+ min-inline-size: 0;
4626
+ min-block-size: calc(3rem * 2);
4627
+ margin: 0;
4628
+ --_padding-block: var(--ui-space-2);
4629
+ padding: var(--ui-space-2) var(--ui-space-3);
4630
+ padding-inline-end: var(
4631
+ --ui-textarea-padding-inline-end,
4632
+ var(--_ui-default-textarea-padding-inline-end, var(--ui-space-3))
4633
+ );
4634
+ appearance: none;
4635
+ resize: vertical;
4636
+ border: var(
4637
+ --ui-textarea-border-width,
4638
+ var(--_ui-default-textarea-border-width, var(--ui-border-width))
4639
+ ) solid
4640
+ var(
4641
+ --ui-textarea-border,
4642
+ var(--_ui-default-textarea-border, var(--ui-control-border, var(--ui-border-strong)))
4643
+ );
4644
+ border-radius: var(
4645
+ --ui-textarea-radius,
4646
+ var(--_ui-default-textarea-radius, var(--ui-field-radius, var(--ui-radius-md)))
4647
+ );
4648
+ background: var(
4649
+ --ui-textarea-surface,
4650
+ var(--_ui-default-textarea-surface, var(--ui-control-surface, var(--ui-surface-elevated)))
4651
+ );
4652
+ color: var(--ui-text-primary);
4653
+ font: inherit;
4654
+ line-height: var(--ui-line-height-md);
4655
+ box-shadow: var(
4656
+ --ui-textarea-shadow,
4657
+ var(--_ui-default-textarea-shadow, var(--ui-control-inset))
4658
+ );
4659
+ transition:
4660
+ border-color var(--ui-motion-fast) var(--ui-motion-ease),
4661
+ box-shadow var(--ui-motion-fast) var(--ui-motion-ease),
4662
+ background-color var(--ui-motion-fast) var(--ui-motion-ease);
4663
+ }
4664
+ :scope::selection {
4665
+ background: color-mix(in srgb, var(--ui-accent-solid) 20%, transparent);
4666
+ color: inherit;
4667
+ }
4668
+ :scope::placeholder {
4669
+ color: var(--ui-control-placeholder, var(--ui-text-secondary));
4670
+ opacity: 1;
4671
+ }
4672
+ :scope:hover:not(:focus):not(:disabled):not(:read-only):not([aria-invalid="true"]):not(:is(:user-invalid, [data-user-invalid])) {
4673
+ border-color: var(
4674
+ --ui-textarea-border-hover,
4675
+ var(
4676
+ --_ui-default-textarea-border-hover,
4677
+ var(--ui-control-border-hover, var(--ui-text-secondary))
4678
+ )
4679
+ );
4680
+ }
4681
+ :scope:focus-visible {
4682
+ border-color: var(
4683
+ --ui-textarea-focus-border,
4684
+ var(--_ui-default-textarea-focus-border, var(--ui-control-focus, var(--ui-accent-solid)))
4685
+ );
4686
+ outline: var(--ui-textarea-focus-outline, var(--_ui-default-textarea-focus-outline, none));
4687
+ box-shadow: var(
4688
+ --ui-textarea-focus-shadow,
4689
+ var(
4690
+ --_ui-default-textarea-focus-shadow,
4691
+ var(--ui-control-inset),
4692
+ var(--ui-control-focus-halo-shadow)
4693
+ )
4694
+ );
4695
+ }
4696
+ :scope[aria-invalid="true"],:scope:is(:user-invalid, [data-user-invalid]) {
4697
+ border-color: var(
4698
+ --ui-textarea-invalid-border,
4699
+ var(--_ui-default-textarea-invalid-border, var(--ui-field-danger, var(--ui-danger-solid)))
4700
+ );
4701
+ }
4702
+ :scope:is([aria-invalid="true"], :is(:user-invalid, [data-user-invalid])):focus-visible {
4703
+ box-shadow: var(
4704
+ --ui-textarea-invalid-focus-shadow,
4705
+ var(
4706
+ --_ui-default-textarea-invalid-focus-shadow,
4707
+ var(--ui-control-inset),
4708
+ 0 0 0 calc(var(--ui-focus-width) * 1.5) color-mix(
4709
+ in srgb,
4710
+ var(
4711
+ --ui-textarea-invalid-border,
4712
+ var(
4713
+ --_ui-default-textarea-invalid-border,
4714
+ var(--ui-field-danger, var(--ui-danger-solid))
4715
+ )
4716
+ ) 22%,
4717
+ transparent
4718
+ )
4719
+ )
4720
+ );
4721
+ }
4722
+ :scope:disabled {
4723
+ background: var(--ui-control-surface-disabled, var(--ui-surface-muted));
4724
+ color: var(--ui-disabled-text);
4725
+ box-shadow: none;
4726
+ cursor: not-allowed;
4727
+ }
4728
+ :scope[data-ui-textarea-state~="size=sm"] {
4729
+ --_padding-block: var(--ui-space-1);
4730
+ padding: var(--ui-space-1) var(--ui-space-2);
4731
+ padding-inline-end: var(
4732
+ --ui-textarea-padding-inline-end,
4733
+ var(--_ui-default-textarea-padding-inline-end, var(--ui-space-2))
4734
+ );
4735
+ font-size: var(--ui-font-size-sm);
4736
+ }
4737
+ :scope[data-ui-textarea-state~="size=lg"] {
4738
+ --_padding-block: var(--ui-space-3);
4739
+ padding: var(--ui-space-3) var(--ui-space-4);
4740
+ padding-inline-end: var(
4741
+ --ui-textarea-padding-inline-end,
4742
+ var(--_ui-default-textarea-padding-inline-end, var(--ui-space-4))
4743
+ );
4744
+ font-size: var(--ui-font-size-md);
4745
+ }
4746
+ :scope[data-ui-textarea-state~="maxRows"] {
4747
+ max-block-size: calc(
4748
+ max(var(--_rows), var(--_max-rows)) * 1lh + var(--_padding-block) + var(--_padding-block) +
4749
+ 2px
4750
+ );
4751
+ }
4752
+ @supports (field-sizing: content) {
4753
+ :scope[data-ui-textarea-state~="autosize"] {
4754
+ field-sizing: content;
4755
+ min-block-size: calc(
4756
+ var(--_rows) * 1lh + var(--_padding-block) + var(--_padding-block) + 2px
4757
+ );
4758
+ }
4759
+ }
4760
+ @media (pointer: coarse) {
4761
+ :scope[data-ui-textarea-state~="size=sm"] {
4762
+ font-size: inherit;
4763
+ }
4764
+ }
4765
+ :scope[hidden] {
4766
+ display: none;
4767
+ }
4768
+ }
4769
+
4246
4770
  /* One row, always. When the controls outgrow the space, the row scrolls sideways rather than
4247
4771
  wrapping into several lines, and a fade at each edge that has more to show says so. */
4248
4772
 
@@ -4351,142 +4875,43 @@ legend.sr-only:where([data-hn-ui-radio-group]) {
4351
4875
  border-bottom: none;
4352
4876
  box-shadow: var(--ui-editor-toolbar-mobile-shadow, 0 -2px 8px rgb(0 0 0 / 0.06));
4353
4877
  }
4354
- :scope[data-ui-editor-toolbar-state~="floating"]:where([data-hn-ui-editor-toolbar]) {
4355
- position: relative;
4356
- inset: auto;
4357
- min-height: auto;
4358
- border: var(--ui-border-width) solid var(--ui-editor-toolbar-border, var(--ui-border-strong));
4359
- border-radius: var(--ui-editor-toolbar-floating-radius, var(--ui-radius-lg));
4360
- box-shadow: var(
4361
- --ui-editor-toolbar-floating-shadow,
4362
- var(--ui-shadow-lg, 0 10px 24px rgb(0 0 0 / 0.12))
4363
- );
4364
- }
4365
- }
4366
- .looma-editor__sticky-toolbar-shell :scope:where([data-hn-ui-editor-toolbar]) {
4367
- position: relative;
4368
- min-height: var(--ui-editor-toolbar-min-height, 48px);
4369
- background: transparent;
4370
- border: 0;
4371
- box-shadow: none;
4372
- }
4373
- .looma-editor__mobile-toolbar-shell
4374
- :scope[data-ui-editor-toolbar-state~="floating"]:where([data-hn-ui-editor-toolbar]) {
4375
- width: 100%;
4376
- max-width: none;
4377
- min-height: 100%;
4378
- padding: 0;
4379
- background: transparent;
4380
- border: 0;
4381
- border-radius: 0;
4382
- box-shadow: none;
4383
- backdrop-filter: none;
4384
- }
4385
- .looma-editor__mobile-toolbar-shell
4386
- :scope[data-ui-editor-toolbar-state~="floating"]
4387
- .strip:where([data-hn-ui-editor-toolbar]) {
4388
- scroll-snap-type: x mandatory;
4389
- }
4390
- :scope[hidden]:where([data-hn-ui-editor-toolbar]) {
4391
- display: none;
4392
- }
4393
- }
4394
-
4395
- /* This component's hooks style the element they are set on, and never a nested one. */
4396
- @property --ui-form-field-danger {
4397
- syntax: "*";
4398
- inherits: false;
4399
- }
4400
- @property --ui-form-field-help-font-size {
4401
- syntax: "*";
4402
- inherits: false;
4403
- }
4404
- @property --ui-form-field-help-min-block-size {
4405
- syntax: "*";
4406
- inherits: false;
4407
- }
4408
- @property --ui-form-field-help-text {
4409
- syntax: "*";
4410
- inherits: false;
4411
- }
4412
- @property --ui-form-field-label-font-size {
4413
- syntax: "*";
4414
- inherits: false;
4415
- }
4416
- @property --ui-form-field-label-text {
4417
- syntax: "*";
4418
- inherits: false;
4419
- }
4420
- @property --ui-form-field-min-inline-size {
4421
- syntax: "*";
4422
- inherits: false;
4423
- }
4424
-
4425
- /* Each named region styles whatever fills it, however it was slotted (slot="…" in HTML, #label
4426
- in Vue), and generates no box of its own, so an empty region adds no gap. */
4427
-
4428
- /* A label action, such as a small help button, sits after the label text in a box one line
4429
- tall, centred on the first line and overflowing it. A button taller than a line of label
4430
- text then never makes this field's label row taller than its neighbours' in a grid row. */
4431
-
4432
- /* An error reads in the danger colour, the one the invalid control's border takes. */
4433
-
4434
- /* A component that sets its display still honours the hidden attribute on its root. */
4435
- @scope (.ui-form-field) to ([data-hn]) {
4436
- :scope:where([data-hn-ui-form-field]) {
4437
- /* Hooks do not inherit, so the parts below read them from the root. */
4438
- --_ui-form-field-danger: var(--ui-form-field-danger);
4439
- --_ui-form-field-help-min-block-size: var(--ui-form-field-help-min-block-size);
4440
- --_ui-form-field-label-text: var(--ui-form-field-label-text);
4441
- --_ui-form-field-label-font-size: var(--ui-form-field-label-font-size);
4442
- --_ui-form-field-help-text: var(--ui-form-field-help-text);
4443
- --_ui-form-field-help-font-size: var(--ui-form-field-help-font-size);
4444
-
4445
- display: grid;
4446
- gap: var(--ui-space-2);
4447
- min-inline-size: var(--ui-form-field-min-inline-size, 0);
4448
- align-content: start;
4449
- color: var(--ui-text-primary);
4450
- }
4451
- .label:where([data-hn-ui-form-field]),.help:where([data-hn-ui-form-field]),.error:where([data-hn-ui-form-field]) {
4452
- display: contents;
4453
- }
4454
- .label:where([data-hn-ui-form-field]) {
4455
- color: var(--_ui-form-field-label-text, var(--ui-text-secondary));
4456
- font-size: var(--_ui-form-field-label-font-size, var(--ui-font-size-sm));
4457
- }
4458
- .label:has(> .label-action > *):where([data-hn-ui-form-field]) {
4459
- display: flex;
4460
- align-items: start;
4461
- gap: var(--ui-space-1);
4462
- }
4463
- .label-action:where([data-hn-ui-form-field]) {
4464
- display: flex;
4465
- align-items: unsafe center;
4466
- block-size: 1lh;
4467
- }
4468
- .label-action:not(:has(> *)):where([data-hn-ui-form-field]) {
4469
- display: none;
4470
- }
4471
- .help:where([data-hn-ui-form-field]) {
4472
- color: var(--_ui-form-field-help-text, var(--ui-text-muted));
4473
- font-size: var(--_ui-form-field-help-font-size, var(--ui-font-size-sm));
4474
- line-height: var(--ui-line-height-md);
4475
- }
4476
- .help > :where(:not([data-hn-ui-form-field])):is(*) {
4477
- min-block-size: var(--_ui-form-field-help-min-block-size, 0);
4878
+ :scope[data-ui-editor-toolbar-state~="floating"]:where([data-hn-ui-editor-toolbar]) {
4879
+ position: relative;
4880
+ inset: auto;
4881
+ min-height: auto;
4882
+ border: var(--ui-border-width) solid var(--ui-editor-toolbar-border, var(--ui-border-strong));
4883
+ border-radius: var(--ui-editor-toolbar-floating-radius, var(--ui-radius-lg));
4884
+ box-shadow: var(
4885
+ --ui-editor-toolbar-floating-shadow,
4886
+ var(--ui-shadow-lg, 0 10px 24px rgb(0 0 0 / 0.12))
4887
+ );
4478
4888
  }
4479
- .error:where([data-hn-ui-form-field]) {
4480
- display: none;
4481
4889
  }
4482
- :scope[data-ui-form-field-state~="invalid"] .error:where([data-hn-ui-form-field]) {
4483
- display: contents;
4890
+ .looma-editor__sticky-toolbar-shell :scope:where([data-hn-ui-editor-toolbar]) {
4891
+ position: relative;
4892
+ min-height: var(--ui-editor-toolbar-min-height, 48px);
4893
+ background: transparent;
4894
+ border: 0;
4895
+ box-shadow: none;
4484
4896
  }
4485
- .error:where([data-hn-ui-form-field]),:where(:not([data-hn-ui-form-field])):is([role="alert"]) {
4486
- color: var(--_ui-form-field-danger, var(--ui-field-danger, var(--ui-danger)));
4487
- font-size: var(--ui-font-size-sm);
4897
+ .looma-editor__mobile-toolbar-shell
4898
+ :scope[data-ui-editor-toolbar-state~="floating"]:where([data-hn-ui-editor-toolbar]) {
4899
+ width: 100%;
4900
+ max-width: none;
4901
+ min-height: 100%;
4902
+ padding: 0;
4903
+ background: transparent;
4904
+ border: 0;
4905
+ border-radius: 0;
4906
+ box-shadow: none;
4907
+ backdrop-filter: none;
4488
4908
  }
4489
- :scope[hidden]:where([data-hn-ui-form-field]) {
4909
+ .looma-editor__mobile-toolbar-shell
4910
+ :scope[data-ui-editor-toolbar-state~="floating"]
4911
+ .strip:where([data-hn-ui-editor-toolbar]) {
4912
+ scroll-snap-type: x mandatory;
4913
+ }
4914
+ :scope[hidden]:where([data-hn-ui-editor-toolbar]) {
4490
4915
  display: none;
4491
4916
  }
4492
4917
  }
@@ -5220,254 +5645,36 @@ html[data-ui-input-modality="touch"] :scope:where([data-hn-ui-icon-button])::aft
5220
5645
  background: var(--ui-surface);
5221
5646
  cursor: pointer;
5222
5647
  }
5223
- .cell.selected {
5224
- background: var(--ui-accent-solid, var(--ui-accent));
5225
- border-color: var(--ui-accent-solid, var(--ui-accent));
5226
- }
5227
- .cell:focus-visible {
5228
- outline: var(--ui-focus-width) solid var(--ui-focus-ring);
5229
- outline-offset: calc(-1 * var(--ui-focus-width));
5230
- }
5231
- .header {
5232
- display: block;
5233
- margin-bottom: var(--ui-space-2);
5234
- font-size: var(--ui-font-size-sm);
5235
- cursor: pointer;
5236
- }
5237
- @media (pointer: coarse) {
5238
- .grid {
5239
- grid-template-columns: repeat(var(--_cols, 8), 44px);
5240
- grid-template-rows: repeat(var(--_rows, 8), 44px);
5241
- }
5242
- .cell {
5243
- width: 44px;
5244
- height: 44px;
5245
- }
5246
- }
5247
- @media (forced-colors: active) {
5248
- .cell:focus-visible {
5249
- outline-color: Highlight;
5250
- }
5251
- }
5252
- :scope[hidden] {
5253
- display: none;
5254
- }
5255
- }
5256
-
5257
- @property --ui-input-group-radius {
5258
- syntax: "*";
5259
- inherits: false;
5260
- }
5261
- @property --ui-input-group-invalid-border {
5262
- syntax: "*";
5263
- inherits: false;
5264
- }
5265
- @property --ui-input-group-invalid-focus-shadow {
5266
- syntax: "*";
5267
- inherits: false;
5268
- }
5269
- /* An input with fixed text before or after it, such as a domain after a site's name
5270
- ("acme" + ".example.com") or slashes around a path. The group draws the field's border and
5271
- focus ring around the input and its affixes together; the input inside drops its own through
5272
- its custom properties, so it is still the one ui-input, with its form behaviour intact. The
5273
- affixes are plain text beside the input, so name the input with a label that says what the
5274
- whole value is. The action slot takes one button at the end, inside the border, for the one
5275
- thing the field is for ("Continue" after a site's address), so it reads as the field's action
5276
- and not the form's. */
5277
-
5278
- /* The frame takes its input's size, so a small group lines up with small buttons and fields. */
5279
-
5280
- /* The ring shows when the field's input would show its own: when it is focus-visible, which a
5281
- text input is for a pointer as well as a keyboard. A focused action button draws its own. */
5282
-
5283
- /* Forced colors drop box shadows, so the focus ring becomes an outline. */
5284
-
5285
- /* Fixed text is part of the value, but should not look editable. */
5286
-
5287
- /* Centred rather than padded above and below: the group is exactly a lone Input's height, so a
5288
- small button sits inside it with the difference split evenly, and the field keeps its height. */
5289
-
5290
- /* Multiline text owns the first row; its action remains inside the same frame below it. */
5291
-
5292
- /* The same textarea keeps its full resizeable box. Its text reserves the action's live width,
5293
- so a translated label or pending indicator cannot cover what the person types. */
5294
-
5295
- /* A component that sets its display still honours the hidden attribute on its root. */
5296
- @scope (.ui-input-group) to ([data-hn]) {
5297
- :scope:where([data-hn-ui-input-group]) {
5298
- /* The group's own border and height stand for the input's, so the group is a lone Input's height.
5299
- Hooks do not inherit, so these are defaults for the input; its own hooks still win. */
5300
- --_ui-default-input-border-width: 0;
5301
- --_ui-default-input-min-block-size: 0;
5302
- --_ui-default-input-border: transparent;
5303
- --_ui-default-input-border-hover: transparent;
5304
- --_ui-default-input-focus-border: transparent;
5305
- --_ui-default-input-invalid-border: transparent;
5306
- --_ui-default-input-invalid-focus-shadow: none;
5307
- --_ui-default-input-shadow: none;
5308
- --_ui-default-input-focus-shadow: none;
5309
- --_ui-default-input-focus-outline: none;
5310
- --_ui-default-input-radius: 0;
5311
- --_ui-default-input-surface: transparent;
5312
- --_ui-default-textarea-border-width: 0;
5313
- --_ui-default-textarea-border: transparent;
5314
- --_ui-default-textarea-border-hover: transparent;
5315
- --_ui-default-textarea-focus-border: transparent;
5316
- --_ui-default-textarea-invalid-border: transparent;
5317
- --_ui-default-textarea-invalid-focus-shadow: none;
5318
- --_ui-default-textarea-shadow: none;
5319
- --_ui-default-textarea-focus-shadow: none;
5320
- --_ui-default-textarea-focus-outline: none;
5321
- --_ui-default-textarea-radius: 0;
5322
- --_ui-default-textarea-surface: transparent;
5323
-
5324
- display: flex;
5325
- align-items: stretch;
5326
- box-sizing: border-box;
5327
- inline-size: 100%;
5328
- min-inline-size: 0;
5329
- min-block-size: var(--ui-control-size-md);
5330
- /* The frame reads the shared control tokens with a lone Input's fallbacks, so the two match. */
5331
- border: var(--ui-border-width) solid var(--ui-control-border, var(--ui-border-strong));
5332
- border-radius: var(--ui-input-group-radius, var(--ui-field-radius, var(--ui-radius-md)));
5333
- background: var(--ui-control-surface, var(--ui-surface-elevated));
5334
- box-shadow: var(--ui-control-inset);
5335
- overflow: hidden;
5336
- /* A press anywhere in the frame focuses the input. */
5337
- cursor: text;
5338
- transition:
5339
- border-color var(--ui-motion-fast) var(--ui-motion-ease),
5340
- box-shadow var(--ui-motion-fast) var(--ui-motion-ease);
5341
- }
5342
- :scope[data-ui-input-group-state~="variant=subtle"]:where([data-hn-ui-input-group]) {
5343
- border-color: var(--ui-border);
5344
- background: var(--ui-surface-muted);
5345
- box-shadow: none;
5346
- }
5347
- :scope:has(.field [data-ui-input-state~="size=sm"]):where([data-hn-ui-input-group]) {
5348
- min-block-size: var(--ui-control-size-sm);
5349
- }
5350
- :scope:has(.field [data-ui-input-state~="size=lg"]):where([data-hn-ui-input-group]) {
5351
- min-block-size: var(--ui-control-size-lg);
5352
- }
5353
- @media (pointer: coarse) {
5354
- :scope:where([data-hn-ui-input-group]) {
5355
- min-block-size: max(var(--ui-control-size-md), var(--ui-control-min-block-size));
5356
- }
5357
- :scope:has(.field [data-ui-input-state~="size=sm"]):where([data-hn-ui-input-group]) {
5358
- min-block-size: var(--ui-control-min-block-size);
5359
- }
5360
- }
5361
- :scope:hover:not(:has(:is(input, textarea):focus, :is(input, textarea):disabled, :is(input, textarea):read-only, [aria-invalid="true"], :is(:user-invalid, [data-user-invalid]))):where([data-hn-ui-input-group]) {
5362
- border-color: var(--ui-control-border-hover, var(--ui-text-secondary));
5363
- }
5364
- :scope:has(.field :is(input, textarea):focus-visible):where([data-hn-ui-input-group]) {
5365
- border-color: var(--ui-control-focus, var(--ui-accent-solid));
5366
- box-shadow:
5367
- var(--ui-control-inset),
5368
- var(--ui-control-focus-halo-shadow);
5369
- }
5370
- :scope:has([aria-invalid="true"], :is(:user-invalid, [data-user-invalid])):where([data-hn-ui-input-group]) {
5371
- border-color: var(
5372
- --ui-input-group-invalid-border,
5373
- var(--ui-field-danger, var(--ui-danger-solid))
5374
- );
5375
- }
5376
- :scope:has(:is(input, textarea):is([aria-invalid="true"], :is(:user-invalid, [data-user-invalid])):focus-visible):where([data-hn-ui-input-group]) {
5377
- box-shadow: var(
5378
- --ui-input-group-invalid-focus-shadow,
5379
- var(--ui-control-inset),
5380
- 0 0 0 calc(var(--ui-focus-width) * 1.5) color-mix(
5381
- in srgb,
5382
- var(--ui-input-group-invalid-border, var(--ui-field-danger, var(--ui-danger-solid))) 22%,
5383
- transparent
5384
- )
5385
- );
5386
- }
5387
- @media (forced-colors: active) {
5388
- :scope:has(:is(input, textarea):focus-visible):where([data-hn-ui-input-group]) {
5389
- outline: var(--ui-focus-width) solid Highlight;
5390
- outline-offset: var(--ui-border-width);
5391
- }
5392
- }
5393
- :scope[data-ui-input-group-state~="disabled"]:where([data-hn-ui-input-group]),:scope:has(:is(input, textarea):disabled):where([data-hn-ui-input-group]) {
5394
- background: var(--ui-control-surface-disabled, var(--ui-surface-muted));
5395
- box-shadow: none;
5396
- cursor: not-allowed;
5397
- }
5398
- .field:where([data-hn-ui-input-group]) {
5399
- display: flex;
5400
- flex: 1;
5401
- min-inline-size: 0;
5402
- }
5403
- .affix:where([data-hn-ui-input-group]) {
5404
- display: inline-flex;
5405
- flex: none;
5406
- align-items: center;
5407
- padding-inline: var(--ui-space-2);
5408
- color: var(--ui-text-muted);
5409
- font-family: var(--ui-font-family-mono);
5410
- font-size: var(--ui-font-size-sm);
5411
- white-space: nowrap;
5412
- }
5413
- .affix:has([slot="prefix"]):where([data-hn-ui-input-group]),.affix:has([slot="suffix"]):where([data-hn-ui-input-group]) {
5414
- background: var(--ui-surface-muted);
5415
- }
5416
- .affix:has([slot="prefix"]):where([data-hn-ui-input-group]) {
5417
- border-inline-end: var(--ui-border-width) solid var(--ui-border-divider);
5418
- }
5419
- .affix:has([slot="suffix"]):where([data-hn-ui-input-group]) {
5420
- border-inline-start: var(--ui-border-width) solid var(--ui-border-divider);
5421
- }
5422
- :scope[data-ui-input-group-state~="prefixKind=icon"]:where([data-hn-ui-input-group]) {
5423
- --_ui-default-input-padding-inline-start: var(--ui-space-2);
5424
- }
5425
- :scope[data-ui-input-group-state~="prefixKind=icon"]
5426
- .affix:first-child:where([data-hn-ui-input-group]) {
5427
- padding-inline-end: 0;
5428
- border-inline-end: 0;
5429
- background: transparent;
5430
- }
5431
- .action:where([data-hn-ui-input-group]) {
5432
- display: flex;
5433
- flex: none;
5434
- align-items: center;
5435
- padding-inline: var(--ui-space-1);
5648
+ .cell.selected {
5649
+ background: var(--ui-accent-solid, var(--ui-accent));
5650
+ border-color: var(--ui-accent-solid, var(--ui-accent));
5436
5651
  }
5437
- :scope[data-ui-input-group-state~="multiline"]:where([data-hn-ui-input-group]) {
5438
- display: grid;
5439
- grid-template-columns: auto minmax(0, 1fr) auto;
5652
+ .cell:focus-visible {
5653
+ outline: var(--ui-focus-width) solid var(--ui-focus-ring);
5654
+ outline-offset: calc(-1 * var(--ui-focus-width));
5440
5655
  }
5441
- :scope[data-ui-input-group-state~="multiline"] .field:where([data-hn-ui-input-group]) {
5442
- grid-column: 2;
5656
+ .header {
5657
+ display: block;
5658
+ margin-bottom: var(--ui-space-2);
5659
+ font-size: var(--ui-font-size-sm);
5660
+ cursor: pointer;
5443
5661
  }
5444
- :scope[data-ui-input-group-state~="multiline"] .action:where([data-hn-ui-input-group]) {
5445
- grid-column: 1 / -1;
5446
- justify-content: end;
5447
- padding: var(--ui-space-2);
5448
- padding-block-start: 0;
5662
+ @media (pointer: coarse) {
5663
+ .grid {
5664
+ grid-template-columns: repeat(var(--_cols, 8), 44px);
5665
+ grid-template-rows: repeat(var(--_rows, 8), 44px);
5449
5666
  }
5450
- :scope[data-ui-input-group-state~="multiline"][data-ui-input-group-state~="actionPosition=top-end"]:where([data-hn-ui-input-group]) {
5451
- --_ui-default-textarea-padding-inline-end: calc(
5452
- var(--_ui-input-group-action-inline-size, 7rem) + var(--ui-space-3)
5453
- );
5667
+ .cell {
5668
+ width: 44px;
5669
+ height: 44px;
5454
5670
  }
5455
- :scope[data-ui-input-group-state~="multiline"][data-ui-input-group-state~="actionPosition=top-end"]
5456
- .field:where([data-hn-ui-input-group]) {
5457
- grid-row: 1;
5458
5671
  }
5459
- :scope[data-ui-input-group-state~="multiline"][data-ui-input-group-state~="actionPosition=top-end"]
5460
- .action:where([data-hn-ui-input-group]) {
5461
- grid-column: 2;
5462
- grid-row: 1;
5463
- align-self: start;
5464
- justify-self: end;
5465
- padding: var(--ui-space-2);
5672
+ @media (forced-colors: active) {
5673
+ .cell:focus-visible {
5674
+ outline-color: Highlight;
5466
5675
  }
5467
- .affix:empty:where([data-hn-ui-input-group]),.action:empty:where([data-hn-ui-input-group]) {
5468
- display: none;
5469
5676
  }
5470
- :scope[hidden]:where([data-hn-ui-input-group]) {
5677
+ :scope[hidden] {
5471
5678
  display: none;
5472
5679
  }
5473
5680
  }
@@ -9121,213 +9328,6 @@ input:where([data-hn-ui-switch]),input:where([data-hn-ui-switch])::after {
9121
9328
  }
9122
9329
  }
9123
9330
 
9124
- /* This component's hooks style the element they are set on, and never a nested one. */
9125
- @property --ui-textarea-border-width {
9126
- syntax: "*";
9127
- inherits: false;
9128
- }
9129
- @property --ui-textarea-border {
9130
- syntax: "*";
9131
- inherits: false;
9132
- }
9133
- @property --ui-textarea-border-hover {
9134
- syntax: "*";
9135
- inherits: false;
9136
- }
9137
- @property --ui-textarea-focus-border {
9138
- syntax: "*";
9139
- inherits: false;
9140
- }
9141
- @property --ui-textarea-focus-outline {
9142
- syntax: "*";
9143
- inherits: false;
9144
- }
9145
- @property --ui-textarea-surface {
9146
- syntax: "*";
9147
- inherits: false;
9148
- }
9149
- @property --ui-textarea-focus-shadow {
9150
- syntax: "*";
9151
- inherits: false;
9152
- }
9153
- @property --ui-textarea-invalid-border {
9154
- syntax: "*";
9155
- inherits: false;
9156
- }
9157
- @property --ui-textarea-invalid-focus-shadow {
9158
- syntax: "*";
9159
- inherits: false;
9160
- }
9161
- @property --ui-textarea-radius {
9162
- syntax: "*";
9163
- inherits: false;
9164
- }
9165
- @property --ui-textarea-shadow {
9166
- syntax: "*";
9167
- inherits: false;
9168
- }
9169
- @property --ui-textarea-padding-inline-end {
9170
- syntax: "*";
9171
- inherits: false;
9172
- }
9173
-
9174
- /* Tabbing into a field selects its text; tint that selection softly instead of the page highlight. */
9175
-
9176
- /* The app's invalid flag, or the browser's own verdict once the user has left an invalid field. */
9177
-
9178
- /* Below 16px, iOS zooms the page into the focused field, so touch keeps body-size text. */
9179
-
9180
- /* A component that sets its display still honours the hidden attribute on its root. */
9181
- @scope (.ui-textarea) to ([data-hn]) {
9182
- :scope {
9183
- box-sizing: border-box;
9184
- display: inline-block;
9185
- inline-size: 100%;
9186
- min-inline-size: 0;
9187
- min-block-size: calc(3rem * 2);
9188
- margin: 0;
9189
- --_padding-block: var(--ui-space-2);
9190
- padding: var(--ui-space-2) var(--ui-space-3);
9191
- padding-inline-end: var(
9192
- --ui-textarea-padding-inline-end,
9193
- var(--_ui-default-textarea-padding-inline-end, var(--ui-space-3))
9194
- );
9195
- appearance: none;
9196
- resize: vertical;
9197
- border: var(
9198
- --ui-textarea-border-width,
9199
- var(--_ui-default-textarea-border-width, var(--ui-border-width))
9200
- ) solid
9201
- var(
9202
- --ui-textarea-border,
9203
- var(--_ui-default-textarea-border, var(--ui-control-border, var(--ui-border-strong)))
9204
- );
9205
- border-radius: var(
9206
- --ui-textarea-radius,
9207
- var(--_ui-default-textarea-radius, var(--ui-field-radius, var(--ui-radius-md)))
9208
- );
9209
- background: var(
9210
- --ui-textarea-surface,
9211
- var(--_ui-default-textarea-surface, var(--ui-control-surface, var(--ui-surface-elevated)))
9212
- );
9213
- color: var(--ui-text-primary);
9214
- font: inherit;
9215
- line-height: var(--ui-line-height-md);
9216
- box-shadow: var(
9217
- --ui-textarea-shadow,
9218
- var(--_ui-default-textarea-shadow, var(--ui-control-inset))
9219
- );
9220
- transition:
9221
- border-color var(--ui-motion-fast) var(--ui-motion-ease),
9222
- box-shadow var(--ui-motion-fast) var(--ui-motion-ease),
9223
- background-color var(--ui-motion-fast) var(--ui-motion-ease);
9224
- }
9225
- :scope::selection {
9226
- background: color-mix(in srgb, var(--ui-accent-solid) 20%, transparent);
9227
- color: inherit;
9228
- }
9229
- :scope::placeholder {
9230
- color: var(--ui-control-placeholder, var(--ui-text-secondary));
9231
- opacity: 1;
9232
- }
9233
- :scope:hover:not(:focus):not(:disabled):not(:read-only):not([aria-invalid="true"]):not(:is(:user-invalid, [data-user-invalid])) {
9234
- border-color: var(
9235
- --ui-textarea-border-hover,
9236
- var(
9237
- --_ui-default-textarea-border-hover,
9238
- var(--ui-control-border-hover, var(--ui-text-secondary))
9239
- )
9240
- );
9241
- }
9242
- :scope:focus-visible {
9243
- border-color: var(
9244
- --ui-textarea-focus-border,
9245
- var(--_ui-default-textarea-focus-border, var(--ui-control-focus, var(--ui-accent-solid)))
9246
- );
9247
- outline: var(--ui-textarea-focus-outline, var(--_ui-default-textarea-focus-outline, none));
9248
- box-shadow: var(
9249
- --ui-textarea-focus-shadow,
9250
- var(
9251
- --_ui-default-textarea-focus-shadow,
9252
- var(--ui-control-inset),
9253
- var(--ui-control-focus-halo-shadow)
9254
- )
9255
- );
9256
- }
9257
- :scope[aria-invalid="true"],:scope:is(:user-invalid, [data-user-invalid]) {
9258
- border-color: var(
9259
- --ui-textarea-invalid-border,
9260
- var(--_ui-default-textarea-invalid-border, var(--ui-field-danger, var(--ui-danger-solid)))
9261
- );
9262
- }
9263
- :scope:is([aria-invalid="true"], :is(:user-invalid, [data-user-invalid])):focus-visible {
9264
- box-shadow: var(
9265
- --ui-textarea-invalid-focus-shadow,
9266
- var(
9267
- --_ui-default-textarea-invalid-focus-shadow,
9268
- var(--ui-control-inset),
9269
- 0 0 0 calc(var(--ui-focus-width) * 1.5) color-mix(
9270
- in srgb,
9271
- var(
9272
- --ui-textarea-invalid-border,
9273
- var(
9274
- --_ui-default-textarea-invalid-border,
9275
- var(--ui-field-danger, var(--ui-danger-solid))
9276
- )
9277
- ) 22%,
9278
- transparent
9279
- )
9280
- )
9281
- );
9282
- }
9283
- :scope:disabled {
9284
- background: var(--ui-control-surface-disabled, var(--ui-surface-muted));
9285
- color: var(--ui-disabled-text);
9286
- box-shadow: none;
9287
- cursor: not-allowed;
9288
- }
9289
- :scope[data-ui-textarea-state~="size=sm"] {
9290
- --_padding-block: var(--ui-space-1);
9291
- padding: var(--ui-space-1) var(--ui-space-2);
9292
- padding-inline-end: var(
9293
- --ui-textarea-padding-inline-end,
9294
- var(--_ui-default-textarea-padding-inline-end, var(--ui-space-2))
9295
- );
9296
- font-size: var(--ui-font-size-sm);
9297
- }
9298
- :scope[data-ui-textarea-state~="size=lg"] {
9299
- --_padding-block: var(--ui-space-3);
9300
- padding: var(--ui-space-3) var(--ui-space-4);
9301
- padding-inline-end: var(
9302
- --ui-textarea-padding-inline-end,
9303
- var(--_ui-default-textarea-padding-inline-end, var(--ui-space-4))
9304
- );
9305
- font-size: var(--ui-font-size-md);
9306
- }
9307
- :scope[data-ui-textarea-state~="maxRows"] {
9308
- max-block-size: calc(
9309
- max(var(--_rows), var(--_max-rows)) * 1lh + var(--_padding-block) + var(--_padding-block) +
9310
- 2px
9311
- );
9312
- }
9313
- @supports (field-sizing: content) {
9314
- :scope[data-ui-textarea-state~="autosize"] {
9315
- field-sizing: content;
9316
- min-block-size: calc(
9317
- var(--_rows) * 1lh + var(--_padding-block) + var(--_padding-block) + 2px
9318
- );
9319
- }
9320
- }
9321
- @media (pointer: coarse) {
9322
- :scope[data-ui-textarea-state~="size=sm"] {
9323
- font-size: inherit;
9324
- }
9325
- }
9326
- :scope[hidden] {
9327
- display: none;
9328
- }
9329
- }
9330
-
9331
9331
  /* Component hooks stay on this toast; group overlay values may inherit from the region. */
9332
9332
  @property --ui-toast-surface {
9333
9333
  syntax: "*";
@@ -9436,7 +9436,7 @@ input:where([data-hn-ui-switch]),input:where([data-hn-ui-switch])::after {
9436
9436
  }
9437
9437
 
9438
9438
  /* Leaving slides on down and fades; the controller removes the toast when this ends. */
9439
- @keyframes ui-toast-enter-f4df0ea9 {
9439
+ @keyframes ui-toast-enter-cab264c9 {
9440
9440
  from {
9441
9441
  opacity: 0;
9442
9442
  transform: translateY(-1rem);
@@ -9446,7 +9446,7 @@ to {
9446
9446
  transform: translateY(0);
9447
9447
  }
9448
9448
  }
9449
- @keyframes ui-toast-exit-f4df0ea9 {
9449
+ @keyframes ui-toast-exit-cab264c9 {
9450
9450
  from {
9451
9451
  opacity: 1;
9452
9452
  transform: translateY(0);
@@ -9456,7 +9456,7 @@ to {
9456
9456
  transform: translateY(0.75rem);
9457
9457
  }
9458
9458
  }
9459
- @keyframes ui-toast-enter-bottom-f4df0ea9 {
9459
+ @keyframes ui-toast-enter-bottom-cab264c9 {
9460
9460
  from {
9461
9461
  opacity: 0;
9462
9462
  transform: translateY(1rem);
@@ -9466,7 +9466,7 @@ to {
9466
9466
  transform: translateY(0);
9467
9467
  }
9468
9468
  }
9469
- @keyframes ui-toast-exit-bottom-f4df0ea9 {
9469
+ @keyframes ui-toast-exit-bottom-cab264c9 {
9470
9470
  from {
9471
9471
  opacity: 1;
9472
9472
  transform: translateY(0);
@@ -9557,7 +9557,7 @@ to {
9557
9557
  --_ui-toast-region-shadow,
9558
9558
  var(--ui-overlay-shadow, var(--ui-elevation-overlay, var(--ui-shadow-lg)))
9559
9559
  );
9560
- animation: ui-toast-enter-f4df0ea9 var(--_ui-toast-region-enter-duration, 0.32s)
9560
+ animation: ui-toast-enter-cab264c9 var(--_ui-toast-region-enter-duration, 0.32s)
9561
9561
  var(--ui-motion-ease-out, cubic-bezier(0.16, 1, 0.3, 1)) both;
9562
9562
  }
9563
9563
  .toast[data-tone="info"]:where([data-hn-ui-toast-region]) {
@@ -9577,17 +9577,17 @@ to {
9577
9577
  --_ui-toast-region-tone-surface: var(--ui-danger-soft);
9578
9578
  }
9579
9579
  .toast.closing:where([data-hn-ui-toast-region]) {
9580
- animation: ui-toast-exit-f4df0ea9 var(--_ui-toast-region-exit-duration, 0.22s) var(--ui-motion-ease)
9580
+ animation: ui-toast-exit-cab264c9 var(--_ui-toast-region-exit-duration, 0.22s) var(--ui-motion-ease)
9581
9581
  both;
9582
9582
  pointer-events: none;
9583
9583
  }
9584
9584
  :is(:scope[data-ui-toast-region-state~="placement=bottom"], :scope[data-ui-toast-region-state~="placement=bottom-start"], :scope[data-ui-toast-region-state~="placement=bottom-end"])
9585
9585
  .toast:where([data-hn-ui-toast-region]) {
9586
- animation-name: ui-toast-enter-bottom-f4df0ea9;
9586
+ animation-name: ui-toast-enter-bottom-cab264c9;
9587
9587
  }
9588
9588
  :is(:scope[data-ui-toast-region-state~="placement=bottom"], :scope[data-ui-toast-region-state~="placement=bottom-start"], :scope[data-ui-toast-region-state~="placement=bottom-end"])
9589
9589
  .toast.closing:where([data-hn-ui-toast-region]) {
9590
- animation-name: ui-toast-exit-bottom-f4df0ea9;
9590
+ animation-name: ui-toast-exit-bottom-cab264c9;
9591
9591
  }
9592
9592
  @media (prefers-reduced-motion: reduce) {
9593
9593
  .toast:where([data-hn-ui-toast-region]),.toast.closing:where([data-hn-ui-toast-region]) {
@@ -9788,7 +9788,7 @@ to {
9788
9788
  slides, the label reaches back under the icon (the controller measures how far) with its text
9789
9789
  where it was, and fades out across the gap before the icon, fully gone where the icon begins
9790
9790
  to cover it: the name slips under the icon rather than stopping at a hard edge beside it. */
9791
- @keyframes ui-tree-item-marquee-26f52f6b {
9791
+ @keyframes ui-tree-item-marquee-16fe002b {
9792
9792
  from {
9793
9793
  transform: translateX(0);
9794
9794
  }
@@ -10044,7 +10044,7 @@ to {
10044
10044
  .row[data-ui-marquee] > .label > .label-text:where([data-hn-ui-tree-item]) {
10045
10045
  /* Once per pass: the controller restarts it after a rest at the end, so the name holds still
10046
10046
  long enough to read rather than sliding back and forth. */
10047
- animation: ui-tree-item-marquee-26f52f6b var(--_marquee-duration) linear 0.5s 1 normal forwards;
10047
+ animation: ui-tree-item-marquee-16fe002b var(--_marquee-duration) linear 0.5s 1 normal forwards;
10048
10048
  will-change: transform;
10049
10049
  }
10050
10050
  .row[data-ui-marquee] > .label:where([data-hn-ui-tree-item]) {