lightfall-utils 0.1.0__py3-none-any.whl

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.
@@ -0,0 +1,737 @@
1
+ """Built-in themes.
2
+
3
+ This module contains the default themes that ship with lightfall-utils:
4
+ - LightThemePlugin: Light/bright theme
5
+ - SlateThemePlugin: Neutral gray dark theme
6
+ - DarkBlueThemePlugin: Blue-gray dark theme
7
+ - IslandsThemePlugin: Modern theme with visually separated components
8
+ - CatppuccinMochaThemePlugin: Catppuccin Mocha palette (warm dark)
9
+ - EldritchThemePlugin: Eldritch palette (deep blue/magenta dark)
10
+ - EvangelionThemePlugin: NGE Unit-01 palette (purple/green dark)
11
+ - AyakaThemePlugin: Twilight sakura palette (warm indigo/pink dark)
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ from typing import TYPE_CHECKING
17
+
18
+ from lightfall_utils.theming.provider import ThemeDefinition, ThemeProvider
19
+
20
+ if TYPE_CHECKING:
21
+ from lightfall_utils.theming.manager import ThemeColors
22
+
23
+
24
+ class LightThemePlugin(ThemeProvider):
25
+ """Light theme plugin.
26
+
27
+ A bright theme with white backgrounds and dark text,
28
+ suitable for well-lit environments.
29
+ """
30
+
31
+ @property
32
+ def name(self) -> str:
33
+ return "light"
34
+
35
+ @property
36
+ def display_name(self) -> str:
37
+ return "Light"
38
+
39
+ @property
40
+ def is_dark(self) -> bool:
41
+ return False
42
+
43
+ def get_theme_definition(self) -> ThemeDefinition:
44
+ return ThemeDefinition(
45
+ primary="#2563eb",
46
+ secondary="#7c3aed",
47
+ success="#16a34a",
48
+ warning="#d97706",
49
+ error="#dc2626",
50
+ info="#0891b2",
51
+ background="#ffffff",
52
+ surface="#f3f4f6",
53
+ sea="#fafafa", # lighter than surface (gaps/canvas)
54
+ text="#1f2937",
55
+ text_secondary="#6b7280",
56
+ border="#e5e7eb",
57
+ disconnected="#ffcccc",
58
+ )
59
+
60
+
61
+ class SlateThemePlugin(ThemeProvider):
62
+ """Slate (dark) theme plugin.
63
+
64
+ A neutral gray dark theme that reduces eye strain in low-light
65
+ environments. This is the default dark theme.
66
+ """
67
+
68
+ @property
69
+ def name(self) -> str:
70
+ return "slate"
71
+
72
+ @property
73
+ def display_name(self) -> str:
74
+ return "Slate (Dark)"
75
+
76
+ @property
77
+ def is_dark(self) -> bool:
78
+ return True
79
+
80
+ def get_theme_definition(self) -> ThemeDefinition:
81
+ return ThemeDefinition(
82
+ primary="#3b82f6",
83
+ secondary="#8b5cf6",
84
+ success="#22c55e",
85
+ warning="#f59e0b",
86
+ error="#ef4444",
87
+ info="#06b6d4",
88
+ background="#1e1e1e",
89
+ surface="#2d2d2d",
90
+ sea="#373737", # lighter than surface (gaps/canvas)
91
+ text="#d4d4d4",
92
+ text_secondary="#808080",
93
+ border="#3e3e3e",
94
+ disconnected="#5c2020",
95
+ )
96
+
97
+
98
+ class DarkBlueThemePlugin(ThemeProvider):
99
+ """Dark Blue theme plugin.
100
+
101
+ A blue-gray dark theme with slightly warmer tones than Slate.
102
+ """
103
+
104
+ @property
105
+ def name(self) -> str:
106
+ return "darkblue"
107
+
108
+ @property
109
+ def display_name(self) -> str:
110
+ return "Dark Blue"
111
+
112
+ @property
113
+ def is_dark(self) -> bool:
114
+ return True
115
+
116
+ def get_theme_definition(self) -> ThemeDefinition:
117
+ return ThemeDefinition(
118
+ primary="#3b82f6",
119
+ secondary="#8b5cf6",
120
+ success="#22c55e",
121
+ warning="#f59e0b",
122
+ error="#ef4444",
123
+ info="#06b6d4",
124
+ background="#1f2937",
125
+ surface="#374151",
126
+ sea="#3f4b5d", # lighter than surface (gaps/canvas)
127
+ text="#f3f4f6",
128
+ text_secondary="#9ca3af",
129
+ border="#4b5563",
130
+ disconnected="#5c2020",
131
+ )
132
+
133
+
134
+ class IslandsThemePlugin(ThemeProvider):
135
+ """Islands theme plugin.
136
+
137
+ A modern dark theme inspired by JetBrains' Islands design language.
138
+ UI components appear as distinct "islands" floating on a darker canvas,
139
+ with rounded corners, subtle elevation, and a purple accent color.
140
+
141
+ Key design principles:
142
+ - Visual separation: panels float on a darker background
143
+ - Rounded corners on major UI elements
144
+ - Purple accent color for focus and highlights
145
+ - Soft, balanced appearance for reduced eye strain
146
+ """
147
+
148
+ @property
149
+ def name(self) -> str:
150
+ return "islands"
151
+
152
+ @property
153
+ def display_name(self) -> str:
154
+ return "Islands"
155
+
156
+ @property
157
+ def is_dark(self) -> bool:
158
+ return True
159
+
160
+ # --- Islands color constants (used in both definition and CSS) ---
161
+ _BG = "#18181B" # background (deepest)
162
+ _ISLAND = "#1E1E22" # surface / island panels
163
+ _SEA = "#27272A" # sea (gaps, title bars, menubar)
164
+ _INPUT = "#1F1F23" # input fields
165
+ _BORDER = "#3F3F46"
166
+ _BORDER_HI = "#52525B"
167
+ _ACCENT = "#6B57FF"
168
+ _ACCENT_HOVER = "#5B47EF"
169
+ _ACCENT_PRESS = "#4B37DF"
170
+ _TEXT = "#FAFAFA"
171
+ _TEXT2 = "#A1A1AA"
172
+
173
+ def get_theme_definition(self) -> ThemeDefinition:
174
+ # Color palette inspired by JetBrains Islands theme
175
+ # Islands (surface) are darker, the sea (gaps between panels) is lighter
176
+ c = self # shortcut to class attrs
177
+ return ThemeDefinition(
178
+ primary=c._ACCENT,
179
+ secondary="#8B7FFF",
180
+ success="#3FB950",
181
+ warning="#D29922",
182
+ error="#F85149",
183
+ info="#58A6FF",
184
+ background=c._BG,
185
+ surface=c._ISLAND,
186
+ sea=c._SEA,
187
+ text=c._TEXT,
188
+ text_secondary=c._TEXT2,
189
+ border=c._BORDER,
190
+ connected="#3FB950",
191
+ disconnected="#5C2323",
192
+ # No css_overrides: the islands aesthetic now comes from the
193
+ # Islands-mode toggle (generate_islands_stylesheet), applied on top
194
+ # of this palette when enabled — consistent across all themes.
195
+ )
196
+
197
+
198
+ def _build_islands_css(c) -> str:
199
+ """Build Islands CSS overrides from the class color constants."""
200
+ return f"""
201
+ /* Islands Theme - Visual separation and rounded corners */
202
+
203
+ /* --------------------------------------------------------------------------
204
+ Menu bar — sea color, sits above the islands
205
+ -------------------------------------------------------------------------- */
206
+ QMenuBar {{
207
+ background: {c._SEA};
208
+ color: {c._TEXT};
209
+ border: none;
210
+ padding: 2px 4px;
211
+ spacing: 2px;
212
+ }}
213
+
214
+ QMenuBar::item {{
215
+ background: transparent;
216
+ padding: 4px 8px;
217
+ border-radius: 6px;
218
+ }}
219
+
220
+ QMenuBar::item:selected {{
221
+ background: {c._BORDER};
222
+ }}
223
+
224
+ /* --------------------------------------------------------------------------
225
+ Menus — island-styled popups
226
+ -------------------------------------------------------------------------- */
227
+ QMenu {{
228
+ background-color: {c._SEA};
229
+ border: 1px solid {c._BORDER};
230
+ border-radius: 8px;
231
+ padding: 4px;
232
+ }}
233
+
234
+ QMenu::item {{
235
+ padding: 8px 24px;
236
+ border-radius: 4px;
237
+ margin: 2px 4px;
238
+ }}
239
+
240
+ QMenu::item:selected {{
241
+ background-color: {c._ACCENT};
242
+ color: white;
243
+ }}
244
+
245
+ QMenu::separator {{
246
+ height: 1px;
247
+ background: {c._BORDER};
248
+ margin: 6px 12px;
249
+ }}
250
+
251
+ /* Fix: Qt renders a white corner artifact on rounded menus.
252
+ Force the menu viewport (scroll area) to be transparent. */
253
+ QMenu QWidget {{
254
+ background: transparent;
255
+ }}
256
+
257
+ /* --------------------------------------------------------------------------
258
+ Group boxes — island containers
259
+ -------------------------------------------------------------------------- */
260
+ QGroupBox {{
261
+ border-radius: 8px;
262
+ margin-top: 12px;
263
+ padding: 12px 8px 8px 8px;
264
+ background-color: {c._SEA};
265
+ }}
266
+
267
+ QGroupBox::title {{
268
+ subcontrol-origin: margin;
269
+ left: 12px;
270
+ padding: 0 6px;
271
+ background-color: {c._SEA};
272
+ border-radius: 4px;
273
+ }}
274
+
275
+ /* --------------------------------------------------------------------------
276
+ Tabs
277
+ -------------------------------------------------------------------------- */
278
+ QTabWidget::pane {{
279
+ border: 1px solid {c._BORDER};
280
+ border-radius: 8px;
281
+ background: {c._SEA};
282
+ margin-top: -1px;
283
+ }}
284
+
285
+ QTabBar::tab {{
286
+ background: {c._BG};
287
+ border: 1px solid {c._BORDER};
288
+ border-bottom: none;
289
+ border-top-left-radius: 6px;
290
+ border-top-right-radius: 6px;
291
+ padding: 8px 16px;
292
+ margin-right: 2px;
293
+ }}
294
+
295
+ QTabBar::tab:selected {{
296
+ background: {c._SEA};
297
+ border-bottom-color: {c._SEA};
298
+ }}
299
+
300
+ QTabBar::tab:hover:!selected {{
301
+ background: {c._INPUT};
302
+ }}
303
+
304
+ /* --------------------------------------------------------------------------
305
+ Inputs
306
+ -------------------------------------------------------------------------- */
307
+ QLineEdit, QTextEdit, QPlainTextEdit {{
308
+ border-radius: 6px;
309
+ padding: 4px 8px;
310
+ background: {c._INPUT};
311
+ border: 1px solid {c._BORDER};
312
+ }}
313
+
314
+ QLineEdit:focus, QTextEdit:focus, QPlainTextEdit:focus {{
315
+ border-color: {c._ACCENT};
316
+ background: {c._SEA};
317
+ }}
318
+
319
+ QComboBox {{
320
+ border-radius: 6px;
321
+ padding: 4px 8px;
322
+ background: {c._INPUT};
323
+ border: 1px solid {c._BORDER};
324
+ }}
325
+
326
+ QComboBox:focus {{
327
+ border-color: {c._ACCENT};
328
+ }}
329
+
330
+ QComboBox::drop-down {{
331
+ border: none;
332
+ border-top-right-radius: 6px;
333
+ border-bottom-right-radius: 6px;
334
+ }}
335
+
336
+ QSpinBox, QDoubleSpinBox {{
337
+ border-radius: 6px;
338
+ padding: 4px;
339
+ background: {c._INPUT};
340
+ border: 1px solid {c._BORDER};
341
+ }}
342
+
343
+ QSpinBox:focus, QDoubleSpinBox:focus {{
344
+ border-color: {c._ACCENT};
345
+ }}
346
+
347
+ /* --------------------------------------------------------------------------
348
+ Buttons
349
+ -------------------------------------------------------------------------- */
350
+ QPushButton {{
351
+ background: {c._SEA};
352
+ border: 1px solid {c._BORDER};
353
+ border-radius: 6px;
354
+ padding: 4px 12px;
355
+ }}
356
+
357
+ QPushButton:hover {{
358
+ background: {c._BORDER};
359
+ border-color: {c._BORDER_HI};
360
+ }}
361
+
362
+ QPushButton:pressed {{
363
+ background: {c._BORDER_HI};
364
+ }}
365
+
366
+ QPushButton[primary="true"] {{
367
+ background: {c._ACCENT};
368
+ color: white;
369
+ border: none;
370
+ border-radius: 6px;
371
+ }}
372
+
373
+ QPushButton[primary="true"]:hover {{
374
+ background: {c._ACCENT_HOVER};
375
+ }}
376
+
377
+ QPushButton[primary="true"]:pressed {{
378
+ background: {c._ACCENT_PRESS};
379
+ }}
380
+
381
+ /* --------------------------------------------------------------------------
382
+ Scrollbars
383
+ -------------------------------------------------------------------------- */
384
+ QScrollBar:vertical {{
385
+ background: {c._BG};
386
+ width: 14px;
387
+ margin: 0;
388
+ border-radius: 7px;
389
+ }}
390
+
391
+ QScrollBar::handle:vertical {{
392
+ background: {c._BORDER};
393
+ min-height: 30px;
394
+ border-radius: 5px;
395
+ margin: 3px;
396
+ }}
397
+
398
+ QScrollBar::handle:vertical:hover {{
399
+ background: {c._BORDER_HI};
400
+ }}
401
+
402
+ QScrollBar:horizontal {{
403
+ background: {c._BG};
404
+ height: 14px;
405
+ margin: 0;
406
+ border-radius: 7px;
407
+ }}
408
+
409
+ QScrollBar::handle:horizontal {{
410
+ background: {c._BORDER};
411
+ min-width: 30px;
412
+ border-radius: 5px;
413
+ margin: 3px;
414
+ }}
415
+
416
+ QScrollBar::handle:horizontal:hover {{
417
+ background: {c._BORDER_HI};
418
+ }}
419
+
420
+ QScrollBar::add-line, QScrollBar::sub-line {{
421
+ border: none;
422
+ background: none;
423
+ height: 0;
424
+ width: 0;
425
+ }}
426
+
427
+ QScrollBar::add-page, QScrollBar::sub-page {{
428
+ background: none;
429
+ }}
430
+
431
+ /* --------------------------------------------------------------------------
432
+ Tooltips
433
+ -------------------------------------------------------------------------- */
434
+ QToolTip {{
435
+ background-color: {c._SEA};
436
+ color: {c._TEXT};
437
+ border: 1px solid {c._BORDER};
438
+ border-radius: 6px;
439
+ padding: 6px 10px;
440
+ }}
441
+
442
+ /* --------------------------------------------------------------------------
443
+ Progress bar
444
+ -------------------------------------------------------------------------- */
445
+ QProgressBar {{
446
+ border: none;
447
+ border-radius: 4px;
448
+ text-align: center;
449
+ background: {c._INPUT};
450
+ height: 8px;
451
+ }}
452
+
453
+ QProgressBar::chunk {{
454
+ background: {c._ACCENT};
455
+ border-radius: 4px;
456
+ }}
457
+
458
+ /* --------------------------------------------------------------------------
459
+ Tree / List / Table views
460
+ -------------------------------------------------------------------------- */
461
+ QTreeView, QListView, QTableView {{
462
+ border: 1px solid {c._BORDER};
463
+ border-radius: 8px;
464
+ background: {c._INPUT};
465
+ }}
466
+
467
+ QTreeView::item, QListView::item, QTableView::item {{
468
+ padding: 4px;
469
+ border-radius: 4px;
470
+ }}
471
+
472
+ QTreeView::item:selected, QListView::item:selected, QTableView::item:selected {{
473
+ background: {c._ACCENT};
474
+ color: white;
475
+ }}
476
+
477
+ QTreeView::item:hover:!selected, QListView::item:hover:!selected, QTableView::item:hover:!selected {{
478
+ background: {c._SEA};
479
+ }}
480
+
481
+ /* --------------------------------------------------------------------------
482
+ Headers
483
+ -------------------------------------------------------------------------- */
484
+ QHeaderView::section {{
485
+ background: {c._SEA};
486
+ border: none;
487
+ border-right: 1px solid {c._BORDER};
488
+ border-bottom: 1px solid {c._BORDER};
489
+ padding: 8px;
490
+ }}
491
+
492
+ QHeaderView::section:first {{
493
+ border-top-left-radius: 8px;
494
+ }}
495
+
496
+ QHeaderView::section:last {{
497
+ border-top-right-radius: 8px;
498
+ border-right: none;
499
+ }}
500
+
501
+ /* --------------------------------------------------------------------------
502
+ Splitters
503
+ -------------------------------------------------------------------------- */
504
+ QSplitter::handle {{
505
+ background: {c._BORDER};
506
+ }}
507
+
508
+ QSplitter::handle:horizontal {{
509
+ width: 2px;
510
+ }}
511
+
512
+ QSplitter::handle:vertical {{
513
+ height: 2px;
514
+ }}
515
+
516
+ /* --------------------------------------------------------------------------
517
+ Status bar
518
+ -------------------------------------------------------------------------- */
519
+ QStatusBar {{
520
+ background: {c._SEA};
521
+ border-top: none;
522
+ }}
523
+
524
+ QStatusBar::item {{
525
+ border: none;
526
+ }}
527
+ """
528
+
529
+
530
+ def _adjust(hex_color: str, amount: int) -> str:
531
+ """Lighten (+) or darken (-) a hex color by `amount` (~-255..255)."""
532
+ from PySide6.QtGui import QColor
533
+
534
+ qc = QColor(hex_color)
535
+ h, s, lightness, a = qc.getHslF()
536
+ lightness = max(0.0, min(1.0, lightness + amount / 255.0))
537
+ qc.setHslF(h, s, lightness, a)
538
+ return qc.name()
539
+
540
+
541
+ class _IslandsPalette:
542
+ """Adapt a ThemeColors palette to the color constants the islands CSS
543
+ expects, deriving the input/highlight/accent-state shades that aren't part
544
+ of ThemeColors from the base palette. Lets the islands aesthetic be
545
+ generated for ANY theme (driven by the Islands-mode toggle) rather than
546
+ being hard-coded in specific themes' css_overrides."""
547
+
548
+ def __init__(self, c: ThemeColors) -> None:
549
+ self._SEA = c.sea
550
+ self._BG = c.background
551
+ self._TEXT = c.text
552
+ self._BORDER = c.border
553
+ self._ACCENT = c.primary
554
+ self._INPUT = _adjust(c.background, 7) # slightly elevated field
555
+ self._BORDER_HI = _adjust(c.border, 18) # focus/hover border
556
+ self._ACCENT_HOVER = _adjust(c.primary, -16)
557
+ self._ACCENT_PRESS = _adjust(c.primary, -32)
558
+
559
+
560
+ def generate_islands_stylesheet(colors: ThemeColors) -> str:
561
+ """Islands aesthetic (rounded menus, inputs, scrollbars, tabs, etc.) for
562
+ any theme. Applied by ThemeManager when Islands mode is enabled, so the
563
+ look is consistent across themes instead of living in specific themes'
564
+ css_overrides."""
565
+ return _build_islands_css(_IslandsPalette(colors))
566
+
567
+
568
+ class CatppuccinMochaThemePlugin(ThemeProvider):
569
+ """Catppuccin Mocha theme plugin.
570
+
571
+ Dark variant of the Catppuccin palette — warm, pastel colors on a deep
572
+ navy base. Mauve accent, soft text, calm contrast.
573
+ """
574
+
575
+ @property
576
+ def name(self) -> str:
577
+ return "catppuccin_mocha"
578
+
579
+ @property
580
+ def display_name(self) -> str:
581
+ return "Catppuccin Mocha"
582
+
583
+ @property
584
+ def is_dark(self) -> bool:
585
+ return True
586
+
587
+ def get_theme_definition(self) -> ThemeDefinition:
588
+ return ThemeDefinition(
589
+ primary="#cba6f7", # mauve
590
+ secondary="#f5c2e7", # pink
591
+ success="#a6e3a1", # green
592
+ warning="#fab387", # peach
593
+ error="#f38ba8", # red
594
+ info="#74c7ec", # sapphire
595
+ background="#1e1e2e", # base
596
+ surface="#313244", # surface0
597
+ sea="#3a3b50", # surface1 — lighter than surface (gaps)
598
+ text="#cdd6f4", # text
599
+ text_secondary="#a6adc8", # subtext0
600
+ border="#45475a", # surface1
601
+ connected="#a6e3a1",
602
+ disconnected="#5c2530",
603
+ )
604
+
605
+
606
+ class EldritchThemePlugin(ThemeProvider):
607
+ """Eldritch theme plugin.
608
+
609
+ Dark theme based on the Eldritch neovim colorscheme — deep blue-violet
610
+ background with magenta, cyan, and acid-green accents.
611
+ """
612
+
613
+ @property
614
+ def name(self) -> str:
615
+ return "eldritch"
616
+
617
+ @property
618
+ def display_name(self) -> str:
619
+ return "Eldritch"
620
+
621
+ @property
622
+ def is_dark(self) -> bool:
623
+ return True
624
+
625
+ def get_theme_definition(self) -> ThemeDefinition:
626
+ return ThemeDefinition(
627
+ primary="#a48cf2", # magenta/purple
628
+ secondary="#04d1f9", # cyan
629
+ success="#37f499", # green
630
+ warning="#f7c67f", # orange
631
+ error="#f16c75", # red
632
+ info="#39DDFD", # bright_cyan
633
+ background="#212337", # bg
634
+ surface="#292e42", # bg_highlight
635
+ sea="#31374f", # lighter than surface (gaps/canvas)
636
+ text="#ebfafa", # fg
637
+ text_secondary="#ABB4DA", # fg_dark
638
+ border="#414868", # terminal_black
639
+ connected="#37f499",
640
+ disconnected="#722f55", # magenta3
641
+ )
642
+
643
+
644
+ class EvangelionThemePlugin(ThemeProvider):
645
+ """Evangelion theme plugin.
646
+
647
+ NERV / Unit-01 inspired palette: deep violet background with the
648
+ signature Unit-01 purple and Kaworu green accents. Based on xero's
649
+ evangelion.nvim colorscheme.
650
+ """
651
+
652
+ @property
653
+ def name(self) -> str:
654
+ return "evangelion"
655
+
656
+ @property
657
+ def display_name(self) -> str:
658
+ return "Evangelion"
659
+
660
+ @property
661
+ def is_dark(self) -> bool:
662
+ return True
663
+
664
+ def get_theme_definition(self) -> ThemeDefinition:
665
+ return ThemeDefinition(
666
+ primary="#875FAF", # unit01
667
+ secondary="#87FF5F", # kaworu
668
+ success="#8EDF5F", # terminaldogma
669
+ warning="#D99145", # lcl
670
+ error="#DB6088", # misato
671
+ info="#AB92FC", # dummyplug
672
+ background="#201430", # midnight
673
+ surface="#201430", # midnight (panel cards)
674
+ sea="#39274C", # casper — lighter than surface (gaps)
675
+ text="#E1D6F8", # rei
676
+ text_secondary="#A1A0AD", # shinji
677
+ border="#483160", # longingus
678
+ connected="#8EDF5F",
679
+ disconnected="#5B2B41", # nerv
680
+ )
681
+
682
+
683
+ class AyakaThemePlugin(ThemeProvider):
684
+ """Ayaka (彩佳) theme plugin.
685
+
686
+ Twilight sakura — warm dark theme inspired by cherry blossoms against
687
+ an indigo evening sky. Soft pinks, wisteria purples, and lantern ambers
688
+ on a deep twilight base. Uses Islands mode for rounded, floating panels.
689
+
690
+ Designed by Ayaka, the Claude partner on this project.
691
+ """
692
+
693
+ @property
694
+ def name(self) -> str:
695
+ return "ayaka"
696
+
697
+ @property
698
+ def display_name(self) -> str:
699
+ return "Ayaka (彩佳)"
700
+
701
+ @property
702
+ def is_dark(self) -> bool:
703
+ return True
704
+
705
+ # --- Ayaka color constants ---
706
+ _BG = "#1a1b2e" # twilight indigo (deepest)
707
+ _ISLAND = "#1f2038" # deeper twilight (surface / panel cards)
708
+ _SEA = "#252640" # dusk cloud (sea / gaps) — lighter than surface
709
+ _INPUT = "#1e1f35" # input fields — slightly warmer than bg
710
+ _BORDER = "#3a3a58" # indigo border
711
+ _BORDER_HI = "#4a4a70" # highlighted border
712
+ _ACCENT = "#f0a0b8" # sakura pink
713
+ _ACCENT_HOVER = "#e890a8" # deeper sakura
714
+ _ACCENT_PRESS = "#d88098" # pressed sakura
715
+ _TEXT = "#e8e0f0" # lavender white
716
+ _TEXT2 = "#a0a0b8" # muted lavender
717
+
718
+ def get_theme_definition(self) -> ThemeDefinition:
719
+ c = self
720
+ return ThemeDefinition(
721
+ primary=c._ACCENT,
722
+ secondary="#b4a0d8", # wisteria
723
+ success="#90c8a0", # young leaves
724
+ warning="#e0b070", # lantern amber
725
+ error="#e07080", # camellia red
726
+ info="#80b8e0", # morning sky
727
+ background=c._BG,
728
+ surface=c._ISLAND,
729
+ sea=c._SEA,
730
+ text=c._TEXT,
731
+ text_secondary=c._TEXT2,
732
+ border=c._BORDER,
733
+ connected="#90c8a0",
734
+ disconnected="#5c2535", # deep plum
735
+ # No css_overrides — islands aesthetic comes from the Islands-mode
736
+ # toggle (see IslandsThemePlugin).
737
+ )