weifuwu 0.87.0 → 0.89.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (392) hide show
  1. package/README.md +111 -135
  2. package/dist/client/components/ActionSheet/ActionSheet.d.ts +1 -1
  3. package/dist/client/components/AiChat/AiChat.d.ts +3 -4
  4. package/dist/client/components/ChatInput/ChatInput.d.ts +5 -0
  5. package/dist/client/components/CitationCard/CitationCard.d.ts +1 -1
  6. package/dist/client/components/Command/Command.d.ts +1 -1
  7. package/dist/client/components/ContextMenu/ContextMenu.d.ts +1 -1
  8. package/dist/client/components/DatePicker/DatePicker.d.ts +1 -1
  9. package/dist/client/components/Dropdown/Dropdown.d.ts +1 -1
  10. package/dist/client/components/Editor/model/html.d.ts +10 -0
  11. package/dist/client/components/ImageCropper/ImageCropper.d.ts +6 -2
  12. package/dist/client/components/Menu/Menu.d.ts +1 -1
  13. package/dist/client/components/NavMenu/NavMenu.d.ts +1 -1
  14. package/dist/client/components/Popconfirm/Popconfirm.d.ts +1 -1
  15. package/dist/client/components/SlideCanvas/SlideCanvas.d.ts +1 -1
  16. package/dist/client/components/Tour/Tour.d.ts +1 -1
  17. package/dist/client/components/TreeSelect/TreeSelect.d.ts +1 -1
  18. package/dist/client/components/index.js +41 -41
  19. package/dist/client/components/style.css +298 -644
  20. package/dist/client/layout/weifuwu-layout.css +286 -640
  21. package/dist/client/vdom/browser/Browser.d.ts +2 -0
  22. package/dist/client/vdom/commands.d.ts +4 -1
  23. package/dist/client/vdom/context/UIContext.d.ts +8 -0
  24. package/dist/client/vdom/core/diff/attrs.d.ts +10 -2
  25. package/dist/client/vdom/core/field/attributes.d.ts +12 -0
  26. package/dist/client/vdom/core/field/events.d.ts +8 -0
  27. package/dist/client/vdom/core/field/input-sync.d.ts +14 -0
  28. package/dist/client/vdom/core/field/key.d.ts +3 -0
  29. package/dist/client/vdom/core/field/props.d.ts +13 -1
  30. package/dist/client/vdom/core/field/ref.d.ts +6 -0
  31. package/dist/client/vdom/core/field/style.d.ts +7 -1
  32. package/dist/client/vdom/core/node/component.d.ts +3 -4
  33. package/dist/client/vdom/core/node/native.d.ts +6 -1
  34. package/dist/client/vdom/core/patch/index.d.ts +24 -1
  35. package/dist/client/vdom/core/patch/processors.d.ts +8 -1
  36. package/dist/client/vdom/core/protocol.d.ts +45 -0
  37. package/dist/client/vdom/core/router.d.ts +7 -0
  38. package/dist/client/vdom/core/ssr/absorb.d.ts +31 -4
  39. package/dist/client/vdom/core/transform/index.d.ts +6 -6
  40. package/dist/client/vdom/core/v2/cycle.d.ts +54 -0
  41. package/dist/client/vdom/core/v2/diff.d.ts +80 -0
  42. package/dist/client/vdom/core/v2/integrate.d.ts +24 -0
  43. package/dist/client/vdom/core/v2/render.d.ts +28 -0
  44. package/dist/client/vdom/core/v2/schedule.d.ts +33 -0
  45. package/dist/client/vdom/core/v2/serve.d.ts +4 -0
  46. package/dist/client/vdom/core/v2/spy.d.ts +21 -0
  47. package/dist/client/vdom/core/v2/ssr.d.ts +14 -0
  48. package/dist/client/vdom/core/vnode.d.ts +9 -6
  49. package/dist/client/vdom/dev/error-counter.d.ts +27 -0
  50. package/dist/client/vdom/dev/render-health.d.ts +60 -0
  51. package/dist/client/vdom/hooks/chat.d.ts +32 -5
  52. package/dist/client/vdom/hooks/drag-media.d.ts +3 -1
  53. package/dist/client/vdom/hooks/env.d.ts +32 -0
  54. package/dist/client/vdom/hooks/popup-manager.d.ts +21 -0
  55. package/dist/client/vdom/hooks/popup.d.ts +4 -1
  56. package/dist/client/vdom/hooks/stable.d.ts +4 -0
  57. package/dist/client/vdom/hooks/use-observable.d.ts +13 -0
  58. package/dist/client/vdom/index.d.ts +14 -6
  59. package/dist/client/vdom/index.js +4 -7
  60. package/dist/client/vdom/jsx-runtime.js +1 -1
  61. package/dist/client/vdom/middlewares/api.d.ts +8 -0
  62. package/dist/client/vdom/middlewares/auth-i18n.d.ts +7 -0
  63. package/dist/client/vdom/middlewares/ws.d.ts +41 -1
  64. package/dist/client/vdom/observable/index.d.ts +13 -0
  65. package/dist/client/vdom/observable/observable.d.ts +26 -0
  66. package/dist/client/vdom/observable/operators.d.ts +76 -0
  67. package/dist/client/vdom/observable/sources.d.ts +54 -0
  68. package/dist/client/vdom/observable/types.d.ts +45 -0
  69. package/dist/client/vdom/store.d.ts +17 -2
  70. package/dist/client/vdom/testing.js +2 -2
  71. package/dist/server/ai/agent.d.ts +18 -0
  72. package/dist/server/ai/client.d.ts +14 -2
  73. package/dist/server/ai/contracts.d.ts +2 -2
  74. package/dist/server/ai/sse.d.ts +6 -0
  75. package/dist/server/core/collect.d.ts +31 -0
  76. package/dist/server/core/error-counter.d.ts +11 -0
  77. package/dist/server/core/hub.d.ts +2 -0
  78. package/dist/server/core/router.d.ts +12 -9
  79. package/dist/server/db/contracts.d.ts +24 -0
  80. package/dist/server/db/memory-redis.d.ts +3 -4
  81. package/dist/server/db/memory-sql.d.ts +20 -4
  82. package/dist/server/db/postgres-server.d.ts +2 -0
  83. package/dist/server/db/query.d.ts +21 -0
  84. package/dist/server/db/redis-server.d.ts +4 -2
  85. package/dist/server/db/sql-parser.d.ts +2 -1
  86. package/dist/server/email/index.d.ts +2 -0
  87. package/dist/server/index.d.ts +4 -1
  88. package/dist/server/index.js +3927 -1982
  89. package/dist/server/messager/index.d.ts +21 -2
  90. package/dist/server/middleware/compress.d.ts +25 -0
  91. package/dist/server/ui/index.d.ts +8 -1
  92. package/dist/server/user/index.d.ts +4 -0
  93. package/dist/shared/router/chain.d.ts +9 -0
  94. package/dist/shared/router/context.d.ts +35 -0
  95. package/dist/shared/router/ctx-fields.d.ts +20 -0
  96. package/dist/shared/router/pipeline.d.ts +70 -0
  97. package/dist/shared/router/trie.d.ts +11 -3
  98. package/dist/shared/router/types.d.ts +23 -0
  99. package/docs/style-guide.md +44 -41
  100. package/package.json +13 -10
  101. package/content/apps/admin.md +0 -55
  102. package/content/apps/agent-platform.md +0 -35
  103. package/content/apps/auth.md +0 -49
  104. package/content/apps/multi.md +0 -44
  105. package/content/apps/todo.md +0 -51
  106. package/content/backend/ai.md +0 -28
  107. package/content/backend/auth.md +0 -20
  108. package/content/backend/email.md +0 -23
  109. package/content/backend/graphql.md +0 -23
  110. package/content/backend/http.md +0 -23
  111. package/content/backend/limit.md +0 -23
  112. package/content/backend/middleware.md +0 -17
  113. package/content/backend/queue.md +0 -23
  114. package/content/backend/redis.md +0 -26
  115. package/content/backend/router.md +0 -23
  116. package/content/backend/schedule.md +0 -23
  117. package/content/backend/sql.md +0 -27
  118. package/content/backend/sse.md +0 -26
  119. package/content/backend/ws.md +0 -26
  120. package/content/capabilities/app-node.md +0 -21
  121. package/content/capabilities/data.md +0 -21
  122. package/content/capabilities/events.md +0 -21
  123. package/content/capabilities/hooks.md +0 -22
  124. package/content/capabilities/i18n.md +0 -21
  125. package/content/capabilities/popup.md +0 -21
  126. package/content/capabilities/render-only.md +0 -23
  127. package/content/capabilities/router.md +0 -22
  128. package/content/capabilities/self-id.md +0 -21
  129. package/content/capabilities/store.md +0 -21
  130. package/content/capabilities/theme.md +0 -21
  131. package/content/capabilities/two-phase.md +0 -21
  132. package/content/components/accordion.md +0 -50
  133. package/content/components/actionsheet.md +0 -46
  134. package/content/components/affix.md +0 -51
  135. package/content/components/aichat.md +0 -57
  136. package/content/components/alert.md +0 -52
  137. package/content/components/alertgroup.md +0 -45
  138. package/content/components/anchor.md +0 -52
  139. package/content/components/app.md +0 -37
  140. package/content/components/approvalcard.md +0 -56
  141. package/content/components/appshell.md +0 -50
  142. package/content/components/aspectratio.md +0 -47
  143. package/content/components/authpage.md +0 -61
  144. package/content/components/autocomplete-v2.md +0 -40
  145. package/content/components/autocomplete.md +0 -56
  146. package/content/components/avatar.md +0 -51
  147. package/content/components/avatargroup.md +0 -47
  148. package/content/components/backtop.md +0 -53
  149. package/content/components/badge.md +0 -55
  150. package/content/components/breadcrumb.md +0 -49
  151. package/content/components/button.md +0 -63
  152. package/content/components/calendar-v2.md +0 -40
  153. package/content/components/calendar.md +0 -50
  154. package/content/components/card.md +0 -58
  155. package/content/components/carousel.md +0 -52
  156. package/content/components/cascader-v2.md +0 -39
  157. package/content/components/cascader.md +0 -54
  158. package/content/components/chart.md +0 -53
  159. package/content/components/chatinput.md +0 -63
  160. package/content/components/checkbox.md +0 -51
  161. package/content/components/checkboxgroup.md +0 -52
  162. package/content/components/citationcard.md +0 -48
  163. package/content/components/codeblock.md +0 -48
  164. package/content/components/codeeditor.md +0 -47
  165. package/content/components/collapse.md +0 -49
  166. package/content/components/colorpicker.md +0 -50
  167. package/content/components/command.md +0 -50
  168. package/content/components/confirm.md +0 -57
  169. package/content/components/contextmenu.md +0 -48
  170. package/content/components/copybutton.md +0 -51
  171. package/content/components/datepicker.md +0 -52
  172. package/content/components/descriptions-v2.md +0 -39
  173. package/content/components/descriptions.md +0 -52
  174. package/content/components/diffview-v2.md +0 -39
  175. package/content/components/diffview.md +0 -50
  176. package/content/components/divider.md +0 -48
  177. package/content/components/drawer.md +0 -55
  178. package/content/components/dropdown.md +0 -53
  179. package/content/components/editor.md +0 -49
  180. package/content/components/emptystate.md +0 -51
  181. package/content/components/exportcsv.md +0 -38
  182. package/content/components/field.md +0 -54
  183. package/content/components/filepreview-office.md +0 -37
  184. package/content/components/filepreview.md +0 -49
  185. package/content/components/filetree.md +0 -56
  186. package/content/components/fileupload-v2.md +0 -39
  187. package/content/components/fileupload.md +0 -57
  188. package/content/components/floatbutton.md +0 -52
  189. package/content/components/form-v2.md +0 -41
  190. package/content/components/form.md +0 -60
  191. package/content/components/grid.md +0 -51
  192. package/content/components/highlight-v2.md +0 -39
  193. package/content/components/highlight.md +0 -46
  194. package/content/components/hovercard.md +0 -51
  195. package/content/components/icon.md +0 -50
  196. package/content/components/imagecropper.md +0 -45
  197. package/content/components/img.md +0 -56
  198. package/content/components/infinitescroll-v2.md +0 -40
  199. package/content/components/infinitescroll.md +0 -54
  200. package/content/components/input.md +0 -65
  201. package/content/components/inputnumber.md +0 -58
  202. package/content/components/inview.md +0 -56
  203. package/content/components/jsonschemaform.md +0 -53
  204. package/content/components/jsonviewer-v2.md +0 -39
  205. package/content/components/jsonviewer.md +0 -49
  206. package/content/components/kanban.md +0 -46
  207. package/content/components/label.md +0 -48
  208. package/content/components/layout.md +0 -54
  209. package/content/components/layoutcontent.md +0 -43
  210. package/content/components/layoutheader.md +0 -43
  211. package/content/components/layoutsider.md +0 -43
  212. package/content/components/link.md +0 -52
  213. package/content/components/list.md +0 -44
  214. package/content/components/loading.md +0 -45
  215. package/content/components/logviewer-v2.md +0 -39
  216. package/content/components/logviewer.md +0 -53
  217. package/content/components/markdown.md +0 -51
  218. package/content/components/markdowneditor.md +0 -47
  219. package/content/components/math.md +0 -42
  220. package/content/components/mentions-v2.md +0 -39
  221. package/content/components/mentions.md +0 -52
  222. package/content/components/menu.md +0 -56
  223. package/content/components/menubar.md +0 -44
  224. package/content/components/messagebubble.md +0 -50
  225. package/content/components/modal.md +0 -59
  226. package/content/components/navmenu.md +0 -47
  227. package/content/components/notification.md +0 -51
  228. package/content/components/pageheader.md +0 -53
  229. package/content/components/pagination.md +0 -49
  230. package/content/components/paragraph.md +0 -45
  231. package/content/components/passwordinput.md +0 -57
  232. package/content/components/pininput-v2.md +0 -39
  233. package/content/components/pininput.md +0 -50
  234. package/content/components/pipeline.md +0 -49
  235. package/content/components/popconfirm.md +0 -58
  236. package/content/components/popover.md +0 -61
  237. package/content/components/progressbar.md +0 -50
  238. package/content/components/prompttemplate.md +0 -49
  239. package/content/components/qrcode.md +0 -50
  240. package/content/components/radiogroup.md +0 -53
  241. package/content/components/rate.md +0 -53
  242. package/content/components/reasoningblock.md +0 -47
  243. package/content/components/relationgraph.md +0 -52
  244. package/content/components/resizable.md +0 -53
  245. package/content/components/result.md +0 -49
  246. package/content/components/scrollbar.md +0 -49
  247. package/content/components/searchinput.md +0 -51
  248. package/content/components/segmentedcontrol.md +0 -59
  249. package/content/components/select-searchable.md +0 -47
  250. package/content/components/select.md +0 -66
  251. package/content/components/sessionlist.md +0 -52
  252. package/content/components/sheetgrid.md +0 -44
  253. package/content/components/skeleton.md +0 -55
  254. package/content/components/slidecanvas.md +0 -44
  255. package/content/components/slider.md +0 -62
  256. package/content/components/sortablelist.md +0 -39
  257. package/content/components/space.md +0 -52
  258. package/content/components/sparkline.md +0 -52
  259. package/content/components/statcard-countdown.md +0 -39
  260. package/content/components/statcard.md +0 -56
  261. package/content/components/steps.md +0 -48
  262. package/content/components/switch.md +0 -50
  263. package/content/components/tabbar.md +0 -45
  264. package/content/components/table-v2.md +0 -40
  265. package/content/components/table.md +0 -66
  266. package/content/components/tabs.md +0 -56
  267. package/content/components/tag.md +0 -51
  268. package/content/components/tagsinput-v2.md +0 -39
  269. package/content/components/tagsinput.md +0 -54
  270. package/content/components/text.md +0 -45
  271. package/content/components/textarea.md +0 -57
  272. package/content/components/themeswitch.md +0 -69
  273. package/content/components/timeline.md +0 -50
  274. package/content/components/title.md +0 -45
  275. package/content/components/toast.md +0 -52
  276. package/content/components/toggle-togglegroup.md +0 -52
  277. package/content/components/togglegroup.md +0 -47
  278. package/content/components/toolcallcard.md +0 -51
  279. package/content/components/tooltip.md +0 -50
  280. package/content/components/tour.md +0 -50
  281. package/content/components/transfer.md +0 -52
  282. package/content/components/tree-v2.md +0 -39
  283. package/content/components/tree.md +0 -59
  284. package/content/components/treeselect.md +0 -54
  285. package/content/components/typography.md +0 -51
  286. package/content/components/videoplayer.md +0 -52
  287. package/content/components/virtuallist.md +0 -52
  288. package/content/components/virtualtable-v2.md +0 -39
  289. package/content/components/virtualtable.md +0 -55
  290. package/content/components/watermark.md +0 -53
  291. package/content/components/wave.md +0 -43
  292. package/content/guides/ai-chat-family.md +0 -24
  293. package/content/guides/choose.md +0 -67
  294. package/content/guides/component-model.md +0 -32
  295. package/content/guides/component-standards.md +0 -123
  296. package/content/guides/components-guide.md +0 -813
  297. package/content/guides/custom-component.md +0 -321
  298. package/content/guides/data-guide.md +0 -281
  299. package/content/guides/file-preview-family.md +0 -18
  300. package/content/guides/frontend.md +0 -968
  301. package/content/guides/layout-choice.md +0 -64
  302. package/content/guides/layout-guide.md +0 -241
  303. package/content/guides/middleware.md +0 -459
  304. package/content/guides/mobile-guide.md +0 -105
  305. package/content/guides/page-building.md +0 -98
  306. package/content/guides/production.md +0 -37
  307. package/content/guides/quality.md +0 -60
  308. package/content/guides/realtime-guide.md +0 -296
  309. package/content/guides/render-only.md +0 -44
  310. package/content/guides/saas-guide.md +0 -253
  311. package/content/guides/server-guide.md +0 -359
  312. package/content/guides/start.md +0 -41
  313. package/content/guides/styling.md +0 -154
  314. package/content/guides/ui-dom-guide.md +0 -157
  315. package/content/index.json +0 -4344
  316. package/content/index.md +0 -181
  317. package/content/layout/align.md +0 -20
  318. package/content/layout/anchor.md +0 -19
  319. package/content/layout/app-shell.md +0 -23
  320. package/content/layout/border.md +0 -20
  321. package/content/layout/center.md +0 -19
  322. package/content/layout/cluster.md +0 -19
  323. package/content/layout/container.md +0 -19
  324. package/content/layout/fill.md +0 -19
  325. package/content/layout/grid.md +0 -19
  326. package/content/layout/hidden.md +0 -22
  327. package/content/layout/layer.md +0 -19
  328. package/content/layout/position.md +0 -22
  329. package/content/layout/row.md +0 -23
  330. package/content/layout/safe-area.md +0 -20
  331. package/content/layout/scroll.md +0 -21
  332. package/content/layout/spacing.md +0 -22
  333. package/content/layout/split.md +0 -19
  334. package/content/layout/stack.md +0 -19
  335. package/content/layout/surface.md +0 -23
  336. package/content/layout/text.md +0 -22
  337. package/content/patterns/app-shell.md +0 -34
  338. package/content/patterns/dashboard.md +0 -36
  339. package/content/patterns/data-screen.md +0 -30
  340. package/content/patterns/detail-page.md +0 -31
  341. package/content/patterns/docs.md +0 -34
  342. package/content/patterns/focus-task.md +0 -34
  343. package/content/patterns/landing.md +0 -35
  344. package/content/patterns/list-page.md +0 -32
  345. package/content/patterns/mobile.md +0 -31
  346. package/content/patterns/settings-page.md +0 -33
  347. package/content/patterns/workspace.md +0 -32
  348. package/dist/cli/content-sync.test.d.ts +0 -1
  349. package/dist/cli/docs-cli.test.d.ts +0 -1
  350. package/dist/cli/docs.d.ts +0 -2
  351. package/dist/cli/docs.mjs +0 -10961
  352. package/dist/client/vdom/core/build.d.ts +0 -36
  353. package/dist/client/vdom/core/diff/children.d.ts +0 -29
  354. package/dist/client/vdom/core/diff/index.d.ts +0 -22
  355. package/dist/client/vdom/core/diff/output.d.ts +0 -30
  356. package/dist/client/vdom/core/diff/same.d.ts +0 -22
  357. package/dist/client/vdom/core/serve.d.ts +0 -75
  358. package/dist/client/vdom/core/ssr/index.d.ts +0 -25
  359. package/examples/apps/admin/README.md +0 -23
  360. package/examples/apps/admin/api.ts +0 -27
  361. package/examples/apps/admin/app.tsx +0 -144
  362. package/examples/apps/admin/main.tsx +0 -8
  363. package/examples/apps/admin/server.ts +0 -37
  364. package/examples/apps/auth/README.md +0 -23
  365. package/examples/apps/auth/api.ts +0 -49
  366. package/examples/apps/auth/app.tsx +0 -137
  367. package/examples/apps/auth/main.tsx +0 -8
  368. package/examples/apps/auth/server.ts +0 -37
  369. package/examples/apps/multi/README.md +0 -23
  370. package/examples/apps/multi/app.tsx +0 -83
  371. package/examples/apps/multi/main.tsx +0 -8
  372. package/examples/apps/multi/server.ts +0 -33
  373. package/examples/apps/todo/README.md +0 -23
  374. package/examples/apps/todo/api.ts +0 -26
  375. package/examples/apps/todo/app.tsx +0 -128
  376. package/examples/apps/todo/main.tsx +0 -9
  377. package/examples/apps/todo/server.ts +0 -39
  378. package/examples/hello-world/README.md +0 -9
  379. package/examples/hello-world/client.ts +0 -14
  380. package/examples/hello-world/routes.tsx +0 -26
  381. package/examples/hello-world/server.ts +0 -46
  382. package/examples/patterns/AppShell.tsx +0 -224
  383. package/examples/patterns/Dashboard.tsx +0 -153
  384. package/examples/patterns/DataScreen.tsx +0 -104
  385. package/examples/patterns/DetailPage.tsx +0 -79
  386. package/examples/patterns/Docs.tsx +0 -105
  387. package/examples/patterns/FocusTask.tsx +0 -67
  388. package/examples/patterns/Landing.tsx +0 -90
  389. package/examples/patterns/ListPage.tsx +0 -77
  390. package/examples/patterns/Mobile.tsx +0 -154
  391. package/examples/patterns/SettingsPage.tsx +0 -98
  392. package/examples/patterns/SplitWorkspace.tsx +0 -113
@@ -1,8 +1,7 @@
1
- /* weifuwu/layout — 基于 CSS 标准的布局原语 */
1
+ /* weifuwu/layout — 基于 CSS 标准的布局原语
2
2
 
3
3
  @layer tokens, base, layout, utilities, components;
4
4
 
5
- @layer tokens {
6
5
  /* weifuwu/theme — 设计 Token(Primitive + Semantic 双层)
7
6
  *
8
7
  * 原始层(Primitive):色值/暗色值只定义一次。品牌换色/暗色调校只改这一层。
@@ -253,6 +252,7 @@
253
252
 
254
253
  /* ── 色彩 — 实心填充上的文字/图标(primary/success 等实心底色) ── */
255
254
  --wf-color-on-brand: #fff;
255
+ --wf-color-on-warning: #451a03; /* 警告实心底上的深色文字(暗色经 _dark.css 映射) */
256
256
 
257
257
  /* ── 浮层遮罩(Modal/Drawer overlay,暗色经 --wf-dark-overlay 映射) ── */
258
258
  --wf-overlay: rgba(0, 0, 0, 0.4);
@@ -304,9 +304,7 @@
304
304
  --wf-dark-brand-50: #1e293b;
305
305
  }
306
306
  }
307
- }
308
307
 
309
- @layer tokens {
310
308
  /* weifuwu/theme — 暗色模式
311
309
  *
312
310
  * 两种激活方式(优先级:显式 data-theme > 系统偏好):
@@ -430,9 +428,7 @@
430
428
  --wf-overlay: var(--wf-dark-overlay);
431
429
  }
432
430
  }
433
- }
434
431
 
435
- @layer tokens {
436
432
  /* weifuwu/theme — 预设主题(shadcn themes.css 式变量组切换)
437
433
  *
438
434
  * 用法:<html data-preset="minimal|compact|rounded">
@@ -485,7 +481,6 @@
485
481
  --wf-btn-radius: 999px;
486
482
  --wf-field-radius: var(--wf-radius-md);
487
483
  }
488
- }
489
484
 
490
485
  @layer base {
491
486
  /* weifuwu/theme — 基础元素默认样式 */
@@ -765,34 +760,20 @@ body.wf-dragging {
765
760
  }
766
761
 
767
762
  @layer layout {
768
- /* stack — 纵向堆叠(L3:gap 默认值 :where() 零优先级——wf-gap-* 等覆盖工具
769
- 靠优先级获胜,不再依赖 import 顺序) */
763
+ /* stack — 纵向堆叠(L3:gap/align 默认值 :where() 零优先级——wf-gap-*、
764
+ wf-items-* 覆盖工具靠优先级获胜,不再依赖 import 顺序) */
770
765
  .wf-stack {
771
766
  display: flex;
772
767
  flex-direction: column;
773
768
  }
774
769
  :where(.wf-stack) {
775
770
  gap: var(--wf-gap, var(--wf-gap-md));
771
+ align-items: var(--wf-align, stretch);
776
772
  }
777
- @media (min-width: 640px) { .wf-stack\@sm { flex-direction: row; align-items: var(--wf-align, center); } }
778
- @media (min-width: 768px) { .wf-stack\@md { flex-direction: row; align-items: var(--wf-align, center); } }
779
- @media (min-width: 1024px) { .wf-stack\@lg { flex-direction: row; align-items: var(--wf-align, center); } }
780
-
781
- /* stack-reverse — 纵向反向堆叠 */
782
- .wf-stack-reverse {
783
- display: flex;
784
- flex-direction: column-reverse;
785
- }
786
- :where(.wf-stack-reverse) {
787
- gap: var(--wf-gap, var(--wf-gap-md));
788
- }
789
- @media (min-width: 640px) { .wf-stack-reverse\@sm { flex-direction: row-reverse; align-items: var(--wf-align, center); } }
790
- @media (min-width: 768px) { .wf-stack-reverse\@md { flex-direction: row-reverse; align-items: var(--wf-align, center); } }
791
- @media (min-width: 1024px) { .wf-stack-reverse\@lg { flex-direction: row-reverse; align-items: var(--wf-align, center); } }
792
773
  }
793
774
 
794
775
  @layer layout {
795
- /* row — 横向排列(L3:gap/align 默认值 :where() 零优先级——wf-gap-*、wf-top 等
776
+ /* row — 横向排列(L3:gap/align 默认值 :where() 零优先级——wf-gap-* 等
796
777
  覆盖工具靠优先级获胜,不再依赖 import 顺序) */
797
778
  .wf-row {
798
779
  display: flex;
@@ -802,9 +783,6 @@ body.wf-dragging {
802
783
  gap: var(--wf-gap, var(--wf-gap-md));
803
784
  align-items: var(--wf-align, center);
804
785
  }
805
- @media (min-width: 640px) { .wf-row\@sm { flex-direction: row; flex-wrap: wrap; } }
806
- @media (min-width: 768px) { .wf-row\@md { flex-direction: row; flex-wrap: wrap; } }
807
- @media (min-width: 1024px) { .wf-row\@lg { flex-direction: row; flex-wrap: wrap; } }
808
786
 
809
787
  /* row-reverse — 横向反向排列 */
810
788
  .wf-row-reverse {
@@ -816,12 +794,9 @@ body.wf-dragging {
816
794
  gap: var(--wf-gap, var(--wf-gap-md));
817
795
  align-items: var(--wf-align, center);
818
796
  }
819
- @media (min-width: 640px) { .wf-row-reverse\@sm { flex-direction: row-reverse; flex-wrap: wrap; } }
820
- @media (min-width: 768px) { .wf-row-reverse\@md { flex-direction: row-reverse; flex-wrap: wrap; } }
821
- @media (min-width: 1024px) { .wf-row-reverse\@lg { flex-direction: row-reverse; flex-wrap: wrap; } }
822
797
 
823
- /* items — 交叉轴对齐工具(设 --wf-align 变量,wf-row/wf-row-reverse 消费;
824
- 语义与 wf-top/bottom/stretch 等价——items 命名对齐消费侧习惯) */
798
+ /* items — 交叉轴对齐(单机制——设 --wf-align 变量,wf-row/wf-stack 等消费;
799
+ 值为 CSS align-items 值词。物理方向词(top/bottom)禁入对齐域) */
825
800
  .wf-items-start { --wf-align: flex-start; }
826
801
  .wf-items-center { --wf-align: center; }
827
802
  .wf-items-end { --wf-align: flex-end; }
@@ -854,84 +829,22 @@ body.wf-dragging {
854
829
  }
855
830
 
856
831
  @layer layout {
857
- /* between — 两端对齐(行内垂直居中;L3:align/gap 默认值 :where() 零优先级) */
858
- .wf-between {
832
+ /* justify — 主轴分布(对齐域统一 CSS 词根——值为 justify-content 值词;
833
+ L3:align/gap 默认值 :where() 零优先级) */
834
+ .wf-justify-between {
859
835
  display: flex;
860
836
  justify-content: space-between;
861
837
  }
862
- :where(.wf-between) {
838
+ :where(.wf-justify-between) {
863
839
  align-items: var(--wf-align, center);
864
840
  gap: var(--wf-gap, var(--wf-gap-md));
865
841
  }
866
- @media (min-width: 640px) { .wf-between\@sm { display: flex; justify-content: space-between; align-items: var(--wf-align, center); gap: var(--wf-gap, var(--wf-gap-md)); } }
867
- @media (min-width: 768px) { .wf-between\@md { display: flex; justify-content: space-between; align-items: var(--wf-align, center); gap: var(--wf-gap, var(--wf-gap-md)); } }
868
- @media (min-width: 1024px) { .wf-between\@lg { display: flex; justify-content: space-between; align-items: var(--wf-align, center); gap: var(--wf-gap, var(--wf-gap-md)); } }
869
- }
870
842
 
871
- @layer layout {
872
- /* right — 靠右对齐(L3:align/gap 默认值 :where() 零优先级) */
873
- .wf-right {
843
+ .wf-justify-end {
874
844
  display: flex;
875
845
  justify-content: flex-end;
876
846
  }
877
- :where(.wf-right) {
878
- align-items: var(--wf-align, center);
879
- gap: var(--wf-gap, var(--wf-gap-md));
880
- }
881
- }
882
-
883
- @layer layout {
884
- /* top — 顶部对齐(L3:gap 默认值 :where() 零优先级;align-items 是身份属性) */
885
- .wf-top {
886
- display: flex;
887
- align-items: flex-start;
888
- }
889
- :where(.wf-top) {
890
- gap: var(--wf-gap, var(--wf-gap-md));
891
- }
892
- }
893
-
894
- @layer layout {
895
- /* bottom — 底部对齐(L3:gap 默认值 :where() 零优先级;align-items 是身份属性) */
896
- .wf-bottom {
897
- display: flex;
898
- align-items: flex-end;
899
- }
900
- :where(.wf-bottom) {
901
- gap: var(--wf-gap, var(--wf-gap-md));
902
- }
903
- }
904
-
905
- @layer layout {
906
- /* stretch — 拉伸对齐(L3:gap 默认值 :where() 零优先级;align-items 是身份属性) */
907
- .wf-stretch {
908
- display: flex;
909
- align-items: stretch;
910
- }
911
- :where(.wf-stretch) {
912
- gap: var(--wf-gap, var(--wf-gap-md));
913
- }
914
- }
915
-
916
- @layer layout {
917
- /* around — 均匀环绕分布(L3:align/gap 默认值 :where() 零优先级) */
918
- .wf-around {
919
- display: flex;
920
- justify-content: space-around;
921
- }
922
- :where(.wf-around) {
923
- align-items: var(--wf-align, center);
924
- gap: var(--wf-gap, var(--wf-gap-md));
925
- }
926
- }
927
-
928
- @layer layout {
929
- /* evenly — 均匀分布(L3:align/gap 默认值 :where() 零优先级) */
930
- .wf-evenly {
931
- display: flex;
932
- justify-content: space-evenly;
933
- }
934
- :where(.wf-evenly) {
847
+ :where(.wf-justify-end) {
935
848
  align-items: var(--wf-align, center);
936
849
  gap: var(--wf-gap, var(--wf-gap-md));
937
850
  }
@@ -946,183 +859,6 @@ body.wf-dragging {
946
859
  }
947
860
  }
948
861
 
949
- @layer layout {
950
- /* flex-none — 固定不伸缩(推荐名;wf-fixed 为兼容别名——易与 position:fixed 混淆,
951
- position:fixed 请用 wf-pin) */
952
- .wf-flex-none,
953
- .wf-fixed {
954
- flex: none;
955
- }
956
-
957
- /* pin — 固定定位(角标/浮层锚点——position: fixed,坐标由 inline 参数控制) */
958
- .wf-pin {
959
- position: fixed;
960
- z-index: var(--wf-z, var(--wf-cover-z));
961
- }
962
- }
963
-
964
- @layer layout {
965
- /* auto — 按内容撑满 */
966
- .wf-auto {
967
- flex: auto;
968
- min-width: 0;
969
- min-height: 0;
970
- }
971
- }
972
-
973
- @layer layout {
974
- /* cover — 全屏覆盖 */
975
- .wf-cover {
976
- position: fixed;
977
- inset: 0;
978
- display: flex;
979
- align-items: center;
980
- justify-content: center;
981
- z-index: var(--wf-z, var(--wf-cover-z));
982
- }
983
- }
984
-
985
- @layer layout {
986
- /* pop — 浮动层 */
987
- .wf-pop {
988
- position: absolute;
989
- z-index: var(--wf-z, var(--wf-pop-z));
990
- }
991
- }
992
-
993
- @layer layout {
994
- /* popup — 浮层基类(usePopup.portal 自动附加;Modal/Drawer 等手动浮层可选用)
995
- *
996
- * 宽度视口 clamp:任何浮层默认不横向溢出(375px 屏也能完整操作)。
997
- * usePopup 已内联 maxWidth;本类兜底组件手动引用场景(audit 规则的目标选择器)。
998
- */
999
- .wf-popup {
1000
- max-width: min(var(--wf-popup-max, 480px), calc(100vw - 32px));
1001
- box-sizing: border-box;
1002
- }
1003
-
1004
- /* usePopup mask 模式遮罩:全屏 fixed,z-index 低于面板(overlay=80 < popover=120),
1005
- * 模态语义阻断页面交互;点击遮罩关闭(maskClosable 门控在组件层) */
1006
- .wf-popup-mask {
1007
- position: fixed;
1008
- inset: 0;
1009
- z-index: var(--wf-z-overlay);
1010
- background: var(--wf-overlay);
1011
- }
1012
- }
1013
-
1014
- @layer layout {
1015
- /* safe-area — iOS 刘海屏/Home 条安全区工具(env() 未生效环境自动为 0) */
1016
- .wf-safe-bottom {
1017
- padding-bottom: env(safe-area-inset-bottom);
1018
- }
1019
- .wf-safe-top {
1020
- padding-top: env(safe-area-inset-top);
1021
- }
1022
- }
1023
-
1024
- @layer layout {
1025
- /* anchor — 定位锚点容器 */
1026
- .wf-anchor {
1027
- position: relative;
1028
- }
1029
- }
1030
-
1031
- @layer layout {
1032
- /* sticky — 粘性定位 */
1033
- .wf-sticky {
1034
- position: sticky;
1035
- top: var(--wf-offset, 0);
1036
- }
1037
- }
1038
-
1039
- @layer utilities {
1040
- /* surface — 基础面 + 面工具类(背景色/气泡/胶囊) */
1041
-
1042
- .wf-surface {
1043
- border-radius: var(--wf-surface-radius);
1044
- box-shadow: var(--wf-surface-shadow);
1045
- background: var(--wf-surface-bg);
1046
- }
1047
-
1048
- /* 平面表面(M4 表面语言——静态卡片/面板组合 wf-border 用:阴影仅抬升语义) */
1049
- .wf-surface--flat {
1050
- box-shadow: none;
1051
- }
1052
-
1053
- /* ── 背景色工具 — 引用语义 Token,免自定义 CSS ── */
1054
- .wf-bg-secondary { background: var(--wf-color-bg-secondary); }
1055
- .wf-bg-tertiary { background: var(--wf-color-bg-tertiary); }
1056
- .wf-bg-brand { background: var(--wf-color-primary-bg); } /* 兼容别名 → wf-bg-primary */
1057
- .wf-bg-primary { background: var(--wf-color-primary-bg); }
1058
- .wf-bg-success { background: var(--wf-color-success-bg); }
1059
- .wf-bg-warning { background: var(--wf-color-warning-bg); }
1060
- .wf-bg-error { background: var(--wf-color-error-bg); }
1061
- .wf-bg-info { background: var(--wf-color-info-bg); }
1062
-
1063
- /* ── 胶囊圆角(状态徽章/标签/色块) ── */
1064
- .wf-pill { border-radius: 999px; }
1065
-
1066
- /* ── 圆角工具 — 引用圆角 Token ── */
1067
- .wf-rounded-sm { border-radius: var(--wf-radius-sm); }
1068
- .wf-rounded { border-radius: var(--wf-radius); }
1069
- .wf-rounded-md { border-radius: var(--wf-radius-md); }
1070
- .wf-rounded-lg { border-radius: var(--wf-radius-lg); }
1071
-
1072
- /* ── hover 抬升(Card/StatCard 可点击/悬停共用,阴影 + 上移 + 焦点环) ── */
1073
- .wf-elevate {
1074
- transition: box-shadow var(--wf-dur-fast) var(--wf-ease-out), transform var(--wf-dur-fast) var(--wf-ease-out);
1075
- }
1076
- .wf-elevate:hover {
1077
- box-shadow: var(--wf-shadow-md);
1078
- transform: translateY(-2px);
1079
- }
1080
- .wf-elevate:focus-visible {
1081
- outline: none;
1082
- box-shadow: var(--wf-shadow-md), var(--wf-focus-ring);
1083
- }
1084
-
1085
- /* ── 面板入场:统一 scale+fade(面板族:dropdown/select/datepicker 从触发点下方弹出) ── */
1086
- .wf-panel-in {
1087
- animation: wf-panel-in var(--wf-dur-fast) var(--wf-ease-out);
1088
- transform-origin: top center;
1089
- }
1090
-
1091
- @keyframes wf-panel-in {
1092
- from { opacity: 0; transform: translateY(-4px) scale(0.97); }
1093
- to { opacity: 1; transform: translateY(0) scale(1); }
1094
- }
1095
-
1096
- /* ── 聊天气泡 ──
1097
- * 用法:wf-bubble(对方/AI)+ wf-bubble--own(自己)
1098
- * 行布局用 wf-row + wf-gap/wf-mb 覆盖;文字用 wf-pre-wrap 已内建
1099
- */
1100
- .wf-bubble {
1101
- display: inline-block;
1102
- max-width: 70%;
1103
- padding: var(--wf-space-sm) var(--wf-space-md);
1104
- border-radius: var(--wf-radius-md);
1105
- background: var(--wf-color-bg-secondary);
1106
- color: var(--wf-color-text);
1107
- font-size: var(--wf-font-size-base);
1108
- line-height: var(--wf-line-height);
1109
- white-space: pre-wrap;
1110
- word-break: break-word;
1111
- }
1112
-
1113
- .wf-bubble--own {
1114
- background: var(--wf-color-primary);
1115
- color: var(--wf-color-on-brand);
1116
- border-bottom-right-radius: var(--wf-radius-sm);
1117
- }
1118
-
1119
- .wf-bubble--ai {
1120
- background: var(--wf-color-primary-bg);
1121
- border: var(--wf-border-width) solid var(--wf-color-border-light);
1122
- border-bottom-left-radius: var(--wf-radius-sm);
1123
- }
1124
- }
1125
-
1126
862
  @layer layout {
1127
863
  /* grid — 二维网格(L3:gap 默认值 :where() 零优先级) */
1128
864
  .wf-grid {
@@ -1136,7 +872,7 @@ body.wf-dragging {
1136
872
 
1137
873
  @layer layout {
1138
874
  /* cluster — 换行簇(L3:justify/align/gap 默认值 :where() 零优先级——
1139
- wf-right 等分布工具叠加时靠优先级获胜) */
875
+ wf-justify-end 等分布工具叠加时靠优先级获胜) */
1140
876
  .wf-cluster {
1141
877
  display: flex;
1142
878
  flex-wrap: wrap;
@@ -1149,100 +885,47 @@ body.wf-dragging {
1149
885
  }
1150
886
 
1151
887
  @layer layout {
1152
- /* scroll — 可滚动容器(全局滚动条样式见 _base.css;此类仅标记语义 + overflow) */
1153
- .wf-scroll {
1154
- overflow: auto;
1155
- }
1156
- }
1157
-
1158
- @layer layout {
1159
- /* clip — 裁剪溢出 */
1160
- .wf-clip {
1161
- overflow: hidden;
1162
- }
1163
- }
1164
-
1165
- @layer utilities {
1166
- /* hidden — 隐藏元素 */
1167
- .wf-hidden {
1168
- display: none;
1169
- }
1170
- @media (min-width: 640px) { .wf-hidden\@sm { display: none; } }
1171
- @media (min-width: 768px) { .wf-hidden\@md { display: none; } }
1172
- @media (min-width: 1024px) { .wf-hidden\@lg { display: none; } }
1173
-
1174
- /* dim — 视觉淡化(运行中/历史态/次要操作) */
1175
- .wf-dim {
1176
- opacity: 0.7;
1177
- }
1178
-
1179
- /* cursor — 交互指针 */
1180
- .wf-pointer { cursor: pointer; }
1181
- .wf-not-allowed { cursor: not-allowed; }
1182
-
1183
- /* 打印工具 — 导出 PDF 时隐藏工具区 / 恢复块级 */
1184
- @media print {
1185
- .wf-print-hidden { display: none !important; }
1186
- .wf-print-block { display: block !important; }
1187
- }
1188
- }
1189
-
1190
- @layer utilities {
1191
- /* block — 块级显示 */
1192
- .wf-block {
1193
- display: block;
888
+ /* cover — 全屏覆盖 */
889
+ .wf-cover {
890
+ position: fixed;
891
+ inset: 0;
892
+ display: flex;
893
+ align-items: center;
894
+ justify-content: center;
895
+ z-index: var(--wf-z, var(--wf-cover-z));
1194
896
  }
1195
- @media (min-width: 640px) { .wf-block\@sm { display: block; } }
1196
- @media (min-width: 768px) { .wf-block\@md { display: block; } }
1197
- @media (min-width: 1024px) { .wf-block\@lg { display: block; } }
1198
897
  }
1199
898
 
1200
899
  @layer layout {
1201
- /* inline — 行内显示 */
1202
- .wf-inline {
1203
- display: inline;
1204
- }
900
+ /* position — 定位工具(属性名即类名——wf-relative + wf-absolute 是 CSS
901
+ 用户的零学习配对:容器 wf-relative,角标/覆盖层子项 wf-absolute。
902
+ fixed 视口覆盖用组合原语 wf-cover;sticky 用 wf-sticky) */
903
+ .wf-relative { position: relative; }
904
+ .wf-absolute { position: absolute; }
1205
905
  }
1206
906
 
1207
907
  @layer layout {
1208
- /* inline-block — 行内块 */
1209
- .wf-inline-block {
1210
- display: inline-block;
1211
- }
1212
- }
1213
-
1214
- @layer utilities {
1215
- /* flex — 弹性盒 display 工具(补全 display 族:block/inline/inline-block/contents/hidden/flex)
1216
- * 核心场景:响应式显隐的 flex 容器——`wf-hidden wf-flex@lg`(窄隐宽显且保持 flex 布局)。
1217
- * 不可用 wf-block@lg 替代:block 会覆盖 wf-stack 的 display:flex,
1218
- * 致 flex-direction/gap/mt-auto 全部静默失效(layouts-demo 侧栏 mt-auto 实测踩坑)。 */
1219
- .wf-flex {
1220
- display: flex;
1221
- }
1222
- @media (min-width: 640px) { .wf-flex\@sm { display: flex; } }
1223
- @media (min-width: 768px) { .wf-flex\@md { display: flex; } }
1224
- @media (min-width: 1024px) { .wf-flex\@lg { display: flex; } }
1225
-
1226
- @media (min-width: 640px) { .wf-flex@sm { display: flex; } }
1227
- @media (min-width: 768px) { .wf-flex@md { display: flex; } }
908
+ /* sticky — 粘性定位 */
909
+ .wf-sticky {
910
+ position: sticky;
911
+ top: var(--wf-offset, 0);
1228
912
  }
1229
-
1230
- @layer layout {
1231
- /* container — 内容宽度约束居中 */
1232
- /* width: 100% 必须:margin: 0 auto 在 flex 父中阻止 stretch(宽度=内容)
1233
- ——landing 特性区 404px 而非撑满 1100 容器的根因 */
1234
- .wf-container {
1235
- width: 100%;
1236
- max-width: var(--wf-max, 1200px);
1237
- margin: 0 auto;
1238
- padding: 0 var(--wf-gap, var(--wf-gap-lg));
1239
913
  }
914
+
915
+ @layer layout {
916
+ /* overflow — 溢出控制(属性根 + CSS 值词;全局滚动条样式见 _base.css) */
917
+ .wf-overflow-auto { overflow: auto; }
918
+ .wf-overflow-hidden { overflow: hidden; }
919
+ .wf-overflow-x { overflow-x: auto; }
1240
920
  }
1241
921
 
1242
922
  @layer layout {
1243
- /* contents — 容器抹除(子元素直接参与上层布局) */
1244
- .wf-contents {
1245
- display: contents;
923
+ /* safe-area — iOS 刘海屏/Home 条安全区工具(env() 未生效环境自动为 0) */
924
+ .wf-safe-bottom {
925
+ padding-bottom: env(safe-area-inset-bottom);
926
+ }
927
+ .wf-safe-top {
928
+ padding-top: env(safe-area-inset-top);
1246
929
  }
1247
930
  }
1248
931
 
@@ -1254,9 +937,17 @@ body.wf-dragging {
1254
937
  }
1255
938
  }
1256
939
 
940
+ @layer layout {
941
+ /* align-self — 弹性子项交叉轴对齐(消费侧 wf-self-* 缺口——容器内单元素对齐) */
942
+ .wf-self-start { align-self: flex-start; }
943
+ .wf-self-center { align-self: center; }
944
+ .wf-self-end { align-self: flex-end; }
945
+ .wf-self-stretch { align-self: stretch; }
946
+ }
947
+
1257
948
  @layer layout {
1258
949
  /* nowrap — 不换行(只管 flex-wrap——不定义 align-items,避免与
1259
- wf-stretch 等对齐工具叠加冲突:双份 CSS 下 nowrap 后置曾覆盖 stretch;
950
+ wf-items-* 对齐工具叠加冲突:双份 CSS 下 nowrap 后置曾覆盖 stretch;
1260
951
  L3:gap 默认值 :where() 零优先级) */
1261
952
  .wf-nowrap {
1262
953
  display: flex;
@@ -1268,135 +959,29 @@ body.wf-dragging {
1268
959
  }
1269
960
 
1270
961
  @layer layout {
1271
- /* min — flex 子项可收缩约束 */
962
+ /* min — flex 子项可收缩约束(flex 收缩坑标配:默认 min-width/height: auto
963
+ 会阻止子项收缩——内容溢出/撑破布局时加这类) */
1272
964
  .wf-shrink {
1273
965
  min-width: 0;
1274
966
  min-height: 0;
1275
967
  }
1276
- }
1277
-
1278
- @layer utilities {
1279
- /* 间距/尺寸工具类 — 全部引用 --wf-* Token,无硬编码
1280
- *
1281
- * 命名:wf-p(adding)/wf-m(argin)[x|y|t|b] + 刻度(xs sm md lg xl 2xl)
1282
- * 与 flex 原语协作:wf-gap-* 设置 --wf-gap 变量(stack/row/split 等读取)
1283
- */
1284
-
1285
- /* ── padding ── */
1286
- .wf-p-xs { padding: var(--wf-space-xs); }
1287
- .wf-p-sm { padding: var(--wf-space-sm); }
1288
- .wf-p-md { padding: var(--wf-space-md); }
1289
- .wf-p-lg { padding: var(--wf-space-lg); }
1290
- .wf-p-xl { padding: var(--wf-space-xl); }
1291
- .wf-p-2xl { padding: var(--wf-space-2xl); }
1292
-
1293
- /* ── padding: 水平/垂直 ── */
1294
- .wf-px-xs { padding-left: var(--wf-space-xs); padding-right: var(--wf-space-xs); }
1295
- .wf-px-sm { padding-left: var(--wf-space-sm); padding-right: var(--wf-space-sm); }
1296
- .wf-px-md { padding-left: var(--wf-space-md); padding-right: var(--wf-space-md); }
1297
- .wf-px-lg { padding-left: var(--wf-space-lg); padding-right: var(--wf-space-lg); }
1298
- .wf-px-xl { padding-left: var(--wf-space-xl); padding-right: var(--wf-space-xl); }
1299
- .wf-px-2xl { padding-left: var(--wf-space-2xl); padding-right: var(--wf-space-2xl); }
1300
-
1301
- .wf-py-xs { padding-top: var(--wf-space-xs); padding-bottom: var(--wf-space-xs); }
1302
- .wf-py-sm { padding-top: var(--wf-space-sm); padding-bottom: var(--wf-space-sm); }
1303
- .wf-py-md { padding-top: var(--wf-space-md); padding-bottom: var(--wf-space-md); }
1304
- .wf-py-lg { padding-top: var(--wf-space-lg); padding-bottom: var(--wf-space-lg); }
1305
- .wf-py-xl { padding-top: var(--wf-space-xl); padding-bottom: var(--wf-space-xl); }
1306
- .wf-py-2xl { padding-top: var(--wf-space-2xl); padding-bottom: var(--wf-space-2xl); }
1307
-
1308
- /* ── padding: 单侧顶/底(幽灵类防线抓出 wf-pt-md/wf-pb-md 误用——补全家族) ── */
1309
- .wf-pt-xs { padding-top: var(--wf-space-xs); }
1310
- .wf-pt-sm { padding-top: var(--wf-space-sm); }
1311
- .wf-pt-md { padding-top: var(--wf-space-md); }
1312
- .wf-pt-lg { padding-top: var(--wf-space-lg); }
1313
- .wf-pt-xl { padding-top: var(--wf-space-xl); }
1314
- .wf-pt-2xl { padding-top: var(--wf-space-2xl); }
1315
- .wf-pb-xs { padding-bottom: var(--wf-space-xs); }
1316
- .wf-pb-sm { padding-bottom: var(--wf-space-sm); }
1317
- .wf-pb-md { padding-bottom: var(--wf-space-md); }
1318
- .wf-pb-lg { padding-bottom: var(--wf-space-lg); }
1319
- .wf-pb-xl { padding-bottom: var(--wf-space-xl); }
1320
- .wf-pb-2xl { padding-bottom: var(--wf-space-2xl); }
1321
-
1322
- /* ── margin:重置 ── */
1323
- .wf-m-0 { margin: 0; }
1324
- .wf-p-0 { padding: 0; }
1325
-
1326
- /* ── margin(高频方向:top / bottom / 垂直) ── */
1327
- .wf-mt-xs { margin-top: var(--wf-space-xs); }
1328
- .wf-mt-sm { margin-top: var(--wf-space-sm); }
1329
- .wf-mt-md { margin-top: var(--wf-space-md); }
1330
- .wf-mt-lg { margin-top: var(--wf-space-lg); }
1331
- .wf-mt-xl { margin-top: var(--wf-space-xl); }
1332
- .wf-mt-2xl { margin-top: var(--wf-space-2xl); }
1333
-
1334
- .wf-mb-xs { margin-bottom: var(--wf-space-xs); }
1335
- .wf-mb-sm { margin-bottom: var(--wf-space-sm); }
1336
- .wf-mb-md { margin-bottom: var(--wf-space-md); }
1337
- .wf-mb-lg { margin-bottom: var(--wf-space-lg); }
1338
- .wf-mb-xl { margin-bottom: var(--wf-space-xl); }
1339
- .wf-mb-2xl { margin-bottom: var(--wf-space-2xl); }
1340
-
1341
- .wf-my-xs { margin-top: var(--wf-space-xs); margin-bottom: var(--wf-space-xs); }
1342
- .wf-my-sm { margin-top: var(--wf-space-sm); margin-bottom: var(--wf-space-sm); }
1343
- .wf-my-md { margin-top: var(--wf-space-md); margin-bottom: var(--wf-space-md); }
1344
- .wf-my-lg { margin-top: var(--wf-space-lg); margin-bottom: var(--wf-space-lg); }
1345
- .wf-my-xl { margin-top: var(--wf-space-xl); margin-bottom: var(--wf-space-xl); }
1346
- .wf-my-2xl { margin-top: var(--wf-space-2xl); margin-bottom: var(--wf-space-2xl); }
1347
-
1348
- /* ── margin: auto(居中) ── */
1349
- .wf-mx-auto { margin-left: auto; margin-right: auto; }
1350
-
1351
- /* ── margin: 左/右(间距体系对称——消费侧 ml-* 缺口) ── */
1352
- .wf-ml-none { margin-left: 0; }
1353
- .wf-ml-xs { margin-left: var(--wf-space-xs); }
1354
- .wf-ml-sm { margin-left: var(--wf-space-sm); }
1355
- .wf-ml-md { margin-left: var(--wf-space-md); }
1356
- .wf-ml-lg { margin-left: var(--wf-space-lg); }
1357
- .wf-ml-xl { margin-left: var(--wf-space-xl); }
1358
- .wf-ml-2xl { margin-left: var(--wf-space-2xl); }
1359
- .wf-ml-auto { margin-left: auto; }
1360
- .wf-mr-none { margin-right: 0; }
1361
- .wf-mr-xs { margin-right: var(--wf-space-xs); }
1362
- .wf-mr-sm { margin-right: var(--wf-space-sm); }
1363
- .wf-mr-md { margin-right: var(--wf-space-md); }
1364
- .wf-mr-lg { margin-right: var(--wf-space-lg); }
1365
- .wf-mr-xl { margin-right: var(--wf-space-xl); }
1366
- .wf-mr-2xl { margin-right: var(--wf-space-2xl); }
1367
- .wf-mr-auto { margin-right: auto; }
1368
- .wf-mt-none { margin-top: 0; }
1369
- .wf-mb-none { margin-bottom: 0; }
1370
- .wf-mx-none { margin-left: 0; margin-right: 0; }
1371
-
1372
- .wf-my-auto { margin-top: auto; margin-bottom: auto; }
1373
- .wf-mt-auto { margin-top: auto; } /* flex 列推底(侧栏 footer——曾写不存在类静默失效) */
1374
- .wf-mb-auto { margin-bottom: auto; }
1375
-
1376
- /* ── gap:直接设置 gap 属性(不设 --wf-gap 变量——变量会继承污染子孙:
1377
- 壳 root wf-gap-none 曾让 KPI grid 的 gap: var(--wf-gap) = 0 卡无间距) ── */
1378
- .wf-gap-none { gap: 0; }
1379
- .wf-gap-xs { gap: var(--wf-gap-xs); }
1380
- .wf-gap-sm { gap: var(--wf-gap-sm); }
1381
- .wf-gap-md { gap: var(--wf-gap-md); }
1382
- .wf-gap-lg { gap: var(--wf-gap-lg); }
1383
- .wf-gap-xl { gap: var(--wf-gap-xl); }
1384
- .wf-gap-2xl { gap: var(--wf-gap-2xl); }
1385
968
 
1386
- /* ── 尺寸 ── */
1387
- .wf-w-full { width: 100%; }
1388
- .wf-h-full { height: 100%; }
1389
- .wf-w-auto { width: auto; }
969
+ /* 单边版本(只需横向收缩的场景——属性名即类名) */
970
+ .wf-min-width-0 {
971
+ min-width: 0;
972
+ }
973
+ }
1390
974
 
1391
- /* ── 固定宽度阶梯(对齐 token 阶梯——卡片/面板/容器宽不再内联) ── */
1392
- .wf-w-xs { width: var(--wf-w-xs, 320px); }
1393
- .wf-w-sm { width: var(--wf-w-sm, 480px); }
1394
- .wf-w-md { width: var(--wf-w-md, 640px); }
1395
- .wf-w-lg { width: var(--wf-w-lg, 768px); }
1396
- .wf-w-xl { width: var(--wf-w-xl, 1024px); }
1397
- .wf-w-max { max-width: 100%; }
1398
- .wf-w-md-auto { width: 100%; }
1399
- @media (min-width: 768px) { .wf-w-md-auto { width: var(--wf-w-md, 640px); } }
975
+ @layer layout {
976
+ /* container — 内容宽度约束居中 */
977
+ /* width: 100% 必须:margin: 0 auto 在 flex 父中阻止 stretch(宽度=内容)
978
+ ——landing 特性区 404px 而非撑满 1100 容器的根因 */
979
+ .wf-container {
980
+ width: 100%;
981
+ max-width: var(--wf-max, 1200px);
982
+ margin: 0 auto;
983
+ padding: 0 var(--wf-gap, var(--wf-gap-lg));
984
+ }
1400
985
  }
1401
986
 
1402
987
  @layer layout {
@@ -1510,10 +1095,6 @@ body.wf-dragging {
1510
1095
  color: var(--wf-color-primary-text);
1511
1096
  }
1512
1097
 
1513
- .wf-nav-icon {
1514
- flex-shrink: 0;
1515
- display: inline-flex;
1516
- }
1517
1098
 
1518
1099
  /* ── 折叠态:图标-only 导航(配合 --wf-sidebar-width 收窄侧栏) ── */
1519
1100
  .wf-nav--collapsed .wf-nav-item {
@@ -1578,88 +1159,155 @@ body.wf-dragging {
1578
1159
  }
1579
1160
 
1580
1161
  @layer utilities {
1581
- /* 边框工具类 — 全部引用 --wf-border-width / --wf-color-border */
1582
- .wf-border { border: var(--wf-border-width) solid var(--wf-color-border); }
1583
- .wf-border-t { border-top: var(--wf-border-width) solid var(--wf-color-border); }
1584
- .wf-border-b { border-bottom: var(--wf-border-width) solid var(--wf-color-border); }
1585
- .wf-border-l { border-left: var(--wf-border-width) solid var(--wf-color-border); }
1586
- .wf-border-r { border-right: var(--wf-border-width) solid var(--wf-color-border); }
1162
+ /* surface — 基础面 + 面工具类(背景色/圆角/阴影——全部引用语义 Token) */
1163
+
1164
+ .wf-surface {
1165
+ border-radius: var(--wf-surface-radius);
1166
+ box-shadow: var(--wf-surface-shadow);
1167
+ background: var(--wf-surface-bg);
1587
1168
  }
1588
1169
 
1589
- @layer utilities {
1590
- /* 排版工具类 — 字号 / 色阶 / 字重 / 截断(零 CSS 用户自排版) */
1170
+ /* 平面表面(M4 表面语言——静态卡片/面板组合 wf-border 用:阴影仅抬升语义) */
1171
+ .wf-surface--flat {
1172
+ box-shadow: none;
1173
+ }
1591
1174
 
1592
- /* ── text-align ── */
1175
+ /* ── 背景色工具 — 引用语义 Token,免自定义 CSS ── */
1176
+ .wf-bg-secondary { background: var(--wf-color-bg-secondary); }
1177
+ .wf-bg-tertiary { background: var(--wf-color-bg-tertiary); }
1178
+ .wf-bg-primary { background: var(--wf-color-primary-bg); }
1179
+ .wf-bg-warning { background: var(--wf-color-warning-bg); }
1180
+ .wf-bg-error { background: var(--wf-color-error-bg); }
1181
+ .wf-bg-none { background: transparent; }
1593
1182
 
1594
- .wf-text-left {
1595
- text-align: left;
1183
+ /* ── 胶囊圆角(状态徽章/标签/色块) ── */
1184
+ .wf-pill { border-radius: 999px; }
1185
+
1186
+ /* ── 圆角工具 — 随 token --wf-radius-*(同名推导) ── */
1187
+ .wf-radius-sm { border-radius: var(--wf-radius-sm); }
1188
+ .wf-radius { border-radius: var(--wf-radius); }
1189
+ .wf-radius-md { border-radius: var(--wf-radius-md); }
1190
+ .wf-radius-lg { border-radius: var(--wf-radius-lg); }
1191
+
1192
+ /* ── 阴影工具 — 随 token --wf-shadow-*(同名推导;抬升语义见表面语言) ── */
1193
+ .wf-shadow { box-shadow: var(--wf-shadow); }
1194
+
1195
+ /* ── hover 抬升(Card/StatCard 可点击/悬停共用,阴影 + 上移 + 焦点环) ── */
1196
+ .wf-elevate {
1197
+ transition: box-shadow var(--wf-dur-fast) var(--wf-ease-out), transform var(--wf-dur-fast) var(--wf-ease-out);
1198
+ }
1199
+ .wf-elevate:hover {
1200
+ box-shadow: var(--wf-shadow-md);
1201
+ transform: translateY(-2px);
1202
+ }
1203
+ .wf-elevate:focus-visible {
1204
+ outline: none;
1205
+ box-shadow: var(--wf-shadow-md), var(--wf-focus-ring);
1596
1206
  }
1597
1207
 
1598
- .wf-text-center {
1599
- text-align: center;
1208
+ /* ── 面板入场:统一 scale+fade(面板族:dropdown/select/datepicker 从触发点下方弹出) ── */
1209
+ .wf-panel-in {
1210
+ animation: wf-panel-in var(--wf-dur-fast) var(--wf-ease-out);
1211
+ transform-origin: top center;
1600
1212
  }
1601
1213
 
1602
- .wf-text-right {
1603
- text-align: right;
1214
+ @keyframes wf-panel-in {
1215
+ from { opacity: 0; transform: translateY(-4px) scale(0.97); }
1216
+ to { opacity: 1; transform: translateY(0) scale(1); }
1217
+ }
1218
+
1219
+ /* ── 聊天气泡 ──
1220
+ * 用法:wf-bubble(对方/AI)+ wf-bubble--own(自己)
1221
+ * 行布局用 wf-row + wf-gap 覆盖;文字用 wf-pre-wrap 已内建
1222
+ */
1223
+ .wf-bubble {
1224
+ display: inline-block;
1225
+ max-width: 70%;
1226
+ padding: var(--wf-space-sm) var(--wf-space-md);
1227
+ border-radius: var(--wf-radius-md);
1228
+ background: var(--wf-color-bg-secondary);
1229
+ color: var(--wf-color-text);
1230
+ font-size: var(--wf-font-size-base);
1231
+ line-height: var(--wf-line-height);
1232
+ white-space: pre-wrap;
1233
+ word-break: break-word;
1234
+ }
1235
+
1236
+ .wf-bubble--own {
1237
+ background: var(--wf-color-primary);
1238
+ color: var(--wf-color-on-brand);
1239
+ border-bottom-right-radius: var(--wf-radius-sm);
1240
+ }
1241
+
1242
+ .wf-bubble--ai {
1243
+ background: var(--wf-color-primary-bg);
1244
+ border: var(--wf-border-width) solid var(--wf-color-border-light);
1245
+ border-bottom-left-radius: var(--wf-radius-sm);
1246
+ }
1247
+ }
1248
+
1249
+ @layer utilities {
1250
+ /* 边框工具类 — 全部引用 --wf-border-width / --wf-color-border(方向全词) */
1251
+ .wf-border { border: var(--wf-border-width) solid var(--wf-color-border); }
1252
+ .wf-border-top { border-top: var(--wf-border-width) solid var(--wf-color-border); }
1253
+ .wf-border-bottom { border-bottom: var(--wf-border-width) solid var(--wf-color-border); }
1254
+ .wf-border-left { border-left: var(--wf-border-width) solid var(--wf-color-border); }
1255
+ .wf-border-right { border-right: var(--wf-border-width) solid var(--wf-color-border); }
1256
+ .wf-border-none { border: none; }
1604
1257
  }
1605
1258
 
1606
- /* ── 字号 ── */
1259
+ @layer utilities {
1260
+ /* 排版工具类(design/layout-naming.md 词根分域——过载歼灭):
1261
+ * wf-font-<刻度> 字号(font-size ← --wf-font-size-*)
1262
+ * wf-medium/semibold/bold 字重(裸值词)
1263
+ * wf-text-<色> 文字颜色(语义 Token——含 on-brand 填充上文字)
1264
+ * wf-text-<方向> 文本对齐(text-align)
1265
+ * wf-tracking-* 字距(排版术语 = letter-spacing)
1266
+ */
1607
1267
 
1608
- .wf-text-xs { font-size: var(--wf-font-size-xs); }
1609
- .wf-text-sm { font-size: var(--wf-font-size-sm); }
1610
- .wf-text-base { font-size: var(--wf-font-size-base); }
1611
- .wf-text-lg { font-size: var(--wf-font-size-lg); }
1612
- .wf-text-xl { font-size: var(--wf-font-size-xl); }
1613
- .wf-text-2xl { font-size: var(--wf-font-size-2xl); }
1614
- .wf-text-3xl { font-size: var(--wf-font-size-3xl); }
1615
- .wf-text-4xl { font-size: var(--wf-font-size-4xl); }
1616
- .wf-text-5xl { font-size: var(--wf-font-size-5xl); }
1617
- .wf-text-display { font-size: var(--wf-font-size-display); }
1268
+ /* ── 文本对齐(text-align——自然读法保留) ── */
1269
+ .wf-text-left { text-align: left; }
1270
+ .wf-text-center { text-align: center; }
1271
+ .wf-text-right { text-align: right; }
1618
1272
 
1619
- /* ── 数字等宽(统计/表格数值防宽度抖动) ── */
1273
+ /* ── 字号(font 属性族) ── */
1274
+ .wf-font-xs { font-size: var(--wf-font-size-xs); }
1275
+ .wf-font-sm { font-size: var(--wf-font-size-sm); }
1276
+ .wf-font-base { font-size: var(--wf-font-size-base); }
1277
+ .wf-font-lg { font-size: var(--wf-font-size-lg); }
1278
+ .wf-font-2xl { font-size: var(--wf-font-size-2xl); }
1279
+ .wf-font-3xl { font-size: var(--wf-font-size-3xl); }
1280
+ .wf-font-4xl { font-size: var(--wf-font-size-4xl); }
1620
1281
 
1282
+ /* ── 数字等宽(统计/表格数值防宽度抖动) ── */
1621
1283
  .wf-nums {
1622
1284
  font-variant-numeric: var(--wf-nums);
1623
1285
  }
1624
1286
 
1625
- /* ── 色阶 ── */
1626
-
1287
+ /* ── 文字色(语义唯一名——随 token 用 error;浅底可读 700 级) ── */
1627
1288
  .wf-text-secondary { color: var(--wf-color-text-secondary); }
1628
1289
  .wf-text-tertiary { color: var(--wf-color-text-tertiary); }
1629
- .wf-text-disabled { color: var(--wf-color-text-disabled); }
1630
- .wf-text-brand { color: var(--wf-color-primary-text); } /* 兼容别名 → wf-text-primary */
1631
1290
  .wf-text-primary { color: var(--wf-color-primary-text); }
1632
1291
  .wf-text-success { color: var(--wf-color-success-text); }
1633
1292
  .wf-text-warning { color: var(--wf-color-warning-text); }
1634
1293
  .wf-text-error { color: var(--wf-color-error-text); }
1635
- .wf-text-info { color: var(--wf-color-info-text); }
1636
-
1637
- /* ── 字重 ── */
1638
-
1639
- .wf-text-medium { font-weight: var(--wf-font-weight-medium); }
1640
- .wf-text-semibold { font-weight: var(--wf-font-weight-semibold); }
1641
- .wf-text-bold { font-weight: var(--wf-font-weight-bold); }
1642
1294
 
1643
- /* ── 行高 ── */
1295
+ /* ── 填充上的文字色(实心品牌/警告底——对比度保障) ── */
1296
+ .wf-text-on-brand { color: var(--wf-color-on-brand); }
1297
+ .wf-text-on-warning { color: var(--wf-color-on-warning); }
1644
1298
 
1645
- .wf-leading-tight { line-height: var(--wf-line-height-tight); }
1646
- .wf-leading-base { line-height: var(--wf-line-height); }
1647
- .wf-leading-relaxed { line-height: var(--wf-line-height-relaxed); }
1299
+ /* ── 字重(裸值词) ── */
1300
+ .wf-medium { font-weight: var(--wf-font-weight-medium); }
1301
+ .wf-semibold { font-weight: var(--wf-font-weight-semibold); }
1302
+ .wf-bold { font-weight: var(--wf-font-weight-bold); }
1648
1303
 
1649
- /* ── 字距 ── */
1650
-
1651
- .wf-tracking-normal { letter-spacing: var(--wf-letter-spacing); }
1304
+ /* ── 字距(排版术语 tracking = letter-spacing) ── */
1652
1305
  .wf-tracking-wide { letter-spacing: var(--wf-letter-spacing-wide); }
1653
- .wf-tracking-wider { letter-spacing: var(--wf-letter-spacing-wider); }
1654
-
1655
- /* ── 文本变换 ── */
1656
1306
 
1307
+ /* ── 文本变换(裸值词) ── */
1657
1308
  .wf-uppercase { text-transform: uppercase; }
1658
- .wf-lowercase { text-transform: lowercase; }
1659
- .wf-capitalize { text-transform: capitalize; }
1660
1309
 
1661
1310
  /* ── 换行/折行 ── */
1662
-
1663
1311
  .wf-pre-wrap {
1664
1312
  white-space: pre-wrap;
1665
1313
  word-break: break-word;
@@ -1675,138 +1323,136 @@ body.wf-dragging {
1675
1323
  }
1676
1324
 
1677
1325
  /* ── 截断 ── */
1678
-
1679
1326
  .wf-truncate {
1680
1327
  overflow: hidden;
1681
1328
  text-overflow: ellipsis;
1682
1329
  white-space: nowrap;
1683
1330
  }
1684
-
1685
- .wf-line-clamp-2 {
1686
- display: -webkit-box;
1687
- -webkit-line-clamp: 2;
1688
- -webkit-box-orient: vertical;
1689
- overflow: hidden;
1690
- }
1691
-
1692
- .wf-line-clamp-3 {
1693
- display: -webkit-box;
1694
- -webkit-line-clamp: 3;
1695
- -webkit-box-orient: vertical;
1696
- overflow: hidden;
1697
- }
1698
-
1699
- /* 语义文字色(消费侧 wf-text-danger 缺口——错误/危险操作文字) */
1700
- .wf-text-danger { color: var(--wf-color-error-text); }
1701
1331
  }
1702
1332
 
1703
1333
  @layer utilities {
1704
- /* prose — 富文本正文排版(文章/博客/文档渲染,一个类包全部)
1334
+ /* 间距/尺寸工具类 — 全部引用 --wf-* Token,无硬编码
1335
+ *
1336
+ * 命名规则(design/layout-naming.md):属性根全名 + 物理方向全词 + 标尺值
1337
+ * wf-padding[-{x,y,top,bottom}]-<刻度> padding(刻度 ← --wf-space-*)
1338
+ * wf-margin[-{x,y,top,bottom,left}]-<刻度> margin(刻度 ← --wf-space-*)
1339
+ * wf-gap-<刻度> 直接设 gap 属性
1340
+ * 刻度 = none|xs|sm|md|lg|xl(none = 零/取消的唯一形态)
1705
1341
  *
1706
- * 用法:<article class="wf-prose">…markdown/富文本 HTML…</article>
1707
- * 覆盖:h2-h4 / p / ul / ol / li / blockquote / pre / code / a / img / table / hr / strong
1342
+ * 类面随消费证据生长(缺口审计机制化——layout-inventory.test.ts)。
1708
1343
  */
1709
1344
 
1710
- .wf-prose {
1711
- font-size: var(--wf-font-size-base);
1712
- line-height: var(--wf-line-height-relaxed);
1713
- color: var(--wf-color-text);
1714
- }
1715
-
1716
- .wf-prose h2 {
1717
- font-size: var(--wf-font-size-2xl);
1718
- font-weight: var(--wf-font-weight-semibold);
1719
- line-height: var(--wf-line-height-tight);
1720
- margin: var(--wf-space-xl) 0 var(--wf-space-md);
1721
- }
1722
-
1723
- .wf-prose h3 {
1724
- font-size: var(--wf-font-size-xl);
1725
- font-weight: var(--wf-font-weight-semibold);
1726
- line-height: var(--wf-line-height-tight);
1727
- margin: var(--wf-space-lg) 0 var(--wf-space-sm);
1728
- }
1729
-
1730
- .wf-prose h4 {
1731
- font-size: var(--wf-font-size-base);
1732
- font-weight: var(--wf-font-weight-semibold);
1733
- margin: var(--wf-space-md) 0 var(--wf-space-sm);
1734
- }
1735
-
1736
- .wf-prose p {
1737
- margin: 0 0 var(--wf-space-md);
1738
- line-height: var(--wf-line-height-relaxed);
1739
- }
1740
-
1741
- .wf-prose ul,
1742
- .wf-prose ol {
1743
- margin: 0 0 var(--wf-space-md);
1744
- padding-left: var(--wf-space-lg);
1745
- }
1746
-
1747
- .wf-prose li {
1748
- margin: var(--wf-space-xs) 0;
1749
- line-height: var(--wf-line-height-relaxed);
1750
- }
1345
+ /* ── padding ── */
1346
+ .wf-padding-xs { padding: var(--wf-space-xs); }
1347
+ .wf-padding-sm { padding: var(--wf-space-sm); }
1348
+ .wf-padding-md { padding: var(--wf-space-md); }
1349
+ .wf-padding-lg { padding: var(--wf-space-lg); }
1350
+ .wf-padding-xl { padding: var(--wf-space-xl); }
1351
+
1352
+ /* ── padding: 轴 ── */
1353
+ .wf-padding-x-sm { padding-left: var(--wf-space-sm); padding-right: var(--wf-space-sm); }
1354
+ .wf-padding-x-md { padding-left: var(--wf-space-md); padding-right: var(--wf-space-md); }
1355
+
1356
+ .wf-padding-y-xs { padding-top: var(--wf-space-xs); padding-bottom: var(--wf-space-xs); }
1357
+ .wf-padding-y-sm { padding-top: var(--wf-space-sm); padding-bottom: var(--wf-space-sm); }
1358
+ .wf-padding-y-md { padding-top: var(--wf-space-md); padding-bottom: var(--wf-space-md); }
1359
+ .wf-padding-y-lg { padding-top: var(--wf-space-lg); padding-bottom: var(--wf-space-lg); }
1360
+
1361
+ /* ── padding: 单侧 ── */
1362
+ .wf-padding-top-sm { padding-top: var(--wf-space-sm); }
1363
+ .wf-padding-left-sm { padding-left: var(--wf-space-sm); }
1364
+ .wf-padding-bottom-xs { padding-bottom: var(--wf-space-xs); }
1365
+ .wf-padding-bottom-sm { padding-bottom: var(--wf-space-sm); }
1366
+ .wf-padding-bottom-md { padding-bottom: var(--wf-space-md); }
1367
+
1368
+ /* ── margin:重置(零值唯一形态 none) ── */
1369
+ .wf-margin-none { margin: 0; }
1370
+
1371
+ /* ── margin: top / bottom ── */
1372
+ .wf-margin-top-none { margin-top: 0; }
1373
+ .wf-margin-top-xs { margin-top: var(--wf-space-xs); }
1374
+ .wf-margin-top-sm { margin-top: var(--wf-space-sm); }
1375
+ .wf-margin-top-md { margin-top: var(--wf-space-md); }
1376
+
1377
+ .wf-margin-bottom-xs { margin-bottom: var(--wf-space-xs); }
1378
+ .wf-margin-bottom-sm { margin-bottom: var(--wf-space-sm); }
1379
+ .wf-margin-bottom-md { margin-bottom: var(--wf-space-md); }
1380
+ .wf-margin-bottom-lg { margin-bottom: var(--wf-space-lg); }
1381
+
1382
+ /* ── margin: left / x 轴 ── */
1383
+ .wf-margin-left-xs { margin-left: var(--wf-space-xs); }
1384
+ .wf-margin-left-sm { margin-left: var(--wf-space-sm); }
1385
+ .wf-margin-x-auto { margin-left: auto; margin-right: auto; }
1751
1386
 
1752
- .wf-prose blockquote {
1753
- margin: 0 0 var(--wf-space-md);
1754
- padding: var(--wf-space-xs) var(--wf-space-md);
1755
- border-left: 3px solid var(--wf-color-primary);
1756
- background: var(--wf-color-primary-bg);
1757
- border-radius: var(--wf-radius);
1758
- color: var(--wf-color-text-secondary);
1759
- }
1387
+ /* ── gap:直接设置 gap 属性(不设 --wf-gap 变量——变量会继承污染子孙:
1388
+ 壳 root wf-gap-none 曾让 KPI grid 的 gap: var(--wf-gap) = 0 卡无间距) ── */
1389
+ .wf-gap-none { gap: 0; }
1390
+ .wf-gap-xs { gap: var(--wf-gap-xs); }
1391
+ .wf-gap-sm { gap: var(--wf-gap-sm); }
1392
+ .wf-gap-md { gap: var(--wf-gap-md); }
1393
+ .wf-gap-lg { gap: var(--wf-gap-lg); }
1394
+ .wf-gap-xl { gap: var(--wf-gap-xl); }
1760
1395
 
1761
- .wf-prose pre {
1762
- margin: 0 0 var(--wf-space-md);
1763
- padding: var(--wf-space-md);
1764
- background: var(--wf-color-bg-tertiary);
1765
- border: var(--wf-border-width) solid var(--wf-color-border);
1766
- border-radius: var(--wf-radius);
1767
- overflow-x: auto;
1768
- white-space: pre;
1396
+ /* ── 尺寸 ── */
1397
+ .wf-width-full { width: 100%; }
1398
+ .wf-width-sm { width: var(--wf-w-sm, 480px); }
1399
+ .wf-height-full { height: 100%; }
1769
1400
  }
1770
1401
 
1771
- .wf-prose code {
1772
- background: var(--wf-color-bg-tertiary);
1773
- padding: 2px 6px;
1774
- border-radius: var(--wf-radius-sm);
1402
+ @layer utilities {
1403
+ /* hidden — 隐藏元素(响应式显隐唯一模式:`wf-hidden wf-flex@lg` 窄隐宽显) */
1404
+ .wf-hidden {
1405
+ display: none;
1775
1406
  }
1407
+ @media (min-width: 1024px) { .wf-hidden\@lg { display: none; } }
1776
1408
 
1777
- .wf-prose pre code {
1778
- background: none;
1779
- padding: 0;
1409
+ /* dim — 视觉淡化(运行中/历史态/次要操作) */
1410
+ .wf-dim {
1411
+ opacity: 0.7;
1780
1412
  }
1781
1413
 
1782
- .wf-prose a {
1783
- color: var(--wf-color-primary-text);
1784
- text-decoration: none;
1414
+ /* cursor — 交互指针(裸值词) */
1415
+ .wf-pointer { cursor: pointer; }
1785
1416
  }
1786
1417
 
1787
- .wf-prose a:hover {
1788
- text-decoration: underline;
1418
+ @layer utilities {
1419
+ /* block — 块级显示 */
1420
+ .wf-block {
1421
+ display: block;
1789
1422
  }
1790
-
1791
- .wf-prose img {
1792
- max-width: 100%;
1793
- border-radius: var(--wf-radius-md);
1794
1423
  }
1795
1424
 
1796
- .wf-prose hr {
1797
- margin: var(--wf-space-lg) 0;
1425
+ @layer utilities {
1426
+ /* flex — 弹性盒 display 工具(补全 display 族:block/hidden/flex)
1427
+ * 核心场景:响应式显隐的 flex 容器——`wf-hidden wf-flex@lg`(窄隐宽显且保持 flex 布局)。
1428
+ * 不可用 wf-block@lg 替代:block 会覆盖 wf-stack 的 display:flex,
1429
+ * 致 flex-direction/gap 全部静默失效(layouts-demo 侧栏 mt-auto 实测踩坑)。
1430
+ * 注意:@ 选择器必须转义(\.wf-flex\@lg——未转义 @ 是非法选择器,整条规则被丢弃) */
1431
+ .wf-flex {
1432
+ display: flex;
1798
1433
  }
1799
-
1800
- .wf-prose strong {
1801
- font-weight: var(--wf-font-weight-semibold);
1434
+ @media (min-width: 640px) { .wf-flex\@sm { display: flex; } }
1435
+ @media (min-width: 1024px) { .wf-flex\@lg { display: flex; } }
1802
1436
  }
1803
1437
 
1804
- .wf-prose > :first-child {
1805
- margin-top: 0;
1438
+ @layer layout {
1439
+ /* popup — 浮层基类(usePopup.portal 自动附加;Modal/Drawer 等手动浮层可选用)
1440
+ *
1441
+ * 宽度视口 clamp:任何浮层默认不横向溢出(375px 屏也能完整操作)。
1442
+ * usePopup 已内联 maxWidth;本类兜底组件手动引用场景(audit 规则的目标选择器)。
1443
+ */
1444
+ .wf-popup {
1445
+ max-width: min(var(--wf-popup-max, 480px), calc(100vw - 32px));
1446
+ box-sizing: border-box;
1806
1447
  }
1807
1448
 
1808
- .wf-prose > :last-child {
1809
- margin-bottom: 0;
1449
+ /* usePopup mask 模式遮罩:全屏 fixed,z-index 低于面板(overlay=80 < popover=120),
1450
+ * 模态语义阻断页面交互;点击遮罩关闭(maskClosable 门控在组件层) */
1451
+ .wf-popup-mask {
1452
+ position: fixed;
1453
+ inset: 0;
1454
+ z-index: var(--wf-z-overlay);
1455
+ background: var(--wf-overlay);
1810
1456
  }
1811
1457
  }
1812
1458
  @layer components {
@@ -2542,6 +2188,13 @@ body.wf-dragging {
2542
2188
  .wf-autocomplete--disabled { opacity: 0.6; cursor: not-allowed; }
2543
2189
  .wf-autocomplete--disabled input { cursor: not-allowed; }
2544
2190
 
2191
+ /* 错误文案(F2 输入类基线——wf-input-err 同 Input——2027-XX 补齐) */
2192
+ .wf-autocomplete .wf-input-err {
2193
+ color: var(--wf-color-error-text);
2194
+ font-size: var(--wf-font-size-xs);
2195
+ margin-top: 4px;
2196
+ }
2197
+
2545
2198
  /* weifuwu/components — Avatar */
2546
2199
 
2547
2200
  .wf-avatar {
@@ -3344,7 +2997,8 @@ body.wf-dragging {
3344
2997
  border-radius: var(--wf-radius-sm);
3345
2998
  font-size: var(--wf-font-size-xs);
3346
2999
  pointer-events: none;
3347
- transform: translate(-50%, -100%);
3000
+ /* 定位由 openPopup 内核 computePos 完成(placement top + 水平居中 + gap 8)——
3001
+ * 不再 transform 双重偏移(旧 usePopup 自定位残留——tooltip 漂移一面板高/半宽) */
3348
3002
  white-space: nowrap;
3349
3003
  }
3350
3004