dx-devkit 0.0.0-stage → 1.1.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 (172) hide show
  1. package/CHANGELOG.md +81 -0
  2. package/LICENSE +21 -0
  3. package/README.md +475 -2
  4. package/bin/dx-mcp.js +2 -0
  5. package/dist/command.d.ts +9 -0
  6. package/dist/command.d.ts.map +1 -0
  7. package/dist/command.js +2 -0
  8. package/dist/command.js.map +1 -0
  9. package/dist/commands/ai.d.ts +7 -0
  10. package/dist/commands/ai.d.ts.map +1 -0
  11. package/dist/commands/ai.js +148 -0
  12. package/dist/commands/ai.js.map +1 -0
  13. package/dist/commands/clean.d.ts +3 -0
  14. package/dist/commands/clean.d.ts.map +1 -0
  15. package/dist/commands/clean.js +72 -0
  16. package/dist/commands/clean.js.map +1 -0
  17. package/dist/commands/deps.d.ts +3 -0
  18. package/dist/commands/deps.d.ts.map +1 -0
  19. package/dist/commands/deps.js +98 -0
  20. package/dist/commands/deps.js.map +1 -0
  21. package/dist/commands/go.d.ts +3 -0
  22. package/dist/commands/go.d.ts.map +1 -0
  23. package/dist/commands/go.js +202 -0
  24. package/dist/commands/go.js.map +1 -0
  25. package/dist/commands/log.d.ts +3 -0
  26. package/dist/commands/log.d.ts.map +1 -0
  27. package/dist/commands/log.js +51 -0
  28. package/dist/commands/log.js.map +1 -0
  29. package/dist/commands/new.d.ts +3 -0
  30. package/dist/commands/new.d.ts.map +1 -0
  31. package/dist/commands/new.js +117 -0
  32. package/dist/commands/new.js.map +1 -0
  33. package/dist/commands/port.d.ts +4 -0
  34. package/dist/commands/port.d.ts.map +1 -0
  35. package/dist/commands/port.js +106 -0
  36. package/dist/commands/port.js.map +1 -0
  37. package/dist/commands/projects.d.ts +5 -0
  38. package/dist/commands/projects.d.ts.map +1 -0
  39. package/dist/commands/projects.js +46 -0
  40. package/dist/commands/projects.js.map +1 -0
  41. package/dist/commands/stack.d.ts +34 -0
  42. package/dist/commands/stack.d.ts.map +1 -0
  43. package/dist/commands/stack.js +140 -0
  44. package/dist/commands/stack.js.map +1 -0
  45. package/dist/commands/summary.d.ts +3 -0
  46. package/dist/commands/summary.d.ts.map +1 -0
  47. package/dist/commands/summary.js +88 -0
  48. package/dist/commands/summary.js.map +1 -0
  49. package/dist/commands/system.d.ts +5 -0
  50. package/dist/commands/system.d.ts.map +1 -0
  51. package/dist/commands/system.js +104 -0
  52. package/dist/commands/system.js.map +1 -0
  53. package/dist/commands/ui.d.ts +3 -0
  54. package/dist/commands/ui.d.ts.map +1 -0
  55. package/dist/commands/ui.js +96 -0
  56. package/dist/commands/ui.js.map +1 -0
  57. package/dist/index.d.ts +3 -0
  58. package/dist/index.d.ts.map +1 -0
  59. package/dist/index.js +103 -0
  60. package/dist/index.js.map +1 -0
  61. package/dist/ui.d.ts +27 -0
  62. package/dist/ui.d.ts.map +1 -0
  63. package/dist/ui.js +104 -0
  64. package/dist/ui.js.map +1 -0
  65. package/node_modules/@dx/core/dist/config.d.ts +46 -0
  66. package/node_modules/@dx/core/dist/config.d.ts.map +1 -0
  67. package/node_modules/@dx/core/dist/config.js +131 -0
  68. package/node_modules/@dx/core/dist/config.js.map +1 -0
  69. package/node_modules/@dx/core/dist/fuzzy.d.ts +15 -0
  70. package/node_modules/@dx/core/dist/fuzzy.d.ts.map +1 -0
  71. package/node_modules/@dx/core/dist/fuzzy.js +63 -0
  72. package/node_modules/@dx/core/dist/fuzzy.js.map +1 -0
  73. package/node_modules/@dx/core/dist/index.d.ts +17 -0
  74. package/node_modules/@dx/core/dist/index.d.ts.map +1 -0
  75. package/node_modules/@dx/core/dist/index.js +19 -0
  76. package/node_modules/@dx/core/dist/index.js.map +1 -0
  77. package/node_modules/@dx/core/dist/runs.d.ts +19 -0
  78. package/node_modules/@dx/core/dist/runs.d.ts.map +1 -0
  79. package/node_modules/@dx/core/dist/runs.js +41 -0
  80. package/node_modules/@dx/core/dist/runs.js.map +1 -0
  81. package/node_modules/@dx/core/dist/tools/aiSetup.d.ts +58 -0
  82. package/node_modules/@dx/core/dist/tools/aiSetup.d.ts.map +1 -0
  83. package/node_modules/@dx/core/dist/tools/aiSetup.js +243 -0
  84. package/node_modules/@dx/core/dist/tools/aiSetup.js.map +1 -0
  85. package/node_modules/@dx/core/dist/tools/cleanup.d.ts +61 -0
  86. package/node_modules/@dx/core/dist/tools/cleanup.d.ts.map +1 -0
  87. package/node_modules/@dx/core/dist/tools/cleanup.js +171 -0
  88. package/node_modules/@dx/core/dist/tools/cleanup.js.map +1 -0
  89. package/node_modules/@dx/core/dist/tools/deps.d.ts +57 -0
  90. package/node_modules/@dx/core/dist/tools/deps.d.ts.map +1 -0
  91. package/node_modules/@dx/core/dist/tools/deps.js +151 -0
  92. package/node_modules/@dx/core/dist/tools/deps.js.map +1 -0
  93. package/node_modules/@dx/core/dist/tools/devErrors.d.ts +74 -0
  94. package/node_modules/@dx/core/dist/tools/devErrors.d.ts.map +1 -0
  95. package/node_modules/@dx/core/dist/tools/devErrors.js +261 -0
  96. package/node_modules/@dx/core/dist/tools/devErrors.js.map +1 -0
  97. package/node_modules/@dx/core/dist/tools/doctor.d.ts +12 -0
  98. package/node_modules/@dx/core/dist/tools/doctor.d.ts.map +1 -0
  99. package/node_modules/@dx/core/dist/tools/doctor.js +176 -0
  100. package/node_modules/@dx/core/dist/tools/doctor.js.map +1 -0
  101. package/node_modules/@dx/core/dist/tools/github.d.ts +31 -0
  102. package/node_modules/@dx/core/dist/tools/github.d.ts.map +1 -0
  103. package/node_modules/@dx/core/dist/tools/github.js +80 -0
  104. package/node_modules/@dx/core/dist/tools/github.js.map +1 -0
  105. package/node_modules/@dx/core/dist/tools/journal.d.ts +23 -0
  106. package/node_modules/@dx/core/dist/tools/journal.d.ts.map +1 -0
  107. package/node_modules/@dx/core/dist/tools/journal.js +80 -0
  108. package/node_modules/@dx/core/dist/tools/journal.js.map +1 -0
  109. package/node_modules/@dx/core/dist/tools/launch.d.ts +24 -0
  110. package/node_modules/@dx/core/dist/tools/launch.d.ts.map +1 -0
  111. package/node_modules/@dx/core/dist/tools/launch.js +137 -0
  112. package/node_modules/@dx/core/dist/tools/launch.js.map +1 -0
  113. package/node_modules/@dx/core/dist/tools/ports.d.ts +42 -0
  114. package/node_modules/@dx/core/dist/tools/ports.d.ts.map +1 -0
  115. package/node_modules/@dx/core/dist/tools/ports.js +220 -0
  116. package/node_modules/@dx/core/dist/tools/ports.js.map +1 -0
  117. package/node_modules/@dx/core/dist/tools/projects.d.ts +58 -0
  118. package/node_modules/@dx/core/dist/tools/projects.d.ts.map +1 -0
  119. package/node_modules/@dx/core/dist/tools/projects.js +208 -0
  120. package/node_modules/@dx/core/dist/tools/projects.js.map +1 -0
  121. package/node_modules/@dx/core/dist/tools/scaffold.d.ts +40 -0
  122. package/node_modules/@dx/core/dist/tools/scaffold.d.ts.map +1 -0
  123. package/node_modules/@dx/core/dist/tools/scaffold.js +188 -0
  124. package/node_modules/@dx/core/dist/tools/scaffold.js.map +1 -0
  125. package/node_modules/@dx/core/dist/tools/stacks.d.ts +119 -0
  126. package/node_modules/@dx/core/dist/tools/stacks.d.ts.map +1 -0
  127. package/node_modules/@dx/core/dist/tools/stacks.js +386 -0
  128. package/node_modules/@dx/core/dist/tools/stacks.js.map +1 -0
  129. package/node_modules/@dx/core/dist/tools/summary.d.ts +87 -0
  130. package/node_modules/@dx/core/dist/tools/summary.d.ts.map +1 -0
  131. package/node_modules/@dx/core/dist/tools/summary.js +331 -0
  132. package/node_modules/@dx/core/dist/tools/summary.js.map +1 -0
  133. package/node_modules/@dx/core/package.json +20 -0
  134. package/node_modules/@dx/mcp/dist/index.d.ts +3 -0
  135. package/node_modules/@dx/mcp/dist/index.d.ts.map +1 -0
  136. package/node_modules/@dx/mcp/dist/index.js +540 -0
  137. package/node_modules/@dx/mcp/dist/index.js.map +1 -0
  138. package/node_modules/@dx/mcp/package.json +8 -0
  139. package/node_modules/@dx/web/dist/api.d.ts +13 -0
  140. package/node_modules/@dx/web/dist/api.d.ts.map +1 -0
  141. package/node_modules/@dx/web/dist/api.js +351 -0
  142. package/node_modules/@dx/web/dist/api.js.map +1 -0
  143. package/node_modules/@dx/web/dist/background.d.ts +2 -0
  144. package/node_modules/@dx/web/dist/background.d.ts.map +1 -0
  145. package/node_modules/@dx/web/dist/background.js +24 -0
  146. package/node_modules/@dx/web/dist/background.js.map +1 -0
  147. package/node_modules/@dx/web/dist/check.d.ts +39 -0
  148. package/node_modules/@dx/web/dist/check.d.ts.map +1 -0
  149. package/node_modules/@dx/web/dist/check.js +97 -0
  150. package/node_modules/@dx/web/dist/check.js.map +1 -0
  151. package/node_modules/@dx/web/dist/dev.d.ts +109 -0
  152. package/node_modules/@dx/web/dist/dev.d.ts.map +1 -0
  153. package/node_modules/@dx/web/dist/dev.js +645 -0
  154. package/node_modules/@dx/web/dist/dev.js.map +1 -0
  155. package/node_modules/@dx/web/dist/link.d.ts +45 -0
  156. package/node_modules/@dx/web/dist/link.d.ts.map +1 -0
  157. package/node_modules/@dx/web/dist/link.js +150 -0
  158. package/node_modules/@dx/web/dist/link.js.map +1 -0
  159. package/node_modules/@dx/web/dist/proxy.d.ts +21 -0
  160. package/node_modules/@dx/web/dist/proxy.d.ts.map +1 -0
  161. package/node_modules/@dx/web/dist/proxy.js +140 -0
  162. package/node_modules/@dx/web/dist/proxy.js.map +1 -0
  163. package/node_modules/@dx/web/dist/server.d.ts +33 -0
  164. package/node_modules/@dx/web/dist/server.d.ts.map +1 -0
  165. package/node_modules/@dx/web/dist/server.js +184 -0
  166. package/node_modules/@dx/web/dist/server.js.map +1 -0
  167. package/node_modules/@dx/web/package.json +26 -0
  168. package/node_modules/@dx/web/public/app.js +1553 -0
  169. package/node_modules/@dx/web/public/icon.svg +1 -0
  170. package/node_modules/@dx/web/public/index.html +47 -0
  171. package/node_modules/@dx/web/public/styles.css +1124 -0
  172. package/package.json +52 -4
@@ -0,0 +1,1124 @@
1
+ /*
2
+ * dx dashboard. Every shared value lives in these tokens; the rest of the file only uses them.
3
+ * Status colours keep the meaning they have in the dx terminal output:
4
+ * ok = green ✓, warn = yellow !, danger = red ✗, accent = cyan (commands, links).
5
+ */
6
+ :root {
7
+ --bg: #f5f6f8;
8
+ --surface: #ffffff;
9
+ --surface-2: #eef0f3;
10
+ --surface-hover: #e6e9ee;
11
+ --border: #dde1e7;
12
+ --border-strong: #c6ccd5;
13
+ --text: #171b21;
14
+ --text-dim: #5a6370;
15
+ --accent: #0e7490;
16
+ --accent-hover: #0b5f76;
17
+ --accent-text: #ffffff;
18
+ --accent-soft: #e0f4f8;
19
+ --ok: #15803d;
20
+ --ok-soft: #e3f5e8;
21
+ --warn: #a15c07;
22
+ --warn-soft: #fdf1dc;
23
+ --danger: #b42318;
24
+ --danger-hover: #93190f;
25
+ --danger-soft: #fde7e5;
26
+ --focus: #0e7490;
27
+ --log-bg: #11151a;
28
+ --log-text: #d5dbe3;
29
+ --log-dim: #8a94a2;
30
+ --log-err: #ff9b8f;
31
+ --log-dx: #67d8ee;
32
+ --shadow: 0 1px 2px rgb(16 24 40 / 0.06), 0 1px 3px rgb(16 24 40 / 0.08);
33
+ --shadow-lg: 0 12px 32px rgb(16 24 40 / 0.18);
34
+
35
+ --s1: 4px;
36
+ --s2: 8px;
37
+ --s3: 12px;
38
+ --s4: 16px;
39
+ --s5: 24px;
40
+ --s6: 32px;
41
+ --s8: 48px;
42
+ --r1: 6px;
43
+ --r2: 10px;
44
+ --r3: 14px;
45
+
46
+ --font: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
47
+ --mono: ui-monospace, "Cascadia Code", "SF Mono", Consolas, "Liberation Mono", monospace;
48
+ --t-xs: 0.75rem;
49
+ --t-sm: 0.8125rem;
50
+ --t-base: 0.875rem;
51
+ --t-md: 1rem;
52
+ --t-lg: 1.125rem;
53
+ --t-xl: 1.5rem;
54
+ --t-2xl: 1.875rem;
55
+
56
+ --sidebar: 232px;
57
+ --control: 34px;
58
+ color-scheme: light;
59
+ }
60
+
61
+ @media (prefers-color-scheme: dark) {
62
+ :root:not([data-theme="light"]) {
63
+ --bg: #0e1115;
64
+ --surface: #161a20;
65
+ --surface-2: #1c2128;
66
+ --surface-hover: #232a33;
67
+ --border: #2a313b;
68
+ --border-strong: #3a4350;
69
+ --text: #e7eaef;
70
+ --text-dim: #9aa4b2;
71
+ --accent: #2cc4e0;
72
+ --accent-hover: #5fd6ec;
73
+ --accent-text: #052a33;
74
+ --accent-soft: #0f2f37;
75
+ --ok: #4ade80;
76
+ --ok-soft: #12301f;
77
+ --warn: #fbbf24;
78
+ --warn-soft: #36290b;
79
+ --danger: #f87171;
80
+ --danger-hover: #fca5a5;
81
+ --danger-soft: #3a1714;
82
+ --focus: #5fd6ec;
83
+ --log-bg: #090b0e;
84
+ --shadow: 0 1px 2px rgb(0 0 0 / 0.4);
85
+ --shadow-lg: 0 16px 40px rgb(0 0 0 / 0.55);
86
+ color-scheme: dark;
87
+ }
88
+ }
89
+ :root[data-theme="dark"] {
90
+ --bg: #0e1115;
91
+ --surface: #161a20;
92
+ --surface-2: #1c2128;
93
+ --surface-hover: #232a33;
94
+ --border: #2a313b;
95
+ --border-strong: #3a4350;
96
+ --text: #e7eaef;
97
+ --text-dim: #9aa4b2;
98
+ --accent: #2cc4e0;
99
+ --accent-hover: #5fd6ec;
100
+ --accent-text: #052a33;
101
+ --accent-soft: #0f2f37;
102
+ --ok: #4ade80;
103
+ --ok-soft: #12301f;
104
+ --warn: #fbbf24;
105
+ --warn-soft: #36290b;
106
+ --danger: #f87171;
107
+ --danger-hover: #fca5a5;
108
+ --danger-soft: #3a1714;
109
+ --focus: #5fd6ec;
110
+ --log-bg: #090b0e;
111
+ --shadow: 0 1px 2px rgb(0 0 0 / 0.4);
112
+ --shadow-lg: 0 16px 40px rgb(0 0 0 / 0.55);
113
+ color-scheme: dark;
114
+ }
115
+
116
+ /* ------------------------------------------------------------ base */
117
+ *,
118
+ *::before,
119
+ *::after {
120
+ box-sizing: border-box;
121
+ }
122
+ html {
123
+ -webkit-text-size-adjust: 100%;
124
+ }
125
+ body {
126
+ margin: 0;
127
+ background: var(--bg);
128
+ color: var(--text);
129
+ font: var(--t-base) / 1.5 var(--font);
130
+ -webkit-font-smoothing: antialiased;
131
+ }
132
+ h1,
133
+ h2,
134
+ h3,
135
+ p {
136
+ margin: 0;
137
+ }
138
+ a {
139
+ color: var(--accent);
140
+ }
141
+ code,
142
+ .mono {
143
+ font-family: var(--mono);
144
+ font-size: 0.92em;
145
+ }
146
+ button,
147
+ input,
148
+ select {
149
+ font: inherit;
150
+ color: inherit;
151
+ }
152
+ :focus-visible {
153
+ outline: 2px solid var(--focus);
154
+ outline-offset: 2px;
155
+ }
156
+ .visually-hidden {
157
+ position: absolute;
158
+ width: 1px;
159
+ height: 1px;
160
+ overflow: hidden;
161
+ clip: rect(0 0 0 0);
162
+ white-space: nowrap;
163
+ }
164
+ .skip-link {
165
+ position: absolute;
166
+ left: var(--s2);
167
+ top: -100px;
168
+ z-index: 50;
169
+ padding: var(--s2) var(--s3);
170
+ background: var(--surface);
171
+ border-radius: var(--r1);
172
+ }
173
+ .skip-link:focus {
174
+ top: var(--s2);
175
+ }
176
+ .dim {
177
+ color: var(--text-dim);
178
+ }
179
+ .icon {
180
+ width: 16px;
181
+ height: 16px;
182
+ flex: none;
183
+ stroke: currentColor;
184
+ fill: none;
185
+ stroke-width: 2;
186
+ stroke-linecap: round;
187
+ stroke-linejoin: round;
188
+ }
189
+
190
+ /* ------------------------------------------------------------ layout */
191
+ .app {
192
+ display: grid;
193
+ grid-template-columns: var(--sidebar) minmax(0, 1fr);
194
+ min-height: 100vh;
195
+ }
196
+ .sidebar {
197
+ position: sticky;
198
+ top: 0;
199
+ height: 100vh;
200
+ display: flex;
201
+ flex-direction: column;
202
+ gap: var(--s4);
203
+ padding: var(--s4) var(--s3);
204
+ background: var(--surface);
205
+ border-right: 1px solid var(--border);
206
+ }
207
+ .brand {
208
+ display: flex;
209
+ align-items: center;
210
+ gap: var(--s2);
211
+ padding: var(--s1) var(--s2);
212
+ }
213
+ .brand-mark {
214
+ display: grid;
215
+ place-items: center;
216
+ width: 28px;
217
+ height: 28px;
218
+ border-radius: var(--r1);
219
+ background: var(--accent);
220
+ color: var(--accent-text);
221
+ font: 700 var(--t-sm) / 1 var(--mono);
222
+ }
223
+ .brand-name {
224
+ font-weight: 650;
225
+ font-size: var(--t-md);
226
+ }
227
+ .nav {
228
+ display: flex;
229
+ flex-direction: column;
230
+ gap: 2px;
231
+ }
232
+ .nav a {
233
+ display: flex;
234
+ align-items: center;
235
+ gap: var(--s3);
236
+ padding: var(--s2) var(--s3);
237
+ border-radius: var(--r1);
238
+ color: var(--text-dim);
239
+ text-decoration: none;
240
+ font-weight: 500;
241
+ }
242
+ .nav a:hover {
243
+ background: var(--surface-2);
244
+ color: var(--text);
245
+ }
246
+ .nav a[aria-current="page"] {
247
+ background: var(--accent-soft);
248
+ color: var(--accent);
249
+ }
250
+ .nav .count {
251
+ margin-left: auto;
252
+ min-width: 20px;
253
+ padding: 0 var(--s2);
254
+ border-radius: 999px;
255
+ background: var(--ok-soft);
256
+ color: var(--ok);
257
+ font-size: var(--t-xs);
258
+ font-weight: 650;
259
+ text-align: center;
260
+ }
261
+ .sidebar-foot {
262
+ margin-top: auto;
263
+ }
264
+ .theme-select select {
265
+ width: 100%;
266
+ }
267
+ .main {
268
+ min-width: 0;
269
+ padding: var(--s6) var(--s6) var(--s8);
270
+ outline: none;
271
+ }
272
+ .page {
273
+ max-width: 1120px;
274
+ margin: 0 auto;
275
+ display: flex;
276
+ flex-direction: column;
277
+ gap: var(--s5);
278
+ }
279
+ .page-head {
280
+ display: flex;
281
+ flex-wrap: wrap;
282
+ align-items: flex-end;
283
+ justify-content: space-between;
284
+ gap: var(--s4);
285
+ }
286
+ .page-title {
287
+ font-size: var(--t-2xl);
288
+ font-weight: 700;
289
+ line-height: 1.2;
290
+ letter-spacing: -0.01em;
291
+ }
292
+ .page-sub {
293
+ margin-top: var(--s1);
294
+ color: var(--text-dim);
295
+ }
296
+ .toolbar {
297
+ display: flex;
298
+ flex-wrap: wrap;
299
+ align-items: center;
300
+ gap: var(--s2);
301
+ }
302
+ .section {
303
+ display: flex;
304
+ flex-direction: column;
305
+ gap: var(--s3);
306
+ }
307
+ .section-title {
308
+ font-size: var(--t-lg);
309
+ font-weight: 650;
310
+ }
311
+ .section-head {
312
+ display: flex;
313
+ align-items: center;
314
+ justify-content: space-between;
315
+ gap: var(--s3);
316
+ }
317
+
318
+ /* ------------------------------------------------------------ controls */
319
+ .btn {
320
+ display: inline-flex;
321
+ align-items: center;
322
+ justify-content: center;
323
+ gap: var(--s2);
324
+ min-height: var(--control);
325
+ padding: 0 var(--s3);
326
+ border: 1px solid var(--border-strong);
327
+ border-radius: var(--r1);
328
+ background: var(--surface);
329
+ color: var(--text);
330
+ font-weight: 550;
331
+ white-space: nowrap;
332
+ cursor: pointer;
333
+ text-decoration: none;
334
+ }
335
+ .btn:hover {
336
+ background: var(--surface-2);
337
+ }
338
+ .btn:disabled {
339
+ opacity: 0.55;
340
+ cursor: not-allowed;
341
+ }
342
+ .btn-primary {
343
+ background: var(--accent);
344
+ border-color: var(--accent);
345
+ color: var(--accent-text);
346
+ }
347
+ .btn-primary:hover {
348
+ background: var(--accent-hover);
349
+ border-color: var(--accent-hover);
350
+ }
351
+ .btn-danger {
352
+ background: var(--danger);
353
+ border-color: var(--danger);
354
+ color: #fff;
355
+ }
356
+ .btn-danger:hover {
357
+ background: var(--danger-hover);
358
+ border-color: var(--danger-hover);
359
+ }
360
+ :root[data-theme="dark"] .btn-danger,
361
+ :root[data-theme="dark"] .btn-danger:hover {
362
+ color: #1a0a08;
363
+ }
364
+ @media (prefers-color-scheme: dark) {
365
+ :root:not([data-theme="light"]) .btn-danger,
366
+ :root:not([data-theme="light"]) .btn-danger:hover {
367
+ color: #1a0a08;
368
+ }
369
+ }
370
+ .btn-ghost {
371
+ border-color: transparent;
372
+ background: transparent;
373
+ }
374
+ .btn-ghost:hover {
375
+ background: var(--surface-2);
376
+ }
377
+ .btn-danger-ghost {
378
+ border-color: transparent;
379
+ background: transparent;
380
+ color: var(--danger);
381
+ }
382
+ .btn-danger-ghost:hover {
383
+ background: var(--danger-soft);
384
+ }
385
+ .btn-sm {
386
+ min-height: 28px;
387
+ padding: 0 var(--s2);
388
+ font-size: var(--t-sm);
389
+ }
390
+ .input,
391
+ select {
392
+ min-height: var(--control);
393
+ padding: 0 var(--s3);
394
+ border: 1px solid var(--border-strong);
395
+ border-radius: var(--r1);
396
+ background: var(--surface);
397
+ color: var(--text);
398
+ }
399
+ .input::placeholder {
400
+ color: var(--text-dim);
401
+ }
402
+ .input-wide {
403
+ flex: 1;
404
+ min-width: 200px;
405
+ }
406
+ .check {
407
+ display: inline-flex;
408
+ align-items: center;
409
+ gap: var(--s2);
410
+ cursor: pointer;
411
+ }
412
+ .check input {
413
+ width: 16px;
414
+ height: 16px;
415
+ accent-color: var(--accent);
416
+ }
417
+ .segmented {
418
+ display: inline-flex;
419
+ padding: 2px;
420
+ border: 1px solid var(--border-strong);
421
+ border-radius: var(--r1);
422
+ background: var(--surface);
423
+ }
424
+ .segmented button {
425
+ min-height: 28px;
426
+ padding: 0 var(--s3);
427
+ border: 0;
428
+ border-radius: 4px;
429
+ background: transparent;
430
+ color: var(--text-dim);
431
+ font-weight: 550;
432
+ cursor: pointer;
433
+ }
434
+ .segmented button[aria-pressed="true"] {
435
+ background: var(--accent-soft);
436
+ color: var(--accent);
437
+ }
438
+ .field {
439
+ display: flex;
440
+ flex-direction: column;
441
+ gap: var(--s1);
442
+ }
443
+ .field-label {
444
+ font-weight: 600;
445
+ }
446
+ .field-hint {
447
+ color: var(--text-dim);
448
+ font-size: var(--t-sm);
449
+ }
450
+ .form-grid {
451
+ display: grid;
452
+ grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
453
+ gap: var(--s4);
454
+ }
455
+ .form-actions {
456
+ display: flex;
457
+ flex-wrap: wrap;
458
+ align-items: center;
459
+ gap: var(--s3);
460
+ }
461
+
462
+ /* ------------------------------------------------------------ surfaces */
463
+ .card {
464
+ background: var(--surface);
465
+ border: 1px solid var(--border);
466
+ border-radius: var(--r2);
467
+ box-shadow: var(--shadow);
468
+ }
469
+ .card-pad {
470
+ padding: var(--s4) var(--s5);
471
+ }
472
+ .stats {
473
+ display: grid;
474
+ grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
475
+ gap: var(--s3);
476
+ }
477
+ .stat {
478
+ padding: var(--s4);
479
+ }
480
+ .stat-value {
481
+ font-size: var(--t-xl);
482
+ font-weight: 700;
483
+ line-height: 1.2;
484
+ font-variant-numeric: tabular-nums;
485
+ }
486
+ .stat-label {
487
+ color: var(--text-dim);
488
+ font-size: var(--t-sm);
489
+ }
490
+ .note {
491
+ display: flex;
492
+ gap: var(--s3);
493
+ align-items: flex-start;
494
+ padding: var(--s3) var(--s4);
495
+ border-radius: var(--r2);
496
+ background: var(--surface-2);
497
+ color: var(--text-dim);
498
+ }
499
+ .note-warn {
500
+ background: var(--warn-soft);
501
+ color: var(--text);
502
+ }
503
+ .note-danger {
504
+ background: var(--danger-soft);
505
+ color: var(--text);
506
+ }
507
+ .note .icon {
508
+ margin-top: 2px;
509
+ }
510
+
511
+ /* ------------------------------------------------------------ lists and tables */
512
+ .table-wrap {
513
+ position: relative; /* keeps screen-reader-only labels inside the scrolling box */
514
+ overflow-x: auto;
515
+ }
516
+ .table {
517
+ width: 100%;
518
+ border-collapse: collapse;
519
+ }
520
+ .table th {
521
+ padding: var(--s2) var(--s4);
522
+ border-bottom: 1px solid var(--border);
523
+ color: var(--text-dim);
524
+ font-size: var(--t-xs);
525
+ font-weight: 600;
526
+ letter-spacing: 0.04em;
527
+ text-align: left;
528
+ text-transform: uppercase;
529
+ white-space: nowrap;
530
+ }
531
+ .table td {
532
+ padding: var(--s3) var(--s4);
533
+ border-bottom: 1px solid var(--border);
534
+ vertical-align: middle;
535
+ }
536
+ .table tr:last-child td {
537
+ border-bottom: 0;
538
+ }
539
+ .table tbody tr:hover td {
540
+ background: var(--surface-2);
541
+ }
542
+ .table .num {
543
+ text-align: right;
544
+ font-variant-numeric: tabular-nums;
545
+ white-space: nowrap;
546
+ }
547
+ .table .cmd {
548
+ max-width: 420px;
549
+ overflow: hidden;
550
+ text-overflow: ellipsis;
551
+ white-space: nowrap;
552
+ font-family: var(--mono);
553
+ font-size: var(--t-xs);
554
+ color: var(--text-dim);
555
+ }
556
+ .table .actions {
557
+ text-align: right;
558
+ white-space: nowrap;
559
+ }
560
+ .row-detail td {
561
+ background: var(--surface-2);
562
+ }
563
+
564
+ .project-list {
565
+ display: flex;
566
+ flex-direction: column;
567
+ }
568
+ .project {
569
+ display: grid;
570
+ grid-template-columns: minmax(0, 1fr) auto;
571
+ gap: var(--s4);
572
+ align-items: center;
573
+ padding: var(--s3) var(--s5);
574
+ border-bottom: 1px solid var(--border);
575
+ }
576
+ .project:last-child {
577
+ border-bottom: 0;
578
+ }
579
+ .project-name {
580
+ display: flex;
581
+ flex-wrap: wrap;
582
+ align-items: center;
583
+ gap: var(--s2);
584
+ font-weight: 650;
585
+ font-size: var(--t-md);
586
+ }
587
+ .project-meta {
588
+ display: flex;
589
+ flex-wrap: wrap;
590
+ gap: var(--s1) var(--s4);
591
+ margin-top: 2px;
592
+ color: var(--text-dim);
593
+ font-size: var(--t-sm);
594
+ }
595
+ .project-meta .mono {
596
+ overflow-wrap: anywhere;
597
+ }
598
+ .project-actions {
599
+ display: flex;
600
+ flex-wrap: wrap;
601
+ justify-content: flex-end;
602
+ gap: var(--s2);
603
+ }
604
+
605
+ .badge {
606
+ display: inline-flex;
607
+ align-items: center;
608
+ gap: var(--s1);
609
+ padding: 1px var(--s2);
610
+ border-radius: 999px;
611
+ background: var(--surface-2);
612
+ color: var(--text-dim);
613
+ font-size: var(--t-xs);
614
+ font-weight: 600;
615
+ white-space: nowrap;
616
+ }
617
+ .badge-ok {
618
+ background: var(--ok-soft);
619
+ color: var(--ok);
620
+ }
621
+ .badge-warn {
622
+ background: var(--warn-soft);
623
+ color: var(--warn);
624
+ }
625
+ .badge-danger {
626
+ background: var(--danger-soft);
627
+ color: var(--danger);
628
+ }
629
+ .badge-accent {
630
+ background: var(--accent-soft);
631
+ color: var(--accent);
632
+ }
633
+ .dot {
634
+ width: 8px;
635
+ height: 8px;
636
+ border-radius: 50%;
637
+ background: currentColor;
638
+ }
639
+ .dot-pulse {
640
+ animation: pulse 1.4s ease-in-out infinite;
641
+ }
642
+ @keyframes pulse {
643
+ 50% {
644
+ opacity: 0.35;
645
+ }
646
+ }
647
+
648
+ /* menu for "More" actions */
649
+ .menu {
650
+ position: relative;
651
+ }
652
+ .menu > summary {
653
+ list-style: none;
654
+ }
655
+ .menu > summary::-webkit-details-marker {
656
+ display: none;
657
+ }
658
+ .menu-list {
659
+ position: absolute;
660
+ right: 0;
661
+ top: calc(100% + var(--s1));
662
+ z-index: 20;
663
+ display: flex;
664
+ flex-direction: column;
665
+ min-width: 220px;
666
+ padding: var(--s1);
667
+ background: var(--surface);
668
+ border: 1px solid var(--border);
669
+ border-radius: var(--r2);
670
+ box-shadow: var(--shadow-lg);
671
+ }
672
+ .menu-list button {
673
+ display: flex;
674
+ align-items: center;
675
+ gap: var(--s2);
676
+ padding: var(--s2) var(--s3);
677
+ border: 0;
678
+ border-radius: var(--r1);
679
+ background: transparent;
680
+ text-align: left;
681
+ cursor: pointer;
682
+ }
683
+ .menu-list button:hover:not(:disabled) {
684
+ background: var(--surface-2);
685
+ }
686
+ .menu-list button:disabled {
687
+ color: var(--text-dim);
688
+ cursor: not-allowed;
689
+ }
690
+
691
+ /* ------------------------------------------------------------ dev servers */
692
+ .dev-list {
693
+ display: flex;
694
+ flex-direction: column;
695
+ gap: var(--s3);
696
+ }
697
+ .dev {
698
+ overflow: hidden;
699
+ }
700
+ .dev-head {
701
+ display: flex;
702
+ flex-wrap: wrap;
703
+ align-items: center;
704
+ justify-content: space-between;
705
+ gap: var(--s3);
706
+ padding: var(--s3) var(--s4);
707
+ }
708
+ .dev-title {
709
+ display: flex;
710
+ flex-wrap: wrap;
711
+ align-items: center;
712
+ gap: var(--s2) var(--s3);
713
+ min-width: 0;
714
+ }
715
+ .log {
716
+ height: 280px;
717
+ margin: 0;
718
+ padding: var(--s3) var(--s4);
719
+ overflow: auto;
720
+ background: var(--log-bg);
721
+ color: var(--log-text);
722
+ font: var(--t-xs) / 1.6 var(--mono);
723
+ white-space: pre-wrap;
724
+ overflow-wrap: anywhere;
725
+ }
726
+ .log .err {
727
+ color: var(--log-err);
728
+ }
729
+ .log .dx {
730
+ color: var(--log-dx);
731
+ }
732
+ .log .empty {
733
+ color: var(--log-dim);
734
+ }
735
+ .log-snippet {
736
+ height: auto;
737
+ max-height: 160px;
738
+ padding: var(--s2) var(--s3);
739
+ border-radius: var(--r1);
740
+ font-size: var(--t-xs);
741
+ }
742
+
743
+ /* A stack's services */
744
+ .stack-services {
745
+ margin: 0;
746
+ padding: 0 var(--s4) var(--s3);
747
+ list-style: none;
748
+ }
749
+ .stack-services li {
750
+ display: flex;
751
+ flex-wrap: wrap;
752
+ align-items: center;
753
+ gap: var(--s2) var(--s3);
754
+ padding: var(--s2) 0;
755
+ border-top: 1px solid var(--border);
756
+ min-width: 0;
757
+ }
758
+ .stack-services li > .badge:first-child {
759
+ min-width: 84px;
760
+ }
761
+ .stack-cmd {
762
+ overflow-wrap: anywhere;
763
+ }
764
+ .stack-note {
765
+ display: flex;
766
+ align-items: center;
767
+ gap: var(--s2);
768
+ margin: 0;
769
+ padding: var(--s2) var(--s4) var(--s3);
770
+ color: var(--warn);
771
+ }
772
+ .log-filter {
773
+ padding: var(--s2) var(--s4);
774
+ border-top: 1px solid var(--border);
775
+ overflow-x: auto;
776
+ }
777
+ .log .svc {
778
+ color: var(--log-dx);
779
+ }
780
+
781
+ /* Errors found in a dev server's output */
782
+ .dev-errors {
783
+ border-top: 1px solid var(--border);
784
+ }
785
+ .dev-error-list {
786
+ margin: 0;
787
+ padding: 0;
788
+ list-style: none;
789
+ }
790
+ .dev-error {
791
+ display: flex;
792
+ flex-direction: column;
793
+ align-items: flex-start;
794
+ gap: var(--s2);
795
+ padding: var(--s3) var(--s4);
796
+ border-bottom: 1px solid var(--border);
797
+ }
798
+ .dev-error:last-child {
799
+ border-bottom: 0;
800
+ }
801
+ .dev-error .log-snippet {
802
+ align-self: stretch;
803
+ }
804
+ .dev-error-head {
805
+ display: flex;
806
+ flex-wrap: wrap;
807
+ align-items: baseline;
808
+ gap: var(--s2);
809
+ min-width: 0;
810
+ }
811
+ .dev-error-message {
812
+ overflow-wrap: anywhere;
813
+ }
814
+ .dev-errors-empty {
815
+ display: flex;
816
+ align-items: center;
817
+ gap: var(--s2);
818
+ margin: 0;
819
+ padding: var(--s3) var(--s4);
820
+ color: var(--text-dim);
821
+ }
822
+
823
+ /* ------------------------------------------------------------ journal and summary */
824
+ .day {
825
+ display: flex;
826
+ flex-direction: column;
827
+ gap: var(--s2);
828
+ padding: var(--s4) var(--s5);
829
+ border-bottom: 1px solid var(--border);
830
+ }
831
+ .day:last-child {
832
+ border-bottom: 0;
833
+ }
834
+ .day-title {
835
+ font-size: var(--t-base);
836
+ font-weight: 650;
837
+ }
838
+ .entries {
839
+ margin: 0;
840
+ padding: 0;
841
+ list-style: none;
842
+ display: flex;
843
+ flex-direction: column;
844
+ gap: var(--s1);
845
+ }
846
+ .entries li {
847
+ display: grid;
848
+ grid-template-columns: 52px minmax(0, 1fr);
849
+ gap: var(--s3);
850
+ }
851
+ .entries .time {
852
+ color: var(--text-dim);
853
+ font-family: var(--mono);
854
+ font-size: var(--t-xs);
855
+ line-height: 1.85;
856
+ }
857
+ .bullets {
858
+ margin: 0;
859
+ padding-left: var(--s5);
860
+ display: flex;
861
+ flex-direction: column;
862
+ gap: var(--s1);
863
+ }
864
+ .bar-row {
865
+ display: grid;
866
+ grid-template-columns: minmax(120px, 200px) minmax(0, 1fr);
867
+ gap: var(--s3);
868
+ align-items: center;
869
+ }
870
+ .bar {
871
+ height: 8px;
872
+ border-radius: 999px;
873
+ background: var(--accent);
874
+ }
875
+ .bar-track {
876
+ display: flex;
877
+ align-items: center;
878
+ gap: var(--s3);
879
+ min-width: 0;
880
+ }
881
+ .bar-label {
882
+ color: var(--text-dim);
883
+ font-size: var(--t-sm);
884
+ white-space: nowrap;
885
+ }
886
+
887
+ /* ------------------------------------------------------------ progress, states, feedback */
888
+ .progress {
889
+ height: 8px;
890
+ overflow: hidden;
891
+ border-radius: 999px;
892
+ background: var(--surface-2);
893
+ }
894
+ .progress > div {
895
+ height: 100%;
896
+ background: var(--accent);
897
+ transition: width 0.3s ease;
898
+ }
899
+ .state {
900
+ display: flex;
901
+ flex-direction: column;
902
+ align-items: center;
903
+ gap: var(--s2);
904
+ padding: var(--s8) var(--s5);
905
+ color: var(--text-dim);
906
+ text-align: center;
907
+ }
908
+ .state-title {
909
+ color: var(--text);
910
+ font-size: var(--t-md);
911
+ font-weight: 650;
912
+ }
913
+ .spinner {
914
+ width: 18px;
915
+ height: 18px;
916
+ border: 2px solid var(--border-strong);
917
+ border-top-color: var(--accent);
918
+ border-radius: 50%;
919
+ animation: spin 0.8s linear infinite;
920
+ }
921
+ @keyframes spin {
922
+ to {
923
+ transform: rotate(360deg);
924
+ }
925
+ }
926
+ .checks {
927
+ margin: 0;
928
+ padding: 0;
929
+ list-style: none;
930
+ }
931
+ .checks li {
932
+ display: grid;
933
+ grid-template-columns: 24px 150px minmax(0, 1fr);
934
+ gap: var(--s3);
935
+ padding: var(--s3) var(--s5);
936
+ border-bottom: 1px solid var(--border);
937
+ }
938
+ .checks li:last-child {
939
+ border-bottom: 0;
940
+ }
941
+ .checks-actions li {
942
+ grid-template-columns: 24px 150px minmax(0, 1fr) auto;
943
+ align-items: center;
944
+ }
945
+ .check-fix {
946
+ display: block;
947
+ margin-top: var(--s1);
948
+ font-size: var(--t-sm);
949
+ color: var(--text-dim);
950
+ }
951
+ .status-ok {
952
+ color: var(--ok);
953
+ }
954
+ .status-warn {
955
+ color: var(--warn);
956
+ }
957
+ .status-fail {
958
+ color: var(--danger);
959
+ }
960
+ .chips {
961
+ display: flex;
962
+ flex-wrap: wrap;
963
+ gap: var(--s2);
964
+ }
965
+ .chip {
966
+ display: inline-flex;
967
+ align-items: center;
968
+ gap: var(--s1);
969
+ padding: var(--s1) var(--s1) var(--s1) var(--s3);
970
+ border: 1px solid var(--border);
971
+ border-radius: 999px;
972
+ background: var(--surface-2);
973
+ font-family: var(--mono);
974
+ font-size: var(--t-xs);
975
+ }
976
+
977
+ .toasts {
978
+ position: fixed;
979
+ right: var(--s5);
980
+ bottom: var(--s5);
981
+ z-index: 60;
982
+ display: flex;
983
+ flex-direction: column;
984
+ gap: var(--s2);
985
+ max-width: min(420px, calc(100vw - 2 * var(--s4)));
986
+ }
987
+ .toast {
988
+ display: flex;
989
+ gap: var(--s3);
990
+ align-items: flex-start;
991
+ padding: var(--s3) var(--s4);
992
+ border: 1px solid var(--border);
993
+ border-left: 4px solid var(--ok);
994
+ border-radius: var(--r2);
995
+ background: var(--surface);
996
+ box-shadow: var(--shadow-lg);
997
+ }
998
+ .toast-error {
999
+ border-left-color: var(--danger);
1000
+ }
1001
+ .dialog {
1002
+ width: min(480px, calc(100vw - 2 * var(--s4)));
1003
+ padding: 0;
1004
+ border: 1px solid var(--border);
1005
+ border-radius: var(--r3);
1006
+ background: var(--surface);
1007
+ color: var(--text);
1008
+ box-shadow: var(--shadow-lg);
1009
+ }
1010
+ .dialog::backdrop {
1011
+ background: rgb(10 14 20 / 0.5);
1012
+ }
1013
+ .dialog-body {
1014
+ display: flex;
1015
+ flex-direction: column;
1016
+ gap: var(--s3);
1017
+ padding: var(--s5);
1018
+ }
1019
+ .dialog-title {
1020
+ font-size: var(--t-lg);
1021
+ font-weight: 650;
1022
+ }
1023
+ .dialog-text {
1024
+ color: var(--text-dim);
1025
+ overflow-wrap: anywhere;
1026
+ }
1027
+ .dialog-actions {
1028
+ display: flex;
1029
+ justify-content: flex-end;
1030
+ gap: var(--s2);
1031
+ margin-top: var(--s2);
1032
+ }
1033
+ .sticky-bar {
1034
+ position: sticky;
1035
+ bottom: var(--s4);
1036
+ display: flex;
1037
+ flex-wrap: wrap;
1038
+ align-items: center;
1039
+ justify-content: space-between;
1040
+ gap: var(--s3);
1041
+ padding: var(--s3) var(--s4);
1042
+ background: var(--surface);
1043
+ border: 1px solid var(--border);
1044
+ border-radius: var(--r2);
1045
+ box-shadow: var(--shadow-lg);
1046
+ }
1047
+
1048
+ /* ------------------------------------------------------------ narrow screens */
1049
+ @media (max-width: 860px) {
1050
+ .app {
1051
+ grid-template-columns: minmax(0, 1fr);
1052
+ }
1053
+ .sidebar {
1054
+ position: sticky;
1055
+ z-index: 30;
1056
+ height: auto;
1057
+ flex-direction: row;
1058
+ align-items: center;
1059
+ gap: var(--s2);
1060
+ padding: var(--s2) var(--s4);
1061
+ border-right: 0;
1062
+ border-bottom: 1px solid var(--border);
1063
+ overflow-x: auto;
1064
+ }
1065
+ .brand-name,
1066
+ .sidebar-foot {
1067
+ display: none;
1068
+ }
1069
+ .nav {
1070
+ flex-direction: row;
1071
+ }
1072
+ .nav a {
1073
+ padding: var(--s2);
1074
+ white-space: nowrap;
1075
+ }
1076
+ .nav .nav-label {
1077
+ display: none;
1078
+ }
1079
+ .nav a[aria-current="page"] .nav-label {
1080
+ display: inline;
1081
+ }
1082
+ .main {
1083
+ padding: var(--s5) var(--s4) var(--s8);
1084
+ }
1085
+ .project {
1086
+ grid-template-columns: minmax(0, 1fr);
1087
+ padding: var(--s3) var(--s4);
1088
+ }
1089
+ .project-actions {
1090
+ justify-content: flex-start;
1091
+ }
1092
+ .card-pad,
1093
+ .day,
1094
+ .checks li {
1095
+ padding-left: var(--s4);
1096
+ padding-right: var(--s4);
1097
+ }
1098
+ .checks li {
1099
+ grid-template-columns: 24px minmax(0, 1fr);
1100
+ }
1101
+ .checks li > :last-child,
1102
+ .checks-actions li > :not(:first-child) {
1103
+ grid-column: 2;
1104
+ }
1105
+ .checks-actions li > .btn {
1106
+ justify-self: start;
1107
+ }
1108
+ .bar-row {
1109
+ grid-template-columns: minmax(0, 1fr);
1110
+ gap: var(--s1);
1111
+ }
1112
+ .table .cmd {
1113
+ max-width: 220px;
1114
+ }
1115
+ }
1116
+
1117
+ @media (prefers-reduced-motion: reduce) {
1118
+ *,
1119
+ *::before,
1120
+ *::after {
1121
+ animation-duration: 0.01ms !important;
1122
+ transition-duration: 0.01ms !important;
1123
+ }
1124
+ }