Merge pull request 'feat(ui): last-word letter highlight + dark bonus-square contrast' (#50) from feature/board-recent-highlight-and-dark-bonus into development
CI / changes (push) Successful in 2s
CI / unit (push) Has been skipped
CI / integration (push) Has been skipped
CI / ui (push) Successful in 44s
CI / gate (push) Successful in 0s
CI / deploy (push) Successful in 1m0s

This commit was merged in pull request #50.
This commit is contained in:
2026-06-12 11:12:04 +00:00
3 changed files with 35 additions and 27 deletions
+5 -3
View File
@@ -123,9 +123,11 @@ Login uses `Screen`.
overlays the empty area below, so the layout doesn't resize/jank; other modals stay overlays the empty area below, so the layout doesn't resize/jank; other modals stay
keyboard-aware (they size to the area above the keyboard). keyboard-aware (they size to the area above the keyboard).
- **Highlights**: pending tiles use a slightly darker tile background (no outline). The - **Highlights**: pending tiles use a slightly darker tile background (no outline). The
last completed word gets a dark tile background — static while it is the opponent's last completed word keeps the normal tile background; instead its letters — not the point
turn (our word), and a 1 s flash when it is our turn (their word). While placing, only values — are drawn in the recent-move colour, in both themes. It is static while it is the
the pending tiles are highlighted. opponent's turn (our word), and a 1 s flash (the letter pulses between its normal colour
and the recent-move colour) when it is our turn (their word). While placing, only the
pending tiles are highlighted.
- **Bonus-square labels** — a Settings choice (`boardlabels.ts`): `beginner` shows a - **Bonus-square labels** — a Settings choice (`boardlabels.ts`): `beginner` shows a
split `3×` / `word` (localized слово/буква), `classic` a single `3W` / `3С`, `none` split `3×` / `word` (localized слово/буква), `classic` a single `3W` / `3С`, `none`
nothing. Default **beginner**. nothing. Default **beginner**.
+16 -11
View File
@@ -29,7 +29,9 @@
--tile-edge: #d8c190; --tile-edge: #d8c190;
--tile-text: #2a2113; --tile-text: #2a2113;
--tile-pending: #f2cf73; --tile-pending: #f2cf73;
--tile-recent: #c8a85c; /* Last-word highlight letter — a lighter burgundy than the dark theme on purpose: against
the lighter tile the perceived contrast needs it, so the two are tuned per theme. */
--tile-recent: #9c5849;
--prem-tw: #e06a5b; /* triple word */ --prem-tw: #e06a5b; /* triple word */
--prem-dw: #efa6a0; /* double word + centre */ --prem-dw: #efa6a0; /* double word + centre */
--prem-tl: #4f8fd6; /* triple letter */ --prem-tl: #4f8fd6; /* triple letter */
@@ -75,11 +77,11 @@
--tile-edge: #b6a473; --tile-edge: #b6a473;
--tile-text: #20190d; --tile-text: #20190d;
--tile-pending: #d8b75e; --tile-pending: #d8b75e;
--tile-recent: #7a6638; --tile-recent: #8c4a3c;
--prem-tw: #b1493d; --prem-tw: #9c3f34; /* 3x word: a touch darker red */
--prem-dw: #8c5450; --prem-dw: #a8636b; /* 2x word: softer, pinker */
--prem-tl: #34608f; --prem-tl: #2c527a; /* 3x letter: a touch darker blue */
--prem-dl: #3b5a72; --prem-dl: #4a779b; /* 2x letter: softer, sky blue */
--prem-text: #e7eaf0; --prem-text: #e7eaf0;
} }
} }
@@ -106,11 +108,14 @@
--tile-edge: #b6a473; --tile-edge: #b6a473;
--tile-text: #20190d; --tile-text: #20190d;
--tile-pending: #f0d98f; --tile-pending: #f0d98f;
--tile-recent: #4a4636; /* Last-word highlight letter — a warm burgundy whose red hue stays distinct from both the
--prem-tw: #b1493d; near-black glyph and the warm tile. The light theme uses a lighter burgundy (tuned per
--prem-dw: #8c5450; theme; perceived contrast depends on the surrounding board). */
--prem-tl: #34608f; --tile-recent: #8c4a3c;
--prem-dl: #3b5a72; --prem-tw: #9c3f34; /* 3x word: a touch darker red */
--prem-dw: #a8636b; /* 2x word: softer, pinker */
--prem-tl: #2c527a; /* 3x letter: a touch darker blue */
--prem-dl: #4a779b; /* 2x letter: softer, sky blue */
--prem-text: #e7eaf0; --prem-text: #e7eaf0;
} }
+14 -13
View File
@@ -314,25 +314,26 @@
box-shadow: inset 0 0 0 2px var(--accent); box-shadow: inset 0 0 0 2px var(--accent);
background: color-mix(in srgb, var(--accent) 18%, var(--cell-bg)); background: color-mix(in srgb, var(--accent) 18%, var(--cell-bg));
} }
.cell.hl { /* Last-word highlight: the tile keeps its normal fill (same as every other placed tile);
background: var(--tile-recent); instead the letter glyph — not the point value — is drawn in the recent-move colour, in
/* The bottom edge goes darker than the highlighted fill (not lighter, as the plain both themes. */
--tile-edge would), so the tile still reads as raised. */ .cell.hl .letter,
box-shadow: inset 0 -2px 0 rgba(0, 0, 0, 0.32); .cell.flash .letter {
color: var(--tile-recent);
} }
.cell.flash { .cell.flash .letter {
/* Two flashes to draw the eye, then settle back to normal so it does not distract. */ /* When the opponent just moved and it is now our turn, the highlighted letter pulses
animation: tileflash 1s ease-in-out 2; twice between its normal colour and the recent-move colour to draw the eye, then
settles on the recent colour (matching .hl). The tile background never animates. */
animation: letterflash 1s ease-in-out 2;
} }
@keyframes tileflash { @keyframes letterflash {
0%, 0%,
100% { 100% {
background: var(--tile-bg); color: var(--tile-recent);
box-shadow: inset 0 -2px 0 var(--tile-edge);
} }
50% { 50% {
background: var(--tile-recent); color: var(--tile-text);
box-shadow: inset 0 -2px 0 rgba(0, 0, 0, 0.32);
} }
} }
/* cqw fonts are sized against the fixed viewport, so labels stay a constant size as /* cqw fonts are sized against the fixed viewport, so labels stay a constant size as