nexus-shared 3.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 (121) hide show
  1. package/CHANGELOG.md +446 -262
  2. package/LICENSE +21 -21
  3. package/README.md +1084 -1000
  4. package/dist/Client.Index.d.ts +3 -0
  5. package/dist/Client.Index.js +3 -0
  6. package/dist/Components/Chats/ChatParts.d.ts +2 -2
  7. package/dist/Components/Chats/ChatParts.js +3 -7
  8. package/dist/Components/Chats/ChatThread.js +3 -3
  9. package/dist/Components/Documents/Button.d.ts +6 -1
  10. package/dist/Components/Documents/Button.js +2 -2
  11. package/dist/Components/Documents/Menu.js +21 -9
  12. package/dist/Components/Documents/SplitButton.d.ts +3 -1
  13. package/dist/Components/Documents/SplitButton.js +7 -5
  14. package/dist/Components/Documents/TabButtons.d.ts +5 -2
  15. package/dist/Components/Documents/TabButtons.js +2 -2
  16. package/dist/Components/Forms/ApiForm.d.ts +1 -1
  17. package/dist/Components/Forms/ApiForm.js +1 -1
  18. package/dist/Components/Forms/Crud.js +177 -58
  19. package/dist/Components/Forms/CrudParts.d.ts +5 -1
  20. package/dist/Components/Forms/CrudParts.js +37 -5
  21. package/dist/Components/Forms/ExcelImport.d.ts +23 -7
  22. package/dist/Components/Forms/ExcelImport.js +189 -60
  23. package/dist/Components/Forms/Form.js +5 -13
  24. package/dist/Components/Forms/SubmitForm.d.ts +11 -2
  25. package/dist/Components/Forms/SubmitForm.js +23 -12
  26. package/dist/Components/Inputs/DropdownParts.d.ts +1 -1
  27. package/dist/Components/Inputs/DropdownParts.js +4 -6
  28. package/dist/Components/Inputs/NumberBox.js +24 -2
  29. package/dist/Components/Inputs/RowsInput.js +2 -2
  30. package/dist/Components/Inputs/Slider.js +4 -1
  31. package/dist/Components/Inputs/TabularForm.js +42 -10
  32. package/dist/Components/Inputs/TimePanel.js +4 -3
  33. package/dist/Components/Layouts/Popup.js +1 -4
  34. package/dist/Components/Layouts/ThemePicker.d.ts +20 -3
  35. package/dist/Components/Layouts/ThemePicker.js +77 -6
  36. package/dist/Components/Layouts/ThemeScript.d.ts +4 -2
  37. package/dist/Components/Layouts/ThemeScript.js +4 -2
  38. package/dist/Components/Layouts/ThemeSwitcher.d.ts +6 -3
  39. package/dist/Components/Layouts/ThemeSwitcher.js +9 -8
  40. package/dist/Components/Viewers/Avatar.d.ts +21 -0
  41. package/dist/Components/Viewers/Avatar.js +21 -0
  42. package/dist/Components/Viewers/DataTable.js +192 -44
  43. package/dist/Components/Viewers/DataTableColumns.d.ts +7 -3
  44. package/dist/Components/Viewers/DataTableColumns.js +25 -68
  45. package/dist/Components/Viewers/DataTableFilters.d.ts +21 -0
  46. package/dist/Components/Viewers/DataTableFilters.js +68 -0
  47. package/dist/Components/Viewers/DataTableParts.d.ts +2 -2
  48. package/dist/Components/Viewers/DataTableParts.js +3 -3
  49. package/dist/Helpers/AnimationHelpers.d.ts +11 -0
  50. package/dist/Helpers/AnimationHelpers.js +20 -2
  51. package/dist/Helpers/CrudBackend.d.ts +7 -4
  52. package/dist/Helpers/CrudBackend.js +4 -2
  53. package/dist/Helpers/ExcelBackend.d.ts +3 -3
  54. package/dist/Helpers/ExcelBackend.js +8 -2
  55. package/dist/Helpers/ExcelHelpers.d.ts +36 -8
  56. package/dist/Helpers/ExcelHelpers.js +55 -13
  57. package/dist/Helpers/FormStore.d.ts +9 -5
  58. package/dist/Helpers/FormStore.js +25 -5
  59. package/dist/Helpers/MessageBuilder.js +1 -0
  60. package/dist/Helpers/NumberHelpers.d.ts +7 -1
  61. package/dist/Helpers/NumberHelpers.js +41 -3
  62. package/dist/Helpers/PopoverHelpers.d.ts +17 -5
  63. package/dist/Helpers/PopoverHelpers.js +52 -17
  64. package/dist/Helpers/PopoverHooks.d.ts +24 -0
  65. package/dist/Helpers/PopoverHooks.js +62 -0
  66. package/dist/Helpers/RowsStore.d.ts +7 -2
  67. package/dist/Helpers/RowsStore.js +15 -3
  68. package/dist/Helpers/TableExport.js +12 -12
  69. package/dist/Helpers/TableFilters.d.ts +25 -0
  70. package/dist/Helpers/TableFilters.js +162 -0
  71. package/dist/Helpers/TableHelpers.d.ts +6 -3
  72. package/dist/Helpers/TableHelpers.js +8 -4
  73. package/dist/Helpers/TableStore.d.ts +11 -3
  74. package/dist/Helpers/TableStore.js +16 -5
  75. package/dist/Helpers/ThemeHelpers.d.ts +21 -4
  76. package/dist/Helpers/ThemeHelpers.js +46 -9
  77. package/dist/Helpers/UserPreferences.d.ts +14 -0
  78. package/dist/Helpers/UserPreferences.js +99 -0
  79. package/dist/Interfaces/CrudInterfaces.d.ts +20 -1
  80. package/dist/Interfaces/ExcelInterfaces.d.ts +12 -0
  81. package/dist/Interfaces/FormInterfaces.d.ts +33 -5
  82. package/dist/Interfaces/PreferenceInterfaces.d.ts +43 -0
  83. package/dist/Interfaces/PreferenceInterfaces.js +28 -0
  84. package/dist/Interfaces/TableInterfaces.d.ts +59 -12
  85. package/dist/Interfaces/ThemeInterfaces.d.ts +25 -0
  86. package/dist/Interfaces/ThemeInterfaces.js +15 -0
  87. package/dist/Services/ExcelApi.d.ts +3 -1
  88. package/dist/Services/ExcelApi.js +1 -1
  89. package/dist/Services/ThemeService.d.ts +18 -2
  90. package/dist/Services/ThemeService.js +80 -16
  91. package/dist/Shared.Index.d.ts +2 -0
  92. package/dist/Shared.Index.js +2 -0
  93. package/package.json +85 -85
  94. package/src/Styles/Nexus.Avatar.css +79 -0
  95. package/src/Styles/Nexus.Base.css +117 -70
  96. package/src/Styles/Nexus.Button.css +180 -153
  97. package/src/Styles/Nexus.Calendar.css +273 -275
  98. package/src/Styles/Nexus.Chat.css +1443 -1489
  99. package/src/Styles/Nexus.Choice.css +343 -345
  100. package/src/Styles/Nexus.Crud.css +168 -161
  101. package/src/Styles/Nexus.DateTime.css +81 -81
  102. package/src/Styles/Nexus.Dropdown.css +725 -774
  103. package/src/Styles/Nexus.Editor.css +295 -297
  104. package/src/Styles/Nexus.Excel.css +389 -370
  105. package/src/Styles/Nexus.Form.css +279 -321
  106. package/src/Styles/Nexus.Index.css +37 -36
  107. package/src/Styles/Nexus.Input.css +602 -637
  108. package/src/Styles/Nexus.Markdown.css +237 -265
  109. package/src/Styles/Nexus.Menu.css +237 -259
  110. package/src/Styles/Nexus.Popup.css +724 -731
  111. package/src/Styles/Nexus.RichText.css +2 -32
  112. package/src/Styles/Nexus.Rows.css +637 -596
  113. package/src/Styles/Nexus.Slider.css +276 -278
  114. package/src/Styles/Nexus.Tab.Buttons.css +432 -419
  115. package/src/Styles/Nexus.Table.css +1386 -1296
  116. package/src/Styles/Nexus.Theme.Picker.css +286 -232
  117. package/src/Styles/Nexus.Themes.css +194 -194
  118. package/src/Styles/Nexus.Time.css +144 -147
  119. package/src/Styles/Nexus.Toast.css +263 -265
  120. package/src/Styles/Nexus.Tokens.css +89 -72
  121. package/src/Styles/Nexus.Tree.css +431 -435
@@ -1,1489 +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-chat-avatar: 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-avatar {
791
- position: relative;
792
- display: inline-grid;
793
- flex-shrink: 0;
794
- place-items: center;
795
- width: var(--nx-chat-avatar, 28px);
796
- height: var(--nx-chat-avatar, 28px);
797
- overflow: hidden;
798
- border-radius: 50%;
799
- background: color-mix(in oklab, var(--nx-text) 10%, var(--nx-surface));
800
- color: var(--nx-text);
801
- font-size: max(9px, calc(var(--nx-chat-avatar, 28px) * 0.4));
802
- font-weight: 600;
803
- line-height: 1;
804
- }
805
-
806
- .nx-chat-avatar--sm {
807
- --nx-chat-avatar: 22px;
808
- }
809
-
810
- .nx-chat-avatar[data-tone="primary"] {
811
- background: var(--nx-primary-soft);
812
- }
813
-
814
- .nx-chat-avatar[data-tone="info"] {
815
- background: var(--nx-info-soft);
816
- }
817
-
818
- .nx-chat-avatar[data-tone="success"] {
819
- background: var(--nx-success-soft);
820
- }
821
-
822
- .nx-chat-avatar[data-tone="warning"] {
823
- background: var(--nx-warning-soft);
824
- }
825
-
826
- .nx-chat-avatar img {
827
- position: absolute;
828
- inset: 0;
829
- width: 100%;
830
- height: 100%;
831
- object-fit: cover;
832
- }
833
-
834
- .nx-chat-people {
835
- display: flex;
836
- flex-direction: column;
837
- gap: 2px;
838
- margin: 0;
839
- padding: 0 var(--nx-space-2) var(--nx-space-2);
840
- list-style: none;
841
- }
842
-
843
- .nx-chat-person {
844
- display: flex;
845
- gap: var(--nx-space-2);
846
- align-items: center;
847
- padding: 4px var(--nx-space-2);
848
- border-radius: var(--nx-radius-sm);
849
- }
850
-
851
- .nx-chat-person--inactive {
852
- opacity: 0.6;
853
- }
854
-
855
- .nx-chat-person__text {
856
- display: flex;
857
- flex-direction: column;
858
- min-width: 0;
859
- }
860
-
861
- .nx-chat-person__name {
862
- display: flex;
863
- gap: 4px;
864
- align-items: baseline;
865
- overflow: hidden;
866
- font-size: var(--nx-text-sm);
867
- font-weight: 500;
868
- white-space: nowrap;
869
- text-overflow: ellipsis;
870
- }
871
-
872
- .nx-chat-person__you {
873
- color: var(--nx-text-subtle);
874
- font-size: var(--nx-text-xs);
875
- font-weight: 400;
876
- }
877
-
878
- .nx-chat-person__role {
879
- overflow: hidden;
880
- color: var(--nx-text-muted);
881
- font-size: var(--nx-text-xs);
882
- white-space: nowrap;
883
- text-overflow: ellipsis;
884
- }
885
-
886
- /* Empty, loading, and failed */
887
-
888
- .nx-chat-empty {
889
- display: flex;
890
- flex: 1 1 auto;
891
- flex-direction: column;
892
- gap: 4px;
893
- align-items: center;
894
- justify-content: center;
895
- padding: var(--nx-space-6) var(--nx-space-4);
896
- color: var(--nx-text-muted);
897
- text-align: center;
898
- }
899
-
900
- .nx-chat-empty p {
901
- margin: 0;
902
- }
903
-
904
- .nx-chat-empty__hint {
905
- display: inline-flex;
906
- gap: 6px;
907
- align-items: center;
908
- color: var(--nx-text-subtle);
909
- font-size: var(--nx-text-sm);
910
- }
911
-
912
- .nx-chat-empty .nx-icon {
913
- width: 15px;
914
- height: 15px;
915
- vertical-align: 0;
916
- }
917
-
918
- .nx-chat-loading {
919
- display: flex;
920
- gap: 6px;
921
- align-items: center;
922
- align-self: center;
923
- color: var(--nx-text-muted);
924
- font-size: var(--nx-text-sm);
925
- }
926
-
927
- .nx-chat-loading .nx-icon,
928
- .nx-chat-failure .nx-icon {
929
- width: 15px;
930
- height: 15px;
931
- vertical-align: 0;
932
- }
933
-
934
- .nx-chat-failure {
935
- display: flex;
936
- flex-wrap: wrap;
937
- gap: 6px;
938
- align-items: center;
939
- padding: var(--nx-space-2) var(--nx-space-3);
940
- border: 1px solid color-mix(in oklab, var(--nx-danger) 35%, transparent);
941
- border-radius: var(--nx-radius);
942
- background: var(--nx-danger-soft);
943
- color: var(--nx-danger);
944
- font-size: var(--nx-text-sm);
945
- }
946
-
947
- .nx-chat-failure button {
948
- display: inline-flex;
949
- gap: 3px;
950
- align-items: center;
951
- padding: 0;
952
- border: 0;
953
- background: none;
954
- color: var(--nx-danger);
955
- font: inherit;
956
- font-weight: 600;
957
- text-decoration: underline;
958
- cursor: pointer;
959
- }
960
-
961
- .nx-chat-failure button:focus-visible {
962
- outline: none;
963
- box-shadow: var(--nx-focus-ring);
964
- }
965
-
966
- /* The composer */
967
-
968
- .nx-chat-composer {
969
- display: flex;
970
- flex-shrink: 0;
971
- flex-direction: column;
972
- gap: var(--nx-space-2);
973
- padding: var(--nx-space-2) var(--nx-space-3);
974
- border-top: 1px solid var(--nx-border);
975
- background: var(--nx-surface);
976
- }
977
-
978
- .nx-chat-composer--readonly p {
979
- display: flex;
980
- gap: 6px;
981
- align-items: center;
982
- justify-content: center;
983
- margin: 0;
984
- padding: var(--nx-space-1) 0;
985
- color: var(--nx-text-muted);
986
- font-size: var(--nx-text-sm);
987
- text-align: center;
988
- }
989
-
990
- /* The editor is the whole writing area, so the row under it carries only the hint and the buttons. */
991
- .nx-chat-composer__row {
992
- display: flex;
993
- gap: var(--nx-space-2);
994
- align-items: center;
995
- }
996
-
997
- .nx-chat-composer__hint {
998
- flex: 1 1 auto;
999
- min-width: 0;
1000
- overflow: hidden;
1001
- color: var(--nx-text-subtle);
1002
- font-size: var(--nx-text-xs);
1003
- white-space: nowrap;
1004
- text-overflow: ellipsis;
1005
- }
1006
-
1007
- .nx-chat-composer__attach,
1008
- .nx-chat-composer__send {
1009
- display: inline-grid;
1010
- flex-shrink: 0;
1011
- grid-auto-flow: column;
1012
- gap: 6px;
1013
- place-items: center;
1014
- width: 30px;
1015
- height: 30px;
1016
- padding: 0;
1017
- border: 0;
1018
- border-radius: var(--nx-radius);
1019
- background: none;
1020
- color: var(--nx-text-muted);
1021
- font: inherit;
1022
- cursor: pointer;
1023
- }
1024
-
1025
- .nx-chat-composer__attach:hover {
1026
- background: var(--nx-surface-hover);
1027
- color: var(--nx-text);
1028
- }
1029
-
1030
- .nx-chat-composer__send {
1031
- width: auto;
1032
- padding: 0 10px;
1033
- background: var(--nx-primary-solid);
1034
- color: var(--nx-primary-text);
1035
- font-size: var(--nx-text-sm);
1036
- font-weight: 600;
1037
- }
1038
-
1039
- .nx-chat-composer__send:hover:not(:disabled) {
1040
- background: var(--nx-primary-hover);
1041
- }
1042
-
1043
- .nx-chat-composer__send:disabled {
1044
- background: var(--nx-surface-hover);
1045
- color: var(--nx-text-subtle);
1046
- cursor: not-allowed;
1047
- }
1048
-
1049
- .nx-chat-composer__attach:focus-visible,
1050
- .nx-chat-composer__send:focus-visible {
1051
- outline: none;
1052
- box-shadow: var(--nx-focus-ring);
1053
- }
1054
-
1055
- .nx-chat-composer__attach .nx-icon,
1056
- .nx-chat-composer__send .nx-icon {
1057
- width: 16px;
1058
- height: 16px;
1059
- vertical-align: 0;
1060
- }
1061
-
1062
- .nx-chat-composer__reply {
1063
- display: flex;
1064
- gap: var(--nx-space-2);
1065
- align-items: center;
1066
- padding: var(--nx-space-1) var(--nx-space-2);
1067
- border-left: 2px solid var(--nx-primary);
1068
- border-radius: 0 var(--nx-radius-sm) var(--nx-radius-sm) 0;
1069
- background: var(--nx-surface-2);
1070
- font-size: var(--nx-text-sm);
1071
- }
1072
-
1073
- .nx-chat-composer__reply-text {
1074
- display: flex;
1075
- flex: 1 1 auto;
1076
- gap: 6px;
1077
- min-width: 0;
1078
- color: var(--nx-text-muted);
1079
- }
1080
-
1081
- .nx-chat-composer__reply-text > span:last-child {
1082
- overflow: hidden;
1083
- white-space: nowrap;
1084
- text-overflow: ellipsis;
1085
- }
1086
-
1087
- .nx-chat-composer__reply-author {
1088
- flex-shrink: 0;
1089
- color: var(--nx-primary);
1090
- font-weight: 600;
1091
- }
1092
-
1093
- .nx-chat-composer__reply button,
1094
- .nx-chat-composer__files button {
1095
- display: grid;
1096
- flex-shrink: 0;
1097
- place-items: center;
1098
- width: 20px;
1099
- height: 20px;
1100
- padding: 0;
1101
- border: 0;
1102
- border-radius: var(--nx-radius-sm);
1103
- background: none;
1104
- color: var(--nx-text-subtle);
1105
- cursor: pointer;
1106
- }
1107
-
1108
- .nx-chat-composer__reply button:hover,
1109
- .nx-chat-composer__files button:hover {
1110
- background: var(--nx-surface-hover);
1111
- color: var(--nx-text);
1112
- }
1113
-
1114
- .nx-chat-composer__reply button:focus-visible,
1115
- .nx-chat-composer__files button:focus-visible {
1116
- outline: none;
1117
- box-shadow: var(--nx-focus-ring);
1118
- }
1119
-
1120
- .nx-chat-composer__reply .nx-icon,
1121
- .nx-chat-composer__files .nx-icon {
1122
- width: 13px;
1123
- height: 13px;
1124
- vertical-align: 0;
1125
- }
1126
-
1127
- .nx-chat-composer__files {
1128
- display: flex;
1129
- flex-wrap: wrap;
1130
- gap: var(--nx-space-1);
1131
- margin: 0;
1132
- padding: 0;
1133
- list-style: none;
1134
- }
1135
-
1136
- .nx-chat-composer__files li {
1137
- display: inline-flex;
1138
- gap: 6px;
1139
- align-items: center;
1140
- max-width: 100%;
1141
- padding: 2px 4px 2px 8px;
1142
- border: 1px solid var(--nx-border);
1143
- border-radius: var(--nx-radius-full);
1144
- background: var(--nx-surface-2);
1145
- font-size: var(--nx-text-xs);
1146
- }
1147
-
1148
- .nx-chat-composer__file-name {
1149
- overflow: hidden;
1150
- white-space: nowrap;
1151
- text-overflow: ellipsis;
1152
- }
1153
-
1154
- .nx-chat-composer__file-size {
1155
- color: var(--nx-text-muted);
1156
- font-variant-numeric: tabular-nums;
1157
- }
1158
-
1159
-
1160
- /*
1161
- * The conversation list and the New chat form: the panel's other two views. They sit where the thread sits, with
1162
- * the same bar above them, so the panel never grows a second frame inside itself.
1163
- */
1164
-
1165
- .nx-chat-list {
1166
- display: flex;
1167
- flex: 1 1 auto;
1168
- flex-direction: column;
1169
- min-width: 0;
1170
- padding: var(--nx-space-2);
1171
- overflow-y: auto;
1172
- }
1173
-
1174
- .nx-chat-list__items {
1175
- display: flex;
1176
- flex: 1 1 auto;
1177
- flex-direction: column;
1178
- gap: 2px;
1179
- margin: 0;
1180
- padding: 0;
1181
- list-style: none;
1182
- }
1183
-
1184
- .nx-chat-list__item {
1185
- display: flex;
1186
- gap: var(--nx-space-2);
1187
- align-items: center;
1188
- width: 100%;
1189
- padding: var(--nx-space-2);
1190
- border: 1px solid transparent;
1191
- border-radius: var(--nx-radius);
1192
- background: none;
1193
- color: var(--nx-text);
1194
- font: inherit;
1195
- text-align: start;
1196
- cursor: pointer;
1197
- }
1198
-
1199
- .nx-chat-list__item:hover {
1200
- background: var(--nx-surface-hover);
1201
- }
1202
-
1203
- .nx-chat-list__item:focus-visible {
1204
- outline: none;
1205
- box-shadow: var(--nx-focus-ring);
1206
- }
1207
-
1208
- /* The one open now: the accent tint, so the list says where you are without a word for it. */
1209
- .nx-chat-list__item.is-current {
1210
- border-color: color-mix(in oklab, var(--nx-primary) 28%, transparent);
1211
- background: var(--nx-primary-soft);
1212
- }
1213
-
1214
- .nx-chat-list__group {
1215
- display: grid;
1216
- flex-shrink: 0;
1217
- place-items: center;
1218
- width: var(--nx-chat-avatar, 28px);
1219
- height: var(--nx-chat-avatar, 28px);
1220
- border-radius: 50%;
1221
- background: var(--nx-surface-2);
1222
- color: var(--nx-text-muted);
1223
- }
1224
-
1225
- .nx-chat-list__group .nx-icon {
1226
- width: 15px;
1227
- height: 15px;
1228
- vertical-align: 0;
1229
- }
1230
-
1231
- .nx-chat-list__text {
1232
- display: flex;
1233
- flex: 1 1 auto;
1234
- flex-direction: column;
1235
- gap: 1px;
1236
- min-width: 0;
1237
- }
1238
-
1239
- .nx-chat-list__line {
1240
- display: flex;
1241
- gap: var(--nx-space-2);
1242
- align-items: baseline;
1243
- justify-content: space-between;
1244
- min-width: 0;
1245
- }
1246
-
1247
- .nx-chat-list__name {
1248
- overflow: hidden;
1249
- font-weight: 600;
1250
- white-space: nowrap;
1251
- text-overflow: ellipsis;
1252
- }
1253
-
1254
- .nx-chat-list__when {
1255
- flex-shrink: 0;
1256
- color: var(--nx-text-subtle);
1257
- font-size: var(--nx-text-xs);
1258
- white-space: nowrap;
1259
- }
1260
-
1261
- .nx-chat-list__last {
1262
- overflow: hidden;
1263
- color: var(--nx-text-muted);
1264
- font-size: var(--nx-text-sm);
1265
- white-space: nowrap;
1266
- text-overflow: ellipsis;
1267
- }
1268
-
1269
- .nx-chat-list__badge {
1270
- display: grid;
1271
- flex-shrink: 0;
1272
- place-items: center;
1273
- min-width: 18px;
1274
- height: 18px;
1275
- padding: 0 5px;
1276
- border-radius: var(--nx-radius-full);
1277
- background: var(--nx-danger-solid);
1278
- color: var(--nx-danger-text);
1279
- font-size: 11px;
1280
- font-weight: 700;
1281
- font-variant-numeric: tabular-nums;
1282
- line-height: 1;
1283
- }
1284
-
1285
- .nx-chat-list__new {
1286
- flex-shrink: 0;
1287
- padding-top: var(--nx-space-2);
1288
- margin-top: var(--nx-space-2);
1289
- border-top: 1px solid var(--nx-border);
1290
- }
1291
-
1292
- /* New chat */
1293
-
1294
- .nx-chat-new {
1295
- display: flex;
1296
- flex: 1 1 auto;
1297
- flex-direction: column;
1298
- min-width: 0;
1299
- padding: var(--nx-space-3);
1300
- overflow-y: auto;
1301
- }
1302
-
1303
- .nx-chat-new__fields {
1304
- display: flex;
1305
- flex: 1 1 auto;
1306
- flex-direction: column;
1307
- gap: var(--nx-space-3);
1308
- }
1309
-
1310
- .nx-chat-new__kind {
1311
- display: flex;
1312
- gap: 6px;
1313
- align-items: center;
1314
- margin: 0;
1315
- color: var(--nx-text-muted);
1316
- font-size: var(--nx-text-sm);
1317
- }
1318
-
1319
- .nx-chat-new__kind .nx-icon {
1320
- width: 15px;
1321
- height: 15px;
1322
- flex-shrink: 0;
1323
- vertical-align: 0;
1324
- }
1325
-
1326
- .nx-chat-new__actions {
1327
- display: flex;
1328
- flex-shrink: 0;
1329
- gap: var(--nx-space-2);
1330
- justify-content: flex-end;
1331
- padding-top: var(--nx-space-3);
1332
- }
1333
-
1334
- .nx-chat-new__note {
1335
- margin: var(--nx-space-1) 0 0;
1336
- color: var(--nx-text-subtle);
1337
- font-size: var(--nx-text-xs);
1338
- text-align: end;
1339
- }
1340
-
1341
- /* The bar's switch between conversations */
1342
-
1343
- .nx-chat-panel__switch {
1344
- display: inline-flex;
1345
- gap: 4px;
1346
- align-items: center;
1347
- min-width: 0;
1348
- margin: 0;
1349
- padding: 2px 6px;
1350
- border: 0;
1351
- border-radius: var(--nx-radius-sm);
1352
- background: none;
1353
- color: inherit;
1354
- font: inherit;
1355
- cursor: pointer;
1356
- }
1357
-
1358
- .nx-chat-panel__switch:hover {
1359
- background: var(--nx-surface-hover);
1360
- }
1361
-
1362
- .nx-chat-panel__switch:focus-visible {
1363
- outline: none;
1364
- box-shadow: var(--nx-focus-ring);
1365
- }
1366
-
1367
- .nx-chat-panel__switch .nx-icon {
1368
- width: 14px;
1369
- height: 14px;
1370
- flex-shrink: 0;
1371
- vertical-align: 0;
1372
- }
1373
-
1374
- .nx-chat-panel__of {
1375
- flex-shrink: 0;
1376
- color: var(--nx-text-subtle);
1377
- font-size: var(--nx-text-xs);
1378
- font-weight: 400;
1379
- }
1380
-
1381
- .nx-chat-panel__back {
1382
- display: grid;
1383
- flex-shrink: 0;
1384
- place-items: center;
1385
- width: 24px;
1386
- height: 24px;
1387
- margin-left: calc(var(--nx-space-2) * -1);
1388
- padding: 0;
1389
- border: 0;
1390
- border-radius: var(--nx-radius-sm);
1391
- background: none;
1392
- color: var(--nx-text-muted);
1393
- cursor: pointer;
1394
- }
1395
-
1396
- .nx-chat-panel__back:hover {
1397
- background: var(--nx-surface-hover);
1398
- color: var(--nx-text);
1399
- }
1400
-
1401
- .nx-chat-panel__back:focus-visible {
1402
- outline: none;
1403
- box-shadow: var(--nx-focus-ring);
1404
- }
1405
-
1406
- .nx-chat-panel__back .nx-icon {
1407
- width: 15px;
1408
- height: 15px;
1409
- vertical-align: 0;
1410
- }
1411
-
1412
- /*
1413
- * The people an `@` offers. It opens above the composer, because the composer is at the bottom of the panel and a
1414
- * list under it would fall outside. The highlighted row is the one Enter puts in.
1415
- */
1416
- .nx-chat-mentions {
1417
- display: flex;
1418
- flex-direction: column;
1419
- gap: 1px;
1420
- max-height: 200px;
1421
- margin: 0;
1422
- padding: var(--nx-space-1);
1423
- overflow-y: auto;
1424
- border: 1px solid var(--nx-border);
1425
- border-radius: var(--nx-radius);
1426
- background: var(--nx-surface);
1427
- list-style: none;
1428
- box-shadow: var(--nx-shadow-sm);
1429
- }
1430
-
1431
- .nx-chat-mentions__item {
1432
- display: flex;
1433
- gap: var(--nx-space-2);
1434
- align-items: center;
1435
- width: 100%;
1436
- padding: 4px var(--nx-space-2);
1437
- border: 0;
1438
- border-radius: var(--nx-radius-sm);
1439
- background: none;
1440
- color: var(--nx-text);
1441
- font: inherit;
1442
- font-size: var(--nx-text-sm);
1443
- text-align: start;
1444
- cursor: pointer;
1445
- }
1446
-
1447
- .nx-chat-mentions__item.is-at {
1448
- background: var(--nx-primary-soft);
1449
- color: var(--nx-primary);
1450
- }
1451
-
1452
- .nx-chat-mentions__name {
1453
- overflow: hidden;
1454
- font-weight: 500;
1455
- white-space: nowrap;
1456
- text-overflow: ellipsis;
1457
- }
1458
-
1459
- .nx-chat-mentions__role {
1460
- margin-left: auto;
1461
- overflow: hidden;
1462
- color: var(--nx-text-muted);
1463
- font-size: var(--nx-text-xs);
1464
- white-space: nowrap;
1465
- }
1466
-
1467
- /*
1468
- * A narrow panel: the people cover the thread rather than squeezing it. Measured, not guessed — at 520px the column
1469
- * would leave the thread under 300px, which is narrower than the bubbles want.
1470
- */
1471
- @container (max-width: 520px) {
1472
- .nx-chat-panel__body {
1473
- position: relative;
1474
- }
1475
-
1476
- .nx-chat-panel__aside {
1477
- position: absolute;
1478
- inset: 0;
1479
- flex-basis: auto;
1480
- background: var(--nx-surface);
1481
- }
1482
- }
1483
-
1484
- @media (prefers-reduced-motion: reduce) {
1485
- .nx-chat-btn {
1486
- transition: none;
1487
- }
1488
- }
1489
- }
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
+ }