spec-gen-cli 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (205) hide show
  1. package/README.md +163 -77
  2. package/dist/api/analyze.d.ts.map +1 -1
  3. package/dist/api/analyze.js +56 -27
  4. package/dist/api/analyze.js.map +1 -1
  5. package/dist/api/drift.d.ts.map +1 -1
  6. package/dist/api/drift.js +26 -20
  7. package/dist/api/drift.js.map +1 -1
  8. package/dist/api/generate.d.ts.map +1 -1
  9. package/dist/api/generate.js +19 -43
  10. package/dist/api/generate.js.map +1 -1
  11. package/dist/api/init.d.ts.map +1 -1
  12. package/dist/api/init.js +6 -5
  13. package/dist/api/init.js.map +1 -1
  14. package/dist/api/run.d.ts.map +1 -1
  15. package/dist/api/run.js +67 -51
  16. package/dist/api/run.js.map +1 -1
  17. package/dist/api/specs.d.ts.map +1 -1
  18. package/dist/api/specs.js +5 -4
  19. package/dist/api/specs.js.map +1 -1
  20. package/dist/api/types.d.ts +7 -1
  21. package/dist/api/types.d.ts.map +1 -1
  22. package/dist/api/verify.d.ts.map +1 -1
  23. package/dist/api/verify.js +31 -32
  24. package/dist/api/verify.js.map +1 -1
  25. package/dist/cli/commands/analyze.d.ts.map +1 -1
  26. package/dist/cli/commands/analyze.js +41 -62
  27. package/dist/cli/commands/analyze.js.map +1 -1
  28. package/dist/cli/commands/doctor.d.ts +9 -0
  29. package/dist/cli/commands/doctor.d.ts.map +1 -0
  30. package/dist/cli/commands/doctor.js +273 -0
  31. package/dist/cli/commands/doctor.js.map +1 -0
  32. package/dist/cli/commands/drift.d.ts.map +1 -1
  33. package/dist/cli/commands/drift.js +18 -32
  34. package/dist/cli/commands/drift.js.map +1 -1
  35. package/dist/cli/commands/generate.d.ts.map +1 -1
  36. package/dist/cli/commands/generate.js +40 -101
  37. package/dist/cli/commands/generate.js.map +1 -1
  38. package/dist/cli/commands/init.d.ts.map +1 -1
  39. package/dist/cli/commands/init.js +17 -15
  40. package/dist/cli/commands/init.js.map +1 -1
  41. package/dist/cli/commands/mcp.d.ts.map +1 -1
  42. package/dist/cli/commands/mcp.js +2 -1
  43. package/dist/cli/commands/mcp.js.map +1 -1
  44. package/dist/cli/commands/run.d.ts +0 -15
  45. package/dist/cli/commands/run.d.ts.map +1 -1
  46. package/dist/cli/commands/run.js +61 -111
  47. package/dist/cli/commands/run.js.map +1 -1
  48. package/dist/cli/commands/verify.d.ts.map +1 -1
  49. package/dist/cli/commands/verify.js +18 -52
  50. package/dist/cli/commands/verify.js.map +1 -1
  51. package/dist/cli/commands/view.d.ts +4 -0
  52. package/dist/cli/commands/view.d.ts.map +1 -1
  53. package/dist/cli/commands/view.js +29 -24
  54. package/dist/cli/commands/view.js.map +1 -1
  55. package/dist/cli/index.js +22 -4
  56. package/dist/cli/index.js.map +1 -1
  57. package/dist/constants.d.ts +254 -0
  58. package/dist/constants.d.ts.map +1 -0
  59. package/dist/constants.js +320 -0
  60. package/dist/constants.js.map +1 -0
  61. package/dist/core/analyzer/artifact-generator.d.ts +8 -0
  62. package/dist/core/analyzer/artifact-generator.d.ts.map +1 -1
  63. package/dist/core/analyzer/artifact-generator.js +59 -11
  64. package/dist/core/analyzer/artifact-generator.js.map +1 -1
  65. package/dist/core/analyzer/call-graph.d.ts.map +1 -1
  66. package/dist/core/analyzer/call-graph.js +135 -1
  67. package/dist/core/analyzer/call-graph.js.map +1 -1
  68. package/dist/core/analyzer/dependency-graph.d.ts +32 -0
  69. package/dist/core/analyzer/dependency-graph.d.ts.map +1 -1
  70. package/dist/core/analyzer/dependency-graph.js +104 -10
  71. package/dist/core/analyzer/dependency-graph.js.map +1 -1
  72. package/dist/core/analyzer/duplicate-detector.d.ts.map +1 -1
  73. package/dist/core/analyzer/duplicate-detector.js +4 -0
  74. package/dist/core/analyzer/duplicate-detector.js.map +1 -1
  75. package/dist/core/analyzer/embedding-service.d.ts +6 -0
  76. package/dist/core/analyzer/embedding-service.d.ts.map +1 -1
  77. package/dist/core/analyzer/embedding-service.js +15 -1
  78. package/dist/core/analyzer/embedding-service.js.map +1 -1
  79. package/dist/core/analyzer/file-walker.d.ts.map +1 -1
  80. package/dist/core/analyzer/file-walker.js +4 -3
  81. package/dist/core/analyzer/file-walker.js.map +1 -1
  82. package/dist/core/analyzer/http-route-parser.d.ts +111 -0
  83. package/dist/core/analyzer/http-route-parser.d.ts.map +1 -0
  84. package/dist/core/analyzer/http-route-parser.js +466 -0
  85. package/dist/core/analyzer/http-route-parser.js.map +1 -0
  86. package/dist/core/analyzer/import-parser.d.ts.map +1 -1
  87. package/dist/core/analyzer/import-parser.js +19 -5
  88. package/dist/core/analyzer/import-parser.js.map +1 -1
  89. package/dist/core/analyzer/refactor-analyzer.d.ts.map +1 -1
  90. package/dist/core/analyzer/refactor-analyzer.js +8 -7
  91. package/dist/core/analyzer/refactor-analyzer.js.map +1 -1
  92. package/dist/core/analyzer/repository-mapper.d.ts.map +1 -1
  93. package/dist/core/analyzer/repository-mapper.js +12 -13
  94. package/dist/core/analyzer/repository-mapper.js.map +1 -1
  95. package/dist/core/analyzer/signature-extractor.d.ts +1 -1
  96. package/dist/core/analyzer/signature-extractor.d.ts.map +1 -1
  97. package/dist/core/analyzer/signature-extractor.js +69 -1
  98. package/dist/core/analyzer/signature-extractor.js.map +1 -1
  99. package/dist/core/analyzer/spec-vector-index.d.ts.map +1 -1
  100. package/dist/core/analyzer/spec-vector-index.js +4 -3
  101. package/dist/core/analyzer/spec-vector-index.js.map +1 -1
  102. package/dist/core/analyzer/vector-index.d.ts.map +1 -1
  103. package/dist/core/analyzer/vector-index.js +29 -1
  104. package/dist/core/analyzer/vector-index.js.map +1 -1
  105. package/dist/core/drift/drift-detector.d.ts.map +1 -1
  106. package/dist/core/drift/drift-detector.js +7 -6
  107. package/dist/core/drift/drift-detector.js.map +1 -1
  108. package/dist/core/drift/git-diff.d.ts.map +1 -1
  109. package/dist/core/drift/git-diff.js +28 -16
  110. package/dist/core/drift/git-diff.js.map +1 -1
  111. package/dist/core/generator/mapping-generator.d.ts.map +1 -1
  112. package/dist/core/generator/mapping-generator.js +11 -10
  113. package/dist/core/generator/mapping-generator.js.map +1 -1
  114. package/dist/core/generator/openspec-compat.d.ts.map +1 -1
  115. package/dist/core/generator/openspec-compat.js +3 -2
  116. package/dist/core/generator/openspec-compat.js.map +1 -1
  117. package/dist/core/generator/openspec-format-generator.js.map +1 -1
  118. package/dist/core/generator/openspec-writer.d.ts +0 -4
  119. package/dist/core/generator/openspec-writer.d.ts.map +1 -1
  120. package/dist/core/generator/openspec-writer.js +30 -41
  121. package/dist/core/generator/openspec-writer.js.map +1 -1
  122. package/dist/core/generator/spec-pipeline.d.ts.map +1 -1
  123. package/dist/core/generator/spec-pipeline.js +4 -4
  124. package/dist/core/generator/spec-pipeline.js.map +1 -1
  125. package/dist/core/generator/stages/stage1-survey.d.ts.map +1 -1
  126. package/dist/core/generator/stages/stage1-survey.js +5 -3
  127. package/dist/core/generator/stages/stage1-survey.js.map +1 -1
  128. package/dist/core/generator/stages/stage2-entities.d.ts.map +1 -1
  129. package/dist/core/generator/stages/stage2-entities.js +10 -9
  130. package/dist/core/generator/stages/stage2-entities.js.map +1 -1
  131. package/dist/core/generator/stages/stage3-services.d.ts.map +1 -1
  132. package/dist/core/generator/stages/stage3-services.js +9 -8
  133. package/dist/core/generator/stages/stage3-services.js.map +1 -1
  134. package/dist/core/generator/stages/stage4-api.d.ts.map +1 -1
  135. package/dist/core/generator/stages/stage4-api.js +10 -9
  136. package/dist/core/generator/stages/stage4-api.js.map +1 -1
  137. package/dist/core/generator/stages/stage5-architecture.d.ts.map +1 -1
  138. package/dist/core/generator/stages/stage5-architecture.js +5 -4
  139. package/dist/core/generator/stages/stage5-architecture.js.map +1 -1
  140. package/dist/core/generator/stages/stage6-adr.d.ts.map +1 -1
  141. package/dist/core/generator/stages/stage6-adr.js +7 -2
  142. package/dist/core/generator/stages/stage6-adr.js.map +1 -1
  143. package/dist/core/services/chat-agent.d.ts.map +1 -1
  144. package/dist/core/services/chat-agent.js +46 -15
  145. package/dist/core/services/chat-agent.js.map +1 -1
  146. package/dist/core/services/config-manager.d.ts.map +1 -1
  147. package/dist/core/services/config-manager.js +32 -26
  148. package/dist/core/services/config-manager.js.map +1 -1
  149. package/dist/core/services/gitignore-manager.d.ts.map +1 -1
  150. package/dist/core/services/gitignore-manager.js +2 -13
  151. package/dist/core/services/gitignore-manager.js.map +1 -1
  152. package/dist/core/services/llm-service.d.ts.map +1 -1
  153. package/dist/core/services/llm-service.js +33 -35
  154. package/dist/core/services/llm-service.js.map +1 -1
  155. package/dist/core/services/mcp-handlers/analysis.d.ts.map +1 -1
  156. package/dist/core/services/mcp-handlers/analysis.js +23 -14
  157. package/dist/core/services/mcp-handlers/analysis.js.map +1 -1
  158. package/dist/core/services/mcp-handlers/graph.d.ts.map +1 -1
  159. package/dist/core/services/mcp-handlers/graph.js +24 -23
  160. package/dist/core/services/mcp-handlers/graph.js.map +1 -1
  161. package/dist/core/services/mcp-handlers/semantic.d.ts +1 -1
  162. package/dist/core/services/mcp-handlers/semantic.d.ts.map +1 -1
  163. package/dist/core/services/mcp-handlers/semantic.js +17 -16
  164. package/dist/core/services/mcp-handlers/semantic.js.map +1 -1
  165. package/dist/core/services/mcp-handlers/utils.d.ts.map +1 -1
  166. package/dist/core/services/mcp-handlers/utils.js +4 -3
  167. package/dist/core/services/mcp-handlers/utils.js.map +1 -1
  168. package/dist/core/services/project-detector.d.ts.map +1 -1
  169. package/dist/core/services/project-detector.js +2 -13
  170. package/dist/core/services/project-detector.js.map +1 -1
  171. package/dist/core/verifier/verification-engine.d.ts +9 -3
  172. package/dist/core/verifier/verification-engine.d.ts.map +1 -1
  173. package/dist/core/verifier/verification-engine.js +25 -13
  174. package/dist/core/verifier/verification-engine.js.map +1 -1
  175. package/dist/types/index.d.ts +2 -0
  176. package/dist/types/index.d.ts.map +1 -1
  177. package/dist/utils/command-helpers.d.ts +38 -0
  178. package/dist/utils/command-helpers.d.ts.map +1 -0
  179. package/dist/utils/command-helpers.js +82 -0
  180. package/dist/utils/command-helpers.js.map +1 -0
  181. package/dist/utils/errors.d.ts.map +1 -1
  182. package/dist/utils/errors.js +4 -3
  183. package/dist/utils/errors.js.map +1 -1
  184. package/dist/utils/logger.d.ts.map +1 -1
  185. package/dist/utils/logger.js +14 -3
  186. package/dist/utils/logger.js.map +1 -1
  187. package/dist/utils/progress.d.ts +1 -1
  188. package/dist/utils/progress.d.ts.map +1 -1
  189. package/dist/utils/progress.js +15 -12
  190. package/dist/utils/progress.js.map +1 -1
  191. package/dist/utils/shutdown.d.ts.map +1 -1
  192. package/dist/utils/shutdown.js +4 -3
  193. package/dist/utils/shutdown.js.map +1 -1
  194. package/package.json +9 -5
  195. package/src/viewer/InteractiveGraphViewer.jsx +182 -139
  196. package/src/viewer/components/ArchitectureView.jsx +19 -19
  197. package/src/viewer/components/ChatPanel.jsx +40 -40
  198. package/src/viewer/components/ClusterGraph.jsx +34 -22
  199. package/src/viewer/components/FilterBar.jsx +26 -26
  200. package/src/viewer/components/FlatGraph.jsx +22 -15
  201. package/src/viewer/components/MicroComponents.jsx +14 -12
  202. package/src/viewer/utils/constants.js +17 -0
  203. package/src/viewer/utils/graph-helpers.js +7 -3
  204. package/src/viewer/utils/graph-helpers.test.ts +39 -0
  205. package/src/viewer/utils/themes.js +170 -0
@@ -10,7 +10,7 @@ export function ArchitectureView({ graph, llmCtx, focusedIds }) {
10
10
  return new Set(graph.nodes.filter(n => focusedIds.includes(n.id)).map(n => n.cluster.id));
11
11
  }, [focusedIds, graph]);
12
12
 
13
- if (!overview) return <div style={{ color: '#3a3f5c', padding: 24, fontSize: 11 }}>No graph loaded.</div>;
13
+ if (!overview) return <div style={{ color: 'var(--tx-ghost)', padding: 24, fontSize: 11 }}>No graph loaded.</div>;
14
14
 
15
15
  const { summary, clusters, globalEntryPoints, criticalHubs } = overview;
16
16
 
@@ -49,7 +49,7 @@ export function ArchitectureView({ graph, llmCtx, focusedIds }) {
49
49
  <line
50
50
  key={`${cl.id}->${toId}`}
51
51
  x1={sx} y1={sy} x2={ex} y2={ey}
52
- stroke={isHov ? '#7c6af7' : '#1e2240'}
52
+ stroke={isHov ? 'var(--ac-primary)' : 'var(--ac-arrow)'}
53
53
  strokeWidth={isHov ? 1.5 : 1}
54
54
  markerEnd="url(#arrowhead)"
55
55
  opacity={isHov ? 1 : 0.6}
@@ -71,8 +71,8 @@ export function ArchitectureView({ graph, llmCtx, focusedIds }) {
71
71
  summary.cycles > 0 ? ['⚠ cycles', summary.cycles] : null,
72
72
  summary.layerViolations > 0 ? ['⚠ violations', summary.layerViolations] : null,
73
73
  ].filter(Boolean).map(([l, v]) => (
74
- <div key={l} style={{ fontSize: 9, color: '#6a70a0', background: '#0e1028', borderRadius: 4, padding: '2px 8px', border: '1px solid #141830' }}>
75
- <span style={{ color: l.startsWith('⚠') ? '#f97316' : '#c8cde8' }}>{v}</span> {l}
74
+ <div key={l} style={{ fontSize: 9, color: 'var(--tx-muted)', background: 'var(--bg-raised)', borderRadius: 4, padding: '2px 8px', border: '1px solid var(--bd-muted)' }}>
75
+ <span style={{ color: l.startsWith('⚠') ? '#f97316' : 'var(--tx-primary)' }}>{v}</span> {l}
76
76
  </div>
77
77
  ))}
78
78
  </div>
@@ -80,7 +80,7 @@ export function ArchitectureView({ graph, llmCtx, focusedIds }) {
80
80
  <svg width={SVG_W} height={SVG_H} style={{ display: 'block', minWidth: SVG_W }}>
81
81
  <defs>
82
82
  <marker id="arrowhead" markerWidth="6" markerHeight="6" refX="3" refY="3" orient="auto">
83
- <path d="M0,0 L0,6 L6,3 z" fill="#3a3f6c" />
83
+ <path d="M0,0 L0,6 L6,3 z" style={{ fill: 'var(--ac-cluster-arr)' }} />
84
84
  </marker>
85
85
  </defs>
86
86
 
@@ -102,25 +102,25 @@ export function ArchitectureView({ graph, llmCtx, focusedIds }) {
102
102
  <rect
103
103
  x={x} y={y} width={BOX_W} height={BOX_H}
104
104
  rx={6} ry={6}
105
- fill={isHov ? '#12163a' : '#0b0e28'}
106
- stroke={isHov ? color : isDimmed ? '#0e1028' : '#1e2240'}
105
+ style={{ fill: isHov ? 'var(--bg-hover)' : 'var(--bg-node)' }}
106
+ stroke={isHov ? color : isDimmed ? 'var(--bg-raised)' : 'var(--ac-arrow)'}
107
107
  strokeWidth={isHov ? 1.5 : 1}
108
108
  />
109
109
  <rect x={x} y={y} width={4} height={BOX_H} rx={3} ry={3} fill={color} opacity={0.8} />
110
- <text x={x + 12} y={y + 18} fill="#c8cde8" fontSize={10} fontWeight="600" fontFamily="inherit">
111
- {cl.name.length > 18 ? cl.name.slice(0, 17) + '...' : cl.name}
110
+ <text x={x + 12} y={y + 18} style={{ fill: 'var(--tx-primary)' }} fontSize={10} fontWeight="600" fontFamily="inherit">
111
+ {cl.name.length > 18 ? cl.name.slice(0, 17) + '' : cl.name}
112
112
  </text>
113
113
  <text x={x + 12} y={y + 31} fill={color} fontSize={8} fontFamily="inherit" opacity={0.9}>
114
114
  {ROLE_LABEL[cl.role] ?? cl.role}
115
115
  </text>
116
- <text x={x + 12} y={y + 44} fill="#3a4060" fontSize={8} fontFamily="inherit">
116
+ <text x={x + 12} y={y + 44} style={{ fill: 'var(--tx-dim)' }} fontSize={8} fontFamily="inherit">
117
117
  {cl.fileCount} files
118
118
  {cl.hubCount > 0 ? ` · ${cl.hubCount} hub${cl.hubCount > 1 ? 's' : ''}` : ''}
119
119
  {cl.entryPointCount > 0 ? ` · ${cl.entryPointCount} entry` : ''}
120
120
  </text>
121
121
  {cl.dependsOn.length > 0 && (
122
- <text x={x + BOX_W - 6} y={y + 18} fill="#3a4060" fontSize={7} fontFamily="inherit" textAnchor="end">
123
- {'->'}{ cl.dependsOn.length}
122
+ <text x={x + BOX_W - 6} y={y + 18} style={{ fill: 'var(--tx-dim)' }} fontSize={7} fontFamily="inherit" textAnchor="end">
123
+ {cl.dependsOn.length}
124
124
  </text>
125
125
  )}
126
126
  </g>
@@ -130,7 +130,7 @@ export function ArchitectureView({ graph, llmCtx, focusedIds }) {
130
130
 
131
131
  <div style={{ display: 'flex', gap: 12, marginTop: 12, flexWrap: 'wrap' }}>
132
132
  {Object.entries(ROLE_LABEL).map(([role, label]) => (
133
- <div key={role} style={{ display: 'flex', alignItems: 'center', gap: 4, fontSize: 8, color: '#3a4060' }}>
133
+ <div key={role} style={{ display: 'flex', alignItems: 'center', gap: 4, fontSize: 8, color: 'var(--tx-dim)' }}>
134
134
  <div style={{ width: 8, height: 8, borderRadius: 2, background: ROLE_COLOR[role] }} />
135
135
  {label}
136
136
  </div>
@@ -138,7 +138,7 @@ export function ArchitectureView({ graph, llmCtx, focusedIds }) {
138
138
  </div>
139
139
  </div>
140
140
 
141
- <div style={{ width: 220, borderLeft: '1px solid #0f1224', overflow: 'auto', padding: '12px 10px', flexShrink: 0 }}>
141
+ <div style={{ width: 220, borderLeft: '1px solid var(--bd-faint)', overflow: 'auto', padding: '12px 10px', flexShrink: 0 }}>
142
142
  {globalEntryPoints.length > 0 && (
143
143
  <>
144
144
  <div style={{ ...S, color: '#4ade80', fontWeight: 600, marginBottom: 6, letterSpacing: '0.08em', textTransform: 'uppercase' }}>
@@ -146,8 +146,8 @@ export function ArchitectureView({ graph, llmCtx, focusedIds }) {
146
146
  </div>
147
147
  {globalEntryPoints.map((ep, i) => (
148
148
  <div key={i} style={{ marginBottom: 6 }}>
149
- <div style={{ ...S, color: '#c8cde8', fontWeight: 600 }}>{ep.name}</div>
150
- <div style={{ ...S, color: '#3a4060', wordBreak: 'break-all' }}>{ep.file}</div>
149
+ <div style={{ ...S, color: 'var(--tx-primary)', fontWeight: 600 }}>{ep.name}</div>
150
+ <div style={{ ...S, color: 'var(--tx-dim)', wordBreak: 'break-all' }}>{ep.file}</div>
151
151
  </div>
152
152
  ))}
153
153
  </>
@@ -160,8 +160,8 @@ export function ArchitectureView({ graph, llmCtx, focusedIds }) {
160
160
  </div>
161
161
  {criticalHubs.map((hub, i) => (
162
162
  <div key={i} style={{ marginBottom: 6 }}>
163
- <div style={{ ...S, color: '#c8cde8', fontWeight: 600 }}>{hub.name}</div>
164
- <div style={{ ...S, color: '#3a4060', wordBreak: 'break-all' }}>{hub.file}</div>
163
+ <div style={{ ...S, color: 'var(--tx-primary)', fontWeight: 600 }}>{hub.name}</div>
164
+ <div style={{ ...S, color: 'var(--tx-dim)', wordBreak: 'break-all' }}>{hub.file}</div>
165
165
  <div style={{ ...S, color: '#f97316', opacity: 0.7 }}>fanIn {hub.fanIn} · fanOut {hub.fanOut}</div>
166
166
  </div>
167
167
  ))}
@@ -169,7 +169,7 @@ export function ArchitectureView({ graph, llmCtx, focusedIds }) {
169
169
  )}
170
170
 
171
171
  {globalEntryPoints.length === 0 && criticalHubs.length === 0 && (
172
- <div style={{ ...S, color: '#3a3f5c' }}>Run <code style={{ color: '#7c6af7' }}>spec-gen analyze</code> to populate call graph data.</div>
172
+ <div style={{ ...S, color: 'var(--tx-ghost)' }}>Run <code style={{ color: 'var(--ac-primary)' }}>spec-gen analyze</code> to populate call graph data.</div>
173
173
  )}
174
174
  </div>
175
175
  </div>
@@ -11,9 +11,9 @@ function escapeHtml(str) {
11
11
  function renderInline(text) {
12
12
  // Escape HTML first to prevent XSS, then apply markdown formatting
13
13
  return escapeHtml(text)
14
- .replace(/`([^`]+)`/g, '<code style="background:#1a1f38;padding:1px 4px;border-radius:3px;font-family:JetBrains Mono,monospace;font-size:8px;color:#c8cde8">$1</code>')
15
- .replace(/\*\*([^*]+)\*\*/g, '<strong style="color:#c8cde8">$1</strong>')
16
- .replace(/\*([^*]+)\*/g, '<em style="color:#9b96c8">$1</em>');
14
+ .replace(/`([^`]+)`/g, '<code style="background:var(--bd-muted);padding:1px 4px;border-radius:3px;font-family:JetBrains Mono,monospace;font-size:8px;color:var(--tx-primary)">$1</code>')
15
+ .replace(/\*\*([^*]+)\*\*/g, '<strong style="color:var(--tx-primary)">$1</strong>')
16
+ .replace(/\*([^*]+)\*/g, '<em style="color:var(--tx-secondary)">$1</em>');
17
17
  }
18
18
 
19
19
  function MarkdownBlock({ text }) {
@@ -34,9 +34,9 @@ function MarkdownBlock({ text }) {
34
34
  }
35
35
  elements.push(
36
36
  <pre key={i} style={{
37
- background: '#0c0e22', border: '1px solid #141830', borderRadius: 4,
37
+ background: 'var(--bg-input)', border: '1px solid var(--bd-muted)', borderRadius: 4,
38
38
  padding: '6px 8px', margin: '4px 0', overflowX: 'auto',
39
- fontSize: 8, color: '#9b96c8', fontFamily: 'JetBrains Mono,monospace', lineHeight: 1.5,
39
+ fontSize: 8, color: 'var(--tx-secondary)', fontFamily: 'JetBrains Mono,monospace', lineHeight: 1.5,
40
40
  }}>
41
41
  {codeLines.join('\n')}
42
42
  </pre>
@@ -49,7 +49,7 @@ function MarkdownBlock({ text }) {
49
49
  if (/^#{3,4}\s+/.test(line)) {
50
50
  const content = line.replace(/^#{3,4}\s+/, '');
51
51
  elements.push(
52
- <div key={i} style={{ fontSize: 9, color: '#7c6af7', fontWeight: 600, margin: '8px 0 3px', letterSpacing: '0.04em' }}
52
+ <div key={i} style={{ fontSize: 9, color: 'var(--ac-primary)', fontWeight: 600, margin: '8px 0 3px', letterSpacing: '0.04em' }}
53
53
  dangerouslySetInnerHTML={{ __html: renderInline(content) }} />
54
54
  );
55
55
  i++;
@@ -60,7 +60,7 @@ function MarkdownBlock({ text }) {
60
60
  if (/^#{1,2}\s+/.test(line)) {
61
61
  const content = line.replace(/^#{1,2}\s+/, '');
62
62
  elements.push(
63
- <div key={i} style={{ fontSize: 10, color: '#c8cde8', fontWeight: 700, margin: '10px 0 4px' }}
63
+ <div key={i} style={{ fontSize: 10, color: 'var(--tx-primary)', fontWeight: 700, margin: '10px 0 4px' }}
64
64
  dangerouslySetInnerHTML={{ __html: renderInline(content) }} />
65
65
  );
66
66
  i++;
@@ -77,8 +77,8 @@ function MarkdownBlock({ text }) {
77
77
  elements.push(
78
78
  <ul key={i} style={{ margin: '3px 0', paddingLeft: 14, listStyle: 'none' }}>
79
79
  {items.map((item, j) => (
80
- <li key={j} style={{ fontSize: 9, color: '#9b96c8', lineHeight: 1.6, position: 'relative', paddingLeft: 8 }}>
81
- <span style={{ position: 'absolute', left: 0, color: '#7c6af7' }}>·</span>
80
+ <li key={j} style={{ fontSize: 9, color: 'var(--tx-secondary)', lineHeight: 1.6, position: 'relative', paddingLeft: 8 }}>
81
+ <span style={{ position: 'absolute', left: 0, color: 'var(--ac-primary)' }}>·</span>
82
82
  <span dangerouslySetInnerHTML={{ __html: renderInline(item) }} />
83
83
  </li>
84
84
  ))}
@@ -98,8 +98,8 @@ function MarkdownBlock({ text }) {
98
98
  elements.push(
99
99
  <ol key={i} style={{ margin: '3px 0', paddingLeft: 0, listStyle: 'none' }}>
100
100
  {items.map((item, j) => (
101
- <li key={j} style={{ fontSize: 9, color: '#9b96c8', lineHeight: 1.6, display: 'flex', gap: 5, margin: '1px 0' }}>
102
- <span style={{ color: '#7c6af7', flexShrink: 0, fontVariantNumeric: 'tabular-nums' }}>{item.num}.</span>
101
+ <li key={j} style={{ fontSize: 9, color: 'var(--tx-secondary)', lineHeight: 1.6, display: 'flex', gap: 5, margin: '1px 0' }}>
102
+ <span style={{ color: 'var(--ac-primary)', flexShrink: 0, fontVariantNumeric: 'tabular-nums' }}>{item.num}.</span>
103
103
  <span dangerouslySetInnerHTML={{ __html: renderInline(item.text) }} />
104
104
  </li>
105
105
  ))}
@@ -110,7 +110,7 @@ function MarkdownBlock({ text }) {
110
110
 
111
111
  // Horizontal rule
112
112
  if (/^---+$/.test(line.trim())) {
113
- elements.push(<hr key={i} style={{ border: 'none', borderTop: '1px solid #141830', margin: '6px 0' }} />);
113
+ elements.push(<hr key={i} style={{ border: 'none', borderTop: '1px solid var(--bd-muted)', margin: '6px 0' }} />);
114
114
  i++;
115
115
  continue;
116
116
  }
@@ -124,7 +124,7 @@ function MarkdownBlock({ text }) {
124
124
 
125
125
  // Plain paragraph
126
126
  elements.push(
127
- <div key={i} style={{ fontSize: 9, color: '#9b96c8', lineHeight: 1.6 }}
127
+ <div key={i} style={{ fontSize: 9, color: 'var(--tx-secondary)', lineHeight: 1.6 }}
128
128
  dangerouslySetInnerHTML={{ __html: renderInline(line) }} />
129
129
  );
130
130
  i++;
@@ -144,7 +144,7 @@ function ToolSpinner() {
144
144
  const id = setInterval(() => setFrame((f) => (f + 1) % frames.length), 80);
145
145
  return () => clearInterval(id);
146
146
  }, []);
147
- return <span style={{ color: '#7c6af7', fontFamily: 'monospace', fontSize: 10, lineHeight: 1 }}>{frames[frame]}</span>;
147
+ return <span style={{ color: 'var(--ac-primary)', fontFamily: 'monospace', fontSize: 10, lineHeight: 1 }}>{frames[frame]}</span>;
148
148
  }
149
149
 
150
150
  // ============================================================================
@@ -270,8 +270,8 @@ export function ChatPanel({ onHighlight, onClose }) {
270
270
  <div
271
271
  style={{
272
272
  width: 340,
273
- borderLeft: '1px solid #0f1224',
274
- background: '#080b1e',
273
+ borderLeft: '1px solid var(--bd-faint)',
274
+ background: 'var(--bg-deep)',
275
275
  display: 'flex',
276
276
  flexDirection: 'column',
277
277
  overflow: 'hidden',
@@ -284,22 +284,22 @@ export function ChatPanel({ onHighlight, onClose }) {
284
284
  display: 'flex',
285
285
  flexDirection: 'column',
286
286
  padding: '6px 10px',
287
- borderBottom: '1px solid #0f1224',
287
+ borderBottom: '1px solid var(--bd-faint)',
288
288
  flexShrink: 0,
289
289
  gap: 5,
290
290
  }}
291
291
  >
292
292
  <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
293
- <span style={{ fontSize: 9, color: '#7c6af7', letterSpacing: '0.1em', fontFamily: 'inherit' }}>
294
- DIAGRAM CHAT
293
+ <span style={{ fontSize: 9, color: 'var(--ac-primary)', letterSpacing: '0.1em', fontFamily: 'inherit' }}>
294
+ DIAGRAM CHAT
295
295
  </span>
296
296
  <div style={{ display: 'flex', gap: 6 }}>
297
297
  <button
298
298
  onClick={clear}
299
299
  title="Clear conversation"
300
300
  style={{
301
- background: 'none', border: '1px solid #1a1f38', borderRadius: 3,
302
- color: '#3a3f5c', fontSize: 8, padding: '2px 6px', cursor: 'pointer', fontFamily: 'inherit',
301
+ background: 'none', border: '1px solid var(--bd-muted)', borderRadius: 3,
302
+ color: 'var(--tx-ghost)', fontSize: 8, padding: '2px 6px', cursor: 'pointer', fontFamily: 'inherit',
303
303
  }}
304
304
  >
305
305
  CLEAR
@@ -308,8 +308,8 @@ export function ChatPanel({ onHighlight, onClose }) {
308
308
  onClick={onClose}
309
309
  title="Close chat"
310
310
  style={{
311
- background: 'none', border: '1px solid #1a1f38', borderRadius: 3,
312
- color: '#3a3f5c', fontSize: 10, padding: '2px 6px', cursor: 'pointer', fontFamily: 'inherit', lineHeight: 1,
311
+ background: 'none', border: '1px solid var(--bd-muted)', borderRadius: 3,
312
+ color: 'var(--tx-ghost)', fontSize: 10, padding: '2px 6px', cursor: 'pointer', fontFamily: 'inherit', lineHeight: 1,
313
313
  }}
314
314
  >
315
315
  x
@@ -319,15 +319,15 @@ export function ChatPanel({ onHighlight, onClose }) {
319
319
  {/* Model selector */}
320
320
  {modelInfo && (
321
321
  <div style={{ display: 'flex', alignItems: 'center', gap: 5 }}>
322
- <span style={{ fontSize: 8, color: '#3a3f5c', letterSpacing: '0.06em', flexShrink: 0 }}>
322
+ <span style={{ fontSize: 8, color: 'var(--tx-ghost)', letterSpacing: '0.06em', flexShrink: 0 }}>
323
323
  {modelInfo.provider.toUpperCase()}
324
324
  </span>
325
325
  <select
326
326
  value={modelInfo.currentModel}
327
327
  onChange={(e) => setModelInfo((prev) => ({ ...prev, currentModel: e.target.value }))}
328
328
  style={{
329
- flex: 1, background: '#0c0e22', border: '1px solid #2a2f4c', borderRadius: 3,
330
- color: '#9b96c8', fontSize: 8, padding: '2px 4px', fontFamily: 'inherit',
329
+ flex: 1, background: 'var(--bg-input)', border: '1px solid var(--bd-muted)', borderRadius: 3,
330
+ color: 'var(--tx-secondary)', fontSize: 8, padding: '2px 4px', fontFamily: 'inherit',
331
331
  cursor: 'pointer', outline: 'none',
332
332
  }}
333
333
  >
@@ -353,15 +353,15 @@ export function ChatPanel({ onHighlight, onClose }) {
353
353
  <div key={i} style={{ alignSelf: m.role === 'user' ? 'flex-end' : 'flex-start', maxWidth: '96%' }}>
354
354
  <div
355
355
  style={{
356
- background: m.role === 'user' ? '#141830' : '#0c0e22',
357
- border: `1px solid ${m.role === 'user' ? '#1a1f38' : '#0f1224'}`,
356
+ background: m.role === 'user' ? 'var(--bg-hover)' : 'var(--bg-input)',
357
+ border: `1px solid ${m.role === 'user' ? 'var(--bd-muted)' : 'var(--bd-faint)'}`,
358
358
  borderRadius: m.role === 'user' ? '8px 8px 2px 8px' : '8px 8px 8px 2px',
359
359
  padding: '6px 10px',
360
360
  fontFamily: 'inherit',
361
361
  }}
362
362
  >
363
363
  {m.role === 'user' ? (
364
- <div style={{ fontSize: 9, color: '#c8cde8', lineHeight: 1.5, whiteSpace: 'pre-wrap' }}>
364
+ <div style={{ fontSize: 9, color: 'var(--tx-primary)', lineHeight: 1.5, whiteSpace: 'pre-wrap' }}>
365
365
  {m.content}
366
366
  </div>
367
367
  ) : (
@@ -374,8 +374,8 @@ export function ChatPanel({ onHighlight, onClose }) {
374
374
  {loading && (
375
375
  <div style={{ alignSelf: 'flex-start' }}>
376
376
  <div style={{
377
- fontSize: 9, color: '#7c6af7', background: '#0c0e22',
378
- border: '1px solid #0f1224', borderRadius: '8px 8px 8px 2px',
377
+ fontSize: 9, color: 'var(--ac-primary)', background: 'var(--bg-input)',
378
+ border: '1px solid var(--bd-faint)', borderRadius: '8px 8px 8px 2px',
379
379
  padding: '6px 10px', fontFamily: 'inherit',
380
380
  display: 'flex', flexDirection: 'column', gap: 4,
381
381
  }}>
@@ -385,7 +385,7 @@ export function ChatPanel({ onHighlight, onClose }) {
385
385
  activeTools.map((name, i) => (
386
386
  <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 5 }}>
387
387
  <ToolSpinner />
388
- <span style={{ color: '#9b96c8' }}>{name.replace(/_/g, ' ')}</span>
388
+ <span style={{ color: 'var(--tx-secondary)' }}>{name.replace(/_/g, ' ')}</span>
389
389
  </div>
390
390
  ))
391
391
  )}
@@ -395,8 +395,8 @@ export function ChatPanel({ onHighlight, onClose }) {
395
395
 
396
396
  {error && (
397
397
  <div style={{
398
- fontSize: 9, color: '#f87171', background: '#1a0a0a',
399
- border: '1px solid #3a1a1a', borderRadius: 4,
398
+ fontSize: 9, color: 'var(--tx-primary)', background: 'rgba(192,57,43,0.10)',
399
+ border: '1px solid rgba(192,57,43,0.35)', borderRadius: 4,
400
400
  padding: '5px 8px', fontFamily: 'inherit',
401
401
  }}>
402
402
  Error: {error}
@@ -409,7 +409,7 @@ export function ChatPanel({ onHighlight, onClose }) {
409
409
  {/* Input area */}
410
410
  <div
411
411
  style={{
412
- borderTop: '1px solid #0f1224', padding: '8px 10px',
412
+ borderTop: '1px solid var(--bd-faint)', padding: '8px 10px',
413
413
  display: 'flex', flexDirection: 'column', gap: 6, flexShrink: 0,
414
414
  }}
415
415
  >
@@ -420,8 +420,8 @@ export function ChatPanel({ onHighlight, onClose }) {
420
420
  placeholder="Ask about the codebase... (Enter to send, Shift+Enter for newline)"
421
421
  rows={3}
422
422
  style={{
423
- background: '#0c0e22', border: '1px solid #141830', borderRadius: 4,
424
- color: '#c8cde8', fontSize: 9, padding: '6px 8px',
423
+ background: 'var(--bg-input)', border: '1px solid var(--bd-muted)', borderRadius: 4,
424
+ color: 'var(--tx-primary)', fontSize: 9, padding: '6px 8px',
425
425
  resize: 'none', outline: 'none', fontFamily: 'inherit', lineHeight: 1.4,
426
426
  }}
427
427
  />
@@ -430,10 +430,10 @@ export function ChatPanel({ onHighlight, onClose }) {
430
430
  onClick={send}
431
431
  disabled={!input.trim() || loading}
432
432
  style={{
433
- background: input.trim() && !loading ? '#1a1050' : 'transparent',
434
- border: `1px solid ${input.trim() && !loading ? '#7c6af7' : '#1a1f38'}`,
433
+ background: input.trim() && !loading ? 'var(--bg-select)' : 'transparent',
434
+ border: `1px solid ${input.trim() && !loading ? 'var(--ac-primary)' : 'var(--bd-muted)'}`,
435
435
  borderRadius: 4,
436
- color: input.trim() && !loading ? '#c8cde8' : '#3a3f5c',
436
+ color: input.trim() && !loading ? 'var(--tx-primary)' : 'var(--tx-ghost)',
437
437
  fontSize: 8, padding: '4px 12px',
438
438
  cursor: input.trim() && !loading ? 'pointer' : 'default',
439
439
  fontFamily: 'inherit', letterSpacing: '0.06em',
@@ -17,6 +17,7 @@ export function ClusterGraph({
17
17
  affectedIds,
18
18
  linkedIds,
19
19
  focusedIds,
20
+ noGlow,
20
21
  }) {
21
22
  const clusterPos = useMemo(
22
23
  () => computeClusterLayout(clusters),
@@ -112,13 +113,13 @@ export function ClusterGraph({
112
113
  >
113
114
  <defs>
114
115
  <marker id="carr" markerWidth="6" markerHeight="6" refX="5" refY="2.5" orient="auto">
115
- <path d="M0,0 L0,5 L6,2.5z" fill="#2a3060" />
116
+ <path d="M0,0 L0,5 L6,2.5z" style={{ fill: 'var(--ac-cluster-arr)' }} />
116
117
  </marker>
117
118
  <marker id="carr-sel" markerWidth="6" markerHeight="6" refX="5" refY="2.5" orient="auto">
118
- <path d="M0,0 L0,5 L6,2.5z" fill="#7c6af7" />
119
+ <path d="M0,0 L0,5 L6,2.5z" style={{ fill: 'var(--ac-primary)' }} />
119
120
  </marker>
120
121
  <marker id="carr-in" markerWidth="6" markerHeight="6" refX="5" refY="2.5" orient="auto">
121
- <path d="M0,0 L0,5 L6,2.5z" fill="#3ecfcf" />
122
+ <path d="M0,0 L0,5 L6,2.5z" style={{ fill: 'var(--ac-teal)' }} />
122
123
  </marker>
123
124
  <filter id="cglow">
124
125
  <feGaussianBlur stdDeviation="6" result="b" />
@@ -139,7 +140,11 @@ export function ClusterGraph({
139
140
  <g transform={`translate(${transform.x},${transform.y}) scale(${transform.k})`}>
140
141
  {/* Inter-cluster edges */}
141
142
  {!selectedId &&
142
- clusterEdges.map((e) => {
143
+ (() => {
144
+ const focusedClusterIds = focusedIds?.length > 0
145
+ ? new Set(nodes.filter((n) => focusedIds.includes(n.id)).map((n) => n.cluster.id))
146
+ : null;
147
+ return clusterEdges.map((e) => {
143
148
  const s = clusterPos[e.source],
144
149
  t = clusterPos[e.target];
145
150
  if (!s || !t) return null;
@@ -151,6 +156,8 @@ export function ClusterGraph({
151
156
  const rs = 38,
152
157
  rt = 38;
153
158
  const w = Math.min(1 + e.count * 0.15, 4);
159
+ const isDimEdge = focusedClusterIds &&
160
+ !focusedClusterIds.has(e.source) && !focusedClusterIds.has(e.target);
154
161
  return (
155
162
  <g key={e.id}>
156
163
  <line
@@ -158,9 +165,9 @@ export function ClusterGraph({
158
165
  y1={s.y + ny * rs}
159
166
  x2={t.x - nx * (rt + 5)}
160
167
  y2={t.y - ny * (rt + 5)}
161
- stroke="#1e2448"
168
+ stroke="var(--ac-arrow)"
162
169
  strokeWidth={w}
163
- strokeOpacity={0.5}
170
+ strokeOpacity={isDimEdge ? 0.06 : 0.5}
164
171
  markerEnd="url(#carr)"
165
172
  />
166
173
  <text
@@ -168,15 +175,15 @@ export function ClusterGraph({
168
175
  y={(s.y + ny * rs + t.y - ny * (rt + 5)) / 2 - 4}
169
176
  textAnchor="middle"
170
177
  fontSize={7}
171
- fill="#2a3060"
172
178
  fontFamily="'JetBrains Mono',monospace"
173
- style={{ pointerEvents: 'none' }}
179
+ style={{ pointerEvents: 'none', fill: 'var(--ac-cluster-arr)' }}
174
180
  >
175
181
  {e.count}
176
182
  </text>
177
183
  </g>
178
184
  );
179
- })}
185
+ });
186
+ })()}
180
187
 
181
188
  {/* Node-level edges when a node is selected */}
182
189
  {selectedId &&
@@ -208,7 +215,7 @@ export function ClusterGraph({
208
215
  y1={sp.y + ny * 14}
209
216
  x2={tp.x - nx * 19}
210
217
  y2={tp.y - ny * 19}
211
- stroke={isOut ? '#7c6af7' : '#3ecfcf'}
218
+ stroke={isOut ? 'var(--ac-primary)' : 'var(--ac-teal)'}
212
219
  strokeWidth={1.5}
213
220
  strokeOpacity={0.9}
214
221
  strokeDasharray={e.isType ? '4 2' : undefined}
@@ -239,6 +246,9 @@ export function ClusterGraph({
239
246
  const nx = dx / len,
240
247
  ny = dy / len,
241
248
  r = 13;
249
+ const isSel = e.source === selectedId || e.target === selectedId;
250
+ const isDimEdge = focusedIds?.length > 0 && !isSel &&
251
+ !focusedIds.includes(e.source) && !focusedIds.includes(e.target);
242
252
  return (
243
253
  <line
244
254
  key={e.id}
@@ -248,7 +258,7 @@ export function ClusterGraph({
248
258
  y2={t.y - ny * (r + 4)}
249
259
  stroke={cl.color}
250
260
  strokeWidth={0.8}
251
- strokeOpacity={0.45}
261
+ strokeOpacity={isDimEdge ? 0.06 : 0.45}
252
262
  strokeDasharray={e.isType ? '3 2' : undefined}
253
263
  markerEnd="url(#carr)"
254
264
  />
@@ -278,7 +288,7 @@ export function ClusterGraph({
278
288
  linkedIds.size > 0 && allMembers.some((n) => linkedIds.has(n.id));
279
289
  const hasFocused = focusedIds?.length > 0;
280
290
  const clusterFocused = hasFocused && allMembers.some((n) => focusedIds.includes(n.id));
281
- const isClusterGreyed =
291
+ const isClusterGreyed =
282
292
  (hasFocused && !clusterFocused && !clusterLinked) ||
283
293
  (!hasFocused && visibleMembers.length === 0 && !clusterLinked);
284
294
  const isLinkedCollapsed = clusterLinked && !isExpanded;
@@ -290,10 +300,11 @@ export function ClusterGraph({
290
300
  }}
291
301
  style={{ cursor: 'pointer' }}
292
302
  filter={
293
- isExpanded ? 'url(#cglow)' : isLinkedCollapsed ? 'url(#cglow)' : undefined
303
+ noGlow ? undefined : isExpanded ? 'url(#cglow)' : isLinkedCollapsed ? 'url(#cglow)' : undefined
294
304
  }
295
305
  opacity={isClusterGreyed ? 0.18 : 1}
296
306
  >
307
+ <title>{cl.name} — {allMembers.length} file{allMembers.length !== 1 ? 's' : ''}</title>
297
308
  <circle
298
309
  r={r}
299
310
  fill={isLinkedCollapsed ? `${cl.color}18` : `${cl.color}10`}
@@ -371,12 +382,13 @@ export function ClusterGraph({
371
382
  if (!isDrag()) onSelectNode(n.id);
372
383
  }}
373
384
  style={{ cursor: 'pointer' }}
374
- filter={isSel ? 'url(#nglow)' : undefined}
385
+ filter={noGlow ? undefined : isSel ? 'url(#nglow)' : undefined}
375
386
  opacity={isGreyed ? 0.18 : 1}
376
387
  >
388
+ <title>{n.label}{n.path ? `\n${n.path}` : ''}</title>
377
389
  <circle
378
390
  r={13}
379
- fill={isSel ? `${col}1a` : '#0b0d1e'}
391
+ fill={isSel ? `${col}1a` : 'var(--bg-node)'}
380
392
  stroke={isSel ? col : isAff ? col : cl.color}
381
393
  strokeWidth={isSel ? 2 : 0.8}
382
394
  strokeOpacity={isSel ? 1 : isAff ? 0.9 : 0.45}
@@ -385,7 +397,7 @@ export function ClusterGraph({
385
397
  textAnchor="middle"
386
398
  dominantBaseline="middle"
387
399
  fontSize={6}
388
- fill={isSel ? '#fff' : '#5a6090'}
400
+ fill={isSel ? 'var(--tx-node-sel)' : 'var(--tx-node)'}
389
401
  fontFamily="'JetBrains Mono',monospace"
390
402
  style={{ pointerEvents: 'none' }}
391
403
  >
@@ -406,10 +418,10 @@ export function ClusterGraph({
406
418
  style={{
407
419
  fontSize: 8,
408
420
  padding: '2px 6px',
409
- background: '#0d0f22',
410
- border: `1px solid ${transform.x !== 0 || transform.y !== 0 || transform.k !== 1 ? '#7c6af7' : '#1a1f38'}`,
421
+ background: 'var(--bg-input)',
422
+ border: `1px solid ${transform.x !== 0 || transform.y !== 0 || transform.k !== 1 ? 'var(--ac-primary)' : 'var(--bd-muted)'}`,
411
423
  borderRadius: 4,
412
- color: transform.x !== 0 || transform.y !== 0 || transform.k !== 1 ? '#7c6af7' : '#2a2f4a',
424
+ color: transform.x !== 0 || transform.y !== 0 || transform.k !== 1 ? 'var(--ac-primary)' : 'var(--tx-faint)',
413
425
  cursor: 'pointer',
414
426
  fontFamily: "'JetBrains Mono',monospace",
415
427
  letterSpacing: '0.05em',
@@ -423,10 +435,10 @@ export function ClusterGraph({
423
435
  style={{
424
436
  fontSize: 8,
425
437
  padding: '2px 6px',
426
- background: '#0d0f22',
427
- border: `1px solid ${hasSelection ? '#7c6af7' : '#1a1f38'}`,
438
+ background: 'var(--bg-input)',
439
+ border: `1px solid ${hasSelection ? 'var(--ac-primary)' : 'var(--bd-muted)'}`,
428
440
  borderRadius: 4,
429
- color: hasSelection ? '#7c6af7' : '#2a2f4a',
441
+ color: hasSelection ? 'var(--ac-primary)' : 'var(--tx-faint)',
430
442
  cursor: hasSelection ? 'pointer' : 'default',
431
443
  fontFamily: "'JetBrains Mono',monospace",
432
444
  letterSpacing: '0.05em',