anvilsign in

collin/mahjong

1@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+TC:wght@400;600;900&display=swap');
2
3:root {
4 /* Depth of each player's strip. `--h-len` is floored so a window too narrow
5 to hold two strips shrinks the tiles rather than going negative. */
6 --depth: clamp(232px, 30vh, 330px);
7 --h-len: max(160px, calc(100vw - 2 * var(--depth)));
8 --v-len: 100vh;
9 /* Largest tile a strip can hold. Edge inwards it has to fit one row of
10 discards (0.88 tiles tall), the melds (0.86), the buttons (56px, once one
11 is actually in there), the hand (1.71 + 6px) and the nameplate (28px),
12 plus its own padding, gaps and margins — so 3.45 tiles plus 112px.
13
14 Tile size otherwise follows the strip's *length*, which is why a window
15 with less height than F11 kept full-size tiles and left the discards a
16 sliver of a row to be cut off in. */
17 --tile-fit: calc((var(--depth) - 112px) / 3.45);
18
19 --felt: #0f4534;
20 --felt-2: #0a3126;
21 --ivory: #f6f0e2;
22 --ivory-edge: #d9cfb6;
23 --ink: #21262b;
24 --gold: #d9b45c;
25 --red: #b3261e;
26 --green: #1c7a4b;
27 --blue: #1d5aa8;
28}
29
30* {
31 box-sizing: border-box;
32 -webkit-tap-highlight-color: transparent;
33}
34
35html,
36body,
37#root {
38 height: 100%;
39 margin: 0;
40 overflow: hidden;
41 overscroll-behavior: none;
42 touch-action: manipulation;
43 user-select: none;
44}
45
46body {
47 font-family: 'Noto Sans TC', system-ui, sans-serif;
48 color: var(--ivory);
49 background: var(--felt-2);
50}
51
52/* ---------- lobby ---------- */
53.lobby {
54 height: 100%;
55 display: flex;
56 flex-direction: column;
57 align-items: center;
58 justify-content: center;
59 gap: 0.5rem;
60 background: radial-gradient(ellipse at center, var(--felt) 0%, var(--felt-2) 75%);
61}
62.lobby h1 {
63 font-size: clamp(3rem, 9vw, 7rem);
64 font-weight: 900;
65 letter-spacing: 0.1em;
66 margin: 0 0 0.5rem;
67 color: var(--gold);
68}
69.lobby p {
70 margin: 0;
71 opacity: 0.75;
72 letter-spacing: 0.15em;
73}
74.lobby .hint {
75 opacity: 0.45;
76 font-size: 0.9rem;
77 margin-bottom: 1.5rem;
78}
79
80/* ---------- table ---------- */
81.table {
82 position: relative;
83 height: 100%;
84 width: 100%;
85 background: radial-gradient(ellipse at center, var(--felt) 0%, var(--felt-2) 80%);
86}
87
88.slot {
89 position: absolute;
90 overflow: hidden;
91}
92.slot-bottom {
93 bottom: 0;
94 left: var(--depth);
95 right: var(--depth);
96 height: var(--depth);
97}
98.slot-top {
99 top: 0;
100 left: var(--depth);
101 right: var(--depth);
102 height: var(--depth);
103}
104.slot-left {
105 left: 0;
106 top: 0;
107 width: var(--depth);
108 height: 100%;
109}
110.slot-right {
111 right: 0;
112 top: 0;
113 width: var(--depth);
114 height: 100%;
115}
116
117.seat {
118 position: absolute;
119 top: 50%;
120 left: 50%;
121 height: var(--depth);
122 display: flex;
123 flex-direction: column;
124 justify-content: flex-end;
125 align-items: center;
126 gap: 2px;
127 padding: 2px 8px 4px;
128 border-radius: 10px;
129 overflow: hidden;
130 transition: background 0.2s;
131}
132.slot-bottom .seat,
133.slot-top .seat {
134 width: var(--h-len);
135 --tile-w: min(calc((var(--h-len) - 40px) / 18), var(--tile-fit), 72px);
136}
137.slot-left .seat,
138.slot-right .seat {
139 width: var(--v-len);
140 --tile-w: min(calc((var(--v-len) - 40px) / 18), var(--tile-fit), 72px);
141}
142.seat.active {
143 background: linear-gradient(to top, rgba(217, 180, 92, 0.22), transparent 70%);
144}
145.seat.claiming {
146 background: linear-gradient(to top, rgba(179, 38, 30, 0.25), transparent 70%);
147 animation: pulse 1.1s ease-in-out infinite;
148}
149@keyframes pulse {
150 50% {
151 background: linear-gradient(to top, rgba(179, 38, 30, 0.45), transparent 70%);
152 }
153}
154
155/* ---------- tiles ---------- */
156/* Faces come from a 43x2 sprite sheet; the second row is the highlighted
157 variant, which we use for the tile a player has lifted to discard. */
158.tile {
159 position: relative;
160 flex: none;
161 --tw: var(--tile-w);
162 width: var(--tw);
163 height: calc(var(--tw) * 1.375);
164 border-radius: calc(var(--tw) * 0.1);
165 transition: transform 0.12s ease, filter 0.12s ease;
166}
167.tile.t-meld {
168 --tw: calc(var(--tile-w) * 0.62);
169}
170.tile.t-small {
171 --tw: calc(var(--tile-w) * 0.64);
172}
173.tile.face {
174 background-image: url('/tiles/tiles.svg');
175 background-repeat: no-repeat;
176 background-size: calc(var(--tw) * 43) calc(var(--tw) * 2.75);
177 background-position: calc(var(--col) * var(--tw) * -1) 0;
178 filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.45));
179}
180.tile.back {
181 background-image: url('/tiles/back.png');
182 background-size: 100% 100%;
183 filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.45));
184}
185.tile.tappable {
186 cursor: pointer;
187}
188.tile.raised {
189 transform: translateY(calc(var(--tw) * -0.28));
190 filter: drop-shadow(0 10px 12px rgba(0, 0, 0, 0.55));
191}
192/* Lifted tiles switch to the sheet's highlighted row. */
193.tile.face.raised {
194 background-position: calc(var(--col) * var(--tw) * -1) calc(var(--tw) * -1.375);
195}
196.tile.hl {
197 outline: 2px solid var(--gold);
198 outline-offset: 1px;
199 border-radius: calc(var(--tw) * 0.1);
200}
201.tile.dim {
202 opacity: 0.45;
203}
204
205/* ---------- seat sections ---------- */
206.hand {
207 display: flex;
208 gap: 2px;
209 /* the extra top room is where the 摸 tag sits */
210 height: calc(var(--tile-w) * 1.71 + 6px);
211 padding-top: calc(var(--tile-w) * 0.34);
212 align-items: flex-end;
213 flex: none;
214}
215/* Every hand tile sits in a draggable cell. */
216.hand-cell {
217 position: relative;
218 display: flex;
219 align-items: flex-end;
220 touch-action: none;
221 cursor: grab;
222}
223.hand-cell.dragging {
224 z-index: 5;
225 cursor: grabbing;
226}
227.hand-cell.dragging .tile {
228 transform: translateY(calc(var(--tile-w) * -0.2)) scale(1.06);
229 filter: drop-shadow(0 14px 18px rgba(0, 0, 0, 0.65));
230}
231.drawn-slot {
232 margin-left: calc(var(--tile-w) * 0.45);
233}
234.drawn-slot .tile {
235 outline: 2px solid var(--gold);
236 outline-offset: 1px;
237 border-radius: calc(var(--tw) * 0.1);
238}
239.drawn-tag {
240 position: absolute;
241 top: calc(var(--tile-w) * -0.3);
242 left: 0;
243 right: 0;
244 text-align: center;
245 font-size: calc(var(--tile-w) * 0.24);
246 font-weight: 600;
247 letter-spacing: 0.1em;
248 color: var(--gold);
249 white-space: nowrap;
250 pointer-events: none;
251}
252
253.melds {
254 display: flex;
255 gap: 10px;
256 flex-wrap: wrap;
257 justify-content: center;
258 min-height: calc(var(--tile-w) * 0.86);
259 flex: none;
260}
261.meld {
262 display: flex;
263 gap: 1px;
264}
265.meld.flowers {
266 margin-left: 12px;
267 padding-left: 12px;
268 border-left: 1px dashed rgba(246, 240, 226, 0.3);
269}
270.discards {
271 display: flex;
272 flex-wrap: wrap;
273 gap: 2px;
274 justify-content: center;
275 align-content: flex-start;
276 max-width: 94%;
277 min-height: 0;
278 margin-bottom: 2px;
279 flex: 1 1 0;
280 overflow-y: auto;
281 scrollbar-width: none;
282}
283
284.nameplate {
285 display: flex;
286 align-items: center;
287 gap: 8px;
288 font-size: 13px;
289 letter-spacing: 0.08em;
290 opacity: 0.9;
291 padding-top: 2px;
292 flex: none;
293}
294.nameplate .wind {
295 display: flex;
296 flex-direction: column;
297 align-items: center;
298 line-height: 1;
299 font-size: 18px;
300 font-weight: 900;
301 color: var(--gold);
302}
303.nameplate .wind em {
304 font-style: normal;
305 font-size: 8px;
306 font-weight: 600;
307 letter-spacing: 0.1em;
308 text-transform: uppercase;
309 opacity: 0.6;
310}
311.nameplate .wind.dealer {
312 color: #ff7a68;
313}
314.nameplate .tag {
315 font-size: 11px;
316 padding: 1px 6px;
317 border-radius: 999px;
318 background: rgba(217, 180, 92, 0.2);
319 border: 1px solid rgba(217, 180, 92, 0.5);
320}
321.nameplate .tag.ting {
322 background: rgba(46, 170, 120, 0.2);
323 border-color: rgba(46, 170, 120, 0.6);
324}
325.nameplate .tag.sacred {
326 background: rgba(179, 38, 30, 0.22);
327 border-color: rgba(224, 108, 96, 0.6);
328 color: #ffc9c2;
329}
330.nameplate .chips {
331 margin-left: 4px;
332 font-weight: 900;
333 font-size: 16px;
334 color: var(--gold);
335}
336
337.actionbar {
338 display: flex;
339 gap: 8px;
340 align-items: center;
341 justify-content: flex-end;
342 padding-right: calc(var(--tile-w) * 0.4);
343 align-self: stretch;
344 min-height: 40px;
345 flex-wrap: wrap;
346 flex: none;
347}
348.waiting {
349 font-size: 12px;
350 opacity: 0.5;
351}
352.delta {
353 font-size: 20px;
354 font-weight: 900;
355}
356.delta.up {
357 color: #5fd39a;
358}
359.delta.down {
360 color: #ff8a80;
361}
362
363/* ---------- buttons ---------- */
364.btn {
365 font-family: inherit;
366 font-size: 17px;
367 font-weight: 400;
368 color: #1a1a1a;
369 background: linear-gradient(180deg, #f3e6c4, #d9b45c);
370 border: none;
371 border-radius: 8px;
372 padding: 6px 15px;
373 min-height: 46px;
374 box-shadow: 0 2px 0 #9a7d38;
375 cursor: pointer;
376 display: inline-flex;
377 align-items: center;
378 gap: 6px;
379}
380.btn:active {
381 transform: translateY(2px);
382 box-shadow: none;
383}
384.btn-sub {
385 font-size: 12px;
386 opacity: 0.7;
387}
388
389/* Bilingual label: the called term above, English cue below. */
390.bi {
391 display: flex;
392 flex-direction: column;
393 align-items: center;
394 justify-content: center;
395 line-height: 1.05;
396 gap: 1px;
397}
398.bi .zh {
399 font-size: 19px;
400 font-weight: 400;
401 letter-spacing: 0.06em;
402}
403.bi .en {
404 font-size: 9.5px;
405 font-weight: 600;
406 letter-spacing: 0.11em;
407 text-transform: uppercase;
408 opacity: 0.68;
409 white-space: nowrap;
410}
411.bi .bi-sub {
412 font-size: 11px;
413 opacity: 0.72;
414 white-space: nowrap;
415}
416.big-btn .bi .zh {
417 font-size: 24px;
418}
419.big-btn .bi .en {
420 font-size: 11px;
421}
422.btn.claim.hu {
423 background: linear-gradient(180deg, #ff8a7a, #c0392b);
424 color: #fff;
425 box-shadow: 0 2px 0 #7c231a;
426}
427.btn.claim.kong,
428.btn.claim.pung {
429 background: linear-gradient(180deg, #8fd3ff, #2b7ec0);
430 color: #fff;
431 box-shadow: 0 2px 0 #1c527d;
432}
433.btn.claim.chow {
434 background: linear-gradient(180deg, #9be3b7, #2e9e63);
435 color: #fff;
436 box-shadow: 0 2px 0 #1d6640;
437}
438.btn.sort {
439 min-height: 20px;
440 padding: 1px 8px;
441 font-size: 11px;
442 letter-spacing: 0.06em;
443 border-radius: 999px;
444}
445.btn.proceed {
446 background: linear-gradient(180deg, #f3e6c4, #d9b45c);
447}
448.btn.pass,
449.btn.ghost {
450 background: transparent;
451 color: rgba(246, 240, 226, 0.75);
452 border: 1px solid rgba(246, 240, 226, 0.35);
453 box-shadow: none;
454}
455.btn.discard {
456 background: linear-gradient(180deg, #fff2cf, #e0c070);
457}
458.big-btn {
459 font-size: 22px;
460 padding: 12px 34px;
461 min-height: 56px;
462}
463
464/* ---------- center ---------- */
465.center {
466 position: absolute;
467 inset: var(--depth);
468 display: flex;
469 flex-direction: column;
470 align-items: center;
471 justify-content: center;
472 gap: 10px;
473 pointer-events: none;
474}
475.center > * {
476 pointer-events: auto;
477}
478/* Everything in the centre reads on top of the wall square. */
479.info,
480.last-discard,
481.prompt,
482.result,
483.info {
484 display: flex;
485 flex-direction: column;
486 align-items: center;
487 gap: 2px;
488 opacity: 0.9;
489 text-align: center;
490}
491.info .round,
492.info .wall {
493 display: flex;
494 flex-direction: column;
495 align-items: center;
496 line-height: 1.05;
497}
498.info .wall {
499 margin-top: 10px;
500 padding-top: 10px;
501 border-top: 1px solid rgba(246, 240, 226, 0.14);
502}
503.info .big {
504 font-size: 40px;
505 font-weight: 400;
506 color: var(--gold);
507}
508.info .lbl {
509 font-size: 11px;
510 letter-spacing: 0.06em;
511 opacity: 0.6;
512}
513.info .hand-no {
514 margin-top: 8px;
515 font-size: 11px;
516 opacity: 0.5;
517 letter-spacing: 0.1em;
518}
519/* The wall: a square of four staggered sides, 18 stacks of two each, drawn
520 with the tileset's own blank tile. Sits behind the centre readout. */
521.wall-ring {
522 position: absolute;
523 top: 50%;
524 left: 50%;
525 --ring: min(calc(100vh - 2 * var(--depth) - 16px), calc(100vw - 2 * var(--depth) - 16px), 560px);
526 --ws: calc(var(--ring) / 19.375);
527 --wd: calc(var(--ws) * 1.375);
528 width: var(--ring);
529 height: var(--ring);
530 transform: translate(-50%, -50%);
531 pointer-events: none;
532 z-index: 0;
533}
534.wall-side {
535 position: absolute;
536 display: flex;
537}
538/* Pinwheel: each side starts where the previous one ended. */
539.wall-side.top {
540 top: 0;
541 left: var(--wd);
542 right: 0;
543 height: var(--wd);
544}
545.wall-side.right {
546 top: var(--wd);
547 right: 0;
548 bottom: 0;
549 width: var(--wd);
550 flex-direction: column;
551}
552.wall-side.bottom {
553 bottom: 0;
554 left: 0;
555 right: var(--wd);
556 height: var(--wd);
557 flex-direction: row-reverse;
558}
559.wall-side.left {
560 top: 0;
561 left: 0;
562 bottom: var(--wd);
563 width: var(--wd);
564 flex-direction: column-reverse;
565}
566.wall-stack {
567 position: relative;
568 flex: none;
569 width: var(--ws);
570 height: var(--wd);
571}
572.wall-side.left .wall-stack,
573.wall-side.right .wall-stack {
574 width: var(--wd);
575 height: var(--ws);
576}
577.wall-stack i {
578 position: absolute;
579 top: 50%;
580 left: 50%;
581 width: var(--ws);
582 height: var(--wd);
583 margin: calc(var(--wd) / -2) 0 0 calc(var(--ws) / -2);
584 background-image: url('/tiles/back.png');
585 background-size: 100% 100%;
586 filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.45));
587}
588.wall-side.left .wall-stack i,
589.wall-side.right .wall-stack i {
590 transform: rotate(90deg);
591}
592/* One tile left in the stack. */
593.wall-stack.s1 i {
594 opacity: 0.8;
595 transform: scale(0.86);
596}
597.wall-side.left .wall-stack.s1 i,
598.wall-side.right .wall-stack.s1 i {
599 transform: rotate(90deg) scale(0.86);
600}
601/* Spent stacks stay as ghosts so the square keeps its shape. */
602.wall-stack.s0 i {
603 background: none;
604 filter: none;
605 border: 1px dashed rgba(246, 240, 226, 0.11);
606 border-radius: 2px;
607}
608.wall-stack.dead i {
609 opacity: 0.4;
610 filter: grayscale(0.6);
611}
612.wall-stack.next::after {
613 content: '';
614 position: absolute;
615 inset: -2px;
616 border: 2px solid var(--gold);
617 border-radius: 3px;
618 box-shadow: 0 0 12px rgba(217, 180, 92, 0.7);
619}
620
621.facing {
622 position: relative;
623 z-index: 1;
624 display: flex;
625 flex-direction: column;
626 align-items: center;
627 gap: 8px;
628 transition: transform 0.35s ease;
629}
630
631.last-discard {
632 display: flex;
633 flex-direction: column;
634 align-items: center;
635 gap: 6px;
636 --tile-w: 64px;
637}
638.ld-label {
639 font-size: 12px;
640 opacity: 0.6;
641}
642.prompt {
643 font-size: 15px;
644 letter-spacing: 0.1em;
645 opacity: 0.8;
646}
647.prompt.warn {
648 color: #ffb4a2;
649 font-weight: 600;
650}
651.result {
652 background: rgba(10, 30, 24, 0.94);
653 border: 1px solid rgba(217, 180, 92, 0.45);
654 border-radius: 14px;
655 padding: 18px 26px;
656 display: flex;
657 flex-direction: column;
658 align-items: center;
659 gap: 10px;
660 max-height: 90%;
661 overflow: auto;
662}
663.result h2 {
664 margin: 0;
665 font-size: 24px;
666 color: var(--gold);
667}
668.result .wt {
669 color: var(--ivory);
670 opacity: 0.8;
671}
672.tai-list {
673 display: grid;
674 grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
675 gap: 2px 18px;
676 font-size: 14px;
677 width: 100%;
678}
679.tai-item {
680 display: flex;
681 align-items: baseline;
682 justify-content: space-between;
683 gap: 12px;
684 padding: 2px 0;
685 border-bottom: 1px dotted rgba(246, 240, 226, 0.2);
686}
687.tai-name {
688 display: flex;
689 flex-direction: column;
690 line-height: 1.15;
691}
692.tai-name em {
693 font-style: normal;
694 font-size: 10px;
695 letter-spacing: 0.08em;
696 text-transform: uppercase;
697 opacity: 0.55;
698}
699.tai-val {
700 font-weight: 700;
701 color: var(--gold);
702}
703.deltas {
704 display: flex;
705 gap: 16px;
706 font-size: 14px;
707 opacity: 0.9;
708}
709.deltas .up {
710 color: #5fd39a;
711}
712.deltas .down {
713 color: #ff8a80;
714}
715
716/* ---------- help panel ---------- */
717.helpbtn {
718 margin-left: 2px;
719 width: 22px;
720 height: 22px;
721 border-radius: 50%;
722 border: 1px solid rgba(246, 240, 226, 0.35);
723 background: transparent;
724 color: rgba(246, 240, 226, 0.75);
725 font-family: inherit;
726 font-size: 12px;
727 line-height: 1;
728 cursor: pointer;
729}
730/* The rules panel gets its own deeper slot so it is comfortable to read. */
731.help-slot {
732 position: absolute;
733 inset: 0;
734 z-index: 30;
735 background: rgba(4, 18, 14, 0.55);
736}
737.help-slot.slot-bottom,
738.help-slot.slot-top,
739.help-slot.slot-left,
740.help-slot.slot-right {
741 inset: 0;
742 width: auto;
743 height: auto;
744}
745.help {
746 position: absolute;
747 top: 50%;
748 left: 50%;
749 height: var(--hd);
750 z-index: 31;
751 display: flex;
752 flex-direction: column;
753 background: rgba(8, 32, 25, 0.985);
754 border: 1px solid rgba(217, 180, 92, 0.4);
755 border-radius: 12px;
756 padding: 10px 18px 14px;
757 box-shadow: 0 18px 50px rgba(0, 0, 0, 0.6);
758}
759/* Anchored to the asking player's own edge, and rotated to face them. The
760 leading translate is applied last, so it shifts the box in screen space. */
761.help-slot.slot-bottom .help,
762.help-slot.slot-top .help {
763 width: calc(100vw - 60px);
764 --hd: min(52vh, 560px);
765 --off: calc(50vh - var(--hd) / 2 - 14px);
766}
767.help-slot.slot-left .help,
768.help-slot.slot-right .help {
769 width: calc(100vh - 60px);
770 --hd: min(52vw, 560px);
771 --off: calc(50vw - var(--hd) / 2 - 14px);
772}
773.help-slot.slot-bottom .help {
774 translate: 0 var(--off);
775}
776.help-slot.slot-top .help {
777 translate: 0 calc(var(--off) * -1);
778}
779.help-slot.slot-left .help {
780 translate: calc(var(--off) * -1) 0;
781}
782.help-slot.slot-right .help {
783 translate: var(--off) 0;
784}
785.help-head {
786 display: flex;
787 align-items: center;
788 justify-content: space-between;
789 gap: 16px;
790 flex: none;
791}
792.help-head h3 {
793 margin: 0;
794 font-size: 15px;
795 font-weight: 400;
796 letter-spacing: 0.08em;
797 color: var(--gold);
798}
799.help-head .btn {
800 min-height: 30px;
801 padding: 2px 12px;
802 font-size: 13px;
803}
804.help-body {
805 flex: 1 1 0;
806 min-height: 0;
807 overflow-y: auto;
808 columns: 4;
809 column-gap: 26px;
810 column-fill: auto;
811 padding-top: 8px;
812 overflow-x: auto;
813 scrollbar-width: thin;
814}
815.help-body section {
816 break-inside: avoid;
817 margin-bottom: 10px;
818}
819.help-body h4 {
820 margin: 0 0 2px;
821 font-size: 13px;
822 font-weight: 400;
823 color: var(--gold);
824 letter-spacing: 0.06em;
825}
826.help-body h4 em {
827 font-style: normal;
828 font-size: 9px;
829 letter-spacing: 0.12em;
830 text-transform: uppercase;
831 opacity: 0.55;
832 margin-left: 4px;
833}
834.help-body p {
835 margin: 0 0 4px;
836 display: flex;
837 flex-direction: column;
838 line-height: 1.35;
839 font-size: 11.5px;
840}
841.help-body p em {
842 font-style: normal;
843 font-size: 10.5px;
844 opacity: 0.6;
845}
846.help-body .credit {
847 opacity: 0.6;
848}
849
850/* ---------- lobby resume ---------- */
851.lobby .sub {
852 font-size: 0.95rem;
853}
854.resume {
855 margin-top: 1.4rem;
856 padding: 12px 26px;
857 border: 1px solid rgba(217, 180, 92, 0.35);
858 border-radius: 12px;
859 background: rgba(0, 0, 0, 0.2);
860 text-align: center;
861 display: flex;
862 flex-direction: column;
863 gap: 6px;
864}
865.resume-line {
866 font-size: 14px;
867 color: var(--gold);
868 letter-spacing: 0.06em;
869}
870.resume-scores {
871 display: flex;
872 gap: 18px;
873 justify-content: center;
874 font-size: 13px;
875 opacity: 0.8;
876}
877.resume-scores b {
878 color: var(--gold);
879 font-weight: 600;
880}
881.resume-when {
882 font-size: 11px;
883 opacity: 0.45;
884 letter-spacing: 0.08em;
885}
886.lobby-buttons {
887 display: flex;
888 gap: 14px;
889 margin-top: 1.6rem;
890 align-items: center;
891}
892
893/* ---------- sound ---------- */
894.lobby-extras {
895 margin-top: 1.4rem;
896 display: flex;
897 gap: 12px;
898 align-items: center;
899}
900/* Small rounded button for the things that sit under the main choices. */
901.btn.pill {
902 min-height: 34px;
903 padding: 2px 14px;
904 font-size: 13px;
905 letter-spacing: 0.06em;
906 border-radius: 999px;
907 gap: 8px;
908}
909.sound-toggle.on {
910 border-color: rgba(217, 180, 92, 0.7);
911 color: var(--gold);
912}
913.sound-toggle.compact {
914 min-height: 28px;
915 padding: 2px 9px;
916 font-size: 15px;
917}
918.sound-toggle .spk {
919 font-size: 15px;
920 line-height: 1;
921}
922
923/* ---------- shared table controls ---------- */
924/* Bottom-right of the centre square, opposite the log. Unrotated on purpose:
925 it belongs to the table, not to a seat. */
926.table-controls {
927 position: absolute;
928 right: 10px;
929 bottom: 8px;
930 display: flex;
931 align-items: center;
932 gap: 8px;
933}
934.btn.undo {
935 min-height: 34px;
936 padding: 3px 14px;
937 border-radius: 999px;
938 gap: 9px;
939 max-width: 40vh;
940}
941.undo-arrow {
942 font-size: 17px;
943 line-height: 1;
944 color: var(--gold);
945}
946.undo-what {
947 display: flex;
948 flex-direction: column;
949 align-items: flex-start;
950 line-height: 1.15;
951 min-width: 0;
952}
953.undo-what .zh {
954 font-size: 13px;
955 letter-spacing: 0.05em;
956}
957.undo-what .en {
958 font-size: 9px;
959 letter-spacing: 0.09em;
960 text-transform: uppercase;
961 opacity: 0.55;
962 white-space: nowrap;
963 overflow: hidden;
964 text-overflow: ellipsis;
965 max-width: 100%;
966}
967
968/* ---------- result: one block per winner ---------- */
969.result .win {
970 display: flex;
971 flex-direction: column;
972 align-items: center;
973 gap: 8px;
974 width: 100%;
975}
976.result .win + .win {
977 padding-top: 10px;
978 border-top: 1px solid rgba(217, 180, 92, 0.3);
979}
980.result .liable {
981 font-size: 12px;
982 letter-spacing: 0.08em;
983 color: #ffb4a2;
984}
985.result .multi {
986 font-size: 12px;
987 letter-spacing: 0.1em;
988 color: var(--gold);
989 opacity: 0.85;
990}
991
992/* ---------- settings ---------- */
993.over-buttons {
994 display: flex;
995 gap: 12px;
996 align-items: center;
997}
998.settings-scrim {
999 position: absolute;
1000 inset: 0;
1001 z-index: 40;
1002 background: rgba(4, 18, 14, 0.72);
1003 display: flex;
1004 align-items: center;
1005 justify-content: center;
1006 padding: 20px;
1007}
1008.settings {
1009 width: min(1180px, 100%);
1010 max-height: 100%;
1011 display: flex;
1012 flex-direction: column;
1013 background: rgba(8, 32, 25, 0.99);
1014 border: 1px solid rgba(217, 180, 92, 0.4);
1015 border-radius: 14px;
1016 box-shadow: 0 18px 50px rgba(0, 0, 0, 0.6);
1017 padding: 16px 28px 22px;
1018}
1019.settings-head {
1020 display: flex;
1021 align-items: center;
1022 justify-content: space-between;
1023 gap: 16px;
1024 flex: none;
1025 padding-bottom: 12px;
1026 border-bottom: 1px solid rgba(246, 240, 226, 0.12);
1027}
1028.settings-head h3 {
1029 margin: 0;
1030 font-size: 22px;
1031 font-weight: 400;
1032 letter-spacing: 0.08em;
1033 color: var(--gold);
1034}
1035.settings-head-btns {
1036 display: flex;
1037 gap: 10px;
1038}
1039.settings-head .btn {
1040 min-height: 46px;
1041 padding: 2px 22px;
1042 font-size: 17px;
1043}
1044.settings-body {
1045 /* `1 1 auto`, not `1 1 0`: the panel's own height comes from this content,
1046 so a zero basis collapses the pair of them to nothing. `max-height` on the
1047 panel is what brings the scrollbar back at the other end. */
1048 flex: 1 1 auto;
1049 min-height: 0;
1050 overflow-y: auto;
1051 scrollbar-width: thin;
1052 padding-top: 14px;
1053 /* Columns rather than a grid: grid rows would size to the tallest section
1054 and leave the shorter one padded with air, which is what pushed the last
1055 house rule off the bottom. */
1056 columns: 2;
1057 column-gap: 44px;
1058}
1059.settings-body section {
1060 break-inside: avoid;
1061 margin-bottom: 22px;
1062}
1063.settings-body h4 {
1064 margin: 0 0 10px;
1065 font-size: 16px;
1066 font-weight: 400;
1067 color: var(--gold);
1068 letter-spacing: 0.06em;
1069}
1070.settings-body h4 em {
1071 font-style: normal;
1072 font-size: 11px;
1073 letter-spacing: 0.12em;
1074 text-transform: uppercase;
1075 opacity: 0.55;
1076 margin-left: 5px;
1077}
1078.settings .field {
1079 display: flex;
1080 align-items: center;
1081 gap: 14px;
1082 padding: 5px 0;
1083}
1084.settings .f-label {
1085 display: flex;
1086 align-items: baseline;
1087 gap: 6px;
1088 font-size: 16px;
1089 /* Wide enough for 起始籌碼 STARTING CHIPS, so every input in a section
1090 starts at the same place. */
1091 min-width: 196px;
1092 opacity: 0.85;
1093}
1094/* ...except the player rows, which are labelled 1–4 and need no such room. */
1095.settings .names .f-label {
1096 min-width: 26px;
1097}
1098.settings .f-label em {
1099 font-style: normal;
1100 font-size: 11px;
1101 letter-spacing: 0.1em;
1102 text-transform: uppercase;
1103 opacity: 0.55;
1104}
1105.settings input[type='text'],
1106.settings input:not([type]),
1107.settings input[type='number'] {
1108 flex: 1 1 0;
1109 min-width: 0;
1110 font-family: inherit;
1111 font-size: 18px;
1112 color: var(--ivory);
1113 background: rgba(0, 0, 0, 0.28);
1114 border: 1px solid rgba(246, 240, 226, 0.25);
1115 border-radius: 8px;
1116 padding: 11px 14px;
1117 min-height: 48px;
1118 user-select: text;
1119}
1120.settings input:focus {
1121 outline: none;
1122 border-color: rgba(217, 180, 92, 0.8);
1123}
1124.settings input[type='number'] {
1125 max-width: 150px;
1126}
1127.settings input[type='range'] {
1128 flex: 1 1 0;
1129 height: 34px;
1130 accent-color: var(--gold);
1131}
1132.settings input:disabled {
1133 opacity: 0.4;
1134}
1135.settings .switch {
1136 display: grid;
1137 grid-template-columns: auto 1fr;
1138 gap: 3px 14px;
1139 align-items: center;
1140 padding: 9px 0;
1141 cursor: pointer;
1142}
1143.settings .switch input {
1144 width: 26px;
1145 height: 26px;
1146 accent-color: var(--gold);
1147 cursor: pointer;
1148}
1149.settings .sw-name {
1150 display: flex;
1151 align-items: baseline;
1152 gap: 8px;
1153 font-size: 17px;
1154}
1155.settings .sw-name em {
1156 font-style: normal;
1157 font-size: 11px;
1158 letter-spacing: 0.1em;
1159 text-transform: uppercase;
1160 opacity: 0.55;
1161}
1162.settings .note {
1163 grid-column: 2;
1164 font-size: 13px;
1165 line-height: 1.4;
1166 opacity: 0.55;
1167}
1168.settings .switch.dead {
1169 opacity: 0.4;
1170 cursor: default;
1171}
1172.settings .note.lock {
1173 grid-column: auto;
1174 margin: 4px 0 0;
1175 color: #ffb4a2;
1176 opacity: 0.75;
1177}