@icen.ai/ui 0.9.0 → 0.11.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 (431) hide show
  1. package/AGENTS.md +82 -254
  2. package/LICENSE +21 -0
  3. package/README.md +60 -96
  4. package/dist/base.css +258 -188
  5. package/dist/behaviors/accordion.mjs +8 -8
  6. package/dist/behaviors/ai-branch.d.mts +1 -1
  7. package/dist/behaviors/ai-branch.mjs +1011 -94
  8. package/dist/behaviors/ai-chat.d.mts +9 -9
  9. package/dist/behaviors/ai-chat.mjs +1122 -169
  10. package/dist/behaviors/ai-composer.d.mts +47 -15
  11. package/dist/behaviors/ai-composer.mjs +2018 -534
  12. package/dist/behaviors/ai-core.d.mts +1 -1
  13. package/dist/behaviors/ai-core.mjs +1017 -107
  14. package/dist/behaviors/ai-diff.mjs +1020 -127
  15. package/dist/behaviors/ai-feedback.d.mts +1 -1
  16. package/dist/behaviors/ai-feedback.mjs +1036 -126
  17. package/dist/behaviors/ai-panel.d.mts +10 -10
  18. package/dist/behaviors/ai-panel.mjs +1285 -266
  19. package/dist/behaviors/ai-provider.d.mts +1 -1
  20. package/dist/behaviors/ai-provider.mjs +1004 -101
  21. package/dist/behaviors/ai-threads.d.mts +1 -1
  22. package/dist/behaviors/ai-threads.mjs +1069 -154
  23. package/dist/behaviors/ai-tool.d.mts +3 -3
  24. package/dist/behaviors/ai-tool.mjs +2087 -413
  25. package/dist/behaviors/ai-tools.d.mts +89 -16
  26. package/dist/behaviors/ai-tools.mjs +5365 -380
  27. package/dist/behaviors/autocomplete.d.mts +53 -0
  28. package/dist/behaviors/autocomplete.mjs +1601 -0
  29. package/dist/behaviors/back-top.d.mts +1 -1
  30. package/dist/behaviors/back-top.mjs +952 -14
  31. package/dist/behaviors/carousel.d.mts +1 -1
  32. package/dist/behaviors/carousel.mjs +914 -12
  33. package/dist/behaviors/cascader.d.mts +48 -0
  34. package/dist/behaviors/cascader.mjs +1867 -0
  35. package/dist/behaviors/charts.d.mts +72 -8
  36. package/dist/behaviors/charts.mjs +1953 -272
  37. package/dist/behaviors/code-block.d.mts +36 -0
  38. package/dist/behaviors/code-block.mjs +1619 -0
  39. package/dist/behaviors/command-palette.d.mts +9 -6
  40. package/dist/behaviors/command-palette.mjs +164 -62
  41. package/dist/behaviors/context-menu.d.mts +10 -9
  42. package/dist/behaviors/context-menu.mjs +1113 -44
  43. package/dist/behaviors/controls.d.mts +21 -21
  44. package/dist/behaviors/controls.mjs +1024 -134
  45. package/dist/behaviors/copy.d.mts +21 -2
  46. package/dist/behaviors/copy.mjs +1207 -42
  47. package/dist/behaviors/datatable.d.mts +55 -5
  48. package/dist/behaviors/datatable.mjs +2033 -212
  49. package/dist/behaviors/date-picker.d.mts +0 -1
  50. package/dist/behaviors/date-picker.mjs +1341 -293
  51. package/dist/behaviors/design.d.mts +54 -0
  52. package/dist/behaviors/design.mjs +109 -0
  53. package/dist/behaviors/dropdown.d.mts +5 -6
  54. package/dist/behaviors/dropdown.mjs +262 -110
  55. package/dist/behaviors/events.d.mts +127 -10
  56. package/dist/behaviors/events.mjs +58 -3
  57. package/dist/behaviors/feedback.d.mts +30 -0
  58. package/dist/behaviors/feedback.mjs +296 -0
  59. package/dist/behaviors/focus.d.mts +8 -0
  60. package/dist/behaviors/focus.mjs +24 -0
  61. package/dist/behaviors/form-validate.d.mts +111 -0
  62. package/dist/behaviors/form-validate.mjs +1746 -0
  63. package/dist/behaviors/i18n.d.mts +790 -0
  64. package/dist/behaviors/i18n.mjs +1713 -0
  65. package/dist/behaviors/icons.d.mts +93 -0
  66. package/dist/behaviors/icons.mjs +113 -0
  67. package/dist/behaviors/input.d.mts +9 -1
  68. package/dist/behaviors/input.mjs +1059 -60
  69. package/dist/behaviors/kb-access.d.mts +3 -3
  70. package/dist/behaviors/kb-access.mjs +2135 -239
  71. package/dist/behaviors/kb-acl.d.mts +8 -8
  72. package/dist/behaviors/kb-acl.mjs +1120 -179
  73. package/dist/behaviors/kb-answer.d.mts +2 -2
  74. package/dist/behaviors/kb-answer.mjs +2120 -435
  75. package/dist/behaviors/kb-audit.d.mts +3 -3
  76. package/dist/behaviors/kb-audit.mjs +1077 -154
  77. package/dist/behaviors/kb-canvas.d.mts +3 -3
  78. package/dist/behaviors/kb-canvas.mjs +1101 -177
  79. package/dist/behaviors/kb-chain.d.mts +2 -2
  80. package/dist/behaviors/kb-chain.mjs +1023 -100
  81. package/dist/behaviors/kb-checkpoint.d.mts +3 -3
  82. package/dist/behaviors/kb-checkpoint.mjs +1320 -169
  83. package/dist/behaviors/kb-chunks.d.mts +2 -2
  84. package/dist/behaviors/kb-chunks.mjs +1153 -213
  85. package/dist/behaviors/kb-citation.d.mts +3 -3
  86. package/dist/behaviors/kb-citation.mjs +1221 -185
  87. package/dist/behaviors/kb-clarify.d.mts +2 -2
  88. package/dist/behaviors/kb-clarify.mjs +1059 -130
  89. package/dist/behaviors/kb-conflict.d.mts +2 -2
  90. package/dist/behaviors/kb-conflict.mjs +1042 -119
  91. package/dist/behaviors/kb-connector.d.mts +2 -2
  92. package/dist/behaviors/kb-connector.mjs +1105 -176
  93. package/dist/behaviors/kb-core.d.mts +7 -2
  94. package/dist/behaviors/kb-core.mjs +1078 -162
  95. package/dist/behaviors/kb-eval.d.mts +2 -2
  96. package/dist/behaviors/kb-eval.mjs +1977 -144
  97. package/dist/behaviors/kb-explain.d.mts +3 -3
  98. package/dist/behaviors/kb-explain.mjs +1037 -104
  99. package/dist/behaviors/kb-filter.d.mts +2 -2
  100. package/dist/behaviors/kb-filter.mjs +2014 -178
  101. package/dist/behaviors/kb-gap.d.mts +3 -3
  102. package/dist/behaviors/kb-gap.mjs +1044 -121
  103. package/dist/behaviors/kb-hittest.d.mts +3 -3
  104. package/dist/behaviors/kb-hittest.mjs +1095 -151
  105. package/dist/behaviors/kb-metadata.mjs +1058 -130
  106. package/dist/behaviors/kb-passage.d.mts +4 -4
  107. package/dist/behaviors/kb-passage.mjs +1102 -161
  108. package/dist/behaviors/kb-pipeline.d.mts +4 -4
  109. package/dist/behaviors/kb-pipeline.mjs +1083 -162
  110. package/dist/behaviors/kb-qa.mjs +1089 -160
  111. package/dist/behaviors/kb-rerank.d.mts +2 -2
  112. package/dist/behaviors/kb-rerank.mjs +1048 -114
  113. package/dist/behaviors/kb-retrieval.d.mts +2 -2
  114. package/dist/behaviors/kb-retrieval.mjs +2079 -226
  115. package/dist/behaviors/kb-review.d.mts +2 -2
  116. package/dist/behaviors/kb-review.mjs +1996 -159
  117. package/dist/behaviors/kb-sandbox.d.mts +3 -3
  118. package/dist/behaviors/kb-sandbox.mjs +1033 -105
  119. package/dist/behaviors/kb-segment.d.mts +2 -2
  120. package/dist/behaviors/kb-segment.mjs +1112 -179
  121. package/dist/behaviors/kb-select.d.mts +24 -0
  122. package/dist/behaviors/kb-select.mjs +1995 -0
  123. package/dist/behaviors/kb-sources.d.mts +3 -3
  124. package/dist/behaviors/kb-sources.mjs +1085 -170
  125. package/dist/behaviors/kb-sql.d.mts +3 -3
  126. package/dist/behaviors/kb-sql.mjs +1144 -226
  127. package/dist/behaviors/kb-trace.d.mts +3 -3
  128. package/dist/behaviors/kb-trace.mjs +1051 -131
  129. package/dist/behaviors/kb-visibility.d.mts +2 -2
  130. package/dist/behaviors/kb-visibility.mjs +1087 -158
  131. package/dist/behaviors/kb-who-can.d.mts +2 -2
  132. package/dist/behaviors/kb-who-can.mjs +1980 -137
  133. package/dist/behaviors/mentions.d.mts +93 -0
  134. package/dist/behaviors/mentions.mjs +2153 -0
  135. package/dist/behaviors/modal.d.mts +4 -3
  136. package/dist/behaviors/modal.mjs +1056 -33
  137. package/dist/behaviors/nav.d.mts +1 -1
  138. package/dist/behaviors/nav.mjs +6 -6
  139. package/dist/behaviors/notification.d.mts +16 -8
  140. package/dist/behaviors/notification.mjs +1629 -268
  141. package/dist/behaviors/panel.d.mts +4 -0
  142. package/dist/behaviors/panel.mjs +995 -0
  143. package/dist/behaviors/popover.d.mts +28 -5
  144. package/dist/behaviors/popover.mjs +225 -24
  145. package/dist/behaviors/scroll-area.d.mts +17 -0
  146. package/dist/behaviors/scroll-area.mjs +59 -0
  147. package/dist/behaviors/select.d.mts +5 -2
  148. package/dist/behaviors/select.mjs +1416 -117
  149. package/dist/behaviors/sidebar.d.mts +1 -1
  150. package/dist/behaviors/sidebar.mjs +13 -13
  151. package/dist/behaviors/slider.d.mts +1 -1
  152. package/dist/behaviors/slider.mjs +12 -12
  153. package/dist/behaviors/split-pane.d.mts +1 -1
  154. package/dist/behaviors/split-pane.mjs +9 -7
  155. package/dist/behaviors/suggestions.d.mts +27 -0
  156. package/dist/behaviors/suggestions.mjs +1090 -0
  157. package/dist/behaviors/svg-parse.d.mts +14 -0
  158. package/dist/behaviors/svg-parse.mjs +37 -0
  159. package/dist/behaviors/tabs.d.mts +2 -2
  160. package/dist/behaviors/tabs.mjs +35 -25
  161. package/dist/behaviors/tag-input.d.mts +23 -5
  162. package/dist/behaviors/tag-input.mjs +1360 -104
  163. package/dist/behaviors/theme-switcher.d.mts +24 -0
  164. package/dist/behaviors/theme-switcher.mjs +1996 -0
  165. package/dist/behaviors/theme.d.mts +15 -8
  166. package/dist/behaviors/theme.mjs +406 -30
  167. package/dist/behaviors/toast.d.mts +24 -25
  168. package/dist/behaviors/toast.mjs +1267 -88
  169. package/dist/behaviors/tooltip.d.mts +4 -0
  170. package/dist/behaviors/tooltip.mjs +378 -0
  171. package/dist/behaviors/tree-select.d.mts +69 -0
  172. package/dist/behaviors/tree-select.mjs +1921 -0
  173. package/dist/behaviors/tree.d.mts +1 -1
  174. package/dist/behaviors/tree.mjs +18 -18
  175. package/dist/behaviors/upload.d.mts +3 -2
  176. package/dist/behaviors/upload.mjs +1077 -66
  177. package/dist/behaviors/url-safety.d.mts +8 -0
  178. package/dist/behaviors/url-safety.mjs +11 -0
  179. package/dist/cli.mjs +5 -6
  180. package/dist/components/accordion.d.mts +2 -0
  181. package/dist/components/ai-branch.d.mts +2 -0
  182. package/dist/components/ai-chat.css +682 -582
  183. package/dist/components/ai-chat.d.mts +2 -0
  184. package/dist/components/ai-composer.d.mts +2 -0
  185. package/dist/components/ai-context.d.mts +2 -0
  186. package/dist/components/ai-context.mjs +1 -0
  187. package/dist/components/ai-diff.css +153 -132
  188. package/dist/components/ai-diff.d.mts +2 -0
  189. package/dist/components/ai-feedback.d.mts +2 -0
  190. package/dist/components/ai-files.d.mts +2 -0
  191. package/dist/components/ai-message.d.mts +2 -0
  192. package/dist/components/ai-panel.css +353 -343
  193. package/dist/components/ai-reasoning.d.mts +2 -0
  194. package/dist/components/ai-subagent.d.mts +2 -0
  195. package/dist/components/ai-subagent.mjs +1 -0
  196. package/dist/components/ai-threads.d.mts +2 -0
  197. package/dist/components/ai-todo.d.mts +2 -0
  198. package/dist/components/ai-todo.mjs +1 -0
  199. package/dist/components/ai-tool-call.d.mts +2 -0
  200. package/dist/components/ai-tool-call.mjs +1 -0
  201. package/dist/components/ai-tool.css +397 -242
  202. package/dist/components/ai-usage.d.mts +2 -0
  203. package/dist/components/alert.d.mts +2 -0
  204. package/dist/components/autocomplete.css +61 -0
  205. package/dist/components/autocomplete.d.mts +2 -0
  206. package/dist/components/autocomplete.mjs +3 -0
  207. package/dist/components/avatar.d.mts +2 -0
  208. package/dist/components/back-top.css +74 -40
  209. package/dist/components/back-top.d.mts +2 -0
  210. package/dist/components/badge.css +44 -41
  211. package/dist/components/badge.d.mts +2 -0
  212. package/dist/components/breadcrumb.css +85 -46
  213. package/dist/components/breadcrumb.d.mts +2 -0
  214. package/dist/components/btn.css +105 -94
  215. package/dist/components/btn.d.mts +2 -0
  216. package/dist/components/card.css +124 -113
  217. package/dist/components/card.d.mts +2 -0
  218. package/dist/components/carousel.d.mts +2 -0
  219. package/dist/components/cascader.css +332 -0
  220. package/dist/components/cascader.d.mts +2 -0
  221. package/dist/components/cascader.mjs +3 -0
  222. package/dist/components/chart-area.css +54 -2
  223. package/dist/components/chart-area.d.mts +2 -0
  224. package/dist/components/chart-bar.css +147 -38
  225. package/dist/components/chart-bar.d.mts +2 -0
  226. package/dist/components/chart-calendar.d.mts +2 -0
  227. package/dist/components/chart-gauge.css +36 -13
  228. package/dist/components/chart-gauge.d.mts +2 -0
  229. package/dist/components/chart-graph.css +35 -20
  230. package/dist/components/chart-graph.d.mts +2 -0
  231. package/dist/components/chart-heatmap.css +67 -39
  232. package/dist/components/chart-heatmap.d.mts +2 -0
  233. package/dist/components/chart-line.css +62 -3
  234. package/dist/components/chart-line.d.mts +2 -0
  235. package/dist/components/chart-map.d.mts +2 -0
  236. package/dist/components/chart-pie.css +38 -6
  237. package/dist/components/chart-pie.d.mts +2 -0
  238. package/dist/components/chart-radar.css +57 -5
  239. package/dist/components/chart-radar.d.mts +2 -0
  240. package/dist/components/chart-scatter.css +47 -7
  241. package/dist/components/chart-scatter.d.mts +2 -0
  242. package/dist/components/chart-sparkline.css +25 -2
  243. package/dist/components/chart-sparkline.d.mts +2 -0
  244. package/dist/components/chart-stack.css +27 -13
  245. package/dist/components/chart-stack.d.mts +2 -0
  246. package/dist/components/charts.css +220 -84
  247. package/dist/components/charts.d.mts +2 -0
  248. package/dist/components/code-block.css +420 -0
  249. package/dist/components/code-block.d.mts +2 -0
  250. package/dist/components/code-block.mjs +4 -0
  251. package/dist/components/command-palette.css +150 -122
  252. package/dist/components/command-palette.d.mts +2 -0
  253. package/dist/components/content.css +274 -263
  254. package/dist/components/context-menu.d.mts +2 -0
  255. package/dist/components/copy.css +73 -45
  256. package/dist/components/copy.d.mts +2 -0
  257. package/dist/components/datatable.css +457 -202
  258. package/dist/components/datatable.d.mts +2 -0
  259. package/dist/components/date-picker.css +136 -105
  260. package/dist/components/date-picker.d.mts +2 -0
  261. package/dist/components/desc.d.mts +2 -0
  262. package/dist/components/dropdown.d.mts +2 -0
  263. package/dist/components/empty.css +72 -69
  264. package/dist/components/empty.d.mts +2 -0
  265. package/dist/components/feedback.css +211 -191
  266. package/dist/components/form-validate.css +134 -0
  267. package/dist/components/form-validate.d.mts +2 -0
  268. package/dist/components/form-validate.mjs +3 -0
  269. package/dist/components/form.css +157 -131
  270. package/dist/components/form.d.mts +2 -0
  271. package/dist/components/icon.css +113 -0
  272. package/dist/components/icon.d.mts +2 -0
  273. package/dist/components/icon.mjs +3 -0
  274. package/dist/components/input.css +163 -108
  275. package/dist/components/input.d.mts +2 -0
  276. package/dist/components/kb-access.d.mts +2 -0
  277. package/dist/components/kb-acl.d.mts +2 -0
  278. package/dist/components/kb-agent.css +300 -206
  279. package/dist/components/kb-answer.d.mts +2 -0
  280. package/dist/components/kb-audit.d.mts +2 -0
  281. package/dist/components/kb-canvas.d.mts +2 -0
  282. package/dist/components/kb-chain.d.mts +2 -0
  283. package/dist/components/kb-checkpoint.d.mts +2 -0
  284. package/dist/components/kb-chunks.d.mts +2 -0
  285. package/dist/components/kb-citation.d.mts +2 -0
  286. package/dist/components/kb-clarify.d.mts +2 -0
  287. package/dist/components/kb-conflict.d.mts +2 -0
  288. package/dist/components/kb-connector.d.mts +2 -0
  289. package/dist/components/kb-data.css +431 -315
  290. package/dist/components/kb-eval.d.mts +2 -0
  291. package/dist/components/kb-explain.d.mts +2 -0
  292. package/dist/components/kb-filter.d.mts +2 -0
  293. package/dist/components/kb-gap.d.mts +2 -0
  294. package/dist/components/kb-ground.css +333 -229
  295. package/dist/components/kb-hittest.d.mts +2 -0
  296. package/dist/components/kb-ingest.css +613 -434
  297. package/dist/components/kb-metadata.d.mts +2 -0
  298. package/dist/components/kb-ops.css +422 -302
  299. package/dist/components/kb-passage.d.mts +2 -0
  300. package/dist/components/kb-perm.css +374 -314
  301. package/dist/components/kb-pipeline.d.mts +2 -0
  302. package/dist/components/kb-qa.d.mts +2 -0
  303. package/dist/components/kb-rerank.d.mts +2 -0
  304. package/dist/components/kb-retrieval.d.mts +2 -0
  305. package/dist/components/kb-review.d.mts +2 -0
  306. package/dist/components/kb-sandbox.d.mts +2 -0
  307. package/dist/components/kb-search.css +653 -459
  308. package/dist/components/kb-segment.d.mts +2 -0
  309. package/dist/components/kb-sources.d.mts +2 -0
  310. package/dist/components/kb-sql.d.mts +2 -0
  311. package/dist/components/kb-trace.d.mts +2 -0
  312. package/dist/components/kb-visibility.d.mts +2 -0
  313. package/dist/components/kb-who-can.d.mts +2 -0
  314. package/dist/components/kb.css +170 -135
  315. package/dist/components/kb.d.mts +2 -0
  316. package/dist/components/kbd.d.mts +2 -0
  317. package/dist/components/layout.css +86 -83
  318. package/dist/components/layout.d.mts +2 -0
  319. package/dist/components/list.d.mts +2 -0
  320. package/dist/components/material-chinese.css +83 -0
  321. package/dist/components/material-soviet.css +86 -0
  322. package/dist/components/material.css +318 -0
  323. package/dist/components/media-card.d.mts +2 -0
  324. package/dist/components/media.css +225 -176
  325. package/dist/components/mentions.css +190 -0
  326. package/dist/components/mentions.d.mts +2 -0
  327. package/dist/components/mentions.mjs +3 -0
  328. package/dist/components/menu.css +121 -109
  329. package/dist/components/modal.css +116 -118
  330. package/dist/components/modal.d.mts +2 -0
  331. package/dist/components/nav.css +136 -129
  332. package/dist/components/nav.d.mts +2 -0
  333. package/dist/components/notification.css +247 -177
  334. package/dist/components/notification.d.mts +2 -0
  335. package/dist/components/pagination.css +62 -57
  336. package/dist/components/pagination.d.mts +2 -0
  337. package/dist/components/panel.css +70 -68
  338. package/dist/components/panel.d.mts +2 -0
  339. package/dist/components/panel.mjs +1 -0
  340. package/dist/components/pill.css +83 -72
  341. package/dist/components/pill.d.mts +2 -0
  342. package/dist/components/popover.css +80 -57
  343. package/dist/components/popover.d.mts +2 -0
  344. package/dist/components/progress.d.mts +2 -0
  345. package/dist/components/rating.d.mts +2 -0
  346. package/dist/components/result.d.mts +2 -0
  347. package/dist/components/scroll-area.css +29 -54
  348. package/dist/components/scroll-area.d.mts +2 -0
  349. package/dist/components/scroll-area.mjs +1 -0
  350. package/dist/components/segmented.css +167 -146
  351. package/dist/components/segmented.d.mts +2 -0
  352. package/dist/components/select.css +250 -191
  353. package/dist/components/select.d.mts +2 -0
  354. package/dist/components/sidebar.css +157 -143
  355. package/dist/components/sidebar.d.mts +2 -0
  356. package/dist/components/skeleton.d.mts +2 -0
  357. package/dist/components/slider.css +135 -128
  358. package/dist/components/slider.d.mts +2 -0
  359. package/dist/components/spinner.d.mts +2 -0
  360. package/dist/components/split-pane.css +120 -108
  361. package/dist/components/split-pane.d.mts +2 -0
  362. package/dist/components/stat.css +116 -109
  363. package/dist/components/stat.d.mts +2 -0
  364. package/dist/components/steps.css +114 -108
  365. package/dist/components/steps.d.mts +2 -0
  366. package/dist/components/switch.css +192 -149
  367. package/dist/components/switch.d.mts +2 -0
  368. package/dist/components/table.css +158 -112
  369. package/dist/components/table.d.mts +2 -0
  370. package/dist/components/tabs.css +143 -116
  371. package/dist/components/tabs.d.mts +2 -0
  372. package/dist/components/tag-input.css +52 -133
  373. package/dist/components/tag-input.d.mts +2 -0
  374. package/dist/components/tag.css +90 -72
  375. package/dist/components/tag.d.mts +2 -0
  376. package/dist/components/theme-switcher.css +105 -0
  377. package/dist/components/theme-switcher.d.mts +2 -0
  378. package/dist/components/theme-switcher.mjs +3 -0
  379. package/dist/components/timeline.d.mts +2 -0
  380. package/dist/components/toast.css +115 -97
  381. package/dist/components/toast.d.mts +2 -0
  382. package/dist/components/toolbar.css +47 -43
  383. package/dist/components/toolbar.d.mts +2 -0
  384. package/dist/components/tooltip.css +103 -43
  385. package/dist/components/tooltip.d.mts +2 -0
  386. package/dist/components/tooltip.mjs +1 -0
  387. package/dist/components/tree-select.css +439 -0
  388. package/dist/components/tree-select.d.mts +2 -0
  389. package/dist/components/tree-select.mjs +3 -0
  390. package/dist/components/tree.d.mts +2 -0
  391. package/dist/components/upload.css +138 -97
  392. package/dist/components/upload.d.mts +2 -0
  393. package/dist/fonts/LICENSES/ark-pixel/OFL.txt +96 -0
  394. package/dist/fonts/LICENSES/cubic-11/OFL.txt +108 -0
  395. package/dist/fonts/LICENSES/galmuri/LICENSE.txt +93 -0
  396. package/dist/fonts/OFL.txt +96 -0
  397. package/dist/fonts/README.md +14 -0
  398. package/dist/fonts/fusion-pixel-12px-zh-hans.woff2 +0 -0
  399. package/dist/index.d.mts +85 -70
  400. package/dist/index.mjs +17330 -5773
  401. package/dist/react.d.mts +91 -0
  402. package/dist/react.mjs +8307 -0
  403. package/dist/registry.json +918 -70
  404. package/dist/tokens/chinese.css +44 -0
  405. package/dist/tokens/colors.css +371 -1222
  406. package/dist/tokens/design.css +209 -0
  407. package/dist/tokens/dtcg.json +15926 -0
  408. package/dist/tokens/figma.variables.json +10779 -0
  409. package/dist/tokens/icon-masks.css +78 -0
  410. package/dist/tokens/pixel.css +53 -0
  411. package/dist/tokens/scrollbars.css +40 -0
  412. package/dist/tokens/soviet.css +44 -0
  413. package/dist/tokens/style-profiles.css +36 -547
  414. package/dist/tokens/themes.json +308 -0
  415. package/dist/tokens/tokens-studio.json +11648 -0
  416. package/dist/tokens/typography.css +21 -18
  417. package/dist/tokens.css +1783 -1806
  418. package/dist/ui.css +14796 -10750
  419. package/dist/vue.d.mts +344 -0
  420. package/dist/vue.mjs +7876 -0
  421. package/docs/spec/ai-input-experience.md +75 -0
  422. package/docs/spec/ai-native.md +238 -147
  423. package/docs/spec/design-philosophy.md +189 -0
  424. package/docs/spec/design-primitives.md +196 -0
  425. package/docs/spec/kb-family.md +147 -115
  426. package/docs/spec/scrollbars.md +46 -0
  427. package/package.json +56 -8
  428. package/dist/retro-effects.css +0 -255
  429. package/dist/tokens/retro-effects.css +0 -255
  430. package/docs/research/2026-10-03-ai-kb-components.md +0 -392
  431. package/docs/research/2026-10-03-kb-permissions.md +0 -992
@@ -1,60 +1,59 @@
1
+ @layer icen.components {
1
2
  /*
2
3
  * @icen.ai/ui — Component: ai-chat(AI 原生组件族:ai-chat / ai-message / ai-reasoning / ai-composer)
3
4
  *
4
5
  * 完整契约:
5
- * <div class="ai-chat" data-density="normal"> ← verbose|normal|summary 三档
6
- * <div class="ai-chat-scroll">
7
- * <div class="ai-msg ai-msg--user|ai-msg--assistant|ai-msg--system|ai-msg--tool">
8
- * <span class="ai-msg-avatar"></span>
9
- * <div class="ai-msg-body">…消费方自行渲染 markdown…</div>
10
- * <div class="ai-msg-actions"><button data-ai-msg-action="copy|retry">…</button></div>
11
- * <div class="ai-msg-meta">12:04 · 1.2k tok</div>
6
+ * <div class="icen-ai-chat" data-icen-density="normal"> ← verbose|normal|summary 三档
7
+ * <div class="icen-ai-chat-scroll">
8
+ * <div class="icen-ai-msg icen-ai-msg--user|icen-ai-msg--assistant|icen-ai-msg--system|icen-ai-msg--tool">
9
+ * <span class="icen-ai-msg-avatar"></span>
10
+ * <div class="icen-ai-msg-body">…消费方自行渲染 markdown…</div>
11
+ * <div class="icen-ai-msg-actions"><button data-icen-ai-msg-action="copy|retry">…</button></div>
12
+ * <div class="icen-ai-msg-meta">12:04 · 1.2k tok</div>
12
13
  * </div>
13
14
  * </div>
14
- * <button class="ai-chat-jump" hidden>回到底部 · N 条新消息</button>
15
+ * <button class="icen-ai-chat-jump" hidden>回到底部 · N 条新消息</button>
15
16
  * </div>
16
17
  *
17
- * <div class="ai-reasoning [.is-streaming|.is-done]">
18
- * <button class="ai-reasoning-head" aria-expanded="false">
19
- * <span class="ai-reasoning-label">思考过程</span><span class="ai-reasoning-time">3s</span>
18
+ * <div class="icen-ai-reasoning [.is-streaming|.is-done]">
19
+ * <button class="icen-ai-reasoning-head" aria-expanded="false">
20
+ * <span class="icen-ai-reasoning-label">思考过程</span><span class="icen-ai-reasoning-time">3s</span>
20
21
  * </button>
21
- * <div class="ai-reasoning-body" hidden>…</div>
22
+ * <div class="icen-ai-reasoning-body" hidden>…</div>
22
23
  * </div>
23
24
  *
24
- * <div class="ai-composer" data-ai-composer [.is-running]>
25
- * <div class="ai-composer-queue" hidden><span class="ai-composer-chip">
26
- * <span class="ai-composer-chip-text">…</span>
27
- * <button class="ai-composer-chip-remove" aria-label="移除">×</button>
25
+ * <div class="icen-ai-composer" data-icen-ai-composer [.is-running]>
26
+ * <div class="icen-ai-composer-queue" hidden><span class="icen-ai-composer-chip">
27
+ * <span class="icen-ai-composer-chip-text">…</span>
28
+ * <button class="icen-ai-composer-chip-remove" aria-label="移除">×</button>
28
29
  * </span></div>
29
- * <div class="ai-composer-refs" hidden><!-- @ 引用 chips,结构同上(v2 setComposerRefs) --></div>
30
- * <div class="ai-composer-attach" hidden><!-- 附件 chips,结构同上 --></div>
31
- * <div class="ai-composer-box control">
32
- * <textarea class="ai-composer-input" rows="1" placeholder="…"></textarea>
33
- * <div class="ai-composer-actions"><!-- v1 旧结构(无 toolbar 配置时保留): -->
34
- * <button class="ai-composer-btn" data-ai-attach aria-label="附件"></button>
35
- * <button class="ai-composer-send" data-ai-send aria-label="发送"></button> ← 运行态 .is-stop
36
- * </div>
37
- * <div class="ai-composer-toolbar"><!-- v2 工具条(setComposerModels/Usage 配置时 JS 装配):
38
- * <button class="ai-composer-model" data-ai-model-open>provider 图标/首字母章 + 模型名 + chevron</button>
39
- * <span class="ai-composer-spacer"></span>
40
- * <span class="ai-composer-usage" data-ai-usage></span> ← 用量环挂载点(renderAiUsageRing)
41
- * <button class="ai-composer-btn" data-ai-attach></button>
42
- * <button class="ai-composer-send" data-ai-send></button> ← 运行态 .is-stop
30
+ * <div class="icen-ai-composer-refs" hidden><!-- @ 引用 chips,结构同上(v2 setComposerRefs) --></div>
31
+ * <div class="icen-ai-composer-attach" hidden><!-- 附件 chips,结构同上 --></div>
32
+ * <div class="icen-ai-composer-box icen-control">
33
+ * <icen-textarea class="icen-ai-composer-input" rows="1" placeholder="…"></icen-textarea>
34
+ * <div class="icen-ai-composer-toolbar"><!-- 工具条(手写或 setComposerModels/Usage 配置时 JS 装配):
35
+ * <button class="icen-ai-composer-btn" data-icen-ai-attach aria-label="附件"></button>
36
+ * <button class="icen-ai-composer-send" data-icen-ai-send aria-label="发送"></button> ← 运行态 .is-stop
37
+ * <button class="icen-ai-composer-model" data-icen-ai-model-open>provider 图标/首字母章 + 模型名 + chevron</button>
38
+ * <span class="icen-ai-composer-spacer"></span>
39
+ * <span class="icen-ai-composer-usage" data-icen-ai-usage></span> ← 用量环挂载点(renderAiUsageRing)
40
+ * <button class="icen-ai-composer-btn" data-icen-ai-attach></button>
41
+ * <button class="icen-ai-composer-send" data-icen-ai-send></button> ← 运行态 .is-stop
43
42
  * </div>
44
43
  * </div>
45
44
  * </div>
46
- * 弹层 .ai-composer-popup(portal body,JS 动态创建):模型切换 / 斜杠命令 / @ 引用
47
- * 三模式共用基座——.ai-composer-popup-search 搜索框、.ai-composer-popup-list(listbox)
48
- * > .ai-composer-popup-group > .ai-composer-popup-group-label + .ai-composer-popup-option(role=option),
49
- * .ai-composer-popup-empty 空态、.ai-composer-popup-foot 底部提示。
45
+ * 弹层 .icen-ai-composer-popup(portal body,JS 动态创建):模型切换 / 斜杠命令 / @ 引用
46
+ * 三模式共用基座——.icen-ai-composer-popup-search 搜索框、.icen-ai-composer-popup-list(listbox)
47
+ * > .icen-ai-composer-popup-group > .icen-ai-composer-popup-group-label + .icen-ai-composer-popup-option(role=option),
48
+ * .icen-ai-composer-popup-empty 空态、.icen-ai-composer-popup-foot 底部提示。
50
49
  *
51
50
  * 配套 behaviors:behaviors/ai-chat.ts(initAiChat / createAiStream)
52
51
  * + behaviors/ai-composer.ts(initAiComposer / setComposerRunning
53
52
  * + v2:setComposerModels / setComposerCommands / setComposerRefs / setComposerUsage)。
54
- * 状态机 7 态 .is-* 中的 streaming/done 在本文件消费;running 脉冲点等条目态见 ai-tool.css(.ai-item 基元)。
55
- * data-density:summary 档隐藏 meta、默认折叠 reasoning(纯 CSS);
53
+ * 状态机 7 态 .is-* 中的 streaming/done 在本文件消费;running 脉冲点等条目态见 ai-tool.css(.icen-ai-item 基元)。
54
+ * data-icen-density:summary 档隐藏 meta、默认折叠 reasoning(纯 CSS);
56
55
  * tool/system 类次要消息在 summary 档压淡。verbose 与 normal 目前同视觉(透明度两档生效)。
57
- * 流式光标复用 tokens 的 blink keyframes(.animate-blink 同款);reasoning shimmer 时长走
56
+ * 流式光标复用 base.css 的 icen-blink keyframes;reasoning shimmer 时长走
58
57
  * --ai-shimmer-duration 局部变量(默认值 1.6s)。
59
58
  */
60
59
 
@@ -63,144 +62,146 @@
63
62
  /* 输出容器宽度自稳定契约:即使宿主是 flex/grid 居中上下文(shrink-wrap 陷阱),
64
63
  也不随内容多少改变宽度——流式内容只允许纵向生长。
65
64
  (用 align-self 而非 width:100%——width 在 shrink-wrap 父级下会塌成 min-content) */
66
- .ai-chat,
67
- .ai-reasoning,
68
- .ai-composer {
65
+ .icen-ai-chat,
66
+ .icen-ai-reasoning,
67
+ .icen-ai-composer {
69
68
  align-self: stretch;
70
69
  }
71
70
 
72
- .ai-chat {
71
+ .icen-ai-chat {
73
72
  position: relative;
74
73
  display: flex;
75
74
  flex-direction: column;
76
75
  height: 100%;
77
76
  min-height: 0;
78
- gap: var(--density-space-sm);
77
+ gap: var(--icen-density-space-sm);
79
78
  }
80
79
 
81
- .ai-chat-scroll {
80
+ .icen-ai-chat-scroll {
82
81
  flex: 1;
83
82
  min-height: 0;
84
83
  overflow-y: auto;
85
84
  display: flex;
86
85
  flex-direction: column;
87
- gap: var(--density-space-md);
88
- padding: var(--density-space-xs) var(--density-space-2xs, 2px);
86
+ gap: var(--icen-density-space-md);
87
+ padding: var(--icen-density-space-xs) var(--icen-density-space-2xs, 2px);
89
88
  scroll-behavior: smooth;
90
89
  }
91
90
 
92
91
  /* 「回到底部 · N 条新消息」浮动钮(用户上滚暂停跟随时出现,initAiChat 驱动) */
93
- .ai-chat-jump {
92
+ .icen-ai-chat-jump {
94
93
  position: absolute;
95
- left: 50%;
96
- bottom: var(--density-space-md);
94
+ left: 50%; /* guard:allow-physical 水平居中(translateX(-50%) 配套) */
95
+ bottom: var(--icen-density-space-md);
97
96
  transform: translateX(-50%);
98
- z-index: var(--z-raised);
97
+ z-index: var(--icen-z-raised);
99
98
  display: inline-flex;
100
99
  align-items: center;
101
- gap: var(--density-space-xs);
102
- padding: var(--density-space-xs) var(--density-space-md);
103
- border: 1px solid var(--token-line-soft);
104
- border-radius: var(--radius-full);
105
- background: var(--token-surface);
106
- box-shadow: var(--token-shadow-card);
107
- color: var(--token-text-muted);
108
- font-family: var(--font-mono);
109
- font-size: var(--density-font-size-xs);
100
+ gap: var(--icen-density-space-xs);
101
+ padding: var(--icen-density-space-xs) var(--icen-density-space-md);
102
+ border: 1px solid var(--icen-token-line-soft);
103
+ border-radius: var(--icen-radius-full);
104
+ background: var(--icen-token-surface);
105
+ box-shadow: var(--icen-token-shadow-card);
106
+ color: var(--icen-token-text-muted);
107
+ font-family: var(--icen-font-mono);
108
+ font-size: var(--icen-density-font-size-xs);
110
109
  letter-spacing: 0.02em;
111
110
  white-space: nowrap;
112
111
  cursor: pointer;
113
- animation: icen-pop-in var(--ai-jump-enter-duration, var(--duration-normal)) var(--ease-out);
112
+ animation: icen-pop-in var(--ai-jump-enter-duration, var(--icen-duration-normal)) var(--icen-ease-out);
114
113
  transition:
115
114
  color var(--icen-tx-fast),
116
115
  border-color var(--icen-tx-fast),
117
116
  box-shadow var(--icen-tx-fast);
118
117
  }
119
- .ai-chat-jump:hover {
120
- color: var(--token-accent);
118
+ .icen-ai-chat-jump:hover {
119
+ color: var(--icen-token-accent);
121
120
  border-color: var(--icen-hover-border);
122
121
  }
123
- .ai-chat-jump:focus-visible {
122
+ .icen-ai-chat-jump:focus-visible {
124
123
  outline: none;
125
124
  box-shadow: var(--icen-ring);
126
125
  }
127
- .ai-chat-jump[hidden] {
126
+ .icen-ai-chat-jump[hidden] {
128
127
  display: none;
129
128
  }
130
129
 
131
130
  /* ══════════════ ai-message ══════════════ */
132
131
 
133
- .ai-msg {
132
+ .icen-ai-msg {
134
133
  position: relative;
135
134
  display: grid;
136
135
  grid-template-columns: auto 1fr;
137
- gap: var(--density-space-sm);
138
- padding: var(--density-space-sm) var(--density-space-md);
139
- border-radius: var(--radius-md);
140
- animation: icen-pop-in var(--ai-msg-enter-duration, var(--duration-normal)) var(--ease-out);
136
+ gap: var(--icen-density-space-sm);
137
+ padding: 6px var(--icen-density-space-xs);
138
+ border-radius: var(--icen-control-radius-lg);
139
+ animation: icen-pop-in var(--ai-msg-enter-duration, var(--icen-duration-normal)) var(--icen-ease-out);
141
140
  }
142
141
 
143
- .ai-msg-avatar {
144
- width: 28px;
145
- height: 28px;
142
+ .icen-ai-msg-avatar {
143
+ width: 26px;
144
+ height: 26px;
146
145
  flex-shrink: 0;
147
146
  display: inline-flex;
148
147
  align-items: center;
149
148
  justify-content: center;
150
- border-radius: var(--radius-sm);
151
- background: var(--token-fill-2);
152
- color: var(--token-text-muted);
153
- font-family: var(--font-mono);
154
- font-size: var(--density-font-size-2xs);
155
- letter-spacing: 0.04em;
149
+ border-radius: var(--icen-radius-xs);
150
+ background: var(--icen-token-fill-2);
151
+ color: var(--icen-token-text-muted);
152
+ font-family: var(--icen-font-mono);
153
+ font-size: var(--icen-density-font-size-2xs);
154
+ letter-spacing: 0.03em;
156
155
  user-select: none;
157
156
  }
158
- .ai-msg--user .ai-msg-avatar {
159
- background: color-mix(in srgb, var(--token-accent) 14%, transparent);
160
- color: var(--token-accent);
157
+ .icen-ai-msg--user .icen-ai-msg-avatar {
158
+ background: color-mix(in srgb, var(--icen-token-accent) 14%, transparent);
159
+ color: var(--icen-token-accent-text);
161
160
  }
162
- .ai-msg--assistant .ai-msg-avatar {
163
- background: color-mix(in srgb, var(--token-success) 12%, transparent);
164
- color: var(--token-success);
161
+ .icen-ai-msg--assistant .icen-ai-msg-avatar {
162
+ background: color-mix(in srgb, var(--icen-token-success) 12%, transparent);
163
+ color: var(--icen-token-success);
165
164
  }
166
- .ai-msg--system .ai-msg-avatar {
167
- background: color-mix(in srgb, var(--token-warning) 12%, transparent);
168
- color: var(--token-warning);
165
+ .icen-ai-msg--system .icen-ai-msg-avatar {
166
+ background: color-mix(in srgb, var(--icen-token-warning) 12%, transparent);
167
+ color: var(--icen-token-warning);
169
168
  }
170
- .ai-msg--tool .ai-msg-avatar {
171
- background: color-mix(in srgb, var(--token-info) 12%, transparent);
172
- color: var(--token-info);
169
+ .icen-ai-msg--tool .icen-ai-msg-avatar {
170
+ background: color-mix(in srgb, var(--icen-token-info) 12%, transparent);
171
+ color: var(--icen-token-info);
173
172
  }
174
173
 
175
- .ai-msg-body {
174
+ .icen-ai-msg-body {
176
175
  min-width: 0;
177
176
  min-height: 1.6em; /* 流式从空开始时占住一行高度,不塌 */
178
- font-size: var(--density-font-size-md);
177
+ font-size: var(--icen-font-size-control);
179
178
  line-height: 1.6;
180
179
  white-space: pre-wrap;
181
180
  word-break: break-word;
182
181
  }
183
182
 
184
- /* 流式光标(▍闪烁,复用 tokens 的 blink keyframes,同 .animate-blink) */
185
- .ai-msg-body.is-streaming::after,
186
- .ai-reasoning-body.is-streaming::after {
183
+ /* 流式光标(▍闪烁,共享 base.css 的 icen-blink keyframes);
184
+ .icen-ai-msg-text 命中库内自带绑定的 stream() 节点(createAiStream 挂 .is-streaming) */
185
+ .icen-ai-msg-body.is-streaming::after,
186
+ .icen-ai-msg-text.is-streaming::after,
187
+ .icen-ai-reasoning-body.is-streaming::after {
187
188
  content: '▍';
188
- margin-left: 1px;
189
- color: var(--token-accent);
190
- animation: blink 1s step-end infinite;
189
+ margin-inline-start: 1px;
190
+ color: var(--icen-token-accent);
191
+ animation: icen-blink 1s step-end infinite;
191
192
  }
192
193
 
193
194
  /* 消息操作:hover / focus-within 才出现(键盘可达等价) */
194
- .ai-msg-actions {
195
+ .icen-ai-msg-actions {
195
196
  position: absolute;
196
- top: var(--density-space-xs);
197
- right: var(--density-space-xs);
197
+ top: var(--icen-density-space-xs);
198
+ inset-inline-end: var(--icen-density-space-xs);
198
199
  display: flex;
199
200
  gap: 2px;
200
201
  padding: 2px;
201
- border-radius: var(--radius-sm);
202
- background: var(--token-surface);
203
- border: 1px solid var(--token-line-soft);
202
+ border-radius: var(--icen-radius-sm);
203
+ background: var(--icen-token-surface);
204
+ border: 1px solid var(--icen-token-line-soft);
204
205
  opacity: 0;
205
206
  visibility: hidden;
206
207
  transform: translateY(-2px);
@@ -209,13 +210,13 @@
209
210
  transform var(--icen-tx-fast),
210
211
  visibility var(--icen-tx-fast);
211
212
  }
212
- .ai-msg:hover .ai-msg-actions,
213
- .ai-msg:focus-within .ai-msg-actions {
213
+ .icen-ai-msg:hover .icen-ai-msg-actions,
214
+ .icen-ai-msg:focus-within .icen-ai-msg-actions {
214
215
  opacity: 1;
215
216
  visibility: visible;
216
217
  transform: translateY(0);
217
218
  }
218
- .ai-msg-actions [data-ai-msg-action] {
219
+ .icen-ai-msg-actions [data-icen-ai-msg-action] {
219
220
  display: inline-flex;
220
221
  align-items: center;
221
222
  justify-content: center;
@@ -223,190 +224,187 @@
223
224
  height: 22px;
224
225
  padding: 0;
225
226
  border: 0;
226
- border-radius: var(--radius-xs);
227
+ border-radius: var(--icen-radius-xs);
227
228
  background: transparent;
228
- color: var(--token-text-muted);
229
+ color: var(--icen-token-text-muted);
229
230
  cursor: pointer;
230
231
  transition:
231
232
  color var(--icen-tx-fast),
232
233
  background-color var(--icen-tx-fast);
233
234
  }
234
- .ai-msg-actions [data-ai-msg-action]:hover {
235
- color: var(--token-accent);
236
- background: var(--token-fill-2);
235
+ .icen-ai-msg-actions [data-icen-ai-msg-action]:hover {
236
+ color: var(--icen-token-accent);
237
+ background: var(--icen-token-fill-2);
237
238
  }
238
- .ai-msg-actions [data-ai-msg-action]:focus-visible {
239
+ .icen-ai-msg-actions [data-icen-ai-msg-action]:focus-visible {
239
240
  outline: none;
240
241
  box-shadow: var(--icen-ring);
241
242
  }
242
- .ai-msg-actions [data-ai-msg-action] svg {
243
+ .icen-ai-msg-actions [data-icen-ai-msg-action] svg {
243
244
  width: 12px;
244
245
  height: 12px;
245
246
  }
246
247
 
247
248
  /* meta:时间 · token 数(summary 档隐藏) */
248
- .ai-msg-meta {
249
+ .icen-ai-msg-meta {
250
+ grid-column: 2; /* 归属正文列:落在 auto 第一列会把列宽撑到 meta 宽度,正文被挤窄(流式收尾时突跳) */
249
251
  margin-top: 2px;
250
- font-family: var(--font-mono);
251
- font-size: var(--density-font-size-2xs);
252
- color: var(--token-text-faint);
252
+ font-family: var(--icen-font-mono);
253
+ font-size: var(--icen-density-font-size-2xs);
254
+ color: var(--icen-token-text-faint);
253
255
  font-variant-numeric: tabular-nums;
254
256
  }
255
257
 
256
258
  /* ── 多模态消息部件(renderAiMessage,spec §10)── */
257
259
 
258
- .ai-msg-text {
260
+ .icen-ai-msg-text {
259
261
  display: block;
260
262
  }
261
263
 
262
264
  /* 图片 / 音频 / 视频:宽度自稳定(不超正文列),纵向生长 */
263
- .ai-msg-media {
265
+ .icen-ai-msg-media {
264
266
  display: block;
265
- max-width: min(100%, 360px);
266
- margin: var(--density-space-xs) 0;
267
- border: 1px solid var(--token-line-soft);
268
- border-radius: var(--radius-md);
269
- background: var(--token-surface);
270
- }
271
- .ai-msg-media--image {
272
- max-height: 320px;
267
+ max-inline-size: min(100%, 360px);
268
+ margin: var(--icen-density-space-xs) 0;
269
+ border: 1px solid var(--icen-token-line-soft);
270
+ border-radius: var(--icen-radius-md);
271
+ background: var(--icen-token-surface);
272
+ }
273
+ .icen-ai-msg-media--image {
274
+ max-block-size: 320px;
273
275
  object-fit: contain;
274
276
  }
275
- .ai-msg-media--audio {
276
- width: min(100%, 300px);
277
+ .icen-ai-msg-media--audio {
278
+ inline-size: min(100%, 300px);
277
279
  height: 40px;
278
280
  }
279
- .ai-msg-media--video {
280
- max-width: min(100%, 480px);
281
- max-height: 300px;
281
+ .icen-ai-msg-media--video {
282
+ max-inline-size: min(100%, 480px);
283
+ max-block-size: 300px;
282
284
  }
283
285
 
284
- /* 文件 chip(含可选下载链接) */
285
- .ai-msg-file {
286
+ /* 文件 chip(含可选下载链接;行内方向间距:inline-end 侧留隙) */
287
+ .icen-ai-msg-file {
286
288
  display: inline-flex;
287
289
  align-items: center;
288
- gap: var(--density-space-xs);
289
- margin: 2px var(--density-space-xs) 2px 0;
290
- padding: 2px var(--density-space-sm);
291
- border: 1px solid var(--token-line);
292
- border-radius: var(--radius-sm);
293
- background: var(--token-surface);
294
- font-family: var(--font-mono);
295
- font-size: var(--density-font-size-xs);
296
- color: var(--token-text);
297
- }
298
- .ai-msg-file-link {
299
- color: var(--token-accent);
290
+ gap: var(--icen-density-space-xs);
291
+ margin-block: 2px;
292
+ margin-inline-end: var(--icen-density-space-xs);
293
+ padding: 2px var(--icen-density-space-sm);
294
+ border: 1px solid var(--icen-token-line);
295
+ border-radius: var(--icen-radius-sm);
296
+ background: var(--icen-token-surface);
297
+ font-family: var(--icen-font-mono);
298
+ font-size: var(--icen-density-font-size-xs);
299
+ color: var(--icen-token-text);
300
+ }
301
+ .icen-ai-msg-file-link {
302
+ color: var(--icen-token-accent);
300
303
  text-decoration: none;
301
304
  }
302
- .ai-msg-file-link:hover {
305
+ .icen-ai-msg-file-link:hover {
303
306
  text-decoration: underline;
304
307
  }
305
308
 
306
309
  /* MCP ResourceLink 等资源引用 */
307
- .ai-msg-link {
308
- color: var(--token-accent);
310
+ .icen-ai-msg-link {
311
+ color: var(--icen-token-accent);
309
312
  }
310
313
 
311
314
  /* assistant 消息的模型名标签 */
312
- .ai-msg-model {
315
+ .icen-ai-msg-model {
313
316
  display: inline-block;
314
- margin-left: var(--density-space-xs);
317
+ margin-inline-start: var(--icen-density-space-xs);
315
318
  padding: 0 6px;
316
- border-radius: var(--radius-xs);
317
- background: var(--token-fill-1);
318
- color: var(--token-text-faint);
319
- font-family: var(--font-mono);
320
- font-size: var(--density-font-size-2xs);
319
+ border-radius: var(--icen-radius-xs);
320
+ background: var(--icen-token-fill-1);
321
+ color: var(--icen-token-text-faint);
322
+ font-family: var(--icen-font-mono);
323
+ font-size: var(--icen-density-font-size-2xs);
321
324
  vertical-align: middle;
322
325
  }
323
326
 
324
327
  /* ── 错误变体(renderAiMessage.setError / createAiStream.fail)── */
325
328
 
326
- .ai-msg--error .ai-msg-body {
327
- border-left: 2px solid var(--token-error);
328
- padding-left: var(--density-space-sm);
329
+ .icen-ai-msg--error .icen-ai-msg-body {
330
+ border-inline-start: 2px solid var(--icen-token-error);
331
+ padding-inline-start: var(--icen-density-space-sm);
329
332
  }
330
- .ai-msg-error-text {
333
+ .icen-ai-msg-error-text {
331
334
  display: block;
332
- margin-top: var(--density-space-xs);
333
- color: var(--token-error);
334
- font-size: var(--density-font-size-xs);
335
+ margin-top: var(--icen-density-space-xs);
336
+ color: var(--icen-token-error);
337
+ font-size: var(--icen-density-font-size-xs);
335
338
  }
336
339
 
337
340
  /* ══════════════ ai-reasoning ══════════════ */
338
341
 
339
- .ai-reasoning {
340
- margin: var(--density-space-xs) 0;
341
- padding-left: var(--density-space-md);
342
- border-left: 2px solid var(--token-line-soft);
342
+ .icen-ai-reasoning {
343
+ margin: var(--icen-density-space-xs) 0;
344
+ padding-inline-start: var(--icen-density-space-md);
345
+ border-inline-start: 2px solid var(--icen-token-line-soft);
343
346
  }
344
347
 
345
- .ai-reasoning-head {
348
+ .icen-ai-reasoning-head {
346
349
  display: flex;
347
350
  align-items: center;
348
- gap: var(--density-space-sm);
351
+ gap: var(--icen-density-space-sm);
349
352
  width: 100%;
350
- padding: var(--density-space-xs) 0;
353
+ padding: var(--icen-density-space-xs) 0;
351
354
  border: 0;
352
355
  background: none;
353
- color: var(--token-text-muted);
354
- font-family: var(--font-mono);
355
- font-size: var(--density-font-size-sm);
356
+ color: var(--icen-token-text-muted);
357
+ font-family: var(--icen-font-mono);
358
+ font-size: var(--icen-density-font-size-sm);
356
359
  letter-spacing: 0.02em;
357
360
  cursor: pointer;
358
- text-align: left;
361
+ text-align: start;
359
362
  }
360
- .ai-reasoning-head:hover {
361
- color: var(--token-text);
363
+ .icen-ai-reasoning-head:hover {
364
+ color: var(--icen-token-text);
362
365
  }
363
- .ai-reasoning-head:focus-visible {
366
+ .icen-ai-reasoning-head:focus-visible {
364
367
  outline: none;
365
368
  box-shadow: var(--icen-ring);
366
- border-radius: var(--radius-xs);
369
+ border-radius: var(--icen-radius-xs);
367
370
  }
368
371
 
369
- /* 折叠指示 chevron(CSS 三角,展开时旋转) */
370
- .ai-reasoning-head::before {
372
+ /* 折叠指示(共享 chevron-right mask;展开旋转 90° 朝下) */
373
+ .icen-ai-reasoning-head::before {
371
374
  content: '';
372
375
  flex-shrink: 0;
373
- width: 6px;
374
- height: 6px;
375
- border-right: 1.5px solid currentColor;
376
- border-bottom: 1.5px solid currentColor;
377
- transform: rotate(-45deg);
376
+ inline-size: 12px;
377
+ block-size: 12px;
378
+ background: currentColor;
379
+ mask: var(--icen-token-icon-chevron-right) center / contain no-repeat;
378
380
  transition: transform var(--icen-tx-fast);
379
381
  }
380
- .ai-reasoning:has(.ai-reasoning-head[aria-expanded='true']) .ai-reasoning-head::before {
381
- transform: rotate(45deg);
382
+ .icen-ai-reasoning:has(.icen-ai-reasoning-head[aria-expanded='true']) .icen-ai-reasoning-head::before {
383
+ transform: rotate(90deg);
382
384
  }
383
385
 
384
- .ai-reasoning-label {
386
+ .icen-ai-reasoning-label {
385
387
  overflow: hidden;
386
388
  text-overflow: ellipsis;
387
389
  white-space: nowrap;
388
390
  }
389
391
 
390
- .ai-reasoning-time {
391
- margin-left: auto;
392
- font-size: var(--density-font-size-2xs);
393
- color: var(--token-text-faint);
392
+ .icen-ai-reasoning-time {
393
+ margin-inline-start: auto;
394
+ font-size: var(--icen-density-font-size-2xs);
395
+ color: var(--icen-token-text-faint);
394
396
  font-variant-numeric: tabular-nums;
395
397
  }
396
398
 
397
- /* 流式中:耗时位换成 shimmer「正在思考…」(时长走局部变量) */
398
- .ai-reasoning.is-streaming .ai-reasoning-time {
399
- display: none;
400
- }
401
- .ai-reasoning.is-streaming .ai-reasoning-head::after {
402
- content: '正在思考…';
403
- margin-left: auto;
404
- font-size: var(--density-font-size-2xs);
399
+ /* 流式中:耗时位显示 shimmer「正在思考…」——文案由 createAiStream 写入(i18n),
400
+ 此处只做视觉(shimmer 渐变 + 透明填充),不再用 CSS content 冻死中文 */
401
+ .icen-ai-reasoning.is-streaming .icen-ai-reasoning-time {
402
+ font-variant-numeric: normal;
405
403
  background: linear-gradient(
406
404
  90deg,
407
- var(--token-text-faint) 25%,
408
- var(--token-text) 50%,
409
- var(--token-text-faint) 75%
405
+ var(--icen-token-text-faint) 25%,
406
+ var(--icen-token-text) 50%,
407
+ var(--icen-token-text-faint) 75%
410
408
  );
411
409
  background-size: 200% 100%;
412
410
  -webkit-background-clip: text;
@@ -416,77 +414,86 @@
416
414
  animation: ai-shimmer var(--ai-shimmer-duration, 1.6s) linear infinite;
417
415
  }
418
416
 
419
- .ai-reasoning-body {
420
- padding: var(--density-space-xs) 0 var(--density-space-sm);
421
- color: var(--token-text-muted);
422
- font-size: var(--density-font-size-sm);
417
+ .icen-ai-reasoning-body {
418
+ padding: var(--icen-density-space-xs) 0 var(--icen-density-space-sm);
419
+ color: var(--icen-token-text-muted);
420
+ font-size: var(--icen-density-font-size-sm);
423
421
  line-height: 1.6;
424
422
  white-space: pre-wrap;
425
423
  word-break: break-word;
426
424
  }
427
- .ai-reasoning-body[hidden] {
425
+ .icen-ai-reasoning-body[hidden] {
428
426
  display: none;
429
427
  }
430
428
 
431
429
  /* ══════════════ ai-composer ══════════════ */
432
430
 
433
- .ai-composer {
431
+ .icen-ai-composer {
434
432
  display: flex;
435
433
  flex-direction: column;
436
- gap: var(--density-space-xs);
437
- padding: var(--density-space-sm);
438
- border: 1px solid var(--token-line-soft);
439
- border-radius: var(--radius-lg);
440
- background: var(--token-surface);
441
- box-shadow: var(--token-shadow-card);
442
- }
443
- .ai-composer:focus-within {
444
- border-color: var(--icen-hover-border);
434
+ gap: var(--icen-density-space-xs);
435
+ min-inline-size: 0;
436
+ padding: var(--icen-density-space-sm);
437
+ border: 1px solid var(--icen-token-control-border);
438
+ border-radius: var(--icen-control-radius-lg);
439
+ background: var(--icen-token-surface);
440
+ box-shadow: var(--icen-token-shadow-field);
441
+ transition: border-color var(--icen-tx-fast), box-shadow var(--icen-tx-fast);
442
+ }
443
+ .icen-ai-composer:focus-within {
444
+ border-color: var(--icen-control-focus-border);
445
+ box-shadow: var(--icen-token-shadow-field), 0 0 0 3px color-mix(in srgb, var(--icen-token-accent) 16%, transparent);
446
+ }
447
+ .icen-ai-composer:has(.icen-ai-composer-input:focus-visible) {
448
+ border-color: var(--icen-control-focus-border);
449
+ box-shadow: var(--icen-token-shadow-field), 0 0 0 3px color-mix(in srgb, var(--icen-token-accent) 16%, transparent);
445
450
  }
446
451
 
447
452
  /* 排队 / 引用 / 附件 chips 行 */
448
- .ai-composer-queue,
449
- .ai-composer-refs,
450
- .ai-composer-attach {
453
+ .icen-ai-composer-queue,
454
+ .icen-ai-composer-refs,
455
+ .icen-ai-composer-attach {
451
456
  display: flex;
452
457
  flex-wrap: wrap;
453
- gap: var(--density-space-xs);
458
+ gap: var(--icen-density-space-xs);
454
459
  }
455
- .ai-composer-queue[hidden],
456
- .ai-composer-refs[hidden],
457
- .ai-composer-attach[hidden] {
460
+ .icen-ai-composer-queue[hidden],
461
+ .icen-ai-composer-refs[hidden],
462
+ .icen-ai-composer-attach[hidden] {
458
463
  display: none;
459
464
  }
460
465
 
461
- .ai-composer-chip {
466
+ .icen-ai-composer-chip {
462
467
  display: inline-flex;
463
468
  align-items: center;
464
469
  gap: 4px;
465
- max-width: 240px;
466
- padding: 2px var(--density-space-xs);
467
- border: 1px solid var(--token-line-soft);
468
- border-radius: var(--radius-full);
469
- background: var(--token-surface-strong);
470
- color: var(--token-text-muted);
471
- font-size: var(--density-font-size-xs);
470
+ max-inline-size: min(100%, 280px);
471
+ min-block-size: 26px;
472
+ padding: 2px 4px 2px 7px; /* guard:allow-physical symmetric chip padding */
473
+ border: 1px solid var(--icen-token-separator-soft);
474
+ border-radius: var(--icen-radius-xs);
475
+ background: var(--icen-token-fill-hover);
476
+ color: var(--icen-token-text);
477
+ font-size: var(--icen-density-font-size-xs);
472
478
  line-height: 1.4;
473
479
  }
474
- .ai-composer-chip-text {
480
+ .icen-ai-composer-chip-text {
475
481
  overflow: hidden;
476
482
  text-overflow: ellipsis;
477
483
  white-space: nowrap;
478
484
  }
479
- .ai-composer-chip-remove {
485
+ .icen-ai-composer-chip-remove {
480
486
  display: inline-flex;
481
487
  align-items: center;
482
488
  justify-content: center;
483
- width: 14px;
484
- height: 14px;
489
+ inline-size: 24px;
490
+ block-size: 24px;
491
+ flex-shrink: 0;
485
492
  padding: 0;
486
493
  border: 0;
487
- border-radius: var(--radius-full);
494
+ border-radius: var(--icen-radius-sm);
488
495
  background: transparent;
489
- color: var(--token-text-faint);
496
+ color: var(--icen-token-text-faint);
490
497
  font-size: 12px;
491
498
  line-height: 1;
492
499
  cursor: pointer;
@@ -494,371 +501,352 @@
494
501
  color var(--icen-tx-fast),
495
502
  background-color var(--icen-tx-fast);
496
503
  }
497
- .ai-composer-chip-remove:hover {
498
- color: var(--token-error);
499
- background: var(--token-error-muted);
504
+ .icen-ai-composer-chip-remove:hover {
505
+ color: var(--icen-token-error);
506
+ background: var(--icen-token-error-muted);
500
507
  }
501
- .ai-composer-chip-remove:focus-visible {
508
+ .icen-ai-composer-chip-remove:focus-visible {
502
509
  outline: none;
503
510
  box-shadow: var(--icen-ring);
504
511
  }
505
512
 
506
- /* 输入框(.control 基元提供 hover/focus 边框与光晕);flex-wrap 让工具条独占下一行 */
507
- .ai-composer-box {
513
+ /* 输入框(.icen-control 基元提供 hover/focus 边框与光晕);flex-wrap 让工具条独占下一行 */
514
+ .icen-ai-composer-box {
515
+ /* The outer composer owns text focus. */
516
+ --icen-control-focus-shadow: none;
517
+ --icen-control-focus-border: transparent;
508
518
  display: flex;
509
519
  flex-wrap: wrap;
510
520
  align-items: flex-end;
511
- gap: var(--density-space-sm);
512
- padding: var(--density-space-xs) var(--density-space-sm);
513
- border: 1px solid var(--token-line-soft);
514
- border-radius: var(--radius-md);
515
- background: var(--token-panel);
516
- box-shadow: var(--token-shadow-inset);
521
+ gap: var(--icen-density-space-sm);
522
+ padding: 4px var(--icen-field-padding-inline);
523
+ min-inline-size: 0;
524
+ border: 0;
525
+ border-radius: var(--icen-control-radius);
526
+ background: transparent;
527
+ box-shadow: none;
517
528
  }
518
529
 
519
- .ai-composer-input {
530
+ .icen-ai-composer-input {
520
531
  flex: 1;
521
- min-width: 0;
522
- padding: var(--density-space-xs) 0;
532
+ min-inline-size: 0;
533
+ min-block-size: 56px;
534
+ padding: var(--icen-density-space-xs) 0;
523
535
  border: 0;
524
536
  outline: none;
525
537
  background: transparent;
526
538
  resize: none;
527
539
  font-family: inherit;
528
- font-size: var(--density-font-size-md);
540
+ font-size: var(--icen-font-size-control);
529
541
  line-height: 1.5;
530
542
  max-height: 12em;
531
543
  overflow-y: auto;
532
544
  }
533
545
 
534
- /* v1 旧结构按钮行(无 toolbar 配置时保留);v2 中按钮被移入工具条后此容器由 JS 移除 */
535
- .ai-composer-actions {
536
- display: flex;
537
- align-items: center;
538
- gap: var(--density-space-xs);
539
- flex-shrink: 0;
540
- }
541
-
542
- /* ── v2 工具条(composer-box 内底部,业界主流形态)── */
546
+ /* ── 工具条(composer-box 内底部,业界主流形态)── */
543
547
 
544
- .ai-composer-toolbar {
548
+ .icen-ai-composer-toolbar {
545
549
  flex: 0 0 100%;
546
550
  display: flex;
547
551
  align-items: center;
548
- gap: var(--density-space-xs);
549
- padding-top: var(--density-space-xs);
550
- border-top: 1px solid var(--token-line-soft);
552
+ gap: var(--icen-density-space-xs);
553
+ padding-top: var(--icen-density-space-xs);
554
+ min-inline-size: 0;
555
+ flex-wrap: wrap;
556
+ border-top: 0;
551
557
  }
552
- .ai-composer-toolbar[hidden] {
558
+ .icen-ai-composer-toolbar[hidden] {
553
559
  display: none;
554
560
  }
555
561
 
556
- .ai-composer-spacer {
562
+ .icen-ai-composer-spacer {
557
563
  flex: 1;
558
564
  }
559
565
 
560
566
  /* 模型切换钮:provider 图标/首字母章 + 模型名 + chevron */
561
- .ai-composer-model {
567
+ .icen-ai-composer-model {
562
568
  display: inline-flex;
563
569
  align-items: center;
564
570
  gap: 4px;
565
571
  max-width: 180px;
566
572
  height: 28px;
567
- padding: 0 var(--density-space-xs);
573
+ padding: 0 var(--icen-density-space-xs);
568
574
  border: 1px solid transparent;
569
- border-radius: var(--radius-sm);
575
+ border-radius: var(--icen-radius-sm);
570
576
  background: transparent;
571
- color: var(--token-text-muted);
572
- font-size: var(--density-font-size-xs);
577
+ color: var(--icen-token-text-muted);
578
+ font-size: var(--icen-density-font-size-xs);
573
579
  cursor: pointer;
574
580
  transition:
575
581
  color var(--icen-tx-fast),
576
582
  background-color var(--icen-tx-fast);
577
583
  }
578
- .ai-composer-model:hover {
579
- color: var(--token-text);
580
- background: var(--token-fill-2);
584
+ .icen-ai-composer-model:hover {
585
+ color: var(--icen-token-text);
586
+ background: var(--icen-token-fill-2);
581
587
  }
582
- .ai-composer-model:focus-visible {
588
+ .icen-ai-composer-model:focus-visible {
583
589
  outline: none;
584
590
  box-shadow: var(--icen-ring);
585
591
  }
586
- .ai-composer-model-icon,
587
- .ai-composer-model-provider-icon {
592
+ .icen-ai-composer-model-icon,
593
+ .icen-ai-composer-model-provider-icon {
588
594
  display: inline-flex;
589
595
  align-items: center;
590
596
  justify-content: center;
591
597
  flex-shrink: 0;
592
598
  }
593
- .ai-composer-model-provider-icon svg {
599
+ .icen-ai-composer-model-provider-icon svg {
594
600
  width: 14px;
595
601
  height: 14px;
596
602
  }
597
- .ai-composer-model-name {
603
+ .icen-ai-composer-model-name {
598
604
  overflow: hidden;
599
605
  text-overflow: ellipsis;
600
606
  white-space: nowrap;
601
607
  }
602
- .ai-composer-model-chevron {
608
+ .icen-ai-composer-model-chevron {
603
609
  display: inline-flex;
604
610
  align-items: center;
605
611
  justify-content: center;
606
612
  flex-shrink: 0;
607
- color: var(--token-text-faint);
613
+ color: var(--icen-token-text-faint);
608
614
  transition: transform var(--icen-tx-fast);
609
615
  }
610
- .ai-composer-model-chevron svg {
616
+ .icen-ai-composer-model-chevron svg {
611
617
  width: 12px;
612
618
  height: 12px;
613
619
  }
614
- .ai-composer-model[aria-expanded='true'] .ai-composer-model-chevron {
620
+ .icen-ai-composer-model[aria-expanded='true'] .icen-ai-composer-model-chevron {
615
621
  transform: rotate(180deg);
616
622
  }
617
623
 
618
624
  /* provider 图标缺失时的首字母圆形章(token 色) */
619
- .ai-composer-model-badge {
625
+ .icen-ai-composer-model-badge {
620
626
  display: inline-flex;
621
627
  align-items: center;
622
628
  justify-content: center;
623
629
  width: 16px;
624
630
  height: 16px;
625
- border-radius: var(--radius-full);
626
- background: color-mix(in srgb, var(--token-accent) 15%, transparent);
627
- color: var(--token-accent);
631
+ border-radius: var(--icen-radius-full);
632
+ background: color-mix(in srgb, var(--icen-token-accent) 15%, transparent);
633
+ color: var(--icen-token-accent);
628
634
  font-size: 10px;
629
635
  font-weight: 600;
630
636
  line-height: 1;
631
637
  user-select: none;
632
638
  }
633
- .ai-composer-model-icon .ai-composer-model-badge {
639
+ .icen-ai-composer-model-icon .icen-ai-composer-model-badge {
634
640
  width: 14px;
635
641
  height: 14px;
636
642
  font-size: 9px;
637
643
  }
638
644
 
639
- /* 用量环挂载点(环本体 .ai-usage-ring 在 ai-panel.css) */
640
- .ai-composer-usage {
645
+ /* 用量环挂载点(环本体 .icen-ai-usage-ring 在 ai-panel.css) */
646
+ .icen-ai-composer-usage {
641
647
  display: inline-flex;
642
648
  align-items: center;
643
649
  flex-shrink: 0;
644
650
  }
645
- .ai-composer-usage:empty {
651
+ .icen-ai-composer-usage:empty {
646
652
  display: none;
647
653
  }
648
654
 
649
655
  /* ── v2 弹层(portal body,模型/命令/引用三模式共用基座;定位 inline 由 behavior 写入)── */
650
656
 
651
- .ai-composer-popup {
657
+ .icen-ai-composer-popup {
652
658
  position: fixed;
653
- z-index: var(--z-popover);
659
+ z-index: var(--icen-z-popover);
654
660
  display: flex;
655
661
  flex-direction: column;
656
- padding: var(--density-space-2xs);
657
- border: 1px solid var(--token-line-soft);
658
- border-radius: var(--radius-md);
659
- background: var(--token-card-strong);
660
- box-shadow: var(--token-shadow-popover, var(--token-shadow-card));
662
+ padding: 6px;
663
+ border: 1px solid var(--icen-token-line);
664
+ border-radius: var(--icen-radius-lg);
665
+ background: var(--icen-token-card-strong);
666
+ box-shadow: var(--icen-token-shadow-popover, var(--icen-token-shadow-card));
661
667
  overflow: hidden;
662
- animation: icen-pop-in var(--ai-composer-popup-enter-duration, var(--duration-normal)) var(--ease-out);
668
+ animation: icen-pop-in var(--ai-composer-popup-enter-duration, var(--icen-duration-normal)) var(--icen-ease-out);
663
669
  }
664
670
 
665
671
  /* 搜索框(模型/引用过滤) */
666
- .ai-composer-popup-search {
672
+ .icen-ai-composer-popup-search {
673
+ display: flex;
674
+ align-items: center;
675
+ gap: 8px;
667
676
  flex-shrink: 0;
668
- padding: var(--density-space-2xs);
669
- border-bottom: 1px solid var(--token-line-soft);
670
- }
671
- .ai-composer-popup-search-input {
672
- width: 100%;
673
- padding: var(--density-space-2xs) var(--density-space-xs);
674
- border: 1px solid var(--token-line-soft);
675
- border-radius: var(--radius-sm);
676
- background: var(--token-panel);
677
- color: var(--token-text);
678
- font-size: var(--density-font-size-sm);
679
- outline: none;
680
- transition: border-color var(--icen-tx-fast);
681
- }
682
- .ai-composer-popup-search-input:focus {
683
- border-color: var(--token-accent);
677
+ padding: 4px 8px 8px;
678
+ color: var(--icen-token-text-muted);
679
+ border-bottom: 1px solid var(--icen-token-line-soft);
684
680
  }
685
- .ai-composer-popup-search-input::placeholder {
686
- color: var(--token-text-faint);
681
+ .icen-ai-composer-popup-search-input { min-inline-size: 0; }
682
+
683
+ .icen-ai-composer-popup-search-input::placeholder {
684
+ color: var(--icen-token-text-faint);
687
685
  }
688
686
 
689
687
  /* 列表(max-height inline 由 behavior 按 computePopoverLayout 写入) */
690
- .ai-composer-popup-list {
688
+ .icen-ai-composer-popup-list {
691
689
  flex: 1;
692
690
  min-height: 0;
693
691
  overflow-y: auto;
694
692
  overscroll-behavior: contain;
695
- padding: var(--density-space-2xs);
693
+ padding: var(--icen-density-space-2xs);
696
694
  }
697
695
 
698
696
  /* 分组(provider / ref kind) */
699
- .ai-composer-popup-group[hidden] {
697
+ .icen-ai-composer-popup-group[hidden] {
700
698
  display: none;
701
699
  }
702
- .ai-composer-popup-group-label {
700
+ .icen-ai-composer-popup-group-label {
703
701
  display: flex;
704
702
  align-items: center;
705
703
  gap: 4px;
706
- padding: var(--density-space-xs) var(--density-space-xs) var(--density-space-2xs);
707
- font-size: var(--density-font-size-2xs);
708
- color: var(--token-text-faint);
704
+ padding: var(--icen-density-space-xs) var(--icen-density-space-xs) var(--icen-density-space-2xs);
705
+ font-size: var(--icen-density-font-size-2xs);
706
+ color: var(--icen-token-text-faint);
709
707
  letter-spacing: 0.02em;
710
708
  }
711
- .ai-composer-popup-group-icon {
709
+ .icen-ai-composer-popup-group-icon {
712
710
  display: inline-flex;
713
711
  align-items: center;
714
712
  justify-content: center;
715
713
  flex-shrink: 0;
716
- color: var(--token-text-muted);
714
+ color: var(--icen-token-text-muted);
717
715
  }
718
- .ai-composer-popup-group-icon svg {
716
+ .icen-ai-composer-popup-group-icon svg {
719
717
  width: 12px;
720
718
  height: 12px;
721
719
  }
722
- .ai-composer-popup-group-icon .ai-composer-model-badge {
720
+ .icen-ai-composer-popup-group-icon .icen-ai-composer-model-badge {
723
721
  width: 12px;
724
722
  height: 12px;
725
723
  font-size: 8px;
726
724
  }
727
725
 
728
726
  /* 选项行(label + meta + check) */
729
- .ai-composer-popup-option {
727
+ .icen-ai-composer-popup-option {
730
728
  display: flex;
731
729
  align-items: center;
732
- gap: var(--density-space-xs);
730
+ gap: var(--icen-density-space-xs);
733
731
  width: 100%;
734
- padding: var(--density-space-xs);
732
+ min-block-size: 48px;
733
+ min-inline-size: 0;
734
+ padding: 8px;
735
735
  border: 0;
736
- border-radius: var(--radius-sm);
736
+ border-radius: var(--icen-radius-md);
737
737
  background: transparent;
738
- color: var(--token-text);
739
- font-size: var(--density-font-size-sm);
740
- text-align: left;
738
+ color: var(--icen-token-text);
739
+ font-size: var(--icen-density-font-size-sm);
740
+ text-align: start;
741
741
  cursor: pointer;
742
742
  transition: background-color var(--icen-tx-fast);
743
743
  }
744
- .ai-composer-popup-option:hover {
745
- background: var(--token-fill-2);
744
+ .icen-ai-composer-popup-option:hover {
745
+ background: var(--icen-token-fill-2);
746
746
  }
747
- .ai-composer-popup-option.is-focused {
748
- background: var(--token-fill-2);
747
+ .icen-ai-composer-popup-option.is-focused {
748
+ background: var(--icen-token-fill-2);
749
749
  }
750
- .ai-composer-popup-option:focus-visible {
750
+ .icen-ai-composer-popup-option:focus-visible {
751
751
  outline: none;
752
752
  box-shadow: var(--icen-ring);
753
753
  }
754
- .ai-composer-popup-option-icon {
754
+ .icen-ai-composer-popup-option-icon {
755
755
  display: inline-flex;
756
756
  align-items: center;
757
757
  justify-content: center;
758
758
  flex-shrink: 0;
759
- color: var(--token-text-muted);
759
+ color: var(--icen-token-text-muted);
760
760
  }
761
- .ai-composer-popup-option-icon svg {
761
+ .icen-ai-composer-popup-option-icon svg {
762
762
  width: 14px;
763
763
  height: 14px;
764
764
  }
765
- .ai-composer-popup-option-icon .ai-composer-model-badge {
765
+ .icen-ai-composer-popup-option-icon .icen-ai-composer-model-badge {
766
766
  width: 14px;
767
767
  height: 14px;
768
768
  font-size: 9px;
769
769
  }
770
- .ai-composer-popup-option-label {
770
+ .icen-ai-composer-popup-option-label {
771
771
  overflow: hidden;
772
772
  text-overflow: ellipsis;
773
773
  white-space: nowrap;
774
774
  }
775
- .ai-composer-popup-option-sub {
776
- margin-left: 6px;
777
- font-size: var(--density-font-size-2xs);
778
- color: var(--token-text-faint);
775
+ .icen-ai-composer-popup-option-sub {
776
+ display: block;
777
+ margin-block-start: 2px;
778
+ font-size: var(--icen-density-font-size-xs);
779
+ color: var(--icen-token-text-muted);
779
780
  }
780
- .ai-composer-popup-option-meta {
781
- margin-left: auto;
781
+ .icen-ai-composer-popup-option-meta {
782
+ margin-inline-start: auto;
782
783
  flex-shrink: 0;
783
- font-family: var(--font-mono);
784
- font-size: var(--density-font-size-2xs);
785
- color: var(--token-text-faint);
784
+ font-family: var(--icen-font-mono);
785
+ font-size: var(--icen-density-font-size-2xs);
786
+ color: var(--icen-token-text-faint);
786
787
  font-variant-numeric: tabular-nums;
787
788
  }
788
- .ai-composer-popup-option-check {
789
- display: none;
790
- flex-shrink: 0;
791
- color: var(--token-accent);
792
- }
793
- .ai-composer-popup-option-check svg {
794
- width: 12px;
795
- height: 12px;
796
- }
797
- .ai-composer-popup-option[aria-selected='true'] .ai-composer-popup-option-check {
798
- display: inline-flex;
799
- }
800
789
 
801
790
  /* 命令行:/name <argsHint> + 描述 */
802
- .ai-composer-popup-cmd {
803
- flex-direction: column;
804
- align-items: flex-start;
805
- gap: 1px;
791
+ .icen-ai-composer-popup-cmd {
792
+ flex-direction: row;
793
+ align-items: center;
806
794
  }
807
- .ai-composer-popup-cmd-line {
795
+ .icen-ai-composer-popup-cmd-line {
808
796
  display: flex;
809
797
  align-items: baseline;
810
798
  gap: 6px;
811
799
  max-width: 100%;
812
800
  }
813
- .ai-composer-popup-cmd-name {
814
- font-family: var(--font-mono);
815
- color: var(--token-accent);
801
+ .icen-ai-composer-popup-cmd-name {
802
+ font-family: var(--icen-font-mono);
803
+ color: var(--icen-token-text-muted);
816
804
  }
817
- .ai-composer-popup-cmd-args {
818
- font-family: var(--font-mono);
819
- font-size: var(--density-font-size-2xs);
820
- color: var(--token-text-faint);
805
+ .icen-ai-composer-popup-cmd-args {
806
+ font-family: var(--icen-font-mono);
807
+ font-size: var(--icen-density-font-size-2xs);
808
+ color: var(--icen-token-text-faint);
821
809
  }
822
- .ai-composer-popup-cmd-desc {
823
- font-size: var(--density-font-size-2xs);
824
- color: var(--token-text-muted);
810
+ .icen-ai-composer-popup-cmd-desc {
811
+ font-size: var(--icen-density-font-size-2xs);
812
+ color: var(--icen-token-text-muted);
825
813
  }
826
814
 
827
815
  /* 空态 */
828
- .ai-composer-popup-empty {
816
+ .icen-ai-composer-popup-empty {
829
817
  flex-shrink: 0;
830
- padding: var(--density-space-md);
818
+ padding: var(--icen-density-space-md);
831
819
  text-align: center;
832
- font-size: var(--density-font-size-sm);
833
- color: var(--token-text-faint);
820
+ font-size: var(--icen-density-font-size-sm);
821
+ color: var(--icen-token-text-faint);
834
822
  }
835
- .ai-composer-popup-empty[hidden] {
823
+ .icen-ai-composer-popup-empty[hidden] {
836
824
  display: none;
837
825
  }
838
826
 
839
827
  /* 底部提示(模型弹层:切换模型会使 prompt 缓存失效;cacheRead 占比高时 warning 色) */
840
- .ai-composer-popup-foot {
828
+ .icen-ai-composer-popup-foot {
841
829
  flex-shrink: 0;
842
830
  display: flex;
843
831
  align-items: center;
844
832
  gap: 4px;
845
- padding: var(--density-space-xs);
846
- border-top: 1px solid var(--token-line-soft);
847
- font-size: var(--density-font-size-2xs);
848
- color: var(--token-text-faint);
833
+ padding: var(--icen-density-space-xs);
834
+ border-top: 1px solid var(--icen-token-line-soft);
835
+ font-size: var(--icen-density-font-size-2xs);
836
+ color: var(--icen-token-text-faint);
849
837
  }
850
- .ai-composer-popup-foot svg {
838
+ .icen-ai-composer-popup-foot svg {
851
839
  width: 12px;
852
840
  height: 12px;
853
841
  flex-shrink: 0;
854
842
  }
855
- .ai-composer-popup-foot.is-warn {
856
- color: var(--token-warning);
843
+ .icen-ai-composer-popup-foot.is-warn {
844
+ color: var(--icen-token-warning);
857
845
  }
858
846
 
859
- /* ── 工具条按钮统一 28px 方形、svg 14px 居中(v1 旧结构按钮同样收敛)── */
847
+ /* ── 工具条按钮统一 28px 方形、svg 14px 居中 ── */
860
848
 
861
- .ai-composer-btn {
849
+ .icen-ai-composer-btn {
862
850
  display: inline-flex;
863
851
  align-items: center;
864
852
  justify-content: center;
@@ -866,29 +854,29 @@
866
854
  height: 28px;
867
855
  padding: 0;
868
856
  border: 1px solid transparent;
869
- border-radius: var(--radius-sm);
857
+ border-radius: var(--icen-radius-sm);
870
858
  background: transparent;
871
- color: var(--token-text-muted);
859
+ color: var(--icen-token-text-muted);
872
860
  cursor: pointer;
873
861
  transition:
874
862
  color var(--icen-tx-fast),
875
863
  background-color var(--icen-tx-fast);
876
864
  }
877
- .ai-composer-btn:hover {
878
- color: var(--token-text);
879
- background: var(--token-fill-2);
865
+ .icen-ai-composer-btn:hover {
866
+ color: var(--icen-token-text);
867
+ background: var(--icen-token-fill-2);
880
868
  }
881
- .ai-composer-btn:focus-visible {
869
+ .icen-ai-composer-btn:focus-visible {
882
870
  outline: none;
883
871
  box-shadow: var(--icen-ring);
884
872
  }
885
- .ai-composer-btn svg {
873
+ .icen-ai-composer-btn svg {
886
874
  width: 14px;
887
875
  height: 14px;
888
876
  }
889
877
 
890
878
  /* 发送钮:accent 实底;运行态 .is-stop 变停止钮(中性底 + error 色方标,停语气但不整钮铺红) */
891
- .ai-composer-send {
879
+ .icen-ai-composer-send {
892
880
  display: inline-flex;
893
881
  align-items: center;
894
882
  justify-content: center;
@@ -896,63 +884,63 @@
896
884
  height: 28px;
897
885
  padding: 0;
898
886
  border: 1px solid transparent;
899
- border-radius: var(--radius-sm);
900
- background: var(--token-accent);
901
- color: var(--token-on-accent);
887
+ border-radius: var(--icen-radius-sm);
888
+ background: var(--icen-token-accent-strong);
889
+ color: var(--icen-token-on-accent);
902
890
  cursor: pointer;
903
891
  transition:
904
892
  background-color var(--icen-tx-fast),
905
893
  color var(--icen-tx-fast),
906
894
  border-color var(--icen-tx-fast);
907
895
  }
908
- .ai-composer-send:hover {
909
- background: var(--token-accent-deep, var(--token-accent));
896
+ .icen-ai-composer-send:hover {
897
+ background: var(--icen-token-accent-deep, var(--icen-token-accent));
910
898
  }
911
- .ai-composer-send:focus-visible {
899
+ .icen-ai-composer-send:focus-visible {
912
900
  outline: none;
913
901
  box-shadow: var(--icen-ring);
914
902
  }
915
- .ai-composer-send svg {
903
+ .icen-ai-composer-send svg {
916
904
  width: 14px;
917
905
  height: 14px;
918
906
  }
919
- .ai-composer-send .ai-composer-send-icon[hidden] {
907
+ .icen-ai-composer-send .icen-ai-composer-send-icon[hidden] {
920
908
  display: none;
921
909
  }
922
- .ai-composer-send.is-stop {
923
- background: var(--token-surface-strong);
924
- color: var(--token-error);
925
- border-color: color-mix(in srgb, var(--token-error) 35%, transparent);
910
+ .icen-ai-composer-send.is-stop {
911
+ background: var(--icen-token-surface-strong);
912
+ color: var(--icen-token-error);
913
+ border-color: color-mix(in srgb, var(--icen-token-error) 35%, transparent);
926
914
  }
927
- .ai-composer-send.is-stop:hover {
928
- background: var(--token-error-muted);
915
+ .icen-ai-composer-send.is-stop:hover {
916
+ background: var(--icen-token-error-muted);
929
917
  }
930
918
 
931
919
  /* 运行态:输入台整体 busy 标记(aria-busy 等价,状态机语言) */
932
- .ai-composer.is-running .ai-composer-box {
933
- border-color: color-mix(in srgb, var(--token-accent) 30%, var(--token-line-soft));
920
+ .icen-ai-composer.is-running .icen-ai-composer-box {
921
+ border-color: color-mix(in srgb, var(--icen-token-accent) 30%, var(--icen-token-line-soft));
934
922
  }
935
923
 
936
924
  /* 拖放文件高亮(粘贴/拖放附件入口,spec §11) */
937
- .ai-composer-box.is-dragover {
938
- border-color: var(--token-accent);
925
+ .icen-ai-composer-box.is-dragover {
926
+ border-color: var(--icen-token-accent);
939
927
  box-shadow: var(--icen-ring);
940
928
  }
941
929
 
942
- /* ══════════════ data-density 三档(summary 纯 CSS 降噪) ══════════════ */
930
+ /* ══════════════ data-icen-density 三档(summary 纯 CSS 降噪) ══════════════ */
943
931
 
944
932
  /* summary:隐藏 meta、默认折叠 reasoning(head 展开仍可看)、次要消息压淡 */
945
- .ai-chat[data-density='summary'] .ai-msg-meta {
933
+ .icen-ai-chat[data-icen-density='summary'] .icen-ai-msg-meta {
946
934
  display: none;
947
935
  }
948
- .ai-chat[data-density='summary'] .ai-reasoning-body {
936
+ .icen-ai-chat[data-icen-density='summary'] .icen-ai-reasoning-body {
949
937
  display: none;
950
938
  }
951
- .ai-chat[data-density='summary'] .ai-reasoning:has(.ai-reasoning-head[aria-expanded='true']) .ai-reasoning-body {
939
+ .icen-ai-chat[data-icen-density='summary'] .icen-ai-reasoning:has(.icen-ai-reasoning-head[aria-expanded='true']) .icen-ai-reasoning-body {
952
940
  display: block;
953
941
  }
954
- .ai-chat[data-density='summary'] .ai-msg--tool,
955
- .ai-chat[data-density='summary'] .ai-msg--system {
942
+ .icen-ai-chat[data-icen-density='summary'] .icen-ai-msg--tool,
943
+ .icen-ai-chat[data-icen-density='summary'] .icen-ai-msg--system {
956
944
  opacity: 0.72;
957
945
  }
958
946
 
@@ -972,81 +960,89 @@
972
960
  /* ══════════════ 动效守卫 ══════════════ */
973
961
 
974
962
  @media (prefers-reduced-motion: reduce) {
975
- .ai-msg,
976
- .ai-chat-jump,
977
- .ai-composer-popup {
963
+ .icen-ai-msg,
964
+ .icen-ai-chat-jump,
965
+ .icen-ai-composer-popup {
978
966
  animation: none;
979
967
  }
980
- .ai-chat-jump,
981
- .ai-msg-actions,
982
- .ai-composer-chip-remove,
983
- .ai-composer-btn,
984
- .ai-composer-send,
985
- .ai-composer-model,
986
- .ai-composer-model-chevron,
987
- .ai-composer-popup-option,
988
- .ai-composer-popup-search-input,
989
- .ai-reasoning-head,
990
- .ai-reasoning-head::before {
968
+ .icen-ai-chat-jump,
969
+ .icen-ai-msg-actions,
970
+ .icen-ai-composer-chip-remove,
971
+ .icen-ai-composer-btn,
972
+ .icen-ai-composer-send,
973
+ .icen-ai-composer-model,
974
+ .icen-ai-composer-model-chevron,
975
+ .icen-ai-composer-popup-option,
976
+ .icen-ai-composer-popup-search-input,
977
+ .icen-ai-reasoning-head,
978
+ .icen-ai-reasoning-head::before {
991
979
  transition: none;
992
980
  }
993
- .ai-reasoning.is-streaming .ai-reasoning-head::after {
981
+ .icen-ai-reasoning.is-streaming .icen-ai-reasoning-head::after {
994
982
  animation: none;
995
983
  background: none;
996
984
  -webkit-text-fill-color: currentColor;
997
- color: var(--token-text-faint);
985
+ color: var(--icen-token-text-faint);
998
986
  }
999
- .ai-msg-body.is-streaming::after,
1000
- .ai-reasoning-body.is-streaming::after {
987
+ .icen-ai-msg-body.is-streaming::after,
988
+ .icen-ai-reasoning-body.is-streaming::after {
1001
989
  animation: none;
1002
990
  }
1003
991
  }
1004
992
 
1005
- /* 触屏无 hover:消息操作常显(否则不可达) */
993
+ /* 触屏无 hover:消息操作常显(否则不可达);动作钮抬到 44px 触达面
994
+ (copy/retry、分支切换、线程操作原为 20-22px,低于 WCAG 2.5.8 下限) */
1006
995
  @media (pointer: coarse) {
1007
- .ai-msg-actions {
996
+ .icen-ai-msg-actions {
1008
997
  opacity: 1;
1009
998
  visibility: visible;
1010
999
  transform: none;
1011
1000
  }
1001
+ .icen-ai-msg-actions [data-icen-ai-msg-action],
1002
+ .icen-ai-branch-prev,
1003
+ .icen-ai-branch-next,
1004
+ .icen-ai-thread-action {
1005
+ min-inline-size: 44px;
1006
+ min-block-size: 44px;
1007
+ }
1012
1008
  }
1013
1009
 
1014
1010
  /* 实时待办 chip(setComposerTodo:业界模式——plan 状态挂输入区,不进对话流) */
1015
- .ai-composer-todo {
1011
+ .icen-ai-composer-todo {
1016
1012
  display: inline-flex;
1017
1013
  align-items: center;
1018
1014
  gap: 5px;
1019
1015
  height: 28px;
1020
1016
  padding: 0 8px;
1021
- border: 1px solid var(--token-line-soft);
1022
- border-radius: var(--radius-full);
1023
- background: var(--token-surface);
1024
- color: var(--token-text-muted);
1025
- font-family: var(--font-mono);
1026
- font-size: var(--density-font-size-2xs);
1017
+ border: 1px solid var(--icen-token-line-soft);
1018
+ border-radius: var(--icen-radius-full);
1019
+ background: var(--icen-token-surface);
1020
+ color: var(--icen-token-text-muted);
1021
+ font-family: var(--icen-font-mono);
1022
+ font-size: var(--icen-density-font-size-2xs);
1027
1023
  font-variant-numeric: tabular-nums;
1028
1024
  cursor: pointer;
1029
1025
  transition: color var(--icen-tx-fast), border-color var(--icen-tx-fast);
1030
1026
  }
1031
- .ai-composer-todo svg { width: 13px; height: 13px; color: var(--token-accent); }
1032
- .ai-composer-todo:hover { border-color: var(--icen-hover-border, var(--token-line)); color: var(--token-text); }
1033
- .ai-composer-todo:focus-visible { outline: none; box-shadow: var(--icen-ring); }
1034
- .ai-composer-todo.is-done svg { color: var(--token-success); }
1035
- .ai-composer-todo.is-error svg { color: var(--token-warning); }
1036
- .ai-composer-todo-pop { min-width: 240px; max-width: 320px; }
1037
- .ai-composer-todo-pop .ai-todo { padding: 0; }
1027
+ .icen-ai-composer-todo svg { width: 13px; height: 13px; color: var(--icen-token-accent); }
1028
+ .icen-ai-composer-todo:hover { border-color: var(--icen-hover-border, var(--icen-token-line)); color: var(--icen-token-text); }
1029
+ .icen-ai-composer-todo:focus-visible { outline: none; box-shadow: var(--icen-ring); }
1030
+ .icen-ai-composer-todo.is-done svg { color: var(--icen-token-success); }
1031
+ .icen-ai-composer-todo.is-error svg { color: var(--icen-token-warning); }
1032
+ .icen-ai-composer-todo-pop { min-width: 240px; max-width: 320px; }
1033
+ .icen-ai-composer-todo-pop .icen-ai-todo { padding: 0; }
1038
1034
 
1039
1035
  /* ══════════════ ai-threads · 会话列表侧栏(§5.27,behaviors/ai-threads.ts) ══════════════ */
1040
1036
 
1041
1037
  /*
1042
- * <div class="ai-threads"> ← 240px 侧栏形态(--ai-threads-width 可调)
1043
- * <div class="ai-threads-group" data-group="今天" [.is-collapsed]>
1044
- * <button class="ai-threads-group-head" aria-expanded="true">今天</button>
1045
- * <div class="ai-threads-group-list">
1046
- * <div class="ai-thread [.is-active|.is-archived]" role="button" tabindex="0" data-key="…">
1047
- * <span class="ai-thread-icon">…svg…</span>
1048
- * <span class="ai-thread-label">…</span>
1049
- * <button class="ai-thread-action">···</button> ← 动作菜单挂载点(宿主实现)
1038
+ * <div class="icen-ai-threads"> ← 240px 侧栏形态(--ai-threads-width 可调)
1039
+ * <div class="icen-ai-threads-group" data-icen-group="今天" [.is-collapsed]>
1040
+ * <button class="icen-ai-threads-group-head" aria-expanded="true">今天</button>
1041
+ * <div class="icen-ai-threads-group-list">
1042
+ * <div class="icen-ai-thread [.is-active|.is-archived]" role="button" tabindex="0" data-icen-key="…">
1043
+ * <span class="icen-ai-thread-icon">…svg…</span>
1044
+ * <span class="icen-ai-thread-label">…</span>
1045
+ * <button class="icen-ai-thread-action">···</button> ← 动作菜单挂载点(宿主实现)
1050
1046
  * </div>…
1051
1047
  * </div>
1052
1048
  * </div>… ← 「已归档」组由 behavior 沉底
@@ -1054,123 +1050,133 @@
1054
1050
  * .is-active:左 2px accent;.is-archived:降透明;组头 11px faint。
1055
1051
  */
1056
1052
 
1057
- .ai-threads {
1053
+ .icen-ai-threads {
1058
1054
  display: flex;
1059
1055
  flex-direction: column;
1060
- gap: var(--density-space-xs);
1056
+ gap: var(--icen-density-space-xs);
1061
1057
  width: var(--ai-threads-width, 240px);
1062
1058
  min-width: 0;
1063
1059
  align-self: stretch; /* 宽度自稳定:宿主 flex/grid 居中时不 shrink-wrap */
1064
- font-size: var(--density-font-size-sm);
1060
+ font-size: var(--icen-density-font-size-sm);
1065
1061
  }
1066
1062
 
1067
- .ai-threads-group {
1063
+ .icen-ai-threads-group {
1068
1064
  display: flex;
1069
1065
  flex-direction: column;
1070
1066
  gap: 2px;
1071
1067
  min-width: 0;
1072
1068
  }
1073
1069
 
1074
- /* 组头:11px faint 小标,可折叠(aria-expanded 驱动 CSS 三角,与 .ai-reasoning-head 同款) */
1075
- .ai-threads-group-head {
1070
+ /* 组头:11px faint 小标,可折叠(aria-expanded 驱动 CSS 三角,与 .icen-ai-reasoning-head 同款) */
1071
+ .icen-ai-threads-group-head {
1076
1072
  display: flex;
1077
1073
  align-items: center;
1078
1074
  gap: 4px;
1079
- padding: var(--density-space-xs) 2px;
1075
+ padding: var(--icen-density-space-xs) 2px;
1080
1076
  border: 0;
1081
1077
  background: none;
1082
1078
  font-size: 11px;
1083
1079
  font-weight: 500;
1084
- color: var(--token-text-faint);
1080
+ color: var(--icen-token-text-faint);
1085
1081
  letter-spacing: 0.02em;
1086
- text-align: left;
1082
+ text-align: start;
1087
1083
  cursor: pointer;
1088
1084
  transition: color var(--icen-tx-fast);
1089
1085
  }
1090
- .ai-threads-group-head:hover {
1091
- color: var(--token-text-muted);
1086
+ .icen-ai-threads-group-head:hover {
1087
+ color: var(--icen-token-text-muted);
1092
1088
  }
1093
- .ai-threads-group-head:focus-visible {
1089
+ .icen-ai-threads-group-head:focus-visible {
1094
1090
  outline: none;
1095
1091
  box-shadow: var(--icen-ring);
1096
- border-radius: var(--radius-xs);
1092
+ border-radius: var(--icen-radius-xs);
1097
1093
  }
1098
- .ai-threads-group-head::before {
1094
+ .icen-ai-threads-group-head::before {
1099
1095
  content: '';
1100
1096
  flex-shrink: 0;
1101
- width: 6px;
1102
- height: 6px;
1103
- border-right: 1.5px solid currentColor;
1104
- border-bottom: 1.5px solid currentColor;
1105
- transform: rotate(-45deg);
1097
+ inline-size: 10px;
1098
+ block-size: 10px;
1099
+ background: currentColor;
1100
+ mask: var(--icen-token-icon-chevron-right) center / contain no-repeat;
1106
1101
  transition: transform var(--icen-tx-fast);
1107
1102
  }
1108
- .ai-threads-group-head[aria-expanded='true']::before {
1109
- transform: rotate(45deg);
1103
+ .icen-ai-threads-group-head[aria-expanded='true']::before {
1104
+ transform: rotate(90deg);
1110
1105
  }
1111
- .ai-threads-group.is-collapsed .ai-threads-group-list {
1106
+ .icen-ai-threads-group.is-collapsed .icen-ai-threads-group-list {
1112
1107
  display: none;
1113
1108
  }
1114
1109
 
1115
- .ai-threads-group-list {
1110
+ .icen-ai-threads-group-list {
1116
1111
  display: flex;
1117
1112
  flex-direction: column;
1118
1113
  gap: 1px;
1119
1114
  min-width: 0;
1120
1115
  }
1121
1116
 
1122
- /* 会话行:激活左 2px accent 线;归档降透明 */
1123
- .ai-thread {
1117
+ /* 会话行:中性容器(激活起始缘 2px accent 线);交互 affordance 归 .icen-ai-thread-main 真按钮 */
1118
+ .icen-ai-thread {
1124
1119
  position: relative;
1125
1120
  display: flex;
1126
1121
  align-items: center;
1127
- gap: var(--density-space-xs);
1128
- min-width: 0;
1129
- padding: var(--density-space-xs) var(--density-space-sm);
1130
- border-left: 2px solid transparent;
1131
- border-radius: var(--radius-xs);
1122
+ gap: var(--icen-density-space-xs);
1123
+ min-inline-size: 0;
1124
+ border-inline-start: 2px solid transparent;
1125
+ border-radius: var(--icen-radius-xs);
1132
1126
  background: transparent;
1133
- color: var(--token-text-muted);
1134
- font-size: var(--density-font-size-sm);
1135
- text-align: left;
1127
+ color: var(--icen-token-text-muted);
1128
+ font-size: var(--icen-density-font-size-sm);
1129
+ }
1130
+ .icen-ai-thread-main {
1131
+ flex: 1;
1132
+ min-inline-size: 0;
1133
+ display: flex;
1134
+ align-items: center;
1135
+ gap: var(--icen-density-space-xs);
1136
+ padding: var(--icen-density-space-xs) var(--icen-density-space-sm);
1137
+ border: 0;
1138
+ border-radius: var(--icen-radius-xs);
1139
+ background: transparent;
1140
+ color: inherit;
1141
+ font: inherit;
1142
+ text-align: start;
1136
1143
  cursor: pointer;
1137
1144
  transition:
1138
1145
  background-color var(--icen-tx-fast),
1139
- color var(--icen-tx-fast),
1140
- border-color var(--icen-tx-fast),
1141
- opacity var(--icen-tx-fast);
1146
+ color var(--icen-tx-fast);
1142
1147
  }
1143
- .ai-thread:hover {
1144
- background: var(--token-fill-1);
1145
- color: var(--token-text);
1148
+ .icen-ai-thread-main:hover {
1149
+ background: var(--icen-token-fill-1);
1150
+ color: var(--icen-token-text);
1146
1151
  }
1147
- .ai-thread:focus-visible {
1152
+ .icen-ai-thread-main:focus-visible {
1148
1153
  outline: none;
1149
1154
  box-shadow: var(--icen-ring);
1150
1155
  }
1151
- .ai-thread.is-active {
1152
- border-left-color: var(--token-accent);
1153
- background: var(--token-fill-1);
1154
- color: var(--token-text);
1156
+ .icen-ai-thread.is-active {
1157
+ border-inline-start-color: var(--icen-token-accent);
1158
+ background: var(--icen-token-fill-1);
1159
+ color: var(--icen-token-text);
1155
1160
  }
1156
- .ai-thread.is-archived {
1157
- opacity: 0.55;
1161
+ .icen-ai-thread.is-archived .icen-ai-thread-label {
1162
+ color: var(--icen-token-text-muted);
1158
1163
  }
1159
- .ai-thread-icon {
1164
+ .icen-ai-thread.is-archived .icen-ai-thread-icon { opacity: 0.7; }
1165
+ .icen-ai-thread-icon {
1160
1166
  display: inline-flex;
1161
1167
  align-items: center;
1162
1168
  justify-content: center;
1163
1169
  flex-shrink: 0;
1164
- color: var(--token-text-faint);
1170
+ color: var(--icen-token-text-faint);
1165
1171
  }
1166
- .ai-thread-icon svg {
1172
+ .icen-ai-thread-icon svg {
1167
1173
  width: 14px;
1168
1174
  height: 14px;
1169
1175
  }
1170
- .ai-thread.is-active .ai-thread-icon {
1171
- color: var(--token-accent);
1176
+ .icen-ai-thread.is-active .icen-ai-thread-icon {
1177
+ color: var(--icen-token-accent);
1172
1178
  }
1173
- .ai-thread-label {
1179
+ .icen-ai-thread-label {
1174
1180
  flex: 1;
1175
1181
  min-width: 0;
1176
1182
  overflow: hidden;
@@ -1179,7 +1185,7 @@
1179
1185
  }
1180
1186
 
1181
1187
  /* 动作钮「···」:hover/聚焦/激活才出现(菜单本体由宿主经 icen:ai-thread-action 实现) */
1182
- .ai-thread-action {
1188
+ .icen-ai-thread-action {
1183
1189
  display: none;
1184
1190
  flex-shrink: 0;
1185
1191
  align-items: center;
@@ -1188,9 +1194,9 @@
1188
1194
  height: 20px;
1189
1195
  padding: 0;
1190
1196
  border: 0;
1191
- border-radius: var(--radius-xs);
1197
+ border-radius: var(--icen-radius-xs);
1192
1198
  background: transparent;
1193
- color: var(--token-text-faint);
1199
+ color: var(--icen-token-text-faint);
1194
1200
  font-size: 13px;
1195
1201
  font-weight: 700;
1196
1202
  letter-spacing: 0.04em;
@@ -1200,16 +1206,16 @@
1200
1206
  color var(--icen-tx-fast),
1201
1207
  background-color var(--icen-tx-fast);
1202
1208
  }
1203
- .ai-thread:hover .ai-thread-action,
1204
- .ai-thread:focus-within .ai-thread-action,
1205
- .ai-thread.is-active .ai-thread-action {
1209
+ .icen-ai-thread:hover .icen-ai-thread-action,
1210
+ .icen-ai-thread:focus-within .icen-ai-thread-action,
1211
+ .icen-ai-thread.is-active .icen-ai-thread-action {
1206
1212
  display: inline-flex;
1207
1213
  }
1208
- .ai-thread-action:hover {
1209
- color: var(--token-accent);
1210
- background: var(--token-fill-2);
1214
+ .icen-ai-thread-action:hover {
1215
+ color: var(--icen-token-accent);
1216
+ background: var(--icen-token-fill-2);
1211
1217
  }
1212
- .ai-thread-action:focus-visible {
1218
+ .icen-ai-thread-action:focus-visible {
1213
1219
  outline: none;
1214
1220
  box-shadow: var(--icen-ring);
1215
1221
  }
@@ -1217,22 +1223,22 @@
1217
1223
  /* ══════════════ ai-branch · 分支版本切换器(§5.27,behaviors/ai-branch.ts) ══════════════ */
1218
1224
 
1219
1225
  /*
1220
- * <div class="ai-branch" data-index data-count role="group">
1221
- * <button class="ai-branch-prev" [disabled]>‹</button>
1222
- * <span class="ai-branch-page">2/3</span> ← mono 数字(当前从 1 计)
1223
- * <button class="ai-branch-next" [disabled]>›</button>
1226
+ * <div class="icen-ai-branch" data-icen-index data-icen-count role="group">
1227
+ * <button class="icen-ai-branch-prev" [disabled]>‹</button>
1228
+ * <span class="icen-ai-branch-page">2/3</span> ← icen-mono 数字(当前从 1 计)
1229
+ * <button class="icen-ai-branch-next" [disabled]>›</button>
1224
1230
  * </div>
1225
1231
  * count ≤ 1 时挂载容器由 behavior 置空 + hidden/aria-hidden(此处无额外规则)。
1226
1232
  */
1227
1233
 
1228
- .ai-branch {
1234
+ .icen-ai-branch {
1229
1235
  display: inline-flex;
1230
1236
  align-items: center;
1231
1237
  gap: 3px;
1232
- color: var(--token-text-muted);
1238
+ color: var(--icen-token-text-muted);
1233
1239
  }
1234
- .ai-branch-prev,
1235
- .ai-branch-next {
1240
+ .icen-ai-branch-prev,
1241
+ .icen-ai-branch-next {
1236
1242
  display: inline-flex;
1237
1243
  align-items: center;
1238
1244
  justify-content: center;
@@ -1240,10 +1246,10 @@
1240
1246
  height: 22px;
1241
1247
  padding: 0;
1242
1248
  border: 0;
1243
- border-radius: var(--radius-xs);
1249
+ border-radius: var(--icen-radius-xs);
1244
1250
  background: transparent;
1245
- color: var(--token-text-muted);
1246
- font-family: var(--font-mono);
1251
+ color: var(--icen-token-text-muted);
1252
+ font-family: var(--icen-font-mono);
1247
1253
  font-size: 13px;
1248
1254
  line-height: 1;
1249
1255
  cursor: pointer;
@@ -1251,46 +1257,48 @@
1251
1257
  color var(--icen-tx-fast),
1252
1258
  background-color var(--icen-tx-fast);
1253
1259
  }
1254
- .ai-branch-prev:hover,
1255
- .ai-branch-next:hover {
1256
- color: var(--token-text);
1257
- background: var(--token-fill-1);
1260
+ .icen-ai-branch-prev:hover,
1261
+ .icen-ai-branch-next:hover {
1262
+ color: var(--icen-token-text);
1263
+ background: var(--icen-token-fill-1);
1258
1264
  }
1259
- .ai-branch-prev:focus-visible,
1260
- .ai-branch-next:focus-visible {
1265
+ .icen-ai-branch-prev:focus-visible,
1266
+ .icen-ai-branch-next:focus-visible {
1261
1267
  outline: none;
1262
1268
  box-shadow: var(--icen-ring);
1263
1269
  }
1264
- .ai-branch-prev:disabled,
1265
- .ai-branch-next:disabled {
1270
+ .icen-ai-branch-prev:disabled,
1271
+ .icen-ai-branch-next:disabled {
1266
1272
  opacity: 0.4;
1267
1273
  cursor: default;
1268
1274
  background: transparent;
1269
1275
  }
1270
- .ai-branch-page {
1271
- min-width: 2.5em;
1276
+ .icen-ai-branch-page {
1277
+ min-inline-size: 2.5em;
1272
1278
  text-align: center;
1273
- font-family: var(--font-mono);
1274
- font-size: var(--density-font-size-xs);
1275
- color: var(--token-text-faint);
1279
+ font-family: var(--icen-font-mono);
1280
+ font-size: var(--icen-density-font-size-xs);
1281
+ color: var(--icen-token-text-faint);
1276
1282
  font-variant-numeric: tabular-nums;
1277
1283
  user-select: none;
1278
1284
  }
1279
1285
 
1280
1286
  /* ══════════════ ai-msg-continue · aborted「继续生成」槽(§5.27,createAiStream fail/cancel) ══════════════ */
1281
1287
 
1282
- /* ghost 小钮右浮:挂在 .ai-msg-body 尾部(消息尾),点按 → icen:ai-retry {el} */
1283
- .ai-msg-continue {
1288
+ /* ghost 小钮行内末端浮动:挂在 .icen-ai-msg-body 尾部(消息尾),点按 → icen:ai-retry {el} */
1289
+ .icen-ai-msg-continue {
1284
1290
  display: inline-flex;
1285
1291
  align-items: center;
1286
- float: right;
1287
- margin: var(--density-space-2xs, 2px) 0 0 var(--density-space-xs);
1292
+ float: inline-end;
1293
+ margin-block-start: var(--icen-density-space-2xs, 2px);
1294
+ margin-inline-end: 0;
1295
+ margin-inline-start: var(--icen-density-space-xs);
1288
1296
  padding: 2px 10px;
1289
- border: 1px solid var(--token-line);
1290
- border-radius: var(--radius-full);
1297
+ border: 1px solid var(--icen-token-line);
1298
+ border-radius: var(--icen-radius-full);
1291
1299
  background: transparent;
1292
- color: var(--token-text-muted);
1293
- font-size: var(--density-font-size-xs);
1300
+ color: var(--icen-token-text-muted);
1301
+ font-size: var(--icen-density-font-size-xs);
1294
1302
  white-space: nowrap;
1295
1303
  cursor: pointer;
1296
1304
  transition:
@@ -1298,35 +1306,127 @@
1298
1306
  border-color var(--icen-tx-fast),
1299
1307
  background-color var(--icen-tx-fast);
1300
1308
  }
1301
- .ai-msg-continue:hover {
1302
- color: var(--token-accent);
1309
+ .icen-ai-msg-continue:hover {
1310
+ color: var(--icen-token-accent);
1303
1311
  border-color: var(--icen-hover-border);
1304
- background: var(--token-fill-1);
1312
+ background: var(--icen-token-fill-1);
1305
1313
  }
1306
- .ai-msg-continue:focus-visible {
1314
+ .icen-ai-msg-continue:focus-visible {
1307
1315
  outline: none;
1308
1316
  box-shadow: var(--icen-ring);
1309
1317
  }
1310
1318
 
1311
- /* §5.27 reasoning 自动收起无新样式:复用 .ai-reasoning 既有折叠/耗时规则 */
1319
+ /* §5.27 reasoning 自动收起无新样式:复用 .icen-ai-reasoning 既有折叠/耗时规则 */
1312
1320
 
1313
1321
  /* ── 动效守卫(§5.27 新增段) ── */
1314
1322
 
1315
1323
  @media (prefers-reduced-motion: reduce) {
1316
- .ai-thread,
1317
- .ai-thread-action,
1318
- .ai-threads-group-head,
1319
- .ai-threads-group-head::before,
1320
- .ai-branch-prev,
1321
- .ai-branch-next,
1322
- .ai-msg-continue {
1324
+ .icen-ai-thread,
1325
+ .icen-ai-thread-action,
1326
+ .icen-ai-threads-group-head,
1327
+ .icen-ai-threads-group-head::before,
1328
+ .icen-ai-branch-prev,
1329
+ .icen-ai-branch-next,
1330
+ .icen-ai-msg-continue {
1323
1331
  transition: none;
1324
1332
  }
1325
1333
  }
1326
1334
 
1327
1335
  /* 触屏无 hover:动作钮常显(否则不可达) */
1328
1336
  @media (pointer: coarse) {
1329
- .ai-thread .ai-thread-action {
1337
+ .icen-ai-thread .icen-ai-thread-action {
1330
1338
  display: inline-flex;
1331
1339
  }
1332
1340
  }
1341
+
1342
+ /* ── RTL:方向性指示镜像(共享 chevron mask 经 scaleX(-1) 翻转向左) ── */
1343
+ :is([dir='rtl']) .icen-ai-reasoning-head::before { transform: scaleX(-1); }
1344
+ :is([dir='rtl']) .icen-ai-reasoning:has(.icen-ai-reasoning-head[aria-expanded='true']) .icen-ai-reasoning-head::before { transform: rotate(90deg) scaleX(-1); }
1345
+ :is([dir='rtl']) .icen-ai-threads-group-head::before { transform: scaleX(-1); }
1346
+ :is([dir='rtl']) .icen-ai-threads-group-head[aria-expanded='true']::before { transform: rotate(90deg) scaleX(-1); }
1347
+
1348
+ .icen-ai-composer-model-chevron, .icen-ai-composer-popup-option-check { display: none; }
1349
+
1350
+ /* Context has its own quiet material: icon tile → readable name → secondary detail.
1351
+ The theme owns all hues; primitive tokens own geometry. No brand-specific gradients. */
1352
+ .icen-ai-composer-popup-option-copy { display: flex; flex: 1; flex-direction: column; min-inline-size: 0; }
1353
+ .icen-ai-composer-popup-option-copy > .icen-ai-composer-popup-option-label { font-weight: 550; }
1354
+ .icen-ai-composer-popup-option-icon,
1355
+ .icen-ai-composer-chip-icon {
1356
+ display: inline-flex;
1357
+ align-items: center;
1358
+ justify-content: center;
1359
+ flex: 0 0 auto;
1360
+ inline-size: 30px;
1361
+ block-size: 30px;
1362
+ border-radius: var(--icen-radius-sm);
1363
+ background: color-mix(in srgb, var(--icen-token-accent) 9%, var(--icen-token-surface));
1364
+ color: var(--icen-token-accent);
1365
+ }
1366
+ .icen-ai-composer-popup-option-icon svg { inline-size: 18px; block-size: 18px; }
1367
+ .icen-ai-composer-chip-icon,
1368
+ .icen-ai-composer-chip > .icen-ai-composer-popup-option-icon { inline-size: 22px; block-size: 22px; background: transparent; }
1369
+ .icen-ai-composer-chip-icon svg,
1370
+ .icen-ai-composer-chip > .icen-ai-composer-popup-option-icon svg { inline-size: 16px; block-size: 16px; }
1371
+ .icen-ai-composer-chip-remove svg { inline-size: 14px; block-size: 14px; }
1372
+ .icen-ai-composer-chip-text { min-inline-size: 0; }
1373
+ .icen-ai-composer-chip-meta { color: var(--icen-token-text-muted); font-size: var(--icen-density-font-size-2xs); white-space: nowrap; }
1374
+ .icen-ai-msg-context { display: flex; flex-wrap: wrap; gap: 6px; margin-block-start: 8px; min-inline-size: 0; }
1375
+ .icen-ai-composer-refs .icen-ai-composer-chip {
1376
+ border-color: color-mix(in srgb, var(--icen-token-accent) 18%, var(--icen-token-line-soft));
1377
+ background: color-mix(in srgb, var(--icen-token-accent) 5%, var(--icen-token-surface));
1378
+ }
1379
+ .icen-ai-composer-popup-option-sub { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1380
+ .icen-ai-composer-popup-option[aria-selected='true'] {
1381
+ background: color-mix(in srgb, var(--icen-token-accent) 9%, var(--icen-token-surface));
1382
+ box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--icen-token-accent) 34%, transparent);
1383
+ }
1384
+ .icen-ai-composer-popup-option[aria-disabled='true'] { opacity: .5; cursor: default; }
1385
+ .icen-ai-composer-popup-option[hidden] { display: none; }
1386
+ .icen-ai-composer-popup-option mark {
1387
+ padding: 0;
1388
+ border-radius: var(--icen-radius-xs);
1389
+ color: inherit;
1390
+ background: color-mix(in srgb, var(--icen-token-accent) 18%, transparent);
1391
+ }
1392
+ .icen-ai-composer-popup-filters {
1393
+ display: flex;
1394
+ flex: 0 0 auto;
1395
+ gap: 4px;
1396
+ overflow-x: auto;
1397
+ overscroll-behavior-inline: contain;
1398
+ padding: 8px 2px;
1399
+ }
1400
+ .icen-ai-composer-popup-filters button {
1401
+ flex: 0 0 auto;
1402
+ min-block-size: 32px;
1403
+ padding: 4px 10px;
1404
+ border: 0;
1405
+ border-radius: var(--icen-radius-sm);
1406
+ background: transparent;
1407
+ color: var(--icen-token-text-muted);
1408
+ font: inherit;
1409
+ font-size: var(--icen-density-font-size-xs);
1410
+ cursor: pointer;
1411
+ }
1412
+ .icen-ai-composer-popup-filters button[aria-pressed='true'] { background: var(--icen-token-fill-2); color: var(--icen-token-text); box-shadow: inset 0 0 0 1px var(--icen-token-line); }
1413
+ .icen-ai-composer-popup-filters button:focus-visible { outline: 2px solid var(--icen-token-accent); outline-offset: -2px; }
1414
+ .icen-ai-composer-popup-cmd-line { min-inline-size: 0; flex-wrap: wrap; row-gap: 0; }
1415
+ .icen-ai-composer-popup-cmd-name, .icen-ai-composer-popup-cmd-args { overflow-wrap: anywhere; }
1416
+ .icen-ai-composer-library { background: var(--icen-token-fill-2); color: var(--icen-token-text); }
1417
+ .icen-ai-composer-model { min-inline-size: 0; max-inline-size: min(180px, 46%); }
1418
+ .icen-ai-composer[data-icen-composer-size='compact'] .icen-ai-composer-input { min-block-size: 32px; }
1419
+ @media (pointer: coarse) {
1420
+ .icen-ai-composer-chip-remove, .icen-ai-composer-btn, .icen-ai-composer-send,
1421
+ .icen-ai-composer-model, .icen-ai-composer-popup-filters button { min-inline-size: 44px; min-block-size: 44px; }
1422
+ .icen-ai-composer-input { font-size: max(16px, var(--icen-density-font-size-md)); }
1423
+ }
1424
+ @media (forced-colors: active) {
1425
+ .icen-ai-composer:focus-within { outline: 1px solid Highlight; }
1426
+ .icen-ai-composer-popup-option[aria-selected='true'], .icen-ai-composer-popup-filters button[aria-pressed='true'] { outline: 2px solid Highlight; outline-offset: -2px; }
1427
+ .icen-ai-composer-popup-option.is-focused { outline: 1px solid CanvasText; outline-offset: -1px; }
1428
+ .icen-ai-composer-popup-option-icon { border: 1px solid ButtonText; }
1429
+ }
1430
+ @media (prefers-reduced-motion: reduce) { .icen-ai-composer { transition: none; } }
1431
+
1432
+ }