@aceshooting/lyra-ui 5.1.0 → 5.2.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 (1278) hide show
  1. package/README.md +2 -1
  2. package/custom-elements.json +5796 -354
  3. package/dist/components/agent-tools/activity-feed/activity-feed.class.d.ts +9 -0
  4. package/dist/components/agent-tools/activity-feed/activity-feed.class.d.ts.map +1 -1
  5. package/dist/components/agent-tools/activity-feed/activity-feed.class.js +33 -2
  6. package/dist/components/agent-tools/activity-feed/activity-feed.class.js.map +1 -1
  7. package/dist/components/agent-tools/activity-feed/activity-feed.styles.d.ts.map +1 -1
  8. package/dist/components/agent-tools/activity-feed/activity-feed.styles.js +34 -9
  9. package/dist/components/agent-tools/activity-feed/activity-feed.styles.js.map +1 -1
  10. package/dist/components/agent-tools/agent-run/agent-run.class.d.ts +18 -0
  11. package/dist/components/agent-tools/agent-run/agent-run.class.d.ts.map +1 -1
  12. package/dist/components/agent-tools/agent-run/agent-run.class.js +22 -0
  13. package/dist/components/agent-tools/agent-run/agent-run.class.js.map +1 -1
  14. package/dist/components/agent-tools/agent-run/agent-run.styles.d.ts.map +1 -1
  15. package/dist/components/agent-tools/agent-run/agent-run.styles.js +19 -0
  16. package/dist/components/agent-tools/agent-run/agent-run.styles.js.map +1 -1
  17. package/dist/components/agent-tools/agent-trace/agent-trace.class.d.ts +4 -0
  18. package/dist/components/agent-tools/agent-trace/agent-trace.class.d.ts.map +1 -1
  19. package/dist/components/agent-tools/agent-trace/agent-trace.class.js +4 -0
  20. package/dist/components/agent-tools/agent-trace/agent-trace.class.js.map +1 -1
  21. package/dist/components/agent-tools/agent-trace/agent-trace.styles.js +1 -1
  22. package/dist/components/agent-tools/artifact-panel/artifact-panel.class.d.ts +7 -0
  23. package/dist/components/agent-tools/artifact-panel/artifact-panel.class.d.ts.map +1 -1
  24. package/dist/components/agent-tools/artifact-panel/artifact-panel.class.js +9 -2
  25. package/dist/components/agent-tools/artifact-panel/artifact-panel.class.js.map +1 -1
  26. package/dist/components/agent-tools/artifact-panel/artifact-panel.styles.d.ts.map +1 -1
  27. package/dist/components/agent-tools/artifact-panel/artifact-panel.styles.js +17 -2
  28. package/dist/components/agent-tools/artifact-panel/artifact-panel.styles.js.map +1 -1
  29. package/dist/components/agent-tools/browser-frame/browser-frame.class.d.ts.map +1 -1
  30. package/dist/components/agent-tools/browser-frame/browser-frame.class.js +18 -2
  31. package/dist/components/agent-tools/browser-frame/browser-frame.class.js.map +1 -1
  32. package/dist/components/agent-tools/browser-frame/browser-frame.styles.d.ts.map +1 -1
  33. package/dist/components/agent-tools/browser-frame/browser-frame.styles.js +4 -0
  34. package/dist/components/agent-tools/browser-frame/browser-frame.styles.js.map +1 -1
  35. package/dist/components/agent-tools/commit-card/commit-card.class.d.ts +20 -1
  36. package/dist/components/agent-tools/commit-card/commit-card.class.d.ts.map +1 -1
  37. package/dist/components/agent-tools/commit-card/commit-card.class.js +41 -4
  38. package/dist/components/agent-tools/commit-card/commit-card.class.js.map +1 -1
  39. package/dist/components/agent-tools/commit-card/commit-card.styles.d.ts.map +1 -1
  40. package/dist/components/agent-tools/commit-card/commit-card.styles.js +24 -0
  41. package/dist/components/agent-tools/commit-card/commit-card.styles.js.map +1 -1
  42. package/dist/components/agent-tools/compare-panel/compare-panel.styles.d.ts.map +1 -1
  43. package/dist/components/agent-tools/compare-panel/compare-panel.styles.js +4 -1
  44. package/dist/components/agent-tools/compare-panel/compare-panel.styles.js.map +1 -1
  45. package/dist/components/agent-tools/confirm-bar/confirm-bar.class.d.ts +19 -0
  46. package/dist/components/agent-tools/confirm-bar/confirm-bar.class.d.ts.map +1 -1
  47. package/dist/components/agent-tools/confirm-bar/confirm-bar.class.js +22 -0
  48. package/dist/components/agent-tools/confirm-bar/confirm-bar.class.js.map +1 -1
  49. package/dist/components/agent-tools/confirm-bar/confirm-bar.styles.d.ts.map +1 -1
  50. package/dist/components/agent-tools/confirm-bar/confirm-bar.styles.js +50 -0
  51. package/dist/components/agent-tools/confirm-bar/confirm-bar.styles.js.map +1 -1
  52. package/dist/components/agent-tools/eval-dataset/eval-dataset.class.d.ts +7 -1
  53. package/dist/components/agent-tools/eval-dataset/eval-dataset.class.d.ts.map +1 -1
  54. package/dist/components/agent-tools/eval-dataset/eval-dataset.class.js +17 -2
  55. package/dist/components/agent-tools/eval-dataset/eval-dataset.class.js.map +1 -1
  56. package/dist/components/agent-tools/eval-dataset/eval-dataset.styles.d.ts.map +1 -1
  57. package/dist/components/agent-tools/eval-dataset/eval-dataset.styles.js +13 -2
  58. package/dist/components/agent-tools/eval-dataset/eval-dataset.styles.js.map +1 -1
  59. package/dist/components/agent-tools/policy-summary/policy-summary.class.d.ts +10 -1
  60. package/dist/components/agent-tools/policy-summary/policy-summary.class.d.ts.map +1 -1
  61. package/dist/components/agent-tools/policy-summary/policy-summary.class.js +15 -2
  62. package/dist/components/agent-tools/policy-summary/policy-summary.class.js.map +1 -1
  63. package/dist/components/agent-tools/policy-summary/policy-summary.styles.js +3 -3
  64. package/dist/components/agent-tools/result-card/result-card.class.d.ts +18 -0
  65. package/dist/components/agent-tools/result-card/result-card.class.d.ts.map +1 -1
  66. package/dist/components/agent-tools/result-card/result-card.class.js +21 -0
  67. package/dist/components/agent-tools/result-card/result-card.class.js.map +1 -1
  68. package/dist/components/agent-tools/result-card/result-card.styles.d.ts.map +1 -1
  69. package/dist/components/agent-tools/result-card/result-card.styles.js +21 -0
  70. package/dist/components/agent-tools/result-card/result-card.styles.js.map +1 -1
  71. package/dist/components/agent-tools/span-waterfall/span-waterfall.class.d.ts +3 -0
  72. package/dist/components/agent-tools/span-waterfall/span-waterfall.class.d.ts.map +1 -1
  73. package/dist/components/agent-tools/span-waterfall/span-waterfall.class.js +3 -0
  74. package/dist/components/agent-tools/span-waterfall/span-waterfall.class.js.map +1 -1
  75. package/dist/components/agent-tools/span-waterfall/span-waterfall.styles.d.ts.map +1 -1
  76. package/dist/components/agent-tools/span-waterfall/span-waterfall.styles.js +4 -1
  77. package/dist/components/agent-tools/span-waterfall/span-waterfall.styles.js.map +1 -1
  78. package/dist/components/agent-tools/stack-trace/stack-trace.class.d.ts +10 -1
  79. package/dist/components/agent-tools/stack-trace/stack-trace.class.d.ts.map +1 -1
  80. package/dist/components/agent-tools/stack-trace/stack-trace.class.js +28 -3
  81. package/dist/components/agent-tools/stack-trace/stack-trace.class.js.map +1 -1
  82. package/dist/components/agent-tools/stack-trace/stack-trace.styles.d.ts.map +1 -1
  83. package/dist/components/agent-tools/stack-trace/stack-trace.styles.js +14 -0
  84. package/dist/components/agent-tools/stack-trace/stack-trace.styles.js.map +1 -1
  85. package/dist/components/agent-tools/task-list/task-list.class.d.ts +18 -0
  86. package/dist/components/agent-tools/task-list/task-list.class.d.ts.map +1 -1
  87. package/dist/components/agent-tools/task-list/task-list.class.js +22 -0
  88. package/dist/components/agent-tools/task-list/task-list.class.js.map +1 -1
  89. package/dist/components/agent-tools/task-list/task-list.styles.d.ts.map +1 -1
  90. package/dist/components/agent-tools/task-list/task-list.styles.js +27 -1
  91. package/dist/components/agent-tools/task-list/task-list.styles.js.map +1 -1
  92. package/dist/components/agent-tools/terminal/terminal.class.d.ts +19 -1
  93. package/dist/components/agent-tools/terminal/terminal.class.d.ts.map +1 -1
  94. package/dist/components/agent-tools/terminal/terminal.class.js +62 -11
  95. package/dist/components/agent-tools/terminal/terminal.class.js.map +1 -1
  96. package/dist/components/agent-tools/terminal/terminal.styles.d.ts.map +1 -1
  97. package/dist/components/agent-tools/terminal/terminal.styles.js +7 -0
  98. package/dist/components/agent-tools/terminal/terminal.styles.js.map +1 -1
  99. package/dist/components/agent-tools/test-results/test-results.class.d.ts +10 -1
  100. package/dist/components/agent-tools/test-results/test-results.class.d.ts.map +1 -1
  101. package/dist/components/agent-tools/test-results/test-results.class.js +30 -3
  102. package/dist/components/agent-tools/test-results/test-results.class.js.map +1 -1
  103. package/dist/components/agent-tools/test-results/test-results.styles.d.ts.map +1 -1
  104. package/dist/components/agent-tools/test-results/test-results.styles.js +10 -3
  105. package/dist/components/agent-tools/test-results/test-results.styles.js.map +1 -1
  106. package/dist/components/agent-tools/tool-approval-dialog/tool-approval-dialog.class.d.ts +4 -0
  107. package/dist/components/agent-tools/tool-approval-dialog/tool-approval-dialog.class.d.ts.map +1 -1
  108. package/dist/components/agent-tools/tool-approval-dialog/tool-approval-dialog.class.js +30 -4
  109. package/dist/components/agent-tools/tool-approval-dialog/tool-approval-dialog.class.js.map +1 -1
  110. package/dist/components/agent-tools/tool-approval-dialog/tool-approval-dialog.styles.d.ts.map +1 -1
  111. package/dist/components/agent-tools/tool-approval-dialog/tool-approval-dialog.styles.js +6 -2
  112. package/dist/components/agent-tools/tool-approval-dialog/tool-approval-dialog.styles.js.map +1 -1
  113. package/dist/components/agent-tools/tool-call-chip/tool-call-chip.class.d.ts.map +1 -1
  114. package/dist/components/agent-tools/tool-call-chip/tool-call-chip.class.js +10 -0
  115. package/dist/components/agent-tools/tool-call-chip/tool-call-chip.class.js.map +1 -1
  116. package/dist/components/agent-tools/tool-call-chip/tool-call-chip.styles.js +1 -1
  117. package/dist/components/agent-tools/tool-param-form/tool-param-form.class.d.ts +14 -0
  118. package/dist/components/agent-tools/tool-param-form/tool-param-form.class.d.ts.map +1 -1
  119. package/dist/components/agent-tools/tool-param-form/tool-param-form.class.js +60 -1
  120. package/dist/components/agent-tools/tool-param-form/tool-param-form.class.js.map +1 -1
  121. package/dist/components/agent-tools/tool-param-form/tool-param-form.styles.d.ts.map +1 -1
  122. package/dist/components/agent-tools/tool-param-form/tool-param-form.styles.js +8 -0
  123. package/dist/components/agent-tools/tool-param-form/tool-param-form.styles.js.map +1 -1
  124. package/dist/components/agent-tools/tool-select-dialog/tool-select-dialog.styles.d.ts.map +1 -1
  125. package/dist/components/agent-tools/tool-select-dialog/tool-select-dialog.styles.js +8 -0
  126. package/dist/components/agent-tools/tool-select-dialog/tool-select-dialog.styles.js.map +1 -1
  127. package/dist/components/agent-tools/tool-timeline/tool-timeline.class.d.ts +5 -0
  128. package/dist/components/agent-tools/tool-timeline/tool-timeline.class.d.ts.map +1 -1
  129. package/dist/components/agent-tools/tool-timeline/tool-timeline.class.js +5 -0
  130. package/dist/components/agent-tools/tool-timeline/tool-timeline.class.js.map +1 -1
  131. package/dist/components/agent-tools/tool-timeline/tool-timeline.styles.d.ts.map +1 -1
  132. package/dist/components/agent-tools/tool-timeline/tool-timeline.styles.js +5 -2
  133. package/dist/components/agent-tools/tool-timeline/tool-timeline.styles.js.map +1 -1
  134. package/dist/components/agent-tools/trace-tree/trace-tree.class.d.ts +14 -0
  135. package/dist/components/agent-tools/trace-tree/trace-tree.class.d.ts.map +1 -1
  136. package/dist/components/agent-tools/trace-tree/trace-tree.class.js +14 -0
  137. package/dist/components/agent-tools/trace-tree/trace-tree.class.js.map +1 -1
  138. package/dist/components/agent-tools/trace-tree/trace-tree.styles.d.ts.map +1 -1
  139. package/dist/components/agent-tools/trace-tree/trace-tree.styles.js +39 -1
  140. package/dist/components/agent-tools/trace-tree/trace-tree.styles.js.map +1 -1
  141. package/dist/components/charts/chart/chart.class.d.ts +17 -0
  142. package/dist/components/charts/chart/chart.class.d.ts.map +1 -1
  143. package/dist/components/charts/chart/chart.class.js +90 -7
  144. package/dist/components/charts/chart/chart.class.js.map +1 -1
  145. package/dist/components/charts/chart/chart.styles.d.ts.map +1 -1
  146. package/dist/components/charts/chart/chart.styles.js +13 -0
  147. package/dist/components/charts/chart/chart.styles.js.map +1 -1
  148. package/dist/components/conversation/agent-workspace/agent-workspace.class.d.ts.map +1 -1
  149. package/dist/components/conversation/agent-workspace/agent-workspace.class.js +18 -3
  150. package/dist/components/conversation/agent-workspace/agent-workspace.class.js.map +1 -1
  151. package/dist/components/conversation/audio-visualizer/audio-visualizer.class.d.ts +11 -1
  152. package/dist/components/conversation/audio-visualizer/audio-visualizer.class.d.ts.map +1 -1
  153. package/dist/components/conversation/audio-visualizer/audio-visualizer.class.js +36 -1
  154. package/dist/components/conversation/audio-visualizer/audio-visualizer.class.js.map +1 -1
  155. package/dist/components/conversation/branch-picker/branch-picker.class.d.ts.map +1 -1
  156. package/dist/components/conversation/branch-picker/branch-picker.class.js +1 -0
  157. package/dist/components/conversation/branch-picker/branch-picker.class.js.map +1 -1
  158. package/dist/components/conversation/branch-picker/branch-picker.styles.d.ts.map +1 -1
  159. package/dist/components/conversation/branch-picker/branch-picker.styles.js +6 -2
  160. package/dist/components/conversation/branch-picker/branch-picker.styles.js.map +1 -1
  161. package/dist/components/conversation/chat-composer/chat-composer.class.d.ts +25 -7
  162. package/dist/components/conversation/chat-composer/chat-composer.class.d.ts.map +1 -1
  163. package/dist/components/conversation/chat-composer/chat-composer.class.js +47 -22
  164. package/dist/components/conversation/chat-composer/chat-composer.class.js.map +1 -1
  165. package/dist/components/conversation/chat-composer/chat-composer.styles.d.ts.map +1 -1
  166. package/dist/components/conversation/chat-composer/chat-composer.styles.js +30 -3
  167. package/dist/components/conversation/chat-composer/chat-composer.styles.js.map +1 -1
  168. package/dist/components/conversation/chat-message/chat-message.class.d.ts +3 -1
  169. package/dist/components/conversation/chat-message/chat-message.class.d.ts.map +1 -1
  170. package/dist/components/conversation/chat-message/chat-message.class.js +5 -1
  171. package/dist/components/conversation/chat-message/chat-message.class.js.map +1 -1
  172. package/dist/components/conversation/chat-message/chat-message.styles.d.ts.map +1 -1
  173. package/dist/components/conversation/chat-message/chat-message.styles.js +10 -2
  174. package/dist/components/conversation/chat-message/chat-message.styles.js.map +1 -1
  175. package/dist/components/conversation/chat-viewport/chat-viewport.class.d.ts +10 -2
  176. package/dist/components/conversation/chat-viewport/chat-viewport.class.d.ts.map +1 -1
  177. package/dist/components/conversation/chat-viewport/chat-viewport.class.js +42 -4
  178. package/dist/components/conversation/chat-viewport/chat-viewport.class.js.map +1 -1
  179. package/dist/components/conversation/chat-viewport/chat-viewport.styles.d.ts.map +1 -1
  180. package/dist/components/conversation/chat-viewport/chat-viewport.styles.js +30 -2
  181. package/dist/components/conversation/chat-viewport/chat-viewport.styles.js.map +1 -1
  182. package/dist/components/conversation/checkpoint/checkpoint.styles.d.ts.map +1 -1
  183. package/dist/components/conversation/checkpoint/checkpoint.styles.js +3 -0
  184. package/dist/components/conversation/checkpoint/checkpoint.styles.js.map +1 -1
  185. package/dist/components/conversation/code-block/code-block-core.class.d.ts +8 -0
  186. package/dist/components/conversation/code-block/code-block-core.class.d.ts.map +1 -1
  187. package/dist/components/conversation/code-block/code-block-core.class.js +33 -56
  188. package/dist/components/conversation/code-block/code-block-core.class.js.map +1 -1
  189. package/dist/components/conversation/code-block/code-block-shared.d.ts +27 -0
  190. package/dist/components/conversation/code-block/code-block-shared.d.ts.map +1 -1
  191. package/dist/components/conversation/code-block/code-block-shared.js +61 -0
  192. package/dist/components/conversation/code-block/code-block-shared.js.map +1 -1
  193. package/dist/components/conversation/code-block/code-block.class.d.ts +30 -8
  194. package/dist/components/conversation/code-block/code-block.class.d.ts.map +1 -1
  195. package/dist/components/conversation/code-block/code-block.class.js +76 -65
  196. package/dist/components/conversation/code-block/code-block.class.js.map +1 -1
  197. package/dist/components/conversation/code-block/code-block.styles.d.ts.map +1 -1
  198. package/dist/components/conversation/code-block/code-block.styles.js +46 -16
  199. package/dist/components/conversation/code-block/code-block.styles.js.map +1 -1
  200. package/dist/components/conversation/code-block/shiki-dark-theme.d.ts +14 -0
  201. package/dist/components/conversation/code-block/shiki-dark-theme.d.ts.map +1 -0
  202. package/dist/components/conversation/code-block/shiki-dark-theme.js +92 -0
  203. package/dist/components/conversation/code-block/shiki-dark-theme.js.map +1 -0
  204. package/dist/components/conversation/conversation-item/conversation-item.class.d.ts +22 -0
  205. package/dist/components/conversation/conversation-item/conversation-item.class.d.ts.map +1 -1
  206. package/dist/components/conversation/conversation-item/conversation-item.class.js +46 -1
  207. package/dist/components/conversation/conversation-item/conversation-item.class.js.map +1 -1
  208. package/dist/components/conversation/conversation-item/conversation-item.styles.d.ts.map +1 -1
  209. package/dist/components/conversation/conversation-item/conversation-item.styles.js +31 -2
  210. package/dist/components/conversation/conversation-item/conversation-item.styles.js.map +1 -1
  211. package/dist/components/conversation/markdown/markdown-core.class.d.ts +20 -11
  212. package/dist/components/conversation/markdown/markdown-core.class.d.ts.map +1 -1
  213. package/dist/components/conversation/markdown/markdown-core.class.js +56 -249
  214. package/dist/components/conversation/markdown/markdown-core.class.js.map +1 -1
  215. package/dist/components/conversation/markdown/markdown-loader.d.ts +1 -3
  216. package/dist/components/conversation/markdown/markdown-loader.d.ts.map +1 -1
  217. package/dist/components/conversation/markdown/markdown-loader.js +7 -1
  218. package/dist/components/conversation/markdown/markdown-loader.js.map +1 -1
  219. package/dist/components/conversation/markdown/markdown-shared.d.ts +93 -0
  220. package/dist/components/conversation/markdown/markdown-shared.d.ts.map +1 -0
  221. package/dist/components/conversation/markdown/markdown-shared.js +252 -0
  222. package/dist/components/conversation/markdown/markdown-shared.js.map +1 -0
  223. package/dist/components/conversation/markdown/markdown.class.d.ts +20 -11
  224. package/dist/components/conversation/markdown/markdown.class.d.ts.map +1 -1
  225. package/dist/components/conversation/markdown/markdown.class.js +56 -249
  226. package/dist/components/conversation/markdown/markdown.class.js.map +1 -1
  227. package/dist/components/conversation/markdown/markdown.styles.d.ts.map +1 -1
  228. package/dist/components/conversation/markdown/markdown.styles.js +19 -0
  229. package/dist/components/conversation/markdown/markdown.styles.js.map +1 -1
  230. package/dist/components/conversation/message-actions/message-actions.styles.d.ts.map +1 -1
  231. package/dist/components/conversation/message-actions/message-actions.styles.js +4 -0
  232. package/dist/components/conversation/message-actions/message-actions.styles.js.map +1 -1
  233. package/dist/components/conversation/message-feedback/message-feedback.class.d.ts +24 -0
  234. package/dist/components/conversation/message-feedback/message-feedback.class.d.ts.map +1 -1
  235. package/dist/components/conversation/message-feedback/message-feedback.class.js +34 -1
  236. package/dist/components/conversation/message-feedback/message-feedback.class.js.map +1 -1
  237. package/dist/components/conversation/message-feedback/message-feedback.styles.d.ts.map +1 -1
  238. package/dist/components/conversation/message-feedback/message-feedback.styles.js +23 -9
  239. package/dist/components/conversation/message-feedback/message-feedback.styles.js.map +1 -1
  240. package/dist/components/conversation/model-select/model-select.class.d.ts +21 -0
  241. package/dist/components/conversation/model-select/model-select.class.d.ts.map +1 -1
  242. package/dist/components/conversation/model-select/model-select.class.js +65 -1
  243. package/dist/components/conversation/model-select/model-select.class.js.map +1 -1
  244. package/dist/components/conversation/model-select/model-select.styles.d.ts.map +1 -1
  245. package/dist/components/conversation/model-select/model-select.styles.js +45 -6
  246. package/dist/components/conversation/model-select/model-select.styles.js.map +1 -1
  247. package/dist/components/conversation/push-to-talk/push-to-talk.class.d.ts +3 -0
  248. package/dist/components/conversation/push-to-talk/push-to-talk.class.d.ts.map +1 -1
  249. package/dist/components/conversation/push-to-talk/push-to-talk.class.js +17 -1
  250. package/dist/components/conversation/push-to-talk/push-to-talk.class.js.map +1 -1
  251. package/dist/components/conversation/push-to-talk/push-to-talk.styles.d.ts.map +1 -1
  252. package/dist/components/conversation/push-to-talk/push-to-talk.styles.js +12 -3
  253. package/dist/components/conversation/push-to-talk/push-to-talk.styles.js.map +1 -1
  254. package/dist/components/conversation/suggestion-chips/suggestion-chips.class.d.ts +2 -0
  255. package/dist/components/conversation/suggestion-chips/suggestion-chips.class.d.ts.map +1 -1
  256. package/dist/components/conversation/suggestion-chips/suggestion-chips.class.js +2 -0
  257. package/dist/components/conversation/suggestion-chips/suggestion-chips.class.js.map +1 -1
  258. package/dist/components/conversation/suggestion-chips/suggestion-chips.styles.js +2 -2
  259. package/dist/components/conversation/thread-list/thread-list.class.d.ts +67 -5
  260. package/dist/components/conversation/thread-list/thread-list.class.d.ts.map +1 -1
  261. package/dist/components/conversation/thread-list/thread-list.class.js +161 -23
  262. package/dist/components/conversation/thread-list/thread-list.class.js.map +1 -1
  263. package/dist/components/conversation/thread-list/thread-list.styles.d.ts.map +1 -1
  264. package/dist/components/conversation/thread-list/thread-list.styles.js +33 -1
  265. package/dist/components/conversation/thread-list/thread-list.styles.js.map +1 -1
  266. package/dist/components/conversation/transcript-feed/transcript-feed.class.d.ts.map +1 -1
  267. package/dist/components/conversation/transcript-feed/transcript-feed.class.js +18 -1
  268. package/dist/components/conversation/transcript-feed/transcript-feed.class.js.map +1 -1
  269. package/dist/components/conversation/transcript-feed/transcript-feed.styles.d.ts.map +1 -1
  270. package/dist/components/conversation/transcript-feed/transcript-feed.styles.js +4 -0
  271. package/dist/components/conversation/transcript-feed/transcript-feed.styles.js.map +1 -1
  272. package/dist/components/conversation/typing-indicator/typing-indicator.class.d.ts +14 -10
  273. package/dist/components/conversation/typing-indicator/typing-indicator.class.d.ts.map +1 -1
  274. package/dist/components/conversation/typing-indicator/typing-indicator.class.js +26 -11
  275. package/dist/components/conversation/typing-indicator/typing-indicator.class.js.map +1 -1
  276. package/dist/components/conversation/usage-badge/usage-badge.class.d.ts +4 -0
  277. package/dist/components/conversation/usage-badge/usage-badge.class.d.ts.map +1 -1
  278. package/dist/components/conversation/usage-badge/usage-badge.class.js +15 -1
  279. package/dist/components/conversation/usage-badge/usage-badge.class.js.map +1 -1
  280. package/dist/components/conversation/usage-badge/usage-badge.styles.js +1 -1
  281. package/dist/components/conversation/voice-picker/voice-picker.class.d.ts +12 -0
  282. package/dist/components/conversation/voice-picker/voice-picker.class.d.ts.map +1 -1
  283. package/dist/components/conversation/voice-picker/voice-picker.class.js +35 -1
  284. package/dist/components/conversation/voice-picker/voice-picker.class.js.map +1 -1
  285. package/dist/components/conversation/voice-picker/voice-picker.styles.d.ts.map +1 -1
  286. package/dist/components/conversation/voice-picker/voice-picker.styles.js +17 -1
  287. package/dist/components/conversation/voice-picker/voice-picker.styles.js.map +1 -1
  288. package/dist/components/data/calendar/calendar.class.d.ts +2 -1
  289. package/dist/components/data/calendar/calendar.class.d.ts.map +1 -1
  290. package/dist/components/data/calendar/calendar.class.js +3 -2
  291. package/dist/components/data/calendar/calendar.class.js.map +1 -1
  292. package/dist/components/data/calendar/calendar.styles.d.ts.map +1 -1
  293. package/dist/components/data/calendar/calendar.styles.js +39 -5
  294. package/dist/components/data/calendar/calendar.styles.js.map +1 -1
  295. package/dist/components/data/data-grid/data-grid.class.d.ts +4 -0
  296. package/dist/components/data/data-grid/data-grid.class.d.ts.map +1 -1
  297. package/dist/components/data/data-grid/data-grid.class.js +4 -0
  298. package/dist/components/data/data-grid/data-grid.class.js.map +1 -1
  299. package/dist/components/data/data-grid/data-grid.styles.d.ts.map +1 -1
  300. package/dist/components/data/data-grid/data-grid.styles.js +4 -2
  301. package/dist/components/data/data-grid/data-grid.styles.js.map +1 -1
  302. package/dist/components/data/env-list/env-list.class.d.ts +5 -0
  303. package/dist/components/data/env-list/env-list.class.d.ts.map +1 -1
  304. package/dist/components/data/env-list/env-list.class.js +22 -2
  305. package/dist/components/data/env-list/env-list.class.js.map +1 -1
  306. package/dist/components/data/env-list/env-list.styles.d.ts.map +1 -1
  307. package/dist/components/data/env-list/env-list.styles.js +6 -2
  308. package/dist/components/data/env-list/env-list.styles.js.map +1 -1
  309. package/dist/components/data/flow-canvas/flow-canvas.class.d.ts +10 -0
  310. package/dist/components/data/flow-canvas/flow-canvas.class.d.ts.map +1 -1
  311. package/dist/components/data/flow-canvas/flow-canvas.class.js +24 -3
  312. package/dist/components/data/flow-canvas/flow-canvas.class.js.map +1 -1
  313. package/dist/components/data/flow-canvas/flow-canvas.styles.d.ts.map +1 -1
  314. package/dist/components/data/flow-canvas/flow-canvas.styles.js +14 -4
  315. package/dist/components/data/flow-canvas/flow-canvas.styles.js.map +1 -1
  316. package/dist/components/data/flow-controls/flow-controls.class.d.ts +16 -1
  317. package/dist/components/data/flow-controls/flow-controls.class.d.ts.map +1 -1
  318. package/dist/components/data/flow-controls/flow-controls.class.js +17 -1
  319. package/dist/components/data/flow-controls/flow-controls.class.js.map +1 -1
  320. package/dist/components/data/flow-controls/flow-controls.styles.d.ts.map +1 -1
  321. package/dist/components/data/flow-controls/flow-controls.styles.js +26 -2
  322. package/dist/components/data/flow-controls/flow-controls.styles.js.map +1 -1
  323. package/dist/components/data/flow-minimap/flow-minimap.styles.d.ts.map +1 -1
  324. package/dist/components/data/flow-minimap/flow-minimap.styles.js +4 -0
  325. package/dist/components/data/flow-minimap/flow-minimap.styles.js.map +1 -1
  326. package/dist/components/data/flow-node/flow-node.class.d.ts +20 -1
  327. package/dist/components/data/flow-node/flow-node.class.d.ts.map +1 -1
  328. package/dist/components/data/flow-node/flow-node.class.js +24 -2
  329. package/dist/components/data/flow-node/flow-node.class.js.map +1 -1
  330. package/dist/components/data/flow-node/flow-node.styles.d.ts.map +1 -1
  331. package/dist/components/data/flow-node/flow-node.styles.js +23 -5
  332. package/dist/components/data/flow-node/flow-node.styles.js.map +1 -1
  333. package/dist/components/data/flow-run-overlay/flow-run-overlay.class.d.ts +9 -1
  334. package/dist/components/data/flow-run-overlay/flow-run-overlay.class.d.ts.map +1 -1
  335. package/dist/components/data/flow-run-overlay/flow-run-overlay.class.js +9 -1
  336. package/dist/components/data/flow-run-overlay/flow-run-overlay.class.js.map +1 -1
  337. package/dist/components/data/flow-run-overlay/flow-run-overlay.styles.d.ts.map +1 -1
  338. package/dist/components/data/flow-run-overlay/flow-run-overlay.styles.js +11 -0
  339. package/dist/components/data/flow-run-overlay/flow-run-overlay.styles.js.map +1 -1
  340. package/dist/components/data/graph-query-builder/graph-query-builder.class.d.ts +15 -1
  341. package/dist/components/data/graph-query-builder/graph-query-builder.class.d.ts.map +1 -1
  342. package/dist/components/data/graph-query-builder/graph-query-builder.class.js +40 -3
  343. package/dist/components/data/graph-query-builder/graph-query-builder.class.js.map +1 -1
  344. package/dist/components/data/graph-query-builder/graph-query-builder.styles.d.ts.map +1 -1
  345. package/dist/components/data/graph-query-builder/graph-query-builder.styles.js +7 -1
  346. package/dist/components/data/graph-query-builder/graph-query-builder.styles.js.map +1 -1
  347. package/dist/components/data/heatmap/heatmap.class.d.ts +107 -7
  348. package/dist/components/data/heatmap/heatmap.class.d.ts.map +1 -1
  349. package/dist/components/data/heatmap/heatmap.class.js +174 -19
  350. package/dist/components/data/heatmap/heatmap.class.js.map +1 -1
  351. package/dist/components/data/heatmap/heatmap.styles.d.ts.map +1 -1
  352. package/dist/components/data/heatmap/heatmap.styles.js +20 -0
  353. package/dist/components/data/heatmap/heatmap.styles.js.map +1 -1
  354. package/dist/components/data/pagination/pagination.class.d.ts +3 -0
  355. package/dist/components/data/pagination/pagination.class.d.ts.map +1 -1
  356. package/dist/components/data/pagination/pagination.class.js +3 -0
  357. package/dist/components/data/pagination/pagination.class.js.map +1 -1
  358. package/dist/components/data/pagination/pagination.styles.d.ts.map +1 -1
  359. package/dist/components/data/pagination/pagination.styles.js +22 -4
  360. package/dist/components/data/pagination/pagination.styles.js.map +1 -1
  361. package/dist/components/data/sequence-strip/sequence-strip.class.d.ts +13 -3
  362. package/dist/components/data/sequence-strip/sequence-strip.class.d.ts.map +1 -1
  363. package/dist/components/data/sequence-strip/sequence-strip.class.js +30 -7
  364. package/dist/components/data/sequence-strip/sequence-strip.class.js.map +1 -1
  365. package/dist/components/data/sequence-strip/sequence-strip.styles.d.ts.map +1 -1
  366. package/dist/components/data/sequence-strip/sequence-strip.styles.js +11 -1
  367. package/dist/components/data/sequence-strip/sequence-strip.styles.js.map +1 -1
  368. package/dist/components/data/stat/stat.class.d.ts +33 -4
  369. package/dist/components/data/stat/stat.class.d.ts.map +1 -1
  370. package/dist/components/data/stat/stat.class.js +35 -6
  371. package/dist/components/data/stat/stat.class.js.map +1 -1
  372. package/dist/components/data/stat/stat.styles.d.ts.map +1 -1
  373. package/dist/components/data/stat/stat.styles.js +69 -5
  374. package/dist/components/data/stat/stat.styles.js.map +1 -1
  375. package/dist/components/data/table/table.class.d.ts +238 -11
  376. package/dist/components/data/table/table.class.d.ts.map +1 -1
  377. package/dist/components/data/table/table.class.js +470 -84
  378. package/dist/components/data/table/table.class.js.map +1 -1
  379. package/dist/components/data/table/table.styles.d.ts.map +1 -1
  380. package/dist/components/data/table/table.styles.js +46 -4
  381. package/dist/components/data/table/table.styles.js.map +1 -1
  382. package/dist/components/data/timeline/timeline-item.class.d.ts +2 -2
  383. package/dist/components/data/timeline/timeline-item.class.d.ts.map +1 -1
  384. package/dist/components/data/timeline/timeline-item.class.js +2 -1
  385. package/dist/components/data/timeline/timeline-item.class.js.map +1 -1
  386. package/dist/components/data/timeline/timeline.class.d.ts +4 -4
  387. package/dist/components/data/timeline/timeline.class.d.ts.map +1 -1
  388. package/dist/components/data/timeline/timeline.class.js +4 -3
  389. package/dist/components/data/timeline/timeline.class.js.map +1 -1
  390. package/dist/components/data/timeline/timeline.styles.d.ts.map +1 -1
  391. package/dist/components/data/timeline/timeline.styles.js +21 -2
  392. package/dist/components/data/timeline/timeline.styles.js.map +1 -1
  393. package/dist/components/data/tree/tree-node.class.d.ts +2 -2
  394. package/dist/components/data/tree/tree-node.class.d.ts.map +1 -1
  395. package/dist/components/data/tree/tree-node.class.js +2 -1
  396. package/dist/components/data/tree/tree-node.class.js.map +1 -1
  397. package/dist/components/data/tree/tree.class.d.ts +53 -2
  398. package/dist/components/data/tree/tree.class.d.ts.map +1 -1
  399. package/dist/components/data/tree/tree.class.js +138 -13
  400. package/dist/components/data/tree/tree.class.js.map +1 -1
  401. package/dist/components/data/tree/tree.styles.d.ts.map +1 -1
  402. package/dist/components/data/tree/tree.styles.js +6 -1
  403. package/dist/components/data/tree/tree.styles.js.map +1 -1
  404. package/dist/components/data/word-cloud/word-cloud.class.d.ts.map +1 -1
  405. package/dist/components/data/word-cloud/word-cloud.class.js +1 -0
  406. package/dist/components/data/word-cloud/word-cloud.class.js.map +1 -1
  407. package/dist/components/forms/button/button.class.d.ts +30 -4
  408. package/dist/components/forms/button/button.class.d.ts.map +1 -1
  409. package/dist/components/forms/button/button.class.js +46 -5
  410. package/dist/components/forms/button/button.class.js.map +1 -1
  411. package/dist/components/forms/button/button.styles.d.ts.map +1 -1
  412. package/dist/components/forms/button/button.styles.js +74 -42
  413. package/dist/components/forms/button/button.styles.js.map +1 -1
  414. package/dist/components/forms/checkbox/checkbox.class.d.ts +19 -2
  415. package/dist/components/forms/checkbox/checkbox.class.d.ts.map +1 -1
  416. package/dist/components/forms/checkbox/checkbox.class.js +57 -2
  417. package/dist/components/forms/checkbox/checkbox.class.js.map +1 -1
  418. package/dist/components/forms/checkbox/checkbox.styles.d.ts.map +1 -1
  419. package/dist/components/forms/checkbox/checkbox.styles.js +24 -3
  420. package/dist/components/forms/checkbox/checkbox.styles.js.map +1 -1
  421. package/dist/components/forms/checkbox-group/checkbox-group.class.d.ts +26 -1
  422. package/dist/components/forms/checkbox-group/checkbox-group.class.d.ts.map +1 -1
  423. package/dist/components/forms/checkbox-group/checkbox-group.class.js +115 -6
  424. package/dist/components/forms/checkbox-group/checkbox-group.class.js.map +1 -1
  425. package/dist/components/forms/checkbox-group/checkbox-group.styles.d.ts.map +1 -1
  426. package/dist/components/forms/checkbox-group/checkbox-group.styles.js +9 -1
  427. package/dist/components/forms/checkbox-group/checkbox-group.styles.js.map +1 -1
  428. package/dist/components/forms/code-editor/code-editor.class.d.ts +1 -1
  429. package/dist/components/forms/code-editor/code-editor.class.d.ts.map +1 -1
  430. package/dist/components/forms/code-editor/code-editor.class.js +18 -2
  431. package/dist/components/forms/code-editor/code-editor.class.js.map +1 -1
  432. package/dist/components/forms/code-editor/code-editor.styles.d.ts.map +1 -1
  433. package/dist/components/forms/code-editor/code-editor.styles.js +14 -1
  434. package/dist/components/forms/code-editor/code-editor.styles.js.map +1 -1
  435. package/dist/components/forms/color-picker/color-picker.styles.d.ts.map +1 -1
  436. package/dist/components/forms/color-picker/color-picker.styles.js +2 -0
  437. package/dist/components/forms/color-picker/color-picker.styles.js.map +1 -1
  438. package/dist/components/forms/combobox/combobox.class.d.ts +46 -6
  439. package/dist/components/forms/combobox/combobox.class.d.ts.map +1 -1
  440. package/dist/components/forms/combobox/combobox.class.js +136 -20
  441. package/dist/components/forms/combobox/combobox.class.js.map +1 -1
  442. package/dist/components/forms/combobox/combobox.styles.d.ts.map +1 -1
  443. package/dist/components/forms/combobox/combobox.styles.js +41 -3
  444. package/dist/components/forms/combobox/combobox.styles.js.map +1 -1
  445. package/dist/components/forms/date-picker/date-input.class.d.ts +17 -0
  446. package/dist/components/forms/date-picker/date-input.class.d.ts.map +1 -1
  447. package/dist/components/forms/date-picker/date-input.class.js +35 -0
  448. package/dist/components/forms/date-picker/date-input.class.js.map +1 -1
  449. package/dist/components/forms/date-picker/date-input.styles.d.ts.map +1 -1
  450. package/dist/components/forms/date-picker/date-input.styles.js +46 -4
  451. package/dist/components/forms/date-picker/date-input.styles.js.map +1 -1
  452. package/dist/components/forms/date-picker/date-picker.class.d.ts +1 -1
  453. package/dist/components/forms/date-picker/date-picker.class.d.ts.map +1 -1
  454. package/dist/components/forms/date-picker/date-picker.class.js +5 -1
  455. package/dist/components/forms/date-picker/date-picker.class.js.map +1 -1
  456. package/dist/components/forms/date-picker/date-picker.styles.d.ts.map +1 -1
  457. package/dist/components/forms/date-picker/date-picker.styles.js +4 -0
  458. package/dist/components/forms/date-picker/date-picker.styles.js.map +1 -1
  459. package/dist/components/forms/emoji-picker/emoji-data-loader.js +8 -1
  460. package/dist/components/forms/emoji-picker/emoji-data-loader.js.map +1 -1
  461. package/dist/components/forms/emoji-picker/emoji-picker.class.d.ts +46 -1
  462. package/dist/components/forms/emoji-picker/emoji-picker.class.d.ts.map +1 -1
  463. package/dist/components/forms/emoji-picker/emoji-picker.class.js +142 -27
  464. package/dist/components/forms/emoji-picker/emoji-picker.class.js.map +1 -1
  465. package/dist/components/forms/emoji-picker/emoji-picker.styles.d.ts.map +1 -1
  466. package/dist/components/forms/emoji-picker/emoji-picker.styles.js +54 -1
  467. package/dist/components/forms/emoji-picker/emoji-picker.styles.js.map +1 -1
  468. package/dist/components/forms/icon-button/icon-button.class.d.ts +36 -6
  469. package/dist/components/forms/icon-button/icon-button.class.d.ts.map +1 -1
  470. package/dist/components/forms/icon-button/icon-button.class.js +59 -13
  471. package/dist/components/forms/icon-button/icon-button.class.js.map +1 -1
  472. package/dist/components/forms/icon-button/icon-button.styles.d.ts.map +1 -1
  473. package/dist/components/forms/icon-button/icon-button.styles.js +4 -1
  474. package/dist/components/forms/icon-button/icon-button.styles.js.map +1 -1
  475. package/dist/components/forms/input/input.class.d.ts +25 -0
  476. package/dist/components/forms/input/input.class.d.ts.map +1 -1
  477. package/dist/components/forms/input/input.class.js +45 -0
  478. package/dist/components/forms/input/input.class.js.map +1 -1
  479. package/dist/components/forms/input/input.styles.d.ts.map +1 -1
  480. package/dist/components/forms/input/input.styles.js +27 -2
  481. package/dist/components/forms/input/input.styles.js.map +1 -1
  482. package/dist/components/forms/phone-input/phone-input.class.d.ts +34 -1
  483. package/dist/components/forms/phone-input/phone-input.class.d.ts.map +1 -1
  484. package/dist/components/forms/phone-input/phone-input.class.js +61 -13
  485. package/dist/components/forms/phone-input/phone-input.class.js.map +1 -1
  486. package/dist/components/forms/phone-input/phone-input.styles.d.ts.map +1 -1
  487. package/dist/components/forms/phone-input/phone-input.styles.js +92 -9
  488. package/dist/components/forms/phone-input/phone-input.styles.js.map +1 -1
  489. package/dist/components/forms/radio/radio.class.d.ts +24 -0
  490. package/dist/components/forms/radio/radio.class.d.ts.map +1 -1
  491. package/dist/components/forms/radio/radio.class.js +50 -1
  492. package/dist/components/forms/radio/radio.class.js.map +1 -1
  493. package/dist/components/forms/radio/radio.styles.d.ts.map +1 -1
  494. package/dist/components/forms/radio/radio.styles.js +36 -5
  495. package/dist/components/forms/radio/radio.styles.js.map +1 -1
  496. package/dist/components/forms/rubric-form/rubric-form.class.d.ts +9 -7
  497. package/dist/components/forms/rubric-form/rubric-form.class.d.ts.map +1 -1
  498. package/dist/components/forms/rubric-form/rubric-form.class.js +34 -8
  499. package/dist/components/forms/rubric-form/rubric-form.class.js.map +1 -1
  500. package/dist/components/forms/rubric-form/rubric-form.styles.d.ts.map +1 -1
  501. package/dist/components/forms/rubric-form/rubric-form.styles.js +7 -1
  502. package/dist/components/forms/rubric-form/rubric-form.styles.js.map +1 -1
  503. package/dist/components/forms/select/select.class.d.ts +26 -7
  504. package/dist/components/forms/select/select.class.d.ts.map +1 -1
  505. package/dist/components/forms/select/select.class.js +86 -8
  506. package/dist/components/forms/select/select.class.js.map +1 -1
  507. package/dist/components/forms/select/select.styles.d.ts.map +1 -1
  508. package/dist/components/forms/select/select.styles.js +39 -19
  509. package/dist/components/forms/select/select.styles.js.map +1 -1
  510. package/dist/components/forms/slider/slider.class.d.ts +5 -6
  511. package/dist/components/forms/slider/slider.class.d.ts.map +1 -1
  512. package/dist/components/forms/slider/slider.class.js +20 -7
  513. package/dist/components/forms/slider/slider.class.js.map +1 -1
  514. package/dist/components/forms/slider/slider.styles.d.ts.map +1 -1
  515. package/dist/components/forms/slider/slider.styles.js +8 -0
  516. package/dist/components/forms/slider/slider.styles.js.map +1 -1
  517. package/dist/components/forms/switch/switch.class.d.ts +7 -2
  518. package/dist/components/forms/switch/switch.class.d.ts.map +1 -1
  519. package/dist/components/forms/switch/switch.class.js +48 -2
  520. package/dist/components/forms/switch/switch.class.js.map +1 -1
  521. package/dist/components/forms/switch/switch.styles.d.ts.map +1 -1
  522. package/dist/components/forms/switch/switch.styles.js +8 -0
  523. package/dist/components/forms/switch/switch.styles.js.map +1 -1
  524. package/dist/components/forms/textarea/textarea.class.d.ts +1 -1
  525. package/dist/components/forms/textarea/textarea.class.d.ts.map +1 -1
  526. package/dist/components/forms/textarea/textarea.class.js +5 -1
  527. package/dist/components/forms/textarea/textarea.class.js.map +1 -1
  528. package/dist/components/forms/textarea/textarea.styles.d.ts.map +1 -1
  529. package/dist/components/forms/textarea/textarea.styles.js +8 -0
  530. package/dist/components/forms/textarea/textarea.styles.js.map +1 -1
  531. package/dist/components/forms/time-range/time-range.class.d.ts +8 -0
  532. package/dist/components/forms/time-range/time-range.class.d.ts.map +1 -1
  533. package/dist/components/forms/time-range/time-range.class.js +47 -1
  534. package/dist/components/forms/time-range/time-range.class.js.map +1 -1
  535. package/dist/components/forms/time-range/time-range.styles.d.ts.map +1 -1
  536. package/dist/components/forms/time-range/time-range.styles.js +32 -7
  537. package/dist/components/forms/time-range/time-range.styles.js.map +1 -1
  538. package/dist/components/forms/token-input/token-input.class.d.ts +61 -3
  539. package/dist/components/forms/token-input/token-input.class.d.ts.map +1 -1
  540. package/dist/components/forms/token-input/token-input.class.js +253 -10
  541. package/dist/components/forms/token-input/token-input.class.js.map +1 -1
  542. package/dist/components/forms/token-input/token-input.styles.d.ts.map +1 -1
  543. package/dist/components/forms/token-input/token-input.styles.js +16 -1
  544. package/dist/components/forms/token-input/token-input.styles.js.map +1 -1
  545. package/dist/components/layout/app-rail/app-rail-item.class.d.ts +6 -0
  546. package/dist/components/layout/app-rail/app-rail-item.class.d.ts.map +1 -1
  547. package/dist/components/layout/app-rail/app-rail-item.class.js +6 -0
  548. package/dist/components/layout/app-rail/app-rail-item.class.js.map +1 -1
  549. package/dist/components/layout/app-rail/app-rail-item.styles.d.ts.map +1 -1
  550. package/dist/components/layout/app-rail/app-rail-item.styles.js +11 -2
  551. package/dist/components/layout/app-rail/app-rail-item.styles.js.map +1 -1
  552. package/dist/components/layout/breadcrumb/breadcrumb-item.class.d.ts +4 -0
  553. package/dist/components/layout/breadcrumb/breadcrumb-item.class.d.ts.map +1 -1
  554. package/dist/components/layout/breadcrumb/breadcrumb-item.class.js +4 -0
  555. package/dist/components/layout/breadcrumb/breadcrumb-item.class.js.map +1 -1
  556. package/dist/components/layout/breadcrumb/breadcrumb-item.styles.d.ts.map +1 -1
  557. package/dist/components/layout/breadcrumb/breadcrumb-item.styles.js +6 -1
  558. package/dist/components/layout/breadcrumb/breadcrumb-item.styles.js.map +1 -1
  559. package/dist/components/layout/card/card.class.d.ts +29 -5
  560. package/dist/components/layout/card/card.class.d.ts.map +1 -1
  561. package/dist/components/layout/card/card.class.js +90 -6
  562. package/dist/components/layout/card/card.class.js.map +1 -1
  563. package/dist/components/layout/card/card.styles.d.ts.map +1 -1
  564. package/dist/components/layout/card/card.styles.js +8 -0
  565. package/dist/components/layout/card/card.styles.js.map +1 -1
  566. package/dist/components/layout/carousel/carousel.class.d.ts +6 -0
  567. package/dist/components/layout/carousel/carousel.class.d.ts.map +1 -1
  568. package/dist/components/layout/carousel/carousel.class.js +22 -1
  569. package/dist/components/layout/carousel/carousel.class.js.map +1 -1
  570. package/dist/components/layout/carousel/carousel.styles.d.ts.map +1 -1
  571. package/dist/components/layout/carousel/carousel.styles.js +10 -0
  572. package/dist/components/layout/carousel/carousel.styles.js.map +1 -1
  573. package/dist/components/layout/command-palette/command-palette.class.d.ts +8 -0
  574. package/dist/components/layout/command-palette/command-palette.class.d.ts.map +1 -1
  575. package/dist/components/layout/command-palette/command-palette.class.js +6 -1
  576. package/dist/components/layout/command-palette/command-palette.class.js.map +1 -1
  577. package/dist/components/layout/command-palette/command-palette.styles.d.ts.map +1 -1
  578. package/dist/components/layout/command-palette/command-palette.styles.js +11 -2
  579. package/dist/components/layout/command-palette/command-palette.styles.js.map +1 -1
  580. package/dist/components/layout/dashboard-grid/dashboard-grid.class.d.ts.map +1 -1
  581. package/dist/components/layout/dashboard-grid/dashboard-grid.class.js +1 -0
  582. package/dist/components/layout/dashboard-grid/dashboard-grid.class.js.map +1 -1
  583. package/dist/components/layout/dashboard-grid/dashboard-grid.styles.d.ts.map +1 -1
  584. package/dist/components/layout/dashboard-grid/dashboard-grid.styles.js +15 -0
  585. package/dist/components/layout/dashboard-grid/dashboard-grid.styles.js.map +1 -1
  586. package/dist/components/layout/details/details.class.js +1 -1
  587. package/dist/components/layout/details/details.class.js.map +1 -1
  588. package/dist/components/layout/details/details.styles.d.ts.map +1 -1
  589. package/dist/components/layout/details/details.styles.js +2 -0
  590. package/dist/components/layout/details/details.styles.js.map +1 -1
  591. package/dist/components/layout/dock-panel/dock-panel.class.d.ts.map +1 -1
  592. package/dist/components/layout/dock-panel/dock-panel.class.js +16 -1
  593. package/dist/components/layout/dock-panel/dock-panel.class.js.map +1 -1
  594. package/dist/components/layout/drilldown-panel/drilldown-panel.class.d.ts.map +1 -1
  595. package/dist/components/layout/drilldown-panel/drilldown-panel.class.js +15 -1
  596. package/dist/components/layout/drilldown-panel/drilldown-panel.class.js.map +1 -1
  597. package/dist/components/layout/filter-bar/filter-bar.class.d.ts +54 -9
  598. package/dist/components/layout/filter-bar/filter-bar.class.d.ts.map +1 -1
  599. package/dist/components/layout/filter-bar/filter-bar.class.js +149 -5
  600. package/dist/components/layout/filter-bar/filter-bar.class.js.map +1 -1
  601. package/dist/components/layout/filter-bar/filter-bar.d.ts +1 -0
  602. package/dist/components/layout/filter-bar/filter-bar.d.ts.map +1 -1
  603. package/dist/components/layout/filter-bar/filter-bar.js +1 -0
  604. package/dist/components/layout/filter-bar/filter-bar.js.map +1 -1
  605. package/dist/components/layout/filter-bar/filter-bar.styles.d.ts.map +1 -1
  606. package/dist/components/layout/filter-bar/filter-bar.styles.js +12 -3
  607. package/dist/components/layout/filter-bar/filter-bar.styles.js.map +1 -1
  608. package/dist/components/layout/menu/menu.class.d.ts +119 -24
  609. package/dist/components/layout/menu/menu.class.d.ts.map +1 -1
  610. package/dist/components/layout/menu/menu.class.js +202 -35
  611. package/dist/components/layout/menu/menu.class.js.map +1 -1
  612. package/dist/components/layout/menu/menu.styles.d.ts.map +1 -1
  613. package/dist/components/layout/menu/menu.styles.js +38 -1
  614. package/dist/components/layout/menu/menu.styles.js.map +1 -1
  615. package/dist/components/layout/responsive-panel/responsive-panel.class.d.ts +2 -0
  616. package/dist/components/layout/responsive-panel/responsive-panel.class.d.ts.map +1 -1
  617. package/dist/components/layout/responsive-panel/responsive-panel.class.js +4 -0
  618. package/dist/components/layout/responsive-panel/responsive-panel.class.js.map +1 -1
  619. package/dist/components/layout/responsive-panel/responsive-panel.styles.d.ts.map +1 -1
  620. package/dist/components/layout/responsive-panel/responsive-panel.styles.js +12 -2
  621. package/dist/components/layout/responsive-panel/responsive-panel.styles.js.map +1 -1
  622. package/dist/components/layout/scroller/scroller.styles.d.ts.map +1 -1
  623. package/dist/components/layout/scroller/scroller.styles.js +4 -0
  624. package/dist/components/layout/scroller/scroller.styles.js.map +1 -1
  625. package/dist/components/layout/segmented/segmented.class.d.ts +20 -2
  626. package/dist/components/layout/segmented/segmented.class.d.ts.map +1 -1
  627. package/dist/components/layout/segmented/segmented.class.js +20 -2
  628. package/dist/components/layout/segmented/segmented.class.js.map +1 -1
  629. package/dist/components/layout/segmented/segmented.styles.d.ts.map +1 -1
  630. package/dist/components/layout/segmented/segmented.styles.js +27 -8
  631. package/dist/components/layout/segmented/segmented.styles.js.map +1 -1
  632. package/dist/components/layout/split/split.class.d.ts +79 -27
  633. package/dist/components/layout/split/split.class.d.ts.map +1 -1
  634. package/dist/components/layout/split/split.class.js +119 -36
  635. package/dist/components/layout/split/split.class.js.map +1 -1
  636. package/dist/components/layout/stepper/stepper.class.d.ts +30 -3
  637. package/dist/components/layout/stepper/stepper.class.d.ts.map +1 -1
  638. package/dist/components/layout/stepper/stepper.class.js +44 -8
  639. package/dist/components/layout/stepper/stepper.class.js.map +1 -1
  640. package/dist/components/layout/stepper/stepper.styles.d.ts.map +1 -1
  641. package/dist/components/layout/stepper/stepper.styles.js +71 -6
  642. package/dist/components/layout/stepper/stepper.styles.js.map +1 -1
  643. package/dist/components/layout/tabs/tabs.class.d.ts +7 -0
  644. package/dist/components/layout/tabs/tabs.class.d.ts.map +1 -1
  645. package/dist/components/layout/tabs/tabs.class.js +7 -0
  646. package/dist/components/layout/tabs/tabs.class.js.map +1 -1
  647. package/dist/components/layout/tabs/tabs.styles.d.ts.map +1 -1
  648. package/dist/components/layout/tabs/tabs.styles.js +12 -4
  649. package/dist/components/layout/tabs/tabs.styles.js.map +1 -1
  650. package/dist/components/layout/virtual-list/virtual-list.class.d.ts +144 -2
  651. package/dist/components/layout/virtual-list/virtual-list.class.d.ts.map +1 -1
  652. package/dist/components/layout/virtual-list/virtual-list.class.js +259 -16
  653. package/dist/components/layout/virtual-list/virtual-list.class.js.map +1 -1
  654. package/dist/components/layout/virtual-list/virtual-list.styles.d.ts.map +1 -1
  655. package/dist/components/layout/virtual-list/virtual-list.styles.js +57 -0
  656. package/dist/components/layout/virtual-list/virtual-list.styles.js.map +1 -1
  657. package/dist/components/layout/widget/widget.class.d.ts +6 -0
  658. package/dist/components/layout/widget/widget.class.d.ts.map +1 -1
  659. package/dist/components/layout/widget/widget.class.js +6 -0
  660. package/dist/components/layout/widget/widget.class.js.map +1 -1
  661. package/dist/components/layout/widget/widget.styles.d.ts.map +1 -1
  662. package/dist/components/layout/widget/widget.styles.js +13 -2
  663. package/dist/components/layout/widget/widget.styles.js.map +1 -1
  664. package/dist/components/media/animated-image/animated-image.class.d.ts.map +1 -1
  665. package/dist/components/media/animated-image/animated-image.class.js +20 -1
  666. package/dist/components/media/animated-image/animated-image.class.js.map +1 -1
  667. package/dist/components/media/animated-image/animated-image.styles.d.ts.map +1 -1
  668. package/dist/components/media/animated-image/animated-image.styles.js +6 -1
  669. package/dist/components/media/animated-image/animated-image.styles.js.map +1 -1
  670. package/dist/components/media/animation/animation.class.d.ts.map +1 -1
  671. package/dist/components/media/animation/animation.class.js +20 -1
  672. package/dist/components/media/animation/animation.class.js.map +1 -1
  673. package/dist/components/media/attachment-chip/attachment-chip.class.d.ts +3 -2
  674. package/dist/components/media/attachment-chip/attachment-chip.class.d.ts.map +1 -1
  675. package/dist/components/media/attachment-chip/attachment-chip.class.js +20 -4
  676. package/dist/components/media/attachment-chip/attachment-chip.class.js.map +1 -1
  677. package/dist/components/media/attachment-chip/attachment-chip.styles.d.ts.map +1 -1
  678. package/dist/components/media/attachment-chip/attachment-chip.styles.js +9 -0
  679. package/dist/components/media/attachment-chip/attachment-chip.styles.js.map +1 -1
  680. package/dist/components/media/attachment-trigger/attachment-trigger.class.d.ts.map +1 -1
  681. package/dist/components/media/attachment-trigger/attachment-trigger.class.js +15 -1
  682. package/dist/components/media/attachment-trigger/attachment-trigger.class.js.map +1 -1
  683. package/dist/components/media/av-player/av-player.class.d.ts +24 -0
  684. package/dist/components/media/av-player/av-player.class.d.ts.map +1 -1
  685. package/dist/components/media/av-player/av-player.class.js +56 -18
  686. package/dist/components/media/av-player/av-player.class.js.map +1 -1
  687. package/dist/components/media/av-player/av-player.styles.d.ts.map +1 -1
  688. package/dist/components/media/av-player/av-player.styles.js +70 -14
  689. package/dist/components/media/av-player/av-player.styles.js.map +1 -1
  690. package/dist/components/media/avatar/avatar.class.d.ts +4 -0
  691. package/dist/components/media/avatar/avatar.class.d.ts.map +1 -1
  692. package/dist/components/media/avatar/avatar.class.js +4 -0
  693. package/dist/components/media/avatar/avatar.class.js.map +1 -1
  694. package/dist/components/media/avatar/avatar.styles.d.ts.map +1 -1
  695. package/dist/components/media/avatar/avatar.styles.js +8 -1
  696. package/dist/components/media/avatar/avatar.styles.js.map +1 -1
  697. package/dist/components/media/avatar-group/avatar-group.class.d.ts +4 -0
  698. package/dist/components/media/avatar-group/avatar-group.class.d.ts.map +1 -1
  699. package/dist/components/media/avatar-group/avatar-group.class.js +5 -1
  700. package/dist/components/media/avatar-group/avatar-group.class.js.map +1 -1
  701. package/dist/components/media/avatar-group/avatar-group.styles.d.ts.map +1 -1
  702. package/dist/components/media/avatar-group/avatar-group.styles.js +7 -1
  703. package/dist/components/media/avatar-group/avatar-group.styles.js.map +1 -1
  704. package/dist/components/media/file-input/file-input.class.d.ts +20 -1
  705. package/dist/components/media/file-input/file-input.class.d.ts.map +1 -1
  706. package/dist/components/media/file-input/file-input.class.js +41 -2
  707. package/dist/components/media/file-input/file-input.class.js.map +1 -1
  708. package/dist/components/media/file-input/file-input.styles.d.ts.map +1 -1
  709. package/dist/components/media/file-input/file-input.styles.js +22 -4
  710. package/dist/components/media/file-input/file-input.styles.js.map +1 -1
  711. package/dist/components/media/flag/flag.class.d.ts.map +1 -1
  712. package/dist/components/media/flag/flag.class.js +3 -0
  713. package/dist/components/media/flag/flag.class.js.map +1 -1
  714. package/dist/components/media/flag/language-map.d.ts +15 -0
  715. package/dist/components/media/flag/language-map.d.ts.map +1 -1
  716. package/dist/components/media/flag/language-map.js +23 -0
  717. package/dist/components/media/flag/language-map.js.map +1 -1
  718. package/dist/components/media/image-comparer/image-comparer.styles.d.ts.map +1 -1
  719. package/dist/components/media/image-comparer/image-comparer.styles.js +11 -0
  720. package/dist/components/media/image-comparer/image-comparer.styles.js.map +1 -1
  721. package/dist/components/media/image-viewer/image-viewer.class.d.ts +17 -0
  722. package/dist/components/media/image-viewer/image-viewer.class.d.ts.map +1 -1
  723. package/dist/components/media/image-viewer/image-viewer.class.js +47 -6
  724. package/dist/components/media/image-viewer/image-viewer.class.js.map +1 -1
  725. package/dist/components/media/image-viewer/image-viewer.styles.d.ts.map +1 -1
  726. package/dist/components/media/image-viewer/image-viewer.styles.js +41 -3
  727. package/dist/components/media/image-viewer/image-viewer.styles.js.map +1 -1
  728. package/dist/components/media/lightbox/lightbox.class.d.ts +4 -9
  729. package/dist/components/media/lightbox/lightbox.class.d.ts.map +1 -1
  730. package/dist/components/media/lightbox/lightbox.class.js +32 -2
  731. package/dist/components/media/lightbox/lightbox.class.js.map +1 -1
  732. package/dist/components/media/lightbox/lightbox.styles.d.ts.map +1 -1
  733. package/dist/components/media/lightbox/lightbox.styles.js +7 -3
  734. package/dist/components/media/lightbox/lightbox.styles.js.map +1 -1
  735. package/dist/components/media/map/map.class.d.ts +8 -0
  736. package/dist/components/media/map/map.class.d.ts.map +1 -1
  737. package/dist/components/media/map/map.class.js +30 -6
  738. package/dist/components/media/map/map.class.js.map +1 -1
  739. package/dist/components/media/map/map.styles.d.ts.map +1 -1
  740. package/dist/components/media/map/map.styles.js +73 -0
  741. package/dist/components/media/map/map.styles.js.map +1 -1
  742. package/dist/components/media/media-card/media-card.class.d.ts +14 -0
  743. package/dist/components/media/media-card/media-card.class.d.ts.map +1 -1
  744. package/dist/components/media/media-card/media-card.class.js +14 -0
  745. package/dist/components/media/media-card/media-card.class.js.map +1 -1
  746. package/dist/components/media/media-card/media-card.styles.d.ts.map +1 -1
  747. package/dist/components/media/media-card/media-card.styles.js +10 -0
  748. package/dist/components/media/media-card/media-card.styles.js.map +1 -1
  749. package/dist/components/media/playback/playback.class.d.ts +6 -1
  750. package/dist/components/media/playback/playback.class.d.ts.map +1 -1
  751. package/dist/components/media/playback/playback.class.js +23 -1
  752. package/dist/components/media/playback/playback.class.js.map +1 -1
  753. package/dist/components/media/playback/playback.styles.d.ts.map +1 -1
  754. package/dist/components/media/playback/playback.styles.js +9 -0
  755. package/dist/components/media/playback/playback.styles.js.map +1 -1
  756. package/dist/components/media/qr-code/qr-code.class.d.ts +2 -0
  757. package/dist/components/media/qr-code/qr-code.class.d.ts.map +1 -1
  758. package/dist/components/media/qr-code/qr-code.class.js +27 -0
  759. package/dist/components/media/qr-code/qr-code.class.js.map +1 -1
  760. package/dist/components/overlays/badge/badge.class.d.ts +10 -0
  761. package/dist/components/overlays/badge/badge.class.d.ts.map +1 -1
  762. package/dist/components/overlays/badge/badge.class.js +12 -0
  763. package/dist/components/overlays/badge/badge.class.js.map +1 -1
  764. package/dist/components/overlays/badge/badge.styles.d.ts.map +1 -1
  765. package/dist/components/overlays/badge/badge.styles.js +15 -2
  766. package/dist/components/overlays/badge/badge.styles.js.map +1 -1
  767. package/dist/components/overlays/callout/callout.class.d.ts +8 -0
  768. package/dist/components/overlays/callout/callout.class.d.ts.map +1 -1
  769. package/dist/components/overlays/callout/callout.class.js +25 -1
  770. package/dist/components/overlays/callout/callout.class.js.map +1 -1
  771. package/dist/components/overlays/callout/callout.styles.d.ts.map +1 -1
  772. package/dist/components/overlays/callout/callout.styles.js +12 -1
  773. package/dist/components/overlays/callout/callout.styles.js.map +1 -1
  774. package/dist/components/overlays/chip/chip.class.d.ts +7 -0
  775. package/dist/components/overlays/chip/chip.class.d.ts.map +1 -1
  776. package/dist/components/overlays/chip/chip.class.js +7 -0
  777. package/dist/components/overlays/chip/chip.class.js.map +1 -1
  778. package/dist/components/overlays/chip/chip.styles.d.ts.map +1 -1
  779. package/dist/components/overlays/chip/chip.styles.js +21 -1
  780. package/dist/components/overlays/chip/chip.styles.js.map +1 -1
  781. package/dist/components/overlays/empty/empty.class.d.ts +2 -0
  782. package/dist/components/overlays/empty/empty.class.d.ts.map +1 -1
  783. package/dist/components/overlays/empty/empty.class.js +2 -0
  784. package/dist/components/overlays/empty/empty.class.js.map +1 -1
  785. package/dist/components/overlays/empty/empty.styles.d.ts.map +1 -1
  786. package/dist/components/overlays/empty/empty.styles.js +5 -0
  787. package/dist/components/overlays/empty/empty.styles.js.map +1 -1
  788. package/dist/components/overlays/overlay/popover.class.d.ts +12 -6
  789. package/dist/components/overlays/overlay/popover.class.d.ts.map +1 -1
  790. package/dist/components/overlays/overlay/popover.class.js +34 -18
  791. package/dist/components/overlays/overlay/popover.class.js.map +1 -1
  792. package/dist/components/overlays/overlay/tooltip.class.d.ts +12 -7
  793. package/dist/components/overlays/overlay/tooltip.class.d.ts.map +1 -1
  794. package/dist/components/overlays/overlay/tooltip.class.js +36 -21
  795. package/dist/components/overlays/overlay/tooltip.class.js.map +1 -1
  796. package/dist/components/overlays/rating/rating.styles.d.ts.map +1 -1
  797. package/dist/components/overlays/rating/rating.styles.js +5 -0
  798. package/dist/components/overlays/rating/rating.styles.js.map +1 -1
  799. package/dist/components/overlays/skeleton/skeleton.class.d.ts.map +1 -1
  800. package/dist/components/overlays/skeleton/skeleton.class.js +15 -1
  801. package/dist/components/overlays/skeleton/skeleton.class.js.map +1 -1
  802. package/dist/components/retrieval/chunk-inspector/chunk-inspector.class.d.ts +28 -2
  803. package/dist/components/retrieval/chunk-inspector/chunk-inspector.class.d.ts.map +1 -1
  804. package/dist/components/retrieval/chunk-inspector/chunk-inspector.class.js +77 -36
  805. package/dist/components/retrieval/chunk-inspector/chunk-inspector.class.js.map +1 -1
  806. package/dist/components/retrieval/chunk-inspector/chunk-inspector.styles.d.ts.map +1 -1
  807. package/dist/components/retrieval/chunk-inspector/chunk-inspector.styles.js +73 -14
  808. package/dist/components/retrieval/chunk-inspector/chunk-inspector.styles.js.map +1 -1
  809. package/dist/components/retrieval/citation-badge/citation-badge.class.d.ts.map +1 -1
  810. package/dist/components/retrieval/citation-badge/citation-badge.class.js +12 -0
  811. package/dist/components/retrieval/citation-badge/citation-badge.class.js.map +1 -1
  812. package/dist/components/retrieval/citation-badge/citation-badge.styles.js +1 -1
  813. package/dist/components/retrieval/community-card/community-card.class.d.ts +8 -0
  814. package/dist/components/retrieval/community-card/community-card.class.d.ts.map +1 -1
  815. package/dist/components/retrieval/community-card/community-card.class.js +8 -0
  816. package/dist/components/retrieval/community-card/community-card.class.js.map +1 -1
  817. package/dist/components/retrieval/community-card/community-card.styles.d.ts.map +1 -1
  818. package/dist/components/retrieval/community-card/community-card.styles.js +25 -0
  819. package/dist/components/retrieval/community-card/community-card.styles.js.map +1 -1
  820. package/dist/components/retrieval/entity-card/entity-card.class.d.ts +16 -0
  821. package/dist/components/retrieval/entity-card/entity-card.class.d.ts.map +1 -1
  822. package/dist/components/retrieval/entity-card/entity-card.class.js +35 -1
  823. package/dist/components/retrieval/entity-card/entity-card.class.js.map +1 -1
  824. package/dist/components/retrieval/entity-card/entity-card.styles.d.ts.map +1 -1
  825. package/dist/components/retrieval/entity-card/entity-card.styles.js +19 -0
  826. package/dist/components/retrieval/entity-card/entity-card.styles.js.map +1 -1
  827. package/dist/components/retrieval/entity-chip/entity-chip.class.d.ts.map +1 -1
  828. package/dist/components/retrieval/entity-chip/entity-chip.class.js +8 -0
  829. package/dist/components/retrieval/entity-chip/entity-chip.class.js.map +1 -1
  830. package/dist/components/retrieval/entity-chip/entity-chip.styles.js +1 -1
  831. package/dist/components/retrieval/entity-dossier/entity-dossier.class.d.ts.map +1 -1
  832. package/dist/components/retrieval/entity-dossier/entity-dossier.class.js +15 -1
  833. package/dist/components/retrieval/entity-dossier/entity-dossier.class.js.map +1 -1
  834. package/dist/components/retrieval/graph/graph.class.d.ts +24 -0
  835. package/dist/components/retrieval/graph/graph.class.d.ts.map +1 -1
  836. package/dist/components/retrieval/graph/graph.class.js +77 -3
  837. package/dist/components/retrieval/graph/graph.class.js.map +1 -1
  838. package/dist/components/retrieval/graph/graph.styles.d.ts.map +1 -1
  839. package/dist/components/retrieval/graph/graph.styles.js +22 -0
  840. package/dist/components/retrieval/graph/graph.styles.js.map +1 -1
  841. package/dist/components/retrieval/graph-legend/graph-legend.class.d.ts +2 -0
  842. package/dist/components/retrieval/graph-legend/graph-legend.class.d.ts.map +1 -1
  843. package/dist/components/retrieval/graph-legend/graph-legend.class.js +17 -1
  844. package/dist/components/retrieval/graph-legend/graph-legend.class.js.map +1 -1
  845. package/dist/components/retrieval/graph-legend/graph-legend.styles.js +1 -1
  846. package/dist/components/retrieval/ingestion-queue/ingestion-queue.class.d.ts.map +1 -1
  847. package/dist/components/retrieval/ingestion-queue/ingestion-queue.class.js +1 -0
  848. package/dist/components/retrieval/ingestion-queue/ingestion-queue.class.js.map +1 -1
  849. package/dist/components/retrieval/knowledge-base/knowledge-base.class.d.ts +2 -1
  850. package/dist/components/retrieval/knowledge-base/knowledge-base.class.d.ts.map +1 -1
  851. package/dist/components/retrieval/knowledge-base/knowledge-base.class.js +4 -2
  852. package/dist/components/retrieval/knowledge-base/knowledge-base.class.js.map +1 -1
  853. package/dist/components/retrieval/knowledge-graph-explorer/knowledge-graph-explorer.class.d.ts.map +1 -1
  854. package/dist/components/retrieval/knowledge-graph-explorer/knowledge-graph-explorer.class.js +1 -0
  855. package/dist/components/retrieval/knowledge-graph-explorer/knowledge-graph-explorer.class.js.map +1 -1
  856. package/dist/components/retrieval/knowledge-graph-explorer/knowledge-graph-explorer.styles.js +1 -1
  857. package/dist/components/retrieval/memory-panel/memory-panel.class.d.ts +6 -0
  858. package/dist/components/retrieval/memory-panel/memory-panel.class.d.ts.map +1 -1
  859. package/dist/components/retrieval/memory-panel/memory-panel.class.js +6 -0
  860. package/dist/components/retrieval/memory-panel/memory-panel.class.js.map +1 -1
  861. package/dist/components/retrieval/memory-panel/memory-panel.styles.d.ts.map +1 -1
  862. package/dist/components/retrieval/memory-panel/memory-panel.styles.js +11 -3
  863. package/dist/components/retrieval/memory-panel/memory-panel.styles.js.map +1 -1
  864. package/dist/components/retrieval/mind-map/mind-map.class.d.ts +7 -0
  865. package/dist/components/retrieval/mind-map/mind-map.class.d.ts.map +1 -1
  866. package/dist/components/retrieval/mind-map/mind-map.class.js +15 -1
  867. package/dist/components/retrieval/mind-map/mind-map.class.js.map +1 -1
  868. package/dist/components/retrieval/mind-map/mind-map.styles.d.ts.map +1 -1
  869. package/dist/components/retrieval/mind-map/mind-map.styles.js +6 -0
  870. package/dist/components/retrieval/mind-map/mind-map.styles.js.map +1 -1
  871. package/dist/components/retrieval/neighbor-list/neighbor-list.class.d.ts +13 -3
  872. package/dist/components/retrieval/neighbor-list/neighbor-list.class.d.ts.map +1 -1
  873. package/dist/components/retrieval/neighbor-list/neighbor-list.class.js +30 -21
  874. package/dist/components/retrieval/neighbor-list/neighbor-list.class.js.map +1 -1
  875. package/dist/components/retrieval/neighbor-list/neighbor-list.styles.d.ts.map +1 -1
  876. package/dist/components/retrieval/neighbor-list/neighbor-list.styles.js +43 -10
  877. package/dist/components/retrieval/neighbor-list/neighbor-list.styles.js.map +1 -1
  878. package/dist/components/retrieval/node-palette/node-palette.class.d.ts +8 -0
  879. package/dist/components/retrieval/node-palette/node-palette.class.d.ts.map +1 -1
  880. package/dist/components/retrieval/node-palette/node-palette.class.js +21 -1
  881. package/dist/components/retrieval/node-palette/node-palette.class.js.map +1 -1
  882. package/dist/components/retrieval/node-palette/node-palette.styles.d.ts.map +1 -1
  883. package/dist/components/retrieval/node-palette/node-palette.styles.js +19 -3
  884. package/dist/components/retrieval/node-palette/node-palette.styles.js.map +1 -1
  885. package/dist/components/retrieval/path-strip/path-strip.styles.d.ts.map +1 -1
  886. package/dist/components/retrieval/path-strip/path-strip.styles.js +4 -0
  887. package/dist/components/retrieval/path-strip/path-strip.styles.js.map +1 -1
  888. package/dist/components/retrieval/provenance-panel/provenance-panel.styles.d.ts.map +1 -1
  889. package/dist/components/retrieval/provenance-panel/provenance-panel.styles.js +7 -0
  890. package/dist/components/retrieval/provenance-panel/provenance-panel.styles.js.map +1 -1
  891. package/dist/components/retrieval/retrieval-results/retrieval-results.class.d.ts +25 -0
  892. package/dist/components/retrieval/retrieval-results/retrieval-results.class.d.ts.map +1 -1
  893. package/dist/components/retrieval/retrieval-results/retrieval-results.class.js +51 -5
  894. package/dist/components/retrieval/retrieval-results/retrieval-results.class.js.map +1 -1
  895. package/dist/components/retrieval/retrieval-results/retrieval-results.styles.d.ts.map +1 -1
  896. package/dist/components/retrieval/retrieval-results/retrieval-results.styles.js +48 -13
  897. package/dist/components/retrieval/retrieval-results/retrieval-results.styles.js.map +1 -1
  898. package/dist/components/retrieval/retrieval-search/retrieval-search.styles.js +1 -1
  899. package/dist/components/retrieval/retrieval-trace/retrieval-trace.class.d.ts +2 -0
  900. package/dist/components/retrieval/retrieval-trace/retrieval-trace.class.d.ts.map +1 -1
  901. package/dist/components/retrieval/retrieval-trace/retrieval-trace.class.js +10 -1
  902. package/dist/components/retrieval/retrieval-trace/retrieval-trace.class.js.map +1 -1
  903. package/dist/components/retrieval/retrieval-trace/retrieval-trace.styles.js +1 -1
  904. package/dist/components/retrieval/source-card/source-card.class.d.ts +20 -2
  905. package/dist/components/retrieval/source-card/source-card.class.d.ts.map +1 -1
  906. package/dist/components/retrieval/source-card/source-card.class.js +24 -1
  907. package/dist/components/retrieval/source-card/source-card.class.js.map +1 -1
  908. package/dist/components/retrieval/source-card/source-card.styles.d.ts.map +1 -1
  909. package/dist/components/retrieval/source-card/source-card.styles.js +20 -0
  910. package/dist/components/retrieval/source-card/source-card.styles.js.map +1 -1
  911. package/dist/components/retrieval/source-list/source-list.class.d.ts +2 -2
  912. package/dist/components/retrieval/source-list/source-list.class.d.ts.map +1 -1
  913. package/dist/components/retrieval/source-list/source-list.class.js +2 -1
  914. package/dist/components/retrieval/source-list/source-list.class.js.map +1 -1
  915. package/dist/components/retrieval/source-picker/source-picker.class.d.ts +8 -0
  916. package/dist/components/retrieval/source-picker/source-picker.class.d.ts.map +1 -1
  917. package/dist/components/retrieval/source-picker/source-picker.class.js +27 -2
  918. package/dist/components/retrieval/source-picker/source-picker.class.js.map +1 -1
  919. package/dist/components/retrieval/source-picker/source-picker.styles.d.ts.map +1 -1
  920. package/dist/components/retrieval/source-picker/source-picker.styles.js +13 -6
  921. package/dist/components/retrieval/source-picker/source-picker.styles.js.map +1 -1
  922. package/dist/components/utility/diff-view/diff-view.class.d.ts.map +1 -1
  923. package/dist/components/utility/diff-view/diff-view.class.js +1 -0
  924. package/dist/components/utility/diff-view/diff-view.class.js.map +1 -1
  925. package/dist/components/utility/diff-view/diff-view.styles.d.ts.map +1 -1
  926. package/dist/components/utility/diff-view/diff-view.styles.js +1 -0
  927. package/dist/components/utility/diff-view/diff-view.styles.js.map +1 -1
  928. package/dist/components/utility/export-button/export-button.class.d.ts +1 -1
  929. package/dist/components/utility/export-button/export-button.class.d.ts.map +1 -1
  930. package/dist/components/utility/export-button/export-button.class.js +3 -1
  931. package/dist/components/utility/export-button/export-button.class.js.map +1 -1
  932. package/dist/components/utility/export-button/export-button.styles.d.ts.map +1 -1
  933. package/dist/components/utility/export-button/export-button.styles.js +9 -3
  934. package/dist/components/utility/export-button/export-button.styles.js.map +1 -1
  935. package/dist/components/utility/format/relative-time.class.d.ts.map +1 -1
  936. package/dist/components/utility/format/relative-time.class.js +1 -0
  937. package/dist/components/utility/format/relative-time.class.js.map +1 -1
  938. package/dist/components/utility/icon/icon.class.d.ts +2 -2
  939. package/dist/components/utility/icon/icon.class.d.ts.map +1 -1
  940. package/dist/components/utility/icon/icon.class.js +2 -1
  941. package/dist/components/utility/icon/icon.class.js.map +1 -1
  942. package/dist/components/utility/intersection-observer/intersection-observer.class.d.ts.map +1 -1
  943. package/dist/components/utility/intersection-observer/intersection-observer.class.js +1 -0
  944. package/dist/components/utility/intersection-observer/intersection-observer.class.js.map +1 -1
  945. package/dist/components/utility/json-viewer/json-viewer.class.d.ts +2 -0
  946. package/dist/components/utility/json-viewer/json-viewer.class.d.ts.map +1 -1
  947. package/dist/components/utility/json-viewer/json-viewer.class.js +3 -0
  948. package/dist/components/utility/json-viewer/json-viewer.class.js.map +1 -1
  949. package/dist/components/utility/json-viewer/json-viewer.styles.d.ts.map +1 -1
  950. package/dist/components/utility/json-viewer/json-viewer.styles.js +27 -8
  951. package/dist/components/utility/json-viewer/json-viewer.styles.js.map +1 -1
  952. package/dist/components/utility/known-date/known-date.class.d.ts +12 -1
  953. package/dist/components/utility/known-date/known-date.class.d.ts.map +1 -1
  954. package/dist/components/utility/known-date/known-date.class.js +13 -1
  955. package/dist/components/utility/known-date/known-date.class.js.map +1 -1
  956. package/dist/components/utility/known-date/known-date.styles.d.ts.map +1 -1
  957. package/dist/components/utility/known-date/known-date.styles.js +33 -1
  958. package/dist/components/utility/known-date/known-date.styles.js.map +1 -1
  959. package/dist/components/utility/mention-popover/mention-popover.class.d.ts +2 -0
  960. package/dist/components/utility/mention-popover/mention-popover.class.d.ts.map +1 -1
  961. package/dist/components/utility/mention-popover/mention-popover.class.js +2 -0
  962. package/dist/components/utility/mention-popover/mention-popover.class.js.map +1 -1
  963. package/dist/components/utility/mention-popover/mention-popover.styles.d.ts.map +1 -1
  964. package/dist/components/utility/mention-popover/mention-popover.styles.js +7 -2
  965. package/dist/components/utility/mention-popover/mention-popover.styles.js.map +1 -1
  966. package/dist/components/utility/mutation-observer/mutation-observer.class.d.ts.map +1 -1
  967. package/dist/components/utility/mutation-observer/mutation-observer.class.js +17 -2
  968. package/dist/components/utility/mutation-observer/mutation-observer.class.js.map +1 -1
  969. package/dist/components/utility/poll-status/poll-status.class.d.ts +10 -0
  970. package/dist/components/utility/poll-status/poll-status.class.d.ts.map +1 -1
  971. package/dist/components/utility/poll-status/poll-status.class.js +34 -3
  972. package/dist/components/utility/poll-status/poll-status.class.js.map +1 -1
  973. package/dist/components/utility/poll-status/poll-status.styles.js +1 -1
  974. package/dist/components/utility/tour/tour.class.d.ts +3 -0
  975. package/dist/components/utility/tour/tour.class.d.ts.map +1 -1
  976. package/dist/components/utility/tour/tour.class.js +18 -1
  977. package/dist/components/utility/tour/tour.class.js.map +1 -1
  978. package/dist/components/utility/tour/tour.styles.d.ts.map +1 -1
  979. package/dist/components/utility/tour/tour.styles.js +9 -6
  980. package/dist/components/utility/tour/tour.styles.js.map +1 -1
  981. package/dist/components/viewers/archive-viewer/archive-viewer.class.d.ts +1 -0
  982. package/dist/components/viewers/archive-viewer/archive-viewer.class.d.ts.map +1 -1
  983. package/dist/components/viewers/archive-viewer/archive-viewer.class.js +4 -2
  984. package/dist/components/viewers/archive-viewer/archive-viewer.class.js.map +1 -1
  985. package/dist/components/viewers/archive-viewer/archive-viewer.styles.d.ts.map +1 -1
  986. package/dist/components/viewers/archive-viewer/archive-viewer.styles.js +11 -5
  987. package/dist/components/viewers/archive-viewer/archive-viewer.styles.js.map +1 -1
  988. package/dist/components/viewers/calendar-viewer/calendar-viewer.class.d.ts.map +1 -1
  989. package/dist/components/viewers/calendar-viewer/calendar-viewer.class.js +2 -3
  990. package/dist/components/viewers/calendar-viewer/calendar-viewer.class.js.map +1 -1
  991. package/dist/components/viewers/contact-viewer/contact-viewer.class.d.ts.map +1 -1
  992. package/dist/components/viewers/contact-viewer/contact-viewer.class.js +6 -3
  993. package/dist/components/viewers/contact-viewer/contact-viewer.class.js.map +1 -1
  994. package/dist/components/viewers/csv-viewer/csv-viewer.class.d.ts +7 -0
  995. package/dist/components/viewers/csv-viewer/csv-viewer.class.d.ts.map +1 -1
  996. package/dist/components/viewers/csv-viewer/csv-viewer.class.js +27 -3
  997. package/dist/components/viewers/csv-viewer/csv-viewer.class.js.map +1 -1
  998. package/dist/components/viewers/csv-viewer/csv-viewer.styles.d.ts.map +1 -1
  999. package/dist/components/viewers/csv-viewer/csv-viewer.styles.js +22 -3
  1000. package/dist/components/viewers/csv-viewer/csv-viewer.styles.js.map +1 -1
  1001. package/dist/components/viewers/dataset-viewer/dataset-viewer.class.d.ts +8 -2
  1002. package/dist/components/viewers/dataset-viewer/dataset-viewer.class.d.ts.map +1 -1
  1003. package/dist/components/viewers/dataset-viewer/dataset-viewer.class.js +18 -5
  1004. package/dist/components/viewers/dataset-viewer/dataset-viewer.class.js.map +1 -1
  1005. package/dist/components/viewers/dataset-viewer/dataset-viewer.styles.d.ts.map +1 -1
  1006. package/dist/components/viewers/dataset-viewer/dataset-viewer.styles.js +3 -0
  1007. package/dist/components/viewers/dataset-viewer/dataset-viewer.styles.js.map +1 -1
  1008. package/dist/components/viewers/document-compare/document-compare.class.d.ts.map +1 -1
  1009. package/dist/components/viewers/document-compare/document-compare.class.js +14 -1
  1010. package/dist/components/viewers/document-compare/document-compare.class.js.map +1 -1
  1011. package/dist/components/viewers/document-compare/document-compare.styles.d.ts.map +1 -1
  1012. package/dist/components/viewers/document-compare/document-compare.styles.js +1 -0
  1013. package/dist/components/viewers/document-compare/document-compare.styles.js.map +1 -1
  1014. package/dist/components/viewers/document-preview/document-preview.class.d.ts +4 -1
  1015. package/dist/components/viewers/document-preview/document-preview.class.d.ts.map +1 -1
  1016. package/dist/components/viewers/document-preview/document-preview.class.js +5 -1
  1017. package/dist/components/viewers/document-preview/document-preview.class.js.map +1 -1
  1018. package/dist/components/viewers/document-preview/document-preview.styles.d.ts.map +1 -1
  1019. package/dist/components/viewers/document-preview/document-preview.styles.js +8 -1
  1020. package/dist/components/viewers/document-preview/document-preview.styles.js.map +1 -1
  1021. package/dist/components/viewers/document-viewer/document-viewer.class.d.ts.map +1 -1
  1022. package/dist/components/viewers/document-viewer/document-viewer.class.js +1 -0
  1023. package/dist/components/viewers/document-viewer/document-viewer.class.js.map +1 -1
  1024. package/dist/components/viewers/docx-viewer/docx-viewer.styles.d.ts.map +1 -1
  1025. package/dist/components/viewers/docx-viewer/docx-viewer.styles.js +3 -0
  1026. package/dist/components/viewers/docx-viewer/docx-viewer.styles.js.map +1 -1
  1027. package/dist/components/viewers/ebook-viewer/ebook-viewer.styles.d.ts.map +1 -1
  1028. package/dist/components/viewers/ebook-viewer/ebook-viewer.styles.js +4 -0
  1029. package/dist/components/viewers/ebook-viewer/ebook-viewer.styles.js.map +1 -1
  1030. package/dist/components/viewers/email-viewer/email-viewer.class.d.ts +2 -0
  1031. package/dist/components/viewers/email-viewer/email-viewer.class.d.ts.map +1 -1
  1032. package/dist/components/viewers/email-viewer/email-viewer.class.js +5 -2
  1033. package/dist/components/viewers/email-viewer/email-viewer.class.js.map +1 -1
  1034. package/dist/components/viewers/email-viewer/email-viewer.styles.d.ts.map +1 -1
  1035. package/dist/components/viewers/email-viewer/email-viewer.styles.js +20 -1
  1036. package/dist/components/viewers/email-viewer/email-viewer.styles.js.map +1 -1
  1037. package/dist/components/viewers/geojson-view/geojson-view.class.d.ts.map +1 -1
  1038. package/dist/components/viewers/geojson-view/geojson-view.class.js +2 -1
  1039. package/dist/components/viewers/geojson-view/geojson-view.class.js.map +1 -1
  1040. package/dist/components/viewers/highlight-layer/highlight-layer.class.d.ts.map +1 -1
  1041. package/dist/components/viewers/highlight-layer/highlight-layer.class.js +16 -1
  1042. package/dist/components/viewers/highlight-layer/highlight-layer.class.js.map +1 -1
  1043. package/dist/components/viewers/highlight-layer/highlight-layer.styles.d.ts.map +1 -1
  1044. package/dist/components/viewers/highlight-layer/highlight-layer.styles.js +3 -0
  1045. package/dist/components/viewers/highlight-layer/highlight-layer.styles.js.map +1 -1
  1046. package/dist/components/viewers/html-viewer/dompurify-loader.d.ts +1 -1
  1047. package/dist/components/viewers/html-viewer/dompurify-loader.d.ts.map +1 -1
  1048. package/dist/components/viewers/html-viewer/dompurify-loader.js +5 -1
  1049. package/dist/components/viewers/html-viewer/dompurify-loader.js.map +1 -1
  1050. package/dist/components/viewers/html-viewer/html-viewer.class.d.ts.map +1 -1
  1051. package/dist/components/viewers/html-viewer/html-viewer.class.js +2 -1
  1052. package/dist/components/viewers/html-viewer/html-viewer.class.js.map +1 -1
  1053. package/dist/components/viewers/include/include.class.d.ts.map +1 -1
  1054. package/dist/components/viewers/include/include.class.js +1 -0
  1055. package/dist/components/viewers/include/include.class.js.map +1 -1
  1056. package/dist/components/viewers/notebook-viewer/dompurify-loader.d.ts +1 -1
  1057. package/dist/components/viewers/notebook-viewer/dompurify-loader.d.ts.map +1 -1
  1058. package/dist/components/viewers/notebook-viewer/dompurify-loader.js +7 -1
  1059. package/dist/components/viewers/notebook-viewer/dompurify-loader.js.map +1 -1
  1060. package/dist/components/viewers/notebook-viewer/notebook-viewer.class.d.ts +7 -0
  1061. package/dist/components/viewers/notebook-viewer/notebook-viewer.class.d.ts.map +1 -1
  1062. package/dist/components/viewers/notebook-viewer/notebook-viewer.class.js +15 -4
  1063. package/dist/components/viewers/notebook-viewer/notebook-viewer.class.js.map +1 -1
  1064. package/dist/components/viewers/notebook-viewer/notebook-viewer.styles.d.ts.map +1 -1
  1065. package/dist/components/viewers/notebook-viewer/notebook-viewer.styles.js +31 -12
  1066. package/dist/components/viewers/notebook-viewer/notebook-viewer.styles.js.map +1 -1
  1067. package/dist/components/viewers/page-rail/page-rail.class.d.ts +9 -0
  1068. package/dist/components/viewers/page-rail/page-rail.class.d.ts.map +1 -1
  1069. package/dist/components/viewers/page-rail/page-rail.class.js +16 -4
  1070. package/dist/components/viewers/page-rail/page-rail.class.js.map +1 -1
  1071. package/dist/components/viewers/page-rail/page-rail.styles.d.ts.map +1 -1
  1072. package/dist/components/viewers/page-rail/page-rail.styles.js +24 -14
  1073. package/dist/components/viewers/page-rail/page-rail.styles.js.map +1 -1
  1074. package/dist/components/viewers/pdf-viewer/pdf-viewer.class.d.ts +15 -0
  1075. package/dist/components/viewers/pdf-viewer/pdf-viewer.class.d.ts.map +1 -1
  1076. package/dist/components/viewers/pdf-viewer/pdf-viewer.class.js +29 -4
  1077. package/dist/components/viewers/pdf-viewer/pdf-viewer.class.js.map +1 -1
  1078. package/dist/components/viewers/pdf-viewer/pdf-viewer.styles.d.ts.map +1 -1
  1079. package/dist/components/viewers/pdf-viewer/pdf-viewer.styles.js +26 -9
  1080. package/dist/components/viewers/pdf-viewer/pdf-viewer.styles.js.map +1 -1
  1081. package/dist/components/viewers/pptx-viewer/pptx-viewer.class.d.ts.map +1 -1
  1082. package/dist/components/viewers/pptx-viewer/pptx-viewer.class.js +1 -0
  1083. package/dist/components/viewers/pptx-viewer/pptx-viewer.class.js.map +1 -1
  1084. package/dist/components/viewers/pptx-viewer/pptx-viewer.styles.d.ts.map +1 -1
  1085. package/dist/components/viewers/pptx-viewer/pptx-viewer.styles.js +2 -0
  1086. package/dist/components/viewers/pptx-viewer/pptx-viewer.styles.js.map +1 -1
  1087. package/dist/components/viewers/spreadsheet-viewer/fixtures/minimal-xlsx-fixture.d.ts +2 -0
  1088. package/dist/components/viewers/spreadsheet-viewer/fixtures/minimal-xlsx-fixture.d.ts.map +1 -0
  1089. package/dist/components/viewers/spreadsheet-viewer/fixtures/minimal-xlsx-fixture.js +5 -0
  1090. package/dist/components/viewers/spreadsheet-viewer/fixtures/minimal-xlsx-fixture.js.map +1 -0
  1091. package/dist/components/viewers/spreadsheet-viewer/spreadsheet-viewer.class.d.ts +3 -0
  1092. package/dist/components/viewers/spreadsheet-viewer/spreadsheet-viewer.class.d.ts.map +1 -1
  1093. package/dist/components/viewers/spreadsheet-viewer/spreadsheet-viewer.class.js +6 -1
  1094. package/dist/components/viewers/spreadsheet-viewer/spreadsheet-viewer.class.js.map +1 -1
  1095. package/dist/components/viewers/spreadsheet-viewer/spreadsheet-viewer.styles.d.ts.map +1 -1
  1096. package/dist/components/viewers/spreadsheet-viewer/spreadsheet-viewer.styles.js +12 -1
  1097. package/dist/components/viewers/spreadsheet-viewer/spreadsheet-viewer.styles.js.map +1 -1
  1098. package/dist/components/viewers/svg-viewer/dompurify-loader.d.ts +1 -1
  1099. package/dist/components/viewers/svg-viewer/dompurify-loader.d.ts.map +1 -1
  1100. package/dist/components/viewers/svg-viewer/dompurify-loader.js +6 -1
  1101. package/dist/components/viewers/svg-viewer/dompurify-loader.js.map +1 -1
  1102. package/dist/components/viewers/svg-viewer/svg-viewer.class.d.ts +3 -0
  1103. package/dist/components/viewers/svg-viewer/svg-viewer.class.d.ts.map +1 -1
  1104. package/dist/components/viewers/svg-viewer/svg-viewer.class.js +5 -1
  1105. package/dist/components/viewers/svg-viewer/svg-viewer.class.js.map +1 -1
  1106. package/dist/components/viewers/svg-viewer/svg-viewer.styles.d.ts.map +1 -1
  1107. package/dist/components/viewers/svg-viewer/svg-viewer.styles.js +8 -1
  1108. package/dist/components/viewers/svg-viewer/svg-viewer.styles.js.map +1 -1
  1109. package/dist/components/viewers/xml-viewer/xml-viewer.class.d.ts +9 -0
  1110. package/dist/components/viewers/xml-viewer/xml-viewer.class.d.ts.map +1 -1
  1111. package/dist/components/viewers/xml-viewer/xml-viewer.class.js +0 -0
  1112. package/dist/components/viewers/xml-viewer/xml-viewer.class.js.map +1 -1
  1113. package/dist/components/viewers/xml-viewer/xml-viewer.styles.d.ts.map +1 -1
  1114. package/dist/components/viewers/xml-viewer/xml-viewer.styles.js +22 -8
  1115. package/dist/components/viewers/xml-viewer/xml-viewer.styles.js.map +1 -1
  1116. package/dist/internal/localization.d.ts +1 -1
  1117. package/dist/internal/localization.d.ts.map +1 -1
  1118. package/dist/internal/localization.js +7 -0
  1119. package/dist/internal/localization.js.map +1 -1
  1120. package/dist/internal/orientation-breakpoint.d.ts +19 -8
  1121. package/dist/internal/orientation-breakpoint.d.ts.map +1 -1
  1122. package/dist/internal/orientation-breakpoint.js +181 -0
  1123. package/dist/internal/orientation-breakpoint.js.map +1 -1
  1124. package/dist/internal/tokens.styles.d.ts.map +1 -1
  1125. package/dist/internal/tokens.styles.js +22 -5
  1126. package/dist/internal/tokens.styles.js.map +1 -1
  1127. package/dist/lyra.d.ts +7 -7
  1128. package/dist/lyra.d.ts.map +1 -1
  1129. package/dist/lyra.js +1 -1
  1130. package/dist/lyra.js.map +1 -1
  1131. package/dist/theme.css +103 -0
  1132. package/llms/components/lr-activity-feed.md +11 -2
  1133. package/llms/components/lr-agent-run.md +16 -1
  1134. package/llms/components/lr-agent-trace.md +11 -0
  1135. package/llms/components/lr-app-rail-item.md +11 -0
  1136. package/llms/components/lr-app-rail.md +11 -0
  1137. package/llms/components/lr-archive-viewer.md +7 -1
  1138. package/llms/components/lr-artifact-panel.md +11 -1
  1139. package/llms/components/lr-av-player.md +38 -2
  1140. package/llms/components/lr-avatar-group.md +6 -1
  1141. package/llms/components/lr-avatar.md +6 -2
  1142. package/llms/components/lr-badge.md +8 -1
  1143. package/llms/components/lr-bar-chart.md +3 -1
  1144. package/llms/components/lr-breadcrumb-item.md +9 -0
  1145. package/llms/components/lr-breadcrumb.md +9 -0
  1146. package/llms/components/lr-bubble-chart.md +3 -1
  1147. package/llms/components/lr-button.md +29 -1
  1148. package/llms/components/lr-calendar.md +5 -1
  1149. package/llms/components/lr-callout.md +6 -1
  1150. package/llms/components/lr-card.md +26 -5
  1151. package/llms/components/lr-carousel.md +9 -0
  1152. package/llms/components/lr-chart.md +2 -1
  1153. package/llms/components/lr-chat-composer.md +18 -5
  1154. package/llms/components/lr-chat-message.md +16 -0
  1155. package/llms/components/lr-chat-viewport.md +12 -0
  1156. package/llms/components/lr-checkbox-group.md +17 -0
  1157. package/llms/components/lr-checkbox.md +28 -1
  1158. package/llms/components/lr-chip-group.md +19 -1
  1159. package/llms/components/lr-chip.md +19 -1
  1160. package/llms/components/lr-chunk-inspector.md +33 -5
  1161. package/llms/components/lr-code-block-core.md +6 -1
  1162. package/llms/components/lr-code-block.md +20 -1
  1163. package/llms/components/lr-combobox.md +39 -4
  1164. package/llms/components/lr-command-palette.md +18 -7
  1165. package/llms/components/lr-commit-card.md +10 -0
  1166. package/llms/components/lr-community-card.md +5 -0
  1167. package/llms/components/lr-confirm-bar.md +26 -1
  1168. package/llms/components/lr-conversation-item.md +41 -1
  1169. package/llms/components/lr-csv-viewer.md +16 -3
  1170. package/llms/components/lr-data-grid.md +8 -0
  1171. package/llms/components/lr-dataset-viewer.md +4 -1
  1172. package/llms/components/lr-date-input.md +31 -6
  1173. package/llms/components/lr-date-picker.md +31 -6
  1174. package/llms/components/lr-document-preview.md +9 -1
  1175. package/llms/components/lr-doughnut-chart.md +3 -1
  1176. package/llms/components/lr-dropdown-item.md +63 -11
  1177. package/llms/components/lr-email-viewer.md +4 -3
  1178. package/llms/components/lr-emoji-picker.md +28 -4
  1179. package/llms/components/lr-empty.md +5 -2
  1180. package/llms/components/lr-entity-card.md +14 -1
  1181. package/llms/components/lr-env-list.md +9 -0
  1182. package/llms/components/lr-eval-dataset.md +3 -1
  1183. package/llms/components/lr-export-button.md +4 -1
  1184. package/llms/components/lr-file-input.md +19 -2
  1185. package/llms/components/lr-filter-bar.md +23 -0
  1186. package/llms/components/lr-flag.md +39 -1
  1187. package/llms/components/lr-flow-canvas.md +15 -2
  1188. package/llms/components/lr-flow-controls.md +14 -3
  1189. package/llms/components/lr-flow-node.md +24 -3
  1190. package/llms/components/lr-flow-run-overlay.md +4 -0
  1191. package/llms/components/lr-graph-legend.md +4 -1
  1192. package/llms/components/lr-graph.md +4 -1
  1193. package/llms/components/lr-heatmap.md +29 -3
  1194. package/llms/components/lr-histogram.md +3 -1
  1195. package/llms/components/lr-icon-button.md +20 -4
  1196. package/llms/components/lr-image-viewer.md +20 -1
  1197. package/llms/components/lr-ingestion-queue.md +8 -0
  1198. package/llms/components/lr-input.md +36 -1
  1199. package/llms/components/lr-json-viewer.md +6 -3
  1200. package/llms/components/lr-known-date.md +22 -3
  1201. package/llms/components/lr-line-chart.md +3 -1
  1202. package/llms/components/lr-map.md +3 -1
  1203. package/llms/components/lr-markdown-core.md +9 -0
  1204. package/llms/components/lr-markdown.md +13 -1
  1205. package/llms/components/lr-media-card.md +5 -0
  1206. package/llms/components/lr-memory-panel.md +6 -1
  1207. package/llms/components/lr-mention-popover.md +10 -3
  1208. package/llms/components/lr-menu-item.md +63 -11
  1209. package/llms/components/lr-menu.md +63 -11
  1210. package/llms/components/lr-message-feedback.md +15 -0
  1211. package/llms/components/lr-mind-map.md +3 -1
  1212. package/llms/components/lr-model-select.md +29 -4
  1213. package/llms/components/lr-neighbor-list.md +10 -4
  1214. package/llms/components/lr-node-palette.md +3 -1
  1215. package/llms/components/lr-notebook-viewer.md +17 -2
  1216. package/llms/components/lr-number-input.md +3 -2
  1217. package/llms/components/lr-option.md +39 -4
  1218. package/llms/components/lr-page-rail.md +14 -3
  1219. package/llms/components/lr-pagination.md +5 -2
  1220. package/llms/components/lr-pdf-viewer.md +25 -9
  1221. package/llms/components/lr-phone-input.md +39 -5
  1222. package/llms/components/lr-pie-chart.md +3 -1
  1223. package/llms/components/lr-polar-area-chart.md +3 -1
  1224. package/llms/components/lr-policy-summary.md +10 -0
  1225. package/llms/components/lr-poll-status.md +5 -1
  1226. package/llms/components/lr-push-to-talk.md +8 -1
  1227. package/llms/components/lr-radar-chart.md +3 -1
  1228. package/llms/components/lr-radio.md +10 -2
  1229. package/llms/components/lr-responsive-panel.md +5 -1
  1230. package/llms/components/lr-result-card.md +14 -2
  1231. package/llms/components/lr-result-field.md +14 -2
  1232. package/llms/components/lr-retrieval-results.md +30 -3
  1233. package/llms/components/lr-retrieval-trace.md +8 -1
  1234. package/llms/components/lr-rubric-form.md +5 -0
  1235. package/llms/components/lr-scatter-chart.md +3 -1
  1236. package/llms/components/lr-segmented.md +23 -1
  1237. package/llms/components/lr-select.md +31 -4
  1238. package/llms/components/lr-sequence-strip.md +16 -4
  1239. package/llms/components/lr-source-card.md +14 -1
  1240. package/llms/components/lr-source-list.md +14 -1
  1241. package/llms/components/lr-source-picker.md +13 -1
  1242. package/llms/components/lr-span-waterfall.md +12 -2
  1243. package/llms/components/lr-split.md +46 -4
  1244. package/llms/components/lr-spreadsheet-viewer.md +10 -1
  1245. package/llms/components/lr-stack-trace.md +7 -1
  1246. package/llms/components/lr-stat.md +26 -4
  1247. package/llms/components/lr-stepper.md +25 -8
  1248. package/llms/components/lr-suggestion-chips.md +9 -0
  1249. package/llms/components/lr-svg-viewer.md +8 -0
  1250. package/llms/components/lr-table.md +117 -6
  1251. package/llms/components/lr-tabs.md +12 -1
  1252. package/llms/components/lr-tag.md +8 -1
  1253. package/llms/components/lr-task-list.md +12 -2
  1254. package/llms/components/lr-terminal.md +14 -2
  1255. package/llms/components/lr-test-results.md +11 -0
  1256. package/llms/components/lr-thread-list.md +67 -7
  1257. package/llms/components/lr-time-input.md +3 -2
  1258. package/llms/components/lr-time-range.md +18 -2
  1259. package/llms/components/lr-token-input.md +33 -6
  1260. package/llms/components/lr-tool-approval-dialog.md +5 -5
  1261. package/llms/components/lr-tool-timeline.md +6 -1
  1262. package/llms/components/lr-tour.md +11 -1
  1263. package/llms/components/lr-trace-tree.md +23 -0
  1264. package/llms/components/lr-tree-node.md +21 -3
  1265. package/llms/components/lr-tree.md +21 -3
  1266. package/llms/components/lr-virtual-list.md +99 -10
  1267. package/llms/components/lr-voice-picker.md +8 -0
  1268. package/llms/components/lr-widget.md +11 -0
  1269. package/llms/components/lr-xml-viewer.md +24 -1
  1270. package/llms/peers.md +1 -1
  1271. package/llms/shared.md +129 -7
  1272. package/llms/tokens.md +14 -7
  1273. package/llms-full.txt +2180 -250
  1274. package/llms.txt +12 -0
  1275. package/package.json +10 -3
  1276. package/vscode-css-data.json +1421 -168
  1277. package/vscode-html-data.json +499 -155
  1278. package/web-types.json +1296 -188
package/llms-full.txt CHANGED
@@ -71,7 +71,7 @@ module-resolution failure, not a silent no-op — `exports` maps `./components/*
71
71
  `lr-bar-chart`, `lr-pie-chart`, `lr-doughnut-chart`, `lr-radar-chart`, `lr-polar-area-chart`,
72
72
  `lr-bubble-chart`, `lr-scatter-chart`), `lr-box-plot`, `lr-histogram`, `lr-map`, `lr-graph`,
73
73
  `lr-knowledge-graph-explorer`, and `lr-geojson-view`. Those always need their own subpath import.
74
- The barrel also re-exports every class and type (127 `Lyra*EventMap` types included), so it is the
74
+ The barrel also re-exports every class and type (every `Lyra*EventMap` type included), so it is the
75
75
  one import that defeats tree-shaking — prefer per-component entries in application code.
76
76
  - **`lr-flag`** registers from the barrel, but resolving a flag by `country`/`language` (rather than
77
77
  a pre-resolved `src`) additionally needs
@@ -154,17 +154,78 @@ Readonly getters, on every form-associated control: `form`, `labels`, `validity`
154
154
 
155
155
  ## Theming and design tokens
156
156
 
157
- Two layers, both inherited from `LyraElement` (`internal/tokens.styles.ts`):
157
+ Three layers, and **which one you set decides how far the override reaches**:
158
158
 
159
- 1. **`--lr-theme-*`** — the application input layer. Set these to retheme; this is the only supported
160
- theming mechanism.
159
+ 1. **`--lr-theme-*`** — the application input layer. Declared exactly once, at `:root` in
160
+ `theme.css`, and never inside any component's shadow styles. Set these to retheme.
161
161
  2. **`--lr-*`** — internal tokens. Each reads one `--lr-theme-*` input with a hardcoded fallback
162
162
  (`--lr-color-brand: var(--lr-theme-color-brand-fill-loud, #0969da)`), so every component renders
163
163
  correctly with no theme configured.
164
+ 3. **`--lr-<component>-*`** — per-component properties, for one element at a time. Listed in each
165
+ component's own section.
166
+
167
+ ### Where an override actually reaches
168
+
169
+ **A `--lr-*` token is declared on every `lr-*` element's `:host`.** So a `--lr-*` value you set on
170
+ an ancestor is re-declared — and lost — at the first `lr-*` element between that ancestor and the
171
+ component you meant to style. It never reaches anything nested inside another component.
172
+
173
+ **`--lr-theme-*` inputs are declared only once**, at `:root`, and never inside a component's shadow
174
+ styles — so they inherit normally through every nested shadow root. **Setting a `--lr-theme-*` input
175
+ on a wrapper element is the supported way to retheme one subtree.** Setting a `--lr-*` token there
176
+ only works for that wrapper's direct children.
177
+
178
+ ```css
179
+ /* Reaches everything in the subtree, however deeply nested. */
180
+ .invoice-panel { --lr-theme-color-brand-fill-loud: #7c3aed; }
181
+
182
+ /* Reaches direct lr-* children only — shadowed at the first nested lr-* host. */
183
+ .invoice-panel { --lr-color-brand: #7c3aed; }
184
+ ```
185
+
186
+ Layer 3 is the exception that proves the rule: a handful of `--lr-<component>-*` escape hatches are
187
+ deliberately left **undeclared** by their component and read only through a `var()` fallback at the
188
+ point of use, precisely so a value set on an ancestor is not shadowed. Each one says so in its own
189
+ section; assume shadowing for anything that doesn't.
190
+
191
+ **Diagnostic:** if a token override has no effect on a nested component, check which layer you set
192
+ before assuming the component is at fault. A `--lr-*` override that works on a standalone control
193
+ and stops working once you nest that control inside another component is this rule, not a bug.
194
+
195
+ **There is no way to tell a live `--lr-*` declaration from a dead one without rendering.** A dead
196
+ declaration is byte-identical to a working one in the stylesheet, and nothing in a build reports
197
+ it — a test asserting on stylesheet source text (`expect(source).toContain('--lr-token: …')`)
198
+ passes just as happily when the token is being shadowed at a nested host. Verify with
199
+ `getComputedStyle` on the real element in the real state, and perturb the value deliberately to
200
+ confirm the assertion actually bites.
201
+
202
+ The same trap has a second form inside a component's own styles: a *declared* value always wins
203
+ over a `var()` fallback arm, and `auto` is a declared value. That is why the exact-height escape
204
+ hatches (`--lr-input-control-height`, `--lr-select-trigger-height`, `--lr-chip-height`, …) are
205
+ undeclared by default rather than set to `auto`. Setting one *to* `auto` is therefore not the same
206
+ as leaving it alone: it wins over the fallback arm and makes the per-size minimum-height floor dead
207
+ code. See each control's own reference page for its exact pair.
208
+
209
+ ### Tokens with a contract attached
210
+
211
+ - **`--lr-theme-icon-button-size`** (default `2.5rem`) backs `--lr-icon-button-size`, the tappable
212
+ box of **every** icon-only control in the library — `lr-icon-button` itself, and the
213
+ expand/clear/toggle affordances inside `lr-date-input`, `lr-combobox`, `lr-input`, and
214
+ `lr-select`. It is a *floor*, not a fixed size. Keep the resolved value **at or above 24px**
215
+ (WCAG 2.2 SC 2.5.8 target size); the default leaves headroom. Lowering it below that shrinks
216
+ every affordance in the library at once.
217
+ - **Aligning your own content next to a checkbox or radio.** `--lr-checkbox-label-indent` /
218
+ `--lr-radio-label-indent` publish the label offset, but custom properties inherit *down*, not
219
+ sideways, so a sibling node in your tree cannot read them off the control. Compute the same
220
+ formula from the `--lr-theme-*` inputs you control:
221
+ ```css
222
+ padding-inline-start: calc(
223
+ min(var(--lr-theme-icon-button-size, 2.5rem), 1.75rem) + var(--lr-theme-space-s, 0.5rem)
224
+ );
225
+ ```
164
226
 
165
227
  **`llms/tokens.md` is the full generated catalog** of every token, its `--lr-theme-*` input, and its
166
- fallback — consult it rather than guessing a token name. Components additionally expose scoped
167
- `--lr-<component>-*` properties for one-off overrides, listed in each component's own section.
228
+ fallback — consult it rather than guessing a token name.
168
229
 
169
230
  ```css
170
231
  @import '@aceshooting/lyra-ui/theme.css'; /* optional ready-made light + dark base */
@@ -336,7 +397,7 @@ Not custom elements — infrastructure the components compose. Importable via
336
397
  Returns a cleanup function that stops the `autoUpdate` loop — call it in `disconnectedCallback()`.
337
398
  Used by `lr-combobox`, `lr-select`, `lr-date-input`, `lr-export-button`, `lr-model-select`,
338
399
  `lr-mention-popover`, `lr-tool-call-chip`, `lr-citation-badge`, and `lr-menu`.
339
- - **`prefix.ts`** — `LYRA_PREFIX = 'lyra'`; `tag(name)` → `` `lr-${name}` ``; `defineElement(name, ctor)`,
400
+ - **`prefix.ts`** — `LYRA_PREFIX = 'lr'`; `tag(name)` → `` `lr-${name}` ``; `defineElement(name, ctor)`,
340
401
  an idempotent `customElements.define` that is safe if a module is evaluated twice.
341
402
  - **`a11y.ts`** — `nextId(scope)`, a monotonic id generator (`nextId('combobox-list')` →
342
403
  `"lr-combobox-list-3"`); `srOnly`, a visually-hidden-but-AT-visible class.
@@ -370,6 +431,67 @@ Not custom elements — infrastructure the components compose. Importable via
370
431
  `prepack` and included in `package.json`'s `files` allowlist, so a published tarball always carries
371
432
  an up-to-date copy matching its `dist/`.
372
433
 
434
+ ## When no component fits, file it
435
+
436
+ First rule out a naming mismatch: check `llms/index.md` for a component covering the same job
437
+ under a different name. Most apparent gaps are discovery failures, not missing components.
438
+
439
+ Then check the live catalog — one read-only request, no side effects, nothing filed:
440
+
441
+ ```bash
442
+ curl -sS 'https://www.lyra-ui.com/api/v1/components/search?q=kanban+board+swimlane'
443
+ ```
444
+
445
+ It returns the closest components with doc links. Search as many phrasings as you like; this
446
+ endpoint is meant to be used freely, and it is the cheapest way to discover that a "missing"
447
+ component already exists under a name you did not guess.
448
+
449
+ If nothing fits, report the gap so it can be built — but **ask the user and get their explicit
450
+ agreement first.** Filing sends the user's description to an external service; show them what you
451
+ intend to submit, and never file as a silent side effect of noticing a gap. If the user has not
452
+ said yes, do not send it.
453
+
454
+ ```bash
455
+ curl -sS -X POST https://www.lyra-ui.com/api/v1/feature-requests \
456
+ -H 'Content-Type: application/json' \
457
+ -d '{
458
+ "title": "Kanban board",
459
+ "description": "Needed a drag-and-drop board with swimlanes for a task view; nothing in the catalog covers it.",
460
+ "searched_for": ["kanban", "board", "swimlane", "drag drop"],
461
+ "settled_for": "a hand-rolled div grid with HTML5 drag events",
462
+ "agent": "claude-code"
463
+ }'
464
+ ```
465
+
466
+ Accepted fields: `title` (required, ≤120 chars), `description` (required, ≤4000 chars), `use_case`,
467
+ `searched_for` (array of terms tried — the most valuable field, since it records which name was
468
+ expected and that's exactly what makes a component undiscoverable), `settled_for` (what was used
469
+ instead), `agent`, and the optional contact fields `name` (≤120) and `email` (≤200). Anonymous
470
+ submission is the default and is fine — `name`/`email` only add value if the maintainer might
471
+ follow up. Ask the user whether they want to be reachable before adding either one; never invent,
472
+ guess, or reuse an address from context you happen to have (git config, an earlier message, the
473
+ environment). All submissions, including any name/email, are stored privately and shown only to
474
+ the maintainer — never published.
475
+
476
+ The response includes `matches` (the closest existing components, with doc links — read it, since
477
+ it often answers the gap outright) and an `id`; status is readable later at
478
+ `https://www.lyra-ui.com/api/v1/feature-requests/{id}`. The full schema is at
479
+ `https://www.lyra-ui.com/api/v1/openapi.json`.
480
+
481
+ **Never include private material.** Submissions leave the user's machine. Describe the component
482
+ generically — no source code, no client or product names, no file paths, no credentials. If the
483
+ need cannot be described without such details, do not file it.
484
+
485
+ Use the API even when you are working inside the lyra-ui repo itself. It is the only intake path —
486
+ do not write the request into a local file instead, where nothing will pick it up.
487
+
488
+ Keep the report short and concrete:
489
+
490
+ - **Name the component you wanted**, in library style (`lr-kanban-board`), so the gap is searchable.
491
+ - **Say what it had to do** in a sentence or two — the behaviour, not your implementation.
492
+ - **List the `lr-*` components you actually checked** and why each fell short. This is what separates
493
+ a real gap from a naming mismatch, and it is the part only you can supply.
494
+
373
495
  # Form controls & inputs (`components/forms/`)
374
496
 
375
497
  ## `lr-combobox` / `lr-option`
@@ -396,7 +518,9 @@ shared `FormAssociated` mixin — see gotchas).
396
518
  - `errorText: string = ''` (attribute `error-text` — static error copy shown below the hint;
397
519
  overridden by slotted `error` content when provided)
398
520
  - `open: boolean = false` (reflected)
399
- - `clearable: boolean = false` (reflected) — displays the clear button while a value is selected
521
+ - `clearable: boolean = false` (reflected) — displays the clear button while there is something to
522
+ clear on **either** axis this control owns: a committed selection, or *visible* filter text. See
523
+ "the clear button covers two axes" below
400
524
  - `withClear: boolean = false` (attribute `with-clear`) — deprecated compatibility alias for
401
525
  `clearable`; either property enables the same clear button
402
526
  - `autocomplete: string = 'off'`, `inputMode: string = ''` (attribute `inputmode`),
@@ -457,10 +581,31 @@ the filter silently, mirroring how `<lr-input>`'s `lr-input` only reports user e
457
581
  `lr-show` and `lr-hide` report listbox visibility transitions.
458
582
  The internal input's `focus` and `blur` are re-dispatched as bubbling, composed host events.
459
583
 
460
- **Slots:** default (`<lr-option>` children), `label`, `hint`, `error` (overrides the `errorText`
461
- attribute when provided)
584
+ **The clear button covers two axes, and announces only the one that moved.** A combobox owns both a
585
+ committed selection and an in-progress filter query, so the button renders whenever either has
586
+ something to clear, and one press clears both:
587
+
588
+ - Clearing a selection emits `input`, then `change`, then `lr-clear` — and, if the query was also
589
+ non-empty, `lr-filter` with an empty `value`.
590
+ - A **query-only** clear (nothing selected, just typed text) emits `lr-filter` with an empty
591
+ `value` and deliberately **no** `change` and **no** `lr-clear`. There was no selection
592
+ transition to report, so announcing one would be a lie. Don't listen for `lr-clear` to detect
593
+ "the user emptied the field" — listen for `lr-filter` when you care about the query.
594
+ - The query half of the render gate is scoped to states where the query is actually *visible*: an
595
+ open listbox in single-select, or any time in `multiple` mode. A closed single-select shows the
596
+ selected label rather than the query, so a stale query alone never surfaces a button offering to
597
+ clear text the user cannot see.
462
598
 
463
- **CSS parts:** `form-control`, `form-control-label`, `combobox`, `tags`, `tag`,
599
+ **Slots:** default (`<lr-option>` children), `label`, `hint`, `error` (overrides the `errorText`
600
+ attribute when provided), plus two adornment slots:
601
+ - `start` — content at the inline-start of the trigger row, before the selected-value tags and the
602
+ filter input. It is decorative chrome, **not** an option: only `<lr-option>` elements in the
603
+ default slot are ever collected into the option list.
604
+ - `end` — content after the filter input and the built-in clear action, and before the expand icon,
605
+ so consumer content never sits outboard of the dropdown chevron.
606
+
607
+ **CSS parts:** `form-control`, `form-control-label`, `combobox`, `start` and `end` (the two
608
+ adornment-slot wrappers, each `hidden` while nothing is slotted into it), `tags`, `tag`,
464
609
  `tag__remove-button`, `combobox-input`, `clear-button`, `expand-icon`, `listbox`, `option`,
465
610
  `option-dot` (the leading status dot, when a row's `dotColor` is set), `option-icon` (the decorative
466
611
  leading visual for an async row), `option-label`, `option-sub` (a row's secondary line, when `sub`
@@ -472,6 +617,18 @@ indicator from `maxRender`), `error`, `hint`
472
617
  `--lr-combobox-tag-font-size`, and `--lr-combobox-expand-size` (the decorative icon box; each
473
618
  standard size supplies an aligned default), plus shared tokens.
474
619
 
620
+ `--lr-combobox-option-active-bg` (default `var(--lr-color-brand-quiet)`) recolors the background of
621
+ a hovered or keyboard-active `[part='option']` row — the same per-component indirection
622
+ `lr-select`'s identical `--lr-select-option-active-bg` uses, so a consumer can retheme just this
623
+ row state without hijacking the shared `--lr-color-brand-quiet` token library-wide.
624
+
625
+ `--lr-combobox-trigger-height` pins an **exact** input-container height (both floors and caps it),
626
+ for pixel-matching an `<lr-input>` or `<lr-select>` in the same toolbar row. It is **undeclared by
627
+ default**, leaving `--lr-combobox-trigger-min-height` as a floor only and the row free to grow —
628
+ see "exact-height hatches" under `lr-input` for why `auto` is not a way to opt back out. Intended
629
+ for a single-row combobox: in `multiple` mode, a tag row long enough to wrap overflows the pinned
630
+ box visibly (nothing is clipped or made unreachable), so leave it unset there.
631
+
475
632
  **Optional peer deps:** none.
476
633
 
477
634
  ### `lr-option`
@@ -604,6 +761,15 @@ selection change — a native `<select>` doesn't meaningfully distinguish the tw
604
761
  **Slots:** default (`<lr-option>` children), `label`, `hint`, `error` (overrides the `errorText`
605
762
  attribute when provided)
606
763
 
764
+ **`lr-select` deliberately has no `start`/`end` adornment slots**, unlike
765
+ `lr-input`/`lr-combobox`/`lr-date-input`. Two reasons, both structural rather than incidental:
766
+ its `[part='trigger']` is a native `<button>`, and HTML's content model forbids interactive
767
+ descendants inside one — so the slot could only ever accept decorative content, a materially
768
+ different contract from the other three that would read as the same feature; and the trigger lays
769
+ out with `justify-content: space-between`, so injecting a leading element pushes the selected label
770
+ into the middle of the control instead of leaving it at the start. **Instead:** put a glyph in the
771
+ `label` slot, or compose the select into `<lr-control-group>` alongside the adornment.
772
+
607
773
  When hint/error content is present, the trigger's `aria-describedby` references stable shadow-local
608
774
  IDs for both messages (error first, then hint), so the visible supporting text is part of the
609
775
  control's accessible description.
@@ -616,10 +782,28 @@ presentational `<div>`, not a `role="group"`; options with an empty `group` get
616
782
 
617
783
  **Themeable custom properties:** `--lr-select-trigger-padding`, `--lr-select-trigger-min-height`,
618
784
  `--lr-select-font-size`, `--lr-select-expand-size` — all four auto-swapped per `size` (`xs`…`xl`), the same pattern
619
- `lr-toast-item`'s `--lr-toast-padding`/`--lr-toast-font-size` use. `--lr-select-trigger-height`
620
- (default `auto`) — unset, it leaves `--lr-select-trigger-min-height` as a floor only, unchanged; set
621
- it to force an exact trigger height (e.g. to pixel-match a sibling text field in the same row), which
622
- both floors and caps the trigger at that height.
785
+ `lr-toast-item`'s `--lr-toast-padding`/`--lr-toast-font-size` use.
786
+
787
+ `--lr-select-trigger-min-height` is live at **every** tier, the default `m` included, where it is
788
+ `2.5rem` byte-identical to `lr-input`'s and `lr-combobox`'s own `m` floor, so the three controls
789
+ agree at that tier. It used to be dead code: the component declared `--lr-select-trigger-height:
790
+ auto` on `:host`, and a *declared* value (`auto` is one) wins over the `var()` fallback arm that
791
+ the floor lives in, so the floor never applied and four extra specificity rules existed only to
792
+ patch it back for four of the tiers. Those rules are gone.
793
+
794
+ `--lr-select-trigger-height` pins an **exact** trigger height — both a floor and a cap — e.g. to
795
+ pixel-match a sibling text field in the same toolbar row. It is **undeclared by default**, which is
796
+ exactly what keeps the per-tier floor alive; see "exact-height hatches" under `lr-input`. Because
797
+ the component never declares it, it can be set inline, from an ancestor, or from an outer-tree
798
+ rule. One consequence worth knowing when testing:
799
+ `getComputedStyle(el).getPropertyValue('--lr-select-trigger-height')` now reads `''` rather than
800
+ `'auto'` — assert the rendered `min-block-size`/`block-size` instead of the property string.
801
+
802
+ `--lr-select-option-active-bg` (default `var(--lr-color-brand-quiet)`) recolors the background of a
803
+ hovered or keyboard-active `[part='option']` row. Not declared on `:host`, so a value set on any
804
+ ancestor is never shadowed — retheme just this row state without hijacking the shared
805
+ `--lr-color-brand-quiet` token every other component's own hover/active state also reads. Same
806
+ knob `lr-combobox`'s own `--lr-combobox-option-active-bg` provides.
623
807
 
624
808
  **Optional peer deps:** none.
625
809
 
@@ -775,17 +959,42 @@ internal native date input.
775
959
  the internal `<input>`'s own `blur`, bubbling and composed unlike the native event), `focus`
776
960
  (re-dispatched from the internal `<input>`'s own `focus`, for the same reason as `blur`)
777
961
 
778
- **Slots:** `label`, `error` (overrides `errorText`), `hint`
962
+ **Slots:** `label`, `error` (overrides `errorText`), `hint`, plus two adornment slots:
963
+ - `start` — content at the inline-start of the input row, before the text field.
964
+ - `end` — content after the text field and the built-in clear action, and before the calendar
965
+ toggle, so consumer content never sits outboard of the calendar button.
779
966
 
780
- **CSS parts:** `form-control`, `form-control-label`, `input-wrapper`, `input`, `clear-button`,
967
+ **CSS parts:** `form-control`, `form-control-label`, `input-wrapper`, `input`, `start` and `end`
968
+ (the two adornment-slot wrappers, each `hidden` while nothing is slotted into it), `clear-button`,
781
969
  `expand-button`, `expand-icon`, `popup`, `date-picker`, `error`, `hint`
782
970
 
783
971
  **Themeable custom properties:** `--lr-date-input-padding-block` (default `--lr-space-xs`) and
784
972
  `--lr-date-input-padding-inline` (default `--lr-space-s`) — the `input-wrapper`'s padding;
785
- `--lr-date-input-font-size` (default `inherit`) — the `input` part's font size. All three are
786
- declared on `:host` and auto-swapped per `size` (`2xs`/`xs`/`s`/`l`/`xl`; `m` keeps the `:host`
787
- defaults), deliberately matching `lr-input`'s own per-`size` padding/font-size values so a
788
- same-`size` `lr-input` and `lr-date-input` end up height/density-matched. Plus shared tokens.
973
+ `--lr-date-input-font-size` (default `inherit`) — the `input` part's font size;
974
+ `--lr-date-input-control-min-height` (default `--lr-size-2-5rem`) the `input-wrapper`'s block-size
975
+ floor. All four are declared on `:host` and auto-swapped per `size`
976
+ (`2xs`/`xs`/`s`/`l`/`xl`; `m` keeps the `:host` defaults), using the same per-`size` values
977
+ `lr-input` uses. Plus shared tokens.
978
+
979
+ `--lr-date-input-control-height` pins an **exact** `input-wrapper` height (both floors and caps it).
980
+ It is **undeclared by default**, so the row grows to fit its content — see "exact-height hatches"
981
+ under `lr-input`. Pinning it *below* the calendar toggle's 24×24 target is safe: the toggle keeps
982
+ its own `--lr-icon-button-size` floor and simply overflows a short row rather than shrinking, so
983
+ WCAG 2.2 SC 2.5.8 is preserved either way.
984
+
985
+ **Height parity with `lr-input` is density parity, not pixel parity.** The per-`size` padding and
986
+ font-size scale is shared with `lr-input`, so the two look equally dense at a given `size` — but a
987
+ same-`size` pair does **not** end up the same height, and code that assumes it will be
988
+ disappointed at the small tiers. `[part='input-wrapper']` carries no intrinsic `min-block-size` of
989
+ its own, while `[part='expand-button']` pins `min-block-size: var(--lr-icon-button-size)` that is
990
+ deliberately **not** gated by `size` — the calendar toggle must keep a 24×24 touch target at every
991
+ tier, and `lr-input`'s own password-toggle floors identically. So the row height is pinned
992
+ transitively by that button: at `size="s"` an `lr-input` floors at `1.875rem`/30px, while an
993
+ `lr-date-input` cannot go below roughly 40px plus its padding. Every default value of
994
+ `--lr-date-input-control-min-height` sits below that transitive height, which means the floor is
995
+ inert until you raise it past the button — a lower value changes nothing. To line the two controls
996
+ up exactly, either raise `lr-input`'s floor to meet the date input, or lower
997
+ `--lr-theme-icon-button-size` on a common ancestor (never below 24px).
789
998
 
790
999
  **Optional peer deps:** none.
791
1000
 
@@ -1000,12 +1209,40 @@ loud fill token), `--lr-button-outlined-border` (default `--lr-color-border-stro
1000
1209
  `--lr-button-hover-brightness` (default `1.08`, the `:hover` filter intensity),
1001
1210
  `--lr-button-active-scale` (default `0.9875`, the `:active` press-scale, disabled under
1002
1211
  `prefers-reduced-motion`), `--lr-button-spinner-duration` (default `1s`, the `loading` spinner's
1003
- rotation period; forced to `0.001ms` under `prefers-reduced-motion`), and the per-`size`
1212
+ rotation period; forced to `0.001ms` under `prefers-reduced-motion`),
1213
+ `--lr-button-outlined-fill` (default `transparent`, the `appearance="outlined"` background — also
1214
+ variant-independent; set it to tint an outlined button with, say, a faint surface wash behind the
1215
+ outline, without a `::part(base)` rule. Note that the `:hover` `filter: brightness()` applies to
1216
+ whatever fill is set, so a tinted outlined button visibly brightens on hover where a transparent
1217
+ one did not),
1218
+ and the per-`size`
1004
1219
  `min-block-size` floors `--lr-button-size-2xs` (`1.25rem`), `--lr-button-size-xs` (`1.5rem`),
1005
1220
  `--lr-button-size-s` (`1.75rem`), `--lr-button-size-m` (`2rem`), `--lr-button-size-l` (`2.5rem`),
1006
1221
  `--lr-button-size-xl` (`3rem`) — each read only by its own `size` tier, and all ignored by
1007
1222
  `appearance="link"`.
1008
1223
 
1224
+ **Retuning one `size` tier's geometry, without a `::part(base)` rule.** Four more properties carry
1225
+ the active tier's geometry, and every `:host([size='…'])` rule does nothing but re-assign them — no
1226
+ per-tier rule ever declares a property on `[part='base']`. Overriding one therefore retunes
1227
+ whatever tier is active (e.g. pinning a `size="s"` button into a compact toolbar row), the same
1228
+ pattern `lr-input`/`lr-select`/`lr-combobox`/`lr-segmented`/`lr-date-input` follow. Their defaults
1229
+ below are the `m` tier's values, because `size` reflects and defaults to `m`, so the `:host`
1230
+ declarations *are* the `m` tier:
1231
+
1232
+ - `--lr-button-padding-block` (default `--lr-space-xs`)
1233
+ - `--lr-button-padding-inline` (default `--lr-space-m`)
1234
+ - `--lr-button-font-size` (default `--lr-font-size-m`)
1235
+ - `--lr-button-min-height` (default `--lr-button-size-m`) — the active tier's `min-block-size`
1236
+ floor, re-assigned per tier to that tier's own `--lr-button-size-*` token, and used as the
1237
+ fallback when `--lr-button-height` is unset.
1238
+ - `--lr-button-height` — an **exact** height (both floor and cap), for pinning the button to a
1239
+ fixed toolbar row. **Undeclared by default**, so the button keeps the active tier's floor and an
1240
+ `auto` height; see "exact-height hatches" under `lr-input`.
1241
+
1242
+ `appearance="link"` ignores all five: it is declared after the `size` rules and resets padding,
1243
+ font, and both height properties with literals, so an inline link can never take a button-shaped
1244
+ box no matter what tier or override is in play.
1245
+
1009
1246
  **Optional peer deps:** none.
1010
1247
 
1011
1248
  ```html
@@ -1044,14 +1281,30 @@ With neither `accessibleLabel` nor `label` set, the name falls back to the local
1044
1281
  app-wide with `registerLyraLocale()` (see `llms/shared.md`); don't rely on the fallback for a
1045
1282
  button whose purpose isn't generic.
1046
1283
 
1047
- **Methods:** `focus(options?)`, `blur()` — forward to the native button.
1284
+ **Methods:** `focus(options?)`, `blur()` — forward to the native button. `click()` also forwards to
1285
+ the native button, activating it — including this component's own `type="submit"`/`type="reset"`
1286
+ handling, since the click goes through the same `<button>` the pointer/keyboard path does.
1048
1287
 
1049
- **Slots:** (default) — custom icon content, forwarded into the inner `lr-icon`'s slot; use it
1050
- instead of `icon` for a glyph outside the built-in set.
1288
+ **Slots:** (default) — custom icon content. It is rendered **beside** the `icon` glyph, as a
1289
+ sibling of it, not piped through `<lr-icon>`: the internal `<lr-icon>` mounts only when `icon` is
1290
+ set, so with `icon` left empty your content is the button's only child. That is what lets a
1291
+ complete element — an `<svg>`, an `<img>`, an `<lr-flag>` — render at its own natural aspect ratio
1292
+ instead of being forced into a 1:1 box. Setting both `icon` and slotted content renders both, side
1293
+ by side; that is a valid composition, not a fallback.
1294
+
1295
+ **Migration note:** bare SVG *geometry* (`<path>`, `<circle>`, `<rect>` …) slotted with no `icon`
1296
+ set has no SVG parent here and will not paint. Wrap it in an `<lr-icon>`, or in a complete `<svg>`
1297
+ of your own.
1051
1298
 
1052
1299
  **CSS parts:** `button`
1053
1300
 
1054
- **Themeable custom properties:** `--lr-icon-button-size` sets both dimensions of the hit target.
1301
+ **Themeable custom properties:** `--lr-icon-button-size` (default `2.5rem`) is the **minimum**
1302
+ tappable inline and block size of the native button — a floor, not a fixed size. Content larger
1303
+ than it grows the button and keeps its own aspect ratio; a small glyph pads out to it. It is a
1304
+ library-wide token (declared on `:root` by the token layer, and the shared minimum tappable size
1305
+ that several other components size their icon-only controls against), so overriding
1306
+ `--lr-theme-icon-button-size` globally resizes all of them together. Keep the resolved value at or
1307
+ above 24px — see `llms/shared.md`.
1055
1308
 
1056
1309
  ## `lr-input`
1057
1310
 
@@ -1089,7 +1342,14 @@ form-associated via the same `FormAssociated` mixin as `lr-textarea`. Ships the
1089
1342
  - `name`/`disabled`/`required` (from `FormAssociated`)
1090
1343
 
1091
1344
  **Getters/methods:** `input: HTMLInputElement | null` (the internal native `<input>`, for direct DOM
1092
- access), `focus(options?: FocusOptions)`, `blur()`, `select()`.
1345
+ access), `focus(options?: FocusOptions)`, `blur()`, `select()`. Also forwards the full native
1346
+ selection/editing surface, mirroring `lr-textarea`'s identical passthrough: `selectionStart: number
1347
+ | null` and `selectionEnd: number | null` (readable/writable; `null` both before the internal input
1348
+ has rendered and whenever `type` doesn't support selection — only `text`/`search`/`password` do,
1349
+ matching the native `<input>`'s own contract), `setSelectionRange(start, end, direction?)`
1350
+ (no-op before render, otherwise throws the same native `InvalidStateError` a native `<input>` would
1351
+ for an unsupported `type`), and `setRangeText(replacement, start?, end?, selectMode?)` (no-op
1352
+ before render; syncs `value` afterward without emitting a user event).
1093
1353
 
1094
1354
  **Events:** native-style composed `input` and `change`, plus `lr-input` (`detail: { value }`,
1095
1355
  fired on every user-driven edit) and `lr-change` (`detail: { value }`, fired on the native
@@ -1108,6 +1368,34 @@ input and built-in actions).
1108
1368
  `--lr-input-font-size`, `--lr-input-control-min-height` — all four auto-swapped per `size`
1109
1369
  (`2xs`…`xl`), the same pattern
1110
1370
  `lr-select`'s `--lr-select-trigger-padding`/`--lr-select-font-size` use.
1371
+ `--lr-input-control-height` pins an **exact** outer control-row height (both floors and caps it) —
1372
+ for example to pixel-match an `<lr-select>` or `<lr-combobox>` in the same toolbar row. It is
1373
+ undeclared by default, leaving `--lr-input-control-min-height` as a floor only and the row free to
1374
+ grow.
1375
+
1376
+ ### Exact-height hatches — the one rule that applies to all of them
1377
+
1378
+ Several controls expose the same pair: a per-`size` `*-min-height` **floor**, and an exact
1379
+ `*-height` **cap**. The family is `--lr-input-control-height`, `--lr-select-trigger-height`,
1380
+ `--lr-combobox-trigger-height`, `--lr-date-input-control-height`, `--lr-button-height`,
1381
+ `--lr-known-date-field-height`, and `--lr-chip-height`. Every one of them behaves identically:
1382
+
1383
+ - **Each is undeclared by default.** The component reads it only through two `var()` fallbacks —
1384
+ `min-block-size: var(--lr-x-height, var(--lr-x-min-height))` and
1385
+ `block-size: var(--lr-x-height, auto)` — so leaving it unset is what makes the per-tier floor
1386
+ and the content-driven height work at all.
1387
+ - **Setting one to `auto` is not the same as leaving it unset.** `auto` is a perfectly valid
1388
+ *declared* value, and a declared value wins over the `var()` fallback arm — so `auto` silently
1389
+ turns the per-tier `*-min-height` floor into dead code, and nothing anywhere reports it. To
1390
+ return a control to default behavior, **remove** the declaration; never neutralize it with
1391
+ `auto`.
1392
+ - Because the component itself never declares them, each can be set inline on the element, from an
1393
+ ancestor, or from an outer-tree rule (`lr-input { --lr-input-control-height: 44px }`) — no
1394
+ `::part()` rule needed.
1395
+ - **A dead declaration is invisible in source.** There is no way to tell a live `--lr-*`
1396
+ declaration from a shadowed or defeated one without rendering: a test asserting on stylesheet
1397
+ text passes either way. Assert the rendered `min-block-size`/`block-size` via
1398
+ `getComputedStyle` on the real element instead of reading the custom property back.
1111
1399
 
1112
1400
  **Optional peer deps:** none.
1113
1401
 
@@ -1147,8 +1435,9 @@ input), and `lr-clear` (inherited, never fired here).
1147
1435
  alias ever renders.
1148
1436
 
1149
1437
  **Themeable custom properties:** inherited from `lr-input`, identical in meaning —
1150
- `--lr-input-control-min-height`, `--lr-input-padding-block`, `--lr-input-padding-inline` and
1151
- `--lr-input-font-size` (the last three swap per `size`).
1438
+ `--lr-input-control-min-height`, `--lr-input-control-height`, `--lr-input-padding-block`,
1439
+ `--lr-input-padding-inline` and `--lr-input-font-size` (all but `--lr-input-control-height` swap
1440
+ per `size`; that one stays undeclared until you pin an exact row height).
1152
1441
 
1153
1442
  **Known gotchas:**
1154
1443
  - `clearable`/`clear-button`/`lr-clear` are inert: the clear action only renders for
@@ -1190,8 +1479,9 @@ native input's own constraint validation reports `rangeUnderflow`/`rangeOverflow
1190
1479
  `hint`, `error`, plus the inherited, never-rendered `clear-button` and `password-toggle`.
1191
1480
 
1192
1481
  **Themeable custom properties:** inherited from `lr-input`, identical in meaning —
1193
- `--lr-input-control-min-height`, `--lr-input-padding-block`, `--lr-input-padding-inline` and
1194
- `--lr-input-font-size` (the last three swap per `size`).
1482
+ `--lr-input-control-min-height`, `--lr-input-control-height`, `--lr-input-padding-block`,
1483
+ `--lr-input-padding-inline` and `--lr-input-font-size` (all but `--lr-input-control-height` swap
1484
+ per `size`; that one stays undeclared until you pin an exact row height).
1195
1485
 
1196
1486
  **Known gotchas:** the same two as `lr-number-input` — the inert clear/password surface, and `type`
1197
1487
  only being re-forced on connect. The native `type="time"` UI (spinners, AM/PM, picker) is the
@@ -1208,6 +1498,12 @@ synchronous `PhoneNumberAdapter`, or lazily create one from a `libphonenumber-js
1208
1498
  with `loadLibphonenumberAdapter()`. Without an adapter, already-international E.164 input still
1209
1499
  normalizes and validates; national input remains editable with `incomplete` validity.
1210
1500
 
1501
+ The country selector keeps the real native `<select>` (localized full country names in its popup,
1502
+ native mobile pickers, keyboard type-ahead) but stretches it invisibly over a compact decorative
1503
+ trigger showing the selected alpha-2 code plus a design-system chevron — long country names never
1504
+ clip the closed control and the adjacent calling code isn't repeated. With `flags`, the trigger
1505
+ also shows the selected country's `<lr-flag>`.
1506
+
1211
1507
  **Types:**
1212
1508
 
1213
1509
  ```ts
@@ -1245,6 +1541,15 @@ interface PhoneNumberAdapter {
1245
1541
  precedence over `adapter.countries`.
1246
1542
  - `defaultCountry: string = ''` (attribute `default-country`) — selected when `country` has not been
1247
1543
  set explicitly.
1544
+ - `flags: boolean = false` (reflected) — show the selected country's flag in the country trigger as
1545
+ `<lr-flag variant="compact" aria-label="">` (decorative; the native select already announces the
1546
+ country name). The `<lr-flag>` element definition is registered lazily the first time any
1547
+ `lr-phone-input` enables this, so nothing flag-related is bundled while it stays off. Flag
1548
+ *artwork* still follows the standalone `<lr-flag>` contract: install the optional
1549
+ `@aceshooting/lyra-flags` peer and import
1550
+ `@aceshooting/lyra-ui/components/media/flag/flag-peer.js` once; without that registration the
1551
+ trigger simply omits the image. The open popup list stays text-only — a native `<option>` cannot
1552
+ contain elements.
1248
1553
  - `country: string` — current uppercase ISO alpha-2 selection; falls back to `defaultCountry`, then
1249
1554
  the first explicit/adapter country. Changing the country reparses the editable number.
1250
1555
  - `label: string = ''`, `hint: string = ''`, `errorText: string = ''` (attribute `error-text`) —
@@ -1305,8 +1610,11 @@ Programmatic property assignments and form reset/state restoration are silent.
1305
1610
  **Slots:** `label`, `hint`, `error`, `country-prefix` (optional visual before the country selector,
1306
1611
  such as a consumer-owned `<lr-flag>`; no flag package is imported automatically).
1307
1612
 
1308
- **CSS parts:** `form-control`, `form-control-label`, `input-wrapper`, `country-prefix`,
1309
- `country-select`, `calling-code`, `input`, `hint`, `error`.
1613
+ **CSS parts:** `form-control`, `form-control-label`, `input-wrapper`, `country-prefix`, `country`
1614
+ (the selector region: invisible native select layered over the visual trigger), `country-select`,
1615
+ `country-trigger` (visible, `aria-hidden` closed-state box), `flag` (the `<lr-flag>`, only with
1616
+ `flags`), `country-code` (selected alpha-2 code, `data-placeholder` when no country exists),
1617
+ `expand-icon`, `calling-code`, `input`, `hint`, `error`.
1310
1618
 
1311
1619
  **Themeable custom properties:** shared tokens only. The phone-number input and calling code are
1312
1620
  deliberately `dir="ltr"`/isolated because telephone numbers are algorithmic content; surrounding
@@ -1336,6 +1644,15 @@ phone.adapter = await loadLibphonenumberAdapter(() => import('libphonenumber-js/
1336
1644
  ></lr-phone-input>
1337
1645
  ```
1338
1646
 
1647
+ ```ts
1648
+ // Country flags in the trigger (optional): same peer contract as a standalone <lr-flag>.
1649
+ import '@aceshooting/lyra-ui/components/media/flag/flag-peer.js';
1650
+ ```
1651
+
1652
+ ```html
1653
+ <lr-phone-input label="Mobile number" flags default-country="LU"></lr-phone-input>
1654
+ ```
1655
+
1339
1656
  **Known gotchas:**
1340
1657
 
1341
1658
  - An adapter's `parse()` method is synchronous because it runs on every keystroke. Load any optional
@@ -1345,8 +1662,15 @@ phone.adapter = await loadLibphonenumberAdapter(() => import('libphonenumber-js/
1345
1662
  as invalid instead of entering form submission.
1346
1663
  - Country names use `Intl.DisplayNames` and fall back to the ISO code; set `PhoneCountry.label` for
1347
1664
  a product-specific name. Calling codes are data, not derived by the component.
1348
- - The component does not import `@aceshooting/lyra-flags`. Compose an optional flag through
1349
- `country-prefix` and keep it decorative when the adjacent select already announces the country.
1665
+ - The component never imports `@aceshooting/lyra-flags` itself, with `flags` or without. `flags`
1666
+ lazily registers only the `<lr-flag>` element; the artwork resolver comes from the consumer's own
1667
+ `flag-peer.js` import (plus the installed peer package), so forgetting either shows a flagless
1668
+ trigger rather than erroring. `country-prefix` remains available for a fully consumer-owned
1669
+ adornment instead.
1670
+ - The visible trigger (`country-trigger` and everything inside it) is `aria-hidden` by design; the
1671
+ layered native select is the accessible control. Don't move interactive content into those parts
1672
+ via `::part` styling tricks, and don't expect the flag inside the open popup list — a native
1673
+ `<option>` is text-only.
1350
1674
 
1351
1675
  ---
1352
1676
 
@@ -1381,11 +1705,27 @@ key-up-commit, or when a preset button is clicked, `detail: { start, end }`)
1381
1705
 
1382
1706
  **CSS parts:** `base`, `track`, `range`, `handle-start`, `handle-end`, `presets`, `preset-button`
1383
1707
 
1384
- **Themeable custom properties:** shared tokens only — `--lr-color-border`, `--lr-color-brand`,
1708
+ **Themeable custom properties:** mostly shared tokens — `--lr-color-border`, `--lr-color-brand`,
1385
1709
  `--lr-color-surface`, `--lr-shadow` (track/handles), `--lr-opacity-disabled` (`:host([disabled])`
1386
1710
  dimming), plus (for `presets`) `--lr-color-text`, `--lr-color-on-brand` (the active preset
1387
1711
  button's text), `--lr-radius`, `--lr-space-xs/-s`, `--lr-transition-fast`,
1388
- `--lr-focus-ring-*`. No component-local tokens.
1712
+ `--lr-focus-ring-*`.
1713
+
1714
+ Three component-local properties recolor the **active** preset button independently of the shared
1715
+ palette: `--lr-time-range-preset-active-bg` (falls back to `--lr-color-brand`),
1716
+ `--lr-time-range-preset-active-border-color` (falls back to `--lr-color-brand`), and
1717
+ `--lr-time-range-preset-active-color` (falls back to `--lr-color-on-brand`). Unset, each resolves
1718
+ to exactly the token the rule used before they existed, so the default rendering is unchanged.
1719
+
1720
+ They exist because the active preset is marked with an attribute on a part, and
1721
+ `::part(preset-button)[data-active]` is **invalid CSS** — an attribute selector cannot follow
1722
+ `::part()`. Without these, recoloring just the active preset meant hijacking the shared
1723
+ `--lr-color-brand`/`--lr-color-on-brand` tokens and repainting everything else that reads them.
1724
+
1725
+ They are written as **inline `var()` fallbacks at the point of use, never declared on `:host`** —
1726
+ deliberately, because a `:host` declaration would shadow any value an ancestor set. Setting one on
1727
+ any ancestor of the `<lr-time-range>` therefore reaches it. (The same technique is used for
1728
+ `lr-emoji-picker`'s `--lr-emoji-picker-active-bg`.)
1389
1729
 
1390
1730
  **Optional peer deps:** none.
1391
1731
 
@@ -1541,10 +1881,37 @@ host so the control still has an accessible name.
1541
1881
  showing the checkmark/indeterminate dash), `checkmark` (the checkmark or indeterminate-dash glyph),
1542
1882
  `label` (wrapper around the default slot)
1543
1883
 
1544
- **Themeable custom properties:** shared tokens only `--lr-space-s`, `--lr-icon-button-size`,
1884
+ **Themeable custom properties:** `--lr-checkbox-label-indent` (below), plus shared tokens —
1885
+ `--lr-space-s`, `--lr-icon-button-size`,
1545
1886
  `--lr-color-border/-surface/-on-brand/-brand/-text/-danger`, `--lr-radius`,
1546
1887
  `--lr-transition-fast`, `--lr-focus-ring-width/-color/-offset`, `--lr-opacity-disabled`.
1547
1888
 
1889
+ **`--lr-checkbox-label-indent`** — the inline distance from the control's start edge to the start of
1890
+ the label text: the box's own floor plus the gap beside it. It defaults to
1891
+ `calc(min(var(--lr-icon-button-size), 1.75rem) + var(--lr-space-s))`, and the rendered gap is
1892
+ *derived* from it, so the advertised value and the real label offset cannot drift. Setting it on
1893
+ the element (or on `lr-checkbox` in your own stylesheet) moves the label.
1894
+
1895
+ It is published so you can align your own per-option hint text under the label without re-deriving
1896
+ that formula by reading the shadow styles. **But custom properties inherit down, not sideways**, so
1897
+ a *sibling* node in your tree cannot read it off the checkbox. Align a sibling by computing the
1898
+ same formula from the `--lr-theme-*` inputs you control:
1899
+
1900
+ ```css
1901
+ .checkbox-hint {
1902
+ padding-inline-start: calc(
1903
+ min(var(--lr-theme-icon-button-size, 2.5rem), 1.75rem) + var(--lr-theme-space-s, 0.5rem)
1904
+ );
1905
+ }
1906
+ ```
1907
+
1908
+ `--lr-checkbox-checked-bg` (default `var(--lr-color-brand)`) and `--lr-checkbox-checked-border`
1909
+ (default `var(--lr-color-brand)`) recolor `[part='box']`'s background/border while `checked` or
1910
+ `indeterminate` — a component-scoped indirection (the same pattern `lr-source-picker`'s own
1911
+ `--lr-source-picker-checked-bg`/`-border` pair uses) so a consumer can retint just this control's
1912
+ checked/indeterminate fill without hijacking the shared `--lr-color-brand` token everything else
1913
+ reads.
1914
+
1548
1915
  **Optional peer deps:** none.
1549
1916
 
1550
1917
  ```html
@@ -1736,8 +2103,8 @@ A form-associated single-choice control. Use it alone or inside `lr-radio-group`
1736
2103
 
1737
2104
  **Properties:** `checked`, `disabled`, `required`, `name`, and `value` (all reflected where
1738
2105
  applicable). A selected radio submits its value through `ElementInternals`.
1739
- `effectiveRequired` exposes the required state inherited from a containing radio group. `focus()`
1740
- and `blur()` forward to the internal radio control.
2106
+ `effectiveRequired` exposes the required state inherited from a containing radio group. `focus()`,
2107
+ `blur()`, and `click()` forward to the internal radio control.
1741
2108
 
1742
2109
  **Events:** native-style composed `input` and `change`, plus `lr-change` with
1743
2110
  `{ checked, value }`.
@@ -1746,6 +2113,14 @@ and `blur()` forward to the internal radio control.
1746
2113
 
1747
2114
  **CSS parts:** `base`, `circle`, `dot`, `label`.
1748
2115
 
2116
+ **Themeable custom properties:** `--lr-radio-label-indent` — the inline distance from the control's
2117
+ start edge to the start of the label text, i.e. the circle's own floor plus the gap beside it,
2118
+ defaulting to `calc(min(var(--lr-icon-button-size), 1.75rem) + var(--lr-space-s))`. The rendered
2119
+ gap is derived from it, so the advertised value and the real offset cannot drift; setting it on the
2120
+ element (or on `lr-radio` in your own stylesheet) moves the label. Exactly the same knob, defaults,
2121
+ purpose, and sideways-inheritance caveat as `--lr-checkbox-label-indent` — see `lr-checkbox` above
2122
+ for the formula to align a sibling hint element.
2123
+
1749
2124
  ```html
1750
2125
  <lr-radio name="format" value="json">JSON</lr-radio>
1751
2126
  ```
@@ -1774,6 +2149,23 @@ selected value is submitted under `name` and `required` requires at least one se
1774
2149
  **Events:** `input`, `change`, and `lr-change` with `{ value: string[] }`.
1775
2150
  **CSS parts:** `form-control`, `form-control-label`, `options`, `hint`, `error`.
1776
2151
 
2152
+ **`value` is a read-out of child state, not an input.** The children are the single source of
2153
+ truth. An internal sync recomputes `value` from them and reassigns it on every child toggle,
2154
+ `slotchange`, `name`/`required` change, blur, and `form.reset()` — so a host assignment is
2155
+ silently overwritten by the next of those. `connectedCallback()` runs that sync **before the first
2156
+ render**, which means even a constructor-time or template-time `.value=${…}` binding is discarded
2157
+ before anything can observe it. Assigning `value` logs a `console.warn` naming the property (once
2158
+ per group instance).
2159
+
2160
+ - **To preselect**, set `checked` on the children: `<lr-checkbox value="a" checked>`.
2161
+ - **To read the selection**, use this property or the `lr-change` event detail.
2162
+ - **Give every child a distinct `value`.** `<lr-checkbox>`'s `value` defaults to `'on'`, so a group
2163
+ of undifferentiated children submits several identical `FormData` entries and the submitted data
2164
+ cannot say which one was checked. The group warns once per duplicated value when it sees this.
2165
+ - Making `value` authoritative is deliberately not implemented, for the same reason: a host
2166
+ assigning `['on']` would check every child that kept the default. A distinct `defaultValue` API
2167
+ could be added later without reversing any of the above.
2168
+
1777
2169
  ## `lr-token-input`
1778
2170
 
1779
2171
  An editable form-associated token list. Enter, comma, or blur commits a token; Backspace removes
@@ -1781,18 +2173,45 @@ the last token. `value` is a `string[]` and repeated values are submitted under
1781
2173
 
1782
2174
  **Properties:** `value`, `label`, `hint`, `errorText` (`error-text`), `placeholder`, `name`,
1783
2175
  `required`, `disabled`, `accessibleLabel` (attribute `aria-label` — forwarded to the internal text
1784
- input), `allowDuplicates` (`allow-duplicates`, default `false`), and `delimiter` (default `','`).
2176
+ input), `allowDuplicates` (`allow-duplicates`, default `false`), `editable` (reflected, default
2177
+ `false` — see below), and `delimiter: string | null` (default `','` — see below).
1785
2178
  **Slots:** `label`, `hint`, `error`.
1786
- **Events:** `input`, `change`, `lr-add` (`detail: { value }`), and `lr-remove`
1787
- (`detail: { value, index }`).
1788
- **CSS parts:** `form-control`, `form-control-label`, `input-wrapper`, `token`, `remove` (the
2179
+ **Events:** `input`, `change`, `lr-add` (`detail: { value }`), `lr-remove`
2180
+ (`detail: { value, index }`), and `lr-token-edit`
2181
+ (`detail: { value, previousValue, index }` — an existing token was edited in place and committed).
2182
+ **CSS parts:** `form-control`, `form-control-label`, `input-wrapper`, `token`, `token-label` (the
2183
+ token's text, doubling as the roving-focus edit trigger — rendered only while `editable`),
2184
+ `token-editor` (the inline text field that replaces a token's text while it is open for editing —
2185
+ rendered only while `editable` and only for the token being edited), `remove` (the
1789
2186
  per-token remove button, floored at the shared `--lr-icon-button-size` tap size around a compact
1790
2187
  glyph), `input`, `hint`, `error`. `focus()` and `blur()` forward to the internal text input.
1791
2188
 
2189
+ **`editable` — editing a token in place.** Off by default, in which case the token row renders
2190
+ exactly as it does without the feature and stays non-focusable. Turn it on and each token becomes a
2191
+ roving tab stop (one Tab stop for the whole row): click, Enter, Space, or F2 opens an inline
2192
+ editor on that token; ArrowLeft/ArrowRight move between tokens (swapped under RTL, since they mean
2193
+ previous/next *visually*), Home/End jump to the first/last. Inside the editor, Enter commits and
2194
+ returns focus to the token, Escape cancels (and is consumed rather than left to bubble, so an
2195
+ enclosing dialog or popover does not also close), and blurring commits *without* pulling focus
2196
+ back — a blur means the user already aimed focus elsewhere. `lr-token-edit` fires only for an edit
2197
+ that actually changed something: a reverted, unchanged, emptied, or (under the default
2198
+ `allowDuplicates = false`) duplicate-colliding edit is discarded silently, mirroring how a
2199
+ duplicate draft is skipped rather than rejecting the whole entry.
2200
+
2201
+ **`delimiter` is nullable, and only a single character acts as a commit key.** It does two separate
2202
+ jobs: it splits a committed draft into several tokens, and — *only when it is exactly one
2203
+ character* — it is the keystroke that commits the draft. A multi-character delimiter still splits a
2204
+ pasted or committed draft, but no keystroke can ever match it, so nothing commits on typing.
2205
+ Setting it to `null` disables both, so a token may contain the delimiter verbatim. **`delimiter="null"`
2206
+ does not work** — that is the four-character string `null`. Use `delimiter="none"`, `delimiter=""`
2207
+ (both of which the attribute converter maps to `null`), or a property binding
2208
+ (`.delimiter=${null}`). Removing the attribute restores the `,` default.
2209
+
1792
2210
  **Themeable custom properties:** `--lr-token-input-input-inline-size` (the editable input's
1793
2211
  `flex-basis` inside the wrapped token row; undeclared by default, falling back inline to
1794
- `--lr-size-8rem`) and `--lr-token-input-min-input-inline-size` (default `--lr-size-4rem`, the floor
1795
- that input keeps once tokens have consumed the row).
2212
+ `--lr-size-8rem`), `--lr-token-input-min-input-inline-size` (default `--lr-size-4rem`, the floor
2213
+ that input keeps once tokens have consumed the row), and `--lr-token-input-editor-inline-size`
2214
+ (default `--lr-size-6rem`, the inline size of the inline token editor opened by `editable`).
1796
2215
 
1797
2216
  ## `lr-code-editor`
1798
2217
 
@@ -1875,13 +2294,23 @@ supplied (an explicit empty array still counts as supplied and skips the auto-lo
1875
2294
  When the filtered set reaches 200 items, the grid automatically windows its visible rows while
1876
2295
  preserving the full option count through `aria-setsize`/`aria-posinset`.
1877
2296
 
2297
+ Ships the same opt-in `label`/`hint`/`errorText` form-control chrome as `lr-select`/
2298
+ `lr-color-picker` (props + matching named slots + `form-control`/`form-control-label`/`hint`/
2299
+ `error` CSS parts) — left unset, none of that chrome renders.
2300
+
1878
2301
  **Properties:** the shared form properties `name`, `value`, `disabled`, and `required`, plus
1879
2302
  `groups: EmojiPickerGroup[] = []` (attribute: false) — `EmojiPickerGroup { key, label, emojis:
1880
2303
  EmojiPickerItem[] }`, `EmojiPickerItem { emoji, name, shortcodes? }`; the search field matches `name`
1881
2304
  and every `shortcodes` entry, case-insensitively. Empty (the default, before the auto-loader
1882
2305
  resolves) renders just the search input and the empty state. `accessibleLabel` (`aria-label`)
1883
2306
  forwards a host-supplied accessible name to the internal `role="listbox"` grid; empty falls back to
1884
- the localized default grid label.
2307
+ the localized default grid label. `label: string = ''` — visible label rendered above the
2308
+ search/grid; unset renders no label chrome. When `label` (or the `label` slot) is set and
2309
+ `accessibleLabel`/a host `aria-label` is not, the grid's accessible name switches from the
2310
+ localized default to `aria-labelledby` pointing at the visible label. `hint: string = ''` —
2311
+ supporting text rendered below the search/grid; unset renders no hint chrome. `errorText: string =
2312
+ ''` (attribute `error-text`) — validation-error text rendered below the hint (overridden by slotted
2313
+ `error` content when provided); unset renders no error chrome.
1885
2314
 
1886
2315
  **Events:** `lr-change` with `detail: { emoji }` (an emoji was picked — click, or Enter/Space on
1887
2316
  the active grid cell; also sets `value`), plus the shared form `input`, `change`, `focus`, and `blur`.
@@ -1894,9 +2323,14 @@ Home/End jump to the first/last item, and Enter/Space picks the active item. The
1894
2323
  the input, with `aria-activedescendant` tracking the active option. Hovering an emoji with the
1895
2324
  pointer also moves the active item to it.
1896
2325
 
1897
- **CSS parts:** `base`, `search` (`role="combobox"`), `grid` (`role="listbox"`, the scroll
1898
- viewport), `group-label`, `emoji` (each emoji's own `role="option"` button), `empty` (shown when
1899
- the search matches nothing). While windowing is active the rows are wrapped in `virtual-spacer`
2326
+ **Slots:** `label` (custom label content), `hint` (custom hint content), `error` (custom error
2327
+ content, overrides the `errorText` attribute when provided).
2328
+
2329
+ **CSS parts:** `form-control` (the outer wrapper around label, `base`, error and hint),
2330
+ `form-control-label` (the visible label), `base`, `search` (`role="combobox"`), `grid`
2331
+ (`role="listbox"`, the scroll viewport), `group-label`, `emoji` (each emoji's own `role="option"`
2332
+ button), `empty` (shown when the search matches nothing), `hint` (the hint message), `error` (the
2333
+ error message). While windowing is active the rows are wrapped in `virtual-spacer`
1900
2334
  (full-height scroll spacer), `virtual-row` (one absolutely-positioned row), `virtual-label` (an
1901
2335
  `aria-hidden` spacer standing in for a row's missing `group-label`), and `virtual-items` (the row's
1902
2336
  emoji flex line).
@@ -1913,6 +2347,15 @@ and re-derived only when the resolved pixels can actually change (a token overri
1913
2347
  first render, a theme swap, a root or host font-size change feeding a `rem`/`em` value), never per
1914
2348
  frame.
1915
2349
 
2350
+ `--lr-emoji-picker-active-bg` recolors the highlight behind the active/hovered emoji, falling back
2351
+ to `--lr-color-brand-quiet` when unset — so the default rendering is unchanged. Hover and
2352
+ keyboard-active deliberately share one declaration, so this single hook retints both consistently.
2353
+ It exists because `::part(emoji)[data-active]` is **invalid CSS** (an attribute selector cannot
2354
+ follow `::part()`), which previously left hijacking the shared `--lr-color-brand-quiet` token — and
2355
+ repainting everything else that reads it — as the only way in. Like `lr-time-range`'s preset
2356
+ properties, it is written as an inline `var()` fallback at the point of use rather than declared on
2357
+ `:host`, so a value set on **any ancestor** reaches it instead of being shadowed.
2358
+
1916
2359
  Two constraints remain. `--lr-emoji-picker-item-size` is clamped up to `--lr-icon-button-size`, the
1917
2360
  shared minimum tappable box: a smaller value does not shrink the button, and the windowed geometry
1918
2361
  follows the clamped, painted size. And windowed rows are absolutely positioned at the row-height
@@ -1951,6 +2394,11 @@ message), `footer`, `submit`, `skip` (only rendered when `skippable`), `empty` (
1951
2394
  no entries), and `unsupported` (the fallback note for a key whose `type` is outside the three
1952
2395
  supported ones).
1953
2396
 
2397
+ **Themeable custom properties:** shared tokens only. The footer's disabled `submit`/`skip` buttons
2398
+ dim through `--lr-opacity-disabled`, the same library-wide token every other disabled control
2399
+ reads — so retuning `--lr-theme-opacity-disabled` keeps this form's disabled state consistent with
2400
+ the rest of the UI instead of needing a `::part()` rule here.
2401
+
1954
2402
  # Data display, dashboards & flow canvas (`components/data/`)
1955
2403
 
1956
2404
  ## `lr-sparkline`
@@ -2040,6 +2488,19 @@ KPI/stat card — value + unit + label + optional icon/trend/caption.
2040
2488
  hides `[part="unit"]`, for rendering a loading/status message in place of a numeric value
2041
2489
  - `compact: boolean = false` (reflected) — tighter card padding; same convention as `lr-empty`'s and
2042
2490
  `lr-widget`'s `compact`
2491
+ - `appearance: 'card'|'plain' = 'card'` (reflected) — visual chrome, mirroring `lr-card`'s
2492
+ `appearance` vocabulary. `'card'` keeps the bordered, filled, padded box that stretches to fill its
2493
+ parent; `'plain'` removes the border, background, padding, corner radius **and** the
2494
+ `block-size: 100%` stretch, so the stat can sit inline in prose, a toolbar, or a table cell.
2495
+ `plain` wins over `compact` when both are set (there is no padding left to tighten), and it drops
2496
+ `emphasis`'s accent edge — that edge is card chrome — while `emphasis`'s brand value tint still
2497
+ applies. A `plain` stat with a safe `href` swaps the card's border-color/lift hover affordance
2498
+ (invisible with no border) for an underline on `[part="value"]`; the `:focus-visible` ring is
2499
+ unchanged
2500
+ - `orientation: 'vertical'|'horizontal' = 'vertical'` (reflected) — layout axis. `'vertical'` stacks
2501
+ label, value, trend, sub and caption. `'horizontal'` lays label, value+unit, trend, sub and caption
2502
+ out on a single wrapping baseline row; `[part="spark"]` and `[part="rows"]` have no sensible place
2503
+ on a text baseline and stay stacked on their own full-width line beneath that row
2043
2504
 
2044
2505
  **Events:** none.
2045
2506
 
@@ -2049,15 +2510,24 @@ slot="spark">`, or other compact trend visual — `lr-stat` only reserves the sl
2049
2510
  render one itself), `sub` (rich sub-line content — overrides the `sub` attribute when slotted content
2050
2511
  is provided)
2051
2512
 
2052
- **CSS parts:** `base` (a `<div>`, or an `<a>` for a safe `href`), `icon`, `label`, `value-row`, `value`, `unit`, `trend`, `sub`, `spark`,
2513
+ **CSS parts:** `base` (a `<div>`, or an `<a>` for a safe `href`), `icon`, `label` (carries `hidden`,
2514
+ and is collapsed, whenever `label` is empty — a label-less stat leaves no blank line above the
2515
+ value), `value-row`, `value`, `unit`, `trend`, `sub`, `spark`,
2053
2516
  `caption`, `rows`, `row`, `row-label`, `row-value` — `[part="value"]` gets `aria-labelledby` pairing
2054
2517
  it with `[part="label"]`'s generated id whenever `label` is non-empty (so tabbing straight to the
2055
2518
  `exactValue`-focusable value still announces e.g. "Revenue $1.2K", not just the bare value); each
2056
2519
  `[part="row-value"]` is paired the same way with its own row's `[part="row-label"]`.
2057
2520
 
2058
- **Themeable custom properties:** shared tokens only (`--lr-color-success/-warning/-danger` drive
2059
- the `variant`-colored value text and up/down trend pill; `--lr-color-brand` drives `emphasis`'s
2060
- accent edge and value tint).
2521
+ **Themeable custom properties:** `--lr-stat-trend-good-color` (default `var(--lr-color-success)`)
2522
+ and `--lr-stat-trend-good-bg` (default `color-mix(in srgb, var(--lr-color-success) 8%,
2523
+ transparent)`) text/background of `[part="trend"]` when its polarity (per `goodDirection`) is
2524
+ "good"; `--lr-stat-trend-bad-color` (default `var(--lr-color-danger)`) and `--lr-stat-trend-bad-bg`
2525
+ (default `color-mix(in srgb, var(--lr-color-danger) 8%, transparent)`) — the "bad"-polarity
2526
+ counterparts. All four are independent of the headline value's `variant="success"`/`"danger"` tint,
2527
+ which keeps reading the shared `--lr-color-success`/`--lr-color-danger` tokens directly — retinting
2528
+ the trend pill doesn't also recolor the value, and vice versa. Otherwise shared tokens only
2529
+ (`--lr-color-success/-warning/-danger` drive the `variant`-colored value text; `--lr-color-brand`
2530
+ drives `emphasis`'s accent edge and value tint).
2061
2531
 
2062
2532
  **Optional peer deps:** none.
2063
2533
 
@@ -2111,13 +2581,42 @@ own "consumer computes/renders" contract rather than assuming addition.
2111
2581
  via the retheme-able `--lr-table-heat-tint-lo`/`-hi` custom properties, matching `lr-heatmap`'s
2112
2582
  own ramp-token convention; `cellStyle` is applied directly to the generated `<td>` via `styleMap` — e.g. a computed heat-tint
2113
2583
  background a `cell()`-returned inner element can't paint into the cell's own padding — omit it for
2114
- no per-cell style override (the default, unchanged output); `editable` enables double-click
2115
- editing, `editValue` supplies the editor value, and `editType` selects `text` or `number`
2584
+ no per-cell style override (the default, unchanged output); `editable` enables inline editing —
2585
+ `true` opens a native editor on that cell's double-click (one cell at a time), `'always'` instead
2586
+ renders a persistent editor in every body cell of the column from first paint, for a
2587
+ settings/rate-style column meant to be typed straight into — while `editValue` supplies the editor
2588
+ value and `editType` selects `text` or `number`
2589
+ `cellTitle(row) => string | undefined` is the `title` analogue of `cellStyle`, applied directly to
2590
+ the generated `<td>` — e.g. the untruncated text behind an ellipsized cell, or a formatted
2591
+ timestamp behind a relative one;
2116
2592
  `resizable` adds a focusable separator `[part='resize-handle']` and emits `lr-column-resize` with
2117
2593
  the live width in CSS pixels. Drag it, or use logical ArrowLeft/ArrowRight for 10px steps (mirrored
2118
2594
  under RTL), Shift+Arrow for 50px steps, Home for the minimum, and End for an explicit pixel
2119
2595
  `maxWidth`; explicit pixel `minWidth`/`maxWidth` values bound both input paths. The separator
2120
2596
  exposes its current/minimum/bounded-maximum pixel width through ARIA value attributes.
2597
+ - `columns[].editable: boolean | 'always'` — a widening of the original `boolean`, non-breaking.
2598
+ `true` is unchanged: double-click a cell to open its editor, one at a time, Enter commits and
2599
+ closes, Escape cancels and closes, blur-after-change commits. `'always'` renders an editor in
2600
+ every body cell of that column, permanently:
2601
+ - **Focus model.** Each editor is a plain tab stop — no `tabindex` of its own — exactly like the
2602
+ existing row-expand toggle, and stays *outside* the header/row roving-tabindex model. Tab walks
2603
+ down the column; arrow keys still navigate the grid from a row's own roving stop, and act as
2604
+ ordinary caret movement once focus is inside a field. Non-editable columns are unaffected.
2605
+ - **Value binding.** A persistent editor binds its `value` as a **content attribute**, not as the
2606
+ `.value` property, so native dirty-value-flag semantics apply. Trade-off: once the user has
2607
+ typed into a cell, an out-of-band `rows` update to that same cell will **not** visibly replace
2608
+ their draft. An editor the user has not touched still picks up a new `rows` value normally.
2609
+ `lr-cell-edit` remains the only mutation channel — the table never mutates `row`.
2610
+ - **Keys.** Enter commits (emits `lr-cell-edit`) and *keeps focus* in the field, since there is no
2611
+ closed state to fall back to. `change` (blur after a modification) commits, as with `true`.
2612
+ Escape is **not** cancelled and does nothing to the editor — there is nothing to cancel back to
2613
+ — so an ancestor dialog/popover still acts on it.
2614
+ - **Focus across re-sorts and pagination.** Rows are keyed, so a re-sort *moves* the editor's
2615
+ `<input>` (the typed value rides along) and the table restores focus to the same logical cell
2616
+ afterwards. If the focused row leaves the rendered page entirely (pagination, filtering), focus
2617
+ is simply lost rather than yanked to whichever unrelated row now sits in that position.
2618
+ - Each editor keeps its own interpolated `tableEditCell` accessible name (`Edit {column}`), so a
2619
+ column of otherwise-identical inputs is still individually named to a screen reader.
2121
2620
  - `columnsHidden: boolean = false` (attribute `columns-hidden`, reflected) — computed/read-only: true
2122
2621
  when a `priority` column is *actually* hidden right now by the `@container` breakpoints above, or
2123
2622
  `showAllColumns` force-visible mode is currently active. Measured via a `ResizeObserver` on
@@ -2128,6 +2627,13 @@ own "consumer computes/renders" contract rather than assuming addition.
2128
2627
  renders exactly when `columnsHidden` is true — no longer whenever any column merely *declares* a
2129
2628
  `priority` regardless of whether anything is actually hidden
2130
2629
  - `rows: T[] = []` (attribute: false)
2630
+ - `layout: 'auto'|'fixed' = 'auto'` (reflected) — a **floor** on the `<table>`'s `table-layout`, not
2631
+ an override. `'fixed'` forces the fixed algorithm even when no column declares a `width`, so every
2632
+ column shares the available width evenly and long cell content is clipped/wrapped instead of
2633
+ stretching its column. The default `'auto'` still *resolves* to `fixed` whenever a column declares
2634
+ a `width`, a column has been drag-resized, or a resize gesture is in flight — column resizing does
2635
+ not work under `table-layout: auto`, so `'auto'` can never mean "never fixed". See the gotchas for
2636
+ the two consequences of the fixed algorithm worth knowing before opting in
2131
2637
  - `sortKey: string = ''` (attribute `sort-key`)
2132
2638
  - `sortDir: 'asc'|'desc' = 'asc'` (attribute `sort-dir`)
2133
2639
  - `rowKey?: (row: T) => string | number` (attribute: false) — derives each row's stable identity for
@@ -2153,7 +2659,20 @@ own "consumer computes/renders" contract rather than assuming addition.
2153
2659
  converter would otherwise treat any attribute value, including the literal string `"false"`, as
2154
2660
  `true`).
2155
2661
  - `loading: boolean = false` (attribute `loading`, reflected) and `loadingLabel: string = ''`
2156
- (attribute `loading-label`) — renders a busy spinner and suppresses the grid while loading
2662
+ (attribute `loading-label`) — renders busy chrome and suppresses the real rows while loading
2663
+ - `loadingAppearance: 'spinner'|'skeleton' = 'spinner'` (attribute `loading-appearance`, reflected) —
2664
+ how `loading` renders. `'spinner'` replaces the whole grid with an indeterminate spinner.
2665
+ `'skeleton'` instead renders the real table — the same `<colgroup>` (declared *and* drag-resized
2666
+ widths included), the same `<thead>`, the filter field and the pagination footer — and fills
2667
+ `<tbody>` with placeholder rows, so a cold load sketches the grid's shape rather than collapsing to
2668
+ a spinner and reflowing when the rows land. Kept as a separate property rather than widening
2669
+ `loading` to a string union, so `?loading=${…}` bindings and `el.loading === true` checks keep
2670
+ working
2671
+ - `skeletonRows: number = 0` (attribute `skeleton-rows`) — placeholder row count under
2672
+ `loadingAppearance="skeleton"`. `0` derives the count instead: the normalized `pageSize` when
2673
+ pagination is on (capped at 20, so a large page size can't emit thousands of placeholder cells),
2674
+ otherwise 3. Any positive value is used verbatim and is *not* capped. Ignored entirely under the
2675
+ default spinner appearance
2157
2676
  - `pageSize: number = 0` (attribute `page-size`) — positive values enable controlled pagination;
2158
2677
  zero disables the pagination footer
2159
2678
  - `page: number = 1` (attribute `page`, reflected) — controlled current page
@@ -2177,6 +2696,13 @@ own "consumer computes/renders" contract rather than assuming addition.
2177
2696
  - `emptyDescription: string = ''` (attribute `empty-description`)
2178
2697
  - `noColumnsHeading: string = 'No columns configured'` (attribute `no-columns-heading`)
2179
2698
  - `noColumnsDescription: string = ''` (attribute `no-columns-description`)
2699
+ - `emptyCompact?: boolean` (attribute `empty-compact`) — overrides the built-in `[part='empty']`
2700
+ state's `compact` rendering. Tri-state: leave it `undefined` (the default) to keep each empty
2701
+ branch's own built-in default — the two shadow-root-level branches (no columns, no rows) render
2702
+ spacious, while the filtered-to-zero branch, which sits inside `[part='base']` alongside the filter
2703
+ field, renders compact. `empty-compact="false"` forces the spacious rendering everywhere, and is
2704
+ parsed as `false` rather than as mere attribute presence. Has no effect once the `empty` slot is
2705
+ filled
2180
2706
  - `revealColumnsLabel: string = 'Show all columns'` (attribute `reveal-columns-label` — the
2181
2707
  reveal-button's label while `priority`-hidden columns are hidden)
2182
2708
  - `hideColumnsLabel: string = 'Show fewer columns'` (attribute `hide-columns-label` — the same
@@ -2209,7 +2735,12 @@ columns, and `lr-column-resize` (`detail: { key, width }`) on every pointer or k
2209
2735
  The internal filter/cell-editor native inputs' `focus` and `blur` are also re-dispatched from the
2210
2736
  host as bubbling, composed events (the native ones are neither).
2211
2737
 
2212
- **Slots:** nonecontent comes entirely from `columns`/`rows`.
2738
+ **Slots:** `empty`replaces the built-in empty state on the two *data*-empty branches (no rows at
2739
+ all, and filtered/paginated down to zero). Left unfilled, the built-in `[part='empty']` `<lr-empty>`
2740
+ renders as this slot's fallback content. The no-columns branch is deliberately **not**
2741
+ slot-replaceable: it reports a configuration problem (`noColumnsHeading`), not "this query returned
2742
+ nothing", and one slot covering all three would collapse that distinction. Everything else comes
2743
+ from `columns`/`rows`.
2213
2744
 
2214
2745
  **CSS parts:** `base`, `table`, `head`, `header-cell`, `row`, `cell`, `more-button`, `sort-icon` (a
2215
2746
  chevron indicator shown on the active sortable header, rotated per `sortDir`), `reveal-columns-button`
@@ -2218,9 +2749,20 @@ column defines `footer`), `footer-row`, `footer-cell`, `row-total-cell` (each bo
2218
2749
  `<td>` holding `rowTotal(row)`, rendered only when `rowTotal` is set — the corresponding footer-row
2219
2750
  cell, holding `grandTotal`, is a `footer-cell` instead, matching every other footer cell),
2220
2751
  `expand-toggle-cell`, `row-expand-toggle`,
2221
- `row-expand-icon`, `expanded-row`, `expanded-cell`, `filter-label`, `filter`, `loading`, and
2752
+ `row-expand-icon`, `expanded-row`, `expanded-cell`, `filter-label`, `filter`, `loading` (under
2753
+ `loadingAppearance="spinner"` the visible block holding the spinner; under `"skeleton"` the
2754
+ visually-hidden `role="status"` node, since the placeholder rows are the visible affordance),
2755
+ `skeleton` (each `<lr-skeleton>` placeholder inside a skeleton-mode body cell — the placeholder rows
2756
+ and cells reuse the ordinary `row`/`cell`/`row-total-cell` parts, which is exactly what keeps them
2757
+ geometrically identical to real rows, so `skeleton` is the part to target for the placeholder's own
2758
+ look: `::part(skeleton) { --lr-skeleton-h: 2em; }`), and
2222
2759
  `pagination`, `cell-editor`, `group-row`, `group-cell`, and `resize-handle` (the focusable column
2223
- separator)
2760
+ separator). The built-in empty state is addressable rather than fixed: `empty` is the `<lr-empty>`
2761
+ host in all three empty states, and it re-exports that element's own inner parts as `empty-base`,
2762
+ `empty-icon`, `empty-heading`, `empty-description` and `empty-actions`. Note that the no-columns and
2763
+ no-rows states return the empty element as the shadow root's own root, with no `[part='base']`
2764
+ wrapper around it — `::part(base)` does not apply in those two states, only in the filtered-to-zero
2765
+ one — and that `empty` disappears entirely once the `empty` slot is filled.
2224
2766
 
2225
2767
  **Themeable custom properties:** `--lr-table-max-height` (default `none`; controls the scrollable
2226
2768
  body's `max-block-size`). `--lr-table-heat-tint-lo` (default `var(--lr-color-brand-quiet)`) and
@@ -2228,6 +2770,16 @@ body's `max-block-size`). `--lr-table-heat-tint-lo` (default `var(--lr-color-bra
2228
2770
  for heat-tint mode's per-cell background, consulted only on columns/rows that define `heatValue`;
2229
2771
  `--lr-table-resize-min-width` (default `var(--lr-size-3rem)`) and
2230
2772
  `--lr-table-resize-handle-opacity` (default `0.12`) control resizable-column behavior.
2773
+ `--lr-table-row-selected-bg` (default `var(--lr-color-brand-quiet)`) — the background of a row whose
2774
+ `aria-selected` is `true`. Like every state-scoped custom property in this library it is an inline
2775
+ `var()` fallback at its point of use and is **not** declared on `:host`, so it can be set on the
2776
+ element *or on any ancestor* and still reach the rule that reads it. It exists because Shadow Parts
2777
+ forbids an attribute selector after `::part()` — `::part(row)[aria-selected='true']` is invalid CSS —
2778
+ so the only prior lever for restyling the selected row was overriding the library-wide
2779
+ `--lr-color-brand-quiet` token, which repaints everything else reading it.
2780
+ `--lr-table-sticky-offset` (default `0`) is measured and written inline per column by the component
2781
+ so multiple `sticky` columns stack instead of overlapping; it is a read-out, not a knob you set.
2782
+ `--lr-table-heat-t` is likewise component-written (each `[data-heat]` cell's position on the ramp).
2231
2783
 
2232
2784
  **Optional peer deps:** none.
2233
2785
 
@@ -2267,6 +2819,35 @@ for heat-tint mode's per-cell background, consulted only on columns/rows that de
2267
2819
  [role="slider"]`, **or any custom element** (any tag name containing a hyphen — e.g. a
2268
2820
  `<lr-select>`/`<lr-combobox>` rendered inside a `cell()`), are left alone by the table's own
2269
2821
  delegated `click`/`keydown` handlers instead of triggering `lr-sort`/`lr-row-click`.
2822
+ - `layout="fixed"` (and any `'auto'` that resolves to fixed) carries two consequences of the CSS
2823
+ fixed algorithm. With no declared widths the **first** row — the header row included — determines
2824
+ every column's width, so revealing a `priority`-hidden column via
2825
+ `[part='reveal-columns-button']` re-measures and changes *all* of them, not just the revealed one.
2826
+ And `columns[].minWidth`/`maxWidth` are silently ignored by `table-layout: fixed`; declare `width`
2827
+ instead when a specific column needs a specific size.
2828
+ - skeleton mode keeps geometry stable only when the browser isn't sizing columns from cell content.
2829
+ Under the default `table-layout: auto`, placeholder cells have no intrinsic width, so the columns
2830
+ re-measure when real content arrives — exactly as they do between any two different data sets. For
2831
+ pixel-identical widths across the load, declare `columns[].width` or set `layout="fixed"`. Either
2832
+ loading appearance keeps exactly one `role="status"` live region announcing the state: every
2833
+ placeholder opts out of `<lr-skeleton>`'s own announcement, so a skeleton table never announces
2834
+ once per placeholder row.
2835
+ - `columns[].cellTitle` returning an empty string **or** `undefined` omits the `title` attribute
2836
+ entirely rather than rendering `title=""` — an empty `title` would suppress an ancestor element's
2837
+ own tooltip. The attribute is also suppressed while that cell is in inline-edit mode, so the
2838
+ tooltip can't shadow the editor. Accessibility caveat: some screen readers announce a `<td title>`
2839
+ as the cell's accessible *name*, replacing the cell's content rather than supplementing it (the
2840
+ same caveat `lr-stat`'s `exactValue` carries). Use it for a longer form of what the cell already
2841
+ shows, never for information that exists nowhere else.
2842
+ - `editable: 'always'` deliberately does not re-assert a cell's source value once the user has typed
2843
+ into it. That is the native dirty-value-flag behavior the attribute binding buys, and it is the
2844
+ point: a background `rows` refresh cannot silently overwrite an in-progress edit. If you need the
2845
+ opposite — an authoritative external value that always wins — do not use `'always'`; re-key the
2846
+ row (`rowKey`) so the editor is recreated rather than updated, or keep `editable: true` and let
2847
+ the short-lived double-click editor's property binding re-assert. Also note the two things
2848
+ `'always'` intentionally does *not* do: it never sets the roving `tabindex` (its editors are
2849
+ ordinary tab stops, so Tab order in that column interleaves with the grid's two roving stops,
2850
+ the same way the row-expand toggle's already does), and it never cancels Escape.
2270
2851
 
2271
2852
  ---
2272
2853
 
@@ -2317,8 +2898,11 @@ The internal page input's `focus` and `blur` are also bridged as bubbling, compo
2317
2898
  `page-input`, `page-count`, `next-button`, `next-icon`, `live-region`.
2318
2899
 
2319
2900
  **Themeable custom properties:** `--lr-pagination-control-size` and
2320
- `--lr-pagination-font-size` (both default from `size`), plus shared color, spacing, border, radius,
2321
- disabled-opacity, and focus-ring tokens.
2901
+ `--lr-pagination-font-size` (both default from `size`), `--lr-pagination-control-padding` (default
2902
+ `var(--lr-space-xs)`) — inner padding of the previous/next buttons and the page input, deliberately
2903
+ uniform across every `size` tier because the control's outer footprint is already fixed by
2904
+ `--lr-pagination-control-size`, so this only adjusts the icon/digit inset — plus shared color,
2905
+ spacing, border, radius, disabled-opacity, and focus-ring tokens.
2322
2906
 
2323
2907
  **Optional peer deps:** none.
2324
2908
 
@@ -2530,6 +3114,16 @@ focus; it continues to emit `lr-cell-click` and leaves selection state consumer-
2530
3114
  measured `clientWidth` on every draw/resize instead of the fixed `cell-size`, so the grid actually
2531
3115
  fills the available width; now applies to calendar mode as well as matrix mode — see gotchas for
2532
3116
  the default, non-`fit-to-width` behavior)
3117
+ - `maxCellSize?: number` (attribute `max-cell-size`) — ceiling, in CSS px, on the cell size
3118
+ `fitToWidth` derives from the host width, in **both** modes. Exists because `fitToWidth` divides
3119
+ the *whole* host width across the grid, so a 5-week calendar or a 3-column matrix in a wide pane
3120
+ produces enormous blocks; capping them keeps a cell a cell
3121
+ - `minCellSize?: number` (attribute `min-cell-size`) — the mirror floor, in CSS px, so a year-long
3122
+ calendar in a narrow pane keeps legible, hit-testable cells and overflows its host instead of
3123
+ collapsing to hairlines. It can only *raise* the built-in `4`px floor, never lower it: a value
3124
+ below `4` normalizes to `4`. When both clamps are set and `maxCellSize < minCellSize`, the ceiling
3125
+ wins. For both: a non-finite value, or an empty attribute, means unset rather than `0`, and unset
3126
+ (the default) reproduces the unclamped fit-to-width behavior exactly
2533
3127
  - `valueLabel: string = 'value'` (attribute `value-label`)
2534
3128
  - `scale: 'linear' | 'sqrt' = 'linear'` — governs both modes: in matrix mode, `'sqrt'` compresses the
2535
3129
  color ramp via `sqrtStep()` instead of mapping linearly; in calendar mode, the default `'linear'`
@@ -2563,7 +3157,12 @@ focus; it continues to emit `lr-cell-click` and leaves selection state consumer-
2563
3157
  its low DOM footprint.
2564
3158
  - `cellText?: (pos: MatrixCellPos | CalendarCellPos, value: number) => string` (attribute: false) —
2565
3159
  formats the per-cell hover tooltip and keyboard live-region announcement text; receives the cell
2566
- position (`{ row, col }` in matrix mode, `{ week, weekday }` in calendar mode) and its value.
3160
+ position (`MatrixCellPos { row, col }` in matrix mode, `CalendarCellPos { week, weekday, date }` in
3161
+ calendar mode) and its value. `CalendarCellPos.date` is a **required** ISO `yyyy-mm-dd` string,
3162
+ present for every grid position — including a sparse gap position with no matching entry in `days`
3163
+ at all, which still sits on a real calendar day (that case simply reports the `-1` "no data" value
3164
+ alongside it). It lets a callback key off the date without re-deriving the grid's own
3165
+ anchor-week arithmetic; `MatrixCellPos` is unchanged, and so is `lr-cell-click`'s detail.
2567
3166
  Unset (the default) falls back to the built-in English "Row X, Col Y: value" (matrix) / "Jan 15:
2568
3167
  value" — short month + day, **not** a weekday abbreviation (calendar) — template. Additive, not
2569
3168
  breaking.
@@ -2610,10 +3209,14 @@ focus; it continues to emit `lr-cell-click` and leaves selection state consumer-
2610
3209
  interpolate continuously into `colorSteps.length` buckets instead. Unset (the default, or fewer
2611
3210
  than 2 entries) keeps today's 2-endpoint interpolation exactly.
2612
3211
  - `legendStops?: HeatmapLegendStop[]` (attribute: false) — `HeatmapLegendStop { value: number;
2613
- color: string; label?: string }`: a discrete legend key rendered **instead of** the
3212
+ color?: string; label?: string }`: a discrete legend key rendered **instead of** the
2614
3213
  `--lr-heatmap-scale-lo`/`-hi` gradient bar and its `[part="legend-lo"]`/`[part="legend-hi"]`
2615
3214
  endpoint labels — one `[part="legend-stop"]` per entry, in array order, each a
2616
3215
  `[part="legend-swatch"]` filled with that entry's `color` plus a `[part="legend-stop-label"]`.
3216
+ `color` is optional: omit it (or pass an empty string) for a **caption-only** stop, which renders
3217
+ its `[part="legend-stop-label"]` alone with no `[part="legend-swatch"]` element in the DOM at all —
3218
+ so a leading "0" or trailing "more" caption around a run of colored stops doesn't leave an empty
3219
+ swatch box in the row.
2617
3220
  A stop's label defaults to the component's own locale-aware numeric formatting of `value`, so an
2618
3221
  explicit `label` is only needed when the number isn't the right caption ("none", "≥ 90%"). Exists
2619
3222
  for the consumer who supplies `cellColor`: because that callback overrides a cell's color
@@ -2639,7 +3242,9 @@ button), `tooltip` (hover tooltip, positioned over the hovered cell),
2639
3242
  `live-region` (visually-hidden `role="status" aria-live="polite"` element announcing the
2640
3243
  keyboard-focused cell), `legend`, `legend-lo`, `legend-hi` (both omitted, along with the gradient
2641
3244
  bar between them, while `legendStops` is supplied), `legend-stop` (one per `legendStops` entry),
2642
- `legend-swatch` (that stop's color chip), `legend-stop-label` (that stop's text),
3245
+ `legend-swatch` (that stop's color chip, not rendered at all for a caption-only stop),
3246
+ `legend-stop-label` (that stop's text), `legend-value-label` (the trailing `valueLabel` caption that
3247
+ closes the legend row, present in both the gradient and the `legendStops` branch),
2643
3248
  `legend-annotation` (one per labeled `annotations` entry)
2644
3249
 
2645
3250
  **Themeable custom properties:** `--lr-heatmap-scale-lo` (default `#cde2fb`),
@@ -2704,6 +3309,11 @@ same color as `--lr-heatmap-focus-ring-color`).
2704
3309
  width, so a container-resize redraw is a geometric no-op; the stylesheet's
2705
3310
  `canvas { inline-size: 100% }` is also dead code in that case, since `draw()` unconditionally sets
2706
3311
  an inline `canvas.style.width/height` that wins over it.
3312
+ - `maxCellSize`/`minCellSize` are no-ops without `fit-to-width` — an explicit `cellSize` is an exact
3313
+ request and is never clamped. And the canvas is sized *from the clamped* cell size, so a capped
3314
+ grid deliberately leaves the host's remaining width unfilled: the canvas simply ends early rather
3315
+ than stretching to fill. Position it with ordinary CSS on the host if you want it centered or
3316
+ end-aligned.
2707
3317
  - the host is `role="group"` (not `role="img"`) with a dimensions+range summary `aria-label`
2708
3318
  (calendar mode: a day-count + range summary instead) — `[part="canvas"]` inside it is a real
2709
3319
  focusable, keyboard-operable, per-cell-interactive control (roving arrow-key focus,
@@ -2758,6 +3368,12 @@ mapping is readable without hovering each cell.
2758
3368
  filtering legend). Because it only repeats the category names `[part="base"]` already announces
2759
3369
  through its `role="img"` summary, the legend is `aria-hidden` — visible on screen, announced
2760
3370
  exactly once — and it wraps onto further rows in a narrow allocation rather than overflowing
3371
+ - `markerLabel?: string` (attribute `marker-label`) — names what an item's `marker` *means* (e.g.
3372
+ `"Subagent"`). Setting it does two things: with `showLegend` on it adds one trailing
3373
+ `[part="legend-item"]`, whose `[part="legend-marker-swatch"]` reproduces the cell's own marker
3374
+ treatment, and it adds the marker to the auto-generated `aria-label` summary, which is otherwise
3375
+ per-category only. The marker count is reported as its own clause rather than folded into any
3376
+ category's count. Unset (the default) changes nothing: no extra legend row, no extra summary clause
2761
3377
 
2762
3378
  **Events:** none.
2763
3379
 
@@ -2768,13 +3384,19 @@ by its category), `marker` (the small bottom marker on a cell whose item sets `m
2768
3384
  `tooltip` (the hover tooltip showing the hovered item's label, hidden until a cell is hovered),
2769
3385
  `legend` (the static category key rendered below the strip when `showLegend` is set — `aria-hidden`,
2770
3386
  as it repeats the strip's own `aria-label`), `legend-item` (one swatch + label pair, one per
2771
- `categories` entry), `legend-swatch` (the color chip, matching that category's cell color),
2772
- `legend-label` (the category's `label`, or its `key` when unset).
3387
+ `categories` entry, plus one trailing marker row when `markerLabel` is set), `legend-swatch` (the
3388
+ color chip, matching that category's cell color), `legend-marker-swatch` (the marker row's chip
3389
+ instead: a neutral chip carrying the same bottom bar a `marker: true` cell paints, in the same
3390
+ `--lr-sequence-strip-marker-color`), `legend-label` (the category's `label`, or its `key` when
3391
+ unset).
2773
3392
 
2774
3393
  **Themeable custom properties:** `--lr-sequence-strip-height` (default `1.5rem` — the strip's
2775
3394
  block-size), `--lr-sequence-strip-marker-color` (default `var(--lr-color-text)` — the
2776
- `[part="marker"]` fill), and `--lr-sequence-strip-legend-swatch-size` (default `0.625rem` — the
2777
- `[part="legend-swatch"]` chip's inline- and block-size); the tooltip also consumes shared tokens
3395
+ `[part="marker"]` fill, and of the marker legend row's bar), `--lr-sequence-strip-legend-swatch-size`
3396
+ (default `0.625rem` — a legend swatch's inline- and block-size, category and marker rows alike), and
3397
+ `--lr-sequence-strip-legend-marker-bg` (default `var(--lr-color-surface-raised)` — the neutral chip
3398
+ background behind the marker legend row's bar; it stands in for "any cell", so it deliberately
3399
+ matches no category color); the tooltip also consumes shared tokens
2778
3400
  `--lr-color-surface`, `--lr-color-text`, `--lr-font-size-xs`, `--lr-radius`, and `--lr-shadow`, and
2779
3401
  the legend consumes `--lr-space-2xs`, `--lr-space-xs`, `--lr-space-s`, `--lr-font-size-xs`,
2780
3402
  `--lr-color-text-quiet`, and `--lr-radius-xs`.
@@ -2830,18 +3452,34 @@ deeply-nested node's own shadow root still reaches it).
2830
3452
  `[part="base"]` element. The component forwards a host `aria-label` to that semantic element when
2831
3453
  `label` is empty; `label` takes precedence when both are set. External `aria-labelledby` idrefs
2832
3454
  are not forwarded across the shadow boundary.
3455
+ - `reorderable: boolean = false` (reflected) — opts into keyboard reordering. Unset, no `lr-reorder`
3456
+ is ever emitted, Ctrl/Cmd+Arrow behaves exactly like a plain Arrow press, and the internal live
3457
+ region is not rendered at all.
2833
3458
 
2834
3459
  **Keyboard:** ArrowDown/ArrowUp move the roving focus to the next/previous *visible* node.
2835
3460
  ArrowRight expands a collapsed node (focus stays put; a second ArrowRight then steps into the first
2836
3461
  child) or moves into an already-expanded node's first child. ArrowLeft collapses an expanded node, or
2837
3462
  moves focus to its parent. Home/End jump to the first/last visible node. Enter/Space activate
2838
- `select()` on the focused node.
3463
+ `select()` on the focused node. While `reorderable`, **Ctrl/Cmd**+ArrowUp/ArrowDown moves the focused
3464
+ node within its own parent's child list instead of navigating. Ctrl/Cmd rather than Alt: Alt+Arrow is
3465
+ browser back/forward on Windows and Linux. ArrowUp/ArrowDown are not direction-sensitive, so this
3466
+ binding is deliberately **not** RTL-swapped — "down" always means later in the sibling list.
2839
3467
 
2840
3468
  **Methods:** `expandAll()`, `collapseAll()` (both recursive, properly sequenced around Lit's render
2841
3469
  cycle).
2842
3470
 
2843
- **Events:** none dispatched directly (see `lr-tree-node` below they bubble up and are also
2844
- observed internally to keep the roving `activeId` in sync with clicks).
3471
+ **Events:** `lr-reorder` (`detail: { id, parentId, fromIndex, toIndex }`, only while `reorderable`).
3472
+ Like every other event here it is a **request**: `data` is host-owned and is never mutated by this
3473
+ component, so nothing moves until the host reassigns a reordered `data` — focus then follows the
3474
+ moved node. `parentId` is `null` for a top-level item, and `fromIndex`/`toIndex` are **sibling-scoped
3475
+ indices**, not positions in the flattened visible list. The move is constrained to one sibling list
3476
+ and never fires at a subtree boundary, so a reorder can never become a reparent: Ctrl+ArrowDown on
3477
+ the last child of a subtree is ambiguous (the visually next row is a top-level uncle, so "move down"
3478
+ could mean either "swap with the next sibling" — there is none — or "reparent up a level"), and
3479
+ reparenting is a structural edit with no keyboard affordance distinguishing the two. Such a request
3480
+ is simply not made: no event, no announcement, focus stays put. Otherwise this element dispatches
3481
+ nothing directly (see `lr-tree-node` below — those bubble up and are also observed internally to keep
3482
+ the roving `activeId` in sync with clicks).
2845
3483
 
2846
3484
  **Slots:** default (holds the `<lr-tree-node>` elements it manages).
2847
3485
 
@@ -2925,6 +3563,8 @@ indentation), plus the shared tokens listed above.
2925
3563
  - row enrichment is intentionally structured rather than an unrestricted renderer: use `icon`,
2926
3564
  `label`, `description`, `badge`, and `accessibleLabel`. This keeps the host as the single
2927
3565
  `role="treeitem"` interaction target and preserves the APG keyboard model.
3566
+ - `lr-file-tree` does **not** forward `reorderable`, and deliberately so: its `TreeItem[]` is derived
3567
+ from `nodes` on every render and keyed by filesystem path, an order it does not own.
2928
3568
 
2929
3569
  ---
2930
3570
 
@@ -2991,8 +3631,21 @@ with a console warning), `top-start`, `top-end` (floating corner overlays), `bot
2991
3631
  `live-region`, `edge-list` (a visually hidden list of every edge).
2992
3632
 
2993
3633
  **Themeable custom properties:** `--lr-flow-canvas-grid-size` (default `8px`, dotted background
2994
- spacing), `--lr-flow-canvas-march-duration` (default `var(--lr-transition-ambient)`, running-edge
2995
- march animation duration).
3634
+ spacing — the canvas also writes it inline as `${grid}px` from the `grid` property, which wins over
3635
+ the stylesheet fallback whenever a grid is in effect), `--lr-flow-canvas-march-duration` (default
3636
+ `var(--lr-transition-ambient)`, running-edge march animation duration), and
3637
+ `--lr-flow-canvas-node-current-outline-color` (default `var(--lr-color-brand)`) — the outline color
3638
+ of the current (`aria-current`) node. Like every state-scoped custom property in this library it is
3639
+ an inline `var()` fallback at its point of use rather than a `:host` declaration, so it can be set on
3640
+ the element *or any ancestor*. It exists because Shadow Parts forbids an attribute selector after
3641
+ `::part()` — `::part(node)[aria-current='true']` is invalid CSS — so the current node could otherwise
3642
+ only be restyled by overriding the library-wide `--lr-color-brand` token, repainting everything else
3643
+ that reads it. The same restriction motivates three more state-scoped outline colors:
3644
+ `--lr-flow-canvas-node-connect-invalid-outline-color` (default `var(--lr-color-danger)`) — outline of
3645
+ a node that is an invalid connect-gesture drop target; `--lr-flow-canvas-node-connect-target-outline-color`
3646
+ (default `var(--lr-color-brand)`) — outline of a node that is a valid connect-gesture drop target; and
3647
+ `--lr-flow-canvas-drop-active-outline-color` (default `var(--lr-color-brand)`) — outline of the
3648
+ viewport itself while a palette item is dragged over it (`droppable`).
2996
3649
 
2997
3650
  **Optional peer deps:** none.
2998
3651
 
@@ -3045,6 +3698,8 @@ owns none of that.
3045
3698
  - `statusDetail: string = ''` (attribute `status-detail`) — appended to the status line
3046
3699
  - `durationMs: number | null = null` (attribute `duration-ms`) — formatted into the status line
3047
3700
  - `selected: boolean = false` (reflected)
3701
+ - `compact: boolean = false` (reflected) — tighter card padding for dense canvases and palette
3702
+ previews; the border, background, shadow and the `selected`/`status="running"` treatments all stay
3048
3703
  - `inputs: FlowHandle[] = [{ id: 'in' }]`, `outputs: FlowHandle[] = [{ id: 'out' }]` (attribute:
3049
3704
  false) — `FlowHandle { id: string; label?: string }`
3050
3705
  - `orientation: 'horizontal' | 'vertical' = 'horizontal'` (reflected) — which physical edge handles
@@ -3055,10 +3710,24 @@ owns none of that.
3055
3710
  **Slots:** default (body content), `icon` (leading header glyph), `header` (replaces the built-in
3056
3711
  heading row entirely), `toolbar` (action row at the block-end edge).
3057
3712
 
3058
- **CSS parts:** `base`, `header`, `icon`, `heading`, `status` (never color-only always paired with
3059
- text), `progress`, `body`, `toolbar`, `handle` (every handle dot), `handle-input`, `handle-output`.
3060
-
3061
- **Themeable custom properties:** `--lr-flow-node-min-inline-size` (default `11rem`).
3713
+ **CSS parts:** `base` (the row wrapping the input handles, the card and the output handles — it
3714
+ carries no card chrome of its own), `card` (the bordered, filled node card), `header`, `icon`,
3715
+ `heading`, `status` (never color-only — always paired with text), `progress`, `body`, `toolbar`,
3716
+ `handle` (every handle dot), `handle-input`, `handle-output`.
3717
+
3718
+ **Themeable custom properties:** `--lr-flow-node-min-inline-size` (default `11rem`),
3719
+ `--lr-flow-node-compact-padding` (default `var(--lr-space-xs)`) and `--lr-flow-node-compact-gap`
3720
+ (default `var(--lr-space-2xs)`) — `[part="card"]`'s padding and row gap while `compact` — and
3721
+ `--lr-flow-node-selected-border` (default `var(--lr-color-brand)`) — the card's border color while
3722
+ `selected`. Like the other state-scoped custom properties here they are inline `var()` fallbacks at
3723
+ their point of use rather than `:host` declarations, so they can be set on the element *or any
3724
+ ancestor* (a canvas retunes every card at once); overriding the selection color otherwise means
3725
+ hijacking the library-wide `--lr-color-brand` token and repainting everything else that reads it.
3726
+ `--lr-flow-node-running-border` (default `var(--lr-color-brand)`) — the card's border color while
3727
+ `status="running"`, independent of `--lr-flow-node-selected-border` so a consumer can retint just one
3728
+ of the two states without the other following along — and `--lr-flow-node-running-glow` (default
3729
+ `var(--lr-color-brand-quiet)`) — the box-shadow color of the running-state ring around the card, and
3730
+ the pulse keyframes' peak color.
3062
3731
 
3063
3732
  **Optional peer deps:** none.
3064
3733
 
@@ -3071,6 +3740,11 @@ text), `progress`, `body`, `toolbar`, `handle` (every handle dot), `handle-input
3071
3740
  reduced-motion exception every animated surface in this library follows.
3072
3741
  - `status` drives a status chip with a localized label plus `statusDetail`/`durationMs`, never a
3073
3742
  color-only indicator.
3743
+ - All card chrome lives on `[part="card"]`, not `[part="base"]` — `base` is only the flex row that
3744
+ holds the input handles, the card and the output handles. Style the box through `::part(card)`.
3745
+ - `--lr-flow-node-min-inline-size` was previously overridden by a duplicate declaration and had no
3746
+ effect. It now sets the card's minimum inline size again, so a node that was relying on the card
3747
+ collapsing below `11rem` will render wider than it used to.
3074
3748
 
3075
3749
  ---
3076
3750
 
@@ -3125,16 +3799,23 @@ no editing commands live here.
3125
3799
  - `for: string = ''` — id of the target `lr-flow-canvas`; empty resolves to the nearest ancestor
3126
3800
  - `orientation: 'vertical' | 'horizontal' = 'vertical'` (reflected) — button-cluster layout axis
3127
3801
  - `hideLock: boolean = false` (attribute `hide-lock`) — omits the lock/unlock toggle button
3802
+ - `appearance: FlowControlsAppearance = 'card'` (reflected) — `'card' | 'plain'`; `'plain'` drops
3803
+ `[part="base"]`'s border, background, padding, corner radius and its floating-surface `box-shadow`,
3804
+ for a cluster placed in a host toolbar or panel that already draws its own surface. There is
3805
+ deliberately no `compact`: the padding is already the smallest spacing step and the only remaining
3806
+ room is the buttons' `--lr-icon-button-size` hit-area floor
3128
3807
 
3129
3808
  **Events:** none dispatched directly — each button calls the resolved canvas's own `zoomIn()`/
3130
3809
  `zoomOut()`/`fit()`, or toggles its `locked` property.
3131
3810
 
3132
3811
  **Slots:** default — extra host buttons appended to the cluster, styled by the same group.
3133
3812
 
3134
- **CSS parts:** `base` (the `role="group"` wrapper), `zoom-in`, `zoom-out`, `fit`, `lock` (omitted
3135
- when `hideLock`).
3813
+ **CSS parts:** `base` (the `role="group"` wrapper; drops its floating-surface chrome under
3814
+ `appearance="plain"`), `zoom-in`, `zoom-out`, `fit`, `lock` (omitted when `hideLock`).
3136
3815
 
3137
- **Themeable custom properties:** shared tokens only.
3816
+ **Themeable custom properties:** shared tokens only — `--lr-icon-button-size` (each button's minimum
3817
+ hit area, unchanged by `appearance`), `--lr-shadow`, `--lr-color-surface`, `--lr-color-border`,
3818
+ `--lr-radius`, `--lr-space-2xs`, `--lr-focus-ring-width`/`-color`/`-offset`.
3138
3819
 
3139
3820
  **Optional peer deps:** none.
3140
3821
 
@@ -3148,6 +3829,10 @@ when `hideLock`).
3148
3829
  - `for` resolution is identical to `lr-flow-minimap`/`lr-flow-run-overlay`: an explicit id, else
3149
3830
  the nearest ancestor canvas — none of the three companions import `LyraFlowCanvas` as a value, only
3150
3831
  its types, so registration order between them and the canvas never matters.
3832
+ - `appearance="plain"` drops the `box-shadow` along with the border and background — unlike most
3833
+ `plain` escapes in this library, which only reset the border/background/padding/radius. A lift
3834
+ shadow with no surface under it reads as a stray smudge, so the whole floating-surface treatment
3835
+ goes together (same as `lr-flow-run-overlay`'s `plain`).
3151
3836
 
3152
3837
  ---
3153
3838
 
@@ -3164,6 +3849,10 @@ strip. Does not execute, poll, or time anything — pure pushed state; `duration
3164
3849
  - `hideSummary: boolean = false` (attribute `hide-summary`) — omits the "{done} of {total} steps
3165
3850
  complete" strip, keeping only the decoration push
3166
3851
  - `label: string = ''` — accessible name for the summary strip
3852
+ - `appearance: 'card'|'plain' = 'card'` (reflected) — `'plain'` removes the border, background,
3853
+ shadow, padding and radius, so a summary strip dropped straight into a host toolbar that already
3854
+ draws its own frame does not double it. `'card'` is the standalone floating-strip presentation and
3855
+ is unchanged.
3167
3856
 
3168
3857
  **Events:** none dispatched directly.
3169
3858
 
@@ -3313,6 +4002,14 @@ The focus position is re-clamped whenever `rows`/`columns` shrink, so the grid c
3313
4002
  **CSS parts:** `viewport` (the scrolling bordered wrapper), `grid` (the `<table role="grid">`),
3314
4003
  `header` (each sticky `<th>`), `row`, `cell`, `empty` (the loading / no-data cell).
3315
4004
 
4005
+ **Themeable custom properties:** `--lr-data-grid-row-selected-bg` (default
4006
+ `var(--lr-color-brand-quiet)`) — the background of the selected row's cells. It is an inline `var()`
4007
+ fallback at its point of use rather than a `:host` declaration, so it can be set on the element *or
4008
+ any ancestor*. It exists because Shadow Parts forbids an attribute selector after `::part()` —
4009
+ `::part(row)[aria-selected='true']` is invalid CSS — leaving the library-wide
4010
+ `--lr-color-brand-quiet` token as the only prior lever, which repaints every other surface reading
4011
+ it. `lr-table` exposes the equivalent knob as `--lr-table-row-selected-bg`.
4012
+
3316
4013
  ## `lr-calendar`
3317
4014
 
3318
4015
  Responsive month calendar with event markers and an agenda view.
@@ -3347,7 +4044,11 @@ the next button), `nav-glyph` (the chevron, `scaleX(-1)`-mirrored under RTL), `t
3347
4044
 
3348
4045
  **Themeable custom properties:** `--lr-calendar-day-min-block-size` (default `var(--lr-size-6rem)`)
3349
4046
  and `--lr-calendar-day-min-block-size-narrow` (default `4rem`, applied at container inline-size
3350
- ≤ 28rem).
4047
+ ≤ 28rem), and `--lr-calendar-day-selected-bg` (default `var(--lr-color-brand-quiet)`) — background of
4048
+ a selected (`data-selected="true"`) day cell. Component-scoped indirection over the shared
4049
+ `--lr-color-brand-quiet` token, so a consumer can retint the persistent selected-day highlight
4050
+ without also recoloring `[part='nav']:hover`/`[part='agenda-event']:hover`, which read that shared
4051
+ token directly for a visually distinct purpose (transient hover feedback).
3351
4052
 
3352
4053
  **Gotcha:** month-view `[part='event']` markers are a mouse-only quick-select affordance — they sit
3353
4054
  inside the day `<button>`, which may not contain focusable descendants. Agenda view renders each
@@ -3441,6 +4142,15 @@ the real unmasked value).
3441
4142
  an entry's value text and buttons), `value` (carries `data-masked`), `reveal-button`, and
3442
4143
  `copy-button`.
3443
4144
 
4145
+ **Themeable custom properties:** `--lr-env-list-reveal-active-bg` (default
4146
+ `var(--lr-color-brand-quiet)`) and `--lr-env-list-reveal-active-border` (default
4147
+ `var(--lr-color-brand)`) — the background and border color of a pressed (revealed) reveal toggle.
4148
+ Both are inline `var()` fallbacks at their point of use rather than `:host` declarations, so either
4149
+ can be set on the element *or any ancestor*. They exist because
4150
+ `::part(reveal-button)[aria-pressed='true']` is invalid CSS — Shadow Parts forbids an attribute
4151
+ selector after `::part()` — so restyling the pressed state otherwise required overriding the
4152
+ library-wide brand tokens.
4153
+
3444
4154
  ## `lr-document-library`
3445
4155
 
3446
4156
  Controlled searchable and filterable document inventory with versions, tags, owners, freshness,
@@ -3545,12 +4255,39 @@ auto-inserted between each adjacent pair.
3545
4255
  the panel's clamped width or `data-collapse-state`, see below).
3546
4256
  - `railWidth: string = '3.5rem'` (attribute `rail-width`) — the fixed CSS length the collapsing panel
3547
4257
  clamps to in `'rail'` state.
3548
- - `railBreakpoint: number = 640` (attribute `rail-breakpoint`, px) — below this container width (a
3549
- `ResizeObserver` on `[part='base']`, active only while `collapse !== 'none'`), the collapsing panel
3550
- switches from its normal drag-resizable percent width to the fixed `railWidth`.
3551
- - `floatBreakpoint: number = 400` (attribute `float-breakpoint`, px) below this narrower container
4258
+ - `railBreakpoint: number | string = 640` (attribute `rail-breakpoint`) — below this width, the
4259
+ collapsing panel switches from its normal drag-resizable percent width to the fixed `railWidth`.
4260
+ Accepts a bare pixel number (`640`, `rail-breakpoint="640"` the original form) or a CSS length
4261
+ string: `'640px'`, `'68.75rem'`, `'3em'`. Under the default `collapseBreakpointBasis='container'`
4262
+ it is compared against this component's own measured `[part='base']` inline size (a
4263
+ `ResizeObserver`, active only while `collapse !== 'none'`), and `rem` resolves against the
4264
+ document root's **computed** font size while `em` resolves against this element's own; the length
4265
+ is re-resolved on every measurement, never cached. Anything the grammar rejects — `''`, `'auto'`,
4266
+ garbage, a non-finite number, and deliberately `%`, `vw`/`vh`, `calc()` and `var()` — falls back
4267
+ to the `640` default rather than switching the feature off (unlike `orientationBreakpoint`, this
4268
+ breakpoint has a documented default to fall back to). A negative length is floored at `0`, i.e.
4269
+ never crossed. Must stay above `floatBreakpoint` — an inverted pair is sanitized by raising this
4270
+ one to match, collapsing the `'rail'` band away rather than reporting a wide container as
4271
+ collapsed.
4272
+ - `floatBreakpoint: number | string = 400` (attribute `float-breakpoint`) — below this narrower
3552
4273
  width, the collapsing panel instead becomes an absolutely-positioned overlay ("floating card") on
3553
4274
  top of the other pane(s), removed from the normal flex flow; the sibling(s) take the full width.
4275
+ Same accepted forms, basis, and sanitization as `railBreakpoint`; an unparseable value falls back
4276
+ to the `400` default.
4277
+ - `collapseBreakpointBasis: 'container'|'viewport' = 'container'` (reflected, attribute
4278
+ `collapse-breakpoint-basis`) — which box `railBreakpoint`/`floatBreakpoint` are measured against.
4279
+ Unset, behavior is identical to before this property existed. `'container'` observes this
4280
+ component's own `[part='base']` inline size via `ResizeObserver` and compares strictly `<`;
4281
+ `'viewport'` evaluates `matchMedia('(max-width: <breakpoint>)')` for each of the two thresholds,
4282
+ which is inclusive (`<=`) — native `max-width` semantics, deliberately, so the crossing point
4283
+ matches a CSS `@media` rule authored with the same length exactly. Use `'viewport'` to collapse in
4284
+ step with a page-level responsive layout (a shell whose own `@media` rules restack at the same
4285
+ width) rather than with this split's own allocation; it is also what lets the browser resolve a
4286
+ `rem` breakpoint with real `@media` semantics (against the *initial* font size, ignoring an
4287
+ `html { font-size }` override). Both bands are classified from both queries together on every
4288
+ change, so a fast resize crossing both thresholds at once still lands on one correct state and
4289
+ fires `lr-split-collapse-change` once; under `'viewport'` the first paint is already correct — no
4290
+ `ResizeObserver` round-trip — and that initial state is not announced as a transition.
3554
4291
  - `collapseState: 'wide'|'rail'|'floating'` (reflected, attribute `collapse-state`) — a public
3555
4292
  accessor with force/auto semantics mirroring `<lr-app-rail>`'s `mode`: normally derived
3556
4293
  automatically from the measured container width, but assigning it a concrete value pins it there
@@ -3636,6 +4373,21 @@ the visually-adjacent panel).
3636
4373
  `disconnectedCallback`) is solid and safe to rely on.
3637
4374
  - `orientationBreakpoint` shares its `[part='base']` `ResizeObserver` with `collapse` (one observer,
3638
4375
  not two) — arming logic covers either feature being opted into independently.
4376
+ - **Switching a basis moves the crossing point by exactly 1px.** Container basis compares strictly
4377
+ `<` against a measured width; viewport basis asks `matchMedia('(max-width: …)')`, which is
4378
+ inclusive (`<=`). So at a breakpoint of `640`, a container-basis split is still `'wide'` at 640px
4379
+ while a viewport-basis one has already collapsed. This is deliberate on both sides: `<` is the
4380
+ right comparison for "how much room do I actually have", and `<=` is what a CSS `@media` rule with
4381
+ the same length does, which is the whole point of the viewport basis.
4382
+ - `collapseBreakpointBasis='viewport'` does **not** drop the `ResizeObserver` the way the
4383
+ orientation feature's viewport basis does. The measured width it feeds is still read by a
4384
+ container-basis `orientationBreakpoint` and by the `collapseState = 'auto'` release path, which
4385
+ re-derives from the current measured width. Collapse's basis changes only *which values* the
4386
+ classification consults, never whether the split measures itself.
4387
+ - `railBreakpoint`/`floatBreakpoint` are typed `number | string`. Authored as attributes they read
4388
+ back as **strings** (`el.railBreakpoint === '640'`, not `640`) — the same value, a different type.
4389
+ Compare with `Number(el.railBreakpoint)` rather than `===`, or assign the property directly when a
4390
+ numeric identity matters.
3639
4391
  - **Picking a basis.** `orientationBreakpointBasis='container'` (the default) observes the
3640
4392
  component's own allocated inline size, so it fits a component that is the sole flex/grid item in
3641
4393
  the container being measured. It does **not** fit a component sitting beside a fixed-width sibling
@@ -3721,6 +4473,17 @@ the fullscreen backdrop scrim color), `--lr-widget-fullscreen-inset` (default pe
3721
4473
  tokens (`--lr-space-*`, `--lr-color-border/-surface/-text-quiet`,
3722
4474
  `--lr-radius`, `--lr-shadow`, `--lr-icon-button-size`, `--lr-focus-ring-*`).
3723
4475
 
4476
+ Two further properties style the pressed view toggle: `--lr-widget-view-toggle-active-bg` (default
4477
+ `var(--lr-color-brand-quiet)`) and `--lr-widget-view-toggle-active-color` (default
4478
+ `var(--lr-color-brand)`) — the background and text color of the `aria-pressed="true"` toggle. Both
4479
+ are **state hooks**: declared as inline `var()` fallbacks at the point of use and never on `:host`,
4480
+ so setting either on the element *or on any ancestor* reaches the toggle. That shape exists because
4481
+ `::part(view-toggle)[aria-pressed='true']` is not valid CSS — Shadow Parts forbids an attribute
4482
+ selector after `::part()` — so before these hooks the only way to recolor an active toggle was to
4483
+ override the library-wide `--lr-color-brand-quiet`/`--lr-color-brand` tokens, repainting every other
4484
+ element that reads them. Left unset, each falls back to exactly the token the rule used before, so
4485
+ rendering is unchanged.
4486
+
3724
4487
  **Optional peer deps:** none.
3725
4488
 
3726
4489
  ```html
@@ -3775,6 +4538,15 @@ viewport), `track`, `controls`, `previous-button`, `next-button`, `previous-glyp
3775
4538
  chevron inside each, mirrored under RTL), `indicators`, `indicator` (one indicator's hit target,
3776
4539
  sized to the shared minimum tappable size), and `indicator-dot` (the compact visible dot inside it).
3777
4540
 
4541
+ **Themeable custom properties:** `--lr-carousel-indicator-current-bg` (default
4542
+ `var(--lr-color-brand-quiet)`) and `--lr-carousel-indicator-current-border-color` (default
4543
+ `var(--lr-color-brand)`) — background and border color of the current slide's `indicator-dot`
4544
+ (`[aria-current='true']`). Same state-hook mechanics as `<lr-widget>`'s view-toggle pair above:
4545
+ inline `var()` fallbacks, never declared on `:host`, so either can be set on the element or on any
4546
+ ancestor; unset, each falls back to the token the rule used before. This shape is what makes the
4547
+ current indicator addressable at all — `::part(indicator)[aria-current='true']` is invalid CSS, so
4548
+ hijacking a library-wide color token was previously the only lever.
4549
+
3778
4550
  ```html
3779
4551
  <lr-carousel aria-label="Screenshots">
3780
4552
  <img alt="Dashboard overview" src="overview.png">
@@ -3896,7 +4668,18 @@ inside a tab button; only rendered when that tab has a matching `<id>-icon` sibl
3896
4668
  single `role="tabpanel"` wrapper, one per tab, hidden unless active)
3897
4669
 
3898
4670
  **Themeable custom properties:** `--lr-scroll-fade-size` (default `2rem`) — width of the static
3899
- mask fade at each horizontal scroll edge of the tablist. Otherwise shared tokens —
4671
+ mask fade at each horizontal scroll edge of the tablist. `--lr-tabs-selected-color` (default
4672
+ `var(--lr-color-brand)`) — text color of the selected tab, scoped to `[aria-selected='true']` only,
4673
+ so it never repaints a hovered unselected tab. `--lr-tabs-indicator-color` (default
4674
+ `var(--lr-color-brand)`) — the selected tab's underline, themeable independently of its text color.
4675
+ `--lr-tabs-hover-color` (default `var(--lr-color-text)`) — text color of a hovered, non-disabled
4676
+ tab, independent of the two selected-state hooks. All three are declared as inline `var()` fallbacks
4677
+ at the point of use rather than on `:host`, so each can be set on the element *or on any ancestor* —
4678
+ the pattern exists because `::part(tab)[aria-selected='true']` is invalid CSS (Shadow Parts forbids
4679
+ an attribute selector after `::part()`), which previously left overriding the library-wide
4680
+ `--lr-color-brand`/`--lr-color-text` tokens as the only way to restyle a selected or hovered tab,
4681
+ repainting everything else that reads them. Unset, each falls back to the token its rule used
4682
+ before, so rendering is unchanged. Otherwise shared tokens —
3900
4683
  `--lr-space-xs/-s/-m`, `--lr-color-border/-text-quiet/-text/-brand`, `--lr-transition-fast`,
3901
4684
  `--lr-radius`, `--lr-focus-ring-width/-color/-offset`, `--lr-opacity-disabled`.
3902
4685
 
@@ -3937,10 +4720,13 @@ convention).
3937
4720
 
3938
4721
  **Properties:**
3939
4722
  - `steps: StepItem[] = []` (attribute: false) — `StepItem { id: string; label: string; state:
3940
- 'pending' | 'current' | 'completed' | 'disabled' | 'error'; title?: string }`; `title` is an
3941
- optional native tooltip for the step's button (e.g. explaining why a `disabled` step is locked) —
3942
- omit it for no `title` attribute at all, not an empty string. Never mutated by this component.
3943
- Empty (the default) renders nothing.
4723
+ 'pending' | 'current' | 'completed' | 'disabled' | 'error'; title?: string; icon?: unknown }`;
4724
+ `title` is an optional native tooltip for the step's button (e.g. explaining why a `disabled` step
4725
+ is locked) — omit it for no `title` attribute at all, not an empty string. `icon` is an optional
4726
+ leading topic glyph (a `TemplateResult`, an emoji string, etc. — not restricted to a square icon)
4727
+ rendered in the `step-icon` part additionally to, never instead of, the state-driven
4728
+ `step-index`/`step-check` glyph. Never mutated by this component. Empty (the default) renders
4729
+ nothing.
3944
4730
  - `orientation: 'horizontal' | 'vertical' = 'horizontal'` (reflected) — `'horizontal'` (the default)
3945
4731
  lays steps out in a row (Left/Right, RTL-aware, navigate); `'vertical'` stacks them (Up/Down
3946
4732
  navigate instead, no RTL swap needed). The axis used at/above `orientationBreakpoint` (or always,
@@ -3989,11 +4775,25 @@ single place to short-circuit its own listener's follow-up work. `lr-stepper-ori
3989
4775
  **Slots:** none.
3990
4776
 
3991
4777
  **CSS parts:** `base` (root wrapper, `role="tablist"`), `step` (a single step button, `role="tab"`),
3992
- `step-index` (the numbered index chip, shown for `pending`/`current`/`error` steps), `step-check`
3993
- (the completed-checkmark glyph, shown for `completed` steps instead of `step-index`), `step-label`
3994
- (the step's label text).
3995
-
3996
- **Themeable custom properties:** shared tokens only — `--lr-space-m`/`-xs`/`-2xs`,
4778
+ `step-icon` (optional leading topic glyph from the step's `icon` field; only rendered when the step
4779
+ has one, additionally to never instead of `step-index`/`step-check`), `step-index` (the numbered
4780
+ index chip, shown for `pending`/`current`/`error` steps), `step-check` (the completed-checkmark
4781
+ glyph, shown for `completed` steps instead of `step-index`), `step-label` (the step's label text).
4782
+
4783
+ **Themeable custom properties:** `--lr-stepper-current-color` (default `var(--lr-color-text)`) —
4784
+ text color of the `current` step. `--lr-stepper-current-font-weight` (default
4785
+ `var(--lr-font-weight-semibold)`) — font weight of the `current` step's label.
4786
+ `--lr-stepper-error-color` (default `var(--lr-color-danger)`) —
4787
+ text color of an `error` step. `--lr-stepper-current-index-bg` (default `var(--lr-color-brand)`) and
4788
+ `--lr-stepper-current-index-color` (default `var(--lr-color-surface)`) — background and text color
4789
+ of the `current` step's numbered `step-index` chip. Each is an inline `var()` fallback at the point
4790
+ of use, never declared on `:host`, so it can be set on the element or on any ancestor; and each is
4791
+ scoped to its own `data-state`, so recoloring the current step leaves `pending`/`completed`/`error`
4792
+ steps alone. The hooks exist because `::part(step)[data-state='current']` is invalid CSS — Shadow
4793
+ Parts forbids an attribute selector after `::part()` — so state-specific theming previously meant
4794
+ overriding a library-wide `--lr-color-*` token and repainting everything else that read it. Unset,
4795
+ each falls back to the token its rule used before. Otherwise shared tokens —
4796
+ `--lr-space-m`/`-xs`/`-2xs`,
3997
4797
  `--lr-color-text-quiet`/`-text`/`-danger`/`-brand`/`-surface`, `--lr-radius`/`-pill`,
3998
4798
  `--lr-font-size-xs`, `--lr-font-weight-semibold`, `--lr-opacity-disabled`,
3999
4799
  `--lr-focus-ring-*`.
@@ -4100,7 +4900,29 @@ fade at each horizontal scroll edge of the track. `--lr-segmented-track-min-heig
4100
4900
  `--lr-segmented-segment-padding`, and `--lr-segmented-font-size` are the three knobs `size` swaps
4101
4901
  (`m` defaults: `auto`, `var(--lr-size-0-125rem) var(--lr-space-s)`, `var(--lr-font-size-sm)`) —
4102
4902
  override them on the host for a size tier the scale doesn't cover, since a `:host([size])` rule
4103
- wins over the `:host` default. Otherwise shared tokens — `--lr-color-border`/`-surface`/`-text`/
4903
+ wins over the `:host` default.
4904
+
4905
+ `--lr-segmented-track-height` pins the `base` track's exact height at every `size` tier (it sets
4906
+ both `block-size` and `min-block-size`), for a row that has to sit flush beside a hard-sized toolbar
4907
+ control. It is **genuinely undeclared by default** — not `auto` — and that is load-bearing: an
4908
+ exact-height hatch only works as an undeclared sentinel, because `auto` is itself a valid value that
4909
+ would always win and would silently turn every tier's `--lr-segmented-track-min-height` floor into
4910
+ dead code. While it is unset, each tier keeps its own floor and the track grows with its content.
4911
+
4912
+ `--lr-segmented-selected-bg` (default `var(--lr-color-surface)`), `--lr-segmented-selected-color`
4913
+ (default `var(--lr-color-text)`), `--lr-segmented-selected-font-weight` (default
4914
+ `var(--lr-font-weight-semibold)`) and `--lr-segmented-selected-shadow` (default `var(--lr-shadow)`)
4915
+ style the checked segment's pill; `--lr-segmented-hover-color` (default `var(--lr-color-text)`)
4916
+ styles a hovered segment that is neither checked nor disabled, independently of the four above — so
4917
+ recoloring the checked pill never bleeds onto hover. All five are inline `var()` fallbacks at the
4918
+ point of use rather than `:host` declarations, so each can be set on the element *or on any
4919
+ ancestor*; unset, each falls back to the token its rule used before. They exist because
4920
+ `::part(segment)[aria-checked='true']` is invalid CSS — Shadow Parts forbids an attribute selector
4921
+ after `::part()` — which previously left hijacking the library-wide
4922
+ `--lr-color-surface`/`--lr-color-text` tokens as the only way to restyle a selected segment,
4923
+ repainting every other element that read them.
4924
+
4925
+ Otherwise shared tokens — `--lr-color-border`/`-surface`/`-text`/
4104
4926
  `-text-quiet`, `--lr-radius`, `--lr-font-weight-semibold`, `--lr-space-s`, `--lr-shadow`,
4105
4927
  `--lr-opacity-disabled`, `--lr-focus-ring-*`.
4106
4928
 
@@ -4150,10 +4972,39 @@ invention (no Web Awesome equivalent).
4150
4972
  which is only a safe identity while `items` never reorders/inserts/removes — provide this whenever
4151
4973
  possible, or scroll position and per-row DOM state (e.g. an `<audio>` element's playback position)
4152
4974
  can attach to the wrong row across a mutation.
4153
- - `groups?: VirtualListGroup[]` (attribute: false) — renders a labeled `role="heading"` marker at each
4154
- group's `startIndex`, positioned independently of the row window (so it stays in place as its rows
4155
- scroll past). Groups are sorted by `startIndex`; a `startIndex` that's non-integer, out of range, or
4156
- a duplicate of an earlier group's is silently dropped rather than rendered wrong.
4975
+ - `groups?: VirtualListGroup[]` (attribute: false) — renders a labeled marker at each group's
4976
+ `startIndex`, positioned independently of the row window (so it stays in place as its rows scroll
4977
+ past). Groups are sorted by `startIndex`; a `startIndex` that's non-integer, out of range, or a
4978
+ duplicate of an earlier group's is silently dropped rather than rendered wrong. An entry whose
4979
+ `label` is the **empty string** renders no marker at all — it is a pure position anchor, for a host
4980
+ that renders its own group header as an ordinary row (and would otherwise end up with two stacked
4981
+ headers) but still needs this component to know where each group starts, e.g. to drive
4982
+ `renderStickyGroup` below. Omitting `label` entirely still falls back to rendering `key`.
4983
+ - `renderStickyGroup?: (group: VirtualListGroup) => unknown` (attribute: false) — renders a pinned
4984
+ copy of whichever `groups` entry the viewport is currently inside, into a `[part="sticky-group"]`
4985
+ overlay that stays at the top of the scroll viewport and is pushed out by the overlap as the next
4986
+ group's header arrives (rather than swapped abruptly at the boundary). Native `position: sticky` on
4987
+ the rows or markers themselves cannot do this: every row is absolutely positioned and
4988
+ transform-offset by the windowing math, which makes sticky structurally inert. Unset (the default)
4989
+ renders no overlay element whatsoever and changes nothing about the list's output. The overlay is a
4990
+ *visual copy* of content that already exists in the list, which fixes its contract:
4991
+ - it is `aria-hidden`, and ordinary focusable HTML inside it is forced to `tabindex="-1"`, so the
4992
+ real row keeps sole ownership of the heading semantics and of the tab order (a focus-delegating
4993
+ custom element rendered into the copy needs its own `tabindex="-1"`; `inert` is deliberately not
4994
+ used, because it would also block the pointer opt-in below);
4995
+ - it is `pointer-events: none` by default — opt back in with
4996
+ `lr-virtual-list::part(sticky-group) { pointer-events: auto; }` when the copied header content is
4997
+ interactive;
4998
+ - it is never measured as a row, so a group header that is also a real row is not double-counted in
4999
+ `row-height="auto"` mode;
5000
+ - its measured height is applied as `scroll-padding-block-start` on the scroll container and
5001
+ subtracted from top-aligned scroll targets, so `active-id`, `scrollToIndex({ align: 'start' })`
5002
+ and native keyboard scrolling all stop *below* the band instead of parking the row behind it.
5003
+
5004
+ The callback runs on every scroll-driven update, so keep it cheap and side-effect free. While the
5005
+ viewport is above the first group there is nothing to pin: the band shows nothing, but it stays
5006
+ mounted (called with the first group, rendered hidden) so its height is known before the first
5007
+ programmatic jump rather than only after it.
4157
5008
  - `rowHeight: string = 'auto'` (attribute `row-height`) — `'auto'` measures each row's real height via
4158
5009
  `ResizeObserver`; a numeric string (e.g. `"56"`) fixes every row to that many pixels. Anything else
4159
5010
  (non-numeric, zero, negative, non-finite) silently falls back to `'auto'` rather than throwing.
@@ -4180,7 +5031,8 @@ invention (no Web Awesome equivalent).
4180
5031
 
4181
5032
  **Exported types:** `VirtualListRange { start: number; end: number }` (the `lr-visible-range-changed`
4182
5033
  detail shape); `VirtualListGroup { key: string | number; label?: string; startIndex: number }` — the
4183
- shape consumed by `groups` above.
5034
+ shape consumed by `groups` above; `VirtualListScroll { scrollTop: number; viewportHeight: number }` —
5035
+ the `lr-scroll` detail shape.
4184
5036
  The package root also exports `groupByRecency(items, options?)`, a DOM-free helper that returns
4185
5037
  non-empty Today/Yesterday/Previous 7 Days/Older buckets, preserves input order within each bucket,
4186
5038
  and accepts a timestamp extractor, reference date, and label overrides.
@@ -4190,12 +5042,35 @@ automatic scroll-into-view, for a host that needs to scroll to a specific row wi
4190
5042
  row is "active." `options.align` is `'start'`, `'end'`, or `'auto'` (default — no scroll at all when
4191
5043
  already fully visible); `options.behavior` (default `'smooth'`) is forced to `'auto'` under
4192
5044
  `prefers-reduced-motion: reduce`. `index` is clamped to `0…items.length-1`.
5045
+ `offsetForIndex(index)` returns the pixel top row `index` renders at, in the same coordinate space as
5046
+ the scroll container's `scrollTop`; it is clamped to `0…items.length`, so `offsetForIndex(items.length)`
5047
+ is the total content height and an empty list is always `0`. `indexAtOffset(px)` is its inverse — the
5048
+ row whose box contains that offset, clamped at both ends, `-1` for an empty list — so
5049
+ `indexAtOffset(offsetForIndex(i)) === i` and `indexAtOffset(scrollContainer.scrollTop)` is the row at
5050
+ the top of the viewport. In `row-height="auto"` mode both are estimate-based for any row that (or
5051
+ above which) has not been measured yet, and converge as those `ResizeObserver` measurements land;
5052
+ fixed numeric `row-height` offsets are exact from the first render. Both read the most recent render,
5053
+ so `await el.updateComplete` after assigning `items` before querying.
5054
+
5055
+ **Getters:** `scrollContainer: HTMLElement | undefined` — the real scroll container (`[part="base"]`),
5056
+ `undefined` before the first render; for a host that needs the live scroll position or wants to scroll
5057
+ the list itself without reaching into the shadow root. `renderedRows: HTMLElement[]` — the row
5058
+ wrappers (`[part="row"]`) that currently exist as real DOM, in item order (the current window, not the
5059
+ whole collection; empty before the first render). It exists for hosts that must *reach* a rendered row
5060
+ rather than style it — keyboard focus management across a windowed list, where the row to focus may
5061
+ not have existed a frame earlier, and which `exportparts` cannot serve since it forwards styling, not
5062
+ element references. Treat both as read-only: positioning, keys, and lifetime belong to the windowing
5063
+ math, and any row element can be recycled or removed on the next update.
4193
5064
 
4194
5065
  **Events:** `lr-load-more` (no detail — fired once per approach to the bottom of the list while
4195
5066
  `has-more` is true and `loading` is false; does not refire on every scroll tick while still near the
4196
5067
  bottom — scrolling back away from the bottom and returning, or `items` growing enough to move the
4197
5068
  window away from the end, re-arms it), `lr-visible-range-changed` (`detail: VirtualListRange`, the
4198
- current visible, non-overscanned item index range — fired only when it actually changes)
5069
+ current visible, non-overscanned item index range — fired only when it actually changes), `lr-scroll`
5070
+ (`detail: VirtualListScroll` — the scroll container moved; emitted from the same animation frame that
5071
+ already coalesces native `scroll` events, so a fling produces at most one per frame and none at all
5072
+ when the position did not change. Unlike `lr-visible-range-changed`, which only fires on index-range
5073
+ changes, this reports *sub-row* movement, which is what scroll-linked layout needs)
4199
5074
 
4200
5075
  **Slots:** none — all content comes from `renderItem`.
4201
5076
 
@@ -4203,8 +5078,11 @@ current visible, non-overscanned item index range — fired only when it actuall
4203
5078
  `item-role="row"` mode — `tabindex="0"`), `spacer` (the full-content-height inner element
4204
5079
  establishing true scroll extent; `role="presentation"` in `item-role="row"` mode), `row` (one
4205
5080
  rendered row's absolutely-positioned wrapper, `role="listitem"` — or `role="row"` with
4206
- `aria-rowindex` in `item-role="row"` mode), `group` (a `groups` entry's positioned `role="heading"`
4207
- marker)
5081
+ `aria-rowindex` in `item-role="row"` mode), `group` (a `groups` entry's positioned marker; not
5082
+ rendered for an entry whose `label` is the empty string), `sticky-group` (the pinned copy of the
5083
+ current group, present only while `renderStickyGroup` is set — `aria-hidden` and
5084
+ `pointer-events: none` by default; style it with `pointer-events: auto` to make copied interactive
5085
+ content clickable, and it shows nothing while the viewport is above the first group)
4208
5086
 
4209
5087
  **Themeable custom properties:** `--lr-virtual-list-height` (default `24rem` — the host's bounded
4210
5088
  scroll extent; component-specific since a virtualized list is meaningless without a sized viewport),
@@ -4233,6 +5111,20 @@ so it isn't clipped by the container's own `overflow: auto`).
4233
5111
  ></lr-virtual-list>
4234
5112
  ```
4235
5113
 
5114
+ ```html
5115
+ <!-- Sticky group headers: the header is a real row, so the `groups` entries are position anchors
5116
+ only (`label: ''`), and the pinned copy opts back into pointer events for its own toggle. -->
5117
+ <lr-virtual-list
5118
+ .items=${rows}
5119
+ .groups=${groupStarts /* [{ key: 'Today', label: '', startIndex: 0 }, …] */}
5120
+ .renderItem=${(item, index) => (item.isHeader ? headerTemplate(item) : rowTemplate(item))}
5121
+ .renderStickyGroup=${(group) => headerTemplate(group)}
5122
+ ></lr-virtual-list>
5123
+ <style>
5124
+ lr-virtual-list::part(sticky-group) { pointer-events: auto; }
5125
+ </style>
5126
+ ```
5127
+
4236
5128
  Every row — in both `row-height` modes — is positioned by a `transform: translateY(offset)` computed
4237
5129
  from a single cumulative offsets array, rather than by page flow; this is what lets a small DOM window
4238
5130
  exist while the scrollbar still reflects the true total content height. That array is rebuilt only
@@ -4260,8 +5152,27 @@ history sidebar); it is not the right approach for a hundred-thousand-row list w
4260
5152
  - `aria-setsize`/`aria-posinset` are computed from a row's real index in the full `items` array, not its
4261
5153
  position among the currently-rendered DOM window, so assistive tech still announces e.g. "item 12 of
4262
5154
  340" correctly even though only a handful of rows exist in the DOM at a time.
4263
- - `groups` is accepted today purely for forward API compatibility; setting it has no visible effect
4264
- yet.
5155
+ - `groups`, `renderStickyGroup`, `offsetForIndex()`/`indexAtOffset()` and the `lr-scroll` event are
5156
+ all expressed against the *same* windowing math, so they agree with each other — but that math is
5157
+ estimate-based in `row-height="auto"` mode until the rows involved have been measured. Read a
5158
+ position after `await el.updateComplete`, and expect the value to converge rather than be final on
5159
+ the first frame.
5160
+ - A sticky band only appears when `renderStickyGroup` *and* at least one valid `groups` entry are
5161
+ both present; `groups` alone renders positioned markers with nothing pinned, and
5162
+ `renderStickyGroup` alone renders no overlay element at all.
5163
+ - **A row that renders a popup needs the focused-row lift, and this is why `[part='row']` has one.**
5164
+ Each row carries `will-change: transform` (a compositor hint for the per-frame translate), which
5165
+ makes every row its own stacking context. Rows otherwise carry no `z-index`, so they paint in DOM
5166
+ order and each one paints over the previous. Anything a row renders that overflows its own box —
5167
+ an `<lr-menu>` popup in a row-action menu, a tooltip, an outward focus ring — is therefore painted
5168
+ *underneath* every following row, no matter how high its own `z-index` is: that `z-index` only
5169
+ orders siblings inside the row's own context. The last row always looks correct, which is exactly
5170
+ why a short fixture never catches it. `[part='row']:focus-within` lifts the row to
5171
+ `--lr-layer-content` for precisely as long as something inside it holds focus — the lifetime of an
5172
+ open popup — and costs nothing otherwise. The value deliberately *matches* `[part='group']`'s
5173
+ rather than exceeding it, so the two land on the same layer and DOM order decides: groups render
5174
+ before the rows, so a focused row wins while (and only while) it holds focus, which is right — a
5175
+ group header is a non-interactive `pointer-events: none` label.
4265
5176
 
4266
5177
  ---
4267
5178
 
@@ -4467,6 +5378,17 @@ when the item has an explicit `aria-label`).
4467
5378
  **CSS parts:** `base`, `icon`, `label`, `tooltip` (the hover/focus label flyout, only rendered while
4468
5379
  `tooltip` is set, the item is `icon-only`, and it is hovered or focused).
4469
5380
 
5381
+ **Themeable custom properties:** `--lr-app-rail-item-current-bg` (default
5382
+ `var(--lr-color-brand-quiet)`) and `--lr-app-rail-item-current-color` (default
5383
+ `var(--lr-color-brand)`) — background and text/icon color of the `active` (`aria-current="page"`)
5384
+ item. Both are scoped to `[aria-current='page']` only and declared as inline `var()` fallbacks at
5385
+ the point of use, never on `:host`, so either can be set on the item itself *or on any ancestor* —
5386
+ including on `<lr-app-rail>` or a wrapper above it, to tint every item's active state at once.
5387
+ `::part(base)[aria-current='page']` is invalid CSS (Shadow Parts forbids an attribute selector after
5388
+ `::part()`), so before these hooks the only lever was overriding the library-wide
5389
+ `--lr-color-brand-quiet`/`--lr-color-brand` tokens, which repainted every other element reading
5390
+ them. Unset, each falls back to the token its rule used before.
5391
+
4470
5392
  **Optional peer deps:** none.
4471
5393
 
4472
5394
  ---
@@ -4520,7 +5442,11 @@ the *effective* mode — not the `mode` prop's possibly-`'auto'` literal value
4520
5442
  in the overlay presentation).
4521
5443
 
4522
5444
  **Themeable custom properties:** `--lr-responsive-panel-overlay-color` (default
4523
- `var(--lr-color-overlay)` — the overlay presentation's backdrop scrim color), plus shared tokens (`--lr-color-border`, `--lr-color-surface`,
5445
+ `var(--lr-color-overlay)` — the overlay presentation's backdrop scrim color),
5446
+ `--lr-responsive-panel-sheet-max-block-size` (default `85dvh`, falling back to `85vh` where `dvh`
5447
+ isn't supported — the maximum height of a `variant="bottom-sheet"` overlay panel, so a long sheet
5448
+ stops short of the top of the viewport instead of covering it; it has no effect on
5449
+ `variant="fullscreen"` or on the inline presentation), plus shared tokens (`--lr-color-border`, `--lr-color-surface`,
4524
5450
  `--lr-space-*`, `--lr-radius`, `--lr-shadow`).
4525
5451
 
4526
5452
  **Optional peer deps:** none.
@@ -4597,8 +5523,25 @@ menu, an avatar menu, or a history row's overflow menu. Uses the WAI-ARIA "menu
4597
5523
  `this.getAttribute('aria-label') || <computed default>` precedence
4598
5524
 
4599
5525
  - `closeOnEscapeAnywhere: boolean = false` (attribute `close-on-escape-anywhere`) — lets Escape
4600
- close the menu when focus is on slotted non-menu-item content inside the popup; item activation
4601
- remains scoped to actual menu items
5526
+ close the menu when focus is on non-menu-item content slotted into the **default** slot, i.e.
5527
+ rendered inside `[part="list"]`; item activation remains scoped to actual menu items. It has no
5528
+ bearing on the `header`/`footer` slots, which sit outside the `role="menu"` list and always close
5529
+ on Escape — so a menu that keeps its composed controls there never needs this property
5530
+
5531
+ **Methods:** `show(focus: 'first' | 'last' = 'first')` opens the menu and moves roving focus to the
5532
+ first (or, with `'last'`, the last) non-disabled item; a no-op when already open.
5533
+ `hide(options?: { focusTrigger?: boolean })` closes it; a no-op when already closed. They are the
5534
+ imperative pair for the cases the slotted trigger can't express — a "Done"/"Apply" button *inside*
5535
+ the menu, a keyboard shortcut, a parent restoring UI state — without hand-reproducing the
5536
+ pending-focus bookkeeping. Both are deliberately thin: positioning, the outside-click listener, the
5537
+ `lr-show`/`lr-hide` events, and the initial focus move all stay in one place, so **writing `open`
5538
+ directly is fully supported and equivalent apart from the focus moves**. In particular the
5539
+ roving-tabindex reset is centralized, so a bare `el.open = false` also clears `activeIndex` and
5540
+ never leaves a stale `tabindex="0"` tab stop on the last active item. `hide()` never refocuses
5541
+ unless you ask: pass `{ focusTrigger: true }` for a dismissal with nowhere else for focus to land,
5542
+ and leave it off when the interaction that closed the menu already put focus somewhere the user
5543
+ chose (an outside click, a Tab out). Focus restoration lives in `hide()` rather than in the
5544
+ close branch precisely so teardown — disconnecting an open menu — can't steal focus.
4602
5545
 
4603
5546
  **Events:** `lr-show` (no detail — fires only when `open` transitions to `true`, not for markup
4604
5547
  that renders `open` true from the start), `lr-hide` (same first-render guard, opposite
@@ -4610,10 +5553,25 @@ returning to the trigger)
4610
5553
  are assigned; enhanced imperatively with `aria-haspopup="menu"`/`aria-expanded`/`aria-controls`
4611
5554
  since those attributes belong on the actual interactive trigger, which lives outside this
4612
5555
  component's shadow root), default (`<lr-menu-item>` elements, plus optionally plain `<hr>`
4613
- dividers between groups — native `<hr>` already carries an implicit `separator` role)
5556
+ dividers between groups — native `<hr>` already carries an implicit `separator` role),
5557
+ `header` and `footer` (composed, deliberately non-menu-item content — a filter/search field, a
5558
+ section title, an "Apply"/"Done" button, a count — rendered above/below the items inside
5559
+ `[part="popup"]` but **outside** the `role="menu"` list. Both collapse to no box at all while
5560
+ unfilled, so a menu that uses neither renders exactly as it did before they existed)
5561
+
5562
+ Put composed controls in `header`/`footer` rather than the default slot. Non-item content in the
5563
+ default slot still works and is not deprecated at runtime (no warning is emitted), but it sits
5564
+ inside `role="menu"`, where ARIA permits only
5565
+ `menuitem`/`menuitemradio`/`menuitemcheckbox`/`group`/`separator` children — anything else is an
5566
+ `aria-required-children` violation. It is also not Tab-reachable from an item, and needs
5567
+ `closeOnEscapeAnywhere` before Escape will close the menu. The named regions have none of those
5568
+ problems.
4614
5569
 
4615
5570
  **CSS parts:** `trigger` (wrapper around the `trigger` slot — the positioning anchor), `popup` (the
4616
- positioned floating panel), `list` (the `role="menu"` container wrapping the default slot)
5571
+ positioned floating panel), `header` (wrapper around the `header` slot, above the list and outside
5572
+ `role="menu"`; `display: none` while that slot is unfilled), `list` (the `role="menu"` container
5573
+ wrapping the default slot), `footer` (wrapper around the `footer` slot, below the list and outside
5574
+ `role="menu"`; `display: none` while that slot is unfilled)
4617
5575
 
4618
5576
  **Themeable custom properties:** shared tokens only (`--lr-color-surface`, `--lr-color-border`,
4619
5577
  `--lr-radius`, `--lr-shadow`, `--lr-space-xs`, `--lr-transition-fast`).
@@ -4703,11 +5661,19 @@ navigation with no separate JS bookkeeping. ArrowDown/ArrowUp *on the trigger wh
4703
5661
  opens the menu, focusing the first/last non-disabled item respectively (mirrors native `<select>`).
4704
5662
  Once open, ArrowDown/ArrowUp move the roving focus among non-disabled items and wrap past either end
4705
5663
  (unlike `<lr-select>`'s clamped listbox nav); Home/End jump to the first/last non-disabled item;
4706
- Enter/Space activate the focused item; Escape closes and refocuses the trigger; Tab closes without
4707
- `preventDefault()`, letting the browser's own Tab navigation proceed untouched. All of this list-level
4708
- keydown handling Escape, Tab, the arrow keys, Home/End, and type-ahead alike only responds when
4709
- the triggering keydown event's own target is an actual `<lr-menu-item>` element; a keydown bubbling
4710
- up from any other node inside the popup is ignored rather than misread as list navigation. A printable
5664
+ Enter/Space activate the focused item; Escape closes and refocuses the trigger. The arrow keys,
5665
+ Home/End, Enter/Space and type-ahead only respond when the triggering keydown event's own target is
5666
+ an actual `<lr-menu-item>` element; a keydown bubbling up from any other node inside the popup is
5667
+ ignored rather than misread as list navigation. Escape and Tab are the two deliberate exceptions.
5668
+ Escape from `header`/`footer` content always closes the menu and refocuses the trigger (mirroring
5669
+ `lr-popover`'s handling of arbitrary popup content), while Escape from non-item content in the
5670
+ *default* slot closes it only with `closeOnEscapeAnywhere` set. Tab never traps focus and never
5671
+ calls `preventDefault()` — the browser's own Tab navigation always proceeds untouched — and closes
5672
+ the menu only when focus is on its way *out* of `[part="popup"]`: with a focusable in the
5673
+ `header`/`footer` region on the far side of the keypress the menu stays open so native Tab can carry
5674
+ focus there, and with neither region filled Tab closes exactly as it always has. Tabbing past the
5675
+ popup's last focusable in either direction closes the menu, including from slotted non-item content
5676
+ — which previously left the menu open while focus walked out of the popup entirely. A printable
4711
5677
  keypress runs type-ahead: roving focus jumps to the next non-disabled item whose text starts with the
4712
5678
  accumulated buffer (cycling from just after the active item, buffer resets ~500ms after the last
4713
5679
  keystroke) — mirrors `<lr-select>`'s identical listbox type-ahead. A click outside both the trigger
@@ -4725,8 +5691,20 @@ click itself already moved focus somewhere the user chose.
4725
5691
  - `lr-menu-item-select` carries no detail payload (`event.detail === null`); read
4726
5692
  `event.target.value` instead. `<lr-menu>`'s own re-fired `lr-menu-select` is the one that
4727
5693
  carries `detail: { value }`.
4728
- - Tab closes the menu without `preventDefault()` or focus trapping — the browser's own default Tab
4729
- navigation proceeds untouched, only the (now-stale) open state is cleared.
5694
+ - Tab never calls `preventDefault()` and never traps focus — the browser's own default Tab
5695
+ navigation always proceeds untouched. It closes the menu only when Tab would leave
5696
+ `[part="popup"]` entirely; when the `header`/`footer` region holds a focusable on the far side of
5697
+ the keypress, the menu stays open instead and native Tab moves focus into it. With neither region
5698
+ filled, Tab closes exactly as before.
5699
+ - Non-item content in the *default* slot is not Tab-reachable from an item — Tab from an
5700
+ `<lr-menu-item>` still closes the menu when there is no `header`/`footer` focusable to move to,
5701
+ even if a `<button>` is slotted alongside the items. Move such controls to `header`/`footer`.
5702
+ - `header`/`footer` emptiness is tracked from each slot's own `slotchange` and reflected on the host
5703
+ as `data-has-header` / `data-has-footer` (plus `data-list-empty`, which suppresses the region
5704
+ divider next to an empty list). They are internal styling hooks, not public API — don't set them
5705
+ by hand — but they are why `[part="header"]`/`[part="footer"]` collapse cleanly: a
5706
+ `[part]:empty` rule can never match a part that contains a slot, since Chromium counts the
5707
+ whitespace-only text nodes Lit leaves there.
4730
5708
  - Only Escape and a committed selection refocus the trigger on close; a click outside does not.
4731
5709
 
4732
5710
  ---
@@ -4842,14 +5820,19 @@ to `<wa-card>`'s contract, staying slot-compatible with `lr-result-card` where t
4842
5820
  for a quiet brand-tinted background; `'filled-outlined'` keeps the border and adds that same tinted
4843
5821
  background; `'accent'` drops the border for a single colored accent stripe on the leading edge;
4844
5822
  `'plain'` has no border or background at all.
4845
- - `interactive: boolean = false` (reflected) — opt-in hover/focus-visible treatment (border-color
4846
- shift, cursor: pointer) for a card used as a clickable tile — purely visual; this component takes
4847
- no position on what "activate" means unless `href` is also set. `false` (the default) reproduces a
4848
- plain static card.
5823
+ - `interactive: boolean = false` (reflected) — opt-in clickable-tile behavior: the hover/focus-visible
5824
+ treatment (border-color shift, `cursor: pointer`) plus, when `href` is **not** also set, real
5825
+ activation semantics `[part='base']` becomes focusable (`tabindex="0"`), responds to
5826
+ Enter/Space, and emits `lr-card-activate`. With `href` set, the root is already a real `<a>`, so
5827
+ native navigation *is* the activation and `lr-card-activate` never fires. `false` (the default)
5828
+ reproduces a plain static card: no `tabindex`, no listeners, no events.
4849
5829
  - `href?: string` — when set, the card's root renders as a real `<a href=...>` instead of a `<div>`,
4850
5830
  for a whole-card link (e.g. a wide CTA tile). Unset (the default) renders a plain `<div>`.
4851
5831
 
4852
- **Events:** none.
5832
+ **Events:** `lr-card-activate` (no detail) — the whole card was activated, by click or by
5833
+ Enter/Space while `[part='base']` has focus. Only fired while `interactive` is set **without**
5834
+ `href`. Never fired for an interaction that originated in a slotted control, so a card can keep its
5835
+ own action buttons (see the gotchas below).
4853
5836
 
4854
5837
  **Slots:** default (the card body), `header` (header row content, rendered above the body), `media`
4855
5838
  (media content, e.g. an image, rendered above the header), `footer` (footer content, rendered below
@@ -4883,6 +5866,22 @@ the `footer` slot, hidden entirely when empty).
4883
5866
  - slot-presence (`header`/`media`/`footer`/`actions`) is tracked in JS, not via CSS `:empty` (a
4884
5867
  `[part]` wrapper always contains a literal `<slot>` child, so `:empty` never matches) — the same
4885
5868
  pattern `lr-empty`/`lr-widget` use.
5869
+ - **an `interactive` card without `href` deliberately carries no `role="button"`.** A card is a
5870
+ *container* — it routinely holds slotted buttons and links — and `role="button"` around focusable
5871
+ descendants is the `nested-interactive` accessibility violation this library's own a11y gate
5872
+ enforces. (`lr-chip`'s `toggleable` mode *can* carry `role="button"` because it forbids focusable
5873
+ children outright.) The consequence is that the card is announced as a plain focusable region, so
5874
+ give it your own `aria-label` when the content doesn't already name it.
5875
+ - because there is no `role="button"` to disambiguate, "did the user aim at the card or at a control
5876
+ inside it?" is answered at event time: the composed path from the original target up to
5877
+ `[part='base']` is walked, and `lr-card-activate` is suppressed if anything along the way is
5878
+ itself a control (a link, `button`, `input`, `select`, `textarea`, `label`, `summary`,
5879
+ `contenteditable`, anything carrying a `tabindex` other than `-1`, or an ARIA widget role such as
5880
+ `button`/`link`/`checkbox`/`switch`/`radio`/`menuitem`/`option`/`tab`/`textbox`/`slider`/
5881
+ `spinbutton`). Using the *composed*
5882
+ path is what makes this work through a slotted component's own shadow root — a click on
5883
+ `<lr-button>` retargets to the host, but its composed path still contains the internal native
5884
+ `<button>`.
4886
5885
 
4887
5886
  ---
4888
5887
 
@@ -4895,10 +5894,13 @@ dismissal, ref-counted document scroll lock).
4895
5894
  **Properties:**
4896
5895
  - `open: boolean = false` (reflected)
4897
5896
  - `commands: LyraCommand[] = []` (attribute: false) — `{ id, label, description?, group?, shortcut?,
4898
- keywords?, disabled?, onSelect? }`. Filtering is case-insensitive substring matching over
4899
- `label` + `description` + `group` + `keywords` joined together (not fuzzy/subsequence), memoized
4900
- per `commands` array identity reassign the array, never mutate it in place. Consecutive commands
4901
- sharing a `group` render one `[part='group']` heading, so pre-sort by group yourself.
5897
+ keywords?, disabled?, icon?, onSelect? }`. `icon` is an optional leading glyph (a `TemplateResult`,
5898
+ an emoji string, etc. not restricted to a square icon) rendered in the `icon` part before the
5899
+ label; a command with no `icon` renders no `icon` part at all. Filtering is case-insensitive
5900
+ substring matching over `label` + `description` + `group` + `keywords` joined together (not
5901
+ fuzzy/subsequence), memoized per `commands` array identity — reassign the array, never mutate it
5902
+ in place. Consecutive commands sharing a `group` render one `[part='group']` heading, so pre-sort
5903
+ by group yourself.
4902
5904
  - `shortcut: string = 'mod+k'` — global toggle chord parsed as `+`-separated parts; `mod` resolves to
4903
5905
  Cmd on Mac and Ctrl elsewhere. The listener is on `window`, added in `connectedCallback`.
4904
5906
  - `accessibleLabel: string = ''` (attribute `aria-label`) — overrides the localized dialog name
@@ -4917,13 +5919,21 @@ fired before the command's own `onSelect` runs and before the palette closes).
4917
5919
 
4918
5920
  **CSS parts:** `backdrop`, `dialog` (the `role="dialog" aria-modal="true"` panel), `search` (the
4919
5921
  input row), `input` (the `type="search"` field), `list` (the `role="listbox"`), `group` (a group
4920
- heading), `command` (a `role="option"` button), `description`, `shortcut`, `empty`.
5922
+ heading), `command` (a `role="option"` button), `icon` (a command's leading icon glyph; only
5923
+ rendered when the command has one), `description`, `shortcut`, `empty`.
4921
5924
 
4922
5925
  **Themeable custom properties:** `--lr-command-palette-z-index` (default
4923
5926
  `var(--lr-overlay-stack-index, var(--lr-layer-modal))`), `--lr-command-palette-offset-block-start`
4924
5927
  (default `12vh` — how far down the viewport the dialog sits), `--lr-command-palette-max-inline-size`
4925
- (default `var(--lr-size-48rem)`), `--lr-command-palette-max-block-size` (default `70vh`), and
4926
- `--lr-command-palette-list-max-block-size` (default `50vh` — the scrolling result list).
5928
+ (default `var(--lr-size-48rem)`), `--lr-command-palette-max-block-size` (default `70vh`),
5929
+ `--lr-command-palette-list-max-block-size` (default `50vh` — the scrolling result list), and
5930
+ `--lr-command-palette-active-bg` (default `var(--lr-color-brand-quiet)` — the background of the
5931
+ active, keyboard-highlighted command row). That last one is an inline `var()` fallback at the point
5932
+ of use rather than a `:host` declaration, so it can be set on the element *or on any ancestor*:
5933
+ `::part(command)[data-active='true']` is invalid CSS (Shadow Parts forbids an attribute selector
5934
+ after `::part()`), so highlighting the active row previously required hijacking the library-wide
5935
+ `--lr-color-brand-quiet` token and repainting everything else that read it. Unset, it falls back to
5936
+ that token, so rendering is unchanged.
4927
5937
 
4928
5938
  ## `lr-details`, `lr-accordion`, and `lr-accordion-item`
4929
5939
 
@@ -4954,6 +5964,15 @@ its label.
4954
5964
  **CSS parts:** breadcrumb `base` (the `<nav>`) and `list` (the `role="list"` flex row wrapping the
4955
5965
  slotted items); item `base` (the `<a>` or `<span>`).
4956
5966
 
5967
+ **Themeable custom properties:** `--lr-breadcrumb-current-color` (default
5968
+ `var(--lr-color-text-quiet)`) — text color of the current-page item (`current`/`aria-current="page"`).
5969
+ It is an inline `var()` fallback at the point of use rather than a `:host` declaration, so it can be
5970
+ set on the item, on `<lr-breadcrumb>`, or on any ancestor above the trail:
5971
+ `::part(base)[aria-current='page']` is invalid CSS (Shadow Parts forbids an attribute selector after
5972
+ `::part()`), so tinting the current item previously meant overriding the library-wide
5973
+ `--lr-color-text-quiet` token and repainting everything else that read it. Unset, it falls back to
5974
+ that token.
5975
+
4957
5976
  ## `lr-dashboard-grid`
4958
5977
 
4959
5978
  Responsive, keyboard-accessible controlled widget grid. It positions layout entries and emits
@@ -5000,6 +6019,29 @@ Dashboard filter row that composes Lyra inputs and removable chips, with reset a
5000
6019
  `lr-validity-change`. **CSS parts:** `base`, `controls`, `filter-control`, `active-filters`,
5001
6020
  `chips`, `chip`, `reset-button`, `status`.
5002
6021
 
6022
+ Each filter definition's `type` selects which existing Lyra input renders it — this component
6023
+ composes them and never invents a control of its own. `'select'`/`'combobox'` map to their
6024
+ same-named counterparts (with `combobox`'s `multiple` opting into a multi-value filter),
6025
+ `'date'`/`'date-range'` both map to `<lr-date-input>` (single vs. `mode="range"`), and `'text'` maps
6026
+ to `<lr-input>` for an open-ended free-text query rather than a closed choice set. A `'text'`
6027
+ filter's value is the raw query string, verbatim, and its chip shows exactly that string — the same
6028
+ text the user typed, not a truncated or normalized form.
6029
+
6030
+ A `'text'` filter is the one control that is **not** a fully controlled `.value=` binding.
6031
+ Re-rendering a text field from `value` mid-typing would push a stale value back in and drop the
6032
+ caret to the end, so the field owns its own value while the user types, and an external `value`
6033
+ write is synced back into it only once no edit is in flight (a host write, a chip removal, and
6034
+ `reset()` all take that path).
6035
+
6036
+ `'text'` filters also accept an optional per-filter `debounce` (ms) — how long to wait after the
6037
+ last keystroke before committing the typed value to `value` and emitting a single `lr-input`, so a
6038
+ server-side query runs once per pause instead of once per character. Omitted, `0`, or a non-finite
6039
+ value means no debounce at all: every keystroke commits immediately. A pending debounce is always
6040
+ **flushed** by the field's own `change`/blur, so a blur never loses the last keystroke, and
6041
+ **cancelled outright** by `reset()`, by removing that filter's chip, and on disconnect — a stale
6042
+ keystroke can never overwrite a reset or fire after teardown. `debounce` is ignored for every other
6043
+ `type`, whose commits are discrete choices with nothing to debounce.
6044
+
5003
6045
  # Overlays, status & feedback (`components/overlays/`)
5004
6046
 
5005
6047
  ## `lr-toast` / `lr-toast-item` / `toast()`
@@ -5134,8 +6176,11 @@ attribute), `description` (rich description content, overrides the `description`
5134
6176
 
5135
6177
  **Themeable custom properties:** `--lr-empty-compact-align` (compact mode only; defaults preserve
5136
6178
  the existing `flex-start` cross-axis and `start` text alignment, and `center` centers both),
5137
- `--lr-empty-compact-padding` (default `--lr-space-xs` — padding used in compact mode), plus
5138
- shared tokens (`--lr-space-xs/-s/-l`, `--lr-color-text-quiet/-border/-text`).
6179
+ `--lr-empty-compact-padding` (default `--lr-space-xs` — padding used in compact mode),
6180
+ `--lr-empty-compact-gap` (default `--lr-space-2xs` — gap between the icon, heading, and description
6181
+ in compact mode; the non-compact layout's gap stays the plain shared `--lr-space-s` token, not
6182
+ independently themeable), plus shared tokens (`--lr-space-xs/-s/-l`,
6183
+ `--lr-color-text-quiet/-border/-text`).
5139
6184
 
5140
6185
  **Optional peer deps:** none.
5141
6186
 
@@ -5472,12 +6517,30 @@ back to `--lr-chip-bg`), the density quintet `--lr-chip-font-size`, `--lr-chip-p
5472
6517
  `--lr-chip-padding-inline`, `--lr-chip-gap`, `--lr-chip-icon-size` (all five are rewritten by each
5473
6518
  `:host([size])` rule, so setting one directly on the element overrides that step of the scale; the
5474
6519
  `m` defaults are `--lr-font-size-sm` / `--lr-size-0-25rem` / `--lr-space-s` / `--lr-space-xs` /
5475
- `--lr-font-size-sm`), plus shared tokens (`--lr-space-xs`, `--lr-space-s`,
6520
+ `--lr-font-size-sm`), the height pair `--lr-chip-min-height` / `--lr-chip-height` (below),
6521
+ plus shared tokens (`--lr-space-xs`, `--lr-space-s`,
5476
6522
  `--lr-color-brand`/`-brand-quiet`, `--lr-color-success`/`-success-quiet`,
5477
6523
  `--lr-color-warning`/`-warning-quiet`, `--lr-color-danger`/`-danger-quiet`,
5478
6524
  `--lr-icon-button-size`, `--lr-focus-ring-width`, `--lr-focus-ring-color`,
5479
6525
  `--lr-focus-ring-offset`, `--lr-transition-fast`).
5480
6526
 
6527
+ **Chip height — a floor and an exact cap:**
6528
+
6529
+ - `--lr-chip-min-height` (default `--lr-size-1-5rem`) floors an **interactive** chip only — one in
6530
+ toggle mode or with `removable` set. `2xs`/`xs`/`s`/`m` all share that `1.5rem` value because it
6531
+ is the 24px WCAG 2.2 SC 2.5.8 target minimum and an interactive chip must never shrink below it;
6532
+ `l` and `xl` raise it to their own taller floors. A passive display chip takes no floor from
6533
+ this at all, and every default sits below the chip's own content-driven height, so the floor is
6534
+ invisible until you raise it.
6535
+ - `--lr-chip-height` pins an **exact** height on `[part='base']` — interactive and passive chips
6536
+ alike — so a row of chips can line up with a sibling control of a known height. It is
6537
+ **undeclared by default**, which is what keeps the per-tier floor alive: `auto` is a valid
6538
+ declared value that would win over the `var()` fallback arm and make `--lr-chip-min-height` dead
6539
+ code, so never set it to `auto` — remove the declaration instead. Because the component never
6540
+ declares it, it can be set inline, from an ancestor, or from an outer-tree rule.
6541
+ **A value below 24px is for non-interactive display chips only**; pinning an interactive chip
6542
+ that short breaks its tap target.
6543
+
5481
6544
  **Optional peer deps:** none.
5482
6545
 
5483
6546
  ```html
@@ -5732,7 +6795,10 @@ period, shared with `lr-progress-bar`'s sweep).
5732
6795
 
5733
6796
  ## `lr-badge` and `lr-tag`
5734
6797
 
5735
- Compact status labels. Both expose `variant: 'neutral' | 'brand' | 'success' | 'warning' | 'danger'`.
6798
+ Compact status labels. Both expose `variant: 'neutral' | 'brand' | 'success' | 'warning' | 'danger'`
6799
+ and `size: '2xs' | 'xs' | 's' | 'm' | 'l' | 'xl' = 'm'` (reflected) — the same visual-density scale
6800
+ `<lr-chip>` uses, for typography/padding/minimum block size; `m` preserves the original badge
6801
+ dimensions. `lr-tag` inherits `size` unchanged from `lr-badge` rather than redeclaring it.
5736
6802
  The two tags share the same visual contract; `lr-tag` is a semantic alias for migration-friendly
5737
6803
  markup.
5738
6804
 
@@ -5742,6 +6808,10 @@ markup.
5742
6808
  — the trio each `:host([variant])` rule rewrites (`neutral` defaults to
5743
6809
  `--lr-color-surface`/`-text`/`-border`; the other four to the matching `*-quiet` fill with the loud
5744
6810
  color for text and border). Set one directly on the element for a tint outside the five variants.
6811
+ `--lr-badge-font-size` (default `var(--lr-font-size-sm)`), `--lr-badge-padding-inline` (default
6812
+ `var(--lr-space-s)`), and `--lr-badge-min-height` (default `var(--lr-size-1-25rem)`) — the density
6813
+ trio each `:host([size])` rule rewrites to that step's font size, inline padding, and minimum block
6814
+ size; the `m` defaults above exactly reproduce the pre-`size` fixed badge treatment.
5745
6815
 
5746
6816
  ## `lr-callout`
5747
6817
 
@@ -5767,7 +6837,12 @@ visible "×" glyph inside it — this is what shrinks under `inline`, so the hit
5767
6837
  **Themeable custom properties:** `--lr-callout-background`, `--lr-callout-color`,
5768
6838
  `--lr-callout-border` — the trio each `:host([variant])` rule rewrites (same
5769
6839
  surface/text/border → `*-quiet`/loud/loud scheme as `lr-badge`). `inline` drops the border,
5770
- background, and panel padding regardless of what these are set to.
6840
+ background, and panel padding regardless of what these are set to. `--lr-callout-close-hover-bg`
6841
+ (default `var(--lr-color-brand-quiet)`) — the close button's `:hover` background, deliberately
6842
+ decoupled from `--lr-callout-background` (which every non-neutral `variant` also retargets for the
6843
+ panel itself) so a consumer can retint the hover fill — e.g. to keep it visibly distinct from a
6844
+ `variant="brand"` panel, which shares the same default token — without a collateral effect on the
6845
+ panel background, and vice versa.
5771
6846
 
5772
6847
  ## `lr-rating`
5773
6848
 
@@ -5820,7 +6895,10 @@ built-in download completes), `lr-show`, `lr-hide` (format-menu visibility trans
5820
6895
 
5821
6896
  **CSS parts:** `trigger`, `menu`, `menu-item`, `format-label`, `format-description`
5822
6897
 
5823
- **Themeable custom properties:** shared tokens only.
6898
+ **Themeable custom properties:** shared tokens only, including `--lr-popover-viewport-clamp`
6899
+ (default `92vw`) — the shared narrow-viewport ceiling the `menu`'s max-inline-size is `min()`ed
6900
+ against, alongside its own `20rem` cap and the positioner's available space. See `lr-tour` for the
6901
+ shared-clamp note.
5824
6902
 
5825
6903
  **Optional peer deps:** none.
5826
6904
 
@@ -6011,9 +7089,12 @@ clipboard") or a per-node one (aria-label `Copy ${key/type}`, e.g. "Copy age");
6011
7089
  `copyable`)
6012
7090
 
6013
7091
  **Themeable custom properties:** `--lr-json-viewer-max-height` (default `none` — grows with content
6014
- until `max-height` is set), `--lr-json-viewer-font` (default `ui-monospace, SFMono-Regular, Menlo,
6015
- Consolas, monospace` component-specific since no shared monospace token exists), plus shared tokens
6016
- `--lr-color-border/-surface/-text/-text-quiet/-brand/-brand-quiet/-success/-warning/-warning-quiet`,
7092
+ until `max-height` is set), `--lr-json-viewer-font` (default `var(--lr-font-mono)`),
7093
+ `--lr-json-viewer-match-bg` (default `var(--lr-color-warning-quiet)`) background, and surrounding
7094
+ box-shadow, of a key/value that currently matches `search`. Component-scoped indirection over the
7095
+ shared `--lr-color-warning-quiet` token, so a consumer can retheme just this search-match highlight
7096
+ without repainting every other warning-toned surface that reads the same shared token. Plus shared
7097
+ tokens `--lr-color-border/-surface/-text/-text-quiet/-brand/-brand-quiet/-success/-warning/-warning-quiet`,
6017
7098
  `--lr-radius`, `--lr-space-xs/-s/-l`, `--lr-focus-ring-width/-color/-offset`,
6018
7099
  `--lr-transition-fast`.
6019
7100
 
@@ -6166,7 +7247,11 @@ button).
6166
7247
  **CSS parts:** `base`, `indicator` (the pulsing status dot), `countdown` (the `M:SS`, or
6167
7248
  "Refreshing…", text), `pause-button` (the built-in pause/resume toggle).
6168
7249
 
6169
- **Themeable custom properties:** shared tokens only — `--lr-space-xs`, `--lr-font-size-sm`,
7250
+ **Themeable custom properties:** `--lr-poll-status-due-bg` (default `var(--lr-color-success)`) —
7251
+ background of `indicator` while `data-due` is set. Component-scoped indirection over the shared
7252
+ `--lr-color-success` token, so a consumer can retheme just this due-state indicator without
7253
+ repainting every other component that reuses the same shared success token. Plus shared tokens —
7254
+ `--lr-space-xs`, `--lr-font-size-sm`,
6170
7255
  `--lr-color-text-quiet`, `--lr-color-brand`, `--lr-color-success`, `--lr-radius`/`-pill`,
6171
7256
  `--lr-focus-ring-*`.
6172
7257
 
@@ -6256,12 +7341,19 @@ renders `open="false"` on first paint)
6256
7341
  **CSS parts:** `listbox`, `option`, `option-icon` (when `icon` is set), `option-label`,
6257
7342
  `option-description` (when `description` is set), `empty`
6258
7343
 
6259
- **Themeable custom properties:** shared tokens only — `--lr-space-xs`/`-s`/`-m` (popup padding,
7344
+ **Themeable custom properties:** `--lr-mention-popover-option-active-bg` (default
7345
+ `var(--lr-color-brand-quiet)`) — background of the hovered or `[data-active]`
7346
+ (keyboard-highlighted) suggestion row. Component-scoped indirection over the shared
7347
+ `--lr-color-brand-quiet` token, so a consumer can retheme just this highlighted/active row without
7348
+ repainting every other component that reuses the same shared token. Plus shared tokens —
7349
+ `--lr-space-xs`/`-s`/`-m` (popup padding,
6260
7350
  row padding/gap), `--lr-color-surface`/`-border` (popup background/border), `--lr-radius`
6261
7351
  (popup and row corners), `--lr-shadow` (popup elevation), `--lr-transition-fast` (open/close
6262
- transition), `--lr-color-brand-quiet` (active-row background), `--lr-color-brand` (selected-row
7352
+ transition), `--lr-color-brand` (selected-row
6263
7353
  text), `--lr-color-text-quiet`/`--lr-color-text` (description text, full-contrast on the active
6264
- row).
7354
+ row), and `--lr-popover-viewport-clamp` (default `92vw`) — the shared narrow-viewport ceiling the
7355
+ popup's max-inline-size is `min()`ed against, alongside its own `24rem` cap and the positioner's
7356
+ available space. See `lr-tour` for the shared-clamp note.
6265
7357
 
6266
7358
  **Optional peer deps:** none.
6267
7359
 
@@ -6585,12 +7677,31 @@ block, repeated three times, `data-field="day"|"month"|"year"`), `field-input` (
6585
7677
  small per-field text label), `hint`, `error` (`role="alert"`).
6586
7678
 
6587
7679
  **Themeable custom properties:** `--lr-known-date-field-padding-block`,
6588
- `--lr-known-date-field-padding-inline`, `--lr-known-date-field-font-size` (all three rewritten by
6589
- each `:host([size])` rule; `m` defaults `--lr-space-s`/`--lr-space-s`/`--lr-font-size-md-sm`),
7680
+ `--lr-known-date-field-padding-inline`, `--lr-known-date-field-font-size`,
7681
+ `--lr-known-date-field-min-height` (all four rewritten by
7682
+ each `:host([size])` rule; `m` defaults `--lr-space-s`/`--lr-space-s`/`--lr-font-size-md-sm`/
7683
+ `--lr-size-2-5rem`), `--lr-known-date-field-height`,
6590
7684
  `--lr-known-date-field-gap` (default `--lr-space-s` — gap between the three field blocks),
6591
7685
  `--lr-known-date-day-field-width` / `--lr-known-date-month-field-width` (default `--lr-size-3-5em`)
6592
7686
  and `--lr-known-date-year-field-width` (default `--lr-size-5em`) — the per-field input widths, not
6593
- size-scaled.
7687
+ size-scaled. `--lr-known-date-invalid-border-color` (default `var(--lr-color-danger)`) — border
7688
+ color of each `field-input` while `:host([data-invalid])` is set. Component-scoped indirection over
7689
+ the shared `--lr-color-danger` token, so a consumer can retheme just this invalid-field border
7690
+ without repainting every other component that reads the same shared danger token.
7691
+
7692
+ The two height knobs work as a pair on `[part='field-input']`, the same way
7693
+ `lr-input`/`lr-select`/`lr-combobox`/`lr-date-input` expose theirs:
7694
+
7695
+ - `--lr-known-date-field-min-height` is a **floor**, re-assigned per `size` tier. Every tier's
7696
+ default sits below the field's own padding/font-driven height, so raising it is what makes it
7697
+ visible; lowering it changes nothing.
7698
+ - `--lr-known-date-field-height` pins an **exact** height (both floors and caps), so the three
7699
+ inputs can line up with a neighbouring control of a known height. It is **undeclared by
7700
+ default** — the field grows to fit its content. Never set it to `auto`: `auto` is a valid
7701
+ declared value that wins over the `var()` fallback arm, which would make the per-tier floor
7702
+ dead code. To go back to the default behavior, remove the declaration rather than neutralizing
7703
+ it. Because the component never declares it, it can be set inline, from an ancestor, or from an
7704
+ outer-tree rule.
6594
7705
 
6595
7706
  **Known gotchas:**
6596
7707
  - Field *order* is derived from the locale by formatting a probe date (Jan 2 2026) with
@@ -6727,7 +7838,17 @@ label switches to Done on the last step).
6727
7838
  `--lr-tour-spotlight-radius` (default `--lr-radius` — shared by the cutout and the ring),
6728
7839
  `--lr-tour-spotlight-ring-color` (default `--lr-color-brand`), `--lr-tour-spotlight-ring-width`
6729
7840
  (default `--lr-border-width-medium`), `--lr-tour-popover-max-width` (default `--lr-size-22rem`,
6730
- further capped by `92vw` and the positioner's available space).
7841
+ further capped by `--lr-popover-viewport-clamp` and the positioner's available space),
7842
+ `--lr-tour-progress-dot-current-bg` (default `var(--lr-color-brand)`) — background of
7843
+ `progress-dot` for the current step. Component-scoped indirection over the shared `--lr-color-brand`
7844
+ token, so a consumer can retheme just the current-step dot without repainting every other component
7845
+ that reuses the same shared brand token.
7846
+
7847
+ `--lr-popover-viewport-clamp` (default `92vw`, from `--lr-theme-popover-viewport-clamp`) is the
7848
+ shared ceiling that keeps any floating surface inside a narrow viewport. `lr-tour`,
7849
+ `lr-mention-popover`, and `lr-export-button` all `min()` their own max-inline-size against it, so
7850
+ retuning `--lr-theme-popover-viewport-clamp` once at `:root` narrows or widens all three together
7851
+ rather than per component.
6731
7852
 
6732
7853
  **Known gotchas:**
6733
7854
  - By default the spotlighted target is **non-interactive**: it stays visible and announceable (not
@@ -6800,7 +7921,45 @@ installed, renders an empty template (see gotchas).
6800
7921
  Also exported from the package root:
6801
7922
  `languageToCountry(language: string): string | undefined` and the `LANGUAGE_TO_COUNTRY` lookup
6802
7923
  table (region subtag wins, e.g. `en-US` → `us`; plain `en` → `gb`; override the table per-app if you
6803
- need different defaults).
7924
+ need different defaults), plus `localeNativeName(tag: string): string`.
7925
+
7926
+ `localeNativeName()` returns a BCP-47 tag's **endonym** — the locale's name written in that locale
7927
+ itself (`'fr'` → `français`, `'pt-BR'` → `português (Brasil)`). That is what a language switcher
7928
+ should list, so a reader who understands none of the current UI language can still find their own.
7929
+ It derives from `Intl.DisplayNames`, so no name table ships with the library and results follow the
7930
+ browser's own ICU data; the underlying instance comes from a shared memoized cache, since a picker
7931
+ does one lookup per offered locale on every render pass. A tag with no display name resolves to the
7932
+ tag itself, and so does a structurally invalid one — `Intl.DisplayNames` throws a `RangeError` on
7933
+ those rather than falling back, and a language picker should degrade to showing the raw tag rather
7934
+ than tearing down the render. Pair it with `languageToCountry()` for the flag half of the same row.
7935
+
7936
+ **Locale picker recipe.** A locale picker is a composition, not a component: `<lr-popover>` supplies
7937
+ the light-dismiss surface, `<lr-flag>` the country mark, `localeNativeName()` the endonym, and
7938
+ `aria-current="true"` marks the active choice. Which locales exist is the app's decision, so the app
7939
+ owns the list. Set `lang` on each row so assistive tech pronounces the endonym in its own language,
7940
+ and use `variant="compact"` at icon scale.
7941
+
7942
+ ```html
7943
+ <lr-popover placement="bottom-start">
7944
+ <button slot="trigger">
7945
+ <lr-flag language="fr" label="" style="height: 1rem"></lr-flag>
7946
+ <span>français</span>
7947
+ </button>
7948
+ <ul role="list">
7949
+ <!-- one <li><button lang="pt-BR" aria-current="false"> … </button></li> per offered locale -->
7950
+ </ul>
7951
+ </lr-popover>
7952
+ ```
7953
+
7954
+ ```js
7955
+ import { localeNativeName, languageToCountry } from '@aceshooting/lyra-ui';
7956
+
7957
+ const rows = ['en', 'fr', 'de', 'pt-BR', 'ja', 'ar'].map((tag) => ({
7958
+ tag,
7959
+ name: localeNativeName(tag), // endonym, e.g. "português (Brasil)"
7960
+ country: languageToCountry(tag), // flag code for the same row
7961
+ }));
7962
+ ```
6804
7963
 
6805
7964
  ```html
6806
7965
  <lr-flag country="fr" label="France"></lr-flag>
@@ -6982,7 +8141,9 @@ exists and was hit)
6982
8141
 
6983
8142
  **Slots:** none.
6984
8143
 
6985
- **CSS parts:** `base`, `container`, `legend`, `legend-swatch`
8144
+ **CSS parts:** `base`, `container`, `legend`, `legend-swatch`, `error` (`role="alert"` message
8145
+ rendered in place of `container` if the optional `maplibre-gl` peer dependency fails to load, e.g.
8146
+ not installed)
6986
8147
 
6987
8148
  **Themeable custom properties:** shared tokens only — `--lr-space-xs/-s`, `--lr-color-surface`,
6988
8149
  `--lr-color-border`, `--lr-shadow`, `--lr-radius`.
@@ -7059,6 +8220,10 @@ parsing (that's left entirely to the host).
7059
8220
  - `maxFileSize: number = 0` (attribute `max-file-size` — bytes; `0` disables the check)
7060
8221
  - `directory: boolean = false` (reflected) — enables native directory selection where supported
7061
8222
  - `paste: boolean = true` (reflected) — accepts files pasted into the dropzone
8223
+ - `compact: boolean = false` (reflected) — tighter dropzone padding, gap and label font for
8224
+ constrained spaces (a toolbar, a table cell) — the same convention as `lr-empty`'s `compact`. The
8225
+ dashed border stays; only the internal spacing shrinks. `false` (the default) keeps the full
8226
+ `--lr-space-l` dropzone.
7062
8227
  - `label: string = 'Drop files here or click to browse'`
7063
8228
  - `accessibleLabel: string = ''` (attribute `aria-label`) — overrides `label` as the internal
7064
8229
  dropzone/button accessible name without changing visible copy
@@ -7085,9 +8250,22 @@ announces correctly.
7085
8250
  **CSS parts:** `base`, `input`, `status` (a visually-hidden `role="status" aria-live="polite"`
7086
8251
  element carrying the drag accept/reject announcement)
7087
8252
 
7088
- **Themeable custom properties:** shared tokens only — `--lr-space-xs`, `--lr-space-l`,
8253
+ **Themeable custom properties:** `--lr-file-input-compact-padding` (default `var(--lr-space-s)`) —
8254
+ `[part='base']`'s padding while `compact`; `--lr-file-input-compact-gap` (default
8255
+ `var(--lr-space-2xs)`) — the gap between the dropzone's slotted children while `compact`; and
8256
+ `--lr-file-input-compact-font-size` (default `var(--lr-font-size-sm)`) — the label's font size while
8257
+ `compact`. All three apply only while `compact` is set, so they are the way to tune a dense dropzone
8258
+ without re-pointing shared spacing tokens for everything else on the page. The drag accept/reject
8259
+ highlight on `[part='base'][data-drag-state='accept'|'reject']` is independently overridable too:
8260
+ `--lr-file-input-accept-border-color` (default `var(--lr-color-success)`) and
8261
+ `--lr-file-input-accept-bg` (default `color-mix(in srgb, var(--lr-color-success) 8%, transparent)`)
8262
+ for the drag-accept state; `--lr-file-input-reject-border-color` (default `var(--lr-color-danger)`)
8263
+ and `--lr-file-input-reject-bg` (default `color-mix(in srgb, var(--lr-color-danger) 8%,
8264
+ transparent)`) for drag-reject. All four are inline `var()` fallbacks at the point of use, settable
8265
+ on the element or any ancestor, so a consumer can retint just this dropzone's drag highlight without
8266
+ hijacking the shared `--lr-color-success`/`--lr-color-danger` tokens used elsewhere. Plus shared
8267
+ tokens — `--lr-space-xs`, `--lr-space-l`,
7089
8268
  `--lr-color-border`, `--lr-radius`, `--lr-color-surface`, `--lr-color-text-quiet`,
7090
- `--lr-color-success` (drag-accept state), `--lr-color-danger` (drag-reject state),
7091
8269
  `--lr-focus-ring-width/-color/-offset` (`[part="base"]:focus-visible` outline),
7092
8270
  `--lr-opacity-disabled` (`:host([disabled])` dimming).
7093
8271
 
@@ -7375,6 +8553,11 @@ final.
7375
8553
  overrides the `--lr-media-card-max-height` custom property for this instance only (applied
7376
8554
  inline on `[part="base"]`, so it reliably wins over a `:host{}`-declared default from outside the
7377
8555
  shadow root) — same contract as `<lr-document-preview>`'s identically-named prop.
8556
+ - `appearance: 'card' | 'plain' = 'card'` (reflected) — visual chrome, mirroring
8557
+ `<lr-source-card>`'s `appearance` vocabulary. `'card'` (the default) keeps the bordered, filled
8558
+ box. `'plain'` removes `[part="base"]`'s border, background, padding, and corner radius, so a
8559
+ card inside a dense chat transcript (or any container already drawing its own separation between
8560
+ attachments) doesn't double the frame.
7378
8561
 
7379
8562
  **Events:** `lr-open` (`detail: { src: string; filename: string }`, cancelable) — fired when the
7380
8563
  card (or, for `kind="video"`, its separate `open-button`) is activated. `detail.src` is whichever
@@ -7564,8 +8747,12 @@ initials text, rendered whenever neither `icon` nor `image` is).
7564
8747
  **Themeable custom properties:** `--lr-avatar-size` (default `2rem`, swapped to `1.5rem`/`2.5rem`
7565
8748
  per `size="sm"`/`"lg"`), `--lr-avatar-bg` (default `var(--lr-color-surface-alt,
7566
8749
  var(--lr-color-border))`, swapped per `tone`), `--lr-avatar-color` (default
7567
- `var(--lr-color-text)`, swapped per `tone`), plus shared tokens `--lr-radius`/`-pill`,
7568
- `--lr-font-size-sm`, `--lr-font-weight-semibold`.
8750
+ `var(--lr-color-text)`, swapped per `tone`), `--lr-avatar-font-size` (default
8751
+ `var(--lr-font-size-sm)`) — the font size of the initials fallback, and of any `em`-sized slotted
8752
+ glyph. `size` swaps it per tier too (`var(--lr-font-size-xs)` at `sm`, `var(--lr-font-size-md)` at
8753
+ `lg`), so the initials track the circle instead of staying one fixed size across every tier;
8754
+ override it on the element for a size the built-in scale doesn't cover. Plus shared tokens
8755
+ `--lr-radius`/`-pill`, `--lr-font-size-sm`, `--lr-font-weight-semibold`.
7569
8756
 
7570
8757
  **Optional peer deps:** none.
7571
8758
 
@@ -7735,7 +8922,12 @@ under `dir="rtl"` — setting `0` or a positive length turns the stack into norm
7735
8922
  `--lr-avatar-group-ring-color` (default `var(--lr-color-surface)`),
7736
8923
  `--lr-avatar-group-ring-width` (default `var(--lr-border-width-medium)`),
7737
8924
  `--lr-avatar-group-badge-bg` (default `var(--lr-color-border)`, swapped per `tone`),
7738
- `--lr-avatar-group-badge-color` (default `var(--lr-color-text)`, swapped per `tone`).
8925
+ `--lr-avatar-group-badge-color` (default `var(--lr-color-text)`, swapped per `tone`),
8926
+ `--lr-avatar-group-badge-font-size` (default `var(--lr-font-size-sm)`) — the font size of the "+N"
8927
+ badge label. `size` swaps it per tier (`var(--lr-font-size-xs)` at `sm`, `var(--lr-font-size-md)` at
8928
+ `lg`), matching `<lr-avatar>`'s own `--lr-avatar-font-size` scale so the badge and the avatars it
8929
+ caps read at the same optical weight; override it alongside `--lr-avatar-font-size` on the avatars
8930
+ themselves when tuning a custom tier.
7739
8931
 
7740
8932
  **Optional peer deps:** none.
7741
8933
 
@@ -7843,7 +9035,12 @@ documents) and `<lr-image-comparer>` (before/after slotted surfaces). Adopts `Do
7843
9035
  with `anchorKinds: ['region']` only — no text selection is bound.
7844
9036
 
7845
9037
  **Properties:** `src: string = ''`, `name: string = ''`, `alt?: string`, `fit: 'contain' | 'width' |
7846
- 'actual' = 'contain'` (reflected), `zoom: number = 1` (reflected), `rotation: 0 | 90 | 180 | 270 = 0`
9038
+ 'actual' = 'contain'` (reflected), `zoom: number = 1` (reflected), `minZoom: number = 0.5` (attribute
9039
+ `min-zoom`), `maxZoom: number = 4` (attribute `max-zoom`), `zoomStep: number = 0.25` (attribute
9040
+ `zoom-step`) — `minZoom`/`maxZoom`/`zoomStep` are pure pass-throughs to the embedded
9041
+ `<lr-zoomable-frame>` as its own `.minZoom`/`.maxZoom`/`.zoomStep`, which does the actual
9042
+ clamping/normalizing; same names/defaults as `<lr-lightbox>`'s identical trio, both wrapping the
9043
+ same pan/zoom surface — `rotation: 0 | 90 | 180 | 270 = 0`
7847
9044
  (reflected), and `annotatable: boolean = false` (reflected).
7848
9045
 
7849
9046
  **Methods:** `rotate()` advances `rotation` by 90°. `zoomIn()`, `zoomOut()`, and `resetZoom()` adjust
@@ -7859,6 +9056,20 @@ zoom }`), `lr-rotation-change` (`detail: { rotation }`), `lr-fit-change` (`detai
7859
9056
  embedded `lr-zoomable-frame`), `image-wrapper`, `image`, `highlight-layer`, `highlight` (carries
7860
9057
  `data-tone`/`data-active`), `highlight-label`, `annotation-box`, and `error`.
7861
9058
 
9059
+ **Themeable custom properties:** `--lr-image-viewer-annotate-active-bg` (default
9060
+ `var(--lr-color-brand-quiet)`) and `--lr-image-viewer-annotate-active-border` (default
9061
+ `var(--lr-color-brand)`) — the background and border of `[part='annotate-toggle']` while annotation
9062
+ mode is on. The toggle carries its own glyph in `--lr-color-text`, so keep a 4.5:1 ratio against it
9063
+ when overriding the background. `--lr-image-viewer-highlight-active-color` (default
9064
+ `var(--lr-color-brand)`) — the outline of the `[part='highlight']` matching `activeHighlightId`,
9065
+ independent of the per-tone border colors, so the active box stays distinguishable whatever tone it
9066
+ carries. All three are declared as inline `var()` fallbacks at the point of use rather than on
9067
+ `:host`, so each can be set on the element *or on any ancestor*: `::part(highlight)[data-active]` is
9068
+ invalid CSS — Shadow Parts forbids an attribute selector after `::part()` — which previously left
9069
+ overriding the library-wide `--lr-color-brand`/`--lr-color-brand-quiet` tokens as the only lever,
9070
+ repainting every other element that read them. Unset, each falls back to the token its rule used
9071
+ before.
9072
+
7862
9073
  ## `lr-av-player`
7863
9074
 
7864
9075
  An audio/video player built on a native `<audio>`/`<video>` element, plus a cue transcript synced to
@@ -7892,11 +9103,47 @@ found }`), `lr-search-change` (`detail: { query, matchCount, activeIndex }`), an
7892
9103
  **CSS parts:** `base`, `media` (the native `<audio>`/`<video>` element), `toolbar`, `rate-select`,
7893
9104
  `timeline` (click-to-seek and arrow-key seeking), `timeline-marker` (one per `time-range` highlight;
7894
9105
  `data-tone`, `data-active`), `transcript` (the `<lr-virtual-list>` itself), `cue` (`aria-current`,
7895
- `data-match`, `data-active-match`), `cue-time`, `cue-speaker`, `cue-text`, and `error`.
9106
+ `data-match`, `data-active-match`), `cue-current` (added alongside `cue` on the row the playhead is
9107
+ inside), `cue-match` (added alongside `cue` on a row matching the current search query),
9108
+ `cue-active-match` (added alongside `cue`/`cue-match` on the row holding the current match),
9109
+ `cue-time`, `cue-speaker`, `cue-text`, and `error`.
9110
+
9111
+ Every cue-level part above is rendered into the embedded `<lr-virtual-list>`'s own shadow root and
9112
+ forwarded back out through `exportparts`, so `lr-av-player::part(cue)` and friends work from a
9113
+ consumer stylesheet. The three cue states are separate part *names* rather than attribute selectors,
9114
+ because Shadow Parts forbids an attribute selector after `::part()` —
9115
+ `::part(cue)[aria-current='true']` is invalid CSS, so use `::part(cue-current)`. The `aria-current`
9116
+ and `data-*` attributes remain on each row for semantics and scripting.
7896
9117
 
7897
9118
  **Themeable custom properties:** `--lr-av-player-transcript-height` (default
7898
9119
  `var(--lr-size-16rem)` — block size of the transcript pane; forwarded to the embedded
7899
- `<lr-virtual-list>`'s own `--lr-virtual-list-height`).
9120
+ `<lr-virtual-list>`'s own `--lr-virtual-list-height`). `--lr-av-player-marker-active-color` (default
9121
+ `var(--lr-color-brand)`) — the outline of the `[part='timeline-marker']` matching
9122
+ `activeHighlightId`, leaving the per-tone marker fills alone. It is an inline `var()` fallback at
9123
+ the point of use rather than a `:host` declaration, so it can be set on the element or on any
9124
+ ancestor — `::part(timeline-marker)[data-active]` is invalid CSS (Shadow Parts forbids an attribute
9125
+ selector after `::part()`), so re-pointing the shared `--lr-color-brand` token was the only previous
9126
+ lever.
9127
+
9128
+ Each `[part='timeline-marker']`'s own background is independently overridable per tone, the same
9129
+ inline-`var()`-fallback pattern as `--lr-av-player-marker-active-color` above:
9130
+ `--lr-av-player-marker-bg` (default `color-mix(in srgb, var(--lr-color-brand) 35%, transparent)`) —
9131
+ no (or an unrecognized) `data-tone`; `--lr-av-player-marker-success-bg` (default `color-mix(in srgb,
9132
+ var(--lr-color-success) 35%, transparent)`) — `data-tone="success"`;
9133
+ `--lr-av-player-marker-warning-bg` (default `color-mix(in srgb, var(--lr-color-warning) 35%,
9134
+ transparent)`) — `data-tone="warning"`; `--lr-av-player-marker-danger-bg` (default `color-mix(in
9135
+ srgb, var(--lr-color-danger) 35%, transparent)`) — `data-tone="danger"`; and
9136
+ `--lr-av-player-marker-neutral-bg` (default `color-mix(in srgb, var(--lr-color-text) 25%,
9137
+ transparent)`) — `data-tone="neutral"`. Each can be set on the element or on any ancestor without
9138
+ hijacking the shared `--lr-color-success`/`-warning`/`-danger`/`-brand`/`-text` tokens used
9139
+ elsewhere in the theme.
9140
+
9141
+ Two further cue-state properties tint the transcript: `--lr-av-player-cue-current-bg` (default
9142
+ `var(--lr-color-brand-quiet)`) is the background of the `cue-current` row the playhead is inside,
9143
+ and `--lr-av-player-cue-active-match-color` (default `var(--lr-color-warning)`) is the outline of
9144
+ the `cue-active-match` row, leaving the other matches' dashed outline on the shared warning token.
9145
+ Both are inline `var()` fallbacks at the point of use rather than `:host` declarations, so either
9146
+ can be set on the element or on any ancestor.
7900
9147
 
7901
9148
  # Charts (`components/charts/`)
7902
9149
 
@@ -7963,7 +9210,8 @@ number, label: string | undefined, value: unknown }`)
7963
9210
  optional overlay content positioned at the chart area's center, useful for doughnut and pie totals.
7964
9211
 
7965
9212
  **CSS parts:** `base`, `canvas`, `reset-zoom-button`, `description`, `data-table`, `center` (the
7966
- chart-area-centered wrapper for the `center` slot)
9213
+ chart-area-centered wrapper for the `center` slot), `error` (`role="alert"` message rendered in
9214
+ place of `canvas` when the optional `chart.js` peer dependency fails to load)
7967
9215
 
7968
9216
  **Themeable custom properties:** `--lr-chart-height` (set programmatically on the host from the
7969
9217
  `height` property — must be read from the host, not a shadow-tree descendant, since custom
@@ -8196,7 +9444,9 @@ index, label, value }`).
8196
9444
 
8197
9445
  **Slots:** `data-table`, `center`.
8198
9446
 
8199
- **CSS parts:** `base`, `canvas`, `reset-zoom-button`, `description`, `data-table`, `center`.
9447
+ **CSS parts:** `base`, `canvas`, `reset-zoom-button`, `description`, `data-table`, `center`,
9448
+ `error` (`role="alert"` message rendered in place of `canvas` when the optional `chart.js` peer
9449
+ dependency fails to load — see `llms/components/lr-chart.md`).
8200
9450
 
8201
9451
  **Themeable custom properties:** `--lr-chart-height`, `--lr-chart-grid-color`,
8202
9452
  `--lr-chart-tick-color`, `--lr-chart-legend-color`, `--lr-chart-tooltip-bg`,
@@ -8257,7 +9507,9 @@ and `label` the generated bucket range string (`"lo–hi"`, both bounds at one d
8257
9507
 
8258
9508
  **Slots:** `data-table`, `center`.
8259
9509
 
8260
- **CSS parts:** `base`, `canvas`, `reset-zoom-button`, `description`, `data-table`, `center`.
9510
+ **CSS parts:** `base`, `canvas`, `reset-zoom-button`, `description`, `data-table`, `center`,
9511
+ `error` (`role="alert"` message rendered in place of `canvas` when the optional `chart.js` peer
9512
+ dependency fails to load — inherited from `LyraChart`, unaffected by the binning logic).
8261
9513
 
8262
9514
  **Themeable custom properties:** `--lr-chart-height`, `--lr-chart-grid-color`,
8263
9515
  `--lr-chart-tick-color`, `--lr-chart-legend-color`, `--lr-chart-tooltip-bg`,
@@ -8445,7 +9697,15 @@ SFMono-Regular, Menlo, Consolas, monospace`) and `--lr-document-preview-spin-dur
8445
9697
  `0.8s`, stopped under reduced motion). `--lr-document-preview-progress` (default `0`) — a unitless
8446
9698
  0–100 number the determinate spinner's `conic-gradient` fill reads; written inline on the ring by
8447
9699
  the component itself from the clamped `progress` property, so overriding it only makes sense to
8448
- repaint the fraction. Plus shared tokens
9700
+ repaint the fraction. `--lr-document-preview-active-border` (default
9701
+ `var(--lr-color-warning, var(--lr-color-brand))`) — the border color of the `[part='region-highlight']`
9702
+ matching `activeHighlightId` (image format only), deliberately distinct from the resting highlight
9703
+ border so the active region can be recolored without touching the rest. Like the library's other
9704
+ state hooks it is an inline `var()` fallback at the point of use rather than a `:host` declaration,
9705
+ so it can be set on the element or on any ancestor — `::part(region-highlight)[data-active]` is
9706
+ invalid CSS (Shadow Parts forbids an attribute selector after `::part()`), which previously left
9707
+ re-pointing the shared `--lr-color-warning`/`--lr-color-brand` tokens as the only lever, repainting
9708
+ every other element that read them. Plus shared tokens
8449
9709
  `--lr-color-border`, `--lr-radius`, `--lr-color-surface`, `--lr-space-s/-m/-l/-xs`,
8450
9710
  `--lr-color-text`, `--lr-color-text-quiet`, `--lr-color-danger`, `--lr-color-brand`,
8451
9711
  `--lr-color-on-brand`, `--lr-focus-ring-width/-color/-offset`, `--lr-transition-fast`.
@@ -8661,9 +9921,10 @@ localized show/hide toggle. `false` (the default) preserves the full body render
8661
9921
  **CSS parts:** `base`, `headers`, `from-label`, `from`, `to-label`, `to`, `subject-label`, `subject`,
8662
9922
  `date-label`, `date`, `body`, `body-html`, `body-text`, `attachments`, `attachments-label`,
8663
9923
  `attachment-list`, `attachment-item`, `attachment-button` (an attachment's open button, inside its
8664
- `attachment-item`), `quoted` (a folded quoted-text block, hidden until expanded, only
8665
- while `foldQuotes`), `quote-toggle` (the show/hide-quoted-text toggle button, only while `foldQuotes`),
8666
- `spinner`, and `error`.
9924
+ `attachment-item`), `attachment-name` (an attachment's filename, inside `attachment-button`),
9925
+ `attachment-size` (an attachment's formatted file size, inside `attachment-button`), `quoted` (a
9926
+ folded quoted-text block, hidden until expanded, only while `foldQuotes`), `quote-toggle` (the
9927
+ show/hide-quoted-text toggle button, only while `foldQuotes`), `spinner`, and `error`.
8667
9928
 
8668
9929
  **Themeable custom properties:** `--lr-email-viewer-max-height` (default `none`) — maximum block size
8669
9930
  of `[part="body"]`; also settable via the `max-height` property, which writes this token inline.
@@ -8710,7 +9971,13 @@ listing region as `role="region"`; with neither set, the region is unnamed.
8710
9971
 
8711
9972
  **Events:** `lr-render-error` with `detail.error` when fetching or parsing fails.
8712
9973
 
8713
- **CSS parts:** `base`, `entry`, `entry-icon`, `entry-name`, `entry-size`, `spinner`, and `error`.
9974
+ **CSS parts:** `base`, `entry`, `entry-icon`, `entry-name`, `entry-name-dir`, `entry-size`,
9975
+ `spinner`, and `error`. A directory row's name element carries both `entry-name` and
9976
+ `entry-name-dir` (a part list), so `::part(entry-name-dir)` selects only directory names while
9977
+ `::part(entry-name)` still selects every name. Entry rows are rendered into the embedded
9978
+ `<lr-virtual-list>`'s own shadow root and forwarded with `exportparts`, so
9979
+ `lr-archive-viewer::part(entry)` (and every other row part above) reaches them from a consuming
9980
+ stylesheet.
8714
9981
 
8715
9982
  **Exports:** `ArchiveEntry` — `{ name: string; dir: boolean; size: number }`.
8716
9983
 
@@ -8825,6 +10092,14 @@ rendered region highlight), `region-highlight` (one region highlight, `data-tone
8825
10092
 
8826
10093
  **Themeable custom properties:** `--lr-svg-viewer-max-height` (default `none`) — maximum block size
8827
10094
  of `[part="body"]`; also settable via the `max-height` property, which writes this token inline.
10095
+ `--lr-svg-viewer-active-border` (default `var(--lr-color-warning, var(--lr-color-brand))`) — the
10096
+ border color of the `[part='region-highlight']` matching `activeHighlightId`, distinct from the
10097
+ resting highlight border so the active region can be recolored without touching the rest. It is an
10098
+ inline `var()` fallback at the point of use rather than a `:host` declaration, so it can be set on
10099
+ the element *or on any ancestor*: `::part(region-highlight)[data-active]` is invalid CSS — Shadow
10100
+ Parts forbids an attribute selector after `::part()` — so re-pointing a shared `--lr-color-*` token,
10101
+ and repainting everything else reading it, was previously the only way. Unset, it falls back to
10102
+ exactly the tokens the rule used before.
8828
10103
 
8829
10104
  **Optional peer dependency:** `dompurify`.
8830
10105
 
@@ -8881,7 +10156,10 @@ Enter/Space. `lr-anchor-result` (`detail: { found }`) — fired after an `anchor
8881
10156
  **CSS parts:** `base`, `body`, `table`, `header-row`, `header-cell`, `data-row`, `cell`,
8882
10157
  `cell-highlight` (a `role="cell"` covered by a `highlights` entry; wraps the action button),
8883
10158
  `cell-highlight-action` (the native button filling a highlighted cell — focusable, emits
8884
- `lr-highlight-activate` on click or Enter/Space), `spinner`, and `error`.
10159
+ `lr-highlight-activate` on click or Enter/Space), `spinner`, and `error`. `data-row`, `cell`,
10160
+ `cell-highlight` and `cell-highlight-action` render inside the internal `<lr-virtual-list>` and are
10161
+ forwarded via `exportparts`, so `lr-dataset-viewer::part(cell)` reaches them from a consumer
10162
+ stylesheet.
8885
10163
 
8886
10164
  **Exports:** `DatasetTable` is `{ fields: string[]; rows: Record<string, string>[] }`.
8887
10165
 
@@ -8937,8 +10215,11 @@ drag* over a highlighted passage never activates it — the selection-in-progres
8937
10215
  to tell that apart from a genuine activation click.
8938
10216
 
8939
10217
  **Properties:** `src` and `name` are strings. `page: number = 1` is the one-based current page and
8940
- `zoom: number = 1` is clamped to `0.25`–`4`. `anchorKinds` is a readonly `['page', 'text-quote',
8941
- 'region']` (this viewer's supported `LyraAnchor.kind` values for the shared anchor-target contract).
10218
+ `zoom: number = 1` is clamped to `0.25`–`4`. `maxHeight: string = ''` (attribute `max-height`) is a
10219
+ CSS length that, once set, overrides `--lr-pdf-viewer-height` the block size of the virtualized
10220
+ page list — declaratively, writing it inline on `[part="base"]`. `anchorKinds` is a readonly
10221
+ `['page', 'text-quote', 'region']` (this viewer's supported `LyraAnchor.kind` values for the shared
10222
+ anchor-target contract).
8942
10223
 
8943
10224
  **Events:**
8944
10225
  - `lr-render-error` — `detail: { error }` — fetching, parsing, or rendering (page canvas or text
@@ -8970,15 +10251,28 @@ table of contents as `PdfOutlineItem[]` (`{ title, page?, children? }`), `[]` wh
8970
10251
  `clearSearch()`); `searchNext()` and `searchPrevious()` advance/step back through matches (wrapping,
8971
10252
  resolving `false` when there are none); `clearSearch()` clears the query, matches, and painted marks.
8972
10253
 
8973
- **CSS parts:** `base`, `toolbar`, `page-indicator`, `zoom-indicator`, `pages`, `page`, `text-layer`,
8974
- `search-match` (a `<mark>` painted into a mounted page's text layer around one search match),
8975
- `search-match-active` (the currently active match, also carries `search-match`), `spinner`, and
8976
- `error`. Search painting is best-effort: a page outside the virtualized render window is skipped and
8977
- repainted once its text layer mounts, and a match spanning a text-layer span boundary that
8978
- `Range.surroundContents()` can't wrap stays unpainted (still reachable via `searchNext()`).
10254
+ **CSS parts:** `base`, `toolbar`, `page-indicator`, `zoom-indicator`, `pages`, `page`, `page-canvas`
10255
+ (the canvas one page's content is painted onto), `text-layer`, `text-span` (one generated text run
10256
+ inside a page's text layer PDF.js creates these imperatively, and they carry the part so a rule can
10257
+ reach them without a descendant combinator), `search-match` (a `<mark>` painted into a mounted page's
10258
+ text layer around one search match), `search-match-active` (the currently active match, also carries
10259
+ `search-match`), `spinner`, and `error`. Search painting is best-effort: a page outside the
10260
+ virtualized render window is skipped and repainted once its text layer mounts, and a match spanning a
10261
+ text-layer span boundary that `Range.surroundContents()` can't wrap stays unpainted (still reachable
10262
+ via `searchNext()`).
10263
+
10264
+ `page`, `page-canvas`, `text-layer`, `text-span`, `search-match` and `search-match-active` are
10265
+ rendered inside the virtualizing `lr-virtual-list`'s own shadow root and forwarded out through
10266
+ `exportparts`, so `lr-pdf-viewer::part(page)` (and each of the others) works from a consumer
10267
+ stylesheet exactly like the parts in this viewer's own shadow root. The selection tint over a page's
10268
+ text is styled on `text-span` rather than on `text-layer`, because a highlight pseudo-element is
10269
+ matched against the element the selected text originates in:
10270
+ `lr-pdf-viewer::part(text-span)::selection { background: … }`.
8979
10271
 
8980
10272
  **Themeable custom properties:** `--lr-pdf-viewer-height` (default `var(--lr-size-24rem)`) — block
8981
- size of the virtualized page list (`[part="pages"]`).
10273
+ size of the virtualized page list (`[part="pages"]`); also settable via the `maxHeight` property,
10274
+ which writes this token inline on `[part="base"]`. Everything below the page list is retuned
10275
+ through the exported parts above rather than through dedicated custom properties.
8982
10276
 
8983
10277
  **Optional peer dependency:** install `pdfjs-dist` with `pnpm add pdfjs-dist`. The component registers
8984
10278
  a lazy `application/pdf` renderer with `<lr-document-viewer>` so the PDF library is loaded only when
@@ -9016,7 +10310,16 @@ Enter/Space. `lr-anchor-result` (`detail: { found }`) — fired after an `anchor
9016
10310
  `search()`/`searchNext()`/`searchPrevious()`/`clearSearch()`.
9017
10311
 
9018
10312
  **CSS parts:** `base`, `tabs`, `sheet`, `header-row`, `data-row`, `cell`, `cell-highlight` (a cell
9019
- covered by a `highlights` entry), `rows`, `spinner`, and `error`.
10313
+ covered by a `highlights` entry), `rows`, `spinner`, and `error`. `data-row`, `cell` and
10314
+ `cell-highlight` are rendered inside the internal `<lr-virtual-list>` and forwarded via
10315
+ `exportparts`, so `lr-spreadsheet-viewer::part(cell)` reaches them from a consumer stylesheet.
10316
+
10317
+ **Themeable custom properties:** `--lr-spreadsheet-viewer-highlight-color` (default
10318
+ `var(--lr-color-brand)`) — the outline color of a `cell-highlight` cell. The component writes it
10319
+ inline (as `var(--lr-color-warning, var(--lr-color-brand))`) on the cell matching
10320
+ `activeHighlightId`, since a `[data-active]` selector can't be chained onto the
10321
+ `::part(cell-highlight)` the cell reaches this component's stylesheet through; a custom property
10322
+ inherits across that boundary instead.
9020
10323
 
9021
10324
  **Optional peer dependency:** install `xlsx` with `pnpm add https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz`. The official CDN matches the
9022
10325
  `.xlsx` and `.xls` MIME types and filename extensions.
@@ -9036,8 +10339,10 @@ row/column into view via the virtualized list's `active-id`. `highlights` paint
9036
10339
 
9037
10340
  **Properties:** `src` and `name` are strings. `hasHeaderRow: boolean = true` (attribute
9038
10341
  `has-header-row`) controls whether the first parsed row is rendered as a sticky header.
9039
- `anchorKinds` is a readonly `['cell-range']` (this viewer's supported `LyraAnchor.kind` values for
9040
- the shared anchor-target contract).
10342
+ `maxHeight: string = ''` (attribute `max-height`) is a CSS length that caps the scrollable body —
10343
+ setting it writes `--lr-csv-viewer-max-height` inline on `[part="base"]`. `anchorKinds` is a
10344
+ readonly `['cell-range']` (this viewer's supported `LyraAnchor.kind` values for the shared
10345
+ anchor-target contract).
9041
10346
 
9042
10347
  **Methods:** `search(query)` resolves the match count via a case-insensitive substring match over
9043
10348
  the same stringified cell values `cell()` renders, ordered row then column (empty/whitespace query
@@ -9052,7 +10357,18 @@ Enter/Space. `lr-anchor-result` (`detail: { found }`) — fired after an `anchor
9052
10357
  `search()`/`searchNext()`/`searchPrevious()`/`clearSearch()`.
9053
10358
 
9054
10359
  **CSS parts:** `base`, `sheet`, `header-row`, `data-row`, `cell`, `cell-highlight` (a cell covered by
9055
- a `highlights` entry), `rows`, `spinner`, and `error`.
10360
+ a `highlights` entry), `rows`, `spinner`, and `error`. `data-row`, `cell` and `cell-highlight` are
10361
+ rendered inside the internal `<lr-virtual-list>` and forwarded via `exportparts`, so
10362
+ `lr-csv-viewer::part(cell)` reaches them from a consumer stylesheet.
10363
+
10364
+ **Themeable custom properties:** `--lr-csv-viewer-max-height` (default `none`) — maximum block size
10365
+ of `[part="body"]` before it scrolls internally; also settable via the `maxHeight` property, which
10366
+ writes this token inline on `[part="base"]`. `--lr-csv-viewer-highlight-color` (default
10367
+ `var(--lr-color-brand)`) — the outline color of a `cell-highlight` cell. The component writes it
10368
+ inline (as `var(--lr-color-warning, var(--lr-color-brand))`) on the cell matching
10369
+ `activeHighlightId`, since a `[data-active]` selector can't be chained onto the
10370
+ `::part(cell-highlight)` the cell reaches this component's stylesheet through; a custom property
10371
+ inherits across that boundary instead.
9056
10372
 
9057
10373
  **Optional peer dependency:** install `papaparse` with `pnpm add papaparse`. The registry matches
9058
10374
  `text/csv` and `.csv` filenames.
@@ -9144,12 +10460,23 @@ truth.
9144
10460
  `detail: { page }`. In wired mode the rail also sets `viewer.page` itself.
9145
10461
 
9146
10462
  **CSS parts:** `base` (the rail), `pages` (the embedded `<lr-virtual-list>`), `page` (one page
9147
- button), `thumbnail` (the thumbnail canvas wrapper), `page-number` (the visible page number), `heat`
9148
- (the heat-marker cluster), and `heat-dot` (one tone-colored heat marker, or the `+n` overflow
10463
+ button), `page-current` (the button for the current `page`), `thumbnail` (the thumbnail canvas
10464
+ wrapper), `page-number` (the visible page number), `heat` (the heat-marker cluster), `heat-dot` (one
10465
+ heat marker), `heat-dot-accent`, `heat-dot-success`, `heat-dot-warning`, `heat-dot-danger` and
10466
+ `heat-dot-neutral` (the tone-specific name on each marker), and `heat-dot-overflow` (the `+n`
9149
10467
  marker).
9150
10468
 
10469
+ Page rows are rendered into the embedded `<lr-virtual-list>`'s own shadow root and forwarded with
10470
+ `exportparts`, so `lr-page-rail::part(page)` and the rest reach them from a consuming stylesheet.
10471
+ State variants each carry a second name in the element's part list rather than a state attribute,
10472
+ because `::part()` cannot be followed by an attribute selector: the current row is
10473
+ `part="page page-current"` and a danger marker is `part="heat-dot heat-dot-danger"`, and `::part()`
10474
+ matches with `part~=` semantics, so both names select the same element.
10475
+
9151
10476
  **Themeable custom properties:** `--lr-page-rail-height` (default `var(--lr-size-24rem)`) — block
9152
- size of the virtualized rail.
10477
+ size of the virtualized rail. `--lr-page-rail-current-bg` (default `var(--lr-color-brand-quiet)`) —
10478
+ background of the `page-current` button, kept while the row is hovered so the current page stays
10479
+ identifiable under the pointer.
9153
10480
 
9154
10481
  ## `lr-notebook-viewer`
9155
10482
 
@@ -9187,11 +10514,26 @@ activeIndex }`. `lr-render-error` — `detail: { error }`, fetching, parsing, or
9187
10514
  notebook failed.
9188
10515
 
9189
10516
  **CSS parts:** `base` (the root scroll container), `cell` (`data-cell-type="code|markdown|raw"`,
9190
- `data-active`), `cell-gutter` (the `In [n]`/`Out [n]` label column), `cell-source`, `outputs`,
9191
- `output` (`data-output-type`, `data-stream`), `output-toggle`, `error`, `spinner`.
10517
+ `data-active`), `cell-active` (added alongside `cell` on the cell an anchor currently targets),
10518
+ `cell-gutter` (the `In [n]`/`Out [n]` label column), `cell-source`, `outputs`, `output`
10519
+ (`data-output-type`, `data-stream`), `output-error` (added alongside `output` on a stderr stream or
10520
+ an error output), `error-output-label` (the label introducing an error output's traceback),
10521
+ `output-toggle`, `error`, `spinner`.
10522
+
10523
+ Every cell-level part above is rendered into the embedded `<lr-virtual-list>`'s own shadow root and
10524
+ forwarded back out through `exportparts`, so `lr-notebook-viewer::part(cell)` and friends work from
10525
+ a consumer stylesheet. The three state variants are separate part *names* rather than attribute
10526
+ selectors, because Shadow Parts forbids an attribute selector after `::part()` —
10527
+ `::part(cell)[data-active]` is invalid CSS, so use `::part(cell-active)`. The `data-*` attributes
10528
+ remain on the elements for scripting.
9192
10529
 
9193
10530
  **Themeable custom properties:** `--lr-notebook-viewer-max-height` (default `none`).
9194
10531
 
10532
+ `--lr-notebook-viewer-active-bg` (default `var(--lr-color-brand-quiet)`) is the background of the
10533
+ cell currently targeted by an anchor — the `cell-active` part. It is an inline `var()` fallback at
10534
+ the point of use rather than a `:host` declaration, so it can be set on the element or on any
10535
+ ancestor.
10536
+
9195
10537
  **Optional peer deps:** `marked`+`dompurify` (markdown cells, falls back to plain text per cell),
9196
10538
  `shiki` (code cells, falls back to unhighlighted), `dompurify` (HTML/SVG outputs, falls back to
9197
10539
  `text/plain`).
@@ -9241,7 +10583,30 @@ the resolved anchor target, `data-match`, `data-active-match`), `tag` (`data-mat
9241
10583
  `toggle` (an element's expand/collapse button, hidden but present for row alignment on leaf/empty
9242
10584
  elements), `error`, `spinner`.
9243
10585
 
9244
- **Themeable custom properties:** `--lr-xml-viewer-max-height` (default `none`).
10586
+ **Themeable custom properties:** `--lr-xml-viewer-max-height` (default `none`) — maximum block size
10587
+ of the scrollable body; also settable via the `max-height` property.
10588
+ `--lr-xml-viewer-active-match-color` (default `var(--lr-color-warning)`) — the solid outline on the
10589
+ `[part='node']` holding the *current* search match, leaving every other match on its dashed
10590
+ `--lr-xml-viewer-match-color` outline. It is an inline `var()` fallback at the point of use rather
10591
+ than a `:host` declaration, so it can be set on the element *or on any ancestor*:
10592
+ `::part(node)[data-active-match]` is invalid CSS — Shadow Parts forbids an attribute selector after
10593
+ `::part()` — so distinguishing the active match previously meant re-pointing the shared
10594
+ `--lr-color-warning` token, which recolored every other match (and every other warning surface)
10595
+ along with it. Unset, it falls back to that token, so rendering is unchanged.
10596
+
10597
+ `--lr-xml-viewer-match-color` (default `var(--lr-color-warning)`) — outline color of a non-active
10598
+ `[part='node']` search match, and (via `color-mix`) the tint source for a matching `[part='text']`'s
10599
+ background — kept distinct from `--lr-xml-viewer-active-match-color` so the non-active matches can
10600
+ be recolored without touching the active one. `--lr-xml-viewer-match-bg` (default
10601
+ `var(--lr-color-warning-quiet)`) — background of a matching `[part='tag']`/`[part='attribute-value']`.
10602
+ Both are inline `var()` fallbacks at the point of use, so either can be set on the element or any
10603
+ ancestor; unset, they fall back to the same shared tokens the rules used before.
10604
+
10605
+ `[part='toggle']`'s glyph box stays compact (`1.25rem`) while its *interactive* box takes the shared
10606
+ minimum target size as a floor via `--lr-icon-button-size`. That token is a floor, not a fixed size,
10607
+ so lowering it never squashes the chevron below its own box — the visible glyph keeps its size while
10608
+ the hit target follows the token, and it can never fall under the accessible minimum from this
10609
+ component's own rules.
9245
10610
 
9246
10611
  ```html
9247
10612
  <lr-xml-viewer .xml=${payload} collapsed-depth="2" copyable
@@ -9401,7 +10766,8 @@ carrying `data-display="inline"|"block"`)
9401
10766
 
9402
10767
  **Themeable custom properties:** `--lr-markdown-font-mono` (default `ui-monospace, SFMono-Regular,
9403
10768
  Menlo, Consolas, monospace` — the code/code-block font; component-specific since no shared
9404
- `--lr-*` monospace token exists), plus shared tokens `--lr-space-xs/-s/-m/-l`,
10769
+ `--lr-*` monospace token exists), `--lr-code-block-tab-size` (default `2` — tab width inside a
10770
+ rendered fenced or indented `code-block`), plus shared tokens `--lr-space-xs/-s/-m/-l`,
9405
10771
  `--lr-color-brand-quiet`, `--lr-color-brand`, `--lr-color-border`, `--lr-color-text-quiet`,
9406
10772
  `--lr-radius`.
9407
10773
 
@@ -9437,6 +10803,17 @@ cleared in `updated()` based on whether the deps have loaded) and shows the same
9437
10803
  rendering — there's no separate loading skeleton, since the un-rendered Markdown source is already
9438
10804
  legible text in the meantime.
9439
10805
 
10806
+ **One tab width for every code surface.** `--lr-code-block-tab-size` is deliberately the same
10807
+ property name and default (`2`) that `<lr-code-block>` and `<lr-code-editor>` use, so a consumer sets
10808
+ tab width once for every code surface in the app. It is declared as a `var()` fallback **at the point
10809
+ of use, never on `:host`** — a `:host` declaration is re-stamped on every instance and shadows any
10810
+ inherited value, so a page- or container-level declaration could never reach it. This element carries
10811
+ its own copy of that fallback rather than inheriting `<lr-code-block>`'s because the two are
10812
+ **sibling** custom elements, not ancestor and descendant: no single declaration inside one of them
10813
+ can cover the other. The same value can still *look* different between the two — a markdown code
10814
+ block inherits `white-space: pre-wrap` while `<lr-code-block>` is `white-space: pre`, and tab stops
10815
+ restart at the beginning of each visual line, so a wrapped line's tabs land differently.
10816
+
9440
10817
  **Known gotchas:**
9441
10818
  - a malformed percent-escape or lone UTF-16 surrogate in a link's raw `href` makes the internal
9442
10819
  `encodeURI`-based validity guard throw, silently dropping just that anchor (the link text still
@@ -9499,6 +10876,15 @@ unhighlighted permanently, `headingAnchors: boolean = false` (attribute `heading
9499
10876
  **CSS parts:** `content`, `heading`, `paragraph`, `list`, `code-block`, `inline-code`, `link`,
9500
10877
  `table`, `blockquote`, `img`, `math` — identical to `<lr-markdown>`'s own parts.
9501
10878
 
10879
+ **Themeable custom properties:** `--lr-code-block-tab-size` (default `2` — tab width inside a
10880
+ rendered fenced or indented `code-block`), with exactly the mechanics described under
10881
+ `<lr-markdown>` above: the same property name and default that `<lr-code-block>`/`<lr-code-editor>`
10882
+ read, declared as a `var()` fallback at the point of use rather than on `:host` so a page- or
10883
+ container-level value reaches it, and carried here in its own right because this element is a
10884
+ **sibling** of `<lr-code-block>` rather than an ancestor of it. Markdown code blocks wrap
10885
+ (`white-space: pre-wrap`) while `<lr-code-block>` does not, so the same tab width can render
10886
+ differently on a wrapped line.
10887
+
9502
10888
  **Optional peer deps:** `marked`, `dompurify` (both lazy-loaded, same as `<lr-markdown>`), `katex`
9503
10889
  (for `math`). Does *not* depend on the full `shiki` package's default entry point — only
9504
10890
  `shiki/core`/`shiki/engine/oniguruma`/`shiki/langs/*`, the same fine-grained subset
@@ -9595,6 +10981,22 @@ between 4.x and 5.0.0, which silently turned one consumer's inner-surface scrim
9595
10981
  bubble (near-black text on `rgba(0,0,0,0.22)`, visible only by eye). These four are that stable
9596
10982
  contract.
9597
10983
 
10984
+ Two matching geometry properties cover the bubble's box:
10985
+
10986
+ - `--lr-chat-message-bubble-padding` (default `var(--lr-space-m)`) — the bubble's padding.
10987
+ - `--lr-chat-message-bubble-radius` (default `var(--lr-radius)`) — the bubble's corner radius.
10988
+ Bubble-only by design: `[part='collapse-button']` and `[part='retry-button']` keep reading the
10989
+ shared `--lr-radius`, so a rounder bubble never desyncs those controls from the rest of the
10990
+ library.
10991
+
10992
+ **Use these instead of a `::part(bubble)` padding/radius override.** A `::part` declaration written
10993
+ in the consumer's tree outranks *every* rule inside this component's shadow tree, so a
10994
+ `::part(bubble) { padding: … }` rule silently suppresses the per-`status` treatments layered on the
10995
+ same element — `status="failed"`'s danger tint, `status="streaming"`'s border — along with the
10996
+ per-role fills above. The two properties are declared as `var()` fallbacks at the point of use and
10997
+ never on `:host`, both so they can't shadow an inherited value and so a container can set them once
10998
+ above a whole transcript rather than per message.
10999
+
9598
11000
  Plus shared tokens `--lr-space-xs/-m`, `--lr-color-border`, `--lr-color-surface`,
9599
11001
  `--lr-color-brand-quiet`, `--lr-color-brand`, `--lr-color-text-quiet`, `--lr-color-danger`,
9600
11002
  `--lr-color-danger-quiet`, `--lr-radius`, `--lr-icon-button-size`, `--lr-focus-ring-*`,
@@ -9741,6 +11143,10 @@ reveals the invalid state, and `form.reset()` clears the touched presentation.
9741
11143
  - `maxRows: number = 8` (attribute `max-rows`) — floored to at least `minRows`
9742
11144
  - `status: ChatComposerStatus = 'idle'` (reflected) — `'idle' | 'sending' | 'streaming'`; drives the
9743
11145
  built-in button's icon/label (send vs. stop) and whether Enter still submits
11146
+ - `appearance: ChatComposerAppearance = 'card'` (reflected) — `'card' | 'plain'`; `'plain'` drops
11147
+ `[part="base"]`'s border, background, padding and corner radius so a composer docked inside a chat
11148
+ panel, dialog footer or toolbar that already draws its own border doesn't double the frame. The
11149
+ focus affordance is swapped, not dropped — see **Known gotchas**
9744
11150
  - `submitOnEnter: boolean = true` (reflected, attribute `submit-on-enter`) — when `false`, Enter
9745
11151
  always inserts a newline instead of submitting
9746
11152
  - `submitDisabled: boolean = false` (reflected, attribute `submit-disabled`) — consumer-controlled
@@ -9784,11 +11190,15 @@ entirely when it has assigned content)
9784
11190
 
9785
11191
  **CSS parts:** `base`, `chips`, `row`, `leading`, `textarea`, `trailing`, `action-button`
9786
11192
 
9787
- **Themeable custom properties:** no component-specific custom properties; consumes shared tokens
9788
- `--lr-space-xs`, `--lr-space-s`, `--lr-color-border`, `--lr-color-surface`,
9789
- `--lr-color-brand`, `--lr-color-on-brand`, `--lr-color-text-quiet`, `--lr-radius`,
9790
- `--lr-icon-button-size`, `--lr-transition-fast`, `--lr-opacity-disabled`,
9791
- `--lr-focus-ring-width`, `--lr-focus-ring-color`, `--lr-focus-ring-offset`.
11193
+ **Themeable custom properties:** `--lr-chat-composer-busy-bg` (default `var(--lr-color-text-quiet)`)
11194
+ `[part="action-button"]`'s background while `status` is `"sending"` or `"streaming"` (the busy/stop
11195
+ treatment). Scoped separately from the shared `--lr-color-text-quiet` token, which
11196
+ `[part="textarea"]`'s placeholder color also reads — overriding this cssprop recolors only the busy
11197
+ button, not the placeholder too (the same shared-token-collision fix `<lr-chat-message>`'s own
11198
+ user-bubble background pair documents). Plus shared tokens `--lr-space-xs`, `--lr-space-s`,
11199
+ `--lr-color-border`, `--lr-color-surface`, `--lr-color-brand`, `--lr-color-on-brand`,
11200
+ `--lr-color-text-quiet`, `--lr-radius`, `--lr-icon-button-size`, `--lr-transition-fast`,
11201
+ `--lr-opacity-disabled`, `--lr-focus-ring-width`, `--lr-focus-ring-color`, `--lr-focus-ring-offset`.
9792
11202
 
9793
11203
  **Optional peer deps:** none.
9794
11204
 
@@ -9844,6 +11254,11 @@ and disables only the built-in Send button; editing and busy-state Stop behavior
9844
11254
  - `[part="chips"]`/`[part="leading"]` are hidden via a JS-tracked `[hidden]` attribute rather than a
9845
11255
  CSS `:empty` selector, because each always contains a literal `<slot>` child regardless of
9846
11256
  assigned content.
11257
+ - Under `appearance="card"` the only focus affordance is a border-color shift on `[part="base"]`
11258
+ (the internal `<textarea>` sets `outline: none`). `appearance="plain"` removes that border, so it
11259
+ swaps in a different affordance rather than losing focus visibility: an underline across the whole
11260
+ input row, drawn as an inset `box-shadow` from `--lr-focus-ring-width`/`--lr-focus-ring-color` so
11261
+ it costs no layout. If you restyle `[part="base"]` under `plain`, keep a focus indicator.
9847
11262
 
9848
11263
  ---
9849
11264
 
@@ -9986,6 +11401,15 @@ First-party invention (no Web Awesome equivalent).
9986
11401
  rename button never renders and the row can never enter its editing state; flipping it to `false`
9987
11402
  while a rename is already in progress cancels that edit (discards the draft, like Escape) rather
9988
11403
  than leaving it stranded and still committable.
11404
+ - `compact: boolean = false` (reflected) — tighter row padding and gaps, for the dense history
11405
+ sidebars these rows usually render in (same convention as `lr-empty`'s `compact`). Tightens
11406
+ `[part='base']`'s padding to `var(--lr-space-xs) var(--lr-space-s)` and its gap to
11407
+ `var(--lr-space-2xs)`, and collapses `[part='content']`'s inter-line gap to `0`. Deliberately
11408
+ changes nothing else: it does **not** shrink `[part='rename-button']` below the shared
11409
+ `--lr-icon-button-size` target floor, hide the excerpt, or reduce the excerpt/timestamp font
11410
+ sizes — so a row carrying a rename button or slotted `actions` still floors at roughly that icon
11411
+ size plus the compact padding, while a row with `editable=false` and no actions collapses much
11412
+ further.
9989
11413
  - `spellcheck: boolean = true` — forwarded to the in-place rename `<input>`; `spellcheck="false"` is
9990
11414
  parsed as false (not Lit's default boolean-attribute behavior)
9991
11415
  - `autocapitalize: string = ''` — forwarded to the in-place rename `<input>`; empty omits the attribute
@@ -10021,7 +11445,33 @@ in-place rename `<input>`'s own `focus`, for the same reason as `blur`)
10021
11445
  **CSS parts:** `base`, `option`, `content`, `title`, `title-input`, `rename-button`, `excerpt`,
10022
11446
  `timestamp`, `actions`
10023
11447
 
10024
- **Themeable custom properties:** shared tokens only — `--lr-space-xs/-s/-m`, `--lr-radius`,
11448
+ **Themeable custom properties:** `--lr-conversation-item-active-bg` (default
11449
+ `var(--lr-color-brand-quiet)`) — the row's background while `active`. `--lr-conversation-item-active-color`
11450
+ (default `var(--lr-color-text)`) — the text color of `[part='excerpt']` and `[part='timestamp']`
11451
+ while `active`. Both are declared as inline `var()` fallbacks at the point of use and never on
11452
+ `:host`, so either can be set on the element *or on any ancestor* (a thread-list wrapper, a page
11453
+ theme layer); `::part(base)[active]` is not valid CSS — Shadow Parts forbids an attribute selector
11454
+ after `::part()` — so the only previous lever was overriding the library-wide `--lr-color-brand-quiet`
11455
+ token and repainting everything else reading it. Unset, each falls back to exactly the token its rule
11456
+ used before.
11457
+
11458
+ **These two are a contrast-sensitive pair — override them together, never one alone.** The
11459
+ `-active-color` hook exists precisely because the quiet text tone only reaches about 4.25:1 against
11460
+ the default active background; keep any override at 4.5:1 or better against it. And note that
11461
+ `[part='title']` is *not* restyled by the pair — it keeps `--lr-color-text` regardless — so a dark
11462
+ custom active background needs its own title color set alongside them, or the title drops below
11463
+ contrast while the excerpt stays legible.
11464
+
11465
+ `--lr-conversation-item-compact-padding` (default `var(--lr-space-xs) var(--lr-space-s)`) —
11466
+ `[part='base']`'s padding while `compact`. `--lr-conversation-item-compact-gap` (default
11467
+ `var(--lr-space-2xs)`) — `[part='base']`'s gap while `compact`. Like the active-state pair, both are
11468
+ inline `var()` fallbacks at the point of use and never declared on `:host`, so a surrounding list can
11469
+ retune every row at once from an ancestor. `[part='content']`'s gap collapses to a flat `0` under
11470
+ `compact` with no hatch of its own — there is no smaller step left to retune to. `:host([compact])
11471
+ [part='base']` is ordered *before* `:host([active]) [part='base']` (equal specificity), so a row that
11472
+ is both compact and active keeps the active background and the promoted excerpt/timestamp contrast.
11473
+
11474
+ Plus shared tokens — `--lr-space-xs/-s/-m`, `--lr-radius`,
10025
11475
  `--lr-transition-fast`, `--lr-color-text/-text-quiet/-brand/-brand-quiet/-surface`,
10026
11476
  `--lr-focus-ring-width/-color/-offset`, `--lr-icon-button-size`.
10027
11477
 
@@ -10068,6 +11518,11 @@ duration of an edit rather than just visually swapping content (a row mid-edit *
10068
11518
  - Setting `editable = false` mid-rename silently discards the in-progress draft (no `lr-rename`
10069
11519
  fires) — a consumer toggling `editable` off (e.g. in response to some other row entering rename
10070
11520
  mode) should not expect the previous edit to be committed first.
11521
+ - `compact` is a spacing knob only — it never lowers the rename button's `--lr-icon-button-size`
11522
+ floor. A compact row that still shows a rename button (or slotted `actions` at the same floor)
11523
+ therefore bottoms out at roughly that icon size plus the compact padding, not at the text height.
11524
+ Lowering `--lr-icon-button-size` at an ancestor is the explicit, informed opt-out of the
11525
+ target-size floor; a density flag deliberately won't do it silently on your behalf.
10071
11526
 
10072
11527
  ---
10073
11528
 
@@ -10123,10 +11578,24 @@ emitting `lr-change`.
10123
11578
  - `disabled: boolean = false` (reflected)
10124
11579
  - `required: boolean = false` (reflected — enforced via `internals.setValidity()`)
10125
11580
  - `open: boolean = false` (reflected)
11581
+ - `size: 'xs' | 's' | 'm' | 'l' | 'xl' = 'm'` (reflected) — visual size; same `xs`–`xl` scale as
11582
+ `<lr-select>`'s own `size`, scaling `[part="trigger"]`/`[part="combobox"]`'s padding/min-height/
11583
+ font-size and `[part="expand-icon"]`'s box size (see the themeable custom properties below).
10126
11584
  - `value: string` — getter/setter (hand-rolled, not the `FormAssociated` mixin); the current model id,
10127
11585
  `''` when nothing is selected. Writing it calls `internals.setFormValue()` synchronously. A named,
10128
11586
  untouched model-select contributes `''` to `FormData` instead of omitting its key.
10129
11587
 
11588
+ **Methods:** `click()` (override) — forwards to whichever internal control the active mode renders,
11589
+ since `HTMLElement.prototype.click()` is otherwise a no-op on a custom element with no native click
11590
+ semantics of its own (mirrors `<lr-button>`'s identical host `click()` forwarding, so a generic
11591
+ form-automation helper or another component calling `.click()` on the host actually opens the picker
11592
+ instead of silently doing nothing). Closed-dropdown mode forwards a real `.click()` to the trigger
11593
+ `<button>`, whose own `@click` handler opens it. Free-text mode instead calls `.focus()` on the
11594
+ combobox `<input>`: unlike a genuine pointer click, `HTMLElement.click()` never moves focus (that's a
11595
+ `mousedown` side effect the browser applies only to real pointer interaction), and this mode's open
11596
+ behavior is wired to the input's `focus` event (`onInputFocus`), not a `click` handler on the input
11597
+ itself.
11598
+
10130
11599
  **Mode switching:** `closedMode` (private) is `true` whenever `normalizedCatalog.length > 0 &&
10131
11600
  !allowCustom` — a non-empty `catalog` with `allowCustom` left `false` renders the closed dropdown
10132
11601
  trigger-button UI (`[part="trigger"]`, `role="combobox"` on a `<button>`, no typing). Any other
@@ -10163,10 +11632,21 @@ both modes), `option`, `option-label`, `option-badge` (the "not in catalog" badg
10163
11632
  stale-value row), `expand-icon` (the dropdown chevron, present in both modes), `hint` (the hint
10164
11633
  message), `error` (the error message)
10165
11634
 
10166
- **Themeable custom properties:** shared tokens only — `--lr-space-xs/-s`,
10167
- `--lr-color-border/-surface/-brand/-brand-quiet/-text-quiet`, `--lr-radius`, `--lr-shadow`,
10168
- `--lr-focus-ring-width/-color/-offset`, `--lr-icon-button-size`, `--lr-transition-fast`,
10169
- `--lr-opacity-disabled`.
11635
+ **Themeable custom properties:** `--lr-model-select-trigger-padding` (default `var(--lr-space-xs)
11636
+ var(--lr-space-s)`) `[part="trigger"]`/`[part="combobox"]`'s padding shorthand.
11637
+ `--lr-model-select-trigger-min-height` (default `var(--lr-size-2-5rem)`) — their block-size floor.
11638
+ `--lr-model-select-font-size` (default `var(--lr-font-size-md)`) — their font size.
11639
+ `--lr-model-select-expand-size` (default `var(--lr-size-1-75rem)`) — `[part="expand-icon"]`'s
11640
+ decorative box size (clamped against `--lr-icon-button-size` via `min()`). All four are declared on
11641
+ `:host` at these `size="m"` (the default) values and re-declared inside each
11642
+ `:host([size="xs"|"s"|"l"|"xl"])` block at that tier's own value — same xs–xl scale `<lr-select>`
11643
+ uses — so `size` is the primary lever; override the cssprop directly only to retune a single tier or
11644
+ step outside the scale entirely. `--lr-model-select-option-active-bg` (default
11645
+ `var(--lr-color-brand-quiet)`) — background of a hovered or keyboard-active `[part="option"]` row;
11646
+ declared as a `var()` fallback at the point of use, not on `:host`, so it isn't tied to `size`. Plus
11647
+ shared tokens — `--lr-space-xs/-s`, `--lr-color-border/-surface/-brand/-brand-quiet/-text-quiet`,
11648
+ `--lr-radius`, `--lr-shadow`, `--lr-focus-ring-width/-color/-offset`, `--lr-icon-button-size`,
11649
+ `--lr-transition-fast`, `--lr-opacity-disabled`.
10170
11650
 
10171
11651
  **Optional peer deps:** none.
10172
11652
 
@@ -10467,11 +11947,30 @@ are both set)
10467
11947
  **Themeable custom properties:** `--lr-code-block-max-height` (default `none` — the consumer-tunable
10468
11948
  scroll cap; only takes effect once `max-height` is set), `--lr-code-block-font` (default
10469
11949
  `ui-monospace, SFMono-Regular, Menlo, Consolas, monospace` — no shared `--lr-*` monospace
10470
- token exists to resolve through), plus shared tokens `--lr-color-border`, `--lr-radius`,
11950
+ token exists to resolve through), `--lr-code-block-tab-size` (default `2` — tab width for the
11951
+ rendered code, applied to `[part='pre']`), `--lr-code-block-active-line-outline-color` (default
11952
+ `var(--lr-color-brand)` — the outline around the line marked active by `active-highlight-id`), plus shared tokens `--lr-color-border`, `--lr-radius`,
10471
11953
  `--lr-color-surface`, `--lr-space-xs/-s/-m`, `--lr-font`, `--lr-color-text-quiet`,
10472
11954
  `--lr-color-text`, `--lr-color-brand`/`-brand-quiet`, `--lr-transition-fast`,
10473
11955
  `--lr-focus-ring-width/-color/-offset`.
10474
11956
 
11957
+ `--lr-code-block-tab-size` carries the same default as `--lr-code-editor-tab-size`, so the editable
11958
+ and read-only code surfaces agree on what a literal tab looks like. It is declared as a `var()`
11959
+ fallback **at the point of use, not on `:host`** — a `:host` rule is re-stamped on every instance and
11960
+ shadows any inherited value, so a page- or container-level declaration could never reach it. It is
11961
+ also never written as an inline `tab-size`: `shiki` puts its own `style` attribute on the highlighted
11962
+ `<pre>`, and an inline declaration is the one thing a host override cannot beat. `<lr-markdown>` and
11963
+ `<lr-markdown-core>` carry the same fallback for their own `code-block` part because they are
11964
+ **sibling** custom elements rather than descendants of this one — no single declaration covers both.
11965
+ The identical value can still look different across the two: this component is `white-space: pre`
11966
+ while a markdown code block inherits `pre-wrap`, and tab stops restart at each visual line, so a
11967
+ wrapped line's tabs diverge.
11968
+
11969
+ `--lr-code-block-active-line-outline-color` retints just the active line's outline and leaves every
11970
+ other `--lr-color-brand` surface in the component — the header language pill, hover states, the focus
11971
+ ring — alone. It too is an inline `var()` fallback rather than a `:host` declaration, deliberately,
11972
+ so it inherits: set it on the element, on an ancestor, or at the theme level.
11973
+
10475
11974
  **Optional peer deps:** `shiki` (lazy-loaded and cached once per page by `code-loader.ts`'s
10476
11975
  `loadShikiHighlighter()`, which builds a single `Highlighter` seeded with the bundled `github-light`/
10477
11976
  `github-dark` "dual themes" and *zero* language grammars up front; each `language` a
@@ -10596,7 +12095,12 @@ body ended; `anchor` is a `line-range` anchor covering the selected lines).
10596
12095
  `code`, `line-highlight`, `line-button` — identical set to `<lr-code-block>`.
10597
12096
 
10598
12097
  **Themeable custom properties:** identical to `<lr-code-block>` — `--lr-code-block-max-height`,
10599
- `--lr-code-block-font`, plus the same shared tokens.
12098
+ `--lr-code-block-font`, `--lr-code-block-tab-size` (default `2`, applied to `[part='pre']`),
12099
+ `--lr-code-block-active-line-outline-color` (default `var(--lr-color-brand)`), plus the same shared
12100
+ tokens. Both of the last two are inline `var()` fallbacks at the point of use rather than `:host`
12101
+ declarations, so a page-, container-, or theme-level value reaches them; see `<lr-code-block>` above
12102
+ for the full rationale, including why `<lr-markdown>`/`<lr-markdown-core>` must declare the tab-size
12103
+ fallback separately.
10600
12104
 
10601
12105
  **Optional peer deps:** `shiki` (specifically its `shiki/core`, `shiki/engine/oniguruma`,
10602
12106
  `shiki/wasm`, and `shiki/themes/github-{light,dark}.mjs` subpaths — never `shiki`'s main entry point,
@@ -10829,6 +12333,21 @@ for a set rating).
10829
12333
  `commentable` is set), `reasons` (the reason-chip group), `comment` (the comment `<textarea>`), and
10830
12334
  `submit-button`.
10831
12335
 
12336
+ **Themeable custom properties:** six pressed-state hooks, three per thumb —
12337
+ `--lr-message-feedback-up-active-color` (default `var(--lr-color-success)`),
12338
+ `--lr-message-feedback-up-active-bg` (default `var(--lr-color-success-quiet)`),
12339
+ `--lr-message-feedback-up-active-border` (default `var(--lr-color-success)`), and the thumbs-down
12340
+ trio `--lr-message-feedback-down-active-color`, `--lr-message-feedback-down-active-bg`,
12341
+ `--lr-message-feedback-down-active-border` (defaulting to `var(--lr-color-danger)`,
12342
+ `var(--lr-color-danger-quiet)`, `var(--lr-color-danger)`). Each styles the glyph, background, and
12343
+ border of its thumb only while that thumb is pressed. All six are declared as inline `var()`
12344
+ fallbacks at the point of use and never on `:host`, so each can be set on the element *or on any
12345
+ ancestor* — a whole transcript's feedback controls retint from one declaration. That shape is
12346
+ required because `::part(up-button)[aria-pressed='true']` is invalid CSS (Shadow Parts forbids an
12347
+ attribute selector after `::part()`), which previously left overriding the library-wide
12348
+ `--lr-color-success`/`--lr-color-danger` tokens as the only lever, repainting every other element
12349
+ reading them. Unset, each falls back to exactly the token its rule used before.
12350
+
10832
12351
  ## `lr-push-to-talk`
10833
12352
 
10834
12353
  A mic capture button owning the full `getUserMedia` + `MediaRecorder` lifecycle: permission request,
@@ -10866,7 +12385,14 @@ Blob }`, only when `timeslice-ms > 0`), `lr-record-stop` (`detail: { blob: Blob;
10866
12385
  (visible status text for the `requesting`/`denied`/`error`/unsupported states).
10867
12386
 
10868
12387
  **Themeable custom properties:** `--lr-push-to-talk-size` (default `var(--lr-size-3rem)`) — the
10869
- trigger button's inline and block size.
12388
+ trigger button's inline and block size. `--lr-push-to-talk-recording-color` (default
12389
+ `var(--lr-color-danger)`) — the border and text color of `[part='trigger']` while `state` is
12390
+ `recording`; it recolors only the recording treatment and leaves every other danger-toned surface on
12391
+ the page untouched. Like the library's other state hooks it is an inline `var()` fallback at the
12392
+ point of use rather than a `:host` declaration, so it can be set on the element or on any ancestor —
12393
+ `::part(trigger)[data-state='recording']` is invalid CSS (Shadow Parts forbids an attribute selector
12394
+ after `::part()`), so re-pointing the shared `--lr-color-danger` token was previously the only way,
12395
+ and it repainted every other danger surface with it.
10870
12396
 
10871
12397
  ## `lr-transcript-feed`
10872
12398
 
@@ -10967,6 +12493,18 @@ Renders no messages and computes no unread state itself — the host supplies `u
10967
12493
  virtualization of its own (`lr-virtual-list`); not a generic overflow surface (`lr-scroller`); no
10968
12494
  message semantics (`lr-chat-message`).
10969
12495
 
12496
+ **Sizing in virtual mode.** `[part='scroll']` steps aside and the slotted `lr-virtual-list`'s own
12497
+ viewport becomes the real scroller, so it is given this component's full height — otherwise it would
12498
+ scroll inside `lr-virtual-list`'s `24rem` default no matter how tall the viewport is. An explicit
12499
+ `block-size` on the slotted list is what makes that resolvable: without it the list host is
12500
+ auto-height, its own base percentage chains to `auto`, and the two size each other circularly.
12501
+ `<lr-thread-list>` solves the same problem by turning the internal list's shipped `24rem` into a
12502
+ flex-basis through `::part(base)`, which is not available here — that list lives in the *consumer's*
12503
+ light DOM, and `::slotted()` cannot be followed by `::part()`. Virtual mode therefore inherits this
12504
+ component's existing requirement of a height-bounded parent, exactly as slotted mode's own
12505
+ `[part='scroll']` already does. A document-tree declaration on the list (a consumer's own rule or an
12506
+ inline style) still wins over the built-in one.
12507
+
10970
12508
  ```html
10971
12509
  <lr-chat-viewport unread-start-index="12" @lr-follow-change=${(e) => console.log(e.detail.following)}>
10972
12510
  <lr-chat-message role="user">…</lr-chat-message>
@@ -10996,6 +12534,15 @@ string = ''` — accessible name for the group, defaults to the localized `sugge
10996
12534
  **CSS parts:** `base` (the labeled group), `chip` (each suggestion button), `chip-label` (the primary
10997
12535
  text), `chip-detail` (the secondary line, only rendered when `detail` is set).
10998
12536
 
12537
+ **Themeable custom properties:** `--lr-suggestion-chips-hover-bg` (default
12538
+ `var(--lr-color-brand-quiet)`) — a `chip`'s background on hover. `--lr-suggestion-chips-hover-border`
12539
+ (default `var(--lr-color-brand)`) — a `chip`'s border color on hover. Both are declared as `var()`
12540
+ fallbacks at the point of use, not on `:host`. Plus shared tokens `--lr-space-xs/-m/-2xs`,
12541
+ `--lr-color-border/-surface/-text/-text-quiet`, `--lr-radius-pill`, `--lr-font-size-xs`,
12542
+ `--lr-focus-ring-width/-color/-offset`.
12543
+
12544
+ **Optional peer deps:** none.
12545
+
10999
12546
  Keyboard: roving tabindex across chips; ArrowLeft/ArrowRight (direction-aware) plus Home/End;
11000
12547
  Enter/Space activate. Renders inside an internal `lr-scroller` (`orientation="horizontal"`,
11001
12548
  `hide-scrollbar`) unless `wrap` is set.
@@ -11039,10 +12586,23 @@ set; `lr-group-toggle` requests the matching state change. `rowActions: ThreadRo
11039
12586
  data mode only: built-in icon buttons rendered into each row's `actions` slot. `showArchived: boolean
11040
12587
  = false` (attribute `show-archived`, reflected) — data mode: include `archived` threads (in their own
11041
12588
  trailing group). `editable: boolean = true` (reflected) — forwarded to each data-mode row's inline
11042
- rename. `label: string = ''` — accessible name for the list region, defaults to the localized
11043
- `threadListLabel`. `wrapRow?: (thread: ChatThread, row: TemplateResult) => TemplateResult` (attribute:
11044
- false) data mode only: wraps each row's built-in `lr-conversation-item` with host-supplied content
11045
- that has no home in the item's own `title`/`excerpt`/`meta`/`actions` surface (e.g. a leading purpose
12589
+ rename. `compact: boolean = false` (reflected) data mode only: forwarded to each row
12590
+ `lr-conversation-item`'s own `compact`, tightening every row's padding and gaps from one attribute
12591
+ (the density itself lives on the row item; retune it through
12592
+ `--lr-conversation-item-compact-padding`/`-gap` on this element or any ancestor). Slotted mode is a
12593
+ deliberate no-op — that mode renders host-supplied items as-is, so the host sets `compact` on its own
12594
+ items there, the same division of responsibility slotted mode already has for every other row
12595
+ property. `stickyGroups: boolean = false` (attribute `sticky-groups`, reflected) — data mode: pins
12596
+ the current date/custom group's header to the top of the scroll viewport while its rows are in view,
12597
+ pushing it off as the next group's header arrives. Group headers are ordinary virtualized rows, so
12598
+ this renders an `aria-hidden` copy of the header into the internal `lr-virtual-list`'s sticky layer:
12599
+ the real row keeps the `role="heading"`/`aria-level` semantics and the tab order (the copy's toggle
12600
+ is not a second tab stop), while the pinned copy stays clickable and requests the same
12601
+ `lr-group-toggle` collapse. Default `false` renders exactly as before; `grouping="none"` has no
12602
+ headers to pin, so it is a no-op there. `label: string = ''` — accessible name for the list region,
12603
+ defaults to the localized `threadListLabel`. `wrapRow?: (thread: ChatThread, row: TemplateResult) =>
12604
+ TemplateResult` (attribute: false) — data mode only: wraps each row's built-in
12605
+ `lr-conversation-item` with host-supplied content that has no home in the item's own `title`/`excerpt`/`meta`/`actions` surface (e.g. a leading purpose
11046
12606
  icon — the item has no default slot to receive one); unset renders the built-in row unwrapped.
11047
12607
  `renderActions?: (thread: ChatThread) => TemplateResult` (attribute: false) — data mode only:
11048
12608
  appends host-supplied content (re-invoked per row on every render, e.g. a `lr-menu` with custom
@@ -11068,20 +12628,67 @@ id }`), `lr-thread-pin` (`detail: { id, pinned }` — the requested new state),
11068
12628
  `lr-thread-rename` (`detail: { id, title }`, re-emitted from the row's `lr-rename`),
11069
12629
  `lr-filter-change` (`detail: { text, matchCount }`), `lr-group-toggle` (`detail: { id, collapsed }` —
11070
12630
  controlled intent; native group buttons provide Enter/Space activation and explicit
11071
- `aria-expanded="true"|"false"`).
12631
+ `aria-expanded="true"|"false"`). `searchable` only: `blur`/`focus` (no detail) — re-dispatched from
12632
+ the internal search `<input>`'s own `blur`/`focus`, bubbling and composed unlike the native events,
12633
+ which are neither.
11072
12634
 
11073
12635
  **CSS parts:** `base`, `search`/`search-input` (the search field wrapper and `<input
11074
12636
  type="search">`), `list` (the list region), `empty`, `viewport` (the actual internal virtual-list
11075
12637
  scroll container, suitable for scrollbar styling), `row-action` (a built-in pin/archive/delete icon
11076
12638
  button), `pin-glyph` (the small pin indicator on a pinned row), `group-header`, `group-toggle`,
11077
- `group-label`, `group-icon`, `row` (all exported across the internal `lr-virtual-list` shadow
11078
- boundary), and `row-leading`/`row-content`/`row-meta`/`row-actions` (the library-owned wrappers around
12639
+ `group-label`, `group-icon`, `group-sticky` (`sticky-groups` only: the pinned copy of the current
12640
+ group's header, exported from the internal `lr-virtual-list`'s sticky layer it wraps a full copy of
12641
+ the `group-header`/`group-toggle`/`group-label`/`group-icon` markup, so those parts style the real
12642
+ header row and the pinned copy alike, and the band itself is where a shadow or bottom border
12643
+ belongs), `row` (all exported across the internal `lr-virtual-list` shadow
12644
+ boundary), `row-wrapper` (the wrapper around `wrapRow` output, only present when `wrapRow` is set;
12645
+ row-only — group headers are never passed through `wrapRow`, so they never carry it), and
12646
+ `row-leading`/`row-content`/`row-meta`/`row-actions` (the library-owned wrappers around
11079
12647
  their corresponding render-hook output; inherited fonts, layout values, and theme custom properties
11080
12648
  reach callback-rendered descendants through these parts).
11081
12649
 
12650
+ Data mode additionally forwards each row `<lr-conversation-item>`'s own parts under a `row-item-`
12651
+ prefix: `row-item-base`, `row-item-option`, `row-item-leading`, `row-item-content`,
12652
+ `row-item-title`, `row-item-title-input`, `row-item-rename-button`, `row-item-excerpt`,
12653
+ `row-item-meta`, `row-item-timestamp`, `row-item-actions`.
12654
+
12655
+ **Keep the two prefixes straight — they are different surfaces.** The `row-*` parts wrap *this*
12656
+ component's own render-callback output (`wrapRow`, `renderLeading`, `renderRowContent`,
12657
+ `renderMeta`, `renderActions`); the `row-item-*` parts are the row item's *internals*. Row density
12658
+ in particular lives in `row-item-base`'s padding and `row-item-title`'s font size, so
12659
+ `::part(row-item-base)` is the supported way to build a dense sidebar.
12660
+
12661
+ For plain row density, prefer the `compact` property above — it forwards straight to the row item's
12662
+ own density knob. The `row-item-*` parts remain the lever for tuning beyond it (a different font
12663
+ size, a different padding ratio):
12664
+
12665
+ ```css
12666
+ lr-thread-list::part(row-item-base) { padding-block: 0.25rem; }
12667
+ lr-thread-list::part(row-item-title) { font-size: 0.8125rem; }
12668
+ ```
12669
+
12670
+ Do **not** reach for `::part(row) { --lr-theme-space-s: … }` instead. That is a whole-subtree
12671
+ retheme: it shrinks everything nested inside the row, including the items of a `renderActions` menu,
12672
+ which pushes their touch targets below the accessible minimum. The `row-item-*` parts exist so row
12673
+ density can be tuned without that blast radius.
12674
+
12675
+ **Sizing:** the internal list fills whatever height this component is given, with no consumer CSS —
12676
+ `[part='viewport']` is the real scroll container, and it falls back to `lr-virtual-list`'s own `24rem`
12677
+ default only when the container has no resolvable height. This is deliberately *not* implemented by
12678
+ setting `--lr-virtual-list-height: 100%`: that percentage resolves against this host, which is a flex
12679
+ item, so in an auto-height container it chains to `auto` and the viewport either collapses to zero
12680
+ (with no rows) or grows to the full un-virtualized content height (with rows) — defeating
12681
+ virtualization in both directions. Instead the list host is made a column flex container, which turns
12682
+ the shipped `24rem` into a *flex-basis*: it grows to fill a bounded pane, shrinks below `24rem` in a
12683
+ short one, and falls back to exactly `24rem` in an auto-height container.
12684
+
12685
+ `sticky-groups` keeps the current date group's header visible while scrolling through a long sidebar;
12686
+ style the pinned band with `lr-thread-list::part(group-sticky)`.
12687
+
11082
12688
  ```html
11083
12689
  <lr-thread-list
11084
12690
  searchable
12691
+ sticky-groups
11085
12692
  .threads=${threads}
11086
12693
  active-id=${activeThreadId}
11087
12694
  .rowActions=${['pin', 'archive', 'delete']}
@@ -11262,6 +12869,14 @@ identically-named properties.
11262
12869
  getter/setter (the current voice id, `''` when nothing is selected), `name` (reflected), `disabled`
11263
12870
  (reflected), `required` (reflected — enforced via `internals.setValidity()`).
11264
12871
 
12872
+ **Methods:** `click()` (override) — same forwarding contract as `lr-model-select`'s own `click()`
12873
+ override (see that section for the full rationale): closed-dropdown mode forwards a real `.click()`
12874
+ to the trigger `<button>`, whose own `@click` handler opens it; free-text mode instead calls
12875
+ `.focus()` on the combobox `<input>`, since a synthetic `.click()` on a text input never dispatches
12876
+ `focus` the way a real click's `mousedown` default action does, and this mode's open behavior is
12877
+ wired to the input's native `focus` event, not a `click` handler on the input itself. Mirrors
12878
+ `<lr-button>`'s identical host `click()` forwarding.
12879
+
11265
12880
  **Events:** `lr-change` — `detail: { value, inCatalog }`. `lr-preview-request` — `detail: {
11266
12881
  voiceId, previewUrl? }`, cancelable. `lr-preview-change` — `detail: { voiceId }`, internal playback
11267
12882
  started (`voiceId`) or stopped (`null`). Plus mirrored native `input`/`change` and re-dispatched
@@ -11945,6 +13560,11 @@ invention (no Web Awesome equivalent).
11945
13560
  - `maxHeight: string = ''` (attribute: `max-height`) — caps the rendered block size and enables an
11946
13561
  internal scrollbar once content exceeds it (any valid CSS length). Empty string (the default)
11947
13562
  grows with content.
13563
+ - `appearance: 'card' | 'plain' = 'card'` (reflected) — visual chrome, mirroring `lr-card`'s
13564
+ `appearance` vocabulary. `'card'` keeps the bordered, filled, padded box. `'plain'` removes the
13565
+ border, background, padding and corner radius, so a trace nested inside an
13566
+ `lr-result-card`/`lr-agent-run` — which already draws a border — doesn't double the frame. The
13567
+ `max-height` scroll cap and the copy/frame affordances are unaffected either way.
11948
13568
 
11949
13569
  **Events:**
11950
13570
  - `lr-frame-select` (`detail: { file?: string; line?: number; column?: number; raw: string }`) —
@@ -11955,7 +13575,8 @@ invention (no Web Awesome equivalent).
11955
13575
 
11956
13576
  **Slots:** none.
11957
13577
 
11958
- **CSS parts:** `base` (the root wrapper; respects `max-height`), `message` (the leading error
13578
+ **CSS parts:** `base` (the root wrapper; respects `max-height`, and drops its card chrome under
13579
+ `appearance="plain"`), `message` (the leading error
11959
13580
  message text for a group), `group` (one chained-error group of frames), `frame` (a single frame
11960
13581
  button; carries `data-internal` for internal frames), `frame-function` (the frame's function
11961
13582
  name), `frame-location` (the frame's `file:line:col` text), `internal-toggle` (the collapse/expand
@@ -12014,6 +13635,10 @@ renders at the start of the action row, before Deny/Edit/Approve.
12014
13635
  **Properties:**
12015
13636
  - `open: boolean = false` (reflected) — set this (or call `close()`) to dismiss; there is no separate
12016
13637
  `show()`/`hide()` pair
13638
+ - `accessibleLabel: string | null = null` (attribute `aria-label`) — directly names the internal
13639
+ dialog panel; otherwise the tool-name heading supplies `aria-labelledby`. Mirrors
13640
+ `<lr-tool-result-dialog>`'s/`<lr-tool-select-dialog>`'s own host-`aria-label` override pattern; fed
13641
+ only by a host `aria-label`
12017
13642
  - `toolName: string = ''` (attribute `tool-name`) — the proposed call's name, e.g. `web_search`;
12018
13643
  drives the heading and the dialog's accessible name
12019
13644
  - `args: unknown = {}` (attribute: false) — the proposed call's arguments, rendered via
@@ -12026,11 +13651,7 @@ renders at the start of the action row, before Deny/Edit/Approve.
12026
13651
  `autoCorrect: string = 'off'` (attribute `autocorrect`), `autocomplete: string = 'off'`,
12027
13652
  `wrap: 'hard'|'soft'|'off' = 'soft'`, `inputMode: string = ''` (attribute `inputmode`),
12028
13653
  and `enterKeyHint: string = ''` (attribute `enterkeyhint`) — forwarded to the raw-JSON
12029
- textarea; the defaults keep browser editing assistance from changing JSON text
12030
- - `spellcheck: boolean = false`, `autocapitalize: string = 'off'`, `autoCorrect: string = 'off'`
12031
- (`autocorrect`), `autocomplete: string = 'off'`, `wrap: 'hard'|'soft'|'off' = 'soft'`,
12032
- `inputMode: string = ''` (`inputmode`), and `enterKeyHint: string = ''` (`enterkeyhint`) —
12033
- forwarded to the raw-JSON `<textarea>` while editing.
13654
+ `<textarea>` while editing; the defaults keep browser editing assistance from changing JSON text
12034
13655
 
12035
13656
  **Methods:** `close(reason: ToolApprovalDialogCloseReason = 'api'): void` — closes the dialog, emits
12036
13657
  `lr-close` with `reason`, and returns focus to whatever had it before the dialog opened; a no-op if
@@ -12265,6 +13886,15 @@ A small bordered card shell. Purely visual, with no state of its own beyond slot
12265
13886
  **Properties:**
12266
13887
  - `title: string = ''` — small heading for the card. Leave unset for an untitled card (e.g. a bare
12267
13888
  block of `lr-result-field` rows with no natural heading).
13889
+ - `compact: boolean = false` (reflected) — tighter header/body padding for dense contexts (a card
13890
+ rendered as a row in a transcript or result list), same convention as `<lr-agent-run>`'s own
13891
+ `compact`. Purely a density knob: the border and background stay, so use `appearance="plain"`
13892
+ instead to drop the chrome entirely.
13893
+ - `appearance: 'card' | 'plain' = 'card'` (reflected) — mirrors `lr-card`'s/`<lr-agent-run>`'s
13894
+ `appearance` vocabulary. `'card'` (the default) keeps the bordered, filled box. `'plain'` removes
13895
+ the border, background, and corner radius, so a card nested inside a host frame that already draws
13896
+ a border (e.g. `<lr-tool-result-view>`'s own chrome) doesn't double it. `plain` wins over `compact`
13897
+ when both are set (nothing left to tighten).
12268
13898
 
12269
13899
  **Events:** none.
12270
13900
 
@@ -12279,8 +13909,11 @@ later `slotchange` on `actions` is still observed, but `hidden` whenever there's
12279
13909
  default tooltip, scoped to just this element rather than the whole card), `actions` (`hidden`
12280
13910
  whenever the slot has no assigned content), `body`.
12281
13911
 
12282
- **Themeable custom properties:** shared tokens only — `--lr-space-xs`/`-s`, `--lr-color-border`/
12283
- `-surface`/`-text`, `--lr-radius`.
13912
+ **Themeable custom properties:** `--lr-result-card-compact-header-padding` (default
13913
+ `var(--lr-space-xs)`) — `[part="header"]` block/inline padding while `compact`;
13914
+ `--lr-result-card-compact-body-padding` (default `var(--lr-space-xs)`) — `[part="body"]` padding
13915
+ while `compact`; plus shared tokens — `--lr-space-xs`/`-s`, `--lr-color-border`/`-surface`/`-text`,
13916
+ `--lr-radius`.
12284
13917
 
12285
13918
  ### `lr-result-field`
12286
13919
 
@@ -12380,9 +14013,19 @@ Space).
12380
14013
  bar), `meta` (secondary row info, shown inline under 480px), `status-text`, `duration`, `empty` (shown
12381
14014
  when `spans` is empty), and `live-region`.
12382
14015
 
12383
- **Themeable custom properties:** `--lr-span-waterfall-name-width` (default `8rem`) and
14016
+ **Themeable custom properties:** `--lr-span-waterfall-name-width` (default `8rem`),
12384
14017
  `--lr-span-waterfall-stripe-speed` (a `running` span's striped-bar animation duration; defaults to
12385
- `--lr-transition-ambient`).
14018
+ `--lr-transition-ambient`), and `--lr-span-waterfall-row-active-bg` (default
14019
+ `var(--lr-color-brand-quiet)`) — the background of the active (`activeSpanId`) row.
14020
+
14021
+ That last one follows the convention every **state-scoped** custom property in this family uses, and
14022
+ it is worth reading once: it is an inline `var()` fallback at its point of use and is deliberately
14023
+ **not** declared on `:host`, so it can be set on the element *or on any ancestor* and still reach the
14024
+ rule that consumes it. It exists because Shadow Parts forbids an attribute selector after `::part()`
14025
+ — `::part(row)[data-active]` and every selector like it is invalid CSS — so before it, the only way
14026
+ to restyle a state-dependent surface was to override a library-wide `--lr-color-*` token, which repaints
14027
+ every other surface reading that token. Every `*-active-*`, `*-selected-*` and per-state color
14028
+ property below works the same way.
12386
14029
 
12387
14030
  ## `lr-task-list`
12388
14031
 
@@ -12397,7 +14040,13 @@ status: TaskStatus; detail?: string; children?: TaskItem[] }` with `TaskStatus =
12397
14040
  'running' | 'success' | 'error'` (both exported here). `detail` is an optional secondary plain-text
12398
14041
  line; `children` is exactly **one** level of sub-steps — a child's own `children` is ignored with a
12399
14042
  `console.warn`. `label: string = 'Tasks'`, `expanded: boolean = true` (reflected), and
12400
- `collapsible: boolean = true`.
14043
+ `collapsible: boolean = true`. `compact: boolean = false` (reflected) — tighter header/body padding
14044
+ and item gap for dense contexts (a plan tracker nested in an already-padded transcript row), same
14045
+ convention as `<lr-agent-run>`'s/`<lr-source-card>`'s `compact`; purely a density knob, the border
14046
+ and background stay. `appearance: 'card' | 'plain' = 'card'` (reflected) — mirrors `lr-card`'s
14047
+ `appearance` vocabulary; `'plain'` removes `[part="base"]`'s border, background, and corner radius so
14048
+ a list embedded in a frame that already draws a border (an agent-run panel, a message bubble) doesn't
14049
+ double it.
12401
14050
 
12402
14051
  **Slots:** `detail-<id>` — dynamic, one per item id (e.g. `slot="detail-step-3"`); rich detail under
12403
14052
  that item's label, typically a `<lr-tool-call-chip>` or file `<lr-chip>`.
@@ -12413,7 +14062,11 @@ indicator, only rendered when `collapsible`), `body` (the list of items, `hidden
12413
14062
  children).
12414
14063
 
12415
14064
  **Themeable custom properties:** `--lr-task-list-spin` (default `1s linear`) — running-status icon
12416
- spin animation duration/timing.
14065
+ spin animation duration/timing; `--lr-task-list-compact-header-padding` (default
14066
+ `var(--lr-space-2xs) var(--lr-space-s)`) — `[part="header"]` padding while `compact`;
14067
+ `--lr-task-list-compact-gap` (default `var(--lr-space-2xs)`) — gap between `[part="body"]`'s item
14068
+ rows while `compact`; `--lr-task-list-compact-body-padding` (default `var(--lr-space-2xs)
14069
+ var(--lr-space-s) var(--lr-space-s)`) — `[part="body"]` padding while `compact`.
12417
14070
 
12418
14071
  ## `lr-terminal`
12419
14072
 
@@ -12441,12 +14094,24 @@ text, anchor, rects }`).
12441
14094
 
12442
14095
  **CSS parts:** `base`, `toolbar` (only rendered when copy/download are enabled), `copy-button`,
12443
14096
  `download-button`, `viewport` (the `role="log"` scrollable region), `line` (one rendered line; carries
12444
- `data-line-number`/`data-match`/`data-highlight-tone`), `jump-to-latest` (shown while `follow` is
14097
+ `data-line-number`/`data-match`/`data-highlight-tone`, and is forwarded via `exportparts` so
14098
+ `lr-terminal::part(line)` reaches the rendered lines from a consumer stylesheet despite them living
14099
+ in the internal `<lr-virtual-list>`'s shadow root), `jump-to-latest` (shown while `follow` is
12445
14100
  disengaged and new output has arrived), and `announcer` (the visually-hidden `role="status"` region
12446
14101
  used when `announce-output` is set).
12447
14102
 
12448
14103
  **Themeable custom properties:** `--lr-terminal-height` (default `var(--lr-size-20rem)`) — the
12449
- viewport's block size.
14104
+ viewport's block size; not declared on `:host`, so it is inherited from the host or any ancestor.
14105
+ `--lr-terminal-highlight-accent-bg` (default `var(--lr-color-brand-quiet)`),
14106
+ `--lr-terminal-highlight-success-bg` (default `var(--lr-color-success-quiet)`),
14107
+ `--lr-terminal-highlight-warning-bg` (default `var(--lr-color-warning-quiet)`),
14108
+ `--lr-terminal-highlight-danger-bg` (default `var(--lr-color-danger-quiet)`), and
14109
+ `--lr-terminal-highlight-neutral-bg` (default `var(--lr-color-surface)`) — the background of a
14110
+ `highlights[]` entry of the matching `tone`. Each is decoupled from the identical shared token it
14111
+ falls back to (e.g. `accent`'s `--lr-color-brand-quiet` is also the copy/download-button hover tint)
14112
+ so retinting one tone doesn't repaint the other surface reading that token, and from any
14113
+ `::part('line')` stylesheet override — the background is applied inline, so a stylesheet rule can't
14114
+ beat it without `!important`.
12450
14115
 
12451
14116
  ## `lr-trace-tree`
12452
14117
 
@@ -12472,6 +14137,29 @@ as a root rather than being dropped. `activeSpanId: string | null = null`
12472
14137
  `duration`, `tokens-in`, `tokens-out` (when `showTokens`), `cost` (when `showCost`), `bar-track`,
12473
14138
  `bar`, `empty` (shown when `spans` is empty), and `live-region`.
12474
14139
 
14140
+ **Themeable custom properties:** `--lr-trace-tree-row-active-bg` (default
14141
+ `var(--lr-color-brand-quiet)`) — the background of the active (`activeSpanId`) row — and
14142
+ `--lr-trace-tree-row-active-color` (default `var(--lr-color-text)`) — the color of that row's
14143
+ secondary text (`detail`, `duration`, `tokens-in`, `tokens-out`, `cost`, and the `pending`
14144
+ `status-text` label). Same state-scoped-property convention described under `lr-span-waterfall`
14145
+ above: an inline `var()` fallback rather than a `:host` declaration, so either can be set on the
14146
+ element or any ancestor, and they exist because `::part(row)[data-active]` is invalid CSS.
14147
+
14148
+ **Contrast note:** the active row is more than a tint. Its secondary text would sit at ~4.25:1
14149
+ against the default tint if it stayed at `--lr-color-text-quiet`, so it rises to full-strength
14150
+ `--lr-color-text` while the row is active, and the semantic `status-text` labels are rendered as
14151
+ `color-mix(in srgb, var(--lr-color-<tone>) 75%, var(--lr-color-text))` — keeping the status hue
14152
+ (an error row stays red) while clearing the 4.5:1 floor (success 4.46 → 6.18, `denied` 4.28 →
14153
+ 5.96). Both adjustments are theme-symmetric, because `--lr-color-text` flips with the color
14154
+ scheme. `[part='bar']` is deliberately untouched: it is a non-text graphic on a 3:1 floor, and its
14155
+ saturation is the row's primary status signal.
14156
+
14157
+ The two properties are a **pair**. The defaults assume the active background stays on the same
14158
+ side of the lightness midpoint as the ambient surface, so a consumer who sets
14159
+ `--lr-trace-tree-row-active-bg` to a dark tint in light mode (or a light one in dark mode) must
14160
+ set `--lr-trace-tree-row-active-color` to match, and should re-check the status-label tones
14161
+ against the new tint as well.
14162
+
12475
14163
  ## `lr-activity-feed`
12476
14164
 
12477
14165
  An append-only streaming log of granular agent actions ("Searching the web…", "Read
@@ -12500,12 +14188,21 @@ rather than augmenting it, and `virtualizeThreshold: number = 200` (attribute
12500
14188
 
12501
14189
  **CSS parts:** `base`, `header` (a `<button>`), `status-dot` (pulses while `mode="live"`),
12502
14190
  `summary`, `toggle`, `body` (the scrollable region, or the internal virtual-list), `entry` (carries
12503
- `data-tone`), `entry-icon`, `entry-text`, and `entry-timestamp` (only while `showTimestamps` and a
12504
- valid `timestamp` is set).
14191
+ `data-tone`), `entry-icon`, `tone-dot` (the dot rendered inside `entry-icon` when the entry sets no
14192
+ literal `icon`), `tone-dot-neutral`/`tone-dot-brand`/`tone-dot-success`/`tone-dot-warning`/
14193
+ `tone-dot-danger` (each also carries `tone-dot`), `entry-text`, and `entry-timestamp` (only while
14194
+ `showTimestamps` and a valid `timestamp` is set). Every entry-level part is reachable in both
14195
+ rendering paths, virtualized or not.
12505
14196
 
12506
14197
  **Themeable custom properties:** `--lr-activity-feed-max-height` (default `16rem`) — cap on how
12507
14198
  tall the expanded body grows before it scrolls internally.
12508
14199
 
14200
+ **Known gotchas:**
14201
+ - The tone dot's color is selected by its *part name*, not by `[data-tone]`: `::part()` cannot be
14202
+ followed by an attribute selector, so `lr-activity-feed::part(tone-dot)[data-tone='success']`
14203
+ never matches. Target `lr-activity-feed::part(tone-dot-success)` instead. `data-tone` remains on
14204
+ both the entry and the dot for DOM queries.
14205
+
12509
14206
  ## `lr-commit-card`
12510
14207
 
12511
14208
  A compact commit summary (subject, author/time, diffstat, per-file changes) that links file rows out
@@ -12518,6 +14215,13 @@ number` (attribute: false, epoch milliseconds), `files: CommitFileChange[] = []`
12518
14215
  'conflicted' | 'ignored'` (shared with `lr-file-tree`); the diffstat is summed from `additions`/
12519
14216
  `deletions` across `files`. `filesCollapsed:
12520
14217
  boolean = true` (attribute `files-collapsed`, reflected), and `copyable: boolean = true` (reflected).
14218
+ `compact: boolean = false` (reflected) — tighter `[part="base"]` padding for a commit rendered as a
14219
+ row in a list or PR timeline, same convention as `<lr-agent-run>`'s own `compact`; the border stays,
14220
+ so pair it with `appearance="plain"` to drop the chrome entirely. `appearance: 'card' | 'plain' =
14221
+ 'card'` (reflected) — mirrors `lr-card`'s/`<lr-agent-run>`'s `appearance` vocabulary: `'card'` keeps
14222
+ the bordered, padded box, `'plain'` removes the border, padding, and corner radius so a commit nested
14223
+ in a host list that already draws its own row chrome doesn't double it; `plain` wins over `compact`
14224
+ when both are set.
12521
14225
 
12522
14226
  **Slots:** `actions` — trailing header controls (e.g. an "open PR" button).
12523
14227
 
@@ -12528,6 +14232,9 @@ boolean = true` (attribute `files-collapsed`, reflected), and `copyable: boolean
12528
14232
  `deletions`, `files-toggle`, `file` (carries `data-status`), `file-path`, `file-additions`,
12529
14233
  `file-deletions`, `copy-button`, and `actions`.
12530
14234
 
14235
+ **Themeable custom properties:** `--lr-commit-card-compact-padding` (default `var(--lr-space-s)`) —
14236
+ `[part="base"]` padding while `compact`.
14237
+
12531
14238
  ## `lr-test-results`
12532
14239
 
12533
14240
  A pass/fail suite summary with per-status counts, status filter toggles, and per-test rows whose
@@ -12555,6 +14262,17 @@ expanded/collapsed).
12555
14262
  `data-status`), `test-status`, `test-name`, `test-duration`, `test-expand-toggle`, `failure`
12556
14263
  (hidden while collapsed), and `failure-message`.
12557
14264
 
14265
+ **Themeable custom properties:** `--lr-test-results-filter-active-bg` (default
14266
+ `var(--lr-color-brand-quiet)`), `--lr-test-results-filter-active-border` (default
14267
+ `var(--lr-color-brand)`) and `--lr-test-results-filter-active-color` (default
14268
+ `var(--lr-color-brand)`) — the background, border color and text color of a pressed (active) status
14269
+ filter toggle. All three follow the state-scoped-property convention described under
14270
+ `lr-span-waterfall`: inline `var()` fallbacks rather than `:host` declarations, so each can be set on
14271
+ the element or on any ancestor. They exist because
14272
+ `::part(filter-toggle)[aria-pressed='true']` is invalid CSS — Shadow Parts forbids an attribute
14273
+ selector after `::part()` — so restyling the pressed state otherwise meant overriding the
14274
+ library-wide brand tokens.
14275
+
12558
14276
  ## `lr-confirm-bar`
12559
14277
 
12560
14278
  An inline, non-modal approve/deny block for one proposed action — the in-flow sibling of
@@ -12572,7 +14290,14 @@ free-form heading override for non-tool proposals; wins over `toolName`. `args:
12572
14290
  (attribute: false) — shown read-only inside a collapsed `lr-details` + `lr-json-viewer` when
12573
14291
  defined. `decision: 'approved' | 'denied' | null = null` (reflected) — decided state, set by the
12574
14292
  component on activation and host-writable (an externally-resolved decision renders identically but
12575
- emits nothing). `tone: 'neutral' | 'danger' = 'neutral'` (reflected).
14293
+ emits nothing). `tone: 'neutral' | 'danger' = 'neutral'` (reflected). `compact: boolean = false`
14294
+ (reflected) — collapses the bar from a full card (bordered, padded, `display: block` surface) to a
14295
+ single inline row with no chrome of its own, for a confirmation that has to live inside an existing
14296
+ container: a table cell, a card's action row, a toolbar. The host becomes `inline-flex`, and the
14297
+ narrow-allocation `@container` treatment is switched off — a compact bar is *expected* to be narrow,
14298
+ so stretching the buttons to fill would be exactly wrong. Re-chrome it through the
14299
+ `--lr-confirm-bar-compact-*` properties below. Everything else is unchanged: the event shapes, the
14300
+ focus-to-`[part="status"]`-before-unmount contract, and `role="group"` with its heading label.
12576
14301
 
12577
14302
  **Slots:** default — supplementary body content between the heading and the actions (e.g. a
12578
14303
  `lr-diff-view`). `footer` — extra content at the start of the action row.
@@ -12585,6 +14310,24 @@ details/json-viewer wrapper, only rendered when `args` is defined), `footer`, `d
12585
14310
  `approve-button` (named identically to the dialog's parts), `status` (the decided-state text, always
12586
14311
  present in the DOM as a focus landing spot).
12587
14312
 
14313
+ **Themeable custom properties:** the `compact` presentation is deliberately chrome-less by default
14314
+ and re-chromed entirely through five properties, all scoped to `[part="base"]` while `compact`:
14315
+ `--lr-confirm-bar-compact-padding` (default `0`, any padding shorthand),
14316
+ `--lr-confirm-bar-compact-gap` (default `var(--lr-space-s)`, the gap between the row's items),
14317
+ `--lr-confirm-bar-compact-border` (default `none`, any `border` shorthand),
14318
+ `--lr-confirm-bar-compact-background` (default `transparent`) and
14319
+ `--lr-confirm-bar-compact-radius` (default `0` — only visible once the border or background is set).
14320
+ They are inline `var()` fallbacks at their point of use rather than `:host` declarations, so any of
14321
+ them can be set on the element *or on any ancestor*, which is what makes "give every compact confirm
14322
+ bar in this panel a hairline border" a one-rule change on the panel.
14323
+
14324
+ **Known gotchas:**
14325
+ - `[part="status"]` is always rendered and must never be given `display: none`. Deciding moves focus
14326
+ to it synchronously, before the Deny/Approve buttons unmount, so hiding it would drop focus to
14327
+ `<body>`. The shipped `:empty` rule on it has never matched, and that is load-bearing.
14328
+ - `[part="deny-button"]` and `[part="approve-button"]` are raw `<button>` elements, not composed
14329
+ `lr-button`s, so `--lr-button-*` theming does not reach them. Style them through their parts.
14330
+
12588
14331
  ```html
12589
14332
  <lr-tool-call-chip status="pending"></lr-tool-call-chip>
12590
14333
  <lr-confirm-bar tool-name="run_shell" .args=${args}
@@ -12667,12 +14410,22 @@ src? }`, with the sanitized download URL).
12667
14410
 
12668
14411
  **CSS parts:** `base`, `header`, `label`, `kind`, `view-toggle` (rendered only once the `code` slot
12669
14412
  has content), `view-button` (carries `data-view="preview"` or `data-view="code"`), `version-nav`
12670
- (rendered only once `versions` is non-empty), `version-previous`, `version-next`, `version-position`
14413
+ (rendered only once `versions` is non-empty), `version-previous`, `version-previous-glyph` (the `‹`
14414
+ chevron inside `version-previous`, mirrored via `scaleX(-1)` under `:dir(rtl)`), `version-next`,
14415
+ `version-next-glyph` (the `›` chevron inside `version-next`, mirrored the same way), `version-position`
12671
14416
  (the "Version N of M" text), `restore-button` (rendered only while the active version isn't the
12672
14417
  latest), `actions`, `copy-button` (rendered only while `copyText` is non-empty), `download-button`
12673
14418
  (rendered only while `downloadSrc` is non-empty), `body`, `streaming-indicator` (rendered only while
12674
14419
  `streaming`).
12675
14420
 
14421
+ **Themeable custom properties:** `--lr-artifact-panel-view-active-bg` (default
14422
+ `var(--lr-color-brand-quiet)`) and `--lr-artifact-panel-view-active-color` (default
14423
+ `var(--lr-color-brand)`) — the background and text color of the pressed (active) preview/code toggle
14424
+ button. Both follow the state-scoped-property convention described under `lr-span-waterfall`: inline
14425
+ `var()` fallbacks rather than `:host` declarations, so either can be set on the element or on any
14426
+ ancestor. They exist because `::part(view-button)[aria-pressed='true']` is invalid CSS, leaving the
14427
+ library-wide brand tokens as the only prior lever.
14428
+
12676
14429
  ```html
12677
14430
  <lr-artifact-panel label="report.md" kind="document" .versions=${versions}
12678
14431
  @lr-restore=${(e) => restoreVersion(e.detail.versionId)}>
@@ -12718,6 +14471,16 @@ cancelable. Retry is available for `error` and `cancelled`.
12718
14471
  `show-retry`) — whether the built-in buttons may render at all, still gated by the run's own
12719
14472
  status. Both use a `true`-defaulting string converter, so plain-HTML `show-cancel="false"` works; a
12720
14473
  `?show-cancel=${false}` boolean-attribute binding starting from absent markup does not
14474
+ - `compact: boolean = false` (reflected) — tighter root padding and header/body gap for dense
14475
+ contexts (a run rendered as a row in a list, or in a side panel); same convention as `lr-empty`'s
14476
+ `compact`. Purely a density knob: the border and background stay, so reach for
14477
+ `appearance="plain"` instead when the goal is to drop the chrome entirely
14478
+ - `appearance: 'card' | 'plain' = 'card'` (reflected) — visual chrome, mirroring `lr-card`'s
14479
+ `appearance` vocabulary. `'card'` keeps the bordered, filled, padded box; `'plain'` removes the
14480
+ border, background, padding and corner radius, so a run nested inside a host frame that already
14481
+ draws a border doesn't double it. `plain` wins over `compact` when both are set — there is no
14482
+ padding left to tighten. The built-in Cancel/Retry buttons draw their own border and background
14483
+ and stay visibly interactive either way
12721
14484
 
12722
14485
  **Events:** `lr-cancel` (`detail: CancelEventDetail` = `{ reason?: string }`, from
12723
14486
  `@aceshooting/lyra-ui/ai`; `reason` is `undefined` from the built-in button), `lr-retry`
@@ -12734,7 +14497,12 @@ this component's own retry counter, reset when `run.id` changes).
12734
14497
  (carries `data-variant`), `empty`.
12735
14498
 
12736
14499
  **Themeable custom properties:** `--lr-agent-run-spin` (default `1s linear`) — the running-status
12737
- spinner icon's rotation duration/timing.
14500
+ spinner icon's rotation duration/timing. `--lr-agent-run-compact-padding` (default
14501
+ `var(--lr-space-s)`) and `--lr-agent-run-compact-gap` (default `var(--lr-space-s)`) — `[part="base"]`'s
14502
+ padding, and the gap between its header and body, while `compact`; both are ignored while `compact`
14503
+ is unset. Like the other density/state properties in this family they are inline `var()` fallbacks at
14504
+ their point of use rather than `:host` declarations, so either can be set on the element *or on any
14505
+ ancestor* — one rule on a run list retunes every compact run inside it.
12738
14506
 
12739
14507
  ## `lr-agent-trace`
12740
14508
 
@@ -12767,6 +14535,17 @@ graph node-type ids).
12767
14535
  visible span has `kind: 'agent'`), `handoff` (one entry — a `<button>` wrapping an
12768
14536
  `lr-handoff-divider`, carrying `data-active`), `tree` (the composed `lr-trace-tree`).
12769
14537
 
14538
+ **Themeable custom properties:** `--lr-agent-trace-handoff-active-bg` (default
14539
+ `var(--lr-color-brand-quiet)`) — the background of the active (`activeSpanId`) handoff quick-jump
14540
+ entry. Same state-scoped-property convention described under `lr-span-waterfall`: an inline `var()`
14541
+ fallback rather than a `:host` declaration, settable on the element or any ancestor, and it exists
14542
+ because `::part(handoff)[data-active]` is invalid CSS. The composed tree's own
14543
+ `--lr-trace-tree-row-active-bg` and `--lr-trace-tree-row-active-color` are separate knobs and
14544
+ inherit straight through, so restyling both surfaces means setting both — and they carry the
14545
+ pairing caveat documented under `lr-trace-tree` above: the tree's active-row defaults assume the
14546
+ active background stays on the same side of the lightness midpoint as the ambient surface, so a
14547
+ tint that crosses it needs the matching text color set too.
14548
+
12770
14549
  ## `lr-context-inspector`
12771
14550
 
12772
14551
  Inspection view of model-call context segments, with token estimates, source citations, redaction
@@ -12830,7 +14609,9 @@ Filterable and taggable evaluation-example list with add, remove, import, and ex
12830
14609
 
12831
14610
  **Events:** `lr-example-select` (`detail: { id: string | null }`), `lr-example-add-request`
12832
14611
  (`detail: undefined`), `lr-example-remove-request` (`detail: { id: string }`), `lr-import-request`
12833
- (`detail: { files: File[] }`), `lr-export-request` (`detail: { format: string }`).
14612
+ (`detail: { files: File[] }`), `lr-export-request` (`detail: { format: string }`). `focus`/`blur` —
14613
+ re-dispatched (no detail) when the internal search field (only rendered while `searchable`) gains or
14614
+ loses focus, since native focus neither bubbles nor crosses the shadow boundary.
12834
14615
 
12835
14616
  **CSS parts:** `base`, `toolbar`, `search`, `search-input`, `tag-filter`, `grid`,
12836
14617
  `add-button`, `remove-button`, `import`, `export`.
@@ -12935,6 +14716,16 @@ gate.
12935
14716
  **CSS parts:** `base`, `empty`, `summary`, `count`, `state-badge`,
12936
14717
  `list`, `decision`, `decision-header`, `category`, `label`, `detail`, `explanation`.
12937
14718
 
14719
+ **Themeable custom properties:** `--lr-policy-summary-count-allow-color` (default
14720
+ `var(--lr-color-success)`), `--lr-policy-summary-count-deny-color` (default
14721
+ `var(--lr-color-danger)`) and `--lr-policy-summary-count-needs-review-color` (default
14722
+ `var(--lr-color-warning)`) — the text color of each state's count in the summary strip. All three
14723
+ follow the state-scoped-property convention described under `lr-span-waterfall`: inline `var()`
14724
+ fallbacks rather than `:host` declarations, so each can be set on the element or on any ancestor.
14725
+ They exist because `::part(count)[data-state='deny']` is invalid CSS — Shadow Parts forbids an
14726
+ attribute selector after `::part()` — so retoning one state's count otherwise meant overriding the
14727
+ library-wide status tokens and repainting every other surface reading them.
14728
+
12938
14729
  ## `lr-tool-timeline`
12939
14730
 
12940
14731
  Chronological list of agent tool/function calls composed from tool-call, result, and approval
@@ -12978,7 +14769,12 @@ can ignore it; one actually executing the tool needs it.
12978
14769
 
12979
14770
  **Themeable custom properties:** `--lr-tool-timeline-gap` (default `var(--lr-space-l)`) — vertical
12980
14771
  gap between entries; `--lr-tool-timeline-marker-size` (default `var(--lr-size-0-625rem)`) — the
12981
- per-entry timeline marker dot's size, which also sets the entry grid's leading column width.
14772
+ per-entry timeline marker dot's size, which also sets the entry grid's leading column width;
14773
+ `--lr-tool-timeline-denied-marker-color` (default `var(--lr-color-warning)`) — rail-dot color for a
14774
+ `status="denied"` entry, decoupled from the pending-approval border color below so either can be
14775
+ retinted independently; `--lr-tool-timeline-pending-approval-border-color` (default
14776
+ `var(--lr-color-warning)`) — color of the entry body's leading border while that entry's
14777
+ `data-pending-approval` is `"true"`.
12982
14778
 
12983
14779
  # Retrieval, knowledge graph & grounding (`components/retrieval/`)
12984
14780
 
@@ -13074,7 +14870,10 @@ Enter/Space activations within 500ms — regardless of `GraphNode.expandable`),
13074
14870
  `label`, `link-label` (a drawn edge label, only rendered when `showEdgeLabels` is set),
13075
14871
  `expand-indicator` (the "+" badge on a node with `expandable: true`), `focus-halo` (the persistent
13076
14872
  ring tracking `focusId`'s node), `hull` (a community hull), `community-label`,
13077
- `live-region`, `data-list`, `empty`, `canvas`/`tooltip`/`cursor-items`/`cursor-item`
14873
+ `live-region`, `data-list`, `empty`, `error` (`role="alert"` message shown instead of the graph when
14874
+ the optional `d3-force`/`d3-drag`/`d3-zoom`/`d3-selection` peers fail to load —
14875
+ distinct from the empty state, which means the peers loaded fine but `nodes` is empty),
14876
+ `canvas`/`tooltip`/`cursor-items`/`cursor-item`
13078
14877
  (`renderer="canvas"` only — the drawing surface, its hover tooltip replacing the SVG `<title>`, and
13079
14878
  the offscreen keyboard-roving items)
13080
14879
 
@@ -13215,7 +15014,9 @@ with a `droppable` canvas on the `FLOW_PALETTE_MIME_TYPE` drag payload shape.
13215
15014
 
13216
15015
  **Events:** `lr-palette-place` (`detail: { type }`, a pointer click or Enter/Space — the
13217
15016
  click/keyboard alternative to dragging), `lr-select` (`detail: { item }`, emitted alongside
13218
- `lr-palette-place` on both gestures, carrying the full item).
15017
+ `lr-palette-place` on both gestures, carrying the full item), `focus`/`blur` (no detail —
15018
+ re-dispatched from the internal search field's own `focus`/`blur`, bubbling and composed unlike
15019
+ the native events, since neither bubbles nor crosses the shadow boundary on its own).
13219
15020
 
13220
15021
  **Slots:** `header` (content above the search field, e.g. a heading or tabs), `footer` (content
13221
15022
  below the list).
@@ -13278,7 +15079,10 @@ after each toggle).
13278
15079
  **CSS parts:** `base`, `item` (a `<button>` when `interactive`, a plain `<div>` otherwise), `swatch`,
13279
15080
  `label`, `count`, `live-region` (the visually hidden filter-toggle announcement).
13280
15081
 
13281
- **Themeable custom properties:** no component-local tokens; reads `--lr-graph-cat-1` through `-8`
15082
+ **Themeable custom properties:** `--lr-graph-legend-hidden-color` (default
15083
+ `var(--lr-color-text-quiet)`) — text color of a filtered-out (hidden) row's `label`/`count`,
15084
+ independent of the shared quiet-text token so a host can retint "hidden" rows without repainting
15085
+ every other quiet-text surface. Also reads `--lr-graph-cat-1` through `-8`
13282
15086
  (the same computed-style fallback palette `lr-graph`/`lr-word-cloud` use) plus shared tokens.
13283
15087
 
13284
15088
  **Optional peer deps:** none.
@@ -13321,6 +15125,15 @@ itself — `lr-entity-activate` is a request a host routes into `lr-graph`'s own
13321
15125
  `lr-graph-legend.types` entry shape, resolving `entity.type` to a label/color/shape for the badge
13322
15126
  - `communityLabel: string = ''` (attribute `community-label`) — override text for the community chip
13323
15127
  - `showFocusButton: boolean = true` (attribute `show-focus-button`)
15128
+ - `compact: boolean = false` (reflected) — tighter root padding and row gap for dense contexts (a
15129
+ dossier rendered in a sidebar, a result list) — the same convention as `lr-empty`'s `compact` and
15130
+ as this component's sibling `lr-community-card`. Purely a density knob: the border and background
15131
+ stay. `false` (the default) keeps the full card padding.
15132
+ - `appearance: 'card' | 'plain' = 'card'` (reflected) — visual chrome, mirroring `lr-card`'s
15133
+ `appearance` vocabulary. `'card'` (the default) keeps the bordered, filled, padded box; `'plain'`
15134
+ removes the border, background, padding and corner radius, so a card nested inside a container
15135
+ that already draws a border doesn't double the frame. `plain` wins over `compact` when both are
15136
+ set — there is nothing left to tighten.
13324
15137
 
13325
15138
  **Events:** `lr-entity-activate` (`detail: { id }`, the built-in focus button was activated).
13326
15139
 
@@ -13331,7 +15144,11 @@ itself — `lr-entity-activate` is a request a host routes into `lr-graph`'s own
13331
15144
  `description`, `properties`, `property` (one key/value row), `degree`, `community`, `actions`,
13332
15145
  `focus-button`, `empty` (shown when `entity` is `null`).
13333
15146
 
13334
- **Themeable custom properties:** shared tokens only; a data-driven `entity.type` color is applied as
15147
+ **Themeable custom properties:** `--lr-entity-card-compact-padding` (default `var(--lr-space-s)`)
15148
+ `[part='base']`'s padding while `compact`; `--lr-entity-card-compact-gap` (default
15149
+ `var(--lr-space-xs)`) — the gap between `[part='base']`'s rows while `compact`. Both apply only in
15150
+ the `compact` state, so a dense card can be tuned without re-pointing shared spacing tokens for
15151
+ everything else. Otherwise shared tokens; a data-driven `entity.type` color is applied as
13335
15152
  sanitized inline `--lr-badge-*` overrides on the type badge only (the one "type color is
13336
15153
  data-driven by design" exception this library already grants graph nodes) — every other color comes
13337
15154
  from tokens.
@@ -13417,10 +15234,13 @@ name and detail shape as `lr-graph`'s own event, so one host handler serves both
13417
15234
 
13418
15235
  **Slots:** none.
13419
15236
 
13420
- **CSS parts:** `base` (`role="list"`), `group-header` (only when `groupByRelation`), `row`
13421
- (`role="listitem"`), `direction` (`aria-hidden` glyph), `relation`, `node-label`, `node-meta`
13422
- (secondary type/degree text, when present), `expand-button` (only when `expandable`), `empty`
13423
- (shown when `rows` is empty).
15237
+ **CSS parts:** `base` (`role="list"`), `group-header` (only when `groupByRelation`; above
15238
+ `virtualizeAt` this is the internal virtual-list's own group label, re-exported under the same
15239
+ name), `row` (`role="listitem"`; above `virtualizeAt` this is the internal virtual-list's own row
15240
+ wrapper, re-exported under the same name), `direction` (`aria-hidden` glyph), `relation`,
15241
+ `node-label`, `node-meta` (secondary type/degree text, when present), `expand-button` (only when
15242
+ `expandable`), `empty` (shown when `rows` is empty). Every part presents identically either side of
15243
+ `virtualizeAt`.
13424
15244
 
13425
15245
  **Themeable custom properties:** shared tokens only.
13426
15246
 
@@ -13438,6 +15258,9 @@ name and detail shape as `lr-graph`'s own event, so one host handler serves both
13438
15258
  **Known gotchas:**
13439
15259
  - `lr-node-expand`'s detail shape is intentionally identical to `lr-graph`'s own event of the
13440
15260
  same name, so a single listener wired to both handles "expand this node's neighborhood" uniformly.
15261
+ - A row is exactly one `[part="row"]` element in both rendering paths. Above `virtualizeAt` that
15262
+ element is the internal virtual-list's own row wrapper (the component renders only the row's
15263
+ content into it), so a `::part(row)` rule applies once, not twice.
13441
15264
 
13442
15265
  ---
13443
15266
 
@@ -13499,6 +15322,11 @@ graph or membership fetching — `lr-drill` asks the host to load members/subgra
13499
15322
  - `maxMembers: number = 8` (attribute `max-members`) — remaining members collapse into a "+N"
13500
15323
  overflow chip
13501
15324
  - `compact: boolean = false` (reflected) — omits the summary excerpt and member chips
15325
+ - `appearance: 'card' | 'plain' = 'card'` (reflected) — visual chrome, mirroring `lr-card`'s
15326
+ `appearance` vocabulary and this component's sibling `lr-entity-card`'s identical property.
15327
+ `'card'` (the default) keeps the bordered, filled, padded box; `'plain'` removes the border,
15328
+ background, and padding, so a card nested inside a container that already draws a border doesn't
15329
+ double the frame.
13502
15330
 
13503
15331
  **Events:** `lr-drill` (`detail: { id }`, the drill button, header, or overflow chip — all three
13504
15332
  mean "show me this whole community"), `lr-entity-activate` (`detail: { id }`, a member chip was
@@ -13555,13 +15383,41 @@ activated).
13555
15383
 
13556
15384
  **Slots:** none.
13557
15385
 
13558
- **CSS parts:** `base` (`role="group"`), `chunk` (`role="listitem"`), `score` (visible percent text),
13559
- `score-bar` (`aria-hidden` track), `score-fill` (tone-mapped fill), `open-button`, `title` (the
13560
- `<span>` inside `open-button` carrying the visible title text), `text` (line-clamped unless
13561
- expanded, omitted when `compact`), `toggle` ("Show more"/"Show less", omitted when `compact`),
15386
+ **CSS parts:** `base` (`role="group"`), `chunk` (one chunk row; carries `role="listitem"` only
15387
+ below `virtualize-at` while virtualized the surrounding `lr-virtual-list` row supplies that role
15388
+ instead), `chunk-current` (additional part on the row matching `activeId`), `score` (visible
15389
+ percent text), `score-current` (additional part on the current row's score line), `score-bar`
15390
+ (`aria-hidden` track), `score-fill` (tone-mapped fill), `score-fill-success` /
15391
+ `score-fill-warning` / `score-fill-danger` (additional part on the fill, one per scoring tier),
15392
+ `open-button`, `title` (the `<span>` inside `open-button` carrying the visible title text), `text`
15393
+ (omitted when `compact`), `text-clamped` (additional part on a `text` preview that is still
15394
+ collapsed; dropped once expanded), `toggle` ("Show more"/"Show less", omitted when `compact`),
13562
15395
  `empty` (shown when `chunks` is empty).
13563
15396
 
13564
- **Themeable custom properties:** shared tokens only.
15397
+ Every row-level part is reachable through `::part()` in both rendering paths: above
15398
+ `virtualize-at` the row lives in the internal `lr-virtual-list`'s shadow root and its parts are
15399
+ re-exported from there under the same names. Row *state* is exposed as an additional part name
15400
+ rather than as an attribute on the part, because Shadow Parts forbids an attribute selector after
15401
+ `::part()` — `::part(chunk)[aria-current='true']` is invalid CSS. The equivalent attributes
15402
+ (`aria-current`, `data-tone`, `data-clamped`) are still present on the elements. A state part is a
15403
+ second token in the same `part` attribute, so a `[part~="…"]` (not `[part="…"]`) selector is the
15404
+ one that matches inside a tree.
15405
+
15406
+ **Themeable custom properties:** `--lr-chunk-inspector-current-bg` (default
15407
+ `var(--lr-color-brand-quiet)`) — the background of the chunk matching `activeId`.
15408
+ `--lr-chunk-inspector-current-color` (default `var(--lr-color-text)`) — the text color of that
15409
+ chunk's `score` line (`::part(score-current)`). Both are inline `var()` fallbacks at the point of
15410
+ use rather than `:host` declarations, so either can be set on the element *or on any ancestor*:
15411
+ `::part(chunk)[data-active]` is invalid CSS — Shadow Parts forbids an attribute selector after
15412
+ `::part()` — which is why the current-chunk state is also published as its own part name
15413
+ (`chunk-current`, `score-current`); either the custom properties or `::part(chunk-current)` will
15414
+ retint it.
15415
+
15416
+ **They are a contrast-sensitive pair — override them together, never one alone.** The `-current-color`
15417
+ hook exists precisely because the quiet token it replaces only reaches about 4.24:1 against the
15418
+ current background; keep any override at 4.5:1 or better against `--lr-chunk-inspector-current-bg`.
15419
+
15420
+ Plus shared tokens otherwise.
13565
15421
 
13566
15422
  **Optional peer deps:** none.
13567
15423
 
@@ -13614,7 +15470,19 @@ fired after every toggle including select-all).
13614
15470
  `lr-file-icon` type badge), `label`, `empty` (`noData` when `sources` is empty, `noMatches` when a
13615
15471
  filter empties the tree).
13616
15472
 
13617
- **Themeable custom properties:** shared tokens only.
15473
+ **Themeable custom properties:** `--lr-source-picker-checked-bg` the background of a fully-checked
15474
+ selection control: the `select-all` pill (whose resting default is `var(--lr-color-brand-quiet)`) and
15475
+ a fully-selected entry's `[part='checkbox']` (whose resting default is `var(--lr-color-brand)`). The
15476
+ two keep their distinct defaults while it is unset; setting it unifies both.
15477
+ `--lr-source-picker-checked-border` (default `var(--lr-color-brand)`) — the border color of every
15478
+ checked *or* mixed selection control. `--lr-source-picker-mixed-bg` (default
15479
+ `color-mix(in srgb, var(--lr-color-brand) 50%, var(--lr-color-surface))`) — the background of a
15480
+ partially-selected entry's `[part='checkbox']`, so a tri-state folder reads as distinct from a fully
15481
+ selected one. All three are inline `var()` fallbacks at the point of use rather than `:host`
15482
+ declarations, so each can be set on the element *or on any ancestor*:
15483
+ `::part(checkbox)[aria-checked='true']` is invalid CSS — Shadow Parts forbids an attribute selector
15484
+ after `::part()` — which previously left re-pointing the library-wide `--lr-color-brand` token as
15485
+ the only lever, repainting every other brand surface with it. Plus shared tokens otherwise.
13618
15486
 
13619
15487
  **Optional peer deps:** none.
13620
15488
 
@@ -13709,7 +15577,9 @@ keyboard descent).
13709
15577
  announcement region), `empty` (shown when `topics` is empty).
13710
15578
 
13711
15579
  **Themeable custom properties:** `--lr-mind-map-ring-gap` (default `6rem`, radius step per depth
13712
- ring).
15580
+ ring). `--lr-mind-map-node-hover-halo` (default `var(--lr-color-brand-quiet)`) — stroke color of
15581
+ the halo drawn around a topic node's dot on `:hover`, giving mouse users the same "this is
15582
+ clickable" feedback keyboard users already get from the drawn `focus-ring` part.
13713
15583
 
13714
15584
  **Optional peer deps:** none.
13715
15585
 
@@ -13873,6 +15743,15 @@ while collapsed).
13873
15743
  - `page?: string | number` — optional page reference, e.g. `12` or `"iv"`, rendered as-is (never
13874
15744
  parsed/validated as a number), appended to the title as `" — p. {page}"`.
13875
15745
  - `href?: string` — optional URL, echoed back (unopened) in `lr-open`'s detail.
15746
+ - `compact: boolean = false` (reflected) — tighter root padding and row gap, for the dense citation
15747
+ lists these cards usually render in — the same convention as `lr-empty`'s `compact`. Purely a
15748
+ density knob: the border and background stay. `false` (the default) keeps the full card padding.
15749
+ - `appearance: 'card' | 'plain' = 'card'` (reflected) — visual chrome, mirroring `lr-card`'s
15750
+ `appearance` vocabulary. `'card'` (the default) keeps the bordered, filled, padded box; `'plain'`
15751
+ removes the border, background, padding and corner radius, so a card inside a `<lr-source-list>`
15752
+ (or any container already drawing its own border/dividers) doesn't double the frame. `plain` wins
15753
+ over `compact` when both are set — nothing left to tighten. The title and toggle keep their brand
15754
+ color and hover underline under `plain`, since neither ever depended on the card chrome.
13876
15755
 
13877
15756
  **Events:**
13878
15757
  - `lr-expand` (`detail: { sourceId: string; expanded: boolean }`) — the per-card "Show
@@ -13893,7 +15772,11 @@ behind the "Show more"/"Show less" toggle — when left empty, no toggle renders
13893
15772
  (wrapper around the `full` slot, `hidden` while collapsed), `toggle` (the "Show more"/"Show less"
13894
15773
  button — only rendered when the `full` slot has content).
13895
15774
 
13896
- **Themeable custom properties:** shared tokens only — `--lr-color-border`, `--lr-color-surface`,
15775
+ **Themeable custom properties:** `--lr-source-card-compact-padding` (default `var(--lr-space-xs)`) —
15776
+ `[part='base']`'s padding while `compact`; `--lr-source-card-compact-gap` (default
15777
+ `var(--lr-space-2xs)`) — the gap between `[part='base']`'s rows while `compact`. Both apply only in
15778
+ the `compact` state, so a dense citation list can be tuned without re-pointing shared spacing tokens
15779
+ elsewhere. Plus shared tokens — `--lr-color-border`, `--lr-color-surface`,
13897
15780
  `--lr-color-text` / `-text-quiet`, `--lr-color-brand`, `--lr-radius`, `--lr-space-xs`/`-s`,
13898
15781
  `--lr-focus-ring-*`.
13899
15782
 
@@ -14092,6 +15975,14 @@ per-item stage label), `item-progress`,
14092
15975
  `item-error` (only for `stage="failed"` with `error` set), `item-actions`, `retry-button`,
14093
15976
  `cancel-button`, `empty`.
14094
15977
 
15978
+ In virtualized mode (at or above `virtualizeThreshold`) the rows live in the internal
15979
+ `lr-virtual-list`'s shadow root, and `item`, `item-header`, `item-name`, `item-progress`,
15980
+ `item-meta`, `item-error`, `item-actions`, `retry-button` and `cancel-button` are forwarded out
15981
+ through `exportparts`, so `lr-ingestion-queue::part(item)` and the rest keep working from a consumer
15982
+ stylesheet. `item-stage`, `item-chunk-count`, `item-embedding-status` and `item-attempts` are not
15983
+ forwarded, so those four are only reachable through `::part()` while the queue is below the
15984
+ threshold.
15985
+
14095
15986
  **Themeable custom properties:** `--lr-ingestion-queue-max-height` (default `none`) — non-virtualized
14096
15987
  mode only: caps how tall the list grows before it scrolls internally. No effect once virtualized —
14097
15988
  retheme the internal list via `lr-virtual-list { --lr-virtual-list-height: … }` instead.
@@ -14278,7 +16169,12 @@ somewhere to land after a confirmation resolves), `item-row`, `item-text`, `conf
14278
16169
  `provenance` is unset; `item-body` is `hidden` while collapsed), `item-actions`, `add-button`,
14279
16170
  `remove-button`, `forget-all-button`.
14280
16171
 
14281
- **Themeable custom properties:** shared tokens only.
16172
+ **Themeable custom properties:** `--lr-memory-panel-confidence-success-color` (default
16173
+ `var(--lr-color-success)`), `--lr-memory-panel-confidence-warning-color` (default
16174
+ `var(--lr-color-warning)`), `--lr-memory-panel-confidence-danger-color` (default
16175
+ `var(--lr-color-danger)`) — text color of an item's `confidence` indicator, one per confidence
16176
+ tier (`high`/`medium`/`low` against `thresholds`, the same tiering `lr-chunk-inspector` uses for
16177
+ its score bar). Plus shared tokens otherwise.
14282
16178
 
14283
16179
  **Optional peer deps:** none.
14284
16180
 
@@ -14348,10 +16244,37 @@ neither `error` nor `loading` is set), `row` (a plain element in this shadow roo
14348
16244
  virtualization threshold; exported from the internal `lr-virtual-list`'s own `row` part while
14349
16245
  virtualized — `::part(row)` reaches it either way), `group-header` (exported from the virtual list's
14350
16246
  `group` part; grouped/virtualized mode only), `select` (per-row `lr-checkbox`, omitted when
14351
- `selectable` is false), `row-body` (carries `data-selected`), `metadata` (a `<dl>`; omitted when the
14352
- chunk has none or while `presentation="compact"`), `metadata-entry`, `load-more-row`, `load-more`.
14353
-
14354
- **Themeable custom properties:** shared tokens only.
16247
+ `selectable` is false), `row-body` (carries `data-selected`), `row-body-selected` (additional part
16248
+ on a selected `row-body`), `metadata` (a `<dl>`; omitted when the chunk has none or while
16249
+ `presentation="compact"`), `metadata-entry`, `metadata-term` (the `<dt>` carrying a metadata key),
16250
+ `metadata-value` (the `<dd>` carrying its value), `load-more-row`, `load-more`.
16251
+
16252
+ The per-row `lr-chunk-inspector`'s own parts are forwarded onward under a `chunk-` prefix —
16253
+ `chunk`, `chunk-current`, `chunk-score`, `chunk-score-current`, `chunk-score-bar`,
16254
+ `chunk-score-fill`, `chunk-score-fill-success`, `chunk-score-fill-warning`,
16255
+ `chunk-score-fill-danger`, `chunk-open-button`,
16256
+ `chunk-title`, `chunk-text`, `chunk-text-clamped`, `chunk-toggle`. Those elements sit two shadow
16257
+ hops deep while virtualized, so this forwarding is the only way to reach them.
16258
+
16259
+ Selection state is exposed as the additional `row-body-selected` part name rather than through the
16260
+ `data-selected` attribute, because Shadow Parts forbids an attribute selector after `::part()`:
16261
+ `::part(row-body)[data-selected]` is invalid CSS, and while virtualized `::part()` is the only way
16262
+ in. `data-selected` is unchanged. A state part is a second token in the same `part` attribute, so
16263
+ a `[part~="…"]` (not `[part="…"]`) selector is the one that matches inside a tree. The `<dt>`/`<dd>`
16264
+ carry their own part names for the same class of reason — `::part()` matches a single element and
16265
+ cannot be followed by a descendant combinator, so `::part(metadata-entry) dt` reaches nothing.
16266
+
16267
+ **Themeable custom properties:** `--lr-retrieval-results-selected-border` (default
16268
+ `var(--lr-color-brand)`) — the inline-start border color marking a selected row body
16269
+ (`::part(row-body-selected)`). A
16270
+ border rather than a fill by design: the row's own text (the nested chunk inspector's quiet-toned
16271
+ score line in particular) is sized and colored for the page's default surface, and a tinted
16272
+ background can drop it below the required contrast ratio, while a border-only indicator carries no
16273
+ such risk — so recoloring this hook is contrast-safe. It is an inline `var()` fallback at the point
16274
+ of use rather than a `:host` declaration, so it can be set on the element *or on any ancestor*:
16275
+ `::part(row-body)[data-selected]` is invalid CSS — Shadow Parts forbids an attribute selector after
16276
+ `::part()` — which previously left re-pointing the library-wide `--lr-color-brand` token as the only
16277
+ lever, repainting every other brand surface with it. Plus shared tokens otherwise.
14355
16278
 
14356
16279
  **Optional peer deps:** none.
14357
16280
 
@@ -14462,7 +16385,14 @@ no stage has evidence), `evidence-row` (omitted for a stage with no evidence), `
14462
16385
  `evidence-metadata` (a `<dl>`), `evidence-metadata-row` (one key/value pair), `evidence-metadata-key`
14463
16386
  (`<dt>`), `evidence-metadata-value` (`<dd>`).
14464
16387
 
14465
- **Themeable custom properties:** shared tokens only.
16388
+ **Themeable custom properties:** `--lr-retrieval-trace-active-border` (default
16389
+ `var(--lr-color-brand)`) — the border color of the `[part='evidence-row']` whose stage matches
16390
+ `activeStageId`, leaving every other row on the resting border token. It is an inline `var()`
16391
+ fallback at the point of use rather than a `:host` declaration, so it can be set on the element *or
16392
+ on any ancestor*: `::part(evidence-row)[data-active]` is invalid CSS — Shadow Parts forbids an
16393
+ attribute selector after `::part()` — so marking the active stage previously meant overriding the
16394
+ library-wide `--lr-color-brand` token and repainting every other brand surface with it. Unset, it
16395
+ falls back to that token, so rendering is unchanged. Plus shared tokens otherwise.
14466
16396
 
14467
16397
  **Optional peer deps:** none.
14468
16398