@slotted/styles 0.0.0-stage → 0.1.0-beta.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 (254) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +10 -2
  3. package/package.json +276 -3
  4. package/src/accordion/accordion.css +96 -0
  5. package/src/accordion/accordion.tokens.json +14 -0
  6. package/src/action-bar/action-bar.css +455 -0
  7. package/src/action-bar/action-bar.tokens.json +50 -0
  8. package/src/action-sheet/action-sheet.css +462 -0
  9. package/src/action-sheet/action-sheet.tokens.json +59 -0
  10. package/src/alert/alert.css +764 -0
  11. package/src/alert/alert.tokens.json +77 -0
  12. package/src/app-shell/app-shell.css +1899 -0
  13. package/src/app-shell/app-shell.tokens.json +88 -0
  14. package/src/aspect-ratio/aspect-ratio.css +131 -0
  15. package/src/aspect-ratio/aspect-ratio.tokens.json +1 -0
  16. package/src/attachment/attachment.css +906 -0
  17. package/src/attachment/attachment.tokens.json +85 -0
  18. package/src/avatar/avatar.css +598 -0
  19. package/src/avatar/avatar.tokens.json +64 -0
  20. package/src/avatar-group/avatar-group.css +268 -0
  21. package/src/avatar-group/avatar-group.tokens.json +16 -0
  22. package/src/badge/badge.css +462 -0
  23. package/src/badge/badge.tokens.json +58 -0
  24. package/src/breadcrumb/breadcrumb.css +441 -0
  25. package/src/breadcrumb/breadcrumb.tokens.json +50 -0
  26. package/src/button/button.css +754 -0
  27. package/src/button/button.tokens.json +72 -0
  28. package/src/button-group/button-group.css +455 -0
  29. package/src/button-group/button-group.tokens.json +11 -0
  30. package/src/calendar/calendar.css +846 -0
  31. package/src/calendar/calendar.tokens.json +67 -0
  32. package/src/card/card.css +602 -0
  33. package/src/card/card.tokens.json +68 -0
  34. package/src/carousel/carousel.css +860 -0
  35. package/src/carousel/carousel.tokens.json +62 -0
  36. package/src/cascader/cascader.css +1320 -0
  37. package/src/cascader/cascader.tokens.json +103 -0
  38. package/src/chart/chart.css +1473 -0
  39. package/src/chart/chart.tokens.json +107 -0
  40. package/src/checkbox/checkbox.css +1011 -0
  41. package/src/checkbox/checkbox.tokens.json +102 -0
  42. package/src/checkbox-group/checkbox-group.css +70 -0
  43. package/src/checkbox-group/checkbox-group.tokens.json +6 -0
  44. package/src/code-block/code-block.css +555 -0
  45. package/src/code-block/code-block.tokens.json +69 -0
  46. package/src/collapsible/collapsible.css +546 -0
  47. package/src/collapsible/collapsible.tokens.json +55 -0
  48. package/src/color-picker/color-picker.css +607 -0
  49. package/src/color-picker/color-picker.tokens.json +58 -0
  50. package/src/column-manager/column-manager.css +452 -0
  51. package/src/column-manager/column-manager.tokens.json +43 -0
  52. package/src/combobox/combobox.css +1048 -0
  53. package/src/combobox/combobox.tokens.json +112 -0
  54. package/src/command-palette/command-palette.css +1000 -0
  55. package/src/command-palette/command-palette.tokens.json +75 -0
  56. package/src/container/container.css +198 -0
  57. package/src/container/container.tokens.json +18 -0
  58. package/src/context-menu/context-menu.css +104 -0
  59. package/src/context-menu/context-menu.tokens.json +11 -0
  60. package/src/currency-field/currency-field.css +787 -0
  61. package/src/currency-field/currency-field.tokens.json +80 -0
  62. package/src/dashboard-grid/dashboard-grid.css +748 -0
  63. package/src/dashboard-grid/dashboard-grid.tokens.json +67 -0
  64. package/src/data-grid/data-grid.css +2484 -0
  65. package/src/data-grid/data-grid.tokens.json +100 -0
  66. package/src/data-list/data-list.css +455 -0
  67. package/src/data-list/data-list.tokens.json +35 -0
  68. package/src/date-field/date-field.css +560 -0
  69. package/src/date-field/date-field.tokens.json +80 -0
  70. package/src/date-picker/date-picker.css +420 -0
  71. package/src/date-picker/date-picker.tokens.json +49 -0
  72. package/src/date-range-picker/date-range-picker.css +983 -0
  73. package/src/date-range-picker/date-range-picker.tokens.json +109 -0
  74. package/src/datetime-field/datetime-field.css +850 -0
  75. package/src/datetime-field/datetime-field.tokens.json +91 -0
  76. package/src/datetime-picker/datetime-picker.css +843 -0
  77. package/src/datetime-picker/datetime-picker.tokens.json +78 -0
  78. package/src/datetime-range-picker/datetime-range-picker.css +1375 -0
  79. package/src/datetime-range-picker/datetime-range-picker.tokens.json +135 -0
  80. package/src/description-list/description-list.css +675 -0
  81. package/src/description-list/description-list.tokens.json +66 -0
  82. package/src/detail-panel/detail-panel.css +329 -0
  83. package/src/detail-panel/detail-panel.tokens.json +33 -0
  84. package/src/dialog/dialog.css +968 -0
  85. package/src/dialog/dialog.tokens.json +66 -0
  86. package/src/divider/divider.css +131 -0
  87. package/src/divider/divider.tokens.json +18 -0
  88. package/src/drawer/drawer.css +1303 -0
  89. package/src/drawer/drawer.tokens.json +75 -0
  90. package/src/entity-picker/entity-picker.css +1367 -0
  91. package/src/entity-picker/entity-picker.tokens.json +118 -0
  92. package/src/event-calendar/event-calendar.css +2148 -0
  93. package/src/event-calendar/event-calendar.tokens.json +87 -0
  94. package/src/field/field.css +707 -0
  95. package/src/field/field.tokens.json +58 -0
  96. package/src/field-group/field-group.css +226 -0
  97. package/src/field-group/field-group.tokens.json +33 -0
  98. package/src/filter-bar/filter-bar.css +1306 -0
  99. package/src/filter-bar/filter-bar.tokens.json +78 -0
  100. package/src/form/form.css +218 -0
  101. package/src/form/form.tokens.json +32 -0
  102. package/src/fullscreen/fullscreen.css +376 -0
  103. package/src/fullscreen/fullscreen.tokens.json +50 -0
  104. package/src/grid/grid.css +173 -0
  105. package/src/grid/grid.tokens.json +20 -0
  106. package/src/highlight/highlight.css +135 -0
  107. package/src/highlight/highlight.tokens.json +16 -0
  108. package/src/hover-card/hover-card.css +93 -0
  109. package/src/hover-card/hover-card.tokens.json +17 -0
  110. package/src/icon/icon.css +136 -0
  111. package/src/icon/icon.tokens.json +14 -0
  112. package/src/image/image.css +449 -0
  113. package/src/image/image.tokens.json +27 -0
  114. package/src/import-export-center/import-export-center.css +1175 -0
  115. package/src/import-export-center/import-export-center.tokens.json +84 -0
  116. package/src/inline/inline.css +149 -0
  117. package/src/inline/inline.tokens.json +14 -0
  118. package/src/inline-message/inline-message.css +396 -0
  119. package/src/inline-message/inline-message.tokens.json +19 -0
  120. package/src/kbd/kbd.css +490 -0
  121. package/src/kbd/kbd.tokens.json +40 -0
  122. package/src/link/link.css +237 -0
  123. package/src/link/link.tokens.json +25 -0
  124. package/src/list/list.css +240 -0
  125. package/src/list/list.tokens.json +42 -0
  126. package/src/list-item/list-item.css +937 -0
  127. package/src/list-item/list-item.tokens.json +114 -0
  128. package/src/listbox/listbox.css +674 -0
  129. package/src/listbox/listbox.tokens.json +72 -0
  130. package/src/loading-overlay/loading-overlay.css +730 -0
  131. package/src/loading-overlay/loading-overlay.tokens.json +48 -0
  132. package/src/markdown/markdown.css +168 -0
  133. package/src/markdown/markdown.tokens.json +18 -0
  134. package/src/menu/menu.css +817 -0
  135. package/src/menu/menu.tokens.json +78 -0
  136. package/src/menubar/menubar.css +170 -0
  137. package/src/menubar/menubar.tokens.json +32 -0
  138. package/src/message/message.css +1453 -0
  139. package/src/message/message.tokens.json +85 -0
  140. package/src/message-scroller/message-scroller.css +371 -0
  141. package/src/message-scroller/message-scroller.tokens.json +47 -0
  142. package/src/multi-select/multi-select.css +1427 -0
  143. package/src/multi-select/multi-select.tokens.json +114 -0
  144. package/src/navigation-menu/navigation-menu.css +1029 -0
  145. package/src/navigation-menu/navigation-menu.tokens.json +70 -0
  146. package/src/notification-center/notification-center.css +856 -0
  147. package/src/notification-center/notification-center.tokens.json +84 -0
  148. package/src/number-field/number-field.css +794 -0
  149. package/src/number-field/number-field.tokens.json +80 -0
  150. package/src/otp-input/otp-input.css +525 -0
  151. package/src/otp-input/otp-input.tokens.json +69 -0
  152. package/src/page/page.css +179 -0
  153. package/src/page/page.tokens.json +20 -0
  154. package/src/page-header/page-header.css +1181 -0
  155. package/src/page-header/page-header.tokens.json +71 -0
  156. package/src/pagination/pagination.css +500 -0
  157. package/src/pagination/pagination.tokens.json +56 -0
  158. package/src/popover/popover.css +526 -0
  159. package/src/popover/popover.tokens.json +60 -0
  160. package/src/progress-indicator/progress-indicator.css +1584 -0
  161. package/src/progress-indicator/progress-indicator.tokens.json +50 -0
  162. package/src/prompt-composer/prompt-composer.css +680 -0
  163. package/src/prompt-composer/prompt-composer.tokens.json +99 -0
  164. package/src/prose/prose.css +733 -0
  165. package/src/prose/prose.tokens.json +79 -0
  166. package/src/radio-group/radio-group.css +778 -0
  167. package/src/radio-group/radio-group.tokens.json +103 -0
  168. package/src/rating/rating.css +1071 -0
  169. package/src/rating/rating.tokens.json +88 -0
  170. package/src/result-state/result-state.css +980 -0
  171. package/src/result-state/result-state.tokens.json +63 -0
  172. package/src/runtime-properties.mjs +321 -0
  173. package/src/saved-views/saved-views.css +394 -0
  174. package/src/saved-views/saved-views.tokens.json +41 -0
  175. package/src/scroll-area/scroll-area.css +481 -0
  176. package/src/scroll-area/scroll-area.tokens.json +15 -0
  177. package/src/section/section.css +177 -0
  178. package/src/section/section.tokens.json +39 -0
  179. package/src/segmented-control/segmented-control.css +564 -0
  180. package/src/segmented-control/segmented-control.tokens.json +67 -0
  181. package/src/select/select.css +1593 -0
  182. package/src/select/select.tokens.json +110 -0
  183. package/src/side-navigation/side-navigation.css +1096 -0
  184. package/src/side-navigation/side-navigation.tokens.json +87 -0
  185. package/src/skeleton/skeleton.css +431 -0
  186. package/src/skeleton/skeleton.tokens.json +29 -0
  187. package/src/slider/slider.css +792 -0
  188. package/src/slider/slider.tokens.json +75 -0
  189. package/src/sparkline/sparkline.css +282 -0
  190. package/src/sparkline/sparkline.tokens.json +45 -0
  191. package/src/spinner/spinner.css +224 -0
  192. package/src/spinner/spinner.tokens.json +8 -0
  193. package/src/split-button/split-button.css +253 -0
  194. package/src/split-button/split-button.tokens.json +12 -0
  195. package/src/splitter/splitter.css +336 -0
  196. package/src/splitter/splitter.tokens.json +24 -0
  197. package/src/stack/stack.css +128 -0
  198. package/src/stack/stack.tokens.json +14 -0
  199. package/src/stat-card/stat-card.css +641 -0
  200. package/src/stat-card/stat-card.tokens.json +95 -0
  201. package/src/status-indicator/status-indicator.css +481 -0
  202. package/src/status-indicator/status-indicator.tokens.json +38 -0
  203. package/src/stepper/stepper.css +629 -0
  204. package/src/stepper/stepper.tokens.json +72 -0
  205. package/src/switch/switch.css +703 -0
  206. package/src/switch/switch.tokens.json +75 -0
  207. package/src/table/table.css +1482 -0
  208. package/src/table/table.tokens.json +69 -0
  209. package/src/table-of-contents/table-of-contents.css +533 -0
  210. package/src/table-of-contents/table-of-contents.tokens.json +53 -0
  211. package/src/tabs/tabs.css +998 -0
  212. package/src/tabs/tabs.tokens.json +82 -0
  213. package/src/tag/tag.css +768 -0
  214. package/src/tag/tag.tokens.json +85 -0
  215. package/src/tags-input/tags-input.css +757 -0
  216. package/src/tags-input/tags-input.tokens.json +84 -0
  217. package/src/text-field/text-field.css +900 -0
  218. package/src/text-field/text-field.tokens.json +87 -0
  219. package/src/textarea/textarea.css +365 -0
  220. package/src/textarea/textarea.tokens.json +59 -0
  221. package/src/time-field/time-field.css +719 -0
  222. package/src/time-field/time-field.tokens.json +86 -0
  223. package/src/time-picker/time-picker.css +665 -0
  224. package/src/time-picker/time-picker.tokens.json +66 -0
  225. package/src/time-range-picker/time-range-picker.css +1287 -0
  226. package/src/time-range-picker/time-range-picker.tokens.json +134 -0
  227. package/src/timeline/timeline.css +1596 -0
  228. package/src/timeline/timeline.tokens.json +96 -0
  229. package/src/toast/toast.css +943 -0
  230. package/src/toast/toast.tokens.json +90 -0
  231. package/src/toggle/toggle.css +290 -0
  232. package/src/toggle/toggle.tokens.json +54 -0
  233. package/src/toggle-group/toggle-group.css +463 -0
  234. package/src/toggle-group/toggle-group.tokens.json +54 -0
  235. package/src/toolbar/toolbar.css +434 -0
  236. package/src/toolbar/toolbar.tokens.json +49 -0
  237. package/src/tooltip/tooltip.css +368 -0
  238. package/src/tooltip/tooltip.tokens.json +39 -0
  239. package/src/top-navigation/top-navigation.css +1287 -0
  240. package/src/top-navigation/top-navigation.tokens.json +91 -0
  241. package/src/tour/tour.css +680 -0
  242. package/src/tour/tour.tokens.json +67 -0
  243. package/src/transfer/transfer.css +571 -0
  244. package/src/transfer/transfer.tokens.json +49 -0
  245. package/src/tree/tree.css +1000 -0
  246. package/src/tree/tree.tokens.json +80 -0
  247. package/src/typography/typography.css +211 -0
  248. package/src/typography/typography.tokens.json +31 -0
  249. package/src/upload/upload.css +1706 -0
  250. package/src/upload/upload.tokens.json +123 -0
  251. package/src/visually-hidden/visually-hidden.css +52 -0
  252. package/src/visually-hidden/visually-hidden.tokens.json +1 -0
  253. package/src/wizard/wizard.css +740 -0
  254. package/src/wizard/wizard.tokens.json +63 -0
@@ -0,0 +1,856 @@
1
+ @layer slotted.components {
2
+ /**
3
+ * The persistent list of what happened while the reader was not looking.
4
+ *
5
+ * ┌──────────────────────────────────────────────────────┐
6
+ * │ header ▸ title (count) · mark-all · actions │
7
+ * ├──────────────────────────────────────────────────────┤
8
+ * │ views ▸ tabs (list only) │
9
+ * ├──────────────────────────────────────────────────────┤
10
+ * │ fresh ▸ "3 novas notificações" │
11
+ * │ feed ▸ (group ▸ group-label ·) item … │
12
+ * │ item ▸ unread · visual · content ▸ title │
13
+ * │ description │
14
+ * │ time · actions │
15
+ * │ controls ▸ read-toggle · │
16
+ * │ dismiss │
17
+ * │ more │
18
+ * │ empty │
19
+ * ├──────────────────────────────────────────────────────┤
20
+ * │ footer │
21
+ * └──────────────────────────────────────────────────────┘
22
+ *
23
+ * A notification is a row with a dot, not an event on a rail: the Feed
24
+ * keyboard and the timestamp are `@slotted/core/timeline`'s, the paint is
25
+ * this family's. The tabs strip, the badge, the buttons, the skeleton and
26
+ * the result-state inside are theirs, reached with child combinators so a
27
+ * `title`, an `actions` or a `description` of theirs is never restyled.
28
+ */
29
+ [data-ui='notification-center'] {
30
+ --_text: var(--slotted-text, CanvasText);
31
+ --_muted: var(--slotted-text-muted, GrayText);
32
+ --_rule: var(--slotted-notification-center-border, var(--slotted-border-subtle, ButtonBorder));
33
+ --_ground: var(--slotted-notification-center-background, var(--slotted-surface, Canvas));
34
+ --_hover: var(--slotted-tone-secondary-subtle-hover, ButtonFace);
35
+ --_active: var(--slotted-tone-secondary-subtle-active, ButtonFace);
36
+ /**
37
+ * The item's tone: the colour of the family's own visual, and the tint
38
+ * an unread item stands on. Accent unless the item says otherwise. The
39
+ * glyph the visual draws is the binding's, from the contract's `toneGlyph`.
40
+ */
41
+ --_tone-solid: var(--slotted-tone-accent-solid, Highlight);
42
+ --_tone-text: var(--slotted-tone-accent-text, Highlight);
43
+ --_tone-surface: var(--slotted-tone-accent-surface, Canvas);
44
+ /**
45
+ * An unread item stands on a wash mixed from the tone's text at the
46
+ * highlight share, for the reason the highlight band does: a tone's
47
+ * surface role is a ground and does not separate from the surface it
48
+ * sits on, and this wash has to be seen beside a read item on the same
49
+ * surface.
50
+ */
51
+ --_unread-ground: color-mix(
52
+ in oklab,
53
+ var(--_tone-text) calc(var(--slotted-highlight-tint-opacity, 0.075) * 100%),
54
+ transparent
55
+ );
56
+ --_inset-inline: var(
57
+ --slotted-notification-center-inset-inline-md,
58
+ var(--slotted-space-6, 1rem)
59
+ );
60
+ --_inset-block: var(
61
+ --slotted-notification-center-inset-block-md,
62
+ var(--slotted-space-5, 0.75rem)
63
+ );
64
+ --_gap: var(--slotted-notification-center-gap-md, var(--slotted-space-5, 0.75rem));
65
+ --_title-size: var(
66
+ --slotted-notification-center-title-size-md,
67
+ var(--slotted-font-size-lg, 1rem)
68
+ );
69
+ --_title-line-height: var(--slotted-line-height-lg, 1.5);
70
+ --_item-title-size: var(--slotted-font-size-md, 0.875rem);
71
+ --_item-title-line-height: var(--slotted-line-height-md, 1.5);
72
+ --_meta-size: var(--slotted-font-size-sm, 0.8125rem);
73
+ --_meta-line-height: var(--slotted-line-height-sm, 1.45);
74
+ /**
75
+ * The visual: the consumer's avatar at its small step, or the family's
76
+ * own — the tone's glyph in a tinted circle of the same size — for an
77
+ * item with a tone and no visual. A row with neither has no visual and
78
+ * the words take the column.
79
+ *
80
+ * Unread is said by the wash and the semibold title; no dot, and no
81
+ * fill on the visual. A dot in a column of its own read as a bullet, a
82
+ * disc on the title's line sat off the avatar's axis, a dot on a visual
83
+ * that already carries the tone said the tone twice, and a solid circle
84
+ * shouted beside the avatars around it.
85
+ */
86
+ --_visual: var(--slotted-avatar-size-sm, 28px);
87
+ --_visual-glyph: calc(var(--_visual) * 6 / 7);
88
+ /** A count beside words: a chip a step below the meta size, on the sunken surface. */
89
+ --_count-size: var(--slotted-font-size-xs, 0.75rem);
90
+ --_count-box: calc(
91
+ var(--_count-size) + 2 * var(--slotted-space-1, 0.125rem) + 2 *
92
+ var(--slotted-border-width-thin, 1px)
93
+ );
94
+ /** The family's own icon controls: the glyph at the small control step, the box capped by the inner-control scale. */
95
+ --_glyph: var(--slotted-control-icon-size-sm, 14px);
96
+ --_control: min(
97
+ calc(var(--_glyph) + 2 * var(--slotted-space-2, 0.25rem)),
98
+ var(--slotted-control-inner-size-md, 24px)
99
+ );
100
+ --_rule-size: var(--slotted-border-width-thin, 1px);
101
+ --_duration: var(--slotted-control-transition-duration);
102
+ --_easing: var(--slotted-control-transition-easing);
103
+ /**
104
+ * The feed's bar, where a host bounds the feed: the thumb at the strong
105
+ * border step, as `scroll-area` and `app-shell` draw it; the track the
106
+ * centre's own ground, so a groove does not stand beside the rows.
107
+ */
108
+ --_scrollbar-thumb: var(
109
+ --slotted-notification-center-scrollbar-thumb-color,
110
+ var(--slotted-border-strong, ButtonBorder)
111
+ );
112
+ --_scrollbar-track: var(--slotted-notification-center-scrollbar-track-color, transparent);
113
+
114
+ background-color: var(--_ground);
115
+ color: var(--_text);
116
+ container-name: notification-center;
117
+ container-type: inline-size;
118
+ display: flex;
119
+ flex-direction: column;
120
+ font-family: var(--slotted-font-family-sans, ui-sans-serif, system-ui, sans-serif);
121
+ min-inline-size: 0;
122
+ }
123
+
124
+ /** In the popover: the small control step, tighter insets, a smaller title. */
125
+ /**
126
+ * The popover's step. A root with inline-size containment contributes no
127
+ * intrinsic width, so inside a panel sized to its content — a popover — it
128
+ * would collapse to nothing; `sm` states a floor, capped by the viewport
129
+ * for a phone, and `100%` keeps it filling a host that has a width.
130
+ */
131
+ [data-ui='notification-center'][data-size='sm'] {
132
+ min-inline-size: var(
133
+ --slotted-notification-center-min-inline-size-sm,
134
+ min(22rem, calc(100vw - var(--slotted-space-8, 2rem)))
135
+ );
136
+ --_inset-inline: var(
137
+ --slotted-notification-center-inset-inline-sm,
138
+ var(--slotted-space-5, 0.75rem)
139
+ );
140
+ --_inset-block: var(
141
+ --slotted-notification-center-inset-block-sm,
142
+ var(--slotted-space-4, 0.5rem)
143
+ );
144
+ --_gap: var(--slotted-notification-center-gap-sm, var(--slotted-space-4, 0.5rem));
145
+ --_title-size: var(
146
+ --slotted-notification-center-title-size-sm,
147
+ var(--slotted-font-size-md, 0.875rem)
148
+ );
149
+ --_title-line-height: var(--slotted-line-height-md, 1.5);
150
+ --_item-title-size: var(--slotted-font-size-sm, 0.8125rem);
151
+ --_item-title-line-height: var(--slotted-line-height-sm, 1.45);
152
+ --_meta-size: var(--slotted-font-size-xs, 0.75rem);
153
+ --_meta-line-height: var(--slotted-line-height-xs, 1.4);
154
+ --_control: min(
155
+ calc(var(--_glyph) + 2 * var(--slotted-space-2, 0.25rem)),
156
+ var(--slotted-control-inner-size-sm, 22px)
157
+ );
158
+ --_visual: var(--slotted-avatar-size-xs, 24px);
159
+ --_visual-glyph: calc(var(--_visual) * 6 / 7);
160
+ }
161
+
162
+ /* ── The header ──────────────────────────────────────────────────────── */
163
+
164
+ /**
165
+ * The title pushes the rest to the end; a control that wraps lands at the
166
+ * end of its own line, under the one before it, not at the start.
167
+ */
168
+ [data-ui='notification-center'] > [data-part='header'] {
169
+ align-items: center;
170
+ border-block-end: var(--_rule-size) solid var(--_rule);
171
+ display: flex;
172
+ flex-wrap: wrap;
173
+ gap: var(--slotted-space-3, 0.375rem) var(--_gap);
174
+ justify-content: flex-end;
175
+ min-inline-size: 0;
176
+ padding-block: var(--_inset-block);
177
+ padding-inline: var(--_inset-inline);
178
+ }
179
+
180
+ [data-ui='notification-center'] > [data-part='header'] > [data-part='title'] {
181
+ align-items: center;
182
+ color: var(--_text);
183
+ display: inline-flex;
184
+ font-family: var(
185
+ --slotted-font-family-heading,
186
+ var(--slotted-font-family-sans, ui-sans-serif, system-ui, sans-serif)
187
+ );
188
+ font-size: var(--_title-size);
189
+ font-weight: var(--slotted-font-weight-semibold, 600);
190
+ gap: var(--slotted-space-3, 0.375rem);
191
+ letter-spacing: -0.01em;
192
+ line-height: var(--_title-line-height);
193
+ margin: 0;
194
+ margin-inline-end: auto;
195
+ min-inline-size: 0;
196
+ }
197
+
198
+ /**
199
+ * A count beside words — the unread total after the title, the size of a
200
+ * view in its tab: a chip on the type scale's smallest step, in tabular
201
+ * figures, on the sunken surface so it reads as a figure and not as a
202
+ * status. On the header it takes the accent pair, because what it counts
203
+ * is what waits.
204
+ */
205
+ /** One measure for both dimensions: a single digit is a circle, two digits a pill. */
206
+ [data-ui='notification-center'] [data-part='count'] {
207
+ align-items: center;
208
+ background-color: var(--slotted-surface-sunken, Canvas);
209
+ block-size: var(--_count-box);
210
+ border-radius: var(--slotted-radius-full, 9999px);
211
+ border: var(--slotted-border-width-thin, 1px) solid
212
+ color-mix(in oklab, currentcolor 20%, transparent);
213
+ box-sizing: border-box;
214
+ color: var(--_muted);
215
+ display: inline-flex;
216
+ font-size: var(--_count-size);
217
+ font-variant-numeric: tabular-nums;
218
+ font-weight: var(--slotted-font-weight-semibold, 600);
219
+ justify-content: center;
220
+ line-height: 1;
221
+ min-inline-size: var(--_count-box);
222
+ padding-block: 0;
223
+ padding-inline: var(--slotted-space-2, 0.25rem);
224
+ }
225
+
226
+ [data-ui='notification-center']
227
+ > [data-part='header']
228
+ > [data-part='title']
229
+ > [data-part='count'] {
230
+ background-color: var(--slotted-tone-accent-surface, Canvas);
231
+ color: var(--slotted-tone-accent-text, Highlight);
232
+ }
233
+
234
+ /** The slot a Button sits in, pushed to the end of the row; the consumer's actions after it. */
235
+ [data-ui='notification-center'] > [data-part='header'] > [data-part='mark-all'] {
236
+ display: inline-flex;
237
+ }
238
+
239
+ /** The consumer's controls read at the row's meta size: a link beside a small button, not beside the title. */
240
+ [data-ui='notification-center'] > [data-part='header'] > [data-part='actions'] {
241
+ align-items: center;
242
+ display: inline-flex;
243
+ font-size: var(--_meta-size);
244
+ gap: var(--slotted-control-gap-sm, 6px);
245
+ line-height: var(--_meta-line-height);
246
+ }
247
+
248
+ /* ── The views ───────────────────────────────────────────────────────── */
249
+
250
+ /**
251
+ * The strip sits on the header's rule, so the tabs family's own track is
252
+ * off (`track="none"`) and the marker lands on the line the header drew.
253
+ */
254
+ [data-ui='notification-center'] > [data-part='views'] {
255
+ border-block-end: var(--_rule-size) solid var(--_rule);
256
+ min-inline-size: 0;
257
+ padding-inline: var(--_inset-inline);
258
+ }
259
+
260
+ /* ── Fresh and more ──────────────────────────────────────────────────── */
261
+
262
+ /**
263
+ * Two things that are not notifications: the held arrivals, and the end of
264
+ * what has been loaded. Both are family-drawn pills on the control scale,
265
+ * the idiom `timeline` set for the same two controls; `fresh` in the accent
266
+ * pair so it reads as something new, `more` in the secondary.
267
+ */
268
+ [data-ui='notification-center'] > [data-part='fresh'],
269
+ [data-ui='notification-center'] > button[data-part='more'] {
270
+ align-items: center;
271
+ appearance: none;
272
+ background-color: var(--_ground);
273
+ border: var(--_rule-size) solid var(--_rule);
274
+ border-radius: var(--slotted-radius-full, 9999px);
275
+ color: var(--_text);
276
+ cursor: pointer;
277
+ display: flex;
278
+ font: inherit;
279
+ font-size: var(--_meta-size);
280
+ font-weight: var(--slotted-font-weight-medium, 500);
281
+ gap: var(--slotted-control-gap-sm, 6px);
282
+ inline-size: fit-content;
283
+ justify-content: center;
284
+ line-height: var(--slotted-control-line-height, 1);
285
+ margin-block: var(--_inset-block);
286
+ margin-inline: auto;
287
+ min-block-size: var(--slotted-control-height-sm, 30px);
288
+ padding-inline: var(--slotted-control-padding-inline-md, 13px);
289
+ transition:
290
+ background-color var(--_duration) var(--_easing),
291
+ border-color var(--_duration) var(--_easing),
292
+ color var(--_duration) var(--_easing);
293
+ }
294
+
295
+ [data-ui='notification-center'] > [data-part='fresh'] {
296
+ background-color: var(--slotted-tone-accent-surface, Canvas);
297
+ border-color: var(--slotted-tone-accent-border, Highlight);
298
+ color: var(--slotted-tone-accent-text, Highlight);
299
+ }
300
+
301
+ [data-ui='notification-center'] > [data-part='fresh']:enabled:hover {
302
+ background-color: var(--slotted-tone-accent-subtle-hover, Canvas);
303
+ }
304
+
305
+ [data-ui='notification-center'] > [data-part='fresh']:enabled:active {
306
+ background-color: var(--slotted-tone-accent-subtle-active, Canvas);
307
+ }
308
+
309
+ [data-ui='notification-center'] > button[data-part='more']:enabled:hover {
310
+ background-color: var(--_hover);
311
+ }
312
+
313
+ [data-ui='notification-center'] > button[data-part='more']:enabled:active {
314
+ background-color: var(--_active);
315
+ }
316
+
317
+ [data-ui='notification-center'] > button[data-part='more']:disabled {
318
+ color: var(--slotted-disabled-foreground, GrayText);
319
+ cursor: default;
320
+ }
321
+
322
+ /** Under growing=scroll the sentinel is a box the observer watches, and it says it is waiting. */
323
+ [data-ui='notification-center'] > div[data-part='more'] {
324
+ color: var(--_muted);
325
+ font-size: var(--_meta-size);
326
+ line-height: var(--_meta-line-height);
327
+ min-block-size: var(--slotted-space-6, 1rem);
328
+ padding-block: var(--_inset-block);
329
+ padding-inline: var(--_inset-inline);
330
+ text-align: center;
331
+ }
332
+
333
+ [data-ui='notification-center'] > [data-part='fresh']:focus-visible,
334
+ [data-ui='notification-center'] > button[data-part='more']:focus-visible {
335
+ outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
336
+ outline-offset: var(--slotted-focus-ring-offset, 2px);
337
+ }
338
+
339
+ /* ── The feed ────────────────────────────────────────────────────────── */
340
+
341
+ /**
342
+ * The one part that gives way. A host with a height — the popover under the
343
+ * bell, whose panel is bounded by the room the positioner reports — bounds
344
+ * the feed alone: the header, the views and the footer keep their rows and
345
+ * the feed scrolls between them, which is what GitHub's and Linear's inboxes
346
+ * do. A host with no height, a page, gets the whole feed and no bar. The bar
347
+ * is `scroll-area`'s: a reserved gutter so the rows do not move when the
348
+ * feed grows past the panel, the thin platform bar, the family's ink on it.
349
+ */
350
+ [data-ui='notification-center'] > [data-part='feed'] {
351
+ display: flex;
352
+ flex: 1 1 auto;
353
+ flex-direction: column;
354
+ min-block-size: 0;
355
+ min-inline-size: 0;
356
+ overflow-y: auto;
357
+ overscroll-behavior: contain;
358
+ scrollbar-color: var(--_scrollbar-thumb) var(--_scrollbar-track);
359
+ scrollbar-gutter: stable;
360
+ scrollbar-width: thin;
361
+ }
362
+
363
+ /** The footer draws its own rule above, so the last row gives up the one below it: one seam, not two. */
364
+ [data-ui='notification-center']
365
+ > [data-part='feed']:has(+ [data-part='footer'])
366
+ > [data-part='item']:last-child,
367
+ [data-ui='notification-center']
368
+ > [data-part='feed']:has(+ [data-part='footer'])
369
+ > [data-part='group']:last-child
370
+ > [data-part='item']:last-child {
371
+ border-block-end: 0;
372
+ }
373
+
374
+ [data-ui='notification-center'] > [data-part='feed'] > [data-part='group'] {
375
+ display: flex;
376
+ flex-direction: column;
377
+ min-inline-size: 0;
378
+ }
379
+
380
+ /**
381
+ * A group's heading: an overline in the muted text, on the feed's inset, so
382
+ * the groups read as one list with dates between rather than as boxes.
383
+ */
384
+ [data-ui='notification-center']
385
+ > [data-part='feed']
386
+ > [data-part='group']
387
+ > [data-part='group-label'] {
388
+ color: var(--_muted);
389
+ font-size: var(--slotted-font-size-xs, 0.75rem);
390
+ font-weight: var(--slotted-font-weight-semibold, 600);
391
+ letter-spacing: 0.06em;
392
+ line-height: var(--slotted-line-height-xs, 1.4);
393
+ margin: 0;
394
+ padding-block: var(--_inset-block) var(--slotted-space-2, 0.25rem);
395
+ padding-inline: var(--_inset-inline);
396
+ text-transform: uppercase;
397
+ }
398
+
399
+ /* ── An item ─────────────────────────────────────────────────────────── */
400
+
401
+ /**
402
+ * One row: the visual, the content, the two controls at the end. A rule under each, so a list of forty reads as
403
+ * rows and not as a column of cards. The visual, the title's first line
404
+ * and the controls are centred on one axis.
405
+ */
406
+ [data-ui='notification-center'] > [data-part='feed'] [data-part='item'] {
407
+ align-items: flex-start;
408
+ border-block-end: var(--_rule-size) solid var(--_rule);
409
+ display: grid;
410
+ gap: 0 var(--slotted-space-4, 0.5rem);
411
+ grid-template-columns: auto minmax(0, 1fr) auto;
412
+ min-inline-size: 0;
413
+ padding-block: var(--_inset-block);
414
+ padding-inline: var(--_inset-inline);
415
+ position: relative;
416
+ transition: background-color var(--_duration) var(--_easing);
417
+ }
418
+
419
+ [data-ui='notification-center'] > [data-part='feed'] [data-part='item'][data-tone='secondary'] {
420
+ --_tone-solid: var(--slotted-tone-secondary-solid, ButtonText);
421
+ --_tone-text: var(--slotted-tone-secondary-text, ButtonText);
422
+ --_tone-surface: var(--slotted-tone-secondary-surface, Canvas);
423
+ }
424
+ [data-ui='notification-center'] > [data-part='feed'] [data-part='item'][data-tone='success'] {
425
+ --_tone-solid: var(--slotted-tone-success-solid, ButtonText);
426
+ --_tone-text: var(--slotted-tone-success-text, ButtonText);
427
+ --_tone-surface: var(--slotted-tone-success-surface, Canvas);
428
+ }
429
+ [data-ui='notification-center'] > [data-part='feed'] [data-part='item'][data-tone='warning'] {
430
+ --_tone-solid: var(--slotted-tone-warning-solid, ButtonText);
431
+ --_tone-text: var(--slotted-tone-warning-text, ButtonText);
432
+ --_tone-surface: var(--slotted-tone-warning-surface, Canvas);
433
+ }
434
+ [data-ui='notification-center'] > [data-part='feed'] [data-part='item'][data-tone='danger'] {
435
+ --_tone-solid: var(--slotted-tone-danger-solid, ButtonText);
436
+ --_tone-text: var(--slotted-tone-danger-text, ButtonText);
437
+ --_tone-surface: var(--slotted-tone-danger-surface, Canvas);
438
+ }
439
+
440
+ /** Unread stands on the wash; read stands on the surface. The dot says the same thing a second way. */
441
+ [data-ui='notification-center'] > [data-part='feed'] [data-part='item']:not([data-read]) {
442
+ background-color: var(--_unread-ground);
443
+ }
444
+
445
+ /**
446
+ * The row answers the pointer as a row does, and the guard is the
447
+ * vocabulary's: an item is never disabled, and the rule says so where the
448
+ * states test looks.
449
+ */
450
+ [data-ui='notification-center']
451
+ > [data-part='feed']
452
+ [data-part='item']:not([data-disabled]):hover {
453
+ background-color: var(--_hover);
454
+ }
455
+
456
+ /**
457
+ * The article is in the tab sequence, which is where PageDown lands. Its
458
+ * ring is drawn inward, because the rows touch and an outward ring would be
459
+ * cut by the neighbours.
460
+ */
461
+ [data-ui='notification-center'] > [data-part='feed'] [data-part='item']:focus-visible {
462
+ outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
463
+ outline-offset: calc(var(--slotted-focus-ring-offset, 2px) * -1);
464
+ }
465
+
466
+ [data-ui='notification-center'] > [data-part='feed'] [data-part='item'] > [data-part='visual'] {
467
+ align-items: center;
468
+ display: flex;
469
+ grid-column: 1;
470
+ justify-content: center;
471
+ min-inline-size: 0;
472
+ }
473
+
474
+ /** Without a visual the words take the column. */
475
+ [data-ui='notification-center']
476
+ > [data-part='feed']
477
+ [data-part='item']:not(:has(> [data-part='visual']))
478
+ > [data-part='content'] {
479
+ grid-column: 1 / 3;
480
+ }
481
+
482
+ /**
483
+ * The family's visual: the tone's glyph, filled. Every tone glyph but the
484
+ * bell is a ring with a mark in it, and the ring is what the visual is
485
+ * bounded by: the tone's surface is painted as a disc under the glyph,
486
+ * with the radius the ring is drawn at on the icon grid — ten units of
487
+ * twenty-four — so the ring is the disc's own edge and the mark stands
488
+ * inside it. The disc and the glyph are two pseudo-elements on one box,
489
+ * the same size at the same place, so the two are concentric by
490
+ * construction. What stood here before was a disc with an edge of its own
491
+ * and a smaller ringed glyph on top — a circle drawn inside a circle —
492
+ * and at a zoom or a density where the two rounded to different pixels
493
+ * the inner one sat visibly off centre. A bare glyph, tried in between,
494
+ * read as a coloured mark left loose in the column.
495
+ *
496
+ * The glyph is the size the avatar beside it is, less the step the icon
497
+ * grid keeps clear, so the filled ring is the avatar's own diameter. The
498
+ * wrapper carries the tone only when the item states one; a wrapper a
499
+ * consumer's template left empty on an untoned item is withdrawn, so the
500
+ * words keep the column.
501
+ *
502
+ * The binding renders the tone's glyph in an icon box marked
503
+ * `data-tone-glyph`, which is what tells the family's visual from an icon
504
+ * the consumer put there. The disc is the wrapper's own background, centred
505
+ * on the box the glyph is centred in, so the two stay concentric.
506
+ */
507
+ [data-ui='notification-center']
508
+ > [data-part='feed']
509
+ [data-part='item']
510
+ > [data-part='visual']:empty:not([data-tone]) {
511
+ display: none;
512
+ }
513
+
514
+ /**
515
+ * The disc: the ring's own radius on the grid, less a half unit so the
516
+ * fill stops under the stroke rather than beside it, cut in lengths
517
+ * rather than percentages of the ray (Chrome paints a `calc(100% - …)`
518
+ * stop as a ramp several pixels wide).
519
+ */
520
+ [data-ui='notification-center']
521
+ > [data-part='feed']
522
+ [data-part='item']
523
+ > [data-part='visual'][data-tone]:has(> [data-tone-glyph]) {
524
+ --slotted-icon-size: var(--_visual-glyph);
525
+
526
+ align-items: center;
527
+ background-image: radial-gradient(
528
+ circle,
529
+ var(--_tone-surface) calc(var(--_visual-glyph) * 9.5 / 24 - 0.5px),
530
+ transparent calc(var(--_visual-glyph) * 9.5 / 24 + 0.5px)
531
+ );
532
+ block-size: var(--_visual);
533
+ color: var(--_tone-text);
534
+ display: flex;
535
+ inline-size: var(--_visual);
536
+ justify-content: center;
537
+ }
538
+
539
+ /**
540
+ * The content's type is the title's, so `1lh` here is the title's first
541
+ * line and the offset centres that line on the visual — a visual taller
542
+ * than the line pushes the words down, never the other way.
543
+ */
544
+ [data-ui='notification-center'] > [data-part='feed'] [data-part='item'] > [data-part='content'] {
545
+ display: flex;
546
+ flex-direction: column;
547
+ font-size: var(--_item-title-size);
548
+ gap: var(--slotted-space-1, 0.125rem);
549
+ grid-column: 2;
550
+ line-height: var(--_item-title-line-height);
551
+ margin-block-start: max(0px, calc((var(--_visual) - 1lh) / 2));
552
+ min-inline-size: 0;
553
+ }
554
+
555
+ [data-ui='notification-center']
556
+ > [data-part='feed']
557
+ [data-part='item']
558
+ > [data-part='content']
559
+ > [data-part='title'] {
560
+ -webkit-box-orient: vertical;
561
+ -webkit-line-clamp: var(--slotted-notification-center-title-clamp, 2);
562
+ color: var(--_text);
563
+ display: -webkit-box;
564
+ font-size: var(--_item-title-size);
565
+ font-weight: var(--slotted-font-weight-medium, 500);
566
+ line-height: var(--_item-title-line-height);
567
+ margin: 0;
568
+ overflow: hidden;
569
+ overflow-wrap: anywhere;
570
+ text-decoration: none;
571
+ }
572
+
573
+ /** Unread says so with weight as well as with the dot and the wash. */
574
+ [data-ui='notification-center']
575
+ > [data-part='feed']
576
+ [data-part='item']:not([data-read])
577
+ > [data-part='content']
578
+ > [data-part='title'] {
579
+ font-weight: var(--slotted-font-weight-semibold, 600);
580
+ }
581
+
582
+ /**
583
+ * A title that is a link covers the row: the press anywhere on the item
584
+ * opens the thing, and the controls stand above it so they take their own
585
+ * press. The ring stays on the article, which is what has focus.
586
+ */
587
+ [data-ui='notification-center']
588
+ > [data-part='feed']
589
+ [data-part='item']
590
+ > [data-part='content']
591
+ > a[data-part='title']::after {
592
+ content: '';
593
+ inset: 0;
594
+ position: absolute;
595
+ }
596
+
597
+ [data-ui='notification-center']
598
+ > [data-part='feed']
599
+ [data-part='item']
600
+ > [data-part='content']
601
+ > a[data-part='title']:not([data-disabled]):hover {
602
+ text-decoration: underline;
603
+ text-underline-offset: 0.15em;
604
+ }
605
+
606
+ [data-ui='notification-center']
607
+ > [data-part='feed']
608
+ [data-part='item']
609
+ > [data-part='content']
610
+ > a[data-part='title']:focus-visible {
611
+ outline: none;
612
+ }
613
+
614
+ [data-ui='notification-center']
615
+ > [data-part='feed']
616
+ [data-part='item']
617
+ > [data-part='content']
618
+ > [data-part='description'] {
619
+ -webkit-box-orient: vertical;
620
+ -webkit-line-clamp: var(--slotted-notification-center-description-clamp, 3);
621
+ color: var(--_muted);
622
+ display: -webkit-box;
623
+ font-size: var(--_meta-size);
624
+ line-height: var(--_meta-line-height);
625
+ margin: 0;
626
+ overflow: hidden;
627
+ overflow-wrap: anywhere;
628
+ }
629
+
630
+ [data-ui='notification-center']
631
+ > [data-part='feed']
632
+ [data-part='item']
633
+ > [data-part='content']
634
+ > [data-part='time'] {
635
+ color: var(--_muted);
636
+ font-size: var(--_meta-size);
637
+ font-variant-numeric: tabular-nums;
638
+ line-height: var(--_meta-line-height);
639
+ }
640
+
641
+ /** The consumer's controls for the item, above the covering link. */
642
+ [data-ui='notification-center']
643
+ > [data-part='feed']
644
+ [data-part='item']
645
+ > [data-part='content']
646
+ > [data-part='actions'] {
647
+ align-items: center;
648
+ display: flex;
649
+ flex-wrap: wrap;
650
+ gap: var(--slotted-control-gap-sm, 6px);
651
+ margin-block-start: var(--slotted-space-2, 0.25rem);
652
+ position: relative;
653
+ z-index: 1;
654
+ }
655
+
656
+ /* ── The family's controls ───────────────────────────────────────────── */
657
+
658
+ [data-ui='notification-center'] > [data-part='feed'] [data-part='item'] > [data-part='controls'] {
659
+ display: flex;
660
+ gap: var(--slotted-space-1, 0.125rem);
661
+ grid-column: 3;
662
+ /* Centred on the same axis as the visual. */
663
+ margin-block-start: max(0px, calc((var(--_visual) - var(--_control)) / 2));
664
+ position: relative;
665
+ z-index: 1;
666
+ }
667
+
668
+ /**
669
+ * Two icon controls the family draws itself: mark read or unread, and
670
+ * dismiss. Each box is the glyph plus a step of air a side, capped by the
671
+ * inner-control scale, and the hit area is taken to the target minimum by a
672
+ * transparent halo — the same construction the row's copy control in
673
+ * description-list uses. The binding renders the glyph: `check` while
674
+ * unread, `dot` while read (the control offers to mark it unread), and `x`
675
+ * to dismiss; the control hands its icon box the glyph size.
676
+ */
677
+ [data-ui='notification-center']
678
+ > [data-part='feed']
679
+ [data-part='item']
680
+ > [data-part='controls']
681
+ > button {
682
+ --slotted-icon-size: var(--_glyph);
683
+
684
+ align-items: center;
685
+ appearance: none;
686
+ background: none;
687
+ block-size: var(--_control);
688
+ border: 0;
689
+ border-radius: var(--slotted-control-radius, 4px);
690
+ color: var(--_muted);
691
+ cursor: pointer;
692
+ display: inline-flex;
693
+ font: inherit;
694
+ inline-size: var(--_control);
695
+ justify-content: center;
696
+ padding: 0;
697
+ position: relative;
698
+ transition:
699
+ color var(--_duration) var(--_easing),
700
+ background-color var(--_duration) var(--_easing);
701
+ }
702
+
703
+ [data-ui='notification-center']
704
+ > [data-part='feed']
705
+ [data-part='item']
706
+ > [data-part='controls']
707
+ > button::before {
708
+ /* The halo: the target minimum, centred on the box, taking the press and drawing nothing. */
709
+ block-size: max(var(--_control), var(--slotted-target-min, 24px));
710
+ content: '';
711
+ inline-size: max(var(--_control), var(--slotted-target-min, 24px));
712
+ inset-block-start: 50%;
713
+ inset-inline-start: 50%;
714
+ position: absolute;
715
+ translate: -50% -50%;
716
+ }
717
+
718
+ [data-ui='notification-center']
719
+ > [data-part='feed']
720
+ [data-part='item']
721
+ > [data-part='controls']
722
+ > button:enabled:hover {
723
+ background-color: var(--_hover);
724
+ color: var(--_text);
725
+ }
726
+
727
+ [data-ui='notification-center']
728
+ > [data-part='feed']
729
+ [data-part='item']
730
+ > [data-part='controls']
731
+ > button:enabled:active {
732
+ background-color: var(--_active);
733
+ }
734
+
735
+ [data-ui='notification-center']
736
+ > [data-part='feed']
737
+ [data-part='item']
738
+ > [data-part='controls']
739
+ > button:focus-visible {
740
+ outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
741
+ outline-offset: var(--slotted-focus-ring-offset, 2px);
742
+ }
743
+
744
+ /** The `controls` axis: a product with its own triage keeps one of the two, or neither. */
745
+ [data-ui='notification-center'][data-controls='read']
746
+ > [data-part='feed']
747
+ [data-part='item']
748
+ > [data-part='controls']
749
+ > [data-part='dismiss'],
750
+ [data-ui='notification-center'][data-controls='dismiss']
751
+ > [data-part='feed']
752
+ [data-part='item']
753
+ > [data-part='controls']
754
+ > [data-part='read-toggle'],
755
+ [data-ui='notification-center'][data-controls='none']
756
+ > [data-part='feed']
757
+ [data-part='item']
758
+ > [data-part='controls'] {
759
+ display: none;
760
+ }
761
+
762
+ /* ── Loading, empty and the footer ───────────────────────────────────── */
763
+
764
+ /** The waiting rows are skeleton's; the family gives them the item's inset and rule, and no wash. */
765
+ [data-ui='notification-center'] > [data-part='feed'] > [data-part='item'][aria-hidden] {
766
+ background-color: transparent;
767
+ }
768
+
769
+ [data-ui='notification-center'] > [data-part='empty'] {
770
+ color: var(--_muted);
771
+ display: grid;
772
+ font-size: var(--_meta-size);
773
+ line-height: var(--_meta-line-height);
774
+ min-block-size: calc(2 * var(--slotted-space-12, 4rem));
775
+ padding-block: var(--_inset-block);
776
+ padding-inline: var(--_inset-inline);
777
+ place-items: center;
778
+ text-align: center;
779
+ }
780
+
781
+ [data-ui='notification-center'] > [data-part='footer'] {
782
+ align-items: center;
783
+ border-block-start: var(--_rule-size) solid var(--_rule);
784
+ display: flex;
785
+ font-size: var(--_meta-size);
786
+ gap: var(--_gap);
787
+ justify-content: center;
788
+ line-height: var(--_meta-line-height);
789
+ margin-block-start: auto;
790
+ padding-block: var(--_inset-block);
791
+ padding-inline: var(--_inset-inline);
792
+ }
793
+
794
+ /* ── Narrow ──────────────────────────────────────────────────────────── */
795
+
796
+ /**
797
+ * Below 320 pixels — a popover on a narrow phone — the controls drop under the
798
+ * content rather than squeezing it, and the header's actions wrap under
799
+ * the title.
800
+ */
801
+ @container notification-center (max-width: 319px) {
802
+ [data-ui='notification-center'] > [data-part='feed'] [data-part='item'] {
803
+ grid-template-columns: auto minmax(0, 1fr);
804
+ }
805
+
806
+ [data-ui='notification-center']
807
+ > [data-part='feed']
808
+ [data-part='item']
809
+ > [data-part='controls'] {
810
+ grid-column: 2;
811
+ justify-content: flex-end;
812
+ margin-block-start: var(--slotted-space-2, 0.25rem);
813
+ }
814
+ }
815
+
816
+ /* ── On a finger ─────────────────────────────────────────────────────── */
817
+
818
+ /**
819
+ * The two controls are a glyph with a step of air a side, and the halo
820
+ * that takes the press is the target minimum. A finger is not a pointer:
821
+ * the theme raises every control it owns to `--slotted-target-comfortable`
822
+ * under a coarse pointer, and these are the family's own, so the family
823
+ * raises them. The box grows rather than the halo, so two controls side by
824
+ * side keep their distance instead of sharing one press; the glyph stays
825
+ * its size. A box taller than the visual is centred on the visual's axis,
826
+ * which puts its top above the row's inset — the box is transparent, and
827
+ * the halo already reached there.
828
+ */
829
+ @media (pointer: coarse) {
830
+ [data-ui='notification-center']
831
+ > [data-part='feed']
832
+ [data-part='item']
833
+ > [data-part='controls'] {
834
+ --_control: var(--slotted-target-comfortable, 44px);
835
+
836
+ margin-block-start: calc((var(--_visual) - var(--_control)) / 2);
837
+ }
838
+ }
839
+
840
+ /* ── Forced colours ──────────────────────────────────────────────────── */
841
+
842
+ /**
843
+ * The glyphs are `Glyph` elements drawn in their box's ink, which the
844
+ * system has already forced. The count takes the highlight pair as
845
+ * top-navigation's does; the wash under unread is gone, so the weight
846
+ * carries unread.
847
+ */
848
+ @media (forced-colors: active) {
849
+ [data-ui='notification-center'] [data-part='count'] {
850
+ background-color: Highlight;
851
+ border-color: Highlight;
852
+ color: HighlightText;
853
+ forced-color-adjust: none;
854
+ }
855
+ }
856
+ }