@jant/core 0.3.35 → 0.3.37

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 (307) hide show
  1. package/bin/commands/export.js +1 -1
  2. package/bin/commands/import-site.js +529 -0
  3. package/bin/commands/reset-password.js +3 -2
  4. package/dist/client/assets/heic-to-DIRPI3VF.js +1 -0
  5. package/dist/client/assets/module-RjUF93sV.js +716 -0
  6. package/dist/client/assets/native-48B9X9Wg.js +1 -0
  7. package/dist/client/assets/url-FWFqPJPb.js +1 -0
  8. package/dist/client/client.css +1 -1
  9. package/dist/client/client.js +4564 -3013
  10. package/dist/index.js +12885 -8161
  11. package/package.json +23 -6
  12. package/src/__tests__/helpers/app.ts +10 -10
  13. package/src/__tests__/helpers/db.ts +91 -87
  14. package/src/app.tsx +157 -31
  15. package/src/auth.ts +20 -2
  16. package/src/client/archive-nav.js +187 -0
  17. package/src/client/audio-player.ts +478 -0
  18. package/src/client/audio-processor.ts +84 -0
  19. package/src/{lib → client}/avatar-upload.ts +4 -3
  20. package/src/{lib → client}/collection-form-bridge.ts +2 -2
  21. package/src/{ui → client}/components/__tests__/jant-collection-form.test.ts +26 -9
  22. package/src/client/components/__tests__/jant-compose-dialog.test.ts +1140 -0
  23. package/src/client/components/__tests__/jant-compose-editor.test.ts +504 -0
  24. package/src/{ui → client}/components/__tests__/jant-post-form.test.ts +37 -17
  25. package/src/{ui → client}/components/__tests__/jant-settings-avatar.test.ts +2 -2
  26. package/src/{ui → client}/components/__tests__/jant-settings-general.test.ts +3 -3
  27. package/src/client/components/collection-sidebar-types.ts +43 -0
  28. package/src/{ui → client}/components/collection-types.ts +3 -4
  29. package/src/client/components/compose-types.ts +174 -0
  30. package/src/client/components/jant-collection-form.ts +667 -0
  31. package/src/client/components/jant-collection-sidebar.ts +805 -0
  32. package/src/client/components/jant-compose-dialog.ts +2161 -0
  33. package/src/client/components/jant-compose-editor.ts +1813 -0
  34. package/src/client/components/jant-compose-fullscreen.ts +283 -0
  35. package/src/client/components/jant-media-lightbox.ts +259 -0
  36. package/src/{ui → client}/components/jant-nav-manager.ts +97 -298
  37. package/src/{ui → client}/components/jant-post-form.ts +141 -12
  38. package/src/client/components/jant-post-menu.ts +1019 -0
  39. package/src/{ui → client}/components/jant-settings-avatar.ts +3 -3
  40. package/src/{ui → client}/components/jant-settings-general.ts +38 -4
  41. package/src/client/components/jant-text-preview.ts +232 -0
  42. package/src/{ui → client}/components/nav-manager-types.ts +6 -18
  43. package/src/{ui → client}/components/post-form-template.ts +137 -38
  44. package/src/{ui → client}/components/post-form-types.ts +15 -4
  45. package/src/client/compose-bridge.ts +583 -0
  46. package/src/{lib → client}/image-processor.ts +26 -8
  47. package/src/client/lazy-slugify.ts +51 -0
  48. package/src/client/media-metadata.ts +247 -0
  49. package/src/client/multipart-upload.ts +160 -0
  50. package/src/{lib → client}/nav-manager-bridge.ts +1 -1
  51. package/src/{lib → client}/post-form-bridge.ts +53 -2
  52. package/src/{lib → client}/settings-bridge.ts +3 -15
  53. package/src/client/thread-context.ts +140 -0
  54. package/src/client/tiptap/bubble-menu.ts +205 -0
  55. package/src/client/tiptap/create-editor.ts +86 -0
  56. package/src/client/tiptap/exitable-marks.ts +73 -0
  57. package/src/client/tiptap/extensions.ts +65 -0
  58. package/src/client/tiptap/image-node.ts +482 -0
  59. package/src/client/tiptap/link-toolbar.ts +371 -0
  60. package/src/client/tiptap/more-break.ts +50 -0
  61. package/src/client/tiptap/paste-image.ts +129 -0
  62. package/src/client/tiptap/slash-commands.ts +438 -0
  63. package/src/{lib → client}/toast.ts +101 -3
  64. package/src/client/types/sortablejs.d.ts +44 -0
  65. package/src/client/upload-with-metadata.ts +54 -0
  66. package/src/client/video-processor.ts +207 -0
  67. package/src/client.ts +27 -17
  68. package/src/db/__tests__/migrations.test.ts +118 -0
  69. package/src/db/index.ts +52 -0
  70. package/src/db/migrations/0000_baseline.sql +269 -0
  71. package/src/db/migrations/0001_fts_setup.sql +31 -0
  72. package/src/db/migrations/meta/0000_snapshot.json +703 -119
  73. package/src/db/migrations/meta/0001_snapshot.json +1337 -0
  74. package/src/db/migrations/meta/_journal.json +4 -39
  75. package/src/db/schema.ts +409 -140
  76. package/src/i18n/__tests__/detect.test.ts +115 -0
  77. package/src/i18n/context.tsx +2 -2
  78. package/src/i18n/detect.ts +85 -1
  79. package/src/i18n/i18n.ts +1 -1
  80. package/src/i18n/index.ts +2 -1
  81. package/src/i18n/locales/en.po +783 -1087
  82. package/src/i18n/locales/en.ts +1 -1
  83. package/src/i18n/locales/zh-Hans.po +867 -812
  84. package/src/i18n/locales/zh-Hans.ts +1 -1
  85. package/src/i18n/locales/zh-Hant.po +878 -823
  86. package/src/i18n/locales/zh-Hant.ts +1 -1
  87. package/src/i18n/middleware.ts +6 -0
  88. package/src/index.ts +5 -7
  89. package/src/lib/__tests__/blurhash-placeholder.test.ts +75 -0
  90. package/src/lib/__tests__/constants.test.ts +0 -1
  91. package/src/lib/__tests__/markdown-to-tiptap.test.ts +358 -0
  92. package/src/lib/__tests__/nanoid.test.ts +26 -0
  93. package/src/lib/__tests__/resolve-config.test.ts +2 -2
  94. package/src/lib/__tests__/schemas.test.ts +186 -65
  95. package/src/lib/__tests__/slug.test.ts +126 -0
  96. package/src/lib/__tests__/sse.test.ts +6 -6
  97. package/src/lib/__tests__/summary.test.ts +264 -0
  98. package/src/lib/__tests__/theme.test.ts +1 -1
  99. package/src/lib/__tests__/timeline.test.ts +33 -30
  100. package/src/lib/__tests__/tiptap-to-markdown.test.ts +346 -0
  101. package/src/lib/__tests__/url.test.ts +2 -2
  102. package/src/lib/__tests__/view.test.ts +140 -65
  103. package/src/lib/blurhash-placeholder.ts +102 -0
  104. package/src/lib/constants.ts +3 -1
  105. package/src/lib/emoji-catalog.ts +963 -0
  106. package/src/lib/errors.ts +11 -8
  107. package/src/lib/feed.ts +77 -31
  108. package/src/lib/html.ts +2 -1
  109. package/src/lib/icon-catalog.ts +5033 -1
  110. package/src/lib/icons.ts +3 -2
  111. package/src/lib/index.ts +0 -1
  112. package/src/lib/markdown-to-tiptap.ts +286 -0
  113. package/src/lib/media-helpers.ts +22 -12
  114. package/src/lib/nanoid.ts +29 -0
  115. package/src/lib/navigation.ts +1 -1
  116. package/src/lib/render.tsx +24 -5
  117. package/src/lib/resolve-config.ts +13 -2
  118. package/src/lib/schemas.ts +226 -58
  119. package/src/lib/search-snippet.ts +34 -0
  120. package/src/lib/slug.ts +96 -0
  121. package/src/lib/sse.ts +6 -6
  122. package/src/lib/storage.ts +115 -7
  123. package/src/lib/summary.ts +158 -0
  124. package/src/lib/theme.ts +11 -8
  125. package/src/lib/timeline.ts +76 -34
  126. package/src/lib/tiptap-render.ts +191 -0
  127. package/src/lib/tiptap-to-markdown.ts +305 -0
  128. package/src/lib/upload.ts +263 -14
  129. package/src/lib/url.ts +37 -22
  130. package/src/lib/view.ts +236 -55
  131. package/src/middleware/__tests__/auth.test.ts +191 -11
  132. package/src/middleware/__tests__/onboarding.test.ts +12 -10
  133. package/src/middleware/auth.ts +63 -9
  134. package/src/middleware/error-handler.ts +3 -3
  135. package/src/middleware/onboarding.ts +1 -1
  136. package/src/middleware/secure-headers.ts +40 -0
  137. package/src/preset.css +83 -2
  138. package/src/routes/__tests__/compose.test.ts +17 -24
  139. package/src/routes/api/__tests__/collections.test.ts +109 -61
  140. package/src/routes/api/__tests__/nav-items.test.ts +46 -29
  141. package/src/routes/api/__tests__/posts.test.ts +132 -68
  142. package/src/routes/api/__tests__/search.test.ts +15 -2
  143. package/src/routes/api/__tests__/upload-multipart.test.ts +534 -0
  144. package/src/routes/api/collections.ts +57 -31
  145. package/src/routes/api/custom-urls.ts +80 -0
  146. package/src/routes/api/export.ts +31 -0
  147. package/src/routes/api/nav-items.ts +23 -19
  148. package/src/routes/api/posts.ts +81 -62
  149. package/src/routes/api/search.ts +3 -4
  150. package/src/routes/api/upload-multipart.ts +245 -0
  151. package/src/routes/api/upload.ts +92 -24
  152. package/src/routes/auth/__tests__/setup.test.ts +20 -60
  153. package/src/routes/auth/reset.tsx +5 -4
  154. package/src/routes/auth/setup.tsx +39 -31
  155. package/src/routes/auth/signin.tsx +13 -14
  156. package/src/routes/compose.tsx +27 -63
  157. package/src/routes/dash/__tests__/settings-avatar.test.ts +44 -9
  158. package/src/routes/dash/custom-urls.tsx +414 -0
  159. package/src/routes/dash/settings.tsx +475 -99
  160. package/src/routes/feed/__tests__/rss.test.ts +22 -23
  161. package/src/routes/feed/rss.ts +6 -2
  162. package/src/routes/feed/sitemap.ts +2 -12
  163. package/src/routes/pages/__tests__/collections.test.ts +5 -6
  164. package/src/routes/pages/__tests__/featured.test.ts +36 -18
  165. package/src/routes/pages/archive.tsx +177 -37
  166. package/src/routes/pages/collection.tsx +43 -14
  167. package/src/routes/pages/collections.tsx +11 -2
  168. package/src/routes/pages/featured.tsx +27 -3
  169. package/src/routes/pages/home.tsx +15 -14
  170. package/src/routes/pages/latest.tsx +1 -11
  171. package/src/routes/pages/new.tsx +39 -0
  172. package/src/routes/pages/page.tsx +95 -49
  173. package/src/routes/pages/search.tsx +1 -1
  174. package/src/services/__tests__/api-token.test.ts +135 -0
  175. package/src/services/__tests__/collection.test.ts +275 -227
  176. package/src/services/__tests__/custom-url.test.ts +213 -0
  177. package/src/services/__tests__/media.test.ts +162 -22
  178. package/src/services/__tests__/navigation.test.ts +109 -68
  179. package/src/services/__tests__/post-timeline.test.ts +205 -32
  180. package/src/services/__tests__/post.test.ts +800 -230
  181. package/src/services/__tests__/search.test.ts +67 -10
  182. package/src/services/__tests__/settings.test.ts +3 -3
  183. package/src/services/api-token.ts +166 -0
  184. package/src/services/auth.ts +17 -2
  185. package/src/services/collection.ts +397 -131
  186. package/src/services/custom-url.ts +188 -0
  187. package/src/services/export.ts +802 -0
  188. package/src/services/index.ts +26 -19
  189. package/src/services/media.ts +100 -22
  190. package/src/services/navigation.ts +158 -47
  191. package/src/services/path.ts +339 -0
  192. package/src/services/post.ts +764 -172
  193. package/src/services/search.ts +161 -74
  194. package/src/services/settings.ts +6 -2
  195. package/src/styles/components.css +293 -62
  196. package/src/styles/tokens.css +93 -5
  197. package/src/styles/ui.css +4349 -766
  198. package/src/types/bindings.ts +8 -0
  199. package/src/types/config.ts +34 -4
  200. package/src/types/constants.ts +17 -2
  201. package/src/types/entities.ts +83 -37
  202. package/src/types/operations.ts +20 -27
  203. package/src/types/props.ts +52 -17
  204. package/src/types/views.ts +48 -24
  205. package/src/ui/color-themes.ts +133 -23
  206. package/src/ui/compose/ComposeDialog.tsx +255 -16
  207. package/src/ui/compose/ComposePrompt.tsx +1 -1
  208. package/src/ui/dash/CrudPageHeader.tsx +1 -1
  209. package/src/ui/dash/ListItemRow.tsx +1 -1
  210. package/src/ui/dash/StatusBadge.tsx +12 -2
  211. package/src/ui/dash/appearance/AdvancedContent.tsx +71 -59
  212. package/src/ui/dash/appearance/ColorThemeContent.tsx +48 -33
  213. package/src/ui/dash/appearance/FontThemeContent.tsx +65 -73
  214. package/src/ui/dash/appearance/NavigationContent.tsx +106 -135
  215. package/src/ui/dash/index.ts +0 -3
  216. package/src/ui/dash/settings/AccountContent.tsx +87 -146
  217. package/src/ui/dash/settings/AccountMenuContent.tsx +147 -0
  218. package/src/ui/dash/settings/ApiTokensContent.tsx +232 -0
  219. package/src/ui/dash/settings/AvatarContent.tsx +78 -0
  220. package/src/ui/dash/settings/GeneralContent.tsx +3 -62
  221. package/src/ui/dash/settings/SessionsContent.tsx +159 -0
  222. package/src/ui/dash/settings/SettingsRootContent.tsx +266 -0
  223. package/src/ui/feed/LinkCard.tsx +89 -40
  224. package/src/ui/feed/NoteCard.tsx +39 -25
  225. package/src/ui/feed/PostStatusBadges.tsx +67 -0
  226. package/src/ui/feed/QuoteCard.tsx +38 -23
  227. package/src/ui/feed/ThreadPreview.tsx +90 -26
  228. package/src/ui/feed/TimelineFeed.tsx +3 -2
  229. package/src/ui/feed/TimelineItem.tsx +15 -6
  230. package/src/ui/feed/__tests__/thread-preview.test.ts +107 -0
  231. package/src/ui/feed/thread-preview-state.ts +61 -0
  232. package/src/ui/font-themes.ts +2 -2
  233. package/src/ui/layouts/BaseLayout.tsx +2 -2
  234. package/src/ui/layouts/SiteLayout.tsx +116 -103
  235. package/src/ui/pages/ArchivePage.tsx +923 -95
  236. package/src/ui/pages/CollectionPage.tsx +6 -35
  237. package/src/ui/pages/CollectionsPage.tsx +2 -1
  238. package/src/ui/pages/ComposePage.tsx +54 -0
  239. package/src/ui/pages/FeaturedPage.tsx +2 -1
  240. package/src/ui/pages/HomePage.tsx +1 -1
  241. package/src/ui/pages/PostPage.tsx +30 -45
  242. package/src/ui/pages/SearchPage.tsx +182 -38
  243. package/src/ui/shared/AdminBreadcrumb.tsx +29 -0
  244. package/src/ui/shared/CollectionsSidebar.tsx +239 -4
  245. package/src/ui/shared/MediaGallery.tsx +475 -41
  246. package/src/ui/shared/PostFooter.tsx +204 -0
  247. package/src/ui/shared/StarRating.tsx +27 -0
  248. package/src/ui/shared/__tests__/format-chars.test.ts +35 -0
  249. package/src/ui/shared/index.ts +0 -1
  250. package/src/db/migrations/0000_square_wallflower.sql +0 -118
  251. package/src/db/migrations/0001_add_search_fts.sql +0 -34
  252. package/src/db/migrations/0002_add_media_attachments.sql +0 -3
  253. package/src/db/migrations/0003_add_navigation_links.sql +0 -8
  254. package/src/db/migrations/0004_add_storage_provider.sql +0 -3
  255. package/src/db/migrations/0005_v2_schema_migration.sql +0 -268
  256. package/src/db/migrations/0006_rename_slug_to_path.sql +0 -5
  257. package/src/db/migrations/0007_post_collections_m2m.sql +0 -94
  258. package/src/db/migrations/0008_add_collection_dividers.sql +0 -8
  259. package/src/db/migrations/0009_drop_collection_show_divider.sql +0 -2
  260. package/src/db/migrations/0010_add_performance_indexes.sql +0 -16
  261. package/src/db/migrations/0011_add_path_registry.sql +0 -23
  262. package/src/db/migrations/meta/0003_snapshot.json +0 -821
  263. package/src/lib/__tests__/sqid.test.ts +0 -65
  264. package/src/lib/collections-reorder.ts +0 -28
  265. package/src/lib/compose-bridge.ts +0 -280
  266. package/src/lib/media-upload.ts +0 -148
  267. package/src/lib/sqid.ts +0 -79
  268. package/src/routes/api/__tests__/pages.test.ts +0 -218
  269. package/src/routes/api/pages.ts +0 -73
  270. package/src/routes/dash/__tests__/pages.test.ts +0 -226
  271. package/src/routes/dash/appearance.tsx +0 -240
  272. package/src/routes/dash/collections.tsx +0 -211
  273. package/src/routes/dash/index.tsx +0 -103
  274. package/src/routes/dash/media.tsx +0 -132
  275. package/src/routes/dash/pages.tsx +0 -239
  276. package/src/routes/dash/posts.tsx +0 -334
  277. package/src/routes/dash/redirects.tsx +0 -257
  278. package/src/routes/pages/post.tsx +0 -59
  279. package/src/services/__tests__/page.test.ts +0 -298
  280. package/src/services/__tests__/path-registry.test.ts +0 -165
  281. package/src/services/__tests__/redirect.test.ts +0 -159
  282. package/src/services/page.ts +0 -203
  283. package/src/services/path-registry.ts +0 -160
  284. package/src/services/redirect.ts +0 -97
  285. package/src/types/sortablejs.d.ts +0 -29
  286. package/src/ui/components/__tests__/jant-compose-dialog.test.ts +0 -512
  287. package/src/ui/components/__tests__/jant-compose-editor.test.ts +0 -272
  288. package/src/ui/components/compose-types.ts +0 -75
  289. package/src/ui/components/jant-collection-form.ts +0 -512
  290. package/src/ui/components/jant-compose-dialog.ts +0 -495
  291. package/src/ui/components/jant-compose-editor.ts +0 -814
  292. package/src/ui/dash/PageForm.tsx +0 -185
  293. package/src/ui/dash/PostList.tsx +0 -95
  294. package/src/ui/dash/appearance/AppearanceNav.tsx +0 -60
  295. package/src/ui/dash/collections/CollectionForm.tsx +0 -166
  296. package/src/ui/dash/collections/CollectionsListContent.tsx +0 -146
  297. package/src/ui/dash/collections/IconPickerGrid.tsx +0 -50
  298. package/src/ui/dash/collections/ViewCollectionContent.tsx +0 -103
  299. package/src/ui/dash/media/MediaListContent.tsx +0 -201
  300. package/src/ui/dash/media/ViewMediaContent.tsx +0 -208
  301. package/src/ui/dash/pages/PagesContent.tsx +0 -74
  302. package/src/ui/dash/posts/PostForm.tsx +0 -248
  303. package/src/ui/dash/settings/SettingsNav.tsx +0 -52
  304. package/src/ui/layouts/DashLayout.tsx +0 -165
  305. package/src/ui/pages/SinglePage.tsx +0 -23
  306. package/src/ui/shared/ThreadView.tsx +0 -136
  307. /package/src/{ui → client}/components/settings-types.ts +0 -0
@@ -5,6 +5,20 @@
5
5
  * AFTER Tailwind is initialized in the user's CSS entry.
6
6
  */
7
7
 
8
+ /* Search result highlight */
9
+ mark {
10
+ background-color: var(--search-mark-bg);
11
+ color: var(--search-mark-color);
12
+ border-radius: 2px;
13
+ padding: 0 2px;
14
+ }
15
+
16
+ .search-snippet {
17
+ font-size: var(--text-sm);
18
+ color: var(--muted-foreground);
19
+ line-height: var(--leading);
20
+ }
21
+
8
22
  /* Icon stroke width — CSS property overrides SVG presentational attributes */
9
23
  svg[stroke-width] {
10
24
  stroke-width: var(--icon-stroke);
@@ -23,22 +37,22 @@ svg[stroke-width].icon-fine {
23
37
  padding-left: var(--site-padding);
24
38
  padding-right: var(--site-padding);
25
39
  }
26
-
27
- .container-sidebar {
28
- max-width: calc(
29
- var(--sidebar-width) + var(--sidebar-gap) + var(--site-width)
30
- );
31
- margin-left: auto;
32
- margin-right: auto;
33
- padding-left: var(--site-padding);
34
- padding-right: var(--site-padding);
35
- }
36
40
  }
37
41
 
38
42
  /* Toast notifications */
39
43
  @layer components {
40
44
  .toast-container {
41
- @apply fixed top-4 right-4 z-50 flex flex-col gap-2 pointer-events-none;
45
+ @apply fixed flex flex-col gap-2 pointer-events-none;
46
+ /* Override browser popover defaults for both idle and open states */
47
+ @apply inset-auto border-none bg-transparent p-0 m-0 overflow-visible;
48
+ top: 1rem;
49
+ right: 1rem;
50
+
51
+ &:popover-open {
52
+ @apply inset-auto border-none bg-transparent p-0 m-0 overflow-visible;
53
+ top: 1rem;
54
+ right: 1rem;
55
+ }
42
56
  }
43
57
 
44
58
  .toast {
@@ -64,6 +78,17 @@ svg[stroke-width].icon-fine {
64
78
  color: var(--color-destructive);
65
79
  }
66
80
 
81
+ .toast-action {
82
+ @apply shrink-0 text-xs font-medium no-underline;
83
+ color: var(--color-foreground);
84
+ opacity: 0.7;
85
+ transition: opacity 0.15s;
86
+
87
+ &:hover {
88
+ opacity: 1;
89
+ }
90
+ }
91
+
67
92
  .toast-close {
68
93
  @apply shrink-0 translate-y-0.5 cursor-pointer rounded-sm p-0 border-0 bg-transparent;
69
94
  color: var(--color-muted-foreground);
@@ -102,7 +127,7 @@ svg[stroke-width].icon-fine {
102
127
  }
103
128
  }
104
129
 
105
- /* Dashboard header */
130
+ /* Admin header */
106
131
  @layer components {
107
132
  .dash-header {
108
133
  padding: 20px 0 0;
@@ -121,29 +146,50 @@ svg[stroke-width].icon-fine {
121
146
  padding-bottom: 12px;
122
147
  }
123
148
 
124
- .dash-header-left {
149
+ .dash-header-avatar-link {
150
+ flex-shrink: 0;
151
+ line-height: 0;
152
+ }
153
+
154
+ .dash-header-avatar {
155
+ width: 22px;
156
+ height: 22px;
157
+ border-radius: 5px;
158
+ }
159
+
160
+ .dash-header-avatar:is(img) {
161
+ object-fit: cover;
162
+ }
163
+
164
+ .dash-header-avatar-fallback {
125
165
  display: flex;
126
166
  align-items: center;
127
- gap: 6px;
167
+ justify-content: center;
168
+ color: white;
169
+ font-size: 0.625rem;
170
+ font-weight: var(--fw-semibold);
171
+ line-height: 1;
128
172
  }
129
173
 
130
174
  .dash-header-nav {
131
175
  display: flex;
132
176
  align-items: center;
133
- justify-content: center;
134
- gap: 4px;
135
- flex: 1;
177
+ gap: 16px;
136
178
  }
137
179
 
138
- .dash-header-logo {
139
- font-size: 1.125rem;
140
- font-weight: 800;
141
- line-height: 1;
142
- color: var(--color-foreground);
180
+ .dash-header-nav-sep {
181
+ display: none;
143
182
  }
144
183
 
145
- .dash-header-site-link {
146
- @apply flex items-center justify-center;
184
+ .dash-header-right {
185
+ display: flex;
186
+ align-items: center;
187
+ gap: 8px;
188
+ margin-left: auto;
189
+ }
190
+
191
+ .dash-header-link {
192
+ font-size: 0.8125rem;
147
193
  color: var(--color-muted-foreground);
148
194
  transition: color 0.15s;
149
195
 
@@ -152,33 +198,41 @@ svg[stroke-width].icon-fine {
152
198
  }
153
199
  }
154
200
 
155
- .dash-header-link {
156
- position: relative;
201
+ .dash-header-link-active {
202
+ color: var(--color-foreground);
203
+ font-weight: var(--fw-medium);
204
+ }
205
+
206
+ .dash-header-visit {
207
+ @apply flex items-center gap-3;
157
208
  font-size: 0.875rem;
158
- padding: 6px 10px;
159
- border-radius: var(--radius);
160
209
  color: var(--color-muted-foreground);
161
- transition:
162
- color 0.15s,
163
- background-color 0.15s;
210
+ transition: color 0.15s;
164
211
 
165
212
  &:hover {
166
213
  color: var(--color-foreground);
167
- background-color: var(--color-accent);
168
214
  }
169
215
  }
170
216
 
171
- .dash-header-link-active {
172
- color: var(--color-foreground);
173
- font-weight: 600;
174
- background-color: var(--color-accent);
217
+ .dash-header-visit-text {
218
+ display: none;
219
+ }
220
+
221
+ @media (min-width: 700px) {
222
+ .dash-header-visit-text {
223
+ display: inline;
224
+ }
225
+
226
+ .dash-header-visit-icon {
227
+ display: none;
228
+ }
175
229
  }
176
230
 
177
231
  .dash-header-menu-btn {
178
232
  @apply flex items-center justify-center;
179
233
  width: 32px;
180
234
  height: 32px;
181
- border-radius: 999px;
235
+ border-radius: var(--radius);
182
236
  border: none;
183
237
  background: transparent;
184
238
  color: var(--color-muted-foreground);
@@ -198,33 +252,210 @@ svg[stroke-width].icon-fine {
198
252
  }
199
253
  }
200
254
 
201
- /* Sub-navigationunderline style for secondary tabs (Settings, Appearance) */
255
+ /* Breadcrumbsecond row below header on settings sub-pages */
256
+ @layer components {
257
+ .dash-breadcrumb {
258
+ display: flex;
259
+ align-items: center;
260
+ gap: 8px;
261
+ padding: 8px 0;
262
+ font-size: 0.8125rem;
263
+ }
264
+
265
+ .dash-breadcrumb-parent {
266
+ color: var(--color-muted-foreground);
267
+ transition: color 0.15s;
268
+
269
+ &:hover {
270
+ color: var(--color-foreground);
271
+ }
272
+ }
273
+
274
+ .dash-breadcrumb-sep {
275
+ color: var(--color-muted-foreground);
276
+ opacity: 0.5;
277
+ }
278
+
279
+ .dash-breadcrumb-current {
280
+ color: var(--color-foreground);
281
+ font-weight: var(--fw-medium);
282
+ }
283
+ }
284
+
285
+ /* Settings root — iOS-style grouped list */
202
286
  @layer components {
203
- .dash-subnav {
204
- @apply flex gap-4 mb-6;
205
-
206
- > a {
207
- position: relative;
208
- font-size: 0.8125rem;
209
- padding-bottom: 8px;
210
- color: var(--color-muted-foreground);
211
- transition: color 0.15s;
212
-
213
- &:hover {
214
- color: var(--color-foreground);
215
- }
216
-
217
- &.active {
218
- color: var(--color-foreground);
219
- font-weight: 500;
220
-
221
- &::after {
222
- content: "";
223
- @apply absolute inset-x-0 bottom-0 h-0.5 rounded-full;
224
- background-color: var(--color-foreground);
225
- }
226
- }
287
+ .settings-root {
288
+ @apply flex flex-col gap-6;
289
+ }
290
+
291
+ .settings-group-label {
292
+ @apply text-xs font-medium uppercase tracking-wider mb-2 px-1;
293
+ color: var(--color-muted-foreground);
294
+ }
295
+
296
+ .settings-group {
297
+ @apply border rounded-xl overflow-hidden;
298
+ border-radius: var(--dash-card-radius);
299
+ }
300
+
301
+ .settings-item {
302
+ @apply flex items-center gap-3 px-4 py-3;
303
+ transition: background-color 0.15s;
304
+ border-bottom: 1px solid var(--color-border);
305
+
306
+ &:last-child {
307
+ border-bottom: none;
227
308
  }
309
+
310
+ &:hover {
311
+ background-color: var(--color-accent);
312
+ }
313
+ }
314
+
315
+ .settings-item-icon {
316
+ @apply flex items-center justify-center shrink-0;
317
+ width: 28px;
318
+ height: 28px;
319
+ border-radius: 6px;
320
+ color: white;
321
+ }
322
+
323
+ .settings-item-text {
324
+ @apply flex flex-col flex-1 min-w-0;
325
+ }
326
+
327
+ .settings-item-name {
328
+ @apply text-sm font-medium;
329
+ color: var(--color-foreground);
330
+ }
331
+
332
+ .settings-item-desc {
333
+ @apply text-xs;
334
+ color: var(--color-muted-foreground);
335
+ }
336
+
337
+ .settings-item-chevron {
338
+ @apply shrink-0;
339
+ color: var(--color-muted-foreground);
340
+ opacity: 0.5;
341
+ }
342
+
343
+ .settings-export-form {
344
+ display: contents;
345
+ }
346
+
347
+ button.settings-item {
348
+ @apply w-full text-left cursor-pointer;
349
+ background: none;
350
+ border: none;
351
+ font: inherit;
352
+ border-bottom: 1px solid var(--color-border);
353
+
354
+ &:last-child {
355
+ border-bottom: none;
356
+ }
357
+ }
358
+ }
359
+
360
+ /* Admin scoped font rules */
361
+ @layer components {
362
+ .dash-heading {
363
+ font-family: var(--font-serif);
364
+ }
365
+ }
366
+
367
+ /* Navigation preview — browser-chrome frame for nav preview */
368
+ @layer components {
369
+ .nav-preview {
370
+ @apply border rounded-lg overflow-hidden;
371
+ background-color: var(--color-card);
372
+ }
373
+
374
+ .nav-preview-chrome {
375
+ @apply flex items-center gap-3 px-4 py-2.5 border-b;
376
+ background-color: var(--color-muted);
377
+ }
378
+
379
+ .nav-preview-dots {
380
+ @apply flex gap-1.5;
381
+
382
+ > span {
383
+ @apply block size-2.5 rounded-full;
384
+ background-color: var(--color-muted-foreground);
385
+ opacity: 0.3;
386
+ }
387
+ }
388
+
389
+ .nav-preview-label {
390
+ @apply text-xs;
391
+ color: var(--color-muted-foreground);
392
+ }
393
+
394
+ .nav-preview-content {
395
+ @apply px-5 py-3;
396
+ }
397
+ }
398
+
399
+ /* Navigation items list — card-style draggable nav items */
400
+ @layer components {
401
+ .nav-items-list {
402
+ @apply flex flex-col gap-2;
403
+ }
404
+
405
+ .nav-item {
406
+ @apply border rounded-lg transition-shadow;
407
+
408
+ &:hover {
409
+ @apply shadow-xs;
410
+ }
411
+ }
412
+
413
+ .nav-item-editing {
414
+ @apply ring-1 ring-ring;
415
+ }
416
+
417
+ .nav-item-row {
418
+ @apply flex items-center gap-1 px-1 py-1;
419
+ }
420
+
421
+ .nav-item-handle {
422
+ @apply flex items-center justify-center w-8 h-8 shrink-0 cursor-grab rounded;
423
+ transition: background-color 0.15s;
424
+
425
+ &:hover {
426
+ background-color: var(--color-accent);
427
+ }
428
+
429
+ &:active {
430
+ cursor: grabbing;
431
+ }
432
+ }
433
+
434
+ .nav-item-info {
435
+ @apply flex flex-col flex-1 min-w-0 py-1.5 px-1.5 rounded cursor-pointer;
436
+ transition: background-color 0.15s;
437
+
438
+ &:hover {
439
+ background-color: var(--color-accent);
440
+ }
441
+ }
442
+
443
+ .nav-item-toggle {
444
+ @apply flex items-center justify-center w-8 h-8 shrink-0 rounded border-0 bg-transparent cursor-pointer;
445
+ color: var(--color-muted-foreground);
446
+ transition:
447
+ color 0.15s,
448
+ background-color 0.15s;
449
+
450
+ &:hover {
451
+ color: var(--color-foreground);
452
+ background-color: var(--color-accent);
453
+ }
454
+ }
455
+
456
+ .nav-item-edit {
457
+ @apply flex flex-col gap-3 px-4 pb-3 pt-3 border-t mx-1 mb-1;
458
+ border-color: var(--color-border);
228
459
  }
229
460
  }
230
461
 
@@ -7,22 +7,39 @@
7
7
  */
8
8
 
9
9
  :root {
10
- /* Typography */
11
- --font-body: system-ui, sans-serif;
10
+ /* Typography — Font families */
11
+ --font-body:
12
+ system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
13
+ "Helvetica Neue", Helvetica, Arial, "PingFang SC", "Hiragino Sans GB",
14
+ "Microsoft YaHei", "Noto Sans CJK SC", sans-serif;
12
15
  --font-heading: var(--font-body);
13
- --font-mono: ui-monospace, monospace;
16
+ --font-serif:
17
+ ui-serif, "New York Small", "New York", "Iowan Old Style", Charter, Georgia,
18
+ "Times New Roman", Times, "Songti SC", "Noto Serif CJK SC", "STSong",
19
+ "SimSun", serif;
20
+ --font-mono:
21
+ ui-monospace, Menlo, Monaco, Consolas, "Cascadia Code", "Courier New",
22
+ monospace;
23
+
24
+ /* Typography — Font weights */
25
+ --fw-light: 300;
26
+ --fw-regular: 400;
27
+ --fw-medium: 500;
28
+ --fw-semibold: 600;
29
+ --fw-bold: 700;
30
+ --fw-extrabold: 800;
14
31
  --text-sm: 0.8125rem;
15
32
  --text-base: 0.9375rem;
16
33
  --text-lg: 1.0625rem;
17
34
  --leading: 1.5;
18
35
 
19
36
  /* Layout */
20
- --site-width: 600px;
37
+ --site-width: 500px;
21
38
  --site-padding: 1.5rem;
22
39
  --content-gap: 1rem;
23
40
  --space-xl: 2rem;
24
41
 
25
- /* Sidebar layout (dashboard + site sidebar pages) */
42
+ /* Sidebar layout (admin + site sidebar pages) */
26
43
  --sidebar-width: 12rem;
27
44
  --sidebar-gap: 2rem;
28
45
 
@@ -43,7 +60,14 @@
43
60
  --icon-stroke-fine: 1.5;
44
61
 
45
62
  /* Derived color tokens (from BaseCoat variables) */
63
+ --site-accent: var(--primary);
64
+ --site-accent-text: var(--primary-foreground);
46
65
  --site-column-outline: var(--border);
66
+ --site-border-light: color-mix(
67
+ in srgb,
68
+ var(--site-column-outline) 52%,
69
+ transparent
70
+ );
47
71
  --site-threadline: var(--border);
48
72
  --site-page-bg: var(--background);
49
73
  --site-elevated-bg: var(--background);
@@ -53,4 +77,68 @@
53
77
  --site-text-placeholder: oklch(from var(--muted-foreground) l c h / 0.5);
54
78
  --site-media-outline: var(--border);
55
79
  --site-divider: var(--border);
80
+ --site-feed-card-bg: color-mix(
81
+ in srgb,
82
+ var(--site-elevated-bg) 88%,
83
+ var(--site-nav-hover-bg)
84
+ );
85
+ --site-feed-card-border: color-mix(
86
+ in srgb,
87
+ var(--site-divider) 78%,
88
+ transparent
89
+ );
90
+ --site-feed-card-shadow: color-mix(
91
+ in srgb,
92
+ var(--site-text-primary) 12%,
93
+ transparent
94
+ );
95
+ --site-feed-divider-color: color-mix(
96
+ in srgb,
97
+ var(--site-text-secondary) 30%,
98
+ transparent
99
+ );
100
+ --site-feed-link-tint: color-mix(in srgb, var(--site-accent) 7%, transparent);
101
+ --site-feed-quote-tint: color-mix(
102
+ in srgb,
103
+ var(--site-accent) 10%,
104
+ transparent
105
+ );
106
+ --site-thread-context-bg: color-mix(
107
+ in srgb,
108
+ var(--site-nav-hover-bg) 58%,
109
+ transparent
110
+ );
111
+ --site-thread-context-border: color-mix(
112
+ in srgb,
113
+ var(--site-divider) 74%,
114
+ transparent
115
+ );
116
+ --site-thread-gap-bg: color-mix(
117
+ in srgb,
118
+ var(--site-nav-hover-bg) 42%,
119
+ transparent
120
+ );
121
+ --site-thread-item-spacing: 14px;
122
+ --site-thread-context-max-height: 188px;
123
+ --site-thread-dot-ring: color-mix(
124
+ in srgb,
125
+ var(--site-accent) 16%,
126
+ transparent
127
+ );
128
+
129
+ /* Search highlight */
130
+ --search-mark-bg: oklch(0.92 0.14 90 / 0.55);
131
+ --search-mark-color: oklch(0.35 0.09 70);
132
+
133
+ /* Admin */
134
+ --dash-bg: oklch(0.97 0.005 80);
135
+ --dash-card-radius: 10px;
136
+ }
137
+
138
+ @media (prefers-color-scheme: dark) {
139
+ :root {
140
+ --search-mark-bg: oklch(0.45 0.1 85 / 0.5);
141
+ --search-mark-color: oklch(0.92 0.08 90);
142
+ --dash-bg: oklch(0.2 0.005 80);
143
+ }
56
144
  }