@logictan/dsh-config-manager 0.1.60

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 (429) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +105 -0
  3. package/cordis.patch.yml +21 -0
  4. package/lib/adapters/agent-instructions.d.ts +13 -0
  5. package/lib/adapters/agent-instructions.js +46 -0
  6. package/lib/adapters/agent-presets.d.ts +13 -0
  7. package/lib/adapters/agent-presets.js +14 -0
  8. package/lib/adapters/credentials.d.ts +37 -0
  9. package/lib/adapters/credentials.js +122 -0
  10. package/lib/adapters/file-collection.d.ts +15 -0
  11. package/lib/adapters/file-collection.js +127 -0
  12. package/lib/adapters/index.d.ts +57 -0
  13. package/lib/adapters/index.js +55 -0
  14. package/lib/adapters/link-report.d.ts +16 -0
  15. package/lib/adapters/link-report.js +47 -0
  16. package/lib/adapters/mcp.d.ts +28 -0
  17. package/lib/adapters/mcp.js +178 -0
  18. package/lib/adapters/plugin-files.d.ts +18 -0
  19. package/lib/adapters/plugin-files.js +142 -0
  20. package/lib/adapters/plugins.d.ts +41 -0
  21. package/lib/adapters/plugins.js +603 -0
  22. package/lib/adapters/pnpm-workspace.d.ts +26 -0
  23. package/lib/adapters/pnpm-workspace.js +147 -0
  24. package/lib/adapters/prompts.d.ts +30 -0
  25. package/lib/adapters/prompts.js +231 -0
  26. package/lib/adapters/providers.d.ts +34 -0
  27. package/lib/adapters/providers.js +155 -0
  28. package/lib/adapters/self.d.ts +17 -0
  29. package/lib/adapters/self.js +71 -0
  30. package/lib/adapters/sessions.d.ts +14 -0
  31. package/lib/adapters/sessions.js +15 -0
  32. package/lib/adapters/settings.d.ts +28 -0
  33. package/lib/adapters/settings.js +165 -0
  34. package/lib/adapters/skills.d.ts +13 -0
  35. package/lib/adapters/skills.js +14 -0
  36. package/lib/adapters/test-helpers.d.ts +125 -0
  37. package/lib/adapters/test-helpers.js +236 -0
  38. package/lib/adapters/ui.d.ts +27 -0
  39. package/lib/adapters/ui.js +89 -0
  40. package/lib/adapters/workspaces.d.ts +13 -0
  41. package/lib/adapters/workspaces.js +106 -0
  42. package/lib/client.d.ts +1026 -0
  43. package/lib/client.js +10047 -0
  44. package/lib/core/analyzer.d.ts +99 -0
  45. package/lib/core/analyzer.js +934 -0
  46. package/lib/core/backup.d.ts +138 -0
  47. package/lib/core/backup.js +513 -0
  48. package/lib/core/boot-rescue.d.ts +146 -0
  49. package/lib/core/boot-rescue.js +618 -0
  50. package/lib/core/cache-cleaner.d.ts +31 -0
  51. package/lib/core/cache-cleaner.js +95 -0
  52. package/lib/core/config-lifecycle.d.ts +180 -0
  53. package/lib/core/config-lifecycle.js +481 -0
  54. package/lib/core/config-snapshot.d.ts +135 -0
  55. package/lib/core/config-snapshot.js +424 -0
  56. package/lib/core/config-state.d.ts +70 -0
  57. package/lib/core/config-state.js +177 -0
  58. package/lib/core/consult-source.d.ts +58 -0
  59. package/lib/core/consult-source.js +260 -0
  60. package/lib/core/crash-report.d.ts +84 -0
  61. package/lib/core/crash-report.js +317 -0
  62. package/lib/core/exporter.d.ts +68 -0
  63. package/lib/core/exporter.js +375 -0
  64. package/lib/core/ghost-sweep.d.ts +19 -0
  65. package/lib/core/ghost-sweep.js +52 -0
  66. package/lib/core/importer.d.ts +60 -0
  67. package/lib/core/importer.js +29 -0
  68. package/lib/core/index.d.ts +14 -0
  69. package/lib/core/index.js +14 -0
  70. package/lib/core/journal.d.ts +197 -0
  71. package/lib/core/journal.js +418 -0
  72. package/lib/core/local-plugin-host.d.ts +35 -0
  73. package/lib/core/local-plugin-host.js +120 -0
  74. package/lib/core/local-plugin-pack.d.ts +135 -0
  75. package/lib/core/local-plugin-pack.js +278 -0
  76. package/lib/core/messages.d.ts +310 -0
  77. package/lib/core/messages.js +621 -0
  78. package/lib/core/migration-consult.d.ts +117 -0
  79. package/lib/core/migration-consult.js +363 -0
  80. package/lib/core/migration-history.d.ts +153 -0
  81. package/lib/core/migration-history.js +411 -0
  82. package/lib/core/model-tools.d.ts +50 -0
  83. package/lib/core/model-tools.js +148 -0
  84. package/lib/core/msg-types.d.ts +8 -0
  85. package/lib/core/msg-types.js +6 -0
  86. package/lib/core/phase3-child-crash.d.ts +1 -0
  87. package/lib/core/phase3-child-crash.js +87 -0
  88. package/lib/core/phase3-host.d.ts +138 -0
  89. package/lib/core/phase3-host.js +359 -0
  90. package/lib/core/phase3-prod-child.d.ts +1 -0
  91. package/lib/core/phase3-prod-child.js +35 -0
  92. package/lib/core/phase4-crash-child.d.ts +1 -0
  93. package/lib/core/phase4-crash-child.js +103 -0
  94. package/lib/core/plugin-cli.d.ts +150 -0
  95. package/lib/core/plugin-cli.js +497 -0
  96. package/lib/core/reconcile.d.ts +120 -0
  97. package/lib/core/reconcile.js +389 -0
  98. package/lib/core/recovery-orchestrator.d.ts +94 -0
  99. package/lib/core/recovery-orchestrator.js +327 -0
  100. package/lib/core/restore.d.ts +162 -0
  101. package/lib/core/restore.js +703 -0
  102. package/lib/core/rollback.d.ts +12 -0
  103. package/lib/core/rollback.js +145 -0
  104. package/lib/core/run-registry.d.ts +85 -0
  105. package/lib/core/run-registry.js +157 -0
  106. package/lib/core/startup-barrier.d.ts +53 -0
  107. package/lib/core/startup-barrier.js +77 -0
  108. package/lib/core/types.d.ts +515 -0
  109. package/lib/core/types.js +27 -0
  110. package/lib/core/undo.d.ts +73 -0
  111. package/lib/core/undo.js +87 -0
  112. package/lib/core/validator.d.ts +18 -0
  113. package/lib/core/validator.js +77 -0
  114. package/lib/core/verify-recovery.d.ts +21 -0
  115. package/lib/core/verify-recovery.js +256 -0
  116. package/lib/core/watcher.d.ts +101 -0
  117. package/lib/core/watcher.js +219 -0
  118. package/lib/index.d.ts +238 -0
  119. package/lib/index.js +2764 -0
  120. package/lib/migrations/index.d.ts +29 -0
  121. package/lib/migrations/index.js +56 -0
  122. package/lib/migrations/v1-to-v2.d.ts +9 -0
  123. package/lib/migrations/v1-to-v2.js +10 -0
  124. package/lib/profiles/index.d.ts +4 -0
  125. package/lib/profiles/index.js +5 -0
  126. package/lib/profiles/profile-manager.d.ts +106 -0
  127. package/lib/profiles/profile-manager.js +543 -0
  128. package/lib/schema/config.d.ts +28 -0
  129. package/lib/schema/config.js +165 -0
  130. package/lib/schema/index.d.ts +24 -0
  131. package/lib/schema/index.js +26 -0
  132. package/lib/schema/manifest.d.ts +28 -0
  133. package/lib/schema/manifest.js +109 -0
  134. package/lib/schema/tombstones.d.ts +46 -0
  135. package/lib/schema/tombstones.js +64 -0
  136. package/lib/schema/types.d.ts +232 -0
  137. package/lib/schema/types.js +8 -0
  138. package/lib/schema/versions.d.ts +27 -0
  139. package/lib/schema/versions.js +50 -0
  140. package/lib/security/encryption.d.ts +85 -0
  141. package/lib/security/encryption.js +279 -0
  142. package/lib/security/index.d.ts +16 -0
  143. package/lib/security/index.js +17 -0
  144. package/lib/security/integrity.d.ts +30 -0
  145. package/lib/security/integrity.js +78 -0
  146. package/lib/security/redaction.d.ts +26 -0
  147. package/lib/security/redaction.js +95 -0
  148. package/lib/security/secret-scanner.d.ts +86 -0
  149. package/lib/security/secret-scanner.js +404 -0
  150. package/lib/security/vault.d.ts +59 -0
  151. package/lib/security/vault.js +151 -0
  152. package/lib/security/zip-security.d.ts +27 -0
  153. package/lib/security/zip-security.js +154 -0
  154. package/lib/sync/autosync-config.d.ts +39 -0
  155. package/lib/sync/autosync-config.js +151 -0
  156. package/lib/sync/autosync-scheduler.d.ts +139 -0
  157. package/lib/sync/autosync-scheduler.js +564 -0
  158. package/lib/sync/fs.d.ts +18 -0
  159. package/lib/sync/fs.js +49 -0
  160. package/lib/sync/git/git-transport.d.ts +100 -0
  161. package/lib/sync/git/git-transport.js +437 -0
  162. package/lib/sync/github-auth.d.ts +131 -0
  163. package/lib/sync/github-auth.js +264 -0
  164. package/lib/sync/layout.d.ts +43 -0
  165. package/lib/sync/layout.js +203 -0
  166. package/lib/sync/snapshot-json.d.ts +9 -0
  167. package/lib/sync/snapshot-json.js +107 -0
  168. package/lib/sync/sync-config.d.ts +81 -0
  169. package/lib/sync/sync-config.js +281 -0
  170. package/lib/sync/sync-engine.d.ts +269 -0
  171. package/lib/sync/sync-engine.js +591 -0
  172. package/lib/sync/sync-history.d.ts +42 -0
  173. package/lib/sync/sync-history.js +78 -0
  174. package/lib/sync/sync-selection.d.ts +29 -0
  175. package/lib/sync/sync-selection.js +127 -0
  176. package/lib/sync/sync-session.d.ts +40 -0
  177. package/lib/sync/sync-session.js +54 -0
  178. package/lib/sync/sync-state.d.ts +37 -0
  179. package/lib/sync/sync-state.js +108 -0
  180. package/lib/sync/transport.d.ts +75 -0
  181. package/lib/sync/transport.js +55 -0
  182. package/lib/sync/ui-prefs.d.ts +34 -0
  183. package/lib/sync/ui-prefs.js +109 -0
  184. package/lib/sync/webdav/webdav-transport.d.ts +77 -0
  185. package/lib/sync/webdav/webdav-transport.js +451 -0
  186. package/lib/ui/errors.d.ts +19 -0
  187. package/lib/ui/errors.js +81 -0
  188. package/lib/ui/export-flow.d.ts +82 -0
  189. package/lib/ui/export-flow.js +98 -0
  190. package/lib/ui/i18n.d.ts +289 -0
  191. package/lib/ui/i18n.js +581 -0
  192. package/lib/ui/migration-consult-view.d.ts +91 -0
  193. package/lib/ui/migration-consult-view.js +115 -0
  194. package/lib/ui/progress.d.ts +38 -0
  195. package/lib/ui/progress.js +87 -0
  196. package/lib/ui/report.d.ts +23 -0
  197. package/lib/ui/report.js +153 -0
  198. package/lib/ui/test-helpers.d.ts +69 -0
  199. package/lib/ui/test-helpers.js +154 -0
  200. package/lib/ui/types.d.ts +257 -0
  201. package/lib/ui/types.js +21 -0
  202. package/lib/utils/atomic-write.d.ts +88 -0
  203. package/lib/utils/atomic-write.js +399 -0
  204. package/lib/utils/env-lock.d.ts +393 -0
  205. package/lib/utils/env-lock.js +930 -0
  206. package/lib/utils/hashing.d.ts +17 -0
  207. package/lib/utils/hashing.js +41 -0
  208. package/lib/utils/json.d.ts +24 -0
  209. package/lib/utils/json.js +76 -0
  210. package/lib/utils/logger.d.ts +39 -0
  211. package/lib/utils/logger.js +82 -0
  212. package/lib/utils/paths.d.ts +42 -0
  213. package/lib/utils/paths.js +189 -0
  214. package/lib/utils/proxy.d.ts +69 -0
  215. package/lib/utils/proxy.js +455 -0
  216. package/lib/utils/recursive-walk.d.ts +24 -0
  217. package/lib/utils/recursive-walk.js +134 -0
  218. package/lib/utils/zip.d.ts +54 -0
  219. package/lib/utils/zip.js +285 -0
  220. package/package.json +188 -0
  221. package/src/adapters/agent-instructions.ts +48 -0
  222. package/src/adapters/agent-presets.ts +14 -0
  223. package/src/adapters/credentials.test.ts +90 -0
  224. package/src/adapters/credentials.ts +143 -0
  225. package/src/adapters/file-collection.ts +137 -0
  226. package/src/adapters/files.test.ts +353 -0
  227. package/src/adapters/index.ts +94 -0
  228. package/src/adapters/link-report.test.ts +65 -0
  229. package/src/adapters/link-report.ts +61 -0
  230. package/src/adapters/mcp.test.ts +96 -0
  231. package/src/adapters/mcp.ts +185 -0
  232. package/src/adapters/plugin-files.ts +146 -0
  233. package/src/adapters/plugins.test.ts +326 -0
  234. package/src/adapters/plugins.ts +615 -0
  235. package/src/adapters/pnpm-workspace.test.ts +87 -0
  236. package/src/adapters/pnpm-workspace.ts +150 -0
  237. package/src/adapters/prompts.test.ts +110 -0
  238. package/src/adapters/prompts.ts +230 -0
  239. package/src/adapters/providers.test.ts +126 -0
  240. package/src/adapters/providers.ts +173 -0
  241. package/src/adapters/roundtrip.test.ts +190 -0
  242. package/src/adapters/self.test.ts +92 -0
  243. package/src/adapters/self.ts +75 -0
  244. package/src/adapters/sessions.ts +15 -0
  245. package/src/adapters/settings.test.ts +100 -0
  246. package/src/adapters/settings.ts +187 -0
  247. package/src/adapters/skills.ts +14 -0
  248. package/src/adapters/test-helpers.ts +248 -0
  249. package/src/adapters/ui.test.ts +57 -0
  250. package/src/adapters/ui.ts +108 -0
  251. package/src/adapters/workspaces.test.ts +106 -0
  252. package/src/adapters/workspaces.ts +109 -0
  253. package/src/client/ConfigManagerSection.tsx +90 -0
  254. package/src/client/api.ts +66 -0
  255. package/src/client/client-types.ts +18 -0
  256. package/src/client/common/ErrorBanner.tsx +73 -0
  257. package/src/client/common/Icon.tsx +129 -0
  258. package/src/client/common/Modal.tsx +173 -0
  259. package/src/client/common/ToastViewport.tsx +73 -0
  260. package/src/client/common/toast-store.test.ts +192 -0
  261. package/src/client/common/toast-store.ts +181 -0
  262. package/src/client/common/toast-types.ts +7 -0
  263. package/src/client/common/ui.tsx +342 -0
  264. package/src/client/config-manager.module.css +2971 -0
  265. package/src/client/css-modules.d.ts +8 -0
  266. package/src/client/index.ts +65 -0
  267. package/src/client/locales.ts +56 -0
  268. package/src/client/lucide-icons.d.ts +38 -0
  269. package/src/client/run-store.test.ts +223 -0
  270. package/src/client/run-store.ts +372 -0
  271. package/src/client/sync/SyncConfirmView.tsx +379 -0
  272. package/src/client/sync/SyncHistoryView.test.ts +40 -0
  273. package/src/client/sync/SyncHistoryView.tsx +220 -0
  274. package/src/client/sync/SyncSettingsView.tsx +1535 -0
  275. package/src/client/sync/history-model.test.ts +194 -0
  276. package/src/client/sync/history-model.ts +195 -0
  277. package/src/client/sync/sync-api.test.ts +585 -0
  278. package/src/client/sync/sync-api.ts +543 -0
  279. package/src/client/sync/sync-locales.ts +416 -0
  280. package/src/client/sync/sync-push-preview.test.ts +52 -0
  281. package/src/client/sync/sync-view-v2.test.ts +213 -0
  282. package/src/client/sync/sync-view.test.ts +487 -0
  283. package/src/client/sync/sync-view.ts +759 -0
  284. package/src/core/analyzer.ts +1068 -0
  285. package/src/core/backup.ts +605 -0
  286. package/src/core/boot-rescue.test.ts +847 -0
  287. package/src/core/boot-rescue.ts +737 -0
  288. package/src/core/cache-cleaner.test.ts +169 -0
  289. package/src/core/cache-cleaner.ts +121 -0
  290. package/src/core/config-lifecycle.test.ts +727 -0
  291. package/src/core/config-lifecycle.ts +573 -0
  292. package/src/core/config-snapshot.test.ts +369 -0
  293. package/src/core/config-snapshot.ts +522 -0
  294. package/src/core/config-state.test.ts +381 -0
  295. package/src/core/config-state.ts +207 -0
  296. package/src/core/consult-source.test.ts +199 -0
  297. package/src/core/consult-source.ts +293 -0
  298. package/src/core/crash-report.test.ts +380 -0
  299. package/src/core/crash-report.ts +369 -0
  300. package/src/core/exporter.ts +417 -0
  301. package/src/core/ghost-sweep.test.ts +94 -0
  302. package/src/core/ghost-sweep.ts +67 -0
  303. package/src/core/importer.ts +83 -0
  304. package/src/core/index.ts +56 -0
  305. package/src/core/journal.test.ts +257 -0
  306. package/src/core/journal.ts +518 -0
  307. package/src/core/local-plugin-host.ts +152 -0
  308. package/src/core/local-plugin-pack.test.ts +359 -0
  309. package/src/core/local-plugin-pack.ts +363 -0
  310. package/src/core/messages.test.ts +54 -0
  311. package/src/core/messages.ts +664 -0
  312. package/src/core/migration-consult.test.ts +315 -0
  313. package/src/core/migration-consult.ts +494 -0
  314. package/src/core/migration-history.test.ts +319 -0
  315. package/src/core/migration-history.ts +484 -0
  316. package/src/core/model-tools.test.ts +190 -0
  317. package/src/core/model-tools.ts +208 -0
  318. package/src/core/msg-types.ts +10 -0
  319. package/src/core/phase3-child-crash.ts +95 -0
  320. package/src/core/phase3-host.ts +411 -0
  321. package/src/core/phase3-p1.test.ts +212 -0
  322. package/src/core/phase3-p2b-fingerprint.test.ts +189 -0
  323. package/src/core/phase3-prod-child.ts +36 -0
  324. package/src/core/phase3-production-integration.test.ts +286 -0
  325. package/src/core/phase4-crash-child.ts +101 -0
  326. package/src/core/phase4-crash-injection.test.ts +166 -0
  327. package/src/core/plugin-cli.fs.test.ts +184 -0
  328. package/src/core/plugin-cli.test.ts +137 -0
  329. package/src/core/plugin-cli.ts +563 -0
  330. package/src/core/reconcile.test.ts +392 -0
  331. package/src/core/reconcile.ts +498 -0
  332. package/src/core/recovery-orchestrator.test.ts +145 -0
  333. package/src/core/recovery-orchestrator.ts +366 -0
  334. package/src/core/restore-manage.test.ts +94 -0
  335. package/src/core/restore.ts +849 -0
  336. package/src/core/rollback.ts +151 -0
  337. package/src/core/run-progress.test.ts +237 -0
  338. package/src/core/run-registry.test.ts +232 -0
  339. package/src/core/run-registry.ts +209 -0
  340. package/src/core/smoke.test.ts +842 -0
  341. package/src/core/startup-barrier.ts +99 -0
  342. package/src/core/types.ts +542 -0
  343. package/src/core/undo.ts +116 -0
  344. package/src/core/validator.ts +84 -0
  345. package/src/core/verify-recovery.ts +265 -0
  346. package/src/core/watcher.test.ts +326 -0
  347. package/src/core/watcher.ts +263 -0
  348. package/src/index.facade.test.ts +265 -0
  349. package/src/index.sync.test.ts +217 -0
  350. package/src/index.ts +2975 -0
  351. package/src/migrations/index.ts +71 -0
  352. package/src/migrations/v1-to-v2.ts +17 -0
  353. package/src/profiles/index.ts +8 -0
  354. package/src/profiles/profile-manager.test.ts +282 -0
  355. package/src/profiles/profile-manager.ts +630 -0
  356. package/src/schema/config.ts +165 -0
  357. package/src/schema/index.ts +71 -0
  358. package/src/schema/manifest-schema.test.ts +519 -0
  359. package/src/schema/manifest.ts +124 -0
  360. package/src/schema/tombstones.test.ts +131 -0
  361. package/src/schema/tombstones.ts +89 -0
  362. package/src/schema/types.ts +245 -0
  363. package/src/schema/versions.ts +55 -0
  364. package/src/security/encryption.ts +335 -0
  365. package/src/security/index.ts +16 -0
  366. package/src/security/integrity.ts +102 -0
  367. package/src/security/redaction.ts +101 -0
  368. package/src/security/secret-scanner.ts +445 -0
  369. package/src/security/security.test.ts +1215 -0
  370. package/src/security/vault.test.ts +164 -0
  371. package/src/security/vault.ts +198 -0
  372. package/src/security/zip-security.ts +180 -0
  373. package/src/sync/autosync-config.test.ts +147 -0
  374. package/src/sync/autosync-config.ts +179 -0
  375. package/src/sync/autosync-scheduler.test.ts +490 -0
  376. package/src/sync/autosync-scheduler.ts +646 -0
  377. package/src/sync/fs.ts +48 -0
  378. package/src/sync/git/git-transport.test.ts +673 -0
  379. package/src/sync/git/git-transport.ts +491 -0
  380. package/src/sync/github-auth.test.ts +280 -0
  381. package/src/sync/github-auth.ts +356 -0
  382. package/src/sync/layout.test.ts +270 -0
  383. package/src/sync/layout.ts +222 -0
  384. package/src/sync/snapshot-json.test.ts +119 -0
  385. package/src/sync/snapshot-json.ts +128 -0
  386. package/src/sync/sync-config.test.ts +310 -0
  387. package/src/sync/sync-config.ts +299 -0
  388. package/src/sync/sync-engine.test.ts +1074 -0
  389. package/src/sync/sync-engine.ts +754 -0
  390. package/src/sync/sync-history.test.ts +116 -0
  391. package/src/sync/sync-history.ts +120 -0
  392. package/src/sync/sync-selection.test.ts +186 -0
  393. package/src/sync/sync-selection.ts +143 -0
  394. package/src/sync/sync-session.test.ts +143 -0
  395. package/src/sync/sync-session.ts +77 -0
  396. package/src/sync/sync-state.test.ts +164 -0
  397. package/src/sync/sync-state.ts +131 -0
  398. package/src/sync/transport.test.ts +111 -0
  399. package/src/sync/transport.ts +118 -0
  400. package/src/sync/ui-prefs.test.ts +152 -0
  401. package/src/sync/ui-prefs.ts +135 -0
  402. package/src/sync/webdav/webdav-transport.test.ts +871 -0
  403. package/src/sync/webdav/webdav-transport.ts +535 -0
  404. package/src/ui/errors.test.ts +47 -0
  405. package/src/ui/errors.ts +100 -0
  406. package/src/ui/export-flow.test.ts +87 -0
  407. package/src/ui/export-flow.ts +156 -0
  408. package/src/ui/i18n.ts +590 -0
  409. package/src/ui/migration-consult-view.test.ts +151 -0
  410. package/src/ui/migration-consult-view.ts +178 -0
  411. package/src/ui/progress.test.ts +47 -0
  412. package/src/ui/progress.ts +102 -0
  413. package/src/ui/report.test.ts +101 -0
  414. package/src/ui/report.ts +146 -0
  415. package/src/ui/test-helpers.ts +184 -0
  416. package/src/ui/types.ts +325 -0
  417. package/src/utils/atomic-write.test.ts +312 -0
  418. package/src/utils/atomic-write.ts +422 -0
  419. package/src/utils/env-lock.test.ts +999 -0
  420. package/src/utils/env-lock.ts +1086 -0
  421. package/src/utils/hashing.ts +53 -0
  422. package/src/utils/json.ts +77 -0
  423. package/src/utils/logger.ts +114 -0
  424. package/src/utils/paths.ts +176 -0
  425. package/src/utils/proxy.test.ts +465 -0
  426. package/src/utils/proxy.ts +493 -0
  427. package/src/utils/recursive-walk.test.ts +148 -0
  428. package/src/utils/recursive-walk.ts +145 -0
  429. package/src/utils/zip.ts +332 -0
@@ -0,0 +1,2971 @@
1
+ /**
2
+ * dsh-config-manager — Workbench Design System(2026-09 Full UI Rebuild)
3
+ *
4
+ * 定位:DSH settings.section 内嵌工作台(画布 ≈ 564 × 720,800px 设置弹窗内)。
5
+ * 设计语言:高密度开发者工具(参考 Linear/Raycast/VS Code settings 的信息密度),
6
+ * 零硬编码颜色 —— 全部走 DSH Design System 的 --dsw-* token(跟随亮/暗主题与皮肤)。
7
+ *
8
+ * 分层结构:
9
+ * §1 Tokens & Base —— 尺寸/字号/焦点基础
10
+ * §2 Shell —— 导航条 / 页面工具栏 / 状态栏 / 内容区
11
+ * §3 Primitives —— Button / Input / Select / Checkbox / Badge / Banner / Spinner
12
+ * §4 Surfaces —— Card / 分组 / 字段 / 空态
13
+ * §5 Data Display —— 表格 / 统计块 / 键值行 / Stepper / 进度
14
+ * §6 Overlays —— Dialog / Drawer
15
+ * §7 Page: Overview —— 控制中心
16
+ * §8 Page: Backups —— 备份/快照/定时/恢复
17
+ * §9 Page: Export / Import —— 迁移工作流(含冲突/路径映射/密钥补录/日志)
18
+ * §10 Page: Sync —— 远程同步
19
+ * §11 Page: Market —— 配置市场 / 我的配置
20
+ * §12 Page: Profiles —— 配置档案
21
+ * §13 Page: History / About —— 活动抽屉 / 关于
22
+ * §14 Responsive —— 窄弹窗降级
23
+ */
24
+
25
+ /* ================================================================ §1 Tokens & Base */
26
+
27
+ .section {
28
+ display: flex;
29
+ flex-direction: column;
30
+ height: 100%;
31
+ min-height: 0;
32
+ font-family: var(--dsw-font-family);
33
+ font-size: 12.5px;
34
+ line-height: 1.5;
35
+ color: var(--dsw-alias-label-primary);
36
+ /* 弹窗内容区内的滚动包容:本组件自己管理滚动,不外溢 */
37
+ overflow: hidden;
38
+ /* Toast 视口的定位上下文(见 §6 Overlays 的 .toastViewport):
39
+ 通知层必须留在插件自己的层叠上下文内(宿主 overlay z-index 1000),
40
+ 故用绝对定位贴合本根节点,而非 Portal 到 body。 */
41
+ position: relative;
42
+ }
43
+
44
+ /* 交互过渡统一参数(hover/focus 颜色过渡;仅颜色属性,克制) */
45
+ .section :is(button, a, input, select, textarea, [role='tab']) {
46
+ transition-property: background-color, border-color, color;
47
+ transition-duration: 120ms;
48
+ transition-timing-function: ease;
49
+ }
50
+
51
+ /* 键盘焦点环:仅键盘导航(:focus-visible)触发 */
52
+ .section :is(button, a, input, select, textarea, [role='tab']):focus-visible {
53
+ outline: 2px solid var(--dsw-alias-state-business-primary);
54
+ outline-offset: 2px;
55
+ }
56
+
57
+ /* 等宽栈:路径 / 命令 / 值 / 日志(数字等宽对齐) */
58
+ .mono {
59
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
60
+ font-variant-numeric: tabular-nums;
61
+ }
62
+
63
+ /* Lucide 图标统一行为:继承文字色(跟随 --dsw-* token / data-danger / hover),
64
+ 在 flex 容器(按钮/行)内不收缩、垂直居中,描边与正文视觉重量匹配。 */
65
+ .section svg {
66
+ flex: none;
67
+ color: inherit;
68
+ }
69
+
70
+ /* 键盘提示 */
71
+ .kbd {
72
+ display: inline-block;
73
+ padding: 0 5px;
74
+ border: 1px solid var(--dsw-alias-border-l2);
75
+ border-bottom-width: 2px;
76
+ border-radius: 4px;
77
+ background: var(--dsw-alias-bg-layer-2);
78
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
79
+ font-size: 10.5px;
80
+ line-height: 16px;
81
+ color: var(--dsw-alias-label-secondary);
82
+ }
83
+
84
+ /* ================================================================ §2 Shell */
85
+
86
+ /* —— 顶部导航条:左侧页签(圆角分段条),右侧图标动作 ——
87
+ 刻意**不铺背景色**:宿主设置面板底色随主题变化(暗色面板 = #2c2c2e,
88
+ 而 --dsw-alias-bg-base = #151517),铺底色会在导航条两侧形成一条比面板更暗的
89
+ 通栏色块(亮色下两者同为 #fff 才看不出来)。页签分组感由 .navStrip 自身的
90
+ 底色 + 描边承担,与底部 .statusBar 的「不铺底色」保持一致。 */
91
+ .shellNav {
92
+ display: flex;
93
+ align-items: center;
94
+ gap: 8px;
95
+ flex: none;
96
+ padding: 8px;
97
+ }
98
+
99
+ .navStrip {
100
+ display: flex;
101
+ align-items: center;
102
+ gap: 2px;
103
+ flex: 1 1 auto;
104
+ min-width: 0;
105
+ padding: 2px;
106
+ border: 1px solid var(--dsw-alias-border-l1);
107
+ border-radius: 8px;
108
+ background: var(--dsw-alias-bg-layer-2);
109
+ overflow-x: auto;
110
+ scrollbar-width: none;
111
+ }
112
+
113
+ .navStrip::-webkit-scrollbar {
114
+ display: none;
115
+ }
116
+
117
+ /* 页签:分段条内的圆角药丸,激活态 = 主色淡底 + 主色描边 */
118
+ .navTab {
119
+ position: relative;
120
+ display: inline-flex;
121
+ align-items: center;
122
+ gap: 5px;
123
+ flex: none;
124
+ height: 24px;
125
+ padding: 0 10px;
126
+ border: none;
127
+ border-radius: 6px;
128
+ background: none;
129
+ font: inherit;
130
+ font-size: 12px;
131
+ font-weight: 500;
132
+ color: var(--dsw-alias-label-secondary);
133
+ cursor: pointer;
134
+ white-space: nowrap;
135
+ }
136
+
137
+ .navTab:hover {
138
+ color: var(--dsw-alias-label-primary);
139
+ background: var(--dsw-alias-interactive-bg-hover);
140
+ }
141
+
142
+ .navTab:focus-visible {
143
+ outline: 2px solid var(--dsw-alias-state-business-primary);
144
+ outline-offset: 1px;
145
+ border-radius: 6px;
146
+ }
147
+
148
+ .navTab[data-active] {
149
+ background: color-mix(in srgb, var(--dsw-alias-state-business-primary) 16%, transparent);
150
+ box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--dsw-alias-state-business-primary) 45%, transparent);
151
+ color: var(--dsw-alias-label-primary);
152
+ font-weight: 600;
153
+ }
154
+
155
+ /* 页签上的告警点(如恢复待处理) */
156
+ .navDot {
157
+ width: 6px;
158
+ height: 6px;
159
+ border-radius: 50%;
160
+ background: var(--dsw-alias-state-error-primary);
161
+ flex: none;
162
+ }
163
+
164
+ /* 导航条右侧图标动作 */
165
+ .navActions {
166
+ display: flex;
167
+ align-items: center;
168
+ gap: 4px;
169
+ flex: none;
170
+ margin-left: 4px;
171
+ }
172
+
173
+ /* 导航条动作按钮激活态(抽屉打开时对应按钮高亮) */
174
+ .navActions .ghostButton[data-active] {
175
+ border-color: color-mix(in srgb, var(--dsw-alias-state-business-primary) 55%, transparent);
176
+ color: var(--dsw-alias-state-business-primary);
177
+ }
178
+
179
+ /* —— 图标按钮(工具栏/导航通用) —— */
180
+ .iconBtn {
181
+ display: inline-flex;
182
+ align-items: center;
183
+ justify-content: center;
184
+ width: 26px;
185
+ height: 26px;
186
+ padding: 0;
187
+ border: none;
188
+ border-radius: 6px;
189
+ background: none;
190
+ font: inherit;
191
+ font-size: 14px;
192
+ line-height: 1;
193
+ color: var(--dsw-alias-label-secondary);
194
+ cursor: pointer;
195
+ align-self: center;
196
+ }
197
+
198
+ .iconBtn:hover {
199
+ background: var(--dsw-alias-interactive-bg-hover);
200
+ color: var(--dsw-alias-label-primary);
201
+ }
202
+
203
+ .iconBtn:focus-visible {
204
+ outline: 2px solid var(--dsw-alias-state-business-primary);
205
+ outline-offset: 1px;
206
+ }
207
+
208
+ .iconBtn:disabled {
209
+ opacity: 0.45;
210
+ cursor: default;
211
+ }
212
+
213
+ .iconBtn[data-active] {
214
+ background: color-mix(in srgb, var(--dsw-alias-state-business-primary) 14%, transparent);
215
+ color: var(--dsw-alias-state-business-primary);
216
+ }
217
+
218
+ /* 危险语义图标按钮(行内删除等破坏性动作的视觉隔离) */
219
+ .iconBtn[data-danger] {
220
+ color: var(--dsw-alias-state-error-primary);
221
+ }
222
+
223
+ .iconBtn[data-danger]:hover {
224
+ background: color-mix(in srgb, var(--dsw-alias-state-error-primary) 12%, transparent);
225
+ border-color: var(--dsw-alias-state-error-primary);
226
+ color: var(--dsw-alias-state-error-primary);
227
+ }
228
+
229
+ /* 行内动作分隔(安全操作与破坏性操作之间的 1px 竖线) */
230
+ .rowDivider {
231
+ width: 1px;
232
+ height: 14px;
233
+ background: var(--dsw-alias-border-l2);
234
+ margin: 0 2px;
235
+ flex: none;
236
+ align-self: center;
237
+ }
238
+
239
+ /* —— 页面主体(滚动区):flex 链让页面内容可伸展填满视口高度 —— */
240
+ .shellMain {
241
+ flex: 1 1 auto;
242
+ min-height: 0;
243
+ overflow-y: auto;
244
+ overscroll-behavior: contain;
245
+ display: flex;
246
+ flex-direction: column;
247
+ }
248
+
249
+ /* 页面内容统一内边距(flex 链中层:撑满 shellMain,让 viewBody 能 flex 填充) */
250
+ .pagePad {
251
+ flex: 1 1 auto;
252
+ display: flex;
253
+ flex-direction: column;
254
+ min-height: 0;
255
+ padding: 12px 16px 16px;
256
+ }
257
+
258
+ /* —— 底部状态栏:与顶部页签条同款(圆角分段条 + 四周留白,不再通栏贴边) —— */
259
+ .statusBar {
260
+ display: flex;
261
+ align-items: center;
262
+ gap: 10px;
263
+ flex: none;
264
+ height: 28px;
265
+ margin: 0 8px 8px;
266
+ padding: 0 10px;
267
+ border: 1px solid var(--dsw-alias-border-l1);
268
+ border-radius: 8px;
269
+ background: var(--dsw-alias-bg-layer-2);
270
+ font-size: 11px;
271
+ color: var(--dsw-alias-label-tertiary);
272
+ white-space: nowrap;
273
+ overflow: hidden;
274
+ }
275
+
276
+ .statusDot {
277
+ display: inline-block;
278
+ width: 7px;
279
+ height: 7px;
280
+ border-radius: 50%;
281
+ background: var(--dsw-alias-label-tertiary);
282
+ flex: none;
283
+ }
284
+
285
+ .statusDot[data-kind='ok'] {
286
+ background: var(--dsw-alias-state-success-primary);
287
+ }
288
+
289
+ .statusDot[data-kind='info'] {
290
+ background: var(--dsw-alias-state-business-primary);
291
+ }
292
+
293
+ .statusDot[data-kind='warn'] {
294
+ background: var(--dsw-alias-state-warn-primary);
295
+ }
296
+
297
+ .statusDot[data-kind='error'] {
298
+ background: var(--dsw-alias-state-error-primary);
299
+ }
300
+
301
+ .statusDot[data-pulse] {
302
+ animation: statusPulse 1.2s ease-in-out infinite;
303
+ }
304
+
305
+ @keyframes statusPulse {
306
+ 0%, 100% { opacity: 1; }
307
+ 50% { opacity: 0.35; }
308
+ }
309
+
310
+ .statusText {
311
+ overflow: hidden;
312
+ text-overflow: ellipsis;
313
+ }
314
+
315
+ .statusSpacer {
316
+ flex: 1 1 auto;
317
+ }
318
+
319
+ .statusMeta {
320
+ flex: none;
321
+ color: var(--dsw-alias-label-tertiary);
322
+ }
323
+
324
+ /* ================================================================ §3 Primitives */
325
+
326
+ /* —— 按钮 —— */
327
+ .primaryButton,
328
+ .ghostButton,
329
+ .dangerButton {
330
+ display: inline-flex;
331
+ align-items: center;
332
+ justify-content: center;
333
+ gap: 6px;
334
+ height: 28px;
335
+ padding: 0 12px;
336
+ border-radius: 6px;
337
+ border: 1px solid transparent;
338
+ font: inherit;
339
+ font-size: 12.5px;
340
+ font-weight: 600;
341
+ line-height: 1;
342
+ white-space: nowrap;
343
+ cursor: pointer;
344
+ user-select: none;
345
+ }
346
+
347
+ .primaryButton {
348
+ background: var(--dsw-alias-button-info-fill);
349
+ color: var(--dsw-alias-label-primary-foreground);
350
+ }
351
+
352
+ .primaryButton:hover:not(:disabled) {
353
+ background: var(--dsw-alias-button-info-hover);
354
+ }
355
+
356
+ .ghostButton {
357
+ background: transparent;
358
+ border-color: var(--dsw-alias-border-l2);
359
+ color: var(--dsw-alias-label-primary);
360
+ }
361
+
362
+ .ghostButton:hover:not(:disabled) {
363
+ background: var(--dsw-alias-interactive-bg-hover);
364
+ }
365
+
366
+ .dangerButton {
367
+ background: transparent;
368
+ border-color: color-mix(in srgb, var(--dsw-alias-state-error-primary) 45%, transparent);
369
+ color: var(--dsw-alias-state-error-primary);
370
+ }
371
+
372
+ .dangerButton:hover:not(:disabled) {
373
+ background: color-mix(in srgb, var(--dsw-alias-state-error-primary) 12%, transparent);
374
+ border-color: var(--dsw-alias-state-error-primary);
375
+ }
376
+
377
+ .primaryButton:focus-visible,
378
+ .ghostButton:focus-visible,
379
+ .dangerButton:focus-visible {
380
+ outline: 2px solid var(--dsw-alias-state-business-primary);
381
+ outline-offset: 1px;
382
+ }
383
+
384
+ .primaryButton:disabled,
385
+ .ghostButton:disabled,
386
+ .dangerButton:disabled {
387
+ opacity: 0.45;
388
+ cursor: default;
389
+ }
390
+
391
+ /* 小尺寸(表格行内 / 密集工具栏) */
392
+ .primaryButton[data-size='sm'],
393
+ .ghostButton[data-size='sm'],
394
+ .dangerButton[data-size='sm'] {
395
+ height: 24px;
396
+ padding: 0 8px;
397
+ font-size: 11.5px;
398
+ border-radius: 5px;
399
+ }
400
+
401
+ /* —— 输入 / 选择 —— */
402
+ .input,
403
+ .select {
404
+ height: 28px;
405
+ padding: 0 8px;
406
+ border: 1px solid var(--dsw-alias-border-l2);
407
+ border-radius: 6px;
408
+ background: var(--dsw-specific-input-major);
409
+ font: inherit;
410
+ font-size: 12.5px;
411
+ color: var(--dsw-alias-label-primary);
412
+ box-sizing: border-box;
413
+ }
414
+
415
+ /* 满宽仅限**纵向**容器内的字段(.field 是 column flex,需要拉满):
416
+ 不可全局设 width:100% —— 那会让行内 flex 容器里的每个 select 各占一整行
417
+ (市场页筛选、同步页快照下拉都曾被撑成整行)。 */
418
+ .field > .input,
419
+ .field > .select {
420
+ width: 100%;
421
+ }
422
+
423
+ .input::placeholder {
424
+ color: var(--dsw-alias-label-tertiary);
425
+ }
426
+
427
+ .input:hover,
428
+ .select:hover {
429
+ border-color: color-mix(in srgb, var(--dsw-alias-state-business-primary) 40%, var(--dsw-alias-border-l2));
430
+ }
431
+
432
+ .input:focus,
433
+ .select:focus {
434
+ outline: none;
435
+ border-color: var(--dsw-alias-state-business-primary);
436
+ box-shadow: 0 0 0 2px color-mix(in srgb, var(--dsw-alias-state-business-primary) 18%, transparent);
437
+ }
438
+
439
+ .input:disabled,
440
+ .select:disabled {
441
+ opacity: 0.5;
442
+ cursor: default;
443
+ }
444
+
445
+ .select {
446
+ appearance: none;
447
+ padding-right: 22px;
448
+ background-image: linear-gradient(45deg, transparent 50%, var(--dsw-alias-label-secondary) 50%),
449
+ linear-gradient(135deg, var(--dsw-alias-label-secondary) 50%, transparent 50%);
450
+ background-position: calc(100% - 12px) 12px, calc(100% - 8px) 12px;
451
+ background-size: 4px 4px;
452
+ background-repeat: no-repeat;
453
+ cursor: pointer;
454
+ }
455
+
456
+ /* 密码/路径输入(等宽利于核对) */
457
+ .input[type='password'] {
458
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
459
+ font-size: 12px;
460
+ }
461
+
462
+ /* —— 复选 / 单选行 —— */
463
+ .checkboxRow,
464
+ .radioLabel {
465
+ display: flex;
466
+ align-items: flex-start;
467
+ gap: 7px;
468
+ cursor: pointer;
469
+ font-size: 12.5px;
470
+ color: var(--dsw-alias-label-primary);
471
+ }
472
+
473
+ .checkboxRow input,
474
+ .radioLabel input {
475
+ width: 14px;
476
+ height: 14px;
477
+ margin: 2px 0 0;
478
+ accent-color: var(--dsw-alias-state-business-primary);
479
+ cursor: pointer;
480
+ flex: none;
481
+ }
482
+
483
+ .checkboxRow input:focus-visible,
484
+ .radioLabel input:focus-visible {
485
+ outline: 2px solid var(--dsw-alias-state-business-primary);
486
+ outline-offset: 2px;
487
+ }
488
+
489
+ /* —— 徽章 —— */
490
+ .badge {
491
+ display: inline-flex;
492
+ align-items: center;
493
+ gap: 4px;
494
+ height: 18px;
495
+ padding: 0 7px;
496
+ border-radius: 9px;
497
+ font-size: 10.5px;
498
+ font-weight: 600;
499
+ line-height: 1;
500
+ white-space: nowrap;
501
+ border: 1px solid var(--dsw-alias-border-l2);
502
+ color: var(--dsw-alias-label-secondary);
503
+ }
504
+
505
+ .badgeOk {
506
+ border-color: transparent;
507
+ background: color-mix(in srgb, var(--dsw-alias-state-success-primary) 14%, transparent);
508
+ color: var(--dsw-alias-state-success-primary);
509
+ }
510
+
511
+ .badgeInfo {
512
+ border-color: color-mix(in srgb, var(--dsw-alias-state-business-primary) 30%, transparent);
513
+ background: transparent;
514
+ color: var(--dsw-alias-label-secondary);
515
+ }
516
+
517
+ .badgeWarn {
518
+ border-color: transparent;
519
+ background: color-mix(in srgb, var(--dsw-alias-state-warn-primary) 14%, transparent);
520
+ color: var(--dsw-alias-state-warn-primary);
521
+ }
522
+
523
+ .badgeError {
524
+ border-color: transparent;
525
+ background: color-mix(in srgb, var(--dsw-alias-state-error-primary) 14%, transparent);
526
+ color: var(--dsw-alias-state-error-primary);
527
+ }
528
+
529
+ /* —— 横幅(四态;紧凑) —— */
530
+ .banner {
531
+ display: flex;
532
+ align-items: center;
533
+ flex-wrap: wrap;
534
+ gap: 6px 10px;
535
+ padding: 8px 12px;
536
+ border-radius: 8px;
537
+ border: 1px solid var(--dsw-alias-border-l2);
538
+ background: var(--dsw-alias-bg-layer-2);
539
+ font-size: 12.5px;
540
+ margin: 0 0 10px;
541
+ /* 通栏元素:flex 父容器(.viewBody 等)里不随内容收缩 */
542
+ width: 100%;
543
+ box-sizing: border-box;
544
+ }
545
+
546
+ .banner[data-kind='ok'] {
547
+ border-color: color-mix(in srgb, var(--dsw-alias-state-success-primary) 35%, transparent);
548
+ background: color-mix(in srgb, var(--dsw-alias-state-success-primary) 9%, transparent);
549
+ }
550
+
551
+ .banner[data-kind='info'] {
552
+ border-color: color-mix(in srgb, var(--dsw-alias-state-business-primary) 30%, transparent);
553
+ background: color-mix(in srgb, var(--dsw-alias-state-business-primary) 8%, transparent);
554
+ }
555
+
556
+ .banner[data-kind='warn'] {
557
+ border-color: color-mix(in srgb, var(--dsw-alias-state-warn-primary) 40%, transparent);
558
+ background: color-mix(in srgb, var(--dsw-alias-state-warn-primary) 9%, transparent);
559
+ }
560
+
561
+ .banner[data-kind='error'] {
562
+ border-color: color-mix(in srgb, var(--dsw-alias-state-error-primary) 45%, transparent);
563
+ background: color-mix(in srgb, var(--dsw-alias-state-error-primary) 9%, transparent);
564
+ }
565
+
566
+ /* —— Spinner —— */
567
+ .spinnerWrap {
568
+ display: inline-flex;
569
+ align-items: center;
570
+ gap: 7px;
571
+ vertical-align: middle;
572
+ }
573
+
574
+ .spinner {
575
+ display: inline-block;
576
+ width: 13px;
577
+ height: 13px;
578
+ border: 2px solid color-mix(in srgb, var(--dsw-alias-state-business-primary) 25%, transparent);
579
+ border-top-color: var(--dsw-alias-state-business-primary);
580
+ border-radius: 50%;
581
+ animation: spin 0.7s linear infinite;
582
+ flex: none;
583
+ }
584
+
585
+ @keyframes spin {
586
+ to { transform: rotate(360deg); }
587
+ }
588
+
589
+ .spinnerLabel {
590
+ font-size: 12px;
591
+ color: var(--dsw-alias-label-secondary);
592
+ }
593
+
594
+ /* ================================================================ §4 Surfaces */
595
+
596
+ .card {
597
+ border: 1px solid var(--dsw-alias-border-l1);
598
+ border-radius: 8px;
599
+ background: var(--dsw-alias-bg-layer-2);
600
+ padding: 12px;
601
+ margin: 0 0 10px;
602
+ }
603
+
604
+ /* 分组标题(卡内小节头) */
605
+ .groupLabel {
606
+ display: block;
607
+ font-size: 11px;
608
+ font-weight: 700;
609
+ letter-spacing: 0.02em;
610
+ color: var(--dsw-alias-label-tertiary);
611
+ margin-bottom: 8px;
612
+ }
613
+
614
+ .groupHeader {
615
+ display: flex;
616
+ align-items: baseline;
617
+ gap: 8px;
618
+ margin-bottom: 10px;
619
+ }
620
+
621
+ /* 卡头内的分组标题:不收缩、不换行(防止长 hint 把标题挤成竖排) */
622
+ .groupHeader .groupLabel {
623
+ flex: none;
624
+ white-space: nowrap;
625
+ margin-bottom: 0;
626
+ }
627
+
628
+ .groupNote {
629
+ font-size: 11px;
630
+ color: var(--dsw-alias-label-tertiary);
631
+ }
632
+
633
+ .groupItems {
634
+ display: flex;
635
+ flex-direction: column;
636
+ gap: 6px;
637
+ }
638
+
639
+ /* 表单字段 */
640
+ .field {
641
+ display: flex;
642
+ flex-direction: column;
643
+ gap: 4px;
644
+ margin: 0 0 10px;
645
+ }
646
+
647
+ .fieldLabel {
648
+ font-size: 11.5px;
649
+ font-weight: 600;
650
+ color: var(--dsw-alias-label-secondary);
651
+ }
652
+
653
+ .hint {
654
+ font-size: 11.5px;
655
+ line-height: 1.5;
656
+ color: var(--dsw-alias-label-tertiary);
657
+ }
658
+
659
+ .formError {
660
+ font-size: 11.5px;
661
+ color: var(--dsw-alias-state-error-primary);
662
+ }
663
+
664
+ /* 区块标题(页面内二级标题) */
665
+ .sectionTitleBlock {
666
+ min-width: 0;
667
+ }
668
+
669
+ .sectionTitle {
670
+ margin: 0;
671
+ font-size: 13px;
672
+ font-weight: 700;
673
+ line-height: 1.4;
674
+ color: var(--dsw-alias-label-primary);
675
+ }
676
+
677
+ .sectionSubtitle {
678
+ margin: 1px 0 0;
679
+ font-size: 11.5px;
680
+ color: var(--dsw-alias-label-tertiary);
681
+ }
682
+
683
+ /* 空态 */
684
+ .empty {
685
+ display: flex;
686
+ flex-direction: column;
687
+ align-items: center;
688
+ justify-content: center;
689
+ gap: 4px;
690
+ padding: 28px 16px;
691
+ border: 1px dashed var(--dsw-alias-border-l2);
692
+ border-radius: 8px;
693
+ text-align: center;
694
+ font-size: 12px;
695
+ color: var(--dsw-alias-label-tertiary);
696
+ /* 通栏占位:不被 flex 父容器压成内容宽 */
697
+ width: 100%;
698
+ box-sizing: border-box;
699
+ }
700
+
701
+ /* 居中空态页(大块空视图:垂直居中 + 图形 + CTA,替代贴顶小虚线框) */
702
+ .emptyHero {
703
+ flex: 1 1 auto;
704
+ display: flex;
705
+ flex-direction: column;
706
+ align-items: center;
707
+ justify-content: center;
708
+ gap: 6px;
709
+ min-height: 320px;
710
+ text-align: center;
711
+ }
712
+
713
+ .emptyHeroSymbol {
714
+ font-size: 30px;
715
+ line-height: 1;
716
+ color: var(--dsw-alias-label-tertiary);
717
+ opacity: 0.75;
718
+ }
719
+
720
+ .emptyHeroTitle {
721
+ font-size: 13px;
722
+ font-weight: 700;
723
+ color: var(--dsw-alias-label-primary);
724
+ }
725
+
726
+ .emptyHeroBody {
727
+ max-width: 340px;
728
+ font-size: 12px;
729
+ line-height: 1.6;
730
+ color: var(--dsw-alias-label-tertiary);
731
+ margin: 0 0 6px;
732
+ }
733
+
734
+ /* ================================================================ §5 Data Display */
735
+
736
+ /* —— 数据表 —— */
737
+ .tableWrap {
738
+ border: 1px solid var(--dsw-alias-border-l1);
739
+ border-radius: 8px;
740
+ background: var(--dsw-alias-bg-layer-2);
741
+ overflow: hidden;
742
+ margin-bottom: 10px;
743
+ }
744
+
745
+ /* 表格用固定布局(.tableFixed)时列宽容易偏紧:给每列留一点水平呼吸,
746
+ 避免内容差几个像素就触发单元格省略号(操作列的「…」即由此而来)。 */
747
+ .tableFixed th,
748
+ .tableFixed td {
749
+ padding-left: 12px;
750
+ padding-right: 12px;
751
+ }
752
+
753
+ .tableScroll {
754
+ overflow: auto;
755
+ max-height: 420px;
756
+ }
757
+
758
+ .dataTable {
759
+ width: 100%;
760
+ border-collapse: collapse;
761
+ font-size: 12px;
762
+ }
763
+
764
+ .dataTable th,
765
+ .dataTable td {
766
+ box-sizing: border-box;
767
+ }
768
+
769
+ /* 固定布局变体:配合 th 宽度使用,主列内容省略不撑破(行内长文件名/路径场景) */
770
+ .tableFixed {
771
+ table-layout: fixed;
772
+ }
773
+
774
+ .tableFixed td,
775
+ .tableFixed th {
776
+ overflow: hidden;
777
+ text-overflow: ellipsis;
778
+ }
779
+
780
+ /* 紧凑变体:单元格 padding 8px(列多画布窄的场景) */
781
+ .tableCompact th,
782
+ .tableCompact td {
783
+ padding-left: 8px;
784
+ padding-right: 8px;
785
+ }
786
+
787
+ .dataTable td.dim {
788
+ white-space: nowrap;
789
+ }
790
+
791
+ .dataTable th {
792
+ position: sticky;
793
+ top: 0;
794
+ z-index: 1;
795
+ padding: 6px 10px;
796
+ text-align: left;
797
+ font-size: 11px;
798
+ font-weight: 600;
799
+ color: var(--dsw-alias-label-tertiary);
800
+ background: var(--dsw-alias-bg-layer-2);
801
+ border-bottom: 1px solid var(--dsw-alias-border-l1);
802
+ white-space: nowrap;
803
+ }
804
+
805
+ .dataTable td {
806
+ padding: 6px 10px;
807
+ border-bottom: 1px solid color-mix(in srgb, var(--dsw-alias-border-l1) 55%, transparent);
808
+ vertical-align: middle;
809
+ color: var(--dsw-alias-label-primary);
810
+ }
811
+
812
+ .dataTable tbody tr:last-child td {
813
+ border-bottom: none;
814
+ }
815
+
816
+ .dataTable tbody tr {
817
+ transition: background-color 100ms ease-out;
818
+ }
819
+
820
+ .dataTable tbody tr:hover {
821
+ background: var(--dsw-alias-interactive-bg-hover);
822
+ }
823
+
824
+ .dataTable tbody tr[data-selected] {
825
+ background: color-mix(in srgb, var(--dsw-alias-state-business-primary) 9%, transparent);
826
+ }
827
+
828
+ .dataTable .num {
829
+ text-align: right;
830
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
831
+ font-size: 11.5px;
832
+ white-space: nowrap;
833
+ }
834
+
835
+ .dataTable .dim {
836
+ color: var(--dsw-alias-label-secondary);
837
+ }
838
+
839
+ .dataTable .cellActions {
840
+ text-align: right;
841
+ white-space: nowrap;
842
+ }
843
+
844
+ /* 操作列内容优先完整展示:.tableFixed 给所有单元格都加了
845
+ `overflow:hidden; text-overflow:ellipsis`,列宽略紧时行内操作按钮后会被
846
+ 浏览器补一个「…」省略号(备份页两张表都出现过)。操作列是按钮组,
847
+ 宁可略微溢出也不截断,故这里单独放开省略号。 */
848
+ .dataTable td.cellActions {
849
+ overflow: visible;
850
+ text-overflow: clip;
851
+ }
852
+
853
+ .rowActions {
854
+ display: inline-flex;
855
+ align-items: center;
856
+ gap: 3px;
857
+ }
858
+
859
+ /* 表格主列:名称 + 内联元数据(固定最小高度,避免「有徽章/备注」与「无」的行高跳动) */
860
+ .cellMain {
861
+ display: flex;
862
+ flex-direction: column;
863
+ justify-content: center;
864
+ gap: 1px;
865
+ min-width: 0;
866
+ min-height: 30px;
867
+ }
868
+
869
+ .cellTitle {
870
+ font-weight: 500;
871
+ overflow: hidden;
872
+ text-overflow: ellipsis;
873
+ white-space: nowrap;
874
+ }
875
+
876
+ .cellMeta {
877
+ display: inline-flex;
878
+ align-items: center;
879
+ gap: 6px;
880
+ font-size: 11px;
881
+ color: var(--dsw-alias-label-tertiary);
882
+ overflow: hidden;
883
+ min-width: 0;
884
+ }
885
+
886
+ /* 备注文本:作为 cellMeta 的可收缩子项,单行省略(避免硬截断无 … 的「未完成感」 */
887
+ .cellMetaNote {
888
+ display: inline-flex;
889
+ align-items: center;
890
+ gap: 3px;
891
+ min-width: 0;
892
+ flex: 0 1 auto;
893
+ }
894
+
895
+ /* 备注文字本体:块级省略(text-overflow 需作用于可收缩的块/inline-block 文本元素) */
896
+ .cellMetaNoteText {
897
+ min-width: 0;
898
+ overflow: hidden;
899
+ text-overflow: ellipsis;
900
+ white-space: nowrap;
901
+ }
902
+
903
+ /* —— 统计块(指标) —— */
904
+ .statGrid,
905
+ .metricGrid {
906
+ display: grid;
907
+ grid-template-columns: repeat(4, minmax(0, 1fr));
908
+ gap: 8px;
909
+ margin-bottom: 10px;
910
+ }
911
+
912
+ .statCard,
913
+ .metricCard {
914
+ display: flex;
915
+ flex-direction: column;
916
+ gap: 2px;
917
+ padding: 10px 12px;
918
+ border: 1px solid var(--dsw-alias-border-l1);
919
+ border-radius: 8px;
920
+ background: var(--dsw-alias-bg-layer-2);
921
+ min-width: 0;
922
+ }
923
+
924
+ /* 可点击统计卡(button 元素需重置默认样式) */
925
+ button.statCard {
926
+ font: inherit;
927
+ color: inherit;
928
+ text-align: left;
929
+ width: 100%;
930
+ cursor: pointer;
931
+ }
932
+
933
+ button.statCard:hover {
934
+ border-color: color-mix(in srgb, var(--dsw-alias-state-business-primary) 45%, var(--dsw-alias-border-l1));
935
+ }
936
+
937
+ button.statCard:focus-visible {
938
+ outline: 2px solid var(--dsw-alias-state-business-primary);
939
+ outline-offset: 1px;
940
+ }
941
+
942
+ /* 页头行内的横幅:占满剩余宽度(刷新按钮靠右) */
943
+ .actionRow .banner {
944
+ flex: 1 1 auto;
945
+ min-width: 0;
946
+ margin: 0;
947
+ }
948
+
949
+ .statValue {
950
+ display: flex;
951
+ align-items: baseline;
952
+ gap: 5px;
953
+ font-size: 19px;
954
+ font-weight: 700;
955
+ line-height: 1.2;
956
+ color: var(--dsw-alias-label-primary);
957
+ }
958
+
959
+ .metricValue {
960
+ font-size: 19px;
961
+ font-weight: 700;
962
+ line-height: 1.2;
963
+ }
964
+
965
+ .statValueSmall {
966
+ font-size: 13px;
967
+ font-weight: 600;
968
+ }
969
+
970
+ .statLabel,
971
+ .metricLabel {
972
+ font-size: 11px;
973
+ font-weight: 600;
974
+ color: var(--dsw-alias-label-tertiary);
975
+ }
976
+
977
+ .statMeta,
978
+ .metricMeta {
979
+ font-size: 11px;
980
+ color: var(--dsw-alias-label-tertiary);
981
+ overflow: hidden;
982
+ text-overflow: ellipsis;
983
+ white-space: nowrap;
984
+ }
985
+
986
+ .warnText {
987
+ color: var(--dsw-alias-state-warn-primary);
988
+ }
989
+
990
+ /* —— 键值行 —— */
991
+ .kvRow {
992
+ display: flex;
993
+ align-items: baseline;
994
+ gap: 10px;
995
+ padding: 5px 0;
996
+ border-bottom: 1px solid color-mix(in srgb, var(--dsw-alias-border-l1) 55%, transparent);
997
+ font-size: 12px;
998
+ min-width: 0;
999
+ }
1000
+
1001
+ .kvRow:last-child {
1002
+ border-bottom: none;
1003
+ }
1004
+
1005
+ .kvKey {
1006
+ flex: none;
1007
+ width: 88px;
1008
+ color: var(--dsw-alias-label-tertiary);
1009
+ font-size: 11.5px;
1010
+ }
1011
+
1012
+ .kvValue {
1013
+ flex: 1 1 auto;
1014
+ min-width: 0;
1015
+ overflow-wrap: anywhere;
1016
+ }
1017
+
1018
+ .kvValue.mono {
1019
+ font-size: 11.5px;
1020
+ color: var(--dsw-alias-label-secondary);
1021
+ }
1022
+
1023
+ /* —— 分段控件(页内子视图切换) —— */
1024
+ .segGroup,
1025
+ .modeTabs {
1026
+ display: inline-flex;
1027
+ align-items: center;
1028
+ gap: 2px;
1029
+ padding: 2px;
1030
+ border: 1px solid var(--dsw-alias-border-l2);
1031
+ border-radius: 7px;
1032
+ background: var(--dsw-alias-bg-base);
1033
+ margin: 0 0 10px;
1034
+ }
1035
+
1036
+ .segItem,
1037
+ .modeTab {
1038
+ display: inline-flex;
1039
+ align-items: center;
1040
+ gap: 5px;
1041
+ height: 22px;
1042
+ padding: 0 9px;
1043
+ border: none;
1044
+ border-radius: 5px;
1045
+ background: none;
1046
+ font: inherit;
1047
+ font-size: 11.5px;
1048
+ font-weight: 500;
1049
+ color: var(--dsw-alias-label-secondary);
1050
+ cursor: pointer;
1051
+ white-space: nowrap;
1052
+ }
1053
+
1054
+ .segItem:hover,
1055
+ .modeTab:hover {
1056
+ color: var(--dsw-alias-label-primary);
1057
+ }
1058
+
1059
+ .segItem:focus-visible,
1060
+ .modeTab:focus-visible {
1061
+ outline: 2px solid var(--dsw-alias-state-business-primary);
1062
+ outline-offset: 1px;
1063
+ }
1064
+
1065
+ .segItem[data-active],
1066
+ .modeTab[data-active] {
1067
+ background: var(--dsw-alias-bg-layer-2);
1068
+ color: var(--dsw-alias-label-primary);
1069
+ font-weight: 600;
1070
+ box-shadow: 0 0 0 1px var(--dsw-alias-border-l1);
1071
+ }
1072
+
1073
+ .modeHint {
1074
+ font-size: 11.5px;
1075
+ color: var(--dsw-alias-label-tertiary);
1076
+ margin: -4px 0 10px;
1077
+ }
1078
+
1079
+ /* —— 步骤条(紧凑横向) —— */
1080
+ .stepper {
1081
+ display: flex;
1082
+ align-items: center;
1083
+ padding: 2px 0;
1084
+ overflow-x: auto;
1085
+ scrollbar-width: none;
1086
+ }
1087
+
1088
+ .stepper::-webkit-scrollbar {
1089
+ display: none;
1090
+ }
1091
+
1092
+ .stepperStep {
1093
+ display: inline-flex;
1094
+ align-items: center;
1095
+ gap: 5px;
1096
+ flex: none;
1097
+ }
1098
+
1099
+ .stepperDot {
1100
+ display: inline-flex;
1101
+ align-items: center;
1102
+ justify-content: center;
1103
+ width: 17px;
1104
+ height: 17px;
1105
+ border-radius: 50%;
1106
+ border: 1.5px solid var(--dsw-alias-border-l2);
1107
+ font-size: 9.5px;
1108
+ font-weight: 700;
1109
+ color: var(--dsw-alias-label-tertiary);
1110
+ background: var(--dsw-alias-bg-layer-2);
1111
+ flex: none;
1112
+ }
1113
+
1114
+ .stepperDot[data-state='current'] {
1115
+ border-color: var(--dsw-alias-state-business-primary);
1116
+ background: var(--dsw-alias-state-business-primary);
1117
+ color: var(--dsw-alias-label-primary-foreground);
1118
+ }
1119
+
1120
+ .stepperDot[data-state='done'] {
1121
+ border-color: transparent;
1122
+ background: color-mix(in srgb, var(--dsw-alias-state-success-primary) 16%, transparent);
1123
+ color: var(--dsw-alias-state-success-primary);
1124
+ }
1125
+
1126
+ .stepperLabel {
1127
+ font-size: 11px;
1128
+ color: var(--dsw-alias-label-tertiary);
1129
+ white-space: nowrap;
1130
+ }
1131
+
1132
+ .stepperStep[data-state='current'] .stepperLabel {
1133
+ color: var(--dsw-alias-label-primary);
1134
+ font-weight: 600;
1135
+ }
1136
+
1137
+ .stepperStep[data-state='done'] .stepperLabel {
1138
+ color: var(--dsw-alias-label-secondary);
1139
+ }
1140
+
1141
+ .stepperConnector {
1142
+ width: 14px;
1143
+ height: 1.5px;
1144
+ margin: 0 5px;
1145
+ background: var(--dsw-alias-border-l2);
1146
+ flex: none;
1147
+ }
1148
+
1149
+ .stepperStep[data-state='done'] .stepperConnector {
1150
+ background: color-mix(in srgb, var(--dsw-alias-state-success-primary) 45%, transparent);
1151
+ }
1152
+
1153
+ /* —— 进度条 —— */
1154
+ .progressBlock {
1155
+ margin: 0 0 10px;
1156
+ }
1157
+
1158
+ .progressTrack {
1159
+ position: relative;
1160
+ height: 5px;
1161
+ border-radius: 3px;
1162
+ background: color-mix(in srgb, var(--dsw-alias-border-l1) 80%, transparent);
1163
+ overflow: hidden;
1164
+ }
1165
+
1166
+ .progressBar {
1167
+ position: absolute;
1168
+ inset: 0 auto 0 0;
1169
+ border-radius: 3px;
1170
+ background: var(--dsw-alias-state-business-primary);
1171
+ transition: width 300ms ease-out;
1172
+ }
1173
+
1174
+ .progressBarDone {
1175
+ background: var(--dsw-alias-state-success-primary);
1176
+ }
1177
+
1178
+ .progressIndeterminate {
1179
+ position: absolute;
1180
+ top: 0;
1181
+ bottom: 0;
1182
+ width: 34%;
1183
+ border-radius: 3px;
1184
+ background: var(--dsw-alias-state-business-primary);
1185
+ animation: indet 1.15s ease-in-out infinite;
1186
+ }
1187
+
1188
+ @keyframes indet {
1189
+ 0% { left: -34%; }
1190
+ 100% { left: 100%; }
1191
+ }
1192
+
1193
+ .progressMeta {
1194
+ display: flex;
1195
+ align-items: center;
1196
+ gap: 8px;
1197
+ margin-top: 5px;
1198
+ font-size: 11.5px;
1199
+ color: var(--dsw-alias-label-secondary);
1200
+ }
1201
+
1202
+ .progressLabel {
1203
+ min-width: 0;
1204
+ overflow: hidden;
1205
+ text-overflow: ellipsis;
1206
+ white-space: nowrap;
1207
+ }
1208
+
1209
+ .progressPercent {
1210
+ flex: none;
1211
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
1212
+ color: var(--dsw-alias-label-tertiary);
1213
+ }
1214
+
1215
+ .progressBadge {
1216
+ display: inline-flex;
1217
+ align-items: center;
1218
+ gap: 4px;
1219
+ flex: none;
1220
+ font-size: 11px;
1221
+ color: var(--dsw-alias-label-tertiary);
1222
+ }
1223
+
1224
+ .progressBadgeCount {
1225
+ padding: 0 5px;
1226
+ border-radius: 8px;
1227
+ background: color-mix(in srgb, var(--dsw-alias-state-info-primary) 14%, transparent);
1228
+ color: var(--dsw-alias-label-secondary);
1229
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
1230
+ }
1231
+
1232
+ .progressBadgeSection {
1233
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
1234
+ }
1235
+
1236
+ .progressDetail {
1237
+ margin-top: 3px;
1238
+ font-size: 11px;
1239
+ color: var(--dsw-alias-label-tertiary);
1240
+ }
1241
+
1242
+ /* —— 限高滚动容器(大报告/列表通用) —— */
1243
+ .planScroll,
1244
+ .reportScroll,
1245
+ .confirmScroll,
1246
+ .pullScroll,
1247
+ .diffScroll,
1248
+ .historyScroll,
1249
+ .consultScroll {
1250
+ overflow: auto;
1251
+ max-height: 380px;
1252
+ border: 1px solid var(--dsw-alias-border-l1);
1253
+ border-radius: 8px;
1254
+ background: var(--dsw-alias-bg-base);
1255
+ }
1256
+
1257
+ /* 咨询卡的评分维度:留出左右内边距 —— 维度行的徽章胶囊原本紧贴容器左边框
1258
+ (实测仅 1px,即边框本身),右侧也贴着滚动条。 */
1259
+ .consultScroll {
1260
+ padding: 0 6px;
1261
+ }
1262
+
1263
+ .logScroll {
1264
+ overflow: auto;
1265
+ max-height: 220px;
1266
+ background: var(--dsw-alias-bg-base);
1267
+ }
1268
+
1269
+ /* ================================================================ §6 Overlays */
1270
+
1271
+ /* —— 确认弹窗 —— */
1272
+ .dialogMask {
1273
+ position: fixed;
1274
+ inset: 0;
1275
+ z-index: 100;
1276
+ display: flex;
1277
+ align-items: center;
1278
+ justify-content: center;
1279
+ background: color-mix(in srgb, var(--dsw-alias-bg-base) 55%, transparent);
1280
+ }
1281
+
1282
+ /* Radix Dialog.Content 自居中定位(Portal 下与 Overlay 平级,需自身 fixed 居中;
1283
+ 旧内联弹窗里 .dialogCard 是 .dialogMask(flex) 的子元素,无需此类——两者并存兼容)。 */
1284
+ .dialogContentCenter {
1285
+ position: fixed;
1286
+ top: 50%;
1287
+ left: 50%;
1288
+ transform: translate(-50%, -50%);
1289
+ z-index: 101;
1290
+ }
1291
+
1292
+ .dialogCard {
1293
+ /* 弹窗尺寸(2026-09 放大):旧值 380×480 在长内容(配置更改明细 / 分区构成)
1294
+ 下可读性差 —— 内容被压成很窄的一列、且正文很早就开始内滚。
1295
+ 现按宿主设置弹窗的可见范围(min(800px, 100vw-48px))取整:宽 640、高 600
1296
+ (接近插件画布 564×720 的观感),并给长行留足横向余量。
1297
+ 说明:Radix Portal 落在插件根节点内,而插件在宿主 800px 面板中,
1298
+ 因此 vw/vh 基准约等于面板尺寸;乘以 0.95/0.92 后再减去宿主导航余量兜底。 */
1299
+ width: min(640px, calc(100vw - 48px), 95%);
1300
+ max-width: calc(100vw - 48px);
1301
+ max-height: min(600px, calc(100vh - 64px), 92%);
1302
+ display: flex;
1303
+ flex-direction: column;
1304
+ border: 1px solid var(--dsw-alias-border-l1);
1305
+ border-radius: 10px;
1306
+ background: var(--dsw-alias-bg-layer-2);
1307
+ box-shadow: 0 12px 32px color-mix(in srgb, var(--dsw-alias-bg-base) 40%, transparent);
1308
+ }
1309
+
1310
+ .dialogHeader {
1311
+ padding: 12px 16px 0;
1312
+ font-size: 13px;
1313
+ font-weight: 700;
1314
+ color: var(--dsw-alias-label-primary);
1315
+ }
1316
+
1317
+ .dialogHeaderRow {
1318
+ display: flex;
1319
+ align-items: center;
1320
+ gap: 8px;
1321
+ padding: 12px 14px 0;
1322
+ }
1323
+
1324
+ .dialogClose {
1325
+ margin-left: auto;
1326
+ }
1327
+
1328
+ /* 弹窗正文区:padding 拆分为上下与左右,便于给「迁移前咨询」这类内嵌卡片
1329
+ 单独收窄左右内边距(见 .dialogBodyConsult)。 */
1330
+ .dialogBody {
1331
+ flex: 1 1 auto;
1332
+ min-height: 0;
1333
+ overflow-y: auto;
1334
+ padding: 8px 16px 12px;
1335
+ font-size: 12.5px;
1336
+ color: var(--dsw-alias-label-secondary);
1337
+ }
1338
+
1339
+ .dialogBodyScroll {
1340
+ overflow-y: auto;
1341
+ max-height: 460px;
1342
+ }
1343
+
1344
+ .dialogWide {
1345
+ width: min(720px, calc(100vw - 48px), 96%);
1346
+ max-height: min(620px, calc(100vh - 64px), 92%);
1347
+ }
1348
+
1349
+ /* 弹窗底部按钮区:右对齐,顶部分隔线,与正文区分 */
1350
+ .dialogFooter {
1351
+ justify-content: flex-end;
1352
+ gap: 8px;
1353
+ padding: 10px 16px 14px;
1354
+ margin: 0;
1355
+ border-top: 1px solid var(--dsw-alias-border-l1);
1356
+ }
1357
+
1358
+ /* —— 全局通知(右下角堆叠) ——
1359
+ 定位:absolute 贴合 .section(非 fixed/Portal),确保落在宿主弹窗层叠上下文内;
1360
+ 容器不吃指针事件,避免遮挡右下角的页面点击(状态栏/列表),仅卡片自身可交互。 */
1361
+ .toastViewport {
1362
+ position: absolute;
1363
+ right: 10px;
1364
+ bottom: 42px; /* 让开 28px 状态栏 + 8px 外边距 */
1365
+ /* 高于页面内容、状态栏(无)、弹窗遮罩(100)与卡片(101):弹窗打开期间触发的通知
1366
+ 不能落在遮罩之下(否则被 55% 不透明遮罩盖住而严重褪色)。
1367
+ 仍留在插件层叠上下文内,因此不会越过宿主 overlay(z-index: 1000)。 */
1368
+ z-index: 120;
1369
+ display: flex;
1370
+ flex-direction: column;
1371
+ align-items: flex-end;
1372
+ gap: 8px;
1373
+ max-width: calc(100% - 20px);
1374
+ pointer-events: none;
1375
+ }
1376
+
1377
+ .toast {
1378
+ pointer-events: auto;
1379
+ display: flex;
1380
+ align-items: flex-start;
1381
+ gap: 8px;
1382
+ width: fit-content;
1383
+ max-width: 340px;
1384
+ padding: 8px 10px;
1385
+ border: 1px solid var(--dsw-alias-border-l1);
1386
+ border-radius: 8px;
1387
+ background: var(--dsw-alias-bg-layer-2);
1388
+ box-shadow: 0 8px 24px color-mix(in srgb, var(--dsw-alias-bg-base) 45%, transparent);
1389
+ font-size: 12px;
1390
+ line-height: 1.45;
1391
+ color: var(--dsw-alias-label-primary);
1392
+ animation: toastIn 160ms ease-out;
1393
+ }
1394
+
1395
+ @keyframes toastIn {
1396
+ from { transform: translateY(6px); opacity: 0; }
1397
+ to { transform: translateY(0); opacity: 1; }
1398
+ }
1399
+
1400
+ /* 四态语义:左侧色条 + 图标着色(复用 Badge/Banner 的 --dsw-* 状态色) */
1401
+ .toast[data-kind='ok'] {
1402
+ border-color: color-mix(in srgb, var(--dsw-alias-state-success-primary) 40%, transparent);
1403
+ }
1404
+
1405
+ .toast[data-kind='ok'] .toastGlyph {
1406
+ color: var(--dsw-alias-state-success-primary);
1407
+ }
1408
+
1409
+ .toast[data-kind='info'] .toastGlyph {
1410
+ color: var(--dsw-alias-state-business-primary);
1411
+ }
1412
+
1413
+ .toast[data-kind='warn'] {
1414
+ border-color: color-mix(in srgb, var(--dsw-alias-state-warn-primary) 40%, transparent);
1415
+ }
1416
+
1417
+ .toast[data-kind='warn'] .toastGlyph {
1418
+ color: var(--dsw-alias-state-warn-primary);
1419
+ }
1420
+
1421
+ .toast[data-kind='error'] {
1422
+ border-color: color-mix(in srgb, var(--dsw-alias-state-error-primary) 45%, transparent);
1423
+ }
1424
+
1425
+ .toast[data-kind='error'] .toastGlyph {
1426
+ color: var(--dsw-alias-state-error-primary);
1427
+ }
1428
+
1429
+ .toastGlyph {
1430
+ display: inline-flex;
1431
+ flex: none;
1432
+ /* 与首行文字对齐(图标 14px 对 12px 正文,上移 1px 视觉居中) */
1433
+ margin-top: 1px;
1434
+ }
1435
+
1436
+ .toastText {
1437
+ min-width: 0;
1438
+ word-break: break-word;
1439
+ }
1440
+
1441
+ /* 关闭按钮:与 IconButton 尺寸一致但更贴合通知条(26px → 18px 视觉内缩) */
1442
+ .toast > button {
1443
+ width: 18px;
1444
+ height: 18px;
1445
+ flex: none;
1446
+ margin-left: 2px;
1447
+ }
1448
+
1449
+ /* —— 右侧抽屉(活动/历史) —— */
1450
+ .drawerMask {
1451
+ position: fixed;
1452
+ inset: 0;
1453
+ z-index: 90;
1454
+ background: color-mix(in srgb, var(--dsw-alias-bg-base) 35%, transparent);
1455
+ }
1456
+
1457
+ .drawerPanel {
1458
+ position: fixed;
1459
+ top: 0;
1460
+ right: 0;
1461
+ bottom: 0;
1462
+ z-index: 91;
1463
+ width: 400px;
1464
+ max-width: calc(100vw - 64px);
1465
+ display: flex;
1466
+ flex-direction: column;
1467
+ border-left: 1px solid var(--dsw-alias-border-l1);
1468
+ background: var(--dsw-alias-bg-layer-2);
1469
+ box-shadow: -12px 0 32px color-mix(in srgb, var(--dsw-alias-bg-base) 35%, transparent);
1470
+ animation: drawerIn 180ms ease-out;
1471
+ }
1472
+
1473
+ @keyframes drawerIn {
1474
+ from { transform: translateX(24px); opacity: 0; }
1475
+ to { transform: translateX(0); opacity: 1; }
1476
+ }
1477
+
1478
+ .drawerHeader {
1479
+ display: flex;
1480
+ align-items: center;
1481
+ gap: 8px;
1482
+ flex: none;
1483
+ padding: 12px 14px;
1484
+ border-bottom: 1px solid var(--dsw-alias-border-l1);
1485
+ }
1486
+
1487
+ .drawerTitle {
1488
+ flex: 1 1 auto;
1489
+ font-size: 13px;
1490
+ font-weight: 700;
1491
+ color: var(--dsw-alias-label-primary);
1492
+ }
1493
+
1494
+ .drawerBody {
1495
+ flex: 1 1 auto;
1496
+ min-height: 0;
1497
+ overflow-y: auto;
1498
+ padding: 12px 14px;
1499
+ }
1500
+
1501
+ /* 通用操作行 */
1502
+ .actionRow {
1503
+ display: flex;
1504
+ align-items: center;
1505
+ gap: 8px;
1506
+ flex-wrap: wrap;
1507
+ margin: 0 0 10px;
1508
+ }
1509
+
1510
+ /* 上方有说明文案的操作行(如「通道配置」按钮紧跟在 hint 之后):
1511
+ 补一点上边距,避免按钮与说明文字贴在一起。 */
1512
+ .actionRowTop {
1513
+ display: flex;
1514
+ align-items: center;
1515
+ gap: 8px;
1516
+ flex-wrap: wrap;
1517
+ margin: 10px 0 10px;
1518
+ }
1519
+
1520
+ /* 独占一行的分段/页签行(如同步页「默认 / 高级」模式切换):
1521
+ 与上方说明文案分行,自身作为独立行块。
1522
+ 注意:本类必须**自带分段控件外壳**(border/radius/padding/bg-base),
1523
+ 否则 `.modeTab[data-active]` 的选中底色(layer-2)会与 Card 底色相同而「隐形」。 */
1524
+ .tabRow {
1525
+ display: flex;
1526
+ align-items: center;
1527
+ gap: 2px;
1528
+ flex-wrap: wrap;
1529
+ width: fit-content;
1530
+ padding: 2px;
1531
+ border: 1px solid var(--dsw-alias-border-l2);
1532
+ border-radius: 7px;
1533
+ background: var(--dsw-alias-bg-base);
1534
+ margin: 10px 0 10px;
1535
+ }
1536
+
1537
+ /* 同步页「选择历史快照」空态提示行(原为行内 hint,独立成行以保持下拉与按钮同基线) */
1538
+ .snapshotPickerHint {
1539
+ margin-top: 4px;
1540
+ margin-bottom: 10px;
1541
+ }
1542
+
1543
+ /* 卡头单行(标题 + 右侧动作/徽章):标题左、其余右。
1544
+ 与 .groupHeader 的区别:本类不做 baseline 对齐(按钮组需要居中),
1545
+ 且内嵌 .groupLabel 不保留底部外边距(否则整行会被撑高)。 */
1546
+ .headRow {
1547
+ display: flex;
1548
+ align-items: center;
1549
+ gap: 8px;
1550
+ flex-wrap: wrap;
1551
+ margin: 0 0 10px;
1552
+ }
1553
+
1554
+ .headRow .groupLabel {
1555
+ margin-bottom: 0;
1556
+ }
1557
+
1558
+ /* 作者行(关于页):标签与作者名基线对齐 */
1559
+ .authorRow {
1560
+ display: flex;
1561
+ align-items: center;
1562
+ gap: 8px;
1563
+ flex-wrap: wrap;
1564
+ margin-top: 8px;
1565
+ }
1566
+
1567
+ /* 定时备份卡:事实行与设置行沿用统一下边距节奏(替代组件内联 style) */
1568
+ .scheduleFacts {
1569
+ margin-top: 8px;
1570
+ }
1571
+
1572
+ .scheduleRow {
1573
+ margin-top: 10px;
1574
+ }
1575
+
1576
+ .scheduleNote {
1577
+ margin-top: 6px;
1578
+ }
1579
+
1580
+ .authorRow .groupLabel {
1581
+ margin-bottom: 0;
1582
+ }
1583
+
1584
+ /* 市场条目筛选区:搜索框跨整行,其下 4 个下拉两两一行(2×2)。
1585
+ 用 grid 而非 flex:列宽严格等分,窄画布下也不会出现「每行只放得下 1 个」
1586
+ 或「控件被内容宽度挤歪」。 */
1587
+ .marketFilterGrid {
1588
+ display: grid;
1589
+ grid-template-columns: repeat(2, minmax(0, 1fr));
1590
+ gap: 8px;
1591
+ margin-bottom: 8px;
1592
+ }
1593
+
1594
+ .marketFilterSearch {
1595
+ grid-column: 1 / -1;
1596
+ }
1597
+
1598
+ /* 筛选区下方的元信息行(分区未知提示 + 条目计数徽章) */
1599
+ .marketFilterMeta {
1600
+ display: flex;
1601
+ align-items: center;
1602
+ gap: 8px;
1603
+ flex-wrap: wrap;
1604
+ margin-bottom: 8px;
1605
+ }
1606
+
1607
+ .pushRight {
1608
+ margin-left: auto;
1609
+ }
1610
+
1611
+ /* ================================================================ §7 Page: Overview(控制中心) */
1612
+
1613
+ /* —— 状态条:健康点 + 指标段(可点击导航),32px 单行 —— */
1614
+ .statStrip {
1615
+ display: flex;
1616
+ align-items: stretch;
1617
+ gap: 0;
1618
+ min-height: 32px;
1619
+ border: 1px solid var(--dsw-alias-border-l1);
1620
+ border-radius: 8px;
1621
+ background: var(--dsw-alias-bg-layer-2);
1622
+ margin-bottom: 10px;
1623
+ overflow-x: auto;
1624
+ scrollbar-width: none;
1625
+ }
1626
+
1627
+ .statStrip::-webkit-scrollbar {
1628
+ display: none;
1629
+ }
1630
+
1631
+ /* 末段不被容器右缘裁切:预留内边距,保证最后一个指标值完整可见 */
1632
+ .statStrip > :last-child {
1633
+ padding-right: 12px;
1634
+ }
1635
+
1636
+ .statStrip[data-tone='error'] {
1637
+ border-color: color-mix(in srgb, var(--dsw-alias-state-error-primary) 45%, transparent);
1638
+ background: color-mix(in srgb, var(--dsw-alias-state-error-primary) 7%, transparent);
1639
+ }
1640
+
1641
+ .statStrip[data-tone='warn'] {
1642
+ border-color: color-mix(in srgb, var(--dsw-alias-state-warn-primary) 40%, transparent);
1643
+ background: color-mix(in srgb, var(--dsw-alias-state-warn-primary) 6%, transparent);
1644
+ }
1645
+
1646
+ .statHealth {
1647
+ display: flex;
1648
+ align-items: center;
1649
+ gap: 6px;
1650
+ padding: 0 12px;
1651
+ font-size: 12px;
1652
+ font-weight: 600;
1653
+ color: var(--dsw-alias-label-primary);
1654
+ white-space: nowrap;
1655
+ flex: none;
1656
+ }
1657
+
1658
+ /* 健康段兼作入口:仅在「存在未解决恢复事项」时渲染为按钮,直达备份页「事故恢复」。
1659
+ 其余状态仍是纯展示的 span,避免出现无落点的可点区域。 */
1660
+ .statHealthAction {
1661
+ border: none;
1662
+ background: none;
1663
+ font: inherit;
1664
+ font-size: 12px;
1665
+ font-weight: 600;
1666
+ cursor: pointer;
1667
+ text-align: left;
1668
+ }
1669
+
1670
+ .statHealthAction:hover {
1671
+ background: var(--dsw-alias-interactive-bg-hover);
1672
+ }
1673
+
1674
+ .statHealthAction:focus-visible {
1675
+ outline: 2px solid var(--dsw-alias-state-business-primary);
1676
+ outline-offset: -2px;
1677
+ border-radius: 6px;
1678
+ }
1679
+
1680
+ .statSeg {
1681
+ display: flex;
1682
+ align-items: center;
1683
+ gap: 6px;
1684
+ padding: 0 12px;
1685
+ border: none;
1686
+ border-left: 1px solid var(--dsw-alias-border-l1);
1687
+ background: none;
1688
+ font: inherit;
1689
+ font-size: 11.5px;
1690
+ color: var(--dsw-alias-label-secondary);
1691
+ white-space: nowrap;
1692
+ cursor: pointer;
1693
+ flex: none;
1694
+ }
1695
+
1696
+ /* 指标段标签:弱化、不换行,与加粗值形成清晰两级 */
1697
+ .statSeg > span:first-child {
1698
+ color: var(--dsw-alias-label-tertiary);
1699
+ }
1700
+
1701
+ .statSeg:hover {
1702
+ background: var(--dsw-alias-interactive-bg-hover);
1703
+ color: var(--dsw-alias-label-primary);
1704
+ }
1705
+
1706
+ .statSeg:hover > span:first-child {
1707
+ color: var(--dsw-alias-label-secondary);
1708
+ }
1709
+
1710
+ .statSeg:focus-visible {
1711
+ outline: 2px solid var(--dsw-alias-state-business-primary);
1712
+ outline-offset: -2px;
1713
+ }
1714
+
1715
+ .statSeg b {
1716
+ font-weight: 700;
1717
+ color: var(--dsw-alias-label-primary);
1718
+ font-variant-numeric: tabular-nums;
1719
+ }
1720
+
1721
+ .statSegDim {
1722
+ color: var(--dsw-alias-label-tertiary);
1723
+ }
1724
+
1725
+ /* —— 动作工具栏:主操作 + ghost 按钮一行(描述入 tooltip) —— */
1726
+ .toolRow {
1727
+ display: flex;
1728
+ align-items: center;
1729
+ gap: 8px;
1730
+ flex-wrap: wrap;
1731
+ margin-bottom: 10px;
1732
+ }
1733
+
1734
+ /* —— 备份位置信息块(两列 kv) —— */
1735
+ .infoGrid {
1736
+ display: grid;
1737
+ grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
1738
+ gap: 4px 24px;
1739
+ }
1740
+
1741
+ .infoRow {
1742
+ display: flex;
1743
+ align-items: baseline;
1744
+ gap: 8px;
1745
+ min-width: 0;
1746
+ font-size: 12px;
1747
+ padding: 2px 0;
1748
+ }
1749
+
1750
+ .infoKey {
1751
+ flex: none;
1752
+ width: 76px;
1753
+ color: var(--dsw-alias-label-tertiary);
1754
+ font-size: 11.5px;
1755
+ }
1756
+
1757
+ .infoValue {
1758
+ flex: 1 1 auto;
1759
+ min-width: 0;
1760
+ display: inline-flex;
1761
+ align-items: center;
1762
+ gap: 8px;
1763
+ }
1764
+
1765
+ .infoValue .mono {
1766
+ font-size: 11px;
1767
+ color: var(--dsw-alias-label-secondary);
1768
+ overflow: hidden;
1769
+ text-overflow: ellipsis;
1770
+ white-space: nowrap;
1771
+ }
1772
+
1773
+ /* 行内 copy 图标按钮(行内 hover 显示,减少视觉噪音) */
1774
+ .copyBtn {
1775
+ display: inline-flex;
1776
+ align-items: center;
1777
+ justify-content: center;
1778
+ width: 20px;
1779
+ height: 20px;
1780
+ padding: 0;
1781
+ border: none;
1782
+ border-radius: 4px;
1783
+ background: none;
1784
+ font: inherit;
1785
+ font-size: 11px;
1786
+ line-height: 1;
1787
+ color: var(--dsw-alias-label-tertiary);
1788
+ cursor: pointer;
1789
+ flex: none;
1790
+ }
1791
+
1792
+ .copyBtn:hover {
1793
+ background: var(--dsw-alias-interactive-bg-hover);
1794
+ color: var(--dsw-alias-label-primary);
1795
+ }
1796
+
1797
+ .copyBtn:focus-visible {
1798
+ outline: 2px solid var(--dsw-alias-state-business-primary);
1799
+ outline-offset: 1px;
1800
+ }
1801
+
1802
+ /* 活动行内的 copy 按钮:hover 行时显现 */
1803
+ .activityRow .copyBtn {
1804
+ opacity: 0;
1805
+ }
1806
+
1807
+ .activityRow:hover .copyBtn,
1808
+ .activityRow .copyBtn:focus-visible {
1809
+ opacity: 1;
1810
+ }
1811
+
1812
+ /* —— 活动卡(填充剩余高度;内部滚动) —— */
1813
+ .activityCard {
1814
+ display: flex;
1815
+ flex-direction: column;
1816
+ margin-bottom: 0;
1817
+ min-height: 0;
1818
+ }
1819
+
1820
+ .activityHeader {
1821
+ display: flex;
1822
+ align-items: center;
1823
+ gap: 8px;
1824
+ margin-bottom: 8px;
1825
+ }
1826
+
1827
+ .activityTitle {
1828
+ flex: 1 1 auto;
1829
+ font-size: 11px;
1830
+ font-weight: 700;
1831
+ letter-spacing: 0.02em;
1832
+ color: var(--dsw-alias-label-tertiary);
1833
+ }
1834
+
1835
+ .activityRows {
1836
+ /* 可收缩:卡片被页面挤压缩短时列表随之收缩(自身 overflow 内滚),
1837
+ 否则列表保持 272px 而卡片变矮 → 内容溢出卡片边框(曾实测 274px 内容 vs 205px 卡片)。 */
1838
+ flex: 0 1 auto;
1839
+ min-height: 0;
1840
+ overflow-y: auto;
1841
+ border: 1px solid var(--dsw-alias-border-l1);
1842
+ border-radius: 8px;
1843
+ background: var(--dsw-alias-bg-base);
1844
+ }
1845
+
1846
+ /* 自适应上限变体:fit-content,超过 8 行内部滚动(不再强制撑出空黑块) */
1847
+ .activityFit {
1848
+ max-height: 272px;
1849
+ }
1850
+
1851
+ .activityRow {
1852
+ display: grid;
1853
+ grid-template-columns: 72px minmax(0, 1fr) auto;
1854
+ align-items: center;
1855
+ gap: 10px;
1856
+ padding: 5px 10px;
1857
+ border-bottom: 1px solid color-mix(in srgb, var(--dsw-alias-border-l1) 55%, transparent);
1858
+ font-size: 11.5px;
1859
+ line-height: 1.5;
1860
+ min-width: 0;
1861
+ }
1862
+
1863
+ .activityRow:last-child {
1864
+ border-bottom: none;
1865
+ }
1866
+
1867
+ .activityTime {
1868
+ justify-self: end;
1869
+ line-height: 1.5;
1870
+ color: var(--dsw-alias-label-tertiary);
1871
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
1872
+ font-size: 10.5px;
1873
+ white-space: nowrap;
1874
+ }
1875
+
1876
+ .activityKind {
1877
+ flex: none;
1878
+ line-height: 1.5;
1879
+ color: var(--dsw-alias-label-tertiary);
1880
+ font-size: 11px;
1881
+ white-space: nowrap;
1882
+ }
1883
+
1884
+ .activitySummary {
1885
+ min-width: 0;
1886
+ line-height: 1.5;
1887
+ display: inline-flex;
1888
+ align-items: center;
1889
+ gap: 6px;
1890
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
1891
+ font-size: 11px;
1892
+ color: var(--dsw-alias-label-secondary);
1893
+ }
1894
+
1895
+ .activitySummaryText {
1896
+ overflow: hidden;
1897
+ text-overflow: ellipsis;
1898
+ white-space: nowrap;
1899
+ }
1900
+
1901
+ .activityBadge {
1902
+ flex: none;
1903
+ display: inline-flex;
1904
+ align-items: center;
1905
+ justify-content: flex-end;
1906
+ line-height: 1.5;
1907
+ }
1908
+
1909
+ /* 活动行成功态降噪(绿点 + 灰字,替代全绿徽章) */
1910
+ .activityResultOk {
1911
+ display: inline-flex;
1912
+ align-items: center;
1913
+ gap: 5px;
1914
+ line-height: 1.5;
1915
+ font-size: 11px;
1916
+ color: var(--dsw-alias-label-tertiary);
1917
+ white-space: nowrap;
1918
+ }
1919
+
1920
+ /* —— 备份位置卡:四列事实网格(标签上、值下,tabular-nums 对齐) —— */
1921
+ .factGrid {
1922
+ display: grid;
1923
+ grid-template-columns: repeat(4, minmax(0, 1fr));
1924
+ gap: 6px 12px;
1925
+ }
1926
+
1927
+ .factCell {
1928
+ display: flex;
1929
+ flex-direction: column;
1930
+ gap: 2px;
1931
+ min-width: 0;
1932
+ }
1933
+
1934
+ .factLabel {
1935
+ font-size: 10.5px;
1936
+ color: var(--dsw-alias-label-tertiary);
1937
+ white-space: nowrap;
1938
+ }
1939
+
1940
+ .factValue {
1941
+ font-size: 12px;
1942
+ font-weight: 600;
1943
+ color: var(--dsw-alias-label-primary);
1944
+ white-space: nowrap;
1945
+ overflow: hidden;
1946
+ text-overflow: ellipsis;
1947
+ }
1948
+
1949
+ /* —— 分区构成卡:两列网格行(名称 | 条目数 | 体积) ——
1950
+ 用 auto-fit,窄容器(弹窗内的分区构成)自动退化为单列,
1951
+ 宽容器(总览 / 导出预览弹窗)仍是两列。 */
1952
+ .sectionGrid {
1953
+ display: grid;
1954
+ grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
1955
+ gap: 0 28px;
1956
+ }
1957
+
1958
+ .sectionRow {
1959
+ display: grid;
1960
+ grid-template-columns: minmax(0, 1fr) auto 56px;
1961
+ align-items: center;
1962
+ gap: 10px;
1963
+ padding: 4px 0;
1964
+ border-bottom: 1px solid color-mix(in srgb, var(--dsw-alias-border-l1) 55%, transparent);
1965
+ font-size: 11.5px;
1966
+ min-width: 0;
1967
+ }
1968
+
1969
+ .sectionRow:nth-last-child(-n+2) {
1970
+ border-bottom: none;
1971
+ }
1972
+
1973
+ .sectionName {
1974
+ min-width: 0;
1975
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
1976
+ font-size: 11px;
1977
+ color: var(--dsw-alias-label-secondary);
1978
+ overflow: hidden;
1979
+ text-overflow: ellipsis;
1980
+ white-space: nowrap;
1981
+ }
1982
+
1983
+ .sectionCount {
1984
+ justify-self: end;
1985
+ color: var(--dsw-alias-label-tertiary);
1986
+ font-size: 10.5px;
1987
+ font-variant-numeric: tabular-nums;
1988
+ white-space: nowrap;
1989
+ }
1990
+
1991
+ .sectionSize {
1992
+ justify-self: end;
1993
+ font-size: 10.5px;
1994
+ color: var(--dsw-alias-label-secondary);
1995
+ font-variant-numeric: tabular-nums;
1996
+ white-space: nowrap;
1997
+ }
1998
+
1999
+ /* CJK 断行纪律:插入语不劈词 */
2000
+ .quickActionHint,
2001
+ .todoText {
2002
+ line-break: strict;
2003
+ }
2004
+
2005
+ /* 活动空态(紧凑) */
2006
+ .activityEmpty {
2007
+ padding: 16px;
2008
+ font-size: 11.5px;
2009
+ color: var(--dsw-alias-label-tertiary);
2010
+ text-align: center;
2011
+ }
2012
+
2013
+ .ovGrid {
2014
+ display: grid;
2015
+ grid-template-columns: minmax(0, 1fr) 200px;
2016
+ gap: 10px;
2017
+ align-items: start;
2018
+ }
2019
+
2020
+ .ovMain {
2021
+ min-width: 0;
2022
+ }
2023
+
2024
+ .ovSide {
2025
+ min-width: 0;
2026
+ display: flex;
2027
+ flex-direction: column;
2028
+ gap: 10px;
2029
+ }
2030
+
2031
+ /* 快速操作:紧凑网格 */
2032
+ .quickGrid {
2033
+ display: grid;
2034
+ grid-template-columns: repeat(4, minmax(0, 1fr));
2035
+ gap: 6px;
2036
+ margin-bottom: 10px;
2037
+ }
2038
+
2039
+ .quickAction {
2040
+ display: flex;
2041
+ flex-direction: column;
2042
+ gap: 3px;
2043
+ padding: 9px 10px;
2044
+ border: 1px solid var(--dsw-alias-border-l2);
2045
+ border-radius: 7px;
2046
+ background: var(--dsw-alias-bg-base);
2047
+ font: inherit;
2048
+ text-align: left;
2049
+ cursor: pointer;
2050
+ }
2051
+
2052
+ .quickAction:hover:not(:disabled) {
2053
+ border-color: color-mix(in srgb, var(--dsw-alias-state-business-primary) 45%, var(--dsw-alias-border-l2));
2054
+ background: color-mix(in srgb, var(--dsw-alias-state-business-primary) 5%, transparent);
2055
+ }
2056
+
2057
+ .quickAction:focus-visible {
2058
+ outline: 2px solid var(--dsw-alias-state-business-primary);
2059
+ outline-offset: 1px;
2060
+ }
2061
+
2062
+ .quickAction:disabled {
2063
+ opacity: 0.5;
2064
+ cursor: default;
2065
+ }
2066
+
2067
+ .quickActionSymbol {
2068
+ font-size: 13px;
2069
+ color: var(--dsw-alias-state-business-primary);
2070
+ line-height: 1;
2071
+ }
2072
+
2073
+ .quickActionTitle {
2074
+ display: flex;
2075
+ align-items: center;
2076
+ gap: 5px;
2077
+ font-size: 12px;
2078
+ font-weight: 600;
2079
+ color: var(--dsw-alias-label-primary);
2080
+ }
2081
+
2082
+ .quickActionHint {
2083
+ font-size: 10.5px;
2084
+ line-height: 1.45;
2085
+ color: var(--dsw-alias-label-tertiary);
2086
+ }
2087
+
2088
+ /* 活动列表 */
2089
+ .ovActivity {
2090
+ display: flex;
2091
+ flex-direction: column;
2092
+ }
2093
+
2094
+ .ovActivityItem {
2095
+ display: flex;
2096
+ align-items: flex-start;
2097
+ gap: 7px;
2098
+ padding: 6px 0;
2099
+ border-bottom: 1px solid color-mix(in srgb, var(--dsw-alias-border-l1) 55%, transparent);
2100
+ font-size: 11.5px;
2101
+ min-width: 0;
2102
+ }
2103
+
2104
+ .ovActivityItem:last-child {
2105
+ border-bottom: none;
2106
+ }
2107
+
2108
+ .ovActivityTime {
2109
+ flex: none;
2110
+ width: 58px;
2111
+ color: var(--dsw-alias-label-tertiary);
2112
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
2113
+ font-size: 10.5px;
2114
+ padding-top: 1px;
2115
+ }
2116
+
2117
+ .ovActivityText {
2118
+ flex: 1 1 auto;
2119
+ min-width: 0;
2120
+ overflow-wrap: anywhere;
2121
+ color: var(--dsw-alias-label-secondary);
2122
+ }
2123
+
2124
+ /* 待办/建议行 */
2125
+ .todoRow {
2126
+ display: flex;
2127
+ align-items: center;
2128
+ gap: 8px;
2129
+ padding: 7px 10px;
2130
+ border: 1px solid color-mix(in srgb, var(--dsw-alias-state-warn-primary) 35%, transparent);
2131
+ border-radius: 7px;
2132
+ background: color-mix(in srgb, var(--dsw-alias-state-warn-primary) 7%, transparent);
2133
+ font-size: 12px;
2134
+ margin-bottom: 6px;
2135
+ }
2136
+
2137
+ .todoRow:last-child {
2138
+ margin-bottom: 0;
2139
+ }
2140
+
2141
+ .todoText {
2142
+ flex: 1 1 auto;
2143
+ min-width: 0;
2144
+ color: var(--dsw-alias-label-primary);
2145
+ }
2146
+
2147
+ /* ================================================================ §8 Page: Backups */
2148
+
2149
+ .snapshotList,
2150
+ .backupFileList {
2151
+ display: flex;
2152
+ flex-direction: column;
2153
+ gap: 6px;
2154
+ margin-bottom: 10px;
2155
+ }
2156
+
2157
+ .snapshotRow,
2158
+ .backupFileRow {
2159
+ border: 1px solid var(--dsw-alias-border-l1);
2160
+ border-radius: 8px;
2161
+ background: var(--dsw-alias-bg-layer-2);
2162
+ padding: 9px 12px;
2163
+ }
2164
+
2165
+ .snapshotRow[data-selected],
2166
+ .backupFileRow[data-selected] {
2167
+ border-color: var(--dsw-alias-state-business-primary);
2168
+ background: color-mix(in srgb, var(--dsw-alias-state-business-primary) 7%, transparent);
2169
+ }
2170
+
2171
+ .snapshotRowHeader,
2172
+ .backupFileMeta {
2173
+ display: flex;
2174
+ align-items: center;
2175
+ gap: 8px;
2176
+ font-size: 12px;
2177
+ }
2178
+
2179
+ .snapshotRowMain,
2180
+ .backupFileName {
2181
+ flex: 1 1 auto;
2182
+ min-width: 0;
2183
+ font-weight: 500;
2184
+ overflow: hidden;
2185
+ text-overflow: ellipsis;
2186
+ white-space: nowrap;
2187
+ }
2188
+
2189
+ .backupFileNote {
2190
+ font-size: 11px;
2191
+ color: var(--dsw-alias-label-tertiary);
2192
+ }
2193
+
2194
+ /* 咨询卡「建议依据」:去重后每条独占一行。
2195
+ flex-basis:100% 是必需的 —— .banner 是 flex+wrap,「建议依据」标题与
2196
+ 本列表是同一行的兄弟项,列表必须独占整行才谈得上「换行」。 */
2197
+ .reasonList {
2198
+ display: flex;
2199
+ flex-direction: column;
2200
+ gap: 4px;
2201
+ flex-basis: 100%;
2202
+ min-width: 0;
2203
+ }
2204
+
2205
+ .reasonLine {
2206
+ display: flex;
2207
+ align-items: baseline;
2208
+ gap: 6px;
2209
+ min-width: 0;
2210
+ }
2211
+
2212
+ .reasonLine > span:first-child {
2213
+ min-width: 0;
2214
+ overflow-wrap: anywhere;
2215
+ }
2216
+
2217
+ /* ================================================================ §9 Page: Export / Import */
2218
+
2219
+ .viewBody {
2220
+ flex: 1 1 auto;
2221
+ display: flex;
2222
+ flex-direction: column;
2223
+ min-height: 0;
2224
+ min-width: 0;
2225
+ /* 页面根即纵向 flex:最后一个内容块可用 margin-top:auto / flex 填充贴底 */
2226
+ }
2227
+
2228
+ /* 页面可伸展填充块(如总览的最近活动卡) */
2229
+ .fillCard {
2230
+ flex: 1 1 auto;
2231
+ margin-bottom: 0;
2232
+ }
2233
+
2234
+ /* 填充视口(卡片内列表容器撑满剩余高度,读作文件管理器视口) */
2235
+ .fillViewport {
2236
+ flex: 1 1 auto;
2237
+ min-height: 0;
2238
+ display: flex;
2239
+ flex-direction: column;
2240
+ margin-bottom: 0;
2241
+ }
2242
+
2243
+ .fillViewport .tableScroll {
2244
+ flex: 1 1 auto;
2245
+ max-height: none;
2246
+ }
2247
+
2248
+ /* 稀疏步骤顶部对齐填充(导入「选择 ZIP」等内容极少的步骤):
2249
+ 内容贴顶排布在剩余视口内,不再垂直居中(居中会让 CTA 悬在页面中段、与步骤条脱节)。 */
2250
+ .sparseFill {
2251
+ flex: 1 1 auto;
2252
+ display: flex;
2253
+ flex-direction: column;
2254
+ align-items: flex-start;
2255
+ justify-content: flex-start;
2256
+ gap: 10px;
2257
+ min-height: 280px;
2258
+ }
2259
+
2260
+ /* 导出分组目录(两列致密勾选网格) */
2261
+ .exportGrid {
2262
+ display: grid;
2263
+ grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
2264
+ gap: 8px 12px;
2265
+ margin-bottom: 10px;
2266
+ }
2267
+
2268
+ .exportGroup {
2269
+ border: 1px solid var(--dsw-alias-border-l1);
2270
+ border-radius: 8px;
2271
+ background: var(--dsw-alias-bg-layer-2);
2272
+ padding: 10px 12px;
2273
+ min-width: 0;
2274
+ }
2275
+
2276
+ .exportItems {
2277
+ display: flex;
2278
+ flex-direction: column;
2279
+ gap: 4px;
2280
+ }
2281
+
2282
+ .exportItem {
2283
+ min-width: 0;
2284
+ padding: 1px 0;
2285
+ }
2286
+
2287
+ /* 选项行(加密/导出密钥复选内联) */
2288
+ .optionsRow {
2289
+ display: flex;
2290
+ align-items: center;
2291
+ gap: 18px;
2292
+ margin-bottom: 4px;
2293
+ }
2294
+
2295
+ .groupList {
2296
+ display: flex;
2297
+ flex-direction: column;
2298
+ gap: 8px;
2299
+ margin-bottom: 10px;
2300
+ }
2301
+
2302
+ .groupCard {
2303
+ margin: 0;
2304
+ }
2305
+
2306
+ .categoryItem {
2307
+ display: flex;
2308
+ align-items: baseline;
2309
+ gap: 8px;
2310
+ min-width: 0;
2311
+ flex-wrap: wrap;
2312
+ }
2313
+
2314
+ .categoryName {
2315
+ font-weight: 500;
2316
+ color: var(--dsw-alias-label-primary);
2317
+ flex: none;
2318
+ }
2319
+
2320
+ .categoryDesc {
2321
+ font-size: 11px;
2322
+ color: var(--dsw-alias-label-tertiary);
2323
+ min-width: 0;
2324
+ }
2325
+
2326
+ .optionsCard {
2327
+ margin: 0 0 10px;
2328
+ }
2329
+
2330
+ .optionsHeader {
2331
+ display: block;
2332
+ font-size: 11px;
2333
+ font-weight: 700;
2334
+ color: var(--dsw-alias-label-tertiary);
2335
+ margin-bottom: 8px;
2336
+ }
2337
+
2338
+ .secretFields {
2339
+ display: grid;
2340
+ grid-template-columns: 1fr 1fr;
2341
+ gap: 0 10px;
2342
+ padding: 0;
2343
+ border: none;
2344
+ border-radius: 0;
2345
+ /* 与页面同底:原先用 --dsw-alias-bg-base,暗色下比宿主面板底色更暗
2346
+ (#151517 vs #2c2c2e),「自定义文件名 / 备注」会呈现成一块突兀的深色面板。 */
2347
+ background: none;
2348
+ margin: 6px 0 10px;
2349
+ }
2350
+
2351
+ .warnList {
2352
+ margin: 4px 0 0;
2353
+ padding-left: 18px;
2354
+ font-size: 11.5px;
2355
+ color: var(--dsw-alias-label-secondary);
2356
+ }
2357
+
2358
+ .wizardCard {
2359
+ margin: 0 0 10px;
2360
+ }
2361
+
2362
+ .wizardStepperRow {
2363
+ display: flex;
2364
+ align-items: center;
2365
+ gap: 10px;
2366
+ margin-bottom: 10px;
2367
+ }
2368
+
2369
+ /* 配置更改明细(ConflictList 的 .conflictDetail)与路径映射块都已经自带
2370
+ 边框与内边距,这里补一点与上方描述之间的呼吸。 */
2371
+ .conflictDetail {
2372
+ margin-top: 2px;
2373
+ }
2374
+
2375
+ /* 冲突列表 */
2376
+ .conflictList {
2377
+ display: flex;
2378
+ flex-direction: column;
2379
+ gap: 8px;
2380
+ margin-bottom: 10px;
2381
+ }
2382
+
2383
+ .conflictItem {
2384
+ border: 1px solid color-mix(in srgb, var(--dsw-alias-state-warn-primary) 35%, transparent);
2385
+ border-radius: 8px;
2386
+ background: var(--dsw-alias-bg-layer-2);
2387
+ padding: 10px 12px;
2388
+ }
2389
+
2390
+ .conflictHead {
2391
+ display: flex;
2392
+ align-items: center;
2393
+ gap: 8px;
2394
+ margin-bottom: 6px;
2395
+ font-size: 12px;
2396
+ }
2397
+
2398
+ .conflictId {
2399
+ font-weight: 600;
2400
+ color: var(--dsw-alias-label-primary);
2401
+ min-width: 0;
2402
+ overflow: hidden;
2403
+ text-overflow: ellipsis;
2404
+ white-space: nowrap;
2405
+ }
2406
+
2407
+ .conflictOptions {
2408
+ display: flex;
2409
+ flex-wrap: wrap;
2410
+ gap: 4px 14px;
2411
+ margin-top: 6px;
2412
+ }
2413
+
2414
+ /* 选边卡片:保留当前 / 使用备份 两块并排,选中高亮 */
2415
+ .conflictChoices {
2416
+ display: grid;
2417
+ grid-template-columns: repeat(2, minmax(0, 1fr));
2418
+ gap: 8px;
2419
+ margin-top: 8px;
2420
+ }
2421
+
2422
+ .choiceCard {
2423
+ display: flex;
2424
+ align-items: center;
2425
+ gap: 7px;
2426
+ padding: 8px 10px;
2427
+ border: 1px solid var(--dsw-alias-border-l2);
2428
+ border-radius: 7px;
2429
+ background: var(--dsw-alias-bg-base);
2430
+ font-size: 12px;
2431
+ font-weight: 500;
2432
+ color: var(--dsw-alias-label-secondary);
2433
+ cursor: pointer;
2434
+ transition: border-color 120ms ease-out, background-color 120ms ease-out;
2435
+ }
2436
+
2437
+ .choiceCard:hover {
2438
+ border-color: color-mix(in srgb, var(--dsw-alias-state-business-primary) 40%, var(--dsw-alias-border-l2));
2439
+ }
2440
+
2441
+ .choiceCard:focus-within {
2442
+ outline: 2px solid var(--dsw-alias-state-business-primary);
2443
+ outline-offset: 1px;
2444
+ }
2445
+
2446
+ .choiceCard[data-selected] {
2447
+ border-color: var(--dsw-alias-state-business-primary);
2448
+ background: color-mix(in srgb, var(--dsw-alias-state-business-primary) 9%, transparent);
2449
+ color: var(--dsw-alias-label-primary);
2450
+ }
2451
+
2452
+ .choiceCard input {
2453
+ width: 13px;
2454
+ height: 13px;
2455
+ margin: 0;
2456
+ accent-color: var(--dsw-alias-state-business-primary);
2457
+ flex: none;
2458
+ }
2459
+
2460
+ .choiceTitle {
2461
+ min-width: 0;
2462
+ }
2463
+
2464
+ .conflictDetail {
2465
+ padding: 8px 10px;
2466
+ border: 1px solid var(--dsw-alias-border-l1);
2467
+ border-radius: 6px;
2468
+ background: var(--dsw-alias-bg-base);
2469
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
2470
+ font-size: 11px;
2471
+ color: var(--dsw-alias-label-secondary);
2472
+ overflow-wrap: anywhere;
2473
+ /* 原为 <pre>(white-space:pre 不换行)→ 长配置会横向溢出并产生左右滚动条;
2474
+ 现改普通块:换行(含长路径/JSON 的任意位置折行)。 */
2475
+ white-space: normal;
2476
+ }
2477
+
2478
+ /* 配置更改明细:prefix(如 namespace= / 行号)→ current 行 → 分割线 → imported 行 */
2479
+ .conflictPrefix {
2480
+ margin-bottom: 4px;
2481
+ color: var(--dsw-alias-label-tertiary);
2482
+ }
2483
+
2484
+ .conflictLine {
2485
+ display: flex;
2486
+ align-items: baseline;
2487
+ gap: 8px;
2488
+ padding: 5px 0;
2489
+ }
2490
+
2491
+ /* 两行之间的分割线(第一行不加,避免与容器上边框重复) */
2492
+ .conflictLine + .conflictLine {
2493
+ border-top: 1px solid color-mix(in srgb, var(--dsw-alias-border-l1) 55%, transparent);
2494
+ }
2495
+
2496
+ .conflictLineLabel {
2497
+ flex: none;
2498
+ min-width: 56px;
2499
+ font-weight: 600;
2500
+ color: var(--dsw-alias-label-tertiary);
2501
+ }
2502
+
2503
+ .conflictLineValue {
2504
+ flex: 1 1 auto;
2505
+ min-width: 0;
2506
+ /* 长 JSON 不撑破容器:任意位置折行 */
2507
+ overflow-wrap: anywhere;
2508
+ }
2509
+
2510
+ /* 路径映射 */
2511
+ .pathMappingList {
2512
+ display: flex;
2513
+ flex-direction: column;
2514
+ gap: 6px;
2515
+ margin-bottom: 10px;
2516
+ }
2517
+
2518
+ /* 路径映射:每条 issue = 「原路径」块在上、「新路径」块在下(各自整宽) */
2519
+ .pathRow {
2520
+ display: flex;
2521
+ flex-direction: column;
2522
+ align-items: stretch;
2523
+ gap: 8px;
2524
+ padding: 8px 10px;
2525
+ border: 1px solid var(--dsw-alias-border-l1);
2526
+ border-radius: 7px;
2527
+ background: var(--dsw-alias-bg-layer-2);
2528
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
2529
+ font-size: 11px;
2530
+ }
2531
+
2532
+ .pathOld,
2533
+ .pathNew {
2534
+ min-width: 0;
2535
+ width: 100%;
2536
+ /* 纵向列容器:让内部 input 拉满块宽(等价于旧版全局 .input{width:100%} 的效果,
2537
+ 但不影响行内 flex 里的 select) */
2538
+ display: flex;
2539
+ flex-direction: column;
2540
+ padding: 5px 8px;
2541
+ border: 1px solid var(--dsw-alias-border-l2);
2542
+ border-radius: 6px;
2543
+ background: var(--dsw-alias-bg-base);
2544
+ overflow-wrap: anywhere;
2545
+ flex: 1 1 auto;
2546
+ }
2547
+
2548
+ .pathValue {
2549
+ color: var(--dsw-alias-label-secondary);
2550
+ /* 等宽长路径折行:<pre> 默认不换行会横向溢出卡片 */
2551
+ white-space: pre-wrap;
2552
+ overflow-wrap: anywhere;
2553
+ margin: 2px 0 0;
2554
+ }
2555
+
2556
+ .pathIssueKind {
2557
+ flex: none;
2558
+ }
2559
+
2560
+ /* 密钥补录 */
2561
+ .secretsList {
2562
+ display: flex;
2563
+ flex-direction: column;
2564
+ }
2565
+
2566
+ /* 快照选择行(同步页):下拉 + 「刷新快照列表」按钮强制同一行 ——
2567
+ nowrap + 下拉列可收缩(minWidth:0)+ 按钮列 flex:none。
2568
+ 窄画布下宁可下拉变窄,也不让按钮换到下一行。 */
2569
+ .snapshotPickerRow {
2570
+ display: flex;
2571
+ align-items: flex-end;
2572
+ flex-wrap: nowrap;
2573
+ gap: 8px;
2574
+ margin-top: 10px;
2575
+ }
2576
+
2577
+ /* 该行内的字段标签归零底部外边距:.field 自带 margin-bottom:10px,
2578
+ 会让标签的 margin-box 比 select 低 10px,flex-end 对齐时按钮
2579
+ 被一并推低 10px(实测 select 底 1042 vs 按钮底 1052)→ 视觉上「不在一条线上」。 */
2580
+ .snapshotPickerRow .field {
2581
+ margin-bottom: 0;
2582
+ }
2583
+
2584
+ .pickerAction {
2585
+ flex: none;
2586
+ display: inline-flex;
2587
+ align-items: center;
2588
+ }
2589
+
2590
+ /* 导入日志面板 */
2591
+ .logPanel {
2592
+ border: 1px solid var(--dsw-alias-border-l1);
2593
+ border-radius: 8px;
2594
+ background: var(--dsw-alias-bg-base);
2595
+ overflow: hidden;
2596
+ margin-bottom: 10px;
2597
+ }
2598
+
2599
+ .logHeader {
2600
+ display: flex;
2601
+ align-items: center;
2602
+ gap: 8px;
2603
+ padding: 6px 10px;
2604
+ border-bottom: 1px solid var(--dsw-alias-border-l1);
2605
+ font-size: 11px;
2606
+ font-weight: 600;
2607
+ color: var(--dsw-alias-label-tertiary);
2608
+ background: var(--dsw-alias-bg-layer-2);
2609
+ }
2610
+
2611
+ .logLine {
2612
+ padding: 1px 10px;
2613
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
2614
+ font-size: 11px;
2615
+ line-height: 1.6;
2616
+ color: var(--dsw-alias-label-secondary);
2617
+ white-space: pre-wrap;
2618
+ overflow-wrap: anywhere;
2619
+ }
2620
+
2621
+ .logEmpty {
2622
+ padding: 12px;
2623
+ font-size: 11px;
2624
+ color: var(--dsw-alias-label-tertiary);
2625
+ text-align: center;
2626
+ }
2627
+
2628
+ .logJumpButton {
2629
+ margin-left: auto;
2630
+ border: none;
2631
+ background: none;
2632
+ font: inherit;
2633
+ font-size: 11px;
2634
+ color: var(--dsw-alias-state-business-primary);
2635
+ cursor: pointer;
2636
+ padding: 0 4px;
2637
+ }
2638
+
2639
+ /* 报告 / 错误 */
2640
+ .reportView {
2641
+ border: 1px solid var(--dsw-alias-border-l1);
2642
+ border-radius: 8px;
2643
+ background: var(--dsw-alias-bg-layer-2);
2644
+ overflow: hidden;
2645
+ margin-bottom: 10px;
2646
+ }
2647
+
2648
+ .reportList {
2649
+ display: flex;
2650
+ flex-direction: column;
2651
+ }
2652
+
2653
+ .reportText {
2654
+ font-size: 12px;
2655
+ color: var(--dsw-alias-label-secondary);
2656
+ }
2657
+
2658
+ .reportFooter {
2659
+ display: flex;
2660
+ align-items: center;
2661
+ gap: 8px;
2662
+ padding: 8px 12px;
2663
+ border-top: 1px solid var(--dsw-alias-border-l1);
2664
+ background: var(--dsw-alias-bg-base);
2665
+ }
2666
+
2667
+ .errorBanner {
2668
+ display: flex;
2669
+ align-items: flex-start;
2670
+ gap: 8px;
2671
+ padding: 9px 12px;
2672
+ border: 1px solid color-mix(in srgb, var(--dsw-alias-state-error-primary) 45%, transparent);
2673
+ border-radius: 8px;
2674
+ background: color-mix(in srgb, var(--dsw-alias-state-error-primary) 8%, transparent);
2675
+ margin: 0 0 10px;
2676
+ font-size: 12px;
2677
+ }
2678
+
2679
+ .errorTitle {
2680
+ font-weight: 600;
2681
+ color: var(--dsw-alias-state-error-primary);
2682
+ }
2683
+
2684
+ .errorLine {
2685
+ overflow-wrap: anywhere;
2686
+ color: var(--dsw-alias-label-secondary);
2687
+ }
2688
+
2689
+ .errorList {
2690
+ margin: 4px 0 0;
2691
+ padding-left: 18px;
2692
+ font-size: 11.5px;
2693
+ }
2694
+
2695
+ .errorItem {
2696
+ overflow-wrap: anywhere;
2697
+ }
2698
+
2699
+ .errorReason {
2700
+ color: var(--dsw-alias-label-tertiary);
2701
+ }
2702
+
2703
+ .errorFooter {
2704
+ margin-top: 6px;
2705
+ }
2706
+
2707
+ .errorAction {
2708
+ margin-right: 8px;
2709
+ }
2710
+
2711
+ .errorActionLabel {
2712
+ color: var(--dsw-alias-state-business-primary);
2713
+ }
2714
+
2715
+ /* 恢复计划 / 差异查看 */
2716
+ .inspectGroup {
2717
+ margin-bottom: 10px;
2718
+ }
2719
+
2720
+ .kindTag {
2721
+ display: inline-flex;
2722
+ align-items: center;
2723
+ height: 16px;
2724
+ padding: 0 6px;
2725
+ border-radius: 4px;
2726
+ background: var(--dsw-alias-interactive-bg-hover);
2727
+ font-size: 10px;
2728
+ font-weight: 600;
2729
+ color: var(--dsw-alias-label-secondary);
2730
+ white-space: nowrap;
2731
+ }
2732
+
2733
+ .kindTagOk {
2734
+ background: color-mix(in srgb, var(--dsw-alias-state-success-primary) 13%, transparent);
2735
+ color: var(--dsw-alias-state-success-primary);
2736
+ }
2737
+
2738
+ .kindTagInfo {
2739
+ background: color-mix(in srgb, var(--dsw-alias-state-business-primary) 13%, transparent);
2740
+ color: var(--dsw-alias-state-business-primary);
2741
+ }
2742
+
2743
+ .kindTagWarn {
2744
+ background: color-mix(in srgb, var(--dsw-alias-state-warn-primary) 13%, transparent);
2745
+ color: var(--dsw-alias-state-warn-primary);
2746
+ }
2747
+
2748
+ .kindTagError {
2749
+ background: color-mix(in srgb, var(--dsw-alias-state-error-primary) 13%, transparent);
2750
+ color: var(--dsw-alias-state-error-primary);
2751
+ }
2752
+
2753
+ .nextStepsGroup {
2754
+ margin-bottom: 10px;
2755
+ }
2756
+
2757
+ .rollbackBox {
2758
+ border: 1px solid var(--dsw-alias-border-l2);
2759
+ border-radius: 7px;
2760
+ background: var(--dsw-alias-bg-base);
2761
+ padding: 8px 10px;
2762
+ margin-bottom: 10px;
2763
+ }
2764
+
2765
+ .statRow {
2766
+ display: flex;
2767
+ align-items: center;
2768
+ flex-wrap: wrap;
2769
+ gap: 8px;
2770
+ margin-top: 8px;
2771
+ }
2772
+
2773
+ /* 徽章行下方留出间距,避免与紧随其后的面板(兼容性/导入预览的黄色警示条、
2774
+ 咨询卡的建议依据)挤在一起;作为容器末子元素时不补(否则卡片底部会多一段空白)。 */
2775
+ .statRow:not(:last-child) {
2776
+ margin-bottom: 10px;
2777
+ }
2778
+
2779
+ /* 咨询卡内的徽章行:与上方小节标题拉开一点距离(原先与标题贴在一起) */
2780
+ .consultSection {
2781
+ margin-top: 10px;
2782
+ }
2783
+
2784
+ .consultSection:first-of-type {
2785
+ margin-top: 8px;
2786
+ }
2787
+
2788
+ .consultSection .statRow {
2789
+ margin-top: 0;
2790
+ }
2791
+
2792
+ .hiddenFile {
2793
+ display: none;
2794
+ }
2795
+
2796
+ .cliName,
2797
+ .cliCommand {
2798
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
2799
+ font-size: 11px;
2800
+ }
2801
+
2802
+ .cliCommand {
2803
+ color: var(--dsw-alias-label-secondary);
2804
+ overflow-wrap: anywhere;
2805
+ }
2806
+
2807
+ /* ================================================================ §10-13 过渡页样式(逐页重建时替换/细化) */
2808
+
2809
+ .syncChannelHead {
2810
+ display: flex;
2811
+ align-items: center;
2812
+ gap: 8px;
2813
+ margin-bottom: 8px;
2814
+ }
2815
+
2816
+ .historyGroup {
2817
+ margin-bottom: 12px;
2818
+ }
2819
+
2820
+ .historyRow {
2821
+ display: flex;
2822
+ align-items: flex-start;
2823
+ gap: 8px;
2824
+ padding: 6px 0;
2825
+ border-bottom: 1px solid color-mix(in srgb, var(--dsw-alias-border-l1) 55%, transparent);
2826
+ font-size: 12px;
2827
+ }
2828
+
2829
+ .historyRow:last-child {
2830
+ border-bottom: none;
2831
+ }
2832
+
2833
+ .historyRowMain {
2834
+ flex: 1 1 auto;
2835
+ min-width: 0;
2836
+ }
2837
+
2838
+ .historySummary {
2839
+ overflow-wrap: anywhere;
2840
+ color: var(--dsw-alias-label-secondary);
2841
+ }
2842
+
2843
+ .historyTime {
2844
+ flex: none;
2845
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
2846
+ font-size: 10.5px;
2847
+ color: var(--dsw-alias-label-tertiary);
2848
+ padding-top: 1px;
2849
+ }
2850
+
2851
+ .historySections {
2852
+ font-size: 11px;
2853
+ color: var(--dsw-alias-label-tertiary);
2854
+ }
2855
+
2856
+ .profileRow {
2857
+ border: 1px solid var(--dsw-alias-border-l1);
2858
+ border-radius: 8px;
2859
+ background: var(--dsw-alias-bg-layer-2);
2860
+ padding: 9px 12px;
2861
+ margin-bottom: 6px;
2862
+ }
2863
+
2864
+ .profileRow[data-selected] {
2865
+ border-color: var(--dsw-alias-state-business-primary);
2866
+ background: color-mix(in srgb, var(--dsw-alias-state-business-primary) 7%, transparent);
2867
+ }
2868
+
2869
+ .profileRowHeader {
2870
+ display: flex;
2871
+ align-items: center;
2872
+ gap: 8px;
2873
+ font-size: 12px;
2874
+ }
2875
+
2876
+ .profileRowMain {
2877
+ flex: 1 1 auto;
2878
+ min-width: 0;
2879
+ font-weight: 500;
2880
+ overflow: hidden;
2881
+ text-overflow: ellipsis;
2882
+ white-space: nowrap;
2883
+ }
2884
+
2885
+ /* 档案名按钮重置(透明、左对齐) */
2886
+ button.profileRowMain {
2887
+ border: none;
2888
+ background: none;
2889
+ font: inherit;
2890
+ color: var(--dsw-alias-label-primary);
2891
+ text-align: left;
2892
+ cursor: pointer;
2893
+ padding: 0;
2894
+ }
2895
+
2896
+ button.profileRowMain:hover {
2897
+ color: var(--dsw-alias-state-business-primary);
2898
+ }
2899
+
2900
+ .aboutLinkRow {
2901
+ display: flex;
2902
+ align-items: center;
2903
+ gap: 8px;
2904
+ flex-wrap: wrap;
2905
+ }
2906
+
2907
+ /* 作者名外链(AboutPanel):该组件一直在引用本类,但此前从未定义 ——
2908
+ 作者名因此落回浏览器默认 <a> 样式(下划线 + 字号/行高与相邻标签不一致)。 */
2909
+ .aboutAuthor {
2910
+ font-size: 12.5px;
2911
+ font-weight: 600;
2912
+ color: var(--dsw-alias-state-business-primary);
2913
+ text-decoration: none;
2914
+ overflow-wrap: anywhere;
2915
+ }
2916
+
2917
+ .aboutAuthor:hover {
2918
+ text-decoration: underline;
2919
+ }
2920
+
2921
+ .aboutAuthor:focus-visible {
2922
+ outline: 2px solid var(--dsw-alias-state-business-primary);
2923
+ outline-offset: 1px;
2924
+ border-radius: 4px;
2925
+ }
2926
+
2927
+ .consultDimension {
2928
+ padding: 6px 0;
2929
+ border-bottom: 1px solid color-mix(in srgb, var(--dsw-alias-border-l1) 55%, transparent);
2930
+ font-size: 12px;
2931
+ }
2932
+
2933
+ .consultDimension:last-child {
2934
+ border-bottom: none;
2935
+ }
2936
+
2937
+ .severityError {
2938
+ color: var(--dsw-alias-state-error-primary);
2939
+ font-weight: 600;
2940
+ }
2941
+
2942
+ /* ================================================================ §14 Responsive */
2943
+
2944
+ /* 设置弹窗收缩(<900px 视口:弹窗变 100vw-48px,内容列变窄) */
2945
+ @media (max-width: 900px) {
2946
+ .ovGrid {
2947
+ grid-template-columns: minmax(0, 1fr);
2948
+ }
2949
+
2950
+ .statGrid,
2951
+ .metricGrid {
2952
+ grid-template-columns: repeat(2, minmax(0, 1fr));
2953
+ }
2954
+
2955
+ .quickGrid {
2956
+ grid-template-columns: repeat(2, minmax(0, 1fr));
2957
+ }
2958
+
2959
+ .secretFields {
2960
+ grid-template-columns: 1fr;
2961
+ }
2962
+
2963
+ .pagePad {
2964
+ padding: 10px 12px 12px;
2965
+ }
2966
+
2967
+ .drawerPanel {
2968
+ width: 100vw;
2969
+ max-width: 100vw;
2970
+ }
2971
+ }