claude-controller 0.1.2 → 0.3.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 (71) hide show
  1. package/README.md +2 -2
  2. package/bin/autoloop.sh +382 -0
  3. package/bin/ctl +1189 -0
  4. package/bin/native-app.py +6 -3
  5. package/bin/watchdog.sh +357 -0
  6. package/cognitive/__init__.py +14 -0
  7. package/cognitive/__pycache__/__init__.cpython-314.pyc +0 -0
  8. package/cognitive/__pycache__/dispatcher.cpython-314.pyc +0 -0
  9. package/cognitive/__pycache__/evaluator.cpython-314.pyc +0 -0
  10. package/cognitive/__pycache__/goal_engine.cpython-314.pyc +0 -0
  11. package/cognitive/__pycache__/learning.cpython-314.pyc +0 -0
  12. package/cognitive/__pycache__/orchestrator.cpython-314.pyc +0 -0
  13. package/cognitive/__pycache__/planner.cpython-314.pyc +0 -0
  14. package/cognitive/dispatcher.py +192 -0
  15. package/cognitive/evaluator.py +289 -0
  16. package/cognitive/goal_engine.py +232 -0
  17. package/cognitive/learning.py +189 -0
  18. package/cognitive/orchestrator.py +303 -0
  19. package/cognitive/planner.py +207 -0
  20. package/cognitive/prompts/analyst.md +31 -0
  21. package/cognitive/prompts/coder.md +22 -0
  22. package/cognitive/prompts/reviewer.md +33 -0
  23. package/cognitive/prompts/tester.md +21 -0
  24. package/cognitive/prompts/writer.md +25 -0
  25. package/config.sh +6 -1
  26. package/dag/__init__.py +5 -0
  27. package/dag/__pycache__/__init__.cpython-314.pyc +0 -0
  28. package/dag/__pycache__/graph.cpython-314.pyc +0 -0
  29. package/dag/graph.py +222 -0
  30. package/lib/jobs.sh +12 -1
  31. package/package.json +11 -5
  32. package/postinstall.sh +1 -1
  33. package/service/controller.sh +43 -11
  34. package/web/audit.py +122 -0
  35. package/web/checkpoint.py +80 -0
  36. package/web/config.py +2 -5
  37. package/web/handler.py +634 -473
  38. package/web/handler_fs.py +153 -0
  39. package/web/handler_goals.py +203 -0
  40. package/web/handler_jobs.py +372 -0
  41. package/web/handler_memory.py +203 -0
  42. package/web/handler_sessions.py +132 -0
  43. package/web/jobs.py +585 -13
  44. package/web/personas.py +419 -0
  45. package/web/pipeline.py +981 -0
  46. package/web/presets.py +506 -0
  47. package/web/projects.py +246 -0
  48. package/web/static/api.js +141 -0
  49. package/web/static/app.js +25 -1937
  50. package/web/static/attachments.js +144 -0
  51. package/web/static/base.css +497 -0
  52. package/web/static/context.js +204 -0
  53. package/web/static/dirs.js +246 -0
  54. package/web/static/form.css +763 -0
  55. package/web/static/goals.css +363 -0
  56. package/web/static/goals.js +300 -0
  57. package/web/static/i18n.js +625 -0
  58. package/web/static/index.html +215 -13
  59. package/web/static/{styles.css → jobs.css} +746 -1141
  60. package/web/static/jobs.js +1270 -0
  61. package/web/static/memoryview.js +117 -0
  62. package/web/static/personas.js +228 -0
  63. package/web/static/pipeline.css +338 -0
  64. package/web/static/pipelines.js +487 -0
  65. package/web/static/presets.js +244 -0
  66. package/web/static/send.js +135 -0
  67. package/web/static/settings-style.css +291 -0
  68. package/web/static/settings.js +81 -0
  69. package/web/static/stream.js +534 -0
  70. package/web/static/utils.js +131 -0
  71. package/web/webhook.py +210 -0
@@ -0,0 +1,763 @@
1
+ /* ── Form & Directory Components ── */
2
+ /* ── Layout ── */
3
+ .layout {
4
+ min-height: 100vh;
5
+ }
6
+
7
+ .main {
8
+ padding: 8px 0;
9
+ overflow-x: hidden;
10
+ }
11
+
12
+ /* ── CWD badge ── */
13
+ .cwd-badge {
14
+ display: inline-flex;
15
+ align-items: center;
16
+ gap: 4px;
17
+ padding: 2px 8px;
18
+ border-radius: 12px;
19
+ font-size: 0.7rem;
20
+ font-weight: 500;
21
+ background: var(--accent-glow);
22
+ color: var(--accent);
23
+ margin-left: 8px;
24
+ max-width: 180px;
25
+ overflow: hidden;
26
+ text-overflow: ellipsis;
27
+ white-space: nowrap;
28
+ vertical-align: middle;
29
+ }
30
+
31
+ .cwd-badge:empty { display: none; }
32
+
33
+ /* ── Directory Picker ── */
34
+ .dir-picker {
35
+ display: flex;
36
+ align-items: center;
37
+ gap: 8px;
38
+ }
39
+
40
+ .dir-picker-display {
41
+ flex: 1;
42
+ display: flex;
43
+ align-items: center;
44
+ gap: 8px;
45
+ padding: 8px 12px;
46
+ border-radius: var(--radius);
47
+ background: var(--bg);
48
+ border: 1px solid var(--border);
49
+ color: var(--text-muted);
50
+ font-size: 0.85rem;
51
+ font-family: var(--font-mono);
52
+ min-height: 38px;
53
+ overflow: hidden;
54
+ text-overflow: ellipsis;
55
+ white-space: nowrap;
56
+ cursor: pointer;
57
+ transition: all var(--transition);
58
+ }
59
+
60
+ .dir-picker-display:hover {
61
+ border-color: var(--border-light);
62
+ background: var(--surface);
63
+ }
64
+
65
+ .dir-picker-display.has-value {
66
+ color: var(--text);
67
+ }
68
+
69
+ .dir-picker-display .dir-icon {
70
+ flex-shrink: 0;
71
+ color: var(--text-muted);
72
+ }
73
+
74
+ .dir-picker-clear {
75
+ flex-shrink: 0;
76
+ padding: 4px;
77
+ border-radius: 4px;
78
+ background: transparent;
79
+ color: var(--text-muted);
80
+ border: none;
81
+ cursor: pointer;
82
+ display: none;
83
+ }
84
+
85
+ .dir-picker-clear:hover {
86
+ background: var(--red-dim);
87
+ color: var(--red);
88
+ }
89
+
90
+ .dir-picker-clear.visible { display: inline-flex; }
91
+
92
+ /* ── Recent Directory Chips ── */
93
+ /* ── Project Bar ── */
94
+ .project-bar {
95
+ display: flex;
96
+ align-items: center;
97
+ gap: 6px;
98
+ flex-wrap: wrap;
99
+ margin-bottom: 10px;
100
+ }
101
+ .project-bar:empty { display: none; }
102
+ .project-chips { display: flex; gap: 5px; flex-wrap: wrap; flex: 1; min-height: 0; }
103
+ .project-chips:empty + .project-action-btn { margin-left: 0; }
104
+
105
+ .project-chip {
106
+ display: inline-flex;
107
+ align-items: center;
108
+ gap: 5px;
109
+ padding: 4px 12px;
110
+ border-radius: 14px;
111
+ background: var(--surface);
112
+ border: 1px solid var(--border);
113
+ color: var(--text-secondary);
114
+ font-size: 0.75rem;
115
+ cursor: pointer;
116
+ transition: all var(--transition);
117
+ max-width: 200px;
118
+ }
119
+ .project-chip:hover { background: var(--surface-hover); border-color: var(--border-light); }
120
+ .project-chip.selected {
121
+ background: var(--accent-glow);
122
+ border-color: var(--accent);
123
+ color: var(--accent);
124
+ }
125
+ .project-chip .project-chip-name {
126
+ overflow: hidden;
127
+ text-overflow: ellipsis;
128
+ white-space: nowrap;
129
+ }
130
+ .project-chip .project-chip-remove {
131
+ display: inline-flex;
132
+ align-items: center;
133
+ opacity: 0;
134
+ transition: opacity var(--transition);
135
+ color: var(--text-muted);
136
+ flex-shrink: 0;
137
+ }
138
+ .project-chip:hover .project-chip-remove { opacity: 1; }
139
+ .project-chip .project-chip-remove:hover { color: var(--red); }
140
+
141
+ .project-action-btn {
142
+ display: inline-flex;
143
+ align-items: center;
144
+ justify-content: center;
145
+ width: 24px;
146
+ height: 24px;
147
+ border-radius: 50%;
148
+ border: 1px dashed var(--border-light);
149
+ background: transparent;
150
+ color: var(--text-muted);
151
+ cursor: pointer;
152
+ transition: all var(--transition);
153
+ flex-shrink: 0;
154
+ }
155
+ .project-action-btn:hover { border-color: var(--accent); color: var(--accent); background: var(--accent-glow); }
156
+
157
+ .recent-dirs {
158
+ display: flex;
159
+ align-items: center;
160
+ gap: 6px;
161
+ flex-wrap: wrap;
162
+ margin-bottom: 10px;
163
+ }
164
+
165
+ .recent-dirs:empty { display: none; }
166
+
167
+ .recent-dirs-label {
168
+ font-size: 0.72rem;
169
+ color: var(--text-muted);
170
+ font-weight: 500;
171
+ flex-shrink: 0;
172
+ margin-right: 2px;
173
+ }
174
+
175
+ .recent-chip {
176
+ display: inline-flex;
177
+ align-items: center;
178
+ gap: 4px;
179
+ padding: 3px 10px;
180
+ border-radius: 14px;
181
+ background: var(--surface);
182
+ border: 1px solid var(--border);
183
+ color: var(--text-secondary);
184
+ font-size: 0.75rem;
185
+ font-family: var(--font-mono);
186
+ cursor: pointer;
187
+ transition: all var(--transition);
188
+ max-width: 200px;
189
+ }
190
+
191
+ .recent-chip:hover {
192
+ border-color: var(--accent);
193
+ color: var(--accent);
194
+ background: var(--accent-glow);
195
+ }
196
+
197
+ .recent-chip.active {
198
+ border-color: var(--accent);
199
+ color: var(--accent);
200
+ background: var(--accent-glow);
201
+ font-weight: 500;
202
+ }
203
+
204
+ .recent-chip-name {
205
+ overflow: hidden;
206
+ text-overflow: ellipsis;
207
+ white-space: nowrap;
208
+ }
209
+
210
+ .recent-chip-remove {
211
+ flex-shrink: 0;
212
+ width: 14px;
213
+ height: 14px;
214
+ padding: 0;
215
+ margin-left: 2px;
216
+ border: none;
217
+ background: transparent;
218
+ color: var(--text-muted);
219
+ cursor: pointer;
220
+ border-radius: 50%;
221
+ display: inline-flex;
222
+ align-items: center;
223
+ justify-content: center;
224
+ transition: all var(--transition);
225
+ }
226
+
227
+ .recent-chip-remove:hover {
228
+ background: var(--red-dim);
229
+ color: var(--red);
230
+ }
231
+
232
+ /* ── Inline Directory Browser Panel ── */
233
+ .dir-browser-panel {
234
+ display: none;
235
+ border: 1px solid var(--border);
236
+ border-radius: var(--radius);
237
+ background: var(--surface);
238
+ margin-top: 8px;
239
+ overflow: hidden;
240
+ animation: panel-slide 0.15s ease-out;
241
+ }
242
+
243
+ .dir-browser-panel.open { display: block; }
244
+
245
+ @keyframes panel-slide {
246
+ from { opacity: 0; transform: translateY(-4px); }
247
+ to { opacity: 1; transform: translateY(0); }
248
+ }
249
+
250
+ .dir-modal-header {
251
+ display: flex;
252
+ align-items: center;
253
+ justify-content: space-between;
254
+ padding: 10px 12px;
255
+ border-bottom: 1px solid var(--border);
256
+ }
257
+
258
+ .dir-modal-title {
259
+ font-size: 0.82rem;
260
+ font-weight: 600;
261
+ color: var(--text);
262
+ }
263
+
264
+ .dir-modal-close {
265
+ padding: 4px;
266
+ border-radius: 4px;
267
+ background: transparent;
268
+ color: var(--text-muted);
269
+ border: none;
270
+ cursor: pointer;
271
+ }
272
+
273
+ .dir-modal-close:hover { background: var(--surface-active); color: var(--text); }
274
+
275
+ .dir-create-row {
276
+ display: flex;
277
+ align-items: center;
278
+ gap: 6px;
279
+ padding: 6px 12px;
280
+ border-bottom: 1px solid var(--border);
281
+ background: var(--bg);
282
+ }
283
+
284
+ .dir-create-input {
285
+ flex: 1;
286
+ padding: 4px 8px;
287
+ font-size: 0.78rem;
288
+ border: 1px solid var(--border);
289
+ border-radius: 4px;
290
+ background: var(--surface);
291
+ color: var(--text);
292
+ outline: none;
293
+ }
294
+
295
+ .dir-create-input:focus {
296
+ border-color: var(--accent);
297
+ box-shadow: 0 0 0 2px var(--accent-glow);
298
+ }
299
+
300
+ .dir-modal-path {
301
+ display: flex;
302
+ align-items: center;
303
+ gap: 4px;
304
+ padding: 8px 12px;
305
+ background: var(--bg);
306
+ border-bottom: 1px solid var(--border);
307
+ font-family: var(--font-mono);
308
+ font-size: 0.75rem;
309
+ color: var(--text-secondary);
310
+ overflow-x: auto;
311
+ white-space: nowrap;
312
+ }
313
+
314
+ .dir-modal-path .breadcrumb-seg {
315
+ padding: 2px 6px;
316
+ border-radius: 4px;
317
+ cursor: pointer;
318
+ color: var(--accent);
319
+ transition: background var(--transition);
320
+ }
321
+
322
+ .dir-modal-path .breadcrumb-seg:hover {
323
+ background: var(--accent-glow);
324
+ }
325
+
326
+ .dir-modal-path .breadcrumb-sep {
327
+ color: var(--text-muted);
328
+ }
329
+
330
+ .dir-modal-list {
331
+ flex: 1;
332
+ overflow-y: auto;
333
+ padding: 4px 0;
334
+ max-height: 240px;
335
+ }
336
+
337
+ .dir-item {
338
+ display: flex;
339
+ align-items: center;
340
+ gap: 10px;
341
+ padding: 8px 16px;
342
+ cursor: pointer;
343
+ font-size: 0.85rem;
344
+ color: var(--text);
345
+ transition: background var(--transition);
346
+ }
347
+
348
+ .dir-item:hover { background: var(--surface-hover); }
349
+
350
+ .dir-item-icon {
351
+ flex-shrink: 0;
352
+ width: 18px;
353
+ height: 18px;
354
+ color: var(--text-muted);
355
+ }
356
+
357
+ .dir-item-icon.is-dir { color: var(--yellow); }
358
+ .dir-item-icon.is-parent { color: var(--accent); }
359
+
360
+ .dir-item-name {
361
+ flex: 1;
362
+ overflow: hidden;
363
+ text-overflow: ellipsis;
364
+ white-space: nowrap;
365
+ }
366
+
367
+ .dir-item-name.is-dir { font-weight: 500; }
368
+
369
+ .dir-modal-footer {
370
+ display: flex;
371
+ align-items: center;
372
+ justify-content: space-between;
373
+ padding: 10px 12px;
374
+ border-top: 1px solid var(--border);
375
+ gap: 8px;
376
+ }
377
+
378
+ .dir-modal-current {
379
+ flex: 1;
380
+ font-family: var(--font-mono);
381
+ font-size: 0.78rem;
382
+ color: var(--text-secondary);
383
+ overflow: hidden;
384
+ text-overflow: ellipsis;
385
+ white-space: nowrap;
386
+ }
387
+
388
+ .dir-modal-loading {
389
+ display: flex;
390
+ align-items: center;
391
+ justify-content: center;
392
+ padding: 32px;
393
+ color: var(--text-muted);
394
+ font-size: 0.85rem;
395
+ gap: 8px;
396
+ }
397
+
398
+ /* ── Cards / Sections ── */
399
+ .section {
400
+ animation: fadeIn 0.3s ease forwards;
401
+ animation-iteration-count: 1;
402
+ }
403
+
404
+ @keyframes fadeIn {
405
+ from { opacity: 0; transform: translateY(8px); }
406
+ to { opacity: 1; transform: translateY(0); }
407
+ }
408
+
409
+ .card {
410
+ background: var(--surface);
411
+ border: 1px solid var(--border);
412
+ border-left: none;
413
+ border-right: none;
414
+ border-radius: 0;
415
+ overflow: visible;
416
+ }
417
+
418
+ .card-header {
419
+ display: flex;
420
+ align-items: center;
421
+ justify-content: space-between;
422
+ padding: 14px 18px;
423
+ border-bottom: 1px solid var(--border);
424
+ gap: 8px;
425
+ flex-wrap: wrap;
426
+ }
427
+
428
+ .card-title {
429
+ font-size: 0.92rem;
430
+ font-weight: 600;
431
+ color: var(--text);
432
+ display: flex;
433
+ align-items: center;
434
+ gap: 8px;
435
+ min-width: 0;
436
+ flex: 1 1 0;
437
+ }
438
+
439
+ .card-title svg { width: 16px; height: 16px; flex-shrink: 0; color: var(--accent); }
440
+
441
+ .card-header-actions {
442
+ display: flex;
443
+ align-items: center;
444
+ gap: 8px;
445
+ flex-shrink: 0;
446
+ }
447
+
448
+ .card-body { padding: 18px; }
449
+
450
+ /* ── Send Task Form ── */
451
+ .form-group { margin-bottom: 14px; }
452
+
453
+ .form-label {
454
+ display: flex;
455
+ align-items: center;
456
+ font-size: 0.78rem;
457
+ font-weight: 500;
458
+ color: var(--text-secondary);
459
+ margin-bottom: 6px;
460
+ }
461
+
462
+ textarea, input[type="text"] {
463
+ width: 100%;
464
+ padding: 10px 14px;
465
+ background: var(--bg);
466
+ border: 1px solid var(--border);
467
+ border-radius: var(--radius);
468
+ color: var(--text);
469
+ font-family: var(--font);
470
+ font-size: 0.85rem;
471
+ line-height: 1.6;
472
+ resize: vertical;
473
+ transition: border-color var(--transition);
474
+ }
475
+
476
+ textarea:focus, input[type="text"]:focus {
477
+ outline: none;
478
+ border-color: var(--accent);
479
+ box-shadow: 0 0 0 3px var(--accent-glow);
480
+ }
481
+
482
+ textarea { min-height: unset; position: relative; }
483
+
484
+ /* ── Prompt Input + Mirror (color-only highlight, no text replacement) ── */
485
+ #promptInput {
486
+ color: transparent;
487
+ caret-color: var(--text);
488
+ padding-right: 44px;
489
+ }
490
+
491
+ #promptInput::selection {
492
+ background: rgba(108, 140, 255, 0.3);
493
+ color: transparent;
494
+ }
495
+
496
+ .prompt-mirror {
497
+ position: absolute;
498
+ top: 0;
499
+ left: 0;
500
+ right: 0;
501
+ bottom: 0;
502
+ padding: 10px 14px;
503
+ padding-right: 44px;
504
+ font-family: var(--font);
505
+ font-size: 0.85rem;
506
+ line-height: 1.6;
507
+ color: var(--text);
508
+ white-space: pre-wrap;
509
+ word-wrap: break-word;
510
+ overflow: hidden;
511
+ pointer-events: none;
512
+ }
513
+
514
+ .prompt-at-ref {
515
+ color: var(--green);
516
+ font-weight: 500;
517
+ }
518
+
519
+ /* ── Image Attachments ── */
520
+ .prompt-wrapper {
521
+ position: relative;
522
+ }
523
+
524
+ .prompt-wrapper.drag-over textarea {
525
+ border-color: transparent;
526
+ box-shadow: none;
527
+ }
528
+
529
+ .drop-overlay {
530
+ display: none;
531
+ position: absolute;
532
+ inset: 0;
533
+ background: rgba(108, 140, 255, 0.08);
534
+ border: 2px dashed var(--accent);
535
+ border-radius: var(--radius);
536
+ z-index: 10;
537
+ pointer-events: none;
538
+ align-items: center;
539
+ justify-content: center;
540
+ font-size: 0.85rem;
541
+ font-weight: 600;
542
+ color: var(--accent);
543
+ gap: 8px;
544
+ }
545
+
546
+ .prompt-wrapper.drag-over .drop-overlay {
547
+ display: flex;
548
+ box-shadow: 0 0 0 3px var(--accent-glow);
549
+ }
550
+
551
+ .image-previews {
552
+ display: flex;
553
+ flex-wrap: wrap;
554
+ gap: 8px;
555
+ margin-top: 8px;
556
+ }
557
+
558
+ .image-previews:empty { display: none; }
559
+
560
+ .img-thumb {
561
+ position: relative;
562
+ width: 72px;
563
+ height: 72px;
564
+ border-radius: 6px;
565
+ border: 1px solid var(--border);
566
+ overflow: hidden;
567
+ background: var(--bg);
568
+ flex-shrink: 0;
569
+ animation: fadeIn 0.2s ease;
570
+ }
571
+
572
+ .img-thumb img {
573
+ width: 100%;
574
+ height: 100%;
575
+ object-fit: cover;
576
+ cursor: pointer;
577
+ }
578
+
579
+ .img-thumb .img-remove {
580
+ position: absolute;
581
+ top: 2px;
582
+ right: 2px;
583
+ width: 18px;
584
+ height: 18px;
585
+ border-radius: 50%;
586
+ background: rgba(0,0,0,0.7);
587
+ color: #fff;
588
+ font-size: 11px;
589
+ display: flex;
590
+ align-items: center;
591
+ justify-content: center;
592
+ cursor: pointer;
593
+ opacity: 0;
594
+ transition: opacity 0.15s;
595
+ border: none;
596
+ padding: 0;
597
+ line-height: 1;
598
+ }
599
+
600
+ .img-thumb:hover .img-remove {
601
+ opacity: 1;
602
+ }
603
+
604
+ .img-thumb.uploading {
605
+ opacity: 0.5;
606
+ }
607
+
608
+ .img-thumb.uploading::after {
609
+ content: '';
610
+ position: absolute;
611
+ inset: 0;
612
+ display: flex;
613
+ align-items: center;
614
+ justify-content: center;
615
+ background: rgba(0,0,0,0.3);
616
+ }
617
+
618
+ .img-count-badge {
619
+ display: inline-flex;
620
+ align-items: center;
621
+ gap: 4px;
622
+ padding: 2px 8px;
623
+ border-radius: 12px;
624
+ font-size: 0.7rem;
625
+ font-weight: 600;
626
+ background: var(--accent-glow);
627
+ color: var(--accent);
628
+ margin-left: 8px;
629
+ }
630
+
631
+ .img-count-badge:empty { display: none; }
632
+
633
+ /* ── File Attachments (non-image) ── */
634
+ .file-thumb {
635
+ position: relative;
636
+ display: inline-flex;
637
+ align-items: center;
638
+ gap: 6px;
639
+ padding: 6px 10px 6px 8px;
640
+ border-radius: 6px;
641
+ border: 1px solid var(--border);
642
+ background: var(--surface);
643
+ max-width: 200px;
644
+ animation: fadeIn 0.2s ease;
645
+ flex-shrink: 0;
646
+ }
647
+ .file-thumb .file-icon {
648
+ width: 28px;
649
+ height: 28px;
650
+ display: flex;
651
+ align-items: center;
652
+ justify-content: center;
653
+ border-radius: 4px;
654
+ background: var(--surface-active);
655
+ color: var(--text-muted);
656
+ flex-shrink: 0;
657
+ font-size: 0.6rem;
658
+ font-weight: 700;
659
+ font-family: var(--font-mono);
660
+ text-transform: uppercase;
661
+ letter-spacing: -0.02em;
662
+ }
663
+ .file-thumb .file-info {
664
+ display: flex;
665
+ flex-direction: column;
666
+ gap: 1px;
667
+ overflow: hidden;
668
+ min-width: 0;
669
+ }
670
+ .file-thumb .file-name {
671
+ font-size: 0.75rem;
672
+ font-weight: 500;
673
+ color: var(--text);
674
+ white-space: nowrap;
675
+ overflow: hidden;
676
+ text-overflow: ellipsis;
677
+ }
678
+ .file-thumb .file-size {
679
+ font-size: 0.65rem;
680
+ color: var(--text-muted);
681
+ }
682
+ .file-thumb .file-remove {
683
+ position: absolute;
684
+ top: -4px;
685
+ right: -4px;
686
+ width: 16px;
687
+ height: 16px;
688
+ border-radius: 50%;
689
+ background: rgba(0,0,0,0.7);
690
+ color: #fff;
691
+ font-size: 10px;
692
+ display: flex;
693
+ align-items: center;
694
+ justify-content: center;
695
+ cursor: pointer;
696
+ opacity: 0;
697
+ transition: opacity 0.15s;
698
+ border: none;
699
+ padding: 0;
700
+ line-height: 1;
701
+ }
702
+ .file-thumb:hover .file-remove { opacity: 1; }
703
+ .file-thumb.uploading { opacity: 0.5; }
704
+
705
+ /* ── Attach Button (inside prompt-wrapper) ── */
706
+ .attach-float-btn {
707
+ position: absolute;
708
+ bottom: 12px;
709
+ right: 10px;
710
+ width: 28px;
711
+ height: 28px;
712
+ border-radius: 6px;
713
+ background: var(--surface-hover);
714
+ border: 1px solid var(--border);
715
+ color: var(--text-muted);
716
+ display: flex;
717
+ align-items: center;
718
+ justify-content: center;
719
+ cursor: pointer;
720
+ transition: all var(--transition);
721
+ z-index: 5;
722
+ }
723
+ .attach-float-btn:hover {
724
+ background: var(--surface-active);
725
+ color: var(--accent);
726
+ border-color: var(--accent);
727
+ }
728
+
729
+ textarea::placeholder, input::placeholder {
730
+ color: var(--text-muted);
731
+ }
732
+
733
+ .form-actions {
734
+ display: flex;
735
+ align-items: center;
736
+ gap: 8px;
737
+ }
738
+ .automation-inline {
739
+ display: flex;
740
+ align-items: center;
741
+ gap: 6px;
742
+ padding: 4px 10px;
743
+ background: var(--bg-secondary);
744
+ border-radius: 6px;
745
+ border: 1px solid color-mix(in srgb, var(--primary) 20%, transparent);
746
+ flex-shrink: 0;
747
+ }
748
+ .automation-inline-label {
749
+ font-size: 0.72rem;
750
+ color: var(--primary);
751
+ font-weight: 500;
752
+ white-space: nowrap;
753
+ }
754
+ .automation-inline-hint {
755
+ font-size: 0.62rem;
756
+ color: var(--text-muted);
757
+ white-space: nowrap;
758
+ }
759
+ .form-actions-buttons {
760
+ display: flex;
761
+ gap: 8px;
762
+ margin-left: auto;
763
+ }