claude-code-memory-explorer 0.5.1 → 0.6.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-code-memory-explorer",
3
- "version": "0.5.1",
3
+ "version": "0.6.0",
4
4
  "description": "Memory explorer dashboard for Claude Code",
5
5
  "main": "server.js",
6
6
  "bin": {
package/public/app.js CHANGED
@@ -92,11 +92,74 @@ function restorePlaceholders(html, placeholders) {
92
92
 
93
93
  // #region THEME
94
94
 
95
+ const COLOR_THEMES = [
96
+ ['ember', 'Ember'],
97
+ ['gruvbox', 'Gruvbox'],
98
+ ['catppuccin', 'Catppuccin'],
99
+ ['tokyo-night', 'Tokyo Night'],
100
+ ['solarized', 'Solarized'],
101
+ ['dracula', 'Dracula'],
102
+ ['nord', 'Nord'],
103
+ ['rose-pine', 'Rosé Pine'],
104
+ ['everforest', 'Everforest'],
105
+ ['kanagawa', 'Kanagawa'],
106
+ ['one-dark', 'One Dark'],
107
+ ['night-owl', 'Night Owl'],
108
+ ['monokai', 'Monokai Pro'],
109
+ ['github', 'GitHub'],
110
+ ['ayu', 'Ayu'],
111
+ ['vitesse', 'Vitesse'],
112
+ ['synthwave', "Synthwave '84"],
113
+ ];
114
+
95
115
  function loadTheme() {
96
116
  if (localStorage.getItem('theme') === 'light') document.body.classList.add('light');
117
+ buildThemeMenu();
118
+ const colorTheme = localStorage.getItem('color-theme');
119
+ if (colorTheme) document.body.dataset.colorTheme = colorTheme;
120
+ syncColorThemeMenu(colorTheme || 'ember');
97
121
  syncHljsTheme();
98
122
  }
99
123
 
124
+ // 'ember' (the :root default) has no override block — selecting it clears the attribute.
125
+ function setColorTheme(id) {
126
+ if (!id || id === 'ember') {
127
+ delete document.body.dataset.colorTheme;
128
+ localStorage.removeItem('color-theme');
129
+ } else {
130
+ document.body.dataset.colorTheme = id;
131
+ localStorage.setItem('color-theme', id);
132
+ }
133
+ syncColorThemeMenu(id);
134
+ }
135
+
136
+ function buildThemeMenu() {
137
+ const menu = document.getElementById('themeMenu');
138
+ menu.innerHTML = COLOR_THEMES.map(
139
+ ([id, label]) =>
140
+ `<button type="button" class="theme-menu-item" data-theme-id="${id}"
141
+ onclick="event.stopPropagation(); setColorTheme('${id}'); toggleThemeMenu()">
142
+ <span class="theme-swatch theme-swatch-${id}"><i class="sw-bg"></i><i class="sw-accent"></i><i class="sw-ink"></i></span>${label}
143
+ </button>`,
144
+ ).join('');
145
+ }
146
+
147
+ // biome-ignore lint/correctness/noUnusedVariables: called from topbar markup
148
+ function toggleThemeMenu(e) {
149
+ e?.stopPropagation();
150
+ const menu = document.getElementById('themeMenu');
151
+ const open = menu.classList.toggle('open');
152
+ if (open) {
153
+ document.addEventListener('click', () => menu.classList.remove('open'), { once: true });
154
+ }
155
+ }
156
+
157
+ function syncColorThemeMenu(id) {
158
+ document.querySelectorAll('.theme-menu-item').forEach((el) => {
159
+ el.classList.toggle('on', el.dataset.themeId === (id || 'ember'));
160
+ });
161
+ }
162
+
100
163
  function toggleTheme() {
101
164
  document.body.classList.toggle('light');
102
165
  localStorage.setItem('theme', document.body.classList.contains('light') ? 'light' : 'dark');
@@ -933,22 +996,36 @@ function _hubNavigate(app, url) {
933
996
 
934
997
  (function initHubTheme() {
935
998
  const getTheme = () => (document.body.classList.contains('light') ? 'light' : 'dark');
999
+ const getColorTheme = () => document.body.dataset.colorTheme || 'ember';
936
1000
  const hubOrigin = () => (window.__HUB__?.url ? new URL(window.__HUB__.url).origin : null);
1001
+ // lastTheme/lastColorTheme are updated synchronously when applying a hub
1002
+ // message, so the (async) observer sees no diff and doesn't echo it back.
937
1003
  let lastTheme = getTheme();
1004
+ let lastColorTheme = getColorTheme();
938
1005
  window.addEventListener('message', (e) => {
939
1006
  if (e.source !== window.parent || e.origin !== hubOrigin()) return;
940
1007
  if (e.data?.type !== 'hub:theme') return;
941
- if (getTheme() === e.data.theme) return;
942
- window.toggleTheme();
943
- lastTheme = getTheme();
1008
+ if (typeof e.data.colorTheme === 'string' && e.data.colorTheme !== getColorTheme()) {
1009
+ setColorTheme(e.data.colorTheme);
1010
+ lastColorTheme = getColorTheme();
1011
+ }
1012
+ if (getTheme() !== e.data.theme) {
1013
+ window.toggleTheme();
1014
+ lastTheme = getTheme();
1015
+ }
944
1016
  });
945
1017
  new MutationObserver(() => {
946
1018
  const t = getTheme();
947
- if (t === lastTheme) return;
1019
+ const ct = getColorTheme();
1020
+ if (t === lastTheme && ct === lastColorTheme) return;
948
1021
  lastTheme = t;
1022
+ lastColorTheme = ct;
949
1023
  const origin = hubOrigin();
950
- if (origin) window.parent.postMessage({ type: 'hub:theme', theme: t }, origin);
951
- }).observe(document.body, { attributes: true, attributeFilter: ['class'] });
1024
+ if (origin) window.parent.postMessage({ type: 'hub:theme', theme: t, colorTheme: ct }, origin);
1025
+ }).observe(document.body, {
1026
+ attributes: true,
1027
+ attributeFilter: ['class', 'data-color-theme'],
1028
+ });
952
1029
  })();
953
1030
 
954
1031
  // #endregion HUB_INTEGRATION
package/public/index.html CHANGED
@@ -8,6 +8,7 @@
8
8
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
9
9
  <link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600&family=Playfair+Display:wght@400;500;600&display=swap" rel="stylesheet">
10
10
  <link rel="stylesheet" href="style.css">
11
+ <link rel="stylesheet" href="themes.css">
11
12
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/styles/github-dark.min.css" id="hljsDark">
12
13
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/styles/github.min.css" id="hljsLight" disabled>
13
14
  <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/highlight.min.js"></script>
@@ -34,6 +35,10 @@
34
35
  <button class="topbar-btn" id="refreshBtn" title="Refresh (r)" onclick="refreshData()">
35
36
  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="23 4 23 10 17 10"/><path d="M20.49 15a9 9 0 11-2.12-9.36L23 10"/></svg>
36
37
  </button>
38
+ <span class="topbar-btn theme-picker" id="themePickerBtn" title="Color theme" onclick="toggleThemeMenu(event)">
39
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="13.5" cy="6.5" r=".5" fill="currentColor"/><circle cx="17.5" cy="10.5" r=".5" fill="currentColor"/><circle cx="8.5" cy="7.5" r=".5" fill="currentColor"/><circle cx="6.5" cy="12.5" r=".5" fill="currentColor"/><path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c.926 0 1.648-.746 1.648-1.688 0-.437-.18-.835-.437-1.125-.29-.289-.438-.652-.438-1.125a1.64 1.64 0 0 1 1.668-1.668h1.996c3.051 0 5.555-2.503 5.555-5.554C21.965 6.012 17.461 2 12 2z"/></svg>
40
+ <div class="theme-menu" id="themeMenu"></div>
41
+ </span>
37
42
  <button class="topbar-btn" id="themeBtn" title="Toggle theme (t)" onclick="toggleTheme()">
38
43
  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/></svg>
39
44
  </button>
package/public/style.css CHANGED
@@ -158,6 +158,75 @@ body {
158
158
  .topbar-btn.loading svg {
159
159
  animation: spin 1s linear infinite;
160
160
  }
161
+ /* theme picker: palette icon button + custom popover with per-theme swatches
162
+ (swatch colors are generated into themes.css) */
163
+ .theme-picker {
164
+ position: relative;
165
+ }
166
+ .theme-menu {
167
+ display: none;
168
+ position: absolute;
169
+ top: calc(100% + 6px);
170
+ right: 0;
171
+ z-index: 100;
172
+ min-width: 170px;
173
+ max-height: 70vh;
174
+ overflow-y: auto;
175
+ padding: 4px;
176
+ background: var(--bg-elevated);
177
+ border: 1px solid var(--border);
178
+ border-radius: 8px;
179
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
180
+ }
181
+ .theme-menu.open {
182
+ display: block;
183
+ }
184
+ .theme-menu-item {
185
+ display: flex;
186
+ align-items: center;
187
+ gap: 8px;
188
+ width: 100%;
189
+ padding: 6px 8px;
190
+ border: 0;
191
+ border-radius: 6px;
192
+ background: none;
193
+ color: var(--text-secondary);
194
+ font-family: var(--font-mono);
195
+ font-size: 11px;
196
+ text-transform: uppercase;
197
+ letter-spacing: 0.03em;
198
+ text-align: left;
199
+ cursor: pointer;
200
+ }
201
+ .theme-menu-item:hover {
202
+ background: var(--bg-hover);
203
+ color: var(--text-primary);
204
+ }
205
+ .theme-menu-item.on {
206
+ color: var(--accent-text);
207
+ }
208
+ /* 3-dot palette preview: surface, accent, ink (colors from themes.css vars) */
209
+ .theme-swatch {
210
+ display: inline-flex;
211
+ align-items: center;
212
+ gap: 3px;
213
+ flex: 0 0 auto;
214
+ }
215
+ .theme-swatch i {
216
+ width: 9px;
217
+ height: 9px;
218
+ border-radius: 50%;
219
+ border: 1px solid var(--sw-border);
220
+ }
221
+ .theme-swatch .sw-bg {
222
+ background: var(--sw-bg);
223
+ }
224
+ .theme-swatch .sw-accent {
225
+ background: var(--sw-accent);
226
+ }
227
+ .theme-swatch .sw-ink {
228
+ background: var(--sw-ink);
229
+ }
161
230
  /* #endregion TOPBAR */
162
231
 
163
232
  /* #region BUDGET_BAR */
@@ -0,0 +1,551 @@
1
+ /* GENERATED by scripts/generate-themes.mjs — do not edit by hand.
2
+ Color themes override only the shared design-token variables; semantic
3
+ colors (success/warning/error/scope/...) stay constant across themes. */
4
+
5
+ /* picker swatches */
6
+ .theme-swatch-ember { --sw-bg: #16181c; --sw-accent: #e86f33; --sw-ink: #f0f1f3; --sw-border: #363840; }
7
+ body.light .theme-swatch-ember { --sw-bg: #efede9; --sw-accent: #e86f33; --sw-ink: #0a0a0a; --sw-border: #cfcbc4; }
8
+ .theme-swatch-gruvbox { --sw-bg: #282828; --sw-accent: #fe8019; --sw-ink: #ebdbb2; --sw-border: #504945; }
9
+ body.light .theme-swatch-gruvbox { --sw-bg: #f3eee0; --sw-accent: #d65d0e; --sw-ink: #3c3836; --sw-border: #c9bc9d; }
10
+ .theme-swatch-catppuccin { --sw-bg: #181825; --sw-accent: #cba6f7; --sw-ink: #cdd6f4; --sw-border: #45475a; }
11
+ body.light .theme-swatch-catppuccin { --sw-bg: #eff1f5; --sw-accent: #8839ef; --sw-ink: #4c4f69; --sw-border: #bcc0cc; }
12
+ .theme-swatch-tokyo-night { --sw-bg: #1a1b26; --sw-accent: #7aa2f7; --sw-ink: #c0caf5; --sw-border: #3b4261; }
13
+ body.light .theme-swatch-tokyo-night { --sw-bg: #e9eaf0; --sw-accent: #2e7de9; --sw-ink: #343b58; --sw-border: #a8aecb; }
14
+ .theme-swatch-solarized { --sw-bg: #073642; --sw-accent: #cb4b16; --sw-ink: #93a1a1; --sw-border: #586e75; }
15
+ body.light .theme-swatch-solarized { --sw-bg: #f5efdc; --sw-accent: #cb4b16; --sw-ink: #073642; --sw-border: #d3cbb7; }
16
+ .theme-swatch-dracula { --sw-bg: #282a36; --sw-accent: #bd93f9; --sw-ink: #f8f8f2; --sw-border: #565a75; }
17
+ body.light .theme-swatch-dracula { --sw-bg: #f0f0f5; --sw-accent: #7c3aed; --sw-ink: #16161e; --sw-border: #c9c9d6; }
18
+ .theme-swatch-nord { --sw-bg: #2e3440; --sw-accent: #88c0d0; --sw-ink: #eceff4; --sw-border: #4c566a; }
19
+ body.light .theme-swatch-nord { --sw-bg: #eceff4; --sw-accent: #5e81ac; --sw-ink: #2e3440; --sw-border: #c2c9d6; }
20
+ .theme-swatch-rose-pine { --sw-bg: #1f1d2e; --sw-accent: #c4a7e7; --sw-ink: #e0def4; --sw-border: #403d52; }
21
+ body.light .theme-swatch-rose-pine { --sw-bg: #faf4ed; --sw-accent: #907aa9; --sw-ink: #575279; --sw-border: #dfdad9; }
22
+ .theme-swatch-everforest { --sw-bg: #2d353b; --sw-accent: #a7c080; --sw-ink: #d3c6aa; --sw-border: #475258; }
23
+ body.light .theme-swatch-everforest { --sw-bg: #fdf6e3; --sw-accent: #6f8352; --sw-ink: #4d5960; --sw-border: #d8d3ba; }
24
+ .theme-swatch-kanagawa { --sw-bg: #1f1f28; --sw-accent: #7e9cd8; --sw-ink: #dcd7ba; --sw-border: #54546d; }
25
+ body.light .theme-swatch-kanagawa { --sw-bg: #f2ecbc; --sw-accent: #4d699b; --sw-ink: #545464; --sw-border: #c7bf94; }
26
+ .theme-swatch-one-dark { --sw-bg: #282c34; --sw-accent: #61afef; --sw-ink: #d7dae0; --sw-border: #4b5263; }
27
+ body.light .theme-swatch-one-dark { --sw-bg: #fafafa; --sw-accent: #4078f2; --sw-ink: #383a42; --sw-border: #d4d4d6; }
28
+ .theme-swatch-night-owl { --sw-bg: #0b2942; --sw-accent: #82aaff; --sw-ink: #d6deeb; --sw-border: #5f7e97; }
29
+ body.light .theme-swatch-night-owl { --sw-bg: #f6f6f6; --sw-accent: #0c969b; --sw-ink: #403f53; --sw-border: #d0d0d0; }
30
+ .theme-swatch-monokai { --sw-bg: #2d2a2e; --sw-accent: #ffd866; --sw-ink: #fcfcfa; --sw-border: #5b595c; }
31
+ body.light .theme-swatch-monokai { --sw-bg: #f1efed; --sw-accent: #c08a00; --sw-ink: #2c292d; --sw-border: #cdc8c5; }
32
+ .theme-swatch-github { --sw-bg: #24292e; --sw-accent: #58a6ff; --sw-ink: #e1e4e8; --sw-border: #444d56; }
33
+ body.light .theme-swatch-github { --sw-bg: #f6f8fa; --sw-accent: #0366d6; --sw-ink: #24292e; --sw-border: #d1d5da; }
34
+ .theme-swatch-ayu { --sw-bg: #10141c; --sw-accent: #e6b450; --sw-ink: #bfbdb6; --sw-border: #2d3343; }
35
+ body.light .theme-swatch-ayu { --sw-bg: #f8f9fa; --sw-accent: #f2ae49; --sw-ink: #3d4149; --sw-border: #d8dde2; }
36
+ .theme-swatch-vitesse { --sw-bg: #181818; --sw-accent: #4d9375; --sw-ink: #dbd7ca; --sw-border: #333333; }
37
+ body.light .theme-swatch-vitesse { --sw-bg: #f7f7f7; --sw-accent: #1c6b48; --sw-ink: #393a34; --sw-border: #d6d6d6; }
38
+ .theme-swatch-synthwave { --sw-bg: #262335; --sw-accent: #ff7edb; --sw-ink: #ffffff; --sw-border: #495495; }
39
+ body.light .theme-swatch-synthwave { --sw-bg: #efecf6; --sw-accent: #c936a6; --sw-ink: #241b2f; --sw-border: #c5bcdd; }
40
+
41
+ /* Gruvbox */
42
+ body[data-color-theme="gruvbox"]:not(.light) {
43
+ --accent: #fe8019;
44
+ --accent-text: #f9b27c;
45
+ --accent-dim: rgba(254,128,25,0.25);
46
+ --accent-glow: rgba(254, 128, 25, 0.55);
47
+ --bg-deep: #1d2021;
48
+ --bg-surface: #282828;
49
+ --bg-elevated: #32302f;
50
+ --bg-hover: #3c3836;
51
+ --border: #504945;
52
+ --text-primary: #ebdbb2;
53
+ --text-secondary: #d5c4a1;
54
+ --text-tertiary: #bdae93;
55
+ --text-muted: #928374;
56
+ }
57
+ body.light[data-color-theme="gruvbox"] {
58
+ --accent: #d65d0e;
59
+ --accent-text: #af3a03;
60
+ --accent-dim: rgba(214,93,14,0.18);
61
+ --accent-glow: rgba(214, 93, 14, 0.5);
62
+ --bg-deep: #ede7d5;
63
+ --bg-surface: #f3eee0;
64
+ --bg-elevated: #faf7ec;
65
+ --bg-hover: #e4dcc6;
66
+ --border: #c9bc9d;
67
+ --text-primary: #3c3836;
68
+ --text-secondary: #504945;
69
+ --text-tertiary: #665c54;
70
+ --text-muted: #7c6f64;
71
+ }
72
+
73
+ /* Catppuccin */
74
+ body[data-color-theme="catppuccin"]:not(.light) {
75
+ --accent: #cba6f7;
76
+ --accent-text: #d8c2fa;
77
+ --accent-dim: rgba(203,166,247,0.25);
78
+ --accent-glow: rgba(203, 166, 247, 0.55);
79
+ --bg-deep: #11111b;
80
+ --bg-surface: #181825;
81
+ --bg-elevated: #1e1e2e;
82
+ --bg-hover: #313244;
83
+ --border: #45475a;
84
+ --text-primary: #cdd6f4;
85
+ --text-secondary: #bac2de;
86
+ --text-tertiary: #a6adc8;
87
+ --text-muted: #7f849c;
88
+ }
89
+ body.light[data-color-theme="catppuccin"] {
90
+ --accent: #8839ef;
91
+ --accent-text: #6f2dbd;
92
+ --accent-dim: rgba(136,57,239,0.18);
93
+ --accent-glow: rgba(136, 57, 239, 0.5);
94
+ --bg-deep: #e6e9ef;
95
+ --bg-surface: #eff1f5;
96
+ --bg-elevated: #ffffff;
97
+ --bg-hover: #ccd0da;
98
+ --border: #bcc0cc;
99
+ --text-primary: #4c4f69;
100
+ --text-secondary: #5c5f77;
101
+ --text-tertiary: #6c6f85;
102
+ --text-muted: #8c8fa1;
103
+ }
104
+
105
+ /* Tokyo Night */
106
+ body[data-color-theme="tokyo-night"]:not(.light) {
107
+ --accent: #7aa2f7;
108
+ --accent-text: #9ab8ff;
109
+ --accent-dim: rgba(122,162,247,0.25);
110
+ --accent-glow: rgba(122, 162, 247, 0.55);
111
+ --bg-deep: #16161e;
112
+ --bg-surface: #1a1b26;
113
+ --bg-elevated: #1f2335;
114
+ --bg-hover: #292e42;
115
+ --border: #3b4261;
116
+ --text-primary: #c0caf5;
117
+ --text-secondary: #a9b1d6;
118
+ --text-tertiary: #787c99;
119
+ --text-muted: #565f89;
120
+ }
121
+ body.light[data-color-theme="tokyo-night"] {
122
+ --accent: #2e7de9;
123
+ --accent-text: #1659c7;
124
+ --accent-dim: rgba(46,125,233,0.18);
125
+ --accent-glow: rgba(46, 125, 233, 0.5);
126
+ --bg-deep: #e1e2e7;
127
+ --bg-surface: #e9eaf0;
128
+ --bg-elevated: #f7f8fc;
129
+ --bg-hover: #d0d5e3;
130
+ --border: #a8aecb;
131
+ --text-primary: #343b58;
132
+ --text-secondary: #565a6e;
133
+ --text-tertiary: #6c6e75;
134
+ --text-muted: #848cb5;
135
+ }
136
+
137
+ /* Solarized */
138
+ body[data-color-theme="solarized"]:not(.light) {
139
+ --accent: #cb4b16;
140
+ --accent-text: #e9663a;
141
+ --accent-dim: rgba(203,75,22,0.25);
142
+ --accent-glow: rgba(203, 75, 22, 0.55);
143
+ --bg-deep: #002b36;
144
+ --bg-surface: #073642;
145
+ --bg-elevated: #0a4250;
146
+ --bg-hover: #11505f;
147
+ --border: #586e75;
148
+ --text-primary: #93a1a1;
149
+ --text-secondary: #839496;
150
+ --text-tertiary: #657b83;
151
+ --text-muted: #586e75;
152
+ }
153
+ body.light[data-color-theme="solarized"] {
154
+ --accent: #cb4b16;
155
+ --accent-text: #b34a12;
156
+ --accent-dim: rgba(203,75,22,0.18);
157
+ --accent-glow: rgba(203, 75, 22, 0.5);
158
+ --bg-deep: #eee8d5;
159
+ --bg-surface: #f5efdc;
160
+ --bg-elevated: #fdf6e3;
161
+ --bg-hover: #e4ddc8;
162
+ --border: #d3cbb7;
163
+ --text-primary: #073642;
164
+ --text-secondary: #586e75;
165
+ --text-tertiary: #657b83;
166
+ --text-muted: #839496;
167
+ }
168
+
169
+ /* Dracula */
170
+ body[data-color-theme="dracula"]:not(.light) {
171
+ --accent: #bd93f9;
172
+ --accent-text: #d6b5ff;
173
+ --accent-dim: rgba(189,147,249,0.25);
174
+ --accent-glow: rgba(189, 147, 249, 0.55);
175
+ --bg-deep: #21222c;
176
+ --bg-surface: #282a36;
177
+ --bg-elevated: #343746;
178
+ --bg-hover: #44475a;
179
+ --border: #565a75;
180
+ --text-primary: #f8f8f2;
181
+ --text-secondary: #d8d8d2;
182
+ --text-tertiary: #b0b3c5;
183
+ --text-muted: #6272a4;
184
+ }
185
+ body.light[data-color-theme="dracula"] {
186
+ --accent: #7c3aed;
187
+ --accent-text: #5b21b6;
188
+ --accent-dim: rgba(124,58,237,0.18);
189
+ --accent-glow: rgba(124, 58, 237, 0.5);
190
+ --bg-deep: #e8e8ee;
191
+ --bg-surface: #f0f0f5;
192
+ --bg-elevated: #fbfbfd;
193
+ --bg-hover: #dfdfe8;
194
+ --border: #c9c9d6;
195
+ --text-primary: #16161e;
196
+ --text-secondary: #34343f;
197
+ --text-tertiary: #5a5a68;
198
+ --text-muted: #787885;
199
+ }
200
+
201
+ /* Nord */
202
+ body[data-color-theme="nord"]:not(.light) {
203
+ --accent: #88c0d0;
204
+ --accent-text: #a8d8e8;
205
+ --accent-dim: rgba(136,192,208,0.25);
206
+ --accent-glow: rgba(136, 192, 208, 0.55);
207
+ --bg-deep: #272c36;
208
+ --bg-surface: #2e3440;
209
+ --bg-elevated: #3b4252;
210
+ --bg-hover: #434c5e;
211
+ --border: #4c566a;
212
+ --text-primary: #eceff4;
213
+ --text-secondary: #d8dee9;
214
+ --text-tertiary: #aeb6c5;
215
+ --text-muted: #7b88a1;
216
+ }
217
+ body.light[data-color-theme="nord"] {
218
+ --accent: #5e81ac;
219
+ --accent-text: #44688f;
220
+ --accent-dim: rgba(94,129,172,0.18);
221
+ --accent-glow: rgba(94, 129, 172, 0.5);
222
+ --bg-deep: #e5e9f0;
223
+ --bg-surface: #eceff4;
224
+ --bg-elevated: #f8f9fb;
225
+ --bg-hover: #d8dee9;
226
+ --border: #c2c9d6;
227
+ --text-primary: #2e3440;
228
+ --text-secondary: #3b4252;
229
+ --text-tertiary: #4c566a;
230
+ --text-muted: #6b7589;
231
+ }
232
+
233
+ /* Rosé Pine */
234
+ body[data-color-theme="rose-pine"]:not(.light) {
235
+ --accent: #c4a7e7;
236
+ --accent-text: #d9c4f2;
237
+ --accent-dim: rgba(196,167,231,0.25);
238
+ --accent-glow: rgba(196, 167, 231, 0.55);
239
+ --bg-deep: #191724;
240
+ --bg-surface: #1f1d2e;
241
+ --bg-elevated: #26233a;
242
+ --bg-hover: #34304e;
243
+ --border: #403d52;
244
+ --text-primary: #e0def4;
245
+ --text-secondary: #c5c2dd;
246
+ --text-tertiary: #908caa;
247
+ --text-muted: #6e6a86;
248
+ }
249
+ body.light[data-color-theme="rose-pine"] {
250
+ --accent: #907aa9;
251
+ --accent-text: #6f598c;
252
+ --accent-dim: rgba(144,122,169,0.18);
253
+ --accent-glow: rgba(144, 122, 169, 0.5);
254
+ --bg-deep: #f2e9e1;
255
+ --bg-surface: #faf4ed;
256
+ --bg-elevated: #fffaf3;
257
+ --bg-hover: #ebdfd4;
258
+ --border: #dfdad9;
259
+ --text-primary: #575279;
260
+ --text-secondary: #635e87;
261
+ --text-tertiary: #797593;
262
+ --text-muted: #9893a5;
263
+ }
264
+
265
+ /* Everforest */
266
+ body[data-color-theme="everforest"]:not(.light) {
267
+ --accent: #a7c080;
268
+ --accent-text: #c3d6a2;
269
+ --accent-dim: rgba(167,192,128,0.25);
270
+ --accent-glow: rgba(167, 192, 128, 0.55);
271
+ --bg-deep: #232a2e;
272
+ --bg-surface: #2d353b;
273
+ --bg-elevated: #343f44;
274
+ --bg-hover: #3d484d;
275
+ --border: #475258;
276
+ --text-primary: #d3c6aa;
277
+ --text-secondary: #bfb6a3;
278
+ --text-tertiary: #9da9a0;
279
+ --text-muted: #859289;
280
+ }
281
+ body.light[data-color-theme="everforest"] {
282
+ --accent: #6f8352;
283
+ --accent-text: #56683f;
284
+ --accent-dim: rgba(111,131,82,0.18);
285
+ --accent-glow: rgba(111, 131, 82, 0.5);
286
+ --bg-deep: #f4f0d9;
287
+ --bg-surface: #fdf6e3;
288
+ --bg-elevated: #fffbef;
289
+ --bg-hover: #efebd4;
290
+ --border: #d8d3ba;
291
+ --text-primary: #4d5960;
292
+ --text-secondary: #5c6a72;
293
+ --text-tertiary: #7a8478;
294
+ --text-muted: #939f91;
295
+ }
296
+
297
+ /* Kanagawa */
298
+ body[data-color-theme="kanagawa"]:not(.light) {
299
+ --accent: #7e9cd8;
300
+ --accent-text: #9fb9ec;
301
+ --accent-dim: rgba(126,156,216,0.25);
302
+ --accent-glow: rgba(126, 156, 216, 0.55);
303
+ --bg-deep: #16161d;
304
+ --bg-surface: #1f1f28;
305
+ --bg-elevated: #2a2a37;
306
+ --bg-hover: #363646;
307
+ --border: #54546d;
308
+ --text-primary: #dcd7ba;
309
+ --text-secondary: #c8c093;
310
+ --text-tertiary: #a6a69c;
311
+ --text-muted: #727169;
312
+ }
313
+ body.light[data-color-theme="kanagawa"] {
314
+ --accent: #4d699b;
315
+ --accent-text: #38537f;
316
+ --accent-dim: rgba(77,105,155,0.18);
317
+ --accent-glow: rgba(77, 105, 155, 0.5);
318
+ --bg-deep: #e5ddb0;
319
+ --bg-surface: #f2ecbc;
320
+ --bg-elevated: #faf5d2;
321
+ --bg-hover: #dcd5ac;
322
+ --border: #c7bf94;
323
+ --text-primary: #545464;
324
+ --text-secondary: #66667a;
325
+ --text-tertiary: #716e61;
326
+ --text-muted: #8a8775;
327
+ }
328
+
329
+ /* One Dark */
330
+ body[data-color-theme="one-dark"]:not(.light) {
331
+ --accent: #61afef;
332
+ --accent-text: #8cc7ff;
333
+ --accent-dim: rgba(97,175,239,0.25);
334
+ --accent-glow: rgba(97, 175, 239, 0.55);
335
+ --bg-deep: #21252b;
336
+ --bg-surface: #282c34;
337
+ --bg-elevated: #2f343e;
338
+ --bg-hover: #3e4452;
339
+ --border: #4b5263;
340
+ --text-primary: #d7dae0;
341
+ --text-secondary: #abb2bf;
342
+ --text-tertiary: #8b919e;
343
+ --text-muted: #5c6370;
344
+ }
345
+ body.light[data-color-theme="one-dark"] {
346
+ --accent: #4078f2;
347
+ --accent-text: #2c5dd4;
348
+ --accent-dim: rgba(64,120,242,0.18);
349
+ --accent-glow: rgba(64, 120, 242, 0.5);
350
+ --bg-deep: #eaeaeb;
351
+ --bg-surface: #fafafa;
352
+ --bg-elevated: #ffffff;
353
+ --bg-hover: #e0e0e2;
354
+ --border: #d4d4d6;
355
+ --text-primary: #383a42;
356
+ --text-secondary: #50525a;
357
+ --text-tertiary: #696c77;
358
+ --text-muted: #a0a1a7;
359
+ }
360
+
361
+ /* Night Owl */
362
+ body[data-color-theme="night-owl"]:not(.light) {
363
+ --accent: #82aaff;
364
+ --accent-text: #a8c4ff;
365
+ --accent-dim: rgba(130,170,255,0.25);
366
+ --accent-glow: rgba(130, 170, 255, 0.55);
367
+ --bg-deep: #011627;
368
+ --bg-surface: #0b2942;
369
+ --bg-elevated: #13344f;
370
+ --bg-hover: #1d3b53;
371
+ --border: #5f7e97;
372
+ --text-primary: #d6deeb;
373
+ --text-secondary: #b8c5d6;
374
+ --text-tertiary: #8ba3b8;
375
+ --text-muted: #637777;
376
+ }
377
+ body.light[data-color-theme="night-owl"] {
378
+ --accent: #0c969b;
379
+ --accent-text: #0a7479;
380
+ --accent-dim: rgba(12,150,155,0.18);
381
+ --accent-glow: rgba(12, 150, 155, 0.5);
382
+ --bg-deep: #ededed;
383
+ --bg-surface: #f6f6f6;
384
+ --bg-elevated: #fbfbfb;
385
+ --bg-hover: #e2e2e2;
386
+ --border: #d0d0d0;
387
+ --text-primary: #403f53;
388
+ --text-secondary: #545167;
389
+ --text-tertiary: #6f6e85;
390
+ --text-muted: #989fb1;
391
+ }
392
+
393
+ /* Monokai Pro */
394
+ body[data-color-theme="monokai"]:not(.light) {
395
+ --accent: #ffd866;
396
+ --accent-text: #ffe6a0;
397
+ --accent-dim: rgba(255,216,102,0.25);
398
+ --accent-glow: rgba(255, 216, 102, 0.55);
399
+ --bg-deep: #221f22;
400
+ --bg-surface: #2d2a2e;
401
+ --bg-elevated: #403e41;
402
+ --bg-hover: #4a484b;
403
+ --border: #5b595c;
404
+ --text-primary: #fcfcfa;
405
+ --text-secondary: #d9d8d6;
406
+ --text-tertiary: #939293;
407
+ --text-muted: #727072;
408
+ }
409
+ body.light[data-color-theme="monokai"] {
410
+ --accent: #c08a00;
411
+ --accent-text: #9a6e00;
412
+ --accent-dim: rgba(192,138,0,0.18);
413
+ --accent-glow: rgba(192, 138, 0, 0.5);
414
+ --bg-deep: #e9e6e4;
415
+ --bg-surface: #f1efed;
416
+ --bg-elevated: #fcfbfa;
417
+ --bg-hover: #e0dcda;
418
+ --border: #cdc8c5;
419
+ --text-primary: #2c292d;
420
+ --text-secondary: #46434a;
421
+ --text-tertiary: #6b686d;
422
+ --text-muted: #8d8a8d;
423
+ }
424
+
425
+ /* GitHub */
426
+ body[data-color-theme="github"]:not(.light) {
427
+ --accent: #58a6ff;
428
+ --accent-text: #85bdff;
429
+ --accent-dim: rgba(88,166,255,0.25);
430
+ --accent-glow: rgba(88, 166, 255, 0.55);
431
+ --bg-deep: #1f2428;
432
+ --bg-surface: #24292e;
433
+ --bg-elevated: #2b3138;
434
+ --bg-hover: #2f363d;
435
+ --border: #444d56;
436
+ --text-primary: #e1e4e8;
437
+ --text-secondary: #d1d5da;
438
+ --text-tertiary: #959da5;
439
+ --text-muted: #6a737d;
440
+ }
441
+ body.light[data-color-theme="github"] {
442
+ --accent: #0366d6;
443
+ --accent-text: #044289;
444
+ --accent-dim: rgba(3,102,214,0.18);
445
+ --accent-glow: rgba(3, 102, 214, 0.5);
446
+ --bg-deep: #f0f2f4;
447
+ --bg-surface: #f6f8fa;
448
+ --bg-elevated: #ffffff;
449
+ --bg-hover: #e8eaed;
450
+ --border: #d1d5da;
451
+ --text-primary: #24292e;
452
+ --text-secondary: #444d56;
453
+ --text-tertiary: #586069;
454
+ --text-muted: #6a737d;
455
+ }
456
+
457
+ /* Ayu */
458
+ body[data-color-theme="ayu"]:not(.light) {
459
+ --accent: #e6b450;
460
+ --accent-text: #f0cd85;
461
+ --accent-dim: rgba(230,180,80,0.25);
462
+ --accent-glow: rgba(230, 180, 80, 0.55);
463
+ --bg-deep: #0d1017;
464
+ --bg-surface: #10141c;
465
+ --bg-elevated: #141821;
466
+ --bg-hover: #1d2330;
467
+ --border: #2d3343;
468
+ --text-primary: #bfbdb6;
469
+ --text-secondary: #a8a6a0;
470
+ --text-tertiary: #8a9199;
471
+ --text-muted: #6c7380;
472
+ }
473
+ body.light[data-color-theme="ayu"] {
474
+ --accent: #f2ae49;
475
+ --accent-text: #b87514;
476
+ --accent-dim: rgba(242,174,73,0.18);
477
+ --accent-glow: rgba(242, 174, 73, 0.5);
478
+ --bg-deep: #eff1f3;
479
+ --bg-surface: #f8f9fa;
480
+ --bg-elevated: #fcfcfc;
481
+ --bg-hover: #e7eaed;
482
+ --border: #d8dde2;
483
+ --text-primary: #3d4149;
484
+ --text-secondary: #5c6166;
485
+ --text-tertiary: #787b80;
486
+ --text-muted: #8a9199;
487
+ }
488
+
489
+ /* Vitesse */
490
+ body[data-color-theme="vitesse"]:not(.light) {
491
+ --accent: #4d9375;
492
+ --accent-text: #6fb392;
493
+ --accent-dim: rgba(77,147,117,0.25);
494
+ --accent-glow: rgba(77, 147, 117, 0.55);
495
+ --bg-deep: #121212;
496
+ --bg-surface: #181818;
497
+ --bg-elevated: #1e1e1e;
498
+ --bg-hover: #262626;
499
+ --border: #333333;
500
+ --text-primary: #dbd7ca;
501
+ --text-secondary: #bfbaaa;
502
+ --text-tertiary: #8f8f85;
503
+ --text-muted: #758575;
504
+ }
505
+ body.light[data-color-theme="vitesse"] {
506
+ --accent: #1c6b48;
507
+ --accent-text: #145236;
508
+ --accent-dim: rgba(28,107,72,0.18);
509
+ --accent-glow: rgba(28, 107, 72, 0.5);
510
+ --bg-deep: #f0f0f0;
511
+ --bg-surface: #f7f7f7;
512
+ --bg-elevated: #ffffff;
513
+ --bg-hover: #e7e7e7;
514
+ --border: #d6d6d6;
515
+ --text-primary: #393a34;
516
+ --text-secondary: #4e4f47;
517
+ --text-tertiary: #6b6d63;
518
+ --text-muted: #a0ada0;
519
+ }
520
+
521
+ /* Synthwave '84 */
522
+ body[data-color-theme="synthwave"]:not(.light) {
523
+ --accent: #ff7edb;
524
+ --accent-text: #ffa9e7;
525
+ --accent-dim: rgba(255,126,219,0.25);
526
+ --accent-glow: rgba(255, 126, 219, 0.55);
527
+ --bg-deep: #241b2f;
528
+ --bg-surface: #262335;
529
+ --bg-elevated: #322a47;
530
+ --bg-hover: #3d3460;
531
+ --border: #495495;
532
+ --text-primary: #ffffff;
533
+ --text-secondary: #d8d6e8;
534
+ --text-tertiary: #b6b1d8;
535
+ --text-muted: #848bbd;
536
+ }
537
+ body.light[data-color-theme="synthwave"] {
538
+ --accent: #c936a6;
539
+ --accent-text: #9c2381;
540
+ --accent-dim: rgba(201,54,166,0.18);
541
+ --accent-glow: rgba(201, 54, 166, 0.5);
542
+ --bg-deep: #e6e2f0;
543
+ --bg-surface: #efecf6;
544
+ --bg-elevated: #fbfafd;
545
+ --bg-hover: #ddd7ec;
546
+ --border: #c5bcdd;
547
+ --text-primary: #241b2f;
548
+ --text-secondary: #3d3455;
549
+ --text-tertiary: #5c5380;
550
+ --text-muted: #7d76a3;
551
+ }