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