@takodotid/circuit 0.20.0 → 0.22.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.
@@ -1,305 +1,576 @@
1
- /* Circuit Studio's look, the documentation site's own: Inter for text, Newsreader for headings, terracotta for the brand, and VitePress's neutrals. Colors are tokens, redefined for a dark screen; then the page, the tables and the graph. */
1
+ /* The documentation site's cobalt, white and highlighter yellow, set in Special Gothic, at working density. */
2
+
3
+ @font-face {
4
+ font-family: "Special Gothic";
5
+ font-style: normal;
6
+ font-weight: 400 700;
7
+ font-stretch: 75% 125%;
8
+ font-display: swap;
9
+ src: url("special-gothic-latin-ext.woff2") format("woff2");
10
+ unicode-range:
11
+ U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF,
12
+ U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
13
+ }
14
+
15
+ @font-face {
16
+ font-family: "Special Gothic";
17
+ font-style: normal;
18
+ font-weight: 400 700;
19
+ font-stretch: 75% 125%;
20
+ font-display: swap;
21
+ src: url("special-gothic-latin.woff2") format("woff2");
22
+ unicode-range:
23
+ U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191,
24
+ U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
25
+ }
26
+
2
27
  :root {
3
- --bg: #f6f6f7;
28
+ /* The shell: the same in both themes. */
29
+ --cobalt: #0a47b8;
30
+ --cobalt-deep: #08337f;
31
+ --navy: #0a1a36;
32
+ --yellow: #f8e347;
33
+ --yellow-deep: #e8cd1c;
34
+ --on-cobalt: #ffffff;
35
+ --on-cobalt-soft: #c9d7f5;
36
+
37
+ /* The page. */
38
+ --bg: #eff2f9;
4
39
  --surface: #ffffff;
5
- --line: #e2e2e3;
6
- --text: #3c3c43;
7
- --muted: #67676c;
8
- --edge: #929295;
9
- --accent: #a8432b;
10
- --accent-strong: #b4492f;
11
- --on-accent: #ffffff;
12
- --error: #b8272c;
13
- --error-strong: #b8272c;
14
- --warning: #915930;
15
- --warning-strong: #9f6a00;
16
- --ok: #18794e;
17
- --segment: rgba(180, 73, 47, 0.08);
18
- --font: "Inter", ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
19
- --serif: "Newsreader", "Iowan Old Style", "Palatino Linotype", Georgia, serif;
20
- --mono: ui-monospace, "Menlo", "Monaco", "Consolas", "Liberation Mono", "Courier New", monospace;
40
+ --surface-raised: #f4f6fb;
41
+ --line: #d3d9e7;
42
+ --head: #e1e7f3;
43
+ --hover: rgba(10, 71, 184, 0.045);
44
+ --text: #11141b;
45
+ --muted: #49536a;
46
+ --edge: #7b86a0;
47
+ --accent: #0a47b8;
48
+ --accent-strong: #f8e347;
49
+ --on-accent: #11141b;
50
+ --selected: #fff7c2;
51
+ --error: #c0262c;
52
+ --error-strong: #c0262c;
53
+ --warning: #b35a00;
54
+ --warning-strong: #f0a030;
55
+ --ok: #11733b;
56
+ --segment: rgba(248, 227, 71, 0.32);
57
+ --dots: rgba(10, 71, 184, 0.14);
58
+ --heading-dots: var(--cobalt);
59
+
60
+ --font:
61
+ "Special Gothic", "Segoe UI", system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
62
+ --display: "Special Gothic", "Segoe UI", system-ui, sans-serif;
63
+ --mono: ui-monospace, "Cascadia Code", "SFMono-Regular", Menlo, Consolas, monospace;
21
64
  }
65
+
22
66
  @media (prefers-color-scheme: dark) {
23
67
  :root {
24
- --bg: #161618;
25
- --surface: #1b1b1f;
26
- --line: #2e2e32;
27
- --text: #dfdfd6;
28
- --muted: #98989f;
29
- --edge: #6a6a71;
30
- --accent: #e8866b;
31
- --accent-strong: #b4492f;
32
- --error: #f66f81;
33
- --error-strong: #b62a3c;
34
- --warning: #f9b44e;
35
- --warning-strong: #a46a0a;
36
- --ok: #3dd68c;
37
- --segment: rgba(232, 134, 107, 0.12);
68
+ --bg: #0b1122;
69
+ --surface: #121a30;
70
+ --surface-raised: #182241;
71
+ --line: #26314d;
72
+ --head: #26325a;
73
+ --hover: rgba(156, 185, 255, 0.05);
74
+ --text: #f1f4fb;
75
+ --muted: #a9b4cc;
76
+ --edge: #7c89a8;
77
+ --accent: #9cb9ff;
78
+ --on-accent: #11141b;
79
+ --selected: #3a3510;
80
+ --error: #ff8086;
81
+ --error-strong: #c0262c;
82
+ --warning: #ffad4f;
83
+ --warning-strong: #e08a1e;
84
+ --ok: #5fd38f;
85
+ --segment: rgba(248, 227, 71, 0.16);
86
+ --dots: rgba(156, 185, 255, 0.12);
38
87
  }
39
88
  }
89
+
40
90
  * {
41
91
  box-sizing: border-box;
42
92
  }
93
+
43
94
  html,
44
95
  body {
45
96
  margin: 0;
46
97
  height: 100%;
47
98
  background: var(--bg);
48
99
  color: var(--text);
49
- font: 14px/1.45 var(--font);
100
+ font: 15px/1.5 var(--font);
101
+ scrollbar-color: var(--edge) transparent;
50
102
  }
103
+
51
104
  body {
52
105
  display: flex;
53
106
  flex-direction: column;
54
107
  }
108
+
109
+ ::selection {
110
+ color: #11141b;
111
+ background: var(--yellow);
112
+ }
113
+
114
+ :focus-visible {
115
+ outline: 3px solid var(--accent);
116
+ outline-offset: 2px;
117
+ }
118
+
119
+ /* On the cobalt rail a cobalt ring would vanish, so it is yellow there. */
120
+ header :focus-visible {
121
+ outline-color: var(--yellow);
122
+ }
123
+
55
124
  button {
56
- font: inherit;
57
- color: inherit;
125
+ min-height: 36px;
126
+ padding: 6px 12px;
127
+ border: 1.5px solid var(--edge);
128
+ border-radius: 2px;
58
129
  background: var(--surface);
59
- border: 1px solid var(--line);
60
- border-radius: 6px;
61
- padding: 4px 10px;
130
+ color: inherit;
131
+ font: inherit;
132
+ font-weight: 600;
62
133
  cursor: pointer;
63
134
  }
135
+
64
136
  button:hover {
65
137
  border-color: var(--accent);
138
+ color: var(--accent);
66
139
  }
140
+
67
141
  button[aria-pressed="true"] {
68
- background: var(--accent-strong);
69
- border-color: var(--accent-strong);
70
- color: var(--on-accent);
142
+ border-color: var(--cobalt);
143
+ background: var(--cobalt);
144
+ color: #ffffff;
145
+ }
146
+
147
+ input,
148
+ select,
149
+ button {
150
+ box-sizing: border-box;
151
+ }
152
+
153
+ code {
154
+ font-family: var(--mono);
155
+ font-size: 0.92em;
156
+ }
157
+
158
+ a {
159
+ color: var(--accent);
160
+ font-weight: 600;
161
+ text-decoration: underline dotted 1.5px;
162
+ text-underline-offset: 3px;
163
+ cursor: pointer;
164
+ }
165
+
166
+ a:hover {
167
+ text-decoration-style: solid;
168
+ }
169
+
170
+ .muted {
171
+ color: var(--muted);
71
172
  }
173
+
174
+ /* The rail: the wordmark, the views and the search, on cobalt. */
175
+
72
176
  header {
73
177
  display: flex;
74
178
  flex-wrap: wrap;
75
- align-items: center;
76
- gap: 8px 16px;
77
- padding: 10px 16px;
78
- background: var(--surface);
79
- border-bottom: 1px solid var(--line);
179
+ align-items: stretch;
180
+ gap: 0;
181
+ padding: 0;
182
+ background: var(--cobalt);
183
+ color: var(--on-cobalt);
80
184
  }
81
- /* The wordmark is Circuit's own; Studio is set apart from it, as the part of Circuit this is. */
185
+
82
186
  header .brand {
83
187
  display: flex;
84
- align-items: baseline;
85
- gap: 8px;
188
+ align-items: center;
189
+ gap: 10px;
190
+ padding: 0 18px;
191
+ color: inherit;
192
+ text-decoration: none;
193
+ }
194
+
195
+ header .brand:hover .wordmark {
196
+ color: var(--yellow);
86
197
  }
198
+
87
199
  header .wordmark {
88
- font-family: var(--serif);
89
- font-size: 22px;
90
- font-weight: 400;
91
- letter-spacing: -0.01em;
200
+ font-family: var(--display);
201
+ font-size: 21px;
202
+ font-weight: 700;
203
+ font-stretch: 125%;
204
+ letter-spacing: 0.04em;
205
+ text-transform: uppercase;
92
206
  }
207
+
93
208
  header .product {
94
- font-size: 13px;
95
- font-weight: 500;
96
- color: var(--accent);
97
- padding-left: 8px;
98
- border-left: 1px solid var(--line);
99
- }
100
- code {
101
- font-family: var(--mono);
102
- font-size: 0.92em;
209
+ padding: 2px 7px;
210
+ border-radius: 2px;
211
+ background: var(--yellow);
212
+ color: #0a1a36;
213
+ font-size: 11px;
214
+ font-weight: 700;
215
+ font-stretch: 118%;
216
+ letter-spacing: 0.1em;
217
+ text-transform: uppercase;
103
218
  }
219
+
104
220
  nav,
105
221
  .actions {
106
222
  display: flex;
107
223
  flex-wrap: wrap;
108
224
  gap: 6px;
109
225
  }
226
+
227
+ header > nav {
228
+ gap: 0;
229
+ padding-inline: 6px;
230
+ }
231
+
232
+ header > nav button {
233
+ position: relative;
234
+ min-height: 52px;
235
+ padding: 0 11px;
236
+ border: 0;
237
+ border-radius: 0;
238
+ background: transparent;
239
+ color: var(--on-cobalt-soft);
240
+ font-size: 12.5px;
241
+ font-weight: 700;
242
+ font-stretch: 112%;
243
+ letter-spacing: 0.06em;
244
+ text-transform: uppercase;
245
+ }
246
+
247
+ header > nav button:hover {
248
+ color: #ffffff;
249
+ background: rgba(255, 255, 255, 0.08);
250
+ }
251
+
252
+ header > nav button[aria-pressed="true"] {
253
+ color: #ffffff;
254
+ background: transparent;
255
+ }
256
+
257
+ header > nav button[aria-pressed="true"]::after {
258
+ content: "";
259
+ position: absolute;
260
+ right: 9px;
261
+ bottom: 0;
262
+ left: 9px;
263
+ height: 4px;
264
+ background: var(--yellow);
265
+ animation: bar 0.28s cubic-bezier(0.16, 1, 0.3, 1);
266
+ }
267
+
268
+ /* The bar under the view or tab just chosen grows out from its middle. */
269
+ @keyframes bar {
270
+ from {
271
+ transform: scaleX(0);
272
+ }
273
+ }
274
+
110
275
  .count {
111
- opacity: 0.7;
112
- margin-left: 4px;
113
- font-size: 12px;
276
+ margin-left: 6px;
277
+ padding: 0 5px;
278
+ border-radius: 2px;
279
+ background: var(--yellow);
280
+ color: #0a1a36;
281
+ font-size: 11px;
282
+ letter-spacing: 0;
283
+ }
284
+
285
+ .count:empty {
286
+ display: none;
114
287
  }
288
+
115
289
  header input[type="search"] {
116
- font: inherit;
117
- color: inherit;
118
- background: var(--bg);
119
- border: 1px solid var(--line);
120
- border-radius: 6px;
121
- padding: 4px 10px;
122
- width: 220px;
290
+ width: 230px;
123
291
  max-width: 100%;
292
+ min-height: 36px;
293
+ margin: 8px 16px 8px auto;
294
+ padding: 4px 12px;
295
+ border: 1.5px solid rgba(201, 215, 245, 0.7);
296
+ border-radius: 2px;
297
+ background: rgba(8, 28, 64, 0.35);
298
+ color: #ffffff;
299
+ font: inherit;
124
300
  }
125
- header input[type="search"]:focus {
126
- outline: 2px solid var(--accent);
127
- outline-offset: -1px;
301
+
302
+ header input[type="search"]::placeholder {
303
+ color: var(--on-cobalt-soft);
128
304
  }
129
- a {
130
- color: var(--accent);
131
- cursor: pointer;
132
- text-decoration: none;
305
+
306
+ header input[type="search"]:focus {
307
+ border-color: #ffffff;
308
+ outline: 3px solid var(--yellow);
309
+ outline-offset: 1px;
133
310
  }
134
- a:hover {
135
- text-decoration: underline;
311
+
312
+ /* The status rail: the network's health in counts, each with a mark as well as a colour. */
313
+
314
+ .status-rail {
315
+ order: 10;
316
+ display: flex;
317
+ flex: 1 0 100%;
318
+ align-items: center;
319
+ min-height: 38px;
320
+ padding: 0 18px;
321
+ background: var(--surface);
322
+ border-bottom: 1px solid var(--line);
323
+ color: var(--text);
136
324
  }
137
- .muted {
325
+
326
+ .status-rail .summary {
327
+ display: flex;
328
+ flex-wrap: wrap;
329
+ align-items: center;
138
330
  color: var(--muted);
331
+ font-size: 13px;
139
332
  }
140
- header .summary {
141
- color: var(--muted);
333
+
334
+ .summary-item {
335
+ display: inline-flex;
336
+ align-items: center;
337
+ min-height: 24px;
338
+ padding: 0 12px;
339
+ border-left: 1px solid var(--line);
340
+ color: var(--text);
142
341
  font-size: 13px;
342
+ font-weight: 700;
143
343
  }
144
- header .live {
145
- margin-left: auto;
344
+
345
+ .summary-item:first-child {
346
+ padding-left: 0;
347
+ border-left: 0;
348
+ }
349
+
350
+ .summary-item::before {
351
+ content: "";
352
+ width: 8px;
353
+ height: 8px;
354
+ margin-right: 7px;
355
+ border: 1.5px solid currentColor;
356
+ border-radius: 50%;
357
+ }
358
+
359
+ .summary-item.error {
360
+ color: var(--error);
361
+ }
362
+
363
+ .summary-item.warning,
364
+ .summary-item.changed {
365
+ color: var(--warning);
366
+ }
367
+
368
+ .summary-item.error::before,
369
+ .summary-item.warning::before,
370
+ .summary-item.changed::before {
371
+ background: currentColor;
372
+ }
373
+
374
+ .summary-item.changed::before {
375
+ border-radius: 1px;
376
+ }
377
+
378
+ .summary-item.quiet {
146
379
  color: var(--muted);
147
- font-size: 12px;
380
+ font-weight: 600;
381
+ }
382
+
383
+ .status-rail .live {
384
+ display: inline-flex;
385
+ align-items: center;
386
+ margin-left: auto;
387
+ white-space: nowrap;
388
+ color: var(--text);
389
+ font-size: 13px;
390
+ font-weight: 700;
391
+ text-transform: capitalize;
148
392
  }
149
- header .live::before {
393
+
394
+ .status-rail .live::before {
150
395
  content: "";
151
396
  display: inline-block;
152
397
  width: 8px;
153
398
  height: 8px;
399
+ margin-right: 7px;
154
400
  border-radius: 50%;
155
401
  background: var(--warning);
156
- margin-right: 6px;
157
402
  }
158
- header .live.on::before {
403
+
404
+ .status-rail .live.on::before {
159
405
  background: var(--ok);
160
406
  }
407
+
408
+ /* When a changed config arrives, the live mark beats once in yellow. */
409
+ .status-rail .live.beat::before {
410
+ animation: beat 0.7s cubic-bezier(0.16, 1, 0.3, 1);
411
+ }
412
+
413
+ @keyframes beat {
414
+ 30% {
415
+ background: var(--yellow);
416
+ transform: scale(1.9);
417
+ }
418
+ }
419
+
161
420
  .banner {
162
421
  margin: 0;
163
- padding: 10px 16px;
422
+ padding: 10px 18px;
164
423
  background: var(--error-strong);
165
- color: var(--on-accent);
424
+ color: #ffffff;
166
425
  white-space: pre-wrap;
167
- font: 12px/1.4 var(--mono);
426
+ font: 12px/1.45 var(--mono);
168
427
  max-height: 30vh;
169
428
  overflow: auto;
170
429
  }
430
+
171
431
  main {
172
432
  flex: 1;
173
433
  display: flex;
174
434
  flex-direction: column;
175
435
  min-height: 0;
176
436
  }
437
+
177
438
  .view {
178
439
  flex: 1;
179
440
  display: flex;
180
441
  flex-direction: column;
181
442
  min-height: 0;
182
443
  }
444
+
183
445
  .view[hidden] {
184
446
  display: none;
185
447
  }
448
+
449
+ /* The graph's toolbar: the layers as one segmented control, the actions to the right. */
450
+
186
451
  .toolbar {
187
452
  display: flex;
188
453
  flex-wrap: wrap;
189
454
  align-items: center;
455
+ justify-content: space-between;
190
456
  gap: 8px 16px;
191
- padding: 8px 16px;
457
+ min-height: 52px;
458
+ padding: 8px 18px;
192
459
  background: var(--surface);
193
460
  border-bottom: 1px solid var(--line);
194
461
  }
195
- .stage {
196
- flex: 1;
197
- display: flex;
198
- min-height: 0;
462
+
463
+ .toolbar nav {
464
+ gap: 0;
465
+ border: 1.5px solid var(--text);
466
+ border-radius: 2px;
199
467
  }
200
- .tables {
201
- flex: 1;
202
- overflow: auto;
203
- padding: 16px 24px 48px;
468
+
469
+ .toolbar nav button {
470
+ min-height: 32px;
471
+ padding: 4px 12px;
472
+ border: 0;
473
+ border-radius: 0;
474
+ background: transparent;
475
+ font-size: 13px;
204
476
  }
205
- .tables h2 {
206
- font-family: var(--serif);
207
- font-size: 30px;
208
- font-weight: 400;
209
- letter-spacing: -0.01em;
210
- line-height: 1.25;
211
- margin: 4px 0 8px;
212
- display: flex;
213
- align-items: center;
214
- flex-wrap: wrap;
215
- gap: 8px;
477
+
478
+ .toolbar nav button + button {
479
+ border-left: 1.5px solid var(--line);
216
480
  }
217
- .tables h3 {
218
- font-size: 14px;
219
- margin: 24px 0 8px;
481
+
482
+ .toolbar nav button[aria-pressed="true"] {
483
+ background: var(--cobalt);
484
+ color: #ffffff;
220
485
  }
221
- .tables h4 {
222
- font-size: 13px;
223
- margin: 16px 0 6px;
224
- font-family: var(--mono);
225
- font-weight: 600;
486
+
487
+ .toolbar nav button .count,
488
+ .toolbar nav button small {
489
+ background: none;
490
+ color: inherit;
491
+ opacity: 0.7;
226
492
  }
227
- .tables p {
228
- margin: 4px 0 8px;
493
+
494
+ .toolbar .actions {
495
+ align-items: center;
496
+ gap: 6px;
229
497
  }
230
- .tables .crumbs {
231
- margin: 0;
498
+
499
+ .toolbar .actions button,
500
+ .menu summary {
501
+ min-height: 34px;
502
+ padding: 4px 12px;
232
503
  font-size: 13px;
233
504
  }
234
- .tables .tabs {
235
- margin: 14px 0 6px;
505
+
506
+ .menu {
507
+ position: relative;
236
508
  }
237
- .tables .findings {
509
+
510
+ .menu summary {
511
+ display: flex;
512
+ align-items: center;
513
+ gap: 8px;
514
+ border: 1.5px solid var(--edge);
515
+ border-radius: 2px;
516
+ background: var(--surface);
517
+ font-weight: 600;
238
518
  list-style: none;
239
- padding: 0;
240
- margin: 0;
519
+ cursor: pointer;
241
520
  }
242
- .tables .findings li {
243
- padding: 3px 0;
521
+
522
+ .menu summary::-webkit-details-marker {
523
+ display: none;
244
524
  }
245
- table.data {
246
- border-collapse: separate;
247
- border-spacing: 0;
248
- width: 100%;
249
- font-size: 13px;
525
+
526
+ .menu summary::after {
527
+ content: "";
528
+ width: 7px;
529
+ height: 7px;
530
+ margin-top: -4px;
531
+ border-right: 1.5px solid currentColor;
532
+ border-bottom: 1.5px solid currentColor;
533
+ transform: rotate(45deg);
534
+ }
535
+
536
+ .menu summary:hover {
537
+ border-color: var(--accent);
538
+ color: var(--accent);
539
+ }
540
+
541
+ .menu-items {
542
+ position: absolute;
543
+ top: calc(100% + 4px);
544
+ right: 0;
545
+ z-index: 5;
546
+ display: grid;
547
+ min-width: 120px;
548
+ padding: 4px;
549
+ border: 1.5px solid var(--text);
550
+ border-radius: 2px;
250
551
  background: var(--surface);
251
- border: 1px solid var(--line);
252
- border-radius: 8px;
552
+ box-shadow: 0 8px 20px rgba(10, 26, 54, 0.18);
253
553
  }
254
- table.data th,
255
- table.data td {
554
+
555
+ .menu-items button {
556
+ justify-content: flex-start;
557
+ border: 0;
256
558
  text-align: left;
257
- padding: 6px 10px;
258
- border-bottom: 1px solid var(--line);
259
- vertical-align: top;
260
- overflow-wrap: break-word;
261
- }
262
- table.data tr:last-child > td,
263
- table.data tr:last-child > th {
264
- border-bottom: 0;
265
559
  }
266
- table.data thead th {
267
- color: var(--muted);
268
- font-weight: 600;
269
- font-size: 12px;
270
- white-space: nowrap;
271
- }
272
- table.data th[title] {
273
- cursor: help;
274
- text-decoration: underline dotted;
275
- text-underline-offset: 3px;
276
- }
277
- table.data tr.muted td {
278
- color: var(--muted);
279
- }
280
- table.settings {
281
- width: auto;
282
- min-width: min(560px, 100%);
283
- }
284
- table.settings > tbody > tr > th {
285
- width: 1%;
286
- white-space: nowrap;
287
- color: var(--muted);
288
- font-weight: 500;
289
- }
290
- table.data table.data {
291
- margin: 0;
292
- }
293
- pre.code {
294
- margin: 0;
295
- font: 12px/1.5 var(--mono);
296
- background: var(--surface);
297
- border: 1px solid var(--line);
298
- border-radius: 8px;
299
- padding: 12px;
300
- overflow: auto;
301
- white-space: pre;
560
+
561
+ /* The drawing board. */
562
+
563
+ .stage {
564
+ position: relative;
565
+ flex: 1;
566
+ display: flex;
567
+ min-height: 0;
568
+ overflow: hidden;
569
+ background-color: var(--bg);
570
+ background-image: radial-gradient(circle, var(--dots) 1.2px, transparent 1.6px);
571
+ background-size: 24px 24px;
302
572
  }
573
+
303
574
  svg.canvas {
304
575
  flex: 1;
305
576
  min-width: 0;
@@ -308,258 +579,622 @@ svg.canvas {
308
579
  touch-action: none;
309
580
  user-select: none;
310
581
  }
582
+
311
583
  svg.canvas.panning {
312
584
  cursor: grabbing;
313
585
  }
586
+
587
+ .edge path {
588
+ fill: none;
589
+ stroke: var(--edge);
590
+ stroke-width: 2;
591
+ transition:
592
+ stroke 0.2s,
593
+ stroke-width 0.2s;
594
+ }
595
+
596
+ /* Lighting one part dims the rest gently, so the eye follows what changed. */
597
+ .edge,
598
+ .node {
599
+ transition: opacity 0.25s ease-out;
600
+ }
601
+
602
+ /* Dots travelling a cable both ends declare: traffic where the link works. On a lit cable they turn to the highlighter. */
603
+ .edge .signal {
604
+ fill: var(--accent);
605
+ pointer-events: none;
606
+ }
607
+
608
+ .edge.lit .signal,
609
+ .edge.selected .signal {
610
+ r: 4.5px;
611
+ fill: var(--yellow);
612
+ stroke: var(--navy);
613
+ stroke-width: 1.5;
614
+ }
615
+
616
+ .edge.added .signal {
617
+ fill: var(--ok);
618
+ }
619
+
620
+ .edge text {
621
+ font-size: 12.5px;
622
+ fill: var(--muted);
623
+ paint-order: stroke;
624
+ stroke: var(--bg);
625
+ stroke-width: 5px;
626
+ stroke-linejoin: round;
627
+ }
628
+
629
+ .edge .hit {
630
+ stroke: transparent;
631
+ stroke-width: 12;
632
+ cursor: pointer;
633
+ }
634
+
635
+ .edge.one-sided path:not(.hit) {
636
+ stroke: var(--warning);
637
+ stroke-width: 3;
638
+ stroke-dasharray: 4 4;
639
+ }
640
+
641
+ .edge.selected path:not(.hit),
642
+ .edge.lit path:not(.hit) {
643
+ stroke: var(--accent);
644
+ stroke-width: 4;
645
+ }
646
+
647
+ .edge.selected text,
648
+ .edge.lit text {
649
+ fill: var(--text);
650
+ }
651
+
652
+ .edge.added path:not(.hit) {
653
+ stroke: var(--ok);
654
+ stroke-width: 4;
655
+ }
656
+
657
+ .edge.gone path:not(.hit) {
658
+ stroke: var(--error);
659
+ stroke-width: 4;
660
+ stroke-dasharray: 10 5;
661
+ }
662
+
663
+ .node {
664
+ cursor: pointer;
665
+ }
666
+
667
+ .node > rect {
668
+ fill: var(--surface);
669
+ stroke: var(--text);
670
+ stroke-width: 2;
671
+ }
672
+
673
+ .node.segment > rect {
674
+ fill: var(--segment);
675
+ stroke: var(--yellow-deep);
676
+ }
677
+
678
+ .node.outside > rect {
679
+ fill: var(--bg);
680
+ stroke: var(--edge);
681
+ stroke-dasharray: 2 4;
682
+ }
683
+
684
+ .node.error > rect {
685
+ stroke: var(--error);
686
+ stroke-width: 4;
687
+ }
688
+
689
+ .node.warning > rect {
690
+ stroke: var(--warning);
691
+ stroke-width: 4;
692
+ stroke-dasharray: 10 3;
693
+ }
694
+
695
+ .node.selected > rect {
696
+ fill: var(--selected);
697
+ stroke: var(--cobalt);
698
+ stroke-width: 4;
699
+ }
700
+
701
+ .node .chassis > rect:first-child {
702
+ fill: var(--cobalt);
703
+ stroke: none;
704
+ }
705
+
706
+ .node .chassis .socket {
707
+ fill: #ffffff;
708
+ stroke: none;
709
+ }
710
+
711
+ .node.selected .chassis .socket {
712
+ fill: var(--yellow);
713
+ }
714
+
715
+ .node text {
716
+ fill: var(--text);
717
+ font-size: 14px;
718
+ text-anchor: middle;
719
+ dominant-baseline: central;
720
+ pointer-events: none;
721
+ }
722
+
723
+ .node.device text {
724
+ text-anchor: start;
725
+ }
726
+
727
+ .node text.name {
728
+ font-size: 18px;
729
+ font-weight: 700;
730
+ }
731
+
732
+ .node text.sub {
733
+ fill: var(--muted);
734
+ font-size: 13px;
735
+ }
736
+
737
+ .node.segment text,
738
+ .node.outside text {
739
+ font-family: var(--mono);
740
+ font-size: 12px;
741
+ }
742
+
743
+ .dim {
744
+ opacity: 0.18;
745
+ }
746
+
747
+ svg.far .edge text {
748
+ display: none;
749
+ }
750
+
751
+ /* Presenting: the network for a big screen. The panel steps aside, lines and dots are heavier, and the drawing drifts slowly. */
752
+
753
+ .presenting #panel {
754
+ display: none;
755
+ }
756
+
757
+ .presenting .edge path:not(.hit) {
758
+ stroke-width: 3;
759
+ }
760
+
761
+ .presenting .edge.lit path:not(.hit) {
762
+ stroke-width: 5;
763
+ }
764
+
765
+ .presenting .edge .signal {
766
+ r: 4.5px;
767
+ }
768
+
769
+ .presenting .edge.lit .signal {
770
+ r: 6px;
771
+ }
772
+
773
+ .present-caption {
774
+ position: absolute;
775
+ bottom: 22px;
776
+ left: 22px;
777
+ display: grid;
778
+ gap: 2px;
779
+ margin: 0;
780
+ padding: 12px 18px 14px;
781
+ border: 2px solid var(--text);
782
+ border-radius: 2px;
783
+ background: var(--surface);
784
+ pointer-events: none;
785
+ }
786
+
787
+ .present-caption[hidden] {
788
+ display: none;
789
+ }
790
+
791
+ .present-caption strong {
792
+ font-size: 26px;
793
+ letter-spacing: -0.015em;
794
+ line-height: 1.15;
795
+ }
796
+
797
+ .present-caption span {
798
+ color: var(--muted);
799
+ font-size: 14px;
800
+ }
801
+
802
+ @media (prefers-reduced-motion: no-preference) {
803
+ .presenting svg.canvas {
804
+ animation: drift 48s ease-in-out infinite alternate;
805
+ }
806
+
807
+ .presenting svg.canvas:hover,
808
+ .presenting svg.canvas.panning {
809
+ animation-play-state: paused;
810
+ }
811
+ }
812
+
813
+ @keyframes drift {
814
+ from {
815
+ transform: scale(1) translate(-1%, -0.6%);
816
+ }
817
+
818
+ to {
819
+ transform: scale(1.05) translate(1%, 0.6%);
820
+ }
821
+ }
822
+
823
+ /* The side panel: what is selected, or the layer's legend. */
824
+
314
825
  aside {
315
- width: 340px;
826
+ width: 390px;
316
827
  overflow: auto;
317
- padding: 14px 16px;
828
+ padding: 20px 22px 32px;
318
829
  background: var(--surface);
319
830
  border-left: 1px solid var(--line);
320
831
  }
832
+
321
833
  aside h2 {
322
- font-family: var(--serif);
323
- font-size: 21px;
324
- font-weight: 400;
325
- margin: 0 0 4px;
834
+ margin: 0 0 8px;
835
+ font-family: var(--display);
836
+ font-size: 26px;
837
+ font-weight: 700;
838
+ letter-spacing: -0.015em;
839
+ line-height: 1.15;
326
840
  overflow-wrap: anywhere;
841
+ display: table;
842
+ padding-bottom: 12px;
843
+ background: radial-gradient(circle, var(--heading-dots) 48%, transparent 52%) left bottom / 14px 7px space no-repeat;
327
844
  }
328
- aside h3 {
329
- font-size: 13px;
330
- font-weight: 600;
331
- color: var(--muted);
332
- margin: 18px 0 6px;
845
+
846
+ aside h3,
847
+ .tables h3 {
848
+ margin: 26px 0 8px;
849
+ color: var(--text);
850
+ font-size: 11px;
851
+ font-weight: 700;
852
+ font-stretch: 115%;
853
+ letter-spacing: 0.1em;
854
+ text-transform: uppercase;
333
855
  }
856
+
334
857
  aside ul {
335
858
  list-style: none;
336
859
  margin: 0;
337
860
  padding: 0;
338
861
  }
862
+
339
863
  aside li {
340
864
  padding: 3px 0;
341
865
  overflow-wrap: anywhere;
342
866
  }
867
+
343
868
  aside .kind {
344
869
  color: var(--muted);
345
870
  font-size: 12px;
346
871
  }
872
+
347
873
  aside pre {
348
874
  margin: 0;
349
- font: 12px/1.45 var(--mono);
875
+ padding: 10px;
876
+ border-radius: 2px;
877
+ background: var(--navy);
878
+ color: #e6ecfa;
879
+ font: 12px/1.5 var(--mono);
350
880
  white-space: pre-wrap;
351
881
  overflow-wrap: anywhere;
352
- background: var(--bg);
353
- padding: 8px;
354
- border-radius: 6px;
355
882
  }
883
+
884
+ .legend li {
885
+ display: flex;
886
+ align-items: center;
887
+ gap: 10px;
888
+ }
889
+
890
+ .legend svg {
891
+ flex: none;
892
+ }
893
+
894
+ /* Marks that pair a colour with a word. */
895
+
356
896
  .badge {
357
897
  display: inline-block;
358
- font-size: 11px;
359
- font-weight: 600;
360
- padding: 0 6px;
361
- border-radius: 4px;
362
898
  margin-right: 6px;
363
- color: var(--on-accent);
899
+ padding: 1px 6px;
900
+ border-radius: 2px;
364
901
  font-family: var(--font);
902
+ font-size: 11px;
903
+ font-weight: 700;
904
+ font-stretch: 112%;
905
+ letter-spacing: 0.06em;
906
+ text-transform: uppercase;
365
907
  }
908
+
366
909
  .badge.error {
367
910
  background: var(--error-strong);
911
+ color: #ffffff;
368
912
  }
913
+
369
914
  .badge.warning {
370
915
  background: var(--warning-strong);
916
+ color: #11141b;
371
917
  }
918
+
372
919
  .chips {
373
920
  display: flex;
374
921
  flex-wrap: wrap;
375
922
  gap: 6px;
376
923
  }
924
+
377
925
  .chips button {
378
- padding: 2px 8px;
926
+ min-height: 28px;
927
+ padding: 2px 9px;
379
928
  font-size: 12px;
380
929
  }
381
- .legend li {
382
- display: flex;
383
- align-items: center;
384
- gap: 8px;
930
+
931
+ /* The tables. */
932
+
933
+ .tables {
934
+ flex: 1;
935
+ overflow: auto;
936
+ padding: 28px clamp(16px, 4vw, 56px) 64px;
385
937
  }
386
- .legend svg {
387
- flex: none;
938
+
939
+ .tables h2 {
940
+ margin: 6px 0 18px;
941
+ font-family: var(--display);
942
+ font-size: clamp(30px, 3.2vw, 44px);
943
+ font-weight: 700;
944
+ letter-spacing: -0.03em;
945
+ line-height: 1.2;
946
+ display: table;
947
+ padding-bottom: 14px;
948
+ background: radial-gradient(circle, var(--heading-dots) 48%, transparent 52%) left bottom / 18px 9px space no-repeat;
388
949
  }
389
- .edge path {
390
- fill: none;
391
- stroke: var(--edge);
392
- stroke-width: 1.6;
950
+
951
+ .tables h2 .badge {
952
+ margin-left: 10px;
953
+ vertical-align: middle;
954
+ letter-spacing: 0.06em;
393
955
  }
394
- .edge.one-sided path:not(.hit) {
395
- stroke: var(--warning);
396
- stroke-dasharray: 6 4;
956
+
957
+ @media (prefers-color-scheme: dark) {
958
+ :root {
959
+ --heading-dots: var(--accent);
960
+ }
397
961
  }
398
- .edge text {
399
- font-size: 11px;
400
- fill: var(--muted);
401
- paint-order: stroke;
402
- stroke: var(--bg);
403
- stroke-width: 4px;
404
- stroke-linejoin: round;
962
+
963
+ .tables h4 {
964
+ margin: 16px 0 6px;
965
+ font-family: var(--mono);
966
+ font-size: 13px;
967
+ font-weight: 600;
405
968
  }
406
- .edge .hit {
407
- stroke: transparent;
408
- stroke-width: 12;
409
- cursor: pointer;
969
+
970
+ .tables p {
971
+ margin: 4px 0 8px;
410
972
  }
411
- .edge.selected path:not(.hit),
412
- .edge.lit path:not(.hit) {
413
- stroke: var(--accent);
414
- stroke-width: 2.6;
973
+
974
+ .tables .crumbs {
975
+ margin: 0;
976
+ font-size: 13px;
415
977
  }
416
- .edge.selected text,
417
- .edge.lit text {
418
- fill: var(--text);
978
+
979
+ .tables .findings {
980
+ list-style: none;
981
+ margin: 0;
982
+ padding: 0;
419
983
  }
420
- .node {
421
- cursor: pointer;
984
+
985
+ .tables .findings li {
986
+ padding: 3px 0;
422
987
  }
423
- .node rect {
424
- fill: var(--surface);
425
- stroke: var(--line);
426
- stroke-width: 1.5;
988
+
989
+ .tables .tabs {
990
+ display: flex;
991
+ flex-wrap: wrap;
992
+ gap: 0;
993
+ margin: 18px 0 14px;
994
+ border-bottom: 1.5px solid var(--line);
427
995
  }
428
- .node.segment rect {
429
- fill: var(--segment);
996
+
997
+ .tabs button {
998
+ position: relative;
999
+ min-height: 40px;
1000
+ padding: 8px 12px 10px;
1001
+ border: 0;
1002
+ border-radius: 0;
1003
+ background: transparent;
1004
+ color: var(--muted);
1005
+ font-size: 14px;
430
1006
  }
431
- .node.outside rect {
432
- stroke-dasharray: 5 3;
1007
+
1008
+ .tabs button:hover {
1009
+ color: var(--text);
1010
+ background: var(--surface-raised);
433
1011
  }
434
- .node.error rect {
435
- stroke: var(--error);
436
- stroke-width: 3;
1012
+
1013
+ .tabs button[aria-pressed="true"] {
1014
+ background: transparent;
1015
+ color: var(--text);
437
1016
  }
438
- .node.warning rect {
439
- stroke: var(--warning);
440
- stroke-width: 3;
1017
+
1018
+ .tabs button[aria-pressed="true"]::after {
1019
+ content: "";
1020
+ position: absolute;
1021
+ right: 8px;
1022
+ bottom: -1.5px;
1023
+ left: 8px;
1024
+ height: 4px;
1025
+ background: var(--cobalt);
1026
+ animation: bar 0.28s cubic-bezier(0.16, 1, 0.3, 1);
441
1027
  }
442
- .node.selected rect {
443
- stroke: var(--accent);
444
- stroke-width: 3;
1028
+
1029
+ .table-block {
1030
+ max-width: 100%;
1031
+ overflow-x: auto;
445
1032
  }
446
- .node text {
447
- fill: var(--text);
448
- font-size: 12px;
449
- text-anchor: middle;
450
- dominant-baseline: central;
451
- pointer-events: none;
1033
+
1034
+ table.data tbody th,
1035
+ table.data td:first-child {
1036
+ white-space: nowrap;
452
1037
  }
453
- .node text.name {
454
- font-weight: 600;
1038
+
1039
+ .table-actions {
1040
+ margin: 0 0 6px;
455
1041
  font-size: 13px;
1042
+ text-align: right;
456
1043
  }
457
- .node text.sub {
458
- fill: var(--muted);
459
- font-size: 11px;
1044
+
1045
+ table.data {
1046
+ width: 100%;
1047
+ border: 0;
1048
+ border-collapse: collapse;
1049
+ background: var(--surface);
1050
+ font-size: 13.5px;
1051
+ font-variant-numeric: tabular-nums;
460
1052
  }
461
- .node.segment text,
462
- .node.outside text {
463
- font-family: var(--mono);
1053
+
1054
+ table.data th,
1055
+ table.data td {
1056
+ padding: 8px 12px;
1057
+ border-bottom: 1px solid var(--line);
1058
+ overflow-wrap: break-word;
1059
+ text-align: left;
1060
+ vertical-align: top;
1061
+ }
1062
+
1063
+ /* The head is a tinted band rather than a rule, so it is never read as a divider between rows. */
1064
+ table.data thead th {
1065
+ border-bottom: 0;
1066
+ background: var(--head);
1067
+ color: var(--text);
464
1068
  font-size: 11px;
1069
+ font-weight: 700;
1070
+ font-stretch: 112%;
1071
+ letter-spacing: 0.08em;
1072
+ text-transform: uppercase;
1073
+ white-space: nowrap;
465
1074
  }
466
- .dim {
467
- opacity: 0.18;
1075
+
1076
+ table.data th[title] {
1077
+ cursor: help;
1078
+ text-decoration: underline dotted;
1079
+ text-underline-offset: 3px;
468
1080
  }
469
- svg.far .edge text {
470
- display: none;
1081
+
1082
+ /* Only the row under the pointer is washed, not every row that holds it, and the wash is a faint link tint well apart from the head's band. */
1083
+ table.data tbody tr:hover:not(:has(tr:hover)) > td,
1084
+ table.data tbody tr:hover:not(:has(tr:hover)) > th {
1085
+ background: var(--hover);
471
1086
  }
472
- @media (max-width: 760px) {
473
- .stage {
474
- flex-direction: column;
475
- }
476
- aside {
477
- width: auto;
478
- height: 40%;
479
- border-left: 0;
480
- border-top: 1px solid var(--line);
481
- }
482
- .tables {
483
- padding: 12px 16px 40px;
484
- }
485
- header input[type="search"] {
486
- width: 100%;
487
- }
1087
+
1088
+ table.data tr.muted td {
1089
+ color: var(--muted);
488
1090
  }
489
1091
 
490
- /* A table that can be saved, with its action above it. */
491
- .table-actions {
492
- margin: 0 0 6px;
493
- font-size: 13px;
494
- text-align: right;
1092
+ table.settings {
1093
+ width: auto;
1094
+ min-width: min(560px, 100%);
1095
+ }
1096
+
1097
+ table.settings > tbody > tr > th {
1098
+ width: 1%;
1099
+ color: var(--muted);
1100
+ font-weight: 600;
1101
+ white-space: nowrap;
1102
+ }
1103
+
1104
+ table.data table.data {
1105
+ margin: 0;
495
1106
  }
496
1107
 
497
- /* The row a port's square points to. */
498
1108
  tr.flash td {
499
- background: var(--segment);
1109
+ background: var(--selected) !important;
500
1110
  transition: background 0.4s;
501
1111
  }
502
1112
 
503
- /* A device's front panel: a square per port, by speed. */
1113
+ pre.code {
1114
+ margin: 0;
1115
+ padding: 14px;
1116
+ overflow: auto;
1117
+ border-radius: 2px;
1118
+ background: var(--navy);
1119
+ color: #e6ecfa;
1120
+ font: 12.5px/1.55 var(--mono);
1121
+ white-space: pre;
1122
+ }
1123
+
1124
+ /* A device's front panel: a square per port, by speed. Each use has its own fill and edge, not colour alone. */
1125
+
504
1126
  .faceplate {
505
1127
  display: flex;
506
1128
  flex-wrap: wrap;
507
- gap: 12px 24px;
508
- padding: 12px;
1129
+ gap: 16px 28px;
1130
+ max-width: 100%;
509
1131
  margin: 8px 0;
1132
+ padding: 18px;
1133
+ overflow-x: auto;
1134
+ border: 2px solid var(--text);
1135
+ border-radius: 2px;
510
1136
  background: var(--surface);
511
- border: 1px solid var(--line);
512
- border-radius: 8px;
513
1137
  }
1138
+
514
1139
  .faceplate .speed {
515
1140
  display: flex;
516
1141
  align-items: center;
517
1142
  gap: 10px;
1143
+ min-width: max-content;
518
1144
  }
1145
+
519
1146
  .faceplate .speed-name {
1147
+ min-width: 36px;
1148
+ color: var(--muted);
520
1149
  font-family: var(--mono);
521
1150
  font-size: 12px;
522
- color: var(--muted);
523
- min-width: 36px;
524
1151
  }
1152
+
525
1153
  .faceplate .ports {
526
1154
  display: grid;
527
1155
  grid-template-rows: repeat(2, auto);
528
1156
  grid-auto-flow: column;
529
1157
  gap: 4px;
530
1158
  }
1159
+
531
1160
  .port {
532
1161
  position: relative;
533
1162
  display: inline-block;
534
1163
  width: 28px;
535
1164
  height: 24px;
536
1165
  padding: 0;
537
- font: 500 11px var(--font);
538
- border-radius: 4px;
539
- border: 1px solid var(--line);
1166
+ border: 1.5px solid var(--edge);
1167
+ border-radius: 2px;
540
1168
  background: var(--surface);
541
1169
  color: var(--text);
1170
+ font: 600 11px var(--font);
542
1171
  }
1172
+
543
1173
  .port.shut {
544
- border-style: dashed;
545
1174
  color: var(--muted);
546
- background: var(--bg);
1175
+ background: repeating-linear-gradient(135deg, var(--surface) 0 3px, var(--line) 3px 5px);
547
1176
  }
1177
+
548
1178
  .port.access {
549
- background: var(--segment);
550
- border-color: var(--accent);
1179
+ background: var(--surface);
1180
+ border: 2px solid var(--cobalt);
551
1181
  }
1182
+
552
1183
  .port.trunk {
553
- background: var(--accent-strong);
554
- border-color: var(--accent-strong);
555
- color: var(--on-accent);
1184
+ background: var(--yellow);
1185
+ border: 2px solid var(--text);
1186
+ color: #11141b;
556
1187
  }
1188
+
557
1189
  .port.routed {
558
- border: 2px solid var(--text);
1190
+ background: var(--surface);
1191
+ border: 3px double var(--text);
559
1192
  }
1193
+
560
1194
  .port.lag {
561
- border: 2px solid var(--accent);
1195
+ border: 2px dashed var(--cobalt);
562
1196
  }
1197
+
563
1198
  .port.linked::after {
564
1199
  content: "";
565
1200
  position: absolute;
@@ -570,124 +1205,258 @@ tr.flash td {
570
1205
  border-radius: 50%;
571
1206
  background: var(--ok);
572
1207
  }
1208
+
573
1209
  .faceplate-legend {
574
1210
  display: flex;
575
1211
  flex-wrap: wrap;
576
1212
  gap: 6px 16px;
577
- list-style: none;
578
- padding: 0;
579
1213
  margin: 0 0 12px;
580
- font-size: 12px;
1214
+ padding: 0;
581
1215
  color: var(--muted);
1216
+ font-size: 12px;
1217
+ list-style: none;
582
1218
  }
1219
+
583
1220
  .faceplate-legend li {
584
1221
  display: flex;
585
1222
  align-items: center;
586
1223
  gap: 6px;
587
1224
  }
1225
+
588
1226
  .faceplate-legend .port {
589
1227
  width: 18px;
590
1228
  height: 14px;
591
1229
  }
592
1230
 
593
1231
  /* A line diff: removed lines, added lines, and runs of the same folded away. */
1232
+
594
1233
  pre.diff .removed,
595
1234
  p .removed {
596
1235
  color: var(--error);
597
1236
  }
1237
+
598
1238
  pre.diff .added,
599
1239
  p .added {
600
1240
  color: var(--ok);
601
1241
  }
1242
+
1243
+ pre.code.diff .removed {
1244
+ color: #ff9ca0;
1245
+ }
1246
+
1247
+ pre.code.diff .added {
1248
+ color: #7fe0a6;
1249
+ }
1250
+
602
1251
  pre.diff .fold {
603
1252
  display: block;
1253
+ margin: 4px 0;
604
1254
  color: var(--muted);
605
1255
  font-style: italic;
606
- margin: 4px 0;
1256
+ }
1257
+
1258
+ pre.code.diff .fold {
1259
+ color: #9db3e0;
1260
+ }
1261
+
1262
+ .added {
1263
+ color: var(--ok);
1264
+ }
1265
+
1266
+ .removed {
1267
+ color: var(--error);
1268
+ }
1269
+
1270
+ details.change {
1271
+ margin: 6px 0;
1272
+ }
1273
+
1274
+ details.change summary {
1275
+ padding: 4px 0;
1276
+ font-weight: 600;
1277
+ cursor: pointer;
607
1278
  }
608
1279
 
609
1280
  /* The tools' forms: a field per line on a narrow screen, several side by side on a wide one. */
1281
+
610
1282
  .tool-form {
611
1283
  display: flex;
612
1284
  flex-wrap: wrap;
613
- align-items: flex-end;
1285
+ align-items: flex-start;
614
1286
  gap: 12px 16px;
615
- margin: 12px 0 16px;
616
- padding: 14px;
1287
+ margin: 12px 0 18px;
1288
+ padding: 16px;
1289
+ border: 2px solid var(--text);
1290
+ border-radius: 2px;
617
1291
  background: var(--surface);
618
- border: 1px solid var(--line);
619
- border-radius: 8px;
620
1292
  }
1293
+
1294
+ .tool-form > button {
1295
+ margin-top: 24px;
1296
+ }
1297
+
621
1298
  .field {
622
1299
  display: flex;
623
1300
  flex-direction: column;
624
1301
  gap: 4px;
625
- font-size: 13px;
626
1302
  color: var(--muted);
1303
+ font-size: 13px;
1304
+ font-weight: 600;
627
1305
  }
1306
+
628
1307
  .field input[type="text"],
629
1308
  .field select {
630
- font: inherit;
631
- color: var(--text);
632
- background: var(--bg);
633
- border: 1px solid var(--line);
634
- border-radius: 6px;
635
- padding: 5px 8px;
636
1309
  min-width: 150px;
1310
+ min-height: 36px;
1311
+ padding: 5px 9px;
1312
+ border: 1.5px solid var(--edge);
1313
+ border-radius: 2px;
1314
+ background: var(--bg);
1315
+ color: var(--text);
1316
+ font: inherit;
1317
+ font-weight: 400;
1318
+ }
1319
+
1320
+ .field input[type="text"]:focus,
1321
+ .field select:focus {
1322
+ border-color: var(--cobalt);
637
1323
  }
1324
+
638
1325
  .field small {
639
1326
  font-size: 11px;
1327
+ font-weight: 400;
640
1328
  }
1329
+
641
1330
  .flags {
642
1331
  display: flex;
643
1332
  flex-wrap: wrap;
644
1333
  gap: 4px 12px;
645
1334
  color: var(--text);
646
1335
  }
1336
+
647
1337
  .flag {
648
1338
  display: flex;
649
1339
  align-items: center;
650
1340
  gap: 4px;
651
1341
  }
1342
+
652
1343
  button.primary {
653
- background: var(--accent-strong);
654
- border-color: var(--accent-strong);
655
- color: var(--on-accent);
1344
+ border-color: var(--text);
1345
+ background: var(--yellow);
1346
+ color: #11141b;
1347
+ }
1348
+
1349
+ button.primary:hover {
1350
+ background: var(--yellow-deep);
1351
+ color: #11141b;
656
1352
  }
1353
+
657
1354
  .verdict {
658
- font-weight: 600;
1355
+ font-weight: 700;
659
1356
  }
1357
+
660
1358
  .verdict.accept {
661
1359
  color: var(--ok);
662
1360
  }
1361
+
663
1362
  .verdict.drop,
664
1363
  .verdict.reject {
665
1364
  color: var(--error);
666
1365
  }
1366
+
667
1367
  .verdict.unknown {
668
1368
  color: var(--warning);
669
1369
  }
670
1370
 
671
- /* A comparison on the graph: what is new, and what is gone. */
672
- .edge.added path:not(.hit) {
673
- stroke: var(--ok);
674
- stroke-width: 2.6;
675
- }
676
- .edge.gone path:not(.hit) {
677
- stroke: var(--error);
678
- stroke-dasharray: 6 4;
679
- }
680
- .added {
681
- color: var(--ok);
682
- }
683
- .removed {
684
- color: var(--error);
1371
+ /* Narrower windows: the search drops under the views, then the panel moves under the graph. */
1372
+
1373
+ @media (max-width: 1180px) {
1374
+ header input[type="search"] {
1375
+ order: 5;
1376
+ width: calc(100% - 36px);
1377
+ margin: 0 18px 10px;
1378
+ }
685
1379
  }
686
- details.change {
687
- margin: 6px 0;
1380
+
1381
+ @media (max-width: 760px) {
1382
+ header .brand {
1383
+ width: 100%;
1384
+ min-height: 52px;
1385
+ }
1386
+
1387
+ header > nav {
1388
+ width: 100%;
1389
+ overflow-x: auto;
1390
+ flex-wrap: nowrap;
1391
+ }
1392
+
1393
+ header > nav button {
1394
+ flex: none;
1395
+ }
1396
+
1397
+ .status-rail {
1398
+ align-items: flex-start;
1399
+ gap: 8px;
1400
+ padding-block: 8px;
1401
+ }
1402
+
1403
+ .summary-item,
1404
+ .summary-item:first-child {
1405
+ min-height: 28px;
1406
+ padding: 0 14px 0 0;
1407
+ border-left: 0;
1408
+ }
1409
+
1410
+ .toolbar nav {
1411
+ flex-wrap: nowrap;
1412
+ max-width: 100%;
1413
+ overflow-x: auto;
1414
+ }
1415
+
1416
+ .toolbar nav button {
1417
+ flex: none;
1418
+ }
1419
+
1420
+ .stage {
1421
+ flex-direction: column;
1422
+ }
1423
+
1424
+ svg.canvas {
1425
+ flex: 1 1 auto;
1426
+ width: 100%;
1427
+ min-height: 320px;
1428
+ }
1429
+
1430
+ aside {
1431
+ width: auto;
1432
+ height: 42%;
1433
+ border-top: 2px solid var(--text);
1434
+ border-left: 0;
1435
+ }
1436
+
1437
+ .tables {
1438
+ padding: 20px 16px 40px;
1439
+ }
1440
+
1441
+ .port {
1442
+ width: 44px;
1443
+ height: 40px;
1444
+ font-size: 13px;
1445
+ }
1446
+
1447
+ .faceplate-legend .port {
1448
+ width: 24px;
1449
+ height: 18px;
1450
+ }
688
1451
  }
689
- details.change summary {
690
- cursor: pointer;
691
- font-weight: 600;
692
- padding: 4px 0;
1452
+
1453
+ @media (prefers-reduced-motion: reduce) {
1454
+ *,
1455
+ *::before,
1456
+ *::after {
1457
+ scroll-behavior: auto !important;
1458
+ transition-duration: 0.01ms !important;
1459
+ animation-duration: 0.01ms !important;
1460
+ animation-iteration-count: 1 !important;
1461
+ }
693
1462
  }