@stevejtrettel/shader-sandbox 0.1.3 → 0.1.4

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 (113) hide show
  1. package/README.md +220 -23
  2. package/bin/cli.js +106 -14
  3. package/dist-lib/app/App.d.ts +143 -15
  4. package/dist-lib/app/App.d.ts.map +1 -1
  5. package/dist-lib/app/App.js +1343 -108
  6. package/dist-lib/app/app.css +349 -24
  7. package/dist-lib/app/types.d.ts +48 -5
  8. package/dist-lib/app/types.d.ts.map +1 -1
  9. package/dist-lib/editor/EditorPanel.d.ts +2 -2
  10. package/dist-lib/editor/EditorPanel.d.ts.map +1 -1
  11. package/dist-lib/editor/EditorPanel.js +1 -1
  12. package/dist-lib/editor/editor-panel.css +55 -32
  13. package/dist-lib/editor/prism-editor.css +16 -16
  14. package/dist-lib/embed.js +1 -1
  15. package/dist-lib/engine/{ShadertoyEngine.d.ts → ShaderEngine.d.ts} +134 -10
  16. package/dist-lib/engine/ShaderEngine.d.ts.map +1 -0
  17. package/dist-lib/engine/ShaderEngine.js +1523 -0
  18. package/dist-lib/engine/glHelpers.d.ts +24 -0
  19. package/dist-lib/engine/glHelpers.d.ts.map +1 -1
  20. package/dist-lib/engine/glHelpers.js +88 -0
  21. package/dist-lib/engine/std140.d.ts +47 -0
  22. package/dist-lib/engine/std140.d.ts.map +1 -0
  23. package/dist-lib/engine/std140.js +119 -0
  24. package/dist-lib/engine/types.d.ts +55 -5
  25. package/dist-lib/engine/types.d.ts.map +1 -1
  26. package/dist-lib/engine/types.js +1 -1
  27. package/dist-lib/index.d.ts +4 -3
  28. package/dist-lib/index.d.ts.map +1 -1
  29. package/dist-lib/index.js +2 -1
  30. package/dist-lib/layouts/SplitLayout.d.ts +2 -1
  31. package/dist-lib/layouts/SplitLayout.d.ts.map +1 -1
  32. package/dist-lib/layouts/SplitLayout.js +3 -0
  33. package/dist-lib/layouts/TabbedLayout.d.ts.map +1 -1
  34. package/dist-lib/layouts/UILayout.d.ts +55 -0
  35. package/dist-lib/layouts/UILayout.d.ts.map +1 -0
  36. package/dist-lib/layouts/UILayout.js +147 -0
  37. package/dist-lib/layouts/default.css +2 -2
  38. package/dist-lib/layouts/index.d.ts +11 -1
  39. package/dist-lib/layouts/index.d.ts.map +1 -1
  40. package/dist-lib/layouts/index.js +17 -1
  41. package/dist-lib/layouts/split.css +33 -31
  42. package/dist-lib/layouts/tabbed.css +127 -74
  43. package/dist-lib/layouts/types.d.ts +14 -3
  44. package/dist-lib/layouts/types.d.ts.map +1 -1
  45. package/dist-lib/main.js +33 -0
  46. package/dist-lib/project/configHelpers.d.ts +45 -0
  47. package/dist-lib/project/configHelpers.d.ts.map +1 -0
  48. package/dist-lib/project/configHelpers.js +196 -0
  49. package/dist-lib/project/generatedLoader.d.ts +2 -2
  50. package/dist-lib/project/generatedLoader.d.ts.map +1 -1
  51. package/dist-lib/project/generatedLoader.js +23 -5
  52. package/dist-lib/project/loadProject.d.ts +6 -6
  53. package/dist-lib/project/loadProject.d.ts.map +1 -1
  54. package/dist-lib/project/loadProject.js +396 -144
  55. package/dist-lib/project/loaderHelper.d.ts +4 -4
  56. package/dist-lib/project/loaderHelper.d.ts.map +1 -1
  57. package/dist-lib/project/loaderHelper.js +278 -116
  58. package/dist-lib/project/types.d.ts +292 -13
  59. package/dist-lib/project/types.d.ts.map +1 -1
  60. package/dist-lib/project/types.js +13 -1
  61. package/dist-lib/styles/base.css +5 -1
  62. package/dist-lib/uniforms/UniformControls.d.ts +60 -0
  63. package/dist-lib/uniforms/UniformControls.d.ts.map +1 -0
  64. package/dist-lib/uniforms/UniformControls.js +518 -0
  65. package/dist-lib/uniforms/UniformStore.d.ts +74 -0
  66. package/dist-lib/uniforms/UniformStore.d.ts.map +1 -0
  67. package/dist-lib/uniforms/UniformStore.js +145 -0
  68. package/dist-lib/uniforms/UniformsPanel.d.ts +53 -0
  69. package/dist-lib/uniforms/UniformsPanel.d.ts.map +1 -0
  70. package/dist-lib/uniforms/UniformsPanel.js +124 -0
  71. package/dist-lib/uniforms/index.d.ts +11 -0
  72. package/dist-lib/uniforms/index.d.ts.map +1 -0
  73. package/dist-lib/uniforms/index.js +8 -0
  74. package/package.json +1 -1
  75. package/src/app/App.ts +1469 -126
  76. package/src/app/app.css +349 -24
  77. package/src/app/types.ts +53 -5
  78. package/src/editor/EditorPanel.ts +5 -5
  79. package/src/editor/editor-panel.css +55 -32
  80. package/src/editor/prism-editor.css +16 -16
  81. package/src/embed.ts +1 -1
  82. package/src/engine/ShaderEngine.ts +1934 -0
  83. package/src/engine/glHelpers.ts +117 -0
  84. package/src/engine/std140.ts +136 -0
  85. package/src/engine/types.ts +69 -5
  86. package/src/index.ts +4 -3
  87. package/src/layouts/SplitLayout.ts +8 -3
  88. package/src/layouts/TabbedLayout.ts +3 -3
  89. package/src/layouts/UILayout.ts +185 -0
  90. package/src/layouts/default.css +2 -2
  91. package/src/layouts/index.ts +20 -1
  92. package/src/layouts/split.css +33 -31
  93. package/src/layouts/tabbed.css +127 -74
  94. package/src/layouts/types.ts +19 -3
  95. package/src/layouts/ui.css +289 -0
  96. package/src/main.ts +39 -1
  97. package/src/project/configHelpers.ts +225 -0
  98. package/src/project/generatedLoader.ts +27 -6
  99. package/src/project/loadProject.ts +459 -173
  100. package/src/project/loaderHelper.ts +377 -130
  101. package/src/project/types.ts +360 -14
  102. package/src/styles/base.css +5 -1
  103. package/src/styles/theme.css +292 -0
  104. package/src/uniforms/UniformControls.ts +660 -0
  105. package/src/uniforms/UniformStore.ts +166 -0
  106. package/src/uniforms/UniformsPanel.ts +163 -0
  107. package/src/uniforms/index.ts +13 -0
  108. package/src/uniforms/uniform-controls.css +342 -0
  109. package/src/uniforms/uniforms-panel.css +277 -0
  110. package/templates/shaders/example-buffer/config.json +1 -0
  111. package/dist-lib/engine/ShadertoyEngine.d.ts.map +0 -1
  112. package/dist-lib/engine/ShadertoyEngine.js +0 -704
  113. package/src/engine/ShadertoyEngine.ts +0 -929
@@ -0,0 +1,147 @@
1
+ /**
2
+ * UI Layout
3
+ *
4
+ * Shader on left, uniform controls panel on right (~200px wide).
5
+ * Playback controls (play/pause, reset, screenshot) at bottom of UI panel.
6
+ * Responsive: stacks vertically on small screens (<600px).
7
+ */
8
+ import './ui.css';
9
+ export class UILayout {
10
+ constructor(opts) {
11
+ this.uniformControls = null;
12
+ this.playPauseButton = null;
13
+ // Callbacks (set by App)
14
+ this.onPlayPause = null;
15
+ this.onReset = null;
16
+ this.onScreenshot = null;
17
+ this.onUniformChange = null;
18
+ this.container = opts.container;
19
+ this.project = opts.project;
20
+ // Create root layout container
21
+ this.root = document.createElement('div');
22
+ this.root.className = 'layout-ui';
23
+ // Create canvas container (left side)
24
+ this.canvasContainer = document.createElement('div');
25
+ this.canvasContainer.className = 'ui-canvas-container';
26
+ // Create UI panel (right side)
27
+ this.uiPanel = document.createElement('div');
28
+ this.uiPanel.className = 'ui-panel';
29
+ // Create uniforms container (scrollable, vertically centered)
30
+ this.uniformsContainer = document.createElement('div');
31
+ this.uniformsContainer.className = 'ui-uniforms-container';
32
+ this.uiPanel.appendChild(this.uniformsContainer);
33
+ // Create playback controls container (fixed at bottom)
34
+ this.playbackContainer = document.createElement('div');
35
+ this.playbackContainer.className = 'ui-playback-container';
36
+ this.buildPlaybackControls();
37
+ this.uiPanel.appendChild(this.playbackContainer);
38
+ // Load uniform controls
39
+ this.loadUniformControls();
40
+ // Assemble and append to DOM
41
+ this.root.appendChild(this.canvasContainer);
42
+ this.root.appendChild(this.uiPanel);
43
+ this.container.appendChild(this.root);
44
+ }
45
+ getCanvasContainer() {
46
+ return this.canvasContainer;
47
+ }
48
+ /**
49
+ * Set callbacks for playback controls.
50
+ * Called by App after initialization.
51
+ */
52
+ setPlaybackCallbacks(callbacks) {
53
+ this.onPlayPause = callbacks.onPlayPause;
54
+ this.onReset = callbacks.onReset;
55
+ this.onScreenshot = callbacks.onScreenshot;
56
+ }
57
+ /**
58
+ * Set callback for uniform changes.
59
+ * Called by App after initialization.
60
+ */
61
+ setUniformCallback(callback) {
62
+ this.onUniformChange = callback;
63
+ }
64
+ /**
65
+ * Update play/pause button state.
66
+ */
67
+ setPaused(paused) {
68
+ if (this.playPauseButton) {
69
+ this.playPauseButton.innerHTML = paused
70
+ ? `<svg viewBox="0 0 16 16"><path d="M4 3v10l8-5-8-5z"/></svg>`
71
+ : `<svg viewBox="0 0 16 16"><path d="M5 3h2v10H5V3zm4 0h2v10H9V3z"/></svg>`;
72
+ this.playPauseButton.title = paused ? 'Play' : 'Pause';
73
+ }
74
+ }
75
+ dispose() {
76
+ if (this.uniformControls) {
77
+ this.uniformControls.destroy();
78
+ this.uniformControls = null;
79
+ }
80
+ this.container.innerHTML = '';
81
+ }
82
+ /**
83
+ * Build playback control buttons.
84
+ */
85
+ buildPlaybackControls() {
86
+ // Play/Pause button
87
+ this.playPauseButton = document.createElement('button');
88
+ this.playPauseButton.className = 'ui-control-button';
89
+ this.playPauseButton.title = 'Pause';
90
+ this.playPauseButton.innerHTML = `<svg viewBox="0 0 16 16"><path d="M5 3h2v10H5V3zm4 0h2v10H9V3z"/></svg>`;
91
+ this.playPauseButton.addEventListener('click', () => {
92
+ if (this.onPlayPause)
93
+ this.onPlayPause();
94
+ });
95
+ // Reset button
96
+ const resetButton = document.createElement('button');
97
+ resetButton.className = 'ui-control-button';
98
+ resetButton.title = 'Reset';
99
+ resetButton.innerHTML = `<svg viewBox="0 0 16 16"><path d="M8 3a5 5 0 1 0 4.546 2.914.5.5 0 0 1 .908-.417A6 6 0 1 1 8 2v1z"/><path d="M8 4.466V.534a.25.25 0 0 1 .41-.192l2.36 1.966c.12.1.12.284 0 .384L8.41 4.658A.25.25 0 0 1 8 4.466z"/></svg>`;
100
+ resetButton.addEventListener('click', () => {
101
+ if (this.onReset)
102
+ this.onReset();
103
+ });
104
+ // Screenshot button
105
+ const screenshotButton = document.createElement('button');
106
+ screenshotButton.className = 'ui-control-button';
107
+ screenshotButton.title = 'Screenshot';
108
+ screenshotButton.innerHTML = `<svg viewBox="0 0 16 16"><path d="M10.5 8.5a2.5 2.5 0 1 1-5 0 2.5 2.5 0 0 1 5 0z"/><path d="M2 4a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2h-1.172a2 2 0 0 1-1.414-.586l-.828-.828A2 2 0 0 0 9.172 2H6.828a2 2 0 0 0-1.414.586l-.828.828A2 2 0 0 1 3.172 4H2zm.5 2a.5.5 0 1 1 0-1 .5.5 0 0 1 0 1zm9 2.5a3.5 3.5 0 1 1-7 0 3.5 3.5 0 0 1 7 0z"/></svg>`;
109
+ screenshotButton.addEventListener('click', () => {
110
+ if (this.onScreenshot)
111
+ this.onScreenshot();
112
+ });
113
+ this.playbackContainer.appendChild(this.playPauseButton);
114
+ this.playbackContainer.appendChild(resetButton);
115
+ this.playbackContainer.appendChild(screenshotButton);
116
+ }
117
+ /**
118
+ * Load uniform controls dynamically.
119
+ */
120
+ async loadUniformControls() {
121
+ const uniforms = this.project.uniforms;
122
+ // If no uniforms, show empty state
123
+ if (!uniforms || Object.keys(uniforms).length === 0) {
124
+ const emptyState = document.createElement('div');
125
+ emptyState.className = 'ui-empty-state';
126
+ emptyState.textContent = 'No uniforms';
127
+ this.uniformsContainer.appendChild(emptyState);
128
+ return;
129
+ }
130
+ try {
131
+ const { UniformControls } = await import('../uniforms/UniformControls');
132
+ this.uniformControls = new UniformControls({
133
+ container: this.uniformsContainer,
134
+ uniforms: uniforms,
135
+ onChange: (name, value) => {
136
+ if (this.onUniformChange) {
137
+ this.onUniformChange(name, value);
138
+ }
139
+ },
140
+ });
141
+ }
142
+ catch (err) {
143
+ console.error('Failed to load uniform controls:', err);
144
+ this.uniformsContainer.textContent = 'Failed to load controls';
145
+ }
146
+ }
147
+ }
@@ -15,8 +15,8 @@
15
15
  position: relative;
16
16
  width: 800px;
17
17
  height: 600px;
18
- background: #000;
18
+ background: var(--bg-canvas);
19
19
  border-radius: 8px;
20
- box-shadow: 0 20px 60px rgba(0, 0, 0, 0.25), 0 5px 15px rgba(0, 0, 0, 0.15);
20
+ box-shadow: var(--shadow-lg), var(--shadow-sm);
21
21
  overflow: hidden;
22
22
  }
@@ -1,18 +1,28 @@
1
1
  /**
2
2
  * Layouts - Modular layout system for Shadertoy viewer
3
3
  *
4
- * Provides four layout modes:
4
+ * Provides five layout modes:
5
5
  * - Default: Canvas centered with styling
6
6
  * - Fullscreen: Canvas fills entire viewport
7
7
  * - Split: Canvas on left, code viewer on right
8
8
  * - Tabbed: Single window with tabs for shader and code
9
+ * - UI: Canvas on left, uniforms panel on right
9
10
  */
10
11
  export { FullscreenLayout } from './FullscreenLayout';
11
12
  export { DefaultLayout } from './DefaultLayout';
12
13
  export { SplitLayout } from './SplitLayout';
13
14
  export { TabbedLayout } from './TabbedLayout';
15
+ export { UILayout } from './UILayout';
14
16
  export type { BaseLayout, LayoutOptions, LayoutMode } from './types';
15
17
  import { BaseLayout, LayoutOptions, LayoutMode } from './types';
18
+ import { ThemeMode } from '../project/types';
19
+ /**
20
+ * Apply theme to the document.
21
+ * Sets the data-theme attribute on the html element.
22
+ *
23
+ * @param theme - Theme mode to apply ('light', 'dark', or 'system')
24
+ */
25
+ export declare function applyTheme(theme: ThemeMode): void;
16
26
  /**
17
27
  * Factory function to create the appropriate layout based on mode.
18
28
  *
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/layouts/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAMrE,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAEhE;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,UAAU,EAChB,OAAO,EAAE,aAAa,GACrB,UAAU,CAWZ"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/layouts/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAOrE,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,CAEjD;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,UAAU,EAChB,OAAO,EAAE,aAAa,GACrB,UAAU,CAgBZ"}
@@ -1,20 +1,32 @@
1
1
  /**
2
2
  * Layouts - Modular layout system for Shadertoy viewer
3
3
  *
4
- * Provides four layout modes:
4
+ * Provides five layout modes:
5
5
  * - Default: Canvas centered with styling
6
6
  * - Fullscreen: Canvas fills entire viewport
7
7
  * - Split: Canvas on left, code viewer on right
8
8
  * - Tabbed: Single window with tabs for shader and code
9
+ * - UI: Canvas on left, uniforms panel on right
9
10
  */
10
11
  export { FullscreenLayout } from './FullscreenLayout';
11
12
  export { DefaultLayout } from './DefaultLayout';
12
13
  export { SplitLayout } from './SplitLayout';
13
14
  export { TabbedLayout } from './TabbedLayout';
15
+ export { UILayout } from './UILayout';
14
16
  import { FullscreenLayout } from './FullscreenLayout';
15
17
  import { DefaultLayout } from './DefaultLayout';
16
18
  import { SplitLayout } from './SplitLayout';
17
19
  import { TabbedLayout } from './TabbedLayout';
20
+ import { UILayout } from './UILayout';
21
+ /**
22
+ * Apply theme to the document.
23
+ * Sets the data-theme attribute on the html element.
24
+ *
25
+ * @param theme - Theme mode to apply ('light', 'dark', or 'system')
26
+ */
27
+ export function applyTheme(theme) {
28
+ document.documentElement.setAttribute('data-theme', theme);
29
+ }
18
30
  /**
19
31
  * Factory function to create the appropriate layout based on mode.
20
32
  *
@@ -23,6 +35,8 @@ import { TabbedLayout } from './TabbedLayout';
23
35
  * @returns Layout instance implementing BaseLayout interface
24
36
  */
25
37
  export function createLayout(mode, options) {
38
+ // Apply theme from project configuration
39
+ applyTheme(options.project.theme);
26
40
  switch (mode) {
27
41
  case 'fullscreen':
28
42
  return new FullscreenLayout(options);
@@ -32,5 +46,7 @@ export function createLayout(mode, options) {
32
46
  return new SplitLayout(options);
33
47
  case 'tabbed':
34
48
  return new TabbedLayout(options);
49
+ case 'ui':
50
+ return new UILayout(options);
35
51
  }
36
52
  }
@@ -16,9 +16,9 @@
16
16
  .layout-split .canvas-container {
17
17
  position: relative;
18
18
  flex: 1;
19
- background: #000;
19
+ background: var(--bg-canvas);
20
20
  border-radius: 8px;
21
- box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2), 0 3px 8px rgba(0, 0, 0, 0.12);
21
+ box-shadow: var(--shadow-md), var(--shadow-sm);
22
22
  overflow: hidden;
23
23
  }
24
24
 
@@ -27,17 +27,17 @@
27
27
  flex: 1;
28
28
  display: flex;
29
29
  flex-direction: column;
30
- background: white;
30
+ background: var(--bg-secondary);
31
31
  border-radius: 8px;
32
- box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2), 0 3px 8px rgba(0, 0, 0, 0.12);
32
+ box-shadow: var(--shadow-md), var(--shadow-sm);
33
33
  overflow: hidden;
34
34
  }
35
35
 
36
36
  /* ===== Code Panel ===== */
37
37
  .tab-bar {
38
38
  display: flex;
39
- background: #f8f8f8;
40
- border-bottom: 1px solid #e0e0e0;
39
+ background: var(--tab-bg);
40
+ border-bottom: 1px solid var(--border-primary);
41
41
  padding: 8px 8px 0 8px;
42
42
  gap: 4px;
43
43
  }
@@ -50,17 +50,18 @@
50
50
  font-size: 13px;
51
51
  font-family: 'Monaco', 'Menlo', 'Courier New', monospace;
52
52
  cursor: pointer;
53
- transition: background 0.2s;
54
- color: #666;
53
+ transition: background 0.2s, color 0.2s;
54
+ color: var(--tab-text);
55
55
  }
56
56
 
57
57
  .tab-button:hover {
58
- background: #e8e8e8;
58
+ background: var(--button-bg-hover);
59
+ color: var(--tab-text-hover);
59
60
  }
60
61
 
61
62
  .tab-button.active {
62
- background: white;
63
- color: #000;
63
+ background: var(--bg-secondary);
64
+ color: var(--tab-text-active);
64
65
  font-weight: 500;
65
66
  }
66
67
 
@@ -69,10 +70,10 @@
69
70
  top: 12px;
70
71
  right: 12px;
71
72
  padding: 6px;
72
- background: transparent;
73
+ background: var(--button-bg);
73
74
  border: none;
74
75
  border-radius: 4px;
75
- color: #666;
76
+ color: var(--button-text);
76
77
  cursor: pointer;
77
78
  transition: all 0.2s;
78
79
  z-index: 10;
@@ -82,8 +83,8 @@
82
83
  }
83
84
 
84
85
  .copy-button:hover {
85
- background: rgba(0, 0, 0, 0.05);
86
- color: #333;
86
+ background: var(--button-bg-hover);
87
+ color: var(--button-text-hover);
87
88
  }
88
89
 
89
90
  .copy-button:active {
@@ -91,7 +92,7 @@
91
92
  }
92
93
 
93
94
  .copy-button.copied {
94
- color: #4caf50;
95
+ color: var(--success-text);
95
96
  }
96
97
 
97
98
  .code-viewer {
@@ -99,7 +100,7 @@
99
100
  min-height: 0; /* Allow shrinking below content size in flexbox */
100
101
  overflow: auto;
101
102
  position: relative;
102
- background: white;
103
+ background: var(--code-bg);
103
104
  }
104
105
 
105
106
  /* Prism.js syntax highlighting */
@@ -109,7 +110,8 @@
109
110
  font-size: 13px;
110
111
  line-height: 1.5;
111
112
  font-family: 'Monaco', 'Menlo', 'Courier New', monospace;
112
- background: white;
113
+ background: var(--code-bg);
114
+ color: var(--code-text);
113
115
  }
114
116
 
115
117
  .code-viewer code {
@@ -117,23 +119,23 @@
117
119
  font-size: inherit;
118
120
  }
119
121
 
120
- /* Prism theme - simple light theme */
121
- .token.comment { color: #6a9955; }
122
- .token.keyword { color: #0000ff; }
123
- .token.string { color: #a31515; }
124
- .token.number { color: #098658; }
125
- .token.operator { color: #000000; }
126
- .token.function { color: #795e26; }
127
- .token.class-name { color: #267f99; }
128
- .token.punctuation { color: #000000; }
122
+ /* Prism theme - uses CSS variables */
123
+ .token.comment { color: var(--syntax-comment); }
124
+ .token.keyword { color: var(--syntax-keyword); }
125
+ .token.string { color: var(--syntax-string); }
126
+ .token.number { color: var(--syntax-number); }
127
+ .token.operator { color: var(--syntax-operator); }
128
+ .token.function { color: var(--syntax-function); }
129
+ .token.class-name { color: var(--syntax-class); }
130
+ .token.punctuation { color: var(--syntax-punctuation); }
129
131
 
130
132
  /* Image tab styling */
131
133
  .tab-button.image-tab {
132
- color: #7c4dff;
134
+ color: var(--accent-secondary);
133
135
  }
134
136
 
135
137
  .tab-button.image-tab.active {
136
- color: #7c4dff;
138
+ color: var(--accent-secondary);
137
139
  }
138
140
 
139
141
  /* Image viewer */
@@ -143,7 +145,7 @@
143
145
  justify-content: center;
144
146
  height: 100%;
145
147
  padding: 16px;
146
- background: #f5f5f5;
148
+ background: var(--image-viewer-bg);
147
149
  }
148
150
 
149
151
  .image-viewer img {
@@ -151,7 +153,7 @@
151
153
  max-height: 100%;
152
154
  object-fit: contain;
153
155
  border-radius: 4px;
154
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
156
+ box-shadow: var(--shadow-sm);
155
157
  }
156
158
 
157
159
  /* ===== Responsive adjustments ===== */