@icen.ai/ui 0.8.1 → 0.10.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 (335) hide show
  1. package/AGENTS.md +176 -75
  2. package/README.md +66 -88
  3. package/dist/base.css +208 -179
  4. package/dist/behaviors/accordion.mjs +8 -8
  5. package/dist/behaviors/ai-branch.d.mts +19 -0
  6. package/dist/behaviors/ai-branch.mjs +1133 -0
  7. package/dist/behaviors/ai-chat.d.mts +12 -10
  8. package/dist/behaviors/ai-chat.mjs +1125 -155
  9. package/dist/behaviors/ai-composer.d.mts +44 -12
  10. package/dist/behaviors/ai-composer.mjs +2084 -523
  11. package/dist/behaviors/ai-core.d.mts +1 -1
  12. package/dist/behaviors/ai-core.mjs +1016 -107
  13. package/dist/behaviors/ai-diff.mjs +1019 -127
  14. package/dist/behaviors/ai-feedback.d.mts +26 -0
  15. package/dist/behaviors/ai-feedback.mjs +1212 -0
  16. package/dist/behaviors/ai-panel.d.mts +21 -7
  17. package/dist/behaviors/ai-panel.mjs +1308 -264
  18. package/dist/behaviors/ai-provider.mjs +1003 -101
  19. package/dist/behaviors/ai-threads.d.mts +38 -0
  20. package/dist/behaviors/ai-threads.mjs +1233 -0
  21. package/dist/behaviors/ai-tool.d.mts +2 -2
  22. package/dist/behaviors/ai-tool.mjs +2042 -396
  23. package/dist/behaviors/ai-tools.d.mts +89 -16
  24. package/dist/behaviors/ai-tools.mjs +4453 -372
  25. package/dist/behaviors/autocomplete.d.mts +53 -0
  26. package/dist/behaviors/autocomplete.mjs +1600 -0
  27. package/dist/behaviors/back-top.d.mts +1 -1
  28. package/dist/behaviors/back-top.mjs +951 -14
  29. package/dist/behaviors/carousel.d.mts +1 -1
  30. package/dist/behaviors/carousel.mjs +906 -11
  31. package/dist/behaviors/cascader.d.mts +48 -0
  32. package/dist/behaviors/cascader.mjs +1853 -0
  33. package/dist/behaviors/charts.d.mts +174 -8
  34. package/dist/behaviors/charts.mjs +2632 -192
  35. package/dist/behaviors/code-block.d.mts +36 -0
  36. package/dist/behaviors/code-block.mjs +1611 -0
  37. package/dist/behaviors/command-palette.d.mts +9 -6
  38. package/dist/behaviors/command-palette.mjs +161 -59
  39. package/dist/behaviors/context-menu.d.mts +9 -8
  40. package/dist/behaviors/context-menu.mjs +1112 -44
  41. package/dist/behaviors/controls.d.mts +13 -13
  42. package/dist/behaviors/controls.mjs +989 -130
  43. package/dist/behaviors/copy.d.mts +21 -2
  44. package/dist/behaviors/copy.mjs +1206 -42
  45. package/dist/behaviors/datatable.d.mts +53 -3
  46. package/dist/behaviors/datatable.mjs +1963 -207
  47. package/dist/behaviors/date-picker.d.mts +0 -1
  48. package/dist/behaviors/date-picker.mjs +1340 -293
  49. package/dist/behaviors/design.d.mts +54 -0
  50. package/dist/behaviors/design.mjs +109 -0
  51. package/dist/behaviors/dropdown.d.mts +5 -6
  52. package/dist/behaviors/dropdown.mjs +262 -110
  53. package/dist/behaviors/events.d.mts +313 -3
  54. package/dist/behaviors/events.mjs +47 -2
  55. package/dist/behaviors/feedback.d.mts +30 -0
  56. package/dist/behaviors/feedback.mjs +296 -0
  57. package/dist/behaviors/focus.d.mts +8 -0
  58. package/dist/behaviors/focus.mjs +24 -0
  59. package/dist/behaviors/form-validate.d.mts +102 -0
  60. package/dist/behaviors/form-validate.mjs +6091 -0
  61. package/dist/behaviors/i18n.d.mts +789 -0
  62. package/dist/behaviors/i18n.mjs +1711 -0
  63. package/dist/behaviors/icons.d.mts +93 -0
  64. package/dist/behaviors/icons.mjs +113 -0
  65. package/dist/behaviors/input.d.mts +9 -1
  66. package/dist/behaviors/input.mjs +1056 -60
  67. package/dist/behaviors/kb-access.d.mts +34 -0
  68. package/dist/behaviors/kb-access.mjs +2459 -0
  69. package/dist/behaviors/kb-acl.d.mts +50 -0
  70. package/dist/behaviors/kb-acl.mjs +1345 -0
  71. package/dist/behaviors/kb-answer.d.mts +38 -0
  72. package/dist/behaviors/kb-answer.mjs +3707 -0
  73. package/dist/behaviors/kb-audit.d.mts +23 -0
  74. package/dist/behaviors/kb-audit.mjs +1297 -0
  75. package/dist/behaviors/kb-canvas.d.mts +44 -0
  76. package/dist/behaviors/kb-canvas.mjs +1512 -0
  77. package/dist/behaviors/kb-chain.d.mts +15 -0
  78. package/dist/behaviors/kb-chain.mjs +1192 -0
  79. package/dist/behaviors/kb-checkpoint.d.mts +16 -0
  80. package/dist/behaviors/kb-checkpoint.mjs +1492 -0
  81. package/dist/behaviors/kb-chunks.d.mts +31 -0
  82. package/dist/behaviors/kb-chunks.mjs +1414 -0
  83. package/dist/behaviors/kb-citation.d.mts +38 -0
  84. package/dist/behaviors/kb-citation.mjs +1699 -0
  85. package/dist/behaviors/kb-clarify.d.mts +20 -0
  86. package/dist/behaviors/kb-clarify.mjs +1176 -0
  87. package/dist/behaviors/kb-conflict.d.mts +22 -0
  88. package/dist/behaviors/kb-conflict.mjs +1206 -0
  89. package/dist/behaviors/kb-connector.d.mts +17 -0
  90. package/dist/behaviors/kb-connector.mjs +1303 -0
  91. package/dist/behaviors/kb-core.d.mts +534 -0
  92. package/dist/behaviors/kb-core.mjs +1805 -0
  93. package/dist/behaviors/kb-eval.d.mts +22 -0
  94. package/dist/behaviors/kb-eval.mjs +2235 -0
  95. package/dist/behaviors/kb-explain.d.mts +11 -0
  96. package/dist/behaviors/kb-explain.mjs +1165 -0
  97. package/dist/behaviors/kb-filter.d.mts +31 -0
  98. package/dist/behaviors/kb-filter.mjs +2417 -0
  99. package/dist/behaviors/kb-gap.d.mts +27 -0
  100. package/dist/behaviors/kb-gap.mjs +1195 -0
  101. package/dist/behaviors/kb-hittest.d.mts +34 -0
  102. package/dist/behaviors/kb-hittest.mjs +1352 -0
  103. package/dist/behaviors/kb-metadata.d.mts +29 -0
  104. package/dist/behaviors/kb-metadata.mjs +1248 -0
  105. package/dist/behaviors/kb-passage.d.mts +41 -0
  106. package/dist/behaviors/kb-passage.mjs +1469 -0
  107. package/dist/behaviors/kb-pipeline.d.mts +18 -0
  108. package/dist/behaviors/kb-pipeline.mjs +1301 -0
  109. package/dist/behaviors/kb-qa.d.mts +26 -0
  110. package/dist/behaviors/kb-qa.mjs +1260 -0
  111. package/dist/behaviors/kb-rerank.d.mts +20 -0
  112. package/dist/behaviors/kb-rerank.mjs +1248 -0
  113. package/dist/behaviors/kb-retrieval.d.mts +49 -0
  114. package/dist/behaviors/kb-retrieval.mjs +2585 -0
  115. package/dist/behaviors/kb-review.d.mts +44 -0
  116. package/dist/behaviors/kb-review.mjs +2282 -0
  117. package/dist/behaviors/kb-sandbox.d.mts +33 -0
  118. package/dist/behaviors/kb-sandbox.mjs +1247 -0
  119. package/dist/behaviors/kb-segment.d.mts +32 -0
  120. package/dist/behaviors/kb-segment.mjs +1431 -0
  121. package/dist/behaviors/kb-select.d.mts +24 -0
  122. package/dist/behaviors/kb-select.mjs +1989 -0
  123. package/dist/behaviors/kb-sources.d.mts +27 -0
  124. package/dist/behaviors/kb-sources.mjs +1287 -0
  125. package/dist/behaviors/kb-sql.d.mts +43 -0
  126. package/dist/behaviors/kb-sql.mjs +1865 -0
  127. package/dist/behaviors/kb-trace.d.mts +16 -0
  128. package/dist/behaviors/kb-trace.mjs +1328 -0
  129. package/dist/behaviors/kb-visibility.d.mts +44 -0
  130. package/dist/behaviors/kb-visibility.mjs +1331 -0
  131. package/dist/behaviors/kb-who-can.d.mts +32 -0
  132. package/dist/behaviors/kb-who-can.mjs +2216 -0
  133. package/dist/behaviors/mentions.d.mts +93 -0
  134. package/dist/behaviors/mentions.mjs +2152 -0
  135. package/dist/behaviors/modal.d.mts +4 -3
  136. package/dist/behaviors/modal.mjs +1055 -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 +1615 -265
  141. package/dist/behaviors/panel.d.mts +4 -0
  142. package/dist/behaviors/panel.mjs +994 -0
  143. package/dist/behaviors/popover.d.mts +28 -5
  144. package/dist/behaviors/popover.mjs +225 -24
  145. package/dist/behaviors/select.d.mts +5 -2
  146. package/dist/behaviors/select.mjs +1410 -117
  147. package/dist/behaviors/sidebar.d.mts +1 -1
  148. package/dist/behaviors/sidebar.mjs +13 -13
  149. package/dist/behaviors/slider.d.mts +1 -1
  150. package/dist/behaviors/slider.mjs +9 -9
  151. package/dist/behaviors/split-pane.d.mts +1 -1
  152. package/dist/behaviors/split-pane.mjs +7 -7
  153. package/dist/behaviors/suggestions.d.mts +27 -0
  154. package/dist/behaviors/suggestions.mjs +1089 -0
  155. package/dist/behaviors/svg-parse.d.mts +14 -0
  156. package/dist/behaviors/svg-parse.mjs +37 -0
  157. package/dist/behaviors/tabs.d.mts +2 -2
  158. package/dist/behaviors/tabs.mjs +25 -25
  159. package/dist/behaviors/tag-input.d.mts +23 -5
  160. package/dist/behaviors/tag-input.mjs +1359 -104
  161. package/dist/behaviors/theme-switcher.d.mts +24 -0
  162. package/dist/behaviors/theme-switcher.mjs +1981 -0
  163. package/dist/behaviors/theme.d.mts +15 -8
  164. package/dist/behaviors/theme.mjs +390 -28
  165. package/dist/behaviors/toast.d.mts +24 -25
  166. package/dist/behaviors/toast.mjs +1266 -88
  167. package/dist/behaviors/tooltip.d.mts +4 -0
  168. package/dist/behaviors/tooltip.mjs +378 -0
  169. package/dist/behaviors/tree-select.d.mts +69 -0
  170. package/dist/behaviors/tree-select.mjs +1907 -0
  171. package/dist/behaviors/tree.d.mts +1 -1
  172. package/dist/behaviors/tree.mjs +15 -15
  173. package/dist/behaviors/upload.d.mts +3 -2
  174. package/dist/behaviors/upload.mjs +1076 -66
  175. package/dist/cli.mjs +5 -6
  176. package/dist/components/ai-branch.mjs +3 -0
  177. package/dist/components/ai-chat.css +846 -458
  178. package/dist/components/ai-diff.css +153 -132
  179. package/dist/components/ai-feedback.mjs +3 -0
  180. package/dist/components/ai-panel.css +495 -270
  181. package/dist/components/ai-threads.mjs +3 -0
  182. package/dist/components/ai-tool.css +393 -238
  183. package/dist/components/autocomplete.css +61 -0
  184. package/dist/components/autocomplete.mjs +3 -0
  185. package/dist/components/back-top.css +34 -31
  186. package/dist/components/badge.css +44 -41
  187. package/dist/components/breadcrumb.css +67 -46
  188. package/dist/components/btn.css +80 -74
  189. package/dist/components/card.css +117 -106
  190. package/dist/components/cascader.css +311 -0
  191. package/dist/components/cascader.mjs +3 -0
  192. package/dist/components/chart-area.css +8 -2
  193. package/dist/components/chart-bar.css +95 -33
  194. package/dist/components/chart-gauge.css +14 -11
  195. package/dist/components/chart-graph.css +60 -0
  196. package/dist/components/chart-graph.mjs +4 -0
  197. package/dist/components/chart-heatmap.css +96 -90
  198. package/dist/components/chart-line.css +8 -3
  199. package/dist/components/chart-map.mjs +3 -0
  200. package/dist/components/chart-pie.css +9 -6
  201. package/dist/components/chart-radar.css +8 -5
  202. package/dist/components/chart-scatter.css +9 -6
  203. package/dist/components/chart-scatter.mjs +1 -1
  204. package/dist/components/chart-sparkline.css +5 -2
  205. package/dist/components/chart-stack.css +14 -11
  206. package/dist/components/charts.css +190 -67
  207. package/dist/components/charts.mjs +1 -0
  208. package/dist/components/code-block.css +418 -0
  209. package/dist/components/code-block.mjs +4 -0
  210. package/dist/components/command-palette.css +138 -117
  211. package/dist/components/content.css +257 -251
  212. package/dist/components/copy.css +72 -44
  213. package/dist/components/datatable.css +423 -181
  214. package/dist/components/date-picker.css +135 -104
  215. package/dist/components/empty.css +68 -65
  216. package/dist/components/feedback.css +201 -183
  217. package/dist/components/form-validate.css +120 -0
  218. package/dist/components/form-validate.mjs +3 -0
  219. package/dist/components/form.css +150 -127
  220. package/dist/components/icon.css +102 -0
  221. package/dist/components/icon.mjs +3 -0
  222. package/dist/components/input.css +159 -104
  223. package/dist/components/kb-access.mjs +4 -0
  224. package/dist/components/kb-acl.mjs +4 -0
  225. package/dist/components/kb-agent.css +496 -0
  226. package/dist/components/kb-answer.mjs +4 -0
  227. package/dist/components/kb-audit.mjs +4 -0
  228. package/dist/components/kb-canvas.mjs +4 -0
  229. package/dist/components/kb-chain.mjs +4 -0
  230. package/dist/components/kb-checkpoint.mjs +4 -0
  231. package/dist/components/kb-chunks.mjs +4 -0
  232. package/dist/components/kb-citation.mjs +4 -0
  233. package/dist/components/kb-clarify.mjs +4 -0
  234. package/dist/components/kb-conflict.mjs +4 -0
  235. package/dist/components/kb-connector.mjs +4 -0
  236. package/dist/components/kb-data.css +653 -0
  237. package/dist/components/kb-eval.mjs +4 -0
  238. package/dist/components/kb-explain.mjs +4 -0
  239. package/dist/components/kb-filter.mjs +4 -0
  240. package/dist/components/kb-gap.mjs +4 -0
  241. package/dist/components/kb-ground.css +578 -0
  242. package/dist/components/kb-hittest.mjs +4 -0
  243. package/dist/components/kb-ingest.css +882 -0
  244. package/dist/components/kb-metadata.mjs +4 -0
  245. package/dist/components/kb-ops.css +554 -0
  246. package/dist/components/kb-passage.mjs +4 -0
  247. package/dist/components/kb-perm.css +433 -0
  248. package/dist/components/kb-pipeline.mjs +4 -0
  249. package/dist/components/kb-qa.mjs +4 -0
  250. package/dist/components/kb-rerank.mjs +4 -0
  251. package/dist/components/kb-retrieval.mjs +4 -0
  252. package/dist/components/kb-review.mjs +4 -0
  253. package/dist/components/kb-sandbox.mjs +4 -0
  254. package/dist/components/kb-search.css +897 -0
  255. package/dist/components/kb-segment.mjs +4 -0
  256. package/dist/components/kb-sources.mjs +4 -0
  257. package/dist/components/kb-sql.mjs +4 -0
  258. package/dist/components/kb-trace.mjs +4 -0
  259. package/dist/components/kb-visibility.mjs +4 -0
  260. package/dist/components/kb-who-can.mjs +4 -0
  261. package/dist/components/kb.css +263 -0
  262. package/dist/components/kb.mjs +9 -0
  263. package/dist/components/layout.css +85 -82
  264. package/dist/components/material-chinese.css +73 -0
  265. package/dist/components/material-soviet.css +76 -0
  266. package/dist/components/material.css +275 -0
  267. package/dist/components/media.css +220 -166
  268. package/dist/components/mentions.css +189 -0
  269. package/dist/components/mentions.mjs +3 -0
  270. package/dist/components/menu.css +113 -105
  271. package/dist/components/modal.css +107 -112
  272. package/dist/components/nav.css +118 -115
  273. package/dist/components/notification.css +238 -174
  274. package/dist/components/pagination.css +56 -53
  275. package/dist/components/panel.css +66 -63
  276. package/dist/components/panel.mjs +1 -0
  277. package/dist/components/pill.css +81 -71
  278. package/dist/components/popover.css +67 -53
  279. package/dist/components/scroll-area.css +113 -110
  280. package/dist/components/segmented.css +146 -143
  281. package/dist/components/select.css +206 -186
  282. package/dist/components/sidebar.css +137 -127
  283. package/dist/components/slider.css +117 -114
  284. package/dist/components/split-pane.css +112 -109
  285. package/dist/components/stat.css +112 -106
  286. package/dist/components/steps.css +109 -103
  287. package/dist/components/switch.css +138 -134
  288. package/dist/components/table.css +131 -107
  289. package/dist/components/tabs.css +114 -108
  290. package/dist/components/tag-input.css +48 -133
  291. package/dist/components/tag.css +81 -71
  292. package/dist/components/theme-switcher.css +105 -0
  293. package/dist/components/theme-switcher.mjs +3 -0
  294. package/dist/components/toast.css +100 -86
  295. package/dist/components/toolbar.css +45 -42
  296. package/dist/components/tooltip.css +102 -43
  297. package/dist/components/tooltip.mjs +1 -0
  298. package/dist/components/tree-select.css +416 -0
  299. package/dist/components/tree-select.mjs +3 -0
  300. package/dist/components/upload.css +135 -92
  301. package/dist/fonts/LICENSES/ark-pixel/OFL.txt +96 -0
  302. package/dist/fonts/LICENSES/cubic-11/OFL.txt +108 -0
  303. package/dist/fonts/LICENSES/galmuri/LICENSE.txt +93 -0
  304. package/dist/fonts/OFL.txt +96 -0
  305. package/dist/fonts/README.md +14 -0
  306. package/dist/fonts/fusion-pixel-12px-zh-hans.woff2 +0 -0
  307. package/dist/index.d.mts +64 -15
  308. package/dist/index.mjs +28049 -8595
  309. package/dist/react.d.mts +91 -0
  310. package/dist/react.mjs +8208 -0
  311. package/dist/registry.json +454 -15
  312. package/dist/tokens/chinese.css +44 -0
  313. package/dist/tokens/colors.css +365 -1222
  314. package/dist/tokens/design.css +109 -0
  315. package/dist/tokens/dtcg.json +11198 -0
  316. package/dist/tokens/figma.variables.json +7017 -0
  317. package/dist/tokens/icon-masks.css +78 -0
  318. package/dist/tokens/pixel.css +50 -0
  319. package/dist/tokens/soviet.css +44 -0
  320. package/dist/tokens/style-profiles.css +36 -547
  321. package/dist/tokens/themes.json +308 -0
  322. package/dist/tokens/tokens-studio.json +6728 -0
  323. package/dist/tokens/typography.css +21 -18
  324. package/dist/tokens.css +1555 -1801
  325. package/dist/ui.css +16147 -8597
  326. package/dist/vue.d.mts +344 -0
  327. package/dist/vue.mjs +7781 -0
  328. package/docs/spec/ai-input-experience.md +75 -0
  329. package/docs/spec/ai-native.md +238 -147
  330. package/docs/spec/design-philosophy.md +189 -0
  331. package/docs/spec/design-primitives.md +196 -0
  332. package/docs/spec/kb-family.md +475 -0
  333. package/package.json +42 -7
  334. package/dist/retro-effects.css +0 -255
  335. package/dist/tokens/retro-effects.css +0 -255
@@ -1,172 +1,173 @@
1
+ @layer icen.components {
1
2
  /*
2
3
  * @icen.ai/ui — Component: ai-panel(AI 任务面板族:todo / context / usage,与 behaviors/ai-panel.ts 配套)
3
4
  *
4
5
  * 完整 DOM 契约(类名与规格 §4.8/§4.9/§4.10 一致):
5
- * <div class="ai-todo" [.is-complete] [data-ai-todo-interactive]>
6
- * <div class="ai-todo-head">
7
- * <span class="ai-todo-progress">2/5</span>
8
- * <div class="ai-todo-bar" role="progressbar" …><i style="width:40%"></i></div>
6
+ * <div class="icen-ai-todo" [.is-complete] [data-icen-ai-todo-interactive]>
7
+ * <div class="icen-ai-todo-head">
8
+ * <span class="icen-ai-todo-progress">2/5</span>
9
+ * <div class="icen-ai-todo-bar" role="progressbar" …><i style="width:40%"></i></div>
9
10
  * </div>
10
- * <div class="ai-todo-item is-pending|running|streaming|approval|done|error|cancelled
11
- * [role="button" tabindex="0"]" data-index="0">
12
- * <span class="ai-item-status"></span> <!-- 状态点,纯 CSS 由 .is-* 驱动 -->
13
- * <span class="ai-todo-text">实现登录页</span>
14
- * <span class="ai-todo-active">正在实现登录页…</span> <!-- is-running 时替换 text(CSS 驱动) -->
11
+ * <div class="icen-ai-todo-item is-pending|running|streaming|approval|done|error|cancelled
12
+ * [role="button" tabindex="0"]" data-icen-index="0">
13
+ * <span class="icen-ai-item-status"></span> <!-- 状态点,纯 CSS 由 .is-* 驱动 -->
14
+ * <span class="icen-ai-todo-text">实现登录页</span>
15
+ * <span class="icen-ai-todo-active">正在实现登录页…</span> <!-- is-running 时替换 text(CSS 驱动) -->
15
16
  * </div>
16
17
  * </div>
17
18
  *
18
- * <div class="ai-usage">
19
- * <div class="ai-usage-bar" role="img" aria-label="…">
20
- * <i class="ai-usage-seg ai-usage-seg--input|output|cache-read|cache-write|reasoning" style="width:35%"></i>…
19
+ * <div class="icen-ai-usage">
20
+ * <div class="icen-ai-usage-bar" role="img" aria-label="…">
21
+ * <i class="icen-ai-usage-seg icen-ai-usage-seg--input|output|cache-read|cache-write|reasoning" style="width:35%"></i>…
21
22
  * </div>
22
- * <div class="ai-usage-legend">
23
- * <span class="ai-usage-legend-item">
24
- * <i class="ai-usage-dot ai-usage-seg--input"></i>
25
- * <span class="ai-usage-legend-label">输入</span> <span class="ai-usage-legend-value">35k</span>
23
+ * <div class="icen-ai-usage-legend">
24
+ * <span class="icen-ai-usage-legend-item">
25
+ * <i class="icen-ai-usage-dot icen-ai-usage-seg--input"></i>
26
+ * <span class="icen-ai-usage-legend-label">输入</span> <span class="icen-ai-usage-legend-value">35k</span>
26
27
  * </span>…
27
28
  * </div>
28
- * <div class="ai-usage-total">82k / 200k · 41%</div>
29
+ * <div class="icen-ai-usage-total">82k / 200k · 41%</div>
29
30
  * </div>
30
31
  *
31
- * <aside class="ai-context [.ai-context--inline]" hidden role="dialog" aria-label="上下文">
32
- * <div class="ai-context-head"><span>上下文</span>
33
- * <button type="button" data-ai-context-close aria-label="关闭">×</button></div>
34
- * <section class="ai-context-section"><h3>…</h3>
35
- * <div class="ai-context-section-body">…renderAiContext 产物…</div> <!-- 可选包裹,亦可直接放内容 -->
32
+ * <aside class="icen-ai-context [.icen-ai-context--inline]" hidden role="dialog" aria-label="上下文">
33
+ * <div class="icen-ai-context-head"><span>上下文</span>
34
+ * <button type="button" data-icen-ai-context-close aria-label="关闭">×</button></div>
35
+ * <section class="icen-ai-context-section"><h3>…</h3>
36
+ * <div class="icen-ai-context-section-body">…renderAiContext 产物…</div> <!-- 可选包裹,亦可直接放内容 -->
36
37
  * </section>…
37
38
  * </aside>
38
39
  *
39
- * .ai-item 行(MCP / Skills,规格 §2 基元):
40
- * <div class="ai-item is-done|is-error" style="--ai-item-tint: var(--token-accent)">
41
- * <span class="ai-item-icon">…svg…</span>
42
- * <span class="ai-item-main">
43
- * <span class="ai-item-title">github</span><span class="ai-item-sub">…</span>
40
+ * .icen-ai-item 行(MCP / Skills,规格 §2 基元):
41
+ * <div class="icen-ai-item is-done|is-error" style="--ai-item-tint: var(--icen-token-accent)">
42
+ * <span class="icen-ai-item-icon">…svg…</span>
43
+ * <span class="icen-ai-item-main">
44
+ * <span class="icen-ai-item-title">github</span><span class="icen-ai-item-sub">…</span>
44
45
  * </span>
45
- * <span class="ai-item-side"><span class="ai-item-status"></span><span class="ai-item-meta">12 工具</span></span>
46
+ * <span class="icen-ai-item-side"><span class="icen-ai-item-status"></span><span class="icen-ai-item-meta">12 工具</span></span>
46
47
  * </div>
47
48
  *
48
49
  * 依赖说明:
49
- * - .ai-item 完整版在 ai-tool.css(S2)。此处按任务约定重新声明最小骨架(含 --ai-item-tint
50
+ * - .icen-ai-item 完整版在 ai-tool.css(S2)。此处按任务约定重新声明最小骨架(含 --ai-item-tint
50
51
  * 局部变量与状态点),保证 ai-panel.css 单独引入时 todo/context 可用;两边类名/语义一致,
51
52
  * 同页面共存时后加载者覆盖同款属性,视觉不冲突。
52
53
  * - keyframes ai-status-pulse 为组件局部定义(等同 pill.css 的 pill-pulse),
53
54
  * 时长走 var(--pill-pulse-duration, 1.5s):pill.css 在场时与其同步,否则自洽。
54
- * - blink keyframes 来自 tokens/colors.css(.animate-blink 同款,共享复用)。
55
- * - base.css:--z-chrome / --icen-tx-* / --icen-ring。只消费 --token-* / --density-* / --radius-*。
55
+ * - blink keyframes 来自 tokens/colors.css(.icen-animate-blink 同款,共享复用)。
56
+ * - base.css:--icen-z-chrome / --icen-tx-* / --icen-ring。只消费 --icen-token-* / --icen-density-* / --icen-radius-*。
56
57
  */
57
58
 
58
- /* ══════════════ .ai-item 最小基元(自包含,兼容 ai-tool.css 完整版) ══════════════ */
59
+ /* ══════════════ .icen-ai-item 最小基元(自包含,兼容 ai-tool.css 完整版) ══════════════ */
59
60
 
60
- .ai-item {
61
- --ai-item-tint: var(--token-accent);
61
+ .icen-ai-item {
62
+ --ai-item-tint: var(--icen-token-accent);
62
63
  display: flex;
63
64
  align-items: center;
64
- gap: var(--density-space-sm);
65
- padding: var(--density-space-xs) var(--density-space-sm);
66
- border-radius: var(--radius-sm);
67
- font-size: var(--density-font-size-sm);
65
+ gap: var(--icen-density-space-sm);
66
+ padding: var(--icen-density-space-xs) var(--icen-density-space-sm);
67
+ border-radius: var(--icen-radius-sm);
68
+ font-size: var(--icen-density-font-size-sm);
68
69
  min-width: 0;
69
70
  align-self: stretch; /* 宽度自稳定:宿主 flex/grid 居中时不 shrink-wrap */
70
71
  }
71
72
 
72
- .ai-item-icon {
73
+ .icen-ai-item-icon {
73
74
  flex-shrink: 0;
74
75
  display: inline-flex;
75
76
  color: var(--ai-item-tint);
76
77
  }
77
- .ai-item-icon svg {
78
+ .icen-ai-item-icon svg {
78
79
  width: 15px;
79
80
  height: 15px;
80
81
  }
81
82
 
82
- .ai-item-main {
83
+ .icen-ai-item-main {
83
84
  flex: 1;
84
85
  min-width: 0;
85
86
  display: flex;
86
87
  flex-direction: column;
87
88
  gap: 1px;
88
89
  }
89
- .ai-item-title {
90
- color: var(--token-text);
90
+ .icen-ai-item-title {
91
+ color: var(--icen-token-text);
91
92
  line-height: 1.4;
92
93
  overflow: hidden;
93
94
  text-overflow: ellipsis;
94
95
  white-space: nowrap;
95
96
  }
96
- .ai-item-sub {
97
- font-size: var(--density-font-size-xs);
98
- color: var(--token-text-muted);
97
+ .icen-ai-item-sub {
98
+ font-size: var(--icen-density-font-size-xs);
99
+ color: var(--icen-token-text-muted);
99
100
  overflow: hidden;
100
101
  text-overflow: ellipsis;
101
102
  white-space: nowrap;
102
103
  }
103
104
 
104
- .ai-item-side {
105
+ .icen-ai-item-side {
105
106
  flex-shrink: 0;
106
107
  display: inline-flex;
107
108
  align-items: center;
108
- gap: var(--density-space-xs);
109
+ gap: var(--icen-density-space-xs);
109
110
  }
110
- .ai-item-meta {
111
- font-size: var(--density-font-size-xs);
112
- color: var(--token-text-faint);
111
+ .icen-ai-item-meta {
112
+ font-size: var(--icen-density-font-size-xs);
113
+ color: var(--icen-token-text-faint);
113
114
  font-variant-numeric: tabular-nums;
114
115
  }
115
116
 
116
- /* ── 状态点 .ai-item-status:纯 CSS 圆点,由 .is-* 驱动(ai-item 与 ai-todo-item 共用) ── */
117
+ /* ── 状态点 .icen-ai-item-status:纯 CSS 圆点,由 .is-* 驱动(ai-item 与 ai-todo-item 共用) ── */
117
118
 
118
- .ai-item-status {
119
+ .icen-ai-item-status {
119
120
  flex-shrink: 0;
120
121
  width: 8px;
121
122
  height: 8px;
122
- border-radius: var(--radius-full);
123
- border: 1.5px solid var(--token-text-faint);
123
+ border-radius: var(--icen-radius-full);
124
+ border: 1.5px solid var(--icen-token-text-faint);
124
125
  background: transparent;
125
126
  }
126
127
 
127
128
  /* pending:faint 空心点(默认态即空心) */
128
- .ai-item.is-pending > .ai-item-status,
129
- .ai-todo-item.is-pending > .ai-item-status { }
129
+ .icen-ai-item.is-pending > .icen-ai-item-status,
130
+ .icen-ai-todo-item.is-pending > .icen-ai-item-status { }
130
131
 
131
132
  /* running / streaming:accent 脉冲点 */
132
- .ai-item.is-running > .ai-item-status,
133
- .ai-todo-item.is-running > .ai-item-status,
134
- .ai-item.is-streaming > .ai-item-status,
135
- .ai-todo-item.is-streaming > .ai-item-status {
136
- border-color: var(--token-accent);
137
- background: var(--token-accent);
133
+ .icen-ai-item.is-running > .icen-ai-item-status,
134
+ .icen-ai-todo-item.is-running > .icen-ai-item-status,
135
+ .icen-ai-item.is-streaming > .icen-ai-item-status,
136
+ .icen-ai-todo-item.is-streaming > .icen-ai-item-status {
137
+ border-color: var(--icen-token-accent);
138
+ background: var(--icen-token-accent);
138
139
  animation: ai-status-pulse var(--pill-pulse-duration, 1.5s) ease-in-out infinite;
139
140
  }
140
141
 
141
142
  /* approval:warning 点 */
142
- .ai-item.is-approval > .ai-item-status,
143
- .ai-todo-item.is-approval > .ai-item-status {
144
- border-color: var(--token-warning);
145
- background: var(--token-warning);
143
+ .icen-ai-item.is-approval > .icen-ai-item-status,
144
+ .icen-ai-todo-item.is-approval > .icen-ai-item-status {
145
+ border-color: var(--icen-token-warning);
146
+ background: var(--icen-token-warning);
146
147
  }
147
148
 
148
149
  /* done:success 点 */
149
- .ai-item.is-done > .ai-item-status,
150
- .ai-todo-item.is-done > .ai-item-status {
151
- border-color: var(--token-success);
152
- background: var(--token-success);
150
+ .icen-ai-item.is-done > .icen-ai-item-status,
151
+ .icen-ai-todo-item.is-done > .icen-ai-item-status {
152
+ border-color: var(--icen-token-success);
153
+ background: var(--icen-token-success);
153
154
  }
154
155
 
155
156
  /* error:error 点 */
156
- .ai-item.is-error > .ai-item-status,
157
- .ai-todo-item.is-error > .ai-item-status {
158
- border-color: var(--token-error);
159
- background: var(--token-error);
157
+ .icen-ai-item.is-error > .icen-ai-item-status,
158
+ .icen-ai-todo-item.is-error > .icen-ai-item-status {
159
+ border-color: var(--icen-token-error);
160
+ background: var(--icen-token-error);
160
161
  }
161
162
 
162
163
  /* cancelled:faint 实心点 + 标题删除线(规格 §1) */
163
- .ai-item.is-cancelled > .ai-item-status,
164
- .ai-todo-item.is-cancelled > .ai-item-status {
165
- border-color: var(--token-text-faint);
166
- background: var(--token-text-faint);
164
+ .icen-ai-item.is-cancelled > .icen-ai-item-status,
165
+ .icen-ai-todo-item.is-cancelled > .icen-ai-item-status {
166
+ border-color: var(--icen-token-text-faint);
167
+ background: var(--icen-token-text-faint);
167
168
  }
168
- .ai-item.is-cancelled .ai-item-title,
169
- .ai-todo-item.is-cancelled .ai-todo-text {
169
+ .icen-ai-item.is-cancelled .icen-ai-item-title,
170
+ .icen-ai-todo-item.is-cancelled .icen-ai-todo-text {
170
171
  text-decoration: line-through;
171
172
  }
172
173
 
@@ -178,71 +179,71 @@
178
179
 
179
180
  /* ══════════════ ai-todo · 任务清单(§4.8) ══════════════ */
180
181
 
181
- .ai-todo {
182
+ .icen-ai-todo {
182
183
  display: flex;
183
184
  flex-direction: column;
184
- gap: var(--density-space-xs);
185
- font-size: var(--density-font-size-sm);
185
+ gap: var(--icen-density-space-xs);
186
+ font-size: var(--icen-density-font-size-sm);
186
187
  min-width: 0;
187
188
  align-self: stretch; /* 输出容器宽度自稳定 */
188
189
  }
189
190
 
190
- .ai-todo-head {
191
+ .icen-ai-todo-head {
191
192
  display: flex;
192
193
  align-items: center;
193
- gap: var(--density-space-sm);
194
+ gap: var(--icen-density-space-sm);
194
195
  min-width: 0;
195
196
  }
196
197
 
197
- .ai-todo-progress {
198
+ .icen-ai-todo-progress {
198
199
  flex-shrink: 0;
199
- font-size: var(--density-font-size-xs);
200
- color: var(--token-text-muted);
200
+ font-size: var(--icen-density-font-size-xs);
201
+ color: var(--icen-token-text-muted);
201
202
  font-variant-numeric: tabular-nums;
202
203
  }
203
204
 
204
205
  /* 进度条:feedback progress 视觉(token 消费) */
205
- .ai-todo-bar {
206
+ .icen-ai-todo-bar {
206
207
  flex: 1;
207
208
  height: 4px;
208
- border-radius: var(--radius-full);
209
+ border-radius: var(--icen-radius-full);
209
210
  overflow: hidden;
210
- background: color-mix(in srgb, var(--token-line-soft) 40%, transparent);
211
+ background: color-mix(in srgb, var(--icen-token-line-soft) 40%, transparent);
211
212
  }
212
- .ai-todo-bar > i {
213
+ .icen-ai-todo-bar > i {
213
214
  display: block;
214
215
  height: 100%;
215
- border-radius: var(--radius-full);
216
- background: var(--token-accent);
216
+ border-radius: var(--icen-radius-full);
217
+ background: var(--icen-token-accent);
217
218
  transition: width var(--icen-tx-slow);
218
219
  }
219
- .ai-todo.is-complete .ai-todo-bar > i {
220
- background: var(--token-success);
220
+ .icen-ai-todo.is-complete .icen-ai-todo-bar > i {
221
+ background: var(--icen-token-success);
221
222
  }
222
223
 
223
- .ai-todo-item {
224
+ .icen-ai-todo-item {
224
225
  display: flex;
225
226
  align-items: center;
226
- gap: var(--density-space-sm);
227
- padding: 3px var(--density-space-xs);
228
- border-radius: var(--radius-xs);
227
+ gap: var(--icen-density-space-sm);
228
+ padding: 3px var(--icen-density-space-xs);
229
+ border-radius: var(--icen-radius-xs);
229
230
  min-width: 0;
230
231
  }
231
232
 
232
233
  /* 交互模式(initAiTodo 升级 role=button) */
233
- .ai-todo-item[role='button'] {
234
+ .icen-ai-todo-item[role='button'] {
234
235
  cursor: pointer;
235
236
  transition: background-color var(--icen-tx-fast);
236
237
  }
237
- .ai-todo-item[role='button']:hover {
238
- background: var(--token-fill-1);
238
+ .icen-ai-todo-item[role='button']:hover {
239
+ background: var(--icen-token-fill-1);
239
240
  }
240
- .ai-todo-item:focus-visible {
241
+ .icen-ai-todo-item:focus-visible {
241
242
  outline: none;
242
243
  box-shadow: var(--icen-ring);
243
244
  }
244
245
 
245
- .ai-todo-text {
246
+ .icen-ai-todo-text {
246
247
  min-width: 0;
247
248
  overflow: hidden;
248
249
  text-overflow: ellipsis;
@@ -250,45 +251,45 @@
250
251
  }
251
252
 
252
253
  /* activeForm:运行中替换式强调(Claude Code 模式) */
253
- .ai-todo-active {
254
+ .icen-ai-todo-active {
254
255
  display: none;
255
256
  min-width: 0;
256
257
  overflow: hidden;
257
258
  text-overflow: ellipsis;
258
259
  white-space: nowrap;
259
- color: var(--token-accent-deep);
260
+ color: var(--icen-token-accent-deep);
260
261
  }
261
- .ai-todo-item.is-running .ai-todo-text { display: none; }
262
- .ai-todo-item.is-running .ai-todo-active { display: inline; }
262
+ .icen-ai-todo-item.is-running .icen-ai-todo-text { display: none; }
263
+ .icen-ai-todo-item.is-running .icen-ai-todo-active { display: inline; }
263
264
 
264
265
  /* done/cancelled:淡化 + 删除线 */
265
- .ai-todo-item.is-done .ai-todo-text,
266
- .ai-todo-item.is-cancelled .ai-todo-text {
267
- color: var(--token-text-faint);
266
+ .icen-ai-todo-item.is-done .icen-ai-todo-text,
267
+ .icen-ai-todo-item.is-cancelled .icen-ai-todo-text {
268
+ color: var(--icen-token-text-faint);
268
269
  text-decoration: line-through;
269
270
  }
270
271
 
271
272
  /* ══════════════ ai-usage · 用量条(§4.9) ══════════════ */
272
273
 
273
- .ai-usage {
274
+ .icen-ai-usage {
274
275
  display: flex;
275
276
  flex-direction: column;
276
- gap: var(--density-space-xs);
277
- font-size: var(--density-font-size-xs);
278
- color: var(--token-text-muted);
277
+ gap: var(--icen-density-space-xs);
278
+ font-size: var(--icen-density-font-size-xs);
279
+ color: var(--icen-token-text-muted);
279
280
  min-width: 0;
280
281
  align-self: stretch; /* 输出容器宽度自稳定 */
281
282
  }
282
283
 
283
- .ai-usage-bar {
284
+ .icen-ai-usage-bar {
284
285
  display: flex;
285
286
  height: 6px;
286
- border-radius: var(--radius-full);
287
+ border-radius: var(--icen-radius-full);
287
288
  overflow: hidden;
288
- background: color-mix(in srgb, var(--token-line-soft) 40%, transparent);
289
+ background: color-mix(in srgb, var(--icen-token-line-soft) 40%, transparent);
289
290
  }
290
291
 
291
- .ai-usage-seg {
292
+ .icen-ai-usage-seg {
292
293
  display: block;
293
294
  height: 100%;
294
295
  min-width: 0;
@@ -296,41 +297,41 @@
296
297
  }
297
298
 
298
299
  /* 配色契约:input=accent / output=success / cacheRead=info / cacheWrite=warning / reasoning=faint */
299
- .ai-usage-seg--input { background: var(--token-accent); }
300
- .ai-usage-seg--output { background: var(--token-success); }
301
- .ai-usage-seg--cache-read { background: var(--token-info); }
302
- .ai-usage-seg--cache-write { background: var(--token-warning); }
303
- .ai-usage-seg--reasoning { background: var(--token-text-faint); }
300
+ .icen-ai-usage-seg--input { background: var(--icen-token-accent); }
301
+ .icen-ai-usage-seg--output { background: var(--icen-token-success); }
302
+ .icen-ai-usage-seg--cache-read { background: var(--icen-token-info); }
303
+ .icen-ai-usage-seg--cache-write { background: var(--icen-token-warning); }
304
+ .icen-ai-usage-seg--reasoning { background: var(--icen-token-text-faint); }
304
305
 
305
306
  /* 图例:色点 + 标签 + 数值(缓存分列,计费诚实) */
306
- .ai-usage-legend {
307
+ .icen-ai-usage-legend {
307
308
  display: flex;
308
309
  flex-wrap: wrap;
309
- gap: var(--density-space-xs) var(--density-space-sm);
310
+ gap: var(--icen-density-space-xs) var(--icen-density-space-sm);
310
311
  }
311
- .ai-usage-legend-item {
312
+ .icen-ai-usage-legend-item {
312
313
  display: inline-flex;
313
314
  align-items: center;
314
315
  gap: 5px;
315
316
  font-variant-numeric: tabular-nums;
316
317
  }
317
- .ai-usage-dot {
318
+ .icen-ai-usage-dot {
318
319
  flex-shrink: 0;
319
320
  width: 8px;
320
321
  height: 8px;
321
- border-radius: var(--radius-full);
322
+ border-radius: var(--icen-radius-full);
322
323
  }
323
- .ai-usage-legend-label { color: var(--token-text-muted); }
324
- .ai-usage-legend-value { color: var(--token-text); font-weight: 500; }
324
+ .icen-ai-usage-legend-label { color: var(--icen-token-text-muted); }
325
+ .icen-ai-usage-legend-value { color: var(--icen-token-text); font-weight: 500; }
325
326
 
326
- .ai-usage-total {
327
+ .icen-ai-usage-total {
327
328
  font-variant-numeric: tabular-nums;
328
- color: var(--token-text-muted);
329
+ color: var(--icen-token-text-muted);
329
330
  }
330
331
 
331
332
  /* ══════════════ ai-usage-ring · 上下文窗口环形指示器(点击弹出完整分解) ══════════════ */
332
333
 
333
- .ai-usage-ring {
334
+ .icen-ai-usage-ring {
334
335
  position: relative;
335
336
  display: inline-flex;
336
337
  align-items: center;
@@ -340,48 +341,48 @@
340
341
  padding: 0;
341
342
  border: 0;
342
343
  background: transparent;
343
- border-radius: var(--radius-full);
344
- color: var(--token-text-muted);
344
+ border-radius: var(--icen-radius-full);
345
+ color: var(--icen-token-text-muted);
345
346
  cursor: pointer;
346
347
  flex-shrink: 0;
347
348
  transition:
348
349
  color var(--icen-tx-fast),
349
350
  background-color var(--icen-tx-fast);
350
351
  }
351
- .ai-usage-ring:hover {
352
- background: var(--token-fill-1);
353
- color: var(--token-text);
352
+ .icen-ai-usage-ring:hover {
353
+ background: var(--icen-token-fill-1);
354
+ color: var(--icen-token-text);
354
355
  }
355
- .ai-usage-ring:focus-visible {
356
+ .icen-ai-usage-ring:focus-visible {
356
357
  outline: none;
357
358
  box-shadow: var(--icen-ring);
358
359
  }
359
360
 
360
- .ai-usage-ring > svg {
361
+ .icen-ai-usage-ring > svg {
361
362
  position: absolute;
362
363
  inset: 0;
363
364
  width: 100%;
364
365
  height: 100%;
365
366
  transform: rotate(-90deg); /* 12 点起笔 */
366
367
  }
367
- .ai-usage-ring-track {
368
+ .icen-ai-usage-ring-track {
368
369
  fill: none;
369
- stroke: var(--token-fill-2);
370
+ stroke: var(--icen-token-fill-2);
370
371
  stroke-width: 3;
371
372
  }
372
- .ai-usage-ring-fill {
373
+ .icen-ai-usage-ring-fill {
373
374
  fill: none;
374
- stroke: var(--token-accent);
375
+ stroke: var(--icen-token-accent);
375
376
  stroke-width: 3;
376
377
  stroke-linecap: round;
377
378
  transition:
378
379
  stroke-dasharray var(--icen-tx-slow),
379
380
  stroke var(--icen-tx-fast);
380
381
  }
381
- /* 状态档:<60% ok(accent)/ 60–85% warn / >85% hot */
382
- .ai-usage-ring.is-warn .ai-usage-ring-fill { stroke: var(--token-warning); }
383
- .ai-usage-ring.is-hot .ai-usage-ring-fill { stroke: var(--token-error); }
384
- .ai-usage-ring.is-hot {
382
+ /* 状态档:<60% ok(icen-accent)/ 60–85% warn / >85% hot */
383
+ .icen-ai-usage-ring.is-warn .icen-ai-usage-ring-fill { stroke: var(--icen-token-warning); }
384
+ .icen-ai-usage-ring.is-hot .icen-ai-usage-ring-fill { stroke: var(--icen-token-error); }
385
+ .icen-ai-usage-ring.is-hot {
385
386
  animation: ai-usage-ring-pulse var(--ai-usage-ring-pulse-duration, 1.6s) ease-in-out infinite;
386
387
  }
387
388
  @keyframes ai-usage-ring-pulse {
@@ -389,9 +390,9 @@
389
390
  50% { opacity: 0.55; }
390
391
  }
391
392
 
392
- .ai-usage-ring-pct {
393
+ .icen-ai-usage-ring-pct {
393
394
  position: relative;
394
- font-family: var(--font-mono);
395
+ font-family: var(--icen-font-mono);
395
396
  font-size: 9px;
396
397
  font-weight: 600;
397
398
  letter-spacing: -0.02em;
@@ -400,84 +401,85 @@
400
401
  }
401
402
 
402
403
  /* 大号变体(消费方变体,常驻头部大号环;behavior 不产出,由使用方手写标记) */
403
- .ai-usage-ring--lg {
404
+ .icen-ai-usage-ring--lg {
404
405
  width: 44px;
405
406
  height: 44px;
406
407
  }
407
- .ai-usage-ring--lg .ai-usage-ring-pct { font-size: 10px; }
408
+ .icen-ai-usage-ring--lg .icen-ai-usage-ring-pct { font-size: 10px; }
408
409
 
409
- /* 弹层(复用 .popover 基座,内容区只补间距) */
410
- .ai-usage-popover {
410
+ /* 弹层(复用 .icen-popover 基座,内容区只补间距) */
411
+ .icen-ai-usage-popover {
411
412
  display: flex;
412
413
  flex-direction: column;
413
- gap: var(--density-space-sm);
414
- padding: var(--density-space-md);
414
+ gap: var(--icen-density-space-sm);
415
+ padding: var(--icen-density-space-md);
415
416
  }
416
- .ai-usage-popover-title {
417
- font-size: var(--density-font-size-sm);
417
+ .icen-ai-usage-popover-title {
418
+ font-size: var(--icen-density-font-size-sm);
418
419
  font-weight: 600;
419
- color: var(--token-text);
420
+ color: var(--icen-token-text);
420
421
  }
421
422
 
422
423
  @media (prefers-reduced-motion: reduce) {
423
- .ai-usage-ring.is-hot { animation: none; }
424
- .ai-usage-ring-fill { transition: none; }
424
+ .icen-ai-usage-ring.is-hot { animation: none; }
425
+ .icen-ai-usage-ring-fill { transition: none; }
425
426
  }
426
427
 
427
428
  /* ══════════════ ai-context · 上下文抽屉(§4.10) ══════════════ */
428
429
 
429
- .ai-context {
430
+ .icen-ai-context {
430
431
  position: fixed;
431
- inset: 0 0 0 auto;
432
- width: min(360px, 92vw);
433
- z-index: var(--z-chrome);
432
+ inset-block: 0;
433
+ inset-inline-end: 0; /* 贴视口行内末端侧(LTR 右侧 / RTL 镜像左侧) */
434
+ inline-size: min(360px, 92vw);
435
+ z-index: var(--icen-z-chrome);
434
436
  display: flex;
435
437
  flex-direction: column;
436
- background: var(--token-surface);
437
- border-left: 1px solid var(--token-line-soft);
438
- box-shadow: var(--token-shadow-overlay);
439
- transform: translateX(100%);
440
- transition: transform var(--ai-context-duration, var(--duration-normal)) var(--ease-out);
438
+ background: var(--icen-token-surface);
439
+ border-inline-start: 1px solid var(--icen-token-line-soft);
440
+ box-shadow: var(--icen-token-shadow-overlay);
441
+ transform: translateX(100%); /* guard:allow-physical 隐藏位沿物理右缘滑出(LTR 抽屉侧),RTL 镜像规则翻为 translateX(-100%) */
442
+ transition: transform var(--ai-context-duration, var(--icen-duration-normal)) var(--icen-ease-out);
441
443
  overflow-y: auto;
442
444
  }
443
- .ai-context[hidden] {
445
+ .icen-ai-context[hidden] {
444
446
  display: none;
445
447
  }
446
- .ai-context.is-open {
448
+ .icen-ai-context.is-open {
447
449
  transform: translateX(0);
448
450
  }
449
451
 
450
452
  /* 页面流内嵌变体:不做 fixed、不滑入 */
451
- .ai-context--inline {
453
+ .icen-ai-context--inline {
452
454
  position: static;
453
455
  inset: auto;
454
456
  width: auto;
455
457
  z-index: auto;
456
458
  transform: none;
457
459
  transition: none;
458
- border: 1px solid var(--token-line-soft);
459
- border-radius: var(--radius-md);
460
- box-shadow: var(--token-shadow-elevated);
460
+ border: 1px solid var(--icen-token-line-soft);
461
+ border-radius: var(--icen-radius-md);
462
+ box-shadow: var(--icen-token-shadow-elevated);
461
463
  overflow-y: visible;
462
464
  }
463
465
 
464
- .ai-context-head {
466
+ .icen-ai-context-head {
465
467
  position: sticky;
466
468
  top: 0;
467
469
  z-index: 1;
468
470
  display: flex;
469
471
  align-items: center;
470
472
  justify-content: space-between;
471
- gap: var(--density-space-sm);
472
- padding: var(--density-space-sm) var(--density-space-md);
473
- background: var(--token-surface);
474
- border-bottom: 1px solid var(--token-line-soft);
475
- font-size: var(--density-font-size-sm);
473
+ gap: var(--icen-density-space-sm);
474
+ padding: var(--icen-density-space-sm) var(--icen-density-space-md);
475
+ background: var(--icen-token-surface);
476
+ border-bottom: 1px solid var(--icen-token-line-soft);
477
+ font-size: var(--icen-density-font-size-sm);
476
478
  font-weight: 600;
477
- color: var(--token-text);
479
+ color: var(--icen-token-text);
478
480
  }
479
481
 
480
- .ai-context-head [data-ai-context-close] {
482
+ .icen-ai-context-head [data-icen-ai-context-close] {
481
483
  flex-shrink: 0;
482
484
  display: inline-flex;
483
485
  align-items: center;
@@ -486,9 +488,9 @@
486
488
  height: 26px;
487
489
  padding: 0;
488
490
  border: 0;
489
- border-radius: var(--radius-xs);
491
+ border-radius: var(--icen-radius-xs);
490
492
  background: none;
491
- color: var(--token-text-faint);
493
+ color: var(--icen-token-text-faint);
492
494
  font-size: 16px;
493
495
  line-height: 1;
494
496
  cursor: pointer;
@@ -496,187 +498,410 @@
496
498
  background-color var(--icen-tx-fast),
497
499
  color var(--icen-tx-fast);
498
500
  }
499
- .ai-context-head [data-ai-context-close]:hover {
500
- color: var(--token-text);
501
- background: var(--token-fill-1);
501
+ .icen-ai-context-head [data-icen-ai-context-close]:hover {
502
+ color: var(--icen-token-text);
503
+ background: var(--icen-token-fill-1);
502
504
  }
503
- .ai-context-head [data-ai-context-close]:focus-visible {
505
+ .icen-ai-context-head [data-icen-ai-context-close]:focus-visible {
504
506
  outline: none;
505
507
  box-shadow: var(--icen-ring);
506
508
  }
507
509
 
508
- .ai-context-section {
510
+ .icen-ai-context-section {
509
511
  display: flex;
510
512
  flex-direction: column;
511
- gap: var(--density-space-xs);
512
- padding: var(--density-space-sm) var(--density-space-md);
513
+ gap: var(--icen-density-space-xs);
514
+ padding: var(--icen-density-space-sm) var(--icen-density-space-md);
513
515
  min-width: 0;
514
516
  }
515
- .ai-context-section ~ .ai-context-section {
516
- border-top: 1px solid var(--token-line-soft);
517
+ .icen-ai-context-section ~ .icen-ai-context-section {
518
+ border-top: 1px solid var(--icen-token-line-soft);
517
519
  }
518
- .ai-context-section h3 {
520
+ .icen-ai-context-section h3 {
519
521
  margin: 0;
520
- font-size: var(--density-font-size-xs);
522
+ font-size: var(--icen-density-font-size-xs);
521
523
  font-weight: 600;
522
- color: var(--token-text-muted);
524
+ color: var(--icen-token-text-muted);
523
525
  }
524
- .ai-context-section-body {
526
+ .icen-ai-context-section-body {
525
527
  display: flex;
526
528
  flex-direction: column;
527
- gap: var(--density-space-xs);
529
+ gap: var(--icen-density-space-xs);
528
530
  min-width: 0;
529
531
  }
530
532
 
531
533
  /* ══════════════ ai-audit(renderAiAudit,规格 §12.2) ══════════════ */
532
534
 
533
535
  /*
534
- * <div class="ai-audit">
535
- * <div class="ai-audit-totals"><span class="ai-audit-totals-text">12 次请求 · 1 失败 · 1.2M tok · $0.42 · TTFT 240ms</span></div>
536
- * <div class="ai-audit-models">
537
- * <div class="ai-audit-model-row"><span class="ai-audit-model-name">kimi/kimi-k3</span>
538
- * <span class="ai-audit-model-meta">8 次 · 900k tok · $0.31</span></div>…
536
+ * <div class="icen-ai-audit">
537
+ * <div class="ai-audit-totals"><span class="icen-ai-audit-totals-text">12 次请求 · 1 失败 · 1.2M tok · $0.42 · TTFT 240ms</span></div>
538
+ * <div class="icen-ai-audit-models">
539
+ * <div class="icen-ai-audit-model-row"><span class="icen-ai-audit-model-name">kimi/kimi-k3</span>
540
+ * <span class="icen-ai-audit-model-meta">8 次 · 900k tok · $0.31</span></div>…
539
541
  * </div>
540
- * <div class="ai-audit-list">
541
- * <div class="ai-audit-item is-done|is-error">
542
- * <span class="ai-audit-dot"></span>
543
- * <span class="ai-audit-item-main"><span class="ai-audit-item-model">kimi · kimi-k3</span>
544
- * <span class="ai-audit-item-meta">14:03 · 1.2s · TTFT 240ms · 12.3k tok</span></span>
545
- * <span class="ai-audit-item-error">网络请求失败:…</span> <!-- 仅 is-error -->
542
+ * <div class="icen-ai-audit-list">
543
+ * <div class="icen-ai-audit-item is-done|is-error">
544
+ * <span class="icen-ai-audit-dot"></span>
545
+ * <span class="icen-ai-audit-item-main"><span class="icen-ai-audit-item-model">kimi · kimi-k3</span>
546
+ * <span class="icen-ai-audit-item-meta">14:03 · 1.2s · TTFT 240ms · 12.3k tok</span></span>
547
+ * <span class="icen-ai-audit-item-error">网络请求失败:…</span> <!-- 仅 is-error -->
546
548
  * </div>…
547
549
  * </div>
548
- * <button class="btn btn-sm ai-audit-clear">清除审计</button>
550
+ * <button class="icen-btn icen-btn-sm icen-ai-audit-clear">清除审计</button>
549
551
  * </div>
550
552
  */
551
553
 
552
- .ai-audit {
554
+ .icen-ai-audit {
553
555
  display: flex;
554
556
  flex-direction: column;
555
- gap: var(--density-space-sm);
557
+ gap: var(--icen-density-space-sm);
556
558
  align-self: stretch;
557
559
  min-width: 0;
558
- font-size: var(--density-font-size-sm);
560
+ font-size: var(--icen-density-font-size-sm);
559
561
  }
560
- .ai-audit-empty {
561
- padding: var(--density-space-md);
562
+ .icen-ai-audit-empty {
563
+ padding: var(--icen-density-space-md);
562
564
  text-align: center;
563
- color: var(--token-text-faint);
564
- font-size: var(--density-font-size-xs);
565
+ color: var(--icen-token-text-faint);
566
+ font-size: var(--icen-density-font-size-xs);
565
567
  }
566
568
 
567
569
  /* totals 行:等宽数字,faint 汇总 */
568
- .ai-audit-totals-text {
570
+ .icen-ai-audit-totals-text {
569
571
  display: block;
570
- font-family: var(--font-mono);
571
- font-size: var(--density-font-size-xs);
572
- color: var(--token-text-faint);
572
+ font-family: var(--icen-font-mono);
573
+ font-size: var(--icen-density-font-size-xs);
574
+ color: var(--icen-token-text-faint);
573
575
  font-variant-numeric: tabular-nums;
574
576
  }
575
577
 
576
578
  /* byModel 分组行 */
577
- .ai-audit-models {
579
+ .icen-ai-audit-models {
578
580
  display: flex;
579
581
  flex-direction: column;
580
582
  gap: 2px;
581
583
  }
582
- .ai-audit-model-row {
584
+ .icen-ai-audit-model-row {
583
585
  display: flex;
584
586
  align-items: baseline;
585
587
  justify-content: space-between;
586
- gap: var(--density-space-sm);
588
+ gap: var(--icen-density-space-sm);
587
589
  min-width: 0;
588
590
  }
589
- .ai-audit-model-name {
590
- font-family: var(--font-mono);
591
- font-size: var(--density-font-size-xs);
592
- color: var(--token-text);
591
+ .icen-ai-audit-model-name {
592
+ font-family: var(--icen-font-mono);
593
+ font-size: var(--icen-density-font-size-xs);
594
+ color: var(--icen-token-text);
593
595
  overflow: hidden;
594
596
  text-overflow: ellipsis;
595
597
  white-space: nowrap;
596
598
  }
597
- .ai-audit-model-meta {
599
+ .icen-ai-audit-model-meta {
598
600
  flex-shrink: 0;
599
- font-family: var(--font-mono);
600
- font-size: var(--density-font-size-2xs);
601
- color: var(--token-text-faint);
601
+ font-family: var(--icen-font-mono);
602
+ font-size: var(--icen-density-font-size-2xs);
603
+ color: var(--icen-token-text-faint);
602
604
  font-variant-numeric: tabular-nums;
603
605
  }
604
606
 
605
607
  /* 最近条目(最新在前) */
606
- .ai-audit-list {
608
+ .icen-ai-audit-list {
607
609
  display: flex;
608
610
  flex-direction: column;
609
611
  gap: 2px;
610
612
  max-height: 280px;
611
613
  overflow-y: auto;
612
614
  }
613
- .ai-audit-item {
615
+ .icen-ai-audit-item {
614
616
  display: flex;
615
617
  align-items: baseline;
616
- gap: var(--density-space-xs);
617
- padding: 2px var(--density-space-xs);
618
- border-radius: var(--radius-xs);
618
+ gap: var(--icen-density-space-xs);
619
+ padding: 2px var(--icen-density-space-xs);
620
+ border-radius: var(--icen-radius-xs);
619
621
  min-width: 0;
620
622
  }
621
- .ai-audit-item:hover {
622
- background: var(--token-fill-1);
623
+ .icen-ai-audit-item:hover {
624
+ background: var(--icen-token-fill-1);
623
625
  }
624
- .ai-audit-dot {
626
+ .icen-ai-audit-dot {
625
627
  flex-shrink: 0;
626
628
  width: 6px;
627
629
  height: 6px;
628
630
  border-radius: 50%;
629
- background: var(--token-text-faint);
631
+ background: var(--icen-token-text-faint);
630
632
  }
631
- .ai-audit-item.is-done .ai-audit-dot {
632
- background: var(--token-success);
633
+ .icen-ai-audit-item.is-done .icen-ai-audit-dot {
634
+ background: var(--icen-token-success);
633
635
  }
634
- .ai-audit-item.is-error .ai-audit-dot {
635
- background: var(--token-error);
636
+ .icen-ai-audit-item.is-error .icen-ai-audit-dot {
637
+ background: var(--icen-token-error);
636
638
  }
637
- .ai-audit-item-main {
639
+ .icen-ai-audit-item-main {
638
640
  display: flex;
639
641
  flex-direction: column;
640
642
  min-width: 0;
641
643
  flex: 1;
642
644
  }
643
- .ai-audit-item-model {
644
- font-family: var(--font-mono);
645
- font-size: var(--density-font-size-2xs);
646
- color: var(--token-text);
645
+ .icen-ai-audit-item-model {
646
+ font-family: var(--icen-font-mono);
647
+ font-size: var(--icen-density-font-size-2xs);
648
+ color: var(--icen-token-text);
647
649
  overflow: hidden;
648
650
  text-overflow: ellipsis;
649
651
  white-space: nowrap;
650
652
  }
651
- .ai-audit-item-meta {
652
- font-family: var(--font-mono);
653
- font-size: var(--density-font-size-2xs);
654
- color: var(--token-text-faint);
653
+ .icen-ai-audit-item-meta {
654
+ font-family: var(--icen-font-mono);
655
+ font-size: var(--icen-density-font-size-2xs);
656
+ color: var(--icen-token-text-faint);
655
657
  font-variant-numeric: tabular-nums;
656
658
  }
657
- .ai-audit-item-error {
659
+ .icen-ai-audit-item-error {
658
660
  flex-shrink: 0;
659
661
  max-width: 45%;
660
- font-size: var(--density-font-size-2xs);
661
- color: var(--token-error);
662
+ font-size: var(--icen-density-font-size-2xs);
663
+ color: var(--icen-token-error);
662
664
  overflow: hidden;
663
665
  text-overflow: ellipsis;
664
666
  white-space: nowrap;
665
667
  }
666
- .ai-audit-item.is-error .ai-audit-item-model {
667
- color: var(--token-error);
668
+ .icen-ai-audit-item.is-error .icen-ai-audit-item-model {
669
+ color: var(--icen-token-error);
668
670
  }
669
671
 
670
- /* 清除钮(右对齐;视觉复用 .btn .btn-sm) */
671
- .ai-audit-clear {
672
+ /* 清除钮(右对齐;视觉复用 .icen-btn .icen-btn-sm) */
673
+ .icen-ai-audit-clear {
672
674
  align-self: flex-end;
673
675
  }
674
676
 
675
677
  /* ── 动效守卫 ── */
676
678
 
677
679
  @media (prefers-reduced-motion: reduce) {
678
- .ai-todo-bar > i,
679
- .ai-usage-seg { transition: none; }
680
- .ai-context { transition: none; }
681
- .ai-item-status { animation: none; }
680
+ .icen-ai-todo-bar > i,
681
+ .icen-ai-usage-seg { transition: none; }
682
+ .icen-ai-context { transition: none; }
683
+ .icen-ai-item-status { animation: none; }
684
+ }
685
+
686
+ /* ══════════════ ai-feedback · 回答反馈(§5.27,behaviors/ai-feedback.ts) ══════════════ */
687
+
688
+ /*
689
+ * <div class="icen-ai-feedback [.is-done]">
690
+ * <div class="icen-ai-feedback-votes">
691
+ * <button class="icen-ai-feedback-vote is-up [.is-picked]" aria-pressed>svg</button>
692
+ * <button class="icen-ai-feedback-vote is-down [.is-picked]" aria-pressed>svg</button>
693
+ * </div>
694
+ * <div class="icen-ai-feedback-reasons" hidden>
695
+ * <button class="icen-ai-feedback-chip [.is-picked]">答案有误</button>…
696
+ * <button class="icen-ai-feedback-submit">提交</button>
697
+ * </div>
698
+ * <div class="icen-ai-feedback-done" hidden>感谢反馈,已关联到该条回答的追踪记录</div>
699
+ * </div>
700
+ * 双钮 28px;is-picked accent 边;.is-done 终态隐藏控件只留小字感谢文案。
701
+ */
702
+
703
+ .icen-ai-feedback {
704
+ display: inline-flex;
705
+ flex-wrap: wrap;
706
+ align-items: center;
707
+ gap: var(--icen-density-space-sm);
708
+ min-width: 0;
709
+ }
710
+
711
+ .icen-ai-feedback-votes {
712
+ display: inline-flex;
713
+ gap: 4px;
714
+ }
715
+
716
+ /* 双钮:28px 方形图标钮 */
717
+ .icen-ai-feedback-vote {
718
+ display: inline-flex;
719
+ align-items: center;
720
+ justify-content: center;
721
+ width: 28px;
722
+ height: 28px;
723
+ padding: 0;
724
+ border: 1px solid var(--icen-token-line-soft);
725
+ border-radius: var(--icen-radius-sm);
726
+ background: transparent;
727
+ color: var(--icen-token-text-muted);
728
+ cursor: pointer;
729
+ transition:
730
+ color var(--icen-tx-fast),
731
+ border-color var(--icen-tx-fast),
732
+ background-color var(--icen-tx-fast),
733
+ opacity var(--icen-tx-fast);
734
+ }
735
+ .icen-ai-feedback-vote svg {
736
+ width: 14px;
737
+ height: 14px;
738
+ }
739
+ .icen-ai-feedback-vote:hover {
740
+ color: var(--icen-token-text);
741
+ border-color: var(--icen-hover-border);
742
+ background: var(--icen-token-fill-1);
743
+ }
744
+ .icen-ai-feedback-vote:focus-visible {
745
+ outline: none;
746
+ box-shadow: var(--icen-ring);
747
+ }
748
+ /* 锁定:对侧禁用降透明;选中侧 accent 边 + 浅 accent 底 */
749
+ .icen-ai-feedback-vote:disabled {
750
+ opacity: 0.45;
751
+ cursor: default;
752
+ background: transparent;
753
+ border-color: var(--icen-token-line-soft);
754
+ }
755
+ .icen-ai-feedback-vote.is-picked {
756
+ color: var(--icen-token-accent);
757
+ border-color: var(--icen-token-accent);
758
+ background: color-mix(in srgb, var(--icen-token-accent) 10%, transparent);
759
+ }
760
+
761
+ /* 踩因枚举 chips + 提交(点 👎 展开) */
762
+ .icen-ai-feedback-reasons {
763
+ display: inline-flex;
764
+ flex-wrap: wrap;
765
+ align-items: center;
766
+ gap: var(--icen-density-space-xs);
767
+ min-width: 0;
768
+ }
769
+ .icen-ai-feedback-reasons[hidden] {
770
+ display: none;
771
+ }
772
+ .icen-ai-feedback-chip {
773
+ padding: 2px 10px;
774
+ border: 1px solid var(--icen-token-line-soft);
775
+ border-radius: var(--icen-radius-full);
776
+ background: transparent;
777
+ color: var(--icen-token-text-muted);
778
+ font-size: var(--icen-density-font-size-xs);
779
+ line-height: 1.5;
780
+ cursor: pointer;
781
+ transition:
782
+ color var(--icen-tx-fast),
783
+ border-color var(--icen-tx-fast),
784
+ background-color var(--icen-tx-fast);
785
+ }
786
+ .icen-ai-feedback-chip:hover {
787
+ color: var(--icen-token-text);
788
+ border-color: var(--icen-hover-border);
789
+ }
790
+ .icen-ai-feedback-chip:focus-visible {
791
+ outline: none;
792
+ box-shadow: var(--icen-ring);
793
+ }
794
+ .icen-ai-feedback-chip.is-picked {
795
+ color: var(--icen-token-accent);
796
+ border-color: var(--icen-token-accent);
797
+ background: color-mix(in srgb, var(--icen-token-accent) 10%, transparent);
798
+ }
799
+
800
+ /* 提交钮:小号 ghost(accent 留给状态,非主行动不铺实底) */
801
+ .icen-ai-feedback-submit {
802
+ padding: 2px 12px;
803
+ border: 1px solid var(--icen-token-line);
804
+ border-radius: var(--icen-radius-full);
805
+ background: transparent;
806
+ color: var(--icen-token-text);
807
+ font-size: var(--icen-density-font-size-xs);
808
+ line-height: 1.5;
809
+ cursor: pointer;
810
+ transition:
811
+ color var(--icen-tx-fast),
812
+ border-color var(--icen-tx-fast),
813
+ background-color var(--icen-tx-fast);
814
+ }
815
+ .icen-ai-feedback-submit:hover {
816
+ color: var(--icen-token-accent);
817
+ border-color: var(--icen-token-accent);
818
+ background: color-mix(in srgb, var(--icen-token-accent) 8%, transparent);
819
+ }
820
+ .icen-ai-feedback-submit:focus-visible {
821
+ outline: none;
822
+ box-shadow: var(--icen-ring);
823
+ }
824
+
825
+ /* 已提交终态:小字感谢文案,控件隐藏 */
826
+ .icen-ai-feedback-done {
827
+ font-size: var(--icen-density-font-size-2xs);
828
+ color: var(--icen-token-text-faint);
829
+ }
830
+ .icen-ai-feedback-done[hidden] {
831
+ display: none;
832
+ }
833
+ .icen-ai-feedback.is-done .icen-ai-feedback-votes,
834
+ .icen-ai-feedback.is-done .icen-ai-feedback-reasons {
835
+ display: none;
836
+ }
837
+
838
+ /* ══════════════ ai-usage-metrics · 派生指标明细行(§5.27,renderAiUsage) ══════════════ */
839
+
840
+ /* 图例下 mono 一行:TTFT 0.8s · 42 tok/s · finish: stop */
841
+ .icen-ai-usage-metrics {
842
+ font-family: var(--icen-font-mono);
843
+ font-size: 11.5px;
844
+ color: var(--icen-token-text-faint);
845
+ font-variant-numeric: tabular-nums;
846
+ letter-spacing: 0.01em;
847
+ }
848
+
849
+ /* ══════════════ ai-todo-check · done 描边勾(§5.27,renderAiTodo) ══════════════ */
850
+
851
+ /* 与 .icen-ai-item-status 同位替换:done 时显勾隐点(:has 守卫——静态手写 DOM 无勾时保留状态点);
852
+ * pathLength=1 → stroke-dasharray 1,.is-anim 做 stroke-dashoffset 描边动画(480ms 一次不循环) */
853
+ .icen-ai-todo-check {
854
+ position: relative;
855
+ display: none;
856
+ flex-shrink: 0;
857
+ width: 8px;
858
+ height: 8px;
859
+ color: var(--icen-token-success);
860
+ }
861
+ .icen-ai-todo-check svg {
862
+ position: absolute;
863
+ inset: 0;
864
+ margin: auto;
865
+ width: 12px;
866
+ height: 12px;
867
+ }
868
+ .icen-ai-todo-check path {
869
+ stroke-dasharray: 1;
870
+ }
871
+ .icen-ai-todo-item.is-done .icen-ai-todo-check {
872
+ display: inline-flex;
873
+ }
874
+ .icen-ai-todo-item.is-done:has(.icen-ai-todo-check) > .icen-ai-item-status {
875
+ display: none;
876
+ }
877
+ .icen-ai-todo-check.is-anim path {
878
+ animation: ai-todo-check-draw var(--ai-todo-check-duration, 480ms) var(--icen-ease-out) 1 forwards;
879
+ }
880
+ @keyframes ai-todo-check-draw {
881
+ from {
882
+ stroke-dashoffset: 1;
883
+ }
884
+ to {
885
+ stroke-dashoffset: 0;
886
+ }
887
+ }
888
+
889
+ /* ── 动效守卫(§5.27 新增段) ── */
890
+
891
+ @media (prefers-reduced-motion: reduce) {
892
+ .icen-ai-feedback-vote,
893
+ .icen-ai-feedback-chip,
894
+ .icen-ai-feedback-submit {
895
+ transition: none;
896
+ }
897
+ .icen-ai-todo-check.is-anim path {
898
+ animation: none;
899
+ stroke-dashoffset: 0;
900
+ }
901
+ }
902
+
903
+ /* ── RTL:上下文抽屉隐藏位镜像(抽屉改贴行内末端左侧,滑出方向同步翻转) ── */
904
+ :is([dir='rtl']) .icen-ai-context { transform: translateX(-100%); }
905
+ :is([dir='rtl']) .icen-ai-context.is-open { transform: translateX(0); }
906
+
682
907
  }