optikos 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (527) hide show
  1. package/CHANGELOG.md +146 -0
  2. package/LICENSE +21 -0
  3. package/README.md +213 -2
  4. package/THIRD_PARTY_NOTICES.md +83 -0
  5. package/dist/bind.js +2 -0
  6. package/dist/bind.js.map +7 -0
  7. package/dist/chunk-23XLG2EM.js +2 -0
  8. package/dist/chunk-23XLG2EM.js.map +7 -0
  9. package/dist/chunk-27UZFEXD.js +2 -0
  10. package/dist/chunk-27UZFEXD.js.map +7 -0
  11. package/dist/chunk-2UPUC4RK.js +2 -0
  12. package/dist/chunk-2UPUC4RK.js.map +7 -0
  13. package/dist/chunk-2ZRNGG2N.js +2 -0
  14. package/dist/chunk-2ZRNGG2N.js.map +7 -0
  15. package/dist/chunk-2ZUZ5HDL.js +2 -0
  16. package/dist/chunk-2ZUZ5HDL.js.map +7 -0
  17. package/dist/chunk-3DBEZGOY.js +2 -0
  18. package/dist/chunk-3DBEZGOY.js.map +7 -0
  19. package/dist/chunk-3S24ZRPK.js +2 -0
  20. package/dist/chunk-3S24ZRPK.js.map +7 -0
  21. package/dist/chunk-3TAW4AKH.js +2 -0
  22. package/dist/chunk-3TAW4AKH.js.map +7 -0
  23. package/dist/chunk-4AA4FQEM.js +2 -0
  24. package/dist/chunk-4AA4FQEM.js.map +7 -0
  25. package/dist/chunk-4C666HHU.js +2 -0
  26. package/dist/chunk-4C666HHU.js.map +7 -0
  27. package/dist/chunk-4EZJ5FKJ.js +2 -0
  28. package/dist/chunk-4EZJ5FKJ.js.map +7 -0
  29. package/dist/chunk-4LZZ244E.js +2 -0
  30. package/dist/chunk-4LZZ244E.js.map +7 -0
  31. package/dist/chunk-4SYIIX5A.js +2 -0
  32. package/dist/chunk-4SYIIX5A.js.map +7 -0
  33. package/dist/chunk-5BC72727.js +2 -0
  34. package/dist/chunk-5BC72727.js.map +7 -0
  35. package/dist/chunk-5DJTP53N.js +2 -0
  36. package/dist/chunk-5DJTP53N.js.map +7 -0
  37. package/dist/chunk-5JEXM5S7.js +2 -0
  38. package/dist/chunk-5JEXM5S7.js.map +7 -0
  39. package/dist/chunk-5Q76ACVI.js +2 -0
  40. package/dist/chunk-5Q76ACVI.js.map +7 -0
  41. package/dist/chunk-5QUY72FX.js +2 -0
  42. package/dist/chunk-5QUY72FX.js.map +7 -0
  43. package/dist/chunk-5YS7OD5E.js +2 -0
  44. package/dist/chunk-5YS7OD5E.js.map +7 -0
  45. package/dist/chunk-676AKAGF.js +2 -0
  46. package/dist/chunk-676AKAGF.js.map +7 -0
  47. package/dist/chunk-6NCXO5ZP.js +2 -0
  48. package/dist/chunk-6NCXO5ZP.js.map +7 -0
  49. package/dist/chunk-6VBK2I5B.js +2 -0
  50. package/dist/chunk-6VBK2I5B.js.map +7 -0
  51. package/dist/chunk-7KMIFXHZ.js +2 -0
  52. package/dist/chunk-7KMIFXHZ.js.map +7 -0
  53. package/dist/chunk-A2NKDOYN.js +2 -0
  54. package/dist/chunk-A2NKDOYN.js.map +7 -0
  55. package/dist/chunk-ATFJ7PNA.js +2 -0
  56. package/dist/chunk-ATFJ7PNA.js.map +7 -0
  57. package/dist/chunk-BXYWVRKJ.js +2 -0
  58. package/dist/chunk-BXYWVRKJ.js.map +7 -0
  59. package/dist/chunk-CKXS375P.js +2 -0
  60. package/dist/chunk-CKXS375P.js.map +7 -0
  61. package/dist/chunk-CUN5QO4T.js +2 -0
  62. package/dist/chunk-CUN5QO4T.js.map +7 -0
  63. package/dist/chunk-DBMWS3O5.js +2 -0
  64. package/dist/chunk-DBMWS3O5.js.map +7 -0
  65. package/dist/chunk-E4VNLYO2.js +2 -0
  66. package/dist/chunk-E4VNLYO2.js.map +7 -0
  67. package/dist/chunk-EDUMAMK4.js +2 -0
  68. package/dist/chunk-EDUMAMK4.js.map +7 -0
  69. package/dist/chunk-ELYARUCN.js +2 -0
  70. package/dist/chunk-ELYARUCN.js.map +7 -0
  71. package/dist/chunk-EV73ADN2.js +2 -0
  72. package/dist/chunk-EV73ADN2.js.map +7 -0
  73. package/dist/chunk-FEHGU6EP.js +3 -0
  74. package/dist/chunk-FEHGU6EP.js.map +7 -0
  75. package/dist/chunk-FHM5NUS4.js +3 -0
  76. package/dist/chunk-FHM5NUS4.js.map +7 -0
  77. package/dist/chunk-G2DAD3MQ.js +2 -0
  78. package/dist/chunk-G2DAD3MQ.js.map +7 -0
  79. package/dist/chunk-G2KUK6AT.js +2 -0
  80. package/dist/chunk-G2KUK6AT.js.map +7 -0
  81. package/dist/chunk-GBPLNXMP.js +2 -0
  82. package/dist/chunk-GBPLNXMP.js.map +7 -0
  83. package/dist/chunk-GNU4VOOE.js +2 -0
  84. package/dist/chunk-GNU4VOOE.js.map +7 -0
  85. package/dist/chunk-GZ7X34QP.js +2 -0
  86. package/dist/chunk-GZ7X34QP.js.map +7 -0
  87. package/dist/chunk-HOF4JGMQ.js +2 -0
  88. package/dist/chunk-HOF4JGMQ.js.map +7 -0
  89. package/dist/chunk-HXDTGP2K.js +2 -0
  90. package/dist/chunk-HXDTGP2K.js.map +7 -0
  91. package/dist/chunk-I4SP6JTU.js +2 -0
  92. package/dist/chunk-I4SP6JTU.js.map +7 -0
  93. package/dist/chunk-IHE2MQ3W.js +2 -0
  94. package/dist/chunk-IHE2MQ3W.js.map +7 -0
  95. package/dist/chunk-II6ITOA6.js +2 -0
  96. package/dist/chunk-II6ITOA6.js.map +7 -0
  97. package/dist/chunk-JBLRAM7Z.js +2 -0
  98. package/dist/chunk-JBLRAM7Z.js.map +7 -0
  99. package/dist/chunk-JI265XFO.js +2 -0
  100. package/dist/chunk-JI265XFO.js.map +7 -0
  101. package/dist/chunk-JK74QK3M.js +2 -0
  102. package/dist/chunk-JK74QK3M.js.map +7 -0
  103. package/dist/chunk-JOFQJGZK.js +2 -0
  104. package/dist/chunk-JOFQJGZK.js.map +7 -0
  105. package/dist/chunk-KCEUD232.js +2 -0
  106. package/dist/chunk-KCEUD232.js.map +7 -0
  107. package/dist/chunk-KLLAY2IM.js +2 -0
  108. package/dist/chunk-KLLAY2IM.js.map +7 -0
  109. package/dist/chunk-LBJSMXLV.js +2 -0
  110. package/dist/chunk-LBJSMXLV.js.map +7 -0
  111. package/dist/chunk-LQRFNQ2N.js +2 -0
  112. package/dist/chunk-LQRFNQ2N.js.map +7 -0
  113. package/dist/chunk-LW2WRUVL.js +2 -0
  114. package/dist/chunk-LW2WRUVL.js.map +7 -0
  115. package/dist/chunk-M242VYZA.js +2 -0
  116. package/dist/chunk-M242VYZA.js.map +7 -0
  117. package/dist/chunk-MB3MU6HR.js +2 -0
  118. package/dist/chunk-MB3MU6HR.js.map +7 -0
  119. package/dist/chunk-MW3RWBZ7.js +2 -0
  120. package/dist/chunk-MW3RWBZ7.js.map +7 -0
  121. package/dist/chunk-NXSTUFS7.js +2 -0
  122. package/dist/chunk-NXSTUFS7.js.map +7 -0
  123. package/dist/chunk-OEAXCCVM.js +2 -0
  124. package/dist/chunk-OEAXCCVM.js.map +7 -0
  125. package/dist/chunk-OGRFQTXA.js +2 -0
  126. package/dist/chunk-OGRFQTXA.js.map +7 -0
  127. package/dist/chunk-OWEQT2HN.js +2 -0
  128. package/dist/chunk-OWEQT2HN.js.map +7 -0
  129. package/dist/chunk-PZSHOSOS.js +2 -0
  130. package/dist/chunk-PZSHOSOS.js.map +7 -0
  131. package/dist/chunk-REW4LR46.js +2 -0
  132. package/dist/chunk-REW4LR46.js.map +7 -0
  133. package/dist/chunk-RNN55473.js +2 -0
  134. package/dist/chunk-RNN55473.js.map +7 -0
  135. package/dist/chunk-SA53QUBF.js +2 -0
  136. package/dist/chunk-SA53QUBF.js.map +7 -0
  137. package/dist/chunk-TIPK3SCJ.js +2 -0
  138. package/dist/chunk-TIPK3SCJ.js.map +7 -0
  139. package/dist/chunk-TOLTUOZS.js +2 -0
  140. package/dist/chunk-TOLTUOZS.js.map +7 -0
  141. package/dist/chunk-TZOQWCVH.js +2 -0
  142. package/dist/chunk-TZOQWCVH.js.map +7 -0
  143. package/dist/chunk-VF7BGP6L.js +2 -0
  144. package/dist/chunk-VF7BGP6L.js.map +7 -0
  145. package/dist/chunk-VU3GIDZ3.js +2 -0
  146. package/dist/chunk-VU3GIDZ3.js.map +7 -0
  147. package/dist/chunk-VV7CFMPZ.js +2 -0
  148. package/dist/chunk-VV7CFMPZ.js.map +7 -0
  149. package/dist/chunk-W3H7GTJY.js +2 -0
  150. package/dist/chunk-W3H7GTJY.js.map +7 -0
  151. package/dist/chunk-X2ASKUFD.js +2 -0
  152. package/dist/chunk-X2ASKUFD.js.map +7 -0
  153. package/dist/chunk-X6AULZI4.js +1 -0
  154. package/dist/chunk-X6AULZI4.js.map +7 -0
  155. package/dist/chunk-XHOBNSBO.js +2 -0
  156. package/dist/chunk-XHOBNSBO.js.map +7 -0
  157. package/dist/chunk-XX2MVWFS.js +4 -0
  158. package/dist/chunk-XX2MVWFS.js.map +7 -0
  159. package/dist/chunk-XYZ6VZ5T.js +2 -0
  160. package/dist/chunk-XYZ6VZ5T.js.map +7 -0
  161. package/dist/chunk-YBAYEU25.js +2 -0
  162. package/dist/chunk-YBAYEU25.js.map +7 -0
  163. package/dist/chunk-YHEMA56R.js +2 -0
  164. package/dist/chunk-YHEMA56R.js.map +7 -0
  165. package/dist/chunk-Z2JBUHKA.js +2 -0
  166. package/dist/chunk-Z2JBUHKA.js.map +7 -0
  167. package/dist/chunk-Z2Z52GFT.js +2 -0
  168. package/dist/chunk-Z2Z52GFT.js.map +7 -0
  169. package/dist/chunk-ZPPELYNJ.js +2 -0
  170. package/dist/chunk-ZPPELYNJ.js.map +7 -0
  171. package/dist/chunk-ZVK4L5GK.js +2 -0
  172. package/dist/chunk-ZVK4L5GK.js.map +7 -0
  173. package/dist/chunk-ZWNQREWS.js +2 -0
  174. package/dist/chunk-ZWNQREWS.js.map +7 -0
  175. package/dist/components/badge.js +2 -0
  176. package/dist/components/badge.js.map +7 -0
  177. package/dist/components/breadcrumb.js +2 -0
  178. package/dist/components/breadcrumb.js.map +7 -0
  179. package/dist/components/button.js +2 -0
  180. package/dist/components/button.js.map +7 -0
  181. package/dist/components/calendar.js +2 -0
  182. package/dist/components/calendar.js.map +7 -0
  183. package/dist/components/cellediting.js +2 -0
  184. package/dist/components/cellediting.js.map +7 -0
  185. package/dist/components/chat.js +2 -0
  186. package/dist/components/chat.js.map +7 -0
  187. package/dist/components/checkbox.js +2 -0
  188. package/dist/components/checkbox.js.map +7 -0
  189. package/dist/components/checkboxgroup.js +2 -0
  190. package/dist/components/checkboxgroup.js.map +7 -0
  191. package/dist/components/chip.js +2 -0
  192. package/dist/components/chip.js.map +7 -0
  193. package/dist/components/codeviewer.js +2 -0
  194. package/dist/components/codeviewer.js.map +7 -0
  195. package/dist/components/combobox.js +2 -0
  196. package/dist/components/combobox.js.map +7 -0
  197. package/dist/components/commandpalette.js +2 -0
  198. package/dist/components/commandpalette.js.map +7 -0
  199. package/dist/components/container.js +2 -0
  200. package/dist/components/container.js.map +7 -0
  201. package/dist/components/dataview.js +2 -0
  202. package/dist/components/dataview.js.map +7 -0
  203. package/dist/components/datefield.js +2 -0
  204. package/dist/components/datefield.js.map +7 -0
  205. package/dist/components/daterangefield.js +2 -0
  206. package/dist/components/daterangefield.js.map +7 -0
  207. package/dist/components/dial.js +2 -0
  208. package/dist/components/dial.js.map +7 -0
  209. package/dist/components/dropdown.js +2 -0
  210. package/dist/components/dropdown.js.map +7 -0
  211. package/dist/components/fieldgroup.js +2 -0
  212. package/dist/components/fieldgroup.js.map +7 -0
  213. package/dist/components/fieldlist.js +2 -0
  214. package/dist/components/fieldlist.js.map +7 -0
  215. package/dist/components/fieldset.js +2 -0
  216. package/dist/components/fieldset.js.map +7 -0
  217. package/dist/components/filterbuilder.js +2 -0
  218. package/dist/components/filterbuilder.js.map +7 -0
  219. package/dist/components/form.js +2 -0
  220. package/dist/components/form.js.map +7 -0
  221. package/dist/components/formactions.js +2 -0
  222. package/dist/components/formactions.js.map +7 -0
  223. package/dist/components/formerrors.js +2 -0
  224. package/dist/components/formerrors.js.map +7 -0
  225. package/dist/components/formsection.js +2 -0
  226. package/dist/components/formsection.js.map +7 -0
  227. package/dist/components/grid.js +2 -0
  228. package/dist/components/grid.js.map +7 -0
  229. package/dist/components/icon.js +2 -0
  230. package/dist/components/icon.js.map +7 -0
  231. package/dist/components/inputgroup.js +2 -0
  232. package/dist/components/inputgroup.js.map +7 -0
  233. package/dist/components/label.js +2 -0
  234. package/dist/components/label.js.map +7 -0
  235. package/dist/components/listbox.js +2 -0
  236. package/dist/components/listbox.js.map +7 -0
  237. package/dist/components/lookupfield.js +2 -0
  238. package/dist/components/lookupfield.js.map +7 -0
  239. package/dist/components/menu.js +2 -0
  240. package/dist/components/menu.js.map +7 -0
  241. package/dist/components/messagebox.js +2 -0
  242. package/dist/components/messagebox.js.map +7 -0
  243. package/dist/components/navmenu.js +2 -0
  244. package/dist/components/navmenu.js.map +7 -0
  245. package/dist/components/numberfield.js +2 -0
  246. package/dist/components/numberfield.js.map +7 -0
  247. package/dist/components/pagination.js +2 -0
  248. package/dist/components/pagination.js.map +7 -0
  249. package/dist/components/panel.js +2 -0
  250. package/dist/components/panel.js.map +7 -0
  251. package/dist/components/pickerfield.js +2 -0
  252. package/dist/components/pickerfield.js.map +7 -0
  253. package/dist/components/radiogroup.js +2 -0
  254. package/dist/components/radiogroup.js.map +7 -0
  255. package/dist/components/searchgrid.js +2 -0
  256. package/dist/components/searchgrid.js.map +7 -0
  257. package/dist/components/secretfield.js +2 -0
  258. package/dist/components/secretfield.js.map +7 -0
  259. package/dist/components/select.js +2 -0
  260. package/dist/components/select.js.map +7 -0
  261. package/dist/components/slider.js +2 -0
  262. package/dist/components/slider.js.map +7 -0
  263. package/dist/components/spacer.js +2 -0
  264. package/dist/components/spacer.js.map +7 -0
  265. package/dist/components/spinner.js +2 -0
  266. package/dist/components/spinner.js.map +7 -0
  267. package/dist/components/stepform.js +2 -0
  268. package/dist/components/stepform.js.map +7 -0
  269. package/dist/components/stepper.js +2 -0
  270. package/dist/components/stepper.js.map +7 -0
  271. package/dist/components/suggestfield.js +2 -0
  272. package/dist/components/suggestfield.js.map +7 -0
  273. package/dist/components/table.js +2 -0
  274. package/dist/components/table.js.map +7 -0
  275. package/dist/components/tabs.js +2 -0
  276. package/dist/components/tabs.js.map +7 -0
  277. package/dist/components/textarea.js +2 -0
  278. package/dist/components/textarea.js.map +7 -0
  279. package/dist/components/textfield.js +2 -0
  280. package/dist/components/textfield.js.map +7 -0
  281. package/dist/components/toast.js +2 -0
  282. package/dist/components/toast.js.map +7 -0
  283. package/dist/components/toggle.js +2 -0
  284. package/dist/components/toggle.js.map +7 -0
  285. package/dist/components/toolbar.js +2 -0
  286. package/dist/components/toolbar.js.map +7 -0
  287. package/dist/components/tooltip.js +2 -0
  288. package/dist/components/tooltip.js.map +7 -0
  289. package/dist/components/tree.js +2 -0
  290. package/dist/components/tree.js.map +7 -0
  291. package/dist/components/viewmanager.js +2 -0
  292. package/dist/components/viewmanager.js.map +7 -0
  293. package/dist/components/viewport.js +2 -0
  294. package/dist/components/viewport.js.map +7 -0
  295. package/dist/components/widget.js +2 -0
  296. package/dist/components/widget.js.map +7 -0
  297. package/dist/components/window.js +2 -0
  298. package/dist/components/window.js.map +7 -0
  299. package/dist/core.js +2 -0
  300. package/dist/core.js.map +7 -0
  301. package/dist/css/badge.css +39 -0
  302. package/dist/css/base.css +180 -0
  303. package/dist/css/breadcrumb.css +53 -0
  304. package/dist/css/button.css +103 -0
  305. package/dist/css/calendar.css +108 -0
  306. package/dist/css/cellediting.css +33 -0
  307. package/dist/css/chat.css +232 -0
  308. package/dist/css/checkbox.css +64 -0
  309. package/dist/css/checkboxgroup.css +12 -0
  310. package/dist/css/chip.css +64 -0
  311. package/dist/css/codeviewer.css +109 -0
  312. package/dist/css/commandpalette.css +167 -0
  313. package/dist/css/container.css +5 -0
  314. package/dist/css/core.css +88 -0
  315. package/dist/css/dataview.css +56 -0
  316. package/dist/css/dial.css +203 -0
  317. package/dist/css/dropdown.css +13 -0
  318. package/dist/css/field.css +62 -0
  319. package/dist/css/fieldgroup.css +26 -0
  320. package/dist/css/fieldlist.css +84 -0
  321. package/dist/css/fieldset.css +68 -0
  322. package/dist/css/filterbuilder.css +125 -0
  323. package/dist/css/form.css +8 -0
  324. package/dist/css/formactions.css +40 -0
  325. package/dist/css/formerrors.css +39 -0
  326. package/dist/css/formsection.css +45 -0
  327. package/dist/css/grid.css +378 -0
  328. package/dist/css/icon.css +16 -0
  329. package/dist/css/inputgroup.css +58 -0
  330. package/dist/css/label.css +12 -0
  331. package/dist/css/layout.css +116 -0
  332. package/dist/css/listbox.css +50 -0
  333. package/dist/css/menu.css +92 -0
  334. package/dist/css/messagebox.css +6 -0
  335. package/dist/css/motion.css +29 -0
  336. package/dist/css/navmenu.css +115 -0
  337. package/dist/css/pagination.css +23 -0
  338. package/dist/css/panel.css +84 -0
  339. package/dist/css/pickerfield.css +85 -0
  340. package/dist/css/radiogroup.css +53 -0
  341. package/dist/css/searchgrid.css +37 -0
  342. package/dist/css/secretfield.css +73 -0
  343. package/dist/css/slider.css +107 -0
  344. package/dist/css/spacer.css +7 -0
  345. package/dist/css/stepform.css +46 -0
  346. package/dist/css/stepper.css +122 -0
  347. package/dist/css/table.css +36 -0
  348. package/dist/css/tabs.css +108 -0
  349. package/dist/css/textarea.css +11 -0
  350. package/dist/css/textfield.css +59 -0
  351. package/dist/css/toast.css +91 -0
  352. package/dist/css/toggle.css +39 -0
  353. package/dist/css/toolbar.css +14 -0
  354. package/dist/css/tooltip.css +17 -0
  355. package/dist/css/tree.css +94 -0
  356. package/dist/css/viewport.css +9 -0
  357. package/dist/css/widget.css +135 -0
  358. package/dist/css/window.css +35 -0
  359. package/dist/data.js +2 -0
  360. package/dist/data.js.map +7 -0
  361. package/dist/index.js +8 -0
  362. package/dist/index.js.map +7 -0
  363. package/dist/motion.js +2 -0
  364. package/dist/motion.js.map +7 -0
  365. package/dist/optikos.css +4240 -0
  366. package/dist/themes/compact.css +17 -0
  367. package/dist/themes/dark.css +53 -0
  368. package/dist/types/bind/index.d.ts +23 -0
  369. package/dist/types/components/badge.d.ts +1 -0
  370. package/dist/types/components/base/badge/badge.d.ts +18 -0
  371. package/dist/types/components/base/button/button.d.ts +34 -0
  372. package/dist/types/components/base/chip/chip.d.ts +27 -0
  373. package/dist/types/components/base/codeviewer/codeviewer.d.ts +48 -0
  374. package/dist/types/components/base/icon/icon.d.ts +17 -0
  375. package/dist/types/components/base/label/label.d.ts +14 -0
  376. package/dist/types/components/breadcrumb.d.ts +1 -0
  377. package/dist/types/components/button.d.ts +1 -0
  378. package/dist/types/components/calendar.d.ts +1 -0
  379. package/dist/types/components/cellediting.d.ts +1 -0
  380. package/dist/types/components/chat/chat/chat.d.ts +84 -0
  381. package/dist/types/components/chat.d.ts +1 -0
  382. package/dist/types/components/checkbox.d.ts +1 -0
  383. package/dist/types/components/checkboxgroup.d.ts +1 -0
  384. package/dist/types/components/chip.d.ts +1 -0
  385. package/dist/types/components/codeviewer.d.ts +1 -0
  386. package/dist/types/components/combobox.d.ts +1 -0
  387. package/dist/types/components/commandpalette.d.ts +1 -0
  388. package/dist/types/components/container.d.ts +1 -0
  389. package/dist/types/components/data/cellediting/cellediting.d.ts +10 -0
  390. package/dist/types/components/data/dataview/dataview.d.ts +61 -0
  391. package/dist/types/components/data/filterbuilder/filterbuilder.d.ts +73 -0
  392. package/dist/types/components/data/grid/grid.d.ts +177 -0
  393. package/dist/types/components/data/pagination/pagination.d.ts +31 -0
  394. package/dist/types/components/data/searchgrid/searchgrid.d.ts +63 -0
  395. package/dist/types/components/data/table/table.d.ts +26 -0
  396. package/dist/types/components/data/tree/tree.d.ts +71 -0
  397. package/dist/types/components/data/viewmanager/viewmanager.d.ts +86 -0
  398. package/dist/types/components/dataview.d.ts +1 -0
  399. package/dist/types/components/datefield.d.ts +1 -0
  400. package/dist/types/components/daterangefield.d.ts +1 -0
  401. package/dist/types/components/dates/calendar/calendar.d.ts +48 -0
  402. package/dist/types/components/dial.d.ts +1 -0
  403. package/dist/types/components/dropdown.d.ts +1 -0
  404. package/dist/types/components/feedback/spinner/spinner.d.ts +11 -0
  405. package/dist/types/components/fieldgroup.d.ts +1 -0
  406. package/dist/types/components/fieldlist.d.ts +1 -0
  407. package/dist/types/components/fields/checkbox/checkbox.d.ts +20 -0
  408. package/dist/types/components/fields/checkboxgroup/checkboxgroup.d.ts +27 -0
  409. package/dist/types/components/fields/combobox/combobox.d.ts +15 -0
  410. package/dist/types/components/fields/datefield/datefield.d.ts +30 -0
  411. package/dist/types/components/fields/daterangefield/daterangefield.d.ts +32 -0
  412. package/dist/types/components/fields/dial/dial.d.ts +84 -0
  413. package/dist/types/components/fields/listbox/listbox.d.ts +54 -0
  414. package/dist/types/components/fields/lookupfield/lookupfield.d.ts +25 -0
  415. package/dist/types/components/fields/numberfield/numberfield.d.ts +31 -0
  416. package/dist/types/components/fields/pickerfield/pickerfield.d.ts +77 -0
  417. package/dist/types/components/fields/radiogroup/radiogroup.d.ts +26 -0
  418. package/dist/types/components/fields/secretfield/secretfield.d.ts +52 -0
  419. package/dist/types/components/fields/select/select.d.ts +10 -0
  420. package/dist/types/components/fields/slider/slider.d.ts +62 -0
  421. package/dist/types/components/fields/suggestfield/suggestfield.d.ts +34 -0
  422. package/dist/types/components/fields/textarea/textarea.d.ts +16 -0
  423. package/dist/types/components/fields/textfield/textfield.d.ts +38 -0
  424. package/dist/types/components/fields/toggle/toggle.d.ts +9 -0
  425. package/dist/types/components/fieldset.d.ts +1 -0
  426. package/dist/types/components/filterbuilder.d.ts +1 -0
  427. package/dist/types/components/form/fieldgroup/fieldgroup.d.ts +33 -0
  428. package/dist/types/components/form/fieldlist/fieldlist.d.ts +58 -0
  429. package/dist/types/components/form/form/form.d.ts +68 -0
  430. package/dist/types/components/form/formactions/formactions.d.ts +34 -0
  431. package/dist/types/components/form/formerrors/formerrors.d.ts +23 -0
  432. package/dist/types/components/form/formsection/formsection.d.ts +26 -0
  433. package/dist/types/components/form/inputgroup/inputgroup.d.ts +28 -0
  434. package/dist/types/components/form/stepform/stepform.d.ts +64 -0
  435. package/dist/types/components/form.d.ts +1 -0
  436. package/dist/types/components/formactions.d.ts +1 -0
  437. package/dist/types/components/formerrors.d.ts +1 -0
  438. package/dist/types/components/formsection.d.ts +1 -0
  439. package/dist/types/components/grid.d.ts +1 -0
  440. package/dist/types/components/icon.d.ts +1 -0
  441. package/dist/types/components/inputgroup.d.ts +1 -0
  442. package/dist/types/components/label.d.ts +1 -0
  443. package/dist/types/components/layout/container/container.d.ts +1 -0
  444. package/dist/types/components/layout/fieldset/fieldset.d.ts +30 -0
  445. package/dist/types/components/layout/panel/panel.d.ts +53 -0
  446. package/dist/types/components/layout/panel/reload.d.ts +1 -0
  447. package/dist/types/components/layout/spacer/spacer.d.ts +12 -0
  448. package/dist/types/components/layout/toolbar/toolbar.d.ts +15 -0
  449. package/dist/types/components/layout/viewport/viewport.d.ts +7 -0
  450. package/dist/types/components/listbox.d.ts +1 -0
  451. package/dist/types/components/lookupfield.d.ts +1 -0
  452. package/dist/types/components/menu.d.ts +1 -0
  453. package/dist/types/components/messagebox.d.ts +1 -0
  454. package/dist/types/components/navigation/breadcrumb/breadcrumb.d.ts +32 -0
  455. package/dist/types/components/navigation/navmenu/navmenu.d.ts +63 -0
  456. package/dist/types/components/navigation/stepper/stepper.d.ts +31 -0
  457. package/dist/types/components/navigation/tabs/tabs.d.ts +57 -0
  458. package/dist/types/components/navmenu.d.ts +1 -0
  459. package/dist/types/components/numberfield.d.ts +1 -0
  460. package/dist/types/components/overlays/commandpalette/commandpalette.d.ts +80 -0
  461. package/dist/types/components/overlays/dropdown/dropdown.d.ts +41 -0
  462. package/dist/types/components/overlays/menu/menu.d.ts +56 -0
  463. package/dist/types/components/overlays/messagebox/messagebox.d.ts +61 -0
  464. package/dist/types/components/overlays/toast/toast.d.ts +45 -0
  465. package/dist/types/components/overlays/tooltip/tooltip.d.ts +13 -0
  466. package/dist/types/components/overlays/widget/widget.d.ts +61 -0
  467. package/dist/types/components/overlays/window/window.d.ts +38 -0
  468. package/dist/types/components/pagination.d.ts +1 -0
  469. package/dist/types/components/panel.d.ts +1 -0
  470. package/dist/types/components/pickerfield.d.ts +1 -0
  471. package/dist/types/components/radiogroup.d.ts +1 -0
  472. package/dist/types/components/searchgrid.d.ts +1 -0
  473. package/dist/types/components/secretfield.d.ts +1 -0
  474. package/dist/types/components/select.d.ts +1 -0
  475. package/dist/types/components/slider.d.ts +1 -0
  476. package/dist/types/components/spacer.d.ts +1 -0
  477. package/dist/types/components/spinner.d.ts +1 -0
  478. package/dist/types/components/stepform.d.ts +1 -0
  479. package/dist/types/components/stepper.d.ts +1 -0
  480. package/dist/types/components/suggestfield.d.ts +1 -0
  481. package/dist/types/components/table.d.ts +1 -0
  482. package/dist/types/components/tabs.d.ts +1 -0
  483. package/dist/types/components/textarea.d.ts +1 -0
  484. package/dist/types/components/textfield.d.ts +1 -0
  485. package/dist/types/components/toast.d.ts +1 -0
  486. package/dist/types/components/toggle.d.ts +1 -0
  487. package/dist/types/components/toolbar.d.ts +1 -0
  488. package/dist/types/components/tooltip.d.ts +1 -0
  489. package/dist/types/components/tree.d.ts +1 -0
  490. package/dist/types/components/viewmanager.d.ts +1 -0
  491. package/dist/types/components/viewport.d.ts +1 -0
  492. package/dist/types/components/widget.d.ts +1 -0
  493. package/dist/types/components/window.d.ts +1 -0
  494. package/dist/types/core/component.d.ts +94 -0
  495. package/dist/types/core/container.d.ts +43 -0
  496. package/dist/types/core/date.d.ts +14 -0
  497. package/dist/types/core/dom.d.ts +11 -0
  498. package/dist/types/core/emitter.d.ts +12 -0
  499. package/dist/types/core/field.d.ts +78 -0
  500. package/dist/types/core/focus.d.ts +18 -0
  501. package/dist/types/core/i18n.d.ts +12 -0
  502. package/dist/types/core/index.d.ts +15 -0
  503. package/dist/types/core/layer.d.ts +6 -0
  504. package/dist/types/core/position.d.ts +19 -0
  505. package/dist/types/core/registry.d.ts +12 -0
  506. package/dist/types/core/validators.d.ts +10 -0
  507. package/dist/types/core/virtual.d.ts +24 -0
  508. package/dist/types/data/column.d.ts +32 -0
  509. package/dist/types/data/format.d.ts +4 -0
  510. package/dist/types/data/index.d.ts +5 -0
  511. package/dist/types/data/model.d.ts +28 -0
  512. package/dist/types/data/proxy.d.ts +61 -0
  513. package/dist/types/data/store.d.ts +94 -0
  514. package/dist/types/index.d.ts +67 -0
  515. package/dist/types/layout/layout.d.ts +27 -0
  516. package/dist/types/motion/config.d.ts +83 -0
  517. package/dist/types/motion/core.d.ts +40 -0
  518. package/dist/types/motion/extras.d.ts +66 -0
  519. package/dist/types/motion/index.d.ts +3 -0
  520. package/dist/types/themes/define.d.ts +31 -0
  521. package/dist/types/themes/index.d.ts +1 -0
  522. package/dist/types/ui/enums.d.ts +82 -0
  523. package/dist/types/ui/index.d.ts +2 -0
  524. package/dist/types/ui/ui.d.ts +67 -0
  525. package/dist/ui.js +2 -0
  526. package/dist/ui.js.map +7 -0
  527. package/package.json +104 -4
@@ -0,0 +1,4240 @@
1
+ /*
2
+ * Optikos tokens. Three layers, all custom properties:
3
+ * 1. primitives --op-blue-500 (raw palette, never used by components)
4
+ * 2. semantic --op-color-primary (what themes change)
5
+ * 3. component --op-button-bg (declared by each component, falls back to a semantic token)
6
+ * Everything lives in @layer optikos so unlayered user CSS always wins without !important.
7
+ * Scope a theme with data-op-theme="dark" (several allowed: "dark compact") on any element.
8
+ */
9
+ @layer optikos {
10
+ :root,
11
+ [data-op-theme~='light'] {
12
+ /* primitives */
13
+ --op-gray-0: #ffffff;
14
+ --op-gray-50: #f8fafc;
15
+ --op-gray-100: #f1f5f9;
16
+ --op-gray-200: #e2e8f0;
17
+ --op-gray-300: #cbd5e1;
18
+ --op-gray-400: #94a3b8;
19
+ --op-gray-500: #64748b;
20
+ --op-gray-600: #475569;
21
+ --op-gray-700: #334155;
22
+ --op-gray-800: #1e293b;
23
+ --op-gray-900: #0f172a;
24
+ --op-blue-50: #eff6ff;
25
+ --op-blue-100: #dbeafe;
26
+ --op-blue-500: #3b82f6;
27
+ --op-blue-600: #2563eb;
28
+ --op-blue-700: #1d4ed8;
29
+ --op-red-50: #fef2f2;
30
+ --op-red-500: #ef4444;
31
+ --op-red-600: #dc2626;
32
+ --op-red-700: #b91c1c;
33
+ --op-green-50: #f0fdf4;
34
+ --op-green-600: #16a34a;
35
+ --op-green-700: #15803d;
36
+ --op-amber-50: #fffbeb;
37
+ --op-amber-600: #d97706;
38
+ --op-amber-700: #b45309;
39
+
40
+ /* semantic colors: steel blue on cool grey, made for long sessions in grids and forms */
41
+ --op-color-bg: #edf0f4;
42
+ --op-color-surface: var(--op-gray-0);
43
+ --op-color-surface-2: #f3f5f8;
44
+ --op-color-fg: #1b2430;
45
+ --op-color-fg-muted: #5b6676; /* keeps 4.5:1 on surface-2 */
46
+ --op-color-border: #d8dee6;
47
+ --op-color-border-strong: #a9b3c1;
48
+ --op-color-hover: #eaeff6;
49
+ --op-color-selected: #d9e6f7;
50
+ --op-color-primary: #1f4e8c;
51
+ --op-color-primary-hover: #173d6f;
52
+ --op-color-primary-fg: var(--op-gray-0);
53
+ --op-color-primary-soft: #e4edf8;
54
+ --op-color-danger: #b3261e;
55
+ --op-color-danger-hover: #8f1d17;
56
+ --op-color-danger-fg: var(--op-gray-0);
57
+ --op-color-danger-soft: #fbe4e2;
58
+ --op-color-success: #1e7a4d;
59
+ --op-color-success-soft: #dff2e8;
60
+ --op-color-warning: #9a5b00;
61
+ --op-color-warning-soft: #fcecc9;
62
+ --op-color-info: #1f5fa8;
63
+ --op-color-info-soft: #dfeaf8;
64
+ --op-color-focus: #2f7bd6;
65
+ --op-color-disabled-fg: #9aa4b2;
66
+ --op-color-disabled-bg: #eef1f5;
67
+ --op-color-overlay: rgb(16 24 38 / 0.5);
68
+ --op-color-inverse-bg: #14213a;
69
+ --op-color-inverse-fg: #eaf0fa;
70
+
71
+ /* typography */
72
+ --op-font-family: 'Segoe UI', Inter, Roboto, 'Helvetica Neue', Arial, system-ui, sans-serif;
73
+ --op-font-mono: ui-monospace, SFMono-Regular, Menlo, monospace;
74
+ --op-font-size: 0.9375rem;
75
+ --op-font-size-sm: 0.8125rem;
76
+ --op-font-size-lg: 1.0625rem;
77
+ --op-font-size-xl: 1.3125rem;
78
+ --op-line-height: 1.45;
79
+ --op-font-weight: 400;
80
+ --op-font-weight-medium: 500;
81
+ --op-font-weight-bold: 600;
82
+
83
+ /* spacing, density, shape: comfortable, small radii, hairline borders */
84
+ --op-space-1: 0.25rem;
85
+ --op-space-2: 0.5rem;
86
+ --op-space-3: 0.875rem;
87
+ --op-space-4: 1.125rem;
88
+ --op-space-5: 1.5rem;
89
+ --op-space-6: 2.25rem;
90
+ --op-control-height: 2.375rem;
91
+ --op-control-padding-x: 0.875rem;
92
+ --op-row-height: 2.75rem;
93
+ --op-border-width: 1px;
94
+ --op-radius-sm: 0.1875rem;
95
+ --op-radius: 0.25rem;
96
+ --op-radius-lg: 0.375rem;
97
+ --op-radius-pill: 62.5rem;
98
+ --op-focus-width: 2px;
99
+ --op-focus-offset: 1px;
100
+ --op-icon-size: 1.3em;
101
+ --op-icon-stroke: 1.75;
102
+
103
+ /* elevation and motion: flat at rest, shadows only on what floats */
104
+ --op-shadow-sm: none;
105
+ --op-shadow: 0 2px 6px rgb(16 24 38 / 0.14);
106
+ --op-shadow-lg: 0 10px 28px rgb(16 24 38 / 0.28);
107
+ --op-duration: 90ms;
108
+
109
+ /* scrollbars follow the theme: thin, thumb from the strong border, track transparent */
110
+ --op-scrollbar-width: thin;
111
+ --op-scrollbar-size: 0.5rem;
112
+ --op-scrollbar-thumb: var(--op-color-border-strong);
113
+ --op-scrollbar-track: transparent;
114
+ --op-easing: ease-out;
115
+ --op-z-layer: 1000;
116
+ }
117
+
118
+ /* The light look's component colors (a navy sidebar, a tinted grid header). Literal values, and not on :root under
119
+ another theme, so a theme that does not set them keeps the component defaults. dark.css sets its own. */
120
+ :root:not([data-op-theme]),
121
+ [data-op-theme~='light'],
122
+ [data-op-theme='compact'] {
123
+ --op-navmenu-item-height: 2.5rem;
124
+ --op-navmenu-bg: #14213a;
125
+ --op-navmenu-fg: #d5ddeb;
126
+ --op-navmenu-group-fg: #8195b4;
127
+ --op-navmenu-item-hover-bg: #1d2f52;
128
+ --op-navmenu-active-bg: #203c6a;
129
+ --op-navmenu-active-fg: #ffffff;
130
+ --op-navmenu-active-bar: #5ea6f5;
131
+ --op-navmenu-badge-bg: #5ea6f5;
132
+ --op-navmenu-badge-fg: #0a1730;
133
+ --op-grid-header-bg: #e6ebf1;
134
+ --op-grid-header-fg: #2a3547;
135
+ --op-field-label-weight: 600;
136
+ }
137
+
138
+ @media (prefers-reduced-motion: reduce) {
139
+ :root,
140
+ [data-op-theme] {
141
+ --op-duration: 0.01ms;
142
+ }
143
+ }
144
+
145
+ /* inherited: every scroll area below a themed element (and the global layer) picks it up */
146
+ :root,
147
+ [data-op-theme] {
148
+ scrollbar-width: var(--op-scrollbar-width);
149
+ scrollbar-color: var(--op-scrollbar-thumb) var(--op-scrollbar-track);
150
+ }
151
+ /* browsers without scrollbar-color (older Safari) */
152
+ @supports not (scrollbar-color: auto) {
153
+ :root ::-webkit-scrollbar,
154
+ [data-op-theme] ::-webkit-scrollbar {
155
+ inline-size: var(--op-scrollbar-size);
156
+ block-size: var(--op-scrollbar-size);
157
+ }
158
+ :root ::-webkit-scrollbar-thumb,
159
+ [data-op-theme] ::-webkit-scrollbar-thumb {
160
+ background: var(--op-scrollbar-thumb);
161
+ border-radius: var(--op-radius-pill);
162
+ }
163
+ :root ::-webkit-scrollbar-track,
164
+ [data-op-theme] ::-webkit-scrollbar-track {
165
+ background: var(--op-scrollbar-track);
166
+ }
167
+ }
168
+
169
+ /* Base look for any themed subtree, so a scoped theme repaints its background and text. */
170
+ [data-op-theme] {
171
+ color: var(--op-color-fg);
172
+ background: var(--op-color-bg);
173
+ font-family: var(--op-font-family);
174
+ font-size: var(--op-font-size);
175
+ line-height: var(--op-line-height);
176
+ }
177
+ :where(.op-layout, .op-component, .op-field, .op-panel, .op-container, .op-layer *) {
178
+ box-sizing: border-box;
179
+ }
180
+ }
181
+
182
+ @layer optikos {
183
+ :root {
184
+ --op-spinner-size: 1.5rem;
185
+ --op-spinner-stroke: 2px;
186
+ }
187
+
188
+ /* every Optikos element gets the themed font; zero specificity, so any component rule overrides it */
189
+ :where([class^='op-'], [class*=' op-']) {
190
+ font-family: var(--op-font-family);
191
+ font-size: var(--op-font-size);
192
+ }
193
+ .op-component,
194
+ .op-container {
195
+ color: var(--op-color-fg);
196
+ }
197
+
198
+ /* loading mask (Component.setLoading) */
199
+ .is-loading {
200
+ position: relative;
201
+ }
202
+ .op-mask {
203
+ position: absolute;
204
+ inset: 0;
205
+ z-index: 1;
206
+ display: flex;
207
+ flex-direction: column;
208
+ align-items: center;
209
+ justify-content: center;
210
+ gap: var(--op-space-2);
211
+ background: var(--op-mask-bg, color-mix(in srgb, var(--op-color-surface) 70%, transparent));
212
+ color: var(--op-color-fg);
213
+ }
214
+
215
+ .op-spinner {
216
+ display: inline-block;
217
+ box-sizing: border-box;
218
+ width: var(--op-spinner-size);
219
+ height: var(--op-spinner-size);
220
+ border: var(--op-spinner-stroke) solid var(--op-color-border-strong);
221
+ border-top-color: var(--op-spinner-color, var(--op-color-primary));
222
+ border-radius: 50%;
223
+ animation: op-spin 700ms linear infinite;
224
+ }
225
+ @keyframes op-spin {
226
+ to {
227
+ transform: rotate(360deg);
228
+ }
229
+ }
230
+ @media (prefers-reduced-motion: reduce) {
231
+ .op-spinner {
232
+ animation-duration: 2s;
233
+ }
234
+ }
235
+
236
+ /* virtual lists (core/virtual.ts) */
237
+ .op-virtual {
238
+ position: relative;
239
+ inline-size: 100%;
240
+ }
241
+ .op-sr-only {
242
+ position: absolute;
243
+ inline-size: 0;
244
+ block-size: 0;
245
+ overflow: hidden;
246
+ clip-path: inset(50%);
247
+ white-space: nowrap;
248
+ }
249
+
250
+ /* floating layer */
251
+ .op-layer {
252
+ position: fixed;
253
+ inset: 0;
254
+ z-index: var(--op-z-layer);
255
+ pointer-events: none;
256
+ font-family: var(--op-font-family);
257
+ font-size: var(--op-font-size);
258
+ line-height: var(--op-line-height);
259
+ color: var(--op-color-fg);
260
+ }
261
+ .op-layer > * {
262
+ pointer-events: auto;
263
+ }
264
+
265
+ :where(.op-component, .op-field, .op-container) :focus-visible {
266
+ outline: var(--op-focus-width) solid var(--op-color-focus);
267
+ outline-offset: var(--op-focus-offset);
268
+ }
269
+ }
270
+
271
+ @layer optikos {
272
+ :root {
273
+ --op-field-label-width: 8rem;
274
+ }
275
+
276
+ .op-field {
277
+ --_label-fg: var(--op-field-label-fg, var(--op-color-fg));
278
+ display: flex;
279
+ flex-direction: column;
280
+ gap: var(--op-field-gap, var(--op-space-1));
281
+ font-family: var(--op-font-family);
282
+ font-size: var(--op-font-size);
283
+ color: var(--op-color-fg);
284
+ min-width: 0;
285
+ }
286
+ .op-field__label {
287
+ color: var(--_label-fg);
288
+ font-size: var(--op-field-label-size, var(--op-font-size));
289
+ font-weight: var(--op-field-label-weight, var(--op-font-weight-medium));
290
+ }
291
+ .op-field.is-required > .op-field__label::after {
292
+ content: ' *';
293
+ color: var(--op-color-danger);
294
+ }
295
+ .op-field__control {
296
+ min-width: 0;
297
+ }
298
+ .op-field__help {
299
+ color: var(--op-field-help-fg, var(--op-color-fg-muted));
300
+ font-size: var(--op-font-size-sm);
301
+ }
302
+ .op-field__error {
303
+ color: var(--op-field-error-fg, var(--op-color-danger));
304
+ font-size: var(--op-font-size-sm);
305
+ }
306
+ .op-field__error:empty {
307
+ display: none;
308
+ }
309
+ /* stableSize: the error line is always reserved, so a field does not grow when it becomes invalid */
310
+ .op-field.op-stable > .op-field__error:empty {
311
+ display: block;
312
+ min-block-size: calc(var(--op-font-size-sm) * var(--op-line-height));
313
+ }
314
+ .op-field--label-left {
315
+ display: grid;
316
+ grid-template-columns: var(--op-field-label-width) minmax(0, 1fr);
317
+ align-items: start;
318
+ column-gap: var(--op-space-3);
319
+ }
320
+ .op-field--label-left > .op-field__label {
321
+ padding-block: var(--op-space-2);
322
+ grid-column: 1;
323
+ }
324
+ .op-field--label-left > .op-field__control,
325
+ .op-field--label-left > .op-field__help,
326
+ .op-field--label-left > .op-field__error {
327
+ grid-column: 2;
328
+ }
329
+ .op-field.is-disabled {
330
+ color: var(--op-color-disabled-fg);
331
+ }
332
+ }
333
+
334
+ @layer optikos {
335
+ [hidden] {
336
+ display: none !important;
337
+ }
338
+ .op-layout {
339
+ box-sizing: border-box;
340
+ }
341
+ .op-layout-fit {
342
+ display: flex;
343
+ flex-direction: column;
344
+ }
345
+ .op-layout-fit > * {
346
+ flex: 1;
347
+ min-width: 0;
348
+ min-height: 0;
349
+ }
350
+ .op-layout-hbox,
351
+ .op-layout-vbox {
352
+ display: flex;
353
+ gap: var(--op-layout-gap, var(--op-space-2));
354
+ align-items: var(--op-layout-align, stretch);
355
+ justify-content: var(--op-layout-justify, flex-start);
356
+ flex-wrap: var(--op-layout-wrap, nowrap);
357
+ }
358
+ .op-layout-hbox {
359
+ flex-direction: row;
360
+ }
361
+ .op-layout-vbox {
362
+ flex-direction: column;
363
+ }
364
+ .op-layout-hbox > *,
365
+ .op-layout-vbox > * {
366
+ min-width: 0;
367
+ min-height: 0;
368
+ }
369
+ /* a column keeps its children at their natural height (the container scrolls or clips instead of squashing them);
370
+ a child that sets `flex` (e.g. a grid with flex: 1) still grows and shrinks as asked */
371
+ .op-layout-vbox > * {
372
+ flex-shrink: 0;
373
+ }
374
+ /* content that is taller than its column scrolls inside it; it never spills over what comes next */
375
+ .op-layout-vbox {
376
+ overflow: auto;
377
+ }
378
+ .op-layout-grid {
379
+ display: grid;
380
+ grid-template-columns: repeat(var(--op-layout-columns, 1), minmax(0, 1fr));
381
+ gap: var(--op-layout-gap, var(--op-space-2));
382
+ }
383
+ .op-layout-border {
384
+ display: grid;
385
+ grid-template-areas: 'north north north' 'west center east' 'south south south';
386
+ grid-template-columns: auto minmax(0, 1fr) auto;
387
+ grid-template-rows: auto minmax(0, 1fr) auto;
388
+ gap: var(--op-layout-gap, 0);
389
+ }
390
+ .op-layout-border > * {
391
+ min-width: 0;
392
+ min-height: 0;
393
+ }
394
+ .op-layout-hbox.op-layout-stack.is-narrow {
395
+ flex-direction: column;
396
+ }
397
+ /* stacked children take their natural height (a `flex: 1` meant for the row would squash them in a column) */
398
+ .op-layout-hbox.op-layout-stack.is-narrow > * {
399
+ flex: 0 0 auto !important;
400
+ }
401
+ .op-layout-grid.is-narrow {
402
+ grid-template-columns: minmax(0, 1fr);
403
+ }
404
+ .op-layout-grid.is-narrow > * {
405
+ grid-column: auto !important;
406
+ }
407
+
408
+ /* narrow border layout: one column; west/east become drawers sliding over the center */
409
+ :root {
410
+ --op-region-drawer-width: 20rem;
411
+ --op-region-drawer-z: 3;
412
+ }
413
+ .op-layout-border {
414
+ position: relative;
415
+ }
416
+ .op-layout-border.is-narrow {
417
+ grid-template-areas: 'north' 'center' 'south';
418
+ grid-template-columns: minmax(0, 1fr);
419
+ }
420
+ .op-layout-border.is-narrow > [data-region='west'],
421
+ .op-layout-border.is-narrow > [data-region='east'] {
422
+ position: absolute;
423
+ inset-block: 0;
424
+ z-index: var(--op-region-drawer-z);
425
+ inline-size: min(var(--op-region-drawer-width), 100%) !important;
426
+ visibility: hidden;
427
+ transition: transform var(--op-duration) var(--op-easing), visibility var(--op-duration);
428
+ box-shadow: var(--op-shadow-lg);
429
+ }
430
+ .op-layout-border.is-narrow > [data-region='west'] {
431
+ inset-inline-start: 0;
432
+ transform: translateX(-100%);
433
+ }
434
+ .op-layout-border.is-narrow > [data-region='east'] {
435
+ inset-inline-end: 0;
436
+ transform: translateX(100%);
437
+ }
438
+ .op-layout-border.is-narrow > [data-region].is-open {
439
+ visibility: visible;
440
+ transform: none;
441
+ }
442
+ .op-layout-border.is-narrow.has-open-region::after {
443
+ content: '';
444
+ position: absolute;
445
+ inset: 0;
446
+ z-index: calc(var(--op-region-drawer-z) - 1);
447
+ background: var(--op-color-overlay);
448
+ }
449
+ }
450
+
451
+ @layer optikos {
452
+ :root {
453
+ --op-badge-dot-size: 0.5rem;
454
+ --op-badge-height: 1.5em;
455
+ --op-badge-icon-size: 1em;
456
+ }
457
+ .op-badge {
458
+ --_fg: var(--op-color-fg);
459
+ --_bg: var(--op-color-surface-2);
460
+ display: inline-flex;
461
+ align-items: center;
462
+ gap: var(--op-space-1);
463
+ padding: 0 var(--op-badge-padding-x, var(--op-space-2));
464
+ min-block-size: var(--op-badge-height);
465
+ box-sizing: border-box;
466
+ color: var(--op-badge-fg, var(--_fg));
467
+ background: var(--op-badge-bg, var(--_bg));
468
+ border-radius: var(--op-badge-radius, var(--op-radius-pill));
469
+ font-size: var(--op-font-size-sm);
470
+ font-weight: var(--op-badge-font-weight, var(--op-font-weight-bold));
471
+ line-height: 1;
472
+ white-space: nowrap;
473
+ vertical-align: middle;
474
+ }
475
+ .op-badge--primary { --_fg: var(--op-color-primary-text, var(--op-color-primary)); --_bg: var(--op-color-primary-soft); }
476
+ .op-badge--success { --_fg: var(--op-color-success); --_bg: var(--op-color-success-soft); }
477
+ .op-badge--warning { --_fg: var(--op-color-warning); --_bg: var(--op-color-warning-soft); }
478
+ .op-badge--danger { --_fg: var(--op-color-danger); --_bg: var(--op-color-danger-soft); }
479
+ .op-badge--info { --_fg: var(--op-color-info); --_bg: var(--op-color-info-soft); }
480
+ .op-badge__dot {
481
+ inline-size: var(--op-badge-dot-size);
482
+ block-size: var(--op-badge-dot-size);
483
+ border-radius: 50%;
484
+ background: currentColor;
485
+ }
486
+ .op-badge .op-icon {
487
+ --op-icon-size: var(--op-badge-icon-size);
488
+ }
489
+ }
490
+
491
+ @layer optikos {
492
+ :root {
493
+ --op-button-spinner-size: 1em;
494
+ --op-button-primary-shadow: inset 0 -1px 0 rgb(0 0 0 / 0.25);
495
+ }
496
+
497
+ .op-button {
498
+ --_bg: var(--op-button-bg, var(--op-color-surface));
499
+ --_fg: var(--op-button-fg, var(--op-color-fg));
500
+ --_border: var(--op-button-border, var(--op-color-border-strong));
501
+ --_hover: var(--op-button-hover-bg, var(--op-color-hover));
502
+ --_active: var(--op-button-active-bg, var(--op-color-selected));
503
+ display: inline-grid;
504
+ place-items: center;
505
+ box-sizing: border-box;
506
+ min-block-size: var(--op-button-height, var(--op-control-height));
507
+ padding: var(--op-button-padding-y, 0) var(--op-button-padding-x, var(--op-control-padding-x));
508
+ font: inherit;
509
+ font-weight: var(--op-button-font-weight, var(--op-font-weight-medium));
510
+ color: var(--_fg);
511
+ background: var(--_bg);
512
+ border: var(--op-border-width) solid var(--_border);
513
+ border-radius: var(--op-button-radius, var(--op-radius));
514
+ cursor: pointer;
515
+ user-select: none;
516
+ white-space: nowrap;
517
+ transition: background var(--op-duration) var(--op-easing), border-color var(--op-duration) var(--op-easing), transform var(--op-motion-press-duration, 100ms) var(--op-motion-ease-out, ease-out);
518
+ }
519
+ .op-button:hover:not(:disabled) {
520
+ background: var(--_hover);
521
+ }
522
+ .op-button:active:not(:disabled),
523
+ .op-button.is-pressed {
524
+ background: var(--_active);
525
+ }
526
+ .op-button:focus-visible {
527
+ outline: var(--op-focus-width) solid var(--op-color-focus);
528
+ outline-offset: var(--op-focus-offset);
529
+ }
530
+ /* normal face and loading face occupy the same grid cell */
531
+ .op-button__face,
532
+ .op-button__busy {
533
+ grid-area: 1 / 1;
534
+ display: inline-flex;
535
+ align-items: center;
536
+ justify-content: center;
537
+ gap: var(--op-button-gap, var(--op-space-2));
538
+ }
539
+ .op-button--icon-right .op-button__face {
540
+ flex-direction: row-reverse;
541
+ }
542
+ .op-button__busy {
543
+ visibility: hidden;
544
+ }
545
+ .op-button.is-loading .op-button__busy {
546
+ visibility: visible;
547
+ }
548
+ .op-button.is-loading .op-button__face {
549
+ visibility: hidden;
550
+ }
551
+ /* stableSize: false → only the active face takes space, the button fits its content */
552
+ .op-button:not(.op-stable) .op-button__busy,
553
+ .op-button:not(.op-stable).is-loading .op-button__face {
554
+ display: none;
555
+ }
556
+ .op-button:not(.op-stable).is-loading .op-button__busy {
557
+ display: inline-flex;
558
+ }
559
+
560
+ .op-button--primary {
561
+ --_bg: var(--op-button-primary-bg, var(--op-color-primary));
562
+ --_fg: var(--op-button-primary-fg, var(--op-color-primary-fg));
563
+ --_border: var(--op-button-primary-bg, var(--op-color-primary));
564
+ --_hover: var(--op-button-primary-hover-bg, var(--op-color-primary-hover));
565
+ --_active: var(--op-button-primary-hover-bg, var(--op-color-primary-hover));
566
+ box-shadow: var(--op-button-primary-shadow);
567
+ }
568
+ .op-button--danger {
569
+ --_bg: var(--op-button-danger-bg, var(--op-color-danger));
570
+ --_fg: var(--op-button-danger-fg, var(--op-color-danger-fg));
571
+ --_border: var(--op-button-danger-bg, var(--op-color-danger));
572
+ --_hover: var(--op-button-danger-hover-bg, var(--op-color-danger-hover));
573
+ --_active: var(--op-button-danger-hover-bg, var(--op-color-danger-hover));
574
+ }
575
+ .op-button--ghost {
576
+ --_bg: transparent;
577
+ --_border: transparent;
578
+ }
579
+
580
+ .op-button:disabled {
581
+ cursor: not-allowed;
582
+ color: var(--op-color-disabled-fg);
583
+ background: var(--op-color-disabled-bg);
584
+ border-color: var(--op-color-border);
585
+ }
586
+ .op-button.is-loading {
587
+ cursor: progress;
588
+ }
589
+ .op-button__spinner {
590
+ --op-spinner-size: var(--op-button-spinner-size);
591
+ --op-spinner-color: currentColor;
592
+ }
593
+ }
594
+
595
+ @layer optikos {
596
+ .op-chip {
597
+ display: inline-flex;
598
+ align-items: center;
599
+ max-inline-size: 100%;
600
+ box-sizing: border-box;
601
+ min-block-size: var(--op-chip-height, calc(var(--op-control-height) * 0.8));
602
+ color: var(--op-chip-fg, var(--op-color-fg));
603
+ background: var(--op-chip-bg, var(--op-color-surface));
604
+ border: var(--op-border-width) solid var(--op-chip-border, var(--op-color-border-strong));
605
+ border-radius: var(--op-chip-radius, var(--op-radius-pill));
606
+ font-size: var(--op-font-size-sm);
607
+ vertical-align: middle;
608
+ }
609
+ .op-chip__main,
610
+ .op-chip__remove {
611
+ display: inline-flex;
612
+ align-items: center;
613
+ gap: var(--op-space-1);
614
+ padding: 0 var(--op-space-3);
615
+ min-block-size: inherit;
616
+ color: inherit;
617
+ background: none;
618
+ border: 0;
619
+ border-radius: inherit;
620
+ font: inherit;
621
+ cursor: pointer;
622
+ }
623
+ .op-chip__main {
624
+ min-inline-size: 0;
625
+ }
626
+ .op-chip__text {
627
+ overflow: hidden;
628
+ text-overflow: ellipsis;
629
+ white-space: nowrap;
630
+ }
631
+ .op-chip__remove {
632
+ padding-inline: var(--op-space-1) var(--op-space-2);
633
+ color: var(--op-color-fg-muted);
634
+ }
635
+ .op-chip__remove:hover:not(:disabled) {
636
+ color: var(--op-color-danger);
637
+ }
638
+ .op-chip__main:focus-visible,
639
+ .op-chip__remove:focus-visible {
640
+ outline: var(--op-focus-width) solid var(--op-color-focus);
641
+ outline-offset: calc(var(--op-focus-width) * -1);
642
+ }
643
+ .op-chip:hover:not(.is-disabled) {
644
+ border-color: var(--op-chip-hover-border, var(--op-color-primary));
645
+ }
646
+ .op-chip.is-selected {
647
+ color: var(--op-chip-selected-fg, var(--op-color-primary-text, var(--op-color-primary)));
648
+ background: var(--op-chip-selected-bg, var(--op-color-primary-soft));
649
+ border-color: var(--op-chip-selected-border, var(--op-color-primary));
650
+ }
651
+ .op-chip.is-disabled {
652
+ color: var(--op-color-disabled-fg);
653
+ border-color: var(--op-color-border);
654
+ }
655
+ .op-chip.is-disabled button {
656
+ cursor: default;
657
+ }
658
+ }
659
+
660
+ @layer optikos {
661
+ :root {
662
+ --op-codeviewer-font-size: 0.8125rem;
663
+ --op-codeviewer-line-height: 1.6;
664
+ --op-codeviewer-tab-size: 2;
665
+ --op-codeviewer-gutter-gap: 1.25rem;
666
+ --op-codeviewer-max-height: 32rem;
667
+ }
668
+ .op-codeviewer {
669
+ overflow: hidden;
670
+ color: var(--op-codeviewer-fg, var(--op-color-fg));
671
+ background: var(--op-codeviewer-bg, var(--op-color-surface-2));
672
+ border: var(--op-border-width) solid var(--op-color-border);
673
+ border-radius: var(--op-radius-lg);
674
+ }
675
+ .op-codeviewer__bar {
676
+ display: flex;
677
+ align-items: center;
678
+ justify-content: space-between;
679
+ gap: var(--op-space-2);
680
+ min-block-size: var(--op-control-height);
681
+ padding-inline: var(--op-space-3) var(--op-space-1);
682
+ color: var(--op-color-fg-muted);
683
+ border-block-end: var(--op-border-width) solid var(--op-color-border);
684
+ font-size: var(--op-font-size-sm);
685
+ }
686
+ .op-codeviewer__title {
687
+ overflow: hidden;
688
+ text-overflow: ellipsis;
689
+ white-space: nowrap;
690
+ }
691
+ .op-codeviewer__pre {
692
+ margin: 0;
693
+ padding: var(--op-space-3) var(--op-space-4);
694
+ max-block-size: var(--op-codeviewer-max-height);
695
+ overflow: auto;
696
+ font-family: var(--op-font-mono);
697
+ font-size: var(--op-codeviewer-font-size);
698
+ line-height: var(--op-codeviewer-line-height);
699
+ tab-size: var(--op-codeviewer-tab-size);
700
+ }
701
+ .op-codeviewer__pre:focus-visible {
702
+ outline: var(--op-focus-width) solid var(--op-color-focus);
703
+ outline-offset: calc(var(--op-focus-width) * -1);
704
+ }
705
+ /* the global op-* rule would give lines and tokens the base font: everything inside the code keeps the mono one */
706
+ .op-codeviewer__pre * {
707
+ font-family: inherit;
708
+ font-size: inherit;
709
+ }
710
+ /* lines stretch to the widest one, so a marked line is marked across the whole scroll width */
711
+ .op-codeviewer__code {
712
+ display: block;
713
+ min-inline-size: 100%;
714
+ inline-size: max-content;
715
+ font: inherit;
716
+ }
717
+ .op-codeviewer.is-wrapped .op-codeviewer__code {
718
+ inline-size: auto;
719
+ white-space: pre-wrap;
720
+ overflow-wrap: anywhere;
721
+ }
722
+ .op-codeviewer__line {
723
+ position: relative;
724
+ display: block;
725
+ margin-inline: calc(var(--op-space-4) * -1);
726
+ padding-inline: var(--op-space-4);
727
+ }
728
+ .op-codeviewer__line.is-marked {
729
+ background: var(--op-codeviewer-mark-bg, var(--op-color-selected));
730
+ box-shadow: inset calc(var(--op-border-width) * 3) 0 0 var(--op-color-primary);
731
+ }
732
+ /* line numbers: a CSS counter in the gutter, never part of the text (selection and screen readers skip it) */
733
+ .op-codeviewer.has-numbers .op-codeviewer__line {
734
+ padding-inline-start: calc(var(--op-space-4) + var(--op-codeviewer-gutter, 2ch) + var(--op-codeviewer-gutter-gap));
735
+ }
736
+ .op-codeviewer.has-numbers .op-codeviewer__line::before {
737
+ counter-increment: op-codeline;
738
+ content: counter(op-codeline);
739
+ position: absolute;
740
+ inset-inline-start: var(--op-space-4);
741
+ inline-size: var(--op-codeviewer-gutter, 2ch);
742
+ color: var(--op-codeviewer-gutter-fg, var(--op-color-fg-muted));
743
+ text-align: end;
744
+ user-select: none;
745
+ }
746
+ /* syntax colors are pulled towards the text color, so they keep their contrast in every theme */
747
+ .op-codeviewer__tok--keyword {
748
+ color: var(--op-codeviewer-keyword, color-mix(in srgb, var(--op-color-primary) 80%, var(--op-color-fg)));
749
+ font-weight: var(--op-font-weight-bold);
750
+ }
751
+ .op-codeviewer__tok--string {
752
+ color: var(--op-codeviewer-string, color-mix(in srgb, var(--op-color-success) 70%, var(--op-color-fg)));
753
+ }
754
+ .op-codeviewer__tok--comment {
755
+ color: var(--op-codeviewer-comment, var(--op-color-fg-muted));
756
+ font-style: italic;
757
+ }
758
+ .op-codeviewer__tok--number {
759
+ color: var(--op-codeviewer-number, color-mix(in srgb, var(--op-color-warning) 65%, var(--op-color-fg)));
760
+ }
761
+ .op-codeviewer__tok--property,
762
+ .op-codeviewer__tok--attr {
763
+ color: var(--op-codeviewer-property, color-mix(in srgb, var(--op-color-info) 70%, var(--op-color-fg)));
764
+ }
765
+ .op-codeviewer__tok--tag {
766
+ color: var(--op-codeviewer-tag, color-mix(in srgb, var(--op-color-danger) 70%, var(--op-color-fg)));
767
+ }
768
+ }
769
+
770
+ @layer optikos {
771
+ .op-icon {
772
+ display: inline-flex;
773
+ flex: none;
774
+ align-items: center;
775
+ justify-content: center;
776
+ inline-size: var(--op-icon-size);
777
+ block-size: var(--op-icon-size);
778
+ line-height: 1;
779
+ }
780
+ .op-icon > svg {
781
+ inline-size: 100%;
782
+ block-size: 100%;
783
+ stroke-width: var(--op-icon-stroke);
784
+ }
785
+ }
786
+
787
+ @layer optikos {
788
+ .op-label {
789
+ color: var(--op-label-fg, var(--op-color-fg));
790
+ }
791
+ .op-label--muted {
792
+ color: var(--op-label-muted-fg, var(--op-color-fg-muted));
793
+ }
794
+ .op-label--title {
795
+ font-size: var(--op-label-title-size, var(--op-font-size-lg));
796
+ font-weight: var(--op-label-title-weight, var(--op-font-weight-bold));
797
+ }
798
+ }
799
+
800
+ @layer optikos {
801
+ :root {
802
+ --op-chat-max-width: 75%;
803
+ --op-chat-input-max-height: 8rem;
804
+ --op-chat-dot-size: 0.4rem;
805
+ --op-chat-reply-bg: rgb(0 0 0 / 0.07);
806
+ }
807
+ .op-chat {
808
+ display: flex;
809
+ flex-direction: column;
810
+ min-inline-size: 0;
811
+ min-block-size: 0;
812
+ color: var(--op-color-fg);
813
+ background: var(--op-chat-bg, var(--op-color-bg));
814
+ }
815
+ .op-chat__log {
816
+ display: flex;
817
+ flex: 1;
818
+ flex-direction: column;
819
+ gap: var(--op-chat-gap, var(--op-space-1));
820
+ min-block-size: 0;
821
+ padding: var(--op-space-3) var(--op-space-4);
822
+ overflow: auto;
823
+ }
824
+ .op-chat__log:focus-visible {
825
+ outline: var(--op-focus-width) solid var(--op-color-focus);
826
+ outline-offset: calc(var(--op-focus-width) * -1);
827
+ }
828
+ .op-chat__empty {
829
+ margin: auto;
830
+ color: var(--op-color-fg-muted);
831
+ }
832
+ .op-chat__empty[hidden] {
833
+ display: none;
834
+ }
835
+ .op-chat__day {
836
+ display: flex;
837
+ justify-content: center;
838
+ margin-block: var(--op-space-3);
839
+ }
840
+ .op-chat__day > span {
841
+ padding: var(--op-space-1) var(--op-space-3);
842
+ color: var(--op-chat-day-fg, var(--op-color-fg-muted));
843
+ background: var(--op-chat-day-bg, var(--op-color-surface-2));
844
+ border-radius: var(--op-radius);
845
+ font-size: var(--op-font-size-sm);
846
+ }
847
+ .op-chat__msg {
848
+ display: flex;
849
+ max-inline-size: 100%;
850
+ }
851
+ .op-chat__msg.is-me {
852
+ justify-content: flex-end;
853
+ }
854
+ .op-chat__msg.is-first {
855
+ margin-block-start: var(--op-space-2);
856
+ }
857
+ .op-chat__bubble {
858
+ box-sizing: border-box;
859
+ max-inline-size: var(--op-chat-max-width);
860
+ padding: var(--op-space-2) var(--op-space-3);
861
+ overflow-wrap: anywhere;
862
+ color: var(--op-chat-bubble-them-fg, var(--op-color-fg));
863
+ background: var(--op-chat-bubble-them-bg, var(--op-color-surface));
864
+ border-radius: var(--op-chat-bubble-radius, var(--op-radius-lg));
865
+ box-shadow: var(--op-chat-bubble-shadow, var(--op-shadow-sm));
866
+ }
867
+ .op-chat__msg.is-me .op-chat__bubble {
868
+ color: var(--op-chat-bubble-me-fg, var(--op-color-primary-fg));
869
+ background: var(--op-chat-bubble-me-bg, var(--op-color-primary));
870
+ }
871
+ /* inside a run the corners next to the neighbour are squared, like a stack of bubbles */
872
+ .op-chat__msg.is-them:not(.is-first) .op-chat__bubble {
873
+ border-start-start-radius: var(--op-radius-sm);
874
+ }
875
+ .op-chat__msg.is-them:not(.is-last) .op-chat__bubble {
876
+ border-end-start-radius: var(--op-radius-sm);
877
+ }
878
+ .op-chat__msg.is-me:not(.is-first) .op-chat__bubble {
879
+ border-start-end-radius: var(--op-radius-sm);
880
+ }
881
+ .op-chat__msg.is-me:not(.is-last) .op-chat__bubble {
882
+ border-end-end-radius: var(--op-radius-sm);
883
+ }
884
+ .op-chat__author {
885
+ font-size: var(--op-font-size-sm);
886
+ font-weight: var(--op-font-weight-bold);
887
+ }
888
+ .op-chat__author[hidden] {
889
+ display: none;
890
+ }
891
+ .op-chat__reply {
892
+ margin-block-end: var(--op-space-1);
893
+ padding: var(--op-space-1) var(--op-space-2);
894
+ border-inline-start: var(--op-space-1) solid currentColor;
895
+ border-radius: var(--op-radius-sm);
896
+ background: var(--op-chat-reply-bg);
897
+ font-size: var(--op-font-size-sm);
898
+ opacity: 0.85;
899
+ }
900
+ .op-chat__reply strong {
901
+ display: block;
902
+ }
903
+ .op-chat__code {
904
+ padding: 0 var(--op-space-1);
905
+ font-family: var(--op-font-mono);
906
+ background: var(--op-chat-reply-bg);
907
+ border-radius: var(--op-radius-sm);
908
+ }
909
+ .op-chat__meta {
910
+ display: inline-flex;
911
+ float: inline-end;
912
+ align-items: center;
913
+ gap: var(--op-space-1);
914
+ margin-inline-start: var(--op-space-3);
915
+ margin-block-start: var(--op-space-2);
916
+ font-size: var(--op-font-size-sm);
917
+ }
918
+ .op-chat__status {
919
+ display: inline-flex;
920
+ }
921
+ .op-chat__status .op-icon:nth-child(2) {
922
+ margin-inline-start: calc(var(--op-icon-size) * -0.6);
923
+ }
924
+ .op-chat__status.is-read {
925
+ color: var(--op-chat-read-fg, var(--op-color-info));
926
+ opacity: 1;
927
+ }
928
+ .op-chat__status.is-error {
929
+ color: var(--op-color-danger);
930
+ }
931
+ .op-chat__status.is-sending::before {
932
+ content: '…';
933
+ }
934
+ .op-chat__typing {
935
+ display: inline-flex;
936
+ align-items: center;
937
+ align-self: flex-start;
938
+ gap: var(--op-space-2);
939
+ padding: var(--op-space-2) var(--op-space-3);
940
+ color: var(--op-color-fg-muted);
941
+ background: var(--op-chat-bubble-them-bg, var(--op-color-surface));
942
+ border-radius: var(--op-chat-bubble-radius, var(--op-radius-lg));
943
+ font-size: var(--op-font-size-sm);
944
+ }
945
+ .op-chat__typing[hidden] {
946
+ display: none;
947
+ }
948
+ .op-chat__dots {
949
+ display: inline-flex;
950
+ gap: var(--op-space-1);
951
+ }
952
+ .op-chat__dots i {
953
+ inline-size: var(--op-chat-dot-size);
954
+ block-size: var(--op-chat-dot-size);
955
+ background: currentColor;
956
+ border-radius: var(--op-radius-pill);
957
+ animation: op-chat-dot calc(var(--op-duration) * 10) infinite ease-in-out both;
958
+ }
959
+ .op-chat__dots i:nth-child(2) {
960
+ animation-delay: calc(var(--op-duration) * 1.5);
961
+ }
962
+ .op-chat__dots i:nth-child(3) {
963
+ animation-delay: calc(var(--op-duration) * 3);
964
+ }
965
+ @keyframes op-chat-dot {
966
+ 0%,
967
+ 80%,
968
+ 100% {
969
+ opacity: 0.25;
970
+ }
971
+ 40% {
972
+ opacity: 1;
973
+ }
974
+ }
975
+ .op-chat__suggestions {
976
+ display: flex;
977
+ flex: none;
978
+ flex-wrap: wrap;
979
+ gap: var(--op-space-2);
980
+ padding: var(--op-space-2) var(--op-space-4) 0;
981
+ }
982
+ .op-chat__suggestions[hidden] {
983
+ display: none;
984
+ }
985
+ .op-chat__chip {
986
+ padding: var(--op-space-1) var(--op-space-3);
987
+ font: inherit;
988
+ color: var(--op-chat-chip-fg, var(--op-color-primary));
989
+ background: var(--op-chat-chip-bg, var(--op-color-surface));
990
+ border: var(--op-border-width) solid var(--op-chat-chip-border, var(--op-color-primary));
991
+ border-radius: var(--op-radius-pill);
992
+ cursor: pointer;
993
+ }
994
+ .op-chat__chip:hover:not(:disabled) {
995
+ background: var(--op-color-primary-soft);
996
+ }
997
+ .op-chat__chip:disabled {
998
+ color: var(--op-color-disabled-fg);
999
+ border-color: var(--op-color-border);
1000
+ cursor: not-allowed;
1001
+ }
1002
+ .op-chat__composer {
1003
+ display: flex;
1004
+ flex: none;
1005
+ align-items: flex-end;
1006
+ gap: var(--op-space-2);
1007
+ padding: var(--op-space-3) var(--op-space-4);
1008
+ background: var(--op-chat-composer-bg, var(--op-color-surface));
1009
+ border-block-start: var(--op-border-width) solid var(--op-color-border);
1010
+ }
1011
+ .op-chat__input {
1012
+ flex: 1;
1013
+ box-sizing: border-box;
1014
+ min-block-size: var(--op-control-height);
1015
+ max-block-size: var(--op-chat-input-max-height);
1016
+ padding: var(--op-space-2) var(--op-control-padding-x);
1017
+ font: inherit;
1018
+ color: var(--op-color-fg);
1019
+ background: var(--op-chat-input-bg, var(--op-color-surface));
1020
+ border: var(--op-border-width) solid var(--op-color-border-strong);
1021
+ border-radius: var(--op-chat-input-radius, var(--op-radius));
1022
+ resize: none;
1023
+ }
1024
+ .op-chat__input:focus {
1025
+ outline: var(--op-focus-width) solid var(--op-color-focus);
1026
+ outline-offset: 0;
1027
+ }
1028
+ .op-chat.is-readonly .op-chat__composer {
1029
+ display: none;
1030
+ }
1031
+ }
1032
+
1033
+ @layer optikos {
1034
+ /* the editor fills the cell: no label, no error line, the row height */
1035
+ .op-grid__cell.is-editing {
1036
+ position: relative;
1037
+ padding-block: 0;
1038
+ padding-inline: var(--op-grid-editor-inset, var(--op-space-1));
1039
+ overflow: visible;
1040
+ }
1041
+ .op-grid__editor {
1042
+ inline-size: 100%;
1043
+ }
1044
+ .op-grid__editor .op-textfield__input {
1045
+ min-block-size: 0;
1046
+ block-size: calc(var(--op-grid-row-height, var(--op-row-height)) - 2 * var(--op-space-1));
1047
+ }
1048
+ .op-grid__editor.is-invalid .op-textfield__input {
1049
+ border-color: var(--op-color-danger);
1050
+ }
1051
+ .op-grid__editor .op-field__error {
1052
+ position: absolute;
1053
+ z-index: 1;
1054
+ inset-block-start: 100%;
1055
+ padding: var(--op-space-1) var(--op-space-2);
1056
+ color: var(--op-color-danger-fg);
1057
+ background: var(--op-color-danger);
1058
+ border-radius: var(--op-radius-sm);
1059
+ font-size: var(--op-font-size-sm);
1060
+ white-space: nowrap;
1061
+ }
1062
+ .op-grid__editor .op-field__error:empty {
1063
+ display: none;
1064
+ }
1065
+ }
1066
+
1067
+ @layer optikos {
1068
+ :root {
1069
+ --op-dataview-item-width: 10rem;
1070
+ --op-dataview-gap: var(--op-space-3);
1071
+ --op-dataview-ring-width: 0.1875rem;
1072
+ }
1073
+ .op-dataview {
1074
+ display: flex;
1075
+ flex-direction: column;
1076
+ gap: var(--op-space-3);
1077
+ min-inline-size: 0;
1078
+ min-block-size: 0;
1079
+ overflow: auto;
1080
+ }
1081
+ .op-dataview__items {
1082
+ display: grid;
1083
+ grid-template-columns: repeat(auto-fill, minmax(var(--op-dataview-item-width), 1fr));
1084
+ /* every row is as tall as the tallest card, so rows line up whatever each card's text does */
1085
+ grid-auto-rows: 1fr;
1086
+ gap: var(--op-dataview-gap);
1087
+ padding: var(--op-space-1);
1088
+ }
1089
+ .op-dataview__item {
1090
+ position: relative;
1091
+ min-inline-size: 0;
1092
+ border-radius: var(--op-dataview-item-radius, var(--op-radius));
1093
+ display: flex;
1094
+ flex-direction: column;
1095
+ cursor: pointer;
1096
+ user-select: none;
1097
+ }
1098
+ /* the card fills its cell: a short card stretches to the row instead of leaving a gap under it */
1099
+ .op-dataview__item > * {
1100
+ flex: 1;
1101
+ min-block-size: 0;
1102
+ }
1103
+ .op-dataview__item:focus-visible {
1104
+ outline: var(--op-focus-width) solid var(--op-color-focus);
1105
+ outline-offset: var(--op-focus-offset);
1106
+ }
1107
+ .op-dataview__item.is-selected {
1108
+ box-shadow: 0 0 0 var(--op-dataview-ring-width) var(--op-dataview-selected-ring, var(--op-color-primary));
1109
+ }
1110
+ .op-dataview__empty {
1111
+ padding: var(--op-space-6);
1112
+ color: var(--op-color-fg-muted);
1113
+ text-align: center;
1114
+ }
1115
+ .op-dataview__empty[hidden] {
1116
+ display: none;
1117
+ }
1118
+ .op-dataview__pager {
1119
+ flex: none;
1120
+ padding: var(--op-space-2);
1121
+ }
1122
+ }
1123
+
1124
+ @layer optikos {
1125
+ :root {
1126
+ --op-filterbuilder-gap: var(--op-space-2);
1127
+ --op-filterbuilder-group-padding: var(--op-space-3);
1128
+ --op-filterbuilder-value-width: 8rem;
1129
+ --op-filterbuilder-value-max-width: 18rem;
1130
+ --op-filterbuilder-chips-max-height: 6rem;
1131
+ --op-filterbuilder-nested-bg: var(--op-color-surface-2);
1132
+ }
1133
+ .op-filterbuilder {
1134
+ display: flex;
1135
+ flex-direction: column;
1136
+ gap: var(--op-filterbuilder-gap);
1137
+ min-inline-size: 0;
1138
+ }
1139
+ .op-filterbuilder__group {
1140
+ display: flex;
1141
+ flex-direction: column;
1142
+ gap: var(--op-filterbuilder-gap);
1143
+ }
1144
+ .op-filterbuilder__group.is-nested {
1145
+ padding: var(--op-filterbuilder-group-padding);
1146
+ background: var(--op-filterbuilder-nested-bg);
1147
+ border: var(--op-border-width) solid var(--op-color-border);
1148
+ border-radius: var(--op-radius);
1149
+ }
1150
+ .op-filterbuilder__head,
1151
+ .op-filterbuilder__row {
1152
+ display: flex;
1153
+ flex-wrap: wrap;
1154
+ align-items: center;
1155
+ gap: var(--op-filterbuilder-gap);
1156
+ }
1157
+ .op-filterbuilder__value {
1158
+ flex: 1 1 var(--op-filterbuilder-value-width);
1159
+ min-inline-size: 0;
1160
+ max-inline-size: var(--op-filterbuilder-value-max-width);
1161
+ }
1162
+ /* a validation message hangs below the field instead of making the row taller (and the controls beside it jump) */
1163
+ .op-filterbuilder__value {
1164
+ position: relative;
1165
+ }
1166
+ .op-filterbuilder__value > .op-field__error {
1167
+ position: absolute;
1168
+ inset-block-start: 100%;
1169
+ inset-inline-start: 0;
1170
+ z-index: 1;
1171
+ margin: 0;
1172
+ white-space: nowrap;
1173
+ font-size: var(--op-font-size-sm);
1174
+ }
1175
+ .op-filterbuilder__row:has(.op-field__error:not(:empty)) {
1176
+ margin-block-end: var(--op-space-4);
1177
+ }
1178
+ .op-filterbuilder__to {
1179
+ color: var(--op-color-fg-muted);
1180
+ }
1181
+ .op-filterbuilder__none {
1182
+ color: var(--op-color-fg-muted);
1183
+ }
1184
+ .op-filterbuilder__select {
1185
+ min-block-size: var(--op-control-height);
1186
+ padding-inline: var(--op-control-padding-x);
1187
+ font: inherit;
1188
+ color: var(--op-color-fg);
1189
+ background: var(--op-color-surface);
1190
+ border: var(--op-border-width) solid var(--op-color-border);
1191
+ border-radius: var(--op-radius);
1192
+ }
1193
+ .op-filterbuilder__select:focus-visible,
1194
+ .op-filterbuilder__remove:focus-visible {
1195
+ outline: var(--op-focus-width) solid var(--op-color-focus);
1196
+ outline-offset: 0;
1197
+ }
1198
+ .op-filterbuilder__remove {
1199
+ display: inline-flex;
1200
+ padding: var(--op-space-1);
1201
+ color: var(--op-color-fg-muted);
1202
+ background: transparent;
1203
+ border: 0;
1204
+ border-radius: var(--op-radius-sm);
1205
+ cursor: pointer;
1206
+ }
1207
+ .op-filterbuilder__remove:hover {
1208
+ color: var(--op-color-danger);
1209
+ background: var(--op-color-hover);
1210
+ }
1211
+ .op-filterbuilder__foot {
1212
+ display: flex;
1213
+ justify-content: flex-end;
1214
+ }
1215
+ .op-filterbuilder__chips {
1216
+ display: flex;
1217
+ flex-wrap: wrap;
1218
+ gap: var(--op-space-1);
1219
+ max-block-size: var(--op-filterbuilder-chips-max-height);
1220
+ overflow: auto;
1221
+ }
1222
+ .op-filterbuilder__chip {
1223
+ display: inline-flex;
1224
+ align-items: center;
1225
+ padding: var(--op-space-1) var(--op-space-3);
1226
+ color: var(--op-color-fg);
1227
+ background: var(--op-color-surface);
1228
+ border: var(--op-border-width) solid var(--op-color-border);
1229
+ border-radius: var(--op-radius-pill);
1230
+ cursor: pointer;
1231
+ }
1232
+ .op-filterbuilder__chip:hover {
1233
+ background: var(--op-color-hover);
1234
+ }
1235
+ .op-filterbuilder__chip:has(:checked) {
1236
+ color: var(--op-filterbuilder-chip-on-fg, var(--op-color-primary));
1237
+ background: var(--op-color-primary-soft);
1238
+ border-color: var(--op-color-primary);
1239
+ }
1240
+ .op-filterbuilder__chip:has(:focus-visible) {
1241
+ outline: var(--op-focus-width) solid var(--op-color-focus);
1242
+ }
1243
+ .op-filterbuilder__chipbox {
1244
+ position: absolute;
1245
+ opacity: 0;
1246
+ pointer-events: none;
1247
+ }
1248
+ }
1249
+
1250
+ @layer optikos {
1251
+ :root {
1252
+ --op-grid-colmenu-width: 14rem;
1253
+ --op-grid-colmenu-height: 20rem;
1254
+ --op-grid-drop-width: 0.1875rem;
1255
+ --op-grid-resizer-width: 0.5rem;
1256
+ --op-grid-group-tracking: 0.05em;
1257
+ --op-grid-action-size: 2rem;
1258
+ --op-grid-action-gap: var(--op-space-1);
1259
+ --op-grid-action-idle-opacity: 0.45;
1260
+ --op-grid-action-disabled-opacity: 0.3;
1261
+ --op-grid-selected-bar-width: 0.125rem;
1262
+ }
1263
+ .op-grid {
1264
+ --_border: var(--op-grid-border, var(--op-color-border));
1265
+ display: flex;
1266
+ flex-direction: column;
1267
+ position: relative;
1268
+ min-inline-size: 0;
1269
+ min-block-size: 0;
1270
+ color: var(--op-grid-fg, var(--op-color-fg));
1271
+ background: var(--op-grid-bg, var(--op-color-surface));
1272
+ border: var(--op-border-width) solid var(--_border);
1273
+ border-radius: var(--op-grid-radius, var(--op-radius));
1274
+ overflow: hidden;
1275
+ }
1276
+ /* header + rows: the focusable role=grid part, between the bulk bar and the pager */
1277
+ .op-grid__table {
1278
+ display: flex;
1279
+ flex: 1 1 auto;
1280
+ flex-direction: column;
1281
+ position: relative;
1282
+ min-inline-size: 0;
1283
+ min-block-size: 0;
1284
+ }
1285
+ .op-grid__table:focus-visible {
1286
+ outline: var(--op-focus-width) solid var(--op-color-focus);
1287
+ outline-offset: calc(var(--op-focus-width) * -1);
1288
+ }
1289
+ .op-grid__header {
1290
+ position: relative;
1291
+ flex: none;
1292
+ overflow: hidden;
1293
+ color: var(--op-grid-header-fg, var(--op-color-fg));
1294
+ background: var(--op-grid-header-bg, var(--op-color-surface-2));
1295
+ border-block-end: var(--op-border-width) solid var(--op-grid-header-border, var(--op-color-border-strong));
1296
+ font-weight: var(--op-font-weight-bold);
1297
+ }
1298
+ .op-grid__row {
1299
+ display: grid;
1300
+ grid-template-columns: var(--op-grid-cols);
1301
+ box-sizing: border-box;
1302
+ min-inline-size: var(--op-grid-min-width);
1303
+ }
1304
+ .op-grid__header-row {
1305
+ min-block-size: var(--op-grid-row-height, var(--op-row-height));
1306
+ }
1307
+ .op-grid__viewport {
1308
+ flex: 1;
1309
+ min-block-size: 0;
1310
+ overflow: auto;
1311
+ }
1312
+ .op-grid__body-row {
1313
+ border-block-end: var(--op-border-width) solid var(--_border);
1314
+ cursor: default;
1315
+ }
1316
+ .op-grid__body-row:hover {
1317
+ background: var(--op-grid-row-hover-bg, var(--op-color-hover));
1318
+ }
1319
+ .op-grid--striped .op-grid__body-row.is-odd {
1320
+ background: var(--op-grid-row-stripe-bg, var(--op-color-surface-2));
1321
+ }
1322
+ .op-grid__body-row.is-selected {
1323
+ background: var(--op-grid-row-selected-bg, var(--op-color-selected));
1324
+ box-shadow: inset var(--op-grid-selected-bar-width) 0 0 var(--op-grid-selected-bar, var(--op-color-primary));
1325
+ }
1326
+ .op-grid__body-row.is-active {
1327
+ outline: var(--op-focus-width) solid var(--op-color-focus);
1328
+ outline-offset: calc(var(--op-focus-width) * -1);
1329
+ }
1330
+ .op-grid__cell {
1331
+ display: flex;
1332
+ align-items: center;
1333
+ min-inline-size: 0;
1334
+ padding-inline: var(--op-grid-cell-padding-x, var(--op-control-padding-x));
1335
+ overflow: hidden;
1336
+ text-overflow: ellipsis;
1337
+ white-space: nowrap;
1338
+ }
1339
+ .op-grid__cell--right {
1340
+ justify-content: flex-end;
1341
+ text-align: end;
1342
+ }
1343
+ .op-grid__cell--center {
1344
+ justify-content: center;
1345
+ }
1346
+ .op-grid__sort {
1347
+ text-transform: inherit;
1348
+ letter-spacing: inherit;
1349
+ display: inline-flex;
1350
+ align-items: center;
1351
+ gap: var(--op-space-1);
1352
+ padding: 0;
1353
+ font: inherit;
1354
+ color: inherit;
1355
+ background: transparent;
1356
+ border: 0;
1357
+ cursor: pointer;
1358
+ }
1359
+ .op-grid__arrow {
1360
+ display: inline-flex;
1361
+ opacity: 0;
1362
+ transition: transform var(--op-duration) var(--op-easing);
1363
+ }
1364
+ .op-grid__hcell.is-sortable:hover .op-grid__arrow {
1365
+ opacity: 0.4;
1366
+ }
1367
+ .op-grid__hcell.is-sorted-asc .op-grid__arrow,
1368
+ .op-grid__hcell.is-sorted-desc .op-grid__arrow {
1369
+ opacity: 1;
1370
+ }
1371
+ .op-grid__hcell.is-sorted-desc .op-grid__arrow {
1372
+ transform: rotate(180deg);
1373
+ }
1374
+ .op-grid__empty {
1375
+ padding: var(--op-space-5);
1376
+ text-align: center;
1377
+ color: var(--op-color-fg-muted);
1378
+ }
1379
+ .op-grid__pager {
1380
+ flex: none;
1381
+ padding: var(--op-space-2);
1382
+ border-block-start: var(--op-border-width) solid var(--_border);
1383
+ }
1384
+ .op-grid .op-virtual {
1385
+ min-inline-size: var(--op-grid-min-width);
1386
+ }
1387
+ .op-grid__check {
1388
+ margin: 0;
1389
+ accent-color: var(--op-grid-check-accent, var(--op-color-primary));
1390
+ cursor: pointer;
1391
+ }
1392
+ /* the checkbox and action columns are narrow: the frame gives them their own padding instead of the text-cell one */
1393
+ .op-grid__selcell,
1394
+ .op-grid__actcell {
1395
+ padding-inline: var(--op-grid-action-gap);
1396
+ }
1397
+ .op-grid__actcell {
1398
+ justify-content: flex-end;
1399
+ gap: var(--op-grid-action-gap);
1400
+ }
1401
+ .op-grid__actbtn {
1402
+ display: inline-flex;
1403
+ align-items: center;
1404
+ justify-content: center;
1405
+ box-sizing: border-box;
1406
+ min-inline-size: var(--op-grid-action-size);
1407
+ block-size: var(--op-grid-action-size);
1408
+ padding: var(--op-space-1);
1409
+ font: inherit;
1410
+ font-size: var(--op-font-size-sm);
1411
+ color: var(--op-color-fg-muted);
1412
+ background: transparent;
1413
+ border: 0;
1414
+ border-radius: var(--op-radius-sm);
1415
+ cursor: pointer;
1416
+ }
1417
+ .op-grid__actbtn:hover {
1418
+ color: var(--op-color-fg);
1419
+ background: var(--op-color-hover);
1420
+ }
1421
+ .op-grid__bar {
1422
+ display: flex;
1423
+ flex: none;
1424
+ align-items: center;
1425
+ justify-content: space-between;
1426
+ gap: var(--op-space-2);
1427
+ min-block-size: var(--op-grid-row-height, var(--op-row-height));
1428
+ padding-inline: var(--op-space-2);
1429
+ background: var(--op-grid-bar-bg, var(--op-color-surface));
1430
+ border-block-end: var(--op-border-width) solid var(--_border);
1431
+ }
1432
+ .op-grid__bulk {
1433
+ display: flex;
1434
+ flex-wrap: wrap;
1435
+ align-items: center;
1436
+ gap: var(--op-space-2);
1437
+ }
1438
+ .op-grid__bulk[hidden] {
1439
+ display: none;
1440
+ }
1441
+ .op-grid__count {
1442
+ font-weight: var(--op-font-weight-bold);
1443
+ }
1444
+ .op-grid__bar > .op-button {
1445
+ margin-inline-start: auto;
1446
+ }
1447
+ .op-grid__colmenu {
1448
+ display: flex;
1449
+ flex-direction: column;
1450
+ gap: var(--op-space-2);
1451
+ min-inline-size: var(--op-grid-colmenu-width);
1452
+ max-block-size: var(--op-grid-colmenu-height);
1453
+ padding: var(--op-space-2);
1454
+ }
1455
+ .op-grid__collist {
1456
+ display: flex;
1457
+ flex-direction: column;
1458
+ overflow: auto;
1459
+ }
1460
+ .op-grid__colitem {
1461
+ display: flex;
1462
+ align-items: center;
1463
+ gap: var(--op-space-2);
1464
+ padding: var(--op-space-1) var(--op-space-2);
1465
+ border-radius: var(--op-radius-sm);
1466
+ cursor: pointer;
1467
+ }
1468
+ .op-grid__colitem:hover {
1469
+ background: var(--op-color-hover);
1470
+ }
1471
+ .op-grid__colitem[hidden],
1472
+ .op-grid__colempty[hidden] {
1473
+ display: none;
1474
+ }
1475
+ .op-grid__colempty {
1476
+ padding: var(--op-space-2);
1477
+ color: var(--op-color-fg-muted);
1478
+ text-align: center;
1479
+ }
1480
+ /* visible mode: always there, dimmed until the row is hovered, active or selected */
1481
+ .op-grid--actions-visible .op-grid__actbtn {
1482
+ opacity: var(--op-grid-action-idle-opacity);
1483
+ }
1484
+ .op-grid--actions-visible .op-grid__body-row:hover .op-grid__actbtn,
1485
+ .op-grid--actions-visible .op-grid__body-row.is-active .op-grid__actbtn,
1486
+ .op-grid--actions-visible .op-grid__body-row.is-selected .op-grid__actbtn,
1487
+ .op-grid--actions-visible .op-grid__actbtn:focus-visible {
1488
+ opacity: 1;
1489
+ }
1490
+ .op-grid__actbtn.is-danger:hover {
1491
+ color: var(--op-color-danger);
1492
+ }
1493
+ .op-grid__actbtn:disabled {
1494
+ opacity: var(--op-grid-action-disabled-opacity);
1495
+ cursor: not-allowed;
1496
+ }
1497
+ /* column drag: grab cursor, a ghost label under the pointer and a bar where the column will land */
1498
+ .op-grid--reorderable .op-grid__hcell.is-reorderable {
1499
+ cursor: grab;
1500
+ user-select: none;
1501
+ touch-action: none;
1502
+ }
1503
+ .op-grid__hcell {
1504
+ position: relative;
1505
+ }
1506
+ /* resize handle: a thin strip on the header's end edge; a hairline shows on hover and while dragging */
1507
+ .op-grid__resizer {
1508
+ position: absolute;
1509
+ inset-block: 0;
1510
+ inset-inline-end: 0;
1511
+ inline-size: var(--op-grid-resizer-width);
1512
+ cursor: col-resize;
1513
+ touch-action: none;
1514
+ z-index: 1;
1515
+ }
1516
+ .op-grid__resizer::after {
1517
+ content: '';
1518
+ position: absolute;
1519
+ inset-block: 25%;
1520
+ inset-inline-end: 0;
1521
+ inline-size: var(--op-border-width);
1522
+ background: var(--op-color-border-strong);
1523
+ }
1524
+ .op-grid__resizer:hover::after,
1525
+ .op-grid.is-resizing .op-grid__resizer:hover::after {
1526
+ inset-block: 0;
1527
+ inline-size: var(--op-grid-drop-width);
1528
+ background: var(--op-color-primary);
1529
+ }
1530
+ .op-grid.is-resizing {
1531
+ cursor: col-resize;
1532
+ user-select: none;
1533
+ }
1534
+ .op-grid__hcell.is-dragging-col {
1535
+ opacity: 0.4;
1536
+ }
1537
+ .op-grid__ghost {
1538
+ position: fixed;
1539
+ z-index: var(--op-z-layer);
1540
+ padding: var(--op-space-1) var(--op-space-3);
1541
+ color: var(--op-color-fg);
1542
+ background: var(--op-color-surface);
1543
+ border: var(--op-border-width) solid var(--op-color-primary);
1544
+ border-radius: var(--op-radius);
1545
+ box-shadow: var(--op-shadow);
1546
+ pointer-events: none;
1547
+ transform: translate(var(--op-space-2), var(--op-space-2));
1548
+ font-weight: var(--op-font-weight-bold);
1549
+ white-space: nowrap;
1550
+ }
1551
+ .op-grid__drop {
1552
+ position: absolute;
1553
+ inset-block: 0;
1554
+ inline-size: var(--op-grid-drop-width);
1555
+ margin-inline-start: calc(var(--op-grid-drop-width) / -2);
1556
+ background: var(--op-color-primary);
1557
+ pointer-events: none;
1558
+ }
1559
+ /* group band over the header */
1560
+ .op-grid__group-row {
1561
+ min-block-size: 0;
1562
+ }
1563
+ .op-grid__gcell {
1564
+ padding: var(--op-space-1) var(--op-grid-cell-padding-x, var(--op-control-padding-x));
1565
+ overflow: hidden;
1566
+ color: var(--op-grid-group-fg, var(--op-color-fg-muted));
1567
+ background: var(--op-grid-group-bg, var(--op-color-surface-2));
1568
+ border-block-end: var(--op-border-width) solid var(--_border);
1569
+ border-inline-end: var(--op-border-width) solid var(--_border);
1570
+ font-size: var(--op-font-size-sm);
1571
+ letter-spacing: var(--op-grid-group-tracking);
1572
+ text-overflow: ellipsis;
1573
+ text-transform: uppercase;
1574
+ white-space: nowrap;
1575
+ }
1576
+ .op-grid__gcell.is-empty {
1577
+ background: transparent;
1578
+ border-inline-end-color: transparent;
1579
+ }
1580
+ /* column menu: group chips and sections */
1581
+ .op-grid__colchips {
1582
+ display: flex;
1583
+ flex-wrap: wrap;
1584
+ gap: var(--op-space-1);
1585
+ }
1586
+ .op-grid__colchips[hidden],
1587
+ .op-grid__colgroup[hidden] {
1588
+ display: none;
1589
+ }
1590
+ .op-grid__colchip {
1591
+ padding: 0 var(--op-space-3);
1592
+ font: inherit;
1593
+ font-size: var(--op-font-size-sm);
1594
+ color: var(--op-color-fg-muted);
1595
+ background: transparent;
1596
+ border: var(--op-border-width) solid var(--op-color-border);
1597
+ border-radius: var(--op-radius-pill);
1598
+ cursor: pointer;
1599
+ }
1600
+ .op-grid__colchip.is-on {
1601
+ color: var(--op-color-primary-fg);
1602
+ background: var(--op-color-primary);
1603
+ border-color: var(--op-color-primary);
1604
+ }
1605
+ .op-grid__colgroup {
1606
+ display: flex;
1607
+ align-items: center;
1608
+ justify-content: space-between;
1609
+ gap: var(--op-space-2);
1610
+ padding: var(--op-space-1) var(--op-space-2);
1611
+ margin-block-start: var(--op-space-1);
1612
+ color: var(--op-color-fg-muted);
1613
+ border-block-end: var(--op-border-width) solid var(--op-color-border);
1614
+ font-size: var(--op-font-size-sm);
1615
+ font-weight: var(--op-font-weight-bold);
1616
+ text-transform: uppercase;
1617
+ }
1618
+ .op-grid__colgroup label {
1619
+ display: flex;
1620
+ align-items: center;
1621
+ gap: var(--op-space-2);
1622
+ cursor: pointer;
1623
+ }
1624
+ .op-grid__colgroup ~ .op-grid__colitem {
1625
+ padding-inline-start: var(--op-space-4);
1626
+ }
1627
+ }
1628
+
1629
+ @layer optikos {
1630
+ .op-pagination {
1631
+ display: flex;
1632
+ flex-wrap: wrap;
1633
+ align-items: center;
1634
+ gap: var(--op-pagination-gap, var(--op-space-1));
1635
+ color: var(--op-color-fg);
1636
+ }
1637
+ .op-pagination__btn.is-current {
1638
+ color: var(--op-color-primary-fg);
1639
+ background: var(--op-color-primary);
1640
+ }
1641
+ .op-pagination__gap {
1642
+ padding-inline: var(--op-space-1);
1643
+ color: var(--op-color-fg-muted);
1644
+ }
1645
+ .op-pagination__info {
1646
+ margin-inline-start: auto;
1647
+ padding-inline-start: var(--op-space-3);
1648
+ color: var(--op-color-fg-muted);
1649
+ font-size: var(--op-font-size-sm);
1650
+ }
1651
+ }
1652
+
1653
+ @layer optikos {
1654
+ :root {
1655
+ --op-searchgrid-gap: var(--op-space-3);
1656
+ --op-searchgrid-filters-padding: 0;
1657
+ --op-searchgrid-field-width: 12rem;
1658
+ --op-searchgrid-grid-min-height: 12rem;
1659
+ }
1660
+ .op-searchgrid {
1661
+ display: flex;
1662
+ flex-direction: column;
1663
+ gap: var(--op-searchgrid-gap);
1664
+ block-size: 100%;
1665
+ min-block-size: 0;
1666
+ }
1667
+ .op-searchgrid__filters {
1668
+ display: flex;
1669
+ flex: none;
1670
+ flex-wrap: wrap;
1671
+ align-items: flex-end;
1672
+ gap: var(--op-searchgrid-gap);
1673
+ padding: var(--op-searchgrid-filters-padding);
1674
+ background: var(--op-searchgrid-filters-bg, transparent);
1675
+ }
1676
+ .op-searchgrid__filters > .op-field {
1677
+ flex: 1 1 var(--op-searchgrid-field-width);
1678
+ min-inline-size: 0;
1679
+ }
1680
+ .op-searchgrid__buttons {
1681
+ display: flex;
1682
+ gap: var(--op-space-2);
1683
+ margin-inline-start: auto;
1684
+ }
1685
+ .op-searchgrid > .op-grid {
1686
+ flex: 1;
1687
+ min-block-size: var(--op-searchgrid-grid-min-height);
1688
+ }
1689
+ }
1690
+
1691
+ @layer optikos {
1692
+ .op-table {
1693
+ inline-size: 100%;
1694
+ border-collapse: collapse;
1695
+ color: var(--op-color-fg);
1696
+ font-size: var(--op-font-size);
1697
+ }
1698
+ .op-table caption {
1699
+ padding: var(--op-space-2);
1700
+ text-align: start;
1701
+ color: var(--op-color-fg-muted);
1702
+ }
1703
+ .op-table th,
1704
+ .op-table td {
1705
+ padding: var(--op-table-cell-padding-y, var(--op-space-2)) var(--op-table-cell-padding-x, var(--op-space-3));
1706
+ text-align: start;
1707
+ border-block-end: var(--op-border-width) solid var(--op-table-border, var(--op-color-border));
1708
+ }
1709
+ .op-table th {
1710
+ background: var(--op-table-header-bg, var(--op-color-surface-2));
1711
+ font-weight: var(--op-font-weight-bold);
1712
+ }
1713
+ .op-table--striped tbody tr:nth-child(even) {
1714
+ background: var(--op-table-stripe-bg, var(--op-color-surface-2));
1715
+ }
1716
+ .op-table .op-table__cell--right {
1717
+ text-align: end;
1718
+ }
1719
+ .op-table .op-table__cell--center {
1720
+ text-align: center;
1721
+ }
1722
+ .op-table__empty td {
1723
+ text-align: center;
1724
+ color: var(--op-color-fg-muted);
1725
+ }
1726
+ }
1727
+
1728
+ @layer optikos {
1729
+ :root {
1730
+ --op-tree-indent: 1.25rem;
1731
+ --op-tree-check-size: 1rem;
1732
+ --op-tree-check-icon-size: 0.8em;
1733
+ }
1734
+ .op-tree {
1735
+ display: block;
1736
+ min-inline-size: 0;
1737
+ overflow: auto;
1738
+ color: var(--op-tree-fg, var(--op-color-fg));
1739
+ background: var(--op-tree-bg, transparent);
1740
+ }
1741
+ .op-tree__root,
1742
+ .op-tree__group {
1743
+ margin: 0;
1744
+ padding: 0;
1745
+ list-style: none;
1746
+ }
1747
+ .op-tree__item {
1748
+ display: flex;
1749
+ align-items: center;
1750
+ gap: var(--op-space-2);
1751
+ box-sizing: border-box;
1752
+ min-block-size: var(--op-tree-item-height, var(--op-row-height));
1753
+ padding-inline: var(--op-space-1) var(--op-space-3);
1754
+ padding-inline-start: calc(var(--op-space-1) + var(--_level, 0) * var(--op-tree-indent));
1755
+ border-radius: var(--op-radius-sm);
1756
+ cursor: pointer;
1757
+ user-select: none;
1758
+ }
1759
+ .op-tree__item:hover:not(.is-disabled) {
1760
+ background: var(--op-tree-hover-bg, var(--op-color-hover));
1761
+ }
1762
+ .op-tree__item:focus-visible {
1763
+ outline: var(--op-focus-width) solid var(--op-color-focus);
1764
+ outline-offset: calc(var(--op-focus-width) * -1);
1765
+ }
1766
+ .op-tree__item.is-selected {
1767
+ color: var(--op-tree-selected-fg, var(--op-color-fg));
1768
+ background: var(--op-tree-selected-bg, var(--op-color-selected));
1769
+ }
1770
+ .op-tree__item.is-disabled {
1771
+ color: var(--op-color-disabled-fg);
1772
+ cursor: default;
1773
+ }
1774
+ .op-tree__toggle {
1775
+ display: inline-grid;
1776
+ place-items: center;
1777
+ flex: none;
1778
+ inline-size: var(--op-tree-indent);
1779
+ color: var(--op-color-fg-muted);
1780
+ }
1781
+ .op-tree__toggle .op-icon {
1782
+ transition: transform var(--op-duration) var(--op-easing);
1783
+ }
1784
+ .op-tree__item.is-expanded > .op-tree__toggle .op-icon {
1785
+ transform: rotate(90deg);
1786
+ }
1787
+ .op-tree__spinner {
1788
+ --op-spinner-size: var(--op-tree-check-size);
1789
+ }
1790
+ .op-tree__check {
1791
+ display: inline-grid;
1792
+ place-items: center;
1793
+ flex: none;
1794
+ box-sizing: border-box;
1795
+ inline-size: var(--op-tree-check-size);
1796
+ block-size: var(--op-tree-check-size);
1797
+ border: var(--op-border-width) solid var(--op-color-border-strong);
1798
+ border-radius: var(--op-radius-sm);
1799
+ background: var(--op-color-surface);
1800
+ --op-icon-size: var(--op-tree-check-icon-size);
1801
+ }
1802
+ .op-tree__check.is-checked,
1803
+ .op-tree__check.is-mixed {
1804
+ color: var(--op-color-primary-fg);
1805
+ background: var(--op-color-primary);
1806
+ border-color: var(--op-color-primary);
1807
+ }
1808
+ .op-tree__icon {
1809
+ display: inline-flex;
1810
+ color: var(--op-tree-icon-fg, var(--op-color-fg-muted));
1811
+ }
1812
+ .op-tree__text {
1813
+ overflow: hidden;
1814
+ text-overflow: ellipsis;
1815
+ white-space: nowrap;
1816
+ }
1817
+ .op-tree__empty {
1818
+ padding: var(--op-space-3);
1819
+ color: var(--op-color-fg-muted);
1820
+ }
1821
+ }
1822
+
1823
+ @layer optikos {
1824
+ :root {
1825
+ --op-calendar-day-size: 2.25rem;
1826
+ }
1827
+ .op-calendar {
1828
+ box-sizing: border-box;
1829
+ padding: var(--op-calendar-padding, var(--op-space-2));
1830
+ color: var(--op-color-fg);
1831
+ background: var(--op-calendar-bg, var(--op-color-surface));
1832
+ }
1833
+ .op-calendar__header {
1834
+ display: flex;
1835
+ align-items: center;
1836
+ justify-content: space-between;
1837
+ gap: var(--op-space-1);
1838
+ margin-block-end: var(--op-space-2);
1839
+ }
1840
+ .op-calendar__nav,
1841
+ .op-calendar__title,
1842
+ .op-calendar__month {
1843
+ font: inherit;
1844
+ color: inherit;
1845
+ background: transparent;
1846
+ border: 0;
1847
+ border-radius: var(--op-radius);
1848
+ cursor: pointer;
1849
+ }
1850
+ .op-calendar__nav {
1851
+ display: inline-flex;
1852
+ padding: var(--op-space-2);
1853
+ }
1854
+ .op-calendar__title {
1855
+ flex: 1;
1856
+ padding: var(--op-space-2);
1857
+ font-weight: var(--op-font-weight-bold);
1858
+ text-transform: capitalize;
1859
+ }
1860
+ .op-calendar__nav:hover,
1861
+ .op-calendar__title:hover,
1862
+ .op-calendar__month:hover {
1863
+ background: var(--op-color-hover);
1864
+ }
1865
+ .op-calendar__grid {
1866
+ border-collapse: collapse;
1867
+ }
1868
+ .op-calendar__dow {
1869
+ padding-block-end: var(--op-space-1);
1870
+ font-size: var(--op-font-size-sm);
1871
+ font-weight: var(--op-font-weight-medium);
1872
+ color: var(--op-color-fg-muted);
1873
+ text-transform: capitalize;
1874
+ }
1875
+ .op-calendar__day {
1876
+ box-sizing: border-box;
1877
+ inline-size: var(--op-calendar-day-size);
1878
+ block-size: var(--op-calendar-day-size);
1879
+ padding: 0;
1880
+ text-align: center;
1881
+ border-radius: var(--op-radius);
1882
+ cursor: pointer;
1883
+ }
1884
+ .op-calendar__day:hover {
1885
+ background: var(--op-calendar-day-hover-bg, var(--op-color-hover));
1886
+ }
1887
+ .op-calendar__day.is-outside {
1888
+ color: var(--op-calendar-outside-fg, var(--op-color-fg-muted));
1889
+ }
1890
+ .op-calendar__day.is-today {
1891
+ box-shadow: inset 0 0 0 var(--op-border-width) var(--op-calendar-today-border, var(--op-color-primary));
1892
+ }
1893
+ .op-calendar__day.is-selected,
1894
+ .op-calendar__month.is-selected {
1895
+ color: var(--op-calendar-day-selected-fg, var(--op-color-primary-fg));
1896
+ background: var(--op-calendar-day-selected-bg, var(--op-color-primary));
1897
+ }
1898
+ .op-calendar__day.is-in-range {
1899
+ color: var(--op-calendar-range-fg, var(--op-color-fg));
1900
+ background: var(--op-calendar-range-bg, var(--op-color-selected));
1901
+ border-radius: 0;
1902
+ }
1903
+ .op-calendar__day.is-range-start {
1904
+ border-start-end-radius: 0;
1905
+ border-end-end-radius: 0;
1906
+ }
1907
+ .op-calendar__day.is-range-end {
1908
+ border-start-start-radius: 0;
1909
+ border-end-start-radius: 0;
1910
+ }
1911
+ .op-calendar__day.is-disabled {
1912
+ color: var(--op-color-disabled-fg);
1913
+ background: transparent;
1914
+ cursor: not-allowed;
1915
+ text-decoration: line-through;
1916
+ }
1917
+ .op-calendar__day:focus-visible {
1918
+ outline: var(--op-focus-width) solid var(--op-color-focus);
1919
+ outline-offset: 0;
1920
+ }
1921
+ .op-calendar__months {
1922
+ display: grid;
1923
+ grid-template-columns: repeat(3, 1fr);
1924
+ gap: var(--op-space-1);
1925
+ }
1926
+ .op-calendar__month {
1927
+ padding: var(--op-space-3) var(--op-space-2);
1928
+ text-transform: capitalize;
1929
+ }
1930
+ }
1931
+
1932
+ @layer optikos {
1933
+ :root {
1934
+ --op-checkbox-size: 1.125rem;
1935
+ }
1936
+ .op-checkbox__label {
1937
+ display: inline-flex;
1938
+ align-items: center;
1939
+ gap: var(--op-space-2);
1940
+ min-block-size: var(--op-control-height);
1941
+ cursor: pointer;
1942
+ }
1943
+ .op-checkbox__input {
1944
+ position: absolute;
1945
+ opacity: 0;
1946
+ inline-size: 0;
1947
+ block-size: 0;
1948
+ }
1949
+ .op-checkbox__box {
1950
+ position: relative;
1951
+ display: inline-flex;
1952
+ align-items: center;
1953
+ justify-content: center;
1954
+ flex: none;
1955
+ box-sizing: border-box;
1956
+ inline-size: var(--op-checkbox-size);
1957
+ block-size: var(--op-checkbox-size);
1958
+ color: var(--op-checkbox-checked-fg, var(--op-color-primary-fg));
1959
+ background: var(--op-checkbox-bg, var(--op-color-surface));
1960
+ border: var(--op-border-width) solid var(--op-checkbox-border, var(--op-color-border-strong));
1961
+ border-radius: var(--op-checkbox-radius, var(--op-radius-sm));
1962
+ transition: background var(--op-duration) var(--op-easing);
1963
+ }
1964
+ .op-checkbox__box .op-icon {
1965
+ font-size: var(--op-checkbox-size);
1966
+ visibility: hidden;
1967
+ }
1968
+ .op-checkbox__dash {
1969
+ position: absolute;
1970
+ inset-inline: 25%;
1971
+ block-size: var(--op-icon-stroke);
1972
+ background: currentColor;
1973
+ visibility: hidden;
1974
+ }
1975
+ .op-checkbox.is-checked .op-checkbox__box,
1976
+ .op-checkbox.is-indeterminate .op-checkbox__box {
1977
+ background: var(--op-checkbox-checked-bg, var(--op-color-primary));
1978
+ border-color: var(--op-checkbox-checked-bg, var(--op-color-primary));
1979
+ }
1980
+ .op-checkbox.is-checked .op-checkbox__box .op-icon,
1981
+ .op-checkbox.is-indeterminate .op-checkbox__dash {
1982
+ visibility: visible;
1983
+ }
1984
+ .op-checkbox__input:focus-visible + .op-checkbox__box {
1985
+ outline: var(--op-focus-width) solid var(--op-color-focus);
1986
+ outline-offset: var(--op-focus-offset);
1987
+ }
1988
+ .op-checkbox.is-invalid .op-checkbox__box {
1989
+ border-color: var(--op-field-invalid-border, var(--op-color-danger));
1990
+ }
1991
+ .op-checkbox.is-disabled .op-checkbox__label {
1992
+ cursor: not-allowed;
1993
+ color: var(--op-color-disabled-fg);
1994
+ }
1995
+ }
1996
+
1997
+ @layer optikos {
1998
+ .op-checkboxgroup__options {
1999
+ display: flex;
2000
+ flex-direction: column;
2001
+ gap: var(--op-checkboxgroup-gap, var(--op-space-1));
2002
+ }
2003
+ .op-checkboxgroup__options--horizontal {
2004
+ flex-direction: row;
2005
+ flex-wrap: wrap;
2006
+ gap: var(--op-checkboxgroup-gap, var(--op-space-4));
2007
+ }
2008
+ }
2009
+
2010
+ @layer optikos {
2011
+ :root {
2012
+ --op-dial-spacing: 0.75rem;
2013
+ --op-dial-item-spacing: 3.5rem;
2014
+ --op-dial-height: 3.75rem;
2015
+ --op-dial-size: 13rem;
2016
+ --op-dial-readout-size: 2.75rem;
2017
+ --op-dial-readout-size-circle: 2rem;
2018
+ --op-dial-roll-duration: 380ms;
2019
+ --op-dial-tick-height: 0.75rem;
2020
+ --op-dial-major-height: 1.375rem;
2021
+ --op-dial-needle-width: 0.1875rem;
2022
+ --op-dial-label-gap: 0.25rem;
2023
+ --op-dial-ring-inset: 0.5rem;
2024
+ --op-dial-hub: 0.625rem;
2025
+ --op-dial-digit-height: 1em; /* one line of the readout: a reel moves by this per digit */
2026
+ }
2027
+ .op-dial {
2028
+ --_sp: var(--op-dial-spacing);
2029
+ }
2030
+ .op-dial--list {
2031
+ --_sp: var(--op-dial-item-spacing);
2032
+ }
2033
+ .op-dial__box {
2034
+ display: flex;
2035
+ flex-direction: column;
2036
+ align-items: center;
2037
+ gap: var(--op-space-2);
2038
+ }
2039
+
2040
+ /* the readout: digits roll like an odometer (each reel is the column 0–9, moved by --d) */
2041
+ .op-dial__readout {
2042
+ display: flex;
2043
+ justify-content: center;
2044
+ min-block-size: var(--op-dial-digit-height);
2045
+ color: var(--op-dial-readout-fg, var(--op-color-fg));
2046
+ font-size: var(--op-dial-readout-size);
2047
+ font-weight: var(--op-font-weight-bold);
2048
+ font-variant-numeric: tabular-nums;
2049
+ line-height: 1;
2050
+ white-space: pre;
2051
+ }
2052
+ .op-dial__digit,
2053
+ .op-dial__reel {
2054
+ font-size: inherit; /* the global op-* rule would reset them to the base size */
2055
+ }
2056
+ .op-dial__digit {
2057
+ display: inline-block;
2058
+ block-size: var(--op-dial-digit-height);
2059
+ overflow: hidden;
2060
+ }
2061
+ .op-dial__reel {
2062
+ display: flex;
2063
+ flex-direction: column;
2064
+ transform: translateY(calc(var(--d, 0) * -10%));
2065
+ transition: transform var(--op-dial-roll-duration) var(--op-motion-ease-out);
2066
+ }
2067
+ .op-dial__reel > span {
2068
+ display: block;
2069
+ block-size: var(--op-dial-digit-height);
2070
+ }
2071
+
2072
+ /* the face: a flat ruler sliding under a fixed needle */
2073
+ .op-dial__face {
2074
+ position: relative;
2075
+ inline-size: 100%;
2076
+ block-size: var(--op-dial-height);
2077
+ border-radius: var(--op-radius);
2078
+ cursor: grab;
2079
+ touch-action: none;
2080
+ user-select: none;
2081
+ }
2082
+ .op-dial__face:focus-visible {
2083
+ outline: var(--op-focus-width) solid var(--op-color-focus);
2084
+ outline-offset: var(--op-focus-offset);
2085
+ }
2086
+ .op-dial.is-dragging .op-dial__face {
2087
+ cursor: grabbing;
2088
+ }
2089
+ .op-dial__window {
2090
+ position: absolute;
2091
+ inset: 0;
2092
+ overflow: hidden;
2093
+ mask-image: linear-gradient(to right, transparent, black 20%, black 80%, transparent);
2094
+ }
2095
+ .op-dial__tape {
2096
+ position: absolute;
2097
+ inset-block: 0;
2098
+ inset-inline-start: 50%;
2099
+ /* --pos (set by the component) is the item under the needle, fractional while dragging */
2100
+ transform: translateX(calc(var(--pos, 0) * -1 * var(--_sp)));
2101
+ transition: transform var(--op-dial-roll-duration) var(--op-motion-ease-out);
2102
+ }
2103
+ .op-dial.is-dragging .op-dial__tape {
2104
+ transition: none;
2105
+ }
2106
+ .op-dial.is-gliding .op-dial__tape {
2107
+ transition-timing-function: var(--op-motion-ease-out);
2108
+ }
2109
+ .op-dial__tick {
2110
+ position: absolute;
2111
+ inset-block-start: 0;
2112
+ inset-inline-start: calc(var(--i) * var(--_sp));
2113
+ inline-size: var(--op-border-width);
2114
+ block-size: var(--op-dial-tick-height);
2115
+ background: var(--op-dial-tick-fg, var(--op-color-border-strong));
2116
+ transform: translateX(-50%);
2117
+ }
2118
+ .op-dial__tick.is-major {
2119
+ inline-size: calc(var(--op-border-width) * 2);
2120
+ block-size: var(--op-dial-major-height);
2121
+ background: var(--op-dial-major-fg, var(--op-color-fg-muted));
2122
+ }
2123
+ .op-dial__tick-label {
2124
+ position: absolute;
2125
+ inset-block-start: calc(100% + var(--op-dial-label-gap));
2126
+ inset-inline-start: 50%;
2127
+ color: var(--op-color-fg-muted);
2128
+ font-size: var(--op-font-size-sm);
2129
+ white-space: nowrap;
2130
+ transform: translateX(-50%);
2131
+ transition: color var(--op-duration) var(--op-easing);
2132
+ }
2133
+ .op-dial__tick.is-current .op-dial__tick-label {
2134
+ color: var(--op-color-primary-text, var(--op-color-primary));
2135
+ font-weight: var(--op-font-weight-bold);
2136
+ }
2137
+ .op-dial__needle {
2138
+ position: absolute;
2139
+ inset-block-start: 0;
2140
+ inset-inline-start: 50%;
2141
+ inline-size: var(--op-dial-needle-width);
2142
+ block-size: calc(var(--op-dial-major-height) + var(--op-space-1));
2143
+ background: var(--op-dial-needle, var(--op-color-primary));
2144
+ border-radius: var(--op-radius-pill);
2145
+ transform: translateX(-50%);
2146
+ pointer-events: none;
2147
+ }
2148
+
2149
+ /* circle: a clock face, the ticks around the ring and a hand from the center */
2150
+ .op-dial--circle .op-dial__face {
2151
+ inline-size: var(--op-dial-size);
2152
+ block-size: var(--op-dial-size);
2153
+ border: var(--op-border-width) solid var(--op-color-border);
2154
+ border-radius: 50%;
2155
+ }
2156
+ .op-dial--circle .op-dial__window {
2157
+ overflow: visible;
2158
+ mask-image: none;
2159
+ }
2160
+ .op-dial--circle .op-dial__tape {
2161
+ inset: 0;
2162
+ transform: none;
2163
+ transition: none;
2164
+ }
2165
+ .op-dial--circle .op-dial__tick {
2166
+ inset-block-start: var(--op-dial-ring-inset);
2167
+ inset-inline-start: 50%;
2168
+ transform-origin: 50% calc(var(--op-dial-size) / 2 - var(--op-dial-ring-inset) - var(--op-border-width));
2169
+ transform: translateX(-50%) rotate(var(--a));
2170
+ }
2171
+ .op-dial--circle .op-dial__tick-label {
2172
+ transform: translateX(-50%) rotate(calc(var(--a) * -1));
2173
+ }
2174
+ .op-dial--circle .op-dial__needle {
2175
+ inset-block-start: auto;
2176
+ inset-block-end: 50%;
2177
+ block-size: calc(var(--op-dial-size) / 2 - var(--op-dial-ring-inset) - var(--op-dial-major-height) - var(--op-space-5) - var(--op-space-2));
2178
+ transform-origin: 50% 100%;
2179
+ transition: transform var(--op-dial-roll-duration) var(--op-motion-ease-out);
2180
+ }
2181
+ .op-dial--circle.is-dragging .op-dial__needle {
2182
+ transition: none;
2183
+ }
2184
+ /* the hub the hand turns on */
2185
+ .op-dial--circle .op-dial__needle::after {
2186
+ content: '';
2187
+ position: absolute;
2188
+ inset-block-end: calc(var(--op-dial-hub) / -2);
2189
+ inset-inline-start: 50%;
2190
+ inline-size: var(--op-dial-hub);
2191
+ block-size: var(--op-dial-hub);
2192
+ background: inherit;
2193
+ border-radius: 50%;
2194
+ transform: translateX(-50%);
2195
+ }
2196
+ .op-dial--circle .op-dial__readout {
2197
+ font-size: var(--op-dial-readout-size-circle);
2198
+ }
2199
+
2200
+ .op-dial.is-disabled .op-dial__face {
2201
+ cursor: not-allowed;
2202
+ opacity: 0.5;
2203
+ }
2204
+ .op-dial.is-readonly .op-dial__face {
2205
+ cursor: default;
2206
+ }
2207
+ .op-motion-off .op-dial__reel,
2208
+ .op-motion-off .op-dial__tape,
2209
+ .op-motion-off .op-dial__needle {
2210
+ transition: none;
2211
+ }
2212
+ }
2213
+
2214
+ @layer optikos {
2215
+ :root {
2216
+ --op-listbox-max-height: 15rem;
2217
+ }
2218
+ .op-listbox {
2219
+ position: relative;
2220
+ box-sizing: border-box;
2221
+ max-block-size: var(--op-listbox-max-height);
2222
+ overflow: auto;
2223
+ background: var(--op-listbox-bg, var(--op-color-surface));
2224
+ color: var(--op-color-fg);
2225
+ }
2226
+ .op-listbox__item {
2227
+ box-sizing: border-box;
2228
+ display: flex;
2229
+ align-items: center;
2230
+ padding: var(--op-listbox-item-padding-y, 0) var(--op-listbox-item-padding-x, var(--op-control-padding-x));
2231
+ cursor: pointer;
2232
+ white-space: nowrap;
2233
+ overflow: hidden;
2234
+ text-overflow: ellipsis;
2235
+ }
2236
+ .op-listbox__item.is-active {
2237
+ background: var(--op-listbox-item-active-bg, var(--op-color-hover));
2238
+ }
2239
+ .op-listbox__item.is-selected {
2240
+ color: var(--op-listbox-item-selected-fg, var(--op-color-primary));
2241
+ font-weight: var(--op-font-weight-bold);
2242
+ }
2243
+ .op-listbox__item.is-disabled {
2244
+ color: var(--op-color-disabled-fg);
2245
+ cursor: not-allowed;
2246
+ }
2247
+ .op-listbox__mark {
2248
+ color: inherit;
2249
+ background: var(--op-color-primary-soft);
2250
+ font-weight: var(--op-font-weight-bold);
2251
+ }
2252
+ .op-listbox__hint {
2253
+ margin-inline-start: auto;
2254
+ padding-inline-start: var(--op-space-3);
2255
+ color: var(--op-listbox-hint-fg, var(--op-color-fg-muted));
2256
+ font-size: var(--op-font-size-sm);
2257
+ font-weight: normal;
2258
+ }
2259
+ .op-listbox__empty {
2260
+ padding: var(--op-space-3);
2261
+ color: var(--op-listbox-empty-fg, var(--op-color-fg-muted));
2262
+ }
2263
+ }
2264
+
2265
+ @layer optikos {
2266
+ .op-picker__trigger {
2267
+ position: absolute;
2268
+ inset-inline-end: var(--op-space-1);
2269
+ display: inline-flex;
2270
+ padding: var(--op-space-1);
2271
+ color: var(--op-picker-arrow-fg, var(--op-color-fg-muted));
2272
+ background: transparent;
2273
+ border: 0;
2274
+ border-radius: var(--op-radius-sm);
2275
+ cursor: pointer;
2276
+ transition: transform var(--op-duration) var(--op-easing);
2277
+ }
2278
+ .op-picker.is-open .op-picker__trigger {
2279
+ transform: rotate(180deg);
2280
+ }
2281
+ .op-picker:has(.op-picker__trigger) .op-textfield__input {
2282
+ padding-inline-end: calc(var(--op-icon-size) + var(--op-space-3));
2283
+ }
2284
+ .op-picker.is-readonly .op-textfield__input,
2285
+ .op-select .op-textfield__input {
2286
+ cursor: pointer;
2287
+ text-overflow: ellipsis;
2288
+ }
2289
+ /* stableSize: room for the spinner is always there, so the text does not shift when a search starts */
2290
+ .op-suggest.op-stable .op-textfield__input {
2291
+ padding-inline-end: calc(var(--op-icon-size) + var(--op-space-3));
2292
+ }
2293
+ .op-picker.is-searching .op-picker__spinner {
2294
+ display: inline-block;
2295
+ }
2296
+ .op-picker__spinner {
2297
+ --op-spinner-size: var(--op-icon-size);
2298
+ position: absolute;
2299
+ inset-inline-end: var(--op-space-2);
2300
+ display: none;
2301
+ }
2302
+ .op-picker__trigger:disabled {
2303
+ cursor: not-allowed;
2304
+ }
2305
+ .op-suggest__icon {
2306
+ position: absolute;
2307
+ inset-inline-start: var(--op-space-2);
2308
+ display: inline-flex;
2309
+ align-items: center;
2310
+ height: 100%;
2311
+ color: var(--op-picker-arrow-fg, var(--op-color-fg-muted));
2312
+ pointer-events: none;
2313
+ }
2314
+ .op-textfield__wrap.has-icon .op-textfield__input {
2315
+ padding-inline-start: calc(var(--op-icon-size) + var(--op-space-3));
2316
+ }
2317
+ /* the lookup's magnifier button sits where the arrow would; the spinner moves left of it */
2318
+ .op-lookup .op-picker__spinner {
2319
+ inset-inline-end: calc(var(--op-icon-size) + var(--op-space-4));
2320
+ }
2321
+ .op-lookup.op-stable .op-textfield__input {
2322
+ padding-inline-end: calc(var(--op-icon-size) * 2 + var(--op-space-5));
2323
+ }
2324
+ /* showValue: the record's id as a badge at the start of the field */
2325
+ .op-picker__id {
2326
+ position: absolute;
2327
+ inset-inline-start: var(--op-space-2);
2328
+ inset-block: 50% auto;
2329
+ transform: translateY(-50%);
2330
+ padding: 0 var(--op-space-2);
2331
+ color: var(--op-picker-id-fg, var(--op-color-fg-muted));
2332
+ background: var(--op-picker-id-bg, var(--op-color-surface-2));
2333
+ border-radius: var(--op-radius-pill);
2334
+ font-size: var(--op-font-size-sm);
2335
+ pointer-events: none;
2336
+ }
2337
+ .op-picker__id[hidden] {
2338
+ display: none;
2339
+ }
2340
+ .op-textfield__wrap.has-id .op-textfield__input {
2341
+ padding-inline-start: calc(var(--op-picker-id-width) + var(--op-space-4));
2342
+ }
2343
+ .op-textfield__wrap.has-id.has-icon .op-picker__id {
2344
+ inset-inline-start: calc(var(--op-icon-size) + var(--op-space-3));
2345
+ }
2346
+ .op-textfield__wrap.has-id.has-icon .op-textfield__input {
2347
+ padding-inline-start: calc(var(--op-icon-size) + var(--op-picker-id-width) + var(--op-space-5));
2348
+ }
2349
+ }
2350
+
2351
+ @layer optikos {
2352
+ :root {
2353
+ --op-radio-size: 1.125rem;
2354
+ }
2355
+ .op-radiogroup__options {
2356
+ display: flex;
2357
+ flex-direction: column;
2358
+ gap: var(--op-radiogroup-gap, var(--op-space-1));
2359
+ }
2360
+ .op-radiogroup__options--horizontal {
2361
+ flex-direction: row;
2362
+ flex-wrap: wrap;
2363
+ gap: var(--op-radiogroup-gap, var(--op-space-4));
2364
+ }
2365
+ .op-radio {
2366
+ display: inline-flex;
2367
+ align-items: center;
2368
+ gap: var(--op-space-2);
2369
+ min-block-size: var(--op-control-height);
2370
+ cursor: pointer;
2371
+ }
2372
+ .op-radio__input {
2373
+ position: absolute;
2374
+ opacity: 0;
2375
+ inline-size: 0;
2376
+ block-size: 0;
2377
+ }
2378
+ .op-radio__dot {
2379
+ flex: none;
2380
+ box-sizing: border-box;
2381
+ inline-size: var(--op-radio-size);
2382
+ block-size: var(--op-radio-size);
2383
+ background: var(--op-radio-bg, var(--op-color-surface));
2384
+ border: var(--op-border-width) solid var(--op-radio-border, var(--op-color-border-strong));
2385
+ border-radius: 50%;
2386
+ }
2387
+ .op-radio.is-checked .op-radio__dot {
2388
+ background: var(--op-radio-checked-bg, var(--op-color-primary));
2389
+ border-color: var(--op-radio-checked-bg, var(--op-color-primary));
2390
+ box-shadow: inset 0 0 0 var(--op-space-1) var(--op-radio-bg, var(--op-color-surface));
2391
+ }
2392
+ .op-radio__input:focus-visible + .op-radio__dot {
2393
+ outline: var(--op-focus-width) solid var(--op-color-focus);
2394
+ outline-offset: var(--op-focus-offset);
2395
+ }
2396
+ .op-radio:has(:disabled) {
2397
+ cursor: not-allowed;
2398
+ color: var(--op-color-disabled-fg);
2399
+ }
2400
+ .op-radiogroup.is-invalid .op-radio__dot {
2401
+ border-color: var(--op-field-invalid-border, var(--op-color-danger));
2402
+ }
2403
+ }
2404
+
2405
+ @layer optikos {
2406
+ :root {
2407
+ --op-secret-mask-tracking: 0.1em;
2408
+ }
2409
+ .op-secret__box {
2410
+ display: flex;
2411
+ flex-direction: column;
2412
+ gap: var(--op-space-1);
2413
+ }
2414
+ .op-secret .op-textfield__input {
2415
+ padding-inline-end: calc(var(--op-icon-size) + var(--op-space-5));
2416
+ }
2417
+ .op-secret__eye,
2418
+ .op-secret__replace,
2419
+ .op-secret__keep {
2420
+ font: inherit;
2421
+ cursor: pointer;
2422
+ }
2423
+ .op-secret__eye {
2424
+ position: absolute;
2425
+ inset-inline-end: var(--op-space-1);
2426
+ display: inline-flex;
2427
+ padding: var(--op-space-1);
2428
+ color: var(--op-color-fg-muted);
2429
+ background: transparent;
2430
+ border: 0;
2431
+ border-radius: var(--op-radius-sm);
2432
+ }
2433
+ .op-secret__eye:hover,
2434
+ .op-secret__eye[aria-pressed='true'] {
2435
+ color: var(--op-color-primary);
2436
+ }
2437
+ .op-secret__replace,
2438
+ .op-secret__keep {
2439
+ color: var(--op-color-primary);
2440
+ background: transparent;
2441
+ border: 0;
2442
+ text-decoration: underline;
2443
+ }
2444
+ .op-secret__replace {
2445
+ position: absolute;
2446
+ inset-inline-end: var(--op-space-3);
2447
+ }
2448
+ .op-secret__eye:focus-visible,
2449
+ .op-secret__replace:focus-visible,
2450
+ .op-secret__keep:focus-visible {
2451
+ outline: var(--op-focus-width) solid var(--op-color-focus);
2452
+ outline-offset: var(--op-focus-offset);
2453
+ }
2454
+ /* saved: a mask where the value would be, and a field that looks closed (it opens through the warning) */
2455
+ .op-secret.is-stored .op-textfield__input {
2456
+ cursor: pointer;
2457
+ background: var(--op-color-surface-2);
2458
+ }
2459
+ .op-secret.is-stored .op-textfield__input::placeholder {
2460
+ color: var(--op-secret-mask-fg, var(--op-color-fg));
2461
+ letter-spacing: var(--op-secret-mask-tracking);
2462
+ }
2463
+ .op-secret__hint {
2464
+ display: flex;
2465
+ align-items: baseline;
2466
+ gap: var(--op-space-3);
2467
+ color: var(--op-color-fg-muted);
2468
+ font-size: var(--op-font-size-sm);
2469
+ }
2470
+ .op-secret__hint[hidden],
2471
+ .op-secret__note[hidden],
2472
+ .op-secret__keep[hidden],
2473
+ .op-secret__eye[hidden],
2474
+ .op-secret__replace[hidden] {
2475
+ display: none;
2476
+ }
2477
+ }
2478
+
2479
+ @layer optikos {
2480
+ :root {
2481
+ --op-slider-track-height: 0.375rem;
2482
+ --op-slider-knob-size: 1.25rem;
2483
+ --op-slider-bubble-offset: 0.5rem;
2484
+ }
2485
+ .op-slider__box {
2486
+ padding-block: calc(var(--op-slider-knob-size) / 2 + var(--op-space-2)) var(--op-space-1);
2487
+ padding-inline: calc(var(--op-slider-knob-size) / 2);
2488
+ }
2489
+ .op-slider.has-bubble-always .op-slider__box {
2490
+ padding-block-start: calc(var(--op-slider-knob-size) + var(--op-space-4));
2491
+ }
2492
+ .op-slider__track {
2493
+ position: relative;
2494
+ block-size: var(--op-slider-track-height);
2495
+ background: var(--op-slider-track-bg, var(--op-color-border-strong));
2496
+ border-radius: var(--op-radius-pill);
2497
+ cursor: pointer;
2498
+ touch-action: none;
2499
+ }
2500
+ .op-slider__fill {
2501
+ position: absolute;
2502
+ inset-block: 0;
2503
+ background: var(--op-slider-fill-bg, var(--op-color-primary));
2504
+ border-radius: inherit;
2505
+ }
2506
+ .op-slider__knob {
2507
+ position: absolute;
2508
+ inset-block-start: 50%;
2509
+ inline-size: var(--op-slider-knob-size);
2510
+ block-size: var(--op-slider-knob-size);
2511
+ margin-inline-start: calc(var(--op-slider-knob-size) / -2);
2512
+ margin-block-start: calc(var(--op-slider-knob-size) / -2);
2513
+ box-sizing: border-box;
2514
+ background: var(--op-slider-knob-bg, var(--op-color-surface));
2515
+ border: calc(var(--op-border-width) * 2) solid var(--op-slider-knob-border, var(--op-color-primary));
2516
+ border-radius: 50%;
2517
+ box-shadow: var(--op-shadow-sm);
2518
+ cursor: grab;
2519
+ touch-action: none;
2520
+ }
2521
+ .op-slider.is-dragging .op-slider__knob {
2522
+ cursor: grabbing;
2523
+ }
2524
+ .op-slider__knob:focus-visible {
2525
+ outline: var(--op-focus-width) solid var(--op-color-focus);
2526
+ outline-offset: var(--op-focus-offset);
2527
+ }
2528
+ .op-slider__knob[aria-valuenow] {
2529
+ z-index: 1;
2530
+ }
2531
+ /* the bubble with the value: above the knob, while dragging or focused (or always / never) */
2532
+ .op-slider__bubble {
2533
+ position: absolute;
2534
+ inset-inline-start: 50%;
2535
+ inset-block-end: calc(100% + var(--op-slider-bubble-offset));
2536
+ padding: 0 var(--op-space-2);
2537
+ color: var(--op-slider-bubble-fg, var(--op-color-inverse-fg));
2538
+ background: var(--op-slider-bubble-bg, var(--op-color-inverse-bg));
2539
+ border-radius: var(--op-radius-sm);
2540
+ font-size: var(--op-font-size-sm);
2541
+ white-space: nowrap;
2542
+ transform: translateX(-50%);
2543
+ opacity: 0;
2544
+ pointer-events: none;
2545
+ }
2546
+ .op-slider.is-dragging .op-slider__bubble,
2547
+ .op-slider.is-focus-knob .op-slider__knob:focus-visible .op-slider__bubble,
2548
+ .op-slider.has-bubble-always .op-slider__bubble {
2549
+ opacity: 1;
2550
+ }
2551
+ .op-slider.has-bubble-never .op-slider__bubble {
2552
+ display: none;
2553
+ }
2554
+ .op-slider__mark {
2555
+ position: absolute;
2556
+ inset-block-start: 100%;
2557
+ inline-size: var(--op-border-width);
2558
+ block-size: var(--op-space-2);
2559
+ margin-block-start: var(--op-space-1);
2560
+ background: var(--op-color-border-strong);
2561
+ }
2562
+ .op-slider__mark-label {
2563
+ position: absolute;
2564
+ inset-block-start: 100%;
2565
+ inset-inline-start: 50%;
2566
+ color: var(--op-color-fg-muted);
2567
+ font-size: var(--op-font-size-sm);
2568
+ white-space: nowrap;
2569
+ transform: translateX(-50%);
2570
+ }
2571
+ .op-slider__scale {
2572
+ display: flex;
2573
+ justify-content: space-between;
2574
+ margin-block-start: var(--op-space-3);
2575
+ color: var(--op-color-fg-muted);
2576
+ font-size: var(--op-font-size-sm);
2577
+ }
2578
+ .op-slider.is-disabled .op-slider__track,
2579
+ .op-slider.is-readonly .op-slider__track {
2580
+ cursor: not-allowed;
2581
+ }
2582
+ .op-slider.is-disabled {
2583
+ opacity: 0.6;
2584
+ }
2585
+ }
2586
+
2587
+ @layer optikos {
2588
+ :root {
2589
+ --op-textarea-min-height: 4rem;
2590
+ }
2591
+ .op-textarea__input {
2592
+ min-block-size: var(--op-textarea-min-height);
2593
+ padding-block: var(--op-space-2);
2594
+ resize: vertical;
2595
+ line-height: var(--op-line-height);
2596
+ }
2597
+ }
2598
+
2599
+ @layer optikos {
2600
+ .op-textfield {
2601
+ --_bg: var(--op-textfield-bg, var(--op-color-surface));
2602
+ --_border: var(--op-textfield-border, var(--op-color-border-strong));
2603
+ }
2604
+ .op-textfield__wrap {
2605
+ position: relative;
2606
+ display: flex;
2607
+ align-items: center;
2608
+ }
2609
+ .op-textfield__input {
2610
+ box-sizing: border-box;
2611
+ inline-size: 100%;
2612
+ min-block-size: var(--op-textfield-height, var(--op-control-height));
2613
+ padding: var(--op-textfield-padding-y, 0) var(--op-textfield-padding-x, var(--op-control-padding-x));
2614
+ font: inherit;
2615
+ color: var(--op-textfield-fg, var(--op-color-fg));
2616
+ background: var(--_bg);
2617
+ border: var(--op-border-width) solid var(--_border);
2618
+ border-radius: var(--op-textfield-radius, var(--op-radius));
2619
+ transition: border-color var(--op-duration) var(--op-easing);
2620
+ }
2621
+ .op-textfield__input::placeholder {
2622
+ color: var(--op-textfield-placeholder, var(--op-color-fg-muted));
2623
+ }
2624
+ .op-textfield__input:focus {
2625
+ outline: var(--op-focus-width) solid var(--op-color-focus);
2626
+ outline-offset: 0;
2627
+ border-color: var(--op-textfield-border-focus, var(--op-color-focus));
2628
+ }
2629
+ .op-textfield.is-invalid .op-textfield__input {
2630
+ --_border: var(--op-field-invalid-border, var(--op-color-danger));
2631
+ }
2632
+ .op-textfield.is-readonly .op-textfield__input {
2633
+ background: var(--op-color-surface-2);
2634
+ }
2635
+ .op-textfield__input:disabled {
2636
+ color: var(--op-color-disabled-fg);
2637
+ background: var(--op-color-disabled-bg);
2638
+ cursor: not-allowed;
2639
+ }
2640
+ .op-textfield__clear {
2641
+ position: absolute;
2642
+ inset-inline-end: var(--op-space-1);
2643
+ display: none;
2644
+ padding: var(--op-space-1);
2645
+ color: var(--op-color-fg-muted);
2646
+ background: transparent;
2647
+ border: 0;
2648
+ border-radius: var(--op-radius-sm);
2649
+ cursor: pointer;
2650
+ }
2651
+ .op-textfield.has-value .op-textfield__clear {
2652
+ display: inline-flex;
2653
+ }
2654
+ .op-textfield__clear:hover {
2655
+ color: var(--op-color-fg);
2656
+ }
2657
+ }
2658
+
2659
+ @layer optikos {
2660
+ :root {
2661
+ --op-toggle-width: 2.25rem;
2662
+ --op-toggle-height: 1.25rem;
2663
+ --op-toggle-knob-inset: 0.1875rem;
2664
+ }
2665
+ /* the checkbox box becomes a track; its knob is a pseudo-element that slides */
2666
+ .op-toggle .op-checkbox__box {
2667
+ inline-size: var(--op-toggle-width);
2668
+ block-size: var(--op-toggle-height);
2669
+ border-radius: var(--op-radius-pill);
2670
+ background: var(--op-toggle-track-bg, var(--op-color-border-strong));
2671
+ border-color: transparent;
2672
+ transition: background var(--op-duration) var(--op-easing);
2673
+ }
2674
+ .op-toggle .op-checkbox__box > * {
2675
+ display: none;
2676
+ }
2677
+ .op-toggle .op-checkbox__box::after {
2678
+ content: '';
2679
+ position: absolute;
2680
+ inset-block: var(--op-toggle-knob-inset);
2681
+ inset-inline-start: var(--op-toggle-knob-inset);
2682
+ aspect-ratio: 1;
2683
+ border-radius: 50%;
2684
+ background: var(--op-toggle-knob-bg, var(--op-color-surface));
2685
+ box-shadow: var(--op-shadow-sm);
2686
+ transition: translate var(--op-duration) var(--op-easing);
2687
+ }
2688
+ .op-toggle.is-checked .op-checkbox__box {
2689
+ background: var(--op-toggle-on-bg, var(--op-color-primary));
2690
+ }
2691
+ .op-toggle.is-checked .op-checkbox__box::after {
2692
+ translate: calc(var(--op-toggle-width) - var(--op-toggle-height)) 0;
2693
+ }
2694
+ [dir='rtl'] .op-toggle.is-checked .op-checkbox__box::after {
2695
+ translate: calc((var(--op-toggle-width) - var(--op-toggle-height)) * -1) 0;
2696
+ }
2697
+ }
2698
+
2699
+ @layer optikos {
2700
+ .op-fieldgroup__body {
2701
+ --op-layout-gap: var(--op-fieldgroup-gap, var(--op-space-2));
2702
+ }
2703
+ /* the fields share the row; each still has its label for screen readers, but only the group's label shows */
2704
+ .op-fieldgroup__body > .op-field {
2705
+ flex: 1 1 0;
2706
+ min-inline-size: 0;
2707
+ }
2708
+ .op-fieldgroup__body .op-field__label {
2709
+ position: absolute;
2710
+ inline-size: 0;
2711
+ block-size: 0;
2712
+ overflow: hidden;
2713
+ clip-path: inset(50%);
2714
+ white-space: nowrap;
2715
+ }
2716
+ .op-fieldgroup__body .op-field__help,
2717
+ .op-fieldgroup__body .op-field__error,
2718
+ .op-fieldgroup__body .op-field.op-stable > .op-field__error:empty {
2719
+ display: none; /* the group has the one error line (and beats the reserved line of stableSize) */
2720
+ }
2721
+ .op-fieldgroup > .op-field__label {
2722
+ cursor: default;
2723
+ }
2724
+ }
2725
+
2726
+ @layer optikos {
2727
+ .op-fieldlist__box {
2728
+ display: flex;
2729
+ flex-direction: column;
2730
+ align-items: flex-start;
2731
+ gap: var(--op-fieldlist-gap, var(--op-space-2));
2732
+ }
2733
+ .op-fieldlist__rows {
2734
+ display: flex;
2735
+ flex-direction: column;
2736
+ gap: var(--op-fieldlist-row-gap, var(--op-space-2));
2737
+ align-self: stretch;
2738
+ }
2739
+ .op-fieldlist__row {
2740
+ --op-layout-gap: var(--op-space-2);
2741
+ }
2742
+ .op-fieldlist__row > .op-field {
2743
+ flex: 1 1 0;
2744
+ min-inline-size: 0;
2745
+ }
2746
+ /* the labels read as a column header: shown on the first row, kept for screen readers on the others */
2747
+ .op-fieldlist__row:not(.is-first) .op-field__label {
2748
+ position: absolute;
2749
+ inline-size: 0;
2750
+ block-size: 0;
2751
+ overflow: hidden;
2752
+ clip-path: inset(50%);
2753
+ white-space: nowrap;
2754
+ }
2755
+ .op-fieldlist__row:not(.is-first) .op-field__help {
2756
+ display: none;
2757
+ }
2758
+ .op-fieldlist__tools {
2759
+ display: flex;
2760
+ flex: none;
2761
+ gap: var(--op-space-1);
2762
+ align-self: flex-start;
2763
+ min-block-size: var(--op-control-height);
2764
+ align-items: center;
2765
+ }
2766
+ /* on the first row the tools line up with the inputs, under the labels */
2767
+ .op-fieldlist__row.is-first > .op-fieldlist__tools {
2768
+ margin-block-start: calc(var(--op-font-size) * var(--op-line-height) + var(--op-field-gap, var(--op-space-1)));
2769
+ }
2770
+ .op-fieldlist__tool,
2771
+ .op-fieldlist__add {
2772
+ display: inline-flex;
2773
+ align-items: center;
2774
+ gap: var(--op-space-1);
2775
+ color: var(--op-color-fg-muted);
2776
+ background: transparent;
2777
+ border: 0;
2778
+ border-radius: var(--op-radius-sm);
2779
+ font: inherit;
2780
+ cursor: pointer;
2781
+ }
2782
+ .op-fieldlist__tool {
2783
+ padding: var(--op-space-1);
2784
+ }
2785
+ .op-fieldlist__add {
2786
+ padding: var(--op-space-1) var(--op-space-2);
2787
+ color: var(--op-color-primary-text, var(--op-color-primary));
2788
+ font-weight: var(--op-font-weight-medium);
2789
+ }
2790
+ .op-fieldlist__tool:hover:not(:disabled),
2791
+ .op-fieldlist__add:hover:not(:disabled) {
2792
+ color: var(--op-color-fg);
2793
+ background: var(--op-color-hover);
2794
+ }
2795
+ .op-fieldlist__tool:disabled,
2796
+ .op-fieldlist__add:disabled {
2797
+ color: var(--op-color-disabled-fg);
2798
+ cursor: not-allowed;
2799
+ }
2800
+ .op-fieldlist__tool:focus-visible,
2801
+ .op-fieldlist__add:focus-visible {
2802
+ outline: var(--op-focus-width) solid var(--op-color-focus);
2803
+ outline-offset: var(--op-focus-offset);
2804
+ }
2805
+ .op-fieldlist__empty {
2806
+ color: var(--op-color-fg-muted);
2807
+ font-size: var(--op-font-size-sm);
2808
+ }
2809
+ }
2810
+
2811
+ @layer optikos {
2812
+ .op-form {
2813
+ --op-layout-gap: var(--op-form-gap, var(--op-space-3));
2814
+ }
2815
+ .op-form__tab {
2816
+ padding: var(--op-form-tab-padding, var(--op-space-4));
2817
+ }
2818
+ }
2819
+
2820
+ @layer optikos {
2821
+ .op-formactions {
2822
+ display: flex;
2823
+ flex-wrap: wrap;
2824
+ align-items: center;
2825
+ gap: var(--op-space-2) var(--op-space-3);
2826
+ padding: var(--op-formactions-padding, var(--op-space-3) 0 0);
2827
+ border-block-start: var(--op-border-width) solid var(--op-formactions-border, var(--op-color-border));
2828
+ }
2829
+ .op-formactions__status {
2830
+ flex: 1;
2831
+ min-inline-size: 0;
2832
+ color: var(--op-color-fg-muted);
2833
+ font-size: var(--op-font-size-sm);
2834
+ }
2835
+ .op-formactions__status:not(:empty)::before {
2836
+ content: '';
2837
+ display: inline-block;
2838
+ inline-size: var(--op-space-2);
2839
+ block-size: var(--op-space-2);
2840
+ margin-inline-end: var(--op-space-2);
2841
+ background: var(--op-color-warning);
2842
+ border-radius: 50%;
2843
+ }
2844
+ .op-formactions__buttons {
2845
+ display: flex;
2846
+ flex-wrap: wrap;
2847
+ gap: var(--op-space-2);
2848
+ margin-inline-start: auto;
2849
+ }
2850
+ /* sticky: stays at the bottom of the scrolling area while the form scrolls under it */
2851
+ .op-formactions.is-sticky {
2852
+ position: sticky;
2853
+ inset-block-end: 0;
2854
+ z-index: 1;
2855
+ padding: var(--op-formactions-padding, var(--op-space-3));
2856
+ background: var(--op-formactions-bg, var(--op-color-surface));
2857
+ box-shadow: var(--op-shadow-sm);
2858
+ }
2859
+ }
2860
+
2861
+ @layer optikos {
2862
+ .op-formerrors {
2863
+ padding: var(--op-space-3) var(--op-space-4);
2864
+ color: var(--op-formerrors-fg, var(--op-color-fg));
2865
+ background: var(--op-formerrors-bg, var(--op-color-danger-soft));
2866
+ border: var(--op-border-width) solid var(--op-formerrors-border, var(--op-color-danger));
2867
+ border-inline-start-width: calc(var(--op-border-width) * 4);
2868
+ border-radius: var(--op-radius);
2869
+ }
2870
+ .op-formerrors:focus-visible {
2871
+ outline: var(--op-focus-width) solid var(--op-color-focus);
2872
+ outline-offset: var(--op-focus-offset);
2873
+ }
2874
+ .op-formerrors__title {
2875
+ font-weight: var(--op-font-weight-bold);
2876
+ }
2877
+ .op-formerrors__list {
2878
+ margin: var(--op-space-2) 0 0;
2879
+ padding-inline-start: var(--op-space-4);
2880
+ }
2881
+ .op-formerrors__link {
2882
+ padding: 0;
2883
+ color: var(--op-color-danger);
2884
+ background: none;
2885
+ border: 0;
2886
+ font: inherit;
2887
+ text-align: start;
2888
+ text-decoration: underline;
2889
+ cursor: pointer;
2890
+ }
2891
+ .op-formerrors__link:hover {
2892
+ text-decoration-thickness: calc(var(--op-border-width) * 2);
2893
+ }
2894
+ .op-formerrors__link:focus-visible {
2895
+ outline: var(--op-focus-width) solid var(--op-color-focus);
2896
+ outline-offset: var(--op-focus-offset);
2897
+ border-radius: var(--op-radius-sm);
2898
+ }
2899
+ }
2900
+
2901
+ @layer optikos {
2902
+ :root {
2903
+ --op-formsection-aside-width: 16rem;
2904
+ --op-formsection-gap: var(--op-space-6);
2905
+ }
2906
+ /* side by side when the section itself is wide enough: a container query, so it works inside any panel or window */
2907
+ .op-formsection {
2908
+ display: flow-root; /* holds the floated aside */
2909
+ container-type: inline-size;
2910
+ min-inline-size: 0;
2911
+ }
2912
+ .op-formsection__aside,
2913
+ .op-formsection__body {
2914
+ min-inline-size: 0;
2915
+ }
2916
+ .op-formsection__body {
2917
+ --op-layout-gap: var(--op-form-gap, var(--op-space-3));
2918
+ margin-block-start: var(--op-space-3);
2919
+ }
2920
+ .op-formsection__title {
2921
+ margin: 0;
2922
+ font-size: var(--op-font-size-lg);
2923
+ font-weight: var(--op-font-weight-bold);
2924
+ }
2925
+ .op-formsection__desc {
2926
+ margin: var(--op-space-1) 0 0;
2927
+ color: var(--op-color-fg-muted);
2928
+ font-size: var(--op-font-size-sm);
2929
+ }
2930
+ .op-formsection--divided + .op-formsection--divided {
2931
+ margin-block-start: var(--op-space-4);
2932
+ padding-block-start: var(--op-space-5);
2933
+ border-block-start: var(--op-border-width) solid var(--op-formsection-divider, var(--op-color-border));
2934
+ }
2935
+ @container (min-width: 40rem) {
2936
+ .op-formsection:not(.op-formsection--stacked) > .op-formsection__aside {
2937
+ float: inline-start;
2938
+ inline-size: var(--op-formsection-aside-width);
2939
+ }
2940
+ .op-formsection:not(.op-formsection--stacked) > .op-formsection__body {
2941
+ margin-block-start: 0;
2942
+ margin-inline-start: calc(var(--op-formsection-aside-width) + var(--op-formsection-gap));
2943
+ }
2944
+ }
2945
+ }
2946
+
2947
+ @layer optikos {
2948
+ /* the field's control becomes a row: [prefix][input box][suffix], the inner corners squared off */
2949
+ .op-inputgroup__row {
2950
+ display: flex;
2951
+ align-items: stretch;
2952
+ }
2953
+ .op-inputgroup__row > :not(.op-inputgroup__affix) {
2954
+ flex: 1;
2955
+ min-inline-size: 0;
2956
+ }
2957
+ .op-inputgroup__affix {
2958
+ display: inline-flex;
2959
+ align-items: center;
2960
+ gap: var(--op-space-1);
2961
+ padding-inline: var(--op-control-padding-x);
2962
+ color: var(--op-inputgroup-affix-fg, var(--op-color-fg-muted));
2963
+ background: var(--op-inputgroup-affix-bg, var(--op-color-surface-2));
2964
+ border: var(--op-border-width) solid var(--op-textfield-border, var(--op-color-border-strong));
2965
+ white-space: nowrap;
2966
+ }
2967
+ .op-inputgroup__btn {
2968
+ color: var(--op-color-fg);
2969
+ font: inherit;
2970
+ font-weight: var(--op-font-weight-medium);
2971
+ cursor: pointer;
2972
+ }
2973
+ .op-inputgroup__btn:hover {
2974
+ background: var(--op-color-hover);
2975
+ }
2976
+ .op-inputgroup__btn:focus-visible {
2977
+ position: relative;
2978
+ z-index: 1;
2979
+ outline: var(--op-focus-width) solid var(--op-color-focus);
2980
+ }
2981
+ .op-inputgroup__affix--prefix {
2982
+ margin-inline-end: calc(var(--op-border-width) * -1);
2983
+ border-start-start-radius: var(--op-textfield-radius, var(--op-radius));
2984
+ border-end-start-radius: var(--op-textfield-radius, var(--op-radius));
2985
+ }
2986
+ .op-inputgroup__affix--suffix {
2987
+ margin-inline-start: calc(var(--op-border-width) * -1);
2988
+ border-start-end-radius: var(--op-textfield-radius, var(--op-radius));
2989
+ border-end-end-radius: var(--op-textfield-radius, var(--op-radius));
2990
+ }
2991
+ /* every text-based field (Select, DateField, NumberField...) draws its box on .op-textfield__input */
2992
+ .op-inputgroup .has-prefix .op-textfield__input {
2993
+ border-start-start-radius: 0;
2994
+ border-end-start-radius: 0;
2995
+ }
2996
+ .op-inputgroup .has-suffix .op-textfield__input {
2997
+ border-start-end-radius: 0;
2998
+ border-end-end-radius: 0;
2999
+ }
3000
+ .op-inputgroup .op-textfield__input:focus {
3001
+ position: relative;
3002
+ z-index: 1; /* the focus ring stays above the joined segments */
3003
+ }
3004
+ }
3005
+
3006
+ @layer optikos {
3007
+ :root {
3008
+ --op-stepform-review-label-width: 9rem;
3009
+ }
3010
+ .op-stepform {
3011
+ display: flex;
3012
+ flex-direction: column;
3013
+ gap: var(--op-stepform-gap, var(--op-space-4));
3014
+ min-block-size: 0;
3015
+ }
3016
+ .op-stepform > .op-stepper {
3017
+ flex: none;
3018
+ padding-inline: var(--op-stepform-step-padding, var(--op-space-3));
3019
+ }
3020
+ .op-stepform__body {
3021
+ flex: 1;
3022
+ min-block-size: 0;
3023
+ overflow: auto;
3024
+ }
3025
+ .op-stepform__step {
3026
+ padding: var(--op-stepform-step-padding, var(--op-space-3));
3027
+ }
3028
+ .op-stepform > .op-stepform__footer {
3029
+ flex: none;
3030
+ border-block-end: 0;
3031
+ border-block-start: var(--op-border-width) solid var(--op-color-border);
3032
+ }
3033
+ .op-stepform__review-title {
3034
+ margin: var(--op-space-3) 0 var(--op-space-2);
3035
+ font-size: var(--op-font-size-lg);
3036
+ font-weight: var(--op-font-weight-bold);
3037
+ }
3038
+ .op-stepform__review-list {
3039
+ display: grid;
3040
+ grid-template-columns: minmax(var(--op-stepform-review-label-width), max-content) minmax(0, 1fr);
3041
+ gap: var(--op-space-1) var(--op-space-4);
3042
+ margin: 0;
3043
+ }
3044
+ .op-stepform__review-list dt {
3045
+ color: var(--op-color-fg-muted);
3046
+ }
3047
+ .op-stepform__review-list dd {
3048
+ margin: 0;
3049
+ overflow-wrap: anywhere;
3050
+ }
3051
+ }
3052
+
3053
+ @layer optikos {
3054
+ .op-container {
3055
+ min-width: 0;
3056
+ }
3057
+ }
3058
+
3059
+ @layer optikos {
3060
+ .op-fieldset {
3061
+ min-inline-size: 0;
3062
+ margin: 0;
3063
+ padding: var(--op-fieldset-padding, var(--op-space-3));
3064
+ color: var(--op-color-fg);
3065
+ border: var(--op-border-width) solid var(--op-fieldset-border, var(--op-color-border));
3066
+ border-radius: var(--op-fieldset-radius, var(--op-radius));
3067
+ }
3068
+ .op-fieldset__legend {
3069
+ display: flex;
3070
+ align-items: center;
3071
+ gap: var(--op-space-1);
3072
+ padding-inline: var(--op-space-1);
3073
+ color: var(--op-fieldset-legend-fg, var(--op-color-fg));
3074
+ font-weight: var(--op-font-weight-bold);
3075
+ }
3076
+ .op-fieldset__toggle {
3077
+ display: inline-flex;
3078
+ padding: 0;
3079
+ color: inherit;
3080
+ background: transparent;
3081
+ border: 0;
3082
+ cursor: pointer;
3083
+ }
3084
+ .op-fieldset.is-collapsed .op-fieldset__toggle .op-icon {
3085
+ transform: rotate(180deg);
3086
+ }
3087
+ .op-fieldset.is-collapsed {
3088
+ padding-block-end: 0;
3089
+ }
3090
+ .op-fieldset__desc {
3091
+ margin: 0 0 var(--op-space-3);
3092
+ padding-inline: var(--op-space-1);
3093
+ color: var(--op-color-fg-muted);
3094
+ font-size: var(--op-font-size-sm);
3095
+ }
3096
+ .op-fieldset__body {
3097
+ --op-layout-gap: var(--op-form-gap, var(--op-space-3));
3098
+ }
3099
+ /* line: no frame, a rule under the legend; plain: just the legend */
3100
+ .op-fieldset--line,
3101
+ .op-fieldset--plain {
3102
+ padding: 0;
3103
+ border: 0;
3104
+ border-radius: 0;
3105
+ }
3106
+ .op-fieldset--line > .op-fieldset__legend,
3107
+ .op-fieldset--plain > .op-fieldset__legend {
3108
+ inline-size: 100%;
3109
+ margin-block-end: var(--op-space-3);
3110
+ padding: 0;
3111
+ }
3112
+ .op-fieldset--line > .op-fieldset__legend {
3113
+ padding-block-end: var(--op-space-2);
3114
+ border-block-end: var(--op-border-width) solid var(--op-fieldset-border, var(--op-color-border));
3115
+ }
3116
+ .op-fieldset--line > .op-fieldset__desc,
3117
+ .op-fieldset--plain > .op-fieldset__desc {
3118
+ margin-block-start: calc(var(--op-space-2) * -1);
3119
+ padding: 0;
3120
+ }
3121
+ .op-fieldset--collapsible-title .op-fieldset__title,
3122
+ .op-fieldset__toggle + .op-fieldset__title {
3123
+ cursor: pointer;
3124
+ user-select: none;
3125
+ }
3126
+ }
3127
+
3128
+ @layer optikos {
3129
+ .op-panel {
3130
+ --_bg: var(--op-panel-bg, var(--op-color-surface));
3131
+ display: flex;
3132
+ flex-direction: column;
3133
+ min-width: 0;
3134
+ min-height: 0;
3135
+ color: var(--op-panel-fg, var(--op-color-fg));
3136
+ background: var(--_bg);
3137
+ border: var(--op-border-width) solid var(--op-panel-border, var(--op-color-border));
3138
+ border-radius: var(--op-panel-radius, var(--op-radius));
3139
+ box-shadow: var(--op-panel-shadow, none);
3140
+ overflow: hidden;
3141
+ }
3142
+ .op-panel__header {
3143
+ display: flex;
3144
+ align-items: center;
3145
+ gap: var(--op-space-2);
3146
+ padding: var(--op-panel-header-padding, var(--op-space-2) var(--op-space-3));
3147
+ background: var(--op-panel-header-bg, var(--op-color-surface-2));
3148
+ color: var(--op-panel-header-fg, var(--op-color-fg));
3149
+ border-block-end: var(--op-border-width) solid var(--op-panel-header-border, var(--op-panel-border, var(--op-color-border-strong)));
3150
+ font-weight: var(--op-font-weight-bold);
3151
+ }
3152
+ .op-panel__title {
3153
+ flex: 1;
3154
+ min-width: 0;
3155
+ overflow: hidden;
3156
+ text-overflow: ellipsis;
3157
+ white-space: nowrap;
3158
+ }
3159
+ .op-panel--collapsible .op-panel__title {
3160
+ cursor: pointer;
3161
+ }
3162
+ .op-panel__tools {
3163
+ display: flex;
3164
+ gap: var(--op-space-1);
3165
+ }
3166
+ .op-panel__tool {
3167
+ display: inline-flex;
3168
+ padding: var(--op-space-1);
3169
+ color: inherit;
3170
+ background: transparent;
3171
+ border: 0;
3172
+ border-radius: var(--op-radius-sm);
3173
+ cursor: pointer;
3174
+ }
3175
+ .op-panel__tool:hover {
3176
+ background: var(--op-color-hover);
3177
+ }
3178
+ .op-panel__tool:focus-visible {
3179
+ outline: var(--op-focus-width) solid var(--op-color-focus);
3180
+ outline-offset: 0;
3181
+ }
3182
+ .op-panel.is-collapsed .op-panel__header {
3183
+ border-block-end: 0;
3184
+ }
3185
+ .op-panel.is-collapsed .op-panel__tool:first-child .op-icon {
3186
+ transform: rotate(180deg);
3187
+ }
3188
+ .op-panel__body {
3189
+ flex: 1;
3190
+ min-height: 0;
3191
+ padding: var(--op-panel-body-padding, var(--op-space-3));
3192
+ overflow: auto;
3193
+ }
3194
+ .op-panel__tbar,
3195
+ .op-panel__bbar,
3196
+ .op-panel__footer {
3197
+ border-block-end: var(--op-border-width) solid var(--op-color-border);
3198
+ }
3199
+ .op-panel__bbar,
3200
+ .op-panel__footer {
3201
+ border-block-end: 0;
3202
+ border-block-start: var(--op-border-width) solid var(--op-color-border);
3203
+ }
3204
+ /* the ↻ tool turns while the panel reloads */
3205
+ .op-panel.is-reloading > .op-panel__header .op-panel__tool svg {
3206
+ animation: op-spin 700ms linear infinite;
3207
+ }
3208
+ .op-motion-off .op-panel.is-reloading > .op-panel__header .op-panel__tool svg {
3209
+ animation: none;
3210
+ }
3211
+ }
3212
+
3213
+ @layer optikos {
3214
+ .op-spacer--line {
3215
+ align-self: stretch;
3216
+ inline-size: var(--op-border-width);
3217
+ background: var(--op-spacer-line, var(--op-color-border));
3218
+ }
3219
+ }
3220
+
3221
+ @layer optikos {
3222
+ .op-toolbar {
3223
+ --op-layout-gap: var(--op-toolbar-gap, var(--op-space-2));
3224
+ flex-wrap: wrap;
3225
+ padding: var(--op-toolbar-padding, var(--op-space-2));
3226
+ background: var(--op-toolbar-bg, var(--op-color-surface));
3227
+ border-block-end: var(--op-border-width) solid var(--op-toolbar-border, var(--op-color-border));
3228
+ }
3229
+ /* toolbar items keep their size and wrap to a new row instead of being squeezed or cut */
3230
+ .op-toolbar > * {
3231
+ flex-shrink: 0;
3232
+ white-space: nowrap;
3233
+ }
3234
+ }
3235
+
3236
+ @layer optikos {
3237
+ .op-viewport {
3238
+ position: fixed;
3239
+ inset: 0;
3240
+ overflow: hidden;
3241
+ color: var(--op-viewport-fg, var(--op-color-fg));
3242
+ background: var(--op-viewport-bg, var(--op-color-bg));
3243
+ }
3244
+ }
3245
+
3246
+ @layer optikos {
3247
+ :root {
3248
+ --op-breadcrumb-separator: '›';
3249
+ }
3250
+ .op-breadcrumb {
3251
+ color: var(--op-breadcrumb-fg, var(--op-color-fg-muted));
3252
+ }
3253
+ .op-breadcrumb__list {
3254
+ display: flex;
3255
+ flex-wrap: wrap;
3256
+ align-items: center;
3257
+ gap: var(--op-breadcrumb-gap, var(--op-space-1));
3258
+ margin: 0;
3259
+ padding: 0;
3260
+ list-style: none;
3261
+ }
3262
+ .op-breadcrumb__list > li + li::before {
3263
+ content: var(--op-breadcrumb-separator);
3264
+ margin-inline-end: var(--op-breadcrumb-gap, var(--op-space-1));
3265
+ }
3266
+ .op-breadcrumb__item,
3267
+ .op-breadcrumb__more,
3268
+ .op-breadcrumb__current {
3269
+ display: inline-flex;
3270
+ align-items: center;
3271
+ gap: var(--op-space-1);
3272
+ padding: var(--op-space-1);
3273
+ font: inherit;
3274
+ color: inherit;
3275
+ text-decoration: none;
3276
+ background: transparent;
3277
+ border: 0;
3278
+ border-radius: var(--op-radius-sm);
3279
+ }
3280
+ .op-breadcrumb__item,
3281
+ .op-breadcrumb__more {
3282
+ cursor: pointer;
3283
+ }
3284
+ .op-breadcrumb__item:hover,
3285
+ .op-breadcrumb__more:hover {
3286
+ color: var(--op-breadcrumb-hover-fg, var(--op-color-fg));
3287
+ background: var(--op-color-hover);
3288
+ }
3289
+ .op-breadcrumb__item:focus-visible,
3290
+ .op-breadcrumb__more:focus-visible {
3291
+ outline: var(--op-focus-width) solid var(--op-color-focus);
3292
+ outline-offset: 0;
3293
+ }
3294
+ .op-breadcrumb__current {
3295
+ color: var(--op-breadcrumb-current-fg, var(--op-color-fg));
3296
+ font-weight: var(--op-font-weight-medium);
3297
+ }
3298
+ }
3299
+
3300
+ @layer optikos {
3301
+ :root {
3302
+ --op-navmenu-rail-width: 3.5rem;
3303
+ --op-navmenu-indent: 1rem;
3304
+ --op-navmenu-group-tracking: 0.04em;
3305
+ --op-navmenu-badge-min-width: 1.25rem;
3306
+ }
3307
+ .op-navmenu {
3308
+ display: block;
3309
+ box-sizing: border-box;
3310
+ min-inline-size: 0;
3311
+ color: var(--op-navmenu-fg, var(--op-color-fg));
3312
+ background: var(--op-navmenu-bg, var(--op-color-surface));
3313
+ overflow: auto;
3314
+ }
3315
+ .op-navmenu__tree,
3316
+ .op-navmenu__group {
3317
+ margin: 0;
3318
+ padding: 0;
3319
+ list-style: none;
3320
+ }
3321
+ .op-navmenu__tree {
3322
+ padding: var(--op-space-2);
3323
+ }
3324
+ .op-navmenu__item {
3325
+ display: flex;
3326
+ align-items: center;
3327
+ gap: var(--op-space-3);
3328
+ box-sizing: border-box;
3329
+ min-block-size: var(--op-navmenu-item-height, var(--op-control-height));
3330
+ padding: 0 var(--op-space-3);
3331
+ padding-inline-start: calc(var(--op-space-3) + var(--_level, 0) * var(--op-navmenu-indent));
3332
+ border-radius: var(--op-radius);
3333
+ border-inline-start: var(--op-space-1) solid transparent;
3334
+ cursor: pointer;
3335
+ user-select: none;
3336
+ }
3337
+ .op-navmenu__item:hover:not(.is-disabled) {
3338
+ background: var(--op-navmenu-item-hover-bg, var(--op-color-hover));
3339
+ }
3340
+ .op-navmenu__item:focus-visible {
3341
+ outline: var(--op-focus-width) solid var(--op-color-focus);
3342
+ outline-offset: calc(var(--op-focus-width) * -1);
3343
+ }
3344
+ .op-navmenu__item.is-active {
3345
+ color: var(--op-navmenu-active-fg, var(--op-color-primary));
3346
+ background: var(--op-navmenu-active-bg, var(--op-color-primary-soft));
3347
+ border-inline-start-color: var(--op-navmenu-active-bar, var(--op-color-primary));
3348
+ font-weight: var(--op-font-weight-bold);
3349
+ }
3350
+ .op-navmenu__item.is-disabled {
3351
+ color: var(--op-color-disabled-fg);
3352
+ cursor: not-allowed;
3353
+ }
3354
+ .op-navmenu__item.is-group {
3355
+ color: var(--op-navmenu-group-fg, var(--op-color-fg-muted));
3356
+ font-size: var(--op-font-size-sm);
3357
+ font-weight: var(--op-font-weight-bold);
3358
+ letter-spacing: var(--op-navmenu-group-tracking);
3359
+ text-transform: uppercase;
3360
+ }
3361
+ .op-navmenu__icon {
3362
+ display: inline-flex;
3363
+ flex: none;
3364
+ inline-size: var(--op-icon-size);
3365
+ }
3366
+ .op-navmenu__text {
3367
+ flex: 1;
3368
+ min-inline-size: 0;
3369
+ overflow: hidden;
3370
+ text-overflow: ellipsis;
3371
+ white-space: nowrap;
3372
+ }
3373
+ .op-navmenu__badge {
3374
+ flex: none;
3375
+ min-inline-size: var(--op-navmenu-badge-min-width);
3376
+ padding: 0 var(--op-space-2);
3377
+ color: var(--op-navmenu-badge-fg, var(--op-color-primary-fg));
3378
+ background: var(--op-navmenu-badge-bg, var(--op-color-primary));
3379
+ border-radius: var(--op-radius-pill);
3380
+ font-size: var(--op-font-size-sm);
3381
+ font-weight: var(--op-font-weight-bold);
3382
+ text-align: center;
3383
+ }
3384
+ .op-navmenu__chevron {
3385
+ display: inline-flex;
3386
+ flex: none;
3387
+ transition: transform var(--op-duration) var(--op-easing);
3388
+ }
3389
+ .op-navmenu__item.is-group:not(.is-expanded) .op-navmenu__chevron {
3390
+ transform: rotate(-90deg);
3391
+ }
3392
+ /* rail: icons only; a group is just a thin rule between its neighbours */
3393
+ .op-navmenu.is-rail {
3394
+ inline-size: var(--op-navmenu-rail-width);
3395
+ }
3396
+ .op-navmenu.is-rail .op-navmenu__text,
3397
+ .op-navmenu.is-rail .op-navmenu__chevron,
3398
+ .op-navmenu.is-rail .op-navmenu__item.is-group .op-navmenu__icon {
3399
+ display: none;
3400
+ }
3401
+ .op-navmenu.is-rail .op-navmenu__item {
3402
+ justify-content: center;
3403
+ padding-inline: 0;
3404
+ }
3405
+ .op-navmenu.is-rail .op-navmenu__item.is-group {
3406
+ min-block-size: var(--op-space-3);
3407
+ border-block-start: var(--op-border-width) solid var(--op-color-border);
3408
+ border-radius: 0;
3409
+ pointer-events: none;
3410
+ }
3411
+ .op-navmenu.is-rail .op-navmenu__badge {
3412
+ display: none;
3413
+ }
3414
+ }
3415
+
3416
+ @layer optikos {
3417
+ :root {
3418
+ --op-stepper-marker-size: 1.75rem;
3419
+ }
3420
+ .op-stepper__list {
3421
+ display: flex;
3422
+ gap: var(--op-space-2);
3423
+ margin: 0;
3424
+ padding: 0;
3425
+ list-style: none;
3426
+ }
3427
+ .op-stepper__step {
3428
+ display: flex;
3429
+ flex: 1;
3430
+ min-inline-size: 0;
3431
+ }
3432
+ .op-stepper__step:last-child {
3433
+ flex: none;
3434
+ }
3435
+ /* the line to the next step: fills what is left after the text, level with the middle of the marker */
3436
+ .op-stepper__line {
3437
+ flex: 1;
3438
+ align-self: flex-start;
3439
+ min-inline-size: var(--op-space-3);
3440
+ margin-block-start: calc(var(--op-stepper-marker-size) / 2);
3441
+ margin-inline: var(--op-space-1) var(--op-space-2);
3442
+ block-size: var(--op-border-width);
3443
+ background: var(--op-stepper-line, var(--op-color-border-strong));
3444
+ }
3445
+ .op-stepper__step.is-done .op-stepper__line {
3446
+ background: var(--op-stepper-done-bg, var(--op-color-success));
3447
+ }
3448
+ .op-stepper__btn {
3449
+ display: flex;
3450
+ align-items: flex-start;
3451
+ gap: var(--op-space-2);
3452
+ min-inline-size: 0;
3453
+ padding: 0;
3454
+ font: inherit;
3455
+ color: var(--op-color-fg-muted);
3456
+ text-align: start;
3457
+ background: transparent;
3458
+ border: 0;
3459
+ border-radius: var(--op-radius);
3460
+ cursor: pointer;
3461
+ }
3462
+ .op-stepper__btn:disabled {
3463
+ cursor: default;
3464
+ }
3465
+ .op-stepper__btn:focus-visible {
3466
+ outline: var(--op-focus-width) solid var(--op-color-focus);
3467
+ outline-offset: var(--op-focus-offset);
3468
+ }
3469
+ .op-stepper__marker {
3470
+ display: inline-flex;
3471
+ flex: none;
3472
+ align-items: center;
3473
+ justify-content: center;
3474
+ inline-size: var(--op-stepper-marker-size);
3475
+ block-size: var(--op-stepper-marker-size);
3476
+ background: var(--op-color-surface);
3477
+ border: var(--op-border-width) solid var(--op-stepper-line, var(--op-color-border-strong));
3478
+ border-radius: 50%;
3479
+ font-size: var(--op-font-size-sm);
3480
+ font-weight: var(--op-font-weight-bold);
3481
+ }
3482
+ .op-stepper__text {
3483
+ display: flex;
3484
+ flex-direction: column;
3485
+ min-inline-size: 0;
3486
+ padding-inline-end: var(--op-space-2);
3487
+ background: inherit;
3488
+ }
3489
+ .op-stepper__title {
3490
+ overflow: hidden;
3491
+ text-overflow: ellipsis;
3492
+ white-space: nowrap;
3493
+ }
3494
+ .op-stepper__desc,
3495
+ .op-stepper__opt {
3496
+ font-size: var(--op-font-size-sm);
3497
+ color: var(--op-color-fg-muted);
3498
+ }
3499
+ .op-stepper__step.is-current .op-stepper__btn {
3500
+ color: var(--op-color-fg);
3501
+ font-weight: var(--op-font-weight-bold);
3502
+ }
3503
+ .op-stepper__step.is-current .op-stepper__marker {
3504
+ color: var(--op-color-primary-fg);
3505
+ background: var(--op-stepper-current-bg, var(--op-color-primary));
3506
+ border-color: var(--op-stepper-current-bg, var(--op-color-primary));
3507
+ }
3508
+ .op-stepper__step.is-done:not(.is-current) .op-stepper__marker {
3509
+ color: var(--op-color-success);
3510
+ border-color: var(--op-stepper-done-bg, var(--op-color-success));
3511
+ }
3512
+ .op-stepper__step.is-error .op-stepper__marker {
3513
+ color: var(--op-color-danger-fg);
3514
+ background: var(--op-stepper-error-bg, var(--op-color-danger));
3515
+ border-color: var(--op-stepper-error-bg, var(--op-color-danger));
3516
+ }
3517
+ .op-stepper__step.is-error .op-stepper__btn {
3518
+ color: var(--op-color-danger);
3519
+ }
3520
+ /* phones: only the current step shows its words; the others keep them for screen readers (the button's name) */
3521
+ @media (max-width: 40rem) {
3522
+ .op-stepper__step:not(.is-current) .op-stepper__text {
3523
+ position: absolute;
3524
+ inline-size: 0;
3525
+ block-size: 0;
3526
+ overflow: hidden;
3527
+ clip-path: inset(50%);
3528
+ white-space: nowrap;
3529
+ }
3530
+ .op-stepper__step:not(.is-current) {
3531
+ flex: none;
3532
+ }
3533
+ .op-stepper__step:not(.is-current) .op-stepper__line {
3534
+ min-inline-size: var(--op-space-2);
3535
+ }
3536
+ }
3537
+ }
3538
+
3539
+ @layer optikos {
3540
+ :root {
3541
+ --op-tabs-badge-min-width: 1.25em;
3542
+ }
3543
+ .op-tabs {
3544
+ display: flex;
3545
+ flex-direction: column;
3546
+ min-width: 0;
3547
+ min-height: 0;
3548
+ color: var(--op-color-fg);
3549
+ }
3550
+ .op-tabs--left {
3551
+ flex-direction: row;
3552
+ }
3553
+ .op-tabs__bar {
3554
+ display: flex;
3555
+ flex: none;
3556
+ gap: var(--op-tabs-gap, var(--op-space-1));
3557
+ background: var(--op-tabs-bar-bg, var(--op-color-surface-2));
3558
+ border-block-end: var(--op-border-width) solid var(--op-color-border);
3559
+ overflow-x: auto;
3560
+ overflow-y: hidden;
3561
+ }
3562
+ .op-tabs--left > .op-tabs__bar {
3563
+ flex-direction: column;
3564
+ border-block-end: 0;
3565
+ border-inline-end: var(--op-border-width) solid var(--op-color-border);
3566
+ overflow: visible;
3567
+ }
3568
+ .op-tabs__tab {
3569
+ display: inline-flex;
3570
+ align-items: center;
3571
+ gap: var(--op-space-2);
3572
+ padding: var(--op-tabs-tab-padding-y, var(--op-space-2)) var(--op-tabs-tab-padding-x, var(--op-space-4));
3573
+ color: var(--op-tabs-tab-fg, var(--op-color-fg-muted));
3574
+ border-block-end: var(--op-space-1) solid transparent;
3575
+ margin-block-end: calc(var(--op-border-width) * -1);
3576
+ cursor: pointer;
3577
+ white-space: nowrap;
3578
+ user-select: none;
3579
+ }
3580
+ .op-tabs--left > .op-tabs__bar > .op-tabs__tab {
3581
+ border-block-end: 0;
3582
+ border-inline-end: var(--op-space-1) solid transparent;
3583
+ margin-block-end: 0;
3584
+ margin-inline-end: calc(var(--op-border-width) * -1);
3585
+ }
3586
+ .op-tabs__tab:hover {
3587
+ color: var(--op-color-fg);
3588
+ }
3589
+ .op-tabs__tab.is-active {
3590
+ color: var(--op-tabs-tab-active-fg, var(--op-color-primary));
3591
+ border-color: var(--op-tabs-tab-active-border, var(--op-color-primary));
3592
+ font-weight: var(--op-font-weight-bold);
3593
+ }
3594
+ .op-tabs__tab[aria-disabled='true'] {
3595
+ color: var(--op-color-disabled-fg);
3596
+ cursor: not-allowed;
3597
+ }
3598
+ .op-tabs__close,
3599
+ .op-tabs__reload {
3600
+ display: inline-flex;
3601
+ border-radius: var(--op-radius-sm);
3602
+ }
3603
+ .op-tabs__close:hover,
3604
+ .op-tabs__reload:hover {
3605
+ background: var(--op-color-hover);
3606
+ }
3607
+ /* the ↻ turns while the tab reloads */
3608
+ .op-tabs__tab.is-reloading .op-tabs__reload svg {
3609
+ animation: op-spin 700ms linear infinite;
3610
+ }
3611
+ .op-motion-off .op-tabs__tab.is-reloading .op-tabs__reload svg {
3612
+ animation: none;
3613
+ }
3614
+ .op-tabs__panels {
3615
+ flex: 1;
3616
+ min-width: 0;
3617
+ min-height: 0;
3618
+ display: flex;
3619
+ flex-direction: column;
3620
+ }
3621
+ .op-tabs__panels > * {
3622
+ flex: 1;
3623
+ min-height: 0;
3624
+ overflow: auto;
3625
+ }
3626
+ .op-tabs__badge {
3627
+ display: inline-flex;
3628
+ align-items: center;
3629
+ justify-content: center;
3630
+ min-inline-size: var(--op-tabs-badge-min-width);
3631
+ padding: 0 var(--op-space-1);
3632
+ color: var(--op-color-danger-fg);
3633
+ background: var(--op-color-danger);
3634
+ border-radius: var(--op-radius-pill);
3635
+ font-size: var(--op-font-size-sm);
3636
+ font-weight: var(--op-font-weight-bold);
3637
+ }
3638
+ .op-tabs__tab.has-error {
3639
+ color: var(--op-color-danger);
3640
+ }
3641
+ .op-tabs__tab.is-dirty .op-tabs__title::after {
3642
+ content: '•';
3643
+ margin-inline-start: var(--op-space-1);
3644
+ color: var(--op-color-primary);
3645
+ }
3646
+ }
3647
+
3648
+ @layer optikos {
3649
+ :root {
3650
+ --op-palette-width: 38rem;
3651
+ --op-palette-top: 12vh;
3652
+ --op-palette-max-height: 26rem;
3653
+ }
3654
+ .op-palette-backdrop {
3655
+ position: fixed;
3656
+ inset: 0;
3657
+ display: flex;
3658
+ align-items: flex-start;
3659
+ justify-content: center;
3660
+ padding: var(--op-palette-top) var(--op-space-3) var(--op-space-3);
3661
+ background: var(--op-backdrop-bg, var(--op-color-overlay));
3662
+ }
3663
+ .op-palette {
3664
+ display: flex;
3665
+ flex-direction: column;
3666
+ inline-size: min(var(--op-palette-width), 100%);
3667
+ max-block-size: 100%;
3668
+ color: var(--op-color-fg);
3669
+ background: var(--op-palette-bg, var(--op-color-surface));
3670
+ border: var(--op-border-width) solid var(--op-color-border);
3671
+ border-radius: var(--op-palette-radius, var(--op-radius-lg));
3672
+ box-shadow: var(--op-shadow-lg);
3673
+ overflow: hidden;
3674
+ }
3675
+ .op-palette__search {
3676
+ display: flex;
3677
+ align-items: center;
3678
+ gap: var(--op-space-2);
3679
+ padding: var(--op-space-3) var(--op-space-4);
3680
+ color: var(--op-color-fg-muted);
3681
+ border-block-end: var(--op-border-width) solid var(--op-color-border);
3682
+ }
3683
+ .op-palette__crumb {
3684
+ flex: none;
3685
+ padding: 0 var(--op-space-2);
3686
+ color: var(--op-color-primary);
3687
+ background: var(--op-color-primary-soft);
3688
+ border-radius: var(--op-radius-sm);
3689
+ font-size: var(--op-font-size-sm);
3690
+ white-space: nowrap;
3691
+ }
3692
+ .op-palette__crumb[hidden],
3693
+ .op-palette__filters[hidden] {
3694
+ display: none;
3695
+ }
3696
+ .op-palette__input {
3697
+ flex: 1;
3698
+ min-inline-size: 0;
3699
+ padding: 0;
3700
+ font: inherit;
3701
+ font-size: var(--op-font-size-lg);
3702
+ color: var(--op-color-fg);
3703
+ background: transparent;
3704
+ border: 0;
3705
+ outline: none;
3706
+ }
3707
+ .op-palette__filters {
3708
+ display: flex;
3709
+ flex-wrap: wrap;
3710
+ gap: var(--op-space-1);
3711
+ padding: var(--op-space-2) var(--op-space-4) 0;
3712
+ }
3713
+ .op-palette__chip {
3714
+ padding: 0 var(--op-space-3);
3715
+ font: inherit;
3716
+ font-size: var(--op-font-size-sm);
3717
+ color: var(--op-color-fg-muted);
3718
+ background: transparent;
3719
+ border: var(--op-border-width) solid var(--op-color-border);
3720
+ border-radius: var(--op-radius-pill);
3721
+ cursor: pointer;
3722
+ }
3723
+ .op-palette__chip.is-on {
3724
+ color: var(--op-color-primary-fg);
3725
+ background: var(--op-color-primary);
3726
+ border-color: var(--op-color-primary);
3727
+ }
3728
+ .op-palette__chip:focus-visible {
3729
+ outline: var(--op-focus-width) solid var(--op-color-focus);
3730
+ }
3731
+ .op-palette__list {
3732
+ flex: 1;
3733
+ min-block-size: 0;
3734
+ max-block-size: var(--op-palette-max-height);
3735
+ padding: var(--op-space-2);
3736
+ overflow: auto;
3737
+ }
3738
+ .op-palette__group {
3739
+ padding: var(--op-space-2) var(--op-space-3) var(--op-space-1);
3740
+ color: var(--op-palette-group-fg, var(--op-color-fg-muted));
3741
+ font-size: var(--op-font-size-sm);
3742
+ font-weight: var(--op-font-weight-bold);
3743
+ }
3744
+ .op-palette__item {
3745
+ display: flex;
3746
+ align-items: center;
3747
+ gap: var(--op-space-3);
3748
+ padding: var(--op-space-2) var(--op-space-3);
3749
+ border-radius: var(--op-radius);
3750
+ cursor: pointer;
3751
+ }
3752
+ .op-palette__item.is-active {
3753
+ background: var(--op-palette-item-active-bg, var(--op-color-hover));
3754
+ }
3755
+ .op-palette__item.is-disabled {
3756
+ color: var(--op-color-disabled-fg);
3757
+ cursor: not-allowed;
3758
+ }
3759
+ .op-palette__icon {
3760
+ display: inline-flex;
3761
+ flex: none;
3762
+ inline-size: var(--op-icon-size);
3763
+ color: var(--op-color-fg-muted);
3764
+ }
3765
+ .op-palette__text {
3766
+ display: flex;
3767
+ flex: 1;
3768
+ flex-direction: column;
3769
+ min-inline-size: 0;
3770
+ }
3771
+ .op-palette__title {
3772
+ overflow: hidden;
3773
+ text-overflow: ellipsis;
3774
+ white-space: nowrap;
3775
+ }
3776
+ .op-palette__desc {
3777
+ color: var(--op-color-fg-muted);
3778
+ font-size: var(--op-font-size-sm);
3779
+ }
3780
+ .op-palette__mark {
3781
+ color: inherit;
3782
+ background: var(--op-color-primary-soft);
3783
+ font-weight: var(--op-font-weight-bold);
3784
+ }
3785
+ .op-palette__cat,
3786
+ .op-palette__kbd {
3787
+ flex: none;
3788
+ color: var(--op-color-fg-muted);
3789
+ font-size: var(--op-font-size-sm);
3790
+ }
3791
+ .op-palette__kbd {
3792
+ padding: 0 var(--op-space-2);
3793
+ font-family: var(--op-font-mono);
3794
+ background: var(--op-color-surface-2);
3795
+ border: var(--op-border-width) solid var(--op-color-border);
3796
+ border-radius: var(--op-radius-sm);
3797
+ }
3798
+ .op-palette__more {
3799
+ display: inline-flex;
3800
+ color: var(--op-color-fg-muted);
3801
+ }
3802
+ .op-palette__empty {
3803
+ padding: var(--op-space-5);
3804
+ color: var(--op-color-fg-muted);
3805
+ text-align: center;
3806
+ }
3807
+ .op-palette__hint {
3808
+ padding: var(--op-space-2) var(--op-space-4);
3809
+ color: var(--op-color-fg-muted);
3810
+ font-size: var(--op-font-size-sm);
3811
+ background: var(--op-color-surface-2);
3812
+ border-block-start: var(--op-border-width) solid var(--op-color-border);
3813
+ }
3814
+ }
3815
+
3816
+ @layer optikos {
3817
+ .op-dropdown {
3818
+ position: fixed;
3819
+ box-sizing: border-box;
3820
+ max-inline-size: calc(100vw - var(--op-space-4));
3821
+ color: var(--op-dropdown-fg, var(--op-color-fg));
3822
+ background: var(--op-dropdown-bg, var(--op-color-surface));
3823
+ border: var(--op-border-width) solid var(--op-dropdown-border, var(--op-color-border));
3824
+ border-radius: var(--op-dropdown-radius, var(--op-radius));
3825
+ box-shadow: var(--op-dropdown-shadow, var(--op-shadow));
3826
+ overflow: hidden;
3827
+ }
3828
+ }
3829
+
3830
+ @layer optikos {
3831
+ :root {
3832
+ --op-menu-min-width: 10rem;
3833
+ --op-menu-max-height: 22rem;
3834
+ --op-menu-group-tracking: 0.04em;
3835
+ }
3836
+ .op-menu {
3837
+ box-sizing: border-box;
3838
+ min-inline-size: var(--op-menu-min-width);
3839
+ padding: var(--op-menu-padding, var(--op-space-1));
3840
+ color: var(--op-color-fg);
3841
+ background: var(--op-menu-bg, var(--op-color-surface));
3842
+ }
3843
+ .op-menu__item {
3844
+ display: flex;
3845
+ align-items: center;
3846
+ gap: var(--op-space-2);
3847
+ min-block-size: var(--op-menu-item-height, var(--op-control-height));
3848
+ padding: 0 var(--op-menu-item-padding-x, var(--op-space-3)) 0 var(--op-space-2);
3849
+ border-radius: var(--op-radius-sm);
3850
+ cursor: pointer;
3851
+ outline: none;
3852
+ }
3853
+ .op-menu__item:hover,
3854
+ .op-menu__item:focus {
3855
+ background: var(--op-menu-item-hover-bg, var(--op-color-hover));
3856
+ }
3857
+ .op-menu__item[aria-disabled='true'] {
3858
+ color: var(--op-color-disabled-fg);
3859
+ cursor: not-allowed;
3860
+ }
3861
+ .op-menu__icon {
3862
+ display: inline-flex;
3863
+ inline-size: var(--op-icon-size);
3864
+ }
3865
+ .op-menu__text {
3866
+ flex: 1;
3867
+ white-space: nowrap;
3868
+ }
3869
+ .op-menu__arrow {
3870
+ display: inline-flex;
3871
+ color: var(--op-color-fg-muted);
3872
+ }
3873
+ .op-menu__sep {
3874
+ margin-block: var(--op-space-1);
3875
+ block-size: var(--op-border-width);
3876
+ background: var(--op-menu-sep, var(--op-color-border));
3877
+ }
3878
+ /* with search: the field on top, the items scroll under it */
3879
+ .op-menu__search {
3880
+ box-sizing: border-box;
3881
+ inline-size: 100%;
3882
+ min-block-size: var(--op-control-height);
3883
+ margin-block-end: var(--op-space-1);
3884
+ padding: 0 var(--op-space-2);
3885
+ color: var(--op-color-fg);
3886
+ background: var(--op-color-surface);
3887
+ border: var(--op-border-width) solid var(--op-color-border-strong);
3888
+ border-radius: var(--op-radius-sm);
3889
+ font: inherit;
3890
+ }
3891
+ .op-menu__search:focus-visible {
3892
+ outline: var(--op-focus-width) solid var(--op-color-focus);
3893
+ outline-offset: calc(var(--op-focus-width) * -1);
3894
+ }
3895
+ .op-menu__list {
3896
+ max-block-size: var(--op-menu-max-height);
3897
+ overflow: auto;
3898
+ }
3899
+ .op-menu__empty {
3900
+ padding: var(--op-space-2) var(--op-space-3);
3901
+ color: var(--op-color-fg-muted);
3902
+ font-size: var(--op-font-size-sm);
3903
+ }
3904
+ .op-menu.is-searching .op-menu__sep,
3905
+ .op-menu__group:not(:has(.op-menu__item:not([hidden]))) {
3906
+ display: none;
3907
+ }
3908
+ /* groups: a quiet header over the items that share it */
3909
+ .op-menu__group + .op-menu__group,
3910
+ .op-menu__item + .op-menu__group {
3911
+ margin-block-start: var(--op-space-1);
3912
+ }
3913
+ .op-menu__group-label {
3914
+ padding: var(--op-space-2) var(--op-space-3) var(--op-space-1) var(--op-space-2);
3915
+ color: var(--op-menu-group-fg, var(--op-color-fg-muted));
3916
+ font-size: var(--op-font-size-sm);
3917
+ font-weight: var(--op-font-weight-bold);
3918
+ letter-spacing: var(--op-menu-group-tracking);
3919
+ text-transform: uppercase;
3920
+ }
3921
+ }
3922
+
3923
+ @layer optikos {
3924
+ .op-messagebox__icon {
3925
+ font-size: var(--op-font-size-xl);
3926
+ color: var(--op-color-primary);
3927
+ }
3928
+ }
3929
+
3930
+ @layer optikos {
3931
+ :root {
3932
+ --op-toast-width: 22rem;
3933
+ --op-z-toast: 2;
3934
+ }
3935
+ .op-toast-region {
3936
+ position: fixed;
3937
+ display: flex;
3938
+ flex-direction: column;
3939
+ gap: var(--op-toast-gap, var(--op-space-2));
3940
+ padding: var(--op-space-4);
3941
+ max-inline-size: 100%;
3942
+ z-index: var(--op-z-toast);
3943
+ pointer-events: none;
3944
+ }
3945
+ .op-toast-region > * {
3946
+ pointer-events: auto;
3947
+ }
3948
+ .op-toast-region[data-pos^='top'] {
3949
+ inset-block-start: 0;
3950
+ }
3951
+ .op-toast-region[data-pos^='bottom'] {
3952
+ inset-block-end: 0;
3953
+ }
3954
+ .op-toast-region[data-pos$='right'] {
3955
+ inset-inline-end: 0;
3956
+ }
3957
+ .op-toast-region[data-pos$='left'] {
3958
+ inset-inline-start: 0;
3959
+ }
3960
+ .op-toast-region[data-pos='top'],
3961
+ .op-toast-region[data-pos='bottom'] {
3962
+ inset-inline: 0;
3963
+ align-items: center;
3964
+ }
3965
+ .op-toast {
3966
+ --_accent: var(--op-toast-accent-info, var(--op-color-info));
3967
+ display: flex;
3968
+ align-items: flex-start;
3969
+ gap: var(--op-space-2);
3970
+ box-sizing: border-box;
3971
+ inline-size: var(--op-toast-width);
3972
+ max-inline-size: 100%;
3973
+ padding: var(--op-space-3);
3974
+ color: var(--op-toast-fg, var(--op-color-fg));
3975
+ background: var(--op-toast-bg, var(--op-color-surface));
3976
+ border: var(--op-border-width) solid var(--op-color-border);
3977
+ border-inline-start: var(--op-space-1) solid var(--_accent);
3978
+ border-radius: var(--op-toast-radius, var(--op-radius));
3979
+ box-shadow: var(--op-toast-shadow, var(--op-shadow));
3980
+ animation: op-toast-in var(--op-duration) var(--op-easing);
3981
+ }
3982
+ .op-toast--success {
3983
+ --_accent: var(--op-toast-accent-success, var(--op-color-success));
3984
+ }
3985
+ .op-toast--warning {
3986
+ --_accent: var(--op-toast-accent-warning, var(--op-color-warning));
3987
+ }
3988
+ .op-toast--error {
3989
+ --_accent: var(--op-toast-accent-error, var(--op-color-danger));
3990
+ }
3991
+ .op-toast__icon {
3992
+ color: var(--_accent);
3993
+ display: inline-flex;
3994
+ }
3995
+ .op-toast__body {
3996
+ flex: 1;
3997
+ min-inline-size: 0;
3998
+ }
3999
+ .op-toast__title {
4000
+ font-weight: var(--op-font-weight-bold);
4001
+ }
4002
+ .op-toast__close {
4003
+ display: inline-flex;
4004
+ padding: var(--op-space-1);
4005
+ color: var(--op-color-fg-muted);
4006
+ background: transparent;
4007
+ border: 0;
4008
+ border-radius: var(--op-radius-sm);
4009
+ cursor: pointer;
4010
+ }
4011
+ .op-toast__close:hover {
4012
+ background: var(--op-color-hover);
4013
+ }
4014
+ @keyframes op-toast-in {
4015
+ from {
4016
+ opacity: 0;
4017
+ transform: translateY(calc(var(--op-space-2) * -1));
4018
+ }
4019
+ }
4020
+ }
4021
+
4022
+ @layer optikos {
4023
+ :root {
4024
+ --op-tooltip-max-width: 20rem;
4025
+ }
4026
+ .op-tooltip {
4027
+ position: fixed;
4028
+ box-sizing: border-box;
4029
+ max-inline-size: var(--op-tooltip-max-width);
4030
+ padding: var(--op-tooltip-padding, var(--op-space-1) var(--op-space-2));
4031
+ color: var(--op-tooltip-fg, var(--op-color-inverse-fg));
4032
+ background: var(--op-tooltip-bg, var(--op-color-inverse-bg));
4033
+ border-radius: var(--op-tooltip-radius, var(--op-radius-sm));
4034
+ font-size: var(--op-tooltip-font-size, var(--op-font-size-sm));
4035
+ pointer-events: none;
4036
+ overflow-wrap: anywhere;
4037
+ }
4038
+ }
4039
+
4040
+ @layer optikos {
4041
+ :root {
4042
+ --op-widget-width: 24rem;
4043
+ --op-widget-height: 26rem;
4044
+ --op-widget-wide: 36rem;
4045
+ --op-widget-offset: var(--op-space-4);
4046
+ --op-widget-grip: 0.5rem;
4047
+ --op-widget-corner: 1rem;
4048
+ }
4049
+ .op-widget {
4050
+ min-block-size: 0;
4051
+ background: var(--op-widget-bg, var(--op-color-surface));
4052
+ border-radius: var(--op-widget-radius, var(--op-radius-lg));
4053
+ }
4054
+ .op-widget.is-floating {
4055
+ --_from: translateX(0);
4056
+ position: fixed;
4057
+ box-shadow: var(--op-widget-shadow, var(--op-shadow-lg));
4058
+ opacity: 0;
4059
+ transform: var(--_from);
4060
+ transition: transform var(--op-duration) var(--op-easing), opacity var(--op-duration) var(--op-easing);
4061
+ }
4062
+ .op-widget.is-floating.is-open {
4063
+ opacity: 1;
4064
+ transform: none;
4065
+ }
4066
+ .op-widget.is-floating[hidden] {
4067
+ display: none;
4068
+ }
4069
+ /* sides: a column on the left/right, a bar (anchored to the end corner) on top/bottom */
4070
+ .op-widget--right.is-floating,
4071
+ .op-widget--left.is-floating {
4072
+ inset-block: var(--op-widget-offset);
4073
+ inline-size: var(--op-widget-size, var(--op-widget-width));
4074
+ max-inline-size: calc(100% - 2 * var(--op-widget-offset));
4075
+ }
4076
+ .op-widget--right.is-floating {
4077
+ inset-inline-end: var(--op-widget-offset);
4078
+ --_from: translateX(calc(100% + var(--op-widget-offset)));
4079
+ }
4080
+ .op-widget--left.is-floating {
4081
+ inset-inline-start: var(--op-widget-offset);
4082
+ --_from: translateX(calc(-100% - var(--op-widget-offset)));
4083
+ }
4084
+ .op-widget--top.is-floating,
4085
+ .op-widget--bottom.is-floating {
4086
+ inset-inline-end: var(--op-widget-offset);
4087
+ inline-size: min(var(--op-widget-wide), calc(100% - 2 * var(--op-widget-offset)));
4088
+ block-size: var(--op-widget-size, var(--op-widget-height));
4089
+ max-block-size: calc(100% - 2 * var(--op-widget-offset));
4090
+ }
4091
+ .op-widget--top.is-floating {
4092
+ inset-block-start: var(--op-widget-offset);
4093
+ --_from: translateY(calc(-100% - var(--op-widget-offset)));
4094
+ }
4095
+ .op-widget--bottom.is-floating {
4096
+ inset-block-end: var(--op-widget-offset);
4097
+ --_from: translateY(calc(100% + var(--op-widget-offset)));
4098
+ }
4099
+ .op-widget [aria-pressed='true'] {
4100
+ color: var(--op-color-primary);
4101
+ background: var(--op-color-primary-soft);
4102
+ }
4103
+ /* dragged: no longer tied to a side; the slide-in becomes a small rise */
4104
+ .op-widget.is-moved.is-floating {
4105
+ --_from: translateY(var(--op-space-3));
4106
+ }
4107
+ .op-widget__handle {
4108
+ cursor: grab;
4109
+ user-select: none;
4110
+ touch-action: none;
4111
+ }
4112
+ .op-widget.is-dragging .op-widget__handle {
4113
+ cursor: grabbing;
4114
+ }
4115
+ .op-widget.is-dragging {
4116
+ transition: none;
4117
+ }
4118
+ /* resize: an invisible strip on the inner edge (a line shows on hover/focus); a corner grip once the widget was moved */
4119
+ .op-widget__resize {
4120
+ position: absolute;
4121
+ z-index: 1;
4122
+ touch-action: none;
4123
+ }
4124
+ .op-widget--right .op-widget__resize,
4125
+ .op-widget--left .op-widget__resize {
4126
+ inset-block: 0;
4127
+ inline-size: var(--op-widget-grip);
4128
+ cursor: ew-resize;
4129
+ }
4130
+ .op-widget--right .op-widget__resize {
4131
+ inset-inline-start: calc(var(--op-widget-grip) / -2);
4132
+ }
4133
+ .op-widget--left .op-widget__resize {
4134
+ inset-inline-end: calc(var(--op-widget-grip) / -2);
4135
+ }
4136
+ .op-widget--top .op-widget__resize,
4137
+ .op-widget--bottom .op-widget__resize {
4138
+ inset-inline: 0;
4139
+ block-size: var(--op-widget-grip);
4140
+ cursor: ns-resize;
4141
+ }
4142
+ .op-widget--top .op-widget__resize {
4143
+ inset-block-end: calc(var(--op-widget-grip) / -2);
4144
+ }
4145
+ .op-widget--bottom .op-widget__resize {
4146
+ inset-block-start: calc(var(--op-widget-grip) / -2);
4147
+ }
4148
+ .op-widget__resize:hover,
4149
+ .op-widget__resize:focus-visible,
4150
+ .op-widget.is-resizing .op-widget__resize {
4151
+ background: linear-gradient(var(--op-color-primary), var(--op-color-primary)) center / var(--op-focus-width) 100% no-repeat;
4152
+ outline: none;
4153
+ }
4154
+ .op-widget--top .op-widget__resize:is(:hover, :focus-visible),
4155
+ .op-widget--bottom .op-widget__resize:is(:hover, :focus-visible),
4156
+ .op-widget--top.is-resizing .op-widget__resize,
4157
+ .op-widget--bottom.is-resizing .op-widget__resize {
4158
+ background-size: 100% var(--op-focus-width);
4159
+ }
4160
+ .op-widget.is-moved .op-widget__resize {
4161
+ inset: auto 0 0 auto;
4162
+ inline-size: var(--op-widget-corner);
4163
+ block-size: var(--op-widget-corner);
4164
+ background: linear-gradient(135deg, transparent 55%, var(--op-color-border-strong) 55% 62%, transparent 62% 75%, var(--op-color-border-strong) 75% 82%, transparent 82%);
4165
+ cursor: nwse-resize;
4166
+ }
4167
+ .op-widget.is-moved .op-widget__resize:focus-visible {
4168
+ outline: var(--op-focus-width) solid var(--op-color-focus);
4169
+ }
4170
+ .op-widget.is-resizing {
4171
+ transition: none;
4172
+ user-select: none;
4173
+ }
4174
+ }
4175
+
4176
+ @layer optikos {
4177
+ :root {
4178
+ --op-window-width: 28rem;
4179
+ }
4180
+ .op-window-backdrop {
4181
+ position: fixed;
4182
+ inset: 0;
4183
+ background: var(--op-backdrop-bg, var(--op-color-overlay));
4184
+ }
4185
+ /* mask: false — still modal (the page is inert and takes no clicks), just not dimmed */
4186
+ .op-window-backdrop.is-clear {
4187
+ background: transparent;
4188
+ }
4189
+ .op-window {
4190
+ position: fixed;
4191
+ inline-size: var(--op-window-width);
4192
+ max-inline-size: calc(100vw - var(--op-space-4));
4193
+ max-block-size: calc(100vh - var(--op-space-4));
4194
+ max-block-size: calc(100dvh - var(--op-space-4));
4195
+ background: var(--op-window-bg, var(--op-color-surface));
4196
+ border-radius: var(--op-window-radius, var(--op-radius-lg));
4197
+ box-shadow: var(--op-window-shadow, var(--op-shadow-lg));
4198
+ }
4199
+ .op-window:focus {
4200
+ outline: none;
4201
+ }
4202
+ .op-window__handle {
4203
+ cursor: grab;
4204
+ user-select: none;
4205
+ touch-action: none;
4206
+ }
4207
+ .op-window.is-dragging .op-window__handle {
4208
+ cursor: grabbing;
4209
+ }
4210
+ }
4211
+
4212
+ @layer optikos {
4213
+ :root {
4214
+ --op-motion-ease-out: cubic-bezier(0, 0, 0.2, 1);
4215
+ --op-motion-ease-in: cubic-bezier(0.4, 0, 1, 1);
4216
+ --op-motion-ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
4217
+ --op-motion-press-scale: 0.97;
4218
+ --op-motion-press-duration: 100ms;
4219
+ --op-motion-popover-scale: 0.95;
4220
+ --op-motion-dropdown-duration: 200ms;
4221
+ --op-motion-exit-ratio: 0.8;
4222
+ --op-motion-stagger-step: 30ms;
4223
+ --op-motion-blur: 4px;
4224
+ }
4225
+ /* Rule 4: interactive things shrink a little under the finger. Rule 14: while held, only transform may animate. */
4226
+ .op-button:active:not(:disabled),
4227
+ .op-dataview__item:active,
4228
+ [data-op-press]:active {
4229
+ transform: scale(var(--op-motion-press-scale));
4230
+ transition-property: transform;
4231
+ transition-duration: var(--op-motion-press-duration);
4232
+ transition-timing-function: var(--op-motion-ease-out);
4233
+ }
4234
+ [data-op-press] {
4235
+ transition: transform var(--op-motion-press-duration) var(--op-motion-ease-out);
4236
+ }
4237
+ .op-dataview__item {
4238
+ transition: transform var(--op-motion-press-duration) var(--op-motion-ease-out), box-shadow var(--op-duration) var(--op-easing);
4239
+ }
4240
+ }