@jant/core 0.6.15 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (537) hide show
  1. package/README.md +11 -11
  2. package/bin/commands/assets/upload.js +192 -15
  3. package/bin/commands/import-site.js +67 -4
  4. package/bin/commands/reset-password.js +21 -8
  5. package/bin/commands/site/snapshot/export.js +1 -1
  6. package/bin/commands/site/snapshot/import.js +1 -1
  7. package/bin/lib/d1-query.js +5 -16
  8. package/bin/lib/node-env.js +40 -4
  9. package/bin/lib/site-selection.js +85 -29
  10. package/bin/lib/wrangler-cli.js +28 -2
  11. package/bin/lib/wrangler-json.js +35 -0
  12. package/dist/{app-C-oi_t8W.js → app-K_Aa1MMn.js} +52623 -13193
  13. package/dist/client/.vite/manifest.json +255 -90
  14. package/dist/client/_assets/chunks/confirm-D7GrwsCN.js +45 -0
  15. package/dist/client/_assets/chunks/create-editor-CD3FhrOB.js +257 -0
  16. package/dist/client/_assets/chunks/{native-DpcrFAPh.js → emoji-mart-C4RpRKcU.js} +716 -1
  17. package/dist/client/_assets/chunks/footnote-rail-CmeoVtnU.js +1 -0
  18. package/dist/client/_assets/chunks/heic-to-CuP2Qlsw.js +1 -0
  19. package/dist/client/_assets/chunks/jant-locale-picker-DL6mIOT5.js +69 -0
  20. package/dist/client/_assets/chunks/lit-DW8VmJAT.js +2 -0
  21. package/dist/client/_assets/chunks/mediabunny-DRaCQ1r-.js +31 -0
  22. package/dist/client/_assets/chunks/rolldown-runtime-hePW80VL.js +1 -0
  23. package/dist/client/_assets/chunks/settings-paths-BcdySNx6.js +84 -0
  24. package/dist/client/_assets/chunks/site-header-nav-DzXsFk05.js +1 -0
  25. package/dist/client/_assets/chunks/slug-format-CRXO1AL5.js +1 -0
  26. package/dist/client/_assets/chunks/slugify-373citbs.js +1 -0
  27. package/dist/client/_assets/chunks/sortable-list-CgaL2jCs.js +2 -0
  28. package/dist/client/_assets/chunks/types-D5iF3H1a.js +1 -0
  29. package/dist/client/_assets/chunks/unsafe-html-B5ZEXaxg.js +1 -0
  30. package/dist/client/_assets/chunks/unsafe-svg-0QCkP0vZ.js +2 -0
  31. package/dist/client/_assets/client-GiYENVw8.css +2 -0
  32. package/dist/client/_assets/client-VnFxJN7G.js +295 -0
  33. package/dist/client/_assets/client-auth-k8gJ6QJj.js +828 -0
  34. package/dist/client/_assets/client-author-DQ8R-8KR.css +2 -0
  35. package/dist/client/_assets/client-compose-B_kDtWkW.js +2004 -0
  36. package/dist/client/_assets/client-manage-M90aSTOk.js +2170 -0
  37. package/dist/client/_assets/client-settings-DfYs9n1F.js +1112 -0
  38. package/dist/{export-CsFx6F_M.js → github-sync-BPAvT999.js} +2343 -110
  39. package/dist/index.js +2 -5
  40. package/dist/node.js +5 -7
  41. package/package.json +3 -3
  42. package/src/__tests__/auth-session-freshness.test.ts +57 -0
  43. package/src/__tests__/basecoat-variants.test.ts +121 -0
  44. package/src/__tests__/bin/assets-upload.test.ts +68 -0
  45. package/src/__tests__/export-hugo-build.test.ts +260 -0
  46. package/src/__tests__/export-service.test.ts +231 -0
  47. package/src/__tests__/helpers/component-css.ts +91 -0
  48. package/src/__tests__/helpers/db.ts +33 -0
  49. package/src/__tests__/helpers/export-fixtures.ts +3 -0
  50. package/src/__tests__/mise-config.test.ts +22 -0
  51. package/src/__tests__/stylesheet-audience.test.ts +159 -0
  52. package/src/__tests__/stylesheet-breakpoints.test.ts +183 -0
  53. package/src/app.tsx +71 -16
  54. package/src/auth.ts +18 -1
  55. package/src/client/__tests__/collection-page-actions.test.ts +51 -2
  56. package/src/client/__tests__/compose-bridge-image-upload.test.ts +196 -0
  57. package/src/client/__tests__/compose-bridge-video-poster.test.ts +159 -0
  58. package/src/client/__tests__/compose-bridge.test.ts +524 -2
  59. package/src/client/__tests__/compose-launch.test.ts +62 -1
  60. package/src/client/__tests__/compose-shortcuts.test.ts +57 -8
  61. package/src/client/__tests__/compose-triggers.test.ts +90 -0
  62. package/src/client/__tests__/copy-field.test.ts +162 -0
  63. package/src/client/__tests__/custom-url-menu.test.ts +127 -6
  64. package/src/client/__tests__/image-processor.test.ts +324 -2
  65. package/src/client/__tests__/lazy-entries.test.ts +92 -0
  66. package/src/client/__tests__/media-scroll-hint.test.ts +155 -0
  67. package/src/client/__tests__/runtime-paths.test.ts +84 -0
  68. package/src/client/__tests__/smart-collection-page-actions.test.ts +158 -0
  69. package/src/client/__tests__/toast.test.ts +88 -1
  70. package/src/client/__tests__/video-processor-probe.test.ts +175 -0
  71. package/src/client/__tests__/video-processor.test.ts +181 -0
  72. package/src/client/audio-processor.ts +24 -15
  73. package/src/client/audio-waveform.ts +49 -0
  74. package/src/client/collection-dialog-host.ts +72 -0
  75. package/src/client/collection-navigation.ts +51 -16
  76. package/src/client/collection-page-actions.ts +26 -0
  77. package/src/client/components/__tests__/compose-format-convert.test.ts +0 -19
  78. package/src/client/components/__tests__/jant-collection-dialog.test.ts +329 -0
  79. package/src/client/components/__tests__/jant-collection-directory.test.ts +274 -10
  80. package/src/client/components/__tests__/jant-collection-form.test.ts +59 -178
  81. package/src/client/components/__tests__/jant-command-palette.test.ts +79 -0
  82. package/src/client/components/__tests__/jant-compose-dialog-draft-storage.test.ts +340 -0
  83. package/src/client/components/__tests__/jant-compose-dialog.test.ts +3283 -389
  84. package/src/client/components/__tests__/jant-compose-editor.test.ts +581 -86
  85. package/src/client/components/__tests__/jant-compose-fullscreen.test.ts +34 -89
  86. package/src/client/components/__tests__/jant-locale-picker.test.ts +207 -0
  87. package/src/client/components/__tests__/jant-nav-manager.test.ts +234 -15
  88. package/src/client/components/__tests__/jant-post-menu.test.ts +413 -2
  89. package/src/client/components/__tests__/jant-post-picker.test.ts +197 -0
  90. package/src/client/components/__tests__/jant-settings-avatar.test.ts +15 -12
  91. package/src/client/components/__tests__/jant-settings-general.test.ts +541 -172
  92. package/src/client/components/__tests__/jant-settings-language.test.ts +851 -0
  93. package/src/client/components/__tests__/jant-smart-collection-dialog.test.ts +665 -0
  94. package/src/client/components/collection-dialog-types.ts +49 -0
  95. package/src/client/components/collection-manager-types.ts +32 -1
  96. package/src/client/components/collection-types.ts +1 -15
  97. package/src/client/components/compose-format-convert.ts +5 -1
  98. package/src/client/components/compose-types.ts +121 -3
  99. package/src/client/components/jant-collection-dialog.ts +722 -0
  100. package/src/client/components/jant-collection-directory.ts +567 -182
  101. package/src/client/components/jant-collection-form.ts +53 -232
  102. package/src/client/components/jant-command-palette.ts +106 -49
  103. package/src/client/components/jant-compose-dialog.ts +2757 -1194
  104. package/src/client/components/jant-compose-editor.ts +866 -397
  105. package/src/client/components/jant-compose-fullscreen.ts +53 -47
  106. package/src/client/components/jant-config-editor.ts +65 -53
  107. package/src/client/components/jant-confirm-dialog.ts +13 -11
  108. package/src/client/components/jant-locale-picker.ts +418 -0
  109. package/src/client/components/jant-media-lightbox.ts +146 -136
  110. package/src/client/components/jant-nav-manager.ts +690 -366
  111. package/src/client/components/jant-post-menu.ts +1142 -268
  112. package/src/client/components/jant-post-picker.ts +324 -0
  113. package/src/client/components/jant-repo-picker.ts +138 -106
  114. package/src/client/components/jant-settings-avatar.ts +31 -27
  115. package/src/client/components/jant-settings-general.ts +617 -543
  116. package/src/client/components/jant-settings-language.ts +1087 -0
  117. package/src/client/components/jant-smart-collection-dialog.ts +1021 -0
  118. package/src/client/components/jant-text-preview.ts +94 -86
  119. package/src/client/components/nav-manager-types.ts +62 -1
  120. package/src/client/components/settings-types.ts +14 -29
  121. package/src/client/components/smart-collection-conditions.ts +285 -0
  122. package/src/client/components/smart-collection-dialog-types.ts +68 -0
  123. package/src/client/compose-bridge.ts +336 -242
  124. package/src/client/compose-launch.ts +89 -2
  125. package/src/client/compose-shortcuts.ts +9 -7
  126. package/src/client/compose-triggers.ts +50 -0
  127. package/src/client/copy-field.ts +108 -0
  128. package/src/client/custom-url-menu.ts +60 -4
  129. package/src/client/icons.ts +14 -0
  130. package/src/client/image-plan.ts +165 -0
  131. package/src/client/image-processor.ts +195 -117
  132. package/src/client/image-worker-client.ts +45 -0
  133. package/src/client/image-worker.ts +135 -0
  134. package/src/client/lazy-entries.ts +95 -0
  135. package/src/client/lazy-slugify.ts +2 -2
  136. package/src/client/media-scroll-hint.ts +43 -2
  137. package/src/client/mediabunny.ts +29 -0
  138. package/src/client/post-picker.ts +41 -0
  139. package/src/client/post-refresh.ts +135 -0
  140. package/src/client/runtime-paths.ts +74 -1
  141. package/src/client/settings-bridge.ts +4 -10
  142. package/src/client/site-header-nav.js +18 -6
  143. package/src/client/smart-collection-dialog-host.ts +116 -0
  144. package/src/client/smart-collection-page-actions.ts +208 -0
  145. package/src/client/tiptap/__tests__/bubble-menu.test.ts +110 -0
  146. package/src/client/tiptap/__tests__/floating-position.test.ts +136 -1
  147. package/src/client/tiptap/__tests__/inline-image-upload.test.ts +37 -0
  148. package/src/client/tiptap/__tests__/link-input-rules.test.ts +121 -0
  149. package/src/client/tiptap/bubble-menu.ts +47 -16
  150. package/src/client/tiptap/floating-position.ts +216 -2
  151. package/src/client/tiptap/inline-image-upload.ts +7 -3
  152. package/src/client/tiptap/link-input-rules.ts +4 -4
  153. package/src/client/tiptap/link-toolbar.ts +22 -9
  154. package/src/client/toast.ts +143 -38
  155. package/src/client/types/vite-worker.d.ts +12 -0
  156. package/src/client/upload-with-metadata.ts +3 -13
  157. package/src/client/video-processor.ts +351 -107
  158. package/src/client-auth.ts +14 -31
  159. package/src/client-compose.ts +19 -0
  160. package/src/client-manage.ts +13 -0
  161. package/src/client-settings.ts +14 -0
  162. package/src/client-site.ts +10 -3
  163. package/src/client.ts +4 -0
  164. package/src/db/__tests__/backfill-nav-label-mirrors.test.ts +149 -0
  165. package/src/db/__tests__/backfill-thread-activity.test.ts +234 -0
  166. package/src/db/__tests__/schema-enum-sources.test.ts +33 -0
  167. package/src/db/__tests__/smart-collection-placement.test.ts +402 -0
  168. package/src/db/__tests__/thread-activity.test.ts +113 -0
  169. package/src/db/backfills/0005_split_thread_activity_from_quiet_replies.sql +68 -0
  170. package/src/db/backfills/0006_clear_mirrored_page_nav_labels.sql +31 -0
  171. package/src/db/migrations/0031_many_ego.sql +3 -0
  172. package/src/db/migrations/0032_married_tomas.sql +3 -0
  173. package/src/db/migrations/0033_busy_johnny_storm.sql +198 -0
  174. package/src/db/migrations/0034_cheerful_rumiko_fujikawa.sql +35 -0
  175. package/src/db/migrations/meta/0031_snapshot.json +2562 -0
  176. package/src/db/migrations/meta/0032_snapshot.json +2582 -0
  177. package/src/db/migrations/meta/0033_snapshot.json +2816 -0
  178. package/src/db/migrations/meta/0034_snapshot.json +2816 -0
  179. package/src/db/migrations/meta/_journal.json +28 -0
  180. package/src/db/migrations/pg/0029_rare_hairball.sql +3 -0
  181. package/src/db/migrations/pg/0030_abandoned_nighthawk.sql +3 -0
  182. package/src/db/migrations/pg/0031_strong_ultimatum.sql +128 -0
  183. package/src/db/migrations/pg/0032_furry_multiple_man.sql +6 -0
  184. package/src/db/migrations/pg/meta/0029_snapshot.json +3289 -0
  185. package/src/db/migrations/pg/meta/0030_snapshot.json +3329 -0
  186. package/src/db/migrations/pg/meta/0031_snapshot.json +3660 -0
  187. package/src/db/migrations/pg/meta/0032_snapshot.json +3660 -0
  188. package/src/db/migrations/pg/meta/_journal.json +28 -0
  189. package/src/db/pg/schema.ts +213 -27
  190. package/src/db/post-visibility.ts +117 -0
  191. package/src/db/schema.ts +242 -27
  192. package/src/db/thread-activity.ts +101 -0
  193. package/src/i18n/__tests__/detect.test.ts +26 -81
  194. package/src/i18n/__tests__/supported-locales.test.ts +83 -0
  195. package/src/i18n/context.tsx +12 -2
  196. package/src/i18n/detect.ts +7 -66
  197. package/src/i18n/locales/glossary.zh-Hans.yml +44 -4
  198. package/src/i18n/locales/glossary.zh-Hant.yml +44 -4
  199. package/src/i18n/locales/public/en.po +568 -168
  200. package/src/i18n/locales/public/en.ts +1 -1
  201. package/src/i18n/locales/public/zh-Hans.po +562 -162
  202. package/src/i18n/locales/public/zh-Hans.ts +1 -1
  203. package/src/i18n/locales/public/zh-Hant.po +562 -162
  204. package/src/i18n/locales/public/zh-Hant.ts +1 -1
  205. package/src/i18n/locales/settings/en.po +551 -69
  206. package/src/i18n/locales/settings/en.ts +1 -1
  207. package/src/i18n/locales/settings/zh-Hans.po +597 -115
  208. package/src/i18n/locales/settings/zh-Hans.ts +1 -1
  209. package/src/i18n/locales/settings/zh-Hant.po +610 -128
  210. package/src/i18n/locales/settings/zh-Hant.ts +1 -1
  211. package/src/i18n/locales.ts +94 -0
  212. package/src/i18n/middleware.ts +12 -2
  213. package/src/i18n/supported-locales.ts +80 -0
  214. package/src/lib/__tests__/api-settings.test.ts +11 -2
  215. package/src/lib/__tests__/asset-path.test.ts +92 -0
  216. package/src/lib/__tests__/deferred.test.ts +90 -0
  217. package/src/lib/__tests__/discover-ping.test.ts +89 -0
  218. package/src/lib/__tests__/discover.test.ts +410 -0
  219. package/src/lib/__tests__/feed-policy.test.ts +26 -0
  220. package/src/lib/__tests__/feed.test.ts +1691 -12
  221. package/src/lib/__tests__/filter-dimensions.test.ts +341 -0
  222. package/src/lib/__tests__/hosted-signin.test.ts +1 -1
  223. package/src/lib/__tests__/http-cache.test.ts +162 -0
  224. package/src/lib/__tests__/jant-docs-dev.test.ts +21 -0
  225. package/src/lib/__tests__/jant-docs.test.ts +23 -0
  226. package/src/lib/__tests__/lang-detect.test.ts +231 -0
  227. package/src/lib/__tests__/markdown.test.ts +16 -0
  228. package/src/lib/__tests__/media-helpers.test.ts +81 -0
  229. package/src/lib/__tests__/navigation.test.ts +135 -1
  230. package/src/lib/__tests__/resolve-config.test.ts +64 -3
  231. package/src/lib/__tests__/schemas.test.ts +42 -4
  232. package/src/lib/__tests__/site-unavailable-page.test.ts +25 -0
  233. package/src/lib/__tests__/slug.test.ts +88 -0
  234. package/src/lib/__tests__/slugify.test.ts +85 -0
  235. package/src/lib/__tests__/storage.test.ts +32 -0
  236. package/src/lib/__tests__/thread-fold.test.ts +113 -0
  237. package/src/lib/__tests__/translit.test.ts +87 -0
  238. package/src/lib/__tests__/upload-sideload.test.ts +14 -0
  239. package/src/lib/__tests__/url-fetch.test.ts +1 -2
  240. package/src/lib/__tests__/url.test.ts +93 -34
  241. package/src/lib/__tests__/view-language.test.ts +413 -0
  242. package/src/lib/__tests__/worker-response-cache.test.ts +90 -0
  243. package/src/lib/address.ts +57 -0
  244. package/src/lib/api-posts.ts +12 -0
  245. package/src/lib/asset-path.ts +98 -1
  246. package/src/lib/build-env.ts +16 -0
  247. package/src/lib/collection-groups.ts +5 -1
  248. package/src/lib/collection-paths.ts +3 -10
  249. package/src/lib/constants.ts +28 -3
  250. package/src/lib/copy-field.ts +36 -0
  251. package/src/lib/crypto.ts +40 -0
  252. package/src/lib/csp-builder.ts +2 -1
  253. package/src/lib/deferred.ts +79 -0
  254. package/src/lib/discover-ping.ts +141 -0
  255. package/src/lib/discover.ts +437 -0
  256. package/src/lib/env.ts +134 -0
  257. package/src/lib/errors.ts +33 -0
  258. package/src/lib/feed-policy.ts +236 -2
  259. package/src/lib/feed.ts +1021 -66
  260. package/src/lib/filter-dimensions.ts +1349 -0
  261. package/src/lib/github-sync-site-config.ts +3 -0
  262. package/src/lib/hosted-signin.ts +1 -1
  263. package/src/lib/http-cache.ts +148 -0
  264. package/src/lib/hugo-markdown.ts +21 -0
  265. package/src/lib/icons.ts +9 -2
  266. package/src/lib/ids.ts +3 -0
  267. package/src/lib/jant-docs.ts +42 -0
  268. package/src/lib/lang-detect.ts +308 -0
  269. package/src/lib/link-preview.ts +25 -0
  270. package/src/lib/markdown-manager.ts +6 -1
  271. package/src/lib/media-helpers.ts +13 -1
  272. package/src/lib/navigation.ts +78 -11
  273. package/src/lib/pagination.ts +28 -24
  274. package/src/lib/per-language-surfaces.ts +67 -0
  275. package/src/lib/post-display.ts +42 -9
  276. package/src/lib/post-meta.ts +19 -0
  277. package/src/lib/render.tsx +55 -7
  278. package/src/lib/resolve-config.ts +53 -5
  279. package/src/lib/schemas.ts +201 -10
  280. package/src/lib/site-header-fragment.tsx +2 -1
  281. package/src/lib/site-unavailable-page.ts +47 -0
  282. package/src/lib/slug.ts +51 -7
  283. package/src/lib/slugify.ts +113 -0
  284. package/src/lib/startup-config.ts +4 -6
  285. package/src/lib/storage.ts +7 -0
  286. package/src/lib/summary.ts +50 -0
  287. package/src/lib/thread-fold.ts +161 -0
  288. package/src/lib/time.ts +32 -0
  289. package/src/lib/timeline.ts +81 -10
  290. package/src/lib/tiptap-render.ts +5 -4
  291. package/src/lib/translit.ts +288 -0
  292. package/src/lib/upload.ts +16 -13
  293. package/src/lib/url.ts +188 -24
  294. package/src/lib/version.ts +10 -8
  295. package/src/lib/view-language.ts +436 -0
  296. package/src/lib/view.ts +79 -23
  297. package/src/lib/viewer-context.ts +62 -0
  298. package/src/middleware/__tests__/auth.test.ts +70 -2
  299. package/src/middleware/__tests__/cache-control.test.ts +71 -3
  300. package/src/middleware/__tests__/onboarding.test.ts +76 -5
  301. package/src/middleware/__tests__/secure-headers.test.ts +1 -1
  302. package/src/middleware/__tests__/session.test.ts +181 -33
  303. package/src/middleware/auth.ts +50 -31
  304. package/src/middleware/cache-control.ts +75 -10
  305. package/src/middleware/config.ts +6 -6
  306. package/src/middleware/error-handler.ts +12 -0
  307. package/src/middleware/onboarding.ts +32 -10
  308. package/src/middleware/secure-headers.ts +1 -1
  309. package/src/middleware/session.ts +96 -8
  310. package/src/node/__tests__/cli-migrate.test.ts +21 -19
  311. package/src/node/__tests__/cli-reset-password.test.ts +81 -8
  312. package/src/node/__tests__/cli-runtime-target.test.ts +48 -1
  313. package/src/node/__tests__/cli-site-selection.test.ts +128 -38
  314. package/src/node/__tests__/runtime.test.ts +37 -0
  315. package/src/node/index.ts +1 -0
  316. package/src/preset.css +76 -22
  317. package/src/routes/__tests__/feed-validator.test.ts +156 -0
  318. package/src/routes/api/__tests__/collections.test.ts +114 -0
  319. package/src/routes/api/__tests__/discover.test.ts +222 -0
  320. package/src/routes/api/__tests__/nav-items.test.ts +212 -2
  321. package/src/routes/api/__tests__/palette.test.ts +44 -0
  322. package/src/routes/api/__tests__/post-translations.test.ts +829 -0
  323. package/src/routes/api/__tests__/settings.test.ts +24 -3
  324. package/src/routes/api/__tests__/telegram.test.ts +6 -5
  325. package/src/routes/api/collections.ts +49 -6
  326. package/src/routes/api/custom-urls.ts +0 -1
  327. package/src/routes/api/discover.ts +95 -0
  328. package/src/routes/api/export.ts +3 -0
  329. package/src/routes/api/internal/__tests__/sites.test.ts +42 -2
  330. package/src/routes/api/nav-items.ts +55 -8
  331. package/src/routes/api/posts.ts +172 -9
  332. package/src/routes/api/public/__tests__/archive.test.ts +111 -0
  333. package/src/routes/api/public/__tests__/posts.test.ts +38 -0
  334. package/src/routes/api/public/archive.ts +77 -81
  335. package/src/routes/api/public/posts.ts +30 -6
  336. package/src/routes/api/smart-collections.ts +132 -0
  337. package/src/routes/api/telegram.ts +2 -40
  338. package/src/routes/api/uploads.ts +1 -2
  339. package/src/routes/auth/__tests__/setup-auth.test.ts +137 -0
  340. package/src/routes/auth/__tests__/setup-discover.test.ts +204 -0
  341. package/src/routes/auth/__tests__/setup-flow.test.ts +270 -0
  342. package/src/routes/auth/__tests__/setup-page.test.tsx +329 -0
  343. package/src/routes/auth/__tests__/setup-steps.test.ts +310 -0
  344. package/src/routes/auth/__tests__/setup.test.ts +278 -26
  345. package/src/routes/auth/__tests__/signin.test.ts +135 -0
  346. package/src/routes/auth/setup.tsx +934 -186
  347. package/src/routes/auth/signin.tsx +10 -8
  348. package/src/routes/compose.tsx +11 -2
  349. package/src/routes/dash/__tests__/custom-urls-archive.test.ts +44 -0
  350. package/src/routes/dash/__tests__/custom-urls-page.test.ts +49 -0
  351. package/src/routes/dash/__tests__/delete-account.test.ts +106 -0
  352. package/src/routes/dash/__tests__/settings-discover.test.ts +213 -0
  353. package/src/routes/dash/custom-urls.tsx +1 -37
  354. package/src/routes/dash/settings.tsx +502 -41
  355. package/src/routes/discover-announce.ts +96 -0
  356. package/src/routes/feed/__tests__/feed.test.ts +165 -2
  357. package/src/routes/feed/__tests__/sitemap.test.ts +68 -1
  358. package/src/routes/feed/feed.ts +69 -40
  359. package/src/routes/feed/sitemap.ts +95 -11
  360. package/src/routes/pages/__tests__/archive-indexing.test.ts +200 -0
  361. package/src/routes/pages/__tests__/archive-params.test.ts +657 -1
  362. package/src/routes/pages/__tests__/collection-routing.test.ts +16 -0
  363. package/src/routes/pages/__tests__/collections-feed-links.test.ts +72 -0
  364. package/src/routes/pages/__tests__/collections.test.ts +9 -3
  365. package/src/routes/pages/__tests__/custom-archive-url.test.ts +119 -0
  366. package/src/routes/pages/__tests__/featured.test.ts +6 -2
  367. package/src/routes/pages/__tests__/feed-autodiscovery.test.ts +148 -0
  368. package/src/routes/pages/__tests__/language-routing.test.ts +679 -0
  369. package/src/routes/pages/__tests__/post-preview-partial.test.ts +96 -0
  370. package/src/routes/pages/__tests__/preview.test.ts +3 -1
  371. package/src/routes/pages/__tests__/smart-collection.test.ts +298 -0
  372. package/src/routes/pages/__tests__/subscribe.test.ts +248 -0
  373. package/src/routes/pages/archive.tsx +507 -357
  374. package/src/routes/pages/collection.tsx +94 -96
  375. package/src/routes/pages/collections.tsx +38 -50
  376. package/src/routes/pages/featured.tsx +32 -13
  377. package/src/routes/pages/home.tsx +25 -6
  378. package/src/routes/pages/language.tsx +113 -0
  379. package/src/routes/pages/latest.tsx +26 -16
  380. package/src/routes/pages/new.tsx +3 -0
  381. package/src/routes/pages/page.tsx +183 -19
  382. package/src/routes/pages/partials.tsx +41 -0
  383. package/src/routes/pages/search.tsx +18 -3
  384. package/src/routes/pages/smart-collection.tsx +340 -0
  385. package/src/routes/pages/subscribe.tsx +182 -0
  386. package/src/runtime/__tests__/index.test.ts +19 -0
  387. package/src/runtime/__tests__/node.test.ts +129 -4
  388. package/src/runtime/cloudflare.ts +21 -2
  389. package/src/runtime/index.ts +27 -1
  390. package/src/runtime/node.ts +18 -1
  391. package/src/runtime/site.ts +95 -24
  392. package/src/services/__tests__/auth.test.ts +116 -7
  393. package/src/services/__tests__/collection.test.ts +139 -4
  394. package/src/services/__tests__/language.test.ts +495 -0
  395. package/src/services/__tests__/navigation.test.ts +213 -10
  396. package/src/services/__tests__/path.test.ts +180 -0
  397. package/src/services/__tests__/post-language.test.ts +830 -0
  398. package/src/services/__tests__/post-timeline.test.ts +142 -11
  399. package/src/services/__tests__/post.test.ts +323 -9
  400. package/src/services/__tests__/settings.test.ts +228 -17
  401. package/src/services/__tests__/site-admin.test.ts +5 -5
  402. package/src/services/__tests__/smart-collection.test.ts +651 -0
  403. package/src/services/about-page.ts +22 -1
  404. package/src/services/auth.ts +51 -49
  405. package/src/services/bootstrap.ts +188 -38
  406. package/src/services/collection-directory-position.ts +76 -0
  407. package/src/services/collection.ts +330 -47
  408. package/src/services/custom-url.ts +27 -22
  409. package/src/services/export-theme/assets/client-site.css +1 -1
  410. package/src/services/export-theme/assets/client-site.js +123 -123
  411. package/src/services/export-theme/layouts/_default/rss.xml +77 -1
  412. package/src/services/export-theme/layouts/partials/feed-post-content.xml +105 -2
  413. package/src/services/export-theme/layouts/partials/media-gallery.html +35 -21
  414. package/src/services/export-theme/layouts/partials/pagination.html +14 -13
  415. package/src/services/export-theme/layouts/partials/post-card.html +8 -4
  416. package/src/services/export-theme/layouts/partials/reply.html +2 -1
  417. package/src/services/export-theme/layouts/partials/thread-preview.html +40 -30
  418. package/src/services/export-theme/styles/main.css +13 -1
  419. package/src/services/export.ts +281 -24
  420. package/src/services/index.ts +34 -3
  421. package/src/services/language.ts +412 -0
  422. package/src/services/mcp.ts +3 -1
  423. package/src/services/media.ts +14 -6
  424. package/src/services/navigation.ts +429 -67
  425. package/src/services/path.ts +225 -7
  426. package/src/services/post.ts +1318 -252
  427. package/src/services/search.ts +48 -2
  428. package/src/services/settings.ts +238 -43
  429. package/src/services/site-admin.ts +24 -7
  430. package/src/services/site.ts +77 -1
  431. package/src/services/smart-collection.ts +636 -0
  432. package/src/services/telegram.ts +20 -22
  433. package/src/services/upload-session.ts +1 -3
  434. package/src/style-author.css +27 -0
  435. package/src/styles/components-author.css +1622 -0
  436. package/src/styles/components.css +24 -1585
  437. package/src/styles/site-media.css +20 -6
  438. package/src/styles/tokens.css +144 -13
  439. package/src/styles/ui-author.css +7602 -0
  440. package/src/styles/ui.css +1224 -7276
  441. package/src/types/app-context.ts +7 -0
  442. package/src/types/bindings.ts +3 -0
  443. package/src/types/config.ts +94 -15
  444. package/src/types/constants.ts +188 -16
  445. package/src/types/entities.ts +92 -1
  446. package/src/types/operations.ts +64 -2
  447. package/src/types/props.ts +168 -30
  448. package/src/types/views.ts +61 -1
  449. package/src/ui/__tests__/font-themes.test.ts +52 -12
  450. package/src/ui/compose/ComposeDialog.tsx +215 -21
  451. package/src/ui/compose/ComposePrompt.tsx +1 -5
  452. package/src/ui/compose/__tests__/ComposeDialog.test.tsx +125 -0
  453. package/src/ui/dash/appearance/AdvancedContent.tsx +2 -2
  454. package/src/ui/dash/appearance/CodeInjectionContent.tsx +12 -16
  455. package/src/ui/dash/appearance/NavigationContent.tsx +117 -16
  456. package/src/ui/dash/appearance/__tests__/NavigationContent.test.tsx +33 -11
  457. package/src/ui/dash/appearance/__tests__/system-nav-descriptions.test.ts +44 -0
  458. package/src/ui/dash/appearance/system-nav-descriptions.ts +75 -0
  459. package/src/ui/dash/settings/AccountMenuContent.tsx +2 -2
  460. package/src/ui/dash/settings/ApiTokensContent.tsx +2 -1
  461. package/src/ui/dash/settings/ConfigEditorContent.tsx +35 -16
  462. package/src/ui/dash/settings/GeneralContent.tsx +275 -113
  463. package/src/ui/dash/settings/LanguageContent.tsx +409 -0
  464. package/src/ui/dash/settings/SettingsRootContent.tsx +19 -1
  465. package/src/ui/dash/settings/__tests__/GeneralContent.test.tsx +324 -4
  466. package/src/ui/dash/settings/__tests__/LanguageContent.test.tsx +144 -0
  467. package/src/ui/dash/settings/__tests__/discover-copy.test.ts +66 -0
  468. package/src/ui/dash/settings/discover-copy.ts +116 -0
  469. package/src/ui/feed/LinkCard.tsx +55 -45
  470. package/src/ui/feed/LinkPreview.tsx +2 -7
  471. package/src/ui/feed/NoteCard.tsx +9 -4
  472. package/src/ui/feed/PostStatusBadges.tsx +103 -17
  473. package/src/ui/feed/QuoteCard.tsx +55 -30
  474. package/src/ui/feed/ThreadPreview.tsx +6 -2
  475. package/src/ui/feed/__tests__/thread-preview.test.ts +13 -16
  476. package/src/ui/feed/__tests__/timeline-cards.test.ts +314 -49
  477. package/src/ui/feed/thread-preview-state.ts +20 -6
  478. package/src/ui/font-themes.ts +39 -29
  479. package/src/ui/layouts/BaseLayout.tsx +155 -10
  480. package/src/ui/layouts/SiteLayout.tsx +192 -34
  481. package/src/ui/layouts/__tests__/BaseLayout.test.tsx +196 -17
  482. package/src/ui/layouts/__tests__/SiteLayout.test.tsx +109 -85
  483. package/src/ui/pages/ArchivePage.tsx +401 -301
  484. package/src/ui/pages/CollectionPage.tsx +86 -76
  485. package/src/ui/pages/CollectionsPage.tsx +5 -0
  486. package/src/ui/pages/ComposePage.tsx +8 -0
  487. package/src/ui/pages/PostPage.tsx +47 -0
  488. package/src/ui/pages/SearchPage.tsx +3 -3
  489. package/src/ui/pages/SmartCollectionPage.tsx +434 -0
  490. package/src/ui/pages/SubscribePage.tsx +236 -0
  491. package/src/ui/pages/__tests__/ArchivePage.test.tsx +122 -3
  492. package/src/ui/pages/__tests__/collections-directory-rows.test.tsx +92 -0
  493. package/src/ui/pages/__tests__/collections-view-links.test.tsx +81 -0
  494. package/src/ui/shared/CollectionDirectory.tsx +178 -3
  495. package/src/ui/shared/CollectionsManager.tsx +70 -17
  496. package/src/ui/shared/CopyField.tsx +127 -0
  497. package/src/ui/shared/DraftPreviewBar.tsx +25 -9
  498. package/src/ui/shared/EmptyPostContent.tsx +23 -0
  499. package/src/ui/shared/MediaGallery.tsx +125 -46
  500. package/src/ui/shared/Pagination.tsx +20 -5
  501. package/src/ui/shared/PostFooter.tsx +55 -23
  502. package/src/ui/shared/__tests__/archive-labels.test.ts +100 -0
  503. package/src/ui/shared/__tests__/media-gallery.test.ts +210 -2
  504. package/src/ui/shared/__tests__/navigation-labels.test.ts +16 -22
  505. package/src/ui/shared/__tests__/pagination.test.ts +38 -24
  506. package/src/ui/shared/__tests__/post-footer.test.ts +32 -0
  507. package/src/ui/shared/archive-labels.ts +98 -0
  508. package/src/ui/shared/collection-management-labels.ts +94 -16
  509. package/src/ui/shared/custom-icons.ts +5 -0
  510. package/src/ui/shared/navigation-labels.ts +45 -71
  511. package/src/ui/shared/post-article-attributes.ts +8 -0
  512. package/src/ui/shared/smart-collection-labels.ts +343 -0
  513. package/dist/app-BxCOR3Uc.js +0 -6
  514. package/dist/client/_assets/chunks/heic-to-DUUaO23q.js +0 -1
  515. package/dist/client/_assets/chunks/module-DcsAZQZ_.js +0 -716
  516. package/dist/client/_assets/chunks/url-pLre2DM_.js +0 -1
  517. package/dist/client/_assets/client-B_eGKN5p.css +0 -2
  518. package/dist/client/_assets/client-DxY5BFe8.js +0 -296
  519. package/dist/client/_assets/client-auth-CakPESv9.js +0 -5533
  520. package/dist/env-OHRKGcMj.js +0 -281
  521. package/dist/github-api-BgSiE71w.js +0 -176
  522. package/dist/github-app-BbklkFmU.js +0 -275
  523. package/dist/github-sync-Cq1pzzOI.js +0 -431
  524. package/dist/github-sync-ppWXN3jb.js +0 -4
  525. package/dist/url-BMYO-Zlt.js +0 -395
  526. package/src/client/__tests__/collection-created-notice.test.ts +0 -36
  527. package/src/client/__tests__/collection-form-bridge.test.ts +0 -216
  528. package/src/client/__tests__/post-form-bridge.test.ts +0 -82
  529. package/src/client/collection-created-notice.ts +0 -66
  530. package/src/client/collection-form-bridge.ts +0 -191
  531. package/src/client/components/__tests__/jant-post-form.test.ts +0 -193
  532. package/src/client/components/jant-post-form.ts +0 -422
  533. package/src/client/components/post-form-template.ts +0 -352
  534. package/src/client/components/post-form-types.ts +0 -96
  535. package/src/client/media-metadata.ts +0 -247
  536. package/src/client/post-form-bridge.ts +0 -193
  537. package/src/ui/pages/CollectionEditorPage.tsx +0 -175
@@ -3,6 +3,11 @@
3
3
  *
4
4
  * These use Tailwind's @layer and @apply, so they must be imported
5
5
  * AFTER Tailwind is initialized in the user's CSS entry.
6
+ *
7
+ * Reader half only. The settings pages, the config editor, the navigation
8
+ * manager, the custom URL manager, the dash chrome and the form skeletons
9
+ * live in `components-author.css`, which loads only on authenticated pages —
10
+ * see the note in `style-author.css`.
6
11
  */
7
12
 
8
13
  /* Search result highlight */
@@ -15,377 +20,10 @@ mark {
15
20
 
16
21
  /* Config Editor — a quiet utility list, not a stack of nested cards. */
17
22
  @layer components {
18
- .config-editor-page {
19
- display: flex;
20
- flex-direction: column;
21
- width: min(54rem, 100%);
22
- gap: clamp(1rem, 2vw, 1.25rem);
23
- padding-bottom: 1rem;
24
- }
25
-
26
23
  jant-config-editor {
27
24
  display: block;
28
25
  min-width: 0;
29
26
  }
30
-
31
- .config-editor-toolbar,
32
- .config-editor-search {
33
- min-width: 0;
34
- }
35
-
36
- .config-editor-search {
37
- position: relative;
38
- }
39
-
40
- .config-editor-search > svg {
41
- position: absolute;
42
- z-index: 1;
43
- top: 50%;
44
- left: 0.78rem;
45
- transform: translateY(-50%);
46
- color: var(--color-muted-foreground);
47
- pointer-events: none;
48
- }
49
-
50
- .config-editor-search .config-editor-search-input {
51
- width: 100%;
52
- min-height: 2.65rem;
53
- padding-left: 2.35rem;
54
- border-radius: var(--radius);
55
- font-family: var(--font-ui);
56
- }
57
-
58
- .config-editor-fallback .config-editor-search-input {
59
- padding-left: 0.8rem;
60
- }
61
-
62
- .config-editor-toolbar-meta {
63
- display: flex;
64
- min-height: 1.85rem;
65
- align-items: center;
66
- justify-content: space-between;
67
- gap: 1rem;
68
- margin: 0.35rem 0.1rem 0.25rem;
69
- }
70
-
71
- .config-editor-count {
72
- margin: 0;
73
- color: var(--color-muted-foreground);
74
- font-family: var(--font-ui);
75
- font-size: var(--type-2xs);
76
- line-height: 1.35;
77
- }
78
-
79
- .config-editor-modified-filter {
80
- display: inline-flex;
81
- min-height: 1.85rem;
82
- align-items: center;
83
- gap: 0.42rem;
84
- color: var(--color-muted-foreground);
85
- font-family: var(--font-ui);
86
- font-size: var(--type-2xs);
87
- cursor: pointer;
88
- touch-action: manipulation;
89
- white-space: nowrap;
90
- }
91
-
92
- .config-editor-modified-filter:hover,
93
- .config-editor-modified-filter:focus-within {
94
- color: var(--color-foreground);
95
- }
96
-
97
- .config-editor-modified-filter:focus-within {
98
- outline: 2px solid color-mix(in srgb, var(--site-accent) 26%, transparent);
99
- outline-offset: 2px;
100
- }
101
-
102
- .config-editor-list {
103
- margin: 0;
104
- padding: 0;
105
- border-top: 1px solid var(--color-border);
106
- border-bottom: 1px solid var(--color-border);
107
- list-style: none;
108
- }
109
-
110
- .config-editor-row {
111
- display: grid;
112
- grid-template-columns: minmax(0, 1fr) minmax(16rem, 18rem);
113
- align-items: center;
114
- gap: clamp(1.25rem, 3vw, 2.25rem);
115
- min-width: 0;
116
- padding: 0.88rem 0.1rem;
117
- border-bottom: 1px solid
118
- color-mix(in srgb, var(--color-border) 78%, transparent);
119
- }
120
-
121
- .config-editor-row:last-child {
122
- border-bottom: 0;
123
- }
124
-
125
- .config-editor-row[aria-busy="true"] {
126
- background: color-mix(in srgb, var(--site-accent) 2.5%, transparent);
127
- }
128
-
129
- .config-editor-copy,
130
- .config-editor-value-column,
131
- .config-editor-control-row {
132
- min-width: 0;
133
- }
134
-
135
- .config-editor-heading {
136
- display: flex;
137
- flex-wrap: wrap;
138
- align-items: center;
139
- gap: 0.45rem;
140
- }
141
-
142
- .config-editor-heading > label {
143
- cursor: pointer;
144
- }
145
-
146
- .config-editor-key {
147
- overflow-wrap: anywhere;
148
- color: var(--color-foreground);
149
- font-family: var(--font-mono);
150
- font-size: var(--type-xs);
151
- font-weight: var(--fw-medium);
152
- line-height: 1.35;
153
- }
154
-
155
- .config-editor-state {
156
- display: inline-flex;
157
- align-items: center;
158
- gap: 0.3rem;
159
- color: var(--color-muted-foreground);
160
- font-family: var(--font-ui);
161
- font-size: var(--type-2xs);
162
- line-height: 1.3;
163
- }
164
-
165
- .config-editor-state::before {
166
- width: 0.28rem;
167
- height: 0.28rem;
168
- flex: none;
169
- border-radius: 999px;
170
- background: currentColor;
171
- content: "";
172
- }
173
-
174
- .config-editor-modified {
175
- color: color-mix(in srgb, var(--site-accent) 72%, var(--color-foreground));
176
- }
177
-
178
- .config-editor-locked::before {
179
- border-radius: 0.05rem;
180
- }
181
-
182
- .config-editor-description {
183
- margin: 0.28rem 0 0;
184
- color: var(--color-muted-foreground);
185
- font-family: var(--font-ui);
186
- font-size: var(--type-xs);
187
- line-height: 1.42;
188
- text-wrap: pretty;
189
- }
190
-
191
- .config-editor-value-column {
192
- display: flex;
193
- flex-direction: column;
194
- align-items: stretch;
195
- gap: 0.28rem;
196
- }
197
-
198
- .config-editor-control-row {
199
- display: grid;
200
- grid-template-columns: minmax(0, 1fr) 2rem;
201
- align-items: center;
202
- gap: 0.7rem;
203
- }
204
-
205
- .config-editor-control-row-select {
206
- grid-template-columns: minmax(0, 1fr) 2rem;
207
- }
208
-
209
- .config-editor-control-row-number {
210
- grid-template-columns: minmax(0, 8rem) 2rem;
211
- justify-content: start;
212
- }
213
-
214
- .config-editor-control-row > input[role="switch"] {
215
- justify-self: end;
216
- }
217
-
218
- .config-editor-control-row .config-editor-select,
219
- .config-editor-value-input {
220
- width: 100%;
221
- max-width: 100%;
222
- min-width: 0;
223
- font-family: var(--font-mono);
224
- font-size: var(--type-xs);
225
- }
226
-
227
- .config-editor-control-row .config-editor-select {
228
- overflow: hidden;
229
- text-overflow: ellipsis;
230
- white-space: nowrap;
231
- }
232
-
233
- .config-editor-status {
234
- align-self: flex-end;
235
- color: var(--color-muted-foreground);
236
- font-family: var(--font-ui);
237
- font-size: var(--type-2xs);
238
- line-height: 1.35;
239
- }
240
-
241
- .config-editor-status-saved {
242
- color: color-mix(in srgb, var(--site-accent) 68%, var(--color-foreground));
243
- }
244
-
245
- .config-editor-status-error {
246
- max-width: 100%;
247
- color: var(--color-destructive);
248
- text-align: right;
249
- text-wrap: pretty;
250
- }
251
-
252
- .config-editor-reset {
253
- display: grid;
254
- width: 2rem;
255
- height: 2rem;
256
- place-items: center;
257
- padding: 0;
258
- border: 0;
259
- border-radius: var(--radius);
260
- background: transparent;
261
- color: var(--color-muted-foreground);
262
- cursor: pointer;
263
- touch-action: manipulation;
264
- }
265
-
266
- .config-editor-reset:hover,
267
- .config-editor-reset:focus-visible {
268
- background: var(--color-muted);
269
- color: var(--color-foreground);
270
- }
271
-
272
- .config-editor-reset:focus-visible,
273
- .config-editor-open-control:focus-visible {
274
- outline: 2px solid color-mix(in srgb, var(--site-accent) 28%, transparent);
275
- outline-offset: 3px;
276
- }
277
-
278
- .config-editor-reset:disabled {
279
- opacity: 0.45;
280
- cursor: not-allowed;
281
- }
282
-
283
- .config-editor-open-control {
284
- display: flex;
285
- min-width: 0;
286
- min-height: 2.35rem;
287
- align-items: center;
288
- justify-content: space-between;
289
- gap: 0.8rem;
290
- padding: 0.35rem 0.1rem;
291
- color: inherit;
292
- text-decoration: none;
293
- cursor: pointer;
294
- touch-action: manipulation;
295
- }
296
-
297
- .config-editor-linked-value {
298
- min-width: 0;
299
- overflow: hidden;
300
- color: var(--site-text-secondary);
301
- font-family: var(--font-mono);
302
- font-size: var(--type-xs);
303
- line-height: 1.4;
304
- text-overflow: ellipsis;
305
- white-space: nowrap;
306
- }
307
-
308
- .config-editor-open-action {
309
- display: inline-flex;
310
- flex: none;
311
- align-items: center;
312
- gap: 0.3rem;
313
- color: var(--color-muted-foreground);
314
- font-family: var(--font-ui);
315
- font-size: var(--type-2xs);
316
- line-height: 1.35;
317
- white-space: nowrap;
318
- }
319
-
320
- .config-editor-open-control:hover .config-editor-linked-value,
321
- .config-editor-open-control:hover .config-editor-open-action,
322
- .config-editor-open-control:focus-visible .config-editor-linked-value,
323
- .config-editor-open-control:focus-visible .config-editor-open-action {
324
- color: var(--color-foreground);
325
- }
326
-
327
- .config-editor-fallback-value {
328
- width: 100%;
329
- min-width: 0;
330
- overflow: hidden;
331
- padding-block: 0.35rem;
332
- color: var(--site-text-secondary);
333
- font-family: var(--font-mono);
334
- font-size: var(--type-xs);
335
- line-height: 1.4;
336
- text-align: right;
337
- text-overflow: ellipsis;
338
- white-space: nowrap;
339
- }
340
-
341
- .config-editor-empty {
342
- display: grid;
343
- min-height: 9rem;
344
- place-items: center;
345
- padding: 2rem;
346
- border-top: 1px solid var(--color-border);
347
- border-bottom: 1px solid var(--color-border);
348
- color: var(--color-muted-foreground);
349
- font-family: var(--font-ui);
350
- font-size: var(--type-sm);
351
- line-height: 1.45;
352
- text-align: center;
353
- }
354
-
355
- .config-editor-empty p {
356
- max-width: 28rem;
357
- margin: 0;
358
- }
359
-
360
- @media (hover: hover) and (pointer: fine) {
361
- .config-editor-row .config-editor-reset {
362
- opacity: 0;
363
- pointer-events: none;
364
- }
365
-
366
- .config-editor-row:hover .config-editor-reset,
367
- .config-editor-row:focus-within .config-editor-reset {
368
- opacity: 1;
369
- pointer-events: auto;
370
- }
371
- }
372
-
373
- @media (max-width: 760px) {
374
- .config-editor-row {
375
- grid-template-columns: minmax(0, 1fr);
376
- align-items: stretch;
377
- gap: 0.62rem;
378
- padding-block: 0.85rem;
379
- }
380
-
381
- .config-editor-control-row > input[role="switch"] {
382
- justify-self: start;
383
- }
384
-
385
- .config-editor-fallback-value {
386
- text-align: left;
387
- }
388
- }
389
27
  }
390
28
 
391
29
  .search-snippet {
@@ -481,20 +119,6 @@ svg[stroke-width].icon-fine {
481
119
  }
482
120
  }
483
121
 
484
- .toast-copy {
485
- @apply shrink-0 translate-y-0.5 cursor-pointer rounded-sm p-0 border-0 bg-transparent;
486
- color: var(--color-muted-foreground);
487
- transition: color 0.15s;
488
-
489
- &:hover {
490
- color: var(--color-foreground);
491
- }
492
-
493
- > svg {
494
- @apply size-3.5;
495
- }
496
- }
497
-
498
122
  .toast-out {
499
123
  animation: toast-out 0.3s ease-in forwards;
500
124
  }
@@ -522,159 +146,10 @@ svg[stroke-width].icon-fine {
522
146
 
523
147
  /* Admin header */
524
148
  @layer components {
525
- .dash-header {
526
- padding: 20px 0 0;
527
- }
528
-
529
- @media (min-width: 700px) {
530
- .dash-header {
531
- padding: 24px 0 0;
532
- }
533
- }
534
-
535
- .dash-header-inner {
536
- display: flex;
537
- align-items: center;
538
- gap: 16px;
539
- padding-bottom: 12px;
540
- }
541
-
542
- .dash-header-avatar-link {
543
- flex-shrink: 0;
544
- line-height: 0;
545
- }
546
-
547
- .dash-header-avatar {
548
- width: 22px;
549
- height: 22px;
550
- border-radius: 5px;
551
- }
552
-
553
- .dash-header-avatar:is(img) {
554
- object-fit: cover;
555
- }
556
-
557
- .dash-header-avatar-fallback {
558
- display: flex;
559
- align-items: center;
560
- justify-content: center;
561
- color: white;
562
- font-size: var(--type-2xs);
563
- font-weight: var(--fw-semibold);
564
- line-height: 1;
565
- }
566
-
567
- .dash-header-nav {
568
- display: flex;
569
- align-items: center;
570
- gap: 16px;
571
- }
572
-
573
- .dash-header-nav-sep {
574
- display: none;
575
- }
576
-
577
- .dash-header-right {
578
- display: flex;
579
- align-items: center;
580
- gap: 8px;
581
- margin-left: auto;
582
- }
583
-
584
- .dash-header-link {
585
- font-size: var(--type-xs);
586
- color: var(--color-muted-foreground);
587
- transition: color 0.15s;
588
-
589
- &:hover {
590
- color: var(--color-foreground);
591
- }
592
- }
593
-
594
- .dash-header-link-active {
595
- color: var(--color-foreground);
596
- font-weight: var(--fw-medium);
597
- }
598
-
599
- .dash-header-visit {
600
- @apply flex items-center gap-3;
601
- font-size: var(--type-sm);
602
- color: var(--color-muted-foreground);
603
- transition: color 0.15s;
604
-
605
- &:hover {
606
- color: var(--color-foreground);
607
- }
608
- }
609
-
610
- .dash-header-visit-text {
611
- display: none;
612
- }
613
-
614
- @media (min-width: 700px) {
615
- .dash-header-visit-text {
616
- display: inline;
617
- }
618
-
619
- .dash-header-visit-icon {
620
- display: none;
621
- }
622
- }
623
-
624
- .dash-header-menu-btn {
625
- @apply flex items-center justify-center;
626
- width: 32px;
627
- height: 32px;
628
- border-radius: var(--radius);
629
- border: none;
630
- background: transparent;
631
- color: var(--color-muted-foreground);
632
- cursor: pointer;
633
- transition:
634
- color 0.15s,
635
- background-color 0.15s;
636
-
637
- &:hover {
638
- color: var(--color-foreground);
639
- background-color: var(--color-accent);
640
- }
641
- }
642
-
643
- .dash-header-menu-btn + [data-popover] {
644
- min-width: 170px;
645
- }
646
149
  }
647
150
 
648
151
  /* Breadcrumb — second row below header on settings sub-pages */
649
152
  @layer components {
650
- .dash-breadcrumb {
651
- display: flex;
652
- align-items: center;
653
- flex-wrap: wrap;
654
- gap: 8px;
655
- padding: 8px 0;
656
- font-size: var(--type-base);
657
- line-height: 1.35;
658
- }
659
-
660
- .dash-breadcrumb-parent {
661
- color: var(--color-muted-foreground);
662
- transition: color 0.15s;
663
-
664
- &:hover {
665
- color: var(--color-foreground);
666
- }
667
- }
668
-
669
- .dash-breadcrumb-sep {
670
- color: var(--color-muted-foreground);
671
- opacity: 0.5;
672
- }
673
-
674
- .dash-breadcrumb-current {
675
- color: var(--color-foreground);
676
- font-weight: var(--fw-medium);
677
- }
678
153
  }
679
154
 
680
155
  /* Page intro — shared title block for top-level pages */
@@ -730,1064 +205,28 @@ svg[stroke-width].icon-fine {
730
205
 
731
206
  /* Settings root — iOS-style grouped list */
732
207
  @layer components {
733
- .settings-root {
734
- @apply flex flex-col;
735
- width: var(--layout-content-width);
736
- gap: clamp(1.15rem, 2.8vw, 1.65rem);
737
- padding-bottom: 0.15rem;
738
- }
739
-
740
- @media (max-width: 760px) {
741
- .settings-root {
742
- width: 100%;
743
- }
744
- }
745
-
746
- .settings-directory-section {
747
- @apply flex flex-col;
748
- gap: 0.22rem;
749
- }
750
-
751
- .settings-directory-section + .settings-directory-section {
752
- padding-top: 0.34rem;
753
- }
754
-
755
- .settings-directory-section-title {
756
- margin: 0;
757
- font-family: var(--font-ui);
758
- color: var(--site-text-secondary);
759
- font-size: var(--type-xs);
760
- font-weight: var(--fw-medium);
761
- line-height: 1.3;
762
- letter-spacing: 0.02em;
763
- }
764
-
765
- .settings-directory-section-title[data-tone="danger"] {
766
- color: color-mix(
767
- in srgb,
768
- var(--color-destructive) 72%,
769
- var(--site-text-secondary)
770
- );
771
- }
208
+ }
772
209
 
773
- .settings-directory-list {
774
- @apply flex flex-col;
775
- gap: 0.35rem;
776
- }
210
+ /* Admin scoped font rules */
211
+ @layer components {
212
+ }
777
213
 
778
- .settings-directory-item {
779
- @apply flex items-center w-full text-left;
780
- gap: 0.68rem;
781
- padding: 0.85rem 0.6rem 0.85rem 0;
782
- border: none;
783
- border-radius: 0.85rem;
784
- background: transparent;
785
- box-shadow: none;
786
- color: inherit;
787
- text-decoration: none;
788
- transition:
789
- background-color 0.18s ease,
790
- color 0.18s ease;
791
- }
214
+ /* Navigation preview — browser-chrome frame for nav preview */
215
+ @layer components {
216
+ }
792
217
 
793
- button.settings-directory-item {
794
- appearance: none;
795
- cursor: pointer;
796
- font: inherit;
797
- }
218
+ /* Navigation items list — card-style draggable nav items */
219
+ @layer components {
220
+ }
798
221
 
799
- .settings-directory-item:hover {
800
- background: color-mix(
801
- in srgb,
802
- var(--color-foreground) 4%,
803
- var(--color-background)
804
- );
805
- }
222
+ /* Skeleton screen sizing — used in SSR fallbacks while Lit hydrates */
223
+ @layer components {
224
+ }
806
225
 
807
- .settings-directory-item:focus-visible {
808
- outline: 2px solid color-mix(in srgb, var(--site-accent) 28%, transparent);
809
- outline-offset: 3px;
810
- background: color-mix(in srgb, var(--site-accent) 6%, var(--color-card));
811
- }
812
-
813
- .settings-directory-item[data-tone="subtle"] {
814
- color: inherit;
815
- }
816
-
817
- .settings-directory-item[data-tone="danger"] {
818
- color: inherit;
819
- }
820
-
821
- .settings-directory-item[data-tone="danger"]:hover,
822
- .settings-directory-item[data-tone="danger"]:focus-visible {
823
- background: color-mix(
824
- in srgb,
825
- var(--color-destructive) 7%,
826
- var(--color-background)
827
- );
828
- }
829
-
830
- .settings-directory-item-icon {
831
- @apply flex items-center justify-center shrink-0;
832
- width: 2.55rem;
833
- height: 2.55rem;
834
- border: 1px solid color-mix(in srgb, var(--color-border) 76%, white 24%);
835
- border-radius: 999px;
836
- background: transparent;
837
- color: var(--color-foreground);
838
- }
839
-
840
- .settings-directory-item[data-tone="subtle"] .settings-directory-item-icon {
841
- color: color-mix(
842
- in srgb,
843
- var(--color-foreground) 86%,
844
- var(--color-muted-foreground)
845
- );
846
- }
847
-
848
- .settings-directory-item[data-tone="danger"] .settings-directory-item-icon {
849
- border-color: color-mix(
850
- in srgb,
851
- var(--color-destructive) 16%,
852
- var(--color-border)
853
- );
854
- color: color-mix(
855
- in srgb,
856
- var(--color-destructive) 86%,
857
- var(--color-foreground)
858
- );
859
- }
860
-
861
- .settings-directory-item-icon svg {
862
- width: 1.08rem;
863
- height: 1.08rem;
864
- stroke-width: 1.9;
865
- }
866
-
867
- .settings-directory-item-copy {
868
- @apply flex flex-col flex-1 min-w-0;
869
- gap: 0.3rem;
870
- }
871
-
872
- .settings-directory-item-name {
873
- font-family: var(--font-ui);
874
- font-size: var(--type-secondary);
875
- font-weight: var(--fw-regular);
876
- line-height: 1.3;
877
- color: var(--color-foreground);
878
- text-wrap: pretty;
879
- }
880
-
881
- .settings-directory-item-desc {
882
- font-family: var(--font-ui);
883
- font-size: var(--type-sm);
884
- line-height: 1.4;
885
- color: var(--muted-foreground);
886
- text-wrap: pretty;
887
- }
888
-
889
- .settings-directory-item-chevron {
890
- @apply shrink-0;
891
- color: color-mix(
892
- in srgb,
893
- var(--color-muted-foreground) 82%,
894
- var(--color-foreground)
895
- );
896
- opacity: 0.72;
897
- transition:
898
- transform 0.18s ease,
899
- opacity 0.18s ease,
900
- color 0.18s ease;
901
- }
902
-
903
- .settings-directory-item:hover .settings-directory-item-chevron,
904
- .settings-directory-item:focus-visible .settings-directory-item-chevron {
905
- transform: translateX(1px);
906
- opacity: 1;
907
- color: color-mix(
908
- in srgb,
909
- var(--color-foreground) 62%,
910
- var(--color-muted-foreground)
911
- );
912
- }
913
-
914
- .settings-root-version {
915
- text-align: center;
916
- font-size: var(--type-2xs);
917
- font-family: var(--font-mono, monospace);
918
- color: var(--color-muted-foreground);
919
- opacity: 0.45;
920
- margin: 0 0 0.6rem;
921
- user-select: all;
922
- }
923
-
924
- .settings-root-version-link {
925
- color: inherit;
926
- text-decoration: underline;
927
- text-decoration-style: dotted;
928
- text-underline-offset: 2px;
929
- }
930
-
931
- .settings-root-version-link:hover {
932
- opacity: 0.75;
933
- }
934
-
935
- .settings-root-signout {
936
- @apply flex justify-center;
937
- padding-top: 0.1rem;
938
- }
939
-
940
- .settings-root-signout-btn {
941
- @apply inline-flex items-center justify-center cursor-pointer;
942
- min-height: 1.8rem;
943
- padding: 0;
944
- border: none;
945
- background: transparent;
946
- color: var(--color-destructive);
947
- font-size: var(--type-xs);
948
- font-weight: var(--fw-medium);
949
- letter-spacing: -0.01em;
950
- transition:
951
- opacity 0.18s ease,
952
- color 0.18s ease;
953
- }
954
-
955
- .settings-root-signout-btn:hover,
956
- .settings-root-signout-btn:focus-visible {
957
- opacity: 0.78;
958
- }
959
-
960
- .settings-root-signout-btn:focus-visible {
961
- outline: 2px solid
962
- color-mix(in srgb, var(--color-destructive) 28%, transparent);
963
- outline-offset: 3px;
964
- }
965
-
966
- .settings-group-label {
967
- margin: 0 0 0.55rem;
968
- padding-inline: 0.15rem;
969
- font-size: var(--type-xs);
970
- font-weight: var(--fw-medium);
971
- line-height: 1.3;
972
- letter-spacing: 0.04em;
973
- color: color-mix(
974
- in srgb,
975
- var(--color-foreground) 72%,
976
- var(--color-muted-foreground)
977
- );
978
- }
979
-
980
- .settings-group {
981
- overflow: hidden;
982
- border: 1px solid
983
- color-mix(in srgb, var(--color-border) 84%, var(--site-accent) 8%);
984
- border-radius: 0.95rem;
985
- background-color: color-mix(
986
- in srgb,
987
- var(--color-card) 97%,
988
- var(--site-accent) 3%
989
- );
990
- box-shadow: 0 10px 24px -22px
991
- color-mix(in srgb, var(--color-foreground) 18%, transparent);
992
- }
993
-
994
- .settings-item {
995
- @apply flex items-center;
996
- gap: 0.75rem;
997
- padding: 0.82rem 0.9rem;
998
- --settings-item-icon-accent: var(--site-accent);
999
- --settings-item-icon-bg-strength: 13%;
1000
- --settings-item-icon-border-strength: 22%;
1001
- --settings-item-icon-fg-strength: 70%;
1002
- transition:
1003
- background-color 0.18s ease,
1004
- border-color 0.18s ease;
1005
- border-bottom: 1px solid
1006
- color-mix(in srgb, var(--color-border) 78%, transparent);
1007
-
1008
- &:last-child {
1009
- border-bottom: none;
1010
- }
1011
-
1012
- &:hover {
1013
- background-color: color-mix(
1014
- in srgb,
1015
- var(--settings-item-icon-accent) 5%,
1016
- var(--color-card)
1017
- );
1018
- }
1019
-
1020
- &:focus-visible {
1021
- outline: 2px solid
1022
- color-mix(in srgb, var(--settings-item-icon-accent) 24%, transparent);
1023
- outline-offset: -2px;
1024
- background-color: color-mix(
1025
- in srgb,
1026
- var(--settings-item-icon-accent) 6%,
1027
- var(--color-card)
1028
- );
1029
- }
1030
- }
1031
-
1032
- .settings-item[data-tone="subtle"] {
1033
- --settings-item-icon-bg-strength: 8%;
1034
- --settings-item-icon-border-strength: 16%;
1035
- --settings-item-icon-fg-strength: 56%;
1036
- }
1037
-
1038
- .settings-item[data-tone="danger"] {
1039
- --settings-item-icon-accent: var(--color-destructive);
1040
- --settings-item-icon-bg-strength: 10%;
1041
- --settings-item-icon-border-strength: 20%;
1042
- --settings-item-icon-fg-strength: 76%;
1043
- }
1044
-
1045
- .settings-item-icon {
1046
- @apply flex items-center justify-center shrink-0;
1047
- width: 28px;
1048
- height: 28px;
1049
- border-radius: 8px;
1050
- border: 1px solid
1051
- color-mix(
1052
- in srgb,
1053
- var(--settings-item-icon-accent)
1054
- var(--settings-item-icon-border-strength),
1055
- var(--color-border)
1056
- );
1057
- background-color: color-mix(
1058
- in srgb,
1059
- var(--settings-item-icon-accent) var(--settings-item-icon-bg-strength),
1060
- var(--color-card)
1061
- );
1062
- color: color-mix(
1063
- in srgb,
1064
- var(--settings-item-icon-accent) var(--settings-item-icon-fg-strength),
1065
- var(--color-foreground)
1066
- );
1067
- transition:
1068
- background-color 0.18s ease,
1069
- border-color 0.18s ease,
1070
- color 0.18s ease;
1071
- }
1072
-
1073
- .settings-item-text {
1074
- @apply flex flex-col flex-1 min-w-0;
1075
- gap: 0.08rem;
1076
- }
1077
-
1078
- .settings-item-name {
1079
- font-size: var(--type-base);
1080
- font-weight: var(--fw-medium);
1081
- line-height: 1.3;
1082
- color: var(--color-foreground);
1083
- }
1084
-
1085
- .settings-item-desc {
1086
- font-family: var(--font-ui);
1087
- font-size: var(--type-xs);
1088
- line-height: 1.4;
1089
- color: var(--color-muted-foreground);
1090
- }
1091
-
1092
- .settings-item-chevron {
1093
- @apply shrink-0;
1094
- color: var(--color-muted-foreground);
1095
- opacity: 0.38;
1096
- transition:
1097
- opacity 0.18s ease,
1098
- color 0.18s ease;
1099
- }
1100
-
1101
- .settings-item:hover .settings-item-chevron,
1102
- .settings-item:focus-visible .settings-item-chevron {
1103
- opacity: 0.62;
1104
- color: color-mix(
1105
- in srgb,
1106
- var(--color-foreground) 46%,
1107
- var(--color-muted-foreground)
1108
- );
1109
- }
1110
-
1111
- .settings-export-form {
1112
- display: block;
1113
- }
1114
-
1115
- @media (max-width: 699px) {
1116
- .settings-directory-item {
1117
- gap: 0.62rem;
1118
- padding: 0.78rem 0.52rem 0.78rem 0;
1119
- border-radius: 0.8rem;
1120
- }
1121
-
1122
- .settings-directory-item-icon {
1123
- width: 2.38rem;
1124
- height: 2.38rem;
1125
- }
1126
-
1127
- .settings-root-version {
1128
- text-align: left;
1129
- }
1130
-
1131
- .settings-root-signout {
1132
- justify-content: flex-start;
1133
- }
1134
- }
1135
-
1136
- button.settings-item {
1137
- @apply w-full text-left cursor-pointer;
1138
- background: none;
1139
- border: none;
1140
- font: inherit;
1141
- border-bottom: 1px solid
1142
- color-mix(in srgb, var(--color-border) 78%, transparent);
1143
-
1144
- &:last-child {
1145
- border-bottom: none;
1146
- }
1147
- }
1148
-
1149
- .custom-url-row {
1150
- position: relative;
1151
- display: flex;
1152
- align-items: stretch;
1153
- padding: 0.8rem 0.9rem 0.78rem;
1154
- transition: background-color 0.18s ease;
1155
- border-bottom: 1px solid
1156
- color-mix(in srgb, var(--color-border) 78%, transparent);
1157
-
1158
- &:last-child {
1159
- border-bottom: none;
1160
- }
1161
-
1162
- &:hover {
1163
- background-color: color-mix(
1164
- in srgb,
1165
- var(--site-accent) 4%,
1166
- var(--color-card)
1167
- );
1168
- }
1169
-
1170
- &:focus-within {
1171
- background-color: color-mix(
1172
- in srgb,
1173
- var(--site-accent) 5%,
1174
- var(--color-card)
1175
- );
1176
- }
1177
- }
1178
-
1179
- .custom-url-row-main {
1180
- display: flex;
1181
- flex: 1;
1182
- min-width: 0;
1183
- flex-direction: column;
1184
- gap: 0.28rem;
1185
- padding-right: 2.1rem;
1186
- }
1187
-
1188
- .custom-url-row-header {
1189
- position: relative;
1190
- min-width: 0;
1191
- }
1192
-
1193
- .custom-url-row-flow {
1194
- display: flex;
1195
- flex-direction: column;
1196
- align-items: flex-start;
1197
- gap: 0.16rem;
1198
- min-width: 0;
1199
- padding-top: 0.04rem;
1200
- }
1201
-
1202
- .custom-url-row-target {
1203
- display: flex;
1204
- flex-wrap: wrap;
1205
- align-items: flex-start;
1206
- gap: 0.24rem 0.56rem;
1207
- min-width: 0;
1208
- }
1209
-
1210
- .custom-url-row-menu {
1211
- position: absolute;
1212
- top: -0.18rem;
1213
- right: -0.24rem;
1214
- z-index: 2;
1215
- }
1216
-
1217
- .custom-url-path {
1218
- display: block;
1219
- min-width: 0;
1220
- overflow-wrap: anywhere;
1221
- font-size: var(--type-base);
1222
- line-height: 1.3;
1223
- letter-spacing: -0.018em;
1224
- color: color-mix(
1225
- in srgb,
1226
- var(--color-foreground) 94%,
1227
- var(--site-accent) 6%
1228
- );
1229
- }
1230
-
1231
- .custom-url-target-path {
1232
- display: inline;
1233
- max-width: 100%;
1234
- overflow-wrap: anywhere;
1235
- font-size: var(--type-xs);
1236
- line-height: 1.4;
1237
- letter-spacing: -0.01em;
1238
- color: color-mix(
1239
- in srgb,
1240
- var(--color-foreground) 74%,
1241
- var(--color-muted-foreground)
1242
- );
1243
- }
1244
-
1245
- .custom-url-menu-trigger {
1246
- @apply flex items-center justify-center cursor-pointer;
1247
- width: 1.75rem;
1248
- height: 1.75rem;
1249
- border: 1px solid transparent;
1250
- border-radius: 999px;
1251
- background: transparent;
1252
- color: color-mix(
1253
- in srgb,
1254
- var(--color-muted-foreground) 88%,
1255
- var(--color-foreground)
1256
- );
1257
- transition:
1258
- background-color 0.18s ease,
1259
- border-color 0.18s ease,
1260
- color 0.18s ease;
1261
-
1262
- &:hover {
1263
- background-color: color-mix(
1264
- in srgb,
1265
- var(--site-accent) 5%,
1266
- var(--color-card)
1267
- );
1268
- border-color: color-mix(
1269
- in srgb,
1270
- var(--color-border) 72%,
1271
- var(--site-accent) 12%
1272
- );
1273
- color: var(--color-foreground);
1274
- }
1275
-
1276
- &:focus-visible {
1277
- outline: 2px solid color-mix(in srgb, var(--site-accent) 20%, transparent);
1278
- outline-offset: 2px;
1279
- background-color: color-mix(
1280
- in srgb,
1281
- var(--site-accent) 6%,
1282
- var(--color-card)
1283
- );
1284
- border-color: color-mix(
1285
- in srgb,
1286
- var(--color-border) 72%,
1287
- var(--site-accent) 14%
1288
- );
1289
- color: var(--color-foreground);
1290
- }
1291
- }
1292
-
1293
- .custom-url-flow-arrow {
1294
- @apply flex items-center justify-center;
1295
- width: 0.9rem;
1296
- height: 0.9rem;
1297
- color: color-mix(
1298
- in srgb,
1299
- var(--color-muted-foreground) 82%,
1300
- var(--site-accent) 18%
1301
- );
1302
- opacity: 0.7;
1303
- }
1304
-
1305
- .custom-url-menu {
1306
- position: absolute;
1307
- right: 0;
1308
- top: calc(100% + 0.35rem);
1309
- z-index: 30;
1310
- min-width: 8.5rem;
1311
- padding: 0.35rem;
1312
- border: 1px solid
1313
- color-mix(in srgb, var(--color-border) 84%, var(--site-accent) 8%);
1314
- border-radius: 0.85rem;
1315
- background-color: color-mix(
1316
- in srgb,
1317
- var(--color-card) 98%,
1318
- var(--site-accent) 2%
1319
- );
1320
- box-shadow: 0 20px 38px -28px
1321
- color-mix(in srgb, var(--color-foreground) 26%, transparent);
1322
- }
1323
-
1324
- .custom-url-menu-item {
1325
- @apply w-full text-left cursor-pointer;
1326
- border: none;
1327
- background: transparent;
1328
- border-radius: 0.6rem;
1329
- padding: 0.58rem 0.72rem;
1330
- font-size: var(--type-sm);
1331
- line-height: 1.35;
1332
- color: var(--color-foreground);
1333
- transition:
1334
- background-color 0.18s ease,
1335
- color 0.18s ease;
1336
-
1337
- &:hover,
1338
- &:focus-visible {
1339
- background-color: color-mix(
1340
- in srgb,
1341
- var(--site-accent) 7%,
1342
- var(--color-card)
1343
- );
1344
- color: var(--color-foreground);
1345
- outline: none;
1346
- }
1347
- }
1348
-
1349
- .custom-url-menu-item-danger {
1350
- color: var(--color-destructive);
1351
-
1352
- &:hover,
1353
- &:focus-visible {
1354
- background-color: color-mix(
1355
- in srgb,
1356
- var(--color-destructive) 8%,
1357
- var(--color-card)
1358
- );
1359
- color: var(--color-destructive);
1360
- }
1361
- }
1362
-
1363
- .custom-url-target-meta {
1364
- display: inline-flex;
1365
- flex-wrap: wrap;
1366
- align-items: center;
1367
- gap: 0.38rem;
1368
- min-width: 0;
1369
- }
1370
-
1371
- .custom-url-type-mark {
1372
- display: inline-flex;
1373
- align-items: center;
1374
- gap: 0.26rem;
1375
- font-size: var(--type-2xs);
1376
- line-height: 1.32;
1377
- letter-spacing: 0.02em;
1378
- color: var(--color-muted-foreground);
1379
- }
1380
-
1381
- .custom-url-type-icon {
1382
- flex-shrink: 0;
1383
- color: color-mix(
1384
- in srgb,
1385
- var(--site-accent) 28%,
1386
- var(--color-muted-foreground)
1387
- );
1388
- opacity: 0.9;
1389
- }
1390
-
1391
- .custom-url-redirect-code {
1392
- font-size: var(--type-2xs);
1393
- line-height: 1.3;
1394
- letter-spacing: 0.05em;
1395
- color: var(--color-muted-foreground);
1396
- }
1397
-
1398
- @media (max-width: 640px) {
1399
- .custom-url-row {
1400
- padding-inline: 0.8rem;
1401
- }
1402
-
1403
- .custom-url-row-main {
1404
- padding-right: 1.95rem;
1405
- }
1406
-
1407
- .custom-url-menu {
1408
- min-width: 7.75rem;
1409
- }
1410
- }
1411
- }
1412
-
1413
- /* Admin scoped font rules */
1414
- @layer components {
1415
- .dash-heading {
1416
- font-family: var(--font-ui);
1417
- }
1418
- }
1419
-
1420
- /* Navigation preview — browser-chrome frame for nav preview */
1421
- @layer components {
1422
- .nav-preview {
1423
- @apply border rounded-lg overflow-hidden;
1424
- background-color: var(--color-card);
1425
- }
1426
-
1427
- .nav-preview-chrome {
1428
- @apply flex items-center gap-3 px-4 py-2.5 border-b;
1429
- background-color: var(--color-muted);
1430
- }
1431
-
1432
- .nav-preview-dots {
1433
- @apply flex gap-1.5;
1434
-
1435
- > span {
1436
- @apply block size-2.5 rounded-full;
1437
- background-color: var(--color-muted-foreground);
1438
- opacity: 0.3;
1439
- }
1440
- }
1441
-
1442
- .nav-preview-label {
1443
- @apply text-xs;
1444
- color: var(--color-muted-foreground);
1445
- }
1446
-
1447
- .nav-preview-content {
1448
- @apply px-5 py-3;
1449
- }
1450
-
1451
- .nav-preview-content .site-header-top {
1452
- justify-content: flex-start;
1453
- }
1454
- }
1455
-
1456
- /* Navigation items list — card-style draggable nav items */
1457
- @layer components {
1458
- .nav-items-list {
1459
- @apply flex flex-col gap-2;
1460
- }
1461
-
1462
- .nav-items-list-drop {
1463
- min-height: 3rem;
1464
- border: 1.5px dashed
1465
- color-mix(in srgb, var(--color-border) 60%, transparent);
1466
- border-radius: 0.75rem;
1467
- padding: 0.5rem;
1468
- transition: border-color 0.15s;
1469
- }
1470
-
1471
- .nav-items-list-drop:has(.nav-item) {
1472
- border-color: transparent;
1473
- padding: 0;
1474
- }
1475
-
1476
- .nav-items-empty-hint {
1477
- display: flex;
1478
- align-items: center;
1479
- justify-content: center;
1480
- height: 100%;
1481
- min-height: 2rem;
1482
- font-size: var(--type-xs);
1483
- color: var(--muted-foreground);
1484
- opacity: 0.6;
1485
- text-align: center;
1486
- margin: 0;
1487
- }
1488
-
1489
- .nav-item {
1490
- @apply border rounded-lg;
1491
- }
1492
-
1493
- .nav-item-editing {
1494
- @apply ring-1 ring-ring;
1495
- }
1496
-
1497
- .nav-item-row {
1498
- @apply flex items-center gap-1 px-1 py-1;
1499
- }
1500
-
1501
- .nav-item-handle {
1502
- @apply flex items-center justify-center w-8 h-8 shrink-0 cursor-grab rounded;
1503
- transition: background-color 0.15s;
1504
-
1505
- &:hover {
1506
- background-color: var(--color-accent);
1507
- }
1508
-
1509
- &:active {
1510
- cursor: grabbing;
1511
- }
1512
- }
1513
-
1514
- .nav-item-info {
1515
- @apply flex flex-col flex-1 min-w-0 py-1.5 px-1.5 rounded cursor-pointer;
1516
- transition: background-color 0.15s;
1517
-
1518
- &:hover {
1519
- background-color: var(--color-accent);
1520
- }
1521
- }
1522
-
1523
- .nav-item-toggle {
1524
- @apply flex items-center justify-center w-8 h-8 shrink-0 rounded border-0 bg-transparent cursor-pointer;
1525
- color: var(--color-muted-foreground);
1526
- transition:
1527
- color 0.15s,
1528
- background-color 0.15s;
1529
-
1530
- &:hover {
1531
- color: var(--color-foreground);
1532
- background-color: var(--color-accent);
1533
- }
1534
- }
1535
-
1536
- .nav-item-edit {
1537
- @apply flex flex-col gap-3 px-4 pb-3 pt-3 border-t mx-1 mb-1;
1538
- border-color: var(--color-border);
1539
- }
1540
-
1541
- .nav-suggestions-list {
1542
- @apply flex flex-col gap-2;
1543
- }
1544
-
1545
- .nav-suggestion-item {
1546
- @apply flex items-center justify-between gap-3 rounded-lg border px-3 py-2;
1547
- }
1548
-
1549
- .nav-suggestion-info {
1550
- @apply flex min-w-0 flex-col;
1551
- }
1552
-
1553
- .nav-suggestion-title {
1554
- @apply truncate text-sm font-medium;
1555
- }
1556
-
1557
- .nav-suggestion-meta {
1558
- @apply truncate text-xs text-muted-foreground;
1559
- }
1560
-
1561
- /* Collection picker dropdown menu */
1562
- .collection-picker {
1563
- @apply absolute left-0 z-10 mt-1.5 w-64 overflow-y-auto rounded-lg border py-1.5;
1564
- max-height: 20rem;
1565
- background-color: var(--color-popover);
1566
- box-shadow: var(--shadow-md);
1567
- }
1568
-
1569
- .collection-picker-group {
1570
- @apply px-3 pb-1 pt-3 text-xs font-medium;
1571
- color: var(--color-muted-foreground);
1572
-
1573
- &:first-child {
1574
- padding-top: 0.5rem;
1575
- }
1576
- }
1577
-
1578
- .collection-picker-item {
1579
- @apply flex items-center gap-2 rounded-md text-left border-0 bg-transparent cursor-pointer;
1580
- font-size: 0.9375rem;
1581
- line-height: 1.35;
1582
- padding: 0.5rem 0.625rem;
1583
- margin: 0 0.25rem;
1584
- width: calc(100% - 0.5rem);
1585
- color: var(--color-foreground);
1586
- transition: background-color 0.1s;
1587
-
1588
- &:hover:not(:disabled) {
1589
- background-color: var(--color-accent);
1590
- }
1591
-
1592
- &:disabled {
1593
- opacity: 0.5;
1594
- cursor: not-allowed;
1595
- }
1596
- }
1597
-
1598
- .collection-picker-title {
1599
- @apply truncate flex-1;
1600
- }
1601
-
1602
- .collection-picker-footer {
1603
- @apply sticky mt-1 border-t px-1 pb-1 pt-1;
1604
- bottom: -0.375rem;
1605
- background-color: var(--color-popover);
1606
- }
1607
-
1608
- .collection-picker-create {
1609
- @apply flex w-full cursor-pointer items-center gap-1 rounded-md border-0 bg-transparent px-2 py-1.5 text-left text-sm font-normal;
1610
- color: var(--color-muted-foreground);
1611
- transition:
1612
- background-color 0.1s,
1613
- color 0.1s;
1614
-
1615
- &:hover,
1616
- &:focus-visible {
1617
- background-color: var(--color-accent);
1618
- color: var(--color-foreground);
1619
- outline: none;
1620
- }
1621
- }
1622
-
1623
- /* Page picker — a focused search/create flow inside Navigation settings */
1624
- .nav-page-dialog > .nav-page-dialog-panel {
1625
- width: min(34rem, calc(100% - 2rem));
1626
- gap: 1.25rem;
1627
- }
1628
-
1629
- .nav-page-picker-section {
1630
- min-height: 16rem;
1631
- }
1632
-
1633
- .nav-page-search-wrap {
1634
- @apply relative;
1635
-
1636
- > svg {
1637
- @apply pointer-events-none absolute left-3 top-1/2 -translate-y-1/2;
1638
- color: var(--color-muted-foreground);
1639
- }
1640
- }
1641
-
1642
- .nav-page-search-wrap .nav-page-search-input.nav-page-search-input {
1643
- padding-inline-start: 2.5rem;
1644
- }
1645
-
1646
- .nav-page-results-label {
1647
- @apply mb-1.5 mt-4 text-xs font-medium;
1648
- color: var(--color-muted-foreground);
1649
- }
1650
-
1651
- .nav-page-results {
1652
- @apply -mx-2 flex flex-col gap-1 overflow-y-auto px-2;
1653
- max-height: min(18rem, 42vh);
1654
- }
1655
-
1656
- .nav-page-result {
1657
- @apply flex w-full cursor-pointer items-center justify-between gap-3 rounded-lg border-0 bg-transparent px-3 py-2.5 text-left;
1658
- color: var(--color-foreground);
1659
- transition:
1660
- background-color 0.12s,
1661
- color 0.12s;
1662
-
1663
- &:hover:not(:disabled),
1664
- &:focus-visible,
1665
- &.nav-page-result-selected {
1666
- background-color: var(--color-accent);
1667
- outline: none;
1668
- }
1669
-
1670
- &:disabled {
1671
- cursor: not-allowed;
1672
- opacity: 0.55;
1673
- }
1674
-
1675
- > svg {
1676
- @apply shrink-0;
1677
- color: var(--color-muted-foreground);
1678
- }
1679
- }
1680
-
1681
- .nav-page-result-copy {
1682
- @apply flex min-w-0 flex-col gap-0.5;
1683
- }
1684
-
1685
- .nav-page-result-title {
1686
- @apply truncate text-sm font-medium;
1687
- }
1688
-
1689
- .nav-page-result-path {
1690
- @apply truncate text-xs;
1691
- color: var(--color-muted-foreground);
1692
- }
1693
-
1694
- .nav-page-status {
1695
- @apply flex min-h-44 items-center justify-center px-6 text-center text-sm;
1696
- color: var(--color-muted-foreground);
1697
- }
1698
-
1699
- .nav-page-dialog-footer.nav-page-dialog-footer {
1700
- @apply sm:justify-between;
1701
- }
1702
-
1703
- .nav-page-create-link {
1704
- @apply gap-2;
1705
- }
1706
-
1707
- .nav-page-spinner {
1708
- @apply size-4 shrink-0 animate-spin rounded-full border-2;
1709
- border-color: var(--color-border);
1710
- border-top-color: var(--color-foreground);
1711
- }
1712
-
1713
- .nav-page-slug-field {
1714
- @apply flex items-center overflow-hidden rounded-md border;
1715
- background-color: var(--color-background);
1716
- border-color: var(--color-input);
1717
-
1718
- &:focus-within {
1719
- border-color: var(--color-ring);
1720
- box-shadow: 0 0 0 1px var(--color-ring);
1721
- }
1722
- }
1723
-
1724
- .nav-page-slug-prefix {
1725
- @apply shrink-0 pl-3 text-sm;
1726
- color: var(--color-muted-foreground);
1727
- }
1728
-
1729
- .nav-page-slug-input.nav-page-slug-input {
1730
- @apply min-w-0 flex-1 border-0 pl-0 shadow-none outline-none;
1731
-
1732
- &:focus {
1733
- box-shadow: none;
1734
- }
1735
- }
1736
-
1737
- .nav-page-visibility-note {
1738
- @apply flex items-start gap-2 rounded-lg px-3 py-2.5 text-sm;
1739
- color: var(--color-muted-foreground);
1740
- background-color: var(--color-muted);
1741
-
1742
- > svg {
1743
- @apply mt-0.5 shrink-0;
1744
- }
1745
- }
1746
-
1747
- .nav-collection-dialog > .nav-collection-dialog-panel {
1748
- width: min(32rem, calc(100% - 2rem));
1749
- gap: 1.25rem;
1750
- }
1751
-
1752
- .nav-create-success-header {
1753
- @apply items-center text-center;
1754
- }
1755
-
1756
- .nav-create-success-icon {
1757
- @apply mb-1 flex size-10 items-center justify-center rounded-full;
1758
- color: var(--color-primary);
1759
- background-color: color-mix(in srgb, var(--color-primary) 12%, transparent);
1760
- }
1761
-
1762
- .nav-create-success-card {
1763
- @apply flex flex-col gap-1 rounded-lg border px-4 py-3;
1764
- background-color: var(--color-muted);
1765
- }
1766
- }
1767
-
1768
- /* Skeleton screen sizing — used in SSR fallbacks while Lit hydrates */
1769
- @layer components {
1770
- .skel-label {
1771
- min-height: 1.5rem;
1772
- }
1773
-
1774
- .skel-input {
1775
- height: 2.75rem;
1776
- }
1777
-
1778
- .skel-textarea {
1779
- height: 6rem;
1780
- }
1781
-
1782
- .skel-section-sm {
1783
- min-height: 180px;
1784
- }
1785
-
1786
- .skel-section-md {
1787
- min-height: 200px;
1788
- }
1789
-
1790
- .skel-section-lg {
1791
- min-height: 300px;
1792
- }
226
+ /* Progressive enhancement for the locale picker: the plain <select> beside it
227
+ is the real field until the element upgrades, at which point the element
228
+ hides it and takes over. Keeping the picker out of the layout until then
229
+ avoids showing two controls for one choice. */
230
+ jant-locale-picker:not(:defined) {
231
+ display: none;
1793
232
  }