@unbrained/pm-web 1.0.0

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 (150) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/README.md +107 -0
  3. package/dist/auth.js +20 -0
  4. package/dist/auth.js.map +1 -0
  5. package/dist/crypto.js +42 -0
  6. package/dist/crypto.js.map +1 -0
  7. package/dist/db.js +111 -0
  8. package/dist/db.js.map +1 -0
  9. package/dist/index.js +88 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/middleware/auth.js +16 -0
  12. package/dist/middleware/auth.js.map +1 -0
  13. package/dist/routes/admin.js +207 -0
  14. package/dist/routes/admin.js.map +1 -0
  15. package/dist/routes/auth.js +163 -0
  16. package/dist/routes/auth.js.map +1 -0
  17. package/dist/routes/github.js +354 -0
  18. package/dist/routes/github.js.map +1 -0
  19. package/dist/routes/groups.js +180 -0
  20. package/dist/routes/groups.js.map +1 -0
  21. package/dist/routes/pm.js +2446 -0
  22. package/dist/routes/pm.js.map +1 -0
  23. package/dist/routes/projects.js +151 -0
  24. package/dist/routes/projects.js.map +1 -0
  25. package/dist/routes/sharing.js +155 -0
  26. package/dist/routes/sharing.js.map +1 -0
  27. package/dist/server.js +64 -0
  28. package/dist/server.js.map +1 -0
  29. package/dist/services/pm-runner.js +190 -0
  30. package/dist/services/pm-runner.js.map +1 -0
  31. package/dist/services/sse.js +111 -0
  32. package/dist/services/sse.js.map +1 -0
  33. package/manifest.json +15 -0
  34. package/package.json +111 -0
  35. package/public/icons/icon-192.png +0 -0
  36. package/public/icons/icon-512.png +0 -0
  37. package/public/index.html +265 -0
  38. package/public/manifest.json +66 -0
  39. package/public/src/api.js +28 -0
  40. package/public/src/api.js.map +1 -0
  41. package/public/src/api.ts +29 -0
  42. package/public/src/app.js +926 -0
  43. package/public/src/app.js.map +1 -0
  44. package/public/src/app.ts +929 -0
  45. package/public/src/components/modals.js +62 -0
  46. package/public/src/components/modals.js.map +1 -0
  47. package/public/src/components/modals.ts +73 -0
  48. package/public/src/components/toast.js +10 -0
  49. package/public/src/components/toast.js.map +1 -0
  50. package/public/src/components/toast.ts +13 -0
  51. package/public/src/constants.js +30 -0
  52. package/public/src/constants.js.map +1 -0
  53. package/public/src/constants.ts +41 -0
  54. package/public/src/state.js +15 -0
  55. package/public/src/state.js.map +1 -0
  56. package/public/src/state.ts +19 -0
  57. package/public/src/types.js +5 -0
  58. package/public/src/types.js.map +1 -0
  59. package/public/src/types.ts +253 -0
  60. package/public/src/utils.js +57 -0
  61. package/public/src/utils.js.map +1 -0
  62. package/public/src/utils.ts +56 -0
  63. package/public/src/views/activity.js +47 -0
  64. package/public/src/views/activity.js.map +1 -0
  65. package/public/src/views/activity.ts +41 -0
  66. package/public/src/views/admin.js +435 -0
  67. package/public/src/views/admin.js.map +1 -0
  68. package/public/src/views/admin.ts +504 -0
  69. package/public/src/views/auth.js +81 -0
  70. package/public/src/views/auth.js.map +1 -0
  71. package/public/src/views/auth.ts +74 -0
  72. package/public/src/views/calendar.js +133 -0
  73. package/public/src/views/calendar.js.map +1 -0
  74. package/public/src/views/calendar.ts +129 -0
  75. package/public/src/views/comments-audit.js +109 -0
  76. package/public/src/views/comments-audit.js.map +1 -0
  77. package/public/src/views/comments-audit.ts +108 -0
  78. package/public/src/views/config.js +322 -0
  79. package/public/src/views/config.js.map +1 -0
  80. package/public/src/views/config.ts +344 -0
  81. package/public/src/views/context.js +98 -0
  82. package/public/src/views/context.js.map +1 -0
  83. package/public/src/views/context.ts +100 -0
  84. package/public/src/views/create.js +293 -0
  85. package/public/src/views/create.js.map +1 -0
  86. package/public/src/views/create.ts +246 -0
  87. package/public/src/views/dedupe.js +51 -0
  88. package/public/src/views/dedupe.js.map +1 -0
  89. package/public/src/views/dedupe.ts +43 -0
  90. package/public/src/views/export.js +300 -0
  91. package/public/src/views/export.js.map +1 -0
  92. package/public/src/views/export.ts +274 -0
  93. package/public/src/views/github.js +360 -0
  94. package/public/src/views/github.js.map +1 -0
  95. package/public/src/views/github.ts +308 -0
  96. package/public/src/views/graph-canvas.js +1986 -0
  97. package/public/src/views/graph-canvas.js.map +1 -0
  98. package/public/src/views/graph-canvas.ts +2218 -0
  99. package/public/src/views/graph.js +1824 -0
  100. package/public/src/views/graph.js.map +1 -0
  101. package/public/src/views/graph.ts +1891 -0
  102. package/public/src/views/groups.js +186 -0
  103. package/public/src/views/groups.js.map +1 -0
  104. package/public/src/views/groups.ts +172 -0
  105. package/public/src/views/guide.js +151 -0
  106. package/public/src/views/guide.js.map +1 -0
  107. package/public/src/views/guide.ts +162 -0
  108. package/public/src/views/health.js +105 -0
  109. package/public/src/views/health.js.map +1 -0
  110. package/public/src/views/health.ts +102 -0
  111. package/public/src/views/items.js +1306 -0
  112. package/public/src/views/items.js.map +1 -0
  113. package/public/src/views/items.ts +1196 -0
  114. package/public/src/views/normalize.js +67 -0
  115. package/public/src/views/normalize.js.map +1 -0
  116. package/public/src/views/normalize.ts +58 -0
  117. package/public/src/views/plan.js +454 -0
  118. package/public/src/views/plan.js.map +1 -0
  119. package/public/src/views/plan.ts +496 -0
  120. package/public/src/views/projects.js +204 -0
  121. package/public/src/views/projects.js.map +1 -0
  122. package/public/src/views/projects.ts +196 -0
  123. package/public/src/views/router.js +227 -0
  124. package/public/src/views/router.js.map +1 -0
  125. package/public/src/views/router.ts +188 -0
  126. package/public/src/views/search.js +103 -0
  127. package/public/src/views/search.js.map +1 -0
  128. package/public/src/views/search.ts +94 -0
  129. package/public/src/views/settings.js +272 -0
  130. package/public/src/views/settings.js.map +1 -0
  131. package/public/src/views/settings.ts +190 -0
  132. package/public/src/views/shared.js +49 -0
  133. package/public/src/views/shared.js.map +1 -0
  134. package/public/src/views/shared.ts +49 -0
  135. package/public/src/views/sharing.js +152 -0
  136. package/public/src/views/sharing.js.map +1 -0
  137. package/public/src/views/sharing.ts +139 -0
  138. package/public/src/views/stats.js +92 -0
  139. package/public/src/views/stats.js.map +1 -0
  140. package/public/src/views/stats.ts +88 -0
  141. package/public/src/views/templates.js +117 -0
  142. package/public/src/views/templates.js.map +1 -0
  143. package/public/src/views/templates.ts +113 -0
  144. package/public/src/views/validate.js +54 -0
  145. package/public/src/views/validate.js.map +1 -0
  146. package/public/src/views/validate.ts +48 -0
  147. package/public/styles.css +2231 -0
  148. package/public/sw.js +318 -0
  149. package/public/tsconfig.json +20 -0
  150. package/sql/schema.sql +105 -0
@@ -0,0 +1,2231 @@
1
+ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
2
+
3
+ /* ── Accessibility: Skip Link & Screen Reader Only ── */
4
+ .skip-link {
5
+ position: absolute;
6
+ top: -100px;
7
+ left: 50%;
8
+ transform: translateX(-50%);
9
+ background: var(--accent);
10
+ color: #0f172a;
11
+ padding: 10px 20px;
12
+ border-radius: 0 0 var(--radius) var(--radius);
13
+ font-weight: 600;
14
+ font-size: 14px;
15
+ z-index: 10000;
16
+ text-decoration: none;
17
+ transition: top 0.15s ease;
18
+ }
19
+ .skip-link:focus {
20
+ top: 0;
21
+ }
22
+ .sr-only {
23
+ position: absolute;
24
+ width: 1px;
25
+ height: 1px;
26
+ padding: 0;
27
+ margin: -1px;
28
+ overflow: hidden;
29
+ clip: rect(0, 0, 0, 0);
30
+ white-space: nowrap;
31
+ border: 0;
32
+ }
33
+
34
+ /* ── Focus Styles ── */
35
+ :focus-visible {
36
+ outline: 2px solid var(--accent);
37
+ outline-offset: 2px;
38
+ }
39
+ .sidebar-item:focus-visible {
40
+ background: var(--accent-glow);
41
+ color: var(--accent);
42
+ }
43
+ .mobile-bottom-nav-item:focus-visible {
44
+ color: var(--accent);
45
+ background: var(--accent-glow);
46
+ border-radius: var(--radius);
47
+ }
48
+ .content-area:focus {
49
+ outline: none;
50
+ }
51
+
52
+ :root {
53
+ --bg-base: #0a0f1e;
54
+ --bg-sidebar: #0f172a;
55
+ --bg-sidebar-hover: #1e293b;
56
+ --bg-card: #1e293b;
57
+ --bg-card2: #162032;
58
+ --bg-input: #0f172a;
59
+ --bg-modal: #1a2540;
60
+ --border: #1e293b;
61
+ --border-light: #2d3f5a;
62
+ --accent: #2dd4bf;
63
+ --accent-dim: #1a8a7a;
64
+ --accent-glow: rgba(45,212,191,0.15);
65
+ --text-primary: #f1f5f9;
66
+ --text-secondary: #94a3b8;
67
+ --text-muted: #475569;
68
+ --text-accent: #2dd4bf;
69
+ --status-draft: #94a3b8;
70
+ --status-open: #60a5fa;
71
+ --status-in_progress: #2dd4bf;
72
+ --status-blocked: #f87171;
73
+ --status-closed: #4ade80;
74
+ --status-canceled: #6b7280;
75
+ --priority-1: #f87171;
76
+ --priority-2: #fb923c;
77
+ --priority-3: #facc15;
78
+ --priority-4: #60a5fa;
79
+ --priority-5: #94a3b8;
80
+ --radius: 8px;
81
+ --radius-lg: 12px;
82
+ --shadow: 0 4px 24px rgba(0,0,0,0.4);
83
+ --transition: 0.15s ease;
84
+ }
85
+
86
+ html, body { height: 100%; font-family: 'Inter', sans-serif; background: var(--bg-base); color: var(--text-primary); font-size: 14px; line-height: 1.5; }
87
+
88
+ /* ── Scrollbars ── */
89
+ ::-webkit-scrollbar { width: 6px; height: 6px; }
90
+ ::-webkit-scrollbar-track { background: transparent; }
91
+ ::-webkit-scrollbar-thumb { background: var(--border-light); border-radius: 3px; }
92
+ ::-webkit-scrollbar-thumb:hover { background: var(--text-muted); }
93
+
94
+ /* ── Layout ── */
95
+ #app { height: 100vh; display: flex; flex-direction: column; }
96
+ #auth-screen { display: flex; height: 100vh; }
97
+ #main-app { display: flex; flex-direction: column; height: 100vh; overflow: hidden; }
98
+
99
+ /* ── Auth Screen ── */
100
+ .auth-left {
101
+ flex: 1; background: linear-gradient(135deg, #0f172a 0%, #0a1628 60%, #061020 100%);
102
+ display: flex; flex-direction: column; justify-content: center; align-items: center;
103
+ padding: 60px; position: relative; overflow: hidden;
104
+ }
105
+ .auth-left::before {
106
+ content: ''; position: absolute; top: -50%; left: -50%; width: 200%; height: 200%;
107
+ background: radial-gradient(circle at 40% 40%, rgba(45,212,191,0.08) 0%, transparent 60%);
108
+ pointer-events: none;
109
+ }
110
+ .auth-brand { text-align: center; z-index: 1; }
111
+ .auth-logo {
112
+ font-family: 'JetBrains Mono', monospace; font-size: 48px; font-weight: 500;
113
+ color: var(--accent); letter-spacing: -2px; margin-bottom: 16px;
114
+ }
115
+ .auth-logo span { color: var(--text-secondary); }
116
+ .auth-tagline { font-size: 18px; color: var(--text-secondary); margin-bottom: 40px; font-weight: 300; }
117
+ .auth-features { list-style: none; text-align: left; display: inline-block; }
118
+ .auth-features li {
119
+ color: var(--text-secondary); padding: 8px 0; font-size: 14px;
120
+ display: flex; align-items: center; gap: 10px;
121
+ }
122
+ .auth-features li::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: var(--accent); flex-shrink: 0; }
123
+
124
+ .auth-right {
125
+ width: 440px; background: var(--bg-sidebar); display: flex; flex-direction: column;
126
+ justify-content: center; padding: 60px 48px; border-left: 1px solid var(--border);
127
+ }
128
+ .auth-form-title { font-size: 24px; font-weight: 600; margin-bottom: 8px; }
129
+ .auth-form-sub { color: var(--text-secondary); margin-bottom: 32px; font-size: 14px; }
130
+ .auth-toggle {
131
+ display: flex; gap: 4px; background: var(--bg-input); border-radius: var(--radius);
132
+ padding: 4px; margin-bottom: 32px;
133
+ }
134
+ .auth-toggle button {
135
+ flex: 1; padding: 8px; border: none; border-radius: 6px; cursor: pointer;
136
+ font-size: 13px; font-weight: 500; transition: var(--transition);
137
+ background: transparent; color: var(--text-secondary);
138
+ }
139
+ .auth-toggle button.active { background: var(--bg-card); color: var(--text-primary); }
140
+
141
+ /* ── Forms ── */
142
+ .form-group { margin-bottom: 16px; }
143
+ .form-label { display: block; font-size: 12px; font-weight: 500; color: var(--text-secondary); margin-bottom: 6px; letter-spacing: 0.5px; text-transform: uppercase; }
144
+ .form-input, .form-select, .form-textarea {
145
+ width: 100%; background: var(--bg-input); border: 1px solid var(--border-light);
146
+ color: var(--text-primary); border-radius: var(--radius); padding: 10px 12px;
147
+ font-family: inherit; font-size: 14px; transition: var(--transition); outline: none;
148
+ }
149
+ .form-input:focus, .form-select:focus, .form-textarea:focus {
150
+ border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-glow);
151
+ }
152
+ .form-select { cursor: pointer; }
153
+ .form-select option { background: var(--bg-card); }
154
+ .form-textarea { resize: vertical; min-height: 80px; }
155
+ .form-error { color: #f87171; font-size: 12px; margin-top: 8px; }
156
+
157
+ /* ── Buttons ── */
158
+ .btn {
159
+ display: inline-flex; align-items: center; gap: 6px; padding: 9px 16px;
160
+ border: none; border-radius: var(--radius); cursor: pointer; font-family: inherit;
161
+ font-size: 13px; font-weight: 500; transition: var(--transition); text-decoration: none;
162
+ white-space: nowrap;
163
+ }
164
+ .btn-primary { background: var(--accent); color: #0f172a; }
165
+ .btn-primary:hover { background: #34ead4; }
166
+ .btn-secondary { background: var(--bg-card); color: var(--text-primary); border: 1px solid var(--border-light); }
167
+ .btn-secondary:hover { background: var(--bg-sidebar-hover); border-color: var(--accent); }
168
+ .btn-ghost { background: transparent; color: var(--text-secondary); }
169
+ .btn-ghost:hover { background: var(--bg-sidebar-hover); color: var(--text-primary); }
170
+ .btn-danger { background: rgba(248,113,113,0.15); color: #f87171; border: 1px solid rgba(248,113,113,0.3); }
171
+ .btn-danger:hover { background: rgba(248,113,113,0.25); }
172
+ .btn-sm { padding: 6px 12px; font-size: 12px; }
173
+ .btn-lg { padding: 12px 24px; font-size: 15px; font-weight: 600; }
174
+ .btn-full { width: 100%; justify-content: center; }
175
+ .btn:disabled { opacity: 0.5; cursor: not-allowed; }
176
+
177
+ /* ── Top Nav ── */
178
+ #top-nav {
179
+ height: 52px; background: var(--bg-sidebar); border-bottom: 1px solid var(--border);
180
+ display: flex; align-items: center; padding: 0 16px; gap: 12px; flex-shrink: 0;
181
+ z-index: 100;
182
+ }
183
+ .nav-logo { font-family: 'JetBrains Mono', monospace; font-size: 18px; color: var(--accent); font-weight: 500; letter-spacing: -1px; flex-shrink: 0; }
184
+ .nav-logo span { color: var(--text-muted); }
185
+ .nav-divider { width: 1px; height: 20px; background: var(--border-light); flex-shrink: 0; }
186
+ .project-selector-wrap { flex: 1; max-width: 320px; }
187
+ .project-selector {
188
+ width: 100%; background: var(--bg-input); border: 1px solid var(--border-light);
189
+ color: var(--text-primary); border-radius: var(--radius); padding: 7px 10px;
190
+ font-family: inherit; font-size: 13px; cursor: pointer; outline: none; transition: var(--transition);
191
+ }
192
+ .project-selector:focus { border-color: var(--accent); }
193
+ .project-selector option { background: var(--bg-sidebar); }
194
+ .nav-spacer { flex: 1; }
195
+ .nav-search-hint {
196
+ font-size: 11px; color: var(--text-muted); background: var(--bg-input);
197
+ border: 1px solid var(--border); border-radius: 6px; padding: 4px 8px;
198
+ font-family: 'JetBrains Mono', monospace; cursor: pointer; transition: var(--transition);
199
+ }
200
+ .nav-search-hint:hover { border-color: var(--accent); color: var(--text-secondary); }
201
+ .user-menu { display: flex; align-items: center; gap: 8px; }
202
+ .user-avatar {
203
+ width: 30px; height: 30px; border-radius: 50%; background: var(--accent-dim);
204
+ display: flex; align-items: center; justify-content: center; font-size: 12px;
205
+ font-weight: 600; color: var(--accent); flex-shrink: 0;
206
+ }
207
+ .user-name { font-size: 13px; color: var(--text-secondary); }
208
+
209
+ /* ── App Body ── */
210
+ #app-body { display: flex; flex: 1; overflow: hidden; }
211
+
212
+ /* ── Sidebar ── */
213
+ #sidebar {
214
+ width: 220px; background: var(--bg-sidebar); border-right: 1px solid var(--border);
215
+ display: flex; flex-direction: column; flex-shrink: 0; overflow-y: auto;
216
+ padding: 12px 0;
217
+ }
218
+ .sidebar-section { margin-bottom: 4px; }
219
+ .sidebar-section-label {
220
+ font-size: 10px; font-weight: 600; color: var(--text-muted); letter-spacing: 1px;
221
+ text-transform: uppercase; padding: 8px 16px 4px;
222
+ }
223
+ .sidebar-item {
224
+ display: flex; align-items: center; gap: 10px; padding: 8px 16px;
225
+ cursor: pointer; transition: var(--transition); color: var(--text-secondary);
226
+ font-size: 13px; border-left: 2px solid transparent; user-select: none;
227
+ }
228
+ .sidebar-item:hover { background: var(--bg-sidebar-hover); color: var(--text-primary); }
229
+ .sidebar-item.active { background: var(--accent-glow); color: var(--accent); border-left-color: var(--accent); }
230
+ .sidebar-item-icon { font-size: 14px; width: 18px; text-align: center; flex-shrink: 0; }
231
+ .sidebar-badge {
232
+ margin-left: auto; font-size: 10px; background: var(--bg-card);
233
+ color: var(--text-muted); padding: 1px 6px; border-radius: 10px; font-family: 'JetBrains Mono', monospace;
234
+ }
235
+ .sidebar-item.active .sidebar-badge { background: var(--accent-dim); color: var(--accent); }
236
+
237
+ .sidebar-empty {
238
+ padding: 24px 16px; text-align: center; color: var(--text-muted); font-size: 12px;
239
+ }
240
+
241
+ /* ── Main Content ── */
242
+ #main-content { flex: 1; overflow-y: auto; display: flex; flex-direction: column; }
243
+ .content-area { padding: 24px; flex: 1; }
244
+
245
+ /* ── Page Header ── */
246
+ .page-header { display: flex; align-items: flex-start; justify-content: space-between; margin-bottom: 24px; gap: 16px; }
247
+ .page-title { font-size: 20px; font-weight: 600; }
248
+ .page-subtitle { color: var(--text-secondary); font-size: 13px; margin-top: 2px; }
249
+ .page-actions { display: flex; gap: 8px; flex-shrink: 0; }
250
+
251
+ /* ── Welcome / No Project ── */
252
+ .welcome-state {
253
+ display: flex; flex-direction: column; align-items: center; justify-content: center;
254
+ height: 100%; min-height: 400px; text-align: center; padding: 40px;
255
+ }
256
+ .welcome-icon { font-size: 48px; margin-bottom: 20px; opacity: 0.4; }
257
+ .welcome-title { font-size: 22px; font-weight: 600; margin-bottom: 8px; }
258
+ .welcome-text { color: var(--text-secondary); max-width: 360px; line-height: 1.7; margin-bottom: 24px; }
259
+
260
+ /* ── Cards ── */
261
+ .card { background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius-lg); }
262
+ .card-header { padding: 16px 20px; border-bottom: 1px solid var(--border); display: flex; align-items: center; justify-content: space-between; }
263
+ .card-title { font-size: 14px; font-weight: 600; }
264
+ .card-body { padding: 20px; }
265
+
266
+ /* ── Filter Bar ── */
267
+ .filter-bar { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 16px; }
268
+ .filter-select {
269
+ background: var(--bg-input); border: 1px solid var(--border-light); color: var(--text-secondary);
270
+ border-radius: var(--radius); padding: 6px 10px; font-family: inherit; font-size: 12px;
271
+ cursor: pointer; outline: none; transition: var(--transition);
272
+ }
273
+ .filter-select:focus, .filter-select:hover { border-color: var(--accent); color: var(--text-primary); }
274
+ .filter-select option { background: var(--bg-sidebar); }
275
+
276
+ /* ── Item List ── */
277
+ .item-list { display: flex; flex-direction: column; gap: 2px; }
278
+ .item-row {
279
+ display: flex; align-items: center; gap: 12px; padding: 10px 14px;
280
+ background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius);
281
+ cursor: pointer; transition: var(--transition);
282
+ }
283
+ .item-row:hover { border-color: var(--border-light); background: var(--bg-sidebar-hover); transform: translateX(2px); }
284
+ .item-type-icon { font-size: 14px; width: 20px; text-align: center; flex-shrink: 0; color: var(--text-muted); }
285
+ .item-id { font-family: 'JetBrains Mono', monospace; font-size: 11px; color: var(--text-muted); flex-shrink: 0; min-width: 70px; }
286
+ .item-title { flex: 1; font-size: 13px; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
287
+ .item-meta { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
288
+ .status-badge {
289
+ font-size: 10px; font-weight: 500; padding: 2px 8px; border-radius: 10px;
290
+ text-transform: uppercase; letter-spacing: 0.5px;
291
+ }
292
+ .status-draft { background: rgba(148,163,184,0.15); color: var(--status-draft); }
293
+ .status-open { background: rgba(96,165,250,0.15); color: var(--status-open); }
294
+ .status-in_progress { background: rgba(45,212,191,0.15); color: var(--status-in_progress); }
295
+ .status-blocked { background: rgba(248,113,113,0.15); color: var(--status-blocked); }
296
+ .status-closed { background: rgba(74,222,128,0.15); color: var(--status-closed); }
297
+ .status-canceled { background: rgba(107,114,128,0.15); color: var(--status-canceled); }
298
+
299
+ .priority-dot {
300
+ width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0;
301
+ }
302
+ .priority-1 { background: var(--priority-1); }
303
+ .priority-2 { background: var(--priority-2); }
304
+ .priority-3 { background: var(--priority-3); }
305
+ .priority-4 { background: var(--priority-4); }
306
+ .priority-5 { background: var(--priority-5); }
307
+
308
+ .item-tags { display: flex; gap: 4px; flex-wrap: wrap; }
309
+ .tag { font-size: 10px; background: rgba(45,212,191,0.1); color: var(--accent); padding: 1px 6px; border-radius: 4px; font-family: 'JetBrains Mono', monospace; }
310
+
311
+ /* ── Empty State ── */
312
+ .empty-state { padding: 48px; text-align: center; color: var(--text-muted); }
313
+ .empty-state-icon { font-size: 36px; margin-bottom: 12px; opacity: 0.5; }
314
+ .empty-state-text { font-size: 14px; }
315
+ .empty-state-sub { font-size: 12px; margin-top: 4px; }
316
+
317
+ /* ── Loading ── */
318
+ .loading-spinner {
319
+ display: inline-block; width: 16px; height: 16px; border: 2px solid var(--border-light);
320
+ border-top-color: var(--accent); border-radius: 50%; animation: spin 0.7s linear infinite;
321
+ }
322
+ @keyframes spin { to { transform: rotate(360deg); } }
323
+ .loading-state { padding: 48px; text-align: center; }
324
+ .loading-state .loading-spinner { width: 24px; height: 24px; }
325
+
326
+ /* ── Modals ── */
327
+ .modal-backdrop {
328
+ position: fixed; inset: 0; background: rgba(0,0,0,0.7); backdrop-filter: blur(4px);
329
+ display: flex; align-items: center; justify-content: center; z-index: 1000;
330
+ padding: 20px; animation: fadeIn 0.15s ease;
331
+ }
332
+ @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
333
+ .modal {
334
+ background: var(--bg-modal); border: 1px solid var(--border-light); border-radius: var(--radius-lg);
335
+ width: 100%; max-width: 560px; max-height: 90vh; overflow: hidden; display: flex; flex-direction: column;
336
+ box-shadow: var(--shadow); animation: slideUp 0.15s ease;
337
+ }
338
+ .modal-wide { max-width: 740px; }
339
+ @keyframes slideUp { from { transform: translateY(12px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
340
+ .modal-header { padding: 20px 24px 16px; border-bottom: 1px solid var(--border); display: flex; align-items: center; justify-content: space-between; flex-shrink: 0; }
341
+ .modal-title { font-size: 16px; font-weight: 600; }
342
+ .modal-close { background: none; border: none; color: var(--text-muted); cursor: pointer; font-size: 18px; padding: 4px; border-radius: 4px; transition: var(--transition); }
343
+ .modal-close:hover { color: var(--text-primary); background: var(--bg-sidebar-hover); }
344
+ .modal-body { padding: 24px; overflow-y: auto; flex: 1; }
345
+ .modal-footer { padding: 16px 24px; border-top: 1px solid var(--border); display: flex; justify-content: flex-end; gap: 8px; flex-shrink: 0; }
346
+
347
+ /* ── Item Detail ── */
348
+ .item-detail-header { margin-bottom: 24px; }
349
+ .item-detail-id { font-family: 'JetBrains Mono', monospace; font-size: 12px; color: var(--text-muted); margin-bottom: 6px; }
350
+ .item-detail-title { font-size: 20px; font-weight: 600; margin-bottom: 12px; line-height: 1.3; }
351
+ .item-detail-meta { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
352
+ .meta-chip {
353
+ display: flex; align-items: center; gap: 5px; background: var(--bg-input);
354
+ border: 1px solid var(--border-light); border-radius: 6px; padding: 4px 10px;
355
+ font-size: 12px; color: var(--text-secondary);
356
+ }
357
+ .meta-chip strong { color: var(--text-primary); }
358
+ .item-detail-desc { color: var(--text-secondary); line-height: 1.7; font-size: 14px; white-space: pre-wrap; }
359
+ .item-detail-section { margin-bottom: 24px; }
360
+ .item-detail-section-title { font-size: 11px; font-weight: 600; color: var(--text-muted); text-transform: uppercase; letter-spacing: 1px; margin-bottom: 12px; }
361
+
362
+ .comment-item { display: flex; gap: 12px; margin-bottom: 16px; }
363
+ .comment-avatar { width: 28px; height: 28px; border-radius: 50%; background: var(--bg-card); display: flex; align-items: center; justify-content: center; font-size: 11px; color: var(--text-muted); flex-shrink: 0; }
364
+ .comment-body { flex: 1; }
365
+ .comment-meta { font-size: 11px; color: var(--text-muted); margin-bottom: 4px; }
366
+ .comment-text { font-size: 13px; color: var(--text-secondary); line-height: 1.6; white-space: pre-wrap; }
367
+
368
+ .history-item { display: flex; gap: 12px; margin-bottom: 10px; align-items: flex-start; }
369
+ .history-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--accent-dim); flex-shrink: 0; margin-top: 5px; }
370
+ .history-text { font-size: 12px; color: var(--text-secondary); }
371
+ .history-time { font-size: 11px; color: var(--text-muted); }
372
+
373
+ /* ── Activity ── */
374
+ .activity-item { display: flex; gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--border); }
375
+ .activity-item:last-child { border-bottom: none; }
376
+ .activity-icon { width: 28px; height: 28px; border-radius: 6px; background: var(--bg-input); display: flex; align-items: center; justify-content: center; font-size: 13px; flex-shrink: 0; }
377
+ .activity-body { flex: 1; }
378
+ .activity-desc { font-size: 13px; color: var(--text-primary); }
379
+ .activity-time { font-size: 11px; color: var(--text-muted); margin-top: 2px; }
380
+
381
+ /* ── Stats ── */
382
+ .stats-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 12px; margin-bottom: 24px; }
383
+ .stat-card { background: var(--bg-card2); border: 1px solid var(--border); border-radius: var(--radius-lg); padding: 16px; }
384
+ .stat-icon { font-size: 16px; color: var(--text-muted); margin-bottom: 6px; line-height: 1; }
385
+ .stat-value { font-size: 28px; font-weight: 700; font-family: 'JetBrains Mono', monospace; color: var(--accent); line-height: 1; }
386
+ .stat-label { font-size: 11px; color: var(--text-muted); margin-top: 4px; text-transform: uppercase; letter-spacing: 0.5px; }
387
+
388
+ .breakdown-row { display: flex; align-items: center; gap: 10px; padding: 6px 0; border-bottom: 1px solid var(--border); }
389
+ .breakdown-row:last-child { border-bottom: none; }
390
+ .breakdown-label { flex: 1; font-size: 13px; color: var(--text-secondary); }
391
+ .breakdown-count { font-family: 'JetBrains Mono', monospace; font-size: 13px; color: var(--text-primary); min-width: 30px; text-align: right; }
392
+ .breakdown-bar-wrap { width: 80px; height: 4px; background: var(--border); border-radius: 2px; overflow: hidden; }
393
+ .breakdown-bar { height: 100%; background: var(--accent); border-radius: 2px; transition: width 0.5s ease; }
394
+
395
+ /* ── Calendar ── */
396
+ .calendar-event { padding: 10px 14px; border-left: 3px solid var(--accent); background: var(--bg-card2); border-radius: 0 var(--radius) var(--radius) 0; margin-bottom: 8px; cursor: pointer; transition: var(--transition); }
397
+ .calendar-event:hover { background: var(--bg-sidebar-hover); }
398
+ .calendar-event-title { font-size: 13px; font-weight: 500; }
399
+ .calendar-event-date { font-size: 11px; color: var(--text-muted); margin-top: 2px; }
400
+ .calendar-event-id { font-family: 'JetBrains Mono', monospace; font-size: 10px; color: var(--text-muted); }
401
+
402
+ /* ── Context ── */
403
+ .context-section { margin-bottom: 20px; }
404
+ .context-section-title { font-size: 13px; font-weight: 600; color: var(--accent); margin-bottom: 10px; display: flex; align-items: center; gap: 8px; }
405
+ .context-block { background: var(--bg-input); border: 1px solid var(--border); border-radius: var(--radius); padding: 12px 14px; font-family: 'JetBrains Mono', monospace; font-size: 12px; color: var(--text-secondary); white-space: pre-wrap; overflow-x: auto; }
406
+ .context-item-row { display: flex; align-items: center; gap: 10px; padding: 6px 0; border-bottom: 1px solid var(--border); font-size: 13px; }
407
+ .context-item-row:last-child { border-bottom: none; }
408
+
409
+ /* ── Graph (Immersive) ── */
410
+
411
+ /* Full-screen graph mode: hide sidebar */
412
+ body.graph-mode #sidebar {
413
+ display: none;
414
+ }
415
+ body.graph-mode #app-body {
416
+ position: relative;
417
+ }
418
+
419
+ #content-graph {
420
+ padding: 0;
421
+ overflow: hidden;
422
+ position: relative;
423
+ }
424
+
425
+ .graph-immersive-wrap {
426
+ position: relative;
427
+ width: 100%;
428
+ height: 100%;
429
+ overflow: hidden;
430
+ background: #080d1a;
431
+ }
432
+
433
+ .graph-canvas-host {
434
+ position: absolute;
435
+ inset: 0;
436
+ background: #080d1a;
437
+ overflow: hidden;
438
+ }
439
+
440
+ /* HUD Top bar */
441
+ .graph-hud-top {
442
+ position: absolute;
443
+ top: 0; left: 0; right: 0;
444
+ z-index: 20;
445
+ display: flex;
446
+ align-items: center;
447
+ gap: 10px;
448
+ padding: 10px 14px;
449
+ background: linear-gradient(to bottom, rgba(8,13,26,0.94) 0%, rgba(8,13,26,0) 100%);
450
+ pointer-events: none;
451
+ }
452
+ .graph-hud-top > * { pointer-events: auto; }
453
+
454
+ .graph-hud-left {
455
+ display: flex;
456
+ flex-direction: column;
457
+ gap: 3px;
458
+ flex-shrink: 0;
459
+ min-width: 0;
460
+ }
461
+ .graph-hud-title {
462
+ display: flex;
463
+ align-items: center;
464
+ gap: 7px;
465
+ font-size: 14px;
466
+ font-weight: 700;
467
+ color: var(--text-primary);
468
+ white-space: nowrap;
469
+ }
470
+ .graph-mode-chip {
471
+ font-family: 'JetBrains Mono', monospace;
472
+ font-size: 9px;
473
+ font-weight: 500;
474
+ padding: 2px 7px;
475
+ border-radius: 999px;
476
+ background: rgba(148,163,184,0.12);
477
+ color: var(--text-muted);
478
+ border: 1px solid rgba(148,163,184,0.2);
479
+ letter-spacing: 0.06em;
480
+ text-transform: uppercase;
481
+ }
482
+ .graph-mode-chip.neo4j {
483
+ background: rgba(45,212,191,0.1);
484
+ color: var(--accent);
485
+ border-color: rgba(45,212,191,0.3);
486
+ }
487
+ .graph-hud-stats {
488
+ display: flex;
489
+ gap: 12px;
490
+ font-size: 11px;
491
+ color: var(--text-muted);
492
+ flex-wrap: wrap;
493
+ }
494
+ .graph-hud-stats span { white-space: nowrap; }
495
+ .graph-hud-stats b { color: var(--text-secondary); font-weight: 600; margin-right: 2px; }
496
+ .graph-hud-warn b { color: #fb923c; }
497
+ .graph-hud-center {
498
+ flex: 1;
499
+ max-width: 520px;
500
+ margin: 0 auto;
501
+ display: flex;
502
+ flex-direction: column;
503
+ gap: 7px;
504
+ }
505
+ .graph-search-hud {
506
+ display: flex;
507
+ align-items: center;
508
+ gap: 8px;
509
+ background: rgba(10,15,30,0.82);
510
+ border: 1px solid rgba(148,163,184,0.18);
511
+ border-radius: 8px;
512
+ padding: 0 12px;
513
+ height: 36px;
514
+ backdrop-filter: blur(8px);
515
+ transition: border-color 0.15s;
516
+ }
517
+ .graph-search-hud:focus-within { border-color: rgba(45,212,191,0.5); }
518
+ .graph-search-hud-icon { color: var(--text-muted); font-size: 15px; flex-shrink: 0; }
519
+ .graph-search-hud-input {
520
+ flex: 1;
521
+ background: transparent;
522
+ border: none;
523
+ outline: none;
524
+ color: var(--text-primary);
525
+ font-size: 13px;
526
+ font-family: 'Inter', sans-serif;
527
+ }
528
+ .graph-search-hud-input::placeholder { color: var(--text-muted); }
529
+ .graph-preset-rail {
530
+ display: grid;
531
+ grid-template-columns: repeat(6, minmax(0, 1fr));
532
+ gap: 5px;
533
+ pointer-events: auto;
534
+ }
535
+ .graph-preset-btn {
536
+ min-width: 0;
537
+ height: 34px;
538
+ display: flex;
539
+ align-items: center;
540
+ justify-content: space-between;
541
+ gap: 6px;
542
+ padding: 5px 8px;
543
+ border: 1px solid rgba(148,163,184,0.16);
544
+ border-radius: 7px;
545
+ background: rgba(10,15,30,0.74);
546
+ color: var(--text-secondary);
547
+ cursor: pointer;
548
+ backdrop-filter: blur(8px);
549
+ transition: border-color 0.15s, background 0.15s, color 0.15s;
550
+ }
551
+ .graph-preset-btn:hover {
552
+ border-color: rgba(148,163,184,0.34);
553
+ background: rgba(10,15,30,0.92);
554
+ color: var(--text-primary);
555
+ }
556
+ .graph-preset-btn.active {
557
+ border-color: rgba(45,212,191,0.42);
558
+ background: rgba(45,212,191,0.10);
559
+ color: var(--accent);
560
+ }
561
+ .graph-preset-btn span,
562
+ .graph-preset-btn strong {
563
+ min-width: 0;
564
+ overflow: hidden;
565
+ text-overflow: ellipsis;
566
+ white-space: nowrap;
567
+ }
568
+ .graph-preset-btn span {
569
+ font-size: 11px;
570
+ font-weight: 650;
571
+ }
572
+ .graph-preset-btn strong {
573
+ color: var(--text-muted);
574
+ font-family: 'JetBrains Mono', monospace;
575
+ font-size: 9px;
576
+ font-weight: 600;
577
+ text-transform: uppercase;
578
+ }
579
+ .graph-preset-btn.active strong { color: var(--accent); }
580
+ .graph-hud-right {
581
+ display: flex;
582
+ align-items: center;
583
+ gap: 5px;
584
+ flex-shrink: 0;
585
+ }
586
+ .graph-hud-btn {
587
+ display: inline-flex;
588
+ align-items: center;
589
+ gap: 5px;
590
+ background: rgba(10,15,30,0.82);
591
+ border: 1px solid rgba(148,163,184,0.18);
592
+ border-radius: 6px;
593
+ color: var(--text-secondary);
594
+ font-size: 12px;
595
+ font-family: 'Inter', sans-serif;
596
+ padding: 5px 10px;
597
+ cursor: pointer;
598
+ white-space: nowrap;
599
+ backdrop-filter: blur(8px);
600
+ transition: border-color 0.15s, color 0.15s, background 0.15s;
601
+ height: 30px;
602
+ flex-shrink: 0;
603
+ }
604
+ .graph-hud-btn:hover {
605
+ border-color: rgba(148,163,184,0.4);
606
+ color: var(--text-primary);
607
+ background: rgba(10,15,30,0.92);
608
+ }
609
+ .graph-hud-btn.active {
610
+ border-color: rgba(45,212,191,0.45);
611
+ color: var(--accent);
612
+ background: rgba(45,212,191,0.08);
613
+ }
614
+
615
+ /* Filter overlay (bottom-left) */
616
+ .graph-filter-overlay {
617
+ position: absolute;
618
+ bottom: 40px;
619
+ left: 12px;
620
+ z-index: 20;
621
+ min-width: 240px;
622
+ background: rgba(8,13,26,0.96);
623
+ border: 1px solid rgba(148,163,184,0.18);
624
+ border-radius: 12px;
625
+ backdrop-filter: blur(14px);
626
+ box-shadow: 0 8px 32px rgba(0,0,0,0.55);
627
+ display: none;
628
+ flex-direction: column;
629
+ overflow: hidden;
630
+ }
631
+ .graph-filter-overlay.open { display: flex; }
632
+ .graph-filter-overlay-header {
633
+ display: flex;
634
+ justify-content: space-between;
635
+ align-items: center;
636
+ padding: 10px 14px;
637
+ border-bottom: 1px solid rgba(148,163,184,0.1);
638
+ font-size: 11px;
639
+ font-weight: 600;
640
+ color: var(--text-muted);
641
+ letter-spacing: 0.07em;
642
+ text-transform: uppercase;
643
+ }
644
+ .graph-filter-close-btn {
645
+ background: none;
646
+ border: none;
647
+ color: var(--text-muted);
648
+ cursor: pointer;
649
+ padding: 2px 6px;
650
+ border-radius: 4px;
651
+ font-size: 14px;
652
+ line-height: 1;
653
+ }
654
+ .graph-filter-close-btn:hover { color: var(--text-primary); background: rgba(148,163,184,0.1); }
655
+ .graph-filter-overlay-body { padding: 12px 14px; display: flex; flex-direction: column; gap: 8px; }
656
+ .graph-filter-row {
657
+ display: grid;
658
+ grid-template-columns: 72px 1fr;
659
+ align-items: center;
660
+ gap: 8px;
661
+ }
662
+ .graph-filter-row-depth {
663
+ display: flex;
664
+ flex-direction: column;
665
+ gap: 6px;
666
+ }
667
+ .graph-filter-row-depth label {
668
+ font-size: 11px;
669
+ color: var(--text-muted);
670
+ font-weight: 500;
671
+ }
672
+ .graph-filter-row label {
673
+ font-size: 11px;
674
+ color: var(--text-muted);
675
+ font-weight: 500;
676
+ }
677
+ .graph-filter-row select {
678
+ background: rgba(15,20,35,0.9);
679
+ border: 1px solid rgba(148,163,184,0.18);
680
+ border-radius: 6px;
681
+ color: var(--text-secondary);
682
+ font-size: 12px;
683
+ padding: 5px 8px;
684
+ cursor: pointer;
685
+ outline: none;
686
+ appearance: none;
687
+ }
688
+ .graph-filter-row select:focus { border-color: rgba(45,212,191,0.4); }
689
+ .graph-scope-btn {
690
+ margin-top: 4px;
691
+ width: 100%;
692
+ background: rgba(45,212,191,0.1);
693
+ border: 1px solid rgba(45,212,191,0.25);
694
+ border-radius: 6px;
695
+ color: var(--accent);
696
+ font-size: 12px;
697
+ padding: 7px 10px;
698
+ cursor: pointer;
699
+ transition: background 0.15s;
700
+ text-align: center;
701
+ font-family: 'Inter', sans-serif;
702
+ }
703
+ .graph-scope-btn:hover { background: rgba(45,212,191,0.18); }
704
+ .graph-dep-mode-btn {
705
+ display: flex;
706
+ align-items: center;
707
+ justify-content: space-between;
708
+ gap: 10px;
709
+ width: 100%;
710
+ margin-top: 2px;
711
+ background: rgba(251,146,60,0.08);
712
+ border: 1px solid rgba(251,146,60,0.22);
713
+ border-radius: 6px;
714
+ color: var(--text-secondary);
715
+ font-size: 12px;
716
+ padding: 7px 9px;
717
+ cursor: pointer;
718
+ font-family: 'Inter', sans-serif;
719
+ }
720
+ .graph-dep-mode-btn:hover,
721
+ .graph-dep-mode-btn.active {
722
+ background: rgba(251,146,60,0.14);
723
+ border-color: rgba(251,146,60,0.48);
724
+ color: #fed7aa;
725
+ }
726
+ .graph-dep-mode-btn strong {
727
+ color: #fb923c;
728
+ font-family: 'JetBrains Mono', monospace;
729
+ font-size: 10px;
730
+ text-transform: uppercase;
731
+ }
732
+ .graph-filter-note {
733
+ color: var(--text-muted);
734
+ font-size: 11px;
735
+ line-height: 1.35;
736
+ }
737
+
738
+ /* Legend HUD (bottom-center) */
739
+ .graph-legend-hud {
740
+ position: absolute;
741
+ bottom: 10px;
742
+ left: 50%;
743
+ transform: translateX(-50%);
744
+ z-index: 15;
745
+ display: flex;
746
+ flex-wrap: wrap;
747
+ justify-content: center;
748
+ gap: 7px 12px;
749
+ align-items: center;
750
+ background: rgba(8,13,26,0.82);
751
+ border: 1px solid rgba(148,163,184,0.14);
752
+ border-radius: 999px;
753
+ padding: 5px 16px;
754
+ backdrop-filter: blur(10px);
755
+ color: var(--text-muted);
756
+ font-size: 11px;
757
+ white-space: nowrap;
758
+ pointer-events: none;
759
+ }
760
+ .graph-legend-hud span { display: inline-flex; align-items: center; gap: 5px; }
761
+
762
+ .legend-dot {
763
+ width: 7px;
764
+ height: 7px;
765
+ border-radius: 50%;
766
+ display: inline-block;
767
+ }
768
+ .legend-item { background: var(--accent); }
769
+ .legend-facet { background: #60a5fa; }
770
+ .legend-sep { color: var(--text-muted); padding: 0 2px; }
771
+ .legend-external { background: #f87171; }
772
+ .legend-line {
773
+ width: 18px;
774
+ height: 1px;
775
+ display: inline-block;
776
+ background: rgba(148,163,184,0.5);
777
+ }
778
+ .legend-tag-btn {
779
+ display: inline-flex;
780
+ align-items: center;
781
+ gap: 4px;
782
+ padding: 1px 6px 1px 4px;
783
+ border: 1px solid transparent;
784
+ border-radius: 10px;
785
+ background: transparent;
786
+ cursor: pointer;
787
+ font: inherit;
788
+ font-size: 10px;
789
+ color: var(--text-secondary);
790
+ transition: background 0.12s, border-color 0.12s;
791
+ }
792
+ .legend-tag-btn:hover { background: rgba(255,255,255,0.06); }
793
+ .legend-tag-btn.active { background: rgba(45,212,191,0.10); border-color: rgba(45,212,191,0.35); }
794
+
795
+ /* Info drawer (right side) */
796
+ .graph-info-drawer {
797
+ position: absolute;
798
+ top: 0; right: 0; bottom: 0;
799
+ z-index: 20;
800
+ width: 304px;
801
+ background: rgba(8,13,26,0.97);
802
+ border-left: 1px solid rgba(148,163,184,0.15);
803
+ display: flex;
804
+ flex-direction: column;
805
+ transform: translateX(100%);
806
+ transition: transform 0.22s cubic-bezier(0.4,0,0.2,1);
807
+ backdrop-filter: blur(16px);
808
+ box-shadow: -4px 0 24px rgba(0,0,0,0.45);
809
+ }
810
+ .graph-info-drawer.open { transform: translateX(0); }
811
+ .graph-info-drawer-header {
812
+ display: flex;
813
+ justify-content: space-between;
814
+ align-items: center;
815
+ padding: 11px 14px;
816
+ border-bottom: 1px solid rgba(148,163,184,0.1);
817
+ flex-shrink: 0;
818
+ gap: 8px;
819
+ }
820
+ .graph-info-drawer-title {
821
+ font-size: 13px;
822
+ font-weight: 600;
823
+ color: var(--text-primary);
824
+ }
825
+ .graph-info-drawer-body {
826
+ flex: 1;
827
+ overflow-y: auto;
828
+ padding: 14px;
829
+ scrollbar-width: thin;
830
+ scrollbar-color: rgba(148,163,184,0.2) transparent;
831
+ }
832
+
833
+ /* Relationship drawer (bottom) */
834
+ .graph-rel-drawer {
835
+ position: absolute;
836
+ left: 0; right: 0; bottom: 0;
837
+ z-index: 18;
838
+ max-height: 300px;
839
+ background: rgba(8,13,26,0.97);
840
+ border-top: 1px solid rgba(148,163,184,0.15);
841
+ display: flex;
842
+ flex-direction: column;
843
+ transform: translateY(100%);
844
+ transition: transform 0.22s cubic-bezier(0.4,0,0.2,1);
845
+ backdrop-filter: blur(16px);
846
+ box-shadow: 0 -4px 24px rgba(0,0,0,0.4);
847
+ }
848
+ .graph-rel-drawer.open { transform: translateY(0); }
849
+ .graph-rel-drawer-header {
850
+ display: flex;
851
+ justify-content: space-between;
852
+ align-items: center;
853
+ padding: 9px 16px;
854
+ border-bottom: 1px solid rgba(148,163,184,0.1);
855
+ flex-shrink: 0;
856
+ font-size: 11px;
857
+ font-weight: 600;
858
+ color: var(--text-muted);
859
+ letter-spacing: 0.06em;
860
+ text-transform: uppercase;
861
+ }
862
+ .graph-rel-drawer-body {
863
+ overflow-y: auto;
864
+ padding: 0 14px;
865
+ scrollbar-width: thin;
866
+ scrollbar-color: rgba(148,163,184,0.2) transparent;
867
+ }
868
+
869
+ /* Info panel content (used inside drawer) */
870
+ .graph-panel-title {
871
+ font-size: 11px;
872
+ font-weight: 600;
873
+ color: var(--text-muted);
874
+ letter-spacing: 0.08em;
875
+ text-transform: uppercase;
876
+ margin-bottom: 12px;
877
+ }
878
+ .graph-panel-title-spaced { margin-top: 18px; }
879
+ .graph-limit-note { margin-top: 10px; color: var(--text-muted); font-size: 12px; }
880
+ .graph-rel-row {
881
+ display: grid;
882
+ grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
883
+ gap: 12px;
884
+ align-items: center;
885
+ width: 100%;
886
+ background: transparent;
887
+ border: 0;
888
+ border-bottom: 1px solid var(--border);
889
+ padding: 10px 0;
890
+ color: inherit;
891
+ text-align: left;
892
+ cursor: pointer;
893
+ }
894
+ .graph-rel-row:last-child { border-bottom: none; }
895
+ .graph-rel-row:hover .graph-rel-title { color: var(--accent); }
896
+ .graph-rel-title {
897
+ font-size: 13px;
898
+ color: var(--text-primary);
899
+ white-space: nowrap;
900
+ overflow: hidden;
901
+ text-overflow: ellipsis;
902
+ }
903
+ .graph-rel-id {
904
+ font-family: 'JetBrains Mono', monospace;
905
+ font-size: 11px;
906
+ color: var(--text-muted);
907
+ }
908
+ .graph-rel-type {
909
+ font-family: 'JetBrains Mono', monospace;
910
+ font-size: 10px;
911
+ color: var(--accent);
912
+ border: 1px solid var(--border-light);
913
+ border-radius: 999px;
914
+ padding: 4px 8px;
915
+ white-space: nowrap;
916
+ }
917
+ .graph-rel-props {
918
+ display: flex;
919
+ flex-wrap: wrap;
920
+ gap: 4px;
921
+ margin-top: 4px;
922
+ font-size: 10px;
923
+ color: var(--text-muted);
924
+ font-family: 'JetBrains Mono', monospace;
925
+ }
926
+ .graph-rel-props em {
927
+ color: var(--text-secondary);
928
+ font-style: normal;
929
+ font-weight: 600;
930
+ }
931
+ .graph-rel-props span {
932
+ background: rgba(148,163,184,0.07);
933
+ border-radius: 4px;
934
+ padding: 1px 5px;
935
+ }
936
+ .graph-type-list { display: flex; flex-direction: column; gap: 0; margin-top: 4px; }
937
+ .graph-type-row {
938
+ display: flex;
939
+ justify-content: space-between;
940
+ border-bottom: 1px solid var(--border);
941
+ padding: 7px 0;
942
+ font-size: 13px;
943
+ color: var(--text-secondary);
944
+ }
945
+ .graph-type-row strong { color: var(--text-primary); font-family: 'JetBrains Mono', monospace; }
946
+ .graph-node-list { display: flex; flex-direction: column; gap: 6px; }
947
+ .graph-node {
948
+ width: 100%;
949
+ display: flex;
950
+ justify-content: space-between;
951
+ gap: 10px;
952
+ text-align: left;
953
+ background: var(--bg-input);
954
+ border: 1px solid var(--border);
955
+ border-radius: var(--radius);
956
+ color: var(--text-primary);
957
+ padding: 9px 10px;
958
+ cursor: pointer;
959
+ }
960
+ .graph-node:hover { border-color: var(--accent-dim); }
961
+ .graph-node strong {
962
+ display: block;
963
+ font-size: 13px;
964
+ white-space: nowrap;
965
+ overflow: hidden;
966
+ text-overflow: ellipsis;
967
+ }
968
+ .graph-node small {
969
+ display: block;
970
+ color: var(--text-muted);
971
+ font-size: 11px;
972
+ margin-top: 2px;
973
+ }
974
+ .graph-node em {
975
+ color: var(--accent);
976
+ font-style: normal;
977
+ font-size: 11px;
978
+ flex-shrink: 0;
979
+ }
980
+ .graph-node-empty { color: var(--text-muted); font-size: 13px; line-height: 1.45; }
981
+ .graph-coverage-grid {
982
+ display: grid;
983
+ grid-template-columns: repeat(3, minmax(0, 1fr));
984
+ gap: 8px;
985
+ margin-bottom: 14px;
986
+ }
987
+ .graph-coverage-card {
988
+ min-width: 0;
989
+ border: 1px solid var(--border);
990
+ border-radius: var(--radius);
991
+ background: var(--bg-input);
992
+ padding: 9px 10px;
993
+ }
994
+ .graph-coverage-card span {
995
+ display: block;
996
+ color: var(--text-muted);
997
+ font-size: 10px;
998
+ font-weight: 600;
999
+ text-transform: uppercase;
1000
+ }
1001
+ .graph-coverage-card strong {
1002
+ display: block;
1003
+ margin-top: 4px;
1004
+ overflow: hidden;
1005
+ color: var(--text-primary);
1006
+ font-size: 13px;
1007
+ text-overflow: ellipsis;
1008
+ white-space: nowrap;
1009
+ font-weight: 700;
1010
+ letter-spacing: -0.02em;
1011
+ }
1012
+ .graph-coverage-card em {
1013
+ display: block;
1014
+ margin-top: 2px;
1015
+ color: var(--text-muted);
1016
+ font-size: 11px;
1017
+ font-style: normal;
1018
+ line-height: 1.3;
1019
+ }
1020
+ /* Coverage progress bar */
1021
+ .graph-coverage-bar {
1022
+ width: 100%;
1023
+ height: 4px;
1024
+ background: rgba(148,163,184,0.12);
1025
+ border-radius: 2px;
1026
+ overflow: hidden;
1027
+ margin-top: 4px;
1028
+ }
1029
+ .graph-coverage-fill {
1030
+ height: 100%;
1031
+ background: var(--accent);
1032
+ border-radius: 2px;
1033
+ transition: width 0.6s ease;
1034
+ }
1035
+ /* HUD select dropdown (layout) */
1036
+ .graph-hud-select-wrap {
1037
+ display: inline-flex;
1038
+ align-items: center;
1039
+ }
1040
+ .graph-hud-select {
1041
+ background: rgba(10,15,30,0.82);
1042
+ border: 1px solid rgba(148,163,184,0.18);
1043
+ border-radius: 6px;
1044
+ color: var(--text-secondary);
1045
+ font-size: 12px;
1046
+ font-family: 'Inter', sans-serif;
1047
+ padding: 5px 8px;
1048
+ cursor: pointer;
1049
+ outline: none;
1050
+ appearance: none;
1051
+ height: 30px;
1052
+ backdrop-filter: blur(8px);
1053
+ transition: border-color 0.15s, color 0.15s;
1054
+ }
1055
+ .graph-hud-select:hover {
1056
+ border-color: rgba(148,163,184,0.4);
1057
+ color: var(--text-primary);
1058
+ }
1059
+ .graph-hud-select option {
1060
+ background: #0f172a;
1061
+ color: var(--text-primary);
1062
+ }
1063
+ /* Relationship edit bar */
1064
+ .graph-rel-edit-bar {
1065
+ display: flex;
1066
+ gap: 8px;
1067
+ padding: 10px 0;
1068
+ border-bottom: 1px solid var(--border);
1069
+ margin-bottom: 6px;
1070
+ }
1071
+ .graph-selected-title { font-size: 15px; font-weight: 700; color: var(--text-primary); line-height: 1.3; }
1072
+ .graph-selected-meta { margin-top: 4px; color: var(--text-muted); font-family: 'JetBrains Mono', monospace; font-size: 11px; overflow-wrap: anywhere; }
1073
+ .graph-selected-actions { display: flex; gap: 8px; margin-top: 12px; flex-wrap: wrap; }
1074
+ .graph-selected-counts {
1075
+ display: flex;
1076
+ gap: 8px;
1077
+ flex-wrap: wrap;
1078
+ margin-top: 10px;
1079
+ }
1080
+ .graph-selected-counts span {
1081
+ border: 1px solid var(--border);
1082
+ border-radius: 999px;
1083
+ color: var(--text-secondary);
1084
+ font-family: 'JetBrains Mono', monospace;
1085
+ font-size: 10px;
1086
+ padding: 4px 8px;
1087
+ }
1088
+ .graph-blocker-strip {
1089
+ display: flex;
1090
+ flex-wrap: wrap;
1091
+ gap: 6px;
1092
+ margin-top: 10px;
1093
+ }
1094
+ .graph-blocker-strip span {
1095
+ border: 1px solid rgba(251,146,60,0.24);
1096
+ border-radius: 999px;
1097
+ background: rgba(251,146,60,0.08);
1098
+ color: #fed7aa;
1099
+ font-size: 10px;
1100
+ padding: 4px 8px;
1101
+ }
1102
+ .graph-blocker-strip strong { color: #fb923c; }
1103
+ .graph-blocker-strip .critical {
1104
+ border-color: rgba(251,191,36,0.45);
1105
+ background: rgba(251,191,36,0.12);
1106
+ color: #fde68a;
1107
+ }
1108
+ .graph-blocker-list {
1109
+ display: flex;
1110
+ flex-direction: column;
1111
+ gap: 6px;
1112
+ }
1113
+ .graph-blocker-row {
1114
+ display: grid;
1115
+ grid-template-columns: 72px minmax(0, 1fr);
1116
+ gap: 8px;
1117
+ width: 100%;
1118
+ padding: 8px 9px;
1119
+ background: rgba(15,23,42,0.74);
1120
+ border: 1px solid var(--border);
1121
+ border-radius: var(--radius);
1122
+ color: inherit;
1123
+ text-align: left;
1124
+ cursor: pointer;
1125
+ }
1126
+ .graph-blocker-row:hover { border-color: rgba(251,146,60,0.42); }
1127
+ .graph-blocker-row span {
1128
+ color: #fb923c;
1129
+ font-family: 'JetBrains Mono', monospace;
1130
+ font-size: 9px;
1131
+ text-transform: uppercase;
1132
+ }
1133
+ .graph-blocker-row strong {
1134
+ min-width: 0;
1135
+ overflow: hidden;
1136
+ text-overflow: ellipsis;
1137
+ white-space: nowrap;
1138
+ color: var(--text-secondary);
1139
+ font-size: 12px;
1140
+ }
1141
+ .graph-property-grid {
1142
+ display: grid;
1143
+ gap: 0;
1144
+ margin-top: 10px;
1145
+ }
1146
+ .graph-property-row {
1147
+ display: grid;
1148
+ grid-template-columns: 78px minmax(0, 1fr);
1149
+ gap: 8px;
1150
+ border-bottom: 1px solid var(--border);
1151
+ padding: 5px 0;
1152
+ font-size: 12px;
1153
+ }
1154
+ .graph-property-row span { color: var(--text-muted); }
1155
+ .graph-property-row strong {
1156
+ min-width: 0;
1157
+ overflow-wrap: anywhere;
1158
+ color: var(--text-secondary);
1159
+ font-weight: 500;
1160
+ }
1161
+ .graph-tag-list {
1162
+ display: flex;
1163
+ flex-wrap: wrap;
1164
+ gap: 6px;
1165
+ margin-top: 10px;
1166
+ }
1167
+ .graph-tag-chip {
1168
+ max-width: 100%;
1169
+ overflow: hidden;
1170
+ text-overflow: ellipsis;
1171
+ white-space: nowrap;
1172
+ border: 1px solid rgba(45,212,191,0.24);
1173
+ border-radius: 999px;
1174
+ background: rgba(45,212,191,0.08);
1175
+ color: var(--accent);
1176
+ padding: 4px 8px;
1177
+ font-size: 11px;
1178
+ cursor: pointer;
1179
+ }
1180
+ .graph-tag-chip:hover { border-color: var(--accent); }
1181
+ .graph-neighbor {
1182
+ display: flex;
1183
+ justify-content: space-between;
1184
+ gap: 10px;
1185
+ width: 100%;
1186
+ background: transparent;
1187
+ border: 0;
1188
+ padding: 7px 0;
1189
+ border-bottom: 1px solid var(--border);
1190
+ font-size: 12px;
1191
+ color: inherit;
1192
+ text-align: left;
1193
+ cursor: pointer;
1194
+ }
1195
+ .graph-neighbor:last-child { border-bottom: none; }
1196
+ .graph-neighbor span { color: var(--text-muted); }
1197
+ .graph-neighbor strong { color: var(--text-secondary); font-weight: 500; }
1198
+ .graph-neighbor:hover strong { color: var(--text-primary); }
1199
+ .graph-rel-badge {
1200
+ display: inline-block;
1201
+ font-family: 'JetBrains Mono', monospace;
1202
+ font-size: 9px;
1203
+ color: var(--accent);
1204
+ border: 1px solid var(--border-light);
1205
+ border-radius: 999px;
1206
+ padding: 2px 6px;
1207
+ margin-right: 4px;
1208
+ white-space: nowrap;
1209
+ }
1210
+ .graph-insight-list {
1211
+ display: flex;
1212
+ flex-direction: column;
1213
+ gap: 6px;
1214
+ }
1215
+ .graph-insight-row {
1216
+ display: grid;
1217
+ grid-template-columns: minmax(0, 1fr) minmax(28px, auto);
1218
+ gap: 4px 10px;
1219
+ width: 100%;
1220
+ padding: 9px 10px;
1221
+ background: var(--bg-input);
1222
+ border: 1px solid var(--border);
1223
+ border-radius: var(--radius);
1224
+ color: inherit;
1225
+ text-align: left;
1226
+ cursor: pointer;
1227
+ }
1228
+ .graph-insight-row:hover { border-color: var(--accent-dim); }
1229
+ .graph-insight-row.critical {
1230
+ border-color: rgba(251,191,36,0.28);
1231
+ background: rgba(251,191,36,0.06);
1232
+ }
1233
+ .graph-insight-row.critical b { color: #fbbf24; }
1234
+ .graph-insight-row span { min-width: 0; }
1235
+ .graph-insight-row strong {
1236
+ display: block;
1237
+ overflow: hidden;
1238
+ text-overflow: ellipsis;
1239
+ white-space: nowrap;
1240
+ font-size: 12px;
1241
+ }
1242
+ .graph-insight-row em {
1243
+ display: block;
1244
+ margin-top: 2px;
1245
+ color: var(--text-muted);
1246
+ font-family: 'JetBrains Mono', monospace;
1247
+ font-size: 10px;
1248
+ font-style: normal;
1249
+ }
1250
+ .graph-insight-row b {
1251
+ align-self: center;
1252
+ color: var(--accent);
1253
+ font-family: 'JetBrains Mono', monospace;
1254
+ }
1255
+ .graph-insight-row small {
1256
+ grid-column: 1 / -1;
1257
+ color: var(--text-muted);
1258
+ font-size: 11px;
1259
+ line-height: 1.35;
1260
+ overflow-wrap: anywhere;
1261
+ }
1262
+ .graph-chain-list {
1263
+ display: flex;
1264
+ flex-direction: column;
1265
+ gap: 7px;
1266
+ }
1267
+ .graph-chain-row {
1268
+ display: block;
1269
+ width: 100%;
1270
+ padding: 9px 10px;
1271
+ border: 1px solid var(--border);
1272
+ border-radius: var(--radius);
1273
+ background: rgba(15,23,42,0.74);
1274
+ color: inherit;
1275
+ text-align: left;
1276
+ cursor: pointer;
1277
+ }
1278
+ .graph-chain-row:hover { border-color: var(--accent-dim); }
1279
+ .graph-chain-row.critical {
1280
+ border-color: rgba(251,191,36,0.30);
1281
+ background: rgba(251,191,36,0.07);
1282
+ }
1283
+ .graph-chain-row.warning {
1284
+ border-color: rgba(248,113,113,0.34);
1285
+ background: rgba(248,113,113,0.08);
1286
+ }
1287
+ .graph-chain-row.root {
1288
+ border-color: rgba(45,212,191,0.24);
1289
+ background: rgba(45,212,191,0.06);
1290
+ }
1291
+ .graph-chain-row span {
1292
+ display: flex;
1293
+ flex-wrap: wrap;
1294
+ align-items: center;
1295
+ gap: 5px;
1296
+ color: var(--text-secondary);
1297
+ font-size: 12px;
1298
+ font-weight: 650;
1299
+ line-height: 1.35;
1300
+ }
1301
+ .graph-chain-row i {
1302
+ color: var(--text-muted);
1303
+ font-family: 'JetBrains Mono', monospace;
1304
+ font-style: normal;
1305
+ font-weight: 500;
1306
+ }
1307
+ .graph-chain-row small {
1308
+ display: block;
1309
+ margin-top: 4px;
1310
+ color: var(--text-muted);
1311
+ font-size: 11px;
1312
+ line-height: 1.35;
1313
+ }
1314
+ .graph-path-section { margin-bottom: 10px; }
1315
+ .graph-path-label {
1316
+ margin-bottom: 6px;
1317
+ color: var(--text-muted);
1318
+ font-family: 'JetBrains Mono', monospace;
1319
+ font-size: 10px;
1320
+ text-transform: uppercase;
1321
+ }
1322
+ .graph-path-chips {
1323
+ display: flex;
1324
+ flex-wrap: wrap;
1325
+ gap: 6px;
1326
+ }
1327
+ .graph-path-chips span {
1328
+ color: var(--text-muted);
1329
+ font-size: 12px;
1330
+ }
1331
+ .graph-path-chip {
1332
+ max-width: 100%;
1333
+ overflow: hidden;
1334
+ text-overflow: ellipsis;
1335
+ white-space: nowrap;
1336
+ padding: 5px 8px;
1337
+ border: 1px solid var(--border);
1338
+ border-radius: 999px;
1339
+ background: var(--bg-input);
1340
+ color: var(--text-secondary);
1341
+ cursor: pointer;
1342
+ }
1343
+ .graph-path-chip:hover {
1344
+ border-color: var(--accent-dim);
1345
+ color: var(--text-primary);
1346
+ }
1347
+
1348
+ /* ── Physics Controls Panel ──────────────────────────────────── */
1349
+ .graph-physics-panel {
1350
+ position: absolute;
1351
+ bottom: 56px;
1352
+ left: 14px;
1353
+ z-index: 30;
1354
+ width: 270px;
1355
+ background: rgba(8,13,26,0.96);
1356
+ border: 1px solid rgba(148,163,184,0.2);
1357
+ border-radius: 10px;
1358
+ backdrop-filter: blur(16px);
1359
+ box-shadow: 0 8px 32px rgba(0,0,0,0.55);
1360
+ display: none;
1361
+ flex-direction: column;
1362
+ overflow: hidden;
1363
+ animation: fadeIn 0.12s ease;
1364
+ }
1365
+ .graph-physics-panel.open { display: flex; }
1366
+ .graph-physics-body {
1367
+ padding: 10px 14px 14px;
1368
+ display: flex;
1369
+ flex-direction: column;
1370
+ gap: 10px;
1371
+ }
1372
+ .graph-physics-row {
1373
+ display: grid;
1374
+ grid-template-columns: 90px 1fr 38px;
1375
+ align-items: center;
1376
+ gap: 8px;
1377
+ }
1378
+ .graph-physics-row label {
1379
+ font-size: 11px;
1380
+ color: var(--text-muted);
1381
+ white-space: nowrap;
1382
+ }
1383
+ .graph-physics-val {
1384
+ font-family: 'JetBrains Mono', monospace;
1385
+ font-size: 10px;
1386
+ color: var(--accent);
1387
+ text-align: right;
1388
+ }
1389
+ .graph-physics-slider {
1390
+ -webkit-appearance: none;
1391
+ appearance: none;
1392
+ width: 100%;
1393
+ height: 3px;
1394
+ border-radius: 2px;
1395
+ background: rgba(148,163,184,0.18);
1396
+ outline: none;
1397
+ cursor: pointer;
1398
+ }
1399
+ .graph-physics-slider::-webkit-slider-thumb {
1400
+ -webkit-appearance: none;
1401
+ appearance: none;
1402
+ width: 14px;
1403
+ height: 14px;
1404
+ border-radius: 50%;
1405
+ background: var(--accent);
1406
+ box-shadow: 0 0 6px rgba(45,212,191,0.5);
1407
+ cursor: pointer;
1408
+ transition: transform 0.1s;
1409
+ }
1410
+ .graph-physics-slider::-webkit-slider-thumb:hover {
1411
+ transform: scale(1.2);
1412
+ box-shadow: 0 0 10px rgba(45,212,191,0.7);
1413
+ }
1414
+ .graph-physics-slider::-moz-range-thumb {
1415
+ width: 14px;
1416
+ height: 14px;
1417
+ border-radius: 50%;
1418
+ background: var(--accent);
1419
+ border: none;
1420
+ cursor: pointer;
1421
+ }
1422
+
1423
+ /* ── Depth slider in filter panel ────────────────────────────── */
1424
+ .graph-filter-row-depth label {
1425
+ display: flex;
1426
+ align-items: center;
1427
+ gap: 6px;
1428
+ }
1429
+ .graph-depth-val {
1430
+ font-family: 'JetBrains Mono', monospace;
1431
+ font-size: 10px;
1432
+ color: var(--accent);
1433
+ min-width: 14px;
1434
+ text-align: center;
1435
+ }
1436
+ .graph-depth-slider {
1437
+ flex: 1;
1438
+ -webkit-appearance: none;
1439
+ appearance: none;
1440
+ height: 3px;
1441
+ border-radius: 2px;
1442
+ background: rgba(148,163,184,0.18);
1443
+ outline: none;
1444
+ cursor: pointer;
1445
+ }
1446
+ .graph-depth-slider:disabled {
1447
+ opacity: 0.35;
1448
+ cursor: not-allowed;
1449
+ }
1450
+ .graph-depth-slider::-webkit-slider-thumb {
1451
+ -webkit-appearance: none;
1452
+ width: 14px;
1453
+ height: 14px;
1454
+ border-radius: 50%;
1455
+ background: var(--accent);
1456
+ box-shadow: 0 0 5px rgba(45,212,191,0.4);
1457
+ cursor: pointer;
1458
+ }
1459
+ .graph-depth-slider::-moz-range-thumb {
1460
+ width: 14px;
1461
+ height: 14px;
1462
+ border-radius: 50%;
1463
+ background: var(--accent);
1464
+ border: none;
1465
+ }
1466
+
1467
+ /* Graph context menu */
1468
+ .graph-ctx-menu {
1469
+ position: fixed;
1470
+ z-index: 999;
1471
+ background: rgba(8,13,26,0.97);
1472
+ border: 1px solid rgba(148,163,184,0.22);
1473
+ border-radius: 8px;
1474
+ padding: 4px 0;
1475
+ min-width: 170px;
1476
+ backdrop-filter: blur(14px);
1477
+ box-shadow: 0 8px 32px rgba(0,0,0,0.6);
1478
+ animation: fadeIn 0.08s ease;
1479
+ }
1480
+ .graph-ctx-item {
1481
+ display: flex;
1482
+ align-items: center;
1483
+ gap: 8px;
1484
+ padding: 7px 14px;
1485
+ font-size: 12px;
1486
+ color: var(--text-secondary);
1487
+ cursor: pointer;
1488
+ transition: background 0.1s, color 0.1s;
1489
+ white-space: nowrap;
1490
+ background: none;
1491
+ border: none;
1492
+ width: 100%;
1493
+ text-align: left;
1494
+ font-family: 'Inter', sans-serif;
1495
+ }
1496
+ .graph-ctx-item:hover {
1497
+ background: rgba(148,163,184,0.08);
1498
+ color: var(--text-primary);
1499
+ }
1500
+ .graph-ctx-item.danger { color: #f87171; }
1501
+ .graph-ctx-item.danger:hover { background: rgba(248,113,113,0.1); }
1502
+ .graph-ctx-sep {
1503
+ height: 1px;
1504
+ background: rgba(148,163,184,0.1);
1505
+ margin: 3px 0;
1506
+ }
1507
+
1508
+ /* ── Admin ── */
1509
+ .admin-stats {
1510
+ display: grid;
1511
+ grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
1512
+ gap: 12px;
1513
+ margin-bottom: 16px;
1514
+ }
1515
+ .admin-panel {
1516
+ background: var(--bg-card2);
1517
+ border: 1px solid var(--border);
1518
+ border-radius: var(--radius-lg);
1519
+ padding: 16px;
1520
+ margin-bottom: 16px;
1521
+ }
1522
+ .admin-table-wrap { overflow-x: auto; }
1523
+ .admin-table {
1524
+ width: 100%;
1525
+ border-collapse: collapse;
1526
+ min-width: 720px;
1527
+ }
1528
+ .admin-table th,
1529
+ .admin-table td {
1530
+ border-bottom: 1px solid var(--border);
1531
+ padding: 10px 8px;
1532
+ text-align: left;
1533
+ vertical-align: middle;
1534
+ }
1535
+ .admin-table th {
1536
+ color: var(--text-muted);
1537
+ font-size: 11px;
1538
+ font-weight: 600;
1539
+ letter-spacing: 0.08em;
1540
+ text-transform: uppercase;
1541
+ }
1542
+ .admin-table td { color: var(--text-secondary); font-size: 13px; }
1543
+ .admin-table td strong {
1544
+ display: block;
1545
+ color: var(--text-primary);
1546
+ font-weight: 650;
1547
+ }
1548
+ .admin-table td span {
1549
+ display: block;
1550
+ margin-top: 2px;
1551
+ color: var(--text-muted);
1552
+ font-family: 'JetBrains Mono', monospace;
1553
+ font-size: 11px;
1554
+ }
1555
+ .admin-pill {
1556
+ display: inline-flex !important;
1557
+ width: max-content;
1558
+ margin-top: 0 !important;
1559
+ padding: 3px 8px;
1560
+ border: 1px solid var(--border-light);
1561
+ border-radius: 999px;
1562
+ color: var(--text-secondary) !important;
1563
+ font-family: inherit !important;
1564
+ font-size: 11px !important;
1565
+ }
1566
+ .admin-pill-strong {
1567
+ border-color: rgba(45,212,191,0.35);
1568
+ color: var(--accent) !important;
1569
+ }
1570
+ .admin-grid-list {
1571
+ display: grid;
1572
+ grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
1573
+ gap: 10px;
1574
+ }
1575
+ .admin-group-card {
1576
+ border: 1px solid var(--border);
1577
+ border-radius: var(--radius);
1578
+ background: var(--bg-input);
1579
+ padding: 12px;
1580
+ }
1581
+ .admin-group-card strong { display: block; margin-bottom: 4px; }
1582
+ .admin-group-card span {
1583
+ color: var(--text-muted);
1584
+ font-size: 12px;
1585
+ }
1586
+ .admin-group-card p {
1587
+ margin-top: 8px;
1588
+ color: var(--text-secondary);
1589
+ font-size: 13px;
1590
+ }
1591
+
1592
+ /* ── Search ── */
1593
+ .search-box-wrap { position: relative; margin-bottom: 16px; }
1594
+ .search-icon { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); color: var(--text-muted); font-size: 14px; pointer-events: none; }
1595
+ .search-input { width: 100%; background: var(--bg-input); border: 1px solid var(--border-light); color: var(--text-primary); border-radius: var(--radius); padding: 10px 12px 10px 36px; font-family: inherit; font-size: 14px; outline: none; transition: var(--transition); }
1596
+ .search-input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-glow); }
1597
+
1598
+ /* ── Notifications ── */
1599
+ #toast-container { position: fixed; bottom: 24px; right: 24px; display: flex; flex-direction: column; gap: 8px; z-index: 2000; }
1600
+ .toast {
1601
+ padding: 12px 16px; border-radius: var(--radius); font-size: 13px; font-weight: 500;
1602
+ min-width: 240px; max-width: 360px; box-shadow: var(--shadow);
1603
+ animation: toastIn 0.2s ease;
1604
+ }
1605
+ @keyframes toastIn { from { transform: translateX(20px); opacity: 0; } to { transform: translateX(0); opacity: 1; } }
1606
+ .toast-success { background: rgba(74,222,128,0.15); border: 1px solid rgba(74,222,128,0.3); color: #4ade80; }
1607
+ .toast-error { background: rgba(248,113,113,0.15); border: 1px solid rgba(248,113,113,0.3); color: #f87171; }
1608
+ .toast-info { background: rgba(45,212,191,0.15); border: 1px solid rgba(45,212,191,0.3); color: var(--accent); }
1609
+
1610
+ /* ── Health ── */
1611
+ .health-indicator { display: flex; align-items: center; gap: 8px; }
1612
+ .health-dot { width: 8px; height: 8px; border-radius: 50%; }
1613
+ .health-good { background: #4ade80; }
1614
+ .health-warn { background: #facc15; }
1615
+ .health-bad { background: #f87171; }
1616
+
1617
+ /* ── Tabs ── */
1618
+ .tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--border); margin-bottom: 20px; }
1619
+ .tab { padding: 8px 16px; cursor: pointer; font-size: 13px; color: var(--text-muted); border-bottom: 2px solid transparent; margin-bottom: -1px; transition: var(--transition); }
1620
+ .tab:hover { color: var(--text-primary); }
1621
+ .tab.active { color: var(--accent); border-bottom-color: var(--accent); }
1622
+
1623
+ /* ── Project cards (no project selected) ── */
1624
+ .projects-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 16px; }
1625
+ .project-card {
1626
+ background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius-lg);
1627
+ padding: 20px; cursor: pointer; transition: var(--transition); position: relative;
1628
+ }
1629
+ .project-card:hover { border-color: var(--accent); transform: translateY(-2px); box-shadow: 0 8px 24px rgba(0,0,0,0.3); }
1630
+ .project-card-name { font-size: 16px; font-weight: 600; margin-bottom: 4px; }
1631
+ .project-card-slug { font-family: 'JetBrains Mono', monospace; font-size: 11px; color: var(--text-muted); margin-bottom: 8px; }
1632
+ .project-card-desc { font-size: 13px; color: var(--text-secondary); line-height: 1.5; }
1633
+ .project-card-meta { display: flex; justify-content: space-between; align-items: center; margin-top: 16px; }
1634
+ .project-card-prefix { font-family: 'JetBrains Mono', monospace; font-size: 11px; background: var(--accent-glow); color: var(--accent); padding: 2px 8px; border-radius: 4px; }
1635
+ .project-card-date { font-size: 11px; color: var(--text-muted); }
1636
+ .project-card-del { position: absolute; top: 12px; right: 12px; opacity: 0; transition: var(--transition); }
1637
+ .project-card:hover .project-card-del { opacity: 1; }
1638
+
1639
+ /* ── Inline edit ── */
1640
+ .inline-edit-row { display: flex; gap: 8px; align-items: flex-end; }
1641
+ .inline-edit-row .form-input { flex: 1; }
1642
+
1643
+ /* ── Responsive ── */
1644
+ @media (max-width: 768px) {
1645
+ .auth-left { display: none; }
1646
+ .auth-right { width: 100%; padding: 40px 24px; }
1647
+ #sidebar { width: 180px; }
1648
+ .content-area { padding: 16px; }
1649
+ .stats-grid { grid-template-columns: repeat(2, 1fr); }
1650
+ .projects-grid { grid-template-columns: 1fr; }
1651
+ }
1652
+ @media (max-width: 540px) {
1653
+ #sidebar { display: none; }
1654
+ .modal { max-width: 100%; max-height: 100vh; border-radius: 0; }
1655
+ }
1656
+
1657
+ /* ── Divider ── */
1658
+ hr.section-divider { border: none; border-top: 1px solid var(--border); margin: 20px 0; }
1659
+
1660
+ /* ── Code/mono snippets ── */
1661
+ .mono { font-family: 'JetBrains Mono', monospace; }
1662
+
1663
+ /* ── Two-col layout ── */
1664
+ .two-col { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
1665
+ @media (max-width: 600px) { .two-col { grid-template-columns: 1fr; } }
1666
+
1667
+ /* ── GitHub sync two-panel layout ── */
1668
+ .github-sync-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
1669
+ @media (max-width: 900px) { .github-sync-grid { grid-template-columns: 1fr; } }
1670
+
1671
+ .row { display: flex; gap: 12px; align-items: center; }
1672
+ .flex-1 { flex: 1; }
1673
+
1674
+ /* ── Notes / Tests / Health ── */
1675
+ .notes-item { padding: 10px 0; border-bottom: 1px solid var(--border); }
1676
+ .notes-item:last-child { border-bottom: none; }
1677
+ .notes-item-text { font-size: 13px; color: var(--text-primary); line-height: 1.5; }
1678
+ .notes-item-meta { font-size: 11px; color: var(--text-muted); margin-bottom: 4px; }
1679
+ .test-item { padding: 10px 0; border-bottom: 1px solid var(--border); display: flex; align-items: flex-start; gap: 10px; }
1680
+ .test-item:last-child { border-bottom: none; }
1681
+ .test-item-cmd { font-family: 'JetBrains Mono', monospace; font-size: 12px; background: var(--bg-input); border-radius: 4px; padding: 2px 6px; }
1682
+ .health-score-display { text-align: center; padding: 32px; }
1683
+ .health-score-number { font-size: 72px; font-weight: 700; line-height: 1; }
1684
+ .health-score-label { font-size: 14px; color: var(--text-secondary); margin-top: 8px; }
1685
+ .health-issue-item { padding: 10px 12px; border-left: 3px solid var(--priority-2); background: var(--bg-card2); border-radius: 4px; margin-bottom: 8px; font-size: 13px; }
1686
+
1687
+ /* ── Deps / Learnings / Shares ── */
1688
+ .dep-row { display: flex; align-items: center; gap: 10px; padding: 7px 0; border-bottom: 1px solid var(--border); font-size: 13px; }
1689
+ .dep-row:last-child { border-bottom: none; }
1690
+ .dep-rel { font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; background: var(--bg-input); color: var(--text-muted); padding: 2px 7px; border-radius: 4px; flex-shrink: 0; }
1691
+ .dep-id { font-family: 'JetBrains Mono', monospace; font-size: 11px; color: var(--accent); cursor: pointer; text-decoration: underline; text-underline-offset: 2px; }
1692
+ .learning-row { padding: 8px 0; border-bottom: 1px solid var(--border); font-size: 13px; color: var(--text-secondary); line-height: 1.6; }
1693
+ .learning-row:last-child { border-bottom: none; }
1694
+ .share-row { display: flex; align-items: center; gap: 10px; padding: 8px 0; border-bottom: 1px solid var(--border); font-size: 13px; }
1695
+ .share-row:last-child { border-bottom: none; }
1696
+ .share-perm { font-size: 10px; font-weight: 600; text-transform: uppercase; background: var(--accent-glow); color: var(--accent); padding: 2px 8px; border-radius: 4px; flex-shrink: 0; }
1697
+ .group-row { display: flex; align-items: center; gap: 12px; padding: 10px 14px; background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius); cursor: pointer; transition: var(--transition); }
1698
+ .group-row:hover { border-color: var(--border-light); background: var(--bg-sidebar-hover); }
1699
+ .group-name { font-size: 13px; font-weight: 500; flex: 1; }
1700
+ .group-desc { font-size: 12px; color: var(--text-muted); }
1701
+ .member-row { display: flex; align-items: center; gap: 10px; padding: 7px 0; border-bottom: 1px solid var(--border); font-size: 13px; }
1702
+ .member-row:last-child { border-bottom: none; }
1703
+ .member-avatar { width: 26px; height: 26px; border-radius: 50%; background: var(--accent-dim); display: flex; align-items: center; justify-content: center; font-size: 10px; font-weight: 600; color: var(--accent); flex-shrink: 0; }
1704
+ .claim-btn-wrap { display: flex; gap: 8px; align-items: center; margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--border); }
1705
+
1706
+ /* ── PWA Install Banner ── */
1707
+ .offline-banner {
1708
+ display: none; position: fixed; bottom: 0; left: 0; right: 0; z-index: 950;
1709
+ background: #7c3aed; color: #fff; font-size: 13px; font-weight: 500;
1710
+ padding: 10px 20px; text-align: center;
1711
+ box-shadow: 0 -2px 12px rgba(0,0,0,0.4);
1712
+ }
1713
+ .offline-banner.visible { display: flex; align-items: center; justify-content: center; gap: 8px; }
1714
+
1715
+ .install-banner {
1716
+ display: none; position: fixed; bottom: 0; left: 0; right: 0; z-index: 900;
1717
+ background: var(--bg-sidebar); border-top: 1px solid var(--border-light);
1718
+ padding: 14px 20px; gap: 12px; align-items: center; justify-content: space-between;
1719
+ box-shadow: 0 -4px 20px rgba(0,0,0,0.5);
1720
+ }
1721
+ .install-banner.visible { display: flex; }
1722
+ .install-banner-text { font-size: 13px; color: var(--text-secondary); }
1723
+ .install-banner-text strong { color: var(--text-primary); }
1724
+
1725
+ /* ── Mobile Bottom Nav (PWA) ── */
1726
+ .mobile-bottom-nav {
1727
+ display: none; position: fixed; bottom: 0; left: 0; right: 0; z-index: 800;
1728
+ background: var(--bg-sidebar); border-top: 1px solid var(--border);
1729
+ height: 56px; padding-bottom: env(safe-area-inset-bottom, 0px);
1730
+ }
1731
+ .mobile-bottom-nav-inner {
1732
+ display: flex; align-items: center; justify-content: space-around; height: 56px;
1733
+ }
1734
+ .mobile-bottom-nav-item {
1735
+ display: flex; flex-direction: column; align-items: center; gap: 2px;
1736
+ color: var(--text-muted); font-size: 10px; text-decoration: none;
1737
+ padding: 6px 8px; cursor: pointer; transition: color 0.15s;
1738
+ -webkit-tap-highlight-color: transparent;
1739
+ }
1740
+ .mobile-bottom-nav-item:active, .mobile-bottom-nav-item.active { color: var(--accent); }
1741
+ .mobile-bottom-nav-item-icon { font-size: 18px; line-height: 1; }
1742
+ .mobile-bottom-nav-item-label { font-weight: 500; }
1743
+
1744
+ @media (max-width: 768px) {
1745
+ .mobile-bottom-nav.visible { display: block; }
1746
+ #main-content { padding-bottom: 72px; }
1747
+ #app-body { padding-bottom: 56px; }
1748
+ }
1749
+
1750
+ /* ── Safe area support for notched devices ── */
1751
+ @supports (padding: env(safe-area-inset-top)) {
1752
+ #top-nav { padding-top: env(safe-area-inset-top, 0px); }
1753
+ .mobile-bottom-nav { padding-bottom: env(safe-area-inset-bottom, 0px); }
1754
+ }
1755
+
1756
+ /* ── Skeleton Loading ── */
1757
+ .skeleton { background: var(--bg-card); border-radius: var(--radius); position: relative; overflow: hidden; }
1758
+ .skeleton::after { content: ''; position: absolute; inset: 0; background: linear-gradient(90deg, transparent 0%, rgba(255,255,255,0.04) 50%, transparent 100%); animation: shimmer 1.5s ease-in-out infinite; }
1759
+ @keyframes shimmer { 0% { transform: translateX(-100%); } 100% { transform: translateX(100%); } }
1760
+ .skeleton-row { height: 42px; margin-bottom: 4px; }
1761
+ .skeleton-card { height: 120px; margin-bottom: 12px; }
1762
+ .skeleton-text { height: 14px; margin-bottom: 8px; width: 80%; }
1763
+ .skeleton-text-sm { height: 10px; margin-bottom: 6px; width: 50%; }
1764
+
1765
+ /* ── Confirm Dialog ── */
1766
+ .confirm-dialog {
1767
+ text-align: center; padding: 8px 0;
1768
+ }
1769
+ .confirm-dialog-icon { font-size: 36px; margin-bottom: 12px; opacity: 0.7; }
1770
+ .confirm-dialog-title { font-size: 16px; font-weight: 600; margin-bottom: 8px; }
1771
+ .confirm-dialog-desc { font-size: 13px; color: var(--text-secondary); margin-bottom: 20px; line-height: 1.6; }
1772
+ .confirm-dialog-actions { display: flex; gap: 8px; justify-content: center; }
1773
+
1774
+ /* ── Pull to Refresh ── */
1775
+ .pull-indicator {
1776
+ position: absolute; top: -40px; left: 50%; transform: translateX(-50%);
1777
+ height: 36px; display: flex; align-items: center; justify-content: center;
1778
+ font-size: 18px; color: var(--accent); transition: top 0.2s ease;
1779
+ }
1780
+ .pull-indicator.pulling { top: 8px; }
1781
+ .pull-indicator.refreshing { animation: spin 0.7s linear infinite; }
1782
+
1783
+ /* ── Calendar Grid ── */
1784
+ .cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; margin-bottom: 16px; }
1785
+ .cal-header { font-size: 10px; font-weight: 600; color: var(--text-muted); text-align: center; padding: 8px 2px; text-transform: uppercase; }
1786
+ .cal-day {
1787
+ min-height: 64px; background: var(--bg-card2); border: 1px solid var(--border); border-radius: 4px;
1788
+ padding: 3px; font-size: 11px; position: relative; cursor: pointer; transition: var(--transition);
1789
+ }
1790
+ .cal-day:hover { border-color: var(--border-light); }
1791
+ .cal-day.other-month { opacity: 0.35; }
1792
+ .cal-day.today { border-color: var(--accent); background: var(--accent-glow); }
1793
+ .cal-day-num { font-size: 10px; color: var(--text-muted); font-weight: 600; margin-bottom: 2px; }
1794
+ .cal-day.today .cal-day-num { color: var(--accent); }
1795
+ .cal-event-dot {
1796
+ display: block; font-size: 9px; padding: 1px 3px; border-radius: 2px;
1797
+ white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
1798
+ margin-bottom: 1px; cursor: pointer;
1799
+ }
1800
+ .cal-event-dot.status-open { background: rgba(96,165,250,0.2); color: var(--status-open); }
1801
+ .cal-event-dot.status-in_progress { background: rgba(45,212,191,0.2); color: var(--status-in_progress); }
1802
+ .cal-event-dot.status-blocked { background: rgba(248,113,113,0.2); color: var(--status-blocked); }
1803
+ .cal-event-dot.status-closed { background: rgba(74,222,128,0.2); color: var(--status-closed); }
1804
+ .cal-event-dot.more { background: var(--bg-input); color: var(--text-muted); text-align: center; }
1805
+
1806
+ /* ── Export / Import ── */
1807
+ .export-card { display: flex; align-items: center; gap: 16px; padding: 16px; background: var(--bg-card2); border: 1px solid var(--border); border-radius: var(--radius-lg); }
1808
+ .export-card-icon { font-size: 24px; flex-shrink: 0; }
1809
+ .export-card-info { flex: 1; }
1810
+ .export-card-title { font-size: 14px; font-weight: 600; }
1811
+ .export-card-desc { font-size: 12px; color: var(--text-muted); margin-top: 2px; }
1812
+
1813
+ /* ── Files ── */
1814
+ .file-row { display: flex; align-items: center; gap: 10px; padding: 7px 0; border-bottom: 1px solid var(--border); font-size: 13px; }
1815
+ .file-row:last-child { border-bottom: none; }
1816
+ .file-path { font-family: 'JetBrains Mono', monospace; font-size: 12px; color: var(--accent); flex: 1; }
1817
+
1818
+ /* ── SSE Real-time Indicator ── */
1819
+ .sse-indicator {
1820
+ display: flex; align-items: center; justify-content: center;
1821
+ width: 24px; height: 24px; cursor: default; flex-shrink: 0;
1822
+ }
1823
+ .sse-dot {
1824
+ width: 8px; height: 8px; border-radius: 50%;
1825
+ background: var(--text-muted); transition: background 0.4s ease;
1826
+ }
1827
+ .sse-indicator.connected .sse-dot {
1828
+ background: #4ade80;
1829
+ box-shadow: 0 0 6px rgba(74,222,128,0.6);
1830
+ animation: ssePulse 2s ease-in-out infinite;
1831
+ }
1832
+ .sse-indicator.reconnecting .sse-dot {
1833
+ background: #facc15;
1834
+ animation: sseBlink 1s ease-in-out infinite;
1835
+ }
1836
+ @keyframes ssePulse {
1837
+ 0%, 100% { box-shadow: 0 0 4px rgba(74,222,128,0.4); }
1838
+ 50% { box-shadow: 0 0 10px rgba(74,222,128,0.8); }
1839
+ }
1840
+ @keyframes sseBlink {
1841
+ 0%, 100% { opacity: 1; } 50% { opacity: 0.3; }
1842
+ }
1843
+
1844
+ /* ── Presence bar ── */
1845
+ .presence-bar {
1846
+ display: flex; align-items: center; gap: 4px; flex-shrink: 0;
1847
+ }
1848
+ .presence-label {
1849
+ font-size: 10px; color: var(--text-muted); margin-right: 2px; white-space: nowrap;
1850
+ }
1851
+ .presence-chip {
1852
+ display: inline-flex; align-items: center; justify-content: center;
1853
+ width: 26px; height: 26px; border-radius: 50%;
1854
+ font-size: 10px; font-weight: 700; letter-spacing: 0.02em;
1855
+ border: 1px solid transparent;
1856
+ cursor: default; flex-shrink: 0; transition: transform 0.15s ease;
1857
+ }
1858
+ .presence-chip:hover { transform: scale(1.15); }
1859
+ .presence-chip-extra {
1860
+ background: rgba(148,163,184,0.12);
1861
+ border-color: rgba(148,163,184,0.3);
1862
+ color: var(--text-secondary);
1863
+ font-size: 9px;
1864
+ }
1865
+
1866
+ /* ── Drag Handle ── */
1867
+ .drag-hint { font-size: 11px; color: var(--text-muted); padding: 8px 0; display: flex; align-items: center; gap: 6px; }
1868
+
1869
+ /* ── Optimistic overlay ── */
1870
+ .optimistic-overlay {
1871
+ position: absolute; inset: 0; background: rgba(10,15,30,0.6); display: flex;
1872
+ align-items: center; justify-content: center; border-radius: var(--radius); z-index: 5;
1873
+ }
1874
+
1875
+ /* ── Guide View ── */
1876
+ .guide-topic-grid {
1877
+ display: grid;
1878
+ grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
1879
+ gap: 12px;
1880
+ }
1881
+ .guide-topic-card {
1882
+ display: flex; align-items: flex-start; gap: 12px; padding: 16px;
1883
+ transition: border-color 0.15s, transform 0.1s;
1884
+ }
1885
+ .guide-topic-card:hover { border-color: var(--accent); transform: translateY(-1px); }
1886
+ .guide-topic-icon { font-size: 24px; flex-shrink: 0; line-height: 1; margin-top: 2px; }
1887
+ .guide-topic-body { flex: 1; min-width: 0; }
1888
+ .guide-topic-title { font-weight: 600; font-size: 15px; margin-bottom: 4px; }
1889
+ .guide-topic-summary { font-size: 13px; color: var(--text-muted); line-height: 1.5; }
1890
+ .guide-cmd-row {
1891
+ display: flex; align-items: center; gap: 8px; padding: 6px 0;
1892
+ border-bottom: 1px solid var(--border);
1893
+ }
1894
+ .guide-cmd-row:last-child { border-bottom: none; }
1895
+ .guide-cmd-code {
1896
+ flex: 1; font-family: var(--font-mono); font-size: 13px;
1897
+ color: var(--accent); background: var(--bg-input); padding: 4px 8px;
1898
+ border-radius: 4px; word-break: break-all;
1899
+ }
1900
+ .guide-copy-btn { flex-shrink: 0; opacity: 0.6; }
1901
+ .guide-copy-btn:hover { opacity: 1; }
1902
+
1903
+ /* ── Mobile command sheet ── */
1904
+ .mobile-command-intro {
1905
+ display: flex;
1906
+ align-items: center;
1907
+ justify-content: space-between;
1908
+ gap: 12px;
1909
+ padding: 12px 14px;
1910
+ margin-bottom: 14px;
1911
+ background: var(--bg-input);
1912
+ border: 1px solid var(--border);
1913
+ border-radius: var(--radius-lg);
1914
+ }
1915
+ .mobile-command-project {
1916
+ min-width: 0;
1917
+ }
1918
+ .mobile-command-project-label {
1919
+ font-size: 10px;
1920
+ font-weight: 700;
1921
+ letter-spacing: 0.08em;
1922
+ text-transform: uppercase;
1923
+ color: var(--text-muted);
1924
+ }
1925
+ .mobile-command-project-name {
1926
+ font-size: 14px;
1927
+ font-weight: 600;
1928
+ overflow: hidden;
1929
+ text-overflow: ellipsis;
1930
+ white-space: nowrap;
1931
+ }
1932
+ .mobile-command-sync {
1933
+ display: inline-flex;
1934
+ align-items: center;
1935
+ gap: 6px;
1936
+ color: var(--text-secondary);
1937
+ font-size: 12px;
1938
+ flex-shrink: 0;
1939
+ }
1940
+ .mobile-command-grid {
1941
+ display: grid;
1942
+ grid-template-columns: repeat(2, minmax(0, 1fr));
1943
+ gap: 10px;
1944
+ }
1945
+ .mobile-command-group {
1946
+ margin-bottom: 18px;
1947
+ }
1948
+ .mobile-command-group-title {
1949
+ margin-bottom: 8px;
1950
+ color: var(--text-muted);
1951
+ font-size: 10px;
1952
+ font-weight: 700;
1953
+ letter-spacing: 0.1em;
1954
+ text-transform: uppercase;
1955
+ }
1956
+ .mobile-command {
1957
+ width: 100%;
1958
+ min-height: 74px;
1959
+ padding: 12px;
1960
+ border: 1px solid var(--border);
1961
+ border-radius: var(--radius-lg);
1962
+ background: var(--bg-card2);
1963
+ color: var(--text-primary);
1964
+ text-align: left;
1965
+ font: inherit;
1966
+ cursor: pointer;
1967
+ transition: var(--transition);
1968
+ -webkit-tap-highlight-color: transparent;
1969
+ }
1970
+ .mobile-command:active,
1971
+ .mobile-command:hover {
1972
+ border-color: var(--accent);
1973
+ background: var(--bg-sidebar-hover);
1974
+ }
1975
+ .mobile-command[disabled] {
1976
+ cursor: not-allowed;
1977
+ opacity: 0.5;
1978
+ }
1979
+ .mobile-command-top {
1980
+ display: flex;
1981
+ align-items: center;
1982
+ gap: 8px;
1983
+ margin-bottom: 5px;
1984
+ }
1985
+ .mobile-command-icon {
1986
+ display: inline-flex;
1987
+ align-items: center;
1988
+ justify-content: center;
1989
+ width: 24px;
1990
+ height: 24px;
1991
+ border-radius: 7px;
1992
+ background: var(--accent-glow);
1993
+ color: var(--accent);
1994
+ font-size: 14px;
1995
+ flex-shrink: 0;
1996
+ }
1997
+ .mobile-command-title {
1998
+ font-size: 13px;
1999
+ font-weight: 650;
2000
+ overflow-wrap: anywhere;
2001
+ }
2002
+ .mobile-command-desc {
2003
+ color: var(--text-muted);
2004
+ font-size: 11px;
2005
+ line-height: 1.35;
2006
+ }
2007
+
2008
+ @media (max-width: 768px) {
2009
+ html, body {
2010
+ overscroll-behavior-y: contain;
2011
+ }
2012
+ #top-nav {
2013
+ height: auto;
2014
+ min-height: 56px;
2015
+ padding: 8px 10px;
2016
+ gap: 8px;
2017
+ }
2018
+ .nav-logo {
2019
+ font-size: 16px;
2020
+ }
2021
+ .nav-divider,
2022
+ .nav-search-hint,
2023
+ .user-name,
2024
+ .user-menu .btn {
2025
+ display: none;
2026
+ }
2027
+ .project-selector-wrap {
2028
+ max-width: none;
2029
+ min-width: 0;
2030
+ }
2031
+ .project-selector {
2032
+ min-height: 38px;
2033
+ font-size: 14px;
2034
+ }
2035
+ .user-menu {
2036
+ gap: 4px;
2037
+ }
2038
+ .user-avatar {
2039
+ width: 34px;
2040
+ height: 34px;
2041
+ }
2042
+ .sse-indicator {
2043
+ width: 18px;
2044
+ }
2045
+ .page-header {
2046
+ flex-direction: column;
2047
+ align-items: stretch;
2048
+ gap: 12px;
2049
+ margin-bottom: 16px;
2050
+ }
2051
+ .page-title {
2052
+ font-size: 18px;
2053
+ }
2054
+ .page-actions {
2055
+ width: 100%;
2056
+ flex-wrap: wrap;
2057
+ }
2058
+ .page-actions .btn,
2059
+ .filter-bar .btn,
2060
+ .filter-select {
2061
+ min-height: 38px;
2062
+ }
2063
+ .page-actions .btn {
2064
+ flex: 1 1 auto;
2065
+ justify-content: center;
2066
+ }
2067
+ .item-row {
2068
+ align-items: flex-start;
2069
+ gap: 8px;
2070
+ padding: 12px;
2071
+ }
2072
+ .item-id {
2073
+ min-width: 58px;
2074
+ }
2075
+ .item-title {
2076
+ white-space: normal;
2077
+ line-height: 1.35;
2078
+ }
2079
+ .item-meta {
2080
+ flex-direction: column;
2081
+ align-items: flex-end;
2082
+ gap: 5px;
2083
+ }
2084
+ .tabs {
2085
+ overflow-x: auto;
2086
+ -webkit-overflow-scrolling: touch;
2087
+ }
2088
+ .graph-hud-top { flex-wrap: wrap; gap: 8px; padding: 8px 10px; }
2089
+ .graph-hud-left { width: 100%; }
2090
+ .graph-hud-left > div:first-child {
2091
+ display: grid !important;
2092
+ grid-template-columns: auto minmax(0, 1fr);
2093
+ width: 100%;
2094
+ }
2095
+ .graph-hud-left .graph-back-btn { width: auto; }
2096
+ .graph-hud-title {
2097
+ min-width: 0;
2098
+ overflow: hidden;
2099
+ text-overflow: ellipsis;
2100
+ }
2101
+ .graph-hud-center { order: 3; max-width: 100%; width: 100%; }
2102
+ .graph-hud-right {
2103
+ display: grid;
2104
+ grid-template-columns: repeat(4, minmax(0, 1fr));
2105
+ width: 100%;
2106
+ flex-shrink: 1;
2107
+ justify-content: stretch;
2108
+ }
2109
+ .graph-hud-btn,
2110
+ .graph-hud-select {
2111
+ width: 100%;
2112
+ height: 32px;
2113
+ justify-content: center;
2114
+ overflow: hidden;
2115
+ text-overflow: ellipsis;
2116
+ }
2117
+ .graph-preset-rail { grid-template-columns: repeat(3, minmax(0, 1fr)); }
2118
+ .graph-preset-btn { height: 30px; padding-inline: 6px; font-size: 11px; }
2119
+ .graph-info-drawer { width: 100%; top: auto; height: 60vh; transform: translateY(100%); }
2120
+ .graph-info-drawer.open { transform: translateY(0); }
2121
+ .graph-rel-row { grid-template-columns: 1fr; gap: 6px; }
2122
+ .graph-rel-type { width: max-content; }
2123
+ .graph-coverage-grid { grid-template-columns: 1fr 1fr; }
2124
+ .tab {
2125
+ flex: 0 0 auto;
2126
+ }
2127
+ #toast-container {
2128
+ left: 12px;
2129
+ right: 12px;
2130
+ bottom: calc(72px + env(safe-area-inset-bottom, 0px));
2131
+ }
2132
+ .toast {
2133
+ min-width: 0;
2134
+ max-width: none;
2135
+ width: 100%;
2136
+ }
2137
+ }
2138
+
2139
+ @media (max-width: 540px) {
2140
+ .graph-preset-rail { grid-template-columns: repeat(3, minmax(0, 1fr)); }
2141
+ .content-area {
2142
+ padding: 14px 12px;
2143
+ }
2144
+ .modal-backdrop {
2145
+ align-items: flex-end;
2146
+ padding: 0;
2147
+ }
2148
+ .modal {
2149
+ max-height: 92vh;
2150
+ border-right: none;
2151
+ border-left: none;
2152
+ border-bottom: none;
2153
+ border-radius: 18px 18px 0 0;
2154
+ }
2155
+ .modal-header {
2156
+ padding: 16px 18px 12px;
2157
+ }
2158
+ .modal-body {
2159
+ padding: 18px;
2160
+ }
2161
+ .modal-footer {
2162
+ padding: 12px 18px calc(12px + env(safe-area-inset-bottom, 0px));
2163
+ flex-wrap: wrap;
2164
+ }
2165
+ .modal-footer .btn {
2166
+ flex: 1 1 auto;
2167
+ justify-content: center;
2168
+ }
2169
+ .mobile-command-grid {
2170
+ grid-template-columns: 1fr;
2171
+ }
2172
+ .install-banner.visible {
2173
+ bottom: calc(56px + env(safe-area-inset-bottom, 0px));
2174
+ align-items: stretch;
2175
+ flex-direction: column;
2176
+ }
2177
+ }
2178
+
2179
+ /* ═══════════════════════════════════════════════════════════════
2180
+ PLAN VIEW
2181
+ ═══════════════════════════════════════════════════════════════ */
2182
+
2183
+ .plan-layout {
2184
+ display: flex;
2185
+ gap: 16px;
2186
+ align-items: flex-start;
2187
+ }
2188
+
2189
+ .plan-list-panel {
2190
+ min-width: 260px;
2191
+ max-width: 300px;
2192
+ flex-shrink: 0;
2193
+ }
2194
+
2195
+ .plan-detail-panel {
2196
+ flex: 1;
2197
+ min-width: 0;
2198
+ }
2199
+
2200
+ .plan-step-row {
2201
+ display: flex;
2202
+ align-items: flex-start;
2203
+ gap: 10px;
2204
+ padding: 10px 0;
2205
+ border-bottom: 1px solid var(--border);
2206
+ transition: background 0.1s;
2207
+ }
2208
+
2209
+ .plan-step-row:last-child {
2210
+ border-bottom: none;
2211
+ }
2212
+
2213
+ .plan-step-row:hover {
2214
+ background: var(--bg-elevated);
2215
+ border-radius: var(--radius-sm, 4px);
2216
+ }
2217
+
2218
+ .plan-steps-list {
2219
+ padding: 4px 0;
2220
+ }
2221
+
2222
+ @media (max-width: 700px) {
2223
+ .plan-layout {
2224
+ flex-direction: column;
2225
+ }
2226
+ .plan-list-panel {
2227
+ min-width: 0;
2228
+ max-width: none;
2229
+ width: 100%;
2230
+ }
2231
+ }