@pierre/theme 0.0.20 → 0.0.21

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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Pierre Theme
2
2
 
3
- Light and dark themes for Visual Studio Code, Cursor, and Shiki. Built for [Diffs.com](https://diffs.com) by [The Pierre Computer Company](https://pierre.computer).
3
+ Light and dark themes for Visual Studio Code, Cursor, Zed, and Shiki. Built for [Diffs.com](https://diffs.com) by [The Pierre Computer Company](https://pierre.computer).
4
4
 
5
5
  ## Preview
6
6
 
@@ -29,6 +29,14 @@ From the menu in Cursor:
29
29
 
30
30
  You can also install or download from the [Open VSX registry](https://open-vsx.org/extension/pierrecomputer/pierre-theme).
31
31
 
32
+ ### Zed
33
+
34
+ From the menu in Zed:
35
+
36
+ - Zed > Extensions (or hit Command+Shift+X or Control+Shift+X)
37
+ - Search for `Pierre`
38
+ - Click install
39
+
32
40
  ## Vibrant themes (Display P3)
33
41
 
34
42
  > [!NOTE]
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@pierre/theme",
3
3
  "displayName": "Pierre Theme",
4
4
  "description": "Pierre theme for Shiki, VS Code, and more",
5
- "version": "0.0.20",
5
+ "version": "0.0.21",
6
6
  "publisher": "pierrecomputer",
7
7
  "icon": "icon.png",
8
8
  "galleryBanner": {
package/src/build.ts CHANGED
@@ -2,22 +2,38 @@
2
2
  import { writeFileSync, mkdirSync } from "node:fs";
3
3
  import { light as rolesLight, dark as rolesDark } from "./palette";
4
4
  import { makeTheme } from "./theme";
5
+ import { makeZedThemeFamily } from "./zed-theme";
5
6
  import { convertRolesToP3 } from "./color-p3";
6
7
 
7
8
  mkdirSync("themes", { recursive: true });
9
+ mkdirSync("zed/themes", { recursive: true });
8
10
 
9
11
  // Convert palettes to Display P3 color space
10
12
  const rolesLightP3 = convertRolesToP3(rolesLight);
11
13
  const rolesDarkP3 = convertRolesToP3(rolesDark);
12
14
 
13
- const out = [
15
+ // ============================================
16
+ // VS Code Themes
17
+ // ============================================
18
+ const vscodeThemes = [
14
19
  { file: "themes/pierre-light.json", theme: makeTheme("Pierre Light", "light", rolesLight) },
15
20
  { file: "themes/pierre-dark.json", theme: makeTheme("Pierre Dark", "dark", rolesDark) },
16
21
  { file: "themes/pierre-light-vibrant.json", theme: makeTheme("Pierre Light Vibrant", "light", rolesLightP3) },
17
22
  { file: "themes/pierre-dark-vibrant.json", theme: makeTheme("Pierre Dark Vibrant", "dark", rolesDarkP3) }
18
23
  ];
19
24
 
20
- for (const {file, theme} of out) {
25
+ for (const {file, theme} of vscodeThemes) {
21
26
  writeFileSync(file, JSON.stringify(theme, null, 2), "utf8");
22
27
  console.log("Wrote", file);
23
28
  }
29
+
30
+ // ============================================
31
+ // Zed Theme Family
32
+ // ============================================
33
+ const zedTheme = makeZedThemeFamily("Pierre", "pierrecomputer", [
34
+ { name: "Pierre Light", appearance: "light", roles: rolesLight },
35
+ { name: "Pierre Dark", appearance: "dark", roles: rolesDark },
36
+ ]);
37
+
38
+ writeFileSync("zed/themes/pierre.json", JSON.stringify(zedTheme, null, 2), "utf8");
39
+ console.log("Wrote zed/themes/pierre.json");
package/src/palette.ts CHANGED
@@ -318,11 +318,11 @@ export const dark: Roles = {
318
318
  },
319
319
  border: {
320
320
  window: gray["1040"],
321
- editor: gray["920"],
322
- indentGuide: gray["940"],
321
+ editor: gray["980"],
322
+ indentGuide: gray["980"],
323
323
  indentGuideActive: gray["960"],
324
- inset: gray["920"],
325
- elevated: gray["960"]
324
+ inset: gray["980"],
325
+ elevated: gray["980"]
326
326
  },
327
327
  accent: {
328
328
  primary: blue["500"],
@@ -0,0 +1,606 @@
1
+ // src/zed-theme.ts
2
+ import type { Roles } from "./palette";
3
+
4
+ type ZedHighlightStyle = {
5
+ color?: string;
6
+ background_color?: string;
7
+ font_style?: "normal" | "italic" | "oblique";
8
+ font_weight?: 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900;
9
+ };
10
+
11
+ type ZedPlayerColor = {
12
+ cursor?: string;
13
+ background?: string;
14
+ selection?: string;
15
+ };
16
+
17
+ type ZedThemeStyle = {
18
+ // Backgrounds
19
+ background: string;
20
+ "background.appearance"?: "opaque" | "transparent" | "blurred";
21
+ "surface.background": string;
22
+ "elevated_surface.background": string;
23
+ "drop_target.background": string;
24
+
25
+ // Editor
26
+ "editor.background": string;
27
+ "editor.foreground": string;
28
+ "editor.gutter.background": string;
29
+ "editor.active_line.background": string;
30
+ "editor.active_line_number": string;
31
+ "editor.line_number": string;
32
+ "editor.highlighted_line.background": string;
33
+ "editor.indent_guide": string;
34
+ "editor.indent_guide_active": string;
35
+ "editor.invisible": string;
36
+ "editor.wrap_guide": string;
37
+ "editor.active_wrap_guide": string;
38
+ "editor.document_highlight.read_background": string;
39
+ "editor.document_highlight.write_background": string;
40
+ "editor.document_highlight.bracket_background": string;
41
+ "editor.subheader.background": string;
42
+
43
+ // Text
44
+ text: string;
45
+ "text.muted": string;
46
+ "text.placeholder": string;
47
+ "text.disabled": string;
48
+ "text.accent": string;
49
+
50
+ // Borders
51
+ border: string;
52
+ "border.variant": string;
53
+ "border.focused": string;
54
+ "border.selected": string;
55
+ "border.transparent": string;
56
+ "border.disabled": string;
57
+
58
+ // UI Elements
59
+ "element.background": string;
60
+ "element.hover": string;
61
+ "element.active": string;
62
+ "element.selected": string;
63
+ "element.disabled": string;
64
+ "ghost_element.background": string;
65
+ "ghost_element.hover": string;
66
+ "ghost_element.active": string;
67
+ "ghost_element.selected": string;
68
+ "ghost_element.disabled": string;
69
+
70
+ // Icons & Links
71
+ icon: string;
72
+ "icon.muted": string;
73
+ "icon.disabled": string;
74
+ "icon.placeholder": string;
75
+ "icon.accent": string;
76
+ "link_text.hover": string;
77
+
78
+ // Status colors
79
+ error: string;
80
+ "error.background": string;
81
+ "error.border": string;
82
+ warning: string;
83
+ "warning.background": string;
84
+ "warning.border": string;
85
+ success: string;
86
+ "success.background": string;
87
+ "success.border": string;
88
+ info: string;
89
+ "info.background": string;
90
+ "info.border": string;
91
+ hint: string;
92
+ "hint.background": string;
93
+ "hint.border": string;
94
+ predictive: string;
95
+ "predictive.background": string;
96
+ "predictive.border": string;
97
+ unreachable: string;
98
+ "unreachable.background": string;
99
+ "unreachable.border": string;
100
+
101
+ // Git status
102
+ created: string;
103
+ "created.background": string;
104
+ "created.border": string;
105
+ modified: string;
106
+ "modified.background": string;
107
+ "modified.border": string;
108
+ deleted: string;
109
+ "deleted.background": string;
110
+ "deleted.border": string;
111
+ conflict: string;
112
+ "conflict.background": string;
113
+ "conflict.border": string;
114
+ hidden: string;
115
+ "hidden.background": string;
116
+ "hidden.border": string;
117
+ ignored: string;
118
+ "ignored.background": string;
119
+ "ignored.border": string;
120
+ renamed: string;
121
+ "renamed.background": string;
122
+ "renamed.border": string;
123
+
124
+ // Search
125
+ "search.match_background": string;
126
+
127
+ // Tabs
128
+ "tab_bar.background": string;
129
+ "tab.active_background": string;
130
+ "tab.inactive_background": string;
131
+
132
+ // Toolbar & Title bar
133
+ "toolbar.background": string;
134
+ "title_bar.background": string;
135
+ "title_bar.inactive_background": string;
136
+
137
+ // Panel & Status bar
138
+ "panel.background": string;
139
+ "panel.focused_border": string;
140
+ "status_bar.background": string;
141
+
142
+ // Scrollbar
143
+ "scrollbar.thumb.background": string;
144
+ "scrollbar.thumb.hover_background": string;
145
+ "scrollbar.thumb.border": string;
146
+ "scrollbar.track.background": string;
147
+ "scrollbar.track.border": string;
148
+
149
+ // Terminal
150
+ "terminal.background": string;
151
+ "terminal.foreground": string;
152
+ "terminal.bright_foreground": string;
153
+ "terminal.dim_foreground": string;
154
+ "terminal.ansi.black": string;
155
+ "terminal.ansi.red": string;
156
+ "terminal.ansi.green": string;
157
+ "terminal.ansi.yellow": string;
158
+ "terminal.ansi.blue": string;
159
+ "terminal.ansi.magenta": string;
160
+ "terminal.ansi.cyan": string;
161
+ "terminal.ansi.white": string;
162
+ "terminal.ansi.bright_black": string;
163
+ "terminal.ansi.bright_red": string;
164
+ "terminal.ansi.bright_green": string;
165
+ "terminal.ansi.bright_yellow": string;
166
+ "terminal.ansi.bright_blue": string;
167
+ "terminal.ansi.bright_magenta": string;
168
+ "terminal.ansi.bright_cyan": string;
169
+ "terminal.ansi.bright_white": string;
170
+ "terminal.ansi.dim_black"?: string;
171
+ "terminal.ansi.dim_red"?: string;
172
+ "terminal.ansi.dim_green"?: string;
173
+ "terminal.ansi.dim_yellow"?: string;
174
+ "terminal.ansi.dim_blue"?: string;
175
+ "terminal.ansi.dim_magenta"?: string;
176
+ "terminal.ansi.dim_cyan"?: string;
177
+ "terminal.ansi.dim_white"?: string;
178
+
179
+ // Players (multiplayer cursors)
180
+ players: ZedPlayerColor[];
181
+
182
+ // Syntax highlighting
183
+ syntax: Record<string, ZedHighlightStyle>;
184
+ };
185
+
186
+ type ZedTheme = {
187
+ name: string;
188
+ appearance: "light" | "dark";
189
+ style: ZedThemeStyle;
190
+ };
191
+
192
+ type ZedThemeFamilyContent = {
193
+ $schema: string;
194
+ name: string;
195
+ author: string;
196
+ themes: ZedTheme[];
197
+ };
198
+
199
+ export type ZedThemeVariant = {
200
+ name: string;
201
+ appearance: "light" | "dark";
202
+ roles: Roles;
203
+ };
204
+
205
+ export function makeZedThemeFamily(
206
+ familyName: string,
207
+ author: string,
208
+ variants: ZedThemeVariant[]
209
+ ): ZedThemeFamilyContent {
210
+ return {
211
+ $schema: "https://zed.dev/schema/themes/v0.2.0.json",
212
+ name: familyName,
213
+ author,
214
+ themes: variants.map((v) => makeZedTheme(v.name, v.appearance, v.roles)),
215
+ };
216
+ }
217
+
218
+ function makeZedTheme(
219
+ name: string,
220
+ appearance: "light" | "dark",
221
+ c: Roles
222
+ ): ZedTheme {
223
+ const isDark = appearance === "dark";
224
+
225
+ return {
226
+ name,
227
+ appearance,
228
+ style: {
229
+ // Backgrounds
230
+ background: c.bg.window,
231
+ "surface.background": c.bg.window,
232
+ "elevated_surface.background": c.bg.elevated,
233
+ "drop_target.background": alpha(c.accent.primary, 0.15),
234
+
235
+ // Editor
236
+ "editor.background": c.bg.editor,
237
+ "editor.foreground": c.fg.base,
238
+ "editor.gutter.background": c.bg.editor,
239
+ "editor.active_line.background": alpha(c.accent.subtle, 0.55),
240
+ "editor.active_line_number": c.fg.fg2,
241
+ "editor.line_number": c.fg.fg3,
242
+ "editor.highlighted_line.background": alpha(c.accent.subtle, 0.35),
243
+ "editor.indent_guide": c.border.indentGuide,
244
+ "editor.indent_guide_active": c.border.indentGuideActive,
245
+ "editor.invisible": c.fg.fg4,
246
+ "editor.wrap_guide": c.border.indentGuide,
247
+ "editor.active_wrap_guide": c.border.indentGuideActive,
248
+ "editor.document_highlight.read_background": alpha(c.accent.primary, isDark ? 0.15 : 0.1),
249
+ "editor.document_highlight.write_background": alpha(c.accent.primary, isDark ? 0.25 : 0.18),
250
+ "editor.document_highlight.bracket_background": alpha(c.accent.primary, 0.2),
251
+ "editor.subheader.background": c.bg.window,
252
+
253
+ // Text
254
+ text: c.fg.base,
255
+ "text.muted": c.fg.fg3,
256
+ "text.placeholder": c.fg.fg4,
257
+ "text.disabled": c.fg.fg4,
258
+ "text.accent": c.accent.primary,
259
+
260
+ // Borders - use darker borders for dark themes
261
+ border: isDark ? c.border.indentGuide : c.border.editor,
262
+ "border.variant": isDark ? c.border.indentGuideActive : c.border.window,
263
+ "border.focused": c.accent.primary,
264
+ "border.selected": c.accent.primary,
265
+ "border.transparent": "transparent",
266
+ "border.disabled": isDark ? c.border.indentGuideActive : c.border.inset,
267
+
268
+ // UI Elements
269
+ "element.background": c.bg.inset,
270
+ "element.hover": alpha(c.accent.subtle, 0.5),
271
+ "element.active": alpha(c.accent.subtle, 0.7),
272
+ "element.selected": alpha(c.accent.subtle, isDark ? 0.6 : 0.8),
273
+ "element.disabled": alpha(c.bg.inset, 0.5),
274
+ "ghost_element.background": "transparent",
275
+ "ghost_element.hover": alpha(c.accent.subtle, 0.35),
276
+ "ghost_element.active": alpha(c.accent.subtle, 0.55),
277
+ "ghost_element.selected": alpha(c.accent.subtle, isDark ? 0.5 : 0.65),
278
+ "ghost_element.disabled": "transparent",
279
+
280
+ // Icons & Links
281
+ icon: c.fg.fg2,
282
+ "icon.muted": c.fg.fg3,
283
+ "icon.disabled": c.fg.fg4,
284
+ "icon.placeholder": c.fg.fg4,
285
+ "icon.accent": c.accent.primary,
286
+ "link_text.hover": c.accent.link,
287
+
288
+ // Status colors
289
+ error: c.states.danger,
290
+ "error.background": alpha(c.states.danger, 0.1),
291
+ "error.border": alpha(c.states.danger, 0.3),
292
+ warning: c.accent.primary,
293
+ "warning.background": alpha(c.accent.primary, 0.1),
294
+ "warning.border": alpha(c.accent.primary, 0.3),
295
+ success: c.states.success,
296
+ "success.background": alpha(c.states.success, 0.1),
297
+ "success.border": alpha(c.states.success, 0.3),
298
+ info: c.states.info,
299
+ "info.background": alpha(c.states.info, 0.1),
300
+ "info.border": alpha(c.states.info, 0.3),
301
+ hint: c.fg.fg3,
302
+ "hint.background": alpha(c.fg.fg3, 0.1),
303
+ "hint.border": alpha(c.fg.fg3, 0.2),
304
+ predictive: c.fg.fg4,
305
+ "predictive.background": alpha(c.fg.fg4, 0.1),
306
+ "predictive.border": alpha(c.fg.fg4, 0.2),
307
+ unreachable: c.fg.fg4,
308
+ "unreachable.background": alpha(c.fg.fg4, 0.05),
309
+ "unreachable.border": alpha(c.fg.fg4, 0.1),
310
+
311
+ // Git status
312
+ created: c.states.success,
313
+ "created.background": alpha(c.states.success, 0.1),
314
+ "created.border": alpha(c.states.success, 0.3),
315
+ modified: c.accent.primary,
316
+ "modified.background": alpha(c.accent.primary, 0.1),
317
+ "modified.border": alpha(c.accent.primary, 0.3),
318
+ deleted: c.states.danger,
319
+ "deleted.background": alpha(c.states.danger, 0.1),
320
+ "deleted.border": alpha(c.states.danger, 0.3),
321
+ conflict: c.accent.primary,
322
+ "conflict.background": alpha(c.accent.primary, 0.1),
323
+ "conflict.border": alpha(c.accent.primary, 0.3),
324
+ hidden: c.fg.fg4,
325
+ "hidden.background": alpha(c.fg.fg4, 0.05),
326
+ "hidden.border": alpha(c.fg.fg4, 0.1),
327
+ ignored: c.fg.fg3,
328
+ "ignored.background": alpha(c.fg.fg3, 0.05),
329
+ "ignored.border": alpha(c.fg.fg3, 0.1),
330
+ renamed: c.states.info,
331
+ "renamed.background": alpha(c.states.info, 0.1),
332
+ "renamed.border": alpha(c.states.info, 0.3),
333
+
334
+ // Search
335
+ "search.match_background": alpha(c.states.warn, 0.3),
336
+
337
+ // Tabs
338
+ "tab_bar.background": c.bg.window,
339
+ "tab.active_background": c.bg.window,
340
+ "tab.inactive_background": c.bg.window,
341
+
342
+ // Toolbar & Title bar
343
+ "toolbar.background": c.bg.window,
344
+ "title_bar.background": c.bg.window,
345
+ "title_bar.inactive_background": c.bg.window,
346
+
347
+ // Panel & Status bar
348
+ "panel.background": c.bg.window,
349
+ "panel.focused_border": c.accent.primary,
350
+ "status_bar.background": c.bg.window,
351
+
352
+ // Scrollbar
353
+ "scrollbar.thumb.background": alpha(c.fg.fg4, 0.3),
354
+ "scrollbar.thumb.hover_background": alpha(c.fg.fg4, 0.5),
355
+ "scrollbar.thumb.border": "transparent",
356
+ "scrollbar.track.background": "transparent",
357
+ "scrollbar.track.border": "transparent",
358
+
359
+ // Terminal
360
+ "terminal.background": c.bg.window,
361
+ "terminal.foreground": c.fg.fg2,
362
+ "terminal.bright_foreground": c.fg.base,
363
+ "terminal.dim_foreground": c.fg.fg3,
364
+ "terminal.ansi.black": c.ansi.black,
365
+ "terminal.ansi.red": c.ansi.red,
366
+ "terminal.ansi.green": c.ansi.green,
367
+ "terminal.ansi.yellow": c.ansi.yellow,
368
+ "terminal.ansi.blue": c.ansi.blue,
369
+ "terminal.ansi.magenta": c.ansi.magenta,
370
+ "terminal.ansi.cyan": c.ansi.cyan,
371
+ "terminal.ansi.white": c.ansi.white,
372
+ "terminal.ansi.bright_black": c.ansi.brightBlack,
373
+ "terminal.ansi.bright_red": c.ansi.brightRed,
374
+ "terminal.ansi.bright_green": c.ansi.brightGreen,
375
+ "terminal.ansi.bright_yellow": c.ansi.brightYellow,
376
+ "terminal.ansi.bright_blue": c.ansi.brightBlue,
377
+ "terminal.ansi.bright_magenta": c.ansi.brightMagenta,
378
+ "terminal.ansi.bright_cyan": c.ansi.brightCyan,
379
+ "terminal.ansi.bright_white": c.ansi.brightWhite,
380
+
381
+ // Players (multiplayer cursors) - use colors from the palette
382
+ players: [
383
+ { cursor: c.accent.primary, background: c.accent.primary, selection: alpha(c.accent.primary, 0.25) },
384
+ { cursor: c.states.success, background: c.states.success, selection: alpha(c.states.success, 0.25) },
385
+ { cursor: c.syntax.keyword, background: c.syntax.keyword, selection: alpha(c.syntax.keyword, 0.25) },
386
+ { cursor: c.syntax.func, background: c.syntax.func, selection: alpha(c.syntax.func, 0.25) },
387
+ { cursor: c.syntax.string, background: c.syntax.string, selection: alpha(c.syntax.string, 0.25) },
388
+ { cursor: c.states.warn, background: c.states.warn, selection: alpha(c.states.warn, 0.25) },
389
+ { cursor: c.syntax.type, background: c.syntax.type, selection: alpha(c.syntax.type, 0.25) },
390
+ { cursor: c.states.info, background: c.states.info, selection: alpha(c.states.info, 0.25) },
391
+ ],
392
+
393
+ // Syntax highlighting
394
+ syntax: {
395
+ // Comments
396
+ comment: { color: c.syntax.comment },
397
+ "comment.doc": { color: c.syntax.comment },
398
+
399
+ // Strings
400
+ string: { color: c.syntax.string },
401
+ "string.escape": { color: c.syntax.escape },
402
+ "string.regex": { color: c.syntax.regexp },
403
+ "string.special": { color: c.syntax.escape },
404
+ "string.special.symbol": { color: c.syntax.constant },
405
+
406
+ // Numbers & Constants
407
+ number: { color: c.syntax.number },
408
+ constant: { color: c.syntax.constant },
409
+ boolean: { color: c.syntax.number },
410
+
411
+ // Keywords
412
+ keyword: { color: c.syntax.keyword },
413
+ "keyword.operator": { color: c.syntax.operator },
414
+
415
+ // Functions
416
+ function: { color: c.syntax.func },
417
+ "function.method": { color: c.syntax.func },
418
+ "function.builtin": { color: c.syntax.func },
419
+ "function.special.definition": { color: c.syntax.func },
420
+ // CSS/SCSS function calls like var(), calc(), light-dark()
421
+ "function.call": { color: c.syntax.func },
422
+
423
+ // Types
424
+ type: { color: c.syntax.type },
425
+ "type.builtin": { color: c.syntax.type },
426
+ constructor: { color: c.syntax.type },
427
+
428
+ // Variables
429
+ variable: { color: c.syntax.variable },
430
+ "variable.builtin": { color: c.syntax.namespace }, // this, self, super
431
+ "variable.member": { color: c.syntax.variable },
432
+ "variable.parameter": { color: c.syntax.parameter },
433
+ "variable.special": { color: c.syntax.namespace },
434
+
435
+ // Properties - Used for JS object keys and property access
436
+ // Keep as variable color (orange) for JS compatibility
437
+ property: { color: c.syntax.variable },
438
+
439
+ // ========================================
440
+ // CSS/SCSS SPECIFIC
441
+ // ========================================
442
+ // CSS property names (e.g., position, display, margin) - blue
443
+ // These more specific scopes should override `property` for CSS
444
+ "property.css": { color: c.accent.primary },
445
+ "property.definition": { color: c.accent.primary },
446
+ property_name: { color: c.accent.primary },
447
+
448
+ // CSS property values that are keywords (e.g., relative, flex, auto, solid)
449
+ "value": { color: c.syntax.number },
450
+ "constant.css": { color: c.syntax.constant },
451
+ "string.plain": { color: c.syntax.number },
452
+ plain_value: { color: c.syntax.number },
453
+
454
+ // CSS selectors - element/tag selectors (p, ul, ol, div, table)
455
+ "tag.css": { color: c.syntax.tag },
456
+ tag_name: { color: c.syntax.tag },
457
+ // Class selectors (.prose, .container)
458
+ "class": { color: c.syntax.attribute },
459
+ class_name: { color: c.syntax.attribute },
460
+ "selector.class": { color: c.syntax.attribute },
461
+ // ID selectors (#main)
462
+ "selector.id": { color: c.syntax.func },
463
+ id_name: { color: c.syntax.func },
464
+ // Pseudo-elements and pseudo-classes (::before, :hover)
465
+ "selector.pseudo": { color: c.syntax.operator },
466
+ pseudo_class_selector: { color: c.syntax.operator },
467
+ pseudo_element_selector: { color: c.syntax.operator },
468
+
469
+ // @-rules (@use, @layer, @media, @mixin)
470
+ "keyword.directive": { color: c.syntax.keyword },
471
+ "keyword.control.at-rule": { color: c.syntax.keyword },
472
+ at_keyword: { color: c.syntax.keyword },
473
+
474
+ // SCSS/CSS variables - these should be orange (variable color)
475
+ // SCSS variables ($variable)
476
+ "variable.scss": { color: c.syntax.variable },
477
+ // CSS custom properties (--custom-prop) - orange
478
+ "variable.css": { color: c.syntax.variable },
479
+ "property.custom": { color: c.syntax.variable },
480
+
481
+ // Units (px, em, %, rem)
482
+ "unit": { color: c.syntax.number },
483
+ "number.unit": { color: c.syntax.number },
484
+
485
+ // Colors
486
+ "color": { color: c.syntax.constant },
487
+ "constant.color": { color: c.syntax.constant },
488
+
489
+ // Important
490
+ "keyword.important": { color: c.syntax.keyword },
491
+
492
+ // ========================================
493
+ // END CSS/SCSS SPECIFIC
494
+ // ========================================
495
+
496
+ // ========================================
497
+ // JAVASCRIPT/TYPESCRIPT SPECIFIC
498
+ // ========================================
499
+ // `this`, `self`, `super` - namespace/yellow color
500
+ "variable.language": { color: c.syntax.namespace },
501
+ this: { color: c.syntax.namespace },
502
+ self: { color: c.syntax.namespace },
503
+
504
+ // Class/Type names (Dropdown, BaseComponent, TypeError)
505
+ "type.class": { color: c.syntax.type },
506
+ // Note: class_name is defined in CSS section for CSS class selectors
507
+
508
+ // Object literal keys
509
+ "property.object": { color: c.syntax.variable },
510
+ property_identifier: { color: c.syntax.variable },
511
+ shorthand_property_identifier: { color: c.syntax.variable },
512
+ shorthand_property_identifier_pattern: { color: c.syntax.variable },
513
+
514
+ // Method definitions and calls
515
+ method_definition: { color: c.syntax.func },
516
+ "function.method.call": { color: c.syntax.func },
517
+
518
+ // Template literal interpolation
519
+ "string.template": { color: c.syntax.string },
520
+ template_string: { color: c.syntax.string },
521
+
522
+ // JSX
523
+ "tag.jsx": { color: c.syntax.tag },
524
+ "tag.component": { color: c.syntax.type },
525
+
526
+ // ========================================
527
+ // END JAVASCRIPT/TYPESCRIPT SPECIFIC
528
+ // ========================================
529
+
530
+ // Punctuation
531
+ punctuation: { color: c.syntax.punctuation },
532
+ "punctuation.bracket": { color: c.syntax.punctuation },
533
+ "punctuation.delimiter": { color: c.syntax.punctuation },
534
+ "punctuation.list_marker": { color: c.syntax.punctuation },
535
+ "punctuation.special": { color: c.syntax.keyword },
536
+
537
+ // Operators
538
+ operator: { color: c.syntax.operator },
539
+
540
+ // Tags (HTML/XML/JSX)
541
+ tag: { color: c.syntax.tag },
542
+ attribute: { color: c.syntax.attribute },
543
+
544
+ // Labels & Namespaces
545
+ label: { color: c.syntax.namespace },
546
+ namespace: { color: c.syntax.namespace },
547
+
548
+ // Embedded / Preprocessor
549
+ embedded: { color: c.fg.base },
550
+ preproc: { color: c.syntax.keyword },
551
+
552
+ // Markup
553
+ "text.literal": { color: c.syntax.string },
554
+ "markup.heading": { color: c.syntax.tag, font_weight: 700 },
555
+ "markup.bold": { color: c.syntax.constant, font_weight: 700 },
556
+ "markup.italic": { color: c.syntax.keyword, font_style: "italic" },
557
+ "markup.strikethrough": { color: c.fg.fg3 },
558
+ "markup.link.url": { color: c.accent.link },
559
+ "markup.link.text": { color: c.syntax.func },
560
+ "markup.quote": { color: c.syntax.comment, font_style: "italic" },
561
+ "markup.list": { color: c.syntax.tag },
562
+ "markup.list.numbered": { color: c.syntax.tag },
563
+ "markup.list.unnumbered": { color: c.syntax.tag },
564
+ "markup.raw": { color: c.syntax.string },
565
+ "markup.raw.inline": { color: c.syntax.string },
566
+ "markup.raw.block": { color: c.syntax.string },
567
+
568
+ // Diff
569
+ "diff.plus": { color: c.states.success },
570
+ "diff.minus": { color: c.states.danger },
571
+ "diff.delta": { color: c.states.warn },
572
+
573
+ // Links
574
+ link_text: { color: c.accent.link },
575
+ link_uri: { color: c.syntax.keyword },
576
+
577
+ // Emphasis & Primary
578
+ emphasis: { font_style: "italic" },
579
+ "emphasis.strong": { font_weight: 700 },
580
+ primary: { color: c.accent.primary },
581
+ title: { color: c.syntax.tag, font_weight: 700 },
582
+
583
+ // Predictive / AI suggestions
584
+ predictive: { color: c.fg.fg4, font_style: "italic" },
585
+ },
586
+ },
587
+ };
588
+ }
589
+
590
+ // Helper: add alpha to hex color
591
+ function alpha(color: string, opacity: number): string {
592
+ // Handle Display P3 color format
593
+ if (color.startsWith("color(display-p3")) {
594
+ if (color.includes(" / ")) {
595
+ return color.replace(/ \/ [\d.]+\)$/, ` / ${opacity.toFixed(6)})`);
596
+ } else {
597
+ return color.replace(/\)$/, ` / ${opacity.toFixed(6)})`);
598
+ }
599
+ }
600
+
601
+ // Handle hex color format
602
+ const alphaHex = Math.round(opacity * 255)
603
+ .toString(16)
604
+ .padStart(2, "0");
605
+ return `${color}${alphaHex}`;
606
+ }