collabmd 0.1.18 → 0.1.20

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 (64) hide show
  1. package/README.md +107 -25
  2. package/docker-compose.yml +1 -1
  3. package/package.json +1 -1
  4. package/public/assets/css/style.css +1 -1
  5. package/public/assets/js/chunks/{preview-render-compiler-WD3A76I6.js → chunk-5QRWYPYT.js} +18 -18
  6. package/public/assets/js/chunks/chunk-HEWVH67U.js +9 -0
  7. package/public/assets/js/chunks/chunk-R3DDMJHH.js +1 -0
  8. package/public/assets/js/chunks/editor-session-TAV2VXTA.js +22 -0
  9. package/public/assets/js/chunks/preview-render-compiler-UZ4SZDQQ.js +1 -0
  10. package/public/assets/js/chunks/quick-switcher-controller-J7I3CUET.js +5 -0
  11. package/public/assets/js/{excalidraw-editor-LKW2AZBU.js → excalidraw-editor-ZDYKMZOL.js} +33 -33
  12. package/public/assets/js/excalidraw-editor.js +1 -1
  13. package/public/assets/js/main.js +100 -73
  14. package/public/assets/js/preview-render-worker.js +19 -19
  15. package/public/index.html +14 -4
  16. package/src/client/application/app-shell/git-feature.js +29 -1
  17. package/src/client/application/app-shell/presence-feature.js +2 -1
  18. package/src/client/application/app-shell/ui-feature.js +113 -1
  19. package/src/client/application/app-shell/workspace-feature.js +9 -0
  20. package/src/client/application/app-shell-elements.js +1 -0
  21. package/src/client/application/preview-render-compiler.js +55 -5
  22. package/src/client/application/preview-render-executor.js +8 -0
  23. package/src/client/application/preview-render-worker.js +13 -2
  24. package/src/client/application/preview-renderer.js +5 -0
  25. package/src/client/application/workspace-chrome-controller.js +12 -1
  26. package/src/client/application/workspace-coordinator.js +16 -7
  27. package/src/client/application/workspace-preview-controller.js +45 -5
  28. package/src/client/application/workspace-route-controller.js +4 -0
  29. package/src/client/bootstrap/collabmd-app-shell.js +19 -3
  30. package/src/client/domain/room.js +37 -0
  31. package/src/client/domain/vault-utils.js +46 -0
  32. package/src/client/infrastructure/comment-thread-store.js +98 -0
  33. package/src/client/infrastructure/editor-paste-utils.js +45 -0
  34. package/src/client/infrastructure/editor-session.js +10 -0
  35. package/src/client/infrastructure/editor-view-adapter.js +98 -7
  36. package/src/client/infrastructure/vault-api-client.js +17 -0
  37. package/src/client/presentation/backlinks-panel.js +157 -101
  38. package/src/client/presentation/comment-markdown-renderer.js +68 -0
  39. package/src/client/presentation/comment-ui-controller.js +352 -20
  40. package/src/client/presentation/file-explorer-controller.js +5 -0
  41. package/src/client/presentation/file-explorer-view.js +10 -2
  42. package/src/client/presentation/file-tree-state.js +7 -1
  43. package/src/client/presentation/git-panel-controller.js +73 -0
  44. package/src/client/presentation/image-lightbox-controller.js +394 -0
  45. package/src/client/presentation/outline-controller.js +25 -0
  46. package/src/client/styles/style.css +677 -21
  47. package/src/domain/comment-threads.js +95 -13
  48. package/src/domain/file-kind.js +16 -1
  49. package/src/server/infrastructure/git/errors.js +4 -1
  50. package/src/server/infrastructure/git/git-service.js +215 -1
  51. package/src/server/infrastructure/http/create-git-api-command-handler.js +6 -1
  52. package/src/server/infrastructure/http/create-git-api-query-handler.js +16 -1
  53. package/src/server/infrastructure/http/create-vault-api-command-handler.js +48 -2
  54. package/src/server/infrastructure/http/create-vault-api-query-handler.js +67 -1
  55. package/src/server/infrastructure/http/request-body.js +11 -2
  56. package/src/server/infrastructure/persistence/path-utils.js +1 -1
  57. package/src/server/infrastructure/persistence/pull-backup-store.js +283 -0
  58. package/src/server/infrastructure/persistence/vault-file-store.js +203 -2
  59. package/public/assets/js/chunks/chunk-BBHPYU2R.js +0 -1
  60. package/public/assets/js/chunks/chunk-OG2TNZEU.js +0 -9
  61. package/public/assets/js/chunks/chunk-QSTBGTWJ.js +0 -1
  62. package/public/assets/js/chunks/chunk-SR3U53EQ.js +0 -1
  63. package/public/assets/js/chunks/editor-session-IHFTYG5D.js +0 -22
  64. package/public/assets/js/chunks/quick-switcher-controller-JYDIJVAJ.js +0 -5
@@ -2265,6 +2265,10 @@ html[data-initial-file-requested="true"] .editor-page.hidden {
2265
2265
 
2266
2266
  /* Preview body (contains preview + outline side by side) */
2267
2267
  .preview-body {
2268
+ --preview-floating-sidebar-gap: var(--space-3);
2269
+ --preview-floating-comments-width: min(300px, 34vw);
2270
+ --preview-floating-outline-width: 220px;
2271
+ --preview-content-max-width: 720px;
2268
2272
  display: flex;
2269
2273
  flex: 1;
2270
2274
  overflow: hidden;
@@ -2298,6 +2302,12 @@ html[data-initial-file-requested="true"] .editor-page.hidden {
2298
2302
  color: var(--color-text-muted);
2299
2303
  }
2300
2304
 
2305
+ @media (min-width: 769px) {
2306
+ .preview-content {
2307
+ padding-bottom: calc(var(--space-12) + 96px);
2308
+ }
2309
+ }
2310
+
2301
2311
  .preview-content.is-excalidraw-file-preview {
2302
2312
  display: flex;
2303
2313
  width: 100%;
@@ -2310,6 +2320,17 @@ html[data-initial-file-requested="true"] .editor-page.hidden {
2310
2320
  max-width: none;
2311
2321
  }
2312
2322
 
2323
+ .preview-content.is-image-file-preview {
2324
+ display: flex;
2325
+ width: 100%;
2326
+ min-height: 100%;
2327
+ margin: 0;
2328
+ padding: var(--space-4);
2329
+ position: relative;
2330
+ box-sizing: border-box;
2331
+ max-width: none;
2332
+ }
2333
+
2313
2334
  .preview-content.is-plantuml-file-preview {
2314
2335
  width: 100%;
2315
2336
  min-height: 100%;
@@ -2337,6 +2358,31 @@ html[data-initial-file-requested="true"] .editor-page.hidden {
2337
2358
  min-height: 100%;
2338
2359
  }
2339
2360
 
2361
+ .preview-content.is-image-file-preview [data-preview-render-host="true"] {
2362
+ display: flex;
2363
+ flex: 1;
2364
+ min-width: 0;
2365
+ min-height: 100%;
2366
+ }
2367
+
2368
+ .image-file-preview-shell {
2369
+ width: 100%;
2370
+ min-height: 100%;
2371
+ margin: 0;
2372
+ display: flex;
2373
+ align-items: center;
2374
+ justify-content: center;
2375
+ }
2376
+
2377
+ .image-file-preview-image {
2378
+ max-width: min(100%, 1200px);
2379
+ max-height: calc(100vh - 180px);
2380
+ object-fit: contain;
2381
+ border-radius: var(--radius-lg);
2382
+ box-shadow: var(--shadow-lg);
2383
+ background: var(--color-surface);
2384
+ }
2385
+
2340
2386
  .preview-content.is-mermaid-file-preview .mermaid-shell {
2341
2387
  margin: 0;
2342
2388
  min-height: 100%;
@@ -2590,6 +2636,163 @@ html[data-initial-file-requested="true"] .editor-page.hidden {
2590
2636
  height: auto;
2591
2637
  border-radius: var(--radius-md);
2592
2638
  margin: var(--space-4) 0;
2639
+ cursor: zoom-in;
2640
+ }
2641
+
2642
+ .image-lightbox-root {
2643
+ position: fixed;
2644
+ inset: 0;
2645
+ z-index: 220;
2646
+ display: grid;
2647
+ place-items: center;
2648
+ pointer-events: auto;
2649
+ }
2650
+
2651
+ .image-lightbox-root[hidden] {
2652
+ display: none !important;
2653
+ }
2654
+
2655
+ .image-lightbox-backdrop {
2656
+ position: absolute;
2657
+ inset: 0;
2658
+ border: none;
2659
+ background: oklch(0.08 0.01 260 / 0.82);
2660
+ backdrop-filter: blur(10px);
2661
+ cursor: zoom-out;
2662
+ }
2663
+
2664
+ .image-lightbox-shell {
2665
+ position: absolute;
2666
+ inset: 0;
2667
+ z-index: 1;
2668
+ }
2669
+
2670
+ .image-lightbox-toolbar {
2671
+ position: absolute;
2672
+ top: var(--space-5);
2673
+ left: var(--space-5);
2674
+ right: var(--space-5);
2675
+ z-index: 2;
2676
+ display: flex;
2677
+ align-items: center;
2678
+ justify-content: space-between;
2679
+ gap: var(--space-3);
2680
+ pointer-events: none;
2681
+ }
2682
+
2683
+ .image-lightbox-title {
2684
+ min-width: 0;
2685
+ font-size: var(--text-xs);
2686
+ font-weight: 600;
2687
+ color: white;
2688
+ overflow: hidden;
2689
+ text-overflow: ellipsis;
2690
+ white-space: nowrap;
2691
+ padding: 8px 12px;
2692
+ border-radius: 999px;
2693
+ background: oklch(0.18 0.02 260 / 0.68);
2694
+ backdrop-filter: blur(12px);
2695
+ box-shadow: 0 16px 40px oklch(0 0 0 / 0.24);
2696
+ pointer-events: auto;
2697
+ }
2698
+
2699
+ .image-lightbox-controls {
2700
+ display: inline-flex;
2701
+ align-items: center;
2702
+ gap: var(--space-2);
2703
+ flex-wrap: wrap;
2704
+ justify-content: flex-end;
2705
+ pointer-events: auto;
2706
+ }
2707
+
2708
+ .image-lightbox-btn {
2709
+ min-width: 0;
2710
+ padding: 8px 12px;
2711
+ border: none;
2712
+ border-radius: 999px;
2713
+ background: oklch(0.18 0.02 260 / 0.68);
2714
+ color: white;
2715
+ font-size: var(--text-xs);
2716
+ font-weight: 600;
2717
+ backdrop-filter: blur(12px);
2718
+ box-shadow: 0 16px 40px oklch(0 0 0 / 0.24);
2719
+ transition: background 0.18s ease, transform 0.18s ease;
2720
+ }
2721
+
2722
+ .image-lightbox-btn:hover:not(:disabled) {
2723
+ background: oklch(0.24 0.02 260 / 0.82);
2724
+ }
2725
+
2726
+ .image-lightbox-btn:disabled {
2727
+ opacity: 0.45;
2728
+ cursor: default;
2729
+ }
2730
+
2731
+ .image-lightbox-zoom-label {
2732
+ min-width: 58px;
2733
+ padding: 8px 12px;
2734
+ border-radius: 999px;
2735
+ background: oklch(0.18 0.02 260 / 0.68);
2736
+ color: white;
2737
+ font-size: var(--text-xs);
2738
+ font-weight: 600;
2739
+ font-variant-numeric: tabular-nums;
2740
+ text-align: center;
2741
+ backdrop-filter: blur(12px);
2742
+ box-shadow: 0 16px 40px oklch(0 0 0 / 0.24);
2743
+ }
2744
+
2745
+ .image-lightbox-viewport {
2746
+ position: absolute;
2747
+ inset: 0;
2748
+ overflow: hidden;
2749
+ touch-action: none;
2750
+ user-select: none;
2751
+ }
2752
+
2753
+ .image-lightbox-viewport.is-dragging .image-lightbox-image {
2754
+ cursor: grabbing !important;
2755
+ }
2756
+
2757
+ .image-lightbox-image {
2758
+ position: absolute;
2759
+ inset: 0;
2760
+ margin: auto;
2761
+ max-width: calc(100vw - (var(--space-8) * 2));
2762
+ max-height: calc(100vh - (var(--space-8) * 2));
2763
+ width: auto;
2764
+ height: auto;
2765
+ object-fit: contain;
2766
+ transform-origin: center center;
2767
+ will-change: transform;
2768
+ box-shadow: 0 28px 80px oklch(0 0 0 / 0.28);
2769
+ }
2770
+
2771
+ body.image-lightbox-open {
2772
+ overflow: hidden;
2773
+ }
2774
+
2775
+ @media (max-width: 768px) {
2776
+ .image-lightbox-toolbar {
2777
+ top: var(--space-3);
2778
+ left: var(--space-3);
2779
+ right: var(--space-3);
2780
+ align-items: flex-start;
2781
+ flex-direction: column;
2782
+ }
2783
+
2784
+ .image-lightbox-controls {
2785
+ justify-content: flex-start;
2786
+ }
2787
+
2788
+ .image-lightbox-btn {
2789
+ flex: 0 0 auto;
2790
+ }
2791
+
2792
+ .image-lightbox-image {
2793
+ max-width: calc(100vw - (var(--space-4) * 2));
2794
+ max-height: calc(100vh - (var(--space-4) * 2));
2795
+ }
2593
2796
  }
2594
2797
 
2595
2798
  .preview-content .video-embed-shell {
@@ -2923,13 +3126,29 @@ body.plantuml-maximized-open::before {
2923
3126
  font-family: var(--font-mono);
2924
3127
  font-size: 11.5px;
2925
3128
  line-height: 1.65;
2926
- white-space: pre;
2927
- overflow-x: auto;
2928
- overflow-y: hidden;
2929
- word-break: normal;
2930
- text-wrap: nowrap;
3129
+ white-space: pre-wrap;
3130
+ overflow: auto;
3131
+ overflow-wrap: anywhere;
3132
+ word-break: break-word;
3133
+ max-height: 9.5rem;
2931
3134
  scrollbar-width: thin;
2932
- padding-bottom: calc(var(--space-2) + 2px);
3135
+ padding-bottom: calc(var(--space-3) + 2px);
3136
+ }
3137
+
3138
+ .comments-drawer-item-preview {
3139
+ position: relative;
3140
+ max-height: 7.8rem;
3141
+ overflow: hidden;
3142
+ color: var(--color-text-muted);
3143
+ }
3144
+
3145
+ .comments-drawer-item-preview:after {
3146
+ content: "";
3147
+ position: absolute;
3148
+ inset: auto 0 0 0;
3149
+ height: 2.5rem;
3150
+ background: linear-gradient(180deg, oklch(0 0 0 / 0), color-mix(in srgb, var(--color-surface-2) 95%, var(--color-comment) 5%));
3151
+ pointer-events: none;
2933
3152
  }
2934
3153
 
2935
3154
  .comments-drawer-item-footer {
@@ -2937,6 +3156,12 @@ body.plantuml-maximized-open::before {
2937
3156
  color: var(--color-text-muted);
2938
3157
  font-weight: 600;
2939
3158
  letter-spacing: 0.01em;
3159
+ align-items: flex-end;
3160
+ flex-wrap: wrap;
3161
+ }
3162
+
3163
+ .comments-drawer-item-updated {
3164
+ color: var(--color-text-faint);
2940
3165
  }
2941
3166
 
2942
3167
  .comment-editor-layer,
@@ -3029,7 +3254,7 @@ body.plantuml-maximized-open::before {
3029
3254
  }
3030
3255
 
3031
3256
  .comment-card {
3032
- width: min(100%, 360px);
3257
+ width: min(100%, 520px);
3033
3258
  border-radius: 18px;
3034
3259
  border: 1px solid color-mix(in srgb, var(--color-border) 82%, var(--color-comment) 18%);
3035
3260
  background: color-mix(in srgb, var(--color-surface) 94%, var(--color-comment) 6%);
@@ -3038,6 +3263,8 @@ body.plantuml-maximized-open::before {
3038
3263
  display: flex;
3039
3264
  flex-direction: column;
3040
3265
  gap: var(--space-3);
3266
+ max-height: min(78vh, 720px);
3267
+ overflow: hidden;
3041
3268
  animation: comment-card-in 140ms cubic-bezier(0.16, 1, 0.3, 1);
3042
3269
  }
3043
3270
 
@@ -3056,6 +3283,19 @@ body.plantuml-maximized-open::before {
3056
3283
  justify-content: space-between;
3057
3284
  }
3058
3285
 
3286
+ .comment-card-header {
3287
+ flex-shrink: 0;
3288
+ }
3289
+
3290
+ .comment-card-scroll {
3291
+ display: flex;
3292
+ flex-direction: column;
3293
+ gap: var(--space-3);
3294
+ min-height: 0;
3295
+ overflow: auto;
3296
+ padding-right: 2px;
3297
+ }
3298
+
3059
3299
  .comment-card-title {
3060
3300
  font-size: 15px;
3061
3301
  font-weight: 700;
@@ -3110,15 +3350,15 @@ body.plantuml-maximized-open::before {
3110
3350
  }
3111
3351
 
3112
3352
  .comment-card-quote {
3113
- white-space: pre;
3114
- overflow-x: auto;
3115
- overflow-y: hidden;
3116
- word-break: normal;
3117
- text-wrap: nowrap;
3353
+ white-space: pre-wrap;
3354
+ overflow: auto;
3355
+ overflow-wrap: anywhere;
3356
+ word-break: break-word;
3118
3357
  font-family: var(--font-mono);
3119
3358
  font-size: 11.5px;
3120
3359
  line-height: 1.65;
3121
- padding-bottom: calc(var(--space-2) + 2px);
3360
+ max-height: 11rem;
3361
+ padding-bottom: calc(var(--space-3) + 2px);
3122
3362
  scrollbar-width: thin;
3123
3363
  }
3124
3364
 
@@ -3137,11 +3377,24 @@ body.plantuml-maximized-open::before {
3137
3377
  .comment-thread-card {
3138
3378
  display: flex;
3139
3379
  flex-direction: column;
3140
- gap: var(--space-2);
3380
+ gap: var(--space-3);
3141
3381
  padding-top: var(--space-3);
3142
3382
  border-top: 1px solid var(--color-divider);
3143
3383
  }
3144
3384
 
3385
+ .comment-thread-card-header {
3386
+ align-items: flex-start;
3387
+ flex-wrap: wrap;
3388
+ }
3389
+
3390
+ .comment-thread-card-heading {
3391
+ display: flex;
3392
+ flex: 1 1 160px;
3393
+ flex-wrap: wrap;
3394
+ gap: var(--space-1) var(--space-2);
3395
+ min-width: 0;
3396
+ }
3397
+
3145
3398
  .comment-thread-card-author,
3146
3399
  .comment-message-card-author {
3147
3400
  font-size: 12px;
@@ -3156,8 +3409,10 @@ body.plantuml-maximized-open::before {
3156
3409
 
3157
3410
  .comment-thread-card-actions {
3158
3411
  display: inline-flex;
3412
+ flex-wrap: wrap;
3159
3413
  gap: var(--space-1);
3160
3414
  margin-left: auto;
3415
+ justify-content: flex-end;
3161
3416
  }
3162
3417
 
3163
3418
  .comment-message-card {
@@ -3170,6 +3425,246 @@ body.plantuml-maximized-open::before {
3170
3425
  .comment-message-card-body {
3171
3426
  margin-top: var(--space-1);
3172
3427
  font-size: 12px;
3428
+ line-height: 1.65;
3429
+ }
3430
+
3431
+ .comment-reaction-bar {
3432
+ display: flex;
3433
+ align-items: flex-start;
3434
+ justify-content: space-between;
3435
+ gap: var(--space-2);
3436
+ flex-wrap: wrap;
3437
+ margin-top: var(--space-2);
3438
+ }
3439
+
3440
+ .comment-reaction-chips {
3441
+ display: flex;
3442
+ flex-wrap: wrap;
3443
+ gap: var(--space-2);
3444
+ }
3445
+
3446
+ .comment-reaction-actions {
3447
+ display: flex;
3448
+ align-items: center;
3449
+ flex-wrap: wrap;
3450
+ gap: var(--space-2);
3451
+ }
3452
+
3453
+ .comment-reaction-chip,
3454
+ .comment-reaction-more-trigger {
3455
+ display: inline-flex;
3456
+ align-items: center;
3457
+ justify-content: center;
3458
+ gap: 6px;
3459
+ min-height: 30px;
3460
+ padding: 4px 10px;
3461
+ border-radius: var(--radius-full);
3462
+ border: 1px solid color-mix(in srgb, var(--color-divider) 88%, var(--color-comment) 12%);
3463
+ background: color-mix(in srgb, var(--color-surface) 90%, var(--color-comment) 10%);
3464
+ color: var(--color-text-muted);
3465
+ font-size: 11px;
3466
+ font-weight: 600;
3467
+ transition: background var(--transition-interactive), border-color var(--transition-interactive), color var(--transition-interactive), transform 140ms ease;
3468
+ }
3469
+
3470
+ .comment-reaction-chip:hover,
3471
+ .comment-reaction-more-trigger:hover {
3472
+ color: var(--color-text);
3473
+ border-color: oklch(from var(--color-comment) l c h / 0.22);
3474
+ background: color-mix(in srgb, var(--color-surface-offset) 76%, var(--color-comment) 24%);
3475
+ }
3476
+
3477
+ .comment-reaction-chip.is-active {
3478
+ color: var(--color-comment);
3479
+ border-color: oklch(from var(--color-comment) l c h / 0.28);
3480
+ background: color-mix(in srgb, var(--color-surface-offset) 64%, var(--color-comment) 36%);
3481
+ }
3482
+
3483
+ .comment-reaction-chip-emoji,
3484
+ .comment-reaction-chip-count {
3485
+ line-height: 1;
3486
+ }
3487
+
3488
+ .comment-reaction-quick-add,
3489
+ .comment-reaction-picker-btn {
3490
+ display: inline-flex;
3491
+ align-items: center;
3492
+ justify-content: center;
3493
+ min-width: 34px;
3494
+ min-height: 34px;
3495
+ padding: 0;
3496
+ border-radius: var(--radius-md);
3497
+ border: 1px solid color-mix(in srgb, var(--color-divider) 88%, var(--color-comment) 12%);
3498
+ background: color-mix(in srgb, var(--color-surface-2) 92%, var(--color-comment) 8%);
3499
+ font-size: 18px;
3500
+ transition: background var(--transition-interactive), border-color var(--transition-interactive), transform 140ms ease;
3501
+ }
3502
+
3503
+ .comment-reaction-quick-add:hover,
3504
+ .comment-reaction-picker-btn:hover {
3505
+ border-color: oklch(from var(--color-comment) l c h / 0.24);
3506
+ background: color-mix(in srgb, var(--color-surface-offset) 78%, var(--color-comment) 22%);
3507
+ transform: translateY(-1px);
3508
+ }
3509
+
3510
+ .comment-reaction-picker-wrap {
3511
+ position: relative;
3512
+ display: inline-flex;
3513
+ }
3514
+
3515
+ .comment-reaction-picker {
3516
+ position: absolute;
3517
+ top: calc(100% + 8px);
3518
+ right: 0;
3519
+ z-index: 2;
3520
+ min-width: 220px;
3521
+ display: flex;
3522
+ flex-direction: column;
3523
+ gap: var(--space-2);
3524
+ padding: var(--space-3);
3525
+ border-radius: var(--radius-lg);
3526
+ border: 1px solid color-mix(in srgb, var(--color-border) 82%, var(--color-comment) 18%);
3527
+ background: color-mix(in srgb, var(--color-surface) 96%, var(--color-comment) 4%);
3528
+ box-shadow: var(--shadow-lg);
3529
+ overflow: auto;
3530
+ scrollbar-width: thin;
3531
+ }
3532
+
3533
+ .comment-reaction-picker.is-upward {
3534
+ top: auto;
3535
+ bottom: calc(100% + 8px);
3536
+ }
3537
+
3538
+ .comment-reaction-picker-grid {
3539
+ display: grid;
3540
+ grid-template-columns: repeat(5, minmax(0, 1fr));
3541
+ gap: var(--space-2);
3542
+ }
3543
+
3544
+ .comment-markdown {
3545
+ color: var(--color-text);
3546
+ font-size: 12px;
3547
+ line-height: 1.65;
3548
+ }
3549
+
3550
+ .comment-markdown > :first-child {
3551
+ margin-top: 0;
3552
+ }
3553
+
3554
+ .comment-markdown > :last-child {
3555
+ margin-bottom: 0;
3556
+ }
3557
+
3558
+ .comment-markdown p,
3559
+ .comment-markdown ul,
3560
+ .comment-markdown ol,
3561
+ .comment-markdown blockquote,
3562
+ .comment-markdown pre,
3563
+ .comment-markdown .comment-markdown-table,
3564
+ .comment-markdown table {
3565
+ max-width: none;
3566
+ }
3567
+
3568
+ .comment-markdown p,
3569
+ .comment-markdown ul,
3570
+ .comment-markdown ol,
3571
+ .comment-markdown blockquote,
3572
+ .comment-markdown pre,
3573
+ .comment-markdown .comment-markdown-table {
3574
+ margin: var(--space-2) 0;
3575
+ }
3576
+
3577
+ .comment-markdown li + li {
3578
+ margin-top: 4px;
3579
+ }
3580
+
3581
+ .comment-markdown ul,
3582
+ .comment-markdown ol {
3583
+ padding-left: var(--space-5);
3584
+ }
3585
+
3586
+ .comment-markdown a {
3587
+ color: var(--color-primary);
3588
+ overflow-wrap: anywhere;
3589
+ text-decoration: underline;
3590
+ }
3591
+
3592
+ .comment-markdown blockquote {
3593
+ padding: var(--space-2) var(--space-3);
3594
+ border-left: 3px solid oklch(from var(--color-comment) l c h / 0.45);
3595
+ border-radius: 0 var(--radius-md) var(--radius-md) 0;
3596
+ background: color-mix(in srgb, var(--color-surface-offset) 84%, var(--color-comment) 16%);
3597
+ color: var(--color-text-muted);
3598
+ }
3599
+
3600
+ .comment-markdown code {
3601
+ font-family: var(--font-mono);
3602
+ font-size: 0.9em;
3603
+ background: color-mix(in srgb, var(--color-surface-offset) 88%, var(--color-comment) 12%);
3604
+ padding: 2px 6px;
3605
+ border-radius: var(--radius-sm);
3606
+ color: var(--color-primary);
3607
+ }
3608
+
3609
+ .comment-markdown pre {
3610
+ border-radius: var(--radius-lg);
3611
+ overflow: auto;
3612
+ border: 1px solid color-mix(in srgb, var(--color-divider) 88%, var(--color-comment) 12%);
3613
+ background: color-mix(in srgb, var(--color-surface) 96%, var(--color-comment) 4%);
3614
+ max-width: 100%;
3615
+ }
3616
+
3617
+ .comment-markdown pre code {
3618
+ display: block;
3619
+ padding: var(--space-3);
3620
+ background: none;
3621
+ color: var(--color-text);
3622
+ font-size: 12px;
3623
+ line-height: 1.6;
3624
+ white-space: pre;
3625
+ width: max-content;
3626
+ min-width: 100%;
3627
+ }
3628
+
3629
+ .comment-markdown .comment-markdown-table {
3630
+ border: 1px solid color-mix(in srgb, var(--color-divider) 88%, var(--color-comment) 12%);
3631
+ border-radius: var(--radius-md);
3632
+ overflow: auto;
3633
+ }
3634
+
3635
+ .comment-markdown table {
3636
+ width: 100%;
3637
+ border-collapse: collapse;
3638
+ }
3639
+
3640
+ .comment-markdown th,
3641
+ .comment-markdown td {
3642
+ padding: var(--space-2) var(--space-3);
3643
+ text-align: left;
3644
+ border-bottom: 1px solid var(--color-divider);
3645
+ font-size: 12px;
3646
+ }
3647
+
3648
+ .comment-markdown th {
3649
+ background: color-mix(in srgb, var(--color-surface-offset) 90%, var(--color-comment) 10%);
3650
+ }
3651
+
3652
+ .comment-markdown-preview > :not(pre):not(blockquote):not(.comment-markdown-table) {
3653
+ display: -webkit-box;
3654
+ -webkit-box-orient: vertical;
3655
+ -webkit-line-clamp: 4;
3656
+ overflow: hidden;
3657
+ }
3658
+
3659
+ .comment-markdown-preview pre code {
3660
+ max-height: 6.6rem;
3661
+ min-width: 0;
3662
+ width: 100%;
3663
+ overflow: hidden;
3664
+ }
3665
+
3666
+ .comment-markdown-preview .comment-markdown-table {
3667
+ display: none;
3173
3668
  }
3174
3669
 
3175
3670
  @keyframes comment-card-in {
@@ -3185,14 +3680,45 @@ body.plantuml-maximized-open::before {
3185
3680
 
3186
3681
  /* ===== BACKLINKS PANEL ===== */
3187
3682
 
3683
+ .backlinks-panel.hidden,
3684
+ .backlinks-panel-layer.hidden {
3685
+ display: none;
3686
+ }
3188
3687
  .backlinks-panel {
3688
+ min-width: 0;
3689
+ }
3690
+ .backlinks-panel-layer {
3691
+ position: absolute;
3692
+ left: max(
3693
+ var(--space-4),
3694
+ calc((100% - min(var(--preview-content-max-width), 100%)) / 2)
3695
+ );
3696
+ bottom: calc(var(--space-5) + env(safe-area-inset-bottom, 0px));
3697
+ width: min(320px, calc(min(var(--preview-content-max-width), 100%) - var(--space-8)));
3698
+ z-index: 14;
3699
+ pointer-events: none;
3700
+ }
3701
+ .backlinks-panel-dock {
3702
+ display: flex;
3703
+ flex-direction: column-reverse;
3704
+ border: 1px solid var(--color-divider);
3705
+ border-radius: 18px;
3706
+ background: color-mix(in srgb, var(--color-surface) 84%, var(--color-surface-offset) 16%);
3707
+ box-shadow: 0 14px 34px oklch(0 0 0 / 0.18);
3708
+ backdrop-filter: blur(16px);
3709
+ overflow: hidden;
3710
+ pointer-events: auto;
3711
+ transition: box-shadow 160ms ease, transform 160ms ease, background-color 160ms ease, border-color 160ms ease;
3712
+ }
3713
+ .backlinks-panel-dock:hover {
3714
+ transform: translateY(-1px);
3715
+ box-shadow: 0 18px 40px oklch(0 0 0 / 0.2);
3716
+ }
3717
+ .backlinks-panel-inline {
3189
3718
  border-top: 1px solid var(--color-divider);
3190
3719
  margin-top: var(--space-6);
3191
3720
  padding: 0 var(--space-4);
3192
3721
  }
3193
- .backlinks-panel.hidden {
3194
- display: none;
3195
- }
3196
3722
  .backlinks-header {
3197
3723
  display: flex;
3198
3724
  align-items: center;
@@ -3208,6 +3734,10 @@ body.plantuml-maximized-open::before {
3208
3734
  .backlinks-header:hover {
3209
3735
  color: var(--color-text);
3210
3736
  }
3737
+ .backlinks-panel-dock .backlinks-header {
3738
+ padding: 11px 14px;
3739
+ background: color-mix(in srgb, var(--color-surface-offset) 76%, var(--color-bg) 24%);
3740
+ }
3211
3741
  .backlinks-header-empty {
3212
3742
  cursor: default;
3213
3743
  opacity: 0.5;
@@ -3224,15 +3754,20 @@ body.plantuml-maximized-open::before {
3224
3754
  }
3225
3755
  .backlinks-toggle {
3226
3756
  flex: 1;
3757
+ min-width: 0;
3758
+ overflow: hidden;
3759
+ text-overflow: ellipsis;
3760
+ white-space: nowrap;
3227
3761
  }
3228
3762
  .backlinks-count {
3229
3763
  font-size: var(--text-xs);
3230
3764
  font-weight: 600;
3231
3765
  color: var(--color-primary);
3232
- background: oklch(from var(--color-primary) l c h / 0.12);
3766
+ background: oklch(from var(--color-primary) l c h / 0.14);
3233
3767
  border-radius: var(--radius-full);
3234
- padding: 1px 8px;
3235
- min-width: 0;
3768
+ padding: 1px 7px;
3769
+ min-width: 22px;
3770
+ text-align: center;
3236
3771
  }
3237
3772
  .backlinks-count:empty {
3238
3773
  display: none;
@@ -3242,16 +3777,31 @@ body.plantuml-maximized-open::before {
3242
3777
  max-height: 0;
3243
3778
  transition: max-height 200ms ease;
3244
3779
  }
3245
- .backlinks-panel.expanded .backlinks-body {
3780
+ .backlinks-panel-inline.expanded .backlinks-body {
3246
3781
  max-height: 600px;
3247
3782
  overflow-y: auto;
3248
3783
  }
3784
+ .backlinks-panel-dock .backlinks-body {
3785
+ background: color-mix(in srgb, var(--color-surface) 94%, var(--color-surface-offset) 6%);
3786
+ }
3787
+ .backlinks-panel-dock.expanded .backlinks-body {
3788
+ max-height: min(44vh, 400px);
3789
+ overflow-y: auto;
3790
+ border-bottom: 1px solid color-mix(in srgb, var(--color-divider) 78%, var(--color-primary) 22%);
3791
+ }
3792
+ .backlinks-panel-dock.expanded {
3793
+ border-color: color-mix(in srgb, var(--color-divider) 72%, var(--color-primary) 28%);
3794
+ background: color-mix(in srgb, var(--color-surface) 90%, var(--color-surface-offset) 10%);
3795
+ }
3249
3796
  .backlinks-list {
3250
3797
  padding-bottom: var(--space-4);
3251
3798
  display: flex;
3252
3799
  flex-direction: column;
3253
3800
  gap: var(--space-2);
3254
3801
  }
3802
+ .backlinks-panel-dock .backlinks-list {
3803
+ padding: 10px;
3804
+ }
3255
3805
  .backlink-item {
3256
3806
  display: block;
3257
3807
  width: 100%;
@@ -3263,6 +3813,10 @@ body.plantuml-maximized-open::before {
3263
3813
  cursor: pointer;
3264
3814
  transition: border-color var(--transition-interactive), background var(--transition-interactive);
3265
3815
  }
3816
+ .backlinks-panel-dock .backlink-item {
3817
+ border-radius: 12px;
3818
+ background: color-mix(in srgb, var(--color-surface) 88%, var(--color-surface-offset) 12%);
3819
+ }
3266
3820
  .backlink-item:hover {
3267
3821
  border-color: var(--color-primary);
3268
3822
  background: oklch(from var(--color-primary) l c h / 0.04);
@@ -3304,6 +3858,12 @@ body.plantuml-maximized-open::before {
3304
3858
  color: var(--color-text-faint);
3305
3859
  }
3306
3860
 
3861
+ @media (min-width: 769px) {
3862
+ .backlinks-panel-inline {
3863
+ display: none !important;
3864
+ }
3865
+ }
3866
+
3307
3867
  .outline-panel {
3308
3868
  width: 220px;
3309
3869
  flex-shrink: 0;
@@ -3404,12 +3964,18 @@ body.plantuml-maximized-open::before {
3404
3964
  .editor-layout[data-view="preview"] .preview-pane {
3405
3965
  flex: 1;
3406
3966
  }
3967
+ .editor-layout[data-view="preview"] .preview-body {
3968
+ --preview-content-max-width: 1080px;
3969
+ }
3407
3970
  .editor-layout[data-view="preview"] .preview-content {
3408
3971
  max-width: 1080px;
3409
3972
  }
3410
3973
  .editor-layout[data-view="preview"] .preview-content.is-excalidraw-file-preview {
3411
3974
  max-width: none;
3412
3975
  }
3976
+ .editor-layout[data-view="preview"] .preview-content.is-image-file-preview {
3977
+ max-width: none;
3978
+ }
3413
3979
  .editor-layout[data-view="preview"] .preview-content.is-mermaid-file-preview {
3414
3980
  max-width: none;
3415
3981
  }
@@ -3435,6 +4001,55 @@ body.plantuml-maximized-open::before {
3435
4001
  .editor-layout[data-view="preview"] .preview-content p:has(> .plantuml-shell:only-child) {
3436
4002
  max-width: none;
3437
4003
  }
4004
+ @media (min-width: 769px) {
4005
+ .preview-body > .comments-drawer,
4006
+ .preview-body > .outline-panel {
4007
+ position: absolute;
4008
+ top: var(--preview-floating-sidebar-gap);
4009
+ right: var(--preview-floating-sidebar-gap);
4010
+ bottom: var(--preview-floating-sidebar-gap);
4011
+ z-index: 20;
4012
+ overflow: hidden;
4013
+ border: 1px solid var(--color-divider);
4014
+ border-radius: calc(var(--radius-lg) + 2px);
4015
+ box-shadow: var(--shadow-lg);
4016
+ backdrop-filter: blur(14px);
4017
+ }
4018
+
4019
+ .preview-body > .comments-drawer {
4020
+ width: var(--preview-floating-comments-width);
4021
+ min-width: 240px;
4022
+ border-left: 1px solid var(--color-divider);
4023
+ }
4024
+
4025
+ .preview-body > .outline-panel {
4026
+ width: var(--preview-floating-outline-width);
4027
+ border-left: 1px solid var(--color-divider);
4028
+ }
4029
+
4030
+ .preview-body > .comments-drawer.hidden,
4031
+ .preview-body > .outline-panel.hidden {
4032
+ display: flex !important;
4033
+ opacity: 0;
4034
+ pointer-events: none;
4035
+ transform: translateX(12px);
4036
+ visibility: hidden;
4037
+ }
4038
+
4039
+ .preview-body > .comments-drawer:not(.hidden),
4040
+ .preview-body > .outline-panel:not(.hidden) {
4041
+ opacity: 1;
4042
+ transform: translateX(0);
4043
+ visibility: visible;
4044
+ }
4045
+
4046
+ .preview-body:has(> .outline-panel:not(.hidden)) > .comments-drawer:not(.hidden) {
4047
+ right: calc(
4048
+ var(--preview-floating-sidebar-gap) * 2
4049
+ + var(--preview-floating-outline-width)
4050
+ );
4051
+ }
4052
+ }
3438
4053
  .editor-layout[data-view="editor"] .editor-pane {
3439
4054
  flex: 1;
3440
4055
  }
@@ -3534,6 +4149,10 @@ body.plantuml-maximized-open::before {
3534
4149
  padding: var(--space-4);
3535
4150
  }
3536
4151
 
4152
+ .backlinks-panel-layer {
4153
+ display: none !important;
4154
+ }
4155
+
3537
4156
  .diff-toolbar {
3538
4157
  flex-wrap: wrap;
3539
4158
  padding: var(--space-2) var(--space-3);
@@ -3631,6 +4250,23 @@ body.plantuml-maximized-open::before {
3631
4250
  .chat-send-btn {
3632
4251
  padding-inline: var(--space-3);
3633
4252
  }
4253
+
4254
+ .comment-card {
4255
+ width: min(100vw - 32px, 520px);
4256
+ max-height: min(72vh, 680px);
4257
+ }
4258
+
4259
+ .comment-thread-card-actions {
4260
+ width: 100%;
4261
+ margin-left: 0;
4262
+ justify-content: flex-start;
4263
+ }
4264
+
4265
+ .comment-reaction-picker {
4266
+ left: 0;
4267
+ right: auto;
4268
+ min-width: min(240px, calc(100vw - 64px));
4269
+ }
3634
4270
  }
3635
4271
 
3636
4272
  @media (min-width: 769px) {
@@ -3655,8 +4291,12 @@ body.plantuml-maximized-open::before {
3655
4291
  .git-panel,
3656
4292
  .diff-scroll,
3657
4293
  .comments-drawer-list,
4294
+ .comments-drawer-item-quote,
3658
4295
  .comment-card-quote,
4296
+ .comment-card-scroll,
3659
4297
  .markdown-toolbar,
4298
+ .comment-markdown pre,
4299
+ .comment-markdown .comment-markdown-table,
3660
4300
  .preview-content pre,
3661
4301
  .preview-content .table-wrapper,
3662
4302
  .preview-content .mermaid-frame,
@@ -3672,8 +4312,12 @@ body.plantuml-maximized-open::before {
3672
4312
  .git-panel::-webkit-scrollbar,
3673
4313
  .diff-scroll::-webkit-scrollbar,
3674
4314
  .comments-drawer-list::-webkit-scrollbar,
4315
+ .comments-drawer-item-quote::-webkit-scrollbar,
3675
4316
  .comment-card-quote::-webkit-scrollbar,
4317
+ .comment-card-scroll::-webkit-scrollbar,
3676
4318
  .markdown-toolbar::-webkit-scrollbar,
4319
+ .comment-markdown pre::-webkit-scrollbar,
4320
+ .comment-markdown .comment-markdown-table::-webkit-scrollbar,
3677
4321
  .preview-content pre::-webkit-scrollbar,
3678
4322
  .preview-content .table-wrapper::-webkit-scrollbar,
3679
4323
  .preview-content .mermaid-frame::-webkit-scrollbar,
@@ -3688,8 +4332,12 @@ body.plantuml-maximized-open::before {
3688
4332
  .git-panel::-webkit-scrollbar-track,
3689
4333
  .diff-scroll::-webkit-scrollbar-track,
3690
4334
  .comments-drawer-list::-webkit-scrollbar-track,
4335
+ .comments-drawer-item-quote::-webkit-scrollbar-track,
3691
4336
  .comment-card-quote::-webkit-scrollbar-track,
4337
+ .comment-card-scroll::-webkit-scrollbar-track,
3692
4338
  .markdown-toolbar::-webkit-scrollbar-track,
4339
+ .comment-markdown pre::-webkit-scrollbar-track,
4340
+ .comment-markdown .comment-markdown-table::-webkit-scrollbar-track,
3693
4341
  .preview-content pre::-webkit-scrollbar-track,
3694
4342
  .preview-content .table-wrapper::-webkit-scrollbar-track,
3695
4343
  .preview-content .mermaid-frame::-webkit-scrollbar-track,
@@ -3703,8 +4351,12 @@ body.plantuml-maximized-open::before {
3703
4351
  .git-panel::-webkit-scrollbar-thumb,
3704
4352
  .diff-scroll::-webkit-scrollbar-thumb,
3705
4353
  .comments-drawer-list::-webkit-scrollbar-thumb,
4354
+ .comments-drawer-item-quote::-webkit-scrollbar-thumb,
3706
4355
  .comment-card-quote::-webkit-scrollbar-thumb,
4356
+ .comment-card-scroll::-webkit-scrollbar-thumb,
3707
4357
  .markdown-toolbar::-webkit-scrollbar-thumb,
4358
+ .comment-markdown pre::-webkit-scrollbar-thumb,
4359
+ .comment-markdown .comment-markdown-table::-webkit-scrollbar-thumb,
3708
4360
  .preview-content pre::-webkit-scrollbar-thumb,
3709
4361
  .preview-content .table-wrapper::-webkit-scrollbar-thumb,
3710
4362
  .preview-content .mermaid-frame::-webkit-scrollbar-thumb,
@@ -3719,8 +4371,12 @@ body.plantuml-maximized-open::before {
3719
4371
  .git-panel::-webkit-scrollbar-thumb:hover,
3720
4372
  .diff-scroll::-webkit-scrollbar-thumb:hover,
3721
4373
  .comments-drawer-list::-webkit-scrollbar-thumb:hover,
4374
+ .comments-drawer-item-quote::-webkit-scrollbar-thumb:hover,
3722
4375
  .comment-card-quote::-webkit-scrollbar-thumb:hover,
4376
+ .comment-card-scroll::-webkit-scrollbar-thumb:hover,
3723
4377
  .markdown-toolbar::-webkit-scrollbar-thumb:hover,
4378
+ .comment-markdown pre::-webkit-scrollbar-thumb:hover,
4379
+ .comment-markdown .comment-markdown-table::-webkit-scrollbar-thumb:hover,
3724
4380
  .preview-content pre::-webkit-scrollbar-thumb:hover,
3725
4381
  .preview-content .table-wrapper::-webkit-scrollbar-thumb:hover,
3726
4382
  .preview-content .mermaid-frame::-webkit-scrollbar-thumb:hover,