@yss123/cage-cli 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (499) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +40 -2
  3. package/bin/cage.js +6 -0
  4. package/bin/create-cage-app.js +6 -0
  5. package/dist/analyze.d.ts +18 -0
  6. package/dist/analyze.js +28 -0
  7. package/dist/analyze.js.map +1 -0
  8. package/dist/baseline.d.ts +5 -0
  9. package/dist/baseline.js +50 -0
  10. package/dist/baseline.js.map +1 -0
  11. package/dist/budget.d.ts +7 -0
  12. package/dist/budget.js +52 -0
  13. package/dist/budget.js.map +1 -0
  14. package/dist/config.d.ts +30 -0
  15. package/dist/config.js +46 -0
  16. package/dist/config.js.map +1 -0
  17. package/dist/context.d.ts +72 -0
  18. package/dist/context.js +202 -0
  19. package/dist/context.js.map +1 -0
  20. package/dist/create-prompt.d.ts +5 -0
  21. package/dist/create-prompt.js +50 -0
  22. package/dist/create-prompt.js.map +1 -0
  23. package/dist/create.d.ts +18 -0
  24. package/dist/create.js +64 -0
  25. package/dist/create.js.map +1 -0
  26. package/dist/derive.d.ts +14 -0
  27. package/dist/derive.js +163 -0
  28. package/dist/derive.js.map +1 -0
  29. package/dist/dev.d.ts +2 -0
  30. package/dist/dev.js +116 -0
  31. package/dist/dev.js.map +1 -0
  32. package/dist/env.d.ts +1 -0
  33. package/dist/env.js +15 -0
  34. package/dist/env.js.map +1 -0
  35. package/dist/findings.d.ts +11 -0
  36. package/dist/findings.js +13 -0
  37. package/dist/findings.js.map +1 -0
  38. package/dist/gen/contracts.d.ts +6 -0
  39. package/dist/gen/contracts.js +188 -0
  40. package/dist/gen/contracts.js.map +1 -0
  41. package/dist/gen/index.d.ts +19 -0
  42. package/dist/gen/index.js +177 -0
  43. package/dist/gen/index.js.map +1 -0
  44. package/dist/gen/zod-code.d.ts +7 -0
  45. package/dist/gen/zod-code.js +163 -0
  46. package/dist/gen/zod-code.js.map +1 -0
  47. package/dist/graph-command.d.ts +11 -0
  48. package/dist/graph-command.js +67 -0
  49. package/dist/graph-command.js.map +1 -0
  50. package/dist/graph-model.d.ts +21 -0
  51. package/dist/graph-model.js +101 -0
  52. package/dist/graph-model.js.map +1 -0
  53. package/dist/graph-presentation.d.ts +11 -0
  54. package/dist/graph-presentation.js +25 -0
  55. package/dist/graph-presentation.js.map +1 -0
  56. package/dist/graph-query.d.ts +171 -0
  57. package/dist/graph-query.js +242 -0
  58. package/dist/graph-query.js.map +1 -0
  59. package/dist/graph-relations.d.ts +14 -0
  60. package/dist/graph-relations.js +142 -0
  61. package/dist/graph-relations.js.map +1 -0
  62. package/dist/graph-search.d.ts +21 -0
  63. package/dist/graph-search.js +63 -0
  64. package/dist/graph-search.js.map +1 -0
  65. package/dist/graph-snapshot.d.ts +11 -0
  66. package/dist/graph-snapshot.js +29 -0
  67. package/dist/graph-snapshot.js.map +1 -0
  68. package/dist/graph.d.ts +11 -0
  69. package/dist/graph.js +105 -0
  70. package/dist/graph.js.map +1 -0
  71. package/dist/impact.d.ts +34 -0
  72. package/dist/impact.js +235 -0
  73. package/dist/impact.js.map +1 -0
  74. package/dist/index.d.ts +20 -0
  75. package/dist/index.js +22 -0
  76. package/dist/index.js.map +1 -0
  77. package/dist/init.d.ts +6 -0
  78. package/dist/init.js +131 -0
  79. package/dist/init.js.map +1 -0
  80. package/dist/load.d.ts +6 -0
  81. package/dist/load.js +17 -0
  82. package/dist/load.js.map +1 -0
  83. package/dist/main.d.ts +1 -0
  84. package/dist/main.js +221 -0
  85. package/dist/main.js.map +1 -0
  86. package/dist/migrate.d.ts +4 -0
  87. package/dist/migrate.js +30 -0
  88. package/dist/migrate.js.map +1 -0
  89. package/dist/ontology.d.ts +43 -0
  90. package/dist/ontology.js +280 -0
  91. package/dist/ontology.js.map +1 -0
  92. package/dist/process.d.ts +6 -0
  93. package/dist/process.js +39 -0
  94. package/dist/process.js.map +1 -0
  95. package/dist/project-structure.d.ts +8 -0
  96. package/dist/project-structure.js +94 -0
  97. package/dist/project-structure.js.map +1 -0
  98. package/dist/rules.d.ts +23 -0
  99. package/dist/rules.js +251 -0
  100. package/dist/rules.js.map +1 -0
  101. package/dist/static-check.d.ts +23 -0
  102. package/dist/static-check.js +222 -0
  103. package/dist/static-check.js.map +1 -0
  104. package/dist/sync.d.ts +5 -0
  105. package/dist/sync.js +118 -0
  106. package/dist/sync.js.map +1 -0
  107. package/dist/upgrade.d.ts +10 -0
  108. package/dist/upgrade.js +81 -0
  109. package/dist/upgrade.js.map +1 -0
  110. package/dist/verify.d.ts +7 -0
  111. package/dist/verify.js +88 -0
  112. package/dist/verify.js.map +1 -0
  113. package/dist/version.d.ts +4 -0
  114. package/dist/version.js +6 -0
  115. package/dist/version.js.map +1 -0
  116. package/graph-ui/app.js +1103 -0
  117. package/graph-ui/graph-model.js +100 -0
  118. package/graph-ui/graph-relations.js +141 -0
  119. package/graph-ui/graph-search.js +62 -0
  120. package/graph-ui/index.html +197 -0
  121. package/graph-ui/model.js +83 -0
  122. package/graph-ui/relations.js +2 -0
  123. package/graph-ui/structure.js +77 -0
  124. package/graph-ui/style.css +1719 -0
  125. package/package.json +60 -3
  126. package/templates/app/.dockerignore +10 -0
  127. package/templates/app/.env.example +61 -0
  128. package/templates/app/.github/workflows/cage.yml +44 -0
  129. package/templates/app/AGENTS.md +96 -0
  130. package/templates/app/Dockerfile +25 -0
  131. package/templates/app/README.md +88 -0
  132. package/templates/app/_gitignore +8 -0
  133. package/templates/app/apps/api/package.json +16 -0
  134. package/templates/app/apps/api/src/main.ts +10 -0
  135. package/templates/app/apps/api/src/worker.ts +14 -0
  136. package/templates/app/apps/api/tsconfig.json +5 -0
  137. package/templates/app/apps/web/index.html +13 -0
  138. package/templates/app/apps/web/package.json +22 -0
  139. package/templates/app/apps/web/src/app/app.tsx +18 -0
  140. package/templates/app/apps/web/src/app/styles/global.css +663 -0
  141. package/templates/app/apps/web/src/app/workspace-layout.tsx +70 -0
  142. package/templates/app/apps/web/src/main.tsx +13 -0
  143. package/templates/app/apps/web/src/modules/approval/hooks/use-approval-tasks.ts +20 -0
  144. package/templates/app/apps/web/src/modules/approval/index.ts +2 -0
  145. package/templates/app/apps/web/src/modules/approval/pages/approval-tasks-page.tsx +54 -0
  146. package/templates/app/apps/web/src/modules/auth/index.ts +1 -0
  147. package/templates/app/apps/web/src/modules/auth/pages/login-page.tsx +59 -0
  148. package/templates/app/apps/web/src/modules/inventory/index.ts +1 -0
  149. package/templates/app/apps/web/src/modules/inventory/pages/inventory-page.tsx +74 -0
  150. package/templates/app/apps/web/src/modules/purchase/components/purchase-order-form.tsx +60 -0
  151. package/templates/app/apps/web/src/modules/purchase/index.ts +2 -0
  152. package/templates/app/apps/web/src/modules/purchase/pages/purchase-orders-page.tsx +210 -0
  153. package/templates/app/apps/web/src/shared/hooks/use-command.ts +29 -0
  154. package/templates/app/apps/web/src/shared/lib/error-message.ts +15 -0
  155. package/templates/app/apps/web/src/shared/ui/notice.tsx +13 -0
  156. package/templates/app/apps/web/src/shared/ui/page-heading.tsx +28 -0
  157. package/templates/app/apps/web/tsconfig.json +11 -0
  158. package/templates/app/apps/web/vite.config.ts +19 -0
  159. package/templates/app/cage.config.json +114 -0
  160. package/templates/app/db/migrations/0001_init.sql +112 -0
  161. package/templates/app/docs/ai/README.md +77 -0
  162. package/templates/app/docs/ai/architecture.md +122 -0
  163. package/templates/app/docs/ai/ontology-context.md +117 -0
  164. package/templates/app/docs/ai/primitives.md +249 -0
  165. package/templates/app/docs/ai/project-structure.md +123 -0
  166. package/templates/app/docs/ai/purchase-example.md +97 -0
  167. package/templates/app/docs/ai/recipes.md +81 -0
  168. package/templates/app/docs/ai/relations.md +160 -0
  169. package/templates/app/docs/ai/transfers.md +92 -0
  170. package/templates/app/docs/ai/troubleshooting.md +60 -0
  171. package/templates/app/docs/ai/workflow.md +139 -0
  172. package/templates/app/docs/errors/CAGE-APPR-001.md +47 -0
  173. package/templates/app/docs/errors/CAGE-APPR-002.md +47 -0
  174. package/templates/app/docs/errors/CAGE-APPR-003.md +47 -0
  175. package/templates/app/docs/errors/CAGE-APPR-004.md +47 -0
  176. package/templates/app/docs/errors/CAGE-APPR-005.md +47 -0
  177. package/templates/app/docs/errors/CAGE-APPR-006.md +47 -0
  178. package/templates/app/docs/errors/CAGE-APPR-007.md +50 -0
  179. package/templates/app/docs/errors/CAGE-APPR-010.md +48 -0
  180. package/templates/app/docs/errors/CAGE-AUTH-001.md +47 -0
  181. package/templates/app/docs/errors/CAGE-BUDGET-001.md +47 -0
  182. package/templates/app/docs/errors/CAGE-BUDGET-002.md +47 -0
  183. package/templates/app/docs/errors/CAGE-BUDGET-003.md +47 -0
  184. package/templates/app/docs/errors/CAGE-CMD-002.md +47 -0
  185. package/templates/app/docs/errors/CAGE-CMD-003.md +47 -0
  186. package/templates/app/docs/errors/CAGE-CONN-001.md +47 -0
  187. package/templates/app/docs/errors/CAGE-CONN-002.md +47 -0
  188. package/templates/app/docs/errors/CAGE-CONN-003.md +47 -0
  189. package/templates/app/docs/errors/CAGE-CONN-004.md +47 -0
  190. package/templates/app/docs/errors/CAGE-CONN-005.md +47 -0
  191. package/templates/app/docs/errors/CAGE-CONN-006.md +47 -0
  192. package/templates/app/docs/errors/CAGE-CONN-007.md +47 -0
  193. package/templates/app/docs/errors/CAGE-CONN-008.md +47 -0
  194. package/templates/app/docs/errors/CAGE-CONN-009.md +47 -0
  195. package/templates/app/docs/errors/CAGE-CONN-010.md +47 -0
  196. package/templates/app/docs/errors/CAGE-CONN-011.md +47 -0
  197. package/templates/app/docs/errors/CAGE-CONN-012.md +47 -0
  198. package/templates/app/docs/errors/CAGE-CREATE-001.md +52 -0
  199. package/templates/app/docs/errors/CAGE-DECL-001.md +48 -0
  200. package/templates/app/docs/errors/CAGE-DECL-002.md +47 -0
  201. package/templates/app/docs/errors/CAGE-DECL-003.md +47 -0
  202. package/templates/app/docs/errors/CAGE-DECL-004.md +47 -0
  203. package/templates/app/docs/errors/CAGE-DEP-001.md +48 -0
  204. package/templates/app/docs/errors/CAGE-DEP-002.md +47 -0
  205. package/templates/app/docs/errors/CAGE-DEP-003.md +47 -0
  206. package/templates/app/docs/errors/CAGE-DEP-004.md +47 -0
  207. package/templates/app/docs/errors/CAGE-DEP-005.md +47 -0
  208. package/templates/app/docs/errors/CAGE-DLQ-001.md +48 -0
  209. package/templates/app/docs/errors/CAGE-ENV-001.md +52 -0
  210. package/templates/app/docs/errors/CAGE-EVENT-001.md +47 -0
  211. package/templates/app/docs/errors/CAGE-EVENT-002.md +50 -0
  212. package/templates/app/docs/errors/CAGE-FIELD-001.md +47 -0
  213. package/templates/app/docs/errors/CAGE-FIELD-002.md +47 -0
  214. package/templates/app/docs/errors/CAGE-FIELD-003.md +47 -0
  215. package/templates/app/docs/errors/CAGE-FIELD-004.md +47 -0
  216. package/templates/app/docs/errors/CAGE-GEN-001.md +48 -0
  217. package/templates/app/docs/errors/CAGE-GEN-002.md +47 -0
  218. package/templates/app/docs/errors/CAGE-GRANT-001.md +49 -0
  219. package/templates/app/docs/errors/CAGE-GRANT-002.md +48 -0
  220. package/templates/app/docs/errors/CAGE-GRANT-003.md +47 -0
  221. package/templates/app/docs/errors/CAGE-IMPACT-001.md +48 -0
  222. package/templates/app/docs/errors/CAGE-INIT-001.md +47 -0
  223. package/templates/app/docs/errors/CAGE-INIT-002.md +49 -0
  224. package/templates/app/docs/errors/CAGE-INIT-003.md +48 -0
  225. package/templates/app/docs/errors/CAGE-INIT-004.md +48 -0
  226. package/templates/app/docs/errors/CAGE-JOB-001.md +47 -0
  227. package/templates/app/docs/errors/CAGE-JOB-002.md +47 -0
  228. package/templates/app/docs/errors/CAGE-JOB-003.md +47 -0
  229. package/templates/app/docs/errors/CAGE-LINT-001.md +47 -0
  230. package/templates/app/docs/errors/CAGE-MIG-001.md +47 -0
  231. package/templates/app/docs/errors/CAGE-MIG-002.md +47 -0
  232. package/templates/app/docs/errors/CAGE-MIG-003.md +5 -0
  233. package/templates/app/docs/errors/CAGE-MIG-004.md +5 -0
  234. package/templates/app/docs/errors/CAGE-MIG-005.md +47 -0
  235. package/templates/app/docs/errors/CAGE-NAME-001.md +47 -0
  236. package/templates/app/docs/errors/CAGE-NAME-002.md +47 -0
  237. package/templates/app/docs/errors/CAGE-NAME-003.md +47 -0
  238. package/templates/app/docs/errors/CAGE-NAME-004.md +47 -0
  239. package/templates/app/docs/errors/CAGE-NAME-005.md +47 -0
  240. package/templates/app/docs/errors/CAGE-NAME-006.md +47 -0
  241. package/templates/app/docs/errors/CAGE-ORG-001.md +49 -0
  242. package/templates/app/docs/errors/CAGE-PAIR-002.md +50 -0
  243. package/templates/app/docs/errors/CAGE-QUERY-001.md +47 -0
  244. package/templates/app/docs/errors/CAGE-QUERY-002.md +47 -0
  245. package/templates/app/docs/errors/CAGE-QUERY-003.md +49 -0
  246. package/templates/app/docs/errors/CAGE-REACT-001.md +47 -0
  247. package/templates/app/docs/errors/CAGE-REACT-002.md +47 -0
  248. package/templates/app/docs/errors/CAGE-READS-001.md +47 -0
  249. package/templates/app/docs/errors/CAGE-REG-001.md +53 -0
  250. package/templates/app/docs/errors/CAGE-REG-002.md +48 -0
  251. package/templates/app/docs/errors/CAGE-REG-003.md +47 -0
  252. package/templates/app/docs/errors/CAGE-REL-001.md +64 -0
  253. package/templates/app/docs/errors/CAGE-ROUTE-001.md +47 -0
  254. package/templates/app/docs/errors/CAGE-SCOPE-001.md +47 -0
  255. package/templates/app/docs/errors/CAGE-SCOPE-002.md +47 -0
  256. package/templates/app/docs/errors/CAGE-SECRET-001.md +48 -0
  257. package/templates/app/docs/errors/CAGE-SECRET-002.md +47 -0
  258. package/templates/app/docs/errors/CAGE-SENS-001.md +48 -0
  259. package/templates/app/docs/errors/CAGE-SQL-001.md +47 -0
  260. package/templates/app/docs/errors/CAGE-SQL-002.md +47 -0
  261. package/templates/app/docs/errors/CAGE-STATE-001.md +49 -0
  262. package/templates/app/docs/errors/CAGE-STATE-002.md +47 -0
  263. package/templates/app/docs/errors/CAGE-STATE-003.md +47 -0
  264. package/templates/app/docs/errors/CAGE-STATE-004.md +47 -0
  265. package/templates/app/docs/errors/CAGE-STATE-005.md +48 -0
  266. package/templates/app/docs/errors/CAGE-STATE-010.md +48 -0
  267. package/templates/app/docs/errors/CAGE-STATE-011.md +48 -0
  268. package/templates/app/docs/errors/CAGE-STRUCT-001.md +51 -0
  269. package/templates/app/docs/errors/CAGE-STRUCT-002.md +51 -0
  270. package/templates/app/docs/errors/CAGE-SYNC-001.md +48 -0
  271. package/templates/app/docs/errors/CAGE-TEST-001.md +47 -0
  272. package/templates/app/docs/errors/CAGE-UNSAFE-001.md +48 -0
  273. package/templates/app/docs/errors/CAGE-UPGRADE-001.md +48 -0
  274. package/templates/app/docs/errors/README.md +307 -0
  275. package/templates/app/docs/errors/runtime.md +50 -0
  276. package/templates/app/package.json +22 -0
  277. package/templates/app/packages/contracts/package.json +16 -0
  278. package/templates/app/packages/contracts/src/aggregates/dept/index.ts +74 -0
  279. package/templates/app/packages/contracts/src/aggregates/inventory/index.ts +57 -0
  280. package/templates/app/packages/contracts/src/aggregates/inventory-lock/index.ts +52 -0
  281. package/templates/app/packages/contracts/src/aggregates/purchase-order/index.ts +72 -0
  282. package/templates/app/packages/contracts/src/aggregates/role/index.ts +85 -0
  283. package/templates/app/packages/contracts/src/aggregates/user/index.ts +89 -0
  284. package/templates/app/packages/contracts/src/index.ts +81 -0
  285. package/templates/app/packages/contracts/src/queries/index.ts +17 -0
  286. package/templates/app/packages/contracts/tsconfig.json +5 -0
  287. package/templates/app/packages/domain/package.json +23 -0
  288. package/templates/app/packages/domain/src/index.ts +6 -0
  289. package/templates/app/packages/domain/src/integrations/erp.ts +36 -0
  290. package/templates/app/packages/domain/src/modules/inventory/index.ts +2 -0
  291. package/templates/app/packages/domain/src/modules/inventory/inventory.ts +43 -0
  292. package/templates/app/packages/domain/src/modules/purchase/approvals.ts +18 -0
  293. package/templates/app/packages/domain/src/modules/purchase/index.ts +6 -0
  294. package/templates/app/packages/domain/src/modules/purchase/jobs.ts +13 -0
  295. package/templates/app/packages/domain/src/modules/purchase/purchase-order.test.ts +137 -0
  296. package/templates/app/packages/domain/src/modules/purchase/purchase-order.ts +122 -0
  297. package/templates/app/packages/domain/src/modules/purchase/queries.ts +10 -0
  298. package/templates/app/packages/domain/src/workflows/purchase-inventory.ts +24 -0
  299. package/templates/app/packages/domain/tsconfig.json +5 -0
  300. package/templates/app/pnpm-workspace.yaml +10 -0
  301. package/templates/app/renovate.json +5 -0
  302. package/templates/app/tsconfig.base.json +8 -0
  303. package/templates/blank/.dockerignore +10 -0
  304. package/templates/blank/.env.example +61 -0
  305. package/templates/blank/.github/workflows/cage.yml +44 -0
  306. package/templates/blank/AGENTS.md +96 -0
  307. package/templates/blank/Dockerfile +25 -0
  308. package/templates/blank/README.md +37 -0
  309. package/templates/blank/_gitignore +8 -0
  310. package/templates/blank/apps/api/package.json +15 -0
  311. package/templates/blank/apps/api/src/main.ts +11 -0
  312. package/templates/blank/apps/api/src/worker.ts +8 -0
  313. package/templates/blank/apps/api/tsconfig.json +5 -0
  314. package/templates/blank/apps/web/index.html +13 -0
  315. package/templates/blank/apps/web/package.json +22 -0
  316. package/templates/blank/apps/web/src/app/app.tsx +44 -0
  317. package/templates/blank/apps/web/src/app/styles/global.css +516 -0
  318. package/templates/blank/apps/web/src/app/workspace-layout.tsx +70 -0
  319. package/templates/blank/apps/web/src/main.tsx +13 -0
  320. package/templates/blank/apps/web/src/modules/auth/index.ts +1 -0
  321. package/templates/blank/apps/web/src/modules/auth/pages/login-page.tsx +87 -0
  322. package/templates/blank/apps/web/src/modules/workspace/index.ts +1 -0
  323. package/templates/blank/apps/web/src/modules/workspace/pages/home-page.tsx +45 -0
  324. package/templates/blank/apps/web/src/shared/lib/error-message.ts +11 -0
  325. package/templates/blank/apps/web/src/shared/ui/brand.tsx +11 -0
  326. package/templates/blank/apps/web/tsconfig.json +11 -0
  327. package/templates/blank/apps/web/vite.config.ts +19 -0
  328. package/templates/blank/cage.config.json +14 -0
  329. package/templates/blank/db/migrations/0001_init.sql +63 -0
  330. package/templates/blank/docs/ai/README.md +77 -0
  331. package/templates/blank/docs/ai/architecture.md +122 -0
  332. package/templates/blank/docs/ai/ontology-context.md +117 -0
  333. package/templates/blank/docs/ai/primitives.md +249 -0
  334. package/templates/blank/docs/ai/project-structure.md +123 -0
  335. package/templates/blank/docs/ai/purchase-example.md +97 -0
  336. package/templates/blank/docs/ai/recipes.md +81 -0
  337. package/templates/blank/docs/ai/relations.md +160 -0
  338. package/templates/blank/docs/ai/transfers.md +92 -0
  339. package/templates/blank/docs/ai/troubleshooting.md +60 -0
  340. package/templates/blank/docs/ai/workflow.md +139 -0
  341. package/templates/blank/docs/errors/CAGE-APPR-001.md +47 -0
  342. package/templates/blank/docs/errors/CAGE-APPR-002.md +47 -0
  343. package/templates/blank/docs/errors/CAGE-APPR-003.md +47 -0
  344. package/templates/blank/docs/errors/CAGE-APPR-004.md +47 -0
  345. package/templates/blank/docs/errors/CAGE-APPR-005.md +47 -0
  346. package/templates/blank/docs/errors/CAGE-APPR-006.md +47 -0
  347. package/templates/blank/docs/errors/CAGE-APPR-007.md +50 -0
  348. package/templates/blank/docs/errors/CAGE-APPR-010.md +48 -0
  349. package/templates/blank/docs/errors/CAGE-AUTH-001.md +47 -0
  350. package/templates/blank/docs/errors/CAGE-BUDGET-001.md +47 -0
  351. package/templates/blank/docs/errors/CAGE-BUDGET-002.md +47 -0
  352. package/templates/blank/docs/errors/CAGE-BUDGET-003.md +47 -0
  353. package/templates/blank/docs/errors/CAGE-CMD-002.md +47 -0
  354. package/templates/blank/docs/errors/CAGE-CMD-003.md +47 -0
  355. package/templates/blank/docs/errors/CAGE-CONN-001.md +47 -0
  356. package/templates/blank/docs/errors/CAGE-CONN-002.md +47 -0
  357. package/templates/blank/docs/errors/CAGE-CONN-003.md +47 -0
  358. package/templates/blank/docs/errors/CAGE-CONN-004.md +47 -0
  359. package/templates/blank/docs/errors/CAGE-CONN-005.md +47 -0
  360. package/templates/blank/docs/errors/CAGE-CONN-006.md +47 -0
  361. package/templates/blank/docs/errors/CAGE-CONN-007.md +47 -0
  362. package/templates/blank/docs/errors/CAGE-CONN-008.md +47 -0
  363. package/templates/blank/docs/errors/CAGE-CONN-009.md +47 -0
  364. package/templates/blank/docs/errors/CAGE-CONN-010.md +47 -0
  365. package/templates/blank/docs/errors/CAGE-CONN-011.md +47 -0
  366. package/templates/blank/docs/errors/CAGE-CONN-012.md +47 -0
  367. package/templates/blank/docs/errors/CAGE-CREATE-001.md +52 -0
  368. package/templates/blank/docs/errors/CAGE-DECL-001.md +48 -0
  369. package/templates/blank/docs/errors/CAGE-DECL-002.md +47 -0
  370. package/templates/blank/docs/errors/CAGE-DECL-003.md +47 -0
  371. package/templates/blank/docs/errors/CAGE-DECL-004.md +47 -0
  372. package/templates/blank/docs/errors/CAGE-DEP-001.md +48 -0
  373. package/templates/blank/docs/errors/CAGE-DEP-002.md +47 -0
  374. package/templates/blank/docs/errors/CAGE-DEP-003.md +47 -0
  375. package/templates/blank/docs/errors/CAGE-DEP-004.md +47 -0
  376. package/templates/blank/docs/errors/CAGE-DEP-005.md +47 -0
  377. package/templates/blank/docs/errors/CAGE-DLQ-001.md +48 -0
  378. package/templates/blank/docs/errors/CAGE-ENV-001.md +52 -0
  379. package/templates/blank/docs/errors/CAGE-EVENT-001.md +47 -0
  380. package/templates/blank/docs/errors/CAGE-EVENT-002.md +50 -0
  381. package/templates/blank/docs/errors/CAGE-FIELD-001.md +47 -0
  382. package/templates/blank/docs/errors/CAGE-FIELD-002.md +47 -0
  383. package/templates/blank/docs/errors/CAGE-FIELD-003.md +47 -0
  384. package/templates/blank/docs/errors/CAGE-FIELD-004.md +47 -0
  385. package/templates/blank/docs/errors/CAGE-GEN-001.md +48 -0
  386. package/templates/blank/docs/errors/CAGE-GEN-002.md +47 -0
  387. package/templates/blank/docs/errors/CAGE-GRANT-001.md +49 -0
  388. package/templates/blank/docs/errors/CAGE-GRANT-002.md +48 -0
  389. package/templates/blank/docs/errors/CAGE-GRANT-003.md +47 -0
  390. package/templates/blank/docs/errors/CAGE-IMPACT-001.md +48 -0
  391. package/templates/blank/docs/errors/CAGE-INIT-001.md +47 -0
  392. package/templates/blank/docs/errors/CAGE-INIT-002.md +49 -0
  393. package/templates/blank/docs/errors/CAGE-INIT-003.md +48 -0
  394. package/templates/blank/docs/errors/CAGE-INIT-004.md +48 -0
  395. package/templates/blank/docs/errors/CAGE-JOB-001.md +47 -0
  396. package/templates/blank/docs/errors/CAGE-JOB-002.md +47 -0
  397. package/templates/blank/docs/errors/CAGE-JOB-003.md +47 -0
  398. package/templates/blank/docs/errors/CAGE-LINT-001.md +47 -0
  399. package/templates/blank/docs/errors/CAGE-MIG-001.md +47 -0
  400. package/templates/blank/docs/errors/CAGE-MIG-002.md +47 -0
  401. package/templates/blank/docs/errors/CAGE-MIG-003.md +5 -0
  402. package/templates/blank/docs/errors/CAGE-MIG-004.md +5 -0
  403. package/templates/blank/docs/errors/CAGE-MIG-005.md +47 -0
  404. package/templates/blank/docs/errors/CAGE-NAME-001.md +47 -0
  405. package/templates/blank/docs/errors/CAGE-NAME-002.md +47 -0
  406. package/templates/blank/docs/errors/CAGE-NAME-003.md +47 -0
  407. package/templates/blank/docs/errors/CAGE-NAME-004.md +47 -0
  408. package/templates/blank/docs/errors/CAGE-NAME-005.md +47 -0
  409. package/templates/blank/docs/errors/CAGE-NAME-006.md +47 -0
  410. package/templates/blank/docs/errors/CAGE-ORG-001.md +49 -0
  411. package/templates/blank/docs/errors/CAGE-PAIR-002.md +50 -0
  412. package/templates/blank/docs/errors/CAGE-QUERY-001.md +47 -0
  413. package/templates/blank/docs/errors/CAGE-QUERY-002.md +47 -0
  414. package/templates/blank/docs/errors/CAGE-QUERY-003.md +49 -0
  415. package/templates/blank/docs/errors/CAGE-REACT-001.md +47 -0
  416. package/templates/blank/docs/errors/CAGE-REACT-002.md +47 -0
  417. package/templates/blank/docs/errors/CAGE-READS-001.md +47 -0
  418. package/templates/blank/docs/errors/CAGE-REG-001.md +53 -0
  419. package/templates/blank/docs/errors/CAGE-REG-002.md +48 -0
  420. package/templates/blank/docs/errors/CAGE-REG-003.md +47 -0
  421. package/templates/blank/docs/errors/CAGE-REL-001.md +64 -0
  422. package/templates/blank/docs/errors/CAGE-ROUTE-001.md +47 -0
  423. package/templates/blank/docs/errors/CAGE-SCOPE-001.md +47 -0
  424. package/templates/blank/docs/errors/CAGE-SCOPE-002.md +47 -0
  425. package/templates/blank/docs/errors/CAGE-SECRET-001.md +48 -0
  426. package/templates/blank/docs/errors/CAGE-SECRET-002.md +47 -0
  427. package/templates/blank/docs/errors/CAGE-SENS-001.md +48 -0
  428. package/templates/blank/docs/errors/CAGE-SQL-001.md +47 -0
  429. package/templates/blank/docs/errors/CAGE-SQL-002.md +47 -0
  430. package/templates/blank/docs/errors/CAGE-STATE-001.md +49 -0
  431. package/templates/blank/docs/errors/CAGE-STATE-002.md +47 -0
  432. package/templates/blank/docs/errors/CAGE-STATE-003.md +47 -0
  433. package/templates/blank/docs/errors/CAGE-STATE-004.md +47 -0
  434. package/templates/blank/docs/errors/CAGE-STATE-005.md +48 -0
  435. package/templates/blank/docs/errors/CAGE-STATE-010.md +48 -0
  436. package/templates/blank/docs/errors/CAGE-STATE-011.md +48 -0
  437. package/templates/blank/docs/errors/CAGE-STRUCT-001.md +51 -0
  438. package/templates/blank/docs/errors/CAGE-STRUCT-002.md +51 -0
  439. package/templates/blank/docs/errors/CAGE-SYNC-001.md +48 -0
  440. package/templates/blank/docs/errors/CAGE-TEST-001.md +47 -0
  441. package/templates/blank/docs/errors/CAGE-UNSAFE-001.md +48 -0
  442. package/templates/blank/docs/errors/CAGE-UPGRADE-001.md +48 -0
  443. package/templates/blank/docs/errors/README.md +307 -0
  444. package/templates/blank/docs/errors/runtime.md +50 -0
  445. package/templates/blank/docs/examples/purchase-admin/README.md +5 -0
  446. package/templates/blank/docs/examples/purchase-admin/apps/api/src/main.ts +10 -0
  447. package/templates/blank/docs/examples/purchase-admin/apps/api/src/worker.ts +14 -0
  448. package/templates/blank/docs/examples/purchase-admin/apps/web/src/app/app.tsx +18 -0
  449. package/templates/blank/docs/examples/purchase-admin/apps/web/src/app/styles/global.css +663 -0
  450. package/templates/blank/docs/examples/purchase-admin/apps/web/src/app/workspace-layout.tsx +70 -0
  451. package/templates/blank/docs/examples/purchase-admin/apps/web/src/main.tsx +13 -0
  452. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/approval/hooks/use-approval-tasks.ts +20 -0
  453. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/approval/index.ts +2 -0
  454. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/approval/pages/approval-tasks-page.tsx +54 -0
  455. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/auth/index.ts +1 -0
  456. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/auth/pages/login-page.tsx +59 -0
  457. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/inventory/index.ts +1 -0
  458. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/inventory/pages/inventory-page.tsx +74 -0
  459. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/components/purchase-order-form.tsx +60 -0
  460. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/index.ts +2 -0
  461. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/pages/purchase-orders-page.tsx +210 -0
  462. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/hooks/use-command.ts +29 -0
  463. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/lib/error-message.ts +15 -0
  464. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/notice.tsx +13 -0
  465. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/page-heading.tsx +28 -0
  466. package/templates/blank/docs/examples/purchase-admin/cage.config.json +114 -0
  467. package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/aggregates/dept/index.ts +74 -0
  468. package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/aggregates/inventory/index.ts +57 -0
  469. package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/aggregates/inventory-lock/index.ts +52 -0
  470. package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/aggregates/purchase-order/index.ts +72 -0
  471. package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/aggregates/role/index.ts +85 -0
  472. package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/aggregates/user/index.ts +89 -0
  473. package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/index.ts +81 -0
  474. package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/queries/index.ts +17 -0
  475. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/index.ts +6 -0
  476. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/integrations/erp.ts +36 -0
  477. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/inventory/index.ts +2 -0
  478. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/inventory/inventory.ts +43 -0
  479. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/approvals.ts +18 -0
  480. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/index.ts +6 -0
  481. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/jobs.ts +13 -0
  482. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/purchase-order.test.ts +137 -0
  483. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/purchase-order.ts +122 -0
  484. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/queries.ts +10 -0
  485. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/workflows/purchase-inventory.ts +24 -0
  486. package/templates/blank/package.json +22 -0
  487. package/templates/blank/packages/contracts/package.json +16 -0
  488. package/templates/blank/packages/contracts/src/aggregates/dept/index.ts +74 -0
  489. package/templates/blank/packages/contracts/src/aggregates/role/index.ts +85 -0
  490. package/templates/blank/packages/contracts/src/aggregates/user/index.ts +89 -0
  491. package/templates/blank/packages/contracts/src/index.ts +55 -0
  492. package/templates/blank/packages/contracts/src/queries/index.ts +13 -0
  493. package/templates/blank/packages/contracts/tsconfig.json +5 -0
  494. package/templates/blank/packages/domain/package.json +23 -0
  495. package/templates/blank/packages/domain/src/index.ts +4 -0
  496. package/templates/blank/packages/domain/tsconfig.json +5 -0
  497. package/templates/blank/pnpm-workspace.yaml +10 -0
  498. package/templates/blank/renovate.json +5 -0
  499. package/templates/blank/tsconfig.base.json +8 -0
@@ -0,0 +1,1719 @@
1
+ /* 图谱工作台使用低饱和的纸面色与矿物绿。节点颜色承担类型区分,装饰保持克制,
2
+ 让长名称、连线和选中状态始终是画面的第一层信息。 */
3
+ :root {
4
+ font-family: 'Bahnschrift', 'Microsoft YaHei UI', 'PingFang SC', sans-serif;
5
+ color: #283d37;
6
+ background: #f6f7f3;
7
+ font-synthesis: none;
8
+ --green: #286b59;
9
+ --muted: #83918b;
10
+ --border: #e4e8e2;
11
+ --soft: #f6f8f4;
12
+ --sidebar: 216px;
13
+ }
14
+ * {
15
+ box-sizing: border-box;
16
+ }
17
+ body {
18
+ margin: 0;
19
+ }
20
+ button,
21
+ input,
22
+ a {
23
+ -webkit-tap-highlight-color: transparent;
24
+ }
25
+ button,
26
+ input {
27
+ font: inherit;
28
+ }
29
+ button,
30
+ a {
31
+ touch-action: manipulation;
32
+ }
33
+ button {
34
+ cursor: pointer;
35
+ }
36
+ button {
37
+ color: inherit;
38
+ }
39
+ button:disabled {
40
+ cursor: wait;
41
+ opacity: 0.65;
42
+ }
43
+ button:focus-visible,
44
+ a:focus-visible,
45
+ input:focus-visible {
46
+ outline: 2px solid #468b78;
47
+ outline-offset: 3px;
48
+ }
49
+ button {
50
+ border: 0;
51
+ }
52
+ a {
53
+ color: inherit;
54
+ text-decoration: none;
55
+ }
56
+ [hidden] {
57
+ display: none !important;
58
+ }
59
+ .app-shell {
60
+ min-height: 100vh;
61
+ display: grid;
62
+ grid-template-columns: var(--sidebar) minmax(0, 1fr);
63
+ grid-template-rows: 69px 1fr;
64
+ }
65
+ .topbar {
66
+ grid-column: 1/-1;
67
+ display: flex;
68
+ align-items: center;
69
+ border-bottom: 1px solid var(--border);
70
+ background: #fbfcf9;
71
+ padding: 0 29px 0 25px;
72
+ gap: 34px;
73
+ }
74
+ .brand {
75
+ width: 157px;
76
+ display: flex;
77
+ align-items: center;
78
+ gap: 12px;
79
+ }
80
+ .brand-mark {
81
+ width: 30px;
82
+ height: 30px;
83
+ border-radius: 8px;
84
+ background: #28604f;
85
+ display: grid;
86
+ grid-template-columns: repeat(2, 6px);
87
+ grid-template-rows: repeat(2, 6px);
88
+ gap: 3px;
89
+ place-content: center;
90
+ transform: rotate(-3deg);
91
+ }
92
+ .brand-mark i {
93
+ background: #c5ded3;
94
+ border-radius: 1px;
95
+ }
96
+ .brand-mark i:last-child {
97
+ background: #88b798;
98
+ }
99
+ .brand strong {
100
+ font-size: 18px;
101
+ letter-spacing: 2.4px;
102
+ }
103
+ .brand strong span {
104
+ font-size: 10px;
105
+ letter-spacing: 2.8px;
106
+ font-weight: 400;
107
+ display: block;
108
+ color: #8a9790;
109
+ margin-top: 1px;
110
+ }
111
+ .breadcrumb {
112
+ display: flex;
113
+ gap: 14px;
114
+ align-items: center;
115
+ font-size: 12px;
116
+ color: #8a9690;
117
+ }
118
+ .breadcrumb b {
119
+ font-weight: 400;
120
+ color: #c4cbc5;
121
+ }
122
+ .breadcrumb span:last-child {
123
+ color: #485e54;
124
+ }
125
+ .local-badge {
126
+ margin-left: auto;
127
+ font-size: 11px;
128
+ display: flex;
129
+ align-items: center;
130
+ gap: 7px;
131
+ padding: 6px 9px;
132
+ border: 1px solid var(--border);
133
+ border-radius: 5px;
134
+ background: white;
135
+ }
136
+ .local-badge i,
137
+ .tiny-dot {
138
+ width: 6px;
139
+ height: 6px;
140
+ background: #74a58a;
141
+ border-radius: 50%;
142
+ display: inline-block;
143
+ }
144
+ .mobile-filters {
145
+ display: none;
146
+ }
147
+ .sidebar {
148
+ padding: 28px 17px 16px;
149
+ background: #f9faf6;
150
+ border-right: 1px solid var(--border);
151
+ display: flex;
152
+ flex-direction: column;
153
+ gap: 0;
154
+ min-height: calc(100vh - 69px);
155
+ }
156
+ .section-label {
157
+ font-size: 9px;
158
+ letter-spacing: 2px;
159
+ color: #8e9b94;
160
+ display: flex;
161
+ justify-content: space-between;
162
+ padding: 0 12px;
163
+ margin-bottom: 14px;
164
+ }
165
+ .section-label span {
166
+ letter-spacing: 0;
167
+ }
168
+ .nav-active {
169
+ padding: 11px 13px;
170
+ border-radius: 6px;
171
+ background: #e8efe7;
172
+ color: #316a54;
173
+ font-size: 12px;
174
+ display: flex;
175
+ align-items: center;
176
+ gap: 10px;
177
+ font-weight: 600;
178
+ }
179
+ .nav-symbol {
180
+ font-size: 21px;
181
+ line-height: 20px;
182
+ }
183
+ .nav-dot {
184
+ width: 5px;
185
+ height: 5px;
186
+ border-radius: 50%;
187
+ background: var(--green);
188
+ margin-left: auto;
189
+ }
190
+ .sidebar-heading {
191
+ display: flex;
192
+ align-items: center;
193
+ justify-content: space-between;
194
+ font-size: 10px;
195
+ letter-spacing: 0.7px;
196
+ color: #939e97;
197
+ padding: 26px 11px 10px;
198
+ }
199
+ .sidebar-heading span {
200
+ font-size: 10px;
201
+ }
202
+ .text-button {
203
+ background: transparent;
204
+ font-size: 10px;
205
+ color: #5c8270;
206
+ padding: 2px 0;
207
+ }
208
+ .text-button:hover {
209
+ color: #225d49;
210
+ text-decoration: underline;
211
+ }
212
+ .aggregate-list {
213
+ display: grid;
214
+ gap: 3px;
215
+ }
216
+ .aggregate-button {
217
+ display: flex;
218
+ align-items: center;
219
+ gap: 8px;
220
+ width: 100%;
221
+ text-align: left;
222
+ background: transparent;
223
+ font-size: 11px;
224
+ border-radius: 5px;
225
+ padding: 10px 11px;
226
+ color: #6b7c71;
227
+ }
228
+ .aggregate-button span {
229
+ overflow: hidden;
230
+ text-overflow: ellipsis;
231
+ white-space: nowrap;
232
+ }
233
+ .aggregate-button b {
234
+ margin-left: auto;
235
+ color: #a1aaa3;
236
+ font-size: 10px;
237
+ font-weight: 400;
238
+ }
239
+ .aggregate-button.active {
240
+ color: #2d6657;
241
+ background: #eef2eb;
242
+ }
243
+ .aggregate-button:hover {
244
+ background: #eef2eb;
245
+ }
246
+ .type-filters {
247
+ display: grid;
248
+ gap: 1px;
249
+ }
250
+ .type-filter {
251
+ display: flex;
252
+ align-items: center;
253
+ gap: 8px;
254
+ padding: 6px 10px;
255
+ cursor: pointer;
256
+ font-size: 11px;
257
+ color: #5f7267;
258
+ }
259
+ .type-filter .type-dot {
260
+ width: 7px;
261
+ height: 7px;
262
+ border-radius: 2px;
263
+ }
264
+ .type-filter small {
265
+ margin-left: auto;
266
+ color: #a1aaa2;
267
+ font-size: 10px;
268
+ }
269
+ .type-filter input,
270
+ .system-toggle input {
271
+ accent-color: #3b7761;
272
+ width: 12px;
273
+ height: 12px;
274
+ margin: 0;
275
+ }
276
+ .type-filter:hover {
277
+ background: #eef2eb;
278
+ border-radius: 4px;
279
+ }
280
+ .system-toggle {
281
+ display: flex;
282
+ gap: 8px;
283
+ align-items: center;
284
+ border-top: 1px solid var(--border);
285
+ margin: 18px 10px 0;
286
+ padding-top: 17px;
287
+ font-size: 10px;
288
+ color: #6f8075;
289
+ }
290
+ .sidebar-note {
291
+ margin-top: auto;
292
+ padding: 29px 9px 18px;
293
+ display: flex;
294
+ gap: 9px;
295
+ }
296
+ .note-icon {
297
+ color: #92aa95;
298
+ font-size: 18px;
299
+ }
300
+ .sidebar-note strong {
301
+ font-size: 11px;
302
+ color: #748a79;
303
+ font-weight: 500;
304
+ }
305
+ .sidebar-note p {
306
+ font-size: 10px;
307
+ line-height: 1.9;
308
+ color: #a1aba1;
309
+ margin: 5px 0 0;
310
+ }
311
+ .sidebar-footer {
312
+ border-top: 1px solid var(--border);
313
+ font-size: 10px;
314
+ color: #8a998e;
315
+ padding: 15px 8px 0;
316
+ display: flex;
317
+ justify-content: space-between;
318
+ }
319
+ .main {
320
+ padding: 32px 30px 18px;
321
+ min-width: 0;
322
+ }
323
+ .page-heading {
324
+ display: flex;
325
+ justify-content: space-between;
326
+ align-items: center;
327
+ margin-bottom: 25px;
328
+ gap: 20px;
329
+ }
330
+ .eyebrow {
331
+ font-size: 9px;
332
+ letter-spacing: 2.5px;
333
+ color: #869c88;
334
+ margin-bottom: 10px;
335
+ }
336
+ h1 {
337
+ font-weight: 500;
338
+ font-size: 28px;
339
+ letter-spacing: 1.5px;
340
+ margin: 0;
341
+ color: #263f32;
342
+ display: flex;
343
+ align-items: center;
344
+ gap: 12px;
345
+ }
346
+ .version-tag {
347
+ font-size: 10px;
348
+ letter-spacing: 0;
349
+ font-family: Consolas, monospace;
350
+ font-weight: 400;
351
+ background: #e9eee6;
352
+ padding: 4px 6px;
353
+ border-radius: 4px;
354
+ color: #8b9e86;
355
+ }
356
+ .page-heading p {
357
+ font-size: 11px;
358
+ color: #89968b;
359
+ margin: 10px 0 0;
360
+ letter-spacing: 0.4px;
361
+ }
362
+ .heading-actions {
363
+ display: flex;
364
+ gap: 9px;
365
+ }
366
+ .button {
367
+ padding: 10px 14px;
368
+ border-radius: 6px;
369
+ font-size: 11px;
370
+ display: inline-flex;
371
+ align-items: center;
372
+ justify-content: center;
373
+ gap: 7px;
374
+ white-space: nowrap;
375
+ transition:
376
+ background 0.15s,
377
+ transform 0.15s;
378
+ }
379
+ .button:active {
380
+ transform: translateY(1px);
381
+ }
382
+ .button.primary {
383
+ background: #326e59;
384
+ color: #fff;
385
+ border: 1px solid #326e59;
386
+ box-shadow: 0 2px 3px #315b4912;
387
+ }
388
+ .button.primary:hover {
389
+ background: #245d49;
390
+ }
391
+ .button.secondary {
392
+ background: #fbfcf9;
393
+ border: 1px solid #dde4d9;
394
+ color: #697e6d;
395
+ }
396
+ .button.secondary:hover {
397
+ background: #eef3e9;
398
+ }
399
+ .button span {
400
+ font-size: 16px;
401
+ line-height: 12px;
402
+ }
403
+ .overview {
404
+ display: flex;
405
+ align-items: center;
406
+ min-height: 82px;
407
+ background: #fcfdf9;
408
+ border: 1px solid var(--border);
409
+ border-radius: 9px;
410
+ margin-bottom: 21px;
411
+ padding: 17px 25px;
412
+ gap: 26px;
413
+ }
414
+ .overview-item {
415
+ display: flex;
416
+ gap: 13px;
417
+ align-items: center;
418
+ padding-right: 26px;
419
+ border-right: 1px solid #e9ece5;
420
+ min-width: 150px;
421
+ }
422
+ .metric-icon {
423
+ width: 37px;
424
+ height: 37px;
425
+ display: grid;
426
+ place-items: center;
427
+ font-size: 22px;
428
+ border-radius: 9px;
429
+ background: #edf2e9;
430
+ color: #6b8b70;
431
+ }
432
+ .node-icon {
433
+ color: #6a859d;
434
+ background: #eef2f4;
435
+ }
436
+ .edge-icon {
437
+ color: #ac9669;
438
+ background: #f5f1e9;
439
+ }
440
+ .overview-item small {
441
+ display: block;
442
+ font-size: 10px;
443
+ color: #9aa395;
444
+ margin-bottom: 4px;
445
+ }
446
+ .overview-item strong {
447
+ font-family: 'Bahnschrift', Consolas, sans-serif;
448
+ font-size: 24px;
449
+ line-height: 1;
450
+ font-weight: 500;
451
+ color: #415845;
452
+ letter-spacing: -0.6px;
453
+ }
454
+ .overview-health {
455
+ margin-left: auto;
456
+ display: flex;
457
+ align-items: center;
458
+ gap: 10px;
459
+ }
460
+ .health-dot {
461
+ width: 7px;
462
+ height: 7px;
463
+ background: #74a17e;
464
+ border-radius: 50%;
465
+ box-shadow: 0 0 0 4px #edf4e9;
466
+ }
467
+ .health-dot.warning {
468
+ background: #c49242;
469
+ box-shadow: 0 0 0 4px #f7f0e2;
470
+ }
471
+ .overview-health strong {
472
+ display: block;
473
+ font-size: 11px;
474
+ font-weight: 400;
475
+ color: #657d61;
476
+ }
477
+ .overview-health small {
478
+ display: block;
479
+ font-size: 9px;
480
+ color: #a0aa9b;
481
+ margin-top: 6px;
482
+ }
483
+ .notice {
484
+ padding: 12px 15px;
485
+ margin-bottom: 16px;
486
+ background: #fff4e2;
487
+ border: 1px solid #e8d5b3;
488
+ color: #876c38;
489
+ border-radius: 6px;
490
+ font-size: 12px;
491
+ white-space: pre-wrap;
492
+ }
493
+ .explorer {
494
+ display: grid;
495
+ grid-template-columns: minmax(0, 1fr) 267px;
496
+ border: 1px solid #dfe5dc;
497
+ border-radius: 10px;
498
+ overflow: hidden;
499
+ background: #fff;
500
+ box-shadow: 0 7px 24px #354d3510;
501
+ height: calc(100vh - 325px);
502
+ min-height: 570px;
503
+ max-height: 1000px;
504
+ }
505
+ .graph-panel {
506
+ min-width: 0;
507
+ display: flex;
508
+ flex-direction: column;
509
+ }
510
+ .graph-toolbar {
511
+ display: flex;
512
+ align-items: center;
513
+ justify-content: space-between;
514
+ padding: 13px 17px;
515
+ border-bottom: 1px solid #edf0e9;
516
+ gap: 12px;
517
+ }
518
+ .tabs {
519
+ display: flex;
520
+ background: #f1f4ee;
521
+ border-radius: 5px;
522
+ padding: 3px;
523
+ flex-shrink: 0;
524
+ }
525
+ .tabs button {
526
+ background: transparent;
527
+ padding: 6px 10px;
528
+ font-size: 10px;
529
+ color: #8c9887;
530
+ border-radius: 4px;
531
+ }
532
+ .tabs button.active {
533
+ background: #fff;
534
+ color: #55704d;
535
+ box-shadow: 0 1px 4px #405a3412;
536
+ }
537
+ .search-wrap {
538
+ display: flex;
539
+ align-items: center;
540
+ border: 1px solid #e6ebe1;
541
+ border-radius: 5px;
542
+ background: #fff;
543
+ padding: 0 9px;
544
+ gap: 6px;
545
+ position: relative;
546
+ width: 230px;
547
+ }
548
+ .search-wrap > span {
549
+ font-size: 20px;
550
+ color: #9aab96;
551
+ }
552
+ .search-wrap input {
553
+ border: 0;
554
+ outline: none;
555
+ background: transparent;
556
+ width: 100%;
557
+ min-width: 0;
558
+ height: 30px;
559
+ font-size: 10px;
560
+ color: #3c5848;
561
+ }
562
+ .search-wrap input::placeholder {
563
+ color: #a1ad9b;
564
+ }
565
+ .search-wrap kbd {
566
+ border: 1px solid #e6eadf;
567
+ border-radius: 3px;
568
+ font-size: 9px;
569
+ padding: 1px 4px;
570
+ color: #a6afa0;
571
+ }
572
+ .search-results {
573
+ position: absolute;
574
+ z-index: 10;
575
+ top: 37px;
576
+ right: 0;
577
+ width: 320px;
578
+ max-height: 310px;
579
+ overflow: auto;
580
+ border: 1px solid var(--border);
581
+ border-radius: 7px;
582
+ background: #fff;
583
+ box-shadow: 0 8px 35px #314d3326;
584
+ padding: 5px;
585
+ }
586
+ .search-result {
587
+ display: flex;
588
+ gap: 8px;
589
+ align-items: center;
590
+ width: 100%;
591
+ text-align: left;
592
+ padding: 10px 8px;
593
+ background: white;
594
+ border-radius: 4px;
595
+ font-size: 11px;
596
+ }
597
+ .search-result:hover {
598
+ background: #f0f5eb;
599
+ }
600
+ .search-result small {
601
+ font-size: 9px;
602
+ min-width: 35px;
603
+ color: #8e9c84;
604
+ }
605
+ .search-result span {
606
+ overflow: hidden;
607
+ text-overflow: ellipsis;
608
+ }
609
+ .search-empty {
610
+ font-size: 11px;
611
+ padding: 14px;
612
+ color: #83917b;
613
+ }
614
+ .graph-subbar {
615
+ height: 39px;
616
+ display: flex;
617
+ align-items: center;
618
+ padding: 0 19px;
619
+ font-size: 10px;
620
+ color: #7e8e78;
621
+ gap: 10px;
622
+ background: #fefefc;
623
+ }
624
+ .graph-subbar > span:first-child {
625
+ display: flex;
626
+ gap: 7px;
627
+ align-items: center;
628
+ min-width: 0;
629
+ }
630
+ .graph-subbar strong {
631
+ font-weight: 500;
632
+ color: #63795b;
633
+ white-space: nowrap;
634
+ }
635
+ .graph-subbar #view-count {
636
+ color: #a8b19f;
637
+ font-size: 9px;
638
+ white-space: nowrap;
639
+ }
640
+ .drag-hint {
641
+ margin-left: auto;
642
+ font-size: 9px;
643
+ color: #a8b19f;
644
+ white-space: nowrap;
645
+ }
646
+ .canvas {
647
+ flex: 1;
648
+ min-height: 0;
649
+ position: relative;
650
+ overflow: hidden;
651
+ background-color: #fafcf8;
652
+ background-image: radial-gradient(#cdd8c6 0.7px, transparent 0.7px);
653
+ background-size: 20px 20px;
654
+ }
655
+ .canvas svg {
656
+ width: 100%;
657
+ height: 100%;
658
+ display: block;
659
+ cursor: grab;
660
+ touch-action: none;
661
+ user-select: none;
662
+ }
663
+ .canvas svg.dragging {
664
+ cursor: grabbing;
665
+ }
666
+ .canvas-signature {
667
+ position: absolute;
668
+ bottom: 19px;
669
+ left: 20px;
670
+ pointer-events: none;
671
+ color: #b4bfb0;
672
+ font-size: 8px;
673
+ letter-spacing: 1.5px;
674
+ }
675
+ .canvas-signature span {
676
+ padding: 0 4px;
677
+ color: #c4ccc0;
678
+ }
679
+ .zoom-controls {
680
+ position: absolute;
681
+ bottom: 14px;
682
+ right: 16px;
683
+ display: flex;
684
+ align-items: center;
685
+ gap: 1px;
686
+ background: #fff;
687
+ border: 1px solid #e2e8dc;
688
+ border-radius: 6px;
689
+ box-shadow: 0 3px 8px #42553308;
690
+ padding: 4px;
691
+ }
692
+ .zoom-controls button {
693
+ background: white;
694
+ width: 27px;
695
+ height: 26px;
696
+ color: #728668;
697
+ font-size: 18px;
698
+ border-radius: 3px;
699
+ }
700
+ .zoom-controls button:hover {
701
+ background: #f0f4e9;
702
+ }
703
+ .zoom-controls span {
704
+ font-family: Consolas, monospace;
705
+ font-size: 9px;
706
+ width: 37px;
707
+ text-align: center;
708
+ color: #87977b;
709
+ }
710
+ .zoom-controls i {
711
+ height: 15px;
712
+ border-left: 1px solid #e8ecdf;
713
+ margin: 0 4px;
714
+ }
715
+ .graph-footer {
716
+ height: 33px;
717
+ border-top: 1px solid #edf0e6;
718
+ font-size: 9px;
719
+ color: #9eaa93;
720
+ display: flex;
721
+ align-items: center;
722
+ justify-content: space-between;
723
+ padding: 0 17px;
724
+ background: #fdfefa;
725
+ gap: 10px;
726
+ }
727
+ .graph-footer > div {
728
+ display: flex;
729
+ align-items: center;
730
+ gap: 6px;
731
+ }
732
+ .legend-line {
733
+ display: inline-block;
734
+ width: 16px;
735
+ border-top: 1px solid #9bab91;
736
+ }
737
+ .legend-line.dashed {
738
+ border-top-style: dashed;
739
+ margin-left: 7px;
740
+ }
741
+ .edge {
742
+ fill: none;
743
+ stroke: #aebdb0;
744
+ stroke-width: 1.15;
745
+ opacity: 0.5;
746
+ transition: opacity 0.15s;
747
+ }
748
+ .edge-group.derived .edge {
749
+ stroke-dasharray: 4 4;
750
+ opacity: 0.37;
751
+ }
752
+ .edge-group.active .edge,
753
+ .edge-group:hover .edge,
754
+ .edge-group:focus-visible .edge {
755
+ stroke: #438574;
756
+ stroke-width: 1.6;
757
+ opacity: 0.95;
758
+ }
759
+ .edge-group.dim .edge {
760
+ opacity: 0.09;
761
+ }
762
+ .node {
763
+ cursor: pointer;
764
+ outline: none;
765
+ }
766
+ .node .node-box {
767
+ fill: #fff;
768
+ stroke: #dae3d7;
769
+ stroke-width: 1;
770
+ filter: drop-shadow(0 2px 3px #2e48220a);
771
+ }
772
+ .node:hover .node-box,
773
+ .node:focus-visible .node-box {
774
+ stroke: #76a489;
775
+ stroke-width: 1.7;
776
+ }
777
+ .node .selected-ring {
778
+ fill: #e5f0e9;
779
+ opacity: 0;
780
+ }
781
+ .node.selected .selected-ring {
782
+ opacity: 1;
783
+ }
784
+ .node.selected .node-box {
785
+ stroke: #3f8a70;
786
+ stroke-width: 1.6;
787
+ fill: #fcfffc;
788
+ }
789
+ .node.dim {
790
+ opacity: 0.26;
791
+ }
792
+ .node-title {
793
+ font-family: 'Bahnschrift', 'Microsoft YaHei UI', sans-serif;
794
+ font-size: 12px;
795
+ fill: #3e5447;
796
+ }
797
+ .node-subtitle {
798
+ font-family: Consolas, 'Microsoft YaHei UI', monospace;
799
+ font-size: 8.5px;
800
+ fill: #94a08e;
801
+ }
802
+ .node-code {
803
+ font-family: Consolas, monospace;
804
+ font-size: 8px;
805
+ font-weight: bold;
806
+ }
807
+ .node-indicator {
808
+ fill: #9aaa95;
809
+ }
810
+ .empty-state,
811
+ .loading-state {
812
+ position: absolute;
813
+ inset: 0;
814
+ display: flex;
815
+ align-items: center;
816
+ justify-content: center;
817
+ flex-direction: column;
818
+ background: #fafcf8f0;
819
+ gap: 10px;
820
+ text-align: center;
821
+ }
822
+ .empty-state > span {
823
+ font-size: 40px;
824
+ color: #abc0a5;
825
+ }
826
+ .empty-state strong,
827
+ .loading-state strong {
828
+ font-size: 14px;
829
+ font-weight: 500;
830
+ color: #6e8664;
831
+ }
832
+ .empty-state p {
833
+ font-size: 11px;
834
+ color: #97a58c;
835
+ margin: 0 0 8px;
836
+ }
837
+ .loader {
838
+ width: 25px;
839
+ height: 25px;
840
+ border: 2px solid #dce8d6;
841
+ border-top-color: #54845b;
842
+ border-radius: 50%;
843
+ animation: spin 1s linear infinite;
844
+ }
845
+ @keyframes spin {
846
+ to {
847
+ transform: rotate(360deg);
848
+ }
849
+ }
850
+ .inspector {
851
+ border-left: 1px solid #e5eadd;
852
+ background: #fff;
853
+ overflow: auto;
854
+ padding: 21px 20px;
855
+ }
856
+ .inspector-top {
857
+ display: flex;
858
+ align-items: center;
859
+ justify-content: space-between;
860
+ font-size: 9px;
861
+ color: #9ca992;
862
+ letter-spacing: 0.6px;
863
+ margin-bottom: 21px;
864
+ }
865
+ .inspector-icon {
866
+ width: 38px;
867
+ height: 38px;
868
+ border-radius: 9px;
869
+ display: grid;
870
+ place-items: center;
871
+ font-size: 12px;
872
+ font-family: Consolas, monospace;
873
+ font-weight: bold;
874
+ margin-bottom: 14px;
875
+ }
876
+ .inspector h2 {
877
+ font-size: 19px;
878
+ letter-spacing: -0.2px;
879
+ font-weight: 500;
880
+ overflow-wrap: anywhere;
881
+ margin: 0 0 8px;
882
+ color: #36523e;
883
+ line-height: 1.4;
884
+ }
885
+ .kind-pill {
886
+ display: inline-block;
887
+ font-size: 9px;
888
+ padding: 4px 6px;
889
+ border-radius: 4px;
890
+ margin-bottom: 12px;
891
+ }
892
+ .inspector-description {
893
+ font-size: 10px;
894
+ color: #94a08c;
895
+ line-height: 1.8;
896
+ margin: 0 0 16px;
897
+ }
898
+ .inspector-actions {
899
+ display: flex;
900
+ gap: 7px;
901
+ margin-bottom: 21px;
902
+ }
903
+ .inspector-actions button {
904
+ font-size: 10px;
905
+ padding: 8px 9px;
906
+ }
907
+ /* 交给 AI 的入口沿用纸面绿,以独立阅读块说明包含什么,避免挤进节点操作行。 */
908
+ .context-handoff {
909
+ padding: 12px;
910
+ margin: 0 0 20px;
911
+ background: #f1f6ed;
912
+ border: 1px solid #dde7d5;
913
+ border-radius: 7px;
914
+ }
915
+ .context-handoff .button {
916
+ width: 100%;
917
+ font-size: 11px;
918
+ color: #365f45;
919
+ border-color: #ceddc3;
920
+ background: #fbfdf8;
921
+ }
922
+ .context-handoff p {
923
+ margin: 9px 0 0;
924
+ font-size: 10px;
925
+ line-height: 1.8;
926
+ color: #7b8d72;
927
+ }
928
+ .detail-section {
929
+ border-top: 1px solid #edf0e7;
930
+ padding-top: 16px;
931
+ margin-top: 17px;
932
+ }
933
+ .detail-section h3 {
934
+ font-size: 10px;
935
+ font-weight: 500;
936
+ color: #839575;
937
+ margin: 0 0 12px;
938
+ display: flex;
939
+ align-items: center;
940
+ justify-content: space-between;
941
+ }
942
+ .detail-section h3 span {
943
+ font-size: 9px;
944
+ font-family: Consolas, monospace;
945
+ color: #a4b098;
946
+ }
947
+ .detail-row {
948
+ display: flex;
949
+ align-items: flex-start;
950
+ justify-content: space-between;
951
+ font-size: 10px;
952
+ gap: 10px;
953
+ line-height: 1.9;
954
+ padding: 3px 0;
955
+ }
956
+ .detail-row > span:first-child {
957
+ color: #a0ad94;
958
+ flex-shrink: 0;
959
+ }
960
+ .detail-row > span:last-child {
961
+ color: #657e55;
962
+ overflow-wrap: anywhere;
963
+ text-align: right;
964
+ max-width: 150px;
965
+ }
966
+ .source-location {
967
+ background: #f5f8f0;
968
+ border: 1px solid #e9eee0;
969
+ border-radius: 5px;
970
+ padding: 10px;
971
+ font:
972
+ 9px/1.7 Consolas,
973
+ 'Microsoft YaHei UI',
974
+ monospace;
975
+ overflow-wrap: anywhere;
976
+ color: #7b906c;
977
+ }
978
+ .source-note {
979
+ font-size: 10px;
980
+ color: #9baa8e;
981
+ line-height: 1.7;
982
+ }
983
+ .relation-button {
984
+ width: 100%;
985
+ background: transparent;
986
+ border-radius: 5px;
987
+ padding: 8px 6px;
988
+ margin: 0 -6px;
989
+ text-align: left;
990
+ display: flex;
991
+ gap: 8px;
992
+ align-items: center;
993
+ }
994
+ .relation-button:hover {
995
+ background: #f2f6ec;
996
+ }
997
+ .relation-dot {
998
+ width: 6px;
999
+ height: 6px;
1000
+ border-radius: 50%;
1001
+ flex-shrink: 0;
1002
+ }
1003
+ .relation-button div {
1004
+ min-width: 0;
1005
+ }
1006
+ .relation-button strong {
1007
+ display: block;
1008
+ overflow: hidden;
1009
+ text-overflow: ellipsis;
1010
+ white-space: nowrap;
1011
+ font-size: 10px;
1012
+ font-weight: 400;
1013
+ color: #697f59;
1014
+ }
1015
+ .relation-button small {
1016
+ display: block;
1017
+ font-size: 8px;
1018
+ color: #a3af96;
1019
+ margin-top: 4px;
1020
+ }
1021
+ .relation-button > span:last-child {
1022
+ margin-left: auto;
1023
+ font-size: 12px;
1024
+ color: #b0bba5;
1025
+ }
1026
+ .detail-json {
1027
+ white-space: pre-wrap;
1028
+ overflow-wrap: anywhere;
1029
+ font:
1030
+ 9px/1.7 Consolas,
1031
+ monospace;
1032
+ background: #f7f9f3;
1033
+ padding: 10px;
1034
+ border-radius: 5px;
1035
+ color: #7b8b6d;
1036
+ }
1037
+ .inspector details summary {
1038
+ cursor: pointer;
1039
+ font-size: 10px;
1040
+ color: #92a183;
1041
+ padding: 13px 0;
1042
+ }
1043
+ .page-footer {
1044
+ display: flex;
1045
+ justify-content: space-between;
1046
+ font-size: 9px;
1047
+ color: #9faa96;
1048
+ padding: 13px 1px 0;
1049
+ gap: 10px;
1050
+ }
1051
+ .page-footer span:first-child {
1052
+ font-family: Consolas, monospace;
1053
+ }
1054
+ .icon-button {
1055
+ background: transparent;
1056
+ border-radius: 4px;
1057
+ width: 28px;
1058
+ height: 28px;
1059
+ font-size: 18px;
1060
+ color: #91a183;
1061
+ }
1062
+ dialog {
1063
+ border: 1px solid var(--border);
1064
+ border-radius: 10px;
1065
+ padding: 24px;
1066
+ max-width: 650px;
1067
+ width: calc(100% - 40px);
1068
+ color: #37543f;
1069
+ box-shadow: 0 15px 70px #23342130;
1070
+ }
1071
+ dialog::backdrop {
1072
+ background: #263c2d44;
1073
+ backdrop-filter: blur(3px);
1074
+ }
1075
+ .dialog-heading {
1076
+ display: flex;
1077
+ align-items: center;
1078
+ justify-content: space-between;
1079
+ }
1080
+ .dialog-heading h2 {
1081
+ font-size: 19px;
1082
+ font-weight: 500;
1083
+ }
1084
+ .finding {
1085
+ padding: 15px 0;
1086
+ border-top: 1px solid var(--border);
1087
+ font-size: 12px;
1088
+ line-height: 1.8;
1089
+ }
1090
+ .finding code {
1091
+ font-size: 11px;
1092
+ color: #a4783b;
1093
+ }
1094
+ .finding p {
1095
+ margin: 5px 0;
1096
+ }
1097
+ .finding small {
1098
+ font-size: 10px;
1099
+ color: #8d9f7e;
1100
+ }
1101
+ @media (min-width: 1600px) {
1102
+ .main {
1103
+ padding: 36px 39px 18px;
1104
+ }
1105
+ .explorer {
1106
+ grid-template-columns: minmax(0, 1fr) 294px;
1107
+ }
1108
+ .inspector {
1109
+ padding: 24px;
1110
+ }
1111
+ .sidebar {
1112
+ padding-top: 32px;
1113
+ }
1114
+ .overview {
1115
+ gap: 38px;
1116
+ }
1117
+ .overview-item {
1118
+ min-width: 182px;
1119
+ }
1120
+ .page-heading {
1121
+ margin-bottom: 29px;
1122
+ }
1123
+ }
1124
+ @media (max-width: 1200px) {
1125
+ :root {
1126
+ --sidebar: 186px;
1127
+ }
1128
+ .main {
1129
+ padding: 25px 19px 15px;
1130
+ }
1131
+ .topbar {
1132
+ gap: 17px;
1133
+ }
1134
+ .brand {
1135
+ width: 144px;
1136
+ }
1137
+ .overview {
1138
+ gap: 15px;
1139
+ padding: 15px;
1140
+ }
1141
+ .overview-item {
1142
+ min-width: 110px;
1143
+ padding-right: 15px;
1144
+ gap: 9px;
1145
+ }
1146
+ .overview-health small {
1147
+ font-size: 8px;
1148
+ }
1149
+ .explorer {
1150
+ grid-template-columns: minmax(0, 1fr) 230px;
1151
+ }
1152
+ .inspector {
1153
+ padding: 17px 15px;
1154
+ }
1155
+ .graph-toolbar {
1156
+ padding: 10px;
1157
+ gap: 8px;
1158
+ }
1159
+ .tabs button {
1160
+ padding: 6px 7px;
1161
+ }
1162
+ .search-wrap {
1163
+ width: 175px;
1164
+ }
1165
+ .drag-hint {
1166
+ display: none;
1167
+ }
1168
+ .canvas-signature {
1169
+ display: none;
1170
+ }
1171
+ }
1172
+ @media (max-width: 980px) {
1173
+ :root {
1174
+ --sidebar: 175px;
1175
+ }
1176
+ .overview-health {
1177
+ display: none;
1178
+ }
1179
+ .overview {
1180
+ justify-content: space-between;
1181
+ }
1182
+ .overview-item:last-of-type {
1183
+ border: 0;
1184
+ }
1185
+ .explorer {
1186
+ grid-template-columns: minmax(0, 1fr);
1187
+ height: auto;
1188
+ max-height: none;
1189
+ min-height: 0;
1190
+ }
1191
+ .graph-panel {
1192
+ height: 600px;
1193
+ }
1194
+ .inspector {
1195
+ border-left: 0;
1196
+ border-top: 1px solid var(--border);
1197
+ max-height: 380px;
1198
+ }
1199
+ .inspector-top {
1200
+ margin-bottom: 12px;
1201
+ }
1202
+ .inspector-icon {
1203
+ float: left;
1204
+ margin-right: 13px;
1205
+ }
1206
+ .inspector h2 {
1207
+ font-size: 18px;
1208
+ }
1209
+ .detail-section {
1210
+ margin-top: 12px;
1211
+ }
1212
+ .page-footer {
1213
+ font-size: 8px;
1214
+ }
1215
+ .heading-actions .secondary {
1216
+ display: none;
1217
+ }
1218
+ }
1219
+ @media (max-width: 640px) {
1220
+ .app-shell {
1221
+ display: block;
1222
+ }
1223
+ .topbar {
1224
+ height: 62px;
1225
+ padding: 0 16px;
1226
+ }
1227
+ .brand {
1228
+ width: auto;
1229
+ }
1230
+ .brand strong {
1231
+ font-size: 15px;
1232
+ }
1233
+ .brand strong span {
1234
+ font-size: 8px;
1235
+ }
1236
+ .breadcrumb {
1237
+ display: none;
1238
+ }
1239
+ .local-badge {
1240
+ font-size: 10px;
1241
+ }
1242
+ .mobile-filters {
1243
+ display: block;
1244
+ }
1245
+ .sidebar {
1246
+ display: none;
1247
+ position: absolute;
1248
+ left: 0;
1249
+ top: 62px;
1250
+ z-index: 15;
1251
+ width: 220px;
1252
+ min-height: 0;
1253
+ max-height: calc(100vh - 62px);
1254
+ overflow: auto;
1255
+ box-shadow: 10px 10px 30px #30473120;
1256
+ }
1257
+ .sidebar.open {
1258
+ display: flex;
1259
+ }
1260
+ .sidebar-note {
1261
+ display: none;
1262
+ }
1263
+ .main {
1264
+ padding: 25px 13px 15px;
1265
+ }
1266
+ .page-heading {
1267
+ gap: 10px;
1268
+ margin-bottom: 20px;
1269
+ }
1270
+ h1 {
1271
+ font-size: 25px;
1272
+ }
1273
+ .eyebrow {
1274
+ font-size: 8px;
1275
+ }
1276
+ .page-heading p {
1277
+ font-size: 10px;
1278
+ }
1279
+ .button {
1280
+ padding: 9px 11px;
1281
+ font-size: 10px;
1282
+ }
1283
+ .overview {
1284
+ gap: 8px;
1285
+ padding: 12px;
1286
+ margin-bottom: 15px;
1287
+ min-height: 70px;
1288
+ }
1289
+ .overview-item {
1290
+ min-width: 0;
1291
+ padding-right: 13px;
1292
+ gap: 7px;
1293
+ }
1294
+ .metric-icon {
1295
+ width: 27px;
1296
+ height: 29px;
1297
+ font-size: 17px;
1298
+ }
1299
+ .overview-item strong {
1300
+ font-size: 20px;
1301
+ }
1302
+ .overview-item small {
1303
+ font-size: 8px;
1304
+ }
1305
+ .graph-toolbar {
1306
+ flex-wrap: wrap;
1307
+ gap: 10px;
1308
+ }
1309
+ .search-wrap {
1310
+ width: 100%;
1311
+ flex: 1;
1312
+ min-width: 155px;
1313
+ }
1314
+ .search-wrap kbd {
1315
+ display: none;
1316
+ }
1317
+ .search-results {
1318
+ width: 280px;
1319
+ right: -5px;
1320
+ }
1321
+ .graph-panel {
1322
+ height: 510px;
1323
+ }
1324
+ .graph-footer {
1325
+ font-size: 8px;
1326
+ padding: 0 10px;
1327
+ }
1328
+ .graph-subbar {
1329
+ padding: 0 11px;
1330
+ }
1331
+ .page-footer {
1332
+ flex-direction: column;
1333
+ gap: 6px;
1334
+ }
1335
+ .inspector {
1336
+ max-height: 440px;
1337
+ }
1338
+ }
1339
+ @media (prefers-reduced-motion: reduce) {
1340
+ *,
1341
+ *::before,
1342
+ *::after {
1343
+ animation: none !important;
1344
+ transition: none !important;
1345
+ }
1346
+ }
1347
+ /* 缩放后的节点仍需保留可辨识的主次文字,弱化背景节点但不把它们隐去。 */
1348
+ .node-title {
1349
+ font-size: 14px;
1350
+ }
1351
+ .node-subtitle {
1352
+ font-size: 10px;
1353
+ }
1354
+ .node.dim {
1355
+ opacity: 0.48;
1356
+ }
1357
+ .edge-group.dim .edge {
1358
+ opacity: 0.15;
1359
+ }
1360
+ /* 中文主标题与英文技术标识分层,长名称换行,关系列表保留足够阅读对比度。 */
1361
+ .node-code {
1362
+ font-family: 'Microsoft YaHei UI', 'PingFang SC', sans-serif;
1363
+ font-size: 11px;
1364
+ font-weight: 500;
1365
+ }
1366
+ .node-identifier {
1367
+ font:
1368
+ 10px/1.7 Consolas,
1369
+ monospace;
1370
+ color: #849581;
1371
+ overflow-wrap: anywhere;
1372
+ margin: 0 0 12px;
1373
+ }
1374
+ .search-names {
1375
+ display: flex;
1376
+ flex-direction: column;
1377
+ gap: 5px;
1378
+ min-width: 0;
1379
+ }
1380
+ .search-names strong {
1381
+ font-size: 12px;
1382
+ font-weight: 500;
1383
+ color: #47634d;
1384
+ }
1385
+ .search-names > span {
1386
+ font:
1387
+ 9px Consolas,
1388
+ monospace;
1389
+ color: #93a08e;
1390
+ overflow: hidden;
1391
+ text-overflow: ellipsis;
1392
+ }
1393
+ .relation-code {
1394
+ font-family: Consolas, monospace;
1395
+ }
1396
+ .inspector h2 {
1397
+ letter-spacing: 0.5px;
1398
+ }
1399
+ .detail-row > span:last-child {
1400
+ color: #526a49;
1401
+ }
1402
+
1403
+ /* 标签是连线的一部分:浅底隔开交叉线,选中时用深绿明确当前解释对象。
1404
+ * 概览只标注相关边,聚焦小图显示全部,避免百级关系的文字堆叠。 */
1405
+ .relation-guide {
1406
+ display: flex;
1407
+ align-items: center;
1408
+ gap: 8px;
1409
+ padding: 9px 17px;
1410
+ color: #617861;
1411
+ background: #f2f6ef;
1412
+ border-bottom: 1px solid #e4ebdf;
1413
+ font-size: 11px;
1414
+ line-height: 1.6;
1415
+ }
1416
+ .relation-guide > span:first-child {
1417
+ font-size: 17px;
1418
+ color: #3c7c65;
1419
+ }
1420
+ .edge-group {
1421
+ cursor: pointer;
1422
+ outline: none;
1423
+ }
1424
+ .edge-hit {
1425
+ fill: none;
1426
+ stroke: transparent;
1427
+ stroke-width: 16;
1428
+ pointer-events: stroke;
1429
+ }
1430
+ .edge-label {
1431
+ visibility: hidden;
1432
+ }
1433
+ .edge-label rect {
1434
+ fill: #f9fcf7;
1435
+ stroke: #d2dfce;
1436
+ stroke-width: 1;
1437
+ }
1438
+ .edge-label text {
1439
+ fill: #536c52;
1440
+ font-size: 14px;
1441
+ font-family: 'Microsoft YaHei UI', sans-serif;
1442
+ pointer-events: none;
1443
+ }
1444
+ .edge-group.show-label .edge-label,
1445
+ .edge-group:hover .edge-label,
1446
+ .edge-group:focus-visible .edge-label {
1447
+ visibility: visible;
1448
+ }
1449
+ .edge-group.dim .edge-label {
1450
+ opacity: 0.7;
1451
+ }
1452
+ .edge-group:hover .edge-label,
1453
+ .edge-group:focus-visible .edge-label {
1454
+ opacity: 1;
1455
+ }
1456
+ .edge-group:hover .edge-label rect,
1457
+ .edge-group:focus-visible .edge-label rect {
1458
+ stroke: #438574;
1459
+ stroke-width: 2;
1460
+ }
1461
+ .edge-group.chosen .edge {
1462
+ stroke-width: 2.5;
1463
+ }
1464
+ .edge-group.chosen .edge-label rect {
1465
+ fill: #357c6c;
1466
+ stroke: #357c6c;
1467
+ }
1468
+ .edge-group.chosen .edge-label text {
1469
+ fill: #fff;
1470
+ }
1471
+ .edge-group.derived .edge-label rect {
1472
+ stroke-dasharray: 3 2;
1473
+ }
1474
+ .relation-category {
1475
+ display: inline-block;
1476
+ font-size: 11px;
1477
+ color: #64816d;
1478
+ margin-bottom: 9px;
1479
+ }
1480
+ .relation-route {
1481
+ padding: 12px;
1482
+ border: 1px solid #dfe9dc;
1483
+ border-radius: 9px;
1484
+ background: #f6f9f3;
1485
+ margin: 17px 0 22px;
1486
+ }
1487
+ .relation-endpoint {
1488
+ display: flex;
1489
+ flex-direction: column;
1490
+ gap: 5px;
1491
+ width: 100%;
1492
+ text-align: left;
1493
+ background: #fff;
1494
+ border: 1px solid #e3ebdf;
1495
+ border-radius: 6px;
1496
+ padding: 10px;
1497
+ }
1498
+ .relation-endpoint:hover,
1499
+ .relation-endpoint:focus-visible {
1500
+ border-color: #55957a;
1501
+ }
1502
+ .relation-endpoint small {
1503
+ font-size: 10px;
1504
+ color: #789078;
1505
+ }
1506
+ .relation-endpoint strong {
1507
+ font-size: 13px;
1508
+ font-weight: 500;
1509
+ color: #365d47;
1510
+ }
1511
+ .relation-endpoint code {
1512
+ font:
1513
+ 10px/1.5 Consolas,
1514
+ monospace;
1515
+ color: #879782;
1516
+ overflow-wrap: anywhere;
1517
+ }
1518
+ .relation-arrow {
1519
+ display: block;
1520
+ margin: 8px 0;
1521
+ text-align: center;
1522
+ color: #5f846c;
1523
+ font-size: 11px;
1524
+ }
1525
+ .relation-explanation {
1526
+ margin: 18px 0;
1527
+ }
1528
+ .relation-explanation h3 {
1529
+ font-size: 12px;
1530
+ font-weight: 600;
1531
+ color: #365d47;
1532
+ margin: 0 0 7px;
1533
+ }
1534
+ .relation-explanation p {
1535
+ font-size: 12px;
1536
+ line-height: 1.85;
1537
+ color: #64735f;
1538
+ margin: 0;
1539
+ overflow-wrap: anywhere;
1540
+ }
1541
+ .relation-explanation .source-location {
1542
+ margin-top: 7px;
1543
+ font-size: 10px;
1544
+ }
1545
+ .relation-explanation .source-note {
1546
+ font-size: 10px;
1547
+ margin-top: 10px;
1548
+ }
1549
+
1550
+ /* 数据结构采用表卡片:较深的表头定位对象,字段行保持阅读对比度;
1551
+ * 颜色和行距呼应业务数据字典,避免几十个细碎节点造成的视觉噪声。 */
1552
+ .structure-note {
1553
+ padding: 14px 16px;
1554
+ margin: 0 12px 16px;
1555
+ border: 1px solid #e1e9d9;
1556
+ border-radius: 7px;
1557
+ background: #f3f7ec;
1558
+ color: #74856a;
1559
+ }
1560
+ .structure-note strong {
1561
+ font-size: 11px;
1562
+ font-weight: 500;
1563
+ color: #566c4b;
1564
+ }
1565
+ .structure-note p {
1566
+ font-size: 11px;
1567
+ line-height: 1.8;
1568
+ margin: 8px 0;
1569
+ }
1570
+ .structure-note small {
1571
+ font-size: 10px;
1572
+ color: #8a987e;
1573
+ }
1574
+ .table-card .table-shadow {
1575
+ fill: #e6eedf;
1576
+ opacity: 0;
1577
+ }
1578
+ .table-card.selected .table-shadow {
1579
+ opacity: 1;
1580
+ }
1581
+ .table-body {
1582
+ fill: #fafcf6;
1583
+ stroke: #d7e2cc;
1584
+ stroke-width: 1;
1585
+ filter: drop-shadow(0 5px 8px #4a613610);
1586
+ }
1587
+ .table-card.selected .table-body {
1588
+ stroke: #7e9f68;
1589
+ stroke-width: 1.5;
1590
+ }
1591
+ .table-header {
1592
+ outline: none;
1593
+ cursor: grab;
1594
+ }
1595
+ .table-header path {
1596
+ fill: #7b9b63;
1597
+ }
1598
+ .table-header:hover path,
1599
+ .table-header:focus-visible path {
1600
+ fill: #698a52;
1601
+ }
1602
+ .table-icon {
1603
+ fill: #eaf2e3;
1604
+ font-size: 21px;
1605
+ }
1606
+ .table-name {
1607
+ fill: #fff;
1608
+ font-size: 17px;
1609
+ font-weight: 600;
1610
+ font-family: 'Microsoft YaHei UI', sans-serif;
1611
+ }
1612
+ .table-id {
1613
+ fill: #e0eace;
1614
+ font:
1615
+ 11px Consolas,
1616
+ monospace;
1617
+ }
1618
+ .table-field {
1619
+ cursor: pointer;
1620
+ outline: none;
1621
+ }
1622
+ .table-field rect {
1623
+ fill: #fafcf6;
1624
+ }
1625
+ .table-field rect.alternate {
1626
+ fill: #edf4e1;
1627
+ }
1628
+ .table-field:hover rect,
1629
+ .table-field:focus-visible rect {
1630
+ fill: #e1edcf;
1631
+ }
1632
+ .table-field.selected rect {
1633
+ fill: #dae9c4;
1634
+ stroke: #8daa71;
1635
+ stroke-width: 1;
1636
+ }
1637
+ .table-field text {
1638
+ pointer-events: none;
1639
+ }
1640
+ .field-code {
1641
+ fill: #627e4e;
1642
+ font:
1643
+ 12px Consolas,
1644
+ monospace;
1645
+ }
1646
+ .field-name {
1647
+ fill: #6f875a;
1648
+ font-size: 12px;
1649
+ font-family: 'Microsoft YaHei UI', sans-serif;
1650
+ }
1651
+ .field-type {
1652
+ fill: #8fa47d;
1653
+ font:
1654
+ 10px 'Microsoft YaHei UI',
1655
+ sans-serif;
1656
+ }
1657
+ .field-ref {
1658
+ fill: #8ca371;
1659
+ font-size: 15px;
1660
+ }
1661
+ .field-dot {
1662
+ fill: #bed0a9;
1663
+ font-size: 18px;
1664
+ }
1665
+ .field-required {
1666
+ fill: #b3995d;
1667
+ font-size: 12px;
1668
+ }
1669
+ .table-footer {
1670
+ fill: #8da37a;
1671
+ font:
1672
+ 10px 'Microsoft YaHei UI',
1673
+ sans-serif;
1674
+ }
1675
+ .table-sql {
1676
+ fill: #8da37a;
1677
+ font:
1678
+ 10px Consolas,
1679
+ monospace;
1680
+ }
1681
+ .table-divider {
1682
+ stroke: #dfe8d5;
1683
+ stroke-width: 1;
1684
+ }
1685
+ .aggregate-explainer {
1686
+ padding: 12px;
1687
+ margin: 0 0 16px;
1688
+ background: #f2f6ed;
1689
+ border-left: 2px solid #98b37f;
1690
+ border-radius: 0 5px 5px 0;
1691
+ }
1692
+ .aggregate-explainer strong {
1693
+ font-size: 11px;
1694
+ font-weight: 500;
1695
+ color: #5b7649;
1696
+ }
1697
+ .aggregate-explainer p {
1698
+ font-size: 11px;
1699
+ color: #7e8f70;
1700
+ line-height: 1.85;
1701
+ margin: 7px 0 0;
1702
+ }
1703
+ @media (max-width: 1100px) {
1704
+ .graph-toolbar {
1705
+ flex-wrap: wrap;
1706
+ gap: 10px;
1707
+ }
1708
+ .graph-toolbar .search-wrap {
1709
+ flex: 1;
1710
+ min-width: 160px;
1711
+ }
1712
+ }
1713
+ /* 窄屏详情位于画布下方,随页面自然滚动,避免解释被困在一个短小的嵌套滚动区。 */
1714
+ @media (max-width: 980px) {
1715
+ .inspector:has(.relation-route) {
1716
+ max-height: none;
1717
+ overflow: visible;
1718
+ }
1719
+ }