@crisp-ui-kit/crisp 0.57.1 → 0.57.2

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 (252) hide show
  1. package/dist/authshell.css +9 -4
  2. package/dist/authshell.layered.css +9 -4
  3. package/dist/badge.css +3 -3
  4. package/dist/badge.layered.css +3 -3
  5. package/dist/board.css +28 -8
  6. package/dist/board.layered.css +28 -8
  7. package/dist/bottomsheet.css +26 -0
  8. package/dist/bottomsheet.d.ts +7 -0
  9. package/dist/bottomsheet.layered.css +28 -0
  10. package/dist/button.css +7 -6
  11. package/dist/button.layered.css +7 -6
  12. package/dist/checkbox.css +7 -3
  13. package/dist/checkbox.layered.css +7 -3
  14. package/dist/chip.css +15 -0
  15. package/dist/chip.d.ts +3 -1
  16. package/dist/chip.layered.css +15 -0
  17. package/dist/chipgroup.css +5 -0
  18. package/dist/chipgroup.d.ts +7 -0
  19. package/dist/chipgroup.layered.css +7 -0
  20. package/dist/cjs/components/badge/badge.recipe.js +22 -8
  21. package/dist/cjs/components/bottomsheet/bottomsheet.js +90 -0
  22. package/dist/cjs/components/bottomsheet/bottomsheet.recipe.js +77 -0
  23. package/dist/cjs/components/bottomsheet/index.js +9 -0
  24. package/dist/cjs/components/button/button.recipe.js +39 -15
  25. package/dist/cjs/components/checkbox/checkbox.recipe.js +61 -9
  26. package/dist/cjs/components/chip/chip.js +14 -2
  27. package/dist/cjs/components/chip/chip.recipe.js +69 -1
  28. package/dist/cjs/components/chipgroup/chipgroup.js +51 -0
  29. package/dist/cjs/components/chipgroup/chipgroup.recipe.js +36 -0
  30. package/dist/cjs/components/chipgroup/index.js +7 -0
  31. package/dist/cjs/components/datatable/datatable.js +5 -1
  32. package/dist/cjs/components/datatable/datatable.recipe.js +11 -2
  33. package/dist/cjs/components/dialog/dialog.recipe.js +21 -10
  34. package/dist/cjs/components/emptystate/emptystate.recipe.js +7 -2
  35. package/dist/cjs/components/fileupload/fileupload.js +21 -4
  36. package/dist/cjs/components/input/index.js +2 -1
  37. package/dist/cjs/components/input/input.js +31 -1
  38. package/dist/cjs/components/input/input.recipe.js +16 -9
  39. package/dist/cjs/components/menu/menu.recipe.js +21 -7
  40. package/dist/cjs/components/menusheet/index.js +9 -0
  41. package/dist/cjs/components/menusheet/menusheet.js +133 -0
  42. package/dist/cjs/components/menusheet/menusheet.recipe.js +103 -0
  43. package/dist/cjs/components/multiselect/multiselect.js +1 -1
  44. package/dist/cjs/components/multiselect/multiselect.recipe.js +33 -9
  45. package/dist/cjs/components/select/select.js +1 -1
  46. package/dist/cjs/components/select/select.recipe.js +38 -12
  47. package/dist/cjs/components/snackbar/index.js +8 -0
  48. package/dist/cjs/components/snackbar/snackbar.js +121 -0
  49. package/dist/cjs/components/snackbar/snackbar.recipe.js +71 -0
  50. package/dist/cjs/components/tabletoolbar/tabletoolbar.chrome.js +7 -2
  51. package/dist/cjs/components/tabletoolbar/tabletoolbar.js +37 -12
  52. package/dist/cjs/components/tabs/tabs.js +10 -4
  53. package/dist/cjs/components/tabs/tabs.recipe.js +23 -6
  54. package/dist/cjs/components/textarea/textarea.recipe.js +11 -8
  55. package/dist/cjs/index.js +7 -0
  56. package/dist/cjs/product/authshell/authshell.recipe.js +5 -1
  57. package/dist/cjs/product/command/command.recipe.js +4 -1
  58. package/dist/cjs/product/comments/comments.js +7 -2
  59. package/dist/cjs/product/comments/comments.recipe.js +25 -7
  60. package/dist/cjs/product/memberssettings/index.js +6 -0
  61. package/dist/cjs/product/memberssettings/memberssettings.js +99 -0
  62. package/dist/cjs/product/memberssettings/memberssettings.recipe.js +83 -0
  63. package/dist/cjs/product/notificationssettings/index.js +5 -0
  64. package/dist/cjs/product/notificationssettings/notificationssettings.js +19 -0
  65. package/dist/cjs/product/notificationssettings/notificationssettings.recipe.js +44 -0
  66. package/dist/cjs/product/recordpage/recordpage.js +57 -6
  67. package/dist/cjs/product/recordpage/recordpage.recipe.js +43 -6
  68. package/dist/cjs/product/workspacegeneralsettings/index.js +5 -0
  69. package/dist/cjs/product/workspacegeneralsettings/workspacegeneralsettings.js +21 -0
  70. package/dist/cjs/product/workspacegeneralsettings/workspacegeneralsettings.recipe.js +51 -0
  71. package/dist/cjs/tokens/contract.js +1 -0
  72. package/dist/cjs/tokens/elevation.js +8 -5
  73. package/dist/cjs/tokens/palette.js +28 -8
  74. package/dist/cjs/tokens/scale.js +44 -2
  75. package/dist/cjs/tokens/semantic.js +2 -0
  76. package/dist/columncalc.css +15 -7
  77. package/dist/columncalc.layered.css +15 -7
  78. package/dist/command.css +23 -19
  79. package/dist/command.layered.css +23 -19
  80. package/dist/comments.css +28 -19
  81. package/dist/comments.d.ts +2 -2
  82. package/dist/comments.layered.css +28 -19
  83. package/dist/datatable.css +161 -67
  84. package/dist/datatable.layered.css +161 -67
  85. package/dist/datepicker.css +13 -41
  86. package/dist/datepicker.layered.css +13 -41
  87. package/dist/datepickerfield.css +4 -1
  88. package/dist/datepickerfield.layered.css +4 -1
  89. package/dist/dialog.css +12 -7
  90. package/dist/dialog.layered.css +12 -7
  91. package/dist/emptystate.css +5 -3
  92. package/dist/emptystate.layered.css +5 -3
  93. package/dist/esm/components/badge/badge.recipe.js +22 -8
  94. package/dist/esm/components/bottomsheet/bottomsheet.js +52 -0
  95. package/dist/esm/components/bottomsheet/bottomsheet.recipe.js +74 -0
  96. package/dist/esm/components/bottomsheet/index.js +2 -0
  97. package/dist/esm/components/button/button.recipe.js +40 -16
  98. package/dist/esm/components/checkbox/checkbox.recipe.js +61 -9
  99. package/dist/esm/components/chip/chip.js +14 -2
  100. package/dist/esm/components/chip/chip.recipe.js +69 -1
  101. package/dist/esm/components/chipgroup/chipgroup.js +15 -0
  102. package/dist/esm/components/chipgroup/chipgroup.recipe.js +33 -0
  103. package/dist/esm/components/chipgroup/index.js +2 -0
  104. package/dist/esm/components/datatable/datatable.js +5 -1
  105. package/dist/esm/components/datatable/datatable.recipe.js +11 -2
  106. package/dist/esm/components/dialog/dialog.recipe.js +22 -11
  107. package/dist/esm/components/emptystate/emptystate.recipe.js +7 -2
  108. package/dist/esm/components/fileupload/fileupload.js +20 -5
  109. package/dist/esm/components/input/index.js +1 -1
  110. package/dist/esm/components/input/input.js +30 -0
  111. package/dist/esm/components/input/input.recipe.js +17 -10
  112. package/dist/esm/components/menu/menu.recipe.js +21 -7
  113. package/dist/esm/components/menusheet/index.js +2 -0
  114. package/dist/esm/components/menusheet/menusheet.js +95 -0
  115. package/dist/esm/components/menusheet/menusheet.recipe.js +100 -0
  116. package/dist/esm/components/multiselect/multiselect.js +1 -1
  117. package/dist/esm/components/multiselect/multiselect.recipe.js +33 -9
  118. package/dist/esm/components/select/select.js +1 -1
  119. package/dist/esm/components/select/select.recipe.js +38 -12
  120. package/dist/esm/components/snackbar/index.js +2 -0
  121. package/dist/esm/components/snackbar/snackbar.js +84 -0
  122. package/dist/esm/components/snackbar/snackbar.recipe.js +68 -0
  123. package/dist/esm/components/tabletoolbar/tabletoolbar.chrome.js +7 -2
  124. package/dist/esm/components/tabletoolbar/tabletoolbar.js +37 -12
  125. package/dist/esm/components/tabs/tabs.js +10 -4
  126. package/dist/esm/components/tabs/tabs.recipe.js +23 -6
  127. package/dist/esm/components/textarea/textarea.recipe.js +12 -9
  128. package/dist/esm/index.js +7 -0
  129. package/dist/esm/product/authshell/authshell.recipe.js +5 -1
  130. package/dist/esm/product/command/command.recipe.js +4 -1
  131. package/dist/esm/product/comments/comments.js +7 -2
  132. package/dist/esm/product/comments/comments.recipe.js +25 -7
  133. package/dist/esm/product/memberssettings/index.js +1 -0
  134. package/dist/esm/product/memberssettings/memberssettings.js +62 -0
  135. package/dist/esm/product/memberssettings/memberssettings.recipe.js +80 -0
  136. package/dist/esm/product/notificationssettings/index.js +1 -0
  137. package/dist/esm/product/notificationssettings/notificationssettings.js +16 -0
  138. package/dist/esm/product/notificationssettings/notificationssettings.recipe.js +41 -0
  139. package/dist/esm/product/recordpage/recordpage.js +58 -7
  140. package/dist/esm/product/recordpage/recordpage.recipe.js +43 -6
  141. package/dist/esm/product/workspacegeneralsettings/index.js +1 -0
  142. package/dist/esm/product/workspacegeneralsettings/workspacegeneralsettings.js +18 -0
  143. package/dist/esm/product/workspacegeneralsettings/workspacegeneralsettings.recipe.js +48 -0
  144. package/dist/esm/tokens/contract.js +2 -1
  145. package/dist/esm/tokens/elevation.js +8 -5
  146. package/dist/esm/tokens/palette.js +28 -8
  147. package/dist/esm/tokens/scale.js +43 -1
  148. package/dist/esm/tokens/semantic.js +2 -0
  149. package/dist/fileupload.css +3 -1
  150. package/dist/fileupload.layered.css +3 -1
  151. package/dist/input.css +6 -4
  152. package/dist/input.layered.css +6 -4
  153. package/dist/listpage.css +3 -1
  154. package/dist/listpage.layered.css +3 -1
  155. package/dist/memberssettings.css +67 -0
  156. package/dist/memberssettings.d.ts +7 -0
  157. package/dist/memberssettings.layered.css +69 -0
  158. package/dist/menu.css +2 -2
  159. package/dist/menu.layered.css +2 -2
  160. package/dist/menusheet.css +36 -0
  161. package/dist/menusheet.d.ts +7 -0
  162. package/dist/menusheet.layered.css +38 -0
  163. package/dist/multiselect.css +13 -6
  164. package/dist/multiselect.layered.css +13 -6
  165. package/dist/native/tokens.d.ts +2 -1
  166. package/dist/native/tokens.js +20 -3
  167. package/dist/notificationssettings.css +22 -0
  168. package/dist/notificationssettings.d.ts +7 -0
  169. package/dist/notificationssettings.layered.css +24 -0
  170. package/dist/objectsettings.css +4 -4
  171. package/dist/objectsettings.layered.css +4 -4
  172. package/dist/recordpage.css +67 -23
  173. package/dist/recordpage.layered.css +67 -23
  174. package/dist/recordpanel.css +35 -16
  175. package/dist/recordpanel.layered.css +35 -16
  176. package/dist/resizablepanel.css +8 -5
  177. package/dist/resizablepanel.layered.css +8 -5
  178. package/dist/richtext.css +24 -8
  179. package/dist/richtext.layered.css +24 -8
  180. package/dist/savedviews.css +9 -2
  181. package/dist/savedviews.layered.css +9 -2
  182. package/dist/select.css +25 -5
  183. package/dist/select.layered.css +25 -5
  184. package/dist/settingsshell.css +2 -3
  185. package/dist/settingsshell.layered.css +2 -3
  186. package/dist/slider.css +6 -27
  187. package/dist/slider.layered.css +6 -27
  188. package/dist/snackbar.css +24 -0
  189. package/dist/snackbar.d.ts +7 -0
  190. package/dist/snackbar.layered.css +26 -0
  191. package/dist/statcard.css +3 -1
  192. package/dist/statcard.layered.css +3 -1
  193. package/dist/styles.css +859 -345
  194. package/dist/styles.layered.css +859 -345
  195. package/dist/table.css +28 -10
  196. package/dist/table.layered.css +28 -10
  197. package/dist/tabletoolbar.css +35 -24
  198. package/dist/tabletoolbar.layered.css +35 -24
  199. package/dist/tabs.css +18 -4
  200. package/dist/tabs.layered.css +18 -4
  201. package/dist/textarea.css +2 -6
  202. package/dist/textarea.layered.css +2 -6
  203. package/dist/themepicker.css +2 -1
  204. package/dist/themepicker.layered.css +2 -1
  205. package/dist/tokens.css +13 -2
  206. package/dist/tokens.json +20 -3
  207. package/dist/types/components/bottomsheet/bottomsheet.d.ts +35 -0
  208. package/dist/types/components/bottomsheet/bottomsheet.recipe.d.ts +3 -0
  209. package/dist/types/components/bottomsheet/index.d.ts +2 -0
  210. package/dist/types/components/button/button.recipe.d.ts +11 -6
  211. package/dist/types/components/checkbox/checkbox.recipe.d.ts +28 -5
  212. package/dist/types/components/chip/chip.d.ts +22 -0
  213. package/dist/types/components/chip/chip.recipe.d.ts +48 -0
  214. package/dist/types/components/chipgroup/chipgroup.d.ts +14 -0
  215. package/dist/types/components/chipgroup/chipgroup.recipe.d.ts +5 -0
  216. package/dist/types/components/chipgroup/index.d.ts +2 -0
  217. package/dist/types/components/datatable/datatable.d.ts +19 -0
  218. package/dist/types/components/fileupload/fileupload.d.ts +26 -0
  219. package/dist/types/components/input/index.d.ts +1 -1
  220. package/dist/types/components/input/input.d.ts +72 -0
  221. package/dist/types/components/menusheet/index.d.ts +2 -0
  222. package/dist/types/components/menusheet/menusheet.d.ts +42 -0
  223. package/dist/types/components/menusheet/menusheet.recipe.d.ts +3 -0
  224. package/dist/types/components/snackbar/index.d.ts +2 -0
  225. package/dist/types/components/snackbar/snackbar.d.ts +36 -0
  226. package/dist/types/components/snackbar/snackbar.recipe.d.ts +5 -0
  227. package/dist/types/components/tabletoolbar/tabletoolbar.d.ts +28 -1
  228. package/dist/types/components/tabs/tabs.d.ts +11 -1
  229. package/dist/types/index.d.ts +7 -0
  230. package/dist/types/product/comments/comments.d.ts +9 -3
  231. package/dist/types/product/comments/comments.recipe.d.ts +12 -2
  232. package/dist/types/product/memberssettings/index.d.ts +1 -0
  233. package/dist/types/product/memberssettings/memberssettings.d.ts +85 -0
  234. package/dist/types/product/memberssettings/memberssettings.recipe.d.ts +3 -0
  235. package/dist/types/product/notificationssettings/index.d.ts +1 -0
  236. package/dist/types/product/notificationssettings/notificationssettings.d.ts +37 -0
  237. package/dist/types/product/notificationssettings/notificationssettings.recipe.d.ts +3 -0
  238. package/dist/types/product/recordpage/recordpage.d.ts +53 -2
  239. package/dist/types/product/workspacegeneralsettings/index.d.ts +1 -0
  240. package/dist/types/product/workspacegeneralsettings/workspacegeneralsettings.d.ts +48 -0
  241. package/dist/types/product/workspacegeneralsettings/workspacegeneralsettings.recipe.d.ts +3 -0
  242. package/dist/types/tokens/contract.d.ts +4 -1
  243. package/dist/types/tokens/elevation.d.ts +8 -5
  244. package/dist/types/tokens/palette.d.ts +9 -1
  245. package/dist/types/tokens/scale.d.ts +11 -1
  246. package/dist/types/tokens/semantic.d.ts +2 -0
  247. package/dist/wheelpicker.css +4 -2
  248. package/dist/wheelpicker.layered.css +4 -2
  249. package/dist/workspacegeneralsettings.css +30 -0
  250. package/dist/workspacegeneralsettings.d.ts +7 -0
  251. package/dist/workspacegeneralsettings.layered.css +32 -0
  252. package/package.json +36 -1
@@ -1,8 +1,12 @@
1
1
  @layer crisp-components {
2
2
  .crisp-datatable {
3
- display: flex; flex-direction: column; gap: var(--crisp-space-2-5); font-family: var(--crisp-font-sans); /* The toolbar carried no horizontal inset of its own, so its content (search box, sort/filter chips) sat flush at the table's outer edge
4
- (x=0) while the header row's own th/td padding (table.recipe.ts, #465) starts every column's text at 12px -- one row down, the SAME
5
- grid's own header cell already begins at that inset. c.space["3"] here just matches the row directly below it, measured live against Attio (the sort/filter row's search chip lines up with the first
3
+ display: flex; flex-direction: column; gap: var(--crisp-space-2-5); font-family: var(--crisp-font-sans); /* The toolbar carried no horizontal inset of its own, so its content
4
+ (search box, sort/filter chips) sat flush at the table's outer edge
5
+ (x=0) while the header row's own th/td padding (table.recipe.ts,
6
+ #465) starts every column's text at 12px -- one row down, the SAME
7
+ grid's own header cell already begins at that inset. c.space["3"]
8
+ here just matches the row directly below it, measured live against
9
+ Attio (the sort/filter row's search chip lines up with the first
6
10
  column header's text, not the grid's raw edge). */
7
11
  & .crisp-datatable-toolbar { display: flex; align-items: center; gap: var(--crisp-space-2); min-height: 49px; border-top: 1px solid var(--crisp-border-subtle); padding: 0 var(--crisp-space-3); }
8
12
  & .crisp-datatable-search { position: relative; flex: 1; max-width: 280px; display: inline-flex; align-items: center; }
@@ -12,10 +16,7 @@
12
16
  & .crisp-datatable-search input:focus { box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); }
13
17
  & .crisp-datatable-count { margin-inline-start: auto; font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); }
14
18
  /* announced, never drawn */
15
- & .crisp-datatable-live {
16
- position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
17
- overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
18
- }
19
+ & .crisp-datatable-live { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
19
20
  /* crisp/#645: visually-hidden-but-focusable, not visually-hidden-and-
20
21
  inert like .crisp-datatable-live above -- same clip-rect shape,
21
22
  this one just needs to actually hold DOM focus so a native
@@ -23,7 +24,8 @@
23
24
  in datatable.tsx). resize: none keeps a stray native textarea handle
24
25
  from ever being drawable, even though it's clipped to 1px anyway. */
25
26
  & .crisp-datatable-clipboard-proxy { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; resize: none; }
26
- /* single active cell (crisp/#645 follow-up -- this had no styling of its own at all before, a gap against Golden Rule 0: RecordsTable's own
27
+ /* single active cell (crisp/#645 follow-up -- this had no styling of its
28
+ own at all before, a gap against Golden Rule 0: RecordsTable's own
27
29
  measured value, .crisp-recordstable-td[data-selected], brought
28
30
  across unchanged now that a visible anchor actually matters for the
29
31
  Shift+Click range below). */
@@ -32,57 +34,85 @@
32
34
  tint formula already used twice below (tbody tr[data-selected] td)
33
35
  for the same reason a selected group of rows gets one: a selected
34
36
  GROUP of cells is the same kind of state, just cell-scoped instead of
35
- row-scoped. Not independently re-measured against Attio's own range highlight (out of scope this slice -- flagged on crisp#645). */
37
+ row-scoped. Not independently re-measured against Attio's own range
38
+ highlight (out of scope this slice -- flagged on crisp#645). */
36
39
  & td[data-in-range] { background: color-mix(in srgb, var(--crisp-bg-brand-solid) 10%, var(--crisp-bg-surface)); }
37
- /* The header cell has no padding of its own -- the button owns the full cell so the whole header is clickable (its own inset is 12px). Mirrors the summary-row fix. `& .crisp-table th`, not bare `& th` (found while re-checking #691's
40
+ /* The header cell has no padding of its own -- the button owns the
41
+ full cell so the whole header is clickable (its own inset is 12px).
42
+ Mirrors the summary-row fix.
43
+ `& .crisp-table th`, not bare `& th` (found while re-checking #691's
38
44
  own fix live): DataTable's root nests `Table`'s own wrapper, whose
39
45
  `table.recipe.ts` carries `& th, & td { padding: 0 12px }` at the
40
46
  SAME specificity (.crisp-table th vs .crisp-datatable th, both one
41
47
  class + one element) -- a bare `& th` here only won by source
42
- order, which flipped the moment table.recipe.ts's own CSS file happened to land after datatable's in the build (alphabetical:
48
+ order, which flipped the moment table.recipe.ts's own CSS file
49
+ happened to land after datatable's in the build (alphabetical:
43
50
  datatable < table), silently reinstating 12px on every header cell
44
- in the whole product and making every interactive column's button double it to 24px. Scoping through `.crisp-table` adds a second class to the selector (0,2,1 beats 0,1,1) so this can never lose a specificity tie to source order again. `thead th`, not a bare `th` (crisp#829): #779 made the primary column's BODY cell a real `<th scope="row">` for a11y, and a bare
51
+ in the whole product and making every interactive column's button
52
+ double it to 24px. Scoping through `.crisp-table` adds a second
53
+ class to the selector (0,2,1 beats 0,1,1) so this can never lose a
54
+ specificity tie to source order again.
55
+ `thead th`, not a bare `th` (crisp#829): #779 made the primary
56
+ column's BODY cell a real `<th scope="row">` for a11y, and a bare
45
57
  `th` here matches that one too, zeroing an inset nothing else
46
58
  supplies -- the primary column's text sat flush left, one column's
47
59
  cell no longer matching its own header or any sibling `<td>`. Only
48
- the header row's own `<th>` needs zero padding (its sort BUTTON owns the inset); the body row's `<th scope="row">` has no button,
60
+ the header row's own `<th>` needs zero padding (its sort BUTTON
61
+ owns the inset); the body row's `<th scope="row">` has no button,
49
62
  and needs the SAME base 12px (table.recipe.ts, #465) every other
50
63
  cell already gets. */
51
64
  & .crisp-table thead th { padding: 0; }
52
- /* Same wrapper trap as AUTHORING.md Lesson 40 (ColumnCalc's summary trigger): Menu wraps its trigger in a flex div that sizes to its content, so a long header grew past the column instead of filling it -- with nothing left to squeeze, the label's own ellipsis CSS (below) had no properly
53
- -sized box to truncate against, and the th's own overflow hard-clipped it with no "...". Fill the wrapper, scoped to th so Menu's default
65
+ /* Same wrapper trap as AUTHORING.md Lesson 40 (ColumnCalc's summary trigger):
66
+ Menu wraps its trigger in a flex div that sizes to its content, so a
67
+ long header grew past the column instead of filling it -- with nothing
68
+ left to squeeze, the label's own ellipsis CSS (below) had no properly
69
+ -sized box to truncate against, and the th's own overflow hard-clipped
70
+ it with no "...". Fill the wrapper, scoped to th so Menu's default
54
71
  (correct everywhere else) is untouched. */
55
72
  & th .crisp-menu { width: 100%; height: 100%; }
56
73
  & .crisp-datatable-th-inner { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); width: 100%; min-width: 0; height: 100%; }
57
74
  & .crisp-datatable-th-inner > svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
58
75
  /* crisp/#605 follow-up: a header with neither a Menu nor a sort button
59
- (the primary/entity column's now-inert path, or any column with no columnMenu/sortable at all) renders .crisp-datatable-th-inner as a DIRECT child of th instead of nested inside a button -- and loses the button's own 12px inset, drifting left of the td's 12px base inset. Measured live on Attio's own Companies grid: the header label
60
- and the cell's own text land at the exact same x (335px from the viewport, both 40px from the column's left edge) via two different
76
+ (the primary/entity column's now-inert path, or any column with no
77
+ columnMenu/sortable at all) renders .crisp-datatable-th-inner as a
78
+ DIRECT child of th instead of nested inside a button -- and loses
79
+ the button's own 12px inset, drifting left of the td's 12px base
80
+ inset. Measured live on Attio's own Companies grid: the header label
81
+ and the cell's own text land at the exact same x (335px from the
82
+ viewport, both 40px from the column's left edge) via two different
61
83
  padding+icon+gap combinations -- Attio does not leave the inert
62
84
  primary header flush left either. The `>` combinator targets only
63
- the button-less case: Menu's own wrapper (`.crisp-menu`) and the plain sort `button` both put >=1 more level between `th` and this span, so their own 12px (already on the button) isn't doubled. */
85
+ the button-less case: Menu's own wrapper (`.crisp-menu`) and the
86
+ plain sort `button` both put >=1 more level between `th` and this
87
+ span, so their own 12px (already on the button) isn't doubled. */
64
88
  & th > .crisp-datatable-th-inner { box-sizing: border-box; padding: 0 var(--crisp-space-3); }
65
- /* The summary cell has NO padding of its own -- the calculation trigger
89
+ /* The summary cell has NO padding of its own -- the calculation trigger
66
90
  owns the whole 246x37 area so a click anywhere in the cell opens the
67
91
  menu. Zero the cell's inset and let ColumnCalc supply the 12px. */
68
92
  & tfoot td { padding: 0; }
69
- /* Group heading row -- a view is grouped under a subtle label with the bucket's count beside it. */
70
- & .crisp-datatable-viewsettings { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); height: var(--crisp-size-row); margin: 0; padding: 0 var(--crisp-space-2); border: none; border-radius: var(--crisp-radius-md); background: transparent; color: var(--crisp-fg-muted); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); white-space: nowrap; cursor: pointer; transition: background-color .12s, color .12s; }
93
+ /* Group heading row -- a view is grouped under a subtle label with the
94
+ bucket's count beside it. */
95
+ & .crisp-datatable-viewsettings { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); height: var(--crisp-size-row); margin: 0; padding: 0 var(--crisp-space-2); border: none; border-radius: var(--crisp-radius-md); background: transparent; color: var(--crisp-fg-muted); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); white-space: nowrap; cursor: pointer; transition: background-color .12s, color .12s; }
71
96
  & .crisp-datatable-viewsettings:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); color: var(--crisp-fg-primary); }
72
97
  & .crisp-datatable-group-label { padding: var(--crisp-space-1-5) var(--crisp-space-2) var(--crisp-space-1); font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-muted); }
73
- & .crisp-datatable-group { height: var(--crisp-size-menuRow); padding: 0 var(--crisp-space-3); background: var(--crisp-bg-subtle); border-bottom: 1px solid var(--crisp-border-subtle); font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
98
+ & .crisp-datatable-group { height: var(--crisp-size-menuRow); padding: 0 var(--crisp-space-3); background: var(--crisp-bg-subtle); border-bottom: 1px solid var(--crisp-border-subtle); font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
74
99
  & .crisp-datatable-group-count { margin-inline-start: var(--crisp-space-1-5); color: var(--crisp-fg-muted); font-variant-numeric: tabular-nums; }
75
100
  & .crisp-datatable-th-rename { width: 100%; min-width: 0; height: var(--crisp-size-row); margin: 0; padding: 0 var(--crisp-space-1); border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); font-family: inherit; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); outline: none; }
76
101
  & .crisp-datatable-th-rename:focus { box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); }
77
102
  & .crisp-datatable-th-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
78
- /* #465: 12px per the comment above (and Attio's measured header cell padding: 0 12px) -- was still c.space["2"] (8px), drifted from its own documented value. */
103
+ /* #465: 12px per the comment above (and Attio's measured header cell
104
+ padding: 0 12px) -- was still c.space["2"] (8px), drifted from its
105
+ own documented value. */
79
106
  & .crisp-datatable-sort { display: flex; align-items: center; gap: var(--crisp-space-1-5); width: 100%; min-width: 0; height: 100%; margin: 0; padding: 0 var(--crisp-space-3); border: none; background: none; font: inherit; letter-spacing: inherit; color: inherit; text-align: start; cursor: pointer; }
80
107
  /* A right-aligned column's header keeps its field-icon + label packed at
81
108
  the START, matching its own values only in that the VALUES right-align
82
109
  -- Attio's own right-aligned header (measured live: "Twitter follower
83
- count") keeps the icon+label left and only the trailing column-menu icon sits pinned to the right edge, independent of the label's width
84
- (#406, reversing #393's own justify-content: flex-end here). The chevron's own margin-inline-start: auto below already pins IT to the
85
- end of a flex-start row with no override needed -- that's what pins the trailing icon on Attio too. */
110
+ count") keeps the icon+label left and only the trailing column-menu
111
+ icon sits pinned to the right edge, independent of the label's width
112
+ (#406, reversing #393's own justify-content: flex-end here). The
113
+ chevron's own margin-inline-start: auto below already pins IT to the
114
+ end of a flex-start row with no override needed -- that's what pins
115
+ the trailing icon on Attio too. */
86
116
  & .crisp-datatable-chevron { margin-inline-start: auto; flex-shrink: 0; color: var(--crisp-fg-muted); opacity: 0; transition: opacity .12s; }
87
117
  & .crisp-datatable-sort:hover .crisp-datatable-chevron { opacity: 0.6; }
88
118
  & .crisp-datatable-sort[data-sorted] .crisp-datatable-chevron { opacity: 1; color: var(--crisp-fg-primary); }
@@ -90,17 +120,23 @@
90
120
  & th[data-sticky], & td[data-sticky] { position: sticky; z-index: 1; background: var(--crisp-bg-surface); }
91
121
  /* `thead th[data-sticky]`, not a bare `th[data-sticky]` (crisp#848, same
92
122
  bare-`th` family as #829/#833/#835): this z-index:3 was written for
93
- the HEADER's own sticky corner cell (sticky column x sticky header), meant to win over everything else. Unscoped, it also matched the primary column's BODY cell -- a real `<th scope="row" data-sticky>`
94
- since #779 -- giving every scrolled body row's own sticky cell a HIGHER z-index than the sticky FOOTER's (2), so it painted over the
123
+ the HEADER's own sticky corner cell (sticky column x sticky header),
124
+ meant to win over everything else. Unscoped, it also matched the
125
+ primary column's BODY cell -- a real `<th scope="row" data-sticky>`
126
+ since #779 -- giving every scrolled body row's own sticky cell a
127
+ HIGHER z-index than the sticky FOOTER's (2), so it painted over the
95
128
  footer instead of the footer showing through. Confirmed live on a
96
- real bounded-height, 25-row table (GRC's Risk register): scrolled partway, `elementFromPoint` at the footer's own on-screen cell
129
+ real bounded-height, 25-row table (GRC's Risk register): scrolled
130
+ partway, `elementFromPoint` at the footer's own on-screen cell
97
131
  resolved to a body row's `<th>`, not the footer's `<td>`, and that
98
132
  `<th>`'s computed z-index read 3. Scoped to `thead`, a body row's
99
133
  own sticky `<th>` now falls back to the base rule above (z-index 1,
100
- correct -- the same as a plain sticky `<td>`), and the footer's own explicit z-index below is unaffected either way. */
134
+ correct -- the same as a plain sticky `<td>`), and the footer's own
135
+ explicit z-index below is unaffected either way. */
101
136
  & thead th[data-sticky] { z-index: 3; }
102
137
  /* #554: a footer sticky-column cell sits in the bottom-sticky row (table.recipe.ts's
103
- `tfoot td { z-index: 2 }`), which `td[data-sticky]`'s own higher-specificity `z-index: 1` would otherwise undercut -- keep it level with the row it's in. */
138
+ `tfoot td { z-index: 2 }`), which `td[data-sticky]`'s own higher-specificity
139
+ `z-index: 1` would otherwise undercut -- keep it level with the row it's in. */
104
140
  & tfoot td[data-sticky] { z-index: 2; }
105
141
  & tbody tr[data-selected] td[data-sticky] { background: color-mix(in srgb, var(--crisp-bg-brand-solid) 10%, var(--crisp-bg-surface)); }
106
142
  & tbody tr:hover td[data-sticky] { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, var(--crisp-bg-surface)); }
@@ -120,7 +156,8 @@
120
156
  /* crisp/#758: AI-enriched column marker, ported from RecordsTable's own
121
157
  already-measured value -- a full-bleed #9b69ff (bgPurple) wash at 4%,
122
158
  composited OVER whatever row-state background the cell already has
123
- (hover, selected), which is why it's an ::after overlay and not a plain background. */
159
+ (hover, selected), which is why it's an ::after overlay and not a
160
+ plain background. */
124
161
  & td[data-enriched]::after { content: ""; position: absolute; inset: 0; pointer-events: none; background: color-mix(in srgb, var(--crisp-bg-purple) 4%, transparent); }
125
162
  & .crisp-datatable-edit { width: 100%; height: 28px; margin: 0; padding: 0 var(--crisp-space-1-5); border: none; border-radius: var(--crisp-radius-sm); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); font-family: inherit; font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); outline: none; vertical-align: middle; }
126
163
  & .crisp-datatable-edit:focus { box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); }
@@ -131,40 +168,56 @@
131
168
  & .crisp-datatable-edit:disabled { opacity: 0.5; cursor: not-allowed; }
132
169
  & .crisp-datatable-edit-pending { flex-shrink: 0; margin-inline-start: var(--crisp-space-1); color: var(--crisp-fg-muted); vertical-align: middle; }
133
170
  /* The rejection's message, beside the cell's own content -- a sibling in
134
- the TableCell, never nested inside a column's own render output, so a hover-only wrapper (a Tooltip, say) around a custom render can't hide
171
+ the TableCell, never nested inside a column's own render output, so a
172
+ hover-only wrapper (a Tooltip, say) around a custom render can't hide
135
173
  it. Block-level: the row grows to fit it rather than floating over
136
174
  the row below, so it can never end up clipped by the scroll
137
- container's overflow the way a position:fixed escape would need guarding against. */
175
+ container's overflow the way a position:fixed escape would need
176
+ guarding against. */
138
177
  & .crisp-datatable-edit-error { display: block; padding: var(--crisp-space-0-5) 0 0; font-size: var(--crisp-text-sm); color: var(--crisp-bg-danger); }
139
- /* editor: "select"/"switch" -- always live, no separate edit mode, so the cell IS the picker: same chromeless-fill treatment as RecordsTable's own --picker cells (measured there already; DataTable
178
+ /* editor: "select"/"switch" -- always live, no separate edit mode, so
179
+ the cell IS the picker: same chromeless-fill treatment as
180
+ RecordsTable's own --picker cells (measured there already; DataTable
140
181
  shares RecordsTable's grid, Golden Rule 0). */
141
182
  & .crisp-datatable-td--picker { padding: 0; }
142
183
  & .crisp-datatable-edit-picker { display: flex; align-items: center; gap: var(--crisp-space-1); height: var(--crisp-size-tableRow); padding: 0 var(--crisp-space-2); }
143
184
  & .crisp-datatable-edit-picker .crisp-select-trigger { flex: 1; min-width: 0; height: 100%; min-height: 0; border-radius: 0; box-shadow: none; padding: 0; }
144
185
  & .crisp-datatable-td--picker .crisp-datatable-edit-error { padding-inline-start: var(--crisp-space-2); }
145
- /* reference picker: a leading 16px avatar per option, plus a trailing "Create X" row when the consumer supplies one (#449) -- same measured values as RecordsTable's own .crisp-recordstable-refoption*. */
186
+ /* reference picker: a leading 16px avatar per option, plus a trailing
187
+ "Create X" row when the consumer supplies one (#449) -- same measured
188
+ values as RecordsTable's own .crisp-recordstable-refoption*. */
146
189
  & .crisp-datatable-refoption { display: flex; align-items: center; gap: var(--crisp-space-2); min-width: 0; overflow: hidden; text-overflow: ellipsis; }
147
190
  & .crisp-datatable-refoption-avatar { flex-shrink: 0; }
148
191
  & .crisp-datatable-refoption--create { color: var(--crisp-fg-muted); }
149
192
  & .crisp-datatable-empty { padding: var(--crisp-space-8) var(--crisp-space-3); text-align: center; color: var(--crisp-fg-muted); font-size: var(--crisp-text-lg); }
150
193
  /* #826 -- the full-body loading state (a filter/sort re-query, or a
151
- fresh page boot), measured live on Attio's Companies grid on both triggers: icon+text centred in the row-body area, 10px gap, 14px/500 weight/20px line-height, both icon and text in the SAME muted rgba(0,0,0,0.63) -- the same color-mix figure this file already uses for other muted text (e.g. -phone-dial). Distinct from the cold in-place row load (blank, no indicator) and the warm-navigation per-cell shimmer (#599) -- neither of those swaps the whole body. */
194
+ fresh page boot), measured live on Attio's Companies grid on both
195
+ triggers: icon+text centred in the row-body area, 10px gap, 14px/500
196
+ weight/20px line-height, both icon and text in the SAME muted
197
+ rgba(0,0,0,0.63) -- the same color-mix figure this file already uses
198
+ for other muted text (e.g. -phone-dial). Distinct from the cold
199
+ in-place row load (blank, no indicator) and the warm-navigation
200
+ per-cell shimmer (#599) -- neither of those swaps the whole body. */
152
201
  & .crisp-datatable-loading { display: flex; align-items: center; justify-content: center; gap: 10px; padding: var(--crisp-space-8) var(--crisp-space-3); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); line-height: 20px; }
153
202
  & .crisp-datatable-loading .crisp-spinner { border-top-color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
154
- /* #579: click-to-expand overlay for a truncated cell -- a read-only, full-value card, settled live as click (not Attio's usual
155
- hover-expand) and measured position: absolute, unlike this file's floating chrome (Menu/Select popovers) which portals and escapes the scroll container. Deliberately NOT the edit-error pattern above (grow the row, block-level, never clipped): a virtualized grid assumes a fixed row height for its scroll math (owned by the grid core, not this cell), so growing a row here would fight it. Anchored to the SAME column width the cell itself renders at (measured: Attio's own overlay came out only slightly wider than the
156
- triggering cell's clientWidth -- the overshoot is this padding), wrapping onto as many lines as the value needs; it CAN be clipped by `.crisp-table-scroll`'s own `overflow: auto` if it grows past the
203
+ /* #579: click-to-expand overlay for a truncated cell -- a read-only,
204
+ full-value card, settled live as click (not Attio's usual
205
+ hover-expand) and measured position: absolute, unlike this file's
206
+ floating chrome (Menu/Select popovers) which portals and escapes the
207
+ scroll container. Deliberately NOT the edit-error pattern above
208
+ (grow the row, block-level, never clipped): a virtualized grid
209
+ assumes a fixed row height for its scroll math (owned by the grid
210
+ core, not this cell), so growing a row here would fight it. Anchored
211
+ to the SAME column width the cell itself renders at (measured:
212
+ Attio's own overlay came out only slightly wider than the
213
+ triggering cell's clientWidth -- the overshoot is this padding),
214
+ wrapping onto as many lines as the value needs; it CAN be clipped by
215
+ `.crisp-table-scroll`'s own `overflow: auto` if it grows past the
157
216
  visible viewport, same as the edit-error comment above already
158
217
  notes for any position:absolute escape -- unmeasured against Attio
159
218
  for this exact case, flagged rather than guessed. */
160
219
  & td[data-cell-expanded] { overflow: visible; z-index: 7; }
161
- & .crisp-datatable-cell-overlay {
162
- position: absolute; inset-inline-start: 0; top: 0; width: 100%; box-sizing: border-box;
163
- padding: var(--crisp-space-2) var(--crisp-space-3); background: var(--crisp-bg-surface);
164
- border: 1px solid var(--crisp-bg-brand-solid); border-radius: 4px;
165
- font-family: var(--crisp-font-sans); font-size: var(--crisp-text-lg); line-height: 20px; font-weight: var(--crisp-weight-medium);
166
- color: var(--crisp-fg-primary); white-space: normal; word-break: break-word; cursor: default;
167
- }
220
+ & .crisp-datatable-cell-overlay { position: absolute; inset-inline-start: 0; top: 0; width: 100%; box-sizing: border-box; padding: var(--crisp-space-2) var(--crisp-space-3); background: var(--crisp-bg-surface); border: 1px solid var(--crisp-bg-brand-solid); border-radius: 4px; font-family: var(--crisp-font-sans); font-size: var(--crisp-text-lg); line-height: 20px; font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); white-space: normal; word-break: break-word; cursor: default; }
168
221
  /* fixed layout so column widths (and resize) are exact — like RecordsTable */
169
222
  & table { table-layout: fixed; }
170
223
  /* read-only/computed column marker (#596) -- sits just inside the
@@ -176,42 +229,70 @@
176
229
  & .crisp-datatable-resize { position: absolute; top: 0; inset-inline-end: -3px; width: 9px; height: 100%; cursor: col-resize; z-index: 6; touch-action: none; }
177
230
  & .crisp-datatable-resize::after { content: ""; position: absolute; top: 0; inset-inline-start: 3px; width: 2px; height: 100%; background: var(--crisp-bg-brand-solid); opacity: 0; transition: opacity .12s; }
178
231
  & .crisp-datatable-resize:hover::after, & .crisp-datatable-resize[data-resizing]::after { opacity: 1; }
179
- /* crisp/#731 -- column drag-to-reorder. Measured live against Attio's own grid (the issue's own comment): the dragged header keeps full
232
+ /* crisp/#731 -- column drag-to-reorder. Measured live against Attio's
233
+ own grid (the issue's own comment): the dragged header keeps full
180
234
  opacity and the plain `pointer` cursor throughout (Attio draws no
181
235
  ghost and no "grabbing" cursor of its own), so this adds nothing to
182
236
  `[data-dragging]` itself -- the ONLY new paint is the drop-indicator
183
- line, a 3px bar in the same measured brand blue the resize handle's own hover state (above) already uses, positioned on whichever edge of the hovered header the pointer is closer to. */
237
+ line, a 3px bar in the same measured brand blue the resize handle's
238
+ own hover state (above) already uses, positioned on whichever edge of
239
+ the hovered header the pointer is closer to. */
184
240
  & th[data-dragging] { cursor: pointer; }
185
241
  & th[data-drop-before]::before, & th[data-drop-after]::after { content: ""; position: absolute; top: 0; width: 3px; height: 100%; background: var(--crisp-bg-brand-solid); z-index: 6; pointer-events: none; }
186
242
  & th[data-drop-before]::before { inset-inline-start: -1.5px; }
187
243
  & th[data-drop-after]::after { inset-inline-end: -1.5px; }
188
244
  /* typed cells — entity (avatar + name), colour-coded tags, numbers, dates */
189
245
  & .crisp-datatable-entity { display: flex; align-items: center; gap: var(--crisp-space-1-5); min-width: 0; color: var(--crisp-fg-primary); font-weight: var(--crisp-weight-medium); }
190
- /* crisp/#601 supersession follow-up -- the same flex-row shape .crisp-datatable-entity gives its own avatar+name+actions, but structural only (no entity-specific colour/weight): lets onOpenComments/onOpenPreview compose alongside ANY column's own
246
+ /* crisp/#601 supersession follow-up -- the same flex-row shape
247
+ .crisp-datatable-entity gives its own avatar+name+actions, but
248
+ structural only (no entity-specific colour/weight): lets
249
+ onOpenComments/onOpenPreview compose alongside ANY column's own
191
250
  content (a custom render, or a non-entity built-in type), not just
192
251
  type: "entity"'s own inline rendering. */
193
252
  & .crisp-datatable-cell-actions-row { display: flex; align-items: center; gap: var(--crisp-space-1-5); min-width: 0; width: 100%; }
194
- /* crisp/#601, G-050: measured LIVE (getComputedStyle on the name text, plain hover vs rest) that Attio's underline is unconditional, not a
253
+ /* crisp/#601, G-050: measured LIVE (getComputedStyle on the name text,
254
+ plain hover vs rest) that Attio's underline is unconditional, not a
195
255
  hover reveal -- identical at rest and on hover: text-decoration-color
196
- is rgba(0,0,0,0.09), a 9% tint, not the name's own full-contrast text colour. The previous :hover-gated, full-contrast rule here was itself unmeasured and wrong in two ways at once. */ /* crisp#851 -- Attio's own entity/record names are measured at
197
- font-weight 500, distinct from a plain-text primary column's 400 (table.recipe.ts's own `tbody th` default). This was never its own
256
+ is rgba(0,0,0,0.09), a 9% tint, not the name's own full-contrast text
257
+ colour. The previous :hover-gated, full-contrast rule here was itself
258
+ unmeasured and wrong in two ways at once. */ /* crisp#851 -- Attio's own entity/record names are measured at
259
+ font-weight 500, distinct from a plain-text primary column's 400
260
+ (table.recipe.ts's own `tbody th` default). This was never its own
198
261
  explicit style -- it silently rode on a since-fixed header-rule leak
199
262
  (#833/#835/#848) that happened to apply the same 500 to every
200
263
  primary-column body cell regardless of type. Made explicit here so
201
264
  fixing that leak doesn't also (wrongly) drop entity names to 400. */
202
265
  & .crisp-datatable-entity-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: var(--crisp-weight-medium); text-decoration: underline; text-decoration-color: color-mix(in srgb, var(--crisp-fg-primary) 9%, transparent); }
203
- & button.crisp-datatable-entity-name--link { margin: 0; padding: 0; border: none; background: none; font: inherit; color: inherit; letter-spacing: inherit; text-align: start; cursor: pointer; max-width: 100%; }
204
- /* crisp/#601, G-048: two 20px ghost icons, right-aligned in the primary column, revealed on ROW hover (the issue's own title says "row
266
+ /* #893: shared by the button (onEntityClick, a different record) and
267
+ the anchor (href, the row's own record) -- was button-only, which
268
+ silently left a real <a> unstyled the day #893 added one. */
269
+ & .crisp-datatable-entity-name--link { margin: 0; padding: 0; border: none; background: none; font: inherit; color: inherit; letter-spacing: inherit; text-align: start; cursor: pointer; max-width: 100%; }
270
+ /* crisp/#601, G-048: two 20px ghost icons, right-aligned in the primary
271
+ column, revealed on ROW hover (the issue's own title says "row
205
272
  hover", and a live check confirmed hovering well past the name --
206
- not just the icons' own hit target -- still reveals them) or keyboard focus. Measured live: border-radius 6px, icon colour rgba(0,0,0,0.55) at rest, darkening to the full text colour with a rgba(0,0,0,0.04) background on the icon's OWN hover -- both
273
+ not just the icons' own hit target -- still reveals them) or
274
+ keyboard focus. Measured live: border-radius 6px, icon colour
275
+ rgba(0,0,0,0.55) at rest, darkening to the full text colour with a
276
+ rgba(0,0,0,0.04) background on the icon's OWN hover -- both
207
277
  expressed as color-mix against fgPrimary so they stay correct in
208
278
  dark mode instead of a literal black that would invert. */
209
279
  & .crisp-datatable-entity-actions { display: flex; align-items: center; gap: var(--crisp-space-1-5); margin-inline-start: auto; flex-shrink: 0; opacity: 0; }
210
280
  & tr:hover .crisp-datatable-entity-actions, & .crisp-datatable-entity-actions:focus-within { opacity: 1; }
211
281
  & .crisp-datatable-entity-action { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; margin: 0; padding: 0; border: none; border-radius: var(--crisp-radius-sm); background: none; font-family: inherit; color: color-mix(in srgb, var(--crisp-fg-primary) 55%, transparent); cursor: pointer; flex-shrink: 0; }
212
282
  & .crisp-datatable-entity-action:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); color: var(--crisp-fg-primary); }
213
- & .crisp-datatable-avatar { width: var(--crisp-size-icon); height: var(--crisp-size-icon); border-radius: var(--crisp-radius-sm); flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; font-size: 10px; line-height: 1; font-weight: var(--crisp-weight-semibold); text-transform: uppercase; color: var(--crisp-fg-on-brand); background: var(--crisp-bg-brand-solid); }
214
- & .crisp-datatable-avatar[data-tone="success"] { background: var(--crisp-bg-success); } & .crisp-datatable-avatar[data-tone="warning"] { background: var(--crisp-bg-warning); } & .crisp-datatable-avatar[data-tone="danger"] { background: var(--crisp-bg-danger); } & .crisp-datatable-avatar[data-tone="purple"] { background: var(--crisp-bg-purple); } & .crisp-datatable-avatar[data-tone="cyan"] { background: var(--crisp-bg-cyan); } & .crisp-datatable-avatar[data-tone="orange"] { background: var(--crisp-bg-orange); }
283
+ /* #892: the default shape's radius was a stray literal (radius.sm, 6px)
284
+ -- Attio's own real company/object avatar measures 30%, which is
285
+ Avatar's own already-shipped shape="rounded" value, not a new number.
286
+ shape="circle" reuses Avatar's own shape="circle" value (radius.full)
287
+ the same way, measured live on a real Attio person avatar. */
288
+ & .crisp-datatable-avatar { width: var(--crisp-size-icon); height: var(--crisp-size-icon); border-radius: 30%; flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; font-size: 10px; line-height: 1; font-weight: var(--crisp-weight-semibold); text-transform: uppercase; color: var(--crisp-fg-on-brand); background: var(--crisp-bg-brand-solid); }
289
+ & .crisp-datatable-avatar[data-shape="circle"] { border-radius: var(--crisp-radius-full); }
290
+ & .crisp-datatable-avatar[data-tone="success"] { background: var(--crisp-bg-success); }
291
+ & .crisp-datatable-avatar[data-tone="warning"] { background: var(--crisp-bg-warning); }
292
+ & .crisp-datatable-avatar[data-tone="danger"] { background: var(--crisp-bg-danger); }
293
+ & .crisp-datatable-avatar[data-tone="purple"] { background: var(--crisp-bg-purple); }
294
+ & .crisp-datatable-avatar[data-tone="cyan"] { background: var(--crisp-bg-cyan); }
295
+ & .crisp-datatable-avatar[data-tone="orange"] { background: var(--crisp-bg-orange); }
215
296
  & .crisp-datatable-avatar img { width: 100%; height: 100%; border-radius: inherit; object-fit: cover; }
216
297
  & .crisp-datatable-tags { display: flex; align-items: center; gap: var(--crisp-space-1); overflow: hidden; }
217
298
  & .crisp-datatable-tag { display: inline-flex; align-items: center; height: var(--crisp-size-chip); padding: 0 var(--crisp-space-1); border-radius: var(--crisp-radius-chip); font-size: var(--crisp-text-lg); line-height: 20px; font-weight: var(--crisp-weight-medium); white-space: nowrap; background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); color: color-mix(in srgb, var(--crisp-fg-primary) 82%, transparent); }
@@ -224,13 +305,19 @@
224
305
  & .crisp-datatable-tag[data-tone="orange"] { background: color-mix(in srgb, var(--crisp-bg-orange) 16%, transparent); color: color-mix(in srgb, var(--crisp-bg-orange) 82%, var(--crisp-fg-primary)); }
225
306
  & .crisp-datatable-num { font-variant-numeric: tabular-nums; }
226
307
  & .crisp-datatable-muted { color: var(--crisp-fg-muted); }
227
- /* crisp#822 -- a date/datetime cell's danger/overdue tone: same token as TasksTable's own overdue due-date (crisp#462), plain text colour, no
308
+ /* crisp#822 -- a date/datetime cell's danger/overdue tone: same token as
309
+ TasksTable's own overdue due-date (crisp#462), plain text colour, no
228
310
  fill/weight change. */
229
311
  & .crisp-datatable-danger { color: var(--crisp-fg-danger); }
230
- /* url/email cell types (#654) -- same measured values as RecordsTable's own .crisp-recordstable-link, which this mirrors: no underline at rest, underline on hover, own-colour text rather than a browser-blue link. */
312
+ /* url/email cell types (#654) -- same measured values as RecordsTable's
313
+ own .crisp-recordstable-link, which this mirrors: no underline at
314
+ rest, underline on hover, own-colour text rather than a browser-blue
315
+ link. */
231
316
  & .crisp-datatable-link { color: var(--crisp-fg-primary); text-decoration: none; overflow: hidden; text-overflow: ellipsis; }
232
317
  & .crisp-datatable-link:hover { text-decoration: underline; }
233
- /* phone cell type/editor (#765) -- measured live: the dial-code prefix is a muted rgba(0,0,0,0.63) at 14px, matching every other muted-text value already measured elsewhere in this file. */
318
+ /* phone cell type/editor (#765) -- measured live: the dial-code prefix
319
+ is a muted rgba(0,0,0,0.63) at 14px, matching every other muted-text
320
+ value already measured elsewhere in this file. */
234
321
  & .crisp-datatable-phone { display: inline-flex; align-items: center; gap: var(--crisp-space-1); }
235
322
  & .crisp-datatable-phone-dial { color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
236
323
  & .crisp-datatable-phone-editor { display: flex; align-items: center; gap: var(--crisp-space-1); height: var(--crisp-size-tableRow); padding: 0 var(--crisp-space-2); }
@@ -260,7 +347,8 @@
260
347
  value rows (32px = size.menuRow, 5px 8px padding, 8px gap between
261
348
  the grip/value/actions, 16px icons) above one ALWAYS-blank trailing
262
349
  DataPhoneEditor-shaped row -- that blank row is the only "add
263
- another" affordance, there's no separate button for it. The copy/delete pair reuses .crisp-datatable-entity-action's own
350
+ another" affordance, there's no separate button for it. The
351
+ copy/delete pair reuses .crisp-datatable-entity-action's own
264
352
  hover-reveal chrome (not independently re-measured as its own hit
265
353
  target this pass, only the 16px icon glyphs were). */
266
354
  & .crisp-datatable-phone-multi-editor { display: flex; flex-direction: column; }
@@ -268,8 +356,7 @@
268
356
  & .crisp-datatable-phone-multi-row .crisp-datatable-phone-link { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
269
357
  & .crisp-datatable-phone-multi-grip { color: var(--crisp-fg-muted); flex-shrink: 0; cursor: grab; }
270
358
  & .crisp-datatable-phone-multi-actions { display: flex; align-items: center; gap: var(--crisp-space-1); margin-inline-start: auto; flex-shrink: 0; opacity: 0; }
271
- & .crisp-datatable-phone-multi-row:hover .crisp-datatable-phone-multi-actions,
272
- & .crisp-datatable-phone-multi-actions:focus-within { opacity: 1; }
359
+ & .crisp-datatable-phone-multi-row:hover .crisp-datatable-phone-multi-actions, & .crisp-datatable-phone-multi-actions:focus-within { opacity: 1; }
273
360
  & .crisp-datatable-phone-multi-action { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; margin: 0; padding: 0; border: none; border-radius: var(--crisp-radius-sm); background: none; font-family: inherit; color: color-mix(in srgb, var(--crisp-fg-primary) 55%, transparent); cursor: pointer; flex-shrink: 0; }
274
361
  & .crisp-datatable-phone-multi-action:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); color: var(--crisp-fg-primary); }
275
362
  /* datetime cell editor (#762) -- DatePickerField + TimePicker side by side. */
@@ -278,7 +365,10 @@
278
365
  18px pitch (a 2px gap), an empty star at rgba(0,0,0,0.1), a
279
366
  committed/filled star at brand600 (--crisp-bg-brand-solid, an exact
280
367
  match to the measured #266df0), and a distinct hover-preview colour
281
- -- rgb(33,91,196) -- that's close to but NOT brand700/bgBrandSolidPressed (#1f5fd6); kept as its own literal rather than forced onto that token, since the two were measured stable and different. The read-only svg and the editable button's own inner svg both carry the
368
+ -- rgb(33,91,196) -- that's close to but NOT brand700/bgBrandSolidPressed
369
+ (#1f5fd6); kept as its own literal rather than forced onto that token,
370
+ since the two were measured stable and different. The read-only svg
371
+ and the editable button's own inner svg both carry the
282
372
  crisp-datatable-rating-star class on the svg itself (not the
283
373
  button), so one set of fill rules covers both -- the button only
284
374
  adds its own reset + cursor via a separate -btn class. */
@@ -289,9 +379,13 @@
289
379
  & .crisp-datatable-rating-star[data-hovering] path { fill: #215bc4; }
290
380
  & .crisp-datatable-rating-star-btn { display: inline-flex; padding: 0; margin: 0; border: none; background: none; font-family: inherit; cursor: pointer; }
291
381
  /* row drag-to-reorder -- a Settings > Objects > Attributes screen measures
292
- a leading 20px grip column, a 16px grip icon, and the row's own hairline doubling as the drop indicator (it tints toward the brand colour as the active drop target). The affordance + geometry are measured; the drag MECHANISM is crisp's existing house idiom -- HTML5
382
+ a leading 20px grip column, a 16px grip icon, and the row's own
383
+ hairline doubling as the drop indicator (it tints toward the brand
384
+ colour as the active drop target). The affordance + geometry are
385
+ measured; the drag MECHANISM is crisp's existing house idiom -- HTML5
293
386
  draggable + dataTransfer, the same one column reorder already uses
294
- (RecordsTable's reorderColumn) -- not a proprietary pointer-events implementation. */
387
+ (RecordsTable's reorderColumn) -- not a proprietary
388
+ pointer-events implementation. */
295
389
  & .crisp-datatable-col-grip { width: 20px; padding: 0; text-align: center; }
296
390
  & .crisp-datatable-grip { display: inline-flex; align-items: center; justify-content: center; width: 100%; height: 100%; margin: 0; border: none; border-radius: 0; background: none; font-family: inherit; color: var(--crisp-fg-muted); cursor: grab; }
297
391
  & .crisp-datatable-grip:active { cursor: grabbing; }
@@ -16,36 +16,22 @@
16
16
  measurement -- accessibility wins over the seed reference.
17
17
  neutralMuted clears it, 6.62:1 light / 14.71:1 dark (dark was
18
18
  already fine at 9.43:1). */
19
- & .crisp-datepicker-weekday {
20
- display: flex; align-items: center; justify-content: center;
21
- height: var(--crisp-size-calendarCell); color: var(--crisp-fg-neutral-muted);
22
- font-size: var(--crisp-text-sm); line-height: 16px; font-weight: var(--crisp-weight-medium);
23
- }
24
-
19
+ & .crisp-datepicker-weekday { display: flex; align-items: center; justify-content: center; height: var(--crisp-size-calendarCell); color: var(--crisp-fg-neutral-muted); font-size: var(--crisp-text-sm); line-height: 16px; font-weight: var(--crisp-weight-medium); }
25
20
  & .crisp-datepicker-months { display: grid; grid-template-columns: minmax(0, 1fr); align-items: start; min-width: 0; }
26
21
  & .crisp-datepicker-months[data-wheel-open] { visibility: hidden; }
27
22
  & .crisp-datepicker-month { min-width: 0; }
28
- & .crisp-datepicker-month-label {
29
- display: flex; align-items: center; height: 24px;
30
- color: var(--crisp-fg-primary); font-size: var(--crisp-text-lg); line-height: 20px;
31
- font-weight: var(--crisp-weight-medium);
32
- }
33
-
23
+ & .crisp-datepicker-month-label { display: flex; align-items: center; height: 24px; color: var(--crisp-fg-primary); font-size: var(--crisp-text-lg); line-height: 20px; font-weight: var(--crisp-weight-medium); }
34
24
  & .crisp-datepicker-grid { display: grid; min-width: 0; }
35
25
  & .crisp-datepicker-week-row { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); }
36
-
37
- & .crisp-datepicker-cell {
38
- position: relative; min-width: 0; min-height: var(--crisp-size-calendarCell);
39
- isolation: isolate;
40
- }
26
+ & .crisp-datepicker-cell { position: relative; min-width: 0; min-height: var(--crisp-size-calendarCell); isolation: isolate; }
41
27
  & .crisp-datepicker-empty-cell { min-height: var(--crisp-size-calendarCell); }
42
-
43
28
  /* The bridge joining days inside a completed range.
44
29
  The endpoints do NOT carry data-in-range -- only the interior days do --
45
30
  so these are three independent rules, not a base plus two modifiers. A
46
31
  modifier that sets only inset-inline-start never generates a pseudo
47
32
  element on an endpoint, which leaves a half-cell of white between the
48
- endpoint's pill and the run of grey beside it. Each rule declares its own content. */
33
+ endpoint's pill and the run of grey beside it. Each rule declares its
34
+ own content. */
49
35
  & .crisp-datepicker-cell[data-range-complete][data-in-range]::before { content: ""; position: absolute; z-index: -1; inset-inline: 0; top: calc((var(--crisp-size-calendarCell) - var(--crisp-size-calendarPill)) / 2); height: var(--crisp-size-calendarPill); background: var(--crisp-bg-neutral-weak); }
50
36
  & .crisp-datepicker-cell[data-range-complete][data-range-start]:not([data-range-end])::before { content: ""; position: absolute; z-index: -1; inset-inline-start: 50%; inset-inline-end: 0; top: calc((var(--crisp-size-calendarCell) - var(--crisp-size-calendarPill)) / 2); height: var(--crisp-size-calendarPill); background: var(--crisp-bg-neutral-weak); }
51
37
  & .crisp-datepicker-cell[data-range-complete][data-range-end]:not([data-range-start])::before { content: ""; position: absolute; z-index: -1; inset-inline-start: 0; inset-inline-end: 50%; top: calc((var(--crisp-size-calendarCell) - var(--crisp-size-calendarPill)) / 2); height: var(--crisp-size-calendarPill); background: var(--crisp-bg-neutral-weak); }
@@ -61,33 +47,19 @@
61
47
  & .crisp-datepicker-date:disabled { color: var(--crisp-fg-disabled); cursor: not-allowed; }
62
48
  & .crisp-datepicker-date:focus-visible::after { content: ""; position: absolute; top: calc((var(--crisp-size-calendarCell) - var(--crisp-size-calendarPill)) / 2); left: 50%; width: var(--crisp-size-calendarPill); height: var(--crisp-size-calendarPill); transform: translateX(-50%); border-radius: var(--crisp-radius-md); outline: 2px solid var(--crisp-stroke-focus-ring); outline-offset: -2px; }
63
49
  & .crisp-datepicker-date-content { position: relative; z-index: 1; display: flex; width: 100%; min-height: var(--crisp-size-calendarCell); min-width: 0; box-sizing: border-box; flex-direction: column; align-items: center; gap: 3px; padding-top: calc((var(--crisp-size-calendarCell) - var(--crisp-size-calendarPill)) / 2); color: inherit; font-size: var(--crisp-text-lg); line-height: 20px; font-weight: var(--crisp-weight-medium); font-variant-numeric: tabular-nums; }
64
- /* The numeral is its own 42px flex box so it centres on the 42px pill. Without this the content column top-aligns the glyph and the pill reads as offset — the cell is 48px, the pill 42px inset 3px, and only a 42px-tall numeral box shares the pill's centre line. */
65
- & .crisp-datepicker-date-content > [data-date-picker-day] {
66
- display: flex; min-height: var(--crisp-size-calendarPill); flex-shrink: 0;
67
- align-items: center; justify-content: center;
68
- }
69
-
50
+ /* The numeral is its own 42px flex box so it centres on the 42px pill.
51
+ Without this the content column top-aligns the glyph and the pill reads
52
+ as offset — the cell is 48px, the pill 42px inset 3px, and only a
53
+ 42px-tall numeral box shares the pill's centre line. */
54
+ & .crisp-datepicker-date-content > [data-date-picker-day] { display: flex; min-height: var(--crisp-size-calendarPill); flex-shrink: 0; align-items: center; justify-content: center; }
70
55
  /* the year/month wheel, laid over the grid it replaces */
71
- & .crisp-datepicker-wheel-container {
72
- position: absolute; z-index: 1; inset-inline: 0;
73
- top: var(--crisp-size-menuRow); bottom: 0;
74
- display: flex; align-items: center; overflow: hidden;
75
- background: var(--crisp-bg-surface);
76
- }
56
+ & .crisp-datepicker-wheel-container { position: absolute; z-index: 1; inset-inline: 0; top: var(--crisp-size-menuRow); bottom: 0; display: flex; align-items: center; overflow: hidden; background: var(--crisp-bg-surface); }
77
57
  & .crisp-datepicker-wheel { width: 100%; }
78
-
79
- & .crisp-datepicker-continuous-scroll {
80
- height: 100%; min-height: 0; overflow-y: auto;
81
- overscroll-behavior: contain; scrollbar-width: none;
82
- }
58
+ & .crisp-datepicker-continuous-scroll { height: 100%; min-height: 0; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: none; }
83
59
  & .crisp-datepicker-continuous-scroll::-webkit-scrollbar { display: none; }
84
60
  & .crisp-datepicker-continuous-content { display: flex; flex-direction: column; }
85
-
86
61
  /* announced, never drawn */
87
- & .crisp-datepicker-live-region {
88
- position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
89
- overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
90
- }
62
+ & .crisp-datepicker-live-region { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
91
63
  }
92
64
  .crisp-datepicker--visibleRange_month {
93
65
 
@@ -17,36 +17,22 @@
17
17
  measurement -- accessibility wins over the seed reference.
18
18
  neutralMuted clears it, 6.62:1 light / 14.71:1 dark (dark was
19
19
  already fine at 9.43:1). */
20
- & .crisp-datepicker-weekday {
21
- display: flex; align-items: center; justify-content: center;
22
- height: var(--crisp-size-calendarCell); color: var(--crisp-fg-neutral-muted);
23
- font-size: var(--crisp-text-sm); line-height: 16px; font-weight: var(--crisp-weight-medium);
24
- }
25
-
20
+ & .crisp-datepicker-weekday { display: flex; align-items: center; justify-content: center; height: var(--crisp-size-calendarCell); color: var(--crisp-fg-neutral-muted); font-size: var(--crisp-text-sm); line-height: 16px; font-weight: var(--crisp-weight-medium); }
26
21
  & .crisp-datepicker-months { display: grid; grid-template-columns: minmax(0, 1fr); align-items: start; min-width: 0; }
27
22
  & .crisp-datepicker-months[data-wheel-open] { visibility: hidden; }
28
23
  & .crisp-datepicker-month { min-width: 0; }
29
- & .crisp-datepicker-month-label {
30
- display: flex; align-items: center; height: 24px;
31
- color: var(--crisp-fg-primary); font-size: var(--crisp-text-lg); line-height: 20px;
32
- font-weight: var(--crisp-weight-medium);
33
- }
34
-
24
+ & .crisp-datepicker-month-label { display: flex; align-items: center; height: 24px; color: var(--crisp-fg-primary); font-size: var(--crisp-text-lg); line-height: 20px; font-weight: var(--crisp-weight-medium); }
35
25
  & .crisp-datepicker-grid { display: grid; min-width: 0; }
36
26
  & .crisp-datepicker-week-row { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); }
37
-
38
- & .crisp-datepicker-cell {
39
- position: relative; min-width: 0; min-height: var(--crisp-size-calendarCell);
40
- isolation: isolate;
41
- }
27
+ & .crisp-datepicker-cell { position: relative; min-width: 0; min-height: var(--crisp-size-calendarCell); isolation: isolate; }
42
28
  & .crisp-datepicker-empty-cell { min-height: var(--crisp-size-calendarCell); }
43
-
44
29
  /* The bridge joining days inside a completed range.
45
30
  The endpoints do NOT carry data-in-range -- only the interior days do --
46
31
  so these are three independent rules, not a base plus two modifiers. A
47
32
  modifier that sets only inset-inline-start never generates a pseudo
48
33
  element on an endpoint, which leaves a half-cell of white between the
49
- endpoint's pill and the run of grey beside it. Each rule declares its own content. */
34
+ endpoint's pill and the run of grey beside it. Each rule declares its
35
+ own content. */
50
36
  & .crisp-datepicker-cell[data-range-complete][data-in-range]::before { content: ""; position: absolute; z-index: -1; inset-inline: 0; top: calc((var(--crisp-size-calendarCell) - var(--crisp-size-calendarPill)) / 2); height: var(--crisp-size-calendarPill); background: var(--crisp-bg-neutral-weak); }
51
37
  & .crisp-datepicker-cell[data-range-complete][data-range-start]:not([data-range-end])::before { content: ""; position: absolute; z-index: -1; inset-inline-start: 50%; inset-inline-end: 0; top: calc((var(--crisp-size-calendarCell) - var(--crisp-size-calendarPill)) / 2); height: var(--crisp-size-calendarPill); background: var(--crisp-bg-neutral-weak); }
52
38
  & .crisp-datepicker-cell[data-range-complete][data-range-end]:not([data-range-start])::before { content: ""; position: absolute; z-index: -1; inset-inline-start: 0; inset-inline-end: 50%; top: calc((var(--crisp-size-calendarCell) - var(--crisp-size-calendarPill)) / 2); height: var(--crisp-size-calendarPill); background: var(--crisp-bg-neutral-weak); }
@@ -62,33 +48,19 @@
62
48
  & .crisp-datepicker-date:disabled { color: var(--crisp-fg-disabled); cursor: not-allowed; }
63
49
  & .crisp-datepicker-date:focus-visible::after { content: ""; position: absolute; top: calc((var(--crisp-size-calendarCell) - var(--crisp-size-calendarPill)) / 2); left: 50%; width: var(--crisp-size-calendarPill); height: var(--crisp-size-calendarPill); transform: translateX(-50%); border-radius: var(--crisp-radius-md); outline: 2px solid var(--crisp-stroke-focus-ring); outline-offset: -2px; }
64
50
  & .crisp-datepicker-date-content { position: relative; z-index: 1; display: flex; width: 100%; min-height: var(--crisp-size-calendarCell); min-width: 0; box-sizing: border-box; flex-direction: column; align-items: center; gap: 3px; padding-top: calc((var(--crisp-size-calendarCell) - var(--crisp-size-calendarPill)) / 2); color: inherit; font-size: var(--crisp-text-lg); line-height: 20px; font-weight: var(--crisp-weight-medium); font-variant-numeric: tabular-nums; }
65
- /* The numeral is its own 42px flex box so it centres on the 42px pill. Without this the content column top-aligns the glyph and the pill reads as offset — the cell is 48px, the pill 42px inset 3px, and only a 42px-tall numeral box shares the pill's centre line. */
66
- & .crisp-datepicker-date-content > [data-date-picker-day] {
67
- display: flex; min-height: var(--crisp-size-calendarPill); flex-shrink: 0;
68
- align-items: center; justify-content: center;
69
- }
70
-
51
+ /* The numeral is its own 42px flex box so it centres on the 42px pill.
52
+ Without this the content column top-aligns the glyph and the pill reads
53
+ as offset — the cell is 48px, the pill 42px inset 3px, and only a
54
+ 42px-tall numeral box shares the pill's centre line. */
55
+ & .crisp-datepicker-date-content > [data-date-picker-day] { display: flex; min-height: var(--crisp-size-calendarPill); flex-shrink: 0; align-items: center; justify-content: center; }
71
56
  /* the year/month wheel, laid over the grid it replaces */
72
- & .crisp-datepicker-wheel-container {
73
- position: absolute; z-index: 1; inset-inline: 0;
74
- top: var(--crisp-size-menuRow); bottom: 0;
75
- display: flex; align-items: center; overflow: hidden;
76
- background: var(--crisp-bg-surface);
77
- }
57
+ & .crisp-datepicker-wheel-container { position: absolute; z-index: 1; inset-inline: 0; top: var(--crisp-size-menuRow); bottom: 0; display: flex; align-items: center; overflow: hidden; background: var(--crisp-bg-surface); }
78
58
  & .crisp-datepicker-wheel { width: 100%; }
79
-
80
- & .crisp-datepicker-continuous-scroll {
81
- height: 100%; min-height: 0; overflow-y: auto;
82
- overscroll-behavior: contain; scrollbar-width: none;
83
- }
59
+ & .crisp-datepicker-continuous-scroll { height: 100%; min-height: 0; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: none; }
84
60
  & .crisp-datepicker-continuous-scroll::-webkit-scrollbar { display: none; }
85
61
  & .crisp-datepicker-continuous-content { display: flex; flex-direction: column; }
86
-
87
62
  /* announced, never drawn */
88
- & .crisp-datepicker-live-region {
89
- position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
90
- overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
91
- }
63
+ & .crisp-datepicker-live-region { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
92
64
  }
93
65
  .crisp-datepicker--visibleRange_month {
94
66