@kennycorrea/ui 0.11.3 → 1.6.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 (246) hide show
  1. package/CHANGELOG.md +189 -0
  2. package/README.md +251 -1
  3. package/dist/atoms/ActionMenu/ActionMenu.d.ts +37 -0
  4. package/dist/atoms/ActionMenu/ActionMenu.js +28 -0
  5. package/dist/atoms/ActionMenu/index.d.ts +1 -0
  6. package/dist/atoms/ActionMenu/index.js +1 -0
  7. package/dist/atoms/ActionSheet/ActionSheet.d.ts +10 -4
  8. package/dist/atoms/ActionSheet/ActionSheet.js +6 -15
  9. package/dist/atoms/ActionSheet/confirm.d.ts +1 -1
  10. package/dist/atoms/ActionSheet/confirm.js +1 -1
  11. package/dist/atoms/Avatar/Avatar.d.ts +1 -1
  12. package/dist/atoms/Badge/Badge.js +4 -4
  13. package/dist/atoms/Button/Button.js +2 -3
  14. package/dist/atoms/Button/Button.types.d.ts +5 -8
  15. package/dist/atoms/Card/Card.d.ts +5 -3
  16. package/dist/atoms/Card/Card.js +21 -4
  17. package/dist/atoms/ContextMenu/ContextMenu.d.ts +1 -1
  18. package/dist/atoms/ContextMenu/ContextMenu.js +1 -1
  19. package/dist/atoms/Drawer/Drawer.js +1 -1
  20. package/dist/atoms/Icon/Icon.d.ts +7 -9
  21. package/dist/atoms/Icon/Icon.js +23 -8
  22. package/dist/atoms/Pill/Pill.d.ts +17 -0
  23. package/dist/atoms/Pill/Pill.js +12 -0
  24. package/dist/atoms/Pill/index.d.ts +1 -0
  25. package/dist/atoms/Pill/index.js +1 -0
  26. package/dist/atoms/ResponsiveDialog/ResponsiveDialog.d.ts +9 -2
  27. package/dist/atoms/ResponsiveDialog/ResponsiveDialog.js +6 -15
  28. package/dist/atoms/Sheet/Sheet.js +1 -1
  29. package/dist/atoms/StatusIndicator/StatusIndicator.d.ts +14 -0
  30. package/dist/atoms/StatusIndicator/StatusIndicator.js +8 -0
  31. package/dist/atoms/StatusIndicator/index.d.ts +1 -0
  32. package/dist/atoms/StatusIndicator/index.js +1 -0
  33. package/dist/atoms/TextLink/TextLink.d.ts +36 -0
  34. package/dist/atoms/TextLink/TextLink.js +17 -0
  35. package/dist/atoms/TextLink/index.d.ts +1 -0
  36. package/dist/atoms/TextLink/index.js +1 -0
  37. package/dist/atoms/Toast/Toast.d.ts +1 -1
  38. package/dist/atoms/Toast/Toast.js +1 -1
  39. package/dist/atoms/index.d.ts +4 -0
  40. package/dist/atoms/index.js +4 -0
  41. package/dist/hooks/breakpoints.d.ts +20 -0
  42. package/dist/hooks/breakpoints.js +13 -0
  43. package/dist/hooks/index.d.ts +4 -0
  44. package/dist/hooks/index.js +4 -0
  45. package/dist/hooks/useControllableState.d.ts +17 -0
  46. package/dist/hooks/useControllableState.js +22 -0
  47. package/dist/hooks/useElementWidth.d.ts +7 -0
  48. package/dist/hooks/useElementWidth.js +22 -0
  49. package/dist/hooks/useMediaQuery.d.ts +18 -0
  50. package/dist/hooks/useMediaQuery.js +51 -0
  51. package/dist/index.d.ts +4 -0
  52. package/dist/index.js +4 -0
  53. package/dist/molecules/AccentPicker/AccentPicker.d.ts +30 -0
  54. package/dist/molecules/AccentPicker/AccentPicker.js +27 -0
  55. package/dist/molecules/AccentPicker/index.d.ts +1 -0
  56. package/dist/molecules/AccentPicker/index.js +1 -0
  57. package/dist/molecules/Breadcrumbs/Breadcrumbs.d.ts +27 -0
  58. package/dist/molecules/Breadcrumbs/Breadcrumbs.js +40 -0
  59. package/dist/molecules/Breadcrumbs/index.d.ts +1 -0
  60. package/dist/molecules/Breadcrumbs/index.js +1 -0
  61. package/dist/molecules/Calendar/Calendar.d.ts +42 -0
  62. package/dist/molecules/Calendar/Calendar.js +111 -0
  63. package/dist/molecules/Calendar/index.d.ts +1 -0
  64. package/dist/molecules/Calendar/index.js +1 -0
  65. package/dist/molecules/DateInput/DateInput.d.ts +35 -0
  66. package/dist/molecules/DateInput/DateInput.js +41 -0
  67. package/dist/molecules/DateInput/index.d.ts +1 -0
  68. package/dist/molecules/DateInput/index.js +1 -0
  69. package/dist/molecules/EmptyState/EmptyState.d.ts +19 -0
  70. package/dist/molecules/EmptyState/EmptyState.js +7 -0
  71. package/dist/molecules/EmptyState/index.d.ts +1 -0
  72. package/dist/molecules/EmptyState/index.js +1 -0
  73. package/dist/molecules/ErrorState/ErrorState.d.ts +18 -0
  74. package/dist/molecules/ErrorState/ErrorState.js +12 -0
  75. package/dist/molecules/ErrorState/index.d.ts +1 -0
  76. package/dist/molecules/ErrorState/index.js +1 -0
  77. package/dist/molecules/ErrorSummary/ErrorSummary.d.ts +25 -0
  78. package/dist/molecules/ErrorSummary/ErrorSummary.js +32 -0
  79. package/dist/molecules/ErrorSummary/index.d.ts +1 -0
  80. package/dist/molecules/ErrorSummary/index.js +1 -0
  81. package/dist/molecules/FilterChips/FilterChips.d.ts +10 -0
  82. package/dist/molecules/FilterChips/FilterChips.js +13 -0
  83. package/dist/molecules/FilterChips/index.d.ts +1 -0
  84. package/dist/molecules/FilterChips/index.js +1 -0
  85. package/dist/molecules/FilterPopover/FilterPopover.d.ts +27 -0
  86. package/dist/molecules/FilterPopover/FilterPopover.js +32 -0
  87. package/dist/molecules/FilterPopover/index.d.ts +1 -0
  88. package/dist/molecules/FilterPopover/index.js +1 -0
  89. package/dist/molecules/FormActions/FormActions.d.ts +16 -0
  90. package/dist/molecules/FormActions/FormActions.js +5 -0
  91. package/dist/molecules/FormActions/index.d.ts +1 -0
  92. package/dist/molecules/FormActions/index.js +1 -0
  93. package/dist/molecules/FormField/FormField.d.ts +52 -0
  94. package/dist/molecules/FormField/FormField.js +63 -0
  95. package/dist/molecules/FormField/index.d.ts +1 -0
  96. package/dist/molecules/FormField/index.js +1 -0
  97. package/dist/molecules/FormSection/FormSection.d.ts +14 -0
  98. package/dist/molecules/FormSection/FormSection.js +10 -0
  99. package/dist/molecules/FormSection/index.d.ts +1 -0
  100. package/dist/molecules/FormSection/index.js +1 -0
  101. package/dist/molecules/KeyValueList/KeyValueList.d.ts +22 -0
  102. package/dist/molecules/KeyValueList/KeyValueList.js +9 -0
  103. package/dist/molecules/KeyValueList/index.d.ts +1 -0
  104. package/dist/molecules/KeyValueList/index.js +1 -0
  105. package/dist/molecules/LoadingState/LoadingState.d.ts +20 -0
  106. package/dist/molecules/LoadingState/LoadingState.js +22 -0
  107. package/dist/molecules/LoadingState/index.d.ts +1 -0
  108. package/dist/molecules/LoadingState/index.js +1 -0
  109. package/dist/molecules/NavItem/NavItem.d.ts +31 -0
  110. package/dist/molecules/NavItem/NavItem.js +72 -0
  111. package/dist/molecules/NavItem/context.d.ts +14 -0
  112. package/dist/molecules/NavItem/context.js +5 -0
  113. package/dist/molecules/NavItem/index.d.ts +1 -0
  114. package/dist/molecules/NavItem/index.js +1 -0
  115. package/dist/molecules/Pagination/Pagination.d.ts +32 -0
  116. package/dist/molecules/Pagination/Pagination.js +57 -0
  117. package/dist/molecules/Pagination/index.d.ts +1 -0
  118. package/dist/molecules/Pagination/index.js +1 -0
  119. package/dist/molecules/PasswordInput/PasswordInput.d.ts +14 -0
  120. package/dist/molecules/PasswordInput/PasswordInput.js +16 -0
  121. package/dist/molecules/PasswordInput/index.d.ts +1 -0
  122. package/dist/molecules/PasswordInput/index.js +1 -0
  123. package/dist/molecules/SearchField/SearchField.d.ts +24 -0
  124. package/dist/molecules/SearchField/SearchField.js +58 -0
  125. package/dist/molecules/SearchField/index.d.ts +1 -0
  126. package/dist/molecules/SearchField/index.js +1 -0
  127. package/dist/molecules/StatGroup/StatGroup.d.ts +21 -0
  128. package/dist/molecules/StatGroup/StatGroup.js +10 -0
  129. package/dist/molecules/StatGroup/index.d.ts +1 -0
  130. package/dist/molecules/StatGroup/index.js +1 -0
  131. package/dist/molecules/ThemeToggle/ThemeToggle.d.ts +23 -0
  132. package/dist/molecules/ThemeToggle/ThemeToggle.js +26 -0
  133. package/dist/molecules/ThemeToggle/index.d.ts +1 -0
  134. package/dist/molecules/ThemeToggle/index.js +1 -0
  135. package/dist/molecules/UserMenu/UserMenu.d.ts +20 -0
  136. package/dist/molecules/UserMenu/UserMenu.js +14 -0
  137. package/dist/molecules/UserMenu/index.d.ts +1 -0
  138. package/dist/molecules/UserMenu/index.js +1 -0
  139. package/dist/molecules/index.d.ts +21 -0
  140. package/dist/molecules/index.js +21 -0
  141. package/dist/organisms/AppShell/AppShell.d.ts +29 -0
  142. package/dist/organisms/AppShell/AppShell.js +34 -0
  143. package/dist/organisms/AppShell/context.d.ts +14 -0
  144. package/dist/organisms/AppShell/context.js +6 -0
  145. package/dist/organisms/AppShell/index.d.ts +1 -0
  146. package/dist/organisms/AppShell/index.js +1 -0
  147. package/dist/organisms/AuthForms/AuthForms.d.ts +83 -0
  148. package/dist/organisms/AuthForms/AuthForms.js +57 -0
  149. package/dist/organisms/AuthForms/index.d.ts +2 -0
  150. package/dist/organisms/AuthForms/index.js +1 -0
  151. package/dist/organisms/AuthForms/shared.d.ts +36 -0
  152. package/dist/organisms/AuthForms/shared.js +36 -0
  153. package/dist/organisms/BulkActionBar/BulkActionBar.d.ts +25 -0
  154. package/dist/organisms/BulkActionBar/BulkActionBar.js +18 -0
  155. package/dist/organisms/BulkActionBar/index.d.ts +1 -0
  156. package/dist/organisms/BulkActionBar/index.js +1 -0
  157. package/dist/organisms/Chart/CategoryCharts.d.ts +34 -0
  158. package/dist/organisms/Chart/CategoryCharts.js +93 -0
  159. package/dist/organisms/Chart/ChartFrame.d.ts +26 -0
  160. package/dist/organisms/Chart/ChartFrame.js +18 -0
  161. package/dist/organisms/Chart/DonutChart.d.ts +25 -0
  162. package/dist/organisms/Chart/DonutChart.js +53 -0
  163. package/dist/organisms/Chart/Sparkline.d.ts +15 -0
  164. package/dist/organisms/Chart/Sparkline.js +18 -0
  165. package/dist/organisms/Chart/index.d.ts +5 -0
  166. package/dist/organisms/Chart/index.js +5 -0
  167. package/dist/organisms/Chart/shared.d.ts +51 -0
  168. package/dist/organisms/Chart/shared.js +113 -0
  169. package/dist/organisms/DataTable/DataTable.d.ts +63 -0
  170. package/dist/organisms/DataTable/DataTable.js +119 -0
  171. package/dist/organisms/DataTable/index.d.ts +3 -0
  172. package/dist/organisms/DataTable/index.js +3 -0
  173. package/dist/organisms/DataTable/types.d.ts +39 -0
  174. package/dist/organisms/DataTable/types.js +1 -0
  175. package/dist/organisms/DataTable/useClientTable.d.ts +27 -0
  176. package/dist/organisms/DataTable/useClientTable.js +51 -0
  177. package/dist/organisms/DateRangePicker/DateRangePicker.d.ts +43 -0
  178. package/dist/organisms/DateRangePicker/DateRangePicker.js +54 -0
  179. package/dist/organisms/DateRangePicker/index.d.ts +1 -0
  180. package/dist/organisms/DateRangePicker/index.js +1 -0
  181. package/dist/organisms/FilterBar/FilterBar.d.ts +28 -0
  182. package/dist/organisms/FilterBar/FilterBar.js +16 -0
  183. package/dist/organisms/FilterBar/index.d.ts +1 -0
  184. package/dist/organisms/FilterBar/index.js +1 -0
  185. package/dist/organisms/PageHeader/PageHeader.d.ts +31 -0
  186. package/dist/organisms/PageHeader/PageHeader.js +19 -0
  187. package/dist/organisms/PageHeader/index.d.ts +1 -0
  188. package/dist/organisms/PageHeader/index.js +1 -0
  189. package/dist/organisms/PageTabs/PageTabs.d.ts +27 -0
  190. package/dist/organisms/PageTabs/PageTabs.js +31 -0
  191. package/dist/organisms/PageTabs/index.d.ts +1 -0
  192. package/dist/organisms/PageTabs/index.js +1 -0
  193. package/dist/organisms/Sidebar/Sidebar.d.ts +48 -0
  194. package/dist/organisms/Sidebar/Sidebar.js +61 -0
  195. package/dist/organisms/Sidebar/index.d.ts +1 -0
  196. package/dist/organisms/Sidebar/index.js +1 -0
  197. package/dist/organisms/Topbar/Topbar.d.ts +24 -0
  198. package/dist/organisms/Topbar/Topbar.js +18 -0
  199. package/dist/organisms/Topbar/index.d.ts +1 -0
  200. package/dist/organisms/Topbar/index.js +1 -0
  201. package/dist/organisms/index.d.ts +11 -0
  202. package/dist/organisms/index.js +11 -0
  203. package/dist/strings.d.ts +108 -15
  204. package/dist/strings.js +73 -7
  205. package/dist/templates/AdminLayout/AdminLayout.d.ts +14 -0
  206. package/dist/templates/AdminLayout/AdminLayout.js +9 -0
  207. package/dist/templates/AdminLayout/index.d.ts +1 -0
  208. package/dist/templates/AdminLayout/index.js +1 -0
  209. package/dist/templates/AuthLayout/AuthLayout.d.ts +28 -0
  210. package/dist/templates/AuthLayout/AuthLayout.js +11 -0
  211. package/dist/templates/AuthLayout/index.d.ts +1 -0
  212. package/dist/templates/AuthLayout/index.js +1 -0
  213. package/dist/templates/DashboardPage/DashboardPage.d.ts +25 -0
  214. package/dist/templates/DashboardPage/DashboardPage.js +12 -0
  215. package/dist/templates/DashboardPage/index.d.ts +1 -0
  216. package/dist/templates/DashboardPage/index.js +1 -0
  217. package/dist/templates/DetailPage/DetailPage.d.ts +20 -0
  218. package/dist/templates/DetailPage/DetailPage.js +11 -0
  219. package/dist/templates/DetailPage/index.d.ts +1 -0
  220. package/dist/templates/DetailPage/index.js +1 -0
  221. package/dist/templates/FormPage/FormPage.d.ts +26 -0
  222. package/dist/templates/FormPage/FormPage.js +11 -0
  223. package/dist/templates/FormPage/index.d.ts +1 -0
  224. package/dist/templates/FormPage/index.js +1 -0
  225. package/dist/templates/ListPage/ListPage.d.ts +17 -0
  226. package/dist/templates/ListPage/ListPage.js +8 -0
  227. package/dist/templates/ListPage/index.d.ts +1 -0
  228. package/dist/templates/ListPage/index.js +1 -0
  229. package/dist/templates/SettingsPage/SettingsPage.d.ts +32 -0
  230. package/dist/templates/SettingsPage/SettingsPage.js +13 -0
  231. package/dist/templates/SettingsPage/index.d.ts +1 -0
  232. package/dist/templates/SettingsPage/index.js +1 -0
  233. package/dist/templates/StatusPage/StatusPage.d.ts +18 -0
  234. package/dist/templates/StatusPage/StatusPage.js +8 -0
  235. package/dist/templates/StatusPage/index.d.ts +1 -0
  236. package/dist/templates/StatusPage/index.js +1 -0
  237. package/dist/templates/index.d.ts +8 -0
  238. package/dist/templates/index.js +8 -0
  239. package/dist/utils/dates.d.ts +67 -0
  240. package/dist/utils/dates.js +154 -0
  241. package/dist/utils/index.d.ts +1 -0
  242. package/dist/utils/index.js +1 -0
  243. package/dist/utils/theme.d.ts +4 -0
  244. package/dist/utils/theme.js +7 -3
  245. package/package.json +4 -1
  246. package/tokens.css +513 -21
package/tokens.css CHANGED
@@ -1,27 +1,16 @@
1
1
  /**
2
2
  * The house token bridge — the shared half of every consuming app's stylesheet.
3
3
  *
4
- * Two apps said `text-ink-muted` and `bg-brand-700/8` and each carried its own copy of what
5
- * those meant. The values below are the dashboard's, which was the more complete of the two.
4
+ * Names such as `text-ink-muted` and `bg-brand-700/8` mean the same thing in every app that
5
+ * imports this file, because the meaning lives here and not in a copy per app.
6
6
  *
7
- * **How far the two copies had actually drifted, measured rather than assumed**, because the
8
- * answer is narrower than "two copies always diverge" and the difference matters:
7
+ * Two things worth knowing before editing it:
9
8
  *
10
- * - **The live values agreed.** `--color-ink` resolved to `var(--gray-12)` in both,
11
- * `--color-hairline` to `var(--gray-a6)`, and the backdrop to the same `oklch` literal. The
12
- * `.radix-themes` blocks had been kept in step by hand, and they were right.
13
- * - **The static fallbacks in `@theme` had not been.** `--color-ink` was `#1d3b31` here and
14
- * `#1a211f` there; the hairline 12% against 10%. Those only show if the Radix stylesheet
15
- * fails to load, so the drift was real and invisible — the worst kind to leave lying around,
16
- * and the least urgent.
17
- * - **`--font-sans` was the one live difference**: `'Inter', …` in the dashboard against
18
- * `ui-sans-serif, …` on the site. ⚠ And neither app loads Inter, so the dashboard has been
19
- * asking for a font it does not have and both render the system stack. Unified here; if Inter
20
- * is ever wanted it needs adding to the apps' HTML, and then it will apply to all three at
21
- * once, which is the point.
22
- *
23
- * The drift that was live and visible was in the **components**, not the colours — see the
24
- * `Button` note in the README.
9
+ * - **The live values are in the `.radix-themes` blocks.** The `@theme` values are static
10
+ * fallbacks that only show if the Radix stylesheet fails to load. Keep the two in step;
11
+ * drift between them is invisible until that failure happens.
12
+ * - **`--font-sans` names `'Inter'` first.** The library does not load it. An app that wants it
13
+ * adds it to its own HTML; otherwise the system stack renders.
25
14
  *
26
15
  * **How to use it**, in an app's own `index.css`:
27
16
  *
@@ -154,7 +143,7 @@
154
143
  --color-sheet: var(--color-panel-solid);
155
144
 
156
145
  /**
157
- * The deep field behind sign-in and the public booking page, and the wash behind a
146
+ * The deep field behind sign-in and other full-bleed pages, and the wash behind a
158
147
  * dialog. Both have to stay dark in *either* appearance.
159
148
  *
160
149
  * **Neither can be a step from an accent scale.** Themes flips the whole ramp between
@@ -176,13 +165,28 @@
176
165
  /* An alpha step, so a hairline stays a hairline over whatever surface is beneath it. */
177
166
  --color-hairline: var(--gray-a6);
178
167
 
168
+ /**
169
+ * The categorical chart palette: eight hues that each reach 3:1 (WCAG 1.4.11, graphical
170
+ * objects) against the panel in both appearances, held there by test/contrast.test.tsx.
171
+ * Amber, yellow, lime, mint and sky are left out: their step 9 is under 2:1 on white.
172
+ * Charts also mark series by pattern or shape, so colour is never the only difference.
173
+ */
174
+ --chart-1: var(--blue-9);
175
+ --chart-2: var(--orange-10);
176
+ --chart-3: var(--jade-9);
177
+ --chart-4: var(--violet-9);
178
+ --chart-5: var(--crimson-9);
179
+ --chart-6: var(--cyan-10);
180
+ --chart-7: var(--gold-9);
181
+ --chart-8: var(--pink-9);
182
+
179
183
  /**
180
184
  * Warning, danger and success, from Radix's own scales.
181
185
  *
182
186
  * A fill and an ink, because the two move in opposite directions between appearances:
183
187
  * the fill stays a faint wash while the ink goes from nearly black to nearly white.
184
188
  * Step 11 is Radix's "text on a tinted background", which is precisely this job — and
185
- * it is what makes a pending booking legible in the dark theme without a second rule.
189
+ * it is what makes a pending status legible in the dark theme without a second rule.
186
190
  */
187
191
  --color-warn: var(--amber-9);
188
192
  --color-warn-ink: var(--amber-11);
@@ -233,6 +237,14 @@
233
237
  --safe-bottom: env(safe-area-inset-bottom, 0px);
234
238
  --safe-left: env(safe-area-inset-left, 0px);
235
239
  --material-bar-filter: saturate(180%) blur(20px);
240
+ /* Admin layout. Nothing reads these yet; the shell and table components will. An app can
241
+ override any of them on :root or on a wrapper. */
242
+ --sidebar-width: 256px;
243
+ --sidebar-width-collapsed: 64px;
244
+ --topbar-height: 56px;
245
+ --content-max-width: 1280px;
246
+ --table-row-height-comfortable: 48px;
247
+ --table-row-height-compact: 36px;
236
248
  }
237
249
 
238
250
  @layer base {
@@ -592,6 +604,15 @@
592
604
  * `md` is 768. Ascending media queries of equal specificity, so the widest match wins. The card's
593
605
  * pseudo-elements carry the surface and ring, so grouped/plain switch them off with `content`.
594
606
  */
607
+ /* Unlayered, like Themes' `.rt-Card` padding, and more specific: the header and body pad, the card
608
+ does not. A caller's padding class reaches the card as `!p-*` (see Card.tsx), which still wins. */
609
+ .ui-card.rt-Card { padding: 0; }
610
+ /*
611
+ * Card turns a caller's padding utility into its important form (`p-4` → `!p-4`) so it beats
612
+ * Themes' unlayered card padding. Tailwind only generates classes it finds in source, and the
613
+ * important form is never written anywhere, so it is listed here. Needs Tailwind 4.1+.
614
+ */
615
+ @source inline("{,sm:,md:,lg:,xl:}!{p,px,py,pt,pr,pb,pl,ps,pe}-{0,0.5,1,1.5,2,2.5,3,3.5,4,5,6,7,8,10,12}");
595
616
  .ui-card-header, .ui-card-body { padding: 16px 20px; }
596
617
  .ui-card-title { font-size: 1rem; font-weight: 500; }
597
618
  .ui-card.rt-Card[data-variant="outlined"] { background: transparent; --base-card-border-radius: var(--card-border-radius);}
@@ -841,6 +862,12 @@
841
862
  .ui-segmented__label { display: block; overflow: hidden; text-overflow: ellipsis; }
842
863
  .ui-segmented[data-size="md"] .ui-segmented__item { min-height: 32px; padding: 0 16px; font-size: 14px; }
843
864
  .ui-segmented[data-size="sm"] .ui-segmented__item { min-height: 24px; padding: 0 12px; font-size: 12px; }
865
+ /* Full width: items share the track instead of growing it past the pill. Equal 1fr columns from a
866
+ zero basis keep the thumb (100% / count) on each item exactly; labels ellipsize. */
867
+ .ui-segmented[data-full="true"] { overflow-x: hidden; }
868
+ .ui-segmented[data-full="true"] .ui-segmented__track { grid-auto-columns: minmax(0, 1fr); flex: 1 1 0; }
869
+ .ui-segmented[data-full="true"][data-size="md"] .ui-segmented__item { padding: 0 8px; }
870
+ .ui-segmented[data-full="true"][data-size="sm"] .ui-segmented__item { padding: 0 6px; }
844
871
  .ui-segmented__item[aria-checked="true"] { color: var(--gray-12); }
845
872
  .ui-segmented__item:disabled { opacity: 0.4; cursor: not-allowed; }
846
873
  .ui-segmented__item:focus-visible { outline: 2px solid var(--focus-8); outline-offset: 1px; }
@@ -917,3 +944,468 @@
917
944
  .ui-button, .ui-list-row[data-interactive], .ui-tabbar__item, .ui-stat[data-interactive] { transition: none; }
918
945
  .ui-button:active, .ui-list-row[data-interactive]:active, .ui-tabbar__item:active, .ui-stat[data-interactive]:active { transform: none; }
919
946
  }
947
+
948
+ /* Floating content: Themes' --shadow-5 opens with a `0 0 0 1px` ring that reads as a border on
949
+ menus, popovers and selects. Same elevation, without the ring. Unlayered to beat Themes. */
950
+ .radix-themes {
951
+ --ui-float-shadow: 0 12px 60px var(--black-a3), 0 12px 32px -16px var(--gray-a5);
952
+ }
953
+ .radix-themes:is(.dark, .dark-theme), :is(.dark, .dark-theme) .radix-themes:not(.light, .light-theme) {
954
+ --ui-float-shadow: 0 12px 60px var(--black-a5), 0 12px 32px -16px var(--black-a7);
955
+ }
956
+ .rt-BaseMenuContent, .rt-SelectContent, .rt-PopoverContent { box-shadow: var(--ui-float-shadow); }
957
+
958
+ /**
959
+ * Admin shell and navigation (1.2.0): AppShell, Sidebar, NavItem, Topbar, Breadcrumbs,
960
+ * PageHeader, PageTabs, UserMenu, AccentPicker.
961
+ *
962
+ * Which shell is shown (persistent sidebar or off-canvas panel) is decided in JavaScript,
963
+ * because the markup differs. Everything else here is CSS: media queries for the viewport,
964
+ * container queries where a component sits in a column of unknown width.
965
+ */
966
+ .ui-sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
967
+
968
+ .ui-shell { display: grid; grid-template-columns: minmax(0, 1fr); min-block-size: 100dvh; background: var(--color-canvas); }
969
+ .ui-shell[data-wide] { grid-template-columns: auto minmax(0, 1fr); }
970
+ .ui-shell__main { display: flex; flex-direction: column; min-inline-size: 0; }
971
+ .ui-shell__content { flex: 1; outline: none; }
972
+ .ui-skip-link { position: fixed; inset-block-start: 8px; inset-inline-start: 8px; z-index: 100; padding: 8px 12px; border-radius: var(--radius-3);
973
+ background: var(--color-panel-solid); color: var(--color-ink); box-shadow: var(--ui-float-shadow, 0 4px 16px var(--black-a5)); transform: translateY(-200%); }
974
+ .ui-skip-link:focus { transform: none; outline: 2px solid var(--focus-8); }
975
+
976
+ .ui-sidebar { position: sticky; inset-block-start: 0; display: flex; flex-direction: column; box-sizing: border-box;
977
+ block-size: 100dvh; inline-size: var(--sidebar-width); overflow: hidden;
978
+ border-inline-end: 1px solid var(--color-hairline); background: var(--color-panel-solid);
979
+ transition: inline-size 200ms ease-out; }
980
+ .ui-sidebar[data-collapsed] { inline-size: var(--sidebar-width-collapsed); }
981
+ .ui-sidebar__header, .ui-sidebar__footer { flex: none; padding: 12px; }
982
+ .ui-sidebar__header { min-block-size: var(--topbar-height); box-sizing: border-box; display: flex; align-items: center; gap: 8px; }
983
+ .ui-sidebar__footer { display: flex; flex-direction: column; gap: 4px; border-block-start: 1px solid var(--color-hairline); }
984
+ .ui-sidebar__nav { flex: 1; min-block-size: 0; overflow-y: auto; overscroll-behavior: contain; padding: 8px; }
985
+ .ui-sidebar__section + .ui-sidebar__section { margin-block-start: 16px; }
986
+ .ui-sidebar__section-label { margin: 0 0 4px; padding-inline: 10px; font-size: 12px; font-weight: 500; color: var(--color-ink-muted); }
987
+ .ui-sidebar__list { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 2px; }
988
+ .ui-sidebar[data-collapsed] .ui-sidebar__section-label,
989
+ .ui-sidebar[data-collapsed] .ui-nav-item__label,
990
+ .ui-sidebar[data-collapsed] .ui-nav-item__chevron { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
991
+ .ui-sidebar[data-collapsed] .ui-nav-item { justify-content: center; padding-inline: 0; }
992
+ .ui-sidebar[data-collapsed] .ui-nav-item__badge { position: absolute; inset-block-start: 4px; inset-inline-end: 6px; min-inline-size: 8px; block-size: 8px; padding: 0; font-size: 0; }
993
+ .ui-nav-item.ui-sidebar__close, .ui-nav-item.ui-topbar__menu { inline-size: auto; flex: none; }
994
+ .ui-sidebar-overlay { position: fixed; inset: 0; z-index: 49; background: var(--color-scrim); }
995
+ .ui-sidebar-panel { position: fixed; inset-block: 0; inset-inline-start: 0; z-index: 50; display: flex; flex-direction: column; box-sizing: border-box;
996
+ inline-size: min(var(--sidebar-width), 85vw); padding-block: var(--safe-top) var(--safe-bottom); padding-inline-start: var(--safe-left);
997
+ background: var(--color-panel-solid); box-shadow: var(--ui-float-shadow, 0 12px 60px var(--black-a5)); outline: none; }
998
+ .ui-sidebar-panel[data-state="open"] { animation: ui-sidebar-in 200ms ease-out; }
999
+ .ui-sidebar-overlay[data-state="open"] { animation: ui-fade-in 200ms ease-out; }
1000
+ @keyframes ui-sidebar-in { from { transform: translateX(-100%); } }
1001
+ @keyframes ui-fade-in { from { opacity: 0; } }
1002
+ [dir="rtl"] .ui-sidebar-panel[data-state="open"] { animation-name: ui-sidebar-in-rtl; }
1003
+ @keyframes ui-sidebar-in-rtl { from { transform: translateX(100%); } }
1004
+ @media (prefers-reduced-motion: reduce) {
1005
+ .ui-sidebar { transition: none; }
1006
+ .ui-sidebar-panel[data-state="open"], .ui-sidebar-overlay[data-state="open"] { animation: none; }
1007
+ }
1008
+
1009
+ .ui-nav-item { position: relative; display: flex; align-items: center; gap: 12px; box-sizing: border-box; inline-size: 100%;
1010
+ min-block-size: 36px; padding: 6px 10px; border: 0; border-radius: var(--radius-3); background: none;
1011
+ font: inherit; font-size: 14px; font-weight: 500; line-height: 20px; text-align: start; text-decoration: none;
1012
+ color: var(--gray-11); cursor: pointer; -webkit-tap-highlight-color: transparent; }
1013
+ .ui-nav-item[aria-current="page"] { background: var(--accent-a3); color: var(--accent-11); }
1014
+ .ui-nav-item:focus-visible { outline: 2px solid var(--focus-8); outline-offset: -2px; }
1015
+ .ui-nav-item:active { background: var(--gray-a4); }
1016
+ @media (hover: hover) { .ui-nav-item:hover { background: var(--gray-a3); color: var(--color-ink); } .ui-nav-item[aria-current="page"]:hover { background: var(--accent-a4); color: var(--accent-11); } }
1017
+ @media (pointer: coarse) { .ui-nav-item { min-block-size: var(--tap-min); } }
1018
+ .ui-nav-item__icon { display: inline-flex; flex: none; font-size: 20px; line-height: 1; }
1019
+ .ui-nav-item__label { flex: 1; min-inline-size: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1020
+ .ui-nav-item__badge { flex: none; min-inline-size: 20px; block-size: 20px; padding: 0 6px; box-sizing: border-box; border-radius: 10px;
1021
+ background: var(--accent-9); color: var(--accent-contrast); font-size: 12px; line-height: 20px; text-align: center; font-variant-numeric: tabular-nums; }
1022
+ .ui-nav-item__badge[data-dot] { min-inline-size: 8px; block-size: 8px; padding: 0; }
1023
+ .ui-nav-item__chevron { flex: none; display: inline-flex; transition: transform 150ms ease-out; }
1024
+ .ui-nav-item[aria-expanded="true"] .ui-nav-item__chevron { transform: rotate(180deg); }
1025
+ .ui-nav-group__items { margin: 2px 0 0; padding: 0 0 0 32px; list-style: none; display: flex; flex-direction: column; gap: 2px; }
1026
+ @media (prefers-reduced-motion: reduce) { .ui-nav-item__chevron { transition: none; } }
1027
+
1028
+ .ui-topbar { position: sticky; inset-block-start: 0; z-index: 20; display: grid; box-sizing: border-box;
1029
+ grid-template-columns: auto minmax(0, 1fr) auto; grid-template-areas: "lead title actions" "search search search";
1030
+ align-items: center; column-gap: 12px; min-block-size: calc(var(--topbar-height) + var(--safe-top));
1031
+ padding: var(--safe-top) var(--page-gutter, 16px) 0;
1032
+ background-color: var(--material-bar, var(--color-panel-solid)); -webkit-backdrop-filter: var(--material-bar-filter); backdrop-filter: var(--material-bar-filter);
1033
+ box-shadow: inset 0 -1px 0 var(--color-hairline); }
1034
+ .ui-topbar__lead { grid-area: lead; display: flex; align-items: center; gap: 8px; min-block-size: var(--topbar-height); }
1035
+ .ui-topbar__title { grid-area: title; min-inline-size: 0; margin: 0; font-size: 16px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1036
+ .ui-topbar__actions { grid-area: actions; display: flex; align-items: center; gap: 4px; }
1037
+ .ui-topbar__search { grid-area: search; padding-block-end: 8px; }
1038
+ @media (min-width: 768px) {
1039
+ .ui-topbar { grid-template-columns: auto minmax(0, 1fr) minmax(0, 360px) auto; grid-template-areas: "lead title search actions"; }
1040
+ .ui-topbar__search { padding-block-end: 0; }
1041
+ }
1042
+
1043
+ .ui-breadcrumbs__list { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; margin: 0; padding: 0; list-style: none; font-size: 14px; color: var(--color-ink-muted); }
1044
+ .ui-breadcrumbs__item { display: inline-flex; align-items: center; gap: 4px; min-inline-size: 0; }
1045
+ .ui-breadcrumbs__item [aria-current="page"] { color: var(--color-ink); font-weight: 500; }
1046
+ .ui-breadcrumbs__sep, .ui-breadcrumbs__back { display: inline-flex; color: var(--gray-9); }
1047
+ .ui-breadcrumbs__back { display: none; }
1048
+ .ui-breadcrumbs__item a { color: inherit; text-decoration: none; display: inline-flex; align-items: center; gap: 2px; }
1049
+ @media (hover: hover) { .ui-breadcrumbs__item a:hover { color: var(--color-ink); text-decoration: underline; } }
1050
+ .ui-breadcrumbs__item a:focus-visible, .ui-breadcrumbs__more:focus-visible { outline: 2px solid var(--focus-8); outline-offset: 2px; border-radius: var(--radius-1); }
1051
+ .ui-breadcrumbs__more { display: inline-flex; align-items: center; justify-content: center; min-inline-size: 24px; min-block-size: 24px;
1052
+ padding: 0 4px; border: 0; border-radius: var(--radius-2); background: none; color: inherit; cursor: pointer; }
1053
+ @media (hover: hover) { .ui-breadcrumbs__more:hover { background: var(--gray-a3); } }
1054
+ @media not (min-width: 768px) {
1055
+ .ui-breadcrumbs__item:not([data-parent]) { display: none; }
1056
+ .ui-breadcrumbs__item[data-parent] .ui-breadcrumbs__sep { display: none; }
1057
+ .ui-breadcrumbs__item[data-parent] .ui-breadcrumbs__back { display: inline-flex; }
1058
+ }
1059
+
1060
+ .ui-page-header { container-type: inline-size; display: flex; flex-direction: column; gap: 12px; padding-block: 8px 16px; }
1061
+ .ui-page-header__row { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: 12px; }
1062
+ .ui-page-header__text { flex: 1 1 240px; min-inline-size: 0; }
1063
+ .ui-page-header__title { margin: 0; font-size: 24px; line-height: 32px; font-weight: 600; color: var(--color-ink); overflow-wrap: anywhere; }
1064
+ .ui-page-header__description { margin: 4px 0 0; color: var(--color-ink-muted); }
1065
+ .ui-page-header__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
1066
+ .ui-page-header__secondary { display: contents; }
1067
+ @container (width < 640px) { .ui-page-header__secondary { display: none; } }
1068
+ @container (width >= 640px) { .ui-page-header__overflow { display: none; } }
1069
+
1070
+ .ui-page-tabs__list { display: flex; gap: 4px; margin: 0; padding: 0; list-style: none; overflow-x: auto; scrollbar-width: none;
1071
+ box-shadow: inset 0 -1px 0 var(--color-hairline); }
1072
+ .ui-page-tabs__list::-webkit-scrollbar { display: none; }
1073
+ .ui-page-tabs__item { display: inline-flex; align-items: center; gap: 6px; box-sizing: border-box; min-block-size: 40px; padding: 0 12px;
1074
+ border: 0; background: none; font: inherit; font-size: 14px; font-weight: 500; white-space: nowrap; text-decoration: none;
1075
+ color: var(--gray-11); cursor: pointer; box-shadow: inset 0 -2px 0 transparent; }
1076
+ .ui-page-tabs__item[aria-current="page"] { color: var(--color-ink); box-shadow: inset 0 -2px 0 var(--accent-9); }
1077
+ .ui-page-tabs__item:focus-visible { outline: 2px solid var(--focus-8); outline-offset: -2px; border-radius: var(--radius-2); }
1078
+ @media (hover: hover) { .ui-page-tabs__item:hover { color: var(--color-ink); } }
1079
+ @media (pointer: coarse) { .ui-page-tabs__item { min-block-size: var(--tap-min); } }
1080
+
1081
+ .ui-user-menu__trigger { display: inline-flex; align-items: center; gap: 8px; min-block-size: 36px; padding: 2px 8px 2px 2px; border: 0;
1082
+ border-radius: 999px; background: none; font: inherit; color: var(--color-ink); cursor: pointer; }
1083
+ .ui-user-menu__trigger:focus-visible { outline: 2px solid var(--focus-8); outline-offset: 2px; }
1084
+ @media (hover: hover) { .ui-user-menu__trigger:hover { background: var(--gray-a3); } }
1085
+ @media (pointer: coarse) { .ui-user-menu__trigger { min-block-size: var(--tap-min); } }
1086
+ .ui-user-menu__name { font-size: 14px; font-weight: 500; max-inline-size: 160px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1087
+ @media not (min-width: 768px) { .ui-user-menu__name { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); } .ui-user-menu__trigger { padding-inline-end: 2px; } }
1088
+
1089
+ .ui-accent-picker { display: flex; flex-wrap: wrap; gap: 8px; margin: 0; padding: 0; border: 0; }
1090
+ .ui-accent-picker__option { position: relative; display: inline-flex; cursor: pointer; }
1091
+ .ui-accent-picker__input { position: absolute; opacity: 0; width: 1px; height: 1px; margin: 0; }
1092
+ .ui-accent-picker__swatch { display: block; inline-size: 28px; block-size: 28px; border-radius: 50%; background: var(--swatch); box-shadow: inset 0 0 0 1px var(--black-a3); }
1093
+ .ui-accent-picker__input:checked + .ui-accent-picker__swatch { box-shadow: 0 0 0 2px var(--color-panel-solid), 0 0 0 4px var(--swatch); }
1094
+ .ui-accent-picker__input:focus-visible + .ui-accent-picker__swatch { outline: 2px solid var(--focus-8); outline-offset: 4px; }
1095
+ @media (pointer: coarse) { .ui-accent-picker__option::before { content: ''; position: absolute; inset: -8px; } }
1096
+
1097
+ .ui-admin-content { box-sizing: border-box; inline-size: 100%; max-inline-size: var(--content-max-width); margin-inline: auto; padding: 16px var(--page-gutter, 16px) 32px; }
1098
+ .ui-admin-content[data-width="full"] { max-inline-size: none; }
1099
+ @media (min-width: 768px) { .ui-admin-content { padding-block-start: 24px; } }
1100
+
1101
+ /**
1102
+ * Data display (1.3.0): StatusIndicator, Pill, EmptyState/ErrorState/LoadingState, Pagination,
1103
+ * DataTable, BulkActionBar, ListPage, DetailPage, StatusPage.
1104
+ *
1105
+ * Tables, pagination and states size to their own container, not the viewport: they sit in
1106
+ * columns, panels and dialogs as often as full-width.
1107
+ */
1108
+ .ui-status { display: inline-flex; align-items: center; gap: 6px; font-size: 14px; color: var(--color-ink); }
1109
+ .ui-status__dot { flex: none; inline-size: 8px; block-size: 8px; border-radius: 50%; background: var(--gray-9); }
1110
+ .ui-status[data-tone="success"] .ui-status__dot { background: var(--jade-9); }
1111
+ .ui-status[data-tone="warning"] .ui-status__dot { background: var(--amber-9); }
1112
+ .ui-status[data-tone="danger"] .ui-status__dot { background: var(--red-9); }
1113
+ .ui-status[data-tone="info"] .ui-status__dot { background: var(--blue-9); }
1114
+ .ui-status[data-pulse] .ui-status__dot { animation: ui-status-pulse 1.6s ease-in-out infinite; }
1115
+ @keyframes ui-status-pulse { 50% { opacity: 0.35; } }
1116
+ @media (prefers-reduced-motion: reduce) { .ui-status[data-pulse] .ui-status__dot { animation: none; } }
1117
+
1118
+ .ui-pill { display: inline-flex; align-items: center; gap: 2px; box-sizing: border-box; min-block-size: 24px; padding: 0 10px;
1119
+ border-radius: 999px; background: var(--gray-a3); color: var(--color-ink); font-size: 13px; line-height: 20px; }
1120
+ .ui-pill[data-removable] { padding-inline-end: 2px; }
1121
+ .ui-pill__remove { position: relative; display: inline-flex; align-items: center; justify-content: center; inline-size: 20px; block-size: 20px;
1122
+ padding: 0; border: 0; border-radius: 50%; background: none; color: var(--gray-11); cursor: pointer; }
1123
+ .ui-pill__remove:focus-visible { outline: 2px solid var(--focus-8); outline-offset: 1px; }
1124
+ @media (hover: hover) { .ui-pill__remove:hover { background: var(--gray-a4); color: var(--color-ink); } }
1125
+ @media (pointer: coarse) { .ui-pill__remove::before { content: ''; position: absolute; inset: -12px; } }
1126
+
1127
+ .ui-state { display: flex; flex-direction: column; align-items: center; gap: 8px; box-sizing: border-box;
1128
+ padding: 48px 16px; text-align: center; }
1129
+ .ui-state__icon { display: inline-flex; align-items: center; justify-content: center; inline-size: 48px; block-size: 48px; border-radius: 50%;
1130
+ background: var(--gray-a3); color: var(--gray-11); font-size: 24px; margin-block-end: 4px; }
1131
+ .ui-state[data-tone="danger"] .ui-state__icon { background: var(--red-a3); color: var(--red-11); }
1132
+ .ui-state__title { margin: 0; font-size: 16px; font-weight: 600; color: var(--color-ink); }
1133
+ .ui-state__description { margin: 0; max-inline-size: 48ch; color: var(--color-ink-muted); }
1134
+ .ui-state__actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; margin-block-start: 8px; }
1135
+ .ui-state__details { max-inline-size: 100%; margin-block-start: 8px; text-align: start; font-size: 13px; color: var(--color-ink-muted); }
1136
+ .ui-state__details pre { overflow: auto; white-space: pre-wrap; }
1137
+ .ui-state[data-size="sm"] { padding-block: 24px; }
1138
+ .ui-loading { display: flex; flex-direction: column; gap: 12px; }
1139
+ .ui-loading[data-variant="spinner"] { align-items: center; justify-content: center; padding: 48px 16px; }
1140
+ .ui-loading[data-variant="cards"] { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 220px), 1fr)); }
1141
+
1142
+ .ui-pagination { container-type: inline-size; }
1143
+ .ui-pagination__bar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 16px; font-size: 14px; color: var(--color-ink-muted); }
1144
+ .ui-pagination__size { display: inline-flex; align-items: center; gap: 8px; }
1145
+ .ui-pagination__nav { display: inline-flex; align-items: center; gap: 4px; }
1146
+ .ui-pagination__pages { display: inline-flex; align-items: center; gap: 4px; margin: 0; padding: 0; list-style: none; }
1147
+ .ui-pagination__page { position: relative; display: inline-flex; align-items: center; justify-content: center; box-sizing: border-box;
1148
+ min-inline-size: 32px; block-size: 32px; padding: 0 6px; border: 0; border-radius: var(--radius-2); background: none;
1149
+ font: inherit; font-variant-numeric: tabular-nums; color: var(--color-ink); cursor: pointer; }
1150
+ .ui-pagination__page[aria-current="page"] { background: var(--accent-9); color: var(--accent-contrast); }
1151
+ .ui-pagination__page:disabled { color: var(--gray-8); cursor: default; }
1152
+ .ui-pagination__page:focus-visible { outline: 2px solid var(--focus-8); outline-offset: 1px; }
1153
+ @media (hover: hover) { .ui-pagination__page:not([aria-current="page"]):not(:disabled):hover { background: var(--gray-a3); } }
1154
+ @media (pointer: coarse) { .ui-pagination__page::before { content: ''; position: absolute; inset: -6px; } }
1155
+ .ui-pagination__ellipsis { min-inline-size: 24px; text-align: center; }
1156
+ .ui-pagination__compact { display: none; font-variant-numeric: tabular-nums; color: var(--color-ink); }
1157
+ @container (width < 520px) { .ui-pagination__pages { display: none; } .ui-pagination__compact { display: inline; } .ui-pagination__size { display: none; } }
1158
+
1159
+ .ui-table { container-type: inline-size; display: flex; flex-direction: column; gap: 12px; }
1160
+ .ui-table__region { overflow: auto; border: 1px solid var(--color-hairline); border-radius: var(--radius-4); background: var(--color-panel-solid); }
1161
+ .ui-table__region:focus-visible { outline: 2px solid var(--focus-8); outline-offset: 2px; }
1162
+ .ui-table__table { inline-size: 100%; border-collapse: separate; border-spacing: 0; font-size: 14px; color: var(--color-ink); }
1163
+ .ui-table__caption { padding: 12px; text-align: start; font-weight: 600; }
1164
+ .ui-table__table th, .ui-table__table td { box-sizing: border-box; block-size: var(--table-row-height-comfortable); padding: 0 12px;
1165
+ border-block-end: 1px solid var(--color-hairline); text-align: start; vertical-align: middle; }
1166
+ .ui-table[data-density="compact"] .ui-table__table th, .ui-table[data-density="compact"] .ui-table__table td { block-size: var(--table-row-height-compact); }
1167
+ .ui-table__table thead th { position: sticky; inset-block-start: 0; z-index: 2; background: var(--color-panel-solid);
1168
+ font-size: 13px; font-weight: 500; color: var(--color-ink-muted); white-space: nowrap; }
1169
+ .ui-table__table tbody tr:last-child > * { border-block-end: 0; }
1170
+ .ui-table__table tbody th { font-weight: 500; }
1171
+ .ui-table__table [data-align="end"] { text-align: end; font-variant-numeric: tabular-nums; }
1172
+ .ui-table__table [data-align="center"] { text-align: center; }
1173
+ .ui-table__table [data-col="select"] { inline-size: 44px; padding-inline-end: 0; }
1174
+ .ui-table__table [data-col="actions"] { inline-size: 52px; text-align: end; }
1175
+ /* One tint per row, as a variable, so the sticky first cell can lay it over its solid ground. */
1176
+ .ui-table__table tbody tr { --row-tint: transparent; }
1177
+ .ui-table__table tbody tr[data-selected] { --row-tint: var(--accent-a3); }
1178
+ @media (hover: hover) {
1179
+ .ui-table__table tbody tr[data-clickable]:hover { --row-tint: var(--gray-a3); cursor: pointer; }
1180
+ .ui-table__table tbody tr[data-selected][data-clickable]:hover { --row-tint: var(--accent-a4); }
1181
+ }
1182
+ .ui-table__table tbody tr > * { background-color: var(--row-tint); }
1183
+ .ui-table[data-sticky-first] .ui-table__table tbody th { position: sticky; inset-inline-start: 0; z-index: 1;
1184
+ background: linear-gradient(var(--row-tint), var(--row-tint)), var(--color-panel-solid); }
1185
+ .ui-table__sort { display: inline-flex; align-items: center; gap: 4px; padding: 0; border: 0; background: none; font: inherit; color: inherit; cursor: pointer; }
1186
+ .ui-table__sort[data-sorted] { color: var(--color-ink); }
1187
+ .ui-table__sort:focus-visible, .ui-table__rowbutton:focus-visible { outline: 2px solid var(--focus-8); outline-offset: 2px; border-radius: var(--radius-1); }
1188
+ .ui-table__rowbutton { padding: 0; border: 0; background: none; font: inherit; color: inherit; text-align: start; cursor: pointer; }
1189
+ @media (hover: hover) { .ui-table__rowbutton:hover { text-decoration: underline; } }
1190
+ .ui-table__empty { padding: 0; }
1191
+ .ui-table__table .ui-table__empty { block-size: auto; }
1192
+ .ui-table__empty > * { flex: 1; }
1193
+ /* Specific enough to beat the stacked layout's display: flex on cells, so a narrow table hides
1194
+ these columns whether it is still a table or already cards. */
1195
+ @container (width < 640px) { .ui-table .ui-table__table :is(thead, tbody) tr > :is(th, td)[data-priority="low"] { display: none; } }
1196
+ @container (width < 480px) { .ui-table .ui-table__table :is(thead, tbody) tr > :is(th, td)[data-priority="medium"] { display: none; } }
1197
+ @container (width < 480px) {
1198
+ .ui-table[data-stack="sm"] :is(.ui-table__table, tbody, tr, th, td) { display: block; }
1199
+ .ui-table[data-stack="sm"] thead { display: none; }
1200
+ .ui-table[data-stack="sm"] .ui-table__region { border: 0; background: none; overflow: visible; }
1201
+ .ui-table[data-stack="sm"] tbody tr { position: relative; margin-block-end: 12px; padding: 8px 12px; border: 1px solid var(--color-hairline); border-radius: var(--radius-4); background: var(--color-panel-solid); }
1202
+ .ui-table[data-stack="sm"] .ui-table__table tbody :is(th, td) { display: flex; justify-content: space-between; gap: 12px; block-size: auto; min-block-size: 32px; align-items: center; padding: 4px 0; border: 0; text-align: end; }
1203
+ .ui-table[data-stack="sm"] tbody :is(th, td)[data-label]::before { content: attr(data-label); flex: none; color: var(--color-ink-muted); font-weight: 500; text-align: start; }
1204
+ .ui-table[data-stack="sm"] tbody th { position: static; font-weight: 600; text-align: start; }
1205
+ .ui-table[data-stack="sm"] tbody [data-col="select"] { inline-size: auto; }
1206
+ .ui-table[data-stack="sm"] tbody [data-col="actions"] { position: absolute; inset-block-start: 8px; inset-inline-end: 8px; inline-size: auto; min-block-size: 0; padding: 0; }
1207
+ }
1208
+ @container (width < 640px) {
1209
+ .ui-table[data-stack="md"] :is(.ui-table__table, tbody, tr, th, td) { display: block; }
1210
+ .ui-table[data-stack="md"] thead { display: none; }
1211
+ .ui-table[data-stack="md"] .ui-table__region { border: 0; background: none; overflow: visible; }
1212
+ .ui-table[data-stack="md"] tbody tr { position: relative; margin-block-end: 12px; padding: 8px 12px; border: 1px solid var(--color-hairline); border-radius: var(--radius-4); background: var(--color-panel-solid); }
1213
+ .ui-table[data-stack="md"] .ui-table__table tbody :is(th, td) { display: flex; justify-content: space-between; gap: 12px; block-size: auto; min-block-size: 32px; align-items: center; padding: 4px 0; border: 0; text-align: end; }
1214
+ .ui-table[data-stack="md"] tbody :is(th, td)[data-label]::before { content: attr(data-label); flex: none; color: var(--color-ink-muted); font-weight: 500; text-align: start; }
1215
+ .ui-table[data-stack="md"] tbody th { position: static; font-weight: 600; text-align: start; }
1216
+ .ui-table[data-stack="md"] tbody [data-col="select"] { inline-size: auto; }
1217
+ .ui-table[data-stack="md"] tbody [data-col="actions"] { position: absolute; inset-block-start: 8px; inset-inline-end: 8px; inline-size: auto; min-block-size: 0; padding: 0; }
1218
+ }
1219
+ @container (width < 800px) {
1220
+ .ui-table[data-stack="lg"] :is(.ui-table__table, tbody, tr, th, td) { display: block; }
1221
+ .ui-table[data-stack="lg"] thead { display: none; }
1222
+ .ui-table[data-stack="lg"] .ui-table__region { border: 0; background: none; overflow: visible; }
1223
+ .ui-table[data-stack="lg"] tbody tr { position: relative; margin-block-end: 12px; padding: 8px 12px; border: 1px solid var(--color-hairline); border-radius: var(--radius-4); background: var(--color-panel-solid); }
1224
+ .ui-table[data-stack="lg"] .ui-table__table tbody :is(th, td) { display: flex; justify-content: space-between; gap: 12px; block-size: auto; min-block-size: 32px; align-items: center; padding: 4px 0; border: 0; text-align: end; }
1225
+ .ui-table[data-stack="lg"] tbody :is(th, td)[data-label]::before { content: attr(data-label); flex: none; color: var(--color-ink-muted); font-weight: 500; text-align: start; }
1226
+ .ui-table[data-stack="lg"] tbody th { position: static; font-weight: 600; text-align: start; }
1227
+ .ui-table[data-stack="lg"] tbody [data-col="select"] { inline-size: auto; }
1228
+ .ui-table[data-stack="lg"] tbody [data-col="actions"] { position: absolute; inset-block-start: 8px; inset-inline-end: 8px; inline-size: auto; min-block-size: 0; padding: 0; }
1229
+ }
1230
+
1231
+ .ui-bulk-bar { position: sticky; inset-block-end: 16px; z-index: 10; display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
1232
+ box-sizing: border-box; inline-size: fit-content; max-inline-size: 100%; margin-inline: auto; padding: 8px 8px 8px 16px;
1233
+ border-radius: var(--radius-4); background: var(--color-panel-solid); box-shadow: var(--ui-float-shadow, 0 12px 32px var(--black-a5)), 0 0 0 1px var(--color-hairline); }
1234
+ .ui-bulk-bar__count { font-size: 14px; font-weight: 500; font-variant-numeric: tabular-nums; margin-inline-end: 8px; }
1235
+ .ui-bulk-bar { inset-block-end: calc(var(--bottom-bar-offset, 0px) + 16px); }
1236
+ /* Set by AppShell while its bottom TabBar is showing, so sticky bottom bars sit above it. */
1237
+ .ui-shell[data-tabbar] { --bottom-bar-offset: var(--tabbar-height); }
1238
+
1239
+ .ui-list-page { display: flex; flex-direction: column; gap: 16px; }
1240
+ .ui-detail-page { container-type: inline-size; display: flex; flex-direction: column; gap: 16px; }
1241
+ .ui-detail-page__body { display: grid; grid-template-columns: minmax(0, 1fr); gap: 24px; align-items: start; }
1242
+ @container (width >= 960px) { .ui-detail-page__body[data-has-aside] { grid-template-columns: minmax(0, 1fr) minmax(260px, 320px); } }
1243
+ .ui-status-page { display: grid; place-items: center; box-sizing: border-box; min-block-size: 100dvh; padding: 24px var(--page-gutter, 16px); background: var(--color-canvas); }
1244
+ .ui-status-page__code { margin: 0; font-size: 48px; line-height: 1; font-weight: 700; color: var(--accent-11); font-variant-numeric: tabular-nums; }
1245
+
1246
+ /**
1247
+ * Forms and filters (1.4.0): FormField, FormFieldset, ErrorSummary, FormSection, FormActions,
1248
+ * SearchField, FilterPopover, FilterBar, FormPage, SettingsPage.
1249
+ */
1250
+ .ui-field { display: flex; flex-direction: column; gap: 6px; min-inline-size: 0; }
1251
+ .ui-field[data-layout="inline"] { flex-direction: row; align-items: flex-start; gap: 10px; }
1252
+ .ui-field[data-layout="inline"] .ui-field__control { flex: none; padding-block-start: 2px; }
1253
+ .ui-field__text { display: flex; flex-direction: column; gap: 2px; min-inline-size: 0; }
1254
+ .ui-field__hint { margin: 0; font-size: 13px; color: var(--color-ink-muted); }
1255
+ .ui-field__error { display: flex; align-items: flex-start; gap: 6px; margin: 0; font-size: 13px; font-weight: 500; color: var(--red-11); }
1256
+ .ui-field__error svg { flex: none; margin-block-start: 2px; }
1257
+ .ui-fieldset { display: flex; flex-direction: column; gap: 8px; min-inline-size: 0; margin: 0; padding: 0; border: 0; }
1258
+ .ui-fieldset__legend { padding: 0; margin-block-end: 2px; font-size: 14px; font-weight: 500; color: var(--color-ink); }
1259
+
1260
+ .ui-error-summary { padding: 16px; border: 2px solid var(--red-9); border-radius: var(--radius-4); background: var(--red-a2); outline: none; }
1261
+ .ui-error-summary:focus-visible { outline: 2px solid var(--focus-8); outline-offset: 2px; }
1262
+ .ui-error-summary__title { margin: 0 0 8px; font-size: 16px; font-weight: 600; color: var(--color-ink); }
1263
+ .ui-error-summary__list { margin: 0; padding-inline-start: 20px; display: flex; flex-direction: column; gap: 4px; }
1264
+ .ui-error-summary__list a { color: var(--red-11); font-weight: 500; text-decoration: underline; }
1265
+ .ui-error-summary__list a:focus-visible { outline: 2px solid var(--focus-8); outline-offset: 2px; border-radius: var(--radius-1); }
1266
+
1267
+ .ui-form-section { container-type: inline-size; padding-block: 24px; border-block-end: 1px solid var(--color-hairline); }
1268
+ .ui-form-section:last-of-type { border-block-end: 0; }
1269
+ .ui-form-section__grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; }
1270
+ @container (width >= 720px) { .ui-form-section__grid { grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); gap: 32px; } }
1271
+ .ui-form-section__title { margin: 0; font-size: 16px; font-weight: 600; color: var(--color-ink); }
1272
+ .ui-form-section__description { margin: 4px 0 0; font-size: 14px; color: var(--color-ink-muted); }
1273
+ .ui-form-section__fields { display: flex; flex-direction: column; gap: 16px; min-inline-size: 0; }
1274
+
1275
+ .ui-form-actions { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 8px; padding-block: 16px; }
1276
+ .ui-form-actions[data-align="start"] { justify-content: flex-start; }
1277
+ .ui-form-actions[data-align="between"] { justify-content: space-between; }
1278
+ @media not (min-width: 768px) {
1279
+ .ui-form-actions[data-sticky] { position: sticky; inset-block-end: var(--bottom-bar-offset, 0px); z-index: 10;
1280
+ margin-inline: calc(-1 * var(--page-gutter, 16px)); padding: 12px var(--page-gutter, 16px) calc(12px + var(--safe-bottom));
1281
+ background-color: var(--material-bar, var(--color-panel-solid)); -webkit-backdrop-filter: var(--material-bar-filter); backdrop-filter: var(--material-bar-filter);
1282
+ box-shadow: inset 0 1px 0 var(--color-hairline); }
1283
+ .ui-form-actions[data-sticky] > * { flex: 1 1 0; }
1284
+ }
1285
+
1286
+ .ui-search__kbd { pointer-events: none; }
1287
+ @media (pointer: coarse) { .ui-search__kbd { display: none; } }
1288
+ .ui-count { display: inline-flex; align-items: center; justify-content: center; box-sizing: border-box; min-inline-size: 18px; block-size: 18px; padding: 0 5px;
1289
+ border-radius: 9px; background: var(--accent-9); color: var(--accent-contrast); font-size: 12px; font-weight: 600; font-variant-numeric: tabular-nums; }
1290
+ .ui-filter-popover__body { display: flex; flex-direction: column; gap: 12px; padding: 16px; }
1291
+ .ui-filter-popover__footer { display: flex; justify-content: flex-end; gap: 8px; padding: 12px 16px; border-block-start: 1px solid var(--color-hairline); }
1292
+
1293
+ .ui-filter-bar { container-type: inline-size; display: flex; flex-direction: column; gap: 8px; }
1294
+ .ui-filter-bar__row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
1295
+ .ui-filter-bar__search { flex: 1 1 240px; min-inline-size: 0; }
1296
+ .ui-filter-bar__actions { display: flex; align-items: center; gap: 8px; margin-inline-start: auto; }
1297
+ .ui-filter-bar__active { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: 0; padding: 0; list-style: none; }
1298
+ @container (width < 640px) { .ui-filter-bar__search { flex-basis: 100%; } }
1299
+
1300
+ .ui-settings { container-type: inline-size; }
1301
+ .ui-settings__grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; align-items: start; }
1302
+ .ui-settings__list { display: none; margin: 0; padding: 0; list-style: none; }
1303
+ .ui-settings__select { display: flex; flex-direction: column; gap: 6px; }
1304
+ @container (width >= 768px) {
1305
+ .ui-settings__grid { grid-template-columns: 220px minmax(0, 1fr); gap: 32px; }
1306
+ .ui-settings__list { display: flex; flex-direction: column; gap: 2px; position: sticky; inset-block-start: calc(var(--topbar-height) + 16px); }
1307
+ .ui-settings__select { display: none; }
1308
+ }
1309
+
1310
+ /**
1311
+ * Dates and charts (1.5.0): Calendar, DateInput, DateRangePicker, the chart family and
1312
+ * DashboardPage.
1313
+ */
1314
+ .ui-calendar { position: relative; display: inline-flex; flex-direction: column; padding: 8px; }
1315
+ .ui-calendar__nav { position: absolute; inset-block-start: 8px; inset-inline: 8px; display: flex; justify-content: space-between; pointer-events: none; }
1316
+ .ui-calendar__step { pointer-events: auto; display: inline-flex; align-items: center; justify-content: center; inline-size: 32px; block-size: 32px;
1317
+ border: 0; border-radius: var(--radius-2); background: none; color: var(--color-ink); cursor: pointer; }
1318
+ .ui-calendar__step:disabled { color: var(--gray-8); cursor: default; }
1319
+ .ui-calendar__step:focus-visible { outline: 2px solid var(--focus-8); outline-offset: 1px; }
1320
+ @media (hover: hover) { .ui-calendar__step:not(:disabled):hover { background: var(--gray-a3); } }
1321
+ [dir="rtl"] .ui-calendar__step svg { transform: scaleX(-1); }
1322
+ .ui-calendar__months { display: flex; flex-wrap: wrap; gap: 24px; }
1323
+ .ui-calendar__title { block-size: 32px; display: flex; align-items: center; justify-content: center; font-size: 14px; font-weight: 600; color: var(--color-ink); text-transform: capitalize; }
1324
+ .ui-calendar__grid { border-collapse: collapse; margin-block-start: 4px; }
1325
+ .ui-calendar__grid th { block-size: 28px; padding: 0; font-size: 12px; font-weight: 500; color: var(--color-ink-muted); text-align: center; }
1326
+ .ui-calendar__grid td { padding: 1px 0; text-align: center; }
1327
+ .ui-calendar__day { position: relative; display: inline-flex; align-items: center; justify-content: center; inline-size: 36px; block-size: 36px;
1328
+ border: 0; border-radius: var(--radius-2); background: none; font: inherit; font-size: 14px; font-variant-numeric: tabular-nums; color: var(--color-ink); cursor: pointer; }
1329
+ .ui-calendar__day[aria-current="date"] { font-weight: 700; box-shadow: inset 0 0 0 1px var(--gray-a7); }
1330
+ .ui-calendar__day[data-in-range] { background: var(--accent-a3); border-radius: 0; }
1331
+ .ui-calendar__day[data-selected] { background: var(--accent-9); color: var(--accent-contrast); }
1332
+ .ui-calendar__day[aria-disabled="true"] { color: var(--gray-8); text-decoration: line-through; cursor: default; }
1333
+ .ui-calendar__day:focus-visible { outline: 2px solid var(--focus-8); outline-offset: 1px; z-index: 1; }
1334
+ @media (hover: hover) { .ui-calendar__day:not([data-selected]):not([aria-disabled="true"]):hover { background: var(--gray-a3); } }
1335
+ @media (pointer: coarse) { .ui-calendar__day { inline-size: 44px; block-size: 44px; } }
1336
+ .ui-date-input.rt-Button { justify-content: flex-start; inline-size: 100%; font-weight: 400; }
1337
+ .ui-date-input[data-empty] { color: var(--color-ink-muted); }
1338
+ .ui-range-picker { display: flex; gap: 8px; }
1339
+ .ui-range-picker__presets { display: flex; flex-direction: column; gap: 2px; margin: 0; padding: 8px 0 8px 8px; list-style: none; min-inline-size: 140px;
1340
+ border-inline-end: 1px solid var(--color-hairline); }
1341
+ .ui-range-picker__presets .ui-nav-item[aria-pressed="true"] { background: var(--accent-a3); color: var(--accent-11); }
1342
+
1343
+ .ui-chart { inline-size: 100%; }
1344
+ .ui-chart svg { display: block; overflow: visible; }
1345
+ .ui-chart--donut { display: flex; flex-wrap: wrap; align-items: center; gap: 16px 24px; }
1346
+ .ui-chart--donut svg { flex: none; }
1347
+ .ui-chart__grid { stroke: var(--color-hairline); stroke-width: 1; }
1348
+ .ui-chart__axis { stroke: var(--gray-a8); stroke-width: 1; }
1349
+ .ui-chart__tick { fill: var(--gray-11); font-size: 11px; font-variant-numeric: tabular-nums; }
1350
+ .ui-chart__total { fill: var(--color-ink); font-size: 20px; font-weight: 600; font-variant-numeric: tabular-nums; }
1351
+ .ui-chart-legend { display: flex; flex-wrap: wrap; gap: 6px 16px; margin: 8px 0 0; padding: 0; list-style: none; font-size: 13px; color: var(--color-ink); }
1352
+ .ui-chart-legend li { display: inline-flex; align-items: center; gap: 6px; }
1353
+ .ui-chart-legend svg { flex: none; }
1354
+ .ui-chart-legend__detail { color: var(--color-ink-muted); font-variant-numeric: tabular-nums; }
1355
+ .ui-chart--donut .ui-chart-legend { flex-direction: column; margin: 0; }
1356
+ .ui-sparkline { inline-size: 100%; color: var(--accent-9); }
1357
+ .ui-sparkline svg { display: block; }
1358
+ .ui-chart-frame.rt-Card { padding: 0; }
1359
+ .ui-chart-frame__header { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: 8px; padding: 16px 16px 0; }
1360
+ .ui-chart-frame__title { margin: 0; font-size: 15px; font-weight: 600; color: var(--color-ink); }
1361
+ .ui-chart-frame__description { margin: 2px 0 0; font-size: 13px; color: var(--color-ink-muted); }
1362
+ .ui-chart-frame__actions { display: flex; align-items: center; gap: 8px; }
1363
+ .ui-chart-frame__body { padding: 12px 16px 16px; }
1364
+ .ui-chart-frame__table { overflow-x: auto; }
1365
+
1366
+ .ui-dashboard { container-type: inline-size; }
1367
+ .ui-dashboard__grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; align-items: start; }
1368
+ @container (width >= 640px) {
1369
+ .ui-dashboard__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
1370
+ .ui-dashboard__widget[data-span="2"], .ui-dashboard__widget[data-span="full"] { grid-column: 1 / -1; }
1371
+ }
1372
+ @container (width >= 1024px) {
1373
+ .ui-dashboard__grid[data-columns="3"] { grid-template-columns: repeat(3, minmax(0, 1fr)); }
1374
+ .ui-dashboard__grid[data-columns="4"] { grid-template-columns: repeat(4, minmax(0, 1fr)); }
1375
+ .ui-dashboard__widget[data-span="2"] { grid-column: span 2; }
1376
+ }
1377
+
1378
+ /** Auth pages (1.6.0): AuthLayout and the auth forms. */
1379
+ .ui-auth { display: grid; grid-template-columns: minmax(0, 1fr); min-block-size: 100dvh; background: var(--color-canvas); }
1380
+ .ui-auth__aside { display: none; }
1381
+ @media (min-width: 1024px) {
1382
+ .ui-auth[data-has-aside] { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
1383
+ .ui-auth__aside { display: block; position: relative; overflow: hidden; background: var(--color-backdrop); color: var(--color-onbackdrop); }
1384
+ }
1385
+ .ui-auth__main { position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 16px;
1386
+ box-sizing: border-box; padding: calc(24px + var(--safe-top)) var(--page-gutter, 16px) calc(24px + var(--safe-bottom)); }
1387
+ .ui-auth__toolbar { position: absolute; inset-block-start: calc(12px + var(--safe-top)); inset-inline-end: var(--page-gutter, 16px); }
1388
+ .ui-auth__card { box-sizing: border-box; inline-size: 100%; max-inline-size: 400px; padding: 32px; border-radius: var(--radius-5);
1389
+ background: var(--color-panel-solid); box-shadow: 0 0 0 1px var(--color-hairline), 0 8px 24px var(--black-a3); }
1390
+ .ui-auth__brand { margin-block-end: 16px; }
1391
+ .ui-auth__title { margin: 0; font-size: 22px; line-height: 28px; font-weight: 600; color: var(--color-ink); }
1392
+ .ui-auth__description { margin: 6px 0 0; color: var(--color-ink-muted); }
1393
+ .ui-auth__footer { font-size: 14px; color: var(--color-ink-muted); text-align: center; }
1394
+ @media not (min-width: 520px) {
1395
+ .ui-auth__main { justify-content: flex-start; padding-block-start: calc(56px + var(--safe-top)); }
1396
+ .ui-auth__card { padding: 0; border-radius: 0; background: none; box-shadow: none; }
1397
+ }
1398
+ .ui-auth-form { display: flex; flex-direction: column; gap: 16px; margin-block-start: 24px; }
1399
+ .ui-auth-form__row { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px; font-size: 14px; }
1400
+ .ui-auth-form__footer { font-size: 14px; color: var(--color-ink-muted); text-align: center; }
1401
+
1402
+
1403
+ /*
1404
+ * Invalid fields (1.6.1). Themes' `color="red"` only colours the focus ring, so an invalid field
1405
+ * looked like any other until focused. The field's own edge turns red too; the message under it
1406
+ * still carries the meaning, so colour is never the only signal.
1407
+ */
1408
+ .rt-TextFieldRoot:has(> input[aria-invalid="true"]),
1409
+ .rt-TextAreaRoot:has(> textarea[aria-invalid="true"]),
1410
+ .rt-SelectTrigger[aria-invalid="true"],
1411
+ .ui-date-input.rt-Button[aria-invalid="true"] { box-shadow: inset 0 0 0 1px var(--red-8); }