collabmd 0.1.31 → 0.1.32

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 (93) hide show
  1. package/dist/client/assets/{drawio-editor-B4sHHwWJ.js → drawio-editor-Br4qyh3r.js} +1 -1
  2. package/dist/client/assets/drawioEditor-ClmnTx5J.js +2 -0
  3. package/dist/client/assets/{editor-session-BKHEYkbY.js → editor-session-Cf-iV5-3.js} +2 -2
  4. package/dist/client/assets/embedded-editor-base-CgEkjNYn.css +1 -0
  5. package/dist/client/assets/{excalidraw-editor-CHbeNZu6.js → excalidraw-editor-CXAxVhlw.js} +2 -2
  6. package/dist/client/assets/{excalidrawEditor-BhaTX2Ko.js → excalidrawEditor-DoH_kMdu.js} +2 -2
  7. package/dist/client/assets/exportDocument-9wTrBZNS.css +1 -0
  8. package/dist/client/assets/{index-kPgEYvEX.js → index-C8QZYHvV.js} +2 -2
  9. package/dist/client/assets/index-CxSbUTs2.css +1 -0
  10. package/dist/client/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2 +0 -0
  11. package/dist/client/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2 +0 -0
  12. package/dist/client/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2 +0 -0
  13. package/dist/client/assets/inter-greek-wght-normal-CkhJZR-_.woff2 +0 -0
  14. package/dist/client/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
  15. package/dist/client/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
  16. package/dist/client/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2 +0 -0
  17. package/dist/client/assets/jetbrains-mono-cyrillic-400-normal-BEIGL1Tu.woff2 +0 -0
  18. package/dist/client/assets/jetbrains-mono-cyrillic-400-normal-ugxPyKxw.woff +0 -0
  19. package/dist/client/assets/jetbrains-mono-greek-400-normal-B9oWc5Lo.woff +0 -0
  20. package/dist/client/assets/jetbrains-mono-greek-400-normal-C190GLew.woff2 +0 -0
  21. package/dist/client/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff +0 -0
  22. package/dist/client/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2 +0 -0
  23. package/dist/client/assets/jetbrains-mono-latin-ext-400-normal-Bc8Ftmh3.woff2 +0 -0
  24. package/dist/client/assets/jetbrains-mono-latin-ext-400-normal-fXTG6kC5.woff +0 -0
  25. package/dist/client/assets/jetbrains-mono-vietnamese-400-normal-CqNFfHCs.woff +0 -0
  26. package/dist/client/assets/main-BjHHMlv0.js +1249 -0
  27. package/dist/client/assets/vault-api-client-Bf9tB_GW.js +1 -0
  28. package/dist/client/assets/vault-api-client-D7Ck0CvR.css +1 -0
  29. package/dist/client/drawio-editor.html +1 -1
  30. package/dist/client/excalidraw-editor.html +1 -1
  31. package/dist/client/export-document.html +2 -2
  32. package/dist/client/index.html +2 -2
  33. package/package.json +4 -1
  34. package/src/client/app/main-entry.js +2 -0
  35. package/src/client/application/app-shell/git-feature.js +28 -36
  36. package/src/client/application/app-shell/presence-feature.js +3 -1
  37. package/src/client/application/diagram-preview-hydrator.js +24 -15
  38. package/src/client/application/mermaid-preview-hydrator.js +121 -4
  39. package/src/client/application/plantuml-preview-hydrator.js +6 -16
  40. package/src/client/application/preview-renderer.js +11 -2
  41. package/src/client/bootstrap/collabmd-app-shell.js +176 -50
  42. package/src/client/domain/excalidraw-document-switch.js +3 -0
  43. package/src/client/excalidraw-editor.js +187 -84
  44. package/src/client/infrastructure/auth-client.js +4 -4
  45. package/src/client/infrastructure/backlinks-api-client.js +18 -0
  46. package/src/client/infrastructure/comment-thread-store.js +4 -0
  47. package/src/client/infrastructure/editor-session.js +2 -0
  48. package/src/client/infrastructure/git-api-client.js +134 -0
  49. package/src/client/infrastructure/plantuml-api-client.js +21 -0
  50. package/src/client/infrastructure/vault-api-client.js +67 -0
  51. package/src/client/presentation/backlinks-panel.js +6 -9
  52. package/src/client/presentation/bases-preview-controller.js +26 -7
  53. package/src/client/presentation/excalidraw-embed-controller.js +251 -15
  54. package/src/client/presentation/excalidraw-embed-reconciler.js +0 -1
  55. package/src/client/presentation/file-action-controller.js +97 -0
  56. package/src/client/presentation/file-explorer-controller.js +2 -0
  57. package/src/client/presentation/file-explorer-view.js +368 -0
  58. package/src/client/presentation/file-history-view-controller.js +41 -40
  59. package/src/client/presentation/git-diff-view-controller.js +70 -53
  60. package/src/client/presentation/git-panel-controller.js +12 -30
  61. package/src/client/styles/export-document.css +45 -2
  62. package/src/client/styles/features/auth-gate.css +13 -24
  63. package/src/client/styles/features/comment-card.css +6 -0
  64. package/src/client/styles/features/comments-drawer.css +38 -18
  65. package/src/client/styles/features/diagram-preview.css +33 -0
  66. package/src/client/styles/features/embedded-preview.css +37 -11
  67. package/src/client/styles/features/preview-markdown.css +103 -28
  68. package/src/client/styles/foundation/themes.css +4 -0
  69. package/src/client/styles/foundation/tokens.css +4 -3
  70. package/src/client/styles/layout/sidebar.css +72 -0
  71. package/src/server/auth/auth-common.js +224 -0
  72. package/src/server/auth/auth-constants.js +30 -0
  73. package/src/server/auth/auth-strategies.js +320 -0
  74. package/src/server/auth/create-auth-service.js +24 -545
  75. package/src/server/domain/bases/base-definition.js +255 -0
  76. package/src/server/domain/bases/base-expression-runtime.js +1159 -0
  77. package/src/server/domain/bases/base-index-snapshot-store.js +418 -0
  78. package/src/server/domain/bases/base-query-results.js +205 -0
  79. package/src/server/domain/bases/base-query-service.js +68 -1965
  80. package/src/server/domain/collaboration/collaboration-room.js +36 -1
  81. package/src/server/domain/collaboration/room-client-state-store.js +1 -0
  82. package/src/server/domain/collaboration/room-persistence-controller.js +1 -1
  83. package/src/server/infrastructure/http/create-vault-api-query-handler.js +109 -1
  84. package/src/server/infrastructure/http/http-response.js +56 -0
  85. package/src/server/infrastructure/persistence/vault-file-store.js +110 -0
  86. package/dist/client/assets/drawioEditor-DGpo2hcx.js +0 -2
  87. package/dist/client/assets/embedded-editor-base-DgmRcsR8.css +0 -1
  88. package/dist/client/assets/exportDocument-DmV7Gngb.css +0 -1
  89. package/dist/client/assets/index-D69HOZHr.css +0 -1
  90. package/dist/client/assets/main-DSxNTtD-.js +0 -1243
  91. package/dist/client/assets/vault-api-client-BzHQseMN.js +0 -1
  92. package/dist/client/assets/vault-api-client-De7kMvrE.css +0 -1
  93. /package/dist/client/assets/{exportDocument-CtZKWE2c.js → exportDocument-Bia2hI25.js} +0 -0
@@ -27,11 +27,12 @@
27
27
  box-shadow:
28
28
  var(--shadow-card-strong),
29
29
  var(--shadow-sheet-inset);
30
- font-family: var(--font-display);
30
+ font-family: var(--font-body);
31
31
  }
32
32
 
33
33
  .auth-gate-card h1 {
34
34
  margin: 0 0 10px;
35
+ font-family: var(--font-display);
35
36
  font-size: var(--text-xl);
36
37
  line-height: 1.05;
37
38
  letter-spacing: -0.04em;
@@ -58,20 +59,14 @@
58
59
  }
59
60
 
60
61
  .auth-gate-input {
61
- width: 100%;
62
- padding: 14px 16px;
63
- border: 1px solid var(--color-border);
62
+ min-height: var(--control-h-lg);
64
63
  border-radius: var(--radius-xl);
65
64
  background: var(--surface-overlay);
66
65
  color: inherit;
67
- font: inherit;
68
- box-sizing: border-box;
69
66
  }
70
67
 
71
68
  .auth-gate-input:focus {
72
- outline: none;
73
- border-color: var(--color-primary);
74
- box-shadow: var(--shadow-focus);
69
+ background: var(--surface-overlay-soft);
75
70
  }
76
71
 
77
72
  .auth-gate-actions {
@@ -81,14 +76,16 @@
81
76
 
82
77
  .auth-gate-button,
83
78
  .auth-gate-secondary-button {
79
+ width: 100%;
80
+ justify-content: center;
81
+ min-height: var(--control-h-lg);
84
82
  border-radius: var(--radius-xl);
85
- font: inherit;
86
- cursor: pointer;
87
83
  transition:
88
84
  transform 160ms ease,
89
85
  box-shadow 160ms ease,
90
86
  border-color 160ms ease,
91
- background-color 160ms ease;
87
+ background-color 160ms ease,
88
+ color 160ms ease;
92
89
  }
93
90
 
94
91
  .auth-gate-button:hover,
@@ -103,15 +100,6 @@
103
100
  }
104
101
 
105
102
  .auth-gate-button {
106
- display: inline-flex;
107
- align-items: center;
108
- justify-content: center;
109
- gap: var(--space-3);
110
- width: 100%;
111
- padding: 14px 18px;
112
- border: 1px solid transparent;
113
- background: linear-gradient(135deg, var(--color-primary), var(--color-primary-hover));
114
- color: var(--color-text-inverse);
115
103
  font-weight: 600;
116
104
  box-shadow: var(--shadow-floating-soft);
117
105
  }
@@ -121,10 +109,11 @@
121
109
  }
122
110
 
123
111
  .auth-gate-secondary-button {
124
- padding: 13px 16px;
125
- border: 1px solid var(--color-border);
126
112
  background: var(--surface-overlay);
127
- color: var(--color-text);
113
+ }
114
+
115
+ .auth-gate-secondary-button:hover {
116
+ background: var(--surface-overlay-soft);
128
117
  }
129
118
 
130
119
  .auth-gate-button[disabled],
@@ -106,6 +106,12 @@
106
106
  justify-content: flex-end;
107
107
  }
108
108
 
109
+ .comment-card-input,
110
+ .comment-reply-input {
111
+ padding: var(--space-3) var(--space-4);
112
+ line-height: 1.5;
113
+ }
114
+
109
115
  .comment-card-input {
110
116
  resize: vertical;
111
117
  min-height: 88px;
@@ -12,7 +12,7 @@
12
12
  }
13
13
 
14
14
  .comments-drawer-header {
15
- padding: var(--space-4);
15
+ padding: var(--space-3);
16
16
  border-bottom: 1px solid var(--color-divider);
17
17
  background: var(--surface-comment-shell-header);
18
18
  }
@@ -34,15 +34,15 @@
34
34
  .comments-drawer-list {
35
35
  display: flex;
36
36
  flex-direction: column;
37
- gap: var(--space-3);
37
+ gap: var(--space-1);
38
38
  overflow: auto;
39
- padding: var(--space-3);
39
+ padding: calc(var(--space-2) + 2px);
40
40
  }
41
41
 
42
42
  .comments-drawer-item {
43
- --ui-record-padding: var(--space-4);
44
- --ui-record-gap: var(--space-3);
45
- --ui-record-radius: calc(var(--radius-lg) + 4px);
43
+ --ui-record-padding: calc(var(--space-2) + 2px);
44
+ --ui-record-gap: var(--space-1);
45
+ --ui-record-radius: var(--radius-lg);
46
46
  --ui-record-border: var(--border-comment-soft);
47
47
  --ui-record-bg: var(--surface-comment-record);
48
48
  --ui-record-border-hover: oklch(from var(--color-comment) l c h / 0.18);
@@ -54,16 +54,21 @@
54
54
  --ui-record-hover-transform: translateY(-1px);
55
55
  }
56
56
 
57
+ .comments-drawer-item-header {
58
+ align-items: flex-start;
59
+ }
60
+
57
61
  .comments-drawer-item-title {
58
62
  color: var(--color-comment);
59
63
  font-size: var(--text-meta);
60
64
  font-weight: 700;
61
- letter-spacing: 0.05em;
65
+ letter-spacing: 0.04em;
62
66
  text-transform: uppercase;
63
67
  }
64
68
 
65
69
  .comments-drawer-item-count {
66
- min-height: 20px;
70
+ min-height: 17px;
71
+ padding-inline: 6px;
67
72
  border: 1px solid oklch(from var(--color-comment) l c h / 0.18);
68
73
  background: var(--color-comment-soft);
69
74
  color: var(--color-comment);
@@ -71,44 +76,59 @@
71
76
  }
72
77
 
73
78
  .comments-drawer-item-quote {
74
- max-height: 9.5rem;
75
- margin: var(--space-3) 0;
79
+ max-height: 5.8rem;
80
+ margin: 0;
76
81
  overflow: auto;
77
82
  overflow-wrap: anywhere;
78
- padding: var(--space-3);
79
- padding-bottom: calc(var(--space-3) + 2px);
83
+ padding: 6px 10px;
80
84
  border: 1px solid var(--border-comment-soft);
81
- border-radius: var(--radius-lg);
85
+ border-radius: var(--radius-sm);
82
86
  background: var(--surface-comment-offset);
83
87
  color: var(--color-text-muted);
84
88
  white-space: pre-wrap;
85
89
  word-break: break-word;
86
90
  scrollbar-width: thin;
87
91
  font-family: var(--font-mono);
88
- font-size: var(--text-code-sm);
89
- line-height: 1.65;
92
+ font-size: var(--text-meta);
93
+ line-height: 1.45;
90
94
  }
91
95
 
92
96
  .comments-drawer-item-preview {
93
97
  position: relative;
94
- max-height: 7.8rem;
98
+ max-height: 3.4rem;
95
99
  overflow: hidden;
96
100
  color: var(--color-text-muted);
101
+ font-size: var(--text-label);
102
+ line-height: 1.45;
103
+ }
104
+
105
+ .comments-drawer-item-preview p,
106
+ .comments-drawer-item-preview ul,
107
+ .comments-drawer-item-preview ol,
108
+ .comments-drawer-item-preview blockquote,
109
+ .comments-drawer-item-preview pre,
110
+ .comments-drawer-item-preview .comment-markdown-table {
111
+ margin: 0;
112
+ }
113
+
114
+ .comments-drawer-item-preview > * + * {
115
+ margin-top: var(--space-1);
97
116
  }
98
117
 
99
118
  .comments-drawer-item-preview:after {
100
119
  content: '';
101
120
  position: absolute;
102
121
  inset: auto 0 0 0;
103
- height: 2.5rem;
122
+ height: 1.3rem;
104
123
  background: var(--surface-comment-preview-fade);
105
124
  pointer-events: none;
106
125
  }
107
126
 
108
127
  .comments-drawer-item-footer {
109
- align-items: flex-end;
128
+ align-items: center;
110
129
  justify-content: space-between;
111
130
  flex-wrap: wrap;
131
+ padding-top: 2px;
112
132
  color: var(--color-text-muted);
113
133
  font-size: var(--text-meta);
114
134
  font-weight: 600;
@@ -277,6 +277,16 @@ body.drawio-maximized-open::before {
277
277
  pointer-events: none;
278
278
  }
279
279
 
280
+ .excalidraw-warm-cache-root {
281
+ position: fixed;
282
+ width: 1px;
283
+ height: 1px;
284
+ overflow: hidden;
285
+ opacity: 0;
286
+ pointer-events: none;
287
+ inset: 0 auto auto 0;
288
+ }
289
+
280
290
  body.excalidraw-maximized-open {
281
291
  overflow: hidden;
282
292
  }
@@ -303,6 +313,29 @@ body.excalidraw-maximized-open .resizer {
303
313
  box-shadow: var(--shadow-elevated-soft);
304
314
  }
305
315
 
316
+ .excalidraw-embed.is-loading {
317
+ position: relative;
318
+ }
319
+
320
+ .excalidraw-embed.is-loading::after {
321
+ content: 'Loading Excalidraw...';
322
+ position: absolute;
323
+ inset: 0;
324
+ display: flex;
325
+ align-items: center;
326
+ justify-content: center;
327
+ background: color-mix(in oklab, var(--color-surface) 82%, transparent);
328
+ color: var(--color-text-muted);
329
+ font-size: var(--text-sm);
330
+ letter-spacing: 0.01em;
331
+ z-index: 2;
332
+ }
333
+
334
+ .excalidraw-embed.is-loading .excalidraw-embed-iframe {
335
+ visibility: hidden;
336
+ pointer-events: none;
337
+ }
338
+
306
339
  .excalidraw-embed-placeholder.is-hydrated {
307
340
  visibility: hidden;
308
341
  }
@@ -5,6 +5,10 @@
5
5
  background: var(--surface-media-canvas);
6
6
  }
7
7
 
8
+ .preview-content .bases-embed-placeholder {
9
+ display: block;
10
+ }
11
+
8
12
  .preview-content .video-embed,
9
13
  .preview-content .video-embed-placeholder {
10
14
  display: block;
@@ -58,43 +62,52 @@
58
62
  object-fit: contain;
59
63
  }
60
64
 
61
- .preview-content .mermaid-shell {
65
+ .preview-content .mermaid-shell,
66
+ .mermaid-maximized-root .mermaid-shell {
62
67
  display: grid;
63
68
  gap: 0;
64
69
  }
65
70
 
66
- .preview-content .mermaid-placeholder-card {
71
+ .preview-content .mermaid-placeholder-card,
72
+ .mermaid-maximized-root .mermaid-placeholder-card {
67
73
  border-radius: 0;
68
74
  }
69
75
 
70
- .preview-content .mermaid-toolbar {
76
+ .preview-content .mermaid-toolbar,
77
+ .mermaid-maximized-root .mermaid-toolbar {
71
78
  justify-content: flex-end;
72
79
  }
73
80
 
74
- .preview-content .mermaid-zoom-btn {
81
+ .preview-content .mermaid-zoom-btn,
82
+ .mermaid-maximized-root .mermaid-zoom-btn {
75
83
  min-width: 32px;
76
84
  line-height: 1.5;
77
85
  }
78
86
 
79
- .preview-content .mermaid-zoom-btn:disabled {
87
+ .preview-content .mermaid-zoom-btn:disabled,
88
+ .mermaid-maximized-root .mermaid-zoom-btn:disabled {
80
89
  opacity: 0.5;
81
90
  cursor: not-allowed;
82
91
  }
83
92
 
84
- .preview-content .mermaid-frame {
93
+ .preview-content .mermaid-frame,
94
+ .mermaid-maximized-root .mermaid-frame {
85
95
  max-width: none;
86
96
  }
87
97
 
88
- .preview-content .mermaid-frame.is-pannable {
98
+ .preview-content .mermaid-frame.is-pannable,
99
+ .mermaid-maximized-root .mermaid-frame.is-pannable {
89
100
  cursor: grab;
90
101
  }
91
102
 
92
- .preview-content .mermaid-frame.is-dragging {
103
+ .preview-content .mermaid-frame.is-dragging,
104
+ .mermaid-maximized-root .mermaid-frame.is-dragging {
93
105
  cursor: grabbing;
94
106
  user-select: none;
95
107
  }
96
108
 
97
- .preview-content .mermaid-frame svg {
109
+ .preview-content .mermaid-frame svg,
110
+ .mermaid-maximized-root .mermaid-frame svg {
98
111
  display: block;
99
112
  }
100
113
 
@@ -111,7 +124,15 @@ body.mermaid-maximized-open::before {
111
124
  backdrop-filter: blur(2px);
112
125
  }
113
126
 
114
- .preview-content .mermaid-shell.is-maximized {
127
+ .mermaid-maximized-root {
128
+ position: fixed;
129
+ inset: 0;
130
+ z-index: 171;
131
+ pointer-events: none;
132
+ }
133
+
134
+ .preview-content .mermaid-shell.is-maximized,
135
+ .mermaid-maximized-root .mermaid-shell.is-maximized {
115
136
  position: fixed;
116
137
  inset: var(--space-4);
117
138
  z-index: 171;
@@ -122,7 +143,12 @@ body.mermaid-maximized-open::before {
122
143
  grid-template-rows: auto minmax(0, 1fr);
123
144
  }
124
145
 
125
- .preview-content .mermaid-shell.is-maximized .mermaid-frame {
146
+ .mermaid-maximized-root .mermaid-shell.is-maximized {
147
+ pointer-events: auto;
148
+ }
149
+
150
+ .preview-content .mermaid-shell.is-maximized .mermaid-frame,
151
+ .mermaid-maximized-root .mermaid-shell.is-maximized .mermaid-frame {
126
152
  max-height: none;
127
153
  height: 100%;
128
154
  }
@@ -1,5 +1,18 @@
1
1
  /* ===== PREVIEW / MARKDOWN ===== */
2
2
 
3
+ .preview-content {
4
+ font-family: var(--font-prose);
5
+ }
6
+
7
+ .preview-content h1,
8
+ .preview-content h2,
9
+ .preview-content h3,
10
+ .preview-content h4,
11
+ .preview-content h5,
12
+ .preview-content h6 {
13
+ font-family: var(--font-prose);
14
+ }
15
+
3
16
  .preview-content h1 {
4
17
  margin: var(--space-8) 0 var(--space-4);
5
18
  padding-bottom: var(--space-2);
@@ -183,11 +196,12 @@
183
196
  overflow: hidden;
184
197
  }
185
198
 
199
+ .preview-content .bases-embed-placeholder > .bases-shell {
200
+ margin: 0;
201
+ }
202
+
186
203
  .preview-content .bases-toolbar {
187
- display: flex;
188
- flex-wrap: wrap;
189
- align-items: center;
190
- justify-content: space-between;
204
+ display: grid;
191
205
  gap: var(--space-3);
192
206
  padding: var(--space-4);
193
207
  border-bottom: 1px solid var(--color-divider);
@@ -195,7 +209,6 @@
195
209
 
196
210
  .preview-content .bases-toolbar-main,
197
211
  .preview-content .bases-toolbar-actions,
198
- .preview-content .bases-tabs,
199
212
  .preview-content .bases-summaries,
200
213
  .preview-content .bases-value-list {
201
214
  display: flex;
@@ -204,38 +217,90 @@
204
217
  align-items: center;
205
218
  }
206
219
 
207
- .preview-content .bases-view-tab,
220
+ .preview-content .bases-toolbar-main {
221
+ display: flex;
222
+ flex-wrap: wrap;
223
+ min-width: 0;
224
+ justify-content: flex-start;
225
+ gap: var(--space-3);
226
+ }
227
+
228
+ .preview-content .bases-tabs {
229
+ min-width: 0;
230
+ max-width: 100%;
231
+ flex-wrap: nowrap;
232
+ overflow-x: auto;
233
+ overflow-y: hidden;
234
+ scrollbar-width: none;
235
+ }
236
+
237
+ .preview-content .bases-tabs::-webkit-scrollbar {
238
+ display: none;
239
+ }
240
+
208
241
  .preview-content .bases-export-btn,
209
242
  .preview-content .bases-link-button {
210
- border: 1px solid var(--color-border);
211
- border-radius: 999px;
212
- background: var(--color-surface);
213
- color: var(--color-text);
214
- cursor: pointer;
215
- font: inherit;
243
+ flex-shrink: 0;
216
244
  }
217
245
 
218
- .preview-content .bases-view-tab,
219
- .preview-content .bases-export-btn {
220
- min-height: 34px;
221
- padding: 0 var(--space-3);
246
+ .preview-content .bases-toolbar-actions {
247
+ width: 100%;
248
+ flex-wrap: wrap;
249
+ justify-content: flex-start;
250
+ gap: var(--space-3);
251
+ }
252
+
253
+ .preview-content .bases-search-shell {
254
+ position: relative;
255
+ display: flex;
256
+ align-items: center;
257
+ flex: 1 1 320px;
258
+ width: 100%;
259
+ min-width: min(320px, 100%);
260
+ border: 1px solid color-mix(in oklab, var(--color-border) 82%, var(--color-primary) 18%);
261
+ border-radius: var(--radius-lg);
262
+ background:
263
+ linear-gradient(180deg, color-mix(in oklab, var(--color-surface) 92%, white 8%), var(--color-surface)),
264
+ var(--color-surface);
265
+ box-shadow: inset 0 1px 0 oklch(from var(--color-text) l c h / 0.04);
266
+ transition: border-color var(--transition-interactive), box-shadow var(--transition-interactive), background var(--transition-interactive);
222
267
  }
223
268
 
224
- .preview-content .bases-view-tab.is-active {
225
- background: var(--color-primary);
269
+ .preview-content .bases-search-shell:focus-within {
226
270
  border-color: var(--color-primary);
227
- color: var(--color-primary-contrast);
271
+ box-shadow: var(--shadow-focus), inset 0 1px 0 oklch(from var(--color-text) l c h / 0.04);
272
+ }
273
+
274
+ .preview-content .bases-search-icon {
275
+ position: absolute;
276
+ left: var(--space-3);
277
+ color: var(--color-text-faint);
278
+ pointer-events: none;
228
279
  }
229
280
 
230
281
  .preview-content .bases-search-input {
231
- min-width: 200px;
232
- min-height: 34px;
233
- padding: 0 var(--space-3);
234
- border: 1px solid var(--color-border);
235
- border-radius: 999px;
236
- background: var(--color-surface);
237
- color: var(--color-text);
238
- font: inherit;
282
+ min-width: 0;
283
+ border: 0;
284
+ border-radius: inherit;
285
+ background: transparent;
286
+ box-shadow: none;
287
+ padding-left: calc(var(--space-3) * 2 + 16px);
288
+ }
289
+
290
+ .preview-content .bases-search-input:focus {
291
+ border-color: transparent;
292
+ box-shadow: none;
293
+ }
294
+
295
+ .preview-content .bases-export-btn {
296
+ min-height: var(--control-h-md);
297
+ padding-inline: var(--space-4);
298
+ font-size: var(--text-sm);
299
+ font-weight: 600;
300
+ }
301
+
302
+ .preview-content .bases-export-btn:hover {
303
+ border-color: color-mix(in oklab, var(--color-border) 45%, var(--color-primary) 55%);
239
304
  }
240
305
 
241
306
  .preview-content .bases-meta,
@@ -245,6 +310,16 @@
245
310
  font-size: var(--text-ui-sm);
246
311
  }
247
312
 
313
+ .preview-content .bases-meta {
314
+ display: inline-flex;
315
+ align-items: center;
316
+ min-height: 28px;
317
+ padding: 0 var(--space-3);
318
+ border-radius: var(--radius-full);
319
+ background: color-mix(in oklab, var(--color-surface-offset) 72%, var(--color-surface));
320
+ white-space: nowrap;
321
+ }
322
+
248
323
  .preview-content .bases-summaries {
249
324
  padding: var(--space-3) var(--space-4);
250
325
  border-bottom: 1px solid var(--color-divider);
@@ -429,7 +504,7 @@
429
504
 
430
505
  .preview-content .task-list-item input[type='checkbox'] {
431
506
  position: absolute;
432
- top: 0.3em;
507
+ top: 0.5em;
433
508
  left: calc(var(--space-5) * -1);
434
509
  margin: 0;
435
510
  accent-color: var(--color-primary);
@@ -21,6 +21,7 @@
21
21
  --color-primary: #4f46e5;
22
22
  --color-primary-hover: #4338ca;
23
23
  --color-primary-active: #3730a3;
24
+ --color-primary-contrast: #f5f5f7;
24
25
  --color-primary-highlight: #e0e0ff;
25
26
  --color-comment: #4f46e5;
26
27
  --color-comment-soft: rgba(79, 70, 229, 0.08);
@@ -28,6 +29,7 @@
28
29
  --color-comment-text: #3730a3;
29
30
 
30
31
  --color-error: #dc2626;
32
+ --color-danger: #dc2626;
31
33
  --color-error-highlight: #fce8e8;
32
34
  --color-success: #16a34a;
33
35
  --color-success-highlight: #dcfce7;
@@ -140,6 +142,7 @@
140
142
  --color-primary: #818cf8;
141
143
  --color-primary-hover: #6366f1;
142
144
  --color-primary-active: #4f46e5;
145
+ --color-primary-contrast: #0f1117;
143
146
  --color-primary-highlight: #1e1e3a;
144
147
  --color-comment: #818cf8;
145
148
  --color-comment-soft: rgba(129, 140, 248, 0.1);
@@ -147,6 +150,7 @@
147
150
  --color-comment-text: #c7d2fe;
148
151
 
149
152
  --color-error: #f87171;
153
+ --color-danger: #f87171;
150
154
  --color-error-highlight: #2a1a1a;
151
155
  --color-success: #4ade80;
152
156
  --color-success-highlight: #1a2a1a;
@@ -17,9 +17,10 @@
17
17
  --text-title-sm: 15px;
18
18
  --text-title-md: 18px;
19
19
 
20
- --font-body: 'Inter', system-ui, sans-serif;
21
- --font-display: 'Geist', 'Cal Sans', 'Inter', system-ui, sans-serif;
22
- --font-mono: 'JetBrains Mono', 'Fira Code', monospace;
20
+ --font-body: 'Inter Variable', 'Inter', system-ui, sans-serif;
21
+ --font-display: 'Inter Variable', 'Inter', system-ui, sans-serif;
22
+ --font-prose: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', 'Noto Sans', 'Liberation Sans', Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
23
+ --font-mono: 'JetBrains Mono', ui-monospace, 'SFMono-Regular', 'SF Mono', monospace;
23
24
 
24
25
  --space-1: 0.25rem;
25
26
  --space-2: 0.5rem;
@@ -118,6 +118,17 @@
118
118
  overflow-x: hidden;
119
119
  overflow-y: auto;
120
120
  padding: var(--space-2) 0;
121
+ transition: box-shadow var(--transition-interactive), background var(--transition-interactive);
122
+ }
123
+
124
+ .file-tree.is-drop-target-root {
125
+ background: color-mix(in oklab, var(--color-primary-highlight) 58%, transparent);
126
+ box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--color-primary) 48%, transparent);
127
+ }
128
+
129
+ .file-tree.is-drop-invalid {
130
+ background: color-mix(in oklab, var(--color-danger) 8%, transparent);
131
+ box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--color-danger) 42%, transparent);
121
132
  }
122
133
 
123
134
  .file-tree-empty {
@@ -127,6 +138,43 @@
127
138
  font-size: var(--text-xs);
128
139
  }
129
140
 
141
+ .file-tree-root-drop-zone {
142
+ display: block;
143
+ margin: 0 var(--space-2);
144
+ margin-bottom: var(--space-2);
145
+ padding: var(--space-2) var(--space-3);
146
+ border: 1px dashed transparent;
147
+ border-radius: var(--radius-lg);
148
+ background: transparent;
149
+ color: var(--color-text-faint);
150
+ font-size: var(--text-xs);
151
+ line-height: 1.3;
152
+ opacity: 0.88;
153
+ transition:
154
+ opacity var(--transition-interactive),
155
+ border-color var(--transition-interactive),
156
+ background var(--transition-interactive),
157
+ color var(--transition-interactive);
158
+ }
159
+
160
+ .file-tree-root-drop-zone:hover {
161
+ border-color: color-mix(in oklab, var(--color-border) 85%, transparent);
162
+ background: color-mix(in oklab, var(--color-surface-offset) 72%, transparent);
163
+ color: var(--color-text);
164
+ }
165
+
166
+ .file-tree-root-drop-zone.is-drop-target {
167
+ border-color: color-mix(in oklab, var(--color-primary) 54%, transparent);
168
+ background: color-mix(in oklab, var(--color-primary-highlight) 72%, transparent);
169
+ color: var(--color-primary);
170
+ }
171
+
172
+ .file-tree-root-drop-zone.is-drop-invalid {
173
+ border-color: color-mix(in oklab, var(--color-danger) 48%, transparent);
174
+ background: color-mix(in oklab, var(--color-danger) 10%, transparent);
175
+ color: var(--color-danger);
176
+ }
177
+
130
178
  .file-tree-item {
131
179
  position: relative;
132
180
  display: flex;
@@ -151,6 +199,16 @@
151
199
  font-size: var(--text-ui-sm);
152
200
  }
153
201
 
202
+ .file-tree-item.is-dragging,
203
+ .file-tree-item[draggable='true']:active {
204
+ cursor: grabbing;
205
+ }
206
+
207
+ body.is-file-tree-dragging,
208
+ body.is-file-tree-dragging * {
209
+ cursor: grabbing !important;
210
+ }
211
+
154
212
  .file-tree-item:not([data-depth='0'])::before {
155
213
  content: '';
156
214
  position: absolute;
@@ -171,6 +229,20 @@
171
229
  color: var(--color-text);
172
230
  }
173
231
 
232
+ .file-tree-item.is-dragging {
233
+ opacity: 0.52;
234
+ }
235
+
236
+ .file-tree-dir.is-drop-target {
237
+ background: color-mix(in oklab, var(--color-primary-highlight) 78%, transparent);
238
+ color: var(--color-primary);
239
+ }
240
+
241
+ .file-tree-dir.is-drop-invalid {
242
+ background: color-mix(in oklab, var(--color-danger) 10%, transparent);
243
+ color: var(--color-danger);
244
+ }
245
+
174
246
  .file-tree-file.active {
175
247
  background: var(--color-primary-highlight);
176
248
  color: var(--color-primary);