@pixerate/editor-svelte 0.108.0 → 0.109.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 (27) hide show
  1. package/dist/canvas/createCanvasPlaybackSurface.svelte.d.ts +8 -2
  2. package/dist/canvas/createCanvasPlaybackSurface.svelte.js +13 -8
  3. package/dist/image-editor/AdjustmentLayersPanel.svelte +27 -26
  4. package/dist/image-editor/AdjustmentLayersPanel.svelte.d.ts +2 -0
  5. package/dist/image-editor/BrushOptionsBar.svelte +35 -34
  6. package/dist/image-editor/ColorProfilePanel.svelte +12 -12
  7. package/dist/image-editor/ControlSlider.svelte +6 -4
  8. package/dist/image-editor/ControlSlider.svelte.d.ts +2 -0
  9. package/dist/image-editor/CurvesEditor.svelte +6 -4
  10. package/dist/image-editor/CurvesEditor.svelte.d.ts +2 -0
  11. package/dist/image-editor/FreeTransformOptionsBar.svelte +22 -21
  12. package/dist/image-editor/Histogram.svelte +1 -1
  13. package/dist/image-editor/ImageEditor.svelte +127 -142
  14. package/dist/image-editor/ImageEffectControls.svelte +15 -11
  15. package/dist/image-editor/ImageEffectControls.svelte.d.ts +2 -0
  16. package/dist/image-editor/ImageProviderEffectsPanel.svelte +15 -15
  17. package/dist/image-editor/LayerEffectsPanel.svelte +22 -23
  18. package/dist/image-editor/LayersPanel.svelte +39 -39
  19. package/dist/image-editor/RefineEdgePanel.svelte +14 -13
  20. package/dist/image-editor/SelectionOptionsBar.svelte +12 -11
  21. package/dist/image-editor/ShapeOptionsBar.svelte +14 -13
  22. package/dist/image-editor/TypeOptionsBar.svelte +12 -11
  23. package/dist/image-editor/styles.d.ts +51 -0
  24. package/dist/image-editor/styles.js +51 -0
  25. package/dist/playback/playback.svelte.d.ts +7 -4
  26. package/dist/playback/playback.svelte.js +17 -9
  27. package/package.json +2 -2
@@ -1,4 +1,5 @@
1
1
  <script lang="ts">
2
+ import { imageDividerClass, imageEditorFrameClass, imageEditorHeaderClass, imageErrorBannerClass, imageHeaderButtonClass, imagePrimaryButtonClass, imageRangeClass, imageSectionClass, imageSectionTitleClass, imageSelectClass, imageSidebarClass, imageSmallButtonClass, imageSpinnerClass, imageTabClass, imageTabListClass } from './styles.js';
2
3
  import type {
3
4
  ExportOptions,
4
5
  ImageEditorTool,
@@ -281,13 +282,13 @@
281
282
 
282
283
  <div
283
284
  bind:this={rootEl}
284
- class="relative flex flex-col bg-slate-900 border border-slate-800 rounded-xl overflow-hidden shadow-2xl text-slate-100 {className}"
285
+ class="{imageEditorFrameClass} {className}"
285
286
  {style}
286
287
  >
287
288
  <!-- Top Action Header -->
288
- <div class="flex flex-wrap items-center justify-between px-4 py-3 bg-slate-950/80 border-b border-slate-800 gap-3">
289
+ <div class={imageEditorHeaderClass}>
289
290
  <!-- Navigation Tabs -->
290
- <div class="flex items-center gap-1 bg-slate-900 p-1 rounded-lg border border-slate-800 text-xs">
291
+ <div role="tablist" class={imageTabListClass}>
291
292
  <button
292
293
  type="button"
293
294
  data-image-tab="crop"
@@ -295,9 +296,7 @@
295
296
  activeTab = 'crop';
296
297
  editor.setTool('crop');
297
298
  }}
298
- class="px-3 py-1.5 rounded-md font-medium transition-colors {activeTab === 'crop'
299
- ? 'bg-indigo-600 text-white shadow'
300
- : 'text-slate-400 hover:text-slate-200'}"
299
+ role="tab" aria-selected={activeTab === 'crop'} class="{imageTabClass(activeTab === 'crop')}"
301
300
  >
302
301
  Transform & Crop
303
302
  </button>
@@ -308,9 +307,7 @@
308
307
  activeTab = 'adjust';
309
308
  editor.setTool('select');
310
309
  }}
311
- class="px-3 py-1.5 rounded-md font-medium transition-colors {activeTab === 'adjust'
312
- ? 'bg-indigo-600 text-white shadow'
313
- : 'text-slate-400 hover:text-slate-200'}"
310
+ role="tab" aria-selected={activeTab === 'adjust'} class="{imageTabClass(activeTab === 'adjust')}"
314
311
  >
315
312
  Adjustments
316
313
  </button>
@@ -321,9 +318,7 @@
321
318
  activeTab = 'layers';
322
319
  editor.setTool('select');
323
320
  }}
324
- class="px-3 py-1.5 rounded-md font-medium transition-colors {activeTab === 'layers'
325
- ? 'bg-indigo-600 text-white shadow'
326
- : 'text-slate-400 hover:text-slate-200'}"
321
+ role="tab" aria-selected={activeTab === 'layers'} class="{imageTabClass(activeTab === 'layers')}"
327
322
  >
328
323
  Layers
329
324
  </button>
@@ -334,9 +329,7 @@
334
329
  activeTab = 'paint';
335
330
  editor.setTool('brush');
336
331
  }}
337
- class="px-3 py-1.5 rounded-md font-medium transition-colors {activeTab === 'paint'
338
- ? 'bg-indigo-600 text-white shadow'
339
- : 'text-slate-400 hover:text-slate-200'}"
332
+ role="tab" aria-selected={activeTab === 'paint'} class="{imageTabClass(activeTab === 'paint')}"
340
333
  >
341
334
  Paint
342
335
  </button>
@@ -347,9 +340,7 @@
347
340
  activeTab = 'select';
348
341
  editor.setTool('select');
349
342
  }}
350
- class="px-3 py-1.5 rounded-md font-medium transition-colors {activeTab === 'select'
351
- ? 'bg-indigo-600 text-white shadow'
352
- : 'text-slate-400 hover:text-slate-200'}"
343
+ role="tab" aria-selected={activeTab === 'select'} class="{imageTabClass(activeTab === 'select')}"
353
344
  >
354
345
  Select & Mask
355
346
  </button>
@@ -360,9 +351,7 @@
360
351
  activeTab = 'annotate';
361
352
  editor.setTool('pen');
362
353
  }}
363
- class="px-3 py-1.5 rounded-md font-medium transition-colors {activeTab === 'annotate'
364
- ? 'bg-indigo-600 text-white shadow'
365
- : 'text-slate-400 hover:text-slate-200'}"
354
+ role="tab" aria-selected={activeTab === 'annotate'} class="{imageTabClass(activeTab === 'annotate')}"
366
355
  >
367
356
  Annotations
368
357
  </button>
@@ -373,9 +362,7 @@
373
362
  activeTab = 'depth';
374
363
  editor.setTool('select');
375
364
  }}
376
- class="px-3 py-1.5 rounded-md font-medium transition-colors {activeTab === 'depth'
377
- ? 'bg-indigo-600 text-white shadow'
378
- : 'text-slate-400 hover:text-slate-200'}"
365
+ role="tab" aria-selected={activeTab === 'depth'} class="{imageTabClass(activeTab === 'depth')}"
379
366
  >
380
367
  Depth Mask
381
368
  </button>
@@ -386,9 +373,7 @@
386
373
  activeTab = 'ai';
387
374
  editor.setTool('select');
388
375
  }}
389
- class="px-3 py-1.5 rounded-md font-medium transition-colors flex items-center gap-1.5 {activeTab === 'ai'
390
- ? 'bg-indigo-600 text-white shadow'
391
- : 'text-slate-400 hover:text-slate-200'}"
376
+ role="tab" aria-selected={activeTab === 'ai'} class="{imageTabClass(activeTab === 'ai')} flex items-center gap-1.5"
392
377
  >
393
378
  <svg class="w-3.5 h-3.5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
394
379
  <path d="M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83"/>
@@ -403,7 +388,7 @@
403
388
  type="button"
404
389
  disabled={!editor.canUndo}
405
390
  onclick={() => editor.undo()}
406
- class="p-1.5 rounded-lg border border-slate-800 bg-slate-900 text-slate-300 disabled:opacity-40 disabled:cursor-not-allowed hover:bg-slate-800"
391
+ class={imageHeaderButtonClass}
407
392
  title="Undo"
408
393
  >
409
394
  ↩
@@ -412,7 +397,7 @@
412
397
  type="button"
413
398
  disabled={!editor.canRedo}
414
399
  onclick={() => editor.redo()}
415
- class="p-1.5 rounded-lg border border-slate-800 bg-slate-900 text-slate-300 disabled:opacity-40 disabled:cursor-not-allowed hover:bg-slate-800"
400
+ class={imageHeaderButtonClass}
416
401
  title="Redo"
417
402
  >
418
403
  ↪
@@ -420,33 +405,33 @@
420
405
  <button
421
406
  type="button"
422
407
  onclick={() => editor.reset()}
423
- class="px-2 py-1.5 rounded-lg border border-slate-800 bg-slate-900 text-slate-400 hover:text-slate-200 hover:bg-slate-800"
408
+ class="{imageHeaderButtonClass} px-2 text-muted-foreground"
424
409
  >
425
410
  Reset
426
411
  </button>
427
412
 
428
- <div class="h-4 w-px bg-slate-800 mx-1"></div>
413
+ <div class="h-4 w-px bg-muted mx-1"></div>
429
414
 
430
415
  <!-- Zoom -->
431
416
  <button
432
417
  type="button"
433
418
  onclick={() => editor.zoomOut()}
434
- class="p-1.5 rounded-lg border border-slate-800 bg-slate-900 text-slate-300 hover:bg-slate-800"
419
+ class={imageHeaderButtonClass}
435
420
  title="Zoom Out"
436
421
  >
437
422
  -
438
423
  </button>
439
- <span class="font-mono text-slate-400 w-10 text-center">{Math.round(editor.state.zoom * 100)}%</span>
424
+ <span class="font-mono text-muted-foreground w-10 text-center">{Math.round(editor.state.zoom * 100)}%</span>
440
425
  <button
441
426
  type="button"
442
427
  onclick={() => editor.zoomIn()}
443
- class="p-1.5 rounded-lg border border-slate-800 bg-slate-900 text-slate-300 hover:bg-slate-800"
428
+ class={imageHeaderButtonClass}
444
429
  title="Zoom In"
445
430
  >
446
431
  +
447
432
  </button>
448
433
 
449
- <div class="h-4 w-px bg-slate-800 mx-1"></div>
434
+ <div class="h-4 w-px bg-muted mx-1"></div>
450
435
 
451
436
  <!-- Live Compare -->
452
437
  <button
@@ -454,7 +439,7 @@
454
439
  onmousedown={() => editor.setComparing(true)}
455
440
  onmouseup={() => editor.setComparing(false)}
456
441
  onmouseleave={() => editor.setComparing(false)}
457
- class="px-2.5 py-1.5 rounded-lg border border-slate-800 bg-slate-900 text-amber-400 hover:bg-slate-800 select-none active:bg-amber-950/40"
442
+ class="px-2.5 py-1.5 rounded-lg border border-border bg-background text-amber-600 hover:bg-muted select-none active:bg-amber-500/10"
458
443
  >
459
444
  Hold Compare
460
445
  </button>
@@ -463,7 +448,7 @@
463
448
  <button
464
449
  type="button"
465
450
  onclick={handleExport}
466
- class="px-4 py-1.5 rounded-lg bg-emerald-600 hover:bg-emerald-500 text-white font-medium shadow-md shadow-emerald-900/30 transition-colors"
451
+ class="{imagePrimaryButtonClass} px-4 py-1.5"
467
452
  >
468
453
  Export Image
469
454
  </button>
@@ -473,9 +458,9 @@
473
458
  <!-- Main Viewport + Sidebar Layout -->
474
459
  <!-- Free Transform options bar (Ctrl/Cmd+T), above the viewport while a transform is open -->
475
460
  {#if transformActive}
476
- <FreeTransformOptionsBar tool={transformTool} class="border-b border-slate-800 bg-slate-900/95 px-4 py-2" />
461
+ <FreeTransformOptionsBar tool={transformTool} class="border-b border-border bg-background/95 px-4 py-2" />
477
462
  {:else if transformError}
478
- <div role="alert" class="border-b border-rose-900 bg-rose-950/80 px-4 py-1.5 text-xs text-rose-200">{transformError}</div>
463
+ <div role="alert" class={imageErrorBannerClass}>{transformError}</div>
479
464
  {/if}
480
465
 
481
466
  <div class="flex flex-col md:flex-row flex-1 min-h-[520px] md:h-[560px]">
@@ -498,15 +483,15 @@
498
483
  {onplaybackreveal}
499
484
  chromeRoot={() => rootEl}
500
485
  open={openPanel}
501
- class="flex-1 h-[360px] md:h-full min-h-[320px] bg-slate-950"
486
+ class="flex-1 h-[360px] md:h-full min-h-[320px] bg-muted"
502
487
  />
503
488
 
504
489
  <!-- Tab Controls Sidebar -->
505
- <div class="w-full md:w-80 bg-slate-900/90 border-t md:border-t-0 md:border-l border-slate-800 p-4 overflow-y-auto h-auto md:h-full md:max-h-[560px]">
490
+ <div class={imageSidebarClass}>
506
491
  <!-- TAB 1: CROP & TRANSFORM -->
507
492
  {#if activeTab === 'crop'}
508
493
  <div class="flex flex-col gap-4 text-xs">
509
- <span class="font-semibold text-slate-200 uppercase tracking-wider text-[11px]">
494
+ <span class={imageSectionTitleClass}>
510
495
  Aspect Ratio Presets
511
496
  </span>
512
497
  <div class="grid grid-cols-3 gap-2">
@@ -517,8 +502,8 @@
517
502
  editor.applyCropPreset(null);
518
503
  }}
519
504
  class="px-2.5 py-2 rounded-lg border font-medium {activeCropRatio === null && editor.state.crop
520
- ? 'bg-indigo-600 border-indigo-500 text-white'
521
- : 'bg-slate-800 hover:bg-slate-700 text-slate-200 border-slate-700'}"
505
+ ? 'bg-primary border-primary text-primary-foreground'
506
+ : 'bg-muted hover:bg-accent text-foreground border-border'}"
522
507
  >
523
508
  Freeform
524
509
  </button>
@@ -529,8 +514,8 @@
529
514
  editor.applyCropPreset(1);
530
515
  }}
531
516
  class="px-2.5 py-2 rounded-lg border font-medium {activeCropRatio === 1
532
- ? 'bg-indigo-600 border-indigo-500 text-white'
533
- : 'bg-slate-800 hover:bg-slate-700 text-slate-200 border-slate-700'}"
517
+ ? 'bg-primary border-primary text-primary-foreground'
518
+ : 'bg-muted hover:bg-accent text-foreground border-border'}"
534
519
  >
535
520
  1:1 Square
536
521
  </button>
@@ -541,8 +526,8 @@
541
526
  editor.applyCropPreset(4 / 3);
542
527
  }}
543
528
  class="px-2.5 py-2 rounded-lg border font-medium {activeCropRatio === 4 / 3
544
- ? 'bg-indigo-600 border-indigo-500 text-white'
545
- : 'bg-slate-800 hover:bg-slate-700 text-slate-200 border-slate-700'}"
529
+ ? 'bg-primary border-primary text-primary-foreground'
530
+ : 'bg-muted hover:bg-accent text-foreground border-border'}"
546
531
  >
547
532
  4:3 Standard
548
533
  </button>
@@ -553,8 +538,8 @@
553
538
  editor.applyCropPreset(16 / 9);
554
539
  }}
555
540
  class="px-2.5 py-2 rounded-lg border font-medium {activeCropRatio === 16 / 9
556
- ? 'bg-indigo-600 border-indigo-500 text-white'
557
- : 'bg-slate-800 hover:bg-slate-700 text-slate-200 border-slate-700'}"
541
+ ? 'bg-primary border-primary text-primary-foreground'
542
+ : 'bg-muted hover:bg-accent text-foreground border-border'}"
558
543
  >
559
544
  16:9 Wide
560
545
  </button>
@@ -565,8 +550,8 @@
565
550
  editor.applyCropPreset(3 / 2);
566
551
  }}
567
552
  class="px-2.5 py-2 rounded-lg border font-medium {activeCropRatio === 3 / 2
568
- ? 'bg-indigo-600 border-indigo-500 text-white'
569
- : 'bg-slate-800 hover:bg-slate-700 text-slate-200 border-slate-700'}"
553
+ ? 'bg-primary border-primary text-primary-foreground'
554
+ : 'bg-muted hover:bg-accent text-foreground border-border'}"
570
555
  >
571
556
  3:2 Photo
572
557
  </button>
@@ -576,29 +561,29 @@
576
561
  activeCropRatio = null;
577
562
  editor.resetCrop();
578
563
  }}
579
- class="px-2.5 py-2 rounded-lg bg-rose-950/40 hover:bg-rose-900/60 text-rose-300 border border-rose-800/40 font-medium"
564
+ class="px-2.5 py-2 rounded-lg bg-destructive/10 hover:bg-destructive/20 text-destructive border border-destructive/40 font-medium"
580
565
  >
581
566
  Clear Crop
582
567
  </button>
583
568
  </div>
584
569
 
585
- <div class="h-px bg-slate-800 my-1"></div>
570
+ <div class={imageDividerClass}></div>
586
571
 
587
- <span class="font-semibold text-slate-200 uppercase tracking-wider text-[11px]">
572
+ <span class={imageSectionTitleClass}>
588
573
  Orientation & Flips
589
574
  </span>
590
575
  <div class="grid grid-cols-2 gap-2">
591
576
  <button
592
577
  type="button"
593
578
  onclick={() => editor.rotate(-90)}
594
- class="px-3 py-2 rounded-lg bg-slate-800 hover:bg-slate-700 text-slate-200 border border-slate-700"
579
+ class="px-3 py-2 rounded-lg bg-muted hover:bg-accent text-foreground border border-border"
595
580
  >
596
581
  Rotate -90°
597
582
  </button>
598
583
  <button
599
584
  type="button"
600
585
  onclick={() => editor.rotate(90)}
601
- class="px-3 py-2 rounded-lg bg-slate-800 hover:bg-slate-700 text-slate-200 border border-slate-700"
586
+ class="px-3 py-2 rounded-lg bg-muted hover:bg-accent text-foreground border border-border"
602
587
  >
603
588
  Rotate +90°
604
589
  </button>
@@ -606,8 +591,8 @@
606
591
  type="button"
607
592
  onclick={() => editor.flipHorizontal()}
608
593
  class="px-3 py-2 rounded-lg border transition-colors {editor.state.transform.flipH
609
- ? 'bg-indigo-600 border-indigo-500 text-white'
610
- : 'bg-slate-800 border-slate-700 text-slate-200 hover:bg-slate-700'}"
594
+ ? 'bg-primary border-primary text-primary-foreground'
595
+ : 'bg-muted border-border text-foreground hover:bg-accent'}"
611
596
  >
612
597
  Flip Horizontal
613
598
  </button>
@@ -615,8 +600,8 @@
615
600
  type="button"
616
601
  onclick={() => editor.flipVertical()}
617
602
  class="px-3 py-2 rounded-lg border transition-colors {editor.state.transform.flipV
618
- ? 'bg-indigo-600 border-indigo-500 text-white'
619
- : 'bg-slate-800 border-slate-700 text-slate-200 hover:bg-slate-700'}"
603
+ ? 'bg-primary border-primary text-primary-foreground'
604
+ : 'bg-muted border-border text-foreground hover:bg-accent'}"
620
605
  >
621
606
  Flip Vertical
622
607
  </button>
@@ -628,13 +613,13 @@
628
613
  {#if activeTab === 'adjust'}
629
614
  <div class="flex flex-col gap-3 text-xs">
630
615
  <div class="flex items-center justify-between">
631
- <span class="font-semibold text-slate-200 uppercase tracking-wider text-[11px]">
616
+ <span class={imageSectionTitleClass}>
632
617
  Color Adjustments
633
618
  </span>
634
619
  <button
635
620
  type="button"
636
621
  onclick={() => editor.resetAdjustments()}
637
- class="text-[10px] text-rose-400 hover:underline"
622
+ class="text-[10px] text-destructive hover:underline"
638
623
  >
639
624
  Reset Sliders
640
625
  </button>
@@ -651,7 +636,7 @@
651
636
  />
652
637
  {#if spec.id === 'tint' && legacyProcess}
653
638
  <div
654
- class="flex items-center justify-between gap-2 rounded border border-amber-500/30 bg-amber-500/10 px-2 py-1.5 text-[10px] text-amber-200"
639
+ class="flex items-center justify-between gap-2 rounded border border-amber-500/30 bg-amber-500/10 px-2 py-1.5 text-[10px] text-amber-600"
655
640
  data-testid="image-editor-process-notice"
656
641
  >
657
642
  <span>Legacy rendering (process 1). Tint needs the current process.</span>
@@ -666,7 +651,7 @@
666
651
  {/if}
667
652
  {/each}
668
653
 
669
- <div class="border-t border-slate-700/60 pt-3">
654
+ <div class={imageSectionClass}>
670
655
  <AdjustmentLayersPanel
671
656
  controller={editor.controller}
672
657
  layers={editor.state.adjustments.layers}
@@ -679,34 +664,34 @@
679
664
  <!-- TAB 3: ANNOTATIONS -->
680
665
  {#if activeTab === 'layers'}
681
666
  <div class="flex flex-col gap-3 text-xs">
682
- <span class="font-semibold text-slate-200 uppercase tracking-wider text-[11px]">Layers</span>
667
+ <span class={imageSectionTitleClass}>Layers</span>
683
668
  <button
684
669
  type="button"
685
670
  title="Edit › Free Transform (Ctrl/Cmd+T): the selected pixels, or the whole active layer"
686
- class="px-2 py-1 rounded text-[11px] bg-slate-800 text-slate-300 hover:text-white self-start disabled:opacity-40"
671
+ class={imageSmallButtonClass}
687
672
  disabled={transformActive}
688
673
  onclick={() => transformTool.begin()}>Free Transform</button>
689
674
  <LayersPanel controller={editor.controller} />
690
- {#if effectsShown}<ImageProviderEffectsPanel controller={editor.controller} class="border-t border-slate-700/60 pt-3" />{/if}
691
- <span class="font-semibold text-slate-200 uppercase tracking-wider text-[11px]">Colour</span>
675
+ {#if effectsShown}<ImageProviderEffectsPanel controller={editor.controller} class={imageSectionClass} />{/if}
676
+ <span class={imageSectionTitleClass}>Colour</span>
692
677
  <ColorProfilePanel controller={editor.controller} />
693
678
  </div>
694
679
  {/if}
695
680
 
696
681
  {#if activeTab === 'paint'}
697
682
  <div class="flex flex-col gap-3 text-xs">
698
- <span class="font-semibold text-slate-200 uppercase tracking-wider text-[11px]">Paint</span>
683
+ <span class={imageSectionTitleClass}>Paint</span>
699
684
  <BrushOptionsBar controller={editor.controller} />
700
685
  <button
701
686
  type="button"
702
687
  title="Edit › Free Transform (Ctrl/Cmd+T): the selected pixels, or the whole active layer"
703
- class="px-2 py-1 rounded text-[11px] bg-slate-800 text-slate-300 hover:text-white self-start disabled:opacity-40"
688
+ class={imageSmallButtonClass}
704
689
  disabled={transformActive}
705
690
  onclick={() => transformTool.begin()}>Free Transform</button>
706
691
  {#if paintError}
707
- <p role="alert" class="text-rose-400" data-testid="paint-error">{paintError}</p>
692
+ <p role="alert" class="text-destructive" data-testid="paint-error">{paintError}</p>
708
693
  {/if}
709
- <div class="border-t border-slate-700/60 pt-3">
694
+ <div class={imageSectionClass}>
710
695
  <LayersPanel controller={editor.controller} />
711
696
  </div>
712
697
  </div>
@@ -714,7 +699,7 @@
714
699
 
715
700
  {#if activeTab === 'annotate'}
716
701
  <div class="flex flex-col gap-3 text-xs">
717
- <span class="font-semibold text-slate-200 uppercase tracking-wider text-[11px]">Shape & Type Layers</span>
702
+ <span class={imageSectionTitleClass}>Shape & Type Layers</span>
718
703
  <div class="grid grid-cols-2 gap-1.5">
719
704
  {#each ['shape', 'type'] as const as t (t)}
720
705
  <button
@@ -722,8 +707,8 @@
722
707
  aria-pressed={editor.state.activeTool === t}
723
708
  onclick={() => editor.setTool(t)}
724
709
  class="py-1.5 px-2 rounded-lg font-medium border transition-colors {editor.state.activeTool === t
725
- ? 'bg-indigo-600 border-indigo-500 text-white'
726
- : 'bg-slate-800 border-slate-700 text-slate-300 hover:bg-slate-700'}">{t === 'shape' ? 'Shape' : 'Type'}</button>
710
+ ? 'bg-primary border-primary text-primary-foreground'
711
+ : 'bg-muted border-border text-foreground hover:bg-accent'}">{t === 'shape' ? 'Shape' : 'Type'}</button>
727
712
  {/each}
728
713
  </div>
729
714
  {#if editor.state.activeTool === 'shape'}
@@ -732,15 +717,15 @@
732
717
  {#if editor.state.activeTool === 'type'}
733
718
  <TypeOptionsBar controller={editor.controller} options={typeOptions} onchange={(o) => (typeOptions = o)} session={typeSession} />
734
719
  {#if typeSession}
735
- <button type="button" onclick={finishTyping} class="self-start rounded bg-slate-800 px-2 py-1 text-[11px] text-slate-200 hover:bg-slate-700">Done editing text</button>
720
+ <button type="button" onclick={finishTyping} class="self-start rounded bg-muted px-2 py-1 text-[11px] text-foreground hover:bg-accent">Done editing text</button>
736
721
  {/if}
737
722
  {/if}
738
723
  {#if shapeTypeError}
739
- <p role="alert" class="text-rose-400" data-testid="shape-type-error">{shapeTypeError}</p>
724
+ <p role="alert" class="text-destructive" data-testid="shape-type-error">{shapeTypeError}</p>
740
725
  {/if}
741
- <div class="h-px bg-slate-800 my-1"></div>
726
+ <div class={imageDividerClass}></div>
742
727
 
743
- <span class="font-semibold text-slate-200 uppercase tracking-wider text-[11px]">
728
+ <span class={imageSectionTitleClass}>
744
729
  Draw & Annotate
745
730
  </span>
746
731
 
@@ -751,8 +736,8 @@
751
736
  type="button"
752
737
  onclick={() => editor.setTool(t)}
753
738
  class="py-1.5 px-2 rounded-lg font-medium capitalize border transition-colors {editor.state.activeTool === t
754
- ? 'bg-indigo-600 border-indigo-500 text-white'
755
- : 'bg-slate-800 border-slate-700 text-slate-300 hover:bg-slate-700'}"
739
+ ? 'bg-primary border-primary text-primary-foreground'
740
+ : 'bg-muted border-border text-foreground hover:bg-accent'}"
756
741
  >
757
742
  {t}
758
743
  </button>
@@ -761,14 +746,14 @@
761
746
 
762
747
  <!-- Color & Size -->
763
748
  <div class="flex items-center gap-2 mt-2">
764
- <span class="text-slate-400">Color:</span>
749
+ <span class="text-muted-foreground">Color:</span>
765
750
  <input
766
751
  type="color"
767
752
  bind:value={activeColor}
768
- class="w-8 h-8 rounded border border-slate-700 cursor-pointer bg-transparent"
753
+ class="w-8 h-8 rounded border border-border cursor-pointer bg-transparent"
769
754
  />
770
755
  <div class="flex-1 ml-2">
771
- <div class="flex justify-between text-slate-400 mb-0.5">
756
+ <div class="flex justify-between text-muted-foreground mb-0.5">
772
757
  <span>Width:</span>
773
758
  <span class="font-mono">{strokeWidth}px</span>
774
759
  </div>
@@ -777,32 +762,32 @@
777
762
  min="1"
778
763
  max="20"
779
764
  bind:value={strokeWidth}
780
- class="w-full accent-indigo-500"
765
+ class={imageRangeClass}
781
766
  />
782
767
  </div>
783
768
  </div>
784
769
 
785
- <div class="h-px bg-slate-800 my-1"></div>
770
+ <div class={imageDividerClass}></div>
786
771
 
787
772
  <!-- Text Tool -->
788
- <span class="font-semibold text-slate-200 uppercase tracking-wider text-[11px]">Add Text</span>
773
+ <span class={imageSectionTitleClass}>Add Text</span>
789
774
  <div class="flex gap-2">
790
775
  <input
791
776
  type="text"
792
777
  placeholder="Type watermark or label..."
793
778
  bind:value={textInput}
794
779
  onkeydown={(e) => e.key === 'Enter' && handleAddText()}
795
- class="flex-1 bg-slate-950 border border-slate-700 rounded-lg px-2.5 py-1.5 text-xs text-slate-100 placeholder-slate-500 focus:outline-none focus:border-indigo-500"
780
+ class="flex-1 bg-background border border-border rounded-lg px-2.5 py-1.5 text-xs text-foreground placeholder:text-muted-foreground focus:outline-none focus:border-primary"
796
781
  />
797
782
  <button
798
783
  type="button"
799
784
  onclick={handleAddText}
800
- class="px-3 py-1.5 rounded-lg bg-indigo-600 hover:bg-indigo-500 text-white font-medium shadow"
785
+ class="px-3 py-1.5 rounded-lg bg-primary hover:bg-primary/90 text-primary-foreground font-medium shadow"
801
786
  >
802
787
  Add
803
788
  </button>
804
789
  </div>
805
- <div class="flex items-center justify-between text-slate-400">
790
+ <div class="flex items-center justify-between text-muted-foreground">
806
791
  <span>Font Size:</span>
807
792
  <span class="font-mono">{fontSize}px</span>
808
793
  </div>
@@ -811,18 +796,18 @@
811
796
  min="12"
812
797
  max="72"
813
798
  bind:value={fontSize}
814
- class="w-full accent-indigo-500"
799
+ class={imageRangeClass}
815
800
  />
816
801
 
817
802
  <!-- Layers & Selected Annotation -->
818
- <div class="h-px bg-slate-800 my-1"></div>
803
+ <div class={imageDividerClass}></div>
819
804
  <div class="flex items-center justify-between">
820
- <span class="text-slate-400">Layers ({editor.state.annotations.length})</span>
805
+ <span class="text-muted-foreground">Layers ({editor.state.annotations.length})</span>
821
806
  {#if editor.state.selectedAnnotationId}
822
807
  <button
823
808
  type="button"
824
809
  onclick={() => editor.removeAnnotation(editor.state.selectedAnnotationId!)}
825
- class="text-rose-400 hover:underline text-[11px]"
810
+ class="text-destructive hover:underline text-[11px]"
826
811
  >
827
812
  Delete Selected
828
813
  </button>
@@ -831,7 +816,7 @@
831
816
  <button
832
817
  type="button"
833
818
  onclick={() => editor.clearAnnotations()}
834
- class="text-slate-400 hover:text-slate-200 text-[11px]"
819
+ class="text-muted-foreground hover:text-foreground text-[11px]"
835
820
  >
836
821
  Clear All
837
822
  </button>
@@ -844,37 +829,37 @@
844
829
  {#if activeTab === 'depth'}
845
830
  <div class="flex flex-col gap-3 text-xs">
846
831
  <div class="flex items-center justify-between">
847
- <span class="font-semibold text-slate-200 uppercase tracking-wider text-[11px]">
832
+ <span class={imageSectionTitleClass}>
848
833
  Depth Masking
849
834
  </span>
850
835
  <button
851
836
  type="button"
852
837
  onclick={() => editor.resetDepthMask()}
853
- class="text-[10px] text-rose-400 hover:underline"
838
+ class="text-[10px] text-destructive hover:underline"
854
839
  >
855
840
  Reset Mask
856
841
  </button>
857
842
  </div>
858
843
 
859
- <label class="flex items-center gap-2 cursor-pointer text-slate-300">
844
+ <label class="flex items-center gap-2 cursor-pointer text-foreground">
860
845
  <input
861
846
  type="checkbox"
862
847
  checked={editor.state.depthMask.enabled}
863
848
  onchange={(e) => editor.setDepthMask({ enabled: (e.target as HTMLInputElement).checked })}
864
- class="rounded accent-indigo-500"
849
+ class="rounded accent-primary"
865
850
  />
866
851
  <span>Enable Depth / Alpha Mask</span>
867
852
  </label>
868
853
 
869
854
  {#if editor.state.depthMask.enabled}
870
855
  <div>
871
- <span class="text-slate-400 block mb-1">Mask Image URL:</span>
856
+ <span class="text-muted-foreground block mb-1">Mask Image URL:</span>
872
857
  <input
873
858
  type="text"
874
859
  placeholder="https://.../depthmap.png"
875
860
  value={editor.state.depthMask.maskSource || ''}
876
861
  oninput={(e) => editor.setDepthMask({ maskSource: (e.target as HTMLInputElement).value || null })}
877
- class="w-full bg-slate-950 border border-slate-700 rounded-lg px-2.5 py-1.5 text-xs text-slate-100 placeholder-slate-500"
862
+ class="w-full bg-background border border-border rounded-lg px-2.5 py-1.5 text-xs text-foreground placeholder:text-muted-foreground"
878
863
  />
879
864
  </div>
880
865
 
@@ -883,8 +868,8 @@
883
868
  type="button"
884
869
  onclick={() => editor.setDepthMask({ mode: 'threshold' })}
885
870
  class="flex-1 py-1.5 rounded-lg border text-xs font-medium {editor.state.depthMask.mode === 'threshold'
886
- ? 'bg-indigo-600 border-indigo-500 text-white'
887
- : 'bg-slate-800 border-slate-700 text-slate-300'}"
871
+ ? 'bg-primary border-primary text-primary-foreground'
872
+ : 'bg-muted border-border text-foreground'}"
888
873
  >
889
874
  Threshold Mode
890
875
  </button>
@@ -892,15 +877,15 @@
892
877
  type="button"
893
878
  onclick={() => editor.setDepthMask({ mode: 'brightness' })}
894
879
  class="flex-1 py-1.5 rounded-lg border text-xs font-medium {editor.state.depthMask.mode === 'brightness'
895
- ? 'bg-indigo-600 border-indigo-500 text-white'
896
- : 'bg-slate-800 border-slate-700 text-slate-300'}"
880
+ ? 'bg-primary border-primary text-primary-foreground'
881
+ : 'bg-muted border-border text-foreground'}"
897
882
  >
898
883
  Brightness Mode
899
884
  </button>
900
885
  </div>
901
886
 
902
887
  <div>
903
- <div class="flex justify-between text-slate-400 mb-1">
888
+ <div class="flex justify-between text-muted-foreground mb-1">
904
889
  <span>Depth Start (Lower):</span>
905
890
  <span class="font-mono">{editor.state.depthMask.depthRange[0]}</span>
906
891
  </div>
@@ -913,12 +898,12 @@
913
898
  editor.setDepthMask({
914
899
  depthRange: [Number((e.target as HTMLInputElement).value), editor.state.depthMask.depthRange[1]],
915
900
  })}
916
- class="w-full accent-indigo-500"
901
+ class={imageRangeClass}
917
902
  />
918
903
  </div>
919
904
 
920
905
  <div>
921
- <div class="flex justify-between text-slate-400 mb-1">
906
+ <div class="flex justify-between text-muted-foreground mb-1">
922
907
  <span>Depth Stop (Upper):</span>
923
908
  <span class="font-mono">{editor.state.depthMask.depthRange[1]}</span>
924
909
  </div>
@@ -931,12 +916,12 @@
931
916
  editor.setDepthMask({
932
917
  depthRange: [editor.state.depthMask.depthRange[0], Number((e.target as HTMLInputElement).value)],
933
918
  })}
934
- class="w-full accent-indigo-500"
919
+ class={imageRangeClass}
935
920
  />
936
921
  </div>
937
922
 
938
923
  <div>
939
- <div class="flex justify-between text-slate-400 mb-1">
924
+ <div class="flex justify-between text-muted-foreground mb-1">
940
925
  <span>Softness:</span>
941
926
  <span class="font-mono">{editor.state.depthMask.softness}</span>
942
927
  </div>
@@ -946,16 +931,16 @@
946
931
  max="50"
947
932
  value={editor.state.depthMask.softness}
948
933
  oninput={(e) => editor.setDepthMask({ softness: Number((e.target as HTMLInputElement).value) })}
949
- class="w-full accent-indigo-500"
934
+ class={imageRangeClass}
950
935
  />
951
936
  </div>
952
937
 
953
- <label class="flex items-center gap-2 cursor-pointer text-slate-300 mt-1">
938
+ <label class="flex items-center gap-2 cursor-pointer text-foreground mt-1">
954
939
  <input
955
940
  type="checkbox"
956
941
  checked={editor.state.depthMask.invert}
957
942
  onchange={(e) => editor.setDepthMask({ invert: (e.target as HTMLInputElement).checked })}
958
- class="rounded accent-indigo-500"
943
+ class="rounded accent-primary"
959
944
  />
960
945
  <span>Invert Mask</span>
961
946
  </label>
@@ -974,19 +959,19 @@
974
959
  quickMask={Boolean(editor.state.quickMask)}
975
960
  />
976
961
  {#if selectionError}
977
- <p role="alert" class="text-rose-400">{selectionError}</p>
962
+ <p role="alert" class="text-destructive">{selectionError}</p>
978
963
  {/if}
979
964
  <div class="flex gap-1">
980
965
  <button
981
966
  type="button"
982
967
  title="Select › Transform Selection: the outline only"
983
- class="px-2 py-1 rounded text-[11px] bg-slate-800 text-slate-300 hover:text-white self-start disabled:opacity-40"
968
+ class={imageSmallButtonClass}
984
969
  disabled={transformActive}
985
970
  onclick={() => transformTool.begin({ content: 'selection-outline' })}>Transform Selection</button>
986
971
  <button
987
972
  type="button"
988
973
  title="Edit › Free Transform: the selected pixels of the active layer"
989
- class="px-2 py-1 rounded text-[11px] bg-slate-800 text-slate-300 hover:text-white self-start disabled:opacity-40"
974
+ class={imageSmallButtonClass}
990
975
  disabled={transformActive}
991
976
  onclick={() => transformTool.begin({ content: 'selection' })}>Free Transform Pixels</button>
992
977
  </div>
@@ -1001,12 +986,12 @@
1001
986
  <!-- TAB 5: AI TOOLS / INPAINTING & BACKGROUND REMOVAL -->
1002
987
  {#if activeTab === 'ai'}
1003
988
  <div class="flex flex-col gap-4 text-xs">
1004
- <label class="flex items-center justify-between gap-2 text-slate-300">
989
+ <label class="flex items-center justify-between gap-2 text-foreground">
1005
990
  <span>Results go to</span>
1006
991
  <select
1007
992
  aria-label="AI result target"
1008
993
  bind:value={aiTarget}
1009
- class="bg-slate-800 border border-slate-700 rounded px-1.5 py-1"
994
+ class={imageSelectClass}
1010
995
  >
1011
996
  <option value="auto">{editor.controller.isMultiLayer ? 'Auto (new layer)' : 'Auto (replace image)'}</option>
1012
997
  <option value="new-layer">New layer / mask</option>
@@ -1014,22 +999,22 @@
1014
999
  </select>
1015
1000
  </label>
1016
1001
  <!-- Background Removal Section -->
1017
- <div class="p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5">
1002
+ <div class="p-3 rounded-lg bg-muted/40 border border-border flex flex-col gap-2.5">
1018
1003
  <div class="flex items-center justify-between">
1019
- <span class="font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5">
1020
- <svg class="w-3.5 h-3.5 text-indigo-400" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1004
+ <span class="font-semibold text-foreground uppercase tracking-wider text-[11px] flex items-center gap-1.5">
1005
+ <svg class="w-3.5 h-3.5 text-primary" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1021
1006
  <path d="M6 3v12M18 9a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM6 21a3 3 0 1 0 0-6 3 3 0 0 0 0 6z"/>
1022
1007
  </svg>
1023
1008
  Background Removal
1024
1009
  </span>
1025
1010
  {#if isRemovingBg}
1026
- <span class="inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-medium bg-indigo-900/60 text-indigo-300 animate-pulse">
1011
+ <span class="inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-medium bg-primary/15 text-primary animate-pulse">
1027
1012
  Removing...
1028
1013
  </span>
1029
1014
  {/if}
1030
1015
  </div>
1031
1016
 
1032
- <p class="text-slate-400 text-[11px] leading-relaxed">
1017
+ <p class="text-muted-foreground text-[11px] leading-relaxed">
1033
1018
  Isolate foreground subject with AI alpha transparency segmentation.
1034
1019
  </p>
1035
1020
 
@@ -1037,10 +1022,10 @@
1037
1022
  type="button"
1038
1023
  onclick={handleRemoveBackground}
1039
1024
  disabled={isRemovingBg || isInpainting}
1040
- class="mt-1 px-3 py-2 rounded-lg bg-indigo-600 hover:bg-indigo-500 disabled:opacity-50 text-white font-medium shadow transition-colors flex items-center justify-center gap-2"
1025
+ class="mt-1 px-3 py-2 rounded-lg bg-primary hover:bg-primary/90 disabled:opacity-50 text-primary-foreground font-medium shadow transition-colors flex items-center justify-center gap-2"
1041
1026
  >
1042
1027
  {#if isRemovingBg}
1043
- <div class="w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin"></div>
1028
+ <div class={imageSpinnerClass}></div>
1044
1029
  Removing Background...
1045
1030
  {:else}
1046
1031
  <svg class="w-3.5 h-3.5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
@@ -1052,46 +1037,46 @@
1052
1037
  </div>
1053
1038
 
1054
1039
  <!-- AI Inpainting / Generative Fill Section -->
1055
- <div class="p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5">
1040
+ <div class="p-3 rounded-lg bg-muted/40 border border-border flex flex-col gap-2.5">
1056
1041
  <div class="flex items-center justify-between">
1057
- <span class="font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5">
1058
- <svg class="w-3.5 h-3.5 text-purple-400" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1042
+ <span class="font-semibold text-foreground uppercase tracking-wider text-[11px] flex items-center gap-1.5">
1043
+ <svg class="w-3.5 h-3.5 text-primary" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1059
1044
  <path d="m21.64 3.64-1.28-1.28a1.2 1.2 0 0 0-1.7 0l-9.72 9.72-1.94 4.86 4.86-1.94 9.72-9.72a1.2 1.2 0 0 0 .06-1.64z"/>
1060
1045
  <path d="m14 7 3 3"/>
1061
1046
  </svg>
1062
1047
  Generative Inpainting
1063
1048
  </span>
1064
1049
  {#if isInpainting}
1065
- <span class="inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-medium bg-purple-900/60 text-purple-300 animate-pulse">
1050
+ <span class="inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-medium bg-primary/15 text-primary animate-pulse">
1066
1051
  Inpainting...
1067
1052
  </span>
1068
1053
  {/if}
1069
1054
  </div>
1070
1055
 
1071
- <p class="text-slate-400 text-[11px] leading-relaxed">
1056
+ <p class="text-muted-foreground text-[11px] leading-relaxed">
1072
1057
  Replace, modify, or fill selected regions using prompt-guided generative inpainting.
1073
1058
  </p>
1074
1059
 
1075
1060
  <div class="flex flex-col gap-1">
1076
- <label for="ai-inpaint-prompt" class="text-slate-300 text-[11px] font-medium">Prompt</label>
1061
+ <label for="ai-inpaint-prompt" class="text-foreground text-[11px] font-medium">Prompt</label>
1077
1062
  <textarea
1078
1063
  id="ai-inpaint-prompt"
1079
1064
  bind:value={inpaintPrompt}
1080
1065
  placeholder="e.g. replace sunglasses with steampunk goggles, remove person in background..."
1081
1066
  rows="3"
1082
- class="w-full bg-slate-900 border border-slate-700 rounded-lg p-2 text-xs text-slate-100 placeholder-slate-500 focus:outline-none focus:border-indigo-500 resize-none"
1067
+ class="w-full bg-background border border-border rounded-lg p-2 text-xs text-foreground placeholder:text-muted-foreground focus:outline-none focus:border-primary resize-none"
1083
1068
  ></textarea>
1084
1069
  </div>
1085
1070
 
1086
1071
  <div class="flex flex-col gap-1">
1087
- <span class="text-slate-300 text-[11px] font-medium">Target Mask Region</span>
1072
+ <span class="text-foreground text-[11px] font-medium">Target Mask Region</span>
1088
1073
  <div class="grid grid-cols-2 gap-1.5">
1089
1074
  <button
1090
1075
  type="button"
1091
1076
  onclick={() => inpaintMaskMode = 'annotations'}
1092
1077
  class="px-2 py-1.5 rounded border text-[11px] font-medium text-left transition-colors {inpaintMaskMode === 'annotations'
1093
- ? 'bg-purple-600/30 border-purple-500 text-purple-200'
1094
- : 'bg-slate-900 border-slate-700 text-slate-400 hover:text-slate-200'}"
1078
+ ? 'bg-primary/30 border-primary text-primary'
1079
+ : 'bg-background border-border text-muted-foreground hover:text-foreground'}"
1095
1080
  >
1096
1081
  Drawn Shapes ({editor.state.annotations.length})
1097
1082
  </button>
@@ -1099,8 +1084,8 @@
1099
1084
  type="button"
1100
1085
  onclick={() => inpaintMaskMode = 'crop'}
1101
1086
  class="px-2 py-1.5 rounded border text-[11px] font-medium text-left transition-colors {inpaintMaskMode === 'crop'
1102
- ? 'bg-purple-600/30 border-purple-500 text-purple-200'
1103
- : 'bg-slate-900 border-slate-700 text-slate-400 hover:text-slate-200'}"
1087
+ ? 'bg-primary/30 border-primary text-primary'
1088
+ : 'bg-background border-border text-muted-foreground hover:text-foreground'}"
1104
1089
  >
1105
1090
  Crop Box ({editor.state.crop ? 'Selected' : 'Full'})
1106
1091
  </button>
@@ -1111,10 +1096,10 @@
1111
1096
  type="button"
1112
1097
  onclick={handleInpaint}
1113
1098
  disabled={isInpainting || isRemovingBg || !inpaintPrompt.trim()}
1114
- class="mt-1 px-3 py-2 rounded-lg bg-purple-600 hover:bg-purple-500 disabled:opacity-50 text-white font-medium shadow transition-colors flex items-center justify-center gap-2"
1099
+ class="mt-1 px-3 py-2 rounded-lg bg-primary hover:bg-primary/90 disabled:opacity-50 text-primary-foreground font-medium shadow transition-colors flex items-center justify-center gap-2"
1115
1100
  >
1116
1101
  {#if isInpainting}
1117
- <div class="w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin"></div>
1102
+ <div class={imageSpinnerClass}></div>
1118
1103
  Generating Inpaint...
1119
1104
  {:else}
1120
1105
  <svg class="w-3.5 h-3.5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
@@ -1126,13 +1111,13 @@
1126
1111
  </div>
1127
1112
 
1128
1113
  {#if aiError}
1129
- <div class="p-2.5 rounded-lg bg-rose-950/60 border border-rose-800 text-rose-300 text-[11px]">
1114
+ <div class="p-2.5 rounded-lg bg-destructive/10 border border-destructive/40 text-destructive text-[11px]">
1130
1115
  {aiError}
1131
1116
  </div>
1132
1117
  {/if}
1133
1118
 
1134
1119
  {#if aiSuccess}
1135
- <div class="p-2.5 rounded-lg bg-emerald-950/60 border border-emerald-800 text-emerald-300 text-[11px]">
1120
+ <div class="p-2.5 rounded-lg bg-emerald-500/10 border border-emerald-500/30 text-emerald-600 text-[11px]">
1136
1121
  {aiSuccess}
1137
1122
  </div>
1138
1123
  {/if}