feat(engine): switch card fronts to 4-colour deck
Hearts pink (`#fb9fb1`), Diamonds gold (`#ddb26f`), Clubs lime (`#acc267`), Spades gray (`#d0d0d0`) — each suit picks up its own base16-eighties accent so a player scanning the table can distinguish the suit by hue alone (faster recognition than the 2-colour traditional red/black scheme; common in poker decks). All four colours already exist in the palette as semantic state-token accents, so this is a pure remapping at the suit- glyph site, not a palette extension. The outlined-glyph differentiation (♦ ♣ outlined, ♥ ♠ filled) is preserved on top of the colour split — it stays the always- on colour-blind fallback per `design-system.md` §Accessibility, and matters more than ever now that CBM hearts (lime) and default clubs (lime) share a hue. ### Changes - `card_face_svg.rs`: split `SUIT_RED` / `SUIT_DARK` into four per-suit constants (`SUIT_HEART` / `SUIT_DIAMOND` / `SUIT_CLUB` / `SUIT_SPADE`). `suit_paint()` returns each suit's own colour. Card border picks up the suit colour automatically via the existing `(colour, paint)` destructure. - `card_plugin.rs`: new `DIAMOND_SUIT_COLOUR` + `CLUB_SUIT_COLOUR` constants; `text_colour()` rewritten as a per-suit match (was red/black bifurcation). Both rendering paths (PNG production + constant fallback under MinimalPlugins) stay in lockstep. - CBM behaviour clarified: only hearts swap to lime now; diamonds + clubs + spades are already hue-distinct from the heart pink and stay unchanged. Under CBM the heart (lime) and club (lime) share a hue but stay distinguishable via the always-on filled-vs-outlined glyph differentiation. - HC behaviour: only hearts (→ HC red) and spades (→ HC white) have defined boosts. Diamonds (gold) and clubs (lime) are already mid-luminance accents and stay at their default. New test `text_colour_diamonds_and_clubs_are_immune_to_accessibility_flags` pins all four flag combinations as no-ops for the gold + lime suits. - `design-system.md` §Suit Colors retitled "Four-color deck" with the 4-colour table; CBM section text updated to describe the hearts-only swap and the hearts/clubs hue collision under CBM. - `card_face_svg_pin.rs` rebaselined: 26 hashes drift (13 clubs + 13 diamonds — the two suits whose colours changed). Hearts, spades, and the 5 backs all keep their prior hashes. Surgical scope, exactly what the pin test was designed to surface. ### Tests 1191 passing / 0 failing — net 0 from the prior baseline: two old 2-colour tests removed (`text_colour_is_red_for_hearts_and_diamonds`, `text_colour_is_black_for_clubs_and_spades`), one consolidated 4-colour test added (`text_colour_4_colour_deck_assigns_each_suit_its_own_hue`) plus a pairwise-distinct invariant guard, and one new test covering the gold/lime suits' immunity to CBM/HC flags. Six existing CBM/HC tests rewritten to use only the suits each flag actually affects under the new scheme (hearts for CBM, hearts + spades for HC). Workspace clippy clean. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
@@ -137,18 +137,22 @@ The palette is base16-eighties — a 16-slot terminal palette where indices 00
|
||||
|
||||
## Suit Colors
|
||||
|
||||
**Two-color traditional mapping**, with mandatory color-blind support:
|
||||
**Four-color deck**, with mandatory color-blind support. Each suit
|
||||
picks up its own base16-eighties accent so a player scanning the
|
||||
table can identify the suit by hue alone (faster than the
|
||||
traditional 2-color red/black mapping; common in poker decks and
|
||||
online card games):
|
||||
|
||||
| Suit | Default | Color-blind mode | Glyph differentiation |
|
||||
|---|---|---|---|
|
||||
| Hearts | `#fb9fb1` (pink) | `#acc267` (lime) | Solid filled glyph |
|
||||
| Diamonds | `#fb9fb1` (pink) | `#acc267` (lime) | **Outlined glyph (1.5px stroke)** |
|
||||
| Spades | `#d0d0d0` (foreground) | `#d0d0d0` | Solid filled glyph |
|
||||
| Clubs | `#d0d0d0` (foreground) | `#d0d0d0` | **Outlined glyph (1.5px stroke)** |
|
||||
| Hearts | `#fb9fb1` (pink, base08) | `#acc267` (lime) | Solid filled glyph |
|
||||
| Diamonds | `#ddb26f` (gold, base09) | `#ddb26f` (unchanged) | **Outlined glyph (1.5px stroke)** |
|
||||
| Spades | `#d0d0d0` (foreground, base05) | `#d0d0d0` (unchanged) | Solid filled glyph |
|
||||
| Clubs | `#acc267` (lime, base0A) | `#acc267` (unchanged) | **Outlined glyph (1.5px stroke)** |
|
||||
|
||||
The outlined-glyph treatment is the **primary** differentiation mechanism. Color is supplementary. This means a player viewing the game on a monochrome display, or with severe red-green deficiency, can still distinguish all four suits without context. This is a hard requirement, not an optional setting.
|
||||
|
||||
The "color-blind mode" toggle in Settings only swaps red→lime; it does not turn the outlined glyphs on or off, because outlined glyphs are always on. (Was red→cyan before the 2026-05-08 primary-accent swap; CBM moved to lime to stay hue-distinct from the new red-family primary.)
|
||||
The "color-blind mode" toggle in Settings only swaps the heart suit colour from pink to lime; the other three suits (diamonds gold, clubs lime, spades gray) are already hue-distinct from pink and stay unchanged. The toggle does not turn the outlined glyphs on or off, because outlined glyphs are always on. Note: under CBM with the 4-colour deck, hearts and clubs share the lime hue — the always-on filled-vs-outlined glyph differentiation (♥ filled, ♣ outlined) keeps them readable. (Was red→cyan before the 2026-05-08 primary-accent swap; CBM moved to lime to stay hue-distinct from the new red-family primary.)
|
||||
|
||||
## Typography
|
||||
|
||||
@@ -272,7 +276,7 @@ Top-right corner of the HUD: a 6px circular dot.
|
||||
|
||||
## Accessibility
|
||||
|
||||
1. **Color-blind mode** (Settings → Gameplay): swaps red suits' default `#fb9fb1` for `#acc267` (lime). Outlined-glyph differentiation remains active in *all* modes.
|
||||
1. **Color-blind mode** (Settings → Gameplay): swaps the heart suit colour from `#fb9fb1` (pink) to `#acc267` (lime). The other three suits in the 4-colour deck (diamonds gold, clubs lime, spades gray) are already hue-distinct and stay unchanged. Outlined-glyph differentiation remains active in *all* modes.
|
||||
2. **High-contrast mode** (Settings → Gameplay): boosts on-surface from `#d0d0d0` to `#f5f5f5`, outline from `#505050` to `#a0a0a0`, suit-red from `#fb9fb1` to `#ff8aa0`.
|
||||
3. **Reduce-motion mode** (Settings → Gameplay): disables card-lift transition (instant z-lift), disables CRT scanline effect, disables the warning-chip pulse animation.
|
||||
4. **Tabular figures** are mandatory for any number that updates live (timer, score, moves) so they don't reflow.
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="384" viewBox="0 0 256 384">
|
||||
<rect x="1" y="1" width="254" height="382" rx="16" ry="16"
|
||||
fill="#1a1a1a" stroke="#d0d0d0" stroke-width="2"/>
|
||||
fill="#1a1a1a" stroke="#acc267" stroke-width="2"/>
|
||||
|
||||
<!-- Top-left rank in JetBrains-Mono-styled FiraMono (rank digits
|
||||
and letters render correctly in FiraMono; only the suit glyphs
|
||||
needed to escape to paths). -->
|
||||
<text x="14" y="44" font-family="Fira Mono" font-size="36" font-weight="700"
|
||||
fill="#d0d0d0">10</text>
|
||||
fill="#acc267">10</text>
|
||||
|
||||
<!-- Top-left small suit glyph at (14, 50), 20 × 20.
|
||||
`suit_path_d` is authored in a 32-unit box, so scale 0.625
|
||||
lands the visible glyph at 20 px. -->
|
||||
<g transform="translate(14 50) scale(0.625)">
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#d0d0d0" stroke-width="3"/>
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#acc267" stroke-width="3"/>
|
||||
</g>
|
||||
|
||||
<!-- Bottom-right large suit glyph at (178, 286), 64 × 64.
|
||||
@@ -20,6 +20,6 @@
|
||||
(178, 286). Same upright orientation as the top-left small
|
||||
glyph — no 180° rotation applied. -->
|
||||
<g transform="translate(178 286) scale(2)">
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#d0d0d0" stroke-width="3"/>
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#acc267" stroke-width="3"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
@@ -1,18 +1,18 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="384" viewBox="0 0 256 384">
|
||||
<rect x="1" y="1" width="254" height="382" rx="16" ry="16"
|
||||
fill="#1a1a1a" stroke="#d0d0d0" stroke-width="2"/>
|
||||
fill="#1a1a1a" stroke="#acc267" stroke-width="2"/>
|
||||
|
||||
<!-- Top-left rank in JetBrains-Mono-styled FiraMono (rank digits
|
||||
and letters render correctly in FiraMono; only the suit glyphs
|
||||
needed to escape to paths). -->
|
||||
<text x="14" y="44" font-family="Fira Mono" font-size="36" font-weight="700"
|
||||
fill="#d0d0d0">2</text>
|
||||
fill="#acc267">2</text>
|
||||
|
||||
<!-- Top-left small suit glyph at (14, 50), 20 × 20.
|
||||
`suit_path_d` is authored in a 32-unit box, so scale 0.625
|
||||
lands the visible glyph at 20 px. -->
|
||||
<g transform="translate(14 50) scale(0.625)">
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#d0d0d0" stroke-width="3"/>
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#acc267" stroke-width="3"/>
|
||||
</g>
|
||||
|
||||
<!-- Bottom-right large suit glyph at (178, 286), 64 × 64.
|
||||
@@ -20,6 +20,6 @@
|
||||
(178, 286). Same upright orientation as the top-left small
|
||||
glyph — no 180° rotation applied. -->
|
||||
<g transform="translate(178 286) scale(2)">
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#d0d0d0" stroke-width="3"/>
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#acc267" stroke-width="3"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
@@ -1,18 +1,18 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="384" viewBox="0 0 256 384">
|
||||
<rect x="1" y="1" width="254" height="382" rx="16" ry="16"
|
||||
fill="#1a1a1a" stroke="#d0d0d0" stroke-width="2"/>
|
||||
fill="#1a1a1a" stroke="#acc267" stroke-width="2"/>
|
||||
|
||||
<!-- Top-left rank in JetBrains-Mono-styled FiraMono (rank digits
|
||||
and letters render correctly in FiraMono; only the suit glyphs
|
||||
needed to escape to paths). -->
|
||||
<text x="14" y="44" font-family="Fira Mono" font-size="36" font-weight="700"
|
||||
fill="#d0d0d0">3</text>
|
||||
fill="#acc267">3</text>
|
||||
|
||||
<!-- Top-left small suit glyph at (14, 50), 20 × 20.
|
||||
`suit_path_d` is authored in a 32-unit box, so scale 0.625
|
||||
lands the visible glyph at 20 px. -->
|
||||
<g transform="translate(14 50) scale(0.625)">
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#d0d0d0" stroke-width="3"/>
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#acc267" stroke-width="3"/>
|
||||
</g>
|
||||
|
||||
<!-- Bottom-right large suit glyph at (178, 286), 64 × 64.
|
||||
@@ -20,6 +20,6 @@
|
||||
(178, 286). Same upright orientation as the top-left small
|
||||
glyph — no 180° rotation applied. -->
|
||||
<g transform="translate(178 286) scale(2)">
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#d0d0d0" stroke-width="3"/>
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#acc267" stroke-width="3"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
@@ -1,18 +1,18 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="384" viewBox="0 0 256 384">
|
||||
<rect x="1" y="1" width="254" height="382" rx="16" ry="16"
|
||||
fill="#1a1a1a" stroke="#d0d0d0" stroke-width="2"/>
|
||||
fill="#1a1a1a" stroke="#acc267" stroke-width="2"/>
|
||||
|
||||
<!-- Top-left rank in JetBrains-Mono-styled FiraMono (rank digits
|
||||
and letters render correctly in FiraMono; only the suit glyphs
|
||||
needed to escape to paths). -->
|
||||
<text x="14" y="44" font-family="Fira Mono" font-size="36" font-weight="700"
|
||||
fill="#d0d0d0">4</text>
|
||||
fill="#acc267">4</text>
|
||||
|
||||
<!-- Top-left small suit glyph at (14, 50), 20 × 20.
|
||||
`suit_path_d` is authored in a 32-unit box, so scale 0.625
|
||||
lands the visible glyph at 20 px. -->
|
||||
<g transform="translate(14 50) scale(0.625)">
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#d0d0d0" stroke-width="3"/>
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#acc267" stroke-width="3"/>
|
||||
</g>
|
||||
|
||||
<!-- Bottom-right large suit glyph at (178, 286), 64 × 64.
|
||||
@@ -20,6 +20,6 @@
|
||||
(178, 286). Same upright orientation as the top-left small
|
||||
glyph — no 180° rotation applied. -->
|
||||
<g transform="translate(178 286) scale(2)">
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#d0d0d0" stroke-width="3"/>
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#acc267" stroke-width="3"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
@@ -1,18 +1,18 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="384" viewBox="0 0 256 384">
|
||||
<rect x="1" y="1" width="254" height="382" rx="16" ry="16"
|
||||
fill="#1a1a1a" stroke="#d0d0d0" stroke-width="2"/>
|
||||
fill="#1a1a1a" stroke="#acc267" stroke-width="2"/>
|
||||
|
||||
<!-- Top-left rank in JetBrains-Mono-styled FiraMono (rank digits
|
||||
and letters render correctly in FiraMono; only the suit glyphs
|
||||
needed to escape to paths). -->
|
||||
<text x="14" y="44" font-family="Fira Mono" font-size="36" font-weight="700"
|
||||
fill="#d0d0d0">5</text>
|
||||
fill="#acc267">5</text>
|
||||
|
||||
<!-- Top-left small suit glyph at (14, 50), 20 × 20.
|
||||
`suit_path_d` is authored in a 32-unit box, so scale 0.625
|
||||
lands the visible glyph at 20 px. -->
|
||||
<g transform="translate(14 50) scale(0.625)">
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#d0d0d0" stroke-width="3"/>
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#acc267" stroke-width="3"/>
|
||||
</g>
|
||||
|
||||
<!-- Bottom-right large suit glyph at (178, 286), 64 × 64.
|
||||
@@ -20,6 +20,6 @@
|
||||
(178, 286). Same upright orientation as the top-left small
|
||||
glyph — no 180° rotation applied. -->
|
||||
<g transform="translate(178 286) scale(2)">
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#d0d0d0" stroke-width="3"/>
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#acc267" stroke-width="3"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
@@ -1,18 +1,18 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="384" viewBox="0 0 256 384">
|
||||
<rect x="1" y="1" width="254" height="382" rx="16" ry="16"
|
||||
fill="#1a1a1a" stroke="#d0d0d0" stroke-width="2"/>
|
||||
fill="#1a1a1a" stroke="#acc267" stroke-width="2"/>
|
||||
|
||||
<!-- Top-left rank in JetBrains-Mono-styled FiraMono (rank digits
|
||||
and letters render correctly in FiraMono; only the suit glyphs
|
||||
needed to escape to paths). -->
|
||||
<text x="14" y="44" font-family="Fira Mono" font-size="36" font-weight="700"
|
||||
fill="#d0d0d0">6</text>
|
||||
fill="#acc267">6</text>
|
||||
|
||||
<!-- Top-left small suit glyph at (14, 50), 20 × 20.
|
||||
`suit_path_d` is authored in a 32-unit box, so scale 0.625
|
||||
lands the visible glyph at 20 px. -->
|
||||
<g transform="translate(14 50) scale(0.625)">
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#d0d0d0" stroke-width="3"/>
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#acc267" stroke-width="3"/>
|
||||
</g>
|
||||
|
||||
<!-- Bottom-right large suit glyph at (178, 286), 64 × 64.
|
||||
@@ -20,6 +20,6 @@
|
||||
(178, 286). Same upright orientation as the top-left small
|
||||
glyph — no 180° rotation applied. -->
|
||||
<g transform="translate(178 286) scale(2)">
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#d0d0d0" stroke-width="3"/>
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#acc267" stroke-width="3"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
@@ -1,18 +1,18 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="384" viewBox="0 0 256 384">
|
||||
<rect x="1" y="1" width="254" height="382" rx="16" ry="16"
|
||||
fill="#1a1a1a" stroke="#d0d0d0" stroke-width="2"/>
|
||||
fill="#1a1a1a" stroke="#acc267" stroke-width="2"/>
|
||||
|
||||
<!-- Top-left rank in JetBrains-Mono-styled FiraMono (rank digits
|
||||
and letters render correctly in FiraMono; only the suit glyphs
|
||||
needed to escape to paths). -->
|
||||
<text x="14" y="44" font-family="Fira Mono" font-size="36" font-weight="700"
|
||||
fill="#d0d0d0">7</text>
|
||||
fill="#acc267">7</text>
|
||||
|
||||
<!-- Top-left small suit glyph at (14, 50), 20 × 20.
|
||||
`suit_path_d` is authored in a 32-unit box, so scale 0.625
|
||||
lands the visible glyph at 20 px. -->
|
||||
<g transform="translate(14 50) scale(0.625)">
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#d0d0d0" stroke-width="3"/>
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#acc267" stroke-width="3"/>
|
||||
</g>
|
||||
|
||||
<!-- Bottom-right large suit glyph at (178, 286), 64 × 64.
|
||||
@@ -20,6 +20,6 @@
|
||||
(178, 286). Same upright orientation as the top-left small
|
||||
glyph — no 180° rotation applied. -->
|
||||
<g transform="translate(178 286) scale(2)">
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#d0d0d0" stroke-width="3"/>
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#acc267" stroke-width="3"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
@@ -1,18 +1,18 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="384" viewBox="0 0 256 384">
|
||||
<rect x="1" y="1" width="254" height="382" rx="16" ry="16"
|
||||
fill="#1a1a1a" stroke="#d0d0d0" stroke-width="2"/>
|
||||
fill="#1a1a1a" stroke="#acc267" stroke-width="2"/>
|
||||
|
||||
<!-- Top-left rank in JetBrains-Mono-styled FiraMono (rank digits
|
||||
and letters render correctly in FiraMono; only the suit glyphs
|
||||
needed to escape to paths). -->
|
||||
<text x="14" y="44" font-family="Fira Mono" font-size="36" font-weight="700"
|
||||
fill="#d0d0d0">8</text>
|
||||
fill="#acc267">8</text>
|
||||
|
||||
<!-- Top-left small suit glyph at (14, 50), 20 × 20.
|
||||
`suit_path_d` is authored in a 32-unit box, so scale 0.625
|
||||
lands the visible glyph at 20 px. -->
|
||||
<g transform="translate(14 50) scale(0.625)">
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#d0d0d0" stroke-width="3"/>
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#acc267" stroke-width="3"/>
|
||||
</g>
|
||||
|
||||
<!-- Bottom-right large suit glyph at (178, 286), 64 × 64.
|
||||
@@ -20,6 +20,6 @@
|
||||
(178, 286). Same upright orientation as the top-left small
|
||||
glyph — no 180° rotation applied. -->
|
||||
<g transform="translate(178 286) scale(2)">
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#d0d0d0" stroke-width="3"/>
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#acc267" stroke-width="3"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
@@ -1,18 +1,18 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="384" viewBox="0 0 256 384">
|
||||
<rect x="1" y="1" width="254" height="382" rx="16" ry="16"
|
||||
fill="#1a1a1a" stroke="#d0d0d0" stroke-width="2"/>
|
||||
fill="#1a1a1a" stroke="#acc267" stroke-width="2"/>
|
||||
|
||||
<!-- Top-left rank in JetBrains-Mono-styled FiraMono (rank digits
|
||||
and letters render correctly in FiraMono; only the suit glyphs
|
||||
needed to escape to paths). -->
|
||||
<text x="14" y="44" font-family="Fira Mono" font-size="36" font-weight="700"
|
||||
fill="#d0d0d0">9</text>
|
||||
fill="#acc267">9</text>
|
||||
|
||||
<!-- Top-left small suit glyph at (14, 50), 20 × 20.
|
||||
`suit_path_d` is authored in a 32-unit box, so scale 0.625
|
||||
lands the visible glyph at 20 px. -->
|
||||
<g transform="translate(14 50) scale(0.625)">
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#d0d0d0" stroke-width="3"/>
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#acc267" stroke-width="3"/>
|
||||
</g>
|
||||
|
||||
<!-- Bottom-right large suit glyph at (178, 286), 64 × 64.
|
||||
@@ -20,6 +20,6 @@
|
||||
(178, 286). Same upright orientation as the top-left small
|
||||
glyph — no 180° rotation applied. -->
|
||||
<g transform="translate(178 286) scale(2)">
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#d0d0d0" stroke-width="3"/>
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#acc267" stroke-width="3"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
@@ -1,18 +1,18 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="384" viewBox="0 0 256 384">
|
||||
<rect x="1" y="1" width="254" height="382" rx="16" ry="16"
|
||||
fill="#1a1a1a" stroke="#d0d0d0" stroke-width="2"/>
|
||||
fill="#1a1a1a" stroke="#acc267" stroke-width="2"/>
|
||||
|
||||
<!-- Top-left rank in JetBrains-Mono-styled FiraMono (rank digits
|
||||
and letters render correctly in FiraMono; only the suit glyphs
|
||||
needed to escape to paths). -->
|
||||
<text x="14" y="44" font-family="Fira Mono" font-size="36" font-weight="700"
|
||||
fill="#d0d0d0">A</text>
|
||||
fill="#acc267">A</text>
|
||||
|
||||
<!-- Top-left small suit glyph at (14, 50), 20 × 20.
|
||||
`suit_path_d` is authored in a 32-unit box, so scale 0.625
|
||||
lands the visible glyph at 20 px. -->
|
||||
<g transform="translate(14 50) scale(0.625)">
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#d0d0d0" stroke-width="3"/>
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#acc267" stroke-width="3"/>
|
||||
</g>
|
||||
|
||||
<!-- Bottom-right large suit glyph at (178, 286), 64 × 64.
|
||||
@@ -20,6 +20,6 @@
|
||||
(178, 286). Same upright orientation as the top-left small
|
||||
glyph — no 180° rotation applied. -->
|
||||
<g transform="translate(178 286) scale(2)">
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#d0d0d0" stroke-width="3"/>
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#acc267" stroke-width="3"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
@@ -1,18 +1,18 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="384" viewBox="0 0 256 384">
|
||||
<rect x="1" y="1" width="254" height="382" rx="16" ry="16"
|
||||
fill="#1a1a1a" stroke="#d0d0d0" stroke-width="2"/>
|
||||
fill="#1a1a1a" stroke="#acc267" stroke-width="2"/>
|
||||
|
||||
<!-- Top-left rank in JetBrains-Mono-styled FiraMono (rank digits
|
||||
and letters render correctly in FiraMono; only the suit glyphs
|
||||
needed to escape to paths). -->
|
||||
<text x="14" y="44" font-family="Fira Mono" font-size="36" font-weight="700"
|
||||
fill="#d0d0d0">J</text>
|
||||
fill="#acc267">J</text>
|
||||
|
||||
<!-- Top-left small suit glyph at (14, 50), 20 × 20.
|
||||
`suit_path_d` is authored in a 32-unit box, so scale 0.625
|
||||
lands the visible glyph at 20 px. -->
|
||||
<g transform="translate(14 50) scale(0.625)">
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#d0d0d0" stroke-width="3"/>
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#acc267" stroke-width="3"/>
|
||||
</g>
|
||||
|
||||
<!-- Bottom-right large suit glyph at (178, 286), 64 × 64.
|
||||
@@ -20,6 +20,6 @@
|
||||
(178, 286). Same upright orientation as the top-left small
|
||||
glyph — no 180° rotation applied. -->
|
||||
<g transform="translate(178 286) scale(2)">
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#d0d0d0" stroke-width="3"/>
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#acc267" stroke-width="3"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
@@ -1,18 +1,18 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="384" viewBox="0 0 256 384">
|
||||
<rect x="1" y="1" width="254" height="382" rx="16" ry="16"
|
||||
fill="#1a1a1a" stroke="#d0d0d0" stroke-width="2"/>
|
||||
fill="#1a1a1a" stroke="#acc267" stroke-width="2"/>
|
||||
|
||||
<!-- Top-left rank in JetBrains-Mono-styled FiraMono (rank digits
|
||||
and letters render correctly in FiraMono; only the suit glyphs
|
||||
needed to escape to paths). -->
|
||||
<text x="14" y="44" font-family="Fira Mono" font-size="36" font-weight="700"
|
||||
fill="#d0d0d0">K</text>
|
||||
fill="#acc267">K</text>
|
||||
|
||||
<!-- Top-left small suit glyph at (14, 50), 20 × 20.
|
||||
`suit_path_d` is authored in a 32-unit box, so scale 0.625
|
||||
lands the visible glyph at 20 px. -->
|
||||
<g transform="translate(14 50) scale(0.625)">
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#d0d0d0" stroke-width="3"/>
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#acc267" stroke-width="3"/>
|
||||
</g>
|
||||
|
||||
<!-- Bottom-right large suit glyph at (178, 286), 64 × 64.
|
||||
@@ -20,6 +20,6 @@
|
||||
(178, 286). Same upright orientation as the top-left small
|
||||
glyph — no 180° rotation applied. -->
|
||||
<g transform="translate(178 286) scale(2)">
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#d0d0d0" stroke-width="3"/>
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#acc267" stroke-width="3"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
@@ -1,18 +1,18 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="384" viewBox="0 0 256 384">
|
||||
<rect x="1" y="1" width="254" height="382" rx="16" ry="16"
|
||||
fill="#1a1a1a" stroke="#d0d0d0" stroke-width="2"/>
|
||||
fill="#1a1a1a" stroke="#acc267" stroke-width="2"/>
|
||||
|
||||
<!-- Top-left rank in JetBrains-Mono-styled FiraMono (rank digits
|
||||
and letters render correctly in FiraMono; only the suit glyphs
|
||||
needed to escape to paths). -->
|
||||
<text x="14" y="44" font-family="Fira Mono" font-size="36" font-weight="700"
|
||||
fill="#d0d0d0">Q</text>
|
||||
fill="#acc267">Q</text>
|
||||
|
||||
<!-- Top-left small suit glyph at (14, 50), 20 × 20.
|
||||
`suit_path_d` is authored in a 32-unit box, so scale 0.625
|
||||
lands the visible glyph at 20 px. -->
|
||||
<g transform="translate(14 50) scale(0.625)">
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#d0d0d0" stroke-width="3"/>
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#acc267" stroke-width="3"/>
|
||||
</g>
|
||||
|
||||
<!-- Bottom-right large suit glyph at (178, 286), 64 × 64.
|
||||
@@ -20,6 +20,6 @@
|
||||
(178, 286). Same upright orientation as the top-left small
|
||||
glyph — no 180° rotation applied. -->
|
||||
<g transform="translate(178 286) scale(2)">
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#d0d0d0" stroke-width="3"/>
|
||||
<path d="M16,4 C 13,4 10,7 10,10 C 10,12 11,13 12,14 C 9,14 4,17 4,21 C 4,24 7,27 10,27 C 12,27 14,26 14,24 L 13,30 L 19,30 L 18,24 C 18,26 20,27 22,27 C 25,27 28,24 28,21 C 28,17 23,14 20,14 C 21,13 22,12 22,10 C 22,7 19,4 16,4 Z" fill="none" stroke="#acc267" stroke-width="3"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
@@ -1,18 +1,18 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="384" viewBox="0 0 256 384">
|
||||
<rect x="1" y="1" width="254" height="382" rx="16" ry="16"
|
||||
fill="#1a1a1a" stroke="#fb9fb1" stroke-width="2"/>
|
||||
fill="#1a1a1a" stroke="#ddb26f" stroke-width="2"/>
|
||||
|
||||
<!-- Top-left rank in JetBrains-Mono-styled FiraMono (rank digits
|
||||
and letters render correctly in FiraMono; only the suit glyphs
|
||||
needed to escape to paths). -->
|
||||
<text x="14" y="44" font-family="Fira Mono" font-size="36" font-weight="700"
|
||||
fill="#fb9fb1">10</text>
|
||||
fill="#ddb26f">10</text>
|
||||
|
||||
<!-- Top-left small suit glyph at (14, 50), 20 × 20.
|
||||
`suit_path_d` is authored in a 32-unit box, so scale 0.625
|
||||
lands the visible glyph at 20 px. -->
|
||||
<g transform="translate(14 50) scale(0.625)">
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#fb9fb1" stroke-width="3"/>
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#ddb26f" stroke-width="3"/>
|
||||
</g>
|
||||
|
||||
<!-- Bottom-right large suit glyph at (178, 286), 64 × 64.
|
||||
@@ -20,6 +20,6 @@
|
||||
(178, 286). Same upright orientation as the top-left small
|
||||
glyph — no 180° rotation applied. -->
|
||||
<g transform="translate(178 286) scale(2)">
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#fb9fb1" stroke-width="3"/>
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#ddb26f" stroke-width="3"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
@@ -1,18 +1,18 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="384" viewBox="0 0 256 384">
|
||||
<rect x="1" y="1" width="254" height="382" rx="16" ry="16"
|
||||
fill="#1a1a1a" stroke="#fb9fb1" stroke-width="2"/>
|
||||
fill="#1a1a1a" stroke="#ddb26f" stroke-width="2"/>
|
||||
|
||||
<!-- Top-left rank in JetBrains-Mono-styled FiraMono (rank digits
|
||||
and letters render correctly in FiraMono; only the suit glyphs
|
||||
needed to escape to paths). -->
|
||||
<text x="14" y="44" font-family="Fira Mono" font-size="36" font-weight="700"
|
||||
fill="#fb9fb1">2</text>
|
||||
fill="#ddb26f">2</text>
|
||||
|
||||
<!-- Top-left small suit glyph at (14, 50), 20 × 20.
|
||||
`suit_path_d` is authored in a 32-unit box, so scale 0.625
|
||||
lands the visible glyph at 20 px. -->
|
||||
<g transform="translate(14 50) scale(0.625)">
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#fb9fb1" stroke-width="3"/>
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#ddb26f" stroke-width="3"/>
|
||||
</g>
|
||||
|
||||
<!-- Bottom-right large suit glyph at (178, 286), 64 × 64.
|
||||
@@ -20,6 +20,6 @@
|
||||
(178, 286). Same upright orientation as the top-left small
|
||||
glyph — no 180° rotation applied. -->
|
||||
<g transform="translate(178 286) scale(2)">
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#fb9fb1" stroke-width="3"/>
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#ddb26f" stroke-width="3"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
@@ -1,18 +1,18 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="384" viewBox="0 0 256 384">
|
||||
<rect x="1" y="1" width="254" height="382" rx="16" ry="16"
|
||||
fill="#1a1a1a" stroke="#fb9fb1" stroke-width="2"/>
|
||||
fill="#1a1a1a" stroke="#ddb26f" stroke-width="2"/>
|
||||
|
||||
<!-- Top-left rank in JetBrains-Mono-styled FiraMono (rank digits
|
||||
and letters render correctly in FiraMono; only the suit glyphs
|
||||
needed to escape to paths). -->
|
||||
<text x="14" y="44" font-family="Fira Mono" font-size="36" font-weight="700"
|
||||
fill="#fb9fb1">3</text>
|
||||
fill="#ddb26f">3</text>
|
||||
|
||||
<!-- Top-left small suit glyph at (14, 50), 20 × 20.
|
||||
`suit_path_d` is authored in a 32-unit box, so scale 0.625
|
||||
lands the visible glyph at 20 px. -->
|
||||
<g transform="translate(14 50) scale(0.625)">
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#fb9fb1" stroke-width="3"/>
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#ddb26f" stroke-width="3"/>
|
||||
</g>
|
||||
|
||||
<!-- Bottom-right large suit glyph at (178, 286), 64 × 64.
|
||||
@@ -20,6 +20,6 @@
|
||||
(178, 286). Same upright orientation as the top-left small
|
||||
glyph — no 180° rotation applied. -->
|
||||
<g transform="translate(178 286) scale(2)">
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#fb9fb1" stroke-width="3"/>
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#ddb26f" stroke-width="3"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
@@ -1,18 +1,18 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="384" viewBox="0 0 256 384">
|
||||
<rect x="1" y="1" width="254" height="382" rx="16" ry="16"
|
||||
fill="#1a1a1a" stroke="#fb9fb1" stroke-width="2"/>
|
||||
fill="#1a1a1a" stroke="#ddb26f" stroke-width="2"/>
|
||||
|
||||
<!-- Top-left rank in JetBrains-Mono-styled FiraMono (rank digits
|
||||
and letters render correctly in FiraMono; only the suit glyphs
|
||||
needed to escape to paths). -->
|
||||
<text x="14" y="44" font-family="Fira Mono" font-size="36" font-weight="700"
|
||||
fill="#fb9fb1">4</text>
|
||||
fill="#ddb26f">4</text>
|
||||
|
||||
<!-- Top-left small suit glyph at (14, 50), 20 × 20.
|
||||
`suit_path_d` is authored in a 32-unit box, so scale 0.625
|
||||
lands the visible glyph at 20 px. -->
|
||||
<g transform="translate(14 50) scale(0.625)">
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#fb9fb1" stroke-width="3"/>
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#ddb26f" stroke-width="3"/>
|
||||
</g>
|
||||
|
||||
<!-- Bottom-right large suit glyph at (178, 286), 64 × 64.
|
||||
@@ -20,6 +20,6 @@
|
||||
(178, 286). Same upright orientation as the top-left small
|
||||
glyph — no 180° rotation applied. -->
|
||||
<g transform="translate(178 286) scale(2)">
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#fb9fb1" stroke-width="3"/>
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#ddb26f" stroke-width="3"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
@@ -1,18 +1,18 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="384" viewBox="0 0 256 384">
|
||||
<rect x="1" y="1" width="254" height="382" rx="16" ry="16"
|
||||
fill="#1a1a1a" stroke="#fb9fb1" stroke-width="2"/>
|
||||
fill="#1a1a1a" stroke="#ddb26f" stroke-width="2"/>
|
||||
|
||||
<!-- Top-left rank in JetBrains-Mono-styled FiraMono (rank digits
|
||||
and letters render correctly in FiraMono; only the suit glyphs
|
||||
needed to escape to paths). -->
|
||||
<text x="14" y="44" font-family="Fira Mono" font-size="36" font-weight="700"
|
||||
fill="#fb9fb1">5</text>
|
||||
fill="#ddb26f">5</text>
|
||||
|
||||
<!-- Top-left small suit glyph at (14, 50), 20 × 20.
|
||||
`suit_path_d` is authored in a 32-unit box, so scale 0.625
|
||||
lands the visible glyph at 20 px. -->
|
||||
<g transform="translate(14 50) scale(0.625)">
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#fb9fb1" stroke-width="3"/>
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#ddb26f" stroke-width="3"/>
|
||||
</g>
|
||||
|
||||
<!-- Bottom-right large suit glyph at (178, 286), 64 × 64.
|
||||
@@ -20,6 +20,6 @@
|
||||
(178, 286). Same upright orientation as the top-left small
|
||||
glyph — no 180° rotation applied. -->
|
||||
<g transform="translate(178 286) scale(2)">
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#fb9fb1" stroke-width="3"/>
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#ddb26f" stroke-width="3"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
@@ -1,18 +1,18 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="384" viewBox="0 0 256 384">
|
||||
<rect x="1" y="1" width="254" height="382" rx="16" ry="16"
|
||||
fill="#1a1a1a" stroke="#fb9fb1" stroke-width="2"/>
|
||||
fill="#1a1a1a" stroke="#ddb26f" stroke-width="2"/>
|
||||
|
||||
<!-- Top-left rank in JetBrains-Mono-styled FiraMono (rank digits
|
||||
and letters render correctly in FiraMono; only the suit glyphs
|
||||
needed to escape to paths). -->
|
||||
<text x="14" y="44" font-family="Fira Mono" font-size="36" font-weight="700"
|
||||
fill="#fb9fb1">6</text>
|
||||
fill="#ddb26f">6</text>
|
||||
|
||||
<!-- Top-left small suit glyph at (14, 50), 20 × 20.
|
||||
`suit_path_d` is authored in a 32-unit box, so scale 0.625
|
||||
lands the visible glyph at 20 px. -->
|
||||
<g transform="translate(14 50) scale(0.625)">
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#fb9fb1" stroke-width="3"/>
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#ddb26f" stroke-width="3"/>
|
||||
</g>
|
||||
|
||||
<!-- Bottom-right large suit glyph at (178, 286), 64 × 64.
|
||||
@@ -20,6 +20,6 @@
|
||||
(178, 286). Same upright orientation as the top-left small
|
||||
glyph — no 180° rotation applied. -->
|
||||
<g transform="translate(178 286) scale(2)">
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#fb9fb1" stroke-width="3"/>
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#ddb26f" stroke-width="3"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
@@ -1,18 +1,18 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="384" viewBox="0 0 256 384">
|
||||
<rect x="1" y="1" width="254" height="382" rx="16" ry="16"
|
||||
fill="#1a1a1a" stroke="#fb9fb1" stroke-width="2"/>
|
||||
fill="#1a1a1a" stroke="#ddb26f" stroke-width="2"/>
|
||||
|
||||
<!-- Top-left rank in JetBrains-Mono-styled FiraMono (rank digits
|
||||
and letters render correctly in FiraMono; only the suit glyphs
|
||||
needed to escape to paths). -->
|
||||
<text x="14" y="44" font-family="Fira Mono" font-size="36" font-weight="700"
|
||||
fill="#fb9fb1">7</text>
|
||||
fill="#ddb26f">7</text>
|
||||
|
||||
<!-- Top-left small suit glyph at (14, 50), 20 × 20.
|
||||
`suit_path_d` is authored in a 32-unit box, so scale 0.625
|
||||
lands the visible glyph at 20 px. -->
|
||||
<g transform="translate(14 50) scale(0.625)">
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#fb9fb1" stroke-width="3"/>
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#ddb26f" stroke-width="3"/>
|
||||
</g>
|
||||
|
||||
<!-- Bottom-right large suit glyph at (178, 286), 64 × 64.
|
||||
@@ -20,6 +20,6 @@
|
||||
(178, 286). Same upright orientation as the top-left small
|
||||
glyph — no 180° rotation applied. -->
|
||||
<g transform="translate(178 286) scale(2)">
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#fb9fb1" stroke-width="3"/>
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#ddb26f" stroke-width="3"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
@@ -1,18 +1,18 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="384" viewBox="0 0 256 384">
|
||||
<rect x="1" y="1" width="254" height="382" rx="16" ry="16"
|
||||
fill="#1a1a1a" stroke="#fb9fb1" stroke-width="2"/>
|
||||
fill="#1a1a1a" stroke="#ddb26f" stroke-width="2"/>
|
||||
|
||||
<!-- Top-left rank in JetBrains-Mono-styled FiraMono (rank digits
|
||||
and letters render correctly in FiraMono; only the suit glyphs
|
||||
needed to escape to paths). -->
|
||||
<text x="14" y="44" font-family="Fira Mono" font-size="36" font-weight="700"
|
||||
fill="#fb9fb1">8</text>
|
||||
fill="#ddb26f">8</text>
|
||||
|
||||
<!-- Top-left small suit glyph at (14, 50), 20 × 20.
|
||||
`suit_path_d` is authored in a 32-unit box, so scale 0.625
|
||||
lands the visible glyph at 20 px. -->
|
||||
<g transform="translate(14 50) scale(0.625)">
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#fb9fb1" stroke-width="3"/>
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#ddb26f" stroke-width="3"/>
|
||||
</g>
|
||||
|
||||
<!-- Bottom-right large suit glyph at (178, 286), 64 × 64.
|
||||
@@ -20,6 +20,6 @@
|
||||
(178, 286). Same upright orientation as the top-left small
|
||||
glyph — no 180° rotation applied. -->
|
||||
<g transform="translate(178 286) scale(2)">
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#fb9fb1" stroke-width="3"/>
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#ddb26f" stroke-width="3"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
@@ -1,18 +1,18 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="384" viewBox="0 0 256 384">
|
||||
<rect x="1" y="1" width="254" height="382" rx="16" ry="16"
|
||||
fill="#1a1a1a" stroke="#fb9fb1" stroke-width="2"/>
|
||||
fill="#1a1a1a" stroke="#ddb26f" stroke-width="2"/>
|
||||
|
||||
<!-- Top-left rank in JetBrains-Mono-styled FiraMono (rank digits
|
||||
and letters render correctly in FiraMono; only the suit glyphs
|
||||
needed to escape to paths). -->
|
||||
<text x="14" y="44" font-family="Fira Mono" font-size="36" font-weight="700"
|
||||
fill="#fb9fb1">9</text>
|
||||
fill="#ddb26f">9</text>
|
||||
|
||||
<!-- Top-left small suit glyph at (14, 50), 20 × 20.
|
||||
`suit_path_d` is authored in a 32-unit box, so scale 0.625
|
||||
lands the visible glyph at 20 px. -->
|
||||
<g transform="translate(14 50) scale(0.625)">
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#fb9fb1" stroke-width="3"/>
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#ddb26f" stroke-width="3"/>
|
||||
</g>
|
||||
|
||||
<!-- Bottom-right large suit glyph at (178, 286), 64 × 64.
|
||||
@@ -20,6 +20,6 @@
|
||||
(178, 286). Same upright orientation as the top-left small
|
||||
glyph — no 180° rotation applied. -->
|
||||
<g transform="translate(178 286) scale(2)">
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#fb9fb1" stroke-width="3"/>
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#ddb26f" stroke-width="3"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
@@ -1,18 +1,18 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="384" viewBox="0 0 256 384">
|
||||
<rect x="1" y="1" width="254" height="382" rx="16" ry="16"
|
||||
fill="#1a1a1a" stroke="#fb9fb1" stroke-width="2"/>
|
||||
fill="#1a1a1a" stroke="#ddb26f" stroke-width="2"/>
|
||||
|
||||
<!-- Top-left rank in JetBrains-Mono-styled FiraMono (rank digits
|
||||
and letters render correctly in FiraMono; only the suit glyphs
|
||||
needed to escape to paths). -->
|
||||
<text x="14" y="44" font-family="Fira Mono" font-size="36" font-weight="700"
|
||||
fill="#fb9fb1">A</text>
|
||||
fill="#ddb26f">A</text>
|
||||
|
||||
<!-- Top-left small suit glyph at (14, 50), 20 × 20.
|
||||
`suit_path_d` is authored in a 32-unit box, so scale 0.625
|
||||
lands the visible glyph at 20 px. -->
|
||||
<g transform="translate(14 50) scale(0.625)">
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#fb9fb1" stroke-width="3"/>
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#ddb26f" stroke-width="3"/>
|
||||
</g>
|
||||
|
||||
<!-- Bottom-right large suit glyph at (178, 286), 64 × 64.
|
||||
@@ -20,6 +20,6 @@
|
||||
(178, 286). Same upright orientation as the top-left small
|
||||
glyph — no 180° rotation applied. -->
|
||||
<g transform="translate(178 286) scale(2)">
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#fb9fb1" stroke-width="3"/>
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#ddb26f" stroke-width="3"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
@@ -1,18 +1,18 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="384" viewBox="0 0 256 384">
|
||||
<rect x="1" y="1" width="254" height="382" rx="16" ry="16"
|
||||
fill="#1a1a1a" stroke="#fb9fb1" stroke-width="2"/>
|
||||
fill="#1a1a1a" stroke="#ddb26f" stroke-width="2"/>
|
||||
|
||||
<!-- Top-left rank in JetBrains-Mono-styled FiraMono (rank digits
|
||||
and letters render correctly in FiraMono; only the suit glyphs
|
||||
needed to escape to paths). -->
|
||||
<text x="14" y="44" font-family="Fira Mono" font-size="36" font-weight="700"
|
||||
fill="#fb9fb1">J</text>
|
||||
fill="#ddb26f">J</text>
|
||||
|
||||
<!-- Top-left small suit glyph at (14, 50), 20 × 20.
|
||||
`suit_path_d` is authored in a 32-unit box, so scale 0.625
|
||||
lands the visible glyph at 20 px. -->
|
||||
<g transform="translate(14 50) scale(0.625)">
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#fb9fb1" stroke-width="3"/>
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#ddb26f" stroke-width="3"/>
|
||||
</g>
|
||||
|
||||
<!-- Bottom-right large suit glyph at (178, 286), 64 × 64.
|
||||
@@ -20,6 +20,6 @@
|
||||
(178, 286). Same upright orientation as the top-left small
|
||||
glyph — no 180° rotation applied. -->
|
||||
<g transform="translate(178 286) scale(2)">
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#fb9fb1" stroke-width="3"/>
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#ddb26f" stroke-width="3"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
@@ -1,18 +1,18 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="384" viewBox="0 0 256 384">
|
||||
<rect x="1" y="1" width="254" height="382" rx="16" ry="16"
|
||||
fill="#1a1a1a" stroke="#fb9fb1" stroke-width="2"/>
|
||||
fill="#1a1a1a" stroke="#ddb26f" stroke-width="2"/>
|
||||
|
||||
<!-- Top-left rank in JetBrains-Mono-styled FiraMono (rank digits
|
||||
and letters render correctly in FiraMono; only the suit glyphs
|
||||
needed to escape to paths). -->
|
||||
<text x="14" y="44" font-family="Fira Mono" font-size="36" font-weight="700"
|
||||
fill="#fb9fb1">K</text>
|
||||
fill="#ddb26f">K</text>
|
||||
|
||||
<!-- Top-left small suit glyph at (14, 50), 20 × 20.
|
||||
`suit_path_d` is authored in a 32-unit box, so scale 0.625
|
||||
lands the visible glyph at 20 px. -->
|
||||
<g transform="translate(14 50) scale(0.625)">
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#fb9fb1" stroke-width="3"/>
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#ddb26f" stroke-width="3"/>
|
||||
</g>
|
||||
|
||||
<!-- Bottom-right large suit glyph at (178, 286), 64 × 64.
|
||||
@@ -20,6 +20,6 @@
|
||||
(178, 286). Same upright orientation as the top-left small
|
||||
glyph — no 180° rotation applied. -->
|
||||
<g transform="translate(178 286) scale(2)">
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#fb9fb1" stroke-width="3"/>
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#ddb26f" stroke-width="3"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
@@ -1,18 +1,18 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="384" viewBox="0 0 256 384">
|
||||
<rect x="1" y="1" width="254" height="382" rx="16" ry="16"
|
||||
fill="#1a1a1a" stroke="#fb9fb1" stroke-width="2"/>
|
||||
fill="#1a1a1a" stroke="#ddb26f" stroke-width="2"/>
|
||||
|
||||
<!-- Top-left rank in JetBrains-Mono-styled FiraMono (rank digits
|
||||
and letters render correctly in FiraMono; only the suit glyphs
|
||||
needed to escape to paths). -->
|
||||
<text x="14" y="44" font-family="Fira Mono" font-size="36" font-weight="700"
|
||||
fill="#fb9fb1">Q</text>
|
||||
fill="#ddb26f">Q</text>
|
||||
|
||||
<!-- Top-left small suit glyph at (14, 50), 20 × 20.
|
||||
`suit_path_d` is authored in a 32-unit box, so scale 0.625
|
||||
lands the visible glyph at 20 px. -->
|
||||
<g transform="translate(14 50) scale(0.625)">
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#fb9fb1" stroke-width="3"/>
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#ddb26f" stroke-width="3"/>
|
||||
</g>
|
||||
|
||||
<!-- Bottom-right large suit glyph at (178, 286), 64 × 64.
|
||||
@@ -20,6 +20,6 @@
|
||||
(178, 286). Same upright orientation as the top-left small
|
||||
glyph — no 180° rotation applied. -->
|
||||
<g transform="translate(178 286) scale(2)">
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#fb9fb1" stroke-width="3"/>
|
||||
<path d="M16,2 L 29,16 L 16,30 L 3,16 Z" fill="none" stroke="#ddb26f" stroke-width="3"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
@@ -29,8 +29,19 @@ use solitaire_core::card::{Rank, Suit};
|
||||
pub const TARGET: UVec2 = UVec2::new(256, 384);
|
||||
|
||||
const BG_FACE: &str = "#1a1a1a"; // BG_ELEVATED — face background
|
||||
const SUIT_RED: &str = "#fb9fb1"; // hearts + diamonds
|
||||
const SUIT_DARK: &str = "#d0d0d0"; // spades + clubs (also TEXT_PRIMARY)
|
||||
|
||||
// Four-colour deck: each suit picks up its own base16-eighties
|
||||
// accent so a player scanning the table can distinguish the suit
|
||||
// by hue alone. Faster recognition than the 2-colour traditional
|
||||
// red/black scheme; common in poker-room decks and online card
|
||||
// games. The outlined-glyph differentiation (♦ ♣ outlined, ♥ ♠
|
||||
// filled) is preserved on top of the colour split as the
|
||||
// always-on colour-blind fallback per `design-system.md`
|
||||
// §Accessibility.
|
||||
const SUIT_HEART: &str = "#fb9fb1"; // pink (base08 / RED_SUIT_COLOUR)
|
||||
const SUIT_DIAMOND: &str = "#ddb26f"; // gold (base09 / STATE_WARNING)
|
||||
const SUIT_CLUB: &str = "#acc267"; // lime (base0A / STATE_SUCCESS)
|
||||
const SUIT_SPADE: &str = "#d0d0d0"; // foreground gray (base05 / TEXT_PRIMARY)
|
||||
|
||||
const BACK_BG: &str = "#151515";
|
||||
const BACK_SCANLINE: &str = "#1a1a1a";
|
||||
@@ -145,10 +156,10 @@ enum GlyphPaint {
|
||||
|
||||
fn suit_paint(suit: Suit) -> (&'static str, GlyphPaint) {
|
||||
match suit {
|
||||
Suit::Hearts => (SUIT_RED, GlyphPaint::Filled),
|
||||
Suit::Diamonds => (SUIT_RED, GlyphPaint::Outlined),
|
||||
Suit::Spades => (SUIT_DARK, GlyphPaint::Filled),
|
||||
Suit::Clubs => (SUIT_DARK, GlyphPaint::Outlined),
|
||||
Suit::Hearts => (SUIT_HEART, GlyphPaint::Filled),
|
||||
Suit::Diamonds => (SUIT_DIAMOND, GlyphPaint::Outlined),
|
||||
Suit::Spades => (SUIT_SPADE, GlyphPaint::Filled),
|
||||
Suit::Clubs => (SUIT_CLUB, GlyphPaint::Outlined),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,13 @@ const FONT_SIZE_FRAC: f32 = 0.28;
|
||||
|
||||
/// Card-face background — Terminal `#1a1a1a` (BG_ELEVATED).
|
||||
pub const CARD_FACE_COLOUR: Color = Color::srgb(0.102, 0.102, 0.102);
|
||||
/// Suit colour for hearts + diamonds — Terminal `#fb9fb1` (suit-pink).
|
||||
/// Suit colour for hearts — Terminal `#fb9fb1` (suit-pink). Per
|
||||
/// the 4-colour deck convention, hearts and diamonds no longer
|
||||
/// share a hue: hearts stay pink (the most strongly "red" of the
|
||||
/// four base16 accents), diamonds pick up gold so a player
|
||||
/// scanning the table can distinguish the suit by colour alone.
|
||||
/// Kept as `RED_SUIT_COLOUR` for back-compat; semantically this
|
||||
/// is now "the heart suit colour".
|
||||
pub const RED_SUIT_COLOUR: Color = Color::srgb(0.984, 0.624, 0.694);
|
||||
/// High-contrast variant of [`RED_SUIT_COLOUR`] — `#ff8aa0`. Lifted
|
||||
/// chroma + luminance for the Settings → Accessibility → High-
|
||||
@@ -76,7 +82,19 @@ pub const RED_SUIT_COLOUR: Color = Color::srgb(0.984, 0.624, 0.694);
|
||||
/// alternative. The two modes can stack; CBM wins when both are on
|
||||
/// because the CBM lime is itself a high-contrast colour.
|
||||
pub const RED_SUIT_COLOUR_HC: Color = Color::srgb(1.000, 0.541, 0.627);
|
||||
/// Suit colour for spades + clubs — Terminal `#d0d0d0` (TEXT_PRIMARY).
|
||||
/// Suit colour for diamonds — Terminal `#ddb26f` (gold, base09).
|
||||
/// In the 4-colour deck split, diamonds break away from sharing
|
||||
/// the "red" hue with hearts and pick up gold so the two former
|
||||
/// red suits are visually distinguishable.
|
||||
pub const DIAMOND_SUIT_COLOUR: Color = Color::srgb(0.867, 0.698, 0.435);
|
||||
/// Suit colour for clubs — Terminal `#acc267` (lime, base0A).
|
||||
/// In the 4-colour deck split, clubs break away from sharing the
|
||||
/// "black" hue with spades and pick up lime so the two former
|
||||
/// black suits are visually distinguishable.
|
||||
pub const CLUB_SUIT_COLOUR: Color = Color::srgb(0.675, 0.761, 0.404);
|
||||
/// Suit colour for spades — Terminal `#d0d0d0` (TEXT_PRIMARY).
|
||||
/// Kept as `BLACK_SUIT_COLOUR` for back-compat; semantically this
|
||||
/// is now "the spade suit colour" in the 4-colour deck split.
|
||||
pub const BLACK_SUIT_COLOUR: Color = Color::srgb(0.816, 0.816, 0.816);
|
||||
|
||||
/// Pre-loaded [`Handle<Image>`]s for card face and back PNG textures.
|
||||
@@ -813,39 +831,60 @@ fn label_for(card: &Card) -> String {
|
||||
|
||||
/// Suit colour for the rank/suit overlay rendered atop the constant
|
||||
/// fallback sprite (only fires under `MinimalPlugins` — production
|
||||
/// renders the suit glyph baked into the PNG). Two independent
|
||||
/// accessibility flags compose:
|
||||
/// renders the suit glyph baked into the PNG). The 4-colour deck
|
||||
/// split assigns each suit a distinct base16-eighties accent so
|
||||
/// players can identify the suit by hue alone:
|
||||
///
|
||||
/// - `color_blind`: red-suit cards swap to `RED_SUIT_COLOUR_CBM`
|
||||
/// (lime) — the "Settings toggle swaps red→lime" half of the
|
||||
/// design system's colour-blind support. CBM is a hue-replacement
|
||||
/// for red, so HC has no further effect on red when CBM is on
|
||||
/// (the lime is itself a high-contrast colour).
|
||||
/// - `high_contrast`: when CBM is off, red suits boost to
|
||||
/// `RED_SUIT_COLOUR_HC` (`#ff8aa0` from the spec); black suits
|
||||
/// boost from `#d0d0d0` to `#f5f5f5` (`TEXT_PRIMARY_HC`).
|
||||
/// | Suit | Default colour | CBM swap | HC boost |
|
||||
/// | -------- | ----------------------- | ------------- | ---------------- |
|
||||
/// | Hearts | `RED_SUIT_COLOUR` pink | lime | `RED_SUIT_COLOUR_HC` |
|
||||
/// | Diamonds | `DIAMOND_SUIT_COLOUR` gold | (no swap — already non-red-family) | (no boost — already mid-luminance) |
|
||||
/// | Clubs | `CLUB_SUIT_COLOUR` lime | (no swap) | (no boost) |
|
||||
/// | Spades | `BLACK_SUIT_COLOUR` gray | (no swap) | `TEXT_PRIMARY_HC` |
|
||||
///
|
||||
/// Two independent accessibility flags compose:
|
||||
///
|
||||
/// - `color_blind`: hearts swap from pink to `RED_SUIT_COLOUR_CBM`
|
||||
/// (lime). The other three suits are already hue-distinct from
|
||||
/// pink so they don't change. Note that CBM lime collides with
|
||||
/// the club suit colour — players running CBM on the 4-colour
|
||||
/// deck rely on the always-on filled-vs-outlined differentiation
|
||||
/// (♥ filled, ♣ outlined) to distinguish hearts and clubs.
|
||||
/// - `high_contrast`: hearts boost to `RED_SUIT_COLOUR_HC`
|
||||
/// (`#ff8aa0`); spades boost from `#d0d0d0` to `#f5f5f5`
|
||||
/// (`TEXT_PRIMARY_HC`). Diamonds (gold) and clubs (lime) are
|
||||
/// already mid-luminance accents so no HC boost is defined for
|
||||
/// them.
|
||||
///
|
||||
/// The other half of CBM support (always-on filled-vs-outlined
|
||||
/// glyph differentiation for ♥♠ vs ♦♣) is baked into the PNG art
|
||||
/// and has no constant-fallback equivalent.
|
||||
fn text_colour(card: &Card, color_blind: bool, high_contrast: bool) -> Color {
|
||||
if card.suit.is_red() {
|
||||
match card.suit {
|
||||
Suit::Hearts => {
|
||||
if color_blind {
|
||||
// CBM lime wins — the colour-blind swap replaces the
|
||||
// red hue entirely, and the lime is already high-
|
||||
// luminance, so an HC boost on top has nothing to do.
|
||||
// CBM lime replaces the pink for red-deficient
|
||||
// readers; the always-on filled-vs-outlined split
|
||||
// keeps hearts visually distinct from clubs (which
|
||||
// are also lime in the 4-colour scheme).
|
||||
RED_SUIT_COLOUR_CBM
|
||||
} else if high_contrast {
|
||||
RED_SUIT_COLOUR_HC
|
||||
} else {
|
||||
RED_SUIT_COLOUR
|
||||
}
|
||||
} else if high_contrast {
|
||||
}
|
||||
Suit::Diamonds => DIAMOND_SUIT_COLOUR,
|
||||
Suit::Clubs => CLUB_SUIT_COLOUR,
|
||||
Suit::Spades => {
|
||||
if high_contrast {
|
||||
TEXT_PRIMARY_HC
|
||||
} else {
|
||||
BLACK_SUIT_COLOUR
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn label_visibility(card: &Card) -> Visibility {
|
||||
if card.face_up {
|
||||
@@ -1784,39 +1823,41 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn text_colour_is_red_for_hearts_and_diamonds() {
|
||||
let h = Card {
|
||||
id: 0,
|
||||
suit: Suit::Hearts,
|
||||
rank: Rank::Ace,
|
||||
face_up: true,
|
||||
};
|
||||
let d = Card {
|
||||
id: 0,
|
||||
suit: Suit::Diamonds,
|
||||
rank: Rank::Ace,
|
||||
face_up: true,
|
||||
};
|
||||
assert_eq!(text_colour(&h, false, false), RED_SUIT_COLOUR);
|
||||
assert_eq!(text_colour(&d, false, false), RED_SUIT_COLOUR);
|
||||
}
|
||||
fn text_colour_4_colour_deck_assigns_each_suit_its_own_hue() {
|
||||
// Pre-4-colour-deck this was two tests asserting hearts +
|
||||
// diamonds shared `RED_SUIT_COLOUR` and clubs + spades
|
||||
// shared `BLACK_SUIT_COLOUR`. The 4-colour split breaks
|
||||
// both pairings: hearts pink, diamonds gold, clubs lime,
|
||||
// spades gray. All four colours must be distinct so a
|
||||
// player scanning the table can identify the suit by hue
|
||||
// alone.
|
||||
let h = Card { id: 0, suit: Suit::Hearts, rank: Rank::Ace, face_up: true };
|
||||
let d = Card { id: 0, suit: Suit::Diamonds, rank: Rank::Ace, face_up: true };
|
||||
let c = Card { id: 0, suit: Suit::Clubs, rank: Rank::Ace, face_up: true };
|
||||
let s = Card { id: 0, suit: Suit::Spades, rank: Rank::Ace, face_up: true };
|
||||
|
||||
#[test]
|
||||
fn text_colour_is_black_for_clubs_and_spades() {
|
||||
let c = Card {
|
||||
id: 0,
|
||||
suit: Suit::Clubs,
|
||||
rank: Rank::Ace,
|
||||
face_up: true,
|
||||
};
|
||||
let s = Card {
|
||||
id: 0,
|
||||
suit: Suit::Spades,
|
||||
rank: Rank::Ace,
|
||||
face_up: true,
|
||||
};
|
||||
assert_eq!(text_colour(&c, false, false), BLACK_SUIT_COLOUR);
|
||||
assert_eq!(text_colour(&h, false, false), RED_SUIT_COLOUR);
|
||||
assert_eq!(text_colour(&d, false, false), DIAMOND_SUIT_COLOUR);
|
||||
assert_eq!(text_colour(&c, false, false), CLUB_SUIT_COLOUR);
|
||||
assert_eq!(text_colour(&s, false, false), BLACK_SUIT_COLOUR);
|
||||
|
||||
// All four hues must be pairwise distinct — the visual
|
||||
// identification gain of a 4-colour deck depends on hue
|
||||
// separation, so this is the load-bearing invariant.
|
||||
let colours = [
|
||||
text_colour(&h, false, false),
|
||||
text_colour(&d, false, false),
|
||||
text_colour(&c, false, false),
|
||||
text_colour(&s, false, false),
|
||||
];
|
||||
for i in 0..colours.len() {
|
||||
for j in (i + 1)..colours.len() {
|
||||
assert_ne!(
|
||||
colours[i], colours[j],
|
||||
"4-colour deck requires every suit to have a distinct colour",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -2108,27 +2149,35 @@ mod tests {
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
#[test]
|
||||
fn text_colour_color_blind_mode_swaps_red_suits_to_lime() {
|
||||
let red_card = Card { id: 0, suit: Suit::Diamonds, rank: Rank::Queen, face_up: true };
|
||||
let cbm_colour = text_colour(&red_card, true, false);
|
||||
fn text_colour_color_blind_mode_swaps_hearts_to_lime() {
|
||||
// Pre-4-colour-deck this test asserted both red suits
|
||||
// (hearts + diamonds) swapped to lime under CBM. With
|
||||
// hearts the only "red-family" suit now, CBM only
|
||||
// affects hearts; diamonds is gold and stays gold.
|
||||
let hearts = Card { id: 0, suit: Suit::Hearts, rank: Rank::Queen, face_up: true };
|
||||
let cbm_colour = text_colour(&hearts, true, false);
|
||||
assert_eq!(
|
||||
cbm_colour, RED_SUIT_COLOUR_CBM,
|
||||
"color-blind mode must replace the red suit colour with the CBM lime",
|
||||
"color-blind mode must replace the heart suit colour with the CBM lime",
|
||||
);
|
||||
assert_ne!(
|
||||
cbm_colour, RED_SUIT_COLOUR,
|
||||
"CBM lime must be visibly distinct from the default red suit colour",
|
||||
"CBM lime must be visibly distinct from the default heart suit colour",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn text_colour_color_blind_mode_does_not_change_black_suits() {
|
||||
let black_card = Card { id: 0, suit: Suit::Clubs, rank: Rank::Jack, face_up: true };
|
||||
assert_eq!(
|
||||
text_colour(&black_card, true, false),
|
||||
BLACK_SUIT_COLOUR,
|
||||
"color-blind mode must not alter black-suit text colour",
|
||||
);
|
||||
fn text_colour_color_blind_mode_does_not_change_non_heart_suits() {
|
||||
// CBM only affects hearts in the 4-colour deck. Diamonds
|
||||
// (gold), clubs (lime), and spades (gray) are already
|
||||
// hue-distinct from the original heart pink and stay
|
||||
// unchanged.
|
||||
let d = Card { id: 0, suit: Suit::Diamonds, rank: Rank::Jack, face_up: true };
|
||||
let c = Card { id: 0, suit: Suit::Clubs, rank: Rank::Jack, face_up: true };
|
||||
let s = Card { id: 0, suit: Suit::Spades, rank: Rank::Jack, face_up: true };
|
||||
assert_eq!(text_colour(&d, true, false), DIAMOND_SUIT_COLOUR);
|
||||
assert_eq!(text_colour(&c, true, false), CLUB_SUIT_COLOUR);
|
||||
assert_eq!(text_colour(&s, true, false), BLACK_SUIT_COLOUR);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
@@ -2168,31 +2217,48 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn text_colour_color_blind_wins_over_high_contrast_on_red_suits() {
|
||||
// When both modes are enabled, red→lime (CBM) wins because
|
||||
// the CBM lime is itself a high-luminance accent and the HC
|
||||
// boost would pick a different hue, defeating the purpose of
|
||||
// the colour-blind swap.
|
||||
let red_card = Card { id: 0, suit: Suit::Diamonds, rank: Rank::Ace, face_up: true };
|
||||
fn text_colour_color_blind_wins_over_high_contrast_on_hearts() {
|
||||
// When both modes are enabled on hearts, CBM lime wins over
|
||||
// HC red because the CBM lime is itself a high-luminance
|
||||
// accent and the HC boost would pick a different hue,
|
||||
// defeating the purpose of the colour-blind swap.
|
||||
let hearts = Card { id: 0, suit: Suit::Hearts, rank: Rank::Ace, face_up: true };
|
||||
assert_eq!(
|
||||
text_colour(&red_card, true, true),
|
||||
text_colour(&hearts, true, true),
|
||||
RED_SUIT_COLOUR_CBM,
|
||||
"CBM lime must win over HC red when both modes are on",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn text_colour_high_contrast_alone_does_not_change_black_suits_under_cbm() {
|
||||
// CBM doesn't touch black suits, so HC remains the only
|
||||
// source of variation for the black row when both are on.
|
||||
let black_card = Card { id: 0, suit: Suit::Clubs, rank: Rank::King, face_up: true };
|
||||
fn text_colour_high_contrast_alone_boosts_spades_under_cbm() {
|
||||
// CBM doesn't touch spades, so HC remains the only source
|
||||
// of variation for the spade row when both are on. (Pre-
|
||||
// 4-colour-deck this test used Clubs; in the 4-colour
|
||||
// scheme clubs is lime not gray, so the assertion shifted
|
||||
// to the only suit that's still gray-family.)
|
||||
let spades = Card { id: 0, suit: Suit::Spades, rank: Rank::King, face_up: true };
|
||||
assert_eq!(
|
||||
text_colour(&black_card, true, true),
|
||||
text_colour(&spades, true, true),
|
||||
TEXT_PRIMARY_HC,
|
||||
"with CBM + HC both on, black suits still pick up the HC boost",
|
||||
"with CBM + HC both on, spades still pick up the HC boost",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn text_colour_diamonds_and_clubs_are_immune_to_accessibility_flags() {
|
||||
// Diamonds (gold) and clubs (lime) are already mid-luminance
|
||||
// hue-distinct accents, so neither CBM nor HC has a defined
|
||||
// boost for them. Verify all four flag combinations leave
|
||||
// them at their default suit colour.
|
||||
let d = Card { id: 0, suit: Suit::Diamonds, rank: Rank::King, face_up: true };
|
||||
let c = Card { id: 0, suit: Suit::Clubs, rank: Rank::King, face_up: true };
|
||||
for (cbm, hc) in [(false, false), (false, true), (true, false), (true, true)] {
|
||||
assert_eq!(text_colour(&d, cbm, hc), DIAMOND_SUIT_COLOUR);
|
||||
assert_eq!(text_colour(&c, cbm, hc), CLUB_SUIT_COLOUR);
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// label_visibility (pure)
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
@@ -24,32 +24,32 @@ use solitaire_engine::assets::card_face_svg::{
|
||||
use solitaire_engine::assets::rasterize_svg;
|
||||
|
||||
const EXPECTED: &[(&str, u64)] = &[
|
||||
("face_AC", 0xdac8c6f869cea53c),
|
||||
("face_2C", 0x8976454d1919bfdb),
|
||||
("face_3C", 0x0eda320371ca2d3f),
|
||||
("face_4C", 0x2e921081296553c9),
|
||||
("face_5C", 0xdb574a322d615af0),
|
||||
("face_6C", 0xad93daa160b5e7fa),
|
||||
("face_7C", 0xa3cdae097cb23271),
|
||||
("face_8C", 0x7b652bc9f0a5940b),
|
||||
("face_9C", 0xb5b274c80f319b85),
|
||||
("face_10C", 0x2ed8324f84c443cd),
|
||||
("face_JC", 0x3d9bc380e83d7611),
|
||||
("face_QC", 0xacad01ad4053a396),
|
||||
("face_KC", 0xba575aa772fc2e3e),
|
||||
("face_AD", 0xe1049b5a7d2c110c),
|
||||
("face_2D", 0x58f2a7e60a5cfff9),
|
||||
("face_3D", 0x89aeece03e7afe0b),
|
||||
("face_4D", 0xb97dd2633958d6ba),
|
||||
("face_5D", 0x32b57300e16c5b30),
|
||||
("face_6D", 0xd617e851d97f4a7d),
|
||||
("face_7D", 0xdd2da9b2457bfded),
|
||||
("face_8D", 0xfe00cf683015f30b),
|
||||
("face_9D", 0x7188b0fade3d086a),
|
||||
("face_10D", 0x53d0db517868e1f7),
|
||||
("face_JD", 0xeb2c6a0192146258),
|
||||
("face_QD", 0x36edafbbc3d34f0a),
|
||||
("face_KD", 0x1bbfa8b1176ee3ac),
|
||||
("face_AC", 0x287e3293f95990a5),
|
||||
("face_2C", 0x01c66d8e461fb0c4),
|
||||
("face_3C", 0xfdae6be53af8b7c8),
|
||||
("face_4C", 0x4b2a7aef966c6cc2),
|
||||
("face_5C", 0xa4ca0ce3759b5cc9),
|
||||
("face_6C", 0xe1a730d1ce810314),
|
||||
("face_7C", 0x9c8de5c7d014eca3),
|
||||
("face_8C", 0x39e09f90c957b192),
|
||||
("face_9C", 0xd6627707fb2d5079),
|
||||
("face_10C", 0xbe8411c60411195c),
|
||||
("face_JC", 0x7c33abf5619477ac),
|
||||
("face_QC", 0xe75657d63c99a892),
|
||||
("face_KC", 0xf4a445b771026496),
|
||||
("face_AD", 0xad8820c694c464d7),
|
||||
("face_2D", 0xef771dbb39ae4f5a),
|
||||
("face_3D", 0xe955ec9a96e1256a),
|
||||
("face_4D", 0x6bb5979ef6004957),
|
||||
("face_5D", 0x55715fd2353b2126),
|
||||
("face_6D", 0x87fbd6efce1b1f9f),
|
||||
("face_7D", 0xabb2d52d363e93ab),
|
||||
("face_8D", 0xde78161ee9093b05),
|
||||
("face_9D", 0x1475987ba1e66036),
|
||||
("face_10D", 0x3a52d7fda7158aeb),
|
||||
("face_JD", 0xc9078d8a7b2e6372),
|
||||
("face_QD", 0x84c9011b916fdbe8),
|
||||
("face_KD", 0xbcd20dbb6b1c8cdf),
|
||||
("face_AH", 0x2c8e05964b5e3a5f),
|
||||
("face_2H", 0xb44e68b79bb3842e),
|
||||
("face_3H", 0x15226ed29769e1c4),
|
||||
|
||||