collabmd 0.1.21 → 0.1.23

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/README.md +94 -7
  2. package/bin/collabmd.js +3 -2
  3. package/docker-compose.yml +13 -1
  4. package/package.json +2 -1
  5. package/public/assets/css/style.css +1 -1
  6. package/public/assets/js/chunks/{chunk-HEWVH67U.js → chunk-CYK7KO7W.js} +8 -8
  7. package/public/assets/js/chunks/editor-session-S5AT7BMV.js +22 -0
  8. package/public/assets/js/{excalidraw-editor-TCIH6GJL.js → excalidraw-editor-5YWMGLKF.js} +145 -62
  9. package/public/assets/js/excalidraw-editor.js +1 -1
  10. package/public/assets/js/main.js +503 -182
  11. package/public/index.html +104 -84
  12. package/src/client/application/app-shell/git-feature.js +247 -9
  13. package/src/client/application/app-shell/ui-feature.js +65 -7
  14. package/src/client/application/app-shell/workspace-feature.js +46 -0
  15. package/src/client/application/app-shell-elements.js +2 -0
  16. package/src/client/application/mermaid-preview-hydrator.js +1 -1
  17. package/src/client/application/plantuml-preview-hydrator.js +1 -1
  18. package/src/client/application/workspace-coordinator.js +147 -18
  19. package/src/client/application/workspace-preview-controller.js +34 -0
  20. package/src/client/application/workspace-route-controller.js +104 -0
  21. package/src/client/bootstrap/collabmd-app-shell.js +95 -0
  22. package/src/client/domain/runtime-paths.js +5 -0
  23. package/src/client/excalidraw-editor.js +50 -2
  24. package/src/client/infrastructure/auth-client.js +219 -52
  25. package/src/client/infrastructure/browser-navigation-port.js +20 -0
  26. package/src/client/infrastructure/editor-collaboration-client.js +4 -0
  27. package/src/client/infrastructure/editor-session.js +47 -7
  28. package/src/client/infrastructure/editor-view-adapter.js +122 -58
  29. package/src/client/infrastructure/runtime-config.js +66 -0
  30. package/src/client/presentation/comment-ui-controller.js +82 -26
  31. package/src/client/presentation/comments-panel.js +2 -2
  32. package/src/client/presentation/excalidraw-embed-controller.js +60 -2
  33. package/src/client/presentation/file-history-view-controller.js +806 -0
  34. package/src/client/presentation/git-diff-view-controller.js +718 -121
  35. package/src/client/presentation/git-panel-controller.js +458 -66
  36. package/src/client/presentation/layout-controller.js +1 -1
  37. package/src/client/styles/components/actions.css +89 -0
  38. package/src/client/styles/components/feedback.css +43 -0
  39. package/src/client/styles/components/navigation.css +68 -0
  40. package/src/client/styles/components/scrollbars.css +104 -0
  41. package/src/client/styles/components/states.css +289 -0
  42. package/src/client/styles/components/surfaces.css +155 -0
  43. package/src/client/styles/features/backlinks.css +213 -0
  44. package/src/client/styles/features/collaboration-chat.css +228 -0
  45. package/src/client/styles/features/collaboration-dialogs.css +154 -0
  46. package/src/client/styles/features/collaboration-presence.css +103 -0
  47. package/src/client/styles/features/collaboration-ui.css +3 -0
  48. package/src/client/styles/features/comment-card.css +236 -0
  49. package/src/client/styles/features/comment-markdown.css +127 -0
  50. package/src/client/styles/features/comment-overlays.css +60 -0
  51. package/src/client/styles/features/comments-drawer.css +120 -0
  52. package/src/client/styles/features/comments.css +4 -0
  53. package/src/client/styles/features/diagram-preview.css +227 -0
  54. package/src/client/styles/features/diff-commit.css +268 -0
  55. package/src/client/styles/features/diff-lines.css +160 -0
  56. package/src/client/styles/features/diff-toolbar.css +98 -0
  57. package/src/client/styles/features/diff.css +3 -0
  58. package/src/client/styles/features/embedded-preview.css +218 -0
  59. package/src/client/styles/features/git-branch.css +155 -0
  60. package/src/client/styles/features/git-files.css +105 -0
  61. package/src/client/styles/features/git-history.css +339 -0
  62. package/src/client/styles/features/git.css +3 -0
  63. package/src/client/styles/features/media-lightbox.css +157 -0
  64. package/src/client/styles/features/outline.css +115 -0
  65. package/src/client/styles/features/preview-content.css +3 -0
  66. package/src/client/styles/features/preview-markdown.css +201 -0
  67. package/src/client/styles/features/preview-sidebars.css +2 -0
  68. package/src/client/styles/features/quick-switcher.css +167 -0
  69. package/src/client/styles/foundation/themes.css +347 -0
  70. package/src/client/styles/foundation/tokens.css +66 -0
  71. package/src/client/styles/foundation/utilities.css +36 -0
  72. package/src/client/styles/layout/editor-page.css +203 -0
  73. package/src/client/styles/layout/overlays.css +132 -0
  74. package/src/client/styles/layout/responsive.css +251 -0
  75. package/src/client/styles/layout/shell.css +314 -0
  76. package/src/client/styles/layout/sidebar.css +176 -0
  77. package/src/client/styles/layout/view-modes.css +92 -0
  78. package/src/client/styles/overrides/codemirror.css +53 -0
  79. package/src/client/styles/overrides/highlightjs.css +7 -0
  80. package/src/client/styles/overrides/vendor.css +2 -0
  81. package/src/client/styles/primitives/controls.css +276 -0
  82. package/src/client/styles/style.css +25 -4945
  83. package/src/server/auth/create-auth-service.js +373 -15
  84. package/src/server/auth/session-cookie.js +30 -4
  85. package/src/server/config/env.js +121 -5
  86. package/src/server/create-app-server.js +8 -0
  87. package/src/server/domain/collaboration/collaboration-room.js +90 -47
  88. package/src/server/index.js +3 -1
  89. package/src/server/infrastructure/git/command-runner.js +2 -1
  90. package/src/server/infrastructure/git/git-service.js +48 -2
  91. package/src/server/infrastructure/git/history-service.js +683 -0
  92. package/src/server/infrastructure/git/parsers.js +30 -0
  93. package/src/server/infrastructure/git/responses.js +73 -0
  94. package/src/server/infrastructure/http/create-auth-api-handler.js +30 -2
  95. package/src/server/infrastructure/http/create-git-api-command-handler.js +2 -0
  96. package/src/server/infrastructure/http/create-git-api-handler.js +2 -0
  97. package/src/server/infrastructure/http/create-git-api-query-handler.js +61 -0
  98. package/src/server/infrastructure/http/create-request-handler.js +15 -0
  99. package/public/assets/js/chunks/editor-session-EAUBJCHH.js +0 -22
@@ -0,0 +1,347 @@
1
+ /* ===== FOUNDATION / THEMES ===== */
2
+
3
+ :root,
4
+ [data-theme="light"] {
5
+ --color-bg: #f5f5f7;
6
+ --color-surface: #ffffff;
7
+ --color-surface-2: #fafafe;
8
+ --color-surface-offset: #eeeef2;
9
+ --color-surface-offset-2: #e6e6eb;
10
+ --color-surface-dynamic: #dddde3;
11
+ --color-surface-raised: #ffffff;
12
+ --color-surface-ink: #0f1117;
13
+ --color-divider: #d1d1d8;
14
+ --color-border: #c4c4ce;
15
+
16
+ --color-text: #1a1a2e;
17
+ --color-text-muted: #6b6b80;
18
+ --color-text-faint: #a0a0b0;
19
+ --color-text-inverse: #f5f5f7;
20
+
21
+ --color-primary: #4f46e5;
22
+ --color-primary-hover: #4338ca;
23
+ --color-primary-active: #3730a3;
24
+ --color-primary-highlight: #e0e0ff;
25
+ --color-comment: #4f46e5;
26
+ --color-comment-soft: rgba(79, 70, 229, 0.08);
27
+ --color-comment-strong: rgba(79, 70, 229, 0.14);
28
+ --color-comment-text: #3730a3;
29
+
30
+ --color-error: #dc2626;
31
+ --color-error-highlight: #fce8e8;
32
+ --color-success: #16a34a;
33
+ --color-success-highlight: #dcfce7;
34
+ --color-warning: #d97706;
35
+ --color-warning-highlight: #fef3c7;
36
+
37
+ --diff-add-bg: rgba(22, 163, 74, 0.06);
38
+ --diff-add-line-bg: rgba(22, 163, 74, 0.14);
39
+ --diff-add-text: #16a34a;
40
+ --diff-del-bg: rgba(220, 38, 38, 0.06);
41
+ --diff-del-line-bg: rgba(220, 38, 38, 0.14);
42
+ --diff-del-text: #dc2626;
43
+ --diff-hunk-bg: rgba(79, 70, 229, 0.08);
44
+ --diff-hunk-text: #4f46e5;
45
+ --diff-gutter: #a0a0b0;
46
+
47
+ --surface-fill-subtle: color-mix(in oklab, var(--color-surface) 92%, var(--color-surface-offset) 8%);
48
+ --surface-fill-strong: color-mix(in oklab, var(--color-surface-offset) 72%, var(--color-surface-offset-2) 28%);
49
+ --surface-overlay: color-mix(in srgb, var(--color-surface) 84%, var(--color-surface-offset) 16%);
50
+ --surface-overlay-soft: color-mix(in srgb, var(--color-surface) 88%, var(--color-surface-offset) 12%);
51
+ --surface-overlay-strong: color-mix(in srgb, var(--color-surface) 90%, var(--color-surface-offset) 10%);
52
+ --surface-overlay-raised: color-mix(in oklab, var(--color-surface) 94%, transparent);
53
+ --surface-overlay-header: color-mix(in srgb, var(--color-surface-offset) 76%, var(--color-bg) 24%);
54
+ --surface-overlay-offset: color-mix(in oklab, var(--color-surface-offset) 82%, transparent);
55
+ --surface-scrim: oklch(0.1 0 0 / 0.42);
56
+ --surface-scrim-strong: oklch(0.08 0.01 260 / 0.82);
57
+ --surface-inverse-glass: oklch(0.18 0.02 260 / 0.68);
58
+ --surface-inverse-glass-hover: oklch(0.24 0.02 260 / 0.82);
59
+ --surface-media-canvas: #000;
60
+ --surface-embed-canvas: #ffffff;
61
+ --surface-avatar-muted: rgb(255 255 255 / 0.22);
62
+ --surface-avatar-label: rgb(15 17 23 / 0.84);
63
+ --surface-accent-subtle: color-mix(in oklab, var(--color-primary) 8%, var(--color-surface));
64
+ --surface-accent-soft: color-mix(in oklab, var(--color-primary) 16%, transparent);
65
+ --surface-accent-strong: color-mix(in oklab, var(--color-primary) 22%, transparent);
66
+ --surface-success-soft: color-mix(in oklab, var(--color-success) 14%, transparent);
67
+ --surface-warning-soft: color-mix(in oklab, var(--color-warning) 14%, transparent);
68
+ --surface-danger-soft: color-mix(in oklab, var(--color-error) 14%, transparent);
69
+ --surface-comment-shell: linear-gradient(180deg, oklch(from var(--color-comment) l c h / 0.035), transparent 120px), color-mix(in srgb, var(--color-surface) 96%, var(--color-comment) 4%);
70
+ --surface-comment-shell-header: color-mix(in srgb, var(--color-surface) 97%, var(--color-comment) 3%);
71
+ --surface-comment-record: linear-gradient(180deg, oklch(from var(--color-comment) l c h / 0.028), transparent 70%), color-mix(in srgb, var(--color-surface-2) 95%, var(--color-comment) 5%);
72
+ --surface-comment-record-hover: linear-gradient(180deg, oklch(from var(--color-comment) l c h / 0.042), transparent 70%), color-mix(in srgb, var(--color-surface-2) 92%, var(--color-comment) 8%);
73
+ --surface-comment-record-active: linear-gradient(180deg, oklch(from var(--color-comment) l c h / 0.055), transparent 72%), color-mix(in srgb, var(--color-surface-2) 90%, var(--color-comment) 10%);
74
+ --surface-comment-subtle: color-mix(in srgb, var(--color-surface-2) 95%, var(--color-comment) 5%);
75
+ --surface-comment-subtle-strong: color-mix(in srgb, var(--color-surface-2) 92%, var(--color-comment) 8%);
76
+ --surface-comment-card: color-mix(in srgb, var(--color-surface) 94%, var(--color-comment) 6%);
77
+ --surface-comment-elevated: color-mix(in srgb, var(--color-surface) 96%, var(--color-comment) 4%);
78
+ --surface-comment-offset: color-mix(in srgb, var(--color-surface-offset) 90%, var(--color-comment) 10%);
79
+ --surface-comment-offset-soft: color-mix(in srgb, var(--color-surface-offset) 88%, var(--color-comment) 12%);
80
+ --surface-comment-offset-strong: color-mix(in srgb, var(--color-surface-offset) 84%, var(--color-comment) 16%);
81
+ --surface-comment-offset-active: color-mix(in srgb, var(--color-surface-offset) 72%, var(--color-comment) 28%);
82
+ --surface-comment-highlight-hover: color-mix(in srgb, var(--color-comment-soft) 74%, var(--color-comment) 26%);
83
+ --surface-comment-highlight-active: color-mix(in srgb, var(--color-comment-soft) 62%, var(--color-comment) 38%);
84
+ --surface-comment-selection: color-mix(in srgb, var(--color-surface) 25%, var(--color-comment) 75%);
85
+ --surface-comment-preview-fade: linear-gradient(180deg, oklch(0 0 0 / 0), color-mix(in srgb, var(--color-surface-2) 95%, var(--color-comment) 5%));
86
+ --border-comment-soft: color-mix(in srgb, var(--color-divider) 90%, var(--color-comment) 10%);
87
+ --border-comment-muted: color-mix(in srgb, var(--color-divider) 88%, var(--color-comment) 12%);
88
+ --border-comment-strong: color-mix(in srgb, var(--color-border) 82%, var(--color-comment) 18%);
89
+ --border-comment-active: color-mix(in srgb, var(--color-border) 78%, var(--color-comment) 22%);
90
+ --shadow-comment-outline: 0 0 0 1px oklch(from var(--color-comment) l c h / 0.14);
91
+ --surface-warning-toast: linear-gradient(135deg, color-mix(in oklab, #fcd34d 42%, white 58%), color-mix(in oklab, white 94%, #fff7ed 6%) 42%), #fff8e7;
92
+ --border-warning-toast: color-mix(in oklab, #f59e0b 84%, #b45309 16%);
93
+ --text-warning-toast: #422006;
94
+ --shadow-warning-toast: 0 16px 30px rgb(84 46 10 / 0.18), 0 0 0 1px rgb(245 158 11 / 0.12);
95
+ --border-accent-soft: color-mix(in oklab, var(--color-primary) 22%, transparent);
96
+ --border-accent-muted: color-mix(in oklab, var(--color-primary) 24%, var(--color-border));
97
+ --border-accent-strong: color-mix(in oklab, var(--color-primary) 34%, var(--color-border));
98
+ --border-accent-stronger: color-mix(in oklab, var(--color-primary) 40%, var(--color-border));
99
+ --shadow-accent-inset: inset 0 0 0 1px color-mix(in oklab, var(--color-primary) 14%, transparent);
100
+ --shadow-accent-outline: 0 0 0 1px color-mix(in oklab, var(--color-primary) 16%, transparent);
101
+ --shadow-accent-halo: 0 0 0 3px oklch(from var(--color-primary) l c h / 0.16);
102
+ --shadow-accent-ring: 0 0 0 2px var(--color-surface), 0 0 0 4px oklch(from var(--color-primary) l c h / 0.18);
103
+ --shadow-accent-ring-strong: 0 0 0 2px var(--color-bg), 0 0 0 4px oklch(from var(--color-primary) l c h / 0.45);
104
+ --shadow-accent-ring-solid: 0 0 0 2px var(--color-primary), 0 0 0 4px oklch(from var(--color-primary) l c h / 0.2);
105
+ --shadow-elevated-soft: 0 10px 24px color-mix(in oklab, var(--color-surface-ink) 10%, transparent);
106
+ --shadow-floating-soft: 0 14px 34px oklch(0 0 0 / 0.18);
107
+ --shadow-floating-hover: 0 18px 40px oklch(0 0 0 / 0.2);
108
+ --shadow-media-soft: 0 16px 40px oklch(0 0 0 / 0.24);
109
+ --shadow-media-stage: 0 28px 80px oklch(0 0 0 / 0.28);
110
+ --shadow-media-modal: 0 10px 40px rgb(0 0 0 / 0.35);
111
+ --shadow-card-strong: 0 20px 56px oklch(0 0 0 / 0.24);
112
+ --shadow-sheet-inset: inset 0 1px 0 color-mix(in oklab, var(--color-text) 4%, transparent);
113
+ --shadow-focus: 0 0 0 3px oklch(from var(--color-primary) l c h / 0.15);
114
+ --shadow-focus-compact: 0 0 0 2px oklch(from var(--color-primary) l c h / 0.45);
115
+ --interactive-border: color-mix(in oklab, var(--color-primary) 22%, transparent);
116
+ --interactive-surface: color-mix(in oklab, var(--color-primary) 14%, transparent);
117
+ --color-text-on-dark: #ffffff;
118
+ --shadow-sm: 0 1px 2px oklch(0.2 0.02 260 / 0.06);
119
+ --shadow-md: 0 4px 12px oklch(0.2 0.02 260 / 0.08);
120
+ --shadow-lg: 0 12px 32px oklch(0.2 0.02 260 / 0.12);
121
+ }
122
+
123
+ [data-theme="dark"] {
124
+ --color-bg: #0f1117;
125
+ --color-surface: #161822;
126
+ --color-surface-2: #1c1e2c;
127
+ --color-surface-offset: #1a1c28;
128
+ --color-surface-offset-2: #22243a;
129
+ --color-surface-dynamic: #2a2c3e;
130
+ --color-surface-raised: #202330;
131
+ --color-surface-ink: #050608;
132
+ --color-divider: #2e3044;
133
+ --color-border: #383a50;
134
+
135
+ --color-text: #e2e2ea;
136
+ --color-text-muted: #8b8ba0;
137
+ --color-text-faint: #5a5a70;
138
+ --color-text-inverse: #0f1117;
139
+
140
+ --color-primary: #818cf8;
141
+ --color-primary-hover: #6366f1;
142
+ --color-primary-active: #4f46e5;
143
+ --color-primary-highlight: #1e1e3a;
144
+ --color-comment: #818cf8;
145
+ --color-comment-soft: rgba(129, 140, 248, 0.1);
146
+ --color-comment-strong: rgba(129, 140, 248, 0.16);
147
+ --color-comment-text: #c7d2fe;
148
+
149
+ --color-error: #f87171;
150
+ --color-error-highlight: #2a1a1a;
151
+ --color-success: #4ade80;
152
+ --color-success-highlight: #1a2a1a;
153
+ --color-warning: #fbbf24;
154
+ --color-warning-highlight: #2a261a;
155
+
156
+ --diff-add-bg: rgba(74, 222, 128, 0.08);
157
+ --diff-add-line-bg: rgba(74, 222, 128, 0.15);
158
+ --diff-add-text: #4ade80;
159
+ --diff-del-bg: rgba(248, 113, 113, 0.08);
160
+ --diff-del-line-bg: rgba(248, 113, 113, 0.15);
161
+ --diff-del-text: #f87171;
162
+ --diff-hunk-bg: rgba(129, 140, 248, 0.1);
163
+ --diff-hunk-text: #818cf8;
164
+ --diff-gutter: #5a5a70;
165
+
166
+ --surface-fill-subtle: color-mix(in oklab, var(--color-surface) 88%, var(--color-surface-offset) 12%);
167
+ --surface-fill-strong: color-mix(in oklab, var(--color-surface-offset) 60%, var(--color-surface-offset-2) 40%);
168
+ --surface-overlay: color-mix(in srgb, var(--color-surface) 84%, var(--color-surface-offset) 16%);
169
+ --surface-overlay-soft: color-mix(in srgb, var(--color-surface) 88%, var(--color-surface-offset) 12%);
170
+ --surface-overlay-strong: color-mix(in srgb, var(--color-surface) 90%, var(--color-surface-offset) 10%);
171
+ --surface-overlay-raised: color-mix(in oklab, var(--color-surface) 94%, transparent);
172
+ --surface-overlay-header: color-mix(in srgb, var(--color-surface-offset) 76%, var(--color-bg) 24%);
173
+ --surface-overlay-offset: color-mix(in oklab, var(--color-surface-offset) 82%, transparent);
174
+ --surface-scrim: oklch(0.1 0 0 / 0.42);
175
+ --surface-scrim-strong: oklch(0.08 0.01 260 / 0.82);
176
+ --surface-inverse-glass: oklch(0.18 0.02 260 / 0.68);
177
+ --surface-inverse-glass-hover: oklch(0.24 0.02 260 / 0.82);
178
+ --surface-media-canvas: #000;
179
+ --surface-embed-canvas: #121212;
180
+ --surface-avatar-muted: rgb(255 255 255 / 0.22);
181
+ --surface-avatar-label: rgb(15 17 23 / 0.84);
182
+ --surface-accent-subtle: color-mix(in oklab, var(--color-primary) 8%, var(--color-surface));
183
+ --surface-accent-soft: color-mix(in oklab, var(--color-primary) 16%, transparent);
184
+ --surface-accent-strong: color-mix(in oklab, var(--color-primary) 22%, transparent);
185
+ --surface-success-soft: color-mix(in oklab, var(--color-success) 14%, transparent);
186
+ --surface-warning-soft: color-mix(in oklab, var(--color-warning) 14%, transparent);
187
+ --surface-danger-soft: color-mix(in oklab, var(--color-error) 14%, transparent);
188
+ --surface-comment-shell: linear-gradient(180deg, oklch(from var(--color-comment) l c h / 0.035), transparent 120px), color-mix(in srgb, var(--color-surface) 96%, var(--color-comment) 4%);
189
+ --surface-comment-shell-header: color-mix(in srgb, var(--color-surface) 97%, var(--color-comment) 3%);
190
+ --surface-comment-record: linear-gradient(180deg, oklch(from var(--color-comment) l c h / 0.028), transparent 70%), color-mix(in srgb, var(--color-surface-2) 95%, var(--color-comment) 5%);
191
+ --surface-comment-record-hover: linear-gradient(180deg, oklch(from var(--color-comment) l c h / 0.042), transparent 70%), color-mix(in srgb, var(--color-surface-2) 92%, var(--color-comment) 8%);
192
+ --surface-comment-record-active: linear-gradient(180deg, oklch(from var(--color-comment) l c h / 0.055), transparent 72%), color-mix(in srgb, var(--color-surface-2) 90%, var(--color-comment) 10%);
193
+ --surface-comment-subtle: color-mix(in srgb, var(--color-surface-2) 95%, var(--color-comment) 5%);
194
+ --surface-comment-subtle-strong: color-mix(in srgb, var(--color-surface-2) 92%, var(--color-comment) 8%);
195
+ --surface-comment-card: color-mix(in srgb, var(--color-surface) 94%, var(--color-comment) 6%);
196
+ --surface-comment-elevated: color-mix(in srgb, var(--color-surface) 96%, var(--color-comment) 4%);
197
+ --surface-comment-offset: color-mix(in srgb, var(--color-surface-offset) 90%, var(--color-comment) 10%);
198
+ --surface-comment-offset-soft: color-mix(in srgb, var(--color-surface-offset) 88%, var(--color-comment) 12%);
199
+ --surface-comment-offset-strong: color-mix(in srgb, var(--color-surface-offset) 84%, var(--color-comment) 16%);
200
+ --surface-comment-offset-active: color-mix(in srgb, var(--color-surface-offset) 72%, var(--color-comment) 28%);
201
+ --surface-comment-highlight-hover: color-mix(in srgb, var(--color-comment-soft) 74%, var(--color-comment) 26%);
202
+ --surface-comment-highlight-active: color-mix(in srgb, var(--color-comment-soft) 62%, var(--color-comment) 38%);
203
+ --surface-comment-selection: color-mix(in srgb, var(--color-surface) 25%, var(--color-comment) 75%);
204
+ --surface-comment-preview-fade: linear-gradient(180deg, oklch(0 0 0 / 0), color-mix(in srgb, var(--color-surface-2) 95%, var(--color-comment) 5%));
205
+ --border-comment-soft: color-mix(in srgb, var(--color-divider) 90%, var(--color-comment) 10%);
206
+ --border-comment-muted: color-mix(in srgb, var(--color-divider) 88%, var(--color-comment) 12%);
207
+ --border-comment-strong: color-mix(in srgb, var(--color-border) 82%, var(--color-comment) 18%);
208
+ --border-comment-active: color-mix(in srgb, var(--color-border) 78%, var(--color-comment) 22%);
209
+ --shadow-comment-outline: 0 0 0 1px oklch(from var(--color-comment) l c h / 0.14);
210
+ --surface-warning-toast: linear-gradient(135deg, color-mix(in oklab, #f59e0b 32%, transparent), color-mix(in oklab, var(--color-surface) 86%, #0b1022 14%) 42%), color-mix(in oklab, var(--color-surface) 74%, #1b1320 26%);
211
+ --border-warning-toast: color-mix(in oklab, #f59e0b 78%, white 10%);
212
+ --text-warning-toast: color-mix(in oklab, white 92%, #fef3c7 8%);
213
+ --shadow-warning-toast: 0 18px 34px rgb(0 0 0 / 0.38), 0 0 0 1px color-mix(in oklab, #f59e0b 18%, transparent);
214
+ --border-accent-soft: color-mix(in oklab, var(--color-primary) 22%, transparent);
215
+ --border-accent-muted: color-mix(in oklab, var(--color-primary) 24%, var(--color-border));
216
+ --border-accent-strong: color-mix(in oklab, var(--color-primary) 34%, var(--color-border));
217
+ --border-accent-stronger: color-mix(in oklab, var(--color-primary) 40%, var(--color-border));
218
+ --shadow-accent-inset: inset 0 0 0 1px color-mix(in oklab, var(--color-primary) 14%, transparent);
219
+ --shadow-accent-outline: 0 0 0 1px color-mix(in oklab, var(--color-primary) 16%, transparent);
220
+ --shadow-accent-halo: 0 0 0 3px oklch(from var(--color-primary) l c h / 0.16);
221
+ --shadow-accent-ring: 0 0 0 2px var(--color-surface), 0 0 0 4px oklch(from var(--color-primary) l c h / 0.18);
222
+ --shadow-accent-ring-strong: 0 0 0 2px var(--color-bg), 0 0 0 4px oklch(from var(--color-primary) l c h / 0.45);
223
+ --shadow-accent-ring-solid: 0 0 0 2px var(--color-primary), 0 0 0 4px oklch(from var(--color-primary) l c h / 0.2);
224
+ --shadow-elevated-soft: 0 10px 24px color-mix(in oklab, var(--color-surface-ink) 10%, transparent);
225
+ --shadow-floating-soft: 0 14px 34px oklch(0 0 0 / 0.18);
226
+ --shadow-floating-hover: 0 18px 40px oklch(0 0 0 / 0.2);
227
+ --shadow-media-soft: 0 16px 40px oklch(0 0 0 / 0.24);
228
+ --shadow-media-stage: 0 28px 80px oklch(0 0 0 / 0.28);
229
+ --shadow-media-modal: 0 16px 48px rgb(0 0 0 / 0.6);
230
+ --shadow-card-strong: 0 20px 56px oklch(0 0 0 / 0.24);
231
+ --shadow-sheet-inset: inset 0 1px 0 color-mix(in oklab, var(--color-text) 4%, transparent);
232
+ --shadow-focus: 0 0 0 3px oklch(from var(--color-primary) l c h / 0.15);
233
+ --shadow-focus-compact: 0 0 0 2px oklch(from var(--color-primary) l c h / 0.45);
234
+ --interactive-border: color-mix(in oklab, var(--color-primary) 32%, transparent);
235
+ --interactive-surface: color-mix(in oklab, var(--color-primary) 18%, transparent);
236
+ --color-text-on-dark: #ffffff;
237
+ --shadow-sm: 0 1px 2px oklch(0 0 0 / 0.25);
238
+ --shadow-md: 0 4px 12px oklch(0 0 0 / 0.35);
239
+ --shadow-lg: 0 12px 32px oklch(0 0 0 / 0.5);
240
+ }
241
+
242
+ @media (prefers-color-scheme: dark) {
243
+ :root:not([data-theme]) {
244
+ --color-bg: #0f1117;
245
+ --color-surface: #161822;
246
+ --color-surface-2: #1c1e2c;
247
+ --color-surface-offset: #1a1c28;
248
+ --color-surface-offset-2: #22243a;
249
+ --color-surface-dynamic: #2a2c3e;
250
+ --color-surface-raised: #202330;
251
+ --color-surface-ink: #050608;
252
+ --color-divider: #2e3044;
253
+ --color-border: #383a50;
254
+ --color-text: #e2e2ea;
255
+ --color-text-muted: #8b8ba0;
256
+ --color-text-faint: #5a5a70;
257
+ --color-text-inverse: #0f1117;
258
+ --color-primary: #818cf8;
259
+ --color-primary-hover: #6366f1;
260
+ --color-primary-active: #4f46e5;
261
+ --color-primary-highlight: #1e1e3a;
262
+ --color-comment: #818cf8;
263
+ --color-comment-soft: rgba(129, 140, 248, 0.1);
264
+ --color-comment-strong: rgba(129, 140, 248, 0.16);
265
+ --color-comment-text: #c7d2fe;
266
+ --color-error: #f87171;
267
+ --color-error-highlight: #2a1a1a;
268
+ --color-success: #4ade80;
269
+ --color-success-highlight: #1a2a1a;
270
+ --color-warning: #fbbf24;
271
+ --color-warning-highlight: #2a261a;
272
+ --surface-fill-subtle: color-mix(in oklab, var(--color-surface) 88%, var(--color-surface-offset) 12%);
273
+ --surface-fill-strong: color-mix(in oklab, var(--color-surface-offset) 60%, var(--color-surface-offset-2) 40%);
274
+ --surface-overlay: color-mix(in srgb, var(--color-surface) 84%, var(--color-surface-offset) 16%);
275
+ --surface-overlay-soft: color-mix(in srgb, var(--color-surface) 88%, var(--color-surface-offset) 12%);
276
+ --surface-overlay-strong: color-mix(in srgb, var(--color-surface) 90%, var(--color-surface-offset) 10%);
277
+ --surface-overlay-raised: color-mix(in oklab, var(--color-surface) 94%, transparent);
278
+ --surface-overlay-header: color-mix(in srgb, var(--color-surface-offset) 76%, var(--color-bg) 24%);
279
+ --surface-overlay-offset: color-mix(in oklab, var(--color-surface-offset) 82%, transparent);
280
+ --surface-scrim: oklch(0.1 0 0 / 0.42);
281
+ --surface-scrim-strong: oklch(0.08 0.01 260 / 0.82);
282
+ --surface-inverse-glass: oklch(0.18 0.02 260 / 0.68);
283
+ --surface-inverse-glass-hover: oklch(0.24 0.02 260 / 0.82);
284
+ --surface-media-canvas: #000;
285
+ --surface-embed-canvas: #121212;
286
+ --surface-avatar-muted: rgb(255 255 255 / 0.22);
287
+ --surface-avatar-label: rgb(15 17 23 / 0.84);
288
+ --surface-accent-subtle: color-mix(in oklab, var(--color-primary) 8%, var(--color-surface));
289
+ --surface-accent-soft: color-mix(in oklab, var(--color-primary) 16%, transparent);
290
+ --surface-accent-strong: color-mix(in oklab, var(--color-primary) 22%, transparent);
291
+ --surface-success-soft: color-mix(in oklab, var(--color-success) 14%, transparent);
292
+ --surface-warning-soft: color-mix(in oklab, var(--color-warning) 14%, transparent);
293
+ --surface-danger-soft: color-mix(in oklab, var(--color-error) 14%, transparent);
294
+ --surface-comment-shell: linear-gradient(180deg, oklch(from var(--color-comment) l c h / 0.035), transparent 120px), color-mix(in srgb, var(--color-surface) 96%, var(--color-comment) 4%);
295
+ --surface-comment-shell-header: color-mix(in srgb, var(--color-surface) 97%, var(--color-comment) 3%);
296
+ --surface-comment-record: linear-gradient(180deg, oklch(from var(--color-comment) l c h / 0.028), transparent 70%), color-mix(in srgb, var(--color-surface-2) 95%, var(--color-comment) 5%);
297
+ --surface-comment-record-hover: linear-gradient(180deg, oklch(from var(--color-comment) l c h / 0.042), transparent 70%), color-mix(in srgb, var(--color-surface-2) 92%, var(--color-comment) 8%);
298
+ --surface-comment-record-active: linear-gradient(180deg, oklch(from var(--color-comment) l c h / 0.055), transparent 72%), color-mix(in srgb, var(--color-surface-2) 90%, var(--color-comment) 10%);
299
+ --surface-comment-subtle: color-mix(in srgb, var(--color-surface-2) 95%, var(--color-comment) 5%);
300
+ --surface-comment-subtle-strong: color-mix(in srgb, var(--color-surface-2) 92%, var(--color-comment) 8%);
301
+ --surface-comment-card: color-mix(in srgb, var(--color-surface) 94%, var(--color-comment) 6%);
302
+ --surface-comment-elevated: color-mix(in srgb, var(--color-surface) 96%, var(--color-comment) 4%);
303
+ --surface-comment-offset: color-mix(in srgb, var(--color-surface-offset) 90%, var(--color-comment) 10%);
304
+ --surface-comment-offset-soft: color-mix(in srgb, var(--color-surface-offset) 88%, var(--color-comment) 12%);
305
+ --surface-comment-offset-strong: color-mix(in srgb, var(--color-surface-offset) 84%, var(--color-comment) 16%);
306
+ --surface-comment-offset-active: color-mix(in srgb, var(--color-surface-offset) 72%, var(--color-comment) 28%);
307
+ --surface-comment-highlight-hover: color-mix(in srgb, var(--color-comment-soft) 74%, var(--color-comment) 26%);
308
+ --surface-comment-highlight-active: color-mix(in srgb, var(--color-comment-soft) 62%, var(--color-comment) 38%);
309
+ --surface-comment-selection: color-mix(in srgb, var(--color-surface) 25%, var(--color-comment) 75%);
310
+ --surface-comment-preview-fade: linear-gradient(180deg, oklch(0 0 0 / 0), color-mix(in srgb, var(--color-surface-2) 95%, var(--color-comment) 5%));
311
+ --border-comment-soft: color-mix(in srgb, var(--color-divider) 90%, var(--color-comment) 10%);
312
+ --border-comment-muted: color-mix(in srgb, var(--color-divider) 88%, var(--color-comment) 12%);
313
+ --border-comment-strong: color-mix(in srgb, var(--color-border) 82%, var(--color-comment) 18%);
314
+ --border-comment-active: color-mix(in srgb, var(--color-border) 78%, var(--color-comment) 22%);
315
+ --shadow-comment-outline: 0 0 0 1px oklch(from var(--color-comment) l c h / 0.14);
316
+ --surface-warning-toast: linear-gradient(135deg, color-mix(in oklab, #f59e0b 32%, transparent), color-mix(in oklab, var(--color-surface) 86%, #0b1022 14%) 42%), color-mix(in oklab, var(--color-surface) 74%, #1b1320 26%);
317
+ --border-warning-toast: color-mix(in oklab, #f59e0b 78%, white 10%);
318
+ --text-warning-toast: color-mix(in oklab, white 92%, #fef3c7 8%);
319
+ --shadow-warning-toast: 0 18px 34px rgb(0 0 0 / 0.38), 0 0 0 1px color-mix(in oklab, #f59e0b 18%, transparent);
320
+ --border-accent-soft: color-mix(in oklab, var(--color-primary) 22%, transparent);
321
+ --border-accent-muted: color-mix(in oklab, var(--color-primary) 24%, var(--color-border));
322
+ --border-accent-strong: color-mix(in oklab, var(--color-primary) 34%, var(--color-border));
323
+ --border-accent-stronger: color-mix(in oklab, var(--color-primary) 40%, var(--color-border));
324
+ --shadow-accent-inset: inset 0 0 0 1px color-mix(in oklab, var(--color-primary) 14%, transparent);
325
+ --shadow-accent-outline: 0 0 0 1px color-mix(in oklab, var(--color-primary) 16%, transparent);
326
+ --shadow-accent-halo: 0 0 0 3px oklch(from var(--color-primary) l c h / 0.16);
327
+ --shadow-accent-ring: 0 0 0 2px var(--color-surface), 0 0 0 4px oklch(from var(--color-primary) l c h / 0.18);
328
+ --shadow-accent-ring-strong: 0 0 0 2px var(--color-bg), 0 0 0 4px oklch(from var(--color-primary) l c h / 0.45);
329
+ --shadow-accent-ring-solid: 0 0 0 2px var(--color-primary), 0 0 0 4px oklch(from var(--color-primary) l c h / 0.2);
330
+ --shadow-elevated-soft: 0 10px 24px color-mix(in oklab, var(--color-surface-ink) 10%, transparent);
331
+ --shadow-floating-soft: 0 14px 34px oklch(0 0 0 / 0.18);
332
+ --shadow-floating-hover: 0 18px 40px oklch(0 0 0 / 0.2);
333
+ --shadow-media-soft: 0 16px 40px oklch(0 0 0 / 0.24);
334
+ --shadow-media-stage: 0 28px 80px oklch(0 0 0 / 0.28);
335
+ --shadow-media-modal: 0 16px 48px rgb(0 0 0 / 0.6);
336
+ --shadow-card-strong: 0 20px 56px oklch(0 0 0 / 0.24);
337
+ --shadow-sheet-inset: inset 0 1px 0 color-mix(in oklab, var(--color-text) 4%, transparent);
338
+ --shadow-focus: 0 0 0 3px oklch(from var(--color-primary) l c h / 0.15);
339
+ --shadow-focus-compact: 0 0 0 2px oklch(from var(--color-primary) l c h / 0.45);
340
+ --interactive-border: color-mix(in oklab, var(--color-primary) 32%, transparent);
341
+ --interactive-surface: color-mix(in oklab, var(--color-primary) 18%, transparent);
342
+ --color-text-on-dark: #ffffff;
343
+ --shadow-sm: 0 1px 2px oklch(0 0 0 / 0.25);
344
+ --shadow-md: 0 4px 12px oklch(0 0 0 / 0.35);
345
+ --shadow-lg: 0 12px 32px oklch(0 0 0 / 0.5);
346
+ }
347
+ }
@@ -0,0 +1,66 @@
1
+ /* ===== FOUNDATION / TOKENS ===== */
2
+
3
+ :root {
4
+ --text-xs: clamp(0.75rem, 0.7rem + 0.25vw, 0.875rem);
5
+ --text-sm: clamp(0.875rem, 0.8rem + 0.35vw, 1rem);
6
+ --text-base: clamp(1rem, 0.9rem + 0.5vw, 1.125rem);
7
+ --text-lg: clamp(1.125rem, 0.95rem + 0.85vw, 1.5rem);
8
+ --text-xl: clamp(1.5rem, 1rem + 1.5vw, 2.25rem);
9
+ --text-2xl: clamp(2rem, 1.2rem + 2.5vw, 3.5rem);
10
+ --text-label: 12px;
11
+ --text-meta: 11px;
12
+ --text-caption: 10px;
13
+ --text-micro: 9px;
14
+ --text-code-sm: 11.5px;
15
+ --text-ui-sm: 13px;
16
+ --text-ui-md: 14px;
17
+ --text-title-sm: 15px;
18
+ --text-title-md: 18px;
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;
23
+
24
+ --space-1: 0.25rem;
25
+ --space-2: 0.5rem;
26
+ --space-3: 0.75rem;
27
+ --space-4: 1rem;
28
+ --space-5: 1.25rem;
29
+ --space-6: 1.5rem;
30
+ --space-8: 2rem;
31
+ --space-10: 2.5rem;
32
+ --space-12: 3rem;
33
+ --space-16: 4rem;
34
+ --space-20: 5rem;
35
+ --space-24: 6rem;
36
+ --space-32: 8rem;
37
+
38
+ --radius-sm: 0.375rem;
39
+ --radius-md: 0.5rem;
40
+ --radius-lg: 0.75rem;
41
+ --radius-xl: 1rem;
42
+ --radius-2xs: 2px;
43
+ --radius-xs: 4px;
44
+ --radius-lg-plus: 10px;
45
+ --radius-xl-plus: 18px;
46
+ --radius-full: 9999px;
47
+
48
+ --transition-interactive: 180ms cubic-bezier(0.16, 1, 0.3, 1);
49
+
50
+ --content-narrow: 640px;
51
+ --content-default: 960px;
52
+ --content-wide: 1200px;
53
+ --preview-content-width: 720px;
54
+ --panel-comments-width: min(300px, 34vw);
55
+ --panel-comments-min-width: 240px;
56
+ --panel-outline-width: 220px;
57
+
58
+ --toolbar-h: 48px;
59
+ --control-h-xs: 28px;
60
+ --control-h-sm: 30px;
61
+ --control-h-md: 36px;
62
+ --control-h-lg: 44px;
63
+ --control-icon-sm: 14px;
64
+ --control-icon-md: 16px;
65
+ --panel-border-width: 1px;
66
+ }
@@ -0,0 +1,36 @@
1
+ /* ===== FOUNDATION / UTILITIES ===== */
2
+
3
+ .hidden,
4
+ .u-hidden {
5
+ display: none !important;
6
+ }
7
+
8
+ html[data-initial-file-requested="true"] .empty-state {
9
+ display: none !important;
10
+ }
11
+
12
+ html[data-initial-file-requested="true"] .editor-page.hidden {
13
+ display: flex !important;
14
+ }
15
+
16
+ .skip-link {
17
+ position: fixed;
18
+ top: var(--space-2);
19
+ left: var(--space-2);
20
+ z-index: 1000;
21
+ width: auto;
22
+ height: auto;
23
+ padding: var(--space-2) var(--space-4);
24
+ border-radius: var(--radius-md);
25
+ background: var(--color-primary);
26
+ color: var(--color-text-inverse);
27
+ clip: rect(0, 0, 0, 0);
28
+ transform: translateY(calc(-100% - var(--space-2)));
29
+ transition: transform var(--transition-interactive);
30
+ }
31
+
32
+ .skip-link:focus,
33
+ .skip-link:focus-visible {
34
+ clip: auto;
35
+ transform: translateY(0);
36
+ }
@@ -0,0 +1,203 @@
1
+ /* ===== PAGE LAYOUT ===== */
2
+
3
+ .empty-state {
4
+ flex: 1;
5
+ display: flex;
6
+ align-items: center;
7
+ justify-content: center;
8
+ padding: var(--space-8);
9
+ }
10
+
11
+ .empty-state-content {
12
+ display: flex;
13
+ flex-direction: column;
14
+ align-items: center;
15
+ gap: var(--space-2);
16
+ max-width: 320px;
17
+ text-align: center;
18
+ }
19
+
20
+ .empty-state-logo {
21
+ display: inline-flex;
22
+ align-items: center;
23
+ justify-content: center;
24
+ width: 80px;
25
+ height: 80px;
26
+ margin-bottom: var(--space-2);
27
+ border: 1px solid var(--border-accent-soft);
28
+ border-radius: calc(var(--radius-xl-plus) + var(--radius-sm));
29
+ background:
30
+ radial-gradient(circle at top, var(--interactive-border), transparent 70%),
31
+ linear-gradient(180deg, var(--surface-overlay-raised), var(--surface-overlay-soft));
32
+ box-shadow:
33
+ var(--shadow-floating-soft),
34
+ var(--shadow-sheet-inset);
35
+ }
36
+
37
+ .empty-state-logo svg {
38
+ display: block;
39
+ opacity: 0.72;
40
+ }
41
+
42
+ .empty-state-title {
43
+ margin: 0;
44
+ font-size: var(--text-lg);
45
+ font-weight: 600;
46
+ letter-spacing: -0.02em;
47
+ }
48
+
49
+ .empty-state-desc {
50
+ margin: 0;
51
+ color: var(--color-text-muted);
52
+ font-size: var(--text-sm);
53
+ line-height: 1.5;
54
+ }
55
+
56
+ .empty-state-actions {
57
+ display: flex;
58
+ flex-direction: column;
59
+ gap: var(--space-3);
60
+ width: 100%;
61
+ margin-top: var(--space-4);
62
+ }
63
+
64
+ .empty-state-btn {
65
+ justify-content: flex-start;
66
+ padding: var(--space-3) var(--space-4);
67
+ border: 1px solid var(--color-border);
68
+ background: var(--color-surface-offset);
69
+ color: var(--color-text);
70
+ box-shadow: var(--shadow-sm);
71
+ font-size: var(--text-sm);
72
+ }
73
+
74
+ .empty-state-btn:hover {
75
+ border-color: var(--color-text-faint);
76
+ background: var(--color-surface-offset-2);
77
+ }
78
+
79
+ .empty-state-kbd {
80
+ margin-left: auto;
81
+ padding: 2px 6px;
82
+ border: 1px solid var(--color-divider);
83
+ border-radius: var(--radius-xs);
84
+ background: var(--color-surface);
85
+ color: var(--color-text-muted);
86
+ font-family: var(--font-mono);
87
+ font-size: 0.75rem;
88
+ }
89
+
90
+ .editor-page,
91
+ .diff-page {
92
+ display: flex;
93
+ flex: 1;
94
+ flex-direction: column;
95
+ overflow: hidden;
96
+ }
97
+
98
+ .toolbar {
99
+ z-index: 10;
100
+ display: flex;
101
+ align-items: center;
102
+ justify-content: space-between;
103
+ flex-shrink: 0;
104
+ height: var(--toolbar-h);
105
+ gap: var(--space-2);
106
+ padding: 0 var(--space-3);
107
+ border-bottom: 1px solid var(--color-divider);
108
+ background: var(--color-surface);
109
+ }
110
+
111
+ .toolbar-left,
112
+ .toolbar-right {
113
+ display: flex;
114
+ align-items: center;
115
+ gap: var(--space-2);
116
+ }
117
+
118
+ .toolbar-left {
119
+ min-width: 0;
120
+ flex: 1;
121
+ }
122
+
123
+ .toolbar-right {
124
+ flex-shrink: 0;
125
+ }
126
+
127
+ .toolbar-logo {
128
+ display: flex;
129
+ align-items: center;
130
+ flex-shrink: 0;
131
+ padding: var(--space-1);
132
+ border-radius: var(--radius-sm);
133
+ transition: background var(--transition-interactive);
134
+ }
135
+
136
+ .toolbar-logo:hover {
137
+ background: var(--color-surface-offset);
138
+ }
139
+
140
+ .toolbar-room-info {
141
+ display: flex;
142
+ align-items: center;
143
+ gap: var(--space-2);
144
+ min-width: 0;
145
+ }
146
+
147
+ .toolbar-room-name {
148
+ overflow: hidden;
149
+ text-overflow: ellipsis;
150
+ white-space: nowrap;
151
+ font-size: var(--text-sm);
152
+ font-weight: 600;
153
+ }
154
+
155
+ .toolbar-badge {
156
+ flex-shrink: 0;
157
+ white-space: nowrap;
158
+ }
159
+
160
+ .toolbar-center {
161
+ flex-shrink: 0;
162
+ }
163
+
164
+ .diff-mode-toggle,
165
+ .diff-layout-toggle {
166
+ padding: 3px;
167
+ }
168
+
169
+ .diff-mode-btn,
170
+ .diff-layout-btn {
171
+ width: auto;
172
+ height: 28px;
173
+ padding: 0 var(--space-3);
174
+ font-size: var(--text-label);
175
+ font-weight: 600;
176
+ }
177
+
178
+ .diff-mode-btn {
179
+ min-width: 72px;
180
+ }
181
+
182
+ .diff-layout-btn {
183
+ min-width: 82px;
184
+ }
185
+
186
+ .markdown-toolbar {
187
+ display: flex;
188
+ align-items: center;
189
+ flex-wrap: wrap;
190
+ gap: var(--space-1);
191
+ flex-shrink: 0;
192
+ padding: var(--space-1) var(--space-2);
193
+ border-bottom: 1px solid var(--color-divider);
194
+ background: var(--color-surface);
195
+ }
196
+
197
+ .markdown-toolbar-separator {
198
+ width: 1px;
199
+ height: 18px;
200
+ margin: 0 2px;
201
+ flex-shrink: 0;
202
+ background: var(--color-divider);
203
+ }