collabmd 0.1.31 → 0.1.33

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 (99) hide show
  1. package/dist/client/assets/{drawio-editor-B4sHHwWJ.js → drawio-editor-BMTwP5mD.js} +1 -1
  2. package/dist/client/assets/drawioEditor-D6clB5OH.js +2 -0
  3. package/dist/client/assets/{editor-session-BKHEYkbY.js → editor-session-Dzy_85Wp.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-CAP9F8CB.js} +3 -3
  6. package/dist/client/assets/{excalidrawEditor-BhaTX2Ko.js → excalidrawEditor-DD4AvzYP.js} +2 -2
  7. package/dist/client/assets/exportDocument-BbkN85c4.css +1 -0
  8. package/dist/client/assets/index-BIt5EZXz.css +1 -0
  9. package/dist/client/assets/{index-kPgEYvEX.js → index-Czg_KL-i.js} +2 -2
  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-DeowJOSp.js +1368 -0
  27. package/dist/client/assets/vault-api-client-D7Ck0CvR.css +1 -0
  28. package/dist/client/assets/vault-api-client-p7h7cXKM.js +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 +8 -5
  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 +182 -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 +6 -0
  48. package/src/client/infrastructure/editor-view-adapter.js +23 -0
  49. package/src/client/infrastructure/git-api-client.js +134 -0
  50. package/src/client/infrastructure/plantuml-api-client.js +21 -0
  51. package/src/client/infrastructure/vault-api-client.js +115 -0
  52. package/src/client/presentation/backlinks-panel.js +6 -9
  53. package/src/client/presentation/bases-preview-controller.js +1413 -34
  54. package/src/client/presentation/comments-panel.js +50 -5
  55. package/src/client/presentation/excalidraw-embed-controller.js +251 -15
  56. package/src/client/presentation/excalidraw-embed-reconciler.js +0 -1
  57. package/src/client/presentation/file-action-controller.js +97 -0
  58. package/src/client/presentation/file-explorer-controller.js +2 -0
  59. package/src/client/presentation/file-explorer-view.js +368 -0
  60. package/src/client/presentation/file-history-view-controller.js +41 -40
  61. package/src/client/presentation/git-diff-view-controller.js +70 -53
  62. package/src/client/presentation/git-panel-controller.js +12 -30
  63. package/src/client/styles/components/scrollbars.css +5 -0
  64. package/src/client/styles/export-document.css +45 -2
  65. package/src/client/styles/features/auth-gate.css +13 -24
  66. package/src/client/styles/features/comment-card.css +6 -0
  67. package/src/client/styles/features/comments-drawer.css +38 -18
  68. package/src/client/styles/features/diagram-preview.css +33 -0
  69. package/src/client/styles/features/embedded-preview.css +37 -11
  70. package/src/client/styles/features/preview-markdown.css +559 -39
  71. package/src/client/styles/foundation/themes.css +4 -0
  72. package/src/client/styles/foundation/tokens.css +4 -3
  73. package/src/client/styles/layout/sidebar.css +72 -0
  74. package/src/server/auth/auth-common.js +224 -0
  75. package/src/server/auth/auth-constants.js +30 -0
  76. package/src/server/auth/auth-strategies.js +320 -0
  77. package/src/server/auth/create-auth-service.js +24 -545
  78. package/src/server/domain/backlink-index.js +177 -5
  79. package/src/server/domain/bases/base-definition.js +382 -0
  80. package/src/server/domain/bases/base-expression-runtime.js +1196 -0
  81. package/src/server/domain/bases/base-index-snapshot-store.js +565 -0
  82. package/src/server/domain/bases/base-query-metadata.js +242 -0
  83. package/src/server/domain/bases/base-query-results.js +215 -0
  84. package/src/server/domain/bases/base-query-service.js +406 -1992
  85. package/src/server/domain/bases/base-transform.js +116 -0
  86. package/src/server/domain/collaboration/collaboration-room.js +36 -1
  87. package/src/server/domain/collaboration/room-client-state-store.js +1 -0
  88. package/src/server/domain/collaboration/room-persistence-controller.js +1 -1
  89. package/src/server/infrastructure/http/create-vault-api-query-handler.js +161 -1
  90. package/src/server/infrastructure/http/http-response.js +56 -0
  91. package/src/server/infrastructure/persistence/vault-file-store.js +110 -0
  92. package/dist/client/assets/drawioEditor-DGpo2hcx.js +0 -2
  93. package/dist/client/assets/embedded-editor-base-DgmRcsR8.css +0 -1
  94. package/dist/client/assets/exportDocument-DmV7Gngb.css +0 -1
  95. package/dist/client/assets/index-D69HOZHr.css +0 -1
  96. package/dist/client/assets/main-DSxNTtD-.js +0 -1243
  97. package/dist/client/assets/vault-api-client-BzHQseMN.js +0 -1
  98. package/dist/client/assets/vault-api-client-De7kMvrE.css +0 -1
  99. /package/dist/client/assets/{exportDocument-CtZKWE2c.js → exportDocument-Zfwq1XVx.js} +0 -0
@@ -1,5 +1,4 @@
1
1
  import { escapeHtml } from '../domain/vault-utils.js';
2
- import { resolveApiUrl } from '../domain/runtime-paths.js';
3
2
  import { buttonClassNames } from './components/ui/button.js';
4
3
 
5
4
  function getPathLeaf(pathValue) {
@@ -146,6 +145,7 @@ function renderSplitRow(leftLine, rightLine) {
146
145
 
147
146
  export class GitDiffViewController {
148
147
  constructor({
148
+ gitApiClient = null,
149
149
  onBackToHistory = null,
150
150
  onCommitStaged = null,
151
151
  onOpenFile = null,
@@ -153,6 +153,7 @@ export class GitDiffViewController {
153
153
  onUnstageFile = null,
154
154
  toastController = null,
155
155
  } = {}) {
156
+ this.gitApiClient = gitApiClient;
156
157
  this.onBackToHistory = onBackToHistory;
157
158
  this.onCommitStaged = onCommitStaged;
158
159
  this.onOpenFile = onOpenFile;
@@ -176,6 +177,7 @@ export class GitDiffViewController {
176
177
  this.layoutToggle = document.getElementById('diffLayoutToggle');
177
178
  this.modeButtons = Array.from(document.querySelectorAll('[data-diff-mode]'));
178
179
  this.layoutButtons = Array.from(document.querySelectorAll('[data-diff-layout]'));
180
+ this.isActive = false;
179
181
  this.mode = 'unified';
180
182
  this.layoutMode = 'focused';
181
183
  this.source = 'workspace';
@@ -196,9 +198,22 @@ export class GitDiffViewController {
196
198
  }
197
199
 
198
200
  initialize() {
199
- this.prevButton?.addEventListener('click', () => this.navigateFile(-1));
200
- this.nextButton?.addEventListener('click', () => this.navigateFile(1));
201
+ this.prevButton?.addEventListener('click', () => {
202
+ if (!this.isActive) {
203
+ return;
204
+ }
205
+ this.navigateFile(-1);
206
+ });
207
+ this.nextButton?.addEventListener('click', () => {
208
+ if (!this.isActive) {
209
+ return;
210
+ }
211
+ this.navigateFile(1);
212
+ });
201
213
  this.backToHistoryButton?.addEventListener('click', () => {
214
+ if (!this.isActive) {
215
+ return;
216
+ }
202
217
  if (!this.commitMeta?.hash) {
203
218
  return;
204
219
  }
@@ -208,6 +223,9 @@ export class GitDiffViewController {
208
223
  });
209
224
  });
210
225
  this.openEditorButton?.addEventListener('click', () => {
226
+ if (!this.isActive) {
227
+ return;
228
+ }
211
229
  if (this.source !== 'workspace') {
212
230
  return;
213
231
  }
@@ -220,6 +238,9 @@ export class GitDiffViewController {
220
238
  this.onOpenFile?.(currentFile.path);
221
239
  });
222
240
  this.primaryActionButton?.addEventListener('click', () => {
241
+ if (!this.isActive) {
242
+ return;
243
+ }
223
244
  const action = this.getPrimaryAction();
224
245
  if (!action) {
225
246
  return;
@@ -228,9 +249,15 @@ export class GitDiffViewController {
228
249
  void this.handleFileAction(action);
229
250
  });
230
251
  this.commitButton?.addEventListener('click', () => {
252
+ if (!this.isActive) {
253
+ return;
254
+ }
231
255
  void this.handleFileAction('commit');
232
256
  });
233
257
  this.content?.addEventListener('click', (event) => {
258
+ if (!this.isActive) {
259
+ return;
260
+ }
234
261
  const loadButton = event.target instanceof Element
235
262
  ? event.target.closest('[data-load-full-diff]')
236
263
  : null;
@@ -265,6 +292,9 @@ export class GitDiffViewController {
265
292
  });
266
293
  this.modeButtons.forEach((button) => {
267
294
  button.addEventListener('click', () => {
295
+ if (!this.isActive) {
296
+ return;
297
+ }
268
298
  const nextMode = button.getAttribute('data-diff-mode');
269
299
  if (!nextMode || nextMode === this.mode) {
270
300
  return;
@@ -275,6 +305,9 @@ export class GitDiffViewController {
275
305
  });
276
306
  this.layoutButtons.forEach((button) => {
277
307
  button.addEventListener('click', () => {
308
+ if (!this.isActive) {
309
+ return;
310
+ }
278
311
  const nextLayout = button.getAttribute('data-diff-layout');
279
312
  if (!nextLayout || nextLayout === this.layoutMode) {
280
313
  return;
@@ -283,11 +316,15 @@ export class GitDiffViewController {
283
316
  });
284
317
  });
285
318
  this.scrollContainer?.addEventListener('scroll', () => {
319
+ if (!this.isActive) {
320
+ return;
321
+ }
286
322
  this.handleScrollSelection();
287
323
  });
288
324
  }
289
325
 
290
326
  hide() {
327
+ this.isActive = false;
291
328
  this.page?.classList.add('hidden');
292
329
  if (this.content) {
293
330
  this.content.innerHTML = '';
@@ -308,10 +345,10 @@ export class GitDiffViewController {
308
345
  this.historyFilePath = null;
309
346
  this.pendingAction = null;
310
347
  this.repoStatus = null;
311
- this.syncToolbar();
312
348
  }
313
349
 
314
350
  async openWorkspaceDiff({ filePath = null, scope = 'all' } = {}) {
351
+ this.isActive = true;
315
352
  this.source = 'workspace';
316
353
  this.layoutMode = 'focused';
317
354
  this.commitHash = null;
@@ -327,19 +364,11 @@ export class GitDiffViewController {
327
364
  this.renderLoading('Loading diff summary...');
328
365
 
329
366
  try {
330
- const query = new URLSearchParams();
331
- query.set('scope', scope);
332
- if (filePath) {
333
- query.set('path', filePath);
334
- }
335
- query.set('metaOnly', 'true');
336
-
337
- const response = await fetch(resolveApiUrl(`/git/diff?${query.toString()}`));
338
- const data = await response.json();
339
- if (!response.ok) {
340
- throw new Error(data.error || 'Failed to load git diff');
341
- }
342
-
367
+ const data = await this.gitApiClient.readDiff({
368
+ metaOnly: true,
369
+ path: filePath,
370
+ scope,
371
+ });
343
372
  this.data = data;
344
373
  const initialIndex = filePath
345
374
  ? Math.max(0, data.files.findIndex((file) => file.path === filePath))
@@ -368,6 +397,7 @@ export class GitDiffViewController {
368
397
  }
369
398
 
370
399
  async openCommitDiff({ hash, path = null, historyFilePath = null } = {}) {
400
+ this.isActive = true;
371
401
  this.source = 'commit';
372
402
  this.layoutMode = 'stacked';
373
403
  this.commitHash = String(hash ?? '').trim() || null;
@@ -383,16 +413,10 @@ export class GitDiffViewController {
383
413
  this.renderLoading('Loading commit summary...');
384
414
 
385
415
  try {
386
- const query = new URLSearchParams();
387
- query.set('hash', this.commitHash || '');
388
- query.set('metaOnly', 'true');
389
-
390
- const response = await fetch(resolveApiUrl(`/git/commit?${query.toString()}`));
391
- const data = await response.json();
392
- if (!response.ok) {
393
- throw new Error(data.error || 'Failed to load git commit');
394
- }
395
-
416
+ const data = await this.gitApiClient.readCommit({
417
+ hash: this.commitHash || '',
418
+ metaOnly: true,
419
+ });
396
420
  this.data = data;
397
421
  this.commitMeta = data.commit ?? null;
398
422
  const initialIndex = path
@@ -476,6 +500,9 @@ export class GitDiffViewController {
476
500
  }
477
501
 
478
502
  renderLoading(message = 'Loading git diff...') {
503
+ if (!this.isActive) {
504
+ return;
505
+ }
479
506
  this.page?.classList.remove('hidden');
480
507
  if (this.content) {
481
508
  this.content.innerHTML = `<div class="diff-empty-state">${escapeHtml(message)}</div>`;
@@ -485,6 +512,9 @@ export class GitDiffViewController {
485
512
  }
486
513
 
487
514
  renderEmpty(message) {
515
+ if (!this.isActive) {
516
+ return;
517
+ }
488
518
  this.page?.classList.remove('hidden');
489
519
  if (this.content) {
490
520
  this.content.innerHTML = `<div class="diff-empty-state">${escapeHtml(message)}</div>`;
@@ -1053,37 +1083,21 @@ export class GitDiffViewController {
1053
1083
  try {
1054
1084
  let detail;
1055
1085
  if (this.source === 'commit') {
1056
- const query = new URLSearchParams();
1057
- query.set('hash', this.commitHash || '');
1058
- query.set('path', filePath);
1059
- if (forceFullPatch) {
1060
- query.set('allowLargePatch', 'true');
1061
- }
1062
-
1063
- const response = await fetch(resolveApiUrl(`/git/commit?${query.toString()}`));
1064
- const data = await response.json();
1065
- if (!response.ok) {
1066
- throw new Error(data.error || 'Failed to load commit file diff');
1067
- }
1068
-
1086
+ const data = await this.gitApiClient.readCommit({
1087
+ allowLargePatch: forceFullPatch,
1088
+ hash: this.commitHash || '',
1089
+ path: filePath,
1090
+ });
1069
1091
  detail = {
1070
1092
  ...file,
1071
1093
  ...(data.files?.[0] ?? {}),
1072
1094
  };
1073
1095
  } else {
1074
- const query = new URLSearchParams();
1075
- query.set('scope', this.requestScope);
1076
- query.set('path', filePath);
1077
- if (forceFullPatch) {
1078
- query.set('allowLargePatch', 'true');
1079
- }
1080
-
1081
- const response = await fetch(resolveApiUrl(`/git/diff?${query.toString()}`));
1082
- const data = await response.json();
1083
- if (!response.ok) {
1084
- throw new Error(data.error || 'Failed to load file diff');
1085
- }
1086
-
1096
+ const data = await this.gitApiClient.readDiff({
1097
+ allowLargePatch: forceFullPatch,
1098
+ path: filePath,
1099
+ scope: this.requestScope,
1100
+ });
1087
1101
  detail = {
1088
1102
  ...file,
1089
1103
  ...(data.files?.[0] ?? {}),
@@ -1187,6 +1201,9 @@ export class GitDiffViewController {
1187
1201
  }
1188
1202
 
1189
1203
  render() {
1204
+ if (!this.isActive) {
1205
+ return;
1206
+ }
1190
1207
  this.page?.classList.remove('hidden');
1191
1208
 
1192
1209
  const files = this.data?.files ?? [];
@@ -1,5 +1,4 @@
1
1
  import { escapeHtml } from '../domain/vault-utils.js';
2
- import { resolveApiUrl } from '../domain/runtime-paths.js';
3
2
  import { buttonClassNames } from './components/ui/button.js';
4
3
  import { segmentedButtonClassNames, segmentedControlClassNames } from './components/ui/segmented-control.js';
5
4
 
@@ -94,6 +93,7 @@ function renderHistoryRowTitle(commit = {}) {
94
93
  export class GitPanelController {
95
94
  constructor({
96
95
  enabled = true,
96
+ gitApiClient = null,
97
97
  onCommitStaged = () => {},
98
98
  onOpenPullBackup = () => {},
99
99
  onPullBranch = () => {},
@@ -109,6 +109,7 @@ export class GitPanelController {
109
109
  toastController = null,
110
110
  } = {}) {
111
111
  this.enabled = enabled;
112
+ this.gitApiClient = gitApiClient;
112
113
  this.onCommitStaged = onCommitStaged;
113
114
  this.onOpenPullBackup = onOpenPullBackup;
114
115
  this.onPullBranch = onPullBranch;
@@ -404,21 +405,12 @@ export class GitPanelController {
404
405
  }
405
406
 
406
407
  try {
407
- const response = await fetch(resolveApiUrl(`/git/status${force ? '?force=true' : ''}`));
408
- const data = await response.json();
409
- if (!response.ok) {
410
- throw new Error(data.error || 'Failed to load git status');
411
- }
412
-
408
+ const data = await this.gitApiClient.readStatus({ force });
413
409
  this.status = data;
414
410
  this.pullBackups = [];
415
411
  if (data.isGitRepo) {
416
412
  try {
417
- const backupResponse = await fetch(resolveApiUrl('/git/pull-backups'));
418
- const backupData = await backupResponse.json();
419
- if (!backupResponse.ok) {
420
- throw new Error(backupData.error || 'Failed to load pull backups');
421
- }
413
+ const backupData = await this.gitApiClient.readPullBackups();
422
414
  this.pullBackups = Array.isArray(backupData.backups) ? backupData.backups : [];
423
415
  } catch (backupError) {
424
416
  console.error('[git-panel] Failed to load pull backups:', backupError);
@@ -501,15 +493,10 @@ export class GitPanelController {
501
493
  this.render();
502
494
 
503
495
  try {
504
- const query = new URLSearchParams();
505
- query.set('limit', String(HISTORY_PAGE_SIZE));
506
- query.set('offset', '0');
507
- const response = await fetch(resolveApiUrl(`/git/history?${query.toString()}`));
508
- const data = await response.json();
509
- if (!response.ok) {
510
- throw new Error(data.error || 'Failed to load git history');
511
- }
512
-
496
+ const data = await this.gitApiClient.readHistory({
497
+ limit: HISTORY_PAGE_SIZE,
498
+ offset: 0,
499
+ });
513
500
  this.history = {
514
501
  commits: Array.isArray(data.commits) ? data.commits : [],
515
502
  error: '',
@@ -553,15 +540,10 @@ export class GitPanelController {
553
540
  this.render();
554
541
 
555
542
  try {
556
- const query = new URLSearchParams();
557
- query.set('limit', String(HISTORY_PAGE_SIZE));
558
- query.set('offset', String(this.history.offset));
559
- const response = await fetch(resolveApiUrl(`/git/history?${query.toString()}`));
560
- const data = await response.json();
561
- if (!response.ok) {
562
- throw new Error(data.error || 'Failed to load git history');
563
- }
564
-
543
+ const data = await this.gitApiClient.readHistory({
544
+ limit: HISTORY_PAGE_SIZE,
545
+ offset: this.history.offset,
546
+ });
565
547
  const nextCommits = Array.isArray(data.commits) ? data.commits : [];
566
548
  this.history = {
567
549
  commits: [...this.history.commits, ...nextCommits],
@@ -5,6 +5,7 @@
5
5
  .file-tree,
6
6
  .git-panel,
7
7
  .diff-scroll,
8
+ .backlinks-body,
8
9
  .comments-drawer-list,
9
10
  .comments-drawer-item-quote,
10
11
  .comment-card-quote,
@@ -26,6 +27,7 @@
26
27
  .file-tree::-webkit-scrollbar,
27
28
  .git-panel::-webkit-scrollbar,
28
29
  .diff-scroll::-webkit-scrollbar,
30
+ .backlinks-body::-webkit-scrollbar,
29
31
  .comments-drawer-list::-webkit-scrollbar,
30
32
  .comments-drawer-item-quote::-webkit-scrollbar,
31
33
  .comment-card-quote::-webkit-scrollbar,
@@ -47,6 +49,7 @@
47
49
  .file-tree::-webkit-scrollbar-track,
48
50
  .git-panel::-webkit-scrollbar-track,
49
51
  .diff-scroll::-webkit-scrollbar-track,
52
+ .backlinks-body::-webkit-scrollbar-track,
50
53
  .comments-drawer-list::-webkit-scrollbar-track,
51
54
  .comments-drawer-item-quote::-webkit-scrollbar-track,
52
55
  .comment-card-quote::-webkit-scrollbar-track,
@@ -67,6 +70,7 @@
67
70
  .file-tree::-webkit-scrollbar-thumb,
68
71
  .git-panel::-webkit-scrollbar-thumb,
69
72
  .diff-scroll::-webkit-scrollbar-thumb,
73
+ .backlinks-body::-webkit-scrollbar-thumb,
70
74
  .comments-drawer-list::-webkit-scrollbar-thumb,
71
75
  .comments-drawer-item-quote::-webkit-scrollbar-thumb,
72
76
  .comment-card-quote::-webkit-scrollbar-thumb,
@@ -88,6 +92,7 @@
88
92
  .file-tree::-webkit-scrollbar-thumb:hover,
89
93
  .git-panel::-webkit-scrollbar-thumb:hover,
90
94
  .diff-scroll::-webkit-scrollbar-thumb:hover,
95
+ .backlinks-body::-webkit-scrollbar-thumb:hover,
91
96
  .comments-drawer-list::-webkit-scrollbar-thumb:hover,
92
97
  .comments-drawer-item-quote::-webkit-scrollbar-thumb:hover,
93
98
  .comment-card-quote::-webkit-scrollbar-thumb:hover,
@@ -2,17 +2,24 @@ html[data-surface='export-document'] {
2
2
  height: auto;
3
3
  min-height: 100%;
4
4
  overflow-x: hidden;
5
- overflow-y: auto;
5
+ overflow-y: hidden;
6
6
  overscroll-behavior: auto;
7
+ scrollbar-width: none;
7
8
  }
8
9
 
9
10
  body[data-surface='export-document'] {
10
11
  height: auto;
11
12
  overflow-x: hidden;
12
- overflow-y: auto;
13
+ overflow-y: hidden;
13
14
  overscroll-behavior: auto;
14
15
  background: var(--color-bg);
15
16
  color: var(--color-text);
17
+ scrollbar-width: none;
18
+ }
19
+
20
+ html[data-surface='export-document']::-webkit-scrollbar,
21
+ body[data-surface='export-document']::-webkit-scrollbar {
22
+ display: none;
16
23
  }
17
24
 
18
25
  .export-page-shell {
@@ -78,10 +85,22 @@ body[data-surface='export-document'] {
78
85
  overflow: visible;
79
86
  }
80
87
 
88
+ .export-content .bases-table-shell,
89
+ .export-content pre {
90
+ overflow: visible;
91
+ }
92
+
81
93
  .export-content table {
82
94
  white-space: normal;
83
95
  }
84
96
 
97
+ .export-content pre code {
98
+ width: auto;
99
+ white-space: pre-wrap;
100
+ word-break: break-word;
101
+ overflow-wrap: anywhere;
102
+ }
103
+
85
104
  .export-diagram {
86
105
  display: flex;
87
106
  justify-content: center;
@@ -197,8 +216,18 @@ body[data-surface='export-document'] {
197
216
  }
198
217
 
199
218
  @media print {
219
+ html[data-surface='export-document'],
200
220
  body[data-surface='export-document'] {
221
+ height: auto;
222
+ overflow: hidden !important;
201
223
  background: var(--color-surface);
224
+ scrollbar-width: none;
225
+ }
226
+
227
+ html[data-surface='export-document']::-webkit-scrollbar,
228
+ body[data-surface='export-document']::-webkit-scrollbar,
229
+ .export-content *::-webkit-scrollbar {
230
+ display: none;
202
231
  }
203
232
 
204
233
  .export-page-shell {
@@ -218,6 +247,20 @@ body[data-surface='export-document'] {
218
247
  border: 0;
219
248
  border-radius: 0;
220
249
  box-shadow: none;
250
+ overflow: visible;
251
+ }
252
+
253
+ .export-content pre,
254
+ .export-content .table-wrapper,
255
+ .export-content .bases-table-shell {
256
+ overflow: visible !important;
257
+ }
258
+
259
+ .export-content pre code {
260
+ width: auto;
261
+ white-space: pre-wrap;
262
+ word-break: break-word;
263
+ overflow-wrap: anywhere;
221
264
  }
222
265
 
223
266
  .export-content h1,
@@ -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;