claude-controller 0.1.2 → 0.2.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.
@@ -0,0 +1,580 @@
1
+ /* ── Jobs & Stream ── */
2
+
3
+ /* ── Job Table ── */
4
+ .table-wrap { overflow-x: hidden; }
5
+
6
+ table {
7
+ width: 100%;
8
+ border-collapse: collapse;
9
+ font-size: 0.82rem;
10
+ table-layout: fixed;
11
+ }
12
+
13
+ th {
14
+ text-align: left;
15
+ padding: 10px 14px;
16
+ font-weight: 600;
17
+ font-size: 0.72rem;
18
+ text-transform: uppercase;
19
+ letter-spacing: 0.06em;
20
+ color: var(--text-muted);
21
+ background: var(--bg);
22
+ border-bottom: 1px solid var(--border);
23
+ white-space: nowrap;
24
+ }
25
+
26
+ td {
27
+ padding: 10px 14px;
28
+ border-bottom: 1px solid var(--border);
29
+ color: var(--text-secondary);
30
+ vertical-align: top;
31
+ overflow: hidden;
32
+ text-overflow: ellipsis;
33
+ white-space: nowrap;
34
+ }
35
+
36
+ tr:hover td { background: var(--surface-hover); }
37
+ tr { cursor: pointer; transition: background var(--transition); }
38
+ thead tr { cursor: default; }
39
+
40
+ .badge {
41
+ display: inline-flex;
42
+ align-items: center;
43
+ gap: 5px;
44
+ padding: 3px 9px;
45
+ border-radius: 20px;
46
+ font-size: 0.72rem;
47
+ font-weight: 600;
48
+ white-space: nowrap;
49
+ }
50
+
51
+ .badge-running {
52
+ background: var(--blue-dim);
53
+ color: var(--blue);
54
+ }
55
+
56
+ .badge-running::before {
57
+ content: '';
58
+ width: 6px; height: 6px;
59
+ border-radius: 50%;
60
+ background: var(--blue);
61
+ animation: pulse 1.5s ease-in-out infinite;
62
+ }
63
+
64
+ .badge-done {
65
+ background: var(--green-dim);
66
+ color: var(--green);
67
+ }
68
+
69
+ .badge-failed {
70
+ background: var(--red-dim);
71
+ color: var(--red);
72
+ }
73
+
74
+ .badge-pending {
75
+ background: var(--yellow-dim);
76
+ color: var(--yellow);
77
+ }
78
+
79
+ .job-id {
80
+ font-family: var(--font-mono);
81
+ font-size: 0.78rem;
82
+ color: var(--accent);
83
+ }
84
+
85
+ .job-cwd {
86
+ font-family: var(--font-mono);
87
+ font-size: 0.75rem;
88
+ color: var(--text-muted);
89
+ }
90
+
91
+ .job-session {
92
+ font-family: var(--font-mono);
93
+ font-size: 0.78rem;
94
+ color: var(--text-muted);
95
+ }
96
+ .job-session.clickable {
97
+ color: var(--accent);
98
+ cursor: pointer;
99
+ border-radius: 3px;
100
+ transition: background var(--transition);
101
+ }
102
+ .job-session.clickable:hover {
103
+ text-decoration: underline;
104
+ background: var(--accent-glow);
105
+ }
106
+
107
+ .job-time {
108
+ font-size: 0.75rem;
109
+ color: var(--text-muted);
110
+ white-space: nowrap;
111
+ }
112
+
113
+ .expand-row td {
114
+ padding: 0;
115
+ border-bottom: 1px solid var(--border);
116
+ }
117
+
118
+ .expand-content {
119
+ padding: 14px 18px;
120
+ background: var(--bg);
121
+ font-family: var(--font-mono);
122
+ font-size: 0.78rem;
123
+ line-height: 1.7;
124
+ color: var(--text-secondary);
125
+ white-space: pre-wrap;
126
+ word-break: break-word;
127
+ max-height: 300px;
128
+ overflow-y: auto;
129
+ animation: slideDown 0.2s ease;
130
+ }
131
+
132
+ @keyframes slideDown {
133
+ from { opacity: 0; max-height: 0; }
134
+ to { opacity: 1; max-height: 300px; }
135
+ }
136
+
137
+ .empty-state {
138
+ text-align: center;
139
+ padding: 40px 20px;
140
+ color: var(--text-muted);
141
+ font-size: 0.85rem;
142
+ }
143
+
144
+ .empty-state svg {
145
+ width: 40px;
146
+ height: 40px;
147
+ margin-bottom: 12px;
148
+ opacity: 0.3;
149
+ }
150
+
151
+ /* ── Stream Panel ── */
152
+ .stream-panel {
153
+ background: var(--bg);
154
+ border-top: 1px solid var(--border);
155
+ animation: streamSlideDown 0.25s ease;
156
+ }
157
+
158
+ @keyframes streamSlideDown {
159
+ from { opacity: 0; max-height: 0; }
160
+ to { opacity: 1; max-height: 600px; }
161
+ }
162
+
163
+
164
+ .stream-spinner {
165
+ display: inline-block;
166
+ width: 12px;
167
+ height: 12px;
168
+ border: 2px solid rgba(96, 165, 250, 0.25);
169
+ border-top-color: var(--blue);
170
+ border-radius: 50%;
171
+ animation: spin 0.8s linear infinite;
172
+ }
173
+
174
+ .stream-pulse {
175
+ display: inline-flex;
176
+ align-items: center;
177
+ gap: 4px;
178
+ font-size: 0.7rem;
179
+ color: var(--blue);
180
+ font-weight: 500;
181
+ }
182
+
183
+ .stream-pulse-dot {
184
+ width: 6px;
185
+ height: 6px;
186
+ border-radius: 50%;
187
+ background: var(--blue);
188
+ animation: streamPulse 1.5s ease-in-out infinite;
189
+ }
190
+
191
+ @keyframes streamPulse {
192
+ 0%, 100% { opacity: 1; transform: scale(1); }
193
+ 50% { opacity: 0.3; transform: scale(0.7); }
194
+ }
195
+
196
+ .stream-content {
197
+ max-height: 400px;
198
+ overflow-y: auto;
199
+ padding: 14px 18px;
200
+ background: #080a0e;
201
+ font-family: var(--font-mono);
202
+ font-size: 0.78rem;
203
+ line-height: 1.7;
204
+ scroll-behavior: smooth;
205
+ }
206
+
207
+ .stream-content::-webkit-scrollbar-thumb { background: var(--border-light); }
208
+
209
+ .stream-event {
210
+ padding: 3px 0;
211
+ word-break: break-word;
212
+ }
213
+
214
+ .stream-event + .stream-event {
215
+ margin-top: 2px;
216
+ }
217
+
218
+ .stream-event-text {
219
+ color: #e4e6ed;
220
+ white-space: pre-wrap;
221
+ }
222
+
223
+ .stream-event-tool {
224
+ color: var(--yellow);
225
+ display: flex;
226
+ align-items: flex-start;
227
+ gap: 8px;
228
+ padding: 4px 0;
229
+ }
230
+
231
+ .stream-tool-badge {
232
+ display: inline-flex;
233
+ align-items: center;
234
+ gap: 4px;
235
+ padding: 2px 8px;
236
+ border-radius: 4px;
237
+ background: var(--yellow-dim);
238
+ color: var(--yellow);
239
+ font-size: 0.7rem;
240
+ font-weight: 600;
241
+ white-space: nowrap;
242
+ flex-shrink: 0;
243
+ }
244
+
245
+ .stream-tool-badge::before {
246
+ content: '>';
247
+ opacity: 0.5;
248
+ }
249
+
250
+ .stream-tool-input {
251
+ color: #d4d4d4;
252
+ white-space: pre-wrap;
253
+ flex: 1;
254
+ min-width: 0;
255
+ }
256
+
257
+ .stream-event-result {
258
+ color: var(--green);
259
+ padding: 6px 0;
260
+ display: flex;
261
+ align-items: flex-start;
262
+ gap: 8px;
263
+ }
264
+
265
+ .stream-result-icon {
266
+ color: var(--green);
267
+ flex-shrink: 0;
268
+ font-weight: 700;
269
+ }
270
+
271
+ .stream-result-text {
272
+ white-space: pre-wrap;
273
+ flex: 1;
274
+ min-width: 0;
275
+ }
276
+
277
+ .stream-event-error {
278
+ color: var(--red);
279
+ padding: 4px 0;
280
+ display: flex;
281
+ align-items: flex-start;
282
+ gap: 8px;
283
+ }
284
+
285
+ .stream-error-icon {
286
+ color: var(--red);
287
+ flex-shrink: 0;
288
+ font-weight: 700;
289
+ }
290
+
291
+ .stream-error-text {
292
+ white-space: pre-wrap;
293
+ flex: 1;
294
+ min-width: 0;
295
+ }
296
+
297
+ .stream-empty {
298
+ color: var(--text-muted);
299
+ text-align: center;
300
+ padding: 24px;
301
+ font-size: 0.8rem;
302
+ }
303
+
304
+ .stream-done-banner {
305
+ display: flex;
306
+ align-items: center;
307
+ justify-content: center;
308
+ gap: 8px;
309
+ padding: 8px 18px;
310
+ background: var(--green-dim);
311
+ color: var(--green);
312
+ font-size: 0.75rem;
313
+ font-weight: 600;
314
+ border-top: 1px solid rgba(52, 211, 153, 0.2);
315
+ }
316
+
317
+ .stream-done-banner.failed {
318
+ background: var(--red-dim);
319
+ color: var(--red);
320
+ border-top-color: rgba(248, 113, 113, 0.2);
321
+ }
322
+
323
+ /* ── Stream Action Buttons ── */
324
+ .stream-actions {
325
+ display: flex;
326
+ align-items: center;
327
+ gap: 6px;
328
+ padding: 8px 18px;
329
+ border-top: 1px solid var(--border);
330
+ background: var(--surface);
331
+ }
332
+
333
+ .stream-actions .btn svg { flex-shrink: 0; }
334
+
335
+ /* ── Delete Button in Job Row ── */
336
+ .btn-delete-job {
337
+ padding: 3px 8px;
338
+ border-radius: 4px;
339
+ background: transparent;
340
+ color: var(--text-muted);
341
+ border: 1px solid transparent;
342
+ font-size: 0.72rem;
343
+ cursor: pointer;
344
+ display: inline-flex;
345
+ align-items: center;
346
+ gap: 4px;
347
+ transition: all var(--transition);
348
+ }
349
+
350
+ .btn-delete-job:hover {
351
+ background: var(--red-dim);
352
+ color: var(--red);
353
+ border-color: var(--red);
354
+ }
355
+
356
+ /* ── Retry Job Button in Job Row ── */
357
+ .btn-retry-job {
358
+ padding: 3px 8px;
359
+ border-radius: 4px;
360
+ background: transparent;
361
+ color: var(--text-muted);
362
+ border: 1px solid transparent;
363
+ font-size: 0.72rem;
364
+ cursor: pointer;
365
+ display: inline-flex;
366
+ align-items: center;
367
+ gap: 4px;
368
+ transition: all var(--transition);
369
+ }
370
+
371
+ .btn-retry-job:hover {
372
+ background: var(--yellow-dim);
373
+ color: var(--yellow);
374
+ border-color: var(--yellow);
375
+ }
376
+
377
+ /* ── Continue Session Button in Job Row ── */
378
+ .btn-continue-job {
379
+ padding: 3px 8px;
380
+ border-radius: 4px;
381
+ background: transparent;
382
+ color: var(--text-muted);
383
+ border: 1px solid transparent;
384
+ font-size: 0.72rem;
385
+ cursor: pointer;
386
+ display: inline-flex;
387
+ align-items: center;
388
+ gap: 4px;
389
+ transition: all var(--transition);
390
+ }
391
+
392
+ .btn-continue-job:hover {
393
+ background: var(--accent-glow);
394
+ color: var(--accent);
395
+ border-color: var(--accent);
396
+ }
397
+
398
+ /* ── Fork Session Button in Job Row ── */
399
+ .btn-fork-job {
400
+ padding: 3px 8px;
401
+ border-radius: 4px;
402
+ background: transparent;
403
+ color: var(--text-muted);
404
+ border: 1px solid transparent;
405
+ font-size: 0.72rem;
406
+ cursor: pointer;
407
+ display: inline-flex;
408
+ align-items: center;
409
+ gap: 4px;
410
+ transition: all var(--transition);
411
+ }
412
+
413
+ .btn-fork-job:hover {
414
+ background: var(--yellow-dim);
415
+ color: var(--yellow);
416
+ border-color: var(--yellow);
417
+ }
418
+
419
+ /* ── Follow-up Input in Stream Panel ── */
420
+ .stream-followup {
421
+ display: flex;
422
+ align-items: center;
423
+ gap: 8px;
424
+ padding: 10px 18px;
425
+ border-top: 1px solid var(--border);
426
+ background: var(--bg);
427
+ }
428
+
429
+ .stream-followup-label {
430
+ font-size: 0.7rem;
431
+ color: var(--accent);
432
+ font-weight: 600;
433
+ white-space: nowrap;
434
+ flex-shrink: 0;
435
+ }
436
+
437
+ .followup-input-wrap {
438
+ display: flex;
439
+ align-items: center;
440
+ gap: 6px;
441
+ flex: 1;
442
+ }
443
+
444
+ .followup-input {
445
+ flex: 1;
446
+ padding: 6px 10px;
447
+ border-radius: var(--radius);
448
+ border: 1px solid var(--border);
449
+ background: var(--surface);
450
+ color: var(--text);
451
+ font-size: 0.78rem;
452
+ font-family: var(--font-mono);
453
+ outline: none;
454
+ transition: border-color var(--transition);
455
+ }
456
+
457
+ .followup-input:focus {
458
+ border-color: var(--accent);
459
+ }
460
+
461
+ .followup-input::placeholder {
462
+ color: var(--text-muted);
463
+ font-size: 0.72rem;
464
+ }
465
+
466
+ .followup-previews {
467
+ display: flex;
468
+ flex-wrap: wrap;
469
+ gap: 4px;
470
+ padding: 0 18px;
471
+ }
472
+
473
+ .followup-previews:empty { display: none; }
474
+
475
+ .followup-file-chip {
476
+ display: inline-block;
477
+ padding: 1px 6px;
478
+ border-radius: 4px;
479
+ font-size: 0.68rem;
480
+ font-family: var(--font-mono);
481
+ background: var(--green-dim);
482
+ color: var(--green);
483
+ white-space: nowrap;
484
+ max-width: 200px;
485
+ overflow: hidden;
486
+ text-overflow: ellipsis;
487
+ }
488
+
489
+ /* ── Copy Success Animation ── */
490
+ .btn-copied {
491
+ color: var(--green) !important;
492
+ border-color: var(--green) !important;
493
+ background: var(--green-dim) !important;
494
+ }
495
+
496
+ /* ── Toast ── */
497
+ .toast-container {
498
+ position: fixed;
499
+ top: 70px;
500
+ right: 24px;
501
+ z-index: 1000;
502
+ display: flex;
503
+ flex-direction: column;
504
+ gap: 8px;
505
+ }
506
+
507
+ .toast {
508
+ padding: 10px 16px;
509
+ border-radius: var(--radius);
510
+ font-size: 0.82rem;
511
+ font-weight: 500;
512
+ background: var(--surface);
513
+ border: 1px solid var(--border);
514
+ color: var(--text);
515
+ box-shadow: var(--shadow);
516
+ animation: toastIn 0.3s ease, toastOut 0.3s ease 2.7s forwards;
517
+ display: flex;
518
+ align-items: center;
519
+ gap: 8px;
520
+ }
521
+
522
+ .toast.success { border-color: var(--green); color: var(--green); }
523
+ .toast.error { border-color: var(--red); color: var(--red); }
524
+
525
+ @keyframes toastIn {
526
+ from { opacity: 0; transform: translateX(20px); }
527
+ to { opacity: 1; transform: translateX(0); }
528
+ }
529
+
530
+ @keyframes toastOut {
531
+ from { opacity: 1; transform: translateX(0); }
532
+ to { opacity: 0; transform: translateX(20px); }
533
+ }
534
+
535
+ /* ── Spinner ── */
536
+ .spinner {
537
+ display: inline-block;
538
+ width: 14px;
539
+ height: 14px;
540
+ border: 2px solid var(--border);
541
+ border-top-color: var(--accent);
542
+ border-radius: 50%;
543
+ animation: spin 0.6s linear infinite;
544
+ }
545
+
546
+ @keyframes spin { to { transform: rotate(360deg); } }
547
+
548
+ /* ── Responsive ── */
549
+ /* ── @image Chip in prompt cell ── */
550
+ .prompt-img-chip {
551
+ display: inline-flex;
552
+ align-items: center;
553
+ gap: 3px;
554
+ padding: 1px 7px;
555
+ border-radius: 4px;
556
+ background: var(--blue-dim);
557
+ color: var(--blue);
558
+ font-size: 0.7rem;
559
+ font-weight: 600;
560
+ font-family: var(--font-mono);
561
+ white-space: nowrap;
562
+ vertical-align: baseline;
563
+ }
564
+
565
+ .prompt-img-chip svg {
566
+ width: 10px;
567
+ height: 10px;
568
+ flex-shrink: 0;
569
+ }
570
+
571
+ @media (max-width: 900px) {
572
+ th, td { padding: 10px 10px; font-size: 0.78rem; }
573
+ }
574
+
575
+ @media (max-width: 600px) {
576
+ .main { padding: 4px 0; }
577
+ .card-body { padding: 14px; }
578
+ th, td { padding: 8px 6px; font-size: 0.74rem; }
579
+ .stream-content { max-height: 300px; }
580
+ }