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
@@ -98,7 +98,7 @@ export class LayoutController {
98
98
  const previewIcon = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>';
99
99
  const editorIcon = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="18" height="18" rx="2"/><line x1="8" y1="8" x2="16" y2="8"/><line x1="8" y1="12" x2="14" y2="12"/><line x1="8" y1="16" x2="12" y2="16"/></svg>';
100
100
 
101
- this.mobileToggleButton.innerHTML = `${label === 'Editor' ? editorIcon : previewIcon}<span class="toolbar-btn-label">${label}</span>`;
101
+ this.mobileToggleButton.innerHTML = `${label === 'Editor' ? editorIcon : previewIcon}<span class="ui-toolbar-button-label">${label}</span>`;
102
102
  }
103
103
 
104
104
  syncViewButtons() {
@@ -0,0 +1,89 @@
1
+ /* ===== COMPONENTS / ACTIONS ===== */
2
+
3
+ .ui-toolbar-action {
4
+ flex-shrink: 0;
5
+ }
6
+
7
+ .ui-action-button {
8
+ min-height: var(--control-h-md);
9
+ padding: 0 14px;
10
+ border-radius: var(--radius-lg-plus);
11
+ font-size: var(--text-label);
12
+ font-weight: 600;
13
+ white-space: nowrap;
14
+ }
15
+
16
+ .ui-action-button--wide {
17
+ min-width: 92px;
18
+ }
19
+
20
+ .ui-action-button--surface {
21
+ background: var(--color-surface-offset);
22
+ }
23
+
24
+ .ui-action-button--surface:hover:not(:disabled) {
25
+ background: var(--color-surface-dynamic);
26
+ }
27
+
28
+ .ui-action-pill {
29
+ flex-shrink: 0;
30
+ min-width: 0;
31
+ }
32
+
33
+ .ui-action-pill--surface {
34
+ background: var(--color-surface-offset);
35
+ }
36
+
37
+ .ui-action-pill--surface:hover:not(:disabled) {
38
+ background: var(--color-surface-dynamic);
39
+ }
40
+
41
+ .ui-action-icon {
42
+ flex-shrink: 0;
43
+ }
44
+
45
+ .ui-action-icon--surface {
46
+ background: var(--surface-overlay-offset);
47
+ }
48
+
49
+ .ui-preview-action {
50
+ display: inline-flex;
51
+ align-items: center;
52
+ justify-content: center;
53
+ flex-shrink: 0;
54
+ padding: 2px 8px;
55
+ border: 1px solid var(--color-border);
56
+ border-radius: var(--radius-xs);
57
+ background: var(--color-surface-2);
58
+ color: var(--color-text);
59
+ box-shadow: inset 0 1px 0 oklch(from var(--color-text) l c h / 0.04);
60
+ font-size: var(--text-xs);
61
+ cursor: pointer;
62
+ transition:
63
+ background var(--transition-interactive),
64
+ color var(--transition-interactive),
65
+ border-color var(--transition-interactive);
66
+ }
67
+
68
+ .ui-preview-action:hover:not(:disabled) {
69
+ background: var(--color-surface-offset);
70
+ border-color: oklch(from var(--color-border) calc(l + 0.08) c h);
71
+ }
72
+
73
+ .ui-preview-action:disabled {
74
+ opacity: 0.5;
75
+ cursor: not-allowed;
76
+ }
77
+
78
+ .ui-preview-action--icon-only {
79
+ width: 30px;
80
+ min-width: 30px;
81
+ height: 30px;
82
+ padding: 0;
83
+ }
84
+
85
+ .ui-preview-action--icon-only svg {
86
+ display: block;
87
+ width: 14px;
88
+ height: 14px;
89
+ }
@@ -0,0 +1,43 @@
1
+ /* ===== COMPONENTS / FEEDBACK ===== */
2
+
3
+ .toast-container {
4
+ position: fixed;
5
+ right: var(--space-4);
6
+ bottom: var(--space-4);
7
+ z-index: 100;
8
+ display: flex;
9
+ flex-direction: column;
10
+ gap: var(--space-2);
11
+ pointer-events: none;
12
+ }
13
+
14
+ .toast {
15
+ max-width: 320px;
16
+ padding: var(--space-2) var(--space-4);
17
+ border: 1px solid var(--color-border);
18
+ border-radius: var(--radius-md);
19
+ background: var(--color-surface-2);
20
+ color: var(--color-text);
21
+ box-shadow: var(--shadow-md);
22
+ font-size: var(--text-xs);
23
+ pointer-events: auto;
24
+ opacity: 1;
25
+ transform: translateX(0) scale(1);
26
+ transition:
27
+ opacity 300ms cubic-bezier(0.16, 1, 0.3, 1),
28
+ transform 300ms cubic-bezier(0.16, 1, 0.3, 1),
29
+ display 300ms cubic-bezier(0.16, 1, 0.3, 1) allow-discrete;
30
+ }
31
+
32
+ @starting-style {
33
+ .toast {
34
+ opacity: 0;
35
+ transform: translateX(8px) scale(0.96);
36
+ }
37
+ }
38
+
39
+ .toast.leaving {
40
+ opacity: 0;
41
+ transform: translateX(8px) scale(0.96);
42
+ pointer-events: none;
43
+ }
@@ -0,0 +1,68 @@
1
+ /* ===== COMPONENTS / NAVIGATION ===== */
2
+
3
+ .ui-toolbar-button {
4
+ display: flex;
5
+ align-items: center;
6
+ gap: var(--space-1);
7
+ padding: var(--space-1) var(--space-2);
8
+ border-radius: var(--radius-md);
9
+ font-size: var(--text-xs);
10
+ }
11
+
12
+ .ui-toolbar-button-label,
13
+ .ui-action-label {
14
+ font-size: var(--text-xs);
15
+ }
16
+
17
+ .ui-toolbar-button--name {
18
+ max-width: 132px;
19
+ }
20
+
21
+ .ui-toolbar-button-text {
22
+ overflow: hidden;
23
+ text-overflow: ellipsis;
24
+ white-space: nowrap;
25
+ }
26
+
27
+ .ui-nav-tabs {
28
+ display: flex;
29
+ padding: 0 var(--space-2);
30
+ border-bottom: 1px solid var(--color-divider);
31
+ }
32
+
33
+ .ui-nav-tab {
34
+ position: relative;
35
+ flex: 1;
36
+ display: inline-flex;
37
+ align-items: center;
38
+ justify-content: center;
39
+ gap: 6px;
40
+ padding: var(--space-2) var(--space-3);
41
+ border-bottom: 2px solid transparent;
42
+ color: var(--color-text-muted);
43
+ transition: all var(--transition-interactive);
44
+ font-size: var(--text-xs);
45
+ font-weight: 500;
46
+ }
47
+
48
+ .ui-nav-tab.has-changes::after {
49
+ content: '';
50
+ position: absolute;
51
+ top: 8px;
52
+ right: 12px;
53
+ width: 6px;
54
+ height: 6px;
55
+ border-radius: 50%;
56
+ background-color: var(--color-success);
57
+ animation: pulse-dot 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
58
+ }
59
+
60
+ .ui-nav-tab:hover {
61
+ background: var(--color-surface-offset);
62
+ color: var(--color-text);
63
+ }
64
+
65
+ .ui-nav-tab.active {
66
+ border-bottom-color: var(--color-primary);
67
+ color: var(--color-primary);
68
+ }
@@ -0,0 +1,104 @@
1
+ /* ===== COMPONENTS / SCROLLBARS ===== */
2
+
3
+ .preview-container,
4
+ .cm-scroller,
5
+ .file-tree,
6
+ .git-panel,
7
+ .diff-scroll,
8
+ .comments-drawer-list,
9
+ .comments-drawer-item-quote,
10
+ .comment-card-quote,
11
+ .comment-card-scroll,
12
+ .markdown-toolbar,
13
+ .comment-markdown pre,
14
+ .comment-markdown .comment-markdown-table,
15
+ .preview-content pre,
16
+ .preview-content .table-wrapper,
17
+ .preview-content .mermaid-frame,
18
+ .preview-content .plantuml-frame,
19
+ .plantuml-maximized-root .plantuml-frame {
20
+ scrollbar-width: thin;
21
+ scrollbar-color: var(--color-surface-dynamic) transparent;
22
+ }
23
+
24
+ .preview-container::-webkit-scrollbar,
25
+ .cm-scroller::-webkit-scrollbar,
26
+ .file-tree::-webkit-scrollbar,
27
+ .git-panel::-webkit-scrollbar,
28
+ .diff-scroll::-webkit-scrollbar,
29
+ .comments-drawer-list::-webkit-scrollbar,
30
+ .comments-drawer-item-quote::-webkit-scrollbar,
31
+ .comment-card-quote::-webkit-scrollbar,
32
+ .comment-card-scroll::-webkit-scrollbar,
33
+ .markdown-toolbar::-webkit-scrollbar,
34
+ .comment-markdown pre::-webkit-scrollbar,
35
+ .comment-markdown .comment-markdown-table::-webkit-scrollbar,
36
+ .preview-content pre::-webkit-scrollbar,
37
+ .preview-content .table-wrapper::-webkit-scrollbar,
38
+ .preview-content .mermaid-frame::-webkit-scrollbar,
39
+ .preview-content .plantuml-frame::-webkit-scrollbar,
40
+ .plantuml-maximized-root .plantuml-frame::-webkit-scrollbar {
41
+ width: 8px;
42
+ height: 8px;
43
+ }
44
+
45
+ .preview-container::-webkit-scrollbar-track,
46
+ .cm-scroller::-webkit-scrollbar-track,
47
+ .file-tree::-webkit-scrollbar-track,
48
+ .git-panel::-webkit-scrollbar-track,
49
+ .diff-scroll::-webkit-scrollbar-track,
50
+ .comments-drawer-list::-webkit-scrollbar-track,
51
+ .comments-drawer-item-quote::-webkit-scrollbar-track,
52
+ .comment-card-quote::-webkit-scrollbar-track,
53
+ .comment-card-scroll::-webkit-scrollbar-track,
54
+ .markdown-toolbar::-webkit-scrollbar-track,
55
+ .comment-markdown pre::-webkit-scrollbar-track,
56
+ .comment-markdown .comment-markdown-table::-webkit-scrollbar-track,
57
+ .preview-content pre::-webkit-scrollbar-track,
58
+ .preview-content .table-wrapper::-webkit-scrollbar-track,
59
+ .preview-content .mermaid-frame::-webkit-scrollbar-track,
60
+ .preview-content .plantuml-frame::-webkit-scrollbar-track,
61
+ .plantuml-maximized-root .plantuml-frame::-webkit-scrollbar-track {
62
+ background: transparent;
63
+ }
64
+
65
+ .preview-container::-webkit-scrollbar-thumb,
66
+ .cm-scroller::-webkit-scrollbar-thumb,
67
+ .file-tree::-webkit-scrollbar-thumb,
68
+ .git-panel::-webkit-scrollbar-thumb,
69
+ .diff-scroll::-webkit-scrollbar-thumb,
70
+ .comments-drawer-list::-webkit-scrollbar-thumb,
71
+ .comments-drawer-item-quote::-webkit-scrollbar-thumb,
72
+ .comment-card-quote::-webkit-scrollbar-thumb,
73
+ .comment-card-scroll::-webkit-scrollbar-thumb,
74
+ .markdown-toolbar::-webkit-scrollbar-thumb,
75
+ .comment-markdown pre::-webkit-scrollbar-thumb,
76
+ .comment-markdown .comment-markdown-table::-webkit-scrollbar-thumb,
77
+ .preview-content pre::-webkit-scrollbar-thumb,
78
+ .preview-content .table-wrapper::-webkit-scrollbar-thumb,
79
+ .preview-content .mermaid-frame::-webkit-scrollbar-thumb,
80
+ .preview-content .plantuml-frame::-webkit-scrollbar-thumb,
81
+ .plantuml-maximized-root .plantuml-frame::-webkit-scrollbar-thumb {
82
+ background: var(--color-surface-dynamic);
83
+ border-radius: var(--radius-full);
84
+ }
85
+
86
+ .preview-container::-webkit-scrollbar-thumb:hover,
87
+ .cm-scroller::-webkit-scrollbar-thumb:hover,
88
+ .file-tree::-webkit-scrollbar-thumb:hover,
89
+ .git-panel::-webkit-scrollbar-thumb:hover,
90
+ .diff-scroll::-webkit-scrollbar-thumb:hover,
91
+ .comments-drawer-list::-webkit-scrollbar-thumb:hover,
92
+ .comments-drawer-item-quote::-webkit-scrollbar-thumb:hover,
93
+ .comment-card-quote::-webkit-scrollbar-thumb:hover,
94
+ .comment-card-scroll::-webkit-scrollbar-thumb:hover,
95
+ .markdown-toolbar::-webkit-scrollbar-thumb:hover,
96
+ .comment-markdown pre::-webkit-scrollbar-thumb:hover,
97
+ .comment-markdown .comment-markdown-table::-webkit-scrollbar-thumb:hover,
98
+ .preview-content pre::-webkit-scrollbar-thumb:hover,
99
+ .preview-content .table-wrapper::-webkit-scrollbar-thumb:hover,
100
+ .preview-content .mermaid-frame::-webkit-scrollbar-thumb:hover,
101
+ .preview-content .plantuml-frame::-webkit-scrollbar-thumb:hover,
102
+ .plantuml-maximized-root .plantuml-frame::-webkit-scrollbar-thumb:hover {
103
+ background: var(--color-text-faint);
104
+ }
@@ -0,0 +1,289 @@
1
+ /* ===== COMPONENTS / STATES ===== */
2
+
3
+ .ui-pill-badge {
4
+ display: inline-flex;
5
+ align-items: center;
6
+ justify-content: center;
7
+ min-height: 20px;
8
+ padding: 2px var(--space-2);
9
+ border-radius: var(--radius-full);
10
+ white-space: nowrap;
11
+ font-size: var(--text-meta);
12
+ font-weight: 600;
13
+ }
14
+
15
+ .ui-pill-badge--count {
16
+ min-width: 20px;
17
+ padding-inline: 6px;
18
+ }
19
+
20
+ .ui-pill-badge--accent {
21
+ background: var(--color-primary-highlight);
22
+ color: var(--color-primary);
23
+ }
24
+
25
+ .ui-pill-badge--solid {
26
+ background: var(--color-primary);
27
+ color: var(--color-text-inverse);
28
+ }
29
+
30
+ .ui-pill-badge--muted {
31
+ background: var(--color-surface-dynamic);
32
+ color: var(--color-text-muted);
33
+ }
34
+
35
+ .ui-pill-badge--code {
36
+ background: var(--color-surface-offset-2);
37
+ color: var(--color-text-faint);
38
+ font-family: var(--font-mono);
39
+ font-size: 9px;
40
+ font-weight: 700;
41
+ letter-spacing: 0.02em;
42
+ }
43
+
44
+ .ui-status-badge {
45
+ display: inline-flex;
46
+ align-items: center;
47
+ justify-content: center;
48
+ flex-shrink: 0;
49
+ padding: 1px 5px;
50
+ border-radius: var(--radius-2xs);
51
+ font-family: var(--font-mono);
52
+ font-size: var(--text-caption);
53
+ font-weight: 600;
54
+ letter-spacing: 0.02em;
55
+ text-transform: uppercase;
56
+ }
57
+
58
+ .ui-status-badge--success {
59
+ color: var(--color-success);
60
+ background: var(--surface-success-soft);
61
+ }
62
+
63
+ .ui-status-badge--warning {
64
+ color: var(--color-warning);
65
+ background: var(--surface-warning-soft);
66
+ }
67
+
68
+ .ui-status-badge--danger {
69
+ color: var(--color-error);
70
+ background: var(--surface-danger-soft);
71
+ }
72
+
73
+ .ui-status-badge--accent {
74
+ color: var(--color-primary);
75
+ background: var(--surface-accent-soft);
76
+ }
77
+
78
+ .ui-status-badge--muted {
79
+ color: var(--color-text-faint);
80
+ background: var(--color-surface-offset);
81
+ }
82
+
83
+ .ui-stat-token {
84
+ display: inline-flex;
85
+ align-items: center;
86
+ gap: 2px;
87
+ font-family: var(--font-mono);
88
+ font-size: var(--text-label);
89
+ white-space: nowrap;
90
+ }
91
+
92
+ .ui-stat-token--add {
93
+ color: var(--diff-add-text);
94
+ }
95
+
96
+ .ui-stat-token--del {
97
+ color: var(--diff-del-text);
98
+ }
99
+
100
+ .ui-chip-button {
101
+ --ui-chip-border: var(--color-border);
102
+ --ui-chip-bg: var(--color-surface);
103
+ --ui-chip-color: var(--color-text-muted);
104
+ --ui-chip-border-hover: var(--ui-chip-border);
105
+ --ui-chip-bg-hover: var(--color-surface-offset);
106
+ --ui-chip-color-hover: var(--color-text);
107
+ --ui-chip-border-active: var(--ui-chip-border-hover);
108
+ --ui-chip-bg-active: var(--ui-chip-bg-hover);
109
+ --ui-chip-color-active: var(--ui-chip-color-hover);
110
+ display: inline-flex;
111
+ align-items: center;
112
+ justify-content: center;
113
+ gap: 6px;
114
+ min-height: 30px;
115
+ padding: 4px 10px;
116
+ border: 1px solid var(--ui-chip-border);
117
+ border-radius: var(--radius-full);
118
+ background: var(--ui-chip-bg);
119
+ color: var(--ui-chip-color);
120
+ transition:
121
+ background var(--transition-interactive),
122
+ border-color var(--transition-interactive),
123
+ color var(--transition-interactive),
124
+ transform 140ms ease;
125
+ font-size: var(--text-meta);
126
+ font-weight: 600;
127
+ }
128
+
129
+ .ui-chip-button:hover {
130
+ color: var(--ui-chip-color-hover);
131
+ border-color: var(--ui-chip-border-hover);
132
+ background: var(--ui-chip-bg-hover);
133
+ }
134
+
135
+ .ui-chip-button.is-active,
136
+ .ui-chip-button[aria-pressed='true'] {
137
+ color: var(--ui-chip-color-active);
138
+ border-color: var(--ui-chip-border-active);
139
+ background: var(--ui-chip-bg-active);
140
+ }
141
+
142
+ .ui-chip-button--comment {
143
+ --ui-chip-border: var(--border-comment-muted);
144
+ --ui-chip-bg: var(--surface-comment-offset);
145
+ --ui-chip-border-hover: oklch(from var(--color-comment) l c h / 0.22);
146
+ --ui-chip-bg-hover: var(--surface-comment-offset-active);
147
+ --ui-chip-border-active: oklch(from var(--color-comment) l c h / 0.28);
148
+ --ui-chip-bg-active: var(--surface-comment-selection);
149
+ --ui-chip-color-active: var(--color-comment);
150
+ }
151
+
152
+ .ui-icon-chip {
153
+ --ui-icon-chip-border: var(--color-border);
154
+ --ui-icon-chip-bg: var(--color-surface-2);
155
+ display: inline-flex;
156
+ align-items: center;
157
+ justify-content: center;
158
+ width: 34px;
159
+ min-width: 34px;
160
+ min-height: 34px;
161
+ padding: 0;
162
+ border: 1px solid var(--ui-icon-chip-border);
163
+ border-radius: var(--radius-md);
164
+ background: var(--ui-icon-chip-bg);
165
+ transition:
166
+ background var(--transition-interactive),
167
+ border-color var(--transition-interactive),
168
+ transform 140ms ease;
169
+ font-size: var(--text-title-md);
170
+ }
171
+
172
+ .ui-icon-chip:hover {
173
+ border-color: var(--ui-icon-chip-border);
174
+ background: var(--ui-icon-chip-bg);
175
+ transform: translateY(-1px);
176
+ }
177
+
178
+ .ui-icon-chip--comment {
179
+ --ui-icon-chip-border: var(--border-comment-muted);
180
+ --ui-icon-chip-bg: var(--surface-comment-subtle-strong);
181
+ }
182
+
183
+ .ui-icon-chip--comment:hover {
184
+ border-color: oklch(from var(--color-comment) l c h / 0.24);
185
+ background: var(--surface-comment-offset-active);
186
+ }
187
+
188
+ .ui-state-marker {
189
+ --ui-marker-border: var(--color-border);
190
+ --ui-marker-bg: var(--color-surface);
191
+ --ui-marker-color: var(--color-text);
192
+ --ui-marker-shadow: var(--shadow-md);
193
+ --ui-marker-border-active: var(--ui-marker-border);
194
+ --ui-marker-bg-active: var(--ui-marker-bg);
195
+ --ui-marker-color-active: var(--ui-marker-color);
196
+ --ui-marker-border-passive: var(--ui-marker-border);
197
+ --ui-marker-bg-passive: var(--ui-marker-bg);
198
+ --ui-marker-border-hover: var(--ui-marker-border-active);
199
+ --ui-marker-bg-hover: var(--ui-marker-bg-active);
200
+ --ui-marker-color-hover: var(--ui-marker-color-active);
201
+ position: absolute;
202
+ display: inline-flex;
203
+ align-items: center;
204
+ justify-content: center;
205
+ gap: 4px;
206
+ min-width: 28px;
207
+ height: 24px;
208
+ padding: 0 7px;
209
+ border: 1px solid var(--ui-marker-border);
210
+ border-radius: var(--radius-full);
211
+ background: var(--ui-marker-bg);
212
+ color: var(--ui-marker-color);
213
+ box-shadow: var(--ui-marker-shadow);
214
+ pointer-events: auto;
215
+ transition:
216
+ transform 140ms ease,
217
+ box-shadow 140ms ease,
218
+ background-color 140ms ease,
219
+ border-color 140ms ease,
220
+ color 140ms ease,
221
+ opacity 140ms ease;
222
+ font-size: var(--text-caption);
223
+ font-weight: 700;
224
+ }
225
+
226
+ .ui-state-marker.is-active {
227
+ border-color: var(--ui-marker-border-active);
228
+ background: var(--ui-marker-bg-active);
229
+ color: var(--ui-marker-color-active);
230
+ }
231
+
232
+ .ui-state-marker.is-passive {
233
+ opacity: 0.48;
234
+ border-color: var(--ui-marker-border-passive);
235
+ background: var(--ui-marker-bg-passive);
236
+ box-shadow: none;
237
+ }
238
+
239
+ .ui-state-marker.is-hovered {
240
+ opacity: 1;
241
+ border-color: var(--ui-marker-border-hover);
242
+ background: var(--ui-marker-bg-hover);
243
+ color: var(--ui-marker-color-hover);
244
+ }
245
+
246
+ .ui-state-marker:hover {
247
+ transform: translateY(-1px) scale(1.04);
248
+ box-shadow: var(--shadow-lg);
249
+ }
250
+
251
+ .ui-state-marker--comment {
252
+ --ui-marker-border: oklch(from var(--color-comment) l c h / 0.24);
253
+ --ui-marker-bg: var(--surface-comment-offset-active);
254
+ --ui-marker-color: var(--color-comment);
255
+ --ui-marker-border-active: oklch(from var(--color-comment) l c h / 0.32);
256
+ --ui-marker-bg-active: var(--surface-comment-selection);
257
+ --ui-marker-color-active: var(--color-text-inverse);
258
+ --ui-marker-border-passive: oklch(from var(--color-comment) l c h / 0.16);
259
+ --ui-marker-bg-passive: var(--surface-comment-offset-soft);
260
+ --ui-marker-border-hover: oklch(from var(--color-comment) l c h / 0.28);
261
+ --ui-marker-bg-hover: var(--surface-comment-offset-strong);
262
+ --ui-marker-color-hover: var(--color-text-inverse);
263
+ }
264
+
265
+ .ui-selection-pill {
266
+ position: absolute;
267
+ min-width: 96px;
268
+ padding: 6px 10px;
269
+ border: 1px solid var(--color-primary);
270
+ border-radius: var(--radius-full);
271
+ text-align: center;
272
+ box-shadow: var(--shadow-md);
273
+ pointer-events: auto;
274
+ transition: transform 140ms ease, box-shadow 140ms ease;
275
+ font-size: var(--text-meta);
276
+ font-weight: 700;
277
+ letter-spacing: 0.02em;
278
+ }
279
+
280
+ .ui-selection-pill:hover {
281
+ transform: translateY(-1px) scale(1.04);
282
+ box-shadow: var(--shadow-lg);
283
+ }
284
+
285
+ .ui-selection-pill--comment {
286
+ border-color: oklch(from var(--color-comment) l c h / 0.22);
287
+ background: var(--surface-comment-selection);
288
+ color: var(--color-text-inverse);
289
+ }