@grackle-ai/web-components 0.107.2

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 (279) hide show
  1. package/.rush/temp/3ae72563f781afd72723475938136f113846603e.untar.log +10 -0
  2. package/.rush/temp/bc1d5bf9201ce71abeaeaddd096deb9b0805d703.untar.log +10 -0
  3. package/.rush/temp/operation/_phase_build/all.log +18 -0
  4. package/.rush/temp/operation/_phase_build/log-chunks.jsonl +18 -0
  5. package/.rush/temp/operation/_phase_build/state.json +3 -0
  6. package/.rush/temp/operation/_phase_test/all.log +121 -0
  7. package/.rush/temp/operation/_phase_test/log-chunks.jsonl +121 -0
  8. package/.rush/temp/operation/_phase_test/state.json +3 -0
  9. package/.rush/temp/shrinkwrap-deps.json +938 -0
  10. package/.storybook/main.ts +22 -0
  11. package/.storybook/preview.tsx +30 -0
  12. package/config/rig.json +4 -0
  13. package/config/rush-project.json +12 -0
  14. package/dist/index.css +1 -0
  15. package/dist/index.js +39221 -0
  16. package/eslint.config.cjs +5 -0
  17. package/package.json +83 -0
  18. package/rush-logs/web-components._phase_build.cache.log +4 -0
  19. package/rush-logs/web-components._phase_test.cache.log +4 -0
  20. package/src/components/chat/ChatInput.module.scss +81 -0
  21. package/src/components/chat/ChatInput.stories.tsx +91 -0
  22. package/src/components/chat/ChatInput.tsx +168 -0
  23. package/src/components/chat/index.ts +6 -0
  24. package/src/components/dag/DagView.module.scss +149 -0
  25. package/src/components/dag/DagView.stories.tsx +125 -0
  26. package/src/components/dag/DagView.tsx +109 -0
  27. package/src/components/dag/TaskNode.stories.tsx +133 -0
  28. package/src/components/dag/TaskNode.tsx +40 -0
  29. package/src/components/dag/useDagLayout.ts +139 -0
  30. package/src/components/display/Breadcrumbs.module.scss +71 -0
  31. package/src/components/display/Breadcrumbs.stories.tsx +80 -0
  32. package/src/components/display/Breadcrumbs.tsx +46 -0
  33. package/src/components/display/Button.module.scss +110 -0
  34. package/src/components/display/Button.stories.tsx +88 -0
  35. package/src/components/display/Button.tsx +40 -0
  36. package/src/components/display/ConfirmDialog.module.scss +67 -0
  37. package/src/components/display/ConfirmDialog.stories.tsx +81 -0
  38. package/src/components/display/ConfirmDialog.tsx +88 -0
  39. package/src/components/display/CopyButton.module.scss +41 -0
  40. package/src/components/display/CopyButton.stories.tsx +78 -0
  41. package/src/components/display/CopyButton.tsx +64 -0
  42. package/src/components/display/DemoBanner.module.scss +37 -0
  43. package/src/components/display/DemoBanner.stories.tsx +40 -0
  44. package/src/components/display/DemoBanner.tsx +23 -0
  45. package/src/components/display/EventHoverRow.module.scss +102 -0
  46. package/src/components/display/EventHoverRow.stories.tsx +99 -0
  47. package/src/components/display/EventHoverRow.tsx +154 -0
  48. package/src/components/display/EventRenderer.module.scss +272 -0
  49. package/src/components/display/EventRenderer.stories.tsx +186 -0
  50. package/src/components/display/EventRenderer.tsx +271 -0
  51. package/src/components/display/EventStream.module.scss +93 -0
  52. package/src/components/display/EventStream.stories.tsx +249 -0
  53. package/src/components/display/EventStream.tsx +369 -0
  54. package/src/components/display/FloatingActionBar.module.scss +107 -0
  55. package/src/components/display/FloatingActionBar.stories.tsx +122 -0
  56. package/src/components/display/FloatingActionBar.tsx +119 -0
  57. package/src/components/display/SessionAttemptSelector.module.scss +50 -0
  58. package/src/components/display/SessionAttemptSelector.stories.tsx +78 -0
  59. package/src/components/display/SessionAttemptSelector.tsx +49 -0
  60. package/src/components/display/SessionPicker.module.scss +200 -0
  61. package/src/components/display/SessionPicker.stories.tsx +169 -0
  62. package/src/components/display/SessionPicker.tsx +214 -0
  63. package/src/components/display/Skeleton.module.scss +58 -0
  64. package/src/components/display/Skeleton.stories.tsx +94 -0
  65. package/src/components/display/Skeleton.tsx +127 -0
  66. package/src/components/display/Spinner.module.scss +41 -0
  67. package/src/components/display/Spinner.stories.tsx +66 -0
  68. package/src/components/display/Spinner.tsx +32 -0
  69. package/src/components/display/SplashScreen.module.scss +20 -0
  70. package/src/components/display/SplashScreen.stories.tsx +26 -0
  71. package/src/components/display/SplashScreen.tsx +16 -0
  72. package/src/components/display/SplitButton.module.scss +166 -0
  73. package/src/components/display/SplitButton.stories.tsx +95 -0
  74. package/src/components/display/SplitButton.tsx +128 -0
  75. package/src/components/display/Tooltip.module.scss +84 -0
  76. package/src/components/display/Tooltip.stories.tsx +240 -0
  77. package/src/components/display/Tooltip.tsx +184 -0
  78. package/src/components/display/extractText.test.tsx +48 -0
  79. package/src/components/display/index.ts +20 -0
  80. package/src/components/editable/EditableCheckbox.stories.tsx +54 -0
  81. package/src/components/editable/EditableCheckbox.tsx +39 -0
  82. package/src/components/editable/EditableField.module.scss +135 -0
  83. package/src/components/editable/EditableSelect.tsx +164 -0
  84. package/src/components/editable/EditableTextArea.stories.tsx +50 -0
  85. package/src/components/editable/EditableTextArea.tsx +148 -0
  86. package/src/components/editable/EditableTextField.stories.tsx +62 -0
  87. package/src/components/editable/EditableTextField.tsx +153 -0
  88. package/src/components/editable/EnvironmentSelect.module.scss +17 -0
  89. package/src/components/editable/EnvironmentSelect.stories.tsx +61 -0
  90. package/src/components/editable/EnvironmentSelect.tsx +87 -0
  91. package/src/components/editable/index.ts +13 -0
  92. package/src/components/editable/useEditableField.test.tsx +233 -0
  93. package/src/components/editable/useEditableField.ts +173 -0
  94. package/src/components/index.ts +20 -0
  95. package/src/components/knowledge/KnowledgeDetailPanel.module.scss +162 -0
  96. package/src/components/knowledge/KnowledgeDetailPanel.stories.tsx +208 -0
  97. package/src/components/knowledge/KnowledgeDetailPanel.tsx +122 -0
  98. package/src/components/knowledge/KnowledgeGraph.module.scss +110 -0
  99. package/src/components/knowledge/KnowledgeGraph.stories.tsx +180 -0
  100. package/src/components/knowledge/KnowledgeGraph.tsx +455 -0
  101. package/src/components/knowledge/KnowledgeNav.module.scss +130 -0
  102. package/src/components/knowledge/KnowledgeNav.stories.tsx +108 -0
  103. package/src/components/knowledge/KnowledgeNav.tsx +138 -0
  104. package/src/components/knowledge/index.ts +3 -0
  105. package/src/components/layout/AppNav.module.scss +82 -0
  106. package/src/components/layout/AppNav.stories.tsx +115 -0
  107. package/src/components/layout/AppNav.tsx +133 -0
  108. package/src/components/layout/BottomStatusBar.module.scss +58 -0
  109. package/src/components/layout/BottomStatusBar.stories.tsx +35 -0
  110. package/src/components/layout/BottomStatusBar.tsx +206 -0
  111. package/src/components/layout/Sidebar.module.scss +60 -0
  112. package/src/components/layout/Sidebar.stories.tsx +46 -0
  113. package/src/components/layout/Sidebar.tsx +84 -0
  114. package/src/components/layout/StatusBar.module.scss +108 -0
  115. package/src/components/layout/StatusBar.stories.tsx +119 -0
  116. package/src/components/layout/StatusBar.tsx +70 -0
  117. package/src/components/layout/index.ts +9 -0
  118. package/src/components/lists/EnvironmentNav.module.scss +118 -0
  119. package/src/components/lists/EnvironmentNav.stories.tsx +121 -0
  120. package/src/components/lists/EnvironmentNav.tsx +133 -0
  121. package/src/components/lists/FindingsNav.module.scss +126 -0
  122. package/src/components/lists/FindingsNav.tsx +146 -0
  123. package/src/components/lists/TaskList.module.scss +206 -0
  124. package/src/components/lists/TaskList.stories.tsx +401 -0
  125. package/src/components/lists/TaskList.tsx +509 -0
  126. package/src/components/lists/index.ts +6 -0
  127. package/src/components/lists/listHelpers.tsx +130 -0
  128. package/src/components/notifications/Callout.module.scss +83 -0
  129. package/src/components/notifications/Callout.stories.tsx +81 -0
  130. package/src/components/notifications/Callout.tsx +64 -0
  131. package/src/components/notifications/Toast.module.scss +86 -0
  132. package/src/components/notifications/Toast.stories.tsx +71 -0
  133. package/src/components/notifications/Toast.tsx +51 -0
  134. package/src/components/notifications/ToastContainer.module.scss +23 -0
  135. package/src/components/notifications/ToastContainer.stories.tsx +66 -0
  136. package/src/components/notifications/ToastContainer.tsx +29 -0
  137. package/src/components/notifications/UpdateBanner.stories.tsx +77 -0
  138. package/src/components/notifications/UpdateBanner.test.tsx +64 -0
  139. package/src/components/notifications/UpdateBanner.tsx +44 -0
  140. package/src/components/notifications/index.ts +8 -0
  141. package/src/components/panels/AboutPanel.stories.tsx +70 -0
  142. package/src/components/panels/AboutPanel.tsx +66 -0
  143. package/src/components/panels/AppearancePanel.stories.tsx +45 -0
  144. package/src/components/panels/AppearancePanel.tsx +97 -0
  145. package/src/components/panels/CredentialProvidersPanel.stories.tsx +62 -0
  146. package/src/components/panels/CredentialProvidersPanel.tsx +111 -0
  147. package/src/components/panels/EnvironmentEditPanel.module.scss +170 -0
  148. package/src/components/panels/EnvironmentEditPanel.stories.tsx +206 -0
  149. package/src/components/panels/EnvironmentEditPanel.tsx +785 -0
  150. package/src/components/panels/FindingsPanel.module.scss +94 -0
  151. package/src/components/panels/FindingsPanel.stories.tsx +109 -0
  152. package/src/components/panels/FindingsPanel.tsx +76 -0
  153. package/src/components/panels/KeyboardShortcutsPanel.module.scss +65 -0
  154. package/src/components/panels/KeyboardShortcutsPanel.stories.tsx +40 -0
  155. package/src/components/panels/KeyboardShortcutsPanel.tsx +104 -0
  156. package/src/components/panels/PluginsPanel.tsx +77 -0
  157. package/src/components/panels/SettingsPanel.module.scss +336 -0
  158. package/src/components/panels/TaskActionButtons.module.scss +22 -0
  159. package/src/components/panels/TaskActionButtons.stories.tsx +125 -0
  160. package/src/components/panels/TaskActionButtons.tsx +87 -0
  161. package/src/components/panels/TaskEditPanel.module.scss +202 -0
  162. package/src/components/panels/TaskEditPanel.stories.tsx +75 -0
  163. package/src/components/panels/TaskEditPanel.tsx +328 -0
  164. package/src/components/panels/TaskOverviewPanel.module.scss +236 -0
  165. package/src/components/panels/TaskOverviewPanel.stories.tsx +219 -0
  166. package/src/components/panels/TaskOverviewPanel.tsx +270 -0
  167. package/src/components/panels/TokensPanel.stories.tsx +131 -0
  168. package/src/components/panels/TokensPanel.tsx +143 -0
  169. package/src/components/panels/WorkpadPanel.module.scss +39 -0
  170. package/src/components/panels/WorkpadPanel.stories.tsx +56 -0
  171. package/src/components/panels/WorkpadPanel.tsx +63 -0
  172. package/src/components/panels/index.ts +13 -0
  173. package/src/components/personas/McpToolSelector.module.scss +109 -0
  174. package/src/components/personas/McpToolSelector.stories.tsx +129 -0
  175. package/src/components/personas/McpToolSelector.tsx +180 -0
  176. package/src/components/personas/PersonaManager.module.scss +233 -0
  177. package/src/components/personas/PersonaManager.stories.tsx +139 -0
  178. package/src/components/personas/PersonaManager.tsx +122 -0
  179. package/src/components/schedules/ScheduleManager.module.scss +98 -0
  180. package/src/components/schedules/ScheduleManager.stories.tsx +78 -0
  181. package/src/components/schedules/ScheduleManager.tsx +160 -0
  182. package/src/components/settings/SettingsNav.module.scss +82 -0
  183. package/src/components/settings/SettingsNav.stories.tsx +83 -0
  184. package/src/components/settings/SettingsNav.tsx +104 -0
  185. package/src/components/streams/StreamDetailPanel.module.scss +206 -0
  186. package/src/components/streams/StreamDetailPanel.stories.tsx +132 -0
  187. package/src/components/streams/StreamDetailPanel.tsx +119 -0
  188. package/src/components/streams/StreamList.module.scss +92 -0
  189. package/src/components/streams/StreamList.stories.tsx +99 -0
  190. package/src/components/streams/StreamList.tsx +114 -0
  191. package/src/components/streams/index.ts +10 -0
  192. package/src/components/tools/AgentToolCard.module.scss +118 -0
  193. package/src/components/tools/AgentToolCard.stories.tsx +304 -0
  194. package/src/components/tools/AgentToolCard.tsx +247 -0
  195. package/src/components/tools/FileEditCard.stories.tsx +138 -0
  196. package/src/components/tools/FileEditCard.tsx +160 -0
  197. package/src/components/tools/FileReadCard.stories.tsx +120 -0
  198. package/src/components/tools/FileReadCard.tsx +106 -0
  199. package/src/components/tools/FindingCard.stories.tsx +124 -0
  200. package/src/components/tools/FindingCard.tsx +178 -0
  201. package/src/components/tools/GenericToolCard.stories.tsx +80 -0
  202. package/src/components/tools/GenericToolCard.tsx +111 -0
  203. package/src/components/tools/IpcCard.stories.tsx +129 -0
  204. package/src/components/tools/IpcCard.tsx +178 -0
  205. package/src/components/tools/KnowledgeCard.stories.tsx +112 -0
  206. package/src/components/tools/KnowledgeCard.tsx +165 -0
  207. package/src/components/tools/MetadataCard.stories.tsx +32 -0
  208. package/src/components/tools/MetadataCard.tsx +39 -0
  209. package/src/components/tools/SearchCard.stories.tsx +74 -0
  210. package/src/components/tools/SearchCard.tsx +86 -0
  211. package/src/components/tools/ShellCard.stories.tsx +112 -0
  212. package/src/components/tools/ShellCard.tsx +106 -0
  213. package/src/components/tools/TaskCard.stories.tsx +123 -0
  214. package/src/components/tools/TaskCard.tsx +203 -0
  215. package/src/components/tools/TodoCard.module.scss +131 -0
  216. package/src/components/tools/TodoCard.stories.tsx +202 -0
  217. package/src/components/tools/TodoCard.tsx +200 -0
  218. package/src/components/tools/ToolCard.stories.tsx +177 -0
  219. package/src/components/tools/ToolCard.tsx +60 -0
  220. package/src/components/tools/ToolCardProps.ts +20 -0
  221. package/src/components/tools/ToolSearchCard.stories.tsx +81 -0
  222. package/src/components/tools/ToolSearchCard.tsx +86 -0
  223. package/src/components/tools/WorkpadCard.stories.tsx +106 -0
  224. package/src/components/tools/WorkpadCard.tsx +125 -0
  225. package/src/components/tools/classifyTool.test.ts +44 -0
  226. package/src/components/tools/classifyTool.ts +134 -0
  227. package/src/components/tools/parseDiff.ts +95 -0
  228. package/src/components/tools/parseShellOutput.ts +28 -0
  229. package/src/components/tools/toolCardHelpers.test.ts +53 -0
  230. package/src/components/tools/toolCards.module.scss +234 -0
  231. package/src/components/workspace/WorkspaceBoard.module.scss +238 -0
  232. package/src/components/workspace/WorkspaceBoard.stories.tsx +240 -0
  233. package/src/components/workspace/WorkspaceBoard.tsx +232 -0
  234. package/src/components/workspace/WorkspaceFormFields.module.scss +79 -0
  235. package/src/components/workspace/WorkspaceFormFields.stories.tsx +133 -0
  236. package/src/components/workspace/WorkspaceFormFields.tsx +185 -0
  237. package/src/context/GrackleContext.ts +28 -0
  238. package/src/context/GrackleContextTypes.ts +64 -0
  239. package/src/context/SidebarContext.tsx +53 -0
  240. package/src/context/ThemeContext.tsx +21 -0
  241. package/src/context/ToastContext.tsx +56 -0
  242. package/src/hooks/types.ts +864 -0
  243. package/src/hooks/useEventSelection.test.ts +204 -0
  244. package/src/hooks/useEventSelection.ts +158 -0
  245. package/src/hooks/useSmartScroll.ts +151 -0
  246. package/src/hooks/useTheme.ts +228 -0
  247. package/src/index.ts +210 -0
  248. package/src/mocks/MockGrackleProvider.tsx +1397 -0
  249. package/src/mocks/mockData.ts +1966 -0
  250. package/src/mocks/mockKnowledgeData.ts +294 -0
  251. package/src/scss.d.ts +12 -0
  252. package/src/styles/global.scss +244 -0
  253. package/src/styles/mixins.scss +278 -0
  254. package/src/styles/prism-theme.scss +148 -0
  255. package/src/styles/theme.scss +1102 -0
  256. package/src/test-utils/storybook-decorators.tsx +50 -0
  257. package/src/test-utils/storybook-helpers.ts +262 -0
  258. package/src/themes.ts +142 -0
  259. package/src/utils/boardColumns.ts +141 -0
  260. package/src/utils/breadcrumbs.test.ts +285 -0
  261. package/src/utils/breadcrumbs.ts +222 -0
  262. package/src/utils/dashboard.test.ts +156 -0
  263. package/src/utils/dashboard.ts +195 -0
  264. package/src/utils/eventContent.test.ts +353 -0
  265. package/src/utils/eventContent.ts +209 -0
  266. package/src/utils/findingCategory.ts +33 -0
  267. package/src/utils/format.ts +27 -0
  268. package/src/utils/iconSize.ts +18 -0
  269. package/src/utils/navigation.ts +205 -0
  270. package/src/utils/route-config.test.ts +128 -0
  271. package/src/utils/scrollUtils.test.ts +65 -0
  272. package/src/utils/scrollUtils.ts +49 -0
  273. package/src/utils/sessionEvents.test.ts +302 -0
  274. package/src/utils/sessionEvents.ts +233 -0
  275. package/src/utils/taskStatus.tsx +137 -0
  276. package/src/utils/time.ts +92 -0
  277. package/tsconfig.json +8 -0
  278. package/vite.config.ts +20 -0
  279. package/vitest.config.ts +10 -0
@@ -0,0 +1,1102 @@
1
+ @use 'sass:map';
2
+
3
+ // ============================================================================
4
+ // Design Tokens — Grackle Web UI
5
+ // ============================================================================
6
+ // Multi-theme token system. :root = glassmorphism. Default theme is Grackle (grackle-dark/grackle-light).
7
+ // [data-theme="grackle-light"] and [data-theme="grackle-dark"] are the brand theme.
8
+ // Additional themes use the define-theme mixin for compact palette definitions.
9
+ // Component styles consume these via var(--token-name).
10
+ // ============================================================================
11
+
12
+ // =============================================================================
13
+ // Theme Generator Mixin
14
+ // =============================================================================
15
+ // Produces all CSS custom properties from a compact SCSS map (~30 seed values).
16
+ // Derived variants (-dim, -fg, -subtle, -border) are auto-generated via
17
+ // color-mix(). To add a new theme, define a $palette map and call:
18
+ // [data-theme="my-theme"] { @include define-theme($my-palette); }
19
+ // =============================================================================
20
+
21
+ @mixin define-theme($p) {
22
+ // Backgrounds
23
+ --bg-base: #{map.get($p, 'bg-base')};
24
+ --bg-surface: #{map.get($p, 'bg-surface')};
25
+ --bg-elevated: #{map.get($p, 'bg-elevated')};
26
+ --bg-overlay: #{map.get($p, 'bg-overlay')};
27
+ --bg-input: #{map.get($p, 'bg-input')};
28
+ --bg-inset: #{map.get($p, 'bg-inset')};
29
+
30
+ // Glass effects
31
+ --glass-blur: #{map.get($p, 'glass-blur') or 0px};
32
+ --glass-blur-card: #{map.get($p, 'glass-blur-card') or 0px};
33
+ --glass-blur-inset: #{map.get($p, 'glass-blur-inset') or 0px};
34
+ --glass-border: #{map.get($p, 'glass-border')};
35
+ --glass-border-hover: #{map.get($p, 'glass-border-hover')};
36
+ --glass-highlight: #{map.get($p, 'glass-highlight') or transparent};
37
+ --glass-highlight-strong: #{map.get($p, 'glass-highlight-strong') or transparent};
38
+ --glass-inner-glow: #{map.get($p, 'glass-inner-glow') or 0};
39
+
40
+ // Text
41
+ --text-primary: #{map.get($p, 'text-primary')};
42
+ --text-secondary: #{map.get($p, 'text-secondary')};
43
+ --text-tertiary: #{map.get($p, 'text-tertiary')};
44
+ --text-disabled: #{map.get($p, 'text-disabled')};
45
+
46
+ // Accent base colors
47
+ $green: map.get($p, 'green');
48
+ $red: map.get($p, 'red');
49
+ $yellow: map.get($p, 'yellow');
50
+ $blue: map.get($p, 'blue');
51
+ $purple: map.get($p, 'purple');
52
+ $cyan: map.get($p, 'cyan');
53
+
54
+ --accent-green: #{$green};
55
+ --accent-green-dim: color-mix(in srgb, #{$green} 15%, transparent);
56
+ --accent-green-subtle: color-mix(in srgb, #{$green} 8%, transparent);
57
+ --accent-green-focus: color-mix(in srgb, #{$green} 12%, transparent);
58
+ --accent-green-selection: color-mix(in srgb, #{$green} 25%, transparent);
59
+ --accent-red: #{$red};
60
+ --accent-red-dim: color-mix(in srgb, #{$red} 15%, transparent);
61
+ --accent-yellow: #{$yellow};
62
+ --accent-yellow-dim: color-mix(in srgb, #{$yellow} 15%, transparent);
63
+ --accent-blue: #{$blue};
64
+ --accent-blue-dim: color-mix(in srgb, #{$blue} 15%, transparent);
65
+ --accent-purple: #{$purple};
66
+ --accent-purple-dim: color-mix(in srgb, #{$purple} 15%, transparent);
67
+ --accent-cyan: #{$cyan};
68
+ --accent-cyan-dim: color-mix(in srgb, #{$cyan} 15%, transparent);
69
+
70
+ // Accent foreground variants (defaults to base if not provided)
71
+ --accent-red-fg: #{map.get($p, 'red-fg') or $red};
72
+ --accent-yellow-fg: #{map.get($p, 'yellow-fg') or $yellow};
73
+ --accent-blue-fg: #{map.get($p, 'blue-fg') or $blue};
74
+ --accent-green-fg: #{map.get($p, 'green-fg') or $green};
75
+ --accent-purple-fg: #{map.get($p, 'purple-fg') or $purple};
76
+ --accent-cyan-fg: #{map.get($p, 'cyan-fg') or $cyan};
77
+
78
+ // Accent border variants (30% opacity for callout/badge borders)
79
+ --accent-green-border: color-mix(in srgb, #{$green} 30%, transparent);
80
+ --accent-red-border: color-mix(in srgb, #{$red} 30%, transparent);
81
+ --accent-yellow-border: color-mix(in srgb, #{$yellow} 30%, transparent);
82
+ --accent-blue-border: color-mix(in srgb, #{$blue} 30%, transparent);
83
+
84
+ // Borders
85
+ --border-primary: color-mix(in srgb, #{$green} 18%, transparent);
86
+ --border-subtle: #{map.get($p, 'border-subtle')};
87
+ --border-input: #{map.get($p, 'border-input')};
88
+
89
+ // Ring (focus outline)
90
+ --ring: #{$green};
91
+ --ring-alpha: color-mix(in srgb, #{$green} 24%, transparent);
92
+
93
+ // Card highlight
94
+ --highlight-top: #{map.get($p, 'highlight-top') or none};
95
+
96
+ // Border radii (optional overrides — falls through to :root if omitted)
97
+ @if map.has-key($p, 'radius-sm') {
98
+ --radius-sm: #{map.get($p, 'radius-sm')};
99
+ }
100
+ @if map.has-key($p, 'radius-md') {
101
+ --radius-md: #{map.get($p, 'radius-md')};
102
+ }
103
+ @if map.has-key($p, 'radius-lg') {
104
+ --radius-lg: #{map.get($p, 'radius-lg')};
105
+ }
106
+ @if map.has-key($p, 'radius-xl') {
107
+ --radius-xl: #{map.get($p, 'radius-xl')};
108
+ }
109
+
110
+ // Shadows
111
+ --shadow-xs: #{map.get($p, 'shadow-xs')};
112
+ --shadow-sm: #{map.get($p, 'shadow-sm')};
113
+ --shadow-md: #{map.get($p, 'shadow-md')};
114
+ --shadow-lg: #{map.get($p, 'shadow-lg')};
115
+ --shadow-glow-green: #{map.get($p, 'shadow-glow-green') or none};
116
+ --shadow-glow-red: #{map.get($p, 'shadow-glow-red') or none};
117
+
118
+ // Font
119
+ --font-ui: #{map.get($p, 'font-ui')};
120
+
121
+ // Noise texture overlay opacity
122
+ --noise-opacity: #{map.get($p, 'noise-opacity') or 0};
123
+
124
+ // Syntax highlighting
125
+ --code-comment: #{map.get($p, 'code-comment')};
126
+ --code-keyword: #{map.get($p, 'code-keyword')};
127
+ --code-function: #{map.get($p, 'code-function')};
128
+ --code-string: #{map.get($p, 'code-string')};
129
+ --code-number: #{map.get($p, 'code-number')};
130
+ --code-class: #{map.get($p, 'code-class')};
131
+ --code-tag: #{map.get($p, 'code-tag')};
132
+ --code-deleted: #{map.get($p, 'code-deleted')};
133
+ --code-inserted: #{map.get($p, 'code-inserted')};
134
+ --code-punctuation: #{map.get($p, 'code-punctuation')};
135
+ }
136
+
137
+ // =============================================================================
138
+ // Glassmorphism Theme (Default) — :root
139
+ // =============================================================================
140
+
141
+ :root {
142
+ // ---------------------------------------------------------------------------
143
+ // Backgrounds — Glassmorphism (semi-transparent for backdrop-filter)
144
+ // ---------------------------------------------------------------------------
145
+ --bg-base: #0a0c14;
146
+ --bg-surface: rgba(16, 20, 34, 0.82);
147
+ --bg-elevated: rgba(24, 30, 52, 0.72);
148
+ --bg-overlay: rgba(15, 52, 96, 0.35);
149
+ --bg-input: rgba(20, 26, 46, 0.85);
150
+ --bg-inset: rgba(10, 14, 28, 0.55);
151
+
152
+ // ---------------------------------------------------------------------------
153
+ // Glass effects (active in default theme, zeroed in light/dark)
154
+ // ---------------------------------------------------------------------------
155
+ --glass-blur: 16px;
156
+ --glass-blur-card: 8px;
157
+ --glass-blur-inset: 4px;
158
+ --glass-border: rgba(255, 255, 255, 0.10);
159
+ --glass-border-hover: rgba(255, 255, 255, 0.16);
160
+ --glass-highlight: rgba(255, 255, 255, 0.03);
161
+ --glass-highlight-strong: rgba(255, 255, 255, 0.06);
162
+ --glass-inner-glow: 1;
163
+
164
+ // ---------------------------------------------------------------------------
165
+ // Text
166
+ // ---------------------------------------------------------------------------
167
+ --text-primary: #e2e8f0;
168
+ --text-secondary: #94a3b8;
169
+ --text-tertiary: #6b7a8d;
170
+ --text-disabled: #475569;
171
+
172
+ // ---------------------------------------------------------------------------
173
+ // Accent Colors
174
+ // ---------------------------------------------------------------------------
175
+ --accent-green: #4ecca3;
176
+ --accent-green-dim: rgba(78, 204, 163, 0.18);
177
+ --accent-green-subtle: rgba(78, 204, 163, 0.08);
178
+ --accent-green-focus: rgba(78, 204, 163, 0.1);
179
+ --accent-green-selection: rgba(78, 204, 163, 0.25);
180
+
181
+ --accent-red: #e94560;
182
+ --accent-red-dim: rgba(233, 69, 96, 0.18);
183
+
184
+ --accent-yellow: #f0c040;
185
+ --accent-yellow-dim: rgba(240, 192, 64, 0.18);
186
+
187
+ --accent-blue: #70a1ff;
188
+ --accent-blue-dim: rgba(112, 161, 255, 0.18);
189
+
190
+ --accent-purple: #a855f7;
191
+ --accent-purple-dim: rgba(168, 85, 247, 0.18);
192
+
193
+ --accent-cyan: #22d3ee;
194
+ --accent-cyan-dim: rgba(34, 211, 238, 0.18);
195
+
196
+ // Semantic foreground variants
197
+ --accent-red-fg: #e94560;
198
+ --accent-yellow-fg: #f0c040;
199
+ --accent-blue-fg: #70a1ff;
200
+ --accent-green-fg: #4ecca3;
201
+ --accent-purple-fg: #a855f7;
202
+ --accent-cyan-fg: #22d3ee;
203
+
204
+ // Accent border variants (30% for callout/badge borders)
205
+ --accent-green-border: rgba(78, 204, 163, 0.30);
206
+ --accent-red-border: rgba(233, 69, 96, 0.30);
207
+ --accent-yellow-border: rgba(240, 192, 64, 0.30);
208
+ --accent-blue-border: rgba(112, 161, 255, 0.30);
209
+
210
+ // ---------------------------------------------------------------------------
211
+ // Borders
212
+ // ---------------------------------------------------------------------------
213
+ --border-primary: rgba(78, 204, 163, 0.18);
214
+ --border-subtle: rgba(255, 255, 255, 0.10);
215
+ --border-input: rgba(255, 255, 255, 0.14);
216
+
217
+ // ---------------------------------------------------------------------------
218
+ // Ring (focus outline)
219
+ // ---------------------------------------------------------------------------
220
+ --ring: #4ecca3;
221
+ --ring-alpha: rgba(78, 204, 163, 0.24);
222
+
223
+ // ---------------------------------------------------------------------------
224
+ // Card highlight
225
+ // ---------------------------------------------------------------------------
226
+ --highlight-top: inset 0 1px 0 0 rgba(255, 255, 255, 0.03);
227
+
228
+ // ---------------------------------------------------------------------------
229
+ // Spacing
230
+ // ---------------------------------------------------------------------------
231
+ --space-xs: 4px;
232
+ --space-sm: 8px;
233
+ --space-md: 12px;
234
+ --space-lg: 16px;
235
+ --space-xl: 24px;
236
+
237
+ // ---------------------------------------------------------------------------
238
+ // Border Radii
239
+ // ---------------------------------------------------------------------------
240
+ --radius-sm: 6px;
241
+ --radius-md: 10px;
242
+ --radius-lg: 14px;
243
+ --radius-xl: 20px;
244
+ --radius-full: 9999px;
245
+
246
+ // ---------------------------------------------------------------------------
247
+ // Shadows
248
+ // ---------------------------------------------------------------------------
249
+ --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.3);
250
+ --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.4);
251
+ --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.3);
252
+ --shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.4);
253
+ --shadow-glow-green: 0 0 16px rgba(78, 204, 163, 0.15);
254
+ --shadow-glow-red: 0 0 16px rgba(233, 69, 96, 0.15);
255
+
256
+ // ---------------------------------------------------------------------------
257
+ // Typography
258
+ // ---------------------------------------------------------------------------
259
+ --font-sans: 'DM Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
260
+ --font-mono: 'Fira Code', 'JetBrains Mono', 'Cascadia Code', monospace;
261
+ --font-ui: var(--font-mono);
262
+ --font-size-xs: 11px;
263
+ --font-size-sm: 12px;
264
+ --font-size-md: 13px;
265
+ --font-size-lg: 15px;
266
+ --font-size-xl: 18px;
267
+ --font-weight-light: 300;
268
+ --font-weight-regular: 400;
269
+ --font-weight-medium: 500;
270
+ --font-weight-bold: 700;
271
+ --font-weight-heavy: 800;
272
+ --line-height: 1.5;
273
+
274
+ // ---------------------------------------------------------------------------
275
+ // Transitions
276
+ // ---------------------------------------------------------------------------
277
+ --transition-fast: 150ms ease;
278
+ --transition-base: 250ms ease;
279
+ --transition-slow: 400ms cubic-bezier(0.16, 1, 0.3, 1);
280
+
281
+ // ---------------------------------------------------------------------------
282
+ // Border width (1px default, 2px in brutalist themes)
283
+ // ---------------------------------------------------------------------------
284
+ --border-width: 1px;
285
+
286
+ // ---------------------------------------------------------------------------
287
+ // Noise texture overlay opacity (0 in glass, subtle in T3 themes)
288
+ // ---------------------------------------------------------------------------
289
+ --noise-opacity: 0;
290
+
291
+ // ---------------------------------------------------------------------------
292
+ // Syntax highlighting — Glass / Dark
293
+ // ---------------------------------------------------------------------------
294
+ --code-comment: #6b7a8d;
295
+ --code-keyword: #4ecca3;
296
+ --code-function: #70a1ff;
297
+ --code-string: #22d3ee;
298
+ --code-number: #a855f7;
299
+ --code-class: #f0c040;
300
+ --code-tag: #4ecca3;
301
+ --code-deleted: #e94560;
302
+ --code-inserted: #4ecca3;
303
+ --code-punctuation: #94a3b8;
304
+ }
305
+
306
+ // =============================================================================
307
+ // Grackle Light — Brand theme (light variant) — purple accent
308
+ // =============================================================================
309
+
310
+ [data-theme="grackle-light"] {
311
+ color-scheme: light;
312
+
313
+ // Disable glass effects
314
+ --glass-blur: 0px;
315
+ --glass-blur-card: 0px;
316
+ --glass-blur-inset: 0px;
317
+ --glass-border: rgba(90, 60, 150, 0.10);
318
+ --glass-border-hover: rgba(90, 60, 150, 0.16);
319
+ --glass-highlight: transparent;
320
+ --glass-highlight-strong: transparent;
321
+ --glass-inner-glow: 0;
322
+
323
+ // Backgrounds — white base, cards are tinted grey panels
324
+ --bg-base: #faf9fc;
325
+ --bg-surface: #f0edf5;
326
+ --bg-elevated: #f4f2f7;
327
+ --bg-overlay: rgba(124, 58, 237, 0.04);
328
+ --bg-input: #ffffff;
329
+ --bg-inset: #e8e5ef;
330
+
331
+ // Text — slightly deeper for contrast against off-white
332
+ --text-primary: #1a1528;
333
+ --text-secondary: #5e5775;
334
+ --text-tertiary: #908aa0;
335
+ --text-disabled: #c5c1cf;
336
+
337
+ // Accents — purple brand accent
338
+ --accent-green: #7c3aed;
339
+ --accent-green-dim: rgba(124, 58, 237, 0.10);
340
+ --accent-green-subtle: rgba(124, 58, 237, 0.06);
341
+ --accent-green-focus: rgba(124, 58, 237, 0.12);
342
+ --accent-green-selection: rgba(124, 58, 237, 0.20);
343
+ --accent-red: #ef4444;
344
+ --accent-red-dim: rgba(239, 68, 68, 0.10);
345
+ --accent-yellow: #f59e0b;
346
+ --accent-yellow-dim: rgba(245, 158, 11, 0.10);
347
+ --accent-blue: #3b82f6;
348
+ --accent-blue-dim: rgba(59, 130, 246, 0.10);
349
+ --accent-purple: #8b5cf6;
350
+ --accent-purple-dim: rgba(139, 92, 246, 0.10);
351
+ --accent-cyan: #06b6d4;
352
+ --accent-cyan-dim: rgba(6, 182, 212, 0.10);
353
+
354
+ --accent-red-fg: #b91c1c;
355
+ --accent-yellow-fg: #b45309;
356
+ --accent-blue-fg: #1d4ed8;
357
+ --accent-green-fg: #6d28d9;
358
+ --accent-purple-fg: #6d28d9;
359
+ --accent-cyan-fg: #0e7490;
360
+
361
+ // Accent border variants
362
+ --accent-green-border: rgba(124, 58, 237, 0.30);
363
+ --accent-red-border: rgba(239, 68, 68, 0.30);
364
+ --accent-yellow-border: rgba(245, 158, 11, 0.30);
365
+ --accent-blue-border: rgba(59, 130, 246, 0.30);
366
+
367
+ // Borders — purple-tinted
368
+ --border-primary: rgba(124, 58, 237, 0.18);
369
+ --border-subtle: rgba(90, 60, 150, 0.10);
370
+ --border-input: rgba(90, 60, 150, 0.16);
371
+
372
+ // Ring
373
+ --ring: #7c3aed;
374
+ --ring-alpha: rgba(124, 58, 237, 0.24);
375
+
376
+ // Highlight
377
+ --highlight-top: inset 0 1px 0 rgba(255, 255, 255, 0.6);
378
+
379
+ // Radii (slightly smaller for T3)
380
+ --radius-md: 8px;
381
+ --radius-lg: 10px;
382
+ --radius-xl: 14px;
383
+
384
+ // Shadows — purple-tinted for cohesion
385
+ --shadow-xs: 0 1px 2px rgba(90, 60, 150, 0.06);
386
+ --shadow-sm: 0 1px 3px rgba(90, 60, 150, 0.10), 0 1px 2px rgba(90, 60, 150, 0.06);
387
+ --shadow-md: 0 4px 6px rgba(90, 60, 150, 0.08), 0 2px 4px rgba(90, 60, 150, 0.06);
388
+ --shadow-lg: 0 10px 15px rgba(90, 60, 150, 0.10), 0 4px 6px rgba(90, 60, 150, 0.05);
389
+ --shadow-glow-green: none;
390
+ --shadow-glow-red: none;
391
+
392
+ // Font — sans-serif for T3 themes
393
+ --font-ui: var(--font-sans);
394
+
395
+ // Noise texture
396
+ --noise-opacity: 0.02;
397
+
398
+ // Syntax highlighting
399
+ --code-comment: #6b7280;
400
+ --code-keyword: #7c3aed;
401
+ --code-function: #2563eb;
402
+ --code-string: #0891b2;
403
+ --code-number: #7c3aed;
404
+ --code-class: #d97706;
405
+ --code-tag: #7c3aed;
406
+ --code-deleted: #ef4444;
407
+ --code-inserted: #10b981;
408
+ --code-punctuation: #6b7280;
409
+ }
410
+
411
+ // =============================================================================
412
+ // Grackle Dark — Brand theme (dark variant) — purple accent
413
+ // =============================================================================
414
+
415
+ [data-theme="grackle-dark"] {
416
+ color-scheme: dark;
417
+
418
+ // Disable glass effects
419
+ --glass-blur: 0px;
420
+ --glass-blur-card: 0px;
421
+ --glass-blur-inset: 0px;
422
+ --glass-border: rgba(255, 255, 255, 0.06);
423
+ --glass-border-hover: rgba(255, 255, 255, 0.10);
424
+ --glass-highlight: transparent;
425
+ --glass-highlight-strong: transparent;
426
+ --glass-inner-glow: 0;
427
+
428
+ // Backgrounds
429
+ --bg-base: #0e1218;
430
+ --bg-surface: #161b22;
431
+ --bg-elevated: #1c2129;
432
+ --bg-overlay: rgba(255, 255, 255, 0.04);
433
+ --bg-input: #161b22;
434
+ --bg-inset: #0e1218;
435
+
436
+ // Text
437
+ --text-primary: #e5e7eb;
438
+ --text-secondary: #9ca3af;
439
+ --text-tertiary: #6b7280;
440
+ --text-disabled: #4b5563;
441
+
442
+ // Accents — purple brand accent
443
+ --accent-green: #8b5cf6;
444
+ --accent-green-dim: rgba(139, 92, 246, 0.15);
445
+ --accent-green-subtle: rgba(139, 92, 246, 0.08);
446
+ --accent-green-focus: rgba(139, 92, 246, 0.15);
447
+ --accent-green-selection: rgba(139, 92, 246, 0.25);
448
+ --accent-red: #f87171;
449
+ --accent-red-dim: rgba(248, 113, 113, 0.15);
450
+ --accent-yellow: #fbbf24;
451
+ --accent-yellow-dim: rgba(251, 191, 36, 0.15);
452
+ --accent-blue: #60a5fa;
453
+ --accent-blue-dim: rgba(96, 165, 250, 0.15);
454
+ --accent-purple: #a78bfa;
455
+ --accent-purple-dim: rgba(167, 139, 250, 0.15);
456
+ --accent-cyan: #22d3ee;
457
+ --accent-cyan-dim: rgba(34, 211, 238, 0.15);
458
+
459
+ --accent-red-fg: #fca5a5;
460
+ --accent-yellow-fg: #fcd34d;
461
+ --accent-blue-fg: #93c5fd;
462
+ --accent-green-fg: #c4b5fd;
463
+ --accent-purple-fg: #c4b5fd;
464
+ --accent-cyan-fg: #67e8f9;
465
+
466
+ // Accent border variants
467
+ --accent-green-border: rgba(139, 92, 246, 0.30);
468
+ --accent-red-border: rgba(248, 113, 113, 0.30);
469
+ --accent-yellow-border: rgba(251, 191, 36, 0.30);
470
+ --accent-blue-border: rgba(96, 165, 250, 0.30);
471
+
472
+ // Borders — purple-tinted
473
+ --border-primary: rgba(139, 92, 246, 0.18);
474
+ --border-subtle: rgba(255, 255, 255, 0.06);
475
+ --border-input: rgba(255, 255, 255, 0.10);
476
+
477
+ // Ring
478
+ --ring: #8b5cf6;
479
+ --ring-alpha: rgba(139, 92, 246, 0.24);
480
+
481
+ // Highlight
482
+ --highlight-top: inset 0 -1px 0 rgba(255, 255, 255, 0.06);
483
+
484
+ // Radii
485
+ --radius-md: 8px;
486
+ --radius-lg: 10px;
487
+ --radius-xl: 14px;
488
+
489
+ // Shadows
490
+ --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.3);
491
+ --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.4), 0 1px 2px rgba(0, 0, 0, 0.3);
492
+ --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.4), 0 2px 4px rgba(0, 0, 0, 0.3);
493
+ --shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.5), 0 4px 6px rgba(0, 0, 0, 0.3);
494
+ --shadow-glow-green: none;
495
+ --shadow-glow-red: none;
496
+
497
+ // Font
498
+ --font-ui: var(--font-sans);
499
+
500
+ // Noise texture
501
+ --noise-opacity: 0.03;
502
+
503
+ // Syntax highlighting
504
+ --code-comment: #9ca3af;
505
+ --code-keyword: #8b5cf6;
506
+ --code-function: #60a5fa;
507
+ --code-string: #22d3ee;
508
+ --code-number: #a78bfa;
509
+ --code-class: #fbbf24;
510
+ --code-tag: #8b5cf6;
511
+ --code-deleted: #f87171;
512
+ --code-inserted: #34d399;
513
+ --code-punctuation: #9ca3af;
514
+ }
515
+
516
+ // =============================================================================
517
+ // Matrix — CRT / Retro Terminal
518
+ // =============================================================================
519
+
520
+ $matrix-palette: (
521
+ 'bg-base': #050505,
522
+ 'bg-surface': #0a0f0a,
523
+ 'bg-elevated': #0f160f,
524
+ 'bg-overlay': rgba(0, 255, 65, 0.06),
525
+ 'bg-input': #0a0f0a,
526
+ 'bg-inset': #030303,
527
+
528
+ 'glass-border': rgba(0, 255, 65, 0.12),
529
+ 'glass-border-hover': rgba(0, 255, 65, 0.20),
530
+
531
+ 'text-primary': #33ff77,
532
+ 'text-secondary': #22bb55,
533
+ 'text-tertiary': #1a7a33,
534
+ 'text-disabled': #0d4d1a,
535
+
536
+ 'green': #00ff41,
537
+ 'red': #ff3333,
538
+ 'yellow': #ffb000,
539
+ 'blue': #00bfff,
540
+ 'purple': #b967ff,
541
+ 'cyan': #00ffcc,
542
+
543
+ 'border-subtle': rgba(0, 255, 65, 0.10),
544
+ 'border-input': rgba(0, 255, 65, 0.16),
545
+
546
+ 'highlight-top': inset 0 1px 0 0 rgba(0, 255, 65, 0.04),
547
+
548
+ 'radius-sm': 0px,
549
+ 'radius-md': 0px,
550
+ 'radius-lg': 0px,
551
+ 'radius-xl': 0px,
552
+
553
+ 'shadow-xs': 0 0 2px rgba(0, 255, 65, 0.15),
554
+ 'shadow-sm': 0 0 4px rgba(0, 255, 65, 0.15),
555
+ 'shadow-md': 0 0 8px rgba(0, 255, 65, 0.12),
556
+ 'shadow-lg': 0 0 16px rgba(0, 255, 65, 0.20),
557
+ 'shadow-glow-green': 0 0 20px rgba(0, 255, 65, 0.25),
558
+ 'shadow-glow-red': 0 0 20px rgba(255, 51, 51, 0.25),
559
+
560
+ 'font-ui': var(--font-mono),
561
+
562
+ 'code-comment': #008f11,
563
+ 'code-keyword': #00ff41,
564
+ 'code-function': #00bfff,
565
+ 'code-string': #ffb000,
566
+ 'code-number': #b967ff,
567
+ 'code-class': #ffb000,
568
+ 'code-tag': #00ff41,
569
+ 'code-deleted': #ff3333,
570
+ 'code-inserted': #00ff41,
571
+ 'code-punctuation': #00cc33,
572
+ );
573
+
574
+ [data-theme="matrix"] {
575
+ color-scheme: dark;
576
+ @include define-theme($matrix-palette);
577
+ }
578
+
579
+ // =============================================================================
580
+ // Neubrutalism — thick borders, raw colors, bold type
581
+ // =============================================================================
582
+
583
+ $brutalist-palette: (
584
+ 'bg-base': #f5f0e8,
585
+ 'bg-surface': #ffffff,
586
+ 'bg-elevated': #ffffff,
587
+ 'bg-overlay': rgba(0, 0, 0, 0.06),
588
+ 'bg-input': #ffffff,
589
+ 'bg-inset': #ede8df,
590
+
591
+ 'glass-border': #1a1a1a,
592
+ 'glass-border-hover': #000000,
593
+
594
+ 'text-primary': #1a1a1a,
595
+ 'text-secondary': #4a4a4a,
596
+ 'text-tertiary': #7a7a7a,
597
+ 'text-disabled': #b0b0b0,
598
+
599
+ 'green': #7ed957,
600
+ 'red': #ff5757,
601
+ 'yellow': #ffde59,
602
+ 'blue': #5ce1e6,
603
+ 'purple': #cb6ce6,
604
+ 'cyan': #38b6ff,
605
+
606
+ 'border-subtle': #1a1a1a,
607
+ 'border-input': #1a1a1a,
608
+
609
+ 'highlight-top': none,
610
+
611
+ 'radius-sm': 4px,
612
+ 'radius-md': 4px,
613
+ 'radius-lg': 6px,
614
+ 'radius-xl': 8px,
615
+
616
+ 'shadow-xs': 2px 2px 0px #1a1a1a,
617
+ 'shadow-sm': 3px 3px 0px #1a1a1a,
618
+ 'shadow-md': 4px 4px 0px #1a1a1a,
619
+ 'shadow-lg': 6px 6px 0px #1a1a1a,
620
+
621
+ 'font-ui': var(--font-sans),
622
+ 'noise-opacity': 0,
623
+
624
+ 'code-comment': #7a7a7a,
625
+ 'code-keyword': #ff5757,
626
+ 'code-function': #5ce1e6,
627
+ 'code-string': #7ed957,
628
+ 'code-number': #cb6ce6,
629
+ 'code-class': #ffde59,
630
+ 'code-tag': #ff5757,
631
+ 'code-deleted': #ff5757,
632
+ 'code-inserted': #7ed957,
633
+ 'code-punctuation': #4a4a4a,
634
+ );
635
+
636
+ [data-theme="brutalist-light"] {
637
+ color-scheme: light;
638
+ @include define-theme($brutalist-palette);
639
+ --border-width: 2px;
640
+
641
+ // Press-down effect on interactive elements
642
+ button:active,
643
+ [role="button"]:active {
644
+ --shadow-xs: 1px 1px 0px #1a1a1a;
645
+ --shadow-sm: 1px 1px 0px #1a1a1a;
646
+ transform: translate(1px, 1px);
647
+ }
648
+ }
649
+
650
+ // =============================================================================
651
+ // Neubrutalism Dark — same raw energy, inverted
652
+ // =============================================================================
653
+
654
+ $brutalist-dark-palette: (
655
+ 'bg-base': #1a1a1a,
656
+ 'bg-surface': #252525,
657
+ 'bg-elevated': #2f2f2f,
658
+ 'bg-overlay': rgba(255, 255, 255, 0.06),
659
+ 'bg-input': #252525,
660
+ 'bg-inset': #111111,
661
+
662
+ 'glass-border': #e0e0e0,
663
+ 'glass-border-hover': #ffffff,
664
+
665
+ 'text-primary': #f0f0f0,
666
+ 'text-secondary': #b0b0b0,
667
+ 'text-tertiary': #808080,
668
+ 'text-disabled': #505050,
669
+
670
+ 'green': #7ed957,
671
+ 'red': #ff5757,
672
+ 'yellow': #ffde59,
673
+ 'blue': #5ce1e6,
674
+ 'purple': #cb6ce6,
675
+ 'cyan': #38b6ff,
676
+
677
+ 'border-subtle': #e0e0e0,
678
+ 'border-input': #e0e0e0,
679
+
680
+ 'highlight-top': none,
681
+
682
+ 'radius-sm': 4px,
683
+ 'radius-md': 4px,
684
+ 'radius-lg': 6px,
685
+ 'radius-xl': 8px,
686
+
687
+ 'shadow-xs': 2px 2px 0px #e0e0e0,
688
+ 'shadow-sm': 3px 3px 0px #e0e0e0,
689
+ 'shadow-md': 4px 4px 0px #e0e0e0,
690
+ 'shadow-lg': 6px 6px 0px #e0e0e0,
691
+
692
+ 'font-ui': var(--font-sans),
693
+ 'noise-opacity': 0,
694
+
695
+ 'code-comment': #808080,
696
+ 'code-keyword': #ff5757,
697
+ 'code-function': #5ce1e6,
698
+ 'code-string': #7ed957,
699
+ 'code-number': #cb6ce6,
700
+ 'code-class': #ffde59,
701
+ 'code-tag': #ff5757,
702
+ 'code-deleted': #ff5757,
703
+ 'code-inserted': #7ed957,
704
+ 'code-punctuation': #b0b0b0,
705
+ );
706
+
707
+ [data-theme="brutalist-dark"] {
708
+ color-scheme: dark;
709
+ @include define-theme($brutalist-dark-palette);
710
+ --border-width: 2px;
711
+
712
+ // Press-down effect on interactive elements
713
+ button:active,
714
+ [role="button"]:active {
715
+ --shadow-xs: 1px 1px 0px #e0e0e0;
716
+ --shadow-sm: 1px 1px 0px #e0e0e0;
717
+ transform: translate(1px, 1px);
718
+ }
719
+ }
720
+
721
+ // =============================================================================
722
+ // Monokai — Classic warm editor palette
723
+ // =============================================================================
724
+
725
+ $monokai-palette: (
726
+ 'bg-base': #272822,
727
+ 'bg-surface': #2d2e27,
728
+ 'bg-elevated': #3e3d32,
729
+ 'bg-overlay': rgba(255, 255, 255, 0.05),
730
+ 'bg-input': #2d2e27,
731
+ 'bg-inset': #1e1f1a,
732
+
733
+ 'glass-border': rgba(255, 255, 255, 0.08),
734
+ 'glass-border-hover': rgba(255, 255, 255, 0.14),
735
+
736
+ 'text-primary': #f8f8f2,
737
+ 'text-secondary': #a6a28c,
738
+ 'text-tertiary': #75715e,
739
+ 'text-disabled': #4b4a3e,
740
+
741
+ 'green': #a6e22e,
742
+ 'red': #f92672,
743
+ 'yellow': #e6db74,
744
+ 'blue': #66d9ef,
745
+ 'purple': #ae81ff,
746
+ 'cyan': #66d9ef,
747
+
748
+ 'border-subtle': rgba(255, 255, 255, 0.06),
749
+ 'border-input': rgba(255, 255, 255, 0.10),
750
+
751
+ 'highlight-top': inset 0 1px 0 rgba(255, 255, 255, 0.04),
752
+
753
+ 'radius-md': 8px,
754
+ 'radius-lg': 10px,
755
+ 'radius-xl': 14px,
756
+
757
+ 'shadow-xs': 0 1px 2px rgba(0, 0, 0, 0.3),
758
+ 'shadow-sm': 0 1px 3px rgba(0, 0, 0, 0.4), // single shadow for SCSS map
759
+ 'shadow-md': 0 4px 6px rgba(0, 0, 0, 0.4),
760
+ 'shadow-lg': 0 10px 15px rgba(0, 0, 0, 0.5),
761
+
762
+ 'font-ui': var(--font-mono),
763
+
764
+ 'code-comment': #75715e,
765
+ 'code-keyword': #f92672,
766
+ 'code-function': #a6e22e,
767
+ 'code-string': #e6db74,
768
+ 'code-number': #ae81ff,
769
+ 'code-class': #66d9ef,
770
+ 'code-tag': #f92672,
771
+ 'code-deleted': #f92672,
772
+ 'code-inserted': #a6e22e,
773
+ 'code-punctuation': #f8f8f2,
774
+ );
775
+
776
+ [data-theme="monokai-dark"] {
777
+ color-scheme: dark;
778
+ @include define-theme($monokai-palette);
779
+ }
780
+
781
+ // =============================================================================
782
+ // Monokai Light — warm editor palette on a light background
783
+ // =============================================================================
784
+
785
+ $monokai-light-palette: (
786
+ 'bg-base': #fcfcfa,
787
+ 'bg-surface': #ffffff,
788
+ 'bg-elevated': #ffffff,
789
+ 'bg-overlay': rgba(0, 0, 0, 0.04),
790
+ 'bg-input': #ffffff,
791
+ 'bg-inset': #f0f0ea,
792
+
793
+ 'glass-border': rgba(0, 0, 0, 0.10),
794
+ 'glass-border-hover': rgba(0, 0, 0, 0.16),
795
+
796
+ 'text-primary': #2c292d,
797
+ 'text-secondary': #727072,
798
+ 'text-tertiary': #9e9b9e,
799
+ 'text-disabled': #c8c6c8,
800
+
801
+ 'green': #7a9e1e,
802
+ 'red': #d4185e,
803
+ 'yellow': #b8a510,
804
+ 'blue': #2ba4bf,
805
+ 'purple': #8b5fcf,
806
+ 'cyan': #2ba4bf,
807
+
808
+ 'border-subtle': rgba(0, 0, 0, 0.08),
809
+ 'border-input': rgba(0, 0, 0, 0.14),
810
+
811
+ 'highlight-top': inset 0 1px 0 rgba(255, 255, 255, 0.8),
812
+
813
+ 'radius-md': 8px,
814
+ 'radius-lg': 10px,
815
+ 'radius-xl': 14px,
816
+
817
+ 'shadow-xs': 0 1px 2px rgba(0, 0, 0, 0.06),
818
+ 'shadow-sm': 0 1px 3px rgba(0, 0, 0, 0.10),
819
+ 'shadow-md': 0 4px 6px rgba(0, 0, 0, 0.08),
820
+ 'shadow-lg': 0 10px 15px rgba(0, 0, 0, 0.10),
821
+
822
+ 'font-ui': var(--font-mono),
823
+
824
+ 'code-comment': #9e9b9e,
825
+ 'code-keyword': #d4185e,
826
+ 'code-function': #7a9e1e,
827
+ 'code-string': #b8a510,
828
+ 'code-number': #8b5fcf,
829
+ 'code-class': #2ba4bf,
830
+ 'code-tag': #d4185e,
831
+ 'code-deleted': #d4185e,
832
+ 'code-inserted': #7a9e1e,
833
+ 'code-punctuation': #2c292d,
834
+ );
835
+
836
+ [data-theme="monokai-light"] {
837
+ color-scheme: light;
838
+ @include define-theme($monokai-light-palette);
839
+ }
840
+
841
+ // =============================================================================
842
+ // Ubuntu — Aubergine terminal palette
843
+ // =============================================================================
844
+
845
+ $ubuntu-palette: (
846
+ 'bg-base': #300a24,
847
+ 'bg-surface': #3c1130,
848
+ 'bg-elevated': #4e1a3d,
849
+ 'bg-overlay': rgba(255, 255, 255, 0.05),
850
+ 'bg-input': #3c1130,
851
+ 'bg-inset': #240720,
852
+
853
+ 'glass-border': rgba(255, 255, 255, 0.08),
854
+ 'glass-border-hover': rgba(255, 255, 255, 0.14),
855
+
856
+ 'text-primary': #eeeeec,
857
+ 'text-secondary': #d3d7cf,
858
+ 'text-tertiary': #888a85,
859
+ 'text-disabled': #555753,
860
+
861
+ 'green': #8ae234,
862
+ 'red': #ef2929,
863
+ 'yellow': #fce94f,
864
+ 'blue': #729fcf,
865
+ 'purple': #ad7fa8,
866
+ 'cyan': #34e2e2,
867
+
868
+ 'red-fg': #ef2929,
869
+ 'yellow-fg': #fce94f,
870
+ 'blue-fg': #729fcf,
871
+ 'green-fg': #8ae234,
872
+ 'purple-fg': #ad7fa8,
873
+ 'cyan-fg': #34e2e2,
874
+
875
+ 'border-subtle': rgba(255, 255, 255, 0.08),
876
+ 'border-input': rgba(255, 255, 255, 0.12),
877
+
878
+ 'highlight-top': inset 0 1px 0 rgba(255, 255, 255, 0.04),
879
+
880
+ 'radius-md': 6px,
881
+ 'radius-lg': 8px,
882
+ 'radius-xl': 12px,
883
+
884
+ 'shadow-xs': 0 1px 2px rgba(0, 0, 0, 0.3),
885
+ 'shadow-sm': 0 1px 3px rgba(0, 0, 0, 0.4),
886
+ 'shadow-md': 0 4px 6px rgba(0, 0, 0, 0.4),
887
+ 'shadow-lg': 0 10px 15px rgba(0, 0, 0, 0.5),
888
+
889
+ 'font-ui': var(--font-mono),
890
+
891
+ 'code-comment': #888a85,
892
+ 'code-keyword': #8ae234,
893
+ 'code-function': #729fcf,
894
+ 'code-string': #fce94f,
895
+ 'code-number': #ad7fa8,
896
+ 'code-class': #34e2e2,
897
+ 'code-tag': #8ae234,
898
+ 'code-deleted': #ef2929,
899
+ 'code-inserted': #8ae234,
900
+ 'code-punctuation': #d3d7cf,
901
+ );
902
+
903
+ [data-theme="ubuntu"] {
904
+ color-scheme: dark;
905
+ @include define-theme($ubuntu-palette);
906
+ }
907
+
908
+ // =============================================================================
909
+ // Sandstone — Warm terracotta accent on dark brown
910
+ // =============================================================================
911
+
912
+ $sandstone-palette: (
913
+ 'bg-base': #1a1815,
914
+ 'bg-surface': #201d18,
915
+ 'bg-elevated': #2a2620,
916
+ 'bg-overlay': rgba(193, 95, 60, 0.06),
917
+ 'bg-input': #201d18,
918
+ 'bg-inset': #141210,
919
+
920
+ 'glass-border': rgba(193, 95, 60, 0.14),
921
+ 'glass-border-hover': rgba(193, 95, 60, 0.22),
922
+
923
+ 'text-primary': #e8e6e3,
924
+ 'text-secondary': #b1ada1,
925
+ 'text-tertiary': #7d796e,
926
+ 'text-disabled': #4a473f,
927
+
928
+ 'green': #C15F3C,
929
+ 'red': #e85d4a,
930
+ 'yellow': #d4a054,
931
+ 'blue': #6b8afd,
932
+ 'purple': #a78bfa,
933
+ 'cyan': #5fb8c2,
934
+
935
+ 'green-fg': #d4845f,
936
+ 'red-fg': #f08070,
937
+ 'yellow-fg': #e0b46a,
938
+ 'blue-fg': #8da4fd,
939
+ 'purple-fg': #c4b5fd,
940
+ 'cyan-fg': #7dccd4,
941
+
942
+ 'border-subtle': rgba(255, 255, 255, 0.06),
943
+ 'border-input': rgba(193, 95, 60, 0.18),
944
+
945
+ 'highlight-top': inset 0 1px 0 rgba(193, 95, 60, 0.04),
946
+
947
+ 'radius-md': 8px,
948
+ 'radius-lg': 10px,
949
+ 'radius-xl': 14px,
950
+
951
+ 'shadow-xs': 0 1px 2px rgba(0, 0, 0, 0.3),
952
+ 'shadow-sm': 0 1px 3px rgba(0, 0, 0, 0.4),
953
+ 'shadow-md': 0 4px 6px rgba(0, 0, 0, 0.4),
954
+ 'shadow-lg': 0 10px 15px rgba(0, 0, 0, 0.5),
955
+ 'shadow-glow-green': 0 0 16px rgba(193, 95, 60, 0.15),
956
+ 'shadow-glow-red': 0 0 16px rgba(232, 93, 74, 0.15),
957
+
958
+ 'font-ui': var(--font-mono),
959
+
960
+ 'code-comment': #7d796e,
961
+ 'code-keyword': #C15F3C,
962
+ 'code-function': #6b8afd,
963
+ 'code-string': #5fb8c2,
964
+ 'code-number': #a78bfa,
965
+ 'code-class': #d4a054,
966
+ 'code-tag': #C15F3C,
967
+ 'code-deleted': #e85d4a,
968
+ 'code-inserted': #C15F3C,
969
+ 'code-punctuation': #b1ada1,
970
+ );
971
+
972
+ [data-theme="sandstone"] {
973
+ color-scheme: dark;
974
+ @include define-theme($sandstone-palette);
975
+ }
976
+
977
+ // =============================================================================
978
+ // Verdigris — Teal accent on charcoal (ChatGPT-inspired)
979
+ // =============================================================================
980
+
981
+ $verdigris-palette: (
982
+ 'bg-base': #141414,
983
+ 'bg-surface': #1e1e1e,
984
+ 'bg-elevated': #2a2a2a,
985
+ 'bg-overlay': rgba(0, 166, 126, 0.06),
986
+ 'bg-input': #1e1e1e,
987
+ 'bg-inset': #0e0e0e,
988
+
989
+ 'glass-border': rgba(255, 255, 255, 0.08),
990
+ 'glass-border-hover': rgba(255, 255, 255, 0.14),
991
+
992
+ 'text-primary': #ececec,
993
+ 'text-secondary': #a1a1a6,
994
+ 'text-tertiary': #6e6e73,
995
+ 'text-disabled': #3e3e42,
996
+
997
+ 'green': #00a67e,
998
+ 'red': #ef4444,
999
+ 'yellow': #f59e0b,
1000
+ 'blue': #3b82f6,
1001
+ 'purple': #ab68ff,
1002
+ 'cyan': #06b6d4,
1003
+
1004
+ 'border-subtle': rgba(255, 255, 255, 0.06),
1005
+ 'border-input': rgba(255, 255, 255, 0.12),
1006
+
1007
+ 'highlight-top': inset 0 1px 0 rgba(255, 255, 255, 0.03),
1008
+
1009
+ 'radius-md': 8px,
1010
+ 'radius-lg': 12px,
1011
+ 'radius-xl': 16px,
1012
+
1013
+ 'shadow-xs': 0 1px 2px rgba(0, 0, 0, 0.3),
1014
+ 'shadow-sm': 0 1px 3px rgba(0, 0, 0, 0.4),
1015
+ 'shadow-md': 0 4px 6px rgba(0, 0, 0, 0.4),
1016
+ 'shadow-lg': 0 10px 15px rgba(0, 0, 0, 0.5),
1017
+
1018
+ 'font-ui': var(--font-sans),
1019
+
1020
+ 'code-comment': #6e6e73,
1021
+ 'code-keyword': #00a67e,
1022
+ 'code-function': #3b82f6,
1023
+ 'code-string': #f59e0b,
1024
+ 'code-number': #ab68ff,
1025
+ 'code-class': #06b6d4,
1026
+ 'code-tag': #00a67e,
1027
+ 'code-deleted': #ef4444,
1028
+ 'code-inserted': #00a67e,
1029
+ 'code-punctuation': #a1a1a6,
1030
+ );
1031
+
1032
+ [data-theme="verdigris"] {
1033
+ color-scheme: dark;
1034
+ @include define-theme($verdigris-palette);
1035
+ }
1036
+
1037
+ // =============================================================================
1038
+ // Primer — Blue accent on ink-dark grey (GitHub-inspired)
1039
+ // =============================================================================
1040
+
1041
+ $primer-palette: (
1042
+ 'bg-base': #0d1117,
1043
+ 'bg-surface': #161b22,
1044
+ 'bg-elevated': #1c2129,
1045
+ 'bg-overlay': rgba(255, 255, 255, 0.04),
1046
+ 'bg-input': #0d1117,
1047
+ 'bg-inset': #010409,
1048
+
1049
+ 'glass-border': rgba(255, 255, 255, 0.06),
1050
+ 'glass-border-hover': rgba(255, 255, 255, 0.12),
1051
+
1052
+ 'text-primary': #c9d1d9,
1053
+ 'text-secondary': #8b949e,
1054
+ 'text-tertiary': #6e7681,
1055
+ 'text-disabled': #484f58,
1056
+
1057
+ 'green': #3fb950,
1058
+ 'red': #f85149,
1059
+ 'yellow': #d29922,
1060
+ 'blue': #58a6ff,
1061
+ 'purple': #bc8cff,
1062
+ 'cyan': #39d353,
1063
+
1064
+ 'green-fg': #3fb950,
1065
+ 'red-fg': #ffa198,
1066
+ 'yellow-fg': #e3b341,
1067
+ 'blue-fg': #79c0ff,
1068
+ 'purple-fg': #d2a8ff,
1069
+ 'cyan-fg': #56d364,
1070
+
1071
+ 'border-subtle': rgba(255, 255, 255, 0.06),
1072
+ 'border-input': rgba(255, 255, 255, 0.10),
1073
+
1074
+ 'highlight-top': inset 0 1px 0 rgba(255, 255, 255, 0.03),
1075
+
1076
+ 'radius-md': 6px,
1077
+ 'radius-lg': 8px,
1078
+ 'radius-xl': 12px,
1079
+
1080
+ 'shadow-xs': 0 1px 2px rgba(0, 0, 0, 0.3),
1081
+ 'shadow-sm': 0 1px 3px rgba(0, 0, 0, 0.4),
1082
+ 'shadow-md': 0 4px 6px rgba(0, 0, 0, 0.4),
1083
+ 'shadow-lg': 0 10px 15px rgba(0, 0, 0, 0.5),
1084
+
1085
+ 'font-ui': var(--font-sans),
1086
+
1087
+ 'code-comment': #6e7681,
1088
+ 'code-keyword': #ff7b72,
1089
+ 'code-function': #d2a8ff,
1090
+ 'code-string': #a5d6ff,
1091
+ 'code-number': #79c0ff,
1092
+ 'code-class': #ffa657,
1093
+ 'code-tag': #7ee787,
1094
+ 'code-deleted': #ffa198,
1095
+ 'code-inserted': #7ee787,
1096
+ 'code-punctuation': #c9d1d9,
1097
+ );
1098
+
1099
+ [data-theme="primer"] {
1100
+ color-scheme: dark;
1101
+ @include define-theme($primer-palette);
1102
+ }