Skip to main content

max / alloy

48.5 KB · 1236 lines History Blame Raw
1 <!doctype html>
2 <html lang="en">
3 <head>
4 <meta charset="utf-8">
5 <title>Alloy — UX mockup</title>
6 <meta name="viewport" content="width=device-width, initial-scale=1">
7 <style>
8 /* ------- Fonts ------- */
9 @font-face {
10 font-family: "Departure Mono";
11 src: url("fonts/DepartureMonoNerdFontMono-Regular.otf") format("opentype");
12 font-weight: 400;
13 font-display: block;
14 }
15 /* Quasi Mono has no @font-face and no URL on purpose. It is cut from the
16 checkout by `quasi-type` rather than shipped as a file, and built faces are
17 not committed anywhere, so there is nothing here to point at. Naming the
18 family is enough on a machine that has run the pipeline or booted the image;
19 anywhere else the stack below falls through to the platform mono, and the
20 page degrades into an honest approximation rather than a wrong picture in a
21 face the running system does not have. This is also what makes the page
22 render with no network. */
23
24 /* ------- Tokens (light mode canonical) ------- */
25 :root {
26 /* Ramp — H=80, C=0.012 throughout */
27 --surface-sunken: oklch(92% 0.012 80);
28 --surface: oklch(96% 0.012 80);
29 --surface-raised: oklch(98% 0.012 80);
30 --surface-overlay: oklch(99.5% 0.012 80);
31 --border-subtle: oklch(88% 0.012 80);
32 --border: oklch(80% 0.012 80);
33 --border-strong: oklch(65% 0.012 80);
34 --text-muted: oklch(55% 0.012 80);
35 --text-secondary: oklch(38% 0.012 80);
36 --text-primary: oklch(18% 0.012 80);
37
38 /* Accents (mode-invariant) */
39 --accent-error: oklch(55% 0.18 25);
40 --accent-warn: oklch(70% 0.15 85);
41 --accent-healthy: oklch(62% 0.16 145);
42 --accent-info: oklch(60% 0.16 240);
43 --accent-syntax: oklch(55% 0.18 310);
44
45 /* Typography */
46 --font-mono-working: "Quasi Mono", ui-monospace, "SF Mono", "JetBrains Mono", Menlo, monospace;
47 --font-mono-display: "Departure Mono", "Quasi Mono", ui-monospace, monospace;
48 --size-caption: 12px;
49 --size-body: 14px;
50 --size-section-header: 16px;
51 --size-title: 20px;
52 --size-readout-sm: 16px;
53 --size-readout-md: 24px;
54 --size-readout-lg: 48px;
55 --size-readout-xl: 72px;
56 --weight-body: 400;
57 --weight-emphasis: 600;
58 --tracking-body: 0;
59 --tracking-display: 0.04em;
60 --tracking-display-caps: 0.08em;
61 --line-height-body: 1.4;
62 --line-height-tabular: 1.3;
63 --line-height-display: 1.0;
64
65 /* Geometry */
66 --space-xs: 2px;
67 --space-sm: 4px;
68 --space-md: 8px;
69 --space-lg: 16px;
70 --space-xl: 24px;
71 --radius-control: 4px;
72 --radius-overlay: 6px;
73 --radius-data: 0;
74 --border-width-default: 1px;
75 --border-width-focus: 2px;
76 --focus-ring-offset: 1px;
77 }
78
79 /* Dark-mode polarity flip — same H/C, repositioned L stops per TOKENS.md */
80 body[data-mode="dark"] {
81 --surface-sunken: oklch(8% 0.012 80);
82 --surface: oklch(12% 0.012 80);
83 --surface-raised: oklch(15% 0.012 80);
84 --surface-overlay: oklch(19% 0.012 80);
85 --border-subtle: oklch(22% 0.012 80);
86 --border: oklch(30% 0.012 80);
87 --border-strong: oklch(48% 0.012 80);
88 --text-muted: oklch(60% 0.012 80);
89 --text-secondary: oklch(78% 0.012 80);
90 --text-primary: oklch(94% 0.012 80);
91 }
92
93 /* ------- Base ------- */
94 * { box-sizing: border-box; }
95 html, body {
96 margin: 0;
97 padding: 0;
98 background: var(--surface);
99 color: var(--text-primary);
100 font-family: var(--font-mono-working);
101 font-size: var(--size-body);
102 line-height: var(--line-height-body);
103 font-weight: var(--weight-body);
104 }
105
106 main {
107 max-width: 1100px;
108 margin: 0 auto;
109 padding: var(--space-xl);
110 }
111
112 /* ------- Header strip ------- */
113 .head {
114 display: flex;
115 align-items: baseline;
116 justify-content: space-between;
117 border-bottom: var(--border-width-default) solid var(--border);
118 padding-bottom: var(--space-lg);
119 margin-bottom: var(--space-xl);
120 }
121 .head h1 {
122 font-family: var(--font-mono-display);
123 font-size: var(--size-readout-md);
124 font-weight: 400;
125 letter-spacing: var(--tracking-display-caps);
126 margin: 0;
127 text-transform: uppercase;
128 }
129 .head .meta {
130 font-size: var(--size-caption);
131 color: var(--text-muted);
132 }
133 .head .meta strong { color: var(--text-secondary); font-weight: var(--weight-emphasis); }
134
135 .mode-toggle {
136 font-family: var(--font-mono-working);
137 font-size: var(--size-caption);
138 text-transform: uppercase;
139 letter-spacing: var(--tracking-display-caps);
140 background: var(--surface-raised);
141 border: var(--border-width-default) solid var(--border);
142 border-radius: var(--radius-control);
143 padding: var(--space-sm) var(--space-md);
144 color: var(--text-primary);
145 cursor: pointer;
146 }
147 .mode-toggle:hover { background: var(--surface-overlay); }
148 .mode-toggle:active { background: var(--surface); }
149 .mode-toggle:focus-visible {
150 outline: var(--border-width-focus) solid var(--border-strong);
151 outline-offset: var(--focus-ring-offset);
152 }
153
154 /* ------- Section pattern ------- */
155 section {
156 margin-bottom: var(--space-xl);
157 padding-bottom: var(--space-xl);
158 border-bottom: var(--border-width-default) solid var(--border-subtle);
159 }
160 section:last-child { border-bottom: none; }
161 section > h2 {
162 font-family: var(--font-mono-working);
163 font-size: var(--size-section-header);
164 font-weight: var(--weight-emphasis);
165 margin: 0 0 var(--space-md);
166 color: var(--text-primary);
167 }
168 section > .desc {
169 color: var(--text-secondary);
170 margin: 0 0 var(--space-lg);
171 font-size: var(--size-body);
172 }
173 section > .desc code {
174 background: var(--surface-sunken);
175 padding: 0 var(--space-xs);
176 border-radius: var(--radius-control);
177 font-size: 13px;
178 }
179
180 /* ------- Ramp swatches ------- */
181 .ramps { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-lg); }
182 .ramp-block {
183 background: var(--surface-raised);
184 border: var(--border-width-default) solid var(--border);
185 border-radius: var(--radius-control);
186 padding: var(--space-md);
187 }
188 .ramp-block h3 {
189 font-family: var(--font-mono-display);
190 font-size: var(--size-readout-sm);
191 letter-spacing: var(--tracking-display-caps);
192 text-transform: uppercase;
193 font-weight: 400;
194 margin: 0 0 var(--space-md);
195 color: var(--text-secondary);
196 }
197 .swatch {
198 display: grid;
199 grid-template-columns: 28px 1fr auto;
200 align-items: center;
201 gap: var(--space-md);
202 padding: var(--space-xs) 0;
203 font-size: var(--size-caption);
204 }
205 .swatch .chip {
206 width: 28px;
207 height: 28px;
208 border: var(--border-width-default) solid var(--border);
209 border-radius: var(--radius-data);
210 }
211 .swatch .name { font-weight: var(--weight-emphasis); }
212 .swatch .val { color: var(--text-muted); font-size: var(--size-caption); }
213
214 /* ------- Accents ------- */
215 .accents { display: flex; gap: var(--space-md); flex-wrap: wrap; }
216 .accent-card {
217 flex: 1 1 180px;
218 border: var(--border-width-default) solid var(--border);
219 border-radius: var(--radius-control);
220 background: var(--surface-raised);
221 padding: var(--space-md);
222 }
223 .accent-card .dot {
224 width: 14px; height: 14px;
225 border-radius: 50%;
226 display: inline-block;
227 vertical-align: middle;
228 margin-right: var(--space-sm);
229 }
230 .accent-card .lbl {
231 text-transform: uppercase;
232 letter-spacing: var(--tracking-display-caps);
233 font-size: var(--size-caption);
234 color: var(--text-secondary);
235 }
236 .accent-card .val {
237 display: block;
238 margin-top: var(--space-sm);
239 color: var(--text-muted);
240 font-size: var(--size-caption);
241 }
242
243 /* ------- Typography samples ------- */
244 .type-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-lg); }
245 .type-block {
246 border: var(--border-width-default) solid var(--border);
247 background: var(--surface-raised);
248 padding: var(--space-lg);
249 border-radius: var(--radius-control);
250 }
251 .type-block .role {
252 font-size: var(--size-caption);
253 text-transform: uppercase;
254 letter-spacing: var(--tracking-display-caps);
255 color: var(--text-muted);
256 margin-bottom: var(--space-md);
257 }
258 .type-block .working-line {
259 font-family: var(--font-mono-working);
260 margin: var(--space-xs) 0;
261 }
262 .type-block .display-line {
263 font-family: var(--font-mono-display);
264 margin: var(--space-xs) 0;
265 letter-spacing: var(--tracking-display);
266 line-height: var(--line-height-display);
267 }
268 .type-block .anno {
269 display: inline-block;
270 min-width: 7em;
271 color: var(--text-muted);
272 font-size: var(--size-caption);
273 }
274
275 /* ------- Button states grid ------- */
276 .states-grid {
277 display: grid;
278 grid-template-columns: 7em repeat(5, 1fr);
279 align-items: center;
280 gap: var(--space-md);
281 background: var(--surface-raised);
282 padding: var(--space-lg);
283 border: var(--border-width-default) solid var(--border);
284 border-radius: var(--radius-control);
285 }
286 .states-grid > .col-head {
287 font-size: var(--size-caption);
288 text-transform: uppercase;
289 letter-spacing: var(--tracking-display-caps);
290 color: var(--text-muted);
291 text-align: center;
292 }
293 .states-grid > .row-head {
294 font-size: var(--size-caption);
295 text-transform: uppercase;
296 letter-spacing: var(--tracking-display-caps);
297 color: var(--text-muted);
298 }
299
300 /* Button — base + states (statics; we render each forced state explicitly) */
301 .btn {
302 font-family: var(--font-mono-working);
303 font-size: var(--size-body);
304 font-weight: var(--weight-emphasis);
305 border-radius: var(--radius-control);
306 padding: var(--space-sm) var(--space-md);
307 border: var(--border-width-default) solid var(--border);
308 background: var(--surface-raised);
309 color: var(--text-primary);
310 cursor: pointer;
311 text-align: center;
312 display: inline-block;
313 width: 100%;
314 }
315 .btn.state-hover { background: var(--surface-overlay); }
316 .btn.state-pressed { background: var(--surface); }
317 .btn.state-focused { outline: var(--border-width-focus) solid var(--border-strong); outline-offset: var(--focus-ring-offset); }
318 .btn.state-disabled { background: var(--surface-raised); color: var(--text-muted); border-color: var(--border-subtle); cursor: not-allowed; }
319
320 /* ------- Form elements ------- */
321 .form-grid {
322 display: grid;
323 grid-template-columns: 1fr 1fr;
324 gap: var(--space-lg);
325 background: var(--surface-raised);
326 padding: var(--space-lg);
327 border: var(--border-width-default) solid var(--border);
328 border-radius: var(--radius-control);
329 }
330 .field { display: block; }
331 .field > label {
332 display: block;
333 font-size: var(--size-caption);
334 text-transform: uppercase;
335 letter-spacing: var(--tracking-display-caps);
336 color: var(--text-muted);
337 margin-bottom: var(--space-sm);
338 }
339 .field > input[type="text"],
340 .field > select {
341 width: 100%;
342 font-family: var(--font-mono-working);
343 font-size: var(--size-body);
344 background: var(--surface-sunken);
345 color: var(--text-primary);
346 border: var(--border-width-default) solid var(--border);
347 border-radius: var(--radius-control);
348 padding: var(--space-sm) var(--space-md);
349 }
350 .field > input[type="text"]:focus,
351 .field > select:focus {
352 outline: var(--border-width-focus) solid var(--border-strong);
353 outline-offset: var(--focus-ring-offset);
354 }
355
356 /* Custom checkbox */
357 .check {
358 display: inline-flex;
359 align-items: center;
360 gap: var(--space-md);
361 cursor: pointer;
362 user-select: none;
363 }
364 .check input { position: absolute; opacity: 0; pointer-events: none; }
365 .check .box {
366 width: 18px; height: 18px;
367 border: var(--border-width-default) solid var(--border);
368 background: var(--surface-sunken);
369 border-radius: var(--radius-control);
370 display: inline-flex;
371 align-items: center;
372 justify-content: center;
373 }
374 .check input:checked + .box::after {
375 content: "";
376 width: 10px; height: 10px;
377 background: var(--text-primary);
378 border-radius: 1px;
379 }
380 .check input:focus-visible + .box {
381 outline: var(--border-width-focus) solid var(--border-strong);
382 outline-offset: var(--focus-ring-offset);
383 }
384
385 /* Custom switch */
386 .switch {
387 display: inline-flex;
388 align-items: center;
389 gap: var(--space-md);
390 cursor: pointer;
391 user-select: none;
392 }
393 .switch input { position: absolute; opacity: 0; pointer-events: none; }
394 .switch .track {
395 width: 36px; height: 20px;
396 background: var(--surface-sunken);
397 border: var(--border-width-default) solid var(--border);
398 border-radius: 10px;
399 position: relative;
400 transition: background 0.08s linear;
401 }
402 .switch .track::after {
403 content: "";
404 position: absolute;
405 top: 2px; left: 2px;
406 width: 14px; height: 14px;
407 background: var(--text-secondary);
408 border-radius: 50%;
409 transition: transform 0.08s linear, background 0.08s linear;
410 }
411 .switch input:checked + .track { background: var(--border-strong); }
412 .switch input:checked + .track::after { transform: translateX(16px); background: var(--surface-raised); }
413 .switch input:focus-visible + .track {
414 outline: var(--border-width-focus) solid var(--border-strong);
415 outline-offset: var(--focus-ring-offset);
416 }
417
418 /* ------- Status readout panel (Departure showcase) ------- */
419 .status {
420 background: var(--surface-raised);
421 border: var(--border-width-default) solid var(--border);
422 border-radius: var(--radius-control);
423 padding: var(--space-lg);
424 display: grid;
425 grid-template-columns: 1fr 1fr;
426 gap: var(--space-lg);
427 }
428 .readout {
429 display: flex;
430 flex-direction: column;
431 gap: var(--space-xs);
432 border-left: var(--border-width-default) solid var(--border-subtle);
433 padding-left: var(--space-md);
434 }
435 .readout .lbl {
436 font-family: var(--font-mono-display);
437 font-size: var(--size-caption);
438 text-transform: uppercase;
439 letter-spacing: var(--tracking-display-caps);
440 color: var(--text-muted);
441 }
442 .readout .val {
443 font-family: var(--font-mono-display);
444 font-size: var(--size-readout-lg);
445 line-height: var(--line-height-display);
446 letter-spacing: var(--tracking-display);
447 color: var(--text-primary);
448 font-variant-numeric: tabular-nums;
449 }
450 .readout .val .unit {
451 font-size: var(--size-readout-md);
452 color: var(--text-muted);
453 }
454 .readout .sub {
455 font-family: var(--font-mono-working);
456 font-size: var(--size-caption);
457 color: var(--text-muted);
458 }
459 .bigclock {
460 grid-column: span 2;
461 text-align: center;
462 border-left: none;
463 border-bottom: var(--border-width-default) solid var(--border-subtle);
464 padding-bottom: var(--space-lg);
465 padding-left: 0;
466 }
467 .bigclock .val {
468 font-size: var(--size-readout-xl);
469 letter-spacing: var(--tracking-display);
470 }
471
472 /* ------- Settings row pattern (composed example) ------- */
473 .window {
474 background: var(--surface-raised);
475 border: var(--border-width-default) solid var(--border);
476 border-radius: var(--radius-control);
477 overflow: hidden;
478 }
479 .window > .titlebar {
480 display: flex;
481 align-items: center;
482 justify-content: space-between;
483 padding: var(--space-md) var(--space-lg);
484 background: var(--surface-overlay);
485 border-bottom: var(--border-width-default) solid var(--border-subtle);
486 }
487 .window > .titlebar .title {
488 font-size: var(--size-caption);
489 text-transform: uppercase;
490 letter-spacing: var(--tracking-display-caps);
491 color: var(--text-secondary);
492 }
493 .window > .body {
494 display: grid;
495 grid-template-columns: 200px 1fr;
496 }
497 .sidebar {
498 background: var(--surface);
499 border-right: var(--border-width-default) solid var(--border-subtle);
500 padding: var(--space-md) 0;
501 }
502 .sidebar a {
503 display: flex;
504 align-items: center;
505 gap: var(--space-md);
506 padding: var(--space-sm) var(--space-lg);
507 color: var(--text-secondary);
508 text-decoration: none;
509 font-size: var(--size-body);
510 }
511 .sidebar a:hover { background: var(--surface-overlay); color: var(--text-primary); }
512 .sidebar a.current {
513 background: var(--surface-raised);
514 color: var(--text-primary);
515 font-weight: var(--weight-emphasis);
516 border-left: 2px solid var(--border-strong);
517 padding-left: calc(var(--space-lg) - 2px);
518 }
519 .panel {
520 padding: var(--space-xl);
521 }
522 .panel-header {
523 display: flex;
524 align-items: center;
525 gap: var(--space-lg);
526 margin-bottom: var(--space-xl);
527 padding-bottom: var(--space-lg);
528 border-bottom: var(--border-width-default) solid var(--border-subtle);
529 }
530 .panel-header .hero { flex-shrink: 0; }
531 .panel-header .titleblock h3 {
532 font-family: var(--font-mono-display);
533 text-transform: uppercase;
534 letter-spacing: var(--tracking-display-caps);
535 font-size: var(--size-section-header);
536 font-weight: 400;
537 margin: 0 0 var(--space-sm);
538 color: var(--text-primary);
539 }
540 .panel-header .titleblock .sub {
541 color: var(--text-muted);
542 font-size: var(--size-caption);
543 }
544 .row {
545 display: grid;
546 grid-template-columns: 1fr auto;
547 align-items: center;
548 gap: var(--space-lg);
549 padding: var(--space-md) 0;
550 border-bottom: var(--border-width-default) solid var(--border-subtle);
551 }
552 .row:last-child { border-bottom: none; }
553 .row .key { display: flex; flex-direction: column; gap: var(--space-xs); }
554 .row .key .name { color: var(--text-primary); }
555 .row .key .hint { color: var(--text-muted); font-size: var(--size-caption); }
556
557 /* ------- Messages with accents (color-as-information) ------- */
558 .msg {
559 display: flex;
560 align-items: flex-start;
561 gap: var(--space-md);
562 padding: var(--space-md);
563 border-left: 3px solid var(--border);
564 background: var(--surface-raised);
565 border-radius: 0 var(--radius-control) var(--radius-control) 0;
566 margin: var(--space-sm) 0;
567 }
568 .msg .glyph {
569 width: 18px; height: 18px;
570 display: inline-flex;
571 align-items: center;
572 justify-content: center;
573 font-weight: var(--weight-emphasis);
574 flex-shrink: 0;
575 }
576 .msg.error { border-left-color: var(--accent-error); }
577 .msg.error .glyph { color: var(--accent-error); }
578 .msg.warn { border-left-color: var(--accent-warn); }
579 .msg.warn .glyph { color: var(--accent-warn); }
580 .msg.healthy { border-left-color: var(--accent-healthy); }
581 .msg.healthy .glyph { color: var(--accent-healthy); }
582 .msg.info { border-left-color: var(--accent-info); }
583 .msg.info .glyph { color: var(--accent-info); }
584
585 /* ------- Iso illustration block ------- */
586 .hero-grid {
587 display: grid;
588 grid-template-columns: repeat(4, 1fr);
589 gap: var(--space-lg);
590 }
591 .hero-tile {
592 background: var(--surface-raised);
593 border: var(--border-width-default) solid var(--border);
594 border-radius: var(--radius-control);
595 padding: var(--space-lg);
596 display: flex;
597 flex-direction: column;
598 align-items: center;
599 gap: var(--space-md);
600 }
601 .hero-tile svg { display: block; }
602 .hero-tile .lbl {
603 font-family: var(--font-mono-display);
604 font-size: var(--size-caption);
605 letter-spacing: var(--tracking-display-caps);
606 text-transform: uppercase;
607 color: var(--text-secondary);
608 }
609
610 /* color inheritance for SVG strokes/patterns */
611 .iso { color: var(--border-strong); }
612 .iso path, .iso line, .iso polyline, .iso polygon, .iso ellipse, .iso circle, .iso rect {
613 stroke: currentColor;
614 fill: none;
615 stroke-width: 1.5;
616 stroke-linecap: round;
617 stroke-linejoin: round;
618 }
619 .iso .hatch { stroke-width: 1; }
620 .iso .dim { stroke: var(--text-muted); stroke-width: 0.75; stroke-dasharray: 2 2; }
621 .iso .callout { fill: var(--text-muted); font: 9px var(--font-mono-display); letter-spacing: 0.05em; }
622 .iso .leader { stroke: var(--text-muted); stroke-width: 0.5; }
623
624 /* ------- App icon strip (dock pretend) ------- */
625 .dock {
626 display: flex;
627 gap: var(--space-md);
628 background: var(--surface-overlay);
629 border: var(--border-width-default) solid var(--border);
630 border-radius: var(--radius-overlay);
631 padding: var(--space-md);
632 width: fit-content;
633 margin: 0 auto;
634 }
635 .dock .app {
636 width: 96px; height: 96px;
637 background: var(--surface-raised);
638 border: var(--border-width-default) solid var(--border-subtle);
639 border-radius: var(--radius-control);
640 display: flex;
641 flex-direction: column;
642 align-items: center;
643 justify-content: center;
644 gap: var(--space-xs);
645 cursor: pointer;
646 }
647 .dock .app:hover { background: var(--surface-overlay); border-color: var(--border); }
648 .dock .app .lbl {
649 font-size: 10px;
650 text-transform: uppercase;
651 letter-spacing: var(--tracking-display-caps);
652 color: var(--text-muted);
653 }
654
655 /* Footer */
656 footer {
657 margin-top: var(--space-xl);
658 padding-top: var(--space-lg);
659 border-top: var(--border-width-default) solid var(--border);
660 font-size: var(--size-caption);
661 color: var(--text-muted);
662 }
663 footer a { color: var(--text-secondary); }
664 </style>
665 </head>
666 <body data-mode="light">
667 <main>
668
669 <div class="head">
670 <h1>Alloy &middot; UX mockup</h1>
671 <div style="display:flex; align-items:center; gap: var(--space-lg);">
672 <div class="meta">
673 tokens: <strong>TOKENS.md</strong> &middot;
674 icons: <strong>ICONOGRAPHY.md</strong> &middot;
675 mode: <strong id="mode-readout">light</strong>
676 </div>
677 <button class="mode-toggle" id="mode-toggle">flip polarity</button>
678 </div>
679 </div>
680
681 <!-- ============================================================== -->
682 <section>
683 <h2>1. Ramp</h2>
684 <p class="desc">Ten L-stops at hue 80, chroma 0.012. Dark mode preserves H/C and inverts polarity while keeping elevation ordering (raised reads lighter than base in both modes).</p>
685 <div class="ramps">
686 <div class="ramp-block">
687 <h3>Active mode</h3>
688 <div class="swatch"><div class="chip" style="background: var(--surface-sunken)"></div><span class="name">surface-sunken</span><span class="val">L 92 / 8</span></div>
689 <div class="swatch"><div class="chip" style="background: var(--surface)"></div><span class="name">surface</span><span class="val">L 96 / 12</span></div>
690 <div class="swatch"><div class="chip" style="background: var(--surface-raised)"></div><span class="name">surface-raised</span><span class="val">L 98 / 15</span></div>
691 <div class="swatch"><div class="chip" style="background: var(--surface-overlay)"></div><span class="name">surface-overlay</span><span class="val">L 99.5 / 19</span></div>
692 <div class="swatch"><div class="chip" style="background: var(--border-subtle)"></div><span class="name">border-subtle</span><span class="val">L 88 / 22</span></div>
693 <div class="swatch"><div class="chip" style="background: var(--border)"></div><span class="name">border</span><span class="val">L 80 / 30</span></div>
694 <div class="swatch"><div class="chip" style="background: var(--border-strong)"></div><span class="name">border-strong</span><span class="val">L 65 / 48</span></div>
695 <div class="swatch"><div class="chip" style="background: var(--text-muted)"></div><span class="name">text-muted</span><span class="val">L 55 / 60</span></div>
696 <div class="swatch"><div class="chip" style="background: var(--text-secondary)"></div><span class="name">text-secondary</span><span class="val">L 38 / 78</span></div>
697 <div class="swatch"><div class="chip" style="background: var(--text-primary)"></div><span class="name">text-primary</span><span class="val">L 18 / 94</span></div>
698 </div>
699 <div class="ramp-block">
700 <h3>Accents — same both modes</h3>
701 <div class="swatch"><div class="chip" style="background: var(--accent-error)"></div><span class="name">accent-error</span><span class="val">25°</span></div>
702 <div class="swatch"><div class="chip" style="background: var(--accent-warn)"></div><span class="name">accent-warn</span><span class="val">85°</span></div>
703 <div class="swatch"><div class="chip" style="background: var(--accent-healthy)"></div><span class="name">accent-healthy</span><span class="val">145°</span></div>
704 <div class="swatch"><div class="chip" style="background: var(--accent-info)"></div><span class="name">accent-info</span><span class="val">240°</span></div>
705 <div class="swatch"><div class="chip" style="background: var(--accent-syntax)"></div><span class="name">accent-syntax</span><span class="val">310°</span></div>
706
707 <div style="margin-top: var(--space-lg)">
708 <div class="msg error"><div class="glyph">!</div><div><strong>Disk write failed.</strong> Bay 03 reports a hardware fault. Action required.</div></div>
709 <div class="msg warn"><div class="glyph">&#9888;</div><div><strong>Battery at 18%.</strong> Plug in or close non-essential applications.</div></div>
710 <div class="msg healthy"><div class="glyph">&#10003;</div><div><strong>Backup complete.</strong> 24,108 files written to archive volume.</div></div>
711 <div class="msg info"><div class="glyph">i</div><div><strong>Update available.</strong> alloy-system 0.4.1 is ready to install.</div></div>
712 </div>
713 </div>
714 </div>
715 </section>
716
717 <!-- ============================================================== -->
718 <section>
719 <h2>2. Typography &mdash; two fonts, two roles</h2>
720 <p class="desc">Quasi Mono for anything authored or read. Departure Mono for anything <em>displayed as a readout</em>. The seam between them is where the mil-spec register lives.</p>
721 <p class="desc">The two faces are not interchangeable and the split is not taste. Quasi Mono is the house face the image installs and the only one fontconfig routes the generic monospace family to, and it covers every codepoint Alloy's surfaces emit. Departure is the brand mark, deliberately absent from the image, and it is short five of those eighteen &mdash; four of them starship and helix prompt furniture. So a surface that runs gets Quasi Mono; Departure is for headers, plates and readouts, which is exactly what this page shows it doing.</p>
722 <div class="type-grid">
723 <div class="type-block">
724 <div class="role">Working &mdash; Quasi Mono</div>
725 <div class="working-line" style="font-size: 20px; font-weight: 600"><span class="anno">title 20/600</span>Schedule a maintenance window</div>
726 <div class="working-line" style="font-size: 16px; font-weight: 600"><span class="anno">header 16/600</span>Connected interfaces</div>
727 <div class="working-line" style="font-size: 14px; font-weight: 400"><span class="anno">body 14/400</span>The relay station reports nominal voltage across all three phases.</div>
728 <div class="working-line" style="font-size: 14px; font-weight: 600"><span class="anno">strong 14/600</span>Operator override is in effect.</div>
729 <div class="working-line" style="font-size: 12px; font-weight: 400; color: var(--text-muted)"><span class="anno">caption 12/400</span>Last polled 14:22:08 &middot; jitter 1.4ms</div>
730 </div>
731 <div class="type-block">
732 <div class="role">Display &mdash; Departure</div>
733 <div class="display-line" style="font-size: 48px"><span class="anno" style="color: var(--text-muted); font-family: var(--font-mono-working)">readout 48</span>14:22:08</div>
734 <div class="display-line" style="font-size: 24px"><span class="anno" style="color: var(--text-muted); font-family: var(--font-mono-working)">readout 24</span>CPU 12% &middot; 36C</div>
735 <div class="display-line" style="font-size: 16px; text-transform: uppercase; letter-spacing: var(--tracking-display-caps)"><span class="anno" style="color: var(--text-muted); font-family: var(--font-mono-working)">caps 16/.08</span>Generator A nominal</div>
736 <div class="display-line" style="font-size: 12px; text-transform: uppercase; letter-spacing: var(--tracking-display-caps); color: var(--text-muted)"><span class="anno" style="color: var(--text-muted); font-family: var(--font-mono-working)">caps 12/.08</span>Bay 03 // FAULT</div>
737 </div>
738 </div>
739 </section>
740
741 <!-- ============================================================== -->
742 <section>
743 <h2>3. Control states</h2>
744 <p class="desc">Every interactive surface defines five states. Hover steps toward the eye (lighter in both modes). Pressed steps away. Focus is <code>border-strong</code> at 2px, never an accent color.</p>
745 <div class="states-grid">
746 <div></div>
747 <div class="col-head">default</div>
748 <div class="col-head">hover</div>
749 <div class="col-head">pressed</div>
750 <div class="col-head">focused</div>
751 <div class="col-head">disabled</div>
752
753 <div class="row-head">Button</div>
754 <button class="btn">Apply</button>
755 <button class="btn state-hover">Apply</button>
756 <button class="btn state-pressed">Apply</button>
757 <button class="btn state-focused">Apply</button>
758 <button class="btn state-disabled" disabled>Apply</button>
759 </div>
760 </section>
761
762 <!-- ============================================================== -->
763 <section>
764 <h2>4. Form elements</h2>
765 <p class="desc">Inputs sit on <code>surface-sunken</code> &mdash; recessed, signaling editability. Switches use ramp-only color; the "on" state shifts to <code>border-strong</code>, not an accent.</p>
766 <div class="form-grid">
767 <div class="field">
768 <label>Station identifier</label>
769 <input type="text" value="RS-04 // Bell Hollow">
770 </div>
771 <div class="field">
772 <label>Polling interval</label>
773 <select>
774 <option>250 ms</option>
775 <option selected>500 ms</option>
776 <option>1 s</option>
777 <option>5 s</option>
778 </select>
779 </div>
780 <div class="field">
781 <label>Toggles</label>
782 <div style="display: flex; flex-direction: column; gap: var(--space-md);">
783 <label class="switch"><input type="checkbox" checked><span class="track"></span><span>Annunciator audible</span></label>
784 <label class="switch"><input type="checkbox"><span class="track"></span><span>Auto-reset on fault clear</span></label>
785 <label class="switch"><input type="checkbox" checked><span class="track"></span><span>Log to archive volume</span></label>
786 </div>
787 </div>
788 <div class="field">
789 <label>Channels</label>
790 <div style="display: flex; flex-direction: column; gap: var(--space-md);">
791 <label class="check"><input type="checkbox" checked><span class="box"></span><span>Generator A</span></label>
792 <label class="check"><input type="checkbox" checked><span class="box"></span><span>Generator B</span></label>
793 <label class="check"><input type="checkbox"><span class="box"></span><span>Generator C (offline)</span></label>
794 <label class="check"><input type="checkbox" checked><span class="box"></span><span>Microwave relay 04-N</span></label>
795 </div>
796 </div>
797 </div>
798 </section>
799
800 <!-- ============================================================== -->
801 <section>
802 <h2>5. Status readouts &mdash; Departure in its role</h2>
803 <p class="desc">The display font earning its rent. Tabular numerics, fixed weight, UPPERCASE labels with tracking. This is what makes Alloy look like an instrument rather than a productivity app.</p>
804 <div class="status">
805 <div class="readout bigclock">
806 <span class="lbl">Local time &middot; UTC&minus;06</span>
807 <span class="val">14:22:08</span>
808 <span class="sub">Drift 0.4 ms over last 24h</span>
809 </div>
810 <div class="readout">
811 <span class="lbl">CPU load</span>
812 <span class="val">12<span class="unit">%</span></span>
813 <span class="sub">8 cores nominal &middot; 36&deg;C</span>
814 </div>
815 <div class="readout">
816 <span class="lbl">Memory</span>
817 <span class="val">9.4<span class="unit">G</span></span>
818 <span class="sub">of 32G &middot; 28% utilized</span>
819 </div>
820 <div class="readout">
821 <span class="lbl">Net &uarr;</span>
822 <span class="val">1.4<span class="unit">M</span></span>
823 <span class="sub">wlp1s0 &middot; jitter 1.2 ms</span>
824 </div>
825 <div class="readout">
826 <span class="lbl">Net &darr;</span>
827 <span class="val">12.8<span class="unit">M</span></span>
828 <span class="sub">peak 28.4M / 10s</span>
829 </div>
830 </div>
831 </section>
832
833 <!-- ============================================================== -->
834 <section>
835 <h2>6. Hero iconography &mdash; relay station theme</h2>
836 <p class="desc">Placeholders, drawn in inline SVG to demonstrate the style rules from <code>ICONOGRAPHY.md</code>. True isometric, 1.5px line on <code>border-strong</code>, mandatory hatching, no fills. Real illustrations get drawn for v1.</p>
837 <div class="hero-grid">
838 <div class="hero-tile">
839 <!-- Microwave relay tower -->
840 <svg class="iso" viewBox="0 0 120 160" width="100" height="140" aria-label="Microwave relay tower">
841 <defs>
842 <pattern id="metal-tower" patternUnits="userSpaceOnUse" width="6" height="6" patternTransform="rotate(45)">
843 <line class="hatch" x1="0" y1="0" x2="0" y2="6"/>
844 </pattern>
845 </defs>
846 <!-- ground line -->
847 <line x1="20" y1="140" x2="100" y2="140"/>
848 <line class="hatch" x1="22" y1="143" x2="98" y2="143"/>
849 <line class="hatch" x1="26" y1="146" x2="94" y2="146"/>
850 <line class="hatch" x1="30" y1="149" x2="90" y2="149"/>
851 <!-- concrete pad -->
852 <polygon points="40,140 80,140 84,135 44,135"/>
853 <!-- mast vertical lines (iso vertical) -->
854 <line x1="58" y1="135" x2="58" y2="40"/>
855 <line x1="66" y1="135" x2="66" y2="40"/>
856 <!-- mast crossbracing (X pattern) -->
857 <line x1="58" y1="125" x2="66" y2="115"/>
858 <line x1="66" y1="125" x2="58" y2="115"/>
859 <line x1="58" y1="115" x2="66" y2="105"/>
860 <line x1="66" y1="115" x2="58" y2="105"/>
861 <line x1="58" y1="105" x2="66" y2="95"/>
862 <line x1="66" y1="105" x2="58" y2="95"/>
863 <line x1="58" y1="95" x2="66" y2="85"/>
864 <line x1="66" y1="95" x2="58" y2="85"/>
865 <line x1="58" y1="85" x2="66" y2="75"/>
866 <line x1="66" y1="85" x2="58" y2="75"/>
867 <line x1="58" y1="75" x2="66" y2="65"/>
868 <line x1="66" y1="75" x2="58" y2="65"/>
869 <line x1="58" y1="65" x2="66" y2="55"/>
870 <line x1="66" y1="65" x2="58" y2="55"/>
871 <line x1="58" y1="55" x2="66" y2="45"/>
872 <line x1="66" y1="55" x2="58" y2="45"/>
873 <!-- horn antennas at top -->
874 <path d="M 50 50 L 58 50 L 58 42 L 50 42 Z"/>
875 <path d="M 50 50 L 46 54 L 46 46 L 50 42"/>
876 <path d="M 66 50 L 74 50 L 74 42 L 66 42 Z"/>
877 <path d="M 74 50 L 78 54 L 78 46 L 74 42"/>
878 <!-- top cap -->
879 <line x1="58" y1="40" x2="66" y2="40"/>
880 <circle cx="62" cy="36" r="2"/>
881 </svg>
882 <div class="lbl">Network</div>
883 </div>
884
885 <div class="hero-tile">
886 <!-- Generator + transformer -->
887 <svg class="iso" viewBox="0 0 160 160" width="120" height="120" aria-label="Generator and transformer">
888 <defs>
889 <pattern id="metal-gen" patternUnits="userSpaceOnUse" width="5" height="5" patternTransform="rotate(45)">
890 <line class="hatch" x1="0" y1="0" x2="0" y2="5"/>
891 </pattern>
892 </defs>
893 <!-- ground line -->
894 <line x1="10" y1="140" x2="150" y2="140"/>
895 <line class="hatch" x1="14" y1="144" x2="148" y2="144"/>
896 <line class="hatch" x1="20" y1="148" x2="142" y2="148"/>
897 <!-- concrete plinth (iso box) -->
898 <polygon points="20,140 80,140 90,130 30,130"/>
899 <polygon points="80,140 80,135 90,125 90,130"/>
900 <line x1="20" y1="140" x2="20" y2="138"/>
901 <!-- generator cylinder horizontal (iso) -->
902 <!-- left ellipse -->
903 <ellipse cx="35" cy="110" rx="6" ry="14" transform="rotate(-30 35 110)"/>
904 <!-- right ellipse -->
905 <ellipse cx="80" cy="110" rx="6" ry="14" transform="rotate(-30 80 110)"/>
906 <!-- top connecting line -->
907 <line x1="32" y1="98" x2="77" y2="98"/>
908 <!-- bottom connecting line -->
909 <line x1="38" y1="122" x2="83" y2="122"/>
910 <!-- bands across cylinder -->
911 <line x1="48" y1="100" x2="51" y2="124"/>
912 <line x1="65" y1="100" x2="68" y2="124"/>
913 <!-- junction box on top -->
914 <polygon points="48,90 62,90 66,86 52,86"/>
915 <polygon points="62,90 62,98 66,94 66,86"/>
916 <polygon points="48,90 48,98 62,98 62,90"/>
917 <!-- output conduit going right to transformer -->
918 <line x1="64" y1="88" x2="100" y2="78"/>
919 <!-- transformer (iso box on plinth) -->
920 <polygon points="105,120 140,120 148,114 113,114"/>
921 <polygon points="140,120 140,80 148,74 148,114"/>
922 <polygon points="105,120 105,80 140,80 140,120"/>
923 <!-- transformer cooling fins -->
924 <line x1="142" y1="115" x2="142" y2="80"/>
925 <line x1="144" y1="113" x2="144" y2="78"/>
926 <line x1="146" y1="111" x2="146" y2="76"/>
927 <!-- bushings on top -->
928 <ellipse cx="115" cy="78" rx="2" ry="1"/>
929 <line x1="115" y1="78" x2="115" y2="70"/>
930 <ellipse cx="125" cy="76" rx="2" ry="1"/>
931 <line x1="125" y1="76" x2="125" y2="68"/>
932 <ellipse cx="135" cy="74" rx="2" ry="1"/>
933 <line x1="135" y1="74" x2="135" y2="66"/>
934 </svg>
935 <div class="lbl">Power</div>
936 </div>
937
938 <div class="hero-tile">
939 <!-- Annunciator panel -->
940 <svg class="iso" viewBox="0 0 160 160" width="120" height="120" aria-label="Annunciator panel">
941 <!-- floor line -->
942 <line x1="20" y1="145" x2="140" y2="145"/>
943 <line class="hatch" x1="24" y1="148" x2="138" y2="148"/>
944 <line class="hatch" x1="30" y1="151" x2="132" y2="151"/>
945 <!-- base plinth -->
946 <polygon points="50,145 110,145 120,138 60,138"/>
947 <polygon points="110,145 110,142 120,135 120,138"/>
948 <!-- panel face (iso vertical face) -->
949 <polygon points="50,138 110,138 110,40 50,40"/>
950 <!-- panel top (iso top face) -->
951 <polygon points="50,40 110,40 120,32 60,32"/>
952 <!-- panel side -->
953 <polygon points="110,40 110,138 120,130 120,32"/>
954 <!-- lamp grid 3x4 on front face -->
955 <g>
956 <rect x="55" y="48" width="12" height="10"/>
957 <rect x="72" y="48" width="12" height="10"/>
958 <rect x="89" y="48" width="12" height="10"/>
959 <rect x="55" y="63" width="12" height="10"/>
960 <rect x="72" y="63" width="12" height="10"/>
961 <rect x="89" y="63" width="12" height="10"/>
962 <rect x="55" y="78" width="12" height="10"/>
963 <rect x="72" y="78" width="12" height="10"/>
964 <rect x="89" y="78" width="12" height="10"/>
965 <rect x="55" y="93" width="12" height="10"/>
966 <rect x="72" y="93" width="12" height="10"/>
967 <rect x="89" y="93" width="12" height="10"/>
968 </g>
969 <!-- label strip -->
970 <line x1="55" y1="112" x2="101" y2="112"/>
971 <line x1="55" y1="120" x2="101" y2="120"/>
972 <!-- label hatching (parallel lines = label text placeholder) -->
973 <line class="hatch" x1="57" y1="115" x2="98" y2="115"/>
974 <line class="hatch" x1="57" y1="117" x2="98" y2="117"/>
975 <!-- reset button bottom right -->
976 <ellipse cx="98" cy="130" rx="3" ry="2"/>
977 </svg>
978 <div class="lbl">Notifications</div>
979 </div>
980
981 <div class="hero-tile">
982 <!-- Parts crate on pallet -->
983 <svg class="iso" viewBox="0 0 160 160" width="120" height="120" aria-label="Parts bay crate">
984 <!-- floor -->
985 <line x1="10" y1="145" x2="150" y2="145"/>
986 <line class="hatch" x1="14" y1="148" x2="148" y2="148"/>
987 <line class="hatch" x1="20" y1="151" x2="142" y2="151"/>
988 <!-- pallet slats (iso) -->
989 <polygon points="30,140 110,140 130,128 50,128"/>
990 <polygon points="110,140 110,135 130,123 130,128"/>
991 <line x1="30" y1="140" x2="30" y2="135"/>
992 <line x1="30" y1="135" x2="110" y2="135"/>
993 <!-- pallet gap lines -->
994 <line x1="55" y1="138" x2="75" y2="126"/>
995 <line x1="85" y1="138" x2="105" y2="126"/>
996 <!-- crate body -->
997 <polygon points="40,128 100,128 120,116 60,116"/>
998 <polygon points="100,128 100,60 120,48 120,116"/>
999 <polygon points="40,128 40,60 100,60 100,128"/>
1000 <!-- crate bracing X on front -->
1001 <line x1="40" y1="128" x2="100" y2="60"/>
1002 <line x1="100" y1="128" x2="40" y2="60"/>
1003 <!-- crate bracing on side -->
1004 <line x1="100" y1="128" x2="120" y2="48"/>
1005 <line x1="100" y1="60" x2="120" y2="116"/>
1006 <!-- top slats -->
1007 <line x1="50" y1="60" x2="70" y2="48"/>
1008 <line x1="60" y1="60" x2="80" y2="48"/>
1009 <line x1="70" y1="60" x2="90" y2="48"/>
1010 <line x1="80" y1="60" x2="100" y2="48"/>
1011 <line x1="90" y1="60" x2="110" y2="48"/>
1012 <!-- stencil label on front -->
1013 <line x1="55" y1="100" x2="85" y2="100"/>
1014 <line x1="55" y1="105" x2="85" y2="105"/>
1015 <line class="hatch" x1="58" y1="102" x2="82" y2="102"/>
1016 </svg>
1017 <div class="lbl">Packages</div>
1018 </div>
1019 </div>
1020 </section>
1021
1022 <!-- ============================================================== -->
1023 <section>
1024 <h2>7. Authored app icons &mdash; dock</h2>
1025 <p class="desc">Each marquee Alloy app gets a piece of facility equipment as its identity. Drawn against the chrome ramp, no color.</p>
1026 <div class="dock">
1027 <div class="app">
1028 <svg class="iso" viewBox="0 0 60 60" width="56" height="56" aria-label="Lockscreen">
1029 <line x1="6" y1="52" x2="54" y2="52"/>
1030 <line class="hatch" x1="10" y1="55" x2="50" y2="55"/>
1031 <polygon points="18,52 42,52 48,46 24,46"/>
1032 <polygon points="42,52 42,20 48,14 48,46"/>
1033 <polygon points="18,52 18,20 42,20 42,52"/>
1034 <circle cx="30" cy="36" r="4"/>
1035 <line x1="30" y1="40" x2="30" y2="46"/>
1036 </svg>
1037 <span class="lbl">Lock</span>
1038 </div>
1039 <div class="app">
1040 <svg class="iso" viewBox="0 0 60 60" width="56" height="56" aria-label="Packages">
1041 <line x1="6" y1="52" x2="54" y2="52"/>
1042 <line class="hatch" x1="10" y1="55" x2="50" y2="55"/>
1043 <polygon points="15,48 40,48 48,40 23,40"/>
1044 <polygon points="40,48 40,22 48,14 48,40"/>
1045 <polygon points="15,48 15,22 40,22 40,48"/>
1046 <line x1="15" y1="48" x2="40" y2="22"/>
1047 <line x1="40" y1="48" x2="15" y2="22"/>
1048 </svg>
1049 <span class="lbl">Packages</span>
1050 </div>
1051 <div class="app">
1052 <svg class="iso" viewBox="0 0 60 60" width="56" height="56" aria-label="Settings">
1053 <line x1="6" y1="52" x2="54" y2="52"/>
1054 <line class="hatch" x1="10" y1="55" x2="50" y2="55"/>
1055 <polygon points="20,50 40,50 46,44 26,44"/>
1056 <polygon points="20,44 40,44 40,16 20,16"/>
1057 <polygon points="40,44 40,16 46,10 46,38"/>
1058 <polygon points="20,16 40,16 46,10 26,10"/>
1059 <!-- knobs grid -->
1060 <circle cx="25" cy="24" r="2"/>
1061 <circle cx="32" cy="24" r="2"/>
1062 <circle cx="25" cy="32" r="2"/>
1063 <circle cx="32" cy="32" r="2"/>
1064 </svg>
1065 <span class="lbl">Settings</span>
1066 </div>
1067 <div class="app">
1068 <svg class="iso" viewBox="0 0 60 60" width="56" height="56" aria-label="Terminal">
1069 <line x1="6" y1="52" x2="54" y2="52"/>
1070 <line class="hatch" x1="10" y1="55" x2="50" y2="55"/>
1071 <polygon points="14,50 42,50 48,44 20,44"/>
1072 <polygon points="42,50 42,18 48,12 48,44"/>
1073 <polygon points="14,50 14,18 42,18 42,50"/>
1074 <line x1="18" y1="26" x2="22" y2="30"/>
1075 <line x1="22" y1="30" x2="18" y2="34"/>
1076 <line x1="24" y1="36" x2="32" y2="36"/>
1077 </svg>
1078 <span class="lbl">Terminal</span>
1079 </div>
1080 <div class="app">
1081 <svg class="iso" viewBox="0 0 60 60" width="56" height="56" aria-label="Files">
1082 <line x1="6" y1="52" x2="54" y2="52"/>
1083 <line class="hatch" x1="10" y1="55" x2="50" y2="55"/>
1084 <polygon points="14,46 36,46 42,40 20,40"/>
1085 <polygon points="14,46 14,28 36,28 36,46"/>
1086 <polygon points="36,46 36,28 42,22 42,40"/>
1087 <polygon points="14,28 36,28 42,22 20,22"/>
1088 <line x1="18" y1="34" x2="32" y2="34"/>
1089 <line x1="18" y1="40" x2="32" y2="40"/>
1090 </svg>
1091 <span class="lbl">Files</span>
1092 </div>
1093 </div>
1094 </section>
1095
1096 <!-- ============================================================== -->
1097 <section>
1098 <h2>8. Composed window &mdash; settings panel</h2>
1099 <p class="desc">Putting everything together. A typical chrome surface: titlebar, sidebar navigation, panel header with hero illustration, settings rows with the working-font/display-font split.</p>
1100 <div class="window">
1101 <div class="titlebar">
1102 <div class="title">Alloy &middot; Settings &middot; Network</div>
1103 <div class="title" style="color: var(--text-muted)">RS-04 // BELL HOLLOW</div>
1104 </div>
1105 <div class="body">
1106 <nav class="sidebar">
1107 <a href="#">Display</a>
1108 <a href="#" class="current">Network</a>
1109 <a href="#">Sound</a>
1110 <a href="#">Power</a>
1111 <a href="#">Storage</a>
1112 <a href="#">Updates</a>
1113 <a href="#">Privacy</a>
1114 </nav>
1115 <div class="panel">
1116 <div class="panel-header">
1117 <div class="hero">
1118 <svg class="iso" viewBox="0 0 120 160" width="80" height="110" aria-label="Microwave relay">
1119 <line x1="20" y1="140" x2="100" y2="140"/>
1120 <line class="hatch" x1="22" y1="143" x2="98" y2="143"/>
1121 <line class="hatch" x1="26" y1="146" x2="94" y2="146"/>
1122 <polygon points="40,140 80,140 84,135 44,135"/>
1123 <line x1="58" y1="135" x2="58" y2="40"/>
1124 <line x1="66" y1="135" x2="66" y2="40"/>
1125 <line x1="58" y1="125" x2="66" y2="115"/>
1126 <line x1="66" y1="125" x2="58" y2="115"/>
1127 <line x1="58" y1="105" x2="66" y2="95"/>
1128 <line x1="66" y1="105" x2="58" y2="95"/>
1129 <line x1="58" y1="85" x2="66" y2="75"/>
1130 <line x1="66" y1="85" x2="58" y2="75"/>
1131 <line x1="58" y1="65" x2="66" y2="55"/>
1132 <line x1="66" y1="65" x2="58" y2="55"/>
1133 <path d="M 50 50 L 58 50 L 58 42 L 50 42 Z"/>
1134 <path d="M 50 50 L 46 54 L 46 46 L 50 42"/>
1135 <path d="M 66 50 L 74 50 L 74 42 L 66 42 Z"/>
1136 <path d="M 74 50 L 78 54 L 78 46 L 74 42"/>
1137 </svg>
1138 </div>
1139 <div class="titleblock">
1140 <h3>Network &middot; transmission</h3>
1141 <div class="sub">wlp1s0 &middot; en0 &middot; relay 04-N &middot; auto-failover engaged</div>
1142 </div>
1143 </div>
1144
1145 <div class="row">
1146 <div class="key">
1147 <span class="name">Primary interface</span>
1148 <span class="hint">Used for outbound traffic unless overridden</span>
1149 </div>
1150 <div>
1151 <select style="width: 180px">
1152 <option>wlp1s0 (wifi)</option>
1153 <option selected>en0 (ethernet)</option>
1154 </select>
1155 </div>
1156 </div>
1157
1158 <div class="row">
1159 <div class="key">
1160 <span class="name">Connect on boot</span>
1161 <span class="hint">Restore last-known interface state at session start</span>
1162 </div>
1163 <label class="switch"><input type="checkbox" checked><span class="track"></span></label>
1164 </div>
1165
1166 <div class="row">
1167 <div class="key">
1168 <span class="name">DNS over HTTPS</span>
1169 <span class="hint">Resolve via Cloudflare 1.1.1.1, fall back to ISP</span>
1170 </div>
1171 <label class="switch"><input type="checkbox"><span class="track"></span></label>
1172 </div>
1173
1174 <div class="row">
1175 <div class="key">
1176 <span class="name">Polling interval</span>
1177 <span class="hint">How often link status and throughput are sampled</span>
1178 </div>
1179 <select style="width: 140px">
1180 <option>250 ms</option>
1181 <option selected>500 ms</option>
1182 <option>1 s</option>
1183 </select>
1184 </div>
1185
1186 <div class="row" style="border-bottom: none; padding-top: var(--space-lg)">
1187 <div class="key">
1188 <span class="name">Live readout</span>
1189 <span class="hint">Real-time throughput on the active interface</span>
1190 </div>
1191 <div style="display: flex; gap: var(--space-lg); font-family: var(--font-mono-display); font-variant-numeric: tabular-nums;">
1192 <div style="text-align: right">
1193 <div style="font-size: var(--size-caption); letter-spacing: var(--tracking-display-caps); text-transform: uppercase; color: var(--text-muted)">UP</div>
1194 <div style="font-size: var(--size-readout-md)">1.4M</div>
1195 </div>
1196 <div style="text-align: right">
1197 <div style="font-size: var(--size-caption); letter-spacing: var(--tracking-display-caps); text-transform: uppercase; color: var(--text-muted)">DOWN</div>
1198 <div style="font-size: var(--size-readout-md)">12.8M</div>
1199 </div>
1200 <div style="text-align: right">
1201 <div style="font-size: var(--size-caption); letter-spacing: var(--tracking-display-caps); text-transform: uppercase; color: var(--text-muted)">PING</div>
1202 <div style="font-size: var(--size-readout-md)">8<span style="color: var(--text-muted)">ms</span></div>
1203 </div>
1204 </div>
1205 </div>
1206
1207 <div style="display: flex; justify-content: flex-end; gap: var(--space-md); margin-top: var(--space-xl); padding-top: var(--space-lg); border-top: var(--border-width-default) solid var(--border-subtle)">
1208 <button class="btn state-disabled" style="width: auto" disabled>Revert</button>
1209 <button class="btn" style="width: auto; background: var(--surface); border-color: var(--border)">Cancel</button>
1210 <button class="btn" style="width: auto; background: var(--text-primary); color: var(--surface-raised); border-color: var(--text-primary)">Apply</button>
1211 </div>
1212 </div>
1213 </div>
1214 </div>
1215 </section>
1216
1217 <footer>
1218 Alloy &middot; mockup &middot; tokens locked in <a href="../TOKENS.md">TOKENS.md</a> &middot; iconography in <a href="../ICONOGRAPHY.md">ICONOGRAPHY.md</a>.
1219 Iso illustrations are rough SVG placeholders &mdash; the real ones get drawn for v1.
1220 </footer>
1221
1222 </main>
1223
1224 <script>
1225 const toggle = document.getElementById('mode-toggle');
1226 const readout = document.getElementById('mode-readout');
1227 toggle.addEventListener('click', () => {
1228 const cur = document.body.dataset.mode;
1229 const next = cur === 'dark' ? 'light' : 'dark';
1230 document.body.dataset.mode = next;
1231 readout.textContent = next;
1232 });
1233 </script>
1234 </body>
1235 </html>
1236