@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,2740 @@
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
+ opacity: .7;
1639
+ }
1640
+
1641
+ .ui-code-window-pre {
1642
+ margin: 0;
1643
+ padding: 1.25rem 1.5rem;
1644
+ overflow-x: auto;
1645
+ font-family: var(--ui-mono);
1646
+ font-size: .85rem;
1647
+ line-height: 1.7;
1648
+ color: var(--ui-text);
1649
+ tab-size: 2;
1650
+ }
1651
+
1652
+ .ui-code-window-code { font-family: inherit; }
1653
+
1654
+ /* ─── Footer ─────────────────────────────────────────────────────────────────
1655
+ Site footer — logo, nav links, legal text. Stacks on mobile. */
1656
+ .ui-footer {
1657
+ padding: 3rem 1.5rem;
1658
+ border-top: 1px solid var(--ui-border);
1659
+ }
1660
+
1661
+ .ui-footer-inner {
1662
+ max-width: 1200px;
1663
+ margin: 0 auto;
1664
+ display: flex;
1665
+ align-items: center;
1666
+ gap: 2rem;
1667
+ flex-wrap: wrap;
1668
+ }
1669
+
1670
+ .ui-footer-logo {
1671
+ font-size: 1rem;
1672
+ font-weight: 600;
1673
+ color: var(--ui-text);
1674
+ text-decoration: none;
1675
+ flex-shrink: 0;
1676
+ transition: color .15s;
1677
+ }
1678
+
1679
+ .ui-footer-logo:hover { color: var(--ui-accent); }
1680
+ .ui-footer-logo:focus-visible {
1681
+ outline: 2px solid var(--ui-accent);
1682
+ outline-offset: 2px;
1683
+ border-radius: 2px;
1684
+ }
1685
+
1686
+ .ui-footer-links {
1687
+ display: flex;
1688
+ gap: 1.5rem;
1689
+ flex-wrap: wrap;
1690
+ flex: 1;
1691
+ }
1692
+
1693
+ .ui-footer-link {
1694
+ font-size: .875rem;
1695
+ color: var(--ui-muted);
1696
+ text-decoration: none;
1697
+ transition: color .15s;
1698
+ }
1699
+
1700
+ .ui-footer-link:hover { color: var(--ui-text); }
1701
+ .ui-footer-link:focus-visible {
1702
+ outline: 2px solid var(--ui-accent);
1703
+ outline-offset: 2px;
1704
+ border-radius: 2px;
1705
+ }
1706
+
1707
+ .ui-footer-legal {
1708
+ font-size: .8rem;
1709
+ color: var(--ui-muted);
1710
+ margin: 0 0 0 auto;
1711
+ }
1712
+
1713
+ @media (max-width: 640px) {
1714
+ .ui-footer-inner { flex-direction: column; align-items: flex-start; gap: 1.25rem; }
1715
+ .ui-footer-legal { margin-left: 0; }
1716
+ .ui-footer-links { gap: 1rem; }
1717
+ }
1718
+
1719
+ /* ─── Icon wrapper ───────────────────────────────────────────────────────────
1720
+ Wraps any icon in a tinted background shape.
1721
+ bg: 'circle' → border-radius: 50% | bg: 'square' → var(--ui-radius) */
1722
+
1723
+ .ui-icon-wrap {
1724
+ display: inline-flex;
1725
+ align-items: center;
1726
+ justify-content: center;
1727
+ padding: .55em;
1728
+ flex-shrink: 0;
1729
+ line-height: 1;
1730
+ }
1731
+
1732
+ .ui-icon-wrap--circle { border-radius: 50%; }
1733
+ .ui-icon-wrap--square { border-radius: var(--ui-radius); }
1734
+
1735
+ .ui-icon-wrap--accent { background: var(--ui-accent-dim); color: var(--ui-accent); }
1736
+ .ui-icon-wrap--success { background: var(--ui-green-dim); color: var(--ui-green); }
1737
+ .ui-icon-wrap--warning { background: var(--ui-yellow-dim); color: var(--ui-yellow); }
1738
+ .ui-icon-wrap--error { background: var(--ui-red-dim); color: var(--ui-red); }
1739
+ .ui-icon-wrap--muted { background: var(--ui-surface-2); color: var(--ui-muted); }
1740
+
1741
+ /* ─── Timeline ───────────────────────────────────────────────────────────────
1742
+ Shared rules (dot, label, body) apply to both orientations. */
1743
+
1744
+ /* Shared base */
1745
+ .ui-timeline {
1746
+ list-style: none;
1747
+ padding: 0;
1748
+ margin: 0;
1749
+ }
1750
+
1751
+ .ui-timeline-dot {
1752
+ width: 10px;
1753
+ height: 10px;
1754
+ border-radius: 50%;
1755
+ flex-shrink: 0;
1756
+ display: flex;
1757
+ align-items: center;
1758
+ justify-content: center;
1759
+ position: relative;
1760
+ z-index: 1;
1761
+ }
1762
+
1763
+ /* Icon dot — larger, with dim background */
1764
+ .ui-timeline-dot--icon {
1765
+ width: 2rem;
1766
+ height: 2rem;
1767
+ border-radius: 50%;
1768
+ font-size: 1rem;
1769
+ }
1770
+
1771
+ /* Dot colour variants */
1772
+ .ui-timeline-dot--accent { background: var(--ui-accent); }
1773
+ .ui-timeline-dot--success { background: var(--ui-green); }
1774
+ .ui-timeline-dot--warning { background: var(--ui-yellow); }
1775
+ .ui-timeline-dot--error { background: var(--ui-red); }
1776
+ .ui-timeline-dot--muted { background: var(--ui-surface-2); outline: 2px solid var(--ui-border); outline-offset: 0; }
1777
+
1778
+ /* Icon dot: dim background + coloured icon */
1779
+ .ui-timeline-dot--icon.ui-timeline-dot--accent { background: var(--ui-accent-dim); color: var(--ui-accent); }
1780
+ .ui-timeline-dot--icon.ui-timeline-dot--success { background: var(--ui-green-dim); color: var(--ui-green); }
1781
+ .ui-timeline-dot--icon.ui-timeline-dot--warning { background: var(--ui-yellow-dim); color: var(--ui-yellow); }
1782
+ .ui-timeline-dot--icon.ui-timeline-dot--error { background: var(--ui-red-dim); color: var(--ui-red); }
1783
+ .ui-timeline-dot--icon.ui-timeline-dot--muted { background: var(--ui-surface-2); color: var(--ui-muted); }
1784
+
1785
+ .ui-timeline-label {
1786
+ display: block;
1787
+ font-size: .72rem;
1788
+ font-weight: 600;
1789
+ color: var(--ui-muted);
1790
+ letter-spacing: .05em;
1791
+ text-transform: uppercase;
1792
+ margin-bottom: .35rem;
1793
+ }
1794
+
1795
+ /* ── Vertical ── */
1796
+ .ui-timeline--vertical {
1797
+ display: flex;
1798
+ flex-direction: column;
1799
+ }
1800
+
1801
+ .ui-timeline--vertical .ui-timeline-item {
1802
+ display: flex;
1803
+ gap: 1rem;
1804
+ }
1805
+
1806
+ .ui-timeline--vertical .ui-timeline-side {
1807
+ display: flex;
1808
+ flex-direction: column;
1809
+ align-items: center;
1810
+ flex-shrink: 0;
1811
+ }
1812
+
1813
+ /* Connecting line segments run above and below the dot */
1814
+ .ui-timeline--vertical .ui-timeline-connector {
1815
+ width: 2px;
1816
+ background: var(--ui-border);
1817
+ flex: 1;
1818
+ min-height: .75rem;
1819
+ }
1820
+
1821
+ /* No line above the first item or below the last */
1822
+ .ui-timeline--vertical .ui-timeline-item:first-child .ui-timeline-connector--before,
1823
+ .ui-timeline--vertical .ui-timeline-item:last-child .ui-timeline-connector--after {
1824
+ visibility: hidden;
1825
+ }
1826
+
1827
+ .ui-timeline--vertical .ui-timeline-main {
1828
+ flex: 1;
1829
+ padding-bottom: 1.75rem;
1830
+ }
1831
+
1832
+ .ui-timeline--vertical .ui-timeline-item:last-child .ui-timeline-main {
1833
+ padding-bottom: 0;
1834
+ }
1835
+
1836
+ /* ── Horizontal ── */
1837
+ .ui-timeline--horizontal {
1838
+ display: flex;
1839
+ align-items: flex-start;
1840
+ overflow-x: auto;
1841
+ }
1842
+
1843
+ .ui-timeline--horizontal .ui-timeline-item {
1844
+ flex: 1;
1845
+ min-width: 0;
1846
+ display: flex;
1847
+ flex-direction: column;
1848
+ align-items: center;
1849
+ }
1850
+
1851
+ .ui-timeline--horizontal .ui-timeline-side {
1852
+ display: flex;
1853
+ align-items: center;
1854
+ width: 100%;
1855
+ margin-bottom: .75rem;
1856
+ }
1857
+
1858
+ .ui-timeline--horizontal .ui-timeline-connector {
1859
+ flex: 1;
1860
+ height: 2px;
1861
+ background: var(--ui-border);
1862
+ }
1863
+
1864
+ /* No line before the first item or after the last */
1865
+ .ui-timeline--horizontal .ui-timeline-item:first-child .ui-timeline-connector--before,
1866
+ .ui-timeline--horizontal .ui-timeline-item:last-child .ui-timeline-connector--after {
1867
+ visibility: hidden;
1868
+ }
1869
+
1870
+ .ui-timeline--horizontal .ui-timeline-main {
1871
+ text-align: center;
1872
+ padding: 0 .5rem;
1873
+ width: 100%;
1874
+ }
1875
+
1876
+ /* ─── Switch ─────────────────────────────────────────────────────────────── */
1877
+ .ui-switch-input {
1878
+ position: absolute;
1879
+ width: 1px;
1880
+ height: 1px;
1881
+ padding: 0;
1882
+ margin: -1px;
1883
+ overflow: hidden;
1884
+ clip: rect(0,0,0,0);
1885
+ border: 0;
1886
+ }
1887
+
1888
+ .ui-switch-label {
1889
+ display: inline-flex;
1890
+ align-items: center;
1891
+ gap: .65rem;
1892
+ cursor: pointer;
1893
+ user-select: none;
1894
+ }
1895
+
1896
+ .ui-switch-label--disabled {
1897
+ opacity: .5;
1898
+ cursor: not-allowed;
1899
+ }
1900
+
1901
+ .ui-switch-track {
1902
+ position: relative;
1903
+ display: inline-flex;
1904
+ align-items: center;
1905
+ width: 3rem;
1906
+ height: 1.75rem;
1907
+ border-radius: 999px;
1908
+ background: var(--ui-border);
1909
+ transition: background .2s;
1910
+ flex-shrink: 0;
1911
+ }
1912
+
1913
+ .ui-switch-thumb {
1914
+ position: absolute;
1915
+ left: .2rem;
1916
+ width: 1.35rem;
1917
+ height: 1.35rem;
1918
+ border-radius: 50%;
1919
+ background: #fff;
1920
+ box-shadow: 0 1px 3px rgba(0,0,0,.3);
1921
+ transition: transform .2s cubic-bezier(.34,1.56,.64,1), background .2s;
1922
+ }
1923
+
1924
+ .ui-switch-input:checked + .ui-switch-track {
1925
+ background: var(--ui-accent);
1926
+ }
1927
+
1928
+ .ui-switch-input:checked + .ui-switch-track .ui-switch-thumb {
1929
+ transform: translateX(1.25rem);
1930
+ }
1931
+
1932
+ .ui-switch-input:focus-visible + .ui-switch-track {
1933
+ outline: 2px solid var(--ui-accent);
1934
+ outline-offset: 2px;
1935
+ }
1936
+
1937
+ .ui-switch-text {
1938
+ font-family: var(--ui-font);
1939
+ font-size: .9rem;
1940
+ color: var(--ui-text);
1941
+ line-height: 1.4;
1942
+ }
1943
+
1944
+ /* ─── Radio ──────────────────────────────────────────────────────────────── */
1945
+ .ui-radio-group {
1946
+ border: 1px solid var(--ui-border);
1947
+ border-radius: var(--ui-radius);
1948
+ padding: 0;
1949
+ margin: 0;
1950
+ }
1951
+
1952
+ .ui-radio-group-body {
1953
+ display: flex;
1954
+ flex-direction: column;
1955
+ gap: var(--radio-gap, .75rem);
1956
+ padding: 1.25rem;
1957
+ }
1958
+
1959
+ /* ─── Checkbox ───────────────────────────────────────────────────────────── */
1960
+ .ui-checkbox {
1961
+ display: inline-flex;
1962
+ align-items: flex-start;
1963
+ gap: .6rem;
1964
+ cursor: pointer;
1965
+ user-select: none;
1966
+ }
1967
+
1968
+ .ui-checkbox--disabled {
1969
+ opacity: .5;
1970
+ cursor: not-allowed;
1971
+ }
1972
+
1973
+ .ui-checkbox-input {
1974
+ position: absolute;
1975
+ width: 1px;
1976
+ height: 1px;
1977
+ padding: 0;
1978
+ margin: -1px;
1979
+ overflow: hidden;
1980
+ clip: rect(0,0,0,0);
1981
+ border: 0;
1982
+ }
1983
+
1984
+ .ui-checkbox-box {
1985
+ position: relative;
1986
+ display: inline-flex;
1987
+ align-items: center;
1988
+ justify-content: center;
1989
+ width: 1.125rem;
1990
+ height: 1.125rem;
1991
+ border-radius: .25rem;
1992
+ border: 2px solid var(--ui-border);
1993
+ background: var(--ui-surface);
1994
+ flex-shrink: 0;
1995
+ margin-top: .125rem;
1996
+ transition: border-color .15s, background .15s;
1997
+ }
1998
+
1999
+ .ui-checkbox-box::after {
2000
+ content: '';
2001
+ position: absolute;
2002
+ width: .3rem;
2003
+ height: .55rem;
2004
+ border-right: 2px solid var(--ui-bg);
2005
+ border-bottom: 2px solid var(--ui-bg);
2006
+ transform: rotate(45deg) scale(0);
2007
+ transform-origin: center;
2008
+ margin-top: -.1rem;
2009
+ opacity: 0;
2010
+ transition: opacity .1s, transform .15s cubic-bezier(.34, 1.56, .64, 1);
2011
+ }
2012
+
2013
+ .ui-checkbox-input:checked + .ui-checkbox-box {
2014
+ border-color: var(--ui-accent);
2015
+ background: var(--ui-accent);
2016
+ }
2017
+
2018
+ .ui-checkbox-input:checked + .ui-checkbox-box::after {
2019
+ opacity: 1;
2020
+ transform: rotate(45deg) scale(1);
2021
+ }
2022
+
2023
+ .ui-checkbox-input:focus-visible + .ui-checkbox-box {
2024
+ outline: 2px solid var(--ui-accent);
2025
+ outline-offset: 2px;
2026
+ }
2027
+
2028
+ .ui-checkbox--error .ui-checkbox-box {
2029
+ border-color: var(--ui-red);
2030
+ }
2031
+
2032
+ .ui-checkbox-label {
2033
+ font-family: var(--ui-font);
2034
+ font-size: .9rem;
2035
+ color: var(--ui-text);
2036
+ line-height: 1.4;
2037
+ }
2038
+
2039
+ /* ─── Radio ──────────────────────────────────────────────────────────────── */
2040
+ .ui-radio {
2041
+ display: inline-flex;
2042
+ align-items: center;
2043
+ gap: .6rem;
2044
+ cursor: pointer;
2045
+ user-select: none;
2046
+ }
2047
+
2048
+ .ui-radio--disabled {
2049
+ opacity: .5;
2050
+ cursor: not-allowed;
2051
+ }
2052
+
2053
+ .ui-radio-input {
2054
+ position: absolute;
2055
+ width: 1px;
2056
+ height: 1px;
2057
+ padding: 0;
2058
+ margin: -1px;
2059
+ overflow: hidden;
2060
+ clip: rect(0,0,0,0);
2061
+ border: 0;
2062
+ }
2063
+
2064
+ .ui-radio-dot {
2065
+ position: relative;
2066
+ display: inline-flex;
2067
+ align-items: center;
2068
+ justify-content: center;
2069
+ width: 1.25rem;
2070
+ height: 1.25rem;
2071
+ border-radius: 50%;
2072
+ border: 2px solid var(--ui-border);
2073
+ background: var(--ui-surface);
2074
+ flex-shrink: 0;
2075
+ transition: border-color .15s, background .15s;
2076
+ }
2077
+
2078
+ .ui-radio-dot::after {
2079
+ content: '';
2080
+ width: .5rem;
2081
+ height: .5rem;
2082
+ border-radius: 50%;
2083
+ background: var(--ui-bg);
2084
+ opacity: 0;
2085
+ transform: scale(0);
2086
+ transition: opacity .15s, transform .2s cubic-bezier(.34,1.56,.64,1);
2087
+ }
2088
+
2089
+ .ui-radio-input:checked + .ui-radio-dot {
2090
+ border-color: var(--ui-accent);
2091
+ background: var(--ui-accent);
2092
+ }
2093
+
2094
+ .ui-radio-input:checked + .ui-radio-dot::after {
2095
+ opacity: 1;
2096
+ transform: scale(1);
2097
+ }
2098
+
2099
+ .ui-radio-input:focus-visible + .ui-radio-dot {
2100
+ outline: 2px solid var(--ui-accent);
2101
+ outline-offset: 2px;
2102
+ }
2103
+
2104
+ .ui-radio-label {
2105
+ font-family: var(--ui-font);
2106
+ font-size: .9rem;
2107
+ color: var(--ui-text);
2108
+ line-height: 1.4;
2109
+ }
2110
+
2111
+ .ui-radio-group--error .ui-radio-dot {
2112
+ border-color: var(--ui-red);
2113
+ }
2114
+
2115
+ /* ─── Rating ─────────────────────────────────────────────────────────────── */
2116
+ .ui-rating {
2117
+ display: inline-flex;
2118
+ align-items: center;
2119
+ gap: .1em;
2120
+ font-size: var(--rating-size, 1.5rem);
2121
+ color: var(--ui-muted);
2122
+ line-height: 1;
2123
+ }
2124
+
2125
+ /* Read-only stars */
2126
+ .ui-rating-star--filled,
2127
+ .ui-rating-star--half { color: var(--ui-yellow); }
2128
+
2129
+ /* Interactive stars container — row-reverse makes high→low DOM order appear as 1…max */
2130
+ .ui-rating-stars {
2131
+ display: inline-flex;
2132
+ flex-direction: row-reverse;
2133
+ gap: .1em;
2134
+ font-size: var(--rating-size, 1.5rem);
2135
+ line-height: 1;
2136
+ }
2137
+
2138
+ /* Each input is nested inside its label — hidden but in the tab order */
2139
+ .ui-rating-input {
2140
+ position: absolute;
2141
+ width: 1px;
2142
+ height: 1px;
2143
+ padding: 0;
2144
+ margin: -1px;
2145
+ overflow: hidden;
2146
+ clip: rect(0,0,0,0);
2147
+ border: 0;
2148
+ }
2149
+
2150
+ /* Star labels — only flex items, no invisible elements between them */
2151
+ .ui-rating-stars .ui-rating-star {
2152
+ color: var(--ui-muted);
2153
+ cursor: pointer;
2154
+ transition: color .1s;
2155
+ user-select: none;
2156
+ }
2157
+
2158
+ /* Checked: colour the label containing the checked input + all DOM-subsequent
2159
+ labels (= visually lower-numbered stars due to row-reverse) */
2160
+ .ui-rating-stars .ui-rating-star:has(input:checked),
2161
+ .ui-rating-stars .ui-rating-star:has(input:checked) ~ .ui-rating-star {
2162
+ color: var(--ui-yellow);
2163
+ }
2164
+
2165
+ /* Hover: reset everything, then re-highlight up to the hovered star */
2166
+ .ui-rating-stars:hover .ui-rating-star { color: var(--ui-muted); }
2167
+ .ui-rating-stars .ui-rating-star:hover,
2168
+ .ui-rating-stars .ui-rating-star:hover ~ .ui-rating-star { color: var(--ui-yellow); }
2169
+
2170
+ /* Focus ring on the label when its input is keyboard-focused */
2171
+ .ui-rating-star:focus-within {
2172
+ outline: 2px solid var(--ui-accent);
2173
+ outline-offset: 2px;
2174
+ border-radius: 2px;
2175
+ }
2176
+
2177
+ /* Disabled */
2178
+ fieldset[disabled] .ui-rating-star {
2179
+ cursor: not-allowed;
2180
+ opacity: .5;
2181
+ }
2182
+ fieldset[disabled] .ui-rating-stars:hover .ui-rating-star { color: revert; }
2183
+ fieldset[disabled] .ui-rating-stars .ui-rating-star:hover,
2184
+ fieldset[disabled] .ui-rating-stars .ui-rating-star:hover ~ .ui-rating-star { color: revert; }
2185
+
2186
+ /* ─── Spinner ────────────────────────────────────────────────────────────── */
2187
+ @keyframes ui-spin {
2188
+ to { transform: rotate(360deg); }
2189
+ }
2190
+
2191
+ .ui-spinner {
2192
+ display: inline-block;
2193
+ width: var(--spinner-size, 1.5rem);
2194
+ height: var(--spinner-size, 1.5rem);
2195
+ border: 2px solid color-mix(in srgb, var(--spinner-color, var(--ui-accent)) 20%, transparent);
2196
+ border-top-color: var(--spinner-color, var(--ui-accent));
2197
+ border-radius: 50%;
2198
+ animation: ui-spin .7s linear infinite;
2199
+ flex-shrink: 0;
2200
+ }
2201
+
2202
+ /* ─── Progress ───────────────────────────────────────────────────────────── */
2203
+ .ui-progress { width: 100%; }
2204
+
2205
+ .ui-progress-header {
2206
+ display: flex;
2207
+ justify-content: space-between;
2208
+ align-items: baseline;
2209
+ margin-bottom: .4rem;
2210
+ gap: 1rem;
2211
+ }
2212
+
2213
+ .ui-progress-label {
2214
+ font-size: .8rem;
2215
+ font-weight: 600;
2216
+ color: var(--ui-text);
2217
+ }
2218
+
2219
+ .ui-progress-value {
2220
+ font-size: .8rem;
2221
+ color: var(--ui-muted);
2222
+ font-variant-numeric: tabular-nums;
2223
+ }
2224
+
2225
+ .ui-progress-track {
2226
+ width: 100%;
2227
+ height: var(--progress-height, .5rem);
2228
+ background: var(--ui-border);
2229
+ border-radius: 999px;
2230
+ overflow: hidden;
2231
+ }
2232
+
2233
+ .ui-progress-fill {
2234
+ height: 100%;
2235
+ border-radius: 999px;
2236
+ transition: width .3s ease;
2237
+ }
2238
+
2239
+ /* Variants */
2240
+ .ui-progress--accent .ui-progress-fill { background: var(--ui-accent); }
2241
+ .ui-progress--success .ui-progress-fill { background: var(--ui-green); }
2242
+ .ui-progress--warning .ui-progress-fill { background: var(--ui-yellow); }
2243
+ .ui-progress--error .ui-progress-fill { background: var(--ui-red); }
2244
+
2245
+ /* Indeterminate — animates a fill bar back and forth */
2246
+ @keyframes ui-progress-indeterminate {
2247
+ 0% { transform: translateX(-100%) scaleX(.4); }
2248
+ 50% { transform: translateX( 60%) scaleX(.6); }
2249
+ 100% { transform: translateX( 200%) scaleX(.4); }
2250
+ }
2251
+
2252
+ .ui-progress--indeterminate .ui-progress-fill {
2253
+ width: 50%;
2254
+ animation: ui-progress-indeterminate 1.4s ease infinite;
2255
+ transform-origin: left center;
2256
+ }
2257
+
2258
+ /* ─── Slider ─────────────────────────────────────────────────────────────── */
2259
+ .ui-slider {
2260
+ width: 100%;
2261
+ height: var(--ui-touch-min);
2262
+ -webkit-appearance: none;
2263
+ appearance: none;
2264
+ background: transparent;
2265
+ cursor: pointer;
2266
+ padding: 0;
2267
+ margin: 0;
2268
+ }
2269
+ .ui-slider::-webkit-slider-runnable-track {
2270
+ height: 4px;
2271
+ border-radius: 999px;
2272
+ background: linear-gradient(
2273
+ to right,
2274
+ var(--ui-accent) 0% var(--slider-fill, 50%),
2275
+ var(--ui-border) var(--slider-fill, 50%) 100%
2276
+ );
2277
+ }
2278
+ .ui-slider::-moz-range-track {
2279
+ height: 4px;
2280
+ border-radius: 999px;
2281
+ background: var(--ui-border);
2282
+ }
2283
+ .ui-slider::-moz-range-progress {
2284
+ height: 4px;
2285
+ border-radius: 999px;
2286
+ background: var(--ui-accent);
2287
+ }
2288
+ .ui-slider::-webkit-slider-thumb {
2289
+ -webkit-appearance: none;
2290
+ width: 20px;
2291
+ height: 20px;
2292
+ border-radius: 50%;
2293
+ background: var(--ui-accent);
2294
+ margin-top: -8px;
2295
+ box-shadow: 0 1px 4px rgba(0,0,0,.3);
2296
+ transition: transform .15s;
2297
+ }
2298
+ .ui-slider::-moz-range-thumb {
2299
+ width: 20px;
2300
+ height: 20px;
2301
+ border-radius: 50%;
2302
+ background: var(--ui-accent);
2303
+ border: none;
2304
+ box-shadow: 0 1px 4px rgba(0,0,0,.3);
2305
+ }
2306
+ .ui-slider::-webkit-slider-thumb:hover { transform: scale(1.15); }
2307
+ .ui-slider:focus-visible { outline: none; }
2308
+ .ui-slider:focus-visible::-webkit-slider-thumb {
2309
+ outline: 2px solid var(--ui-accent);
2310
+ outline-offset: 3px;
2311
+ }
2312
+ .ui-slider:disabled { opacity: .5; cursor: not-allowed; }
2313
+
2314
+ .ui-label--row {
2315
+ display: flex;
2316
+ justify-content: space-between;
2317
+ align-items: baseline;
2318
+ }
2319
+ .ui-slider-output {
2320
+ font-size: .8125rem;
2321
+ color: var(--ui-muted);
2322
+ font-variant-numeric: tabular-nums;
2323
+ min-width: 3ch;
2324
+ text-align: right;
2325
+ }
2326
+
2327
+ /* ─── File Upload ────────────────────────────────────────────────────────── */
2328
+
2329
+ .ui-upload {
2330
+ position: relative;
2331
+ display: flex;
2332
+ align-items: center;
2333
+ justify-content: center;
2334
+ padding: 2rem 1.5rem;
2335
+ background: var(--ui-surface);
2336
+ border: 1.5px dashed var(--ui-border);
2337
+ border-radius: var(--ui-radius);
2338
+ cursor: pointer;
2339
+ transition: border-color .15s, background .15s;
2340
+ outline: none;
2341
+ user-select: none;
2342
+ }
2343
+
2344
+ .ui-upload:hover:not(.ui-upload--disabled),
2345
+ .ui-upload:focus-visible {
2346
+ border-color: var(--ui-accent);
2347
+ background: color-mix(in srgb, var(--ui-accent) 5%, var(--ui-surface));
2348
+ }
2349
+
2350
+ .ui-upload--active {
2351
+ border-color: var(--ui-accent);
2352
+ background: color-mix(in srgb, var(--ui-accent) 8%, var(--ui-surface));
2353
+ }
2354
+
2355
+ .ui-upload--error { border-color: var(--ui-red); }
2356
+ .ui-upload--selected { border-color: var(--ui-accent); }
2357
+ .ui-upload--selected .ui-upload-text { color: var(--ui-text); font-weight: 500; }
2358
+
2359
+ .ui-upload--disabled {
2360
+ opacity: .5;
2361
+ cursor: not-allowed;
2362
+ }
2363
+
2364
+ .ui-upload-body {
2365
+ display: flex;
2366
+ flex-direction: column;
2367
+ align-items: center;
2368
+ gap: .6rem;
2369
+ pointer-events: none;
2370
+ }
2371
+
2372
+ .ui-upload-icon { color: var(--ui-muted); display: block; }
2373
+
2374
+ .ui-upload:hover:not(.ui-upload--disabled) .ui-upload-icon,
2375
+ .ui-upload--active .ui-upload-icon { color: var(--ui-accent); }
2376
+
2377
+ .ui-upload-text {
2378
+ font-size: .875rem;
2379
+ color: var(--ui-muted);
2380
+ text-align: center;
2381
+ line-height: 1.5;
2382
+ }
2383
+
2384
+ .ui-upload-browse {
2385
+ color: var(--ui-accent);
2386
+ text-decoration: underline;
2387
+ text-underline-offset: 2px;
2388
+ }
2389
+
2390
+ .ui-upload-input {
2391
+ display: none;
2392
+ }
2393
+
2394
+ /* ─── Segmented ─────────────────────────────────────────────────────────── */
2395
+ .ui-segmented {
2396
+ display: inline-flex;
2397
+ background: var(--ui-surface-2);
2398
+ border-radius: var(--ui-radius);
2399
+ padding: 3px;
2400
+ gap: 2px;
2401
+ }
2402
+ .ui-segmented-input {
2403
+ position: absolute;
2404
+ width: 1px; height: 1px;
2405
+ padding: 0; margin: -1px;
2406
+ overflow: hidden; clip: rect(0,0,0,0); border: 0;
2407
+ }
2408
+ .ui-segmented-label {
2409
+ display: inline-flex;
2410
+ align-items: center;
2411
+ padding: .4rem .9rem;
2412
+ border-radius: calc(var(--ui-radius) - 2px);
2413
+ font-size: .85rem;
2414
+ font-weight: 500;
2415
+ color: var(--ui-muted);
2416
+ cursor: pointer;
2417
+ user-select: none;
2418
+ white-space: nowrap;
2419
+ transition: background .15s, color .15s, box-shadow .15s;
2420
+ }
2421
+ .ui-segmented--sm .ui-segmented-label { font-size: .75rem; padding: .25rem .65rem; }
2422
+ .ui-segmented--lg .ui-segmented-label { font-size: .95rem; padding: .55rem 1.1rem; }
2423
+ .ui-segmented-input:checked + .ui-segmented-label {
2424
+ background: var(--ui-surface);
2425
+ color: var(--ui-text);
2426
+ box-shadow: 0 1px 3px rgba(0,0,0,.25);
2427
+ }
2428
+ .ui-segmented-input:focus-visible + .ui-segmented-label {
2429
+ outline: 2px solid var(--ui-accent);
2430
+ outline-offset: 1px;
2431
+ }
2432
+
2433
+ /* ─── Breadcrumbs ────────────────────────────────────────────────────────── */
2434
+ .ui-breadcrumbs-list {
2435
+ display: flex;
2436
+ flex-wrap: wrap;
2437
+ align-items: center;
2438
+ gap: .25rem;
2439
+ list-style: none;
2440
+ padding: 0;
2441
+ margin: 0;
2442
+ font-size: .85rem;
2443
+ }
2444
+ .ui-breadcrumbs-item {
2445
+ display: flex;
2446
+ align-items: center;
2447
+ gap: .25rem;
2448
+ }
2449
+ .ui-breadcrumbs-link {
2450
+ color: var(--ui-muted);
2451
+ text-decoration: none;
2452
+ transition: color .15s;
2453
+ }
2454
+ .ui-breadcrumbs-link:hover { color: var(--ui-text); }
2455
+ .ui-breadcrumbs-current { color: var(--ui-text); }
2456
+ .ui-breadcrumbs-sep { color: var(--ui-border); user-select: none; }
2457
+
2458
+ /* ─── Stepper ────────────────────────────────────────────────────────────── */
2459
+ .ui-stepper {
2460
+ display: flex;
2461
+ align-items: flex-start;
2462
+ width: 100%;
2463
+ }
2464
+ .ui-stepper-item {
2465
+ flex: 1;
2466
+ display: flex;
2467
+ flex-direction: column;
2468
+ align-items: center;
2469
+ position: relative;
2470
+ }
2471
+ .ui-stepper-item:not(:last-child)::after {
2472
+ content: '';
2473
+ position: absolute;
2474
+ top: 13px;
2475
+ left: 50%;
2476
+ width: 100%;
2477
+ height: 2px;
2478
+ background: var(--ui-border);
2479
+ }
2480
+ .ui-stepper-item--complete:not(:last-child)::after { background: var(--ui-accent); }
2481
+ .ui-stepper-dot {
2482
+ position: relative;
2483
+ z-index: 1;
2484
+ width: 28px;
2485
+ height: 28px;
2486
+ border-radius: 50%;
2487
+ display: flex;
2488
+ align-items: center;
2489
+ justify-content: center;
2490
+ font-size: .75rem;
2491
+ font-weight: 700;
2492
+ background: var(--ui-surface-2);
2493
+ border: 2px solid var(--ui-border);
2494
+ color: var(--ui-muted);
2495
+ transition: background .2s, border-color .2s, color .2s;
2496
+ }
2497
+ .ui-stepper-item--complete .ui-stepper-dot {
2498
+ background: var(--ui-accent);
2499
+ border-color: var(--ui-accent);
2500
+ color: var(--ui-bg);
2501
+ }
2502
+ .ui-stepper-item--active .ui-stepper-dot {
2503
+ border-color: var(--ui-accent);
2504
+ color: var(--ui-accent);
2505
+ }
2506
+ .ui-stepper-label {
2507
+ margin-top: .5rem;
2508
+ font-size: .72rem;
2509
+ color: var(--ui-muted);
2510
+ text-align: center;
2511
+ line-height: 1.3;
2512
+ padding: 0 .25rem;
2513
+ }
2514
+ .ui-stepper-item--active .ui-stepper-label { color: var(--ui-text); font-weight: 600; }
2515
+ .ui-stepper-item--complete .ui-stepper-label { color: var(--ui-muted); }
2516
+
2517
+ /* ─── Image ──────────────────────────────────────────────────────────────── */
2518
+ .ui-image {
2519
+ display: block;
2520
+ }
2521
+ .ui-image-crop {
2522
+ overflow: hidden;
2523
+ border-radius: var(--ui-radius);
2524
+ }
2525
+ .ui-image-wrap {
2526
+ display: block;
2527
+ overflow: hidden;
2528
+ border-radius: var(--ui-radius);
2529
+ }
2530
+ .ui-image-img--cover {
2531
+ display: block;
2532
+ width: 100%;
2533
+ height: auto;
2534
+ object-fit: cover;
2535
+ }
2536
+ .ui-image-img {
2537
+ display: block;
2538
+ max-width: 100%;
2539
+ height: auto;
2540
+ }
2541
+ .ui-image--rounded .ui-image-crop { border-radius: var(--ui-radius-lg, 1rem); }
2542
+ .ui-image--rounded .ui-image-wrap { border-radius: var(--ui-radius-lg, 1rem); }
2543
+ .ui-image--pill .ui-image-crop { border-radius: 999px; }
2544
+ .ui-image--pill .ui-image-wrap { border-radius: 999px; }
2545
+ .ui-image-caption {
2546
+ margin: .5rem 0 0;
2547
+ font-size: .8rem;
2548
+ color: var(--ui-muted);
2549
+ line-height: 1.5;
2550
+ }
2551
+
2552
+ /* ─── Pullquote ──────────────────────────────────────────────────────────── */
2553
+ .ui-pullquote {
2554
+ border-left: 3px solid var(--ui-accent);
2555
+ padding: .75rem 0 .75rem 1.5rem;
2556
+ margin: 0;
2557
+ }
2558
+ .ui-pullquote blockquote { margin: 0; padding: 0; }
2559
+ .ui-pullquote-text {
2560
+ font-size: 1.15rem;
2561
+ line-height: 1.6;
2562
+ color: var(--ui-text);
2563
+ font-style: italic;
2564
+ margin: 0;
2565
+ }
2566
+ .ui-pullquote--lg .ui-pullquote-text { font-size: 1.5rem; }
2567
+ .ui-pullquote-cite {
2568
+ display: block;
2569
+ margin-top: .75rem;
2570
+ font-size: .85rem;
2571
+ color: var(--ui-muted);
2572
+ font-style: normal;
2573
+ }
2574
+
2575
+ /* ─── List ───────────────────────────────────────────────────────────────────
2576
+ Styled list component. Use instead of raw <ul>/<ol>. */
2577
+ .ui-list {
2578
+ display: flex;
2579
+ flex-direction: column;
2580
+ padding-left: 1.5em;
2581
+ color: var(--ui-text);
2582
+ }
2583
+ .ui-list--unordered { list-style-type: disc; }
2584
+ .ui-list--ordered { list-style-type: decimal; }
2585
+ .ui-list-item { line-height: 1.6; }
2586
+
2587
+ /* ─── Prose ──────────────────────────────────────────────────────────────────
2588
+ Typography wrapper for rich text: CMS output, markdown-rendered HTML,
2589
+ blog/article bodies. Styles all descendant elements without class names. */
2590
+ .ui-prose {
2591
+ color: var(--ui-text);
2592
+ line-height: 1.75;
2593
+ font-size: 1rem;
2594
+ }
2595
+ .ui-prose--sm { font-size: .875rem; }
2596
+ .ui-prose--lg { font-size: 1.125rem; }
2597
+
2598
+ .ui-prose h1,
2599
+ .ui-prose h2,
2600
+ .ui-prose h3,
2601
+ .ui-prose h4,
2602
+ .ui-prose h5,
2603
+ .ui-prose h6 {
2604
+ color: var(--ui-text);
2605
+ font-weight: 700;
2606
+ line-height: 1.3;
2607
+ margin-top: 2em;
2608
+ margin-bottom: .6em;
2609
+ }
2610
+ .ui-prose h1 { font-size: 2rem; }
2611
+ .ui-prose h2 { font-size: 1.5rem; }
2612
+ .ui-prose h3 { font-size: 1.25rem; font-weight: 600; }
2613
+ .ui-prose h4 { font-size: 1rem; font-weight: 600; }
2614
+ .ui-prose h5 { font-size: .875rem; font-weight: 600; }
2615
+ .ui-prose h6 { font-size: .875rem; font-weight: 600; color: var(--ui-muted); }
2616
+
2617
+ .ui-prose :is(h1, h2, h3, h4, h5, h6):first-child { margin-top: 0; }
2618
+
2619
+ .ui-prose p { margin-bottom: 1.25em; }
2620
+ .ui-prose p:last-child { margin-bottom: 0; }
2621
+
2622
+ .ui-prose a {
2623
+ color: var(--ui-accent);
2624
+ text-decoration: underline;
2625
+ text-underline-offset: 2px;
2626
+ }
2627
+ .ui-prose a:hover { color: var(--ui-accent-hover); }
2628
+
2629
+ .ui-prose strong { font-weight: 700; }
2630
+ .ui-prose em { font-style: italic; }
2631
+
2632
+ .ui-prose ul,
2633
+ .ui-prose ol {
2634
+ padding-left: 1.5em;
2635
+ margin-bottom: 1.25em;
2636
+ }
2637
+ .ui-prose ul { list-style-type: disc; }
2638
+ .ui-prose ol { list-style-type: decimal; }
2639
+ .ui-prose ul ul { list-style-type: circle; }
2640
+ .ui-prose li { margin-bottom: .375em; }
2641
+ .ui-prose li > ul,
2642
+ .ui-prose li > ol { margin-top: .375em; margin-bottom: .375em; }
2643
+
2644
+ .ui-prose blockquote {
2645
+ border-left: 3px solid var(--ui-border);
2646
+ padding: .5em 0 .5em 1.25em;
2647
+ margin: 1.5em 0;
2648
+ color: var(--ui-muted);
2649
+ font-style: italic;
2650
+ }
2651
+ .ui-prose blockquote p { margin-bottom: 0; }
2652
+
2653
+ .ui-prose code {
2654
+ background: var(--ui-surface-2);
2655
+ color: var(--ui-accent);
2656
+ padding: .1em .35em;
2657
+ border-radius: var(--ui-radius-sm);
2658
+ font-size: .875em;
2659
+ font-family: var(--ui-mono);
2660
+ }
2661
+ .ui-prose pre {
2662
+ background: var(--ui-surface-2);
2663
+ border: 1px solid var(--ui-border);
2664
+ border-radius: var(--ui-radius);
2665
+ padding: 1em 1.25em;
2666
+ overflow-x: auto;
2667
+ margin-bottom: 1.25em;
2668
+ font-family: var(--ui-mono);
2669
+ font-size: .875em;
2670
+ line-height: 1.7;
2671
+ }
2672
+ .ui-prose pre code {
2673
+ background: none;
2674
+ color: inherit;
2675
+ padding: 0;
2676
+ font-size: inherit;
2677
+ }
2678
+
2679
+ .ui-prose hr {
2680
+ border: none;
2681
+ border-top: 1px solid var(--ui-border);
2682
+ margin: 2em 0;
2683
+ }
2684
+
2685
+ .ui-prose img {
2686
+ max-width: 100%;
2687
+ border-radius: var(--ui-radius);
2688
+ height: auto;
2689
+ }
2690
+ .ui-prose figure { margin: 1.5em 0; }
2691
+ .ui-prose figcaption {
2692
+ font-size: .875em;
2693
+ color: var(--ui-muted);
2694
+ margin-top: .5em;
2695
+ text-align: center;
2696
+ }
2697
+
2698
+ .ui-prose table {
2699
+ width: 100%;
2700
+ border-collapse: collapse;
2701
+ margin-bottom: 1.25em;
2702
+ font-size: .9375em;
2703
+ }
2704
+ .ui-prose th {
2705
+ text-align: left;
2706
+ padding: .5em .75em;
2707
+ border-bottom: 2px solid var(--ui-border);
2708
+ font-weight: 600;
2709
+ color: var(--ui-text);
2710
+ }
2711
+ .ui-prose td {
2712
+ padding: .5em .75em;
2713
+ border-bottom: 1px solid var(--ui-border);
2714
+ color: var(--ui-text);
2715
+ }
2716
+
2717
+ /* ─── Light theme ────────────────────────────────────────────────────────────
2718
+ Apply to any ancestor element: <body data-theme="light"> or .ui-theme-light
2719
+ All --ui-* tokens are overridden; component markup stays identical. */
2720
+ [data-theme="light"],
2721
+ .ui-theme-light {
2722
+ --ui-bg: #ffffff;
2723
+ --ui-surface: #f8f8fc;
2724
+ --ui-surface-2: #f0f0f8;
2725
+ --ui-border: #d8d8e8;
2726
+ --ui-text: #111118;
2727
+ --ui-muted: #60607a;
2728
+ --ui-accent: #6b5ce7;
2729
+ --ui-accent-hover: #5847d6;
2730
+ --ui-accent-dim: rgba(107, 92, 231, .12);
2731
+ --ui-green: #166534;
2732
+ --ui-green-dim: rgba(22, 163, 74, .12);
2733
+ --ui-red: #991b1b;
2734
+ --ui-red-dim: rgba(220, 38, 38, .12);
2735
+ --ui-yellow: #92400e;
2736
+ --ui-yellow-dim: rgba(217, 119, 6, .12);
2737
+ --ui-blue: #1e40af;
2738
+ --ui-blue-dim: rgba( 30, 64, 175, .12);
2739
+ --ui-nav-sticky-bg: rgba(255, 255, 255, .85);
2740
+ }