nexus-shared 2.0.0 → 3.1.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 (176) hide show
  1. package/CHANGELOG.md +446 -0
  2. package/LICENSE +21 -21
  3. package/README.md +1084 -903
  4. package/dist/Client.Index.d.ts +14 -0
  5. package/dist/Client.Index.js +14 -0
  6. package/dist/Components/Chats/Chat.d.ts +28 -0
  7. package/dist/Components/Chats/Chat.js +19 -0
  8. package/dist/Components/Chats/ChatButton.d.ts +26 -0
  9. package/dist/Components/Chats/ChatButton.js +41 -0
  10. package/dist/Components/Chats/ChatComposer.d.ts +41 -0
  11. package/dist/Components/Chats/ChatComposer.js +177 -0
  12. package/dist/Components/Chats/ChatConversations.d.ts +35 -0
  13. package/dist/Components/Chats/ChatConversations.js +38 -0
  14. package/dist/Components/Chats/ChatPanel.d.ts +66 -0
  15. package/dist/Components/Chats/ChatPanel.js +94 -0
  16. package/dist/Components/Chats/ChatParts.d.ts +87 -0
  17. package/dist/Components/Chats/ChatParts.js +96 -0
  18. package/dist/Components/Chats/ChatThread.d.ts +22 -0
  19. package/dist/Components/Chats/ChatThread.js +96 -0
  20. package/dist/Components/Documents/Button.d.ts +6 -1
  21. package/dist/Components/Documents/Button.js +2 -2
  22. package/dist/Components/Documents/Menu.js +44 -28
  23. package/dist/Components/Documents/SplitButton.d.ts +3 -1
  24. package/dist/Components/Documents/SplitButton.js +12 -8
  25. package/dist/Components/Documents/TabButtons.d.ts +29 -8
  26. package/dist/Components/Documents/TabButtons.js +24 -5
  27. package/dist/Components/Forms/ApiForm.d.ts +6 -4
  28. package/dist/Components/Forms/ApiForm.js +15 -14
  29. package/dist/Components/Forms/Crud.js +342 -71
  30. package/dist/Components/Forms/CrudParts.d.ts +5 -1
  31. package/dist/Components/Forms/CrudParts.js +37 -5
  32. package/dist/Components/Forms/ExcelImport.d.ts +58 -0
  33. package/dist/Components/Forms/ExcelImport.js +319 -0
  34. package/dist/Components/Forms/Form.js +9 -13
  35. package/dist/Components/Forms/SubmitForm.d.ts +11 -2
  36. package/dist/Components/Forms/SubmitForm.js +23 -12
  37. package/dist/Components/Inputs/DateTimePicker.js +2 -1
  38. package/dist/Components/Inputs/DropdownParts.d.ts +1 -1
  39. package/dist/Components/Inputs/DropdownParts.js +4 -6
  40. package/dist/Components/Inputs/GroupForm.js +4 -2
  41. package/dist/Components/Inputs/InputRenderer.d.ts +2 -0
  42. package/dist/Components/Inputs/InputRenderer.js +1 -1
  43. package/dist/Components/Inputs/NumberBox.js +24 -2
  44. package/dist/Components/Inputs/ReadOnlyNotice.js +2 -1
  45. package/dist/Components/Inputs/RowsInput.d.ts +12 -1
  46. package/dist/Components/Inputs/RowsInput.js +55 -6
  47. package/dist/Components/Inputs/Slider.js +4 -1
  48. package/dist/Components/Inputs/TabularForm.d.ts +7 -3
  49. package/dist/Components/Inputs/TabularForm.js +117 -20
  50. package/dist/Components/Inputs/TimePanel.js +4 -3
  51. package/dist/Components/Inputs/TimePicker.js +2 -1
  52. package/dist/Components/Layouts/Popup.js +1 -4
  53. package/dist/Components/Layouts/ThemePicker.d.ts +20 -3
  54. package/dist/Components/Layouts/ThemePicker.js +77 -6
  55. package/dist/Components/Layouts/ThemeScript.d.ts +4 -2
  56. package/dist/Components/Layouts/ThemeScript.js +4 -2
  57. package/dist/Components/Layouts/ThemeSwitcher.d.ts +6 -3
  58. package/dist/Components/Layouts/ThemeSwitcher.js +39 -18
  59. package/dist/Components/Viewers/Avatar.d.ts +21 -0
  60. package/dist/Components/Viewers/Avatar.js +21 -0
  61. package/dist/Components/Viewers/DataTable.js +262 -60
  62. package/dist/Components/Viewers/DataTableColumns.d.ts +32 -0
  63. package/dist/Components/Viewers/DataTableColumns.js +200 -0
  64. package/dist/Components/Viewers/DataTableFilters.d.ts +21 -0
  65. package/dist/Components/Viewers/DataTableFilters.js +68 -0
  66. package/dist/Components/Viewers/DataTableParts.d.ts +8 -4
  67. package/dist/Components/Viewers/DataTableParts.js +24 -12
  68. package/dist/Helpers/AnimationHelpers.d.ts +11 -0
  69. package/dist/Helpers/AnimationHelpers.js +20 -2
  70. package/dist/Helpers/ApiClient.d.ts +22 -0
  71. package/dist/Helpers/ApiClient.js +4 -1
  72. package/dist/Helpers/ApiFormHelpers.d.ts +27 -4
  73. package/dist/Helpers/ApiFormHelpers.js +73 -9
  74. package/dist/Helpers/ApiModules.d.ts +0 -4
  75. package/dist/Helpers/ApiModules.js +1 -0
  76. package/dist/Helpers/ApiResponses.d.ts +14 -4
  77. package/dist/Helpers/ApiResponses.js +116 -25
  78. package/dist/Helpers/ApiRoutes.d.ts +0 -10
  79. package/dist/Helpers/ApiRoutes.js +2 -10
  80. package/dist/Helpers/ChatBackend.d.ts +134 -0
  81. package/dist/Helpers/ChatBackend.js +332 -0
  82. package/dist/Helpers/ChatHelpers.d.ts +189 -0
  83. package/dist/Helpers/ChatHelpers.js +486 -0
  84. package/dist/Helpers/ChatHooks.d.ts +81 -0
  85. package/dist/Helpers/ChatHooks.js +175 -0
  86. package/dist/Helpers/ChatStore.d.ts +132 -0
  87. package/dist/Helpers/ChatStore.js +394 -0
  88. package/dist/Helpers/ChatSummaries.d.ts +39 -0
  89. package/dist/Helpers/ChatSummaries.js +118 -0
  90. package/dist/Helpers/CrudBackend.d.ts +54 -9
  91. package/dist/Helpers/CrudBackend.js +103 -6
  92. package/dist/Helpers/CrudHelpers.d.ts +39 -4
  93. package/dist/Helpers/CrudHelpers.js +76 -11
  94. package/dist/Helpers/ExcelBackend.d.ts +106 -0
  95. package/dist/Helpers/ExcelBackend.js +296 -0
  96. package/dist/Helpers/ExcelHelpers.d.ts +126 -0
  97. package/dist/Helpers/ExcelHelpers.js +344 -0
  98. package/dist/Helpers/FormStore.d.ts +11 -5
  99. package/dist/Helpers/FormStore.js +44 -6
  100. package/dist/Helpers/MessageBuilder.js +1 -2
  101. package/dist/Helpers/NumberHelpers.d.ts +7 -1
  102. package/dist/Helpers/NumberHelpers.js +41 -3
  103. package/dist/Helpers/PopoverHelpers.d.ts +46 -9
  104. package/dist/Helpers/PopoverHelpers.js +163 -24
  105. package/dist/Helpers/PopoverHooks.d.ts +24 -0
  106. package/dist/Helpers/PopoverHooks.js +62 -0
  107. package/dist/Helpers/RowsStore.d.ts +14 -3
  108. package/dist/Helpers/RowsStore.js +37 -3
  109. package/dist/Helpers/TableColumns.d.ts +7 -0
  110. package/dist/Helpers/TableColumns.js +41 -13
  111. package/dist/Helpers/TableExport.js +12 -12
  112. package/dist/Helpers/TableFilters.d.ts +25 -0
  113. package/dist/Helpers/TableFilters.js +162 -0
  114. package/dist/Helpers/TableHelpers.d.ts +15 -4
  115. package/dist/Helpers/TableHelpers.js +28 -4
  116. package/dist/Helpers/TableStore.d.ts +11 -3
  117. package/dist/Helpers/TableStore.js +16 -5
  118. package/dist/Helpers/ThemeHelpers.d.ts +21 -4
  119. package/dist/Helpers/ThemeHelpers.js +46 -9
  120. package/dist/Helpers/UserPreferences.d.ts +14 -0
  121. package/dist/Helpers/UserPreferences.js +99 -0
  122. package/dist/Interfaces/ApiInterfaces.d.ts +29 -4
  123. package/dist/Interfaces/ApiInterfaces.js +16 -10
  124. package/dist/Interfaces/ChatInterfaces.d.ts +240 -0
  125. package/dist/Interfaces/ChatInterfaces.js +1 -0
  126. package/dist/Interfaces/CrudInterfaces.d.ts +92 -12
  127. package/dist/Interfaces/ExcelInterfaces.d.ts +227 -0
  128. package/dist/Interfaces/ExcelInterfaces.js +45 -0
  129. package/dist/Interfaces/FormInterfaces.d.ts +85 -7
  130. package/dist/Interfaces/MessageInterfaces.d.ts +1 -1
  131. package/dist/Interfaces/PreferenceInterfaces.d.ts +43 -0
  132. package/dist/Interfaces/PreferenceInterfaces.js +28 -0
  133. package/dist/Interfaces/TableInterfaces.d.ts +116 -9
  134. package/dist/Interfaces/ThemeInterfaces.d.ts +25 -0
  135. package/dist/Interfaces/ThemeInterfaces.js +15 -0
  136. package/dist/Services/BrowserApi.d.ts +18 -1
  137. package/dist/Services/BrowserApi.js +18 -0
  138. package/dist/Services/ChatApi.d.ts +37 -0
  139. package/dist/Services/ChatApi.js +98 -0
  140. package/dist/Services/ExcelApi.d.ts +48 -0
  141. package/dist/Services/ExcelApi.js +196 -0
  142. package/dist/Services/ServerApi.d.ts +6 -1
  143. package/dist/Services/ServerApi.js +3 -0
  144. package/dist/Services/ThemeService.d.ts +18 -2
  145. package/dist/Services/ThemeService.js +80 -16
  146. package/dist/Shared.Index.d.ts +10 -0
  147. package/dist/Shared.Index.js +10 -0
  148. package/package.json +85 -82
  149. package/src/Styles/Nexus.Avatar.css +79 -0
  150. package/src/Styles/Nexus.Base.css +117 -70
  151. package/src/Styles/Nexus.Button.css +180 -151
  152. package/src/Styles/Nexus.Calendar.css +273 -275
  153. package/src/Styles/Nexus.Chat.css +1443 -0
  154. package/src/Styles/Nexus.Choice.css +343 -345
  155. package/src/Styles/Nexus.Crud.css +168 -84
  156. package/src/Styles/Nexus.DateTime.css +81 -81
  157. package/src/Styles/Nexus.Dropdown.css +725 -774
  158. package/src/Styles/Nexus.Editor.css +295 -297
  159. package/src/Styles/Nexus.Excel.css +389 -0
  160. package/src/Styles/Nexus.Form.css +279 -298
  161. package/src/Styles/Nexus.Index.css +37 -34
  162. package/src/Styles/Nexus.Input.css +602 -637
  163. package/src/Styles/Nexus.Markdown.css +237 -265
  164. package/src/Styles/Nexus.Menu.css +237 -249
  165. package/src/Styles/Nexus.Popup.css +724 -731
  166. package/src/Styles/Nexus.RichText.css +2 -32
  167. package/src/Styles/Nexus.Rows.css +637 -566
  168. package/src/Styles/Nexus.Slider.css +276 -278
  169. package/src/Styles/Nexus.Tab.Buttons.css +432 -364
  170. package/src/Styles/Nexus.Table.css +1386 -1014
  171. package/src/Styles/Nexus.Theme.Picker.css +286 -159
  172. package/src/Styles/Nexus.Themes.css +194 -194
  173. package/src/Styles/Nexus.Time.css +144 -147
  174. package/src/Styles/Nexus.Toast.css +263 -265
  175. package/src/Styles/Nexus.Tokens.css +89 -72
  176. package/src/Styles/Nexus.Tree.css +431 -435
@@ -0,0 +1,1443 @@
1
+ @layer nexus.components {
2
+ /*
3
+ * The chat: the trigger icon, the conversation, and the composer.
4
+ *
5
+ * The trigger has three looks and one size. Quiet is a subtle outline; a conversation with messages takes the accent
6
+ * on its soft tint; unread takes the solid accent with the count in a badge over the corner. The badge is laid over
7
+ * the box, never beside it, so a column of these in a table does not move as the counts arrive.
8
+ *
9
+ * Everything is drawn from the theme tokens, so all seven themes in light and dark follow without a line of their own.
10
+ */
11
+
12
+ /* The trigger */
13
+
14
+ .nx-chat-btn {
15
+ position: relative;
16
+ display: inline-grid;
17
+ flex-shrink: 0;
18
+ place-items: center;
19
+ width: var(--nx-control-md);
20
+ height: var(--nx-control-md);
21
+ padding: 0;
22
+ border: 1px solid transparent;
23
+ border-radius: var(--nx-radius);
24
+ background: none;
25
+ color: var(--nx-text-subtle);
26
+ font: inherit;
27
+ cursor: pointer;
28
+ transition:
29
+ background-color var(--nx-duration) linear,
30
+ color var(--nx-duration) linear,
31
+ border-color var(--nx-duration) linear;
32
+ }
33
+
34
+ .nx-chat-btn--sm {
35
+ width: var(--nx-control-sm);
36
+ height: var(--nx-control-sm);
37
+ }
38
+
39
+ .nx-chat-btn .nx-icon {
40
+ width: 18px;
41
+ height: 18px;
42
+ vertical-align: 0;
43
+ }
44
+
45
+ .nx-chat-btn--sm .nx-icon {
46
+ width: 16px;
47
+ height: 16px;
48
+ }
49
+
50
+ .nx-chat-btn:hover:not(:disabled) {
51
+ background: var(--nx-surface-hover);
52
+ color: var(--nx-text);
53
+ }
54
+
55
+ .nx-chat-btn:focus-visible {
56
+ outline: none;
57
+ box-shadow: var(--nx-focus-ring);
58
+ }
59
+
60
+ .nx-chat-btn:disabled {
61
+ cursor: not-allowed;
62
+ opacity: 0.55;
63
+ }
64
+
65
+ /* Has messages: the accent on its soft tint. */
66
+ .nx-chat-btn[data-chat="active"] {
67
+ border-color: color-mix(in oklab, var(--nx-primary) 28%, transparent);
68
+ background: var(--nx-primary-soft);
69
+ color: var(--nx-primary);
70
+ }
71
+
72
+ .nx-chat-btn[data-chat="active"]:hover:not(:disabled) {
73
+ border-color: var(--nx-primary);
74
+ background: color-mix(in oklab, var(--nx-primary) 22%, var(--nx-surface));
75
+ color: var(--nx-primary);
76
+ }
77
+
78
+ /* Unread: the strongest step, so one glance down a list finds it. */
79
+ .nx-chat-btn[data-chat="unread"] {
80
+ border-color: var(--nx-primary-solid);
81
+ background: var(--nx-primary-solid);
82
+ color: var(--nx-primary-text);
83
+ }
84
+
85
+ .nx-chat-btn[data-chat="unread"]:hover:not(:disabled) {
86
+ background: var(--nx-primary-hover);
87
+ color: var(--nx-primary-text);
88
+ }
89
+
90
+ /* The number of unread messages, over the corner of the box so the box keeps its size. */
91
+ .nx-chat-btn__badge {
92
+ position: absolute;
93
+ top: -5px;
94
+ right: -5px;
95
+ display: grid;
96
+ place-items: center;
97
+ min-width: 16px;
98
+ height: 16px;
99
+ padding: 0 4px;
100
+ border: 1px solid var(--nx-surface);
101
+ border-radius: var(--nx-radius-full);
102
+ background: var(--nx-danger-solid);
103
+ color: var(--nx-danger-text);
104
+ font-size: 10px;
105
+ font-weight: 700;
106
+ font-variant-numeric: tabular-nums;
107
+ line-height: 1;
108
+ pointer-events: none;
109
+ }
110
+
111
+ /* The panel */
112
+
113
+ .nx-chat-panel {
114
+ --nx-chat-height: min(60vh, 520px);
115
+ --nx-avatar-size: 28px;
116
+
117
+ container-type: inline-size;
118
+ display: flex;
119
+ flex-direction: column;
120
+ height: var(--nx-chat-height);
121
+ min-height: 240px;
122
+ overflow: hidden;
123
+ background: var(--nx-surface);
124
+ color: var(--nx-text);
125
+ font-size: var(--nx-text-md);
126
+ }
127
+
128
+ /* A low bar, as a window has: the name at the start, the buttons flush in the corner. */
129
+ .nx-chat-panel__bar {
130
+ display: flex;
131
+ flex-shrink: 0;
132
+ align-items: center;
133
+ gap: var(--nx-space-2);
134
+ min-height: 36px;
135
+ padding: 0 var(--nx-space-2) 0 var(--nx-space-3);
136
+ border-bottom: 1px solid var(--nx-border);
137
+ background: var(--nx-surface-2);
138
+ }
139
+
140
+ .nx-chat-panel__heading {
141
+ display: flex;
142
+ flex: 1 1 auto;
143
+ gap: var(--nx-space-2);
144
+ align-items: baseline;
145
+ min-width: 0;
146
+ }
147
+
148
+ .nx-chat-panel__title {
149
+ overflow: hidden;
150
+ font-weight: 600;
151
+ white-space: nowrap;
152
+ text-overflow: ellipsis;
153
+ }
154
+
155
+ .nx-chat-panel__description {
156
+ overflow: hidden;
157
+ color: var(--nx-text-muted);
158
+ font-size: var(--nx-text-sm);
159
+ white-space: nowrap;
160
+ text-overflow: ellipsis;
161
+ }
162
+
163
+ .nx-chat-panel__people {
164
+ display: inline-flex;
165
+ flex-shrink: 0;
166
+ gap: 4px;
167
+ align-items: center;
168
+ height: 26px;
169
+ margin: 0;
170
+ padding: 0 6px;
171
+ border: 1px solid transparent;
172
+ border-radius: var(--nx-radius-sm);
173
+ background: none;
174
+ color: var(--nx-text-muted);
175
+ font: inherit;
176
+ font-size: var(--nx-text-sm);
177
+ font-variant-numeric: tabular-nums;
178
+ cursor: pointer;
179
+ }
180
+
181
+ .nx-chat-panel__people:hover,
182
+ .nx-chat-panel__people.is-open {
183
+ background: var(--nx-surface-hover);
184
+ color: var(--nx-text);
185
+ }
186
+
187
+ .nx-chat-panel__people:focus-visible {
188
+ outline: none;
189
+ box-shadow: var(--nx-focus-ring);
190
+ }
191
+
192
+ .nx-chat-panel__people .nx-icon {
193
+ width: 16px;
194
+ height: 16px;
195
+ vertical-align: 0;
196
+ }
197
+
198
+ .nx-chat-panel__body {
199
+ display: flex;
200
+ flex: 1 1 auto;
201
+ min-height: 0;
202
+ }
203
+
204
+ .nx-chat-panel__footer {
205
+ display: flex;
206
+ flex-shrink: 0;
207
+ gap: var(--nx-space-2);
208
+ justify-content: flex-end;
209
+ padding: var(--nx-space-2) var(--nx-space-3);
210
+ border-top: 1px solid var(--nx-border);
211
+ }
212
+
213
+ /* The people, in a column beside the thread: a dividing line, not a panel inside a panel. */
214
+ .nx-chat-panel__aside {
215
+ display: flex;
216
+ flex: 0 0 220px;
217
+ flex-direction: column;
218
+ min-width: 0;
219
+ overflow-y: auto;
220
+ border-left: 1px solid var(--nx-border);
221
+ }
222
+
223
+ .nx-chat-aside__bar {
224
+ display: flex;
225
+ align-items: center;
226
+ justify-content: space-between;
227
+ padding: var(--nx-space-2) var(--nx-space-2) var(--nx-space-2) var(--nx-space-3);
228
+ color: var(--nx-text-muted);
229
+ font-size: var(--nx-text-sm);
230
+ font-weight: 600;
231
+ }
232
+
233
+ .nx-chat-aside__bar button {
234
+ display: grid;
235
+ place-items: center;
236
+ width: 22px;
237
+ height: 22px;
238
+ padding: 0;
239
+ border: 0;
240
+ border-radius: var(--nx-radius-sm);
241
+ background: none;
242
+ color: var(--nx-text-subtle);
243
+ cursor: pointer;
244
+ }
245
+
246
+ .nx-chat-aside__bar button:hover {
247
+ background: var(--nx-surface-hover);
248
+ color: var(--nx-text);
249
+ }
250
+
251
+ .nx-chat-aside__bar button:focus-visible {
252
+ outline: none;
253
+ box-shadow: var(--nx-focus-ring);
254
+ }
255
+
256
+ .nx-chat-aside__bar .nx-icon {
257
+ width: 14px;
258
+ height: 14px;
259
+ vertical-align: 0;
260
+ }
261
+
262
+ .nx-chat-aside__empty {
263
+ margin: 0;
264
+ padding: 0 var(--nx-space-3) var(--nx-space-3);
265
+ color: var(--nx-text-muted);
266
+ font-size: var(--nx-text-sm);
267
+ }
268
+
269
+ .nx-chat-aside__add {
270
+ display: flex;
271
+ flex-direction: column;
272
+ gap: var(--nx-space-2);
273
+ margin-top: auto;
274
+ padding: var(--nx-space-3);
275
+ border-top: 1px solid var(--nx-border);
276
+ }
277
+
278
+ /* The thread */
279
+
280
+ .nx-chat-thread {
281
+ position: relative;
282
+ display: flex;
283
+ flex: 1 1 auto;
284
+ flex-direction: column;
285
+ min-width: 0;
286
+ }
287
+
288
+ .nx-chat-thread__list {
289
+ display: flex;
290
+ flex: 1 1 auto;
291
+ flex-direction: column;
292
+ gap: var(--nx-space-2);
293
+ padding: var(--nx-space-3);
294
+ overflow-y: auto;
295
+ overscroll-behavior: contain;
296
+ scrollbar-gutter: stable;
297
+ }
298
+
299
+ .nx-chat-thread__list:focus-visible {
300
+ outline: none;
301
+ box-shadow: inset var(--nx-focus-ring);
302
+ }
303
+
304
+ .nx-chat-thread__day {
305
+ display: flex;
306
+ flex-direction: column;
307
+ gap: var(--nx-space-2);
308
+ }
309
+
310
+ .nx-chat-thread__older {
311
+ display: flex;
312
+ justify-content: center;
313
+ }
314
+
315
+ /* Down to the newest, with how many arrived while the reader was elsewhere. */
316
+ .nx-chat-thread__jump {
317
+ position: absolute;
318
+ right: var(--nx-space-3);
319
+ bottom: var(--nx-space-3);
320
+ display: grid;
321
+ place-items: center;
322
+ width: 32px;
323
+ height: 32px;
324
+ padding: 0;
325
+ border: 1px solid var(--nx-border);
326
+ border-radius: var(--nx-radius-full);
327
+ background: var(--nx-surface);
328
+ color: var(--nx-text);
329
+ cursor: pointer;
330
+ box-shadow: var(--nx-shadow-sm);
331
+ }
332
+
333
+ .nx-chat-thread__jump:hover {
334
+ border-color: var(--nx-border-strong);
335
+ background: var(--nx-surface-hover);
336
+ }
337
+
338
+ .nx-chat-thread__jump:focus-visible {
339
+ outline: none;
340
+ box-shadow: var(--nx-focus-ring);
341
+ }
342
+
343
+ .nx-chat-thread__jump .nx-icon {
344
+ width: 16px;
345
+ height: 16px;
346
+ vertical-align: 0;
347
+ }
348
+
349
+ .nx-chat-thread__jump-count {
350
+ position: absolute;
351
+ top: -5px;
352
+ right: -5px;
353
+ display: grid;
354
+ place-items: center;
355
+ min-width: 16px;
356
+ height: 16px;
357
+ padding: 0 4px;
358
+ border: 1px solid var(--nx-surface);
359
+ border-radius: var(--nx-radius-full);
360
+ background: var(--nx-danger-solid);
361
+ color: var(--nx-danger-text);
362
+ font-size: 10px;
363
+ font-weight: 700;
364
+ line-height: 1;
365
+ }
366
+
367
+ /* The lines that break a thread up */
368
+
369
+ .nx-chat-day,
370
+ .nx-chat-unread-line {
371
+ display: flex;
372
+ gap: var(--nx-space-2);
373
+ align-items: center;
374
+ font-size: var(--nx-text-xs);
375
+ text-transform: none;
376
+ }
377
+
378
+ .nx-chat-day::before,
379
+ .nx-chat-day::after,
380
+ .nx-chat-unread-line::before,
381
+ .nx-chat-unread-line::after {
382
+ flex: 1 1 auto;
383
+ height: 1px;
384
+ background: var(--nx-border);
385
+ content: "";
386
+ }
387
+
388
+ .nx-chat-day > span {
389
+ color: var(--nx-text-muted);
390
+ font-weight: 600;
391
+ white-space: nowrap;
392
+ }
393
+
394
+ .nx-chat-unread-line::before,
395
+ .nx-chat-unread-line::after {
396
+ background: color-mix(in oklab, var(--nx-primary) 45%, transparent);
397
+ }
398
+
399
+ .nx-chat-unread-line {
400
+ margin: var(--nx-space-1) 0;
401
+ }
402
+
403
+ .nx-chat-unread-line > span {
404
+ padding: 2px 8px;
405
+ border-radius: var(--nx-radius-full);
406
+ background: var(--nx-primary-soft);
407
+ color: var(--nx-primary);
408
+ font-weight: 600;
409
+ white-space: nowrap;
410
+ }
411
+
412
+ /* A run of messages by one author */
413
+
414
+ .nx-chat-run {
415
+ display: flex;
416
+ gap: var(--nx-space-2);
417
+ align-items: flex-end;
418
+ }
419
+
420
+ .nx-chat-run--mine {
421
+ justify-content: flex-end;
422
+ }
423
+
424
+ .nx-chat-run--system {
425
+ flex-direction: column;
426
+ gap: var(--nx-space-1);
427
+ }
428
+
429
+ .nx-chat-run__avatar {
430
+ flex-shrink: 0;
431
+ }
432
+
433
+ .nx-chat-run__messages {
434
+ display: flex;
435
+ flex-direction: column;
436
+ gap: 2px;
437
+ min-width: 0;
438
+ max-width: min(82%, 46ch);
439
+ }
440
+
441
+ .nx-chat-run--mine .nx-chat-run__messages {
442
+ align-items: flex-end;
443
+ }
444
+
445
+ /* One message */
446
+
447
+ .nx-chat-msg {
448
+ display: flex;
449
+ flex-direction: column;
450
+ gap: 2px;
451
+ min-width: 0;
452
+ max-width: 100%;
453
+ }
454
+
455
+ .nx-chat-msg__bubble {
456
+ position: relative;
457
+ min-width: 0;
458
+ padding: 6px var(--nx-space-3) 6px;
459
+ border: 1px solid var(--nx-border);
460
+ border-radius: var(--nx-radius-lg);
461
+ line-height: 1.45;
462
+ }
463
+
464
+ .nx-chat-msg--theirs .nx-chat-msg__bubble {
465
+ background: var(--nx-surface-2);
466
+ }
467
+
468
+ .nx-chat-msg--mine .nx-chat-msg__bubble {
469
+ border-color: color-mix(in oklab, var(--nx-primary) 24%, transparent);
470
+ background: var(--nx-primary-soft);
471
+ }
472
+
473
+ /* A run reads as one block: only its outer corners are fully round. */
474
+ .nx-chat-msg--theirs:not(.nx-chat-msg--first) .nx-chat-msg__bubble {
475
+ border-top-left-radius: var(--nx-radius-sm);
476
+ }
477
+
478
+ .nx-chat-msg--theirs:not(.nx-chat-msg--last) .nx-chat-msg__bubble {
479
+ border-bottom-left-radius: var(--nx-radius-sm);
480
+ }
481
+
482
+ .nx-chat-msg--mine:not(.nx-chat-msg--first) .nx-chat-msg__bubble {
483
+ border-top-right-radius: var(--nx-radius-sm);
484
+ }
485
+
486
+ .nx-chat-msg--mine:not(.nx-chat-msg--last) .nx-chat-msg__bubble {
487
+ border-bottom-right-radius: var(--nx-radius-sm);
488
+ }
489
+
490
+ .nx-chat-msg--failed .nx-chat-msg__bubble {
491
+ border-color: color-mix(in oklab, var(--nx-danger) 45%, transparent);
492
+ background: var(--nx-danger-soft);
493
+ }
494
+
495
+ .nx-chat-msg__author {
496
+ display: block;
497
+ color: var(--nx-primary);
498
+ font-size: var(--nx-text-sm);
499
+ font-weight: 600;
500
+ }
501
+
502
+ /*
503
+ * A message is Markdown. Inside a bubble it keeps the bubble's rhythm rather than a document's: nothing above the
504
+ * first block or below the last, a tighter gap between blocks, headings that do not tower over a line of text, and
505
+ * code and tables that scroll inside the bubble instead of widening it.
506
+ */
507
+ .nx-chat-msg__body {
508
+ overflow-wrap: anywhere;
509
+ }
510
+
511
+ .nx-chat-msg__body > :first-child {
512
+ margin-top: 0;
513
+ }
514
+
515
+ .nx-chat-msg__body > :last-child {
516
+ margin-bottom: 0;
517
+ }
518
+
519
+ .nx-chat-msg__body > * + * {
520
+ margin-top: var(--nx-space-2);
521
+ }
522
+
523
+ .nx-chat-msg__body :is(h1, h2, h3, h4, h5, h6) {
524
+ font-size: var(--nx-text-lg);
525
+ }
526
+
527
+ .nx-chat-msg__body :is(ul, ol) {
528
+ padding-left: var(--nx-space-5);
529
+ }
530
+
531
+ .nx-chat-msg__body :is(pre, table) {
532
+ max-width: 100%;
533
+ overflow-x: auto;
534
+ }
535
+
536
+ .nx-chat-msg__meta {
537
+ display: flex;
538
+ gap: 4px;
539
+ align-items: center;
540
+ justify-content: flex-end;
541
+ color: var(--nx-text-muted);
542
+ font-size: var(--nx-text-xs);
543
+ font-variant-numeric: tabular-nums;
544
+ }
545
+
546
+ .nx-chat-msg__edited {
547
+ font-style: italic;
548
+ }
549
+
550
+ /* Sending, sent, delivered, read — one mark, one size, in the place the time sits. */
551
+ .nx-chat-mark {
552
+ display: inline-grid;
553
+ flex-shrink: 0;
554
+ place-items: center;
555
+ width: 14px;
556
+ height: 14px;
557
+ color: var(--nx-text-subtle);
558
+ }
559
+
560
+ .nx-chat-mark .nx-icon {
561
+ width: 14px;
562
+ height: 14px;
563
+ vertical-align: 0;
564
+ }
565
+
566
+ /* Read: the accent, so a glance down your own messages finds what has landed. */
567
+ .nx-chat-mark--seen {
568
+ color: var(--nx-primary);
569
+ }
570
+
571
+ .nx-chat-mark--failed {
572
+ color: var(--nx-danger);
573
+ }
574
+
575
+ /*
576
+ * The actions of a message: over its top corner, and shown only on hover or keyboard focus. They are laid over the
577
+ * bubble rather than taking a place in it, so nothing in the thread moves as the pointer travels down it.
578
+ */
579
+ .nx-chat-msg__actions {
580
+ position: absolute;
581
+ top: -12px;
582
+ display: none;
583
+ gap: 2px;
584
+ padding: 2px;
585
+ border: 1px solid var(--nx-border);
586
+ border-radius: var(--nx-radius);
587
+ background: var(--nx-surface);
588
+ box-shadow: var(--nx-shadow-sm);
589
+ }
590
+
591
+ .nx-chat-msg--theirs .nx-chat-msg__actions {
592
+ right: var(--nx-space-2);
593
+ }
594
+
595
+ .nx-chat-msg--mine .nx-chat-msg__actions {
596
+ left: var(--nx-space-2);
597
+ }
598
+
599
+ .nx-chat-msg:hover .nx-chat-msg__actions,
600
+ .nx-chat-msg:focus-within .nx-chat-msg__actions {
601
+ display: flex;
602
+ }
603
+
604
+ .nx-chat-msg__action {
605
+ display: grid;
606
+ place-items: center;
607
+ width: 22px;
608
+ height: 22px;
609
+ padding: 0;
610
+ border: 0;
611
+ border-radius: var(--nx-radius-sm);
612
+ background: none;
613
+ color: var(--nx-text-muted);
614
+ cursor: pointer;
615
+ }
616
+
617
+ .nx-chat-msg__action:hover {
618
+ background: var(--nx-surface-hover);
619
+ color: var(--nx-text);
620
+ }
621
+
622
+ .nx-chat-msg__action--danger:hover {
623
+ background: var(--nx-danger-soft);
624
+ color: var(--nx-danger);
625
+ }
626
+
627
+ .nx-chat-msg__action:focus-visible {
628
+ outline: none;
629
+ box-shadow: var(--nx-focus-ring);
630
+ }
631
+
632
+ .nx-chat-msg__action .nx-icon {
633
+ width: 14px;
634
+ height: 14px;
635
+ vertical-align: 0;
636
+ }
637
+
638
+ /* A message that did not arrive: it stays, with why and what can be done. */
639
+ .nx-chat-msg__failure {
640
+ display: flex;
641
+ flex-wrap: wrap;
642
+ gap: 6px;
643
+ align-items: center;
644
+ color: var(--nx-danger);
645
+ font-size: var(--nx-text-xs);
646
+ }
647
+
648
+ .nx-chat-msg__failure .nx-icon {
649
+ width: 14px;
650
+ height: 14px;
651
+ vertical-align: 0;
652
+ }
653
+
654
+ .nx-chat-msg__failure button {
655
+ display: inline-flex;
656
+ gap: 3px;
657
+ align-items: center;
658
+ padding: 0;
659
+ border: 0;
660
+ background: none;
661
+ color: var(--nx-danger);
662
+ font: inherit;
663
+ font-weight: 600;
664
+ text-decoration: underline;
665
+ cursor: pointer;
666
+ }
667
+
668
+ .nx-chat-msg__failure button:focus-visible {
669
+ outline: none;
670
+ box-shadow: var(--nx-focus-ring);
671
+ }
672
+
673
+ /* A quoted message, in the bubble that answers it and in the composer */
674
+
675
+ .nx-chat-quote {
676
+ display: flex;
677
+ flex-direction: column;
678
+ gap: 1px;
679
+ width: 100%;
680
+ margin: 2px 0 4px;
681
+ padding: 2px 0 2px var(--nx-space-2);
682
+ border: 0;
683
+ border-left: 2px solid color-mix(in oklab, var(--nx-primary) 60%, transparent);
684
+ background: none;
685
+ color: var(--nx-text-muted);
686
+ font: inherit;
687
+ font-size: var(--nx-text-sm);
688
+ text-align: start;
689
+ cursor: pointer;
690
+ }
691
+
692
+ .nx-chat-quote--gone {
693
+ border-left-color: var(--nx-border-strong);
694
+ font-style: italic;
695
+ cursor: default;
696
+ }
697
+
698
+ .nx-chat-quote:focus-visible {
699
+ outline: none;
700
+ box-shadow: var(--nx-focus-ring);
701
+ }
702
+
703
+ .nx-chat-quote__author {
704
+ color: var(--nx-primary);
705
+ font-weight: 600;
706
+ }
707
+
708
+ .nx-chat-quote__body {
709
+ display: block;
710
+ overflow: hidden;
711
+ white-space: nowrap;
712
+ text-overflow: ellipsis;
713
+ }
714
+
715
+ /* Files on a message */
716
+
717
+ .nx-chat-files {
718
+ display: flex;
719
+ flex-direction: column;
720
+ gap: 2px;
721
+ margin: 4px 0 2px;
722
+ padding: 0;
723
+ list-style: none;
724
+ }
725
+
726
+ .nx-chat-file > a,
727
+ .nx-chat-file > span {
728
+ display: inline-flex;
729
+ gap: 6px;
730
+ align-items: center;
731
+ max-width: 100%;
732
+ padding: 3px 6px;
733
+ border: 1px solid color-mix(in oklab, var(--nx-text) 18%, transparent);
734
+ border-radius: var(--nx-radius-sm);
735
+ background: none;
736
+ color: var(--nx-text);
737
+ font-size: var(--nx-text-sm);
738
+ text-decoration: none;
739
+ }
740
+
741
+ .nx-chat-file > a:hover {
742
+ border-color: var(--nx-primary);
743
+ background: color-mix(in oklab, var(--nx-primary) 10%, transparent);
744
+ color: var(--nx-primary);
745
+ }
746
+
747
+ .nx-chat-file > a:focus-visible {
748
+ outline: none;
749
+ box-shadow: var(--nx-focus-ring);
750
+ }
751
+
752
+ .nx-chat-file .nx-icon {
753
+ width: 14px;
754
+ height: 14px;
755
+ flex-shrink: 0;
756
+ vertical-align: 0;
757
+ }
758
+
759
+ .nx-chat-file__name {
760
+ overflow: hidden;
761
+ white-space: nowrap;
762
+ text-overflow: ellipsis;
763
+ }
764
+
765
+ .nx-chat-file__size {
766
+ flex-shrink: 0;
767
+ color: var(--nx-text-muted);
768
+ font-variant-numeric: tabular-nums;
769
+ }
770
+
771
+ /* A note the system wrote */
772
+
773
+ .nx-chat-note {
774
+ display: flex;
775
+ gap: 6px;
776
+ align-items: baseline;
777
+ align-self: center;
778
+ justify-content: center;
779
+ max-width: 90%;
780
+ padding: 2px 10px;
781
+ border-radius: var(--nx-radius-full);
782
+ background: var(--nx-surface-2);
783
+ color: var(--nx-text-muted);
784
+ font-size: var(--nx-text-xs);
785
+ text-align: center;
786
+ }
787
+
788
+ /* The people */
789
+
790
+ .nx-chat-people {
791
+ display: flex;
792
+ flex-direction: column;
793
+ gap: 2px;
794
+ margin: 0;
795
+ padding: 0 var(--nx-space-2) var(--nx-space-2);
796
+ list-style: none;
797
+ }
798
+
799
+ .nx-chat-person {
800
+ display: flex;
801
+ gap: var(--nx-space-2);
802
+ align-items: center;
803
+ padding: 4px var(--nx-space-2);
804
+ border-radius: var(--nx-radius-sm);
805
+ }
806
+
807
+ .nx-chat-person--inactive {
808
+ opacity: 0.6;
809
+ }
810
+
811
+ .nx-chat-person__text {
812
+ display: flex;
813
+ flex-direction: column;
814
+ min-width: 0;
815
+ }
816
+
817
+ .nx-chat-person__name {
818
+ display: flex;
819
+ gap: 4px;
820
+ align-items: baseline;
821
+ overflow: hidden;
822
+ font-size: var(--nx-text-sm);
823
+ font-weight: 500;
824
+ white-space: nowrap;
825
+ text-overflow: ellipsis;
826
+ }
827
+
828
+ .nx-chat-person__you {
829
+ color: var(--nx-text-subtle);
830
+ font-size: var(--nx-text-xs);
831
+ font-weight: 400;
832
+ }
833
+
834
+ .nx-chat-person__role {
835
+ overflow: hidden;
836
+ color: var(--nx-text-muted);
837
+ font-size: var(--nx-text-xs);
838
+ white-space: nowrap;
839
+ text-overflow: ellipsis;
840
+ }
841
+
842
+ /* Empty, loading, and failed */
843
+
844
+ .nx-chat-empty {
845
+ display: flex;
846
+ flex: 1 1 auto;
847
+ flex-direction: column;
848
+ gap: 4px;
849
+ align-items: center;
850
+ justify-content: center;
851
+ padding: var(--nx-space-6) var(--nx-space-4);
852
+ color: var(--nx-text-muted);
853
+ text-align: center;
854
+ }
855
+
856
+ .nx-chat-empty p {
857
+ margin: 0;
858
+ }
859
+
860
+ .nx-chat-empty__hint {
861
+ display: inline-flex;
862
+ gap: 6px;
863
+ align-items: center;
864
+ color: var(--nx-text-subtle);
865
+ font-size: var(--nx-text-sm);
866
+ }
867
+
868
+ .nx-chat-empty .nx-icon {
869
+ width: 15px;
870
+ height: 15px;
871
+ vertical-align: 0;
872
+ }
873
+
874
+ .nx-chat-loading {
875
+ display: flex;
876
+ gap: 6px;
877
+ align-items: center;
878
+ align-self: center;
879
+ color: var(--nx-text-muted);
880
+ font-size: var(--nx-text-sm);
881
+ }
882
+
883
+ .nx-chat-loading .nx-icon,
884
+ .nx-chat-failure .nx-icon {
885
+ width: 15px;
886
+ height: 15px;
887
+ vertical-align: 0;
888
+ }
889
+
890
+ .nx-chat-failure {
891
+ display: flex;
892
+ flex-wrap: wrap;
893
+ gap: 6px;
894
+ align-items: center;
895
+ padding: var(--nx-space-2) var(--nx-space-3);
896
+ border: 1px solid color-mix(in oklab, var(--nx-danger) 35%, transparent);
897
+ border-radius: var(--nx-radius);
898
+ background: var(--nx-danger-soft);
899
+ color: var(--nx-danger);
900
+ font-size: var(--nx-text-sm);
901
+ }
902
+
903
+ .nx-chat-failure button {
904
+ display: inline-flex;
905
+ gap: 3px;
906
+ align-items: center;
907
+ padding: 0;
908
+ border: 0;
909
+ background: none;
910
+ color: var(--nx-danger);
911
+ font: inherit;
912
+ font-weight: 600;
913
+ text-decoration: underline;
914
+ cursor: pointer;
915
+ }
916
+
917
+ .nx-chat-failure button:focus-visible {
918
+ outline: none;
919
+ box-shadow: var(--nx-focus-ring);
920
+ }
921
+
922
+ /* The composer */
923
+
924
+ .nx-chat-composer {
925
+ display: flex;
926
+ flex-shrink: 0;
927
+ flex-direction: column;
928
+ gap: var(--nx-space-2);
929
+ padding: var(--nx-space-2) var(--nx-space-3);
930
+ border-top: 1px solid var(--nx-border);
931
+ background: var(--nx-surface);
932
+ }
933
+
934
+ .nx-chat-composer--readonly p {
935
+ display: flex;
936
+ gap: 6px;
937
+ align-items: center;
938
+ justify-content: center;
939
+ margin: 0;
940
+ padding: var(--nx-space-1) 0;
941
+ color: var(--nx-text-muted);
942
+ font-size: var(--nx-text-sm);
943
+ text-align: center;
944
+ }
945
+
946
+ /* The editor is the whole writing area, so the row under it carries only the hint and the buttons. */
947
+ .nx-chat-composer__row {
948
+ display: flex;
949
+ gap: var(--nx-space-2);
950
+ align-items: center;
951
+ }
952
+
953
+ .nx-chat-composer__hint {
954
+ flex: 1 1 auto;
955
+ min-width: 0;
956
+ overflow: hidden;
957
+ color: var(--nx-text-subtle);
958
+ font-size: var(--nx-text-xs);
959
+ white-space: nowrap;
960
+ text-overflow: ellipsis;
961
+ }
962
+
963
+ .nx-chat-composer__attach,
964
+ .nx-chat-composer__send {
965
+ display: inline-grid;
966
+ flex-shrink: 0;
967
+ grid-auto-flow: column;
968
+ gap: 6px;
969
+ place-items: center;
970
+ width: 30px;
971
+ height: 30px;
972
+ padding: 0;
973
+ border: 0;
974
+ border-radius: var(--nx-radius);
975
+ background: none;
976
+ color: var(--nx-text-muted);
977
+ font: inherit;
978
+ cursor: pointer;
979
+ }
980
+
981
+ .nx-chat-composer__attach:hover {
982
+ background: var(--nx-surface-hover);
983
+ color: var(--nx-text);
984
+ }
985
+
986
+ .nx-chat-composer__send {
987
+ width: auto;
988
+ padding: 0 10px;
989
+ background: var(--nx-primary-solid);
990
+ color: var(--nx-primary-text);
991
+ font-size: var(--nx-text-sm);
992
+ font-weight: 600;
993
+ }
994
+
995
+ .nx-chat-composer__send:hover:not(:disabled) {
996
+ background: var(--nx-primary-hover);
997
+ }
998
+
999
+ .nx-chat-composer__send:disabled {
1000
+ background: var(--nx-surface-hover);
1001
+ color: var(--nx-text-subtle);
1002
+ cursor: not-allowed;
1003
+ }
1004
+
1005
+ .nx-chat-composer__attach:focus-visible,
1006
+ .nx-chat-composer__send:focus-visible {
1007
+ outline: none;
1008
+ box-shadow: var(--nx-focus-ring);
1009
+ }
1010
+
1011
+ .nx-chat-composer__attach .nx-icon,
1012
+ .nx-chat-composer__send .nx-icon {
1013
+ width: 16px;
1014
+ height: 16px;
1015
+ vertical-align: 0;
1016
+ }
1017
+
1018
+ .nx-chat-composer__reply {
1019
+ display: flex;
1020
+ gap: var(--nx-space-2);
1021
+ align-items: center;
1022
+ padding: var(--nx-space-1) var(--nx-space-2);
1023
+ border-left: 2px solid var(--nx-primary);
1024
+ border-radius: 0 var(--nx-radius-sm) var(--nx-radius-sm) 0;
1025
+ background: var(--nx-surface-2);
1026
+ font-size: var(--nx-text-sm);
1027
+ }
1028
+
1029
+ .nx-chat-composer__reply-text {
1030
+ display: flex;
1031
+ flex: 1 1 auto;
1032
+ gap: 6px;
1033
+ min-width: 0;
1034
+ color: var(--nx-text-muted);
1035
+ }
1036
+
1037
+ .nx-chat-composer__reply-text > span:last-child {
1038
+ overflow: hidden;
1039
+ white-space: nowrap;
1040
+ text-overflow: ellipsis;
1041
+ }
1042
+
1043
+ .nx-chat-composer__reply-author {
1044
+ flex-shrink: 0;
1045
+ color: var(--nx-primary);
1046
+ font-weight: 600;
1047
+ }
1048
+
1049
+ .nx-chat-composer__reply button,
1050
+ .nx-chat-composer__files button {
1051
+ display: grid;
1052
+ flex-shrink: 0;
1053
+ place-items: center;
1054
+ width: 20px;
1055
+ height: 20px;
1056
+ padding: 0;
1057
+ border: 0;
1058
+ border-radius: var(--nx-radius-sm);
1059
+ background: none;
1060
+ color: var(--nx-text-subtle);
1061
+ cursor: pointer;
1062
+ }
1063
+
1064
+ .nx-chat-composer__reply button:hover,
1065
+ .nx-chat-composer__files button:hover {
1066
+ background: var(--nx-surface-hover);
1067
+ color: var(--nx-text);
1068
+ }
1069
+
1070
+ .nx-chat-composer__reply button:focus-visible,
1071
+ .nx-chat-composer__files button:focus-visible {
1072
+ outline: none;
1073
+ box-shadow: var(--nx-focus-ring);
1074
+ }
1075
+
1076
+ .nx-chat-composer__reply .nx-icon,
1077
+ .nx-chat-composer__files .nx-icon {
1078
+ width: 13px;
1079
+ height: 13px;
1080
+ vertical-align: 0;
1081
+ }
1082
+
1083
+ .nx-chat-composer__files {
1084
+ display: flex;
1085
+ flex-wrap: wrap;
1086
+ gap: var(--nx-space-1);
1087
+ margin: 0;
1088
+ padding: 0;
1089
+ list-style: none;
1090
+ }
1091
+
1092
+ .nx-chat-composer__files li {
1093
+ display: inline-flex;
1094
+ gap: 6px;
1095
+ align-items: center;
1096
+ max-width: 100%;
1097
+ padding: 2px 4px 2px 8px;
1098
+ border: 1px solid var(--nx-border);
1099
+ border-radius: var(--nx-radius-full);
1100
+ background: var(--nx-surface-2);
1101
+ font-size: var(--nx-text-xs);
1102
+ }
1103
+
1104
+ .nx-chat-composer__file-name {
1105
+ overflow: hidden;
1106
+ white-space: nowrap;
1107
+ text-overflow: ellipsis;
1108
+ }
1109
+
1110
+ .nx-chat-composer__file-size {
1111
+ color: var(--nx-text-muted);
1112
+ font-variant-numeric: tabular-nums;
1113
+ }
1114
+
1115
+
1116
+ /*
1117
+ * The conversation list and the New chat form: the panel's other two views. They sit where the thread sits, with
1118
+ * the same bar above them, so the panel never grows a second frame inside itself.
1119
+ */
1120
+
1121
+ .nx-chat-list {
1122
+ display: flex;
1123
+ flex: 1 1 auto;
1124
+ flex-direction: column;
1125
+ min-width: 0;
1126
+ padding: var(--nx-space-2);
1127
+ overflow-y: auto;
1128
+ }
1129
+
1130
+ .nx-chat-list__items {
1131
+ display: flex;
1132
+ flex: 1 1 auto;
1133
+ flex-direction: column;
1134
+ gap: 2px;
1135
+ margin: 0;
1136
+ padding: 0;
1137
+ list-style: none;
1138
+ }
1139
+
1140
+ .nx-chat-list__item {
1141
+ display: flex;
1142
+ gap: var(--nx-space-2);
1143
+ align-items: center;
1144
+ width: 100%;
1145
+ padding: var(--nx-space-2);
1146
+ border: 1px solid transparent;
1147
+ border-radius: var(--nx-radius);
1148
+ background: none;
1149
+ color: var(--nx-text);
1150
+ font: inherit;
1151
+ text-align: start;
1152
+ cursor: pointer;
1153
+ }
1154
+
1155
+ .nx-chat-list__item:hover {
1156
+ background: var(--nx-surface-hover);
1157
+ }
1158
+
1159
+ .nx-chat-list__item:focus-visible {
1160
+ outline: none;
1161
+ box-shadow: var(--nx-focus-ring);
1162
+ }
1163
+
1164
+ /* The one open now: the accent tint, so the list says where you are without a word for it. */
1165
+ .nx-chat-list__item.is-current {
1166
+ border-color: color-mix(in oklab, var(--nx-primary) 28%, transparent);
1167
+ background: var(--nx-primary-soft);
1168
+ }
1169
+
1170
+ .nx-chat-list__group {
1171
+ display: grid;
1172
+ flex-shrink: 0;
1173
+ place-items: center;
1174
+ width: var(--nx-avatar-size, 28px);
1175
+ height: var(--nx-avatar-size, 28px);
1176
+ border-radius: 50%;
1177
+ background: var(--nx-surface-2);
1178
+ color: var(--nx-text-muted);
1179
+ }
1180
+
1181
+ .nx-chat-list__group .nx-icon {
1182
+ width: 15px;
1183
+ height: 15px;
1184
+ vertical-align: 0;
1185
+ }
1186
+
1187
+ .nx-chat-list__text {
1188
+ display: flex;
1189
+ flex: 1 1 auto;
1190
+ flex-direction: column;
1191
+ gap: 1px;
1192
+ min-width: 0;
1193
+ }
1194
+
1195
+ .nx-chat-list__line {
1196
+ display: flex;
1197
+ gap: var(--nx-space-2);
1198
+ align-items: baseline;
1199
+ justify-content: space-between;
1200
+ min-width: 0;
1201
+ }
1202
+
1203
+ .nx-chat-list__name {
1204
+ overflow: hidden;
1205
+ font-weight: 600;
1206
+ white-space: nowrap;
1207
+ text-overflow: ellipsis;
1208
+ }
1209
+
1210
+ .nx-chat-list__when {
1211
+ flex-shrink: 0;
1212
+ color: var(--nx-text-subtle);
1213
+ font-size: var(--nx-text-xs);
1214
+ white-space: nowrap;
1215
+ }
1216
+
1217
+ .nx-chat-list__last {
1218
+ overflow: hidden;
1219
+ color: var(--nx-text-muted);
1220
+ font-size: var(--nx-text-sm);
1221
+ white-space: nowrap;
1222
+ text-overflow: ellipsis;
1223
+ }
1224
+
1225
+ .nx-chat-list__badge {
1226
+ display: grid;
1227
+ flex-shrink: 0;
1228
+ place-items: center;
1229
+ min-width: 18px;
1230
+ height: 18px;
1231
+ padding: 0 5px;
1232
+ border-radius: var(--nx-radius-full);
1233
+ background: var(--nx-danger-solid);
1234
+ color: var(--nx-danger-text);
1235
+ font-size: 11px;
1236
+ font-weight: 700;
1237
+ font-variant-numeric: tabular-nums;
1238
+ line-height: 1;
1239
+ }
1240
+
1241
+ .nx-chat-list__new {
1242
+ flex-shrink: 0;
1243
+ padding-top: var(--nx-space-2);
1244
+ margin-top: var(--nx-space-2);
1245
+ border-top: 1px solid var(--nx-border);
1246
+ }
1247
+
1248
+ /* New chat */
1249
+
1250
+ .nx-chat-new {
1251
+ display: flex;
1252
+ flex: 1 1 auto;
1253
+ flex-direction: column;
1254
+ min-width: 0;
1255
+ padding: var(--nx-space-3);
1256
+ overflow-y: auto;
1257
+ }
1258
+
1259
+ .nx-chat-new__fields {
1260
+ display: flex;
1261
+ flex: 1 1 auto;
1262
+ flex-direction: column;
1263
+ gap: var(--nx-space-3);
1264
+ }
1265
+
1266
+ .nx-chat-new__kind {
1267
+ display: flex;
1268
+ gap: 6px;
1269
+ align-items: center;
1270
+ margin: 0;
1271
+ color: var(--nx-text-muted);
1272
+ font-size: var(--nx-text-sm);
1273
+ }
1274
+
1275
+ .nx-chat-new__kind .nx-icon {
1276
+ width: 15px;
1277
+ height: 15px;
1278
+ flex-shrink: 0;
1279
+ vertical-align: 0;
1280
+ }
1281
+
1282
+ .nx-chat-new__actions {
1283
+ display: flex;
1284
+ flex-shrink: 0;
1285
+ gap: var(--nx-space-2);
1286
+ justify-content: flex-end;
1287
+ padding-top: var(--nx-space-3);
1288
+ }
1289
+
1290
+ .nx-chat-new__note {
1291
+ margin: var(--nx-space-1) 0 0;
1292
+ color: var(--nx-text-subtle);
1293
+ font-size: var(--nx-text-xs);
1294
+ text-align: end;
1295
+ }
1296
+
1297
+ /* The bar's switch between conversations */
1298
+
1299
+ .nx-chat-panel__switch {
1300
+ display: inline-flex;
1301
+ gap: 4px;
1302
+ align-items: center;
1303
+ min-width: 0;
1304
+ margin: 0;
1305
+ padding: 2px 6px;
1306
+ border: 0;
1307
+ border-radius: var(--nx-radius-sm);
1308
+ background: none;
1309
+ color: inherit;
1310
+ font: inherit;
1311
+ cursor: pointer;
1312
+ }
1313
+
1314
+ .nx-chat-panel__switch:hover {
1315
+ background: var(--nx-surface-hover);
1316
+ }
1317
+
1318
+ .nx-chat-panel__switch:focus-visible {
1319
+ outline: none;
1320
+ box-shadow: var(--nx-focus-ring);
1321
+ }
1322
+
1323
+ .nx-chat-panel__switch .nx-icon {
1324
+ width: 14px;
1325
+ height: 14px;
1326
+ flex-shrink: 0;
1327
+ vertical-align: 0;
1328
+ }
1329
+
1330
+ .nx-chat-panel__of {
1331
+ flex-shrink: 0;
1332
+ color: var(--nx-text-subtle);
1333
+ font-size: var(--nx-text-xs);
1334
+ font-weight: 400;
1335
+ }
1336
+
1337
+ .nx-chat-panel__back {
1338
+ display: grid;
1339
+ flex-shrink: 0;
1340
+ place-items: center;
1341
+ width: 24px;
1342
+ height: 24px;
1343
+ margin-left: calc(var(--nx-space-2) * -1);
1344
+ padding: 0;
1345
+ border: 0;
1346
+ border-radius: var(--nx-radius-sm);
1347
+ background: none;
1348
+ color: var(--nx-text-muted);
1349
+ cursor: pointer;
1350
+ }
1351
+
1352
+ .nx-chat-panel__back:hover {
1353
+ background: var(--nx-surface-hover);
1354
+ color: var(--nx-text);
1355
+ }
1356
+
1357
+ .nx-chat-panel__back:focus-visible {
1358
+ outline: none;
1359
+ box-shadow: var(--nx-focus-ring);
1360
+ }
1361
+
1362
+ .nx-chat-panel__back .nx-icon {
1363
+ width: 15px;
1364
+ height: 15px;
1365
+ vertical-align: 0;
1366
+ }
1367
+
1368
+ /*
1369
+ * The people an `@` offers. It opens above the composer, because the composer is at the bottom of the panel and a
1370
+ * list under it would fall outside. The highlighted row is the one Enter puts in.
1371
+ */
1372
+ .nx-chat-mentions {
1373
+ display: flex;
1374
+ flex-direction: column;
1375
+ gap: 1px;
1376
+ max-height: 200px;
1377
+ margin: 0;
1378
+ padding: var(--nx-space-1);
1379
+ overflow-y: auto;
1380
+ border: 1px solid var(--nx-border);
1381
+ border-radius: var(--nx-radius);
1382
+ background: var(--nx-surface);
1383
+ list-style: none;
1384
+ box-shadow: var(--nx-shadow-sm);
1385
+ }
1386
+
1387
+ .nx-chat-mentions__item {
1388
+ display: flex;
1389
+ gap: var(--nx-space-2);
1390
+ align-items: center;
1391
+ width: 100%;
1392
+ padding: 4px var(--nx-space-2);
1393
+ border: 0;
1394
+ border-radius: var(--nx-radius-sm);
1395
+ background: none;
1396
+ color: var(--nx-text);
1397
+ font: inherit;
1398
+ font-size: var(--nx-text-sm);
1399
+ text-align: start;
1400
+ cursor: pointer;
1401
+ }
1402
+
1403
+ .nx-chat-mentions__item.is-at {
1404
+ background: var(--nx-primary-soft);
1405
+ color: var(--nx-primary);
1406
+ }
1407
+
1408
+ .nx-chat-mentions__name {
1409
+ overflow: hidden;
1410
+ font-weight: 500;
1411
+ white-space: nowrap;
1412
+ text-overflow: ellipsis;
1413
+ }
1414
+
1415
+ .nx-chat-mentions__role {
1416
+ margin-left: auto;
1417
+ overflow: hidden;
1418
+ color: var(--nx-text-muted);
1419
+ font-size: var(--nx-text-xs);
1420
+ white-space: nowrap;
1421
+ }
1422
+
1423
+ /*
1424
+ * A narrow panel: the people cover the thread rather than squeezing it. Measured, not guessed — at 520px the column
1425
+ * would leave the thread under 300px, which is narrower than the bubbles want.
1426
+ */
1427
+ @container (max-width: 520px) {
1428
+ .nx-chat-panel__body {
1429
+ position: relative;
1430
+ }
1431
+
1432
+ .nx-chat-panel__aside {
1433
+ position: absolute;
1434
+ inset: 0;
1435
+ flex-basis: auto;
1436
+ background: var(--nx-surface);
1437
+ }
1438
+ }
1439
+
1440
+ [data-nx-motion="reduce"] .nx-chat-btn {
1441
+ transition: none;
1442
+ }
1443
+ }