@crewlethq/ui 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (497) hide show
  1. package/README.md +1714 -14
  2. package/dist/Accordion/Accordion.d.ts +54 -0
  3. package/dist/Accordion/index.d.ts +4 -0
  4. package/dist/Accordion/index.js +6 -0
  5. package/dist/Accordion-ZI2WLD5C.css +87 -0
  6. package/dist/AddPill/AddPill.d.ts +114 -0
  7. package/dist/AddPill/index.d.ts +3 -0
  8. package/dist/AddPill/index.js +3 -0
  9. package/dist/AddPill-DFWXYLIQ.css +434 -0
  10. package/dist/Announcer/Announcer.d.ts +15 -0
  11. package/dist/Announcer/index.d.ts +2 -0
  12. package/dist/Announcer/index.js +3 -0
  13. package/dist/AppShell/AppShell.d.ts +193 -0
  14. package/dist/AppShell/index.d.ts +3 -0
  15. package/dist/AppShell/index.js +6 -0
  16. package/dist/AppShell-NVE6LHNI.css +395 -0
  17. package/dist/Avatar/Avatar.d.ts +104 -0
  18. package/dist/Avatar/index.d.ts +3 -0
  19. package/dist/Avatar/index.js +2 -0
  20. package/dist/Avatar-P2KRQM2B.css +156 -0
  21. package/dist/BrandLockup/BrandLockup.d.ts +41 -0
  22. package/dist/BrandLockup/index.d.ts +3 -0
  23. package/dist/BrandLockup/index.js +2 -0
  24. package/dist/BrandLockup-6ISDEHPJ.css +108 -0
  25. package/dist/Button/Button.d.ts +88 -0
  26. package/dist/Button/index.d.ts +3 -0
  27. package/dist/Button/index.js +3 -0
  28. package/dist/Button-D4J6B4MA.css +302 -0
  29. package/dist/CalendarGrid/CalendarGrid.d.ts +87 -0
  30. package/dist/CalendarGrid/index.d.ts +3 -0
  31. package/dist/CalendarGrid/index.js +2 -0
  32. package/dist/CalendarGrid-V6TQ5QKS.css +128 -0
  33. package/dist/Callout/Callout.d.ts +47 -0
  34. package/dist/Callout/index.d.ts +3 -0
  35. package/dist/Callout/index.js +2 -0
  36. package/dist/Callout-S7QDWHDL.css +111 -0
  37. package/dist/Canvas/Canvas.d.ts +234 -0
  38. package/dist/Canvas/geometry.d.ts +249 -0
  39. package/dist/Canvas/index.d.ts +5 -0
  40. package/dist/Canvas/index.js +8 -0
  41. package/dist/Canvas/layerNode.d.ts +20 -0
  42. package/dist/Canvas-Q6JETCWR.css +315 -0
  43. package/dist/Card/Card.d.ts +142 -0
  44. package/dist/Card/headerSlot.d.ts +65 -0
  45. package/dist/Card/index.d.ts +5 -0
  46. package/dist/Card/index.js +6 -0
  47. package/dist/Card-AHX3Q2JD.css +428 -0
  48. package/dist/Charts/ActivityStrip.d.ts +45 -0
  49. package/dist/Charts/BarList.d.ts +51 -0
  50. package/dist/Charts/Legend.d.ts +32 -0
  51. package/dist/Charts/StackedBar.d.ts +38 -0
  52. package/dist/Charts/TimeSeries.d.ts +92 -0
  53. package/dist/Charts/dataColor.d.ts +20 -0
  54. package/dist/Charts/index.d.ts +12 -0
  55. package/dist/Charts/index.js +3 -0
  56. package/dist/Charts-D7G2BSXH.css +277 -0
  57. package/dist/Checkbox/Checkbox.d.ts +45 -0
  58. package/dist/Checkbox/index.d.ts +3 -0
  59. package/dist/Checkbox/index.js +2 -0
  60. package/dist/Checkbox-VGW26YLQ.css +111 -0
  61. package/dist/CodeBlock/CodeBlock.d.ts +60 -0
  62. package/dist/CodeBlock/index.d.ts +3 -0
  63. package/dist/CodeBlock/index.js +7 -0
  64. package/dist/CodeBlock-U2W6NNVC.css +153 -0
  65. package/dist/Combobox/Combobox.d.ts +89 -0
  66. package/dist/Combobox/index.d.ts +3 -0
  67. package/dist/Combobox/index.js +8 -0
  68. package/dist/Combobox-4FUVYIE7.css +80 -0
  69. package/dist/CommandPalette/CommandPalette.d.ts +77 -0
  70. package/dist/CommandPalette/index.d.ts +3 -0
  71. package/dist/CommandPalette/index.js +11 -0
  72. package/dist/CommandPalette-CSJDUCQA.css +115 -0
  73. package/dist/Container/Container.d.ts +17 -0
  74. package/dist/Container/index.d.ts +3 -0
  75. package/dist/Container/index.js +2 -0
  76. package/dist/Container-3TSKMGNI.css +52 -0
  77. package/dist/Copyable/CopyButton.d.ts +54 -0
  78. package/dist/Copyable/Copyable.d.ts +34 -0
  79. package/dist/Copyable/index.d.ts +5 -0
  80. package/dist/Copyable/index.js +6 -0
  81. package/dist/Copyable-5PNRFOLS.css +125 -0
  82. package/dist/Count/Count.d.ts +24 -0
  83. package/dist/Count/index.d.ts +3 -0
  84. package/dist/Count/index.js +3 -0
  85. package/dist/Count-ZVCJ6VPD.css +20 -0
  86. package/dist/DataTable/CopyableCell.d.ts +12 -0
  87. package/dist/DataTable/DataTable.d.ts +615 -0
  88. package/dist/DataTable/RowActionsMenu.d.ts +7 -0
  89. package/dist/DataTable/index.d.ts +7 -0
  90. package/dist/DataTable/index.js +14 -0
  91. package/dist/DataTable-ITNACQ2X.css +2020 -0
  92. package/dist/DataView/DataView.d.ts +109 -0
  93. package/dist/DataView/DataViewToolbar.d.ts +87 -0
  94. package/dist/DataView/FilterAxisBar.d.ts +103 -0
  95. package/dist/DataView/columns.d.ts +35 -0
  96. package/dist/DataView/filters.d.ts +184 -0
  97. package/dist/DataView/index.d.ts +11 -0
  98. package/dist/DataView/index.js +25 -0
  99. package/dist/DataView-256YF32J.css +441 -0
  100. package/dist/DateTimePicker/DateTimePicker.d.ts +91 -0
  101. package/dist/DateTimePicker/index.d.ts +3 -0
  102. package/dist/DateTimePicker/index.js +9 -0
  103. package/dist/DateTimePicker-22VNXRWC.css +199 -0
  104. package/dist/DescriptionList/DescriptionList.d.ts +36 -0
  105. package/dist/DescriptionList/index.d.ts +3 -0
  106. package/dist/DescriptionList/index.js +2 -0
  107. package/dist/DescriptionList-YYY3V3O6.css +59 -0
  108. package/dist/DiffList/DiffList.d.ts +47 -0
  109. package/dist/DiffList/index.d.ts +3 -0
  110. package/dist/DiffList/index.js +3 -0
  111. package/dist/DiffList-3EX64AAE.css +94 -0
  112. package/dist/Disclosure/Disclosure.d.ts +56 -0
  113. package/dist/Disclosure/anatomy.d.ts +43 -0
  114. package/dist/Disclosure/index.d.ts +5 -0
  115. package/dist/Disclosure/index.js +6 -0
  116. package/dist/Disclosure-VKBJJIZ7.css +176 -0
  117. package/dist/EmptyState/EmptyState.d.ts +39 -0
  118. package/dist/EmptyState/index.d.ts +3 -0
  119. package/dist/EmptyState/index.js +3 -0
  120. package/dist/EmptyState-C6HRBGT7.css +73 -0
  121. package/dist/EmptyValue/EmptyValue.d.ts +31 -0
  122. package/dist/EmptyValue/index.d.ts +3 -0
  123. package/dist/EmptyValue/index.js +3 -0
  124. package/dist/EmptyValue-4B6ODXHT.css +12 -0
  125. package/dist/EntityChip/EntityChip.d.ts +40 -0
  126. package/dist/EntityChip/index.d.ts +3 -0
  127. package/dist/EntityChip/index.js +3 -0
  128. package/dist/EntityChip-LUCPZBBG.css +64 -0
  129. package/dist/ErrorBoundary/ErrorBoundary.d.ts +58 -0
  130. package/dist/ErrorBoundary/index.d.ts +3 -0
  131. package/dist/ErrorBoundary/index.js +4 -0
  132. package/dist/ErrorBoundary-ME36CQTA.css +59 -0
  133. package/dist/Eyebrow/Eyebrow.d.ts +18 -0
  134. package/dist/Eyebrow/index.d.ts +3 -0
  135. package/dist/Eyebrow/index.js +2 -0
  136. package/dist/Eyebrow-5NREGHQH.css +46 -0
  137. package/dist/FilterChip/FilterChip.d.ts +68 -0
  138. package/dist/FilterChip/index.d.ts +3 -0
  139. package/dist/FilterChip/index.js +3 -0
  140. package/dist/FilterChip-GTGLLOXE.css +107 -0
  141. package/dist/Fullscreen/index.d.ts +2 -0
  142. package/dist/Fullscreen/index.js +1 -0
  143. package/dist/Fullscreen/useFullscreen.d.ts +32 -0
  144. package/dist/IconButton/IconButton.d.ts +45 -0
  145. package/dist/IconButton/index.d.ts +3 -0
  146. package/dist/IconButton/index.js +3 -0
  147. package/dist/IconButton-VQGNMJDI.css +158 -0
  148. package/dist/ImageUpload/ImageUpload.d.ts +37 -0
  149. package/dist/ImageUpload/index.d.ts +3 -0
  150. package/dist/ImageUpload/index.js +3 -0
  151. package/dist/ImageUpload-HKFIZR6D.css +193 -0
  152. package/dist/InlineCode/InlineCode.d.ts +37 -0
  153. package/dist/InlineCode/index.d.ts +3 -0
  154. package/dist/InlineCode/index.js +2 -0
  155. package/dist/InlineCode-6WSR5COL.css +65 -0
  156. package/dist/Input/FormField.d.ts +61 -0
  157. package/dist/Input/FormRow.d.ts +6 -0
  158. package/dist/Input/FormSection.d.ts +28 -0
  159. package/dist/Input/Input.d.ts +98 -0
  160. package/dist/Input/Label.d.ts +31 -0
  161. package/dist/Input/ReadOnlyField.d.ts +30 -0
  162. package/dist/Input/Textarea.d.ts +16 -0
  163. package/dist/Input/index.d.ts +15 -0
  164. package/dist/Input/index.js +5 -0
  165. package/dist/Input-2PU5CPKK.css +616 -0
  166. package/dist/Kbd/Kbd.d.ts +40 -0
  167. package/dist/Kbd/index.d.ts +3 -0
  168. package/dist/Kbd/index.js +3 -0
  169. package/dist/Kbd-W66MXQI5.css +61 -0
  170. package/dist/Layer/LayerHost.d.ts +23 -0
  171. package/dist/Layer/index.d.ts +7 -0
  172. package/dist/Layer/index.js +3 -0
  173. package/dist/Layer/place.d.ts +63 -0
  174. package/dist/Layer/stack.d.ts +159 -0
  175. package/dist/Layer-NAFSGCFA.css +23 -0
  176. package/dist/Layout/Layout.d.ts +104 -0
  177. package/dist/Layout/index.d.ts +3 -0
  178. package/dist/Layout/index.js +2 -0
  179. package/dist/Layout-2ZCV3IGF.css +171 -0
  180. package/dist/Link/Link.d.ts +45 -0
  181. package/dist/Link/index.d.ts +3 -0
  182. package/dist/Link/index.js +3 -0
  183. package/dist/Link-6BEFNMN2.css +80 -0
  184. package/dist/List/List.d.ts +73 -0
  185. package/dist/List/index.d.ts +3 -0
  186. package/dist/List/index.js +3 -0
  187. package/dist/List-XTHESXLR.css +161 -0
  188. package/dist/ListInput/ListInput.d.ts +68 -0
  189. package/dist/ListInput/index.d.ts +3 -0
  190. package/dist/ListInput/index.js +10 -0
  191. package/dist/ListInput-O7LJKOIG.css +147 -0
  192. package/dist/Listbox/index.d.ts +5 -0
  193. package/dist/Listbox/index.js +2 -0
  194. package/dist/Listbox/useListbox.d.ts +97 -0
  195. package/dist/Listbox/useOptionKeys.d.ts +64 -0
  196. package/dist/Listbox-X2DOTSQA.css +110 -0
  197. package/dist/Menu/Menu.d.ts +118 -0
  198. package/dist/Menu/index.d.ts +3 -0
  199. package/dist/Menu/index.js +7 -0
  200. package/dist/Menu-6DE7I66I.css +222 -0
  201. package/dist/Meter/Meter.d.ts +49 -0
  202. package/dist/Meter/index.d.ts +3 -0
  203. package/dist/Meter/index.js +3 -0
  204. package/dist/Meter-SKOOXQBC.css +87 -0
  205. package/dist/Modal/ConfirmModal.d.ts +74 -0
  206. package/dist/Modal/Modal.d.ts +154 -0
  207. package/dist/Modal/index.d.ts +5 -0
  208. package/dist/Modal/index.js +8 -0
  209. package/dist/Modal-XYQJ4BL6.css +484 -0
  210. package/dist/NewItemsNotice/NewItemsNotice.d.ts +28 -0
  211. package/dist/NewItemsNotice/index.d.ts +3 -0
  212. package/dist/NewItemsNotice/index.js +4 -0
  213. package/dist/NewItemsNotice-T4DSSPVV.css +60 -0
  214. package/dist/OrgLabel/OrgLabel.d.ts +117 -0
  215. package/dist/OrgLabel/index.d.ts +3 -0
  216. package/dist/OrgLabel/index.js +2 -0
  217. package/dist/OrgLabel-D7U6QJZD.css +293 -0
  218. package/dist/OrgNode/OrgNode.d.ts +103 -0
  219. package/dist/OrgNode/index.d.ts +3 -0
  220. package/dist/OrgNode/index.js +3 -0
  221. package/dist/OrgNode-BT7T2Q2X.css +214 -0
  222. package/dist/OrgTable/OrgTable.d.ts +113 -0
  223. package/dist/OrgTable/index.d.ts +3 -0
  224. package/dist/OrgTable/index.js +11 -0
  225. package/dist/OrgTable-VWMFC3TB.css +360 -0
  226. package/dist/PageHeader/PageHeader.d.ts +35 -0
  227. package/dist/PageHeader/index.d.ts +3 -0
  228. package/dist/PageHeader/index.js +3 -0
  229. package/dist/PageHeader-6EYWQXRE.css +88 -0
  230. package/dist/Popover/Popover.d.ts +91 -0
  231. package/dist/Popover/index.d.ts +3 -0
  232. package/dist/Popover/index.js +4 -0
  233. package/dist/Popover-WJGCF3ZQ.css +185 -0
  234. package/dist/PricingCard/PricingCard.d.ts +56 -0
  235. package/dist/PricingCard/index.d.ts +3 -0
  236. package/dist/PricingCard/index.js +4 -0
  237. package/dist/PricingCard-JFI7RYXP.css +278 -0
  238. package/dist/Prose/Prose.d.ts +33 -0
  239. package/dist/Prose/index.d.ts +3 -0
  240. package/dist/Prose/index.js +2 -0
  241. package/dist/Prose-BTXNFT2Q.css +99 -0
  242. package/dist/RelativeTime/RelativeTime.d.ts +31 -0
  243. package/dist/RelativeTime/clock.d.ts +9 -0
  244. package/dist/RelativeTime/format.d.ts +38 -0
  245. package/dist/RelativeTime/index.d.ts +6 -0
  246. package/dist/RelativeTime/index.js +4 -0
  247. package/dist/RelativeTime-EBAQPGO2.css +10 -0
  248. package/dist/SearchTrigger/SearchTrigger.d.ts +29 -0
  249. package/dist/SearchTrigger/index.d.ts +3 -0
  250. package/dist/SearchTrigger/index.js +2 -0
  251. package/dist/SearchTrigger-QXOYAUUY.css +79 -0
  252. package/dist/Section/Section.d.ts +41 -0
  253. package/dist/Section/index.d.ts +3 -0
  254. package/dist/Section/index.js +3 -0
  255. package/dist/Section-QRUPRIQ2.css +127 -0
  256. package/dist/SegmentedControl/SegmentedControl.d.ts +68 -0
  257. package/dist/SegmentedControl/index.d.ts +4 -0
  258. package/dist/SegmentedControl/index.js +5 -0
  259. package/dist/SegmentedControl-X3BI3XU4.css +68 -0
  260. package/dist/Select/Select.d.ts +138 -0
  261. package/dist/Select/index.d.ts +3 -0
  262. package/dist/Select/index.js +5 -0
  263. package/dist/Select-2X77FSWR.css +350 -0
  264. package/dist/Shortcut/index.d.ts +2 -0
  265. package/dist/Shortcut/index.js +4 -0
  266. package/dist/Shortcut/useShortcut.d.ts +68 -0
  267. package/dist/SidebarNav/SidebarNav.d.ts +117 -0
  268. package/dist/SidebarNav/index.d.ts +3 -0
  269. package/dist/SidebarNav/index.js +3 -0
  270. package/dist/SidebarNav-QGSFKZYA.css +319 -0
  271. package/dist/Skeleton/Skeleton.d.ts +50 -0
  272. package/dist/Skeleton/index.d.ts +3 -0
  273. package/dist/Skeleton/index.js +3 -0
  274. package/dist/Skeleton-V735HRGM.css +421 -0
  275. package/dist/StatCard/StatCard.d.ts +56 -0
  276. package/dist/StatCard/index.d.ts +3 -0
  277. package/dist/StatCard/index.js +3 -0
  278. package/dist/StatCard-KYPKZUWX.css +111 -0
  279. package/dist/StatGroup/StatGroup.d.ts +20 -0
  280. package/dist/StatGroup/index.d.ts +3 -0
  281. package/dist/StatGroup/index.js +2 -0
  282. package/dist/StatGroup-TGB6AEKM.css +80 -0
  283. package/dist/StatusDot/StatusDot.d.ts +25 -0
  284. package/dist/StatusDot/index.d.ts +3 -0
  285. package/dist/StatusDot/index.js +2 -0
  286. package/dist/StatusDot-HA2L2FSX.css +84 -0
  287. package/dist/Switch/Switch.d.ts +38 -0
  288. package/dist/Switch/index.d.ts +3 -0
  289. package/dist/Switch/index.js +2 -0
  290. package/dist/Switch-U4OWK4CL.css +169 -0
  291. package/dist/Table/Table.d.ts +51 -0
  292. package/dist/Table/index.d.ts +3 -0
  293. package/dist/Table/index.js +3 -0
  294. package/dist/Table-MDOLVUAW.css +159 -0
  295. package/dist/Tabs/Tabs.d.ts +97 -0
  296. package/dist/Tabs/index.d.ts +3 -0
  297. package/dist/Tabs/index.js +4 -0
  298. package/dist/Tabs/roving.d.ts +36 -0
  299. package/dist/Tabs-VLICJFVB.css +275 -0
  300. package/dist/Tag/Tag.d.ts +107 -0
  301. package/dist/Tag/index.d.ts +3 -0
  302. package/dist/Tag/index.js +3 -0
  303. package/dist/Tag-VNZEYLB6.css +406 -0
  304. package/dist/TagGroup/TagGroup.d.ts +41 -0
  305. package/dist/TagGroup/index.d.ts +3 -0
  306. package/dist/TagGroup/index.js +4 -0
  307. package/dist/TagGroup-APC2EFH4.css +75 -0
  308. package/dist/TagsInput/TagsInput.d.ts +112 -0
  309. package/dist/TagsInput/index.d.ts +3 -0
  310. package/dist/TagsInput/index.js +10 -0
  311. package/dist/TagsInput-W4P36PRJ.css +168 -0
  312. package/dist/Text/Text.d.ts +67 -0
  313. package/dist/Text/index.d.ts +3 -0
  314. package/dist/Text/index.js +2 -0
  315. package/dist/Text-XIPYYZX2.css +154 -0
  316. package/dist/ThemeSwitcher/ThemeSwitcher.d.ts +47 -0
  317. package/dist/ThemeSwitcher/index.d.ts +4 -0
  318. package/dist/ThemeSwitcher/index.js +6 -0
  319. package/dist/ThemeSwitcher/preferences.d.ts +51 -0
  320. package/dist/TimeWindowPicker/TimeWindowPicker.d.ts +231 -0
  321. package/dist/TimeWindowPicker/index.d.ts +3 -0
  322. package/dist/TimeWindowPicker/index.js +13 -0
  323. package/dist/TimeWindowPicker/mask.d.ts +82 -0
  324. package/dist/TimeWindowPicker-7I7KWCMU.css +403 -0
  325. package/dist/Timeline/Timeline.d.ts +51 -0
  326. package/dist/Timeline/index.d.ts +3 -0
  327. package/dist/Timeline/index.js +3 -0
  328. package/dist/Timeline-27SYKOFX.css +144 -0
  329. package/dist/Toaster/Toaster.d.ts +108 -0
  330. package/dist/Toaster/index.d.ts +3 -0
  331. package/dist/Toaster/index.js +5 -0
  332. package/dist/Toaster-NVDCEIP5.css +306 -0
  333. package/dist/Toolbar/Toolbar.d.ts +62 -0
  334. package/dist/Toolbar/index.d.ts +3 -0
  335. package/dist/Toolbar/index.js +4 -0
  336. package/dist/Toolbar-IP6LXN45.css +48 -0
  337. package/dist/Tooltip/Tooltip.d.ts +51 -0
  338. package/dist/Tooltip/index.d.ts +3 -0
  339. package/dist/Tooltip/index.js +4 -0
  340. package/dist/Tooltip-LKQF7CE4.css +71 -0
  341. package/dist/Tree/index.d.ts +8 -0
  342. package/dist/Tree/index.js +1 -0
  343. package/dist/Tree/layout.d.ts +160 -0
  344. package/dist/Tree/model.d.ts +110 -0
  345. package/dist/Tree/useMeasuredSizes.d.ts +61 -0
  346. package/dist/Tree/useTreeState.d.ts +89 -0
  347. package/dist/TreeCanvas/TreeCanvas.d.ts +384 -0
  348. package/dist/TreeCanvas/index.d.ts +3 -0
  349. package/dist/TreeCanvas/index.js +10 -0
  350. package/dist/TreeCanvas/motion.d.ts +59 -0
  351. package/dist/TreeCanvas-WBNQPHC7.css +1098 -0
  352. package/dist/TreeGrid/TreeGrid.d.ts +142 -0
  353. package/dist/TreeGrid/index.d.ts +3 -0
  354. package/dist/TreeGrid/index.js +8 -0
  355. package/dist/TreeGrid-NSW7VMOX.css +132 -0
  356. package/dist/VisuallyHidden/VisuallyHidden.d.ts +23 -0
  357. package/dist/VisuallyHidden/index.d.ts +3 -0
  358. package/dist/VisuallyHidden/index.js +2 -0
  359. package/dist/VisuallyHidden-L552H7OA.css +21 -0
  360. package/dist/chunk-22O7LAW2.js +41 -0
  361. package/dist/chunk-23DHIMJA.js +38 -0
  362. package/dist/chunk-2EOKFKHX.js +263 -0
  363. package/dist/chunk-2PRH365R.js +74 -0
  364. package/dist/chunk-2ZQMA2WB.js +57 -0
  365. package/dist/chunk-3CZ7XAVY.js +139 -0
  366. package/dist/chunk-3EYF6HKB.js +135 -0
  367. package/dist/chunk-3ZP55QZE.js +40 -0
  368. package/dist/chunk-53DVJCVW.js +14 -0
  369. package/dist/chunk-5C5YMZQU.js +51 -0
  370. package/dist/chunk-5EKIWVOR.js +132 -0
  371. package/dist/chunk-5IMACPJS.js +495 -0
  372. package/dist/chunk-5KPQ6D7N.js +54 -0
  373. package/dist/chunk-5SDBMKUO.js +297 -0
  374. package/dist/chunk-5WS6L6FA.js +114 -0
  375. package/dist/chunk-7EM5T4ME.js +39 -0
  376. package/dist/chunk-7FZ53WDJ.js +163 -0
  377. package/dist/chunk-7HPRF5XN.js +525 -0
  378. package/dist/chunk-7RPGY3JE.js +43 -0
  379. package/dist/chunk-A2UXBCLO.js +48 -0
  380. package/dist/chunk-ARMRX2YV.js +96 -0
  381. package/dist/chunk-AV2DXAEL.js +27 -0
  382. package/dist/chunk-BHHIIK3M.js +17 -0
  383. package/dist/chunk-BZFWDIV6.js +9 -0
  384. package/dist/chunk-BZYDZBAN.js +123 -0
  385. package/dist/chunk-CMEE37QJ.js +628 -0
  386. package/dist/chunk-D3OADIM6.js +112 -0
  387. package/dist/chunk-DD5BBGBE.js +162 -0
  388. package/dist/chunk-EHMQQHYR.js +1652 -0
  389. package/dist/chunk-EN6K2IFA.js +256 -0
  390. package/dist/chunk-EPOOQZYA.js +118 -0
  391. package/dist/chunk-ESCO4XYW.js +144 -0
  392. package/dist/chunk-EUCC37WY.js +14 -0
  393. package/dist/chunk-EV6IMYJ6.js +62 -0
  394. package/dist/chunk-F27EPQ7D.js +68 -0
  395. package/dist/chunk-F4PJZ4ED.js +245 -0
  396. package/dist/chunk-F6OE5FH3.js +49 -0
  397. package/dist/chunk-FBZAKNSX.js +263 -0
  398. package/dist/chunk-FEFTGVMF.js +46 -0
  399. package/dist/chunk-G2QFRTJ2.js +823 -0
  400. package/dist/chunk-GHYY2WPF.js +907 -0
  401. package/dist/chunk-GTOUGQQK.js +147 -0
  402. package/dist/chunk-GUIF6Q6N.js +143 -0
  403. package/dist/chunk-GXQ3B46I.js +216 -0
  404. package/dist/chunk-H4FBTAYS.js +130 -0
  405. package/dist/chunk-HOXGBLEY.js +37 -0
  406. package/dist/chunk-HQNHV7D6.js +54 -0
  407. package/dist/chunk-HTDFCRJZ.js +92 -0
  408. package/dist/chunk-HZ5XZNPS.js +98 -0
  409. package/dist/chunk-IAJLHVUA.js +28 -0
  410. package/dist/chunk-IJ7QXNIJ.js +1 -0
  411. package/dist/chunk-ITHXJHBB.js +280 -0
  412. package/dist/chunk-JCSA3XVH.js +32 -0
  413. package/dist/chunk-KLJCCMF3.js +97 -0
  414. package/dist/chunk-LGCPQIOZ.js +49 -0
  415. package/dist/chunk-LWKJQTOM.js +77 -0
  416. package/dist/chunk-MNAXYY3R.js +215 -0
  417. package/dist/chunk-NN62JQLR.js +29 -0
  418. package/dist/chunk-NPZY6YYL.js +251 -0
  419. package/dist/chunk-NTRZGNEX.js +529 -0
  420. package/dist/chunk-O6232G37.js +273 -0
  421. package/dist/chunk-O67VF5MS.js +58 -0
  422. package/dist/chunk-ODEQTPFM.js +6 -0
  423. package/dist/chunk-PNFASD6F.js +98 -0
  424. package/dist/chunk-PQADV6P6.js +19 -0
  425. package/dist/chunk-PZSWF74H.js +15 -0
  426. package/dist/chunk-Q4ZPPART.js +26 -0
  427. package/dist/chunk-QNCVHRZL.js +17 -0
  428. package/dist/chunk-QVE4GJAT.js +15 -0
  429. package/dist/chunk-QYOFACSP.js +36 -0
  430. package/dist/chunk-RA2ULG6H.js +29 -0
  431. package/dist/chunk-RDGD7Z7I.js +350 -0
  432. package/dist/chunk-RK4XPHVG.js +16 -0
  433. package/dist/chunk-RSAQOKH3.js +38 -0
  434. package/dist/chunk-S2XHHEW4.js +84 -0
  435. package/dist/chunk-S4GZWSKR.js +137 -0
  436. package/dist/chunk-SFZOKW2G.js +52 -0
  437. package/dist/chunk-T7FKOJKW.js +221 -0
  438. package/dist/chunk-UG46QBLT.js +325 -0
  439. package/dist/chunk-UOGSZKLT.js +134 -0
  440. package/dist/chunk-V2XMNLMS.js +52 -0
  441. package/dist/chunk-V663QU4R.js +51 -0
  442. package/dist/chunk-W4ENKCXJ.js +40 -0
  443. package/dist/chunk-W5J7R5EB.js +107 -0
  444. package/dist/chunk-WNI2WSJF.js +27 -0
  445. package/dist/chunk-XDTYBF2F.js +36 -0
  446. package/dist/chunk-XN4JBAN3.js +32 -0
  447. package/dist/chunk-XV6WRMBC.js +211 -0
  448. package/dist/chunk-YLYOWZ4V.js +33 -0
  449. package/dist/chunk-YMWONFSI.js +170 -0
  450. package/dist/chunk-ZCR6YGQ4.js +1 -0
  451. package/dist/generated/index.d.ts +83 -0
  452. package/dist/generated/index.js +91 -0
  453. package/dist/index.d.ts +1 -1217
  454. package/dist/index.js +91 -4518
  455. package/dist/styles.css +14841 -4274
  456. package/dist/utils/cx.d.ts +10 -0
  457. package/dist/utils/headingLevel.d.ts +16 -0
  458. package/dist/utils/index.d.ts +6 -0
  459. package/dist/utils/index.js +4 -0
  460. package/dist/utils/tone.d.ts +25 -0
  461. package/dist/utils/useClipboard.d.ts +30 -0
  462. package/package.json +18 -10
  463. package/scripts/bundle-css.mjs +25 -0
  464. package/scripts/check-css-literals.mjs +166 -0
  465. package/scripts/check-css-variables.mjs +184 -0
  466. package/scripts/check-css.mjs +27 -0
  467. package/scripts/css-source.mjs +67 -0
  468. package/scripts/write-barrel.mjs +60 -0
  469. package/dist/Accordion-NIMJQIOI.css +0 -88
  470. package/dist/AppShell-ZW3NSFBP.css +0 -51
  471. package/dist/Avatar-V6NG6Q45.css +0 -67
  472. package/dist/Button-XGCTXXYP.css +0 -174
  473. package/dist/Callout-LEGDIMAM.css +0 -52
  474. package/dist/Card-BOZGBML7.css +0 -86
  475. package/dist/Checkbox-OCUICIIZ.css +0 -58
  476. package/dist/CodeBlock-IEMBNIQC.css +0 -90
  477. package/dist/Container-LTKBA2FW.css +0 -21
  478. package/dist/Copyable-IB57OTHZ.css +0 -123
  479. package/dist/DataTable-3GALZUW2.css +0 -1593
  480. package/dist/DateTimePicker-NMSSGVPK.css +0 -312
  481. package/dist/Eyebrow-AVBORAS2.css +0 -30
  482. package/dist/IconButton-GB4PJDG2.css +0 -82
  483. package/dist/ImageUpload-3HQDF2KC.css +0 -158
  484. package/dist/Input-ZHUTN7CU.css +0 -210
  485. package/dist/Kbd-Q77CDZY7.css +0 -23
  486. package/dist/Modal-FJVG66S4.css +0 -138
  487. package/dist/Popover-FUFULUE2.css +0 -123
  488. package/dist/PricingCard-NKYV3JHA.css +0 -238
  489. package/dist/Section-665ZIPG6.css +0 -20
  490. package/dist/Select-GPRF7PRB.css +0 -294
  491. package/dist/Skeleton-3WEFLRDN.css +0 -378
  492. package/dist/StatCard-RTJIVTRB.css +0 -50
  493. package/dist/Table-AR3TRY2E.css +0 -89
  494. package/dist/Tabs-XZ4JIH3E.css +0 -153
  495. package/dist/Tag-R5QDJLYJ.css +0 -163
  496. package/dist/TimeWindowPicker-L3G5Q7UT.css +0 -629
  497. package/dist/Toaster-2O65VOR4.css +0 -264
@@ -0,0 +1,2020 @@
1
+ /* ─────────────────────────────────────────────────────────────────
2
+ * Default variant.
3
+ *
4
+ * Every rule is scoped under the variant root, so the table's
5
+ * internals never match an application's own class names and the
6
+ * compact variant's rules further down never leak into this one.
7
+ * ───────────────────────────────────────────────────────────────── */
8
+ .crewlet-data-table--default {
9
+ /*
10
+ * The two knobs the compact root declares, so a host that rebinds either one
11
+ * reaches both variants. The hover is the OVERLAY step rather than an opaque
12
+ * surface: a table sits on the page, on a card and inside a dialog, and only
13
+ * an overlay composites correctly onto all three.
14
+ */
15
+ --crewlet-data-table-row-hover-bg: var(--color-surface-hover);
16
+ --crewlet-data-table-active-sort-color: var(--color-brand-accent-ink);
17
+ width: 100%;
18
+ position: relative;
19
+ overflow-x: auto;
20
+ /* The gesture stops at the table's own edge. Without it a trackpad swipe
21
+ that runs out of table carries on into the browser's back navigation, so
22
+ one column too far left loses the page. */
23
+ overscroll-behavior-x: contain;
24
+ }
25
+
26
+ .crewlet-data-table--default .crewlet-data-table__table {
27
+ width: 100%;
28
+ border-collapse: collapse;
29
+ background: transparent;
30
+ display: table;
31
+ table-layout: auto;
32
+ /* The table register: a cell is scanned down a column rather than read as a
33
+ sentence, and the compact step is where a row of them still lines up with
34
+ the row token the cells are sized to. */
35
+ font-size: var(--font-size-compact);
36
+ }
37
+
38
+ /*
39
+ * THE RULE UNDER THE HEADER IS THE HEADER'S. It used to sit on `thead`, which
40
+ * a sticky header carries nowhere: the group does not stick, its cells do, so
41
+ * the line stayed at the top of the table and the column names scrolled over
42
+ * the rows with nothing under them.
43
+ */
44
+ .crewlet-data-table--default .crewlet-data-table__table thead {
45
+ display: table-header-group;
46
+ }
47
+
48
+ .crewlet-data-table--default .crewlet-data-table__table tbody {
49
+ display: table-row-group;
50
+ }
51
+
52
+ .crewlet-data-table--default .crewlet-data-table__table tr {
53
+ display: table-row;
54
+ }
55
+
56
+ /*
57
+ * THE HEADER IS A MICRO-LABEL, on no ground of its own.
58
+ *
59
+ * A column name is read once, at a glance, to find the column; at the body
60
+ * step in the row's own ink it competed with the values beneath it. The
61
+ * uppercase 11px step at the tertiary ink is the register every micro-label
62
+ * in the system takes, measured on the surface it is painted on. What it is
63
+ * NOT is a filled band: see the compact variant's own header rule, and
64
+ * `maxBodyHeight` for the table that wants one pinned over scrolling rows.
65
+ *
66
+ * Header cells also hold the absolutely positioned resize handle, so the cell
67
+ * is the handle's containing block.
68
+ */
69
+ .crewlet-data-table--default .crewlet-data-table__table th {
70
+ position: relative;
71
+ padding: var(--spacing-2) var(--spacing-3);
72
+ text-align: left;
73
+ font-size: var(--font-size-2xs);
74
+ font-weight: var(--font-weight-medium);
75
+ color: var(--color-text-tertiary);
76
+ text-transform: uppercase;
77
+ letter-spacing: var(--font-letter-spacing-wide);
78
+ border-bottom: 1px solid var(--color-border-default);
79
+ user-select: none;
80
+ display: table-cell;
81
+ white-space: nowrap;
82
+ }
83
+
84
+ .crewlet-data-table--default .crewlet-data-table__table td {
85
+ padding: var(--spacing-2) var(--spacing-3);
86
+ color: var(--color-text-primary);
87
+ border-bottom: 1px solid var(--color-border-default);
88
+ display: table-cell;
89
+ text-align: left;
90
+ vertical-align: middle;
91
+ /* The row token, so a table lines up with every other list in a product and
92
+ a cell holding one word is as tall as a cell holding an avatar. */
93
+ height: var(--size-row-md);
94
+ white-space: nowrap;
95
+ }
96
+
97
+ /* The hairline between one column and the next, on the header row only, for
98
+ the reason the compact variant's own rule gives. This variant draws no
99
+ chrome columns, so it needs none of that rule's exclusions. */
100
+ .crewlet-data-table--default .crewlet-data-table__table thead th:not(:last-child)::after {
101
+ content: '';
102
+ position: absolute;
103
+ top: calc((var(--spacing-1) + var(--spacing-2)) / 2);
104
+ bottom: calc((var(--spacing-1) + var(--spacing-2)) / 2);
105
+ right: 0;
106
+ width: 1px;
107
+ background: var(--color-border-default);
108
+ pointer-events: none;
109
+ }
110
+
111
+
112
+ /*
113
+ * A ROW IS NOT A SURFACE. Rows used to paint the panel colour and hover to the
114
+ * next opaque step, so a table on any other ground drew a block of the wrong
115
+ * grey, and a hovered row changed the table's ground rather than lighting one
116
+ * row of it. The row is transparent and the hover is the OVERLAY, which
117
+ * composites onto whatever the table is standing on.
118
+ */
119
+ .crewlet-data-table--default .crewlet-data-table__table tbody tr {
120
+ transition: background-color var(--motion-duration-fast) var(--motion-easing-default);
121
+ }
122
+
123
+ /*
124
+ * AND EVERY ROW LIGHTS UP UNDER THE POINTER, for the reason the compact
125
+ * variant's own rule gives: the tint is row tracking, and the cursor is what
126
+ * says a row can be pressed.
127
+ */
128
+ .crewlet-data-table--default .crewlet-data-table__table tbody tr:hover {
129
+ background: var(--crewlet-data-table-row-hover-bg);
130
+ }
131
+
132
+ .crewlet-data-table--default .crewlet-data-table__empty {
133
+ color: var(--color-text-tertiary);
134
+ font-size: var(--font-size-compact);
135
+ text-align: center;
136
+ padding: var(--spacing-8) var(--spacing-5);
137
+ }
138
+
139
+ /* Resizable columns.
140
+
141
+ 24px WIDE, INSIDE THE CELL. It was 8px, which is a third of the smallest
142
+ target WCAG 2.2 accepts and not a thing a tremor can hold; and it stays
143
+ inside the cell rather than straddling the boundary because the header
144
+ clips its overflow, so the half that hung over the next column was never
145
+ there to press. */
146
+ .crewlet-data-table--default .crewlet-data-table__column-resizer {
147
+ position: absolute;
148
+ right: 0;
149
+ top: 0;
150
+ bottom: 0;
151
+ width: 24px;
152
+ cursor: col-resize;
153
+ user-select: none;
154
+ z-index: var(--z-index-raised);
155
+ }
156
+
157
+ .crewlet-data-table--default .crewlet-data-table__column-resizer:hover {
158
+ background: var(--color-brand-accent-soft-strong);
159
+ }
160
+
161
+ /* A control with no ring is a control a keyboard reader lands on and cannot
162
+ find: this one paints nothing until it is hovered, so focus had no visible
163
+ effect at all. Inset, because the header sits inside the scroller and an
164
+ outset ring is clipped by it. */
165
+ .crewlet-data-table--default .crewlet-data-table__column-resizer:focus-visible {
166
+ outline: 2px solid var(--color-focus);
167
+ outline-offset: var(--size-focus-ring-inset-offset);
168
+ background: var(--color-brand-accent-soft-strong);
169
+ }
170
+
171
+ /* Set on <body> while a column is being dragged, so the resize cursor
172
+ and the text-selection lock hold even when the pointer leaves the
173
+ header cell. */
174
+ body.crewlet-data-table-resizing {
175
+ cursor: col-resize;
176
+ user-select: none;
177
+ }
178
+
179
+ /* Sortable headers */
180
+ .crewlet-data-table--default .crewlet-data-table__th--sortable {
181
+ cursor: pointer;
182
+ transition: color var(--motion-duration-fast) var(--motion-easing-default);
183
+ }
184
+
185
+ .crewlet-data-table--default .crewlet-data-table__th--sortable:hover {
186
+ color: var(--color-text-primary);
187
+ }
188
+
189
+ .crewlet-data-table--default .crewlet-data-table__header-content {
190
+ display: flex;
191
+ align-items: center;
192
+ gap: var(--spacing-1);
193
+ min-width: 0;
194
+ max-width: 100%;
195
+ overflow: hidden;
196
+ padding-right: 0;
197
+ }
198
+
199
+ .crewlet-data-table--default .crewlet-data-table__header-content > span:first-child {
200
+ overflow: hidden;
201
+ text-overflow: ellipsis;
202
+ white-space: nowrap;
203
+ flex: 1;
204
+ min-width: 0;
205
+ }
206
+
207
+ /*
208
+ * THE SORT MARK IS THE HEADER'S ONE PIECE OF COLOUR. It is quiet while the
209
+ * column is merely sortable, and takes the accent ink when the table is
210
+ * actually sorted by it, which is the one "where the reader is" fact a header
211
+ * row carries. At 0.5 the resting mark measured under the 3:1 a graphical
212
+ * object has to clear against the header band, so it sits at the same 0.7 the
213
+ * compact variant's does and clears it in both themes.
214
+ */
215
+ .crewlet-data-table--default .crewlet-data-table__sort-icon {
216
+ font-size: var(--font-size-md);
217
+ flex-shrink: 0;
218
+ opacity: 0.7;
219
+ transition: opacity var(--motion-duration-fast) var(--motion-easing-default);
220
+ }
221
+
222
+ .crewlet-data-table--default .crewlet-data-table__th--sortable:hover .crewlet-data-table__sort-icon {
223
+ opacity: 1;
224
+ }
225
+
226
+ .crewlet-data-table--default .crewlet-data-table__sort-icon.is-active {
227
+ opacity: 1;
228
+ color: var(--crewlet-data-table-active-sort-color);
229
+ }
230
+
231
+ /* Row action button */
232
+ .crewlet-data-table--default .crewlet-data-table__action-btn {
233
+ background: transparent;
234
+ border: none;
235
+ color: var(--color-text-secondary);
236
+ cursor: pointer;
237
+ padding: 4px;
238
+ border-radius: var(--radius-xs);
239
+ display: inline-flex;
240
+ align-items: center;
241
+ justify-content: center;
242
+ transition: all var(--motion-duration-moderate) ease;
243
+ }
244
+
245
+ .crewlet-data-table--default .crewlet-data-table__action-btn:hover {
246
+ background: var(--color-feedback-danger-soft);
247
+ color: var(--color-feedback-danger-ink);
248
+ }
249
+
250
+
251
+ /* Settings and reset buttons in the Actions column header */
252
+ .crewlet-data-table--default .crewlet-data-table__header-btn {
253
+ position: absolute;
254
+ top: 4px;
255
+ background: transparent;
256
+ border: none;
257
+ color: var(--color-text-secondary);
258
+ cursor: pointer;
259
+ padding: 4px;
260
+ border-radius: var(--radius-xs);
261
+ display: inline-flex;
262
+ align-items: center;
263
+ justify-content: center;
264
+ transition: all var(--motion-duration-moderate) ease;
265
+ }
266
+
267
+ .crewlet-data-table--default .crewlet-data-table__header-btn:hover {
268
+ background: var(--color-surface-elevated);
269
+ color: var(--color-text-primary);
270
+ }
271
+
272
+ .crewlet-data-table--default .crewlet-data-table__header-btn:focus-visible {
273
+ outline: 2px solid var(--color-focus);
274
+ outline-offset: var(--size-focus-ring-inset-offset);
275
+ }
276
+
277
+
278
+ .crewlet-data-table--default .crewlet-data-table__header-btn--settings {
279
+ right: 4px;
280
+ }
281
+
282
+ .crewlet-data-table--default .crewlet-data-table__header-btn--reset {
283
+ right: 28px;
284
+ }
285
+
286
+ /*
287
+ * The settings modal is uilet's Modal primitive, composed in
288
+ * DataTable.tsx. Its inner controls (the settings sections, the
289
+ * items-per-page chips and the column toggles) have no uilet
290
+ * equivalent and are styled below, namespaced under
291
+ * .crewlet-data-table__ so they never collide with an application's
292
+ * own class names.
293
+ */
294
+
295
+ .crewlet-data-table__settings-section {
296
+ margin-bottom: var(--spacing-6);
297
+ position: relative;
298
+ }
299
+
300
+ .crewlet-data-table__settings-section:last-child {
301
+ margin-bottom: 0;
302
+ }
303
+
304
+ .crewlet-data-table__settings-section-title {
305
+ font-size: var(--font-size-2xs);
306
+ font-weight: var(--font-weight-medium);
307
+ color: var(--color-text-tertiary);
308
+ margin: 0 0 var(--spacing-3) 0;
309
+ text-transform: uppercase;
310
+ letter-spacing: var(--font-letter-spacing-wide);
311
+ }
312
+
313
+ .crewlet-data-table__settings-section-hint {
314
+ font-size: var(--font-size-compact);
315
+ color: var(--color-text-secondary);
316
+ margin: 0 0 var(--spacing-3) 0;
317
+ }
318
+
319
+ /* Items Per Page Options */
320
+ /*
321
+ * Settings modal footer layout. Reset on the left, Cancel + Apply on
322
+ * the right, sharing the modal's footer row via space-between. Modal's
323
+ * default footer is justify-content: flex-end, so the wrapper takes
324
+ * over the row to anchor Reset on the left.
325
+ */
326
+
327
+
328
+ /*
329
+ * Reset to Default checkmark confirmation. Renders briefly inside the
330
+ * Button's leadingIcon slot after a click so the operator sees the
331
+ * reset landed; auto-clears after ~1.5s. The colour tracks the
332
+ * theme's success token (with a sensible fallback) so it reads as a
333
+ * positive affordance rather than chrome.
334
+ */
335
+ .crewlet-data-table__reset-confirm-icon {
336
+ font-size: var(--font-size-md);
337
+ color: var(--color-feedback-success-ink);
338
+ }
339
+
340
+ .crewlet-data-table__items-per-page-options {
341
+ display: flex;
342
+ gap: var(--spacing-2);
343
+ flex-wrap: wrap;
344
+ }
345
+
346
+ /* The smallest control in the frame, and the one whose height was its text's:
347
+ padding alone shrinks with the density, and at the tightest step this chip
348
+ was under the 24px floor a pointer target has to keep. The control step
349
+ floors there at every density, so it is what the chip is measured to. */
350
+ .crewlet-data-table__items-per-page-btn {
351
+ display: inline-flex;
352
+ align-items: center;
353
+ justify-content: center;
354
+ min-width: var(--size-control-sm);
355
+ min-height: var(--size-control-sm);
356
+ background: var(--color-surface-subtle);
357
+ border: 1px solid var(--color-border-default);
358
+ color: var(--color-text-primary);
359
+ padding: var(--spacing-2) var(--spacing-4);
360
+ border-radius: var(--radius-sm);
361
+ font-size: var(--font-size-compact);
362
+ font-weight: var(--font-weight-medium);
363
+ cursor: pointer;
364
+ transition: all var(--motion-duration-moderate) ease;
365
+ }
366
+
367
+ .crewlet-data-table__items-per-page-btn:hover {
368
+ background: var(--color-surface-elevated);
369
+ border-color: var(--color-text-secondary);
370
+ }
371
+
372
+ .crewlet-data-table__items-per-page-btn.is-active {
373
+ background: var(--color-brand-accent);
374
+ border-color: var(--color-brand-accent);
375
+ color: var(--color-text-on-accent);
376
+ }
377
+
378
+ .crewlet-data-table__items-per-page-btn:focus-visible {
379
+ outline: 2px solid var(--color-focus);
380
+ outline-offset: 2px;
381
+ }
382
+
383
+ /* Column Toggles */
384
+ /* SIZED BY ITS ROWS, and capped rather than floored. A floor of 350px opened
385
+ the frame with a third of a screen of empty list under a table of four
386
+ columns, and said nothing at all about the table of twenty that scrolls
387
+ inside the dialog instead. The cap is the dialog's own share of the
388
+ viewport, so the footer stays reachable however many columns a table
389
+ declares, and the inline padding is the room the focus ring needs: an
390
+ outline drawn at the edge of a scroller is clipped by it. */
391
+ .crewlet-data-table__column-toggles {
392
+ display: flex;
393
+ flex-direction: column;
394
+ gap: var(--spacing-2);
395
+ max-height: 40vh;
396
+ overflow-y: auto;
397
+ overscroll-behavior: contain;
398
+ padding: var(--spacing-1);
399
+ margin: calc(var(--spacing-1) * -1);
400
+ list-style: none;
401
+ }
402
+
403
+ /* No min-height: the row is its controls and its padding, and both of those
404
+ are steps that already move with the density. */
405
+ .crewlet-data-table__column-toggle-item {
406
+ display: flex;
407
+ align-items: center;
408
+ gap: var(--spacing-3);
409
+ padding: var(--spacing-2) var(--spacing-3);
410
+ background: var(--color-surface-subtle);
411
+ border: 1px solid var(--color-border-default);
412
+ border-radius: var(--radius-sm);
413
+ transition: all var(--motion-duration-moderate) var(--motion-easing-in-out);
414
+ box-sizing: border-box;
415
+ }
416
+
417
+ .crewlet-data-table__column-toggle-item:hover:not(.is-dragging) {
418
+ background: var(--color-surface-elevated);
419
+ border-color: var(--color-text-secondary);
420
+ }
421
+
422
+ .crewlet-data-table__column-toggles:has(.is-dragging) .crewlet-data-table__column-toggle-item:not(.is-dragging):hover {
423
+ background: var(--color-surface-subtle);
424
+ border-color: var(--color-border-default);
425
+ }
426
+
427
+ .crewlet-data-table__column-toggle-item.is-dragging {
428
+ opacity: 0.5;
429
+ }
430
+
431
+ /* The handle is an IconButton now, so its size, its ink, its hover and its
432
+ focus ring are the package's. What is left here is the one thing a button
433
+ does not know: that this one is also what the row is dragged by. */
434
+ .crewlet-data-table__column-drag-handle {
435
+ cursor: grab;
436
+ flex-shrink: 0;
437
+ }
438
+
439
+ .crewlet-data-table__column-drag-handle:active {
440
+ cursor: grabbing;
441
+ }
442
+
443
+ /* A tick that cannot move: still read, still reachable, and visibly not a
444
+ choice. `aria-disabled` rather than `disabled` is what keeps it in the
445
+ reading order, so the ink is what says the rest.
446
+
447
+ The LABEL rather than the row, because the label declares its own colour,
448
+ and the TERTIARY step rather than the muted one, because this is still the
449
+ name of a column somebody has to read: tertiary is the step measured to
450
+ clear 4.5:1 on every surface it can land on, and muted is decoration. */
451
+ .crewlet-data-table__column-toggle.is-fixed .crewlet-checkbox__label {
452
+ color: var(--color-text-tertiary);
453
+ }
454
+
455
+ /*
456
+ * The settings frame's checkboxes are the package Checkbox now, so the rules
457
+ * that drew one by hand (the 18px box, its tick, its own focus ring) and the
458
+ * rules that drew the Wrap lines row around it went with the markup. Nothing
459
+ * in this package emits .crewlet-data-table__toggle-* or
460
+ * .crewlet-data-table__column-toggle-checkbox any more.
461
+ */
462
+
463
+ /*
464
+ * Cursor-pagination footer: centered Load more button rendered when
465
+ * the caller passes hasMore + onLoadMore. The end of the rows is the
466
+ * caller's own sentence, through `endMessage`, and silent without one: a
467
+ * table that is merely short has no end worth announcing.
468
+ */
469
+ .crewlet-data-table__load-more {
470
+ display: flex;
471
+ align-items: center;
472
+ justify-content: center;
473
+ gap: var(--spacing-2);
474
+ padding: var(--spacing-2) 0;
475
+ min-height: var(--size-control-md);
476
+ }
477
+
478
+ /* ─────────────────────────────────────────────────────────────────
479
+ * Compact variant.
480
+ *
481
+ * Lighter table chrome for dense list pages: tight padding, uppercase
482
+ * headers, full-row loading and error states, and the settings cog in
483
+ * the toolbar rather than the header row.
484
+ * Designed to sit inside an external Toolbar + Footer that the host
485
+ * page owns.
486
+ *
487
+ * Tokens declared on the root element are overridable by the host,
488
+ * from a rule that targets the root through the table's className or
489
+ * an ancestor selector (for example `.my-page .crewlet-data-table--compact`),
490
+ * so the active-sort color, the row hover and the archived-row tint
491
+ * can match a non-default palette without uilet needing to know about
492
+ * the host's tokens.
493
+ * ───────────────────────────────────────────────────────────────── */
494
+ .crewlet-data-table--compact {
495
+ /*
496
+ * THE OVERLAY STEP, not an opaque surface. A compact table sits on the page,
497
+ * inside a card and inside a dialog, and a hover painted as `elevated` drew
498
+ * the card's grey on all three: right on one ground and a block of the wrong
499
+ * colour on the other two. The overlay composites onto whatever is under it,
500
+ * which is the only value that is correct everywhere.
501
+ */
502
+ --crewlet-data-table-row-hover-bg: var(--color-surface-hover);
503
+ /*
504
+ * THE INK STEP, because this paints the header's WORDS. The fill step
505
+ * measures 4.06:1 light and 3.18:1 dark as text, under the 4.5:1 a fact has
506
+ * to clear, and the whole sort control takes this colour, label included.
507
+ * A host that overrides the property keeps whatever it sets.
508
+ */
509
+ --crewlet-data-table-active-sort-color: var(--color-brand-accent-ink);
510
+ /*
511
+ * The archived mark is NEUTRAL. It used to be a red the package mixed
512
+ * itself, which said "this failed" about a row whose only fact is that
513
+ * nobody is using it any more; a state that is not a problem takes no
514
+ * status hue.
515
+ */
516
+ --crewlet-data-table-archived-rail: var(--color-border-strong);
517
+ --crewlet-data-table-skeleton-duration: calc(var(--motion-duration-slow) * 6);
518
+
519
+ /*
520
+ * THE TWO INSETS THIS TABLE IS DRAWN ON THAT THE 4px SCALE DOES NOT NAME.
521
+ * The cell sits on 10px and the chrome around it on 14px, and each is the
522
+ * MIDPOINT of the two steps it falls between, written as a calc over those
523
+ * steps rather than as a number: the value stays on the scale, it stays
524
+ * readable as "between 8 and 12", and it still moves with --density, which
525
+ * a literal would not. Rounding either one to the nearer step costs two
526
+ * pixels on every row and four on a wrapped one, which is the difference
527
+ * between this table and the one the product already reads.
528
+ *
529
+ * A host rebinds them the way it rebinds the hover: a table that wants
530
+ * another rhythm sets the pair and every cell, header and sort control
531
+ * moves together.
532
+ */
533
+ --crewlet-data-table-cell-pad-y: calc((var(--spacing-2) + var(--spacing-3)) / 2);
534
+ --crewlet-data-table-cell-pad-x: var(--spacing-3);
535
+ /* The header's own vertical inset. It equals the cell's at this density and
536
+ parts from it at comfortable, which is where 0.2.0 drew the two apart. */
537
+ --crewlet-data-table-head-pad-y: var(--crewlet-data-table-cell-pad-y);
538
+ width: 100%;
539
+ }
540
+
541
+ /*
542
+ * THE CHROME STEP, on the table and on the chrome row alike.
543
+ *
544
+ * It is the MIDPOINT of the two scale steps it falls between, written as a
545
+ * calc over those steps rather than as a number: the value stays on the scale,
546
+ * it stays readable as "between 12 and 16", and it still moves with --density,
547
+ * which a literal would not.
548
+ *
549
+ * The row is named a second time because it does not always sit inside the
550
+ * table: where the table fills a card, the card's header holds it, and the
551
+ * inherited value stops arriving.
552
+ */
553
+ .crewlet-data-table,
554
+ .crewlet-data-table__chrome {
555
+ --crewlet-data-table-chrome-step: calc((var(--spacing-3) + var(--spacing-4)) / 2);
556
+ }
557
+
558
+ /*
559
+ * The toolbar, the header block's sides, the expanded panel and the gap before
560
+ * the settings cog: the chrome around the rows, on its own step.
561
+ *
562
+ * ON BOTH VARIANTS, because both draw a toolbar now: the pager belongs to a
563
+ * table that pages rather than to a look. Unset on the default one, every
564
+ * `padding` written through it was an invalid declaration and was dropped
565
+ * whole, so the bar the pager arrived in had no inset at all. It is left OFF
566
+ * the chrome row so a host that rebinds the inset still rebinds it for the
567
+ * whole of the chrome inside the table, which a declaration on the row itself
568
+ * would have quietly outranked.
569
+ */
570
+ .crewlet-data-table {
571
+ --crewlet-data-table-chrome-pad-x: var(--crewlet-data-table-chrome-step);
572
+ }
573
+
574
+ /*
575
+ * Horizontal-scroll wrapper around the <table> element only. The
576
+ * header (title + description + cog + pagination), toolbar (filter
577
+ * slot), and Load more footer sit OUTSIDE this scroll viewport so
578
+ * they stay anchored when the table overflows on narrow viewports.
579
+ */
580
+ .crewlet-data-table__rail {
581
+ /*
582
+ * Positioning context for the scrollbar mask. The rail wraps the
583
+ * scroll viewport so the mask can be placed at the rail's bottom-
584
+ * right corner without interfering with the table's natural flow.
585
+ * Width matches the scroll viewport inside.
586
+ */
587
+ position: relative;
588
+ width: 100%;
589
+ }
590
+
591
+ /*
592
+ * Scrollbar mask. When the table holds one or more sticky-right
593
+ * columns, the horizontal scrollbar inside the scroll viewport
594
+ * physically spans the full pane width, including the area visually
595
+ * occupied by the sticky cells. The mask overlays the rightmost
596
+ * portion of that scrollbar with the sticky background so the visible
597
+ * scroll track ends exactly at the left border of the sticky cells.
598
+ * Width is sourced from --crewlet-data-table-sticky-pane-width, which
599
+ * the component sets inline from the live sticky column widths so
600
+ * resize and Reset stay in sync. The default of 0 keeps the mask
601
+ * invisible on tables without a sticky pane.
602
+ *
603
+ * Height is sized to cover the tallest common horizontal scrollbar
604
+ * (Windows / X11 classic) without intruding into the rows above it
605
+ * on macOS overlay scrollbars where the bar is thinner. The mask is
606
+ * pointer-events: none so it never swallows clicks targeted at the
607
+ * underlying cells, even though those clicks already land on the
608
+ * sticky cell that sits above.
609
+ */
610
+ .crewlet-data-table__rail::after {
611
+ content: '';
612
+ position: absolute;
613
+ bottom: 0;
614
+ right: 0;
615
+ width: var(--crewlet-data-table-sticky-pane-width, 0);
616
+ height: var(--spacing-4);
617
+ background: var(
618
+ --crewlet-data-table-sticky-bg,
619
+ var(--color-surface-elevated)
620
+ );
621
+ pointer-events: none;
622
+ z-index: var(--z-index-raised);
623
+ }
624
+
625
+ /*
626
+ * Frozen variant: tables that carry a sticky-right action column.
627
+ *
628
+ * THE SCROLLER IS NOT LOCKED. It was `overflow-x: hidden`, on the reasoning
629
+ * that the fit pass redistributes the regular columns at every container-size
630
+ * change so a scrollbar is never needed. The fit has a floor,
631
+ * `minColumnWidth`, which is what keeps a cell legible, and a container
632
+ * narrower than the floors plus the pinned pane is one the columns cannot be
633
+ * fitted to. What the lock did there was CLIP them: measured on the conlet
634
+ * fixture in a 460px box, 164px of the row was cut off, reachable by nothing
635
+ * a reader has. Content behind a hidden overflow cannot be scrolled to by a
636
+ * wheel, a trackpad or a bar, so the pane stopped being a frozen edge and
637
+ * became a wall.
638
+ *
639
+ * The rail still drops its scrollbar mask. CSS cannot tell whether a
640
+ * scrollbar is there, so a mask that covers the track under the pinned pane
641
+ * in the rare state that has one paints a band over the last row in every
642
+ * state that does not.
643
+ */
644
+ .crewlet-data-table__rail--frozen::after {
645
+ display: none;
646
+ }
647
+
648
+ .crewlet-data-table__scroll {
649
+ width: 100%;
650
+ overflow-x: auto;
651
+ /* The gesture stops at the table's own edge, for the reason the default
652
+ variant's root declares it. */
653
+ overscroll-behavior-x: contain;
654
+ -webkit-overflow-scrolling: touch;
655
+ }
656
+
657
+ .crewlet-data-table--compact .crewlet-data-table__table {
658
+ /*
659
+ * width: 100% + table-layout: fixed + a trailing spacer column
660
+ * lets the table fill the container at minimum, while still
661
+ * letting the column-resize handle write widths 1:1. The spacer
662
+ * column has no explicit width so it absorbs all the leftover
663
+ * space; user-resized columns stay at their exact widths. When
664
+ * the sum of column widths exceeds the container, the spacer
665
+ * collapses to zero and the horizontal-scroll wrapper handles
666
+ * overflow.
667
+ */
668
+ width: 100%;
669
+ border-collapse: collapse;
670
+ table-layout: fixed;
671
+ }
672
+
673
+ /*
674
+ * A TABLE WITH NO ROWS LAYS ITSELF OUT BY CONTENT.
675
+ *
676
+ * A column width is a claim about content: this column needs this much room
677
+ * for what is in it. Under the fixed layout above, that claim is an
678
+ * instruction the browser carries out whatever it costs, so a table drawing
679
+ * one full-width message instead of rows came out wider than the box it sits
680
+ * in and a reader scrolled sideways past columns holding nothing.
681
+ *
682
+ * The widths stay stated, so the header keeps the shape its rows will land
683
+ * in and nothing jumps when they arrive. What changes is that the layout now
684
+ * reads them as preferences: the automatic algorithm honours a width it has
685
+ * room for and shrinks the row to fit when it has not, so nothing but the
686
+ * header cells' own content can make an empty table scroll.
687
+ */
688
+ .crewlet-data-table__table--rowless {
689
+ table-layout: auto;
690
+ }
691
+
692
+ .crewlet-data-table__th--spacer,
693
+ .crewlet-data-table__td--spacer {
694
+ /*
695
+ * Trailing spacer column: invisible, padding-free, takes whatever
696
+ * width is left over after the user-defined columns claim theirs.
697
+ * No padding so it never adds to the natural minimum width; no
698
+ * border on the right so the table's right edge stays clean.
699
+ */
700
+ padding: 0;
701
+ border: 0;
702
+ background: transparent;
703
+ min-width: 0;
704
+ width: auto;
705
+ }
706
+
707
+ /*
708
+ * When the table carries a sticky-right action column, the spacer
709
+ * sits BETWEEN the rightmost regular cell and the pinned action
710
+ * cell. Force a minimum gutter on it so the regular content never
711
+ * touches the action column, even if a state mutation bypasses the
712
+ * fit pass (visibility toggle, controlled column-width override,
713
+ * etc.). The fit pass reserves what this rule DRAWS, read off the cell
714
+ * rather than copied, so the gutter and the proportional grow stay in
715
+ * sync at every density: the token is `calc(24px * var(--density))`,
716
+ * which the comfortable density resolves to 27px.
717
+ */
718
+ .crewlet-data-table--compact
719
+ .crewlet-data-table__table:has(.crewlet-data-table__th--sticky-right)
720
+ .crewlet-data-table__th--spacer,
721
+ .crewlet-data-table--compact
722
+ .crewlet-data-table__table:has(.crewlet-data-table__th--sticky-right)
723
+ .crewlet-data-table__td--spacer {
724
+ min-width: var(--spacing-6);
725
+ width: var(--spacing-6);
726
+ }
727
+
728
+ /*
729
+ * Row actions column: pinned to the viewport's right edge with
730
+ * position: sticky so the kebab affordance stays visible during
731
+ * horizontal scroll AND keeps a fixed visual position regardless of
732
+ * how the operator resizes the data columns. The cell intentionally
733
+ * has no background so it blends with the surrounding row tone
734
+ * (default, hover, archived), the parent card surface remains
735
+ * visible underneath. The z-index keeps the kebab above the column
736
+ * separators painted on data cells.
737
+ */
738
+ .crewlet-data-table__th--actions,
739
+ .crewlet-data-table__td--actions {
740
+ position: sticky;
741
+ right: 0;
742
+ z-index: var(--z-index-raised);
743
+ background: transparent;
744
+ }
745
+
746
+ /*
747
+ * Opt-in sticky-right modifier for caller-defined columns. Pins the
748
+ * column to the right edge of the scroll container so a trailing
749
+ * action (a Details link, Edit chip, etc.) stays visible regardless
750
+ * of horizontal scroll or how the operator resizes earlier data
751
+ * columns. The cell paints an opaque background sourced from a
752
+ * theme-overridable token so content scrolling behind the cell does
753
+ * not bleed through the link text. The header z-index sits a layer
754
+ * above body cells so the column boundary remains crisp at the
755
+ * sticky edge. Callers tinting the surface re-bind the token via a
756
+ * wrapper rule (a card-style className on the table, for example).
757
+ */
758
+ .crewlet-data-table__th--sticky-right,
759
+ .crewlet-data-table__td--sticky-right {
760
+ position: sticky;
761
+ right: 0;
762
+ z-index: var(--z-index-raised);
763
+ /*
764
+ * THE LIFTED STEP. The pinned pane is the one part of a row that is not the
765
+ * row: it has to be opaque, so the cells scrolling behind it do not show
766
+ * through, and it reads as the pane it is by standing one step off the
767
+ * ground the rows are on. A table on another ground rebinds
768
+ * --crewlet-data-table-sticky-bg to it.
769
+ */
770
+ background: var(--crewlet-data-table-sticky-bg, var(--color-surface-elevated));
771
+ }
772
+
773
+ /*
774
+ * AND NO EDGE ON IT, because nothing ever passes behind it.
775
+ *
776
+ * An edge on a pinned pane says "the table continues under here". A column
777
+ * pinned right puts this rail in its FROZEN state, whose scroller locks
778
+ * horizontal overflow so the regular columns are always fitted to the
779
+ * container: there is nothing behind the pane on any table this package
780
+ * draws, and a line saying otherwise is chrome claiming a depth the surface
781
+ * does not have. The pane is told apart from the rows by its ground, one step
782
+ * off theirs, which is the whole of what 0.2.0 draws here.
783
+ */
784
+
785
+ /*
786
+ * Sticky cells are the row's trailing action area; the affordance
787
+ * they hold sits centered inside the sticky pane so the chip reads
788
+ * as the focal point of the pane rather than tucked against either
789
+ * edge. The base compact cell rule pins text-align: left at higher
790
+ * specificity, so the override is written with the full selector
791
+ * chain to win the cascade. Inline-flex content (the typical action
792
+ * chip pattern) respects the cell's text-align so this is sufficient
793
+ * on its own, no display change to the table-cell needed.
794
+ */
795
+ .crewlet-data-table--compact .crewlet-data-table__table th.crewlet-data-table__th--sticky-right,
796
+ .crewlet-data-table--compact .crewlet-data-table__table td.crewlet-data-table__td--sticky-right {
797
+ text-align: center;
798
+ }
799
+
800
+ .crewlet-data-table__th--sticky-right {
801
+ z-index: var(--z-index-sticky);
802
+ background: var(
803
+ --crewlet-data-table-sticky-header-bg,
804
+ var(--crewlet-data-table-sticky-bg, var(--color-surface-elevated))
805
+ );
806
+ }
807
+
808
+ /*
809
+ * Row hover, expansion and selection change the <tr> background, but a cell
810
+ * with its own background (the sticky-right column needs one so scrolled
811
+ * content does not bleed through) does not pick that change up. The row's tint
812
+ * is mirrored onto the sticky cell so the right edge stays attached to the row
813
+ * it belongs to instead of standing out as a different shade.
814
+ *
815
+ * AS A LAYER, NOT AS THE COLOUR. Every row tint in this table is now a
816
+ * translucent overlay, which is what makes it correct on the page, on a card
817
+ * and in a dialog alike. Assigning one to `background` here would REPLACE the
818
+ * opaque base the sticky pane exists for, and the rows scrolling underneath
819
+ * would show straight through the pinned action. A gradient of the overlay
820
+ * with itself is one flat layer painted OVER that base, so the pane composites
821
+ * exactly as the rest of the row does and stays opaque.
822
+ *
823
+ * ON EVERY HOVERED ROW, because that is what the row rule above does. Gated on
824
+ * the rows that ACT, the pane stayed on its own ground under a row that had
825
+ * just taken the tint, so the right-hand end of the row a reader was pointing
826
+ * at detached from the rest of it. The table whose owner asked for this pane
827
+ * has no clickable row in it at all: its action is a link inside the pane.
828
+ */
829
+ .crewlet-data-table--compact tbody tr:hover .crewlet-data-table__td--sticky-right,
830
+ .crewlet-data-table--compact .crewlet-data-table__row--expandable.is-expanded .crewlet-data-table__td--sticky-right {
831
+ background-image: linear-gradient(
832
+ var(--crewlet-data-table-row-hover-bg),
833
+ var(--crewlet-data-table-row-hover-bg)
834
+ );
835
+ }
836
+
837
+ .crewlet-data-table--compact tbody tr.crewlet-data-table__row--selected .crewlet-data-table__td--sticky-right {
838
+ background-image: linear-gradient(var(--color-brand-accent-soft), var(--color-brand-accent-soft));
839
+ }
840
+
841
+ /*
842
+ * Unstyled button-as-link cells (an agent name that navigates, a
843
+ * schedule that opens a drawer) must read as table text. Browsers
844
+ * center button text by their UA stylesheet, so a cell value that
845
+ * wraps onto multiple lines would center-align its lines instead of
846
+ * following the cell's alignment. Inherit pins buttons to whatever
847
+ * the cell declares; components that center via flex (Button,
848
+ * IconButton) are unaffected because their alignment comes from
849
+ * justify-content, not text-align.
850
+ */
851
+ .crewlet-data-table__table td button {
852
+ text-align: inherit;
853
+ }
854
+
855
+ .crewlet-data-table--compact .crewlet-data-table__table th,
856
+ .crewlet-data-table--compact .crewlet-data-table__table td {
857
+ /* The table inset, on the scale rather than beside it, so a density setting
858
+ moves the cells with everything else on the screen. */
859
+ padding: var(--crewlet-data-table-cell-pad-y) var(--crewlet-data-table-cell-pad-x);
860
+ text-align: left;
861
+ font-size: var(--font-size-compact);
862
+ border-bottom: 1px solid var(--color-border-default);
863
+ /*
864
+ * Center cells against the row's tallest cell. Tables like an
865
+ * activity feed mix short cells ("4h ago", "success") with tall
866
+ * identity blocks (avatar + name + id stacked vertically),
867
+ * so middle alignment keeps the short cells from sticking to
868
+ * the top while the multi-line ones sit at the row's full height.
869
+ */
870
+ vertical-align: middle;
871
+ /*
872
+ * Default to truncate-with-ellipsis (AWS-style data tables). The
873
+ * Wrap lines toggle in the settings frame flips this on
874
+ * by adding .crewlet-data-table--wrap-lines on the root, which
875
+ * the override below re-enables wrapping for. Long unbroken
876
+ * tokens (UUIDs) get clipped with an ellipsis instead of pushing
877
+ * the column wider. (max-width is intentionally NOT set here:
878
+ * table-layout: fixed already takes the th's width as the column
879
+ * width, and forcing max-width: 0 collapses the column to zero
880
+ * under some browser implementations.)
881
+ */
882
+ white-space: nowrap;
883
+ overflow: hidden;
884
+ text-overflow: ellipsis;
885
+ }
886
+
887
+ /*
888
+ * Wrap-lines toggle only affects BODY cells. Headers always keep
889
+ * their content on a single line; a narrow column truncates the
890
+ * label with an ellipsis instead of wrapping onto two lines, which
891
+ * would change row heights every time someone resizes a column.
892
+ */
893
+ .crewlet-data-table--compact.crewlet-data-table--wrap-lines .crewlet-data-table__table td {
894
+ white-space: normal;
895
+ overflow: visible;
896
+ overflow-wrap: anywhere;
897
+ word-break: break-word;
898
+ max-width: none;
899
+ }
900
+
901
+ /*
902
+ * Force-pin the header cells (and their inner sort-button label) to
903
+ * single-line truncate, even when --wrap-lines is on. The sort
904
+ * button is a flex row [label | arrow]; the label takes whatever
905
+ * space is left, then ellipsises.
906
+ */
907
+ .crewlet-data-table--compact .crewlet-data-table__table th,
908
+ .crewlet-data-table--compact.crewlet-data-table--wrap-lines .crewlet-data-table__table th {
909
+ white-space: nowrap;
910
+ overflow: hidden;
911
+ text-overflow: ellipsis;
912
+ }
913
+
914
+ .crewlet-data-table--compact .crewlet-data-table__sort-button {
915
+ overflow: hidden;
916
+ }
917
+
918
+ .crewlet-data-table--compact .crewlet-data-table__sort-button > span:first-child {
919
+ white-space: nowrap;
920
+ text-overflow: ellipsis;
921
+ }
922
+
923
+ /*
924
+ * THE HEADER ROW. The micro-label register, one rule under it, and a hairline
925
+ * between one column and the next: those three are what say "these are the
926
+ * columns".
927
+ *
928
+ * IT IS NOT A PAINTED BAND AND IT DOES NOT STICK BY DEFAULT. Both were added
929
+ * here and both are visible: a filled band under an unfilled toolbar reads as
930
+ * a second strip of chrome, and a header that pins itself is a header that
931
+ * leaves its ground behind on a table the page scrolls rather than the
932
+ * scroller does. `maxBodyHeight` turns the pair on together, because a pinned
933
+ * header with no ground under it is rows read through column names, and
934
+ * because a bounded body is the only thing a pin can happen against. The cell
935
+ * is `position: relative` regardless, since the resize handle hangs off it.
936
+ */
937
+ .crewlet-data-table--compact .crewlet-data-table__table th {
938
+ position: relative;
939
+ color: var(--color-text-tertiary);
940
+ font-weight: var(--font-weight-medium);
941
+ letter-spacing: var(--font-letter-spacing-wide);
942
+ text-transform: uppercase;
943
+ font-size: var(--font-size-2xs);
944
+ /* Headers must read as a single tight line; never wrap onto two lines
945
+ because the next column is unusually narrow. */
946
+ white-space: nowrap;
947
+ }
948
+
949
+ .crewlet-data-table--compact .crewlet-data-table__table td {
950
+ /* The row token, so a compact table lines up with every other list in a
951
+ product and a cell holding one word is as tall as a cell holding a chip. */
952
+ height: var(--size-row-md);
953
+ }
954
+
955
+ /*
956
+ * EVERY ROW LIGHTS UP UNDER THE POINTER, because on a table twelve columns
957
+ * wide the tint is how a reader keeps their eye on one row while they cross
958
+ * it. What says a row can be PRESSED is the cursor, which only a row that
959
+ * acts takes.
960
+ *
961
+ * THE OVERLAY STEP, not an opaque surface. This table stands on the page, in
962
+ * a card and inside a dialog; an opaque hover is right on one of those three
963
+ * and a block of the wrong grey on the other two.
964
+ */
965
+ .crewlet-data-table--compact .crewlet-data-table__table tbody tr:hover {
966
+ background: var(--crewlet-data-table-row-hover-bg);
967
+ }
968
+
969
+ /*
970
+ * THE HAIRLINE BETWEEN ONE COLUMN AND THE NEXT, on the header row only.
971
+ * Painted off the right edge of every thead cell, with three exclusions:
972
+ * 1. the literal last cell, so the row does not close on a line;
973
+ * 2. a chrome column itself (the spacer, the expand chevron, the actions
974
+ * cell), which is not a column a reader is being shown the edge of;
975
+ * 3. a cell whose next sibling is a chrome column, so the last real column
976
+ * is not divided from a cell that holds nothing.
977
+ * Inset top and bottom, so it reads as a delimiter rather than as a border,
978
+ * and drawn on the header alone: the rows below stay clean.
979
+ */
980
+ .crewlet-data-table--compact .crewlet-data-table__table thead th:not(:last-child):not(.crewlet-data-table__th--chrome):not(:has(+ .crewlet-data-table__th--chrome))::after {
981
+ content: '';
982
+ position: absolute;
983
+ /* Half a step past the 4px one, which is what holds the line clear of the
984
+ cell's own top and bottom rather than running the height of the row. */
985
+ top: calc((var(--spacing-1) + var(--spacing-2)) / 2);
986
+ bottom: calc((var(--spacing-1) + var(--spacing-2)) / 2);
987
+ right: 0;
988
+ width: 1px;
989
+ background: var(--color-border-default);
990
+ pointer-events: none;
991
+ }
992
+
993
+ .crewlet-data-table--compact .crewlet-data-table__row--clickable {
994
+ cursor: pointer;
995
+ }
996
+
997
+ /* A row that takes Enter and Space is a row somebody's focus lands on, and it
998
+ had nothing to show for it. Inset, because the ring is drawn inside a
999
+ scroller and the row below would paint over an outset one. */
1000
+ .crewlet-data-table__row--clickable:focus-visible {
1001
+ outline: 2px solid var(--color-focus);
1002
+ outline-offset: var(--size-focus-ring-inset-offset);
1003
+ }
1004
+
1005
+ /*
1006
+ * The table's own controls: the pagination cluster and the settings cog. They
1007
+ * sit in `__chrome`, which is drawn EITHER at the end of this table's toolbar
1008
+ * or, where the table fills a card, on that card's header row (see
1009
+ * Card/headerSlot.ts). So every rule below is written through `__chrome`
1010
+ * rather than through the table's root: the root is not an ancestor of these
1011
+ * buttons once the card's header holds them, and a geometry that stopped
1012
+ * applying there would hand the cog back to the icon button's own radius and
1013
+ * its own 12px glyph, one row up from a table it no longer looks like it
1014
+ * belongs to.
1015
+ */
1016
+ /* The two chevrons and the number between them read as ONE control, so they
1017
+ sit a half step apart rather than a whole one: at a full step the cluster
1018
+ reads as three things beside each other. */
1019
+ .crewlet-data-table__pagination {
1020
+ display: inline-flex;
1021
+ align-items: center;
1022
+ gap: calc(var(--spacing-1) / 2);
1023
+ }
1024
+
1025
+ /*
1026
+ * Thin vertical separator between the pagination chevrons and the
1027
+ * settings cog. Painted as a pseudo-element on the left edge of the
1028
+ * settings button (inset 4px from top/bottom so it reads as a
1029
+ * delimiter, not a border). Only renders when the settings button
1030
+ * sits adjacent to the pagination block.
1031
+ */
1032
+ .crewlet-data-table__pagination + .crewlet-data-table__settings-btn {
1033
+ position: relative;
1034
+ /*
1035
+ * Widen the gap between the pagination cluster and the settings
1036
+ * cog so the separator can sit close to the pagination side with
1037
+ * comfortable breathing room before the cog.
1038
+ *
1039
+ * THROUGH THE FALLBACK WHEN A CARD'S HEADER HOLDS THIS ROW. The step is the
1040
+ * table's own, declared on its root and inherited down; a chrome row drawn
1041
+ * in the card's header has no such ancestor, and a `var()` that resolves to
1042
+ * nothing takes the whole declaration with it, closing the gap the
1043
+ * separator is drawn in. Written this way the host's own rebinding of the
1044
+ * pad still reaches the row inside the table, which a second declaration
1045
+ * here would have overridden.
1046
+ */
1047
+ margin-left: var(--crewlet-data-table-chrome-pad-x, var(--crewlet-data-table-chrome-step));
1048
+ }
1049
+
1050
+ .crewlet-data-table__pagination + .crewlet-data-table__settings-btn::before {
1051
+ content: '';
1052
+ position: absolute;
1053
+ top: var(--spacing-1);
1054
+ bottom: var(--spacing-1);
1055
+ /*
1056
+ * Anchored one step past the pagination block's right edge, so it reads as
1057
+ * the closer of the pagination cluster rather than a divider centred in the
1058
+ * gap between the two.
1059
+ */
1060
+ left: calc(var(--spacing-3) * -1);
1061
+ width: 1px;
1062
+ background: var(--color-border-default);
1063
+ }
1064
+
1065
+ /*
1066
+ * The two controls are the package IconButton, which is what gives them a
1067
+ * name, a ring and a tooltip. Their GEOMETRY is the table's own, and it is
1068
+ * written through the CHROME ROW so it outranks the icon button's own rules,
1069
+ * which are bundled after this sheet: the radius there is the medium step and
1070
+ * the glyph is pinned to 12px, and both are visibly not this table's. Through
1071
+ * the row rather than through the table's root, which used to carry it,
1072
+ * because the row is what a card's header takes: scoped to the root, the
1073
+ * hosted cog would have kept the geometry only while it stayed in the bar this
1074
+ * change moves it out of.
1075
+ */
1076
+ .crewlet-data-table__chrome .crewlet-data-table__page-btn,
1077
+ .crewlet-data-table__chrome .crewlet-data-table__settings-btn {
1078
+ display: inline-flex;
1079
+ align-items: center;
1080
+ justify-content: center;
1081
+ /* The small control step, which floors at 24px however the density is set. */
1082
+ width: var(--size-control-sm);
1083
+ height: var(--size-control-sm);
1084
+ padding: 0;
1085
+ background: transparent;
1086
+ border: 1px solid transparent;
1087
+ border-radius: var(--radius-sm);
1088
+ color: var(--color-text-secondary);
1089
+ cursor: pointer;
1090
+ transition: background var(--motion-duration-fast) var(--motion-easing-default), color var(--motion-duration-fast) var(--motion-easing-default), border-color var(--motion-duration-fast) var(--motion-easing-default);
1091
+ }
1092
+
1093
+ /* The chevrons and the cog are read across a toolbar rather than inside a
1094
+ label, so they are drawn at the mark step this chrome has always used and
1095
+ not at the 12px an icon button gives a glyph beside words. */
1096
+ .crewlet-data-table__chrome .crewlet-data-table__page-btn .crewlet-glyph,
1097
+ .crewlet-data-table__chrome .crewlet-data-table__settings-btn .crewlet-glyph {
1098
+ width: var(--font-size-lg);
1099
+ height: var(--font-size-lg);
1100
+ }
1101
+
1102
+ .crewlet-data-table__chrome .crewlet-data-table__page-btn:hover:not(:disabled),
1103
+ .crewlet-data-table__chrome .crewlet-data-table__settings-btn:hover {
1104
+ background: var(--color-surface-hover);
1105
+ border-color: var(--color-border-default);
1106
+ color: var(--color-text-primary);
1107
+ }
1108
+
1109
+ .crewlet-data-table__chrome .crewlet-data-table__page-btn:disabled {
1110
+ opacity: 0.35;
1111
+ cursor: default;
1112
+ }
1113
+
1114
+
1115
+ .crewlet-data-table__page-number {
1116
+ display: inline-flex;
1117
+ align-items: center;
1118
+ justify-content: center;
1119
+ min-width: var(--spacing-6);
1120
+ /* Half a step past the 4px one. It is the minimum that holds a single-digit
1121
+ page; on a long table, where the number runs to three, this is the whole
1122
+ of what keeps it off the two chevrons. */
1123
+ padding: 0 calc((var(--spacing-1) + var(--spacing-2)) / 2);
1124
+ font-size: var(--font-size-xs);
1125
+ font-variant-numeric: tabular-nums;
1126
+ color: var(--color-text-primary);
1127
+ }
1128
+
1129
+ /* ─── Toolbar slot (filter bars, search, batch actions) ────────── */
1130
+ /*
1131
+ * Two-zone toolbar: the caller's content (filter pills, search) sits
1132
+ * on the LEFT (toolbar-start); the table's own controls (pagination
1133
+ * chevrons + settings cog) sit on the RIGHT, in `__chrome`. Either
1134
+ * zone can be absent; the toolbar only renders when at least one
1135
+ * has content, and the chrome row is drawn on a card's header instead
1136
+ * wherever the table fills one. The row always aligns to the right
1137
+ * edge so the cog and chevrons hold a consistent position across
1138
+ * pages.
1139
+ */
1140
+ /*
1141
+ * Optional header block. Sits above the toolbar and renders the
1142
+ * table's title (section name) and description (one-line context)
1143
+ * when callers pass either prop. Folds what used to be a per-page
1144
+ * <section><header><h2/><p/></header><DataTable/></section> pattern
1145
+ * into the primitive so the entire surface shares one card.
1146
+ */
1147
+ /*
1148
+ * Header row layout. Icon (optional) + title/description stack on the
1149
+ * left, right-side controls (pagination + settings cog) on the right.
1150
+ * Wraps on narrow viewports so the controls drop below the text rather
1151
+ * than colliding with a long description.
1152
+ */
1153
+ .crewlet-data-table__header {
1154
+ display: flex;
1155
+ align-items: flex-start;
1156
+ gap: var(--spacing-3);
1157
+ flex-wrap: wrap;
1158
+ /* More above than below: the title sits under the panel's own top edge and
1159
+ the description closes onto the rule, which is how the block reads as one
1160
+ thing rather than as two lines centred in a strip. */
1161
+ padding: var(--crewlet-data-table-chrome-pad-x) var(--spacing-4) var(--spacing-3);
1162
+ min-height: var(--size-row-lg);
1163
+ border-bottom: 1px solid var(--color-border-default);
1164
+ background: var(--color-surface-subtle);
1165
+ }
1166
+
1167
+ .crewlet-data-table__header-icon {
1168
+ font-size: var(--font-size-2xl);
1169
+ color: var(--color-text-secondary);
1170
+ flex-shrink: 0;
1171
+ margin-top: 1px;
1172
+ }
1173
+
1174
+ .crewlet-data-table__header-text {
1175
+ display: flex;
1176
+ flex-direction: column;
1177
+ gap: var(--spacing-1);
1178
+ flex: 1;
1179
+ min-width: 0;
1180
+ }
1181
+
1182
+ .crewlet-data-table__header .crewlet-data-table__chrome {
1183
+ flex-shrink: 0;
1184
+ margin-left: auto;
1185
+ }
1186
+
1187
+ /* A SECTION NAME, at the step a section name takes. At the body step it read
1188
+ as the first line of the description under it rather than as the title of
1189
+ the surface, and the tracking is the snug step a heading closes on, not the
1190
+ display step, which at 16px pulls the letters together. */
1191
+ .crewlet-data-table__title {
1192
+ margin: 0;
1193
+ font-size: var(--font-size-md);
1194
+ font-weight: var(--font-weight-semibold);
1195
+ color: var(--color-text-primary);
1196
+ letter-spacing: var(--font-letter-spacing-snug);
1197
+ }
1198
+
1199
+ /* A SENTENCE, so it takes the cell step and the ink a sentence is read at.
1200
+ The quiet ink is for a label nobody reads twice; this is the line that says
1201
+ what the table is for. */
1202
+ .crewlet-data-table__description {
1203
+ margin: 0;
1204
+ font-size: var(--font-size-compact);
1205
+ color: var(--color-text-secondary);
1206
+ line-height: var(--font-line-height-normal);
1207
+ }
1208
+
1209
+ /*
1210
+ * When the header and the toolbar are both present, the toolbar's
1211
+ * top edge already meets the header's bottom border, so the toolbar
1212
+ * keeps its own bottom border (table head delimiter) without painting
1213
+ * a second top border.
1214
+ */
1215
+ .crewlet-data-table__toolbar {
1216
+ display: flex;
1217
+ align-items: flex-end;
1218
+ justify-content: space-between;
1219
+ gap: var(--spacing-4);
1220
+ flex-wrap: wrap;
1221
+ padding: var(--spacing-3) var(--crewlet-data-table-chrome-pad-x);
1222
+ border-bottom: 1px solid var(--color-border-default);
1223
+ background: var(--color-surface-subtle);
1224
+ }
1225
+
1226
+ .crewlet-data-table__toolbar-start {
1227
+ display: flex;
1228
+ align-items: flex-end;
1229
+ flex-wrap: wrap;
1230
+ gap: var(--spacing-3);
1231
+ flex: 1 1 auto;
1232
+ min-width: 0;
1233
+ }
1234
+
1235
+ /*
1236
+ * The band under the toolbar: the state the toolbar's controls produced, on
1237
+ * the same chrome ground and fenced from the rows by the same hairline every
1238
+ * other boundary here is drawn with. It carries no rule of its own on top,
1239
+ * because the toolbar above it already draws one.
1240
+ */
1241
+ .crewlet-data-table__filter-bar {
1242
+ display: flex;
1243
+ align-items: center;
1244
+ flex-wrap: wrap;
1245
+ gap: var(--spacing-2);
1246
+ padding: var(--spacing-2) var(--crewlet-data-table-chrome-pad-x);
1247
+ border-bottom: 1px solid var(--color-border-default);
1248
+ background: var(--color-surface-subtle);
1249
+ }
1250
+
1251
+ /*
1252
+ * Loading skeleton. Shimmer bars painted inside the real table body
1253
+ * while `loading` is true and no rows exist. The pulse mirrors the
1254
+ * Skeleton primitive's timing so mixed pages (skeleton cards above a
1255
+ * loading table) breathe in sync.
1256
+ */
1257
+ @keyframes crewlet-data-table-skeleton-pulse {
1258
+ 0%, 100% { opacity: 1; }
1259
+ 50% { opacity: 0.45; }
1260
+ }
1261
+
1262
+ .crewlet-data-table__skeleton-bar {
1263
+ display: inline-block;
1264
+ height: var(--spacing-3);
1265
+ border-radius: var(--radius-xs);
1266
+ background: var(--color-surface-elevated, var(--color-surface-muted));
1267
+ animation: crewlet-data-table-skeleton-pulse var(--crewlet-data-table-skeleton-duration) var(--motion-easing-in-out) infinite;
1268
+ vertical-align: middle;
1269
+ }
1270
+
1271
+ /*
1272
+ * Clear-filters link. Sits at the end of the filter slot, baseline-
1273
+ * aligned with the filter controls (the slot uses align-items:
1274
+ * flex-end, so the bottom padding tucks the text to the same line
1275
+ * as the Select triggers). Rendered only while a filter is active.
1276
+ *
1277
+ * THE STEP ABOVE, not the one below. The hand-tuned 7px became the 4px step
1278
+ * when this sheet moved onto the scale, and 4 is the FARTHER of the two steps
1279
+ * it sits between: the link dropped three pixels off the line the comment
1280
+ * above says it holds. 8px is one pixel from the value that was measured, and
1281
+ * it is a step.
1282
+ */
1283
+ .crewlet-data-table__clear-filters {
1284
+ background: none;
1285
+ border: none;
1286
+ padding: 0 0 var(--spacing-2);
1287
+ font-size: var(--font-size-compact);
1288
+ font-family: inherit;
1289
+ /* The ink step: this is a word, and the fill step does not clear 4.5:1. */
1290
+ color: var(--color-brand-accent-ink);
1291
+ cursor: pointer;
1292
+ white-space: nowrap;
1293
+ align-self: flex-end;
1294
+ /* Pin to the right edge of the toolbar row (before the pagination
1295
+ cluster when present) so the affordance sits in the same place
1296
+ on every table, regardless of the filter slot's own layout. */
1297
+ margin-left: auto;
1298
+ flex: 0 0 auto;
1299
+ }
1300
+
1301
+ .crewlet-data-table__clear-filters:hover {
1302
+ text-decoration: underline;
1303
+ }
1304
+
1305
+ .crewlet-data-table__clear-filters:focus-visible {
1306
+ outline: 2px solid var(--color-focus);
1307
+ outline-offset: 2px;
1308
+ border-radius: var(--radius-xs);
1309
+ }
1310
+
1311
+ /*
1312
+ * Pagination + settings cog. Always pinned to the right edge of the
1313
+ * toolbar row, even when:
1314
+ * - the toolbar has no filter slot (solo right-side controls)
1315
+ * - the row wraps onto two lines on narrow viewports
1316
+ * `margin-left: auto` consumes the leftover row space, pushing the
1317
+ * cluster past the filter slot (or to the row's right edge when it
1318
+ * is alone). justify-content: space-between alone is not enough,
1319
+ * since space-between with one item left-aligns it.
1320
+ */
1321
+ .crewlet-data-table__chrome {
1322
+ display: flex;
1323
+ align-items: center;
1324
+ gap: var(--spacing-2);
1325
+ flex-shrink: 0;
1326
+ margin-left: auto;
1327
+ }
1328
+
1329
+ /* ─── Expandable rows ──────────────────────────────────────────── */
1330
+
1331
+ /*
1332
+ * Chevron column: fixed 32px width, zero horizontal padding on both
1333
+ * the header and the body cells. With the same padding on both, the
1334
+ * `>` glyph in every data row lines up vertically beneath the
1335
+ * expand-all `>` in the header row.
1336
+ */
1337
+ .crewlet-data-table__expand-header,
1338
+ .crewlet-data-table--compact .crewlet-data-table__table th.crewlet-data-table__expand-header {
1339
+ width: var(--size-control-md);
1340
+ text-align: center;
1341
+ padding-left: 0;
1342
+ padding-right: 0;
1343
+ }
1344
+
1345
+ .crewlet-data-table--compact .crewlet-data-table__table td.crewlet-data-table__expand-cell {
1346
+ width: var(--size-control-md);
1347
+ text-align: center;
1348
+ color: var(--color-text-tertiary);
1349
+ padding-left: 0;
1350
+ padding-right: 0;
1351
+ }
1352
+
1353
+ /*
1354
+ * Expand-all header button. Sits inside the chevron column header
1355
+ * cell, paints the right-pointing chevron, rotates to point down when
1356
+ * every visible row is expanded. Clicking toggles between expand-all
1357
+ * and collapse-all.
1358
+ */
1359
+ .crewlet-data-table__expand-all-btn {
1360
+ /*
1361
+ * THE BOX THAT IS PAINTED, WHICH IS THE DRAWING PLUS ONE STEP OF HALO.
1362
+ * The whole hit target used to be painted, and this cell is what sets the
1363
+ * header row's height: at the small control step the row of column names
1364
+ * stood six pixels taller than the one the product reads. The target is the
1365
+ * ::after below, which reaches past this box into the cell's own padding
1366
+ * rather than making the cell taller.
1367
+ */
1368
+ position: relative;
1369
+ width: calc(var(--font-size-lg) + var(--spacing-1));
1370
+ height: calc(var(--font-size-lg) + var(--spacing-1));
1371
+ display: inline-flex;
1372
+ align-items: center;
1373
+ justify-content: center;
1374
+ background: transparent;
1375
+ border: none;
1376
+ padding: 0;
1377
+ cursor: pointer;
1378
+ color: var(--color-text-tertiary);
1379
+ border-radius: var(--radius-xs);
1380
+ transition: background-color var(--motion-duration-base) ease, color var(--motion-duration-base) ease;
1381
+ }
1382
+
1383
+ /*
1384
+ * THE TARGET, WHICH IS NOT THE DRAWING. A pointer target under 24px fails
1385
+ * WCAG 2.2 and the painted box is 22, so the pressable area is grown here
1386
+ * instead of there: centred on the control, at the small control step, which
1387
+ * floors at 24px however the density is set. It overhangs into the header
1388
+ * cell's own vertical padding, which `overflow: hidden` clips at the padding
1389
+ * edge rather than the content edge, so all of it is reachable; the column is
1390
+ * wider than the target, so nothing overhangs sideways at all.
1391
+ */
1392
+ .crewlet-data-table__expand-all-btn::after,
1393
+ .crewlet-data-table__expand-btn::after {
1394
+ content: '';
1395
+ position: absolute;
1396
+ top: 50%;
1397
+ left: 50%;
1398
+ width: var(--size-control-sm);
1399
+ height: var(--size-control-sm);
1400
+ transform: translate(-50%, -50%);
1401
+ }
1402
+
1403
+ .crewlet-data-table__expand-all-btn:hover {
1404
+ background: var(--color-surface-elevated);
1405
+ color: var(--color-text-primary);
1406
+ }
1407
+
1408
+ /* AROUND THE DRAWING, AND NOT INSIDE IT. Every other ring in this sheet is
1409
+ inset, because its control sits in a scroller where an outset ring is
1410
+ clipped by the edge. These two are the exception: the box is the chevron and
1411
+ nothing else, so an inset ring is a square drawn ON the glyph. It sits in
1412
+ the chevron column's own slack instead, which is five pixels either side of
1413
+ the button and ten above and below, so there is nothing for the scroller to
1414
+ clip. */
1415
+ .crewlet-data-table__expand-all-btn:focus-visible,
1416
+ .crewlet-data-table__expand-btn:focus-visible {
1417
+ outline: 2px solid var(--color-focus);
1418
+ }
1419
+
1420
+ /* A DRAWING, so it is sized as one. This rule set a font size, which an SVG
1421
+ does not read, so the chevron drew at whatever px the component passed and
1422
+ the declaration meant nothing. */
1423
+ .crewlet-data-table__chevron {
1424
+ width: var(--font-size-lg);
1425
+ height: var(--font-size-lg);
1426
+ line-height: 1;
1427
+ transition: transform var(--motion-duration-base) ease;
1428
+ display: inline-block;
1429
+ }
1430
+
1431
+ /*
1432
+ * `chevron_right` glyph points right by default; rotating 90deg
1433
+ * makes it point down to signal "expanded". Both the per-row
1434
+ * chevron and the expand-all header chevron share this transition.
1435
+ */
1436
+ .crewlet-data-table__chevron.is-open {
1437
+ transform: rotate(90deg);
1438
+ }
1439
+
1440
+ .crewlet-data-table--compact .crewlet-data-table__row--expandable.is-expanded {
1441
+ background: var(--crewlet-data-table-row-hover-bg);
1442
+ }
1443
+
1444
+ /* The panel under a row sits on the chrome's own ground and takes the chrome
1445
+ inset at its sides, so it reads as belonging to the table rather than to
1446
+ the row it opened from. */
1447
+ .crewlet-data-table__expanded-row td.crewlet-data-table__expanded-cell {
1448
+ padding: var(--spacing-4) var(--crewlet-data-table-chrome-pad-x);
1449
+ background: var(--color-surface-subtle);
1450
+ border-bottom: 1px solid var(--color-border-default);
1451
+ }
1452
+
1453
+ /* In comfortable density, the expanded panel inherits the same outer
1454
+ 24px margin as its parent row so the detail content lines up with
1455
+ the row's first and last columns. */
1456
+ .crewlet-data-table--compact.crewlet-data-table--density-comfortable .crewlet-data-table__expanded-row td.crewlet-data-table__expanded-cell {
1457
+ padding: var(--spacing-4) var(--spacing-6);
1458
+ }
1459
+
1460
+ /*
1461
+ * Density="comfortable" overrides. Used by surfaces that live inside a
1462
+ * section card with 24px inner padding, where the
1463
+ * canonical compact density (13px font, 10/12px cell padding) looks
1464
+ * cramped against the surrounding card chrome. The font and cell
1465
+ * padding bump up; the first / last column gain extra outer padding
1466
+ * so the row aligns with the card's left and right edges.
1467
+ */
1468
+ .crewlet-data-table--compact.crewlet-data-table--density-comfortable .crewlet-data-table__table {
1469
+ font-size: var(--font-size-sm);
1470
+ }
1471
+
1472
+ /*
1473
+ * The comfortable density moves the pair rather than restating six paddings:
1474
+ * the cell opens to 14 on both axes and the header holds 12 above and below,
1475
+ * which is the one place the two part company.
1476
+ */
1477
+ .crewlet-data-table--compact.crewlet-data-table--density-comfortable {
1478
+ --crewlet-data-table-cell-pad-y: var(--crewlet-data-table-chrome-pad-x);
1479
+ --crewlet-data-table-cell-pad-x: var(--crewlet-data-table-chrome-pad-x);
1480
+ --crewlet-data-table-head-pad-y: var(--spacing-3);
1481
+ }
1482
+
1483
+ /*
1484
+ * And at this density the header IS a band. The rows carry enough air that an
1485
+ * unfilled header row reads as one more row rather than as the names of the
1486
+ * columns.
1487
+ */
1488
+ .crewlet-data-table--compact.crewlet-data-table--density-comfortable .crewlet-data-table__table th {
1489
+ padding: var(--crewlet-data-table-head-pad-y) var(--crewlet-data-table-cell-pad-x);
1490
+ background: var(--color-surface-subtle);
1491
+ }
1492
+
1493
+ .crewlet-data-table--compact.crewlet-data-table--density-comfortable .crewlet-data-table__table th:first-child,
1494
+ .crewlet-data-table--compact.crewlet-data-table--density-comfortable .crewlet-data-table__table td:first-child {
1495
+ padding-left: var(--spacing-6);
1496
+ }
1497
+
1498
+ .crewlet-data-table--compact.crewlet-data-table--density-comfortable .crewlet-data-table__table th:last-child,
1499
+ .crewlet-data-table--compact.crewlet-data-table--density-comfortable .crewlet-data-table__table td:last-child {
1500
+ padding-right: var(--spacing-6);
1501
+ }
1502
+
1503
+ /*
1504
+ * Sortable-header button inside the comfortable density needs the same
1505
+ * horizontal padding bumps so the label sits flush with adjacent cells
1506
+ * (the button supplants the th's padding when sortable=true).
1507
+ */
1508
+ .crewlet-data-table--compact.crewlet-data-table--density-comfortable .crewlet-data-table__sort-button {
1509
+ padding: var(--crewlet-data-table-head-pad-y) var(--crewlet-data-table-cell-pad-x);
1510
+ }
1511
+
1512
+ .crewlet-data-table--compact.crewlet-data-table--density-comfortable .crewlet-data-table__th--sortable:first-child .crewlet-data-table__sort-button {
1513
+ padding-left: var(--spacing-6);
1514
+ }
1515
+
1516
+ .crewlet-data-table--compact.crewlet-data-table--density-comfortable .crewlet-data-table__th--sortable:last-child .crewlet-data-table__sort-button {
1517
+ padding-right: var(--spacing-6);
1518
+ }
1519
+
1520
+ /* ─── The pinned header ──────────────────────────────────────────
1521
+ A header that stays while the rows move, which is what a table whose BODY
1522
+ is bounded has: the scroller it already sits in gains a height, so it
1523
+ scrolls, and the names have something to stay against. Those two are one
1524
+ prop (`maxBodyHeight`) rather than two, because either alone does nothing:
1525
+ a bound with no pin is rows that scroll their names away, and a pin with no
1526
+ bound is a header pinned to a box that never moves.
1527
+
1528
+ The band travels with the pin for the same reason it is not painted by
1529
+ default: names held over rows passing behind them, on no ground of their
1530
+ own, are rows read through column names. */
1531
+ .crewlet-data-table--sticky-head .crewlet-data-table__table th {
1532
+ position: sticky;
1533
+ top: 0;
1534
+ z-index: var(--z-index-sticky);
1535
+ background: var(--color-surface-subtle);
1536
+ }
1537
+
1538
+ /* The pinned cell of a pinned header needs the sticky pane's own ground, not
1539
+ the band's: it is the one cell rows scroll behind horizontally as well. */
1540
+ .crewlet-data-table--sticky-head .crewlet-data-table__table th.crewlet-data-table__th--sticky-right {
1541
+ background: var(
1542
+ --crewlet-data-table-sticky-header-bg,
1543
+ var(--crewlet-data-table-sticky-bg, var(--color-surface-elevated))
1544
+ );
1545
+ }
1546
+
1547
+ /* Sortable header. The button hosts the click target so the arrow icon
1548
+ is part of the same hit region as the label. */
1549
+ .crewlet-data-table--compact .crewlet-data-table__th--sortable {
1550
+ padding: 0 !important;
1551
+ }
1552
+
1553
+ .crewlet-data-table--compact .crewlet-data-table__sort-button {
1554
+ display: inline-flex;
1555
+ align-items: center;
1556
+ /*
1557
+ * Label on the left, sort arrow pinned to the right edge of the
1558
+ * column. justify-content: space-between with gap stretches the
1559
+ * row so the arrow always sits flush against the column boundary
1560
+ * regardless of label length. The flex behaviour also makes the
1561
+ * label and arrow share one hit region.
1562
+ */
1563
+ justify-content: space-between;
1564
+ gap: var(--spacing-2);
1565
+ width: 100%;
1566
+ padding: var(--crewlet-data-table-head-pad-y) var(--crewlet-data-table-cell-pad-x);
1567
+ background: transparent;
1568
+ border: 0;
1569
+ cursor: pointer;
1570
+ color: inherit;
1571
+ font: inherit;
1572
+ text-transform: inherit;
1573
+ letter-spacing: inherit;
1574
+ font-weight: inherit;
1575
+ text-align: left;
1576
+ }
1577
+
1578
+ .crewlet-data-table--compact .crewlet-data-table__sort-button > span:first-child {
1579
+ min-width: 0;
1580
+ overflow: hidden;
1581
+ text-overflow: ellipsis;
1582
+ }
1583
+
1584
+ .crewlet-data-table--compact .crewlet-data-table__sort-button .crewlet-glyph {
1585
+ flex-shrink: 0;
1586
+ margin-left: auto;
1587
+ }
1588
+
1589
+ /* One step up from the header's own ink, which is the lift this header has
1590
+ always taken: the column name brightens, it does not change register. */
1591
+ .crewlet-data-table--compact .crewlet-data-table__sort-button:hover {
1592
+ color: var(--color-text-secondary);
1593
+ }
1594
+
1595
+ /* The sort mark is quiet until this is the column being sorted by, and quiet
1596
+ is as far as it goes: it is the only thing that says a column CAN be
1597
+ sorted, so it stays a graphical object a reader can resolve. At 0.45 it
1598
+ measured 1.94:1 light and 2.32:1 dark against the header, under the 3:1
1599
+ floor; 0.7 clears it in both themes (3.03:1 and 3.66:1). */
1600
+ .crewlet-data-table--compact .crewlet-data-table__sort-button .crewlet-glyph {
1601
+ opacity: 0.7;
1602
+ }
1603
+
1604
+ .crewlet-data-table--compact .crewlet-data-table__th--sortable.is-active .crewlet-data-table__sort-button {
1605
+ color: var(--crewlet-data-table-active-sort-color);
1606
+ }
1607
+
1608
+ .crewlet-data-table--compact .crewlet-data-table__th--sortable.is-active .crewlet-data-table__sort-button .crewlet-glyph {
1609
+ opacity: 1;
1610
+ }
1611
+
1612
+ /*
1613
+ * Compact column resizer. Hovering reveals a soft accent strip so the
1614
+ * operator can find the handle without it cluttering the default header.
1615
+ * mousedown wiring is owned by the JSX; this rule just paints the
1616
+ * affordance and sets the resize cursor.
1617
+ */
1618
+ .crewlet-data-table__resizer {
1619
+ position: absolute;
1620
+ top: 0;
1621
+ bottom: 0;
1622
+ /*
1623
+ * 24px OF HIT AREA, INSIDE THE CELL. The handle used to be 16px straddling
1624
+ * the boundary, which is under the smallest target WCAG 2.2 accepts, and
1625
+ * the half that hung over the next column was clipped away by the header's
1626
+ * own `overflow: hidden` anyway, so what an operator could actually press
1627
+ * was the 8px inside. The line it paints stays on the boundary.
1628
+ */
1629
+ right: 0;
1630
+ width: 24px;
1631
+ cursor: col-resize;
1632
+ user-select: none;
1633
+ z-index: var(--z-index-raised);
1634
+ }
1635
+
1636
+ .crewlet-data-table__resizer::before {
1637
+ content: '';
1638
+ position: absolute;
1639
+ top: 4px;
1640
+ bottom: 4px;
1641
+ /* The boundary, which is the cell's own right edge: the hit area reaches
1642
+ back into the cell from here rather than either side of it. */
1643
+ right: 0;
1644
+ width: 2px;
1645
+ /*
1646
+ * The line is always painted and its COLOUR changes, rather than the hover
1647
+ * painting a background onto the pseudo element. A hover overlay on a
1648
+ * pseudo element is the one way to stack a hover on top of a state that
1649
+ * already owns the background, and the composite that produces is one
1650
+ * nothing has measured.
1651
+ */
1652
+ background: var(--crewlet-data-table-resizer-line, transparent);
1653
+ border-radius: var(--radius-xs);
1654
+ transition: background-color var(--motion-duration-base) ease;
1655
+ }
1656
+
1657
+ .crewlet-data-table__resizer:hover,
1658
+ .crewlet-data-table__resizer:active,
1659
+ .crewlet-data-table__resizer:focus-visible {
1660
+ --crewlet-data-table-resizer-line: var(--color-brand-accent);
1661
+ }
1662
+
1663
+ /* As above: the handle is transparent until something reaches it, so focus
1664
+ has to paint the line AND the ring. Inset, for the scroller. */
1665
+ .crewlet-data-table__resizer:focus-visible {
1666
+ outline: 2px solid var(--color-focus);
1667
+ outline-offset: var(--size-focus-ring-inset-offset);
1668
+ }
1669
+
1670
+ .crewlet-data-table--compact .crewlet-data-table__empty {
1671
+ padding: var(--spacing-6);
1672
+ text-align: center;
1673
+ color: var(--color-text-tertiary);
1674
+ font-size: var(--font-size-compact);
1675
+ }
1676
+
1677
+ /* Archived row treatment: a subdued tone plus a left edge rail so the row
1678
+ reads as "still here for context but not active". A host rebinds
1679
+ --crewlet-data-table-archived-rail to mark it some other way. */
1680
+ .crewlet-data-table--compact .crewlet-data-table__table tbody tr.crewlet-data-table__row--archived td {
1681
+ opacity: 0.55;
1682
+ background: var(--color-surface-inset);
1683
+ }
1684
+
1685
+ .crewlet-data-table--compact .crewlet-data-table__table tbody tr.crewlet-data-table__row--archived td:first-child {
1686
+ position: relative;
1687
+ }
1688
+
1689
+ .crewlet-data-table--compact .crewlet-data-table__table tbody tr.crewlet-data-table__row--archived td:first-child::before {
1690
+ content: '';
1691
+ position: absolute;
1692
+ top: 0;
1693
+ bottom: 0;
1694
+ left: 0;
1695
+ width: 2px;
1696
+ background: var(--crewlet-data-table-archived-rail);
1697
+ }
1698
+
1699
+ .crewlet-data-table--compact .crewlet-data-table__table tbody tr.crewlet-data-table__row--archived:hover td {
1700
+ opacity: 0.75;
1701
+ }
1702
+
1703
+ /* ─── Copyable cell affordance ─────────────────────────────────── */
1704
+ .crewlet-data-table__copy-cell {
1705
+ display: inline-flex;
1706
+ align-items: center;
1707
+ gap: var(--spacing-1);
1708
+ max-width: 100%;
1709
+ }
1710
+
1711
+ .crewlet-data-table__copy-cell-value {
1712
+ min-width: 0;
1713
+ overflow: hidden;
1714
+ text-overflow: ellipsis;
1715
+ white-space: nowrap;
1716
+ }
1717
+
1718
+ .crewlet-data-table__copy-cell-button {
1719
+ flex-shrink: 0;
1720
+ background: transparent;
1721
+ border: 1px solid transparent;
1722
+ border-radius: var(--radius-xs);
1723
+ /*
1724
+ * THE TARGET FLOOR, in both dimensions and at every density: 24px is the
1725
+ * smallest WCAG 2.2 accepts, and this is a hard value rather than a density
1726
+ * step because a control that shrinks with the rows shrinks through the
1727
+ * floor exactly where the rows are tightest.
1728
+ */
1729
+ width: 24px;
1730
+ height: 24px;
1731
+ padding: 0;
1732
+ display: inline-flex;
1733
+ align-items: center;
1734
+ justify-content: center;
1735
+ color: var(--color-text-tertiary);
1736
+ cursor: pointer;
1737
+ opacity: 0;
1738
+ transition: opacity var(--motion-duration-fast) var(--motion-easing-default), background var(--motion-duration-fast) var(--motion-easing-default), color var(--motion-duration-fast) var(--motion-easing-default), border-color var(--motion-duration-fast) var(--motion-easing-default);
1739
+ }
1740
+
1741
+
1742
+ /* Reveal the copy button when the parent row is hovered (compact tables
1743
+ only) or when the cell itself is hovered / focus-visible. The cell
1744
+ selector keeps the affordance reachable outside a table context too. */
1745
+ .crewlet-data-table--compact tbody tr:hover .crewlet-data-table__copy-cell-button,
1746
+ .crewlet-data-table__copy-cell-button:focus-visible,
1747
+ .crewlet-data-table__copy-cell:hover .crewlet-data-table__copy-cell-button {
1748
+ opacity: 1;
1749
+ }
1750
+
1751
+ /* The rule above only REVEALS it on focus. A ring is what says which control
1752
+ the keyboard is on, and an appearing button says only that one is there. */
1753
+ .crewlet-data-table__copy-cell-button:focus-visible {
1754
+ outline: 2px solid var(--color-focus);
1755
+ outline-offset: var(--size-focus-ring-inset-offset);
1756
+ }
1757
+
1758
+ .crewlet-data-table__copy-cell-button:hover {
1759
+ background: var(--color-brand-accent-soft);
1760
+ border-color: var(--color-brand-accent-soft-strong);
1761
+ color: var(--color-brand-accent-ink);
1762
+ }
1763
+
1764
+ .crewlet-data-table__copy-cell-button.is-copied {
1765
+ color: var(--color-brand-accent-ink);
1766
+ opacity: 1;
1767
+ }
1768
+
1769
+ /* ─── The sort control ────────────────────────────────────────────
1770
+ The default variant used to sort from a click handler on the cell, so it
1771
+ had no control to style. The button carries the header's own register and
1772
+ none of a button's chrome: it IS the header, and pressing it is the point. */
1773
+ .crewlet-data-table--default .crewlet-data-table__sort-button {
1774
+ width: 100%;
1775
+ padding: 0;
1776
+ background: transparent;
1777
+ border: 0;
1778
+ color: inherit;
1779
+ font: inherit;
1780
+ text-align: left;
1781
+ cursor: pointer;
1782
+ }
1783
+
1784
+ /* An OUTLINE, inset. Forced-colors mode drops every box-shadow and keeps
1785
+ outlines, and a header cell sits inside a scroller, where an outset ring is
1786
+ clipped by the edge. */
1787
+ .crewlet-data-table__sort-button:focus-visible {
1788
+ outline: 2px solid var(--color-focus);
1789
+ outline-offset: var(--size-focus-ring-inset-offset);
1790
+ }
1791
+
1792
+ /* ─── What a column's own shape does to its cells ─────────────────
1793
+ One rule pair for the header and the body, so a right-aligned column's
1794
+ header points at the edge its numbers line up on. Tabular figures come
1795
+ with the alignment rather than as a second opt-in: a column of numbers
1796
+ whose digits change width is a column that jiggles on every push. */
1797
+ .crewlet-data-table__table th.crewlet-data-table__cell--right,
1798
+ .crewlet-data-table__table td.crewlet-data-table__cell--right {
1799
+ text-align: right;
1800
+ font-variant-numeric: tabular-nums;
1801
+ white-space: nowrap;
1802
+ }
1803
+
1804
+ .crewlet-data-table__table th.crewlet-data-table__cell--right .crewlet-data-table__sort-button {
1805
+ /* The button fills the cell, so the label sits at the aligned edge. */
1806
+ width: 100%;
1807
+ justify-content: flex-end;
1808
+ }
1809
+
1810
+ .crewlet-data-table__table th.crewlet-data-table__cell--center,
1811
+ .crewlet-data-table__table td.crewlet-data-table__cell--center {
1812
+ text-align: center;
1813
+ }
1814
+
1815
+ /* A shrink column is as wide as its content: a status chip, a short id, a
1816
+ count. The 1% is the standard table idiom for "as narrow as you can". */
1817
+ .crewlet-data-table__table th.crewlet-data-table__cell--shrink,
1818
+ .crewlet-data-table__table td.crewlet-data-table__cell--shrink {
1819
+ width: 1%;
1820
+ white-space: nowrap;
1821
+ }
1822
+
1823
+ .crewlet-data-table__table td.crewlet-data-table__cell--mono {
1824
+ font-family: var(--font-family-mono);
1825
+ font-size: var(--font-size-2xs);
1826
+ }
1827
+
1828
+ /* ─── A row that navigates ────────────────────────────────────────
1829
+ A REAL LINK, stretched over the row. The anchor lives in the leading
1830
+ cell and its ::after covers the row, so the row can be opened in a new
1831
+ tab, its address copied, and read as the link it is, with ONE tab stop.
1832
+ Everything interactive in the row sits above the overlay, so a chip is
1833
+ still its own press. */
1834
+ .crewlet-data-table__table tbody tr {
1835
+ position: relative;
1836
+ }
1837
+
1838
+ .crewlet-data-table__row-link::after {
1839
+ content: '';
1840
+ position: absolute;
1841
+ inset: 0;
1842
+ }
1843
+
1844
+ .crewlet-data-table__table tbody tr a:not(.crewlet-data-table__row-link),
1845
+ .crewlet-data-table__table tbody tr button,
1846
+ .crewlet-data-table__table tbody tr input,
1847
+ .crewlet-data-table__table tbody tr select {
1848
+ position: relative;
1849
+ z-index: 1;
1850
+ }
1851
+
1852
+ .crewlet-data-table__row-link:focus-visible::after {
1853
+ outline: 2px solid var(--color-focus);
1854
+ /* Inset: the row sits in a scroller, where an outset ring is clipped by
1855
+ the edge and painted over by the row below it. */
1856
+ outline-offset: var(--size-focus-ring-inset-offset);
1857
+ }
1858
+
1859
+ /* ─── The last row ────────────────────────────────────────────────
1860
+ THE LAST ROW KEEPS ITS RULE, because a table standing on the page has
1861
+ nothing else to close it and stops mid-air without one. It is dropped where
1862
+ something else already closes the list: inside a panel, where the line
1863
+ landed a hairline in from the panel's own edge and straight on top of the
1864
+ count row's border-top, so the list ended on a doubled two-pixel rule. That
1865
+ suppression belongs to the panel and is written where the panel is, in
1866
+ DataView's own sheet. */
1867
+
1868
+ /* ─── A row that is a state, and a row that is the one selected ───
1869
+ The rail is a mark rather than a fill: a tinted row reads as selected,
1870
+ and only one thing in a table may mean "here". The word beside it is in
1871
+ the markup, because the rail is colour and colour is never alone.
1872
+
1873
+ THE INK STEP, NOT THE FILL. The fill step is measured to 3:1 against the
1874
+ OPAQUE surfaces, and a row is not always one of those: on the accent tint a
1875
+ selected row carries, the danger fill measured 2.86:1 in dark on a card and
1876
+ 2.65:1 on the elevated step, so the one row in the table that is both the
1877
+ reader's and broken was the one whose mark could not be seen. The other two
1878
+ tones cleared the floor there (the tightest is the warning fill at 3.58:1)
1879
+ and move with it anyway: which tone a row carries is not a reason for its
1880
+ rail to be drawn to a different floor. Every ink step already clears 4.5:1
1881
+ on every composite a row can have, the selection tint included, and it is
1882
+ the same hue read louder. @crewlethq/tokens measures all three on every
1883
+ ground a row can have; the tightest is 5.05:1. */
1884
+ .crewlet-data-table__table tbody tr.crewlet-data-table__row--tone-danger td:first-child {
1885
+ box-shadow: inset 2px 0 0 var(--color-feedback-danger-ink);
1886
+ }
1887
+
1888
+ .crewlet-data-table__table tbody tr.crewlet-data-table__row--tone-warning td:first-child {
1889
+ box-shadow: inset 2px 0 0 var(--color-feedback-warning-ink);
1890
+ }
1891
+
1892
+ .crewlet-data-table__table tbody tr.crewlet-data-table__row--tone-info td:first-child {
1893
+ box-shadow: inset 2px 0 0 var(--color-feedback-info-ink);
1894
+ }
1895
+
1896
+ /*
1897
+ * THE SELECTED ROW IS THE TINT, AND ONLY THE TINT.
1898
+ *
1899
+ * It used to be the tint AND a two-pixel accent ring drawn round the row, which
1900
+ * is the mark a selected CARD takes: on a table it boxed one row out of a run
1901
+ * of hairline rows and read as a row that had been lifted out of the list
1902
+ * rather than as the row a reader is on. The tint alone is what every table in
1903
+ * the product draws, and @crewlethq/tokens' "the selected tint outreads the
1904
+ * hover overlay" rule is what holds it apart from a hovered row: the two are
1905
+ * a step apart in LUMINANCE and a distance apart in colour, which is the
1906
+ * measure that matters for two fills side by side.
1907
+ *
1908
+ * On the cells rather than on the row: the table collapses its borders, so a
1909
+ * background on the tr is painted under cells that have one of their own.
1910
+ */
1911
+ .crewlet-data-table__table tbody tr.crewlet-data-table__row--selected td {
1912
+ background: var(--color-brand-accent-soft);
1913
+ }
1914
+
1915
+ /* ─── The per-row expand control ──────────────────────────────────
1916
+ A button carrying its own aria-expanded, where the chevron used to be an
1917
+ `aria-hidden` glyph beside a row that took the click: the affordance a
1918
+ reader could see was the one thing they could not reach.
1919
+
1920
+ IT IS THE DRAWING AND NOTHING MORE, because this cell sets the height of
1921
+ every row in the table. Painted at the control step it added ten pixels to
1922
+ each one, which on a list of forty rows is four hundred pixels of a screen
1923
+ spent on a chevron. The pressable area is the ::after above, at the 24px
1924
+ floor, reaching into the cell's own padding. */
1925
+ .crewlet-data-table__expand-btn {
1926
+ position: relative;
1927
+ display: inline-flex;
1928
+ align-items: center;
1929
+ justify-content: center;
1930
+ width: var(--font-size-lg);
1931
+ height: var(--font-size-lg);
1932
+ padding: 0;
1933
+ background: none;
1934
+ border: none;
1935
+ border-radius: var(--radius-xs);
1936
+ color: var(--color-text-tertiary);
1937
+ cursor: pointer;
1938
+ }
1939
+
1940
+ /* The colour alone, because a filled box the size of the glyph is not a halo,
1941
+ it is a swatch behind a chevron. The row's own tint is what says which row
1942
+ the pointer is on. */
1943
+ .crewlet-data-table__expand-btn:hover {
1944
+ color: var(--color-text-primary);
1945
+ }
1946
+
1947
+ /* Its ring is drawn with the expand-all button's, for the reason given there:
1948
+ these two boxes are the chevron itself, so an inset ring lands on the glyph.
1949
+ Written once for both rather than twice, a step apart. */
1950
+
1951
+ /* ─── The settings frame's column list ────────────────────────── */
1952
+ .crewlet-data-table__column-toggle-actions {
1953
+ display: inline-flex;
1954
+ align-items: center;
1955
+ gap: var(--spacing-1);
1956
+ margin-left: auto;
1957
+ }
1958
+
1959
+ /* ─── The end of the rows ─────────────────────────────────────── */
1960
+ .crewlet-data-table__end {
1961
+ margin: 0;
1962
+ padding: var(--spacing-3);
1963
+ text-align: center;
1964
+ font-size: var(--font-size-compact);
1965
+ color: var(--color-text-tertiary);
1966
+ }
1967
+
1968
+ /* ─── Reduced motion ──────────────────────────────────────────────
1969
+ The component states its own, rather than leaning on the document
1970
+ baseline: this stylesheet also ships to an application that imports the
1971
+ component and not the baseline. The skeleton stops PULSING and keeps its
1972
+ bars, which is what says the rows have not arrived.
1973
+
1974
+ THE SETTINGS FRAME IS NAMED SEPARATELY BECAUSE IT IS NOT IN THE TABLE. It
1975
+ is a Modal, which portals onto the layer host, so a descendant selector
1976
+ rooted at .crewlet-data-table reaches none of it: the chip row and every
1977
+ column row kept their transitions under the preference in exactly the
1978
+ application this rule exists for. */
1979
+ /*
1980
+ * EVERY PART OF THE TABLE, INCLUDING THE ONES DRAWN SOMEWHERE ELSE. The list
1981
+ * is not the root and its descendants: two of these live in the settings
1982
+ * frame, which is a dialog portaled to the layer host, and the chrome row is
1983
+ * drawn on a card's header wherever the table fills one. A preference
1984
+ * cancelled through the root alone leaves exactly those pieces animating,
1985
+ * which is the one place a reader who asked for stillness is least able to
1986
+ * connect it back to a table.
1987
+ */
1988
+ @media (prefers-reduced-motion: reduce) {
1989
+ /*
1990
+ * EACH NAME IS WRITTEN TWICE, which is not a typo: a selector repeating one
1991
+ * class matches exactly what it matched and counts for twice as much. A
1992
+ * cancellation is only a cancellation if it outranks what it cancels, and
1993
+ * this one did not: written once, `.crewlet-data-table *` is one class where
1994
+ * the rules it had to beat are two, so the row hover, the sort control, the
1995
+ * action button and the pager and cog all kept their transitions for a
1996
+ * reader who had asked for stillness. The document-wide rule in
1997
+ * @crewlethq/tokens covered it with `!important` wherever that sheet is
1998
+ * loaded, which is the only reason nobody saw it; this rule exists for the
1999
+ * document that loads the components alone, and it has to stand on its own.
2000
+ */
2001
+ .crewlet-data-table.crewlet-data-table,
2002
+ .crewlet-data-table.crewlet-data-table *,
2003
+ .crewlet-data-table.crewlet-data-table *::before,
2004
+ .crewlet-data-table.crewlet-data-table *::after,
2005
+ .crewlet-data-table__chrome.crewlet-data-table__chrome,
2006
+ .crewlet-data-table__chrome.crewlet-data-table__chrome *,
2007
+ .crewlet-data-table__chrome.crewlet-data-table__chrome *::before,
2008
+ .crewlet-data-table__chrome.crewlet-data-table__chrome *::after,
2009
+ .crewlet-data-table__items-per-page-btn.crewlet-data-table__items-per-page-btn,
2010
+ .crewlet-data-table__column-toggle-item.crewlet-data-table__column-toggle-item {
2011
+ animation: none;
2012
+ transition: none;
2013
+ }
2014
+
2015
+ /* The bars stay; only the pulse goes. A skeleton that vanished under a
2016
+ motion preference would take the answer to "has this loaded" with it. */
2017
+ .crewlet-data-table__skeleton-bar {
2018
+ opacity: 0.6;
2019
+ }
2020
+ }