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