@icen.ai/ui 0.9.0 → 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 (281) hide show
  1. package/AGENTS.md +138 -80
  2. package/README.md +66 -91
  3. package/dist/base.css +208 -179
  4. package/dist/behaviors/accordion.mjs +8 -8
  5. package/dist/behaviors/ai-branch.d.mts +1 -1
  6. package/dist/behaviors/ai-branch.mjs +1010 -94
  7. package/dist/behaviors/ai-chat.d.mts +7 -7
  8. package/dist/behaviors/ai-chat.mjs +1071 -161
  9. package/dist/behaviors/ai-composer.d.mts +44 -12
  10. package/dist/behaviors/ai-composer.mjs +1997 -524
  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 +1 -1
  15. package/dist/behaviors/ai-feedback.mjs +1035 -126
  16. package/dist/behaviors/ai-panel.d.mts +8 -8
  17. package/dist/behaviors/ai-panel.mjs +1284 -266
  18. package/dist/behaviors/ai-provider.mjs +1003 -101
  19. package/dist/behaviors/ai-threads.d.mts +1 -1
  20. package/dist/behaviors/ai-threads.mjs +1068 -154
  21. package/dist/behaviors/ai-tool.d.mts +2 -2
  22. package/dist/behaviors/ai-tool.mjs +2037 -396
  23. package/dist/behaviors/ai-tools.d.mts +89 -16
  24. package/dist/behaviors/ai-tools.mjs +4448 -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 +72 -8
  34. package/dist/behaviors/charts.mjs +1901 -256
  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 +120 -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 +1 -1
  68. package/dist/behaviors/kb-access.mjs +2129 -239
  69. package/dist/behaviors/kb-acl.d.mts +6 -6
  70. package/dist/behaviors/kb-acl.mjs +1119 -179
  71. package/dist/behaviors/kb-answer.mjs +2070 -418
  72. package/dist/behaviors/kb-audit.d.mts +1 -1
  73. package/dist/behaviors/kb-audit.mjs +1076 -154
  74. package/dist/behaviors/kb-canvas.mjs +1100 -177
  75. package/dist/behaviors/kb-chain.mjs +1022 -100
  76. package/dist/behaviors/kb-checkpoint.d.mts +1 -1
  77. package/dist/behaviors/kb-checkpoint.mjs +1319 -169
  78. package/dist/behaviors/kb-chunks.mjs +1152 -213
  79. package/dist/behaviors/kb-citation.d.mts +1 -1
  80. package/dist/behaviors/kb-citation.mjs +1201 -179
  81. package/dist/behaviors/kb-clarify.mjs +1058 -130
  82. package/dist/behaviors/kb-conflict.mjs +1041 -119
  83. package/dist/behaviors/kb-connector.mjs +1104 -176
  84. package/dist/behaviors/kb-core.d.mts +6 -1
  85. package/dist/behaviors/kb-core.mjs +1077 -162
  86. package/dist/behaviors/kb-eval.mjs +1971 -144
  87. package/dist/behaviors/kb-explain.d.mts +1 -1
  88. package/dist/behaviors/kb-explain.mjs +1024 -102
  89. package/dist/behaviors/kb-filter.mjs +2008 -178
  90. package/dist/behaviors/kb-gap.d.mts +1 -1
  91. package/dist/behaviors/kb-gap.mjs +1043 -121
  92. package/dist/behaviors/kb-hittest.d.mts +1 -1
  93. package/dist/behaviors/kb-hittest.mjs +1093 -150
  94. package/dist/behaviors/kb-metadata.mjs +1052 -130
  95. package/dist/behaviors/kb-passage.d.mts +2 -2
  96. package/dist/behaviors/kb-passage.mjs +1101 -161
  97. package/dist/behaviors/kb-pipeline.d.mts +2 -2
  98. package/dist/behaviors/kb-pipeline.mjs +1082 -162
  99. package/dist/behaviors/kb-qa.mjs +1088 -160
  100. package/dist/behaviors/kb-rerank.mjs +1047 -114
  101. package/dist/behaviors/kb-retrieval.mjs +2063 -224
  102. package/dist/behaviors/kb-review.mjs +1990 -159
  103. package/dist/behaviors/kb-sandbox.d.mts +1 -1
  104. package/dist/behaviors/kb-sandbox.mjs +1026 -104
  105. package/dist/behaviors/kb-segment.mjs +1111 -179
  106. package/dist/behaviors/kb-select.d.mts +24 -0
  107. package/dist/behaviors/kb-select.mjs +1989 -0
  108. package/dist/behaviors/kb-sources.d.mts +1 -1
  109. package/dist/behaviors/kb-sources.mjs +1084 -170
  110. package/dist/behaviors/kb-sql.d.mts +1 -1
  111. package/dist/behaviors/kb-sql.mjs +1143 -226
  112. package/dist/behaviors/kb-trace.d.mts +1 -1
  113. package/dist/behaviors/kb-trace.mjs +1042 -128
  114. package/dist/behaviors/kb-visibility.mjs +1086 -158
  115. package/dist/behaviors/kb-who-can.mjs +1974 -137
  116. package/dist/behaviors/mentions.d.mts +93 -0
  117. package/dist/behaviors/mentions.mjs +2152 -0
  118. package/dist/behaviors/modal.d.mts +4 -3
  119. package/dist/behaviors/modal.mjs +1055 -33
  120. package/dist/behaviors/nav.d.mts +1 -1
  121. package/dist/behaviors/nav.mjs +6 -6
  122. package/dist/behaviors/notification.d.mts +16 -8
  123. package/dist/behaviors/notification.mjs +1615 -265
  124. package/dist/behaviors/panel.d.mts +4 -0
  125. package/dist/behaviors/panel.mjs +994 -0
  126. package/dist/behaviors/popover.d.mts +28 -5
  127. package/dist/behaviors/popover.mjs +225 -24
  128. package/dist/behaviors/select.d.mts +5 -2
  129. package/dist/behaviors/select.mjs +1410 -117
  130. package/dist/behaviors/sidebar.d.mts +1 -1
  131. package/dist/behaviors/sidebar.mjs +13 -13
  132. package/dist/behaviors/slider.d.mts +1 -1
  133. package/dist/behaviors/slider.mjs +9 -9
  134. package/dist/behaviors/split-pane.d.mts +1 -1
  135. package/dist/behaviors/split-pane.mjs +7 -7
  136. package/dist/behaviors/suggestions.d.mts +27 -0
  137. package/dist/behaviors/suggestions.mjs +1089 -0
  138. package/dist/behaviors/svg-parse.d.mts +14 -0
  139. package/dist/behaviors/svg-parse.mjs +37 -0
  140. package/dist/behaviors/tabs.d.mts +2 -2
  141. package/dist/behaviors/tabs.mjs +25 -25
  142. package/dist/behaviors/tag-input.d.mts +23 -5
  143. package/dist/behaviors/tag-input.mjs +1359 -104
  144. package/dist/behaviors/theme-switcher.d.mts +24 -0
  145. package/dist/behaviors/theme-switcher.mjs +1981 -0
  146. package/dist/behaviors/theme.d.mts +15 -8
  147. package/dist/behaviors/theme.mjs +390 -28
  148. package/dist/behaviors/toast.d.mts +24 -25
  149. package/dist/behaviors/toast.mjs +1266 -88
  150. package/dist/behaviors/tooltip.d.mts +4 -0
  151. package/dist/behaviors/tooltip.mjs +378 -0
  152. package/dist/behaviors/tree-select.d.mts +69 -0
  153. package/dist/behaviors/tree-select.mjs +1907 -0
  154. package/dist/behaviors/tree.d.mts +1 -1
  155. package/dist/behaviors/tree.mjs +15 -15
  156. package/dist/behaviors/upload.d.mts +3 -2
  157. package/dist/behaviors/upload.mjs +1076 -66
  158. package/dist/cli.mjs +5 -6
  159. package/dist/components/ai-chat.css +666 -573
  160. package/dist/components/ai-diff.css +153 -132
  161. package/dist/components/ai-panel.css +351 -343
  162. package/dist/components/ai-tool.css +393 -238
  163. package/dist/components/autocomplete.css +61 -0
  164. package/dist/components/autocomplete.mjs +3 -0
  165. package/dist/components/back-top.css +34 -31
  166. package/dist/components/badge.css +44 -41
  167. package/dist/components/breadcrumb.css +67 -46
  168. package/dist/components/btn.css +80 -74
  169. package/dist/components/card.css +117 -106
  170. package/dist/components/cascader.css +311 -0
  171. package/dist/components/cascader.mjs +3 -0
  172. package/dist/components/chart-area.css +8 -2
  173. package/dist/components/chart-bar.css +95 -33
  174. package/dist/components/chart-gauge.css +14 -11
  175. package/dist/components/chart-graph.css +20 -17
  176. package/dist/components/chart-heatmap.css +96 -90
  177. package/dist/components/chart-line.css +8 -3
  178. package/dist/components/chart-pie.css +9 -6
  179. package/dist/components/chart-radar.css +8 -5
  180. package/dist/components/chart-scatter.css +9 -6
  181. package/dist/components/chart-sparkline.css +5 -2
  182. package/dist/components/chart-stack.css +14 -11
  183. package/dist/components/charts.css +164 -73
  184. package/dist/components/code-block.css +418 -0
  185. package/dist/components/code-block.mjs +4 -0
  186. package/dist/components/command-palette.css +138 -117
  187. package/dist/components/content.css +257 -251
  188. package/dist/components/copy.css +72 -44
  189. package/dist/components/datatable.css +423 -181
  190. package/dist/components/date-picker.css +135 -104
  191. package/dist/components/empty.css +68 -65
  192. package/dist/components/feedback.css +201 -183
  193. package/dist/components/form-validate.css +120 -0
  194. package/dist/components/form-validate.mjs +3 -0
  195. package/dist/components/form.css +150 -127
  196. package/dist/components/icon.css +102 -0
  197. package/dist/components/icon.mjs +3 -0
  198. package/dist/components/input.css +159 -104
  199. package/dist/components/kb-agent.css +188 -173
  200. package/dist/components/kb-data.css +257 -253
  201. package/dist/components/kb-ground.css +197 -185
  202. package/dist/components/kb-ingest.css +334 -350
  203. package/dist/components/kb-ops.css +265 -259
  204. package/dist/components/kb-perm.css +260 -271
  205. package/dist/components/kb-search.css +317 -360
  206. package/dist/components/kb.css +120 -109
  207. package/dist/components/layout.css +85 -82
  208. package/dist/components/material-chinese.css +73 -0
  209. package/dist/components/material-soviet.css +76 -0
  210. package/dist/components/material.css +275 -0
  211. package/dist/components/media.css +220 -166
  212. package/dist/components/mentions.css +189 -0
  213. package/dist/components/mentions.mjs +3 -0
  214. package/dist/components/menu.css +113 -105
  215. package/dist/components/modal.css +107 -112
  216. package/dist/components/nav.css +118 -115
  217. package/dist/components/notification.css +238 -174
  218. package/dist/components/pagination.css +56 -53
  219. package/dist/components/panel.css +66 -63
  220. package/dist/components/panel.mjs +1 -0
  221. package/dist/components/pill.css +81 -71
  222. package/dist/components/popover.css +67 -53
  223. package/dist/components/scroll-area.css +113 -110
  224. package/dist/components/segmented.css +146 -143
  225. package/dist/components/select.css +206 -186
  226. package/dist/components/sidebar.css +137 -127
  227. package/dist/components/slider.css +117 -114
  228. package/dist/components/split-pane.css +112 -109
  229. package/dist/components/stat.css +112 -106
  230. package/dist/components/steps.css +109 -103
  231. package/dist/components/switch.css +138 -134
  232. package/dist/components/table.css +131 -107
  233. package/dist/components/tabs.css +114 -108
  234. package/dist/components/tag-input.css +48 -133
  235. package/dist/components/tag.css +81 -71
  236. package/dist/components/theme-switcher.css +105 -0
  237. package/dist/components/theme-switcher.mjs +3 -0
  238. package/dist/components/toast.css +100 -86
  239. package/dist/components/toolbar.css +45 -42
  240. package/dist/components/tooltip.css +102 -43
  241. package/dist/components/tooltip.mjs +1 -0
  242. package/dist/components/tree-select.css +416 -0
  243. package/dist/components/tree-select.mjs +3 -0
  244. package/dist/components/upload.css +135 -92
  245. package/dist/fonts/LICENSES/ark-pixel/OFL.txt +96 -0
  246. package/dist/fonts/LICENSES/cubic-11/OFL.txt +108 -0
  247. package/dist/fonts/LICENSES/galmuri/LICENSE.txt +93 -0
  248. package/dist/fonts/OFL.txt +96 -0
  249. package/dist/fonts/README.md +14 -0
  250. package/dist/fonts/fusion-pixel-12px-zh-hans.woff2 +0 -0
  251. package/dist/index.d.mts +28 -14
  252. package/dist/index.mjs +20705 -9601
  253. package/dist/react.d.mts +91 -0
  254. package/dist/react.mjs +8208 -0
  255. package/dist/registry.json +130 -13
  256. package/dist/tokens/chinese.css +44 -0
  257. package/dist/tokens/colors.css +365 -1222
  258. package/dist/tokens/design.css +109 -0
  259. package/dist/tokens/dtcg.json +11198 -0
  260. package/dist/tokens/figma.variables.json +7017 -0
  261. package/dist/tokens/icon-masks.css +78 -0
  262. package/dist/tokens/pixel.css +50 -0
  263. package/dist/tokens/soviet.css +44 -0
  264. package/dist/tokens/style-profiles.css +36 -547
  265. package/dist/tokens/themes.json +308 -0
  266. package/dist/tokens/tokens-studio.json +6728 -0
  267. package/dist/tokens/typography.css +21 -18
  268. package/dist/tokens.css +1555 -1801
  269. package/dist/ui.css +11975 -9831
  270. package/dist/vue.d.mts +344 -0
  271. package/dist/vue.mjs +7781 -0
  272. package/docs/spec/ai-input-experience.md +75 -0
  273. package/docs/spec/ai-native.md +238 -147
  274. package/docs/spec/design-philosophy.md +189 -0
  275. package/docs/spec/design-primitives.md +196 -0
  276. package/docs/spec/kb-family.md +147 -115
  277. package/package.json +43 -8
  278. package/dist/retro-effects.css +0 -255
  279. package/dist/tokens/retro-effects.css +0 -255
  280. package/docs/research/2026-10-03-ai-kb-components.md +0 -392
  281. package/docs/research/2026-10-03-kb-permissions.md +0 -992
@@ -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,233 +498,233 @@
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; }
682
684
  }
683
685
 
684
686
  /* ══════════════ ai-feedback · 回答反馈(§5.27,behaviors/ai-feedback.ts) ══════════════ */
685
687
 
686
688
  /*
687
- * <div class="ai-feedback [.is-done]">
688
- * <div class="ai-feedback-votes">
689
- * <button class="ai-feedback-vote is-up [.is-picked]" aria-pressed>svg</button>
690
- * <button class="ai-feedback-vote is-down [.is-picked]" aria-pressed>svg</button>
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>
691
693
  * </div>
692
- * <div class="ai-feedback-reasons" hidden>
693
- * <button class="ai-feedback-chip [.is-picked]">答案有误</button>…
694
- * <button class="ai-feedback-submit">提交</button>
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>
695
697
  * </div>
696
- * <div class="ai-feedback-done" hidden>感谢反馈,已关联到该条回答的追踪记录</div>
698
+ * <div class="icen-ai-feedback-done" hidden>感谢反馈,已关联到该条回答的追踪记录</div>
697
699
  * </div>
698
700
  * 双钮 28px;is-picked accent 边;.is-done 终态隐藏控件只留小字感谢文案。
699
701
  */
700
702
 
701
- .ai-feedback {
703
+ .icen-ai-feedback {
702
704
  display: inline-flex;
703
705
  flex-wrap: wrap;
704
706
  align-items: center;
705
- gap: var(--density-space-sm);
707
+ gap: var(--icen-density-space-sm);
706
708
  min-width: 0;
707
709
  }
708
710
 
709
- .ai-feedback-votes {
711
+ .icen-ai-feedback-votes {
710
712
  display: inline-flex;
711
713
  gap: 4px;
712
714
  }
713
715
 
714
716
  /* 双钮:28px 方形图标钮 */
715
- .ai-feedback-vote {
717
+ .icen-ai-feedback-vote {
716
718
  display: inline-flex;
717
719
  align-items: center;
718
720
  justify-content: center;
719
721
  width: 28px;
720
722
  height: 28px;
721
723
  padding: 0;
722
- border: 1px solid var(--token-line-soft);
723
- border-radius: var(--radius-sm);
724
+ border: 1px solid var(--icen-token-line-soft);
725
+ border-radius: var(--icen-radius-sm);
724
726
  background: transparent;
725
- color: var(--token-text-muted);
727
+ color: var(--icen-token-text-muted);
726
728
  cursor: pointer;
727
729
  transition:
728
730
  color var(--icen-tx-fast),
@@ -730,50 +732,50 @@
730
732
  background-color var(--icen-tx-fast),
731
733
  opacity var(--icen-tx-fast);
732
734
  }
733
- .ai-feedback-vote svg {
735
+ .icen-ai-feedback-vote svg {
734
736
  width: 14px;
735
737
  height: 14px;
736
738
  }
737
- .ai-feedback-vote:hover {
738
- color: var(--token-text);
739
+ .icen-ai-feedback-vote:hover {
740
+ color: var(--icen-token-text);
739
741
  border-color: var(--icen-hover-border);
740
- background: var(--token-fill-1);
742
+ background: var(--icen-token-fill-1);
741
743
  }
742
- .ai-feedback-vote:focus-visible {
744
+ .icen-ai-feedback-vote:focus-visible {
743
745
  outline: none;
744
746
  box-shadow: var(--icen-ring);
745
747
  }
746
748
  /* 锁定:对侧禁用降透明;选中侧 accent 边 + 浅 accent 底 */
747
- .ai-feedback-vote:disabled {
749
+ .icen-ai-feedback-vote:disabled {
748
750
  opacity: 0.45;
749
751
  cursor: default;
750
752
  background: transparent;
751
- border-color: var(--token-line-soft);
753
+ border-color: var(--icen-token-line-soft);
752
754
  }
753
- .ai-feedback-vote.is-picked {
754
- color: var(--token-accent);
755
- border-color: var(--token-accent);
756
- background: color-mix(in srgb, var(--token-accent) 10%, transparent);
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);
757
759
  }
758
760
 
759
761
  /* 踩因枚举 chips + 提交(点 👎 展开) */
760
- .ai-feedback-reasons {
762
+ .icen-ai-feedback-reasons {
761
763
  display: inline-flex;
762
764
  flex-wrap: wrap;
763
765
  align-items: center;
764
- gap: var(--density-space-xs);
766
+ gap: var(--icen-density-space-xs);
765
767
  min-width: 0;
766
768
  }
767
- .ai-feedback-reasons[hidden] {
769
+ .icen-ai-feedback-reasons[hidden] {
768
770
  display: none;
769
771
  }
770
- .ai-feedback-chip {
772
+ .icen-ai-feedback-chip {
771
773
  padding: 2px 10px;
772
- border: 1px solid var(--token-line-soft);
773
- border-radius: var(--radius-full);
774
+ border: 1px solid var(--icen-token-line-soft);
775
+ border-radius: var(--icen-radius-full);
774
776
  background: transparent;
775
- color: var(--token-text-muted);
776
- font-size: var(--density-font-size-xs);
777
+ color: var(--icen-token-text-muted);
778
+ font-size: var(--icen-density-font-size-xs);
777
779
  line-height: 1.5;
778
780
  cursor: pointer;
779
781
  transition:
@@ -781,28 +783,28 @@
781
783
  border-color var(--icen-tx-fast),
782
784
  background-color var(--icen-tx-fast);
783
785
  }
784
- .ai-feedback-chip:hover {
785
- color: var(--token-text);
786
+ .icen-ai-feedback-chip:hover {
787
+ color: var(--icen-token-text);
786
788
  border-color: var(--icen-hover-border);
787
789
  }
788
- .ai-feedback-chip:focus-visible {
790
+ .icen-ai-feedback-chip:focus-visible {
789
791
  outline: none;
790
792
  box-shadow: var(--icen-ring);
791
793
  }
792
- .ai-feedback-chip.is-picked {
793
- color: var(--token-accent);
794
- border-color: var(--token-accent);
795
- background: color-mix(in srgb, var(--token-accent) 10%, transparent);
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);
796
798
  }
797
799
 
798
800
  /* 提交钮:小号 ghost(accent 留给状态,非主行动不铺实底) */
799
- .ai-feedback-submit {
801
+ .icen-ai-feedback-submit {
800
802
  padding: 2px 12px;
801
- border: 1px solid var(--token-line);
802
- border-radius: var(--radius-full);
803
+ border: 1px solid var(--icen-token-line);
804
+ border-radius: var(--icen-radius-full);
803
805
  background: transparent;
804
- color: var(--token-text);
805
- font-size: var(--density-font-size-xs);
806
+ color: var(--icen-token-text);
807
+ font-size: var(--icen-density-font-size-xs);
806
808
  line-height: 1.5;
807
809
  cursor: pointer;
808
810
  transition:
@@ -810,70 +812,70 @@
810
812
  border-color var(--icen-tx-fast),
811
813
  background-color var(--icen-tx-fast);
812
814
  }
813
- .ai-feedback-submit:hover {
814
- color: var(--token-accent);
815
- border-color: var(--token-accent);
816
- background: color-mix(in srgb, var(--token-accent) 8%, transparent);
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);
817
819
  }
818
- .ai-feedback-submit:focus-visible {
820
+ .icen-ai-feedback-submit:focus-visible {
819
821
  outline: none;
820
822
  box-shadow: var(--icen-ring);
821
823
  }
822
824
 
823
825
  /* 已提交终态:小字感谢文案,控件隐藏 */
824
- .ai-feedback-done {
825
- font-size: var(--density-font-size-2xs);
826
- color: var(--token-text-faint);
826
+ .icen-ai-feedback-done {
827
+ font-size: var(--icen-density-font-size-2xs);
828
+ color: var(--icen-token-text-faint);
827
829
  }
828
- .ai-feedback-done[hidden] {
830
+ .icen-ai-feedback-done[hidden] {
829
831
  display: none;
830
832
  }
831
- .ai-feedback.is-done .ai-feedback-votes,
832
- .ai-feedback.is-done .ai-feedback-reasons {
833
+ .icen-ai-feedback.is-done .icen-ai-feedback-votes,
834
+ .icen-ai-feedback.is-done .icen-ai-feedback-reasons {
833
835
  display: none;
834
836
  }
835
837
 
836
838
  /* ══════════════ ai-usage-metrics · 派生指标明细行(§5.27,renderAiUsage) ══════════════ */
837
839
 
838
840
  /* 图例下 mono 一行:TTFT 0.8s · 42 tok/s · finish: stop */
839
- .ai-usage-metrics {
840
- font-family: var(--font-mono);
841
+ .icen-ai-usage-metrics {
842
+ font-family: var(--icen-font-mono);
841
843
  font-size: 11.5px;
842
- color: var(--token-text-faint);
844
+ color: var(--icen-token-text-faint);
843
845
  font-variant-numeric: tabular-nums;
844
846
  letter-spacing: 0.01em;
845
847
  }
846
848
 
847
849
  /* ══════════════ ai-todo-check · done 描边勾(§5.27,renderAiTodo) ══════════════ */
848
850
 
849
- /* 与 .ai-item-status 同位替换:done 时显勾隐点(:has 守卫——静态手写 DOM 无勾时保留状态点);
851
+ /* 与 .icen-ai-item-status 同位替换:done 时显勾隐点(:has 守卫——静态手写 DOM 无勾时保留状态点);
850
852
  * pathLength=1 → stroke-dasharray 1,.is-anim 做 stroke-dashoffset 描边动画(480ms 一次不循环) */
851
- .ai-todo-check {
853
+ .icen-ai-todo-check {
852
854
  position: relative;
853
855
  display: none;
854
856
  flex-shrink: 0;
855
857
  width: 8px;
856
858
  height: 8px;
857
- color: var(--token-success);
859
+ color: var(--icen-token-success);
858
860
  }
859
- .ai-todo-check svg {
861
+ .icen-ai-todo-check svg {
860
862
  position: absolute;
861
863
  inset: 0;
862
864
  margin: auto;
863
865
  width: 12px;
864
866
  height: 12px;
865
867
  }
866
- .ai-todo-check path {
868
+ .icen-ai-todo-check path {
867
869
  stroke-dasharray: 1;
868
870
  }
869
- .ai-todo-item.is-done .ai-todo-check {
871
+ .icen-ai-todo-item.is-done .icen-ai-todo-check {
870
872
  display: inline-flex;
871
873
  }
872
- .ai-todo-item.is-done:has(.ai-todo-check) > .ai-item-status {
874
+ .icen-ai-todo-item.is-done:has(.icen-ai-todo-check) > .icen-ai-item-status {
873
875
  display: none;
874
876
  }
875
- .ai-todo-check.is-anim path {
876
- animation: ai-todo-check-draw var(--ai-todo-check-duration, 480ms) var(--ease-out) 1 forwards;
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;
877
879
  }
878
880
  @keyframes ai-todo-check-draw {
879
881
  from {
@@ -887,13 +889,19 @@
887
889
  /* ── 动效守卫(§5.27 新增段) ── */
888
890
 
889
891
  @media (prefers-reduced-motion: reduce) {
890
- .ai-feedback-vote,
891
- .ai-feedback-chip,
892
- .ai-feedback-submit {
892
+ .icen-ai-feedback-vote,
893
+ .icen-ai-feedback-chip,
894
+ .icen-ai-feedback-submit {
893
895
  transition: none;
894
896
  }
895
- .ai-todo-check.is-anim path {
897
+ .icen-ai-todo-check.is-anim path {
896
898
  animation: none;
897
899
  stroke-dashoffset: 0;
898
900
  }
899
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
+
907
+ }