codebase-onboarder 0.1.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 (216) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +275 -0
  3. package/bin/onboarder.js +14 -0
  4. package/bin/postinstall.js +6 -0
  5. package/cli/commands.js +436 -0
  6. package/cli/main.js +129 -0
  7. package/cli/prompt.js +101 -0
  8. package/cli/ui.js +55 -0
  9. package/cli/wizard.js +325 -0
  10. package/package.json +48 -0
  11. package/public/app.js +1339 -0
  12. package/public/index.html +455 -0
  13. package/public/js/about.js +284 -0
  14. package/public/js/aiDraft.js +163 -0
  15. package/public/js/analysisPanel.js +270 -0
  16. package/public/js/analysisReport.js +154 -0
  17. package/public/js/api.js +264 -0
  18. package/public/js/atlas.js +98 -0
  19. package/public/js/blameView.js +41 -0
  20. package/public/js/codeTab.js +256 -0
  21. package/public/js/codeViewer.js +184 -0
  22. package/public/js/components/FileChip.js +102 -0
  23. package/public/js/components/MetricSparkline.js +89 -0
  24. package/public/js/components/RiskBadge.js +105 -0
  25. package/public/js/deepAnalysisView.js +496 -0
  26. package/public/js/diagramPane.js +154 -0
  27. package/public/js/diffView.js +352 -0
  28. package/public/js/docsView.js +566 -0
  29. package/public/js/fileSourceBrowser.js +47 -0
  30. package/public/js/flameGraph.js +75 -0
  31. package/public/js/forceGraph.js +592 -0
  32. package/public/js/heatmap.js +185 -0
  33. package/public/js/highlight.js +122 -0
  34. package/public/js/html.js +50 -0
  35. package/public/js/insightsView.js +236 -0
  36. package/public/js/inspector.js +535 -0
  37. package/public/js/llm.js +345 -0
  38. package/public/js/mapView.js +159 -0
  39. package/public/js/markdown.js +119 -0
  40. package/public/js/mindmap.js +289 -0
  41. package/public/js/repoFiles.js +44 -0
  42. package/public/js/sbomView.js +142 -0
  43. package/public/js/scanCache.js +76 -0
  44. package/public/js/search.js +874 -0
  45. package/public/js/serverSettings.js +169 -0
  46. package/public/js/state.js +192 -0
  47. package/public/js/tour.js +17 -0
  48. package/public/js/transitions.js +15 -0
  49. package/public/js/tree.js +200 -0
  50. package/public/js/workflowsView.js +95 -0
  51. package/public/styles.css +2767 -0
  52. package/public/vendor/mermaid.min.js +3587 -0
  53. package/public/vendor/monaco/vs/base/browser/ui/codicons/codicon/codicon.ttf +0 -0
  54. package/public/vendor/monaco/vs/base/worker/workerMain.js +31 -0
  55. package/public/vendor/monaco/vs/basic-languages/abap/abap.js +10 -0
  56. package/public/vendor/monaco/vs/basic-languages/apex/apex.js +10 -0
  57. package/public/vendor/monaco/vs/basic-languages/azcli/azcli.js +10 -0
  58. package/public/vendor/monaco/vs/basic-languages/bat/bat.js +10 -0
  59. package/public/vendor/monaco/vs/basic-languages/bicep/bicep.js +11 -0
  60. package/public/vendor/monaco/vs/basic-languages/cameligo/cameligo.js +10 -0
  61. package/public/vendor/monaco/vs/basic-languages/clojure/clojure.js +10 -0
  62. package/public/vendor/monaco/vs/basic-languages/coffee/coffee.js +10 -0
  63. package/public/vendor/monaco/vs/basic-languages/cpp/cpp.js +10 -0
  64. package/public/vendor/monaco/vs/basic-languages/csharp/csharp.js +10 -0
  65. package/public/vendor/monaco/vs/basic-languages/csp/csp.js +10 -0
  66. package/public/vendor/monaco/vs/basic-languages/css/css.js +12 -0
  67. package/public/vendor/monaco/vs/basic-languages/cypher/cypher.js +10 -0
  68. package/public/vendor/monaco/vs/basic-languages/dart/dart.js +10 -0
  69. package/public/vendor/monaco/vs/basic-languages/dockerfile/dockerfile.js +10 -0
  70. package/public/vendor/monaco/vs/basic-languages/ecl/ecl.js +10 -0
  71. package/public/vendor/monaco/vs/basic-languages/elixir/elixir.js +10 -0
  72. package/public/vendor/monaco/vs/basic-languages/flow9/flow9.js +10 -0
  73. package/public/vendor/monaco/vs/basic-languages/freemarker2/freemarker2.js +12 -0
  74. package/public/vendor/monaco/vs/basic-languages/fsharp/fsharp.js +10 -0
  75. package/public/vendor/monaco/vs/basic-languages/go/go.js +10 -0
  76. package/public/vendor/monaco/vs/basic-languages/graphql/graphql.js +10 -0
  77. package/public/vendor/monaco/vs/basic-languages/handlebars/handlebars.js +10 -0
  78. package/public/vendor/monaco/vs/basic-languages/hcl/hcl.js +10 -0
  79. package/public/vendor/monaco/vs/basic-languages/html/html.js +10 -0
  80. package/public/vendor/monaco/vs/basic-languages/ini/ini.js +10 -0
  81. package/public/vendor/monaco/vs/basic-languages/java/java.js +10 -0
  82. package/public/vendor/monaco/vs/basic-languages/javascript/javascript.js +10 -0
  83. package/public/vendor/monaco/vs/basic-languages/julia/julia.js +10 -0
  84. package/public/vendor/monaco/vs/basic-languages/kotlin/kotlin.js +10 -0
  85. package/public/vendor/monaco/vs/basic-languages/less/less.js +11 -0
  86. package/public/vendor/monaco/vs/basic-languages/lexon/lexon.js +10 -0
  87. package/public/vendor/monaco/vs/basic-languages/liquid/liquid.js +10 -0
  88. package/public/vendor/monaco/vs/basic-languages/lua/lua.js +10 -0
  89. package/public/vendor/monaco/vs/basic-languages/m3/m3.js +10 -0
  90. package/public/vendor/monaco/vs/basic-languages/markdown/markdown.js +10 -0
  91. package/public/vendor/monaco/vs/basic-languages/mdx/mdx.js +10 -0
  92. package/public/vendor/monaco/vs/basic-languages/mips/mips.js +10 -0
  93. package/public/vendor/monaco/vs/basic-languages/msdax/msdax.js +10 -0
  94. package/public/vendor/monaco/vs/basic-languages/mysql/mysql.js +10 -0
  95. package/public/vendor/monaco/vs/basic-languages/objective-c/objective-c.js +10 -0
  96. package/public/vendor/monaco/vs/basic-languages/pascal/pascal.js +10 -0
  97. package/public/vendor/monaco/vs/basic-languages/pascaligo/pascaligo.js +10 -0
  98. package/public/vendor/monaco/vs/basic-languages/perl/perl.js +10 -0
  99. package/public/vendor/monaco/vs/basic-languages/pgsql/pgsql.js +10 -0
  100. package/public/vendor/monaco/vs/basic-languages/php/php.js +10 -0
  101. package/public/vendor/monaco/vs/basic-languages/pla/pla.js +10 -0
  102. package/public/vendor/monaco/vs/basic-languages/postiats/postiats.js +10 -0
  103. package/public/vendor/monaco/vs/basic-languages/powerquery/powerquery.js +10 -0
  104. package/public/vendor/monaco/vs/basic-languages/powershell/powershell.js +10 -0
  105. package/public/vendor/monaco/vs/basic-languages/protobuf/protobuf.js +11 -0
  106. package/public/vendor/monaco/vs/basic-languages/pug/pug.js +10 -0
  107. package/public/vendor/monaco/vs/basic-languages/python/python.js +10 -0
  108. package/public/vendor/monaco/vs/basic-languages/qsharp/qsharp.js +10 -0
  109. package/public/vendor/monaco/vs/basic-languages/r/r.js +10 -0
  110. package/public/vendor/monaco/vs/basic-languages/razor/razor.js +10 -0
  111. package/public/vendor/monaco/vs/basic-languages/redis/redis.js +10 -0
  112. package/public/vendor/monaco/vs/basic-languages/redshift/redshift.js +10 -0
  113. package/public/vendor/monaco/vs/basic-languages/restructuredtext/restructuredtext.js +10 -0
  114. package/public/vendor/monaco/vs/basic-languages/ruby/ruby.js +10 -0
  115. package/public/vendor/monaco/vs/basic-languages/rust/rust.js +10 -0
  116. package/public/vendor/monaco/vs/basic-languages/sb/sb.js +10 -0
  117. package/public/vendor/monaco/vs/basic-languages/scala/scala.js +10 -0
  118. package/public/vendor/monaco/vs/basic-languages/scheme/scheme.js +10 -0
  119. package/public/vendor/monaco/vs/basic-languages/scss/scss.js +12 -0
  120. package/public/vendor/monaco/vs/basic-languages/shell/shell.js +10 -0
  121. package/public/vendor/monaco/vs/basic-languages/solidity/solidity.js +10 -0
  122. package/public/vendor/monaco/vs/basic-languages/sophia/sophia.js +10 -0
  123. package/public/vendor/monaco/vs/basic-languages/sparql/sparql.js +10 -0
  124. package/public/vendor/monaco/vs/basic-languages/sql/sql.js +10 -0
  125. package/public/vendor/monaco/vs/basic-languages/st/st.js +10 -0
  126. package/public/vendor/monaco/vs/basic-languages/swift/swift.js +13 -0
  127. package/public/vendor/monaco/vs/basic-languages/systemverilog/systemverilog.js +10 -0
  128. package/public/vendor/monaco/vs/basic-languages/tcl/tcl.js +10 -0
  129. package/public/vendor/monaco/vs/basic-languages/twig/twig.js +10 -0
  130. package/public/vendor/monaco/vs/basic-languages/typescript/typescript.js +10 -0
  131. package/public/vendor/monaco/vs/basic-languages/typespec/typespec.js +10 -0
  132. package/public/vendor/monaco/vs/basic-languages/vb/vb.js +10 -0
  133. package/public/vendor/monaco/vs/basic-languages/wgsl/wgsl.js +307 -0
  134. package/public/vendor/monaco/vs/basic-languages/xml/xml.js +10 -0
  135. package/public/vendor/monaco/vs/basic-languages/yaml/yaml.js +10 -0
  136. package/public/vendor/monaco/vs/editor/editor.main.css +8 -0
  137. package/public/vendor/monaco/vs/editor/editor.main.js +798 -0
  138. package/public/vendor/monaco/vs/language/css/cssMode.js +13 -0
  139. package/public/vendor/monaco/vs/language/css/cssWorker.js +77 -0
  140. package/public/vendor/monaco/vs/language/html/htmlMode.js +13 -0
  141. package/public/vendor/monaco/vs/language/html/htmlWorker.js +454 -0
  142. package/public/vendor/monaco/vs/language/json/jsonMode.js +19 -0
  143. package/public/vendor/monaco/vs/language/json/jsonWorker.js +42 -0
  144. package/public/vendor/monaco/vs/language/typescript/tsMode.js +20 -0
  145. package/public/vendor/monaco/vs/language/typescript/tsWorker.js +51328 -0
  146. package/public/vendor/monaco/vs/loader.js +11 -0
  147. package/public/vendor/monaco/worker-boot.js +9 -0
  148. package/server/.fuse_hidden0000000800000001 +36 -0
  149. package/server/apiDiff.js +25 -0
  150. package/server/apiDocs.js +67 -0
  151. package/server/apiFile.js +36 -0
  152. package/server/apiGitBlame.js +63 -0
  153. package/server/apiMcp.js +110 -0
  154. package/server/apiScan.js +119 -0
  155. package/server/apiSearch.js +253 -0
  156. package/server/apiSettings.js +118 -0
  157. package/server/apiTools.js +90 -0
  158. package/server/config.js +227 -0
  159. package/server/fileSourceNode.js +44 -0
  160. package/server/gitClone.js +95 -0
  161. package/server/gitDiff.js +184 -0
  162. package/server/gitHistory.js +110 -0
  163. package/server/htmlText.js +44 -0
  164. package/server/http.js +55 -0
  165. package/server/httpGuards.js +87 -0
  166. package/server/index.js +156 -0
  167. package/server/llmProxy.js +162 -0
  168. package/server/logger.js +29 -0
  169. package/server/mcp/analysis.js +209 -0
  170. package/server/mcp/http.js +213 -0
  171. package/server/mcp/runner.js +278 -0
  172. package/server/mcp/server.js +241 -0
  173. package/server/mcp/standalone.js +42 -0
  174. package/server/mcp/tools.js +683 -0
  175. package/server/paths.js +39 -0
  176. package/server/router.js +218 -0
  177. package/server/searchIndex.js +118 -0
  178. package/server/sessions.js +163 -0
  179. package/server/static.js +59 -0
  180. package/server/tools/install.js +246 -0
  181. package/server/tools/parse.js +170 -0
  182. package/server/tools/platform.js +91 -0
  183. package/server/tools/registry.js +212 -0
  184. package/server/tools/scan.js +136 -0
  185. package/server/tools.js +212 -0
  186. package/server/tunnel.js +92 -0
  187. package/shared/analyzer/docs.js +135 -0
  188. package/shared/analyzer/explainLocal.js +163 -0
  189. package/shared/analyzer/graph.js +461 -0
  190. package/shared/analyzer/health.js +215 -0
  191. package/shared/analyzer/history.js +146 -0
  192. package/shared/analyzer/languages/csharp.js +39 -0
  193. package/shared/analyzer/languages/generic.js +131 -0
  194. package/shared/analyzer/languages/go.js +70 -0
  195. package/shared/analyzer/languages/index.js +43 -0
  196. package/shared/analyzer/languages/java.js +39 -0
  197. package/shared/analyzer/languages/javascript.js +240 -0
  198. package/shared/analyzer/languages/python.js +120 -0
  199. package/shared/analyzer/languages/rust.js +42 -0
  200. package/shared/analyzer/languages/typescript.js +138 -0
  201. package/shared/analyzer/licenses.js +151 -0
  202. package/shared/analyzer/metrics.js +120 -0
  203. package/shared/analyzer/pathUtil.js +69 -0
  204. package/shared/analyzer/patterns.js +272 -0
  205. package/shared/analyzer/scan.js +473 -0
  206. package/shared/analyzer/security.js +187 -0
  207. package/shared/analyzer/services.js +157 -0
  208. package/shared/analyzer/stack.js +173 -0
  209. package/shared/analyzer/tour.js +69 -0
  210. package/shared/analyzer/util.js +123 -0
  211. package/shared/analyzer/workflows.js +143 -0
  212. package/shared/diagram/aiFacts.js +145 -0
  213. package/shared/diagram/aiMermaid.js +59 -0
  214. package/shared/diagram/atlas.js +93 -0
  215. package/shared/diagram/mermaid.js +459 -0
  216. package/shared/search/query.js +518 -0
@@ -0,0 +1,2767 @@
1
+ /* Onboarder — paper & ink.
2
+ The look is a printed field guide: warm stock, hairline rules, hard offset
3
+ shadows, serif display type, monospace for anything the machine said. */
4
+
5
+ :root {
6
+ --paper: #f7f4ed;
7
+ --paper-2: #efe9dc;
8
+ --paper-3: #e7dfcd;
9
+ --card: #fffdf7;
10
+ --ink: #2a2721;
11
+ --ink-2: #57503f;
12
+ --faint: #8a8577;
13
+ --line: rgba(42, 39, 33, 0.22);
14
+ --line-strong: #2a2721;
15
+ --accent: #2e5d43;
16
+ --accent-soft: #dce8d8;
17
+ --warn: #a4442a;
18
+ --warn-soft: #f3d4c8;
19
+ --hub: #8a5a1d;
20
+ --hub-soft: #f3e3c8;
21
+ --serif: "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, serif;
22
+ --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
23
+ --mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
24
+ --shadow: 3px 3px 0 rgba(42, 39, 33, 0.9);
25
+ --shadow-sm: 2px 2px 0 rgba(42, 39, 33, 0.85);
26
+ --dot: rgba(42, 39, 33, 0.13);
27
+ --dot-strong: rgba(42, 39, 33, 0.22);
28
+ --canvas-bg: #fbf8f1;
29
+ --canvas-shade: rgba(42, 39, 33, 0.06);
30
+ --scrim: rgba(42, 39, 33, 0.28);
31
+ /* Severity pills — soft wash behind a darker ink. */
32
+ --sev-critical-bg: #fde8e4; --sev-critical-ink: #8f2f1f;
33
+ --sev-high-bg: #fdeee0; --sev-high-ink: #8a4a15;
34
+ --sev-medium-bg: #fdf6dd; --sev-medium-ink: #7a6212;
35
+ --sev-low-bg: #e8f0e9; --sev-low-ink: #35603f;
36
+ --sev-info-bg: var(--paper-2); --sev-info-ink: var(--faint);
37
+ }
38
+
39
+ /* Same field guide, read by lamplight. */
40
+ [data-theme="dark"] {
41
+ --paper: #211e19;
42
+ --paper-2: #292520;
43
+ --paper-3: #333026;
44
+ --card: #2b2721;
45
+ --ink: #ece7db;
46
+ --ink-2: #c9c2b2;
47
+ --faint: #9b9484;
48
+ --line: rgba(236, 231, 219, 0.22);
49
+ --line-strong: #ece7db;
50
+ --accent: #8fbd9f;
51
+ --accent-soft: #243d2c;
52
+ --warn: #d97b5a;
53
+ --warn-soft: #472418;
54
+ --hub: #d9a75f;
55
+ --hub-soft: #463617;
56
+ --shadow: 3px 3px 0 rgba(0, 0, 0, 0.6);
57
+ --shadow-sm: 2px 2px 0 rgba(0, 0, 0, 0.55);
58
+ --dot: rgba(236, 231, 219, 0.1);
59
+ --dot-strong: rgba(236, 231, 219, 0.2);
60
+ --canvas-bg: #181612;
61
+ --canvas-shade: rgba(0, 0, 0, 0.5);
62
+ --scrim: rgba(0, 0, 0, 0.5);
63
+ /* Severity pills — reuse the warn/hub/accent washes so they read on dark stock. */
64
+ --sev-critical-bg: #472418; --sev-critical-ink: #d97b5a;
65
+ --sev-high-bg: #463617; --sev-high-ink: #d9a75f;
66
+ --sev-medium-bg: #3a3416; --sev-medium-ink: #d9c25f;
67
+ --sev-low-bg: #243d2c; --sev-low-ink: #8fbd9f;
68
+ --sev-info-bg: var(--paper-2); --sev-info-ink: var(--faint);
69
+ }
70
+
71
+ * { box-sizing: border-box; }
72
+
73
+ html, body {
74
+ margin: 0;
75
+ height: 100%;
76
+ background: var(--paper);
77
+ color: var(--ink);
78
+ font-family: var(--sans);
79
+ font-size: 15px;
80
+ line-height: 1.45;
81
+ }
82
+
83
+ [hidden] { display: none !important; }
84
+
85
+ ::selection { background: var(--accent-soft); }
86
+
87
+ /* ---------- buttons & inputs ---------- */
88
+
89
+ .btn {
90
+ font-family: var(--mono);
91
+ font-size: 12px;
92
+ letter-spacing: 0.02em;
93
+ padding: 7px 12px;
94
+ border: 1.5px solid var(--ink);
95
+ border-radius: 4px;
96
+ background: var(--card);
97
+ color: var(--ink);
98
+ cursor: pointer;
99
+ transition: transform 0.06s ease, box-shadow 0.06s ease;
100
+ }
101
+ .btn:hover { transform: translate(-1px, -1px); box-shadow: var(--shadow-sm); }
102
+ .btn:active { transform: translate(0, 0); box-shadow: none; }
103
+ .btn:disabled { opacity: 0.45; cursor: default; transform: none; box-shadow: none; }
104
+
105
+ .btn-ink { background: var(--ink); color: var(--paper); }
106
+ .btn-outline { background: transparent; }
107
+ .btn-ghost { border-color: transparent; background: transparent; color: var(--ink-2); }
108
+ .btn-ghost:hover { border-color: var(--ink); color: var(--ink); }
109
+ .btn-sm { padding: 4px 9px; font-size: 11px; }
110
+
111
+ .linklike {
112
+ border: 0;
113
+ background: none;
114
+ padding: 0;
115
+ font: inherit;
116
+ color: var(--accent);
117
+ text-decoration: underline;
118
+ text-underline-offset: 3px;
119
+ cursor: pointer;
120
+ }
121
+
122
+ .text-input {
123
+ font-family: var(--mono);
124
+ font-size: 13px;
125
+ padding: 9px 11px;
126
+ border: 1.5px solid var(--ink);
127
+ border-radius: 4px;
128
+ background: var(--card);
129
+ color: var(--ink);
130
+ width: 100%;
131
+ outline: none;
132
+ }
133
+ .text-input:focus { box-shadow: var(--shadow-sm); }
134
+ .text-input::placeholder { color: var(--faint); }
135
+
136
+ /* ---------- top bar ---------- */
137
+
138
+ .topbar {
139
+ height: 54px;
140
+ display: flex;
141
+ align-items: center;
142
+ gap: 16px;
143
+ padding: 0 18px;
144
+ border-bottom: 1.5px solid var(--ink);
145
+ background: var(--paper);
146
+ overflow-x: auto;
147
+ overflow-y: hidden;
148
+ white-space: nowrap;
149
+ }
150
+
151
+ .brand {
152
+ display: flex;
153
+ align-items: center;
154
+ gap: 10px;
155
+ flex-shrink: 0;
156
+ }
157
+
158
+ .brand-mark {
159
+ font-family: var(--serif);
160
+ font-size: 21px;
161
+ font-weight: 600;
162
+ letter-spacing: -0.01em;
163
+ color: var(--ink);
164
+ }
165
+ .brand-mark::after { content: "."; color: var(--accent); }
166
+
167
+ .brand-note {
168
+ font-family: var(--mono);
169
+ font-size: 11.5px;
170
+ color: var(--faint);
171
+ font-style: normal;
172
+ background: var(--card);
173
+ border: 1px solid var(--line);
174
+ border-radius: 12px;
175
+ padding: 2px 9px;
176
+ letter-spacing: -0.01em;
177
+ white-space: nowrap;
178
+ display: inline-flex;
179
+ align-items: center;
180
+ transition: all 0.15s ease;
181
+ }
182
+
183
+ .views { display: flex; gap: 3px; flex-shrink: 0; }
184
+ .view-tab {
185
+ font-family: var(--mono);
186
+ font-size: 11.5px;
187
+ padding: 5px 11px;
188
+ border: 1.5px solid transparent;
189
+ border-radius: 4px;
190
+ background: none;
191
+ color: var(--ink-2);
192
+ cursor: pointer;
193
+ white-space: nowrap;
194
+ transition: all 0.12s ease;
195
+ }
196
+ .view-tab:hover { color: var(--ink); background: rgba(128,128,128,0.06); }
197
+ .view-tab.is-active {
198
+ border-color: var(--ink);
199
+ background: var(--card);
200
+ color: var(--ink);
201
+ box-shadow: var(--shadow-sm);
202
+ font-weight: 600;
203
+ }
204
+
205
+ .topbar-right { margin-left: auto; display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
206
+ .repo-chip {
207
+ display: flex;
208
+ flex-direction: column;
209
+ align-items: flex-end;
210
+ line-height: 1.2;
211
+ border: 1px dashed var(--line);
212
+ border-radius: 4px;
213
+ padding: 3px 9px;
214
+ max-width: 280px;
215
+ overflow: hidden;
216
+ background: var(--card);
217
+ }
218
+ .repo-name {
219
+ font-family: var(--mono);
220
+ font-size: 12.5px;
221
+ font-weight: 600;
222
+ color: var(--ink);
223
+ max-width: 260px;
224
+ overflow: hidden;
225
+ text-overflow: ellipsis;
226
+ white-space: nowrap;
227
+ }
228
+ .repo-sub {
229
+ font-family: var(--mono);
230
+ font-size: 10px;
231
+ color: var(--faint);
232
+ max-width: 260px;
233
+ overflow: hidden;
234
+ text-overflow: ellipsis;
235
+ white-space: nowrap;
236
+ }
237
+
238
+ .btn-search-trigger {
239
+ display: inline-flex;
240
+ align-items: center;
241
+ gap: 6px;
242
+ padding: 5px 9px;
243
+ font-family: var(--mono);
244
+ font-size: 11.5px;
245
+ border-radius: 4px;
246
+ }
247
+ .search-trigger-label { letter-spacing: 0.01em; }
248
+ .search-key-hint {
249
+ font-size: 10px;
250
+ padding: 1px 5px;
251
+ background: var(--paper-2);
252
+ border: 1px solid var(--line);
253
+ border-radius: 3px;
254
+ color: var(--faint);
255
+ }
256
+
257
+ /* ---------- landing ---------- */
258
+
259
+ .landing {
260
+ min-height: calc(100vh - 54px);
261
+ display: flex;
262
+ flex-direction: column;
263
+ }
264
+
265
+ .landing-inner {
266
+ width: min(920px, 92vw);
267
+ margin: 7vh auto 0;
268
+ }
269
+
270
+ .landing-title {
271
+ font-family: var(--serif);
272
+ font-size: clamp(38px, 5.4vw, 58px);
273
+ line-height: 1.04;
274
+ letter-spacing: -0.015em;
275
+ margin: 0 0 18px;
276
+ }
277
+
278
+ .landing-sub {
279
+ max-width: 620px;
280
+ font-size: 16px;
281
+ color: var(--ink-2);
282
+ margin: 0 0 40px;
283
+ }
284
+
285
+ .load-grid {
286
+ display: grid;
287
+ grid-template-columns: repeat(3, 1fr);
288
+ gap: 16px;
289
+ }
290
+
291
+ .load-card {
292
+ background: var(--card);
293
+ border: 1.5px solid var(--ink);
294
+ border-radius: 6px;
295
+ padding: 18px;
296
+ box-shadow: var(--shadow);
297
+ display: flex;
298
+ flex-direction: column;
299
+ gap: 8px;
300
+ }
301
+
302
+ .load-card-title {
303
+ font-family: var(--serif);
304
+ font-size: 19px;
305
+ margin: 0;
306
+ }
307
+
308
+ .load-card-note { font-size: 12.5px; color: var(--faint); margin: 0 0 6px; }
309
+
310
+ .load-form { display: flex; flex-direction: column; gap: 8px; margin-top: auto; }
311
+ #pickCard .btn { margin-top: auto; }
312
+
313
+ .landing-alt { margin-top: 34px; font-size: 14px; color: var(--ink-2); }
314
+
315
+ .landing-error {
316
+ margin-top: 18px;
317
+ font-family: var(--mono);
318
+ font-size: 12.5px;
319
+ color: var(--warn);
320
+ border: 1.5px solid var(--warn);
321
+ background: var(--warn-soft);
322
+ border-radius: 4px;
323
+ padding: 10px 12px;
324
+ }
325
+
326
+ .landing-status {
327
+ margin-top: 18px;
328
+ font-family: var(--mono);
329
+ font-size: 12.5px;
330
+ color: var(--ink-2);
331
+ }
332
+ .landing-status::before {
333
+ content: "";
334
+ display: inline-block;
335
+ width: 8px; height: 8px;
336
+ margin-right: 8px;
337
+ border-radius: 50%;
338
+ background: var(--accent);
339
+ animation: pulse 0.9s ease-in-out infinite alternate;
340
+ }
341
+ @keyframes pulse { from { opacity: 0.25; } to { opacity: 1; } }
342
+
343
+ .landing-foot {
344
+ margin-top: auto;
345
+ padding: 22px 4vw 26px;
346
+ display: flex;
347
+ gap: 28px;
348
+ justify-content: center;
349
+ font-size: 12.5px;
350
+ color: var(--faint);
351
+ font-family: var(--serif);
352
+ font-style: italic;
353
+ }
354
+ /* ---------- explorer layout ---------- */
355
+
356
+ .explorer {
357
+ height: calc(100vh - 54px);
358
+ display: grid;
359
+ grid-template-columns: 250px 1fr 330px;
360
+ }
361
+
362
+ .sidebar {
363
+ border-right: 1.5px solid var(--ink);
364
+ display: flex;
365
+ flex-direction: column;
366
+ min-height: 0;
367
+ background: var(--paper-2);
368
+ }
369
+
370
+ .sidebar-head { padding: 10px; border-bottom: 1px solid var(--line); }
371
+
372
+ .tree-filter {
373
+ width: 100%;
374
+ font-family: var(--mono);
375
+ font-size: 12px;
376
+ padding: 6px 9px;
377
+ border: 1px solid var(--line);
378
+ border-radius: 4px;
379
+ background: var(--card);
380
+ color: var(--ink);
381
+ outline: none;
382
+ }
383
+ .tree-filter:focus { border-color: var(--ink); }
384
+
385
+ .tree {
386
+ overflow: auto;
387
+ padding: 8px 6px 30px;
388
+ font-family: var(--mono);
389
+ font-size: 12px;
390
+ user-select: none;
391
+ }
392
+
393
+ .tree-dir { margin: 1px 0; }
394
+ .tree-dir-head {
395
+ display: flex;
396
+ align-items: center;
397
+ gap: 5px;
398
+ padding: 2.5px 6px;
399
+ border-radius: 3px;
400
+ color: var(--ink-2);
401
+ cursor: pointer;
402
+ white-space: nowrap;
403
+ }
404
+ .tree-dir-head:hover { background: var(--paper-3); color: var(--ink); }
405
+ .tree-caret { display: inline-block; width: 12px; transition: transform 0.1s ease; color: var(--faint); }
406
+ .tree-dir.is-open > .tree-dir-head .tree-caret { transform: rotate(90deg); }
407
+ .tree-count {
408
+ font-size: 10px;
409
+ color: var(--faint);
410
+ background: var(--paper);
411
+ border: 1px solid var(--line);
412
+ border-radius: 10px;
413
+ padding: 0 5px;
414
+ margin-left: auto;
415
+ line-height: 1.4;
416
+ }
417
+ .tree-children { margin-left: 13px; border-left: 1px dotted var(--line); padding-left: 6px; display: none; }
418
+ .tree-dir.is-open > .tree-children { display: block; }
419
+
420
+ .tree-file {
421
+ display: flex;
422
+ align-items: center;
423
+ gap: 6px;
424
+ padding: 2.5px 6px;
425
+ border-radius: 3px;
426
+ cursor: pointer;
427
+ white-space: nowrap;
428
+ color: var(--ink);
429
+ transition: all 0.08s ease;
430
+ }
431
+ .tree-file:hover { background: var(--paper-3); }
432
+ .tree-file.is-selected {
433
+ background: var(--accent-soft);
434
+ outline: 1px solid var(--accent);
435
+ font-weight: 600;
436
+ }
437
+ .tree-dot {
438
+ display: inline-block;
439
+ width: 6.5px;
440
+ height: 6.5px;
441
+ border-radius: 50%;
442
+ flex-shrink: 0;
443
+ }
444
+ .tree-badge {
445
+ margin-left: auto;
446
+ font-size: 10px;
447
+ color: var(--faint);
448
+ border: 1px solid var(--line);
449
+ border-radius: 3px;
450
+ padding: 0 4px;
451
+ }
452
+ .tree-badge.is-entry { color: var(--accent); border-color: var(--accent); font-weight: 600; }
453
+ .tree-badge.is-hub { color: var(--hub); border-color: var(--hub); font-weight: 600; }
454
+
455
+ /* ---------- stage ---------- */
456
+
457
+ .stage { display: flex; flex-direction: column; min-width: 0; min-height: 0; }
458
+
459
+ .stage-head {
460
+ display: flex;
461
+ align-items: center;
462
+ gap: 12px;
463
+ padding: 8px 14px;
464
+ border-bottom: 1px solid var(--line);
465
+ }
466
+
467
+ .crumbs {
468
+ font-family: var(--mono);
469
+ font-size: 12px;
470
+ color: var(--faint);
471
+ overflow: hidden;
472
+ text-overflow: ellipsis;
473
+ white-space: nowrap;
474
+ }
475
+ .crumbs button {
476
+ border: 0;
477
+ background: none;
478
+ padding: 0;
479
+ font: inherit;
480
+ color: var(--accent);
481
+ cursor: pointer;
482
+ }
483
+ .crumbs button:hover { text-decoration: underline; }
484
+ .crumbs .sep { margin: 0 5px; color: var(--line); }
485
+
486
+ .stage-actions { margin-left: auto; display: flex; gap: 6px; align-items: center; }
487
+
488
+ /* ---------- explorer filter row ---------- */
489
+
490
+ .stage-filters {
491
+ display: flex;
492
+ align-items: center;
493
+ gap: 10px;
494
+ padding: 7px 14px;
495
+ border-bottom: 1px solid var(--line);
496
+ background: var(--paper-2);
497
+ }
498
+
499
+ .mode-switch { display: flex; gap: 2px; }
500
+ .mode-chip {
501
+ font-family: var(--mono);
502
+ font-size: 11.5px;
503
+ padding: 4px 11px;
504
+ border: 1.5px solid transparent;
505
+ border-radius: 4px;
506
+ background: none;
507
+ color: var(--ink-2);
508
+ cursor: pointer;
509
+ }
510
+ .mode-chip:hover { color: var(--ink); }
511
+ .mode-chip.is-active {
512
+ border-color: var(--ink);
513
+ background: var(--card);
514
+ color: var(--ink);
515
+ box-shadow: var(--shadow-sm);
516
+ }
517
+
518
+ .node-filter {
519
+ font-family: var(--mono);
520
+ font-size: 11.5px;
521
+ width: 190px;
522
+ padding: 5px 9px;
523
+ border: 1px solid var(--line);
524
+ border-radius: 4px;
525
+ background: var(--card);
526
+ color: var(--ink);
527
+ outline: none;
528
+ }
529
+ .node-filter:focus { border-color: var(--ink); }
530
+
531
+ .chip-toggle {
532
+ font-family: var(--mono);
533
+ font-size: 11px;
534
+ padding: 4px 10px;
535
+ border: 1.5px solid var(--line);
536
+ border-radius: 20px;
537
+ background: none;
538
+ color: var(--faint);
539
+ cursor: pointer;
540
+ }
541
+ .chip-toggle.is-on {
542
+ border-color: var(--accent);
543
+ color: var(--accent);
544
+ background: var(--accent-soft);
545
+ }
546
+
547
+ .depth-select {
548
+ font-family: var(--mono);
549
+ font-size: 11.5px;
550
+ padding: 4px 7px;
551
+ border: 1px solid var(--line);
552
+ border-radius: 4px;
553
+ background: var(--card);
554
+ color: var(--ink-2);
555
+ outline: none;
556
+ }
557
+
558
+ /* ---------- atlas mode ---------- */
559
+
560
+ .atlas-list {
561
+ overflow-y: auto;
562
+ padding: 22px 26px 40px;
563
+ background: var(--paper);
564
+ }
565
+
566
+ .atlas-head {
567
+ font-family: var(--serif);
568
+ font-style: italic;
569
+ color: var(--faint);
570
+ font-size: 14px;
571
+ margin: 0 0 16px;
572
+ }
573
+
574
+ .atlas-grid {
575
+ display: grid;
576
+ grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
577
+ gap: 12px;
578
+ }
579
+
580
+ .atlas-card {
581
+ background: var(--card);
582
+ border: 1.5px solid var(--ink);
583
+ border-radius: 6px;
584
+ box-shadow: var(--shadow-sm);
585
+ padding: 10px 13px;
586
+ cursor: pointer;
587
+ transition: transform 0.06s ease, box-shadow 0.06s ease;
588
+ min-width: 0;
589
+ }
590
+ .atlas-card:hover { transform: translate(-1px, -1px); box-shadow: var(--shadow); }
591
+
592
+ .atlas-card-top {
593
+ display: flex;
594
+ align-items: center;
595
+ gap: 8px;
596
+ margin-bottom: 3px;
597
+ }
598
+ .atlas-kind {
599
+ font-family: var(--mono);
600
+ font-size: 9.5px;
601
+ text-transform: uppercase;
602
+ letter-spacing: 0.07em;
603
+ border: 1px solid var(--line);
604
+ border-radius: 3px;
605
+ padding: 1px 6px;
606
+ color: var(--faint);
607
+ flex-shrink: 0;
608
+ }
609
+ .atlas-kind.is-overview, .atlas-kind.is-layers { border-color: var(--accent); color: var(--accent); }
610
+ .atlas-kind.is-file { border-color: var(--hub); color: var(--hub); }
611
+
612
+ .atlas-title {
613
+ font-family: var(--mono);
614
+ font-size: 12px;
615
+ font-weight: 600;
616
+ color: var(--ink);
617
+ white-space: nowrap;
618
+ overflow: hidden;
619
+ text-overflow: ellipsis;
620
+ }
621
+ .atlas-sub {
622
+ font-family: var(--mono);
623
+ font-size: 10.5px;
624
+ color: var(--faint);
625
+ margin-top: 2px;
626
+ }
627
+
628
+ .canvas {
629
+ position: relative;
630
+ flex: 1;
631
+ min-height: 0;
632
+ overflow: hidden;
633
+ /* Two dot scales: a fine grid for everyday steering and a sparser major
634
+ grid giving reference points, so panning feels like a seamless,
635
+ bounded-less drawing surface. */
636
+ background-color: var(--canvas-bg);
637
+ background-image:
638
+ radial-gradient(var(--dot) 1.1px, transparent 1.3px),
639
+ radial-gradient(var(--dot-strong) 1.5px, transparent 1.9px);
640
+ background-size: 22px 22px, 110px 110px;
641
+ background-position: 0 0, 0 0;
642
+ cursor: grab;
643
+ }
644
+ .canvas.is-dragging { cursor: grabbing; }
645
+ .canvas::after {
646
+ content: '';
647
+ position: absolute;
648
+ inset: 0;
649
+ pointer-events: none;
650
+ background: radial-gradient(125% 95% at 50% 42%, transparent 62%, var(--canvas-shade) 100%);
651
+ }
652
+
653
+ .canvas-content {
654
+ position: absolute;
655
+ top: 0; left: 0;
656
+ z-index: 1; /* above the vignette, so the fade only touches empty canvas */
657
+ transform-origin: 0 0;
658
+ padding: 26px;
659
+ }
660
+ .canvas-content svg { display: block; max-width: none; }
661
+
662
+ .canvas-empty {
663
+ position: absolute;
664
+ inset: 0;
665
+ display: flex;
666
+ align-items: center;
667
+ justify-content: center;
668
+ color: var(--faint);
669
+ font-family: var(--serif);
670
+ font-style: italic;
671
+ font-size: 17px;
672
+ pointer-events: none;
673
+ }
674
+
675
+ /* ---------- stage foot ---------- */
676
+
677
+ .stage-foot {
678
+ border-top: 1px solid var(--line);
679
+ padding: 7px 14px;
680
+ font-family: var(--mono);
681
+ font-size: 11.5px;
682
+ color: var(--faint);
683
+ display: flex;
684
+ align-items: center;
685
+ flex-wrap: wrap;
686
+ gap: 6px 14px;
687
+ overflow: hidden;
688
+ line-height: 1.5;
689
+ }
690
+ .stage-foot b { color: var(--ink-2); font-weight: 600; }
691
+ .stage-foot .warn { color: var(--warn); }
692
+ .stage-foot .foot-stats { white-space: nowrap; }
693
+ .stage-foot .foot-right {
694
+ margin-left: auto;
695
+ display: inline-flex;
696
+ align-items: center;
697
+ gap: 12px;
698
+ white-space: nowrap;
699
+ }
700
+ .stage-foot .langs {
701
+ max-width: 28vw;
702
+ overflow: hidden;
703
+ text-overflow: ellipsis;
704
+ white-space: nowrap;
705
+ }
706
+ .stage-foot .ai-cap {
707
+ color: var(--accent);
708
+ font-family: var(--serif);
709
+ font-style: italic;
710
+ max-width: 24vw;
711
+ overflow: hidden;
712
+ text-overflow: ellipsis;
713
+ white-space: nowrap;
714
+ }
715
+ /* ---------- inspector ---------- */
716
+
717
+ .inspector {
718
+ border-left: 1.5px solid var(--ink);
719
+ background: var(--card);
720
+ overflow-y: auto;
721
+ padding: 18px;
722
+ }
723
+
724
+ .inspector-empty {
725
+ height: 100%;
726
+ display: flex;
727
+ align-items: center;
728
+ justify-content: center;
729
+ text-align: center;
730
+ }
731
+ .insp-back {
732
+ margin-left: auto;
733
+ align-self: flex-start;
734
+ font-family: var(--mono);
735
+ font-size: 11px;
736
+ color: var(--accent);
737
+ background: none;
738
+ border: none;
739
+ cursor: pointer;
740
+ padding: 2px 4px;
741
+ border-radius: 4px;
742
+ white-space: nowrap;
743
+ }
744
+ .insp-back:hover { background: var(--accent-soft); text-decoration: underline; }
745
+
746
+ /* score breakdown + metric legend (health / security panels) */
747
+ .score-bd {
748
+ border: 1px solid var(--line);
749
+ border-radius: 6px;
750
+ background: var(--paper-2);
751
+ padding: 8px 12px;
752
+ margin: 10px 0;
753
+ }
754
+ .score-bd h4 {
755
+ font-family: var(--mono);
756
+ font-size: 11px;
757
+ letter-spacing: 0.04em;
758
+ text-transform: uppercase;
759
+ color: var(--faint);
760
+ margin: 0 0 6px;
761
+ }
762
+ .score-bd ul { list-style: none; margin: 0; padding: 0; }
763
+ .score-bd li {
764
+ display: flex;
765
+ justify-content: space-between;
766
+ gap: 10px;
767
+ font-size: 12px;
768
+ padding: 2px 0;
769
+ color: var(--ink-2);
770
+ }
771
+ .score-bd li b { color: var(--warn); font-family: var(--mono); }
772
+ .score-bd ul.legend li { display: block; padding: 2px 0; }
773
+ .sev-critical { color: var(--warn); font-weight: 600; }
774
+ .sev-high { color: var(--hub); font-weight: 600; }
775
+ .sev-medium { color: var(--ink-2); }
776
+ .sev-low { color: var(--faint); }
777
+
778
+ .inspector-empty-line {
779
+ font-family: var(--serif);
780
+ font-style: italic;
781
+ color: var(--faint);
782
+ font-size: 16px;
783
+ line-height: 1.6;
784
+ }
785
+
786
+ .inspector-head { display: flex; align-items: center; gap: 10px; }
787
+ .inspector-title {
788
+ font-family: var(--serif);
789
+ font-size: 21px;
790
+ margin: 0;
791
+ word-break: break-all;
792
+ }
793
+ .role-chip {
794
+ font-family: var(--mono);
795
+ font-size: 10.5px;
796
+ text-transform: uppercase;
797
+ letter-spacing: 0.06em;
798
+ border: 1.5px solid var(--ink);
799
+ border-radius: 3px;
800
+ padding: 2px 7px;
801
+ flex-shrink: 0;
802
+ }
803
+ .role-chip.is-entry { border-color: var(--accent); color: var(--accent); background: var(--accent-soft); }
804
+ .role-chip.is-hub { border-color: var(--hub); color: var(--hub); background: var(--hub-soft); }
805
+ .role-chip.is-test, .role-chip.is-config { border-color: var(--faint); color: var(--faint); }
806
+
807
+ .inspector-path {
808
+ font-family: var(--mono);
809
+ font-size: 11.5px;
810
+ color: var(--faint);
811
+ margin: 6px 0 12px;
812
+ word-break: break-all;
813
+ }
814
+
815
+ .inspector-stats { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 14px; }
816
+ .stat-chip {
817
+ font-family: var(--mono);
818
+ font-size: 11px;
819
+ border: 1px solid var(--line);
820
+ border-radius: 3px;
821
+ padding: 3px 8px;
822
+ color: var(--ink-2);
823
+ }
824
+ .stat-chip b { color: var(--ink); }
825
+
826
+ .inspector-section { border-top: 1px solid var(--line); padding-top: 12px; margin-top: 12px; }
827
+ #inspSecurityTools:empty { border: none; padding: 0; margin: 0; }
828
+
829
+ /* Deep-analysis panel — the external engines (semgrep, gitleaks, knip…). */
830
+ .tools-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 8px; }
831
+ .tools-head h4 { margin: 0; font-family: var(--mono); font-size: 11px; text-transform: uppercase; letter-spacing: 0.07em; color: var(--ink); }
832
+ .tools-sub { color: var(--faint); text-transform: none; letter-spacing: 0; font-weight: 400; }
833
+ .tools-run { font-size: 11px; padding: 4px 9px; }
834
+ .tools-note { font-size: 12px; color: var(--faint); font-style: italic; line-height: 1.5; }
835
+ .tools-err { font-size: 12px; color: var(--warn); margin-bottom: 8px; }
836
+ .tools-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
837
+ .tools-item { border: 1px solid var(--line); border-radius: 6px; padding: 7px 9px; background: var(--card); }
838
+ .tools-item.is-missing { opacity: 0.75; border-style: dashed; }
839
+ .tools-item-main { display: flex; align-items: baseline; gap: 7px; flex-wrap: wrap; }
840
+ .tools-name { font-family: var(--mono); font-weight: 700; font-size: 12px; color: var(--ink); }
841
+ .tools-purpose { font-size: 11px; color: var(--faint); flex: 1; min-width: 120px; }
842
+ .tools-badge { font-family: var(--mono); font-size: 9.5px; padding: 1px 6px; border-radius: 3px; border: 1px solid var(--line); flex-shrink: 0; }
843
+ .tools-badge.is-ready { color: var(--accent); border-color: var(--accent); }
844
+ .tools-badge.is-ran { color: var(--ink); background: var(--accent-soft); border-color: var(--accent); }
845
+ .tools-badge.is-running { color: var(--faint); }
846
+ .tools-badge.is-failed { color: var(--warn); border-color: var(--warn); }
847
+ .tools-badge.is-missing { color: var(--faint); }
848
+ .tools-reason { display: block; font-size: 10.5px; color: var(--faint); margin-top: 4px; font-family: var(--mono); }
849
+ .tools-summary { font-size: 11.5px; color: var(--ink-2); margin-top: 10px; padding: 8px 10px; background: var(--paper-2); border-radius: 6px; border-left: 2px solid var(--accent); }
850
+ .tools-more { font-size: 11px; color: var(--faint); margin-top: 8px; }
851
+ .tools-summary.is-none { border-left-color: var(--faint); }
852
+ .tools-summary.is-clean { border-left-color: var(--accent); }
853
+ .tools-summary.is-found { border-left-color: var(--warn); }
854
+
855
+ /* Engine Configure panels and the install console (Deep Analysis view). */
856
+ .analysis-config { margin-top: 6px; }
857
+ .analysis-config summary {
858
+ font-family: var(--mono); font-size: 10.5px; color: var(--faint);
859
+ cursor: pointer; user-select: none; width: fit-content;
860
+ }
861
+ .analysis-config summary:hover { color: var(--ink); }
862
+ .analysis-config-body {
863
+ display: flex; flex-direction: column; gap: 10px;
864
+ margin-top: 8px; padding: 10px 12px;
865
+ border: 1px solid var(--line); border-radius: 6px; background: var(--card);
866
+ }
867
+ .analysis-opt { display: flex; flex-direction: column; gap: 3px; }
868
+ .analysis-opt-field { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--ink-2); flex-wrap: wrap; }
869
+ .analysis-opt-field > span { min-width: 150px; }
870
+ .analysis-opt-field .text-input { font-size: 12px; padding: 4px 7px; max-width: 220px; }
871
+ .analysis-opt-check { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--ink-2); cursor: pointer; }
872
+ .analysis-opt-multi { display: flex; gap: 12px; flex-wrap: wrap; }
873
+ .analysis-opt-hint { font-size: 10.5px; color: var(--faint); font-style: italic; }
874
+ .analysis-console-wrap { margin-top: 8px; }
875
+ .analysis-console {
876
+ margin: 0; padding: 10px 12px; max-height: 220px; overflow: auto;
877
+ font-family: var(--mono); font-size: 11px; line-height: 1.5;
878
+ background: var(--paper-2); border: 1px solid var(--line); border-radius: 6px;
879
+ color: var(--ink-2); white-space: pre-wrap; word-break: break-word;
880
+ }
881
+ .analysis-console-verdict { font-size: 11.5px; margin-top: 6px; font-family: var(--mono); }
882
+ .analysis-console-verdict.is-ok { color: var(--accent); }
883
+ .analysis-console-verdict.is-err { color: var(--warn); }
884
+
885
+ /* ================= Deep Analysis view ================= */
886
+ /* Same frame as the Insights and SBOM views — 1040px, the same 24px/20px
887
+ padding, and a flex column so the vertical rhythm comes from `gap` rather
888
+ than a margin on each block that someone will forget to match. */
889
+ .analysis-layout { max-width: 1040px; margin: 0 auto; padding: 24px 20px 60px; display: flex; flex-direction: column; gap: 24px; }
890
+ .analysis-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 12px 18px; flex-wrap: wrap; }
891
+ .analysis-head-text { flex: 1 1 340px; min-width: 0; }
892
+ .analysis-title { font-family: var(--serif, Georgia, serif); font-size: 26px; margin: 0 0 4px; color: var(--ink); letter-spacing: -0.01em; }
893
+ .analysis-sub { margin: 0; font-size: 12.5px; color: var(--faint); max-width: 58ch; line-height: 1.5; }
894
+ .analysis-actions { flex: 0 0 auto; display: flex; gap: 7px; align-items: center; flex-wrap: wrap; }
895
+ .analysis-stats { display: flex; gap: 7px; flex-wrap: wrap; margin: 0; }
896
+ .analysis-chip { font-family: var(--mono); font-size: 10.5px; padding: 3px 8px; border: 1px solid var(--line); border-radius: 4px; background: var(--card); color: var(--faint); }
897
+ .analysis-chip b { color: var(--ink); }
898
+ .analysis-chip.is-critical { border-color: var(--warn); color: var(--warn); }
899
+ .analysis-chip.is-critical b { color: var(--warn); }
900
+ .analysis-chip.is-high { border-color: var(--hub); }
901
+ .analysis-chip.is-external { border-color: var(--accent); color: var(--accent); }
902
+ .analysis-chip.is-external b { color: var(--accent); }
903
+
904
+ .analysis-block { margin: 0; }
905
+ .analysis-h { font-family: var(--mono); font-size: 11px; text-transform: uppercase; letter-spacing: 0.08em; color: var(--ink); margin: 0 0 10px; padding-bottom: 6px; border-bottom: 1px solid var(--line); }
906
+ .analysis-h-sub { text-transform: none; letter-spacing: 0; color: var(--faint); font-weight: 400; margin-left: 6px; }
907
+ .analysis-empty { font-size: 12.5px; color: var(--faint); font-style: italic; line-height: 1.6; padding: 12px 14px; border: 1px dashed var(--line); border-radius: 8px; background: var(--card); max-width: 76ch; }
908
+
909
+ .analysis-engines { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 10px; }
910
+ .analysis-engine { border: 1.5px solid var(--ink); border-radius: 8px; padding: 10px 12px; background: var(--card); box-shadow: var(--shadow-sm); }
911
+ .analysis-engine.is-missing { border-style: dashed; border-color: var(--line); opacity: 0.8; }
912
+ .analysis-engine-top { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
913
+ .analysis-engine-kind { font-family: var(--mono); font-size: 9.5px; color: var(--faint); text-transform: uppercase; letter-spacing: 0.05em; margin-left: auto; }
914
+ .analysis-verdict { font-size: 12px; margin-top: 12px; padding: 9px 12px; border-radius: 6px; background: var(--paper-2); border-left: 3px solid var(--faint); color: var(--ink-2); }
915
+ .analysis-verdict.is-found { border-left-color: var(--warn); }
916
+ .analysis-verdict.is-clean { border-left-color: var(--accent); }
917
+ .analysis-verdict.is-none { border-left-color: var(--warn); }
918
+
919
+ .analysis-ai { border: 1.5px solid var(--ink); border-radius: 8px; background: var(--card); box-shadow: var(--shadow-sm); padding: 12px 14px; }
920
+ .analysis-ai-bar { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }
921
+ .analysis-ai-hint { font-size: 11px; color: var(--faint); }
922
+ .analysis-ai-note { margin-top: 11px; font-size: 13.5px; line-height: 1.62; color: var(--ink); min-height: 20px; }
923
+ .analysis-ai-note p { margin: 0 0 9px; }
924
+ .analysis-ai-note code { font-family: var(--mono); font-size: 12px; background: var(--paper-2); border-radius: 3px; padding: 0 3px; }
925
+ .analysis-ai-idle, .analysis-ai-waiting { color: var(--faint); font-style: italic; font-size: 12.5px; }
926
+ .analysis-ai-error { color: var(--warn); font-size: 12.5px; }
927
+ .analysis-ai-cursor { animation: analysisBlink 1s steps(2, start) infinite; }
928
+ @keyframes analysisBlink { to { visibility: hidden; } }
929
+ .analysis-ai-ask { display: flex; gap: 7px; margin-top: 11px; }
930
+ .analysis-ai-ask .text-input { flex: 1; }
931
+
932
+ .analysis-filterbar { display: flex; flex-direction: column; gap: 8px; margin-bottom: 12px; }
933
+ .analysis-filter-group { display: flex; gap: 5px; flex-wrap: wrap; }
934
+ .analysis-filter-group .btn.is-active { background: var(--accent-soft); border-color: var(--accent); color: var(--ink); font-weight: 600; }
935
+ .analysis-search { max-width: 100%; font-size: 12.5px; }
936
+ .analysis-table-wrap { border: 1.5px solid var(--ink); border-radius: 8px; overflow-x: auto; background: var(--card); box-shadow: var(--shadow-sm); }
937
+ .analysis-table { width: 100%; min-width: 680px; border-collapse: collapse; font-size: 12.5px; }
938
+ .analysis-table thead th { text-align: left; font-family: var(--mono); font-size: 9.5px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--faint); padding: 8px 10px; background: var(--paper-2); border-bottom: 1px solid var(--line); font-weight: 600; }
939
+ .analysis-table tbody td { padding: 8px 10px; border-bottom: 1px solid var(--line); vertical-align: top; }
940
+ .analysis-table tbody tr:last-child td { border-bottom: none; }
941
+ .analysis-table tbody tr:hover { background: var(--paper-2); }
942
+ .analysis-table .col-sev { width: 82px; }
943
+ .analysis-table .col-file { width: 210px; }
944
+ .analysis-table .col-rule { width: 168px; }
945
+ .analysis-table .col-tool { width: 88px; }
946
+ .analysis-table .analysis-msg { color: var(--ink-2); line-height: 1.5; }
947
+ .analysis-table code { font-family: var(--mono); font-size: 10.5px; color: var(--ink-2); word-break: break-all; }
948
+ .sev-pill { display: inline-block; font-family: var(--mono); font-size: 9.5px; font-weight: 700; padding: 2px 6px; border-radius: 3px; text-transform: uppercase; }
949
+ .sev-pill.is-critical { background: var(--sev-critical-bg); color: var(--sev-critical-ink); }
950
+ .sev-pill.is-high { background: var(--sev-high-bg); color: var(--sev-high-ink); }
951
+ .sev-pill.is-medium { background: var(--sev-medium-bg); color: var(--sev-medium-ink); }
952
+ .sev-pill.is-low { background: var(--sev-low-bg); color: var(--sev-low-ink); }
953
+ .sev-pill.is-info { background: var(--sev-info-bg); color: var(--sev-info-ink); }
954
+ .analysis-file { display: block; background: none; border: none; padding: 0; cursor: pointer; text-align: left; font-family: var(--mono); }
955
+ .analysis-file:hover .analysis-file-name { text-decoration: underline; }
956
+ .analysis-file-name { font-size: 11.5px; color: var(--accent); font-weight: 600; }
957
+ .analysis-file-line { font-size: 10px; color: var(--faint); margin-left: 5px; }
958
+ .analysis-file-dir { display: block; font-family: var(--mono); font-size: 10px; color: var(--faint); margin-top: 2px; word-break: break-all; }
959
+ .analysis-tool { font-family: var(--mono); font-size: 9.5px; padding: 1px 5px; border-radius: 3px; border: 1px solid var(--line); white-space: nowrap; }
960
+ .analysis-tool.is-external { border-color: var(--accent); color: var(--accent); }
961
+ .analysis-tool.is-builtin { color: var(--faint); }
962
+ .analysis-no-rows { text-align: center; color: var(--faint); font-style: italic; padding: 22px; }
963
+ .inspector-h {
964
+ font-family: var(--mono);
965
+ font-size: 11px;
966
+ text-transform: uppercase;
967
+ letter-spacing: 0.08em;
968
+ color: var(--faint);
969
+ margin: 0 0 8px;
970
+ }
971
+
972
+ .explain { font-size: 13.5px; color: var(--ink); }
973
+ .explain p { margin: 0 0 9px; }
974
+ .explain code {
975
+ font-family: var(--mono);
976
+ font-size: 12px;
977
+ background: var(--paper-2);
978
+ border: 1px solid var(--line);
979
+ border-radius: 3px;
980
+ padding: 0 4px;
981
+ }
982
+ .explain .caret {
983
+ display: inline-block;
984
+ width: 7px; height: 14px;
985
+ background: var(--accent);
986
+ vertical-align: -2px;
987
+ animation: pulse 0.7s steps(2) infinite;
988
+ }
989
+ .explain-src { font-size: 11px; color: var(--faint); font-style: italic; margin-top: 4px; }
990
+
991
+ .ask-row { display: flex; gap: 6px; margin-top: 10px; }
992
+ .ask-input {
993
+ flex: 1;
994
+ min-width: 0;
995
+ font-size: 12px;
996
+ padding: 6px 9px;
997
+ }
998
+ .ask-auto {
999
+ display: inline-block;
1000
+ margin-top: 8px;
1001
+ font-size: 12.5px;
1002
+ }
1003
+ .ask-q {
1004
+ font-family: var(--serif);
1005
+ font-style: italic;
1006
+ color: var(--ink-2);
1007
+ border-left: 3px solid var(--accent);
1008
+ padding-left: 9px;
1009
+ margin-bottom: 10px !important;
1010
+ }
1011
+
1012
+ .link-list { list-style: none; margin: 0 0 10px; padding: 0; font-family: var(--mono); font-size: 12px; }
1013
+ .link-list li { padding: 2px 0; }
1014
+ .link-list button {
1015
+ border: 0; background: none; padding: 0;
1016
+ font: inherit; color: var(--accent); cursor: pointer;
1017
+ word-break: break-all; text-align: left;
1018
+ }
1019
+
1020
+ @layer components {
1021
+ @property --risk-hue {
1022
+ syntax: '<number>';
1023
+ inherits: false;
1024
+ initial-value: 120;
1025
+ }
1026
+
1027
+ .graph-canvas {
1028
+ width: 100%;
1029
+ height: 100%;
1030
+ display: block;
1031
+ }
1032
+
1033
+ .graph-controls {
1034
+ position: absolute;
1035
+ bottom: 20px;
1036
+ right: 20px;
1037
+ display: flex;
1038
+ align-items: center;
1039
+ gap: 6px;
1040
+ background: var(--card);
1041
+ padding: 6px 10px;
1042
+ border-radius: 8px;
1043
+ box-shadow: 0 4px 16px rgba(0,0,0,0.12);
1044
+ border: 1px solid var(--line);
1045
+ backdrop-filter: blur(8px);
1046
+ z-index: 10;
1047
+ }
1048
+ .graph-controls button {
1049
+ font-family: var(--mono);
1050
+ font-size: 11.5px;
1051
+ padding: 4px 9px;
1052
+ }
1053
+
1054
+ .graph-tooltip, .heatmap-tooltip, .blame-tooltip {
1055
+ position: fixed;
1056
+ background: var(--paper);
1057
+ color: var(--ink);
1058
+ border: 1.5px solid var(--line);
1059
+ padding: 10px 14px;
1060
+ border-radius: 8px;
1061
+ font-size: 12px;
1062
+ pointer-events: none;
1063
+ z-index: 1000;
1064
+ box-shadow: 0 8px 24px rgba(0,0,0,0.18);
1065
+ backdrop-filter: blur(10px);
1066
+ max-width: 300px;
1067
+ transition: opacity 0.1s ease;
1068
+ }
1069
+
1070
+ .heatmap-canvas {
1071
+ width: 100%;
1072
+ height: 100%;
1073
+ display: block;
1074
+ }
1075
+
1076
+ .flame-canvas {
1077
+ width: 100%;
1078
+ height: 100%;
1079
+ display: block;
1080
+ }
1081
+
1082
+ .search-overlay {
1083
+ position: fixed;
1084
+ top: 0; left: 0; right: 0; bottom: 0;
1085
+ background: rgba(0, 0, 0, 0.45);
1086
+ backdrop-filter: blur(8px);
1087
+ display: flex;
1088
+ justify-content: center;
1089
+ padding-top: 12vh;
1090
+ z-index: 2000;
1091
+ animation: searchFadeIn 0.15s ease-out;
1092
+ }
1093
+
1094
+ @keyframes searchFadeIn {
1095
+ from { opacity: 0; transform: scale(0.98); }
1096
+ to { opacity: 1; transform: scale(1); }
1097
+ }
1098
+
1099
+ .search-modal {
1100
+ width: 100%;
1101
+ max-width: 680px;
1102
+ background: var(--card);
1103
+ border-radius: 10px;
1104
+ box-shadow: 0 16px 48px rgba(0, 0, 0, 0.22);
1105
+ border: 1.5px solid var(--line);
1106
+ display: flex;
1107
+ flex-direction: column;
1108
+ max-height: 65vh;
1109
+ overflow: hidden;
1110
+ }
1111
+
1112
+ .search-header {
1113
+ display: flex;
1114
+ flex-direction: column;
1115
+ border-bottom: 1px solid var(--line);
1116
+ background: var(--paper);
1117
+ }
1118
+
1119
+ .search-input {
1120
+ font-family: var(--mono);
1121
+ font-size: 14px;
1122
+ flex: 1;
1123
+ min-width: 0;
1124
+ padding: 14px 0;
1125
+ border: none;
1126
+ background: transparent;
1127
+ outline: none;
1128
+ color: var(--ink);
1129
+ }
1130
+ .search-input::placeholder { color: var(--faint); }
1131
+
1132
+ .search-modes {
1133
+ display: flex;
1134
+ gap: 4px;
1135
+ padding: 0 12px 8px;
1136
+ }
1137
+
1138
+ .search-mode-chip {
1139
+ font-family: var(--mono);
1140
+ font-size: 11px;
1141
+ padding: 2px 8px;
1142
+ border-radius: 4px;
1143
+ border: 1px solid var(--line);
1144
+ background: transparent;
1145
+ color: var(--faint);
1146
+ cursor: pointer;
1147
+ transition: all 0.12s ease;
1148
+ }
1149
+ .search-mode-chip:hover {
1150
+ color: var(--ink);
1151
+ background: var(--paper-2);
1152
+ }
1153
+ .search-mode-chip.is-active {
1154
+ color: var(--ink);
1155
+ background: var(--accent-soft);
1156
+ border-color: var(--accent);
1157
+ font-weight: 600;
1158
+ }
1159
+
1160
+ .search-results {
1161
+ overflow-y: auto;
1162
+ padding: 4px 0;
1163
+ flex: 1;
1164
+ }
1165
+
1166
+ .search-result {
1167
+ padding: 8px 14px;
1168
+ cursor: pointer;
1169
+ display: flex;
1170
+ flex-direction: column;
1171
+ gap: 4px;
1172
+ border-bottom: 1px solid rgba(128,128,128,0.06);
1173
+ transition: background 0.08s ease;
1174
+ }
1175
+
1176
+ .search-result:hover, .search-result.is-selected {
1177
+ background: var(--accent-soft);
1178
+ }
1179
+
1180
+ .search-item-main {
1181
+ display: flex;
1182
+ align-items: center;
1183
+ gap: 8px;
1184
+ width: 100%;
1185
+ }
1186
+
1187
+ .search-ext-badge {
1188
+ font-family: var(--mono);
1189
+ font-size: 9px;
1190
+ font-weight: 700;
1191
+ padding: 1px 4px;
1192
+ border-radius: 3px;
1193
+ background: var(--paper-2);
1194
+ border: 1px solid var(--line);
1195
+ color: var(--faint);
1196
+ flex-shrink: 0;
1197
+ }
1198
+ .search-ext-badge.is-symbol {
1199
+ background: #e0e7ff;
1200
+ color: #3730a3;
1201
+ border-color: #c7d2fe;
1202
+ }
1203
+ .search-ext-badge.is-code {
1204
+ background: #fef3c7;
1205
+ color: #92400e;
1206
+ border-color: #fde68a;
1207
+ }
1208
+
1209
+ .search-title {
1210
+ display: flex;
1211
+ align-items: baseline;
1212
+ gap: 6px;
1213
+ flex: 1;
1214
+ overflow: hidden;
1215
+ }
1216
+ .search-name {
1217
+ font-family: var(--mono);
1218
+ font-size: 12.5px;
1219
+ font-weight: 600;
1220
+ color: var(--ink);
1221
+ white-space: nowrap;
1222
+ }
1223
+ .search-dir {
1224
+ font-family: var(--mono);
1225
+ font-size: 11px;
1226
+ color: var(--faint);
1227
+ overflow: hidden;
1228
+ text-overflow: ellipsis;
1229
+ white-space: nowrap;
1230
+ }
1231
+
1232
+ .search-type-tag {
1233
+ font-family: var(--mono);
1234
+ font-size: 10px;
1235
+ color: var(--faint);
1236
+ margin-left: auto;
1237
+ flex-shrink: 0;
1238
+ }
1239
+ .search-type-tag.is-sym { color: #4338ca; }
1240
+ .search-type-tag.is-code { color: #b45309; }
1241
+
1242
+ .search-snippet {
1243
+ font-family: var(--mono);
1244
+ font-size: 11px;
1245
+ background: var(--paper-2);
1246
+ border-radius: 4px;
1247
+ padding: 4px 8px;
1248
+ color: var(--ink-2);
1249
+ overflow: hidden;
1250
+ text-overflow: ellipsis;
1251
+ white-space: nowrap;
1252
+ border-left: 2px solid var(--accent);
1253
+ }
1254
+
1255
+ mark.search-match {
1256
+ background: rgba(234, 179, 8, 0.35);
1257
+ color: var(--ink);
1258
+ padding: 0 1px;
1259
+ border-radius: 2px;
1260
+ font-weight: 700;
1261
+ }
1262
+
1263
+ .search-empty {
1264
+ padding: 24px 16px;
1265
+ text-align: center;
1266
+ color: var(--faint);
1267
+ font-size: 12.5px;
1268
+ font-style: italic;
1269
+ }
1270
+
1271
+ /* The palette used to end in a shortcut list and nothing else. It now carries
1272
+ the query's own state — how many matches, how many files were indexed, what
1273
+ was skipped — because "no results" is a different message depending on
1274
+ whether the index ever saw the file. */
1275
+ .search-inputrow {
1276
+ display: flex;
1277
+ align-items: center;
1278
+ gap: 8px;
1279
+ padding: 0 12px 0 14px;
1280
+ }
1281
+ .search-icon { display: inline-flex; color: var(--faint); flex-shrink: 0; }
1282
+
1283
+ .search-toggle {
1284
+ font-family: var(--mono);
1285
+ font-size: 11px;
1286
+ line-height: 1;
1287
+ padding: 4px 6px;
1288
+ border-radius: 4px;
1289
+ border: 1px solid var(--line);
1290
+ background: transparent;
1291
+ color: var(--faint);
1292
+ cursor: pointer;
1293
+ flex-shrink: 0;
1294
+ }
1295
+ .search-toggle:hover { color: var(--ink); background: var(--paper-2); }
1296
+ .search-toggle.is-active {
1297
+ color: var(--ink);
1298
+ border-color: var(--accent);
1299
+ background: var(--accent-soft);
1300
+ font-weight: 700;
1301
+ }
1302
+
1303
+ .search-status {
1304
+ display: flex;
1305
+ justify-content: space-between;
1306
+ align-items: center;
1307
+ gap: 12px;
1308
+ padding: 6px 14px;
1309
+ background: var(--paper-2);
1310
+ border-top: 1px solid var(--line);
1311
+ font-size: 10.5px;
1312
+ color: var(--faint);
1313
+ }
1314
+ .search-status-line { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
1315
+ .search-keys { display: flex; gap: 10px; flex-shrink: 0; }
1316
+ .search-sep { color: var(--line); }
1317
+ .search-err { color: #9a3b2e; }
1318
+
1319
+ .search-spinner {
1320
+ display: inline-block;
1321
+ width: 9px;
1322
+ height: 9px;
1323
+ border: 1.5px solid var(--line);
1324
+ border-top-color: var(--accent);
1325
+ border-radius: 50%;
1326
+ animation: searchSpin 0.7s linear infinite;
1327
+ }
1328
+ @keyframes searchSpin { to { transform: rotate(360deg); } }
1329
+ .search-keys kbd {
1330
+ font-family: var(--mono);
1331
+ background: var(--card);
1332
+ border: 1px solid var(--line);
1333
+ border-radius: 3px;
1334
+ padding: 1px 4px;
1335
+ margin-right: 2px;
1336
+ font-size: 10px;
1337
+ }
1338
+
1339
+ .search-mode-count {
1340
+ font-family: var(--mono);
1341
+ font-size: 9.5px;
1342
+ margin-left: 5px;
1343
+ padding: 0 3px;
1344
+ border-radius: 3px;
1345
+ background: var(--paper-2);
1346
+ color: var(--faint);
1347
+ }
1348
+ .search-mode-chip.is-active .search-mode-count { background: var(--card); color: var(--ink); }
1349
+
1350
+ .search-chips {
1351
+ display: flex;
1352
+ flex-wrap: wrap;
1353
+ align-items: center;
1354
+ gap: 5px;
1355
+ padding: 0 12px 9px;
1356
+ }
1357
+ .search-chips[hidden] { display: none; }
1358
+
1359
+ .search-chip {
1360
+ display: inline-flex;
1361
+ align-items: center;
1362
+ gap: 4px;
1363
+ font-family: var(--mono);
1364
+ font-size: 10.5px;
1365
+ padding: 2px 4px 2px 6px;
1366
+ border-radius: 4px;
1367
+ border: 1px solid var(--accent);
1368
+ background: var(--accent-soft);
1369
+ color: var(--ink);
1370
+ }
1371
+ .search-chip-kind {
1372
+ text-transform: uppercase;
1373
+ font-size: 8.5px;
1374
+ letter-spacing: 0.05em;
1375
+ color: var(--faint);
1376
+ }
1377
+ .search-chip-remove {
1378
+ border: none;
1379
+ background: transparent;
1380
+ color: var(--faint);
1381
+ cursor: pointer;
1382
+ font-size: 12px;
1383
+ line-height: 1;
1384
+ padding: 0 2px;
1385
+ }
1386
+ .search-chip-remove:hover { color: var(--ink); }
1387
+
1388
+ .search-group-head {
1389
+ display: flex;
1390
+ justify-content: space-between;
1391
+ align-items: baseline;
1392
+ padding: 9px 14px 4px;
1393
+ font-family: var(--mono);
1394
+ font-size: 9.5px;
1395
+ text-transform: uppercase;
1396
+ letter-spacing: 0.07em;
1397
+ color: var(--faint);
1398
+ background: var(--paper);
1399
+ border-bottom: 1px solid var(--line);
1400
+ }
1401
+ .search-group-count { color: var(--faint); }
1402
+
1403
+ .search-ext-badge.is-recent { color: var(--faint); }
1404
+ .search-ext-badge.is-syntax {
1405
+ background: var(--paper-2);
1406
+ color: var(--ink-2);
1407
+ border-color: var(--line);
1408
+ }
1409
+ .search-result.is-example .search-name { font-weight: 500; color: var(--ink-2); }
1410
+
1411
+ .search-empty-hint {
1412
+ margin-top: 8px;
1413
+ font-size: 11.5px;
1414
+ font-style: normal;
1415
+ line-height: 1.55;
1416
+ max-width: 420px;
1417
+ margin-left: auto;
1418
+ margin-right: auto;
1419
+ }
1420
+ .search-empty code, .search-empty-hint code {
1421
+ font-family: var(--mono);
1422
+ background: var(--paper-2);
1423
+ border-radius: 3px;
1424
+ padding: 0 3px;
1425
+ color: var(--ink-2);
1426
+ }
1427
+
1428
+ .blame-gutter {
1429
+ width: 40px;
1430
+ flex-shrink: 0;
1431
+ display: flex;
1432
+ flex-direction: column;
1433
+ background: var(--paper-2);
1434
+ border-right: 1px solid var(--line);
1435
+ overflow: hidden;
1436
+ }
1437
+
1438
+ .blame-line {
1439
+ height: 20px; /* should match editor line height */
1440
+ width: 100%;
1441
+ position: relative;
1442
+ }
1443
+
1444
+ .landing-title {
1445
+ animation: fadeSlideIn linear both;
1446
+ animation-timeline: view();
1447
+ animation-range: entry 0% entry 100%;
1448
+ }
1449
+
1450
+ @keyframes fadeSlideIn {
1451
+ from { opacity: 0; transform: translateY(30px); }
1452
+ to { opacity: 1; transform: translateY(0); }
1453
+ }
1454
+
1455
+ ::view-transition-old(*),
1456
+ ::view-transition-new(*) {
1457
+ animation-duration: 0.2s;
1458
+ }
1459
+ }
1460
+ .link-list button:hover { text-decoration: underline; }
1461
+ .link-list .fn-kind { color: var(--faint); font-size: 10.5px; margin-left: 5px; }
1462
+
1463
+ /* ---------- docs view ---------- */
1464
+
1465
+ .docview {
1466
+ flex: 1;
1467
+ min-height: 0;
1468
+ overflow-y: auto; /* About & Code scroll normally */
1469
+ background: var(--paper);
1470
+ }
1471
+
1472
+ /* Only the Docs tab is a non-scrolling shell: it owns an inner scroll region
1473
+ plus the sticky ask bar pinned to the bottom. */
1474
+ #docView {
1475
+ display: flex;
1476
+ flex-direction: column;
1477
+ overflow: hidden;
1478
+ }
1479
+
1480
+ .doc-scroll { flex: 1; min-height: 0; overflow-y: auto; }
1481
+
1482
+ .doc-qa-rail {
1483
+ border-top: 1.5px solid var(--ink);
1484
+ background: var(--paper-2);
1485
+ max-height: 34vh;
1486
+ overflow-y: auto;
1487
+ padding: 12px 22px;
1488
+ }
1489
+
1490
+ .doc-askbar {
1491
+ display: flex;
1492
+ gap: 8px;
1493
+ padding: 10px 12px;
1494
+ border-top: 1.5px solid var(--ink);
1495
+ background: var(--card);
1496
+ }
1497
+ .doc-askbar .text-input { flex: 1; min-width: 0; }
1498
+ .doc-askbar .btn { display: inline-flex; align-items: center; }
1499
+ .doc-askbar .doc-clear, .doc-askbar .doc-close { margin-left: 2px; }
1500
+
1501
+ .doc-page {
1502
+ max-width: 760px;
1503
+ margin: 0 auto;
1504
+ padding: 30px 34px 70px;
1505
+ }
1506
+
1507
+ .doc-title {
1508
+ font-family: var(--serif);
1509
+ font-size: 32px;
1510
+ letter-spacing: -0.01em;
1511
+ margin: 0 0 4px;
1512
+ }
1513
+
1514
+ .doc-sub {
1515
+ font-family: var(--mono);
1516
+ font-size: 12px;
1517
+ color: var(--faint);
1518
+ margin: 0 0 6px;
1519
+ }
1520
+
1521
+ .doc-ai-note {
1522
+ font-family: var(--serif);
1523
+ font-style: italic;
1524
+ font-size: 13px;
1525
+ color: var(--faint);
1526
+ min-height: 18px;
1527
+ margin: 4px 0 0;
1528
+ }
1529
+
1530
+ .doc-overview {
1531
+ font-size: 15px;
1532
+ line-height: 1.55;
1533
+ color: var(--ink);
1534
+ margin: 12px 0 8px;
1535
+ }
1536
+
1537
+ .doc-section-h {
1538
+ font-family: var(--serif);
1539
+ font-size: 21px;
1540
+ margin: 30px 0 10px;
1541
+ padding-bottom: 6px;
1542
+ border-bottom: 1.5px solid var(--ink);
1543
+ }
1544
+
1545
+ .doc-readme {
1546
+ background: var(--card);
1547
+ border: 1.5px solid var(--ink);
1548
+ border-radius: 5px;
1549
+ box-shadow: var(--shadow-sm);
1550
+ padding: 18px 20px;
1551
+ font-size: 14px;
1552
+ color: var(--ink-2);
1553
+ max-height: 340px;
1554
+ overflow-y: auto;
1555
+ }
1556
+ .doc-readme .doc-h { font-family: var(--serif); color: var(--ink); margin: 14px 0 6px; }
1557
+ .doc-readme h1.doc-h { font-size: 20px; }
1558
+ .doc-readme h2.doc-h { font-size: 17px; }
1559
+ .doc-readme h3.doc-h { font-size: 15px; }
1560
+ .doc-readme p { margin: 8px 0; line-height: 1.55; }
1561
+ .doc-readme ul { margin: 8px 0; padding-left: 20px; }
1562
+ .doc-readme li { margin: 3px 0; }
1563
+ .doc-readme pre {
1564
+ background: var(--paper-2);
1565
+ border: 1px solid var(--line);
1566
+ border-radius: 4px;
1567
+ padding: 10px 12px;
1568
+ overflow-x: auto;
1569
+ font-size: 12px;
1570
+ }
1571
+ .doc-readme code { font-family: var(--mono); font-size: 12px; }
1572
+ .doc-readme p code, .doc-readme li code {
1573
+ background: var(--paper-2);
1574
+ border: 1px solid var(--line);
1575
+ border-radius: 3px;
1576
+ padding: 0 4px;
1577
+ }
1578
+ .doc-readme a { color: var(--accent); }
1579
+ .doc-dead-link { border-bottom: 1px dotted var(--faint); cursor: help; }
1580
+ .doc-readme-none {
1581
+ font-family: var(--serif);
1582
+ font-style: italic;
1583
+ color: var(--faint);
1584
+ }
1585
+
1586
+ .doc-folder { margin-top: 20px; }
1587
+ .doc-folder-h {
1588
+ font-family: var(--serif);
1589
+ font-size: 18px;
1590
+ margin: 0 0 2px;
1591
+ }
1592
+ .doc-folder-h .doc-depth { color: var(--faint); font-size: 13px; }
1593
+ .doc-folder-brief { font-size: 13.5px; color: var(--ink-2); margin: 2px 0 8px; }
1594
+
1595
+ .doc-indent-1 { margin-left: 18px; }
1596
+ .doc-indent-2 { margin-left: 36px; }
1597
+ .doc-indent-3 { margin-left: 54px; }
1598
+
1599
+ /* ---------- doc tabs ---------- */
1600
+
1601
+ .doc-tabs {
1602
+ position: sticky;
1603
+ top: 0;
1604
+ z-index: 5;
1605
+ display: flex;
1606
+ align-items: center;
1607
+ gap: 6px;
1608
+ padding: 10px 34px 9px;
1609
+ background: var(--paper);
1610
+ border-bottom: 1px solid var(--line);
1611
+ overflow-x: auto;
1612
+ }
1613
+
1614
+ .doc-tab {
1615
+ display: inline-flex;
1616
+ align-items: center;
1617
+ gap: 7px;
1618
+ font-family: var(--mono);
1619
+ font-size: 11.5px;
1620
+ padding: 4px 10px;
1621
+ border: 1.5px solid var(--ink);
1622
+ border-radius: 4px;
1623
+ background: var(--card);
1624
+ color: var(--ink);
1625
+ cursor: pointer;
1626
+ white-space: nowrap;
1627
+ flex-shrink: 0;
1628
+ }
1629
+ .doc-tab:hover { box-shadow: var(--shadow-sm); transform: translate(-1px, -1px); }
1630
+ .doc-tab.is-active { background: var(--ink); color: var(--paper); }
1631
+ .doc-tab.is-active .doc-tab-x { color: var(--paper); }
1632
+ .doc-tab-x {
1633
+ font-size: 13px;
1634
+ line-height: 1;
1635
+ color: var(--faint);
1636
+ padding: 0 1px;
1637
+ }
1638
+ .doc-tab-x:hover { color: var(--warn); }
1639
+ .doc-tab-spin { animation: pulse 0.8s steps(2) infinite; }
1640
+
1641
+ /* ---------- docs: contents index, entries, ask box ---------- */
1642
+
1643
+ .doc-anchor { scroll-margin-top: 62px; }
1644
+
1645
+ .doc-toc {
1646
+ display: flex;
1647
+ flex-direction: column;
1648
+ gap: 3px;
1649
+ background: var(--card);
1650
+ border: 1.5px solid var(--ink);
1651
+ border-radius: 5px;
1652
+ box-shadow: var(--shadow-sm);
1653
+ padding: 14px 18px;
1654
+ margin: 18px 0 8px;
1655
+ font-family: var(--mono);
1656
+ font-size: 12px;
1657
+ }
1658
+ .doc-toc-h {
1659
+ font-size: 10.5px;
1660
+ text-transform: uppercase;
1661
+ letter-spacing: 0.08em;
1662
+ color: var(--faint);
1663
+ margin-bottom: 4px;
1664
+ }
1665
+ .doc-toc a { color: var(--accent); text-decoration: none; }
1666
+ .doc-toc a:hover { text-decoration: underline; }
1667
+ .doc-toc-group { color: var(--faint); margin-top: 4px; }
1668
+ .doc-toc-folder { font-weight: 600; }
1669
+ .doc-toc-files { color: var(--faint); font-size: 11px; line-height: 1.7; }
1670
+ .doc-toc-sep { color: var(--line); }
1671
+
1672
+ .doc-toc-link {
1673
+ border: 0;
1674
+ background: none;
1675
+ padding: 0;
1676
+ font: inherit;
1677
+ color: var(--accent);
1678
+ cursor: pointer;
1679
+ text-align: left;
1680
+ }
1681
+ .doc-toc-link:hover { text-decoration: underline; }
1682
+ .doc-toc .doc-toc-files .doc-toc-link { font-size: 11px; }
1683
+
1684
+ .doc-gen-empty {
1685
+ font-family: var(--serif);
1686
+ font-style: italic;
1687
+ color: var(--faint);
1688
+ margin: 4px 0 10px;
1689
+ }
1690
+ #docGenBtn { margin-bottom: 14px; }
1691
+
1692
+ .doc-entry { margin-bottom: 11px; }
1693
+ .doc-entry-head {
1694
+ display: flex;
1695
+ align-items: baseline;
1696
+ gap: 10px;
1697
+ flex-wrap: wrap;
1698
+ }
1699
+ .doc-entry-name {
1700
+ font-family: var(--mono);
1701
+ font-size: 12.5px;
1702
+ font-weight: 600;
1703
+ }
1704
+ button.doc-entry-name {
1705
+ border: 0;
1706
+ background: none;
1707
+ padding: 0;
1708
+ font: inherit;
1709
+ color: var(--accent);
1710
+ cursor: pointer;
1711
+ }
1712
+ button.doc-entry-name:hover { text-decoration: underline; }
1713
+ .doc-entry-facts {
1714
+ font-family: var(--mono);
1715
+ font-size: 10.5px;
1716
+ color: var(--faint);
1717
+ }
1718
+ .doc-entry-text {
1719
+ margin: 2px 0 0;
1720
+ font-size: 13px;
1721
+ color: var(--ink-2);
1722
+ line-height: 1.55;
1723
+ }
1724
+ .doc-entry.is-unparsed { opacity: 0.7; }
1725
+
1726
+ .doc-qa-card {
1727
+ border: 1.5px solid var(--ink);
1728
+ border-left: 4px solid var(--accent);
1729
+ border-radius: 4px;
1730
+ background: var(--card);
1731
+ padding: 10px 14px;
1732
+ max-width: 760px;
1733
+ margin: 0 auto 10px;
1734
+ }
1735
+ .doc-qa-q {
1736
+ font-family: var(--serif);
1737
+ font-style: italic;
1738
+ color: var(--ink);
1739
+ margin: 0 0 6px;
1740
+ }
1741
+ .doc-qa-a { font-size: 13.5px; color: var(--ink-2); }
1742
+ .doc-qa-a p { margin: 0 0 8px; }
1743
+ .doc-qa-a code {
1744
+ font-family: var(--mono);
1745
+ font-size: 12px;
1746
+ background: var(--paper-2);
1747
+ border: 1px solid var(--line);
1748
+ border-radius: 3px;
1749
+ padding: 0 4px;
1750
+ }
1751
+
1752
+ /* ---------- about view ---------- */
1753
+
1754
+ .about-numbers {
1755
+ display: grid;
1756
+ grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
1757
+ gap: 10px;
1758
+ margin: 18px 0 6px;
1759
+ }
1760
+ .about-num {
1761
+ background: var(--card);
1762
+ border: 1.5px solid var(--ink);
1763
+ border-radius: 5px;
1764
+ box-shadow: var(--shadow-sm);
1765
+ padding: 12px 12px 9px;
1766
+ text-align: center;
1767
+ }
1768
+ .about-num b {
1769
+ display: block;
1770
+ font-family: var(--serif);
1771
+ font-size: 24px;
1772
+ font-weight: 600;
1773
+ color: var(--ink);
1774
+ }
1775
+ .about-num span {
1776
+ font-family: var(--mono);
1777
+ font-size: 10.5px;
1778
+ text-transform: uppercase;
1779
+ letter-spacing: 0.06em;
1780
+ color: var(--faint);
1781
+ }
1782
+ .about-desc {
1783
+ font-size: 14.5px;
1784
+ color: var(--ink-2);
1785
+ font-style: italic;
1786
+ font-family: var(--serif);
1787
+ margin: 10px 0;
1788
+ }
1789
+ .about-lineage {
1790
+ list-style: none;
1791
+ margin: 8px 0;
1792
+ padding: 0;
1793
+ font-size: 13px;
1794
+ color: var(--ink-2);
1795
+ }
1796
+ .about-lineage li { padding: 3px 0; border-bottom: 1px dotted var(--line); }
1797
+ .about-lineage li:last-child { border-bottom: 0; }
1798
+ .about-lineage a { color: var(--accent); }
1799
+
1800
+ .doc-detail .doc-detail-meta { margin-bottom: 4px; }
1801
+ .doc-detail-actions {
1802
+ display: flex;
1803
+ gap: 16px;
1804
+ margin: 10px 0 16px;
1805
+ font-size: 13px;
1806
+ }
1807
+
1808
+ .doc-detail-body { font-size: 14px; color: var(--ink-2); }
1809
+ .doc-detail-body .doc-h { font-family: var(--serif); color: var(--ink); margin: 18px 0 6px; }
1810
+ .doc-detail-body h1.doc-h { font-size: 20px; }
1811
+ .doc-detail-body h2.doc-h { font-size: 17px; border-bottom: 1px solid var(--line); padding-bottom: 4px; }
1812
+ .doc-detail-body h3.doc-h { font-size: 15px; }
1813
+ .doc-detail-body p { margin: 8px 0; line-height: 1.6; }
1814
+ .doc-detail-body ul { margin: 8px 0; padding-left: 20px; }
1815
+ .doc-detail-body li { margin: 3px 0; line-height: 1.5; }
1816
+ .doc-detail-body pre {
1817
+ background: var(--paper-2);
1818
+ border: 1px solid var(--line);
1819
+ border-radius: 4px;
1820
+ padding: 10px 12px;
1821
+ overflow-x: auto;
1822
+ font-size: 12px;
1823
+ }
1824
+ .doc-detail-body code { font-family: var(--mono); font-size: 12px; }
1825
+ .doc-detail-body p code, .doc-detail-body li code {
1826
+ background: var(--paper-2);
1827
+ border: 1px solid var(--line);
1828
+ border-radius: 3px;
1829
+ padding: 0 4px;
1830
+ }
1831
+
1832
+ .caret {
1833
+ display: inline-block;
1834
+ width: 7px; height: 14px;
1835
+ background: var(--accent);
1836
+ vertical-align: -2px;
1837
+ animation: pulse 0.7s steps(2) infinite;
1838
+ }
1839
+
1840
+
1841
+ .finding {
1842
+ border: 1.5px solid var(--ink);
1843
+ border-left-width: 5px;
1844
+ border-radius: 4px;
1845
+ background: var(--card);
1846
+ padding: 8px 11px;
1847
+ margin-bottom: 8px;
1848
+ }
1849
+ .finding h4 {
1850
+ margin: 0 0 3px;
1851
+ font-family: var(--serif);
1852
+ font-size: 15px;
1853
+ }
1854
+ .finding p { margin: 0; font-size: 12.5px; color: var(--ink-2); }
1855
+ .finding p code {
1856
+ font-family: var(--mono);
1857
+ font-size: 11.5px;
1858
+ background: var(--paper-2);
1859
+ border: 1px solid var(--line);
1860
+ border-radius: 3px;
1861
+ padding: 0 4px;
1862
+ }
1863
+ .finding.is-good { border-left-color: var(--accent); }
1864
+ .finding.is-note { border-left-color: var(--hub); }
1865
+ .finding.is-warn { border-left-color: var(--warn); }
1866
+
1867
+ .heat {
1868
+ display: grid;
1869
+ gap: 2px;
1870
+ font-family: var(--mono);
1871
+ font-size: 9.5px;
1872
+ margin: 4px 0 8px;
1873
+ }
1874
+ .heat-cell {
1875
+ aspect-ratio: 1;
1876
+ min-width: 22px;
1877
+ border-radius: 2px;
1878
+ background: var(--paper-2);
1879
+ display: flex;
1880
+ align-items: center;
1881
+ justify-content: center;
1882
+ color: var(--ink);
1883
+ }
1884
+ .heat-label,
1885
+ .heat-col-label {
1886
+ overflow: hidden;
1887
+ text-overflow: ellipsis;
1888
+ white-space: nowrap;
1889
+ color: var(--ink-2);
1890
+ align-self: center;
1891
+ }
1892
+ .heat-col-label { text-align: center; color: var(--faint); }
1893
+
1894
+ /* ---------- tree map (Map view) ---------- */
1895
+
1896
+ .mm { position: relative; }
1897
+ .mm-svg { position: absolute; inset: 0; pointer-events: none; }
1898
+
1899
+ .mm-edge {
1900
+ fill: none;
1901
+ stroke: var(--faint);
1902
+ stroke-width: 1.4;
1903
+ opacity: 0.75;
1904
+ transition: stroke 0.15s ease, stroke-width 0.15s ease, opacity 0.15s ease;
1905
+ }
1906
+ .mm-edge.is-dashed { stroke-dasharray: 5 4; opacity: 0.5; }
1907
+ .mm-edge.is-active {
1908
+ stroke: var(--accent);
1909
+ stroke-width: 2.5;
1910
+ opacity: 1;
1911
+ filter: drop-shadow(0 0 3px var(--accent));
1912
+ }
1913
+
1914
+ .mm-cell {
1915
+ position: absolute;
1916
+ background: var(--card);
1917
+ border: 1.5px solid var(--ink);
1918
+ border-radius: 5px;
1919
+ padding: 5px 9px 6px;
1920
+ cursor: pointer;
1921
+ box-shadow: var(--shadow-sm);
1922
+ transition: transform 0.06s ease, box-shadow 0.06s ease, opacity 0.12s ease;
1923
+ }
1924
+ .mm-cell:hover { transform: translate(-1px, -1px); box-shadow: var(--shadow); }
1925
+
1926
+ .mm.has-hover .mm-cell {
1927
+ opacity: 0.55;
1928
+ }
1929
+ .mm.has-hover .mm-cell.is-active-branch {
1930
+ opacity: 1;
1931
+ box-shadow: 0 0 0 1.5px var(--accent), var(--shadow);
1932
+ }
1933
+
1934
+ .mm-head {
1935
+ display: flex;
1936
+ align-items: center;
1937
+ gap: 5px;
1938
+ min-width: 0;
1939
+ }
1940
+ .mm-caret { color: var(--faint); font-size: 11px; width: 11px; flex-shrink: 0; }
1941
+ .mm-name {
1942
+ font-family: var(--mono);
1943
+ font-size: 12px;
1944
+ font-weight: 600;
1945
+ white-space: nowrap;
1946
+ overflow: hidden;
1947
+ text-overflow: ellipsis;
1948
+ }
1949
+ .mm-sum {
1950
+ font-family: var(--mono);
1951
+ font-size: 10.5px;
1952
+ color: var(--faint);
1953
+ margin-top: 1px;
1954
+ white-space: nowrap;
1955
+ overflow: hidden;
1956
+ text-overflow: ellipsis;
1957
+ }
1958
+
1959
+ .mm-cell.kind-root { background: var(--ink); color: var(--paper); }
1960
+ .mm-cell.kind-root .mm-sum,
1961
+ .mm-cell.kind-root .mm-caret { color: rgba(247, 244, 237, 0.65); }
1962
+
1963
+ [data-theme="dark"] .mm-cell.kind-root .mm-sum,
1964
+ [data-theme="dark"] .mm-cell.kind-root .mm-caret { color: rgba(236, 231, 219, 0.65); }
1965
+
1966
+ .mm-cell.kind-folder { background: var(--paper-2); }
1967
+
1968
+ .mm-cell.is-entry { border-color: var(--accent); background: var(--accent-soft); }
1969
+ .mm-cell.is-entry .mm-sum { color: var(--accent); }
1970
+
1971
+ .mm-cell.is-hub { border-color: var(--hub); background: var(--hub-soft); }
1972
+ .mm-cell.is-hub .mm-sum { color: var(--hub); }
1973
+
1974
+ .mm-cell.is-cycle { border-color: var(--warn); }
1975
+ .mm-cell.is-cycle .mm-sum { color: var(--warn); }
1976
+
1977
+ .mm-cell.is-plain { border-color: var(--line); box-shadow: none; }
1978
+
1979
+ .mm-cell.is-ghost {
1980
+ border-style: dashed;
1981
+ border-color: var(--faint);
1982
+ box-shadow: none;
1983
+ background: transparent;
1984
+ }
1985
+ .mm-cell.is-ghost .mm-name { color: var(--ink-2); font-weight: 400; }
1986
+
1987
+ .mm-cell.kind-more {
1988
+ border-style: dotted;
1989
+ border-color: var(--line);
1990
+ box-shadow: none;
1991
+ background: transparent;
1992
+ }
1993
+ .mm-cell.kind-more .mm-name { color: var(--faint); font-weight: 400; font-style: italic; }
1994
+
1995
+ /* ---------- tour bar ---------- */
1996
+
1997
+ .tourbar {
1998
+ position: fixed;
1999
+ left: 0; right: 0; bottom: 0;
2000
+ z-index: 30;
2001
+ display: flex;
2002
+ align-items: center;
2003
+ gap: 18px;
2004
+ padding: 10px 18px;
2005
+ border-top: 2px solid var(--ink);
2006
+ background: var(--paper);
2007
+ }
2008
+
2009
+ .tourbar-info { display: flex; flex-direction: column; min-width: 0; }
2010
+ .tourbar-kicker {
2011
+ font-family: var(--mono);
2012
+ font-size: 10.5px;
2013
+ text-transform: uppercase;
2014
+ letter-spacing: 0.08em;
2015
+ color: var(--faint);
2016
+ }
2017
+ .tourbar-title {
2018
+ font-family: var(--serif);
2019
+ font-size: 17px;
2020
+ white-space: nowrap;
2021
+ overflow: hidden;
2022
+ text-overflow: ellipsis;
2023
+ }
2024
+ .tourbar-controls { margin-left: auto; display: flex; align-items: center; gap: 8px; }
2025
+ .tourbar-count { font-family: var(--mono); font-size: 12px; color: var(--ink-2); min-width: 48px; text-align: center; }
2026
+
2027
+ /* ---------- settings drawer ---------- */
2028
+
2029
+ .drawer-scrim {
2030
+ position: fixed;
2031
+ inset: 0;
2032
+ z-index: 40;
2033
+ background: var(--scrim);
2034
+ }
2035
+
2036
+ .drawer {
2037
+ position: fixed;
2038
+ top: 0; right: 0; bottom: 0;
2039
+ z-index: 41;
2040
+ width: min(390px, 92vw);
2041
+ background: var(--card);
2042
+ border-left: 2px solid var(--ink);
2043
+ padding: 20px;
2044
+ overflow-y: auto;
2045
+ }
2046
+
2047
+ .drawer-head {
2048
+ display: flex;
2049
+ align-items: center;
2050
+ justify-content: space-between;
2051
+ margin-bottom: 10px;
2052
+ }
2053
+ .drawer-head h2 { font-family: var(--serif); font-size: 22px; margin: 0; }
2054
+
2055
+ .drawer-note { font-size: 13px; color: var(--ink-2); margin: 0 0 16px; }
2056
+
2057
+ .field { display: block; margin-bottom: 12px; }
2058
+ .field-label {
2059
+ display: block;
2060
+ font-family: var(--mono);
2061
+ font-size: 11px;
2062
+ text-transform: uppercase;
2063
+ letter-spacing: 0.07em;
2064
+ color: var(--faint);
2065
+ margin-bottom: 4px;
2066
+ }
2067
+
2068
+ .drawer-actions { display: flex; gap: 8px; margin: 16px 0 10px; }
2069
+
2070
+ .drawer-status { font-family: var(--mono); font-size: 12px; min-height: 16px; }
2071
+ .drawer-status.ok { color: var(--accent); }
2072
+ .drawer-status.err { color: var(--warn); }
2073
+
2074
+ .drawer-fine {
2075
+ margin-top: 18px;
2076
+ padding-top: 12px;
2077
+ border-top: 1px solid var(--line);
2078
+ font-size: 12px;
2079
+ color: var(--faint);
2080
+ font-style: italic;
2081
+ font-family: var(--serif);
2082
+ }
2083
+
2084
+ /* ---------- MCP ---------- */
2085
+
2086
+ /* The dot is the whole status readout: the button carries it, the panel repeats
2087
+ it larger. Three states, three colors, no text to read at a glance. */
2088
+ .mcp-dot {
2089
+ display: inline-block;
2090
+ width: 7px;
2091
+ height: 7px;
2092
+ border-radius: 50%;
2093
+ background: var(--faint);
2094
+ margin-right: 6px;
2095
+ vertical-align: 1px;
2096
+ flex: none;
2097
+ }
2098
+ .mcp-dot-lg { width: 9px; height: 9px; margin-right: 0; }
2099
+ .mcp-dot.is-running { background: var(--accent); }
2100
+ .mcp-dot.is-starting { background: var(--warn); animation: mcp-pulse 1.1s ease-in-out infinite; }
2101
+ .mcp-dot.is-error { background: var(--warn); }
2102
+
2103
+ @keyframes mcp-pulse {
2104
+ 0%, 100% { opacity: 1; }
2105
+ 50% { opacity: 0.3; }
2106
+ }
2107
+
2108
+ #mcpBtn { display: inline-flex; align-items: center; }
2109
+
2110
+ .mcp-state {
2111
+ display: flex;
2112
+ align-items: center;
2113
+ gap: 8px;
2114
+ padding: 10px 12px;
2115
+ border: 1px solid var(--line);
2116
+ border-radius: 4px;
2117
+ margin-bottom: 4px;
2118
+ }
2119
+ .mcp-state-text { font-family: var(--mono); font-size: 12px; }
2120
+
2121
+ .mcp-config { margin-top: 18px; }
2122
+
2123
+ .mcp-config-row { display: flex; gap: 6px; margin: 6px 0 10px; }
2124
+ .mcp-config-input {
2125
+ flex: 1;
2126
+ min-width: 0;
2127
+ font-family: var(--mono);
2128
+ font-size: 11px;
2129
+ }
2130
+
2131
+ .mcp-tabs { display: flex; gap: 4px; margin-bottom: 6px; }
2132
+ .mcp-tab {
2133
+ font-family: var(--mono);
2134
+ font-size: 11px;
2135
+ text-transform: uppercase;
2136
+ letter-spacing: 0.06em;
2137
+ padding: 3px 8px;
2138
+ background: none;
2139
+ border: 1px solid var(--line);
2140
+ border-radius: 3px;
2141
+ color: var(--faint);
2142
+ cursor: pointer;
2143
+ }
2144
+ .mcp-tab.is-on { color: var(--ink); border-color: var(--ink); }
2145
+
2146
+ .mcp-config-block {
2147
+ font-family: var(--mono);
2148
+ font-size: 11px;
2149
+ line-height: 1.55;
2150
+ background: var(--paper-2);
2151
+ border: 1px solid var(--line);
2152
+ border-radius: 4px;
2153
+ padding: 10px 12px;
2154
+ margin: 0;
2155
+ overflow-x: auto;
2156
+ white-space: pre;
2157
+ color: var(--ink-2);
2158
+ }
2159
+
2160
+ /* ---------- toast ---------- */
2161
+
2162
+ .toast {
2163
+ position: fixed;
2164
+ left: 18px; bottom: 18px;
2165
+ z-index: 50;
2166
+ font-family: var(--mono);
2167
+ font-size: 12.5px;
2168
+ background: var(--ink);
2169
+ color: var(--paper);
2170
+ border-radius: 4px;
2171
+ padding: 9px 14px;
2172
+ box-shadow: var(--shadow);
2173
+ }
2174
+
2175
+ /* ---------- scrollbars ---------- */
2176
+
2177
+ ::-webkit-scrollbar { width: 10px; height: 10px; }
2178
+ ::-webkit-scrollbar-track { background: transparent; }
2179
+ ::-webkit-scrollbar-thumb {
2180
+ background: var(--paper-3);
2181
+ border: 2px solid var(--paper);
2182
+ border-radius: 6px;
2183
+ }
2184
+ ::-webkit-scrollbar-thumb:hover { background: var(--faint); }
2185
+
2186
+ /* ---------- small screens ---------- */
2187
+
2188
+ @media (max-width: 980px) {
2189
+ .explorer { grid-template-columns: 200px 1fr 280px; }
2190
+ .load-grid { grid-template-columns: 1fr; }
2191
+ .landing-foot { flex-direction: column; gap: 6px; align-items: center; }
2192
+ }
2193
+
2194
+ /* ---------- code preview ---------- */
2195
+
2196
+ :root {
2197
+ --tok-kw: #9a3b2e;
2198
+ --tok-str: #2f5d3f;
2199
+ --tok-num: #1f5f8b;
2200
+ --tok-com: #8a8578;
2201
+ }
2202
+
2203
+ [data-theme="dark"] {
2204
+ --tok-kw: #e08a6d;
2205
+ --tok-str: #8fc7a0;
2206
+ --tok-num: #7fb3d9;
2207
+ --tok-com: #6f6a5e;
2208
+ }
2209
+
2210
+ .foot-license a {
2211
+ color: var(--ink);
2212
+ text-decoration: underline dotted;
2213
+ text-underline-offset: 3px;
2214
+ }
2215
+ .foot-license a:hover { color: var(--accent); }
2216
+
2217
+ .code-tab-container {
2218
+ display: flex;
2219
+ flex: 1;
2220
+ min-height: 0;
2221
+ width: 100%;
2222
+ height: 100%;
2223
+ position: relative;
2224
+ overflow: hidden;
2225
+ }
2226
+ .code-docview {
2227
+ flex: 1;
2228
+ min-width: 0;
2229
+ height: 100%;
2230
+ overflow-y: auto;
2231
+ }
2232
+
2233
+ .code-page { max-width: 980px; margin: 0 auto; padding: 18px 22px 60px; }
2234
+
2235
+ .code-empty {
2236
+ max-width: 640px;
2237
+ margin: 60px auto;
2238
+ text-align: center;
2239
+ color: var(--faint);
2240
+ font-size: 13.5px;
2241
+ }
2242
+
2243
+ .code-head {
2244
+ display: flex;
2245
+ align-items: flex-start;
2246
+ gap: 14px;
2247
+ margin-bottom: 12px;
2248
+ }
2249
+
2250
+ .code-nav { display: flex; gap: 6px; padding-top: 4px; }
2251
+
2252
+ .code-navbtn {
2253
+ font-family: var(--mono);
2254
+ font-size: 12px;
2255
+ padding: 5px 10px;
2256
+ background: var(--card);
2257
+ color: var(--ink);
2258
+ border: 1.5px solid var(--ink);
2259
+ border-radius: 5px;
2260
+ cursor: pointer;
2261
+ box-shadow: var(--shadow-sm);
2262
+ }
2263
+ .code-navbtn:hover:not(:disabled) { background: var(--accent-soft); }
2264
+ .code-navbtn:disabled { opacity: 0.4; cursor: default; box-shadow: none; }
2265
+
2266
+ .code-title { flex: 1; min-width: 0; }
2267
+ .code-title h2 {
2268
+ font-family: var(--serif);
2269
+ font-size: 22px;
2270
+ font-weight: 600;
2271
+ margin: 0 0 2px;
2272
+ word-break: break-all;
2273
+ }
2274
+ .code-path { font-family: var(--mono); font-size: 11.5px; color: var(--faint); word-break: break-all; }
2275
+ .code-meta { font-size: 12px; color: var(--faint); margin-top: 4px; }
2276
+
2277
+ .code-actions { display: flex; gap: 6px; padding-top: 4px; }
2278
+
2279
+ .code-links {
2280
+ display: flex;
2281
+ flex-wrap: wrap;
2282
+ align-items: center;
2283
+ gap: 6px;
2284
+ margin-bottom: 12px;
2285
+ font-size: 12px;
2286
+ }
2287
+ .code-links-label { color: var(--faint); font-style: italic; margin-right: 2px; }
2288
+ .code-chip {
2289
+ font-family: var(--mono);
2290
+ font-size: 11.5px;
2291
+ padding: 3px 8px;
2292
+ background: var(--card);
2293
+ color: var(--ink);
2294
+ border: 1px solid var(--line);
2295
+ border-radius: 20px;
2296
+ cursor: pointer;
2297
+ }
2298
+ .code-chip:hover { border-color: var(--ink); background: var(--accent-soft); }
2299
+
2300
+ .code-note {
2301
+ font-size: 12px;
2302
+ color: var(--faint);
2303
+ font-style: italic;
2304
+ margin-bottom: 8px;
2305
+ }
2306
+
2307
+ .code-shell {
2308
+ display: flex;
2309
+ align-items: flex-start;
2310
+ overflow: auto;
2311
+ max-height: calc(100vh - 260px);
2312
+ background: var(--card);
2313
+ border: 1.5px solid var(--ink);
2314
+ border-radius: 8px;
2315
+ box-shadow: var(--shadow-sm);
2316
+ font-family: var(--mono);
2317
+ font-size: 12.5px;
2318
+ line-height: 1.55;
2319
+ }
2320
+
2321
+ .code-monaco {
2322
+ height: calc(100vh - 270px);
2323
+ min-height: 320px;
2324
+ background: var(--card);
2325
+ border: 1.5px solid var(--ink);
2326
+ border-radius: 8px;
2327
+ box-shadow: var(--shadow-sm);
2328
+ overflow: hidden;
2329
+ }
2330
+
2331
+
2332
+ /* ---------- author links ---------- */
2333
+
2334
+ .me-links {
2335
+ display: inline-flex;
2336
+ align-items: center;
2337
+ gap: 6px;
2338
+ margin-left: 6px;
2339
+ padding-left: 10px;
2340
+ border-left: 1px solid var(--line);
2341
+ }
2342
+
2343
+ .me-link {
2344
+ width: 30px;
2345
+ height: 30px;
2346
+ display: inline-flex;
2347
+ align-items: center;
2348
+ justify-content: center;
2349
+ color: var(--ink);
2350
+ background: var(--card);
2351
+ border: 1.5px solid var(--ink);
2352
+ border-radius: 6px;
2353
+ box-shadow: var(--shadow-sm);
2354
+ transition: transform 0.12s ease, background 0.12s ease;
2355
+ }
2356
+ .me-link:hover { background: var(--accent-soft); transform: translateY(-1px); }
2357
+ .me-link svg { width: 16px; height: 16px; display: block; }
2358
+
2359
+ /* ---------- about: the tool card ---------- */
2360
+
2361
+ .about-tool {
2362
+ max-width: 540px;
2363
+ padding: 16px 18px 14px;
2364
+ background: var(--card);
2365
+ border: 1.5px solid var(--ink);
2366
+ border-radius: 8px;
2367
+ box-shadow: var(--shadow-sm);
2368
+ }
2369
+ .about-tool-name { font-family: var(--serif); font-size: 20px; font-weight: 600; }
2370
+ .about-tool-note { color: var(--faint); font-size: 12.5px; margin: 4px 0 12px; }
2371
+ .about-tool-links { display: flex; flex-wrap: wrap; gap: 8px; }
2372
+ .tool-link {
2373
+ display: inline-flex;
2374
+ align-items: center;
2375
+ gap: 7px;
2376
+ font-family: var(--mono);
2377
+ font-size: 12px;
2378
+ padding: 6px 12px;
2379
+ color: var(--ink);
2380
+ text-decoration: none;
2381
+ background: var(--paper);
2382
+ border: 1.5px solid var(--ink);
2383
+ border-radius: 6px;
2384
+ box-shadow: var(--shadow-sm);
2385
+ transition: transform 0.12s ease, background 0.12s ease;
2386
+ }
2387
+ .tool-link:hover { background: var(--accent-soft); transform: translateY(-1px); }
2388
+ .tool-link svg { width: 14px; height: 14px; display: block; }
2389
+ .about-tool-by { margin: 12px 0 0; font-size: 12px; color: var(--faint); font-style: italic; }
2390
+
2391
+ .about-maker { margin-bottom: 24px; }
2392
+
2393
+ /* ---------- about: stack ------------------------------ */
2394
+
2395
+ .stack-block { margin-bottom: 22px; }
2396
+ .stack-langs { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 6px; }
2397
+ .stack-lang {
2398
+ font-family: var(--mono);
2399
+ font-size: 11.5px;
2400
+ background: var(--card);
2401
+ border: 1px solid var(--line);
2402
+ border-radius: 20px;
2403
+ padding: 3px 9px;
2404
+ }
2405
+ .stack-lang i { font-style: normal; color: var(--accent); font-weight: 600; }
2406
+ .stack-pm { font-size: 12px; color: var(--faint); margin: 4px 0 10px; }
2407
+ .stack-grid { display: flex; flex-direction: column; gap: 6px; margin-bottom: 8px; }
2408
+ .stack-item {
2409
+ display: flex;
2410
+ flex-wrap: wrap;
2411
+ align-items: center;
2412
+ gap: 8px;
2413
+ padding: 8px 10px;
2414
+ background: var(--card);
2415
+ border: 1px solid var(--line);
2416
+ border-left: 3px solid var(--accent);
2417
+ border-radius: 4px;
2418
+ font-size: 12.5px;
2419
+ }
2420
+ .stack-name { font-family: var(--mono); font-weight: 600; }
2421
+ .stack-cat { color: var(--faint); font-size: 11.5px; }
2422
+ .stack-ver, .stack-dev {
2423
+ font-family: var(--mono);
2424
+ font-size: 10.5px;
2425
+ border: 1px solid var(--line);
2426
+ border-radius: 4px;
2427
+ padding: 1px 5px;
2428
+ color: var(--ink-2);
2429
+ }
2430
+ .stack-dev { color: var(--faint); }
2431
+ .stack-doc {
2432
+ font-family: var(--mono);
2433
+ font-size: 11.5px;
2434
+ color: var(--accent);
2435
+ text-decoration: none;
2436
+ margin-left: auto;
2437
+ }
2438
+ .stack-doc:hover { text-decoration: underline; }
2439
+ .stack-sum {
2440
+ font-family: var(--mono);
2441
+ font-size: 11px;
2442
+ background: var(--paper);
2443
+ border: 1.5px solid var(--ink);
2444
+ border-radius: 4px;
2445
+ color: var(--ink);
2446
+ cursor: pointer;
2447
+ padding: 3px 9px;
2448
+ }
2449
+ .stack-sum:hover:not(:disabled) { background: var(--accent-soft); }
2450
+ .stack-sum:disabled { opacity: 0.5; cursor: default; }
2451
+ .stack-body { width: 100%; }
2452
+ .stack-body-text {
2453
+ font-size: 13px;
2454
+ color: var(--ink-2);
2455
+ border-top: 1px dotted var(--line);
2456
+ margin-top: 6px;
2457
+ padding-top: 8px;
2458
+ }
2459
+ .stack-hint {
2460
+ font-size: 11.5px;
2461
+ color: var(--faint);
2462
+ font-style: italic;
2463
+ margin: 2px 0 0;
2464
+ }
2465
+ .about-maker-role {
2466
+ font-family: var(--mono);
2467
+ font-size: 11.5px;
2468
+ color: var(--accent);
2469
+ letter-spacing: 0.02em;
2470
+ margin: 3px 0 8px;
2471
+ }
2472
+
2473
+ /* ---------- landing: tool & maker card ---------- */
2474
+
2475
+ .landing-about {
2476
+ position: relative;
2477
+ display: flex;
2478
+ align-items: stretch;
2479
+ margin-top: 36px;
2480
+ text-align: left;
2481
+ background: var(--card);
2482
+ border: 1.5px solid var(--ink);
2483
+ border-radius: 10px;
2484
+ box-shadow: var(--shadow-sm);
2485
+ }
2486
+ .la-actions {
2487
+ position: absolute;
2488
+ top: 8px;
2489
+ right: 10px;
2490
+ display: flex;
2491
+ align-items: center;
2492
+ gap: 6px;
2493
+ }
2494
+ .la-hide {
2495
+ font-family: var(--mono);
2496
+ font-size: 10.5px;
2497
+ color: var(--faint);
2498
+ background: none;
2499
+ border: none;
2500
+ border-radius: 4px;
2501
+ padding: 2px 7px;
2502
+ cursor: pointer;
2503
+ }
2504
+ .la-hide:hover { color: var(--ink); background: var(--accent-soft); }
2505
+ .la-remove:hover { color: var(--warn); background: #fee2e2; }
2506
+ .credits-bar { margin: 36px 0 0; display: flex; justify-content: center; align-items: center; gap: 8px; }
2507
+ .credits-show {
2508
+ box-shadow: var(--shadow-sm);
2509
+ padding: 8px 16px;
2510
+ }
2511
+ .credits-show:hover { background: var(--accent-soft); transform: translateY(-1px); }
2512
+ .credits-bar-remove {
2513
+ font-size: 11px;
2514
+ color: var(--faint);
2515
+ padding: 6px 10px;
2516
+ }
2517
+ .credits-bar-remove:hover { color: var(--warn); }
2518
+ .la-col { flex: 1 1 0; padding: 18px 22px 16px; min-width: 0; }
2519
+ .la-rule { border-left: 1px dotted var(--line); margin: 14px 0; }
2520
+ .la-name { font-family: var(--serif); font-size: 20px; font-weight: 600; }
2521
+ .la-role {
2522
+ font-family: var(--mono);
2523
+ font-size: 11.5px;
2524
+ color: var(--accent);
2525
+ letter-spacing: 0.02em;
2526
+ margin: 3px 0 8px;
2527
+ }
2528
+ .la-note { color: var(--faint); font-size: 12.5px; line-height: 1.55; margin: 4px 0 12px; }
2529
+
2530
+ @media (max-width: 860px) {
2531
+ .landing-about { flex-direction: column; }
2532
+ .la-rule { border-left: none; border-top: 1px dotted var(--line); margin: 0 18px; }
2533
+ }
2534
+
2535
+ .code-gutter {
2536
+ position: sticky;
2537
+ left: 0;
2538
+ flex: 0 0 auto;
2539
+ margin: 0;
2540
+ padding: 12px 10px 12px 14px;
2541
+ text-align: right;
2542
+ color: var(--faint);
2543
+ background: var(--card);
2544
+ border-right: 1px dotted var(--line);
2545
+ user-select: none;
2546
+ }
2547
+
2548
+ .code-body { margin: 0; padding: 12px 18px; flex: 1 1 auto; min-width: 0; }
2549
+ .code-body code { font-family: inherit; }
2550
+
2551
+ .tok-kw { color: var(--tok-kw); font-weight: 600; }
2552
+ .tok-str { color: var(--tok-str); }
2553
+ .tok-num { color: var(--tok-num); }
2554
+ .tok-com { color: var(--tok-com); font-style: italic; }
2555
+
2556
+ /* ==========================================================================
2557
+ GitHub-Grade Views: Insights, Diff, Workflows, SBOM
2558
+ ========================================================================== */
2559
+
2560
+ /* ---------- Insights View ------------------------------------------------ */
2561
+ .insights-layout { max-width: 1040px; margin: 0 auto; padding: 24px 20px 60px; display: flex; flex-direction: column; gap: 28px; }
2562
+ .insights-hero { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 14px; }
2563
+ .insights-stat-card { background: var(--card); border: 1px solid var(--line); border-radius: 8px; padding: 16px 20px; box-shadow: var(--shadow-sm); display: flex; flex-direction: column; }
2564
+ .isc-num { font-family: var(--mono); font-size: 26px; font-weight: 700; color: var(--ink); }
2565
+ .isc-lbl { font-size: 12px; color: var(--faint); margin-top: 4px; }
2566
+
2567
+ .insights-section { background: var(--card); border: 1px solid var(--line); border-radius: 8px; padding: 20px 24px; box-shadow: var(--shadow-sm); }
2568
+ .section-head { margin-bottom: 16px; }
2569
+ .section-head h3 { margin: 0 0 4px; font-size: 16px; font-weight: 600; }
2570
+ .section-sub { font-size: 12px; color: var(--faint); }
2571
+
2572
+ .insights-grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
2573
+ @media (max-width: 860px) { .insights-grid-2 { grid-template-columns: 1fr; } }
2574
+
2575
+ .cal-scroll-wrap { overflow-x: auto; padding-bottom: 6px; }
2576
+ .cal-heatmap-svg { width: 100%; min-width: 740px; display: block; }
2577
+ .cal-cell { fill: var(--line); stroke: rgba(0,0,0,0.05); stroke-width: 1px; transition: opacity 0.15s; }
2578
+ .cal-cell:hover { stroke: var(--ink); stroke-width: 1.5px; }
2579
+ .cal-cell.lvl-0 { fill: rgba(128, 128, 128, 0.12); }
2580
+ .cal-cell.lvl-1 { fill: #9be9a8; }
2581
+ .cal-cell.lvl-2 { fill: #40c463; }
2582
+ .cal-cell.lvl-3 { fill: #30a14e; }
2583
+ .cal-cell.lvl-4 { fill: #216e39; }
2584
+ .cal-label { font-size: 9px; fill: var(--faint); font-family: var(--mono); }
2585
+ .cal-legend { display: flex; align-items: center; justify-content: flex-end; gap: 4px; font-size: 11px; color: var(--faint); margin-top: 10px; }
2586
+ .cal-cell-legend { width: 10px; height: 10px; border-radius: 2px; display: inline-block; }
2587
+ .cal-cell-legend.lvl-0 { background: rgba(128, 128, 128, 0.12); }
2588
+ .cal-cell-legend.lvl-1 { background: #9be9a8; }
2589
+ .cal-cell-legend.lvl-2 { background: #40c463; }
2590
+ .cal-cell-legend.lvl-3 { background: #30a14e; }
2591
+ .cal-cell-legend.lvl-4 { background: #216e39; }
2592
+
2593
+ .punch-svg { width: 100%; min-width: 500px; display: block; }
2594
+ .punch-dot { fill: var(--accent); opacity: 0.75; transition: transform 0.1s; }
2595
+ .punch-dot:hover { opacity: 1; stroke: var(--ink); stroke-width: 1.5px; }
2596
+ .punch-lbl { font-size: 9.5px; fill: var(--faint); font-family: var(--mono); }
2597
+
2598
+ .contrib-list { display: flex; flex-direction: column; gap: 10px; }
2599
+ .contrib-item { display: flex; align-items: center; gap: 12px; padding: 6px 0; border-bottom: 1px dotted var(--line); }
2600
+ .contrib-item:last-child { border-bottom: none; }
2601
+ .contrib-rank { font-family: var(--mono); font-size: 12px; font-weight: 700; color: var(--faint); width: 24px; }
2602
+ .contrib-avatar { width: 32px; height: 32px; border-radius: 50%; background: var(--accent-soft); color: var(--accent); display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: 700; font-family: var(--mono); border: 1px solid var(--accent); }
2603
+ .contrib-info { flex: 1; min-width: 0; }
2604
+ .contrib-name { font-weight: 600; font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
2605
+ .contrib-meta { font-size: 11.5px; color: var(--faint); }
2606
+ .contrib-bar-wrap { width: 80px; height: 6px; background: var(--line); border-radius: 3px; overflow: hidden; }
2607
+ .contrib-bar { height: 100%; background: var(--accent); }
2608
+
2609
+ /* ---------- Diff & PR Blast Radius View ---------------------------------- */
2610
+ .diff-layout { display: flex; flex-direction: column; height: 100%; min-height: 0; }
2611
+ .diff-header { display: flex; align-items: center; justify-content: space-between; padding: 12px 18px; border-bottom: 1px solid var(--line); background: var(--card); gap: 12px; flex-wrap: wrap; }
2612
+ .diff-ref-selectors { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
2613
+ .diff-select-group { display: flex; align-items: center; gap: 6px; font-size: 12px; }
2614
+ .diff-select-label { color: var(--faint); font-weight: 500; }
2615
+ .diff-select { font-family: var(--mono); font-size: 12px; padding: 4px 8px; border: 1px solid var(--line); border-radius: 4px; background: var(--paper); color: var(--ink); }
2616
+ .diff-arrow { color: var(--faint); font-weight: bold; }
2617
+ .diff-view-modes { display: flex; gap: 4px; }
2618
+
2619
+ .diff-body { display: flex; flex: 1; min-height: 0; }
2620
+ .diff-sidebar { width: 300px; border-right: 1px solid var(--line); background: var(--card); display: flex; flex-direction: column; flex-shrink: 0; }
2621
+ .diff-sidebar-head { padding: 12px 16px; border-bottom: 1px solid var(--line); display: flex; justify-content: space-between; align-items: center; }
2622
+ .diff-sidebar-head h4 { margin: 0; font-size: 13px; }
2623
+ .diff-stat-chip { font-size: 11.5px; }
2624
+
2625
+ .blast-radius-box { margin: 12px 14px; padding: 12px; background: var(--paper); border: 1.5px solid var(--accent); border-radius: 6px; box-shadow: var(--shadow-sm); }
2626
+ .br-title { font-size: 11px; text-transform: uppercase; letter-spacing: 0.05em; font-weight: 700; color: var(--accent); margin-bottom: 4px; }
2627
+ .br-metric { font-size: 13px; font-weight: 600; color: var(--ink); }
2628
+ .br-desc { font-size: 11px; color: var(--faint); margin-top: 4px; line-height: 1.4; }
2629
+
2630
+ .diff-files-list { flex: 1; overflow-y: auto; padding: 6px 0; }
2631
+ .diff-file-item { display: flex; align-items: center; gap: 8px; padding: 8px 14px; cursor: pointer; font-size: 12px; border-left: 3px solid transparent; transition: background 0.1s; }
2632
+ .diff-file-item:hover { background: var(--paper); }
2633
+ .diff-file-item.is-selected { background: var(--accent-soft); border-left-color: var(--accent); }
2634
+ .diff-file-badge { font-family: var(--mono); font-size: 10px; font-weight: 700; padding: 1px 4px; border-radius: 3px; }
2635
+ .status-modified { background: #fffae6; color: #b78103; border: 1px solid #ffe58f; }
2636
+ .status-added { background: #f6ffed; color: #389e0d; border: 1px solid #b7eb8f; }
2637
+ .status-deleted { background: #fff1f0; color: #cf1322; border: 1px solid #ffa39e; }
2638
+ .diff-file-path { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-family: var(--mono); }
2639
+ .diff-file-counts { font-family: var(--mono); font-size: 11px; display: flex; gap: 4px; }
2640
+ .diff-add { color: #2e5d43; font-weight: 600; }
2641
+ .diff-del { color: #cf1322; font-weight: 600; }
2642
+
2643
+ .diff-content { flex: 1; min-width: 0; overflow-y: auto; padding: 16px; background: var(--paper); }
2644
+ .diff-file-card { background: var(--card); border: 1px solid var(--line); border-radius: 6px; overflow: hidden; box-shadow: var(--shadow-sm); }
2645
+ .diff-file-card-head { padding: 10px 14px; background: var(--paper); border-bottom: 1px solid var(--line); display: flex; justify-content: space-between; align-items: center; }
2646
+ .diff-card-title { font-family: var(--mono); font-weight: 600; font-size: 13px; }
2647
+ .diff-card-meta { font-size: 12px; color: var(--faint); font-family: var(--mono); }
2648
+
2649
+ .diff-hunk { border-bottom: 1px solid var(--line); }
2650
+ .diff-hunk:last-child { border-bottom: none; }
2651
+ .diff-hunk-header { background: rgba(128,128,128,0.08); font-family: var(--mono); font-size: 11.5px; color: var(--faint); padding: 4px 12px; border-bottom: 1px solid var(--line); }
2652
+ .diff-line { display: flex; font-family: var(--mono); font-size: 12px; line-height: 1.5; padding: 0 4px; }
2653
+ .diff-line.line-add { background: rgba(46, 93, 67, 0.12); color: var(--ink); }
2654
+ .diff-line.line-del { background: rgba(207, 19, 34, 0.1); color: var(--ink); }
2655
+ .diff-line.line-context { background: transparent; }
2656
+ .diff-ln { width: 40px; text-align: right; padding-right: 8px; color: var(--faint); user-select: none; font-size: 11px; }
2657
+ .diff-sign { width: 16px; text-align: center; color: var(--faint); user-select: none; }
2658
+ .diff-code { flex: 1; white-space: pre-wrap; word-break: break-all; }
2659
+
2660
+ .split-diff-table { display: flex; flex-direction: column; }
2661
+ .split-diff-row { display: flex; font-family: var(--mono); font-size: 12px; line-height: 1.5; }
2662
+ .split-pane { flex: 1; display: flex; min-width: 0; padding: 0 4px; border-right: 1px solid var(--line); }
2663
+ .split-pane:last-child { border-right: none; }
2664
+ .split-pane.line-add { background: rgba(46, 93, 67, 0.12); }
2665
+ .split-pane.line-del { background: rgba(207, 19, 34, 0.1); }
2666
+ .split-pane.line-empty { background: rgba(128, 128, 128, 0.04); }
2667
+
2668
+ /* ---------- CI/CD Workflows View ----------------------------------------- */
2669
+ .workflows-layout { max-width: 1000px; margin: 0 auto; padding: 24px 20px 60px; display: flex; flex-direction: column; gap: 20px; }
2670
+ .workflows-header { display: flex; justify-content: space-between; align-items: flex-end; padding-bottom: 14px; border-bottom: 1px solid var(--line); }
2671
+ .workflows-header h2 { margin: 0 0 4px; font-size: 22px; font-weight: 700; }
2672
+ .wf-sub { font-size: 12.5px; color: var(--faint); }
2673
+ .wf-count-badge { font-family: var(--mono); font-size: 12px; background: var(--card); border: 1px solid var(--line); padding: 4px 10px; border-radius: 20px; }
2674
+
2675
+ .workflow-card { background: var(--card); border: 1px solid var(--line); border-radius: 8px; padding: 20px; box-shadow: var(--shadow-sm); display: flex; flex-direction: column; gap: 16px; }
2676
+ .wf-card-top { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; flex-wrap: wrap; }
2677
+ .wf-name { font-size: 16px; font-weight: 700; display: block; }
2678
+ .wf-file-path { font-family: var(--mono); font-size: 11.5px; color: var(--faint); margin-top: 2px; display: block; }
2679
+ .wf-triggers { display: flex; align-items: center; gap: 6px; font-size: 12px; }
2680
+ .wf-trigger-label { color: var(--faint); }
2681
+ .wf-trigger-chip { font-family: var(--mono); font-size: 11px; background: var(--accent-soft); color: var(--accent); padding: 2px 8px; border-radius: 4px; font-weight: 600; border: 1px solid var(--accent); }
2682
+
2683
+ .wf-jobs-title { font-size: 12px; text-transform: uppercase; letter-spacing: 0.05em; font-weight: 700; color: var(--faint); margin-bottom: 10px; }
2684
+ .wf-jobs-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 14px; }
2685
+ .wf-job-card { background: var(--paper); border: 1px solid var(--line); border-radius: 6px; padding: 14px; display: flex; flex-direction: column; gap: 10px; }
2686
+ .wf-job-head { display: flex; justify-content: space-between; align-items: center; }
2687
+ .wf-job-name { font-weight: 700; font-size: 13.5px; }
2688
+ .wf-job-os { font-family: var(--mono); font-size: 10.5px; background: var(--card); border: 1px solid var(--line); padding: 2px 6px; border-radius: 4px; color: var(--faint); }
2689
+ .wf-job-needs { font-size: 11px; color: var(--faint); display: flex; gap: 4px; align-items: center; }
2690
+ .wf-need-tag { background: rgba(128,128,128,0.1); padding: 1px 5px; border-radius: 3px; font-family: var(--mono); }
2691
+ .wf-steps-list { display: flex; flex-direction: column; gap: 6px; }
2692
+ .wf-step-item { display: flex; align-items: center; gap: 6px; font-size: 11.5px; padding: 3px 6px; background: var(--card); border-radius: 4px; border: 1px solid var(--line); }
2693
+ .wf-step-num { color: var(--faint); font-family: var(--mono); font-size: 10px; width: 14px; }
2694
+ .wf-step-name { flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
2695
+ .wf-step-action { font-family: var(--mono); font-size: 9.5px; background: var(--accent-soft); color: var(--accent); padding: 1px 4px; border-radius: 3px; }
2696
+
2697
+ /* ---------- Security & SBOM View ----------------------------------------- */
2698
+ .sbom-layout { max-width: 1040px; margin: 0 auto; padding: 24px 20px 60px; display: flex; flex-direction: column; gap: 20px; }
2699
+ .sbom-header { display: flex; justify-content: space-between; align-items: center; gap: 16px; flex-wrap: wrap; background: var(--card); border: 1px solid var(--line); border-radius: 8px; padding: 18px 24px; box-shadow: var(--shadow-sm); }
2700
+ .sbom-lic-card { display: flex; flex-direction: column; gap: 6px; }
2701
+ .sbom-lic-label { font-size: 11px; text-transform: uppercase; letter-spacing: 0.05em; font-weight: 700; color: var(--faint); }
2702
+ .sbom-lic-val { display: flex; align-items: center; gap: 8px; }
2703
+ .sbom-lic-name { font-size: 14px; font-weight: 600; }
2704
+ .sbom-stat-cards { display: flex; gap: 8px; flex-wrap: wrap; }
2705
+ .sbom-stat-chip { font-size: 12px; background: var(--paper); border: 1px solid var(--line); padding: 6px 12px; border-radius: 6px; }
2706
+ .sbom-stat-chip.is-permissive { border-left: 3px solid #2e5d43; }
2707
+ .sbom-stat-chip.is-copyleft { border-left: 3px solid #cf1322; }
2708
+ .sbom-stat-chip.is-weak { border-left: 3px solid #b78103; }
2709
+
2710
+ .sbom-filter-bar { display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap; }
2711
+ .sbom-search-input { max-width: 320px; font-size: 12.5px; }
2712
+ .sbom-filter-chips { display: flex; gap: 4px; }
2713
+
2714
+ .sbom-table-wrap { background: var(--card); border: 1px solid var(--line); border-radius: 8px; overflow: hidden; box-shadow: var(--shadow-sm); }
2715
+ .sbom-table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
2716
+ .sbom-table th { background: var(--paper); padding: 10px 14px; text-align: left; font-size: 11.5px; color: var(--faint); font-weight: 600; border-bottom: 1px solid var(--line); }
2717
+ .sbom-table td { padding: 10px 14px; border-bottom: 1px solid var(--line); }
2718
+ .sbom-table tr:last-child td { border-bottom: none; }
2719
+ .sbom-table tr:hover td { background: var(--paper); }
2720
+ .sbom-cell-pkg { font-family: var(--mono); }
2721
+ .sbom-cell-ver code { font-family: var(--mono); font-size: 11.5px; background: var(--paper); padding: 1px 4px; border-radius: 3px; border: 1px solid var(--line); }
2722
+ .eco-tag { font-family: var(--mono); font-size: 10.5px; padding: 2px 6px; border-radius: 4px; font-weight: 600; text-transform: uppercase; }
2723
+ .eco-npm { background: #ffebee; color: #c62828; }
2724
+ .eco-pip { background: #e3f2fd; color: #1565c0; }
2725
+ .eco-go { background: #e0f2f1; color: #00695c; }
2726
+ .eco-cargo { background: #efebe9; color: #4e342e; }
2727
+ .dep-type-chip { font-family: var(--mono); font-size: 10px; padding: 1px 5px; border-radius: 3px; font-weight: 600; text-transform: uppercase; }
2728
+ .dep-type-chip.is-prod { background: var(--accent-soft); color: var(--accent); }
2729
+ .dep-type-chip.is-dev { background: rgba(128,128,128,0.1); color: var(--faint); }
2730
+ .sbom-badge { font-family: var(--mono); font-size: 11px; font-weight: 600; padding: 2px 6px; border-radius: 4px; }
2731
+ .sbom-badge.is-permissive { background: #f6ffed; color: #389e0d; border: 1px solid #b7eb8f; }
2732
+ .sbom-badge.is-copyleft { background: #fff1f0; color: #cf1322; border: 1px solid #ffa39e; }
2733
+ .sbom-badge.is-weak-copyleft { background: #fffbe6; color: #d48800; border: 1px solid #ffe58f; }
2734
+ .sbom-badge.is-public-domain { background: #e6f7ff; color: #096dd9; border: 1px solid #91d5ff; }
2735
+ .sbom-badge.is-custom, .sbom-badge.is-unknown { background: rgba(128,128,128,0.1); color: var(--faint); }
2736
+
2737
+
2738
+
2739
+ /* ---- server drawer ---- */
2740
+ /* Same drawer chrome as the AI and MCP panels; these are just the bits the
2741
+ server form adds: a two-up row for short fields, checkbox lines, and the
2742
+ one-time fresh-key reveal. */
2743
+ .server-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0 10px; }
2744
+ .server-grid .text-input { width: 100%; box-sizing: border-box; }
2745
+
2746
+ .check-row {
2747
+ display: flex; align-items: center; gap: 8px;
2748
+ font-size: 13px; color: var(--ink-2);
2749
+ margin-bottom: 10px; cursor: pointer; user-select: none;
2750
+ }
2751
+ .check-row input { accent-color: var(--accent); }
2752
+
2753
+ .server-section { margin: 18px 0 6px; }
2754
+ .server-section .field-label { margin-bottom: 8px; }
2755
+ .server-section .drawer-fine { margin: -4px 0 10px; }
2756
+
2757
+ select.text-input { appearance: auto; }
2758
+
2759
+ .server-fresh-key {
2760
+ border: 1px solid var(--accent);
2761
+ border-radius: 6px;
2762
+ padding: 10px;
2763
+ margin: 10px 0;
2764
+ background: var(--accent-soft);
2765
+ }
2766
+ .server-fresh-key .drawer-fine { margin: 0 0 8px; color: var(--ink); }
2767
+