clay-server 2.5.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 (87) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +281 -0
  3. package/bin/cli.js +2385 -0
  4. package/lib/cli-sessions.js +270 -0
  5. package/lib/config.js +237 -0
  6. package/lib/daemon.js +489 -0
  7. package/lib/ipc.js +112 -0
  8. package/lib/notes.js +120 -0
  9. package/lib/pages.js +664 -0
  10. package/lib/project.js +1433 -0
  11. package/lib/public/app.js +2795 -0
  12. package/lib/public/apple-touch-icon-dark.png +0 -0
  13. package/lib/public/apple-touch-icon.png +0 -0
  14. package/lib/public/css/base.css +264 -0
  15. package/lib/public/css/diff.css +128 -0
  16. package/lib/public/css/filebrowser.css +1114 -0
  17. package/lib/public/css/highlight.css +144 -0
  18. package/lib/public/css/icon-strip.css +296 -0
  19. package/lib/public/css/input.css +573 -0
  20. package/lib/public/css/menus.css +856 -0
  21. package/lib/public/css/messages.css +1445 -0
  22. package/lib/public/css/mobile-nav.css +354 -0
  23. package/lib/public/css/overlays.css +697 -0
  24. package/lib/public/css/rewind.css +505 -0
  25. package/lib/public/css/server-settings.css +761 -0
  26. package/lib/public/css/sidebar.css +936 -0
  27. package/lib/public/css/sticky-notes.css +358 -0
  28. package/lib/public/css/title-bar.css +314 -0
  29. package/lib/public/favicon-dark.svg +1 -0
  30. package/lib/public/favicon.svg +1 -0
  31. package/lib/public/icon-192-dark.png +0 -0
  32. package/lib/public/icon-192.png +0 -0
  33. package/lib/public/icon-512-dark.png +0 -0
  34. package/lib/public/icon-512.png +0 -0
  35. package/lib/public/icon-mono.svg +1 -0
  36. package/lib/public/index.html +762 -0
  37. package/lib/public/manifest.json +27 -0
  38. package/lib/public/modules/diff.js +398 -0
  39. package/lib/public/modules/events.js +21 -0
  40. package/lib/public/modules/filebrowser.js +1411 -0
  41. package/lib/public/modules/fileicons.js +172 -0
  42. package/lib/public/modules/icons.js +54 -0
  43. package/lib/public/modules/input.js +584 -0
  44. package/lib/public/modules/markdown.js +356 -0
  45. package/lib/public/modules/notifications.js +649 -0
  46. package/lib/public/modules/qrcode.js +70 -0
  47. package/lib/public/modules/rewind.js +345 -0
  48. package/lib/public/modules/server-settings.js +510 -0
  49. package/lib/public/modules/sidebar.js +1083 -0
  50. package/lib/public/modules/state.js +3 -0
  51. package/lib/public/modules/sticky-notes.js +688 -0
  52. package/lib/public/modules/terminal.js +697 -0
  53. package/lib/public/modules/theme.js +738 -0
  54. package/lib/public/modules/tools.js +1608 -0
  55. package/lib/public/modules/utils.js +56 -0
  56. package/lib/public/style.css +15 -0
  57. package/lib/public/sw.js +75 -0
  58. package/lib/push.js +124 -0
  59. package/lib/sdk-bridge.js +989 -0
  60. package/lib/server.js +582 -0
  61. package/lib/sessions.js +424 -0
  62. package/lib/terminal-manager.js +187 -0
  63. package/lib/terminal.js +24 -0
  64. package/lib/themes/ayu-light.json +9 -0
  65. package/lib/themes/catppuccin-latte.json +9 -0
  66. package/lib/themes/catppuccin-mocha.json +9 -0
  67. package/lib/themes/clay-light.json +10 -0
  68. package/lib/themes/clay.json +10 -0
  69. package/lib/themes/dracula.json +9 -0
  70. package/lib/themes/everforest-light.json +9 -0
  71. package/lib/themes/everforest.json +9 -0
  72. package/lib/themes/github-light.json +9 -0
  73. package/lib/themes/gruvbox-dark.json +9 -0
  74. package/lib/themes/gruvbox-light.json +9 -0
  75. package/lib/themes/monokai.json +9 -0
  76. package/lib/themes/nord-light.json +9 -0
  77. package/lib/themes/nord.json +9 -0
  78. package/lib/themes/one-dark.json +9 -0
  79. package/lib/themes/one-light.json +9 -0
  80. package/lib/themes/rose-pine-dawn.json +9 -0
  81. package/lib/themes/rose-pine.json +9 -0
  82. package/lib/themes/solarized-dark.json +9 -0
  83. package/lib/themes/solarized-light.json +9 -0
  84. package/lib/themes/tokyo-night-light.json +9 -0
  85. package/lib/themes/tokyo-night.json +9 -0
  86. package/lib/updater.js +97 -0
  87. package/package.json +47 -0
@@ -0,0 +1,697 @@
1
+ /* ==========================================================================
2
+ Main App Area
3
+ ========================================================================== */
4
+
5
+ #app {
6
+ flex: 1;
7
+ display: flex;
8
+ flex-direction: column;
9
+ min-width: 0;
10
+ min-height: 0;
11
+ position: relative;
12
+ }
13
+
14
+ /* --- Onboarding banner --- */
15
+ #onboarding-banner {
16
+ flex-shrink: 0;
17
+ display: flex;
18
+ align-items: center;
19
+ justify-content: center;
20
+ gap: 8px;
21
+ padding: 8px 16px;
22
+ background: var(--accent-8);
23
+ border-bottom: 1px solid var(--accent-15);
24
+ font-size: 12px;
25
+ color: var(--text-secondary);
26
+ }
27
+
28
+ #onboarding-banner.hidden { display: none; }
29
+
30
+ .onboarding-banner-text {
31
+ display: flex;
32
+ align-items: center;
33
+ gap: 6px;
34
+ }
35
+
36
+ .onboarding-banner-text .lucide { width: 13px; height: 13px; color: var(--accent); }
37
+
38
+ .onboarding-banner-text a,
39
+ .onboarding-banner-text button.onboarding-cta {
40
+ color: var(--accent);
41
+ font-weight: 500;
42
+ text-decoration: none;
43
+ background: none;
44
+ border: none;
45
+ font-family: inherit;
46
+ font-size: inherit;
47
+ cursor: pointer;
48
+ padding: 0;
49
+ }
50
+
51
+ .onboarding-banner-text a:hover,
52
+ .onboarding-banner-text button.onboarding-cta:hover { text-decoration: underline; }
53
+ .onboarding-step { color: var(--accent); font-weight: 600; font-size: 11px; text-transform: uppercase; letter-spacing: 0.5px; margin-right: 4px; }
54
+
55
+ #onboarding-banner-close {
56
+ background: none;
57
+ border: none;
58
+ color: var(--text-dimmer);
59
+ cursor: pointer;
60
+ padding: 2px;
61
+ display: flex;
62
+ align-items: center;
63
+ flex-shrink: 0;
64
+ }
65
+
66
+ #onboarding-banner-close .lucide { width: 14px; height: 14px; }
67
+ #onboarding-banner-close:hover { color: var(--text-secondary); }
68
+
69
+ /* --- Update banner --- */
70
+ #update-banner {
71
+ flex-shrink: 0;
72
+ display: flex;
73
+ align-items: center;
74
+ justify-content: center;
75
+ gap: 8px;
76
+ padding: 8px 16px;
77
+ background: var(--success-8);
78
+ border-bottom: 1px solid var(--success-15);
79
+ font-size: 12px;
80
+ color: var(--text-secondary);
81
+ position: relative;
82
+ }
83
+
84
+ #update-banner.hidden { display: none; }
85
+
86
+ .update-banner-text {
87
+ display: flex;
88
+ align-items: center;
89
+ gap: 6px;
90
+ }
91
+
92
+ .update-banner-text .lucide { width: 13px; height: 13px; color: var(--success); }
93
+ .update-banner-text strong { color: var(--text); font-weight: 600; }
94
+
95
+ #update-now {
96
+ background: var(--success-15);
97
+ border: 1px solid var(--success-25);
98
+ border-radius: 6px;
99
+ color: var(--success);
100
+ cursor: pointer;
101
+ font-family: inherit;
102
+ font-size: 11px;
103
+ font-weight: 500;
104
+ padding: 3px 10px;
105
+ flex-shrink: 0;
106
+ transition: background 0.15s;
107
+ }
108
+
109
+ #update-now:hover { background: var(--success-25); }
110
+ #update-now:disabled { opacity: 0.6; cursor: default; }
111
+
112
+ #update-how {
113
+ background: transparent;
114
+ border: 1px solid var(--text-dimmer);
115
+ border-radius: 6px;
116
+ color: var(--text-dimmer);
117
+ cursor: pointer;
118
+ font-family: inherit;
119
+ font-size: 11px;
120
+ font-weight: 600;
121
+ padding: 3px 7px;
122
+ flex-shrink: 0;
123
+ transition: background 0.15s, color 0.15s;
124
+ }
125
+
126
+ #update-how:hover { background: rgba(var(--overlay-rgb), 0.05); color: var(--text-secondary); }
127
+
128
+ #update-popover {
129
+ display: none;
130
+ position: absolute;
131
+ top: 100%;
132
+ left: 50%;
133
+ transform: translateX(-50%);
134
+ background: var(--code-bg);
135
+ border: 1px solid var(--border);
136
+ border-radius: 10px;
137
+ padding: 12px 16px;
138
+ z-index: 200;
139
+ box-shadow: 0 4px 16px rgba(var(--shadow-rgb), 0.4);
140
+ white-space: nowrap;
141
+ }
142
+
143
+ #update-popover.visible { display: block; }
144
+
145
+ #update-popover .popover-label {
146
+ font-size: 12px;
147
+ color: var(--text-muted);
148
+ margin-bottom: 6px;
149
+ }
150
+
151
+ #update-popover .popover-cmd {
152
+ display: flex;
153
+ align-items: center;
154
+ gap: 8px;
155
+ }
156
+
157
+ #update-popover .popover-cmd code {
158
+ font-family: "Roboto Mono", monospace;
159
+ font-size: 13px;
160
+ color: var(--text);
161
+ background: rgba(var(--overlay-rgb), 0.06);
162
+ padding: 6px 12px;
163
+ border-radius: 6px;
164
+ user-select: all;
165
+ -webkit-user-select: all;
166
+ }
167
+
168
+ #update-popover .popover-copy {
169
+ background: none;
170
+ border: 1px solid var(--border);
171
+ border-radius: 6px;
172
+ color: var(--text-muted);
173
+ cursor: pointer;
174
+ padding: 5px 7px;
175
+ display: flex;
176
+ align-items: center;
177
+ justify-content: center;
178
+ transition: color 0.15s, border-color 0.15s;
179
+ }
180
+
181
+ #update-popover .popover-copy .lucide { width: 14px; height: 14px; }
182
+ #update-popover .popover-copy:hover { color: var(--text); border-color: var(--text-dimmer); }
183
+ #update-popover .popover-copy.copied { color: var(--success); border-color: var(--success); }
184
+
185
+ #update-banner-close {
186
+ background: none;
187
+ border: none;
188
+ color: var(--text-dimmer);
189
+ cursor: pointer;
190
+ padding: 2px;
191
+ display: flex;
192
+ align-items: center;
193
+ flex-shrink: 0;
194
+ }
195
+
196
+ #update-banner-close .lucide { width: 14px; height: 14px; }
197
+ #update-banner-close:hover { color: var(--text-secondary); }
198
+
199
+ /* --- Skip permissions banner --- */
200
+ #skip-perms-banner {
201
+ flex-shrink: 0;
202
+ display: flex;
203
+ align-items: center;
204
+ justify-content: center;
205
+ gap: 8px;
206
+ padding: 7px 16px;
207
+ background: var(--error-12);
208
+ border-bottom: 1px solid var(--error-25);
209
+ font-size: 12px;
210
+ font-weight: 500;
211
+ color: var(--error);
212
+ }
213
+
214
+ #skip-perms-banner.hidden { display: none; }
215
+ #skip-perms-banner .lucide { width: 14px; height: 14px; flex-shrink: 0; }
216
+
217
+ /* --- Confirm modal --- */
218
+ #confirm-modal {
219
+ position: fixed;
220
+ inset: 0;
221
+ z-index: 300;
222
+ display: flex;
223
+ align-items: center;
224
+ justify-content: center;
225
+ }
226
+
227
+ #confirm-modal.hidden { display: none; }
228
+
229
+ .confirm-backdrop {
230
+ position: absolute;
231
+ inset: 0;
232
+ background: rgba(var(--shadow-rgb), 0.5);
233
+ backdrop-filter: blur(2px);
234
+ -webkit-backdrop-filter: blur(2px);
235
+ }
236
+
237
+ .confirm-dialog {
238
+ position: relative;
239
+ background: var(--bg-alt);
240
+ border: 1px solid var(--border);
241
+ border-radius: 14px;
242
+ padding: 20px 24px;
243
+ max-width: 320px;
244
+ width: 90%;
245
+ box-shadow: 0 8px 32px rgba(var(--shadow-rgb), 0.5);
246
+ }
247
+
248
+ .confirm-text {
249
+ font-size: 14px;
250
+ color: var(--text);
251
+ line-height: 1.5;
252
+ margin-bottom: 18px;
253
+ }
254
+
255
+ .confirm-actions {
256
+ display: flex;
257
+ gap: 8px;
258
+ justify-content: flex-end;
259
+ }
260
+
261
+ .confirm-btn {
262
+ padding: 7px 16px;
263
+ border-radius: 8px;
264
+ border: none;
265
+ font-size: 13px;
266
+ font-weight: 500;
267
+ font-family: inherit;
268
+ cursor: pointer;
269
+ transition: background 0.15s, opacity 0.15s;
270
+ }
271
+
272
+ .confirm-cancel {
273
+ background: var(--input-bg);
274
+ color: var(--text-secondary);
275
+ border: 1px solid var(--border);
276
+ }
277
+
278
+ .confirm-cancel:hover { background: var(--sidebar-hover); }
279
+
280
+ .confirm-delete {
281
+ background: var(--error);
282
+ color: #fff;
283
+ }
284
+
285
+ .confirm-delete:hover { opacity: 0.85; }
286
+
287
+ .confirm-ok {
288
+ background: var(--accent);
289
+ color: #fff;
290
+ }
291
+
292
+ .confirm-ok:hover { opacity: 0.85; }
293
+
294
+ /* --- Resume modal --- */
295
+ /* --- Rewind modal --- */
296
+ #rewind-modal { position: fixed; inset: 0; z-index: 300; display: flex; align-items: center; justify-content: center; }
297
+ #rewind-modal.hidden { display: none; }
298
+
299
+ #rewind-modal .confirm-dialog {
300
+ max-width: 620px;
301
+ width: 94%;
302
+ max-height: 80vh;
303
+ display: flex;
304
+ flex-direction: column;
305
+ }
306
+
307
+ .rewind-modal-title {
308
+ font-size: 15px;
309
+ font-weight: 600;
310
+ color: var(--text);
311
+ margin-bottom: 12px;
312
+ flex-shrink: 0;
313
+ }
314
+
315
+ .rewind-modal-body {
316
+ font-size: 13px;
317
+ color: var(--text-secondary);
318
+ line-height: 1.6;
319
+ margin-bottom: 16px;
320
+ overflow-y: auto;
321
+ min-height: 0;
322
+ }
323
+
324
+ .rewind-modal-body p { margin: 0 0 10px; }
325
+
326
+ #rewind-mode-options {
327
+ display: flex;
328
+ flex-direction: column;
329
+ gap: 6px;
330
+ margin-bottom: 12px;
331
+ font-size: 13px;
332
+ color: var(--text-secondary);
333
+ }
334
+
335
+ #rewind-mode-options label {
336
+ display: flex;
337
+ align-items: center;
338
+ gap: 8px;
339
+ cursor: pointer;
340
+ padding: 4px 0;
341
+ }
342
+
343
+ #rewind-mode-options input[type="radio"] {
344
+ accent-color: var(--accent);
345
+ margin: 0;
346
+ }
347
+
348
+ .rewind-file-section {
349
+ margin-top: 10px;
350
+ border: 1px solid var(--border-subtle);
351
+ border-radius: 10px;
352
+ overflow: hidden;
353
+ }
354
+
355
+ .rewind-file-section + .rewind-file-section { margin-top: 8px; }
356
+
357
+ .rewind-file-header {
358
+ display: flex;
359
+ align-items: center;
360
+ gap: 8px;
361
+ padding: 8px 12px;
362
+ background: rgba(var(--overlay-rgb), 0.03);
363
+ cursor: pointer;
364
+ user-select: none;
365
+ transition: background 0.15s;
366
+ }
367
+
368
+ .rewind-file-header:hover { background: rgba(var(--overlay-rgb), 0.06); }
369
+
370
+ .rewind-file-chevron {
371
+ display: inline-flex;
372
+ color: var(--text-dimmer);
373
+ transition: transform 0.2s;
374
+ flex-shrink: 0;
375
+ }
376
+
377
+ .rewind-file-chevron .lucide { width: 13px; height: 13px; }
378
+
379
+ .rewind-file-section.expanded .rewind-file-chevron { transform: rotate(90deg); }
380
+
381
+ .rewind-file-path {
382
+ flex: 1;
383
+ font-family: "Roboto Mono", monospace;
384
+ font-size: 12px;
385
+ color: var(--text-muted);
386
+ overflow: hidden;
387
+ text-overflow: ellipsis;
388
+ white-space: nowrap;
389
+ direction: rtl;
390
+ text-align: left;
391
+ }
392
+
393
+ .rewind-file-stats {
394
+ font-size: 11px;
395
+ flex-shrink: 0;
396
+ }
397
+
398
+ .rewind-file-stats .stat-add { color: var(--success); }
399
+ .rewind-file-stats .stat-del { color: var(--error); }
400
+
401
+ .rewind-file-diff {
402
+ display: none;
403
+ background: var(--code-bg);
404
+ border-top: 1px solid var(--border-subtle);
405
+ max-height: 280px;
406
+ overflow: auto;
407
+ }
408
+
409
+ .rewind-file-section.expanded .rewind-file-diff { display: block; }
410
+
411
+ .rewind-file-diff pre {
412
+ margin: 0;
413
+ padding: 10px 12px;
414
+ font-family: "Roboto Mono", monospace;
415
+ font-size: 12px;
416
+ line-height: 1.55;
417
+ white-space: pre-wrap;
418
+ word-break: break-all;
419
+ }
420
+
421
+ .rewind-no-diff {
422
+ padding: 12px;
423
+ font-size: 12px;
424
+ color: var(--text-dimmer);
425
+ font-style: italic;
426
+ }
427
+
428
+ /* --- Resume / Session Picker modal --- */
429
+ #resume-modal { position: fixed; inset: 0; z-index: 300; display: flex; align-items: center; justify-content: center; }
430
+ #resume-modal.hidden { display: none; }
431
+
432
+ .resume-modal-title {
433
+ font-size: 15px;
434
+ font-weight: 600;
435
+ color: var(--text);
436
+ margin-bottom: 12px;
437
+ }
438
+
439
+ .resume-picker-dialog { min-width: 380px; max-width: 480px; }
440
+ .resume-picker-body { margin-bottom: 12px; }
441
+
442
+ .resume-picker-loading {
443
+ display: flex; align-items: center; gap: 10px;
444
+ padding: 24px 0; justify-content: center;
445
+ font-size: 13px; color: var(--text-muted);
446
+ }
447
+ .resume-picker-loading.hidden { display: none; }
448
+ .resume-picker-empty.hidden { display: none; }
449
+ .resume-picker-list.hidden { display: none; }
450
+
451
+ .resume-picker-spinner {
452
+ width: 16px; height: 16px;
453
+ border: 2px solid var(--border);
454
+ border-top-color: var(--text-secondary);
455
+ border-radius: 50%;
456
+ animation: spin 0.6s linear infinite;
457
+ }
458
+
459
+ @keyframes spin { to { transform: rotate(360deg); } }
460
+
461
+ .resume-picker-empty {
462
+ padding: 24px 0; text-align: center;
463
+ font-size: 13px; color: var(--text-muted);
464
+ }
465
+
466
+ .resume-picker-list {
467
+ max-height: 400px; overflow-y: auto;
468
+ display: flex; flex-direction: column; gap: 2px;
469
+ }
470
+
471
+ .cli-session-item {
472
+ display: flex; flex-direction: column; gap: 4px;
473
+ padding: 10px 12px; border-radius: 8px;
474
+ cursor: pointer; transition: background 0.15s;
475
+ border: 1px solid transparent;
476
+ }
477
+
478
+ .cli-session-item:hover {
479
+ background: rgba(var(--overlay-rgb), 0.05);
480
+ border-color: var(--border-subtle);
481
+ }
482
+
483
+ .cli-session-title {
484
+ font-size: 13px; color: var(--text);
485
+ white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
486
+ line-height: 1.4;
487
+ }
488
+
489
+ .cli-session-meta {
490
+ display: flex; align-items: center; gap: 8px;
491
+ font-size: 11px; color: var(--text-muted);
492
+ flex-wrap: wrap;
493
+ }
494
+
495
+ .cli-session-meta .badge {
496
+ background: rgba(var(--overlay-rgb), 0.07);
497
+ padding: 1px 6px; border-radius: 4px;
498
+ font-family: "Roboto Mono", monospace;
499
+ font-size: 10px;
500
+ }
501
+
502
+ /* --- Notification help modal --- */
503
+ #notif-help-modal { position: fixed; inset: 0; z-index: 300; display: flex; align-items: center; justify-content: center; }
504
+ #notif-help-modal.hidden { display: none; }
505
+
506
+ .notif-help-title {
507
+ font-size: 15px;
508
+ font-weight: 600;
509
+ color: var(--text);
510
+ margin-bottom: 12px;
511
+ }
512
+
513
+ .notif-help-body {
514
+ font-size: 13px;
515
+ color: var(--text-secondary);
516
+ line-height: 1.6;
517
+ margin-bottom: 16px;
518
+ }
519
+
520
+ .notif-help-body p { margin: 0 0 10px; }
521
+
522
+ .notif-help-body ol {
523
+ margin: 0 0 14px;
524
+ padding-left: 20px;
525
+ }
526
+
527
+ .notif-help-body ol li { margin-bottom: 4px; }
528
+
529
+ .notif-help-url {
530
+ display: flex;
531
+ align-items: center;
532
+ gap: 8px;
533
+ background: rgba(var(--overlay-rgb), 0.04);
534
+ border: 1px solid var(--border);
535
+ border-radius: 8px;
536
+ padding: 8px 10px;
537
+ }
538
+
539
+ .notif-help-url code {
540
+ font-family: "Roboto Mono", monospace;
541
+ font-size: 12px;
542
+ color: var(--text);
543
+ flex: 1;
544
+ user-select: all;
545
+ -webkit-user-select: all;
546
+ }
547
+
548
+ .notif-help-url .popover-copy {
549
+ background: none;
550
+ border: 1px solid var(--border);
551
+ border-radius: 6px;
552
+ color: var(--text-muted);
553
+ cursor: pointer;
554
+ padding: 4px 6px;
555
+ display: flex;
556
+ align-items: center;
557
+ flex-shrink: 0;
558
+ transition: color 0.15s, border-color 0.15s;
559
+ }
560
+
561
+ .notif-help-url .popover-copy .lucide { width: 13px; height: 13px; }
562
+ .notif-help-url .popover-copy:hover { color: var(--text); border-color: var(--text-dimmer); }
563
+ .notif-help-url .popover-copy.copied { color: var(--success); border-color: var(--success); }
564
+
565
+ /* --- Add project modal --- */
566
+ #add-project-modal { position: fixed; inset: 0; z-index: 300; display: flex; align-items: center; justify-content: center; }
567
+ #add-project-modal.hidden { display: none; }
568
+
569
+ .add-project-dialog { max-width: 420px; }
570
+
571
+ .add-project-title {
572
+ font-size: 15px;
573
+ font-weight: 600;
574
+ color: var(--text);
575
+ margin-bottom: 14px;
576
+ }
577
+
578
+ .add-project-body { margin-bottom: 16px; }
579
+
580
+ .add-project-input-wrap { position: relative; }
581
+
582
+ #add-project-input {
583
+ width: 100%;
584
+ background: var(--input-bg);
585
+ border: 1px solid var(--border);
586
+ border-radius: 8px;
587
+ color: var(--text);
588
+ font-size: 13px;
589
+ font-family: "Roboto Mono", monospace;
590
+ padding: 10px 12px;
591
+ outline: none;
592
+ transition: border-color 0.2s;
593
+ }
594
+
595
+ #add-project-input:focus { border-color: var(--text-dimmer); }
596
+ #add-project-input::placeholder { color: var(--text-muted); font-family: "Pretendard", system-ui, sans-serif; }
597
+
598
+ #add-project-suggestions {
599
+ position: absolute;
600
+ top: calc(100% + 4px);
601
+ left: 0;
602
+ right: 0;
603
+ background: var(--bg-alt);
604
+ border: 1px solid var(--border);
605
+ border-radius: 8px;
606
+ max-height: 200px;
607
+ overflow-y: auto;
608
+ z-index: 10;
609
+ box-shadow: 0 4px 16px rgba(var(--shadow-rgb), 0.4);
610
+ }
611
+
612
+ #add-project-suggestions.hidden { display: none; }
613
+
614
+ .add-project-suggestion-item {
615
+ display: flex;
616
+ align-items: center;
617
+ gap: 8px;
618
+ padding: 8px 12px;
619
+ font-size: 13px;
620
+ color: var(--text);
621
+ cursor: pointer;
622
+ transition: background 0.1s;
623
+ }
624
+
625
+ .add-project-suggestion-item:first-child { border-radius: 8px 8px 0 0; }
626
+ .add-project-suggestion-item:last-child { border-radius: 0 0 8px 8px; }
627
+ .add-project-suggestion-item:only-child { border-radius: 8px; }
628
+ .add-project-suggestion-item:hover,
629
+ .add-project-suggestion-item.active { background: var(--sidebar-hover); }
630
+
631
+ .add-project-suggestion-item .lucide { width: 14px; height: 14px; color: var(--text-muted); flex-shrink: 0; }
632
+
633
+ .add-project-suggestion-name {
634
+ flex: 1;
635
+ overflow: hidden;
636
+ text-overflow: ellipsis;
637
+ white-space: nowrap;
638
+ }
639
+
640
+ .add-project-suggestion-path {
641
+ font-size: 11px;
642
+ color: var(--text-muted);
643
+ overflow: hidden;
644
+ text-overflow: ellipsis;
645
+ white-space: nowrap;
646
+ max-width: 50%;
647
+ }
648
+
649
+ #add-project-error {
650
+ font-size: 12px;
651
+ color: var(--error);
652
+ margin-top: 8px;
653
+ }
654
+
655
+ #add-project-error.hidden { display: none; }
656
+
657
+ /* --- Connect overlay --- */
658
+ #connect-overlay {
659
+ position: absolute;
660
+ inset: 0;
661
+ display: flex;
662
+ flex-direction: column;
663
+ align-items: center;
664
+ justify-content: center;
665
+ background: var(--bg);
666
+ z-index: 50;
667
+ transition: opacity 0.6s ease;
668
+ }
669
+
670
+ #connect-overlay.hidden {
671
+ opacity: 0;
672
+ pointer-events: none;
673
+ }
674
+
675
+ .connect-logo {
676
+ width: 48px;
677
+ height: 48px;
678
+ border-radius: 12px;
679
+ animation: connect-breathe 3s ease-in-out infinite;
680
+ }
681
+
682
+ .connect-wordmark {
683
+ margin-top: 12px;
684
+ font-family: "Nunito", sans-serif;
685
+ font-size: 20px;
686
+ font-weight: 800;
687
+ color: var(--text-dimmer);
688
+ letter-spacing: 0.5px;
689
+ animation: connect-breathe 3s ease-in-out infinite;
690
+ animation-delay: 0.3s;
691
+ }
692
+
693
+ @keyframes connect-breathe {
694
+ 0%, 100% { opacity: 0.35; }
695
+ 50% { opacity: 0.7; }
696
+ }
697
+