active_canvas 0.0.1

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 (80) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +318 -0
  4. data/Rakefile +6 -0
  5. data/app/assets/javascripts/active_canvas/editor/ai_panel.js +1607 -0
  6. data/app/assets/javascripts/active_canvas/editor/asset_manager.js +498 -0
  7. data/app/assets/javascripts/active_canvas/editor/blocks.js +1083 -0
  8. data/app/assets/javascripts/active_canvas/editor/code_panel.js +572 -0
  9. data/app/assets/javascripts/active_canvas/editor/component_toolbar.js +394 -0
  10. data/app/assets/javascripts/active_canvas/editor/panels.js +460 -0
  11. data/app/assets/javascripts/active_canvas/editor/utils.js +56 -0
  12. data/app/assets/javascripts/active_canvas/editor.js +295 -0
  13. data/app/assets/stylesheets/active_canvas/application.css +15 -0
  14. data/app/assets/stylesheets/active_canvas/editor.css +2929 -0
  15. data/app/controllers/active_canvas/admin/ai_controller.rb +181 -0
  16. data/app/controllers/active_canvas/admin/application_controller.rb +56 -0
  17. data/app/controllers/active_canvas/admin/media_controller.rb +61 -0
  18. data/app/controllers/active_canvas/admin/page_types_controller.rb +57 -0
  19. data/app/controllers/active_canvas/admin/page_versions_controller.rb +23 -0
  20. data/app/controllers/active_canvas/admin/pages_controller.rb +133 -0
  21. data/app/controllers/active_canvas/admin/partials_controller.rb +88 -0
  22. data/app/controllers/active_canvas/admin/settings_controller.rb +256 -0
  23. data/app/controllers/active_canvas/application_controller.rb +20 -0
  24. data/app/controllers/active_canvas/pages_controller.rb +18 -0
  25. data/app/controllers/concerns/active_canvas/current_user.rb +12 -0
  26. data/app/controllers/concerns/active_canvas/rate_limitable.rb +75 -0
  27. data/app/controllers/concerns/active_canvas/tailwind_compilation.rb +39 -0
  28. data/app/helpers/active_canvas/application_helper.rb +4 -0
  29. data/app/jobs/active_canvas/application_job.rb +4 -0
  30. data/app/jobs/active_canvas/compile_tailwind_job.rb +64 -0
  31. data/app/mailers/active_canvas/application_mailer.rb +6 -0
  32. data/app/models/active_canvas/ai_model.rb +136 -0
  33. data/app/models/active_canvas/application_record.rb +5 -0
  34. data/app/models/active_canvas/media.rb +141 -0
  35. data/app/models/active_canvas/page.rb +85 -0
  36. data/app/models/active_canvas/page_type.rb +22 -0
  37. data/app/models/active_canvas/page_version.rb +80 -0
  38. data/app/models/active_canvas/partial.rb +73 -0
  39. data/app/models/active_canvas/setting.rb +292 -0
  40. data/app/services/active_canvas/ai_configuration.rb +40 -0
  41. data/app/services/active_canvas/ai_models.rb +128 -0
  42. data/app/services/active_canvas/ai_service.rb +289 -0
  43. data/app/services/active_canvas/content_sanitizer.rb +112 -0
  44. data/app/services/active_canvas/tailwind_compiler.rb +156 -0
  45. data/app/views/active_canvas/admin/media/index.html.erb +401 -0
  46. data/app/views/active_canvas/admin/media/show.html.erb +297 -0
  47. data/app/views/active_canvas/admin/page_types/_form.html.erb +25 -0
  48. data/app/views/active_canvas/admin/page_types/edit.html.erb +13 -0
  49. data/app/views/active_canvas/admin/page_types/index.html.erb +29 -0
  50. data/app/views/active_canvas/admin/page_types/new.html.erb +9 -0
  51. data/app/views/active_canvas/admin/page_types/show.html.erb +18 -0
  52. data/app/views/active_canvas/admin/page_versions/show.html.erb +469 -0
  53. data/app/views/active_canvas/admin/pages/_form.html.erb +62 -0
  54. data/app/views/active_canvas/admin/pages/content.html.erb +139 -0
  55. data/app/views/active_canvas/admin/pages/edit.html.erb +335 -0
  56. data/app/views/active_canvas/admin/pages/editor.html.erb +710 -0
  57. data/app/views/active_canvas/admin/pages/index.html.erb +149 -0
  58. data/app/views/active_canvas/admin/pages/new.html.erb +19 -0
  59. data/app/views/active_canvas/admin/pages/show.html.erb +258 -0
  60. data/app/views/active_canvas/admin/pages/versions.html.erb +333 -0
  61. data/app/views/active_canvas/admin/partials/edit.html.erb +182 -0
  62. data/app/views/active_canvas/admin/partials/editor.html.erb +703 -0
  63. data/app/views/active_canvas/admin/partials/index.html.erb +131 -0
  64. data/app/views/active_canvas/admin/settings/show.html.erb +1864 -0
  65. data/app/views/active_canvas/pages/no_homepage.html.erb +45 -0
  66. data/app/views/active_canvas/pages/show.html.erb +113 -0
  67. data/app/views/layouts/active_canvas/admin/application.html.erb +960 -0
  68. data/app/views/layouts/active_canvas/admin/editor.html.erb +826 -0
  69. data/app/views/layouts/active_canvas/application.html.erb +55 -0
  70. data/config/routes.rb +48 -0
  71. data/db/migrate/20260202000001_create_active_canvas_tables.rb +113 -0
  72. data/db/migrate/20260202000002_create_active_canvas_ai_models.rb +26 -0
  73. data/lib/active_canvas/configuration.rb +232 -0
  74. data/lib/active_canvas/engine.rb +44 -0
  75. data/lib/active_canvas/version.rb +3 -0
  76. data/lib/active_canvas.rb +26 -0
  77. data/lib/generators/active_canvas/install/install_generator.rb +263 -0
  78. data/lib/generators/active_canvas/install/templates/initializer.rb.tt +163 -0
  79. data/lib/tasks/active_canvas_tasks.rake +69 -0
  80. metadata +150 -0
@@ -0,0 +1,2929 @@
1
+ /**
2
+ * ActiveCanvas Visual Editor Styles
3
+ * Overrides for GrapeJS components
4
+ * CSS variables are defined in the layout with theme support
5
+ */
6
+
7
+ /* ==================== Hide GrapeJS Default UI ==================== */
8
+
9
+ .gjs-pn-panels,
10
+ .gjs-pn-views-container,
11
+ .gjs-pn-views,
12
+ .gjs-pn-options,
13
+ .gjs-pn-commands,
14
+ .gjs-pn-devices-c,
15
+ .gjs-pn-buttons,
16
+ .gjs-cv-canvas__top,
17
+ .gjs-frame-wrapper__top {
18
+ display: none !important;
19
+ }
20
+
21
+ /* Hide the annoying hover badge/circle */
22
+ .gjs-badge,
23
+ .gjs-badge-warning,
24
+ .gjs-com-badge,
25
+ .gjs-com-badge-red,
26
+ .gjs-badge__icon {
27
+ display: none !important;
28
+ opacity: 0 !important;
29
+ visibility: hidden !important;
30
+ }
31
+
32
+ /* ==================== Override GrapeJS Default Colors ==================== */
33
+
34
+ /* These are the main GrapeJS color utility classes */
35
+ .gjs-one-bg {
36
+ background-color: var(--editor-surface) !important;
37
+ }
38
+
39
+ .gjs-two-color {
40
+ color: var(--editor-text) !important;
41
+ }
42
+
43
+ .gjs-three-bg {
44
+ background-color: var(--editor-bg) !important;
45
+ }
46
+
47
+ .gjs-four-color,
48
+ .gjs-four-color-h:hover {
49
+ color: var(--editor-primary) !important;
50
+ }
51
+
52
+ /* Block manager container background */
53
+ .gjs-blocks-cs {
54
+ background-color: var(--editor-bg) !important;
55
+ }
56
+
57
+ #blocks-container {
58
+ background-color: var(--editor-bg) !important;
59
+ }
60
+
61
+ /* Any remaining brownish backgrounds */
62
+ .gjs-editor-cont,
63
+ .gjs-editor {
64
+ background-color: var(--editor-bg) !important;
65
+ }
66
+
67
+ .gjs-clm-tags,
68
+ .gjs-clm-sels-info {
69
+ background-color: var(--editor-bg) !important;
70
+ }
71
+
72
+ /* ==================== GrapeJS Blocks ==================== */
73
+
74
+ /* Block items */
75
+ .gjs-block {
76
+ background: var(--editor-surface) !important;
77
+ border: 1px solid var(--editor-border) !important;
78
+ border-radius: var(--editor-radius) !important;
79
+ color: var(--editor-text) !important;
80
+ padding: 0.625rem !important;
81
+ min-height: 70px !important;
82
+ transition: all 0.15s ease !important;
83
+ display: flex !important;
84
+ flex-direction: column !important;
85
+ align-items: center !important;
86
+ justify-content: center !important;
87
+ }
88
+
89
+ .gjs-block:hover {
90
+ background: var(--editor-surface-hover) !important;
91
+ border-color: var(--editor-primary) !important;
92
+ box-shadow: 0 0 0 1px var(--editor-primary) !important;
93
+ }
94
+
95
+ .gjs-block.gjs-block--active {
96
+ background: var(--editor-primary-light) !important;
97
+ border-color: var(--editor-primary) !important;
98
+ }
99
+
100
+ /* Block media/icon container */
101
+ .gjs-block__media {
102
+ display: flex !important;
103
+ align-items: center !important;
104
+ justify-content: center !important;
105
+ margin-bottom: 0.375rem !important;
106
+ }
107
+
108
+ .gjs-block__media svg {
109
+ width: 28px !important;
110
+ height: 28px !important;
111
+ }
112
+
113
+ /* Block label */
114
+ .gjs-block-label {
115
+ color: var(--editor-text) !important;
116
+ font-size: 0.75rem !important;
117
+ font-weight: 500 !important;
118
+ margin-top: 0.5rem !important;
119
+ }
120
+
121
+ /* Block SVG/icon */
122
+ .gjs-block svg {
123
+ fill: var(--editor-text-muted) !important;
124
+ }
125
+
126
+ .gjs-block:hover svg {
127
+ fill: var(--editor-primary) !important;
128
+ }
129
+
130
+ /* Block categories */
131
+ .gjs-block-category {
132
+ background: transparent !important;
133
+ border-bottom: 1px solid var(--editor-border) !important;
134
+ }
135
+
136
+ .gjs-block-category .gjs-title {
137
+ background: var(--editor-surface) !important;
138
+ color: var(--editor-text) !important;
139
+ font-weight: 600 !important;
140
+ font-size: 0.8125rem !important;
141
+ padding: 0.75rem 1rem !important;
142
+ border: none !important;
143
+ }
144
+
145
+ .gjs-block-category .gjs-title:hover {
146
+ background: var(--editor-surface-hover) !important;
147
+ }
148
+
149
+ .gjs-block-category .gjs-caret-icon {
150
+ color: var(--editor-text-muted) !important;
151
+ }
152
+
153
+ /* Blocks container/grid - only style when visible (open accordion) */
154
+ .gjs-blocks-c {
155
+ padding: 0.75rem !important;
156
+ grid-template-columns: repeat(2, 1fr) !important;
157
+ gap: 0.5rem !important;
158
+ background-color: var(--editor-bg) !important;
159
+ }
160
+
161
+ /* Apply grid display only when the container is visible (not collapsed) */
162
+ .gjs-block-category.gjs-open .gjs-blocks-c {
163
+ display: grid !important;
164
+ }
165
+
166
+ /* Block items - proper sizing */
167
+ .gjs-blocks-c .gjs-block {
168
+ width: 100% !important;
169
+ box-sizing: border-box !important;
170
+ }
171
+
172
+ /* Scrollbar for blocks panel */
173
+ .gjs-blocks-c::-webkit-scrollbar {
174
+ width: 6px;
175
+ }
176
+
177
+ .gjs-blocks-c::-webkit-scrollbar-track {
178
+ background: var(--editor-bg);
179
+ }
180
+
181
+ .gjs-blocks-c::-webkit-scrollbar-thumb {
182
+ background: var(--editor-border);
183
+ border-radius: 3px;
184
+ }
185
+
186
+ .gjs-blocks-c::-webkit-scrollbar-thumb:hover {
187
+ background: var(--editor-border-light);
188
+ }
189
+
190
+ /* ==================== GrapeJS Style Manager ==================== */
191
+
192
+ .gjs-sm-sector {
193
+ background: transparent !important;
194
+ border-bottom: 1px solid var(--editor-border) !important;
195
+ }
196
+
197
+ .gjs-sm-sector .gjs-sm-sector-title {
198
+ background: var(--editor-surface) !important;
199
+ color: var(--editor-text) !important;
200
+ font-weight: 600 !important;
201
+ font-size: 0.8125rem !important;
202
+ padding: 0.75rem 1rem !important;
203
+ border: none !important;
204
+ }
205
+
206
+ .gjs-sm-sector .gjs-sm-sector-title:hover {
207
+ background: var(--editor-surface-hover) !important;
208
+ }
209
+
210
+ .gjs-sm-sector .gjs-sm-sector-caret {
211
+ color: var(--editor-text-muted) !important;
212
+ }
213
+
214
+ .gjs-sm-properties {
215
+ padding: 0.75rem !important;
216
+ background: var(--editor-bg) !important;
217
+ }
218
+
219
+ .gjs-sm-property {
220
+ margin-bottom: 0.75rem !important;
221
+ }
222
+
223
+ .gjs-sm-label {
224
+ color: var(--editor-text-muted) !important;
225
+ font-size: 0.75rem !important;
226
+ font-weight: 500 !important;
227
+ margin-bottom: 0.375rem !important;
228
+ }
229
+
230
+ /* Style manager inputs */
231
+ .gjs-field {
232
+ background: var(--editor-surface) !important;
233
+ border: 1px solid var(--editor-border) !important;
234
+ border-radius: 4px !important;
235
+ color: var(--editor-text) !important;
236
+ }
237
+
238
+ .gjs-field:focus-within {
239
+ border-color: var(--editor-primary) !important;
240
+ box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.2) !important;
241
+ }
242
+
243
+ .gjs-field input,
244
+ .gjs-field select,
245
+ .gjs-field textarea {
246
+ background: transparent !important;
247
+ color: var(--editor-text) !important;
248
+ border: none !important;
249
+ }
250
+
251
+ .gjs-field-arrows {
252
+ color: var(--editor-text-muted) !important;
253
+ }
254
+
255
+ /* Color picker */
256
+ .gjs-field-color-picker {
257
+ border: 1px solid var(--editor-border) !important;
258
+ border-radius: 4px !important;
259
+ }
260
+
261
+ /* Radio/checkbox buttons */
262
+ .gjs-sm-btn {
263
+ background: var(--editor-surface) !important;
264
+ border: 1px solid var(--editor-border) !important;
265
+ color: var(--editor-text) !important;
266
+ }
267
+
268
+ .gjs-sm-btn:hover {
269
+ background: var(--editor-surface-hover) !important;
270
+ }
271
+
272
+ .gjs-sm-btn.gjs-sm-btn--active {
273
+ background: var(--editor-primary) !important;
274
+ border-color: var(--editor-primary) !important;
275
+ color: white !important;
276
+ }
277
+
278
+ /* ==================== GrapeJS Layer Manager ==================== */
279
+
280
+ .gjs-layer {
281
+ background: var(--editor-surface) !important;
282
+ color: var(--editor-text) !important;
283
+ border-bottom: 1px solid var(--editor-border) !important;
284
+ }
285
+
286
+ .gjs-layer:hover {
287
+ background: var(--editor-surface-hover) !important;
288
+ }
289
+
290
+ .gjs-layer.gjs-selected {
291
+ background: var(--editor-primary) !important;
292
+ color: white !important;
293
+ }
294
+
295
+ .gjs-layer-title {
296
+ padding: 0.5rem 0.75rem !important;
297
+ }
298
+
299
+ .gjs-layer-name {
300
+ font-size: 0.8125rem !important;
301
+ }
302
+
303
+ .gjs-layer-caret {
304
+ color: var(--editor-text-muted) !important;
305
+ }
306
+
307
+ .gjs-layer-vis {
308
+ color: var(--editor-text-muted) !important;
309
+ }
310
+
311
+ /* ==================== GrapeJS Selector Manager ==================== */
312
+
313
+ .gjs-clm-tags {
314
+ padding: 0.5rem !important;
315
+ background: var(--editor-bg) !important;
316
+ }
317
+
318
+ .gjs-clm-tag {
319
+ background: var(--editor-surface) !important;
320
+ border: 1px solid var(--editor-border) !important;
321
+ border-radius: 4px !important;
322
+ color: var(--editor-text) !important;
323
+ padding: 0.25rem 0.5rem !important;
324
+ font-size: 0.75rem !important;
325
+ }
326
+
327
+ .gjs-clm-tag:hover {
328
+ background: var(--editor-surface-hover) !important;
329
+ }
330
+
331
+ .gjs-clm-tag.gjs-clm-tag--active {
332
+ background: var(--editor-primary) !important;
333
+ border-color: var(--editor-primary) !important;
334
+ color: white !important;
335
+ }
336
+
337
+ .gjs-clm-tag-close {
338
+ color: var(--editor-text-muted) !important;
339
+ }
340
+
341
+ .gjs-clm-sels-info {
342
+ color: var(--editor-text-muted) !important;
343
+ font-size: 0.75rem !important;
344
+ padding: 0.5rem !important;
345
+ }
346
+
347
+ /* ==================== GrapeJS Trait Manager ==================== */
348
+
349
+ .gjs-trt-trait {
350
+ padding: 0.5rem 0 !important;
351
+ border-bottom: 1px solid var(--editor-border) !important;
352
+ }
353
+
354
+ .gjs-trt-trait__wrp-title {
355
+ color: var(--editor-text-muted) !important;
356
+ font-size: 0.75rem !important;
357
+ font-weight: 500 !important;
358
+ }
359
+
360
+ /* ==================== GrapeJS Modal / Asset Manager ==================== */
361
+
362
+ /* Modal overlay */
363
+ .gjs-mdl-container {
364
+ background-color: rgba(0, 0, 0, 0.7) !important;
365
+ }
366
+
367
+ /* Modal dialog */
368
+ .gjs-mdl-dialog {
369
+ background: var(--editor-surface) !important;
370
+ border: 1px solid var(--editor-border) !important;
371
+ border-radius: var(--editor-radius-lg) !important;
372
+ box-shadow: var(--editor-shadow-md) !important;
373
+ }
374
+
375
+ /* Modal header */
376
+ .gjs-mdl-header {
377
+ background: var(--editor-surface) !important;
378
+ border-bottom: 1px solid var(--editor-border) !important;
379
+ padding: 1rem 1.25rem !important;
380
+ }
381
+
382
+ .gjs-mdl-title {
383
+ color: var(--editor-text) !important;
384
+ font-weight: 600 !important;
385
+ }
386
+
387
+ .gjs-mdl-btn-close {
388
+ color: var(--editor-text-muted) !important;
389
+ }
390
+
391
+ .gjs-mdl-btn-close:hover {
392
+ color: var(--editor-text) !important;
393
+ }
394
+
395
+ /* Modal content */
396
+ .gjs-mdl-content {
397
+ background: var(--editor-bg) !important;
398
+ padding: 0 !important;
399
+ }
400
+
401
+ /* Asset Manager */
402
+ .gjs-am-assets-cont {
403
+ background: var(--editor-bg) !important;
404
+ padding: 1rem !important;
405
+ }
406
+
407
+ .gjs-am-assets-header {
408
+ background: var(--editor-surface) !important;
409
+ padding: 1rem !important;
410
+ border-bottom: 1px solid var(--editor-border) !important;
411
+ }
412
+
413
+ /* Asset items */
414
+ .gjs-am-asset {
415
+ background: var(--editor-surface) !important;
416
+ border: 1px solid var(--editor-border) !important;
417
+ border-radius: var(--editor-radius) !important;
418
+ overflow: hidden !important;
419
+ margin: 0.25rem !important;
420
+ }
421
+
422
+ .gjs-am-asset:hover {
423
+ border-color: var(--editor-primary) !important;
424
+ }
425
+
426
+ .gjs-am-asset-image {
427
+ background: var(--editor-bg) !important;
428
+ }
429
+
430
+ .gjs-am-meta {
431
+ background: var(--editor-surface) !important;
432
+ color: var(--editor-text) !important;
433
+ padding: 0.5rem !important;
434
+ font-size: 0.75rem !important;
435
+ }
436
+
437
+ .gjs-am-close {
438
+ color: var(--editor-text-muted) !important;
439
+ }
440
+
441
+ .gjs-am-close:hover {
442
+ color: var(--editor-danger) !important;
443
+ }
444
+
445
+ /* File uploader */
446
+ .gjs-am-file-uploader {
447
+ background: var(--editor-bg) !important;
448
+ border: 2px dashed var(--editor-border) !important;
449
+ border-radius: var(--editor-radius) !important;
450
+ padding: 2rem !important;
451
+ margin: 1rem !important;
452
+ text-align: center;
453
+ }
454
+
455
+ .gjs-am-file-uploader:hover {
456
+ border-color: var(--editor-primary) !important;
457
+ }
458
+
459
+ .gjs-am-file-uploader form {
460
+ color: var(--editor-text-muted) !important;
461
+ }
462
+
463
+ /* Add asset button */
464
+ .gjs-am-add-asset {
465
+ background: var(--editor-primary) !important;
466
+ color: white !important;
467
+ border-radius: var(--editor-radius) !important;
468
+ padding: 0.5rem 1rem !important;
469
+ }
470
+
471
+ .gjs-am-add-asset:hover {
472
+ background: var(--editor-primary-hover) !important;
473
+ }
474
+
475
+ /* Asset preview */
476
+ .gjs-am-preview-cont {
477
+ background: var(--editor-bg) !important;
478
+ border: 1px solid var(--editor-border) !important;
479
+ border-radius: var(--editor-radius) !important;
480
+ }
481
+
482
+ /* ==================== Custom Asset Manager Modal ==================== */
483
+
484
+ .ac-asset-modal {
485
+ position: fixed;
486
+ top: 0;
487
+ left: 0;
488
+ right: 0;
489
+ bottom: 0;
490
+ z-index: 10001;
491
+ display: flex;
492
+ align-items: center;
493
+ justify-content: center;
494
+ }
495
+
496
+ .ac-asset-modal-overlay {
497
+ position: absolute;
498
+ top: 0;
499
+ left: 0;
500
+ right: 0;
501
+ bottom: 0;
502
+ background: rgba(0, 0, 0, 0.7);
503
+ }
504
+
505
+ .ac-asset-modal-dialog {
506
+ position: relative;
507
+ background: var(--editor-surface);
508
+ border: 1px solid var(--editor-border);
509
+ border-radius: var(--editor-radius-lg);
510
+ box-shadow: var(--editor-shadow-md);
511
+ width: 90%;
512
+ max-width: 900px;
513
+ max-height: 85vh;
514
+ display: flex;
515
+ flex-direction: column;
516
+ overflow: hidden;
517
+ }
518
+
519
+ .ac-asset-modal-header {
520
+ display: flex;
521
+ align-items: center;
522
+ justify-content: space-between;
523
+ padding: 1rem 1.25rem;
524
+ border-bottom: 1px solid var(--editor-border);
525
+ }
526
+
527
+ .ac-asset-modal-header h3 {
528
+ margin: 0;
529
+ font-size: 1rem;
530
+ font-weight: 600;
531
+ color: var(--editor-text);
532
+ }
533
+
534
+ .ac-asset-modal-close {
535
+ background: none;
536
+ border: none;
537
+ color: var(--editor-text-muted);
538
+ cursor: pointer;
539
+ padding: 0.25rem;
540
+ border-radius: 4px;
541
+ display: flex;
542
+ align-items: center;
543
+ justify-content: center;
544
+ transition: all 0.15s ease;
545
+ }
546
+
547
+ .ac-asset-modal-close:hover {
548
+ background: var(--editor-surface-hover);
549
+ color: var(--editor-text);
550
+ }
551
+
552
+ .ac-asset-modal-tabs {
553
+ display: flex;
554
+ gap: 0;
555
+ background: var(--editor-bg);
556
+ padding: 0;
557
+ border-bottom: 1px solid var(--editor-border);
558
+ }
559
+
560
+ .ac-asset-tab {
561
+ background: none;
562
+ border: none;
563
+ padding: 0.875rem 1.5rem;
564
+ font-size: 0.875rem;
565
+ font-weight: 500;
566
+ color: var(--editor-text-muted);
567
+ cursor: pointer;
568
+ border-bottom: 2px solid transparent;
569
+ margin-bottom: -1px;
570
+ transition: all 0.15s ease;
571
+ }
572
+
573
+ .ac-asset-tab:hover {
574
+ color: var(--editor-text);
575
+ background: var(--editor-surface-hover);
576
+ }
577
+
578
+ .ac-asset-tab.active {
579
+ color: var(--editor-primary);
580
+ border-bottom-color: var(--editor-primary);
581
+ background: var(--editor-surface);
582
+ }
583
+
584
+ .ac-asset-modal-body {
585
+ flex: 1;
586
+ overflow: hidden;
587
+ display: flex;
588
+ flex-direction: column;
589
+ }
590
+
591
+ .ac-asset-tab-content {
592
+ display: none;
593
+ flex: 1;
594
+ overflow: hidden;
595
+ flex-direction: column;
596
+ }
597
+
598
+ .ac-asset-tab-content.active {
599
+ display: flex;
600
+ }
601
+
602
+ /* Media Grid */
603
+ .ac-asset-grid {
604
+ flex: 1;
605
+ overflow-y: auto;
606
+ padding: 1rem;
607
+ display: grid;
608
+ grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
609
+ gap: 0.75rem;
610
+ align-content: start;
611
+ }
612
+
613
+ .ac-asset-item {
614
+ background: var(--editor-bg);
615
+ border: 1px solid var(--editor-border);
616
+ border-radius: var(--editor-radius);
617
+ overflow: hidden;
618
+ cursor: pointer;
619
+ transition: all 0.15s ease;
620
+ }
621
+
622
+ .ac-asset-item:hover {
623
+ border-color: var(--editor-primary);
624
+ box-shadow: 0 0 0 1px var(--editor-primary);
625
+ }
626
+
627
+ .ac-asset-thumb {
628
+ aspect-ratio: 1;
629
+ overflow: hidden;
630
+ background: var(--editor-surface);
631
+ display: flex;
632
+ align-items: center;
633
+ justify-content: center;
634
+ }
635
+
636
+ .ac-asset-thumb img {
637
+ width: 100%;
638
+ height: 100%;
639
+ object-fit: cover;
640
+ }
641
+
642
+ .ac-asset-name {
643
+ padding: 0.5rem;
644
+ font-size: 0.6875rem;
645
+ color: var(--editor-text-muted);
646
+ white-space: nowrap;
647
+ overflow: hidden;
648
+ text-overflow: ellipsis;
649
+ text-align: center;
650
+ }
651
+
652
+ .ac-asset-loading,
653
+ .ac-asset-empty {
654
+ grid-column: 1 / -1;
655
+ text-align: center;
656
+ padding: 3rem;
657
+ color: var(--editor-text-muted);
658
+ }
659
+
660
+ /* Pagination */
661
+ .ac-asset-pagination {
662
+ display: flex;
663
+ align-items: center;
664
+ justify-content: space-between;
665
+ padding: 0.75rem 1rem;
666
+ border-top: 1px solid var(--editor-border);
667
+ background: var(--editor-surface);
668
+ }
669
+
670
+ .ac-pagination-info {
671
+ font-size: 0.75rem;
672
+ color: var(--editor-text-muted);
673
+ }
674
+
675
+ .ac-pagination-buttons {
676
+ display: flex;
677
+ gap: 0.25rem;
678
+ }
679
+
680
+ .ac-pagination-btn {
681
+ background: var(--editor-bg);
682
+ border: 1px solid var(--editor-border);
683
+ color: var(--editor-text);
684
+ padding: 0.375rem 0.75rem;
685
+ font-size: 0.75rem;
686
+ border-radius: 4px;
687
+ cursor: pointer;
688
+ transition: all 0.15s ease;
689
+ }
690
+
691
+ .ac-pagination-btn:hover {
692
+ background: var(--editor-surface-hover);
693
+ border-color: var(--editor-border-light);
694
+ }
695
+
696
+ .ac-pagination-btn.active {
697
+ background: var(--editor-primary);
698
+ border-color: var(--editor-primary);
699
+ color: white;
700
+ }
701
+
702
+ /* Upload Zone */
703
+ .ac-asset-upload-zone {
704
+ flex: 1;
705
+ margin: 1rem;
706
+ border: 2px dashed var(--editor-border);
707
+ border-radius: var(--editor-radius);
708
+ display: flex;
709
+ flex-direction: column;
710
+ align-items: center;
711
+ justify-content: center;
712
+ padding: 3rem;
713
+ cursor: pointer;
714
+ transition: all 0.15s ease;
715
+ color: var(--editor-text-muted);
716
+ }
717
+
718
+ .ac-asset-upload-zone:hover,
719
+ .ac-asset-upload-zone.dragover {
720
+ border-color: var(--editor-primary);
721
+ background: var(--editor-primary-light);
722
+ }
723
+
724
+ .ac-asset-upload-zone svg {
725
+ margin-bottom: 1rem;
726
+ opacity: 0.5;
727
+ }
728
+
729
+ .ac-asset-upload-zone p {
730
+ margin: 0.25rem 0;
731
+ font-size: 0.875rem;
732
+ }
733
+
734
+ .ac-upload-hint {
735
+ font-size: 0.75rem !important;
736
+ opacity: 0.7;
737
+ }
738
+
739
+ .ac-upload-progress {
740
+ margin: 1rem;
741
+ padding: 1rem;
742
+ background: var(--editor-bg);
743
+ border-radius: var(--editor-radius);
744
+ }
745
+
746
+ .ac-upload-progress-bar {
747
+ height: 4px;
748
+ background: var(--editor-primary);
749
+ border-radius: 2px;
750
+ transition: width 0.3s ease;
751
+ }
752
+
753
+ .ac-upload-progress-text {
754
+ display: block;
755
+ margin-top: 0.5rem;
756
+ font-size: 0.75rem;
757
+ color: var(--editor-text-muted);
758
+ }
759
+
760
+ /* Canvas responsive device preview */
761
+ .gjs-cv-canvas {
762
+ top: 0 !important;
763
+ display: flex !important;
764
+ justify-content: center !important;
765
+ align-items: flex-start !important;
766
+ overflow: auto !important;
767
+ background: var(--editor-canvas-bg, var(--editor-bg, #0f172a)) !important;
768
+ padding: 1rem !important;
769
+ }
770
+
771
+ .gjs-frame-wrapper {
772
+ top: 0 !important;
773
+ transition: width 0.3s ease, box-shadow 0.3s ease !important;
774
+ background: #fff !important;
775
+ box-shadow: 0 4px 40px rgba(0, 0, 0, 0.4) !important;
776
+ border-radius: 4px !important;
777
+ overflow: hidden !important;
778
+ }
779
+
780
+ /* When not at full width (responsive preview) */
781
+ .gjs-frame-wrapper:not([style*="width: 100%"]):not([style=""]) {
782
+ margin: 0 auto !important;
783
+ }
784
+
785
+ /* ==================== Header ==================== */
786
+
787
+ .editor-logo {
788
+ display: flex;
789
+ align-items: center;
790
+ text-decoration: none;
791
+ margin-right: 0.5rem;
792
+ }
793
+
794
+ .editor-logo-icon {
795
+ width: 28px;
796
+ height: 28px;
797
+ background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);
798
+ border-radius: 0.375rem;
799
+ display: flex;
800
+ align-items: center;
801
+ justify-content: center;
802
+ transition: transform 0.15s ease;
803
+ }
804
+
805
+ .editor-logo-icon:hover {
806
+ transform: scale(1.05);
807
+ }
808
+
809
+ .editor-logo-icon svg {
810
+ width: 14px;
811
+ height: 14px;
812
+ color: white;
813
+ }
814
+
815
+ .header-separator {
816
+ width: 1px;
817
+ height: 24px;
818
+ background: var(--editor-border);
819
+ margin: 0 0.5rem;
820
+ }
821
+
822
+ /* ==================== Panels ==================== */
823
+
824
+ .editor-panel-left,
825
+ .editor-panel-right {
826
+ transition: width 0.2s ease, min-width 0.2s ease, opacity 0.2s ease, border-width 0.2s ease;
827
+ overflow: hidden;
828
+ }
829
+
830
+ .editor-panel-left.collapsed,
831
+ .editor-panel-right.collapsed {
832
+ width: 0 !important;
833
+ min-width: 0 !important;
834
+ padding: 0 !important;
835
+ opacity: 0;
836
+ pointer-events: none;
837
+ border-width: 0 !important;
838
+ }
839
+
840
+ #btn-toggle-left.active,
841
+ #btn-toggle-right.active,
842
+ #btn-toggle-ai.active {
843
+ background: var(--editor-primary);
844
+ color: white;
845
+ }
846
+
847
+ #btn-code.active {
848
+ background: var(--editor-primary);
849
+ color: white;
850
+ }
851
+
852
+ /* ==================== AI Panel ==================== */
853
+
854
+ .editor-panel-ai {
855
+ width: 320px;
856
+ min-width: 320px;
857
+ height: 100%;
858
+ background: var(--editor-bg, #1a1a1a);
859
+ border-right: 1px solid var(--editor-border, #2d2d2d);
860
+ display: flex;
861
+ flex-direction: column;
862
+ transition: width 0.2s ease, min-width 0.2s ease, opacity 0.2s ease, border-width 0.2s ease;
863
+ overflow: hidden;
864
+ }
865
+
866
+ .editor-panel-ai.collapsed {
867
+ width: 0 !important;
868
+ min-width: 0 !important;
869
+ padding: 0 !important;
870
+ opacity: 0;
871
+ pointer-events: none;
872
+ border-width: 0 !important;
873
+ }
874
+
875
+ .editor-panel-ai .panel-header {
876
+ display: flex;
877
+ align-items: center;
878
+ justify-content: space-between;
879
+ padding: 0.875rem 1rem;
880
+ border-bottom: 1px solid var(--editor-border, #2d2d2d);
881
+ background: var(--editor-surface, #242424);
882
+ }
883
+
884
+ .editor-panel-ai .panel-title {
885
+ display: flex;
886
+ align-items: center;
887
+ gap: 0.5rem;
888
+ font-size: 0.875rem;
889
+ font-weight: 600;
890
+ color: white;
891
+ }
892
+
893
+ .editor-panel-ai .panel-title svg {
894
+ color: var(--editor-primary, #6366f1);
895
+ }
896
+
897
+ .panel-close-btn {
898
+ display: flex;
899
+ align-items: center;
900
+ justify-content: center;
901
+ width: 28px;
902
+ height: 28px;
903
+ background: transparent;
904
+ border: none;
905
+ border-radius: 0.375rem;
906
+ color: var(--editor-text-muted, #9ca3af);
907
+ cursor: pointer;
908
+ transition: all 0.15s ease;
909
+ }
910
+
911
+ .panel-close-btn:hover {
912
+ background: var(--editor-hover, #3d3d3d);
913
+ color: white;
914
+ }
915
+
916
+ .editor-panel-ai .panel-content {
917
+ flex: 1;
918
+ overflow-y: auto;
919
+ }
920
+
921
+ .ai-panel {
922
+ padding: 1rem;
923
+ display: flex;
924
+ flex-direction: column;
925
+ gap: 1rem;
926
+ }
927
+
928
+ .ai-mode-selector h4 {
929
+ font-size: 0.6875rem;
930
+ font-weight: 600;
931
+ text-transform: uppercase;
932
+ letter-spacing: 0.05em;
933
+ color: var(--editor-text-muted, #9ca3af);
934
+ margin-bottom: 0.625rem;
935
+ }
936
+
937
+ .ai-mode-options {
938
+ display: flex;
939
+ gap: 0.5rem;
940
+ }
941
+
942
+ .ai-mode-btn {
943
+ flex: 1;
944
+ display: flex;
945
+ flex-direction: column;
946
+ align-items: center;
947
+ gap: 0.375rem;
948
+ padding: 0.75rem 0.5rem;
949
+ background: var(--editor-surface, #2d2d2d);
950
+ border: 1px solid var(--editor-border, #404040);
951
+ border-radius: 0.5rem;
952
+ color: var(--editor-text-muted, #9ca3af);
953
+ font-size: 0.75rem;
954
+ font-weight: 500;
955
+ cursor: pointer;
956
+ transition: all 0.15s ease;
957
+ }
958
+
959
+ .ai-mode-btn:hover {
960
+ background: var(--editor-hover, #3d3d3d);
961
+ color: white;
962
+ }
963
+
964
+ .ai-mode-btn.active {
965
+ background: rgba(99, 102, 241, 0.15);
966
+ border-color: var(--editor-primary, #6366f1);
967
+ color: var(--editor-primary, #6366f1);
968
+ }
969
+
970
+ .ai-element-info {
971
+ padding: 0.75rem;
972
+ background: var(--editor-surface, #2d2d2d);
973
+ border-radius: 0.5rem;
974
+ }
975
+
976
+ .ai-element-badge {
977
+ display: flex;
978
+ align-items: center;
979
+ justify-content: space-between;
980
+ gap: 0.5rem;
981
+ }
982
+
983
+ .ai-element-badge span {
984
+ font-size: 0.8125rem;
985
+ font-weight: 500;
986
+ color: white;
987
+ font-family: 'SF Mono', Monaco, monospace;
988
+ }
989
+
990
+ .ai-element-select-btn {
991
+ display: flex;
992
+ align-items: center;
993
+ justify-content: center;
994
+ width: 28px;
995
+ height: 28px;
996
+ background: var(--editor-hover, #3d3d3d);
997
+ border: none;
998
+ border-radius: 0.375rem;
999
+ color: var(--editor-text-muted, #9ca3af);
1000
+ cursor: pointer;
1001
+ transition: all 0.15s ease;
1002
+ }
1003
+
1004
+ .ai-element-select-btn:hover {
1005
+ background: var(--editor-primary, #6366f1);
1006
+ color: white;
1007
+ }
1008
+
1009
+ .ai-prompt-area {
1010
+ display: flex;
1011
+ flex-direction: column;
1012
+ gap: 0.75rem;
1013
+ }
1014
+
1015
+ .ai-prompt-area textarea {
1016
+ width: 100%;
1017
+ padding: 0.75rem;
1018
+ background: var(--editor-surface, #2d2d2d);
1019
+ border: 1px solid var(--editor-border, #404040);
1020
+ border-radius: 0.5rem;
1021
+ color: white;
1022
+ font-size: 0.875rem;
1023
+ font-family: inherit;
1024
+ resize: vertical;
1025
+ min-height: 100px;
1026
+ transition: border-color 0.15s ease;
1027
+ }
1028
+
1029
+ .ai-prompt-area textarea:focus {
1030
+ outline: none;
1031
+ border-color: var(--editor-primary, #6366f1);
1032
+ }
1033
+
1034
+ .ai-prompt-area textarea::placeholder {
1035
+ color: var(--editor-text-muted, #9ca3af);
1036
+ }
1037
+
1038
+ .ai-generate-btn {
1039
+ display: flex;
1040
+ align-items: center;
1041
+ justify-content: center;
1042
+ gap: 0.5rem;
1043
+ padding: 0.75rem 1rem;
1044
+ background: var(--editor-primary, #6366f1);
1045
+ border: none;
1046
+ border-radius: 0.5rem;
1047
+ color: white;
1048
+ font-size: 0.875rem;
1049
+ font-weight: 600;
1050
+ cursor: pointer;
1051
+ transition: all 0.15s ease;
1052
+ }
1053
+
1054
+ .ai-generate-btn:hover:not(:disabled) {
1055
+ background: var(--editor-primary-hover, #4f46e5);
1056
+ }
1057
+
1058
+ .ai-generate-btn:disabled {
1059
+ opacity: 0.5;
1060
+ cursor: not-allowed;
1061
+ }
1062
+
1063
+ .ai-coming-soon {
1064
+ display: flex;
1065
+ flex-direction: column;
1066
+ align-items: center;
1067
+ padding: 1.5rem 1rem;
1068
+ text-align: center;
1069
+ color: var(--editor-text-muted, #9ca3af);
1070
+ }
1071
+
1072
+ .ai-coming-soon-badge {
1073
+ display: inline-block;
1074
+ padding: 0.25rem 0.75rem;
1075
+ background: rgba(99, 102, 241, 0.15);
1076
+ border: 1px solid rgba(99, 102, 241, 0.3);
1077
+ border-radius: 9999px;
1078
+ color: var(--editor-primary, #6366f1);
1079
+ font-size: 0.75rem;
1080
+ font-weight: 600;
1081
+ margin-bottom: 0.75rem;
1082
+ }
1083
+
1084
+ .ai-coming-soon p {
1085
+ font-size: 0.8125rem;
1086
+ line-height: 1.5;
1087
+ }
1088
+
1089
+ /* ==================== Editor Layout ==================== */
1090
+
1091
+ .editor-wrapper {
1092
+ display: flex;
1093
+ flex-direction: column;
1094
+ height: calc(100vh - 50px);
1095
+ margin-top: 50px;
1096
+ }
1097
+
1098
+ .editor-main {
1099
+ flex: 1;
1100
+ min-height: 0;
1101
+ display: flex;
1102
+ flex-direction: column;
1103
+ }
1104
+
1105
+ .editor-container {
1106
+ flex: 1;
1107
+ display: flex;
1108
+ min-height: 0;
1109
+ overflow: hidden;
1110
+ position: relative;
1111
+ }
1112
+
1113
+ /* ==================== Canvas ==================== */
1114
+
1115
+ .editor-canvas {
1116
+ flex: 1;
1117
+ position: relative;
1118
+ }
1119
+
1120
+ .add-section-btn {
1121
+ position: absolute;
1122
+ bottom: 1rem;
1123
+ left: 50%;
1124
+ transform: translateX(-50%);
1125
+ display: flex;
1126
+ align-items: center;
1127
+ gap: 0.5rem;
1128
+ padding: 0.625rem 1.25rem;
1129
+ background: var(--editor-primary, #6366f1);
1130
+ color: white;
1131
+ border: none;
1132
+ border-radius: 2rem;
1133
+ font-size: 0.875rem;
1134
+ font-weight: 500;
1135
+ cursor: pointer;
1136
+ box-shadow: 0 4px 12px rgba(99, 102, 241, 0.4);
1137
+ transition: all 0.15s ease;
1138
+ z-index: 10;
1139
+ }
1140
+
1141
+ .add-section-btn:hover {
1142
+ background: var(--editor-primary-hover, #4f46e5);
1143
+ box-shadow: 0 6px 16px rgba(99, 102, 241, 0.5);
1144
+ transform: translateX(-50%) translateY(-2px);
1145
+ }
1146
+
1147
+ .add-section-btn svg {
1148
+ width: 16px;
1149
+ height: 16px;
1150
+ }
1151
+
1152
+ /* ==================== Assets Panel ==================== */
1153
+
1154
+ .assets-panel {
1155
+ display: flex;
1156
+ flex-direction: column;
1157
+ height: 100%;
1158
+ }
1159
+
1160
+ .assets-toolbar {
1161
+ display: flex;
1162
+ gap: 0.5rem;
1163
+ padding: 0.75rem;
1164
+ border-bottom: 1px solid var(--editor-border, #2d2d2d);
1165
+ }
1166
+
1167
+ .assets-upload-btn,
1168
+ .assets-refresh-btn {
1169
+ display: flex;
1170
+ align-items: center;
1171
+ gap: 0.375rem;
1172
+ padding: 0.5rem 0.75rem;
1173
+ background: var(--editor-surface, #2d2d2d);
1174
+ color: var(--editor-text-muted, #9ca3af);
1175
+ border: 1px solid var(--editor-border, #404040);
1176
+ border-radius: 0.375rem;
1177
+ font-size: 0.75rem;
1178
+ font-weight: 500;
1179
+ cursor: pointer;
1180
+ transition: all 0.15s ease;
1181
+ }
1182
+
1183
+ .assets-upload-btn:hover,
1184
+ .assets-refresh-btn:hover {
1185
+ background: var(--editor-hover, #3d3d3d);
1186
+ color: white;
1187
+ }
1188
+
1189
+ .assets-upload-btn:disabled {
1190
+ opacity: 0.6;
1191
+ cursor: not-allowed;
1192
+ }
1193
+
1194
+ .assets-upload-btn {
1195
+ flex: 1;
1196
+ }
1197
+
1198
+ .assets-refresh-btn {
1199
+ padding: 0.5rem;
1200
+ }
1201
+
1202
+ .assets-grid {
1203
+ flex: 1;
1204
+ overflow-y: auto;
1205
+ padding: 0.75rem;
1206
+ display: grid;
1207
+ grid-template-columns: repeat(2, 1fr);
1208
+ gap: 0.5rem;
1209
+ align-content: start;
1210
+ }
1211
+
1212
+ .assets-loading,
1213
+ .assets-empty {
1214
+ grid-column: 1 / -1;
1215
+ display: flex;
1216
+ flex-direction: column;
1217
+ align-items: center;
1218
+ justify-content: center;
1219
+ padding: 2rem 1rem;
1220
+ color: var(--editor-text-muted, #9ca3af);
1221
+ text-align: center;
1222
+ }
1223
+
1224
+ .assets-empty svg {
1225
+ margin-bottom: 0.75rem;
1226
+ opacity: 0.5;
1227
+ }
1228
+
1229
+ .assets-empty p {
1230
+ font-size: 0.875rem;
1231
+ font-weight: 500;
1232
+ margin-bottom: 0.25rem;
1233
+ }
1234
+
1235
+ .assets-empty span {
1236
+ font-size: 0.75rem;
1237
+ opacity: 0.7;
1238
+ }
1239
+
1240
+ .asset-item {
1241
+ position: relative;
1242
+ aspect-ratio: 1;
1243
+ border-radius: 0.375rem;
1244
+ overflow: hidden;
1245
+ background: var(--editor-surface, #2d2d2d);
1246
+ cursor: grab;
1247
+ border: 2px solid transparent;
1248
+ transition: all 0.15s ease;
1249
+ }
1250
+
1251
+ .asset-item:hover {
1252
+ border-color: var(--editor-primary, #6366f1);
1253
+ }
1254
+
1255
+ .asset-item img {
1256
+ width: 100%;
1257
+ height: 100%;
1258
+ object-fit: cover;
1259
+ }
1260
+
1261
+ .asset-item-overlay {
1262
+ position: absolute;
1263
+ inset: 0;
1264
+ background: rgba(0, 0, 0, 0.6);
1265
+ display: flex;
1266
+ align-items: center;
1267
+ justify-content: center;
1268
+ opacity: 0;
1269
+ transition: opacity 0.15s ease;
1270
+ }
1271
+
1272
+ .asset-item:hover .asset-item-overlay {
1273
+ opacity: 1;
1274
+ }
1275
+
1276
+ .asset-insert-btn {
1277
+ display: flex;
1278
+ align-items: center;
1279
+ justify-content: center;
1280
+ width: 32px;
1281
+ height: 32px;
1282
+ background: var(--editor-primary, #6366f1);
1283
+ color: white;
1284
+ border: none;
1285
+ border-radius: 50%;
1286
+ cursor: pointer;
1287
+ transition: all 0.15s ease;
1288
+ }
1289
+
1290
+ .asset-insert-btn:hover {
1291
+ background: var(--editor-primary-hover, #4f46e5);
1292
+ transform: scale(1.1);
1293
+ }
1294
+
1295
+ /* Spin animation for upload button */
1296
+ @keyframes spin {
1297
+ from { transform: rotate(0deg); }
1298
+ to { transform: rotate(360deg); }
1299
+ }
1300
+
1301
+ .spin {
1302
+ animation: spin 1s linear infinite;
1303
+ }
1304
+
1305
+ /* ==================== Empty Section Placeholder ==================== */
1306
+
1307
+ /* Style for empty sections in the editor canvas */
1308
+ .gjs-frame [data-gjs-type="section"]:empty,
1309
+ .gjs-frame .ac-section:empty,
1310
+ .gjs-frame section:empty {
1311
+ min-height: 100px !important;
1312
+ background-color: #fef2f2 !important;
1313
+ border: 2px dashed #fca5a5 !important;
1314
+ display: flex !important;
1315
+ align-items: center !important;
1316
+ justify-content: center !important;
1317
+ }
1318
+
1319
+ .gjs-frame [data-gjs-type="section"]:empty::before,
1320
+ .gjs-frame .ac-section:empty::before,
1321
+ .gjs-frame section:empty::before {
1322
+ content: "Empty section - drag content here";
1323
+ color: #f87171;
1324
+ font-size: 14px;
1325
+ font-weight: 500;
1326
+ }
1327
+
1328
+ /* ==================== Code Panel ==================== */
1329
+
1330
+ .editor-code-panel {
1331
+ height: 300px;
1332
+ min-height: 150px;
1333
+ max-height: 70vh;
1334
+ background: #1e1e1e;
1335
+ border-top: 1px solid var(--editor-border);
1336
+ display: none;
1337
+ flex-direction: column;
1338
+ flex-shrink: 0;
1339
+ position: relative;
1340
+ }
1341
+
1342
+ .editor-code-panel.open {
1343
+ display: flex;
1344
+ }
1345
+
1346
+ .code-panel-header {
1347
+ display: flex;
1348
+ justify-content: space-between;
1349
+ align-items: center;
1350
+ padding: 0 0.75rem;
1351
+ background: #252526;
1352
+ border-bottom: 1px solid #3d3d3d;
1353
+ height: 36px;
1354
+ flex-shrink: 0;
1355
+ }
1356
+
1357
+ .code-panel-tabs {
1358
+ display: flex;
1359
+ gap: 0;
1360
+ }
1361
+
1362
+ .code-panel-tab {
1363
+ padding: 0.5rem 1rem;
1364
+ background: transparent;
1365
+ border: none;
1366
+ color: #999;
1367
+ font-size: 0.75rem;
1368
+ cursor: pointer;
1369
+ border-bottom: 2px solid transparent;
1370
+ margin-bottom: -1px;
1371
+ }
1372
+
1373
+ .code-panel-tab:hover {
1374
+ color: #e5e5e5;
1375
+ }
1376
+
1377
+ .code-panel-tab.active {
1378
+ color: #e5e5e5;
1379
+ border-bottom-color: #3b82f6;
1380
+ }
1381
+
1382
+ .code-panel-actions {
1383
+ display: flex;
1384
+ align-items: center;
1385
+ gap: 0.5rem;
1386
+ }
1387
+
1388
+ .code-status {
1389
+ font-size: 0.6875rem;
1390
+ padding: 0.25rem 0.5rem;
1391
+ border-radius: 0.25rem;
1392
+ }
1393
+
1394
+ .code-status.synced {
1395
+ color: #22c55e;
1396
+ }
1397
+
1398
+ .code-status.modified {
1399
+ color: #f59e0b;
1400
+ }
1401
+
1402
+ .code-panel-btn {
1403
+ padding: 0.25rem 0.625rem;
1404
+ background: #3d3d3d;
1405
+ color: #e5e5e5;
1406
+ border: none;
1407
+ border-radius: 0.25rem;
1408
+ font-size: 0.6875rem;
1409
+ cursor: pointer;
1410
+ display: flex;
1411
+ align-items: center;
1412
+ gap: 0.25rem;
1413
+ }
1414
+
1415
+ .code-panel-btn:hover {
1416
+ background: #4d4d4d;
1417
+ }
1418
+
1419
+ .code-panel-btn.primary {
1420
+ background: #3b82f6;
1421
+ color: white;
1422
+ }
1423
+
1424
+ .code-panel-btn.primary:hover {
1425
+ background: #2563eb;
1426
+ }
1427
+
1428
+ .code-panel-resize {
1429
+ height: 4px;
1430
+ background: #252526;
1431
+ cursor: ns-resize;
1432
+ position: absolute;
1433
+ top: 0;
1434
+ left: 0;
1435
+ right: 0;
1436
+ z-index: 10;
1437
+ }
1438
+
1439
+ .code-panel-resize:hover {
1440
+ background: #3b82f6;
1441
+ }
1442
+
1443
+ .code-panel-content {
1444
+ flex: 1;
1445
+ position: relative;
1446
+ overflow: hidden;
1447
+ }
1448
+
1449
+ .monaco-container {
1450
+ position: absolute;
1451
+ top: 0;
1452
+ left: 0;
1453
+ width: 100%;
1454
+ height: 100%;
1455
+ }
1456
+
1457
+ /* ==================== Component Mode ==================== */
1458
+
1459
+ .code-panel-mode {
1460
+ display: flex;
1461
+ align-items: center;
1462
+ gap: 0.75rem;
1463
+ margin-left: 1rem;
1464
+ padding-left: 1rem;
1465
+ border-left: 1px solid #3d3d3d;
1466
+ }
1467
+
1468
+ .mode-badge {
1469
+ display: flex;
1470
+ align-items: center;
1471
+ gap: 0.375rem;
1472
+ padding: 0.25rem 0.625rem;
1473
+ background: #7c3aed;
1474
+ color: white;
1475
+ border-radius: 0.25rem;
1476
+ font-size: 0.6875rem;
1477
+ font-weight: 500;
1478
+ }
1479
+
1480
+ .mode-badge svg {
1481
+ opacity: 0.8;
1482
+ }
1483
+
1484
+ /* ==================== GrapeJS Toolbar ==================== */
1485
+
1486
+ .gjs-toolbar {
1487
+ background: var(--editor-surface) !important;
1488
+ border: 1px solid var(--editor-border) !important;
1489
+ border-radius: var(--editor-radius) !important;
1490
+ padding: 4px !important;
1491
+ display: inline-flex !important;
1492
+ flex-direction: row !important;
1493
+ flex-wrap: nowrap !important;
1494
+ align-items: center !important;
1495
+ gap: 2px !important;
1496
+ box-shadow: var(--editor-shadow-md) !important;
1497
+ z-index: 10 !important;
1498
+ white-space: nowrap !important;
1499
+ width: auto !important;
1500
+ max-width: none !important;
1501
+ }
1502
+
1503
+ /* Hide empty toolbar (appears as a dot/circle) */
1504
+ .gjs-toolbar:empty {
1505
+ display: none !important;
1506
+ opacity: 0 !important;
1507
+ visibility: hidden !important;
1508
+ pointer-events: none !important;
1509
+ }
1510
+
1511
+ .gjs-toolbar .gjs-toolbar-item {
1512
+ cursor: pointer;
1513
+ padding: 6px 8px !important;
1514
+ border-radius: 4px !important;
1515
+ color: var(--editor-text) !important;
1516
+ display: inline-flex !important;
1517
+ align-items: center !important;
1518
+ justify-content: center !important;
1519
+ transition: background 0.15s ease, color 0.15s ease !important;
1520
+ flex-shrink: 0 !important;
1521
+ float: none !important;
1522
+ clear: none !important;
1523
+ }
1524
+
1525
+ .gjs-toolbar .gjs-toolbar-item:hover {
1526
+ background: var(--editor-surface-hover) !important;
1527
+ color: var(--editor-primary) !important;
1528
+ }
1529
+
1530
+ .gjs-toolbar .gjs-toolbar-item .fa-code {
1531
+ font-size: 12px;
1532
+ }
1533
+
1534
+ .gjs-toolbar .gjs-toolbar-item.toolbar-icon-btn {
1535
+ display: flex !important;
1536
+ align-items: center !important;
1537
+ justify-content: center !important;
1538
+ }
1539
+
1540
+ .gjs-toolbar .gjs-toolbar-item.toolbar-icon-btn svg {
1541
+ width: 14px !important;
1542
+ height: 14px !important;
1543
+ }
1544
+
1545
+ .gjs-toolbar .gjs-toolbar-item.toolbar-ai-btn:hover {
1546
+ color: var(--editor-primary) !important;
1547
+ }
1548
+
1549
+ /* Menu button styling - toolbar item with the ⋮ label */
1550
+ .gjs-toolbar .gjs-toolbar-item.toolbar-menu-btn {
1551
+ font-size: 16px !important;
1552
+ font-weight: bold !important;
1553
+ line-height: 1 !important;
1554
+ padding: 4px 6px !important;
1555
+ min-width: 24px !important;
1556
+ min-height: 24px !important;
1557
+ font-family: system-ui, -apple-system, sans-serif !important;
1558
+ }
1559
+
1560
+ /* Hide empty spans inside toolbar items (GrapeJS adds them for icons) */
1561
+ .gjs-toolbar .gjs-toolbar-item span:empty {
1562
+ display: none !important;
1563
+ }
1564
+
1565
+ /* Style for the icon span inside toolbar items */
1566
+ .gjs-toolbar .gjs-toolbar-item span.fa {
1567
+ font-size: 12px !important;
1568
+ }
1569
+
1570
+ /* Force all toolbar children to stay inline */
1571
+ .gjs-toolbar > * {
1572
+ display: inline-flex !important;
1573
+ float: none !important;
1574
+ clear: none !important;
1575
+ }
1576
+
1577
+ /* ==================== GrapeJS Rich Text Editor Toolbar ==================== */
1578
+
1579
+ /* Hide RTE toolbar via class (controlled by JS) */
1580
+ .gjs-rte-toolbar.ac-rte-hidden {
1581
+ display: none !important;
1582
+ opacity: 0 !important;
1583
+ visibility: hidden !important;
1584
+ pointer-events: none !important;
1585
+ }
1586
+
1587
+ /* Also hide when empty (CSS fallback) */
1588
+ .gjs-rte-toolbar:empty {
1589
+ display: none !important;
1590
+ opacity: 0 !important;
1591
+ visibility: hidden !important;
1592
+ pointer-events: none !important;
1593
+ }
1594
+
1595
+ /* Fixed position toolbar at top of canvas when editing text */
1596
+ .gjs-rte-toolbar {
1597
+ position: fixed !important;
1598
+ top: 62px !important; /* Below the header (52px) + spacing */
1599
+ left: 50% !important;
1600
+ transform: translateX(-50%) !important;
1601
+ background: var(--editor-surface) !important;
1602
+ border: 1px solid var(--editor-border) !important;
1603
+ border-radius: var(--editor-radius-lg) !important;
1604
+ box-shadow: var(--editor-shadow-md) !important;
1605
+ padding: 0.375rem 0.5rem !important;
1606
+ display: flex !important;
1607
+ align-items: center !important;
1608
+ gap: 0.25rem !important;
1609
+ z-index: 100 !important;
1610
+ white-space: nowrap !important;
1611
+ min-width: 50px !important;
1612
+ min-height: 30px !important;
1613
+ animation: rteToolbarSlideIn 0.15s ease !important;
1614
+ }
1615
+
1616
+ @keyframes rteToolbarSlideIn {
1617
+ from {
1618
+ opacity: 0;
1619
+ transform: translateX(-50%) translateY(-10px);
1620
+ }
1621
+ to {
1622
+ opacity: 1;
1623
+ transform: translateX(-50%) translateY(0);
1624
+ }
1625
+ }
1626
+
1627
+ /* RTE toolbar action buttons */
1628
+ .gjs-rte-toolbar .gjs-rte-action {
1629
+ display: inline-flex !important;
1630
+ align-items: center !important;
1631
+ justify-content: center !important;
1632
+ width: 32px !important;
1633
+ height: 32px !important;
1634
+ padding: 0 !important;
1635
+ background: transparent !important;
1636
+ border: none !important;
1637
+ border-radius: var(--editor-radius) !important;
1638
+ color: var(--editor-text) !important;
1639
+ font-size: 14px !important;
1640
+ cursor: pointer !important;
1641
+ transition: all 0.15s ease !important;
1642
+ }
1643
+
1644
+ .gjs-rte-toolbar .gjs-rte-action:hover {
1645
+ background: var(--editor-surface-hover) !important;
1646
+ color: var(--editor-primary) !important;
1647
+ }
1648
+
1649
+ .gjs-rte-toolbar .gjs-rte-action.gjs-rte-active {
1650
+ background: var(--editor-primary) !important;
1651
+ color: white !important;
1652
+ }
1653
+
1654
+ /* Divider between action groups */
1655
+ .gjs-rte-toolbar .gjs-rte-separator,
1656
+ .gjs-rte-toolbar [class*="separator"] {
1657
+ width: 1px !important;
1658
+ height: 20px !important;
1659
+ background: var(--editor-border) !important;
1660
+ margin: 0 0.375rem !important;
1661
+ }
1662
+
1663
+ /* Font family select */
1664
+ .gjs-rte-toolbar select {
1665
+ background: var(--editor-bg) !important;
1666
+ border: 1px solid var(--editor-border) !important;
1667
+ border-radius: var(--editor-radius) !important;
1668
+ color: var(--editor-text) !important;
1669
+ padding: 0.375rem 0.5rem !important;
1670
+ font-size: 0.75rem !important;
1671
+ cursor: pointer !important;
1672
+ min-width: 100px !important;
1673
+ }
1674
+
1675
+ .gjs-rte-toolbar select:hover {
1676
+ border-color: var(--editor-border-light) !important;
1677
+ }
1678
+
1679
+ .gjs-rte-toolbar select:focus {
1680
+ outline: none !important;
1681
+ border-color: var(--editor-primary) !important;
1682
+ box-shadow: 0 0 0 2px var(--editor-primary-light) !important;
1683
+ }
1684
+
1685
+ /* Color picker in RTE */
1686
+ .gjs-rte-toolbar input[type="color"] {
1687
+ width: 28px !important;
1688
+ height: 28px !important;
1689
+ padding: 2px !important;
1690
+ border: 1px solid var(--editor-border) !important;
1691
+ border-radius: var(--editor-radius) !important;
1692
+ cursor: pointer !important;
1693
+ background: var(--editor-bg) !important;
1694
+ }
1695
+
1696
+ .gjs-rte-toolbar input[type="color"]:hover {
1697
+ border-color: var(--editor-primary) !important;
1698
+ }
1699
+
1700
+ /* Link input in RTE */
1701
+ .gjs-rte-toolbar input[type="text"] {
1702
+ background: var(--editor-bg) !important;
1703
+ border: 1px solid var(--editor-border) !important;
1704
+ border-radius: var(--editor-radius) !important;
1705
+ color: var(--editor-text) !important;
1706
+ padding: 0.375rem 0.5rem !important;
1707
+ font-size: 0.75rem !important;
1708
+ min-width: 150px !important;
1709
+ }
1710
+
1711
+ .gjs-rte-toolbar input[type="text"]:focus {
1712
+ outline: none !important;
1713
+ border-color: var(--editor-primary) !important;
1714
+ box-shadow: 0 0 0 2px var(--editor-primary-light) !important;
1715
+ }
1716
+
1717
+ /* ==================== Component Context Menu ==================== */
1718
+
1719
+ .component-context-menu {
1720
+ background: var(--editor-surface);
1721
+ border: 1px solid var(--editor-border);
1722
+ border-radius: var(--editor-radius);
1723
+ box-shadow: var(--editor-shadow-md);
1724
+ min-width: 160px;
1725
+ padding: 0.375rem;
1726
+ z-index: 10000;
1727
+ animation: contextMenuFadeIn 0.15s ease;
1728
+ }
1729
+
1730
+ @keyframes contextMenuFadeIn {
1731
+ from {
1732
+ opacity: 0;
1733
+ transform: translateY(-5px);
1734
+ }
1735
+ to {
1736
+ opacity: 1;
1737
+ transform: translateY(0);
1738
+ }
1739
+ }
1740
+
1741
+ .context-menu-item {
1742
+ display: flex;
1743
+ align-items: center;
1744
+ gap: 0.625rem;
1745
+ padding: 0.5rem 0.75rem;
1746
+ font-size: 0.8125rem;
1747
+ color: var(--editor-text);
1748
+ cursor: pointer;
1749
+ border-radius: calc(var(--editor-radius) - 2px);
1750
+ transition: background 0.15s ease;
1751
+ }
1752
+
1753
+ .context-menu-item:hover {
1754
+ background: var(--editor-surface-hover);
1755
+ }
1756
+
1757
+ .context-menu-item svg {
1758
+ flex-shrink: 0;
1759
+ opacity: 0.7;
1760
+ }
1761
+
1762
+ .context-menu-item:hover svg {
1763
+ opacity: 1;
1764
+ }
1765
+
1766
+ .context-menu-item-danger {
1767
+ color: var(--editor-danger);
1768
+ }
1769
+
1770
+ .context-menu-item-danger:hover {
1771
+ background: rgba(239, 68, 68, 0.15);
1772
+ }
1773
+
1774
+ .context-menu-divider {
1775
+ height: 1px;
1776
+ background: var(--editor-border);
1777
+ margin: 0.375rem 0;
1778
+ }
1779
+
1780
+ /* ==================== Panel Placeholder ==================== */
1781
+
1782
+ .panel-placeholder {
1783
+ display: flex;
1784
+ flex-direction: column;
1785
+ align-items: center;
1786
+ justify-content: center;
1787
+ height: 100%;
1788
+ min-height: 200px;
1789
+ padding: 2rem;
1790
+ text-align: center;
1791
+ color: var(--editor-text-muted);
1792
+ }
1793
+
1794
+ .panel-placeholder-icon {
1795
+ margin-bottom: 1rem;
1796
+ opacity: 0.5;
1797
+ }
1798
+
1799
+ .panel-placeholder-icon svg {
1800
+ width: 48px;
1801
+ height: 48px;
1802
+ }
1803
+
1804
+ .panel-placeholder h3 {
1805
+ font-size: 0.875rem;
1806
+ font-weight: 600;
1807
+ color: var(--editor-text);
1808
+ margin-bottom: 0.25rem;
1809
+ }
1810
+
1811
+ .panel-placeholder p {
1812
+ font-size: 0.75rem;
1813
+ color: var(--editor-text-muted);
1814
+ }
1815
+
1816
+ /* ==================== AI Panel ==================== */
1817
+
1818
+ .ai-panel {
1819
+ padding: 1rem;
1820
+ }
1821
+
1822
+ .ai-mode-selector h4 {
1823
+ font-size: 0.75rem;
1824
+ font-weight: 600;
1825
+ color: var(--editor-text);
1826
+ margin-bottom: 0.75rem;
1827
+ text-transform: uppercase;
1828
+ letter-spacing: 0.05em;
1829
+ }
1830
+
1831
+ .ai-mode-options {
1832
+ display: flex;
1833
+ flex-direction: column;
1834
+ gap: 0.5rem;
1835
+ }
1836
+
1837
+ .ai-mode-btn {
1838
+ display: flex;
1839
+ align-items: center;
1840
+ gap: 0.75rem;
1841
+ padding: 0.75rem;
1842
+ background: var(--editor-bg);
1843
+ border: 1px solid var(--editor-border);
1844
+ border-radius: 0.5rem;
1845
+ color: var(--editor-text-muted);
1846
+ cursor: pointer;
1847
+ transition: all 0.15s ease;
1848
+ text-align: left;
1849
+ }
1850
+
1851
+ .ai-mode-btn:hover {
1852
+ border-color: var(--editor-text-muted);
1853
+ color: var(--editor-text);
1854
+ }
1855
+
1856
+ .ai-mode-btn.active {
1857
+ border-color: var(--editor-primary);
1858
+ background: rgba(59, 130, 246, 0.1);
1859
+ color: var(--editor-text);
1860
+ }
1861
+
1862
+ .ai-mode-btn svg {
1863
+ flex-shrink: 0;
1864
+ opacity: 0.7;
1865
+ }
1866
+
1867
+ .ai-mode-btn.active svg {
1868
+ opacity: 1;
1869
+ color: var(--editor-primary);
1870
+ }
1871
+
1872
+ .ai-mode-btn span {
1873
+ font-size: 0.8125rem;
1874
+ font-weight: 500;
1875
+ }
1876
+
1877
+ .ai-element-info {
1878
+ margin-top: 1rem;
1879
+ padding-top: 1rem;
1880
+ border-top: 1px solid var(--editor-border);
1881
+ }
1882
+
1883
+ .ai-element-badge {
1884
+ display: flex;
1885
+ align-items: center;
1886
+ justify-content: space-between;
1887
+ padding: 0.5rem 0.75rem;
1888
+ background: var(--editor-bg);
1889
+ border: 1px solid var(--editor-border);
1890
+ border-radius: 0.375rem;
1891
+ }
1892
+
1893
+ .ai-element-badge span {
1894
+ font-size: 0.75rem;
1895
+ color: var(--editor-text);
1896
+ font-family: monospace;
1897
+ }
1898
+
1899
+ .ai-element-select-btn {
1900
+ display: flex;
1901
+ align-items: center;
1902
+ justify-content: center;
1903
+ padding: 0.375rem;
1904
+ background: var(--editor-border);
1905
+ border: none;
1906
+ border-radius: 0.25rem;
1907
+ color: var(--editor-text);
1908
+ cursor: pointer;
1909
+ }
1910
+
1911
+ .ai-element-select-btn:hover {
1912
+ background: var(--editor-primary);
1913
+ color: white;
1914
+ }
1915
+
1916
+ .ai-coming-soon {
1917
+ display: flex;
1918
+ flex-direction: column;
1919
+ align-items: center;
1920
+ padding: 2rem 1rem;
1921
+ margin-top: 1.5rem;
1922
+ text-align: center;
1923
+ color: var(--editor-text-muted);
1924
+ border-top: 1px solid var(--editor-border);
1925
+ }
1926
+
1927
+ .ai-coming-soon .panel-placeholder-icon {
1928
+ margin-bottom: 0.75rem;
1929
+ }
1930
+
1931
+ .ai-coming-soon .panel-placeholder-icon svg {
1932
+ width: 32px;
1933
+ height: 32px;
1934
+ }
1935
+
1936
+ .ai-coming-soon p {
1937
+ font-size: 0.75rem;
1938
+ }
1939
+
1940
+ /* ==================== Toast Notification ==================== */
1941
+
1942
+ .editor-toast {
1943
+ position: fixed;
1944
+ bottom: 1rem;
1945
+ right: 1rem;
1946
+ padding: 0.75rem 1rem;
1947
+ border-radius: 0.375rem;
1948
+ font-size: 0.8125rem;
1949
+ font-weight: 500;
1950
+ z-index: 1000;
1951
+ display: none;
1952
+ animation: slideIn 0.3s ease;
1953
+ }
1954
+
1955
+ .editor-toast.show {
1956
+ display: block;
1957
+ }
1958
+
1959
+ .editor-toast.success {
1960
+ background: var(--editor-success, #22c55e);
1961
+ color: white;
1962
+ }
1963
+
1964
+ .editor-toast.error {
1965
+ background: var(--editor-danger, #ef4444);
1966
+ color: white;
1967
+ }
1968
+
1969
+ @keyframes slideIn {
1970
+ from {
1971
+ transform: translateY(100%);
1972
+ opacity: 0;
1973
+ }
1974
+ to {
1975
+ transform: translateY(0);
1976
+ opacity: 1;
1977
+ }
1978
+ }
1979
+
1980
+ /* ==================== Loading Overlay ==================== */
1981
+
1982
+ .editor-loading {
1983
+ position: fixed;
1984
+ top: 0;
1985
+ left: 0;
1986
+ right: 0;
1987
+ bottom: 0;
1988
+ background: rgba(0, 0, 0, 0.7);
1989
+ display: flex;
1990
+ align-items: center;
1991
+ justify-content: center;
1992
+ z-index: 1000;
1993
+ }
1994
+
1995
+ .editor-loading.hidden {
1996
+ display: none;
1997
+ }
1998
+
1999
+ .editor-loading-spinner {
2000
+ width: 40px;
2001
+ height: 40px;
2002
+ border: 3px solid var(--editor-border);
2003
+ border-top-color: var(--editor-primary);
2004
+ border-radius: 50%;
2005
+ animation: spin 1s linear infinite;
2006
+ }
2007
+
2008
+ @keyframes spin {
2009
+ to { transform: rotate(360deg); }
2010
+ }
2011
+
2012
+ /* ==================== AI Panel - Redesigned ==================== */
2013
+
2014
+ /* Panel Container - width/transition defined in main panel section */
2015
+
2016
+ /* Panel Header */
2017
+ .ai-panel-header {
2018
+ display: flex;
2019
+ align-items: center;
2020
+ justify-content: space-between;
2021
+ padding: 0.875rem 1rem;
2022
+ background: linear-gradient(180deg, var(--editor-surface) 0%, var(--editor-bg) 100%);
2023
+ border-bottom: 1px solid var(--editor-border);
2024
+ flex-shrink: 0;
2025
+ }
2026
+
2027
+ .ai-panel-title {
2028
+ display: flex;
2029
+ align-items: center;
2030
+ gap: 0.75rem;
2031
+ }
2032
+
2033
+ .ai-panel-icon {
2034
+ width: 36px;
2035
+ height: 36px;
2036
+ display: flex;
2037
+ align-items: center;
2038
+ justify-content: center;
2039
+ background: var(--editor-primary-light);
2040
+ border-radius: 10px;
2041
+ color: var(--editor-primary);
2042
+ }
2043
+
2044
+ .ai-panel-title-text {
2045
+ display: flex;
2046
+ flex-direction: column;
2047
+ gap: 0.125rem;
2048
+ }
2049
+
2050
+ .ai-panel-title-text span:first-child {
2051
+ font-size: 0.875rem;
2052
+ font-weight: 600;
2053
+ color: var(--editor-text);
2054
+ letter-spacing: -0.01em;
2055
+ }
2056
+
2057
+ .ai-status-indicator {
2058
+ font-size: 0.625rem;
2059
+ font-weight: 500;
2060
+ color: var(--editor-text-muted);
2061
+ text-transform: uppercase;
2062
+ letter-spacing: 0.03em;
2063
+ }
2064
+
2065
+ .ai-status-indicator.configured {
2066
+ color: var(--editor-success);
2067
+ }
2068
+
2069
+ .ai-panel-close {
2070
+ width: 32px;
2071
+ height: 32px;
2072
+ display: flex;
2073
+ align-items: center;
2074
+ justify-content: center;
2075
+ background: transparent;
2076
+ border: none;
2077
+ border-radius: 8px;
2078
+ color: var(--editor-text-muted);
2079
+ cursor: pointer;
2080
+ transition: all 0.15s ease;
2081
+ }
2082
+
2083
+ .ai-panel-close:hover {
2084
+ background: var(--editor-surface-hover);
2085
+ color: var(--editor-text);
2086
+ }
2087
+
2088
+ /* Panel Body */
2089
+ .ai-panel-body {
2090
+ flex: 1;
2091
+ display: flex;
2092
+ flex-direction: column;
2093
+ overflow: hidden;
2094
+ }
2095
+
2096
+ /* Empty State */
2097
+ .ai-empty-state {
2098
+ flex: 1;
2099
+ display: flex;
2100
+ flex-direction: column;
2101
+ align-items: center;
2102
+ justify-content: center;
2103
+ padding: 2rem;
2104
+ text-align: center;
2105
+ position: relative;
2106
+ }
2107
+
2108
+ .ai-empty-state-glow {
2109
+ position: absolute;
2110
+ width: 120px;
2111
+ height: 120px;
2112
+ background: radial-gradient(circle, var(--editor-primary-light) 0%, transparent 70%);
2113
+ opacity: 0.5;
2114
+ animation: pulseGlow 3s ease-in-out infinite;
2115
+ }
2116
+
2117
+ @keyframes pulseGlow {
2118
+ 0%, 100% { transform: scale(1); opacity: 0.5; }
2119
+ 50% { transform: scale(1.2); opacity: 0.3; }
2120
+ }
2121
+
2122
+ .ai-empty-state-icon {
2123
+ width: 72px;
2124
+ height: 72px;
2125
+ display: flex;
2126
+ align-items: center;
2127
+ justify-content: center;
2128
+ background: var(--editor-bg);
2129
+ border: 1px solid var(--editor-border);
2130
+ border-radius: 20px;
2131
+ color: var(--editor-text-muted);
2132
+ margin-bottom: 1.25rem;
2133
+ position: relative;
2134
+ }
2135
+
2136
+ .ai-empty-state h3 {
2137
+ font-size: 1rem;
2138
+ font-weight: 600;
2139
+ color: var(--editor-text);
2140
+ margin: 0 0 0.5rem 0;
2141
+ }
2142
+
2143
+ .ai-empty-state p {
2144
+ font-size: 0.8125rem;
2145
+ color: var(--editor-text-muted);
2146
+ margin: 0 0 1.5rem 0;
2147
+ max-width: 220px;
2148
+ line-height: 1.5;
2149
+ }
2150
+
2151
+ .ai-empty-state-btn {
2152
+ display: inline-flex;
2153
+ align-items: center;
2154
+ gap: 0.5rem;
2155
+ padding: 0.625rem 1rem;
2156
+ font-size: 0.8125rem;
2157
+ font-weight: 500;
2158
+ color: white;
2159
+ background: var(--editor-primary);
2160
+ border: none;
2161
+ border-radius: 8px;
2162
+ text-decoration: none;
2163
+ transition: all 0.2s ease;
2164
+ }
2165
+
2166
+ .ai-empty-state-btn:hover {
2167
+ background: var(--editor-primary-hover);
2168
+ transform: translateY(-1px);
2169
+ box-shadow: 0 4px 12px rgba(99, 102, 241, 0.3);
2170
+ }
2171
+
2172
+ /* Tabs */
2173
+ .ai-tabs {
2174
+ display: flex;
2175
+ padding: 0.5rem;
2176
+ gap: 0.25rem;
2177
+ background: var(--editor-bg);
2178
+ border-bottom: 1px solid var(--editor-border);
2179
+ flex-shrink: 0;
2180
+ }
2181
+
2182
+ .ai-tab {
2183
+ flex: 1;
2184
+ display: flex;
2185
+ align-items: center;
2186
+ justify-content: center;
2187
+ gap: 0.5rem;
2188
+ padding: 0.625rem 0.5rem;
2189
+ font-size: 0.75rem;
2190
+ font-weight: 500;
2191
+ color: var(--editor-text-muted);
2192
+ background: transparent;
2193
+ border: none;
2194
+ border-radius: 8px;
2195
+ cursor: pointer;
2196
+ transition: all 0.2s ease;
2197
+ position: relative;
2198
+ }
2199
+
2200
+ .ai-tab::after {
2201
+ content: '';
2202
+ position: absolute;
2203
+ bottom: -0.5rem;
2204
+ left: 50%;
2205
+ transform: translateX(-50%);
2206
+ width: 0;
2207
+ height: 2px;
2208
+ background: var(--editor-primary);
2209
+ border-radius: 1px;
2210
+ transition: width 0.2s ease;
2211
+ }
2212
+
2213
+ .ai-tab:hover {
2214
+ color: var(--editor-text);
2215
+ background: var(--editor-surface-hover);
2216
+ }
2217
+
2218
+ .ai-tab.active {
2219
+ color: var(--editor-primary);
2220
+ background: var(--editor-primary-light);
2221
+ }
2222
+
2223
+ .ai-tab.active::after {
2224
+ width: 20px;
2225
+ }
2226
+
2227
+ .ai-tab.disabled {
2228
+ opacity: 0.4;
2229
+ cursor: not-allowed;
2230
+ }
2231
+
2232
+ .ai-tab-icon {
2233
+ display: flex;
2234
+ }
2235
+
2236
+ .ai-tab-label {
2237
+ font-size: 0.6875rem;
2238
+ text-transform: uppercase;
2239
+ letter-spacing: 0.04em;
2240
+ }
2241
+
2242
+ /* Tab Panels */
2243
+ .ai-tab-panel {
2244
+ display: none;
2245
+ flex: 1;
2246
+ flex-direction: column;
2247
+ overflow: hidden;
2248
+ padding: 0.75rem;
2249
+ gap: 0.75rem;
2250
+ }
2251
+
2252
+ .ai-tab-panel.active {
2253
+ display: flex;
2254
+ }
2255
+
2256
+ /* Mode Toggle */
2257
+ .ai-mode-toggle {
2258
+ display: flex;
2259
+ padding: 0.25rem;
2260
+ background: var(--editor-bg);
2261
+ border-radius: 10px;
2262
+ position: relative;
2263
+ flex-shrink: 0;
2264
+ }
2265
+
2266
+ .ai-mode-toggle .ai-mode-btn {
2267
+ flex: 1;
2268
+ display: flex;
2269
+ align-items: center;
2270
+ justify-content: center;
2271
+ gap: 0.375rem;
2272
+ padding: 0.5rem 0.75rem;
2273
+ font-size: 0.75rem;
2274
+ font-weight: 500;
2275
+ color: var(--editor-text-muted);
2276
+ background: transparent;
2277
+ border: none;
2278
+ border-radius: 8px;
2279
+ cursor: pointer;
2280
+ transition: color 0.2s ease;
2281
+ position: relative;
2282
+ z-index: 1;
2283
+ }
2284
+
2285
+ .ai-mode-toggle .ai-mode-btn:hover {
2286
+ color: var(--editor-text);
2287
+ }
2288
+
2289
+ .ai-mode-toggle .ai-mode-btn.active {
2290
+ color: var(--editor-text);
2291
+ }
2292
+
2293
+ .ai-mode-toggle .ai-mode-btn svg {
2294
+ flex-shrink: 0;
2295
+ opacity: 1;
2296
+ color: inherit;
2297
+ }
2298
+
2299
+ .ai-mode-slider {
2300
+ position: absolute;
2301
+ top: 0.25rem;
2302
+ left: 0.25rem;
2303
+ width: calc(50% - 0.25rem);
2304
+ height: calc(100% - 0.5rem);
2305
+ background: var(--editor-surface);
2306
+ border-radius: 8px;
2307
+ box-shadow: var(--editor-shadow-sm);
2308
+ transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);
2309
+ }
2310
+
2311
+ .ai-mode-toggle .ai-mode-btn.active[data-mode="element"] ~ .ai-mode-slider {
2312
+ transform: translateX(100%);
2313
+ }
2314
+
2315
+ /* Element Indicator */
2316
+ .ai-element-indicator {
2317
+ display: flex;
2318
+ align-items: center;
2319
+ gap: 0.5rem;
2320
+ padding: 0.5rem 0.75rem;
2321
+ background: var(--editor-bg);
2322
+ border: 1px solid var(--editor-border);
2323
+ border-radius: 8px;
2324
+ flex-shrink: 0;
2325
+ }
2326
+
2327
+ .ai-element-label {
2328
+ font-size: 0.6875rem;
2329
+ font-weight: 500;
2330
+ color: var(--editor-text-muted);
2331
+ text-transform: uppercase;
2332
+ letter-spacing: 0.03em;
2333
+ }
2334
+
2335
+ .ai-element-indicator code {
2336
+ font-size: 0.75rem;
2337
+ font-family: 'SF Mono', 'Monaco', 'Inconsolata', monospace;
2338
+ color: var(--editor-primary);
2339
+ background: var(--editor-primary-light);
2340
+ padding: 0.125rem 0.375rem;
2341
+ border-radius: 4px;
2342
+ }
2343
+
2344
+ /* Model Row */
2345
+ .ai-model-row {
2346
+ display: flex;
2347
+ align-items: center;
2348
+ gap: 0.75rem;
2349
+ flex-shrink: 0;
2350
+ }
2351
+
2352
+ .ai-model-label {
2353
+ font-size: 0.6875rem;
2354
+ font-weight: 600;
2355
+ color: var(--editor-text-muted);
2356
+ text-transform: uppercase;
2357
+ letter-spacing: 0.04em;
2358
+ white-space: nowrap;
2359
+ }
2360
+
2361
+ /* Model Picker */
2362
+ .ai-model-picker {
2363
+ flex: 1;
2364
+ position: relative;
2365
+ }
2366
+
2367
+ .ai-model-picker-btn {
2368
+ width: 100%;
2369
+ display: flex;
2370
+ align-items: center;
2371
+ justify-content: space-between;
2372
+ gap: 0.5rem;
2373
+ padding: 0.5rem 0.75rem;
2374
+ font-size: 0.8125rem;
2375
+ font-weight: 500;
2376
+ color: var(--editor-text);
2377
+ background: var(--editor-bg);
2378
+ border: 1px solid var(--editor-border);
2379
+ border-radius: 8px;
2380
+ cursor: pointer;
2381
+ transition: all 0.15s ease;
2382
+ text-align: left;
2383
+ }
2384
+
2385
+ .ai-model-picker-btn:hover {
2386
+ border-color: var(--editor-border-light);
2387
+ }
2388
+
2389
+ .ai-model-picker.open .ai-model-picker-btn {
2390
+ border-color: var(--editor-primary);
2391
+ box-shadow: 0 0 0 3px var(--editor-primary-light);
2392
+ }
2393
+
2394
+ .ai-model-picker.open .ai-select-chevron {
2395
+ transform: rotate(180deg);
2396
+ }
2397
+
2398
+ .ai-model-picker-label {
2399
+ overflow: hidden;
2400
+ text-overflow: ellipsis;
2401
+ white-space: nowrap;
2402
+ flex: 1;
2403
+ }
2404
+
2405
+ .ai-select-chevron {
2406
+ flex-shrink: 0;
2407
+ color: var(--editor-text-muted);
2408
+ transition: transform 0.15s ease;
2409
+ }
2410
+
2411
+ .ai-model-picker-dropdown {
2412
+ display: none;
2413
+ position: absolute;
2414
+ top: calc(100% + 4px);
2415
+ left: 0;
2416
+ right: 0;
2417
+ z-index: 100;
2418
+ background: var(--editor-surface);
2419
+ border: 1px solid var(--editor-border);
2420
+ border-radius: 8px;
2421
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
2422
+ overflow: hidden;
2423
+ }
2424
+
2425
+ .ai-model-picker.open .ai-model-picker-dropdown {
2426
+ display: block;
2427
+ }
2428
+
2429
+ .ai-model-picker-search {
2430
+ width: 100%;
2431
+ padding: 0.5rem 0.75rem;
2432
+ font-size: 0.8125rem;
2433
+ color: var(--editor-text);
2434
+ background: transparent;
2435
+ border: none;
2436
+ border-bottom: 1px solid var(--editor-border);
2437
+ outline: none;
2438
+ box-sizing: border-box;
2439
+ }
2440
+
2441
+ .ai-model-picker-search::placeholder {
2442
+ color: var(--editor-text-muted);
2443
+ }
2444
+
2445
+ .ai-model-picker-list {
2446
+ list-style: none;
2447
+ margin: 0;
2448
+ padding: 4px;
2449
+ max-height: 200px;
2450
+ overflow-y: auto;
2451
+ }
2452
+
2453
+ .ai-model-picker-item {
2454
+ display: flex;
2455
+ align-items: center;
2456
+ justify-content: space-between;
2457
+ gap: 0.5rem;
2458
+ padding: 0.4rem 0.625rem;
2459
+ border-radius: 6px;
2460
+ cursor: pointer;
2461
+ transition: background 0.1s ease;
2462
+ }
2463
+
2464
+ .ai-model-picker-item:hover {
2465
+ background: var(--editor-hover);
2466
+ }
2467
+
2468
+ .ai-model-picker-item.selected {
2469
+ background: var(--editor-primary-light);
2470
+ }
2471
+
2472
+ .ai-model-picker-item-name {
2473
+ font-size: 0.8125rem;
2474
+ font-weight: 500;
2475
+ color: var(--editor-text);
2476
+ overflow: hidden;
2477
+ text-overflow: ellipsis;
2478
+ white-space: nowrap;
2479
+ }
2480
+
2481
+ .ai-model-picker-item-provider {
2482
+ font-size: 0.6875rem;
2483
+ color: var(--editor-text-muted);
2484
+ text-transform: capitalize;
2485
+ flex-shrink: 0;
2486
+ }
2487
+
2488
+ .ai-model-picker-empty {
2489
+ padding: 0.75rem;
2490
+ font-size: 0.8125rem;
2491
+ color: var(--editor-text-muted);
2492
+ text-align: center;
2493
+ }
2494
+
2495
+ /* Conversation Area */
2496
+ .ai-conversation {
2497
+ flex: 1;
2498
+ min-height: 120px;
2499
+ overflow-y: auto;
2500
+ display: flex;
2501
+ flex-direction: column;
2502
+ }
2503
+
2504
+ .ai-conversation-empty {
2505
+ flex: 1;
2506
+ display: flex;
2507
+ flex-direction: column;
2508
+ align-items: center;
2509
+ justify-content: center;
2510
+ text-align: center;
2511
+ padding: 1.5rem;
2512
+ }
2513
+
2514
+ .ai-conversation-empty-icon {
2515
+ width: 48px;
2516
+ height: 48px;
2517
+ display: flex;
2518
+ align-items: center;
2519
+ justify-content: center;
2520
+ background: var(--editor-bg);
2521
+ border: 1px solid var(--editor-border);
2522
+ border-radius: 14px;
2523
+ color: var(--editor-text-dim);
2524
+ margin-bottom: 0.75rem;
2525
+ }
2526
+
2527
+ .ai-conversation-empty p {
2528
+ font-size: 0.8125rem;
2529
+ color: var(--editor-text-muted);
2530
+ margin: 0;
2531
+ }
2532
+
2533
+ /* Response Area */
2534
+ .ai-response-area,
2535
+ .ai-screenshot-output {
2536
+ background: var(--editor-bg);
2537
+ border: 1px solid var(--editor-border);
2538
+ border-radius: 12px;
2539
+ overflow: hidden;
2540
+ flex-shrink: 0;
2541
+ animation: slideUp 0.3s ease;
2542
+ }
2543
+
2544
+ @keyframes slideUp {
2545
+ from { opacity: 0; transform: translateY(8px); }
2546
+ to { opacity: 1; transform: translateY(0); }
2547
+ }
2548
+
2549
+ .ai-response-header {
2550
+ display: flex;
2551
+ align-items: center;
2552
+ gap: 0.5rem;
2553
+ padding: 0.625rem 0.75rem;
2554
+ background: var(--editor-surface);
2555
+ border-bottom: 1px solid var(--editor-border);
2556
+ }
2557
+
2558
+ .ai-response-avatar {
2559
+ width: 24px;
2560
+ height: 24px;
2561
+ display: flex;
2562
+ align-items: center;
2563
+ justify-content: center;
2564
+ background: var(--editor-primary-light);
2565
+ border-radius: 6px;
2566
+ color: var(--editor-primary);
2567
+ }
2568
+
2569
+ .ai-response-header span {
2570
+ font-size: 0.75rem;
2571
+ font-weight: 500;
2572
+ color: var(--editor-text);
2573
+ flex: 1;
2574
+ }
2575
+
2576
+ .ai-copy-btn {
2577
+ width: 28px;
2578
+ height: 28px;
2579
+ display: flex;
2580
+ align-items: center;
2581
+ justify-content: center;
2582
+ background: transparent;
2583
+ border: none;
2584
+ border-radius: 6px;
2585
+ color: var(--editor-text-muted);
2586
+ cursor: pointer;
2587
+ transition: all 0.15s ease;
2588
+ }
2589
+
2590
+ .ai-copy-btn:hover {
2591
+ background: var(--editor-surface-hover);
2592
+ color: var(--editor-text);
2593
+ }
2594
+
2595
+ .ai-response-content {
2596
+ padding: 0.75rem;
2597
+ font-size: 0.75rem;
2598
+ font-family: 'SF Mono', 'Monaco', 'Inconsolata', monospace;
2599
+ color: var(--editor-text);
2600
+ max-height: 180px;
2601
+ overflow-y: auto;
2602
+ white-space: pre-wrap;
2603
+ word-break: break-word;
2604
+ line-height: 1.6;
2605
+ }
2606
+
2607
+ .ai-response-actions {
2608
+ display: flex;
2609
+ gap: 0.5rem;
2610
+ padding: 0.625rem 0.75rem;
2611
+ background: var(--editor-surface);
2612
+ border-top: 1px solid var(--editor-border);
2613
+ }
2614
+
2615
+ .ai-action-btn {
2616
+ display: inline-flex;
2617
+ align-items: center;
2618
+ gap: 0.375rem;
2619
+ padding: 0.5rem 0.75rem;
2620
+ font-size: 0.75rem;
2621
+ font-weight: 500;
2622
+ color: var(--editor-text-muted);
2623
+ background: var(--editor-bg);
2624
+ border: 1px solid var(--editor-border);
2625
+ border-radius: 6px;
2626
+ cursor: pointer;
2627
+ transition: all 0.15s ease;
2628
+ }
2629
+
2630
+ .ai-action-btn:hover {
2631
+ color: var(--editor-text);
2632
+ border-color: var(--editor-border-light);
2633
+ }
2634
+
2635
+ .ai-action-btn.ai-action-primary {
2636
+ color: white;
2637
+ background: var(--editor-primary);
2638
+ border-color: var(--editor-primary);
2639
+ }
2640
+
2641
+ .ai-action-btn.ai-action-primary:hover {
2642
+ background: var(--editor-primary-hover);
2643
+ border-color: var(--editor-primary-hover);
2644
+ }
2645
+
2646
+ .ai-action-btn:disabled {
2647
+ opacity: 0.5;
2648
+ cursor: not-allowed;
2649
+ }
2650
+
2651
+ .ai-action-btn.cooldown {
2652
+ background: var(--editor-success) !important;
2653
+ border-color: var(--editor-success) !important;
2654
+ color: white !important;
2655
+ opacity: 1;
2656
+ }
2657
+
2658
+ .ai-action-btn.cooldown:hover {
2659
+ background: var(--editor-success) !important;
2660
+ border-color: var(--editor-success) !important;
2661
+ }
2662
+
2663
+ /* Prompt Container */
2664
+ .ai-prompt-container {
2665
+ display: flex;
2666
+ align-items: flex-end;
2667
+ gap: 0.5rem;
2668
+ padding: 0.75rem;
2669
+ background: var(--editor-bg);
2670
+ border: 1px solid var(--editor-border);
2671
+ border-radius: 12px;
2672
+ flex-shrink: 0;
2673
+ transition: border-color 0.15s ease, box-shadow 0.15s ease;
2674
+ }
2675
+
2676
+ .ai-prompt-container:focus-within {
2677
+ border-color: var(--editor-primary);
2678
+ box-shadow: 0 0 0 3px var(--editor-primary-light);
2679
+ }
2680
+
2681
+ .ai-prompt-input {
2682
+ flex: 1;
2683
+ min-height: 24px;
2684
+ max-height: 120px;
2685
+ padding: 0;
2686
+ font-size: 0.875rem;
2687
+ font-family: inherit;
2688
+ color: var(--editor-text);
2689
+ background: transparent;
2690
+ border: none;
2691
+ resize: none;
2692
+ line-height: 1.5;
2693
+ }
2694
+
2695
+ .ai-prompt-input:focus {
2696
+ outline: none;
2697
+ }
2698
+
2699
+ .ai-prompt-input::placeholder {
2700
+ color: var(--editor-text-dim);
2701
+ }
2702
+
2703
+ .ai-send-btn {
2704
+ width: 36px;
2705
+ height: 36px;
2706
+ display: flex;
2707
+ align-items: center;
2708
+ justify-content: center;
2709
+ background: var(--editor-primary);
2710
+ border: none;
2711
+ border-radius: 10px;
2712
+ color: white;
2713
+ cursor: pointer;
2714
+ transition: all 0.2s ease;
2715
+ flex-shrink: 0;
2716
+ }
2717
+
2718
+ .ai-send-btn:hover:not(:disabled) {
2719
+ background: var(--editor-primary-hover);
2720
+ transform: translateY(-1px);
2721
+ }
2722
+
2723
+ .ai-send-btn:disabled {
2724
+ background: var(--editor-border);
2725
+ color: var(--editor-text-dim);
2726
+ cursor: not-allowed;
2727
+ }
2728
+
2729
+ .ai-send-btn.loading svg {
2730
+ animation: spin 1s linear infinite;
2731
+ }
2732
+
2733
+ .ai-prompt-hint {
2734
+ display: flex;
2735
+ align-items: center;
2736
+ gap: 0.375rem;
2737
+ padding-top: 0.25rem;
2738
+ font-size: 0.625rem;
2739
+ color: var(--editor-text-dim);
2740
+ flex-shrink: 0;
2741
+ }
2742
+
2743
+ .ai-prompt-hint kbd {
2744
+ padding: 0.125rem 0.375rem;
2745
+ font-size: 0.5625rem;
2746
+ font-family: inherit;
2747
+ background: var(--editor-bg);
2748
+ border: 1px solid var(--editor-border);
2749
+ border-radius: 4px;
2750
+ }
2751
+
2752
+ .ai-hint-separator {
2753
+ color: var(--editor-border);
2754
+ }
2755
+
2756
+ /* Image Tab */
2757
+ .ai-image-output {
2758
+ background: var(--editor-bg);
2759
+ border: 1px solid var(--editor-border);
2760
+ border-radius: 12px;
2761
+ overflow: hidden;
2762
+ animation: slideUp 0.3s ease;
2763
+ }
2764
+
2765
+ .ai-image-preview {
2766
+ padding: 1rem;
2767
+ display: flex;
2768
+ justify-content: center;
2769
+ }
2770
+
2771
+ .ai-image-preview img {
2772
+ max-width: 100%;
2773
+ max-height: 200px;
2774
+ border-radius: 8px;
2775
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
2776
+ }
2777
+
2778
+ .ai-image-empty {
2779
+ flex: 1;
2780
+ display: flex;
2781
+ flex-direction: column;
2782
+ align-items: center;
2783
+ justify-content: center;
2784
+ padding: 2rem 1rem;
2785
+ text-align: center;
2786
+ }
2787
+
2788
+ .ai-image-empty-icon {
2789
+ width: 56px;
2790
+ height: 56px;
2791
+ display: flex;
2792
+ align-items: center;
2793
+ justify-content: center;
2794
+ background: var(--editor-bg);
2795
+ border: 1px solid var(--editor-border);
2796
+ border-radius: 14px;
2797
+ color: var(--editor-text-dim);
2798
+ margin-bottom: 0.75rem;
2799
+ }
2800
+
2801
+ .ai-image-empty p {
2802
+ font-size: 0.8125rem;
2803
+ color: var(--editor-text-muted);
2804
+ margin: 0;
2805
+ }
2806
+
2807
+ /* Upload Zone */
2808
+ .ai-upload-zone {
2809
+ position: relative;
2810
+ border: 2px dashed var(--editor-border);
2811
+ border-radius: 12px;
2812
+ overflow: hidden;
2813
+ transition: all 0.2s ease;
2814
+ cursor: pointer;
2815
+ flex-shrink: 0;
2816
+ }
2817
+
2818
+ .ai-upload-zone:hover {
2819
+ border-color: var(--editor-primary);
2820
+ background: var(--editor-primary-light);
2821
+ }
2822
+
2823
+ .ai-upload-zone.dragover {
2824
+ border-color: var(--editor-primary);
2825
+ background: var(--editor-primary-light);
2826
+ border-style: solid;
2827
+ }
2828
+
2829
+ .ai-upload-input {
2830
+ position: absolute;
2831
+ inset: 0;
2832
+ width: 100%;
2833
+ height: 100%;
2834
+ opacity: 0;
2835
+ cursor: pointer;
2836
+ }
2837
+
2838
+ .ai-upload-content {
2839
+ display: flex;
2840
+ flex-direction: column;
2841
+ align-items: center;
2842
+ justify-content: center;
2843
+ padding: 1.5rem 1rem;
2844
+ gap: 0.5rem;
2845
+ }
2846
+
2847
+ .ai-upload-icon {
2848
+ width: 48px;
2849
+ height: 48px;
2850
+ display: flex;
2851
+ align-items: center;
2852
+ justify-content: center;
2853
+ background: var(--editor-bg);
2854
+ border-radius: 12px;
2855
+ color: var(--editor-text-muted);
2856
+ margin-bottom: 0.25rem;
2857
+ }
2858
+
2859
+ .ai-upload-text {
2860
+ font-size: 0.8125rem;
2861
+ font-weight: 500;
2862
+ color: var(--editor-text);
2863
+ }
2864
+
2865
+ .ai-upload-subtext {
2866
+ font-size: 0.75rem;
2867
+ color: var(--editor-text-muted);
2868
+ }
2869
+
2870
+ .ai-upload-preview {
2871
+ display: none;
2872
+ padding: 1rem;
2873
+ }
2874
+
2875
+ .ai-upload-preview img {
2876
+ max-width: 100%;
2877
+ max-height: 150px;
2878
+ border-radius: 8px;
2879
+ display: block;
2880
+ margin: 0 auto;
2881
+ }
2882
+
2883
+ .ai-upload-zone.has-preview .ai-upload-content {
2884
+ display: none;
2885
+ }
2886
+
2887
+ .ai-upload-zone.has-preview .ai-upload-preview {
2888
+ display: block;
2889
+ }
2890
+
2891
+ /* Loading States */
2892
+ .ai-loading-indicator {
2893
+ display: flex;
2894
+ align-items: center;
2895
+ gap: 0.75rem;
2896
+ padding: 1rem;
2897
+ color: var(--editor-text-muted);
2898
+ }
2899
+
2900
+ .ai-loading-dots {
2901
+ display: flex;
2902
+ gap: 0.25rem;
2903
+ }
2904
+
2905
+ .ai-loading-dots span {
2906
+ width: 6px;
2907
+ height: 6px;
2908
+ background: var(--editor-primary);
2909
+ border-radius: 50%;
2910
+ animation: loadingDot 1.4s ease-in-out infinite;
2911
+ }
2912
+
2913
+ .ai-loading-dots span:nth-child(2) { animation-delay: 0.2s; }
2914
+ .ai-loading-dots span:nth-child(3) { animation-delay: 0.4s; }
2915
+
2916
+ @keyframes loadingDot {
2917
+ 0%, 80%, 100% { transform: scale(0.6); opacity: 0.4; }
2918
+ 40% { transform: scale(1); opacity: 1; }
2919
+ }
2920
+
2921
+ /* Error State */
2922
+ .ai-error {
2923
+ padding: 0.75rem;
2924
+ background: rgba(239, 68, 68, 0.1);
2925
+ border: 1px solid rgba(239, 68, 68, 0.2);
2926
+ border-radius: 8px;
2927
+ color: var(--editor-danger);
2928
+ font-size: 0.8125rem;
2929
+ }