@rexvane/piweb 0.3.1

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 (535) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +128 -0
  3. package/assets/showcase.png +0 -0
  4. package/bin/pi.js +50 -0
  5. package/bin/piweb.js +12 -0
  6. package/next.config.ts +21 -0
  7. package/package.json +88 -0
  8. package/postcss.config.mjs +7 -0
  9. package/public/file-icons/3d.svg +1 -0
  10. package/public/file-icons/LICENSE +8 -0
  11. package/public/file-icons/adobe-illustrator.svg +1 -0
  12. package/public/file-icons/adobe-photoshop.svg +1 -0
  13. package/public/file-icons/agent.svg +1 -0
  14. package/public/file-icons/asciidoc.svg +1 -0
  15. package/public/file-icons/assembly.svg +1 -0
  16. package/public/file-icons/astro.svg +1 -0
  17. package/public/file-icons/audio.svg +1 -0
  18. package/public/file-icons/authors.svg +1 -0
  19. package/public/file-icons/babel.svg +1 -0
  20. package/public/file-icons/bibliography.svg +1 -0
  21. package/public/file-icons/bicep.svg +1 -0
  22. package/public/file-icons/blender.svg +1 -0
  23. package/public/file-icons/bun.svg +1 -0
  24. package/public/file-icons/c.svg +1 -0
  25. package/public/file-icons/certificate.svg +1 -0
  26. package/public/file-icons/changelog.svg +1 -0
  27. package/public/file-icons/clojure.svg +1 -0
  28. package/public/file-icons/cmake.svg +1 -0
  29. package/public/file-icons/codeowners.svg +1 -0
  30. package/public/file-icons/commitlint.svg +1 -0
  31. package/public/file-icons/conduct.svg +1 -0
  32. package/public/file-icons/console.svg +1 -0
  33. package/public/file-icons/contributing.svg +1 -0
  34. package/public/file-icons/cpp.svg +1 -0
  35. package/public/file-icons/csharp.svg +1 -0
  36. package/public/file-icons/css.svg +1 -0
  37. package/public/file-icons/cursor.svg +1 -0
  38. package/public/file-icons/dart.svg +1 -0
  39. package/public/file-icons/database.svg +1 -0
  40. package/public/file-icons/deno.svg +1 -0
  41. package/public/file-icons/diff.svg +1 -0
  42. package/public/file-icons/docker.svg +1 -0
  43. package/public/file-icons/document.svg +1 -0
  44. package/public/file-icons/editorconfig.svg +1 -0
  45. package/public/file-icons/ejs.svg +1 -0
  46. package/public/file-icons/elixir.svg +1 -0
  47. package/public/file-icons/elm.svg +1 -0
  48. package/public/file-icons/email.svg +1 -0
  49. package/public/file-icons/erlang.svg +1 -0
  50. package/public/file-icons/eslint.svg +1 -0
  51. package/public/file-icons/favicon.svg +1 -0
  52. package/public/file-icons/file.svg +1 -0
  53. package/public/file-icons/folder-admin-open.svg +1 -0
  54. package/public/file-icons/folder-admin.svg +1 -0
  55. package/public/file-icons/folder-android-open.svg +1 -0
  56. package/public/file-icons/folder-android.svg +1 -0
  57. package/public/file-icons/folder-api-open.svg +1 -0
  58. package/public/file-icons/folder-api.svg +1 -0
  59. package/public/file-icons/folder-app-open.svg +1 -0
  60. package/public/file-icons/folder-app.svg +1 -0
  61. package/public/file-icons/folder-archive-open.svg +1 -0
  62. package/public/file-icons/folder-archive.svg +1 -0
  63. package/public/file-icons/folder-atom-open.svg +1 -0
  64. package/public/file-icons/folder-atom.svg +1 -0
  65. package/public/file-icons/folder-audio-open.svg +1 -0
  66. package/public/file-icons/folder-audio.svg +1 -0
  67. package/public/file-icons/folder-aws-open.svg +1 -0
  68. package/public/file-icons/folder-aws.svg +1 -0
  69. package/public/file-icons/folder-backup-open.svg +1 -0
  70. package/public/file-icons/folder-backup.svg +1 -0
  71. package/public/file-icons/folder-benchmark-open.svg +1 -0
  72. package/public/file-icons/folder-benchmark.svg +1 -0
  73. package/public/file-icons/folder-cart-open.svg +1 -0
  74. package/public/file-icons/folder-cart.svg +1 -0
  75. package/public/file-icons/folder-ci-open.svg +1 -0
  76. package/public/file-icons/folder-ci.svg +1 -0
  77. package/public/file-icons/folder-circleci-open.svg +1 -0
  78. package/public/file-icons/folder-circleci.svg +1 -0
  79. package/public/file-icons/folder-class-open.svg +1 -0
  80. package/public/file-icons/folder-class.svg +1 -0
  81. package/public/file-icons/folder-client-open.svg +1 -0
  82. package/public/file-icons/folder-client.svg +1 -0
  83. package/public/file-icons/folder-command-open.svg +1 -0
  84. package/public/file-icons/folder-command.svg +1 -0
  85. package/public/file-icons/folder-components-open.svg +1 -0
  86. package/public/file-icons/folder-components.svg +1 -0
  87. package/public/file-icons/folder-config-open.svg +1 -0
  88. package/public/file-icons/folder-config.svg +1 -0
  89. package/public/file-icons/folder-console-open.svg +1 -0
  90. package/public/file-icons/folder-console.svg +1 -0
  91. package/public/file-icons/folder-content-open.svg +1 -0
  92. package/public/file-icons/folder-content.svg +1 -0
  93. package/public/file-icons/folder-context-open.svg +1 -0
  94. package/public/file-icons/folder-context.svg +1 -0
  95. package/public/file-icons/folder-contract-open.svg +1 -0
  96. package/public/file-icons/folder-contract.svg +1 -0
  97. package/public/file-icons/folder-controller-open.svg +1 -0
  98. package/public/file-icons/folder-controller.svg +1 -0
  99. package/public/file-icons/folder-core-open.svg +1 -0
  100. package/public/file-icons/folder-core.svg +1 -0
  101. package/public/file-icons/folder-coverage-open.svg +1 -0
  102. package/public/file-icons/folder-coverage.svg +1 -0
  103. package/public/file-icons/folder-css-open.svg +1 -0
  104. package/public/file-icons/folder-css.svg +1 -0
  105. package/public/file-icons/folder-database-open.svg +1 -0
  106. package/public/file-icons/folder-database.svg +1 -0
  107. package/public/file-icons/folder-debug-open.svg +1 -0
  108. package/public/file-icons/folder-debug.svg +1 -0
  109. package/public/file-icons/folder-deprecated-open.svg +1 -0
  110. package/public/file-icons/folder-deprecated.svg +1 -0
  111. package/public/file-icons/folder-desktop-open.svg +1 -0
  112. package/public/file-icons/folder-desktop.svg +1 -0
  113. package/public/file-icons/folder-dist-open.svg +1 -0
  114. package/public/file-icons/folder-dist.svg +1 -0
  115. package/public/file-icons/folder-docker-open.svg +1 -0
  116. package/public/file-icons/folder-docker.svg +1 -0
  117. package/public/file-icons/folder-docs-open.svg +1 -0
  118. package/public/file-icons/folder-docs.svg +1 -0
  119. package/public/file-icons/folder-element-open.svg +1 -0
  120. package/public/file-icons/folder-element.svg +1 -0
  121. package/public/file-icons/folder-environment-open.svg +1 -0
  122. package/public/file-icons/folder-environment.svg +1 -0
  123. package/public/file-icons/folder-event-open.svg +1 -0
  124. package/public/file-icons/folder-event.svg +1 -0
  125. package/public/file-icons/folder-examples-open.svg +1 -0
  126. package/public/file-icons/folder-examples.svg +1 -0
  127. package/public/file-icons/folder-features-open.svg +1 -0
  128. package/public/file-icons/folder-features.svg +1 -0
  129. package/public/file-icons/folder-font-open.svg +1 -0
  130. package/public/file-icons/folder-font.svg +1 -0
  131. package/public/file-icons/folder-functions-open.svg +1 -0
  132. package/public/file-icons/folder-functions.svg +1 -0
  133. package/public/file-icons/folder-generator-open.svg +1 -0
  134. package/public/file-icons/folder-generator.svg +1 -0
  135. package/public/file-icons/folder-git-open.svg +1 -0
  136. package/public/file-icons/folder-git.svg +1 -0
  137. package/public/file-icons/folder-github-open.svg +1 -0
  138. package/public/file-icons/folder-github.svg +1 -0
  139. package/public/file-icons/folder-gitlab-open.svg +1 -0
  140. package/public/file-icons/folder-gitlab.svg +1 -0
  141. package/public/file-icons/folder-graphql-open.svg +1 -0
  142. package/public/file-icons/folder-graphql.svg +1 -0
  143. package/public/file-icons/folder-helper-open.svg +1 -0
  144. package/public/file-icons/folder-helper.svg +1 -0
  145. package/public/file-icons/folder-hook-open.svg +1 -0
  146. package/public/file-icons/folder-hook.svg +1 -0
  147. package/public/file-icons/folder-husky-open.svg +1 -0
  148. package/public/file-icons/folder-husky.svg +1 -0
  149. package/public/file-icons/folder-i18n-open.svg +1 -0
  150. package/public/file-icons/folder-i18n.svg +1 -0
  151. package/public/file-icons/folder-images-open.svg +1 -0
  152. package/public/file-icons/folder-images.svg +1 -0
  153. package/public/file-icons/folder-include-open.svg +1 -0
  154. package/public/file-icons/folder-include.svg +1 -0
  155. package/public/file-icons/folder-intellij-open.svg +1 -0
  156. package/public/file-icons/folder-intellij.svg +1 -0
  157. package/public/file-icons/folder-interface-open.svg +1 -0
  158. package/public/file-icons/folder-interface.svg +1 -0
  159. package/public/file-icons/folder-ios-open.svg +1 -0
  160. package/public/file-icons/folder-ios.svg +1 -0
  161. package/public/file-icons/folder-java-open.svg +1 -0
  162. package/public/file-icons/folder-java.svg +1 -0
  163. package/public/file-icons/folder-job-open.svg +1 -0
  164. package/public/file-icons/folder-job.svg +1 -0
  165. package/public/file-icons/folder-jupyter-open.svg +1 -0
  166. package/public/file-icons/folder-jupyter.svg +1 -0
  167. package/public/file-icons/folder-keys-open.svg +1 -0
  168. package/public/file-icons/folder-keys.svg +1 -0
  169. package/public/file-icons/folder-kubernetes-open.svg +1 -0
  170. package/public/file-icons/folder-kubernetes.svg +1 -0
  171. package/public/file-icons/folder-layout-open.svg +1 -0
  172. package/public/file-icons/folder-layout.svg +1 -0
  173. package/public/file-icons/folder-less-open.svg +1 -0
  174. package/public/file-icons/folder-less.svg +1 -0
  175. package/public/file-icons/folder-lib-open.svg +1 -0
  176. package/public/file-icons/folder-lib.svg +1 -0
  177. package/public/file-icons/folder-log-open.svg +1 -0
  178. package/public/file-icons/folder-log.svg +1 -0
  179. package/public/file-icons/folder-messages-open.svg +1 -0
  180. package/public/file-icons/folder-messages.svg +1 -0
  181. package/public/file-icons/folder-meta-open.svg +1 -0
  182. package/public/file-icons/folder-meta.svg +1 -0
  183. package/public/file-icons/folder-middleware-open.svg +1 -0
  184. package/public/file-icons/folder-middleware.svg +1 -0
  185. package/public/file-icons/folder-migrations-open.svg +1 -0
  186. package/public/file-icons/folder-migrations.svg +1 -0
  187. package/public/file-icons/folder-mobile-open.svg +1 -0
  188. package/public/file-icons/folder-mobile.svg +1 -0
  189. package/public/file-icons/folder-mock-open.svg +1 -0
  190. package/public/file-icons/folder-mock.svg +1 -0
  191. package/public/file-icons/folder-molecule-open.svg +1 -0
  192. package/public/file-icons/folder-molecule.svg +1 -0
  193. package/public/file-icons/folder-next-open.svg +1 -0
  194. package/public/file-icons/folder-next.svg +1 -0
  195. package/public/file-icons/folder-node-open.svg +1 -0
  196. package/public/file-icons/folder-node.svg +1 -0
  197. package/public/file-icons/folder-nuxt-open.svg +1 -0
  198. package/public/file-icons/folder-nuxt.svg +1 -0
  199. package/public/file-icons/folder-open.svg +1 -0
  200. package/public/file-icons/folder-organism-open.svg +1 -0
  201. package/public/file-icons/folder-organism.svg +1 -0
  202. package/public/file-icons/folder-packages-open.svg +1 -0
  203. package/public/file-icons/folder-packages.svg +1 -0
  204. package/public/file-icons/folder-plugin-open.svg +1 -0
  205. package/public/file-icons/folder-plugin.svg +1 -0
  206. package/public/file-icons/folder-prisma-open.svg +1 -0
  207. package/public/file-icons/folder-prisma.svg +1 -0
  208. package/public/file-icons/folder-prompts-open.svg +1 -0
  209. package/public/file-icons/folder-prompts.svg +1 -0
  210. package/public/file-icons/folder-proto-open.svg +1 -0
  211. package/public/file-icons/folder-proto.svg +1 -0
  212. package/public/file-icons/folder-public-open.svg +1 -0
  213. package/public/file-icons/folder-public.svg +1 -0
  214. package/public/file-icons/folder-python-open.svg +1 -0
  215. package/public/file-icons/folder-python.svg +1 -0
  216. package/public/file-icons/folder-queue-open.svg +1 -0
  217. package/public/file-icons/folder-queue.svg +1 -0
  218. package/public/file-icons/folder-resource-open.svg +1 -0
  219. package/public/file-icons/folder-resource.svg +1 -0
  220. package/public/file-icons/folder-review-open.svg +1 -0
  221. package/public/file-icons/folder-review.svg +1 -0
  222. package/public/file-icons/folder-robot-open.svg +1 -0
  223. package/public/file-icons/folder-robot.svg +1 -0
  224. package/public/file-icons/folder-routes-open.svg +1 -0
  225. package/public/file-icons/folder-routes.svg +1 -0
  226. package/public/file-icons/folder-rust-open.svg +1 -0
  227. package/public/file-icons/folder-rust.svg +1 -0
  228. package/public/file-icons/folder-sass-open.svg +1 -0
  229. package/public/file-icons/folder-sass.svg +1 -0
  230. package/public/file-icons/folder-scripts-open.svg +1 -0
  231. package/public/file-icons/folder-scripts.svg +1 -0
  232. package/public/file-icons/folder-secure-open.svg +1 -0
  233. package/public/file-icons/folder-secure.svg +1 -0
  234. package/public/file-icons/folder-seeders-open.svg +1 -0
  235. package/public/file-icons/folder-seeders.svg +1 -0
  236. package/public/file-icons/folder-server-open.svg +1 -0
  237. package/public/file-icons/folder-server.svg +1 -0
  238. package/public/file-icons/folder-shared-open.svg +1 -0
  239. package/public/file-icons/folder-shared.svg +1 -0
  240. package/public/file-icons/folder-skills-open.svg +1 -0
  241. package/public/file-icons/folder-skills.svg +1 -0
  242. package/public/file-icons/folder-src-open.svg +1 -0
  243. package/public/file-icons/folder-src.svg +1 -0
  244. package/public/file-icons/folder-store-open.svg +1 -0
  245. package/public/file-icons/folder-store.svg +1 -0
  246. package/public/file-icons/folder-storybook-open.svg +1 -0
  247. package/public/file-icons/folder-storybook.svg +1 -0
  248. package/public/file-icons/folder-supabase-open.svg +1 -0
  249. package/public/file-icons/folder-supabase.svg +1 -0
  250. package/public/file-icons/folder-svelte-open.svg +1 -0
  251. package/public/file-icons/folder-svelte.svg +1 -0
  252. package/public/file-icons/folder-target-open.svg +1 -0
  253. package/public/file-icons/folder-target.svg +1 -0
  254. package/public/file-icons/folder-tasks-open.svg +1 -0
  255. package/public/file-icons/folder-tasks.svg +1 -0
  256. package/public/file-icons/folder-temp-open.svg +1 -0
  257. package/public/file-icons/folder-temp.svg +1 -0
  258. package/public/file-icons/folder-template-open.svg +1 -0
  259. package/public/file-icons/folder-template.svg +1 -0
  260. package/public/file-icons/folder-terraform-open.svg +1 -0
  261. package/public/file-icons/folder-terraform.svg +1 -0
  262. package/public/file-icons/folder-test-open.svg +1 -0
  263. package/public/file-icons/folder-test.svg +1 -0
  264. package/public/file-icons/folder-theme-open.svg +1 -0
  265. package/public/file-icons/folder-theme.svg +1 -0
  266. package/public/file-icons/folder-tools-open.svg +1 -0
  267. package/public/file-icons/folder-tools.svg +1 -0
  268. package/public/file-icons/folder-turborepo-open.svg +1 -0
  269. package/public/file-icons/folder-turborepo.svg +1 -0
  270. package/public/file-icons/folder-typescript-open.svg +1 -0
  271. package/public/file-icons/folder-typescript.svg +1 -0
  272. package/public/file-icons/folder-ui-open.svg +1 -0
  273. package/public/file-icons/folder-ui.svg +1 -0
  274. package/public/file-icons/folder-utils-open.svg +1 -0
  275. package/public/file-icons/folder-utils.svg +1 -0
  276. package/public/file-icons/folder-video-open.svg +1 -0
  277. package/public/file-icons/folder-video.svg +1 -0
  278. package/public/file-icons/folder-views-open.svg +1 -0
  279. package/public/file-icons/folder-views.svg +1 -0
  280. package/public/file-icons/folder-vscode-open.svg +1 -0
  281. package/public/file-icons/folder-vscode.svg +1 -0
  282. package/public/file-icons/folder.svg +1 -0
  283. package/public/file-icons/font.svg +1 -0
  284. package/public/file-icons/fsharp.svg +1 -0
  285. package/public/file-icons/gemfile.svg +1 -0
  286. package/public/file-icons/git.svg +1 -0
  287. package/public/file-icons/go-mod.svg +1 -0
  288. package/public/file-icons/go.svg +1 -0
  289. package/public/file-icons/gradle.svg +1 -0
  290. package/public/file-icons/graphql.svg +1 -0
  291. package/public/file-icons/groovy.svg +1 -0
  292. package/public/file-icons/h.svg +1 -0
  293. package/public/file-icons/handlebars.svg +1 -0
  294. package/public/file-icons/haskell.svg +1 -0
  295. package/public/file-icons/hcl.svg +1 -0
  296. package/public/file-icons/heroku.svg +1 -0
  297. package/public/file-icons/hpp.svg +1 -0
  298. package/public/file-icons/html.svg +1 -0
  299. package/public/file-icons/husky.svg +1 -0
  300. package/public/file-icons/i18n.svg +1 -0
  301. package/public/file-icons/image.svg +1 -0
  302. package/public/file-icons/java.svg +1 -0
  303. package/public/file-icons/javascript.svg +1 -0
  304. package/public/file-icons/jenkins.svg +1 -0
  305. package/public/file-icons/jest.svg +1 -0
  306. package/public/file-icons/jsconfig.svg +1 -0
  307. package/public/file-icons/json.svg +1 -0
  308. package/public/file-icons/julia.svg +1 -0
  309. package/public/file-icons/jupyter.svg +1 -0
  310. package/public/file-icons/just.svg +1 -0
  311. package/public/file-icons/key.svg +1 -0
  312. package/public/file-icons/kotlin.svg +1 -0
  313. package/public/file-icons/lerna.svg +1 -0
  314. package/public/file-icons/less.svg +1 -0
  315. package/public/file-icons/license.svg +1 -0
  316. package/public/file-icons/lintstaged.svg +1 -0
  317. package/public/file-icons/liquid.svg +1 -0
  318. package/public/file-icons/lock.svg +1 -0
  319. package/public/file-icons/log.svg +1 -0
  320. package/public/file-icons/lua.svg +1 -0
  321. package/public/file-icons/makefile.svg +1 -0
  322. package/public/file-icons/markdown.svg +1 -0
  323. package/public/file-icons/maven.svg +1 -0
  324. package/public/file-icons/mdx.svg +1 -0
  325. package/public/file-icons/netlify.svg +1 -0
  326. package/public/file-icons/next.svg +1 -0
  327. package/public/file-icons/nim.svg +1 -0
  328. package/public/file-icons/nix.svg +1 -0
  329. package/public/file-icons/nodejs.svg +1 -0
  330. package/public/file-icons/nodemon.svg +1 -0
  331. package/public/file-icons/npm.svg +1 -0
  332. package/public/file-icons/nx.svg +1 -0
  333. package/public/file-icons/objective-c.svg +1 -0
  334. package/public/file-icons/objective-cpp.svg +1 -0
  335. package/public/file-icons/ocaml.svg +1 -0
  336. package/public/file-icons/pdf.svg +1 -0
  337. package/public/file-icons/php.svg +1 -0
  338. package/public/file-icons/pm2-ecosystem.svg +1 -0
  339. package/public/file-icons/pnpm.svg +1 -0
  340. package/public/file-icons/poetry.svg +1 -0
  341. package/public/file-icons/postcss.svg +1 -0
  342. package/public/file-icons/powerpoint.svg +1 -0
  343. package/public/file-icons/powershell.svg +1 -0
  344. package/public/file-icons/prettier.svg +1 -0
  345. package/public/file-icons/prisma.svg +1 -0
  346. package/public/file-icons/prolog.svg +1 -0
  347. package/public/file-icons/proto.svg +1 -0
  348. package/public/file-icons/pug.svg +1 -0
  349. package/public/file-icons/python-misc.svg +1 -0
  350. package/public/file-icons/python.svg +1 -0
  351. package/public/file-icons/r.svg +1 -0
  352. package/public/file-icons/razor.svg +1 -0
  353. package/public/file-icons/react.svg +1 -0
  354. package/public/file-icons/react_ts.svg +1 -0
  355. package/public/file-icons/readme.svg +1 -0
  356. package/public/file-icons/renovate.svg +1 -0
  357. package/public/file-icons/robots.svg +1 -0
  358. package/public/file-icons/rollup.svg +1 -0
  359. package/public/file-icons/ruby.svg +1 -0
  360. package/public/file-icons/rust.svg +1 -0
  361. package/public/file-icons/sass.svg +1 -0
  362. package/public/file-icons/scala.svg +1 -0
  363. package/public/file-icons/semantic-release.svg +1 -0
  364. package/public/file-icons/settings.svg +1 -0
  365. package/public/file-icons/shader.svg +1 -0
  366. package/public/file-icons/sml.svg +1 -0
  367. package/public/file-icons/solidity.svg +1 -0
  368. package/public/file-icons/stylus.svg +1 -0
  369. package/public/file-icons/svelte.svg +1 -0
  370. package/public/file-icons/svg.svg +1 -0
  371. package/public/file-icons/swift.svg +1 -0
  372. package/public/file-icons/table.svg +1 -0
  373. package/public/file-icons/tailwindcss.svg +1 -0
  374. package/public/file-icons/taskfile.svg +1 -0
  375. package/public/file-icons/terraform.svg +1 -0
  376. package/public/file-icons/test-js.svg +1 -0
  377. package/public/file-icons/test-jsx.svg +1 -0
  378. package/public/file-icons/test-ts.svg +1 -0
  379. package/public/file-icons/tex.svg +1 -0
  380. package/public/file-icons/toml.svg +1 -0
  381. package/public/file-icons/travis.svg +1 -0
  382. package/public/file-icons/tsconfig.svg +1 -0
  383. package/public/file-icons/tune.svg +1 -0
  384. package/public/file-icons/turborepo.svg +1 -0
  385. package/public/file-icons/typescript-def.svg +1 -0
  386. package/public/file-icons/typescript.svg +1 -0
  387. package/public/file-icons/unity.svg +1 -0
  388. package/public/file-icons/uv.svg +1 -0
  389. package/public/file-icons/vala.svg +1 -0
  390. package/public/file-icons/vercel.svg +1 -0
  391. package/public/file-icons/video.svg +1 -0
  392. package/public/file-icons/vim.svg +1 -0
  393. package/public/file-icons/vite.svg +1 -0
  394. package/public/file-icons/vitest.svg +1 -0
  395. package/public/file-icons/vlang.svg +1 -0
  396. package/public/file-icons/vue.svg +1 -0
  397. package/public/file-icons/webassembly.svg +1 -0
  398. package/public/file-icons/webpack.svg +1 -0
  399. package/public/file-icons/word.svg +1 -0
  400. package/public/file-icons/xml.svg +1 -0
  401. package/public/file-icons/yaml.svg +1 -0
  402. package/public/file-icons/yarn.svg +1 -0
  403. package/public/file-icons/zig.svg +1 -0
  404. package/public/file-icons/zip.svg +1 -0
  405. package/public/provider-icons/antgroup-color.svg +1 -0
  406. package/public/provider-icons/anthropic.svg +1 -0
  407. package/public/provider-icons/azure-color.svg +1 -0
  408. package/public/provider-icons/baseten.svg +1 -0
  409. package/public/provider-icons/bedrock-color.svg +1 -0
  410. package/public/provider-icons/cerebras-color.svg +1 -0
  411. package/public/provider-icons/cloudflare-color.svg +1 -0
  412. package/public/provider-icons/deepseek-color.svg +1 -0
  413. package/public/provider-icons/fireworks-color.svg +1 -0
  414. package/public/provider-icons/githubcopilot.svg +1 -0
  415. package/public/provider-icons/google-color.svg +1 -0
  416. package/public/provider-icons/googlecloud-color.svg +1 -0
  417. package/public/provider-icons/groq.svg +1 -0
  418. package/public/provider-icons/huggingface-color.svg +1 -0
  419. package/public/provider-icons/kimi-color.svg +1 -0
  420. package/public/provider-icons/minimax-color.svg +1 -0
  421. package/public/provider-icons/mistral-color.svg +1 -0
  422. package/public/provider-icons/moonshot.svg +1 -0
  423. package/public/provider-icons/nvidia-color.svg +1 -0
  424. package/public/provider-icons/openai.svg +1 -0
  425. package/public/provider-icons/opencode.svg +1 -0
  426. package/public/provider-icons/openrouter-color.svg +1 -0
  427. package/public/provider-icons/qwen-color.svg +1 -0
  428. package/public/provider-icons/together-color.svg +1 -0
  429. package/public/provider-icons/vercel.svg +1 -0
  430. package/public/provider-icons/xai.svg +1 -0
  431. package/public/provider-icons/xiaomimimo.svg +1 -0
  432. package/public/provider-icons/zai.svg +1 -0
  433. package/scripts/build-output.mjs +131 -0
  434. package/scripts/dev.mjs +18 -0
  435. package/scripts/entrypoint.mjs +8 -0
  436. package/scripts/install-build.mjs +134 -0
  437. package/scripts/launcher.mjs +249 -0
  438. package/scripts/pick-folder.ps1 +110 -0
  439. package/scripts/postinstall.mjs +12 -0
  440. package/scripts/process-runner.mjs +60 -0
  441. package/scripts/release.mjs +172 -0
  442. package/scripts/sync-file-icons.mjs +118 -0
  443. package/scripts/sync-provider-icons.mjs +41 -0
  444. package/src/app/api/agent/[id]/events/route.ts +81 -0
  445. package/src/app/api/agent/[id]/route.ts +24 -0
  446. package/src/app/api/agent/[id]/tree/route.ts +49 -0
  447. package/src/app/api/agent/new/route.ts +19 -0
  448. package/src/app/api/config/route.ts +22 -0
  449. package/src/app/api/files/route.ts +63 -0
  450. package/src/app/api/git/route.ts +32 -0
  451. package/src/app/api/growth/route.ts +50 -0
  452. package/src/app/api/health/route.ts +7 -0
  453. package/src/app/api/models/route.ts +129 -0
  454. package/src/app/api/pi-settings/route.ts +22 -0
  455. package/src/app/api/plugins/route.ts +79 -0
  456. package/src/app/api/security/route.ts +41 -0
  457. package/src/app/api/sessions/[id]/export/route.ts +25 -0
  458. package/src/app/api/sessions/[id]/route.ts +37 -0
  459. package/src/app/api/sessions/route.ts +23 -0
  460. package/src/app/api/skills/route.ts +39 -0
  461. package/src/app/api/update/route.ts +33 -0
  462. package/src/app/api/version/route.ts +8 -0
  463. package/src/app/api/web-auth/route.ts +80 -0
  464. package/src/app/api/workspaces/route.ts +78 -0
  465. package/src/app/globals.css +2039 -0
  466. package/src/app/icon.svg +21 -0
  467. package/src/app/layout.tsx +29 -0
  468. package/src/app/login/page.tsx +111 -0
  469. package/src/app/page.tsx +10 -0
  470. package/src/components/AppShell.tsx +1171 -0
  471. package/src/components/ChatInput.tsx +729 -0
  472. package/src/components/ChatWindow.tsx +1320 -0
  473. package/src/components/ContextMeter.tsx +131 -0
  474. package/src/components/DiffView.tsx +139 -0
  475. package/src/components/ExtensionUI.tsx +181 -0
  476. package/src/components/FileViewer.tsx +555 -0
  477. package/src/components/FullDiff.tsx +220 -0
  478. package/src/components/GitPanel.tsx +357 -0
  479. package/src/components/GrowthTree.tsx +317 -0
  480. package/src/components/ModelSelector.tsx +286 -0
  481. package/src/components/OutlineRail.tsx +166 -0
  482. package/src/components/PiMark.tsx +79 -0
  483. package/src/components/ProjectPanel.tsx +309 -0
  484. package/src/components/ProviderBrand.tsx +28 -0
  485. package/src/components/ProviderSetupModal.module.css +560 -0
  486. package/src/components/ProviderSetupModal.tsx +559 -0
  487. package/src/components/SessionSidebar.tsx +1066 -0
  488. package/src/components/SettingsPanel.tsx +2216 -0
  489. package/src/components/TrajectoryAnalyzer.module.css +225 -0
  490. package/src/components/TrajectoryView.tsx +289 -0
  491. package/src/components/icons.tsx +443 -0
  492. package/src/hooks/useFileViewer.ts +58 -0
  493. package/src/hooks/useGrowth.ts +635 -0
  494. package/src/hooks/usePiWeb.ts +900 -0
  495. package/src/i18n.tsx +1043 -0
  496. package/src/lib/agent-manager.ts +1348 -0
  497. package/src/lib/app-root.ts +4 -0
  498. package/src/lib/auth.ts +51 -0
  499. package/src/lib/command-validation.ts +116 -0
  500. package/src/lib/enter-behavior.ts +40 -0
  501. package/src/lib/extension-ui.ts +134 -0
  502. package/src/lib/file-icons.json +557 -0
  503. package/src/lib/file-icons.ts +39 -0
  504. package/src/lib/files-service.ts +280 -0
  505. package/src/lib/git-service.ts +255 -0
  506. package/src/lib/growth-rounds.ts +84 -0
  507. package/src/lib/growth-service.ts +586 -0
  508. package/src/lib/growth-tracker.ts +328 -0
  509. package/src/lib/growth-tree.ts +245 -0
  510. package/src/lib/growth-turns.ts +23 -0
  511. package/src/lib/highlight.ts +59 -0
  512. package/src/lib/model-draft.ts +103 -0
  513. package/src/lib/models-service.ts +852 -0
  514. package/src/lib/path-security.ts +101 -0
  515. package/src/lib/pi-settings.ts +115 -0
  516. package/src/lib/pi.ts +367 -0
  517. package/src/lib/plugins-service.ts +312 -0
  518. package/src/lib/process-format.ts +261 -0
  519. package/src/lib/provider-display.ts +57 -0
  520. package/src/lib/security-service.ts +52 -0
  521. package/src/lib/semver.ts +39 -0
  522. package/src/lib/session-reader.ts +204 -0
  523. package/src/lib/settings-write-lock.ts +45 -0
  524. package/src/lib/skills-service.ts +97 -0
  525. package/src/lib/text-sanitize.ts +20 -0
  526. package/src/lib/theme.ts +137 -0
  527. package/src/lib/trajectory.ts +294 -0
  528. package/src/lib/types.ts +300 -0
  529. package/src/lib/update-service.ts +129 -0
  530. package/src/lib/version.ts +6 -0
  531. package/src/lib/web-auth-shared.ts +35 -0
  532. package/src/lib/web-auth.ts +53 -0
  533. package/src/lib/workspace-store.ts +261 -0
  534. package/src/proxy.ts +53 -0
  535. package/tsconfig.json +49 -0
@@ -0,0 +1,2039 @@
1
+ @import "tailwindcss";
2
+
3
+ /* ============================================================
4
+ Pi Web 视觉令牌 —— 对齐 dsh (deepseek-harness) design-platform.css
5
+ 浅色默认,深色用 body[data-ds-dark-theme]
6
+ ============================================================ */
7
+
8
+ :root {
9
+ /* 静态色阶 */
10
+ --dsw-deepseek-400: rgb(103, 158, 254);
11
+ --dsw-deepseek-450: rgb(86, 134, 254);
12
+ --dsw-deepseek-500: rgb(65, 118, 230);
13
+ --dsw-amber-500: rgb(245, 158, 11);
14
+ --dsw-green-500: rgb(34, 197, 94);
15
+ --dsw-red-600: rgb(236, 19, 19);
16
+
17
+ /* 别名(浅色) */
18
+ --dsw-bg-base: #ffffff;
19
+ --dsw-bg-elevated: #ffffff;
20
+ --dsw-sidebar-fill: rgb(249, 250, 251);
21
+ --dsw-input-major: #ffffff;
22
+ --dsw-bubble: rgb(239, 244, 255); /* deepseek-50 近似 */
23
+ --dsw-hover: rgba(0, 0, 0, 0.04);
24
+ --dsw-active: rgba(0, 0, 0, 0.06);
25
+ --dsw-label-primary: rgb(0, 0, 0);
26
+ --dsw-label-secondary: rgb(64, 64, 66);
27
+ --dsw-label-tertiary: rgb(110, 110, 115);
28
+ --dsw-label-caption: rgb(150, 150, 155);
29
+ --dsw-border-l1: rgba(0, 0, 0, 0.04);
30
+ --dsw-border-l2: rgba(0, 0, 0, 0.1);
31
+ --dsw-border-l3: rgba(0, 0, 0, 0.12);
32
+ --dsw-border-l4: rgba(0, 0, 0, 0.16);
33
+ --dsw-accent: var(--dsw-deepseek-500);
34
+ --dsw-accent-soft: rgba(65, 118, 230, 0.1);
35
+ --dsw-warn: var(--dsw-amber-500);
36
+ --dsw-success: var(--dsw-green-500);
37
+ --dsw-danger: var(--dsw-red-600);
38
+ --dsw-selector: rgba(0, 0, 0, 0.05);
39
+
40
+ /* dsh 层级表面 */
41
+ --dsw-layer-2: #ffffff;
42
+ --dsw-layer-3: #ffffff;
43
+ --dsw-btn-elevated: #ffffff;
44
+ --dsw-btn-floating-hover: rgb(240, 241, 243);
45
+ --dsw-module-platform: rgb(238, 239, 241);
46
+ --dsw-border-strong: rgb(173, 178, 184); /* neutral-bluish-400 */
47
+
48
+ /* 玻璃面 */
49
+ --dsw-glass-popover: #ffffff;
50
+ --dsw-glass-input: #ffffff;
51
+ --dsw-glass-modal: #ffffff;
52
+ --dsw-mask: rgba(0, 0, 0, 0.24);
53
+ --dsw-mask-blur: blur(6px);
54
+
55
+ /* 投影(soft / panel / prominent 三档,描边并入投影实现 0 布局成本发丝线) */
56
+ --dsw-elevation-stroke: var(--dsw-border-l2);
57
+ --dsw-elevation-soft: 0 0 0 0.5px var(--dsw-elevation-stroke), 0 4px 16px rgba(0, 0, 0, 0.03),
58
+ 0 0 24px rgba(0, 0, 0, 0.03);
59
+ --dsw-elevation-panel: 0 0 0 0.5px var(--dsw-elevation-stroke), 0 8px 32px rgba(0, 0, 0, 0.08);
60
+ --dsw-elevation-prominent: 0 0 0 0.5px var(--dsw-elevation-stroke), 0 16px 48px rgba(0, 0, 0, 0.16);
61
+
62
+ /* 动效 */
63
+ --ds-ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
64
+ --ds-duration-fast: 0.1s;
65
+ --ds-duration-normal: 0.2s;
66
+ --ds-duration-slow: 0.3s;
67
+
68
+ /* 字体 */
69
+ --dsh-content-font-size: 14px;
70
+ --dsh-content-font-delta: 0px;
71
+ --dsh-content-font-size-secondary: 13px;
72
+ /* 对话字号(设置里独立调节;theme.ts 启动时按 localStorage 覆盖) */
73
+ --piweb-chat-font-size: var(--dsh-content-font-size);
74
+ /* 对话过程行分级字号:跟随对话字号缩放(基准 14px 时 ≈ 13.5 / 13 / 12.5 / 12 / 11.5) */
75
+ --piweb-chat-font-l: calc(var(--piweb-chat-font-size) * 0.96);
76
+ --piweb-chat-font-m: calc(var(--piweb-chat-font-size) * 0.93);
77
+ --piweb-chat-font-s: calc(var(--piweb-chat-font-size) * 0.89);
78
+ --piweb-chat-font-t: calc(var(--piweb-chat-font-size) * 0.86);
79
+ --piweb-chat-font-xs: calc(var(--piweb-chat-font-size) * 0.82);
80
+ --font-ui: "Maple Mono CN", ui-monospace, SFMono-Regular, Menlo, Consolas, "PingFang SC",
81
+ "Microsoft YaHei", monospace;
82
+ --font-mono: "Maple Mono CN", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
83
+
84
+ /* 内容宽轴(缩短 1/5 保持舒适比例) */
85
+ --dsh-chat-content-width: clamp(544px, 51.2%, 736px);
86
+ --dsh-composer-card-max-width: calc(var(--dsh-chat-content-width) + 32px);
87
+ }
88
+
89
+ @media (prefers-color-scheme: dark) {
90
+ :root:not([data-ds-light-theme]),
91
+ body:not([data-ds-light-theme]) {
92
+ --dsw-bg-base: rgb(21, 21, 23);
93
+ --dsw-bg-elevated: rgb(30, 30, 32);
94
+ --dsw-sidebar-fill: rgb(27, 27, 28);
95
+ --dsw-input-major: rgb(44, 44, 46);
96
+ --dsw-bubble: rgb(38, 40, 46);
97
+ --dsw-hover: rgba(255, 255, 255, 0.05);
98
+ --dsw-active: rgba(255, 255, 255, 0.08);
99
+ --dsw-label-primary: rgb(249, 250, 251);
100
+ --dsw-label-secondary: rgb(207, 211, 214);
101
+ --dsw-label-tertiary: rgb(173, 178, 184);
102
+ --dsw-label-caption: rgb(129, 133, 140);
103
+ --dsw-border-l1: rgba(255, 255, 255, 0.06);
104
+ --dsw-border-l2: rgba(255, 255, 255, 0.12);
105
+ --dsw-border-l3: rgba(255, 255, 255, 0.16);
106
+ --dsw-border-l4: rgba(255, 255, 255, 0.2);
107
+ --dsw-accent: var(--dsw-deepseek-400);
108
+ --dsw-accent-soft: rgba(103, 158, 254, 0.14);
109
+ --dsw-danger: rgb(242, 90, 90);
110
+ --dsw-selector: rgba(255, 255, 255, 0.08);
111
+ --dsw-layer-2: rgb(44, 44, 46);
112
+ --dsw-layer-3: rgb(53, 54, 56);
113
+ --dsw-btn-elevated: rgb(67, 69, 74);
114
+ --dsw-btn-floating-hover: rgb(53, 54, 56);
115
+ --dsw-module-platform: rgb(53, 54, 56);
116
+ --dsw-glass-popover: rgb(53, 54, 56);
117
+ --dsw-glass-input: rgb(44, 44, 46);
118
+ --dsw-glass-modal: rgb(44, 44, 46);
119
+ --dsw-mask: rgba(0, 0, 0, 0.5);
120
+ --dsw-elevation-stroke: var(--dsw-border-l2);
121
+ --dsw-elevation-soft: 0 0 0 0.5px var(--dsw-elevation-stroke), 0 4px 16px rgba(0, 0, 0, 0.2),
122
+ 0 0 24px rgba(0, 0, 0, 0.2);
123
+ --dsw-elevation-panel: 0 0 0 0.5px var(--dsw-elevation-stroke), 0 8px 32px rgba(0, 0, 0, 0.4);
124
+ --dsw-elevation-prominent: 0 0 0 0.5px var(--dsw-elevation-stroke), 0 16px 48px rgba(0, 0, 0, 0.55);
125
+ }
126
+ }
127
+
128
+ html[data-ds-dark-theme],
129
+ body[data-ds-dark-theme] {
130
+ --dsw-bg-base: rgb(21, 21, 23);
131
+ --dsw-bg-elevated: rgb(30, 30, 32);
132
+ --dsw-sidebar-fill: rgb(27, 27, 28);
133
+ --dsw-input-major: rgb(44, 44, 46);
134
+ --dsw-bubble: rgb(38, 40, 46);
135
+ --dsw-hover: rgba(255, 255, 255, 0.05);
136
+ --dsw-active: rgba(255, 255, 255, 0.08);
137
+ --dsw-label-primary: rgb(249, 250, 251);
138
+ --dsw-label-secondary: rgb(207, 211, 214);
139
+ --dsw-label-tertiary: rgb(173, 178, 184);
140
+ --dsw-label-caption: rgb(129, 133, 140);
141
+ --dsw-border-l1: rgba(255, 255, 255, 0.06);
142
+ --dsw-border-l2: rgba(255, 255, 255, 0.12);
143
+ --dsw-border-l3: rgba(255, 255, 255, 0.16);
144
+ --dsw-border-l4: rgba(255, 255, 255, 0.2);
145
+ --dsw-accent: var(--dsw-deepseek-400);
146
+ --dsw-accent-soft: rgba(103, 158, 254, 0.14);
147
+ --dsw-danger: rgb(242, 90, 90);
148
+ --dsw-selector: rgba(255, 255, 255, 0.08);
149
+ --dsw-layer-2: rgb(44, 44, 46);
150
+ --dsw-layer-3: rgb(53, 54, 56);
151
+ --dsw-btn-elevated: rgb(67, 69, 74);
152
+ --dsw-btn-floating-hover: rgb(53, 54, 56);
153
+ --dsw-module-platform: rgb(53, 54, 56);
154
+ --dsw-glass-popover: rgb(53, 54, 56);
155
+ --dsw-glass-input: rgb(44, 44, 46);
156
+ --dsw-glass-modal: rgb(44, 44, 46);
157
+ --dsw-mask: rgba(0, 0, 0, 0.5);
158
+ --dsw-elevation-stroke: var(--dsw-border-l2);
159
+ --dsw-elevation-soft: 0 0 0 0.5px var(--dsw-elevation-stroke), 0 4px 16px rgba(0, 0, 0, 0.2),
160
+ 0 0 24px rgba(0, 0, 0, 0.2);
161
+ --dsw-elevation-panel: 0 0 0 0.5px var(--dsw-elevation-stroke), 0 8px 32px rgba(0, 0, 0, 0.4);
162
+ --dsw-elevation-prominent: 0 0 0 0.5px var(--dsw-elevation-stroke), 0 16px 48px rgba(0, 0, 0, 0.55);
163
+ }
164
+
165
+ /* 基础 */
166
+ html,
167
+ body {
168
+ height: 100%;
169
+ }
170
+ body {
171
+ background: var(--dsw-bg-base);
172
+ color: var(--dsw-label-primary);
173
+ font-family: var(--font-ui);
174
+ font-size: var(--dsh-content-font-size);
175
+ line-height: calc(24px + var(--dsh-content-font-delta));
176
+ -webkit-font-smoothing: antialiased;
177
+ overflow: hidden;
178
+ }
179
+ button {
180
+ font-family: inherit;
181
+ font-size: inherit;
182
+ color: inherit;
183
+ cursor: pointer;
184
+ background: none;
185
+ border: none;
186
+ padding: 0;
187
+ }
188
+ input,
189
+ textarea,
190
+ select {
191
+ font-family: inherit;
192
+ color: inherit;
193
+ background: none;
194
+ border: none;
195
+ outline: none;
196
+ }
197
+ /* 原生下拉弹层跟随主题(暗色下浏览器渲染深色弹层) */
198
+ select {
199
+ color-scheme: light;
200
+ }
201
+ select option {
202
+ background: var(--dsw-layer-2);
203
+ color: var(--dsw-label-primary);
204
+ }
205
+ body[data-ds-dark-theme] select {
206
+ color-scheme: dark;
207
+ }
208
+ input::placeholder,
209
+ textarea::placeholder {
210
+ color: var(--dsw-label-caption);
211
+ }
212
+ * {
213
+ box-sizing: border-box;
214
+ /* dsh: superellipse 渐进增强(不支持则回退普通圆角) */
215
+ corner-shape: superellipse(1.5);
216
+ }
217
+ @media (prefers-reduced-motion: reduce) {
218
+ * {
219
+ transition: none !important;
220
+ animation: none !important;
221
+ }
222
+ }
223
+
224
+ @media (max-width: 840px) {
225
+ :root {
226
+ --dsh-chat-content-width: 100%;
227
+ --dsh-composer-card-max-width: 100%;
228
+ }
229
+
230
+ .pi-main > .hairline-b {
231
+ padding-left: 56px;
232
+ padding-right: 12px;
233
+ }
234
+
235
+ .settings-dialog {
236
+ width: calc(100vw - 16px) !important;
237
+ max-width: none !important;
238
+ height: calc(100vh - 16px) !important;
239
+ flex-direction: column;
240
+ border-radius: 22px !important;
241
+ }
242
+
243
+ .settings-nav {
244
+ width: 100% !important;
245
+ flex-direction: row !important;
246
+ overflow-x: auto;
247
+ padding: 10px !important;
248
+ border-bottom: 0.5px solid var(--dsw-border-l2);
249
+ }
250
+
251
+ .settings-nav > button {
252
+ flex: none;
253
+ height: 36px;
254
+ }
255
+
256
+ .settings-title {
257
+ display: none;
258
+ }
259
+ }
260
+
261
+ /* 滚动条 */
262
+ ::-webkit-scrollbar {
263
+ width: 10px;
264
+ height: 10px;
265
+ }
266
+ ::-webkit-scrollbar-thumb {
267
+ background: var(--dsw-active);
268
+ border-radius: 8px;
269
+ border: 2.5px solid transparent;
270
+ background-clip: content-box;
271
+ }
272
+ ::-webkit-scrollbar-thumb:hover {
273
+ background: var(--dsw-border-l3);
274
+ border: 2px solid transparent;
275
+ background-clip: content-box;
276
+ }
277
+ ::-webkit-scrollbar-track {
278
+ background: transparent;
279
+ }
280
+
281
+ /* ============================================================
282
+ 通用组件样式
283
+ ============================================================ */
284
+
285
+ .icon-btn {
286
+ display: inline-flex;
287
+ align-items: center;
288
+ justify-content: center;
289
+ width: 28px;
290
+ height: 28px;
291
+ border-radius: 8px;
292
+ color: var(--dsw-label-secondary);
293
+ transition: background var(--ds-duration-fast) var(--ds-ease-in-out), color var(--ds-duration-fast)
294
+ var(--ds-ease-in-out);
295
+ }
296
+ .icon-btn:hover {
297
+ background: var(--dsw-hover);
298
+ color: var(--dsw-label-primary);
299
+ }
300
+
301
+ .chip {
302
+ display: inline-flex;
303
+ align-items: center;
304
+ gap: 5px;
305
+ height: 28px;
306
+ padding: 0 10px;
307
+ border-radius: 24px;
308
+ font-size: 13px;
309
+ line-height: 20px;
310
+ font-weight: 500;
311
+ color: var(--dsw-label-primary);
312
+ white-space: nowrap;
313
+ transition: background var(--ds-duration-fast) var(--ds-ease-in-out), color var(--ds-duration-fast)
314
+ var(--ds-ease-in-out);
315
+ }
316
+ .chip:hover {
317
+ background: var(--dsw-hover);
318
+ color: var(--dsw-label-primary);
319
+ }
320
+ .chip .chevron {
321
+ color: var(--dsw-label-caption);
322
+ transition: transform 120ms var(--ds-ease-in-out);
323
+ }
324
+ .chip[data-open="true"] .chevron {
325
+ transform: rotate(180deg);
326
+ }
327
+
328
+ /* Hero 专属工作区 / 预设芯片(对齐 dsh .workspace:透明底、label-primary 纯白高亮、无外框胶囊) */
329
+ .hero-chip {
330
+ display: inline-flex;
331
+ align-items: center;
332
+ gap: 6px;
333
+ height: 28px;
334
+ padding: 0 8px;
335
+ border-radius: 14px;
336
+ background: transparent;
337
+ color: var(--dsw-label-primary);
338
+ font-size: 13px;
339
+ line-height: 20px;
340
+ font-weight: 500;
341
+ white-space: nowrap;
342
+ cursor: pointer;
343
+ transition: background var(--ds-duration-fast) var(--ds-ease-in-out);
344
+ }
345
+ .hero-chip:hover,
346
+ .hero-chip[data-open="true"] {
347
+ background: var(--dsw-hover);
348
+ }
349
+ .hero-chip .hero-chip-icon {
350
+ flex: none;
351
+ color: var(--dsw-label-primary);
352
+ }
353
+ .hero-chip .chevron {
354
+ flex: none;
355
+ color: var(--dsw-label-caption);
356
+ transition: transform 120ms var(--ds-ease-in-out);
357
+ }
358
+ .hero-chip[data-open="true"] .chevron {
359
+ transform: rotate(180deg);
360
+ }
361
+
362
+ /* 描边按钮(dsh Button.outline:胶囊 r18、透明底、0.5px 边) */
363
+ .btn-outline {
364
+ display: inline-flex;
365
+ align-items: center;
366
+ justify-content: center;
367
+ gap: 6px;
368
+ height: 36px;
369
+ padding: 0 14px;
370
+ border-radius: 18px;
371
+ border: 0.5px solid var(--dsw-border-l3);
372
+ background: transparent;
373
+ color: var(--dsw-label-primary);
374
+ font-size: 14px;
375
+ line-height: 22px;
376
+ transition: background var(--ds-duration-fast) var(--ds-ease-in-out);
377
+ }
378
+ .btn-outline:hover {
379
+ background: var(--dsw-hover);
380
+ }
381
+
382
+ /* 主操作实心按钮(表单保存/确认):前景色填充。名称沿用既有调用点。 */
383
+ .btn-primary-white {
384
+ display: inline-flex;
385
+ align-items: center;
386
+ justify-content: center;
387
+ gap: 6px;
388
+ height: 36px;
389
+ padding: 0 14px;
390
+ border-radius: 18px;
391
+ background: var(--dsw-label-primary);
392
+ color: var(--dsw-bg-base);
393
+ font-size: 14px;
394
+ font-weight: 500;
395
+ line-height: 22px;
396
+ transition: opacity var(--ds-duration-fast) var(--ds-ease-in-out);
397
+ }
398
+ .btn-primary-white:disabled {
399
+ opacity: 0.5;
400
+ cursor: default;
401
+ }
402
+
403
+ /* 侧栏「新会话」(dsh .newSession:h38 r12 elevated 底) */
404
+ .btn-new-session {
405
+ display: inline-flex;
406
+ align-items: center;
407
+ justify-content: center;
408
+ gap: 6px;
409
+ height: 38px;
410
+ padding: 8px 16px;
411
+ border-radius: 12px;
412
+ border: 0.5px solid var(--dsw-border-l3);
413
+ background: var(--dsw-btn-elevated);
414
+ color: var(--dsw-label-primary);
415
+ font-size: 14px;
416
+ font-weight: 500;
417
+ line-height: 22px;
418
+ transition: background var(--ds-duration-fast) var(--ds-ease-in-out);
419
+ }
420
+ .btn-new-session:hover {
421
+ background: var(--dsw-btn-floating-hover);
422
+ }
423
+
424
+ /* 设置行右侧下选芯片(dsh「标准模式 ⌄」:胶囊) */
425
+ .select-chip {
426
+ display: inline-flex;
427
+ align-items: center;
428
+ gap: 6px;
429
+ height: 32px;
430
+ padding: 0 12px;
431
+ border-radius: 16px;
432
+ border: 0.5px solid var(--dsw-border-l2);
433
+ font-size: 13px;
434
+ color: var(--dsw-label-primary);
435
+ transition: background var(--ds-duration-fast) var(--ds-ease-in-out);
436
+ }
437
+ .select-chip:hover {
438
+ background: var(--dsw-hover);
439
+ }
440
+
441
+ /* 页签(dsh:蓝色文字 + 蓝色下划线) */
442
+ .tab-underline {
443
+ position: relative;
444
+ padding: 6px 2px;
445
+ font-size: 13.5px;
446
+ color: var(--dsw-label-tertiary);
447
+ transition: color var(--ds-duration-fast) var(--ds-ease-in-out);
448
+ }
449
+ .tab-underline:hover {
450
+ color: var(--dsw-label-primary);
451
+ }
452
+ .tab-underline[data-active="true"] {
453
+ color: var(--dsw-accent);
454
+ font-weight: 600;
455
+ }
456
+ .tab-underline::after {
457
+ content: "";
458
+ position: absolute;
459
+ left: 0;
460
+ right: 0;
461
+ bottom: -1px;
462
+ height: 2px;
463
+ border-radius: 2px;
464
+ background: transparent;
465
+ }
466
+ .tab-underline[data-active="true"]::after {
467
+ background: var(--dsw-accent);
468
+ }
469
+
470
+ .settings-tab-underline {
471
+ position: relative;
472
+ padding: 6px 2px 10px;
473
+ font-size: 13.5px;
474
+ color: var(--dsw-label-tertiary);
475
+ transition: color var(--ds-duration-fast) var(--ds-ease-in-out);
476
+ }
477
+ .settings-tab-underline:hover {
478
+ color: var(--dsw-label-primary);
479
+ }
480
+ .settings-tab-underline[data-active="true"] {
481
+ color: var(--dsw-label-primary);
482
+ font-weight: 500;
483
+ }
484
+ .settings-tab-underline::after {
485
+ content: "";
486
+ position: absolute;
487
+ left: 0;
488
+ right: 0;
489
+ bottom: -1px;
490
+ height: 2px;
491
+ border-radius: 2px;
492
+ background: transparent;
493
+ }
494
+ .settings-tab-underline[data-active="true"]::after {
495
+ background: var(--dsw-label-primary);
496
+ }
497
+
498
+ .btn-primary-circle {
499
+ display: inline-flex;
500
+ align-items: center;
501
+ justify-content: center;
502
+ width: 34px;
503
+ height: 34px;
504
+ border-radius: 999px;
505
+ background: var(--dsw-accent);
506
+ color: #fff;
507
+ transform: translateY(-2px);
508
+ flex: none;
509
+ margin-top: -3px;
510
+ margin-bottom: -3px;
511
+ transition: opacity var(--ds-duration-fast) var(--ds-ease-in-out), transform var(--ds-duration-fast)
512
+ var(--ds-ease-in-out);
513
+ }
514
+ .btn-primary-circle:disabled {
515
+ opacity: 0.4;
516
+ cursor: default;
517
+ }
518
+ /* 运行中有草稿时的幽灵停止钮(发送钮左侧),悬停变警示色 */
519
+ .btn-ghost-circle {
520
+ display: inline-flex;
521
+ align-items: center;
522
+ justify-content: center;
523
+ width: 30px;
524
+ height: 30px;
525
+ border-radius: 999px;
526
+ color: var(--dsw-label-secondary);
527
+ border: 0.5px solid var(--dsw-border-l2);
528
+ background: transparent;
529
+ transform: translateY(-2px);
530
+ flex: none;
531
+ margin-top: -3px;
532
+ margin-bottom: -3px;
533
+ }
534
+ .btn-ghost-circle:hover {
535
+ color: var(--dsw-danger);
536
+ border-color: var(--dsw-danger);
537
+ }
538
+
539
+ /* 排队中的消息:输入卡上方一列(Claude Code 的 queued messages 位置) */
540
+ .pw-queue {
541
+ display: flex;
542
+ flex-direction: column;
543
+ gap: 3px;
544
+ margin: 0 14px 8px;
545
+ font-size: 12.5px;
546
+ }
547
+ .pw-queue-row {
548
+ display: flex;
549
+ align-items: center;
550
+ gap: 8px;
551
+ min-width: 0;
552
+ color: var(--dsw-label-secondary);
553
+ }
554
+ .pw-queue-tag {
555
+ flex: none;
556
+ font-size: 10.5px;
557
+ line-height: 16px;
558
+ padding: 0 6px;
559
+ border-radius: 4px;
560
+ text-transform: capitalize;
561
+ color: var(--dsw-label-tertiary);
562
+ border: 0.5px solid var(--dsw-border-l2);
563
+ }
564
+ .pw-queue-text {
565
+ min-width: 0;
566
+ overflow: hidden;
567
+ text-overflow: ellipsis;
568
+ white-space: nowrap;
569
+ }
570
+ .pw-queue-foot {
571
+ display: flex;
572
+ gap: 12px;
573
+ margin-top: 1px;
574
+ padding-left: 2px;
575
+ font-size: 11.5px;
576
+ color: var(--dsw-label-caption);
577
+ }
578
+ .pw-queue-foot button:hover {
579
+ color: var(--dsw-label-secondary);
580
+ }
581
+ /* 运行中输入卡下方的按键提示 */
582
+ .pw-busy-hint {
583
+ margin: 6px 14px 0;
584
+ font-size: 11.5px;
585
+ line-height: 16px;
586
+ color: var(--dsw-label-caption);
587
+ }
588
+
589
+ .hairline-t {
590
+ border-top: 0.5px solid var(--dsw-border-l2);
591
+ }
592
+ .hairline-b {
593
+ border-bottom: 0.5px solid var(--dsw-border-l2);
594
+ }
595
+ .hairline-r {
596
+ border-right: 0.5px solid var(--dsw-border-l2);
597
+ }
598
+
599
+ /* 侧栏收起导轨按钮(dsh rail:36×36 控件盒、12px 圆角) */
600
+ .rail-btn {
601
+ display: inline-flex;
602
+ align-items: center;
603
+ justify-content: center;
604
+ width: 36px;
605
+ height: 36px;
606
+ border-radius: 12px;
607
+ color: var(--dsw-label-secondary);
608
+ transition: background var(--ds-duration-fast) var(--ds-ease-in-out), color var(--ds-duration-fast)
609
+ var(--ds-ease-in-out);
610
+ }
611
+ .rail-btn:hover {
612
+ background: var(--dsw-hover);
613
+ color: var(--dsw-label-primary);
614
+ }
615
+
616
+ /* 状态点(对齐 dsh StateDot) */
617
+ .state-dot {
618
+ position: relative;
619
+ width: 8px;
620
+ height: 8px;
621
+ border-radius: 999px;
622
+ flex: none;
623
+ }
624
+ .state-dot.running {
625
+ background: var(--dsw-deepseek-450);
626
+ animation: dot-breathe 1s ease-in-out infinite;
627
+ }
628
+ .state-dot.pending {
629
+ background: var(--dsw-warn);
630
+ box-shadow: 0 0 0 3px rgba(245, 158, 11, 0.1);
631
+ }
632
+ .state-dot.done {
633
+ background: var(--dsw-success);
634
+ }
635
+ @keyframes dot-breathe {
636
+ 0%,
637
+ 100% {
638
+ opacity: 1;
639
+ }
640
+ 50% {
641
+ opacity: 0.45;
642
+ }
643
+ }
644
+
645
+ /* 下拉/浮层(玻璃态:半透明层色 + backdrop blur + 发丝线) */
646
+ .popover {
647
+ background: var(--dsw-glass-popover);
648
+ padding: 6px;
649
+ border-radius: 16px;
650
+ box-shadow: var(--dsw-elevation-prominent);
651
+ border: 0.5px solid var(--dsw-border-l1);
652
+ overflow: hidden;
653
+ }
654
+
655
+ /* 居中遮罩层(dsh Modal.mask:遮罩色 + blur) */
656
+ .modal-mask {
657
+ background: var(--dsw-mask);
658
+ backdrop-filter: var(--dsw-mask-blur);
659
+ -webkit-backdrop-filter: var(--dsw-mask-blur);
660
+ }
661
+
662
+ /* 玻璃卡(设置弹窗) */
663
+ .glass-modal {
664
+ background: var(--dsw-glass-modal);
665
+ }
666
+
667
+ /* markdown 内容(字号独立可调:对话字体设置驱动,缺省跟界面字体) */
668
+ .md {
669
+ min-width: 0;
670
+ overflow-wrap: break-word;
671
+ font-size: var(--piweb-chat-font-size);
672
+ line-height: 1.65;
673
+ }
674
+ .md > *:first-child {
675
+ margin-top: 0;
676
+ }
677
+ .md > *:last-child {
678
+ margin-bottom: 0;
679
+ }
680
+ .md p {
681
+ margin: 0.5em 0;
682
+ }
683
+ .md h1,
684
+ .md h2,
685
+ .md h3,
686
+ .md h4 {
687
+ margin: 1em 0 0.4em;
688
+ font-weight: 600;
689
+ line-height: 1.35;
690
+ }
691
+ .md h1 {
692
+ font-size: 1.35em;
693
+ }
694
+ .md h2 {
695
+ font-size: 1.22em;
696
+ }
697
+ .md h3 {
698
+ font-size: 1.1em;
699
+ }
700
+ .md ul,
701
+ .md ol {
702
+ margin: 0.5em 0;
703
+ padding-left: 1.5em;
704
+ }
705
+ .md li {
706
+ margin: 0.2em 0;
707
+ }
708
+ .md a {
709
+ color: var(--dsw-accent);
710
+ text-decoration: none;
711
+ }
712
+ .md a:hover {
713
+ text-decoration: underline;
714
+ }
715
+ .md blockquote {
716
+ margin: 0.6em 0;
717
+ padding: 0.1em 0 0.1em 0.9em;
718
+ border-left: 3px solid var(--dsw-border-l3);
719
+ color: var(--dsw-label-secondary);
720
+ }
721
+ .md code {
722
+ font-family: var(--font-mono);
723
+ font-size: 0.9em;
724
+ background: var(--dsw-selector);
725
+ border-radius: 5px;
726
+ padding: 0.1em 0.35em;
727
+ }
728
+ .md pre {
729
+ margin: 0.7em 0;
730
+ padding: 12px 14px;
731
+ border-radius: 12px;
732
+ background: var(--dsw-selector);
733
+ overflow-x: auto;
734
+ border: 0.5px solid var(--dsw-border-l1);
735
+ }
736
+ .md pre code {
737
+ background: none;
738
+ padding: 0;
739
+ font-size: 13px;
740
+ line-height: 1.55;
741
+ }
742
+ .md table {
743
+ border-collapse: collapse;
744
+ margin: 0.7em 0;
745
+ width: 100%;
746
+ font-size: 0.95em;
747
+ }
748
+ .md th,
749
+ .md td {
750
+ border: 0.5px solid var(--dsw-border-l2);
751
+ padding: 5px 10px;
752
+ text-align: left;
753
+ }
754
+ .md th {
755
+ background: var(--dsw-hover);
756
+ }
757
+ .md hr {
758
+ border: none;
759
+ border-top: 0.5px solid var(--dsw-border-l2);
760
+ margin: 1em 0;
761
+ }
762
+
763
+ /* ---------- 代码高亮(highlight.js):VS Code 式的分类着色,配色跟 Pi 自己的主题走 ---------- */
764
+ :root {
765
+ --hl-comment: rgb(130, 136, 146);
766
+ --hl-keyword: rgb(160, 70, 200);
767
+ --hl-string: rgb(30, 130, 90);
768
+ --hl-number: rgb(190, 100, 20);
769
+ --hl-func: rgb(55, 100, 220);
770
+ --hl-type: rgb(20, 130, 150);
771
+ --hl-attr: rgb(140, 90, 30);
772
+ --hl-tag: rgb(200, 50, 90);
773
+ --hl-regex: rgb(200, 60, 40);
774
+ --hl-meta: rgb(120, 110, 40);
775
+ --hl-punct: var(--dsw-label-tertiary);
776
+ --hl-variable: rgb(30, 100, 170);
777
+ }
778
+ html[data-ds-dark-theme],
779
+ body[data-ds-dark-theme] {
780
+ --hl-comment: rgb(120, 128, 140);
781
+ --hl-keyword: rgb(200, 150, 255);
782
+ --hl-string: rgb(150, 210, 165);
783
+ --hl-number: rgb(240, 175, 110);
784
+ --hl-func: rgb(140, 185, 255);
785
+ --hl-type: rgb(100, 200, 210);
786
+ --hl-attr: rgb(220, 195, 130);
787
+ --hl-tag: rgb(240, 130, 150);
788
+ --hl-regex: rgb(235, 130, 110);
789
+ --hl-meta: rgb(200, 190, 120);
790
+ --hl-punct: var(--dsw-label-tertiary);
791
+ --hl-variable: rgb(150, 200, 250);
792
+ }
793
+ .hljs {
794
+ color: var(--dsw-label-secondary);
795
+ }
796
+ .hljs-comment,
797
+ .hljs-quote {
798
+ color: var(--hl-comment);
799
+ font-style: italic;
800
+ }
801
+ .hljs-keyword,
802
+ .hljs-selector-tag,
803
+ .hljs-literal,
804
+ .hljs-doctag,
805
+ .hljs-section,
806
+ .hljs-strong {
807
+ color: var(--hl-keyword);
808
+ }
809
+ .hljs-strong {
810
+ font-weight: 600;
811
+ }
812
+ .hljs-string,
813
+ .hljs-addition,
814
+ .hljs-symbol,
815
+ .hljs-bullet,
816
+ .hljs-link {
817
+ color: var(--hl-string);
818
+ }
819
+ .hljs-number,
820
+ .hljs-template-variable,
821
+ .hljs-selector-class,
822
+ .hljs-selector-id,
823
+ .hljs-selector-pseudo {
824
+ color: var(--hl-number);
825
+ }
826
+ .hljs-title,
827
+ .hljs-title.function_,
828
+ .hljs-title.class_,
829
+ .hljs-title.class_.inherited__,
830
+ .hljs-name,
831
+ .hljs-code {
832
+ color: var(--hl-func);
833
+ }
834
+ .hljs-type,
835
+ .hljs-built_in,
836
+ .hljs-builtin-name,
837
+ .hljs-class .hljs-title {
838
+ color: var(--hl-type);
839
+ }
840
+ .hljs-attr,
841
+ .hljs-attribute,
842
+ .hljs-property {
843
+ color: var(--hl-attr);
844
+ }
845
+ .hljs-tag,
846
+ .hljs-selector-attr,
847
+ .hljs-deletion {
848
+ color: var(--hl-tag);
849
+ }
850
+ .hljs-regexp,
851
+ .hljs-subst,
852
+ .hljs-char.escape_ {
853
+ color: var(--hl-regex);
854
+ }
855
+ .hljs-meta,
856
+ .hljs-meta .hljs-keyword,
857
+ .hljs-meta .hljs-string,
858
+ .hljs-formula {
859
+ color: var(--hl-meta);
860
+ }
861
+ .hljs-variable,
862
+ .hljs-variable.language_,
863
+ .hljs-params,
864
+ .hljs-operator {
865
+ color: var(--hl-variable);
866
+ }
867
+ .hljs-punctuation {
868
+ color: var(--hl-punct);
869
+ }
870
+ .hljs-emphasis {
871
+ font-style: italic;
872
+ }
873
+ .hljs-deletion {
874
+ background: none;
875
+ }
876
+ .hljs-addition {
877
+ background: none;
878
+ }
879
+
880
+ /* 消息气泡 */
881
+ .msg-user-bubble {
882
+ background: var(--dsw-input-major);
883
+ border-radius: 18px;
884
+ padding: 10px 16px;
885
+ display: inline-block;
886
+ max-width: 85%;
887
+ font-size: var(--piweb-chat-font-size);
888
+ line-height: 1.65;
889
+ }
890
+
891
+ /* 消息操作图标行:常显低透明度,悬停变亮(dsh 同款) */
892
+ .msg-actions {
893
+ display: flex;
894
+ align-items: center;
895
+ gap: 6px;
896
+ margin-top: 6px;
897
+ opacity: 0.45;
898
+ transition: opacity var(--ds-duration-fast) var(--ds-ease-in-out);
899
+ }
900
+ .msg-actions:hover {
901
+ opacity: 1;
902
+ }
903
+
904
+ /* 操作行时钟(dsh MessageIconActions timeStart/timeEnd):
905
+ 次级字号 + 三级标签色;用户行时钟在图标左侧留 12px 间距 */
906
+ .msg-clock {
907
+ font-size: var(--dsh-content-font-size-secondary, 13px);
908
+ line-height: calc(24px + var(--dsh-content-font-delta, 0px));
909
+ color: var(--dsw-label-tertiary);
910
+ }
911
+ .msg-clock-start {
912
+ padding-right: 12px;
913
+ }
914
+
915
+ /* ============================================================
916
+ 对话过程(Pi 版)
917
+ 叙述句 = 阶段标题(基线对齐,主色);其下是「小图标 + 一行摘要」的步骤列表;
918
+ 进行中的思考 / 命令用闪光渐变的英文状态词;回合结束后思考与命令折成一行摘要;
919
+ 编辑文件保留 diff;末尾 π 记号做工作指示。没有连线。
920
+ ============================================================ */
921
+ :root {
922
+ --pw-danger-soft: rgba(236, 19, 19, 0.12);
923
+ /* 闪光高光:浅色主题下比强调色更亮更淡,深色主题下接近白 */
924
+ --pw-shimmer-hi: rgb(150, 190, 255);
925
+ }
926
+ html[data-ds-dark-theme],
927
+ body[data-ds-dark-theme] {
928
+ --pw-danger-soft: rgba(242, 90, 90, 0.16);
929
+ --pw-shimmer-hi: rgb(225, 236, 255);
930
+ }
931
+
932
+ .pw-turn {
933
+ display: flex;
934
+ flex-direction: column;
935
+ gap: 1px;
936
+ padding: 6px 0 2px;
937
+ }
938
+ .pw-run {
939
+ display: flex;
940
+ flex-direction: column;
941
+ gap: 1px;
942
+ }
943
+
944
+ /* 步骤:左侧 16px 图标列 + 内容 */
945
+ .pw-step {
946
+ display: flex;
947
+ align-items: flex-start;
948
+ gap: 10px;
949
+ min-height: 26px;
950
+ animation: pw-in 160ms var(--ds-ease-in-out, ease-out) both;
951
+ }
952
+ @keyframes pw-in {
953
+ from {
954
+ opacity: 0;
955
+ transform: translateY(2px);
956
+ }
957
+ to {
958
+ opacity: 1;
959
+ transform: none;
960
+ }
961
+ }
962
+ .pw-icon {
963
+ flex: none;
964
+ width: 16px;
965
+ height: 26px;
966
+ display: inline-flex;
967
+ align-items: center;
968
+ justify-content: center;
969
+ color: var(--dsw-label-caption);
970
+ }
971
+ .pw-step[data-tone="live"] .pw-icon {
972
+ color: var(--dsw-accent);
973
+ animation: dot-breathe 1.4s ease-in-out infinite;
974
+ }
975
+ .pw-step[data-tone="fail"] .pw-icon {
976
+ color: var(--dsw-danger);
977
+ }
978
+ .pw-step[data-tone="warn"] .pw-icon {
979
+ color: var(--dsw-warn);
980
+ }
981
+ .pw-step[data-kind="retry"] .pw-icon {
982
+ animation: pw-rotate 1.2s linear infinite;
983
+ }
984
+ @keyframes pw-rotate {
985
+ to {
986
+ transform: rotate(360deg);
987
+ }
988
+ }
989
+ /* π 记号:工作指示的图标 */
990
+ .pw-pi {
991
+ font-family: var(--font-mono);
992
+ font-size: 15px;
993
+ font-weight: 600;
994
+ line-height: 1;
995
+ transform: translateY(-1px);
996
+ color: var(--dsw-accent);
997
+ }
998
+ .pw-body {
999
+ min-width: 0;
1000
+ flex: 1;
1001
+ }
1002
+
1003
+ /* 一行摘要 */
1004
+ .pw-line {
1005
+ display: flex;
1006
+ align-items: center;
1007
+ gap: 6px;
1008
+ min-height: 26px;
1009
+ line-height: 26px;
1010
+ font-size: var(--piweb-chat-font-m);
1011
+ color: var(--dsw-label-tertiary);
1012
+ }
1013
+ button.pw-line {
1014
+ width: 100%;
1015
+ text-align: left;
1016
+ background: none;
1017
+ border: 0;
1018
+ padding: 0;
1019
+ cursor: pointer;
1020
+ font: inherit;
1021
+ font-size: var(--piweb-chat-font-m);
1022
+ }
1023
+ button.pw-line:hover {
1024
+ color: var(--dsw-label-secondary);
1025
+ }
1026
+ .pw-verb {
1027
+ flex: none;
1028
+ }
1029
+ .pw-verb[data-failed="true"] {
1030
+ color: var(--dsw-danger);
1031
+ }
1032
+ .pw-arg {
1033
+ min-width: 0;
1034
+ flex: 0 1 auto;
1035
+ overflow: hidden;
1036
+ text-overflow: ellipsis;
1037
+ white-space: nowrap;
1038
+ font-family: var(--font-mono);
1039
+ font-size: var(--piweb-chat-font-s);
1040
+ color: var(--dsw-label-secondary);
1041
+ }
1042
+ .pw-gist {
1043
+ min-width: 0;
1044
+ flex: 1;
1045
+ overflow: hidden;
1046
+ text-overflow: ellipsis;
1047
+ white-space: nowrap;
1048
+ }
1049
+ .pw-meta {
1050
+ flex: none;
1051
+ font-size: var(--piweb-chat-font-t);
1052
+ color: var(--dsw-label-caption);
1053
+ white-space: nowrap;
1054
+ }
1055
+ .pw-line .pw-chev {
1056
+ flex: none;
1057
+ color: var(--dsw-label-caption);
1058
+ transition: transform 120ms var(--ds-ease-in-out, ease);
1059
+ }
1060
+ .pw-line[aria-expanded="true"] .pw-chev {
1061
+ transform: rotate(90deg);
1062
+ }
1063
+ .pw-summary strong {
1064
+ font-weight: 600;
1065
+ color: var(--dsw-label-secondary);
1066
+ }
1067
+ .pw-run[data-open] > .pw-step:not(:first-child) {
1068
+ margin-left: 4px;
1069
+ }
1070
+
1071
+ /* 闪光渐变(进行中的思考 / 命令 / 状态词) */
1072
+ .pw-shimmer {
1073
+ flex: none;
1074
+ /* DeepSeek 式的蓝色渐变闪光:强调色为底,高光扫过 */
1075
+ background: linear-gradient(90deg, var(--dsw-accent) 0%, var(--pw-shimmer-hi) 35%, var(--dsw-accent) 70%);
1076
+ background-size: 220% 100%;
1077
+ -webkit-background-clip: text;
1078
+ background-clip: text;
1079
+ color: transparent;
1080
+ animation: pw-shimmer 2.2s linear infinite;
1081
+ }
1082
+ @keyframes pw-shimmer {
1083
+ from {
1084
+ background-position: 120% 0;
1085
+ }
1086
+ to {
1087
+ background-position: -100% 0;
1088
+ }
1089
+ }
1090
+
1091
+ /* 进行中的思考尾巴:两行截断 */
1092
+ .pw-tail {
1093
+ margin: -4px 0 5px;
1094
+ font-size: var(--piweb-chat-font-s);
1095
+ line-height: 1.5;
1096
+ color: var(--dsw-label-caption);
1097
+ word-break: break-word;
1098
+ display: -webkit-box;
1099
+ -webkit-line-clamp: 2;
1100
+ -webkit-box-orient: vertical;
1101
+ overflow: hidden;
1102
+ }
1103
+
1104
+ /* ⎿ 结果预览 */
1105
+ .pw-result {
1106
+ display: flex;
1107
+ align-items: flex-start;
1108
+ gap: 6px;
1109
+ margin: -4px 0 5px;
1110
+ font-family: var(--font-mono);
1111
+ font-size: var(--piweb-chat-font-t);
1112
+ line-height: 1.55;
1113
+ color: var(--dsw-label-tertiary);
1114
+ }
1115
+ .pw-result[role="button"] {
1116
+ cursor: pointer;
1117
+ }
1118
+ .pw-rail {
1119
+ flex: none;
1120
+ width: 14px;
1121
+ text-align: center;
1122
+ color: var(--dsw-label-caption);
1123
+ user-select: none;
1124
+ }
1125
+ .pw-lines {
1126
+ min-width: 0;
1127
+ flex: 1;
1128
+ white-space: pre-wrap;
1129
+ word-break: break-word;
1130
+ }
1131
+ .pw-lines > div {
1132
+ overflow: hidden;
1133
+ text-overflow: ellipsis;
1134
+ white-space: pre;
1135
+ }
1136
+ .pw-lines .pw-head {
1137
+ color: var(--dsw-label-tertiary);
1138
+ }
1139
+ .pw-lines .pw-more {
1140
+ color: var(--dsw-label-caption);
1141
+ }
1142
+ .pw-result[role="button"]:hover .pw-more {
1143
+ text-decoration: underline;
1144
+ }
1145
+ .pw-result[data-failed="true"],
1146
+ .pw-result[data-failed="true"] .pw-rail,
1147
+ .pw-result[data-failed="true"] .pw-head {
1148
+ color: var(--dsw-danger);
1149
+ }
1150
+
1151
+ /* diff 与完整输出 */
1152
+ .pw-diff {
1153
+ margin: -2px 0 6px 20px;
1154
+ max-height: 420px;
1155
+ overflow: auto;
1156
+ border-radius: 10px;
1157
+ padding: 6px 8px;
1158
+ background: var(--dsw-markdown-code-block, var(--dsw-hover));
1159
+ }
1160
+ .pw-output {
1161
+ margin: 0 0 6px 20px;
1162
+ max-height: 360px;
1163
+ overflow: auto;
1164
+ border-radius: 10px;
1165
+ padding: 8px 12px;
1166
+ background: var(--dsw-markdown-code-block, var(--dsw-hover));
1167
+ font-family: var(--font-mono);
1168
+ font-size: var(--piweb-chat-font-t);
1169
+ line-height: 1.55;
1170
+ color: var(--dsw-label-secondary);
1171
+ white-space: pre-wrap;
1172
+ word-break: break-word;
1173
+ }
1174
+ .pw-output.pw-think-full {
1175
+ font-family: inherit;
1176
+ color: var(--dsw-label-tertiary);
1177
+ }
1178
+ .pw-output .cmdline {
1179
+ color: var(--dsw-label-tertiary);
1180
+ margin-bottom: 6px;
1181
+ padding-bottom: 6px;
1182
+ border-bottom: 0.5px solid var(--dsw-border-l2);
1183
+ white-space: pre-wrap;
1184
+ word-break: break-all;
1185
+ }
1186
+ .pw-output .cmdline::before {
1187
+ content: "$ ";
1188
+ color: var(--dsw-label-caption);
1189
+ }
1190
+ button.pw-more {
1191
+ display: block;
1192
+ margin-top: 4px;
1193
+ font: inherit;
1194
+ font-family: var(--font-mono);
1195
+ font-size: var(--piweb-chat-font-t);
1196
+ color: var(--dsw-label-caption);
1197
+ cursor: pointer;
1198
+ background: none;
1199
+ border: 0;
1200
+ padding: 0;
1201
+ text-align: left;
1202
+ }
1203
+ button.pw-more:hover {
1204
+ color: var(--dsw-label-secondary);
1205
+ text-decoration: underline;
1206
+ }
1207
+
1208
+ /* 叙述:阶段标题,基线对齐(步骤的图标列自然形成缩进) */
1209
+ .pw-narr {
1210
+ margin: 7px 0 3px;
1211
+ font-size: var(--piweb-chat-font-l);
1212
+ line-height: 1.65;
1213
+ color: var(--dsw-label-primary);
1214
+ }
1215
+ .pw-turn > .pw-narr:first-child {
1216
+ margin-top: 1px;
1217
+ }
1218
+ .pw-narr[data-error="true"] {
1219
+ color: var(--dsw-danger);
1220
+ }
1221
+ .pw-narr .md p {
1222
+ margin: 0;
1223
+ }
1224
+ .pw-narr .md p + p {
1225
+ margin-top: 0.5em;
1226
+ }
1227
+ .pw-narr .md pre {
1228
+ margin: 0.5em 0;
1229
+ }
1230
+
1231
+ /* 错误 / 中止 / 上下文注入 */
1232
+ .pw-warn-text {
1233
+ min-width: 0;
1234
+ flex: 1;
1235
+ overflow: hidden;
1236
+ text-overflow: ellipsis;
1237
+ white-space: nowrap;
1238
+ color: var(--dsw-warn);
1239
+ }
1240
+ .pw-step[data-kind="context"] .pw-line,
1241
+ .pw-step[data-kind="abort"] .pw-line {
1242
+ color: var(--dsw-label-caption);
1243
+ font-size: var(--piweb-chat-font-s);
1244
+ }
1245
+
1246
+ /* ============================================================
1247
+ Pebrel 主题(https://github.com/Kuddev/pebrel)
1248
+ 四对亮暗主题 + Pebrel 原生深色(亮色回落 SilverLight)。
1249
+ 每对内亮/暗跟随系统(data-ds-dark-theme 由 theme.ts 同步)。
1250
+ 注意:本段必须位于文件末尾,靠源顺序赢得与旧 dsh 暗色块的平级覆盖。
1251
+ ============================================================ */
1252
+
1253
+ /* ---------- 亮色:Pebrel 通用浅色基 ---------- */
1254
+ html[data-pebrel-theme],
1255
+ body[data-pebrel-theme] {
1256
+ --dsw-bg-base: #ffffff;
1257
+ --dsw-bg-elevated: #ffffff;
1258
+ --dsw-input-major: #ffffff;
1259
+ --dsw-bubble: rgba(100, 116, 139, 0.05);
1260
+ --dsw-hover: rgba(100, 116, 139, 0.13);
1261
+ --dsw-active: rgba(100, 116, 139, 0.2);
1262
+ --dsw-label-primary: #334155;
1263
+ --dsw-label-secondary: #64748b;
1264
+ --dsw-label-tertiary: #94a3b8;
1265
+ --dsw-label-caption: #a3adbb;
1266
+ --dsw-border-l1: rgba(51, 65, 85, 0.08);
1267
+ --dsw-border-l2: rgba(51, 65, 85, 0.12);
1268
+ --dsw-border-l3: rgba(51, 65, 85, 0.16);
1269
+ --dsw-border-l4: rgba(51, 65, 85, 0.24);
1270
+ --dsw-warn: #d97706;
1271
+ --dsw-success: #548c9e;
1272
+ --dsw-danger: #b23a48;
1273
+ --dsw-selector: rgba(100, 116, 139, 0.08);
1274
+ --dsw-layer-2: #ffffff;
1275
+ --dsw-layer-3: #f5f5f6;
1276
+ --dsw-btn-elevated: #ffffff;
1277
+ --dsw-btn-floating-hover: rgba(100, 116, 139, 0.13);
1278
+ --dsw-module-platform: #f5f5f6;
1279
+ --dsw-border-strong: #64748b;
1280
+ --dsw-glass-popover: #ffffff;
1281
+ --dsw-glass-input: #ffffff;
1282
+ --dsw-glass-modal: #ffffff;
1283
+ --dsw-mask: rgba(15, 23, 42, 0.22);
1284
+ --dsw-elevation-stroke: var(--dsw-border-l2);
1285
+ }
1286
+
1287
+ /* 银钢(SilverLight;Pebrel 亮色回落同此) */
1288
+ html[data-pebrel-theme="silver-steel"],
1289
+ html[data-pebrel-theme="pebrel"],
1290
+ body[data-pebrel-theme="silver-steel"],
1291
+ body[data-pebrel-theme="pebrel"] {
1292
+ --dsw-sidebar-fill: #f3f4f6;
1293
+ --dsw-accent: rgb(73, 80, 87);
1294
+ --dsw-accent-soft: rgba(73, 80, 87, 0.12);
1295
+ }
1296
+
1297
+ /* 石灰(LimestoneLight) */
1298
+ html[data-pebrel-theme="limestone-coal"],
1299
+ body[data-pebrel-theme="limestone-coal"] {
1300
+ --dsw-sidebar-fill: #f0efeb;
1301
+ --dsw-layer-3: #f0efeb;
1302
+ --dsw-module-platform: #f0efeb;
1303
+ --dsw-accent: rgb(88, 85, 76);
1304
+ --dsw-accent-soft: rgba(88, 85, 76, 0.12);
1305
+ }
1306
+
1307
+ /* 亚麻(LinenLight) */
1308
+ html[data-pebrel-theme="linen-moss"],
1309
+ body[data-pebrel-theme="linen-moss"] {
1310
+ --dsw-sidebar-fill: #f2f2ec;
1311
+ --dsw-layer-3: #f2f2ec;
1312
+ --dsw-module-platform: #f2f2ec;
1313
+ --dsw-accent: rgb(95, 99, 95);
1314
+ --dsw-accent-soft: rgba(95, 99, 95, 0.12);
1315
+ }
1316
+
1317
+ /* 纸墨(Paper,完整浅色皮肤) */
1318
+ html[data-pebrel-theme="nord-paper"],
1319
+ body[data-pebrel-theme="nord-paper"] {
1320
+ --dsw-bg-base: #fcfbf9;
1321
+ --dsw-bg-elevated: #f5f4f0;
1322
+ --dsw-sidebar-fill: #f5f4f0;
1323
+ --dsw-input-major: #fcfbf9;
1324
+ --dsw-bubble: rgba(140, 138, 128, 0.08);
1325
+ --dsw-hover: #ebeae5;
1326
+ --dsw-active: rgba(43, 90, 56, 0.18);
1327
+ --dsw-label-primary: #1a1a1a;
1328
+ --dsw-label-secondary: #474646;
1329
+ --dsw-label-tertiary: #8c8a80;
1330
+ --dsw-label-caption: #a8a49a;
1331
+ --dsw-border-l1: #eceae4;
1332
+ --dsw-border-l2: #e0dfd5;
1333
+ --dsw-border-l3: #d5d3c9;
1334
+ --dsw-border-l4: #c1beb5;
1335
+ --dsw-accent: #2b5a38;
1336
+ --dsw-accent-soft: rgba(43, 90, 56, 0.18);
1337
+ --dsw-warn: #a85a20;
1338
+ --dsw-success: #2b5a38;
1339
+ --dsw-danger: #a33a3a;
1340
+ --dsw-selector: #ebeae5;
1341
+ --dsw-layer-2: #fcfbf9;
1342
+ --dsw-layer-3: #f5f4f0;
1343
+ --dsw-btn-elevated: #fcfbf9;
1344
+ --dsw-btn-floating-hover: #ebeae5;
1345
+ --dsw-module-platform: #f0efe9;
1346
+ --dsw-border-strong: #8c8a80;
1347
+ --dsw-glass-popover: #fcfbf9;
1348
+ --dsw-glass-input: #fcfbf9;
1349
+ --dsw-glass-modal: #f5f4f0;
1350
+ --dsw-mask: rgba(26, 26, 26, 0.19);
1351
+ }
1352
+
1353
+ /* ---------- 暗色:Pebrel 通用深色基 ---------- */
1354
+ html[data-pebrel-theme][data-ds-dark-theme],
1355
+ body[data-pebrel-theme][data-ds-dark-theme] {
1356
+ --dsw-label-primary: #e2e8f0;
1357
+ --dsw-label-secondary: #b9c3cf;
1358
+ --dsw-label-tertiary: #94a3b8;
1359
+ --dsw-label-caption: #64748b;
1360
+ --dsw-bubble: rgba(255, 255, 255, 0.05);
1361
+ --dsw-hover: rgba(203, 213, 225, 0.14);
1362
+ --dsw-active: rgba(203, 213, 225, 0.21);
1363
+ --dsw-border-l1: rgba(203, 213, 225, 0.08);
1364
+ --dsw-border-l2: rgba(203, 213, 225, 0.12);
1365
+ --dsw-border-l3: rgba(203, 213, 225, 0.16);
1366
+ --dsw-border-l4: rgba(203, 213, 225, 0.24);
1367
+ --dsw-warn: #f59e0b;
1368
+ --dsw-success: #7db2c2;
1369
+ --dsw-danger: #c44a58;
1370
+ --dsw-selector: rgba(203, 213, 225, 0.08);
1371
+ --dsw-border-strong: #94a3b8;
1372
+ --dsw-mask: rgba(2, 6, 23, 0.5);
1373
+ --dsw-elevation-stroke: var(--dsw-border-l2);
1374
+ }
1375
+
1376
+ /* 钢(SteelDark) */
1377
+ html[data-pebrel-theme="silver-steel"][data-ds-dark-theme],
1378
+ body[data-pebrel-theme="silver-steel"][data-ds-dark-theme] {
1379
+ --dsw-bg-base: #16181e;
1380
+ --dsw-bg-elevated: #1e2129;
1381
+ --dsw-sidebar-fill: #16181e;
1382
+ --dsw-input-major: #1a1c24;
1383
+ --dsw-layer-2: #1e2129;
1384
+ --dsw-layer-3: #343a48;
1385
+ --dsw-btn-elevated: #1e2129;
1386
+ --dsw-btn-floating-hover: rgba(203, 213, 225, 0.14);
1387
+ --dsw-module-platform: #1e2129;
1388
+ --dsw-glass-popover: #1e2129;
1389
+ --dsw-glass-input: #1a1c24;
1390
+ --dsw-glass-modal: #1e2129;
1391
+ --dsw-accent: #94a3b8;
1392
+ --dsw-accent-soft: rgba(148, 163, 184, 0.15);
1393
+ }
1394
+
1395
+ /* 煤(CoalDark,金棕点缀) */
1396
+ html[data-pebrel-theme="limestone-coal"][data-ds-dark-theme],
1397
+ body[data-pebrel-theme="limestone-coal"][data-ds-dark-theme] {
1398
+ --dsw-bg-base: #161616;
1399
+ --dsw-bg-elevated: #1e1e1e;
1400
+ --dsw-sidebar-fill: #161616;
1401
+ --dsw-input-major: #171717;
1402
+ --dsw-layer-2: #1e1e1e;
1403
+ --dsw-layer-3: #383836;
1404
+ --dsw-btn-elevated: #1e1e1e;
1405
+ --dsw-btn-floating-hover: rgba(203, 213, 225, 0.14);
1406
+ --dsw-module-platform: #1e1e1e;
1407
+ --dsw-glass-popover: #1e1e1e;
1408
+ --dsw-glass-input: #171717;
1409
+ --dsw-glass-modal: #1e1e1e;
1410
+ --dsw-accent: #d4d4d4;
1411
+ --dsw-accent-soft: rgba(212, 212, 212, 0.14);
1412
+ --dsw-warn: #ceb27e;
1413
+ }
1414
+
1415
+ /* 苔(MossDark) */
1416
+ html[data-pebrel-theme="linen-moss"][data-ds-dark-theme],
1417
+ body[data-pebrel-theme="linen-moss"][data-ds-dark-theme] {
1418
+ --dsw-bg-base: #191c19;
1419
+ --dsw-bg-elevated: #212521;
1420
+ --dsw-sidebar-fill: #191c19;
1421
+ --dsw-input-major: #1e211e;
1422
+ --dsw-layer-2: #212521;
1423
+ --dsw-layer-3: #363d36;
1424
+ --dsw-btn-elevated: #212521;
1425
+ --dsw-btn-floating-hover: rgba(203, 213, 225, 0.14);
1426
+ --dsw-module-platform: #212521;
1427
+ --dsw-glass-popover: #212521;
1428
+ --dsw-glass-input: #1e211e;
1429
+ --dsw-glass-modal: #212521;
1430
+ --dsw-accent: #a3b3a3;
1431
+ --dsw-accent-soft: rgba(163, 179, 163, 0.15);
1432
+ }
1433
+
1434
+ /* 北欧(Nord,完整深色皮肤) */
1435
+ html[data-pebrel-theme="nord-paper"][data-ds-dark-theme],
1436
+ body[data-pebrel-theme="nord-paper"][data-ds-dark-theme] {
1437
+ --dsw-bg-base: #2e3440;
1438
+ --dsw-bg-elevated: #3b4252;
1439
+ --dsw-sidebar-fill: #2e3440;
1440
+ --dsw-input-major: #3b4252;
1441
+ --dsw-bubble: #3b4252;
1442
+ --dsw-hover: rgba(255, 255, 255, 0.06);
1443
+ --dsw-active: rgba(136, 192, 208, 0.18);
1444
+ --dsw-label-primary: #e5e9f0;
1445
+ --dsw-label-secondary: #c0c7d3;
1446
+ --dsw-label-tertiary: #7b8294;
1447
+ --dsw-label-caption: #6f7688;
1448
+ --dsw-border-l1: rgba(255, 255, 255, 0.05);
1449
+ --dsw-border-l2: rgba(255, 255, 255, 0.06);
1450
+ --dsw-border-l3: #434c5e;
1451
+ --dsw-border-l4: #4c566a;
1452
+ --dsw-accent: #88c0d0;
1453
+ --dsw-accent-soft: rgba(136, 192, 208, 0.18);
1454
+ --dsw-warn: #ebcb8b;
1455
+ --dsw-success: #a3be8c;
1456
+ --dsw-danger: #bf616a;
1457
+ --dsw-selector: rgba(255, 255, 255, 0.06);
1458
+ --dsw-layer-2: #3b4252;
1459
+ --dsw-layer-3: #434c5e;
1460
+ --dsw-btn-elevated: #3b4252;
1461
+ --dsw-btn-floating-hover: #434c5e;
1462
+ --dsw-module-platform: #3b4252;
1463
+ --dsw-border-strong: #7b8294;
1464
+ --dsw-glass-popover: #3b4252;
1465
+ --dsw-glass-input: #3b4252;
1466
+ --dsw-glass-modal: #3b4252;
1467
+ --dsw-mask: rgba(2, 6, 23, 0.36);
1468
+ }
1469
+
1470
+ /* Pebrel 原生(Nebula,深色专属) */
1471
+ html[data-pebrel-theme="pebrel"][data-ds-dark-theme],
1472
+ body[data-pebrel-theme="pebrel"][data-ds-dark-theme] {
1473
+ --dsw-bg-base: #222630;
1474
+ --dsw-bg-elevated: #2b303b;
1475
+ --dsw-sidebar-fill: #222630;
1476
+ --dsw-input-major: #0f111a;
1477
+ --dsw-layer-2: #2b303b;
1478
+ --dsw-layer-3: #414858;
1479
+ --dsw-btn-elevated: #2b303b;
1480
+ --dsw-btn-floating-hover: rgba(203, 213, 225, 0.14);
1481
+ --dsw-module-platform: #2b303b;
1482
+ --dsw-glass-popover: #2b303b;
1483
+ --dsw-glass-input: #0f111a;
1484
+ --dsw-glass-modal: #2b303b;
1485
+ --dsw-accent: #52a8ff;
1486
+ --dsw-accent-soft: rgba(82, 168, 255, 0.15);
1487
+ }
1488
+
1489
+ /* 操作按钮进行中反馈(如分支) */
1490
+ @keyframes piweb-spin-kf {
1491
+ to {
1492
+ transform: rotate(360deg);
1493
+ }
1494
+ }
1495
+ .piweb-spin {
1496
+ animation: piweb-spin-kf 0.8s linear infinite;
1497
+ }
1498
+ /* 连接测试阶段节点的呼吸态(照 Nebula 连接卡片的流动感,PiWeb 化为脉冲) */
1499
+ @keyframes piweb-pulse-kf {
1500
+ 0%,
1501
+ 100% {
1502
+ opacity: 1;
1503
+ }
1504
+ 50% {
1505
+ opacity: 0.3;
1506
+ }
1507
+ }
1508
+ .piweb-pulse {
1509
+ animation: piweb-pulse-kf 1.1s ease-in-out infinite;
1510
+ }
1511
+ /* 流式正文末尾的光标:像终端一样告诉用户“还在写” */
1512
+ @keyframes stream-cursor-kf {
1513
+ 0%,
1514
+ 49% {
1515
+ opacity: 1;
1516
+ }
1517
+ 50%,
1518
+ 100% {
1519
+ opacity: 0;
1520
+ }
1521
+ }
1522
+ .stream-cursor {
1523
+ display: inline-block;
1524
+ width: 2px;
1525
+ height: 1em;
1526
+ margin-left: 2px;
1527
+ vertical-align: -0.15em;
1528
+ background: var(--dsw-accent);
1529
+ animation: stream-cursor-kf 1s steps(1) infinite;
1530
+ }
1531
+
1532
+ /* ============================================================
1533
+ 项目生长:项目栏 / 项目树 / 时间轴 / 文件查看器 / 整文件 diff
1534
+ ============================================================ */
1535
+
1536
+ /* 分段开关(本步 / 本会话、变更 / 内容 / 渲染) */
1537
+ .pw-seg {
1538
+ display: inline-flex;
1539
+ flex: none;
1540
+ padding: 2px;
1541
+ border-radius: 8px;
1542
+ background: var(--dsw-hover);
1543
+ gap: 1px;
1544
+ }
1545
+ .pw-seg > button {
1546
+ height: 20px;
1547
+ padding: 0 8px;
1548
+ border-radius: 6px;
1549
+ font-size: 11.5px;
1550
+ line-height: 20px;
1551
+ color: var(--dsw-label-tertiary);
1552
+ white-space: nowrap;
1553
+ transition: background var(--ds-duration-fast) var(--ds-ease-in-out), color var(--ds-duration-fast) var(--ds-ease-in-out);
1554
+ }
1555
+ .pw-seg > button[data-active="true"] {
1556
+ background: var(--dsw-bg-elevated);
1557
+ color: var(--dsw-label-primary);
1558
+ box-shadow: 0 0 0 0.5px var(--dsw-border-l2), 0 1px 2px rgba(0, 0, 0, 0.06);
1559
+ }
1560
+ /* 小胶囊开关(只看变更 / 跟随 / 折叠未改动) */
1561
+ .pw-chip {
1562
+ flex: none;
1563
+ height: 20px;
1564
+ padding: 0 8px;
1565
+ border-radius: 999px;
1566
+ border: 0.5px solid var(--dsw-border-l3);
1567
+ font-size: 11px;
1568
+ line-height: 19px;
1569
+ color: var(--dsw-label-tertiary);
1570
+ white-space: nowrap;
1571
+ transition: background var(--ds-duration-fast) var(--ds-ease-in-out), color var(--ds-duration-fast) var(--ds-ease-in-out), border-color var(--ds-duration-fast) var(--ds-ease-in-out);
1572
+ }
1573
+ .pw-chip:hover {
1574
+ background: var(--dsw-hover);
1575
+ color: var(--dsw-label-primary);
1576
+ }
1577
+ .pw-chip[data-active="true"] {
1578
+ background: var(--dsw-accent-soft);
1579
+ border-color: transparent;
1580
+ color: var(--dsw-accent);
1581
+ }
1582
+ .pw-chip:disabled {
1583
+ opacity: 0.4;
1584
+ pointer-events: none;
1585
+ }
1586
+
1587
+ /* 项目栏 */
1588
+ .pw-project {
1589
+ background: var(--dsw-sidebar-fill);
1590
+ border-right: 0.5px solid var(--dsw-border-l2);
1591
+ }
1592
+ .pw-project input,
1593
+ .pw-viewer input {
1594
+ outline: none;
1595
+ color: var(--dsw-label-primary);
1596
+ }
1597
+
1598
+ /* 项目树:22px 紧凑行 */
1599
+ .pw-tree {
1600
+ font-size: 12.5px;
1601
+ line-height: 22px;
1602
+ user-select: none;
1603
+ }
1604
+ .pw-tree-row {
1605
+ position: absolute;
1606
+ left: 0;
1607
+ right: 0;
1608
+ height: 22px;
1609
+ display: flex;
1610
+ align-items: center;
1611
+ gap: 4px;
1612
+ padding-right: 8px;
1613
+ border-radius: 6px;
1614
+ cursor: pointer;
1615
+ white-space: nowrap;
1616
+ color: var(--dsw-label-primary);
1617
+ transition: background var(--ds-duration-fast) var(--ds-ease-in-out);
1618
+ }
1619
+ .pw-tree-row:hover {
1620
+ background: var(--dsw-hover);
1621
+ }
1622
+ .pw-tree-row[data-selected],
1623
+ .pw-tree-row[data-focused] {
1624
+ background: var(--dsw-active);
1625
+ }
1626
+ .pw-tree:focus-visible .pw-tree-row[data-focused] {
1627
+ box-shadow: inset 0 0 0 1px var(--dsw-accent);
1628
+ }
1629
+ .pw-tree-row[data-lazy] > .pw-tree-name {
1630
+ color: var(--dsw-label-caption);
1631
+ }
1632
+ .pw-tree-chevron {
1633
+ flex: none;
1634
+ width: 12px;
1635
+ display: inline-flex;
1636
+ align-items: center;
1637
+ justify-content: center;
1638
+ color: var(--dsw-label-caption);
1639
+ }
1640
+ .pw-tree-icon {
1641
+ flex: none;
1642
+ width: 16px;
1643
+ height: 16px;
1644
+ object-fit: contain;
1645
+ }
1646
+ .pw-tree-row > .pw-tree-icon {
1647
+ filter: saturate(0.78);
1648
+ transition: filter var(--ds-duration-fast) var(--ds-ease-in-out), opacity var(--ds-duration-fast) var(--ds-ease-in-out);
1649
+ }
1650
+ .pw-tree-row > .pw-tree-icon[data-kind="dir"] {
1651
+ transform: translateY(-0.25px) scale(0.87);
1652
+ opacity: 0.88;
1653
+ }
1654
+ .pw-tree-row > .pw-tree-icon[data-kind="file"] {
1655
+ transform: scale(0.91);
1656
+ opacity: 0.93;
1657
+ }
1658
+ .pw-tree-row:hover > .pw-tree-icon {
1659
+ filter: saturate(0.95);
1660
+ opacity: 1;
1661
+ }
1662
+ .pw-viewer .pw-tree-icon {
1663
+ transform: scale(0.9);
1664
+ filter: saturate(0.82);
1665
+ opacity: 0.92;
1666
+ }
1667
+ .pw-tree-name {
1668
+ min-width: 0;
1669
+ flex: 1;
1670
+ overflow: hidden;
1671
+ text-overflow: ellipsis;
1672
+ }
1673
+ .pw-tree-from {
1674
+ margin-left: 6px;
1675
+ font-size: 11px;
1676
+ color: var(--dsw-label-caption);
1677
+ }
1678
+ .pw-tree-stat {
1679
+ flex: none;
1680
+ display: inline-flex;
1681
+ gap: 4px;
1682
+ font-size: 10.5px;
1683
+ font-variant-numeric: tabular-nums;
1684
+ color: var(--dsw-label-caption);
1685
+ }
1686
+ .pw-tree-badge {
1687
+ flex: none;
1688
+ min-width: 14px;
1689
+ height: 14px;
1690
+ padding: 0 3px;
1691
+ border-radius: 4px;
1692
+ border: 0.5px solid;
1693
+ font-size: 10px;
1694
+ line-height: 13px;
1695
+ text-align: center;
1696
+ font-weight: 600;
1697
+ font-variant-numeric: tabular-nums;
1698
+ }
1699
+ .pw-tree-actions {
1700
+ flex: none;
1701
+ display: none;
1702
+ align-items: center;
1703
+ gap: 1px;
1704
+ }
1705
+ .pw-tree-row:hover .pw-tree-actions {
1706
+ display: inline-flex;
1707
+ }
1708
+ .pw-tree-row:hover .pw-tree-stat {
1709
+ display: none;
1710
+ }
1711
+ /* 生成中:呼吸点 */
1712
+ .pw-tree-pulse {
1713
+ flex: none;
1714
+ width: 6px;
1715
+ height: 6px;
1716
+ border-radius: 999px;
1717
+ background: var(--dsw-accent);
1718
+ animation: dot-breathe 1s ease-in-out infinite;
1719
+ }
1720
+ .pw-tree-row[data-pending] > .pw-tree-name {
1721
+ color: var(--dsw-accent);
1722
+ }
1723
+ /* 新步入场:滑入 + 辉光淡出 */
1724
+ @keyframes pw-tree-in {
1725
+ from {
1726
+ opacity: 0;
1727
+ transform: translateX(-6px);
1728
+ }
1729
+ to {
1730
+ opacity: 1;
1731
+ transform: none;
1732
+ }
1733
+ }
1734
+ @keyframes pw-tree-glow-add {
1735
+ from {
1736
+ background: rgba(34, 197, 94, 0.28);
1737
+ }
1738
+ to {
1739
+ background: transparent;
1740
+ }
1741
+ }
1742
+ @keyframes pw-tree-glow-mod {
1743
+ from {
1744
+ background: rgba(245, 158, 11, 0.26);
1745
+ }
1746
+ to {
1747
+ background: transparent;
1748
+ }
1749
+ }
1750
+ @keyframes pw-tree-glow-del {
1751
+ from {
1752
+ background: rgba(236, 19, 19, 0.24);
1753
+ }
1754
+ to {
1755
+ background: transparent;
1756
+ }
1757
+ }
1758
+ .pw-tree-row[data-fresh] {
1759
+ animation: pw-tree-in 250ms var(--ds-ease-in-out) both, pw-tree-glow-mod 2.2s ease-out both;
1760
+ }
1761
+ .pw-tree-row[data-fresh="A"] {
1762
+ animation-name: pw-tree-in, pw-tree-glow-add;
1763
+ }
1764
+ .pw-tree-row[data-fresh="D"] {
1765
+ animation-name: pw-tree-in, pw-tree-glow-del;
1766
+ }
1767
+
1768
+ /* 轮次导航 */
1769
+ .pw-timeline {
1770
+ flex: none;
1771
+ }
1772
+
1773
+ /* 文件查看器:80vw × 80vh 居中,全屏切 100% */
1774
+ .pw-viewer {
1775
+ width: 80vw;
1776
+ height: 80vh;
1777
+ border-radius: 20px;
1778
+ box-shadow: var(--dsw-elevation-prominent);
1779
+ animation: pw-in 160ms var(--ds-ease-in-out) both;
1780
+ transition: width var(--ds-duration-normal) var(--ds-ease-in-out), height var(--ds-duration-normal) var(--ds-ease-in-out), border-radius var(--ds-duration-normal) var(--ds-ease-in-out);
1781
+ }
1782
+ .pw-viewer[data-fullscreen] {
1783
+ width: 100vw;
1784
+ height: 100vh;
1785
+ border-radius: 0;
1786
+ }
1787
+ .pw-viewer-tabs {
1788
+ flex: none;
1789
+ display: flex;
1790
+ align-items: center;
1791
+ gap: 2px;
1792
+ height: 40px;
1793
+ padding: 0 8px 0 10px;
1794
+ }
1795
+ .pw-viewer-tabstrip {
1796
+ display: flex;
1797
+ align-items: center;
1798
+ gap: 2px;
1799
+ min-width: 0;
1800
+ overflow-x: auto;
1801
+ scrollbar-width: none;
1802
+ }
1803
+ .pw-viewer-tabstrip::-webkit-scrollbar {
1804
+ display: none;
1805
+ }
1806
+ .pw-viewer-tab {
1807
+ flex: none;
1808
+ display: inline-flex;
1809
+ align-items: center;
1810
+ gap: 6px;
1811
+ height: 28px;
1812
+ max-width: 200px;
1813
+ padding: 0 8px 0 8px;
1814
+ border-radius: 8px;
1815
+ font-size: 12.5px;
1816
+ color: var(--dsw-label-tertiary);
1817
+ transition: background var(--ds-duration-fast) var(--ds-ease-in-out), color var(--ds-duration-fast) var(--ds-ease-in-out);
1818
+ }
1819
+ .pw-viewer-tab:hover {
1820
+ background: var(--dsw-hover);
1821
+ color: var(--dsw-label-primary);
1822
+ }
1823
+ .pw-viewer-tab[data-active="true"] {
1824
+ background: var(--dsw-active);
1825
+ color: var(--dsw-label-primary);
1826
+ }
1827
+ .pw-viewer-tab-main {
1828
+ display: inline-flex;
1829
+ align-items: center;
1830
+ gap: 6px;
1831
+ min-width: 0;
1832
+ color: inherit;
1833
+ }
1834
+ .pw-viewer-tab-close {
1835
+ display: inline-flex;
1836
+ align-items: center;
1837
+ justify-content: center;
1838
+ width: 16px;
1839
+ height: 16px;
1840
+ margin-right: -4px;
1841
+ border-radius: 4px;
1842
+ color: var(--dsw-label-caption);
1843
+ opacity: 0;
1844
+ transition: opacity var(--ds-duration-fast) var(--ds-ease-in-out);
1845
+ }
1846
+ .pw-viewer-tab:hover .pw-viewer-tab-close,
1847
+ .pw-viewer-tab[data-active="true"] .pw-viewer-tab-close,
1848
+ .pw-viewer-tab-close:focus-visible {
1849
+ opacity: 1;
1850
+ }
1851
+ .pw-viewer-tab-close:hover {
1852
+ background: var(--dsw-hover);
1853
+ color: var(--dsw-label-primary);
1854
+ }
1855
+ .pw-viewer-toolbar {
1856
+ flex: none;
1857
+ display: flex;
1858
+ align-items: center;
1859
+ gap: 6px;
1860
+ height: 36px;
1861
+ padding: 0 12px;
1862
+ }
1863
+ .pw-crumb {
1864
+ display: flex;
1865
+ align-items: center;
1866
+ flex-wrap: nowrap;
1867
+ overflow: hidden;
1868
+ font-size: 12.5px;
1869
+ color: var(--dsw-label-tertiary);
1870
+ white-space: nowrap;
1871
+ }
1872
+ .pw-crumb button:hover {
1873
+ color: var(--dsw-accent);
1874
+ }
1875
+ .pw-crumb-sep {
1876
+ margin: 0 4px;
1877
+ color: var(--dsw-label-caption);
1878
+ }
1879
+ .pw-viewer-notice {
1880
+ flex: none;
1881
+ padding: 4px 14px;
1882
+ font-size: 11.5px;
1883
+ color: var(--dsw-label-secondary);
1884
+ background: var(--dsw-hover);
1885
+ border-bottom: 0.5px solid var(--dsw-border-l1);
1886
+ }
1887
+ .pw-viewer-notice[data-kind="deleted"] {
1888
+ color: var(--dsw-danger);
1889
+ background: rgba(236, 19, 19, 0.08);
1890
+ }
1891
+ .pw-viewer-notice[data-kind="warn"] {
1892
+ color: var(--dsw-warn);
1893
+ }
1894
+ .pw-viewer .md pre {
1895
+ overflow-x: auto;
1896
+ }
1897
+
1898
+ /* 快速打开 */
1899
+ .pw-quick {
1900
+ position: absolute;
1901
+ inset: 0;
1902
+ z-index: 5;
1903
+ display: flex;
1904
+ justify-content: center;
1905
+ align-items: flex-start;
1906
+ padding-top: 56px;
1907
+ background: rgba(0, 0, 0, 0.08);
1908
+ }
1909
+ .pw-quick-box {
1910
+ width: min(560px, 90%);
1911
+ padding: 4px;
1912
+ border-radius: 14px;
1913
+ }
1914
+ .pw-quick-list {
1915
+ max-height: 50vh;
1916
+ overflow-y: auto;
1917
+ padding: 2px;
1918
+ }
1919
+ .pw-quick-item {
1920
+ display: flex;
1921
+ align-items: center;
1922
+ gap: 8px;
1923
+ width: 100%;
1924
+ height: 30px;
1925
+ padding: 0 8px;
1926
+ border-radius: 8px;
1927
+ font-size: 12.5px;
1928
+ color: var(--dsw-label-primary);
1929
+ text-align: left;
1930
+ }
1931
+ .pw-quick-item[data-active="true"] {
1932
+ background: var(--dsw-active);
1933
+ }
1934
+
1935
+ /* 整文件行内 diff */
1936
+ .pw-fdiff {
1937
+ font-family: var(--font-mono);
1938
+ font-size: 12px;
1939
+ line-height: 20px;
1940
+ }
1941
+ .pw-fdiff-row {
1942
+ position: absolute;
1943
+ left: 0;
1944
+ right: 0;
1945
+ height: 20px;
1946
+ display: flex;
1947
+ align-items: stretch;
1948
+ white-space: pre;
1949
+ color: var(--dsw-label-secondary);
1950
+ }
1951
+ .pw-fdiff-row[data-kind="add"] {
1952
+ background: rgba(34, 197, 94, 0.14);
1953
+ box-shadow: inset 2px 0 0 var(--dsw-success);
1954
+ }
1955
+ .pw-fdiff-row[data-kind="del"] {
1956
+ background: rgba(236, 19, 19, 0.12);
1957
+ box-shadow: inset 2px 0 0 var(--dsw-danger);
1958
+ }
1959
+ .pw-fdiff-gutter {
1960
+ flex: none;
1961
+ display: inline-flex;
1962
+ gap: 1ch;
1963
+ padding: 0 8px 0 10px;
1964
+ color: var(--dsw-label-caption);
1965
+ user-select: none;
1966
+ font-variant-numeric: tabular-nums;
1967
+ position: sticky;
1968
+ left: 0;
1969
+ background: inherit;
1970
+ }
1971
+ .pw-fdiff-gutter > span {
1972
+ display: inline-block;
1973
+ }
1974
+ .pw-fdiff-sign {
1975
+ flex: none;
1976
+ width: 1.5ch;
1977
+ user-select: none;
1978
+ color: var(--dsw-label-caption);
1979
+ }
1980
+ .pw-fdiff-row[data-kind="add"] .pw-fdiff-sign {
1981
+ color: var(--dsw-success);
1982
+ }
1983
+ .pw-fdiff-row[data-kind="del"] .pw-fdiff-sign {
1984
+ color: var(--dsw-danger);
1985
+ }
1986
+ .pw-fdiff-text {
1987
+ flex: 1;
1988
+ padding-right: 24px;
1989
+ background: transparent;
1990
+ }
1991
+ .pw-fdiff-fold {
1992
+ position: absolute;
1993
+ left: 0;
1994
+ right: 0;
1995
+ height: 20px;
1996
+ font-size: 11px;
1997
+ color: var(--dsw-label-caption);
1998
+ background: var(--dsw-hover);
1999
+ text-align: center;
2000
+ letter-spacing: 0.02em;
2001
+ }
2002
+ .pw-fdiff-fold:hover {
2003
+ color: var(--dsw-accent);
2004
+ }
2005
+ .pw-fdiff-ticks {
2006
+ position: absolute;
2007
+ top: 0;
2008
+ right: 2px;
2009
+ bottom: 0;
2010
+ width: 8px;
2011
+ pointer-events: none;
2012
+ }
2013
+ .pw-fdiff-tick {
2014
+ position: absolute;
2015
+ right: 0;
2016
+ width: 8px;
2017
+ height: 3px;
2018
+ border-radius: 1px;
2019
+ pointer-events: auto;
2020
+ cursor: pointer;
2021
+ background: var(--dsw-success);
2022
+ opacity: 0.6;
2023
+ }
2024
+ .pw-fdiff-tick[data-kind="del"] {
2025
+ background: var(--dsw-danger);
2026
+ }
2027
+ .pw-fdiff-tick[data-current] {
2028
+ opacity: 1;
2029
+ box-shadow: 0 0 0 1px var(--dsw-label-tertiary);
2030
+ }
2031
+
2032
+ /* 窄屏:查看器全屏 */
2033
+ @media (max-width: 840px) {
2034
+ .pw-viewer {
2035
+ width: 100vw;
2036
+ height: 100vh;
2037
+ border-radius: 0;
2038
+ }
2039
+ }