@aceshooting/lyra-ui 5.1.0 → 6.0.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 (1394) hide show
  1. package/CHANGELOG.md +3979 -0
  2. package/README.md +8 -6
  3. package/custom-elements.json +11849 -3874
  4. package/dist/components/agent-tools/activity-feed/activity-feed.class.d.ts +9 -0
  5. package/dist/components/agent-tools/activity-feed/activity-feed.class.d.ts.map +1 -1
  6. package/dist/components/agent-tools/activity-feed/activity-feed.class.js +33 -2
  7. package/dist/components/agent-tools/activity-feed/activity-feed.class.js.map +1 -1
  8. package/dist/components/agent-tools/activity-feed/activity-feed.styles.d.ts.map +1 -1
  9. package/dist/components/agent-tools/activity-feed/activity-feed.styles.js +34 -9
  10. package/dist/components/agent-tools/activity-feed/activity-feed.styles.js.map +1 -1
  11. package/dist/components/agent-tools/agent-run/agent-run.class.d.ts +18 -0
  12. package/dist/components/agent-tools/agent-run/agent-run.class.d.ts.map +1 -1
  13. package/dist/components/agent-tools/agent-run/agent-run.class.js +22 -0
  14. package/dist/components/agent-tools/agent-run/agent-run.class.js.map +1 -1
  15. package/dist/components/agent-tools/agent-run/agent-run.styles.d.ts.map +1 -1
  16. package/dist/components/agent-tools/agent-run/agent-run.styles.js +19 -0
  17. package/dist/components/agent-tools/agent-run/agent-run.styles.js.map +1 -1
  18. package/dist/components/agent-tools/agent-trace/agent-trace.class.d.ts +4 -0
  19. package/dist/components/agent-tools/agent-trace/agent-trace.class.d.ts.map +1 -1
  20. package/dist/components/agent-tools/agent-trace/agent-trace.class.js +4 -0
  21. package/dist/components/agent-tools/agent-trace/agent-trace.class.js.map +1 -1
  22. package/dist/components/agent-tools/agent-trace/agent-trace.styles.js +1 -1
  23. package/dist/components/agent-tools/artifact-panel/artifact-panel.class.d.ts +11 -2
  24. package/dist/components/agent-tools/artifact-panel/artifact-panel.class.d.ts.map +1 -1
  25. package/dist/components/agent-tools/artifact-panel/artifact-panel.class.js +9 -2
  26. package/dist/components/agent-tools/artifact-panel/artifact-panel.class.js.map +1 -1
  27. package/dist/components/agent-tools/artifact-panel/artifact-panel.styles.d.ts.map +1 -1
  28. package/dist/components/agent-tools/artifact-panel/artifact-panel.styles.js +17 -2
  29. package/dist/components/agent-tools/artifact-panel/artifact-panel.styles.js.map +1 -1
  30. package/dist/components/agent-tools/browser-frame/browser-frame.class.d.ts +7 -3
  31. package/dist/components/agent-tools/browser-frame/browser-frame.class.d.ts.map +1 -1
  32. package/dist/components/agent-tools/browser-frame/browser-frame.class.js +18 -2
  33. package/dist/components/agent-tools/browser-frame/browser-frame.class.js.map +1 -1
  34. package/dist/components/agent-tools/browser-frame/browser-frame.styles.d.ts.map +1 -1
  35. package/dist/components/agent-tools/browser-frame/browser-frame.styles.js +4 -0
  36. package/dist/components/agent-tools/browser-frame/browser-frame.styles.js.map +1 -1
  37. package/dist/components/agent-tools/commit-card/commit-card.class.d.ts +20 -1
  38. package/dist/components/agent-tools/commit-card/commit-card.class.d.ts.map +1 -1
  39. package/dist/components/agent-tools/commit-card/commit-card.class.js +41 -4
  40. package/dist/components/agent-tools/commit-card/commit-card.class.js.map +1 -1
  41. package/dist/components/agent-tools/commit-card/commit-card.styles.d.ts.map +1 -1
  42. package/dist/components/agent-tools/commit-card/commit-card.styles.js +24 -0
  43. package/dist/components/agent-tools/commit-card/commit-card.styles.js.map +1 -1
  44. package/dist/components/agent-tools/compare-panel/compare-panel.styles.d.ts.map +1 -1
  45. package/dist/components/agent-tools/compare-panel/compare-panel.styles.js +4 -1
  46. package/dist/components/agent-tools/compare-panel/compare-panel.styles.js.map +1 -1
  47. package/dist/components/agent-tools/confirm-bar/confirm-bar.class.d.ts +55 -4
  48. package/dist/components/agent-tools/confirm-bar/confirm-bar.class.d.ts.map +1 -1
  49. package/dist/components/agent-tools/confirm-bar/confirm-bar.class.js +90 -19
  50. package/dist/components/agent-tools/confirm-bar/confirm-bar.class.js.map +1 -1
  51. package/dist/components/agent-tools/confirm-bar/confirm-bar.d.ts +1 -0
  52. package/dist/components/agent-tools/confirm-bar/confirm-bar.d.ts.map +1 -1
  53. package/dist/components/agent-tools/confirm-bar/confirm-bar.js +1 -0
  54. package/dist/components/agent-tools/confirm-bar/confirm-bar.js.map +1 -1
  55. package/dist/components/agent-tools/confirm-bar/confirm-bar.styles.d.ts.map +1 -1
  56. package/dist/components/agent-tools/confirm-bar/confirm-bar.styles.js +56 -25
  57. package/dist/components/agent-tools/confirm-bar/confirm-bar.styles.js.map +1 -1
  58. package/dist/components/agent-tools/eval-dataset/eval-dataset.class.d.ts +14 -8
  59. package/dist/components/agent-tools/eval-dataset/eval-dataset.class.d.ts.map +1 -1
  60. package/dist/components/agent-tools/eval-dataset/eval-dataset.class.js +31 -15
  61. package/dist/components/agent-tools/eval-dataset/eval-dataset.class.js.map +1 -1
  62. package/dist/components/agent-tools/eval-dataset/eval-dataset.d.ts +1 -1
  63. package/dist/components/agent-tools/eval-dataset/eval-dataset.d.ts.map +1 -1
  64. package/dist/components/agent-tools/eval-dataset/eval-dataset.js +1 -1
  65. package/dist/components/agent-tools/eval-dataset/eval-dataset.js.map +1 -1
  66. package/dist/components/agent-tools/eval-dataset/eval-dataset.styles.d.ts.map +1 -1
  67. package/dist/components/agent-tools/eval-dataset/eval-dataset.styles.js +13 -2
  68. package/dist/components/agent-tools/eval-dataset/eval-dataset.styles.js.map +1 -1
  69. package/dist/components/agent-tools/eval-result/eval-result.class.d.ts +11 -9
  70. package/dist/components/agent-tools/eval-result/eval-result.class.d.ts.map +1 -1
  71. package/dist/components/agent-tools/eval-result/eval-result.class.js +9 -7
  72. package/dist/components/agent-tools/eval-result/eval-result.class.js.map +1 -1
  73. package/dist/components/agent-tools/eval-result/eval-result.d.ts +1 -1
  74. package/dist/components/agent-tools/eval-result/eval-result.d.ts.map +1 -1
  75. package/dist/components/agent-tools/eval-result/eval-result.js +1 -1
  76. package/dist/components/agent-tools/eval-result/eval-result.js.map +1 -1
  77. package/dist/components/agent-tools/policy-summary/policy-summary.class.d.ts +10 -1
  78. package/dist/components/agent-tools/policy-summary/policy-summary.class.d.ts.map +1 -1
  79. package/dist/components/agent-tools/policy-summary/policy-summary.class.js +15 -2
  80. package/dist/components/agent-tools/policy-summary/policy-summary.class.js.map +1 -1
  81. package/dist/components/agent-tools/policy-summary/policy-summary.styles.js +3 -3
  82. package/dist/components/agent-tools/result-card/result-card.class.d.ts +18 -0
  83. package/dist/components/agent-tools/result-card/result-card.class.d.ts.map +1 -1
  84. package/dist/components/agent-tools/result-card/result-card.class.js +21 -0
  85. package/dist/components/agent-tools/result-card/result-card.class.js.map +1 -1
  86. package/dist/components/agent-tools/result-card/result-card.styles.d.ts.map +1 -1
  87. package/dist/components/agent-tools/result-card/result-card.styles.js +21 -0
  88. package/dist/components/agent-tools/result-card/result-card.styles.js.map +1 -1
  89. package/dist/components/agent-tools/span-waterfall/span-waterfall.class.d.ts +3 -0
  90. package/dist/components/agent-tools/span-waterfall/span-waterfall.class.d.ts.map +1 -1
  91. package/dist/components/agent-tools/span-waterfall/span-waterfall.class.js +3 -0
  92. package/dist/components/agent-tools/span-waterfall/span-waterfall.class.js.map +1 -1
  93. package/dist/components/agent-tools/span-waterfall/span-waterfall.styles.d.ts.map +1 -1
  94. package/dist/components/agent-tools/span-waterfall/span-waterfall.styles.js +4 -1
  95. package/dist/components/agent-tools/span-waterfall/span-waterfall.styles.js.map +1 -1
  96. package/dist/components/agent-tools/stack-trace/stack-trace.class.d.ts +10 -1
  97. package/dist/components/agent-tools/stack-trace/stack-trace.class.d.ts.map +1 -1
  98. package/dist/components/agent-tools/stack-trace/stack-trace.class.js +28 -3
  99. package/dist/components/agent-tools/stack-trace/stack-trace.class.js.map +1 -1
  100. package/dist/components/agent-tools/stack-trace/stack-trace.styles.d.ts.map +1 -1
  101. package/dist/components/agent-tools/stack-trace/stack-trace.styles.js +14 -0
  102. package/dist/components/agent-tools/stack-trace/stack-trace.styles.js.map +1 -1
  103. package/dist/components/agent-tools/task-list/task-list.class.d.ts +18 -0
  104. package/dist/components/agent-tools/task-list/task-list.class.d.ts.map +1 -1
  105. package/dist/components/agent-tools/task-list/task-list.class.js +22 -0
  106. package/dist/components/agent-tools/task-list/task-list.class.js.map +1 -1
  107. package/dist/components/agent-tools/task-list/task-list.styles.d.ts.map +1 -1
  108. package/dist/components/agent-tools/task-list/task-list.styles.js +27 -1
  109. package/dist/components/agent-tools/task-list/task-list.styles.js.map +1 -1
  110. package/dist/components/agent-tools/terminal/terminal.class.d.ts +19 -1
  111. package/dist/components/agent-tools/terminal/terminal.class.d.ts.map +1 -1
  112. package/dist/components/agent-tools/terminal/terminal.class.js +62 -11
  113. package/dist/components/agent-tools/terminal/terminal.class.js.map +1 -1
  114. package/dist/components/agent-tools/terminal/terminal.styles.d.ts.map +1 -1
  115. package/dist/components/agent-tools/terminal/terminal.styles.js +7 -0
  116. package/dist/components/agent-tools/terminal/terminal.styles.js.map +1 -1
  117. package/dist/components/agent-tools/test-results/test-results.class.d.ts +10 -1
  118. package/dist/components/agent-tools/test-results/test-results.class.d.ts.map +1 -1
  119. package/dist/components/agent-tools/test-results/test-results.class.js +30 -3
  120. package/dist/components/agent-tools/test-results/test-results.class.js.map +1 -1
  121. package/dist/components/agent-tools/test-results/test-results.styles.d.ts.map +1 -1
  122. package/dist/components/agent-tools/test-results/test-results.styles.js +10 -3
  123. package/dist/components/agent-tools/test-results/test-results.styles.js.map +1 -1
  124. package/dist/components/agent-tools/tool-approval-dialog/tool-approval-dialog.class.d.ts +51 -5
  125. package/dist/components/agent-tools/tool-approval-dialog/tool-approval-dialog.class.d.ts.map +1 -1
  126. package/dist/components/agent-tools/tool-approval-dialog/tool-approval-dialog.class.js +120 -19
  127. package/dist/components/agent-tools/tool-approval-dialog/tool-approval-dialog.class.js.map +1 -1
  128. package/dist/components/agent-tools/tool-approval-dialog/tool-approval-dialog.d.ts +2 -1
  129. package/dist/components/agent-tools/tool-approval-dialog/tool-approval-dialog.d.ts.map +1 -1
  130. package/dist/components/agent-tools/tool-approval-dialog/tool-approval-dialog.js +2 -1
  131. package/dist/components/agent-tools/tool-approval-dialog/tool-approval-dialog.js.map +1 -1
  132. package/dist/components/agent-tools/tool-approval-dialog/tool-approval-dialog.styles.d.ts.map +1 -1
  133. package/dist/components/agent-tools/tool-approval-dialog/tool-approval-dialog.styles.js +6 -22
  134. package/dist/components/agent-tools/tool-approval-dialog/tool-approval-dialog.styles.js.map +1 -1
  135. package/dist/components/agent-tools/tool-call-chip/tool-call-chip.class.d.ts.map +1 -1
  136. package/dist/components/agent-tools/tool-call-chip/tool-call-chip.class.js +10 -0
  137. package/dist/components/agent-tools/tool-call-chip/tool-call-chip.class.js.map +1 -1
  138. package/dist/components/agent-tools/tool-call-chip/tool-call-chip.styles.js +1 -1
  139. package/dist/components/agent-tools/tool-param-form/tool-param-form.class.d.ts +14 -0
  140. package/dist/components/agent-tools/tool-param-form/tool-param-form.class.d.ts.map +1 -1
  141. package/dist/components/agent-tools/tool-param-form/tool-param-form.class.js +60 -1
  142. package/dist/components/agent-tools/tool-param-form/tool-param-form.class.js.map +1 -1
  143. package/dist/components/agent-tools/tool-param-form/tool-param-form.styles.d.ts.map +1 -1
  144. package/dist/components/agent-tools/tool-param-form/tool-param-form.styles.js +8 -0
  145. package/dist/components/agent-tools/tool-param-form/tool-param-form.styles.js.map +1 -1
  146. package/dist/components/agent-tools/tool-select-dialog/tool-select-dialog.styles.d.ts.map +1 -1
  147. package/dist/components/agent-tools/tool-select-dialog/tool-select-dialog.styles.js +8 -0
  148. package/dist/components/agent-tools/tool-select-dialog/tool-select-dialog.styles.js.map +1 -1
  149. package/dist/components/agent-tools/tool-timeline/tool-timeline.class.d.ts +5 -0
  150. package/dist/components/agent-tools/tool-timeline/tool-timeline.class.d.ts.map +1 -1
  151. package/dist/components/agent-tools/tool-timeline/tool-timeline.class.js +5 -0
  152. package/dist/components/agent-tools/tool-timeline/tool-timeline.class.js.map +1 -1
  153. package/dist/components/agent-tools/tool-timeline/tool-timeline.styles.d.ts.map +1 -1
  154. package/dist/components/agent-tools/tool-timeline/tool-timeline.styles.js +5 -2
  155. package/dist/components/agent-tools/tool-timeline/tool-timeline.styles.js.map +1 -1
  156. package/dist/components/agent-tools/trace-tree/trace-tree.class.d.ts +14 -0
  157. package/dist/components/agent-tools/trace-tree/trace-tree.class.d.ts.map +1 -1
  158. package/dist/components/agent-tools/trace-tree/trace-tree.class.js +14 -0
  159. package/dist/components/agent-tools/trace-tree/trace-tree.class.js.map +1 -1
  160. package/dist/components/agent-tools/trace-tree/trace-tree.styles.d.ts.map +1 -1
  161. package/dist/components/agent-tools/trace-tree/trace-tree.styles.js +39 -1
  162. package/dist/components/agent-tools/trace-tree/trace-tree.styles.js.map +1 -1
  163. package/dist/components/charts/chart/chart.class.d.ts +17 -0
  164. package/dist/components/charts/chart/chart.class.d.ts.map +1 -1
  165. package/dist/components/charts/chart/chart.class.js +90 -7
  166. package/dist/components/charts/chart/chart.class.js.map +1 -1
  167. package/dist/components/charts/chart/chart.styles.d.ts.map +1 -1
  168. package/dist/components/charts/chart/chart.styles.js +13 -0
  169. package/dist/components/charts/chart/chart.styles.js.map +1 -1
  170. package/dist/components/charts/chart/lite-chart.class.d.ts +5 -1
  171. package/dist/components/charts/chart/lite-chart.class.d.ts.map +1 -1
  172. package/dist/components/charts/chart/lite-chart.class.js.map +1 -1
  173. package/dist/components/conversation/agent-workspace/agent-workspace.class.d.ts.map +1 -1
  174. package/dist/components/conversation/agent-workspace/agent-workspace.class.js +18 -3
  175. package/dist/components/conversation/agent-workspace/agent-workspace.class.js.map +1 -1
  176. package/dist/components/conversation/audio-visualizer/audio-visualizer.class.d.ts +11 -1
  177. package/dist/components/conversation/audio-visualizer/audio-visualizer.class.d.ts.map +1 -1
  178. package/dist/components/conversation/audio-visualizer/audio-visualizer.class.js +36 -1
  179. package/dist/components/conversation/audio-visualizer/audio-visualizer.class.js.map +1 -1
  180. package/dist/components/conversation/branch-picker/branch-picker.class.d.ts.map +1 -1
  181. package/dist/components/conversation/branch-picker/branch-picker.class.js +1 -0
  182. package/dist/components/conversation/branch-picker/branch-picker.class.js.map +1 -1
  183. package/dist/components/conversation/branch-picker/branch-picker.styles.d.ts.map +1 -1
  184. package/dist/components/conversation/branch-picker/branch-picker.styles.js +6 -2
  185. package/dist/components/conversation/branch-picker/branch-picker.styles.js.map +1 -1
  186. package/dist/components/conversation/chat-composer/chat-composer.class.d.ts +25 -7
  187. package/dist/components/conversation/chat-composer/chat-composer.class.d.ts.map +1 -1
  188. package/dist/components/conversation/chat-composer/chat-composer.class.js +47 -22
  189. package/dist/components/conversation/chat-composer/chat-composer.class.js.map +1 -1
  190. package/dist/components/conversation/chat-composer/chat-composer.styles.d.ts.map +1 -1
  191. package/dist/components/conversation/chat-composer/chat-composer.styles.js +30 -3
  192. package/dist/components/conversation/chat-composer/chat-composer.styles.js.map +1 -1
  193. package/dist/components/conversation/chat-message/chat-message.class.d.ts +3 -1
  194. package/dist/components/conversation/chat-message/chat-message.class.d.ts.map +1 -1
  195. package/dist/components/conversation/chat-message/chat-message.class.js +5 -1
  196. package/dist/components/conversation/chat-message/chat-message.class.js.map +1 -1
  197. package/dist/components/conversation/chat-message/chat-message.styles.d.ts.map +1 -1
  198. package/dist/components/conversation/chat-message/chat-message.styles.js +10 -2
  199. package/dist/components/conversation/chat-message/chat-message.styles.js.map +1 -1
  200. package/dist/components/conversation/chat-viewport/chat-viewport.class.d.ts +10 -2
  201. package/dist/components/conversation/chat-viewport/chat-viewport.class.d.ts.map +1 -1
  202. package/dist/components/conversation/chat-viewport/chat-viewport.class.js +42 -4
  203. package/dist/components/conversation/chat-viewport/chat-viewport.class.js.map +1 -1
  204. package/dist/components/conversation/chat-viewport/chat-viewport.styles.d.ts.map +1 -1
  205. package/dist/components/conversation/chat-viewport/chat-viewport.styles.js +30 -2
  206. package/dist/components/conversation/chat-viewport/chat-viewport.styles.js.map +1 -1
  207. package/dist/components/conversation/checkpoint/checkpoint.styles.d.ts.map +1 -1
  208. package/dist/components/conversation/checkpoint/checkpoint.styles.js +3 -0
  209. package/dist/components/conversation/checkpoint/checkpoint.styles.js.map +1 -1
  210. package/dist/components/conversation/code-block/code-block-core.class.d.ts +8 -0
  211. package/dist/components/conversation/code-block/code-block-core.class.d.ts.map +1 -1
  212. package/dist/components/conversation/code-block/code-block-core.class.js +33 -56
  213. package/dist/components/conversation/code-block/code-block-core.class.js.map +1 -1
  214. package/dist/components/conversation/code-block/code-block-shared.d.ts +27 -0
  215. package/dist/components/conversation/code-block/code-block-shared.d.ts.map +1 -1
  216. package/dist/components/conversation/code-block/code-block-shared.js +61 -0
  217. package/dist/components/conversation/code-block/code-block-shared.js.map +1 -1
  218. package/dist/components/conversation/code-block/code-block.class.d.ts +30 -8
  219. package/dist/components/conversation/code-block/code-block.class.d.ts.map +1 -1
  220. package/dist/components/conversation/code-block/code-block.class.js +76 -65
  221. package/dist/components/conversation/code-block/code-block.class.js.map +1 -1
  222. package/dist/components/conversation/code-block/code-block.styles.d.ts.map +1 -1
  223. package/dist/components/conversation/code-block/code-block.styles.js +46 -16
  224. package/dist/components/conversation/code-block/code-block.styles.js.map +1 -1
  225. package/dist/components/conversation/code-block/greycat-language.d.ts +5 -0
  226. package/dist/components/conversation/code-block/greycat-language.d.ts.map +1 -1
  227. package/dist/components/conversation/code-block/greycat-language.js +48 -6
  228. package/dist/components/conversation/code-block/greycat-language.js.map +1 -1
  229. package/dist/components/conversation/code-block/shiki-dark-theme.d.ts +14 -0
  230. package/dist/components/conversation/code-block/shiki-dark-theme.d.ts.map +1 -0
  231. package/dist/components/conversation/code-block/shiki-dark-theme.js +92 -0
  232. package/dist/components/conversation/code-block/shiki-dark-theme.js.map +1 -0
  233. package/dist/components/conversation/conversation-item/conversation-item.class.d.ts +22 -0
  234. package/dist/components/conversation/conversation-item/conversation-item.class.d.ts.map +1 -1
  235. package/dist/components/conversation/conversation-item/conversation-item.class.js +46 -1
  236. package/dist/components/conversation/conversation-item/conversation-item.class.js.map +1 -1
  237. package/dist/components/conversation/conversation-item/conversation-item.styles.d.ts.map +1 -1
  238. package/dist/components/conversation/conversation-item/conversation-item.styles.js +31 -2
  239. package/dist/components/conversation/conversation-item/conversation-item.styles.js.map +1 -1
  240. package/dist/components/conversation/markdown/markdown-core.class.d.ts +20 -11
  241. package/dist/components/conversation/markdown/markdown-core.class.d.ts.map +1 -1
  242. package/dist/components/conversation/markdown/markdown-core.class.js +56 -249
  243. package/dist/components/conversation/markdown/markdown-core.class.js.map +1 -1
  244. package/dist/components/conversation/markdown/markdown-loader.d.ts +1 -3
  245. package/dist/components/conversation/markdown/markdown-loader.d.ts.map +1 -1
  246. package/dist/components/conversation/markdown/markdown-loader.js +7 -1
  247. package/dist/components/conversation/markdown/markdown-loader.js.map +1 -1
  248. package/dist/components/conversation/markdown/markdown-shared.d.ts +93 -0
  249. package/dist/components/conversation/markdown/markdown-shared.d.ts.map +1 -0
  250. package/dist/components/conversation/markdown/markdown-shared.js +252 -0
  251. package/dist/components/conversation/markdown/markdown-shared.js.map +1 -0
  252. package/dist/components/conversation/markdown/markdown.class.d.ts +20 -11
  253. package/dist/components/conversation/markdown/markdown.class.d.ts.map +1 -1
  254. package/dist/components/conversation/markdown/markdown.class.js +56 -249
  255. package/dist/components/conversation/markdown/markdown.class.js.map +1 -1
  256. package/dist/components/conversation/markdown/markdown.styles.d.ts.map +1 -1
  257. package/dist/components/conversation/markdown/markdown.styles.js +19 -0
  258. package/dist/components/conversation/markdown/markdown.styles.js.map +1 -1
  259. package/dist/components/conversation/message-actions/message-actions.styles.d.ts.map +1 -1
  260. package/dist/components/conversation/message-actions/message-actions.styles.js +4 -0
  261. package/dist/components/conversation/message-actions/message-actions.styles.js.map +1 -1
  262. package/dist/components/conversation/message-feedback/message-feedback.class.d.ts +29 -3
  263. package/dist/components/conversation/message-feedback/message-feedback.class.d.ts.map +1 -1
  264. package/dist/components/conversation/message-feedback/message-feedback.class.js +34 -1
  265. package/dist/components/conversation/message-feedback/message-feedback.class.js.map +1 -1
  266. package/dist/components/conversation/message-feedback/message-feedback.styles.d.ts.map +1 -1
  267. package/dist/components/conversation/message-feedback/message-feedback.styles.js +23 -9
  268. package/dist/components/conversation/message-feedback/message-feedback.styles.js.map +1 -1
  269. package/dist/components/conversation/model-select/model-select.class.d.ts +21 -0
  270. package/dist/components/conversation/model-select/model-select.class.d.ts.map +1 -1
  271. package/dist/components/conversation/model-select/model-select.class.js +65 -1
  272. package/dist/components/conversation/model-select/model-select.class.js.map +1 -1
  273. package/dist/components/conversation/model-select/model-select.styles.d.ts.map +1 -1
  274. package/dist/components/conversation/model-select/model-select.styles.js +45 -6
  275. package/dist/components/conversation/model-select/model-select.styles.js.map +1 -1
  276. package/dist/components/conversation/push-to-talk/push-to-talk.class.d.ts +3 -0
  277. package/dist/components/conversation/push-to-talk/push-to-talk.class.d.ts.map +1 -1
  278. package/dist/components/conversation/push-to-talk/push-to-talk.class.js +17 -1
  279. package/dist/components/conversation/push-to-talk/push-to-talk.class.js.map +1 -1
  280. package/dist/components/conversation/push-to-talk/push-to-talk.styles.d.ts.map +1 -1
  281. package/dist/components/conversation/push-to-talk/push-to-talk.styles.js +12 -3
  282. package/dist/components/conversation/push-to-talk/push-to-talk.styles.js.map +1 -1
  283. package/dist/components/conversation/suggestion-chips/suggestion-chips.class.d.ts +2 -0
  284. package/dist/components/conversation/suggestion-chips/suggestion-chips.class.d.ts.map +1 -1
  285. package/dist/components/conversation/suggestion-chips/suggestion-chips.class.js +2 -0
  286. package/dist/components/conversation/suggestion-chips/suggestion-chips.class.js.map +1 -1
  287. package/dist/components/conversation/suggestion-chips/suggestion-chips.styles.js +2 -2
  288. package/dist/components/conversation/thread-list/thread-list.class.d.ts +83 -8
  289. package/dist/components/conversation/thread-list/thread-list.class.d.ts.map +1 -1
  290. package/dist/components/conversation/thread-list/thread-list.class.js +173 -25
  291. package/dist/components/conversation/thread-list/thread-list.class.js.map +1 -1
  292. package/dist/components/conversation/thread-list/thread-list.styles.d.ts.map +1 -1
  293. package/dist/components/conversation/thread-list/thread-list.styles.js +33 -1
  294. package/dist/components/conversation/thread-list/thread-list.styles.js.map +1 -1
  295. package/dist/components/conversation/transcript-feed/transcript-feed.class.d.ts.map +1 -1
  296. package/dist/components/conversation/transcript-feed/transcript-feed.class.js +18 -1
  297. package/dist/components/conversation/transcript-feed/transcript-feed.class.js.map +1 -1
  298. package/dist/components/conversation/transcript-feed/transcript-feed.styles.d.ts.map +1 -1
  299. package/dist/components/conversation/transcript-feed/transcript-feed.styles.js +4 -0
  300. package/dist/components/conversation/transcript-feed/transcript-feed.styles.js.map +1 -1
  301. package/dist/components/conversation/typing-indicator/typing-indicator.class.d.ts +14 -10
  302. package/dist/components/conversation/typing-indicator/typing-indicator.class.d.ts.map +1 -1
  303. package/dist/components/conversation/typing-indicator/typing-indicator.class.js +26 -11
  304. package/dist/components/conversation/typing-indicator/typing-indicator.class.js.map +1 -1
  305. package/dist/components/conversation/usage-badge/usage-badge.class.d.ts +4 -0
  306. package/dist/components/conversation/usage-badge/usage-badge.class.d.ts.map +1 -1
  307. package/dist/components/conversation/usage-badge/usage-badge.class.js +15 -1
  308. package/dist/components/conversation/usage-badge/usage-badge.class.js.map +1 -1
  309. package/dist/components/conversation/usage-badge/usage-badge.styles.js +1 -1
  310. package/dist/components/conversation/voice-picker/voice-picker.class.d.ts +12 -0
  311. package/dist/components/conversation/voice-picker/voice-picker.class.d.ts.map +1 -1
  312. package/dist/components/conversation/voice-picker/voice-picker.class.js +35 -1
  313. package/dist/components/conversation/voice-picker/voice-picker.class.js.map +1 -1
  314. package/dist/components/conversation/voice-picker/voice-picker.styles.d.ts.map +1 -1
  315. package/dist/components/conversation/voice-picker/voice-picker.styles.js +17 -1
  316. package/dist/components/conversation/voice-picker/voice-picker.styles.js.map +1 -1
  317. package/dist/components/data/calendar/calendar.class.d.ts +5 -2
  318. package/dist/components/data/calendar/calendar.class.d.ts.map +1 -1
  319. package/dist/components/data/calendar/calendar.class.js +3 -2
  320. package/dist/components/data/calendar/calendar.class.js.map +1 -1
  321. package/dist/components/data/calendar/calendar.styles.d.ts.map +1 -1
  322. package/dist/components/data/calendar/calendar.styles.js +39 -5
  323. package/dist/components/data/calendar/calendar.styles.js.map +1 -1
  324. package/dist/components/data/document-library/document-library.class.d.ts +6 -5
  325. package/dist/components/data/document-library/document-library.class.d.ts.map +1 -1
  326. package/dist/components/data/document-library/document-library.class.js +2 -3
  327. package/dist/components/data/document-library/document-library.class.js.map +1 -1
  328. package/dist/components/data/env-list/env-list.class.d.ts +5 -0
  329. package/dist/components/data/env-list/env-list.class.d.ts.map +1 -1
  330. package/dist/components/data/env-list/env-list.class.js +22 -2
  331. package/dist/components/data/env-list/env-list.class.js.map +1 -1
  332. package/dist/components/data/env-list/env-list.styles.d.ts.map +1 -1
  333. package/dist/components/data/env-list/env-list.styles.js +6 -2
  334. package/dist/components/data/env-list/env-list.styles.js.map +1 -1
  335. package/dist/components/data/flow-canvas/flow-canvas.class.d.ts +18 -1
  336. package/dist/components/data/flow-canvas/flow-canvas.class.d.ts.map +1 -1
  337. package/dist/components/data/flow-canvas/flow-canvas.class.js +29 -3
  338. package/dist/components/data/flow-canvas/flow-canvas.class.js.map +1 -1
  339. package/dist/components/data/flow-canvas/flow-canvas.styles.d.ts.map +1 -1
  340. package/dist/components/data/flow-canvas/flow-canvas.styles.js +15 -4
  341. package/dist/components/data/flow-canvas/flow-canvas.styles.js.map +1 -1
  342. package/dist/components/data/flow-controls/flow-controls.class.d.ts +16 -1
  343. package/dist/components/data/flow-controls/flow-controls.class.d.ts.map +1 -1
  344. package/dist/components/data/flow-controls/flow-controls.class.js +17 -1
  345. package/dist/components/data/flow-controls/flow-controls.class.js.map +1 -1
  346. package/dist/components/data/flow-controls/flow-controls.styles.d.ts.map +1 -1
  347. package/dist/components/data/flow-controls/flow-controls.styles.js +26 -2
  348. package/dist/components/data/flow-controls/flow-controls.styles.js.map +1 -1
  349. package/dist/components/data/flow-minimap/flow-minimap.styles.d.ts.map +1 -1
  350. package/dist/components/data/flow-minimap/flow-minimap.styles.js +4 -0
  351. package/dist/components/data/flow-minimap/flow-minimap.styles.js.map +1 -1
  352. package/dist/components/data/flow-node/flow-node.class.d.ts +20 -1
  353. package/dist/components/data/flow-node/flow-node.class.d.ts.map +1 -1
  354. package/dist/components/data/flow-node/flow-node.class.js +24 -2
  355. package/dist/components/data/flow-node/flow-node.class.js.map +1 -1
  356. package/dist/components/data/flow-node/flow-node.styles.d.ts.map +1 -1
  357. package/dist/components/data/flow-node/flow-node.styles.js +23 -5
  358. package/dist/components/data/flow-node/flow-node.styles.js.map +1 -1
  359. package/dist/components/data/flow-run-overlay/flow-run-overlay.class.d.ts +9 -1
  360. package/dist/components/data/flow-run-overlay/flow-run-overlay.class.d.ts.map +1 -1
  361. package/dist/components/data/flow-run-overlay/flow-run-overlay.class.js +9 -1
  362. package/dist/components/data/flow-run-overlay/flow-run-overlay.class.js.map +1 -1
  363. package/dist/components/data/flow-run-overlay/flow-run-overlay.styles.d.ts.map +1 -1
  364. package/dist/components/data/flow-run-overlay/flow-run-overlay.styles.js +11 -0
  365. package/dist/components/data/flow-run-overlay/flow-run-overlay.styles.js.map +1 -1
  366. package/dist/components/data/graph-query-builder/graph-query-builder.class.d.ts +15 -1
  367. package/dist/components/data/graph-query-builder/graph-query-builder.class.d.ts.map +1 -1
  368. package/dist/components/data/graph-query-builder/graph-query-builder.class.js +40 -3
  369. package/dist/components/data/graph-query-builder/graph-query-builder.class.js.map +1 -1
  370. package/dist/components/data/graph-query-builder/graph-query-builder.styles.d.ts.map +1 -1
  371. package/dist/components/data/graph-query-builder/graph-query-builder.styles.js +7 -1
  372. package/dist/components/data/graph-query-builder/graph-query-builder.styles.js.map +1 -1
  373. package/dist/components/data/heatmap/heatmap.class.d.ts +113 -9
  374. package/dist/components/data/heatmap/heatmap.class.d.ts.map +1 -1
  375. package/dist/components/data/heatmap/heatmap.class.js +174 -19
  376. package/dist/components/data/heatmap/heatmap.class.js.map +1 -1
  377. package/dist/components/data/heatmap/heatmap.styles.d.ts.map +1 -1
  378. package/dist/components/data/heatmap/heatmap.styles.js +20 -0
  379. package/dist/components/data/heatmap/heatmap.styles.js.map +1 -1
  380. package/dist/components/data/pagination/pagination.class.d.ts +3 -0
  381. package/dist/components/data/pagination/pagination.class.d.ts.map +1 -1
  382. package/dist/components/data/pagination/pagination.class.js +3 -0
  383. package/dist/components/data/pagination/pagination.class.js.map +1 -1
  384. package/dist/components/data/pagination/pagination.styles.d.ts.map +1 -1
  385. package/dist/components/data/pagination/pagination.styles.js +22 -4
  386. package/dist/components/data/pagination/pagination.styles.js.map +1 -1
  387. package/dist/components/data/sequence-strip/sequence-strip.class.d.ts +13 -3
  388. package/dist/components/data/sequence-strip/sequence-strip.class.d.ts.map +1 -1
  389. package/dist/components/data/sequence-strip/sequence-strip.class.js +30 -7
  390. package/dist/components/data/sequence-strip/sequence-strip.class.js.map +1 -1
  391. package/dist/components/data/sequence-strip/sequence-strip.styles.d.ts.map +1 -1
  392. package/dist/components/data/sequence-strip/sequence-strip.styles.js +11 -1
  393. package/dist/components/data/sequence-strip/sequence-strip.styles.js.map +1 -1
  394. package/dist/components/data/stat/stat.class.d.ts +33 -4
  395. package/dist/components/data/stat/stat.class.d.ts.map +1 -1
  396. package/dist/components/data/stat/stat.class.js +35 -6
  397. package/dist/components/data/stat/stat.class.js.map +1 -1
  398. package/dist/components/data/stat/stat.styles.d.ts.map +1 -1
  399. package/dist/components/data/stat/stat.styles.js +69 -5
  400. package/dist/components/data/stat/stat.styles.js.map +1 -1
  401. package/dist/components/data/table/table.class.d.ts +253 -14
  402. package/dist/components/data/table/table.class.d.ts.map +1 -1
  403. package/dist/components/data/table/table.class.js +470 -84
  404. package/dist/components/data/table/table.class.js.map +1 -1
  405. package/dist/components/data/table/table.styles.d.ts.map +1 -1
  406. package/dist/components/data/table/table.styles.js +46 -4
  407. package/dist/components/data/table/table.styles.js.map +1 -1
  408. package/dist/components/data/timeline/timeline-item.class.d.ts +2 -2
  409. package/dist/components/data/timeline/timeline-item.class.d.ts.map +1 -1
  410. package/dist/components/data/timeline/timeline-item.class.js +2 -1
  411. package/dist/components/data/timeline/timeline-item.class.js.map +1 -1
  412. package/dist/components/data/timeline/timeline.class.d.ts +4 -4
  413. package/dist/components/data/timeline/timeline.class.d.ts.map +1 -1
  414. package/dist/components/data/timeline/timeline.class.js +4 -3
  415. package/dist/components/data/timeline/timeline.class.js.map +1 -1
  416. package/dist/components/data/timeline/timeline.styles.d.ts.map +1 -1
  417. package/dist/components/data/timeline/timeline.styles.js +21 -2
  418. package/dist/components/data/timeline/timeline.styles.js.map +1 -1
  419. package/dist/components/data/tree/tree-node.class.d.ts +2 -2
  420. package/dist/components/data/tree/tree-node.class.d.ts.map +1 -1
  421. package/dist/components/data/tree/tree-node.class.js +2 -1
  422. package/dist/components/data/tree/tree-node.class.js.map +1 -1
  423. package/dist/components/data/tree/tree.class.d.ts +56 -3
  424. package/dist/components/data/tree/tree.class.d.ts.map +1 -1
  425. package/dist/components/data/tree/tree.class.js +138 -13
  426. package/dist/components/data/tree/tree.class.js.map +1 -1
  427. package/dist/components/data/tree/tree.styles.d.ts.map +1 -1
  428. package/dist/components/data/tree/tree.styles.js +6 -1
  429. package/dist/components/data/tree/tree.styles.js.map +1 -1
  430. package/dist/components/data/word-cloud/word-cloud-layout.d.ts +7 -2
  431. package/dist/components/data/word-cloud/word-cloud-layout.d.ts.map +1 -1
  432. package/dist/components/data/word-cloud/word-cloud-layout.js.map +1 -1
  433. package/dist/components/data/word-cloud/word-cloud.class.d.ts +3 -3
  434. package/dist/components/data/word-cloud/word-cloud.class.d.ts.map +1 -1
  435. package/dist/components/data/word-cloud/word-cloud.class.js +1 -0
  436. package/dist/components/data/word-cloud/word-cloud.class.js.map +1 -1
  437. package/dist/components/forms/button/button.class.d.ts +35 -4
  438. package/dist/components/forms/button/button.class.d.ts.map +1 -1
  439. package/dist/components/forms/button/button.class.js +51 -5
  440. package/dist/components/forms/button/button.class.js.map +1 -1
  441. package/dist/components/forms/button/button.styles.d.ts.map +1 -1
  442. package/dist/components/forms/button/button.styles.js +80 -44
  443. package/dist/components/forms/button/button.styles.js.map +1 -1
  444. package/dist/components/forms/checkbox/checkbox.class.d.ts +19 -2
  445. package/dist/components/forms/checkbox/checkbox.class.d.ts.map +1 -1
  446. package/dist/components/forms/checkbox/checkbox.class.js +57 -2
  447. package/dist/components/forms/checkbox/checkbox.class.js.map +1 -1
  448. package/dist/components/forms/checkbox/checkbox.styles.d.ts.map +1 -1
  449. package/dist/components/forms/checkbox/checkbox.styles.js +24 -3
  450. package/dist/components/forms/checkbox/checkbox.styles.js.map +1 -1
  451. package/dist/components/forms/checkbox-group/checkbox-group.class.d.ts +26 -1
  452. package/dist/components/forms/checkbox-group/checkbox-group.class.d.ts.map +1 -1
  453. package/dist/components/forms/checkbox-group/checkbox-group.class.js +115 -6
  454. package/dist/components/forms/checkbox-group/checkbox-group.class.js.map +1 -1
  455. package/dist/components/forms/checkbox-group/checkbox-group.styles.d.ts.map +1 -1
  456. package/dist/components/forms/checkbox-group/checkbox-group.styles.js +9 -1
  457. package/dist/components/forms/checkbox-group/checkbox-group.styles.js.map +1 -1
  458. package/dist/components/forms/code-editor/code-editor.class.d.ts +1 -1
  459. package/dist/components/forms/code-editor/code-editor.class.d.ts.map +1 -1
  460. package/dist/components/forms/code-editor/code-editor.class.js +18 -2
  461. package/dist/components/forms/code-editor/code-editor.class.js.map +1 -1
  462. package/dist/components/forms/code-editor/code-editor.styles.d.ts.map +1 -1
  463. package/dist/components/forms/code-editor/code-editor.styles.js +14 -1
  464. package/dist/components/forms/code-editor/code-editor.styles.js.map +1 -1
  465. package/dist/components/forms/color-picker/color-picker.class.d.ts +4 -0
  466. package/dist/components/forms/color-picker/color-picker.class.d.ts.map +1 -1
  467. package/dist/components/forms/color-picker/color-picker.class.js +6 -0
  468. package/dist/components/forms/color-picker/color-picker.class.js.map +1 -1
  469. package/dist/components/forms/color-picker/color-picker.styles.d.ts.map +1 -1
  470. package/dist/components/forms/color-picker/color-picker.styles.js +22 -2
  471. package/dist/components/forms/color-picker/color-picker.styles.js.map +1 -1
  472. package/dist/components/forms/combobox/combobox.class.d.ts +48 -8
  473. package/dist/components/forms/combobox/combobox.class.d.ts.map +1 -1
  474. package/dist/components/forms/combobox/combobox.class.js +137 -21
  475. package/dist/components/forms/combobox/combobox.class.js.map +1 -1
  476. package/dist/components/forms/combobox/combobox.styles.d.ts.map +1 -1
  477. package/dist/components/forms/combobox/combobox.styles.js +49 -3
  478. package/dist/components/forms/combobox/combobox.styles.js.map +1 -1
  479. package/dist/components/forms/date-picker/date-input.class.d.ts +17 -0
  480. package/dist/components/forms/date-picker/date-input.class.d.ts.map +1 -1
  481. package/dist/components/forms/date-picker/date-input.class.js +35 -0
  482. package/dist/components/forms/date-picker/date-input.class.js.map +1 -1
  483. package/dist/components/forms/date-picker/date-input.styles.d.ts.map +1 -1
  484. package/dist/components/forms/date-picker/date-input.styles.js +46 -4
  485. package/dist/components/forms/date-picker/date-input.styles.js.map +1 -1
  486. package/dist/components/forms/date-picker/date-picker.class.d.ts +5 -1
  487. package/dist/components/forms/date-picker/date-picker.class.d.ts.map +1 -1
  488. package/dist/components/forms/date-picker/date-picker.class.js +11 -1
  489. package/dist/components/forms/date-picker/date-picker.class.js.map +1 -1
  490. package/dist/components/forms/date-picker/date-picker.styles.d.ts.map +1 -1
  491. package/dist/components/forms/date-picker/date-picker.styles.js +19 -0
  492. package/dist/components/forms/date-picker/date-picker.styles.js.map +1 -1
  493. package/dist/components/forms/emoji-picker/emoji-data-loader.js +8 -1
  494. package/dist/components/forms/emoji-picker/emoji-data-loader.js.map +1 -1
  495. package/dist/components/forms/emoji-picker/emoji-picker.class.d.ts +55 -3
  496. package/dist/components/forms/emoji-picker/emoji-picker.class.d.ts.map +1 -1
  497. package/dist/components/forms/emoji-picker/emoji-picker.class.js +153 -29
  498. package/dist/components/forms/emoji-picker/emoji-picker.class.js.map +1 -1
  499. package/dist/components/forms/emoji-picker/emoji-picker.styles.d.ts.map +1 -1
  500. package/dist/components/forms/emoji-picker/emoji-picker.styles.js +84 -8
  501. package/dist/components/forms/emoji-picker/emoji-picker.styles.js.map +1 -1
  502. package/dist/components/forms/icon-button/icon-button.class.d.ts +54 -7
  503. package/dist/components/forms/icon-button/icon-button.class.d.ts.map +1 -1
  504. package/dist/components/forms/icon-button/icon-button.class.js +140 -14
  505. package/dist/components/forms/icon-button/icon-button.class.js.map +1 -1
  506. package/dist/components/forms/icon-button/icon-button.styles.d.ts.map +1 -1
  507. package/dist/components/forms/icon-button/icon-button.styles.js +8 -1
  508. package/dist/components/forms/icon-button/icon-button.styles.js.map +1 -1
  509. package/dist/components/forms/input/input.class.d.ts +25 -0
  510. package/dist/components/forms/input/input.class.d.ts.map +1 -1
  511. package/dist/components/forms/input/input.class.js +45 -0
  512. package/dist/components/forms/input/input.class.js.map +1 -1
  513. package/dist/components/forms/input/input.styles.d.ts.map +1 -1
  514. package/dist/components/forms/input/input.styles.js +27 -2
  515. package/dist/components/forms/input/input.styles.js.map +1 -1
  516. package/dist/components/forms/locale-picker/locale-picker.class.d.ts +221 -0
  517. package/dist/components/forms/locale-picker/locale-picker.class.d.ts.map +1 -0
  518. package/dist/components/forms/locale-picker/locale-picker.class.js +630 -0
  519. package/dist/components/forms/locale-picker/locale-picker.class.js.map +1 -0
  520. package/dist/components/forms/locale-picker/locale-picker.d.ts +3 -0
  521. package/dist/components/forms/locale-picker/locale-picker.d.ts.map +1 -0
  522. package/dist/components/forms/locale-picker/locale-picker.js +6 -0
  523. package/dist/components/forms/locale-picker/locale-picker.js.map +1 -0
  524. package/dist/components/forms/locale-picker/locale-picker.styles.d.ts +2 -0
  525. package/dist/components/forms/locale-picker/locale-picker.styles.d.ts.map +1 -0
  526. package/dist/components/forms/locale-picker/locale-picker.styles.js +213 -0
  527. package/dist/components/forms/locale-picker/locale-picker.styles.js.map +1 -0
  528. package/dist/components/forms/phone-input/phone-input.class.d.ts +45 -1
  529. package/dist/components/forms/phone-input/phone-input.class.d.ts.map +1 -1
  530. package/dist/components/forms/phone-input/phone-input.class.js +74 -13
  531. package/dist/components/forms/phone-input/phone-input.class.js.map +1 -1
  532. package/dist/components/forms/phone-input/phone-input.styles.d.ts.map +1 -1
  533. package/dist/components/forms/phone-input/phone-input.styles.js +130 -11
  534. package/dist/components/forms/phone-input/phone-input.styles.js.map +1 -1
  535. package/dist/components/forms/radio/radio.class.d.ts +24 -0
  536. package/dist/components/forms/radio/radio.class.d.ts.map +1 -1
  537. package/dist/components/forms/radio/radio.class.js +50 -1
  538. package/dist/components/forms/radio/radio.class.js.map +1 -1
  539. package/dist/components/forms/radio/radio.styles.d.ts.map +1 -1
  540. package/dist/components/forms/radio/radio.styles.js +36 -5
  541. package/dist/components/forms/radio/radio.styles.js.map +1 -1
  542. package/dist/components/forms/rubric-form/rubric-form.class.d.ts +9 -7
  543. package/dist/components/forms/rubric-form/rubric-form.class.d.ts.map +1 -1
  544. package/dist/components/forms/rubric-form/rubric-form.class.js +34 -8
  545. package/dist/components/forms/rubric-form/rubric-form.class.js.map +1 -1
  546. package/dist/components/forms/rubric-form/rubric-form.styles.d.ts.map +1 -1
  547. package/dist/components/forms/rubric-form/rubric-form.styles.js +7 -1
  548. package/dist/components/forms/rubric-form/rubric-form.styles.js.map +1 -1
  549. package/dist/components/forms/select/select.class.d.ts +28 -9
  550. package/dist/components/forms/select/select.class.d.ts.map +1 -1
  551. package/dist/components/forms/select/select.class.js +87 -9
  552. package/dist/components/forms/select/select.class.js.map +1 -1
  553. package/dist/components/forms/select/select.styles.d.ts.map +1 -1
  554. package/dist/components/forms/select/select.styles.js +45 -19
  555. package/dist/components/forms/select/select.styles.js.map +1 -1
  556. package/dist/components/forms/slider/slider.class.d.ts +5 -6
  557. package/dist/components/forms/slider/slider.class.d.ts.map +1 -1
  558. package/dist/components/forms/slider/slider.class.js +20 -7
  559. package/dist/components/forms/slider/slider.class.js.map +1 -1
  560. package/dist/components/forms/slider/slider.styles.d.ts.map +1 -1
  561. package/dist/components/forms/slider/slider.styles.js +8 -0
  562. package/dist/components/forms/slider/slider.styles.js.map +1 -1
  563. package/dist/components/forms/swatch-picker/swatch-picker.class.d.ts +12 -3
  564. package/dist/components/forms/swatch-picker/swatch-picker.class.d.ts.map +1 -1
  565. package/dist/components/forms/swatch-picker/swatch-picker.class.js +14 -3
  566. package/dist/components/forms/swatch-picker/swatch-picker.class.js.map +1 -1
  567. package/dist/components/forms/swatch-picker/swatch-picker.styles.d.ts.map +1 -1
  568. package/dist/components/forms/swatch-picker/swatch-picker.styles.js +32 -9
  569. package/dist/components/forms/swatch-picker/swatch-picker.styles.js.map +1 -1
  570. package/dist/components/forms/switch/switch.class.d.ts +7 -2
  571. package/dist/components/forms/switch/switch.class.d.ts.map +1 -1
  572. package/dist/components/forms/switch/switch.class.js +48 -2
  573. package/dist/components/forms/switch/switch.class.js.map +1 -1
  574. package/dist/components/forms/switch/switch.styles.d.ts.map +1 -1
  575. package/dist/components/forms/switch/switch.styles.js +8 -0
  576. package/dist/components/forms/switch/switch.styles.js.map +1 -1
  577. package/dist/components/forms/textarea/textarea.class.d.ts +1 -1
  578. package/dist/components/forms/textarea/textarea.class.d.ts.map +1 -1
  579. package/dist/components/forms/textarea/textarea.class.js +5 -1
  580. package/dist/components/forms/textarea/textarea.class.js.map +1 -1
  581. package/dist/components/forms/textarea/textarea.styles.d.ts.map +1 -1
  582. package/dist/components/forms/textarea/textarea.styles.js +8 -0
  583. package/dist/components/forms/textarea/textarea.styles.js.map +1 -1
  584. package/dist/components/forms/time-range/time-range.class.d.ts +16 -0
  585. package/dist/components/forms/time-range/time-range.class.d.ts.map +1 -1
  586. package/dist/components/forms/time-range/time-range.class.js +57 -1
  587. package/dist/components/forms/time-range/time-range.class.js.map +1 -1
  588. package/dist/components/forms/time-range/time-range.styles.d.ts.map +1 -1
  589. package/dist/components/forms/time-range/time-range.styles.js +74 -20
  590. package/dist/components/forms/time-range/time-range.styles.js.map +1 -1
  591. package/dist/components/forms/token-input/token-input.class.d.ts +72 -3
  592. package/dist/components/forms/token-input/token-input.class.d.ts.map +1 -1
  593. package/dist/components/forms/token-input/token-input.class.js +266 -10
  594. package/dist/components/forms/token-input/token-input.class.js.map +1 -1
  595. package/dist/components/forms/token-input/token-input.styles.d.ts.map +1 -1
  596. package/dist/components/forms/token-input/token-input.styles.js +52 -3
  597. package/dist/components/forms/token-input/token-input.styles.js.map +1 -1
  598. package/dist/components/layout/app-rail/app-rail-item.class.d.ts +6 -0
  599. package/dist/components/layout/app-rail/app-rail-item.class.d.ts.map +1 -1
  600. package/dist/components/layout/app-rail/app-rail-item.class.js +6 -0
  601. package/dist/components/layout/app-rail/app-rail-item.class.js.map +1 -1
  602. package/dist/components/layout/app-rail/app-rail-item.styles.d.ts.map +1 -1
  603. package/dist/components/layout/app-rail/app-rail-item.styles.js +11 -2
  604. package/dist/components/layout/app-rail/app-rail-item.styles.js.map +1 -1
  605. package/dist/components/layout/app-rail/app-rail.class.d.ts +6 -2
  606. package/dist/components/layout/app-rail/app-rail.class.d.ts.map +1 -1
  607. package/dist/components/layout/app-rail/app-rail.class.js.map +1 -1
  608. package/dist/components/layout/breadcrumb/breadcrumb-item.class.d.ts +4 -0
  609. package/dist/components/layout/breadcrumb/breadcrumb-item.class.d.ts.map +1 -1
  610. package/dist/components/layout/breadcrumb/breadcrumb-item.class.js +4 -0
  611. package/dist/components/layout/breadcrumb/breadcrumb-item.class.js.map +1 -1
  612. package/dist/components/layout/breadcrumb/breadcrumb-item.styles.d.ts.map +1 -1
  613. package/dist/components/layout/breadcrumb/breadcrumb-item.styles.js +6 -1
  614. package/dist/components/layout/breadcrumb/breadcrumb-item.styles.js.map +1 -1
  615. package/dist/components/layout/card/card.class.d.ts +29 -5
  616. package/dist/components/layout/card/card.class.d.ts.map +1 -1
  617. package/dist/components/layout/card/card.class.js +90 -6
  618. package/dist/components/layout/card/card.class.js.map +1 -1
  619. package/dist/components/layout/card/card.styles.d.ts.map +1 -1
  620. package/dist/components/layout/card/card.styles.js +8 -0
  621. package/dist/components/layout/card/card.styles.js.map +1 -1
  622. package/dist/components/layout/carousel/carousel.class.d.ts +6 -0
  623. package/dist/components/layout/carousel/carousel.class.d.ts.map +1 -1
  624. package/dist/components/layout/carousel/carousel.class.js +22 -1
  625. package/dist/components/layout/carousel/carousel.class.js.map +1 -1
  626. package/dist/components/layout/carousel/carousel.styles.d.ts.map +1 -1
  627. package/dist/components/layout/carousel/carousel.styles.js +10 -0
  628. package/dist/components/layout/carousel/carousel.styles.js.map +1 -1
  629. package/dist/components/layout/command-palette/command-palette.class.d.ts +8 -0
  630. package/dist/components/layout/command-palette/command-palette.class.d.ts.map +1 -1
  631. package/dist/components/layout/command-palette/command-palette.class.js +6 -1
  632. package/dist/components/layout/command-palette/command-palette.class.js.map +1 -1
  633. package/dist/components/layout/command-palette/command-palette.styles.d.ts.map +1 -1
  634. package/dist/components/layout/command-palette/command-palette.styles.js +11 -2
  635. package/dist/components/layout/command-palette/command-palette.styles.js.map +1 -1
  636. package/dist/components/layout/control-group/control-group.class.d.ts +16 -0
  637. package/dist/components/layout/control-group/control-group.class.d.ts.map +1 -1
  638. package/dist/components/layout/control-group/control-group.class.js +19 -0
  639. package/dist/components/layout/control-group/control-group.class.js.map +1 -1
  640. package/dist/components/layout/control-group/control-group.styles.d.ts.map +1 -1
  641. package/dist/components/layout/control-group/control-group.styles.js +8 -3
  642. package/dist/components/layout/control-group/control-group.styles.js.map +1 -1
  643. package/dist/components/layout/dashboard-grid/dashboard-grid.class.d.ts +3 -0
  644. package/dist/components/layout/dashboard-grid/dashboard-grid.class.d.ts.map +1 -1
  645. package/dist/components/layout/dashboard-grid/dashboard-grid.class.js +4 -0
  646. package/dist/components/layout/dashboard-grid/dashboard-grid.class.js.map +1 -1
  647. package/dist/components/layout/dashboard-grid/dashboard-grid.styles.d.ts.map +1 -1
  648. package/dist/components/layout/dashboard-grid/dashboard-grid.styles.js +16 -0
  649. package/dist/components/layout/dashboard-grid/dashboard-grid.styles.js.map +1 -1
  650. package/dist/components/layout/details/details.class.js +1 -1
  651. package/dist/components/layout/details/details.class.js.map +1 -1
  652. package/dist/components/layout/details/details.styles.d.ts.map +1 -1
  653. package/dist/components/layout/details/details.styles.js +2 -0
  654. package/dist/components/layout/details/details.styles.js.map +1 -1
  655. package/dist/components/layout/dock-panel/dock-panel.class.d.ts.map +1 -1
  656. package/dist/components/layout/dock-panel/dock-panel.class.js +16 -1
  657. package/dist/components/layout/dock-panel/dock-panel.class.js.map +1 -1
  658. package/dist/components/layout/drilldown-panel/drilldown-panel.class.d.ts.map +1 -1
  659. package/dist/components/layout/drilldown-panel/drilldown-panel.class.js +15 -1
  660. package/dist/components/layout/drilldown-panel/drilldown-panel.class.js.map +1 -1
  661. package/dist/components/layout/filter-bar/filter-bar.class.d.ts +54 -9
  662. package/dist/components/layout/filter-bar/filter-bar.class.d.ts.map +1 -1
  663. package/dist/components/layout/filter-bar/filter-bar.class.js +149 -5
  664. package/dist/components/layout/filter-bar/filter-bar.class.js.map +1 -1
  665. package/dist/components/layout/filter-bar/filter-bar.d.ts +1 -0
  666. package/dist/components/layout/filter-bar/filter-bar.d.ts.map +1 -1
  667. package/dist/components/layout/filter-bar/filter-bar.js +1 -0
  668. package/dist/components/layout/filter-bar/filter-bar.js.map +1 -1
  669. package/dist/components/layout/filter-bar/filter-bar.styles.d.ts.map +1 -1
  670. package/dist/components/layout/filter-bar/filter-bar.styles.js +12 -3
  671. package/dist/components/layout/filter-bar/filter-bar.styles.js.map +1 -1
  672. package/dist/components/layout/menu/menu.class.d.ts +119 -24
  673. package/dist/components/layout/menu/menu.class.d.ts.map +1 -1
  674. package/dist/components/layout/menu/menu.class.js +202 -35
  675. package/dist/components/layout/menu/menu.class.js.map +1 -1
  676. package/dist/components/layout/menu/menu.styles.d.ts.map +1 -1
  677. package/dist/components/layout/menu/menu.styles.js +38 -1
  678. package/dist/components/layout/menu/menu.styles.js.map +1 -1
  679. package/dist/components/layout/reorder-list/reorder-item.class.d.ts +59 -0
  680. package/dist/components/layout/reorder-list/reorder-item.class.d.ts.map +1 -0
  681. package/dist/components/layout/reorder-list/reorder-item.class.js +110 -0
  682. package/dist/components/layout/reorder-list/reorder-item.class.js.map +1 -0
  683. package/dist/components/layout/reorder-list/reorder-item.d.ts +2 -0
  684. package/dist/components/layout/reorder-list/reorder-item.d.ts.map +1 -0
  685. package/dist/components/layout/reorder-list/reorder-item.js +5 -0
  686. package/dist/components/layout/reorder-list/reorder-item.js.map +1 -0
  687. package/dist/components/{data/data-grid/data-grid.styles.d.ts → layout/reorder-list/reorder-item.styles.d.ts} +1 -1
  688. package/dist/components/layout/reorder-list/reorder-item.styles.d.ts.map +1 -0
  689. package/dist/components/layout/reorder-list/reorder-item.styles.js +62 -0
  690. package/dist/components/layout/reorder-list/reorder-item.styles.js.map +1 -0
  691. package/dist/components/layout/reorder-list/reorder-list.class.d.ts +77 -0
  692. package/dist/components/layout/reorder-list/reorder-list.class.d.ts.map +1 -0
  693. package/dist/components/layout/reorder-list/reorder-list.class.js +197 -0
  694. package/dist/components/layout/reorder-list/reorder-list.class.js.map +1 -0
  695. package/dist/components/layout/reorder-list/reorder-list.d.ts +3 -0
  696. package/dist/components/layout/reorder-list/reorder-list.d.ts.map +1 -0
  697. package/dist/components/layout/reorder-list/reorder-list.js +6 -0
  698. package/dist/components/layout/reorder-list/reorder-list.js.map +1 -0
  699. package/dist/components/layout/reorder-list/reorder-list.styles.d.ts +2 -0
  700. package/dist/components/layout/reorder-list/reorder-list.styles.d.ts.map +1 -0
  701. package/dist/components/layout/reorder-list/reorder-list.styles.js +12 -0
  702. package/dist/components/layout/reorder-list/reorder-list.styles.js.map +1 -0
  703. package/dist/components/layout/responsive-panel/responsive-panel.class.d.ts +2 -0
  704. package/dist/components/layout/responsive-panel/responsive-panel.class.d.ts.map +1 -1
  705. package/dist/components/layout/responsive-panel/responsive-panel.class.js +4 -0
  706. package/dist/components/layout/responsive-panel/responsive-panel.class.js.map +1 -1
  707. package/dist/components/layout/responsive-panel/responsive-panel.styles.d.ts.map +1 -1
  708. package/dist/components/layout/responsive-panel/responsive-panel.styles.js +12 -2
  709. package/dist/components/layout/responsive-panel/responsive-panel.styles.js.map +1 -1
  710. package/dist/components/layout/scroller/scroller.styles.d.ts.map +1 -1
  711. package/dist/components/layout/scroller/scroller.styles.js +4 -0
  712. package/dist/components/layout/scroller/scroller.styles.js.map +1 -1
  713. package/dist/components/layout/segmented/segmented.class.d.ts +20 -2
  714. package/dist/components/layout/segmented/segmented.class.d.ts.map +1 -1
  715. package/dist/components/layout/segmented/segmented.class.js +20 -2
  716. package/dist/components/layout/segmented/segmented.class.js.map +1 -1
  717. package/dist/components/layout/segmented/segmented.styles.d.ts.map +1 -1
  718. package/dist/components/layout/segmented/segmented.styles.js +27 -8
  719. package/dist/components/layout/segmented/segmented.styles.js.map +1 -1
  720. package/dist/components/layout/split/split.class.d.ts +79 -27
  721. package/dist/components/layout/split/split.class.d.ts.map +1 -1
  722. package/dist/components/layout/split/split.class.js +119 -36
  723. package/dist/components/layout/split/split.class.js.map +1 -1
  724. package/dist/components/layout/stepper/stepper.class.d.ts +30 -3
  725. package/dist/components/layout/stepper/stepper.class.d.ts.map +1 -1
  726. package/dist/components/layout/stepper/stepper.class.js +44 -8
  727. package/dist/components/layout/stepper/stepper.class.js.map +1 -1
  728. package/dist/components/layout/stepper/stepper.styles.d.ts.map +1 -1
  729. package/dist/components/layout/stepper/stepper.styles.js +71 -6
  730. package/dist/components/layout/stepper/stepper.styles.js.map +1 -1
  731. package/dist/components/layout/tabs/tabs.class.d.ts +7 -0
  732. package/dist/components/layout/tabs/tabs.class.d.ts.map +1 -1
  733. package/dist/components/layout/tabs/tabs.class.js +7 -0
  734. package/dist/components/layout/tabs/tabs.class.js.map +1 -1
  735. package/dist/components/layout/tabs/tabs.styles.d.ts.map +1 -1
  736. package/dist/components/layout/tabs/tabs.styles.js +12 -4
  737. package/dist/components/layout/tabs/tabs.styles.js.map +1 -1
  738. package/dist/components/layout/virtual-list/virtual-list.class.d.ts +151 -3
  739. package/dist/components/layout/virtual-list/virtual-list.class.d.ts.map +1 -1
  740. package/dist/components/layout/virtual-list/virtual-list.class.js +262 -16
  741. package/dist/components/layout/virtual-list/virtual-list.class.js.map +1 -1
  742. package/dist/components/layout/virtual-list/virtual-list.styles.d.ts.map +1 -1
  743. package/dist/components/layout/virtual-list/virtual-list.styles.js +58 -0
  744. package/dist/components/layout/virtual-list/virtual-list.styles.js.map +1 -1
  745. package/dist/components/layout/widget/widget.class.d.ts +6 -0
  746. package/dist/components/layout/widget/widget.class.d.ts.map +1 -1
  747. package/dist/components/layout/widget/widget.class.js +6 -0
  748. package/dist/components/layout/widget/widget.class.js.map +1 -1
  749. package/dist/components/layout/widget/widget.styles.d.ts.map +1 -1
  750. package/dist/components/layout/widget/widget.styles.js +13 -2
  751. package/dist/components/layout/widget/widget.styles.js.map +1 -1
  752. package/dist/components/media/animated-image/animated-image.class.d.ts.map +1 -1
  753. package/dist/components/media/animated-image/animated-image.class.js +20 -1
  754. package/dist/components/media/animated-image/animated-image.class.js.map +1 -1
  755. package/dist/components/media/animated-image/animated-image.styles.d.ts.map +1 -1
  756. package/dist/components/media/animated-image/animated-image.styles.js +6 -1
  757. package/dist/components/media/animated-image/animated-image.styles.js.map +1 -1
  758. package/dist/components/media/animation/animation.class.d.ts.map +1 -1
  759. package/dist/components/media/animation/animation.class.js +20 -1
  760. package/dist/components/media/animation/animation.class.js.map +1 -1
  761. package/dist/components/media/attachment-chip/attachment-chip.class.d.ts +3 -2
  762. package/dist/components/media/attachment-chip/attachment-chip.class.d.ts.map +1 -1
  763. package/dist/components/media/attachment-chip/attachment-chip.class.js +20 -4
  764. package/dist/components/media/attachment-chip/attachment-chip.class.js.map +1 -1
  765. package/dist/components/media/attachment-chip/attachment-chip.styles.d.ts.map +1 -1
  766. package/dist/components/media/attachment-chip/attachment-chip.styles.js +9 -0
  767. package/dist/components/media/attachment-chip/attachment-chip.styles.js.map +1 -1
  768. package/dist/components/media/attachment-trigger/attachment-trigger.class.d.ts.map +1 -1
  769. package/dist/components/media/attachment-trigger/attachment-trigger.class.js +15 -1
  770. package/dist/components/media/attachment-trigger/attachment-trigger.class.js.map +1 -1
  771. package/dist/components/media/av-player/av-player.class.d.ts +24 -0
  772. package/dist/components/media/av-player/av-player.class.d.ts.map +1 -1
  773. package/dist/components/media/av-player/av-player.class.js +56 -18
  774. package/dist/components/media/av-player/av-player.class.js.map +1 -1
  775. package/dist/components/media/av-player/av-player.styles.d.ts.map +1 -1
  776. package/dist/components/media/av-player/av-player.styles.js +70 -14
  777. package/dist/components/media/av-player/av-player.styles.js.map +1 -1
  778. package/dist/components/media/avatar/avatar.class.d.ts +4 -0
  779. package/dist/components/media/avatar/avatar.class.d.ts.map +1 -1
  780. package/dist/components/media/avatar/avatar.class.js +4 -0
  781. package/dist/components/media/avatar/avatar.class.js.map +1 -1
  782. package/dist/components/media/avatar/avatar.styles.d.ts.map +1 -1
  783. package/dist/components/media/avatar/avatar.styles.js +8 -1
  784. package/dist/components/media/avatar/avatar.styles.js.map +1 -1
  785. package/dist/components/media/avatar-group/avatar-group.class.d.ts +4 -0
  786. package/dist/components/media/avatar-group/avatar-group.class.d.ts.map +1 -1
  787. package/dist/components/media/avatar-group/avatar-group.class.js +5 -1
  788. package/dist/components/media/avatar-group/avatar-group.class.js.map +1 -1
  789. package/dist/components/media/avatar-group/avatar-group.styles.d.ts.map +1 -1
  790. package/dist/components/media/avatar-group/avatar-group.styles.js +7 -1
  791. package/dist/components/media/avatar-group/avatar-group.styles.js.map +1 -1
  792. package/dist/components/media/file-input/file-input.class.d.ts +20 -1
  793. package/dist/components/media/file-input/file-input.class.d.ts.map +1 -1
  794. package/dist/components/media/file-input/file-input.class.js +41 -2
  795. package/dist/components/media/file-input/file-input.class.js.map +1 -1
  796. package/dist/components/media/file-input/file-input.styles.d.ts.map +1 -1
  797. package/dist/components/media/file-input/file-input.styles.js +22 -4
  798. package/dist/components/media/file-input/file-input.styles.js.map +1 -1
  799. package/dist/components/media/flag/flag.class.d.ts.map +1 -1
  800. package/dist/components/media/flag/flag.class.js +3 -0
  801. package/dist/components/media/flag/flag.class.js.map +1 -1
  802. package/dist/components/media/flag/language-map.d.ts +15 -0
  803. package/dist/components/media/flag/language-map.d.ts.map +1 -1
  804. package/dist/components/media/flag/language-map.js +23 -0
  805. package/dist/components/media/flag/language-map.js.map +1 -1
  806. package/dist/components/media/image-comparer/image-comparer.styles.d.ts.map +1 -1
  807. package/dist/components/media/image-comparer/image-comparer.styles.js +11 -0
  808. package/dist/components/media/image-comparer/image-comparer.styles.js.map +1 -1
  809. package/dist/components/media/image-viewer/image-viewer.class.d.ts +17 -0
  810. package/dist/components/media/image-viewer/image-viewer.class.d.ts.map +1 -1
  811. package/dist/components/media/image-viewer/image-viewer.class.js +47 -6
  812. package/dist/components/media/image-viewer/image-viewer.class.js.map +1 -1
  813. package/dist/components/media/image-viewer/image-viewer.styles.d.ts.map +1 -1
  814. package/dist/components/media/image-viewer/image-viewer.styles.js +41 -3
  815. package/dist/components/media/image-viewer/image-viewer.styles.js.map +1 -1
  816. package/dist/components/media/lightbox/lightbox.class.d.ts +4 -9
  817. package/dist/components/media/lightbox/lightbox.class.d.ts.map +1 -1
  818. package/dist/components/media/lightbox/lightbox.class.js +32 -2
  819. package/dist/components/media/lightbox/lightbox.class.js.map +1 -1
  820. package/dist/components/media/lightbox/lightbox.styles.d.ts.map +1 -1
  821. package/dist/components/media/lightbox/lightbox.styles.js +7 -3
  822. package/dist/components/media/lightbox/lightbox.styles.js.map +1 -1
  823. package/dist/components/media/map/map.class.d.ts +8 -0
  824. package/dist/components/media/map/map.class.d.ts.map +1 -1
  825. package/dist/components/media/map/map.class.js +30 -6
  826. package/dist/components/media/map/map.class.js.map +1 -1
  827. package/dist/components/media/map/map.styles.d.ts.map +1 -1
  828. package/dist/components/media/map/map.styles.js +73 -0
  829. package/dist/components/media/map/map.styles.js.map +1 -1
  830. package/dist/components/media/media-card/media-card.class.d.ts +14 -0
  831. package/dist/components/media/media-card/media-card.class.d.ts.map +1 -1
  832. package/dist/components/media/media-card/media-card.class.js +14 -0
  833. package/dist/components/media/media-card/media-card.class.js.map +1 -1
  834. package/dist/components/media/media-card/media-card.styles.d.ts.map +1 -1
  835. package/dist/components/media/media-card/media-card.styles.js +10 -0
  836. package/dist/components/media/media-card/media-card.styles.js.map +1 -1
  837. package/dist/components/media/playback/playback.class.d.ts +6 -1
  838. package/dist/components/media/playback/playback.class.d.ts.map +1 -1
  839. package/dist/components/media/playback/playback.class.js +23 -1
  840. package/dist/components/media/playback/playback.class.js.map +1 -1
  841. package/dist/components/media/playback/playback.styles.d.ts.map +1 -1
  842. package/dist/components/media/playback/playback.styles.js +9 -0
  843. package/dist/components/media/playback/playback.styles.js.map +1 -1
  844. package/dist/components/media/qr-code/qr-code.class.d.ts +2 -0
  845. package/dist/components/media/qr-code/qr-code.class.d.ts.map +1 -1
  846. package/dist/components/media/qr-code/qr-code.class.js +27 -0
  847. package/dist/components/media/qr-code/qr-code.class.js.map +1 -1
  848. package/dist/components/overlays/badge/badge.class.d.ts +10 -0
  849. package/dist/components/overlays/badge/badge.class.d.ts.map +1 -1
  850. package/dist/components/overlays/badge/badge.class.js +12 -0
  851. package/dist/components/overlays/badge/badge.class.js.map +1 -1
  852. package/dist/components/overlays/badge/badge.styles.d.ts.map +1 -1
  853. package/dist/components/overlays/badge/badge.styles.js +15 -2
  854. package/dist/components/overlays/badge/badge.styles.js.map +1 -1
  855. package/dist/components/overlays/callout/callout.class.d.ts +8 -0
  856. package/dist/components/overlays/callout/callout.class.d.ts.map +1 -1
  857. package/dist/components/overlays/callout/callout.class.js +25 -1
  858. package/dist/components/overlays/callout/callout.class.js.map +1 -1
  859. package/dist/components/overlays/callout/callout.styles.d.ts.map +1 -1
  860. package/dist/components/overlays/callout/callout.styles.js +12 -1
  861. package/dist/components/overlays/callout/callout.styles.js.map +1 -1
  862. package/dist/components/overlays/chip/chip.class.d.ts +8 -1
  863. package/dist/components/overlays/chip/chip.class.d.ts.map +1 -1
  864. package/dist/components/overlays/chip/chip.class.js +7 -0
  865. package/dist/components/overlays/chip/chip.class.js.map +1 -1
  866. package/dist/components/overlays/chip/chip.styles.d.ts.map +1 -1
  867. package/dist/components/overlays/chip/chip.styles.js +31 -1
  868. package/dist/components/overlays/chip/chip.styles.js.map +1 -1
  869. package/dist/components/overlays/empty/empty.class.d.ts +2 -0
  870. package/dist/components/overlays/empty/empty.class.d.ts.map +1 -1
  871. package/dist/components/overlays/empty/empty.class.js +2 -0
  872. package/dist/components/overlays/empty/empty.class.js.map +1 -1
  873. package/dist/components/overlays/empty/empty.styles.d.ts.map +1 -1
  874. package/dist/components/overlays/empty/empty.styles.js +5 -0
  875. package/dist/components/overlays/empty/empty.styles.js.map +1 -1
  876. package/dist/components/overlays/overlay/popover.class.d.ts +15 -7
  877. package/dist/components/overlays/overlay/popover.class.d.ts.map +1 -1
  878. package/dist/components/overlays/overlay/popover.class.js +34 -18
  879. package/dist/components/overlays/overlay/popover.class.js.map +1 -1
  880. package/dist/components/overlays/overlay/tooltip.class.d.ts +12 -7
  881. package/dist/components/overlays/overlay/tooltip.class.d.ts.map +1 -1
  882. package/dist/components/overlays/overlay/tooltip.class.js +36 -21
  883. package/dist/components/overlays/overlay/tooltip.class.js.map +1 -1
  884. package/dist/components/overlays/rating/rating.styles.d.ts.map +1 -1
  885. package/dist/components/overlays/rating/rating.styles.js +5 -0
  886. package/dist/components/overlays/rating/rating.styles.js.map +1 -1
  887. package/dist/components/overlays/skeleton/skeleton.class.d.ts.map +1 -1
  888. package/dist/components/overlays/skeleton/skeleton.class.js +15 -1
  889. package/dist/components/overlays/skeleton/skeleton.class.js.map +1 -1
  890. package/dist/components/retrieval/chunk-inspector/chunk-inspector.class.d.ts +28 -2
  891. package/dist/components/retrieval/chunk-inspector/chunk-inspector.class.d.ts.map +1 -1
  892. package/dist/components/retrieval/chunk-inspector/chunk-inspector.class.js +77 -36
  893. package/dist/components/retrieval/chunk-inspector/chunk-inspector.class.js.map +1 -1
  894. package/dist/components/retrieval/chunk-inspector/chunk-inspector.styles.d.ts.map +1 -1
  895. package/dist/components/retrieval/chunk-inspector/chunk-inspector.styles.js +73 -14
  896. package/dist/components/retrieval/chunk-inspector/chunk-inspector.styles.js.map +1 -1
  897. package/dist/components/retrieval/citation-badge/citation-badge.class.d.ts.map +1 -1
  898. package/dist/components/retrieval/citation-badge/citation-badge.class.js +12 -0
  899. package/dist/components/retrieval/citation-badge/citation-badge.class.js.map +1 -1
  900. package/dist/components/retrieval/citation-badge/citation-badge.styles.js +1 -1
  901. package/dist/components/retrieval/community-card/community-card.class.d.ts +8 -0
  902. package/dist/components/retrieval/community-card/community-card.class.d.ts.map +1 -1
  903. package/dist/components/retrieval/community-card/community-card.class.js +8 -0
  904. package/dist/components/retrieval/community-card/community-card.class.js.map +1 -1
  905. package/dist/components/retrieval/community-card/community-card.styles.d.ts.map +1 -1
  906. package/dist/components/retrieval/community-card/community-card.styles.js +25 -0
  907. package/dist/components/retrieval/community-card/community-card.styles.js.map +1 -1
  908. package/dist/components/retrieval/entity-card/entity-card.class.d.ts +16 -0
  909. package/dist/components/retrieval/entity-card/entity-card.class.d.ts.map +1 -1
  910. package/dist/components/retrieval/entity-card/entity-card.class.js +35 -1
  911. package/dist/components/retrieval/entity-card/entity-card.class.js.map +1 -1
  912. package/dist/components/retrieval/entity-card/entity-card.styles.d.ts.map +1 -1
  913. package/dist/components/retrieval/entity-card/entity-card.styles.js +19 -0
  914. package/dist/components/retrieval/entity-card/entity-card.styles.js.map +1 -1
  915. package/dist/components/retrieval/entity-chip/entity-chip.class.d.ts.map +1 -1
  916. package/dist/components/retrieval/entity-chip/entity-chip.class.js +8 -0
  917. package/dist/components/retrieval/entity-chip/entity-chip.class.js.map +1 -1
  918. package/dist/components/retrieval/entity-chip/entity-chip.styles.js +1 -1
  919. package/dist/components/retrieval/entity-dossier/entity-dossier.class.d.ts.map +1 -1
  920. package/dist/components/retrieval/entity-dossier/entity-dossier.class.js +15 -1
  921. package/dist/components/retrieval/entity-dossier/entity-dossier.class.js.map +1 -1
  922. package/dist/components/retrieval/graph/graph.class.d.ts +31 -3
  923. package/dist/components/retrieval/graph/graph.class.d.ts.map +1 -1
  924. package/dist/components/retrieval/graph/graph.class.js +77 -3
  925. package/dist/components/retrieval/graph/graph.class.js.map +1 -1
  926. package/dist/components/retrieval/graph/graph.styles.d.ts.map +1 -1
  927. package/dist/components/retrieval/graph/graph.styles.js +22 -0
  928. package/dist/components/retrieval/graph/graph.styles.js.map +1 -1
  929. package/dist/components/retrieval/graph-legend/graph-legend.class.d.ts +2 -0
  930. package/dist/components/retrieval/graph-legend/graph-legend.class.d.ts.map +1 -1
  931. package/dist/components/retrieval/graph-legend/graph-legend.class.js +17 -1
  932. package/dist/components/retrieval/graph-legend/graph-legend.class.js.map +1 -1
  933. package/dist/components/retrieval/graph-legend/graph-legend.styles.js +1 -1
  934. package/dist/components/retrieval/ingestion-queue/ingestion-queue.class.d.ts.map +1 -1
  935. package/dist/components/retrieval/ingestion-queue/ingestion-queue.class.js +1 -0
  936. package/dist/components/retrieval/ingestion-queue/ingestion-queue.class.js.map +1 -1
  937. package/dist/components/retrieval/knowledge-base/knowledge-base.class.d.ts +2 -1
  938. package/dist/components/retrieval/knowledge-base/knowledge-base.class.d.ts.map +1 -1
  939. package/dist/components/retrieval/knowledge-base/knowledge-base.class.js +4 -2
  940. package/dist/components/retrieval/knowledge-base/knowledge-base.class.js.map +1 -1
  941. package/dist/components/retrieval/knowledge-graph-explorer/knowledge-graph-explorer.class.d.ts +6 -3
  942. package/dist/components/retrieval/knowledge-graph-explorer/knowledge-graph-explorer.class.d.ts.map +1 -1
  943. package/dist/components/retrieval/knowledge-graph-explorer/knowledge-graph-explorer.class.js +1 -0
  944. package/dist/components/retrieval/knowledge-graph-explorer/knowledge-graph-explorer.class.js.map +1 -1
  945. package/dist/components/retrieval/knowledge-graph-explorer/knowledge-graph-explorer.styles.js +1 -1
  946. package/dist/components/retrieval/memory-panel/memory-panel.class.d.ts +6 -0
  947. package/dist/components/retrieval/memory-panel/memory-panel.class.d.ts.map +1 -1
  948. package/dist/components/retrieval/memory-panel/memory-panel.class.js +6 -0
  949. package/dist/components/retrieval/memory-panel/memory-panel.class.js.map +1 -1
  950. package/dist/components/retrieval/memory-panel/memory-panel.styles.d.ts.map +1 -1
  951. package/dist/components/retrieval/memory-panel/memory-panel.styles.js +11 -3
  952. package/dist/components/retrieval/memory-panel/memory-panel.styles.js.map +1 -1
  953. package/dist/components/retrieval/mind-map/mind-map.class.d.ts +7 -0
  954. package/dist/components/retrieval/mind-map/mind-map.class.d.ts.map +1 -1
  955. package/dist/components/retrieval/mind-map/mind-map.class.js +15 -1
  956. package/dist/components/retrieval/mind-map/mind-map.class.js.map +1 -1
  957. package/dist/components/retrieval/mind-map/mind-map.styles.d.ts.map +1 -1
  958. package/dist/components/retrieval/mind-map/mind-map.styles.js +6 -0
  959. package/dist/components/retrieval/mind-map/mind-map.styles.js.map +1 -1
  960. package/dist/components/retrieval/neighbor-list/neighbor-list.class.d.ts +13 -3
  961. package/dist/components/retrieval/neighbor-list/neighbor-list.class.d.ts.map +1 -1
  962. package/dist/components/retrieval/neighbor-list/neighbor-list.class.js +30 -21
  963. package/dist/components/retrieval/neighbor-list/neighbor-list.class.js.map +1 -1
  964. package/dist/components/retrieval/neighbor-list/neighbor-list.styles.d.ts.map +1 -1
  965. package/dist/components/retrieval/neighbor-list/neighbor-list.styles.js +43 -10
  966. package/dist/components/retrieval/neighbor-list/neighbor-list.styles.js.map +1 -1
  967. package/dist/components/retrieval/node-palette/node-palette.class.d.ts +8 -0
  968. package/dist/components/retrieval/node-palette/node-palette.class.d.ts.map +1 -1
  969. package/dist/components/retrieval/node-palette/node-palette.class.js +21 -1
  970. package/dist/components/retrieval/node-palette/node-palette.class.js.map +1 -1
  971. package/dist/components/retrieval/node-palette/node-palette.styles.d.ts.map +1 -1
  972. package/dist/components/retrieval/node-palette/node-palette.styles.js +19 -3
  973. package/dist/components/retrieval/node-palette/node-palette.styles.js.map +1 -1
  974. package/dist/components/retrieval/path-strip/path-strip.styles.d.ts.map +1 -1
  975. package/dist/components/retrieval/path-strip/path-strip.styles.js +4 -0
  976. package/dist/components/retrieval/path-strip/path-strip.styles.js.map +1 -1
  977. package/dist/components/retrieval/provenance-panel/provenance-panel.styles.d.ts.map +1 -1
  978. package/dist/components/retrieval/provenance-panel/provenance-panel.styles.js +7 -0
  979. package/dist/components/retrieval/provenance-panel/provenance-panel.styles.js.map +1 -1
  980. package/dist/components/retrieval/retrieval-results/retrieval-results.class.d.ts +29 -2
  981. package/dist/components/retrieval/retrieval-results/retrieval-results.class.d.ts.map +1 -1
  982. package/dist/components/retrieval/retrieval-results/retrieval-results.class.js +51 -5
  983. package/dist/components/retrieval/retrieval-results/retrieval-results.class.js.map +1 -1
  984. package/dist/components/retrieval/retrieval-results/retrieval-results.styles.d.ts.map +1 -1
  985. package/dist/components/retrieval/retrieval-results/retrieval-results.styles.js +48 -13
  986. package/dist/components/retrieval/retrieval-results/retrieval-results.styles.js.map +1 -1
  987. package/dist/components/retrieval/retrieval-search/retrieval-search.styles.js +1 -1
  988. package/dist/components/retrieval/retrieval-trace/retrieval-trace.class.d.ts +2 -0
  989. package/dist/components/retrieval/retrieval-trace/retrieval-trace.class.d.ts.map +1 -1
  990. package/dist/components/retrieval/retrieval-trace/retrieval-trace.class.js +10 -1
  991. package/dist/components/retrieval/retrieval-trace/retrieval-trace.class.js.map +1 -1
  992. package/dist/components/retrieval/retrieval-trace/retrieval-trace.styles.js +1 -1
  993. package/dist/components/retrieval/source-card/source-card.class.d.ts +20 -2
  994. package/dist/components/retrieval/source-card/source-card.class.d.ts.map +1 -1
  995. package/dist/components/retrieval/source-card/source-card.class.js +24 -1
  996. package/dist/components/retrieval/source-card/source-card.class.js.map +1 -1
  997. package/dist/components/retrieval/source-card/source-card.styles.d.ts.map +1 -1
  998. package/dist/components/retrieval/source-card/source-card.styles.js +20 -0
  999. package/dist/components/retrieval/source-card/source-card.styles.js.map +1 -1
  1000. package/dist/components/retrieval/source-list/source-list.class.d.ts +2 -2
  1001. package/dist/components/retrieval/source-list/source-list.class.d.ts.map +1 -1
  1002. package/dist/components/retrieval/source-list/source-list.class.js +2 -1
  1003. package/dist/components/retrieval/source-list/source-list.class.js.map +1 -1
  1004. package/dist/components/retrieval/source-picker/source-picker.class.d.ts +8 -0
  1005. package/dist/components/retrieval/source-picker/source-picker.class.d.ts.map +1 -1
  1006. package/dist/components/retrieval/source-picker/source-picker.class.js +27 -2
  1007. package/dist/components/retrieval/source-picker/source-picker.class.js.map +1 -1
  1008. package/dist/components/retrieval/source-picker/source-picker.styles.d.ts.map +1 -1
  1009. package/dist/components/retrieval/source-picker/source-picker.styles.js +13 -6
  1010. package/dist/components/retrieval/source-picker/source-picker.styles.js.map +1 -1
  1011. package/dist/components/utility/diff-view/diff-view.class.d.ts +4 -1
  1012. package/dist/components/utility/diff-view/diff-view.class.d.ts.map +1 -1
  1013. package/dist/components/utility/diff-view/diff-view.class.js +1 -0
  1014. package/dist/components/utility/diff-view/diff-view.class.js.map +1 -1
  1015. package/dist/components/utility/diff-view/diff-view.styles.d.ts.map +1 -1
  1016. package/dist/components/utility/diff-view/diff-view.styles.js +1 -0
  1017. package/dist/components/utility/diff-view/diff-view.styles.js.map +1 -1
  1018. package/dist/components/utility/export-button/export-button.class.d.ts +1 -1
  1019. package/dist/components/utility/export-button/export-button.class.d.ts.map +1 -1
  1020. package/dist/components/utility/export-button/export-button.class.js +3 -1
  1021. package/dist/components/utility/export-button/export-button.class.js.map +1 -1
  1022. package/dist/components/utility/export-button/export-button.styles.d.ts.map +1 -1
  1023. package/dist/components/utility/export-button/export-button.styles.js +9 -3
  1024. package/dist/components/utility/export-button/export-button.styles.js.map +1 -1
  1025. package/dist/components/utility/format/relative-time.class.d.ts.map +1 -1
  1026. package/dist/components/utility/format/relative-time.class.js +5 -1
  1027. package/dist/components/utility/format/relative-time.class.js.map +1 -1
  1028. package/dist/components/utility/icon/icon.class.d.ts +2 -2
  1029. package/dist/components/utility/icon/icon.class.d.ts.map +1 -1
  1030. package/dist/components/utility/icon/icon.class.js +2 -1
  1031. package/dist/components/utility/icon/icon.class.js.map +1 -1
  1032. package/dist/components/utility/intersection-observer/intersection-observer.class.d.ts.map +1 -1
  1033. package/dist/components/utility/intersection-observer/intersection-observer.class.js +1 -0
  1034. package/dist/components/utility/intersection-observer/intersection-observer.class.js.map +1 -1
  1035. package/dist/components/utility/json-viewer/json-viewer.class.d.ts +2 -0
  1036. package/dist/components/utility/json-viewer/json-viewer.class.d.ts.map +1 -1
  1037. package/dist/components/utility/json-viewer/json-viewer.class.js +3 -0
  1038. package/dist/components/utility/json-viewer/json-viewer.class.js.map +1 -1
  1039. package/dist/components/utility/json-viewer/json-viewer.styles.d.ts.map +1 -1
  1040. package/dist/components/utility/json-viewer/json-viewer.styles.js +27 -8
  1041. package/dist/components/utility/json-viewer/json-viewer.styles.js.map +1 -1
  1042. package/dist/components/utility/known-date/known-date.class.d.ts +12 -1
  1043. package/dist/components/utility/known-date/known-date.class.d.ts.map +1 -1
  1044. package/dist/components/utility/known-date/known-date.class.js +13 -1
  1045. package/dist/components/utility/known-date/known-date.class.js.map +1 -1
  1046. package/dist/components/utility/known-date/known-date.styles.d.ts.map +1 -1
  1047. package/dist/components/utility/known-date/known-date.styles.js +33 -1
  1048. package/dist/components/utility/known-date/known-date.styles.js.map +1 -1
  1049. package/dist/components/utility/mention-popover/mention-popover.class.d.ts +2 -0
  1050. package/dist/components/utility/mention-popover/mention-popover.class.d.ts.map +1 -1
  1051. package/dist/components/utility/mention-popover/mention-popover.class.js +2 -0
  1052. package/dist/components/utility/mention-popover/mention-popover.class.js.map +1 -1
  1053. package/dist/components/utility/mention-popover/mention-popover.styles.d.ts.map +1 -1
  1054. package/dist/components/utility/mention-popover/mention-popover.styles.js +7 -2
  1055. package/dist/components/utility/mention-popover/mention-popover.styles.js.map +1 -1
  1056. package/dist/components/utility/mutation-observer/mutation-observer.class.d.ts.map +1 -1
  1057. package/dist/components/utility/mutation-observer/mutation-observer.class.js +17 -2
  1058. package/dist/components/utility/mutation-observer/mutation-observer.class.js.map +1 -1
  1059. package/dist/components/utility/poll-status/poll-status.class.d.ts +10 -0
  1060. package/dist/components/utility/poll-status/poll-status.class.d.ts.map +1 -1
  1061. package/dist/components/utility/poll-status/poll-status.class.js +34 -3
  1062. package/dist/components/utility/poll-status/poll-status.class.js.map +1 -1
  1063. package/dist/components/utility/poll-status/poll-status.styles.js +1 -1
  1064. package/dist/components/utility/tour/tour.class.d.ts +3 -0
  1065. package/dist/components/utility/tour/tour.class.d.ts.map +1 -1
  1066. package/dist/components/utility/tour/tour.class.js +18 -1
  1067. package/dist/components/utility/tour/tour.class.js.map +1 -1
  1068. package/dist/components/utility/tour/tour.styles.d.ts.map +1 -1
  1069. package/dist/components/utility/tour/tour.styles.js +9 -6
  1070. package/dist/components/utility/tour/tour.styles.js.map +1 -1
  1071. package/dist/components/viewers/archive-viewer/archive-viewer.class.d.ts +1 -0
  1072. package/dist/components/viewers/archive-viewer/archive-viewer.class.d.ts.map +1 -1
  1073. package/dist/components/viewers/archive-viewer/archive-viewer.class.js +4 -2
  1074. package/dist/components/viewers/archive-viewer/archive-viewer.class.js.map +1 -1
  1075. package/dist/components/viewers/archive-viewer/archive-viewer.styles.d.ts.map +1 -1
  1076. package/dist/components/viewers/archive-viewer/archive-viewer.styles.js +11 -5
  1077. package/dist/components/viewers/archive-viewer/archive-viewer.styles.js.map +1 -1
  1078. package/dist/components/viewers/calendar-viewer/calendar-viewer.class.d.ts.map +1 -1
  1079. package/dist/components/viewers/calendar-viewer/calendar-viewer.class.js +2 -3
  1080. package/dist/components/viewers/calendar-viewer/calendar-viewer.class.js.map +1 -1
  1081. package/dist/components/viewers/contact-viewer/contact-viewer.class.d.ts.map +1 -1
  1082. package/dist/components/viewers/contact-viewer/contact-viewer.class.js +6 -3
  1083. package/dist/components/viewers/contact-viewer/contact-viewer.class.js.map +1 -1
  1084. package/dist/components/viewers/csv-viewer/csv-viewer.class.d.ts +7 -0
  1085. package/dist/components/viewers/csv-viewer/csv-viewer.class.d.ts.map +1 -1
  1086. package/dist/components/viewers/csv-viewer/csv-viewer.class.js +27 -3
  1087. package/dist/components/viewers/csv-viewer/csv-viewer.class.js.map +1 -1
  1088. package/dist/components/viewers/csv-viewer/csv-viewer.styles.d.ts.map +1 -1
  1089. package/dist/components/viewers/csv-viewer/csv-viewer.styles.js +22 -3
  1090. package/dist/components/viewers/csv-viewer/csv-viewer.styles.js.map +1 -1
  1091. package/dist/components/viewers/dataset-viewer/dataset-viewer.class.d.ts +8 -2
  1092. package/dist/components/viewers/dataset-viewer/dataset-viewer.class.d.ts.map +1 -1
  1093. package/dist/components/viewers/dataset-viewer/dataset-viewer.class.js +18 -5
  1094. package/dist/components/viewers/dataset-viewer/dataset-viewer.class.js.map +1 -1
  1095. package/dist/components/viewers/dataset-viewer/dataset-viewer.styles.d.ts.map +1 -1
  1096. package/dist/components/viewers/dataset-viewer/dataset-viewer.styles.js +3 -0
  1097. package/dist/components/viewers/dataset-viewer/dataset-viewer.styles.js.map +1 -1
  1098. package/dist/components/viewers/document-compare/document-compare.class.d.ts +9 -2
  1099. package/dist/components/viewers/document-compare/document-compare.class.d.ts.map +1 -1
  1100. package/dist/components/viewers/document-compare/document-compare.class.js +14 -1
  1101. package/dist/components/viewers/document-compare/document-compare.class.js.map +1 -1
  1102. package/dist/components/viewers/document-compare/document-compare.styles.d.ts.map +1 -1
  1103. package/dist/components/viewers/document-compare/document-compare.styles.js +1 -0
  1104. package/dist/components/viewers/document-compare/document-compare.styles.js.map +1 -1
  1105. package/dist/components/viewers/document-preview/document-preview.class.d.ts +4 -1
  1106. package/dist/components/viewers/document-preview/document-preview.class.d.ts.map +1 -1
  1107. package/dist/components/viewers/document-preview/document-preview.class.js +5 -1
  1108. package/dist/components/viewers/document-preview/document-preview.class.js.map +1 -1
  1109. package/dist/components/viewers/document-preview/document-preview.styles.d.ts.map +1 -1
  1110. package/dist/components/viewers/document-preview/document-preview.styles.js +8 -1
  1111. package/dist/components/viewers/document-preview/document-preview.styles.js.map +1 -1
  1112. package/dist/components/viewers/document-viewer/document-viewer.class.d.ts.map +1 -1
  1113. package/dist/components/viewers/document-viewer/document-viewer.class.js +1 -0
  1114. package/dist/components/viewers/document-viewer/document-viewer.class.js.map +1 -1
  1115. package/dist/components/viewers/docx-viewer/docx-viewer.styles.d.ts.map +1 -1
  1116. package/dist/components/viewers/docx-viewer/docx-viewer.styles.js +3 -0
  1117. package/dist/components/viewers/docx-viewer/docx-viewer.styles.js.map +1 -1
  1118. package/dist/components/viewers/ebook-viewer/ebook-viewer.styles.d.ts.map +1 -1
  1119. package/dist/components/viewers/ebook-viewer/ebook-viewer.styles.js +4 -0
  1120. package/dist/components/viewers/ebook-viewer/ebook-viewer.styles.js.map +1 -1
  1121. package/dist/components/viewers/email-viewer/email-viewer.class.d.ts +2 -0
  1122. package/dist/components/viewers/email-viewer/email-viewer.class.d.ts.map +1 -1
  1123. package/dist/components/viewers/email-viewer/email-viewer.class.js +5 -2
  1124. package/dist/components/viewers/email-viewer/email-viewer.class.js.map +1 -1
  1125. package/dist/components/viewers/email-viewer/email-viewer.styles.d.ts.map +1 -1
  1126. package/dist/components/viewers/email-viewer/email-viewer.styles.js +20 -1
  1127. package/dist/components/viewers/email-viewer/email-viewer.styles.js.map +1 -1
  1128. package/dist/components/viewers/geojson-view/geojson-view.class.d.ts +6 -0
  1129. package/dist/components/viewers/geojson-view/geojson-view.class.d.ts.map +1 -1
  1130. package/dist/components/viewers/geojson-view/geojson-view.class.js +2 -1
  1131. package/dist/components/viewers/geojson-view/geojson-view.class.js.map +1 -1
  1132. package/dist/components/viewers/highlight-layer/highlight-layer.class.d.ts.map +1 -1
  1133. package/dist/components/viewers/highlight-layer/highlight-layer.class.js +16 -1
  1134. package/dist/components/viewers/highlight-layer/highlight-layer.class.js.map +1 -1
  1135. package/dist/components/viewers/highlight-layer/highlight-layer.styles.d.ts.map +1 -1
  1136. package/dist/components/viewers/highlight-layer/highlight-layer.styles.js +3 -0
  1137. package/dist/components/viewers/highlight-layer/highlight-layer.styles.js.map +1 -1
  1138. package/dist/components/viewers/html-viewer/dompurify-loader.d.ts +1 -1
  1139. package/dist/components/viewers/html-viewer/dompurify-loader.d.ts.map +1 -1
  1140. package/dist/components/viewers/html-viewer/dompurify-loader.js +5 -1
  1141. package/dist/components/viewers/html-viewer/dompurify-loader.js.map +1 -1
  1142. package/dist/components/viewers/html-viewer/html-viewer.class.d.ts.map +1 -1
  1143. package/dist/components/viewers/html-viewer/html-viewer.class.js +2 -1
  1144. package/dist/components/viewers/html-viewer/html-viewer.class.js.map +1 -1
  1145. package/dist/components/viewers/include/include.class.d.ts.map +1 -1
  1146. package/dist/components/viewers/include/include.class.js +1 -0
  1147. package/dist/components/viewers/include/include.class.js.map +1 -1
  1148. package/dist/components/viewers/notebook-viewer/dompurify-loader.d.ts +1 -1
  1149. package/dist/components/viewers/notebook-viewer/dompurify-loader.d.ts.map +1 -1
  1150. package/dist/components/viewers/notebook-viewer/dompurify-loader.js +7 -1
  1151. package/dist/components/viewers/notebook-viewer/dompurify-loader.js.map +1 -1
  1152. package/dist/components/viewers/notebook-viewer/notebook-viewer.class.d.ts +7 -0
  1153. package/dist/components/viewers/notebook-viewer/notebook-viewer.class.d.ts.map +1 -1
  1154. package/dist/components/viewers/notebook-viewer/notebook-viewer.class.js +15 -4
  1155. package/dist/components/viewers/notebook-viewer/notebook-viewer.class.js.map +1 -1
  1156. package/dist/components/viewers/notebook-viewer/notebook-viewer.styles.d.ts.map +1 -1
  1157. package/dist/components/viewers/notebook-viewer/notebook-viewer.styles.js +31 -12
  1158. package/dist/components/viewers/notebook-viewer/notebook-viewer.styles.js.map +1 -1
  1159. package/dist/components/viewers/page-rail/page-rail.class.d.ts +9 -0
  1160. package/dist/components/viewers/page-rail/page-rail.class.d.ts.map +1 -1
  1161. package/dist/components/viewers/page-rail/page-rail.class.js +16 -4
  1162. package/dist/components/viewers/page-rail/page-rail.class.js.map +1 -1
  1163. package/dist/components/viewers/page-rail/page-rail.styles.d.ts.map +1 -1
  1164. package/dist/components/viewers/page-rail/page-rail.styles.js +24 -14
  1165. package/dist/components/viewers/page-rail/page-rail.styles.js.map +1 -1
  1166. package/dist/components/viewers/pdf-viewer/pdf-viewer.class.d.ts +15 -0
  1167. package/dist/components/viewers/pdf-viewer/pdf-viewer.class.d.ts.map +1 -1
  1168. package/dist/components/viewers/pdf-viewer/pdf-viewer.class.js +29 -4
  1169. package/dist/components/viewers/pdf-viewer/pdf-viewer.class.js.map +1 -1
  1170. package/dist/components/viewers/pdf-viewer/pdf-viewer.styles.d.ts.map +1 -1
  1171. package/dist/components/viewers/pdf-viewer/pdf-viewer.styles.js +26 -9
  1172. package/dist/components/viewers/pdf-viewer/pdf-viewer.styles.js.map +1 -1
  1173. package/dist/components/viewers/pptx-viewer/pptx-viewer.class.d.ts.map +1 -1
  1174. package/dist/components/viewers/pptx-viewer/pptx-viewer.class.js +1 -0
  1175. package/dist/components/viewers/pptx-viewer/pptx-viewer.class.js.map +1 -1
  1176. package/dist/components/viewers/pptx-viewer/pptx-viewer.styles.d.ts.map +1 -1
  1177. package/dist/components/viewers/pptx-viewer/pptx-viewer.styles.js +2 -0
  1178. package/dist/components/viewers/pptx-viewer/pptx-viewer.styles.js.map +1 -1
  1179. package/dist/components/viewers/spreadsheet-viewer/fixtures/minimal-xlsx-fixture.d.ts +2 -0
  1180. package/dist/components/viewers/spreadsheet-viewer/fixtures/minimal-xlsx-fixture.d.ts.map +1 -0
  1181. package/dist/components/viewers/spreadsheet-viewer/fixtures/minimal-xlsx-fixture.js +5 -0
  1182. package/dist/components/viewers/spreadsheet-viewer/fixtures/minimal-xlsx-fixture.js.map +1 -0
  1183. package/dist/components/viewers/spreadsheet-viewer/spreadsheet-viewer.class.d.ts +3 -0
  1184. package/dist/components/viewers/spreadsheet-viewer/spreadsheet-viewer.class.d.ts.map +1 -1
  1185. package/dist/components/viewers/spreadsheet-viewer/spreadsheet-viewer.class.js +6 -1
  1186. package/dist/components/viewers/spreadsheet-viewer/spreadsheet-viewer.class.js.map +1 -1
  1187. package/dist/components/viewers/spreadsheet-viewer/spreadsheet-viewer.styles.d.ts.map +1 -1
  1188. package/dist/components/viewers/spreadsheet-viewer/spreadsheet-viewer.styles.js +12 -1
  1189. package/dist/components/viewers/spreadsheet-viewer/spreadsheet-viewer.styles.js.map +1 -1
  1190. package/dist/components/viewers/svg-viewer/dompurify-loader.d.ts +1 -1
  1191. package/dist/components/viewers/svg-viewer/dompurify-loader.d.ts.map +1 -1
  1192. package/dist/components/viewers/svg-viewer/dompurify-loader.js +6 -1
  1193. package/dist/components/viewers/svg-viewer/dompurify-loader.js.map +1 -1
  1194. package/dist/components/viewers/svg-viewer/svg-viewer.class.d.ts +3 -0
  1195. package/dist/components/viewers/svg-viewer/svg-viewer.class.d.ts.map +1 -1
  1196. package/dist/components/viewers/svg-viewer/svg-viewer.class.js +5 -1
  1197. package/dist/components/viewers/svg-viewer/svg-viewer.class.js.map +1 -1
  1198. package/dist/components/viewers/svg-viewer/svg-viewer.styles.d.ts.map +1 -1
  1199. package/dist/components/viewers/svg-viewer/svg-viewer.styles.js +8 -1
  1200. package/dist/components/viewers/svg-viewer/svg-viewer.styles.js.map +1 -1
  1201. package/dist/components/viewers/xml-viewer/xml-viewer.class.d.ts +9 -0
  1202. package/dist/components/viewers/xml-viewer/xml-viewer.class.d.ts.map +1 -1
  1203. package/dist/components/viewers/xml-viewer/xml-viewer.class.js +0 -0
  1204. package/dist/components/viewers/xml-viewer/xml-viewer.class.js.map +1 -1
  1205. package/dist/components/viewers/xml-viewer/xml-viewer.styles.d.ts.map +1 -1
  1206. package/dist/components/viewers/xml-viewer/xml-viewer.styles.js +22 -8
  1207. package/dist/components/viewers/xml-viewer/xml-viewer.styles.js.map +1 -1
  1208. package/dist/internal/localization.d.ts +11 -1
  1209. package/dist/internal/localization.d.ts.map +1 -1
  1210. package/dist/internal/localization.js +31 -1
  1211. package/dist/internal/localization.js.map +1 -1
  1212. package/dist/internal/orientation-breakpoint.d.ts +19 -8
  1213. package/dist/internal/orientation-breakpoint.d.ts.map +1 -1
  1214. package/dist/internal/orientation-breakpoint.js +181 -0
  1215. package/dist/internal/orientation-breakpoint.js.map +1 -1
  1216. package/dist/internal/root-registration-allowlist.d.ts +1 -1
  1217. package/dist/internal/root-registration-allowlist.d.ts.map +1 -1
  1218. package/dist/internal/root-registration-allowlist.js +3 -1
  1219. package/dist/internal/root-registration-allowlist.js.map +1 -1
  1220. package/dist/internal/tokens.styles.d.ts.map +1 -1
  1221. package/dist/internal/tokens.styles.js +23 -5
  1222. package/dist/internal/tokens.styles.js.map +1 -1
  1223. package/dist/lyra.d.ts +18 -12
  1224. package/dist/lyra.d.ts.map +1 -1
  1225. package/dist/lyra.js +8 -4
  1226. package/dist/lyra.js.map +1 -1
  1227. package/dist/theme.css +104 -0
  1228. package/llms/components/lr-activity-feed.md +11 -2
  1229. package/llms/components/lr-agent-run.md +16 -1
  1230. package/llms/components/lr-agent-trace.md +11 -0
  1231. package/llms/components/lr-app-rail-item.md +11 -0
  1232. package/llms/components/lr-app-rail.md +11 -0
  1233. package/llms/components/lr-archive-viewer.md +7 -1
  1234. package/llms/components/lr-artifact-panel.md +11 -1
  1235. package/llms/components/lr-av-player.md +38 -2
  1236. package/llms/components/lr-avatar-group.md +6 -1
  1237. package/llms/components/lr-avatar.md +6 -2
  1238. package/llms/components/lr-badge.md +8 -1
  1239. package/llms/components/lr-bar-chart.md +3 -1
  1240. package/llms/components/lr-breadcrumb-item.md +9 -0
  1241. package/llms/components/lr-breadcrumb.md +9 -0
  1242. package/llms/components/lr-bubble-chart.md +3 -1
  1243. package/llms/components/lr-button.md +33 -2
  1244. package/llms/components/lr-calendar.md +5 -1
  1245. package/llms/components/lr-callout.md +6 -1
  1246. package/llms/components/lr-card.md +26 -5
  1247. package/llms/components/lr-carousel.md +9 -0
  1248. package/llms/components/lr-chart.md +2 -1
  1249. package/llms/components/lr-chat-composer.md +18 -5
  1250. package/llms/components/lr-chat-message.md +16 -0
  1251. package/llms/components/lr-chat-viewport.md +12 -0
  1252. package/llms/components/lr-checkbox-group.md +17 -0
  1253. package/llms/components/lr-checkbox.md +28 -1
  1254. package/llms/components/lr-chip-group.md +20 -2
  1255. package/llms/components/lr-chip.md +20 -2
  1256. package/llms/components/lr-chunk-inspector.md +33 -5
  1257. package/llms/components/lr-code-block-core.md +6 -1
  1258. package/llms/components/lr-code-block.md +20 -1
  1259. package/llms/components/lr-color-picker.md +7 -1
  1260. package/llms/components/lr-combobox.md +40 -5
  1261. package/llms/components/lr-command-palette.md +18 -7
  1262. package/llms/components/lr-commit-card.md +10 -0
  1263. package/llms/components/lr-community-card.md +5 -0
  1264. package/llms/components/lr-confirm-bar.md +55 -3
  1265. package/llms/components/lr-control-group.md +12 -4
  1266. package/llms/components/lr-conversation-item.md +41 -1
  1267. package/llms/components/lr-csv-viewer.md +16 -3
  1268. package/llms/components/lr-dashboard-grid.md +4 -1
  1269. package/llms/components/lr-dataset-viewer.md +4 -1
  1270. package/llms/components/lr-date-input.md +36 -7
  1271. package/llms/components/lr-date-picker.md +36 -7
  1272. package/llms/components/lr-document-preview.md +9 -1
  1273. package/llms/components/lr-doughnut-chart.md +3 -1
  1274. package/llms/components/lr-dropdown-item.md +63 -11
  1275. package/llms/components/lr-email-viewer.md +4 -3
  1276. package/llms/components/lr-emoji-picker.md +38 -9
  1277. package/llms/components/lr-empty.md +5 -2
  1278. package/llms/components/lr-entity-card.md +14 -1
  1279. package/llms/components/lr-env-list.md +9 -0
  1280. package/llms/components/lr-eval-dataset.md +4 -2
  1281. package/llms/components/lr-eval-result.md +4 -4
  1282. package/llms/components/lr-export-button.md +4 -1
  1283. package/llms/components/lr-file-input.md +19 -2
  1284. package/llms/components/lr-filter-bar.md +23 -0
  1285. package/llms/components/lr-flag.md +43 -1
  1286. package/llms/components/lr-flow-canvas.md +21 -2
  1287. package/llms/components/lr-flow-controls.md +14 -3
  1288. package/llms/components/lr-flow-node.md +24 -3
  1289. package/llms/components/lr-flow-run-overlay.md +4 -0
  1290. package/llms/components/lr-graph-legend.md +4 -1
  1291. package/llms/components/lr-graph.md +4 -1
  1292. package/llms/components/lr-heatmap.md +29 -3
  1293. package/llms/components/lr-histogram.md +3 -1
  1294. package/llms/components/lr-icon-button.md +29 -8
  1295. package/llms/components/lr-image-viewer.md +20 -1
  1296. package/llms/components/lr-ingestion-queue.md +8 -0
  1297. package/llms/components/lr-input.md +36 -1
  1298. package/llms/components/lr-json-viewer.md +6 -3
  1299. package/llms/components/lr-known-date.md +22 -3
  1300. package/llms/components/lr-line-chart.md +3 -1
  1301. package/llms/components/lr-locale-picker.md +86 -0
  1302. package/llms/components/lr-map.md +3 -1
  1303. package/llms/components/lr-markdown-core.md +9 -0
  1304. package/llms/components/lr-markdown.md +13 -1
  1305. package/llms/components/lr-media-card.md +5 -0
  1306. package/llms/components/lr-memory-panel.md +6 -1
  1307. package/llms/components/lr-mention-popover.md +10 -3
  1308. package/llms/components/lr-menu-item.md +63 -11
  1309. package/llms/components/lr-menu.md +63 -11
  1310. package/llms/components/lr-message-feedback.md +15 -0
  1311. package/llms/components/lr-mind-map.md +3 -1
  1312. package/llms/components/lr-model-select.md +29 -4
  1313. package/llms/components/lr-neighbor-list.md +10 -4
  1314. package/llms/components/lr-node-palette.md +3 -1
  1315. package/llms/components/lr-notebook-viewer.md +17 -2
  1316. package/llms/components/lr-number-input.md +3 -2
  1317. package/llms/components/lr-option.md +40 -5
  1318. package/llms/components/lr-page-rail.md +14 -3
  1319. package/llms/components/lr-pagination.md +5 -2
  1320. package/llms/components/lr-pdf-viewer.md +25 -9
  1321. package/llms/components/lr-phone-input.md +49 -8
  1322. package/llms/components/lr-pie-chart.md +3 -1
  1323. package/llms/components/lr-polar-area-chart.md +3 -1
  1324. package/llms/components/lr-policy-summary.md +10 -0
  1325. package/llms/components/lr-poll-status.md +5 -1
  1326. package/llms/components/lr-push-to-talk.md +8 -1
  1327. package/llms/components/lr-radar-chart.md +3 -1
  1328. package/llms/components/lr-radio.md +10 -2
  1329. package/llms/components/lr-reorder-item.md +81 -0
  1330. package/llms/components/lr-reorder-list.md +81 -0
  1331. package/llms/components/lr-responsive-panel.md +5 -1
  1332. package/llms/components/lr-result-card.md +14 -2
  1333. package/llms/components/lr-result-field.md +14 -2
  1334. package/llms/components/lr-retrieval-results.md +30 -3
  1335. package/llms/components/lr-retrieval-trace.md +8 -1
  1336. package/llms/components/lr-rubric-form.md +5 -0
  1337. package/llms/components/lr-scatter-chart.md +3 -1
  1338. package/llms/components/lr-segmented.md +23 -1
  1339. package/llms/components/lr-select.md +33 -6
  1340. package/llms/components/lr-sequence-strip.md +16 -4
  1341. package/llms/components/lr-source-card.md +14 -1
  1342. package/llms/components/lr-source-list.md +14 -1
  1343. package/llms/components/lr-source-picker.md +13 -1
  1344. package/llms/components/lr-span-waterfall.md +12 -2
  1345. package/llms/components/lr-split.md +46 -4
  1346. package/llms/components/lr-spreadsheet-viewer.md +10 -1
  1347. package/llms/components/lr-stack-trace.md +7 -1
  1348. package/llms/components/lr-stat.md +26 -4
  1349. package/llms/components/lr-stepper.md +25 -8
  1350. package/llms/components/lr-suggestion-chips.md +9 -0
  1351. package/llms/components/lr-svg-viewer.md +8 -0
  1352. package/llms/components/lr-swatch-picker.md +15 -9
  1353. package/llms/components/lr-table.md +117 -6
  1354. package/llms/components/lr-tabs.md +12 -1
  1355. package/llms/components/lr-tag.md +8 -1
  1356. package/llms/components/lr-task-list.md +12 -2
  1357. package/llms/components/lr-terminal.md +14 -2
  1358. package/llms/components/lr-test-results.md +11 -0
  1359. package/llms/components/lr-thread-list.md +75 -10
  1360. package/llms/components/lr-time-input.md +3 -2
  1361. package/llms/components/lr-time-range.md +26 -2
  1362. package/llms/components/lr-token-input.md +43 -8
  1363. package/llms/components/lr-tool-approval-dialog.md +34 -10
  1364. package/llms/components/lr-tool-timeline.md +6 -1
  1365. package/llms/components/lr-tour.md +11 -1
  1366. package/llms/components/lr-trace-tree.md +23 -0
  1367. package/llms/components/lr-tree-node.md +21 -3
  1368. package/llms/components/lr-tree.md +21 -3
  1369. package/llms/components/lr-virtual-list.md +104 -11
  1370. package/llms/components/lr-voice-picker.md +8 -0
  1371. package/llms/components/lr-widget.md +11 -0
  1372. package/llms/components/lr-xml-viewer.md +24 -1
  1373. package/llms/index.md +7 -5
  1374. package/llms/peers.md +1 -1
  1375. package/llms/shared.md +142 -11
  1376. package/llms/tokens.md +16 -7
  1377. package/llms-full.txt +2517 -345
  1378. package/llms.txt +16 -4
  1379. package/package.json +17 -5
  1380. package/vscode-css-data.json +1575 -147
  1381. package/vscode-html-data.json +988 -489
  1382. package/web-types.json +2100 -278
  1383. package/dist/components/data/data-grid/data-grid.class.d.ts +0 -65
  1384. package/dist/components/data/data-grid/data-grid.class.d.ts.map +0 -1
  1385. package/dist/components/data/data-grid/data-grid.class.js +0 -119
  1386. package/dist/components/data/data-grid/data-grid.class.js.map +0 -1
  1387. package/dist/components/data/data-grid/data-grid.d.ts +0 -2
  1388. package/dist/components/data/data-grid/data-grid.d.ts.map +0 -1
  1389. package/dist/components/data/data-grid/data-grid.js +0 -5
  1390. package/dist/components/data/data-grid/data-grid.js.map +0 -1
  1391. package/dist/components/data/data-grid/data-grid.styles.d.ts.map +0 -1
  1392. package/dist/components/data/data-grid/data-grid.styles.js +0 -13
  1393. package/dist/components/data/data-grid/data-grid.styles.js.map +0 -1
  1394. package/llms/components/lr-data-grid.md +0 -47
package/llms-full.txt CHANGED
@@ -7,7 +7,7 @@ Agent UI. Selected components retain documented Web Awesome-compatible public na
7
7
  prefix to make migration easier, but Lyra has its own implementation, design tokens, localization
8
8
  runtime, RTL behavior, and release surface. It has no runtime dependency on either project.
9
9
 
10
- **This file is the whole catalog concatenated — 249 components, several hundred thousand tokens.**
10
+ **This file is the whole catalog concatenated — 251 components, several hundred thousand tokens.**
11
11
  Read it end to end only if you genuinely need everything. Otherwise:
12
12
 
13
13
  | To… | Read |
@@ -31,9 +31,9 @@ and costs a few hundred tokens instead of the whole catalog. `llms/index.md` map
31
31
  family and entry point.
32
32
 
33
33
  - **Foundation** — base class, form association, events, i18n, theming, TypeScript, frameworks, SSR, packaging (`llms/shared.md`)
34
- - **Form controls & inputs** — 25 tags in `components/forms/`
35
- - **Data display, dashboards & flow canvas** — 25 tags in `components/data/`
36
- - **Layout, navigation & structure** — 28 tags in `components/layout/`
34
+ - **Form controls & inputs** — 26 tags in `components/forms/`
35
+ - **Data display, dashboards & flow canvas** — 24 tags in `components/data/`
36
+ - **Layout, navigation & structure** — 30 tags in `components/layout/`
37
37
  - **Overlays, status & feedback** — 19 tags in `components/overlays/`
38
38
  - **Utilities, formatting & observers** — 19 tags in `components/utility/`
39
39
  - **Media, files & maps** — 18 tags in `components/media/`
@@ -58,7 +58,7 @@ import '@aceshooting/lyra-ui/components/forms/combobox/combobox.js'; // register
58
58
  import '@aceshooting/lyra-ui/components/data/table/table.js'; // registers <lr-table>
59
59
  ```
60
60
 
61
- `llms/index.md` lists the exact path for all 249 tags. A wrong or missing family segment is a hard
61
+ `llms/index.md` lists the exact path for all 251 tags. A wrong or missing family segment is a hard
62
62
  module-resolution failure, not a silent no-op — `exports` maps `./components/*` straight onto
63
63
  `./dist/components/*`.
64
64
 
@@ -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 */
@@ -205,12 +266,21 @@ setLyraLocale('fr'); // …or just set <html lang="fr"> and let components inher
205
266
  ```
206
267
 
207
268
  Exported from the package root: `registerLyraLocale`, `setLyraLocale`, `getLyraLocale`,
208
- `resolveLyraLocale`, `resolveLyraDirection`, `resolveLyraString`, `LYRA_DEFAULT_STRINGS`, and the
209
- types `LyraLocaleStrings` / `LyraMessageKey`. **`LYRA_DEFAULT_STRINGS` is the authoritative key list**
210
- (996 keys, matching the `LyraMessageKey` union) read it to find the key to override rather than
269
+ `getRegisteredLyraLocales`, `subscribeLyraLocaleRegistry`, `resolveLyraLocale`,
270
+ `resolveLyraDirection`, `resolveLyraString`, `LYRA_DEFAULT_STRINGS`, and the types
271
+ `LyraLocaleStrings` / `LyraMessageKey`. **`LYRA_DEFAULT_STRINGS` is the authoritative key list**
272
+ (1005 keys, matching the `LyraMessageKey` union) — read it to find the key to override rather than
211
273
  guessing one. Lookup falls back exact locale → base language → English. Date, number, byte,
212
274
  relative-time and calendar output goes through `Intl`.
213
275
 
276
+ `getRegisteredLyraLocales(): string[]` lists every locale with strings registered via
277
+ `registerLyraLocale()`, plus `'en'` (always available through the built-in English fallback),
278
+ sorted and deduped. `subscribeLyraLocaleRegistry(listener: () => void): () => void` fires whenever
279
+ `registerLyraLocale()` registers *any* locale — including one that isn't the currently active
280
+ locale — unlike the page-level locale-change subscription every component already uses
281
+ internally, which only fires for the active locale's own string changes. `<lr-locale-picker>` is
282
+ the built-in consumer of both; see `llms/components/lr-locale-picker.md`.
283
+
214
284
  Gotcha: `localize()`'s optional second argument is a fallback string. Passing a defined literal there
215
285
  silently defeats a registered catalog — omit it, or pass `undefined`.
216
286
 
@@ -336,7 +406,7 @@ Not custom elements — infrastructure the components compose. Importable via
336
406
  Returns a cleanup function that stops the `autoUpdate` loop — call it in `disconnectedCallback()`.
337
407
  Used by `lr-combobox`, `lr-select`, `lr-date-input`, `lr-export-button`, `lr-model-select`,
338
408
  `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)`,
409
+ - **`prefix.ts`** — `LYRA_PREFIX = 'lr'`; `tag(name)` → `` `lr-${name}` ``; `defineElement(name, ctor)`,
340
410
  an idempotent `customElements.define` that is safe if a module is evaluated twice.
341
411
  - **`a11y.ts`** — `nextId(scope)`, a monotonic id generator (`nextId('combobox-list')` →
342
412
  `"lr-combobox-list-3"`); `srOnly`, a visually-hidden-but-AT-visible class.
@@ -370,6 +440,67 @@ Not custom elements — infrastructure the components compose. Importable via
370
440
  `prepack` and included in `package.json`'s `files` allowlist, so a published tarball always carries
371
441
  an up-to-date copy matching its `dist/`.
372
442
 
443
+ ## When no component fits, file it
444
+
445
+ First rule out a naming mismatch: check `llms/index.md` for a component covering the same job
446
+ under a different name. Most apparent gaps are discovery failures, not missing components.
447
+
448
+ Then check the live catalog — one read-only request, no side effects, nothing filed:
449
+
450
+ ```bash
451
+ curl -sS 'https://www.lyra-ui.com/api/v1/components/search?q=kanban+board+swimlane'
452
+ ```
453
+
454
+ It returns the closest components with doc links. Search as many phrasings as you like; this
455
+ endpoint is meant to be used freely, and it is the cheapest way to discover that a "missing"
456
+ component already exists under a name you did not guess.
457
+
458
+ If nothing fits, report the gap so it can be built — but **ask the user and get their explicit
459
+ agreement first.** Filing sends the user's description to an external service; show them what you
460
+ intend to submit, and never file as a silent side effect of noticing a gap. If the user has not
461
+ said yes, do not send it.
462
+
463
+ ```bash
464
+ curl -sS -X POST https://www.lyra-ui.com/api/v1/feature-requests \
465
+ -H 'Content-Type: application/json' \
466
+ -d '{
467
+ "title": "Kanban board",
468
+ "description": "Needed a drag-and-drop board with swimlanes for a task view; nothing in the catalog covers it.",
469
+ "searched_for": ["kanban", "board", "swimlane", "drag drop"],
470
+ "settled_for": "a hand-rolled div grid with HTML5 drag events",
471
+ "agent": "claude-code"
472
+ }'
473
+ ```
474
+
475
+ Accepted fields: `title` (required, ≤120 chars), `description` (required, ≤4000 chars), `use_case`,
476
+ `searched_for` (array of terms tried — the most valuable field, since it records which name was
477
+ expected and that's exactly what makes a component undiscoverable), `settled_for` (what was used
478
+ instead), `agent`, and the optional contact fields `name` (≤120) and `email` (≤200). Anonymous
479
+ submission is the default and is fine — `name`/`email` only add value if the maintainer might
480
+ follow up. Ask the user whether they want to be reachable before adding either one; never invent,
481
+ guess, or reuse an address from context you happen to have (git config, an earlier message, the
482
+ environment). All submissions, including any name/email, are stored privately and shown only to
483
+ the maintainer — never published.
484
+
485
+ The response includes `matches` (the closest existing components, with doc links — read it, since
486
+ it often answers the gap outright) and an `id`; status is readable later at
487
+ `https://www.lyra-ui.com/api/v1/feature-requests/{id}`. The full schema is at
488
+ `https://www.lyra-ui.com/api/v1/openapi.json`.
489
+
490
+ **Never include private material.** Submissions leave the user's machine. Describe the component
491
+ generically — no source code, no client or product names, no file paths, no credentials. If the
492
+ need cannot be described without such details, do not file it.
493
+
494
+ Use the API even when you are working inside the lyra-ui repo itself. It is the only intake path —
495
+ do not write the request into a local file instead, where nothing will pick it up.
496
+
497
+ Keep the report short and concrete:
498
+
499
+ - **Name the component you wanted**, in library style (`lr-kanban-board`), so the gap is searchable.
500
+ - **Say what it had to do** in a sentence or two — the behaviour, not your implementation.
501
+ - **List the `lr-*` components you actually checked** and why each fell short. This is what separates
502
+ a real gap from a naming mismatch, and it is the part only you can supply.
503
+
373
504
  # Form controls & inputs (`components/forms/`)
374
505
 
375
506
  ## `lr-combobox` / `lr-option`
@@ -382,7 +513,7 @@ shared `FormAssociated` mixin — see gotchas).
382
513
 
383
514
  **Properties:**
384
515
  - `multiple: boolean = false` (reflected)
385
- - `size: 'xs' | 's' | 'm' | 'l' | 'xl' = 'm'` (reflected — same scale as `lr-select`'s `size`;
516
+ - `size: '2xs' | 'xs' | 's' | 'm' | 'l' | 'xl' = 'm'` (reflected — same scale as `lr-select`'s `size`;
386
517
  also scales the "+N" overflow tag and decorative expand icon; `size="s"` shares its outer
387
518
  control height with `lr-input`, `lr-select`, and `lr-segmented` without part overrides)
388
519
  - `placeholder: string = ''`
@@ -396,7 +527,9 @@ shared `FormAssociated` mixin — see gotchas).
396
527
  - `errorText: string = ''` (attribute `error-text` — static error copy shown below the hint;
397
528
  overridden by slotted `error` content when provided)
398
529
  - `open: boolean = false` (reflected)
399
- - `clearable: boolean = false` (reflected) — displays the clear button while a value is selected
530
+ - `clearable: boolean = false` (reflected) — displays the clear button while there is something to
531
+ clear on **either** axis this control owns: a committed selection, or *visible* filter text. See
532
+ "the clear button covers two axes" below
400
533
  - `withClear: boolean = false` (attribute `with-clear`) — deprecated compatibility alias for
401
534
  `clearable`; either property enables the same clear button
402
535
  - `autocomplete: string = 'off'`, `inputMode: string = ''` (attribute `inputmode`),
@@ -457,10 +590,31 @@ the filter silently, mirroring how `<lr-input>`'s `lr-input` only reports user e
457
590
  `lr-show` and `lr-hide` report listbox visibility transitions.
458
591
  The internal input's `focus` and `blur` are re-dispatched as bubbling, composed host events.
459
592
 
460
- **Slots:** default (`<lr-option>` children), `label`, `hint`, `error` (overrides the `errorText`
461
- attribute when provided)
593
+ **The clear button covers two axes, and announces only the one that moved.** A combobox owns both a
594
+ committed selection and an in-progress filter query, so the button renders whenever either has
595
+ something to clear, and one press clears both:
596
+
597
+ - Clearing a selection emits `input`, then `change`, then `lr-clear` — and, if the query was also
598
+ non-empty, `lr-filter` with an empty `value`.
599
+ - A **query-only** clear (nothing selected, just typed text) emits `lr-filter` with an empty
600
+ `value` and deliberately **no** `change` and **no** `lr-clear`. There was no selection
601
+ transition to report, so announcing one would be a lie. Don't listen for `lr-clear` to detect
602
+ "the user emptied the field" — listen for `lr-filter` when you care about the query.
603
+ - The query half of the render gate is scoped to states where the query is actually *visible*: an
604
+ open listbox in single-select, or any time in `multiple` mode. A closed single-select shows the
605
+ selected label rather than the query, so a stale query alone never surfaces a button offering to
606
+ clear text the user cannot see.
462
607
 
463
- **CSS parts:** `form-control`, `form-control-label`, `combobox`, `tags`, `tag`,
608
+ **Slots:** default (`<lr-option>` children), `label`, `hint`, `error` (overrides the `errorText`
609
+ attribute when provided), plus two adornment slots:
610
+ - `start` — content at the inline-start of the trigger row, before the selected-value tags and the
611
+ filter input. It is decorative chrome, **not** an option: only `<lr-option>` elements in the
612
+ default slot are ever collected into the option list.
613
+ - `end` — content after the filter input and the built-in clear action, and before the expand icon,
614
+ so consumer content never sits outboard of the dropdown chevron.
615
+
616
+ **CSS parts:** `form-control`, `form-control-label`, `combobox`, `start` and `end` (the two
617
+ adornment-slot wrappers, each `hidden` while nothing is slotted into it), `tags`, `tag`,
464
618
  `tag__remove-button`, `combobox-input`, `clear-button`, `expand-icon`, `listbox`, `option`,
465
619
  `option-dot` (the leading status dot, when a row's `dotColor` is set), `option-icon` (the decorative
466
620
  leading visual for an async row), `option-label`, `option-sub` (a row's secondary line, when `sub`
@@ -472,6 +626,18 @@ indicator from `maxRender`), `error`, `hint`
472
626
  `--lr-combobox-tag-font-size`, and `--lr-combobox-expand-size` (the decorative icon box; each
473
627
  standard size supplies an aligned default), plus shared tokens.
474
628
 
629
+ `--lr-combobox-option-active-bg` (default `var(--lr-color-brand-quiet)`) recolors the background of
630
+ a hovered or keyboard-active `[part='option']` row — the same per-component indirection
631
+ `lr-select`'s identical `--lr-select-option-active-bg` uses, so a consumer can retheme just this
632
+ row state without hijacking the shared `--lr-color-brand-quiet` token library-wide.
633
+
634
+ `--lr-combobox-trigger-height` pins an **exact** input-container height (both floors and caps it),
635
+ for pixel-matching an `<lr-input>` or `<lr-select>` in the same toolbar row. It is **undeclared by
636
+ default**, leaving `--lr-combobox-trigger-min-height` as a floor only and the row free to grow —
637
+ see "exact-height hatches" under `lr-input` for why `auto` is not a way to opt back out. Intended
638
+ for a single-row combobox: in `multiple` mode, a tag row long enough to wrap overflows the pinned
639
+ box visibly (nothing is clipped or made unreachable), so leave it unset there.
640
+
475
641
  **Optional peer deps:** none.
476
642
 
477
643
  ### `lr-option`
@@ -591,8 +757,8 @@ exactly like the multi-option case, until the trigger is actually activated.
591
757
  - `errorText: string = ''` (attribute `error-text` — static error copy shown below the hint;
592
758
  overridden by slotted `error` content when provided)
593
759
  - `open: boolean = false` (reflected)
594
- - `size: 'xs'|'s'|'m'|'l'|'xl' = 'm'` (reflected — same scale as `lr-toast-item`'s `size`, for
595
- compact toolbar placements that don't fit the default trigger height)
760
+ - `size: '2xs'|'xs'|'s'|'m'|'l'|'xl' = 'm'` (reflected — same scale as `lr-input`/`lr-combobox`'s
761
+ `size`, for compact toolbar placements that don't fit the default trigger height)
596
762
  - `autoCommitSingleOption: boolean = false` (attribute `auto-commit-single-option`) — opts in to the
597
763
  single-option auto-commit behavior described above
598
764
  - `value: string` — a getter/setter; always a single string (no `multiple` mode)
@@ -604,6 +770,15 @@ selection change — a native `<select>` doesn't meaningfully distinguish the tw
604
770
  **Slots:** default (`<lr-option>` children), `label`, `hint`, `error` (overrides the `errorText`
605
771
  attribute when provided)
606
772
 
773
+ **`lr-select` deliberately has no `start`/`end` adornment slots**, unlike
774
+ `lr-input`/`lr-combobox`/`lr-date-input`. Two reasons, both structural rather than incidental:
775
+ its `[part='trigger']` is a native `<button>`, and HTML's content model forbids interactive
776
+ descendants inside one — so the slot could only ever accept decorative content, a materially
777
+ different contract from the other three that would read as the same feature; and the trigger lays
778
+ out with `justify-content: space-between`, so injecting a leading element pushes the selected label
779
+ into the middle of the control instead of leaving it at the start. **Instead:** put a glyph in the
780
+ `label` slot, or compose the select into `<lr-control-group>` alongside the adornment.
781
+
607
782
  When hint/error content is present, the trigger's `aria-describedby` references stable shadow-local
608
783
  IDs for both messages (error first, then hint), so the visible supporting text is part of the
609
784
  control's accessible description.
@@ -616,10 +791,28 @@ presentational `<div>`, not a `role="group"`; options with an empty `group` get
616
791
 
617
792
  **Themeable custom properties:** `--lr-select-trigger-padding`, `--lr-select-trigger-min-height`,
618
793
  `--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.
794
+ `lr-toast-item`'s `--lr-toast-padding`/`--lr-toast-font-size` use.
795
+
796
+ `--lr-select-trigger-min-height` is live at **every** tier, the default `m` included, where it is
797
+ `2.5rem` byte-identical to `lr-input`'s and `lr-combobox`'s own `m` floor, so the three controls
798
+ agree at that tier. It used to be dead code: the component declared `--lr-select-trigger-height:
799
+ auto` on `:host`, and a *declared* value (`auto` is one) wins over the `var()` fallback arm that
800
+ the floor lives in, so the floor never applied and four extra specificity rules existed only to
801
+ patch it back for four of the tiers. Those rules are gone.
802
+
803
+ `--lr-select-trigger-height` pins an **exact** trigger height — both a floor and a cap — e.g. to
804
+ pixel-match a sibling text field in the same toolbar row. It is **undeclared by default**, which is
805
+ exactly what keeps the per-tier floor alive; see "exact-height hatches" under `lr-input`. Because
806
+ the component never declares it, it can be set inline, from an ancestor, or from an outer-tree
807
+ rule. One consequence worth knowing when testing:
808
+ `getComputedStyle(el).getPropertyValue('--lr-select-trigger-height')` now reads `''` rather than
809
+ `'auto'` — assert the rendered `min-block-size`/`block-size` instead of the property string.
810
+
811
+ `--lr-select-option-active-bg` (default `var(--lr-color-brand-quiet)`) recolors the background of a
812
+ hovered or keyboard-active `[part='option']` row. Not declared on `:host`, so a value set on any
813
+ ancestor is never shadowed — retheme just this row state without hijacking the shared
814
+ `--lr-color-brand-quiet` token every other component's own hover/active state also reads. Same
815
+ knob `lr-combobox`'s own `--lr-combobox-option-active-bg` provides.
623
816
 
624
817
  **Optional peer deps:** none.
625
818
 
@@ -684,6 +877,10 @@ Inline month-grid calendar, not form-associated (used standalone or embedded ins
684
877
  - `disablePast: boolean = false` (attribute `disable-past`)
685
878
  - `disableFuture: boolean = false` (attribute `disable-future`)
686
879
  - `withOutsideDays: boolean = false` (attribute `with-outside-days`)
880
+ - `size: '2xs' | 'xs' | 's' | 'm' | 'l' | 'xl' = 'm'` (reflected) — scales calendar cell density
881
+ proportionally; unlike `lr-input`'s row-height scale (text containers), this scales cell density
882
+ itself (fewer/more days per visual unit). Month title, weekday labels, and nav buttons stay fixed
883
+ across tiers.
687
884
  - `previousLabel: string = 'Previous month'` (attribute `previous-label` — accessible label for the
688
885
  previous-month nav button; override for a non-English `locale`)
689
886
  - `nextLabel: string = 'Next month'` (attribute `next-label` — accessible label for the next-month
@@ -705,7 +902,7 @@ mode only)
705
902
  `day-range-end`, `day-range-inner`, `day-placeholder`
706
903
 
707
904
  **Themeable custom properties:** `--lr-cell-size` (default `2.25rem`, controls day-cell/grid-column
708
- size).
905
+ size; auto-scaled per `size` tier — `2xs`/`xs`/`s`/`l`/`xl`; `m` keeps the `:host` default).
709
906
 
710
907
  **Optional peer deps:** none.
711
908
 
@@ -775,17 +972,42 @@ internal native date input.
775
972
  the internal `<input>`'s own `blur`, bubbling and composed unlike the native event), `focus`
776
973
  (re-dispatched from the internal `<input>`'s own `focus`, for the same reason as `blur`)
777
974
 
778
- **Slots:** `label`, `error` (overrides `errorText`), `hint`
975
+ **Slots:** `label`, `error` (overrides `errorText`), `hint`, plus two adornment slots:
976
+ - `start` — content at the inline-start of the input row, before the text field.
977
+ - `end` — content after the text field and the built-in clear action, and before the calendar
978
+ toggle, so consumer content never sits outboard of the calendar button.
779
979
 
780
- **CSS parts:** `form-control`, `form-control-label`, `input-wrapper`, `input`, `clear-button`,
980
+ **CSS parts:** `form-control`, `form-control-label`, `input-wrapper`, `input`, `start` and `end`
981
+ (the two adornment-slot wrappers, each `hidden` while nothing is slotted into it), `clear-button`,
781
982
  `expand-button`, `expand-icon`, `popup`, `date-picker`, `error`, `hint`
782
983
 
783
984
  **Themeable custom properties:** `--lr-date-input-padding-block` (default `--lr-space-xs`) and
784
985
  `--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.
986
+ `--lr-date-input-font-size` (default `inherit`) — the `input` part's font size;
987
+ `--lr-date-input-control-min-height` (default `--lr-size-2-5rem`) the `input-wrapper`'s block-size
988
+ floor. All four are declared on `:host` and auto-swapped per `size`
989
+ (`2xs`/`xs`/`s`/`l`/`xl`; `m` keeps the `:host` defaults), using the same per-`size` values
990
+ `lr-input` uses. Plus shared tokens.
991
+
992
+ `--lr-date-input-control-height` pins an **exact** `input-wrapper` height (both floors and caps it).
993
+ It is **undeclared by default**, so the row grows to fit its content — see "exact-height hatches"
994
+ under `lr-input`. Pinning it *below* the calendar toggle's 24×24 target is safe: the toggle keeps
995
+ its own `--lr-icon-button-size` floor and simply overflows a short row rather than shrinking, so
996
+ WCAG 2.2 SC 2.5.8 is preserved either way.
997
+
998
+ **Height parity with `lr-input` is density parity, not pixel parity.** The per-`size` padding and
999
+ font-size scale is shared with `lr-input`, so the two look equally dense at a given `size` — but a
1000
+ same-`size` pair does **not** end up the same height, and code that assumes it will be
1001
+ disappointed at the small tiers. `[part='input-wrapper']` carries no intrinsic `min-block-size` of
1002
+ its own, while `[part='expand-button']` pins `min-block-size: var(--lr-icon-button-size)` that is
1003
+ deliberately **not** gated by `size` — the calendar toggle must keep a 24×24 touch target at every
1004
+ tier, and `lr-input`'s own password-toggle floors identically. So the row height is pinned
1005
+ transitively by that button: at `size="s"` an `lr-input` floors at `1.875rem`/30px, while an
1006
+ `lr-date-input` cannot go below roughly 40px plus its padding. Every default value of
1007
+ `--lr-date-input-control-min-height` sits below that transitive height, which means the floor is
1008
+ inert until you raise it past the button — a lower value changes nothing. To line the two controls
1009
+ up exactly, either raise `lr-input`'s floor to meet the date input, or lower
1010
+ `--lr-theme-icon-button-size` on a common ancestor (never below 24px).
789
1011
 
790
1012
  **Optional peer deps:** none.
791
1013
 
@@ -1000,11 +1222,42 @@ loud fill token), `--lr-button-outlined-border` (default `--lr-color-border-stro
1000
1222
  `--lr-button-hover-brightness` (default `1.08`, the `:hover` filter intensity),
1001
1223
  `--lr-button-active-scale` (default `0.9875`, the `:active` press-scale, disabled under
1002
1224
  `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`
1225
+ rotation period; forced to `0.001ms` under `prefers-reduced-motion`),
1226
+ `--lr-button-outlined-fill` (default `transparent`, the `appearance="outlined"` background — also
1227
+ variant-independent; set it to tint an outlined button with, say, a faint surface wash behind the
1228
+ outline, without a `::part(base)` rule. Note that the `:hover` `filter: brightness()` applies to
1229
+ whatever fill is set, so a tinted outlined button visibly brightens on hover where a transparent
1230
+ one did not),
1231
+ and the per-`size`
1004
1232
  `min-block-size` floors `--lr-button-size-2xs` (`1.25rem`), `--lr-button-size-xs` (`1.5rem`),
1005
1233
  `--lr-button-size-s` (`1.75rem`), `--lr-button-size-m` (`2rem`), `--lr-button-size-l` (`2.5rem`),
1006
1234
  `--lr-button-size-xl` (`3rem`) — each read only by its own `size` tier, and all ignored by
1007
- `appearance="link"`.
1235
+ `appearance="link"`. `--lr-button-gap` (default `--lr-space-2xs`, the gap between the icon/label
1236
+ and any slotted content) and `--lr-button-radius` (default `--lr-radius`, the corner radius) are
1237
+ both retunable without a `::part(base)` rule but — unlike the four size knobs below — do not vary
1238
+ by `size` tier; `appearance="link"` ignores `--lr-button-radius` (it renders with zero radius).
1239
+
1240
+ **Retuning one `size` tier's geometry, without a `::part(base)` rule.** Four more properties carry
1241
+ the active tier's geometry, and every `:host([size='…'])` rule does nothing but re-assign them — no
1242
+ per-tier rule ever declares a property on `[part='base']`. Overriding one therefore retunes
1243
+ whatever tier is active (e.g. pinning a `size="s"` button into a compact toolbar row), the same
1244
+ pattern `lr-input`/`lr-select`/`lr-combobox`/`lr-segmented`/`lr-date-input` follow. Their defaults
1245
+ below are the `m` tier's values, because `size` reflects and defaults to `m`, so the `:host`
1246
+ declarations *are* the `m` tier:
1247
+
1248
+ - `--lr-button-padding-block` (default `--lr-space-xs`)
1249
+ - `--lr-button-padding-inline` (default `--lr-space-m`)
1250
+ - `--lr-button-font-size` (default `--lr-font-size-m`)
1251
+ - `--lr-button-min-height` (default `--lr-button-size-m`) — the active tier's `min-block-size`
1252
+ floor, re-assigned per tier to that tier's own `--lr-button-size-*` token, and used as the
1253
+ fallback when `--lr-button-height` is unset.
1254
+ - `--lr-button-height` — an **exact** height (both floor and cap), for pinning the button to a
1255
+ fixed toolbar row. **Undeclared by default**, so the button keeps the active tier's floor and an
1256
+ `auto` height; see "exact-height hatches" under `lr-input`.
1257
+
1258
+ `appearance="link"` ignores all five: it is declared after the `size` rules and resets padding,
1259
+ font, and both height properties with literals, so an inline link can never take a button-shaped
1260
+ box no matter what tier or override is in play.
1008
1261
 
1009
1262
  **Optional peer deps:** none.
1010
1263
 
@@ -1044,14 +1297,35 @@ With neither `accessibleLabel` nor `label` set, the name falls back to the local
1044
1297
  app-wide with `registerLyraLocale()` (see `llms/shared.md`); don't rely on the fallback for a
1045
1298
  button whose purpose isn't generic.
1046
1299
 
1047
- **Methods:** `focus(options?)`, `blur()` — forward to the native button.
1048
-
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.
1051
-
1052
- **CSS parts:** `button`
1053
-
1054
- **Themeable custom properties:** `--lr-icon-button-size` sets both dimensions of the hit target.
1300
+ **Methods:** `focus(options?)`, `blur()` — forward to the native button. `click()` also forwards to
1301
+ the native button, activating it — including this component's own `type="submit"`/`type="reset"`
1302
+ handling, since the click goes through the same `<button>` the pointer/keyboard path does.
1303
+
1304
+ **Slots:** (default) — custom icon content. It is rendered **beside** the `icon` glyph, as a
1305
+ sibling of it, not piped through `<lr-icon>`: the internal `<lr-icon>` mounts only when `icon` is
1306
+ set, so with `icon` left empty your content is the button's only child. That is what lets a
1307
+ complete element an `<svg>`, an `<img>`, an `<lr-flag>` render at its own natural aspect ratio
1308
+ instead of being forced into a 1:1 box. Setting both `icon` and slotted content renders both, side
1309
+ by side; that is a valid composition, not a fallback.
1310
+
1311
+ **Bare SVG geometry fallback:** slotted bare SVG *geometry* (`path`, `circle`, `rect`, `line`,
1312
+ `polygon`, `polyline`, `ellipse`, `g`, `use`) with no `icon` set and no enclosing `<svg>` of its
1313
+ own has no real SVG parent as parsed, and is detected and cloned into an internal
1314
+ `[part="fallback"]` SVG-namespaced element so it still paints — the same fallback `<lr-icon>`'s own
1315
+ custom-content slot uses. This is narrowly scoped to that whitelist: a complete `<svg>`, `<img>`,
1316
+ or custom element (e.g. `<lr-flag>`) is never touched by it and keeps rendering as an untouched
1317
+ sibling at its own natural aspect ratio.
1318
+
1319
+ **CSS parts:** `button`, `fallback` (only present in the DOM while at least one top-level slotted
1320
+ element needs the bare-geometry fallback above)
1321
+
1322
+ **Themeable custom properties:** `--lr-icon-button-size` (default `2.5rem`) is the **minimum**
1323
+ tappable inline and block size of the native button — a floor, not a fixed size. Content larger
1324
+ than it grows the button and keeps its own aspect ratio; a small glyph pads out to it. It is a
1325
+ library-wide token (declared on `:root` by the token layer, and the shared minimum tappable size
1326
+ that several other components size their icon-only controls against), so overriding
1327
+ `--lr-theme-icon-button-size` globally resizes all of them together. Keep the resolved value at or
1328
+ above 24px — see `llms/shared.md`.
1055
1329
 
1056
1330
  ## `lr-input`
1057
1331
 
@@ -1089,7 +1363,14 @@ form-associated via the same `FormAssociated` mixin as `lr-textarea`. Ships the
1089
1363
  - `name`/`disabled`/`required` (from `FormAssociated`)
1090
1364
 
1091
1365
  **Getters/methods:** `input: HTMLInputElement | null` (the internal native `<input>`, for direct DOM
1092
- access), `focus(options?: FocusOptions)`, `blur()`, `select()`.
1366
+ access), `focus(options?: FocusOptions)`, `blur()`, `select()`. Also forwards the full native
1367
+ selection/editing surface, mirroring `lr-textarea`'s identical passthrough: `selectionStart: number
1368
+ | null` and `selectionEnd: number | null` (readable/writable; `null` both before the internal input
1369
+ has rendered and whenever `type` doesn't support selection — only `text`/`search`/`password` do,
1370
+ matching the native `<input>`'s own contract), `setSelectionRange(start, end, direction?)`
1371
+ (no-op before render, otherwise throws the same native `InvalidStateError` a native `<input>` would
1372
+ for an unsupported `type`), and `setRangeText(replacement, start?, end?, selectMode?)` (no-op
1373
+ before render; syncs `value` afterward without emitting a user event).
1093
1374
 
1094
1375
  **Events:** native-style composed `input` and `change`, plus `lr-input` (`detail: { value }`,
1095
1376
  fired on every user-driven edit) and `lr-change` (`detail: { value }`, fired on the native
@@ -1108,6 +1389,34 @@ input and built-in actions).
1108
1389
  `--lr-input-font-size`, `--lr-input-control-min-height` — all four auto-swapped per `size`
1109
1390
  (`2xs`…`xl`), the same pattern
1110
1391
  `lr-select`'s `--lr-select-trigger-padding`/`--lr-select-font-size` use.
1392
+ `--lr-input-control-height` pins an **exact** outer control-row height (both floors and caps it) —
1393
+ for example to pixel-match an `<lr-select>` or `<lr-combobox>` in the same toolbar row. It is
1394
+ undeclared by default, leaving `--lr-input-control-min-height` as a floor only and the row free to
1395
+ grow.
1396
+
1397
+ ### Exact-height hatches — the one rule that applies to all of them
1398
+
1399
+ Several controls expose the same pair: a per-`size` `*-min-height` **floor**, and an exact
1400
+ `*-height` **cap**. The family is `--lr-input-control-height`, `--lr-select-trigger-height`,
1401
+ `--lr-combobox-trigger-height`, `--lr-date-input-control-height`, `--lr-button-height`,
1402
+ `--lr-known-date-field-height`, and `--lr-chip-height`. Every one of them behaves identically:
1403
+
1404
+ - **Each is undeclared by default.** The component reads it only through two `var()` fallbacks —
1405
+ `min-block-size: var(--lr-x-height, var(--lr-x-min-height))` and
1406
+ `block-size: var(--lr-x-height, auto)` — so leaving it unset is what makes the per-tier floor
1407
+ and the content-driven height work at all.
1408
+ - **Setting one to `auto` is not the same as leaving it unset.** `auto` is a perfectly valid
1409
+ *declared* value, and a declared value wins over the `var()` fallback arm — so `auto` silently
1410
+ turns the per-tier `*-min-height` floor into dead code, and nothing anywhere reports it. To
1411
+ return a control to default behavior, **remove** the declaration; never neutralize it with
1412
+ `auto`.
1413
+ - Because the component itself never declares them, each can be set inline on the element, from an
1414
+ ancestor, or from an outer-tree rule (`lr-input { --lr-input-control-height: 44px }`) — no
1415
+ `::part()` rule needed.
1416
+ - **A dead declaration is invisible in source.** There is no way to tell a live `--lr-*`
1417
+ declaration from a shadowed or defeated one without rendering: a test asserting on stylesheet
1418
+ text passes either way. Assert the rendered `min-block-size`/`block-size` via
1419
+ `getComputedStyle` on the real element instead of reading the custom property back.
1111
1420
 
1112
1421
  **Optional peer deps:** none.
1113
1422
 
@@ -1147,8 +1456,9 @@ input), and `lr-clear` (inherited, never fired here).
1147
1456
  alias ever renders.
1148
1457
 
1149
1458
  **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`).
1459
+ `--lr-input-control-min-height`, `--lr-input-control-height`, `--lr-input-padding-block`,
1460
+ `--lr-input-padding-inline` and `--lr-input-font-size` (all but `--lr-input-control-height` swap
1461
+ per `size`; that one stays undeclared until you pin an exact row height).
1152
1462
 
1153
1463
  **Known gotchas:**
1154
1464
  - `clearable`/`clear-button`/`lr-clear` are inert: the clear action only renders for
@@ -1190,8 +1500,9 @@ native input's own constraint validation reports `rangeUnderflow`/`rangeOverflow
1190
1500
  `hint`, `error`, plus the inherited, never-rendered `clear-button` and `password-toggle`.
1191
1501
 
1192
1502
  **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`).
1503
+ `--lr-input-control-min-height`, `--lr-input-control-height`, `--lr-input-padding-block`,
1504
+ `--lr-input-padding-inline` and `--lr-input-font-size` (all but `--lr-input-control-height` swap
1505
+ per `size`; that one stays undeclared until you pin an exact row height).
1195
1506
 
1196
1507
  **Known gotchas:** the same two as `lr-number-input` — the inert clear/password surface, and `type`
1197
1508
  only being re-forced on connect. The native `type="time"` UI (spinners, AM/PM, picker) is the
@@ -1208,6 +1519,12 @@ synchronous `PhoneNumberAdapter`, or lazily create one from a `libphonenumber-js
1208
1519
  with `loadLibphonenumberAdapter()`. Without an adapter, already-international E.164 input still
1209
1520
  normalizes and validates; national input remains editable with `incomplete` validity.
1210
1521
 
1522
+ The country selector keeps the real native `<select>` (localized full country names in its popup,
1523
+ native mobile pickers, keyboard type-ahead) but stretches it invisibly over a compact decorative
1524
+ trigger showing the selected alpha-2 code plus a design-system chevron — long country names never
1525
+ clip the closed control and the adjacent calling code isn't repeated. With `flags`, the trigger
1526
+ also shows the selected country's `<lr-flag>`.
1527
+
1211
1528
  **Types:**
1212
1529
 
1213
1530
  ```ts
@@ -1245,6 +1562,18 @@ interface PhoneNumberAdapter {
1245
1562
  precedence over `adapter.countries`.
1246
1563
  - `defaultCountry: string = ''` (attribute `default-country`) — selected when `country` has not been
1247
1564
  set explicitly.
1565
+ - `flags: boolean = false` (reflected) — show the selected country's flag in the country trigger as
1566
+ `<lr-flag variant="compact" aria-label="">` (decorative; the native select already announces the
1567
+ country name). The `<lr-flag>` element definition is registered lazily the first time any
1568
+ `lr-phone-input` enables this, so nothing flag-related is bundled while it stays off. Flag
1569
+ *artwork* still follows the standalone `<lr-flag>` contract: install the optional
1570
+ `@aceshooting/lyra-flags` peer and import
1571
+ `@aceshooting/lyra-ui/components/media/flag/flag-peer.js` once; without that registration the
1572
+ trigger simply omits the image. The open popup list stays text-only — a native `<option>` cannot
1573
+ contain elements.
1574
+ - `size: '2xs' | 'xs' | 's' | 'm' | 'l' | 'xl' = 'm'` (reflected — same scale as `lr-input`'s
1575
+ `size`; scales input padding, font size, and wrapper min-height; `size="s"` shares its outer
1576
+ control height with `lr-input`, `lr-select`, and `lr-combobox` without part overrides)
1248
1577
  - `country: string` — current uppercase ISO alpha-2 selection; falls back to `defaultCountry`, then
1249
1578
  the first explicit/adapter country. Changing the country reparses the editable number.
1250
1579
  - `label: string = ''`, `hint: string = ''`, `errorText: string = ''` (attribute `error-text`) —
@@ -1305,12 +1634,19 @@ Programmatic property assignments and form reset/state restoration are silent.
1305
1634
  **Slots:** `label`, `hint`, `error`, `country-prefix` (optional visual before the country selector,
1306
1635
  such as a consumer-owned `<lr-flag>`; no flag package is imported automatically).
1307
1636
 
1308
- **CSS parts:** `form-control`, `form-control-label`, `input-wrapper`, `country-prefix`,
1309
- `country-select`, `calling-code`, `input`, `hint`, `error`.
1637
+ **CSS parts:** `form-control`, `form-control-label`, `input-wrapper`, `country-prefix`, `country`
1638
+ (the selector region: invisible native select layered over the visual trigger), `country-select`,
1639
+ `country-trigger` (visible, `aria-hidden` closed-state box), `flag` (the `<lr-flag>`, only with
1640
+ `flags`), `country-code` (selected alpha-2 code, `data-placeholder` when no country exists),
1641
+ `expand-icon`, `calling-code`, `input`, `hint`, `error`.
1310
1642
 
1311
- **Themeable custom properties:** shared tokens only. The phone-number input and calling code are
1312
- deliberately `dir="ltr"`/isolated because telephone numbers are algorithmic content; surrounding
1313
- form chrome and the country selector inherit LTR/RTL and use logical spacing/borders.
1643
+ **Themeable custom properties:** `--lr-phone-input-padding-block`, `--lr-phone-input-font-size`,
1644
+ and `--lr-phone-input-control-min-height` (each scaled by `size`), plus `--lr-phone-input-control-height`
1645
+ to pin an exact input-wrapper height (both floors and caps it — use it for pixel-matching an
1646
+ `<lr-input>` or `<lr-select>` in the same toolbar row; undeclared by default, leaving the min height
1647
+ as a floor only). The phone-number input and calling code are deliberately `dir="ltr"`/isolated
1648
+ because telephone numbers are algorithmic content; surrounding form chrome and the country selector
1649
+ inherit LTR/RTL and use logical spacing/borders.
1314
1650
 
1315
1651
  **Optional peer deps:** `libphonenumber-js` is declared optional but never imported by Lyra itself.
1316
1652
  For full national parsing/formatting, install it in the consuming app and pass it through the
@@ -1336,6 +1672,15 @@ phone.adapter = await loadLibphonenumberAdapter(() => import('libphonenumber-js/
1336
1672
  ></lr-phone-input>
1337
1673
  ```
1338
1674
 
1675
+ ```ts
1676
+ // Country flags in the trigger (optional): same peer contract as a standalone <lr-flag>.
1677
+ import '@aceshooting/lyra-ui/components/media/flag/flag-peer.js';
1678
+ ```
1679
+
1680
+ ```html
1681
+ <lr-phone-input label="Mobile number" flags default-country="LU"></lr-phone-input>
1682
+ ```
1683
+
1339
1684
  **Known gotchas:**
1340
1685
 
1341
1686
  - An adapter's `parse()` method is synchronous because it runs on every keystroke. Load any optional
@@ -1345,8 +1690,15 @@ phone.adapter = await loadLibphonenumberAdapter(() => import('libphonenumber-js/
1345
1690
  as invalid instead of entering form submission.
1346
1691
  - Country names use `Intl.DisplayNames` and fall back to the ISO code; set `PhoneCountry.label` for
1347
1692
  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.
1693
+ - The component never imports `@aceshooting/lyra-flags` itself, with `flags` or without. `flags`
1694
+ lazily registers only the `<lr-flag>` element; the artwork resolver comes from the consumer's own
1695
+ `flag-peer.js` import (plus the installed peer package), so forgetting either shows a flagless
1696
+ trigger rather than erroring. `country-prefix` remains available for a fully consumer-owned
1697
+ adornment instead.
1698
+ - The visible trigger (`country-trigger` and everything inside it) is `aria-hidden` by design; the
1699
+ layered native select is the accessible control. Don't move interactive content into those parts
1700
+ via `::part` styling tricks, and don't expect the flag inside the open popup list — a native
1701
+ `<option>` is text-only.
1350
1702
 
1351
1703
  ---
1352
1704
 
@@ -1364,6 +1716,10 @@ consumer-facing `disabled` property/attribute itself.
1364
1716
  - `start: number = 0`
1365
1717
  - `end: number = 100`
1366
1718
  - `step: number = 1`
1719
+ - `size: '2xs' | 'xs' | 's' | 'm' | 'l' | 'xl' = 'm'` (reflected) — visual size; proportionally
1720
+ scales the handle, track, and preset buttons via a single `--lr-time-range-size-scale` multiplier
1721
+ (not pixel-matched to `lr-input`'s row-height scale — this component's own dimensions aren't on
1722
+ that ladder); the drag hit-area never shrinks below 24px (WCAG 2.5.8)
1367
1723
  - `disabled: boolean = false` (reflected)
1368
1724
  - `startLabel: string = 'Range start'` (attribute `start-label`) — `aria-label` for the start handle
1369
1725
  - `endLabel: string = 'Range end'` (attribute `end-label`) — `aria-label` for the end handle
@@ -1381,11 +1737,31 @@ key-up-commit, or when a preset button is clicked, `detail: { start, end }`)
1381
1737
 
1382
1738
  **CSS parts:** `base`, `track`, `range`, `handle-start`, `handle-end`, `presets`, `preset-button`
1383
1739
 
1384
- **Themeable custom properties:** shared tokens only — `--lr-color-border`, `--lr-color-brand`,
1740
+ **Themeable custom properties:** mostly shared tokens — `--lr-color-border`, `--lr-color-brand`,
1385
1741
  `--lr-color-surface`, `--lr-shadow` (track/handles), `--lr-opacity-disabled` (`:host([disabled])`
1386
1742
  dimming), plus (for `presets`) `--lr-color-text`, `--lr-color-on-brand` (the active preset
1387
1743
  button's text), `--lr-radius`, `--lr-space-xs/-s`, `--lr-transition-fast`,
1388
- `--lr-focus-ring-*`. No component-local tokens.
1744
+ `--lr-focus-ring-*`.
1745
+
1746
+ Three component-local properties recolor the **active** preset button independently of the shared
1747
+ palette: `--lr-time-range-preset-active-bg` (falls back to `--lr-color-brand`),
1748
+ `--lr-time-range-preset-active-border-color` (falls back to `--lr-color-brand`), and
1749
+ `--lr-time-range-preset-active-color` (falls back to `--lr-color-on-brand`). Unset, each resolves
1750
+ to exactly the token the rule used before they existed, so the default rendering is unchanged.
1751
+
1752
+ One additional component-local property, `--lr-time-range-size-scale` (unitless multiplier,
1753
+ default 1, automatically set based on the `size` property), scales the handle, track, and preset
1754
+ button dimensions proportionally — unset, it defaults to 1 (size='m', no scaling).
1755
+
1756
+ They exist because the active preset is marked with an attribute on a part, and
1757
+ `::part(preset-button)[data-active]` is **invalid CSS** — an attribute selector cannot follow
1758
+ `::part()`. Without these, recoloring just the active preset meant hijacking the shared
1759
+ `--lr-color-brand`/`--lr-color-on-brand` tokens and repainting everything else that reads them.
1760
+
1761
+ They are written as **inline `var()` fallbacks at the point of use, never declared on `:host`** —
1762
+ deliberately, because a `:host` declaration would shadow any value an ancestor set. Setting one on
1763
+ any ancestor of the `<lr-time-range>` therefore reaches it. (The same technique is used for
1764
+ `lr-emoji-picker`'s `--lr-emoji-picker-active-bg`.)
1389
1765
 
1390
1766
  **Optional peer deps:** none.
1391
1767
 
@@ -1448,6 +1824,9 @@ named colors, the shape apps otherwise hand-roll as a row of round accent-color
1448
1824
  `<lr-segmented>`'s `SegmentedItem.icon`.
1449
1825
  - `value: string | null = null` — the currently selected option's `value` (controlled); `null`
1450
1826
  leaves nothing selected while keeping the first swatch tabbable.
1827
+ - `size: '2xs' | 'xs' | 's' | 'm' | 'l' | 'xl' = 'm'` (reflected — scales the swatch hit-area and
1828
+ fill diameter proportionally, hit-area floored at 24px; not pixel-matched to `lr-input`'s
1829
+ row-height scale)
1451
1830
  - `label: string = ''` — accessible name copied to the internal `role="radiogroup"`; when empty, a
1452
1831
  host-level `aria-label` is used as a fallback.
1453
1832
 
@@ -1457,11 +1836,13 @@ changes via click or keyboard (re-selecting the current swatch is a no-op).
1457
1836
  **Slots:** none.
1458
1837
 
1459
1838
  **CSS parts:** `base` (the `role="radiogroup"` root), `swatch` (a single `role="radio"` color
1460
- swatch's interactive hit target, floored at the shared `--lr-icon-button-size` tap size; the
1461
- selected one is `[part='swatch'][aria-checked='true']`), `swatch-fill` (the compact
1462
- `--lr-size-1-5rem` filled circle inside it, rendered when the option has no `icon`), `swatch-icon`
1463
- (the option's `icon` shape, rendered in its place when it has one). Exactly one of
1464
- `swatch-fill`/`swatch-icon` is mounted per swatch, so the two never coexist.
1839
+ swatch's interactive hit target, sized via `--lr-swatch-picker-hit-size` defaults to
1840
+ `--lr-size-2-5rem`, swapped per `size` tier and floored at 24px; the selected one is
1841
+ `[part='swatch'][aria-checked='true']`), `swatch-fill` (the filled circle inside it, sized via
1842
+ `--lr-swatch-picker-fill-size` defaults to `--lr-size-1-5rem`, also swapped per `size` tier
1843
+ rendered when the option has no `icon`), `swatch-icon` (the option's `icon` shape, rendered in its
1844
+ place when it has one). Exactly one of `swatch-fill`/`swatch-icon` is mounted per swatch, so the
1845
+ two never coexist.
1465
1846
 
1466
1847
  **Themeable custom properties:** `--lr-swatch-picker-selected-color` (ring color around the
1467
1848
  selected swatch, defaults to `--lr-color-brand`, themeable independently of the focus ring),
@@ -1472,10 +1853,11 @@ shape), `--lr-swatch-picker-shine-duration` (default `0s`, a no-op; set a durati
1472
1853
  for a looping brighten-and-settle pulse on the selected swatch. It drives a separate
1473
1854
  `filter: brightness()` keyframe rather than `box-shadow`, so it composes with the blur token and
1474
1855
  works identically for a fill and an icon; disabled outright under `prefers-reduced-motion: reduce`,
1475
- which also drops the hover/selection scale transition); plus
1476
- shared tokens `--lr-color-border`/`-brand`, `--lr-icon-button-size`, `--lr-space-xs`,
1477
- `--lr-size-1-5rem`, `--lr-border-width-thin`/`-thick`, `--lr-radius`, `--lr-transition-fast`,
1478
- `--lr-focus-ring-*`.
1856
+ which also drops the hover/selection scale transition), `--lr-swatch-picker-hit-size` (hit-area
1857
+ size, swapped per `size` tier), `--lr-swatch-picker-fill-size` (visible fill/icon diameter, swapped
1858
+ per `size` tier); plus shared tokens — `--lr-color-border`/`-brand`, `--lr-space-xs`,
1859
+ `--lr-border-width-thin`/`-thick`, `--lr-radius`, `--lr-transition-fast`, `--lr-focus-ring-*`,
1860
+ and the per-tier `--lr-size-*` tokens.
1479
1861
 
1480
1862
  **Optional peer deps:** none.
1481
1863
 
@@ -1541,10 +1923,37 @@ host so the control still has an accessible name.
1541
1923
  showing the checkmark/indeterminate dash), `checkmark` (the checkmark or indeterminate-dash glyph),
1542
1924
  `label` (wrapper around the default slot)
1543
1925
 
1544
- **Themeable custom properties:** shared tokens only `--lr-space-s`, `--lr-icon-button-size`,
1926
+ **Themeable custom properties:** `--lr-checkbox-label-indent` (below), plus shared tokens —
1927
+ `--lr-space-s`, `--lr-icon-button-size`,
1545
1928
  `--lr-color-border/-surface/-on-brand/-brand/-text/-danger`, `--lr-radius`,
1546
1929
  `--lr-transition-fast`, `--lr-focus-ring-width/-color/-offset`, `--lr-opacity-disabled`.
1547
1930
 
1931
+ **`--lr-checkbox-label-indent`** — the inline distance from the control's start edge to the start of
1932
+ the label text: the box's own floor plus the gap beside it. It defaults to
1933
+ `calc(min(var(--lr-icon-button-size), 1.75rem) + var(--lr-space-s))`, and the rendered gap is
1934
+ *derived* from it, so the advertised value and the real label offset cannot drift. Setting it on
1935
+ the element (or on `lr-checkbox` in your own stylesheet) moves the label.
1936
+
1937
+ It is published so you can align your own per-option hint text under the label without re-deriving
1938
+ that formula by reading the shadow styles. **But custom properties inherit down, not sideways**, so
1939
+ a *sibling* node in your tree cannot read it off the checkbox. Align a sibling by computing the
1940
+ same formula from the `--lr-theme-*` inputs you control:
1941
+
1942
+ ```css
1943
+ .checkbox-hint {
1944
+ padding-inline-start: calc(
1945
+ min(var(--lr-theme-icon-button-size, 2.5rem), 1.75rem) + var(--lr-theme-space-s, 0.5rem)
1946
+ );
1947
+ }
1948
+ ```
1949
+
1950
+ `--lr-checkbox-checked-bg` (default `var(--lr-color-brand)`) and `--lr-checkbox-checked-border`
1951
+ (default `var(--lr-color-brand)`) recolor `[part='box']`'s background/border while `checked` or
1952
+ `indeterminate` — a component-scoped indirection (the same pattern `lr-source-picker`'s own
1953
+ `--lr-source-picker-checked-bg`/`-border` pair uses) so a consumer can retint just this control's
1954
+ checked/indeterminate fill without hijacking the shared `--lr-color-brand` token everything else
1955
+ reads.
1956
+
1548
1957
  **Optional peer deps:** none.
1549
1958
 
1550
1959
  ```html
@@ -1736,8 +2145,8 @@ A form-associated single-choice control. Use it alone or inside `lr-radio-group`
1736
2145
 
1737
2146
  **Properties:** `checked`, `disabled`, `required`, `name`, and `value` (all reflected where
1738
2147
  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.
2148
+ `effectiveRequired` exposes the required state inherited from a containing radio group. `focus()`,
2149
+ `blur()`, and `click()` forward to the internal radio control.
1741
2150
 
1742
2151
  **Events:** native-style composed `input` and `change`, plus `lr-change` with
1743
2152
  `{ checked, value }`.
@@ -1746,6 +2155,14 @@ and `blur()` forward to the internal radio control.
1746
2155
 
1747
2156
  **CSS parts:** `base`, `circle`, `dot`, `label`.
1748
2157
 
2158
+ **Themeable custom properties:** `--lr-radio-label-indent` — the inline distance from the control's
2159
+ start edge to the start of the label text, i.e. the circle's own floor plus the gap beside it,
2160
+ defaulting to `calc(min(var(--lr-icon-button-size), 1.75rem) + var(--lr-space-s))`. The rendered
2161
+ gap is derived from it, so the advertised value and the real offset cannot drift; setting it on the
2162
+ element (or on `lr-radio` in your own stylesheet) moves the label. Exactly the same knob, defaults,
2163
+ purpose, and sideways-inheritance caveat as `--lr-checkbox-label-indent` — see `lr-checkbox` above
2164
+ for the formula to align a sibling hint element.
2165
+
1749
2166
  ```html
1750
2167
  <lr-radio name="format" value="json">JSON</lr-radio>
1751
2168
  ```
@@ -1774,6 +2191,23 @@ selected value is submitted under `name` and `required` requires at least one se
1774
2191
  **Events:** `input`, `change`, and `lr-change` with `{ value: string[] }`.
1775
2192
  **CSS parts:** `form-control`, `form-control-label`, `options`, `hint`, `error`.
1776
2193
 
2194
+ **`value` is a read-out of child state, not an input.** The children are the single source of
2195
+ truth. An internal sync recomputes `value` from them and reassigns it on every child toggle,
2196
+ `slotchange`, `name`/`required` change, blur, and `form.reset()` — so a host assignment is
2197
+ silently overwritten by the next of those. `connectedCallback()` runs that sync **before the first
2198
+ render**, which means even a constructor-time or template-time `.value=${…}` binding is discarded
2199
+ before anything can observe it. Assigning `value` logs a `console.warn` naming the property (once
2200
+ per group instance).
2201
+
2202
+ - **To preselect**, set `checked` on the children: `<lr-checkbox value="a" checked>`.
2203
+ - **To read the selection**, use this property or the `lr-change` event detail.
2204
+ - **Give every child a distinct `value`.** `<lr-checkbox>`'s `value` defaults to `'on'`, so a group
2205
+ of undifferentiated children submits several identical `FormData` entries and the submitted data
2206
+ cannot say which one was checked. The group warns once per duplicated value when it sees this.
2207
+ - Making `value` authoritative is deliberately not implemented, for the same reason: a host
2208
+ assigning `['on']` would check every child that kept the default. A distinct `defaultValue` API
2209
+ could be added later without reversing any of the above.
2210
+
1777
2211
  ## `lr-token-input`
1778
2212
 
1779
2213
  An editable form-associated token list. Enter, comma, or blur commits a token; Backspace removes
@@ -1781,18 +2215,53 @@ the last token. `value` is a `string[]` and repeated values are submitted under
1781
2215
 
1782
2216
  **Properties:** `value`, `label`, `hint`, `errorText` (`error-text`), `placeholder`, `name`,
1783
2217
  `required`, `disabled`, `accessibleLabel` (attribute `aria-label` — forwarded to the internal text
1784
- input), `allowDuplicates` (`allow-duplicates`, default `false`), and `delimiter` (default `','`).
2218
+ input), `size: '2xs' | 'xs' | 's' | 'm' | 'l' | 'xl' = 'm'` (reflected — same scale as `lr-input`'s
2219
+ `size`, scaling the input-wrapper's row height and text size across six tiers; the remove button's
2220
+ hit area stays fixed at `40px` across all sizes), `allowDuplicates` (`allow-duplicates`, default
2221
+ `false`), `editable` (reflected, default `false` — see below), and `delimiter: string | null` (default
2222
+ `','` — see below).
1785
2223
  **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
2224
+ **Events:** `input`, `change`, `lr-add` (`detail: { value }`), `lr-remove`
2225
+ (`detail: { value, index }`), and `lr-token-edit`
2226
+ (`detail: { value, previousValue, index }` — an existing token was edited in place and committed).
2227
+ **CSS parts:** `form-control`, `form-control-label`, `input-wrapper`, `token`, `token-label` (the
2228
+ token's text, doubling as the roving-focus edit trigger — rendered only while `editable`),
2229
+ `token-editor` (the inline text field that replaces a token's text while it is open for editing —
2230
+ rendered only while `editable` and only for the token being edited), `remove` (the
1789
2231
  per-token remove button, floored at the shared `--lr-icon-button-size` tap size around a compact
1790
2232
  glyph), `input`, `hint`, `error`. `focus()` and `blur()` forward to the internal text input.
1791
2233
 
1792
- **Themeable custom properties:** `--lr-token-input-input-inline-size` (the editable input's
1793
- `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).
2234
+ **`editable` editing a token in place.** Off by default, in which case the token row renders
2235
+ exactly as it does without the feature and stays non-focusable. Turn it on and each token becomes a
2236
+ roving tab stop (one Tab stop for the whole row): click, Enter, Space, or F2 opens an inline
2237
+ editor on that token; ArrowLeft/ArrowRight move between tokens (swapped under RTL, since they mean
2238
+ previous/next *visually*), Home/End jump to the first/last. Inside the editor, Enter commits and
2239
+ returns focus to the token, Escape cancels (and is consumed rather than left to bubble, so an
2240
+ enclosing dialog or popover does not also close), and blurring commits *without* pulling focus
2241
+ back — a blur means the user already aimed focus elsewhere. `lr-token-edit` fires only for an edit
2242
+ that actually changed something: a reverted, unchanged, emptied, or (under the default
2243
+ `allowDuplicates = false`) duplicate-colliding edit is discarded silently, mirroring how a
2244
+ duplicate draft is skipped rather than rejecting the whole entry.
2245
+
2246
+ **`delimiter` is nullable, and only a single character acts as a commit key.** It does two separate
2247
+ jobs: it splits a committed draft into several tokens, and — *only when it is exactly one
2248
+ character* — it is the keystroke that commits the draft. A multi-character delimiter still splits a
2249
+ pasted or committed draft, but no keystroke can ever match it, so nothing commits on typing.
2250
+ Setting it to `null` disables both, so a token may contain the delimiter verbatim. **`delimiter="null"`
2251
+ does not work** — that is the four-character string `null`. Use `delimiter="none"`, `delimiter=""`
2252
+ (both of which the attribute converter maps to `null`), or a property binding
2253
+ (`.delimiter=${null}`). Removing the attribute restores the `,` default.
2254
+
2255
+ **Themeable custom properties:** `--lr-token-input-padding` (the input-wrapper padding, scaled by
2256
+ `size`), `--lr-token-input-font-size` (the input-wrapper and token font size, scaled by `size`),
2257
+ `--lr-token-input-control-min-height` (the input-wrapper's block-size floor, scaled by `size`),
2258
+ `--lr-token-input-control-height` (exact input-wrapper height — undeclared by default, leaving the
2259
+ `--lr-token-input-control-min-height` floor only; set it to a length to both floor and cap the row,
2260
+ e.g. to pixel-match a sibling field in the same toolbar row), `--lr-token-input-input-inline-size`
2261
+ (the editable input's `flex-basis` inside the wrapped token row; undeclared by default, falling back
2262
+ inline to `--lr-size-8rem`), `--lr-token-input-min-input-inline-size` (default `--lr-size-4rem`, the
2263
+ floor that input keeps once tokens have consumed the row), and `--lr-token-input-editor-inline-size`
2264
+ (default `--lr-size-6rem`, the inline size of the inline token editor opened by `editable`).
1796
2265
 
1797
2266
  ## `lr-code-editor`
1798
2267
 
@@ -1859,12 +2328,18 @@ spaces — the Tab key keeps inserting `tabSize` spaces in that case.
1859
2328
 
1860
2329
  A form-associated native color picker with label, hint, and error chrome. **Properties:** the shared
1861
2330
  form properties `name`, `value`, `disabled`, and `required`, plus `label`, `hint`, `errorText`
1862
- (`error-text`), and `accessibleLabel` (`aria-label`). **Slots:** `label`, `hint`, `error`. **Events:**
2331
+ (`error-text`), `accessibleLabel` (`aria-label`), and `size: '2xs' | 'xs' | 's' | 'm' | 'l' | 'xl' = 'm'`
2332
+ (reflected — same scale as `lr-input`'s `size`, for compact swatch rendering at every density tier).
2333
+ **Slots:** `label`, `hint`, `error`. **Events:**
1863
2334
  composed `input` and `change`, `lr-change` with `{ value }`, and `focus`/`blur` (re-dispatched from
1864
2335
  the internal `<input>`'s own `focus`/`blur`, bubbling and composed unlike the native events). **CSS
1865
2336
  parts:** `form-control`, `form-control-label` (the label; `label` is an alias kept for back-compat),
1866
2337
  `input`, `hint`, `error`.
1867
2338
 
2339
+ **Themeable custom properties:** `--lr-color-picker-swatch-size` — the swatch's inline and block size,
2340
+ auto-swapped per `size` tier (default `'m'` reads `2.5rem`, `'2xs'` reads `1.25rem`, etc.), matching
2341
+ the size ladder `lr-input` uses.
2342
+
1868
2343
  ## `lr-emoji-picker`
1869
2344
 
1870
2345
  A searchable, keyboard-navigable, form-associated emoji picker. `groups` is fully consumer-suppliable
@@ -1875,13 +2350,24 @@ supplied (an explicit empty array still counts as supplied and skips the auto-lo
1875
2350
  When the filtered set reaches 200 items, the grid automatically windows its visible rows while
1876
2351
  preserving the full option count through `aria-setsize`/`aria-posinset`.
1877
2352
 
2353
+ Ships the same opt-in `label`/`hint`/`errorText` form-control chrome as `lr-select`/
2354
+ `lr-color-picker` (props + matching named slots + `form-control`/`form-control-label`/`hint`/
2355
+ `error` CSS parts) — left unset, none of that chrome renders.
2356
+
1878
2357
  **Properties:** the shared form properties `name`, `value`, `disabled`, and `required`, plus
1879
2358
  `groups: EmojiPickerGroup[] = []` (attribute: false) — `EmojiPickerGroup { key, label, emojis:
1880
2359
  EmojiPickerItem[] }`, `EmojiPickerItem { emoji, name, shortcodes? }`; the search field matches `name`
1881
2360
  and every `shortcodes` entry, case-insensitively. Empty (the default, before the auto-loader
1882
2361
  resolves) renders just the search input and the empty state. `accessibleLabel` (`aria-label`)
1883
2362
  forwards a host-supplied accessible name to the internal `role="listbox"` grid; empty falls back to
1884
- the localized default grid label.
2363
+ the localized default grid label. `label: string = ''` — visible label rendered above the
2364
+ search/grid; unset renders no label chrome. When `label` (or the `label` slot) is set and
2365
+ `accessibleLabel`/a host `aria-label` is not, the grid's accessible name switches from the
2366
+ localized default to `aria-labelledby` pointing at the visible label. `hint: string = ''` —
2367
+ supporting text rendered below the search/grid; unset renders no hint chrome. `errorText: string =
2368
+ ''` (attribute `error-text`) — validation-error text rendered below the hint (overridden by slotted
2369
+ `error` content when provided); unset renders no error chrome. `size: '2xs' | 'xs' | 's' | 'm' | 'l' | 'xl' = 'm'` —
2370
+ visual size; scales the emoji grid item box and its glyph proportionally, floored at 24px (WCAG 2.5.8).
1885
2371
 
1886
2372
  **Events:** `lr-change` with `detail: { emoji }` (an emoji was picked — click, or Enter/Space on
1887
2373
  the active grid cell; also sets `value`), plus the shared form `input`, `change`, `focus`, and `blur`.
@@ -1894,18 +2380,26 @@ Home/End jump to the first/last item, and Enter/Space picks the active item. The
1894
2380
  the input, with `aria-activedescendant` tracking the active option. Hovering an emoji with the
1895
2381
  pointer also moves the active item to it.
1896
2382
 
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`
2383
+ **Slots:** `label` (custom label content), `hint` (custom hint content), `error` (custom error
2384
+ content, overrides the `errorText` attribute when provided).
2385
+
2386
+ **CSS parts:** `form-control` (the outer wrapper around label, `base`, error and hint),
2387
+ `form-control-label` (the visible label), `base`, `search` (`role="combobox"`), `grid`
2388
+ (`role="listbox"`, the scroll viewport), `group-label`, `emoji` (each emoji's own `role="option"`
2389
+ button), `empty` (shown when the search matches nothing), `hint` (the hint message), `error` (the
2390
+ error message). While windowing is active the rows are wrapped in `virtual-spacer`
1900
2391
  (full-height scroll spacer), `virtual-row` (one absolutely-positioned row), `virtual-label` (an
1901
2392
  `aria-hidden` spacer standing in for a row's missing `group-label`), and `virtual-items` (the row's
1902
2393
  emoji flex line).
1903
2394
 
1904
2395
  **Themeable custom properties:** `--lr-emoji-picker-item-size` (default `--lr-icon-button-size`,
1905
- each emoji button's box), `--lr-emoji-picker-gap` (default `--lr-space-2xs`, the gap between
2396
+ each emoji button's box; scaled by the `size` property), `--lr-emoji-picker-glyph-size` (default
2397
+ `--lr-font-size-lg`, the font size of the emoji glyph; scaled by the `size` property to keep the glyph
2398
+ proportional to the item box), `--lr-emoji-picker-gap` (default `--lr-space-2xs`, the gap between
1906
2399
  emoji within a windowed row), and `--lr-emoji-picker-row-height` (default
1907
- `calc(var(--lr-emoji-picker-item-size) + var(--lr-space-l))`, one windowed row's height). All three
1908
- are also read back in JS to derive columns-per-row and row offsets for the windowed layout,
2400
+ `calc(var(--lr-emoji-picker-item-size) + var(--lr-space-l))`, one windowed row's height).
2401
+ `--lr-emoji-picker-item-size`, `--lr-emoji-picker-gap`, and `--lr-emoji-picker-row-height` are also
2402
+ read back in JS to derive columns-per-row and row offsets for the windowed layout,
1909
2403
  resolved to real pixels by measuring hidden probe boxes the component's own stylesheet sizes from
1910
2404
  those same tokens — so any CSS length unit works, `rem`/`em` and `calc()` included, and the windowed
1911
2405
  geometry matches what is painted without expressing the tokens in `px`. The measurement is cached
@@ -1913,8 +2407,18 @@ and re-derived only when the resolved pixels can actually change (a token overri
1913
2407
  first render, a theme swap, a root or host font-size change feeding a `rem`/`em` value), never per
1914
2408
  frame.
1915
2409
 
1916
- Two constraints remain. `--lr-emoji-picker-item-size` is clamped up to `--lr-icon-button-size`, the
1917
- shared minimum tappable box: a smaller value does not shrink the button, and the windowed geometry
2410
+ `--lr-emoji-picker-active-bg` recolors the highlight behind the active/hovered emoji, falling back
2411
+ to `--lr-color-brand-quiet` when unset so the default rendering is unchanged. Hover and
2412
+ keyboard-active deliberately share one declaration, so this single hook retints both consistently.
2413
+ It exists because `::part(emoji)[data-active]` is **invalid CSS** (an attribute selector cannot
2414
+ follow `::part()`), which previously left hijacking the shared `--lr-color-brand-quiet` token — and
2415
+ repainting everything else that reads it — as the only way in. Like `lr-time-range`'s preset
2416
+ properties, it is written as an inline `var()` fallback at the point of use rather than declared on
2417
+ `:host`, so a value set on **any ancestor** reaches it instead of being shadowed.
2418
+
2419
+ Two constraints remain. `--lr-emoji-picker-item-size` is held at a flat 24px minimum (WCAG 2.5.8
2420
+ touch target floor): the smaller `size` tier values can shrink the box below the old 40px
2421
+ unconditional floor, but the minimum holds at 24px regardless of tokens, and the windowed geometry
1918
2422
  follows the clamped, painted size. And windowed rows are absolutely positioned at the row-height
1919
2423
  pitch, so `--lr-emoji-picker-row-height` must stay at or above the item size plus the group-label
1920
2424
  band (`--lr-space-l`) — the default's own formula — or consecutive rows overlap. Columns per
@@ -1951,6 +2455,86 @@ message), `footer`, `submit`, `skip` (only rendered when `skippable`), `empty` (
1951
2455
  no entries), and `unsupported` (the fallback note for a key whose `type` is outside the three
1952
2456
  supported ones).
1953
2457
 
2458
+ **Themeable custom properties:** shared tokens only. The footer's disabled `submit`/`skip` buttons
2459
+ dim through `--lr-opacity-disabled`, the same library-wide token every other disabled control
2460
+ reads — so retuning `--lr-theme-opacity-disabled` keeps this form's disabled state consistent with
2461
+ the rest of the UI instead of needing a `::part()` rule here.
2462
+
2463
+ ## `lr-locale-picker`
2464
+
2465
+ A closed-list locale switcher over the library's own locale registry. First-party invention (no
2466
+ Web Awesome equivalent). With `locales` unset (the default), the offered rows are exactly
2467
+ `getRegisteredLyraLocales()` — every locale with strings registered via `registerLyraLocale()`,
2468
+ plus `en` — kept live via `subscribeLyraLocaleRegistry()`. Built directly on `lr-select`'s
2469
+ trigger-button/`aria-activedescendant` listbox technique, not composed from it — a plain closed
2470
+ list, no filter/free-text mode.
2471
+
2472
+ **Properties:**
2473
+ - `locales: LyraLocaleCatalog = []` (attribute: false) — `LyraLocaleCatalog = string[] |
2474
+ LyraLocaleEntry[]`, `LyraLocaleEntry { tag: string; label?: string }`. Empty (the default)
2475
+ auto-discovers the registry; a non-empty array (either form) overrides it entirely — a curated
2476
+ subset, custom order, custom labels, or a locale offered before its strings are registered.
2477
+ - `showFlags: boolean = true` — each row's leading `<lr-flag language={tag} variant="compact">`;
2478
+ `false` omits the flag element entirely (not just visually).
2479
+ - `value: string = ''` — the **committed** selection (form value, drives `lr-change`). While `''`
2480
+ and untouched, the trigger *displays* `effectiveLocale` as a preview label, but
2481
+ `checkValidity()`/`required` are governed by the real `value`, which stays `''` until a real
2482
+ commit — mirrors a native `<select>` showing its first option's text without that being a
2483
+ committed selection.
2484
+ - `required: boolean = false`, `disabled: boolean = false`, `name: string = ''` — standard
2485
+ form-associated properties.
2486
+ - `label: string = ''`, `hint: string = ''`, `errorText: string = ''` (attribute `error-text`) —
2487
+ same opt-in form-control chrome as `lr-select` (props + matching named slots + parts); unset
2488
+ renders none of it.
2489
+ - `open: boolean = false` (reflected).
2490
+ - `size: '2xs' | 'xs' | 's' | 'm' | 'l' | 'xl' = 'm'` (reflected — same scale as `lr-select`'s `size`).
2491
+
2492
+ **Events:** `lr-change` (`detail: { value, previousValue }`, **cancelable**) — fired on every
2493
+ explicit pick; if not `defaultPrevented`, the component applies the pick itself via
2494
+ `setLyraLocale(value)`. A listener calling `event.preventDefault()` leaves `value` updated but the
2495
+ active locale untouched, so a host can persist the choice first and apply it later. `blur`/`focus`
2496
+ re-dispatched from the internal trigger as bubbling, composed events.
2497
+
2498
+ **Methods:** `focus(options?)`, `blur()`, and `click()` — all forward to the internal trigger
2499
+ button, same convention as `lr-select`'s identical trio.
2500
+
2501
+ **Slots:** `label`, `hint`, `error`.
2502
+
2503
+ **CSS parts:** `form-control`, `form-control-label`, `trigger`, `listbox`, `option`,
2504
+ `option-flag` (present only while `showFlags` is on), `option-label`, `option-tag` (the row's
2505
+ secondary line — the raw BCP-47 tag), `expand-icon`, `hint`, `error`.
2506
+
2507
+ **Themeable custom properties:** `--lr-locale-picker-trigger-padding`,
2508
+ `--lr-locale-picker-trigger-min-height`, `--lr-locale-picker-trigger-height` (unset by default, a
2509
+ floor-only escape hatch — set a length to both floor and cap the trigger),
2510
+ `--lr-locale-picker-font-size`, `--lr-locale-picker-expand-size` (all scaled by `size`), and
2511
+ `--lr-locale-picker-option-active-bg` (default `--lr-color-brand-quiet`, the hovered/keyboard-active
2512
+ row background).
2513
+
2514
+ **Optional peer deps:** none directly — each row's `<lr-flag>` degrades to an empty render (no
2515
+ peer warning duplication; `lr-flag` itself already logs one) when the optional
2516
+ `@aceshooting/lyra-flags` package isn't installed and `showFlags` is left on.
2517
+
2518
+ ```html
2519
+ <lr-locale-picker label="Language"></lr-locale-picker>
2520
+ <script type="module">
2521
+ import { registerLyraLocale } from '@aceshooting/lyra-ui';
2522
+ registerLyraLocale('fr', { close: 'Fermer' });
2523
+ document
2524
+ .querySelector('lr-locale-picker')
2525
+ .addEventListener('lr-change', (e) => console.log(e.detail.value));
2526
+ </script>
2527
+ ```
2528
+
2529
+ **Known gotchas:**
2530
+ - selecting a row applies `setLyraLocale()` itself unless the listener calls
2531
+ `event.preventDefault()` on `lr-change` — it does not touch
2532
+ `document.documentElement.lang`/`dir`; apply writing-direction changes to the page yourself.
2533
+ - no filter/free-text mode — for a catalog with hundreds+ of rows, roll your own with `lr-select`
2534
+ or `lr-combobox` instead.
2535
+ - arrow-key navigation is vertical-only (Home/End/ArrowUp/ArrowDown); there is no
2536
+ ArrowLeft/ArrowRight remap under RTL, since there is no horizontal axis to remap.
2537
+
1954
2538
  # Data display, dashboards & flow canvas (`components/data/`)
1955
2539
 
1956
2540
  ## `lr-sparkline`
@@ -2040,6 +2624,19 @@ KPI/stat card — value + unit + label + optional icon/trend/caption.
2040
2624
  hides `[part="unit"]`, for rendering a loading/status message in place of a numeric value
2041
2625
  - `compact: boolean = false` (reflected) — tighter card padding; same convention as `lr-empty`'s and
2042
2626
  `lr-widget`'s `compact`
2627
+ - `appearance: 'card'|'plain' = 'card'` (reflected) — visual chrome, mirroring `lr-card`'s
2628
+ `appearance` vocabulary. `'card'` keeps the bordered, filled, padded box that stretches to fill its
2629
+ parent; `'plain'` removes the border, background, padding, corner radius **and** the
2630
+ `block-size: 100%` stretch, so the stat can sit inline in prose, a toolbar, or a table cell.
2631
+ `plain` wins over `compact` when both are set (there is no padding left to tighten), and it drops
2632
+ `emphasis`'s accent edge — that edge is card chrome — while `emphasis`'s brand value tint still
2633
+ applies. A `plain` stat with a safe `href` swaps the card's border-color/lift hover affordance
2634
+ (invisible with no border) for an underline on `[part="value"]`; the `:focus-visible` ring is
2635
+ unchanged
2636
+ - `orientation: 'vertical'|'horizontal' = 'vertical'` (reflected) — layout axis. `'vertical'` stacks
2637
+ label, value, trend, sub and caption. `'horizontal'` lays label, value+unit, trend, sub and caption
2638
+ out on a single wrapping baseline row; `[part="spark"]` and `[part="rows"]` have no sensible place
2639
+ on a text baseline and stay stacked on their own full-width line beneath that row
2043
2640
 
2044
2641
  **Events:** none.
2045
2642
 
@@ -2049,15 +2646,24 @@ slot="spark">`, or other compact trend visual — `lr-stat` only reserves the sl
2049
2646
  render one itself), `sub` (rich sub-line content — overrides the `sub` attribute when slotted content
2050
2647
  is provided)
2051
2648
 
2052
- **CSS parts:** `base` (a `<div>`, or an `<a>` for a safe `href`), `icon`, `label`, `value-row`, `value`, `unit`, `trend`, `sub`, `spark`,
2649
+ **CSS parts:** `base` (a `<div>`, or an `<a>` for a safe `href`), `icon`, `label` (carries `hidden`,
2650
+ and is collapsed, whenever `label` is empty — a label-less stat leaves no blank line above the
2651
+ value), `value-row`, `value`, `unit`, `trend`, `sub`, `spark`,
2053
2652
  `caption`, `rows`, `row`, `row-label`, `row-value` — `[part="value"]` gets `aria-labelledby` pairing
2054
2653
  it with `[part="label"]`'s generated id whenever `label` is non-empty (so tabbing straight to the
2055
2654
  `exactValue`-focusable value still announces e.g. "Revenue $1.2K", not just the bare value); each
2056
2655
  `[part="row-value"]` is paired the same way with its own row's `[part="row-label"]`.
2057
2656
 
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).
2657
+ **Themeable custom properties:** `--lr-stat-trend-good-color` (default `var(--lr-color-success)`)
2658
+ and `--lr-stat-trend-good-bg` (default `color-mix(in srgb, var(--lr-color-success) 8%,
2659
+ transparent)`) text/background of `[part="trend"]` when its polarity (per `goodDirection`) is
2660
+ "good"; `--lr-stat-trend-bad-color` (default `var(--lr-color-danger)`) and `--lr-stat-trend-bad-bg`
2661
+ (default `color-mix(in srgb, var(--lr-color-danger) 8%, transparent)`) — the "bad"-polarity
2662
+ counterparts. All four are independent of the headline value's `variant="success"`/`"danger"` tint,
2663
+ which keeps reading the shared `--lr-color-success`/`--lr-color-danger` tokens directly — retinting
2664
+ the trend pill doesn't also recolor the value, and vice versa. Otherwise shared tokens only
2665
+ (`--lr-color-success/-warning/-danger` drive the `variant`-colored value text; `--lr-color-brand`
2666
+ drives `emphasis`'s accent edge and value tint).
2061
2667
 
2062
2668
  **Optional peer deps:** none.
2063
2669
 
@@ -2111,13 +2717,42 @@ own "consumer computes/renders" contract rather than assuming addition.
2111
2717
  via the retheme-able `--lr-table-heat-tint-lo`/`-hi` custom properties, matching `lr-heatmap`'s
2112
2718
  own ramp-token convention; `cellStyle` is applied directly to the generated `<td>` via `styleMap` — e.g. a computed heat-tint
2113
2719
  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`
2720
+ no per-cell style override (the default, unchanged output); `editable` enables inline editing —
2721
+ `true` opens a native editor on that cell's double-click (one cell at a time), `'always'` instead
2722
+ renders a persistent editor in every body cell of the column from first paint, for a
2723
+ settings/rate-style column meant to be typed straight into — while `editValue` supplies the editor
2724
+ value and `editType` selects `text` or `number`
2725
+ `cellTitle(row) => string | undefined` is the `title` analogue of `cellStyle`, applied directly to
2726
+ the generated `<td>` — e.g. the untruncated text behind an ellipsized cell, or a formatted
2727
+ timestamp behind a relative one;
2116
2728
  `resizable` adds a focusable separator `[part='resize-handle']` and emits `lr-column-resize` with
2117
2729
  the live width in CSS pixels. Drag it, or use logical ArrowLeft/ArrowRight for 10px steps (mirrored
2118
2730
  under RTL), Shift+Arrow for 50px steps, Home for the minimum, and End for an explicit pixel
2119
2731
  `maxWidth`; explicit pixel `minWidth`/`maxWidth` values bound both input paths. The separator
2120
2732
  exposes its current/minimum/bounded-maximum pixel width through ARIA value attributes.
2733
+ - `columns[].editable: boolean | 'always'` — a widening of the original `boolean`, non-breaking.
2734
+ `true` is unchanged: double-click a cell to open its editor, one at a time, Enter commits and
2735
+ closes, Escape cancels and closes, blur-after-change commits. `'always'` renders an editor in
2736
+ every body cell of that column, permanently:
2737
+ - **Focus model.** Each editor is a plain tab stop — no `tabindex` of its own — exactly like the
2738
+ existing row-expand toggle, and stays *outside* the header/row roving-tabindex model. Tab walks
2739
+ down the column; arrow keys still navigate the grid from a row's own roving stop, and act as
2740
+ ordinary caret movement once focus is inside a field. Non-editable columns are unaffected.
2741
+ - **Value binding.** A persistent editor binds its `value` as a **content attribute**, not as the
2742
+ `.value` property, so native dirty-value-flag semantics apply. Trade-off: once the user has
2743
+ typed into a cell, an out-of-band `rows` update to that same cell will **not** visibly replace
2744
+ their draft. An editor the user has not touched still picks up a new `rows` value normally.
2745
+ `lr-cell-edit` remains the only mutation channel — the table never mutates `row`.
2746
+ - **Keys.** Enter commits (emits `lr-cell-edit`) and *keeps focus* in the field, since there is no
2747
+ closed state to fall back to. `change` (blur after a modification) commits, as with `true`.
2748
+ Escape is **not** cancelled and does nothing to the editor — there is nothing to cancel back to
2749
+ — so an ancestor dialog/popover still acts on it.
2750
+ - **Focus across re-sorts and pagination.** Rows are keyed, so a re-sort *moves* the editor's
2751
+ `<input>` (the typed value rides along) and the table restores focus to the same logical cell
2752
+ afterwards. If the focused row leaves the rendered page entirely (pagination, filtering), focus
2753
+ is simply lost rather than yanked to whichever unrelated row now sits in that position.
2754
+ - Each editor keeps its own interpolated `tableEditCell` accessible name (`Edit {column}`), so a
2755
+ column of otherwise-identical inputs is still individually named to a screen reader.
2121
2756
  - `columnsHidden: boolean = false` (attribute `columns-hidden`, reflected) — computed/read-only: true
2122
2757
  when a `priority` column is *actually* hidden right now by the `@container` breakpoints above, or
2123
2758
  `showAllColumns` force-visible mode is currently active. Measured via a `ResizeObserver` on
@@ -2128,6 +2763,13 @@ own "consumer computes/renders" contract rather than assuming addition.
2128
2763
  renders exactly when `columnsHidden` is true — no longer whenever any column merely *declares* a
2129
2764
  `priority` regardless of whether anything is actually hidden
2130
2765
  - `rows: T[] = []` (attribute: false)
2766
+ - `layout: 'auto'|'fixed' = 'auto'` (reflected) — a **floor** on the `<table>`'s `table-layout`, not
2767
+ an override. `'fixed'` forces the fixed algorithm even when no column declares a `width`, so every
2768
+ column shares the available width evenly and long cell content is clipped/wrapped instead of
2769
+ stretching its column. The default `'auto'` still *resolves* to `fixed` whenever a column declares
2770
+ a `width`, a column has been drag-resized, or a resize gesture is in flight — column resizing does
2771
+ not work under `table-layout: auto`, so `'auto'` can never mean "never fixed". See the gotchas for
2772
+ the two consequences of the fixed algorithm worth knowing before opting in
2131
2773
  - `sortKey: string = ''` (attribute `sort-key`)
2132
2774
  - `sortDir: 'asc'|'desc' = 'asc'` (attribute `sort-dir`)
2133
2775
  - `rowKey?: (row: T) => string | number` (attribute: false) — derives each row's stable identity for
@@ -2153,7 +2795,20 @@ own "consumer computes/renders" contract rather than assuming addition.
2153
2795
  converter would otherwise treat any attribute value, including the literal string `"false"`, as
2154
2796
  `true`).
2155
2797
  - `loading: boolean = false` (attribute `loading`, reflected) and `loadingLabel: string = ''`
2156
- (attribute `loading-label`) — renders a busy spinner and suppresses the grid while loading
2798
+ (attribute `loading-label`) — renders busy chrome and suppresses the real rows while loading
2799
+ - `loadingAppearance: 'spinner'|'skeleton' = 'spinner'` (attribute `loading-appearance`, reflected) —
2800
+ how `loading` renders. `'spinner'` replaces the whole grid with an indeterminate spinner.
2801
+ `'skeleton'` instead renders the real table — the same `<colgroup>` (declared *and* drag-resized
2802
+ widths included), the same `<thead>`, the filter field and the pagination footer — and fills
2803
+ `<tbody>` with placeholder rows, so a cold load sketches the grid's shape rather than collapsing to
2804
+ a spinner and reflowing when the rows land. Kept as a separate property rather than widening
2805
+ `loading` to a string union, so `?loading=${…}` bindings and `el.loading === true` checks keep
2806
+ working
2807
+ - `skeletonRows: number = 0` (attribute `skeleton-rows`) — placeholder row count under
2808
+ `loadingAppearance="skeleton"`. `0` derives the count instead: the normalized `pageSize` when
2809
+ pagination is on (capped at 20, so a large page size can't emit thousands of placeholder cells),
2810
+ otherwise 3. Any positive value is used verbatim and is *not* capped. Ignored entirely under the
2811
+ default spinner appearance
2157
2812
  - `pageSize: number = 0` (attribute `page-size`) — positive values enable controlled pagination;
2158
2813
  zero disables the pagination footer
2159
2814
  - `page: number = 1` (attribute `page`, reflected) — controlled current page
@@ -2177,6 +2832,13 @@ own "consumer computes/renders" contract rather than assuming addition.
2177
2832
  - `emptyDescription: string = ''` (attribute `empty-description`)
2178
2833
  - `noColumnsHeading: string = 'No columns configured'` (attribute `no-columns-heading`)
2179
2834
  - `noColumnsDescription: string = ''` (attribute `no-columns-description`)
2835
+ - `emptyCompact?: boolean` (attribute `empty-compact`) — overrides the built-in `[part='empty']`
2836
+ state's `compact` rendering. Tri-state: leave it `undefined` (the default) to keep each empty
2837
+ branch's own built-in default — the two shadow-root-level branches (no columns, no rows) render
2838
+ spacious, while the filtered-to-zero branch, which sits inside `[part='base']` alongside the filter
2839
+ field, renders compact. `empty-compact="false"` forces the spacious rendering everywhere, and is
2840
+ parsed as `false` rather than as mere attribute presence. Has no effect once the `empty` slot is
2841
+ filled
2180
2842
  - `revealColumnsLabel: string = 'Show all columns'` (attribute `reveal-columns-label` — the
2181
2843
  reveal-button's label while `priority`-hidden columns are hidden)
2182
2844
  - `hideColumnsLabel: string = 'Show fewer columns'` (attribute `hide-columns-label` — the same
@@ -2209,7 +2871,12 @@ columns, and `lr-column-resize` (`detail: { key, width }`) on every pointer or k
2209
2871
  The internal filter/cell-editor native inputs' `focus` and `blur` are also re-dispatched from the
2210
2872
  host as bubbling, composed events (the native ones are neither).
2211
2873
 
2212
- **Slots:** nonecontent comes entirely from `columns`/`rows`.
2874
+ **Slots:** `empty`replaces the built-in empty state on the two *data*-empty branches (no rows at
2875
+ all, and filtered/paginated down to zero). Left unfilled, the built-in `[part='empty']` `<lr-empty>`
2876
+ renders as this slot's fallback content. The no-columns branch is deliberately **not**
2877
+ slot-replaceable: it reports a configuration problem (`noColumnsHeading`), not "this query returned
2878
+ nothing", and one slot covering all three would collapse that distinction. Everything else comes
2879
+ from `columns`/`rows`.
2213
2880
 
2214
2881
  **CSS parts:** `base`, `table`, `head`, `header-cell`, `row`, `cell`, `more-button`, `sort-icon` (a
2215
2882
  chevron indicator shown on the active sortable header, rotated per `sortDir`), `reveal-columns-button`
@@ -2218,9 +2885,20 @@ column defines `footer`), `footer-row`, `footer-cell`, `row-total-cell` (each bo
2218
2885
  `<td>` holding `rowTotal(row)`, rendered only when `rowTotal` is set — the corresponding footer-row
2219
2886
  cell, holding `grandTotal`, is a `footer-cell` instead, matching every other footer cell),
2220
2887
  `expand-toggle-cell`, `row-expand-toggle`,
2221
- `row-expand-icon`, `expanded-row`, `expanded-cell`, `filter-label`, `filter`, `loading`, and
2888
+ `row-expand-icon`, `expanded-row`, `expanded-cell`, `filter-label`, `filter`, `loading` (under
2889
+ `loadingAppearance="spinner"` the visible block holding the spinner; under `"skeleton"` the
2890
+ visually-hidden `role="status"` node, since the placeholder rows are the visible affordance),
2891
+ `skeleton` (each `<lr-skeleton>` placeholder inside a skeleton-mode body cell — the placeholder rows
2892
+ and cells reuse the ordinary `row`/`cell`/`row-total-cell` parts, which is exactly what keeps them
2893
+ geometrically identical to real rows, so `skeleton` is the part to target for the placeholder's own
2894
+ look: `::part(skeleton) { --lr-skeleton-h: 2em; }`), and
2222
2895
  `pagination`, `cell-editor`, `group-row`, `group-cell`, and `resize-handle` (the focusable column
2223
- separator)
2896
+ separator). The built-in empty state is addressable rather than fixed: `empty` is the `<lr-empty>`
2897
+ host in all three empty states, and it re-exports that element's own inner parts as `empty-base`,
2898
+ `empty-icon`, `empty-heading`, `empty-description` and `empty-actions`. Note that the no-columns and
2899
+ no-rows states return the empty element as the shadow root's own root, with no `[part='base']`
2900
+ wrapper around it — `::part(base)` does not apply in those two states, only in the filtered-to-zero
2901
+ one — and that `empty` disappears entirely once the `empty` slot is filled.
2224
2902
 
2225
2903
  **Themeable custom properties:** `--lr-table-max-height` (default `none`; controls the scrollable
2226
2904
  body's `max-block-size`). `--lr-table-heat-tint-lo` (default `var(--lr-color-brand-quiet)`) and
@@ -2228,6 +2906,16 @@ body's `max-block-size`). `--lr-table-heat-tint-lo` (default `var(--lr-color-bra
2228
2906
  for heat-tint mode's per-cell background, consulted only on columns/rows that define `heatValue`;
2229
2907
  `--lr-table-resize-min-width` (default `var(--lr-size-3rem)`) and
2230
2908
  `--lr-table-resize-handle-opacity` (default `0.12`) control resizable-column behavior.
2909
+ `--lr-table-row-selected-bg` (default `var(--lr-color-brand-quiet)`) — the background of a row whose
2910
+ `aria-selected` is `true`. Like every state-scoped custom property in this library it is an inline
2911
+ `var()` fallback at its point of use and is **not** declared on `:host`, so it can be set on the
2912
+ element *or on any ancestor* and still reach the rule that reads it. It exists because Shadow Parts
2913
+ forbids an attribute selector after `::part()` — `::part(row)[aria-selected='true']` is invalid CSS —
2914
+ so the only prior lever for restyling the selected row was overriding the library-wide
2915
+ `--lr-color-brand-quiet` token, which repaints everything else reading it.
2916
+ `--lr-table-sticky-offset` (default `0`) is measured and written inline per column by the component
2917
+ so multiple `sticky` columns stack instead of overlapping; it is a read-out, not a knob you set.
2918
+ `--lr-table-heat-t` is likewise component-written (each `[data-heat]` cell's position on the ramp).
2231
2919
 
2232
2920
  **Optional peer deps:** none.
2233
2921
 
@@ -2267,6 +2955,35 @@ for heat-tint mode's per-cell background, consulted only on columns/rows that de
2267
2955
  [role="slider"]`, **or any custom element** (any tag name containing a hyphen — e.g. a
2268
2956
  `<lr-select>`/`<lr-combobox>` rendered inside a `cell()`), are left alone by the table's own
2269
2957
  delegated `click`/`keydown` handlers instead of triggering `lr-sort`/`lr-row-click`.
2958
+ - `layout="fixed"` (and any `'auto'` that resolves to fixed) carries two consequences of the CSS
2959
+ fixed algorithm. With no declared widths the **first** row — the header row included — determines
2960
+ every column's width, so revealing a `priority`-hidden column via
2961
+ `[part='reveal-columns-button']` re-measures and changes *all* of them, not just the revealed one.
2962
+ And `columns[].minWidth`/`maxWidth` are silently ignored by `table-layout: fixed`; declare `width`
2963
+ instead when a specific column needs a specific size.
2964
+ - skeleton mode keeps geometry stable only when the browser isn't sizing columns from cell content.
2965
+ Under the default `table-layout: auto`, placeholder cells have no intrinsic width, so the columns
2966
+ re-measure when real content arrives — exactly as they do between any two different data sets. For
2967
+ pixel-identical widths across the load, declare `columns[].width` or set `layout="fixed"`. Either
2968
+ loading appearance keeps exactly one `role="status"` live region announcing the state: every
2969
+ placeholder opts out of `<lr-skeleton>`'s own announcement, so a skeleton table never announces
2970
+ once per placeholder row.
2971
+ - `columns[].cellTitle` returning an empty string **or** `undefined` omits the `title` attribute
2972
+ entirely rather than rendering `title=""` — an empty `title` would suppress an ancestor element's
2973
+ own tooltip. The attribute is also suppressed while that cell is in inline-edit mode, so the
2974
+ tooltip can't shadow the editor. Accessibility caveat: some screen readers announce a `<td title>`
2975
+ as the cell's accessible *name*, replacing the cell's content rather than supplementing it (the
2976
+ same caveat `lr-stat`'s `exactValue` carries). Use it for a longer form of what the cell already
2977
+ shows, never for information that exists nowhere else.
2978
+ - `editable: 'always'` deliberately does not re-assert a cell's source value once the user has typed
2979
+ into it. That is the native dirty-value-flag behavior the attribute binding buys, and it is the
2980
+ point: a background `rows` refresh cannot silently overwrite an in-progress edit. If you need the
2981
+ opposite — an authoritative external value that always wins — do not use `'always'`; re-key the
2982
+ row (`rowKey`) so the editor is recreated rather than updated, or keep `editable: true` and let
2983
+ the short-lived double-click editor's property binding re-assert. Also note the two things
2984
+ `'always'` intentionally does *not* do: it never sets the roving `tabindex` (its editors are
2985
+ ordinary tab stops, so Tab order in that column interleaves with the grid's two roving stops,
2986
+ the same way the row-expand toggle's already does), and it never cancels Escape.
2270
2987
 
2271
2988
  ---
2272
2989
 
@@ -2317,8 +3034,11 @@ The internal page input's `focus` and `blur` are also bridged as bubbling, compo
2317
3034
  `page-input`, `page-count`, `next-button`, `next-icon`, `live-region`.
2318
3035
 
2319
3036
  **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.
3037
+ `--lr-pagination-font-size` (both default from `size`), `--lr-pagination-control-padding` (default
3038
+ `var(--lr-space-xs)`) — inner padding of the previous/next buttons and the page input, deliberately
3039
+ uniform across every `size` tier because the control's outer footprint is already fixed by
3040
+ `--lr-pagination-control-size`, so this only adjusts the icon/digit inset — plus shared color,
3041
+ spacing, border, radius, disabled-opacity, and focus-ring tokens.
2322
3042
 
2323
3043
  **Optional peer deps:** none.
2324
3044
 
@@ -2530,6 +3250,16 @@ focus; it continues to emit `lr-cell-click` and leaves selection state consumer-
2530
3250
  measured `clientWidth` on every draw/resize instead of the fixed `cell-size`, so the grid actually
2531
3251
  fills the available width; now applies to calendar mode as well as matrix mode — see gotchas for
2532
3252
  the default, non-`fit-to-width` behavior)
3253
+ - `maxCellSize?: number` (attribute `max-cell-size`) — ceiling, in CSS px, on the cell size
3254
+ `fitToWidth` derives from the host width, in **both** modes. Exists because `fitToWidth` divides
3255
+ the *whole* host width across the grid, so a 5-week calendar or a 3-column matrix in a wide pane
3256
+ produces enormous blocks; capping them keeps a cell a cell
3257
+ - `minCellSize?: number` (attribute `min-cell-size`) — the mirror floor, in CSS px, so a year-long
3258
+ calendar in a narrow pane keeps legible, hit-testable cells and overflows its host instead of
3259
+ collapsing to hairlines. It can only *raise* the built-in `4`px floor, never lower it: a value
3260
+ below `4` normalizes to `4`. When both clamps are set and `maxCellSize < minCellSize`, the ceiling
3261
+ wins. For both: a non-finite value, or an empty attribute, means unset rather than `0`, and unset
3262
+ (the default) reproduces the unclamped fit-to-width behavior exactly
2533
3263
  - `valueLabel: string = 'value'` (attribute `value-label`)
2534
3264
  - `scale: 'linear' | 'sqrt' = 'linear'` — governs both modes: in matrix mode, `'sqrt'` compresses the
2535
3265
  color ramp via `sqrtStep()` instead of mapping linearly; in calendar mode, the default `'linear'`
@@ -2563,7 +3293,12 @@ focus; it continues to emit `lr-cell-click` and leaves selection state consumer-
2563
3293
  its low DOM footprint.
2564
3294
  - `cellText?: (pos: MatrixCellPos | CalendarCellPos, value: number) => string` (attribute: false) —
2565
3295
  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.
3296
+ position (`MatrixCellPos { row, col }` in matrix mode, `CalendarCellPos { week, weekday, date }` in
3297
+ calendar mode) and its value. `CalendarCellPos.date` is a **required** ISO `yyyy-mm-dd` string,
3298
+ present for every grid position — including a sparse gap position with no matching entry in `days`
3299
+ at all, which still sits on a real calendar day (that case simply reports the `-1` "no data" value
3300
+ alongside it). It lets a callback key off the date without re-deriving the grid's own
3301
+ anchor-week arithmetic; `MatrixCellPos` is unchanged, and so is `lr-cell-click`'s detail.
2567
3302
  Unset (the default) falls back to the built-in English "Row X, Col Y: value" (matrix) / "Jan 15:
2568
3303
  value" — short month + day, **not** a weekday abbreviation (calendar) — template. Additive, not
2569
3304
  breaking.
@@ -2610,10 +3345,14 @@ focus; it continues to emit `lr-cell-click` and leaves selection state consumer-
2610
3345
  interpolate continuously into `colorSteps.length` buckets instead. Unset (the default, or fewer
2611
3346
  than 2 entries) keeps today's 2-endpoint interpolation exactly.
2612
3347
  - `legendStops?: HeatmapLegendStop[]` (attribute: false) — `HeatmapLegendStop { value: number;
2613
- color: string; label?: string }`: a discrete legend key rendered **instead of** the
3348
+ color?: string; label?: string }`: a discrete legend key rendered **instead of** the
2614
3349
  `--lr-heatmap-scale-lo`/`-hi` gradient bar and its `[part="legend-lo"]`/`[part="legend-hi"]`
2615
3350
  endpoint labels — one `[part="legend-stop"]` per entry, in array order, each a
2616
3351
  `[part="legend-swatch"]` filled with that entry's `color` plus a `[part="legend-stop-label"]`.
3352
+ `color` is optional: omit it (or pass an empty string) for a **caption-only** stop, which renders
3353
+ its `[part="legend-stop-label"]` alone with no `[part="legend-swatch"]` element in the DOM at all —
3354
+ so a leading "0" or trailing "more" caption around a run of colored stops doesn't leave an empty
3355
+ swatch box in the row.
2617
3356
  A stop's label defaults to the component's own locale-aware numeric formatting of `value`, so an
2618
3357
  explicit `label` is only needed when the number isn't the right caption ("none", "≥ 90%"). Exists
2619
3358
  for the consumer who supplies `cellColor`: because that callback overrides a cell's color
@@ -2639,7 +3378,9 @@ button), `tooltip` (hover tooltip, positioned over the hovered cell),
2639
3378
  `live-region` (visually-hidden `role="status" aria-live="polite"` element announcing the
2640
3379
  keyboard-focused cell), `legend`, `legend-lo`, `legend-hi` (both omitted, along with the gradient
2641
3380
  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),
3381
+ `legend-swatch` (that stop's color chip, not rendered at all for a caption-only stop),
3382
+ `legend-stop-label` (that stop's text), `legend-value-label` (the trailing `valueLabel` caption that
3383
+ closes the legend row, present in both the gradient and the `legendStops` branch),
2643
3384
  `legend-annotation` (one per labeled `annotations` entry)
2644
3385
 
2645
3386
  **Themeable custom properties:** `--lr-heatmap-scale-lo` (default `#cde2fb`),
@@ -2704,6 +3445,11 @@ same color as `--lr-heatmap-focus-ring-color`).
2704
3445
  width, so a container-resize redraw is a geometric no-op; the stylesheet's
2705
3446
  `canvas { inline-size: 100% }` is also dead code in that case, since `draw()` unconditionally sets
2706
3447
  an inline `canvas.style.width/height` that wins over it.
3448
+ - `maxCellSize`/`minCellSize` are no-ops without `fit-to-width` — an explicit `cellSize` is an exact
3449
+ request and is never clamped. And the canvas is sized *from the clamped* cell size, so a capped
3450
+ grid deliberately leaves the host's remaining width unfilled: the canvas simply ends early rather
3451
+ than stretching to fill. Position it with ordinary CSS on the host if you want it centered or
3452
+ end-aligned.
2707
3453
  - the host is `role="group"` (not `role="img"`) with a dimensions+range summary `aria-label`
2708
3454
  (calendar mode: a day-count + range summary instead) — `[part="canvas"]` inside it is a real
2709
3455
  focusable, keyboard-operable, per-cell-interactive control (roving arrow-key focus,
@@ -2758,6 +3504,12 @@ mapping is readable without hovering each cell.
2758
3504
  filtering legend). Because it only repeats the category names `[part="base"]` already announces
2759
3505
  through its `role="img"` summary, the legend is `aria-hidden` — visible on screen, announced
2760
3506
  exactly once — and it wraps onto further rows in a narrow allocation rather than overflowing
3507
+ - `markerLabel?: string` (attribute `marker-label`) — names what an item's `marker` *means* (e.g.
3508
+ `"Subagent"`). Setting it does two things: with `showLegend` on it adds one trailing
3509
+ `[part="legend-item"]`, whose `[part="legend-marker-swatch"]` reproduces the cell's own marker
3510
+ treatment, and it adds the marker to the auto-generated `aria-label` summary, which is otherwise
3511
+ per-category only. The marker count is reported as its own clause rather than folded into any
3512
+ category's count. Unset (the default) changes nothing: no extra legend row, no extra summary clause
2761
3513
 
2762
3514
  **Events:** none.
2763
3515
 
@@ -2768,13 +3520,19 @@ by its category), `marker` (the small bottom marker on a cell whose item sets `m
2768
3520
  `tooltip` (the hover tooltip showing the hovered item's label, hidden until a cell is hovered),
2769
3521
  `legend` (the static category key rendered below the strip when `showLegend` is set — `aria-hidden`,
2770
3522
  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).
3523
+ `categories` entry, plus one trailing marker row when `markerLabel` is set), `legend-swatch` (the
3524
+ color chip, matching that category's cell color), `legend-marker-swatch` (the marker row's chip
3525
+ instead: a neutral chip carrying the same bottom bar a `marker: true` cell paints, in the same
3526
+ `--lr-sequence-strip-marker-color`), `legend-label` (the category's `label`, or its `key` when
3527
+ unset).
2773
3528
 
2774
3529
  **Themeable custom properties:** `--lr-sequence-strip-height` (default `1.5rem` — the strip's
2775
3530
  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
3531
+ `[part="marker"]` fill, and of the marker legend row's bar), `--lr-sequence-strip-legend-swatch-size`
3532
+ (default `0.625rem` — a legend swatch's inline- and block-size, category and marker rows alike), and
3533
+ `--lr-sequence-strip-legend-marker-bg` (default `var(--lr-color-surface-raised)` — the neutral chip
3534
+ background behind the marker legend row's bar; it stands in for "any cell", so it deliberately
3535
+ matches no category color); the tooltip also consumes shared tokens
2778
3536
  `--lr-color-surface`, `--lr-color-text`, `--lr-font-size-xs`, `--lr-radius`, and `--lr-shadow`, and
2779
3537
  the legend consumes `--lr-space-2xs`, `--lr-space-xs`, `--lr-space-s`, `--lr-font-size-xs`,
2780
3538
  `--lr-color-text-quiet`, and `--lr-radius-xs`.
@@ -2830,18 +3588,34 @@ deeply-nested node's own shadow root still reaches it).
2830
3588
  `[part="base"]` element. The component forwards a host `aria-label` to that semantic element when
2831
3589
  `label` is empty; `label` takes precedence when both are set. External `aria-labelledby` idrefs
2832
3590
  are not forwarded across the shadow boundary.
3591
+ - `reorderable: boolean = false` (reflected) — opts into keyboard reordering. Unset, no `lr-reorder`
3592
+ is ever emitted, Ctrl/Cmd+Arrow behaves exactly like a plain Arrow press, and the internal live
3593
+ region is not rendered at all.
2833
3594
 
2834
3595
  **Keyboard:** ArrowDown/ArrowUp move the roving focus to the next/previous *visible* node.
2835
3596
  ArrowRight expands a collapsed node (focus stays put; a second ArrowRight then steps into the first
2836
3597
  child) or moves into an already-expanded node's first child. ArrowLeft collapses an expanded node, or
2837
3598
  moves focus to its parent. Home/End jump to the first/last visible node. Enter/Space activate
2838
- `select()` on the focused node.
3599
+ `select()` on the focused node. While `reorderable`, **Ctrl/Cmd**+ArrowUp/ArrowDown moves the focused
3600
+ node within its own parent's child list instead of navigating. Ctrl/Cmd rather than Alt: Alt+Arrow is
3601
+ browser back/forward on Windows and Linux. ArrowUp/ArrowDown are not direction-sensitive, so this
3602
+ binding is deliberately **not** RTL-swapped — "down" always means later in the sibling list.
2839
3603
 
2840
3604
  **Methods:** `expandAll()`, `collapseAll()` (both recursive, properly sequenced around Lit's render
2841
3605
  cycle).
2842
3606
 
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).
3607
+ **Events:** `lr-reorder` (`detail: { id, parentId, fromIndex, toIndex }`, only while `reorderable`).
3608
+ Like every other event here it is a **request**: `data` is host-owned and is never mutated by this
3609
+ component, so nothing moves until the host reassigns a reordered `data` — focus then follows the
3610
+ moved node. `parentId` is `null` for a top-level item, and `fromIndex`/`toIndex` are **sibling-scoped
3611
+ indices**, not positions in the flattened visible list. The move is constrained to one sibling list
3612
+ and never fires at a subtree boundary, so a reorder can never become a reparent: Ctrl+ArrowDown on
3613
+ the last child of a subtree is ambiguous (the visually next row is a top-level uncle, so "move down"
3614
+ could mean either "swap with the next sibling" — there is none — or "reparent up a level"), and
3615
+ reparenting is a structural edit with no keyboard affordance distinguishing the two. Such a request
3616
+ is simply not made: no event, no announcement, focus stays put. Otherwise this element dispatches
3617
+ nothing directly (see `lr-tree-node` below — those bubble up and are also observed internally to keep
3618
+ the roving `activeId` in sync with clicks).
2845
3619
 
2846
3620
  **Slots:** default (holds the `<lr-tree-node>` elements it manages).
2847
3621
 
@@ -2925,6 +3699,8 @@ indentation), plus the shared tokens listed above.
2925
3699
  - row enrichment is intentionally structured rather than an unrestricted renderer: use `icon`,
2926
3700
  `label`, `description`, `badge`, and `accessibleLabel`. This keeps the host as the single
2927
3701
  `role="treeitem"` interaction target and preserves the APG keyboard model.
3702
+ - `lr-file-tree` does **not** forward `reorderable`, and deliberately so: its `TreeItem[]` is derived
3703
+ from `nodes` on every render and keyed by filesystem path, an order it does not own.
2928
3704
 
2929
3705
  ---
2930
3706
 
@@ -2991,8 +3767,27 @@ with a console warning), `top-start`, `top-end` (floating corner overlays), `bot
2991
3767
  `live-region`, `edge-list` (a visually hidden list of every edge).
2992
3768
 
2993
3769
  **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).
3770
+ spacing — the canvas also writes it inline as `${grid}px` from the `grid` property, which wins over
3771
+ the stylesheet fallback whenever a grid is in effect), `--lr-flow-canvas-march-duration` (default
3772
+ `var(--lr-transition-ambient)`, running-edge march animation duration), and
3773
+ `--lr-flow-canvas-node-current-outline-color` (default `var(--lr-color-brand)`) — the outline color
3774
+ of the current (`aria-current`) node. Like every state-scoped custom property in this library it is
3775
+ an inline `var()` fallback at its point of use rather than a `:host` declaration, so it can be set on
3776
+ the element *or any ancestor*. It exists because Shadow Parts forbids an attribute selector after
3777
+ `::part()` — `::part(node)[aria-current='true']` is invalid CSS — so the current node could otherwise
3778
+ only be restyled by overriding the library-wide `--lr-color-brand` token, repainting everything else
3779
+ that reads it. The same restriction motivates three more state-scoped outline colors:
3780
+ `--lr-flow-canvas-node-connect-invalid-outline-color` (default `var(--lr-color-danger)`) — outline of
3781
+ a node that is an invalid connect-gesture drop target; `--lr-flow-canvas-node-connect-target-outline-color`
3782
+ (default `var(--lr-color-brand)`) — outline of a node that is a valid connect-gesture drop target; and
3783
+ `--lr-flow-canvas-drop-active-outline-color` (default `var(--lr-color-brand)`) — outline of the
3784
+ viewport itself while a palette item is dragged over it (`droppable`). A fifth,
3785
+ `--lr-flow-canvas-node-hover-outline-color` (default `var(--lr-color-border-strong)`) — the
3786
+ mouse-hover preview of a node's own `:focus-visible` ring — exists for a different reason than the
3787
+ four above: it is `:hover`-gated rather than attribute-gated, so `::part(node):hover` *is* valid
3788
+ CSS here, but the internal `[part='node']:hover` rule still out-specifies it ((0,2,0) vs. (0,1,1)),
3789
+ which this custom property sidesteps the same way. Set it to `transparent` to opt out of the hover
3790
+ treatment entirely.
2996
3791
 
2997
3792
  **Optional peer deps:** none.
2998
3793
 
@@ -3045,6 +3840,8 @@ owns none of that.
3045
3840
  - `statusDetail: string = ''` (attribute `status-detail`) — appended to the status line
3046
3841
  - `durationMs: number | null = null` (attribute `duration-ms`) — formatted into the status line
3047
3842
  - `selected: boolean = false` (reflected)
3843
+ - `compact: boolean = false` (reflected) — tighter card padding for dense canvases and palette
3844
+ previews; the border, background, shadow and the `selected`/`status="running"` treatments all stay
3048
3845
  - `inputs: FlowHandle[] = [{ id: 'in' }]`, `outputs: FlowHandle[] = [{ id: 'out' }]` (attribute:
3049
3846
  false) — `FlowHandle { id: string; label?: string }`
3050
3847
  - `orientation: 'horizontal' | 'vertical' = 'horizontal'` (reflected) — which physical edge handles
@@ -3055,10 +3852,24 @@ owns none of that.
3055
3852
  **Slots:** default (body content), `icon` (leading header glyph), `header` (replaces the built-in
3056
3853
  heading row entirely), `toolbar` (action row at the block-end edge).
3057
3854
 
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`).
3855
+ **CSS parts:** `base` (the row wrapping the input handles, the card and the output handles — it
3856
+ carries no card chrome of its own), `card` (the bordered, filled node card), `header`, `icon`,
3857
+ `heading`, `status` (never color-only — always paired with text), `progress`, `body`, `toolbar`,
3858
+ `handle` (every handle dot), `handle-input`, `handle-output`.
3859
+
3860
+ **Themeable custom properties:** `--lr-flow-node-min-inline-size` (default `11rem`),
3861
+ `--lr-flow-node-compact-padding` (default `var(--lr-space-xs)`) and `--lr-flow-node-compact-gap`
3862
+ (default `var(--lr-space-2xs)`) — `[part="card"]`'s padding and row gap while `compact` — and
3863
+ `--lr-flow-node-selected-border` (default `var(--lr-color-brand)`) — the card's border color while
3864
+ `selected`. Like the other state-scoped custom properties here they are inline `var()` fallbacks at
3865
+ their point of use rather than `:host` declarations, so they can be set on the element *or any
3866
+ ancestor* (a canvas retunes every card at once); overriding the selection color otherwise means
3867
+ hijacking the library-wide `--lr-color-brand` token and repainting everything else that reads it.
3868
+ `--lr-flow-node-running-border` (default `var(--lr-color-brand)`) — the card's border color while
3869
+ `status="running"`, independent of `--lr-flow-node-selected-border` so a consumer can retint just one
3870
+ of the two states without the other following along — and `--lr-flow-node-running-glow` (default
3871
+ `var(--lr-color-brand-quiet)`) — the box-shadow color of the running-state ring around the card, and
3872
+ the pulse keyframes' peak color.
3062
3873
 
3063
3874
  **Optional peer deps:** none.
3064
3875
 
@@ -3071,6 +3882,11 @@ text), `progress`, `body`, `toolbar`, `handle` (every handle dot), `handle-input
3071
3882
  reduced-motion exception every animated surface in this library follows.
3072
3883
  - `status` drives a status chip with a localized label plus `statusDetail`/`durationMs`, never a
3073
3884
  color-only indicator.
3885
+ - All card chrome lives on `[part="card"]`, not `[part="base"]` — `base` is only the flex row that
3886
+ holds the input handles, the card and the output handles. Style the box through `::part(card)`.
3887
+ - `--lr-flow-node-min-inline-size` was previously overridden by a duplicate declaration and had no
3888
+ effect. It now sets the card's minimum inline size again, so a node that was relying on the card
3889
+ collapsing below `11rem` will render wider than it used to.
3074
3890
 
3075
3891
  ---
3076
3892
 
@@ -3125,16 +3941,23 @@ no editing commands live here.
3125
3941
  - `for: string = ''` — id of the target `lr-flow-canvas`; empty resolves to the nearest ancestor
3126
3942
  - `orientation: 'vertical' | 'horizontal' = 'vertical'` (reflected) — button-cluster layout axis
3127
3943
  - `hideLock: boolean = false` (attribute `hide-lock`) — omits the lock/unlock toggle button
3944
+ - `appearance: FlowControlsAppearance = 'card'` (reflected) — `'card' | 'plain'`; `'plain'` drops
3945
+ `[part="base"]`'s border, background, padding, corner radius and its floating-surface `box-shadow`,
3946
+ for a cluster placed in a host toolbar or panel that already draws its own surface. There is
3947
+ deliberately no `compact`: the padding is already the smallest spacing step and the only remaining
3948
+ room is the buttons' `--lr-icon-button-size` hit-area floor
3128
3949
 
3129
3950
  **Events:** none dispatched directly — each button calls the resolved canvas's own `zoomIn()`/
3130
3951
  `zoomOut()`/`fit()`, or toggles its `locked` property.
3131
3952
 
3132
3953
  **Slots:** default — extra host buttons appended to the cluster, styled by the same group.
3133
3954
 
3134
- **CSS parts:** `base` (the `role="group"` wrapper), `zoom-in`, `zoom-out`, `fit`, `lock` (omitted
3135
- when `hideLock`).
3955
+ **CSS parts:** `base` (the `role="group"` wrapper; drops its floating-surface chrome under
3956
+ `appearance="plain"`), `zoom-in`, `zoom-out`, `fit`, `lock` (omitted when `hideLock`).
3136
3957
 
3137
- **Themeable custom properties:** shared tokens only.
3958
+ **Themeable custom properties:** shared tokens only — `--lr-icon-button-size` (each button's minimum
3959
+ hit area, unchanged by `appearance`), `--lr-shadow`, `--lr-color-surface`, `--lr-color-border`,
3960
+ `--lr-radius`, `--lr-space-2xs`, `--lr-focus-ring-width`/`-color`/`-offset`.
3138
3961
 
3139
3962
  **Optional peer deps:** none.
3140
3963
 
@@ -3148,6 +3971,10 @@ when `hideLock`).
3148
3971
  - `for` resolution is identical to `lr-flow-minimap`/`lr-flow-run-overlay`: an explicit id, else
3149
3972
  the nearest ancestor canvas — none of the three companions import `LyraFlowCanvas` as a value, only
3150
3973
  its types, so registration order between them and the canvas never matters.
3974
+ - `appearance="plain"` drops the `box-shadow` along with the border and background — unlike most
3975
+ `plain` escapes in this library, which only reset the border/background/padding/radius. A lift
3976
+ shadow with no surface under it reads as a stray smudge, so the whole floating-surface treatment
3977
+ goes together (same as `lr-flow-run-overlay`'s `plain`).
3151
3978
 
3152
3979
  ---
3153
3980
 
@@ -3164,6 +3991,10 @@ strip. Does not execute, poll, or time anything — pure pushed state; `duration
3164
3991
  - `hideSummary: boolean = false` (attribute `hide-summary`) — omits the "{done} of {total} steps
3165
3992
  complete" strip, keeping only the decoration push
3166
3993
  - `label: string = ''` — accessible name for the summary strip
3994
+ - `appearance: 'card'|'plain' = 'card'` (reflected) — `'plain'` removes the border, background,
3995
+ shadow, padding and radius, so a summary strip dropped straight into a host toolbar that already
3996
+ draws its own frame does not double it. `'card'` is the standalone floating-strip presentation and
3997
+ is unchanged.
3167
3998
 
3168
3999
  **Events:** none dispatched directly.
3169
4000
 
@@ -3277,42 +4108,6 @@ numbers, so the two circular-meter components in the library share one visual sc
3277
4108
 
3278
4109
  ---
3279
4110
 
3280
- ## `lr-data-grid`
3281
-
3282
- Keyboard-navigable data grid with typed `columns` and `rows`, sortable headers, roving cell focus,
3283
- loading/empty states, and responsive horizontal overflow.
3284
-
3285
- **Properties:**
3286
- - `columns: DataGridColumn<T>[] = []` (attribute: false) — `{ key, label, width?, sortable?,
3287
- value? }`; `width` becomes the header cell's `inline-size`, `value(row)` overrides the default
3288
- `row[key]` lookup
3289
- - `rows: T[] = []` (attribute: false)
3290
- - `rowKey: (row: T, index: number) => string | number = (_row, index) => index` (attribute: false)
3291
- - `selectedKey: string | number | null = null` (attribute: false) — compared against `rowKey(row, i)`
3292
- to set `[part='row'][data-selected]` and `aria-selected`
3293
- - `sortKey: string = ''`, `sortDirection: 'ascending' | 'descending' = 'ascending'`
3294
- (attribute: false) — the grid updates both on header activation and emits `lr-sort`, but never
3295
- reorders `rows`; sorting stays the consumer's job
3296
- - `loading: boolean = false` (reflected) — replaces the body with a localized "loading" row
3297
- - `emptyText: string = ''` (attribute `empty-text`) — empty-state text; falls back to the localized
3298
- `noData`
3299
- - `accessibleLabel: string = ''` (attribute `aria-label`) — names the `role="grid"` table; falls back
3300
- to the localized `dataGridLabel`
3301
-
3302
- **Keyboard:** exactly one cell is tabbable. Arrows move the roving focus (Left/Right are swapped
3303
- under RTL), Home/End jump to the first/last column of the current row, Enter/Space activate the row.
3304
- The focus position is re-clamped whenever `rows`/`columns` shrink, so the grid can't lose its tab stop.
3305
-
3306
- **Events:** `lr-row-click` (`detail: { row }`, click or Enter/Space), `lr-selection-change`
3307
- (`detail: { row }`, emitted alongside it after `selectedKey` updates), `lr-cell-focus`
3308
- (`detail: { row, column }`, `column` is the column `key`), `lr-sort` (`detail: { key, direction }`,
3309
- `sortable` columns only; re-activating the active column flips `direction`).
3310
-
3311
- **Slots:** none.
3312
-
3313
- **CSS parts:** `viewport` (the scrolling bordered wrapper), `grid` (the `<table role="grid">`),
3314
- `header` (each sticky `<th>`), `row`, `cell`, `empty` (the loading / no-data cell).
3315
-
3316
4111
  ## `lr-calendar`
3317
4112
 
3318
4113
  Responsive month calendar with event markers and an agenda view.
@@ -3347,7 +4142,11 @@ the next button), `nav-glyph` (the chevron, `scaleX(-1)`-mirrored under RTL), `t
3347
4142
 
3348
4143
  **Themeable custom properties:** `--lr-calendar-day-min-block-size` (default `var(--lr-size-6rem)`)
3349
4144
  and `--lr-calendar-day-min-block-size-narrow` (default `4rem`, applied at container inline-size
3350
- ≤ 28rem).
4145
+ ≤ 28rem), and `--lr-calendar-day-selected-bg` (default `var(--lr-color-brand-quiet)`) — background of
4146
+ a selected (`data-selected="true"`) day cell. Component-scoped indirection over the shared
4147
+ `--lr-color-brand-quiet` token, so a consumer can retint the persistent selected-day highlight
4148
+ without also recoloring `[part='nav']:hover`/`[part='agenda-event']:hover`, which read that shared
4149
+ token directly for a visually distinct purpose (transient hover feedback).
3351
4150
 
3352
4151
  **Gotcha:** month-view `[part='event']` markers are a mouse-only quick-select affordance — they sit
3353
4152
  inside the day `<button>`, which may not contain focusable descendants. Agenda view renders each
@@ -3441,6 +4240,15 @@ the real unmasked value).
3441
4240
  an entry's value text and buttons), `value` (carries `data-masked`), `reveal-button`, and
3442
4241
  `copy-button`.
3443
4242
 
4243
+ **Themeable custom properties:** `--lr-env-list-reveal-active-bg` (default
4244
+ `var(--lr-color-brand-quiet)`) and `--lr-env-list-reveal-active-border` (default
4245
+ `var(--lr-color-brand)`) — the background and border color of a pressed (revealed) reveal toggle.
4246
+ Both are inline `var()` fallbacks at their point of use rather than `:host` declarations, so either
4247
+ can be set on the element *or any ancestor*. They exist because
4248
+ `::part(reveal-button)[aria-pressed='true']` is invalid CSS — Shadow Parts forbids an attribute
4249
+ selector after `::part()` — so restyling the pressed state otherwise required overriding the
4250
+ library-wide brand tokens.
4251
+
3444
4252
  ## `lr-document-library`
3445
4253
 
3446
4254
  Controlled searchable and filterable document inventory with versions, tags, owners, freshness,
@@ -3545,12 +4353,39 @@ auto-inserted between each adjacent pair.
3545
4353
  the panel's clamped width or `data-collapse-state`, see below).
3546
4354
  - `railWidth: string = '3.5rem'` (attribute `rail-width`) — the fixed CSS length the collapsing panel
3547
4355
  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
4356
+ - `railBreakpoint: number | string = 640` (attribute `rail-breakpoint`) — below this width, the
4357
+ collapsing panel switches from its normal drag-resizable percent width to the fixed `railWidth`.
4358
+ Accepts a bare pixel number (`640`, `rail-breakpoint="640"` the original form) or a CSS length
4359
+ string: `'640px'`, `'68.75rem'`, `'3em'`. Under the default `collapseBreakpointBasis='container'`
4360
+ it is compared against this component's own measured `[part='base']` inline size (a
4361
+ `ResizeObserver`, active only while `collapse !== 'none'`), and `rem` resolves against the
4362
+ document root's **computed** font size while `em` resolves against this element's own; the length
4363
+ is re-resolved on every measurement, never cached. Anything the grammar rejects — `''`, `'auto'`,
4364
+ garbage, a non-finite number, and deliberately `%`, `vw`/`vh`, `calc()` and `var()` — falls back
4365
+ to the `640` default rather than switching the feature off (unlike `orientationBreakpoint`, this
4366
+ breakpoint has a documented default to fall back to). A negative length is floored at `0`, i.e.
4367
+ never crossed. Must stay above `floatBreakpoint` — an inverted pair is sanitized by raising this
4368
+ one to match, collapsing the `'rail'` band away rather than reporting a wide container as
4369
+ collapsed.
4370
+ - `floatBreakpoint: number | string = 400` (attribute `float-breakpoint`) — below this narrower
3552
4371
  width, the collapsing panel instead becomes an absolutely-positioned overlay ("floating card") on
3553
4372
  top of the other pane(s), removed from the normal flex flow; the sibling(s) take the full width.
4373
+ Same accepted forms, basis, and sanitization as `railBreakpoint`; an unparseable value falls back
4374
+ to the `400` default.
4375
+ - `collapseBreakpointBasis: 'container'|'viewport' = 'container'` (reflected, attribute
4376
+ `collapse-breakpoint-basis`) — which box `railBreakpoint`/`floatBreakpoint` are measured against.
4377
+ Unset, behavior is identical to before this property existed. `'container'` observes this
4378
+ component's own `[part='base']` inline size via `ResizeObserver` and compares strictly `<`;
4379
+ `'viewport'` evaluates `matchMedia('(max-width: <breakpoint>)')` for each of the two thresholds,
4380
+ which is inclusive (`<=`) — native `max-width` semantics, deliberately, so the crossing point
4381
+ matches a CSS `@media` rule authored with the same length exactly. Use `'viewport'` to collapse in
4382
+ step with a page-level responsive layout (a shell whose own `@media` rules restack at the same
4383
+ width) rather than with this split's own allocation; it is also what lets the browser resolve a
4384
+ `rem` breakpoint with real `@media` semantics (against the *initial* font size, ignoring an
4385
+ `html { font-size }` override). Both bands are classified from both queries together on every
4386
+ change, so a fast resize crossing both thresholds at once still lands on one correct state and
4387
+ fires `lr-split-collapse-change` once; under `'viewport'` the first paint is already correct — no
4388
+ `ResizeObserver` round-trip — and that initial state is not announced as a transition.
3554
4389
  - `collapseState: 'wide'|'rail'|'floating'` (reflected, attribute `collapse-state`) — a public
3555
4390
  accessor with force/auto semantics mirroring `<lr-app-rail>`'s `mode`: normally derived
3556
4391
  automatically from the measured container width, but assigning it a concrete value pins it there
@@ -3636,6 +4471,21 @@ the visually-adjacent panel).
3636
4471
  `disconnectedCallback`) is solid and safe to rely on.
3637
4472
  - `orientationBreakpoint` shares its `[part='base']` `ResizeObserver` with `collapse` (one observer,
3638
4473
  not two) — arming logic covers either feature being opted into independently.
4474
+ - **Switching a basis moves the crossing point by exactly 1px.** Container basis compares strictly
4475
+ `<` against a measured width; viewport basis asks `matchMedia('(max-width: …)')`, which is
4476
+ inclusive (`<=`). So at a breakpoint of `640`, a container-basis split is still `'wide'` at 640px
4477
+ while a viewport-basis one has already collapsed. This is deliberate on both sides: `<` is the
4478
+ right comparison for "how much room do I actually have", and `<=` is what a CSS `@media` rule with
4479
+ the same length does, which is the whole point of the viewport basis.
4480
+ - `collapseBreakpointBasis='viewport'` does **not** drop the `ResizeObserver` the way the
4481
+ orientation feature's viewport basis does. The measured width it feeds is still read by a
4482
+ container-basis `orientationBreakpoint` and by the `collapseState = 'auto'` release path, which
4483
+ re-derives from the current measured width. Collapse's basis changes only *which values* the
4484
+ classification consults, never whether the split measures itself.
4485
+ - `railBreakpoint`/`floatBreakpoint` are typed `number | string`. Authored as attributes they read
4486
+ back as **strings** (`el.railBreakpoint === '640'`, not `640`) — the same value, a different type.
4487
+ Compare with `Number(el.railBreakpoint)` rather than `===`, or assign the property directly when a
4488
+ numeric identity matters.
3639
4489
  - **Picking a basis.** `orientationBreakpointBasis='container'` (the default) observes the
3640
4490
  component's own allocated inline size, so it fits a component that is the sole flex/grid item in
3641
4491
  the container being measured. It does **not** fit a component sitting beside a fixed-width sibling
@@ -3721,6 +4571,17 @@ the fullscreen backdrop scrim color), `--lr-widget-fullscreen-inset` (default pe
3721
4571
  tokens (`--lr-space-*`, `--lr-color-border/-surface/-text-quiet`,
3722
4572
  `--lr-radius`, `--lr-shadow`, `--lr-icon-button-size`, `--lr-focus-ring-*`).
3723
4573
 
4574
+ Two further properties style the pressed view toggle: `--lr-widget-view-toggle-active-bg` (default
4575
+ `var(--lr-color-brand-quiet)`) and `--lr-widget-view-toggle-active-color` (default
4576
+ `var(--lr-color-brand)`) — the background and text color of the `aria-pressed="true"` toggle. Both
4577
+ are **state hooks**: declared as inline `var()` fallbacks at the point of use and never on `:host`,
4578
+ so setting either on the element *or on any ancestor* reaches the toggle. That shape exists because
4579
+ `::part(view-toggle)[aria-pressed='true']` is not valid CSS — Shadow Parts forbids an attribute
4580
+ selector after `::part()` — so before these hooks the only way to recolor an active toggle was to
4581
+ override the library-wide `--lr-color-brand-quiet`/`--lr-color-brand` tokens, repainting every other
4582
+ element that reads them. Left unset, each falls back to exactly the token the rule used before, so
4583
+ rendering is unchanged.
4584
+
3724
4585
  **Optional peer deps:** none.
3725
4586
 
3726
4587
  ```html
@@ -3775,6 +4636,15 @@ viewport), `track`, `controls`, `previous-button`, `next-button`, `previous-glyp
3775
4636
  chevron inside each, mirrored under RTL), `indicators`, `indicator` (one indicator's hit target,
3776
4637
  sized to the shared minimum tappable size), and `indicator-dot` (the compact visible dot inside it).
3777
4638
 
4639
+ **Themeable custom properties:** `--lr-carousel-indicator-current-bg` (default
4640
+ `var(--lr-color-brand-quiet)`) and `--lr-carousel-indicator-current-border-color` (default
4641
+ `var(--lr-color-brand)`) — background and border color of the current slide's `indicator-dot`
4642
+ (`[aria-current='true']`). Same state-hook mechanics as `<lr-widget>`'s view-toggle pair above:
4643
+ inline `var()` fallbacks, never declared on `:host`, so either can be set on the element or on any
4644
+ ancestor; unset, each falls back to the token the rule used before. This shape is what makes the
4645
+ current indicator addressable at all — `::part(indicator)[aria-current='true']` is invalid CSS, so
4646
+ hijacking a library-wide color token was previously the only lever.
4647
+
3778
4648
  ```html
3779
4649
  <lr-carousel aria-label="Screenshots">
3780
4650
  <img alt="Dashboard overview" src="overview.png">
@@ -3896,7 +4766,18 @@ inside a tab button; only rendered when that tab has a matching `<id>-icon` sibl
3896
4766
  single `role="tabpanel"` wrapper, one per tab, hidden unless active)
3897
4767
 
3898
4768
  **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 —
4769
+ mask fade at each horizontal scroll edge of the tablist. `--lr-tabs-selected-color` (default
4770
+ `var(--lr-color-brand)`) — text color of the selected tab, scoped to `[aria-selected='true']` only,
4771
+ so it never repaints a hovered unselected tab. `--lr-tabs-indicator-color` (default
4772
+ `var(--lr-color-brand)`) — the selected tab's underline, themeable independently of its text color.
4773
+ `--lr-tabs-hover-color` (default `var(--lr-color-text)`) — text color of a hovered, non-disabled
4774
+ tab, independent of the two selected-state hooks. All three are declared as inline `var()` fallbacks
4775
+ at the point of use rather than on `:host`, so each can be set on the element *or on any ancestor* —
4776
+ the pattern exists because `::part(tab)[aria-selected='true']` is invalid CSS (Shadow Parts forbids
4777
+ an attribute selector after `::part()`), which previously left overriding the library-wide
4778
+ `--lr-color-brand`/`--lr-color-text` tokens as the only way to restyle a selected or hovered tab,
4779
+ repainting everything else that reads them. Unset, each falls back to the token its rule used
4780
+ before, so rendering is unchanged. Otherwise shared tokens —
3900
4781
  `--lr-space-xs/-s/-m`, `--lr-color-border/-text-quiet/-text/-brand`, `--lr-transition-fast`,
3901
4782
  `--lr-radius`, `--lr-focus-ring-width/-color/-offset`, `--lr-opacity-disabled`.
3902
4783
 
@@ -3937,10 +4818,13 @@ convention).
3937
4818
 
3938
4819
  **Properties:**
3939
4820
  - `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.
4821
+ 'pending' | 'current' | 'completed' | 'disabled' | 'error'; title?: string; icon?: unknown }`;
4822
+ `title` is an optional native tooltip for the step's button (e.g. explaining why a `disabled` step
4823
+ is locked) — omit it for no `title` attribute at all, not an empty string. `icon` is an optional
4824
+ leading topic glyph (a `TemplateResult`, an emoji string, etc. — not restricted to a square icon)
4825
+ rendered in the `step-icon` part additionally to, never instead of, the state-driven
4826
+ `step-index`/`step-check` glyph. Never mutated by this component. Empty (the default) renders
4827
+ nothing.
3944
4828
  - `orientation: 'horizontal' | 'vertical' = 'horizontal'` (reflected) — `'horizontal'` (the default)
3945
4829
  lays steps out in a row (Left/Right, RTL-aware, navigate); `'vertical'` stacks them (Up/Down
3946
4830
  navigate instead, no RTL swap needed). The axis used at/above `orientationBreakpoint` (or always,
@@ -3989,11 +4873,25 @@ single place to short-circuit its own listener's follow-up work. `lr-stepper-ori
3989
4873
  **Slots:** none.
3990
4874
 
3991
4875
  **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`,
4876
+ `step-icon` (optional leading topic glyph from the step's `icon` field; only rendered when the step
4877
+ has one, additionally to never instead of `step-index`/`step-check`), `step-index` (the numbered
4878
+ index chip, shown for `pending`/`current`/`error` steps), `step-check` (the completed-checkmark
4879
+ glyph, shown for `completed` steps instead of `step-index`), `step-label` (the step's label text).
4880
+
4881
+ **Themeable custom properties:** `--lr-stepper-current-color` (default `var(--lr-color-text)`) —
4882
+ text color of the `current` step. `--lr-stepper-current-font-weight` (default
4883
+ `var(--lr-font-weight-semibold)`) — font weight of the `current` step's label.
4884
+ `--lr-stepper-error-color` (default `var(--lr-color-danger)`) —
4885
+ text color of an `error` step. `--lr-stepper-current-index-bg` (default `var(--lr-color-brand)`) and
4886
+ `--lr-stepper-current-index-color` (default `var(--lr-color-surface)`) — background and text color
4887
+ of the `current` step's numbered `step-index` chip. Each is an inline `var()` fallback at the point
4888
+ of use, never declared on `:host`, so it can be set on the element or on any ancestor; and each is
4889
+ scoped to its own `data-state`, so recoloring the current step leaves `pending`/`completed`/`error`
4890
+ steps alone. The hooks exist because `::part(step)[data-state='current']` is invalid CSS — Shadow
4891
+ Parts forbids an attribute selector after `::part()` — so state-specific theming previously meant
4892
+ overriding a library-wide `--lr-color-*` token and repainting everything else that read it. Unset,
4893
+ each falls back to the token its rule used before. Otherwise shared tokens —
4894
+ `--lr-space-m`/`-xs`/`-2xs`,
3997
4895
  `--lr-color-text-quiet`/`-text`/`-danger`/`-brand`/`-surface`, `--lr-radius`/`-pill`,
3998
4896
  `--lr-font-size-xs`, `--lr-font-weight-semibold`, `--lr-opacity-disabled`,
3999
4897
  `--lr-focus-ring-*`.
@@ -4035,14 +4933,18 @@ single place to short-circuit its own listener's follow-up work. `lr-stepper-ori
4035
4933
 
4036
4934
  ## `lr-control-group`
4037
4935
 
4038
- Responsive semantic grouping for mixed controls and actions. It keeps slotted children in a
4039
- wrapping inline-flex row, centers children with different intrinsic heights, and switches to a
4040
- full-width allocation in narrow containers. Use it for dashboard toolbars that combine segmented
4041
- controls, selects, buttons, and other interactive elements.
4936
+ Semantic grouping for mixed controls and actions. It keeps slotted children in a wrapping
4937
+ inline-flex row and centers children with different intrinsic heights. Use it for dashboard
4938
+ toolbars that combine segmented controls, selects, buttons, and other interactive elements.
4042
4939
 
4043
4940
  **Properties:**
4044
4941
  - `label: string = ''` — accessible name for the internal `role="group"`; when empty, a host
4045
4942
  `aria-label` is forwarded as a fallback.
4943
+ - `responsive: boolean = false` (reflected) — opts into a `@container` narrow-allocation breakpoint
4944
+ (switches to a full-width allocation below `20rem`) by making the host a CSS size-query
4945
+ container. Left unset, the host is `container-type: normal`, since `container-type: inline-size`
4946
+ unconditionally would collapse the group to 0 inline size whenever it sits as an ordinary
4947
+ (`flex-basis: auto`) child of a shrink-to-fit flex row — this component's own primary use case.
4046
4948
 
4047
4949
  **Events:** none.
4048
4950
 
@@ -4065,6 +4967,79 @@ between grouped controls; shared spacing and layout tokens apply as well.
4065
4967
  - This is a layout and semantics primitive; it does not coordinate child values or emit a group
4066
4968
  change event.
4067
4969
  - Children wrap according to the group's own allocated inline size, not the viewport width.
4970
+ - The `@container` narrow-allocation breakpoint only applies when `responsive` is set. Setting
4971
+ `responsive` while this group also sits as a shrink-to-fit flex child re-introduces the 0-width
4972
+ collapse this default is designed to avoid — only opt in when the group's own size comes from
4973
+ somewhere else (a percentage width, a grid track, a block-level parent).
4974
+
4975
+ ---
4976
+
4977
+ ## `lr-reorder-list` / `lr-reorder-item`
4978
+
4979
+ A generic flat-list reorder primitive: per-row move-up/move-down buttons (always available), plus
4980
+ Ctrl/Cmd+ArrowUp/ArrowDown from focus anywhere inside a row — the same modifier convention
4981
+ `<lr-tree>`'s `reorderable` and `<lr-dashboard-grid>`'s `cells-draggable` already establish. Unlike
4982
+ `<lr-tree>`'s controlled `reorderable` mode, this list physically moves its own slotted
4983
+ `<lr-reorder-item>` light-DOM nodes itself (there is no `data` array prop to reconcile against),
4984
+ and emits `lr-reorder` with the full new order so the host can persist it without hand-rolling its
4985
+ own splice/resort logic.
4986
+
4987
+ ### `lr-reorder-list`
4988
+
4989
+ **Properties:**
4990
+ - `label: string = ''` — accessible name for the internal `role="list"`; when empty, a host
4991
+ `aria-label` is forwarded as a fallback.
4992
+ - `disabled: boolean = false` (reflected) — disables every item's move buttons and the Ctrl/Cmd+
4993
+ Arrow shortcut, without mutating any item's own `disabled` attribute.
4994
+
4995
+ **Events:** `lr-reorder` (`detail: { order: string[], fromIndex: number, toIndex: number }` — fired
4996
+ after every successful move; `order` is every current item's `value` (or its DOM-position-index
4997
+ fallback) in the new top-to-bottom order)
4998
+
4999
+ **Slots:** default — `<lr-reorder-item>` elements.
5000
+
5001
+ **CSS parts:** `base` — the internal `role="list"` wrapper.
5002
+
5003
+ **Themeable custom properties:** `--lr-reorder-list-gap` (default `var(--lr-space-2xs)`) — gap
5004
+ between rows.
5005
+
5006
+ ```html
5007
+ <lr-reorder-list label="Form fields" @lr-reorder=${(e) => console.log(e.detail.order)}>
5008
+ <lr-reorder-item value="name">Name</lr-reorder-item>
5009
+ <lr-reorder-item value="email">Email</lr-reorder-item>
5010
+ <lr-reorder-item value="phone">Phone</lr-reorder-item>
5011
+ </lr-reorder-list>
5012
+ ```
5013
+
5014
+ **Known gotchas:**
5015
+ - Boundary-disabled state (`atStart`/`atEnd`) and the `listDisabled` cascade are computed and
5016
+ pushed onto each `<lr-reorder-item>` by this list, on every slot change and every move — an item
5017
+ alone can't know its own position.
5018
+ - No pointer drag-and-drop; move-up/move-down buttons and the keyboard shortcut only.
5019
+
5020
+ ---
5021
+
5022
+ ### `lr-reorder-item`
5023
+
5024
+ **Properties:**
5025
+ - `value?: string` — stable identifier included in the parent's `lr-reorder` order array; falls
5026
+ back to this item's live DOM-position index when unset.
5027
+ - `disabled: boolean = false` (reflected) — disables this row's own move buttons only; does not
5028
+ hide its slotted content.
5029
+ - `atStart: boolean = false`, `atEnd: boolean = false`, `listDisabled: boolean = false`
5030
+ (attribute: false) — pushed down by the parent `<lr-reorder-list>`; normally set internally, not
5031
+ by consumers.
5032
+
5033
+ **Events:** `lr-move-request` (`detail: { direction: 'up' | 'down' }` — a move button was activated
5034
+ while not disabled; handled by the parent `<lr-reorder-list>`, which performs the actual move)
5035
+
5036
+ **Slots:** default — arbitrary row content.
5037
+
5038
+ **CSS parts:** `base` (row wrapper), `move-up-button`, `move-down-button`, `content` (default-slot
5039
+ wrapper).
5040
+
5041
+ **Themeable custom properties:** `--lr-reorder-item-gap` (default `var(--lr-space-xs)`) — gap
5042
+ between the move buttons and the row content.
4068
5043
 
4069
5044
  ---
4070
5045
 
@@ -4100,7 +5075,29 @@ fade at each horizontal scroll edge of the track. `--lr-segmented-track-min-heig
4100
5075
  `--lr-segmented-segment-padding`, and `--lr-segmented-font-size` are the three knobs `size` swaps
4101
5076
  (`m` defaults: `auto`, `var(--lr-size-0-125rem) var(--lr-space-s)`, `var(--lr-font-size-sm)`) —
4102
5077
  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`/
5078
+ wins over the `:host` default.
5079
+
5080
+ `--lr-segmented-track-height` pins the `base` track's exact height at every `size` tier (it sets
5081
+ both `block-size` and `min-block-size`), for a row that has to sit flush beside a hard-sized toolbar
5082
+ control. It is **genuinely undeclared by default** — not `auto` — and that is load-bearing: an
5083
+ exact-height hatch only works as an undeclared sentinel, because `auto` is itself a valid value that
5084
+ would always win and would silently turn every tier's `--lr-segmented-track-min-height` floor into
5085
+ dead code. While it is unset, each tier keeps its own floor and the track grows with its content.
5086
+
5087
+ `--lr-segmented-selected-bg` (default `var(--lr-color-surface)`), `--lr-segmented-selected-color`
5088
+ (default `var(--lr-color-text)`), `--lr-segmented-selected-font-weight` (default
5089
+ `var(--lr-font-weight-semibold)`) and `--lr-segmented-selected-shadow` (default `var(--lr-shadow)`)
5090
+ style the checked segment's pill; `--lr-segmented-hover-color` (default `var(--lr-color-text)`)
5091
+ styles a hovered segment that is neither checked nor disabled, independently of the four above — so
5092
+ recoloring the checked pill never bleeds onto hover. All five are inline `var()` fallbacks at the
5093
+ point of use rather than `:host` declarations, so each can be set on the element *or on any
5094
+ ancestor*; unset, each falls back to the token its rule used before. They exist because
5095
+ `::part(segment)[aria-checked='true']` is invalid CSS — Shadow Parts forbids an attribute selector
5096
+ after `::part()` — which previously left hijacking the library-wide
5097
+ `--lr-color-surface`/`--lr-color-text` tokens as the only way to restyle a selected segment,
5098
+ repainting every other element that read them.
5099
+
5100
+ Otherwise shared tokens — `--lr-color-border`/`-surface`/`-text`/
4104
5101
  `-text-quiet`, `--lr-radius`, `--lr-font-weight-semibold`, `--lr-space-s`, `--lr-shadow`,
4105
5102
  `--lr-opacity-disabled`, `--lr-focus-ring-*`.
4106
5103
 
@@ -4150,10 +5147,39 @@ invention (no Web Awesome equivalent).
4150
5147
  which is only a safe identity while `items` never reorders/inserts/removes — provide this whenever
4151
5148
  possible, or scroll position and per-row DOM state (e.g. an `<audio>` element's playback position)
4152
5149
  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.
5150
+ - `groups?: VirtualListGroup[]` (attribute: false) — renders a labeled marker at each group's
5151
+ `startIndex`, positioned independently of the row window (so it stays in place as its rows scroll
5152
+ past). Groups are sorted by `startIndex`; a `startIndex` that's non-integer, out of range, or a
5153
+ duplicate of an earlier group's is silently dropped rather than rendered wrong. An entry whose
5154
+ `label` is the **empty string** renders no marker at all — it is a pure position anchor, for a host
5155
+ that renders its own group header as an ordinary row (and would otherwise end up with two stacked
5156
+ headers) but still needs this component to know where each group starts, e.g. to drive
5157
+ `renderStickyGroup` below. Omitting `label` entirely still falls back to rendering `key`.
5158
+ - `renderStickyGroup?: (group: VirtualListGroup) => unknown` (attribute: false) — renders a pinned
5159
+ copy of whichever `groups` entry the viewport is currently inside, into a `[part="sticky-group"]`
5160
+ overlay that stays at the top of the scroll viewport and is pushed out by the overlap as the next
5161
+ group's header arrives (rather than swapped abruptly at the boundary). Native `position: sticky` on
5162
+ the rows or markers themselves cannot do this: every row is absolutely positioned and
5163
+ transform-offset by the windowing math, which makes sticky structurally inert. Unset (the default)
5164
+ renders no overlay element whatsoever and changes nothing about the list's output. The overlay is a
5165
+ *visual copy* of content that already exists in the list, which fixes its contract:
5166
+ - it is `aria-hidden`, and ordinary focusable HTML inside it is forced to `tabindex="-1"`, so the
5167
+ real row keeps sole ownership of the heading semantics and of the tab order (a focus-delegating
5168
+ custom element rendered into the copy needs its own `tabindex="-1"`; `inert` is deliberately not
5169
+ used, because it would also block the pointer opt-in below);
5170
+ - it is `pointer-events: none` by default — opt back in with
5171
+ `lr-virtual-list::part(sticky-group) { pointer-events: auto; }` when the copied header content is
5172
+ interactive;
5173
+ - it is never measured as a row, so a group header that is also a real row is not double-counted in
5174
+ `row-height="auto"` mode;
5175
+ - its measured height is applied as `scroll-padding-block-start` on the scroll container and
5176
+ subtracted from top-aligned scroll targets, so `active-id`, `scrollToIndex({ align: 'start' })`
5177
+ and native keyboard scrolling all stop *below* the band instead of parking the row behind it.
5178
+
5179
+ The callback runs on every scroll-driven update, so keep it cheap and side-effect free. While the
5180
+ viewport is above the first group there is nothing to pin: the band shows nothing, but it stays
5181
+ mounted (called with the first group, rendered hidden) so its height is known before the first
5182
+ programmatic jump rather than only after it.
4157
5183
  - `rowHeight: string = 'auto'` (attribute `row-height`) — `'auto'` measures each row's real height via
4158
5184
  `ResizeObserver`; a numeric string (e.g. `"56"`) fixes every row to that many pixels. Anything else
4159
5185
  (non-numeric, zero, negative, non-finite) silently falls back to `'auto'` rather than throwing.
@@ -4180,7 +5206,8 @@ invention (no Web Awesome equivalent).
4180
5206
 
4181
5207
  **Exported types:** `VirtualListRange { start: number; end: number }` (the `lr-visible-range-changed`
4182
5208
  detail shape); `VirtualListGroup { key: string | number; label?: string; startIndex: number }` — the
4183
- shape consumed by `groups` above.
5209
+ shape consumed by `groups` above; `VirtualListScroll { scrollTop: number; viewportHeight: number }` —
5210
+ the `lr-scroll` detail shape.
4184
5211
  The package root also exports `groupByRecency(items, options?)`, a DOM-free helper that returns
4185
5212
  non-empty Today/Yesterday/Previous 7 Days/Older buckets, preserves input order within each bucket,
4186
5213
  and accepts a timestamp extractor, reference date, and label overrides.
@@ -4190,12 +5217,35 @@ automatic scroll-into-view, for a host that needs to scroll to a specific row wi
4190
5217
  row is "active." `options.align` is `'start'`, `'end'`, or `'auto'` (default — no scroll at all when
4191
5218
  already fully visible); `options.behavior` (default `'smooth'`) is forced to `'auto'` under
4192
5219
  `prefers-reduced-motion: reduce`. `index` is clamped to `0…items.length-1`.
5220
+ `offsetForIndex(index)` returns the pixel top row `index` renders at, in the same coordinate space as
5221
+ the scroll container's `scrollTop`; it is clamped to `0…items.length`, so `offsetForIndex(items.length)`
5222
+ is the total content height and an empty list is always `0`. `indexAtOffset(px)` is its inverse — the
5223
+ row whose box contains that offset, clamped at both ends, `-1` for an empty list — so
5224
+ `indexAtOffset(offsetForIndex(i)) === i` and `indexAtOffset(scrollContainer.scrollTop)` is the row at
5225
+ the top of the viewport. In `row-height="auto"` mode both are estimate-based for any row that (or
5226
+ above which) has not been measured yet, and converge as those `ResizeObserver` measurements land;
5227
+ fixed numeric `row-height` offsets are exact from the first render. Both read the most recent render,
5228
+ so `await el.updateComplete` after assigning `items` before querying.
5229
+
5230
+ **Getters:** `scrollContainer: HTMLElement | undefined` — the real scroll container (`[part="base"]`),
5231
+ `undefined` before the first render; for a host that needs the live scroll position or wants to scroll
5232
+ the list itself without reaching into the shadow root. `renderedRows: HTMLElement[]` — the row
5233
+ wrappers (`[part="row"]`) that currently exist as real DOM, in item order (the current window, not the
5234
+ whole collection; empty before the first render). It exists for hosts that must *reach* a rendered row
5235
+ rather than style it — keyboard focus management across a windowed list, where the row to focus may
5236
+ not have existed a frame earlier, and which `exportparts` cannot serve since it forwards styling, not
5237
+ element references. Treat both as read-only: positioning, keys, and lifetime belong to the windowing
5238
+ math, and any row element can be recycled or removed on the next update.
4193
5239
 
4194
5240
  **Events:** `lr-load-more` (no detail — fired once per approach to the bottom of the list while
4195
5241
  `has-more` is true and `loading` is false; does not refire on every scroll tick while still near the
4196
5242
  bottom — scrolling back away from the bottom and returning, or `items` growing enough to move the
4197
5243
  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)
5244
+ current visible, non-overscanned item index range — fired only when it actually changes), `lr-scroll`
5245
+ (`detail: VirtualListScroll` — the scroll container moved; emitted from the same animation frame that
5246
+ already coalesces native `scroll` events, so a fling produces at most one per frame and none at all
5247
+ when the position did not change. Unlike `lr-visible-range-changed`, which only fires on index-range
5248
+ changes, this reports *sub-row* movement, which is what scroll-linked layout needs)
4199
5249
 
4200
5250
  **Slots:** none — all content comes from `renderItem`.
4201
5251
 
@@ -4203,13 +5253,20 @@ current visible, non-overscanned item index range — fired only when it actuall
4203
5253
  `item-role="row"` mode — `tabindex="0"`), `spacer` (the full-content-height inner element
4204
5254
  establishing true scroll extent; `role="presentation"` in `item-role="row"` mode), `row` (one
4205
5255
  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)
5256
+ `aria-rowindex` in `item-role="row"` mode), `group` (a `groups` entry's positioned marker; not
5257
+ rendered for an entry whose `label` is the empty string), `sticky-group` (the pinned copy of the
5258
+ current group, present only while `renderStickyGroup` is set — `aria-hidden` and
5259
+ `pointer-events: none` by default; style it with `pointer-events: auto` to make copied interactive
5260
+ content clickable, and it shows nothing while the viewport is above the first group)
4208
5261
 
4209
5262
  **Themeable custom properties:** `--lr-virtual-list-height` (default `24rem` — the host's bounded
4210
5263
  scroll extent; component-specific since a virtualized list is meaningless without a sized viewport),
4211
5264
  plus shared `--lr-focus-ring-width/-color/-offset` (inward-offset ring on `[part="base"]`, negative
4212
- so it isn't clipped by the container's own `overflow: auto`).
5265
+ so it isn't clipped by the container's own `overflow: auto`). `[part="base"]` also carries a
5266
+ mouse-hover outline — a subtler preview of that same `:focus-visible` ring, shown because the part
5267
+ always carries `tabindex="0"` and is a real keyboard-navigable target — tinted via
5268
+ `--lr-virtual-list-hover-outline-color` (default `var(--lr-color-border-strong)`); set it to
5269
+ `transparent` to opt out of the hover treatment entirely.
4213
5270
 
4214
5271
  **Optional peer deps:** none.
4215
5272
 
@@ -4233,6 +5290,20 @@ so it isn't clipped by the container's own `overflow: auto`).
4233
5290
  ></lr-virtual-list>
4234
5291
  ```
4235
5292
 
5293
+ ```html
5294
+ <!-- Sticky group headers: the header is a real row, so the `groups` entries are position anchors
5295
+ only (`label: ''`), and the pinned copy opts back into pointer events for its own toggle. -->
5296
+ <lr-virtual-list
5297
+ .items=${rows}
5298
+ .groups=${groupStarts /* [{ key: 'Today', label: '', startIndex: 0 }, …] */}
5299
+ .renderItem=${(item, index) => (item.isHeader ? headerTemplate(item) : rowTemplate(item))}
5300
+ .renderStickyGroup=${(group) => headerTemplate(group)}
5301
+ ></lr-virtual-list>
5302
+ <style>
5303
+ lr-virtual-list::part(sticky-group) { pointer-events: auto; }
5304
+ </style>
5305
+ ```
5306
+
4236
5307
  Every row — in both `row-height` modes — is positioned by a `transform: translateY(offset)` computed
4237
5308
  from a single cumulative offsets array, rather than by page flow; this is what lets a small DOM window
4238
5309
  exist while the scrollbar still reflects the true total content height. That array is rebuilt only
@@ -4260,8 +5331,27 @@ history sidebar); it is not the right approach for a hundred-thousand-row list w
4260
5331
  - `aria-setsize`/`aria-posinset` are computed from a row's real index in the full `items` array, not its
4261
5332
  position among the currently-rendered DOM window, so assistive tech still announces e.g. "item 12 of
4262
5333
  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.
5334
+ - `groups`, `renderStickyGroup`, `offsetForIndex()`/`indexAtOffset()` and the `lr-scroll` event are
5335
+ all expressed against the *same* windowing math, so they agree with each other — but that math is
5336
+ estimate-based in `row-height="auto"` mode until the rows involved have been measured. Read a
5337
+ position after `await el.updateComplete`, and expect the value to converge rather than be final on
5338
+ the first frame.
5339
+ - A sticky band only appears when `renderStickyGroup` *and* at least one valid `groups` entry are
5340
+ both present; `groups` alone renders positioned markers with nothing pinned, and
5341
+ `renderStickyGroup` alone renders no overlay element at all.
5342
+ - **A row that renders a popup needs the focused-row lift, and this is why `[part='row']` has one.**
5343
+ Each row carries `will-change: transform` (a compositor hint for the per-frame translate), which
5344
+ makes every row its own stacking context. Rows otherwise carry no `z-index`, so they paint in DOM
5345
+ order and each one paints over the previous. Anything a row renders that overflows its own box —
5346
+ an `<lr-menu>` popup in a row-action menu, a tooltip, an outward focus ring — is therefore painted
5347
+ *underneath* every following row, no matter how high its own `z-index` is: that `z-index` only
5348
+ orders siblings inside the row's own context. The last row always looks correct, which is exactly
5349
+ why a short fixture never catches it. `[part='row']:focus-within` lifts the row to
5350
+ `--lr-layer-content` for precisely as long as something inside it holds focus — the lifetime of an
5351
+ open popup — and costs nothing otherwise. The value deliberately *matches* `[part='group']`'s
5352
+ rather than exceeding it, so the two land on the same layer and DOM order decides: groups render
5353
+ before the rows, so a focused row wins while (and only while) it holds focus, which is right — a
5354
+ group header is a non-interactive `pointer-events: none` label.
4265
5355
 
4266
5356
  ---
4267
5357
 
@@ -4467,6 +5557,17 @@ when the item has an explicit `aria-label`).
4467
5557
  **CSS parts:** `base`, `icon`, `label`, `tooltip` (the hover/focus label flyout, only rendered while
4468
5558
  `tooltip` is set, the item is `icon-only`, and it is hovered or focused).
4469
5559
 
5560
+ **Themeable custom properties:** `--lr-app-rail-item-current-bg` (default
5561
+ `var(--lr-color-brand-quiet)`) and `--lr-app-rail-item-current-color` (default
5562
+ `var(--lr-color-brand)`) — background and text/icon color of the `active` (`aria-current="page"`)
5563
+ item. Both are scoped to `[aria-current='page']` only and declared as inline `var()` fallbacks at
5564
+ the point of use, never on `:host`, so either can be set on the item itself *or on any ancestor* —
5565
+ including on `<lr-app-rail>` or a wrapper above it, to tint every item's active state at once.
5566
+ `::part(base)[aria-current='page']` is invalid CSS (Shadow Parts forbids an attribute selector after
5567
+ `::part()`), so before these hooks the only lever was overriding the library-wide
5568
+ `--lr-color-brand-quiet`/`--lr-color-brand` tokens, which repainted every other element reading
5569
+ them. Unset, each falls back to the token its rule used before.
5570
+
4470
5571
  **Optional peer deps:** none.
4471
5572
 
4472
5573
  ---
@@ -4520,7 +5621,11 @@ the *effective* mode — not the `mode` prop's possibly-`'auto'` literal value
4520
5621
  in the overlay presentation).
4521
5622
 
4522
5623
  **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`,
5624
+ `var(--lr-color-overlay)` — the overlay presentation's backdrop scrim color),
5625
+ `--lr-responsive-panel-sheet-max-block-size` (default `85dvh`, falling back to `85vh` where `dvh`
5626
+ isn't supported — the maximum height of a `variant="bottom-sheet"` overlay panel, so a long sheet
5627
+ stops short of the top of the viewport instead of covering it; it has no effect on
5628
+ `variant="fullscreen"` or on the inline presentation), plus shared tokens (`--lr-color-border`, `--lr-color-surface`,
4524
5629
  `--lr-space-*`, `--lr-radius`, `--lr-shadow`).
4525
5630
 
4526
5631
  **Optional peer deps:** none.
@@ -4597,8 +5702,25 @@ menu, an avatar menu, or a history row's overflow menu. Uses the WAI-ARIA "menu
4597
5702
  `this.getAttribute('aria-label') || <computed default>` precedence
4598
5703
 
4599
5704
  - `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
5705
+ close the menu when focus is on non-menu-item content slotted into the **default** slot, i.e.
5706
+ rendered inside `[part="list"]`; item activation remains scoped to actual menu items. It has no
5707
+ bearing on the `header`/`footer` slots, which sit outside the `role="menu"` list and always close
5708
+ on Escape — so a menu that keeps its composed controls there never needs this property
5709
+
5710
+ **Methods:** `show(focus: 'first' | 'last' = 'first')` opens the menu and moves roving focus to the
5711
+ first (or, with `'last'`, the last) non-disabled item; a no-op when already open.
5712
+ `hide(options?: { focusTrigger?: boolean })` closes it; a no-op when already closed. They are the
5713
+ imperative pair for the cases the slotted trigger can't express — a "Done"/"Apply" button *inside*
5714
+ the menu, a keyboard shortcut, a parent restoring UI state — without hand-reproducing the
5715
+ pending-focus bookkeeping. Both are deliberately thin: positioning, the outside-click listener, the
5716
+ `lr-show`/`lr-hide` events, and the initial focus move all stay in one place, so **writing `open`
5717
+ directly is fully supported and equivalent apart from the focus moves**. In particular the
5718
+ roving-tabindex reset is centralized, so a bare `el.open = false` also clears `activeIndex` and
5719
+ never leaves a stale `tabindex="0"` tab stop on the last active item. `hide()` never refocuses
5720
+ unless you ask: pass `{ focusTrigger: true }` for a dismissal with nowhere else for focus to land,
5721
+ and leave it off when the interaction that closed the menu already put focus somewhere the user
5722
+ chose (an outside click, a Tab out). Focus restoration lives in `hide()` rather than in the
5723
+ close branch precisely so teardown — disconnecting an open menu — can't steal focus.
4602
5724
 
4603
5725
  **Events:** `lr-show` (no detail — fires only when `open` transitions to `true`, not for markup
4604
5726
  that renders `open` true from the start), `lr-hide` (same first-render guard, opposite
@@ -4610,10 +5732,25 @@ returning to the trigger)
4610
5732
  are assigned; enhanced imperatively with `aria-haspopup="menu"`/`aria-expanded`/`aria-controls`
4611
5733
  since those attributes belong on the actual interactive trigger, which lives outside this
4612
5734
  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)
5735
+ dividers between groups — native `<hr>` already carries an implicit `separator` role),
5736
+ `header` and `footer` (composed, deliberately non-menu-item content — a filter/search field, a
5737
+ section title, an "Apply"/"Done" button, a count — rendered above/below the items inside
5738
+ `[part="popup"]` but **outside** the `role="menu"` list. Both collapse to no box at all while
5739
+ unfilled, so a menu that uses neither renders exactly as it did before they existed)
5740
+
5741
+ Put composed controls in `header`/`footer` rather than the default slot. Non-item content in the
5742
+ default slot still works and is not deprecated at runtime (no warning is emitted), but it sits
5743
+ inside `role="menu"`, where ARIA permits only
5744
+ `menuitem`/`menuitemradio`/`menuitemcheckbox`/`group`/`separator` children — anything else is an
5745
+ `aria-required-children` violation. It is also not Tab-reachable from an item, and needs
5746
+ `closeOnEscapeAnywhere` before Escape will close the menu. The named regions have none of those
5747
+ problems.
4614
5748
 
4615
5749
  **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)
5750
+ positioned floating panel), `header` (wrapper around the `header` slot, above the list and outside
5751
+ `role="menu"`; `display: none` while that slot is unfilled), `list` (the `role="menu"` container
5752
+ wrapping the default slot), `footer` (wrapper around the `footer` slot, below the list and outside
5753
+ `role="menu"`; `display: none` while that slot is unfilled)
4617
5754
 
4618
5755
  **Themeable custom properties:** shared tokens only (`--lr-color-surface`, `--lr-color-border`,
4619
5756
  `--lr-radius`, `--lr-shadow`, `--lr-space-xs`, `--lr-transition-fast`).
@@ -4703,11 +5840,19 @@ navigation with no separate JS bookkeeping. ArrowDown/ArrowUp *on the trigger wh
4703
5840
  opens the menu, focusing the first/last non-disabled item respectively (mirrors native `<select>`).
4704
5841
  Once open, ArrowDown/ArrowUp move the roving focus among non-disabled items and wrap past either end
4705
5842
  (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
5843
+ Enter/Space activate the focused item; Escape closes and refocuses the trigger. The arrow keys,
5844
+ Home/End, Enter/Space and type-ahead only respond when the triggering keydown event's own target is
5845
+ an actual `<lr-menu-item>` element; a keydown bubbling up from any other node inside the popup is
5846
+ ignored rather than misread as list navigation. Escape and Tab are the two deliberate exceptions.
5847
+ Escape from `header`/`footer` content always closes the menu and refocuses the trigger (mirroring
5848
+ `lr-popover`'s handling of arbitrary popup content), while Escape from non-item content in the
5849
+ *default* slot closes it only with `closeOnEscapeAnywhere` set. Tab never traps focus and never
5850
+ calls `preventDefault()` — the browser's own Tab navigation always proceeds untouched — and closes
5851
+ the menu only when focus is on its way *out* of `[part="popup"]`: with a focusable in the
5852
+ `header`/`footer` region on the far side of the keypress the menu stays open so native Tab can carry
5853
+ focus there, and with neither region filled Tab closes exactly as it always has. Tabbing past the
5854
+ popup's last focusable in either direction closes the menu, including from slotted non-item content
5855
+ — which previously left the menu open while focus walked out of the popup entirely. A printable
4711
5856
  keypress runs type-ahead: roving focus jumps to the next non-disabled item whose text starts with the
4712
5857
  accumulated buffer (cycling from just after the active item, buffer resets ~500ms after the last
4713
5858
  keystroke) — mirrors `<lr-select>`'s identical listbox type-ahead. A click outside both the trigger
@@ -4725,8 +5870,20 @@ click itself already moved focus somewhere the user chose.
4725
5870
  - `lr-menu-item-select` carries no detail payload (`event.detail === null`); read
4726
5871
  `event.target.value` instead. `<lr-menu>`'s own re-fired `lr-menu-select` is the one that
4727
5872
  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.
5873
+ - Tab never calls `preventDefault()` and never traps focus — the browser's own default Tab
5874
+ navigation always proceeds untouched. It closes the menu only when Tab would leave
5875
+ `[part="popup"]` entirely; when the `header`/`footer` region holds a focusable on the far side of
5876
+ the keypress, the menu stays open instead and native Tab moves focus into it. With neither region
5877
+ filled, Tab closes exactly as before.
5878
+ - Non-item content in the *default* slot is not Tab-reachable from an item — Tab from an
5879
+ `<lr-menu-item>` still closes the menu when there is no `header`/`footer` focusable to move to,
5880
+ even if a `<button>` is slotted alongside the items. Move such controls to `header`/`footer`.
5881
+ - `header`/`footer` emptiness is tracked from each slot's own `slotchange` and reflected on the host
5882
+ as `data-has-header` / `data-has-footer` (plus `data-list-empty`, which suppresses the region
5883
+ divider next to an empty list). They are internal styling hooks, not public API — don't set them
5884
+ by hand — but they are why `[part="header"]`/`[part="footer"]` collapse cleanly: a
5885
+ `[part]:empty` rule can never match a part that contains a slot, since Chromium counts the
5886
+ whitespace-only text nodes Lit leaves there.
4730
5887
  - Only Escape and a committed selection refocus the trigger on close; a click outside does not.
4731
5888
 
4732
5889
  ---
@@ -4842,14 +5999,19 @@ to `<wa-card>`'s contract, staying slot-compatible with `lr-result-card` where t
4842
5999
  for a quiet brand-tinted background; `'filled-outlined'` keeps the border and adds that same tinted
4843
6000
  background; `'accent'` drops the border for a single colored accent stripe on the leading edge;
4844
6001
  `'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.
6002
+ - `interactive: boolean = false` (reflected) — opt-in clickable-tile behavior: the hover/focus-visible
6003
+ treatment (border-color shift, `cursor: pointer`) plus, when `href` is **not** also set, real
6004
+ activation semantics `[part='base']` becomes focusable (`tabindex="0"`), responds to
6005
+ Enter/Space, and emits `lr-card-activate`. With `href` set, the root is already a real `<a>`, so
6006
+ native navigation *is* the activation and `lr-card-activate` never fires. `false` (the default)
6007
+ reproduces a plain static card: no `tabindex`, no listeners, no events.
4849
6008
  - `href?: string` — when set, the card's root renders as a real `<a href=...>` instead of a `<div>`,
4850
6009
  for a whole-card link (e.g. a wide CTA tile). Unset (the default) renders a plain `<div>`.
4851
6010
 
4852
- **Events:** none.
6011
+ **Events:** `lr-card-activate` (no detail) — the whole card was activated, by click or by
6012
+ Enter/Space while `[part='base']` has focus. Only fired while `interactive` is set **without**
6013
+ `href`. Never fired for an interaction that originated in a slotted control, so a card can keep its
6014
+ own action buttons (see the gotchas below).
4853
6015
 
4854
6016
  **Slots:** default (the card body), `header` (header row content, rendered above the body), `media`
4855
6017
  (media content, e.g. an image, rendered above the header), `footer` (footer content, rendered below
@@ -4883,6 +6045,22 @@ the `footer` slot, hidden entirely when empty).
4883
6045
  - slot-presence (`header`/`media`/`footer`/`actions`) is tracked in JS, not via CSS `:empty` (a
4884
6046
  `[part]` wrapper always contains a literal `<slot>` child, so `:empty` never matches) — the same
4885
6047
  pattern `lr-empty`/`lr-widget` use.
6048
+ - **an `interactive` card without `href` deliberately carries no `role="button"`.** A card is a
6049
+ *container* — it routinely holds slotted buttons and links — and `role="button"` around focusable
6050
+ descendants is the `nested-interactive` accessibility violation this library's own a11y gate
6051
+ enforces. (`lr-chip`'s `toggleable` mode *can* carry `role="button"` because it forbids focusable
6052
+ children outright.) The consequence is that the card is announced as a plain focusable region, so
6053
+ give it your own `aria-label` when the content doesn't already name it.
6054
+ - because there is no `role="button"` to disambiguate, "did the user aim at the card or at a control
6055
+ inside it?" is answered at event time: the composed path from the original target up to
6056
+ `[part='base']` is walked, and `lr-card-activate` is suppressed if anything along the way is
6057
+ itself a control (a link, `button`, `input`, `select`, `textarea`, `label`, `summary`,
6058
+ `contenteditable`, anything carrying a `tabindex` other than `-1`, or an ARIA widget role such as
6059
+ `button`/`link`/`checkbox`/`switch`/`radio`/`menuitem`/`option`/`tab`/`textbox`/`slider`/
6060
+ `spinbutton`). Using the *composed*
6061
+ path is what makes this work through a slotted component's own shadow root — a click on
6062
+ `<lr-button>` retargets to the host, but its composed path still contains the internal native
6063
+ `<button>`.
4886
6064
 
4887
6065
  ---
4888
6066
 
@@ -4895,10 +6073,13 @@ dismissal, ref-counted document scroll lock).
4895
6073
  **Properties:**
4896
6074
  - `open: boolean = false` (reflected)
4897
6075
  - `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.
6076
+ keywords?, disabled?, icon?, onSelect? }`. `icon` is an optional leading glyph (a `TemplateResult`,
6077
+ an emoji string, etc. not restricted to a square icon) rendered in the `icon` part before the
6078
+ label; a command with no `icon` renders no `icon` part at all. Filtering is case-insensitive
6079
+ substring matching over `label` + `description` + `group` + `keywords` joined together (not
6080
+ fuzzy/subsequence), memoized per `commands` array identity — reassign the array, never mutate it
6081
+ in place. Consecutive commands sharing a `group` render one `[part='group']` heading, so pre-sort
6082
+ by group yourself.
4902
6083
  - `shortcut: string = 'mod+k'` — global toggle chord parsed as `+`-separated parts; `mod` resolves to
4903
6084
  Cmd on Mac and Ctrl elsewhere. The listener is on `window`, added in `connectedCallback`.
4904
6085
  - `accessibleLabel: string = ''` (attribute `aria-label`) — overrides the localized dialog name
@@ -4917,13 +6098,21 @@ fired before the command's own `onSelect` runs and before the palette closes).
4917
6098
 
4918
6099
  **CSS parts:** `backdrop`, `dialog` (the `role="dialog" aria-modal="true"` panel), `search` (the
4919
6100
  input row), `input` (the `type="search"` field), `list` (the `role="listbox"`), `group` (a group
4920
- heading), `command` (a `role="option"` button), `description`, `shortcut`, `empty`.
6101
+ heading), `command` (a `role="option"` button), `icon` (a command's leading icon glyph; only
6102
+ rendered when the command has one), `description`, `shortcut`, `empty`.
4921
6103
 
4922
6104
  **Themeable custom properties:** `--lr-command-palette-z-index` (default
4923
6105
  `var(--lr-overlay-stack-index, var(--lr-layer-modal))`), `--lr-command-palette-offset-block-start`
4924
6106
  (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).
6107
+ (default `var(--lr-size-48rem)`), `--lr-command-palette-max-block-size` (default `70vh`),
6108
+ `--lr-command-palette-list-max-block-size` (default `50vh` — the scrolling result list), and
6109
+ `--lr-command-palette-active-bg` (default `var(--lr-color-brand-quiet)` — the background of the
6110
+ active, keyboard-highlighted command row). That last one is an inline `var()` fallback at the point
6111
+ of use rather than a `:host` declaration, so it can be set on the element *or on any ancestor*:
6112
+ `::part(command)[data-active='true']` is invalid CSS (Shadow Parts forbids an attribute selector
6113
+ after `::part()`), so highlighting the active row previously required hijacking the library-wide
6114
+ `--lr-color-brand-quiet` token and repainting everything else that read it. Unset, it falls back to
6115
+ that token, so rendering is unchanged.
4927
6116
 
4928
6117
  ## `lr-details`, `lr-accordion`, and `lr-accordion-item`
4929
6118
 
@@ -4954,6 +6143,15 @@ its label.
4954
6143
  **CSS parts:** breadcrumb `base` (the `<nav>`) and `list` (the `role="list"` flex row wrapping the
4955
6144
  slotted items); item `base` (the `<a>` or `<span>`).
4956
6145
 
6146
+ **Themeable custom properties:** `--lr-breadcrumb-current-color` (default
6147
+ `var(--lr-color-text-quiet)`) — text color of the current-page item (`current`/`aria-current="page"`).
6148
+ It is an inline `var()` fallback at the point of use rather than a `:host` declaration, so it can be
6149
+ set on the item, on `<lr-breadcrumb>`, or on any ancestor above the trail:
6150
+ `::part(base)[aria-current='page']` is invalid CSS (Shadow Parts forbids an attribute selector after
6151
+ `::part()`), so tinting the current item previously meant overriding the library-wide
6152
+ `--lr-color-text-quiet` token and repainting everything else that read it. Unset, it falls back to
6153
+ that token.
6154
+
4957
6155
  ## `lr-dashboard-grid`
4958
6156
 
4959
6157
  Responsive, keyboard-accessible controlled widget grid. It positions layout entries and emits
@@ -4975,7 +6173,10 @@ false` (reflected — disables every gesture grid-wide), `accessibleLabel: strin
4975
6173
  **Themeable custom properties:** `--lr-dashboard-grid-columns`, `--lr-dashboard-grid-row-height`,
4976
6174
  and `--lr-dashboard-grid-gap` back the CSS Grid's `grid-template-columns`/`grid-auto-rows`/`gap`.
4977
6175
  The `columns`/`rowHeight`/`gap` properties write them inline on `[part='base']` on every render, so
4978
- overriding them from a stylesheet has no effect — set the properties instead.
6176
+ overriding them from a stylesheet has no effect — set the properties instead. `--lr-dashboard-grid-cell-hover-outline-color`
6177
+ (default `var(--lr-color-border-strong)`) retints the mouse-hover outline on `[part='cell']` — a
6178
+ preview of its own `:focus-visible` ring, shown because every cell is a real focusable,
6179
+ draggable/resizable target; set it to `transparent` to opt out of the hover treatment entirely.
4979
6180
 
4980
6181
  ## `lr-drilldown-panel`
4981
6182
 
@@ -5000,6 +6201,29 @@ Dashboard filter row that composes Lyra inputs and removable chips, with reset a
5000
6201
  `lr-validity-change`. **CSS parts:** `base`, `controls`, `filter-control`, `active-filters`,
5001
6202
  `chips`, `chip`, `reset-button`, `status`.
5002
6203
 
6204
+ Each filter definition's `type` selects which existing Lyra input renders it — this component
6205
+ composes them and never invents a control of its own. `'select'`/`'combobox'` map to their
6206
+ same-named counterparts (with `combobox`'s `multiple` opting into a multi-value filter),
6207
+ `'date'`/`'date-range'` both map to `<lr-date-input>` (single vs. `mode="range"`), and `'text'` maps
6208
+ to `<lr-input>` for an open-ended free-text query rather than a closed choice set. A `'text'`
6209
+ filter's value is the raw query string, verbatim, and its chip shows exactly that string — the same
6210
+ text the user typed, not a truncated or normalized form.
6211
+
6212
+ A `'text'` filter is the one control that is **not** a fully controlled `.value=` binding.
6213
+ Re-rendering a text field from `value` mid-typing would push a stale value back in and drop the
6214
+ caret to the end, so the field owns its own value while the user types, and an external `value`
6215
+ write is synced back into it only once no edit is in flight (a host write, a chip removal, and
6216
+ `reset()` all take that path).
6217
+
6218
+ `'text'` filters also accept an optional per-filter `debounce` (ms) — how long to wait after the
6219
+ last keystroke before committing the typed value to `value` and emitting a single `lr-input`, so a
6220
+ server-side query runs once per pause instead of once per character. Omitted, `0`, or a non-finite
6221
+ value means no debounce at all: every keystroke commits immediately. A pending debounce is always
6222
+ **flushed** by the field's own `change`/blur, so a blur never loses the last keystroke, and
6223
+ **cancelled outright** by `reset()`, by removing that filter's chip, and on disconnect — a stale
6224
+ keystroke can never overwrite a reset or fire after teardown. `debounce` is ignored for every other
6225
+ `type`, whose commits are discrete choices with nothing to debounce.
6226
+
5003
6227
  # Overlays, status & feedback (`components/overlays/`)
5004
6228
 
5005
6229
  ## `lr-toast` / `lr-toast-item` / `toast()`
@@ -5134,8 +6358,11 @@ attribute), `description` (rich description content, overrides the `description`
5134
6358
 
5135
6359
  **Themeable custom properties:** `--lr-empty-compact-align` (compact mode only; defaults preserve
5136
6360
  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`).
6361
+ `--lr-empty-compact-padding` (default `--lr-space-xs` — padding used in compact mode),
6362
+ `--lr-empty-compact-gap` (default `--lr-space-2xs` — gap between the icon, heading, and description
6363
+ in compact mode; the non-compact layout's gap stays the plain shared `--lr-space-s` token, not
6364
+ independently themeable), plus shared tokens (`--lr-space-xs/-s/-l`,
6365
+ `--lr-color-text-quiet/-border/-text`).
5139
6366
 
5140
6367
  **Optional peer deps:** none.
5141
6368
 
@@ -5423,7 +6650,7 @@ already follow.
5423
6650
  ### `lr-chip`
5424
6651
 
5425
6652
  **Properties:**
5426
- - `size: '2xs' | 'xs' | 's' | 'm' | 'l' | 'xl' = 'm'` (reflected) — standard visual-density
6653
+ - `size: '3xs' | '2xs' | 'xs' | 's' | 'm' | 'l' | 'xl' = 'm'` (reflected) — standard visual-density
5427
6654
  scale for typography, padding, gap, and icon size; `m` preserves the original chip dimensions
5428
6655
  - `tone: 'neutral' | 'brand' | 'success' | 'warning' | 'danger' = 'neutral'` (reflected — tints the
5429
6656
  whole pill using a loud-color-on-quiet-tint convention; `neutral` has no dedicated token pair, so
@@ -5472,12 +6699,30 @@ back to `--lr-chip-bg`), the density quintet `--lr-chip-font-size`, `--lr-chip-p
5472
6699
  `--lr-chip-padding-inline`, `--lr-chip-gap`, `--lr-chip-icon-size` (all five are rewritten by each
5473
6700
  `:host([size])` rule, so setting one directly on the element overrides that step of the scale; the
5474
6701
  `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`,
6702
+ `--lr-font-size-sm`), the height pair `--lr-chip-min-height` / `--lr-chip-height` (below),
6703
+ plus shared tokens (`--lr-space-xs`, `--lr-space-s`,
5476
6704
  `--lr-color-brand`/`-brand-quiet`, `--lr-color-success`/`-success-quiet`,
5477
6705
  `--lr-color-warning`/`-warning-quiet`, `--lr-color-danger`/`-danger-quiet`,
5478
6706
  `--lr-icon-button-size`, `--lr-focus-ring-width`, `--lr-focus-ring-color`,
5479
6707
  `--lr-focus-ring-offset`, `--lr-transition-fast`).
5480
6708
 
6709
+ **Chip height — a floor and an exact cap:**
6710
+
6711
+ - `--lr-chip-min-height` (default `--lr-size-1-5rem`) floors an **interactive** chip only — one in
6712
+ toggle mode or with `removable` set. `2xs`/`xs`/`s`/`m` all share that `1.5rem` value because it
6713
+ is the 24px WCAG 2.2 SC 2.5.8 target minimum and an interactive chip must never shrink below it;
6714
+ `l` and `xl` raise it to their own taller floors. A passive display chip takes no floor from
6715
+ this at all, and every default sits below the chip's own content-driven height, so the floor is
6716
+ invisible until you raise it.
6717
+ - `--lr-chip-height` pins an **exact** height on `[part='base']` — interactive and passive chips
6718
+ alike — so a row of chips can line up with a sibling control of a known height. It is
6719
+ **undeclared by default**, which is what keeps the per-tier floor alive: `auto` is a valid
6720
+ declared value that would win over the `var()` fallback arm and make `--lr-chip-min-height` dead
6721
+ code, so never set it to `auto` — remove the declaration instead. Because the component never
6722
+ declares it, it can be set inline, from an ancestor, or from an outer-tree rule.
6723
+ **A value below 24px is for non-interactive display chips only**; pinning an interactive chip
6724
+ that short breaks its tap target.
6725
+
5481
6726
  **Optional peer deps:** none.
5482
6727
 
5483
6728
  ```html
@@ -5732,7 +6977,10 @@ period, shared with `lr-progress-bar`'s sweep).
5732
6977
 
5733
6978
  ## `lr-badge` and `lr-tag`
5734
6979
 
5735
- Compact status labels. Both expose `variant: 'neutral' | 'brand' | 'success' | 'warning' | 'danger'`.
6980
+ Compact status labels. Both expose `variant: 'neutral' | 'brand' | 'success' | 'warning' | 'danger'`
6981
+ and `size: '2xs' | 'xs' | 's' | 'm' | 'l' | 'xl' = 'm'` (reflected) — the same visual-density scale
6982
+ `<lr-chip>` uses, for typography/padding/minimum block size; `m` preserves the original badge
6983
+ dimensions. `lr-tag` inherits `size` unchanged from `lr-badge` rather than redeclaring it.
5736
6984
  The two tags share the same visual contract; `lr-tag` is a semantic alias for migration-friendly
5737
6985
  markup.
5738
6986
 
@@ -5742,6 +6990,10 @@ markup.
5742
6990
  — the trio each `:host([variant])` rule rewrites (`neutral` defaults to
5743
6991
  `--lr-color-surface`/`-text`/`-border`; the other four to the matching `*-quiet` fill with the loud
5744
6992
  color for text and border). Set one directly on the element for a tint outside the five variants.
6993
+ `--lr-badge-font-size` (default `var(--lr-font-size-sm)`), `--lr-badge-padding-inline` (default
6994
+ `var(--lr-space-s)`), and `--lr-badge-min-height` (default `var(--lr-size-1-25rem)`) — the density
6995
+ trio each `:host([size])` rule rewrites to that step's font size, inline padding, and minimum block
6996
+ size; the `m` defaults above exactly reproduce the pre-`size` fixed badge treatment.
5745
6997
 
5746
6998
  ## `lr-callout`
5747
6999
 
@@ -5767,7 +7019,12 @@ visible "×" glyph inside it — this is what shrinks under `inline`, so the hit
5767
7019
  **Themeable custom properties:** `--lr-callout-background`, `--lr-callout-color`,
5768
7020
  `--lr-callout-border` — the trio each `:host([variant])` rule rewrites (same
5769
7021
  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.
7022
+ background, and panel padding regardless of what these are set to. `--lr-callout-close-hover-bg`
7023
+ (default `var(--lr-color-brand-quiet)`) — the close button's `:hover` background, deliberately
7024
+ decoupled from `--lr-callout-background` (which every non-neutral `variant` also retargets for the
7025
+ panel itself) so a consumer can retint the hover fill — e.g. to keep it visibly distinct from a
7026
+ `variant="brand"` panel, which shares the same default token — without a collateral effect on the
7027
+ panel background, and vice versa.
5771
7028
 
5772
7029
  ## `lr-rating`
5773
7030
 
@@ -5820,7 +7077,10 @@ built-in download completes), `lr-show`, `lr-hide` (format-menu visibility trans
5820
7077
 
5821
7078
  **CSS parts:** `trigger`, `menu`, `menu-item`, `format-label`, `format-description`
5822
7079
 
5823
- **Themeable custom properties:** shared tokens only.
7080
+ **Themeable custom properties:** shared tokens only, including `--lr-popover-viewport-clamp`
7081
+ (default `92vw`) — the shared narrow-viewport ceiling the `menu`'s max-inline-size is `min()`ed
7082
+ against, alongside its own `20rem` cap and the positioner's available space. See `lr-tour` for the
7083
+ shared-clamp note.
5824
7084
 
5825
7085
  **Optional peer deps:** none.
5826
7086
 
@@ -6011,9 +7271,12 @@ clipboard") or a per-node one (aria-label `Copy ${key/type}`, e.g. "Copy age");
6011
7271
  `copyable`)
6012
7272
 
6013
7273
  **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`,
7274
+ until `max-height` is set), `--lr-json-viewer-font` (default `var(--lr-font-mono)`),
7275
+ `--lr-json-viewer-match-bg` (default `var(--lr-color-warning-quiet)`) background, and surrounding
7276
+ box-shadow, of a key/value that currently matches `search`. Component-scoped indirection over the
7277
+ shared `--lr-color-warning-quiet` token, so a consumer can retheme just this search-match highlight
7278
+ without repainting every other warning-toned surface that reads the same shared token. Plus shared
7279
+ tokens `--lr-color-border/-surface/-text/-text-quiet/-brand/-brand-quiet/-success/-warning/-warning-quiet`,
6017
7280
  `--lr-radius`, `--lr-space-xs/-s/-l`, `--lr-focus-ring-width/-color/-offset`,
6018
7281
  `--lr-transition-fast`.
6019
7282
 
@@ -6166,7 +7429,11 @@ button).
6166
7429
  **CSS parts:** `base`, `indicator` (the pulsing status dot), `countdown` (the `M:SS`, or
6167
7430
  "Refreshing…", text), `pause-button` (the built-in pause/resume toggle).
6168
7431
 
6169
- **Themeable custom properties:** shared tokens only — `--lr-space-xs`, `--lr-font-size-sm`,
7432
+ **Themeable custom properties:** `--lr-poll-status-due-bg` (default `var(--lr-color-success)`) —
7433
+ background of `indicator` while `data-due` is set. Component-scoped indirection over the shared
7434
+ `--lr-color-success` token, so a consumer can retheme just this due-state indicator without
7435
+ repainting every other component that reuses the same shared success token. Plus shared tokens —
7436
+ `--lr-space-xs`, `--lr-font-size-sm`,
6170
7437
  `--lr-color-text-quiet`, `--lr-color-brand`, `--lr-color-success`, `--lr-radius`/`-pill`,
6171
7438
  `--lr-focus-ring-*`.
6172
7439
 
@@ -6256,12 +7523,19 @@ renders `open="false"` on first paint)
6256
7523
  **CSS parts:** `listbox`, `option`, `option-icon` (when `icon` is set), `option-label`,
6257
7524
  `option-description` (when `description` is set), `empty`
6258
7525
 
6259
- **Themeable custom properties:** shared tokens only — `--lr-space-xs`/`-s`/`-m` (popup padding,
7526
+ **Themeable custom properties:** `--lr-mention-popover-option-active-bg` (default
7527
+ `var(--lr-color-brand-quiet)`) — background of the hovered or `[data-active]`
7528
+ (keyboard-highlighted) suggestion row. Component-scoped indirection over the shared
7529
+ `--lr-color-brand-quiet` token, so a consumer can retheme just this highlighted/active row without
7530
+ repainting every other component that reuses the same shared token. Plus shared tokens —
7531
+ `--lr-space-xs`/`-s`/`-m` (popup padding,
6260
7532
  row padding/gap), `--lr-color-surface`/`-border` (popup background/border), `--lr-radius`
6261
7533
  (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
7534
+ transition), `--lr-color-brand` (selected-row
6263
7535
  text), `--lr-color-text-quiet`/`--lr-color-text` (description text, full-contrast on the active
6264
- row).
7536
+ row), and `--lr-popover-viewport-clamp` (default `92vw`) — the shared narrow-viewport ceiling the
7537
+ popup's max-inline-size is `min()`ed against, alongside its own `24rem` cap and the positioner's
7538
+ available space. See `lr-tour` for the shared-clamp note.
6265
7539
 
6266
7540
  **Optional peer deps:** none.
6267
7541
 
@@ -6585,12 +7859,31 @@ block, repeated three times, `data-field="day"|"month"|"year"`), `field-input` (
6585
7859
  small per-field text label), `hint`, `error` (`role="alert"`).
6586
7860
 
6587
7861
  **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`),
7862
+ `--lr-known-date-field-padding-inline`, `--lr-known-date-field-font-size`,
7863
+ `--lr-known-date-field-min-height` (all four rewritten by
7864
+ each `:host([size])` rule; `m` defaults `--lr-space-s`/`--lr-space-s`/`--lr-font-size-md-sm`/
7865
+ `--lr-size-2-5rem`), `--lr-known-date-field-height`,
6590
7866
  `--lr-known-date-field-gap` (default `--lr-space-s` — gap between the three field blocks),
6591
7867
  `--lr-known-date-day-field-width` / `--lr-known-date-month-field-width` (default `--lr-size-3-5em`)
6592
7868
  and `--lr-known-date-year-field-width` (default `--lr-size-5em`) — the per-field input widths, not
6593
- size-scaled.
7869
+ size-scaled. `--lr-known-date-invalid-border-color` (default `var(--lr-color-danger)`) — border
7870
+ color of each `field-input` while `:host([data-invalid])` is set. Component-scoped indirection over
7871
+ the shared `--lr-color-danger` token, so a consumer can retheme just this invalid-field border
7872
+ without repainting every other component that reads the same shared danger token.
7873
+
7874
+ The two height knobs work as a pair on `[part='field-input']`, the same way
7875
+ `lr-input`/`lr-select`/`lr-combobox`/`lr-date-input` expose theirs:
7876
+
7877
+ - `--lr-known-date-field-min-height` is a **floor**, re-assigned per `size` tier. Every tier's
7878
+ default sits below the field's own padding/font-driven height, so raising it is what makes it
7879
+ visible; lowering it changes nothing.
7880
+ - `--lr-known-date-field-height` pins an **exact** height (both floors and caps), so the three
7881
+ inputs can line up with a neighbouring control of a known height. It is **undeclared by
7882
+ default** — the field grows to fit its content. Never set it to `auto`: `auto` is a valid
7883
+ declared value that wins over the `var()` fallback arm, which would make the per-tier floor
7884
+ dead code. To go back to the default behavior, remove the declaration rather than neutralizing
7885
+ it. Because the component never declares it, it can be set inline, from an ancestor, or from an
7886
+ outer-tree rule.
6594
7887
 
6595
7888
  **Known gotchas:**
6596
7889
  - Field *order* is derived from the locale by formatting a probe date (Jan 2 2026) with
@@ -6727,7 +8020,17 @@ label switches to Done on the last step).
6727
8020
  `--lr-tour-spotlight-radius` (default `--lr-radius` — shared by the cutout and the ring),
6728
8021
  `--lr-tour-spotlight-ring-color` (default `--lr-color-brand`), `--lr-tour-spotlight-ring-width`
6729
8022
  (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).
8023
+ further capped by `--lr-popover-viewport-clamp` and the positioner's available space),
8024
+ `--lr-tour-progress-dot-current-bg` (default `var(--lr-color-brand)`) — background of
8025
+ `progress-dot` for the current step. Component-scoped indirection over the shared `--lr-color-brand`
8026
+ token, so a consumer can retheme just the current-step dot without repainting every other component
8027
+ that reuses the same shared brand token.
8028
+
8029
+ `--lr-popover-viewport-clamp` (default `92vw`, from `--lr-theme-popover-viewport-clamp`) is the
8030
+ shared ceiling that keeps any floating surface inside a narrow viewport. `lr-tour`,
8031
+ `lr-mention-popover`, and `lr-export-button` all `min()` their own max-inline-size against it, so
8032
+ retuning `--lr-theme-popover-viewport-clamp` once at `:root` narrows or widens all three together
8033
+ rather than per component.
6731
8034
 
6732
8035
  **Known gotchas:**
6733
8036
  - By default the spotlighted target is **non-interactive**: it stays visible and announceable (not
@@ -6800,7 +8103,49 @@ installed, renders an empty template (see gotchas).
6800
8103
  Also exported from the package root:
6801
8104
  `languageToCountry(language: string): string | undefined` and the `LANGUAGE_TO_COUNTRY` lookup
6802
8105
  table (region subtag wins, e.g. `en-US` → `us`; plain `en` → `gb`; override the table per-app if you
6803
- need different defaults).
8106
+ need different defaults), plus `localeNativeName(tag: string): string`.
8107
+
8108
+ `localeNativeName()` returns a BCP-47 tag's **endonym** — the locale's name written in that locale
8109
+ itself (`'fr'` → `français`, `'pt-BR'` → `português (Brasil)`). That is what a language switcher
8110
+ should list, so a reader who understands none of the current UI language can still find their own.
8111
+ It derives from `Intl.DisplayNames`, so no name table ships with the library and results follow the
8112
+ browser's own ICU data; the underlying instance comes from a shared memoized cache, since a picker
8113
+ does one lookup per offered locale on every render pass. A tag with no display name resolves to the
8114
+ tag itself, and so does a structurally invalid one — `Intl.DisplayNames` throws a `RangeError` on
8115
+ those rather than falling back, and a language picker should degrade to showing the raw tag rather
8116
+ than tearing down the render. Pair it with `languageToCountry()` for the flag half of the same row.
8117
+
8118
+ **Locale picker recipe.** `<lr-locale-picker>` (`components/forms/locale-picker/`) is the built-in
8119
+ locale switcher — a closed-list dropdown over the locale registry or an explicit catalog, with
8120
+ `lr-flag`/`localeNativeName()` rows and full form association out of the box. The manual
8121
+ composition below remains available for an app that wants different chrome (its own dismiss
8122
+ surface, a different active-state marker, or a layout `<lr-locale-picker>` doesn't offer):
8123
+ `<lr-popover>` supplies the light-dismiss surface, `<lr-flag>` the country mark,
8124
+ `localeNativeName()` the endonym, and `aria-current="true"` marks the active choice. Which locales
8125
+ exist is the app's decision, so the app owns the list. Set `lang` on each row so assistive tech
8126
+ pronounces the endonym in its own language, and use `variant="compact"` at icon scale.
8127
+
8128
+ ```html
8129
+ <lr-popover placement="bottom-start">
8130
+ <button slot="trigger">
8131
+ <lr-flag language="fr" label="" style="height: 1rem"></lr-flag>
8132
+ <span>français</span>
8133
+ </button>
8134
+ <ul role="list">
8135
+ <!-- one <li><button lang="pt-BR" aria-current="false"> … </button></li> per offered locale -->
8136
+ </ul>
8137
+ </lr-popover>
8138
+ ```
8139
+
8140
+ ```js
8141
+ import { localeNativeName, languageToCountry } from '@aceshooting/lyra-ui';
8142
+
8143
+ const rows = ['en', 'fr', 'de', 'pt-BR', 'ja', 'ar'].map((tag) => ({
8144
+ tag,
8145
+ name: localeNativeName(tag), // endonym, e.g. "português (Brasil)"
8146
+ country: languageToCountry(tag), // flag code for the same row
8147
+ }));
8148
+ ```
6804
8149
 
6805
8150
  ```html
6806
8151
  <lr-flag country="fr" label="France"></lr-flag>
@@ -6982,7 +8327,9 @@ exists and was hit)
6982
8327
 
6983
8328
  **Slots:** none.
6984
8329
 
6985
- **CSS parts:** `base`, `container`, `legend`, `legend-swatch`
8330
+ **CSS parts:** `base`, `container`, `legend`, `legend-swatch`, `error` (`role="alert"` message
8331
+ rendered in place of `container` if the optional `maplibre-gl` peer dependency fails to load, e.g.
8332
+ not installed)
6986
8333
 
6987
8334
  **Themeable custom properties:** shared tokens only — `--lr-space-xs/-s`, `--lr-color-surface`,
6988
8335
  `--lr-color-border`, `--lr-shadow`, `--lr-radius`.
@@ -7059,6 +8406,10 @@ parsing (that's left entirely to the host).
7059
8406
  - `maxFileSize: number = 0` (attribute `max-file-size` — bytes; `0` disables the check)
7060
8407
  - `directory: boolean = false` (reflected) — enables native directory selection where supported
7061
8408
  - `paste: boolean = true` (reflected) — accepts files pasted into the dropzone
8409
+ - `compact: boolean = false` (reflected) — tighter dropzone padding, gap and label font for
8410
+ constrained spaces (a toolbar, a table cell) — the same convention as `lr-empty`'s `compact`. The
8411
+ dashed border stays; only the internal spacing shrinks. `false` (the default) keeps the full
8412
+ `--lr-space-l` dropzone.
7062
8413
  - `label: string = 'Drop files here or click to browse'`
7063
8414
  - `accessibleLabel: string = ''` (attribute `aria-label`) — overrides `label` as the internal
7064
8415
  dropzone/button accessible name without changing visible copy
@@ -7085,9 +8436,22 @@ announces correctly.
7085
8436
  **CSS parts:** `base`, `input`, `status` (a visually-hidden `role="status" aria-live="polite"`
7086
8437
  element carrying the drag accept/reject announcement)
7087
8438
 
7088
- **Themeable custom properties:** shared tokens only — `--lr-space-xs`, `--lr-space-l`,
8439
+ **Themeable custom properties:** `--lr-file-input-compact-padding` (default `var(--lr-space-s)`) —
8440
+ `[part='base']`'s padding while `compact`; `--lr-file-input-compact-gap` (default
8441
+ `var(--lr-space-2xs)`) — the gap between the dropzone's slotted children while `compact`; and
8442
+ `--lr-file-input-compact-font-size` (default `var(--lr-font-size-sm)`) — the label's font size while
8443
+ `compact`. All three apply only while `compact` is set, so they are the way to tune a dense dropzone
8444
+ without re-pointing shared spacing tokens for everything else on the page. The drag accept/reject
8445
+ highlight on `[part='base'][data-drag-state='accept'|'reject']` is independently overridable too:
8446
+ `--lr-file-input-accept-border-color` (default `var(--lr-color-success)`) and
8447
+ `--lr-file-input-accept-bg` (default `color-mix(in srgb, var(--lr-color-success) 8%, transparent)`)
8448
+ for the drag-accept state; `--lr-file-input-reject-border-color` (default `var(--lr-color-danger)`)
8449
+ and `--lr-file-input-reject-bg` (default `color-mix(in srgb, var(--lr-color-danger) 8%,
8450
+ transparent)`) for drag-reject. All four are inline `var()` fallbacks at the point of use, settable
8451
+ on the element or any ancestor, so a consumer can retint just this dropzone's drag highlight without
8452
+ hijacking the shared `--lr-color-success`/`--lr-color-danger` tokens used elsewhere. Plus shared
8453
+ tokens — `--lr-space-xs`, `--lr-space-l`,
7089
8454
  `--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
8455
  `--lr-focus-ring-width/-color/-offset` (`[part="base"]:focus-visible` outline),
7092
8456
  `--lr-opacity-disabled` (`:host([disabled])` dimming).
7093
8457
 
@@ -7375,6 +8739,11 @@ final.
7375
8739
  overrides the `--lr-media-card-max-height` custom property for this instance only (applied
7376
8740
  inline on `[part="base"]`, so it reliably wins over a `:host{}`-declared default from outside the
7377
8741
  shadow root) — same contract as `<lr-document-preview>`'s identically-named prop.
8742
+ - `appearance: 'card' | 'plain' = 'card'` (reflected) — visual chrome, mirroring
8743
+ `<lr-source-card>`'s `appearance` vocabulary. `'card'` (the default) keeps the bordered, filled
8744
+ box. `'plain'` removes `[part="base"]`'s border, background, padding, and corner radius, so a
8745
+ card inside a dense chat transcript (or any container already drawing its own separation between
8746
+ attachments) doesn't double the frame.
7378
8747
 
7379
8748
  **Events:** `lr-open` (`detail: { src: string; filename: string }`, cancelable) — fired when the
7380
8749
  card (or, for `kind="video"`, its separate `open-button`) is activated. `detail.src` is whichever
@@ -7564,8 +8933,12 @@ initials text, rendered whenever neither `icon` nor `image` is).
7564
8933
  **Themeable custom properties:** `--lr-avatar-size` (default `2rem`, swapped to `1.5rem`/`2.5rem`
7565
8934
  per `size="sm"`/`"lg"`), `--lr-avatar-bg` (default `var(--lr-color-surface-alt,
7566
8935
  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`.
8936
+ `var(--lr-color-text)`, swapped per `tone`), `--lr-avatar-font-size` (default
8937
+ `var(--lr-font-size-sm)`) — the font size of the initials fallback, and of any `em`-sized slotted
8938
+ glyph. `size` swaps it per tier too (`var(--lr-font-size-xs)` at `sm`, `var(--lr-font-size-md)` at
8939
+ `lg`), so the initials track the circle instead of staying one fixed size across every tier;
8940
+ override it on the element for a size the built-in scale doesn't cover. Plus shared tokens
8941
+ `--lr-radius`/`-pill`, `--lr-font-size-sm`, `--lr-font-weight-semibold`.
7569
8942
 
7570
8943
  **Optional peer deps:** none.
7571
8944
 
@@ -7735,7 +9108,12 @@ under `dir="rtl"` — setting `0` or a positive length turns the stack into norm
7735
9108
  `--lr-avatar-group-ring-color` (default `var(--lr-color-surface)`),
7736
9109
  `--lr-avatar-group-ring-width` (default `var(--lr-border-width-medium)`),
7737
9110
  `--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`).
9111
+ `--lr-avatar-group-badge-color` (default `var(--lr-color-text)`, swapped per `tone`),
9112
+ `--lr-avatar-group-badge-font-size` (default `var(--lr-font-size-sm)`) — the font size of the "+N"
9113
+ badge label. `size` swaps it per tier (`var(--lr-font-size-xs)` at `sm`, `var(--lr-font-size-md)` at
9114
+ `lg`), matching `<lr-avatar>`'s own `--lr-avatar-font-size` scale so the badge and the avatars it
9115
+ caps read at the same optical weight; override it alongside `--lr-avatar-font-size` on the avatars
9116
+ themselves when tuning a custom tier.
7739
9117
 
7740
9118
  **Optional peer deps:** none.
7741
9119
 
@@ -7843,7 +9221,12 @@ documents) and `<lr-image-comparer>` (before/after slotted surfaces). Adopts `Do
7843
9221
  with `anchorKinds: ['region']` only — no text selection is bound.
7844
9222
 
7845
9223
  **Properties:** `src: string = ''`, `name: string = ''`, `alt?: string`, `fit: 'contain' | 'width' |
7846
- 'actual' = 'contain'` (reflected), `zoom: number = 1` (reflected), `rotation: 0 | 90 | 180 | 270 = 0`
9224
+ 'actual' = 'contain'` (reflected), `zoom: number = 1` (reflected), `minZoom: number = 0.5` (attribute
9225
+ `min-zoom`), `maxZoom: number = 4` (attribute `max-zoom`), `zoomStep: number = 0.25` (attribute
9226
+ `zoom-step`) — `minZoom`/`maxZoom`/`zoomStep` are pure pass-throughs to the embedded
9227
+ `<lr-zoomable-frame>` as its own `.minZoom`/`.maxZoom`/`.zoomStep`, which does the actual
9228
+ clamping/normalizing; same names/defaults as `<lr-lightbox>`'s identical trio, both wrapping the
9229
+ same pan/zoom surface — `rotation: 0 | 90 | 180 | 270 = 0`
7847
9230
  (reflected), and `annotatable: boolean = false` (reflected).
7848
9231
 
7849
9232
  **Methods:** `rotate()` advances `rotation` by 90°. `zoomIn()`, `zoomOut()`, and `resetZoom()` adjust
@@ -7859,6 +9242,20 @@ zoom }`), `lr-rotation-change` (`detail: { rotation }`), `lr-fit-change` (`detai
7859
9242
  embedded `lr-zoomable-frame`), `image-wrapper`, `image`, `highlight-layer`, `highlight` (carries
7860
9243
  `data-tone`/`data-active`), `highlight-label`, `annotation-box`, and `error`.
7861
9244
 
9245
+ **Themeable custom properties:** `--lr-image-viewer-annotate-active-bg` (default
9246
+ `var(--lr-color-brand-quiet)`) and `--lr-image-viewer-annotate-active-border` (default
9247
+ `var(--lr-color-brand)`) — the background and border of `[part='annotate-toggle']` while annotation
9248
+ mode is on. The toggle carries its own glyph in `--lr-color-text`, so keep a 4.5:1 ratio against it
9249
+ when overriding the background. `--lr-image-viewer-highlight-active-color` (default
9250
+ `var(--lr-color-brand)`) — the outline of the `[part='highlight']` matching `activeHighlightId`,
9251
+ independent of the per-tone border colors, so the active box stays distinguishable whatever tone it
9252
+ carries. All three are declared as inline `var()` fallbacks at the point of use rather than on
9253
+ `:host`, so each can be set on the element *or on any ancestor*: `::part(highlight)[data-active]` is
9254
+ invalid CSS — Shadow Parts forbids an attribute selector after `::part()` — which previously left
9255
+ overriding the library-wide `--lr-color-brand`/`--lr-color-brand-quiet` tokens as the only lever,
9256
+ repainting every other element that read them. Unset, each falls back to the token its rule used
9257
+ before.
9258
+
7862
9259
  ## `lr-av-player`
7863
9260
 
7864
9261
  An audio/video player built on a native `<audio>`/`<video>` element, plus a cue transcript synced to
@@ -7892,11 +9289,47 @@ found }`), `lr-search-change` (`detail: { query, matchCount, activeIndex }`), an
7892
9289
  **CSS parts:** `base`, `media` (the native `<audio>`/`<video>` element), `toolbar`, `rate-select`,
7893
9290
  `timeline` (click-to-seek and arrow-key seeking), `timeline-marker` (one per `time-range` highlight;
7894
9291
  `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`.
9292
+ `data-match`, `data-active-match`), `cue-current` (added alongside `cue` on the row the playhead is
9293
+ inside), `cue-match` (added alongside `cue` on a row matching the current search query),
9294
+ `cue-active-match` (added alongside `cue`/`cue-match` on the row holding the current match),
9295
+ `cue-time`, `cue-speaker`, `cue-text`, and `error`.
9296
+
9297
+ Every cue-level part above is rendered into the embedded `<lr-virtual-list>`'s own shadow root and
9298
+ forwarded back out through `exportparts`, so `lr-av-player::part(cue)` and friends work from a
9299
+ consumer stylesheet. The three cue states are separate part *names* rather than attribute selectors,
9300
+ because Shadow Parts forbids an attribute selector after `::part()` —
9301
+ `::part(cue)[aria-current='true']` is invalid CSS, so use `::part(cue-current)`. The `aria-current`
9302
+ and `data-*` attributes remain on each row for semantics and scripting.
7896
9303
 
7897
9304
  **Themeable custom properties:** `--lr-av-player-transcript-height` (default
7898
9305
  `var(--lr-size-16rem)` — block size of the transcript pane; forwarded to the embedded
7899
- `<lr-virtual-list>`'s own `--lr-virtual-list-height`).
9306
+ `<lr-virtual-list>`'s own `--lr-virtual-list-height`). `--lr-av-player-marker-active-color` (default
9307
+ `var(--lr-color-brand)`) — the outline of the `[part='timeline-marker']` matching
9308
+ `activeHighlightId`, leaving the per-tone marker fills alone. It is an inline `var()` fallback at
9309
+ the point of use rather than a `:host` declaration, so it can be set on the element or on any
9310
+ ancestor — `::part(timeline-marker)[data-active]` is invalid CSS (Shadow Parts forbids an attribute
9311
+ selector after `::part()`), so re-pointing the shared `--lr-color-brand` token was the only previous
9312
+ lever.
9313
+
9314
+ Each `[part='timeline-marker']`'s own background is independently overridable per tone, the same
9315
+ inline-`var()`-fallback pattern as `--lr-av-player-marker-active-color` above:
9316
+ `--lr-av-player-marker-bg` (default `color-mix(in srgb, var(--lr-color-brand) 35%, transparent)`) —
9317
+ no (or an unrecognized) `data-tone`; `--lr-av-player-marker-success-bg` (default `color-mix(in srgb,
9318
+ var(--lr-color-success) 35%, transparent)`) — `data-tone="success"`;
9319
+ `--lr-av-player-marker-warning-bg` (default `color-mix(in srgb, var(--lr-color-warning) 35%,
9320
+ transparent)`) — `data-tone="warning"`; `--lr-av-player-marker-danger-bg` (default `color-mix(in
9321
+ srgb, var(--lr-color-danger) 35%, transparent)`) — `data-tone="danger"`; and
9322
+ `--lr-av-player-marker-neutral-bg` (default `color-mix(in srgb, var(--lr-color-text) 25%,
9323
+ transparent)`) — `data-tone="neutral"`. Each can be set on the element or on any ancestor without
9324
+ hijacking the shared `--lr-color-success`/`-warning`/`-danger`/`-brand`/`-text` tokens used
9325
+ elsewhere in the theme.
9326
+
9327
+ Two further cue-state properties tint the transcript: `--lr-av-player-cue-current-bg` (default
9328
+ `var(--lr-color-brand-quiet)`) is the background of the `cue-current` row the playhead is inside,
9329
+ and `--lr-av-player-cue-active-match-color` (default `var(--lr-color-warning)`) is the outline of
9330
+ the `cue-active-match` row, leaving the other matches' dashed outline on the shared warning token.
9331
+ Both are inline `var()` fallbacks at the point of use rather than `:host` declarations, so either
9332
+ can be set on the element or on any ancestor.
7900
9333
 
7901
9334
  # Charts (`components/charts/`)
7902
9335
 
@@ -7963,7 +9396,8 @@ number, label: string | undefined, value: unknown }`)
7963
9396
  optional overlay content positioned at the chart area's center, useful for doughnut and pie totals.
7964
9397
 
7965
9398
  **CSS parts:** `base`, `canvas`, `reset-zoom-button`, `description`, `data-table`, `center` (the
7966
- chart-area-centered wrapper for the `center` slot)
9399
+ chart-area-centered wrapper for the `center` slot), `error` (`role="alert"` message rendered in
9400
+ place of `canvas` when the optional `chart.js` peer dependency fails to load)
7967
9401
 
7968
9402
  **Themeable custom properties:** `--lr-chart-height` (set programmatically on the host from the
7969
9403
  `height` property — must be read from the host, not a shadow-tree descendant, since custom
@@ -8196,7 +9630,9 @@ index, label, value }`).
8196
9630
 
8197
9631
  **Slots:** `data-table`, `center`.
8198
9632
 
8199
- **CSS parts:** `base`, `canvas`, `reset-zoom-button`, `description`, `data-table`, `center`.
9633
+ **CSS parts:** `base`, `canvas`, `reset-zoom-button`, `description`, `data-table`, `center`,
9634
+ `error` (`role="alert"` message rendered in place of `canvas` when the optional `chart.js` peer
9635
+ dependency fails to load — see `llms/components/lr-chart.md`).
8200
9636
 
8201
9637
  **Themeable custom properties:** `--lr-chart-height`, `--lr-chart-grid-color`,
8202
9638
  `--lr-chart-tick-color`, `--lr-chart-legend-color`, `--lr-chart-tooltip-bg`,
@@ -8257,7 +9693,9 @@ and `label` the generated bucket range string (`"lo–hi"`, both bounds at one d
8257
9693
 
8258
9694
  **Slots:** `data-table`, `center`.
8259
9695
 
8260
- **CSS parts:** `base`, `canvas`, `reset-zoom-button`, `description`, `data-table`, `center`.
9696
+ **CSS parts:** `base`, `canvas`, `reset-zoom-button`, `description`, `data-table`, `center`,
9697
+ `error` (`role="alert"` message rendered in place of `canvas` when the optional `chart.js` peer
9698
+ dependency fails to load — inherited from `LyraChart`, unaffected by the binning logic).
8261
9699
 
8262
9700
  **Themeable custom properties:** `--lr-chart-height`, `--lr-chart-grid-color`,
8263
9701
  `--lr-chart-tick-color`, `--lr-chart-legend-color`, `--lr-chart-tooltip-bg`,
@@ -8445,7 +9883,15 @@ SFMono-Regular, Menlo, Consolas, monospace`) and `--lr-document-preview-spin-dur
8445
9883
  `0.8s`, stopped under reduced motion). `--lr-document-preview-progress` (default `0`) — a unitless
8446
9884
  0–100 number the determinate spinner's `conic-gradient` fill reads; written inline on the ring by
8447
9885
  the component itself from the clamped `progress` property, so overriding it only makes sense to
8448
- repaint the fraction. Plus shared tokens
9886
+ repaint the fraction. `--lr-document-preview-active-border` (default
9887
+ `var(--lr-color-warning, var(--lr-color-brand))`) — the border color of the `[part='region-highlight']`
9888
+ matching `activeHighlightId` (image format only), deliberately distinct from the resting highlight
9889
+ border so the active region can be recolored without touching the rest. Like the library's other
9890
+ state hooks it is an inline `var()` fallback at the point of use rather than a `:host` declaration,
9891
+ so it can be set on the element or on any ancestor — `::part(region-highlight)[data-active]` is
9892
+ invalid CSS (Shadow Parts forbids an attribute selector after `::part()`), which previously left
9893
+ re-pointing the shared `--lr-color-warning`/`--lr-color-brand` tokens as the only lever, repainting
9894
+ every other element that read them. Plus shared tokens
8449
9895
  `--lr-color-border`, `--lr-radius`, `--lr-color-surface`, `--lr-space-s/-m/-l/-xs`,
8450
9896
  `--lr-color-text`, `--lr-color-text-quiet`, `--lr-color-danger`, `--lr-color-brand`,
8451
9897
  `--lr-color-on-brand`, `--lr-focus-ring-width/-color/-offset`, `--lr-transition-fast`.
@@ -8661,9 +10107,10 @@ localized show/hide toggle. `false` (the default) preserves the full body render
8661
10107
  **CSS parts:** `base`, `headers`, `from-label`, `from`, `to-label`, `to`, `subject-label`, `subject`,
8662
10108
  `date-label`, `date`, `body`, `body-html`, `body-text`, `attachments`, `attachments-label`,
8663
10109
  `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`.
10110
+ `attachment-item`), `attachment-name` (an attachment's filename, inside `attachment-button`),
10111
+ `attachment-size` (an attachment's formatted file size, inside `attachment-button`), `quoted` (a
10112
+ folded quoted-text block, hidden until expanded, only while `foldQuotes`), `quote-toggle` (the
10113
+ show/hide-quoted-text toggle button, only while `foldQuotes`), `spinner`, and `error`.
8667
10114
 
8668
10115
  **Themeable custom properties:** `--lr-email-viewer-max-height` (default `none`) — maximum block size
8669
10116
  of `[part="body"]`; also settable via the `max-height` property, which writes this token inline.
@@ -8710,7 +10157,13 @@ listing region as `role="region"`; with neither set, the region is unnamed.
8710
10157
 
8711
10158
  **Events:** `lr-render-error` with `detail.error` when fetching or parsing fails.
8712
10159
 
8713
- **CSS parts:** `base`, `entry`, `entry-icon`, `entry-name`, `entry-size`, `spinner`, and `error`.
10160
+ **CSS parts:** `base`, `entry`, `entry-icon`, `entry-name`, `entry-name-dir`, `entry-size`,
10161
+ `spinner`, and `error`. A directory row's name element carries both `entry-name` and
10162
+ `entry-name-dir` (a part list), so `::part(entry-name-dir)` selects only directory names while
10163
+ `::part(entry-name)` still selects every name. Entry rows are rendered into the embedded
10164
+ `<lr-virtual-list>`'s own shadow root and forwarded with `exportparts`, so
10165
+ `lr-archive-viewer::part(entry)` (and every other row part above) reaches them from a consuming
10166
+ stylesheet.
8714
10167
 
8715
10168
  **Exports:** `ArchiveEntry` — `{ name: string; dir: boolean; size: number }`.
8716
10169
 
@@ -8825,6 +10278,14 @@ rendered region highlight), `region-highlight` (one region highlight, `data-tone
8825
10278
 
8826
10279
  **Themeable custom properties:** `--lr-svg-viewer-max-height` (default `none`) — maximum block size
8827
10280
  of `[part="body"]`; also settable via the `max-height` property, which writes this token inline.
10281
+ `--lr-svg-viewer-active-border` (default `var(--lr-color-warning, var(--lr-color-brand))`) — the
10282
+ border color of the `[part='region-highlight']` matching `activeHighlightId`, distinct from the
10283
+ resting highlight border so the active region can be recolored without touching the rest. It is an
10284
+ inline `var()` fallback at the point of use rather than a `:host` declaration, so it can be set on
10285
+ the element *or on any ancestor*: `::part(region-highlight)[data-active]` is invalid CSS — Shadow
10286
+ Parts forbids an attribute selector after `::part()` — so re-pointing a shared `--lr-color-*` token,
10287
+ and repainting everything else reading it, was previously the only way. Unset, it falls back to
10288
+ exactly the tokens the rule used before.
8828
10289
 
8829
10290
  **Optional peer dependency:** `dompurify`.
8830
10291
 
@@ -8881,7 +10342,10 @@ Enter/Space. `lr-anchor-result` (`detail: { found }`) — fired after an `anchor
8881
10342
  **CSS parts:** `base`, `body`, `table`, `header-row`, `header-cell`, `data-row`, `cell`,
8882
10343
  `cell-highlight` (a `role="cell"` covered by a `highlights` entry; wraps the action button),
8883
10344
  `cell-highlight-action` (the native button filling a highlighted cell — focusable, emits
8884
- `lr-highlight-activate` on click or Enter/Space), `spinner`, and `error`.
10345
+ `lr-highlight-activate` on click or Enter/Space), `spinner`, and `error`. `data-row`, `cell`,
10346
+ `cell-highlight` and `cell-highlight-action` render inside the internal `<lr-virtual-list>` and are
10347
+ forwarded via `exportparts`, so `lr-dataset-viewer::part(cell)` reaches them from a consumer
10348
+ stylesheet.
8885
10349
 
8886
10350
  **Exports:** `DatasetTable` is `{ fields: string[]; rows: Record<string, string>[] }`.
8887
10351
 
@@ -8937,8 +10401,11 @@ drag* over a highlighted passage never activates it — the selection-in-progres
8937
10401
  to tell that apart from a genuine activation click.
8938
10402
 
8939
10403
  **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).
10404
+ `zoom: number = 1` is clamped to `0.25`–`4`. `maxHeight: string = ''` (attribute `max-height`) is a
10405
+ CSS length that, once set, overrides `--lr-pdf-viewer-height` the block size of the virtualized
10406
+ page list — declaratively, writing it inline on `[part="base"]`. `anchorKinds` is a readonly
10407
+ `['page', 'text-quote', 'region']` (this viewer's supported `LyraAnchor.kind` values for the shared
10408
+ anchor-target contract).
8942
10409
 
8943
10410
  **Events:**
8944
10411
  - `lr-render-error` — `detail: { error }` — fetching, parsing, or rendering (page canvas or text
@@ -8970,15 +10437,28 @@ table of contents as `PdfOutlineItem[]` (`{ title, page?, children? }`), `[]` wh
8970
10437
  `clearSearch()`); `searchNext()` and `searchPrevious()` advance/step back through matches (wrapping,
8971
10438
  resolving `false` when there are none); `clearSearch()` clears the query, matches, and painted marks.
8972
10439
 
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()`).
10440
+ **CSS parts:** `base`, `toolbar`, `page-indicator`, `zoom-indicator`, `pages`, `page`, `page-canvas`
10441
+ (the canvas one page's content is painted onto), `text-layer`, `text-span` (one generated text run
10442
+ inside a page's text layer PDF.js creates these imperatively, and they carry the part so a rule can
10443
+ reach them without a descendant combinator), `search-match` (a `<mark>` painted into a mounted page's
10444
+ text layer around one search match), `search-match-active` (the currently active match, also carries
10445
+ `search-match`), `spinner`, and `error`. Search painting is best-effort: a page outside the
10446
+ virtualized render window is skipped and repainted once its text layer mounts, and a match spanning a
10447
+ text-layer span boundary that `Range.surroundContents()` can't wrap stays unpainted (still reachable
10448
+ via `searchNext()`).
10449
+
10450
+ `page`, `page-canvas`, `text-layer`, `text-span`, `search-match` and `search-match-active` are
10451
+ rendered inside the virtualizing `lr-virtual-list`'s own shadow root and forwarded out through
10452
+ `exportparts`, so `lr-pdf-viewer::part(page)` (and each of the others) works from a consumer
10453
+ stylesheet exactly like the parts in this viewer's own shadow root. The selection tint over a page's
10454
+ text is styled on `text-span` rather than on `text-layer`, because a highlight pseudo-element is
10455
+ matched against the element the selected text originates in:
10456
+ `lr-pdf-viewer::part(text-span)::selection { background: … }`.
8979
10457
 
8980
10458
  **Themeable custom properties:** `--lr-pdf-viewer-height` (default `var(--lr-size-24rem)`) — block
8981
- size of the virtualized page list (`[part="pages"]`).
10459
+ size of the virtualized page list (`[part="pages"]`); also settable via the `maxHeight` property,
10460
+ which writes this token inline on `[part="base"]`. Everything below the page list is retuned
10461
+ through the exported parts above rather than through dedicated custom properties.
8982
10462
 
8983
10463
  **Optional peer dependency:** install `pdfjs-dist` with `pnpm add pdfjs-dist`. The component registers
8984
10464
  a lazy `application/pdf` renderer with `<lr-document-viewer>` so the PDF library is loaded only when
@@ -9016,7 +10496,16 @@ Enter/Space. `lr-anchor-result` (`detail: { found }`) — fired after an `anchor
9016
10496
  `search()`/`searchNext()`/`searchPrevious()`/`clearSearch()`.
9017
10497
 
9018
10498
  **CSS parts:** `base`, `tabs`, `sheet`, `header-row`, `data-row`, `cell`, `cell-highlight` (a cell
9019
- covered by a `highlights` entry), `rows`, `spinner`, and `error`.
10499
+ covered by a `highlights` entry), `rows`, `spinner`, and `error`. `data-row`, `cell` and
10500
+ `cell-highlight` are rendered inside the internal `<lr-virtual-list>` and forwarded via
10501
+ `exportparts`, so `lr-spreadsheet-viewer::part(cell)` reaches them from a consumer stylesheet.
10502
+
10503
+ **Themeable custom properties:** `--lr-spreadsheet-viewer-highlight-color` (default
10504
+ `var(--lr-color-brand)`) — the outline color of a `cell-highlight` cell. The component writes it
10505
+ inline (as `var(--lr-color-warning, var(--lr-color-brand))`) on the cell matching
10506
+ `activeHighlightId`, since a `[data-active]` selector can't be chained onto the
10507
+ `::part(cell-highlight)` the cell reaches this component's stylesheet through; a custom property
10508
+ inherits across that boundary instead.
9020
10509
 
9021
10510
  **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
10511
  `.xlsx` and `.xls` MIME types and filename extensions.
@@ -9036,8 +10525,10 @@ row/column into view via the virtualized list's `active-id`. `highlights` paint
9036
10525
 
9037
10526
  **Properties:** `src` and `name` are strings. `hasHeaderRow: boolean = true` (attribute
9038
10527
  `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).
10528
+ `maxHeight: string = ''` (attribute `max-height`) is a CSS length that caps the scrollable body —
10529
+ setting it writes `--lr-csv-viewer-max-height` inline on `[part="base"]`. `anchorKinds` is a
10530
+ readonly `['cell-range']` (this viewer's supported `LyraAnchor.kind` values for the shared
10531
+ anchor-target contract).
9041
10532
 
9042
10533
  **Methods:** `search(query)` resolves the match count via a case-insensitive substring match over
9043
10534
  the same stringified cell values `cell()` renders, ordered row then column (empty/whitespace query
@@ -9052,7 +10543,18 @@ Enter/Space. `lr-anchor-result` (`detail: { found }`) — fired after an `anchor
9052
10543
  `search()`/`searchNext()`/`searchPrevious()`/`clearSearch()`.
9053
10544
 
9054
10545
  **CSS parts:** `base`, `sheet`, `header-row`, `data-row`, `cell`, `cell-highlight` (a cell covered by
9055
- a `highlights` entry), `rows`, `spinner`, and `error`.
10546
+ a `highlights` entry), `rows`, `spinner`, and `error`. `data-row`, `cell` and `cell-highlight` are
10547
+ rendered inside the internal `<lr-virtual-list>` and forwarded via `exportparts`, so
10548
+ `lr-csv-viewer::part(cell)` reaches them from a consumer stylesheet.
10549
+
10550
+ **Themeable custom properties:** `--lr-csv-viewer-max-height` (default `none`) — maximum block size
10551
+ of `[part="body"]` before it scrolls internally; also settable via the `maxHeight` property, which
10552
+ writes this token inline on `[part="base"]`. `--lr-csv-viewer-highlight-color` (default
10553
+ `var(--lr-color-brand)`) — the outline color of a `cell-highlight` cell. The component writes it
10554
+ inline (as `var(--lr-color-warning, var(--lr-color-brand))`) on the cell matching
10555
+ `activeHighlightId`, since a `[data-active]` selector can't be chained onto the
10556
+ `::part(cell-highlight)` the cell reaches this component's stylesheet through; a custom property
10557
+ inherits across that boundary instead.
9056
10558
 
9057
10559
  **Optional peer dependency:** install `papaparse` with `pnpm add papaparse`. The registry matches
9058
10560
  `text/csv` and `.csv` filenames.
@@ -9144,12 +10646,23 @@ truth.
9144
10646
  `detail: { page }`. In wired mode the rail also sets `viewer.page` itself.
9145
10647
 
9146
10648
  **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
10649
+ button), `page-current` (the button for the current `page`), `thumbnail` (the thumbnail canvas
10650
+ wrapper), `page-number` (the visible page number), `heat` (the heat-marker cluster), `heat-dot` (one
10651
+ heat marker), `heat-dot-accent`, `heat-dot-success`, `heat-dot-warning`, `heat-dot-danger` and
10652
+ `heat-dot-neutral` (the tone-specific name on each marker), and `heat-dot-overflow` (the `+n`
9149
10653
  marker).
9150
10654
 
10655
+ Page rows are rendered into the embedded `<lr-virtual-list>`'s own shadow root and forwarded with
10656
+ `exportparts`, so `lr-page-rail::part(page)` and the rest reach them from a consuming stylesheet.
10657
+ State variants each carry a second name in the element's part list rather than a state attribute,
10658
+ because `::part()` cannot be followed by an attribute selector: the current row is
10659
+ `part="page page-current"` and a danger marker is `part="heat-dot heat-dot-danger"`, and `::part()`
10660
+ matches with `part~=` semantics, so both names select the same element.
10661
+
9151
10662
  **Themeable custom properties:** `--lr-page-rail-height` (default `var(--lr-size-24rem)`) — block
9152
- size of the virtualized rail.
10663
+ size of the virtualized rail. `--lr-page-rail-current-bg` (default `var(--lr-color-brand-quiet)`) —
10664
+ background of the `page-current` button, kept while the row is hovered so the current page stays
10665
+ identifiable under the pointer.
9153
10666
 
9154
10667
  ## `lr-notebook-viewer`
9155
10668
 
@@ -9187,11 +10700,26 @@ activeIndex }`. `lr-render-error` — `detail: { error }`, fetching, parsing, or
9187
10700
  notebook failed.
9188
10701
 
9189
10702
  **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`.
10703
+ `data-active`), `cell-active` (added alongside `cell` on the cell an anchor currently targets),
10704
+ `cell-gutter` (the `In [n]`/`Out [n]` label column), `cell-source`, `outputs`, `output`
10705
+ (`data-output-type`, `data-stream`), `output-error` (added alongside `output` on a stderr stream or
10706
+ an error output), `error-output-label` (the label introducing an error output's traceback),
10707
+ `output-toggle`, `error`, `spinner`.
10708
+
10709
+ Every cell-level part above is rendered into the embedded `<lr-virtual-list>`'s own shadow root and
10710
+ forwarded back out through `exportparts`, so `lr-notebook-viewer::part(cell)` and friends work from
10711
+ a consumer stylesheet. The three state variants are separate part *names* rather than attribute
10712
+ selectors, because Shadow Parts forbids an attribute selector after `::part()` —
10713
+ `::part(cell)[data-active]` is invalid CSS, so use `::part(cell-active)`. The `data-*` attributes
10714
+ remain on the elements for scripting.
9192
10715
 
9193
10716
  **Themeable custom properties:** `--lr-notebook-viewer-max-height` (default `none`).
9194
10717
 
10718
+ `--lr-notebook-viewer-active-bg` (default `var(--lr-color-brand-quiet)`) is the background of the
10719
+ cell currently targeted by an anchor — the `cell-active` part. It is an inline `var()` fallback at
10720
+ the point of use rather than a `:host` declaration, so it can be set on the element or on any
10721
+ ancestor.
10722
+
9195
10723
  **Optional peer deps:** `marked`+`dompurify` (markdown cells, falls back to plain text per cell),
9196
10724
  `shiki` (code cells, falls back to unhighlighted), `dompurify` (HTML/SVG outputs, falls back to
9197
10725
  `text/plain`).
@@ -9241,7 +10769,30 @@ the resolved anchor target, `data-match`, `data-active-match`), `tag` (`data-mat
9241
10769
  `toggle` (an element's expand/collapse button, hidden but present for row alignment on leaf/empty
9242
10770
  elements), `error`, `spinner`.
9243
10771
 
9244
- **Themeable custom properties:** `--lr-xml-viewer-max-height` (default `none`).
10772
+ **Themeable custom properties:** `--lr-xml-viewer-max-height` (default `none`) — maximum block size
10773
+ of the scrollable body; also settable via the `max-height` property.
10774
+ `--lr-xml-viewer-active-match-color` (default `var(--lr-color-warning)`) — the solid outline on the
10775
+ `[part='node']` holding the *current* search match, leaving every other match on its dashed
10776
+ `--lr-xml-viewer-match-color` outline. It is an inline `var()` fallback at the point of use rather
10777
+ than a `:host` declaration, so it can be set on the element *or on any ancestor*:
10778
+ `::part(node)[data-active-match]` is invalid CSS — Shadow Parts forbids an attribute selector after
10779
+ `::part()` — so distinguishing the active match previously meant re-pointing the shared
10780
+ `--lr-color-warning` token, which recolored every other match (and every other warning surface)
10781
+ along with it. Unset, it falls back to that token, so rendering is unchanged.
10782
+
10783
+ `--lr-xml-viewer-match-color` (default `var(--lr-color-warning)`) — outline color of a non-active
10784
+ `[part='node']` search match, and (via `color-mix`) the tint source for a matching `[part='text']`'s
10785
+ background — kept distinct from `--lr-xml-viewer-active-match-color` so the non-active matches can
10786
+ be recolored without touching the active one. `--lr-xml-viewer-match-bg` (default
10787
+ `var(--lr-color-warning-quiet)`) — background of a matching `[part='tag']`/`[part='attribute-value']`.
10788
+ Both are inline `var()` fallbacks at the point of use, so either can be set on the element or any
10789
+ ancestor; unset, they fall back to the same shared tokens the rules used before.
10790
+
10791
+ `[part='toggle']`'s glyph box stays compact (`1.25rem`) while its *interactive* box takes the shared
10792
+ minimum target size as a floor via `--lr-icon-button-size`. That token is a floor, not a fixed size,
10793
+ so lowering it never squashes the chevron below its own box — the visible glyph keeps its size while
10794
+ the hit target follows the token, and it can never fall under the accessible minimum from this
10795
+ component's own rules.
9245
10796
 
9246
10797
  ```html
9247
10798
  <lr-xml-viewer .xml=${payload} collapsed-depth="2" copyable
@@ -9401,7 +10952,8 @@ carrying `data-display="inline"|"block"`)
9401
10952
 
9402
10953
  **Themeable custom properties:** `--lr-markdown-font-mono` (default `ui-monospace, SFMono-Regular,
9403
10954
  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`,
10955
+ `--lr-*` monospace token exists), `--lr-code-block-tab-size` (default `2` — tab width inside a
10956
+ rendered fenced or indented `code-block`), plus shared tokens `--lr-space-xs/-s/-m/-l`,
9405
10957
  `--lr-color-brand-quiet`, `--lr-color-brand`, `--lr-color-border`, `--lr-color-text-quiet`,
9406
10958
  `--lr-radius`.
9407
10959
 
@@ -9437,6 +10989,17 @@ cleared in `updated()` based on whether the deps have loaded) and shows the same
9437
10989
  rendering — there's no separate loading skeleton, since the un-rendered Markdown source is already
9438
10990
  legible text in the meantime.
9439
10991
 
10992
+ **One tab width for every code surface.** `--lr-code-block-tab-size` is deliberately the same
10993
+ property name and default (`2`) that `<lr-code-block>` and `<lr-code-editor>` use, so a consumer sets
10994
+ tab width once for every code surface in the app. It is declared as a `var()` fallback **at the point
10995
+ of use, never on `:host`** — a `:host` declaration is re-stamped on every instance and shadows any
10996
+ inherited value, so a page- or container-level declaration could never reach it. This element carries
10997
+ its own copy of that fallback rather than inheriting `<lr-code-block>`'s because the two are
10998
+ **sibling** custom elements, not ancestor and descendant: no single declaration inside one of them
10999
+ can cover the other. The same value can still *look* different between the two — a markdown code
11000
+ block inherits `white-space: pre-wrap` while `<lr-code-block>` is `white-space: pre`, and tab stops
11001
+ restart at the beginning of each visual line, so a wrapped line's tabs land differently.
11002
+
9440
11003
  **Known gotchas:**
9441
11004
  - a malformed percent-escape or lone UTF-16 surrogate in a link's raw `href` makes the internal
9442
11005
  `encodeURI`-based validity guard throw, silently dropping just that anchor (the link text still
@@ -9499,6 +11062,15 @@ unhighlighted permanently, `headingAnchors: boolean = false` (attribute `heading
9499
11062
  **CSS parts:** `content`, `heading`, `paragraph`, `list`, `code-block`, `inline-code`, `link`,
9500
11063
  `table`, `blockquote`, `img`, `math` — identical to `<lr-markdown>`'s own parts.
9501
11064
 
11065
+ **Themeable custom properties:** `--lr-code-block-tab-size` (default `2` — tab width inside a
11066
+ rendered fenced or indented `code-block`), with exactly the mechanics described under
11067
+ `<lr-markdown>` above: the same property name and default that `<lr-code-block>`/`<lr-code-editor>`
11068
+ read, declared as a `var()` fallback at the point of use rather than on `:host` so a page- or
11069
+ container-level value reaches it, and carried here in its own right because this element is a
11070
+ **sibling** of `<lr-code-block>` rather than an ancestor of it. Markdown code blocks wrap
11071
+ (`white-space: pre-wrap`) while `<lr-code-block>` does not, so the same tab width can render
11072
+ differently on a wrapped line.
11073
+
9502
11074
  **Optional peer deps:** `marked`, `dompurify` (both lazy-loaded, same as `<lr-markdown>`), `katex`
9503
11075
  (for `math`). Does *not* depend on the full `shiki` package's default entry point — only
9504
11076
  `shiki/core`/`shiki/engine/oniguruma`/`shiki/langs/*`, the same fine-grained subset
@@ -9595,6 +11167,22 @@ between 4.x and 5.0.0, which silently turned one consumer's inner-surface scrim
9595
11167
  bubble (near-black text on `rgba(0,0,0,0.22)`, visible only by eye). These four are that stable
9596
11168
  contract.
9597
11169
 
11170
+ Two matching geometry properties cover the bubble's box:
11171
+
11172
+ - `--lr-chat-message-bubble-padding` (default `var(--lr-space-m)`) — the bubble's padding.
11173
+ - `--lr-chat-message-bubble-radius` (default `var(--lr-radius)`) — the bubble's corner radius.
11174
+ Bubble-only by design: `[part='collapse-button']` and `[part='retry-button']` keep reading the
11175
+ shared `--lr-radius`, so a rounder bubble never desyncs those controls from the rest of the
11176
+ library.
11177
+
11178
+ **Use these instead of a `::part(bubble)` padding/radius override.** A `::part` declaration written
11179
+ in the consumer's tree outranks *every* rule inside this component's shadow tree, so a
11180
+ `::part(bubble) { padding: … }` rule silently suppresses the per-`status` treatments layered on the
11181
+ same element — `status="failed"`'s danger tint, `status="streaming"`'s border — along with the
11182
+ per-role fills above. The two properties are declared as `var()` fallbacks at the point of use and
11183
+ never on `:host`, both so they can't shadow an inherited value and so a container can set them once
11184
+ above a whole transcript rather than per message.
11185
+
9598
11186
  Plus shared tokens `--lr-space-xs/-m`, `--lr-color-border`, `--lr-color-surface`,
9599
11187
  `--lr-color-brand-quiet`, `--lr-color-brand`, `--lr-color-text-quiet`, `--lr-color-danger`,
9600
11188
  `--lr-color-danger-quiet`, `--lr-radius`, `--lr-icon-button-size`, `--lr-focus-ring-*`,
@@ -9741,6 +11329,10 @@ reveals the invalid state, and `form.reset()` clears the touched presentation.
9741
11329
  - `maxRows: number = 8` (attribute `max-rows`) — floored to at least `minRows`
9742
11330
  - `status: ChatComposerStatus = 'idle'` (reflected) — `'idle' | 'sending' | 'streaming'`; drives the
9743
11331
  built-in button's icon/label (send vs. stop) and whether Enter still submits
11332
+ - `appearance: ChatComposerAppearance = 'card'` (reflected) — `'card' | 'plain'`; `'plain'` drops
11333
+ `[part="base"]`'s border, background, padding and corner radius so a composer docked inside a chat
11334
+ panel, dialog footer or toolbar that already draws its own border doesn't double the frame. The
11335
+ focus affordance is swapped, not dropped — see **Known gotchas**
9744
11336
  - `submitOnEnter: boolean = true` (reflected, attribute `submit-on-enter`) — when `false`, Enter
9745
11337
  always inserts a newline instead of submitting
9746
11338
  - `submitDisabled: boolean = false` (reflected, attribute `submit-disabled`) — consumer-controlled
@@ -9784,11 +11376,15 @@ entirely when it has assigned content)
9784
11376
 
9785
11377
  **CSS parts:** `base`, `chips`, `row`, `leading`, `textarea`, `trailing`, `action-button`
9786
11378
 
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`.
11379
+ **Themeable custom properties:** `--lr-chat-composer-busy-bg` (default `var(--lr-color-text-quiet)`)
11380
+ `[part="action-button"]`'s background while `status` is `"sending"` or `"streaming"` (the busy/stop
11381
+ treatment). Scoped separately from the shared `--lr-color-text-quiet` token, which
11382
+ `[part="textarea"]`'s placeholder color also reads — overriding this cssprop recolors only the busy
11383
+ button, not the placeholder too (the same shared-token-collision fix `<lr-chat-message>`'s own
11384
+ user-bubble background pair documents). Plus shared tokens `--lr-space-xs`, `--lr-space-s`,
11385
+ `--lr-color-border`, `--lr-color-surface`, `--lr-color-brand`, `--lr-color-on-brand`,
11386
+ `--lr-color-text-quiet`, `--lr-radius`, `--lr-icon-button-size`, `--lr-transition-fast`,
11387
+ `--lr-opacity-disabled`, `--lr-focus-ring-width`, `--lr-focus-ring-color`, `--lr-focus-ring-offset`.
9792
11388
 
9793
11389
  **Optional peer deps:** none.
9794
11390
 
@@ -9844,6 +11440,11 @@ and disables only the built-in Send button; editing and busy-state Stop behavior
9844
11440
  - `[part="chips"]`/`[part="leading"]` are hidden via a JS-tracked `[hidden]` attribute rather than a
9845
11441
  CSS `:empty` selector, because each always contains a literal `<slot>` child regardless of
9846
11442
  assigned content.
11443
+ - Under `appearance="card"` the only focus affordance is a border-color shift on `[part="base"]`
11444
+ (the internal `<textarea>` sets `outline: none`). `appearance="plain"` removes that border, so it
11445
+ swaps in a different affordance rather than losing focus visibility: an underline across the whole
11446
+ input row, drawn as an inset `box-shadow` from `--lr-focus-ring-width`/`--lr-focus-ring-color` so
11447
+ it costs no layout. If you restyle `[part="base"]` under `plain`, keep a focus indicator.
9847
11448
 
9848
11449
  ---
9849
11450
 
@@ -9986,6 +11587,15 @@ First-party invention (no Web Awesome equivalent).
9986
11587
  rename button never renders and the row can never enter its editing state; flipping it to `false`
9987
11588
  while a rename is already in progress cancels that edit (discards the draft, like Escape) rather
9988
11589
  than leaving it stranded and still committable.
11590
+ - `compact: boolean = false` (reflected) — tighter row padding and gaps, for the dense history
11591
+ sidebars these rows usually render in (same convention as `lr-empty`'s `compact`). Tightens
11592
+ `[part='base']`'s padding to `var(--lr-space-xs) var(--lr-space-s)` and its gap to
11593
+ `var(--lr-space-2xs)`, and collapses `[part='content']`'s inter-line gap to `0`. Deliberately
11594
+ changes nothing else: it does **not** shrink `[part='rename-button']` below the shared
11595
+ `--lr-icon-button-size` target floor, hide the excerpt, or reduce the excerpt/timestamp font
11596
+ sizes — so a row carrying a rename button or slotted `actions` still floors at roughly that icon
11597
+ size plus the compact padding, while a row with `editable=false` and no actions collapses much
11598
+ further.
9989
11599
  - `spellcheck: boolean = true` — forwarded to the in-place rename `<input>`; `spellcheck="false"` is
9990
11600
  parsed as false (not Lit's default boolean-attribute behavior)
9991
11601
  - `autocapitalize: string = ''` — forwarded to the in-place rename `<input>`; empty omits the attribute
@@ -10021,7 +11631,33 @@ in-place rename `<input>`'s own `focus`, for the same reason as `blur`)
10021
11631
  **CSS parts:** `base`, `option`, `content`, `title`, `title-input`, `rename-button`, `excerpt`,
10022
11632
  `timestamp`, `actions`
10023
11633
 
10024
- **Themeable custom properties:** shared tokens only — `--lr-space-xs/-s/-m`, `--lr-radius`,
11634
+ **Themeable custom properties:** `--lr-conversation-item-active-bg` (default
11635
+ `var(--lr-color-brand-quiet)`) — the row's background while `active`. `--lr-conversation-item-active-color`
11636
+ (default `var(--lr-color-text)`) — the text color of `[part='excerpt']` and `[part='timestamp']`
11637
+ while `active`. Both are declared as inline `var()` fallbacks at the point of use and never on
11638
+ `:host`, so either can be set on the element *or on any ancestor* (a thread-list wrapper, a page
11639
+ theme layer); `::part(base)[active]` is not valid CSS — Shadow Parts forbids an attribute selector
11640
+ after `::part()` — so the only previous lever was overriding the library-wide `--lr-color-brand-quiet`
11641
+ token and repainting everything else reading it. Unset, each falls back to exactly the token its rule
11642
+ used before.
11643
+
11644
+ **These two are a contrast-sensitive pair — override them together, never one alone.** The
11645
+ `-active-color` hook exists precisely because the quiet text tone only reaches about 4.25:1 against
11646
+ the default active background; keep any override at 4.5:1 or better against it. And note that
11647
+ `[part='title']` is *not* restyled by the pair — it keeps `--lr-color-text` regardless — so a dark
11648
+ custom active background needs its own title color set alongside them, or the title drops below
11649
+ contrast while the excerpt stays legible.
11650
+
11651
+ `--lr-conversation-item-compact-padding` (default `var(--lr-space-xs) var(--lr-space-s)`) —
11652
+ `[part='base']`'s padding while `compact`. `--lr-conversation-item-compact-gap` (default
11653
+ `var(--lr-space-2xs)`) — `[part='base']`'s gap while `compact`. Like the active-state pair, both are
11654
+ inline `var()` fallbacks at the point of use and never declared on `:host`, so a surrounding list can
11655
+ retune every row at once from an ancestor. `[part='content']`'s gap collapses to a flat `0` under
11656
+ `compact` with no hatch of its own — there is no smaller step left to retune to. `:host([compact])
11657
+ [part='base']` is ordered *before* `:host([active]) [part='base']` (equal specificity), so a row that
11658
+ is both compact and active keeps the active background and the promoted excerpt/timestamp contrast.
11659
+
11660
+ Plus shared tokens — `--lr-space-xs/-s/-m`, `--lr-radius`,
10025
11661
  `--lr-transition-fast`, `--lr-color-text/-text-quiet/-brand/-brand-quiet/-surface`,
10026
11662
  `--lr-focus-ring-width/-color/-offset`, `--lr-icon-button-size`.
10027
11663
 
@@ -10068,6 +11704,11 @@ duration of an edit rather than just visually swapping content (a row mid-edit *
10068
11704
  - Setting `editable = false` mid-rename silently discards the in-progress draft (no `lr-rename`
10069
11705
  fires) — a consumer toggling `editable` off (e.g. in response to some other row entering rename
10070
11706
  mode) should not expect the previous edit to be committed first.
11707
+ - `compact` is a spacing knob only — it never lowers the rename button's `--lr-icon-button-size`
11708
+ floor. A compact row that still shows a rename button (or slotted `actions` at the same floor)
11709
+ therefore bottoms out at roughly that icon size plus the compact padding, not at the text height.
11710
+ Lowering `--lr-icon-button-size` at an ancestor is the explicit, informed opt-out of the
11711
+ target-size floor; a density flag deliberately won't do it silently on your behalf.
10071
11712
 
10072
11713
  ---
10073
11714
 
@@ -10123,10 +11764,24 @@ emitting `lr-change`.
10123
11764
  - `disabled: boolean = false` (reflected)
10124
11765
  - `required: boolean = false` (reflected — enforced via `internals.setValidity()`)
10125
11766
  - `open: boolean = false` (reflected)
11767
+ - `size: 'xs' | 's' | 'm' | 'l' | 'xl' = 'm'` (reflected) — visual size; same `xs`–`xl` scale as
11768
+ `<lr-select>`'s own `size`, scaling `[part="trigger"]`/`[part="combobox"]`'s padding/min-height/
11769
+ font-size and `[part="expand-icon"]`'s box size (see the themeable custom properties below).
10126
11770
  - `value: string` — getter/setter (hand-rolled, not the `FormAssociated` mixin); the current model id,
10127
11771
  `''` when nothing is selected. Writing it calls `internals.setFormValue()` synchronously. A named,
10128
11772
  untouched model-select contributes `''` to `FormData` instead of omitting its key.
10129
11773
 
11774
+ **Methods:** `click()` (override) — forwards to whichever internal control the active mode renders,
11775
+ since `HTMLElement.prototype.click()` is otherwise a no-op on a custom element with no native click
11776
+ semantics of its own (mirrors `<lr-button>`'s identical host `click()` forwarding, so a generic
11777
+ form-automation helper or another component calling `.click()` on the host actually opens the picker
11778
+ instead of silently doing nothing). Closed-dropdown mode forwards a real `.click()` to the trigger
11779
+ `<button>`, whose own `@click` handler opens it. Free-text mode instead calls `.focus()` on the
11780
+ combobox `<input>`: unlike a genuine pointer click, `HTMLElement.click()` never moves focus (that's a
11781
+ `mousedown` side effect the browser applies only to real pointer interaction), and this mode's open
11782
+ behavior is wired to the input's `focus` event (`onInputFocus`), not a `click` handler on the input
11783
+ itself.
11784
+
10130
11785
  **Mode switching:** `closedMode` (private) is `true` whenever `normalizedCatalog.length > 0 &&
10131
11786
  !allowCustom` — a non-empty `catalog` with `allowCustom` left `false` renders the closed dropdown
10132
11787
  trigger-button UI (`[part="trigger"]`, `role="combobox"` on a `<button>`, no typing). Any other
@@ -10163,10 +11818,21 @@ both modes), `option`, `option-label`, `option-badge` (the "not in catalog" badg
10163
11818
  stale-value row), `expand-icon` (the dropdown chevron, present in both modes), `hint` (the hint
10164
11819
  message), `error` (the error message)
10165
11820
 
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`.
11821
+ **Themeable custom properties:** `--lr-model-select-trigger-padding` (default `var(--lr-space-xs)
11822
+ var(--lr-space-s)`) `[part="trigger"]`/`[part="combobox"]`'s padding shorthand.
11823
+ `--lr-model-select-trigger-min-height` (default `var(--lr-size-2-5rem)`) — their block-size floor.
11824
+ `--lr-model-select-font-size` (default `var(--lr-font-size-md)`) — their font size.
11825
+ `--lr-model-select-expand-size` (default `var(--lr-size-1-75rem)`) — `[part="expand-icon"]`'s
11826
+ decorative box size (clamped against `--lr-icon-button-size` via `min()`). All four are declared on
11827
+ `:host` at these `size="m"` (the default) values and re-declared inside each
11828
+ `:host([size="xs"|"s"|"l"|"xl"])` block at that tier's own value — same xs–xl scale `<lr-select>`
11829
+ uses — so `size` is the primary lever; override the cssprop directly only to retune a single tier or
11830
+ step outside the scale entirely. `--lr-model-select-option-active-bg` (default
11831
+ `var(--lr-color-brand-quiet)`) — background of a hovered or keyboard-active `[part="option"]` row;
11832
+ declared as a `var()` fallback at the point of use, not on `:host`, so it isn't tied to `size`. Plus
11833
+ shared tokens — `--lr-space-xs/-s`, `--lr-color-border/-surface/-brand/-brand-quiet/-text-quiet`,
11834
+ `--lr-radius`, `--lr-shadow`, `--lr-focus-ring-width/-color/-offset`, `--lr-icon-button-size`,
11835
+ `--lr-transition-fast`, `--lr-opacity-disabled`.
10170
11836
 
10171
11837
  **Optional peer deps:** none.
10172
11838
 
@@ -10467,11 +12133,30 @@ are both set)
10467
12133
  **Themeable custom properties:** `--lr-code-block-max-height` (default `none` — the consumer-tunable
10468
12134
  scroll cap; only takes effect once `max-height` is set), `--lr-code-block-font` (default
10469
12135
  `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`,
12136
+ token exists to resolve through), `--lr-code-block-tab-size` (default `2` — tab width for the
12137
+ rendered code, applied to `[part='pre']`), `--lr-code-block-active-line-outline-color` (default
12138
+ `var(--lr-color-brand)` — the outline around the line marked active by `active-highlight-id`), plus shared tokens `--lr-color-border`, `--lr-radius`,
10471
12139
  `--lr-color-surface`, `--lr-space-xs/-s/-m`, `--lr-font`, `--lr-color-text-quiet`,
10472
12140
  `--lr-color-text`, `--lr-color-brand`/`-brand-quiet`, `--lr-transition-fast`,
10473
12141
  `--lr-focus-ring-width/-color/-offset`.
10474
12142
 
12143
+ `--lr-code-block-tab-size` carries the same default as `--lr-code-editor-tab-size`, so the editable
12144
+ and read-only code surfaces agree on what a literal tab looks like. It is declared as a `var()`
12145
+ fallback **at the point of use, not on `:host`** — a `:host` rule is re-stamped on every instance and
12146
+ shadows any inherited value, so a page- or container-level declaration could never reach it. It is
12147
+ also never written as an inline `tab-size`: `shiki` puts its own `style` attribute on the highlighted
12148
+ `<pre>`, and an inline declaration is the one thing a host override cannot beat. `<lr-markdown>` and
12149
+ `<lr-markdown-core>` carry the same fallback for their own `code-block` part because they are
12150
+ **sibling** custom elements rather than descendants of this one — no single declaration covers both.
12151
+ The identical value can still look different across the two: this component is `white-space: pre`
12152
+ while a markdown code block inherits `pre-wrap`, and tab stops restart at each visual line, so a
12153
+ wrapped line's tabs diverge.
12154
+
12155
+ `--lr-code-block-active-line-outline-color` retints just the active line's outline and leaves every
12156
+ other `--lr-color-brand` surface in the component — the header language pill, hover states, the focus
12157
+ ring — alone. It too is an inline `var()` fallback rather than a `:host` declaration, deliberately,
12158
+ so it inherits: set it on the element, on an ancestor, or at the theme level.
12159
+
10475
12160
  **Optional peer deps:** `shiki` (lazy-loaded and cached once per page by `code-loader.ts`'s
10476
12161
  `loadShikiHighlighter()`, which builds a single `Highlighter` seeded with the bundled `github-light`/
10477
12162
  `github-dark` "dual themes" and *zero* language grammars up front; each `language` a
@@ -10596,7 +12281,12 @@ body ended; `anchor` is a `line-range` anchor covering the selected lines).
10596
12281
  `code`, `line-highlight`, `line-button` — identical set to `<lr-code-block>`.
10597
12282
 
10598
12283
  **Themeable custom properties:** identical to `<lr-code-block>` — `--lr-code-block-max-height`,
10599
- `--lr-code-block-font`, plus the same shared tokens.
12284
+ `--lr-code-block-font`, `--lr-code-block-tab-size` (default `2`, applied to `[part='pre']`),
12285
+ `--lr-code-block-active-line-outline-color` (default `var(--lr-color-brand)`), plus the same shared
12286
+ tokens. Both of the last two are inline `var()` fallbacks at the point of use rather than `:host`
12287
+ declarations, so a page-, container-, or theme-level value reaches them; see `<lr-code-block>` above
12288
+ for the full rationale, including why `<lr-markdown>`/`<lr-markdown-core>` must declare the tab-size
12289
+ fallback separately.
10600
12290
 
10601
12291
  **Optional peer deps:** `shiki` (specifically its `shiki/core`, `shiki/engine/oniguruma`,
10602
12292
  `shiki/wasm`, and `shiki/themes/github-{light,dark}.mjs` subpaths — never `shiki`'s main entry point,
@@ -10829,6 +12519,21 @@ for a set rating).
10829
12519
  `commentable` is set), `reasons` (the reason-chip group), `comment` (the comment `<textarea>`), and
10830
12520
  `submit-button`.
10831
12521
 
12522
+ **Themeable custom properties:** six pressed-state hooks, three per thumb —
12523
+ `--lr-message-feedback-up-active-color` (default `var(--lr-color-success)`),
12524
+ `--lr-message-feedback-up-active-bg` (default `var(--lr-color-success-quiet)`),
12525
+ `--lr-message-feedback-up-active-border` (default `var(--lr-color-success)`), and the thumbs-down
12526
+ trio `--lr-message-feedback-down-active-color`, `--lr-message-feedback-down-active-bg`,
12527
+ `--lr-message-feedback-down-active-border` (defaulting to `var(--lr-color-danger)`,
12528
+ `var(--lr-color-danger-quiet)`, `var(--lr-color-danger)`). Each styles the glyph, background, and
12529
+ border of its thumb only while that thumb is pressed. All six are declared as inline `var()`
12530
+ fallbacks at the point of use and never on `:host`, so each can be set on the element *or on any
12531
+ ancestor* — a whole transcript's feedback controls retint from one declaration. That shape is
12532
+ required because `::part(up-button)[aria-pressed='true']` is invalid CSS (Shadow Parts forbids an
12533
+ attribute selector after `::part()`), which previously left overriding the library-wide
12534
+ `--lr-color-success`/`--lr-color-danger` tokens as the only lever, repainting every other element
12535
+ reading them. Unset, each falls back to exactly the token its rule used before.
12536
+
10832
12537
  ## `lr-push-to-talk`
10833
12538
 
10834
12539
  A mic capture button owning the full `getUserMedia` + `MediaRecorder` lifecycle: permission request,
@@ -10866,7 +12571,14 @@ Blob }`, only when `timeslice-ms > 0`), `lr-record-stop` (`detail: { blob: Blob;
10866
12571
  (visible status text for the `requesting`/`denied`/`error`/unsupported states).
10867
12572
 
10868
12573
  **Themeable custom properties:** `--lr-push-to-talk-size` (default `var(--lr-size-3rem)`) — the
10869
- trigger button's inline and block size.
12574
+ trigger button's inline and block size. `--lr-push-to-talk-recording-color` (default
12575
+ `var(--lr-color-danger)`) — the border and text color of `[part='trigger']` while `state` is
12576
+ `recording`; it recolors only the recording treatment and leaves every other danger-toned surface on
12577
+ the page untouched. Like the library's other state hooks it is an inline `var()` fallback at the
12578
+ point of use rather than a `:host` declaration, so it can be set on the element or on any ancestor —
12579
+ `::part(trigger)[data-state='recording']` is invalid CSS (Shadow Parts forbids an attribute selector
12580
+ after `::part()`), so re-pointing the shared `--lr-color-danger` token was previously the only way,
12581
+ and it repainted every other danger surface with it.
10870
12582
 
10871
12583
  ## `lr-transcript-feed`
10872
12584
 
@@ -10967,6 +12679,18 @@ Renders no messages and computes no unread state itself — the host supplies `u
10967
12679
  virtualization of its own (`lr-virtual-list`); not a generic overflow surface (`lr-scroller`); no
10968
12680
  message semantics (`lr-chat-message`).
10969
12681
 
12682
+ **Sizing in virtual mode.** `[part='scroll']` steps aside and the slotted `lr-virtual-list`'s own
12683
+ viewport becomes the real scroller, so it is given this component's full height — otherwise it would
12684
+ scroll inside `lr-virtual-list`'s `24rem` default no matter how tall the viewport is. An explicit
12685
+ `block-size` on the slotted list is what makes that resolvable: without it the list host is
12686
+ auto-height, its own base percentage chains to `auto`, and the two size each other circularly.
12687
+ `<lr-thread-list>` solves the same problem by turning the internal list's shipped `24rem` into a
12688
+ flex-basis through `::part(base)`, which is not available here — that list lives in the *consumer's*
12689
+ light DOM, and `::slotted()` cannot be followed by `::part()`. Virtual mode therefore inherits this
12690
+ component's existing requirement of a height-bounded parent, exactly as slotted mode's own
12691
+ `[part='scroll']` already does. A document-tree declaration on the list (a consumer's own rule or an
12692
+ inline style) still wins over the built-in one.
12693
+
10970
12694
  ```html
10971
12695
  <lr-chat-viewport unread-start-index="12" @lr-follow-change=${(e) => console.log(e.detail.following)}>
10972
12696
  <lr-chat-message role="user">…</lr-chat-message>
@@ -10996,6 +12720,15 @@ string = ''` — accessible name for the group, defaults to the localized `sugge
10996
12720
  **CSS parts:** `base` (the labeled group), `chip` (each suggestion button), `chip-label` (the primary
10997
12721
  text), `chip-detail` (the secondary line, only rendered when `detail` is set).
10998
12722
 
12723
+ **Themeable custom properties:** `--lr-suggestion-chips-hover-bg` (default
12724
+ `var(--lr-color-brand-quiet)`) — a `chip`'s background on hover. `--lr-suggestion-chips-hover-border`
12725
+ (default `var(--lr-color-brand)`) — a `chip`'s border color on hover. Both are declared as `var()`
12726
+ fallbacks at the point of use, not on `:host`. Plus shared tokens `--lr-space-xs/-m/-2xs`,
12727
+ `--lr-color-border/-surface/-text/-text-quiet`, `--lr-radius-pill`, `--lr-font-size-xs`,
12728
+ `--lr-focus-ring-width/-color/-offset`.
12729
+
12730
+ **Optional peer deps:** none.
12731
+
10999
12732
  Keyboard: roving tabindex across chips; ArrowLeft/ArrowRight (direction-aware) plus Home/End;
11000
12733
  Enter/Space activate. Renders inside an internal `lr-scroller` (`orientation="horizontal"`,
11001
12734
  `hide-scrollbar`) unless `wrap` is set.
@@ -11039,18 +12772,34 @@ set; `lr-group-toggle` requests the matching state change. `rowActions: ThreadRo
11039
12772
  data mode only: built-in icon buttons rendered into each row's `actions` slot. `showArchived: boolean
11040
12773
  = false` (attribute `show-archived`, reflected) — data mode: include `archived` threads (in their own
11041
12774
  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
12775
+ rename. `compact: boolean = false` (reflected) data mode only: forwarded to each row
12776
+ `lr-conversation-item`'s own `compact`, tightening every row's padding and gaps from one attribute
12777
+ (the density itself lives on the row item; retune it through
12778
+ `--lr-conversation-item-compact-padding`/`-gap` on this element or any ancestor). Slotted mode is a
12779
+ deliberate no-op — that mode renders host-supplied items as-is, so the host sets `compact` on its own
12780
+ items there, the same division of responsibility slotted mode already has for every other row
12781
+ property. `stickyGroups: boolean = false` (attribute `sticky-groups`, reflected) — data mode: pins
12782
+ the current date/custom group's header to the top of the scroll viewport while its rows are in view,
12783
+ pushing it off as the next group's header arrives. Group headers are ordinary virtualized rows, so
12784
+ this renders an `aria-hidden` copy of the header into the internal `lr-virtual-list`'s sticky layer:
12785
+ the real row keeps the `role="heading"`/`aria-level` semantics and the tab order (the copy's toggle
12786
+ is not a second tab stop), while the pinned copy stays clickable and requests the same
12787
+ `lr-group-toggle` collapse. Default `false` renders exactly as before; `grouping="none"` has no
12788
+ headers to pin, so it is a no-op there. `label: string = ''` — accessible name for the list region,
12789
+ defaults to the localized `threadListLabel`. `wrapRow?: (thread: ChatThread, row: TemplateResult) =>
12790
+ TemplateResult` (attribute: false) — data mode only: wraps each row's built-in
12791
+ `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
12792
  icon — the item has no default slot to receive one); unset renders the built-in row unwrapped.
11047
12793
  `renderActions?: (thread: ChatThread) => TemplateResult` (attribute: false) — data mode only:
11048
12794
  appends host-supplied content (re-invoked per row on every render, e.g. a `lr-menu` with custom
11049
12795
  actions) after the built-in `rowActions` output in each row's `actions` slot; events it fires reach
11050
12796
  the host normally and never trigger `lr-select`. Unset renders only the built-in `rowActions`.
11051
12797
  `renderLeading?: (thread: ChatThread) => TemplateResult` (attribute: false) — renders non-interactive
11052
- leading content in each virtualized row. `renderMeta?: (thread: ChatThread) => TemplateResult`
11053
- (attribute: false) — appends structured metadata in the row's meta region.
12798
+ leading content in each virtualized row. `renderExcerpt?: (thread: ChatThread) => TemplateResult`
12799
+ (attribute: false) — renders rich content into the row item's own `excerpt` slot, winning over the
12800
+ plain-string `excerpt` property (e.g. a server-highlighted search-match snippet), while leaving the
12801
+ built-in title layout and inline-rename affordance untouched. `renderMeta?: (thread: ChatThread) =>
12802
+ TemplateResult` (attribute: false) — appends structured metadata in the row's meta region.
11054
12803
  `renderRowContent?: (thread: ChatThread) => TemplateResult` (attribute: false) — replaces the
11055
12804
  conversation item's title/excerpt/meta content area with custom non-interactive row content.
11056
12805
  `formatGroupLabel?: (key: ThreadBucketKey, date?: Date) => string` (attribute: false) — overrides
@@ -11068,20 +12817,69 @@ id }`), `lr-thread-pin` (`detail: { id, pinned }` — the requested new state),
11068
12817
  `lr-thread-rename` (`detail: { id, title }`, re-emitted from the row's `lr-rename`),
11069
12818
  `lr-filter-change` (`detail: { text, matchCount }`), `lr-group-toggle` (`detail: { id, collapsed }` —
11070
12819
  controlled intent; native group buttons provide Enter/Space activation and explicit
11071
- `aria-expanded="true"|"false"`).
12820
+ `aria-expanded="true"|"false"`). `searchable` only: `blur`/`focus` (no detail) — re-dispatched from
12821
+ the internal search `<input>`'s own `blur`/`focus`, bubbling and composed unlike the native events,
12822
+ which are neither.
11072
12823
 
11073
12824
  **CSS parts:** `base`, `search`/`search-input` (the search field wrapper and `<input
11074
12825
  type="search">`), `list` (the list region), `empty`, `viewport` (the actual internal virtual-list
11075
12826
  scroll container, suitable for scrollbar styling), `row-action` (a built-in pin/archive/delete icon
11076
12827
  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
12828
+ `group-label`, `group-icon`, `group-sticky` (`sticky-groups` only: the pinned copy of the current
12829
+ group's header, exported from the internal `lr-virtual-list`'s sticky layer it wraps a full copy of
12830
+ the `group-header`/`group-toggle`/`group-label`/`group-icon` markup, so those parts style the real
12831
+ header row and the pinned copy alike, and the band itself is where a shadow or bottom border
12832
+ belongs), `row` (all exported across the internal `lr-virtual-list` shadow
12833
+ boundary), `row-wrapper` (the wrapper around `wrapRow` output, only present when `wrapRow` is set;
12834
+ row-only — group headers are never passed through `wrapRow`, so they never carry it), and
12835
+ `row-leading`/`row-excerpt`/`row-content`/`row-meta`/`row-actions` (the library-owned wrappers around
11079
12836
  their corresponding render-hook output; inherited fonts, layout values, and theme custom properties
11080
- reach callback-rendered descendants through these parts).
12837
+ reach callback-rendered descendants through these parts). `row-excerpt` wraps `renderExcerpt`
12838
+ output, which is slotted into the row item's own `excerpt` slot.
12839
+
12840
+ Data mode additionally forwards each row `<lr-conversation-item>`'s own parts under a `row-item-`
12841
+ prefix: `row-item-base`, `row-item-option`, `row-item-leading`, `row-item-content`,
12842
+ `row-item-title`, `row-item-title-input`, `row-item-rename-button`, `row-item-excerpt`,
12843
+ `row-item-meta`, `row-item-timestamp`, `row-item-actions`.
12844
+
12845
+ **Keep the two prefixes straight — they are different surfaces.** The `row-*` parts wrap *this*
12846
+ component's own render-callback output (`wrapRow`, `renderLeading`, `renderExcerpt`,
12847
+ `renderRowContent`, `renderMeta`, `renderActions`); the `row-item-*` parts are the row item's
12848
+ *internals*. Row density
12849
+ in particular lives in `row-item-base`'s padding and `row-item-title`'s font size, so
12850
+ `::part(row-item-base)` is the supported way to build a dense sidebar.
12851
+
12852
+ For plain row density, prefer the `compact` property above — it forwards straight to the row item's
12853
+ own density knob. The `row-item-*` parts remain the lever for tuning beyond it (a different font
12854
+ size, a different padding ratio):
12855
+
12856
+ ```css
12857
+ lr-thread-list::part(row-item-base) { padding-block: 0.25rem; }
12858
+ lr-thread-list::part(row-item-title) { font-size: 0.8125rem; }
12859
+ ```
12860
+
12861
+ Do **not** reach for `::part(row) { --lr-theme-space-s: … }` instead. That is a whole-subtree
12862
+ retheme: it shrinks everything nested inside the row, including the items of a `renderActions` menu,
12863
+ which pushes their touch targets below the accessible minimum. The `row-item-*` parts exist so row
12864
+ density can be tuned without that blast radius.
12865
+
12866
+ **Sizing:** the internal list fills whatever height this component is given, with no consumer CSS —
12867
+ `[part='viewport']` is the real scroll container, and it falls back to `lr-virtual-list`'s own `24rem`
12868
+ default only when the container has no resolvable height. This is deliberately *not* implemented by
12869
+ setting `--lr-virtual-list-height: 100%`: that percentage resolves against this host, which is a flex
12870
+ item, so in an auto-height container it chains to `auto` and the viewport either collapses to zero
12871
+ (with no rows) or grows to the full un-virtualized content height (with rows) — defeating
12872
+ virtualization in both directions. Instead the list host is made a column flex container, which turns
12873
+ the shipped `24rem` into a *flex-basis*: it grows to fill a bounded pane, shrinks below `24rem` in a
12874
+ short one, and falls back to exactly `24rem` in an auto-height container.
12875
+
12876
+ `sticky-groups` keeps the current date group's header visible while scrolling through a long sidebar;
12877
+ style the pinned band with `lr-thread-list::part(group-sticky)`.
11081
12878
 
11082
12879
  ```html
11083
12880
  <lr-thread-list
11084
12881
  searchable
12882
+ sticky-groups
11085
12883
  .threads=${threads}
11086
12884
  active-id=${activeThreadId}
11087
12885
  .rowActions=${['pin', 'archive', 'delete']}
@@ -11262,6 +13060,14 @@ identically-named properties.
11262
13060
  getter/setter (the current voice id, `''` when nothing is selected), `name` (reflected), `disabled`
11263
13061
  (reflected), `required` (reflected — enforced via `internals.setValidity()`).
11264
13062
 
13063
+ **Methods:** `click()` (override) — same forwarding contract as `lr-model-select`'s own `click()`
13064
+ override (see that section for the full rationale): closed-dropdown mode forwards a real `.click()`
13065
+ to the trigger `<button>`, whose own `@click` handler opens it; free-text mode instead calls
13066
+ `.focus()` on the combobox `<input>`, since a synthetic `.click()` on a text input never dispatches
13067
+ `focus` the way a real click's `mousedown` default action does, and this mode's open behavior is
13068
+ wired to the input's native `focus` event, not a `click` handler on the input itself. Mirrors
13069
+ `<lr-button>`'s identical host `click()` forwarding.
13070
+
11265
13071
  **Events:** `lr-change` — `detail: { value, inCatalog }`. `lr-preview-request` — `detail: {
11266
13072
  voiceId, previewUrl? }`, cancelable. `lr-preview-change` — `detail: { voiceId }`, internal playback
11267
13073
  started (`voiceId`) or stopped (`null`). Plus mirrored native `input`/`change` and re-dispatched
@@ -11945,6 +13751,11 @@ invention (no Web Awesome equivalent).
11945
13751
  - `maxHeight: string = ''` (attribute: `max-height`) — caps the rendered block size and enables an
11946
13752
  internal scrollbar once content exceeds it (any valid CSS length). Empty string (the default)
11947
13753
  grows with content.
13754
+ - `appearance: 'card' | 'plain' = 'card'` (reflected) — visual chrome, mirroring `lr-card`'s
13755
+ `appearance` vocabulary. `'card'` keeps the bordered, filled, padded box. `'plain'` removes the
13756
+ border, background, padding and corner radius, so a trace nested inside an
13757
+ `lr-result-card`/`lr-agent-run` — which already draws a border — doesn't double the frame. The
13758
+ `max-height` scroll cap and the copy/frame affordances are unaffected either way.
11948
13759
 
11949
13760
  **Events:**
11950
13761
  - `lr-frame-select` (`detail: { file?: string; line?: number; column?: number; raw: string }`) —
@@ -11955,7 +13766,8 @@ invention (no Web Awesome equivalent).
11955
13766
 
11956
13767
  **Slots:** none.
11957
13768
 
11958
- **CSS parts:** `base` (the root wrapper; respects `max-height`), `message` (the leading error
13769
+ **CSS parts:** `base` (the root wrapper; respects `max-height`, and drops its card chrome under
13770
+ `appearance="plain"`), `message` (the leading error
11959
13771
  message text for a group), `group` (one chained-error group of frames), `frame` (a single frame
11960
13772
  button; carries `data-internal` for internal frames), `frame-function` (the frame's function
11961
13773
  name), `frame-location` (the frame's `file:line:col` text), `internal-toggle` (the collapse/expand
@@ -12014,6 +13826,10 @@ renders at the start of the action row, before Deny/Edit/Approve.
12014
13826
  **Properties:**
12015
13827
  - `open: boolean = false` (reflected) — set this (or call `close()`) to dismiss; there is no separate
12016
13828
  `show()`/`hide()` pair
13829
+ - `accessibleLabel: string | null = null` (attribute `aria-label`) — directly names the internal
13830
+ dialog panel; otherwise the tool-name heading supplies `aria-labelledby`. Mirrors
13831
+ `<lr-tool-result-dialog>`'s/`<lr-tool-select-dialog>`'s own host-`aria-label` override pattern; fed
13832
+ only by a host `aria-label`
12017
13833
  - `toolName: string = ''` (attribute `tool-name`) — the proposed call's name, e.g. `web_search`;
12018
13834
  drives the heading and the dialog's accessible name
12019
13835
  - `args: unknown = {}` (attribute: false) — the proposed call's arguments, rendered via
@@ -12026,21 +13842,26 @@ renders at the start of the action row, before Deny/Edit/Approve.
12026
13842
  `autoCorrect: string = 'off'` (attribute `autocorrect`), `autocomplete: string = 'off'`,
12027
13843
  `wrap: 'hard'|'soft'|'off' = 'soft'`, `inputMode: string = ''` (attribute `inputmode`),
12028
13844
  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.
13845
+ `<textarea>` while editing; the defaults keep browser editing assistance from changing JSON text.
13846
+ `pending: 'approve' | 'deny' | null = null` (reflected) which decision is awaiting host
13847
+ resolution while an `lr-approve`/`lr-deny` listener has called `preventDefault()` on the
13848
+ now-cancelable event; the pending button shows `loading`, the other is `disabled` (Approve is
13849
+ also still `disabled` while an in-progress edit is invalid JSON, independent of `pending`).
13850
+ Escape/backdrop dismissal is suppressed while `pending` is set. Finalize by calling
13851
+ `close('approve'|'deny')`, or clear `.pending` back to `null` to bounce back to the undecided
13852
+ state; `pending` also resets to `null` every time the dialog re-opens.
12034
13853
 
12035
13854
  **Methods:** `close(reason: ToolApprovalDialogCloseReason = 'api'): void` — closes the dialog, emits
12036
13855
  `lr-close` with `reason`, and returns focus to whatever had it before the dialog opened; a no-op if
12037
13856
  already closed.
12038
13857
 
12039
13858
  **Events:** `lr-approve` (`detail: { args: unknown }` — the current, already-parsed arguments: the
12040
- original `args` prop, or the user's edited-and-validated version if an edit was in progress; always
12041
- followed by `lr-close` with reason `'approve'`), `lr-deny` (no detail — `this.emit('lr-deny')` is
12042
- called with no second argument, so per the DOM spec's `CustomEventInit` default, `event.detail` is
12043
- `null`, not `undefined`; always followed by `lr-close` with reason `'deny'`), `lr-close`
13859
+ original `args` prop, or the user's edited-and-validated version if an edit was in progress.
13860
+ Cancelable: a listener calling `preventDefault()` sets `pending` to `'approve'` instead of
13861
+ closing; otherwise always followed by `lr-close` with reason `'approve'`), `lr-deny` (no detail
13862
+ `this.emit('lr-deny')` is called with no second argument, so per the DOM spec's `CustomEventInit`
13863
+ default, `event.detail` is `null`, not `undefined`. Cancelable, same `pending` mechanism, setting
13864
+ `pending` to `'deny'`; otherwise always followed by `lr-close` with reason `'deny'`), `lr-close`
12044
13865
  (`detail: ToolApprovalDialogCloseReason` — fired exactly once per dismissal, via Escape, a backdrop
12045
13866
  click, the Approve/Deny buttons, or a `close()` call)
12046
13867
 
@@ -12048,7 +13869,12 @@ click, the Approve/Deny buttons, or a `close()` call)
12048
13869
  rendered before the built-in Deny/Edit/Approve buttons.
12049
13870
 
12050
13871
  **CSS parts:** `backdrop`, `panel`, `header`, `tool-name`, `body`, `args-view`, `args-editor`, `error`,
12051
- `footer`, `deny-button`, `edit-button`, `approve-button`
13872
+ `footer`, `deny-button`, `edit-button`, `approve-button`,
13873
+ `deny-button-base`, `deny-button-label`, `deny-button-start`, `deny-button-end`,
13874
+ `deny-button-spinner`, `approve-button-base`, `approve-button-label`, `approve-button-start`,
13875
+ `approve-button-end`, `approve-button-spinner` (`deny-button`/`approve-button` are each an
13876
+ `<lr-button>` host; these five per-button parts are re-exported from its own `lr-button` parts via
13877
+ `exportparts`; `edit-button` stays a plain `<button>`, unaffected by this).
12052
13878
 
12053
13879
  **Themeable custom properties:** `--lr-tool-approval-dialog-overlay-color` (default
12054
13880
  `rgb(0 0 0 / 0.5)` — the backdrop scrim color; component-specific since no shared overlay token
@@ -12110,6 +13936,16 @@ shared composed-tree focus traversal used by the other modal families.
12110
13936
  this a mobile browser (notably iOS Safari, which defaults textarea `autocapitalize` to
12111
13937
  `'sentences'`) could auto-capitalize or auto-correct key/value text as the user edits, silently
12112
13938
  corrupting the JSON.
13939
+ - `deny-button`/`approve-button` are `<lr-button>` hosts (`variant="neutral"`/`"brand"` — this
13940
+ component has no `tone` property) — `--lr-button-*` theming reaches them directly. A consumer
13941
+ previously styling `::part(deny-button)`/`::part(approve-button)` for
13942
+ padding/border/font/`:hover`/`:focus-visible` must move that CSS onto the re-exported
13943
+ `deny-button-base`/`approve-button-base` sub-parts instead. `edit-button` is unaffected and stays
13944
+ a raw `<button>`.
13945
+ - An `lr-approve`/`lr-deny` listener can call `preventDefault()` to keep the decision open while
13946
+ its own async work is in flight — see `pending` above. While `pending` is set, Escape/backdrop
13947
+ dismissal is suppressed, so a consumer that never resolves the pending decision leaves the
13948
+ dialog open until it clears `.pending` or calls `close()` directly itself.
12113
13949
 
12114
13950
  ---
12115
13951
 
@@ -12265,6 +14101,15 @@ A small bordered card shell. Purely visual, with no state of its own beyond slot
12265
14101
  **Properties:**
12266
14102
  - `title: string = ''` — small heading for the card. Leave unset for an untitled card (e.g. a bare
12267
14103
  block of `lr-result-field` rows with no natural heading).
14104
+ - `compact: boolean = false` (reflected) — tighter header/body padding for dense contexts (a card
14105
+ rendered as a row in a transcript or result list), same convention as `<lr-agent-run>`'s own
14106
+ `compact`. Purely a density knob: the border and background stay, so use `appearance="plain"`
14107
+ instead to drop the chrome entirely.
14108
+ - `appearance: 'card' | 'plain' = 'card'` (reflected) — mirrors `lr-card`'s/`<lr-agent-run>`'s
14109
+ `appearance` vocabulary. `'card'` (the default) keeps the bordered, filled box. `'plain'` removes
14110
+ the border, background, and corner radius, so a card nested inside a host frame that already draws
14111
+ a border (e.g. `<lr-tool-result-view>`'s own chrome) doesn't double it. `plain` wins over `compact`
14112
+ when both are set (nothing left to tighten).
12268
14113
 
12269
14114
  **Events:** none.
12270
14115
 
@@ -12279,8 +14124,11 @@ later `slotchange` on `actions` is still observed, but `hidden` whenever there's
12279
14124
  default tooltip, scoped to just this element rather than the whole card), `actions` (`hidden`
12280
14125
  whenever the slot has no assigned content), `body`.
12281
14126
 
12282
- **Themeable custom properties:** shared tokens only — `--lr-space-xs`/`-s`, `--lr-color-border`/
12283
- `-surface`/`-text`, `--lr-radius`.
14127
+ **Themeable custom properties:** `--lr-result-card-compact-header-padding` (default
14128
+ `var(--lr-space-xs)`) — `[part="header"]` block/inline padding while `compact`;
14129
+ `--lr-result-card-compact-body-padding` (default `var(--lr-space-xs)`) — `[part="body"]` padding
14130
+ while `compact`; plus shared tokens — `--lr-space-xs`/`-s`, `--lr-color-border`/`-surface`/`-text`,
14131
+ `--lr-radius`.
12284
14132
 
12285
14133
  ### `lr-result-field`
12286
14134
 
@@ -12380,9 +14228,19 @@ Space).
12380
14228
  bar), `meta` (secondary row info, shown inline under 480px), `status-text`, `duration`, `empty` (shown
12381
14229
  when `spans` is empty), and `live-region`.
12382
14230
 
12383
- **Themeable custom properties:** `--lr-span-waterfall-name-width` (default `8rem`) and
14231
+ **Themeable custom properties:** `--lr-span-waterfall-name-width` (default `8rem`),
12384
14232
  `--lr-span-waterfall-stripe-speed` (a `running` span's striped-bar animation duration; defaults to
12385
- `--lr-transition-ambient`).
14233
+ `--lr-transition-ambient`), and `--lr-span-waterfall-row-active-bg` (default
14234
+ `var(--lr-color-brand-quiet)`) — the background of the active (`activeSpanId`) row.
14235
+
14236
+ That last one follows the convention every **state-scoped** custom property in this family uses, and
14237
+ it is worth reading once: it is an inline `var()` fallback at its point of use and is deliberately
14238
+ **not** declared on `:host`, so it can be set on the element *or on any ancestor* and still reach the
14239
+ rule that consumes it. It exists because Shadow Parts forbids an attribute selector after `::part()`
14240
+ — `::part(row)[data-active]` and every selector like it is invalid CSS — so before it, the only way
14241
+ to restyle a state-dependent surface was to override a library-wide `--lr-color-*` token, which repaints
14242
+ every other surface reading that token. Every `*-active-*`, `*-selected-*` and per-state color
14243
+ property below works the same way.
12386
14244
 
12387
14245
  ## `lr-task-list`
12388
14246
 
@@ -12397,7 +14255,13 @@ status: TaskStatus; detail?: string; children?: TaskItem[] }` with `TaskStatus =
12397
14255
  'running' | 'success' | 'error'` (both exported here). `detail` is an optional secondary plain-text
12398
14256
  line; `children` is exactly **one** level of sub-steps — a child's own `children` is ignored with a
12399
14257
  `console.warn`. `label: string = 'Tasks'`, `expanded: boolean = true` (reflected), and
12400
- `collapsible: boolean = true`.
14258
+ `collapsible: boolean = true`. `compact: boolean = false` (reflected) — tighter header/body padding
14259
+ and item gap for dense contexts (a plan tracker nested in an already-padded transcript row), same
14260
+ convention as `<lr-agent-run>`'s/`<lr-source-card>`'s `compact`; purely a density knob, the border
14261
+ and background stay. `appearance: 'card' | 'plain' = 'card'` (reflected) — mirrors `lr-card`'s
14262
+ `appearance` vocabulary; `'plain'` removes `[part="base"]`'s border, background, and corner radius so
14263
+ a list embedded in a frame that already draws a border (an agent-run panel, a message bubble) doesn't
14264
+ double it.
12401
14265
 
12402
14266
  **Slots:** `detail-<id>` — dynamic, one per item id (e.g. `slot="detail-step-3"`); rich detail under
12403
14267
  that item's label, typically a `<lr-tool-call-chip>` or file `<lr-chip>`.
@@ -12413,7 +14277,11 @@ indicator, only rendered when `collapsible`), `body` (the list of items, `hidden
12413
14277
  children).
12414
14278
 
12415
14279
  **Themeable custom properties:** `--lr-task-list-spin` (default `1s linear`) — running-status icon
12416
- spin animation duration/timing.
14280
+ spin animation duration/timing; `--lr-task-list-compact-header-padding` (default
14281
+ `var(--lr-space-2xs) var(--lr-space-s)`) — `[part="header"]` padding while `compact`;
14282
+ `--lr-task-list-compact-gap` (default `var(--lr-space-2xs)`) — gap between `[part="body"]`'s item
14283
+ rows while `compact`; `--lr-task-list-compact-body-padding` (default `var(--lr-space-2xs)
14284
+ var(--lr-space-s) var(--lr-space-s)`) — `[part="body"]` padding while `compact`.
12417
14285
 
12418
14286
  ## `lr-terminal`
12419
14287
 
@@ -12441,12 +14309,24 @@ text, anchor, rects }`).
12441
14309
 
12442
14310
  **CSS parts:** `base`, `toolbar` (only rendered when copy/download are enabled), `copy-button`,
12443
14311
  `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
14312
+ `data-line-number`/`data-match`/`data-highlight-tone`, and is forwarded via `exportparts` so
14313
+ `lr-terminal::part(line)` reaches the rendered lines from a consumer stylesheet despite them living
14314
+ in the internal `<lr-virtual-list>`'s shadow root), `jump-to-latest` (shown while `follow` is
12445
14315
  disengaged and new output has arrived), and `announcer` (the visually-hidden `role="status"` region
12446
14316
  used when `announce-output` is set).
12447
14317
 
12448
14318
  **Themeable custom properties:** `--lr-terminal-height` (default `var(--lr-size-20rem)`) — the
12449
- viewport's block size.
14319
+ viewport's block size; not declared on `:host`, so it is inherited from the host or any ancestor.
14320
+ `--lr-terminal-highlight-accent-bg` (default `var(--lr-color-brand-quiet)`),
14321
+ `--lr-terminal-highlight-success-bg` (default `var(--lr-color-success-quiet)`),
14322
+ `--lr-terminal-highlight-warning-bg` (default `var(--lr-color-warning-quiet)`),
14323
+ `--lr-terminal-highlight-danger-bg` (default `var(--lr-color-danger-quiet)`), and
14324
+ `--lr-terminal-highlight-neutral-bg` (default `var(--lr-color-surface)`) — the background of a
14325
+ `highlights[]` entry of the matching `tone`. Each is decoupled from the identical shared token it
14326
+ falls back to (e.g. `accent`'s `--lr-color-brand-quiet` is also the copy/download-button hover tint)
14327
+ so retinting one tone doesn't repaint the other surface reading that token, and from any
14328
+ `::part('line')` stylesheet override — the background is applied inline, so a stylesheet rule can't
14329
+ beat it without `!important`.
12450
14330
 
12451
14331
  ## `lr-trace-tree`
12452
14332
 
@@ -12472,6 +14352,29 @@ as a root rather than being dropped. `activeSpanId: string | null = null`
12472
14352
  `duration`, `tokens-in`, `tokens-out` (when `showTokens`), `cost` (when `showCost`), `bar-track`,
12473
14353
  `bar`, `empty` (shown when `spans` is empty), and `live-region`.
12474
14354
 
14355
+ **Themeable custom properties:** `--lr-trace-tree-row-active-bg` (default
14356
+ `var(--lr-color-brand-quiet)`) — the background of the active (`activeSpanId`) row — and
14357
+ `--lr-trace-tree-row-active-color` (default `var(--lr-color-text)`) — the color of that row's
14358
+ secondary text (`detail`, `duration`, `tokens-in`, `tokens-out`, `cost`, and the `pending`
14359
+ `status-text` label). Same state-scoped-property convention described under `lr-span-waterfall`
14360
+ above: an inline `var()` fallback rather than a `:host` declaration, so either can be set on the
14361
+ element or any ancestor, and they exist because `::part(row)[data-active]` is invalid CSS.
14362
+
14363
+ **Contrast note:** the active row is more than a tint. Its secondary text would sit at ~4.25:1
14364
+ against the default tint if it stayed at `--lr-color-text-quiet`, so it rises to full-strength
14365
+ `--lr-color-text` while the row is active, and the semantic `status-text` labels are rendered as
14366
+ `color-mix(in srgb, var(--lr-color-<tone>) 75%, var(--lr-color-text))` — keeping the status hue
14367
+ (an error row stays red) while clearing the 4.5:1 floor (success 4.46 → 6.18, `denied` 4.28 →
14368
+ 5.96). Both adjustments are theme-symmetric, because `--lr-color-text` flips with the color
14369
+ scheme. `[part='bar']` is deliberately untouched: it is a non-text graphic on a 3:1 floor, and its
14370
+ saturation is the row's primary status signal.
14371
+
14372
+ The two properties are a **pair**. The defaults assume the active background stays on the same
14373
+ side of the lightness midpoint as the ambient surface, so a consumer who sets
14374
+ `--lr-trace-tree-row-active-bg` to a dark tint in light mode (or a light one in dark mode) must
14375
+ set `--lr-trace-tree-row-active-color` to match, and should re-check the status-label tones
14376
+ against the new tint as well.
14377
+
12475
14378
  ## `lr-activity-feed`
12476
14379
 
12477
14380
  An append-only streaming log of granular agent actions ("Searching the web…", "Read
@@ -12500,12 +14403,21 @@ rather than augmenting it, and `virtualizeThreshold: number = 200` (attribute
12500
14403
 
12501
14404
  **CSS parts:** `base`, `header` (a `<button>`), `status-dot` (pulses while `mode="live"`),
12502
14405
  `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).
14406
+ `data-tone`), `entry-icon`, `tone-dot` (the dot rendered inside `entry-icon` when the entry sets no
14407
+ literal `icon`), `tone-dot-neutral`/`tone-dot-brand`/`tone-dot-success`/`tone-dot-warning`/
14408
+ `tone-dot-danger` (each also carries `tone-dot`), `entry-text`, and `entry-timestamp` (only while
14409
+ `showTimestamps` and a valid `timestamp` is set). Every entry-level part is reachable in both
14410
+ rendering paths, virtualized or not.
12505
14411
 
12506
14412
  **Themeable custom properties:** `--lr-activity-feed-max-height` (default `16rem`) — cap on how
12507
14413
  tall the expanded body grows before it scrolls internally.
12508
14414
 
14415
+ **Known gotchas:**
14416
+ - The tone dot's color is selected by its *part name*, not by `[data-tone]`: `::part()` cannot be
14417
+ followed by an attribute selector, so `lr-activity-feed::part(tone-dot)[data-tone='success']`
14418
+ never matches. Target `lr-activity-feed::part(tone-dot-success)` instead. `data-tone` remains on
14419
+ both the entry and the dot for DOM queries.
14420
+
12509
14421
  ## `lr-commit-card`
12510
14422
 
12511
14423
  A compact commit summary (subject, author/time, diffstat, per-file changes) that links file rows out
@@ -12518,6 +14430,13 @@ number` (attribute: false, epoch milliseconds), `files: CommitFileChange[] = []`
12518
14430
  'conflicted' | 'ignored'` (shared with `lr-file-tree`); the diffstat is summed from `additions`/
12519
14431
  `deletions` across `files`. `filesCollapsed:
12520
14432
  boolean = true` (attribute `files-collapsed`, reflected), and `copyable: boolean = true` (reflected).
14433
+ `compact: boolean = false` (reflected) — tighter `[part="base"]` padding for a commit rendered as a
14434
+ row in a list or PR timeline, same convention as `<lr-agent-run>`'s own `compact`; the border stays,
14435
+ so pair it with `appearance="plain"` to drop the chrome entirely. `appearance: 'card' | 'plain' =
14436
+ 'card'` (reflected) — mirrors `lr-card`'s/`<lr-agent-run>`'s `appearance` vocabulary: `'card'` keeps
14437
+ the bordered, padded box, `'plain'` removes the border, padding, and corner radius so a commit nested
14438
+ in a host list that already draws its own row chrome doesn't double it; `plain` wins over `compact`
14439
+ when both are set.
12521
14440
 
12522
14441
  **Slots:** `actions` — trailing header controls (e.g. an "open PR" button).
12523
14442
 
@@ -12528,6 +14447,9 @@ boolean = true` (attribute `files-collapsed`, reflected), and `copyable: boolean
12528
14447
  `deletions`, `files-toggle`, `file` (carries `data-status`), `file-path`, `file-additions`,
12529
14448
  `file-deletions`, `copy-button`, and `actions`.
12530
14449
 
14450
+ **Themeable custom properties:** `--lr-commit-card-compact-padding` (default `var(--lr-space-s)`) —
14451
+ `[part="base"]` padding while `compact`.
14452
+
12531
14453
  ## `lr-test-results`
12532
14454
 
12533
14455
  A pass/fail suite summary with per-status counts, status filter toggles, and per-test rows whose
@@ -12555,6 +14477,17 @@ expanded/collapsed).
12555
14477
  `data-status`), `test-status`, `test-name`, `test-duration`, `test-expand-toggle`, `failure`
12556
14478
  (hidden while collapsed), and `failure-message`.
12557
14479
 
14480
+ **Themeable custom properties:** `--lr-test-results-filter-active-bg` (default
14481
+ `var(--lr-color-brand-quiet)`), `--lr-test-results-filter-active-border` (default
14482
+ `var(--lr-color-brand)`) and `--lr-test-results-filter-active-color` (default
14483
+ `var(--lr-color-brand)`) — the background, border color and text color of a pressed (active) status
14484
+ filter toggle. All three follow the state-scoped-property convention described under
14485
+ `lr-span-waterfall`: inline `var()` fallbacks rather than `:host` declarations, so each can be set on
14486
+ the element or on any ancestor. They exist because
14487
+ `::part(filter-toggle)[aria-pressed='true']` is invalid CSS — Shadow Parts forbids an attribute
14488
+ selector after `::part()` — so restyling the pressed state otherwise meant overriding the
14489
+ library-wide brand tokens.
14490
+
12558
14491
  ## `lr-confirm-bar`
12559
14492
 
12560
14493
  An inline, non-modal approve/deny block for one proposed action — the in-flow sibling of
@@ -12572,7 +14505,18 @@ free-form heading override for non-tool proposals; wins over `toolName`. `args:
12572
14505
  (attribute: false) — shown read-only inside a collapsed `lr-details` + `lr-json-viewer` when
12573
14506
  defined. `decision: 'approved' | 'denied' | null = null` (reflected) — decided state, set by the
12574
14507
  component on activation and host-writable (an externally-resolved decision renders identically but
12575
- emits nothing). `tone: 'neutral' | 'danger' = 'neutral'` (reflected).
14508
+ emits nothing). `tone: 'neutral' | 'danger' = 'neutral'` (reflected). `compact: boolean = false`
14509
+ (reflected) — collapses the bar from a full card (bordered, padded, `display: block` surface) to a
14510
+ single inline row with no chrome of its own, for a confirmation that has to live inside an existing
14511
+ container: a table cell, a card's action row, a toolbar. The host becomes `inline-flex`, and the
14512
+ narrow-allocation `@container` treatment is switched off — a compact bar is *expected* to be narrow,
14513
+ so stretching the buttons to fill would be exactly wrong. Re-chrome it through the
14514
+ `--lr-confirm-bar-compact-*` properties below. Everything else is unchanged: the event shapes, the
14515
+ focus-to-`[part="status"]`-before-unmount contract, and `role="group"` with its heading label.
14516
+ `pending: 'approved' | 'denied' | null = null` (reflected) — which decision is awaiting host
14517
+ resolution while an `lr-approve`/`lr-deny` listener has called `preventDefault()` on the
14518
+ now-cancelable event; the pending button shows `loading`, the other is `disabled`. Set `.decision`
14519
+ to finalize, or clear `.pending` back to `null` to bounce back to the undecided state.
12576
14520
 
12577
14521
  **Slots:** default — supplementary body content between the heading and the actions (e.g. a
12578
14522
  `lr-diff-view`). `footer` — extra content at the start of the action row.
@@ -12582,8 +14526,37 @@ emits nothing). `tone: 'neutral' | 'danger' = 'neutral'` (reflected).
12582
14526
 
12583
14527
  **CSS parts:** `base` (`role="group"`), `heading`/`tool-name`, `body`, `args` (the
12584
14528
  details/json-viewer wrapper, only rendered when `args` is defined), `footer`, `deny-button`,
12585
- `approve-button` (named identically to the dialog's parts), `status` (the decided-state text, always
12586
- present in the DOM as a focus landing spot).
14529
+ `approve-button` (each an `<lr-button>` host, named identically to the dialog's parts),
14530
+ `deny-button-base`, `deny-button-label`, `deny-button-start`, `deny-button-end`,
14531
+ `deny-button-spinner`, `approve-button-base`, `approve-button-label`, `approve-button-start`,
14532
+ `approve-button-end`, `approve-button-spinner` (re-exported from each button's own
14533
+ `lr-button` parts via `exportparts`), `status` (the decided-state text, always present in the DOM
14534
+ as a focus landing spot).
14535
+
14536
+ **Themeable custom properties:** the `compact` presentation is deliberately chrome-less by default
14537
+ and re-chromed entirely through five properties, all scoped to `[part="base"]` while `compact`:
14538
+ `--lr-confirm-bar-compact-padding` (default `0`, any padding shorthand),
14539
+ `--lr-confirm-bar-compact-gap` (default `var(--lr-space-s)`, the gap between the row's items),
14540
+ `--lr-confirm-bar-compact-border` (default `none`, any `border` shorthand),
14541
+ `--lr-confirm-bar-compact-background` (default `transparent`) and
14542
+ `--lr-confirm-bar-compact-radius` (default `0` — only visible once the border or background is set).
14543
+ They are inline `var()` fallbacks at their point of use rather than `:host` declarations, so any of
14544
+ them can be set on the element *or on any ancestor*, which is what makes "give every compact confirm
14545
+ bar in this panel a hairline border" a one-rule change on the panel.
14546
+
14547
+ **Known gotchas:**
14548
+ - `[part="status"]` is always rendered and must never be given `display: none`. Deciding moves focus
14549
+ to it synchronously, before the Deny/Approve buttons unmount, so hiding it would drop focus to
14550
+ `<body>`. The shipped `:empty` rule on it has never matched, and that is load-bearing.
14551
+ - `[part="deny-button"]`/`[part="approve-button"]` are `<lr-button>` hosts (`variant="neutral"`/
14552
+ `"brand"`, `"danger"` under `tone="danger"`) — `--lr-button-*` theming reaches them directly. A
14553
+ consumer previously styling `::part(deny-button)`/`::part(approve-button)` for
14554
+ padding/border/font/`:hover`/`:focus-visible` must move that CSS onto the re-exported
14555
+ `deny-button-base`/`approve-button-base` sub-parts instead — the outer part now resolves to the
14556
+ `<lr-button>` host, where those declarations either do nothing or must be re-expressed through
14557
+ `lr-button`'s own parts/custom properties.
14558
+ - An `lr-approve`/`lr-deny` listener can call `preventDefault()` to keep the decision open while
14559
+ its own async work is in flight — see `pending` above.
12587
14560
 
12588
14561
  ```html
12589
14562
  <lr-tool-call-chip status="pending"></lr-tool-call-chip>
@@ -12592,6 +14565,18 @@ present in the DOM as a focus landing spot).
12592
14565
  ></lr-confirm-bar>
12593
14566
  ```
12594
14567
 
14568
+ An `lr-approve`/`lr-deny` listener that needs to await its own async work before finalizing calls
14569
+ `preventDefault()` and sets `.decision` (or clears `.pending`) once it resolves:
14570
+
14571
+ ```ts
14572
+ bar.addEventListener('lr-approve', (e) => {
14573
+ e.preventDefault();
14574
+ runApproval(e.detail.args)
14575
+ .then(() => { bar.decision = 'approved'; })
14576
+ .catch(() => { bar.pending = null; }); // bounce back, retry
14577
+ });
14578
+ ```
14579
+
12595
14580
  ## `lr-browser-frame`
12596
14581
 
12597
14582
  Presentational "agent computer" viewport: a screenshot/frame stream (or slotted live media), a
@@ -12667,12 +14652,22 @@ src? }`, with the sanitized download URL).
12667
14652
 
12668
14653
  **CSS parts:** `base`, `header`, `label`, `kind`, `view-toggle` (rendered only once the `code` slot
12669
14654
  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`
14655
+ (rendered only once `versions` is non-empty), `version-previous`, `version-previous-glyph` (the `‹`
14656
+ chevron inside `version-previous`, mirrored via `scaleX(-1)` under `:dir(rtl)`), `version-next`,
14657
+ `version-next-glyph` (the `›` chevron inside `version-next`, mirrored the same way), `version-position`
12671
14658
  (the "Version N of M" text), `restore-button` (rendered only while the active version isn't the
12672
14659
  latest), `actions`, `copy-button` (rendered only while `copyText` is non-empty), `download-button`
12673
14660
  (rendered only while `downloadSrc` is non-empty), `body`, `streaming-indicator` (rendered only while
12674
14661
  `streaming`).
12675
14662
 
14663
+ **Themeable custom properties:** `--lr-artifact-panel-view-active-bg` (default
14664
+ `var(--lr-color-brand-quiet)`) and `--lr-artifact-panel-view-active-color` (default
14665
+ `var(--lr-color-brand)`) — the background and text color of the pressed (active) preview/code toggle
14666
+ button. Both follow the state-scoped-property convention described under `lr-span-waterfall`: inline
14667
+ `var()` fallbacks rather than `:host` declarations, so either can be set on the element or on any
14668
+ ancestor. They exist because `::part(view-button)[aria-pressed='true']` is invalid CSS, leaving the
14669
+ library-wide brand tokens as the only prior lever.
14670
+
12676
14671
  ```html
12677
14672
  <lr-artifact-panel label="report.md" kind="document" .versions=${versions}
12678
14673
  @lr-restore=${(e) => restoreVersion(e.detail.versionId)}>
@@ -12718,6 +14713,16 @@ cancelable. Retry is available for `error` and `cancelled`.
12718
14713
  `show-retry`) — whether the built-in buttons may render at all, still gated by the run's own
12719
14714
  status. Both use a `true`-defaulting string converter, so plain-HTML `show-cancel="false"` works; a
12720
14715
  `?show-cancel=${false}` boolean-attribute binding starting from absent markup does not
14716
+ - `compact: boolean = false` (reflected) — tighter root padding and header/body gap for dense
14717
+ contexts (a run rendered as a row in a list, or in a side panel); same convention as `lr-empty`'s
14718
+ `compact`. Purely a density knob: the border and background stay, so reach for
14719
+ `appearance="plain"` instead when the goal is to drop the chrome entirely
14720
+ - `appearance: 'card' | 'plain' = 'card'` (reflected) — visual chrome, mirroring `lr-card`'s
14721
+ `appearance` vocabulary. `'card'` keeps the bordered, filled, padded box; `'plain'` removes the
14722
+ border, background, padding and corner radius, so a run nested inside a host frame that already
14723
+ draws a border doesn't double it. `plain` wins over `compact` when both are set — there is no
14724
+ padding left to tighten. The built-in Cancel/Retry buttons draw their own border and background
14725
+ and stay visibly interactive either way
12721
14726
 
12722
14727
  **Events:** `lr-cancel` (`detail: CancelEventDetail` = `{ reason?: string }`, from
12723
14728
  `@aceshooting/lyra-ui/ai`; `reason` is `undefined` from the built-in button), `lr-retry`
@@ -12734,7 +14739,12 @@ this component's own retry counter, reset when `run.id` changes).
12734
14739
  (carries `data-variant`), `empty`.
12735
14740
 
12736
14741
  **Themeable custom properties:** `--lr-agent-run-spin` (default `1s linear`) — the running-status
12737
- spinner icon's rotation duration/timing.
14742
+ spinner icon's rotation duration/timing. `--lr-agent-run-compact-padding` (default
14743
+ `var(--lr-space-s)`) and `--lr-agent-run-compact-gap` (default `var(--lr-space-s)`) — `[part="base"]`'s
14744
+ padding, and the gap between its header and body, while `compact`; both are ignored while `compact`
14745
+ is unset. Like the other density/state properties in this family they are inline `var()` fallbacks at
14746
+ their point of use rather than `:host` declarations, so either can be set on the element *or on any
14747
+ ancestor* — one rule on a run list retunes every compact run inside it.
12738
14748
 
12739
14749
  ## `lr-agent-trace`
12740
14750
 
@@ -12767,6 +14777,17 @@ graph node-type ids).
12767
14777
  visible span has `kind: 'agent'`), `handoff` (one entry — a `<button>` wrapping an
12768
14778
  `lr-handoff-divider`, carrying `data-active`), `tree` (the composed `lr-trace-tree`).
12769
14779
 
14780
+ **Themeable custom properties:** `--lr-agent-trace-handoff-active-bg` (default
14781
+ `var(--lr-color-brand-quiet)`) — the background of the active (`activeSpanId`) handoff quick-jump
14782
+ entry. Same state-scoped-property convention described under `lr-span-waterfall`: an inline `var()`
14783
+ fallback rather than a `:host` declaration, settable on the element or any ancestor, and it exists
14784
+ because `::part(handoff)[data-active]` is invalid CSS. The composed tree's own
14785
+ `--lr-trace-tree-row-active-bg` and `--lr-trace-tree-row-active-color` are separate knobs and
14786
+ inherit straight through, so restyling both surfaces means setting both — and they carry the
14787
+ pairing caveat documented under `lr-trace-tree` above: the tree's active-row defaults assume the
14788
+ active background stays on the same side of the lightness midpoint as the ambient surface, so a
14789
+ tint that crosses it needs the matching text color set too.
14790
+
12770
14791
  ## `lr-context-inspector`
12771
14792
 
12772
14793
  Inspection view of model-call context segments, with token estimates, source citations, redaction
@@ -12815,7 +14836,7 @@ Filterable and taggable evaluation-example list with add, remove, import, and ex
12815
14836
  expectedOutput?: string; tags?: string[]; metadata?: Record<string, unknown> }` (exported here).
12816
14837
  Deliberately its own small shape rather than reusing anything from `src/ai/types.ts` — none of that
12817
14838
  module's interfaces models "one row of a labeled eval dataset". `input`/`expectedOutput` are plain
12818
- strings (not structured payloads) to match `lr-data-grid`'s stringifying cell rendering. Fully
14839
+ strings (not structured payloads), rendered as plain text by every column's `cell()`. Fully
12819
14840
  controlled: add/remove/import/export are all *requests*; the host mutates and passes the array back
12820
14841
  - `searchable: boolean = false` (reflected) — built-in free-text search over `input`,
12821
14842
  `expectedOutput`, and `tags` (case-insensitive substring)
@@ -12830,7 +14851,9 @@ Filterable and taggable evaluation-example list with add, remove, import, and ex
12830
14851
 
12831
14852
  **Events:** `lr-example-select` (`detail: { id: string | null }`), `lr-example-add-request`
12832
14853
  (`detail: undefined`), `lr-example-remove-request` (`detail: { id: string }`), `lr-import-request`
12833
- (`detail: { files: File[] }`), `lr-export-request` (`detail: { format: string }`).
14854
+ (`detail: { files: File[] }`), `lr-export-request` (`detail: { format: string }`). `focus`/`blur` —
14855
+ re-dispatched (no detail) when the internal search field (only rendered while `searchable`) gains or
14856
+ loses focus, since native focus neither bubbles nor crosses the shadow boundary.
12834
14857
 
12835
14858
  **CSS parts:** `base`, `toolbar`, `search`, `search-input`, `tag-filter`, `grid`,
12836
14859
  `add-button`, `remove-button`, `import`, `export`.
@@ -12844,7 +14867,7 @@ Filterable and taggable evaluation-example list with add, remove, import, and ex
12844
14867
 
12845
14868
  Rubric scoring and human-review surface for comparing the runs of one evaluation example.
12846
14869
 
12847
- Composes `lr-data-grid` (the comparison table), `lr-rubric-form` (the review surface), and
14870
+ Composes `lr-table` (the comparison table), `lr-rubric-form` (the review surface), and
12848
14871
  `lr-diff-view` (baseline↔selected output diff) rather than re-deriving any of their behavior.
12849
14872
 
12850
14873
  **Properties:**
@@ -12852,10 +14875,10 @@ Composes `lr-data-grid` (the comparison table), `lr-rubric-form` (the review sur
12852
14875
  model?: string; promptVersion?: string; output: string; scores?: RubricValue; review?: RubricValue }`
12853
14876
  (exported here). One entry per model or prompt version being compared for a single evaluation
12854
14877
  example. `scores`/`review` use the same `RubricValue` shape `lr-rubric-form` itself reads and
12855
- writes, so a `DataGridColumn`'s `value()` accessor and the rubric form's own `value` binding read a
14878
+ writes, so a `TableColumn`'s `cell()` accessor and the rubric form's own `value` binding read a
12856
14879
  run's fields with no conversion
12857
- - `columns: DataGridColumn<EvalRunResult>[] = []` (attribute: false) — plain pass-through to
12858
- `lr-data-grid.columns`, not re-derived here
14880
+ - `columns: TableColumn<EvalRunResult>[] = []` (attribute: false) — plain pass-through to
14881
+ `lr-table.columns`, not re-derived here
12859
14882
  - `rubricKeys: RubricKey[] = []` (attribute: false) — plain pass-through to `lr-rubric-form.keys`
12860
14883
  - `selectedRunId: string = ''` (attribute `selected-run-id`) — the run open for review and the diff's
12861
14884
  **new** side; falls back to `runs[0]?.id` when empty
@@ -12935,6 +14958,16 @@ gate.
12935
14958
  **CSS parts:** `base`, `empty`, `summary`, `count`, `state-badge`,
12936
14959
  `list`, `decision`, `decision-header`, `category`, `label`, `detail`, `explanation`.
12937
14960
 
14961
+ **Themeable custom properties:** `--lr-policy-summary-count-allow-color` (default
14962
+ `var(--lr-color-success)`), `--lr-policy-summary-count-deny-color` (default
14963
+ `var(--lr-color-danger)`) and `--lr-policy-summary-count-needs-review-color` (default
14964
+ `var(--lr-color-warning)`) — the text color of each state's count in the summary strip. All three
14965
+ follow the state-scoped-property convention described under `lr-span-waterfall`: inline `var()`
14966
+ fallbacks rather than `:host` declarations, so each can be set on the element or on any ancestor.
14967
+ They exist because `::part(count)[data-state='deny']` is invalid CSS — Shadow Parts forbids an
14968
+ attribute selector after `::part()` — so retoning one state's count otherwise meant overriding the
14969
+ library-wide status tokens and repainting every other surface reading them.
14970
+
12938
14971
  ## `lr-tool-timeline`
12939
14972
 
12940
14973
  Chronological list of agent tool/function calls composed from tool-call, result, and approval
@@ -12978,7 +15011,12 @@ can ignore it; one actually executing the tool needs it.
12978
15011
 
12979
15012
  **Themeable custom properties:** `--lr-tool-timeline-gap` (default `var(--lr-space-l)`) — vertical
12980
15013
  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.
15014
+ per-entry timeline marker dot's size, which also sets the entry grid's leading column width;
15015
+ `--lr-tool-timeline-denied-marker-color` (default `var(--lr-color-warning)`) — rail-dot color for a
15016
+ `status="denied"` entry, decoupled from the pending-approval border color below so either can be
15017
+ retinted independently; `--lr-tool-timeline-pending-approval-border-color` (default
15018
+ `var(--lr-color-warning)`) — color of the entry body's leading border while that entry's
15019
+ `data-pending-approval` is `"true"`.
12982
15020
 
12983
15021
  # Retrieval, knowledge graph & grounding (`components/retrieval/`)
12984
15022
 
@@ -13074,7 +15112,10 @@ Enter/Space activations within 500ms — regardless of `GraphNode.expandable`),
13074
15112
  `label`, `link-label` (a drawn edge label, only rendered when `showEdgeLabels` is set),
13075
15113
  `expand-indicator` (the "+" badge on a node with `expandable: true`), `focus-halo` (the persistent
13076
15114
  ring tracking `focusId`'s node), `hull` (a community hull), `community-label`,
13077
- `live-region`, `data-list`, `empty`, `canvas`/`tooltip`/`cursor-items`/`cursor-item`
15115
+ `live-region`, `data-list`, `empty`, `error` (`role="alert"` message shown instead of the graph when
15116
+ the optional `d3-force`/`d3-drag`/`d3-zoom`/`d3-selection` peers fail to load —
15117
+ distinct from the empty state, which means the peers loaded fine but `nodes` is empty),
15118
+ `canvas`/`tooltip`/`cursor-items`/`cursor-item`
13078
15119
  (`renderer="canvas"` only — the drawing surface, its hover tooltip replacing the SVG `<title>`, and
13079
15120
  the offscreen keyboard-roving items)
13080
15121
 
@@ -13215,7 +15256,9 @@ with a `droppable` canvas on the `FLOW_PALETTE_MIME_TYPE` drag payload shape.
13215
15256
 
13216
15257
  **Events:** `lr-palette-place` (`detail: { type }`, a pointer click or Enter/Space — the
13217
15258
  click/keyboard alternative to dragging), `lr-select` (`detail: { item }`, emitted alongside
13218
- `lr-palette-place` on both gestures, carrying the full item).
15259
+ `lr-palette-place` on both gestures, carrying the full item), `focus`/`blur` (no detail —
15260
+ re-dispatched from the internal search field's own `focus`/`blur`, bubbling and composed unlike
15261
+ the native events, since neither bubbles nor crosses the shadow boundary on its own).
13219
15262
 
13220
15263
  **Slots:** `header` (content above the search field, e.g. a heading or tabs), `footer` (content
13221
15264
  below the list).
@@ -13278,7 +15321,10 @@ after each toggle).
13278
15321
  **CSS parts:** `base`, `item` (a `<button>` when `interactive`, a plain `<div>` otherwise), `swatch`,
13279
15322
  `label`, `count`, `live-region` (the visually hidden filter-toggle announcement).
13280
15323
 
13281
- **Themeable custom properties:** no component-local tokens; reads `--lr-graph-cat-1` through `-8`
15324
+ **Themeable custom properties:** `--lr-graph-legend-hidden-color` (default
15325
+ `var(--lr-color-text-quiet)`) — text color of a filtered-out (hidden) row's `label`/`count`,
15326
+ independent of the shared quiet-text token so a host can retint "hidden" rows without repainting
15327
+ every other quiet-text surface. Also reads `--lr-graph-cat-1` through `-8`
13282
15328
  (the same computed-style fallback palette `lr-graph`/`lr-word-cloud` use) plus shared tokens.
13283
15329
 
13284
15330
  **Optional peer deps:** none.
@@ -13321,6 +15367,15 @@ itself — `lr-entity-activate` is a request a host routes into `lr-graph`'s own
13321
15367
  `lr-graph-legend.types` entry shape, resolving `entity.type` to a label/color/shape for the badge
13322
15368
  - `communityLabel: string = ''` (attribute `community-label`) — override text for the community chip
13323
15369
  - `showFocusButton: boolean = true` (attribute `show-focus-button`)
15370
+ - `compact: boolean = false` (reflected) — tighter root padding and row gap for dense contexts (a
15371
+ dossier rendered in a sidebar, a result list) — the same convention as `lr-empty`'s `compact` and
15372
+ as this component's sibling `lr-community-card`. Purely a density knob: the border and background
15373
+ stay. `false` (the default) keeps the full card padding.
15374
+ - `appearance: 'card' | 'plain' = 'card'` (reflected) — visual chrome, mirroring `lr-card`'s
15375
+ `appearance` vocabulary. `'card'` (the default) keeps the bordered, filled, padded box; `'plain'`
15376
+ removes the border, background, padding and corner radius, so a card nested inside a container
15377
+ that already draws a border doesn't double the frame. `plain` wins over `compact` when both are
15378
+ set — there is nothing left to tighten.
13324
15379
 
13325
15380
  **Events:** `lr-entity-activate` (`detail: { id }`, the built-in focus button was activated).
13326
15381
 
@@ -13331,7 +15386,11 @@ itself — `lr-entity-activate` is a request a host routes into `lr-graph`'s own
13331
15386
  `description`, `properties`, `property` (one key/value row), `degree`, `community`, `actions`,
13332
15387
  `focus-button`, `empty` (shown when `entity` is `null`).
13333
15388
 
13334
- **Themeable custom properties:** shared tokens only; a data-driven `entity.type` color is applied as
15389
+ **Themeable custom properties:** `--lr-entity-card-compact-padding` (default `var(--lr-space-s)`)
15390
+ `[part='base']`'s padding while `compact`; `--lr-entity-card-compact-gap` (default
15391
+ `var(--lr-space-xs)`) — the gap between `[part='base']`'s rows while `compact`. Both apply only in
15392
+ the `compact` state, so a dense card can be tuned without re-pointing shared spacing tokens for
15393
+ everything else. Otherwise shared tokens; a data-driven `entity.type` color is applied as
13335
15394
  sanitized inline `--lr-badge-*` overrides on the type badge only (the one "type color is
13336
15395
  data-driven by design" exception this library already grants graph nodes) — every other color comes
13337
15396
  from tokens.
@@ -13417,10 +15476,13 @@ name and detail shape as `lr-graph`'s own event, so one host handler serves both
13417
15476
 
13418
15477
  **Slots:** none.
13419
15478
 
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).
15479
+ **CSS parts:** `base` (`role="list"`), `group-header` (only when `groupByRelation`; above
15480
+ `virtualizeAt` this is the internal virtual-list's own group label, re-exported under the same
15481
+ name), `row` (`role="listitem"`; above `virtualizeAt` this is the internal virtual-list's own row
15482
+ wrapper, re-exported under the same name), `direction` (`aria-hidden` glyph), `relation`,
15483
+ `node-label`, `node-meta` (secondary type/degree text, when present), `expand-button` (only when
15484
+ `expandable`), `empty` (shown when `rows` is empty). Every part presents identically either side of
15485
+ `virtualizeAt`.
13424
15486
 
13425
15487
  **Themeable custom properties:** shared tokens only.
13426
15488
 
@@ -13438,6 +15500,9 @@ name and detail shape as `lr-graph`'s own event, so one host handler serves both
13438
15500
  **Known gotchas:**
13439
15501
  - `lr-node-expand`'s detail shape is intentionally identical to `lr-graph`'s own event of the
13440
15502
  same name, so a single listener wired to both handles "expand this node's neighborhood" uniformly.
15503
+ - A row is exactly one `[part="row"]` element in both rendering paths. Above `virtualizeAt` that
15504
+ element is the internal virtual-list's own row wrapper (the component renders only the row's
15505
+ content into it), so a `::part(row)` rule applies once, not twice.
13441
15506
 
13442
15507
  ---
13443
15508
 
@@ -13499,6 +15564,11 @@ graph or membership fetching — `lr-drill` asks the host to load members/subgra
13499
15564
  - `maxMembers: number = 8` (attribute `max-members`) — remaining members collapse into a "+N"
13500
15565
  overflow chip
13501
15566
  - `compact: boolean = false` (reflected) — omits the summary excerpt and member chips
15567
+ - `appearance: 'card' | 'plain' = 'card'` (reflected) — visual chrome, mirroring `lr-card`'s
15568
+ `appearance` vocabulary and this component's sibling `lr-entity-card`'s identical property.
15569
+ `'card'` (the default) keeps the bordered, filled, padded box; `'plain'` removes the border,
15570
+ background, and padding, so a card nested inside a container that already draws a border doesn't
15571
+ double the frame.
13502
15572
 
13503
15573
  **Events:** `lr-drill` (`detail: { id }`, the drill button, header, or overflow chip — all three
13504
15574
  mean "show me this whole community"), `lr-entity-activate` (`detail: { id }`, a member chip was
@@ -13555,13 +15625,41 @@ activated).
13555
15625
 
13556
15626
  **Slots:** none.
13557
15627
 
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`),
15628
+ **CSS parts:** `base` (`role="group"`), `chunk` (one chunk row; carries `role="listitem"` only
15629
+ below `virtualize-at` while virtualized the surrounding `lr-virtual-list` row supplies that role
15630
+ instead), `chunk-current` (additional part on the row matching `activeId`), `score` (visible
15631
+ percent text), `score-current` (additional part on the current row's score line), `score-bar`
15632
+ (`aria-hidden` track), `score-fill` (tone-mapped fill), `score-fill-success` /
15633
+ `score-fill-warning` / `score-fill-danger` (additional part on the fill, one per scoring tier),
15634
+ `open-button`, `title` (the `<span>` inside `open-button` carrying the visible title text), `text`
15635
+ (omitted when `compact`), `text-clamped` (additional part on a `text` preview that is still
15636
+ collapsed; dropped once expanded), `toggle` ("Show more"/"Show less", omitted when `compact`),
13562
15637
  `empty` (shown when `chunks` is empty).
13563
15638
 
13564
- **Themeable custom properties:** shared tokens only.
15639
+ Every row-level part is reachable through `::part()` in both rendering paths: above
15640
+ `virtualize-at` the row lives in the internal `lr-virtual-list`'s shadow root and its parts are
15641
+ re-exported from there under the same names. Row *state* is exposed as an additional part name
15642
+ rather than as an attribute on the part, because Shadow Parts forbids an attribute selector after
15643
+ `::part()` — `::part(chunk)[aria-current='true']` is invalid CSS. The equivalent attributes
15644
+ (`aria-current`, `data-tone`, `data-clamped`) are still present on the elements. A state part is a
15645
+ second token in the same `part` attribute, so a `[part~="…"]` (not `[part="…"]`) selector is the
15646
+ one that matches inside a tree.
15647
+
15648
+ **Themeable custom properties:** `--lr-chunk-inspector-current-bg` (default
15649
+ `var(--lr-color-brand-quiet)`) — the background of the chunk matching `activeId`.
15650
+ `--lr-chunk-inspector-current-color` (default `var(--lr-color-text)`) — the text color of that
15651
+ chunk's `score` line (`::part(score-current)`). Both are inline `var()` fallbacks at the point of
15652
+ use rather than `:host` declarations, so either can be set on the element *or on any ancestor*:
15653
+ `::part(chunk)[data-active]` is invalid CSS — Shadow Parts forbids an attribute selector after
15654
+ `::part()` — which is why the current-chunk state is also published as its own part name
15655
+ (`chunk-current`, `score-current`); either the custom properties or `::part(chunk-current)` will
15656
+ retint it.
15657
+
15658
+ **They are a contrast-sensitive pair — override them together, never one alone.** The `-current-color`
15659
+ hook exists precisely because the quiet token it replaces only reaches about 4.24:1 against the
15660
+ current background; keep any override at 4.5:1 or better against `--lr-chunk-inspector-current-bg`.
15661
+
15662
+ Plus shared tokens otherwise.
13565
15663
 
13566
15664
  **Optional peer deps:** none.
13567
15665
 
@@ -13614,7 +15712,19 @@ fired after every toggle including select-all).
13614
15712
  `lr-file-icon` type badge), `label`, `empty` (`noData` when `sources` is empty, `noMatches` when a
13615
15713
  filter empties the tree).
13616
15714
 
13617
- **Themeable custom properties:** shared tokens only.
15715
+ **Themeable custom properties:** `--lr-source-picker-checked-bg` the background of a fully-checked
15716
+ selection control: the `select-all` pill (whose resting default is `var(--lr-color-brand-quiet)`) and
15717
+ a fully-selected entry's `[part='checkbox']` (whose resting default is `var(--lr-color-brand)`). The
15718
+ two keep their distinct defaults while it is unset; setting it unifies both.
15719
+ `--lr-source-picker-checked-border` (default `var(--lr-color-brand)`) — the border color of every
15720
+ checked *or* mixed selection control. `--lr-source-picker-mixed-bg` (default
15721
+ `color-mix(in srgb, var(--lr-color-brand) 50%, var(--lr-color-surface))`) — the background of a
15722
+ partially-selected entry's `[part='checkbox']`, so a tri-state folder reads as distinct from a fully
15723
+ selected one. All three are inline `var()` fallbacks at the point of use rather than `:host`
15724
+ declarations, so each can be set on the element *or on any ancestor*:
15725
+ `::part(checkbox)[aria-checked='true']` is invalid CSS — Shadow Parts forbids an attribute selector
15726
+ after `::part()` — which previously left re-pointing the library-wide `--lr-color-brand` token as
15727
+ the only lever, repainting every other brand surface with it. Plus shared tokens otherwise.
13618
15728
 
13619
15729
  **Optional peer deps:** none.
13620
15730
 
@@ -13709,7 +15819,9 @@ keyboard descent).
13709
15819
  announcement region), `empty` (shown when `topics` is empty).
13710
15820
 
13711
15821
  **Themeable custom properties:** `--lr-mind-map-ring-gap` (default `6rem`, radius step per depth
13712
- ring).
15822
+ ring). `--lr-mind-map-node-hover-halo` (default `var(--lr-color-brand-quiet)`) — stroke color of
15823
+ the halo drawn around a topic node's dot on `:hover`, giving mouse users the same "this is
15824
+ clickable" feedback keyboard users already get from the drawn `focus-ring` part.
13713
15825
 
13714
15826
  **Optional peer deps:** none.
13715
15827
 
@@ -13873,6 +15985,15 @@ while collapsed).
13873
15985
  - `page?: string | number` — optional page reference, e.g. `12` or `"iv"`, rendered as-is (never
13874
15986
  parsed/validated as a number), appended to the title as `" — p. {page}"`.
13875
15987
  - `href?: string` — optional URL, echoed back (unopened) in `lr-open`'s detail.
15988
+ - `compact: boolean = false` (reflected) — tighter root padding and row gap, for the dense citation
15989
+ lists these cards usually render in — the same convention as `lr-empty`'s `compact`. Purely a
15990
+ density knob: the border and background stay. `false` (the default) keeps the full card padding.
15991
+ - `appearance: 'card' | 'plain' = 'card'` (reflected) — visual chrome, mirroring `lr-card`'s
15992
+ `appearance` vocabulary. `'card'` (the default) keeps the bordered, filled, padded box; `'plain'`
15993
+ removes the border, background, padding and corner radius, so a card inside a `<lr-source-list>`
15994
+ (or any container already drawing its own border/dividers) doesn't double the frame. `plain` wins
15995
+ over `compact` when both are set — nothing left to tighten. The title and toggle keep their brand
15996
+ color and hover underline under `plain`, since neither ever depended on the card chrome.
13876
15997
 
13877
15998
  **Events:**
13878
15999
  - `lr-expand` (`detail: { sourceId: string; expanded: boolean }`) — the per-card "Show
@@ -13893,7 +16014,11 @@ behind the "Show more"/"Show less" toggle — when left empty, no toggle renders
13893
16014
  (wrapper around the `full` slot, `hidden` while collapsed), `toggle` (the "Show more"/"Show less"
13894
16015
  button — only rendered when the `full` slot has content).
13895
16016
 
13896
- **Themeable custom properties:** shared tokens only — `--lr-color-border`, `--lr-color-surface`,
16017
+ **Themeable custom properties:** `--lr-source-card-compact-padding` (default `var(--lr-space-xs)`) —
16018
+ `[part='base']`'s padding while `compact`; `--lr-source-card-compact-gap` (default
16019
+ `var(--lr-space-2xs)`) — the gap between `[part='base']`'s rows while `compact`. Both apply only in
16020
+ the `compact` state, so a dense citation list can be tuned without re-pointing shared spacing tokens
16021
+ elsewhere. Plus shared tokens — `--lr-color-border`, `--lr-color-surface`,
13897
16022
  `--lr-color-text` / `-text-quiet`, `--lr-color-brand`, `--lr-radius`, `--lr-space-xs`/`-s`,
13898
16023
  `--lr-focus-ring-*`.
13899
16024
 
@@ -14092,6 +16217,14 @@ per-item stage label), `item-progress`,
14092
16217
  `item-error` (only for `stage="failed"` with `error` set), `item-actions`, `retry-button`,
14093
16218
  `cancel-button`, `empty`.
14094
16219
 
16220
+ In virtualized mode (at or above `virtualizeThreshold`) the rows live in the internal
16221
+ `lr-virtual-list`'s shadow root, and `item`, `item-header`, `item-name`, `item-progress`,
16222
+ `item-meta`, `item-error`, `item-actions`, `retry-button` and `cancel-button` are forwarded out
16223
+ through `exportparts`, so `lr-ingestion-queue::part(item)` and the rest keep working from a consumer
16224
+ stylesheet. `item-stage`, `item-chunk-count`, `item-embedding-status` and `item-attempts` are not
16225
+ forwarded, so those four are only reachable through `::part()` while the queue is below the
16226
+ threshold.
16227
+
14095
16228
  **Themeable custom properties:** `--lr-ingestion-queue-max-height` (default `none`) — non-virtualized
14096
16229
  mode only: caps how tall the list grows before it scrolls internally. No effect once virtualized —
14097
16230
  retheme the internal list via `lr-virtual-list { --lr-virtual-list-height: … }` instead.
@@ -14278,7 +16411,12 @@ somewhere to land after a confirmation resolves), `item-row`, `item-text`, `conf
14278
16411
  `provenance` is unset; `item-body` is `hidden` while collapsed), `item-actions`, `add-button`,
14279
16412
  `remove-button`, `forget-all-button`.
14280
16413
 
14281
- **Themeable custom properties:** shared tokens only.
16414
+ **Themeable custom properties:** `--lr-memory-panel-confidence-success-color` (default
16415
+ `var(--lr-color-success)`), `--lr-memory-panel-confidence-warning-color` (default
16416
+ `var(--lr-color-warning)`), `--lr-memory-panel-confidence-danger-color` (default
16417
+ `var(--lr-color-danger)`) — text color of an item's `confidence` indicator, one per confidence
16418
+ tier (`high`/`medium`/`low` against `thresholds`, the same tiering `lr-chunk-inspector` uses for
16419
+ its score bar). Plus shared tokens otherwise.
14282
16420
 
14283
16421
  **Optional peer deps:** none.
14284
16422
 
@@ -14348,10 +16486,37 @@ neither `error` nor `loading` is set), `row` (a plain element in this shadow roo
14348
16486
  virtualization threshold; exported from the internal `lr-virtual-list`'s own `row` part while
14349
16487
  virtualized — `::part(row)` reaches it either way), `group-header` (exported from the virtual list's
14350
16488
  `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.
16489
+ `selectable` is false), `row-body` (carries `data-selected`), `row-body-selected` (additional part
16490
+ on a selected `row-body`), `metadata` (a `<dl>`; omitted when the chunk has none or while
16491
+ `presentation="compact"`), `metadata-entry`, `metadata-term` (the `<dt>` carrying a metadata key),
16492
+ `metadata-value` (the `<dd>` carrying its value), `load-more-row`, `load-more`.
16493
+
16494
+ The per-row `lr-chunk-inspector`'s own parts are forwarded onward under a `chunk-` prefix —
16495
+ `chunk`, `chunk-current`, `chunk-score`, `chunk-score-current`, `chunk-score-bar`,
16496
+ `chunk-score-fill`, `chunk-score-fill-success`, `chunk-score-fill-warning`,
16497
+ `chunk-score-fill-danger`, `chunk-open-button`,
16498
+ `chunk-title`, `chunk-text`, `chunk-text-clamped`, `chunk-toggle`. Those elements sit two shadow
16499
+ hops deep while virtualized, so this forwarding is the only way to reach them.
16500
+
16501
+ Selection state is exposed as the additional `row-body-selected` part name rather than through the
16502
+ `data-selected` attribute, because Shadow Parts forbids an attribute selector after `::part()`:
16503
+ `::part(row-body)[data-selected]` is invalid CSS, and while virtualized `::part()` is the only way
16504
+ in. `data-selected` is unchanged. A state part is a second token in the same `part` attribute, so
16505
+ a `[part~="…"]` (not `[part="…"]`) selector is the one that matches inside a tree. The `<dt>`/`<dd>`
16506
+ carry their own part names for the same class of reason — `::part()` matches a single element and
16507
+ cannot be followed by a descendant combinator, so `::part(metadata-entry) dt` reaches nothing.
16508
+
16509
+ **Themeable custom properties:** `--lr-retrieval-results-selected-border` (default
16510
+ `var(--lr-color-brand)`) — the inline-start border color marking a selected row body
16511
+ (`::part(row-body-selected)`). A
16512
+ border rather than a fill by design: the row's own text (the nested chunk inspector's quiet-toned
16513
+ score line in particular) is sized and colored for the page's default surface, and a tinted
16514
+ background can drop it below the required contrast ratio, while a border-only indicator carries no
16515
+ such risk — so recoloring this hook is contrast-safe. It is an inline `var()` fallback at the point
16516
+ of use rather than a `:host` declaration, so it can be set on the element *or on any ancestor*:
16517
+ `::part(row-body)[data-selected]` is invalid CSS — Shadow Parts forbids an attribute selector after
16518
+ `::part()` — which previously left re-pointing the library-wide `--lr-color-brand` token as the only
16519
+ lever, repainting every other brand surface with it. Plus shared tokens otherwise.
14355
16520
 
14356
16521
  **Optional peer deps:** none.
14357
16522
 
@@ -14462,7 +16627,14 @@ no stage has evidence), `evidence-row` (omitted for a stage with no evidence), `
14462
16627
  `evidence-metadata` (a `<dl>`), `evidence-metadata-row` (one key/value pair), `evidence-metadata-key`
14463
16628
  (`<dt>`), `evidence-metadata-value` (`<dd>`).
14464
16629
 
14465
- **Themeable custom properties:** shared tokens only.
16630
+ **Themeable custom properties:** `--lr-retrieval-trace-active-border` (default
16631
+ `var(--lr-color-brand)`) — the border color of the `[part='evidence-row']` whose stage matches
16632
+ `activeStageId`, leaving every other row on the resting border token. It is an inline `var()`
16633
+ fallback at the point of use rather than a `:host` declaration, so it can be set on the element *or
16634
+ on any ancestor*: `::part(evidence-row)[data-active]` is invalid CSS — Shadow Parts forbids an
16635
+ attribute selector after `::part()` — so marking the active stage previously meant overriding the
16636
+ library-wide `--lr-color-brand` token and repainting every other brand surface with it. Unset, it
16637
+ falls back to that token, so rendering is unchanged. Plus shared tokens otherwise.
14466
16638
 
14467
16639
  **Optional peer deps:** none.
14468
16640