@nhic-lab/srv-wrapper 0.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.
@@ -0,0 +1,838 @@
1
+ /* srv ops console — Innovative VAS design system, light.
2
+ Values transcribed from the `Srv Console B.dc.html` prototype. */
3
+
4
+ :root {
5
+ --hillmist: #F3F6F4;
6
+ --white: #FFFFFF;
7
+ --basalt: #17211B;
8
+ --canopy: #0E3B2C;
9
+ --tea: #0B6B4D;
10
+ --tea-dark: #095940;
11
+ --sunbird: #E8A33D;
12
+
13
+ --line: #E4EAE6;
14
+ --line-strong: #C6CFC9;
15
+ --muted: #55605A;
16
+ --muted-2: #5C6761;
17
+
18
+ --danger: #B3372B;
19
+ --danger-bg: #F9E9E7;
20
+ --ok-bg: #E3F0EA;
21
+ --testing-bg: #FBF0DC;
22
+ --testing-fg: #9A5B0B;
23
+ --agent-bg: #E3EEF2;
24
+ --agent-fg: #155E75;
25
+
26
+ --term-bg: #17211B;
27
+ --term-fg: #F3F6F4;
28
+ --term-gutter: #8B9891;
29
+ --stderr: #E8A33D;
30
+ --stderr-bg: rgba(232, 163, 61, 0.07);
31
+
32
+ --font-ui: 'IBM Plex Sans', system-ui, sans-serif;
33
+ --font-head: 'Archivo', sans-serif;
34
+ --font-mono: 'JetBrains Mono', ui-monospace, monospace;
35
+
36
+ --ease: cubic-bezier(0.2, 0, 0, 1);
37
+ --shadow: 0 8px 24px -12px rgba(23, 33, 27, 0.25);
38
+
39
+ --list-w: 404px;
40
+ }
41
+
42
+ /* Dark theme: the same Innovative VAS vocabulary re-grounded on a deep
43
+ basalt-green canvas. Tea Field and the status colours are lifted for
44
+ contrast on dark; Sunbird already reads well and is unchanged. Fill colours
45
+ (button backgrounds) stay saturated, while the matching *text* colours are
46
+ lightened, because dark-on-dark text fails contrast where a fill does not. */
47
+ :root[data-theme="dark"] {
48
+ color-scheme: dark;
49
+
50
+ --hillmist: #0E1411;
51
+ --white: #161E19;
52
+ --basalt: #E8EDE9;
53
+ --canopy: #0A2A1F;
54
+ --tea: #0B6B4D;
55
+ --tea-dark: #0E8560;
56
+ --sunbird: #E8A33D;
57
+
58
+ --line: #26302A;
59
+ --line-strong: #3A463E;
60
+ --muted: #A7B2AB;
61
+ --muted-2: #8E9A93;
62
+
63
+ --danger: #F08C7F;
64
+ --danger-bg: rgba(179, 55, 43, 0.20);
65
+ --ok-bg: rgba(47, 158, 116, 0.18);
66
+ --testing-bg: rgba(232, 163, 61, 0.16);
67
+ --testing-fg: #E8A33D;
68
+ --agent-bg: rgba(21, 94, 117, 0.35);
69
+ --agent-fg: #8CCFE2;
70
+
71
+ --term-bg: #080C0A;
72
+ --term-fg: #E8EDE9;
73
+ --term-gutter: #8B9891;
74
+ --stderr: #E8A33D;
75
+ --stderr-bg: rgba(232, 163, 61, 0.10);
76
+
77
+ --shadow: 0 10px 30px -12px rgba(0, 0, 0, 0.72);
78
+ --scrim: rgba(0, 0, 0, 0.60);
79
+ --raised: #1B241E;
80
+
81
+ --on-canopy: #F3F6F4;
82
+ --on-sunbird: #17211B;
83
+ --on-tea: #FFFFFF;
84
+ --danger-fill: #B3372B;
85
+ /* Tea Field as *text* needs lifting on a dark canvas; as a *fill* it stays. */
86
+ --tea-text: #6FD3A8;
87
+ }
88
+
89
+ :root {
90
+ --scrim: rgba(23, 33, 27, 0.42);
91
+ --raised: #FFFFFF;
92
+
93
+ /* "On-fill" tokens. The command bar, the Sunbird mark and the Tea Field
94
+ buttons are dark/saturated in BOTH themes, so text sitting on them must
95
+ stay fixed. Deriving these from --white/--basalt/--hillmist (which do
96
+ invert) is what produced light-on-amber and dark-on-green in dark mode. */
97
+ --on-canopy: #F3F6F4;
98
+ --on-sunbird: #17211B;
99
+ --on-tea: #FFFFFF;
100
+ --danger-fill: #B3372B;
101
+ --tea-text: #0B6B4D;
102
+ }
103
+
104
+ * { box-sizing: border-box; }
105
+
106
+ html, body {
107
+ margin: 0;
108
+ padding: 0;
109
+ height: 100%;
110
+ background: var(--hillmist);
111
+ }
112
+
113
+ body {
114
+ font: 400 1rem/1.6 var(--font-ui);
115
+ color: var(--basalt);
116
+ -webkit-font-smoothing: antialiased;
117
+ overflow: hidden;
118
+ }
119
+
120
+ input, select, textarea, button { font-family: inherit; }
121
+
122
+ a { color: var(--tea-text); text-decoration: none; }
123
+ a:hover { color: var(--tea-text); text-decoration: underline; }
124
+
125
+ ::selection { background: var(--ok-bg); }
126
+
127
+ :focus-visible { outline: 2px solid var(--sunbird); outline-offset: 2px; }
128
+ /* clip-path clips outlines, so faceted elements take an inset ring instead */
129
+ .facet-8:focus-visible,
130
+ .facet-14:focus-visible,
131
+ .facet-24:focus-visible { outline: none; box-shadow: inset 0 0 0 2px var(--sunbird); }
132
+
133
+ ::-webkit-scrollbar { width: 10px; height: 10px; }
134
+ ::-webkit-scrollbar-thumb { background: var(--line-strong); }
135
+ .term::-webkit-scrollbar-thumb { background: #3a463e; }
136
+
137
+ @keyframes tick { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }
138
+ @keyframes pop { from { transform: translateY(6px) scale(0.99); opacity: 0; } to { transform: none; opacity: 1; } }
139
+ @keyframes fadein { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
140
+
141
+ @media (prefers-reduced-motion: reduce) {
142
+ *, *::before, *::after {
143
+ animation-duration: 0.01ms !important;
144
+ animation-iteration-count: 1 !important;
145
+ }
146
+ }
147
+
148
+ /* ---------- facet cuts ---------- */
149
+ .facet-8 { clip-path: polygon(0 8px, 8px 0, 100% 0, 100% calc(100% - 8px), calc(100% - 8px) 100%, 0 100%); }
150
+ .facet-14 { clip-path: polygon(0 14px, 14px 0, 100% 0, 100% calc(100% - 14px), calc(100% - 14px) 100%, 0 100%); }
151
+ .facet-24 { clip-path: polygon(0 24px, 24px 0, 100% 0, 100% calc(100% - 24px), calc(100% - 24px) 100%, 0 100%); }
152
+
153
+ /* ---------- shell ---------- */
154
+ .app {
155
+ display: flex;
156
+ flex-direction: column;
157
+ height: 100vh;
158
+ height: 100dvh;
159
+ background: var(--hillmist);
160
+ }
161
+
162
+ .topbar { background: var(--canopy); color: var(--on-canopy); flex: none; }
163
+ .topbar-inner { display: flex; align-items: stretch; gap: 28px; padding: 0 28px; }
164
+
165
+ .brand { display: flex; align-items: center; gap: 12px; padding: 14px 0; flex: none; }
166
+ .brand-mark {
167
+ width: 32px; height: 32px; background: var(--sunbird); color: var(--on-sunbird);
168
+ display: grid; place-items: center;
169
+ font: 700 0.8125rem/1 var(--font-mono);
170
+ flex: none;
171
+ }
172
+ .brand-name { font: 700 1.0625rem/1.1 var(--font-head); letter-spacing: -0.02em; white-space: nowrap; }
173
+ .brand-sub {
174
+ font: 500 0.6875rem/1 var(--font-head);
175
+ letter-spacing: 0.08em; text-transform: uppercase;
176
+ color: rgba(243, 246, 244, 0.6); margin-left: 6px;
177
+ }
178
+
179
+ .tabs { display: flex; align-items: stretch; gap: 2px; min-width: 0; }
180
+ .tab {
181
+ display: flex; align-items: center; gap: 8px;
182
+ border: 0; padding: 0 16px; cursor: pointer;
183
+ font: 500 0.9375rem/1.3 var(--font-ui);
184
+ background: transparent; color: rgba(243, 246, 244, 0.7);
185
+ box-shadow: none; white-space: nowrap;
186
+ transition: background 120ms var(--ease), color 120ms var(--ease);
187
+ }
188
+ .tab:hover { color: #FFFFFF; background: rgba(243, 246, 244, 0.06); }
189
+ .tab.active { background: rgba(243, 246, 244, 0.12); color: #FFFFFF; box-shadow: inset 0 -3px 0 var(--sunbird); }
190
+ .tab svg { flex: none; }
191
+ .tab-badge { font: 500 0.75rem/1 var(--font-mono); background: var(--sunbird); color: var(--on-sunbird); padding: 3px 6px; }
192
+ .tab-count { font: 400 0.8125rem/1 var(--font-mono); opacity: 0.6; }
193
+
194
+ .topbar-spacer { flex: 1; }
195
+
196
+ .topbar-right { display: flex; align-items: center; gap: 18px; padding: 14px 0; flex: none; }
197
+ .conn { display: flex; align-items: center; gap: 9px; }
198
+ .conn-dot { width: 7px; height: 7px; flex: none; background: var(--line-strong); }
199
+ .conn[data-state="connected"] .conn-dot { background: var(--tea-text); }
200
+ .conn[data-state="connecting"] .conn-dot { background: var(--sunbird); animation: tick 1.8s ease-in-out infinite; }
201
+ .conn[data-state="disconnected"] .conn-dot { background: var(--danger); }
202
+ .conn-label { font: 400 0.8125rem/1.3 var(--font-ui); color: rgba(243, 246, 244, 0.85); white-space: nowrap; }
203
+ .conn-addr { font: 400 0.8125rem/1.3 var(--font-mono); color: rgba(243, 246, 244, 0.72); white-space: nowrap; }
204
+
205
+ .palette-btn {
206
+ display: flex; align-items: center; gap: 9px;
207
+ background: rgba(243, 246, 244, 0.08);
208
+ border: 1px solid rgba(243, 246, 244, 0.18);
209
+ color: rgba(243, 246, 244, 0.9);
210
+ padding: 7px 11px; cursor: pointer;
211
+ font: 400 0.8125rem/1.3 var(--font-ui);
212
+ white-space: nowrap;
213
+ transition: background 120ms var(--ease);
214
+ }
215
+ .palette-btn:hover { background: rgba(243, 246, 244, 0.16); }
216
+ .palette-btn-kbd { font: 500 0.75rem/1 var(--font-mono); }
217
+
218
+ .imigongo { display: block; }
219
+ .imigongo-bg { fill: var(--canopy); }
220
+
221
+ /* ---------- body / two-pane ---------- */
222
+ .body {
223
+ flex: 1; min-height: 0;
224
+ display: grid;
225
+ grid-template-columns: var(--list-w) minmax(0, 1fr);
226
+ }
227
+
228
+ /* ---------- list pane ---------- */
229
+ .list-pane {
230
+ border-right: 1px solid var(--line);
231
+ background: var(--white);
232
+ display: flex; flex-direction: column;
233
+ min-height: 0; min-width: 0;
234
+ }
235
+
236
+ .list-head { padding: 20px 22px 14px; flex: none; }
237
+ .list-overline {
238
+ font: 600 0.6875rem/1.2 var(--font-head);
239
+ letter-spacing: 0.08em; text-transform: uppercase;
240
+ color: var(--tea-text); margin-bottom: 6px;
241
+ }
242
+ .list-title-row { display: flex; align-items: center; gap: 12px; }
243
+ .list-title {
244
+ flex: 1; min-width: 0; margin: 0;
245
+ font: 700 1.75rem/1.2 var(--font-head);
246
+ letter-spacing: -0.02em;
247
+ }
248
+ .btn-add {
249
+ display: flex; align-items: center; gap: 7px; flex: none;
250
+ background: var(--tea); border: 0; color: var(--on-tea);
251
+ padding: 9px 14px; cursor: pointer;
252
+ font: 600 0.8125rem/1.2 var(--font-ui);
253
+ transition: background 120ms var(--ease);
254
+ }
255
+ .btn-add:hover { background: var(--tea-dark); }
256
+
257
+ .list-filters { padding: 0 22px 14px; display: flex; gap: 8px; flex: none; }
258
+ .search-wrap { position: relative; flex: 1; min-width: 0; }
259
+ .search-icon { position: absolute; left: 10px; top: 10px; pointer-events: none; stroke: var(--muted-2); }
260
+ .search-input {
261
+ width: 100%;
262
+ border: 1px solid var(--line-strong); border-radius: 2px;
263
+ background: var(--hillmist);
264
+ padding: 8px 10px 8px 32px;
265
+ font: 400 0.875rem/1.4 var(--font-ui);
266
+ color: var(--basalt);
267
+ -webkit-appearance: none; appearance: none;
268
+ }
269
+ .search-input::-webkit-search-cancel-button { -webkit-appearance: none; }
270
+ .hist-select {
271
+ border: 1px solid var(--line-strong); border-radius: 2px;
272
+ background: var(--white); padding: 8px;
273
+ font: 400 0.8125rem/1.4 var(--font-ui);
274
+ color: var(--basalt); flex: none;
275
+ }
276
+ .btn-testall {
277
+ display: flex; align-items: center; gap: 7px; flex: none;
278
+ background: transparent; border: 1px solid var(--line-strong);
279
+ color: var(--basalt); padding: 8px 11px; cursor: pointer;
280
+ font: 500 0.8125rem/1.2 var(--font-ui); white-space: nowrap;
281
+ }
282
+ .btn-testall:hover { border-color: var(--muted-2); }
283
+ .btn-testall[disabled] { opacity: 0.55; cursor: default; }
284
+
285
+ .list-scroll { flex: 1; min-height: 0; overflow: auto; border-top: 1px solid var(--line); }
286
+
287
+ .row {
288
+ display: flex; align-items: center; gap: 12px;
289
+ width: 100%; text-align: left;
290
+ border: 0; border-bottom: 1px solid var(--line);
291
+ border-left: 3px solid transparent;
292
+ background: transparent;
293
+ padding: 13px 20px; cursor: pointer;
294
+ font: inherit; color: inherit;
295
+ }
296
+ .row:hover { background: var(--hillmist); }
297
+ .row.active { border-left-color: var(--tea-text); background: var(--ok-bg); }
298
+ .row-dot { width: 8px; height: 8px; flex: none; background: var(--line-strong); }
299
+ .row-dot.lg { width: 9px; height: 9px; }
300
+ .row-dot.online { background: var(--tea-text); }
301
+ .row-dot.offline { background: var(--danger); }
302
+ .row-dot.testing { background: var(--sunbird); animation: tick 1.8s ease-in-out infinite; }
303
+ .row-dot.untested { background: var(--line-strong); }
304
+ .row-dot.live { background: var(--tea-text); animation: tick 1.8s ease-in-out infinite; }
305
+ .row-dot.ended { background: var(--tea-text); }
306
+ .row-dot.failed { background: var(--danger); }
307
+ .row-main { flex: 1; min-width: 0; }
308
+ .row-top { display: flex; align-items: center; gap: 8px; min-width: 0; }
309
+ .row-title {
310
+ font: 500 0.9375rem/1.3 var(--font-mono); color: var(--basalt);
311
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
312
+ }
313
+ .row-sub {
314
+ display: block; margin-top: 3px;
315
+ font: 400 0.8125rem/1.4 var(--font-mono); color: var(--muted);
316
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
317
+ }
318
+ .row-meta {
319
+ font: 400 0.75rem/1.3 var(--font-mono); color: var(--muted-2);
320
+ flex: none; text-align: right; white-space: nowrap;
321
+ }
322
+ .list-empty { padding: 28px 22px; font: 400 0.875rem/1.5 var(--font-ui); color: var(--muted-2); }
323
+
324
+ /* chips */
325
+ .chip {
326
+ display: inline-flex; align-items: center; gap: 6px;
327
+ padding: 3px 9px; font: 500 0.75rem/1.35 var(--font-ui);
328
+ white-space: nowrap; flex: none;
329
+ background: var(--hillmist); color: var(--muted);
330
+ }
331
+ .chip.ok, .chip.running { background: var(--ok-bg); color: var(--tea-text); }
332
+ .chip.fail { background: var(--danger-bg); color: var(--danger); }
333
+ .chip.testing { background: var(--testing-bg); color: var(--testing-fg); }
334
+ .chip.untested { background: var(--hillmist); color: var(--muted); }
335
+ .agent-chip {
336
+ display: inline-flex; flex: none;
337
+ background: var(--agent-bg); color: var(--agent-fg);
338
+ padding: 2px 7px; font: 500 0.6875rem/1.4 var(--font-ui);
339
+ max-width: 150px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
340
+ }
341
+
342
+ /* bulk import disclosure */
343
+ .import { border-top: 1px solid var(--line); padding: 14px 22px 18px; flex: none; }
344
+ .import-toggle {
345
+ display: flex; align-items: center; gap: 8px; width: 100%;
346
+ background: transparent; border: 0; cursor: pointer;
347
+ font: 500 0.8125rem/1.3 var(--font-ui); color: var(--muted);
348
+ /* padding + equal negative margin: a real 29px tap target, zero layout shift */
349
+ padding: 6px 0; margin: -6px 0;
350
+ }
351
+ .import-toggle:hover { color: var(--basalt); }
352
+ .import-chev { flex: none; transition: transform 140ms var(--ease); }
353
+ .import.open .import-chev { transform: rotate(90deg); }
354
+ .import-toggle-label { flex: 1; text-align: left; }
355
+ .import-body { margin-top: 12px; }
356
+ .import-ta {
357
+ width: 100%; min-height: 128px;
358
+ border: 1px solid var(--line-strong); border-radius: 2px;
359
+ background: var(--hillmist); padding: 10px 12px;
360
+ font: 400 0.75rem/1.6 var(--font-mono); color: var(--basalt);
361
+ resize: vertical;
362
+ }
363
+ .import-ta.invalid { border-color: var(--danger); }
364
+ .import-foot { display: flex; align-items: center; gap: 10px; margin-top: 10px; }
365
+ .import-hint { flex: 1; font: 400 0.75rem/1.45 var(--font-ui); color: var(--muted-2); }
366
+
367
+ /* ---------- detail pane ---------- */
368
+ .detail-pane { min-width: 0; overflow: auto; padding: 26px 30px 48px; }
369
+ .detail-inner { max-width: 860px; animation: fadein 250ms var(--ease); }
370
+ @media (prefers-reduced-motion: reduce) { .detail-inner { animation: none; } }
371
+
372
+ .pane-back {
373
+ display: none; align-items: center; gap: 6px;
374
+ background: transparent; border: 1px solid var(--line-strong);
375
+ color: var(--basalt); padding: 7px 12px; cursor: pointer;
376
+ font: 500 0.8125rem/1.2 var(--font-ui); margin-bottom: 18px;
377
+ }
378
+
379
+ /* run detail */
380
+ .run-head { display: flex; align-items: center; gap: 14px; margin-bottom: 4px; flex-wrap: wrap; }
381
+ .run-id { font: 400 0.8125rem/1.3 var(--font-mono); color: var(--muted-2); overflow-wrap: anywhere; }
382
+ .detail-h2 {
383
+ margin: 6px 0 4px;
384
+ font: 700 1.75rem/1.2 var(--font-head);
385
+ letter-spacing: -0.02em; overflow-wrap: anywhere;
386
+ }
387
+ .detail-h2.mono { font-family: var(--font-mono); }
388
+ .detail-lead { margin: 0 0 16px; font: 400 0.875rem/1.5 var(--font-ui); color: var(--muted); }
389
+ .detail-lead.wide { margin-bottom: 20px; }
390
+
391
+ .factgrid {
392
+ display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
393
+ background: var(--white); border: 1px solid var(--line); margin-bottom: 16px;
394
+ }
395
+ .factgrid.wide { grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); margin-bottom: 0; }
396
+ .fact { padding: 13px 18px; border-right: 1px solid var(--line); min-width: 0; }
397
+ .factgrid.wide .fact { padding: 14px 18px; }
398
+ .fact:last-child { border-right: 0; }
399
+ .fact-label {
400
+ font: 600 0.6875rem/1.2 var(--font-head);
401
+ letter-spacing: 0.08em; text-transform: uppercase;
402
+ color: var(--muted-2); margin-bottom: 4px;
403
+ }
404
+ .fact-value { font: 400 0.9375rem/1.4 var(--font-ui); overflow-wrap: anywhere; }
405
+ .fact-value.mono { font-family: var(--font-mono); }
406
+ .fact-value.strong { font-weight: 500; font-family: var(--font-mono); }
407
+
408
+ .cmdbar {
409
+ background: var(--white); border: 1px solid var(--line);
410
+ padding: 13px 18px; margin-bottom: 16px;
411
+ display: flex; align-items: baseline; gap: 12px;
412
+ }
413
+ .cmd-label {
414
+ font: 600 0.6875rem/1.2 var(--font-head);
415
+ letter-spacing: 0.08em; text-transform: uppercase;
416
+ color: var(--muted-2); flex: none;
417
+ }
418
+ .cmd-code { font: 400 0.9375rem/1.55 var(--font-mono); color: var(--basalt); word-break: break-all; min-width: 0; }
419
+
420
+ .outbar { display: flex; align-items: center; gap: 14px; margin-bottom: 8px; flex-wrap: wrap; }
421
+ .out-label {
422
+ font: 600 0.6875rem/1.2 var(--font-head);
423
+ letter-spacing: 0.08em; text-transform: uppercase;
424
+ color: var(--muted-2); flex: 1;
425
+ }
426
+ .legend { display: flex; align-items: center; gap: 6px; font: 400 0.75rem/1.2 var(--font-ui); color: var(--muted); }
427
+ .legend-swatch { width: 8px; height: 2px; background: var(--muted-2); flex: none; }
428
+ .legend-swatch.err { background: var(--sunbird); }
429
+ .btn-copy {
430
+ display: flex; align-items: center; gap: 6px; flex: none;
431
+ background: transparent; border: 1px solid var(--line-strong);
432
+ color: var(--basalt); padding: 5px 10px; cursor: pointer;
433
+ font: 400 0.75rem/1.2 var(--font-ui);
434
+ }
435
+ .btn-copy:hover { border-color: var(--muted-2); }
436
+
437
+ .term {
438
+ background: var(--term-bg);
439
+ min-height: 320px; max-height: 480px; overflow: auto;
440
+ padding: 14px 0 16px;
441
+ }
442
+ .term-line {
443
+ display: flex; gap: 14px; padding: 1px 18px 1px 0;
444
+ font: 400 0.8125rem/1.7 var(--font-mono); color: var(--term-fg);
445
+ }
446
+ .term-line.err { color: var(--stderr); background: var(--stderr-bg); }
447
+ .term-n { color: var(--term-gutter); width: 40px; flex: none; text-align: right; user-select: none; }
448
+ .term-text { flex: 1; min-width: 0; white-space: pre-wrap; word-break: break-word; }
449
+ .term-empty { padding: 2px 18px 2px 54px; font: 400 0.8125rem/1.7 var(--font-mono); color: var(--term-gutter); }
450
+
451
+ /* server detail */
452
+ .srv-head { display: flex; align-items: center; gap: 14px; margin-bottom: 6px; flex-wrap: wrap; }
453
+ .srv-dot { width: 11px; height: 11px; flex: none; background: var(--line-strong); }
454
+ .srv-dot.online { background: var(--tea-text); }
455
+ .srv-dot.offline { background: var(--danger); }
456
+ .srv-dot.testing { background: var(--sunbird); animation: tick 1.8s ease-in-out infinite; }
457
+ .srv-head .detail-h2 { flex: 1; min-width: 0; margin: 0; }
458
+ .btn-plain {
459
+ background: transparent; border: 1px solid var(--line-strong);
460
+ color: var(--basalt); padding: 7px 13px; cursor: pointer;
461
+ font: 500 0.8125rem/1.2 var(--font-ui); flex: none;
462
+ }
463
+ .btn-plain:hover { border-color: var(--muted-2); }
464
+ .btn-plain[disabled] { opacity: 0.55; cursor: default; }
465
+ .btn-del {
466
+ background: transparent; border: 1px solid var(--line);
467
+ color: var(--danger); padding: 7px 13px; cursor: pointer;
468
+ font: 500 0.8125rem/1.2 var(--font-ui); flex: none;
469
+ }
470
+ .btn-del:hover { border-color: var(--danger); }
471
+
472
+ .alert {
473
+ display: flex; align-items: flex-start; gap: 10px;
474
+ background: var(--danger-bg); padding: 12px 16px; margin-bottom: 18px;
475
+ }
476
+ .alert svg { flex: none; margin-top: 3px; stroke: var(--danger); }
477
+ .alert-text { font: 400 0.875rem/1.5 var(--font-ui); color: var(--danger); overflow-wrap: anywhere; }
478
+
479
+ .record { background: var(--white); border: 1px solid var(--line); margin-bottom: 20px; }
480
+ .record-fp { border-top: 1px solid var(--line); padding: 14px 18px; }
481
+ .record-fp .fact-label { margin-bottom: 6px; }
482
+ .record-fp-value { font: 400 0.875rem/1.5 var(--font-mono); color: var(--muted); word-break: break-all; }
483
+
484
+ .section-rule { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; flex-wrap: wrap; }
485
+ .section-label {
486
+ font: 600 0.6875rem/1.2 var(--font-head);
487
+ letter-spacing: 0.08em; text-transform: uppercase;
488
+ color: var(--muted-2); flex: none; min-width: 0;
489
+ }
490
+ .rule { flex: 1; height: 1px; background: var(--line); }
491
+ .section-note { font: 400 0.8125rem/1.3 var(--font-ui); color: var(--muted-2); flex: none; }
492
+
493
+ /* edit card with layered Sunbird stack */
494
+ .editwrap { position: relative; margin-bottom: 26px; }
495
+ .editshadow {
496
+ position: absolute; inset: 10px -10px -10px 10px;
497
+ background: var(--sunbird);
498
+ clip-path: polygon(0 14px, 14px 0, 100% 0, 100% calc(100% - 14px), calc(100% - 14px) 100%, 0 100%);
499
+ }
500
+ .editcard {
501
+ position: relative;
502
+ background: var(--white); border: 1px solid var(--basalt);
503
+ padding: 20px 22px 22px;
504
+ clip-path: polygon(0 14px, 14px 0, 100% 0, 100% calc(100% - 14px), calc(100% - 14px) 100%, 0 100%);
505
+ }
506
+
507
+ .fieldrow { display: grid; gap: 14px; margin-bottom: 16px; }
508
+ .fieldrow.three { grid-template-columns: minmax(0, 1fr) 104px minmax(0, 1fr); }
509
+ .fieldrow.two { grid-template-columns: 148px minmax(0, 1fr); margin-bottom: 20px; }
510
+ .fieldrow.one { grid-template-columns: minmax(0, 1fr); }
511
+ .field { display: block; min-width: 0; }
512
+ .field-label { display: block; font: 500 0.8125rem/1.45 var(--font-ui); margin-bottom: 6px; }
513
+ .input {
514
+ width: 100%; border: 1px solid var(--line-strong); border-radius: 2px;
515
+ padding: 9px 12px; font: 400 0.9375rem/1.4 var(--font-mono);
516
+ color: var(--basalt); background: var(--white);
517
+ }
518
+ .select {
519
+ width: 100%; border: 1px solid var(--line-strong); border-radius: 2px;
520
+ padding: 9px 10px; background: var(--white);
521
+ font: 400 0.875rem/1.4 var(--font-ui); color: var(--basalt);
522
+ }
523
+
524
+ .hops-head { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
525
+ .hops-head .section-label { flex: 1; }
526
+ .btn-hop {
527
+ display: flex; align-items: center; gap: 6px; flex: none;
528
+ background: transparent; border: 1px solid var(--line-strong);
529
+ color: var(--basalt); padding: 4px 10px; cursor: pointer;
530
+ font: 500 0.75rem/1.2 var(--font-ui);
531
+ }
532
+ .btn-hop:hover { border-color: var(--muted-2); }
533
+ .btn-hop[disabled] { opacity: 0.5; cursor: default; }
534
+ .hop { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
535
+ .hop-n { font: 400 0.75rem/1 var(--font-mono); color: var(--muted-2); width: 16px; flex: none; }
536
+ .hop-select {
537
+ flex: 1; min-width: 0;
538
+ border: 1px solid var(--line-strong); border-radius: 2px;
539
+ padding: 8px 10px; background: var(--white);
540
+ font: 400 0.875rem/1.4 var(--font-mono); color: var(--basalt);
541
+ }
542
+ .hop-remove {
543
+ display: grid; place-items: center; width: 26px; height: 26px;
544
+ background: transparent; border: 1px solid var(--line); border-radius: 2px;
545
+ color: var(--muted); cursor: pointer; flex: none;
546
+ }
547
+ .hop-remove:hover { border-color: var(--muted-2); color: var(--basalt); }
548
+
549
+ .pathpreview {
550
+ background: var(--hillmist); border: 1px solid var(--line);
551
+ padding: 11px 13px; margin-top: 10px;
552
+ font: 400 0.9375rem/1.5 var(--font-mono); overflow-wrap: anywhere;
553
+ }
554
+ .pathpreview.bad { background: var(--danger-bg); border-color: var(--danger-bg); color: var(--danger); }
555
+
556
+ .testbox {
557
+ display: flex; align-items: center; gap: 10px; margin-top: 16px;
558
+ padding: 11px 13px; background: var(--hillmist); color: var(--muted);
559
+ font: 400 0.875rem/1.45 var(--font-ui); overflow-wrap: anywhere;
560
+ }
561
+ .testbox.ok { background: var(--ok-bg); color: var(--tea-text); }
562
+ .testbox.fail { background: var(--danger-bg); color: var(--danger); }
563
+
564
+ .form-error {
565
+ display: flex; align-items: flex-start; gap: 10px; margin-top: 16px;
566
+ padding: 11px 13px; background: var(--danger-bg); color: var(--danger);
567
+ font: 400 0.875rem/1.45 var(--font-ui); overflow-wrap: anywhere;
568
+ }
569
+
570
+ .editactions { display: flex; align-items: center; gap: 10px; margin-top: 20px; flex-wrap: wrap; }
571
+ .editactions .spacer { flex: 1; }
572
+ .btn-test-conn {
573
+ display: flex; align-items: center; gap: 8px; flex: none;
574
+ background: transparent; border: 1px solid var(--line-strong);
575
+ color: var(--basalt); padding: 9px 14px; cursor: pointer;
576
+ font: 500 0.875rem/1.2 var(--font-ui);
577
+ }
578
+ .btn-test-conn:hover { border-color: var(--muted-2); }
579
+ .btn-test-conn[disabled] { opacity: 0.55; cursor: default; }
580
+ .btn-ghost {
581
+ background: transparent; border: 0; color: var(--muted);
582
+ padding: 9px 12px; cursor: pointer;
583
+ font: 500 0.875rem/1.2 var(--font-ui); flex: none;
584
+ }
585
+ .btn-ghost:hover { color: var(--basalt); }
586
+ .btn-primary {
587
+ background: var(--tea); border: 0; color: var(--on-tea);
588
+ padding: 10px 18px; cursor: pointer;
589
+ font: 600 0.875rem/1.2 var(--font-ui); flex: none;
590
+ transition: background 120ms var(--ease);
591
+ }
592
+ .btn-primary:hover { background: var(--tea-dark); }
593
+ .btn-primary[disabled] { opacity: 0.6; cursor: default; }
594
+ .btn-outline {
595
+ background: transparent; border: 1px solid var(--line-strong);
596
+ color: var(--basalt); padding: 7px 13px; cursor: pointer;
597
+ font: 500 0.8125rem/1.2 var(--font-ui); flex: none;
598
+ }
599
+ .btn-outline:hover { border-color: var(--muted-2); }
600
+
601
+ .runs-row {
602
+ display: flex; align-items: center; gap: 12px; width: 100%; text-align: left;
603
+ background: var(--white); border: 1px solid var(--line);
604
+ padding: 11px 16px; margin-bottom: 8px; cursor: pointer;
605
+ font: inherit; color: inherit;
606
+ }
607
+ .runs-row:hover { border-color: var(--line-strong); }
608
+ .runs-row-cmd {
609
+ flex: 1; min-width: 0;
610
+ font: 400 0.8125rem/1.4 var(--font-mono); color: var(--basalt);
611
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
612
+ }
613
+ .runs-row-rel { font: 400 0.75rem/1.3 var(--font-ui); color: var(--muted-2); flex: none; }
614
+ .runs-none { font: 400 0.875rem/1.5 var(--font-ui); color: var(--muted-2); }
615
+
616
+ /* empty state */
617
+ .empty-state { display: grid; place-items: center; min-height: 480px; text-align: center; }
618
+ .empty-zigzag { margin-bottom: 18px; }
619
+ .empty-zigzag path { stroke: var(--sunbird); }
620
+ .empty-title { margin: 0 0 8px; font: 600 1.375rem/1.3 var(--font-head); }
621
+ .empty-body { margin: 0 auto; max-width: 400px; font: 400 1rem/1.6 var(--font-ui); color: var(--muted); }
622
+
623
+ /* ---------- overlays ----------
624
+ Centred by the wrapper, never by a transform: the `pop` keyframe ends on
625
+ `transform: none`, which would cancel a translate-based centring and throw
626
+ the panel off-screen. */
627
+ [hidden] { display: none !important; }
628
+
629
+ .overlay { position: fixed; inset: 0; display: flex; }
630
+ .overlay-center { z-index: 50; align-items: center; justify-content: center; padding: 16px; }
631
+ .overlay-top { z-index: 60; align-items: flex-start; justify-content: center; padding: 14vh 16px 16px; }
632
+ .scrim { position: absolute; inset: 0; background: var(--scrim); }
633
+
634
+ .dialog {
635
+ position: relative; width: min(404px, 100%);
636
+ max-height: 100%; overflow: auto;
637
+ background: var(--white); box-shadow: var(--shadow);
638
+ animation: pop 140ms var(--ease);
639
+ }
640
+ .dialog-body { padding: 26px 26px 18px; }
641
+ .dialog-title { margin: 0 0 8px; font: 600 1.375rem/1.3 var(--font-head); overflow-wrap: anywhere; }
642
+ .dialog-text { margin: 0; font: 400 0.9375rem/1.55 var(--font-ui); color: var(--muted); }
643
+ .dialog-actions { display: flex; justify-content: flex-end; gap: 10px; padding: 0 26px 24px; flex-wrap: wrap; }
644
+ .btn-danger {
645
+ background: var(--danger-fill); border: 0; color: #FFFFFF;
646
+ padding: 10px 16px; cursor: pointer;
647
+ font: 600 0.875rem/1.2 var(--font-ui); flex: none;
648
+ }
649
+
650
+ .palette {
651
+ position: relative; width: min(576px, 100%);
652
+ max-height: 100%; display: flex; flex-direction: column;
653
+ background: var(--white); box-shadow: var(--shadow);
654
+ animation: pop 140ms var(--ease);
655
+ }
656
+ .palette-head { display: flex; align-items: center; gap: 12px; padding: 18px 22px; border-bottom: 1px solid var(--line); flex: none; }
657
+ .palette-head svg { flex: none; stroke: var(--muted-2); }
658
+ .palette-input {
659
+ flex: 1; min-width: 0; border: 0; outline: none; background: transparent;
660
+ font: 400 1.0625rem/1.4 var(--font-ui); color: var(--basalt);
661
+ }
662
+ .palette-esc { font: 500 0.75rem/1 var(--font-mono); color: var(--muted-2); flex: none; }
663
+ .palette-list { max-height: min(340px, 50vh); overflow: auto; padding: 8px; flex: 1; }
664
+ .pal-row {
665
+ display: flex; align-items: center; gap: 12px; width: 100%;
666
+ padding: 9px 12px; border: 0; cursor: pointer; background: transparent;
667
+ font: inherit; color: inherit; box-shadow: none;
668
+ }
669
+ .pal-row.active { background: var(--ok-bg); box-shadow: inset 3px 0 0 var(--tea-text); }
670
+ .pal-kind {
671
+ font: 600 0.6875rem/1.2 var(--font-head);
672
+ letter-spacing: 0.08em; text-transform: uppercase;
673
+ color: var(--muted-2); width: 52px; text-align: left; flex: none;
674
+ }
675
+ .pal-label {
676
+ flex: 1; min-width: 0; text-align: left;
677
+ font: 400 0.9375rem/1.4 var(--font-ui);
678
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
679
+ }
680
+ .pal-hint {
681
+ font: 400 0.8125rem/1.2 var(--font-mono); color: var(--muted-2); flex: none;
682
+ max-width: 45%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
683
+ }
684
+ .pal-empty { padding: 18px 12px; font: 400 0.875rem/1.5 var(--font-ui); color: var(--muted-2); text-align: center; }
685
+
686
+ .toasts {
687
+ position: fixed; right: 24px; bottom: 24px; z-index: 70;
688
+ display: flex; flex-direction: column; gap: 10px; align-items: flex-end;
689
+ max-width: calc(100vw - 48px);
690
+ }
691
+ .toast {
692
+ display: flex; align-items: center; gap: 10px;
693
+ background: var(--white); border: 1px solid var(--line);
694
+ box-shadow: var(--shadow); padding: 11px 13px;
695
+ min-width: 280px; max-width: min(420px, calc(100vw - 48px));
696
+ animation: pop 140ms var(--ease);
697
+ }
698
+ .toast-dot { width: 8px; height: 8px; flex: none; background: var(--muted-2); }
699
+ .toast-dot.ok { background: var(--tea); }
700
+ .toast-dot.fail { background: var(--danger); }
701
+ .toast-text { flex: 1; min-width: 0; font: 400 0.875rem/1.45 var(--font-ui); color: var(--basalt); overflow-wrap: anywhere; }
702
+ .toast-x {
703
+ display: grid; place-items: center; width: 22px; height: 22px;
704
+ background: transparent; border: 0; color: var(--muted-2); cursor: pointer; flex: none;
705
+ }
706
+ .toast-x:hover { color: var(--basalt); }
707
+
708
+ /* ---------- responsive ---------- */
709
+
710
+ /* narrower two-pane before collapsing */
711
+ @media (max-width: 1240px) { :root { --list-w: 360px; } }
712
+ @media (max-width: 1100px) { :root { --list-w: 320px; } .detail-pane { padding: 24px 22px 40px; } }
713
+
714
+ /* single column: panes swap, back button appears */
715
+ @media (max-width: 1000px) {
716
+ .body { grid-template-columns: minmax(0, 1fr); }
717
+ .list-pane { border-right: 0; }
718
+ .app[data-pane="list"] .detail-pane { display: none; }
719
+ .app[data-pane="detail"] .list-pane { display: none; }
720
+ .pane-back { display: flex; }
721
+ .detail-inner { max-width: none; }
722
+ }
723
+
724
+ /* header stacks: brand row, then full-width tabs */
725
+ @media (max-width: 900px) {
726
+ .topbar-inner { flex-wrap: wrap; gap: 0 16px; padding: 0 18px; }
727
+ .brand { order: 1; }
728
+ .topbar-spacer { order: 2; }
729
+ .topbar-right { order: 3; gap: 12px; }
730
+ .tabs { order: 4; width: 100%; gap: 0; border-top: 1px solid rgba(243, 246, 244, 0.12); }
731
+ .tab { flex: 1; justify-content: center; padding: 11px 8px; }
732
+ .conn-addr { display: none; }
733
+ }
734
+
735
+ @media (max-width: 680px) {
736
+ .palette-btn-label { display: none; }
737
+ .conn-label { display: none; }
738
+ .factgrid, .factgrid.wide { grid-template-columns: minmax(0, 1fr); }
739
+ .fact { border-right: 0; border-bottom: 1px solid var(--line); }
740
+ .fact:last-child { border-bottom: 0; }
741
+ .fieldrow.three, .fieldrow.two { grid-template-columns: minmax(0, 1fr); }
742
+ .cmdbar { flex-direction: column; gap: 6px; }
743
+ .editshadow { inset: 8px -6px -8px 8px; }
744
+ }
745
+
746
+ @media (max-width: 560px) {
747
+ .section-note { display: none; }
748
+ .topbar-inner { padding: 0 14px; }
749
+ .brand-sub { display: none; }
750
+ .list-head { padding: 16px 16px 12px; }
751
+ .list-filters { padding: 0 16px 12px; flex-wrap: wrap; }
752
+ .search-wrap { flex-basis: 100%; }
753
+ .import { padding: 12px 16px 16px; }
754
+ .row { padding: 12px 14px; }
755
+ .detail-pane { padding: 18px 16px 36px; }
756
+ .list-title { font-size: 1.5rem; }
757
+ .detail-h2 { font-size: 1.5rem; }
758
+ .term { min-height: 240px; max-height: 60vh; }
759
+ .term-n { width: 28px; }
760
+ .term-line { gap: 10px; padding-right: 12px; }
761
+ .toasts { right: 12px; bottom: 12px; left: 12px; align-items: stretch; max-width: none; }
762
+ .toast { min-width: 0; max-width: none; }
763
+ .dialog-actions { justify-content: stretch; }
764
+ .dialog-actions button { flex: 1; }
765
+ .srv-head .detail-h2 { flex-basis: 100%; order: -1; }
766
+ .empty-state { min-height: 320px; }
767
+ }
768
+
769
+ @media (max-width: 400px) {
770
+ .tab-label { display: none; }
771
+ .tab { gap: 6px; }
772
+ .agent-chip { max-width: 92px; }
773
+ }
774
+
775
+ /* ---------- theme toggle ---------- */
776
+ .theme-btn {
777
+ display: grid; place-items: center; flex: none;
778
+ width: 32px; height: 32px;
779
+ background: rgba(243, 246, 244, 0.08);
780
+ border: 1px solid rgba(243, 246, 244, 0.18);
781
+ color: rgba(243, 246, 244, 0.9);
782
+ cursor: pointer;
783
+ transition: background 120ms var(--ease);
784
+ }
785
+ .theme-btn:hover { background: rgba(243, 246, 244, 0.16); }
786
+ .theme-btn svg { display: none; }
787
+ /* show the icon for the theme you would switch *to* */
788
+ :root[data-theme="light"] .theme-icon-moon { display: block; }
789
+ :root[data-theme="dark"] .theme-icon-sun { display: block; }
790
+
791
+ /* ---------- reachability tallies (Servers) ---------- */
792
+ .tallies {
793
+ display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
794
+ padding: 0 22px 14px; flex: none;
795
+ }
796
+ .tally {
797
+ display: inline-flex; align-items: center; gap: 7px;
798
+ background: transparent; border: 1px solid var(--line);
799
+ padding: 5px 10px; cursor: pointer;
800
+ font: 500 0.75rem/1.35 var(--font-ui); color: var(--muted);
801
+ transition: border-color 120ms var(--ease), background 120ms var(--ease);
802
+ }
803
+ .tally:hover { border-color: var(--line-strong); color: var(--basalt); }
804
+ .tally[aria-pressed="true"] { border-color: var(--tea-text); background: var(--ok-bg); color: var(--tea-text); }
805
+ .tally-dot { width: 7px; height: 7px; flex: none; }
806
+ .tally-dot.online { background: var(--tea-text); }
807
+ .tally-dot.offline { background: var(--danger); }
808
+ .tally-dot.untested { background: var(--line-strong); }
809
+ .tally-dot.testing { background: var(--sunbird); animation: tick 1.8s ease-in-out infinite; }
810
+ .tally-n { font-family: var(--font-mono); font-weight: 500; color: var(--basalt); }
811
+ .tally[aria-pressed="true"] .tally-n { color: var(--tea-text); }
812
+
813
+ /* ---------- list footer (pagination) ---------- */
814
+ .list-more {
815
+ display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
816
+ padding: 16px 20px 22px;
817
+ }
818
+ .list-more-note { font: 400 0.75rem/1.4 var(--font-ui); color: var(--muted-2); }
819
+
820
+ /* ---------- output panel meta ---------- */
821
+ .out-size { font: 400 0.75rem/1.2 var(--font-mono); color: var(--muted-2); flex: none; }
822
+ .term-notice {
823
+ display: flex; align-items: flex-start; gap: 8px;
824
+ background: var(--testing-bg); color: var(--testing-fg);
825
+ padding: 9px 13px; margin-bottom: 8px;
826
+ font: 400 0.8125rem/1.45 var(--font-ui);
827
+ }
828
+ .term-notice svg { flex: none; margin-top: 2px; }
829
+ .term-loading {
830
+ padding: 2px 18px 2px 54px;
831
+ font: 400 0.8125rem/1.7 var(--font-mono); color: var(--term-gutter);
832
+ }
833
+ .srv-checked { font: 400 0.75rem/1.3 var(--font-ui); color: var(--muted-2); flex: none; }
834
+
835
+ @media (max-width: 560px) {
836
+ .tallies { padding: 0 16px 12px; }
837
+ .list-more { padding: 14px 14px 20px; }
838
+ }