@rexvane/piweb 0.3.22 → 0.3.24

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 (251) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-path-routes-manifest.json +8 -7
  3. package/.next/build-manifest.json +3 -3
  4. package/.next/prerender-manifest.json +4 -4
  5. package/.next/react-loadable-manifest.json +11 -4
  6. package/.next/routes-manifest.json +8 -0
  7. package/.next/server/app/_global-error/page.js +2 -2
  8. package/.next/server/app/_global-error/page.js.nft.json +1 -1
  9. package/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  10. package/.next/server/app/_global-error.html +1 -1
  11. package/.next/server/app/_global-error.rsc +1 -1
  12. package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  13. package/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  14. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  15. package/.next/server/app/_not-found/page.js +1 -1
  16. package/.next/server/app/_not-found/page.js.nft.json +1 -1
  17. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  18. package/.next/server/app/_not-found.html +1 -1
  19. package/.next/server/app/_not-found.rsc +2 -2
  20. package/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  21. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
  22. package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  23. package/.next/server/app/api/agent/[id]/events/route.js +2 -2
  24. package/.next/server/app/api/agent/[id]/events/route.js.nft.json +1 -1
  25. package/.next/server/app/api/agent/[id]/route.js +1 -1
  26. package/.next/server/app/api/agent/[id]/route.js.nft.json +1 -1
  27. package/.next/server/app/api/agent/[id]/side-chat/route.js +5 -0
  28. package/.next/server/app/api/agent/[id]/side-chat/route.js.nft.json +1 -0
  29. package/.next/server/app/api/agent/[id]/side-chat/route_client-reference-manifest.js +1 -0
  30. package/.next/server/app/api/agent/[id]/tree/route.js +1 -1
  31. package/.next/server/app/api/agent/[id]/tree/route.js.nft.json +1 -1
  32. package/.next/server/app/api/agent/new/route.js +1 -1
  33. package/.next/server/app/api/agent/new/route.js.nft.json +1 -1
  34. package/.next/server/app/api/config/route.js +1 -1
  35. package/.next/server/app/api/config/route.js.nft.json +1 -1
  36. package/.next/server/app/api/files/route.js +1 -1
  37. package/.next/server/app/api/files/route.js.nft.json +1 -1
  38. package/.next/server/app/api/fs/route.js +1 -1
  39. package/.next/server/app/api/fs/route.js.nft.json +1 -1
  40. package/.next/server/app/api/git/route.js +2 -2
  41. package/.next/server/app/api/git/route.js.nft.json +1 -1
  42. package/.next/server/app/api/github/route.js +2 -2
  43. package/.next/server/app/api/github/route.js.nft.json +1 -1
  44. package/.next/server/app/api/growth/route.js +1 -1
  45. package/.next/server/app/api/growth/route.js.nft.json +1 -1
  46. package/.next/server/app/api/health/route.js +1 -1
  47. package/.next/server/app/api/health/route.js.nft.json +1 -1
  48. package/.next/server/app/api/models/defaults/route.js +1 -1
  49. package/.next/server/app/api/models/defaults/route.js.nft.json +1 -1
  50. package/.next/server/app/api/models/route.js +1 -1
  51. package/.next/server/app/api/models/route.js.nft.json +1 -1
  52. package/.next/server/app/api/pi-settings/route.js +1 -1
  53. package/.next/server/app/api/pi-settings/route.js.nft.json +1 -1
  54. package/.next/server/app/api/plugins/route.js +1 -1
  55. package/.next/server/app/api/plugins/route.js.nft.json +1 -1
  56. package/.next/server/app/api/prompts/route.js +1 -1
  57. package/.next/server/app/api/prompts/route.js.nft.json +1 -1
  58. package/.next/server/app/api/remote/route.js +3 -3
  59. package/.next/server/app/api/remote/route.js.nft.json +1 -1
  60. package/.next/server/app/api/security/route.js +1 -1
  61. package/.next/server/app/api/security/route.js.nft.json +1 -1
  62. package/.next/server/app/api/sessions/[id]/export/route.js +1 -1
  63. package/.next/server/app/api/sessions/[id]/export/route.js.nft.json +1 -1
  64. package/.next/server/app/api/sessions/[id]/route.js +1 -1
  65. package/.next/server/app/api/sessions/[id]/route.js.nft.json +1 -1
  66. package/.next/server/app/api/sessions/import/route.js +2 -2
  67. package/.next/server/app/api/sessions/import/route.js.nft.json +1 -1
  68. package/.next/server/app/api/sessions/route.js +1 -1
  69. package/.next/server/app/api/sessions/route.js.nft.json +1 -1
  70. package/.next/server/app/api/skills/route.js +2 -2
  71. package/.next/server/app/api/skills/route.js.nft.json +1 -1
  72. package/.next/server/app/api/update/route.js +2 -2
  73. package/.next/server/app/api/update/route.js.nft.json +1 -1
  74. package/.next/server/app/api/version/route.js +1 -1
  75. package/.next/server/app/api/version/route.js.nft.json +1 -1
  76. package/.next/server/app/api/web-auth/route.js +2 -2
  77. package/.next/server/app/api/web-auth/route.js.nft.json +1 -1
  78. package/.next/server/app/api/workspaces/route.js +1 -1
  79. package/.next/server/app/api/workspaces/route.js.nft.json +1 -1
  80. package/.next/server/app/icon.svg/route.js +1 -1
  81. package/.next/server/app/icon.svg/route.js.nft.json +1 -1
  82. package/.next/server/app/index.html +1 -1
  83. package/.next/server/app/index.rsc +7 -6
  84. package/.next/server/app/index.segments/__PAGE__.segment.rsc +7 -6
  85. package/.next/server/app/index.segments/_full.segment.rsc +7 -6
  86. package/.next/server/app/index.segments/_tree.segment.rsc +3 -2
  87. package/.next/server/app/login/page.js +1 -1
  88. package/.next/server/app/login/page.js.nft.json +1 -1
  89. package/.next/server/app/login/page_client-reference-manifest.js +1 -1
  90. package/.next/server/app/login.html +1 -1
  91. package/.next/server/app/login.rsc +3 -3
  92. package/.next/server/app/login.segments/_full.segment.rsc +3 -3
  93. package/.next/server/app/login.segments/_tree.segment.rsc +2 -2
  94. package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +3 -3
  95. package/.next/server/app/page.js +1 -1
  96. package/.next/server/app/page.js.nft.json +1 -1
  97. package/.next/server/app/page_client-reference-manifest.js +1 -1
  98. package/.next/server/app-paths-manifest.json +8 -7
  99. package/.next/server/chunks/{813.js → 1813.js} +1 -1
  100. package/.next/server/chunks/{430.js → 2430.js} +1 -1
  101. package/.next/server/chunks/{970.js → 2970.js} +1 -1
  102. package/.next/server/chunks/3421.js +1 -0
  103. package/.next/server/chunks/3924.js +6 -0
  104. package/.next/server/chunks/4807.js +1 -0
  105. package/.next/server/chunks/5393.js +1 -0
  106. package/.next/server/chunks/5802.js +2 -0
  107. package/.next/server/chunks/6229.js +1 -0
  108. package/.next/server/chunks/7496.js +1 -0
  109. package/.next/server/chunks/7662.js +2 -0
  110. package/.next/server/chunks/8686.js +1 -0
  111. package/.next/server/chunks/{593.js → 974.js} +1 -1
  112. package/.next/server/chunks/{920.js → 9920.js} +1 -1
  113. package/.next/server/functions-config-manifest.json +2 -1
  114. package/.next/server/instrumentation.js +1 -1
  115. package/.next/server/instrumentation.js.nft.json +1 -1
  116. package/.next/server/middleware-build-manifest.js +1 -1
  117. package/.next/server/middleware-react-loadable-manifest.js +1 -1
  118. package/.next/server/middleware.js +1 -1
  119. package/.next/server/pages/404.html +1 -1
  120. package/.next/server/pages/500.html +1 -1
  121. package/.next/server/preview-props.json +3 -3
  122. package/.next/server/server-reference-manifest.json +1 -1
  123. package/.next/server/webpack-runtime.js +1 -1
  124. package/.next/static/chunks/2716.44fdf1b21454b961.js +1 -0
  125. package/.next/static/chunks/4673.e261707dce391be7.js +1 -0
  126. package/.next/static/chunks/4686-0cd87513f9ea3538.js +1 -0
  127. package/.next/static/chunks/7411.5f79671208209b13.js +1 -0
  128. package/.next/static/chunks/app/_global-error/page-cbaaee0d7aacb85a.js +1 -0
  129. package/.next/static/chunks/app/api/agent/[id]/events/route-cbaaee0d7aacb85a.js +1 -0
  130. package/.next/static/chunks/app/api/agent/[id]/route-cbaaee0d7aacb85a.js +1 -0
  131. package/.next/static/chunks/app/api/agent/[id]/side-chat/route-cbaaee0d7aacb85a.js +1 -0
  132. package/.next/static/chunks/app/api/agent/[id]/tree/route-cbaaee0d7aacb85a.js +1 -0
  133. package/.next/static/chunks/app/api/agent/new/route-cbaaee0d7aacb85a.js +1 -0
  134. package/.next/static/chunks/app/api/config/route-cbaaee0d7aacb85a.js +1 -0
  135. package/.next/static/chunks/app/api/files/route-cbaaee0d7aacb85a.js +1 -0
  136. package/.next/static/chunks/app/api/fs/route-cbaaee0d7aacb85a.js +1 -0
  137. package/.next/static/chunks/app/api/git/route-cbaaee0d7aacb85a.js +1 -0
  138. package/.next/static/chunks/app/api/github/route-cbaaee0d7aacb85a.js +1 -0
  139. package/.next/static/chunks/app/api/growth/route-cbaaee0d7aacb85a.js +1 -0
  140. package/.next/static/chunks/app/api/health/route-cbaaee0d7aacb85a.js +1 -0
  141. package/.next/static/chunks/app/api/models/defaults/route-cbaaee0d7aacb85a.js +1 -0
  142. package/.next/static/chunks/app/api/models/route-cbaaee0d7aacb85a.js +1 -0
  143. package/.next/static/chunks/app/api/pi-settings/route-cbaaee0d7aacb85a.js +1 -0
  144. package/.next/static/chunks/app/api/plugins/route-cbaaee0d7aacb85a.js +1 -0
  145. package/.next/static/chunks/app/api/prompts/route-cbaaee0d7aacb85a.js +1 -0
  146. package/.next/static/chunks/app/api/remote/route-cbaaee0d7aacb85a.js +1 -0
  147. package/.next/static/chunks/app/api/security/route-cbaaee0d7aacb85a.js +1 -0
  148. package/.next/static/chunks/app/api/sessions/[id]/export/route-cbaaee0d7aacb85a.js +1 -0
  149. package/.next/static/chunks/app/api/sessions/[id]/route-cbaaee0d7aacb85a.js +1 -0
  150. package/.next/static/chunks/app/api/sessions/import/route-cbaaee0d7aacb85a.js +1 -0
  151. package/.next/static/chunks/app/api/sessions/route-cbaaee0d7aacb85a.js +1 -0
  152. package/.next/static/chunks/app/api/skills/route-cbaaee0d7aacb85a.js +1 -0
  153. package/.next/static/chunks/app/api/update/route-cbaaee0d7aacb85a.js +1 -0
  154. package/.next/static/chunks/app/api/version/route-cbaaee0d7aacb85a.js +1 -0
  155. package/.next/static/chunks/app/api/web-auth/route-cbaaee0d7aacb85a.js +1 -0
  156. package/.next/static/chunks/app/api/workspaces/route-cbaaee0d7aacb85a.js +1 -0
  157. package/.next/static/chunks/app/page-dc3cb41d91c7432e.js +1 -0
  158. package/.next/static/chunks/next/dist/client/components/builtin/app-error-cbaaee0d7aacb85a.js +1 -0
  159. package/.next/static/chunks/next/dist/client/components/builtin/forbidden-cbaaee0d7aacb85a.js +1 -0
  160. package/.next/static/chunks/next/dist/client/components/builtin/not-found-cbaaee0d7aacb85a.js +1 -0
  161. package/.next/static/chunks/next/dist/client/components/builtin/unauthorized-cbaaee0d7aacb85a.js +1 -0
  162. package/.next/static/chunks/webpack-2ac3d76b81895f5b.js +1 -0
  163. package/.next/static/css/9fc559c2c4ad1d0f.css +1 -0
  164. package/.next/static/css/c6e2227c36ec2fd6.css +1 -0
  165. package/.next/types/app/api/agent/[id]/side-chat/route.ts +355 -0
  166. package/.next/types/routes.d.ts +2 -1
  167. package/.next/types/validator.ts +10 -0
  168. package/next.config.ts +2 -0
  169. package/package.json +9 -3
  170. package/scripts/release.mjs +3 -7
  171. package/scripts/runtime/check-installed.mjs +66 -0
  172. package/scripts/runtime/pi-packages.mjs +52 -0
  173. package/scripts/verify-package.mjs +29 -7
  174. package/src/app/api/agent/[id]/side-chat/route.ts +77 -0
  175. package/src/app/globals.css +1576 -14
  176. package/src/components/AppShell.tsx +63 -13
  177. package/src/components/ChatInput.tsx +33 -29
  178. package/src/components/ChatWindow.tsx +6 -7
  179. package/src/components/ContextMeter.tsx +35 -16
  180. package/src/components/DrawerPanel.tsx +1 -1
  181. package/src/components/FileViewer.tsx +89 -8
  182. package/src/components/GrowthTree.tsx +30 -5
  183. package/src/components/ModelSelector.tsx +21 -5
  184. package/src/components/SettingsPanel.tsx +25 -16
  185. package/src/components/chat/reading-anchor.ts +81 -0
  186. package/src/components/composer/ComposerImages.tsx +31 -11
  187. package/src/components/side-chat/SideChatPanel.module.css +131 -0
  188. package/src/components/side-chat/SideChatPanel.tsx +189 -0
  189. package/src/components/side-chat/icons.tsx +8 -0
  190. package/src/components/side-chat/request-history.ts +29 -0
  191. package/src/components/side-chat/store.ts +248 -0
  192. package/src/hooks/useFileViewer.ts +6 -4
  193. package/src/i18n.tsx +50 -8
  194. package/src/lib/files-service.ts +66 -2
  195. package/src/lib/path-security.ts +24 -32
  196. package/src/lib/session-reader.ts +1 -1
  197. package/src/lib/side-chat/context.ts +123 -0
  198. package/src/lib/side-chat/service.ts +191 -0
  199. package/src/lib/side-chat/types.ts +61 -0
  200. package/src/lib/types.ts +1 -1
  201. package/src/lib/update-service.ts +4 -6
  202. package/.next/server/chunks/229.js +0 -1
  203. package/.next/server/chunks/393.js +0 -1
  204. package/.next/server/chunks/421.js +0 -1
  205. package/.next/server/chunks/496.js +0 -1
  206. package/.next/server/chunks/662.js +0 -2
  207. package/.next/server/chunks/686.js +0 -1
  208. package/.next/server/chunks/802.js +0 -2
  209. package/.next/server/chunks/807.js +0 -1
  210. package/.next/server/chunks/924.js +0 -6
  211. package/.next/static/chunks/2716.7ad073038e94a802.js +0 -1
  212. package/.next/static/chunks/4673.4cf66cbdd8364c57.js +0 -1
  213. package/.next/static/chunks/4686-09fcd0028079006c.js +0 -1
  214. package/.next/static/chunks/7411.67366dc5032a141d.js +0 -1
  215. package/.next/static/chunks/app/_global-error/page-f977af7f858990a2.js +0 -1
  216. package/.next/static/chunks/app/api/agent/[id]/events/route-f977af7f858990a2.js +0 -1
  217. package/.next/static/chunks/app/api/agent/[id]/route-f977af7f858990a2.js +0 -1
  218. package/.next/static/chunks/app/api/agent/[id]/tree/route-f977af7f858990a2.js +0 -1
  219. package/.next/static/chunks/app/api/agent/new/route-f977af7f858990a2.js +0 -1
  220. package/.next/static/chunks/app/api/config/route-f977af7f858990a2.js +0 -1
  221. package/.next/static/chunks/app/api/files/route-f977af7f858990a2.js +0 -1
  222. package/.next/static/chunks/app/api/fs/route-f977af7f858990a2.js +0 -1
  223. package/.next/static/chunks/app/api/git/route-f977af7f858990a2.js +0 -1
  224. package/.next/static/chunks/app/api/github/route-f977af7f858990a2.js +0 -1
  225. package/.next/static/chunks/app/api/growth/route-f977af7f858990a2.js +0 -1
  226. package/.next/static/chunks/app/api/health/route-f977af7f858990a2.js +0 -1
  227. package/.next/static/chunks/app/api/models/defaults/route-f977af7f858990a2.js +0 -1
  228. package/.next/static/chunks/app/api/models/route-f977af7f858990a2.js +0 -1
  229. package/.next/static/chunks/app/api/pi-settings/route-f977af7f858990a2.js +0 -1
  230. package/.next/static/chunks/app/api/plugins/route-f977af7f858990a2.js +0 -1
  231. package/.next/static/chunks/app/api/prompts/route-f977af7f858990a2.js +0 -1
  232. package/.next/static/chunks/app/api/remote/route-f977af7f858990a2.js +0 -1
  233. package/.next/static/chunks/app/api/security/route-f977af7f858990a2.js +0 -1
  234. package/.next/static/chunks/app/api/sessions/[id]/export/route-f977af7f858990a2.js +0 -1
  235. package/.next/static/chunks/app/api/sessions/[id]/route-f977af7f858990a2.js +0 -1
  236. package/.next/static/chunks/app/api/sessions/import/route-f977af7f858990a2.js +0 -1
  237. package/.next/static/chunks/app/api/sessions/route-f977af7f858990a2.js +0 -1
  238. package/.next/static/chunks/app/api/skills/route-f977af7f858990a2.js +0 -1
  239. package/.next/static/chunks/app/api/update/route-f977af7f858990a2.js +0 -1
  240. package/.next/static/chunks/app/api/version/route-f977af7f858990a2.js +0 -1
  241. package/.next/static/chunks/app/api/web-auth/route-f977af7f858990a2.js +0 -1
  242. package/.next/static/chunks/app/api/workspaces/route-f977af7f858990a2.js +0 -1
  243. package/.next/static/chunks/app/page-fc4ed2ff29b6235e.js +0 -1
  244. package/.next/static/chunks/next/dist/client/components/builtin/app-error-f977af7f858990a2.js +0 -1
  245. package/.next/static/chunks/next/dist/client/components/builtin/forbidden-f977af7f858990a2.js +0 -1
  246. package/.next/static/chunks/next/dist/client/components/builtin/not-found-f977af7f858990a2.js +0 -1
  247. package/.next/static/chunks/next/dist/client/components/builtin/unauthorized-f977af7f858990a2.js +0 -1
  248. package/.next/static/chunks/webpack-22ebffc20adb44ae.js +0 -1
  249. package/.next/static/css/6671d0d1589fdc0e.css +0 -1
  250. /package/.next/static/{WMazYvD-gbeLsCUfUxvvM → lvKCJmjFj8LuqSojRVLRF}/_buildManifest.js +0 -0
  251. /package/.next/static/{WMazYvD-gbeLsCUfUxvvM → lvKCJmjFj8LuqSojRVLRF}/_ssgManifest.js +0 -0
@@ -1712,7 +1712,1562 @@ body[data-pebrel-theme="pebrel"][data-ds-dark-theme] {
1712
1712
  pointer-events: none;
1713
1713
  }
1714
1714
 
1715
- /* 输入卡待发送图片:平铺缩略图 / 牌堆 / 扇形(src/components/composer/ComposerImages.tsx) */
1715
+ @media (prefers-reduced-motion: reduce) {
1716
+ * {
1717
+ transition: none !important;
1718
+ animation: none !important;
1719
+ }
1720
+ }
1721
+
1722
+ .piweb-conversation-width-handle {
1723
+ position: absolute;
1724
+ top: 0;
1725
+ bottom: 0;
1726
+ z-index: 3;
1727
+ width: 12px;
1728
+ cursor: col-resize;
1729
+ touch-action: none;
1730
+ }
1731
+ .piweb-conversation-width-handle[data-side="left"] {
1732
+ left: calc(50% - var(--dsh-chat-content-width) / 2 - 20px);
1733
+ }
1734
+ .piweb-conversation-width-handle[data-side="right"] {
1735
+ right: calc(50% - var(--dsh-chat-content-width) / 2 - 20px);
1736
+ }
1737
+ .piweb-conversation-width-handle::after {
1738
+ content: "";
1739
+ position: absolute;
1740
+ /* 常显的中间一小段:整条全高竖线会读成边框/分隔线,短抓手才读成"可拖"。
1741
+ 热区仍是 12px 全高(cursor: col-resize),手感不受影响。 */
1742
+ top: 35%;
1743
+ bottom: 35%;
1744
+ left: 5px;
1745
+ width: 2px;
1746
+ border-radius: 2px;
1747
+ background: var(--dsw-border-l3);
1748
+ opacity: 0.3;
1749
+ transition: opacity var(--ds-duration-fast);
1750
+ }
1751
+ .piweb-conversation-width-handle:hover::after,
1752
+ .piweb-conversation-width-handle[data-dragging]::after,
1753
+ .piweb-conversation-width-handle:focus-visible::after {
1754
+ opacity: 1;
1755
+ }
1756
+
1757
+ @media (max-width: 840px) {
1758
+ :root {
1759
+ --dsh-chat-content-width: 100%;
1760
+ --dsh-composer-card-max-width: 100%;
1761
+ }
1762
+ .piweb-conversation-width-handle {
1763
+ display: none;
1764
+ }
1765
+
1766
+ .pi-main > .hairline-b {
1767
+ padding-left: 56px;
1768
+ padding-right: 12px;
1769
+ }
1770
+
1771
+ .settings-dialog {
1772
+ width: calc(100vw - 16px) !important;
1773
+ max-width: none !important;
1774
+ height: calc(100vh - 16px) !important;
1775
+ flex-direction: column;
1776
+ border-radius: 22px !important;
1777
+ }
1778
+
1779
+ .settings-nav {
1780
+ width: 100% !important;
1781
+ flex-direction: row !important;
1782
+ overflow-x: auto;
1783
+ padding: 10px !important;
1784
+ border-bottom: 0.5px solid var(--dsw-border-l2);
1785
+ }
1786
+
1787
+ .settings-nav > button {
1788
+ flex: none;
1789
+ height: 36px;
1790
+ }
1791
+
1792
+ .settings-title {
1793
+ display: none;
1794
+ }
1795
+ }
1796
+
1797
+ /* 滚动条 */
1798
+ ::-webkit-scrollbar {
1799
+ width: 10px;
1800
+ height: 10px;
1801
+ }
1802
+ ::-webkit-scrollbar-thumb {
1803
+ background: var(--dsw-active);
1804
+ border-radius: 8px;
1805
+ border: 2.5px solid transparent;
1806
+ background-clip: content-box;
1807
+ }
1808
+ ::-webkit-scrollbar-thumb:hover {
1809
+ background: var(--dsw-border-l3);
1810
+ border: 2px solid transparent;
1811
+ background-clip: content-box;
1812
+ }
1813
+ ::-webkit-scrollbar-track {
1814
+ background: transparent;
1815
+ }
1816
+
1817
+ /* ============================================================
1818
+ 通用组件样式
1819
+ ============================================================ */
1820
+
1821
+ .icon-btn {
1822
+ display: inline-flex;
1823
+ align-items: center;
1824
+ justify-content: center;
1825
+ width: 28px;
1826
+ height: 28px;
1827
+ border-radius: 8px;
1828
+ color: var(--dsw-label-secondary);
1829
+ transition: background var(--ds-duration-fast) var(--ds-ease-in-out), color var(--ds-duration-fast)
1830
+ var(--ds-ease-in-out);
1831
+ }
1832
+ .icon-btn:hover {
1833
+ background: var(--dsw-hover);
1834
+ color: var(--dsw-label-primary);
1835
+ }
1836
+
1837
+ .chip {
1838
+ display: inline-flex;
1839
+ align-items: center;
1840
+ gap: 5px;
1841
+ height: 28px;
1842
+ padding: 0 10px;
1843
+ border-radius: 24px;
1844
+ font-size: 13px;
1845
+ line-height: 20px;
1846
+ font-weight: 500;
1847
+ color: var(--dsw-label-primary);
1848
+ white-space: nowrap;
1849
+ transition: background var(--ds-duration-fast) var(--ds-ease-in-out), color var(--ds-duration-fast)
1850
+ var(--ds-ease-in-out);
1851
+ }
1852
+ .chip:hover {
1853
+ background: var(--dsw-hover);
1854
+ color: var(--dsw-label-primary);
1855
+ }
1856
+ .chip .chevron {
1857
+ color: var(--dsw-label-caption);
1858
+ transition: transform 120ms var(--ds-ease-in-out);
1859
+ }
1860
+ .chip[data-open="true"] .chevron {
1861
+ transform: rotate(180deg);
1862
+ }
1863
+
1864
+ /* Hero 专属工作区 / 预设芯片(对齐 dsh .workspace:透明底、label-primary 纯白高亮、无外框胶囊) */
1865
+ .hero-chip {
1866
+ display: inline-flex;
1867
+ align-items: center;
1868
+ gap: 6px;
1869
+ height: 28px;
1870
+ padding: 0 8px;
1871
+ border-radius: 14px;
1872
+ background: transparent;
1873
+ color: var(--dsw-label-primary);
1874
+ font-size: 13px;
1875
+ line-height: 20px;
1876
+ font-weight: 500;
1877
+ white-space: nowrap;
1878
+ cursor: pointer;
1879
+ transition: background var(--ds-duration-fast) var(--ds-ease-in-out);
1880
+ }
1881
+ .hero-chip:hover,
1882
+ .hero-chip[data-open="true"] {
1883
+ background: var(--dsw-hover);
1884
+ }
1885
+ .hero-chip .hero-chip-icon {
1886
+ flex: none;
1887
+ color: var(--dsw-label-primary);
1888
+ }
1889
+ .hero-chip .chevron {
1890
+ flex: none;
1891
+ color: var(--dsw-label-caption);
1892
+ transition: transform 120ms var(--ds-ease-in-out);
1893
+ }
1894
+ .hero-chip[data-open="true"] .chevron {
1895
+ transform: rotate(180deg);
1896
+ }
1897
+
1898
+ /* 描边按钮(dsh Button.outline:胶囊 r18、透明底、0.5px 边) */
1899
+ .btn-outline {
1900
+ display: inline-flex;
1901
+ align-items: center;
1902
+ justify-content: center;
1903
+ gap: 6px;
1904
+ height: 36px;
1905
+ padding: 0 14px;
1906
+ border-radius: 18px;
1907
+ border: 0.5px solid var(--dsw-border-l3);
1908
+ background: transparent;
1909
+ color: var(--dsw-label-primary);
1910
+ font-size: 14px;
1911
+ line-height: 22px;
1912
+ transition: background var(--ds-duration-fast) var(--ds-ease-in-out);
1913
+ }
1914
+ .btn-outline:hover {
1915
+ background: var(--dsw-hover);
1916
+ }
1917
+
1918
+ /* 主操作实心按钮(表单保存/确认):前景色填充。名称沿用既有调用点。 */
1919
+ .btn-primary-white {
1920
+ display: inline-flex;
1921
+ align-items: center;
1922
+ justify-content: center;
1923
+ gap: 6px;
1924
+ height: 36px;
1925
+ padding: 0 14px;
1926
+ border-radius: 18px;
1927
+ background: var(--dsw-label-primary);
1928
+ color: var(--dsw-bg-base);
1929
+ font-size: 14px;
1930
+ font-weight: 500;
1931
+ line-height: 22px;
1932
+ transition: opacity var(--ds-duration-fast) var(--ds-ease-in-out);
1933
+ }
1934
+ .btn-primary-white:disabled {
1935
+ opacity: 0.5;
1936
+ cursor: default;
1937
+ }
1938
+
1939
+ /* 侧栏「新会话」(dsh .newSession:h38 r12 elevated 底) */
1940
+ .btn-new-session {
1941
+ display: inline-flex;
1942
+ align-items: center;
1943
+ justify-content: center;
1944
+ gap: 6px;
1945
+ height: 38px;
1946
+ padding: 8px 16px;
1947
+ border-radius: 12px;
1948
+ border: 0.5px solid var(--dsw-border-l3);
1949
+ background: var(--dsw-btn-elevated);
1950
+ color: var(--dsw-label-primary);
1951
+ font-size: 14px;
1952
+ font-weight: 500;
1953
+ line-height: 22px;
1954
+ transition: background var(--ds-duration-fast) var(--ds-ease-in-out);
1955
+ }
1956
+ .btn-new-session:hover {
1957
+ background: var(--dsw-btn-floating-hover);
1958
+ }
1959
+
1960
+ /* 设置行右侧下选芯片(dsh「标准模式 ⌄」:胶囊) */
1961
+ .select-chip {
1962
+ display: inline-flex;
1963
+ align-items: center;
1964
+ gap: 6px;
1965
+ height: 32px;
1966
+ padding: 0 12px;
1967
+ border-radius: 16px;
1968
+ border: 0.5px solid var(--dsw-border-l2);
1969
+ font-size: 13px;
1970
+ color: var(--dsw-label-primary);
1971
+ transition: background var(--ds-duration-fast) var(--ds-ease-in-out);
1972
+ }
1973
+ .select-chip:hover {
1974
+ background: var(--dsw-hover);
1975
+ }
1976
+
1977
+ /* 页签(dsh:蓝色文字 + 蓝色下划线) */
1978
+ .tab-underline {
1979
+ position: relative;
1980
+ padding: 6px 2px;
1981
+ font-size: 13.5px;
1982
+ color: var(--dsw-label-tertiary);
1983
+ transition: color var(--ds-duration-fast) var(--ds-ease-in-out);
1984
+ }
1985
+ .tab-underline:hover {
1986
+ color: var(--dsw-label-primary);
1987
+ }
1988
+ .tab-underline[data-active="true"] {
1989
+ color: var(--dsw-accent);
1990
+ font-weight: 600;
1991
+ }
1992
+ .tab-underline::after {
1993
+ content: "";
1994
+ position: absolute;
1995
+ left: 0;
1996
+ right: 0;
1997
+ bottom: -1px;
1998
+ height: 2px;
1999
+ border-radius: 2px;
2000
+ background: transparent;
2001
+ }
2002
+ .tab-underline[data-active="true"]::after {
2003
+ background: var(--dsw-accent);
2004
+ }
2005
+
2006
+ .settings-tab-underline {
2007
+ position: relative;
2008
+ padding: 6px 2px 10px;
2009
+ font-size: 13.5px;
2010
+ color: var(--dsw-label-tertiary);
2011
+ transition: color var(--ds-duration-fast) var(--ds-ease-in-out);
2012
+ }
2013
+ .settings-tab-underline:hover {
2014
+ color: var(--dsw-label-primary);
2015
+ }
2016
+ .settings-tab-underline[data-active="true"] {
2017
+ color: var(--dsw-label-primary);
2018
+ font-weight: 500;
2019
+ }
2020
+ .settings-tab-underline::after {
2021
+ content: "";
2022
+ position: absolute;
2023
+ left: 0;
2024
+ right: 0;
2025
+ bottom: -1px;
2026
+ height: 2px;
2027
+ border-radius: 2px;
2028
+ background: transparent;
2029
+ }
2030
+ .settings-tab-underline[data-active="true"]::after {
2031
+ background: var(--dsw-label-primary);
2032
+ }
2033
+ /* 应用外壳占满「实际可见」的高度。100vh 在手机浏览器里是工具栏收起时的大视口:
2034
+ 地址栏在底部的浏览器(如手机 Edge)里,最下面的输入框正好被工具栏盖住、页面又不滚动,
2035
+ 看起来就是没有输入框。dvh 是实际可见高度,不认它的老浏览器退回 100vh。
2036
+ 兜底必须放进 @supports:写成两行 height,构建时的 CSS 压缩会只留后一行,老浏览器就没了高度。 */
2037
+ .pw-app-shell {
2038
+ height: 100vh;
2039
+ }
2040
+ @supports (height: 100dvh) {
2041
+ .pw-app-shell {
2042
+ height: 100dvh;
2043
+ }
2044
+ }
2045
+ /* 右侧抽屉的入口条:未选中项悬停给底色(设置页的同款下划线 tab 没有底色) */
2046
+ .drawer-tab:hover:not([data-active="true"]) {
2047
+ background: var(--dsw-hover);
2048
+ }
2049
+
2050
+ .btn-primary-circle {
2051
+ display: inline-flex;
2052
+ align-items: center;
2053
+ justify-content: center;
2054
+ width: 34px;
2055
+ height: 34px;
2056
+ border-radius: 999px;
2057
+ background: var(--dsw-accent);
2058
+ color: #fff;
2059
+ transform: translateY(-2px);
2060
+ flex: none;
2061
+ margin-top: -3px;
2062
+ margin-bottom: -3px;
2063
+ transition: opacity var(--ds-duration-fast) var(--ds-ease-in-out), transform var(--ds-duration-fast)
2064
+ var(--ds-ease-in-out);
2065
+ }
2066
+ .btn-primary-circle:disabled {
2067
+ opacity: 0.4;
2068
+ cursor: default;
2069
+ }
2070
+ /* 运行中有草稿时的幽灵停止钮(发送钮左侧),悬停变警示色 */
2071
+ .btn-ghost-circle {
2072
+ display: inline-flex;
2073
+ align-items: center;
2074
+ justify-content: center;
2075
+ width: 30px;
2076
+ height: 30px;
2077
+ border-radius: 999px;
2078
+ color: var(--dsw-label-secondary);
2079
+ border: 0.5px solid var(--dsw-border-l2);
2080
+ background: transparent;
2081
+ transform: translateY(-2px);
2082
+ flex: none;
2083
+ margin-top: -3px;
2084
+ margin-bottom: -3px;
2085
+ }
2086
+ .btn-ghost-circle:hover {
2087
+ color: var(--dsw-danger);
2088
+ border-color: var(--dsw-danger);
2089
+ }
2090
+
2091
+ /* 排队中的消息:输入卡上方一列(Claude Code 的 queued messages 位置) */
2092
+ .pw-queue {
2093
+ display: flex;
2094
+ flex-direction: column;
2095
+ gap: 3px;
2096
+ margin: 0 14px 8px;
2097
+ font-size: 12.5px;
2098
+ }
2099
+ .pw-queue-row {
2100
+ display: flex;
2101
+ align-items: center;
2102
+ gap: 8px;
2103
+ min-width: 0;
2104
+ color: var(--dsw-label-secondary);
2105
+ }
2106
+ .pw-queue-tag {
2107
+ flex: none;
2108
+ font-size: 10.5px;
2109
+ line-height: 16px;
2110
+ padding: 0 6px;
2111
+ border-radius: 4px;
2112
+ text-transform: capitalize;
2113
+ color: var(--dsw-label-tertiary);
2114
+ border: 0.5px solid var(--dsw-border-l2);
2115
+ }
2116
+ .pw-queue-text {
2117
+ min-width: 0;
2118
+ overflow: hidden;
2119
+ text-overflow: ellipsis;
2120
+ white-space: nowrap;
2121
+ }
2122
+ .pw-queue-foot {
2123
+ display: flex;
2124
+ gap: 12px;
2125
+ margin-top: 1px;
2126
+ padding-left: 2px;
2127
+ font-size: 11.5px;
2128
+ color: var(--dsw-label-caption);
2129
+ }
2130
+ .pw-queue-foot button:hover {
2131
+ color: var(--dsw-label-secondary);
2132
+ }
2133
+ /* 运行中输入卡下方的按键提示 */
2134
+ .pw-busy-hint {
2135
+ margin: 6px 14px 0;
2136
+ font-size: 11.5px;
2137
+ line-height: 16px;
2138
+ color: var(--dsw-label-caption);
2139
+ }
2140
+
2141
+ .hairline-t {
2142
+ border-top: 0.5px solid var(--dsw-border-l2);
2143
+ }
2144
+ .hairline-b {
2145
+ border-bottom: 0.5px solid var(--dsw-border-l2);
2146
+ }
2147
+ .hairline-r {
2148
+ border-right: 0.5px solid var(--dsw-border-l2);
2149
+ }
2150
+
2151
+ /* 侧栏收起导轨按钮(dsh rail:36×36 控件盒、12px 圆角) */
2152
+ .rail-btn {
2153
+ display: inline-flex;
2154
+ align-items: center;
2155
+ justify-content: center;
2156
+ width: 36px;
2157
+ height: 36px;
2158
+ border-radius: 12px;
2159
+ color: var(--dsw-label-secondary);
2160
+ transition: background var(--ds-duration-fast) var(--ds-ease-in-out), color var(--ds-duration-fast)
2161
+ var(--ds-ease-in-out);
2162
+ }
2163
+ .rail-btn:hover {
2164
+ background: var(--dsw-hover);
2165
+ color: var(--dsw-label-primary);
2166
+ }
2167
+
2168
+ /* 状态点(对齐 dsh StateDot) */
2169
+ .state-dot {
2170
+ position: relative;
2171
+ width: 8px;
2172
+ height: 8px;
2173
+ border-radius: 999px;
2174
+ flex: none;
2175
+ }
2176
+ .state-dot.running {
2177
+ background: var(--dsw-deepseek-450);
2178
+ animation: dot-breathe 1s ease-in-out infinite;
2179
+ }
2180
+ .state-dot.pending {
2181
+ background: var(--dsw-warn);
2182
+ box-shadow: 0 0 0 3px rgba(245, 158, 11, 0.1);
2183
+ }
2184
+ .state-dot.done {
2185
+ background: var(--dsw-success);
2186
+ }
2187
+ @keyframes dot-breathe {
2188
+ 0%,
2189
+ 100% {
2190
+ opacity: 1;
2191
+ }
2192
+ 50% {
2193
+ opacity: 0.45;
2194
+ }
2195
+ }
2196
+
2197
+ /* 下拉/浮层(玻璃态:半透明层色 + backdrop blur + 发丝线) */
2198
+ .popover {
2199
+ background: var(--dsw-glass-popover);
2200
+ padding: 6px;
2201
+ border-radius: 16px;
2202
+ box-shadow: var(--dsw-elevation-prominent);
2203
+ border: 0.5px solid var(--dsw-border-l1);
2204
+ overflow: hidden;
2205
+ }
2206
+
2207
+ /* 居中遮罩层(dsh Modal.mask:遮罩色 + blur) */
2208
+ .modal-mask {
2209
+ background: var(--dsw-mask);
2210
+ backdrop-filter: var(--dsw-mask-blur);
2211
+ -webkit-backdrop-filter: var(--dsw-mask-blur);
2212
+ }
2213
+
2214
+ /* 玻璃卡(设置弹窗) */
2215
+ .glass-modal {
2216
+ background: var(--dsw-glass-modal);
2217
+ }
2218
+
2219
+ /* markdown 内容(字号独立可调:对话字体设置驱动,缺省跟界面字体) */
2220
+ .md {
2221
+ min-width: 0;
2222
+ overflow-wrap: break-word;
2223
+ font-size: var(--piweb-chat-font-size);
2224
+ line-height: 1.65;
2225
+ }
2226
+ .md > *:first-child {
2227
+ margin-top: 0;
2228
+ }
2229
+ .md > *:last-child {
2230
+ margin-bottom: 0;
2231
+ }
2232
+ .md p {
2233
+ margin: 0.5em 0;
2234
+ }
2235
+ .md h1,
2236
+ .md h2,
2237
+ .md h3,
2238
+ .md h4 {
2239
+ margin: 1em 0 0.4em;
2240
+ font-weight: 600;
2241
+ line-height: 1.35;
2242
+ }
2243
+ .md h1 {
2244
+ font-size: 1.35em;
2245
+ }
2246
+ .md h2 {
2247
+ font-size: 1.22em;
2248
+ }
2249
+ .md h3 {
2250
+ font-size: 1.1em;
2251
+ }
2252
+ .md ul,
2253
+ .md ol {
2254
+ margin: 0.5em 0;
2255
+ padding-left: 1.5em;
2256
+ }
2257
+ .md li {
2258
+ margin: 0.2em 0;
2259
+ }
2260
+ .md a {
2261
+ color: var(--dsw-accent);
2262
+ text-decoration: none;
2263
+ }
2264
+ .md a:hover {
2265
+ text-decoration: underline;
2266
+ }
2267
+ .md blockquote {
2268
+ margin: 0.6em 0;
2269
+ padding: 0.1em 0 0.1em 0.9em;
2270
+ border-left: 3px solid var(--dsw-border-l3);
2271
+ color: var(--dsw-label-secondary);
2272
+ }
2273
+ .md code {
2274
+ font-family: var(--font-mono);
2275
+ font-size: 0.9em;
2276
+ background: var(--dsw-selector);
2277
+ border-radius: 5px;
2278
+ padding: 0.1em 0.35em;
2279
+ }
2280
+ .md pre {
2281
+ margin: 0.7em 0;
2282
+ padding: 12px 14px;
2283
+ border-radius: 12px;
2284
+ background: var(--dsw-selector);
2285
+ overflow-x: auto;
2286
+ border: 0.5px solid var(--dsw-border-l1);
2287
+ }
2288
+ .md pre code {
2289
+ background: none;
2290
+ padding: 0;
2291
+ font-size: 13px;
2292
+ line-height: 1.55;
2293
+ }
2294
+ .md-code-block {
2295
+ position: relative;
2296
+ }
2297
+ .md-code-copy {
2298
+ position: absolute;
2299
+ top: 12px;
2300
+ right: 12px;
2301
+ z-index: 1;
2302
+ }
2303
+ .md-code-block pre {
2304
+ padding-top: 40px;
2305
+ }
2306
+ .md table {
2307
+ border-collapse: collapse;
2308
+ margin: 0.7em 0;
2309
+ width: 100%;
2310
+ font-size: 0.95em;
2311
+ }
2312
+ .md th,
2313
+ .md td {
2314
+ border: 0.5px solid var(--dsw-border-l2);
2315
+ padding: 5px 10px;
2316
+ text-align: left;
2317
+ }
2318
+ .md th {
2319
+ background: var(--dsw-hover);
2320
+ }
2321
+ .md hr {
2322
+ border: none;
2323
+ border-top: 0.5px solid var(--dsw-border-l2);
2324
+ margin: 1em 0;
2325
+ }
2326
+
2327
+ /* ---------- 流式正文:稳定块 + 未闭合代码围栏的纯文本尾巴共用一个 .md 容器 ---------- */
2328
+ .pw-stream {
2329
+ display: flow-root;
2330
+ }
2331
+ /* 打字光标模式下尾巴外面包了一层:包层不能改变原有排版,
2332
+ .md > *:first-child/:last-child 的边距归零要透传到最后那个内容元素上 */
2333
+ .pw-stream > .pw-stream-tail:first-child > :first-child {
2334
+ margin-top: 0;
2335
+ }
2336
+ .pw-stream > .pw-stream-tail:last-child > :last-child {
2337
+ margin-bottom: 0;
2338
+ }
2339
+ /* 渐显样式:只让尾巴里新出现的元素柔和淡入。
2340
+ 动画若挂在容器全部直接子级上,块升级(段落从尾巴进入稳定块)会重建 DOM,
2341
+ 已经显示过的内容就把入场动画重播一遍——那正是输出时「闪烁几下」的来源;
2342
+ 收窄到 .pw-stream-tail 内部后,升级进来的块不再带动画,视觉无缝。 */
2343
+ .pw-stream[data-stream-style="fade"] .pw-stream-tail > * {
2344
+ animation: pw-stream-enter 240ms ease-out both;
2345
+ }
2346
+ @keyframes pw-stream-enter {
2347
+ from {
2348
+ opacity: 0;
2349
+ transform: translateY(2px);
2350
+ }
2351
+ to {
2352
+ opacity: 1;
2353
+ transform: none;
2354
+ }
2355
+ }
2356
+
2357
+ /* 打字光标:挂在尾巴最后一个元素的行内末尾(不会另起一行)。
2358
+ 代码块和列表是块级容器,挂在外层会落到下一行,改挂到代码文字 / 最后一项的末尾 */
2359
+ .pw-stream-caret .pw-stream-tail > :last-child:not(.md-code-block, ul, ol)::after,
2360
+ .pw-stream-caret .pw-stream-tail > .md-code-block:last-child code::after,
2361
+ .pw-stream-caret .pw-stream-tail > :is(ul, ol):last-child > li:last-child::after {
2362
+ content: "";
2363
+ display: inline-block;
2364
+ width: 2px;
2365
+ height: 1.05em;
2366
+ margin-left: 2px;
2367
+ vertical-align: -0.18em;
2368
+ border-radius: 1px;
2369
+ background: var(--dsw-accent);
2370
+ animation: pw-stream-caret 1.1s steps(2, start) infinite;
2371
+ }
2372
+ @keyframes pw-stream-caret {
2373
+ 50% {
2374
+ opacity: 0;
2375
+ }
2376
+ }
2377
+
2378
+ @media (prefers-reduced-motion: reduce) {
2379
+ .pw-stream[data-stream-style="fade"] .pw-stream-tail > * {
2380
+ animation: none;
2381
+ }
2382
+ .pw-stream-caret .pw-stream-tail > :last-child:not(.md-code-block, ul, ol)::after,
2383
+ .pw-stream-caret .pw-stream-tail > .md-code-block:last-child code::after,
2384
+ .pw-stream-caret .pw-stream-tail > :is(ul, ol):last-child > li:last-child::after {
2385
+ animation: none;
2386
+ }
2387
+ }
2388
+
2389
+ /* ---------- 代码高亮(highlight.js):VS Code 式的分类着色,配色跟 Pi 自己的主题走 ---------- */
2390
+ :root {
2391
+ --hl-comment: rgb(130, 136, 146);
2392
+ --hl-keyword: rgb(160, 70, 200);
2393
+ --hl-string: rgb(30, 130, 90);
2394
+ --hl-number: rgb(190, 100, 20);
2395
+ --hl-func: rgb(55, 100, 220);
2396
+ --hl-type: rgb(20, 130, 150);
2397
+ --hl-attr: rgb(140, 90, 30);
2398
+ --hl-tag: rgb(200, 50, 90);
2399
+ --hl-regex: rgb(200, 60, 40);
2400
+ --hl-meta: rgb(120, 110, 40);
2401
+ --hl-punct: var(--dsw-label-tertiary);
2402
+ --hl-variable: rgb(30, 100, 170);
2403
+ }
2404
+ html[data-ds-dark-theme],
2405
+ body[data-ds-dark-theme] {
2406
+ --hl-comment: rgb(120, 128, 140);
2407
+ --hl-keyword: rgb(200, 150, 255);
2408
+ --hl-string: rgb(150, 210, 165);
2409
+ --hl-number: rgb(240, 175, 110);
2410
+ --hl-func: rgb(140, 185, 255);
2411
+ --hl-type: rgb(100, 200, 210);
2412
+ --hl-attr: rgb(220, 195, 130);
2413
+ --hl-tag: rgb(240, 130, 150);
2414
+ --hl-regex: rgb(235, 130, 110);
2415
+ --hl-meta: rgb(200, 190, 120);
2416
+ --hl-punct: var(--dsw-label-tertiary);
2417
+ --hl-variable: rgb(150, 200, 250);
2418
+ }
2419
+ .hljs {
2420
+ color: var(--dsw-label-secondary);
2421
+ }
2422
+ .hljs-comment,
2423
+ .hljs-quote {
2424
+ color: var(--hl-comment);
2425
+ font-style: italic;
2426
+ }
2427
+ .hljs-keyword,
2428
+ .hljs-selector-tag,
2429
+ .hljs-literal,
2430
+ .hljs-doctag,
2431
+ .hljs-section,
2432
+ .hljs-strong {
2433
+ color: var(--hl-keyword);
2434
+ }
2435
+ .hljs-strong {
2436
+ font-weight: 600;
2437
+ }
2438
+ .hljs-string,
2439
+ .hljs-addition,
2440
+ .hljs-symbol,
2441
+ .hljs-bullet,
2442
+ .hljs-link {
2443
+ color: var(--hl-string);
2444
+ }
2445
+ .hljs-number,
2446
+ .hljs-template-variable,
2447
+ .hljs-selector-class,
2448
+ .hljs-selector-id,
2449
+ .hljs-selector-pseudo {
2450
+ color: var(--hl-number);
2451
+ }
2452
+ .hljs-title,
2453
+ .hljs-title.function_,
2454
+ .hljs-title.class_,
2455
+ .hljs-title.class_.inherited__,
2456
+ .hljs-name,
2457
+ .hljs-code {
2458
+ color: var(--hl-func);
2459
+ }
2460
+ .hljs-type,
2461
+ .hljs-built_in,
2462
+ .hljs-builtin-name,
2463
+ .hljs-class .hljs-title {
2464
+ color: var(--hl-type);
2465
+ }
2466
+ .hljs-attr,
2467
+ .hljs-attribute,
2468
+ .hljs-property {
2469
+ color: var(--hl-attr);
2470
+ }
2471
+ .hljs-tag,
2472
+ .hljs-selector-attr,
2473
+ .hljs-deletion {
2474
+ color: var(--hl-tag);
2475
+ }
2476
+ .hljs-regexp,
2477
+ .hljs-subst,
2478
+ .hljs-char.escape_ {
2479
+ color: var(--hl-regex);
2480
+ }
2481
+ .hljs-meta,
2482
+ .hljs-meta .hljs-keyword,
2483
+ .hljs-meta .hljs-string,
2484
+ .hljs-formula {
2485
+ color: var(--hl-meta);
2486
+ }
2487
+ .hljs-variable,
2488
+ .hljs-variable.language_,
2489
+ .hljs-params,
2490
+ .hljs-operator {
2491
+ color: var(--hl-variable);
2492
+ }
2493
+ .hljs-punctuation {
2494
+ color: var(--hl-punct);
2495
+ }
2496
+ .hljs-emphasis {
2497
+ font-style: italic;
2498
+ }
2499
+ .hljs-deletion {
2500
+ background: none;
2501
+ }
2502
+ .hljs-addition {
2503
+ background: none;
2504
+ }
2505
+
2506
+ /* 消息气泡 */
2507
+ .msg-user-bubble {
2508
+ background: var(--dsw-input-major);
2509
+ border-radius: 18px;
2510
+ padding: 10px 16px;
2511
+ display: inline-block;
2512
+ max-width: 85%;
2513
+ font-size: var(--piweb-chat-font-size);
2514
+ line-height: 1.65;
2515
+ }
2516
+
2517
+ /* 消息操作图标行:常显低透明度,悬停变亮(dsh 同款) */
2518
+ .msg-actions {
2519
+ display: flex;
2520
+ align-items: center;
2521
+ gap: 6px;
2522
+ margin-top: 6px;
2523
+ opacity: 0.45;
2524
+ transition: opacity var(--ds-duration-fast) var(--ds-ease-in-out);
2525
+ }
2526
+ .msg-actions:hover {
2527
+ opacity: 1;
2528
+ }
2529
+
2530
+ /* 操作行时钟(dsh MessageIconActions timeStart/timeEnd):
2531
+ 次级字号 + 三级标签色;用户行时钟在图标左侧留 12px 间距 */
2532
+ .msg-clock {
2533
+ font-size: var(--dsh-content-font-size-secondary, 13px);
2534
+ line-height: calc(24px + var(--dsh-content-font-delta, 0px));
2535
+ color: var(--dsw-label-tertiary);
2536
+ }
2537
+ .msg-clock-start {
2538
+ padding-right: 12px;
2539
+ }
2540
+
2541
+ /* ============================================================
2542
+ 对话过程(Pi 版)
2543
+ 叙述句 = 阶段标题(基线对齐,主色);其下是「小图标 + 一行摘要」的步骤列表;
2544
+ 进行中的思考 / 命令用闪光渐变的英文状态词;回合结束后思考与命令折成一行摘要;
2545
+ 编辑文件保留 diff;末尾 π 记号做工作指示。没有连线。
2546
+ ============================================================ */
2547
+ :root {
2548
+ --pw-danger-soft: rgba(236, 19, 19, 0.12);
2549
+ /* 闪光高光:浅色主题下比强调色更亮更淡,深色主题下接近白 */
2550
+ --pw-shimmer-hi: rgb(150, 190, 255);
2551
+ }
2552
+ html[data-ds-dark-theme],
2553
+ body[data-ds-dark-theme] {
2554
+ --pw-danger-soft: rgba(242, 90, 90, 0.16);
2555
+ --pw-shimmer-hi: rgb(225, 236, 255);
2556
+ }
2557
+
2558
+ .pw-turn {
2559
+ display: flex;
2560
+ flex-direction: column;
2561
+ gap: 1px;
2562
+ padding: 6px 0 2px;
2563
+ }
2564
+ .pw-run {
2565
+ display: flex;
2566
+ flex-direction: column;
2567
+ gap: 1px;
2568
+ }
2569
+
2570
+ /* 步骤:左侧 16px 图标列 + 内容 */
2571
+ .pw-step {
2572
+ display: flex;
2573
+ align-items: flex-start;
2574
+ gap: 10px;
2575
+ min-height: 26px;
2576
+ animation: pw-in 160ms var(--ds-ease-in-out, ease-out) both;
2577
+ }
2578
+ @keyframes pw-in {
2579
+ from {
2580
+ opacity: 0;
2581
+ transform: translateY(2px);
2582
+ }
2583
+ to {
2584
+ opacity: 1;
2585
+ transform: none;
2586
+ }
2587
+ }
2588
+ .pw-icon {
2589
+ flex: none;
2590
+ width: 16px;
2591
+ height: 26px;
2592
+ display: inline-flex;
2593
+ align-items: center;
2594
+ justify-content: center;
2595
+ color: var(--dsw-label-caption);
2596
+ }
2597
+ .pw-step[data-tone="live"] .pw-icon {
2598
+ color: var(--dsw-accent);
2599
+ animation: dot-breathe 1.4s ease-in-out infinite;
2600
+ }
2601
+ .pw-step[data-tone="fail"] .pw-icon {
2602
+ color: var(--dsw-danger);
2603
+ }
2604
+ .pw-step[data-tone="warn"] .pw-icon {
2605
+ color: var(--dsw-warn);
2606
+ }
2607
+ .pw-step[data-kind="retry"] .pw-icon {
2608
+ animation: pw-rotate 1.2s linear infinite;
2609
+ }
2610
+ @keyframes pw-rotate {
2611
+ to {
2612
+ transform: rotate(360deg);
2613
+ }
2614
+ }
2615
+ /* π 记号:工作指示的图标 */
2616
+ .pw-pi {
2617
+ font-family: var(--font-mono);
2618
+ font-size: 15px;
2619
+ font-weight: 600;
2620
+ line-height: 1;
2621
+ transform: translateY(-1px);
2622
+ color: var(--dsw-accent);
2623
+ }
2624
+ .pw-body {
2625
+ min-width: 0;
2626
+ flex: 1;
2627
+ }
2628
+
2629
+ /* 一行摘要 */
2630
+ .pw-line {
2631
+ display: flex;
2632
+ align-items: center;
2633
+ gap: 6px;
2634
+ min-height: 26px;
2635
+ line-height: 26px;
2636
+ font-size: var(--piweb-chat-font-m);
2637
+ color: var(--dsw-label-tertiary);
2638
+ }
2639
+ button.pw-line {
2640
+ width: 100%;
2641
+ text-align: left;
2642
+ background: none;
2643
+ border: 0;
2644
+ padding: 0;
2645
+ cursor: pointer;
2646
+ font: inherit;
2647
+ font-size: var(--piweb-chat-font-m);
2648
+ }
2649
+ button.pw-line:hover {
2650
+ color: var(--dsw-label-secondary);
2651
+ }
2652
+ .pw-verb {
2653
+ flex: none;
2654
+ }
2655
+ .pw-verb[data-failed="true"] {
2656
+ color: var(--dsw-danger);
2657
+ }
2658
+ .pw-arg {
2659
+ min-width: 0;
2660
+ flex: 0 1 auto;
2661
+ overflow: hidden;
2662
+ text-overflow: ellipsis;
2663
+ white-space: nowrap;
2664
+ font-family: var(--font-mono);
2665
+ font-size: var(--piweb-chat-font-s);
2666
+ color: var(--dsw-label-secondary);
2667
+ }
2668
+ .pw-gist {
2669
+ min-width: 0;
2670
+ flex: 1;
2671
+ overflow: hidden;
2672
+ text-overflow: ellipsis;
2673
+ white-space: nowrap;
2674
+ }
2675
+ .pw-meta {
2676
+ flex: none;
2677
+ font-size: var(--piweb-chat-font-t);
2678
+ color: var(--dsw-label-caption);
2679
+ white-space: nowrap;
2680
+ }
2681
+ .pw-line .pw-chev {
2682
+ flex: none;
2683
+ color: var(--dsw-label-caption);
2684
+ transition: transform 120ms var(--ds-ease-in-out, ease);
2685
+ }
2686
+ .pw-line[aria-expanded="true"] .pw-chev {
2687
+ transform: rotate(90deg);
2688
+ }
2689
+ .pw-summary strong {
2690
+ font-weight: 600;
2691
+ color: var(--dsw-label-secondary);
2692
+ }
2693
+ .pw-run[data-open] > .pw-step:not(:first-child) {
2694
+ margin-left: 4px;
2695
+ }
2696
+
2697
+ /* 闪光渐变(进行中的思考 / 命令 / 状态词) */
2698
+ .pw-shimmer {
2699
+ flex: none;
2700
+ /* DeepSeek 式的蓝色渐变闪光:强调色为底,高光扫过 */
2701
+ background: linear-gradient(90deg, var(--dsw-accent) 0%, var(--pw-shimmer-hi) 35%, var(--dsw-accent) 70%);
2702
+ background-size: 220% 100%;
2703
+ -webkit-background-clip: text;
2704
+ background-clip: text;
2705
+ color: transparent;
2706
+ animation: pw-shimmer 2.2s linear infinite;
2707
+ }
2708
+ @keyframes pw-shimmer {
2709
+ from {
2710
+ background-position: 120% 0;
2711
+ }
2712
+ to {
2713
+ background-position: -100% 0;
2714
+ }
2715
+ }
2716
+
2717
+ /* 进行中的思考尾巴:两行截断 */
2718
+ .pw-tail {
2719
+ margin: -4px 0 5px;
2720
+ font-size: var(--piweb-chat-font-s);
2721
+ line-height: 1.5;
2722
+ color: var(--dsw-label-caption);
2723
+ word-break: break-word;
2724
+ display: -webkit-box;
2725
+ -webkit-line-clamp: 2;
2726
+ -webkit-box-orient: vertical;
2727
+ overflow: hidden;
2728
+ }
2729
+
2730
+ /* ⎿ 结果预览 */
2731
+ .pw-result {
2732
+ display: flex;
2733
+ align-items: flex-start;
2734
+ gap: 6px;
2735
+ margin: -4px 0 5px;
2736
+ font-family: var(--font-mono);
2737
+ font-size: var(--piweb-chat-font-t);
2738
+ line-height: 1.55;
2739
+ color: var(--dsw-label-tertiary);
2740
+ }
2741
+ .pw-result[role="button"] {
2742
+ cursor: pointer;
2743
+ }
2744
+ .pw-rail {
2745
+ flex: none;
2746
+ width: 14px;
2747
+ text-align: center;
2748
+ color: var(--dsw-label-caption);
2749
+ user-select: none;
2750
+ }
2751
+ .pw-lines {
2752
+ min-width: 0;
2753
+ flex: 1;
2754
+ white-space: pre-wrap;
2755
+ word-break: break-word;
2756
+ }
2757
+ .pw-lines > div {
2758
+ overflow: hidden;
2759
+ text-overflow: ellipsis;
2760
+ white-space: pre;
2761
+ }
2762
+ .pw-lines .pw-head {
2763
+ color: var(--dsw-label-tertiary);
2764
+ }
2765
+ .pw-lines .pw-more {
2766
+ color: var(--dsw-label-caption);
2767
+ }
2768
+ .pw-result[role="button"]:hover .pw-more {
2769
+ text-decoration: underline;
2770
+ }
2771
+ .pw-result[data-failed="true"],
2772
+ .pw-result[data-failed="true"] .pw-rail,
2773
+ .pw-result[data-failed="true"] .pw-head {
2774
+ color: var(--dsw-danger);
2775
+ }
2776
+
2777
+ /* diff 与完整输出 */
2778
+ .pw-diff {
2779
+ margin: -2px 0 6px 20px;
2780
+ max-height: 420px;
2781
+ overflow: auto;
2782
+ border-radius: 10px;
2783
+ padding: 6px 8px;
2784
+ background: var(--dsw-markdown-code-block, var(--dsw-hover));
2785
+ }
2786
+ .pw-output {
2787
+ margin: 0 0 6px 20px;
2788
+ max-height: 360px;
2789
+ overflow: auto;
2790
+ border-radius: 10px;
2791
+ padding: 8px 12px;
2792
+ background: var(--dsw-markdown-code-block, var(--dsw-hover));
2793
+ font-family: var(--font-mono);
2794
+ font-size: var(--piweb-chat-font-t);
2795
+ line-height: 1.55;
2796
+ color: var(--dsw-label-secondary);
2797
+ white-space: pre-wrap;
2798
+ word-break: break-word;
2799
+ }
2800
+ .pw-output.pw-think-full {
2801
+ font-family: inherit;
2802
+ color: var(--dsw-label-tertiary);
2803
+ }
2804
+ .pw-output .cmdline {
2805
+ color: var(--dsw-label-tertiary);
2806
+ margin-bottom: 6px;
2807
+ padding-bottom: 6px;
2808
+ border-bottom: 0.5px solid var(--dsw-border-l2);
2809
+ white-space: pre-wrap;
2810
+ word-break: break-all;
2811
+ }
2812
+ .pw-output .cmdline::before {
2813
+ content: "$ ";
2814
+ color: var(--dsw-label-caption);
2815
+ }
2816
+ button.pw-more {
2817
+ display: block;
2818
+ margin-top: 4px;
2819
+ font: inherit;
2820
+ font-family: var(--font-mono);
2821
+ font-size: var(--piweb-chat-font-t);
2822
+ color: var(--dsw-label-caption);
2823
+ cursor: pointer;
2824
+ background: none;
2825
+ border: 0;
2826
+ padding: 0;
2827
+ text-align: left;
2828
+ }
2829
+ button.pw-more:hover {
2830
+ color: var(--dsw-label-secondary);
2831
+ text-decoration: underline;
2832
+ }
2833
+
2834
+ /* 叙述:阶段标题,基线对齐(步骤的图标列自然形成缩进) */
2835
+ .pw-narr {
2836
+ margin: 7px 0 3px;
2837
+ font-size: var(--piweb-chat-font-l);
2838
+ line-height: 1.65;
2839
+ color: var(--dsw-label-primary);
2840
+ }
2841
+ .pw-turn > .pw-narr:first-child {
2842
+ margin-top: 1px;
2843
+ }
2844
+ .pw-narr[data-error="true"] {
2845
+ color: var(--dsw-danger);
2846
+ }
2847
+ .pw-narr .md p {
2848
+ margin: 0;
2849
+ }
2850
+ .pw-narr .md p + p {
2851
+ margin-top: 0.5em;
2852
+ }
2853
+ .pw-narr .md pre {
2854
+ margin: 0.5em 0;
2855
+ }
2856
+
2857
+ /* 错误 / 中止 / 上下文注入 */
2858
+ .pw-warn-text {
2859
+ min-width: 0;
2860
+ flex: 1;
2861
+ overflow: hidden;
2862
+ text-overflow: ellipsis;
2863
+ white-space: nowrap;
2864
+ color: var(--dsw-warn);
2865
+ }
2866
+ .pw-step[data-kind="context"] .pw-line,
2867
+ .pw-step[data-kind="abort"] .pw-line {
2868
+ color: var(--dsw-label-caption);
2869
+ font-size: var(--piweb-chat-font-s);
2870
+ }
2871
+
2872
+ /* ============================================================
2873
+ Pebrel 主题(https://github.com/Kuddev/pebrel)
2874
+ 四对亮暗主题 + Pebrel 原生深色(亮色回落 SilverLight)。
2875
+ 每对内亮/暗跟随系统(data-ds-dark-theme 由 theme.ts 同步)。
2876
+ 注意:本段必须位于文件末尾,靠源顺序赢得与旧 dsh 暗色块的平级覆盖。
2877
+ ============================================================ */
2878
+
2879
+ /* ---------- 亮色:Pebrel 通用浅色基 ---------- */
2880
+ html[data-pebrel-theme],
2881
+ body[data-pebrel-theme] {
2882
+ --dsw-bg-base: #ffffff;
2883
+ --dsw-bg-elevated: #ffffff;
2884
+ --dsw-input-major: #ffffff;
2885
+ --dsw-bubble: rgba(100, 116, 139, 0.05);
2886
+ --dsw-hover: rgba(100, 116, 139, 0.13);
2887
+ --dsw-active: rgba(100, 116, 139, 0.2);
2888
+ --dsw-label-primary: #334155;
2889
+ --dsw-label-secondary: #64748b;
2890
+ --dsw-label-tertiary: #94a3b8;
2891
+ --dsw-label-caption: #a3adbb;
2892
+ --dsw-border-l1: rgba(51, 65, 85, 0.08);
2893
+ --dsw-border-l2: rgba(51, 65, 85, 0.12);
2894
+ --dsw-border-l3: rgba(51, 65, 85, 0.16);
2895
+ --dsw-border-l4: rgba(51, 65, 85, 0.24);
2896
+ --dsw-warn: #d97706;
2897
+ --dsw-success: #548c9e;
2898
+ --dsw-danger: #b23a48;
2899
+ --dsw-selector: rgba(100, 116, 139, 0.08);
2900
+ --dsw-layer-2: #ffffff;
2901
+ --dsw-layer-3: #f5f5f6;
2902
+ --dsw-btn-elevated: #ffffff;
2903
+ --dsw-btn-floating-hover: rgba(100, 116, 139, 0.13);
2904
+ --dsw-module-platform: #f5f5f6;
2905
+ --dsw-border-strong: #64748b;
2906
+ --dsw-glass-popover: #ffffff;
2907
+ --dsw-glass-input: #ffffff;
2908
+ --dsw-glass-modal: #ffffff;
2909
+ --dsw-mask: rgba(15, 23, 42, 0.22);
2910
+ --dsw-elevation-stroke: var(--dsw-border-l2);
2911
+ }
2912
+
2913
+ /* 银钢(SilverLight;Pebrel 亮色回落同此) */
2914
+ html[data-pebrel-theme="silver-steel"],
2915
+ html[data-pebrel-theme="pebrel"],
2916
+ body[data-pebrel-theme="silver-steel"],
2917
+ body[data-pebrel-theme="pebrel"] {
2918
+ --dsw-sidebar-fill: #f3f4f6;
2919
+ --dsw-accent: rgb(73, 80, 87);
2920
+ --dsw-accent-soft: rgba(73, 80, 87, 0.12);
2921
+ }
2922
+
2923
+ /* 石灰(LimestoneLight) */
2924
+ html[data-pebrel-theme="limestone-coal"],
2925
+ body[data-pebrel-theme="limestone-coal"] {
2926
+ --dsw-sidebar-fill: #f0efeb;
2927
+ --dsw-layer-3: #f0efeb;
2928
+ --dsw-module-platform: #f0efeb;
2929
+ --dsw-accent: rgb(88, 85, 76);
2930
+ --dsw-accent-soft: rgba(88, 85, 76, 0.12);
2931
+ }
2932
+
2933
+ /* 亚麻(LinenLight) */
2934
+ html[data-pebrel-theme="linen-moss"],
2935
+ body[data-pebrel-theme="linen-moss"] {
2936
+ --dsw-sidebar-fill: #f2f2ec;
2937
+ --dsw-layer-3: #f2f2ec;
2938
+ --dsw-module-platform: #f2f2ec;
2939
+ --dsw-accent: rgb(95, 99, 95);
2940
+ --dsw-accent-soft: rgba(95, 99, 95, 0.12);
2941
+ }
2942
+
2943
+ /* 纸墨(Paper,完整浅色皮肤) */
2944
+ html[data-pebrel-theme="nord-paper"],
2945
+ body[data-pebrel-theme="nord-paper"] {
2946
+ --dsw-bg-base: #fcfbf9;
2947
+ --dsw-bg-elevated: #f5f4f0;
2948
+ --dsw-sidebar-fill: #f5f4f0;
2949
+ --dsw-input-major: #fcfbf9;
2950
+ --dsw-bubble: rgba(140, 138, 128, 0.08);
2951
+ --dsw-hover: #ebeae5;
2952
+ --dsw-active: rgba(43, 90, 56, 0.18);
2953
+ --dsw-label-primary: #1a1a1a;
2954
+ --dsw-label-secondary: #474646;
2955
+ --dsw-label-tertiary: #8c8a80;
2956
+ --dsw-label-caption: #a8a49a;
2957
+ --dsw-border-l1: #eceae4;
2958
+ --dsw-border-l2: #e0dfd5;
2959
+ --dsw-border-l3: #d5d3c9;
2960
+ --dsw-border-l4: #c1beb5;
2961
+ --dsw-accent: #2b5a38;
2962
+ --dsw-accent-soft: rgba(43, 90, 56, 0.18);
2963
+ --dsw-warn: #a85a20;
2964
+ --dsw-success: #2b5a38;
2965
+ --dsw-danger: #a33a3a;
2966
+ --dsw-selector: #ebeae5;
2967
+ --dsw-layer-2: #fcfbf9;
2968
+ --dsw-layer-3: #f5f4f0;
2969
+ --dsw-btn-elevated: #fcfbf9;
2970
+ --dsw-btn-floating-hover: #ebeae5;
2971
+ --dsw-module-platform: #f0efe9;
2972
+ --dsw-border-strong: #8c8a80;
2973
+ --dsw-glass-popover: #fcfbf9;
2974
+ --dsw-glass-input: #fcfbf9;
2975
+ --dsw-glass-modal: #f5f4f0;
2976
+ --dsw-mask: rgba(26, 26, 26, 0.19);
2977
+ }
2978
+
2979
+ /* ---------- 暗色:Pebrel 通用深色基 ---------- */
2980
+ html[data-pebrel-theme][data-ds-dark-theme],
2981
+ body[data-pebrel-theme][data-ds-dark-theme] {
2982
+ --dsw-label-primary: #e2e8f0;
2983
+ --dsw-label-secondary: #b9c3cf;
2984
+ --dsw-label-tertiary: #94a3b8;
2985
+ --dsw-label-caption: #64748b;
2986
+ --dsw-bubble: rgba(255, 255, 255, 0.05);
2987
+ --dsw-hover: rgba(203, 213, 225, 0.14);
2988
+ --dsw-active: rgba(203, 213, 225, 0.21);
2989
+ --dsw-border-l1: rgba(203, 213, 225, 0.08);
2990
+ --dsw-border-l2: rgba(203, 213, 225, 0.12);
2991
+ --dsw-border-l3: rgba(203, 213, 225, 0.16);
2992
+ --dsw-border-l4: rgba(203, 213, 225, 0.24);
2993
+ --dsw-warn: #f59e0b;
2994
+ --dsw-success: #7db2c2;
2995
+ --dsw-danger: #c44a58;
2996
+ --dsw-selector: rgba(203, 213, 225, 0.08);
2997
+ --dsw-border-strong: #94a3b8;
2998
+ --dsw-mask: rgba(2, 6, 23, 0.5);
2999
+ --dsw-elevation-stroke: var(--dsw-border-l2);
3000
+ }
3001
+
3002
+ /* 钢(SteelDark) */
3003
+ html[data-pebrel-theme="silver-steel"][data-ds-dark-theme],
3004
+ body[data-pebrel-theme="silver-steel"][data-ds-dark-theme] {
3005
+ --dsw-bg-base: #16181e;
3006
+ --dsw-bg-elevated: #1e2129;
3007
+ --dsw-sidebar-fill: #16181e;
3008
+ --dsw-input-major: #1a1c24;
3009
+ --dsw-layer-2: #1e2129;
3010
+ --dsw-layer-3: #343a48;
3011
+ --dsw-btn-elevated: #1e2129;
3012
+ --dsw-btn-floating-hover: rgba(203, 213, 225, 0.14);
3013
+ --dsw-module-platform: #1e2129;
3014
+ --dsw-glass-popover: #1e2129;
3015
+ --dsw-glass-input: #1a1c24;
3016
+ --dsw-glass-modal: #1e2129;
3017
+ --dsw-accent: #94a3b8;
3018
+ --dsw-accent-soft: rgba(148, 163, 184, 0.15);
3019
+ }
3020
+
3021
+ /* 煤(CoalDark,金棕点缀) */
3022
+ html[data-pebrel-theme="limestone-coal"][data-ds-dark-theme],
3023
+ body[data-pebrel-theme="limestone-coal"][data-ds-dark-theme] {
3024
+ --dsw-bg-base: #161616;
3025
+ --dsw-bg-elevated: #1e1e1e;
3026
+ --dsw-sidebar-fill: #161616;
3027
+ --dsw-input-major: #171717;
3028
+ --dsw-layer-2: #1e1e1e;
3029
+ --dsw-layer-3: #383836;
3030
+ --dsw-btn-elevated: #1e1e1e;
3031
+ --dsw-btn-floating-hover: rgba(203, 213, 225, 0.14);
3032
+ --dsw-module-platform: #1e1e1e;
3033
+ --dsw-glass-popover: #1e1e1e;
3034
+ --dsw-glass-input: #171717;
3035
+ --dsw-glass-modal: #1e1e1e;
3036
+ --dsw-accent: #d4d4d4;
3037
+ --dsw-accent-soft: rgba(212, 212, 212, 0.14);
3038
+ --dsw-warn: #ceb27e;
3039
+ }
3040
+
3041
+ /* 苔(MossDark) */
3042
+ html[data-pebrel-theme="linen-moss"][data-ds-dark-theme],
3043
+ body[data-pebrel-theme="linen-moss"][data-ds-dark-theme] {
3044
+ --dsw-bg-base: #191c19;
3045
+ --dsw-bg-elevated: #212521;
3046
+ --dsw-sidebar-fill: #191c19;
3047
+ --dsw-input-major: #1e211e;
3048
+ --dsw-layer-2: #212521;
3049
+ --dsw-layer-3: #363d36;
3050
+ --dsw-btn-elevated: #212521;
3051
+ --dsw-btn-floating-hover: rgba(203, 213, 225, 0.14);
3052
+ --dsw-module-platform: #212521;
3053
+ --dsw-glass-popover: #212521;
3054
+ --dsw-glass-input: #1e211e;
3055
+ --dsw-glass-modal: #212521;
3056
+ --dsw-accent: #a3b3a3;
3057
+ --dsw-accent-soft: rgba(163, 179, 163, 0.15);
3058
+ }
3059
+
3060
+ /* 北欧(Nord,完整深色皮肤) */
3061
+ html[data-pebrel-theme="nord-paper"][data-ds-dark-theme],
3062
+ body[data-pebrel-theme="nord-paper"][data-ds-dark-theme] {
3063
+ --dsw-bg-base: #2e3440;
3064
+ --dsw-bg-elevated: #3b4252;
3065
+ --dsw-sidebar-fill: #2e3440;
3066
+ --dsw-input-major: #3b4252;
3067
+ --dsw-bubble: #3b4252;
3068
+ --dsw-hover: rgba(255, 255, 255, 0.06);
3069
+ --dsw-active: rgba(136, 192, 208, 0.18);
3070
+ --dsw-label-primary: #e5e9f0;
3071
+ --dsw-label-secondary: #c0c7d3;
3072
+ --dsw-label-tertiary: #7b8294;
3073
+ --dsw-label-caption: #6f7688;
3074
+ --dsw-border-l1: rgba(255, 255, 255, 0.05);
3075
+ --dsw-border-l2: rgba(255, 255, 255, 0.06);
3076
+ --dsw-border-l3: #434c5e;
3077
+ --dsw-border-l4: #4c566a;
3078
+ --dsw-accent: #88c0d0;
3079
+ --dsw-accent-soft: rgba(136, 192, 208, 0.18);
3080
+ --dsw-warn: #ebcb8b;
3081
+ --dsw-success: #a3be8c;
3082
+ --dsw-danger: #bf616a;
3083
+ --dsw-selector: rgba(255, 255, 255, 0.06);
3084
+ --dsw-layer-2: #3b4252;
3085
+ --dsw-layer-3: #434c5e;
3086
+ --dsw-btn-elevated: #3b4252;
3087
+ --dsw-btn-floating-hover: #434c5e;
3088
+ --dsw-module-platform: #3b4252;
3089
+ --dsw-border-strong: #7b8294;
3090
+ --dsw-glass-popover: #3b4252;
3091
+ --dsw-glass-input: #3b4252;
3092
+ --dsw-glass-modal: #3b4252;
3093
+ --dsw-mask: rgba(2, 6, 23, 0.36);
3094
+ }
3095
+
3096
+ /* Pebrel 原生(Nebula,深色专属) */
3097
+ html[data-pebrel-theme="pebrel"][data-ds-dark-theme],
3098
+ body[data-pebrel-theme="pebrel"][data-ds-dark-theme] {
3099
+ --dsw-bg-base: #222630;
3100
+ --dsw-bg-elevated: #2b303b;
3101
+ --dsw-sidebar-fill: #222630;
3102
+ --dsw-input-major: #0f111a;
3103
+ --dsw-layer-2: #2b303b;
3104
+ --dsw-layer-3: #414858;
3105
+ --dsw-btn-elevated: #2b303b;
3106
+ --dsw-btn-floating-hover: rgba(203, 213, 225, 0.14);
3107
+ --dsw-module-platform: #2b303b;
3108
+ --dsw-glass-popover: #2b303b;
3109
+ --dsw-glass-input: #0f111a;
3110
+ --dsw-glass-modal: #2b303b;
3111
+ --dsw-accent: #52a8ff;
3112
+ --dsw-accent-soft: rgba(82, 168, 255, 0.15);
3113
+ }
3114
+
3115
+ /* 操作按钮进行中反馈(如分支) */
3116
+ @keyframes piweb-spin-kf {
3117
+ to {
3118
+ transform: rotate(360deg);
3119
+ }
3120
+ }
3121
+ .piweb-spin {
3122
+ animation: piweb-spin-kf 0.8s linear infinite;
3123
+ }
3124
+ /* 连接测试阶段节点的呼吸态(照 Nebula 连接卡片的流动感,PiWeb 化为脉冲) */
3125
+ @keyframes piweb-pulse-kf {
3126
+ 0%,
3127
+ 100% {
3128
+ opacity: 1;
3129
+ }
3130
+ 50% {
3131
+ opacity: 0.3;
3132
+ }
3133
+ }
3134
+ .piweb-pulse {
3135
+ animation: piweb-pulse-kf 1.1s ease-in-out infinite;
3136
+ }
3137
+ /* 流式正文末尾的光标:像终端一样告诉用户“还在写” */
3138
+ @keyframes stream-cursor-kf {
3139
+ 0%,
3140
+ 49% {
3141
+ opacity: 1;
3142
+ }
3143
+ 50%,
3144
+ 100% {
3145
+ opacity: 0;
3146
+ }
3147
+ }
3148
+ .stream-cursor {
3149
+ display: inline-block;
3150
+ width: 2px;
3151
+ height: 1em;
3152
+ margin-left: 2px;
3153
+ vertical-align: -0.15em;
3154
+ background: var(--dsw-accent);
3155
+ animation: stream-cursor-kf 1s steps(1) infinite;
3156
+ }
3157
+
3158
+ /* ============================================================
3159
+ 项目生长:项目栏 / 项目树 / 时间轴 / 文件查看器 / 整文件 diff
3160
+ ============================================================ */
3161
+
3162
+ /* 分段开关(本步 / 本会话、变更 / 内容 / 渲染) */
3163
+ .pw-seg {
3164
+ display: inline-flex;
3165
+ flex: none;
3166
+ padding: 2px;
3167
+ border-radius: 8px;
3168
+ background: var(--dsw-hover);
3169
+ gap: 1px;
3170
+ }
3171
+ .pw-seg > button {
3172
+ height: 20px;
3173
+ padding: 0 8px;
3174
+ border-radius: 6px;
3175
+ font-size: 11.5px;
3176
+ line-height: 20px;
3177
+ color: var(--dsw-label-tertiary);
3178
+ white-space: nowrap;
3179
+ transition: background var(--ds-duration-fast) var(--ds-ease-in-out), color var(--ds-duration-fast) var(--ds-ease-in-out);
3180
+ }
3181
+ .pw-seg > button[data-active="true"] {
3182
+ background: var(--dsw-bg-elevated);
3183
+ color: var(--dsw-label-primary);
3184
+ box-shadow: 0 0 0 0.5px var(--dsw-border-l2), 0 1px 2px rgba(0, 0, 0, 0.06);
3185
+ }
3186
+ /* 小胶囊开关(只看变更 / 跟随 / 折叠未改动) */
3187
+ .pw-chip {
3188
+ flex: none;
3189
+ height: 20px;
3190
+ padding: 0 8px;
3191
+ border-radius: 999px;
3192
+ border: 0.5px solid var(--dsw-border-l3);
3193
+ font-size: 11px;
3194
+ line-height: 19px;
3195
+ color: var(--dsw-label-tertiary);
3196
+ white-space: nowrap;
3197
+ 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);
3198
+ }
3199
+ .pw-chip:hover {
3200
+ background: var(--dsw-hover);
3201
+ color: var(--dsw-label-primary);
3202
+ }
3203
+ .pw-chip[data-active="true"] {
3204
+ background: var(--dsw-accent-soft);
3205
+ border-color: transparent;
3206
+ color: var(--dsw-accent);
3207
+ }
3208
+ .pw-chip:disabled {
3209
+ opacity: 0.4;
3210
+ pointer-events: none;
3211
+ }
3212
+
3213
+ /* 输入卡里的路径引用 chip:降噪的盒子——无边框、透明底,悬停才给底色与 ✕;浮上来时错开(不旋转) */
3214
+ .pw-ref-chip {
3215
+ display: flex;
3216
+ align-items: center;
3217
+ gap: 5px;
3218
+ flex: none;
3219
+ max-width: 260px;
3220
+ height: 22px;
3221
+ padding: 0 4px 0 6px;
3222
+ border-radius: 6px;
3223
+ font-size: 12px;
3224
+ font-family: var(--font-mono);
3225
+ color: var(--dsw-label-secondary);
3226
+ background: transparent;
3227
+ border: 0.5px solid transparent;
3228
+ transition: background var(--ds-duration-fast) var(--ds-ease-in-out), border-color var(--ds-duration-fast) var(--ds-ease-in-out), color var(--ds-duration-fast) var(--ds-ease-in-out);
3229
+ animation: pw-ref-rise 240ms cubic-bezier(0.2, 0.8, 0.2, 1) backwards;
3230
+ }
3231
+ .pw-ref-chip:hover {
3232
+ background: var(--dsw-hover);
3233
+ border-color: var(--dsw-border-l3);
3234
+ color: var(--dsw-label-primary);
3235
+ }
3236
+ @keyframes pw-ref-rise {
3237
+ from { opacity: 0; transform: translateY(6px) scale(0.96); }
3238
+ to { opacity: 1; transform: none; }
3239
+ }
3240
+ .pw-ref-close {
3241
+ display: flex;
3242
+ align-items: center;
3243
+ justify-content: center;
3244
+ width: 16px;
3245
+ height: 16px;
3246
+ flex: none;
3247
+ border-radius: 999px;
3248
+ font-size: 10px;
3249
+ color: var(--dsw-label-caption);
3250
+ opacity: 0;
3251
+ transition: opacity var(--ds-duration-fast) var(--ds-ease-in-out), background var(--ds-duration-fast) var(--ds-ease-in-out);
3252
+ }
3253
+ .pw-ref-chip:hover .pw-ref-close,
3254
+ .pw-ref-chip:focus-within .pw-ref-close {
3255
+ opacity: 1;
3256
+ }
3257
+ .pw-ref-close:hover {
3258
+ background: var(--dsw-selector);
3259
+ color: var(--dsw-label-primary);
3260
+ }
3261
+ .pw-ref-close:disabled {
3262
+ opacity: 0.4;
3263
+ }
3264
+ @media (prefers-reduced-motion: reduce) {
3265
+ .pw-ref-chip {
3266
+ animation: none;
3267
+ }
3268
+ }
3269
+
3270
+ /* 输入卡待发送图片:平铺缩略图 / 牌堆 / 扇形(src/components/composer/ComposerImages.tsx) */
1716
3271
  .pw-image-thumb {
1717
3272
  position: relative;
1718
3273
  flex: none;
@@ -1794,7 +3349,7 @@ body[data-pebrel-theme="pebrel"][data-ds-dark-theme] {
1794
3349
  opacity: 0.4;
1795
3350
  }
1796
3351
  /* 放大预览 */
1797
- .pw-viewer {
3352
+ .pw-lightbox {
1798
3353
  position: fixed;
1799
3354
  inset: 0;
1800
3355
  z-index: 200;
@@ -1804,7 +3359,7 @@ body[data-pebrel-theme="pebrel"][data-ds-dark-theme] {
1804
3359
  padding: 56px 16px 24px;
1805
3360
  background: rgba(0, 0, 0, 0.78);
1806
3361
  }
1807
- .pw-viewer-bar {
3362
+ .pw-lightbox-bar {
1808
3363
  position: absolute;
1809
3364
  top: 12px;
1810
3365
  left: 16px;
@@ -1813,13 +3368,13 @@ body[data-pebrel-theme="pebrel"][data-ds-dark-theme] {
1813
3368
  align-items: center;
1814
3369
  gap: 8px;
1815
3370
  }
1816
- .pw-viewer-count {
3371
+ .pw-lightbox-count {
1817
3372
  flex: 1;
1818
3373
  font-size: 13px;
1819
3374
  font-variant-numeric: tabular-nums;
1820
3375
  color: rgba(255, 255, 255, 0.78);
1821
3376
  }
1822
- .pw-viewer-btn {
3377
+ .pw-lightbox-btn {
1823
3378
  height: 30px;
1824
3379
  min-width: 30px;
1825
3380
  padding: 0 12px;
@@ -1829,19 +3384,26 @@ body[data-pebrel-theme="pebrel"][data-ds-dark-theme] {
1829
3384
  background: rgba(255, 255, 255, 0.14);
1830
3385
  transition: background var(--ds-duration-fast) var(--ds-ease-in-out);
1831
3386
  }
1832
- .pw-viewer-btn:hover {
3387
+ .pw-lightbox-btn:hover {
1833
3388
  background: rgba(255, 255, 255, 0.24);
1834
3389
  }
1835
- .pw-viewer-btn:disabled {
3390
+ .pw-lightbox-btn:disabled {
1836
3391
  opacity: 0.4;
1837
3392
  }
1838
- .pw-viewer-image {
3393
+ .pw-lightbox-image {
1839
3394
  max-width: 100%;
1840
3395
  max-height: 100%;
1841
3396
  object-fit: contain;
1842
3397
  border-radius: 12px;
3398
+ /* 从屏幕中心放大进来(transform-origin: center) */
3399
+ transform-origin: center center;
3400
+ animation: pw-viewer-zoom 200ms cubic-bezier(0.2, 0.8, 0.2, 1);
3401
+ }
3402
+ @keyframes pw-viewer-zoom {
3403
+ from { opacity: 0; transform: scale(0.92); }
3404
+ to { opacity: 1; transform: none; }
1843
3405
  }
1844
- .pw-viewer-nav {
3406
+ .pw-lightbox-nav {
1845
3407
  position: absolute;
1846
3408
  top: 50%;
1847
3409
  width: 40px;
@@ -1854,17 +3416,17 @@ body[data-pebrel-theme="pebrel"][data-ds-dark-theme] {
1854
3416
  background: rgba(255, 255, 255, 0.14);
1855
3417
  transition: background var(--ds-duration-fast) var(--ds-ease-in-out);
1856
3418
  }
1857
- .pw-viewer-nav:hover {
3419
+ .pw-lightbox-nav:hover {
1858
3420
  background: rgba(255, 255, 255, 0.24);
1859
3421
  }
1860
- .pw-viewer-nav[data-side="prev"] {
3422
+ .pw-lightbox-nav[data-side="prev"] {
1861
3423
  left: 16px;
1862
3424
  }
1863
- .pw-viewer-nav[data-side="next"] {
3425
+ .pw-lightbox-nav[data-side="next"] {
1864
3426
  right: 16px;
1865
3427
  }
1866
- .pw-viewer-btn:focus-visible,
1867
- .pw-viewer-nav:focus-visible {
3428
+ .pw-lightbox-btn:focus-visible,
3429
+ .pw-lightbox-nav:focus-visible {
1868
3430
  outline: 2px solid #fff;
1869
3431
  outline-offset: 2px;
1870
3432
  }