total-recall-brain 3.28.2 → 3.30.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 (132) hide show
  1. package/bin/total-recall.mjs +24 -1
  2. package/docs/ARCHITECTURE.md +26 -18
  3. package/extension/background.js +259 -84
  4. package/extension/content-script.css +7 -13
  5. package/extension/content-script.js +252 -477
  6. package/extension/icons/icon-128.png +0 -0
  7. package/extension/icons/icon-16.png +0 -0
  8. package/extension/icons/icon-32.png +0 -0
  9. package/extension/icons/icon-48.png +0 -0
  10. package/extension/icons/mark.svg +6 -0
  11. package/extension/lib/brain-client.js +160 -73
  12. package/extension/lib/tokens.css +187 -0
  13. package/extension/lib/ui-helpers.js +229 -0
  14. package/extension/lib/ui-helpers.spec.mjs +94 -0
  15. package/extension/manifest.json +20 -5
  16. package/extension/options/options.css +64 -218
  17. package/extension/options/options.html +91 -43
  18. package/extension/options/options.js +208 -85
  19. package/extension/sidepanel/sidepanel.css +268 -970
  20. package/extension/sidepanel/sidepanel.html +200 -166
  21. package/extension/sidepanel/sidepanel.js +788 -942
  22. package/frontend/dist/assets/index-DGMNZi_1.js +5742 -0
  23. package/frontend/dist/index.html +1 -1
  24. package/frontend/src/api/plugins.ts +124 -92
  25. package/frontend/src/components/ResearchAgendaTab.spec.tsx +11 -0
  26. package/frontend/src/components/ResearchAgendaTab.tsx +19 -14
  27. package/frontend/src/pages/PluginsPage.spec.tsx +87 -16
  28. package/frontend/src/pages/PluginsPage.tsx +454 -1218
  29. package/package.json +2 -1
  30. package/plugins/code-quality/README.md +25 -0
  31. package/plugins/code-quality/cli.mjs +25 -0
  32. package/plugins/code-quality/plugin.json +17 -0
  33. package/plugins/git-sentinel/README.md +27 -0
  34. package/{scaffold/.agent/plugins → plugins}/git-sentinel/cli.mjs +8 -5
  35. package/plugins/git-sentinel/plugin.json +18 -0
  36. package/plugins/system-monitor/README.md +26 -0
  37. package/{scaffold/.agent/plugins → plugins}/system-monitor/cli.mjs +5 -4
  38. package/{scaffold/.agent/plugins → plugins}/system-monitor/generator.mjs +4 -5
  39. package/plugins/system-monitor/plugin.json +29 -0
  40. package/scaffold/.agent/skills/meta-harness/SKILL.md +4 -4
  41. package/scaffold/.agent/skills/plugins/SKILL.md +53 -0
  42. package/scaffold/.agent/skills/total-recall/scripts/brain-state.json +1 -0
  43. package/src/cli/agent.mjs +1 -1
  44. package/src/cli/app/index.mjs +493 -0
  45. package/src/cli/brain.mjs +33 -3
  46. package/src/cli/command.mjs +80 -41
  47. package/src/cli/harness.mjs +1 -1
  48. package/src/cli/init.mjs +3 -1
  49. package/src/cli/mesh.mjs +118 -12
  50. package/src/cli/plugin/create.mjs +144 -25
  51. package/src/cli/plugin/index.mjs +83 -53
  52. package/src/cli/plugin/install.mjs +10 -127
  53. package/src/cli/plugin/list.mjs +44 -44
  54. package/src/cli/plugin/remove.mjs +23 -30
  55. package/src/cli/plugin/scaffold-cmd.mjs +30 -0
  56. package/src/cli/plugin/search.mjs +108 -23
  57. package/src/cli/rebuild.mjs +37 -1
  58. package/src/cli/recall.mjs +17 -2
  59. package/src/cli/research.mjs +4 -6
  60. package/src/cli/share.mjs +2 -0
  61. package/src/core/app-deploy/apply.mjs +386 -0
  62. package/src/core/app-deploy/design-tokens.mjs +217 -0
  63. package/src/core/app-deploy/plan.mjs +249 -0
  64. package/src/core/app-deploy/resolve.mjs +295 -0
  65. package/src/core/app-deploy/source.mjs +337 -0
  66. package/src/core/app-deploy/standalone.mjs +248 -0
  67. package/src/core/app-deploy/upgrade.mjs +256 -0
  68. package/src/core/app-deploy/verify.mjs +213 -0
  69. package/src/core/bound-hosts.mjs +1 -1
  70. package/src/core/brain-registry.mjs +146 -0
  71. package/src/core/brain-state.json +1 -0
  72. package/src/core/daemon-loop.mjs +30 -26
  73. package/src/core/dream.mjs +5 -17
  74. package/src/core/fact-seeker.mjs +53 -368
  75. package/src/core/lan-discovery.mjs +3 -3
  76. package/src/core/mesh-access-sync.mjs +134 -0
  77. package/src/core/mesh-access.mjs +18 -3
  78. package/src/core/mesh-discover.mjs +173 -0
  79. package/src/core/mesh.mjs +131 -32
  80. package/src/core/optimizer.mjs +4 -41
  81. package/src/core/plugin-bundle.mjs +167 -0
  82. package/src/core/plugin-context.mjs +8 -13
  83. package/src/core/plugin-loader.mjs +272 -68
  84. package/src/core/plugin-peers.mjs +163 -0
  85. package/src/core/plugin-public.mjs +85 -0
  86. package/src/core/plugin-runner-child.mjs +24 -0
  87. package/src/core/plugin-runner.mjs +102 -0
  88. package/src/core/plugin-store.mjs +384 -0
  89. package/src/core/plugin-tasks.mjs +212 -0
  90. package/src/core/post-mortem.mjs +40 -9
  91. package/src/core/research-gate.mjs +182 -0
  92. package/src/core/research-queue.mjs +47 -7
  93. package/src/core/research-surface.mjs +211 -0
  94. package/src/core/research.mjs +25 -32
  95. package/src/core/scheduler.mjs +67 -153
  96. package/src/core/schema.mjs +129 -0
  97. package/src/core/search.mjs +12 -1
  98. package/src/core/secret-integration-research.mjs +12 -8
  99. package/src/core/secrets-store.mjs +32 -2
  100. package/src/core/session-watcher.mjs +6 -0
  101. package/src/core/surface.mjs +64 -3
  102. package/src/core/task-executors.mjs +8 -45
  103. package/src/core/vault-cache.mjs +70 -4
  104. package/src/server/api.mjs +21 -0
  105. package/src/server/rest.mjs +2 -0
  106. package/src/server/route-manifest.json +21 -5
  107. package/src/server/routes/collab.mjs +38 -11
  108. package/src/server/routes/extension.mjs +3 -2
  109. package/src/server/routes/memory.mjs +24 -2
  110. package/src/server/routes/mesh.mjs +7 -7
  111. package/src/server/routes/plugins-mesh.mjs +49 -0
  112. package/src/server/routes/plugins.mjs +91 -426
  113. package/src/server/routes/research.mjs +5 -2
  114. package/src/server/routes/share.mjs +2 -0
  115. package/src/server/tools.mjs +29 -2
  116. package/extension/icons/README.md +0 -27
  117. package/extension/lib/preconfigured.js +0 -5
  118. package/extension/popup/popup.css +0 -227
  119. package/extension/popup/popup.html +0 -50
  120. package/extension/popup/popup.js +0 -175
  121. package/frontend/dist/assets/index-U7o-qU99.js +0 -5742
  122. package/scaffold/.agent/plugins/.gitkeep +0 -0
  123. package/scaffold/.agent/plugins/code-quality/README.md +0 -16
  124. package/scaffold/.agent/plugins/code-quality/cli.mjs +0 -15
  125. package/scaffold/.agent/plugins/code-quality/plugin.json +0 -34
  126. package/scaffold/.agent/plugins/git-sentinel/README.md +0 -16
  127. package/scaffold/.agent/plugins/git-sentinel/plugin.json +0 -34
  128. package/scaffold/.agent/plugins/meta-harness/README.md +0 -16
  129. package/scaffold/.agent/plugins/meta-harness/cli.mjs +0 -34
  130. package/scaffold/.agent/plugins/meta-harness/plugin.json +0 -34
  131. package/scaffold/.agent/plugins/system-monitor/README.md +0 -16
  132. package/scaffold/.agent/plugins/system-monitor/plugin.json +0 -38
@@ -1,971 +1,269 @@
1
- /* Total Recall — Side Panel Styles (Catppuccin Mocha) */
2
-
3
- * {
4
- margin: 0;
5
- padding: 0;
6
- box-sizing: border-box;
7
- }
8
-
9
- body {
10
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
11
- background: #11111b;
12
- color: #cdd6f4;
13
- width: 100%;
14
- height: 100vh;
15
- overflow: hidden;
16
- }
17
-
18
- .panel {
19
- display: flex;
20
- flex-direction: column;
21
- height: 100vh;
22
- }
23
-
24
- /* ---- Header ---- */
25
- .panel-header {
26
- position: relative;
27
- display: flex;
28
- align-items: center;
29
- justify-content: space-between;
30
- padding: 14px 16px;
31
- background: #181825;
32
- border-bottom: 1px solid #313244;
33
- flex-shrink: 0;
34
- }
35
-
36
- .panel-header h1 {
37
- font-size: 15px;
38
- font-weight: 700;
39
- letter-spacing: 0.3px;
40
- }
41
-
42
- .dot {
43
- width: 10px;
44
- height: 10px;
45
- border-radius: 50%;
46
- background: #6c7086;
47
- transition: background 0.3s ease;
48
- }
49
-
50
- .dot.connected {
51
- background: #a6e3a1;
52
- box-shadow: 0 0 6px #a6e3a1;
53
- }
54
-
55
- .dot.disconnected {
56
- background: #f38ba8;
57
- box-shadow: 0 0 6px #f38ba8;
58
- }
59
-
60
- .badge {
61
- font-size: 10px;
62
- font-weight: 600;
63
- background: #313244;
64
- color: #cba6f7;
65
- padding: 2px 8px;
66
- border-radius: 6px;
67
- text-transform: capitalize;
68
- border: 1px solid #45475a;
69
- }
70
-
71
- /* ---- Tab Navigation Bar ---- */
72
- .tab-bar {
73
- display: flex;
74
- background: #181825;
75
- border-bottom: 1px solid #313244;
76
- flex-shrink: 0;
77
- }
78
-
79
- .tab-btn {
80
- flex: 1;
81
- padding: 12px 6px;
82
- background: transparent;
83
- border: none;
84
- border-bottom: 2px solid transparent;
85
- color: #a6adc8;
86
- font-size: 12px;
87
- font-weight: 600;
88
- cursor: pointer;
89
- transition: all 0.2s ease;
90
- }
91
-
92
- .tab-btn:hover {
93
- color: #cdd6f4;
94
- background: rgba(255, 255, 255, 0.02);
95
- }
96
-
97
- .tab-btn.active {
98
- color: #cba6f7;
99
- border-bottom-color: #cba6f7;
100
- }
101
-
102
- /* ---- Tab Panels Container ---- */
103
- .tab-content-container {
104
- flex: 1;
105
- min-height: 0;
106
- position: relative;
107
- display: flex;
108
- flex-direction: column;
109
- }
110
-
111
- .tab-panel {
112
- display: none;
113
- width: 100%;
114
- height: 100%;
115
- flex-direction: column;
116
- overflow: hidden;
117
- }
118
-
119
- .tab-panel.active {
120
- display: flex;
121
- }
122
-
123
- /* ==================== PANEL 1: MEMORIES ==================== */
124
-
125
- /* ---- Search ---- */
126
- .search-box {
127
- padding: 12px 16px 8px;
128
- flex-shrink: 0;
129
- }
130
-
131
- .search-box input {
132
- width: 100%;
133
- padding: 10px 14px;
134
- background: #1e1e2e;
135
- border: 1px solid #313244;
136
- border-radius: 10px;
137
- color: #cdd6f4;
138
- font-size: 14px;
139
- outline: none;
140
- transition: border-color 0.2s ease;
141
- }
142
-
143
- .search-box input::placeholder {
144
- color: #6c7086;
145
- }
146
-
147
- .search-box input:focus {
148
- border-color: #cba6f7;
149
- }
150
-
151
- /* ---- Memories List ---- */
152
- .memories-list {
153
- flex: 1;
154
- overflow-y: auto;
155
- padding: 8px 16px;
156
- }
157
-
158
- .memory-card {
159
- background: #1e1e2e;
160
- border-radius: 12px;
161
- padding: 12px 14px;
162
- margin-bottom: 10px;
163
- border: 1px solid #313244;
164
- cursor: pointer;
165
- transition: border-color 0.2s ease, transform 0.15s ease;
166
- }
167
-
168
- .memory-card:hover {
169
- border-color: #cba6f7;
170
- transform: translateY(-1px);
171
- }
172
-
173
- .memory-card .card-header {
174
- display: flex;
175
- align-items: center;
176
- justify-content: space-between;
177
- margin-bottom: 6px;
178
- }
179
-
180
- .memory-card .card-title {
181
- font-size: 13px;
182
- font-weight: 600;
183
- color: #cdd6f4;
184
- overflow: hidden;
185
- text-overflow: ellipsis;
186
- white-space: nowrap;
187
- flex: 1;
188
- margin-right: 8px;
189
- }
190
-
191
- .memory-card .card-badge {
192
- font-size: 10px;
193
- font-weight: 600;
194
- padding: 2px 8px;
195
- border-radius: 999px;
196
- background: #313244;
197
- color: #89b4fa;
198
- text-transform: uppercase;
199
- letter-spacing: 0.5px;
200
- white-space: nowrap;
201
- }
202
-
203
- .memory-card .card-excerpt {
204
- font-size: 12px;
205
- color: #a6adc8;
206
- line-height: 1.5;
207
- display: -webkit-box;
208
- -webkit-line-clamp: 2;
209
- -webkit-box-orient: vertical;
210
- overflow: hidden;
211
- }
212
-
213
- .memory-card .card-time {
214
- font-size: 10px;
215
- color: #585b70;
216
- margin-top: 6px;
217
- }
218
-
219
- .memories-empty {
220
- text-align: center;
221
- color: #6c7086;
222
- font-size: 13px;
223
- padding: 24px 0;
224
- }
225
-
226
- /* ---- Quick Actions ---- */
227
- .quick-actions {
228
- display: flex;
229
- gap: 8px;
230
- padding: 12px 16px;
231
- border-top: 1px solid #313244;
232
- flex-shrink: 0;
233
- background: #11111b;
234
- }
235
-
236
- .action-btn {
237
- flex: 1;
238
- padding: 10px 6px;
239
- font-size: 12px;
240
- font-weight: 600;
241
- background: #1e1e2e;
242
- color: #cdd6f4;
243
- border: 1px solid #313244;
244
- border-radius: 10px;
245
- cursor: pointer;
246
- transition: background 0.2s ease, border-color 0.2s ease, transform 0.1s ease, opacity 0.2s ease;
247
- }
248
-
249
- .action-btn:hover {
250
- background: #313244;
251
- border-color: #cba6f7;
252
- }
253
-
254
- .action-btn:active {
255
- transform: scale(0.96);
256
- }
257
-
258
- .action-btn:disabled, .action-btn.loading {
259
- opacity: 0.6;
260
- cursor: not-allowed;
261
- transform: none !important;
262
- }
263
-
264
- .action-btn.accent {
265
- background: #cba6f7;
266
- color: #11111b;
267
- border-color: #cba6f7;
268
- }
269
-
270
- .action-btn.accent:hover {
271
- background: #f5c2e7;
272
- border-color: #f5c2e7;
273
- }
274
-
275
- .action-btn.error {
276
- background: rgba(243, 139, 168, 0.1);
277
- color: #f38ba8;
278
- border-color: rgba(243, 139, 168, 0.3);
279
- }
280
-
281
- .action-btn.error:hover {
282
- background: rgba(243, 139, 168, 0.2);
283
- border-color: #f38ba8;
284
- }
285
-
286
- /* ---- Note Area ---- */
287
- .note-area {
288
- padding: 0 16px 12px;
289
- flex-shrink: 0;
290
- }
291
-
292
- .note-area textarea {
293
- width: 100%;
294
- min-height: 80px;
295
- padding: 10px 12px;
296
- background: #1e1e2e;
297
- border: 1px solid #313244;
298
- border-radius: 10px;
299
- color: #cdd6f4;
300
- font-size: 13px;
301
- resize: vertical;
302
- outline: none;
303
- font-family: inherit;
304
- transition: border-color 0.2s ease;
305
- }
306
-
307
- .note-area textarea:focus {
308
- border-color: #cba6f7;
309
- }
310
-
311
- .note-actions {
312
- display: flex;
313
- gap: 8px;
314
- margin-top: 8px;
315
- }
316
-
317
- .hidden {
318
- display: none !important;
319
- }
320
-
321
- /* ==================== PANEL 2: CO-PILOT CHAT ==================== */
322
-
323
- .chat-messages {
324
- flex: 1;
325
- overflow-y: auto;
326
- padding: 16px;
327
- display: flex;
328
- flex-direction: column;
329
- gap: 12px;
330
- }
331
-
332
- .chat-bubble {
333
- max-width: 85%;
334
- padding: 10px 14px;
335
- border-radius: 14px;
336
- font-size: 13px;
337
- line-height: 1.5;
338
- overflow-wrap: break-word;
339
- white-space: pre-wrap;
340
- }
341
-
342
- .chat-bubble.user {
343
- align-self: flex-end;
344
- background: #cba6f7;
345
- color: #11111b;
346
- border-bottom-right-radius: 4px;
347
- font-weight: 500;
348
- }
349
-
350
- .chat-bubble.assistant {
351
- align-self: flex-start;
352
- background: #1e1e2e;
353
- color: #cdd6f4;
354
- border-bottom-left-radius: 4px;
355
- border: 1px solid #313244;
356
- }
357
-
358
- .chat-bubble.system {
359
- align-self: center;
360
- background: transparent;
361
- color: #fab387;
362
- font-size: 11px;
363
- font-weight: 600;
364
- text-align: center;
365
- max-width: 100%;
366
- }
367
-
368
- .chat-suggestions {
369
- display: flex;
370
- gap: 6px;
371
- padding: 8px 16px;
372
- overflow-x: auto;
373
- flex-shrink: 0;
374
- background: #11111b;
375
- }
376
-
377
- .suggestion-btn {
378
- padding: 6px 12px;
379
- background: #181825;
380
- color: #a6adc8;
381
- border: 1px solid #313244;
382
- border-radius: 8px;
383
- font-size: 11px;
384
- font-weight: 500;
385
- cursor: pointer;
386
- white-space: nowrap;
387
- transition: all 0.15s ease;
388
- }
389
-
390
- .suggestion-btn:hover {
391
- background: #1e1e2e;
392
- border-color: #cba6f7;
393
- color: #cdd6f4;
394
- }
395
-
396
- .chat-grounding-row {
397
- padding: 6px 16px 2px;
398
- flex-shrink: 0;
399
- }
400
-
401
- .grounding-checkbox-label {
402
- display: flex;
403
- align-items: center;
404
- gap: 6px;
405
- font-size: 11px;
406
- font-weight: 600;
407
- color: #89b4fa;
408
- cursor: pointer;
409
- user-select: none;
410
- }
411
-
412
- .grounding-checkbox-label input {
413
- cursor: pointer;
414
- accent-color: #89b4fa;
415
- }
416
-
417
- .chat-input-bar {
418
- display: flex;
419
- gap: 8px;
420
- padding: 10px 16px 14px;
421
- background: #11111b;
422
- border-top: 1px solid #313244;
423
- flex-shrink: 0;
424
- align-items: center;
425
- }
426
-
427
- .chat-input-bar textarea {
428
- flex: 1;
429
- background: #1e1e2e;
430
- color: #cdd6f4;
431
- border: 1px solid #313244;
432
- border-radius: 10px;
433
- padding: 10px 12px;
434
- font-size: 13px;
435
- outline: none;
436
- font-family: inherit;
437
- resize: none;
438
- height: 40px;
439
- max-height: 40px;
440
- transition: border-color 0.2s ease;
441
- }
442
-
443
- .chat-input-bar textarea:focus {
444
- border-color: #cba6f7;
445
- }
446
-
447
- .chat-send-btn {
448
- width: 40px;
449
- height: 40px;
450
- border-radius: 10px;
451
- background: #cba6f7;
452
- color: #11111b;
453
- border: none;
454
- cursor: pointer;
455
- display: flex;
456
- align-items: center;
457
- justify-content: center;
458
- transition: background 0.2s ease, transform 0.1s ease;
459
- }
460
-
461
- .chat-send-btn:hover {
462
- background: #f5c2e7;
463
- }
464
-
465
- .chat-send-btn:active {
466
- transform: scale(0.94);
467
- }
468
-
469
- .chat-send-btn:disabled {
470
- background: #313244;
471
- color: #585b70;
472
- cursor: not-allowed;
473
- transform: none;
474
- }
475
-
476
- /* ==================== PANEL 3: RESEARCH ==================== */
477
-
478
- .research-feed {
479
- padding: 16px;
480
- display: flex;
481
- flex-direction: column;
482
- height: 100%;
483
- }
484
-
485
- .research-feed h3 {
486
- font-size: 12px;
487
- font-weight: 700;
488
- text-transform: uppercase;
489
- letter-spacing: 0.8px;
490
- color: #6c7086;
491
- }
492
-
493
- .refresh-btn {
494
- background: transparent;
495
- border: none;
496
- color: #89b4fa;
497
- font-size: 11px;
498
- font-weight: 600;
499
- cursor: pointer;
500
- }
501
-
502
- .refresh-btn:hover {
503
- text-decoration: underline;
504
- }
505
-
506
- #research-list {
507
- flex: 1;
508
- overflow-y: auto;
509
- }
510
-
511
- .research-item {
512
- display: flex;
513
- align-items: center;
514
- gap: 8px;
515
- padding: 10px 12px;
516
- background: #1e1e2e;
517
- border-radius: 10px;
518
- margin-bottom: 8px;
519
- border: 1px solid #313244;
520
- transition: border-color 0.2s ease;
521
- }
522
-
523
- .research-item:hover {
524
- border-color: #89b4fa;
525
- }
526
-
527
- .research-item .spinner {
528
- width: 12px;
529
- height: 12px;
530
- border: 2px solid #313244;
531
- border-top-color: #89b4fa;
532
- border-radius: 50%;
533
- animation: spin 0.8s linear infinite;
534
- flex-shrink: 0;
535
- }
536
-
537
- @keyframes spin {
538
- to { transform: rotate(360deg); }
539
- }
540
-
541
- .research-item .topic {
542
- font-size: 12px;
543
- color: #cdd6f4;
544
- flex: 1;
545
- overflow: hidden;
546
- text-overflow: ellipsis;
547
- white-space: nowrap;
548
- }
549
-
550
- .research-item .status-badge {
551
- font-size: 9px;
552
- font-weight: 600;
553
- padding: 2px 6px;
554
- border-radius: 999px;
555
- background: rgba(137, 180, 250, 0.15);
556
- color: #89b4fa;
557
- text-transform: uppercase;
558
- flex-shrink: 0;
559
- }
560
-
561
- .research-item .steer-btn {
562
- background: none;
563
- border: none;
564
- color: #f38ba8;
565
- cursor: pointer;
566
- padding: 2px;
567
- font-size: 13px;
568
- display: flex;
569
- align-items: center;
570
- justify-content: center;
571
- flex-shrink: 0;
572
- }
573
-
574
- .research-item .steer-btn:hover {
575
- color: #efa6b2;
576
- }
577
-
578
- .research-empty {
579
- font-size: 12px;
580
- color: #6c7086;
581
- text-align: center;
582
- padding: 24px 0;
583
- }
584
-
585
- /* ==================== PANEL 4: SETTINGS ==================== */
586
-
587
- .settings-panel {
588
- padding: 16px;
589
- display: flex;
590
- flex-direction: column;
591
- gap: 16px;
592
- height: 100%;
593
- overflow-y: auto;
594
- }
595
-
596
- .settings-panel h3 {
597
- font-size: 13px;
598
- font-weight: 700;
599
- text-transform: uppercase;
600
- letter-spacing: 0.8px;
601
- color: #6c7086;
602
- border-bottom: 1px solid #313244;
603
- padding-bottom: 8px;
604
- margin-bottom: 4px;
605
- }
606
-
607
- .settings-group {
608
- display: flex;
609
- flex-direction: column;
610
- gap: 6px;
611
- }
612
-
613
- .settings-group label {
614
- font-size: 11px;
615
- font-weight: 700;
616
- text-transform: uppercase;
617
- color: #6c7086;
618
- letter-spacing: 0.5px;
619
- }
620
-
621
- .settings-select {
622
- width: 100%;
623
- padding: 10px 12px;
624
- background: #1e1e2e;
625
- border: 1px solid #313244;
626
- border-radius: 10px;
627
- color: #cdd6f4;
628
- font-size: 13px;
629
- outline: none;
630
- cursor: pointer;
631
- transition: border-color 0.2s ease;
632
- }
633
-
634
- .settings-select:focus {
635
- border-color: #cba6f7;
636
- }
637
-
638
- .settings-help {
639
- font-size: 10px;
640
- color: #6c7086;
641
- line-height: 1.4;
642
- }
643
-
644
- /* ---- Toggle / Switch ---- */
645
- .switch {
646
- position: relative;
647
- display: inline-block;
648
- width: 36px;
649
- height: 20px;
650
- flex-shrink: 0;
651
- }
652
-
653
- .switch input {
654
- opacity: 0;
655
- width: 0;
656
- height: 0;
657
- }
658
-
659
- .slider {
660
- position: absolute;
661
- cursor: pointer;
662
- inset: 0;
663
- background: #313244;
664
- border-radius: 20px;
665
- transition: background 0.3s ease;
666
- }
667
-
668
- .slider::before {
669
- content: '';
670
- position: absolute;
671
- height: 14px;
672
- width: 14px;
673
- left: 3px;
674
- bottom: 3px;
675
- background: #6c7086;
676
- border-radius: 50%;
677
- transition: transform 0.3s ease, background 0.3s ease;
678
- }
679
-
680
- .switch input:checked + .slider {
681
- background: rgba(203, 166, 247, 0.3);
682
- }
683
-
684
- .switch input:checked + .slider::before {
685
- transform: translateX(16px);
686
- background: #cba6f7;
687
- }
688
-
689
- /* ---- Toast Notification ---- */
1
+ /* Total Recall — side panel. Tokens come from ../lib/tokens.css. */
2
+
3
+ html, body { height: 100%; overflow: hidden; }
4
+
5
+ /* overflow: clip (not hidden) so focus/scrollIntoView can never scroll the
6
+ off-canvas settings sheet into view. */
7
+ .app { position: relative; display: flex; flex-direction: column; height: 100vh; min-width: 280px; overflow: clip; }
8
+
9
+ /* ── Top bar ─────────────────────────────────────────────────────────────── */
10
+ .topbar {
11
+ display: flex; align-items: center; gap: 8px;
12
+ padding: 12px 12px 10px 14px;
13
+ }
14
+ .brand { display: flex; align-items: center; gap: 8px; flex: 1; min-width: 0; }
15
+ .brand-mark { width: 22px; height: 22px; border-radius: 6px; background: var(--bg-tertiary); padding: 2px; border: 1px solid var(--glass-border); }
16
+ .brand-name { font-size: 14px; font-weight: 700; letter-spacing: -0.02em; }
17
+
18
+ .brain-chip {
19
+ display: inline-flex; align-items: center; gap: 6px; max-width: 150px; height: 26px; padding: 0 10px 0 8px;
20
+ border-radius: 999px; background: var(--bg-secondary); border: 1px solid var(--border);
21
+ font-size: 11.5px; font-weight: 600; color: var(--text-secondary);
22
+ transition: border-color var(--transition-fast), color var(--transition-fast);
23
+ }
24
+ .brain-chip:hover { border-color: var(--border-hover); color: var(--text-primary); }
25
+ .brain-chip span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
26
+
27
+ .status-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--text-tertiary); flex: none; }
28
+ .status-dot.ok { background: var(--success); box-shadow: 0 0 8px rgba(52, 211, 153, 0.6); }
29
+ .status-dot.warn { background: var(--warning); box-shadow: 0 0 8px rgba(251, 191, 36, 0.5); }
30
+ .status-dot.down { background: var(--error); box-shadow: 0 0 8px rgba(248, 113, 113, 0.5); }
31
+ .status-dot.checking { animation: pulse 1.2s ease-in-out infinite; }
32
+
33
+ /* ── Tabs ─────────────────────────────────────────────────────────────────── */
34
+ .tabs {
35
+ position: relative; display: grid; grid-template-columns: repeat(3, 1fr);
36
+ margin: 0 12px; padding: 3px; border-radius: 10px;
37
+ background: var(--bg-secondary); border: 1px solid var(--border);
38
+ }
39
+ .tab {
40
+ position: relative; z-index: 1; display: inline-flex; align-items: center; justify-content: center; gap: 6px;
41
+ height: 30px; border-radius: 7px; font-size: 12.5px; font-weight: 600; color: var(--text-tertiary);
42
+ transition: color var(--transition-fast);
43
+ }
44
+ .tab:hover { color: var(--text-secondary); }
45
+ .tab.is-active { color: var(--text-primary); }
46
+ .tab-indicator {
47
+ position: absolute; z-index: 0; top: 3px; bottom: 3px; left: 3px; width: calc((100% - 6px) / 3);
48
+ border-radius: 7px; background: var(--bg-elevated); border: 1px solid var(--border-hover);
49
+ box-shadow: var(--shadow-sm); transition: transform var(--transition-normal);
50
+ }
51
+ .tab-count {
52
+ min-width: 16px; height: 16px; padding: 0 4px; border-radius: 999px; display: inline-grid; place-items: center;
53
+ font-size: 10px; font-weight: 700; background: var(--accent); color: #fff;
54
+ }
55
+
56
+ /* ── Panes ────────────────────────────────────────────────────────────────── */
57
+ .panes { position: relative; flex: 1; min-height: 0; }
58
+ .pane { position: absolute; inset: 0; overflow-y: auto; padding: 12px 12px 16px; display: flex; flex-direction: column; gap: 14px; }
59
+ .pane[hidden] { display: none; }
60
+ .pane.is-active { animation: rise 0.2s cubic-bezier(0.23, 1, 0.32, 1); }
61
+ #tab-chat { padding: 0; gap: 0; }
62
+
63
+ /* ── Page card ────────────────────────────────────────────────────────────── */
64
+ .page-card {
65
+ display: flex; flex-direction: column; gap: 12px; padding: 12px;
66
+ border-radius: var(--radius-md); background: var(--glass); border: 1px solid var(--glass-border);
67
+ backdrop-filter: blur(16px) saturate(1.3); box-shadow: var(--shadow-md);
68
+ }
69
+ .page-row { display: flex; gap: 10px; align-items: flex-start; }
70
+ .favicon {
71
+ width: 32px; height: 32px; flex: none; display: grid; place-items: center; border-radius: 8px;
72
+ background: var(--bg-tertiary); border: 1px solid var(--border); color: var(--text-tertiary); overflow: hidden;
73
+ }
74
+ .favicon img { width: 18px; height: 18px; }
75
+ .page-meta { min-width: 0; flex: 1; }
76
+ .page-title { font-size: 13px; font-weight: 600; line-height: 1.35; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; word-break: break-word; }
77
+ .page-host { margin-top: 3px; display: flex; align-items: center; gap: 6px; flex-wrap: wrap; font-size: 11.5px; color: var(--text-tertiary); }
78
+ .page-host .chip { height: 19px; padding: 0 7px 0 5px; font-size: 10.5px; }
79
+ .page-actions { display: grid; grid-template-columns: 1fr 1fr auto; gap: 8px; }
80
+ .btn.icon-only { width: 32px; padding: 0; }
81
+ .btn.icon-only[aria-expanded="true"] { background: var(--accent-muted); border-color: var(--border-accent); color: var(--accent-hover); }
82
+ .page-disabled { font-size: 11.5px; color: var(--text-tertiary); }
83
+ .note-area { display: flex; flex-direction: column; gap: 8px; animation: rise 0.18s ease both; }
84
+ .note-area[hidden] { display: none; }
85
+ .note-actions { display: flex; align-items: center; gap: 6px; }
86
+ .note-actions .hint { flex: 1; display: inline-flex; align-items: center; gap: 3px; font-size: 11px; color: var(--text-tertiary); }
87
+
88
+ /* ── Search ───────────────────────────────────────────────────────────────── */
89
+ .search {
90
+ display: flex; align-items: center; gap: 8px; height: 36px; padding: 0 10px;
91
+ border-radius: var(--radius-sm); background: var(--bg-secondary); border: 1px solid var(--border);
92
+ color: var(--text-tertiary); cursor: text;
93
+ transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
94
+ }
95
+ .search:hover { border-color: var(--border-hover); }
96
+ .search:focus-within { border-color: var(--border-accent); box-shadow: 0 0 0 3px var(--accent-muted); color: var(--text-secondary); }
97
+ .search input { flex: 1; min-width: 0; height: 100%; background: transparent; border: 0; outline: none; color: var(--text-primary); font-size: 13px; }
98
+ .search input::placeholder { color: var(--text-tertiary); }
99
+ .search input::-webkit-search-cancel-button { filter: invert(0.6); cursor: pointer; }
100
+ .search:focus-within .kbd { display: none; }
101
+
102
+ /* ── Sections + memory rows ───────────────────────────────────────────────── */
103
+ .browse { display: flex; flex-direction: column; gap: 14px; }
104
+ .section { display: flex; flex-direction: column; gap: 6px; }
105
+ .section[hidden] { display: none; }
106
+ .section-head { display: flex; align-items: center; justify-content: space-between; padding: 0 2px; min-height: 22px; }
107
+ .section-head h3 { font-size: 11px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-tertiary); }
108
+ .icon-btn.small { width: 24px; height: 24px; }
109
+ .btn.small { height: 26px; padding: 0 8px; font-size: 11.5px; }
110
+
111
+ .list { display: flex; flex-direction: column; gap: 2px; }
112
+ .row {
113
+ display: flex; flex-direction: column; gap: 3px; width: 100%; text-align: left;
114
+ padding: 9px 10px; border-radius: 10px; border: 1px solid transparent;
115
+ transition: background var(--transition-fast), border-color var(--transition-fast);
116
+ }
117
+ button.row:hover { background: var(--bg-secondary); border-color: var(--border); }
118
+ .row-title { font-size: 13px; font-weight: 600; line-height: 1.35; color: var(--text-primary); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; word-break: break-word; }
119
+ .row-excerpt { font-size: 12px; line-height: 1.5; color: var(--text-secondary); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; word-break: break-word; }
120
+ .row-meta { display: flex; align-items: center; gap: 6px; font-size: 11px; color: var(--text-tertiary); }
121
+ .row-meta .cat { color: var(--accent-hover); text-transform: capitalize; font-weight: 500; }
122
+ .row-meta .sep::before { content: '·'; }
123
+
124
+ .empty { padding: 14px 10px; font-size: 12px; color: var(--text-tertiary); line-height: 1.5; border-radius: 10px; border: 1px dashed var(--border); text-align: center; }
125
+ .error-note { padding: 10px; font-size: 12px; color: var(--error); background: var(--error-muted); border: 1px solid rgba(248, 113, 113, 0.2); border-radius: 10px; }
126
+ .skeleton-row { height: 54px; margin: 2px 0; }
127
+
128
+ /* ── Chat ─────────────────────────────────────────────────────────────────── */
129
+ .chat-scroll { flex: 1; min-height: 0; overflow-y: auto; padding: 14px 12px 8px; display: flex; flex-direction: column; }
130
+ .chat-empty { margin: auto 0; padding: 10px 6px 24px; text-align: center; display: flex; flex-direction: column; align-items: center; gap: 8px; }
131
+ .chat-empty[hidden] { display: none; }
132
+ .chat-empty-mark {
133
+ width: 44px; height: 44px; display: grid; place-items: center; border-radius: 14px; margin-bottom: 4px;
134
+ color: var(--accent-hover); background: var(--accent-muted); border: 1px solid var(--border-accent); box-shadow: var(--shadow-glow);
135
+ }
136
+ .chat-empty h2 { font-size: 15px; font-weight: 700; letter-spacing: -0.02em; }
137
+ .chat-empty p { font-size: 12.5px; color: var(--text-secondary); max-width: 260px; }
138
+ .suggestions { margin-top: 10px; display: flex; flex-direction: column; gap: 6px; width: 100%; }
139
+ .suggestion {
140
+ text-align: left; padding: 10px 12px; border-radius: 10px; font-size: 12.5px; color: var(--text-secondary);
141
+ background: var(--bg-secondary); border: 1px solid var(--border);
142
+ transition: border-color var(--transition-fast), color var(--transition-fast), background var(--transition-fast);
143
+ }
144
+ .suggestion:hover { color: var(--text-primary); border-color: var(--border-accent); background: var(--bg-tertiary); }
145
+
146
+ .messages { display: flex; flex-direction: column; gap: 14px; }
147
+ .msg { display: flex; flex-direction: column; gap: 4px; animation: rise 0.2s ease both; }
148
+ .msg.user { align-items: flex-end; }
149
+ .msg.user .bubble {
150
+ max-width: 88%; padding: 8px 12px; border-radius: 14px 14px 4px 14px;
151
+ background: var(--accent-muted); border: 1px solid var(--border-accent); color: var(--text-primary);
152
+ font-size: 13px; white-space: pre-wrap; word-break: break-word;
153
+ }
154
+ .msg-context { font-size: 10.5px; color: var(--text-tertiary); display: inline-flex; align-items: center; gap: 4px; }
155
+ .msg.assistant .bubble { font-size: 13px; line-height: 1.6; color: var(--text-primary); word-break: break-word; }
156
+ .msg.assistant .bubble p + p, .msg.assistant .bubble p + ul, .msg.assistant .bubble p + ol,
157
+ .msg.assistant .bubble ul + p, .msg.assistant .bubble ol + p, .msg.assistant .bubble pre + p, .msg.assistant .bubble p + pre { margin-top: 8px; }
158
+ .msg.assistant .bubble ul, .msg.assistant .bubble ol { padding-left: 18px; }
159
+ .msg.assistant .bubble li + li { margin-top: 3px; }
160
+ .msg.assistant .bubble li::marker { color: var(--text-tertiary); }
161
+ .msg.assistant .bubble .md-heading { font-weight: 700; margin-top: 10px; }
162
+ .msg.assistant .bubble code { font-family: var(--font-mono); font-size: 11.5px; padding: 1px 5px; border-radius: 5px; background: var(--bg-tertiary); border: 1px solid var(--border); }
163
+ .msg.assistant .bubble pre { padding: 10px; border-radius: 10px; background: var(--bg-secondary); border: 1px solid var(--border); overflow-x: auto; }
164
+ .msg.assistant .bubble pre code { padding: 0; border: 0; background: none; font-size: 11.5px; line-height: 1.55; }
165
+ .msg.assistant .bubble a { text-decoration: underline; text-decoration-color: var(--border-accent); text-underline-offset: 2px; }
166
+ .msg-meta { font-size: 10.5px; color: var(--text-tertiary); }
167
+ .msg.error .bubble { padding: 8px 12px; border-radius: 10px; background: var(--error-muted); border: 1px solid rgba(248, 113, 113, 0.2); color: var(--error); font-size: 12.5px; }
168
+ .typing { display: inline-flex; gap: 4px; padding: 6px 0; }
169
+ .typing span { width: 6px; height: 6px; border-radius: 50%; background: var(--text-tertiary); animation: pulse 1s ease-in-out infinite; }
170
+ .typing span:nth-child(2) { animation-delay: 0.15s; }
171
+ .typing span:nth-child(3) { animation-delay: 0.3s; }
172
+
173
+ .composer { padding: 8px 12px 12px; border-top: 1px solid var(--border); background: linear-gradient(180deg, transparent, rgba(7, 11, 20, 0.6)); }
174
+ .composer-box {
175
+ display: flex; align-items: flex-end; gap: 6px; padding: 6px 6px 6px 12px; border-radius: 12px;
176
+ background: var(--bg-secondary); border: 1px solid var(--border);
177
+ transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
178
+ }
179
+ .composer-box:focus-within { border-color: var(--border-accent); box-shadow: 0 0 0 3px var(--accent-muted); }
180
+ .composer-box textarea { flex: 1; min-height: 22px; max-height: 160px; padding: 4px 0; resize: none; border: 0; outline: none; background: transparent; font-size: 13px; line-height: 1.5; }
181
+ .composer-box textarea::placeholder { color: var(--text-tertiary); }
182
+ .send {
183
+ width: 30px; height: 30px; flex: none; display: grid; place-items: center; border-radius: 8px;
184
+ background: var(--accent); color: #fff; transition: background var(--transition-fast), opacity var(--transition-fast);
185
+ }
186
+ .send:hover:not(:disabled) { background: var(--accent-hover); }
187
+ .send:disabled { background: var(--bg-active); color: var(--text-tertiary); }
188
+ .composer-foot { display: flex; align-items: center; justify-content: space-between; margin-top: 8px; min-height: 26px; }
189
+ .context-toggle {
190
+ display: inline-flex; align-items: center; gap: 6px; height: 26px; padding: 0 10px; border-radius: 999px; cursor: pointer;
191
+ font-size: 11.5px; font-weight: 600; color: var(--text-tertiary); border: 1px solid var(--border);
192
+ transition: all var(--transition-fast);
193
+ }
194
+ .context-toggle input { display: none; }
195
+ .context-toggle:has(input:checked) { color: var(--accent-hover); background: var(--accent-muted); border-color: var(--border-accent); }
196
+ .context-toggle:has(input:disabled) { opacity: 0.5; cursor: default; }
197
+
198
+ /* ── Research ─────────────────────────────────────────────────────────────── */
199
+ .research-form { display: flex; gap: 8px; }
200
+ .research-form .input { height: 34px; }
201
+ .research-form .btn { height: 34px; }
202
+ .research-counts { display: flex; gap: 6px; flex-wrap: wrap; }
203
+ .research-counts:empty { display: none; }
204
+ .research-row { display: flex; align-items: center; gap: 10px; padding: 9px 10px; border-radius: 10px; }
205
+ .research-row:hover { background: var(--bg-secondary); }
206
+ .research-row .r-main { flex: 1; min-width: 0; }
207
+ .research-row .r-topic { font-size: 12.5px; font-weight: 600; line-height: 1.35; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; word-break: break-word; }
208
+ .research-row .r-meta { font-size: 11px; color: var(--text-tertiary); margin-top: 2px; }
209
+ .r-status { width: 18px; height: 18px; flex: none; display: grid; place-items: center; }
210
+ .r-status .spin { width: 14px; height: 14px; border-radius: 50%; border: 2px solid var(--accent-muted); border-top-color: var(--accent-hover); animation: spin 0.8s linear infinite; }
211
+ .r-status .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--text-tertiary); }
212
+ .r-status .dot.success { background: var(--success); }
213
+ .r-status .dot.error { background: var(--error); }
214
+ .more-note { padding: 6px 10px 2px; font-size: 11.5px; color: var(--text-tertiary); }
215
+ .research-row .icon-btn { opacity: 0; }
216
+ .research-row:hover .icon-btn, .research-row .icon-btn:focus-visible { opacity: 1; }
217
+
218
+ /* ── Gate (offline / unauthorized) ────────────────────────────────────────── */
219
+ .gate { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; gap: 10px; padding: 24px 22px 40px; }
220
+ .gate[hidden] { display: none; }
221
+ .gate-icon { width: 48px; height: 48px; display: grid; place-items: center; border-radius: 14px; color: var(--accent-hover); background: var(--accent-muted); border: 1px solid var(--border-accent); box-shadow: var(--shadow-glow); margin-bottom: 4px; }
222
+ .gate h2 { font-size: 16px; font-weight: 700; letter-spacing: -0.02em; }
223
+ .gate p { font-size: 12.5px; color: var(--text-secondary); max-width: 280px; }
224
+ .gate-actions { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; width: 100%; max-width: 240px; }
225
+ .gate-hint { font-size: 11.5px !important; color: var(--text-tertiary) !important; margin-top: 6px; }
226
+ .app.is-gated .tabs, .app.is-gated .panes { display: none; }
227
+
228
+ /* ── Settings sheet ───────────────────────────────────────────────────────── */
229
+ .scrim { position: absolute; inset: 0; z-index: 20; background: rgba(3, 6, 12, 0.55); backdrop-filter: blur(2px); animation: fade 0.18s ease both; }
230
+ .scrim[hidden] { display: none; }
231
+ .sheet {
232
+ position: absolute; z-index: 21; top: 0; right: 0; bottom: 0; width: min(100%, 360px);
233
+ display: flex; flex-direction: column; background: var(--bg-secondary); border-left: 1px solid var(--glass-border);
234
+ box-shadow: var(--shadow-lg); transform: translateX(100%); transition: transform var(--transition-normal);
235
+ }
236
+ .sheet.is-open { transform: none; }
237
+ .sheet-head { display: flex; align-items: center; justify-content: space-between; padding: 14px 12px 10px 16px; border-bottom: 1px solid var(--border); }
238
+ .sheet-head h2 { font-size: 14px; font-weight: 700; letter-spacing: -0.01em; }
239
+ .sheet-body { flex: 1; overflow-y: auto; padding: 16px; display: flex; flex-direction: column; gap: 18px; }
240
+ .sheet-foot { padding: 10px 16px 14px; border-top: 1px solid var(--border); font-size: 11px; color: var(--text-tertiary); display: flex; justify-content: space-between; gap: 8px; }
241
+ .field { display: flex; flex-direction: column; gap: 6px; }
242
+ .field-label { display: flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600; color: var(--text-secondary); }
243
+ .field-help { font-size: 11.5px; color: var(--text-tertiary); line-height: 1.5; }
244
+ .setting-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 14px; }
245
+ .setting-row.sub { margin-top: -8px; padding-left: 12px; border-left: 2px solid var(--border); }
246
+ .setting-row.sub.is-disabled { opacity: 0.5; }
247
+ .setting-title { font-size: 12.5px; font-weight: 600; margin-bottom: 2px; }
248
+ .link-list { display: flex; flex-direction: column; border-radius: var(--radius-md); border: 1px solid var(--border); overflow: hidden; }
249
+ .link-row { display: flex; align-items: center; gap: 10px; padding: 11px 12px; font-size: 12.5px; font-weight: 500; color: var(--text-primary); text-align: left; background: var(--bg-tertiary); }
250
+ .link-row + .link-row { border-top: 1px solid var(--border); }
251
+ .link-row:hover { background: var(--bg-hover); }
252
+ .link-row .icon:first-child { color: var(--text-tertiary); }
253
+ .link-row .trail { margin-left: auto; color: var(--text-tertiary); }
254
+ .link-row .trail-text { margin-left: auto; font-family: var(--font-mono); font-size: 11px; color: var(--text-tertiary); }
255
+
256
+ /* ── Toast ────────────────────────────────────────────────────────────────── */
690
257
  .toast {
691
- position: fixed;
692
- bottom: 16px;
693
- left: 50%;
694
- transform: translateX(-50%) translateY(60px);
695
- padding: 10px 20px;
696
- background: #1e1e2e;
697
- color: #a6e3a1;
698
- border: 1px solid #a6e3a1;
699
- border-radius: 10px;
700
- font-size: 13px;
701
- font-weight: 600;
702
- opacity: 0;
703
- transition: transform 0.3s ease, opacity 0.3s ease;
704
- z-index: 1000;
705
- pointer-events: none;
706
- text-align: center;
707
- box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
708
- }
709
-
710
- .toast.show {
711
- transform: translateX(-50%) translateY(0);
712
- opacity: 1;
713
- }
714
-
715
- .toast.error {
716
- color: #f38ba8;
717
- border-color: #f38ba8;
718
- }
719
-
720
- /* ---- Scrollbar ---- */
721
- ::-webkit-scrollbar {
722
- width: 6px;
723
- height: 6px;
724
- }
725
-
726
- ::-webkit-scrollbar-track {
727
- background: transparent;
728
- }
729
-
730
- ::-webkit-scrollbar-thumb {
731
- background: #313244;
732
- border-radius: 3px;
733
- }
734
-
735
- ::-webkit-scrollbar-thumb:hover {
736
- background: #45475a;
737
- }
738
-
739
- /* ==================== PANEL 5: COLLABORATION ==================== */
740
-
741
- .collab-section {
742
- display: flex;
743
- flex-direction: column;
744
- padding: 16px;
745
- height: 100%;
746
- }
747
-
748
- .collab-subtext {
749
- font-size: 12px;
750
- color: #a6adc8;
751
- margin-bottom: 16px;
752
- line-height: 1.4;
753
- }
754
-
755
- .collab-form {
756
- display: flex;
757
- flex-direction: column;
758
- gap: 10px;
759
- }
760
-
761
- .collab-form input {
762
- width: 100%;
763
- padding: 10px 14px;
764
- background: #1e1e2e;
765
- border: 1px solid #313244;
766
- border-radius: 10px;
767
- color: #cdd6f4;
768
- font-size: 14px;
769
- outline: none;
770
- transition: border-color 0.2s ease;
771
- }
772
-
773
- .collab-form input:focus {
774
- border-color: #cba6f7;
775
- }
776
-
777
- .collab-user-bar {
778
- display: flex;
779
- justify-content: space-between;
780
- align-items: center;
781
- padding: 8px 10px;
782
- background: #181825;
783
- border: 1px solid #313244;
784
- border-radius: 10px;
785
- margin-bottom: 12px;
786
- font-size: 13px;
787
- color: #cdd6f4;
788
- flex-shrink: 0;
789
- }
790
-
791
- .collab-logout-btn {
792
- background: transparent;
793
- border: none;
794
- color: #f38ba8;
795
- font-size: 11px;
796
- font-weight: 600;
797
- cursor: pointer;
798
- padding: 2px 6px;
799
- }
800
-
801
- .collab-logout-btn:hover {
802
- text-decoration: underline;
803
- }
804
-
805
- .collab-control-group {
806
- display: flex;
807
- flex-direction: column;
808
- gap: 6px;
809
- margin-bottom: 8px;
810
- flex-shrink: 0;
811
- }
812
-
813
- .collab-control-group label {
814
- font-size: 10px;
815
- font-weight: 700;
816
- text-transform: uppercase;
817
- color: #6c7086;
818
- letter-spacing: 0.5px;
819
- }
820
-
821
- .collab-panel-header {
822
- display: flex;
823
- justify-content: space-between;
824
- align-items: center;
825
- margin-top: 12px;
826
- margin-bottom: 6px;
827
- flex-shrink: 0;
828
- }
829
-
830
- .collab-panel-header h4 {
831
- font-size: 11px;
832
- font-weight: 700;
833
- text-transform: uppercase;
834
- color: #6c7086;
835
- letter-spacing: 0.5px;
836
- }
837
-
838
- .collab-list {
839
- flex: 1;
840
- min-height: 80px;
841
- max-height: 140px;
842
- overflow-y: auto;
843
- border: 1px solid #313244;
844
- background: #181825;
845
- border-radius: 10px;
846
- padding: 8px 10px;
847
- display: flex;
848
- flex-direction: column;
849
- gap: 6px;
850
- margin-bottom: 8px;
851
- }
852
-
853
- .collab-annotation-item {
854
- background: #1e1e2e;
855
- border: 1px solid #313244;
856
- border-radius: 8px;
857
- padding: 8px 10px;
858
- font-size: 12px;
859
- line-height: 1.4;
860
- }
861
-
862
- .collab-annotation-item .author {
863
- font-size: 10px;
864
- color: #89b4fa;
865
- font-weight: 600;
866
- margin-bottom: 2px;
867
- }
868
-
869
- .collab-annotation-item .text {
870
- color: #cdd6f4;
871
- word-break: break-word;
872
- }
873
-
874
- .collab-annotation-item .excerpt {
875
- font-size: 11px;
876
- color: #a6adc8;
877
- font-style: italic;
878
- border-left: 2px solid #89b4fa;
879
- padding-left: 6px;
880
- margin-bottom: 4px;
881
- }
882
-
883
- .collab-annotation-item .time {
884
- font-size: 9px;
885
- color: #585b70;
886
- text-align: right;
887
- margin-top: 4px;
888
- }
889
-
890
- .collab-annotation-form {
891
- display: flex;
892
- flex-direction: column;
893
- flex-shrink: 0;
894
- }
895
-
896
- .collab-annotation-form textarea {
897
- width: 100%;
898
- height: 48px;
899
- min-height: 48px;
900
- padding: 6px 8px;
901
- background: #1e1e2e;
902
- border: 1px solid #313244;
903
- border-radius: 8px;
904
- color: #cdd6f4;
905
- font-size: 12px;
906
- resize: none;
907
- outline: none;
908
- font-family: inherit;
909
- transition: border-color 0.2s ease;
910
- }
911
-
912
- .collab-annotation-form textarea:focus {
913
- border-color: #cba6f7;
914
- }
915
-
916
- .collab-chat-box {
917
- flex: 2;
918
- min-height: 100px;
919
- max-height: 200px;
920
- border: 1px solid #313244;
921
- background: #181825;
922
- border-radius: 10px;
923
- padding: 10px;
924
- display: flex;
925
- flex-direction: column;
926
- gap: 8px;
927
- overflow-y: auto;
928
- margin-bottom: 6px;
929
- }
930
-
931
- .collab-input-bar {
932
- padding: 0 !important;
933
- border-top: none !important;
934
- margin-bottom: 0 !important;
935
- }
936
-
937
- .collab-input-bar textarea {
938
- height: 34px !important;
939
- max-height: 34px !important;
940
- font-size: 12px !important;
941
- border-radius: 8px !important;
942
- padding: 8px !important;
943
- }
944
-
945
- .collab-input-bar button {
946
- height: 34px !important;
947
- width: 50px !important;
948
- border-radius: 8px !important;
949
- font-size: 11px !important;
950
- }
951
-
952
- /* Pulse animation for presence badge */
953
- .pulse {
954
- animation: pulse-glow 2s infinite;
955
- }
956
-
957
- @keyframes pulse-glow {
958
- 0% {
959
- transform: scale(0.95);
960
- box-shadow: 0 0 0 0 rgba(166, 227, 161, 0.7);
961
- }
962
- 70% {
963
- transform: scale(1);
964
- box-shadow: 0 0 0 5px rgba(166, 227, 161, 0);
965
- }
966
- 100% {
967
- transform: scale(0.95);
968
- box-shadow: 0 0 0 0 rgba(166, 227, 161, 0);
969
- }
970
- }
971
-
258
+ position: absolute; z-index: 30; left: 50%; bottom: 16px; transform: translateX(-50%);
259
+ display: inline-flex; align-items: center; gap: 8px; max-width: calc(100% - 32px);
260
+ padding: 9px 14px; border-radius: 12px; font-size: 12.5px; font-weight: 600;
261
+ background: var(--bg-elevated); border: 1px solid var(--border-hover); box-shadow: var(--shadow-md);
262
+ animation: toast-in 0.22s cubic-bezier(0.23, 1, 0.32, 1) both;
263
+ }
264
+ .toast[hidden] { display: none; }
265
+ .toast::before { content: ''; width: 8px; height: 8px; border-radius: 50%; flex: none; background: var(--success); box-shadow: 0 0 10px var(--success); }
266
+ .toast.error::before { background: var(--error); box-shadow: 0 0 10px var(--error); }
267
+
268
+ @keyframes fade { from { opacity: 0; } to { opacity: 1; } }
269
+ @keyframes toast-in { from { opacity: 0; transform: translate(-50%, 8px); } to { opacity: 1; transform: translate(-50%, 0); } }