Source mirror · commit 369512f · 2026-10-26 · MIT · canonical repo: gitlab.com/jiapunk/upgrade-airlock
git clone https://upgrade-airlock.pages.dev/source/upgrade-airlock.git
upgrade-airlock / web / src / style.css
web/src/style.css3633 lines · 70744 bytes
1/* Upgrade Airlock war room, presentation edition.
2 Stage mode (wide landscape: projector, recorded video): a fixed 1920x1080 stage that ui.ts fitStage() scales to the
3 window and letterboxes it, so 1920x1080, 1280x720, a 4:3 or a 5:4 projector and the recorded video all show the
4 same composition. Stack mode (phones, portrait, narrow windows): one scrolling column, see the block at the end.
5 The two are told apart by STAGE_QUERY in ui.ts: (min-width: 960px) and (min-aspect-ratio: 5/4).
6 System fonts only (no web fonts: the venue network may block them). One accent, Chainlink blue, also for "live"
7 and the presenter toggles; green only for a clearance, red only for a veto, amber only for a warning. Every state
8 has an icon or a word as well as a colour. Presenter chrome: hidden with ?clean=1, faded out after 3 s without
9 mouse movement on a stage screen, key hints never shown on a touch screen (see the end of the file). */
10
11:root {
12 color-scheme: dark;
13 --bg: #05070e;
14 --panel: #0d1426;
15 --panel-2: #131c33;
16 --line: rgba(160, 178, 222, 0.14);
17 --line-2: rgba(160, 178, 222, 0.26);
18 --fg: #f3f6fd;
19 --dim: #a7b2c9;
20 --faint: #8a96b0;
21 --accent: #375bd2;
22 --accent-hi: #8aa3ff;
23 --accent-soft: rgba(55, 91, 210, 0.2);
24 --good: #2fd38e;
25 --good-hi: #63f0b4;
26 --good-soft: rgba(47, 211, 142, 0.14);
27 --bad: #ff4d5e;
28 --bad-hi: #ff8590;
29 --bad-soft: rgba(255, 77, 94, 0.15);
30 --warn: #f5b942;
31 --warn-soft: rgba(245, 185, 66, 0.14);
32 --sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'Noto Sans SC', 'Noto Sans CJK SC', system-ui, sans-serif;
33 --mono: ui-monospace, 'SF Mono', SFMono-Regular, Menlo, Consolas, 'Liberation Mono', monospace;
34 /* the airlock picture (stage sizes; stack mode overrides them) */
35 --owner-w: 150px;
36 --door-w: 62px;
37 --dest-w: 200px;
38 --lk-gap: 14px;
39 --lk-h: 330px;
40 --cap-w: 272px;
41 --cap-h: 64px;
42}
43:root:lang(zh-TW) {
44 --sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang TC', 'Hiragino Sans CNS', 'Microsoft JhengHei', 'Noto Sans TC', 'Noto Sans CJK TC', system-ui, sans-serif;
45}
46
47* {
48 box-sizing: border-box;
49}
50html,
51body {
52 margin: 0;
53 height: 100%;
54 background: var(--bg);
55 color: var(--fg);
56 font-family: var(--sans);
57 -webkit-font-smoothing: antialiased;
58 -moz-osx-font-smoothing: grayscale;
59 text-rendering: optimizeLegibility;
60}
61body {
62 overflow: hidden;
63}
64#app {
65 position: fixed;
66 inset: 0;
67 background: var(--bg);
68}
69button {
70 font: inherit;
71 color: inherit;
72}
73a {
74 color: inherit;
75}
76.mono {
77 font-family: var(--mono);
78 font-variant-numeric: tabular-nums;
79}
80.dim {
81 color: var(--faint);
82}
83.ic {
84 width: 1em;
85 height: 1em;
86 flex: none;
87}
88kbd {
89 font-family: var(--mono);
90 font-size: 12px;
91 line-height: 1.4;
92 padding: 1px 7px;
93 border-radius: 6px;
94 border: 1px solid var(--line-2);
95 border-bottom-width: 2px;
96 color: var(--dim);
97 background: rgba(255, 255, 255, 0.04);
98}
99
100/* ---------- stage ---------- */
101.stage {
102 position: absolute;
103 left: 0;
104 top: 0;
105 width: 1920px;
106 height: 1080px;
107 transform-origin: 0 0;
108 padding: 26px 44px 30px;
109 display: grid;
110 grid-template-rows: 64px minmax(0, 1fr) 196px;
111 grid-template-areas: 'bar' 'main' 'dock';
112 gap: 22px;
113 overflow: hidden;
114 background:
115 radial-gradient(1100px 620px at 16% -12%, rgba(55, 91, 210, 0.22), transparent 62%),
116 radial-gradient(900px 560px at 104% 112%, rgba(55, 91, 210, 0.12), transparent 60%),
117 var(--bg);
118}
119
120/* ---------- top bar ---------- */
121.bar {
122 grid-area: bar;
123 display: grid;
124 grid-template-columns: auto minmax(0, 1fr) auto;
125 align-items: center;
126 gap: 28px;
127}
128.brand {
129 display: flex;
130 align-items: center;
131 gap: 16px;
132}
133.brand .mark {
134 width: 50px;
135 height: 50px;
136 flex: none;
137}
138.brand-name {
139 font-size: 29px;
140 font-weight: 760;
141 letter-spacing: -0.01em;
142 line-height: 1.1;
143}
144.brand-sub {
145 margin-top: 3px;
146 font-size: 16px;
147 color: var(--dim);
148}
149.status {
150 justify-self: center;
151 display: flex;
152 align-items: center;
153 gap: 16px;
154}
155.pill {
156 display: inline-flex;
157 align-items: center;
158 gap: 10px;
159 padding: 9px 18px 9px 16px;
160 border-radius: 999px;
161 font-size: 18px;
162 font-weight: 650;
163 white-space: nowrap;
164 background: var(--accent-soft);
165 color: #e3e9ff;
166 border: 1px solid rgba(138, 163, 255, 0.5);
167}
168.pill .dot {
169 width: 10px;
170 height: 10px;
171 border-radius: 50%;
172 color: var(--accent-hi);
173 background: currentColor;
174 animation: beacon 2s ease-out infinite;
175}
176.pill.connecting,
177.pill.down {
178 background: var(--warn-soft);
179 color: var(--warn);
180 border-color: rgba(245, 185, 66, 0.38);
181}
182.pill.connecting .dot,
183.pill.down .dot {
184 color: inherit;
185}
186/* a replay is not live: a hollow, still dot */
187.pill.replay .dot {
188 animation: none;
189 background: transparent;
190 box-shadow: inset 0 0 0 2px currentColor;
191}
192.blk {
193 display: inline-flex;
194 align-items: baseline;
195 gap: 8px;
196 font-size: 15px;
197 color: var(--faint);
198 white-space: nowrap;
199}
200.blk-n {
201 font-family: var(--mono);
202 font-size: 19px;
203 font-weight: 600;
204 color: var(--fg);
205 font-variant-numeric: tabular-nums;
206}
207.bar-r {
208 display: flex;
209 align-items: center;
210 gap: 22px;
211}
212.cre {
213 display: flex;
214 align-items: center;
215 gap: 10px;
216}
217:root:lang(zh-CN) .cre-by,
218:root:lang(zh-TW) .cre-by {
219 font-size: 16px;
220 letter-spacing: 0.04em;
221}
222.cre-by {
223 font-size: 13px;
224 font-weight: 700;
225 letter-spacing: 0.12em;
226 text-transform: uppercase;
227 color: var(--faint);
228}
229.cre-logo {
230 display: inline-flex;
231 align-items: center;
232 gap: 8px;
233 padding: 8px 14px 8px 11px;
234 border-radius: 12px;
235 background: rgba(55, 91, 210, 0.18);
236 border: 1px solid rgba(55, 91, 210, 0.6);
237 font-size: 18px;
238 white-space: nowrap;
239}
240.cre-logo .hex {
241 font-size: 24px;
242 color: var(--accent-hi);
243}
244.cre-logo span {
245 color: var(--accent-hi);
246 font-weight: 750;
247}
248.ctl {
249 display: flex;
250 align-items: center;
251 gap: 10px;
252}
253.seg {
254 display: flex;
255 padding: 3px;
256 border-radius: 11px;
257 background: var(--panel);
258 border: 1px solid var(--line);
259}
260.seg button {
261 font-size: 15px;
262 color: var(--dim);
263 background: none;
264 border: 0;
265 padding: 6px 11px;
266 border-radius: 8px;
267 cursor: pointer;
268}
269.seg button.on {
270 background: var(--panel-2);
271 color: var(--fg);
272 box-shadow: inset 0 0 0 1px var(--line-2);
273}
274.btn {
275 font-size: 15px;
276 color: var(--dim);
277 background: var(--panel);
278 border: 1px solid var(--line);
279 border-radius: 11px;
280 padding: 8px 14px;
281 cursor: pointer;
282 white-space: nowrap;
283}
284.btn.sq {
285 width: 40px;
286 padding: 8px 0;
287 text-align: center;
288 font-weight: 750;
289}
290.btn.on,
291.btn:hover,
292.seg button:hover {
293 color: var(--fg);
294 border-color: var(--line-2);
295}
296:focus-visible {
297 outline: 2px solid var(--accent-hi);
298 outline-offset: 2px;
299}
300
301/* ---------- main row ---------- */
302.main {
303 grid-area: main;
304 display: grid;
305 grid-template-columns: minmax(0, 1fr) 600px;
306 gap: 22px;
307 min-height: 0;
308}
309.hero,
310.verdict {
311 min-height: 0;
312 border-radius: 26px;
313 border: 1px solid var(--line);
314 background: linear-gradient(180deg, rgba(19, 28, 51, 0.92), rgba(12, 18, 34, 0.92));
315 box-shadow: 0 24px 60px rgba(0, 0, 0, 0.35);
316}
317.hero {
318 padding: 26px 36px 26px;
319 display: flex;
320 flex-direction: column;
321}
322
323/* hero: which proposal */
324.h-eyebrow {
325 display: flex;
326 align-items: center;
327 gap: 14px;
328 min-height: 28px;
329 font-size: 16px;
330 font-weight: 750;
331 letter-spacing: 0.12em;
332 text-transform: uppercase;
333 color: var(--accent-hi);
334}
335:root:lang(zh-CN) .h-eyebrow,
336:root:lang(zh-TW) .h-eyebrow {
337 letter-spacing: 0.05em;
338}
339.tag {
340 display: inline-flex;
341 align-items: center;
342 gap: 7px;
343 padding: 4px 11px;
344 border-radius: 8px;
345 font-size: 13px;
346 letter-spacing: 0.06em;
347 white-space: nowrap;
348}
349.tag.replay {
350 background: var(--accent-soft);
351 color: var(--accent-hi);
352 border: 1px solid rgba(138, 163, 255, 0.35);
353}
354.tag.warn {
355 background: var(--warn-soft);
356 color: var(--warn);
357}
358/* a past proposal's real state on chain, dated */
359.tag.state {
360 color: var(--dim);
361 border: 1px solid var(--line-2);
362 letter-spacing: 0.04em;
363}
364.h-off {
365 color: var(--accent-hi);
366 font-weight: 700;
367 text-decoration: underline;
368 text-underline-offset: 3px;
369}
370.h-title {
371 margin: 6px 0 0;
372 font-size: 52px;
373 line-height: 1.1;
374 font-weight: 780;
375 letter-spacing: -0.02em;
376}
377.h-desc {
378 margin: 8px 0 0;
379 font-size: 22px;
380 line-height: 1.35;
381 color: var(--dim);
382}
383
384/* hero: the airlock picture */
385.lockwrap {
386 position: relative;
387 margin-top: 22px;
388 height: var(--lk-h);
389 flex: none;
390}
391.lockbox {
392 height: 100%;
393}
394.lk {
395 height: 100%;
396 display: grid;
397 grid-template-columns: var(--owner-w) var(--door-w) minmax(0, 1fr) var(--door-w) var(--dest-w);
398 gap: var(--lk-gap);
399}
400.lk-owner {
401 position: relative;
402 display: flex;
403 flex-direction: column;
404 align-items: center;
405 justify-content: center;
406 gap: 4px;
407 text-align: center;
408 color: var(--dim);
409}
410.lk-owner .ic {
411 font-size: 40px;
412 color: var(--dim);
413 margin-bottom: 6px;
414}
415.lk-owner b {
416 font-size: 18px;
417 color: var(--fg);
418}
419.lk-owner small {
420 font-size: 15px;
421}
422.lk-path {
423 position: absolute;
424 top: 50%;
425 right: calc(-1 * var(--lk-gap));
426 width: calc(var(--lk-gap) + 10px);
427 border-top: 2px dashed var(--line-2);
428}
429.lk-door {
430 position: relative;
431 border-radius: 14px;
432 border: 2px solid var(--line-2);
433 background: #060a15;
434 overflow: hidden;
435 transition:
436 border-color 0.5s,
437 box-shadow 0.5s;
438}
439.lf {
440 position: absolute;
441 left: 5px;
442 right: 5px;
443 height: calc(50% - 5px);
444 border-radius: 8px;
445 border: 1px solid rgba(160, 178, 222, 0.28);
446 background: repeating-linear-gradient(135deg, #1d2a48 0 9px, #17223d 9px 18px);
447}
448.lf.t {
449 top: 5px;
450}
451.lf.b {
452 bottom: 5px;
453}
454.ph-executed .lk-inner .lf.t {
455 transform: translateY(-88%);
456}
457.ph-executed .lk-inner .lf.b {
458 transform: translateY(88%);
459}
460.lk-lock {
461 position: absolute;
462 left: 50%;
463 top: 50%;
464 transform: translate(-50%, -50%);
465 width: 48px;
466 height: 48px;
467 border-radius: 50%;
468 display: grid;
469 place-items: center;
470 font-size: 26px;
471 color: var(--dim);
472 background: #0a1122;
473 border: 2px solid var(--line-2);
474 box-shadow: 0 6px 18px rgba(0, 0, 0, 0.5);
475}
476.ph-cleared .lk-inner,
477.ph-ready .lk-inner,
478.ph-executed .lk-inner {
479 border-color: rgba(47, 211, 142, 0.7);
480 box-shadow: 0 0 34px rgba(47, 211, 142, 0.25);
481}
482.ph-cleared .lk-lock,
483.ph-ready .lk-lock {
484 color: var(--good-hi);
485 border-color: var(--good);
486 box-shadow: 0 0 22px rgba(47, 211, 142, 0.5);
487}
488.ph-executed .lk-lock {
489 opacity: 0;
490}
491.ph-ejected .lk-inner {
492 border-color: rgba(255, 77, 94, 0.7);
493 box-shadow: 0 0 34px rgba(255, 77, 94, 0.22);
494}
495.ph-ejected .lk-lock {
496 color: var(--bad-hi);
497 border-color: var(--bad);
498}
499.ph-waiting .lk-lock {
500 color: var(--warn);
501 border-color: var(--warn);
502}
503
504.lk-ch {
505 position: relative;
506 border-radius: 20px;
507 border: 2px solid var(--line-2);
508 overflow: hidden;
509 background:
510 radial-gradient(ellipse at 50% 0%, rgba(55, 91, 210, 0.18), transparent 70%),
511 #070c19;
512 transition:
513 border-color 0.5s,
514 background 0.5s;
515}
516.lk-grid {
517 position: absolute;
518 inset: 0;
519 background-image:
520 linear-gradient(rgba(138, 163, 255, 0.06) 1px, transparent 1px),
521 linear-gradient(90deg, rgba(138, 163, 255, 0.06) 1px, transparent 1px);
522 background-size: 28px 28px;
523}
524.ph-chamber .lk-ch {
525 border-color: rgba(138, 163, 255, 0.5);
526}
527.ph-cleared .lk-ch,
528.ph-ready .lk-ch {
529 border-color: rgba(47, 211, 142, 0.55);
530 background:
531 radial-gradient(ellipse at 50% 0%, rgba(47, 211, 142, 0.16), transparent 70%),
532 #061210;
533}
534.ph-executed .lk-ch {
535 border-color: rgba(47, 211, 142, 0.35);
536}
537.ph-waiting .lk-ch {
538 border-color: rgba(245, 185, 66, 0.5);
539}
540.ph-ejected .lk-ch {
541 border-color: rgba(255, 77, 94, 0.6);
542 background:
543 radial-gradient(ellipse at 50% 45%, rgba(255, 77, 94, 0.18), transparent 70%),
544 #10070d;
545}
546.lk-rail {
547 position: absolute;
548 left: 24px;
549 right: 24px;
550 bottom: 22px;
551 height: 8px;
552 border-radius: 99px;
553 background: rgba(160, 178, 222, 0.14);
554}
555.lk-fill {
556 position: absolute;
557 left: 0;
558 top: 0;
559 bottom: 0;
560 width: calc(var(--p, 0) * 100%);
561 border-radius: inherit;
562 background: linear-gradient(90deg, rgba(55, 91, 210, 0.6), var(--accent-hi));
563 transition: width 0.8s cubic-bezier(0.3, 0.7, 0.3, 1);
564}
565.ph-cleared .lk-fill,
566.ph-ready .lk-fill,
567.ph-executed .lk-fill {
568 background: linear-gradient(90deg, rgba(47, 211, 142, 0.5), var(--good-hi));
569}
570.ph-ejected .lk-fill {
571 background: linear-gradient(90deg, rgba(255, 77, 94, 0.45), var(--bad));
572}
573.lk-x {
574 position: absolute;
575 top: 50%;
576 left: calc(var(--p, 0) * 100%);
577 transform: translate(-50%, -50%);
578 width: 30px;
579 height: 30px;
580 border-radius: 50%;
581 display: none;
582 place-items: center;
583 font-size: 16px;
584 color: #fff;
585 background: var(--bad);
586 box-shadow: 0 0 18px rgba(255, 77, 94, 0.7);
587}
588.ph-ejected .lk-x {
589 display: grid;
590}
591.cap-in {
592 position: absolute;
593 bottom: 46px;
594 left: calc(24px + var(--p, 0) * (100% - 48px - var(--cap-w)));
595 width: var(--cap-w);
596 height: var(--cap-h);
597 transition: left 0.8s cubic-bezier(0.3, 0.7, 0.3, 1);
598}
599.cap-out {
600 width: 100%;
601 height: 100%;
602}
603.lk-cap {
604 width: 100%;
605 height: 100%;
606 display: flex;
607 align-items: center;
608 justify-content: center;
609 gap: 10px;
610 padding: 0 14px;
611 border-radius: 16px;
612 background: linear-gradient(180deg, #1c2b55, #142044);
613 border: 2px solid rgba(138, 163, 255, 0.7);
614 box-shadow:
615 0 12px 30px rgba(0, 0, 0, 0.45),
616 0 0 26px rgba(55, 91, 210, 0.4);
617 font-size: 21px;
618 font-weight: 720;
619 white-space: nowrap;
620}
621.lk-cap .ic {
622 font-size: 22px;
623 color: var(--accent-hi);
624}
625.ph-cleared .lk-cap,
626.ph-ready .lk-cap,
627.ph-executed .lk-cap {
628 border-color: var(--good);
629 background: linear-gradient(180deg, #11402f, #0c2f22);
630 box-shadow:
631 0 12px 30px rgba(0, 0, 0, 0.45),
632 0 0 26px rgba(47, 211, 142, 0.4);
633}
634.ph-cleared .lk-cap .ic,
635.ph-ready .lk-cap .ic,
636.ph-executed .lk-cap .ic {
637 color: var(--good-hi);
638}
639.ph-ejected .lk-cap {
640 border-color: var(--bad);
641 background: linear-gradient(180deg, #4a1220, #330b16);
642 box-shadow: 0 0 26px rgba(255, 77, 94, 0.45);
643}
644.ph-ejected .lk-cap .ic {
645 color: #fff;
646}
647.ph-ejected .cap-out,
648.ph-executed .cap-out {
649 opacity: 0;
650}
651.lk-scan {
652 position: absolute;
653 top: 0;
654 bottom: 0;
655 left: -180px;
656 width: 160px;
657 opacity: 0;
658 background: linear-gradient(90deg, transparent, rgba(47, 211, 142, 0.28), rgba(99, 240, 180, 0.6), transparent);
659}
660.lk-flash {
661 position: absolute;
662 inset: 0;
663 opacity: 0;
664 background: radial-gradient(ellipse at 50% 60%, rgba(255, 77, 94, 0.6), rgba(255, 77, 94, 0.08) 72%);
665}
666.lk-dest {
667 display: flex;
668 flex-direction: column;
669 align-items: center;
670 justify-content: center;
671 gap: 8px;
672 padding: 14px;
673 text-align: center;
674 border-radius: 20px;
675 border: 2px solid var(--line);
676 background: rgba(9, 14, 28, 0.75);
677 transition:
678 border-color 0.5s,
679 background 0.5s;
680}
681.lk-dest .ic {
682 font-size: 42px;
683 color: var(--dim);
684 margin-bottom: 4px;
685}
686.lk-dest b {
687 font-size: 18px;
688}
689.lk-dest small {
690 font-size: 16px;
691 color: var(--dim);
692 line-height: 1.3;
693}
694.ph-executed .lk-dest {
695 border-color: var(--good);
696 background: var(--good-soft);
697 box-shadow: 0 0 34px rgba(47, 211, 142, 0.22);
698}
699.ph-executed .lk-dest .ic,
700.ph-executed .lk-dest small {
701 color: var(--good-hi);
702}
703.ph-ejected .lk-dest small {
704 color: var(--good-hi);
705}
706
707/* hero: numbers in the chamber */
708.count {
709 position: absolute;
710 top: 0;
711 left: calc(var(--owner-w) + var(--door-w) + 2 * var(--lk-gap));
712 right: calc(var(--dest-w) + var(--door-w) + 2 * var(--lk-gap));
713 height: calc(100% - 104px);
714 display: flex;
715 align-items: center;
716 justify-content: center;
717 pointer-events: none;
718}
719.cn {
720 display: flex;
721 flex-direction: column;
722 align-items: center;
723 gap: 6px;
724 text-align: center;
725}
726.cn.ph-ejected,
727.cn.ph-executed,
728.cn.ph-ready,
729.cn.ph-waiting {
730 transform: translateY(26px);
731}
732.cn-num {
733 display: flex;
734 align-items: baseline;
735 gap: 12px;
736}
737.cn-num b {
738 font-size: 84px;
739 line-height: 1;
740 font-weight: 800;
741 letter-spacing: -0.03em;
742 font-variant-numeric: tabular-nums;
743}
744.cn-num span {
745 font-size: 24px;
746 font-weight: 650;
747 color: var(--dim);
748}
749.cn-eta {
750 display: flex;
751 align-items: center;
752 gap: 9px;
753 font-family: var(--mono);
754 font-size: 22px;
755 font-variant-numeric: tabular-nums;
756}
757.cn-eta .ic {
758 color: var(--accent-hi);
759}
760.cn-of {
761 font-family: var(--sans);
762 font-size: 17px;
763 color: var(--dim);
764}
765.cn-tag {
766 margin-top: 4px;
767 display: inline-flex;
768 align-items: center;
769 gap: 8px;
770 padding: 5px 14px;
771 border-radius: 999px;
772 font-size: 17px;
773 font-weight: 650;
774}
775.cn-tag.await {
776 background: var(--accent-soft);
777 color: var(--accent-hi);
778}
779.cn-tag.good {
780 background: var(--good-soft);
781 color: var(--good-hi);
782}
783/* a replay: the CRE workflow step the verdict card is on, and the fast-forwarded cooldown */
784.cn-tag.step .spin {
785 flex: none;
786 width: 14px;
787 height: 14px;
788 border-width: 2px;
789}
790.cn-tag.ff {
791 background: var(--accent-soft);
792 color: var(--accent-hi);
793 border: 1px solid rgba(138, 163, 255, 0.35);
794}
795.nw {
796 white-space: nowrap;
797}
798.cn-tag.step span {
799 text-wrap: balance;
800}
801.cn-rp {
802 font-size: 14px;
803 letter-spacing: 0.04em;
804 color: var(--faint);
805}
806.cn-word {
807 display: flex;
808 align-items: center;
809 gap: 12px;
810 font-size: 44px;
811 font-weight: 800;
812}
813.cn-word.good {
814 color: var(--good-hi);
815}
816.cn-word .ic {
817 font-size: 0.82em;
818 stroke-width: 2.6;
819}
820/* the end state of an honest upgrade: as big as a veto's stamp */
821.cn.ph-executed .cn-word {
822 font-size: 58px;
823 letter-spacing: -0.01em;
824}
825.cn-word.warn {
826 color: var(--warn);
827}
828.cn-stamp {
829 font-size: 72px;
830 line-height: 1.05;
831 font-weight: 900;
832 letter-spacing: 0.08em;
833 text-transform: uppercase;
834 color: var(--bad);
835 border: 6px solid var(--bad);
836 border-radius: 18px;
837 padding: 4px 30px 8px 36px;
838 transform: rotate(-4deg);
839 text-shadow: 0 0 30px rgba(255, 77, 94, 0.5);
840 box-shadow:
841 0 0 40px rgba(255, 77, 94, 0.25),
842 inset 0 0 30px rgba(255, 77, 94, 0.18);
843 background: rgba(16, 7, 13, 0.6);
844}
845.cn-sub {
846 font-size: 20px;
847 color: var(--dim);
848 margin-top: 6px;
849}
850/* the operator's launch on its way: its transaction under the waiting line */
851.cn-tx {
852 margin-top: 12px;
853 font-size: 18px;
854}
855/* first-visit intro and a replay's lead-in: one calm line in the empty chamber */
856.cn-sub.intro,
857.cn-sub.arriving {
858 display: inline-flex;
859 align-items: center;
860 gap: 12px;
861 font-size: 24px;
862 font-weight: 600;
863 color: var(--accent-hi);
864}
865.cn-sub.arriving {
866 animation: pulse-text 1.4s ease-in-out infinite;
867}
868@keyframes pulse-text {
869 0%,
870 100% {
871 opacity: 1;
872 }
873 50% {
874 opacity: 0.55;
875 }
876}
877/* the clearance's stamp: green, upright, on its own layer over the countdown for a moment (ui.ts h-stamp) */
878.stampbox {
879 pointer-events: none;
880}
881.cn-stamp.good {
882 color: var(--good-hi);
883 border-color: var(--good);
884 transform: none;
885 text-shadow: 0 0 30px rgba(47, 211, 142, 0.5);
886 box-shadow:
887 0 0 40px rgba(47, 211, 142, 0.28),
888 inset 0 0 30px rgba(47, 211, 142, 0.16);
889 background: rgba(6, 18, 16, 0.85);
890}
891.cstamp .cn-stamp.good {
892 animation: clear-stamp 1.8s cubic-bezier(0.2, 1.2, 0.4, 1) calc(var(--d-clear, 0ms) + 300ms) both;
893}
894.lockwrap.stamping #h-count {
895 animation: count-hide 2s ease-in-out calc(var(--d-clear, 0ms) + 250ms) both;
896}
897@keyframes clear-stamp {
898 0% {
899 opacity: 0;
900 transform: scale(1.8);
901 }
902 16%,
903 78% {
904 opacity: 1;
905 transform: scale(1);
906 }
907 100% {
908 opacity: 0;
909 transform: scale(1.04);
910 }
911}
912@keyframes count-hide {
913 0%,
914 100% {
915 opacity: 1;
916 }
917 12%,
918 80% {
919 opacity: 0;
920 }
921}
922
923/* hero: the doors in words */
924.doors {
925 display: grid;
926 grid-template-columns: repeat(3, minmax(0, 1fr));
927 gap: var(--lk-gap);
928 margin-top: 14px;
929}
930.dl {
931 display: flex;
932 flex-direction: column;
933 gap: 3px;
934 min-width: 0;
935}
936.dl.c {
937 align-items: center;
938 text-align: center;
939}
940.dl.r {
941 align-items: flex-end;
942 text-align: right;
943}
944.dl-k {
945 font-size: 14px;
946 font-weight: 750;
947 letter-spacing: 0.12em;
948 text-transform: uppercase;
949 color: var(--faint);
950}
951:root:lang(zh-CN) .dl-k,
952:root:lang(zh-TW) .dl-k {
953 font-size: 16px;
954 letter-spacing: 0.04em;
955}
956.dl-v {
957 font-size: 19px;
958 line-height: 1.3;
959}
960.dl-v.good {
961 color: var(--good-hi);
962}
963.dl-v.bad {
964 color: var(--bad-hi);
965}
966.dl-v.warn {
967 color: var(--warn);
968}
969
970/* hero: the sentence */
971.banner-slot {
972 margin-top: auto;
973 padding-top: 16px;
974}
975.banner {
976 display: flex;
977 align-items: center;
978 gap: 16px;
979 padding: 15px 22px;
980 border-radius: 18px;
981 background: var(--panel-2);
982 border: 1px solid var(--line);
983 font-size: 27px;
984 font-weight: 720;
985 line-height: 1.25;
986}
987.bn-t {
988 flex: 1 1 180px;
989 min-width: 0;
990}
991.bn-i {
992 display: grid;
993 place-items: center;
994 font-size: 32px;
995 color: var(--dim);
996}
997.banner.ph-chamber {
998 background: linear-gradient(90deg, rgba(55, 91, 210, 0.24), rgba(55, 91, 210, 0.06));
999 border-color: rgba(138, 163, 255, 0.4);
1000}
1001.banner.ph-chamber .bn-i {
1002 color: var(--accent-hi);
1003}
1004.banner.ph-cleared,
1005.banner.ph-ready,
1006.banner.ph-executed {
1007 background: linear-gradient(90deg, rgba(47, 211, 142, 0.22), rgba(47, 211, 142, 0.05));
1008 border-color: rgba(47, 211, 142, 0.45);
1009}
1010.banner.ph-cleared .bn-i,
1011.banner.ph-ready .bn-i,
1012.banner.ph-executed .bn-i {
1013 color: var(--good-hi);
1014}
1015.banner.ph-waiting {
1016 background: linear-gradient(90deg, rgba(245, 185, 66, 0.2), rgba(245, 185, 66, 0.04));
1017 border-color: rgba(245, 185, 66, 0.4);
1018}
1019.banner.ph-waiting .bn-i {
1020 color: var(--warn);
1021}
1022.banner.ph-ejected {
1023 background: linear-gradient(90deg, rgba(255, 77, 94, 0.26), rgba(255, 77, 94, 0.06));
1024 border-color: rgba(255, 77, 94, 0.55);
1025}
1026.banner.ph-ejected .bn-i {
1027 color: var(--bad-hi);
1028}
1029.bn-rule {
1030 margin-left: auto;
1031 display: inline-flex;
1032 align-items: center;
1033 gap: 10px;
1034 padding: 7px 14px;
1035 border-radius: 12px;
1036 background: rgba(255, 77, 94, 0.16);
1037 border: 1px solid rgba(255, 77, 94, 0.45);
1038 font-size: 20px;
1039 font-weight: 650;
1040 color: #ffd9dd;
1041 white-space: nowrap;
1042}
1043.bn-rule b {
1044 font-family: var(--mono);
1045 color: #fff;
1046}
1047
1048/* ---------- verdict card ---------- */
1049.verdict {
1050 padding: 24px 30px 22px;
1051 display: flex;
1052 flex-direction: column;
1053 gap: 12px;
1054}
1055.v-head {
1056 display: flex;
1057 align-items: center;
1058 gap: 12px;
1059}
1060.v-head .hex {
1061 font-size: 30px;
1062 color: var(--accent-hi);
1063}
1064.v-head h2 {
1065 margin: 0;
1066 font-size: 22px;
1067 font-weight: 750;
1068 letter-spacing: 0.01em;
1069}
1070.v-head .v-rp {
1071 margin-left: auto;
1072}
1073.vm {
1074 display: flex;
1075 flex-direction: column;
1076 gap: 8px;
1077}
1078.v-verdict {
1079 display: flex;
1080 align-items: center;
1081 gap: 16px;
1082}
1083.v-chip {
1084 display: inline-flex;
1085 align-items: center;
1086 gap: 10px;
1087 padding: 6px 22px 6px 16px;
1088 border-radius: 14px;
1089 font-size: 40px;
1090 font-weight: 850;
1091 letter-spacing: 0.04em;
1092 text-transform: uppercase;
1093 line-height: 1.15;
1094}
1095.v-chip .ic {
1096 font-size: 34px;
1097 stroke-width: 3;
1098}
1099.v-chip.veto {
1100 background: var(--bad);
1101 color: #fff;
1102 box-shadow: 0 0 40px rgba(255, 77, 94, 0.35);
1103}
1104.v-chip.clear {
1105 background: var(--good);
1106 color: #03251a;
1107 box-shadow: 0 0 40px rgba(47, 211, 142, 0.35);
1108}
1109.v-chip.await {
1110 font-size: 30px;
1111 background: var(--accent-soft);
1112 color: var(--accent-hi);
1113 border: 1px solid rgba(138, 163, 255, 0.4);
1114}
1115.v-chip.none {
1116 font-size: 30px;
1117 background: var(--panel-2);
1118 color: var(--faint);
1119}
1120.spin {
1121 width: 22px;
1122 height: 22px;
1123 border-radius: 50%;
1124 border: 3px solid rgba(138, 163, 255, 0.3);
1125 border-top-color: var(--accent-hi);
1126 animation: spin 1s linear infinite;
1127}
1128.v-code {
1129 font-family: var(--mono);
1130 font-size: 40px;
1131 font-weight: 800;
1132}
1133.v-rule {
1134 margin: 0;
1135 font-size: 22px;
1136 line-height: 1.36;
1137}
1138.v-time {
1139 margin: 0;
1140 font-size: 19px;
1141 color: var(--dim);
1142}
1143.v-time b {
1144 font-size: 25px;
1145 color: var(--fg);
1146 font-variant-numeric: tabular-nums;
1147}
1148
1149.pipe {
1150 list-style: none;
1151 margin: 4px 0 0;
1152 padding: 0;
1153 display: flex;
1154 flex-direction: column;
1155 gap: 6px;
1156}
1157.pipe li {
1158 position: relative;
1159 display: flex;
1160 align-items: center;
1161 gap: 16px;
1162 padding: 7px 12px;
1163 border-radius: 12px;
1164}
1165.pipe li + li::before {
1166 content: '';
1167 position: absolute;
1168 left: 27px;
1169 top: -30px;
1170 height: 50px;
1171 border-left: 2px solid var(--line-2);
1172}
1173.pi-dot {
1174 position: relative;
1175 z-index: 1;
1176 flex: none;
1177 width: 32px;
1178 height: 32px;
1179 border-radius: 50%;
1180 display: grid;
1181 place-items: center;
1182 font-size: 17px;
1183 stroke-width: 3;
1184 border: 2px solid var(--line-2);
1185 color: transparent;
1186 background: #0a1020;
1187}
1188.pi-dot .ic {
1189 stroke-width: 3.2;
1190}
1191.pi-t b {
1192 display: block;
1193 font-size: 20px;
1194 font-weight: 680;
1195}
1196.pi-t small {
1197 display: block;
1198 margin-top: 2px;
1199 font-size: 16px;
1200 color: var(--dim);
1201}
1202/* the step that decided a fail-closed veto (R6) */
1203.pipe.st-done li.fail .pi-dot {
1204 background: var(--bad);
1205 border-color: var(--bad);
1206}
1207.pipe.st-done li.fail b {
1208 color: var(--bad-hi);
1209}
1210.pipe.st-done .pi-dot {
1211 background: var(--accent);
1212 border-color: var(--accent);
1213 color: #fff;
1214}
1215.pipe.st-done li + li::before {
1216 border-color: var(--accent);
1217}
1218.pipe.st-done.k-veto li:last-child {
1219 background: var(--bad-soft);
1220}
1221.pipe.st-done.k-veto li:last-child .pi-dot {
1222 background: var(--bad);
1223 border-color: var(--bad);
1224}
1225.pipe.st-done.k-veto li:last-child b {
1226 color: var(--bad-hi);
1227}
1228.pipe.st-done.k-clear li:last-child {
1229 background: var(--good-soft);
1230}
1231.pipe.st-done.k-clear li:last-child .pi-dot {
1232 background: var(--good);
1233 border-color: var(--good);
1234 color: #03251a;
1235}
1236.pipe.st-done.k-clear li:last-child b {
1237 color: var(--good-hi);
1238}
1239.pipe.st-run .pi-dot {
1240 border-color: rgba(138, 163, 255, 0.55);
1241 animation: running 2.2s ease-in-out infinite;
1242 animation-delay: calc(var(--i) * 0.28s);
1243}
1244.pipe.st-off {
1245 opacity: 0.45;
1246}
1247/* a replay walks through the steps until its verdict lands: done ones filled, the current one spinning, the rest dim */
1248.pipe.st-run.seq .pi-dot {
1249 animation: none;
1250}
1251.pipe.seq li {
1252 transition: opacity 0.35s ease, background-color 0.35s ease;
1253}
1254.pipe.seq li.ok .pi-dot {
1255 background: var(--accent);
1256 border-color: var(--accent);
1257 color: #fff;
1258}
1259.pipe.seq li.ok + li::before,
1260.pipe.seq li.cur::before {
1261 border-color: var(--accent);
1262}
1263.pipe.seq li.cur {
1264 background: rgba(55, 91, 210, 0.16);
1265}
1266.pipe.seq li.cur .pi-dot {
1267 border-color: var(--accent-hi);
1268 box-shadow: 0 0 0 6px rgba(138, 163, 255, 0.14);
1269}
1270.pipe.seq li.cur .pi-dot .spin {
1271 width: 18px;
1272 height: 18px;
1273 border-width: 2.5px;
1274}
1275.pipe.seq li.next {
1276 opacity: 0.45;
1277}
1278
1279.v-links {
1280 margin-top: auto;
1281 padding-top: 12px;
1282 border-top: 1px solid var(--line);
1283 display: grid;
1284 grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
1285 gap: 10px 18px;
1286}
1287.v-links:empty {
1288 display: none;
1289}
1290.lnk {
1291 display: flex;
1292 flex-direction: column;
1293 gap: 3px;
1294 min-width: 0;
1295}
1296.lnk > span:first-child {
1297 font-size: 13px;
1298 font-weight: 700;
1299 letter-spacing: 0.1em;
1300 text-transform: uppercase;
1301 color: var(--faint);
1302}
1303:root:lang(zh-CN) .lnk > span:first-child,
1304:root:lang(zh-TW) .lnk > span:first-child {
1305 font-size: 15px;
1306 letter-spacing: 0.04em;
1307}
1308.lnk .mono {
1309 font-size: 17px;
1310}
1311.lnk.wide {
1312 grid-column: 1 / -1;
1313}
1314.xl {
1315 display: inline-flex;
1316 align-items: center;
1317 gap: 6px;
1318 text-decoration: none;
1319 color: var(--accent-hi);
1320}
1321.xl:hover {
1322 text-decoration: underline;
1323}
1324.xl .ext {
1325 font-size: 0.85em;
1326 opacity: 0.8;
1327}
1328
1329/* ---------- strip ---------- */
1330.strip {
1331 grid-area: dock;
1332 display: flex;
1333 flex-direction: column;
1334 gap: 12px;
1335 min-height: 0;
1336}
1337.s-head {
1338 display: flex;
1339 align-items: center;
1340 gap: 18px;
1341}
1342.s-head h3 {
1343 margin: 0;
1344 font-size: 17px;
1345 font-weight: 750;
1346 letter-spacing: 0.1em;
1347 text-transform: uppercase;
1348 color: var(--dim);
1349}
1350:root:lang(zh-CN) .s-head h3,
1351:root:lang(zh-TW) .s-head h3 {
1352 letter-spacing: 0.04em;
1353}
1354.toggle {
1355 display: inline-flex;
1356 align-items: center;
1357 gap: 8px;
1358 padding: 5px 13px 5px 12px;
1359 border-radius: 999px;
1360 font-size: 15px;
1361 background: var(--panel);
1362 border: 1px solid var(--line);
1363 color: var(--faint);
1364 cursor: pointer;
1365}
1366.toggle .dot {
1367 width: 8px;
1368 height: 8px;
1369 border-radius: 50%;
1370 background: currentColor;
1371}
1372.toggle.on {
1373 color: var(--accent-hi);
1374 border-color: rgba(138, 163, 255, 0.5);
1375}
1376.s-hint {
1377 margin-left: auto;
1378 font-size: 15px;
1379 color: var(--faint);
1380}
1381.s-cards {
1382 flex: 1;
1383 min-height: 0;
1384 display: grid;
1385 grid-template-columns: repeat(var(--n), minmax(0, 1fr));
1386 gap: 14px;
1387}
1388.s-empty {
1389 grid-column: 1 / -1;
1390 display: grid;
1391 place-items: center;
1392 border: 1px dashed var(--line-2);
1393 border-radius: 18px;
1394 color: var(--faint);
1395 font-size: 18px;
1396}
1397.pc {
1398 position: relative;
1399 min-width: 0;
1400 display: flex;
1401 flex-direction: column;
1402 gap: 6px;
1403 padding: 15px 18px 14px;
1404 text-align: left;
1405 border-radius: 18px;
1406 background: var(--panel);
1407 border: 1px solid var(--line);
1408 cursor: pointer;
1409 transition:
1410 transform 0.2s,
1411 border-color 0.2s,
1412 background 0.2s,
1413 box-shadow 0.2s;
1414}
1415.pc::before {
1416 content: '';
1417 position: absolute;
1418 left: 18px;
1419 right: 18px;
1420 top: -1px;
1421 height: 3px;
1422 border-radius: 0 0 4px 4px;
1423 background: var(--line-2);
1424}
1425.pc.ph-ejected::before {
1426 background: var(--bad);
1427}
1428.pc.ph-executed::before,
1429.pc.ph-cleared::before,
1430.pc.ph-ready::before {
1431 background: var(--good);
1432}
1433.pc.ph-chamber::before {
1434 background: var(--accent-hi);
1435}
1436.pc.ph-waiting::before {
1437 background: var(--warn);
1438}
1439.pc:hover {
1440 border-color: var(--line-2);
1441 transform: translateY(-2px);
1442}
1443.pc.on {
1444 border-color: var(--accent-hi);
1445 background: linear-gradient(180deg, rgba(55, 91, 210, 0.26), rgba(55, 91, 210, 0.08));
1446 box-shadow:
1447 inset 0 0 0 1px var(--accent-hi),
1448 0 14px 34px rgba(55, 91, 210, 0.28);
1449}
1450.pc-top {
1451 display: flex;
1452 align-items: center;
1453 justify-content: space-between;
1454 gap: 8px;
1455}
1456.pc-id {
1457 font-family: var(--mono);
1458 font-size: 20px;
1459 font-weight: 700;
1460 color: var(--dim);
1461}
1462.pc-chip {
1463 padding: 3px 10px;
1464 border-radius: 999px;
1465 font-size: 13px;
1466 font-weight: 800;
1467 letter-spacing: 0.08em;
1468 text-transform: uppercase;
1469 white-space: nowrap;
1470 background: var(--panel-2);
1471 color: var(--dim);
1472}
1473.ph-ejected .pc-chip {
1474 background: var(--bad-soft);
1475 color: var(--bad-hi);
1476}
1477.ph-executed .pc-chip,
1478.ph-cleared .pc-chip,
1479.ph-ready .pc-chip {
1480 background: var(--good-soft);
1481 color: var(--good-hi);
1482}
1483.ph-chamber .pc-chip {
1484 background: var(--accent-soft);
1485 color: var(--accent-hi);
1486}
1487.ph-waiting .pc-chip {
1488 background: var(--warn-soft);
1489 color: var(--warn);
1490}
1491.pc-name {
1492 font-size: 22px;
1493 font-weight: 750;
1494 line-height: 1.2;
1495 white-space: nowrap;
1496 overflow: hidden;
1497 text-overflow: ellipsis;
1498}
1499.pc-name.long {
1500 font-size: 19px;
1501 line-height: 1.32;
1502}
1503.pc-line {
1504 font-size: 16px;
1505 line-height: 1.3;
1506 color: var(--dim);
1507 text-wrap: balance;
1508 display: -webkit-box;
1509 -webkit-box-orient: vertical;
1510 -webkit-line-clamp: 2;
1511 overflow: hidden;
1512}
1513.pc-line b,
1514.pc-foot b {
1515 color: var(--fg);
1516}
1517.pc-foot {
1518 margin-top: auto;
1519 font-size: 16px;
1520 color: var(--dim);
1521}
1522.pc-chip.rp {
1523 display: inline-flex;
1524 align-items: center;
1525 gap: 5px;
1526 background: var(--accent-soft);
1527 color: var(--accent-hi);
1528}
1529
1530/* ---------- attack picker (lab-ui.ts): the bottom row of the stage, or under the top bar on a phone ---------- */
1531.lab {
1532 grid-area: dock;
1533 display: flex;
1534 flex-direction: column;
1535 gap: 12px;
1536 min-height: 0;
1537}
1538.no-lab .lab {
1539 display: none;
1540}
1541.lab-head {
1542 display: flex;
1543 align-items: center;
1544 gap: 18px;
1545 min-height: 34px;
1546}
1547.lab-t {
1548 display: flex;
1549 align-items: baseline;
1550 gap: 16px;
1551 min-width: 0;
1552 flex: 0 1 auto;
1553}
1554.lab-t h3 {
1555 margin: 0;
1556 font-size: 24px;
1557 font-weight: 770;
1558 letter-spacing: -0.005em;
1559 white-space: nowrap;
1560}
1561.lab-t h3.invite {
1562 color: var(--accent-hi);
1563}
1564.lab-sub {
1565 min-width: 0;
1566 font-size: 16px;
1567 color: var(--dim);
1568 white-space: nowrap;
1569 overflow: hidden;
1570 text-overflow: ellipsis;
1571}
1572.lab-head.playing .lab-sub {
1573 display: none;
1574}
1575.lab-now {
1576 margin-left: auto;
1577 display: flex;
1578 align-items: center;
1579 gap: 14px;
1580 white-space: nowrap;
1581}
1582.lab-now .tag {
1583 font-size: 14px;
1584}
1585.lab-tx {
1586 display: inline-flex;
1587 align-items: baseline;
1588 gap: 8px;
1589 font-size: 15px;
1590 color: var(--faint);
1591}
1592.lab-tx .mono {
1593 font-size: 16px;
1594}
1595.tabs {
1596 flex: none;
1597 margin-left: auto;
1598}
1599.lab-now + .tabs,
1600.s-hint + .tabs {
1601 margin-left: 0;
1602}
1603.lab-cards {
1604 flex: 1;
1605 min-height: 0;
1606 display: grid;
1607 grid-template-columns: repeat(7, minmax(0, 1fr));
1608 gap: 14px;
1609}
1610.lc {
1611 position: relative;
1612 min-width: 0;
1613 display: flex;
1614 border-radius: 18px;
1615 background: var(--panel);
1616 border: 1px solid var(--line);
1617 transition:
1618 transform 0.2s,
1619 border-color 0.2s,
1620 background 0.2s,
1621 box-shadow 0.2s;
1622}
1623.lc::before {
1624 content: '';
1625 position: absolute;
1626 left: 18px;
1627 right: 18px;
1628 top: -1px;
1629 height: 3px;
1630 border-radius: 0 0 4px 4px;
1631 background: var(--bad);
1632}
1633.lc.k-clear::before {
1634 background: var(--good);
1635}
1636.lc:hover {
1637 border-color: var(--line-2);
1638 transform: translateY(-2px);
1639}
1640.lc.on {
1641 border-color: var(--accent-hi);
1642 background: linear-gradient(180deg, rgba(55, 91, 210, 0.3), rgba(55, 91, 210, 0.08));
1643 box-shadow:
1644 inset 0 0 0 1px var(--accent-hi),
1645 0 14px 34px rgba(55, 91, 210, 0.3);
1646}
1647.lc.live {
1648 border-color: rgba(138, 163, 255, 0.55);
1649}
1650.lc.none {
1651 opacity: 0.55;
1652}
1653.lc.none:hover {
1654 transform: none;
1655}
1656.lc-main {
1657 flex: 1;
1658 min-width: 0;
1659 display: flex;
1660 flex-direction: column;
1661 gap: 5px;
1662 padding: 14px 16px 13px;
1663 text-align: left;
1664 color: inherit;
1665 background: none;
1666 border: 0;
1667 border-radius: inherit;
1668 cursor: pointer;
1669}
1670.lc-main:disabled {
1671 cursor: default;
1672}
1673.lc-top {
1674 display: flex;
1675 align-items: center;
1676 justify-content: space-between;
1677 gap: 8px;
1678 min-height: 25px;
1679}
1680.lc.has-op .lc-top {
1681 padding-right: 36px;
1682}
1683.lc-code {
1684 display: inline-flex;
1685 align-items: center;
1686 gap: 5px;
1687 padding: 2px 9px;
1688 border-radius: 8px;
1689 font-family: var(--mono);
1690 font-size: 15px;
1691 font-weight: 800;
1692 white-space: nowrap;
1693}
1694.lc-code.veto {
1695 background: var(--bad-soft);
1696 color: var(--bad-hi);
1697}
1698.lc-code.clear {
1699 font-family: var(--sans);
1700 font-size: 14px;
1701 background: var(--good-soft);
1702 color: var(--good-hi);
1703}
1704.lc-ref {
1705 font-size: 15px;
1706 font-weight: 650;
1707 color: var(--faint);
1708}
1709.lc-live {
1710 display: inline-flex;
1711 align-items: center;
1712 gap: 6px;
1713 padding: 2px 9px;
1714 border-radius: 999px;
1715 font-size: 13px;
1716 font-weight: 800;
1717 letter-spacing: 0.06em;
1718 white-space: nowrap;
1719 background: var(--accent-soft);
1720 color: var(--accent-hi);
1721}
1722.lc-live .dot {
1723 width: 7px;
1724 height: 7px;
1725 border-radius: 50%;
1726 color: var(--accent-hi);
1727 background: currentColor;
1728 animation: beacon 2s ease-out infinite;
1729}
1730.lc-name {
1731 font-size: 22px;
1732 font-weight: 760;
1733 line-height: 1.2;
1734 white-space: nowrap;
1735 overflow: hidden;
1736 text-overflow: ellipsis;
1737}
1738.lc-line {
1739 font-size: 15px;
1740 line-height: 1.32;
1741 color: var(--dim);
1742 text-wrap: pretty;
1743 display: -webkit-box;
1744 -webkit-box-orient: vertical;
1745 -webkit-line-clamp: 2;
1746 overflow: hidden;
1747}
1748.lc-foot {
1749 margin-top: auto;
1750 min-height: 22px;
1751 display: flex;
1752 flex-direction: column;
1753 justify-content: flex-end;
1754 gap: 7px;
1755}
1756.lc-cta {
1757 display: inline-flex;
1758 align-items: center;
1759 gap: 7px;
1760 font-size: 15px;
1761 font-weight: 700;
1762 color: var(--accent-hi);
1763}
1764.lc-cta .ic {
1765 font-size: 14px;
1766}
1767.lc-cta.dim {
1768 font-weight: 500;
1769 color: var(--faint);
1770}
1771.lc-prog {
1772 height: 4px;
1773 border-radius: 4px;
1774 background: rgba(138, 163, 255, 0.16);
1775 overflow: hidden;
1776}
1777.lc-prog i {
1778 display: block;
1779 height: 100%;
1780 background: var(--accent-hi);
1781 transform-origin: 0 50%;
1782 transform: scaleX(var(--lab-f, 0));
1783}
1784.lc-stage {
1785 display: flex;
1786 align-items: center;
1787 gap: 7px;
1788 min-width: 0;
1789 font-size: 14px;
1790 font-weight: 700;
1791 white-space: nowrap;
1792}
1793.lc-stage > span:not(.lc-steps) {
1794 overflow: hidden;
1795 text-overflow: ellipsis;
1796}
1797.lc-stage .ic {
1798 flex: none;
1799 font-size: 14px;
1800 color: var(--accent-hi);
1801}
1802.lc-stage .spin {
1803 flex: none;
1804 width: 13px;
1805 height: 13px;
1806 border-width: 2px;
1807}
1808.lc-stage.st-veto .ic {
1809 color: var(--bad-hi);
1810}
1811.lc-stage.st-clear .ic,
1812.lc-stage.st-exec .ic {
1813 color: var(--good-hi);
1814}
1815.lc-steps {
1816 flex: none;
1817 margin-left: auto;
1818 display: flex;
1819 gap: 4px;
1820}
1821.lc-steps i {
1822 width: 6px;
1823 height: 6px;
1824 border-radius: 50%;
1825 background: var(--line-2);
1826}
1827.lc-steps i.done {
1828 background: var(--accent-hi);
1829}
1830.lc-steps i.cur {
1831 background: #fff;
1832 box-shadow: 0 0 0 3px rgba(138, 163, 255, 0.35);
1833}
1834/* the operator's launch button on a card (operator mode only) */
1835.lc-op {
1836 position: absolute;
1837 top: 11px;
1838 right: 11px;
1839 display: inline-grid;
1840 place-items: center;
1841 width: 30px;
1842 height: 30px;
1843 padding: 0;
1844 border-radius: 9px;
1845 font-size: 16px;
1846 color: var(--warn);
1847 background: var(--warn-soft);
1848 border: 1px solid rgba(245, 185, 66, 0.4);
1849 cursor: pointer;
1850}
1851.lc-op span {
1852 position: absolute;
1853 width: 1px;
1854 height: 1px;
1855 overflow: hidden;
1856 clip-path: inset(50%);
1857}
1858.lc-op:disabled {
1859 opacity: 0.4;
1860 cursor: not-allowed;
1861}
1862/* after the first-visit replay: the other cards glow twice, one after another, to invite a pick */
1863.lc.nudge {
1864 animation: nudge 1.4s ease-in-out calc(400ms + var(--i) * 110ms) 2 both;
1865}
1866@keyframes nudge {
1867 0%,
1868 100% {
1869 border-color: var(--line);
1870 box-shadow: none;
1871 }
1872 50% {
1873 border-color: rgba(138, 163, 255, 0.7);
1874 box-shadow: 0 0 0 4px rgba(138, 163, 255, 0.16);
1875 }
1876}
1877
1878/* the hero's "live" tag: a proposal happening on chain now, never a replay */
1879.tag.live {
1880 background: var(--accent-soft);
1881 color: #e3e9ff;
1882 border: 1px solid rgba(138, 163, 255, 0.55);
1883}
1884.tag.live .dot {
1885 width: 8px;
1886 height: 8px;
1887 border-radius: 50%;
1888 color: var(--accent-hi);
1889 background: currentColor;
1890 animation: beacon 2s ease-out infinite;
1891}
1892
1893/* ---------- operator mode (lab-ui.ts): launch panel, status toast, token prompt ---------- */
1894.btn.opb {
1895 display: inline-flex;
1896 align-items: center;
1897 gap: 7px;
1898 font-weight: 700;
1899 color: var(--warn);
1900 border-color: rgba(245, 185, 66, 0.45);
1901}
1902.btn.opb.on,
1903.btn.opb:hover {
1904 color: #ffd27a;
1905 border-color: var(--warn);
1906}
1907.op {
1908 position: absolute;
1909 inset: 0;
1910 z-index: 32;
1911 display: grid;
1912 /* one column as wide as the screen, so the card's max-width holds on a phone too */
1913 grid-template-columns: minmax(0, 1fr);
1914 place-items: center;
1915 background: rgba(3, 5, 10, 0.72);
1916 backdrop-filter: blur(6px);
1917 opacity: 0;
1918 visibility: hidden;
1919 transition:
1920 opacity 0.2s,
1921 visibility 0s linear 0.2s;
1922}
1923.op.open {
1924 opacity: 1;
1925 visibility: visible;
1926 transition: opacity 0.2s;
1927}
1928.op-card {
1929 width: 1000px;
1930 max-width: calc(100% - 32px);
1931 max-height: calc(100% - 60px);
1932 overflow: auto;
1933 padding: 30px 36px 24px;
1934 border-radius: 26px;
1935 background: #0d1426;
1936 border: 1px solid var(--line-2);
1937 box-shadow: 0 30px 80px rgba(0, 0, 0, 0.6);
1938}
1939.op-head {
1940 display: flex;
1941 align-items: center;
1942 gap: 14px;
1943}
1944.op-head h3 {
1945 flex: 1;
1946 margin: 0;
1947 font-size: 28px;
1948}
1949.op-badge {
1950 display: inline-flex;
1951 align-items: center;
1952 gap: 6px;
1953 padding: 4px 11px;
1954 border-radius: 8px;
1955 font-size: 14px;
1956 font-weight: 800;
1957 letter-spacing: 0.06em;
1958 white-space: nowrap;
1959 background: var(--warn-soft);
1960 color: var(--warn);
1961}
1962.op-note {
1963 margin: 12px 0 18px;
1964 font-size: 17px;
1965 line-height: 1.45;
1966 color: var(--dim);
1967}
1968.op-status {
1969 display: flex;
1970 align-items: center;
1971 gap: 10px;
1972 margin-bottom: 16px;
1973 padding: 12px 16px;
1974 border-radius: 14px;
1975 font-size: 17px;
1976 border: 1px solid var(--line-2);
1977 background: #0d1426;
1978}
1979.op-status b {
1980 white-space: nowrap;
1981}
1982.op-status > .ic {
1983 flex: none;
1984 font-size: 19px;
1985}
1986.op-status .spin {
1987 flex: none;
1988 width: 16px;
1989 height: 16px;
1990 border-width: 2px;
1991}
1992.op-status.run {
1993 background: linear-gradient(var(--accent-soft), var(--accent-soft)), #0d1426;
1994 border-color: rgba(138, 163, 255, 0.45);
1995}
1996.op-status.good {
1997 background: linear-gradient(var(--good-soft), var(--good-soft)), #0d1426;
1998 border-color: rgba(47, 211, 142, 0.45);
1999}
2000.op-status.good > .ic {
2001 color: var(--good-hi);
2002}
2003.op-status.bad {
2004 background: linear-gradient(var(--bad-soft), var(--bad-soft)), #0d1426;
2005 border-color: rgba(255, 77, 94, 0.45);
2006}
2007.op-status.bad > .ic {
2008 color: var(--bad-hi);
2009}
2010.op-status.warn {
2011 background: linear-gradient(var(--warn-soft), var(--warn-soft)), #0d1426;
2012 border-color: rgba(245, 185, 66, 0.45);
2013}
2014.op-status.warn > .ic {
2015 color: var(--warn);
2016}
2017.op-tx {
2018 margin-left: auto;
2019 white-space: nowrap;
2020}
2021.op-list {
2022 display: grid;
2023 gap: 10px;
2024}
2025.op-row {
2026 display: flex;
2027 flex-wrap: wrap;
2028 align-items: center;
2029 gap: 12px 16px;
2030 padding: 12px 14px 12px 16px;
2031 border-radius: 16px;
2032 background: var(--panel);
2033 border: 1px solid var(--line);
2034}
2035.op-row.ask {
2036 border-color: rgba(245, 185, 66, 0.6);
2037 background: linear-gradient(180deg, rgba(245, 185, 66, 0.09), rgba(245, 185, 66, 0.03)), var(--panel);
2038}
2039.op-what {
2040 flex: 1;
2041 min-width: 0;
2042 display: flex;
2043 flex-wrap: wrap;
2044 align-items: center;
2045 gap: 4px 12px;
2046}
2047.op-what b {
2048 font-size: 19px;
2049}
2050.op-what small {
2051 font-size: 14px;
2052 color: var(--faint);
2053}
2054.op-ask {
2055 flex-basis: 100%;
2056 display: flex;
2057 flex-wrap: wrap;
2058 align-items: center;
2059 gap: 12px 16px;
2060}
2061.op-ask p {
2062 flex: 1;
2063 min-width: 260px;
2064 margin: 0;
2065 font-size: 16px;
2066 line-height: 1.45;
2067 color: var(--dim);
2068}
2069.op-ask p b {
2070 color: var(--fg);
2071}
2072.op-btns {
2073 display: flex;
2074 gap: 10px;
2075}
2076.btn.go,
2077.btn.danger,
2078.btn.primary {
2079 display: inline-flex;
2080 align-items: center;
2081 justify-content: center;
2082 gap: 7px;
2083 font-weight: 750;
2084}
2085.btn.go {
2086 color: var(--warn);
2087 border-color: rgba(245, 185, 66, 0.45);
2088}
2089.btn.go:hover {
2090 color: #ffd27a;
2091 border-color: var(--warn);
2092}
2093.btn.danger {
2094 color: #241600;
2095 background: var(--warn);
2096 border-color: var(--warn);
2097}
2098.btn.primary {
2099 color: #fff;
2100 background: var(--accent);
2101 border-color: var(--accent);
2102}
2103.btn:disabled {
2104 opacity: 0.45;
2105 cursor: not-allowed;
2106}
2107.op-foot {
2108 margin-top: 16px;
2109 display: flex;
2110 align-items: center;
2111 justify-content: space-between;
2112 gap: 12px;
2113 font-size: 14px;
2114 color: var(--faint);
2115}
2116.lnkbtn {
2117 padding: 0;
2118 font-size: 14px;
2119 color: var(--accent-hi);
2120 background: none;
2121 border: 0;
2122 text-decoration: underline;
2123 cursor: pointer;
2124}
2125.op-tok {
2126 width: 540px;
2127}
2128.op-tok h3 {
2129 margin: 0;
2130 font-size: 26px;
2131}
2132.op-input {
2133 width: 100%;
2134 margin-bottom: 14px;
2135 padding: 12px 14px;
2136 font-family: var(--mono);
2137 font-size: 17px;
2138 color: var(--fg);
2139 background: #060a15;
2140 border: 1px solid var(--line-2);
2141 border-radius: 12px;
2142}
2143.op-bad {
2144 margin: -4px 0 12px;
2145 font-size: 15px;
2146 color: var(--bad-hi);
2147}
2148.op-toast {
2149 position: absolute;
2150 top: 100px;
2151 left: 50%;
2152 z-index: 26;
2153 max-width: 1200px;
2154 transform: translateX(-50%);
2155}
2156.op-toast:empty {
2157 display: none;
2158}
2159.op-toast .op-status {
2160 margin: 0;
2161 box-shadow: 0 18px 50px rgba(0, 0, 0, 0.55);
2162}
2163.op-x {
2164 display: inline-grid;
2165 place-items: center;
2166 margin-left: 4px;
2167 padding: 4px;
2168 font-size: 16px;
2169 color: var(--dim);
2170 background: none;
2171 border: 0;
2172 cursor: pointer;
2173}
2174
2175/* ---------- details drawer ---------- */
2176.drawer {
2177 position: absolute;
2178 top: 0;
2179 right: 0;
2180 bottom: 0;
2181 z-index: 20;
2182 width: 720px;
2183 display: flex;
2184 flex-direction: column;
2185 background: #0a0f1e;
2186 border-left: 1px solid var(--line-2);
2187 box-shadow: -30px 0 70px rgba(0, 0, 0, 0.55);
2188 transform: translateX(104%);
2189 visibility: hidden;
2190 transition:
2191 transform 0.35s cubic-bezier(0.3, 0.7, 0.3, 1),
2192 visibility 0s linear 0.35s;
2193}
2194.drawer.open {
2195 transform: none;
2196 visibility: visible;
2197 transition: transform 0.35s cubic-bezier(0.3, 0.7, 0.3, 1);
2198}
2199.dr-head {
2200 display: flex;
2201 align-items: center;
2202 justify-content: space-between;
2203 gap: 16px;
2204 padding: 26px 32px 16px;
2205 border-bottom: 1px solid var(--line);
2206}
2207.dr-head h3 {
2208 margin: 0;
2209 font-size: 24px;
2210}
2211.dr-body {
2212 flex: 1;
2213 overflow: auto;
2214 padding: 4px 32px 32px;
2215}
2216.dr-body h4 {
2217 margin: 22px 0 10px;
2218 font-size: 14px;
2219 font-weight: 750;
2220 letter-spacing: 0.12em;
2221 text-transform: uppercase;
2222 color: var(--accent-hi);
2223}
2224.dr-body dl {
2225 margin: 0;
2226 display: grid;
2227 gap: 8px;
2228}
2229.dr-row {
2230 display: grid;
2231 grid-template-columns: 170px minmax(0, 1fr);
2232 gap: 14px;
2233 font-size: 16px;
2234 line-height: 1.4;
2235}
2236.dr-row dt {
2237 color: var(--dim);
2238}
2239.dr-row dd {
2240 margin: 0;
2241 min-width: 0;
2242 overflow-wrap: anywhere;
2243}
2244.mono.wrap {
2245 font-size: 14px;
2246 word-break: break-all;
2247}
2248.vchip {
2249 display: inline-block;
2250 margin-left: 6px;
2251 padding: 1px 8px;
2252 border-radius: 6px;
2253 font-size: 13px;
2254 color: var(--good-hi);
2255 background: var(--good-soft);
2256}
2257.dr-stream .ln {
2258 display: grid;
2259 grid-template-columns: 74px minmax(0, 1fr);
2260 gap: 10px;
2261 padding: 6px 0;
2262 font-size: 14px;
2263 line-height: 1.4;
2264 border-bottom: 1px dashed var(--line);
2265}
2266.ln-t {
2267 font-family: var(--mono);
2268 color: var(--faint);
2269}
2270.ln-m {
2271 overflow-wrap: anywhere;
2272}
2273.ln.good .ln-m {
2274 color: var(--good-hi);
2275}
2276.ln.bad .ln-m {
2277 color: var(--bad-hi);
2278}
2279.ln.warn .ln-m {
2280 color: var(--warn);
2281}
2282.dr-about {
2283 margin: 0;
2284 font-size: 15px;
2285 line-height: 1.55;
2286 color: var(--dim);
2287}
2288
2289/* ---------- help overlay ---------- */
2290.help {
2291 position: absolute;
2292 inset: 0;
2293 z-index: 30;
2294 display: grid;
2295 place-items: center;
2296 background: rgba(3, 5, 10, 0.7);
2297 backdrop-filter: blur(6px);
2298 opacity: 0;
2299 visibility: hidden;
2300 transition:
2301 opacity 0.2s,
2302 visibility 0s linear 0.2s;
2303}
2304.help.open {
2305 opacity: 1;
2306 visibility: visible;
2307 transition: opacity 0.2s;
2308}
2309.hp-card {
2310 width: max-content;
2311 max-width: calc(100% - 32px);
2312 padding: 36px 44px 30px;
2313 border-radius: 26px;
2314 background: #0d1426;
2315 border: 1px solid var(--line-2);
2316 box-shadow: 0 30px 80px rgba(0, 0, 0, 0.6);
2317}
2318.hp-card h3 {
2319 margin: 0 0 24px;
2320 font-size: 30px;
2321}
2322.hp-rows {
2323 display: grid;
2324 grid-template-columns: repeat(2, max-content);
2325 gap: 16px 56px;
2326}
2327.hp-row {
2328 display: flex;
2329 align-items: center;
2330 gap: 16px;
2331 font-size: 19px;
2332 line-height: 1.35;
2333}
2334.hp-k {
2335 flex: none;
2336 min-width: 92px;
2337 display: flex;
2338 gap: 6px;
2339}
2340.hp-k kbd {
2341 font-size: 17px;
2342 padding: 3px 11px;
2343 color: var(--fg);
2344}
2345/* the URL notes and the footer wrap to the width of the key table instead of widening the card */
2346.hp-url,
2347.hp-foot {
2348 width: 0;
2349 min-width: 100%;
2350}
2351.hp-url {
2352 margin-top: 26px;
2353 padding-top: 18px;
2354 border-top: 1px solid var(--line);
2355 display: flex;
2356 flex-direction: column;
2357 gap: 6px;
2358 font-size: 16px;
2359 color: var(--dim);
2360}
2361.hp-url .mono {
2362 font-size: 15px;
2363 color: var(--fg);
2364 overflow-wrap: anywhere;
2365}
2366.hp-foot {
2367 margin: 16px 0 0;
2368 font-size: 15px;
2369 color: var(--faint);
2370}
2371
2372/* ---------- motion: always-on ---------- */
2373@keyframes beacon {
2374 0% {
2375 box-shadow: 0 0 0 0 currentColor;
2376 }
2377 70%,
2378 100% {
2379 box-shadow: 0 0 0 9px transparent;
2380 }
2381}
2382@keyframes spin {
2383 to {
2384 transform: rotate(360deg);
2385 }
2386}
2387@keyframes running {
2388 0%,
2389 100% {
2390 box-shadow: 0 0 0 0 rgba(138, 163, 255, 0);
2391 background: #0a1020;
2392 }
2393 40% {
2394 box-shadow: 0 0 0 6px rgba(138, 163, 255, 0.14);
2395 background: rgba(55, 91, 210, 0.45);
2396 }
2397}
2398.enter {
2399 animation: enter 0.45s ease-out both;
2400}
2401@keyframes enter {
2402 from {
2403 opacity: 0;
2404 transform: translateY(8px);
2405 }
2406}
2407
2408/* ---------- motion: moments (ui.ts adds m-arrive / m-veto / m-clear / m-exec and --d-* delays for one change) ---------- */
2409/* arrive: the outer door opens, the capsule slides in, the door shuts behind it */
2410.m-arrive .cap-in {
2411 animation: cap-arrive 1.1s cubic-bezier(0.2, 0.75, 0.25, 1) var(--d-arrive, 0ms) both;
2412}
2413@keyframes cap-arrive {
2414 0% {
2415 left: calc(-1 * var(--cap-w) - 40px);
2416 }
2417}
2418.m-arrive .lk-outer .lf.t {
2419 animation: leaf-t-pass 1.15s ease-in-out var(--d-arrive, 0ms) both;
2420}
2421.m-arrive .lk-outer .lf.b {
2422 animation: leaf-b-pass 1.15s ease-in-out var(--d-arrive, 0ms) both;
2423}
2424@keyframes leaf-t-pass {
2425 0%,
2426 50% {
2427 transform: translateY(-112%);
2428 }
2429 88%,
2430 100% {
2431 transform: none;
2432 }
2433}
2434@keyframes leaf-b-pass {
2435 0%,
2436 50% {
2437 transform: translateY(112%);
2438 }
2439 88%,
2440 100% {
2441 transform: none;
2442 }
2443}
2444.m-arrive .lk-outer {
2445 animation: glow-accent 1.3s ease-out var(--d-arrive, 0ms) both;
2446}
2447@keyframes glow-accent {
2448 0%,
2449 60% {
2450 border-color: var(--accent-hi);
2451 box-shadow: 0 0 34px rgba(138, 163, 255, 0.55);
2452 }
2453}
2454
2455/* veto: the capsule shakes and turns red, the chamber flashes, the capsule drops out, the stamp lands */
2456.m-veto .lk-cap {
2457 animation: cap-shake 0.65s ease-in-out var(--d-veto, 0ms) both;
2458}
2459@keyframes cap-shake {
2460 0% {
2461 border-color: rgba(138, 163, 255, 0.7);
2462 background: linear-gradient(180deg, #1c2b55, #142044);
2463 transform: none;
2464 }
2465 20% {
2466 transform: translateX(-9px);
2467 }
2468 40% {
2469 transform: translateX(9px);
2470 }
2471 60% {
2472 transform: translateX(-6px);
2473 }
2474 80% {
2475 transform: translateX(4px);
2476 }
2477 100% {
2478 transform: none;
2479 }
2480}
2481.m-veto .cap-out {
2482 animation: cap-eject 1.05s cubic-bezier(0.55, 0, 0.85, 0.3) calc(var(--d-veto, 0ms) + 650ms) both;
2483}
2484@keyframes cap-eject {
2485 0% {
2486 opacity: 1;
2487 transform: none;
2488 }
2489 100% {
2490 opacity: 1;
2491 transform: translateY(190px) rotate(10deg);
2492 }
2493}
2494.m-veto .lk-flash {
2495 animation: flash 1.3s ease-out calc(var(--d-veto, 0ms) + 350ms) both;
2496}
2497@keyframes flash {
2498 0% {
2499 opacity: 0;
2500 }
2501 14% {
2502 opacity: 1;
2503 }
2504 100% {
2505 opacity: 0;
2506 }
2507}
2508.m-veto .lk-ch {
2509 animation: ch-red 1.4s ease-out calc(var(--d-veto, 0ms) + 350ms) both;
2510}
2511@keyframes ch-red {
2512 0% {
2513 border-color: rgba(138, 163, 255, 0.5);
2514 }
2515}
2516.m-veto .lk-x {
2517 animation: pop 0.45s cubic-bezier(0.3, 1.6, 0.5, 1) calc(var(--d-veto, 0ms) + 500ms) both;
2518}
2519.m-veto .lk-lock {
2520 animation: lock-bad 0.7s ease-in-out calc(var(--d-veto, 0ms) + 900ms) both;
2521}
2522@keyframes lock-bad {
2523 0% {
2524 color: var(--dim);
2525 border-color: var(--line-2);
2526 transform: translate(-50%, -50%);
2527 }
2528 30% {
2529 transform: translate(calc(-50% - 5px), -50%) scale(1.15);
2530 }
2531 60% {
2532 transform: translate(calc(-50% + 5px), -50%) scale(1.15);
2533 }
2534 100% {
2535 transform: translate(-50%, -50%);
2536 }
2537}
2538.cn.m-veto .cn-stamp {
2539 animation: stamp 0.55s cubic-bezier(0.2, 1.5, 0.4, 1) calc(var(--d-veto, 0ms) + 1000ms) both;
2540}
2541@keyframes stamp {
2542 0% {
2543 opacity: 0;
2544 transform: rotate(-4deg) scale(1.9);
2545 }
2546 100% {
2547 opacity: 1;
2548 transform: rotate(-4deg) scale(1);
2549 }
2550}
2551.cn.m-veto .cn-sub {
2552 animation: rise 0.5s ease-out calc(var(--d-veto, 0ms) + 1350ms) both;
2553}
2554.banner.m-veto {
2555 animation: rise 0.55s ease-out calc(var(--d-veto, 0ms) + 1200ms) both;
2556}
2557
2558/* clear: a scan sweeps the chamber, the capsule turns green, the inner door's lock opens */
2559.m-clear .lk-scan {
2560 animation: scan 1.1s ease-in-out var(--d-clear, 0ms) both;
2561}
2562@keyframes scan {
2563 0% {
2564 left: -180px;
2565 opacity: 1;
2566 }
2567 100% {
2568 left: 100%;
2569 opacity: 1;
2570 }
2571}
2572.m-clear .lk-cap {
2573 animation: cap-good 1.3s ease-out calc(var(--d-clear, 0ms) + 450ms) both;
2574}
2575@keyframes cap-good {
2576 0% {
2577 border-color: rgba(138, 163, 255, 0.7);
2578 background: linear-gradient(180deg, #1c2b55, #142044);
2579 }
2580 45% {
2581 box-shadow:
2582 0 0 0 8px rgba(47, 211, 142, 0.22),
2583 0 0 50px rgba(47, 211, 142, 0.7);
2584 }
2585}
2586.m-clear .lk-lock {
2587 animation: lock-pop 0.8s cubic-bezier(0.3, 1.6, 0.5, 1) calc(var(--d-clear, 0ms) + 900ms) both;
2588}
2589@keyframes lock-pop {
2590 0% {
2591 color: var(--dim);
2592 border-color: var(--line-2);
2593 transform: translate(-50%, -50%) scale(0.7);
2594 }
2595 60% {
2596 transform: translate(-50%, -50%) scale(1.3);
2597 }
2598 100% {
2599 transform: translate(-50%, -50%) scale(1);
2600 }
2601}
2602.m-clear .lk-inner {
2603 animation: glow-good 1.6s ease-out calc(var(--d-clear, 0ms) + 900ms) both;
2604}
2605@keyframes glow-good {
2606 0% {
2607 border-color: var(--line-2);
2608 box-shadow: none;
2609 }
2610 40% {
2611 box-shadow: 0 0 60px rgba(47, 211, 142, 0.6);
2612 }
2613}
2614.banner.m-clear {
2615 animation: rise 0.55s ease-out calc(var(--d-clear, 0ms) + 1100ms) both;
2616}
2617
2618/* exec: the inner door opens, the capsule goes through, the proxy lights up */
2619.m-exec .lk-inner .lf.t {
2620 animation: leaf-t-open 0.8s cubic-bezier(0.6, 0, 0.2, 1) var(--d-exec, 0ms) both;
2621}
2622.m-exec .lk-inner .lf.b {
2623 animation: leaf-b-open 0.8s cubic-bezier(0.6, 0, 0.2, 1) var(--d-exec, 0ms) both;
2624}
2625@keyframes leaf-t-open {
2626 from {
2627 transform: none;
2628 }
2629 to {
2630 transform: translateY(-88%);
2631 }
2632}
2633@keyframes leaf-b-open {
2634 from {
2635 transform: none;
2636 }
2637 to {
2638 transform: translateY(88%);
2639 }
2640}
2641.m-exec .lk-lock {
2642 animation: fade-out 0.3s ease-out var(--d-exec, 0ms) both;
2643}
2644@keyframes fade-out {
2645 from {
2646 opacity: 1;
2647 }
2648 to {
2649 opacity: 0;
2650 }
2651}
2652.m-exec .cap-out {
2653 animation: cap-exec 1.05s cubic-bezier(0.55, 0, 0.3, 1) calc(var(--d-exec, 0ms) + 550ms) both;
2654}
2655@keyframes cap-exec {
2656 0% {
2657 opacity: 1;
2658 transform: none;
2659 }
2660 100% {
2661 opacity: 1;
2662 transform: translateX(calc(var(--cap-w) + 60px));
2663 }
2664}
2665.m-exec .lk-dest {
2666 animation: dest-on 1.2s ease-out calc(var(--d-exec, 0ms) + 1300ms) both;
2667}
2668@keyframes dest-on {
2669 0% {
2670 border-color: var(--line);
2671 background: rgba(9, 14, 28, 0.75);
2672 box-shadow: none;
2673 }
2674 45% {
2675 box-shadow: 0 0 70px rgba(47, 211, 142, 0.6);
2676 }
2677}
2678.cn.m-exec .cn-word {
2679 animation: rise 0.55s ease-out calc(var(--d-exec, 0ms) + 1400ms) both;
2680}
2681.banner.m-exec {
2682 animation: rise 0.55s ease-out calc(var(--d-exec, 0ms) + 1500ms) both;
2683}
2684
2685/* the verdict card follows the verdict: each pipeline step lights up in turn, then the chip lands */
2686.pipe.m-veto li,
2687.pipe.m-clear li {
2688 animation: step-on 0.5s ease-out both;
2689}
2690.pipe.m-veto li {
2691 animation-delay: calc(var(--d-veto, 0ms) + var(--i) * 230ms);
2692}
2693.pipe.m-clear li {
2694 animation-delay: calc(var(--d-clear, 0ms) + var(--i) * 230ms);
2695}
2696@keyframes step-on {
2697 0% {
2698 opacity: 0.4;
2699 background: transparent;
2700 }
2701 45% {
2702 opacity: 1;
2703 background: rgba(138, 163, 255, 0.2);
2704 }
2705}
2706.pipe.m-veto .pi-dot,
2707.pipe.m-clear .pi-dot {
2708 animation: dot-on 0.5s ease-out both;
2709}
2710.pipe.m-veto .pi-dot {
2711 animation-delay: calc(var(--d-veto, 0ms) + var(--i) * 230ms);
2712}
2713.pipe.m-clear .pi-dot {
2714 animation-delay: calc(var(--d-clear, 0ms) + var(--i) * 230ms);
2715}
2716@keyframes dot-on {
2717 0% {
2718 background: #0a1020;
2719 border-color: var(--line-2);
2720 color: transparent;
2721 transform: scale(0.8);
2722 }
2723 60% {
2724 transform: scale(1.2);
2725 }
2726}
2727.vm.m-veto .v-chip,
2728.vm.m-veto .v-code {
2729 animation: chip-in 0.55s cubic-bezier(0.3, 1.5, 0.5, 1) calc(var(--d-veto, 0ms) + 1200ms) both;
2730}
2731.vm.m-clear .v-chip {
2732 animation: chip-in 0.55s cubic-bezier(0.3, 1.5, 0.5, 1) calc(var(--d-clear, 0ms) + 1200ms) both;
2733}
2734.vm.m-veto .v-rule,
2735.vm.m-veto .v-time {
2736 animation: rise 0.5s ease-out calc(var(--d-veto, 0ms) + 1450ms) both;
2737}
2738.vm.m-clear .v-rule,
2739.vm.m-clear .v-time {
2740 animation: rise 0.5s ease-out calc(var(--d-clear, 0ms) + 1450ms) both;
2741}
2742@keyframes chip-in {
2743 0% {
2744 opacity: 0;
2745 transform: scale(0.6);
2746 }
2747 100% {
2748 opacity: 1;
2749 transform: scale(1);
2750 }
2751}
2752@keyframes rise {
2753 0% {
2754 opacity: 0;
2755 transform: translateY(10px);
2756 }
2757 100% {
2758 opacity: 1;
2759 transform: none;
2760 }
2761}
2762@keyframes pop {
2763 0% {
2764 opacity: 0;
2765 transform: translate(-50%, -50%) scale(0.3);
2766 }
2767 100% {
2768 opacity: 1;
2769 transform: translate(-50%, -50%) scale(1);
2770 }
2771}
2772
2773@media (prefers-reduced-motion: reduce) {
2774 *,
2775 *::before,
2776 *::after {
2777 animation: none !important;
2778 transition: none !important;
2779 }
2780}
2781
2782/* ---------- stack mode: phones, portrait screens, narrow windows ---------- */
2783@media not all and (min-width: 960px) and (min-aspect-ratio: 5/4) {
2784 html,
2785 body {
2786 height: auto;
2787 }
2788 body {
2789 overflow-x: hidden;
2790 overflow-y: auto;
2791 }
2792 #app {
2793 position: static;
2794 min-height: 100vh;
2795 }
2796 .stage {
2797 position: relative;
2798 width: auto;
2799 height: auto;
2800 max-width: 780px;
2801 margin: 0 auto;
2802 padding: 14px 16px 36px;
2803 display: flex;
2804 flex-direction: column;
2805 gap: 14px;
2806 overflow: visible;
2807 background:
2808 radial-gradient(600px 400px at 10% -10%, rgba(55, 91, 210, 0.22), transparent 62%),
2809 var(--bg);
2810 }
2811 .bar {
2812 grid-template-columns: minmax(0, 1fr) auto;
2813 gap: 10px 12px;
2814 }
2815 .brand {
2816 gap: 10px;
2817 min-width: 0;
2818 }
2819 .brand .mark {
2820 width: 34px;
2821 height: 34px;
2822 }
2823 .brand-name {
2824 font-size: 19px;
2825 }
2826 .brand-sub,
2827 .cre,
2828 .ctl .btn.sq {
2829 display: none;
2830 }
2831 .status {
2832 grid-column: 1 / -1;
2833 grid-row: 2;
2834 justify-self: start;
2835 flex-wrap: wrap;
2836 gap: 6px 12px;
2837 }
2838 .pill {
2839 font-size: 14px;
2840 padding: 6px 12px 6px 11px;
2841 gap: 8px;
2842 }
2843 .pill .dot {
2844 width: 8px;
2845 height: 8px;
2846 }
2847 /* a replay's pill is long: the block number would drop to its own line and push the page down at every switch */
2848 .pill.replay + .blk {
2849 display: none;
2850 }
2851 .blk {
2852 font-size: 12px;
2853 }
2854 .blk-n {
2855 font-size: 14px;
2856 }
2857 .bar-r {
2858 grid-column: 2;
2859 grid-row: 1;
2860 gap: 8px;
2861 }
2862 .ctl {
2863 gap: 6px;
2864 }
2865 .seg button {
2866 font-size: 13px;
2867 padding: 4px 7px;
2868 }
2869 .btn {
2870 font-size: 13px;
2871 padding: 5px 9px;
2872 }
2873 .main {
2874 display: flex;
2875 flex-direction: column;
2876 gap: 14px;
2877 }
2878 .hero,
2879 .verdict {
2880 border-radius: 20px;
2881 }
2882 .hero {
2883 padding: 18px 16px 16px;
2884 }
2885 .h-eyebrow {
2886 font-size: 12px;
2887 min-height: 22px;
2888 gap: 8px;
2889 flex-wrap: wrap;
2890 }
2891 .tag {
2892 font-size: 11px;
2893 padding: 2px 8px;
2894 }
2895 /* a long replay tag wraps as one line of text inside the card (the date as a unit), not as two flex columns */
2896 .h-eyebrow .tag {
2897 display: inline-block;
2898 max-width: 100%;
2899 white-space: normal;
2900 line-height: 1.45;
2901 }
2902 .h-eyebrow .tag .ic {
2903 margin-right: 6px;
2904 vertical-align: -1px;
2905 }
2906 .h-eyebrow .tag .dot {
2907 display: inline-block;
2908 margin-right: 6px;
2909 vertical-align: 0;
2910 }
2911 .cn-rp {
2912 font-size: 10.5px;
2913 }
2914 .h-title {
2915 font-size: 30px;
2916 }
2917 .h-desc {
2918 font-size: 15px;
2919 text-wrap: pretty;
2920 }
2921 .lockwrap {
2922 --owner-w: 0px;
2923 --door-w: 24px;
2924 --dest-w: 76px;
2925 --lk-gap: 6px;
2926 --lk-h: 184px;
2927 --cap-w: 122px;
2928 --cap-h: 40px;
2929 margin-top: 16px;
2930 }
2931 .lk {
2932 grid-template-columns: var(--door-w) minmax(0, 1fr) var(--door-w) var(--dest-w);
2933 }
2934 .lk-owner {
2935 display: none;
2936 }
2937 .lk-door {
2938 border-radius: 8px;
2939 }
2940 .lf {
2941 left: 3px;
2942 right: 3px;
2943 height: calc(50% - 3px);
2944 border-radius: 5px;
2945 }
2946 .lf.t {
2947 top: 3px;
2948 }
2949 .lf.b {
2950 bottom: 3px;
2951 }
2952 .lk-lock {
2953 width: 22px;
2954 height: 22px;
2955 font-size: 13px;
2956 border-width: 1px;
2957 }
2958 .lk-ch {
2959 border-radius: 12px;
2960 }
2961 .lk-grid {
2962 background-size: 18px 18px;
2963 }
2964 .lk-rail {
2965 left: 10px;
2966 right: 10px;
2967 bottom: 12px;
2968 height: 5px;
2969 }
2970 .lk-x {
2971 width: 18px;
2972 height: 18px;
2973 font-size: 10px;
2974 }
2975 .cap-in {
2976 bottom: 24px;
2977 left: calc(10px + var(--p, 0) * (100% - 20px - var(--cap-w)));
2978 }
2979 .lk-cap {
2980 gap: 6px;
2981 padding: 0 8px;
2982 border-radius: 10px;
2983 border-width: 1.5px;
2984 font-size: 13px;
2985 }
2986 .lk-cap .ic {
2987 font-size: 14px;
2988 }
2989 .lk-dest {
2990 padding: 6px;
2991 gap: 4px;
2992 border-radius: 12px;
2993 }
2994 .lk-dest .ic {
2995 font-size: 24px;
2996 margin: 0;
2997 }
2998 .lk-dest b {
2999 font-size: 11px;
3000 }
3001 .lk-dest small {
3002 font-size: 11px;
3003 }
3004 .count {
3005 left: calc(var(--door-w) + var(--lk-gap));
3006 right: calc(var(--dest-w) + var(--door-w) + 2 * var(--lk-gap));
3007 height: calc(100% - 66px);
3008 /* the stamps size themselves to the chamber (cqw), whatever the phone's width */
3009 container-type: inline-size;
3010 }
3011 .cn {
3012 gap: 3px;
3013 }
3014 .cn.ph-ejected,
3015 .cn.ph-executed,
3016 .cn.ph-ready,
3017 .cn.ph-waiting {
3018 transform: translateY(18px);
3019 }
3020 .cn-num b {
3021 font-size: 42px;
3022 }
3023 .cn-num span {
3024 font-size: 14px;
3025 }
3026 .cn-num {
3027 gap: 6px;
3028 }
3029 .cn-eta {
3030 font-size: 14px;
3031 gap: 5px;
3032 }
3033 .cn-of {
3034 font-size: 12px;
3035 }
3036 .cn-tag {
3037 font-size: 11px;
3038 padding: 3px 9px;
3039 }
3040 .cn-word {
3041 font-size: 20px;
3042 gap: 6px;
3043 }
3044 .cn.ph-executed .cn-word {
3045 font-size: 24px;
3046 }
3047 .cn-stamp {
3048 font-size: clamp(18px, 5.6vw, 28px);
3049 font-size: clamp(16px, 12.5cqw, 28px);
3050 letter-spacing: 0.04em;
3051 max-width: 92%;
3052 border-width: 3px;
3053 border-radius: 10px;
3054 padding: 2px 10px 4px 12px;
3055 }
3056 .cn-sub {
3057 font-size: 12px;
3058 margin-top: 2px;
3059 }
3060 .cn-sub.intro,
3061 .cn-sub.arriving {
3062 gap: 8px;
3063 font-size: 14px;
3064 text-align: center;
3065 }
3066 .cn-tx {
3067 margin-top: 6px;
3068 font-size: 12px;
3069 }
3070 .cn-sub.intro .spin {
3071 width: 14px;
3072 height: 14px;
3073 border-width: 2px;
3074 }
3075 /* the three doors as rows: key on the left, the caption's phrases one per line on the right */
3076 .doors {
3077 grid-template-columns: minmax(0, 1fr);
3078 gap: 8px;
3079 margin-top: 12px;
3080 }
3081 .dl,
3082 .dl.c,
3083 .dl.r {
3084 flex-direction: row;
3085 align-items: baseline;
3086 text-align: left;
3087 gap: 12px;
3088 }
3089 .dl-k,
3090 :root:lang(zh-CN) .dl-k,
3091 :root:lang(zh-TW) .dl-k {
3092 flex: none;
3093 width: 92px;
3094 font-size: 11px;
3095 }
3096 :root:lang(zh-CN) .dl-k,
3097 :root:lang(zh-TW) .dl-k {
3098 font-size: 13px;
3099 }
3100 .dl-v {
3101 flex: 1 1 auto;
3102 min-width: 0;
3103 font-size: 14px;
3104 text-wrap: balance;
3105 }
3106 .dl-v .ph {
3107 display: block;
3108 }
3109 .dl-v .sep {
3110 display: none;
3111 }
3112 .banner-slot {
3113 padding-top: 12px;
3114 }
3115 .banner {
3116 flex-wrap: wrap;
3117 gap: 8px 10px;
3118 padding: 11px 13px;
3119 font-size: 16px;
3120 border-radius: 14px;
3121 }
3122 .bn-i {
3123 font-size: 20px;
3124 }
3125 .bn-rule {
3126 margin-left: 0;
3127 font-size: 13px;
3128 padding: 4px 9px;
3129 border-radius: 9px;
3130 }
3131 .verdict {
3132 padding: 18px 16px;
3133 gap: 12px;
3134 }
3135 .v-head .hex {
3136 font-size: 22px;
3137 }
3138 .v-head h2 {
3139 font-size: 17px;
3140 }
3141 .v-chip {
3142 font-size: 24px;
3143 padding: 4px 14px 4px 10px;
3144 border-radius: 10px;
3145 gap: 6px;
3146 }
3147 .v-chip .ic {
3148 font-size: 20px;
3149 }
3150 .v-chip.await,
3151 .v-chip.none {
3152 font-size: 18px;
3153 }
3154 .spin {
3155 width: 14px;
3156 height: 14px;
3157 border-width: 2px;
3158 }
3159 .v-code {
3160 font-size: 24px;
3161 }
3162 .v-rule {
3163 font-size: 16px;
3164 }
3165 .v-time {
3166 font-size: 14px;
3167 }
3168 .v-time b {
3169 font-size: 17px;
3170 }
3171 .pipe li {
3172 gap: 10px;
3173 padding: 4px 8px;
3174 }
3175 .pipe li + li::before {
3176 left: 19px;
3177 top: -9px;
3178 height: 14px;
3179 }
3180 .pi-dot {
3181 width: 22px;
3182 height: 22px;
3183 font-size: 12px;
3184 }
3185 .pipe.seq li.cur .pi-dot .spin {
3186 width: 12px;
3187 height: 12px;
3188 border-width: 2px;
3189 }
3190 .pipe.seq li.cur .pi-dot {
3191 box-shadow: 0 0 0 4px rgba(138, 163, 255, 0.14);
3192 }
3193 .pi-t b {
3194 font-size: 15px;
3195 }
3196 .pi-t small {
3197 font-size: 12px;
3198 }
3199 .v-links {
3200 grid-template-columns: repeat(2, minmax(0, 1fr));
3201 gap: 8px 12px;
3202 }
3203 .lnk > span:first-child {
3204 font-size: 11px;
3205 }
3206 :root:lang(zh-CN) .lnk > span:first-child,
3207 :root:lang(zh-TW) .lnk > span:first-child {
3208 font-size: 13px;
3209 }
3210 .lnk .mono {
3211 font-size: 13px;
3212 }
3213 .strip {
3214 gap: 10px;
3215 }
3216 .s-head {
3217 flex-wrap: wrap;
3218 gap: 8px 12px;
3219 }
3220 .s-head h3 {
3221 font-size: 13px;
3222 }
3223 .toggle {
3224 font-size: 12px;
3225 }
3226 .s-hint {
3227 display: none;
3228 }
3229 .s-cards {
3230 grid-template-columns: repeat(2, minmax(0, 1fr));
3231 gap: 10px;
3232 }
3233 .s-empty {
3234 min-height: 90px;
3235 font-size: 14px;
3236 }
3237 .pc {
3238 padding: 12px 13px 11px;
3239 gap: 4px;
3240 border-radius: 14px;
3241 }
3242 .pc::before {
3243 left: 13px;
3244 right: 13px;
3245 }
3246 .pc-id {
3247 font-size: 15px;
3248 }
3249 .pc-chip {
3250 font-size: 10px;
3251 padding: 2px 7px;
3252 }
3253 .pc-name,
3254 .pc-name.long {
3255 font-size: 16px;
3256 }
3257 .pc-line {
3258 font-size: 13px;
3259 }
3260 .pc-foot {
3261 font-size: 13px;
3262 }
3263 .drawer {
3264 position: fixed;
3265 inset: 0;
3266 width: auto;
3267 border-left: 0;
3268 }
3269 .dr-head {
3270 padding: 16px;
3271 }
3272 .dr-head h3 {
3273 font-size: 19px;
3274 }
3275 .dr-body {
3276 padding: 4px 16px 28px;
3277 }
3278 .dr-row {
3279 grid-template-columns: minmax(0, 1fr);
3280 gap: 2px;
3281 font-size: 14px;
3282 }
3283 .dr-row dt {
3284 font-size: 12px;
3285 }
3286 .help {
3287 position: fixed;
3288 }
3289 .hp-card {
3290 padding: 22px 18px;
3291 }
3292 .hp-card h3 {
3293 font-size: 20px;
3294 margin-bottom: 14px;
3295 }
3296 .hp-card {
3297 width: auto;
3298 }
3299 .hp-rows {
3300 grid-template-columns: minmax(0, 1fr);
3301 gap: 10px;
3302 }
3303 .hp-row {
3304 font-size: 14px;
3305 gap: 10px;
3306 }
3307 .hp-k {
3308 min-width: 70px;
3309 }
3310 .hp-k kbd {
3311 font-size: 13px;
3312 padding: 2px 8px;
3313 }
3314 .hp-url,
3315 .hp-url .mono,
3316 .hp-foot {
3317 font-size: 12px;
3318 }
3319 /* the attack picker right under the top bar: a row of cards to swipe, the next one peeking in at the edge */
3320 .lab {
3321 gap: 8px;
3322 }
3323 .lab-head {
3324 flex-wrap: wrap;
3325 gap: 6px 10px;
3326 min-height: 0;
3327 }
3328 .lab-t {
3329 flex: 1 1 100%;
3330 flex-direction: column;
3331 align-items: flex-start;
3332 gap: 2px;
3333 }
3334 .lab-t h3 {
3335 font-size: 17px;
3336 white-space: normal;
3337 text-wrap: balance;
3338 }
3339 .lab-sub {
3340 font-size: 12.5px;
3341 white-space: normal;
3342 }
3343 .lab-now {
3344 margin-left: 0;
3345 flex-wrap: wrap;
3346 gap: 4px 10px;
3347 white-space: normal;
3348 }
3349 .lab-now .tag {
3350 font-size: 11px;
3351 padding: 2px 8px;
3352 }
3353 .lab-tx {
3354 font-size: 12px;
3355 }
3356 .lab-tx .mono {
3357 font-size: 12.5px;
3358 }
3359 .tabs {
3360 display: none;
3361 }
3362 .lab-cards {
3363 grid-template-columns: none;
3364 grid-auto-flow: column;
3365 grid-auto-columns: 170px;
3366 gap: 8px;
3367 margin: 0 -16px;
3368 padding: 3px 16px 6px;
3369 overflow-x: auto;
3370 overscroll-behavior-x: contain;
3371 scroll-snap-type: x proximity;
3372 scroll-padding-inline: 16px;
3373 scrollbar-width: none;
3374 -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 26px), transparent);
3375 mask-image: linear-gradient(90deg, #000 calc(100% - 26px), transparent);
3376 }
3377 .lab-cards::-webkit-scrollbar {
3378 display: none;
3379 }
3380 .lc {
3381 border-radius: 14px;
3382 scroll-snap-align: start;
3383 }
3384 .lc:hover {
3385 transform: none;
3386 }
3387 .lc::before {
3388 left: 12px;
3389 right: 12px;
3390 }
3391 .lc-main {
3392 gap: 3px;
3393 padding: 10px 11px;
3394 }
3395 .lc-top {
3396 min-height: 20px;
3397 }
3398 .lc.has-op .lc-top {
3399 padding-right: 28px;
3400 }
3401 .lc-code {
3402 padding: 1px 7px;
3403 border-radius: 6px;
3404 font-size: 12px;
3405 }
3406 .lc-code.clear {
3407 font-size: 11.5px;
3408 }
3409 .lc-ref {
3410 font-size: 12px;
3411 }
3412 .lc-live {
3413 padding: 1px 7px;
3414 font-size: 10px;
3415 }
3416 .lc-name {
3417 font-size: 16px;
3418 white-space: normal;
3419 overflow: visible;
3420 text-overflow: clip;
3421 text-wrap: balance;
3422 }
3423 .lc-line {
3424 font-size: 12.5px;
3425 line-height: 1.3;
3426 -webkit-line-clamp: 3;
3427 }
3428 .lc-foot {
3429 min-height: 18px;
3430 gap: 5px;
3431 }
3432 .lc-cta,
3433 .lc-stage {
3434 font-size: 12.5px;
3435 }
3436 .lc-stage {
3437 white-space: normal;
3438 line-height: 1.25;
3439 }
3440 .lc-stage > span:not(.lc-steps) {
3441 overflow: visible;
3442 text-overflow: clip;
3443 }
3444 .lc-steps {
3445 display: none;
3446 }
3447 .lc-op {
3448 top: 8px;
3449 right: 8px;
3450 width: 24px;
3451 height: 24px;
3452 border-radius: 7px;
3453 font-size: 13px;
3454 }
3455 .btn.opb .opb-t {
3456 display: none;
3457 }
3458 .op {
3459 position: fixed;
3460 }
3461 .op-card {
3462 max-height: calc(100% - 24px);
3463 padding: 20px 16px 16px;
3464 border-radius: 20px;
3465 }
3466 .op-head {
3467 flex-wrap: wrap;
3468 gap: 8px 10px;
3469 }
3470 .op-head h3 {
3471 flex: 1 1 100%;
3472 order: 3;
3473 font-size: 19px;
3474 }
3475 .op-head .btn {
3476 margin-left: auto;
3477 }
3478 .op-note {
3479 font-size: 14px;
3480 }
3481 .op-status {
3482 flex-wrap: wrap;
3483 padding: 10px 12px;
3484 font-size: 14px;
3485 }
3486 .op-row {
3487 gap: 10px;
3488 padding: 11px 12px;
3489 }
3490 .op-what b {
3491 font-size: 16px;
3492 }
3493 .op-what small {
3494 flex-basis: 100%;
3495 font-size: 12px;
3496 }
3497 .op-row > .btn.go {
3498 width: 100%;
3499 }
3500 .op-ask p {
3501 flex-basis: 100%;
3502 min-width: 0;
3503 font-size: 14px;
3504 }
3505 .op-ask .op-btns {
3506 width: 100%;
3507 }
3508 .op-ask .op-btns .btn {
3509 flex: 1;
3510 }
3511 .op-foot {
3512 flex-wrap: wrap;
3513 font-size: 12px;
3514 }
3515 .op-tok {
3516 width: auto;
3517 }
3518 .op-toast {
3519 position: fixed;
3520 top: auto;
3521 bottom: calc(12px + env(safe-area-inset-bottom));
3522 left: 12px;
3523 right: 12px;
3524 max-width: none;
3525 transform: none;
3526 }
3527}
3528/* stack mode with room to spare (a tablet in portrait, a narrow desktop window) */
3529@media not all and (min-width: 960px) and (min-aspect-ratio: 5/4) {
3530 @media (min-width: 620px) {
3531 .brand-sub {
3532 display: block;
3533 font-size: 13px;
3534 }
3535 .h-title {
3536 font-size: 38px;
3537 }
3538 .h-desc {
3539 font-size: 17px;
3540 }
3541 .lockwrap {
3542 --owner-w: 96px;
3543 --door-w: 36px;
3544 --dest-w: 120px;
3545 --lk-gap: 10px;
3546 --lk-h: 220px;
3547 --cap-w: 170px;
3548 --cap-h: 50px;
3549 }
3550 .lk {
3551 grid-template-columns: var(--owner-w) var(--door-w) minmax(0, 1fr) var(--door-w) var(--dest-w);
3552 }
3553 .lk-owner {
3554 display: flex;
3555 }
3556 .lk-owner .ic {
3557 font-size: 28px;
3558 }
3559 .lk-owner b {
3560 font-size: 14px;
3561 }
3562 .lk-owner small {
3563 font-size: 12px;
3564 }
3565 .count {
3566 left: calc(var(--owner-w) + var(--door-w) + 2 * var(--lk-gap));
3567 }
3568 .lk-cap {
3569 font-size: 16px;
3570 }
3571 .lk-dest b,
3572 .lk-dest small {
3573 font-size: 13px;
3574 }
3575 .lk-lock {
3576 width: 32px;
3577 height: 32px;
3578 font-size: 17px;
3579 }
3580 .cn-num b {
3581 font-size: 56px;
3582 }
3583 .s-cards {
3584 grid-template-columns: repeat(4, minmax(0, 1fr));
3585 }
3586 .lab-cards {
3587 grid-auto-columns: 184px;
3588 }
3589 }
3590}
3591/* stage screens: the bottom row holds the attack picker or the strip of recent proposals (the tabs); with ?clean=1
3592 there is no picker and the strip is always there. A phone shows both, one above and one below the airlock. */
3593@media (min-width: 960px) and (min-aspect-ratio: 5/4) {
3594 .stage:not(.no-lab):not(.tab-recent) .strip,
3595 .stage.tab-recent .lab {
3596 display: none;
3597 }
3598}
3599
3600/* ---------- presenter chrome ---------- */
3601/* Chinese text breaks at spaces and punctuation, not inside a word; anywhere only if a run cannot fit at all */
3602:root:lang(zh-CN) :is(.h-desc, .v-rule, .bn-t, .dl-v, .pc-line, .lc-line, .op-note, .op-ask p),
3603:root:lang(zh-TW) :is(.h-desc, .v-rule, .bn-t, .dl-v, .pc-line, .lc-line, .op-note, .op-ask p) {
3604 word-break: keep-all;
3605 overflow-wrap: anywhere;
3606}
3607/* ?clean=1 (recording): no language switch, Details, ? or key hints; the Chainlink CRE mark stays at the right edge */
3608.clean .ctl,
3609.clean .s-hint {
3610 display: none;
3611}
3612/* a touch screen has no keyboard: no key hints */
3613@media (hover: none) {
3614 .s-hint {
3615 display: none;
3616 }
3617}
3618/* a stage screen with a mouse: the chrome fades out after 3 s without mouse movement (ui.ts adds .idle), and the
3619 cursor with it; any mouse movement brings both back */
3620@media (hover: hover) and (min-width: 960px) and (min-aspect-ratio: 5/4) {
3621 .ctl,
3622 .s-hint {
3623 transition: opacity 0.45s ease;
3624 }
3625 .idle .ctl,
3626 .idle .s-hint {
3627 opacity: 0;
3628 pointer-events: none;
3629 }
3630 .idle #app {
3631 cursor: none;
3632 }
3633}