anvilsign in

collin/mahjong · d5af31aa

Buttons are tiles, and the wall is a ladder

Collin Richards · 2026-08-25 08:13 UTC · d5af31aa6402b7f6acea8dcf81a2794ae24c5319 · parent bf80fd25 · browse files

modifiedsrc/game/wall.ts+10 −4
⋯ 154 unchanged lines
155155 * `ui/WallRing` is for. `x` is across the table and `y` down it, both in tiles
156156 * so the placement carries to any window. Nought is the wall left where it was
157157 * built. In `WALL_SIDES` order.
158+ *
159+ * A ladder, as it stands: the two flat walls drawn in towards each other until
160+ * the band they leave between them is the room the four strips actually leave,
161+ * and the two upright ones pushed out past the ends of it. Eighteen full-size
162+ * stacks is longer than the middle of a table is deep, so something has to
163+ * overhang; this is a choice about *what* does.
158164 */
159165 export const WALL_PLACED: WallNudge[] = [
160- { x: 0, y: 0 },
161- { x: -1.98, y: -6.7 },
162- { x: 0.52, y: -4.91 },
163- { x: -1.11, y: 0.46 },
166+ { x: -0.47, y: 5.06 },
167+ { x: 1.29, y: -0.76 },
168+ { x: 0.88, y: -4.31 },
169+ { x: -1.6, y: 1.13 },
164170 ];
165171
166172 /** How far a wall has been pushed from where it was built, in tiles. */
⋯ 106 unchanged lines
modifiedsrc/styles.css+92 −8
⋯ 10 unchanged lines
1111 --depth: clamp(226px, 30vh, 307px);
1212 --h-len: max(160px, calc(100vw - 2 * var(--depth)));
1313 --v-len: 100vh;
14- /* Height the action buttons occupy, held whether or not any are showing.
15- The strip is built from its edge inwards, so a bar that grew when 打出
16- appeared would shove the melds and discards along with it — the reservation
17- is what keeps everything above it still. Sized for the tallest button: the
18- ones that name a tile (打出 五萬, 吃 三萬 四萬) carry a third line. */
19- --bar-h: 52px;
14+ /* How tall an action button is: a tile, because that is what they are now.
15+ They sit in the row your hand is in, in the room it already keeps above the
16+ tiles, and they are the same tile as the ones under them — 打出 and 碰 are
17+ things you do with a tile, so they are drawn as one. */
18+ --bar-h: calc(var(--tile-w) * 1.375);
2019 /* Largest tile a strip can hold. Edge inwards it has to fit the melds (a
2120 full tile, 1.375 tall, since they are the same tiles as the ones in the
2221 hand), the button bar, the hand (1.71 + 6px) and the nameplate (28px), plus
⋯ 10 unchanged lines
3332 rather than the tiles growing, so a tile is the size it always was and the
3433 centre is bigger.
3534
35+ And it used to be 122px rather than 70px: the missing 52 is the action bar,
36+ which had a row of its own and had to be budgeted for whether or not
37+ anything was on it. It has no row now — it hangs at the end of the row the
38+ hand is in, out of the flow — so the strip stopped paying for one.
39+
3640 Tile size otherwise follows the strip's *length*, which is why a window
3741 with less height than F11 kept full-size tiles and left the strip's
3842 contents to be cut off. */
39- --tile-fit: calc((var(--depth) - 122px) / 3.085);
43+ --tile-fit: calc((var(--depth) - 70px) / 3.085);
4044
4145 /* One size for every tile on the table — in a hand, in the wall, and lying in
4246 the middle. They are the same tiles, so drawing them at different sizes was
⋯ 404 unchanged lines
447451 height: 100%;
448452 display: flex;
449453 gap: 8px;
450- align-items: center;
454+ /* On the same line the tiles stand on, since they are tiles too. */
455+ align-items: flex-end;
451456 justify-content: flex-end;
452457 padding-right: calc(var(--tile-w) * 0.4);
453458 flex-wrap: wrap;
⋯ 130 unchanged lines
584589 .btn.discard {
585590 background: linear-gradient(180deg, #fff2cf, #e0c070);
586591 }
592+
593+/* ---------- the action buttons are tiles ---------- */
594+/* 打出, 碰, 吃, 槓, 胡, 過 are all things you do *with* a tile, and they sit in
595+ the row your tiles are in — so they are drawn as tiles. Exactly the size of
596+ the ones under them, `--tile-w` by 1.375 of it, ivory face and all, in the
597+ room the hand row already keeps above its tiles for the 摸 tag. The room is
598+ kept whether or not anything is on the bar, which is why the strip does not
599+ move when one arrives.
600+
601+ Ivory, not coloured: a mahjong tile is ivory and it is the *character* that
602+ is red or green. So the call takes the colour and the face never does.
603+
604+ Full size only. A phone's bar is a row of its own with room to write on, and
605+ a thumb wants a button it can hit. */
606+:root:not(.compact) .actionbar .btn {
607+ flex-direction: column;
608+ width: var(--tile-w);
609+ height: var(--bar-h);
610+ min-height: 0;
611+ padding: 2px 1px;
612+ gap: 0;
613+ border-radius: calc(var(--tile-w) * 0.1);
614+ background: linear-gradient(180deg, var(--ivory), var(--ivory-edge));
615+ color: var(--ink);
616+ border: none;
617+ box-shadow: 0 2px 3px rgba(0, 0, 0, 0.45), inset 0 calc(var(--tile-w) * -0.06) 0 rgba(0, 0, 0, 0.09);
618+ overflow: hidden;
619+}
620+:root:not(.compact) .actionbar .btn:active {
621+ transform: translateY(1px);
622+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.45);
623+}
624+/* The call, the size a tile's own character is drawn at. Two of them fit
625+ across a tile; 過.摸牌 is four, and wraps rather than being cut. */
626+:root:not(.compact) .actionbar .btn .bi {
627+ gap: 0;
628+ line-height: 1.02;
629+}
630+:root:not(.compact) .actionbar .btn .bi .zh {
631+ font-size: calc(var(--tile-w) * 0.44);
632+ letter-spacing: 0;
633+ word-break: break-all;
634+}
635+:root:not(.compact) .actionbar .btn .bi .en {
636+ font-size: calc(var(--tile-w) * 0.185);
637+ letter-spacing: 0.03em;
638+ white-space: normal;
639+ opacity: 0.6;
640+}
641+/* Which tile it is about — 打出 五萬, 吃 三萬 四萬. Small, because the tile it
642+ names is lifted out of the row right beside it. */
643+:root:not(.compact) .actionbar .btn .bi .bi-sub {
644+ font-size: calc(var(--tile-w) * 0.22);
645+ white-space: normal;
646+ opacity: 0.75;
647+}
648+/* The character carries the colour, the way the dragons do. */
649+:root:not(.compact) .actionbar .btn.claim.hu {
650+ color: #b3261e;
651+}
652+:root:not(.compact) .actionbar .btn.claim.pung,
653+:root:not(.compact) .actionbar .btn.claim.kong {
654+ color: #1c527d;
655+}
656+:root:not(.compact) .actionbar .btn.claim.chow {
657+ color: #1d6640;
658+}
659+/* 過 and 摸牌 are not calls, so they are the plain face — and a pass reads as
660+ the quiet one it is. */
661+:root:not(.compact) .actionbar .btn.pass,
662+:root:not(.compact) .actionbar .btn.ghost {
663+ color: rgba(33, 38, 43, 0.65);
664+}
665+/* The one that plays a tile: the gold edge every other gold button has, kept
666+ as a rim rather than a face. */
667+:root:not(.compact) .actionbar .btn.discard,
668+:root:not(.compact) .actionbar .btn.proceed {
669+ box-shadow: 0 2px 3px rgba(0, 0, 0, 0.45), inset 0 0 0 2px var(--gold);
670+}
587671 .big-btn {
588672 font-size: 22px;
589673 padding: 12px 34px;
⋯ 1862 unchanged lines