@invisibleloop/pulse 0.1.21

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 (344) hide show
  1. package/.claude/commands/build-page.md +59 -0
  2. package/.claude/commands/new-doc-page.md +45 -0
  3. package/.claude/commands/verify.md +52 -0
  4. package/.claude/pulse-checklist.md +111 -0
  5. package/.claude/settings.local.json +102 -0
  6. package/.github/workflows/ci.yml +22 -0
  7. package/.github/workflows/publish.yml +41 -0
  8. package/.pulse/load-reports/home/1773432711417.json +22 -0
  9. package/CLAUDE.md +383 -0
  10. package/README.md +95 -0
  11. package/docs/.claude/pulse-checklist.md +111 -0
  12. package/docs/public/.pulse-ui-version +1 -0
  13. package/docs/public/dist/accessibility.boot-5DVTARJU.js +115 -0
  14. package/docs/public/dist/actions.boot-P66HKQEM.js +164 -0
  15. package/docs/public/dist/auth.boot-IMAJAUPH.js +140 -0
  16. package/docs/public/dist/caching.boot-DVR6KDE7.js +53 -0
  17. package/docs/public/dist/components--accordion.boot-3HVKMNWC.js +11 -0
  18. package/docs/public/dist/components--alert.boot-GCEXOZAC.js +6 -0
  19. package/docs/public/dist/components--app-badge.boot-DVT3GCHJ.js +6 -0
  20. package/docs/public/dist/components--avatar.boot-PSW24EVA.js +5 -0
  21. package/docs/public/dist/components--badge.boot-TYDY2RMK.js +7 -0
  22. package/docs/public/dist/components--banner.boot-EI5PZSZK.js +7 -0
  23. package/docs/public/dist/components--breadcrumbs.boot-SMA2E2GO.js +34 -0
  24. package/docs/public/dist/components--button.boot-J54BQM2E.js +23 -0
  25. package/docs/public/dist/components--card.boot-PZGNDIB6.js +138 -0
  26. package/docs/public/dist/components--carousel.boot-TP6LPFZZ.js +12 -0
  27. package/docs/public/dist/components--charts.boot-2EOYQWKL.js +108 -0
  28. package/docs/public/dist/components--checkbox.boot-DS5BSL6T.js +54 -0
  29. package/docs/public/dist/components--cluster.boot-HHVIBBJG.js +9 -0
  30. package/docs/public/dist/components--code-window.boot-2GR2DV33.js +20 -0
  31. package/docs/public/dist/components--container.boot-7LOOGK2K.js +5 -0
  32. package/docs/public/dist/components--cta.boot-FSNZ5YRT.js +11 -0
  33. package/docs/public/dist/components--divider.boot-3NI2C3QG.js +6 -0
  34. package/docs/public/dist/components--empty.boot-YX2UR3PV.js +7 -0
  35. package/docs/public/dist/components--feature.boot-MUD7NSUO.js +13 -0
  36. package/docs/public/dist/components--fieldset.boot-J7BYHMKF.js +19 -0
  37. package/docs/public/dist/components--fileupload.boot-NIKVTTPD.js +52 -0
  38. package/docs/public/dist/components--footer.boot-EYUK5FRG.js +14 -0
  39. package/docs/public/dist/components--grid.boot-URDQVDDR.js +59 -0
  40. package/docs/public/dist/components--heading.boot-BPQKU43E.js +44 -0
  41. package/docs/public/dist/components--hero.boot-4RAPRGAB.js +17 -0
  42. package/docs/public/dist/components--icons.boot-ZITNU5JP.js +68 -0
  43. package/docs/public/dist/components--image.boot-XEEGHQZF.js +19 -0
  44. package/docs/public/dist/components--input.boot-SGASZG5K.js +7 -0
  45. package/docs/public/dist/components--list.boot-W3XC5MHD.js +55 -0
  46. package/docs/public/dist/components--media.boot-5VFIETZO.js +13 -0
  47. package/docs/public/dist/components--modal.boot-RZUYXBN2.js +47 -0
  48. package/docs/public/dist/components--nav.boot-ODBOHU7O.js +33 -0
  49. package/docs/public/dist/components--pricing.boot-4AQ4ZVBY.js +21 -0
  50. package/docs/public/dist/components--progress.boot-GHAGYZOK.js +30 -0
  51. package/docs/public/dist/components--prose.boot-QANJL6JI.js +67 -0
  52. package/docs/public/dist/components--pullquote.boot-Q2WMNAZU.js +22 -0
  53. package/docs/public/dist/components--radio.boot-TJRDQ2OL.js +75 -0
  54. package/docs/public/dist/components--rating.boot-QBAN6DEL.js +38 -0
  55. package/docs/public/dist/components--search.boot-PXH5O5AG.js +17 -0
  56. package/docs/public/dist/components--section.boot-AQGIYHWW.js +12 -0
  57. package/docs/public/dist/components--segmented.boot-BEVTKEJO.js +33 -0
  58. package/docs/public/dist/components--select.boot-47X5RHOC.js +10 -0
  59. package/docs/public/dist/components--slider.boot-PSRRX7XL.js +47 -0
  60. package/docs/public/dist/components--spinner.boot-MZ5MO2OH.js +22 -0
  61. package/docs/public/dist/components--stack.boot-DI4NJXBF.js +9 -0
  62. package/docs/public/dist/components--stat.boot-QMFUWBQT.js +9 -0
  63. package/docs/public/dist/components--stepper.boot-34PP2NEV.js +22 -0
  64. package/docs/public/dist/components--table.boot-FCQGSFIQ.js +11 -0
  65. package/docs/public/dist/components--testimonial.boot-DWQPDKYG.js +11 -0
  66. package/docs/public/dist/components--textarea.boot-QVXLBOJ5.js +4 -0
  67. package/docs/public/dist/components--timeline.boot-26LN52P2.js +95 -0
  68. package/docs/public/dist/components--toggle.boot-IQQEI76S.js +29 -0
  69. package/docs/public/dist/components--tooltip.boot-LGHCO6NN.js +9 -0
  70. package/docs/public/dist/components.boot-SE6PQ4P7.js +103 -0
  71. package/docs/public/dist/config.boot-DTRRWUE6.js +126 -0
  72. package/docs/public/dist/constraints.boot-DUHDZBMC.js +71 -0
  73. package/docs/public/dist/deploy.boot-SLAD3NI2.js +163 -0
  74. package/docs/public/dist/docs-8e3d4b5c.css +1 -0
  75. package/docs/public/dist/extending.boot-UA3CN243.js +159 -0
  76. package/docs/public/dist/faq.boot-6EQAWLQR.js +43 -0
  77. package/docs/public/dist/getting-started.boot-TDKIFL5U.js +86 -0
  78. package/docs/public/dist/guard.boot-AUHAWTG4.js +80 -0
  79. package/docs/public/dist/home.boot-BVQXRH32.js +383 -0
  80. package/docs/public/dist/how-it-works.boot-LTWAKWKW.js +104 -0
  81. package/docs/public/dist/hydration.boot-JRM6IPJL.js +78 -0
  82. package/docs/public/dist/images.boot-M6ZVKTZS.js +80 -0
  83. package/docs/public/dist/manifest.json +94 -0
  84. package/docs/public/dist/meta.boot-7NXGPHR4.js +79 -0
  85. package/docs/public/dist/mutations.boot-F6F43UDX.js +79 -0
  86. package/docs/public/dist/navigation.boot-AOXWS3ZF.js +57 -0
  87. package/docs/public/dist/performance.boot-C3UPCOBK.js +98 -0
  88. package/docs/public/dist/persist.boot-WT32PQOQ.js +61 -0
  89. package/docs/public/dist/project-structure.boot-FB3LRVJ4.js +63 -0
  90. package/docs/public/dist/prompt-examples.boot-YKR4VDK4.js +31 -0
  91. package/docs/public/dist/pulse-ui-81a85c03.css +1 -0
  92. package/docs/public/dist/raw-responses.boot-M4KA5YXL.js +104 -0
  93. package/docs/public/dist/routing.boot-FNX5FDGH.js +70 -0
  94. package/docs/public/dist/runtime-B73WLANC.js +1 -0
  95. package/docs/public/dist/runtime-KO4BHUQ3.js +49 -0
  96. package/docs/public/dist/runtime-L2HNXIHW.js +59 -0
  97. package/docs/public/dist/runtime-QFURDKA2.js +5 -0
  98. package/docs/public/dist/runtime-UVPXO4IR.js +375 -0
  99. package/docs/public/dist/runtime-VMJA3Z4N.js +10 -0
  100. package/docs/public/dist/runtime-ZJ4FXT5O.js +11 -0
  101. package/docs/public/dist/server-api.boot-K7X3LCFB.js +219 -0
  102. package/docs/public/dist/server-data.boot-Y7HQYC4R.js +157 -0
  103. package/docs/public/dist/slash-commands.boot-V2UV7OW2.js +26 -0
  104. package/docs/public/dist/spec.boot-2WU7ZHCV.js +159 -0
  105. package/docs/public/dist/state.boot-B24GUE3R.js +73 -0
  106. package/docs/public/dist/store.boot-TLIB4XHH.js +150 -0
  107. package/docs/public/dist/streaming.boot-W2DZSMW4.js +80 -0
  108. package/docs/public/dist/stripe.boot-QN3C2GEL.js +164 -0
  109. package/docs/public/dist/supabase.boot-BG4XXLZE.js +303 -0
  110. package/docs/public/dist/testing.boot-6U4WKMTE.js +130 -0
  111. package/docs/public/dist/validation.boot-PQHYGW5B.js +100 -0
  112. package/docs/public/docs.css +2020 -0
  113. package/docs/public/menu.js +83 -0
  114. package/docs/public/pulse-ui.css +2739 -0
  115. package/docs/public/pulse-ui.js +236 -0
  116. package/docs/server.js +192 -0
  117. package/docs/src/lib/component-page.js +47 -0
  118. package/docs/src/lib/highlight.js +255 -0
  119. package/docs/src/lib/layout.js +131 -0
  120. package/docs/src/lib/metrics-store.js +6 -0
  121. package/docs/src/lib/nav.js +159 -0
  122. package/docs/src/lib/stats.js +81 -0
  123. package/docs/src/pages/accessibility.js +157 -0
  124. package/docs/src/pages/actions.js +191 -0
  125. package/docs/src/pages/auth.js +177 -0
  126. package/docs/src/pages/caching.js +95 -0
  127. package/docs/src/pages/components/accordion.js +48 -0
  128. package/docs/src/pages/components/alert.js +35 -0
  129. package/docs/src/pages/components/app-badge.js +41 -0
  130. package/docs/src/pages/components/avatar.js +35 -0
  131. package/docs/src/pages/components/badge.js +36 -0
  132. package/docs/src/pages/components/banner.js +45 -0
  133. package/docs/src/pages/components/breadcrumbs.js +94 -0
  134. package/docs/src/pages/components/button.js +84 -0
  135. package/docs/src/pages/components/card.js +225 -0
  136. package/docs/src/pages/components/carousel.js +72 -0
  137. package/docs/src/pages/components/charts.js +278 -0
  138. package/docs/src/pages/components/checkbox.js +129 -0
  139. package/docs/src/pages/components/cluster.js +47 -0
  140. package/docs/src/pages/components/code-window.js +57 -0
  141. package/docs/src/pages/components/container.js +40 -0
  142. package/docs/src/pages/components/cta.js +53 -0
  143. package/docs/src/pages/components/divider.js +37 -0
  144. package/docs/src/pages/components/empty.js +36 -0
  145. package/docs/src/pages/components/feature.js +60 -0
  146. package/docs/src/pages/components/fieldset.js +65 -0
  147. package/docs/src/pages/components/fileupload.js +127 -0
  148. package/docs/src/pages/components/footer.js +58 -0
  149. package/docs/src/pages/components/grid.js +165 -0
  150. package/docs/src/pages/components/heading.js +107 -0
  151. package/docs/src/pages/components/hero.js +65 -0
  152. package/docs/src/pages/components/icons.js +285 -0
  153. package/docs/src/pages/components/image.js +71 -0
  154. package/docs/src/pages/components/input.js +51 -0
  155. package/docs/src/pages/components/list.js +112 -0
  156. package/docs/src/pages/components/media.js +51 -0
  157. package/docs/src/pages/components/modal.js +111 -0
  158. package/docs/src/pages/components/nav.js +86 -0
  159. package/docs/src/pages/components/pricing.js +68 -0
  160. package/docs/src/pages/components/progress.js +102 -0
  161. package/docs/src/pages/components/prose.js +111 -0
  162. package/docs/src/pages/components/pullquote.js +71 -0
  163. package/docs/src/pages/components/radio.js +194 -0
  164. package/docs/src/pages/components/rating.js +106 -0
  165. package/docs/src/pages/components/search.js +61 -0
  166. package/docs/src/pages/components/section.js +59 -0
  167. package/docs/src/pages/components/segmented.js +121 -0
  168. package/docs/src/pages/components/select.js +45 -0
  169. package/docs/src/pages/components/slider.js +114 -0
  170. package/docs/src/pages/components/spinner.js +73 -0
  171. package/docs/src/pages/components/stack.js +48 -0
  172. package/docs/src/pages/components/stat.js +55 -0
  173. package/docs/src/pages/components/stepper.js +66 -0
  174. package/docs/src/pages/components/table.js +45 -0
  175. package/docs/src/pages/components/testimonial.js +49 -0
  176. package/docs/src/pages/components/textarea.js +31 -0
  177. package/docs/src/pages/components/timeline.js +227 -0
  178. package/docs/src/pages/components/toggle.js +84 -0
  179. package/docs/src/pages/components/tooltip.js +48 -0
  180. package/docs/src/pages/components.js +204 -0
  181. package/docs/src/pages/config.js +193 -0
  182. package/docs/src/pages/constraints.js +99 -0
  183. package/docs/src/pages/deploy.js +233 -0
  184. package/docs/src/pages/extending.js +198 -0
  185. package/docs/src/pages/faq.js +96 -0
  186. package/docs/src/pages/getting-started.js +106 -0
  187. package/docs/src/pages/guard.js +121 -0
  188. package/docs/src/pages/home.js +401 -0
  189. package/docs/src/pages/how-it-works.js +183 -0
  190. package/docs/src/pages/hydration.js +98 -0
  191. package/docs/src/pages/images.js +121 -0
  192. package/docs/src/pages/meta.js +120 -0
  193. package/docs/src/pages/mutations.js +106 -0
  194. package/docs/src/pages/navigation.js +85 -0
  195. package/docs/src/pages/performance.js +157 -0
  196. package/docs/src/pages/persist.js +88 -0
  197. package/docs/src/pages/project-structure.js +90 -0
  198. package/docs/src/pages/prompt-examples.js +186 -0
  199. package/docs/src/pages/raw-responses.js +124 -0
  200. package/docs/src/pages/routing.js +99 -0
  201. package/docs/src/pages/server-api.js +281 -0
  202. package/docs/src/pages/server-data.js +185 -0
  203. package/docs/src/pages/slash-commands.js +55 -0
  204. package/docs/src/pages/spec.js +207 -0
  205. package/docs/src/pages/state.js +101 -0
  206. package/docs/src/pages/store.js +181 -0
  207. package/docs/src/pages/streaming.js +108 -0
  208. package/docs/src/pages/stripe.js +193 -0
  209. package/docs/src/pages/supabase.js +323 -0
  210. package/docs/src/pages/testing.js +198 -0
  211. package/docs/src/pages/validation.js +138 -0
  212. package/examples/contact.js +166 -0
  213. package/examples/counter.js +94 -0
  214. package/examples/dev.server.js +91 -0
  215. package/examples/examples.test.js +394 -0
  216. package/examples/pricing.js +244 -0
  217. package/examples/products.js +191 -0
  218. package/examples/quiz.js +208 -0
  219. package/examples/shared.js +78 -0
  220. package/examples/todos.js +162 -0
  221. package/package.json +75 -0
  222. package/public/.pulse-ui-version +1 -0
  223. package/public/chippy-bird.css +246 -0
  224. package/public/examples/contact.css +119 -0
  225. package/public/examples/counter.css +79 -0
  226. package/public/examples/pricing.css +132 -0
  227. package/public/examples/products.css +100 -0
  228. package/public/examples/quiz.css +200 -0
  229. package/public/examples/todos.css +137 -0
  230. package/public/favicon.ico +0 -0
  231. package/public/log-dashboard.css +383 -0
  232. package/public/pulse-ui.css +2740 -0
  233. package/public/pulse-ui.js +236 -0
  234. package/public/pulse.css +149 -0
  235. package/scripts/build.js +411 -0
  236. package/src/agent/checklist.md +111 -0
  237. package/src/agent/coverage-check.js +66 -0
  238. package/src/agent/guide-components.md +274 -0
  239. package/src/agent/guide-examples.md +54 -0
  240. package/src/agent/guide-routing.md +36 -0
  241. package/src/agent/guide-server.md +258 -0
  242. package/src/agent/guide-spec.md +103 -0
  243. package/src/agent/guide-styles.md +191 -0
  244. package/src/agent/guide.md +979 -0
  245. package/src/agent/identity.md +106 -0
  246. package/src/agent/workflow.md +108 -0
  247. package/src/cli/cli.test.js +82 -0
  248. package/src/cli/dev.js +195 -0
  249. package/src/cli/discover.js +113 -0
  250. package/src/cli/index.js +361 -0
  251. package/src/cli/load-report.js +91 -0
  252. package/src/cli/load-runner.js +121 -0
  253. package/src/cli/report-server.js +723 -0
  254. package/src/cli/report.js +116 -0
  255. package/src/cli/scaffold.archive.js +1371 -0
  256. package/src/cli/scaffold.js +349 -0
  257. package/src/cli/start.js +74 -0
  258. package/src/html.js +19 -0
  259. package/src/mcp/server.js +884 -0
  260. package/src/mcp/validate-worker.js +110 -0
  261. package/src/runtime/image.js +74 -0
  262. package/src/runtime/image.test.js +111 -0
  263. package/src/runtime/index.js +621 -0
  264. package/src/runtime/navigate.js +146 -0
  265. package/src/runtime/runtime.test.js +773 -0
  266. package/src/runtime/ssr.js +464 -0
  267. package/src/runtime/ssr.test.js +421 -0
  268. package/src/runtime/store.js +92 -0
  269. package/src/runtime/toast.js +163 -0
  270. package/src/server/index.js +1386 -0
  271. package/src/server/server.test.js +1248 -0
  272. package/src/spec/schema.js +428 -0
  273. package/src/spec/schema.test.js +291 -0
  274. package/src/store/index.js +102 -0
  275. package/src/store/store.test.js +210 -0
  276. package/src/testing/html.js +283 -0
  277. package/src/testing/index.js +249 -0
  278. package/src/testing/testing.test.js +450 -0
  279. package/src/ui/accordion.js +28 -0
  280. package/src/ui/alert.js +43 -0
  281. package/src/ui/app-badge.js +48 -0
  282. package/src/ui/avatar.js +47 -0
  283. package/src/ui/badge.js +24 -0
  284. package/src/ui/banner.js +26 -0
  285. package/src/ui/breadcrumbs.js +38 -0
  286. package/src/ui/button.js +66 -0
  287. package/src/ui/card.js +34 -0
  288. package/src/ui/carousel.js +59 -0
  289. package/src/ui/charts.js +321 -0
  290. package/src/ui/checkbox.js +65 -0
  291. package/src/ui/cluster.js +44 -0
  292. package/src/ui/code-window.js +39 -0
  293. package/src/ui/container.js +24 -0
  294. package/src/ui/cta.js +37 -0
  295. package/src/ui/divider.js +29 -0
  296. package/src/ui/empty.js +33 -0
  297. package/src/ui/feature.js +33 -0
  298. package/src/ui/fieldset.js +37 -0
  299. package/src/ui/fileupload.js +89 -0
  300. package/src/ui/footer.js +38 -0
  301. package/src/ui/grid.js +36 -0
  302. package/src/ui/heading.js +45 -0
  303. package/src/ui/hero.js +37 -0
  304. package/src/ui/icons.js +161 -0
  305. package/src/ui/index.js +89 -0
  306. package/src/ui/input.js +74 -0
  307. package/src/ui/list.js +36 -0
  308. package/src/ui/media.js +44 -0
  309. package/src/ui/modal.js +80 -0
  310. package/src/ui/nav.js +61 -0
  311. package/src/ui/pricing.js +56 -0
  312. package/src/ui/progress.js +62 -0
  313. package/src/ui/prose.js +29 -0
  314. package/src/ui/pullquote.js +34 -0
  315. package/src/ui/radio.js +102 -0
  316. package/src/ui/rating.js +93 -0
  317. package/src/ui/search.js +77 -0
  318. package/src/ui/section.js +69 -0
  319. package/src/ui/segmented.js +50 -0
  320. package/src/ui/select.js +77 -0
  321. package/src/ui/slider.js +84 -0
  322. package/src/ui/spinner.js +34 -0
  323. package/src/ui/stack.js +36 -0
  324. package/src/ui/stat.js +52 -0
  325. package/src/ui/stepper.js +46 -0
  326. package/src/ui/switch.js +57 -0
  327. package/src/ui/table.js +45 -0
  328. package/src/ui/testimonial.js +48 -0
  329. package/src/ui/textarea.js +72 -0
  330. package/src/ui/timeline.js +72 -0
  331. package/src/ui/tooltip.js +28 -0
  332. package/src/ui/ui.test.js +1241 -0
  333. package/src/ui/uiimage.js +65 -0
  334. package/tsconfig.json +13 -0
  335. package/types/html.d.ts +17 -0
  336. package/types/image.d.ts +70 -0
  337. package/types/index.d.ts +7 -0
  338. package/types/navigate.d.ts +38 -0
  339. package/types/runtime.d.ts +63 -0
  340. package/types/schema.d.ts +243 -0
  341. package/types/server.d.ts +145 -0
  342. package/types/ssr.d.ts +110 -0
  343. package/types/testing.d.ts +154 -0
  344. package/types/ui.d.ts +704 -0
@@ -0,0 +1,2739 @@
1
+ /**
2
+ * Pulse UI — Component stylesheet
3
+ *
4
+ * Import this file in your page spec:
5
+ * meta: { styles: ['/pulse-ui.css', '/app.css'] }
6
+ *
7
+ * Theming: override these custom properties in :root in your app.css.
8
+ * Do not edit this file — extend via new CSS modifier classes only.
9
+ *
10
+ * Token fallback chain: project token → ui default
11
+ * e.g. --ui-accent falls back to --accent, then to a hardcoded default.
12
+ */
13
+
14
+ /* ─── UI tokens ─────────────────────────────────────────────────────────────
15
+ All component styles reference --ui-* tokens only.
16
+ Override these in :root to retheme the entire library at once. */
17
+ :root {
18
+ --ui-bg: var(--bg, #0d0d10);
19
+ --ui-surface: var(--surface, #111116);
20
+ --ui-surface-2: var(--surface-2, #18181f);
21
+ --ui-border: var(--border, #38383f);
22
+ --ui-text: var(--text, #e2e2ea);
23
+ --ui-muted: var(--muted, #9090a0);
24
+ --ui-accent: var(--accent, #9b8dff);
25
+ --ui-accent-hover: var(--accent-hover, #b5aaff);
26
+ --ui-accent-dim: var(--accent-dim, rgba(155,141,255,.12));
27
+ --ui-accent-text: var(--accent-text, #ffffff);
28
+ --ui-green: var(--green, #3dd68c);
29
+ --ui-green-dim: rgba(61, 214, 140, .12);
30
+ --ui-red: var(--red, #ff6b6b);
31
+ --ui-red-dim: rgba(255, 107, 107, .12);
32
+ --ui-yellow: #f5a623;
33
+ --ui-yellow-dim: rgba(245, 166, 35, .12);
34
+ --ui-blue: #60a5fa;
35
+ --ui-blue-dim: rgba( 96, 165, 250, .12);
36
+ --ui-radius: var(--radius, 8px);
37
+ --ui-radius-sm: 4px;
38
+ --ui-font: var(--font, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif);
39
+ --ui-mono: var(--mono, 'Fira Code', 'Cascadia Code', monospace);
40
+
41
+ /* Touch target minimum per WCAG 2.5.5 */
42
+ --ui-touch-min: 44px;
43
+ }
44
+
45
+ /* ─── Base reset ─────────────────────────────────────────────────────────────
46
+ Apply the dark background and text colour to the document root so the page
47
+ background matches the component surface colours out of the box.
48
+ Projects can opt into a light theme via meta.theme: 'light' (sets
49
+ data-theme="light" on <body>) or override :root tokens in app.css. */
50
+ *, *::before, *::after { box-sizing: border-box; }
51
+ h1, h2, h3, h4, h5, h6, p, ul, ol, li { margin: 0; }
52
+ ul, ol { list-style: none; }
53
+
54
+ html, body {
55
+ margin: 0;
56
+ background-color: var(--ui-bg);
57
+ color: var(--ui-text);
58
+ font-family: var(--ui-font);
59
+ min-height: 100dvh;
60
+ }
61
+
62
+ /* ─── Focus style ────────────────────────────────────────────────────────────
63
+ Applied via :focus-visible to avoid showing on mouse click.
64
+ All interactive components inherit this. */
65
+ .ui-btn:focus-visible,
66
+ .ui-input:focus-visible,
67
+ .ui-select:focus-visible,
68
+ .ui-textarea:focus-visible {
69
+ outline: 2px solid var(--ui-accent);
70
+ outline-offset: 2px;
71
+ }
72
+
73
+ /* ─── Button ─────────────────────────────────────────────────────────────── */
74
+ .ui-btn {
75
+ box-sizing: border-box;
76
+ display: inline-flex;
77
+ align-items: center;
78
+ justify-content: center;
79
+ gap: .45rem;
80
+ padding: 0 1.2rem;
81
+ height: var(--ui-touch-min);
82
+ min-width: var(--ui-touch-min);
83
+ border: 1px solid transparent;
84
+ border-radius: var(--ui-radius);
85
+ font-family: var(--ui-font);
86
+ font-size: .9rem;
87
+ font-weight: 600;
88
+ line-height: 1;
89
+ text-decoration: none;
90
+ white-space: nowrap;
91
+ cursor: pointer;
92
+ transition: background .15s, color .15s, border-color .15s, opacity .15s;
93
+ -webkit-font-smoothing: antialiased;
94
+ }
95
+
96
+ /* Variants */
97
+ .ui-btn--primary {
98
+ background: var(--ui-accent);
99
+ color: var(--ui-bg);
100
+ }
101
+ .ui-btn--primary:hover:not(.ui-btn--disabled):not([disabled]) {
102
+ background: var(--ui-accent-hover);
103
+ }
104
+
105
+ .ui-btn--secondary {
106
+ background: var(--ui-surface-2);
107
+ color: var(--ui-text);
108
+ border-color: var(--ui-muted);
109
+ }
110
+ .ui-btn--secondary:hover:not(.ui-btn--disabled):not([disabled]) {
111
+ background: var(--ui-surface);
112
+ border-color: var(--ui-text);
113
+ }
114
+
115
+ .ui-btn--ghost {
116
+ background: transparent;
117
+ color: var(--ui-muted);
118
+ border: none;
119
+ }
120
+ .ui-btn--ghost:hover:not(.ui-btn--disabled):not([disabled]) {
121
+ background: var(--ui-surface-2);
122
+ color: var(--ui-text);
123
+ }
124
+
125
+ .ui-btn--danger {
126
+ background: var(--ui-red-dim);
127
+ color: var(--ui-red);
128
+ border-color: var(--ui-red);
129
+ }
130
+ .ui-btn--danger:hover:not(.ui-btn--disabled):not([disabled]) {
131
+ background: var(--ui-red);
132
+ color: var(--ui-bg);
133
+ }
134
+
135
+ /* Sizes */
136
+ .ui-btn--sm {
137
+ height: 36px;
138
+ padding: 0 .85rem;
139
+ font-size: .82rem;
140
+ min-width: 36px;
141
+ }
142
+ .ui-btn--lg {
143
+ height: 52px;
144
+ padding: 0 1.75rem;
145
+ font-size: 1rem;
146
+ }
147
+
148
+ /* Modifiers */
149
+ .ui-btn--full { width: 100%; }
150
+ .ui-btn--disabled,
151
+ .ui-btn[disabled] {
152
+ opacity: .45;
153
+ cursor: not-allowed;
154
+ pointer-events: none;
155
+ }
156
+
157
+ .ui-btn-icon {
158
+ display: inline-flex;
159
+ align-items: center;
160
+ flex-shrink: 0;
161
+ }
162
+
163
+ /* ─── Badge ──────────────────────────────────────────────────────────────── */
164
+ .ui-badge {
165
+ display: inline-flex;
166
+ align-items: center;
167
+ align-self: flex-start;
168
+ padding: .3em .55em;
169
+ border-radius: var(--ui-radius-sm);
170
+ font-family: var(--ui-font);
171
+ font-size: .72rem;
172
+ font-weight: 600;
173
+ line-height: 1;
174
+ white-space: nowrap;
175
+ letter-spacing: .02em;
176
+ }
177
+
178
+ .ui-badge--default { background: var(--ui-surface-2); color: var(--ui-muted); }
179
+ .ui-badge--success { background: var(--ui-green-dim); color: var(--ui-green); }
180
+ .ui-badge--warning { background: var(--ui-yellow-dim);color: var(--ui-yellow); }
181
+ .ui-badge--error { background: var(--ui-red-dim); color: var(--ui-red); }
182
+ .ui-badge--info { background: var(--ui-blue-dim); color: var(--ui-blue); }
183
+
184
+ /* ─── Card ───────────────────────────────────────────────────────────────── */
185
+ .ui-card {
186
+ background: var(--ui-surface);
187
+ border: 1px solid var(--ui-border);
188
+ border-radius: var(--ui-radius);
189
+ overflow: hidden;
190
+ }
191
+
192
+ .ui-card-header {
193
+ padding: 1rem 1.25rem;
194
+ border-bottom: 1px solid var(--ui-border);
195
+ }
196
+
197
+ .ui-card-title {
198
+ margin: 0;
199
+ font-size: .95rem;
200
+ font-weight: 600;
201
+ color: var(--ui-text);
202
+ line-height: 1.4;
203
+ }
204
+
205
+ .ui-card-body { padding: 1.25rem; }
206
+
207
+ .ui-card--flush .ui-card-body { padding: 0; }
208
+
209
+ .ui-card-footer {
210
+ padding: 1rem 1.25rem;
211
+ border-top: 1px solid var(--ui-border);
212
+ background: var(--ui-surface-2);
213
+ }
214
+
215
+ /* ============================================================
216
+ Fieldset
217
+ ============================================================ */
218
+
219
+ .ui-fieldset {
220
+ border: 1px solid var(--ui-border);
221
+ border-radius: var(--ui-radius);
222
+ padding: 0;
223
+ margin: 0;
224
+ }
225
+
226
+ .ui-fieldset-legend {
227
+ margin-left: 1rem;
228
+ padding: 0 0.375rem;
229
+ font-size: 0.75rem;
230
+ font-weight: 600;
231
+ letter-spacing: 0.06em;
232
+ text-transform: uppercase;
233
+ color: var(--ui-muted);
234
+ line-height: 1;
235
+ }
236
+
237
+ .ui-fieldset-body {
238
+ display: flex;
239
+ flex-direction: column;
240
+ gap: 1rem;
241
+ padding: 1.25rem;
242
+ }
243
+
244
+ .ui-fieldset--gap-xs .ui-fieldset-body { gap: 0.375rem; }
245
+ .ui-fieldset--gap-sm .ui-fieldset-body { gap: 0.625rem; }
246
+ .ui-fieldset--gap-lg .ui-fieldset-body { gap: 1.5rem; }
247
+
248
+ /* ─── Form fields (shared base) ──────────────────────────────────────────── */
249
+ .ui-field {
250
+ display: flex;
251
+ flex-direction: column;
252
+ gap: .4rem;
253
+ }
254
+
255
+ .ui-label {
256
+ font-family: var(--ui-font);
257
+ font-size: .85rem;
258
+ font-weight: 600;
259
+ color: var(--ui-text);
260
+ line-height: 1.4;
261
+ }
262
+
263
+ .ui-required {
264
+ color: var(--ui-red);
265
+ margin-left: .15rem;
266
+ }
267
+
268
+ .ui-hint {
269
+ font-size: .8rem;
270
+ color: var(--ui-muted);
271
+ margin: 0;
272
+ line-height: 1.5;
273
+ }
274
+
275
+ .ui-error {
276
+ font-size: .8rem;
277
+ color: var(--ui-red);
278
+ margin: 0;
279
+ line-height: 1.5;
280
+ }
281
+
282
+ /* ─── Input ──────────────────────────────────────────────────────────────── */
283
+ .ui-input {
284
+ width: 100%;
285
+ height: var(--ui-touch-min);
286
+ padding: 0 .85rem;
287
+ background: var(--ui-surface);
288
+ border: 1px solid var(--ui-border);
289
+ border-radius: var(--ui-radius);
290
+ font-family: var(--ui-font);
291
+ font-size: .9rem;
292
+ color: var(--ui-text);
293
+ transition: border-color .15s;
294
+ appearance: none;
295
+ -webkit-appearance: none;
296
+ }
297
+
298
+ .ui-input::placeholder { color: var(--ui-muted); }
299
+
300
+ .ui-input:hover:not(:disabled) { border-color: var(--ui-muted); }
301
+
302
+ .ui-input:disabled {
303
+ opacity: .5;
304
+ cursor: not-allowed;
305
+ }
306
+
307
+ .ui-field--error .ui-input {
308
+ border-color: var(--ui-red);
309
+ }
310
+
311
+ /* ─── Search ─────────────────────────────────────────────────────────────── */
312
+ .ui-search-wrap {
313
+ position: relative;
314
+ display: flex;
315
+ align-items: center;
316
+ }
317
+
318
+ .ui-search-icon {
319
+ position: absolute;
320
+ left: .75rem;
321
+ display: flex;
322
+ align-items: center;
323
+ color: var(--ui-muted);
324
+ pointer-events: none;
325
+ }
326
+
327
+ .ui-search-input {
328
+ width: 100%;
329
+ height: var(--ui-touch-min);
330
+ padding: 0 2.5rem 0 2.5rem;
331
+ background: var(--ui-surface);
332
+ border: 1px solid var(--ui-border);
333
+ border-radius: var(--ui-radius);
334
+ font-family: var(--ui-font);
335
+ font-size: .9rem;
336
+ color: var(--ui-text);
337
+ transition: border-color .15s;
338
+ appearance: none;
339
+ -webkit-appearance: none;
340
+ }
341
+
342
+ .ui-search-input::placeholder { color: var(--ui-muted); }
343
+
344
+ .ui-search-input:hover:not(:disabled) { border-color: var(--ui-muted); }
345
+
346
+ .ui-search-input:disabled { opacity: .5; cursor: not-allowed; }
347
+
348
+ /* Hide native browser cancel button — the component provides its own */
349
+ .ui-search-input::-webkit-search-cancel-button { display: none; }
350
+
351
+ .ui-search-clear {
352
+ position: absolute;
353
+ right: .5rem;
354
+ display: flex;
355
+ align-items: center;
356
+ justify-content: center;
357
+ width: 1.75rem;
358
+ height: 1.75rem;
359
+ padding: 0;
360
+ background: transparent;
361
+ border: none;
362
+ border-radius: var(--ui-radius-sm);
363
+ color: var(--ui-muted);
364
+ cursor: pointer;
365
+ transition: color .15s, background .15s;
366
+ }
367
+
368
+ .ui-search-clear:hover { color: var(--ui-text); background: var(--ui-surface-2); }
369
+
370
+ /* ─── Select ─────────────────────────────────────────────────────────────── */
371
+ .ui-select-wrap {
372
+ position: relative;
373
+ display: flex;
374
+ }
375
+
376
+ .ui-select {
377
+ width: 100%;
378
+ height: var(--ui-touch-min);
379
+ padding: 0 2.5rem 0 .85rem;
380
+ background: var(--ui-surface);
381
+ border: 1px solid var(--ui-border);
382
+ border-radius: var(--ui-radius);
383
+ font-family: var(--ui-font);
384
+ font-size: .9rem;
385
+ color: var(--ui-text);
386
+ cursor: pointer;
387
+ appearance: none;
388
+ -webkit-appearance: none;
389
+ transition: border-color .15s;
390
+ }
391
+
392
+ .ui-select:hover:not(:disabled) { border-color: var(--ui-muted); }
393
+
394
+ .ui-select:disabled {
395
+ opacity: .5;
396
+ cursor: not-allowed;
397
+ }
398
+
399
+ .ui-field--error .ui-select { border-color: var(--ui-red); }
400
+
401
+ .ui-select-chevron {
402
+ position: absolute;
403
+ right: .85rem;
404
+ top: 50%;
405
+ transform: translateY(-50%);
406
+ pointer-events: none;
407
+ color: var(--ui-muted);
408
+ display: flex;
409
+ align-items: center;
410
+ }
411
+
412
+ /* ─── Textarea ───────────────────────────────────────────────────────────── */
413
+ .ui-textarea {
414
+ width: 100%;
415
+ padding: .65rem .85rem;
416
+ background: var(--ui-surface);
417
+ border: 1px solid var(--ui-border);
418
+ border-radius: var(--ui-radius);
419
+ font-family: var(--ui-font);
420
+ font-size: .9rem;
421
+ color: var(--ui-text);
422
+ resize: vertical;
423
+ transition: border-color .15s;
424
+ min-height: calc(var(--ui-touch-min) * 2);
425
+ appearance: none;
426
+ }
427
+
428
+ .ui-textarea::placeholder { color: var(--ui-muted); }
429
+
430
+ .ui-textarea:hover:not(:disabled) { border-color: var(--ui-muted); }
431
+
432
+ .ui-textarea:disabled {
433
+ opacity: .5;
434
+ cursor: not-allowed;
435
+ }
436
+
437
+ .ui-field--error .ui-textarea { border-color: var(--ui-red); }
438
+
439
+ /* ─── Alert ──────────────────────────────────────────────────────────────── */
440
+ .ui-alert {
441
+ display: flex;
442
+ align-items: flex-start;
443
+ gap: .75rem;
444
+ padding: .85rem 1rem;
445
+ border-radius: var(--ui-radius);
446
+ border: 1px solid transparent;
447
+ font-size: .88rem;
448
+ line-height: 1.6;
449
+ }
450
+
451
+ .ui-alert--info { background: var(--ui-blue-dim); border-color: var(--ui-blue); color: var(--ui-blue); }
452
+ .ui-alert--success { background: var(--ui-green-dim); border-color: var(--ui-green); color: var(--ui-green); }
453
+ .ui-alert--warning { background: var(--ui-yellow-dim);border-color: var(--ui-yellow); color: var(--ui-yellow);}
454
+ .ui-alert--error { background: var(--ui-red-dim); border-color: var(--ui-red); color: var(--ui-red); }
455
+
456
+ .ui-alert-icon {
457
+ display: flex;
458
+ align-items: center;
459
+ flex-shrink: 0;
460
+ margin-top: .1rem;
461
+ }
462
+
463
+ .ui-alert-body { color: var(--ui-text); }
464
+
465
+ .ui-alert-title { font-weight: 600; }
466
+
467
+ /* ─── Stat ───────────────────────────────────────────────────────────────── */
468
+ .ui-stat {
469
+ display: flex;
470
+ flex-direction: column;
471
+ gap: .3rem;
472
+ }
473
+
474
+ .ui-stat-label {
475
+ font-size: .8rem;
476
+ color: var(--ui-muted);
477
+ font-weight: 500;
478
+ margin: 0;
479
+ }
480
+
481
+ .ui-stat-value {
482
+ font-size: 2rem;
483
+ font-weight: 700;
484
+ color: var(--ui-text);
485
+ line-height: 1;
486
+ margin: 0;
487
+ letter-spacing: -.02em;
488
+ }
489
+
490
+ .ui-stat-change {
491
+ display: inline-flex;
492
+ align-items: center;
493
+ gap: .3rem;
494
+ font-size: .8rem;
495
+ font-weight: 600;
496
+ margin: 0;
497
+ }
498
+
499
+ .ui-stat-change--up { color: var(--ui-green); }
500
+ .ui-stat-change--down { color: var(--ui-red); }
501
+ .ui-stat-change--neutral { color: var(--ui-muted); }
502
+
503
+ .ui-stat--center { align-items: center; text-align: center; }
504
+
505
+ /* ─── Avatar ─────────────────────────────────────────────────────────────── */
506
+ .ui-avatar {
507
+ display: inline-flex;
508
+ align-items: center;
509
+ justify-content: center;
510
+ border-radius: 50%;
511
+ overflow: hidden;
512
+ background: var(--ui-accent-dim);
513
+ color: var(--ui-accent);
514
+ font-family: var(--ui-font);
515
+ font-weight: 700;
516
+ flex-shrink: 0;
517
+ object-fit: cover;
518
+ }
519
+
520
+ .ui-avatar--sm { width: 28px; height: 28px; font-size: .65rem; }
521
+ .ui-avatar--md { width: 40px; height: 40px; font-size: .85rem; }
522
+ .ui-avatar--lg { width: 56px; height: 56px; font-size: 1.1rem; }
523
+ .ui-avatar--xl { width: 80px; height: 80px; font-size: 1.5rem; }
524
+
525
+ /* ─── Empty state ────────────────────────────────────────────────────────── */
526
+ .ui-empty {
527
+ display: flex;
528
+ flex-direction: column;
529
+ align-items: center;
530
+ text-align: center;
531
+ gap: .75rem;
532
+ padding: 3rem 1.5rem;
533
+ }
534
+
535
+ .ui-empty-title {
536
+ font-size: 1.05rem;
537
+ font-weight: 600;
538
+ color: var(--ui-text);
539
+ margin: 0;
540
+ }
541
+
542
+ .ui-empty-desc {
543
+ font-size: .88rem;
544
+ color: var(--ui-muted);
545
+ max-width: 36ch;
546
+ margin: 0;
547
+ line-height: 1.6;
548
+ }
549
+
550
+ /* ─── Table ──────────────────────────────────────────────────────────────── */
551
+ .ui-table-wrap {
552
+ overflow-x: auto;
553
+ border: 1px solid var(--ui-border);
554
+ border-radius: var(--ui-radius);
555
+ /* Explicit outline for keyboard-scrollable region */
556
+ }
557
+
558
+ .ui-table-wrap:focus-visible {
559
+ outline: 2px solid var(--ui-accent);
560
+ outline-offset: 2px;
561
+ }
562
+
563
+ .ui-table {
564
+ width: 100%;
565
+ border-collapse: collapse;
566
+ font-size: .88rem;
567
+ }
568
+
569
+ .ui-table-caption {
570
+ caption-side: top;
571
+ text-align: left;
572
+ padding: .75rem 1rem;
573
+ font-size: .8rem;
574
+ font-weight: 600;
575
+ color: var(--ui-muted);
576
+ text-transform: uppercase;
577
+ letter-spacing: .06em;
578
+ border-bottom: 1px solid var(--ui-border);
579
+ }
580
+
581
+ .ui-table thead th {
582
+ padding: .65rem 1rem;
583
+ text-align: left;
584
+ font-size: .78rem;
585
+ font-weight: 600;
586
+ color: var(--ui-muted);
587
+ text-transform: uppercase;
588
+ letter-spacing: .06em;
589
+ border-bottom: 1px solid var(--ui-border);
590
+ background: var(--ui-surface-2);
591
+ white-space: nowrap;
592
+ }
593
+
594
+ .ui-table tbody td {
595
+ padding: .75rem 1rem;
596
+ border-bottom: 1px solid var(--ui-border);
597
+ color: var(--ui-text);
598
+ vertical-align: top;
599
+ line-height: 1.5;
600
+ }
601
+
602
+ .ui-table tbody tr:last-child td { border-bottom: none; }
603
+
604
+ .ui-table tbody tr:nth-child(even) { background: var(--ui-surface-2); }
605
+
606
+ /* ─── Container ──────────────────────────────────────────────────────────── */
607
+ .ui-container { width: 100%; margin-left: auto; margin-right: auto; padding-left: 1.5rem; padding-right: 1.5rem; }
608
+ .ui-container--sm { max-width: 640px; }
609
+ .ui-container--md { max-width: 768px; }
610
+ .ui-container--lg { max-width: 1100px; }
611
+ .ui-container--xl { max-width: 1280px; }
612
+
613
+ /* ─── Section ────────────────────────────────────────────────────────────── */
614
+ .ui-section { padding-top: 5rem; padding-bottom: 5rem; }
615
+ .ui-section--sm { padding-top: 3rem; padding-bottom: 3rem; }
616
+ .ui-section--lg { padding-top: 7rem; padding-bottom: 7rem; }
617
+ .ui-section--alt { background: var(--ui-surface, var(--surface, #111116)); }
618
+ .ui-section--dark { background: var(--ui-surface-2, var(--surface-2, #18181f)); }
619
+
620
+ /* ─── Grid ───────────────────────────────────────────────────────────────── */
621
+ .ui-grid { display: grid; gap: 2rem; }
622
+
623
+ .ui-grid--cols-1 { grid-template-columns: 1fr; }
624
+ .ui-grid--cols-2 { grid-template-columns: repeat(2, 1fr); }
625
+ .ui-grid--cols-3 { grid-template-columns: repeat(3, 1fr); }
626
+ .ui-grid--cols-4 { grid-template-columns: repeat(4, 1fr); }
627
+
628
+ .ui-grid--gap-sm { gap: 1rem; }
629
+ .ui-grid--gap-lg { gap: 3rem; }
630
+
631
+ /* ─── Stack ──────────────────────────────────────────────────────────────── */
632
+ .ui-stack { display: flex; flex-direction: column; gap: 1rem; }
633
+
634
+ .ui-stack--gap-xs { gap: .25rem; }
635
+ .ui-stack--gap-sm { gap: .5rem; }
636
+ .ui-stack--gap-lg { gap: 2rem; }
637
+ .ui-stack--gap-xl { gap: 3rem; }
638
+
639
+ .ui-stack--align-start { align-items: flex-start; }
640
+ .ui-stack--align-center { align-items: center; }
641
+ .ui-stack--align-end { align-items: flex-end; }
642
+
643
+ /* ─── Cluster ────────────────────────────────────────────────────────────── */
644
+ .ui-cluster { display: flex; flex-wrap: wrap; align-items: center; gap: 1rem; }
645
+
646
+ .ui-cluster--gap-xs { gap: .25rem; }
647
+ .ui-cluster--gap-sm { gap: .5rem; }
648
+ .ui-cluster--gap-lg { gap: 2rem; }
649
+
650
+ .ui-cluster--justify-center { justify-content: center; }
651
+ .ui-cluster--justify-end { justify-content: flex-end; }
652
+ .ui-cluster--justify-between { justify-content: space-between; }
653
+
654
+ .ui-cluster--align-start { align-items: flex-start; }
655
+ .ui-cluster--align-end { align-items: flex-end; }
656
+
657
+ .ui-cluster--nowrap { flex-wrap: nowrap; }
658
+
659
+ /* ─── Divider ────────────────────────────────────────────────────────────── */
660
+ hr.ui-divider {
661
+ border: none;
662
+ border-top: 1px solid var(--ui-border, var(--border, #222228));
663
+ margin: 0;
664
+ }
665
+
666
+ .ui-divider--label {
667
+ display: flex;
668
+ align-items: center;
669
+ gap: .75rem;
670
+ }
671
+
672
+ .ui-divider-line {
673
+ flex: 1;
674
+ height: 1px;
675
+ background: var(--ui-border, var(--border, #222228));
676
+ display: block;
677
+ }
678
+
679
+ .ui-divider-text {
680
+ font-size: .8rem;
681
+ color: var(--ui-muted, var(--muted, #9090a0));
682
+ white-space: nowrap;
683
+ flex-shrink: 0;
684
+ }
685
+
686
+ /* ─── Banner ─────────────────────────────────────────────────────────────── */
687
+ .ui-banner {
688
+ padding: .625rem 1.5rem;
689
+ text-align: center;
690
+ font-size: .875rem;
691
+ font-weight: 500;
692
+ line-height: 1.5;
693
+ }
694
+
695
+ .ui-banner--info {
696
+ background: var(--ui-accent-dim, rgba(155,141,255,.12));
697
+ color: var(--ui-accent, var(--accent, #9b8dff));
698
+ }
699
+
700
+ .ui-banner--promo {
701
+ background: var(--ui-accent, var(--accent, #9b8dff));
702
+ color: #fff;
703
+ }
704
+
705
+ .ui-banner--warning {
706
+ background: rgba(255, 193, 7, .12);
707
+ color: #ffc107;
708
+ }
709
+
710
+ /* ─── Media ──────────────────────────────────────────────────────────────── */
711
+ .ui-media {
712
+ display: grid;
713
+ grid-template-columns: 1fr 1fr;
714
+ gap: 3rem;
715
+ align-items: center;
716
+ }
717
+
718
+ .ui-media--reverse { direction: rtl; }
719
+ .ui-media--reverse > * { direction: ltr; }
720
+
721
+ .ui-media--align-start { align-items: flex-start; }
722
+
723
+ .ui-media--gap-sm { gap: 1.5rem; }
724
+ .ui-media--gap-lg { gap: 5rem; }
725
+
726
+ .ui-media-image { min-width: 0; }
727
+ .ui-media-content { min-width: 0; }
728
+
729
+ .ui-media-image img {
730
+ width: 100%;
731
+ height: auto;
732
+ border-radius: var(--ui-radius, 8px);
733
+ display: block;
734
+ }
735
+
736
+ /* ─── Hero ───────────────────────────────────────────────────────────────── */
737
+ .ui-hero { padding: 5rem 1.5rem; text-align: center; }
738
+ .ui-hero--left { text-align: left; }
739
+ .ui-hero--sm { padding-top: 2.5rem; padding-bottom: 0; }
740
+
741
+ .ui-hero-inner { max-width: 720px; margin: 0 auto; }
742
+ .ui-hero--left .ui-hero-inner { margin: 0; }
743
+
744
+ .ui-hero-eyebrow {
745
+ font-size: .78rem;
746
+ font-weight: 600;
747
+ letter-spacing: .08em;
748
+ text-transform: uppercase;
749
+ color: var(--ui-accent, var(--accent, #9b8dff));
750
+ margin: 0 0 .75rem;
751
+ }
752
+
753
+ .ui-hero-title {
754
+ font-size: clamp(2.2rem, 6vw, 3.5rem);
755
+ font-weight: 800;
756
+ line-height: 1.1;
757
+ letter-spacing: -.02em;
758
+ color: var(--ui-text, var(--text, #e2e2ea));
759
+ margin: 0 0 1.25rem;
760
+ }
761
+
762
+ .ui-hero-subtitle {
763
+ font-size: 1.125rem;
764
+ color: var(--ui-muted, var(--muted, #9090a0));
765
+ line-height: 1.65;
766
+ margin: 0 0 2rem;
767
+ }
768
+
769
+ .ui-hero-actions {
770
+ display: flex;
771
+ gap: .75rem;
772
+ flex-wrap: wrap;
773
+ justify-content: center;
774
+ }
775
+ .ui-hero--left .ui-hero-actions { justify-content: flex-start; }
776
+
777
+ /* ─── Testimonial ────────────────────────────────────────────────────────── */
778
+ .ui-testimonial {
779
+ background: var(--ui-surface, var(--surface, #111116));
780
+ border: 1px solid var(--ui-border, var(--border, #222228));
781
+ border-radius: var(--ui-radius, 8px);
782
+ padding: 1.5rem;
783
+ margin: 0;
784
+ }
785
+
786
+ .ui-testimonial-rating {
787
+ color: #f5a623;
788
+ font-size: 1rem;
789
+ letter-spacing: .1em;
790
+ margin: 0 0 .75rem;
791
+ }
792
+
793
+ .ui-testimonial-quote { margin: 0 0 1.25rem; }
794
+ .ui-testimonial-quote p {
795
+ font-size: .95rem;
796
+ line-height: 1.65;
797
+ color: var(--ui-text, var(--text, #e2e2ea));
798
+ font-style: italic;
799
+ margin: 0;
800
+ }
801
+
802
+ .ui-testimonial-author { display: flex; align-items: center; gap: .75rem; }
803
+
804
+ .ui-testimonial-avatar {
805
+ width: 40px;
806
+ height: 40px;
807
+ border-radius: 50%;
808
+ object-fit: cover;
809
+ flex-shrink: 0;
810
+ }
811
+
812
+ .ui-testimonial-avatar--initials {
813
+ background: var(--ui-accent-dim, rgba(155,141,255,.12));
814
+ color: var(--ui-accent, var(--accent, #9b8dff));
815
+ font-size: .8rem;
816
+ font-weight: 700;
817
+ display: flex;
818
+ align-items: center;
819
+ justify-content: center;
820
+ }
821
+
822
+ .ui-testimonial-meta { display: flex; flex-direction: column; gap: .1rem; }
823
+ .ui-testimonial-name { font-size: .875rem; font-weight: 600; color: var(--ui-text, var(--text, #e2e2ea)); margin: 0; }
824
+ .ui-testimonial-role { font-size: .78rem; color: var(--ui-muted, var(--muted, #9090a0)); margin: 0; }
825
+
826
+ /* ─── Feature ────────────────────────────────────────────────────────────── */
827
+ .ui-feature { display: flex; flex-direction: column; gap: .75rem; }
828
+
829
+ .ui-feature-icon {
830
+ display: block;
831
+ flex-shrink: 0;
832
+ line-height: 1;
833
+ }
834
+
835
+ .ui-feature-title { font-size: 1rem; font-weight: 600; color: var(--ui-text, var(--text, #e2e2ea)); margin: 0; }
836
+ .ui-feature-desc { font-size: .9rem; color: var(--ui-muted, var(--muted, #9090a0)); line-height: 1.6; margin: 0; }
837
+
838
+ .ui-feature--center { align-items: center; text-align: center; }
839
+
840
+ /* ─── Pricing ────────────────────────────────────────────────────────────── */
841
+ .ui-pricing {
842
+ box-sizing: border-box;
843
+ background: var(--ui-surface, var(--surface, #111116));
844
+ border: 1px solid var(--ui-border, var(--border, #222228));
845
+ border-radius: var(--ui-radius, 8px);
846
+ padding: 2rem;
847
+ display: flex;
848
+ flex-direction: column;
849
+ gap: 1.25rem;
850
+ position: relative;
851
+ width: 100%;
852
+ }
853
+
854
+ .ui-pricing--highlighted {
855
+ border-color: var(--ui-accent, var(--accent, #9b8dff));
856
+ box-shadow: 0 0 0 1px var(--ui-accent, var(--accent, #9b8dff));
857
+ }
858
+
859
+ .ui-pricing-badge {
860
+ position: absolute;
861
+ top: -12px;
862
+ left: 50%;
863
+ transform: translateX(-50%);
864
+ background: var(--ui-accent, var(--accent, #9b8dff));
865
+ color: var(--ui-accent-text, #0d0a20);
866
+ font-size: .72rem;
867
+ font-weight: 700;
868
+ letter-spacing: .05em;
869
+ text-transform: uppercase;
870
+ padding: .25rem .75rem;
871
+ border-radius: 99px;
872
+ margin: 0;
873
+ white-space: nowrap;
874
+ }
875
+
876
+ .ui-pricing-header { display: flex; flex-direction: column; gap: .25rem; }
877
+ .ui-pricing-name { font-size: 1.1rem; font-weight: 700; color: var(--ui-text, var(--text, #e2e2ea)); margin: 0; }
878
+ .ui-pricing-desc { font-size: .875rem; color: var(--ui-muted, var(--muted, #9090a0)); margin: 0; }
879
+
880
+ .ui-pricing-price { display: flex; align-items: baseline; gap: .3rem; }
881
+ .ui-pricing-amount { font-size: 2.25rem; font-weight: 800; color: var(--ui-text, var(--text, #e2e2ea)); line-height: 1; letter-spacing: -.02em; }
882
+ .ui-pricing-period { font-size: .875rem; color: var(--ui-muted, var(--muted, #9090a0)); }
883
+
884
+ .ui-pricing-features { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: .6rem; }
885
+ .ui-pricing-feature { font-size: .875rem; color: var(--ui-text, var(--text, #e2e2ea)); display: flex; align-items: flex-start; gap: .5rem; width: 100%; }
886
+ .ui-pricing-check { color: var(--ui-green, var(--green, #3dd68c)); font-weight: 700; flex-shrink: 0; }
887
+
888
+ /* ─── Pricing grid (responsive) ─────────────────────────────────────────── */
889
+ .ui-pricing-grid {
890
+ display: grid;
891
+ gap: 1.5rem;
892
+ align-items: start;
893
+ grid-template-columns: 1fr;
894
+ width: 100%;
895
+ }
896
+ @media (min-width: 640px) {
897
+ .ui-pricing-grid--cols-2 { grid-template-columns: repeat(2, 1fr); }
898
+ .ui-pricing-grid--cols-3 { grid-template-columns: repeat(3, 1fr); }
899
+ }
900
+ .ui-pricing-action { margin-top: auto; }
901
+
902
+ /* ─── Accordion ──────────────────────────────────────────────────────────── */
903
+ .ui-accordion { display: flex; flex-direction: column; gap: .5rem; width: 100%; }
904
+
905
+ .ui-accordion-item {
906
+ background: var(--ui-surface, var(--surface, #111116));
907
+ border: 1px solid var(--ui-border, var(--border, #222228));
908
+ border-radius: var(--ui-radius, 8px);
909
+ overflow: hidden;
910
+ }
911
+
912
+ .ui-accordion-summary {
913
+ display: flex;
914
+ justify-content: space-between;
915
+ align-items: center;
916
+ padding: 1rem 1.25rem;
917
+ cursor: pointer;
918
+ font-size: .95rem;
919
+ font-weight: 500;
920
+ color: var(--ui-text, var(--text, #e2e2ea));
921
+ list-style: none;
922
+ user-select: none;
923
+ gap: 1rem;
924
+ }
925
+ .ui-accordion-summary::-webkit-details-marker { display: none; }
926
+ .ui-accordion-summary:hover { color: var(--ui-accent, var(--accent, #9b8dff)); }
927
+
928
+ .ui-accordion-icon {
929
+ width: 16px;
930
+ height: 16px;
931
+ position: relative;
932
+ flex-shrink: 0;
933
+ }
934
+ .ui-accordion-icon::before,
935
+ .ui-accordion-icon::after {
936
+ content: '';
937
+ position: absolute;
938
+ background: currentColor;
939
+ border-radius: 2px;
940
+ transition: transform .2s;
941
+ }
942
+ .ui-accordion-icon::before { width: 10px; height: 1.5px; top: 7px; left: 3px; }
943
+ .ui-accordion-icon::after { width: 1.5px; height: 10px; top: 3px; left: 7px; }
944
+ .ui-accordion-item[open] .ui-accordion-icon::after { transform: rotate(90deg); }
945
+
946
+ .ui-accordion-body { padding: 0 1.25rem 1rem; }
947
+ .ui-accordion-body p { font-size: .9rem; color: var(--ui-muted, var(--muted, #9090a0)); line-height: 1.7; margin: 0; }
948
+
949
+ /* ─── Tooltip ────────────────────────────────────────────────────────────── */
950
+ .ui-tooltip {
951
+ position: relative;
952
+ display: inline-block;
953
+ }
954
+
955
+ .ui-tooltip::after {
956
+ content: attr(data-tip);
957
+ position: absolute;
958
+ bottom: calc(100% + 8px);
959
+ left: 50%;
960
+ transform: translateX(-50%) translateY(4px);
961
+ background: var(--ui-surface-2, var(--surface-2, #1a1a26));
962
+ color: var(--ui-text, var(--text, #e2e2ea));
963
+ font-size: .78rem;
964
+ font-weight: 500;
965
+ line-height: 1.4;
966
+ white-space: nowrap;
967
+ padding: .35rem .7rem;
968
+ border-radius: 6px;
969
+ border: 1px solid var(--ui-border, var(--border, #2a2a38));
970
+ pointer-events: none;
971
+ opacity: 0;
972
+ transition: opacity .15s, transform .15s;
973
+ z-index: var(--ui-z-tooltip, 200);
974
+ }
975
+
976
+ .ui-tooltip::before {
977
+ content: '';
978
+ position: absolute;
979
+ bottom: calc(100% + 2px);
980
+ left: 50%;
981
+ transform: translateX(-50%);
982
+ border: 5px solid transparent;
983
+ border-top-color: var(--ui-border, var(--border, #2a2a38));
984
+ pointer-events: none;
985
+ opacity: 0;
986
+ transition: opacity .15s;
987
+ z-index: var(--ui-z-tooltip, 200);
988
+ }
989
+
990
+ .ui-tooltip:hover::after,
991
+ .ui-tooltip:focus-within::after {
992
+ opacity: 1;
993
+ transform: translateX(-50%) translateY(0);
994
+ }
995
+ .ui-tooltip:hover::before,
996
+ .ui-tooltip:focus-within::before { opacity: 1; }
997
+
998
+ /* bottom */
999
+ .ui-tooltip--bottom::after { bottom: auto; top: calc(100% + 8px); transform: translateX(-50%) translateY(-4px); }
1000
+ .ui-tooltip--bottom::before { bottom: auto; top: calc(100% + 2px); border-top-color: transparent; border-bottom-color: var(--ui-border, var(--border, #2a2a38)); }
1001
+ .ui-tooltip--bottom:hover::after,
1002
+ .ui-tooltip--bottom:focus-within::after { transform: translateX(-50%) translateY(0); }
1003
+
1004
+ /* left */
1005
+ .ui-tooltip--left::after { bottom: auto; top: 50%; left: auto; right: calc(100% + 8px); transform: translateY(-50%) translateX(4px); }
1006
+ .ui-tooltip--left::before { bottom: auto; top: 50%; left: auto; right: calc(100% + 2px); transform: translateY(-50%); border-top-color: transparent; border-left-color: var(--ui-border, var(--border, #2a2a38)); }
1007
+ .ui-tooltip--left:hover::after,
1008
+ .ui-tooltip--left:focus-within::after { transform: translateY(-50%) translateX(0); }
1009
+
1010
+ /* right */
1011
+ .ui-tooltip--right::after { bottom: auto; top: 50%; left: calc(100% + 8px); transform: translateY(-50%) translateX(-4px); }
1012
+ .ui-tooltip--right::before { bottom: auto; top: 50%; left: calc(100% + 2px); transform: translateY(-50%); border-top-color: transparent; border-right-color: var(--ui-border, var(--border, #2a2a38)); }
1013
+ .ui-tooltip--right:hover::after,
1014
+ .ui-tooltip--right:focus-within::after { transform: translateY(-50%) translateX(0); }
1015
+
1016
+ /* ─── Modal ──────────────────────────────────────────────────────────────── */
1017
+ .ui-modal {
1018
+ position: fixed;
1019
+ inset: 0;
1020
+ margin: auto;
1021
+ width: min(560px, calc(100vw - 2rem));
1022
+ max-height: min(80vh, calc(100dvh - 2rem));
1023
+ padding: 0;
1024
+ background: var(--ui-surface, var(--surface, #13131e));
1025
+ border: 1px solid var(--ui-border, var(--border, #2a2a38));
1026
+ border-radius: var(--ui-radius, 12px);
1027
+ overflow: hidden;
1028
+ box-shadow: 0 20px 60px rgba(0, 0, 0, .5);
1029
+ }
1030
+
1031
+ .ui-modal--sm { width: min(400px, calc(100vw - 2rem)); }
1032
+ .ui-modal--lg { width: min(760px, calc(100vw - 2rem)); }
1033
+ .ui-modal--xl { width: min(1000px, calc(100vw - 2rem)); }
1034
+
1035
+ .ui-modal::backdrop {
1036
+ background: rgba(0, 0, 0, .6);
1037
+ backdrop-filter: blur(2px);
1038
+ }
1039
+
1040
+ .ui-modal-inner {
1041
+ display: flex;
1042
+ flex-direction: column;
1043
+ max-height: inherit;
1044
+ margin: 0;
1045
+ border: none;
1046
+ padding: 0;
1047
+ background: transparent;
1048
+ }
1049
+
1050
+ .ui-modal-header {
1051
+ display: flex;
1052
+ align-items: center;
1053
+ gap: 1rem;
1054
+ padding: 1.25rem 1.5rem;
1055
+ border-bottom: 1px solid var(--ui-border, var(--border, #2a2a38));
1056
+ flex-shrink: 0;
1057
+ }
1058
+
1059
+ .ui-modal-title {
1060
+ flex: 1;
1061
+ font-size: 1.1rem;
1062
+ font-weight: 700;
1063
+ color: var(--ui-text, var(--text, #e2e2ea));
1064
+ margin: 0;
1065
+ }
1066
+
1067
+ .ui-modal-close {
1068
+ display: flex;
1069
+ align-items: center;
1070
+ justify-content: center;
1071
+ width: 32px;
1072
+ height: 32px;
1073
+ padding: 0;
1074
+ background: transparent;
1075
+ border: none;
1076
+ border-radius: 6px;
1077
+ color: var(--ui-muted, var(--muted, #9090a0));
1078
+ cursor: pointer;
1079
+ transition: color .15s, background .15s;
1080
+ flex-shrink: 0;
1081
+ }
1082
+ .ui-modal-close:hover {
1083
+ color: var(--ui-text, var(--text, #e2e2ea));
1084
+ background: var(--ui-surface-2, var(--surface-2, #1a1a26));
1085
+ }
1086
+
1087
+ .ui-modal-body {
1088
+ flex: 1;
1089
+ overflow-y: auto;
1090
+ padding: 1.5rem;
1091
+ color: var(--ui-text, var(--text, #e2e2ea));
1092
+ }
1093
+
1094
+ .ui-modal-footer {
1095
+ display: flex;
1096
+ align-items: center;
1097
+ justify-content: flex-end;
1098
+ gap: .75rem;
1099
+ padding: 1rem 1.5rem;
1100
+ border-top: 1px solid var(--ui-border, var(--border, #2a2a38));
1101
+ flex-shrink: 0;
1102
+ }
1103
+
1104
+ /* ─── Carousel ───────────────────────────────────────────────────────────── */
1105
+ .ui-carousel {
1106
+ position: relative;
1107
+ width: 100%;
1108
+ border-radius: var(--ui-radius, 12px);
1109
+ overflow: hidden;
1110
+ }
1111
+
1112
+ .ui-carousel-track {
1113
+ display: flex;
1114
+ overflow-x: auto;
1115
+ scroll-snap-type: x mandatory;
1116
+ scroll-behavior: smooth;
1117
+ -webkit-overflow-scrolling: touch;
1118
+ scrollbar-width: none;
1119
+ }
1120
+ .ui-carousel-track::-webkit-scrollbar { display: none; }
1121
+
1122
+ .ui-carousel-slide {
1123
+ flex: 0 0 100%;
1124
+ scroll-snap-align: start;
1125
+ }
1126
+
1127
+ .ui-carousel-btn {
1128
+ position: absolute;
1129
+ top: 50%;
1130
+ transform: translateY(-50%);
1131
+ z-index: 2;
1132
+ display: flex;
1133
+ align-items: center;
1134
+ justify-content: center;
1135
+ width: 40px;
1136
+ height: 40px;
1137
+ padding: 0;
1138
+ background: var(--ui-surface, var(--surface, #13131e));
1139
+ border: 1px solid var(--ui-border, var(--border, #2a2a38));
1140
+ border-radius: 50%;
1141
+ color: var(--ui-text, var(--text, #e2e2ea));
1142
+ cursor: pointer;
1143
+ transition: background .15s, opacity .15s;
1144
+ }
1145
+ .ui-carousel-btn:hover { background: var(--ui-surface-2, var(--surface-2, #1a1a26)); }
1146
+ .ui-carousel-btn[hidden] { display: none; }
1147
+ .ui-carousel-prev { left: .75rem; }
1148
+ .ui-carousel-next { right: .75rem; }
1149
+
1150
+ .ui-carousel-dots {
1151
+ display: flex;
1152
+ justify-content: center;
1153
+ gap: .5rem;
1154
+ padding: .75rem 0 .5rem;
1155
+ }
1156
+
1157
+ .ui-carousel-dot {
1158
+ width: 8px;
1159
+ height: 8px;
1160
+ padding: 0;
1161
+ background: var(--ui-border, var(--border, #2a2a38));
1162
+ border: none;
1163
+ border-radius: 50%;
1164
+ cursor: pointer;
1165
+ transition: background .15s, transform .15s;
1166
+ }
1167
+ .ui-carousel-dot.active,
1168
+ .ui-carousel-dot:hover { background: var(--ui-accent, var(--accent, #9b8dff)); }
1169
+ .ui-carousel-dot.active { transform: scale(1.35); }
1170
+
1171
+ /* ─── Nav ────────────────────────────────────────────────────────────────── */
1172
+ .ui-nav {
1173
+ position: relative;
1174
+ background: var(--ui-bg, var(--bg, #0d0d10));
1175
+ border-bottom: 1px solid var(--ui-border, var(--border, #222228));
1176
+ }
1177
+
1178
+ .ui-nav--sticky {
1179
+ position: sticky;
1180
+ top: 0;
1181
+ z-index: 100;
1182
+ backdrop-filter: blur(12px);
1183
+ -webkit-backdrop-filter: blur(12px);
1184
+ background: var(--ui-nav-sticky-bg, rgba(13, 13, 16, .85));
1185
+ }
1186
+
1187
+ .ui-nav-inner {
1188
+ max-width: 1100px;
1189
+ margin: 0 auto;
1190
+ padding: .875rem 1.5rem;
1191
+ display: flex;
1192
+ align-items: center;
1193
+ gap: 2rem;
1194
+ }
1195
+
1196
+ .ui-nav-logo {
1197
+ font-size: 1rem;
1198
+ font-weight: 700;
1199
+ color: var(--ui-text, var(--text, #e2e2ea));
1200
+ text-decoration: none;
1201
+ display: flex;
1202
+ align-items: center;
1203
+ gap: .5rem;
1204
+ flex-shrink: 0;
1205
+ }
1206
+ .ui-nav-logo:hover { color: var(--ui-accent, var(--accent, #9b8dff)); }
1207
+
1208
+ .ui-nav-links { display: flex; gap: 1.5rem; align-items: center; flex: 1; }
1209
+
1210
+ .ui-nav-link {
1211
+ font-size: .875rem;
1212
+ color: var(--ui-muted, var(--muted, #9090a0));
1213
+ text-decoration: none;
1214
+ transition: color .15s;
1215
+ min-height: 44px;
1216
+ display: flex;
1217
+ align-items: center;
1218
+ }
1219
+ .ui-nav-link:hover { color: var(--ui-text, var(--text, #e2e2ea)); }
1220
+
1221
+ .ui-nav-action { margin-left: auto; }
1222
+
1223
+ .ui-nav--burger-left .ui-nav-burger { order: -1; margin-left: 0; margin-right: auto; }
1224
+
1225
+ .ui-nav-burger {
1226
+ display: none;
1227
+ margin-left: auto;
1228
+ padding: .35rem;
1229
+ background: none;
1230
+ border: none;
1231
+ color: var(--ui-text, var(--text, #e2e2ea));
1232
+ cursor: pointer;
1233
+ align-items: center;
1234
+ justify-content: center;
1235
+ border-radius: var(--ui-radius-sm, 6px);
1236
+ transition: background .15s;
1237
+ }
1238
+ .ui-nav-burger:hover { background: var(--ui-surface, var(--surface, #111116)); }
1239
+ .ui-nav-burger-close { display: none; }
1240
+ .ui-nav--open .ui-nav-burger-open { display: none; }
1241
+ .ui-nav--open .ui-nav-burger-close { display: block; }
1242
+
1243
+ .ui-nav-mobile {
1244
+ display: none;
1245
+ position: absolute;
1246
+ top: 100%;
1247
+ left: 0;
1248
+ right: 0;
1249
+ z-index: 99;
1250
+ background: var(--ui-bg, var(--bg, #0d0d10));
1251
+ border-bottom: 1px solid var(--ui-border, var(--border, #222228));
1252
+ padding: 1rem 1.5rem;
1253
+ flex-direction: column;
1254
+ gap: .25rem;
1255
+ }
1256
+ .ui-nav--open .ui-nav-mobile { display: flex; }
1257
+
1258
+ .ui-nav-mobile nav {
1259
+ display: flex;
1260
+ flex-direction: column;
1261
+ }
1262
+ .ui-nav-mobile .ui-nav-link {
1263
+ padding: .6rem 0;
1264
+ border-bottom: 1px solid var(--ui-border, var(--border, #222228));
1265
+ }
1266
+ .ui-nav-mobile .ui-nav-link:last-child { border-bottom: none; }
1267
+ .ui-nav-mobile-action { padding-top: .75rem; }
1268
+
1269
+ /* ─── App Badge ──────────────────────────────────────────────────────────── */
1270
+ .ui-app-badge {
1271
+ display: inline-flex;
1272
+ align-items: center;
1273
+ gap: .625rem;
1274
+ background: var(--ui-text, var(--text, #e2e2ea));
1275
+ color: var(--ui-bg, var(--bg, #0d0d10));
1276
+ border-radius: 10px;
1277
+ padding: .625rem 1.25rem;
1278
+ text-decoration: none;
1279
+ transition: opacity .15s;
1280
+ min-width: 148px;
1281
+ }
1282
+ .ui-app-badge:hover { opacity: .85; }
1283
+
1284
+ .ui-app-badge-text { display: flex; flex-direction: column; gap: .05rem; }
1285
+ .ui-app-badge-line1 { font-size: .65rem; font-weight: 400; line-height: 1; }
1286
+ .ui-app-badge-line2 { font-size: .95rem; font-weight: 700; line-height: 1; }
1287
+
1288
+ /* ─── Mobile ─────────────────────────────────────────────────────────────── */
1289
+ @media (max-width: 640px) {
1290
+ .ui-btn--lg {
1291
+ height: 48px;
1292
+ padding: 0 1.25rem;
1293
+ font-size: .95rem;
1294
+ }
1295
+
1296
+ .ui-stat-value { font-size: 1.6rem; }
1297
+
1298
+ /* Full-width buttons in narrow containers */
1299
+ .ui-btn--full { font-size: .9rem; }
1300
+
1301
+ /* Layout */
1302
+ .ui-section { padding-top: 3rem; padding-bottom: 3rem; }
1303
+ .ui-section--sm { padding-top: 2rem; padding-bottom: 2rem; }
1304
+ .ui-section--lg { padding-top: 4rem; padding-bottom: 4rem; }
1305
+
1306
+ .ui-grid--cols-2,
1307
+ .ui-grid--cols-3,
1308
+ .ui-grid--cols-4 { grid-template-columns: 1fr; }
1309
+
1310
+ .ui-media { grid-template-columns: 1fr; }
1311
+ .ui-media--reverse { direction: ltr; }
1312
+
1313
+ .ui-hero { padding: 3rem 1.25rem; }
1314
+ .ui-hero-title { font-size: 2rem; }
1315
+ .ui-hero-subtitle { font-size: 1rem; }
1316
+
1317
+ .ui-nav-links { display: none; }
1318
+ .ui-nav-burger { display: flex; }
1319
+ .ui-nav-inner { gap: .75rem; }
1320
+ }
1321
+
1322
+ /* ─── Utilities ──────────────────────────────────────────────────────────────
1323
+ Single-purpose helpers for spacing, typography, and layout.
1324
+ Use these in page HTML instead of writing custom CSS for common patterns.
1325
+ Prefix: u- (distinct from component classes which use ui-) */
1326
+
1327
+ /* Screen-reader only — visually hidden but accessible to assistive tech */
1328
+ .ui-sr-only {
1329
+ position: absolute;
1330
+ width: 1px; height: 1px;
1331
+ padding: 0; margin: -1px;
1332
+ overflow: hidden;
1333
+ clip: rect(0,0,0,0);
1334
+ white-space: nowrap;
1335
+ border: 0;
1336
+ }
1337
+
1338
+ /* Spacing scale: 1=4px 2=8px 3=12px 4=16px 5=20px 6=24px 8=32px 10=40px 12=48px 16=64px */
1339
+
1340
+ /* Margin top */
1341
+ .u-mt-0 { margin-top: 0; }
1342
+ .u-mt-1 { margin-top: .25rem; }
1343
+ .u-mt-2 { margin-top: .5rem; }
1344
+ .u-mt-3 { margin-top: .75rem; }
1345
+ .u-mt-4 { margin-top: 1rem; }
1346
+ .u-mt-5 { margin-top: 1.25rem; }
1347
+ .u-mt-6 { margin-top: 1.5rem; }
1348
+ .u-mt-8 { margin-top: 2rem; }
1349
+ .u-mt-10 { margin-top: 2.5rem; }
1350
+ .u-mt-12 { margin-top: 3rem; }
1351
+ .u-mt-16 { margin-top: 4rem; }
1352
+
1353
+ /* Margin bottom */
1354
+ .u-mb-0 { margin-bottom: 0; }
1355
+ .u-mb-1 { margin-bottom: .25rem; }
1356
+ .u-mb-2 { margin-bottom: .5rem; }
1357
+ .u-mb-3 { margin-bottom: .75rem; }
1358
+ .u-mb-4 { margin-bottom: 1rem; }
1359
+ .u-mb-5 { margin-bottom: 1.25rem; }
1360
+ .u-mb-6 { margin-bottom: 1.5rem; }
1361
+ .u-mb-8 { margin-bottom: 2rem; }
1362
+ .u-mb-10 { margin-bottom: 2.5rem; }
1363
+ .u-mb-12 { margin-bottom: 3rem; }
1364
+ .u-mb-16 { margin-bottom: 4rem; }
1365
+
1366
+ /* Margin left / right / auto */
1367
+ .u-ml-auto { margin-left: auto; }
1368
+ .u-mr-auto { margin-right: auto; }
1369
+ .u-mx-auto { margin-left: auto; margin-right: auto; }
1370
+
1371
+ /* Padding */
1372
+ .u-p-0 { padding: 0; }
1373
+ .u-p-1 { padding: .25rem; }
1374
+ .u-p-2 { padding: .5rem; }
1375
+ .u-p-3 { padding: .75rem; }
1376
+ .u-p-4 { padding: 1rem; }
1377
+ .u-p-5 { padding: 1.25rem; }
1378
+ .u-p-6 { padding: 1.5rem; }
1379
+ .u-p-8 { padding: 2rem; }
1380
+
1381
+ .u-px-0 { padding-left: 0; padding-right: 0; }
1382
+ .u-px-2 { padding-left: .5rem; padding-right: .5rem; }
1383
+ .u-px-3 { padding-left: .75rem; padding-right: .75rem; }
1384
+ .u-px-4 { padding-left: 1rem; padding-right: 1rem; }
1385
+ .u-px-5 { padding-left: 1.25rem;padding-right: 1.25rem; }
1386
+ .u-px-6 { padding-left: 1.5rem; padding-right: 1.5rem; }
1387
+ .u-px-8 { padding-left: 2rem; padding-right: 2rem; }
1388
+
1389
+ .u-py-0 { padding-top: 0; padding-bottom: 0; }
1390
+ .u-py-2 { padding-top: .5rem; padding-bottom: .5rem; }
1391
+ .u-py-3 { padding-top: .75rem; padding-bottom: .75rem; }
1392
+ .u-py-4 { padding-top: 1rem; padding-bottom: 1rem; }
1393
+ .u-py-5 { padding-top: 1.25rem;padding-bottom: 1.25rem; }
1394
+ .u-py-6 { padding-top: 1.5rem; padding-bottom: 1.5rem; }
1395
+ .u-py-8 { padding-top: 2rem; padding-bottom: 2rem; }
1396
+
1397
+ /* Typography — size */
1398
+ .u-text-xs { font-size: .75rem; line-height: 1.4; }
1399
+ .u-text-sm { font-size: .875rem; line-height: 1.5; }
1400
+ .u-text-base { font-size: 1rem; line-height: 1.6; }
1401
+ .u-text-lg { font-size: 1.125rem;line-height: 1.5; }
1402
+ .u-text-xl { font-size: 1.25rem; line-height: 1.4; }
1403
+ .u-text-2xl { font-size: 1.5rem; line-height: 1.3; }
1404
+ .u-text-3xl { font-size: 1.875rem;line-height: 1.2; }
1405
+ .u-text-4xl { font-size: 2.25rem; line-height: 1.15; }
1406
+ .u-text-5xl { font-size: 3rem; line-height: 1.1; }
1407
+ .u-text-6xl { font-size: 4rem; line-height: 1.05; }
1408
+ .u-text-7xl { font-size: 5rem; line-height: 1; }
1409
+
1410
+ /* Typography — weight */
1411
+ .u-font-normal { font-weight: 400; }
1412
+ .u-font-medium { font-weight: 500; }
1413
+ .u-font-semibold { font-weight: 600; }
1414
+ .u-font-bold { font-weight: 700; }
1415
+
1416
+ /* Typography — alignment */
1417
+ .u-text-left { text-align: left; }
1418
+ .u-text-center { text-align: center; }
1419
+ .u-text-right { text-align: right; }
1420
+ .u-text-balance { text-wrap: balance; }
1421
+
1422
+ /* Typography — color (uses tokens so theme overrides apply) */
1423
+ .u-text-default { color: var(--ui-text); }
1424
+ .u-text-muted { color: var(--ui-muted); }
1425
+ .u-text-accent { color: var(--ui-accent); }
1426
+ .u-text-green { color: var(--ui-green); }
1427
+ .u-text-red { color: var(--ui-red); }
1428
+ .u-text-yellow { color: var(--ui-yellow); }
1429
+ .u-text-blue { color: var(--ui-blue); }
1430
+
1431
+ /* Typography — line height */
1432
+ .u-leading-tight { line-height: 1.25; }
1433
+ .u-leading-snug { line-height: 1.375; }
1434
+ .u-leading-normal { line-height: 1.5; }
1435
+ .u-leading-relaxed { line-height: 1.625; }
1436
+ .u-leading-loose { line-height: 2; }
1437
+
1438
+ /* Width */
1439
+ .u-w-full { width: 100%; }
1440
+ .u-w-auto { width: auto; }
1441
+ .u-max-w-xs { max-width: 320px; }
1442
+ .u-max-w-sm { max-width: 480px; }
1443
+ .u-max-w-md { max-width: 640px; }
1444
+ .u-max-w-lg { max-width: 800px; }
1445
+ .u-max-w-xl { max-width: 1024px; }
1446
+ .u-max-w-prose { max-width: 65ch; }
1447
+
1448
+ /* Display */
1449
+ .u-block { display: block; }
1450
+ .u-inline { display: inline; }
1451
+ .u-inline-block { display: inline-block; }
1452
+ .u-hidden { display: none; }
1453
+
1454
+ /* Flexbox */
1455
+ .u-flex { display: flex; }
1456
+ .u-flex-col { display: flex; flex-direction: column; }
1457
+ .u-flex-wrap { flex-wrap: wrap; }
1458
+ .u-flex-1 { flex: 1; }
1459
+ .u-shrink-0 { flex-shrink: 0; }
1460
+
1461
+ .u-items-start { align-items: flex-start; }
1462
+ .u-items-center { align-items: center; }
1463
+ .u-items-end { align-items: flex-end; }
1464
+ .u-items-stretch { align-items: stretch; }
1465
+
1466
+ .u-justify-start { justify-content: flex-start; }
1467
+ .u-justify-center { justify-content: center; }
1468
+ .u-justify-end { justify-content: flex-end; }
1469
+ .u-justify-between { justify-content: space-between; }
1470
+
1471
+ .u-gap-1 { gap: .25rem; }
1472
+ .u-gap-2 { gap: .5rem; }
1473
+ .u-gap-3 { gap: .75rem; }
1474
+ .u-gap-4 { gap: 1rem; }
1475
+ .u-gap-5 { gap: 1.25rem; }
1476
+ .u-gap-6 { gap: 1.5rem; }
1477
+ .u-gap-8 { gap: 2rem; }
1478
+
1479
+ /* Border radius */
1480
+ .u-rounded { border-radius: var(--ui-radius-sm); }
1481
+ .u-rounded-md { border-radius: var(--ui-radius); }
1482
+ .u-rounded-lg { border-radius: calc(var(--ui-radius) * 1.5); }
1483
+ .u-rounded-xl { border-radius: calc(var(--ui-radius) * 2); }
1484
+ .u-rounded-full { border-radius: 9999px; }
1485
+
1486
+ /* Border */
1487
+ .u-border { border: 1px solid var(--ui-border); }
1488
+ .u-border-t { border-top: 1px solid var(--ui-border); }
1489
+ .u-border-b { border-bottom: 1px solid var(--ui-border); }
1490
+
1491
+ /* Background */
1492
+ .u-bg-surface { background: var(--ui-surface); }
1493
+ .u-bg-surface2 { background: var(--ui-surface-2); }
1494
+ .u-bg-accent { background: var(--ui-accent); }
1495
+
1496
+ /* Overflow */
1497
+ .u-overflow-hidden { overflow: hidden; }
1498
+ .u-overflow-auto { overflow: auto; }
1499
+
1500
+ /* Position */
1501
+ .u-relative { position: relative; }
1502
+ .u-absolute { position: absolute; }
1503
+
1504
+ /* Opacity */
1505
+ .u-opacity-50 { opacity: .5; }
1506
+ .u-opacity-75 { opacity: .75; }
1507
+
1508
+ /* ─── Section header ─────────────────────────────────────────────────────────
1509
+ Optional heading block prepended to section() when eyebrow/title/subtitle
1510
+ props are supplied. Sits above the content slot. */
1511
+ .ui-section-header { width: 100%; max-width: 1100px; margin: 0 auto 2.5rem; padding-left: 1.5rem; padding-right: 1.5rem; }
1512
+ .ui-section-header--center { text-align: center; }
1513
+ .ui-section-header--gap-none { margin-bottom: 0; }
1514
+ .ui-section-header--gap-sm { margin-bottom: 1.25rem; }
1515
+ .ui-section-header--gap-lg { margin-bottom: 4rem; }
1516
+
1517
+ .ui-section-eyebrow {
1518
+ display: block;
1519
+ font-size: .75rem;
1520
+ font-weight: 600;
1521
+ letter-spacing: .08em;
1522
+ text-transform: uppercase;
1523
+ color: var(--ui-accent);
1524
+ margin: 0 0 2rem;
1525
+ }
1526
+
1527
+ .ui-section-title {
1528
+ font-size: 2rem;
1529
+ font-weight: 700;
1530
+ line-height: 1.15;
1531
+ color: var(--ui-text);
1532
+ margin: 0 0 1.25rem;
1533
+ }
1534
+
1535
+ .ui-section-subtitle {
1536
+ font-size: 1rem;
1537
+ color: var(--ui-muted);
1538
+ line-height: 1.65;
1539
+ margin: 0;
1540
+ max-width: 58ch;
1541
+ }
1542
+
1543
+ .ui-section-header--center .ui-section-subtitle { margin-left: auto; margin-right: auto; }
1544
+
1545
+ @media (max-width: 640px) {
1546
+ .ui-section-title { font-size: 1.5rem; }
1547
+ .ui-section-header { margin-bottom: 2rem; }
1548
+ }
1549
+
1550
+ /* ─── CTA ────────────────────────────────────────────────────────────────────
1551
+ Call-to-action block. Sits inside section() + container(). */
1552
+ .ui-cta { text-align: center; }
1553
+ .ui-cta--left { text-align: left; }
1554
+
1555
+ .ui-cta-eyebrow {
1556
+ display: block;
1557
+ font-size: .75rem;
1558
+ font-weight: 600;
1559
+ letter-spacing: .08em;
1560
+ text-transform: uppercase;
1561
+ color: var(--ui-accent);
1562
+ margin: 0 0 .75rem;
1563
+ }
1564
+
1565
+ .ui-cta-title {
1566
+ font-size: 2.5rem;
1567
+ font-weight: 700;
1568
+ line-height: 1.1;
1569
+ color: var(--ui-text);
1570
+ margin: 0 0 1rem;
1571
+ }
1572
+
1573
+ .ui-cta-subtitle {
1574
+ font-size: 1.05rem;
1575
+ color: var(--ui-muted);
1576
+ line-height: 1.65;
1577
+ max-width: 56ch;
1578
+ margin: 0 auto 2rem;
1579
+ }
1580
+
1581
+ .ui-cta--left .ui-cta-subtitle { margin-left: 0; }
1582
+
1583
+ .ui-cta-actions {
1584
+ display: flex;
1585
+ gap: 1rem;
1586
+ flex-wrap: wrap;
1587
+ justify-content: center;
1588
+ }
1589
+
1590
+ .ui-cta--left .ui-cta-actions { justify-content: flex-start; }
1591
+
1592
+ @media (max-width: 640px) {
1593
+ .ui-cta-title { font-size: 1.75rem; }
1594
+ .ui-cta-actions { flex-direction: column; align-items: stretch; }
1595
+ }
1596
+
1597
+ /* ─── Code Window ────────────────────────────────────────────────────────────
1598
+ macOS-style window chrome around a <pre><code> block. */
1599
+ .ui-code-window {
1600
+ background: var(--ui-surface-2);
1601
+ border: 1px solid var(--ui-border);
1602
+ border-radius: var(--ui-radius);
1603
+ overflow: hidden;
1604
+ }
1605
+
1606
+ .ui-code-window-chrome {
1607
+ display: flex;
1608
+ align-items: center;
1609
+ gap: .4rem;
1610
+ padding: .6rem 1rem;
1611
+ background: var(--ui-surface);
1612
+ border-bottom: 1px solid var(--ui-border);
1613
+ }
1614
+
1615
+ .ui-code-window-dot {
1616
+ width: 10px;
1617
+ height: 10px;
1618
+ border-radius: 50%;
1619
+ flex-shrink: 0;
1620
+ }
1621
+
1622
+ .ui-code-window-dot:nth-child(1) { background: #ff5f57; }
1623
+ .ui-code-window-dot:nth-child(2) { background: #febc2e; }
1624
+ .ui-code-window-dot:nth-child(3) { background: #28c840; }
1625
+
1626
+ .ui-code-window-filename {
1627
+ font-size: .75rem;
1628
+ font-family: var(--ui-mono);
1629
+ color: var(--ui-muted);
1630
+ margin-left: .35rem;
1631
+ }
1632
+
1633
+ .ui-code-window-lang {
1634
+ font-size: .7rem;
1635
+ font-family: var(--ui-mono);
1636
+ color: var(--ui-muted);
1637
+ margin-left: auto;
1638
+ }
1639
+
1640
+ .ui-code-window-pre {
1641
+ margin: 0;
1642
+ padding: 1.25rem 1.5rem;
1643
+ overflow-x: auto;
1644
+ font-family: var(--ui-mono);
1645
+ font-size: .85rem;
1646
+ line-height: 1.7;
1647
+ color: var(--ui-text);
1648
+ tab-size: 2;
1649
+ }
1650
+
1651
+ .ui-code-window-code { font-family: inherit; }
1652
+
1653
+ /* ─── Footer ─────────────────────────────────────────────────────────────────
1654
+ Site footer — logo, nav links, legal text. Stacks on mobile. */
1655
+ .ui-footer {
1656
+ padding: 3rem 1.5rem;
1657
+ border-top: 1px solid var(--ui-border);
1658
+ }
1659
+
1660
+ .ui-footer-inner {
1661
+ max-width: 1200px;
1662
+ margin: 0 auto;
1663
+ display: flex;
1664
+ align-items: center;
1665
+ gap: 2rem;
1666
+ flex-wrap: wrap;
1667
+ }
1668
+
1669
+ .ui-footer-logo {
1670
+ font-size: 1rem;
1671
+ font-weight: 600;
1672
+ color: var(--ui-text);
1673
+ text-decoration: none;
1674
+ flex-shrink: 0;
1675
+ transition: color .15s;
1676
+ }
1677
+
1678
+ .ui-footer-logo:hover { color: var(--ui-accent); }
1679
+ .ui-footer-logo:focus-visible {
1680
+ outline: 2px solid var(--ui-accent);
1681
+ outline-offset: 2px;
1682
+ border-radius: 2px;
1683
+ }
1684
+
1685
+ .ui-footer-links {
1686
+ display: flex;
1687
+ gap: 1.5rem;
1688
+ flex-wrap: wrap;
1689
+ flex: 1;
1690
+ }
1691
+
1692
+ .ui-footer-link {
1693
+ font-size: .875rem;
1694
+ color: var(--ui-muted);
1695
+ text-decoration: none;
1696
+ transition: color .15s;
1697
+ }
1698
+
1699
+ .ui-footer-link:hover { color: var(--ui-text); }
1700
+ .ui-footer-link:focus-visible {
1701
+ outline: 2px solid var(--ui-accent);
1702
+ outline-offset: 2px;
1703
+ border-radius: 2px;
1704
+ }
1705
+
1706
+ .ui-footer-legal {
1707
+ font-size: .8rem;
1708
+ color: var(--ui-muted);
1709
+ margin: 0 0 0 auto;
1710
+ }
1711
+
1712
+ @media (max-width: 640px) {
1713
+ .ui-footer-inner { flex-direction: column; align-items: flex-start; gap: 1.25rem; }
1714
+ .ui-footer-legal { margin-left: 0; }
1715
+ .ui-footer-links { gap: 1rem; }
1716
+ }
1717
+
1718
+ /* ─── Icon wrapper ───────────────────────────────────────────────────────────
1719
+ Wraps any icon in a tinted background shape.
1720
+ bg: 'circle' → border-radius: 50% | bg: 'square' → var(--ui-radius) */
1721
+
1722
+ .ui-icon-wrap {
1723
+ display: inline-flex;
1724
+ align-items: center;
1725
+ justify-content: center;
1726
+ padding: .55em;
1727
+ flex-shrink: 0;
1728
+ line-height: 1;
1729
+ }
1730
+
1731
+ .ui-icon-wrap--circle { border-radius: 50%; }
1732
+ .ui-icon-wrap--square { border-radius: var(--ui-radius); }
1733
+
1734
+ .ui-icon-wrap--accent { background: var(--ui-accent-dim); color: var(--ui-accent); }
1735
+ .ui-icon-wrap--success { background: var(--ui-green-dim); color: var(--ui-green); }
1736
+ .ui-icon-wrap--warning { background: var(--ui-yellow-dim); color: var(--ui-yellow); }
1737
+ .ui-icon-wrap--error { background: var(--ui-red-dim); color: var(--ui-red); }
1738
+ .ui-icon-wrap--muted { background: var(--ui-surface-2); color: var(--ui-muted); }
1739
+
1740
+ /* ─── Timeline ───────────────────────────────────────────────────────────────
1741
+ Shared rules (dot, label, body) apply to both orientations. */
1742
+
1743
+ /* Shared base */
1744
+ .ui-timeline {
1745
+ list-style: none;
1746
+ padding: 0;
1747
+ margin: 0;
1748
+ }
1749
+
1750
+ .ui-timeline-dot {
1751
+ width: 10px;
1752
+ height: 10px;
1753
+ border-radius: 50%;
1754
+ flex-shrink: 0;
1755
+ display: flex;
1756
+ align-items: center;
1757
+ justify-content: center;
1758
+ position: relative;
1759
+ z-index: 1;
1760
+ }
1761
+
1762
+ /* Icon dot — larger, with dim background */
1763
+ .ui-timeline-dot--icon {
1764
+ width: 2rem;
1765
+ height: 2rem;
1766
+ border-radius: 50%;
1767
+ font-size: 1rem;
1768
+ }
1769
+
1770
+ /* Dot colour variants */
1771
+ .ui-timeline-dot--accent { background: var(--ui-accent); }
1772
+ .ui-timeline-dot--success { background: var(--ui-green); }
1773
+ .ui-timeline-dot--warning { background: var(--ui-yellow); }
1774
+ .ui-timeline-dot--error { background: var(--ui-red); }
1775
+ .ui-timeline-dot--muted { background: var(--ui-surface-2); outline: 2px solid var(--ui-border); outline-offset: 0; }
1776
+
1777
+ /* Icon dot: dim background + coloured icon */
1778
+ .ui-timeline-dot--icon.ui-timeline-dot--accent { background: var(--ui-accent-dim); color: var(--ui-accent); }
1779
+ .ui-timeline-dot--icon.ui-timeline-dot--success { background: var(--ui-green-dim); color: var(--ui-green); }
1780
+ .ui-timeline-dot--icon.ui-timeline-dot--warning { background: var(--ui-yellow-dim); color: var(--ui-yellow); }
1781
+ .ui-timeline-dot--icon.ui-timeline-dot--error { background: var(--ui-red-dim); color: var(--ui-red); }
1782
+ .ui-timeline-dot--icon.ui-timeline-dot--muted { background: var(--ui-surface-2); color: var(--ui-muted); }
1783
+
1784
+ .ui-timeline-label {
1785
+ display: block;
1786
+ font-size: .72rem;
1787
+ font-weight: 600;
1788
+ color: var(--ui-muted);
1789
+ letter-spacing: .05em;
1790
+ text-transform: uppercase;
1791
+ margin-bottom: .35rem;
1792
+ }
1793
+
1794
+ /* ── Vertical ── */
1795
+ .ui-timeline--vertical {
1796
+ display: flex;
1797
+ flex-direction: column;
1798
+ }
1799
+
1800
+ .ui-timeline--vertical .ui-timeline-item {
1801
+ display: flex;
1802
+ gap: 1rem;
1803
+ }
1804
+
1805
+ .ui-timeline--vertical .ui-timeline-side {
1806
+ display: flex;
1807
+ flex-direction: column;
1808
+ align-items: center;
1809
+ flex-shrink: 0;
1810
+ }
1811
+
1812
+ /* Connecting line segments run above and below the dot */
1813
+ .ui-timeline--vertical .ui-timeline-connector {
1814
+ width: 2px;
1815
+ background: var(--ui-border);
1816
+ flex: 1;
1817
+ min-height: .75rem;
1818
+ }
1819
+
1820
+ /* No line above the first item or below the last */
1821
+ .ui-timeline--vertical .ui-timeline-item:first-child .ui-timeline-connector--before,
1822
+ .ui-timeline--vertical .ui-timeline-item:last-child .ui-timeline-connector--after {
1823
+ visibility: hidden;
1824
+ }
1825
+
1826
+ .ui-timeline--vertical .ui-timeline-main {
1827
+ flex: 1;
1828
+ padding-bottom: 1.75rem;
1829
+ }
1830
+
1831
+ .ui-timeline--vertical .ui-timeline-item:last-child .ui-timeline-main {
1832
+ padding-bottom: 0;
1833
+ }
1834
+
1835
+ /* ── Horizontal ── */
1836
+ .ui-timeline--horizontal {
1837
+ display: flex;
1838
+ align-items: flex-start;
1839
+ overflow-x: auto;
1840
+ }
1841
+
1842
+ .ui-timeline--horizontal .ui-timeline-item {
1843
+ flex: 1;
1844
+ min-width: 0;
1845
+ display: flex;
1846
+ flex-direction: column;
1847
+ align-items: center;
1848
+ }
1849
+
1850
+ .ui-timeline--horizontal .ui-timeline-side {
1851
+ display: flex;
1852
+ align-items: center;
1853
+ width: 100%;
1854
+ margin-bottom: .75rem;
1855
+ }
1856
+
1857
+ .ui-timeline--horizontal .ui-timeline-connector {
1858
+ flex: 1;
1859
+ height: 2px;
1860
+ background: var(--ui-border);
1861
+ }
1862
+
1863
+ /* No line before the first item or after the last */
1864
+ .ui-timeline--horizontal .ui-timeline-item:first-child .ui-timeline-connector--before,
1865
+ .ui-timeline--horizontal .ui-timeline-item:last-child .ui-timeline-connector--after {
1866
+ visibility: hidden;
1867
+ }
1868
+
1869
+ .ui-timeline--horizontal .ui-timeline-main {
1870
+ text-align: center;
1871
+ padding: 0 .5rem;
1872
+ width: 100%;
1873
+ }
1874
+
1875
+ /* ─── Switch ─────────────────────────────────────────────────────────────── */
1876
+ .ui-switch-input {
1877
+ position: absolute;
1878
+ width: 1px;
1879
+ height: 1px;
1880
+ padding: 0;
1881
+ margin: -1px;
1882
+ overflow: hidden;
1883
+ clip: rect(0,0,0,0);
1884
+ border: 0;
1885
+ }
1886
+
1887
+ .ui-switch-label {
1888
+ display: inline-flex;
1889
+ align-items: center;
1890
+ gap: .65rem;
1891
+ cursor: pointer;
1892
+ user-select: none;
1893
+ }
1894
+
1895
+ .ui-switch-label--disabled {
1896
+ opacity: .5;
1897
+ cursor: not-allowed;
1898
+ }
1899
+
1900
+ .ui-switch-track {
1901
+ position: relative;
1902
+ display: inline-flex;
1903
+ align-items: center;
1904
+ width: 3rem;
1905
+ height: 1.75rem;
1906
+ border-radius: 999px;
1907
+ background: var(--ui-border);
1908
+ transition: background .2s;
1909
+ flex-shrink: 0;
1910
+ }
1911
+
1912
+ .ui-switch-thumb {
1913
+ position: absolute;
1914
+ left: .2rem;
1915
+ width: 1.35rem;
1916
+ height: 1.35rem;
1917
+ border-radius: 50%;
1918
+ background: #fff;
1919
+ box-shadow: 0 1px 3px rgba(0,0,0,.3);
1920
+ transition: transform .2s cubic-bezier(.34,1.56,.64,1), background .2s;
1921
+ }
1922
+
1923
+ .ui-switch-input:checked + .ui-switch-track {
1924
+ background: var(--ui-accent);
1925
+ }
1926
+
1927
+ .ui-switch-input:checked + .ui-switch-track .ui-switch-thumb {
1928
+ transform: translateX(1.25rem);
1929
+ }
1930
+
1931
+ .ui-switch-input:focus-visible + .ui-switch-track {
1932
+ outline: 2px solid var(--ui-accent);
1933
+ outline-offset: 2px;
1934
+ }
1935
+
1936
+ .ui-switch-text {
1937
+ font-family: var(--ui-font);
1938
+ font-size: .9rem;
1939
+ color: var(--ui-text);
1940
+ line-height: 1.4;
1941
+ }
1942
+
1943
+ /* ─── Radio ──────────────────────────────────────────────────────────────── */
1944
+ .ui-radio-group {
1945
+ border: 1px solid var(--ui-border);
1946
+ border-radius: var(--ui-radius);
1947
+ padding: 0;
1948
+ margin: 0;
1949
+ }
1950
+
1951
+ .ui-radio-group-body {
1952
+ display: flex;
1953
+ flex-direction: column;
1954
+ gap: var(--radio-gap, .75rem);
1955
+ padding: 1.25rem;
1956
+ }
1957
+
1958
+ /* ─── Checkbox ───────────────────────────────────────────────────────────── */
1959
+ .ui-checkbox {
1960
+ display: inline-flex;
1961
+ align-items: flex-start;
1962
+ gap: .6rem;
1963
+ cursor: pointer;
1964
+ user-select: none;
1965
+ }
1966
+
1967
+ .ui-checkbox--disabled {
1968
+ opacity: .5;
1969
+ cursor: not-allowed;
1970
+ }
1971
+
1972
+ .ui-checkbox-input {
1973
+ position: absolute;
1974
+ width: 1px;
1975
+ height: 1px;
1976
+ padding: 0;
1977
+ margin: -1px;
1978
+ overflow: hidden;
1979
+ clip: rect(0,0,0,0);
1980
+ border: 0;
1981
+ }
1982
+
1983
+ .ui-checkbox-box {
1984
+ position: relative;
1985
+ display: inline-flex;
1986
+ align-items: center;
1987
+ justify-content: center;
1988
+ width: 1.125rem;
1989
+ height: 1.125rem;
1990
+ border-radius: .25rem;
1991
+ border: 2px solid var(--ui-border);
1992
+ background: var(--ui-surface);
1993
+ flex-shrink: 0;
1994
+ margin-top: .125rem;
1995
+ transition: border-color .15s, background .15s;
1996
+ }
1997
+
1998
+ .ui-checkbox-box::after {
1999
+ content: '';
2000
+ position: absolute;
2001
+ width: .3rem;
2002
+ height: .55rem;
2003
+ border-right: 2px solid var(--ui-bg);
2004
+ border-bottom: 2px solid var(--ui-bg);
2005
+ transform: rotate(45deg) scale(0);
2006
+ transform-origin: center;
2007
+ margin-top: -.1rem;
2008
+ opacity: 0;
2009
+ transition: opacity .1s, transform .15s cubic-bezier(.34, 1.56, .64, 1);
2010
+ }
2011
+
2012
+ .ui-checkbox-input:checked + .ui-checkbox-box {
2013
+ border-color: var(--ui-accent);
2014
+ background: var(--ui-accent);
2015
+ }
2016
+
2017
+ .ui-checkbox-input:checked + .ui-checkbox-box::after {
2018
+ opacity: 1;
2019
+ transform: rotate(45deg) scale(1);
2020
+ }
2021
+
2022
+ .ui-checkbox-input:focus-visible + .ui-checkbox-box {
2023
+ outline: 2px solid var(--ui-accent);
2024
+ outline-offset: 2px;
2025
+ }
2026
+
2027
+ .ui-checkbox--error .ui-checkbox-box {
2028
+ border-color: var(--ui-red);
2029
+ }
2030
+
2031
+ .ui-checkbox-label {
2032
+ font-family: var(--ui-font);
2033
+ font-size: .9rem;
2034
+ color: var(--ui-text);
2035
+ line-height: 1.4;
2036
+ }
2037
+
2038
+ /* ─── Radio ──────────────────────────────────────────────────────────────── */
2039
+ .ui-radio {
2040
+ display: inline-flex;
2041
+ align-items: center;
2042
+ gap: .6rem;
2043
+ cursor: pointer;
2044
+ user-select: none;
2045
+ }
2046
+
2047
+ .ui-radio--disabled {
2048
+ opacity: .5;
2049
+ cursor: not-allowed;
2050
+ }
2051
+
2052
+ .ui-radio-input {
2053
+ position: absolute;
2054
+ width: 1px;
2055
+ height: 1px;
2056
+ padding: 0;
2057
+ margin: -1px;
2058
+ overflow: hidden;
2059
+ clip: rect(0,0,0,0);
2060
+ border: 0;
2061
+ }
2062
+
2063
+ .ui-radio-dot {
2064
+ position: relative;
2065
+ display: inline-flex;
2066
+ align-items: center;
2067
+ justify-content: center;
2068
+ width: 1.25rem;
2069
+ height: 1.25rem;
2070
+ border-radius: 50%;
2071
+ border: 2px solid var(--ui-border);
2072
+ background: var(--ui-surface);
2073
+ flex-shrink: 0;
2074
+ transition: border-color .15s, background .15s;
2075
+ }
2076
+
2077
+ .ui-radio-dot::after {
2078
+ content: '';
2079
+ width: .5rem;
2080
+ height: .5rem;
2081
+ border-radius: 50%;
2082
+ background: var(--ui-bg);
2083
+ opacity: 0;
2084
+ transform: scale(0);
2085
+ transition: opacity .15s, transform .2s cubic-bezier(.34,1.56,.64,1);
2086
+ }
2087
+
2088
+ .ui-radio-input:checked + .ui-radio-dot {
2089
+ border-color: var(--ui-accent);
2090
+ background: var(--ui-accent);
2091
+ }
2092
+
2093
+ .ui-radio-input:checked + .ui-radio-dot::after {
2094
+ opacity: 1;
2095
+ transform: scale(1);
2096
+ }
2097
+
2098
+ .ui-radio-input:focus-visible + .ui-radio-dot {
2099
+ outline: 2px solid var(--ui-accent);
2100
+ outline-offset: 2px;
2101
+ }
2102
+
2103
+ .ui-radio-label {
2104
+ font-family: var(--ui-font);
2105
+ font-size: .9rem;
2106
+ color: var(--ui-text);
2107
+ line-height: 1.4;
2108
+ }
2109
+
2110
+ .ui-radio-group--error .ui-radio-dot {
2111
+ border-color: var(--ui-red);
2112
+ }
2113
+
2114
+ /* ─── Rating ─────────────────────────────────────────────────────────────── */
2115
+ .ui-rating {
2116
+ display: inline-flex;
2117
+ align-items: center;
2118
+ gap: .1em;
2119
+ font-size: var(--rating-size, 1.5rem);
2120
+ color: var(--ui-muted);
2121
+ line-height: 1;
2122
+ }
2123
+
2124
+ /* Read-only stars */
2125
+ .ui-rating-star--filled,
2126
+ .ui-rating-star--half { color: var(--ui-yellow); }
2127
+
2128
+ /* Interactive stars container — row-reverse makes high→low DOM order appear as 1…max */
2129
+ .ui-rating-stars {
2130
+ display: inline-flex;
2131
+ flex-direction: row-reverse;
2132
+ gap: .1em;
2133
+ font-size: var(--rating-size, 1.5rem);
2134
+ line-height: 1;
2135
+ }
2136
+
2137
+ /* Each input is nested inside its label — hidden but in the tab order */
2138
+ .ui-rating-input {
2139
+ position: absolute;
2140
+ width: 1px;
2141
+ height: 1px;
2142
+ padding: 0;
2143
+ margin: -1px;
2144
+ overflow: hidden;
2145
+ clip: rect(0,0,0,0);
2146
+ border: 0;
2147
+ }
2148
+
2149
+ /* Star labels — only flex items, no invisible elements between them */
2150
+ .ui-rating-stars .ui-rating-star {
2151
+ color: var(--ui-muted);
2152
+ cursor: pointer;
2153
+ transition: color .1s;
2154
+ user-select: none;
2155
+ }
2156
+
2157
+ /* Checked: colour the label containing the checked input + all DOM-subsequent
2158
+ labels (= visually lower-numbered stars due to row-reverse) */
2159
+ .ui-rating-stars .ui-rating-star:has(input:checked),
2160
+ .ui-rating-stars .ui-rating-star:has(input:checked) ~ .ui-rating-star {
2161
+ color: var(--ui-yellow);
2162
+ }
2163
+
2164
+ /* Hover: reset everything, then re-highlight up to the hovered star */
2165
+ .ui-rating-stars:hover .ui-rating-star { color: var(--ui-muted); }
2166
+ .ui-rating-stars .ui-rating-star:hover,
2167
+ .ui-rating-stars .ui-rating-star:hover ~ .ui-rating-star { color: var(--ui-yellow); }
2168
+
2169
+ /* Focus ring on the label when its input is keyboard-focused */
2170
+ .ui-rating-star:focus-within {
2171
+ outline: 2px solid var(--ui-accent);
2172
+ outline-offset: 2px;
2173
+ border-radius: 2px;
2174
+ }
2175
+
2176
+ /* Disabled */
2177
+ fieldset[disabled] .ui-rating-star {
2178
+ cursor: not-allowed;
2179
+ opacity: .5;
2180
+ }
2181
+ fieldset[disabled] .ui-rating-stars:hover .ui-rating-star { color: revert; }
2182
+ fieldset[disabled] .ui-rating-stars .ui-rating-star:hover,
2183
+ fieldset[disabled] .ui-rating-stars .ui-rating-star:hover ~ .ui-rating-star { color: revert; }
2184
+
2185
+ /* ─── Spinner ────────────────────────────────────────────────────────────── */
2186
+ @keyframes ui-spin {
2187
+ to { transform: rotate(360deg); }
2188
+ }
2189
+
2190
+ .ui-spinner {
2191
+ display: inline-block;
2192
+ width: var(--spinner-size, 1.5rem);
2193
+ height: var(--spinner-size, 1.5rem);
2194
+ border: 2px solid color-mix(in srgb, var(--spinner-color, var(--ui-accent)) 20%, transparent);
2195
+ border-top-color: var(--spinner-color, var(--ui-accent));
2196
+ border-radius: 50%;
2197
+ animation: ui-spin .7s linear infinite;
2198
+ flex-shrink: 0;
2199
+ }
2200
+
2201
+ /* ─── Progress ───────────────────────────────────────────────────────────── */
2202
+ .ui-progress { width: 100%; }
2203
+
2204
+ .ui-progress-header {
2205
+ display: flex;
2206
+ justify-content: space-between;
2207
+ align-items: baseline;
2208
+ margin-bottom: .4rem;
2209
+ gap: 1rem;
2210
+ }
2211
+
2212
+ .ui-progress-label {
2213
+ font-size: .8rem;
2214
+ font-weight: 600;
2215
+ color: var(--ui-text);
2216
+ }
2217
+
2218
+ .ui-progress-value {
2219
+ font-size: .8rem;
2220
+ color: var(--ui-muted);
2221
+ font-variant-numeric: tabular-nums;
2222
+ }
2223
+
2224
+ .ui-progress-track {
2225
+ width: 100%;
2226
+ height: var(--progress-height, .5rem);
2227
+ background: var(--ui-border);
2228
+ border-radius: 999px;
2229
+ overflow: hidden;
2230
+ }
2231
+
2232
+ .ui-progress-fill {
2233
+ height: 100%;
2234
+ border-radius: 999px;
2235
+ transition: width .3s ease;
2236
+ }
2237
+
2238
+ /* Variants */
2239
+ .ui-progress--accent .ui-progress-fill { background: var(--ui-accent); }
2240
+ .ui-progress--success .ui-progress-fill { background: var(--ui-green); }
2241
+ .ui-progress--warning .ui-progress-fill { background: var(--ui-yellow); }
2242
+ .ui-progress--error .ui-progress-fill { background: var(--ui-red); }
2243
+
2244
+ /* Indeterminate — animates a fill bar back and forth */
2245
+ @keyframes ui-progress-indeterminate {
2246
+ 0% { transform: translateX(-100%) scaleX(.4); }
2247
+ 50% { transform: translateX( 60%) scaleX(.6); }
2248
+ 100% { transform: translateX( 200%) scaleX(.4); }
2249
+ }
2250
+
2251
+ .ui-progress--indeterminate .ui-progress-fill {
2252
+ width: 50%;
2253
+ animation: ui-progress-indeterminate 1.4s ease infinite;
2254
+ transform-origin: left center;
2255
+ }
2256
+
2257
+ /* ─── Slider ─────────────────────────────────────────────────────────────── */
2258
+ .ui-slider {
2259
+ width: 100%;
2260
+ height: var(--ui-touch-min);
2261
+ -webkit-appearance: none;
2262
+ appearance: none;
2263
+ background: transparent;
2264
+ cursor: pointer;
2265
+ padding: 0;
2266
+ margin: 0;
2267
+ }
2268
+ .ui-slider::-webkit-slider-runnable-track {
2269
+ height: 4px;
2270
+ border-radius: 999px;
2271
+ background: linear-gradient(
2272
+ to right,
2273
+ var(--ui-accent) 0% var(--slider-fill, 50%),
2274
+ var(--ui-border) var(--slider-fill, 50%) 100%
2275
+ );
2276
+ }
2277
+ .ui-slider::-moz-range-track {
2278
+ height: 4px;
2279
+ border-radius: 999px;
2280
+ background: var(--ui-border);
2281
+ }
2282
+ .ui-slider::-moz-range-progress {
2283
+ height: 4px;
2284
+ border-radius: 999px;
2285
+ background: var(--ui-accent);
2286
+ }
2287
+ .ui-slider::-webkit-slider-thumb {
2288
+ -webkit-appearance: none;
2289
+ width: 20px;
2290
+ height: 20px;
2291
+ border-radius: 50%;
2292
+ background: var(--ui-accent);
2293
+ margin-top: -8px;
2294
+ box-shadow: 0 1px 4px rgba(0,0,0,.3);
2295
+ transition: transform .15s;
2296
+ }
2297
+ .ui-slider::-moz-range-thumb {
2298
+ width: 20px;
2299
+ height: 20px;
2300
+ border-radius: 50%;
2301
+ background: var(--ui-accent);
2302
+ border: none;
2303
+ box-shadow: 0 1px 4px rgba(0,0,0,.3);
2304
+ }
2305
+ .ui-slider::-webkit-slider-thumb:hover { transform: scale(1.15); }
2306
+ .ui-slider:focus-visible { outline: none; }
2307
+ .ui-slider:focus-visible::-webkit-slider-thumb {
2308
+ outline: 2px solid var(--ui-accent);
2309
+ outline-offset: 3px;
2310
+ }
2311
+ .ui-slider:disabled { opacity: .5; cursor: not-allowed; }
2312
+
2313
+ .ui-label--row {
2314
+ display: flex;
2315
+ justify-content: space-between;
2316
+ align-items: baseline;
2317
+ }
2318
+ .ui-slider-output {
2319
+ font-size: .8125rem;
2320
+ color: var(--ui-muted);
2321
+ font-variant-numeric: tabular-nums;
2322
+ min-width: 3ch;
2323
+ text-align: right;
2324
+ }
2325
+
2326
+ /* ─── File Upload ────────────────────────────────────────────────────────── */
2327
+
2328
+ .ui-upload {
2329
+ position: relative;
2330
+ display: flex;
2331
+ align-items: center;
2332
+ justify-content: center;
2333
+ padding: 2rem 1.5rem;
2334
+ background: var(--ui-surface);
2335
+ border: 1.5px dashed var(--ui-border);
2336
+ border-radius: var(--ui-radius);
2337
+ cursor: pointer;
2338
+ transition: border-color .15s, background .15s;
2339
+ outline: none;
2340
+ user-select: none;
2341
+ }
2342
+
2343
+ .ui-upload:hover:not(.ui-upload--disabled),
2344
+ .ui-upload:focus-visible {
2345
+ border-color: var(--ui-accent);
2346
+ background: color-mix(in srgb, var(--ui-accent) 5%, var(--ui-surface));
2347
+ }
2348
+
2349
+ .ui-upload--active {
2350
+ border-color: var(--ui-accent);
2351
+ background: color-mix(in srgb, var(--ui-accent) 8%, var(--ui-surface));
2352
+ }
2353
+
2354
+ .ui-upload--error { border-color: var(--ui-red); }
2355
+ .ui-upload--selected { border-color: var(--ui-accent); }
2356
+ .ui-upload--selected .ui-upload-text { color: var(--ui-text); font-weight: 500; }
2357
+
2358
+ .ui-upload--disabled {
2359
+ opacity: .5;
2360
+ cursor: not-allowed;
2361
+ }
2362
+
2363
+ .ui-upload-body {
2364
+ display: flex;
2365
+ flex-direction: column;
2366
+ align-items: center;
2367
+ gap: .6rem;
2368
+ pointer-events: none;
2369
+ }
2370
+
2371
+ .ui-upload-icon { color: var(--ui-muted); display: block; }
2372
+
2373
+ .ui-upload:hover:not(.ui-upload--disabled) .ui-upload-icon,
2374
+ .ui-upload--active .ui-upload-icon { color: var(--ui-accent); }
2375
+
2376
+ .ui-upload-text {
2377
+ font-size: .875rem;
2378
+ color: var(--ui-muted);
2379
+ text-align: center;
2380
+ line-height: 1.5;
2381
+ }
2382
+
2383
+ .ui-upload-browse {
2384
+ color: var(--ui-accent);
2385
+ text-decoration: underline;
2386
+ text-underline-offset: 2px;
2387
+ }
2388
+
2389
+ .ui-upload-input {
2390
+ display: none;
2391
+ }
2392
+
2393
+ /* ─── Segmented ─────────────────────────────────────────────────────────── */
2394
+ .ui-segmented {
2395
+ display: inline-flex;
2396
+ background: var(--ui-surface-2);
2397
+ border-radius: var(--ui-radius);
2398
+ padding: 3px;
2399
+ gap: 2px;
2400
+ }
2401
+ .ui-segmented-input {
2402
+ position: absolute;
2403
+ width: 1px; height: 1px;
2404
+ padding: 0; margin: -1px;
2405
+ overflow: hidden; clip: rect(0,0,0,0); border: 0;
2406
+ }
2407
+ .ui-segmented-label {
2408
+ display: inline-flex;
2409
+ align-items: center;
2410
+ padding: .4rem .9rem;
2411
+ border-radius: calc(var(--ui-radius) - 2px);
2412
+ font-size: .85rem;
2413
+ font-weight: 500;
2414
+ color: var(--ui-muted);
2415
+ cursor: pointer;
2416
+ user-select: none;
2417
+ white-space: nowrap;
2418
+ transition: background .15s, color .15s, box-shadow .15s;
2419
+ }
2420
+ .ui-segmented--sm .ui-segmented-label { font-size: .75rem; padding: .25rem .65rem; }
2421
+ .ui-segmented--lg .ui-segmented-label { font-size: .95rem; padding: .55rem 1.1rem; }
2422
+ .ui-segmented-input:checked + .ui-segmented-label {
2423
+ background: var(--ui-surface);
2424
+ color: var(--ui-text);
2425
+ box-shadow: 0 1px 3px rgba(0,0,0,.25);
2426
+ }
2427
+ .ui-segmented-input:focus-visible + .ui-segmented-label {
2428
+ outline: 2px solid var(--ui-accent);
2429
+ outline-offset: 1px;
2430
+ }
2431
+
2432
+ /* ─── Breadcrumbs ────────────────────────────────────────────────────────── */
2433
+ .ui-breadcrumbs-list {
2434
+ display: flex;
2435
+ flex-wrap: wrap;
2436
+ align-items: center;
2437
+ gap: .25rem;
2438
+ list-style: none;
2439
+ padding: 0;
2440
+ margin: 0;
2441
+ font-size: .85rem;
2442
+ }
2443
+ .ui-breadcrumbs-item {
2444
+ display: flex;
2445
+ align-items: center;
2446
+ gap: .25rem;
2447
+ }
2448
+ .ui-breadcrumbs-link {
2449
+ color: var(--ui-muted);
2450
+ text-decoration: none;
2451
+ transition: color .15s;
2452
+ }
2453
+ .ui-breadcrumbs-link:hover { color: var(--ui-text); }
2454
+ .ui-breadcrumbs-current { color: var(--ui-text); }
2455
+ .ui-breadcrumbs-sep { color: var(--ui-border); user-select: none; }
2456
+
2457
+ /* ─── Stepper ────────────────────────────────────────────────────────────── */
2458
+ .ui-stepper {
2459
+ display: flex;
2460
+ align-items: flex-start;
2461
+ width: 100%;
2462
+ }
2463
+ .ui-stepper-item {
2464
+ flex: 1;
2465
+ display: flex;
2466
+ flex-direction: column;
2467
+ align-items: center;
2468
+ position: relative;
2469
+ }
2470
+ .ui-stepper-item:not(:last-child)::after {
2471
+ content: '';
2472
+ position: absolute;
2473
+ top: 13px;
2474
+ left: 50%;
2475
+ width: 100%;
2476
+ height: 2px;
2477
+ background: var(--ui-border);
2478
+ }
2479
+ .ui-stepper-item--complete:not(:last-child)::after { background: var(--ui-accent); }
2480
+ .ui-stepper-dot {
2481
+ position: relative;
2482
+ z-index: 1;
2483
+ width: 28px;
2484
+ height: 28px;
2485
+ border-radius: 50%;
2486
+ display: flex;
2487
+ align-items: center;
2488
+ justify-content: center;
2489
+ font-size: .75rem;
2490
+ font-weight: 700;
2491
+ background: var(--ui-surface-2);
2492
+ border: 2px solid var(--ui-border);
2493
+ color: var(--ui-muted);
2494
+ transition: background .2s, border-color .2s, color .2s;
2495
+ }
2496
+ .ui-stepper-item--complete .ui-stepper-dot {
2497
+ background: var(--ui-accent);
2498
+ border-color: var(--ui-accent);
2499
+ color: var(--ui-bg);
2500
+ }
2501
+ .ui-stepper-item--active .ui-stepper-dot {
2502
+ border-color: var(--ui-accent);
2503
+ color: var(--ui-accent);
2504
+ }
2505
+ .ui-stepper-label {
2506
+ margin-top: .5rem;
2507
+ font-size: .72rem;
2508
+ color: var(--ui-muted);
2509
+ text-align: center;
2510
+ line-height: 1.3;
2511
+ padding: 0 .25rem;
2512
+ }
2513
+ .ui-stepper-item--active .ui-stepper-label { color: var(--ui-text); font-weight: 600; }
2514
+ .ui-stepper-item--complete .ui-stepper-label { color: var(--ui-muted); }
2515
+
2516
+ /* ─── Image ──────────────────────────────────────────────────────────────── */
2517
+ .ui-image {
2518
+ display: block;
2519
+ }
2520
+ .ui-image-crop {
2521
+ overflow: hidden;
2522
+ border-radius: var(--ui-radius);
2523
+ }
2524
+ .ui-image-wrap {
2525
+ display: block;
2526
+ overflow: hidden;
2527
+ border-radius: var(--ui-radius);
2528
+ }
2529
+ .ui-image-img--cover {
2530
+ display: block;
2531
+ width: 100%;
2532
+ height: auto;
2533
+ object-fit: cover;
2534
+ }
2535
+ .ui-image-img {
2536
+ display: block;
2537
+ max-width: 100%;
2538
+ height: auto;
2539
+ }
2540
+ .ui-image--rounded .ui-image-crop { border-radius: var(--ui-radius-lg, 1rem); }
2541
+ .ui-image--rounded .ui-image-wrap { border-radius: var(--ui-radius-lg, 1rem); }
2542
+ .ui-image--pill .ui-image-crop { border-radius: 999px; }
2543
+ .ui-image--pill .ui-image-wrap { border-radius: 999px; }
2544
+ .ui-image-caption {
2545
+ margin: .5rem 0 0;
2546
+ font-size: .8rem;
2547
+ color: var(--ui-muted);
2548
+ line-height: 1.5;
2549
+ }
2550
+
2551
+ /* ─── Pullquote ──────────────────────────────────────────────────────────── */
2552
+ .ui-pullquote {
2553
+ border-left: 3px solid var(--ui-accent);
2554
+ padding: .75rem 0 .75rem 1.5rem;
2555
+ margin: 0;
2556
+ }
2557
+ .ui-pullquote blockquote { margin: 0; padding: 0; }
2558
+ .ui-pullquote-text {
2559
+ font-size: 1.15rem;
2560
+ line-height: 1.6;
2561
+ color: var(--ui-text);
2562
+ font-style: italic;
2563
+ margin: 0;
2564
+ }
2565
+ .ui-pullquote--lg .ui-pullquote-text { font-size: 1.5rem; }
2566
+ .ui-pullquote-cite {
2567
+ display: block;
2568
+ margin-top: .75rem;
2569
+ font-size: .85rem;
2570
+ color: var(--ui-muted);
2571
+ font-style: normal;
2572
+ }
2573
+
2574
+ /* ─── List ───────────────────────────────────────────────────────────────────
2575
+ Styled list component. Use instead of raw <ul>/<ol>. */
2576
+ .ui-list {
2577
+ display: flex;
2578
+ flex-direction: column;
2579
+ padding-left: 1.5em;
2580
+ color: var(--ui-text);
2581
+ }
2582
+ .ui-list--unordered { list-style-type: disc; }
2583
+ .ui-list--ordered { list-style-type: decimal; }
2584
+ .ui-list-item { line-height: 1.6; }
2585
+
2586
+ /* ─── Prose ──────────────────────────────────────────────────────────────────
2587
+ Typography wrapper for rich text: CMS output, markdown-rendered HTML,
2588
+ blog/article bodies. Styles all descendant elements without class names. */
2589
+ .ui-prose {
2590
+ color: var(--ui-text);
2591
+ line-height: 1.75;
2592
+ font-size: 1rem;
2593
+ }
2594
+ .ui-prose--sm { font-size: .875rem; }
2595
+ .ui-prose--lg { font-size: 1.125rem; }
2596
+
2597
+ .ui-prose h1,
2598
+ .ui-prose h2,
2599
+ .ui-prose h3,
2600
+ .ui-prose h4,
2601
+ .ui-prose h5,
2602
+ .ui-prose h6 {
2603
+ color: var(--ui-text);
2604
+ font-weight: 700;
2605
+ line-height: 1.3;
2606
+ margin-top: 2em;
2607
+ margin-bottom: .6em;
2608
+ }
2609
+ .ui-prose h1 { font-size: 2rem; }
2610
+ .ui-prose h2 { font-size: 1.5rem; }
2611
+ .ui-prose h3 { font-size: 1.25rem; font-weight: 600; }
2612
+ .ui-prose h4 { font-size: 1rem; font-weight: 600; }
2613
+ .ui-prose h5 { font-size: .875rem; font-weight: 600; }
2614
+ .ui-prose h6 { font-size: .875rem; font-weight: 600; color: var(--ui-muted); }
2615
+
2616
+ .ui-prose :is(h1, h2, h3, h4, h5, h6):first-child { margin-top: 0; }
2617
+
2618
+ .ui-prose p { margin-bottom: 1.25em; }
2619
+ .ui-prose p:last-child { margin-bottom: 0; }
2620
+
2621
+ .ui-prose a {
2622
+ color: var(--ui-accent);
2623
+ text-decoration: underline;
2624
+ text-underline-offset: 2px;
2625
+ }
2626
+ .ui-prose a:hover { color: var(--ui-accent-hover); }
2627
+
2628
+ .ui-prose strong { font-weight: 700; }
2629
+ .ui-prose em { font-style: italic; }
2630
+
2631
+ .ui-prose ul,
2632
+ .ui-prose ol {
2633
+ padding-left: 1.5em;
2634
+ margin-bottom: 1.25em;
2635
+ }
2636
+ .ui-prose ul { list-style-type: disc; }
2637
+ .ui-prose ol { list-style-type: decimal; }
2638
+ .ui-prose ul ul { list-style-type: circle; }
2639
+ .ui-prose li { margin-bottom: .375em; }
2640
+ .ui-prose li > ul,
2641
+ .ui-prose li > ol { margin-top: .375em; margin-bottom: .375em; }
2642
+
2643
+ .ui-prose blockquote {
2644
+ border-left: 3px solid var(--ui-border);
2645
+ padding: .5em 0 .5em 1.25em;
2646
+ margin: 1.5em 0;
2647
+ color: var(--ui-muted);
2648
+ font-style: italic;
2649
+ }
2650
+ .ui-prose blockquote p { margin-bottom: 0; }
2651
+
2652
+ .ui-prose code {
2653
+ background: var(--ui-surface-2);
2654
+ color: var(--ui-accent);
2655
+ padding: .1em .35em;
2656
+ border-radius: var(--ui-radius-sm);
2657
+ font-size: .875em;
2658
+ font-family: var(--ui-mono);
2659
+ }
2660
+ .ui-prose pre {
2661
+ background: var(--ui-surface-2);
2662
+ border: 1px solid var(--ui-border);
2663
+ border-radius: var(--ui-radius);
2664
+ padding: 1em 1.25em;
2665
+ overflow-x: auto;
2666
+ margin-bottom: 1.25em;
2667
+ font-family: var(--ui-mono);
2668
+ font-size: .875em;
2669
+ line-height: 1.7;
2670
+ }
2671
+ .ui-prose pre code {
2672
+ background: none;
2673
+ color: inherit;
2674
+ padding: 0;
2675
+ font-size: inherit;
2676
+ }
2677
+
2678
+ .ui-prose hr {
2679
+ border: none;
2680
+ border-top: 1px solid var(--ui-border);
2681
+ margin: 2em 0;
2682
+ }
2683
+
2684
+ .ui-prose img {
2685
+ max-width: 100%;
2686
+ border-radius: var(--ui-radius);
2687
+ height: auto;
2688
+ }
2689
+ .ui-prose figure { margin: 1.5em 0; }
2690
+ .ui-prose figcaption {
2691
+ font-size: .875em;
2692
+ color: var(--ui-muted);
2693
+ margin-top: .5em;
2694
+ text-align: center;
2695
+ }
2696
+
2697
+ .ui-prose table {
2698
+ width: 100%;
2699
+ border-collapse: collapse;
2700
+ margin-bottom: 1.25em;
2701
+ font-size: .9375em;
2702
+ }
2703
+ .ui-prose th {
2704
+ text-align: left;
2705
+ padding: .5em .75em;
2706
+ border-bottom: 2px solid var(--ui-border);
2707
+ font-weight: 600;
2708
+ color: var(--ui-text);
2709
+ }
2710
+ .ui-prose td {
2711
+ padding: .5em .75em;
2712
+ border-bottom: 1px solid var(--ui-border);
2713
+ color: var(--ui-text);
2714
+ }
2715
+
2716
+ /* ─── Light theme ────────────────────────────────────────────────────────────
2717
+ Apply to any ancestor element: <body data-theme="light"> or .ui-theme-light
2718
+ All --ui-* tokens are overridden; component markup stays identical. */
2719
+ [data-theme="light"],
2720
+ .ui-theme-light {
2721
+ --ui-bg: #ffffff;
2722
+ --ui-surface: #f8f8fc;
2723
+ --ui-surface-2: #f0f0f8;
2724
+ --ui-border: #d8d8e8;
2725
+ --ui-text: #111118;
2726
+ --ui-muted: #60607a;
2727
+ --ui-accent: #6b5ce7;
2728
+ --ui-accent-hover: #5847d6;
2729
+ --ui-accent-dim: rgba(107, 92, 231, .12);
2730
+ --ui-green: #166534;
2731
+ --ui-green-dim: rgba(22, 163, 74, .12);
2732
+ --ui-red: #991b1b;
2733
+ --ui-red-dim: rgba(220, 38, 38, .12);
2734
+ --ui-yellow: #92400e;
2735
+ --ui-yellow-dim: rgba(217, 119, 6, .12);
2736
+ --ui-blue: #1e40af;
2737
+ --ui-blue-dim: rgba( 30, 64, 175, .12);
2738
+ --ui-nav-sticky-bg: rgba(255, 255, 255, .85);
2739
+ }