slides-grab 1.0.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 (51) hide show
  1. package/AGENTS.md +80 -0
  2. package/LICENSE +21 -0
  3. package/PROGRESS.md +39 -0
  4. package/README.md +120 -0
  5. package/SETUP.md +51 -0
  6. package/bin/ppt-agent.js +204 -0
  7. package/convert.cjs +184 -0
  8. package/package.json +51 -0
  9. package/prd.json +135 -0
  10. package/prd.md +104 -0
  11. package/scripts/editor-server.js +779 -0
  12. package/scripts/html2pdf.js +217 -0
  13. package/scripts/validate-slides.js +416 -0
  14. package/skills/ppt-design-skill/SKILL.md +38 -0
  15. package/skills/ppt-plan-skill/SKILL.md +37 -0
  16. package/skills/ppt-pptx-skill/SKILL.md +37 -0
  17. package/skills/ppt-presentation-skill/SKILL.md +57 -0
  18. package/src/editor/codex-edit.js +213 -0
  19. package/src/editor/editor.html +1733 -0
  20. package/src/editor/js/editor-bbox.js +332 -0
  21. package/src/editor/js/editor-chat.js +56 -0
  22. package/src/editor/js/editor-direct-edit.js +110 -0
  23. package/src/editor/js/editor-dom.js +55 -0
  24. package/src/editor/js/editor-init.js +284 -0
  25. package/src/editor/js/editor-navigation.js +54 -0
  26. package/src/editor/js/editor-select.js +264 -0
  27. package/src/editor/js/editor-send.js +157 -0
  28. package/src/editor/js/editor-sse.js +163 -0
  29. package/src/editor/js/editor-state.js +32 -0
  30. package/src/editor/js/editor-utils.js +167 -0
  31. package/src/editor/screenshot.js +73 -0
  32. package/src/resolve.js +159 -0
  33. package/templates/chart.html +121 -0
  34. package/templates/closing.html +54 -0
  35. package/templates/content.html +50 -0
  36. package/templates/contents.html +60 -0
  37. package/templates/cover.html +64 -0
  38. package/templates/custom/.gitkeep +0 -0
  39. package/templates/custom/README.md +7 -0
  40. package/templates/diagram.html +98 -0
  41. package/templates/quote.html +31 -0
  42. package/templates/section-divider.html +43 -0
  43. package/templates/split-layout.html +41 -0
  44. package/templates/statistics.html +55 -0
  45. package/templates/team.html +49 -0
  46. package/templates/timeline.html +59 -0
  47. package/themes/corporate.css +8 -0
  48. package/themes/executive.css +10 -0
  49. package/themes/modern-dark.css +9 -0
  50. package/themes/sage.css +9 -0
  51. package/themes/warm.css +8 -0
@@ -0,0 +1,1733 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Slide Editor - ppt-agent</title>
7
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/static/pretendard.min.css">
8
+ <style>
9
+ :root {
10
+ --bg-0: #030711;
11
+ --bg-1: #0a0f1a;
12
+ --panel: #0f172a;
13
+ --panel-2: #020617;
14
+ --border: #1e293b;
15
+ --border-soft: #172033;
16
+ --text-0: #f8fafc;
17
+ --text-1: #94a3b8;
18
+ --text-2: #64748b;
19
+ --accent: #3b82f6;
20
+ --accent-2: #60a5fa;
21
+ --danger: #ef4444;
22
+ --success: #22c55e;
23
+ --warn: #f59e0b;
24
+ --mono: 'Pretendard', -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;
25
+ --sans: 'Pretendard', -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;
26
+ --ring: hsla(213, 27%, 84%, 0.15);
27
+ --radius: 8px;
28
+ --radius-sm: 6px;
29
+ --radius-lg: 12px;
30
+ --shadow-card: 0 1px 2px rgba(0,0,0,0.3), 0 4px 8px rgba(0,0,0,0.2);
31
+ --transition: 150ms ease-out;
32
+ }
33
+
34
+ * { margin: 0; padding: 0; box-sizing: border-box; }
35
+
36
+ html, body {
37
+ width: 100%;
38
+ height: 100%;
39
+ overflow: hidden;
40
+ background: var(--bg-0);
41
+ font-family: var(--sans);
42
+ color: var(--text-0);
43
+ letter-spacing: 0.01em;
44
+ }
45
+
46
+ .editor-container {
47
+ width: 100%;
48
+ height: 100%;
49
+ display: flex;
50
+ flex-direction: column;
51
+ }
52
+
53
+ .nav-bar {
54
+ height: 44px;
55
+ background: #08090b;
56
+ border-bottom: 1px solid #171a20;
57
+ display: flex;
58
+ align-items: center;
59
+ padding: 0 14px;
60
+ flex-shrink: 0;
61
+ z-index: 100;
62
+ gap: 12px;
63
+ }
64
+
65
+ .nav-controls {
66
+ display: flex;
67
+ align-items: center;
68
+ gap: 8px;
69
+ }
70
+
71
+ .nav-bar button {
72
+ height: 30px;
73
+ background: #111318;
74
+ color: var(--text-0);
75
+ border: 1px solid #1b2028;
76
+ border-radius: 999px;
77
+ padding: 0 12px;
78
+ font-size: 12px;
79
+ font-family: inherit;
80
+ cursor: pointer;
81
+ transition: all var(--transition);
82
+ }
83
+
84
+ .nav-bar button:hover { background: #171b22; border-color: #252b35; }
85
+ .nav-bar button:disabled { opacity: 0.3; cursor: default; }
86
+ .nav-bar button:disabled:hover { background: #111318; border-color: #1b2028; }
87
+
88
+ .slide-counter {
89
+ color: var(--text-1);
90
+ font-size: 12px;
91
+ font-weight: 600;
92
+ min-width: 84px;
93
+ text-align: center;
94
+ font-family: var(--mono);
95
+ }
96
+
97
+ .nav-spacer { flex: 1; }
98
+
99
+ .slide-status-chip {
100
+ margin-right: 12px;
101
+ font-size: 10px;
102
+ font-weight: 700;
103
+ letter-spacing: 0.3px;
104
+ padding: 4px 8px;
105
+ border-radius: 999px;
106
+ border: 1px solid transparent;
107
+ text-transform: uppercase;
108
+ }
109
+
110
+ .slide-status-chip.idle {
111
+ color: var(--text-2);
112
+ background: var(--panel);
113
+ border-color: var(--border);
114
+ }
115
+
116
+ .slide-status-chip.running {
117
+ color: #fbbf24;
118
+ background: hsl(40 80% 12%);
119
+ border-color: hsl(40 50% 22%);
120
+ }
121
+
122
+ .slide-status-chip.success {
123
+ color: #4ade80;
124
+ background: hsl(150 40% 10%);
125
+ border-color: hsl(150 35% 18%);
126
+ }
127
+
128
+ .slide-status-chip.failed {
129
+ color: #f87171;
130
+ background: hsl(0 50% 12%);
131
+ border-color: hsl(0 40% 20%);
132
+ }
133
+
134
+ .brand {
135
+ color: var(--text-2);
136
+ font-size: 12px;
137
+ font-weight: 600;
138
+ letter-spacing: 0.08em;
139
+ font-family: var(--mono);
140
+ }
141
+
142
+ .main-content {
143
+ flex: 1;
144
+ display: flex;
145
+ overflow: hidden;
146
+ min-height: 0;
147
+ }
148
+
149
+ .slide-panel {
150
+ flex: 1;
151
+ display: flex;
152
+ min-width: 0;
153
+ overflow: hidden;
154
+ padding: 24px 28px;
155
+ background: #050607;
156
+ }
157
+
158
+ .slide-toolbox {
159
+ width: min(100%, 1180px);
160
+ display: flex;
161
+ flex-direction: column;
162
+ gap: 10px;
163
+ padding: 14px 16px 12px;
164
+ border: 1px solid var(--border);
165
+ border-radius: var(--radius-lg);
166
+ background: var(--panel-2);
167
+ box-shadow: var(--shadow-card);
168
+ position: relative;
169
+ z-index: 20;
170
+ align-self: center;
171
+ flex: 0 0 auto;
172
+ overflow: visible;
173
+ }
174
+
175
+ .slide-stage {
176
+ flex: 1;
177
+ min-height: 0;
178
+ display: flex;
179
+ align-items: center;
180
+ justify-content: center;
181
+ overflow: hidden;
182
+ position: relative;
183
+ padding: 28px;
184
+ max-width: 100%;
185
+ max-height: 100%;
186
+ }
187
+
188
+ .tool-mode-group,
189
+ .direct-edit-group,
190
+ .direct-toggle-group,
191
+ .direct-align-group {
192
+ display: inline-flex;
193
+ align-items: center;
194
+ gap: 6px;
195
+ }
196
+
197
+ .tool-separator {
198
+ width: 1px;
199
+ height: 34px;
200
+ flex: 0 0 auto;
201
+ background: linear-gradient(180deg, rgba(58, 72, 90, 0.1) 0%, rgba(58, 72, 90, 0.8) 48%, rgba(58, 72, 90, 0.1) 100%);
202
+ }
203
+
204
+ .toolbar-section {
205
+ min-width: 0;
206
+ flex: 1;
207
+ display: flex;
208
+ align-items: center;
209
+ gap: 10px;
210
+ }
211
+
212
+ .toolbar-section[hidden] {
213
+ display: none !important;
214
+ }
215
+
216
+ .tool-strip {
217
+ width: 100%;
218
+ display: flex;
219
+ align-items: center;
220
+ gap: 12px;
221
+ min-width: 0;
222
+ min-height: 46px;
223
+ }
224
+
225
+ .bbox-toolbar,
226
+ .select-toolbar {
227
+ display: flex;
228
+ align-items: center;
229
+ gap: 10px;
230
+ min-width: 0;
231
+ flex: 1;
232
+ }
233
+
234
+ .bbox-toolbar {
235
+ justify-content: flex-start;
236
+ }
237
+
238
+ .bbox-toolbar[hidden],
239
+ .select-toolbar[hidden] {
240
+ display: none !important;
241
+ }
242
+
243
+ .select-toolbar {
244
+ justify-content: flex-start;
245
+ flex-wrap: nowrap;
246
+ overflow-x: auto;
247
+ padding-bottom: 2px;
248
+ }
249
+
250
+ .toolbar-divider {
251
+ width: 1px;
252
+ height: 34px;
253
+ flex: 0 0 auto;
254
+ background: linear-gradient(180deg, rgba(58, 72, 90, 0.1) 0%, rgba(58, 72, 90, 0.8) 48%, rgba(58, 72, 90, 0.1) 100%);
255
+ }
256
+
257
+ .tool-mode-btn {
258
+ border: 1px solid var(--border);
259
+ background: var(--panel);
260
+ color: var(--text-0);
261
+ border-radius: var(--radius-lg);
262
+ height: 46px;
263
+ padding: 0 16px;
264
+ font-size: 12px;
265
+ font-family: var(--mono);
266
+ font-weight: 700;
267
+ cursor: pointer;
268
+ transition: all var(--transition);
269
+ flex: 0 0 auto;
270
+ display: inline-flex;
271
+ align-items: center;
272
+ gap: 10px;
273
+ white-space: nowrap;
274
+ }
275
+
276
+ .tool-mode-btn:hover {
277
+ background: var(--border);
278
+ }
279
+
280
+ .tool-mode-btn.active {
281
+ border-color: var(--accent);
282
+ background: hsl(217 91% 60% / 0.12);
283
+ color: var(--text-0);
284
+ }
285
+
286
+ .tool-icon-btn {
287
+ position: relative;
288
+ border: 1px solid var(--border);
289
+ background: var(--panel-2);
290
+ color: var(--text-0);
291
+ border-radius: var(--radius-lg);
292
+ min-width: 46px;
293
+ height: 46px;
294
+ padding: 0 12px;
295
+ font-size: 14px;
296
+ font-family: var(--mono);
297
+ font-weight: 700;
298
+ cursor: pointer;
299
+ transition: all var(--transition);
300
+ flex: 0 0 auto;
301
+ display: inline-flex;
302
+ align-items: center;
303
+ justify-content: center;
304
+ }
305
+
306
+ .tool-icon-btn:hover {
307
+ background: var(--panel);
308
+ }
309
+
310
+ .tool-icon-btn.active {
311
+ border-color: var(--accent);
312
+ background: hsl(217 91% 60% / 0.12);
313
+ color: var(--text-0);
314
+ }
315
+
316
+ .tool-icon-btn:disabled {
317
+ opacity: 0.42;
318
+ cursor: default;
319
+ color: var(--text-2);
320
+ background: var(--panel-2);
321
+ }
322
+
323
+ .tool-icon-btn:disabled:hover {
324
+ background: var(--panel-2);
325
+ }
326
+
327
+ .tool-icon-btn.tight {
328
+ min-width: 42px;
329
+ width: 42px;
330
+ padding: 0;
331
+ }
332
+
333
+ .tool-icon {
334
+ width: 16px;
335
+ height: 16px;
336
+ display: block;
337
+ stroke: currentColor;
338
+ stroke-width: 1.8;
339
+ fill: none;
340
+ stroke-linecap: round;
341
+ stroke-linejoin: round;
342
+ flex: 0 0 auto;
343
+ }
344
+
345
+ .tool-mode-btn .tool-icon {
346
+ width: 15px;
347
+ height: 15px;
348
+ }
349
+
350
+ .selected-object-chip {
351
+ min-height: 32px;
352
+ display: inline-flex;
353
+ align-items: center;
354
+ border-radius: 999px;
355
+ border: 1px solid var(--border);
356
+ background: var(--panel);
357
+ color: var(--text-0);
358
+ padding: 0 10px;
359
+ font-size: 11px;
360
+ font-family: var(--mono);
361
+ max-width: 260px;
362
+ overflow: hidden;
363
+ text-overflow: ellipsis;
364
+ white-space: nowrap;
365
+ }
366
+
367
+ .selected-object-chip.empty {
368
+ color: var(--text-2);
369
+ border-color: var(--border-soft);
370
+ background: var(--panel-2);
371
+ }
372
+
373
+ .direct-edit-controls {
374
+ display: flex;
375
+ align-items: center;
376
+ gap: 8px;
377
+ flex-wrap: wrap;
378
+ flex: 1;
379
+ min-width: 0;
380
+ }
381
+
382
+ .direct-edit-controls[hidden] {
383
+ display: none !important;
384
+ }
385
+
386
+ .direct-edit-label {
387
+ color: var(--text-2);
388
+ font-size: 11px;
389
+ font-family: var(--mono);
390
+ text-transform: uppercase;
391
+ letter-spacing: 0.04em;
392
+ }
393
+
394
+ .direct-input,
395
+ .direct-number {
396
+ height: 32px;
397
+ border-radius: var(--radius);
398
+ border: 1px solid var(--border);
399
+ background: var(--panel-2);
400
+ color: var(--text-0);
401
+ font-size: 12px;
402
+ font-family: var(--sans);
403
+ padding: 0 10px;
404
+ outline: none;
405
+ }
406
+
407
+ .direct-input:focus,
408
+ .direct-number:focus {
409
+ border-color: var(--accent);
410
+ box-shadow: 0 0 0 3px var(--ring);
411
+ }
412
+
413
+ .direct-text-input {
414
+ width: 180px;
415
+ }
416
+
417
+ .direct-number {
418
+ width: 74px;
419
+ font-family: var(--mono);
420
+ }
421
+
422
+ .direct-color {
423
+ width: 32px;
424
+ height: 32px;
425
+ border-radius: var(--radius);
426
+ border: 1px solid var(--border);
427
+ background: var(--panel);
428
+ cursor: pointer;
429
+ padding: 2px;
430
+ }
431
+
432
+ .style-toggle,
433
+ .align-btn {
434
+ min-width: 32px;
435
+ height: 32px;
436
+ padding: 0 10px;
437
+ font-weight: 700;
438
+ font-family: var(--mono);
439
+ }
440
+
441
+ .style-toggle.active,
442
+ .align-btn.active {
443
+ border-color: var(--accent);
444
+ background: hsl(217 91% 60% / 0.12);
445
+ color: var(--text-0);
446
+ }
447
+
448
+ .slide-wrapper {
449
+ position: relative;
450
+ width: 960px;
451
+ height: 540px;
452
+ transform-origin: top center;
453
+ z-index: 1;
454
+ }
455
+
456
+ .slide-wrapper iframe {
457
+ width: 960px;
458
+ height: 540px;
459
+ border: none;
460
+ border-radius: 0;
461
+ background: #fff;
462
+ display: block;
463
+ position: relative;
464
+ z-index: 1;
465
+ }
466
+
467
+ .bbox-layer {
468
+ position: absolute;
469
+ inset: 0;
470
+ z-index: 9;
471
+ pointer-events: none;
472
+ }
473
+
474
+ .bbox-layer.inert .bbox-item {
475
+ pointer-events: none;
476
+ opacity: 0.26;
477
+ }
478
+
479
+ .object-layer {
480
+ position: absolute;
481
+ inset: 0;
482
+ z-index: 10;
483
+ pointer-events: none;
484
+ }
485
+
486
+ .object-outline {
487
+ position: absolute;
488
+ display: none;
489
+ border-radius: 6px;
490
+ pointer-events: none;
491
+ }
492
+
493
+ .object-outline.hover {
494
+ border: 1.5px dashed rgba(96, 165, 250, 0.72);
495
+ background: rgba(96, 165, 250, 0.06);
496
+ }
497
+
498
+ .object-outline.selected {
499
+ border: 1.5px solid rgba(96, 165, 250, 0.92);
500
+ background: rgba(96, 165, 250, 0.08);
501
+ box-shadow: 0 0 0 3px rgba(96, 165, 250, 0.14);
502
+ }
503
+
504
+ .draw-layer {
505
+ position: absolute;
506
+ inset: 0;
507
+ z-index: 8;
508
+ pointer-events: auto;
509
+ cursor: crosshair;
510
+ }
511
+
512
+ .mode-select .draw-layer {
513
+ cursor: pointer;
514
+ }
515
+
516
+ .draw-box {
517
+ position: absolute;
518
+ border: 2px dashed #ef4444;
519
+ background: rgba(239, 68, 68, 0.1);
520
+ display: none;
521
+ pointer-events: none;
522
+ }
523
+
524
+ .bbox-item {
525
+ position: absolute;
526
+ border: 1.5px solid rgba(239, 68, 68, 0.78);
527
+ background: rgba(239, 68, 68, 0.08);
528
+ pointer-events: auto;
529
+ cursor: pointer;
530
+ transition: border-color 0.12s ease, box-shadow 0.12s ease;
531
+ }
532
+
533
+ .bbox-item.pending:hover {
534
+ border-color: #dc2626;
535
+ }
536
+
537
+ .bbox-item.review {
538
+ border-color: rgba(34, 197, 94, 0.82);
539
+ background: rgba(34, 197, 94, 0.1);
540
+ }
541
+
542
+ .bbox-item.review:hover {
543
+ border-color: #16a34a;
544
+ }
545
+
546
+ .bbox-item.selected {
547
+ box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.12);
548
+ }
549
+
550
+ .bbox-index {
551
+ position: absolute;
552
+ top: -12px;
553
+ left: 0;
554
+ min-width: 20px;
555
+ height: 18px;
556
+ padding: 0 6px;
557
+ border-radius: 999px;
558
+ background: rgba(127, 29, 29, 0.96);
559
+ color: #fff;
560
+ font-size: 10px;
561
+ line-height: 18px;
562
+ text-align: center;
563
+ font-weight: 600;
564
+ }
565
+
566
+ .bbox-item.review .bbox-index {
567
+ background: rgba(21, 101, 52, 0.96);
568
+ }
569
+
570
+ .bbox-actions {
571
+ display: none;
572
+ position: absolute;
573
+ top: -30px;
574
+ right: -2px;
575
+ align-items: center;
576
+ gap: 6px;
577
+ }
578
+
579
+ .bbox-item.selected .bbox-actions {
580
+ display: inline-flex;
581
+ }
582
+
583
+ .bbox-action-btn {
584
+ border-radius: 999px;
585
+ border: 1px solid transparent;
586
+ height: 22px;
587
+ padding: 0 8px;
588
+ color: #fff;
589
+ font-size: 10px;
590
+ line-height: 20px;
591
+ font-weight: 600;
592
+ cursor: pointer;
593
+ white-space: nowrap;
594
+ }
595
+
596
+ .bbox-delete {
597
+ border-radius: 999px;
598
+ border: 1px solid #7f1d1d;
599
+ background: #ef4444;
600
+ color: #fff;
601
+ font-size: 13px;
602
+ font-weight: 700;
603
+ width: 24px;
604
+ padding: 0;
605
+ line-height: 22px;
606
+ }
607
+
608
+ .bbox-check {
609
+ border-color: #14532d;
610
+ background: #16a34a;
611
+ }
612
+
613
+ .bbox-rerun {
614
+ border-color: #78350f;
615
+ background: #f59e0b;
616
+ color: #111827;
617
+ }
618
+
619
+ .bbox-item.pending .bbox-check,
620
+ .bbox-item.pending .bbox-rerun {
621
+ display: none;
622
+ }
623
+
624
+ .bbox-item.review .bbox-delete {
625
+ display: none;
626
+ }
627
+
628
+ .bbox-item.pending.selected .bbox-delete {
629
+ display: block;
630
+ }
631
+
632
+ .clear-overlay-btn {
633
+ position: absolute;
634
+ top: 10px;
635
+ right: 10px;
636
+ z-index: 12;
637
+ border: 1px solid var(--border);
638
+ background: hsla(215, 28%, 8%, 0.88);
639
+ color: var(--text-0);
640
+ border-radius: var(--radius-sm);
641
+ padding: 6px 10px;
642
+ font-size: 12px;
643
+ font-family: var(--mono);
644
+ cursor: pointer;
645
+ transition: all var(--transition);
646
+ }
647
+
648
+ .clear-overlay-btn:hover {
649
+ background: hsla(215, 28%, 14%, 0.95);
650
+ }
651
+
652
+ .clear-overlay-btn:disabled {
653
+ opacity: 0.35;
654
+ cursor: default;
655
+ }
656
+
657
+ .clear-overlay-btn:disabled:hover {
658
+ background: hsla(215, 28%, 8%, 0.88);
659
+ }
660
+
661
+ .sidebar {
662
+ width: 430px;
663
+ min-width: 340px;
664
+ border-left: 1px solid var(--border);
665
+ background: var(--bg-1);
666
+ display: flex;
667
+ flex-direction: column;
668
+ min-height: 0;
669
+ }
670
+
671
+ .chat-section {
672
+ flex: 1;
673
+ min-height: 0;
674
+ display: flex;
675
+ flex-direction: column;
676
+ }
677
+
678
+ .chat-header {
679
+ height: 42px;
680
+ display: flex;
681
+ align-items: center;
682
+ justify-content: space-between;
683
+ padding: 0 12px;
684
+ border-bottom: 1px solid var(--border);
685
+ background: var(--panel-2);
686
+ }
687
+
688
+ .header-tabs {
689
+ display: inline-flex;
690
+ align-items: center;
691
+ gap: 14px;
692
+ font-family: var(--mono);
693
+ font-size: 12px;
694
+ font-weight: 700;
695
+ letter-spacing: 0.04em;
696
+ }
697
+
698
+ .header-tab {
699
+ color: var(--text-2);
700
+ position: relative;
701
+ padding: 2px 0;
702
+ }
703
+
704
+ .header-tab.active {
705
+ color: var(--text-0);
706
+ }
707
+
708
+ .header-tab.active::after {
709
+ content: '';
710
+ position: absolute;
711
+ left: 0;
712
+ right: 0;
713
+ bottom: -11px;
714
+ height: 2px;
715
+ border-radius: 2px;
716
+ background: var(--accent);
717
+ }
718
+
719
+ .btn-toggle-logs {
720
+ background: var(--panel);
721
+ color: var(--text-1);
722
+ border: 1px solid var(--border);
723
+ border-radius: var(--radius-sm);
724
+ height: 26px;
725
+ padding: 0 8px;
726
+ font-size: 11px;
727
+ font-family: var(--mono);
728
+ cursor: pointer;
729
+ transition: all var(--transition);
730
+ }
731
+
732
+ .btn-toggle-logs:hover {
733
+ background: var(--border);
734
+ }
735
+
736
+ .btn-toggle-logs.active {
737
+ border-color: var(--accent);
738
+ color: var(--text-0);
739
+ background: hsl(217 91% 60% / 0.12);
740
+ }
741
+
742
+ .session-strip {
743
+ border-bottom: 1px solid var(--border-soft);
744
+ padding: 8px 10px;
745
+ display: flex;
746
+ align-items: center;
747
+ gap: 6px;
748
+ min-height: 38px;
749
+ background: var(--bg-1);
750
+ overflow-x: auto;
751
+ }
752
+
753
+ .session-file-chip {
754
+ flex: 0 0 auto;
755
+ display: inline-flex;
756
+ align-items: center;
757
+ height: 22px;
758
+ border-radius: var(--radius-sm);
759
+ border: 1px solid var(--border);
760
+ background: var(--panel);
761
+ color: var(--text-0);
762
+ padding: 0 8px;
763
+ font-size: 11px;
764
+ font-family: var(--mono);
765
+ max-width: 190px;
766
+ white-space: nowrap;
767
+ overflow: hidden;
768
+ text-overflow: ellipsis;
769
+ }
770
+
771
+ .chat-messages {
772
+ flex: 1;
773
+ min-height: 0;
774
+ overflow-y: auto;
775
+ padding: 12px 10px;
776
+ display: flex;
777
+ flex-direction: column;
778
+ gap: 10px;
779
+ background: var(--panel-2);
780
+ }
781
+
782
+ .chat-messages:empty::before {
783
+ content: 'Prompt history appears here.';
784
+ color: var(--text-2);
785
+ font-size: 12px;
786
+ font-style: italic;
787
+ }
788
+
789
+ .message {
790
+ border: 1px solid var(--border);
791
+ border-radius: var(--radius);
792
+ padding: 10px;
793
+ font-size: 12px;
794
+ line-height: 1.5;
795
+ color: var(--text-0);
796
+ white-space: pre-wrap;
797
+ background: var(--panel);
798
+ }
799
+
800
+ .message.user {
801
+ border-color: hsl(217 50% 28%);
802
+ background: hsl(217 55% 14%);
803
+ }
804
+
805
+ .message.system {
806
+ border-color: hsl(150 30% 22%);
807
+ background: hsl(150 30% 10%);
808
+ }
809
+
810
+ .message.error {
811
+ border-color: hsl(0 40% 22%);
812
+ background: hsl(0 40% 12%);
813
+ }
814
+
815
+ .composer {
816
+ border-top: 1px solid var(--border);
817
+ padding: 10px 10px 12px;
818
+ display: flex;
819
+ flex-direction: column;
820
+ gap: 8px;
821
+ background: var(--bg-1);
822
+ }
823
+
824
+ .tool-row {
825
+ display: flex;
826
+ align-items: center;
827
+ gap: 10px;
828
+ flex-wrap: nowrap;
829
+ min-height: 28px;
830
+ }
831
+
832
+ .btn {
833
+ border: none;
834
+ border-radius: var(--radius);
835
+ padding: 7px 10px;
836
+ font-size: 12px;
837
+ font-family: var(--sans);
838
+ cursor: pointer;
839
+ transition: all var(--transition);
840
+ display: inline-flex;
841
+ align-items: center;
842
+ justify-content: center;
843
+ gap: 6px;
844
+ }
845
+
846
+ .btn:disabled {
847
+ opacity: 0.35;
848
+ cursor: default;
849
+ }
850
+
851
+ .btn:disabled:hover {
852
+ filter: none;
853
+ }
854
+
855
+ .bbox-count {
856
+ color: var(--text-2);
857
+ font-size: 11px;
858
+ font-weight: 700;
859
+ font-family: var(--mono);
860
+ flex: 0 0 auto;
861
+ min-width: 128px;
862
+ }
863
+
864
+ .prompt-shell {
865
+ flex: 1 1 0;
866
+ min-width: 0;
867
+ display: flex;
868
+ }
869
+
870
+ .context-chips {
871
+ display: flex;
872
+ align-items: center;
873
+ gap: 6px;
874
+ overflow-x: auto;
875
+ padding-bottom: 1px;
876
+ flex: 1;
877
+ min-width: 0;
878
+ }
879
+
880
+ .context-chip {
881
+ flex: 0 0 auto;
882
+ display: inline-flex;
883
+ align-items: center;
884
+ gap: 4px;
885
+ height: 22px;
886
+ border-radius: var(--radius-sm);
887
+ border: 1px solid var(--border);
888
+ background: var(--panel);
889
+ color: var(--text-0);
890
+ padding: 0 8px;
891
+ font-size: 11px;
892
+ font-family: var(--mono);
893
+ cursor: pointer;
894
+ max-width: 100px;
895
+ overflow: hidden;
896
+ text-overflow: ellipsis;
897
+ white-space: nowrap;
898
+ }
899
+
900
+ .context-chip.file {
901
+ border-color: var(--border);
902
+ background: var(--panel);
903
+ color: var(--text-0);
904
+ cursor: default;
905
+ }
906
+
907
+ .context-chip.pending {
908
+ border-color: hsl(0 40% 22%);
909
+ background: hsl(0 40% 12%);
910
+ color: #fecaca;
911
+ }
912
+
913
+ .context-chip.review {
914
+ border-color: hsl(150 30% 18%);
915
+ background: hsl(150 30% 10%);
916
+ color: #bbf7d0;
917
+ }
918
+
919
+ .context-chip.selected {
920
+ outline: 1px solid var(--accent-2);
921
+ box-shadow: 0 0 0 1px rgba(96, 165, 250, 0.35);
922
+ }
923
+
924
+ .context-chip-empty {
925
+ color: var(--text-2);
926
+ font-size: 11px;
927
+ font-family: var(--mono);
928
+ }
929
+
930
+ .prompt-input {
931
+ flex: 1;
932
+ width: 100%;
933
+ min-width: 0;
934
+ height: 46px;
935
+ border-radius: var(--radius-lg);
936
+ border: 1px solid var(--border);
937
+ background: var(--panel-2);
938
+ color: var(--text-0);
939
+ font-size: 13px;
940
+ font-family: var(--sans);
941
+ line-height: 1;
942
+ padding: 0 14px;
943
+ outline: none;
944
+ }
945
+
946
+ .prompt-input:focus {
947
+ border-color: var(--accent);
948
+ box-shadow: 0 0 0 3px var(--ring);
949
+ }
950
+
951
+ .prompt-input::placeholder {
952
+ color: var(--text-2);
953
+ }
954
+
955
+ .hint {
956
+ color: var(--text-2);
957
+ font-size: 11px;
958
+ font-family: var(--mono);
959
+ }
960
+
961
+ .model-select {
962
+ min-width: 176px;
963
+ width: 176px;
964
+ height: 46px;
965
+ border-radius: var(--radius-lg);
966
+ border: 1px solid var(--border);
967
+ background: var(--panel);
968
+ color: var(--text-0);
969
+ font-size: 12px;
970
+ font-family: var(--mono);
971
+ padding: 0 8px;
972
+ outline: none;
973
+ }
974
+
975
+ .model-select:focus {
976
+ border-color: var(--accent);
977
+ box-shadow: 0 0 0 3px var(--ring);
978
+ }
979
+
980
+ .btn-send {
981
+ background: var(--accent);
982
+ color: #fff;
983
+ min-width: 46px;
984
+ width: 46px;
985
+ height: 46px;
986
+ padding: 0;
987
+ border: 1px solid var(--accent);
988
+ border-radius: var(--radius-lg);
989
+ }
990
+
991
+ .btn-send:hover { background: var(--accent-2); }
992
+
993
+ .btn-send-icon {
994
+ width: 14px;
995
+ height: 14px;
996
+ display: block;
997
+ fill: currentColor;
998
+ transform: translateX(0.5px);
999
+ }
1000
+
1001
+ .tool-popovers {
1002
+ position: absolute;
1003
+ inset: calc(100% + 10px) 0 auto 0;
1004
+ z-index: 30;
1005
+ pointer-events: none;
1006
+ min-height: 0;
1007
+ }
1008
+
1009
+ .editor-popover {
1010
+ position: absolute;
1011
+ top: 0;
1012
+ width: 248px;
1013
+ padding: 12px;
1014
+ border-radius: var(--radius-lg);
1015
+ border: 1px solid var(--border);
1016
+ background: var(--panel-2);
1017
+ box-shadow: var(--shadow-card);
1018
+ display: flex;
1019
+ align-items: flex-end;
1020
+ gap: 10px;
1021
+ pointer-events: auto;
1022
+ animation: fadeIn var(--transition) forwards;
1023
+ }
1024
+
1025
+ @keyframes fadeIn {
1026
+ from { opacity: 0; transform: scale(0.97); }
1027
+ to { opacity: 1; transform: scale(1); }
1028
+ }
1029
+
1030
+ .editor-popover[hidden] {
1031
+ display: none !important;
1032
+ }
1033
+
1034
+ .popover-field {
1035
+ display: flex;
1036
+ flex-direction: column;
1037
+ gap: 6px;
1038
+ flex: 1;
1039
+ min-width: 0;
1040
+ }
1041
+
1042
+ .popover-label {
1043
+ color: var(--text-0);
1044
+ font-size: 11px;
1045
+ font-weight: 700;
1046
+ font-family: var(--mono);
1047
+ text-transform: uppercase;
1048
+ letter-spacing: 0.08em;
1049
+ }
1050
+
1051
+ .popover-input,
1052
+ .popover-number,
1053
+ .popover-color {
1054
+ width: 100%;
1055
+ border-radius: var(--radius);
1056
+ border: 1px solid var(--border);
1057
+ background: var(--panel);
1058
+ color: var(--text-0);
1059
+ font-size: 13px;
1060
+ font-family: var(--sans);
1061
+ outline: none;
1062
+ }
1063
+
1064
+ .popover-input,
1065
+ .popover-number {
1066
+ height: 42px;
1067
+ padding: 0 12px;
1068
+ }
1069
+
1070
+ .popover-color {
1071
+ height: 44px;
1072
+ padding: 4px;
1073
+ cursor: pointer;
1074
+ }
1075
+
1076
+ .popover-input:focus,
1077
+ .popover-number:focus {
1078
+ border-color: var(--accent);
1079
+ box-shadow: 0 0 0 3px var(--ring);
1080
+ }
1081
+
1082
+ .popover-actions {
1083
+ display: flex;
1084
+ justify-content: flex-end;
1085
+ gap: 8px;
1086
+ }
1087
+
1088
+ .popover-apply-btn {
1089
+ border: 1px solid var(--accent);
1090
+ background: hsl(217 91% 60% / 0.12);
1091
+ color: var(--text-0);
1092
+ border-radius: var(--radius);
1093
+ height: 34px;
1094
+ padding: 0 12px;
1095
+ font-size: 12px;
1096
+ font-family: var(--mono);
1097
+ font-weight: 700;
1098
+ cursor: pointer;
1099
+ transition: all var(--transition);
1100
+ }
1101
+
1102
+ .hint {
1103
+ min-height: 14px;
1104
+ white-space: nowrap;
1105
+ overflow: hidden;
1106
+ text-overflow: ellipsis;
1107
+ }
1108
+
1109
+ .runs-section {
1110
+ border-top: 1px solid var(--border);
1111
+ padding: 10px;
1112
+ background: var(--panel-2);
1113
+ max-height: 36%;
1114
+ min-height: 130px;
1115
+ display: flex;
1116
+ flex-direction: column;
1117
+ gap: 8px;
1118
+ }
1119
+
1120
+ .runs-section.collapsed {
1121
+ display: none;
1122
+ }
1123
+
1124
+ .section-label {
1125
+ color: var(--text-1);
1126
+ font-size: 11px;
1127
+ font-weight: 700;
1128
+ letter-spacing: 0.5px;
1129
+ text-transform: uppercase;
1130
+ font-family: var(--mono);
1131
+ }
1132
+
1133
+ .runs-list {
1134
+ overflow-y: auto;
1135
+ min-height: 0;
1136
+ display: flex;
1137
+ flex-direction: column;
1138
+ gap: 8px;
1139
+ }
1140
+
1141
+ .run-item {
1142
+ border: 1px solid var(--border);
1143
+ border-radius: var(--radius);
1144
+ padding: 8px;
1145
+ background: var(--panel);
1146
+ display: flex;
1147
+ flex-direction: column;
1148
+ gap: 6px;
1149
+ }
1150
+
1151
+ .run-item-head {
1152
+ display: flex;
1153
+ align-items: center;
1154
+ gap: 6px;
1155
+ font-size: 11px;
1156
+ color: var(--text-0);
1157
+ font-family: var(--mono);
1158
+ }
1159
+
1160
+ .run-dot {
1161
+ width: 8px;
1162
+ height: 8px;
1163
+ border-radius: 999px;
1164
+ flex-shrink: 0;
1165
+ }
1166
+
1167
+ .run-dot.running { background: #facc15; }
1168
+ .run-dot.success { background: #22c55e; }
1169
+ .run-dot.failed { background: #ef4444; }
1170
+ .run-dot.idle { background: #6b7280; }
1171
+
1172
+ .run-slide {
1173
+ color: var(--text-0);
1174
+ font-weight: 600;
1175
+ word-break: break-all;
1176
+ }
1177
+
1178
+ .run-meta {
1179
+ color: var(--text-1);
1180
+ font-size: 11px;
1181
+ font-family: var(--mono);
1182
+ }
1183
+
1184
+ .run-actions {
1185
+ display: flex;
1186
+ gap: 6px;
1187
+ align-items: center;
1188
+ justify-content: space-between;
1189
+ }
1190
+
1191
+ .btn-log {
1192
+ background: var(--panel);
1193
+ color: var(--text-1);
1194
+ font-size: 11px;
1195
+ padding: 5px 8px;
1196
+ border: 1px solid var(--border);
1197
+ border-radius: var(--radius-sm);
1198
+ font-family: var(--mono);
1199
+ }
1200
+
1201
+ .btn-log:hover { background: var(--border); }
1202
+
1203
+ .run-log {
1204
+ white-space: pre-wrap;
1205
+ background: var(--panel-2);
1206
+ border: 1px solid var(--border);
1207
+ border-radius: var(--radius-sm);
1208
+ padding: 8px;
1209
+ font-size: 11px;
1210
+ line-height: 1.45;
1211
+ color: var(--text-0);
1212
+ max-height: 180px;
1213
+ overflow: auto;
1214
+ font-family: var(--mono);
1215
+ }
1216
+
1217
+ .status-bar {
1218
+ min-height: 32px;
1219
+ background: #08090b;
1220
+ border-top: 1px solid #15181d;
1221
+ display: flex;
1222
+ align-items: center;
1223
+ padding: 0 14px;
1224
+ font-size: 11px;
1225
+ color: var(--text-2);
1226
+ flex-shrink: 0;
1227
+ gap: 16px;
1228
+ font-family: var(--mono);
1229
+ }
1230
+
1231
+ .status-dot {
1232
+ width: 6px;
1233
+ height: 6px;
1234
+ border-radius: 50%;
1235
+ background: var(--text-2);
1236
+ display: inline-block;
1237
+ margin-right: 6px;
1238
+ }
1239
+
1240
+ .status-dot.connected { background: #22c55e; }
1241
+ .status-dot.disconnected { background: #ef4444; }
1242
+
1243
+ .status-message {
1244
+ flex: 1;
1245
+ text-align: right;
1246
+ color: var(--text-2);
1247
+ overflow: hidden;
1248
+ text-overflow: ellipsis;
1249
+ white-space: nowrap;
1250
+ }
1251
+
1252
+ /* ── Editor sidebar ── */
1253
+ .editor-sidebar {
1254
+ width: 336px;
1255
+ min-width: 336px;
1256
+ border-left: 1px solid #171a20;
1257
+ background: #0a0c0f;
1258
+ display: flex;
1259
+ flex-direction: column;
1260
+ min-height: 0;
1261
+ }
1262
+
1263
+ .sidebar-mode-tabs {
1264
+ display: flex;
1265
+ gap: 4px;
1266
+ margin: 12px 14px 0;
1267
+ padding: 4px;
1268
+ border: 1px solid #1b1f27;
1269
+ border-radius: 14px;
1270
+ background: #0d0f13;
1271
+ flex: 0 0 auto;
1272
+ }
1273
+
1274
+ .sidebar-mode-tab {
1275
+ flex: 1;
1276
+ height: 34px;
1277
+ border: 1px solid transparent;
1278
+ background: transparent;
1279
+ color: #8c93a0;
1280
+ border-radius: 10px;
1281
+ font-size: 12px;
1282
+ font-family: var(--sans);
1283
+ font-weight: 600;
1284
+ cursor: pointer;
1285
+ transition: all var(--transition);
1286
+ display: inline-flex;
1287
+ align-items: center;
1288
+ justify-content: center;
1289
+ gap: 8px;
1290
+ }
1291
+
1292
+ .sidebar-mode-tab .tool-icon {
1293
+ width: 14px;
1294
+ height: 14px;
1295
+ }
1296
+
1297
+ .sidebar-mode-tab:hover { background: #141821; color: var(--text-0); }
1298
+
1299
+ .sidebar-mode-tab.active {
1300
+ border-color: rgba(96, 165, 250, 0.28);
1301
+ background: rgba(59, 130, 246, 0.12);
1302
+ color: #f5f7fb;
1303
+ }
1304
+
1305
+ .sidebar-body {
1306
+ flex: 1;
1307
+ overflow-y: auto;
1308
+ padding: 16px 14px;
1309
+ min-height: 0;
1310
+ }
1311
+
1312
+ .sidebar-panel {
1313
+ display: flex;
1314
+ flex-direction: column;
1315
+ gap: 18px;
1316
+ }
1317
+
1318
+ .sidebar-panel[hidden] {
1319
+ display: none !important;
1320
+ }
1321
+
1322
+ .sidebar-section {
1323
+ display: flex;
1324
+ flex-direction: column;
1325
+ gap: 8px;
1326
+ }
1327
+
1328
+ .sidebar-label {
1329
+ font-size: 11px;
1330
+ font-weight: 600;
1331
+ letter-spacing: -0.01em;
1332
+ color: #8c93a0;
1333
+ font-family: var(--sans);
1334
+ }
1335
+
1336
+ .sidebar-divider {
1337
+ height: 1px;
1338
+ background: #16191f;
1339
+ margin: 2px 0;
1340
+ }
1341
+
1342
+ .sidebar-textarea {
1343
+ width: 100%;
1344
+ min-height: 72px;
1345
+ border-radius: 12px;
1346
+ border: 1px solid #1c2027;
1347
+ background: #111318;
1348
+ color: #f5f7fb;
1349
+ font-size: 13px;
1350
+ font-family: var(--sans);
1351
+ padding: 10px 12px;
1352
+ outline: none;
1353
+ resize: vertical;
1354
+ line-height: 1.45;
1355
+ }
1356
+
1357
+ .sidebar-textarea:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--ring); }
1358
+ .sidebar-textarea::placeholder { color: var(--text-2); }
1359
+
1360
+ .editor-sidebar .model-select {
1361
+ width: 100%;
1362
+ min-width: 0;
1363
+ height: 40px;
1364
+ border-radius: 12px;
1365
+ }
1366
+
1367
+ .sidebar-btn {
1368
+ width: 100%;
1369
+ height: 40px;
1370
+ border: 1px solid #1f2530;
1371
+ border-radius: 12px;
1372
+ background: #111318;
1373
+ color: #f5f7fb;
1374
+ font-size: 13px;
1375
+ font-family: var(--sans);
1376
+ font-weight: 600;
1377
+ cursor: pointer;
1378
+ transition: all var(--transition);
1379
+ display: inline-flex;
1380
+ align-items: center;
1381
+ justify-content: center;
1382
+ gap: 8px;
1383
+ }
1384
+
1385
+ .sidebar-btn:hover:not(:disabled) { background: #171b22; border-color: #282e38; }
1386
+ .sidebar-btn:disabled { opacity: 0.35; cursor: default; }
1387
+
1388
+ .sidebar-btn-primary {
1389
+ background: #111318;
1390
+ color: #f5f7fb;
1391
+ border: 1px solid #1f2530;
1392
+ }
1393
+
1394
+ .sidebar-btn-primary:hover:not(:disabled) {
1395
+ background: #171b22;
1396
+ }
1397
+
1398
+ .sidebar-btn-primary .btn-send-icon {
1399
+ width: 14px;
1400
+ height: 14px;
1401
+ fill: currentColor;
1402
+ }
1403
+
1404
+ .sidebar-input {
1405
+ flex: 1;
1406
+ min-width: 0;
1407
+ height: 36px;
1408
+ border-radius: 12px;
1409
+ border: 1px solid #1c2027;
1410
+ background: #111318;
1411
+ color: #f5f7fb;
1412
+ font-size: 12px;
1413
+ font-family: var(--sans);
1414
+ padding: 0 11px;
1415
+ outline: none;
1416
+ }
1417
+ textarea.sidebar-input {
1418
+ height: auto;
1419
+ padding: 9px 11px;
1420
+ resize: vertical;
1421
+ line-height: 1.5;
1422
+ }
1423
+
1424
+ .sidebar-input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--ring); }
1425
+ .sidebar-input:disabled { opacity: 0.4; cursor: default; }
1426
+
1427
+ .sidebar-number {
1428
+ width: 70px;
1429
+ flex: 0 0 auto;
1430
+ font-family: var(--mono);
1431
+ }
1432
+
1433
+ .sidebar-unit {
1434
+ color: #8c93a0;
1435
+ font-size: 12px;
1436
+ font-family: var(--sans);
1437
+ }
1438
+
1439
+ .sidebar-field-row {
1440
+ display: flex;
1441
+ align-items: center;
1442
+ gap: 8px;
1443
+ }
1444
+
1445
+ .sidebar-btn-sm {
1446
+ height: 36px;
1447
+ padding: 0 12px;
1448
+ border-radius: 12px;
1449
+ border: 1px solid #1f2530;
1450
+ background: #111318;
1451
+ color: #f5f7fb;
1452
+ font-size: 11px;
1453
+ font-family: var(--sans);
1454
+ font-weight: 600;
1455
+ cursor: pointer;
1456
+ flex: 0 0 auto;
1457
+ transition: all var(--transition);
1458
+ }
1459
+
1460
+ .sidebar-btn-sm:hover:not(:disabled) { background: #171b22; border-color: #282e38; }
1461
+ .sidebar-btn-sm:disabled { opacity: 0.35; cursor: default; }
1462
+
1463
+ .sidebar-color-row {
1464
+ display: flex;
1465
+ gap: 8px;
1466
+ }
1467
+
1468
+ .sidebar-color-field {
1469
+ flex: 1;
1470
+ display: flex;
1471
+ flex-direction: column;
1472
+ gap: 4px;
1473
+ cursor: pointer;
1474
+ }
1475
+
1476
+ .sidebar-color-label {
1477
+ font-size: 11px;
1478
+ color: #8c93a0;
1479
+ font-family: var(--sans);
1480
+ }
1481
+
1482
+ .sidebar-color {
1483
+ width: 100%;
1484
+ height: 38px;
1485
+ border-radius: 12px;
1486
+ border: 1px solid #1c2027;
1487
+ background: #111318;
1488
+ cursor: pointer;
1489
+ padding: 3px;
1490
+ }
1491
+
1492
+ .sidebar-color:disabled { opacity: 0.35; cursor: default; }
1493
+
1494
+ .sidebar-icon-grid {
1495
+ display: flex;
1496
+ gap: 6px;
1497
+ flex-wrap: wrap;
1498
+ }
1499
+
1500
+ .editor-sidebar .tool-icon-btn {
1501
+ min-width: 36px;
1502
+ height: 36px;
1503
+ border-radius: 10px;
1504
+ padding: 0 8px;
1505
+ border-color: #1f2530;
1506
+ background: #111318;
1507
+ }
1508
+
1509
+ .editor-sidebar .tool-icon-btn.tight {
1510
+ min-width: 36px;
1511
+ width: 36px;
1512
+ padding: 0;
1513
+ }
1514
+
1515
+ .sidebar-object-card {
1516
+ display: flex;
1517
+ align-items: center;
1518
+ padding: 10px 12px;
1519
+ border-radius: 12px;
1520
+ border: 1px solid #1c2027;
1521
+ background: #111318;
1522
+ color: #d9dee7;
1523
+ font-size: 12px;
1524
+ font-family: var(--sans);
1525
+ overflow: hidden;
1526
+ text-overflow: ellipsis;
1527
+ white-space: nowrap;
1528
+ }
1529
+
1530
+ .sidebar-object-card .mini-tag {
1531
+ color: #8ab4ff;
1532
+ font-weight: 600;
1533
+ margin-right: 4px;
1534
+ }
1535
+
1536
+ .select-empty-hint {
1537
+ color: #7f8794;
1538
+ font-size: 12px;
1539
+ font-family: var(--sans);
1540
+ padding: 6px 0;
1541
+ }
1542
+
1543
+ .sidebar-hint {
1544
+ flex: 0 0 auto;
1545
+ padding: 10px 14px;
1546
+ border-top: 1px solid #16191f;
1547
+ color: #6f7784;
1548
+ font-size: 12px;
1549
+ font-family: var(--sans);
1550
+ min-height: 36px;
1551
+ overflow: hidden;
1552
+ text-overflow: ellipsis;
1553
+ white-space: nowrap;
1554
+ }
1555
+
1556
+ :focus-visible {
1557
+ outline: none;
1558
+ box-shadow: 0 0 0 3px var(--ring);
1559
+ }
1560
+
1561
+ @media (max-width: 1380px) {
1562
+ .slide-toolbox {
1563
+ width: calc(100% - 8px);
1564
+ padding: 12px;
1565
+ gap: 10px;
1566
+ }
1567
+ .model-select {
1568
+ min-width: 138px;
1569
+ width: 138px;
1570
+ }
1571
+ .prompt-input {
1572
+ min-width: 160px;
1573
+ }
1574
+ }
1575
+ </style>
1576
+ </head>
1577
+ <body>
1578
+ <div class="editor-container">
1579
+ <div class="nav-bar">
1580
+ <div class="nav-controls">
1581
+ <button id="btn-prev" title="Previous slide (Left arrow)">&#9664; Prev</button>
1582
+ <span class="slide-counter" id="slide-counter">-- / --</span>
1583
+ <button id="btn-next" title="Next slide (Right arrow)">Next &#9654;</button>
1584
+ </div>
1585
+ <div class="nav-spacer"></div>
1586
+ <span class="slide-status-chip idle" id="slide-status-chip">idle</span>
1587
+ <span class="brand">ppt-agent</span>
1588
+ </div>
1589
+
1590
+ <div class="main-content">
1591
+ <div class="slide-panel" id="slide-panel">
1592
+ <div class="slide-stage" id="slide-stage">
1593
+ <div class="slide-wrapper" id="slide-wrapper">
1594
+ <button class="clear-overlay-btn" id="btn-clear-bboxes" title="Clear all boxes on current slide">Clear Boxes</button>
1595
+ <iframe id="slide-iframe" sandbox="allow-same-origin allow-scripts" loading="eager"></iframe>
1596
+ <div class="bbox-layer" id="bbox-layer"></div>
1597
+ <div class="object-layer" id="object-layer">
1598
+ <div class="object-outline hover" id="object-hover-box"></div>
1599
+ <div class="object-outline selected" id="object-selected-box"></div>
1600
+ </div>
1601
+ <div class="draw-layer" id="draw-layer">
1602
+ <div class="draw-box" id="draw-box"></div>
1603
+ </div>
1604
+ </div>
1605
+ </div>
1606
+ </div>
1607
+
1608
+ <aside class="editor-sidebar" id="editor-sidebar">
1609
+ <div class="sidebar-mode-tabs">
1610
+ <button type="button" class="sidebar-mode-tab active" id="tool-mode-draw" aria-pressed="true">
1611
+ <svg class="tool-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M5 5h14v14H5zM9 5v14M15 5v14M5 9h14M5 15h14"/></svg>
1612
+ BBox
1613
+ </button>
1614
+ <button type="button" class="sidebar-mode-tab" id="tool-mode-select" aria-pressed="false">
1615
+ <svg class="tool-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="m6 4 11 8-5 1.2L14.6 20l-2.5 1-2.6-6.8L6 15z"/></svg>
1616
+ Select
1617
+ </button>
1618
+ </div>
1619
+
1620
+ <div class="sidebar-body" id="sidebar-body">
1621
+ <div class="sidebar-panel" id="bbox-toolbar">
1622
+ <div class="sidebar-section">
1623
+ <span class="sidebar-label" id="bbox-count">0 pending · 0 review</span>
1624
+ <div class="context-chips" id="context-chip-list"></div>
1625
+ </div>
1626
+ <div class="sidebar-section">
1627
+ <span class="sidebar-label">Prompt</span>
1628
+ <textarea id="prompt-input" class="sidebar-textarea" placeholder="Describe the edit for red bboxes..." rows="3"></textarea>
1629
+ </div>
1630
+ <div class="sidebar-section">
1631
+ <span class="sidebar-label">Model</span>
1632
+ <select id="model-select" class="model-select">
1633
+ <option value="gpt-5.4">gpt-5.4</option>
1634
+ <option value="gpt-5.3-codex">gpt-5.3-codex</option>
1635
+ <option value="gpt-5.3-codex-spark">gpt-5.3-codex-spark</option>
1636
+ </select>
1637
+ </div>
1638
+ <button class="sidebar-btn" id="btn-send" title="Run Codex">
1639
+ <svg class="btn-send-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M3.4 11.2 19.6 4.4c.8-.3 1.7.5 1.4 1.4l-6.8 16.2c-.3.8-1.4.9-1.9.1L9.2 16l-6.1-3.1c-.8-.5-.7-1.6.3-1.7Zm5.1 3.6 3.2 1.6 4.9-11.7-11.7 4.9 3.6 1.8 6.2-3.7c.4-.2.8.1.6.6l-6.8 6.5Z"/></svg>
1640
+ Run Codex
1641
+ </button>
1642
+ </div>
1643
+
1644
+ <div class="sidebar-panel" id="select-toolbar" hidden>
1645
+ <div class="sidebar-section">
1646
+ <div class="sidebar-object-card" id="selected-object-mini" style="display:none">
1647
+ <span class="mini-tag" id="mini-tag"></span>
1648
+ <span id="mini-text"></span>
1649
+ </div>
1650
+ <span class="select-empty-hint" id="select-empty-hint">Click an object on the slide</span>
1651
+ </div>
1652
+ <div class="sidebar-divider"></div>
1653
+ <div class="sidebar-section">
1654
+ <span class="sidebar-label">Text</span>
1655
+ <div class="sidebar-field-row">
1656
+ <textarea id="popover-text-input" class="sidebar-input" rows="3" placeholder="Edit text..."></textarea>
1657
+ <button type="button" class="sidebar-btn-sm" id="popover-apply-text">Set</button>
1658
+ </div>
1659
+ </div>
1660
+ <div class="sidebar-section">
1661
+ <span class="sidebar-label">Color</span>
1662
+ <div class="sidebar-color-row">
1663
+ <label class="sidebar-color-field">
1664
+ <span class="sidebar-color-label">Text</span>
1665
+ <input id="popover-text-color-input" class="sidebar-color" type="color" value="#111111">
1666
+ </label>
1667
+ <label class="sidebar-color-field">
1668
+ <span class="sidebar-color-label">Bg</span>
1669
+ <input id="popover-bg-color-input" class="sidebar-color" type="color" value="#ffffff">
1670
+ </label>
1671
+ </div>
1672
+ </div>
1673
+ <div class="sidebar-section">
1674
+ <span class="sidebar-label">Size</span>
1675
+ <div class="sidebar-field-row">
1676
+ <input id="popover-size-input" class="sidebar-input sidebar-number" type="number" min="8" max="180" step="1" value="24">
1677
+ <span class="sidebar-unit">px</span>
1678
+ <button type="button" class="sidebar-btn-sm" id="popover-apply-size">Set</button>
1679
+ </div>
1680
+ </div>
1681
+ <div class="sidebar-divider"></div>
1682
+ <div class="sidebar-section">
1683
+ <span class="sidebar-label">Style</span>
1684
+ <div class="sidebar-icon-grid">
1685
+ <button type="button" class="tool-icon-btn style-toggle tight" id="toggle-bold" title="Bold (⌘B)">
1686
+ <svg class="tool-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M14 12a4 4 0 0 0 0-8H6v8"/><path d="M15 20a4 4 0 0 0 0-8H6v8"/></svg>
1687
+ </button>
1688
+ <button type="button" class="tool-icon-btn style-toggle tight" id="toggle-italic" title="Italic (⌘I)">
1689
+ <svg class="tool-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M19 4h-9M14 20H5M15 4 9 20"/></svg>
1690
+ </button>
1691
+ <button type="button" class="tool-icon-btn style-toggle tight" id="toggle-underline" title="Underline (⌘U)">
1692
+ <svg class="tool-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M6 4v6a6 6 0 0 0 12 0V4"/><path d="M4 20h16"/></svg>
1693
+ </button>
1694
+ <button type="button" class="tool-icon-btn style-toggle tight" id="toggle-strike" title="Strikethrough">
1695
+ <svg class="tool-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M16 4H9a3 3 0 0 0-2.83 4"/><path d="M14 12a4 4 0 0 1 0 8H6"/><path d="M4 12h16"/></svg>
1696
+ </button>
1697
+ </div>
1698
+ </div>
1699
+ <div class="sidebar-section">
1700
+ <span class="sidebar-label">Align</span>
1701
+ <div class="sidebar-icon-grid">
1702
+ <button type="button" class="tool-icon-btn align-btn tight" id="align-left" title="Align left">
1703
+ <svg class="tool-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M21 6H3M15 12H3M17 18H3"/></svg>
1704
+ </button>
1705
+ <button type="button" class="tool-icon-btn align-btn tight" id="align-center" title="Align center">
1706
+ <svg class="tool-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M21 6H3M17 12H7M19 18H5"/></svg>
1707
+ </button>
1708
+ <button type="button" class="tool-icon-btn align-btn tight" id="align-right" title="Align right">
1709
+ <svg class="tool-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M21 6H3M21 12H9M21 18H7"/></svg>
1710
+ </button>
1711
+ </div>
1712
+ </div>
1713
+ </div>
1714
+ </div>
1715
+
1716
+ <div class="sidebar-hint" id="editor-hint">
1717
+ Drag on the slide to add red bboxes. Enter to run.
1718
+ </div>
1719
+ </aside>
1720
+ </div>
1721
+
1722
+ <div class="status-bar">
1723
+ <span>
1724
+ <span class="status-dot" id="status-dot"></span>
1725
+ <span id="status-connection">Connecting...</span>
1726
+ </span>
1727
+ <span class="status-message" id="status-message"></span>
1728
+ </div>
1729
+ </div>
1730
+
1731
+ <script type="module" src="/js/editor-init.js"></script>
1732
+ </body>
1733
+ </html>