poetry-ui 0.0.2

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 (442) hide show
  1. checksums.yaml +7 -0
  2. data/.gitattributes +6 -0
  3. data/CHANGELOG.md +3 -0
  4. data/LICENSE.txt +21 -0
  5. data/README.md +87 -0
  6. data/THIRD_PARTY_NOTICES.md +201 -0
  7. data/app/components/poetry/ui/accordion/component.html.erb +3 -0
  8. data/app/components/poetry/ui/accordion/component.rb +197 -0
  9. data/app/components/poetry/ui/accordion/preview.rb +39 -0
  10. data/app/components/poetry/ui/accordion/style.rb +37 -0
  11. data/app/components/poetry/ui/alert/component.html.erb +6 -0
  12. data/app/components/poetry/ui/alert/component.rb +61 -0
  13. data/app/components/poetry/ui/alert/preview.rb +35 -0
  14. data/app/components/poetry/ui/alert/style.rb +24 -0
  15. data/app/components/poetry/ui/alert_dialog/component.html.erb +17 -0
  16. data/app/components/poetry/ui/alert_dialog/component.rb +208 -0
  17. data/app/components/poetry/ui/alert_dialog/preview.rb +48 -0
  18. data/app/components/poetry/ui/alert_dialog/style.rb +46 -0
  19. data/app/components/poetry/ui/aspect_ratio/component.rb +63 -0
  20. data/app/components/poetry/ui/aspect_ratio/preview.rb +29 -0
  21. data/app/components/poetry/ui/aspect_ratio/style.rb +13 -0
  22. data/app/components/poetry/ui/attachment/component.html.erb +13 -0
  23. data/app/components/poetry/ui/attachment/component.rb +139 -0
  24. data/app/components/poetry/ui/attachment/preview.rb +83 -0
  25. data/app/components/poetry/ui/attachment/style.rb +59 -0
  26. data/app/components/poetry/ui/autocomplete/component.html.erb +16 -0
  27. data/app/components/poetry/ui/autocomplete/component.rb +193 -0
  28. data/app/components/poetry/ui/autocomplete/preview.rb +39 -0
  29. data/app/components/poetry/ui/autocomplete/style.rb +18 -0
  30. data/app/components/poetry/ui/avatar/component.rb +103 -0
  31. data/app/components/poetry/ui/avatar/group_preview.html.erb +11 -0
  32. data/app/components/poetry/ui/avatar/preview.rb +50 -0
  33. data/app/components/poetry/ui/avatar/style.rb +34 -0
  34. data/app/components/poetry/ui/badge/component.rb +73 -0
  35. data/app/components/poetry/ui/badge/preview.rb +54 -0
  36. data/app/components/poetry/ui/badge/style.rb +35 -0
  37. data/app/components/poetry/ui/breadcrumb/component.html.erb +32 -0
  38. data/app/components/poetry/ui/breadcrumb/component.rb +102 -0
  39. data/app/components/poetry/ui/breadcrumb/dropdown_crumb_preview.html.erb +21 -0
  40. data/app/components/poetry/ui/breadcrumb/preview.rb +45 -0
  41. data/app/components/poetry/ui/breadcrumb/style.rb +25 -0
  42. data/app/components/poetry/ui/bubble/component.html.erb +4 -0
  43. data/app/components/poetry/ui/bubble/component.rb +106 -0
  44. data/app/components/poetry/ui/bubble/preview.rb +62 -0
  45. data/app/components/poetry/ui/bubble/style.rb +47 -0
  46. data/app/components/poetry/ui/button/component.html.erb +14 -0
  47. data/app/components/poetry/ui/button/component.rb +168 -0
  48. data/app/components/poetry/ui/button/preview.rb +94 -0
  49. data/app/components/poetry/ui/button/style.rb +41 -0
  50. data/app/components/poetry/ui/button_group/component.rb +70 -0
  51. data/app/components/poetry/ui/button_group/popup_triggers_preview.html.erb +21 -0
  52. data/app/components/poetry/ui/button_group/preview.rb +46 -0
  53. data/app/components/poetry/ui/button_group/style.rb +27 -0
  54. data/app/components/poetry/ui/button_group/text_prefix_preview.html.erb +7 -0
  55. data/app/components/poetry/ui/calendar/component.html.erb +72 -0
  56. data/app/components/poetry/ui/calendar/component.rb +366 -0
  57. data/app/components/poetry/ui/calendar/preview.rb +55 -0
  58. data/app/components/poetry/ui/calendar/style.rb +55 -0
  59. data/app/components/poetry/ui/card/component.html.erb +11 -0
  60. data/app/components/poetry/ui/card/component.rb +90 -0
  61. data/app/components/poetry/ui/card/preview.rb +29 -0
  62. data/app/components/poetry/ui/card/style.rb +23 -0
  63. data/app/components/poetry/ui/carousel/component.html.erb +17 -0
  64. data/app/components/poetry/ui/carousel/component.rb +179 -0
  65. data/app/components/poetry/ui/carousel/preview.rb +67 -0
  66. data/app/components/poetry/ui/carousel/style.rb +39 -0
  67. data/app/components/poetry/ui/checkbox/component.html.erb +22 -0
  68. data/app/components/poetry/ui/checkbox/component.rb +179 -0
  69. data/app/components/poetry/ui/checkbox/preview.rb +68 -0
  70. data/app/components/poetry/ui/checkbox/style.rb +28 -0
  71. data/app/components/poetry/ui/clipboard_text/component.html.erb +15 -0
  72. data/app/components/poetry/ui/clipboard_text/component.rb +154 -0
  73. data/app/components/poetry/ui/clipboard_text/preview.rb +24 -0
  74. data/app/components/poetry/ui/clipboard_text/style.rb +23 -0
  75. data/app/components/poetry/ui/code_block/component.html.erb +13 -0
  76. data/app/components/poetry/ui/code_block/component.rb +141 -0
  77. data/app/components/poetry/ui/code_block/preview.rb +40 -0
  78. data/app/components/poetry/ui/code_block/style.rb +38 -0
  79. data/app/components/poetry/ui/collapsible/component.html.erb +4 -0
  80. data/app/components/poetry/ui/collapsible/component.rb +134 -0
  81. data/app/components/poetry/ui/collapsible/preview.rb +24 -0
  82. data/app/components/poetry/ui/combobox/component.html.erb +49 -0
  83. data/app/components/poetry/ui/combobox/component.rb +1086 -0
  84. data/app/components/poetry/ui/combobox/preview.rb +164 -0
  85. data/app/components/poetry/ui/combobox/style.rb +148 -0
  86. data/app/components/poetry/ui/command/component.html.erb +20 -0
  87. data/app/components/poetry/ui/command/component.rb +526 -0
  88. data/app/components/poetry/ui/command/dialog_component.html.erb +14 -0
  89. data/app/components/poetry/ui/command/dialog_component.rb +206 -0
  90. data/app/components/poetry/ui/command/dialog_preview.rb +39 -0
  91. data/app/components/poetry/ui/command/preview.rb +121 -0
  92. data/app/components/poetry/ui/command/style.rb +78 -0
  93. data/app/components/poetry/ui/composable_trigger.rb +63 -0
  94. data/app/components/poetry/ui/context_menu/component.html.erb +6 -0
  95. data/app/components/poetry/ui/context_menu/component.rb +358 -0
  96. data/app/components/poetry/ui/context_menu/preview.rb +111 -0
  97. data/app/components/poetry/ui/context_menu/style.rb +59 -0
  98. data/app/components/poetry/ui/data_table/component.html.erb +78 -0
  99. data/app/components/poetry/ui/data_table/component.rb +277 -0
  100. data/app/components/poetry/ui/data_table/preview.rb +68 -0
  101. data/app/components/poetry/ui/data_table/state.rb +115 -0
  102. data/app/components/poetry/ui/data_table/style.rb +42 -0
  103. data/app/components/poetry/ui/date_field/component.html.erb +7 -0
  104. data/app/components/poetry/ui/date_field/component.rb +209 -0
  105. data/app/components/poetry/ui/date_field/preview.rb +42 -0
  106. data/app/components/poetry/ui/date_field/style.rb +35 -0
  107. data/app/components/poetry/ui/date_picker/component.html.erb +23 -0
  108. data/app/components/poetry/ui/date_picker/component.rb +242 -0
  109. data/app/components/poetry/ui/date_picker/preview.rb +31 -0
  110. data/app/components/poetry/ui/date_picker/style.rb +25 -0
  111. data/app/components/poetry/ui/deferred/component.html.erb +16 -0
  112. data/app/components/poetry/ui/deferred/component.rb +90 -0
  113. data/app/components/poetry/ui/deferred/preview.rb +24 -0
  114. data/app/components/poetry/ui/dialog/component.html.erb +21 -0
  115. data/app/components/poetry/ui/dialog/component.rb +194 -0
  116. data/app/components/poetry/ui/dialog/preview.rb +33 -0
  117. data/app/components/poetry/ui/dialog/style.rb +30 -0
  118. data/app/components/poetry/ui/drawer/component.html.erb +16 -0
  119. data/app/components/poetry/ui/drawer/component.rb +207 -0
  120. data/app/components/poetry/ui/drawer/preview.rb +69 -0
  121. data/app/components/poetry/ui/drawer/style.rb +105 -0
  122. data/app/components/poetry/ui/dropdown_menu/component.html.erb +6 -0
  123. data/app/components/poetry/ui/dropdown_menu/component.rb +350 -0
  124. data/app/components/poetry/ui/dropdown_menu/preview.rb +101 -0
  125. data/app/components/poetry/ui/dropdown_menu/style.rb +60 -0
  126. data/app/components/poetry/ui/empty/component.html.erb +10 -0
  127. data/app/components/poetry/ui/empty/component.rb +79 -0
  128. data/app/components/poetry/ui/empty/preview.rb +27 -0
  129. data/app/components/poetry/ui/empty/style.rb +27 -0
  130. data/app/components/poetry/ui/family_identity.rb +52 -0
  131. data/app/components/poetry/ui/field/component.html.erb +19 -0
  132. data/app/components/poetry/ui/field/component.rb +183 -0
  133. data/app/components/poetry/ui/field/preview.html.erb +30 -0
  134. data/app/components/poetry/ui/field/preview.rb +72 -0
  135. data/app/components/poetry/ui/field/style.rb +68 -0
  136. data/app/components/poetry/ui/field_group/component.rb +61 -0
  137. data/app/components/poetry/ui/field_group/preview.html.erb +30 -0
  138. data/app/components/poetry/ui/field_group/preview.rb +20 -0
  139. data/app/components/poetry/ui/field_group/style.rb +25 -0
  140. data/app/components/poetry/ui/field_separator/component.rb +70 -0
  141. data/app/components/poetry/ui/field_separator/preview.rb +18 -0
  142. data/app/components/poetry/ui/field_separator/style.rb +20 -0
  143. data/app/components/poetry/ui/fieldset/component.rb +90 -0
  144. data/app/components/poetry/ui/fieldset/preview.html.erb +22 -0
  145. data/app/components/poetry/ui/fieldset/preview.rb +25 -0
  146. data/app/components/poetry/ui/fieldset/style.rb +18 -0
  147. data/app/components/poetry/ui/file_input/component.html.erb +14 -0
  148. data/app/components/poetry/ui/file_input/component.rb +188 -0
  149. data/app/components/poetry/ui/file_input/preview.rb +30 -0
  150. data/app/components/poetry/ui/file_input/style.rb +35 -0
  151. data/app/components/poetry/ui/hover_card/component.html.erb +6 -0
  152. data/app/components/poetry/ui/hover_card/component.rb +201 -0
  153. data/app/components/poetry/ui/hover_card/preview.rb +60 -0
  154. data/app/components/poetry/ui/hover_card/style.rb +17 -0
  155. data/app/components/poetry/ui/icon/component.rb +127 -0
  156. data/app/components/poetry/ui/icon/preview.rb +21 -0
  157. data/app/components/poetry/ui/input/component.rb +80 -0
  158. data/app/components/poetry/ui/input/preview.rb +35 -0
  159. data/app/components/poetry/ui/input/style.rb +18 -0
  160. data/app/components/poetry/ui/input_group/button_preview.html.erb +12 -0
  161. data/app/components/poetry/ui/input_group/component.rb +69 -0
  162. data/app/components/poetry/ui/input_group/preview.rb +23 -0
  163. data/app/components/poetry/ui/input_group/search_preview.html.erb +13 -0
  164. data/app/components/poetry/ui/input_group/style.rb +40 -0
  165. data/app/components/poetry/ui/input_group/textarea_preview.html.erb +10 -0
  166. data/app/components/poetry/ui/input_group_field.rb +61 -0
  167. data/app/components/poetry/ui/input_otp/component.html.erb +25 -0
  168. data/app/components/poetry/ui/input_otp/component.rb +250 -0
  169. data/app/components/poetry/ui/input_otp/preview.rb +91 -0
  170. data/app/components/poetry/ui/input_otp/style.rb +36 -0
  171. data/app/components/poetry/ui/item/component.html.erb +13 -0
  172. data/app/components/poetry/ui/item/component.rb +99 -0
  173. data/app/components/poetry/ui/item/group_preview.html.erb +15 -0
  174. data/app/components/poetry/ui/item/preview.rb +52 -0
  175. data/app/components/poetry/ui/item/style.rb +45 -0
  176. data/app/components/poetry/ui/kbd/component.rb +47 -0
  177. data/app/components/poetry/ui/kbd/group_preview.html.erb +4 -0
  178. data/app/components/poetry/ui/kbd/preview.rb +23 -0
  179. data/app/components/poetry/ui/kbd/style.rb +13 -0
  180. data/app/components/poetry/ui/label/component.rb +46 -0
  181. data/app/components/poetry/ui/label/preview.html.erb +5 -0
  182. data/app/components/poetry/ui/label/preview.rb +16 -0
  183. data/app/components/poetry/ui/label/style.rb +13 -0
  184. data/app/components/poetry/ui/link/component.rb +62 -0
  185. data/app/components/poetry/ui/link/preview.rb +31 -0
  186. data/app/components/poetry/ui/link/style.rb +20 -0
  187. data/app/components/poetry/ui/marker/component.html.erb +4 -0
  188. data/app/components/poetry/ui/marker/component.rb +81 -0
  189. data/app/components/poetry/ui/marker/preview.rb +43 -0
  190. data/app/components/poetry/ui/marker/style.rb +24 -0
  191. data/app/components/poetry/ui/menubar/component.html.erb +3 -0
  192. data/app/components/poetry/ui/menubar/component.rb +493 -0
  193. data/app/components/poetry/ui/menubar/preview.rb +164 -0
  194. data/app/components/poetry/ui/menubar/style.rb +71 -0
  195. data/app/components/poetry/ui/menus.rb +386 -0
  196. data/app/components/poetry/ui/message/component.html.erb +8 -0
  197. data/app/components/poetry/ui/message/component.rb +64 -0
  198. data/app/components/poetry/ui/message/preview.rb +33 -0
  199. data/app/components/poetry/ui/message/style.rb +29 -0
  200. data/app/components/poetry/ui/message_scroller/component.html.erb +15 -0
  201. data/app/components/poetry/ui/message_scroller/component.rb +163 -0
  202. data/app/components/poetry/ui/message_scroller/preview.rb +33 -0
  203. data/app/components/poetry/ui/message_scroller/style.rb +39 -0
  204. data/app/components/poetry/ui/metadata_list/component.rb +88 -0
  205. data/app/components/poetry/ui/metadata_list/preview.rb +55 -0
  206. data/app/components/poetry/ui/metadata_list/style.rb +35 -0
  207. data/app/components/poetry/ui/meter/component.rb +117 -0
  208. data/app/components/poetry/ui/meter/preview.rb +28 -0
  209. data/app/components/poetry/ui/meter/style.rb +16 -0
  210. data/app/components/poetry/ui/native_select/component.rb +124 -0
  211. data/app/components/poetry/ui/native_select/labelled_preview.html.erb +7 -0
  212. data/app/components/poetry/ui/native_select/preview.rb +20 -0
  213. data/app/components/poetry/ui/native_select/style.rb +22 -0
  214. data/app/components/poetry/ui/navigation_menu/bar_preview.html.erb +14 -0
  215. data/app/components/poetry/ui/navigation_menu/component.html.erb +25 -0
  216. data/app/components/poetry/ui/navigation_menu/component.rb +254 -0
  217. data/app/components/poetry/ui/navigation_menu/preview.rb +20 -0
  218. data/app/components/poetry/ui/navigation_menu/style.rb +73 -0
  219. data/app/components/poetry/ui/navigation_menu/viewport_preview.html.erb +23 -0
  220. data/app/components/poetry/ui/number_field/component.html.erb +19 -0
  221. data/app/components/poetry/ui/number_field/component.rb +263 -0
  222. data/app/components/poetry/ui/number_field/preview.rb +66 -0
  223. data/app/components/poetry/ui/number_field/style.rb +14 -0
  224. data/app/components/poetry/ui/pagination/component.html.erb +40 -0
  225. data/app/components/poetry/ui/pagination/component.rb +182 -0
  226. data/app/components/poetry/ui/pagination/preview.rb +47 -0
  227. data/app/components/poetry/ui/pagination/style.rb +27 -0
  228. data/app/components/poetry/ui/popover/component.html.erb +17 -0
  229. data/app/components/poetry/ui/popover/component.rb +203 -0
  230. data/app/components/poetry/ui/popover/preview.html.erb +29 -0
  231. data/app/components/poetry/ui/popover/preview.rb +66 -0
  232. data/app/components/poetry/ui/popover/style.rb +26 -0
  233. data/app/components/poetry/ui/popper_consumer.rb +69 -0
  234. data/app/components/poetry/ui/progress/component.rb +95 -0
  235. data/app/components/poetry/ui/progress/preview.rb +22 -0
  236. data/app/components/poetry/ui/progress/style.rb +19 -0
  237. data/app/components/poetry/ui/questionnaire/component.html.erb +80 -0
  238. data/app/components/poetry/ui/questionnaire/component.rb +396 -0
  239. data/app/components/poetry/ui/questionnaire/preview.rb +99 -0
  240. data/app/components/poetry/ui/questionnaire/style.rb +53 -0
  241. data/app/components/poetry/ui/radio_group/component.html.erb +4 -0
  242. data/app/components/poetry/ui/radio_group/component.rb +323 -0
  243. data/app/components/poetry/ui/radio_group/preview.rb +109 -0
  244. data/app/components/poetry/ui/radio_group/style.rb +53 -0
  245. data/app/components/poetry/ui/resizable/component.html.erb +10 -0
  246. data/app/components/poetry/ui/resizable/component.rb +178 -0
  247. data/app/components/poetry/ui/resizable/preview.rb +42 -0
  248. data/app/components/poetry/ui/resizable/style.rb +30 -0
  249. data/app/components/poetry/ui/scroll_area/component.rb +76 -0
  250. data/app/components/poetry/ui/scroll_area/preview.rb +35 -0
  251. data/app/components/poetry/ui/scroll_area/style.rb +19 -0
  252. data/app/components/poetry/ui/search_field/component.html.erb +15 -0
  253. data/app/components/poetry/ui/search_field/component.rb +137 -0
  254. data/app/components/poetry/ui/search_field/preview.rb +23 -0
  255. data/app/components/poetry/ui/search_field/style.rb +18 -0
  256. data/app/components/poetry/ui/select/component.html.erb +15 -0
  257. data/app/components/poetry/ui/select/component.rb +639 -0
  258. data/app/components/poetry/ui/select/preview.rb +113 -0
  259. data/app/components/poetry/ui/select/style.rb +58 -0
  260. data/app/components/poetry/ui/sensitive_input/component.html.erb +29 -0
  261. data/app/components/poetry/ui/sensitive_input/component.rb +274 -0
  262. data/app/components/poetry/ui/sensitive_input/preview.rb +40 -0
  263. data/app/components/poetry/ui/sensitive_input/style.rb +49 -0
  264. data/app/components/poetry/ui/separator/component.rb +57 -0
  265. data/app/components/poetry/ui/separator/preview.rb +19 -0
  266. data/app/components/poetry/ui/separator/style.rb +15 -0
  267. data/app/components/poetry/ui/sheet/component.html.erb +21 -0
  268. data/app/components/poetry/ui/sheet/component.rb +97 -0
  269. data/app/components/poetry/ui/sheet/preview.rb +57 -0
  270. data/app/components/poetry/ui/sheet/style.rb +47 -0
  271. data/app/components/poetry/ui/sidebar/component.html.erb +20 -0
  272. data/app/components/poetry/ui/sidebar/component.rb +249 -0
  273. data/app/components/poetry/ui/sidebar/preview.rb +21 -0
  274. data/app/components/poetry/ui/sidebar/shell_preview.html.erb +47 -0
  275. data/app/components/poetry/ui/sidebar/style.rb +139 -0
  276. data/app/components/poetry/ui/skeleton/component.rb +39 -0
  277. data/app/components/poetry/ui/skeleton/preview.rb +22 -0
  278. data/app/components/poetry/ui/skeleton/style.rb +13 -0
  279. data/app/components/poetry/ui/slider/component.html.erb +13 -0
  280. data/app/components/poetry/ui/slider/component.rb +360 -0
  281. data/app/components/poetry/ui/slider/preview.rb +73 -0
  282. data/app/components/poetry/ui/slider/style.rb +55 -0
  283. data/app/components/poetry/ui/spinner/component.rb +58 -0
  284. data/app/components/poetry/ui/spinner/preview.rb +22 -0
  285. data/app/components/poetry/ui/spinner/style.rb +12 -0
  286. data/app/components/poetry/ui/stat/component.html.erb +13 -0
  287. data/app/components/poetry/ui/stat/component.rb +102 -0
  288. data/app/components/poetry/ui/stat/preview.rb +47 -0
  289. data/app/components/poetry/ui/stat/style.rb +29 -0
  290. data/app/components/poetry/ui/switch/component.html.erb +15 -0
  291. data/app/components/poetry/ui/switch/component.rb +136 -0
  292. data/app/components/poetry/ui/switch/preview.rb +66 -0
  293. data/app/components/poetry/ui/switch/style.rb +22 -0
  294. data/app/components/poetry/ui/table/component.html.erb +3 -0
  295. data/app/components/poetry/ui/table/component.rb +93 -0
  296. data/app/components/poetry/ui/table/preview.rb +96 -0
  297. data/app/components/poetry/ui/table/style.rb +26 -0
  298. data/app/components/poetry/ui/tabs/component.html.erb +10 -0
  299. data/app/components/poetry/ui/tabs/component.rb +253 -0
  300. data/app/components/poetry/ui/tabs/preview.rb +43 -0
  301. data/app/components/poetry/ui/tabs/style.rb +49 -0
  302. data/app/components/poetry/ui/tag_group/component.html.erb +8 -0
  303. data/app/components/poetry/ui/tag_group/component.rb +203 -0
  304. data/app/components/poetry/ui/tag_group/preview.rb +43 -0
  305. data/app/components/poetry/ui/tag_group/style.rb +29 -0
  306. data/app/components/poetry/ui/textarea/component.rb +64 -0
  307. data/app/components/poetry/ui/textarea/preview.rb +75 -0
  308. data/app/components/poetry/ui/textarea/style.rb +18 -0
  309. data/app/components/poetry/ui/time_field/component.html.erb +6 -0
  310. data/app/components/poetry/ui/time_field/component.rb +85 -0
  311. data/app/components/poetry/ui/time_field/preview.rb +40 -0
  312. data/app/components/poetry/ui/time_field/style.rb +30 -0
  313. data/app/components/poetry/ui/timeline/component.rb +134 -0
  314. data/app/components/poetry/ui/timeline/preview.rb +61 -0
  315. data/app/components/poetry/ui/timeline/style.rb +54 -0
  316. data/app/components/poetry/ui/toast/component.html.erb +24 -0
  317. data/app/components/poetry/ui/toast/component.rb +178 -0
  318. data/app/components/poetry/ui/toast/preview.rb +69 -0
  319. data/app/components/poetry/ui/toast/style.rb +33 -0
  320. data/app/components/poetry/ui/toast_trigger/addressed_preview.html.erb +12 -0
  321. data/app/components/poetry/ui/toast_trigger/component.html.erb +3 -0
  322. data/app/components/poetry/ui/toast_trigger/component.rb +82 -0
  323. data/app/components/poetry/ui/toast_trigger/default_preview.html.erb +11 -0
  324. data/app/components/poetry/ui/toast_trigger/preview.rb +19 -0
  325. data/app/components/poetry/ui/toaster/component.html.erb +1 -0
  326. data/app/components/poetry/ui/toaster/component.rb +99 -0
  327. data/app/components/poetry/ui/toaster/positions_preview.html.erb +24 -0
  328. data/app/components/poetry/ui/toaster/preview.rb +46 -0
  329. data/app/components/poetry/ui/toaster/stamp_preview.html.erb +15 -0
  330. data/app/components/poetry/ui/toaster/style.rb +26 -0
  331. data/app/components/poetry/ui/toggle/component.rb +120 -0
  332. data/app/components/poetry/ui/toggle/preview.rb +79 -0
  333. data/app/components/poetry/ui/toggle/style.rb +33 -0
  334. data/app/components/poetry/ui/toggle_group/component.html.erb +4 -0
  335. data/app/components/poetry/ui/toggle_group/component.rb +252 -0
  336. data/app/components/poetry/ui/toggle_group/preview.rb +143 -0
  337. data/app/components/poetry/ui/toggle_group/style.rb +33 -0
  338. data/app/components/poetry/ui/toolbar/component.rb +125 -0
  339. data/app/components/poetry/ui/toolbar/preview.rb +41 -0
  340. data/app/components/poetry/ui/toolbar/style.rb +20 -0
  341. data/app/components/poetry/ui/tooltip/component.html.erb +20 -0
  342. data/app/components/poetry/ui/tooltip/component.rb +185 -0
  343. data/app/components/poetry/ui/tooltip/preview.rb +74 -0
  344. data/app/components/poetry/ui/tooltip/previews/provider_row.html.erb +25 -0
  345. data/app/components/poetry/ui/tooltip/style.rb +24 -0
  346. data/app/components/poetry/ui/tree/component.html.erb +32 -0
  347. data/app/components/poetry/ui/tree/component.rb +233 -0
  348. data/app/components/poetry/ui/tree/preview.rb +55 -0
  349. data/app/components/poetry/ui/tree/style.rb +29 -0
  350. data/app/components/poetry/ui/typeset/component.rb +73 -0
  351. data/app/components/poetry/ui/typeset/preview.rb +45 -0
  352. data/app/components/poetry/ui/typeset/style.rb +15 -0
  353. data/app/controllers/poetry/ui/llms_controller.rb +28 -0
  354. data/app/helpers/poetry/ui/components_helper.rb +1794 -0
  355. data/app/helpers/poetry/ui/form_builder/type_inference.rb +117 -0
  356. data/app/helpers/poetry/ui/form_builder.rb +916 -0
  357. data/app/helpers/poetry/ui/optimistic_form_builder.rb +55 -0
  358. data/app/helpers/poetry/ui/toast_stream_actions.rb +27 -0
  359. data/config/component_descriptions.yml +96 -0
  360. data/config/component_registry.yml +12257 -0
  361. data/config/locales/en.yml +93 -0
  362. data/config/routes.rb +8 -0
  363. data/config/template_classes.txt +113 -0
  364. data/lib/generators/poetry/add/add_generator.rb +218 -0
  365. data/lib/generators/poetry/agent_rules/agent_rules_generator.rb +91 -0
  366. data/lib/generators/poetry/agents/agents_generator.rb +24 -0
  367. data/lib/generators/poetry/agents_section.rb +148 -0
  368. data/lib/generators/poetry/block/block_generator.rb +67 -0
  369. data/lib/generators/poetry/block/templates/action_bar.html.erb +45 -0
  370. data/lib/generators/poetry/block/templates/app_shell.html.erb +139 -0
  371. data/lib/generators/poetry/block/templates/data_index.html.erb +85 -0
  372. data/lib/generators/poetry/block/templates/destructive_panel.html.erb +26 -0
  373. data/lib/generators/poetry/block/templates/page_header.html.erb +25 -0
  374. data/lib/generators/poetry/block/templates/section_card.html.erb +42 -0
  375. data/lib/generators/poetry/block/templates/stepper.html.erb +79 -0
  376. data/lib/generators/poetry/block/templates/top_nav.html.erb +44 -0
  377. data/lib/generators/poetry/diff/diff_generator.rb +135 -0
  378. data/lib/generators/poetry/editor/editor_generator.rb +344 -0
  379. data/lib/generators/poetry/editor/templates/poetry-check-hook +81 -0
  380. data/lib/generators/poetry/install/install_generator.rb +364 -0
  381. data/lib/generators/poetry/pagination/pagination_generator.rb +76 -0
  382. data/lib/generators/poetry/pagination/templates/kaminari_paginator.html.erb +29 -0
  383. data/lib/generators/poetry/pagination/templates/poetry_link_renderer.rb +34 -0
  384. data/lib/generators/poetry/pagination/templates/poetry_pagy_helper.rb +28 -0
  385. data/lib/generators/poetry/recipes/agent_embed/app/javascript/controllers/agent_demo_controller.js +131 -0
  386. data/lib/generators/poetry/recipes/screen_data_index/app/controllers/orders_controller.rb +15 -0
  387. data/lib/generators/poetry/recipes/screen_data_index/app/views/orders/index.html.erb +7 -0
  388. data/lib/generators/poetry/recipes/screen_data_index/test/system/orders_index_test.rb +16 -0
  389. data/lib/generators/poetry/recipes/screen_settings/app/controllers/settings_controller.rb +14 -0
  390. data/lib/generators/poetry/recipes/screen_settings/app/views/settings/show.html.erb +9 -0
  391. data/lib/generators/poetry/recipes/screen_settings/test/system/settings_show_test.rb +16 -0
  392. data/lib/generators/poetry/scaffold_templates/scaffold_templates_generator.rb +60 -0
  393. data/lib/generators/poetry/scaffold_templates/templates/_form.html.erb.tt +77 -0
  394. data/lib/generators/poetry/scaffold_templates/templates/controller.rb.tt +78 -0
  395. data/lib/generators/poetry/scaffold_templates/templates/edit.html.erb.tt +14 -0
  396. data/lib/generators/poetry/scaffold_templates/templates/index.html.erb.tt +24 -0
  397. data/lib/generators/poetry/scaffold_templates/templates/new.html.erb.tt +11 -0
  398. data/lib/generators/poetry/scaffold_templates/templates/partial.html.erb.tt +13 -0
  399. data/lib/generators/poetry/scaffold_templates/templates/show.html.erb.tt +18 -0
  400. data/lib/generators/poetry/skill/skill_generator.rb +34 -0
  401. data/lib/generators/poetry/skill/templates/poetry-component/SKILL.md +58 -0
  402. data/lib/generators/poetry/skill/templates/poetry-component/references/anatomy.md +152 -0
  403. data/lib/generators/poetry/skill/templates/poetry-component/references/checklist.md +67 -0
  404. data/lib/generators/poetry/skill/templates/poetry-component/references/documentation.md +137 -0
  405. data/lib/generators/poetry/skill/templates/poetry-design/SKILL.md +56 -0
  406. data/lib/generators/poetry/skill/templates/poetry-design/references/audit.md +123 -0
  407. data/lib/generators/poetry/skill/templates/poetry-design/references/compose.md +73 -0
  408. data/lib/generators/poetry/skill/templates/poetry-design/references/figma.md +68 -0
  409. data/lib/generators/poetry/skill/templates/poetry-design/references/paper.md +56 -0
  410. data/lib/generators/poetry/skill/templates/poetry-design/references/study.md +47 -0
  411. data/lib/generators/poetry/skill/templates/poetry-design/references/theme.md +70 -0
  412. data/lib/generators/poetry/skills_section.rb +58 -0
  413. data/lib/poetry/ui/chat.rb +283 -0
  414. data/lib/poetry/ui/code_block_highlighter.rb +60 -0
  415. data/lib/poetry/ui/engine.rb +55 -0
  416. data/lib/poetry/ui/recipes.rb +157 -0
  417. data/lib/poetry/ui/testing/combobox.rb +167 -0
  418. data/lib/poetry/ui/testing/dialog.rb +73 -0
  419. data/lib/poetry/ui/testing/menu.rb +127 -0
  420. data/lib/poetry/ui/testing/registration.rb +58 -0
  421. data/lib/poetry/ui/testing/select.rb +147 -0
  422. data/lib/poetry/ui/testing/tester.rb +130 -0
  423. data/lib/poetry/ui/testing.rb +130 -0
  424. data/lib/poetry/ui/themes.rb +109 -0
  425. data/lib/poetry/ui/version.rb +8 -0
  426. data/lib/poetry/ui/webmcp.rb +91 -0
  427. data/lib/poetry/ui.rb +285 -0
  428. data/lib/poetry-ui.rb +5 -0
  429. data/lib/tasks/poetry/check.rake +73 -0
  430. data/lib/tasks/poetry/design.rake +293 -0
  431. data/lib/tasks/poetry/verify.rake +36 -0
  432. data/themes/default.css +1793 -0
  433. data/themes/luma.css +1764 -0
  434. data/themes/lyra.css +1768 -0
  435. data/themes/maia.css +1768 -0
  436. data/themes/mira.css +1760 -0
  437. data/themes/nova.css +1755 -0
  438. data/themes/rhea.css +1771 -0
  439. data/themes/sera.css +1757 -0
  440. data/themes/vega.css +1775 -0
  441. data/typeset/typeset.css +499 -0
  442. metadata +502 -0
data/themes/rhea.css ADDED
@@ -0,0 +1,1771 @@
1
+ /* poetry rhea theme - upstream style-rhea.css ported onto the
2
+ * cn-* layer (pinned clone 1773ecfe, the shadcn@4.19.0 release). Same contract as default.css:
3
+ * imported layer(base); bare selectors while installs carry ONE theme;
4
+ * rule order per component = base < elements < variants < compounds;
5
+ * split-side, no-empty-rules and cross-component-last rules apply.
6
+ *
7
+ * Port disciplines identical to vega (see
8
+ * docs/rhea-port-ledger.txt): verbatim where poetry speaks the
9
+ * vocabulary; data-vertical -> data-[orientation=*]; data-[state=on] ->
10
+ * data-pressed; overlays -> native-dialog backdrop:*; upstream !
11
+ * stripped except the sidebar collapse geometry; icon paddings ship
12
+ * upstream's has-data-[icon=*] (inert) plus working
13
+ * >svg:first/last-child twins; soft destructive holds AA via
14
+ * relative-oklch light-mode darkening (AA-contrast posture). Rhea-judged:
15
+ * boxed 2xl accordion root (the root hook); accordion trigger carries
16
+ * poetry's focus-visible cluster (upstream ships none); the floating
17
+ * drawer geometry is live (ported from the source popup rules).
18
+ */
19
+
20
+ /* MARK: Alert */
21
+ .cn-alert {
22
+ @apply grid grid-cols-[0_1fr] items-start gap-y-0.5 rounded-2xl border px-4 py-3 text-left text-sm has-data-[slot=alert-action]:relative has-data-[slot=alert-action]:pr-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2.5 [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current;
23
+ }
24
+
25
+ .cn-alert-action {
26
+ @apply absolute top-2.5 right-3;
27
+ }
28
+
29
+ .cn-alert-title {
30
+ @apply col-start-2 font-medium;
31
+ }
32
+
33
+ .cn-alert-description {
34
+ @apply col-start-2 text-sm text-muted-foreground text-balance md:text-pretty [&_p:not(:last-child)]:mb-4;
35
+ }
36
+
37
+ .cn-alert-variant-default {
38
+ @apply bg-card text-card-foreground;
39
+ }
40
+
41
+ .cn-alert-variant-destructive {
42
+ @apply text-destructive bg-card *:data-[slot=alert-description]:text-destructive/90 *:[svg]:text-current;
43
+ }
44
+
45
+ /* MARK: Accordion */
46
+ /* Root hook: boxed-root themes (mira/rhea, later luma/maia)
47
+ * style this; every fragment must give the name content (the compile
48
+ * gate), so default carries the upstream demo idiom. */
49
+ .cn-accordion {
50
+ @apply w-full overflow-hidden rounded-2xl border;
51
+ }
52
+
53
+ .cn-accordion-item {
54
+ @apply data-open:bg-muted/50 not-last:border-b;
55
+ }
56
+
57
+ .cn-accordion-trigger {
58
+ @apply gap-6 p-4 text-left text-sm font-medium hover:underline focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50;
59
+ }
60
+
61
+ .cn-accordion-trigger-icon {
62
+ @apply ml-auto size-4 text-muted-foreground;
63
+ }
64
+
65
+ .cn-accordion-content {
66
+ @apply data-open:animate-accordion-down data-closed:animate-accordion-up px-4 text-sm;
67
+ }
68
+
69
+ .cn-accordion-content-inner {
70
+ @apply pt-0 pb-4;
71
+ }
72
+
73
+ /* MARK: AlertDialog */
74
+ .cn-alert-dialog-content {
75
+ @apply w-full max-w-[calc(100%-2rem)] bg-popover text-popover-foreground ring-foreground/5 dark:ring-foreground/10 gap-6 rounded-[min(var(--radius-4xl),24px)] p-6 shadow-xl ring-1 duration-100 data-[size=default]:max-w-xs data-[size=sm]:max-w-xs data-[size=default]:sm:max-w-md backdrop:bg-black/10 supports-backdrop-filter:backdrop:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95;
76
+ }
77
+
78
+ .cn-alert-dialog-header {
79
+ @apply gap-1.5 has-data-[slot=alert-dialog-media]:gap-x-6;
80
+ }
81
+
82
+ .cn-alert-dialog-media {
83
+ @apply mb-2 size-16 rounded-md bg-muted *:[svg:not([class*='size-'])]:size-8;
84
+ }
85
+
86
+ .cn-alert-dialog-title {
87
+ @apply text-lg font-medium;
88
+ }
89
+
90
+ .cn-alert-dialog-description {
91
+ @apply text-muted-foreground *:[a]:hover:text-foreground text-sm text-balance md:text-pretty *:[a]:underline *:[a]:underline-offset-3;
92
+ }
93
+
94
+ /* Footer hook: nova bands it; gap-2 moved here from the inline
95
+ * set with the name (direction/justify stay inline - the sm-size grid
96
+ * branch replaces them consumer-side). */
97
+ .cn-alert-dialog-footer {
98
+ @apply gap-2;
99
+ }
100
+
101
+ /* MARK: Attachment */
102
+ /* w-fit lives here so the vertical orientation's w-24 beats it in-layer
103
+ * (split-side rule). */
104
+ .cn-attachment {
105
+ @apply rounded-2xl w-fit focus-within:ring-1 focus-within:ring-ring/30;
106
+ }
107
+
108
+ .cn-attachment-actions {
109
+ @apply group-data-[orientation=vertical]/attachment:absolute group-data-[orientation=vertical]/attachment:top-3 group-data-[orientation=vertical]/attachment:right-3 relative z-20 group-data-[orientation=vertical]/attachment:gap-1;
110
+ }
111
+
112
+ .cn-attachment-trigger {
113
+ @apply absolute inset-0 z-10 outline-none;
114
+ }
115
+
116
+ .cn-attachment-media-variant-image {
117
+ @apply opacity-60 group-data-[state=idle]/attachment:opacity-100 group-data-[state=done]/attachment:opacity-100;
118
+ }
119
+
120
+ .cn-attachment-size-default {
121
+ @apply gap-2 text-sm has-data-[slot=attachment-content]:px-2.5 has-data-[slot=attachment-content]:py-2 has-data-[slot=attachment-media]:p-2;
122
+ }
123
+
124
+ .cn-attachment-size-sm {
125
+ @apply gap-2.5 text-xs has-data-[slot=attachment-content]:px-2 has-data-[slot=attachment-content]:py-1.5 has-data-[slot=attachment-media]:p-1.5;
126
+ }
127
+
128
+ .cn-attachment-size-xs {
129
+ @apply gap-1.5 has-data-[slot=attachment-content]:px-1.5 has-data-[slot=attachment-content]:py-1 has-data-[slot=attachment-media]:p-1 text-xs rounded-xl;
130
+ }
131
+
132
+ .cn-attachment-orientation-horizontal {
133
+ @apply min-w-40;
134
+ }
135
+
136
+ .cn-attachment-orientation-vertical {
137
+ @apply w-24 has-data-[slot=attachment-content]:w-30;
138
+ }
139
+
140
+ .cn-attachment-media {
141
+ @apply bg-muted text-foreground w-10 rounded-lg group-data-[size=sm]/attachment:w-8 group-data-[size=xs]/attachment:w-7 group-data-[size=xs]/attachment:rounded-md [&_svg:not([class*='size-'])]:size-4 group-data-[size=xs]/attachment:[&_svg:not([class*='size-'])]:size-3.5 group-data-[orientation=vertical]/attachment:w-full group-data-[orientation=vertical]/attachment:[&_svg:not([class*='size-'])]:size-6 group-data-[orientation=vertical]/attachment:*:data-[slot=spinner]:size-6;
142
+ }
143
+
144
+ .cn-attachment-content {
145
+ @apply leading-tight group-data-[orientation=vertical]/attachment:px-1;
146
+ }
147
+
148
+ .cn-attachment-title {
149
+ @apply font-medium;
150
+ }
151
+
152
+ .cn-attachment-description {
153
+ @apply mt-0.5 text-xs;
154
+ }
155
+
156
+ .cn-attachment-group {
157
+ @apply gap-3 py-1 scroll-px-1;
158
+ }
159
+
160
+ /* MARK: Avatar */
161
+ .cn-avatar {
162
+ @apply size-8 rounded-full after:rounded-full data-[size=lg]:size-10 data-[size=sm]:size-6;
163
+ }
164
+
165
+ .cn-avatar-image {
166
+ @apply rounded-full;
167
+ }
168
+
169
+ .cn-avatar-fallback {
170
+ @apply rounded-full bg-muted text-muted-foreground;
171
+ }
172
+
173
+ .cn-avatar-badge {
174
+ @apply bg-primary text-primary-foreground ring-background group-data-[size=sm]/avatar:size-2 group-data-[size=sm]/avatar:[&>svg]:hidden group-data-[size=default]/avatar:size-2.5 group-data-[size=default]/avatar:[&>svg]:size-2 group-data-[size=lg]/avatar:size-3 group-data-[size=lg]/avatar:[&>svg]:size-2;
175
+ }
176
+
177
+ .cn-avatar-group-count {
178
+ @apply size-8 rounded-full bg-muted text-sm text-muted-foreground group-has-data-[size=lg]/avatar-group:size-10 group-has-data-[size=sm]/avatar-group:size-6 [&>svg]:size-4 group-has-data-[size=lg]/avatar-group:[&>svg]:size-5 group-has-data-[size=sm]/avatar-group:[&>svg]:size-3;
179
+ }
180
+
181
+ /* MARK: Badge */
182
+ /* The focus/invalid ring chain lives HERE (upstream keeps it inline): the
183
+ * destructive variant re-colors focus-visible:ring-* and can only beat
184
+ * the base treatment from the same layer. */
185
+ .cn-badge {
186
+ @apply h-5 gap-1 rounded-2xl border border-transparent px-2 py-0.5 text-xs font-medium transition-all has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 has-[>svg:first-child]:pl-1.5 has-[>svg:last-child]:pr-1.5 [&>svg]:size-3 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/30 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40;
187
+ }
188
+
189
+ .cn-badge-variant-ghost {
190
+ @apply hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50;
191
+ }
192
+
193
+ .cn-badge-variant-link {
194
+ @apply text-primary underline-offset-4 hover:underline;
195
+ }
196
+
197
+ .cn-badge-variant-default {
198
+ @apply bg-primary text-primary-foreground [a]:hover:bg-primary/80;
199
+ }
200
+
201
+ .cn-badge-variant-secondary {
202
+ @apply bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80;
203
+ }
204
+
205
+ .cn-badge-variant-destructive {
206
+ @apply bg-destructive/10 [a]:hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 text-[oklch(from_var(--destructive)_calc(l*0.85)_c_h)] dark:text-destructive dark:bg-destructive/20;
207
+ }
208
+
209
+ .cn-badge-variant-outline {
210
+ @apply border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground;
211
+ }
212
+
213
+ .cn-badge-variant-success {
214
+ @apply bg-success/10 [a]:hover:bg-success/20 focus-visible:ring-success/20 dark:focus-visible:ring-success/40 text-[oklch(from_var(--success)_calc(l*0.85)_c_h)] dark:text-success dark:bg-success/20;
215
+ }
216
+
217
+ .cn-badge-variant-warning {
218
+ @apply bg-warning/10 [a]:hover:bg-warning/20 focus-visible:ring-warning/20 dark:focus-visible:ring-warning/40 text-[oklch(from_var(--warning)_calc(l*0.85)_c_h)] dark:text-warning dark:bg-warning/20;
219
+ }
220
+
221
+ .cn-badge-variant-info {
222
+ @apply bg-info/10 [a]:hover:bg-info/20 focus-visible:ring-info/20 dark:focus-visible:ring-info/40 text-[oklch(from_var(--info)_calc(l*0.85)_c_h)] dark:text-info dark:bg-info/20;
223
+ }
224
+
225
+ /* MARK: Breadcrumb */
226
+ .cn-breadcrumb-list {
227
+ @apply gap-1.5 text-sm text-muted-foreground sm:gap-2.5;
228
+ }
229
+
230
+ .cn-breadcrumb-item {
231
+ @apply gap-1.5;
232
+ }
233
+
234
+ .cn-breadcrumb-link {
235
+ @apply transition-colors hover:text-foreground;
236
+ }
237
+
238
+ .cn-breadcrumb-page {
239
+ @apply font-normal text-foreground;
240
+ }
241
+
242
+ .cn-breadcrumb-separator {
243
+ @apply [&>svg]:size-3.5;
244
+ }
245
+
246
+ .cn-breadcrumb-ellipsis {
247
+ @apply size-5 [&>svg]:size-4;
248
+ }
249
+
250
+ /* MARK: Bubble */
251
+ .cn-bubble {
252
+ @apply gap-1 data-[align=end]:self-end max-w-[80%] data-[variant=ghost]:max-w-full group-data-[align=end]/message:self-end;
253
+ }
254
+
255
+ .cn-bubble-group {
256
+ @apply gap-2;
257
+ }
258
+
259
+ .cn-bubble-variant-default {
260
+ @apply *:data-[slot=bubble-content]:bg-primary *:data-[slot=bubble-content]:text-primary-foreground [&>[data-slot=bubble-content]:is(button,a):hover]:bg-primary/80;
261
+ }
262
+
263
+ .cn-bubble-variant-secondary {
264
+ @apply *:data-[slot=bubble-content]:bg-secondary *:data-[slot=bubble-content]:text-secondary-foreground [&>[data-slot=bubble-content]:is(button,a):hover]:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)];
265
+ }
266
+
267
+ .cn-bubble-variant-muted {
268
+ @apply *:data-[slot=bubble-content]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:bg-[color-mix(in_oklch,var(--muted),var(--foreground)_5%)];
269
+ }
270
+
271
+ .cn-bubble-variant-tinted {
272
+ @apply *:data-[slot=bubble-content]:bg-[oklch(from_var(--primary)_0.93_calc(c*0.4)_h)] *:data-[slot=bubble-content]:text-foreground dark:*:data-[slot=bubble-content]:bg-[oklch(from_var(--primary)_0.3_calc(c*0.4)_h)] [&>[data-slot=bubble-content]:is(button,a):hover]:bg-[oklch(from_var(--primary)_0.88_calc(c*0.5)_h)] dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-[oklch(from_var(--primary)_0.35_calc(c*0.5)_h)];
273
+ }
274
+
275
+ .cn-bubble-variant-outline {
276
+ @apply *:data-[slot=bubble-content]:border-border *:data-[slot=bubble-content]:bg-background [&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:text-foreground dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-input/30;
277
+ }
278
+
279
+ .cn-bubble-variant-ghost {
280
+ @apply border-none *:data-[slot=bubble-content]:rounded-none *:data-[slot=bubble-content]:bg-transparent *:data-[slot=bubble-content]:p-0 [&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:text-foreground dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted/50;
281
+ }
282
+
283
+ .cn-bubble-variant-destructive {
284
+ @apply *:data-[slot=bubble-content]:bg-destructive/10 *:data-[slot=bubble-content]:text-destructive dark:*:data-[slot=bubble-content]:bg-destructive/20 [&>[data-slot=bubble-content]:is(button,a):hover]:bg-destructive/20 dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-destructive/30;
285
+ }
286
+
287
+ .cn-bubble-content {
288
+ @apply rounded-3xl border border-transparent px-3 py-2.5 text-sm leading-relaxed [button,a]:outline-none [button,a]:focus-visible:border-ring [button,a]:focus-visible:ring-3 [button,a]:focus-visible:ring-ring/30 group-data-[align=end]/bubble:self-end;
289
+ }
290
+
291
+ .cn-bubble-reactions {
292
+ @apply rounded-full ring-3 ring-card bg-muted gap-1 px-1.5 py-0.5 has-[button]:p-0 text-sm;
293
+ }
294
+
295
+ /* MARK: Button */
296
+ .cn-button {
297
+ @apply focus-visible:border-ring focus-visible:ring-ring/30 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 rounded-2xl border border-transparent bg-clip-padding text-sm font-medium focus-visible:ring-3 aria-invalid:ring-3 active:not-aria-[haspopup]:translate-y-px [&_svg:not([class*='size-'])]:size-4;
298
+ }
299
+
300
+ .cn-button-variant-default {
301
+ @apply bg-primary text-primary-foreground hover:bg-primary/80;
302
+ }
303
+
304
+ .cn-button-variant-destructive {
305
+ @apply bg-destructive/10 hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/20 text-[oklch(from_var(--destructive)_calc(l*0.85)_c_h)] dark:text-destructive focus-visible:border-destructive/40 dark:hover:bg-destructive/30;
306
+ }
307
+
308
+ .cn-button-variant-outline {
309
+ @apply border-border bg-background dark:bg-transparent hover:bg-muted hover:text-foreground dark:hover:bg-input/30 aria-expanded:bg-muted aria-expanded:text-foreground;
310
+ }
311
+
312
+ .cn-button-variant-secondary {
313
+ @apply bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground;
314
+ }
315
+
316
+ .cn-button-variant-ghost {
317
+ @apply hover:bg-muted hover:text-foreground dark:hover:bg-muted/50 aria-expanded:bg-muted aria-expanded:text-foreground;
318
+ }
319
+
320
+ .cn-button-variant-link {
321
+ @apply text-primary underline-offset-4 hover:underline;
322
+ }
323
+
324
+ .cn-button-size-default {
325
+ @apply h-8 gap-1.5 px-3 has-data-[icon=inline-end]:pr-2.5 has-data-[icon=inline-start]:pl-2.5 has-[>svg:first-child]:pl-2.5 has-[>svg:last-child]:pr-2.5;
326
+ }
327
+
328
+ .cn-button-size-xs {
329
+ @apply h-6 gap-1 px-2.5 text-xs has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2 has-[>svg:first-child]:pl-2 has-[>svg:last-child]:pr-2 [&_svg:not([class*='size-'])]:size-3;
330
+ }
331
+
332
+ .cn-button-size-sm {
333
+ @apply h-7 gap-1 px-3 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2 has-[>svg:first-child]:pl-2 has-[>svg:last-child]:pr-2;
334
+ }
335
+
336
+ .cn-button-size-lg {
337
+ @apply h-9 gap-1.5 px-4 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3 has-[>svg:first-child]:pl-3 has-[>svg:last-child]:pr-3;
338
+ }
339
+
340
+ .cn-button-size-icon {
341
+ @apply size-8;
342
+ }
343
+
344
+ .cn-button-size-icon-xs {
345
+ @apply size-6 [&_svg:not([class*='size-'])]:size-3;
346
+ }
347
+
348
+ .cn-button-size-icon-sm {
349
+ @apply size-7;
350
+ }
351
+
352
+ .cn-button-size-icon-lg {
353
+ @apply size-9;
354
+ }
355
+
356
+ /* MARK: ButtonGroup */
357
+ .cn-button-group {
358
+ @apply has-[>[data-slot=button-group]]:gap-2 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-2xl has-[>[data-variant=outline]]:[&>input]:border-border has-[>[data-variant=outline]]:[&>input:focus-visible]:border-ring has-[>[data-variant=outline]]:*:data-[slot=input-group]:border-border has-[>[data-variant=outline]]:[&>[data-slot=input-group]:has(:focus-visible)]:border-ring has-[>[data-variant=outline]]:*:data-[slot=select-trigger]:border-border has-[>[data-variant=outline]]:[&>[data-slot=select-trigger]:focus-visible]:border-ring;
359
+ }
360
+
361
+ .cn-button-group-orientation-horizontal {
362
+ @apply *:data-slot:rounded-r-none [&>[data-slot]:not(:has(~[data-slot]))]:rounded-r-2xl! [&>[data-slot]~[data-slot]]:rounded-l-none [&>[data-slot]~[data-slot]]:border-l-0 [&>:is([data-slot=select],[data-slot=dropdown-menu],[data-slot=popover]):has(~[data-slot])_:is([data-slot=select-trigger],[data-slot=dropdown-menu-trigger],[data-slot=popover-trigger])]:rounded-r-none [&>:is([data-slot=select],[data-slot=dropdown-menu],[data-slot=popover]):not(:has(~[data-slot]))_:is([data-slot=select-trigger],[data-slot=dropdown-menu-trigger],[data-slot=popover-trigger])]:rounded-r-2xl! [&>[data-slot]~:is([data-slot=select],[data-slot=dropdown-menu],[data-slot=popover])_:is([data-slot=select-trigger],[data-slot=dropdown-menu-trigger],[data-slot=popover-trigger])]:rounded-l-none [&>[data-slot]~:is([data-slot=select],[data-slot=dropdown-menu],[data-slot=popover])_:is([data-slot=select-trigger],[data-slot=dropdown-menu-trigger],[data-slot=popover-trigger])]:border-l-0;
363
+ }
364
+
365
+ .cn-button-group-orientation-vertical {
366
+ @apply flex-col *:data-slot:rounded-b-none [&>[data-slot]:not(:has(~[data-slot]))]:rounded-b-2xl! [&>[data-slot]~[data-slot]]:rounded-t-none [&>[data-slot]~[data-slot]]:border-t-0 [&>:is([data-slot=select],[data-slot=dropdown-menu],[data-slot=popover]):has(~[data-slot])_:is([data-slot=select-trigger],[data-slot=dropdown-menu-trigger],[data-slot=popover-trigger])]:rounded-b-none [&>:is([data-slot=select],[data-slot=dropdown-menu],[data-slot=popover]):not(:has(~[data-slot]))_:is([data-slot=select-trigger],[data-slot=dropdown-menu-trigger],[data-slot=popover-trigger])]:rounded-b-2xl! [&>[data-slot]~:is([data-slot=select],[data-slot=dropdown-menu],[data-slot=popover])_:is([data-slot=select-trigger],[data-slot=dropdown-menu-trigger],[data-slot=popover-trigger])]:rounded-t-none [&>[data-slot]~:is([data-slot=select],[data-slot=dropdown-menu],[data-slot=popover])_:is([data-slot=select-trigger],[data-slot=dropdown-menu-trigger],[data-slot=popover-trigger])]:border-t-0;
367
+ }
368
+
369
+ .cn-button-group-text {
370
+ @apply bg-muted gap-2 rounded-2xl border px-2.5 text-sm font-medium [&_svg:not([class*='size-'])]:size-4;
371
+ }
372
+
373
+ .cn-button-group-separator {
374
+ @apply bg-input!;
375
+ }
376
+
377
+ /* MARK: Calendar */
378
+ .cn-calendar {
379
+ @apply p-3;
380
+ }
381
+
382
+ .cn-calendar-caption {
383
+ @apply text-sm font-medium;
384
+ }
385
+
386
+ .cn-calendar-weekday {
387
+ @apply rounded-md text-[0.8rem] font-normal text-muted-foreground;
388
+ }
389
+
390
+ .cn-calendar-day-button {
391
+ @apply rounded-md text-sm leading-none font-normal hover:bg-accent hover:text-accent-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:text-muted-foreground disabled:opacity-50 data-today:bg-muted data-today:text-foreground data-outside:text-muted-foreground data-selected:bg-primary data-selected:text-primary-foreground data-selected:hover:bg-primary data-selected:hover:text-primary-foreground data-range-start:rounded-l-md data-range-start:bg-primary data-range-start:text-primary-foreground data-range-middle:rounded-none data-range-middle:bg-muted data-range-middle:text-foreground data-range-end:rounded-r-md data-range-end:bg-primary data-range-end:text-primary-foreground;
392
+ }
393
+
394
+ /* MARK: Card */
395
+ .cn-card {
396
+ @apply bg-card text-card-foreground ring-foreground/5 dark:ring-foreground/10 gap-(--card-spacing) overflow-hidden rounded-[min(var(--radius-4xl),24px)] py-(--card-spacing) text-sm shadow-sm ring-1 [--card-spacing:--spacing(5)] has-[>img:first-child]:pt-0 data-[size=sm]:[--card-spacing:--spacing(4)] *:[img:first-child]:rounded-t-[min(var(--radius-4xl),24px)] *:[img:last-child]:rounded-b-[min(var(--radius-4xl),24px)];
397
+ }
398
+
399
+ .cn-card-header {
400
+ @apply gap-1.5 rounded-t-[min(var(--radius-4xl),24px)] px-(--card-spacing) [.border-b]:pb-(--card-spacing);
401
+ }
402
+
403
+ .cn-card-title {
404
+ @apply text-base font-medium;
405
+ }
406
+
407
+ .cn-card-description {
408
+ @apply text-sm text-muted-foreground;
409
+ }
410
+
411
+ .cn-card-content {
412
+ @apply px-(--card-spacing);
413
+ }
414
+
415
+ .cn-card-footer {
416
+ @apply rounded-b-[min(var(--radius-4xl),24px)] px-(--card-spacing) [.border-t]:pt-(--card-spacing);
417
+ }
418
+
419
+ /* MARK: Checkbox */
420
+ .cn-checkbox {
421
+ @apply bg-input/90 data-checked:bg-primary data-checked:text-primary-foreground dark:data-checked:bg-primary data-checked:border-primary border-transparent aria-invalid:aria-checked:border-primary aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 focus-visible:border-ring focus-visible:ring-ring/30 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 flex size-4 items-center justify-center rounded-[5px] border transition-shadow focus-visible:ring-3 aria-invalid:ring-3 group-has-[:focus-visible]/field-label:data-checked:border-primary group-has-[:focus-visible]/field-label:not-data-checked:border-transparent group-has-[:focus-visible]/field-label:ring-0 group-has-disabled/field:opacity-50;
422
+ }
423
+
424
+ .cn-checkbox-indicator {
425
+ @apply [&>svg]:size-3.5;
426
+ }
427
+
428
+ /* MARK: CodeBlock */
429
+ /* The syntax palette: seven vars the dictionary's token map reads
430
+ * (GitHub light/dark is the shared v1 baseline - a theme restyles code by
431
+ * redefining the vars); .hll is highlight_lines:, .line::before the CSS
432
+ * counters (out of copied text by construction). */
433
+ .cn-code-block {
434
+ @apply bg-muted/30 rounded-lg border text-foreground [--syntax-keyword:#a40e26] [--syntax-constant:#0550ae] [--syntax-string:#0a3069] [--syntax-entity:#7f3400] [--syntax-markup:#116329] [--syntax-function:#6639ba] [--syntax-comment:#57606a] dark:[--syntax-keyword:#ff7b72] dark:[--syntax-constant:#79c0ff] dark:[--syntax-string:#a5d6ff] dark:[--syntax-entity:#ffa657] dark:[--syntax-markup:#7ee787] dark:[--syntax-function:#d2a8ff] dark:[--syntax-comment:#8b949e];
435
+ }
436
+ .cn-code-block .hll {
437
+ @apply bg-primary/10 -mx-4 w-[calc(100%+2rem)] px-4;
438
+ }
439
+ .cn-code-block[data-line-numbers] .line::before {
440
+ @apply text-muted-foreground me-4 inline-block w-6 text-right content-[counter(line)] [counter-increment:line];
441
+ }
442
+
443
+ /* MARK: Command */
444
+ .cn-command {
445
+ @apply bg-popover text-popover-foreground rounded-3xl p-1;
446
+ }
447
+
448
+ .cn-input-otp-group {
449
+ @apply has-aria-invalid:ring-destructive/20 dark:has-aria-invalid:ring-destructive/40 has-aria-invalid:border-destructive rounded-2xl has-aria-invalid:ring-3;
450
+ }
451
+
452
+ .cn-input-otp-separator {
453
+ @apply [&_svg:not([class*='size-'])]:size-4;
454
+ }
455
+
456
+ .cn-command-input-icon {
457
+ @apply size-4 shrink-0 opacity-50;
458
+ }
459
+
460
+ .cn-command-input-wrapper {
461
+ @apply m-1 mb-0 h-8 gap-2 rounded-2xl border border-input/30 bg-input/50 px-2 shadow-none;
462
+ }
463
+
464
+ .cn-command-input {
465
+ @apply w-full bg-transparent text-sm placeholder:text-muted-foreground;
466
+ }
467
+
468
+ /* Loose items (direct children, no group): the source's palette never
469
+ * renders them, so the list carries the inset itself and its groups drop
470
+ * their horizontal padding - every row aligns; group-only lists keep the
471
+ * cmdk geometry. */
472
+ .cn-command-list {
473
+ @apply no-scrollbar max-h-72 scroll-py-1 outline-none has-[>[data-slot=command-item]]:p-1 has-[>[data-slot=command-item]]:*:data-[slot=command-group]:px-0;
474
+ }
475
+
476
+ .cn-command-empty {
477
+ @apply py-6 text-center text-sm;
478
+ }
479
+
480
+ .cn-command-group {
481
+ @apply text-foreground p-1;
482
+ }
483
+
484
+ .cn-command-group-heading {
485
+ @apply px-2 py-1.5 text-xs font-medium text-muted-foreground;
486
+ }
487
+
488
+ .cn-command-item {
489
+ @apply data-highlighted:bg-muted data-highlighted:text-foreground data-highlighted:*:[svg]:text-foreground items-center gap-2 min-h-7 rounded-xl px-2 py-1.5 text-sm outline-hidden select-none in-data-[slot=dialog-content]:rounded-2xl [&_svg:not([class*='size-'])]:size-4;
490
+ }
491
+
492
+ .cn-command-shortcut {
493
+ @apply text-muted-foreground group-data-highlighted/command-item:text-foreground ml-auto text-xs tracking-widest;
494
+ }
495
+
496
+ .cn-command-separator {
497
+ @apply bg-border/50 my-1 h-px;
498
+ }
499
+
500
+ /* MARK: Combobox */
501
+ .cn-combobox-trigger {
502
+ @apply h-9 w-[200px] gap-2 rounded-md border bg-background px-4 py-2 text-sm font-normal shadow-xs hover:bg-accent hover:text-accent-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[placeholder]:text-muted-foreground dark:aria-invalid:ring-destructive/40 dark:border-input dark:bg-input/30 dark:hover:bg-input/50 has-[>svg]:px-3 [&_svg:not([class*='size-'])]:size-4;
503
+ }
504
+
505
+ .cn-combobox-content {
506
+ @apply bg-popover text-popover-foreground ring-foreground/5 dark:ring-foreground/10 max-h-72 min-w-36 overflow-hidden rounded-2xl p-0 shadow-lg ring-1 duration-100 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2;
507
+ }
508
+
509
+ /* The popup's list and group label: the source's combobox rules (the
510
+ * inset rides the LIST, the group stays unpadded). */
511
+ .cn-combobox-label {
512
+ @apply text-muted-foreground px-2 py-1.5 text-xs;
513
+ }
514
+
515
+ .cn-combobox-list {
516
+ @apply no-scrollbar max-h-[min(calc(--spacing(72)---spacing(9)),calc(var(--available-height)---spacing(9)))] scroll-py-1 overflow-y-auto p-1 data-empty:p-0;
517
+ }
518
+
519
+ .cn-combobox-item-indicator {
520
+ @apply pointer-events-none absolute right-2 flex size-4 items-center justify-center;
521
+ }
522
+
523
+ /* The chips FIELD (multiple:) - rhea's tinted borderless field (the
524
+ * tinted-surface playbook: chips lift as background pills, never
525
+ * muted-on-tint). */
526
+ .cn-combobox-chips {
527
+ @apply min-h-8 gap-1.5 rounded-2xl border border-transparent bg-input/50 px-2.5 py-1 text-sm transition-[color,box-shadow] duration-200 focus-within:border-ring focus-within:ring-3 focus-within:ring-ring/30 has-data-[slot=combobox-chip]:px-1.5 has-aria-invalid:border-destructive dark:has-aria-invalid:border-destructive/50 has-aria-invalid:ring-3 has-aria-invalid:ring-destructive/20 dark:has-aria-invalid:ring-destructive/40;
528
+ }
529
+
530
+ .cn-combobox-chip {
531
+ @apply h-5.5 gap-1 rounded-2xl bg-background px-2 text-xs font-medium shadow-2xs focus-visible:ring-2 focus-visible:ring-ring/30;
532
+ }
533
+
534
+ .cn-combobox-chip-remove {
535
+ @apply -ml-1 rounded-2xl opacity-50 hover:opacity-100 focus-visible:opacity-100;
536
+ }
537
+
538
+ .cn-combobox-chip-input {
539
+ @apply min-w-16 placeholder:text-[oklch(from_var(--muted-foreground)_calc(l*0.85)_c_h)] dark:placeholder:text-muted-foreground;
540
+ }
541
+
542
+ /* MARK: ContextMenu */
543
+ .cn-context-menu-content {
544
+ @apply data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/5 dark:ring-foreground/10 bg-popover text-popover-foreground min-w-36 rounded-2xl p-1 shadow-lg ring-1 duration-100;
545
+ }
546
+
547
+ .cn-context-menu-item {
548
+ @apply focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:text-destructive focus:*:[svg]:text-accent-foreground gap-2 min-h-7 rounded-xl px-2 py-1.5 text-sm data-inset:pl-7 [&_svg:not([class*='size-'])]:size-4;
549
+ }
550
+
551
+ .cn-context-menu-checkbox-item {
552
+ @apply focus:bg-accent focus:text-accent-foreground gap-2 min-h-7 rounded-xl py-1.5 pr-8 pl-2 text-sm data-inset:pl-7 [&_svg:not([class*='size-'])]:size-4;
553
+ }
554
+
555
+ .cn-context-menu-radio-item {
556
+ @apply focus:bg-accent focus:text-accent-foreground gap-2 min-h-7 rounded-xl py-1.5 pr-8 pl-2 text-sm data-inset:pl-7 [&_svg:not([class*='size-'])]:size-4;
557
+ }
558
+
559
+ .cn-context-menu-label {
560
+ @apply text-muted-foreground px-2 py-1 text-xs data-inset:pl-7;
561
+ }
562
+
563
+ .cn-context-menu-separator {
564
+ @apply bg-border/50 -mx-1 my-1 h-px;
565
+ }
566
+
567
+ .cn-context-menu-shortcut {
568
+ @apply text-muted-foreground group-focus/context-menu-item:text-accent-foreground ml-auto text-xs tracking-widest;
569
+ }
570
+
571
+ .cn-context-menu-sub-trigger {
572
+ @apply focus:bg-accent focus:text-accent-foreground data-open:bg-accent data-open:text-accent-foreground min-h-7 rounded-xl px-2 py-1.5 text-sm data-inset:pl-7 [&_svg:not([class*='size-'])]:size-4 data-popup-open:bg-accent data-popup-open:text-accent-foreground;
573
+ }
574
+
575
+ .cn-context-menu-sub-content {
576
+ @apply data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/5 dark:ring-foreground/10 bg-popover text-popover-foreground min-w-32 rounded-2xl p-1 shadow-lg ring-1 duration-100;
577
+ }
578
+
579
+ .cn-context-menu-item-indicator {
580
+ @apply right-2;
581
+ }
582
+
583
+ /* MARK: DataTable */
584
+ .cn-data-table-toolbar {
585
+ @apply py-4;
586
+ }
587
+
588
+ .cn-data-table-container {
589
+ @apply rounded-md border;
590
+ }
591
+
592
+ .cn-data-table-footer {
593
+ @apply py-4;
594
+ }
595
+
596
+ .cn-data-table-empty {
597
+ @apply h-24 text-center;
598
+ }
599
+
600
+ /* MARK: Dialog */
601
+ .cn-dialog-content {
602
+ @apply w-full max-w-[calc(100%-2rem)] bg-popover text-popover-foreground ring-foreground/5 dark:ring-foreground/10 gap-6 rounded-[min(var(--radius-4xl),24px)] p-6 text-sm shadow-xl ring-1 duration-100 sm:max-w-md backdrop:bg-black/10 supports-backdrop-filter:backdrop:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95;
603
+ }
604
+
605
+ .cn-dialog-footer {
606
+ @apply gap-2;
607
+ }
608
+
609
+ .cn-dialog-header {
610
+ @apply gap-1.5;
611
+ }
612
+
613
+ .cn-dialog-title {
614
+ @apply text-base leading-none font-medium;
615
+ }
616
+
617
+ .cn-dialog-description {
618
+ @apply text-muted-foreground *:[a]:hover:text-foreground text-sm *:[a]:underline *:[a]:underline-offset-3;
619
+ }
620
+
621
+ .cn-dialog-close {
622
+ @apply absolute top-4 right-4 bg-secondary;
623
+ }
624
+
625
+ /* MARK: Drawer */
626
+ /* Floating drawer (source .cn-drawer-popup): --drawer-inset gaps the
627
+ viewport edges, so the surface rounds and borders on ALL sides; the
628
+ per-direction rules repeat the radius so they never re-square it. */
629
+ .cn-drawer-content {
630
+ @apply bg-popover text-sm text-popover-foreground rounded-[min(var(--radius-4xl),24px)] border border-popover shadow-xl [--drawer-inset:--spacing(2)] backdrop:bg-black/30 supports-backdrop-filter:backdrop:backdrop-blur-sm dark:border-border;
631
+ }
632
+
633
+ .cn-drawer-direction-down {
634
+ @apply rounded-[min(var(--radius-4xl),24px)];
635
+ }
636
+
637
+ .cn-drawer-direction-up {
638
+ @apply rounded-[min(var(--radius-4xl),24px)];
639
+ }
640
+
641
+ .cn-drawer-direction-left {
642
+ @apply rounded-[min(var(--radius-4xl),24px)];
643
+ }
644
+
645
+ .cn-drawer-direction-right {
646
+ @apply rounded-[min(var(--radius-4xl),24px)];
647
+ }
648
+
649
+ .cn-drawer-swipe-handle {
650
+ @apply after:h-1.5 after:w-[100px] after:rounded-full after:bg-muted;
651
+ }
652
+
653
+ .cn-drawer-header {
654
+ @apply gap-0.5 p-4 pb-0 md:gap-1.5 md:text-left;
655
+ }
656
+
657
+ .cn-drawer-footer {
658
+ @apply gap-2 p-4 pt-0;
659
+ }
660
+
661
+ .cn-drawer-title {
662
+ @apply text-foreground text-base font-medium;
663
+ }
664
+
665
+ .cn-drawer-description {
666
+ @apply text-muted-foreground text-sm;
667
+ }
668
+
669
+ .cn-drawer-body {
670
+ @apply p-4;
671
+ }
672
+
673
+ /* MARK: DropdownMenu */
674
+ .cn-dropdown-menu-content {
675
+ @apply data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/5 dark:ring-foreground/10 bg-popover text-popover-foreground min-w-32 rounded-2xl p-1 shadow-lg ring-1 duration-100;
676
+ }
677
+
678
+ .cn-dropdown-menu-item {
679
+ @apply focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:text-destructive not-data-[variant=destructive]:focus:**:text-accent-foreground gap-2 min-h-7 rounded-xl px-2 py-1.5 text-sm data-inset:pl-7 [&_svg:not([class*='size-'])]:size-4;
680
+ }
681
+
682
+ .cn-dropdown-menu-checkbox-item {
683
+ @apply focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground gap-2 min-h-7 rounded-xl py-1.5 pr-8 pl-2 text-sm data-inset:pl-7 [&_svg:not([class*='size-'])]:size-4;
684
+ }
685
+
686
+ .cn-dropdown-menu-radio-item {
687
+ @apply focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground gap-2 min-h-7 rounded-xl py-1.5 pr-8 pl-2 text-sm data-inset:pl-7 [&_svg:not([class*='size-'])]:size-4;
688
+ }
689
+
690
+ .cn-dropdown-menu-label {
691
+ @apply text-muted-foreground px-2 py-1 text-xs data-inset:pl-7;
692
+ }
693
+
694
+ .cn-dropdown-menu-separator {
695
+ @apply bg-border/50 -mx-1 my-1 h-px;
696
+ }
697
+
698
+ .cn-dropdown-menu-shortcut {
699
+ @apply text-muted-foreground group-focus/dropdown-menu-item:text-accent-foreground ml-auto text-xs tracking-widest;
700
+ }
701
+
702
+ .cn-dropdown-menu-sub-trigger {
703
+ @apply focus:bg-accent focus:text-accent-foreground data-open:bg-accent data-open:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground gap-2 min-h-7 rounded-xl px-2 py-1.5 text-sm data-inset:pl-7 [&_svg:not([class*='size-'])]:size-4 data-popup-open:bg-accent data-popup-open:text-accent-foreground;
704
+ }
705
+
706
+ .cn-dropdown-menu-sub-content {
707
+ @apply data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/5 dark:ring-foreground/10 bg-popover text-popover-foreground min-w-[96px] rounded-2xl p-1 shadow-lg ring-1 duration-100;
708
+ }
709
+
710
+ .cn-dropdown-menu-item-indicator {
711
+ @apply right-2 flex items-center justify-center;
712
+ }
713
+
714
+ /* MARK: Empty */
715
+ .cn-empty {
716
+ @apply gap-4 rounded-3xl border-dashed p-12;
717
+ }
718
+
719
+ .cn-empty-header {
720
+ @apply gap-2;
721
+ }
722
+
723
+ .cn-empty-media {
724
+ @apply mb-2;
725
+ }
726
+
727
+ .cn-empty-media-default {
728
+ @apply bg-transparent;
729
+ }
730
+
731
+ .cn-empty-media-icon {
732
+ @apply bg-muted text-foreground flex size-10 shrink-0 items-center justify-center rounded-xl [&_svg:not([class*='size-'])]:size-5;
733
+ }
734
+
735
+ .cn-empty-title {
736
+ @apply text-lg font-medium tracking-tight;
737
+ }
738
+
739
+ .cn-empty-description {
740
+ @apply text-sm/relaxed;
741
+ }
742
+
743
+ .cn-empty-content {
744
+ @apply gap-4 text-sm;
745
+ }
746
+
747
+ /* MARK: Field */
748
+ .cn-field {
749
+ @apply data-[invalid=true]:text-destructive gap-3;
750
+ }
751
+
752
+ .cn-field-description {
753
+ @apply text-muted-foreground text-left text-sm [[data-variant=legend]+&]:-mt-1.5;
754
+ }
755
+
756
+ .cn-field-error {
757
+ @apply text-destructive text-sm;
758
+ }
759
+
760
+ .cn-field-orientation-horizontal {
761
+ @apply gap-x-3;
762
+ }
763
+
764
+ /* Row layout: the label + hint pair packs at the theme's
765
+ cn-field-content rhythm; the field gap keeps the column axis. */
766
+ .cn-field-orientation-responsive {
767
+ @apply @md/field-group:gap-y-1;
768
+ }
769
+
770
+ .cn-field-set {
771
+ @apply gap-6 has-[>.cn-field-group-choices]:gap-3 has-[>[data-slot=radio-group]]:gap-3;
772
+ }
773
+
774
+ .cn-field-legend {
775
+ @apply mb-3 font-medium data-[variant=legend]:text-base data-[variant=label]:text-sm;
776
+ }
777
+
778
+ .cn-field-group {
779
+ @apply gap-6 *:data-[slot=field-group]:gap-4;
780
+ }
781
+
782
+ .cn-field-group-choices {
783
+ @apply gap-3;
784
+ }
785
+
786
+ .cn-field-content {
787
+ @apply gap-1;
788
+ }
789
+
790
+ .cn-field-label {
791
+ @apply has-data-checked:bg-input/30 gap-2 leading-snug *:data-[slot=field]:p-4 group-data-[disabled=true]/field:opacity-50 has-[>[data-slot=field]]:border has-[>[data-slot=field]]:has-[:focus-visible]:border-ring has-[>[data-slot=field]]:has-[:focus-visible]:ring-3 has-[>[data-slot=field]]:has-[:focus-visible]:ring-ring/50 has-[>[data-slot=field]]:not-has-[:disabled,[data-disabled]]:hover:bg-input/40 has-[>[data-slot=field]]:rounded-2xl;
792
+ }
793
+
794
+ .cn-field-label-card {
795
+ @apply rounded-2xl border p-4;
796
+ }
797
+
798
+ .cn-field-title {
799
+ @apply gap-2 leading-snug text-sm font-medium;
800
+ }
801
+
802
+ .cn-field-separator {
803
+ @apply -my-2 h-5 text-sm;
804
+ }
805
+
806
+ .cn-field-separator-content {
807
+ @apply px-2 text-muted-foreground;
808
+ }
809
+
810
+ /* MARK: HoverCard */
811
+ .cn-hover-card-content {
812
+ @apply data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/5 dark:ring-foreground/10 bg-popover text-popover-foreground w-72 rounded-3xl p-4 text-sm shadow-lg ring-1 duration-100;
813
+ }
814
+
815
+ /* MARK: Input */
816
+ /* Placeholder AA hold: muted-foreground on the tinted field surface
817
+ * (bg-input/50) drops under 4.5:1 - light mode darkens via relative
818
+ * oklch, dark restores the token (AA-contrast posture; axe caught it live).
819
+ * The invalid-state text hold counters rhea's field-level
820
+ * data-[invalid=true]:text-destructive inheritance on the tint. */
821
+ .cn-input {
822
+ @apply bg-input/50 border-transparent placeholder:text-[oklch(from_var(--muted-foreground)_calc(l*0.85)_c_h)] dark:placeholder:text-muted-foreground aria-invalid:text-[oklch(from_var(--destructive)_calc(l*0.85)_c_h)] dark:aria-invalid:text-destructive focus-visible:border-ring focus-visible:ring-ring/30 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 h-8 rounded-2xl border px-2.5 py-1 text-base transition-[color,box-shadow] duration-200 file:h-6 file:text-sm file:font-medium focus-visible:ring-3 aria-invalid:ring-3 md:text-sm;
823
+ }
824
+
825
+ /* MARK: InputGroup */
826
+ .cn-input-group {
827
+ @apply bg-input/50 border-transparent has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-ring/30 has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[[data-slot][aria-invalid=true]]:border-destructive dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40 h-8 rounded-2xl border transition-[color,box-shadow] duration-200 in-data-[slot=combobox-content]:focus-within:border-inherit in-data-[slot=combobox-content]:focus-within:ring-0 has-[[data-slot=input-group-control]:focus-visible]:ring-3 has-[[data-slot][aria-invalid=true]]:ring-3 has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3 has-[>[data-align=inline-end]]:[&>input]:pr-1.5 has-[>[data-align=inline-start]]:[&>input]:pl-1.5;
828
+ }
829
+
830
+ /* Addon AA hold: muted text (and kbd hints) on the tinted group surface
831
+ * (bg-input/50) - light darkens via relative oklch, dark restores. The
832
+ * kbd needs its own scoped token: cn-kbd's direct color beats inherited
833
+ * darkening, and the **: form outranks it by specificity. */
834
+ .cn-input-group-addon {
835
+ @apply text-[oklch(from_var(--muted-foreground)_calc(l*0.85)_c_h)] dark:text-muted-foreground **:data-[slot=kbd]:bg-muted-foreground/10 **:data-[slot=kbd]:text-[oklch(from_var(--muted-foreground)_calc(l*0.8)_c_h)] dark:**:data-[slot=kbd]:text-muted-foreground h-auto gap-2 py-1.5 text-sm font-medium group-data-[disabled=true]/input-group:opacity-50 **:data-[slot=kbd]:rounded-2xl **:data-[slot=kbd]:px-1.5 [&>svg:not([class*='size-'])]:size-4;
836
+ }
837
+
838
+ .cn-input-group-addon-align-inline-start {
839
+ @apply pl-2 has-[>button]:ml-[-0.3rem] has-[>kbd]:ml-[-0.15rem];
840
+ }
841
+
842
+ .cn-input-group-addon-align-inline-end {
843
+ @apply pr-2 has-[>button]:mr-[-0.3rem] has-[>kbd]:mr-[-0.15rem];
844
+ }
845
+
846
+ .cn-input-group-addon-align-block-start {
847
+ @apply px-2.5 pt-2 group-has-[>input]/input-group:pt-2 [.border-b]:pb-2;
848
+ }
849
+
850
+ .cn-input-group-addon-align-block-end {
851
+ @apply px-2.5 pb-2 group-has-[>input]/input-group:pb-2 [.border-t]:pt-2;
852
+ }
853
+
854
+ /* AA hold on the tinted group surface - own rule beats the addon's
855
+ * inherited darkening, so it darkens here too (light only). */
856
+ .cn-input-group-text {
857
+ @apply gap-2 text-sm text-[oklch(from_var(--muted-foreground)_calc(l*0.8)_c_h)] dark:text-muted-foreground [&_svg:not([class*='size-'])]:size-4;
858
+ }
859
+
860
+ /* MARK: InputOTP */
861
+ .cn-input-otp {
862
+ @apply gap-2;
863
+ }
864
+
865
+ .cn-input-otp-slot {
866
+ @apply bg-input/50 border-input data-[active=true]:border-ring data-[active=true]:ring-ring/30 data-[active=true]:aria-invalid:ring-destructive/20 dark:data-[active=true]:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-8 border-y border-r text-sm transition-[color,box-shadow] duration-200 outline-none first:rounded-l-2xl first:border-l last:rounded-r-2xl data-[active=true]:ring-3;
867
+ }
868
+
869
+ .cn-input-otp-caret-line {
870
+ @apply bg-foreground h-4 w-px;
871
+ }
872
+
873
+ /* MARK: Item */
874
+ .cn-item {
875
+ @apply [a]:hover:bg-muted rounded-2xl border text-sm;
876
+ }
877
+
878
+ .cn-item-media {
879
+ @apply gap-2 group-has-data-[slot=item-description]/item:translate-y-0.5 group-has-data-[slot=item-description]/item:self-start;
880
+ }
881
+
882
+ .cn-item-media-variant-default {
883
+ @apply bg-transparent;
884
+ }
885
+
886
+ .cn-item-media-variant-icon {
887
+ @apply [&_svg:not([class*='size-'])]:size-4;
888
+ }
889
+
890
+ .cn-item-media-variant-image {
891
+ @apply size-10 overflow-hidden rounded-xl group-data-[size=sm]/item:size-8 group-data-[size=xs]/item:size-6 group-data-[size=xs]/item:rounded-lg [&_img]:size-full [&_img]:object-cover;
892
+ }
893
+
894
+ .cn-item-content {
895
+ @apply gap-1 group-data-[size=xs]/item:gap-0.5;
896
+ }
897
+
898
+ .cn-item-title {
899
+ @apply gap-2 text-sm leading-snug font-medium underline-offset-4;
900
+ }
901
+
902
+ .cn-item-description {
903
+ @apply text-muted-foreground text-left text-sm;
904
+ }
905
+
906
+ .cn-item-actions {
907
+ @apply gap-2;
908
+ }
909
+
910
+ .cn-item-header {
911
+ @apply gap-2;
912
+ }
913
+
914
+ .cn-item-footer {
915
+ @apply gap-2;
916
+ }
917
+
918
+ .cn-item-group {
919
+ @apply gap-4 has-data-[size=sm]:gap-2.5 has-data-[size=xs]:gap-2;
920
+ }
921
+
922
+ .cn-item-separator {
923
+ @apply my-2;
924
+ }
925
+
926
+ .cn-item-variant-default {
927
+ @apply border-transparent;
928
+ }
929
+
930
+ .cn-item-variant-outline {
931
+ @apply border-border;
932
+ }
933
+
934
+ .cn-item-variant-muted {
935
+ @apply border-transparent bg-muted/50;
936
+ }
937
+
938
+ .cn-item-size-default {
939
+ @apply gap-3.5 px-4 py-3.5;
940
+ }
941
+
942
+ .cn-item-size-sm {
943
+ @apply gap-3.5 px-3.5 py-3;
944
+ }
945
+
946
+ .cn-item-size-xs {
947
+ @apply gap-2 px-2.5 py-2 in-data-[slot=dropdown-menu-content]:p-0;
948
+ }
949
+
950
+ /* MARK: Kbd */
951
+ .cn-kbd {
952
+ @apply bg-muted text-muted-foreground in-data-[slot=tooltip-content]:bg-background/20 in-data-[slot=tooltip-content]:text-background dark:in-data-[slot=tooltip-content]:bg-background/10 h-5 w-fit min-w-5 gap-1 rounded-lg px-1 font-sans text-xs font-medium [&_svg:not([class*='size-'])]:size-3 in-data-[slot=input-group]:bg-input;
953
+ }
954
+
955
+ .cn-kbd-group {
956
+ @apply gap-1;
957
+ }
958
+
959
+ /* MARK: Label */
960
+ .cn-label {
961
+ @apply gap-2 text-sm leading-none font-medium group-data-[disabled=true]:opacity-50 peer-disabled:opacity-50;
962
+ }
963
+
964
+ /* MARK: Link */
965
+ .cn-link {
966
+ @apply gap-1 rounded-sm text-primary underline-offset-4 focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50;
967
+ }
968
+
969
+ .cn-link-underline-hover {
970
+ @apply no-underline hover:underline;
971
+ }
972
+
973
+ .cn-link-underline-always {
974
+ @apply underline;
975
+ }
976
+
977
+ .cn-link-underline-none {
978
+ @apply no-underline;
979
+ }
980
+
981
+ /* MARK: Marker */
982
+ .cn-marker {
983
+ @apply min-h-4 gap-2 text-left text-sm text-muted-foreground [&_svg:not([class*='size-'])]:size-4 [a]:underline [a]:underline-offset-3 [a]:hover:text-foreground;
984
+ }
985
+
986
+ .cn-marker-variant-separator {
987
+ @apply before:mr-1 before:h-px before:min-w-0 before:flex-1 before:bg-border after:ml-1 after:h-px after:min-w-0 after:flex-1 after:bg-border;
988
+ }
989
+
990
+ .cn-marker-variant-border {
991
+ @apply border-b border-border pb-2;
992
+ }
993
+
994
+ .cn-marker-icon {
995
+ @apply size-4 [&_svg:not([class*='size-'])]:size-4;
996
+ }
997
+
998
+ .cn-marker-content {
999
+ @apply group-data-[variant=separator]/marker:flex-none group-data-[variant=separator]/marker:text-center *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground;
1000
+ }
1001
+
1002
+ /* MARK: Menubar */
1003
+ .cn-menubar {
1004
+ @apply h-8 rounded-2xl border p-[3px];
1005
+ }
1006
+
1007
+ .cn-menubar-checkbox-item-indicator {
1008
+ @apply left-1.5 size-4 [&_svg:not([class*='size-'])]:size-4;
1009
+ }
1010
+
1011
+ .cn-menubar-radio-item-indicator {
1012
+ @apply left-1.5 size-4 [&_svg:not([class*='size-'])]:size-4;
1013
+ }
1014
+
1015
+ .cn-navigation-menu {
1016
+ @apply max-w-max;
1017
+ }
1018
+
1019
+ .cn-menubar-trigger {
1020
+ @apply hover:bg-muted aria-expanded:bg-muted rounded-2xl px-1.5 py-[2px] text-sm font-medium;
1021
+ }
1022
+
1023
+ .cn-menubar-content {
1024
+ @apply bg-popover text-popover-foreground data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/5 dark:ring-foreground/10 min-w-36 rounded-2xl p-1 shadow-lg ring-1 duration-100;
1025
+ }
1026
+
1027
+ .cn-menubar-item {
1028
+ @apply focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:text-destructive! not-data-[variant=destructive]:focus:**:text-accent-foreground gap-2 min-h-7 rounded-xl px-2 py-1.5 text-sm data-disabled:opacity-50 data-inset:pl-7 [&_svg:not([class*='size-'])]:size-4;
1029
+ }
1030
+
1031
+ .cn-menubar-checkbox-item {
1032
+ @apply focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground gap-2 min-h-7 rounded-xl py-1.5 pr-1.5 pl-7 text-sm data-inset:pl-7;
1033
+ }
1034
+
1035
+ .cn-menubar-radio-item {
1036
+ @apply focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground gap-2 min-h-7 rounded-xl py-1.5 pr-1.5 pl-7 text-sm data-disabled:opacity-50 data-inset:pl-7 [&_svg:not([class*='size-'])]:size-4;
1037
+ }
1038
+
1039
+ .cn-menubar-label {
1040
+ @apply text-muted-foreground px-2 py-1 text-sm data-inset:pl-7;
1041
+ }
1042
+
1043
+ .cn-menubar-separator {
1044
+ @apply -mx-1 my-1 h-px bg-border/50;
1045
+ }
1046
+
1047
+ .cn-menubar-shortcut {
1048
+ @apply text-muted-foreground group-focus/menubar-item:text-accent-foreground text-xs tracking-widest;
1049
+ }
1050
+
1051
+ .cn-menubar-sub-trigger {
1052
+ @apply focus:bg-accent focus:text-accent-foreground data-open:bg-accent data-open:text-accent-foreground gap-2 min-h-7 rounded-xl px-2 py-1.5 text-sm data-inset:pl-7 [&_svg:not([class*='size-'])]:size-4 data-popup-open:bg-accent data-popup-open:text-accent-foreground;
1053
+ }
1054
+
1055
+ .cn-menubar-sub-content {
1056
+ @apply bg-popover text-popover-foreground data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/5 dark:ring-foreground/10 min-w-32 rounded-2xl p-1 shadow-lg ring-1 duration-100;
1057
+ }
1058
+
1059
+
1060
+ /* MARK: Message */
1061
+ .cn-message {
1062
+ @apply gap-2 text-sm;
1063
+ }
1064
+
1065
+ .cn-message-group {
1066
+ @apply gap-2;
1067
+ }
1068
+
1069
+ .cn-message-avatar {
1070
+ @apply min-w-8 group-has-data-[slot=message-footer]/message:-translate-y-8;
1071
+ }
1072
+
1073
+ .cn-message-content {
1074
+ @apply gap-2.5 group-data-[align=end]/message:*:data-slot:self-end;
1075
+ }
1076
+
1077
+ .cn-message-header {
1078
+ @apply px-3 text-xs font-medium text-muted-foreground group-has-data-[variant=ghost]/message:px-0;
1079
+ }
1080
+
1081
+ .cn-message-footer {
1082
+ @apply px-3 text-xs font-medium text-muted-foreground group-has-data-[variant=ghost]/message:px-0;
1083
+ }
1084
+
1085
+ /* MARK: MessageScroller */
1086
+ .cn-message-scroller-content {
1087
+ @apply gap-8;
1088
+ }
1089
+
1090
+ /* MARK: NavigationMenu */
1091
+ .cn-navigation-menu-list {
1092
+ @apply gap-0;
1093
+ }
1094
+
1095
+ .cn-navigation-menu-trigger {
1096
+ @apply hover:bg-muted focus:bg-muted data-open:hover:bg-muted data-open:focus:bg-muted data-open:bg-muted/50 focus-visible:ring-ring/30 data-popup-open:bg-muted/50 data-popup-open:hover:bg-muted rounded-2xl px-2.5 py-1.5 text-sm font-medium transition-all focus-visible:ring-3 focus-visible:outline-1 disabled:opacity-50;
1097
+ }
1098
+
1099
+ .cn-navigation-menu-trigger-icon {
1100
+ @apply ml-1 size-3 group-data-open/navigation-menu-trigger:rotate-180 group-data-popup-open/navigation-menu-trigger:rotate-180;
1101
+ }
1102
+
1103
+ .cn-navigation-menu-content {
1104
+ @apply data-[motion^=from-]:animate-in data-[motion^=to-]:animate-out data-[motion^=from-]:fade-in data-[motion^=to-]:fade-out data-[motion=from-end]:slide-in-from-right-52 data-[motion=from-start]:slide-in-from-left-52 data-[motion=to-end]:slide-out-to-right-52 data-[motion=to-start]:slide-out-to-left-52 group-data-[viewport=false]/navigation-menu:bg-popover group-data-[viewport=false]/navigation-menu:text-popover-foreground group-data-[viewport=false]/navigation-menu:data-open:animate-in group-data-[viewport=false]/navigation-menu:data-closed:animate-out group-data-[viewport=false]/navigation-menu:data-closed:zoom-out-95 group-data-[viewport=false]/navigation-menu:data-open:zoom-in-95 group-data-[viewport=false]/navigation-menu:data-open:fade-in-0 group-data-[viewport=false]/navigation-menu:data-closed:fade-out-0 group-data-[viewport=false]/navigation-menu:ring-foreground/5 group-data-[viewport=false]/navigation-menu:dark:ring-foreground/10 p-1.5 ease-[cubic-bezier(0.22,1,0.36,1)] group-data-[viewport=false]/navigation-menu:rounded-2xl group-data-[viewport=false]/navigation-menu:shadow-lg group-data-[viewport=false]/navigation-menu:ring-1 group-data-[viewport=false]/navigation-menu:duration-300;
1105
+ }
1106
+
1107
+ .cn-navigation-menu-popup {
1108
+ @apply bg-popover text-popover-foreground ring-foreground/5 dark:ring-foreground/10 rounded-3xl shadow-lg ring-1 transition-all ease-[cubic-bezier(0.22,1,0.36,1)] outline-none data-ending-style:scale-90 data-ending-style:opacity-0 data-ending-style:duration-150 data-starting-style:scale-90 data-starting-style:opacity-0;
1109
+ }
1110
+
1111
+ .cn-navigation-menu-link {
1112
+ @apply data-[active=true]:focus:bg-muted data-[active=true]:hover:bg-muted data-[active=true]:bg-muted/50 focus-visible:ring-ring/30 hover:bg-muted focus:bg-muted gap-2 rounded-2xl px-2.5 py-1.5 text-sm transition-all focus-visible:ring-3 focus-visible:outline-1 [&_svg:not([class*='size-'])]:size-4 in-data-[slot=navigation-menu-content]:rounded-xl font-medium in-data-[slot=navigation-menu-content]:font-normal in-data-[slot=navigation-menu-content]:p-2 in-data-[slot=navigation-menu-content]:w-full;
1113
+ }
1114
+
1115
+ /* MARK: NativeSelect */
1116
+ .cn-native-select {
1117
+ @apply bg-input/50 border-transparent placeholder:text-[oklch(from_var(--muted-foreground)_calc(l*0.85)_c_h)] dark:placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground focus-visible:border-ring focus-visible:ring-ring/30 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 h-8 min-w-0 rounded-2xl border py-1 pr-8 pl-2.5 text-sm transition-[color,box-shadow] duration-200 select-none focus-visible:ring-3 aria-invalid:ring-3 data-[size=sm]:h-7;
1118
+ }
1119
+
1120
+ .cn-native-select-icon {
1121
+ @apply text-muted-foreground;
1122
+ }
1123
+
1124
+ /* MARK: Pagination */
1125
+ .cn-pagination-content {
1126
+ @apply gap-1;
1127
+ }
1128
+
1129
+ .cn-carousel-previous {
1130
+ @apply rounded-2xl;
1131
+ }
1132
+
1133
+ .cn-carousel-next {
1134
+ @apply rounded-2xl;
1135
+ }
1136
+
1137
+ .cn-pagination-previous {
1138
+ @apply pl-1.5!;
1139
+ }
1140
+
1141
+ .cn-pagination-next {
1142
+ @apply pr-1.5!;
1143
+ }
1144
+
1145
+ .cn-pagination-ellipsis {
1146
+ @apply size-8 [&_svg:not([class*='size-'])]:size-4;
1147
+ }
1148
+
1149
+ /* MARK: Popover */
1150
+ .cn-popover-content {
1151
+ @apply bg-popover text-popover-foreground data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/5 dark:ring-foreground/10 flex flex-col gap-4 rounded-3xl p-4 text-sm shadow-lg ring-1 duration-100;
1152
+ }
1153
+
1154
+ .cn-popover-header {
1155
+ @apply gap-1 text-sm;
1156
+ }
1157
+
1158
+ .cn-popover-title {
1159
+ @apply text-base font-medium;
1160
+ }
1161
+
1162
+ .cn-popover-description {
1163
+ @apply text-muted-foreground;
1164
+ }
1165
+
1166
+ /* MARK: Progress */
1167
+ .cn-progress-track {
1168
+ @apply bg-muted h-2 rounded-2xl;
1169
+ }
1170
+
1171
+ .cn-progress-indicator {
1172
+ @apply bg-primary;
1173
+ }
1174
+
1175
+ .cn-progress-label {
1176
+ @apply text-sm font-medium;
1177
+ }
1178
+
1179
+ .cn-progress-value {
1180
+ @apply ml-auto text-sm text-muted-foreground tabular-nums;
1181
+ }
1182
+
1183
+ /* MARK: RadioGroup */
1184
+ .cn-radio-group {
1185
+ @apply grid gap-3;
1186
+ }
1187
+
1188
+ .cn-radio-group-item {
1189
+ @apply bg-input/90 data-checked:bg-primary data-checked:text-primary-foreground dark:data-checked:bg-primary border-transparent aria-invalid:border-destructive focus-visible:border-ring focus-visible:ring-ring/30 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 dark:aria-invalid:border-destructive/50 flex size-4 rounded-2xl focus-visible:ring-3 aria-invalid:ring-3 border group-has-[:focus-visible]/field-label:border-transparent group-has-[:focus-visible]/field-label:ring-0;
1190
+ }
1191
+
1192
+ .cn-radio-group-indicator {
1193
+ @apply flex size-4 items-center justify-center;
1194
+ }
1195
+
1196
+ .cn-radio-group-indicator-icon {
1197
+ @apply bg-primary-foreground absolute top-1/2 left-1/2 size-2 -translate-x-1/2 -translate-y-1/2 rounded-full dark:size-2.5;
1198
+ }
1199
+
1200
+ /* MARK: Resizable */
1201
+ .cn-resizable-handle-icon {
1202
+ @apply bg-border h-6 w-1 rounded-lg;
1203
+ }
1204
+
1205
+ /* MARK: Select */
1206
+ /* Placeholder AA hold on the tinted pill - same idiom as cn-input. */
1207
+ .cn-select-trigger {
1208
+ @apply bg-input/50 border-transparent data-placeholder:text-[oklch(from_var(--muted-foreground)_calc(l*0.85)_c_h)] dark:data-placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/30 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 gap-1.5 rounded-2xl border py-2 px-3 text-sm transition-[color,box-shadow] duration-200 focus-visible:ring-3 aria-invalid:ring-3 data-[size=default]:h-8 data-[size=sm]:h-7 *:data-[slot=select-value]:flex *:data-[slot=select-value]:gap-1.5 [&_svg:not([class*='size-'])]:size-4;
1209
+ }
1210
+
1211
+ .cn-select-trigger-icon {
1212
+ @apply text-muted-foreground size-4;
1213
+ }
1214
+
1215
+ .cn-select-content {
1216
+ @apply bg-popover text-popover-foreground data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/5 dark:ring-foreground/10 min-w-36 rounded-2xl shadow-lg ring-1 duration-100;
1217
+ }
1218
+
1219
+ .cn-select-group {
1220
+ @apply scroll-my-1.5 p-1;
1221
+ }
1222
+
1223
+ .cn-select-value {
1224
+ @apply flex flex-1 text-left;
1225
+ }
1226
+
1227
+ .cn-select-item-text {
1228
+ @apply flex flex-1 gap-2;
1229
+ }
1230
+
1231
+ .cn-select-scroll-up-button {
1232
+ @apply bg-popover z-10 flex cursor-default items-center justify-center py-1 [&_svg:not([class*='size-'])]:size-4;
1233
+ }
1234
+
1235
+ .cn-select-scroll-down-button {
1236
+ @apply bg-popover z-10 flex cursor-default items-center justify-center py-1 [&_svg:not([class*='size-'])]:size-4;
1237
+ }
1238
+
1239
+ .cn-select-viewport {
1240
+ @apply p-1 scroll-my-1;
1241
+ }
1242
+
1243
+ .cn-select-item {
1244
+ @apply focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground gap-2 min-h-7 rounded-xl py-1.5 pr-8 pl-2 text-sm [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2;
1245
+ }
1246
+
1247
+ .cn-select-label {
1248
+ @apply text-muted-foreground px-2 py-1 text-xs;
1249
+ }
1250
+
1251
+ .cn-select-separator {
1252
+ @apply -mx-1 my-1 h-px bg-border;
1253
+ }
1254
+
1255
+ .cn-select-item-indicator {
1256
+ @apply pointer-events-none absolute right-2 flex size-4 items-center justify-center;
1257
+ }
1258
+
1259
+ /* MARK: Sheet */
1260
+ /* w-full lives here so the sides' w-3/4 can beat it in-layer (split-side
1261
+ * rule) - a latent full-width regression the visual gate cannot see on a
1262
+ * closed dialog. */
1263
+ .cn-sheet-content {
1264
+ @apply m-0 w-full bg-popover text-popover-foreground text-sm bg-clip-padding shadow-xl transition duration-200 ease-in-out data-open:animate-in data-closed:animate-out backdrop:bg-black/10 supports-backdrop-filter:backdrop:backdrop-blur-xs;
1265
+ }
1266
+
1267
+ .cn-sheet-side-top {
1268
+ @apply bottom-auto mb-auto h-auto w-full max-w-none border-b data-open:slide-in-from-top data-closed:slide-out-to-top;
1269
+ }
1270
+
1271
+ .cn-sheet-side-right {
1272
+ @apply ml-auto h-full max-h-none w-3/4 border-l data-open:slide-in-from-right data-closed:slide-out-to-right sm:max-w-sm;
1273
+ }
1274
+
1275
+ .cn-sheet-side-bottom {
1276
+ @apply top-auto mt-auto h-auto w-full max-w-none border-t data-open:slide-in-from-bottom data-closed:slide-out-to-bottom;
1277
+ }
1278
+
1279
+ .cn-sheet-side-left {
1280
+ @apply mr-auto h-full max-h-none w-3/4 border-r data-open:slide-in-from-left data-closed:slide-out-to-left sm:max-w-sm;
1281
+ }
1282
+
1283
+ .cn-sheet-header {
1284
+ @apply gap-1.5 p-6;
1285
+ }
1286
+
1287
+ .cn-sheet-title {
1288
+ @apply text-foreground text-base font-medium;
1289
+ }
1290
+
1291
+ .cn-sheet-description {
1292
+ @apply text-sm text-muted-foreground;
1293
+ }
1294
+
1295
+ .cn-sheet-footer {
1296
+ @apply gap-2 p-6;
1297
+ }
1298
+
1299
+ .cn-sheet-close {
1300
+ @apply absolute top-4 right-4 bg-secondary;
1301
+ }
1302
+
1303
+ /* MARK: SensitiveInput */
1304
+ /* The masked MASK OVERLAY is the focusable reveal button (the
1305
+ * group would trip axe nested-interactive around the inert input) - the
1306
+ * bordered group wears the ring when the mask inside holds focus. */
1307
+ .cn-sensitive-input-group:has([data-slot=sensitive-input-mask]:focus-visible) {
1308
+ @apply outline-none border-ring ring-ring/30 ring-3;
1309
+ }
1310
+
1311
+ /* MARK: Sidebar */
1312
+ .cn-sidebar-mobile {
1313
+ @apply bg-sidebar p-0 text-sidebar-foreground shadow-xl transition duration-200 ease-in-out data-open:animate-in data-closed:animate-out backdrop:bg-black/10 supports-backdrop-filter:backdrop:backdrop-blur-xs;
1314
+ }
1315
+
1316
+ .cn-sidebar-mobile-left {
1317
+ @apply border-r data-open:slide-in-from-left data-closed:slide-out-to-left;
1318
+ }
1319
+
1320
+ .cn-sidebar-mobile-right {
1321
+ @apply border-l data-open:slide-in-from-right data-closed:slide-out-to-right;
1322
+ }
1323
+
1324
+ .cn-sidebar-inner {
1325
+ @apply bg-sidebar group-data-[variant=floating]:ring-sidebar-border group-data-[variant=floating]:rounded-2xl group-data-[variant=floating]:shadow-sm group-data-[variant=floating]:ring-1;
1326
+ }
1327
+
1328
+ .cn-sidebar-header {
1329
+ @apply gap-2 p-2 [--radius:var(--radius-xl)];
1330
+ }
1331
+
1332
+ .cn-sidebar-footer {
1333
+ @apply gap-2 p-2;
1334
+ }
1335
+
1336
+ .cn-sidebar-separator {
1337
+ @apply mx-2 bg-sidebar-border;
1338
+ }
1339
+
1340
+ .cn-sidebar-content {
1341
+ @apply gap-2 [--radius:var(--radius-xl)];
1342
+ }
1343
+
1344
+ .cn-sidebar-gap {
1345
+ @apply transition-[width] duration-200 ease-linear;
1346
+ }
1347
+
1348
+ .cn-sidebar-rail {
1349
+ @apply hover:after:bg-sidebar-border;
1350
+ }
1351
+
1352
+ .cn-sidebar-inset {
1353
+ @apply bg-background md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-2xl md:peer-data-[variant=inset]:shadow-sm md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ml-2;
1354
+ }
1355
+
1356
+ .cn-sidebar-group {
1357
+ @apply p-2;
1358
+ }
1359
+
1360
+ .cn-sidebar-group-label {
1361
+ @apply text-sidebar-foreground/70 ring-sidebar-ring h-8 rounded-xl px-3 text-xs font-medium transition-[margin,opacity] duration-200 ease-linear group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0 focus-visible:ring-3 [&>svg]:size-4;
1362
+ }
1363
+
1364
+ .cn-sidebar-group-content {
1365
+ @apply text-sm;
1366
+ }
1367
+
1368
+ .cn-sidebar-menu {
1369
+ @apply gap-0.5;
1370
+ }
1371
+
1372
+ .cn-sidebar-menu-button {
1373
+ @apply ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground active:bg-sidebar-accent active:text-sidebar-accent-foreground data-active:bg-sidebar-accent data-active:text-sidebar-accent-foreground data-open:hover:bg-sidebar-accent data-open:hover:text-sidebar-accent-foreground gap-2 rounded-xl px-3 has-[>svg:first-child]:pl-2.5 has-[>svg:last-child]:pr-2.5 py-2 text-left text-sm transition-[width,height,padding] duration-200 group-has-data-[sidebar=menu-action]/menu-item:pr-8 group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! focus-visible:ring-3 data-active:font-medium whitespace-nowrap [&_svg]:size-4;
1374
+ }
1375
+
1376
+ .cn-sidebar-input {
1377
+ @apply bg-input/50 h-8 w-full shadow-none;
1378
+ }
1379
+
1380
+ .cn-sidebar-group-action {
1381
+ @apply text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground absolute top-3.5 right-3 w-5 rounded-xl p-0 focus-visible:ring-3 [&>svg]:size-4;
1382
+ }
1383
+
1384
+ .cn-sidebar-menu-button-variant-default {
1385
+ @apply hover:bg-sidebar-accent hover:text-sidebar-accent-foreground;
1386
+ }
1387
+
1388
+ .cn-sidebar-menu-button-variant-outline {
1389
+ @apply bg-background hover:bg-sidebar-accent hover:text-sidebar-accent-foreground shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))];
1390
+ }
1391
+
1392
+ .cn-sidebar-menu-skeleton {
1393
+ @apply h-8 gap-2 rounded-xl px-2;
1394
+ }
1395
+
1396
+ .cn-sidebar-menu-skeleton-icon {
1397
+ @apply size-4 rounded-xl;
1398
+ }
1399
+
1400
+ .cn-sidebar-menu-skeleton-text {
1401
+ @apply h-4;
1402
+ }
1403
+
1404
+ .cn-sidebar-menu-button-size-default {
1405
+ @apply h-8 text-sm;
1406
+ }
1407
+
1408
+ .cn-sidebar-menu-button-size-sm {
1409
+ @apply h-7 text-xs;
1410
+ }
1411
+
1412
+ .cn-sidebar-menu-button-size-lg {
1413
+ @apply h-12 px-3 text-sm group-data-[collapsible=icon]:p-0!;
1414
+ }
1415
+
1416
+ .cn-sidebar-menu-action {
1417
+ @apply text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground peer-hover/menu-button:text-sidebar-accent-foreground w-5 rounded-xl p-0 peer-data-[size=default]/menu-button:top-1.5 peer-data-[size=lg]/menu-button:top-2.5 peer-data-[size=sm]/menu-button:top-1 focus-visible:ring-3 [&>svg]:size-4;
1418
+ }
1419
+
1420
+ .cn-sidebar-menu-badge {
1421
+ @apply text-sidebar-foreground peer-hover/menu-button:text-sidebar-accent-foreground peer-data-active/menu-button:text-sidebar-accent-foreground h-5 min-w-5 rounded-xl px-1 text-xs font-medium peer-data-[size=default]/menu-button:top-1.5 peer-data-[size=lg]/menu-button:top-2.5 peer-data-[size=sm]/menu-button:top-1;
1422
+ }
1423
+
1424
+ .cn-sidebar-menu-sub {
1425
+ @apply border-sidebar-border gap-1 border-l px-2.5 py-0.5 group-data-[collapsible=icon]:hidden;
1426
+ }
1427
+
1428
+ .cn-sidebar-menu-sub-button {
1429
+ @apply text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground active:bg-sidebar-accent active:text-sidebar-accent-foreground [&>svg]:text-sidebar-accent-foreground data-active:bg-sidebar-accent data-active:text-sidebar-accent-foreground h-7 gap-2 rounded-xl px-3 focus-visible:ring-3 data-[size=md]:text-sm data-[size=sm]:text-xs [&>svg]:size-4;
1430
+ }
1431
+
1432
+ /* MARK: Skeleton */
1433
+ .cn-skeleton {
1434
+ @apply bg-muted rounded-2xl;
1435
+ }
1436
+
1437
+ /* MARK: Slider */
1438
+ .cn-slider {
1439
+ @apply data-[orientation=vertical]:min-h-40;
1440
+ }
1441
+
1442
+ .cn-slider-track {
1443
+ @apply bg-input/90 rounded-2xl data-[orientation=horizontal]:h-1 data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-1;
1444
+ }
1445
+
1446
+ .cn-slider-range {
1447
+ @apply bg-primary;
1448
+ }
1449
+
1450
+ .cn-slider-thumb {
1451
+ @apply ring-black/10 not-dark:bg-clip-padding ring-1 size-4 rounded-2xl bg-white shadow-md transition-[color,box-shadow] duration-200 hover:ring-4 hover:ring-ring/30 focus-visible:ring-4 focus-visible:ring-ring/30 focus-visible:outline-hidden;
1452
+ }
1453
+
1454
+ /* MARK: Switch */
1455
+ .cn-switch {
1456
+ @apply data-checked:bg-primary data-unchecked:bg-input/90 data-checked:border-primary border-2 data-unchecked:border-transparent focus-visible:border-ring focus-visible:ring-ring/30 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 shrink-0 rounded-2xl focus-visible:ring-3 aria-invalid:ring-3 data-[size=default]:h-5 data-[size=default]:w-8 data-[size=sm]:h-4 data-[size=sm]:w-6 group-has-[:focus-visible]/field-label:data-checked:border-primary group-has-[:focus-visible]/field-label:data-unchecked:border-transparent group-has-[:focus-visible]/field-label:ring-0;
1457
+ }
1458
+
1459
+ .cn-switch-thumb {
1460
+ @apply rounded-full bg-background group-data-[size=default]/switch:size-4 group-data-[size=sm]/switch:size-3 data-checked:translate-x-[calc(100%-4px)] data-unchecked:translate-x-0 rtl:data-checked:-translate-x-[calc(100%-4px)] dark:data-checked:bg-primary-foreground dark:data-unchecked:bg-foreground shadow-sm;
1461
+ }
1462
+
1463
+ /* MARK: Table */
1464
+ .cn-table {
1465
+ @apply w-full caption-bottom text-sm;
1466
+ }
1467
+
1468
+ .cn-table-container {
1469
+ @apply relative w-full overflow-x-auto;
1470
+ }
1471
+
1472
+ .cn-table-header {
1473
+ @apply [&_tr]:border-b;
1474
+ }
1475
+
1476
+ .cn-table-body {
1477
+ @apply [&_tr:last-child]:border-0;
1478
+ }
1479
+
1480
+ .cn-table-footer {
1481
+ @apply border-t bg-muted/50 font-medium [&>tr]:last:border-b-0;
1482
+ }
1483
+
1484
+ .cn-table-row {
1485
+ @apply border-b transition-colors hover:bg-muted/50 has-aria-expanded:bg-muted/50 data-selected:bg-muted;
1486
+ }
1487
+
1488
+ .cn-table-head {
1489
+ @apply h-10 px-2 text-left align-middle font-medium whitespace-nowrap text-foreground [&:has([role=checkbox])]:pr-0;
1490
+ }
1491
+
1492
+ .cn-table-cell {
1493
+ @apply p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0;
1494
+ }
1495
+
1496
+ .cn-table-caption {
1497
+ @apply mt-4 text-sm text-muted-foreground;
1498
+ }
1499
+
1500
+ /* MARK: Tabs */
1501
+ .cn-tabs {
1502
+ @apply gap-2;
1503
+ }
1504
+
1505
+ .cn-tabs-list {
1506
+ @apply rounded-2xl p-[3px] group-data-horizontal/tabs:h-8 data-[variant=line]:rounded-none group-data-vertical/tabs:p-1;
1507
+ }
1508
+
1509
+ .cn-tabs-list-variant-default {
1510
+ @apply bg-muted;
1511
+ }
1512
+
1513
+ .cn-tabs-list-variant-line {
1514
+ @apply gap-1 bg-transparent;
1515
+ }
1516
+
1517
+ /* The whole text-color cluster lives here (split-side rule): the base
1518
+ * dims (text-foreground/60, dark:text-muted-foreground) must lose to the
1519
+ * data-active colors, which they only can in-layer. */
1520
+ .cn-tabs-trigger {
1521
+ @apply gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium text-foreground/60 hover:text-foreground has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 dark:text-muted-foreground dark:hover:text-foreground group-data-[variant=line]/tabs-list:data-active:shadow-none [&_svg:not([class*='size-'])]:size-4 group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-active:bg-transparent dark:group-data-[variant=line]/tabs-list:data-active:border-transparent dark:group-data-[variant=line]/tabs-list:data-active:bg-transparent data-active:bg-background data-active:text-foreground dark:data-active:border-input dark:data-active:bg-input/30 dark:data-active:text-foreground after:bg-foreground group-data-horizontal/tabs:after:inset-x-0 group-data-horizontal/tabs:after:bottom-[-5px] group-data-horizontal/tabs:after:h-0.5 group-data-vertical/tabs:after:inset-y-0 group-data-vertical/tabs:after:-right-1 group-data-vertical/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-active:after:opacity-100;
1522
+ }
1523
+
1524
+ .cn-tabs-content {
1525
+ @apply text-sm;
1526
+ }
1527
+
1528
+ /* MARK: Textarea */
1529
+ /* Placeholder + invalid-text AA holds - same as cn-input. */
1530
+ .cn-textarea {
1531
+ @apply bg-input/50 border-transparent placeholder:text-[oklch(from_var(--muted-foreground)_calc(l*0.85)_c_h)] dark:placeholder:text-muted-foreground aria-invalid:text-[oklch(from_var(--destructive)_calc(l*0.85)_c_h)] dark:aria-invalid:text-destructive focus-visible:border-ring focus-visible:ring-ring/30 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 resize-none rounded-2xl border px-2.5 py-2 text-base transition-[color,box-shadow] duration-200 focus-visible:ring-3 aria-invalid:ring-3 md:text-sm;
1532
+ }
1533
+
1534
+ /* MARK: Toast */
1535
+ .cn-toast {
1536
+ @apply gap-3 rounded-2xl border bg-popover p-4 text-popover-foreground shadow-lg data-open:animate-in data-open:fade-in-0 data-open:slide-in-from-bottom-2 group-data-[position^=top]/toaster:data-open:slide-in-from-top-2 data-closed:animate-out data-closed:fade-out-80 data-closed:slide-out-to-bottom-2 group-data-[position^=top]/toaster:data-closed:slide-out-to-top-2;
1537
+ }
1538
+
1539
+ .cn-toast-variant-success {
1540
+ @apply [&_[data-slot=toast-icon]]:text-primary;
1541
+ }
1542
+
1543
+ .cn-toast-variant-info {
1544
+ @apply [&_[data-slot=toast-icon]]:text-muted-foreground;
1545
+ }
1546
+
1547
+ .cn-toast-variant-warning {
1548
+ @apply [&_[data-slot=toast-icon]]:text-primary;
1549
+ }
1550
+
1551
+ .cn-toast-variant-destructive {
1552
+ @apply text-destructive [&_[data-slot=toast-icon]]:text-destructive;
1553
+ }
1554
+
1555
+ .cn-toast-icon {
1556
+ @apply mt-0.5 size-4 [&_svg]:size-4;
1557
+ }
1558
+
1559
+ .cn-toast-body {
1560
+ @apply gap-1;
1561
+ }
1562
+
1563
+ .cn-toast-title {
1564
+ @apply text-sm font-medium;
1565
+ }
1566
+
1567
+ .cn-toast-description {
1568
+ @apply text-sm text-muted-foreground;
1569
+ }
1570
+
1571
+ /* MARK: Toaster */
1572
+ /* max-w-full lives here WITH its sm: cap (the split-side rule extends to
1573
+ * responsive pairs: a bare utility would beat the themed breakpoint
1574
+ * override from the utilities layer at every width). */
1575
+ .cn-toaster {
1576
+ @apply max-w-full gap-2 p-4 sm:max-w-[420px];
1577
+ }
1578
+
1579
+ /* MARK: Toggle */
1580
+ /* hover:bg-muted lives HERE (not inline, where upstream keeps it): the
1581
+ * outline variant's hover:bg-accent must beat it, and it only can when
1582
+ * both sides share the base layer (in-layer order = the merger's old
1583
+ * last-wins). An inline utility would win the cascade unconditionally. */
1584
+ .cn-toggle {
1585
+ @apply hover:text-foreground aria-pressed:bg-muted focus-visible:border-ring focus-visible:ring-ring/30 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive gap-1 rounded-2xl text-sm font-medium transition-colors [&_svg:not([class*='size-'])]:size-4;
1586
+ }
1587
+
1588
+ .cn-toggle-variant-default {
1589
+ @apply bg-transparent;
1590
+ }
1591
+
1592
+ .cn-toggle-variant-outline {
1593
+ @apply border-input hover:bg-muted border bg-transparent;
1594
+ }
1595
+
1596
+ .cn-toggle-size-default {
1597
+ @apply h-8 min-w-8 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2 has-[>svg:first-child]:pl-2 has-[>svg:last-child]:pr-2;
1598
+ }
1599
+
1600
+ .cn-toggle-size-sm {
1601
+ @apply h-7 min-w-7 px-2.5 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 has-[>svg:first-child]:pl-1.5 has-[>svg:last-child]:pr-1.5;
1602
+ }
1603
+
1604
+ .cn-toggle-size-lg {
1605
+ @apply h-9 min-w-9 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2 has-[>svg:first-child]:pl-2 has-[>svg:last-child]:pr-2;
1606
+ }
1607
+
1608
+ /* MARK: ToggleGroup */
1609
+ .cn-toggle-group {
1610
+ @apply data-[spacing=0]:data-[variant=outline]:rounded-2xl;
1611
+ }
1612
+
1613
+ /* Segmented edge radii live theme-side (side-move): each theme
1614
+ * rounds spacing=0 segments in its own radius language. */
1615
+ .cn-toggle-group-item {
1616
+ @apply data-pressed:bg-muted group-data-[spacing=0]/toggle-group:rounded-none group-data-[spacing=0]/toggle-group:px-2 group-data-[spacing=0]/toggle-group:shadow-none group-data-horizontal/toggle-group:data-[spacing=0]:first:rounded-l-2xl group-data-vertical/toggle-group:data-[spacing=0]:first:rounded-t-2xl group-data-horizontal/toggle-group:data-[spacing=0]:last:rounded-r-2xl group-data-vertical/toggle-group:data-[spacing=0]:last:rounded-b-2xl group-data-[spacing=0]/toggle-group:has-data-[icon=inline-end]:pr-1.5 group-data-[spacing=0]/toggle-group:has-data-[icon=inline-start]:pl-1.5;
1617
+ }
1618
+
1619
+ /* MARK: Tooltip */
1620
+ .cn-tooltip-content {
1621
+ @apply data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 inline-flex items-center gap-1.5 rounded-xl px-3 py-1.5 text-xs has-data-[slot=kbd]:pr-1.5 **:data-[slot=kbd]:relative **:data-[slot=kbd]:isolate **:data-[slot=kbd]:z-50 **:data-[slot=kbd]:rounded-lg;
1622
+ }
1623
+
1624
+ .cn-tooltip-arrow {
1625
+ @apply size-2.5 rounded-[2px] in-data-[side=left]:translate-x-[-1.5px] in-data-[side=right]:translate-x-[1.5px];
1626
+ }
1627
+
1628
+ /* MARK: Consumer utilities
1629
+ * Standalone cn-* classes templates and consumers apply directly (they
1630
+ * ride the css:verify_theme allowlist - no dictionary emits cn-rtl-flip).
1631
+ * cn-font-heading: upstream globals (@apply font-heading); poetry inlines
1632
+ * the var with a sans fallback so it is a no-op until a theme defines
1633
+ * --font-heading. cn-rtl-flip: upstream ships the NAME with no rule
1634
+ * anywhere (dead in source); poetry authors the intended RTL mirror. */
1635
+ .cn-font-heading {
1636
+ font-family: var(--font-heading, var(--font-sans));
1637
+ }
1638
+
1639
+ .cn-rtl-flip {
1640
+ @apply rtl:-scale-x-100;
1641
+ }
1642
+
1643
+ /* MARK: Cross-component overrides
1644
+ * Rules that restyle ANOTHER component's cn surface must come after every
1645
+ * rule they override - in-layer order is what lets an override win, so
1646
+ * alphabetical placement would silently lose (cn-input-group-textarea vs
1647
+ * the later cn-textarea). Keep every such rule in this closing section. */
1648
+ .cn-input-group-input {
1649
+ @apply rounded-none border-0 bg-transparent shadow-none ring-0 focus-visible:ring-0 aria-invalid:ring-0 dark:bg-transparent;
1650
+ }
1651
+
1652
+ .cn-input-group-textarea {
1653
+ @apply rounded-none border-0 bg-transparent py-2 shadow-none ring-0 focus-visible:ring-0 aria-invalid:ring-0 dark:bg-transparent;
1654
+ }
1655
+
1656
+ .cn-input-group-button {
1657
+ @apply gap-2 rounded-2xl text-sm;
1658
+ }
1659
+
1660
+ .cn-input-group-button-size-xs {
1661
+ @apply h-6 gap-1 rounded-xl px-1.5 [&>svg:not([class*='size-'])]:size-3.5;
1662
+ }
1663
+
1664
+ /* poetry-authored: upstream themes this hook only in lyra/mira (gap-1
1665
+ both); the class must compile in every theme (css:verify_compiled). */
1666
+ .cn-input-group-button-size-sm {
1667
+ @apply gap-1;
1668
+ }
1669
+
1670
+ .cn-input-group-button-size-icon-xs {
1671
+ @apply size-6 rounded-xl p-0 has-[>svg]:p-0;
1672
+ }
1673
+
1674
+ .cn-input-group-button-size-icon-sm {
1675
+ @apply size-8 p-0 has-[>svg]:p-0;
1676
+ }
1677
+
1678
+ /* CommandDialog re-tunes the Dialog panel (p-0 must beat cn-dialog-content's p-6). */
1679
+ .cn-command-dialog {
1680
+ @apply rounded-3xl! p-0;
1681
+ }
1682
+
1683
+ /* MARK: Stat */
1684
+ .cn-stat-delta-positive {
1685
+ @apply text-[oklch(from_var(--success)_calc(l*0.85)_c_h)] dark:text-success;
1686
+ }
1687
+
1688
+ /* MARK: Questionnaire */
1689
+ .cn-questionnaire {
1690
+ @apply gap-6;
1691
+ }
1692
+
1693
+ .cn-questionnaire-progress {
1694
+ @apply text-xs;
1695
+ }
1696
+
1697
+ .cn-questionnaire-item {
1698
+ @apply flex flex-col gap-5;
1699
+ }
1700
+
1701
+ .cn-questionnaire-title {
1702
+ @apply text-base font-semibold [&:not(:has(~[data-slot=questionnaire-description]))]:mb-5;
1703
+ }
1704
+
1705
+ .cn-questionnaire-description {
1706
+ @apply text-sm;
1707
+ }
1708
+
1709
+ .cn-questionnaire-choices {
1710
+ @apply gap-3;
1711
+ }
1712
+
1713
+ .cn-questionnaire-choice {
1714
+ @apply border-input hover:bg-input/40 data-checked:border-primary/40 data-checked:bg-primary/10 in-data-invalid:border-destructive has-[>input:focus-visible]:border-ring has-[>input:focus-visible]:ring-ring/50 gap-3 rounded-2xl border px-4 py-3 text-sm has-[>input:focus-visible]:ring-3;
1715
+ }
1716
+
1717
+ .cn-questionnaire-choice-indicator {
1718
+ @apply bg-input/90 group-data-checked/questionnaire-choice:bg-primary dark:group-data-checked/questionnaire-choice:bg-primary group-data-checked/questionnaire-choice:text-primary-foreground group-data-checked/questionnaire-choice:border-primary size-4 translate-y-[--spacing(0.45)] group-has-data-[slot=questionnaire-choice-description]/questionnaire-choice:translate-y-0.5 rounded-[5px] border-transparent;
1719
+ }
1720
+
1721
+ .cn-questionnaire-choice-indicator-dot {
1722
+ @apply bg-primary-foreground size-2 dark:size-2.5;
1723
+ }
1724
+
1725
+ .cn-questionnaire-choice-indicator-check {
1726
+ @apply size-3.5;
1727
+ }
1728
+
1729
+ .cn-questionnaire-choice-content {
1730
+ @apply gap-1;
1731
+ }
1732
+
1733
+ .cn-questionnaire-choice-description {
1734
+ @apply text-muted-foreground;
1735
+ }
1736
+
1737
+ .cn-questionnaire-shortcut {
1738
+ @apply border-primary/10 bg-background/80 text-muted-foreground size-5 translate-y-[--spacing(0.45)] group-has-data-[slot=questionnaire-choice-description]/questionnaire-choice:translate-y-0.5 items-center justify-center rounded-full border font-mono text-[0.625rem] font-medium leading-none;
1739
+ }
1740
+
1741
+ .cn-questionnaire-input-wrapper {
1742
+ @apply w-full;
1743
+ }
1744
+
1745
+ .cn-questionnaire-input {
1746
+ @apply bg-input/50 border-transparent focus-visible:border-ring focus-visible:ring-ring/30 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 h-8 rounded-2xl border px-2.5 py-1 text-base duration-200 focus-visible:ring-3 aria-invalid:ring-3 md:text-sm;
1747
+ }
1748
+
1749
+ .cn-questionnaire-error {
1750
+ @apply mt-2 text-sm;
1751
+ }
1752
+
1753
+ .cn-questionnaire-actions {
1754
+ @apply gap-2 sm:min-h-8;
1755
+ }
1756
+
1757
+ /* MARK: WebMCP agent focus (declarative tools) - the browser marks the
1758
+ form an agent is filling and its submit; :where() keeps the rule
1759
+ forgiving in browsers that lack the pseudo-classes. */
1760
+ :where(form:tool-form-active) {
1761
+ @apply rounded-lg outline-2 outline-dashed outline-offset-4 outline-ring/60;
1762
+ }
1763
+
1764
+ :where(:tool-submit-active) {
1765
+ @apply border-ring ring-3 ring-ring/50;
1766
+ }
1767
+
1768
+ /* MARK: Menu translucent (shared, LAST - wins the content bg cascade) */
1769
+ .cn-menu-translucent {
1770
+ @apply animate-none! relative bg-popover/70 before:pointer-events-none before:absolute before:inset-0 before:-z-1 before:rounded-[inherit] before:backdrop-blur-2xl before:backdrop-saturate-150 **:data-[slot$=-item]:focus:bg-foreground/10 **:data-[slot$=-item]:data-highlighted:bg-foreground/10 **:data-[slot$=-separator]:bg-foreground/5 **:data-[slot$=-trigger]:focus:bg-foreground/10 **:data-[slot$=-trigger]:aria-expanded:bg-foreground/10! **:data-[variant=destructive]:focus:bg-foreground/10! **:data-[variant=destructive]:text-accent-foreground! **:data-[variant=destructive]:**:text-accent-foreground!;
1771
+ }