diff --git a/solitaire_engine/assets/themes/default/back.svg b/solitaire_engine/assets/themes/default/back.svg
index 06454d4..4bdc34e 100644
--- a/solitaire_engine/assets/themes/default/back.svg
+++ b/solitaire_engine/assets/themes/default/back.svg
@@ -1,40 +1,21 @@
-
-
-
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/clubs_10.svg b/solitaire_engine/assets/themes/default/clubs_10.svg
index 2e7788c..cc9d59b 100644
--- a/solitaire_engine/assets/themes/default/clubs_10.svg
+++ b/solitaire_engine/assets/themes/default/clubs_10.svg
@@ -1,281 +1,16 @@
-
+
+
-
+
+ 10
+ ♣
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-1
-0
-1
-0
-
+
+ ♣
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/clubs_2.svg b/solitaire_engine/assets/themes/default/clubs_2.svg
index 0334dec..7858796 100644
--- a/solitaire_engine/assets/themes/default/clubs_2.svg
+++ b/solitaire_engine/assets/themes/default/clubs_2.svg
@@ -1,216 +1,16 @@
-
+
+
-
+
+ 2
+ ♣
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-2
-
-
-
-
-
-2
-
-
-
-
+
+ ♣
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/clubs_3.svg b/solitaire_engine/assets/themes/default/clubs_3.svg
index 0fb95b3..f527127 100644
--- a/solitaire_engine/assets/themes/default/clubs_3.svg
+++ b/solitaire_engine/assets/themes/default/clubs_3.svg
@@ -1,224 +1,16 @@
-
+
+
-
+
+ 3
+ ♣
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-3
-
-
-
-
-
-
-3
-
-
-
-
-
+
+ ♣
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/clubs_4.svg b/solitaire_engine/assets/themes/default/clubs_4.svg
index 70f8904..b9b4b62 100644
--- a/solitaire_engine/assets/themes/default/clubs_4.svg
+++ b/solitaire_engine/assets/themes/default/clubs_4.svg
@@ -1,230 +1,16 @@
-
+
+
-
+
+ 4
+ ♣
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-4
-
-
-
-
-
-
-4
-
-
-
-
-
+
+ ♣
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/clubs_5.svg b/solitaire_engine/assets/themes/default/clubs_5.svg
index 864d2f2..4e33adb 100644
--- a/solitaire_engine/assets/themes/default/clubs_5.svg
+++ b/solitaire_engine/assets/themes/default/clubs_5.svg
@@ -1,238 +1,16 @@
-
+
+
-
+
+ 5
+ ♣
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-5
-
-
-
-
-
-
-
-5
-
-
-
-
-
-
+
+ ♣
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/clubs_6.svg b/solitaire_engine/assets/themes/default/clubs_6.svg
index 306754e..ca85c51 100644
--- a/solitaire_engine/assets/themes/default/clubs_6.svg
+++ b/solitaire_engine/assets/themes/default/clubs_6.svg
@@ -1,244 +1,16 @@
-
+
+
-
+
+ 6
+ ♣
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-6
-
-
-
-
-
-
-
-6
-
-
-
-
-
-
+
+ ♣
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/clubs_7.svg b/solitaire_engine/assets/themes/default/clubs_7.svg
index 11329b1..b0e1613 100644
--- a/solitaire_engine/assets/themes/default/clubs_7.svg
+++ b/solitaire_engine/assets/themes/default/clubs_7.svg
@@ -1,252 +1,16 @@
-
+
+
-
+
+ 7
+ ♣
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-7
-
-
-
-
-
-
-
-
-7
-
-
-
-
-
-
-
+
+ ♣
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/clubs_8.svg b/solitaire_engine/assets/themes/default/clubs_8.svg
index 28ae6fb..fd1eddb 100644
--- a/solitaire_engine/assets/themes/default/clubs_8.svg
+++ b/solitaire_engine/assets/themes/default/clubs_8.svg
@@ -1,260 +1,16 @@
-
+
+
-
+
+ 8
+ ♣
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-8
-
-
-
-
-
-
-
-
-
-8
-
-
-
-
-
-
-
-
+
+ ♣
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/clubs_9.svg b/solitaire_engine/assets/themes/default/clubs_9.svg
index 85cde35..d6facf5 100644
--- a/solitaire_engine/assets/themes/default/clubs_9.svg
+++ b/solitaire_engine/assets/themes/default/clubs_9.svg
@@ -1,254 +1,16 @@
-
+
+
-
+
+ 9
+ ♣
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-9
-
-
-
-
-
-
-
-
-
-
-
-
-9
-
-
-
-
-
-
-
-
-
-
-
+
+ ♣
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/clubs_ace.svg b/solitaire_engine/assets/themes/default/clubs_ace.svg
index be74fe0..7a43d1e 100644
--- a/solitaire_engine/assets/themes/default/clubs_ace.svg
+++ b/solitaire_engine/assets/themes/default/clubs_ace.svg
@@ -1,258 +1,16 @@
-
+
+
-
+
+ A
+ ♣
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-A
-
-
-A
-
+
+ ♣
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/clubs_jack.svg b/solitaire_engine/assets/themes/default/clubs_jack.svg
index a350305..b8efe0e 100644
--- a/solitaire_engine/assets/themes/default/clubs_jack.svg
+++ b/solitaire_engine/assets/themes/default/clubs_jack.svg
@@ -1,224 +1,16 @@
-
+
+
-
+
+ J
+ ♣
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-J
-
-
-
-J
-
-
-
-
+
+ ♣
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/clubs_king.svg b/solitaire_engine/assets/themes/default/clubs_king.svg
index fe6e676..c312301 100644
--- a/solitaire_engine/assets/themes/default/clubs_king.svg
+++ b/solitaire_engine/assets/themes/default/clubs_king.svg
@@ -1,254 +1,16 @@
-
+
+
-
+
+ K
+ ♣
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-K
-
-
-
-
-
-K
-
-
-
-
+
+ ♣
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/clubs_queen.svg b/solitaire_engine/assets/themes/default/clubs_queen.svg
index 6a636f7..909471f 100644
--- a/solitaire_engine/assets/themes/default/clubs_queen.svg
+++ b/solitaire_engine/assets/themes/default/clubs_queen.svg
@@ -1,250 +1,16 @@
-
+
+
-
+
+ Q
+ ♣
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Q
-
-
-
-
-
-Q
-
-
-
-
+
+ ♣
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/diamonds_10.svg b/solitaire_engine/assets/themes/default/diamonds_10.svg
index 3d0b1c0..787dbf3 100644
--- a/solitaire_engine/assets/themes/default/diamonds_10.svg
+++ b/solitaire_engine/assets/themes/default/diamonds_10.svg
@@ -1,401 +1,16 @@
-
+
+
-
+
+ 10
+ ♦
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-0
-1
-0
-
+
+ ♦
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/diamonds_2.svg b/solitaire_engine/assets/themes/default/diamonds_2.svg
index 4956234..ec359ca 100644
--- a/solitaire_engine/assets/themes/default/diamonds_2.svg
+++ b/solitaire_engine/assets/themes/default/diamonds_2.svg
@@ -1,318 +1,16 @@
-
+
+
-
+
+ 2
+ ♦
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-2
-
-
-
-
-
-
-2
-
-
-
-
-
-
+
+ ♦
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/diamonds_3.svg b/solitaire_engine/assets/themes/default/diamonds_3.svg
index a562f1f..0cd574b 100644
--- a/solitaire_engine/assets/themes/default/diamonds_3.svg
+++ b/solitaire_engine/assets/themes/default/diamonds_3.svg
@@ -1,319 +1,16 @@
-
+
+
-
+
+ 3
+ ♦
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-3
-
-
-
-
-
-
-
-
-3
-
-
-
-
-
-
-
-
+
+ ♦
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/diamonds_4.svg b/solitaire_engine/assets/themes/default/diamonds_4.svg
index 8677737..850eb6e 100644
--- a/solitaire_engine/assets/themes/default/diamonds_4.svg
+++ b/solitaire_engine/assets/themes/default/diamonds_4.svg
@@ -1,324 +1,16 @@
-
+
+
-
+
+ 4
+ ♦
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-4
-
-
-
-
-
-
-
-4
-
-
-
-
-
-
-
+
+ ♦
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/diamonds_5.svg b/solitaire_engine/assets/themes/default/diamonds_5.svg
index a8cb2b5..4e5d760 100644
--- a/solitaire_engine/assets/themes/default/diamonds_5.svg
+++ b/solitaire_engine/assets/themes/default/diamonds_5.svg
@@ -1,333 +1,16 @@
-
+
+
-
+
+ 5
+ ♦
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-5
-
-
-
-
-
-
-
-
-5
-
-
-
-
-
-
-
-
+
+ ♦
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/diamonds_6.svg b/solitaire_engine/assets/themes/default/diamonds_6.svg
index 6f12a53..c2ab18b 100644
--- a/solitaire_engine/assets/themes/default/diamonds_6.svg
+++ b/solitaire_engine/assets/themes/default/diamonds_6.svg
@@ -1,340 +1,16 @@
-
+
+
-
+
+ 6
+ ♦
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-6
-
-
-
-
-
-
-
-
-6
-
-
-
-
-
-
-
-
+
+ ♦
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/diamonds_7.svg b/solitaire_engine/assets/themes/default/diamonds_7.svg
index d8483a7..08fc2df 100644
--- a/solitaire_engine/assets/themes/default/diamonds_7.svg
+++ b/solitaire_engine/assets/themes/default/diamonds_7.svg
@@ -1,349 +1,16 @@
-
+
+
-
+
+ 7
+ ♦
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-7
-
-
-
-
-
-
-
-
-
-7
-
-
-
-
-
-
-
-
-
+
+ ♦
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/diamonds_8.svg b/solitaire_engine/assets/themes/default/diamonds_8.svg
index d6d1b0e..56ad92c 100644
--- a/solitaire_engine/assets/themes/default/diamonds_8.svg
+++ b/solitaire_engine/assets/themes/default/diamonds_8.svg
@@ -1,358 +1,16 @@
-
+
+
-
+
+ 8
+ ♦
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-8
-
-
-
-
-
-
-
-
-
-
-8
-
-
-
-
-
-
-
-
-
-
+
+ ♦
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/diamonds_9.svg b/solitaire_engine/assets/themes/default/diamonds_9.svg
index 05292f2..3edd6a8 100644
--- a/solitaire_engine/assets/themes/default/diamonds_9.svg
+++ b/solitaire_engine/assets/themes/default/diamonds_9.svg
@@ -1,367 +1,16 @@
-
+
+
-
+
+ 9
+ ♦
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-9
-
-
-
-
-
-
-
-
-
-
-
-9
-
-
-
-
-
-
-
-
-
-
-
+
+ ♦
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/diamonds_ace.svg b/solitaire_engine/assets/themes/default/diamonds_ace.svg
index e5636a4..a98bc3e 100644
--- a/solitaire_engine/assets/themes/default/diamonds_ace.svg
+++ b/solitaire_engine/assets/themes/default/diamonds_ace.svg
@@ -1,311 +1,16 @@
-
+
+
-
+
+ A
+ ♦
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-A
-
-
-A
-
-
+
+ ♦
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/diamonds_jack.svg b/solitaire_engine/assets/themes/default/diamonds_jack.svg
index d531541..5f2284a 100644
--- a/solitaire_engine/assets/themes/default/diamonds_jack.svg
+++ b/solitaire_engine/assets/themes/default/diamonds_jack.svg
@@ -1,338 +1,16 @@
-
+
+
-
+
+ J
+ ♦
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-J
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-J
-
-
-
-
+
+ ♦
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/diamonds_king.svg b/solitaire_engine/assets/themes/default/diamonds_king.svg
index f983c6a..9c99bd2 100644
--- a/solitaire_engine/assets/themes/default/diamonds_king.svg
+++ b/solitaire_engine/assets/themes/default/diamonds_king.svg
@@ -1,351 +1,16 @@
-
+
+
-
+
+ K
+ ♦
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-K
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-K
-
-
-
-
+
+ ♦
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/diamonds_queen.svg b/solitaire_engine/assets/themes/default/diamonds_queen.svg
index 76b62db..8149a9b 100644
--- a/solitaire_engine/assets/themes/default/diamonds_queen.svg
+++ b/solitaire_engine/assets/themes/default/diamonds_queen.svg
@@ -1,339 +1,16 @@
-
+
+
-
+
+ Q
+ ♦
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Q
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Q
-
-
-
-
+
+ ♦
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/hearts_10.svg b/solitaire_engine/assets/themes/default/hearts_10.svg
index c57575e..dee6d99 100644
--- a/solitaire_engine/assets/themes/default/hearts_10.svg
+++ b/solitaire_engine/assets/themes/default/hearts_10.svg
@@ -1,407 +1,16 @@
-
+
+
-
+
+ 10
+ ♥
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-0
-1
-0
-
+
+ ♥
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/hearts_2.svg b/solitaire_engine/assets/themes/default/hearts_2.svg
index f6c9540..a1004c8 100644
--- a/solitaire_engine/assets/themes/default/hearts_2.svg
+++ b/solitaire_engine/assets/themes/default/hearts_2.svg
@@ -1,308 +1,16 @@
-
+
+
-
+
+ 2
+ ♥
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-2
-
-
-
-
-
-
-2
-
-
-
-
-
-
+
+ ♥
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/hearts_3.svg b/solitaire_engine/assets/themes/default/hearts_3.svg
index aecd1ff..671e2d3 100644
--- a/solitaire_engine/assets/themes/default/hearts_3.svg
+++ b/solitaire_engine/assets/themes/default/hearts_3.svg
@@ -1,318 +1,16 @@
-
+
+
-
+
+ 3
+ ♥
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-3
-
-
-
-
-
-
-
-3
-
-
-
-
-
-
-
+
+ ♥
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/hearts_4.svg b/solitaire_engine/assets/themes/default/hearts_4.svg
index 9b7f0a7..cd7b61b 100644
--- a/solitaire_engine/assets/themes/default/hearts_4.svg
+++ b/solitaire_engine/assets/themes/default/hearts_4.svg
@@ -1,335 +1,16 @@
-
+
+
-
+
+ 4
+ ♥
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-4
-
-
-
-
-
-
-
-4
-
-
-
-
-
-
-
+
+ ♥
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/hearts_5.svg b/solitaire_engine/assets/themes/default/hearts_5.svg
index af7415a..2b73200 100644
--- a/solitaire_engine/assets/themes/default/hearts_5.svg
+++ b/solitaire_engine/assets/themes/default/hearts_5.svg
@@ -1,336 +1,16 @@
-
+
+
-
+
+ 5
+ ♥
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-5
-
-
-
-
-
-
-
-
-5
-
-
-
-
-
-
-
-
+
+ ♥
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/hearts_6.svg b/solitaire_engine/assets/themes/default/hearts_6.svg
index 9c319ad..cedc285 100644
--- a/solitaire_engine/assets/themes/default/hearts_6.svg
+++ b/solitaire_engine/assets/themes/default/hearts_6.svg
@@ -1,344 +1,16 @@
-
+
+
-
+
+ 6
+ ♥
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-6
-
-
-
-
-
-
-
-
-6
-
-
-
-
-
-
-
-
+
+ ♥
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/hearts_7.svg b/solitaire_engine/assets/themes/default/hearts_7.svg
index 8d5fd98..7cc2063 100644
--- a/solitaire_engine/assets/themes/default/hearts_7.svg
+++ b/solitaire_engine/assets/themes/default/hearts_7.svg
@@ -1,356 +1,16 @@
-
+
+
-
+
+ 7
+ ♥
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-7
-
-
-
-
-
-
-
-
-
-
-7
-
-
-
-
-
-
-
-
-
-
+
+ ♥
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/hearts_8.svg b/solitaire_engine/assets/themes/default/hearts_8.svg
index ac8d5ba..b190afa 100644
--- a/solitaire_engine/assets/themes/default/hearts_8.svg
+++ b/solitaire_engine/assets/themes/default/hearts_8.svg
@@ -1,364 +1,16 @@
-
+
+
-
+
+ 8
+ ♥
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-8
-
-
-
-
-
-
-
-
-
-
-8
-
-
-
-
-
-
-
-
-
-
+
+ ♥
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/hearts_9.svg b/solitaire_engine/assets/themes/default/hearts_9.svg
index 0f6a211..83cb835 100644
--- a/solitaire_engine/assets/themes/default/hearts_9.svg
+++ b/solitaire_engine/assets/themes/default/hearts_9.svg
@@ -1,378 +1,16 @@
-
+
+
-
+
+ 9
+ ♥
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-9
-
-
-
-9
-
+
+ ♥
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/hearts_ace.svg b/solitaire_engine/assets/themes/default/hearts_ace.svg
index 24702e2..100e02c 100644
--- a/solitaire_engine/assets/themes/default/hearts_ace.svg
+++ b/solitaire_engine/assets/themes/default/hearts_ace.svg
@@ -1,324 +1,16 @@
-
+
+
-
+
+ A
+ ♥
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-A
-
-A
-
+
+ ♥
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/hearts_jack.svg b/solitaire_engine/assets/themes/default/hearts_jack.svg
index dc95ce1..1b4c8fe 100644
--- a/solitaire_engine/assets/themes/default/hearts_jack.svg
+++ b/solitaire_engine/assets/themes/default/hearts_jack.svg
@@ -1,330 +1,16 @@
-
+
+
-
+
+ J
+ ♥
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-J
-
-
-
-
-
-
-
-
-
-
-
-
-J
-
-
-
-
+
+ ♥
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/hearts_king.svg b/solitaire_engine/assets/themes/default/hearts_king.svg
index 7250745..74934e7 100644
--- a/solitaire_engine/assets/themes/default/hearts_king.svg
+++ b/solitaire_engine/assets/themes/default/hearts_king.svg
@@ -1,337 +1,16 @@
-
+
+
-
+
+ K
+ ♥
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-K
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-K
-
-
-
-
+
+ ♥
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/hearts_queen.svg b/solitaire_engine/assets/themes/default/hearts_queen.svg
index 90ede78..843c3cf 100644
--- a/solitaire_engine/assets/themes/default/hearts_queen.svg
+++ b/solitaire_engine/assets/themes/default/hearts_queen.svg
@@ -1,331 +1,16 @@
-
+
+
-
+
+ Q
+ ♥
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Q
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Q
-
-
-
-
-
+
+ ♥
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/spades_10.svg b/solitaire_engine/assets/themes/default/spades_10.svg
index a14767c..174a1bd 100644
--- a/solitaire_engine/assets/themes/default/spades_10.svg
+++ b/solitaire_engine/assets/themes/default/spades_10.svg
@@ -1,230 +1,16 @@
-
+
+
-
+
+ 10
+ ♠
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-1
-
-
-
-
-
-
-
-
-0
-1
-0
-
+
+ ♠
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/spades_2.svg b/solitaire_engine/assets/themes/default/spades_2.svg
index 759abf6..de978fe 100644
--- a/solitaire_engine/assets/themes/default/spades_2.svg
+++ b/solitaire_engine/assets/themes/default/spades_2.svg
@@ -1,147 +1,16 @@
-
+
+
-
+
+ 2
+ ♠
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-2
-
-
-
-2
-
-
+
+ ♠
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/spades_3.svg b/solitaire_engine/assets/themes/default/spades_3.svg
index 8963195..24696c7 100644
--- a/solitaire_engine/assets/themes/default/spades_3.svg
+++ b/solitaire_engine/assets/themes/default/spades_3.svg
@@ -1,154 +1,16 @@
-
+
+
-
+
+ 3
+ ♠
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-3
-
-
-
-3
-
-
+
+ ♠
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/spades_4.svg b/solitaire_engine/assets/themes/default/spades_4.svg
index 01e27e4..fa700db 100644
--- a/solitaire_engine/assets/themes/default/spades_4.svg
+++ b/solitaire_engine/assets/themes/default/spades_4.svg
@@ -1,163 +1,16 @@
-
+
+
-
+
+ 4
+ ♠
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-4
-
-
-
-
-4
-
-
-
+
+ ♠
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/spades_5.svg b/solitaire_engine/assets/themes/default/spades_5.svg
index d9492ba..bf6cfb9 100644
--- a/solitaire_engine/assets/themes/default/spades_5.svg
+++ b/solitaire_engine/assets/themes/default/spades_5.svg
@@ -1,170 +1,16 @@
-
+
+
-
+
+ 5
+ ♠
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-5
-
-
-
-
-5
-
-
-
+
+ ♠
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/spades_6.svg b/solitaire_engine/assets/themes/default/spades_6.svg
index 83e8feb..7b16a84 100644
--- a/solitaire_engine/assets/themes/default/spades_6.svg
+++ b/solitaire_engine/assets/themes/default/spades_6.svg
@@ -1,177 +1,16 @@
-
+
+
-
+
+ 6
+ ♠
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-6
-
-
-
-
-6
-
-
-
+
+ ♠
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/spades_7.svg b/solitaire_engine/assets/themes/default/spades_7.svg
index 3146b44..f7e946b 100644
--- a/solitaire_engine/assets/themes/default/spades_7.svg
+++ b/solitaire_engine/assets/themes/default/spades_7.svg
@@ -1,186 +1,16 @@
-
+
+
-
+
+ 7
+ ♠
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-7
-
-
-
-
-
-7
-
-
-
-
+
+ ♠
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/spades_8.svg b/solitaire_engine/assets/themes/default/spades_8.svg
index 0e5bd89..545f837 100644
--- a/solitaire_engine/assets/themes/default/spades_8.svg
+++ b/solitaire_engine/assets/themes/default/spades_8.svg
@@ -1,195 +1,16 @@
-
+
+
-
+
+ 8
+ ♠
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-8
-
-
-
-
-
-
-8
-
-
-
-
-
+
+ ♠
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/spades_9.svg b/solitaire_engine/assets/themes/default/spades_9.svg
index 2359db5..6d9ae0a 100644
--- a/solitaire_engine/assets/themes/default/spades_9.svg
+++ b/solitaire_engine/assets/themes/default/spades_9.svg
@@ -1,198 +1,16 @@
-
+
+
-
+
+ 9
+ ♠
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-9
-
-
-
-
-9
-
-
-
+
+ ♠
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/spades_ace.svg b/solitaire_engine/assets/themes/default/spades_ace.svg
index db32c06..ef0b36d 100644
--- a/solitaire_engine/assets/themes/default/spades_ace.svg
+++ b/solitaire_engine/assets/themes/default/spades_ace.svg
@@ -1,131 +1,16 @@
-
+
+
-
+
+ A
+ ♠
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-A
-A
-
+
+ ♠
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/spades_jack.svg b/solitaire_engine/assets/themes/default/spades_jack.svg
index 281113f..96d6382 100644
--- a/solitaire_engine/assets/themes/default/spades_jack.svg
+++ b/solitaire_engine/assets/themes/default/spades_jack.svg
@@ -1,336 +1,16 @@
-
+
+
-
+
+ J
+ ♠
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-J
-
-
-
-
-
-
-J
-
-
-
-
+
+ ♠
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/spades_king.svg b/solitaire_engine/assets/themes/default/spades_king.svg
index ac4338d..87e86b8 100644
--- a/solitaire_engine/assets/themes/default/spades_king.svg
+++ b/solitaire_engine/assets/themes/default/spades_king.svg
@@ -1,329 +1,16 @@
-
+
+
-
+
+ K
+ ♠
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-K
-
-
-
-
-
-
-
-
-K
-
-
-
-
+
+ ♠
+
\ No newline at end of file
diff --git a/solitaire_engine/assets/themes/default/spades_queen.svg b/solitaire_engine/assets/themes/default/spades_queen.svg
index 8dc5540..c462ea6 100644
--- a/solitaire_engine/assets/themes/default/spades_queen.svg
+++ b/solitaire_engine/assets/themes/default/spades_queen.svg
@@ -1,324 +1,16 @@
-
+
+
-
+
+ Q
+ ♠
-image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Q
-
-
-
-
-
-
-
-Q
-
-
-
+
+ ♠
+
\ No newline at end of file
diff --git a/solitaire_engine/examples/card_face_generator.rs b/solitaire_engine/examples/card_face_generator.rs
index 5ac4a1b..0a3842b 100644
--- a/solitaire_engine/examples/card_face_generator.rs
+++ b/solitaire_engine/examples/card_face_generator.rs
@@ -1,5 +1,19 @@
-//! Card-face generator — writes 52 Terminal-aesthetic face PNGs +
-//! 5 back PNGs into `assets/cards/`.
+//! Card-face generator — writes Terminal-aesthetic artwork into both
+//! rendering paths the engine consults at runtime:
+//!
+//! 1. **Asset PNGs at `assets/cards/`** — 52 face + 5 back PNGs loaded
+//! by `card_plugin::load_card_images` as the *fallback* art.
+//! 2. **Default-theme SVGs at `solitaire_engine/assets/themes/default/`**
+//! — 52 face + 1 back SVGs that get `include_bytes!()`-embedded into
+//! the binary by `solitaire_engine::assets::sources` and applied to
+//! `CardImageSet` at startup by `theme::plugin::apply_theme_to_card_image_set`.
+//! These *override* the asset PNGs in production; the PNGs only show
+//! if the active theme fails to provide a face.
+//!
+//! Both paths share the same SVG builders in
+//! `solitaire_engine::assets::card_face_svg`, so the artwork stays
+//! identical at the source level — running this generator keeps both
+//! paths in lockstep.
//!
//! Run with:
//!
@@ -7,63 +21,90 @@
//! cargo run --example card_face_generator --release
//! ```
//!
-//! This is **step 2** of the lockstep migration outlined in
-//! `docs/ui-mockups/card-face-migration.md`. Running it overwrites
-//! the legacy PNG artwork in-place; the resulting bytes are what
-//! step 4 commits alongside the `card_plugin` constant migration.
-//!
-//! The SVG builders live in
-//! `solitaire_engine::assets::card_face_svg` so the integration
-//! test at `tests/card_face_svg_pin.rs` can pin their output
-//! against `usvg`/`resvg` rendering drift.
+//! Step 2 of the lockstep migration outlined in
+//! `docs/ui-mockups/card-face-migration.md`. Running it overwrites the
+//! legacy artwork in-place; the resulting bytes are what step 4 commits
+//! alongside the `card_plugin` constant migration.
use solitaire_engine::assets::card_face_svg::{
- back_svg, face_svg, rank_filename, suit_filename, ALL_RANKS, ALL_SUITS, BACK_ACCENTS, TARGET,
+ back_svg, face_svg, rank_filename, suit_filename, theme_rank_token, theme_suit_token,
+ ALL_RANKS, ALL_SUITS, BACK_ACCENTS, TARGET,
};
use solitaire_engine::assets::rasterize_svg;
use std::path::PathBuf;
use tiny_skia::{IntSize, Pixmap};
fn main() {
- let cards_dir = workspace_assets_dir().join("cards");
+ let workspace_assets = workspace_assets_dir();
+ let cards_dir = workspace_assets.join("cards");
let faces_dir = cards_dir.join("faces");
let backs_dir = cards_dir.join("backs");
std::fs::create_dir_all(&faces_dir).expect("create faces dir");
std::fs::create_dir_all(&backs_dir).expect("create backs dir");
- let mut written = 0usize;
+ // The default theme lives inside the engine crate (so its SVGs can
+ // be `include_bytes!()`-embedded relative to the `assets/sources.rs`
+ // file path). Workspace-level `assets/cards/` is the fallback path;
+ // engine-level `assets/themes/default/` is what production renders.
+ let theme_dir = engine_default_theme_dir();
+ std::fs::create_dir_all(&theme_dir).expect("create default-theme dir");
+
+ let mut png_written = 0usize;
+ let mut svg_written = 0usize;
for suit in ALL_SUITS {
for rank in ALL_RANKS {
let svg = face_svg(rank, suit);
- let pixmap = rasterize_to_pixmap(&svg);
- let path = faces_dir.join(format!(
+
+ // Path 1 — fallback PNG.
+ let png_path = faces_dir.join(format!(
"{}{}.png",
rank_filename(rank),
suit_filename(suit)
));
- pixmap
- .save_png(&path)
- .unwrap_or_else(|e| panic!("write {}: {e}", path.display()));
- written += 1;
+ rasterize_to_pixmap(&svg)
+ .save_png(&png_path)
+ .unwrap_or_else(|e| panic!("write {}: {e}", png_path.display()));
+ png_written += 1;
+
+ // Path 2 — bundled-default-theme SVG. Same SVG bytes; the
+ // theme system rasterises them at runtime.
+ let svg_path = theme_dir.join(format!(
+ "{}_{}.svg",
+ theme_suit_token(suit),
+ theme_rank_token(rank),
+ ));
+ std::fs::write(&svg_path, &svg)
+ .unwrap_or_else(|e| panic!("write {}: {e}", svg_path.display()));
+ svg_written += 1;
}
}
+ // Fallback backs — 5 PNGs, one per `Settings::selected_card_back`.
for (idx, accent) in BACK_ACCENTS.iter().enumerate() {
let svg = back_svg(accent);
- let pixmap = rasterize_to_pixmap(&svg);
- let path = backs_dir.join(format!("back_{idx}.png"));
- pixmap
- .save_png(&path)
- .unwrap_or_else(|e| panic!("write {}: {e}", path.display()));
- written += 1;
+ let png_path = backs_dir.join(format!("back_{idx}.png"));
+ rasterize_to_pixmap(&svg)
+ .save_png(&png_path)
+ .unwrap_or_else(|e| panic!("write {}: {e}", png_path.display()));
+ png_written += 1;
}
+ // Theme back — single SVG. Use the canonical Terminal accent
+ // (`BACK_ACCENTS[0]` cyan) — the theme system only carries one back
+ // per theme, and the canonical Terminal back is the design-system
+ // default. The other four accents only live as PNG fallbacks.
+ let theme_back_path = theme_dir.join("back.svg");
+ std::fs::write(&theme_back_path, back_svg(BACK_ACCENTS[0]))
+ .unwrap_or_else(|e| panic!("write {}: {e}", theme_back_path.display()));
+ svg_written += 1;
+
println!(
- "Wrote {written} PNGs ({}×{} RGBA8) to {}",
+ "Wrote {png_written} PNGs ({}×{} RGBA8) to {} and {svg_written} SVGs to {}",
TARGET.x,
TARGET.y,
cards_dir.display(),
+ theme_dir.display(),
);
}
@@ -88,3 +129,13 @@ fn workspace_assets_dir() -> PathBuf {
.expect("solitaire_engine crate has a workspace-root parent")
.join("assets")
}
+
+/// Resolves `solitaire_engine/assets/themes/default/` relative to the
+/// example crate. Matches `DEFAULT_THEME_MANIFEST_PATH` in
+/// `solitaire_engine::assets::sources`.
+fn engine_default_theme_dir() -> PathBuf {
+ PathBuf::from(env!("CARGO_MANIFEST_DIR"))
+ .join("assets")
+ .join("themes")
+ .join("default")
+}
diff --git a/solitaire_engine/src/assets/card_face_svg.rs b/solitaire_engine/src/assets/card_face_svg.rs
index 798f223..8c91636 100644
--- a/solitaire_engine/src/assets/card_face_svg.rs
+++ b/solitaire_engine/src/assets/card_face_svg.rs
@@ -103,6 +103,39 @@ pub fn suit_filename(suit: Suit) -> &'static str {
}
}
+/// Lowercase full-word suit token used by the bundled-default theme's
+/// SVG filenames (`_.svg` — e.g. `spades_ace.svg`). Mirrors
+/// `solitaire_engine::theme::CardKey::manifest_name`.
+pub fn theme_suit_token(suit: Suit) -> &'static str {
+ match suit {
+ Suit::Clubs => "clubs",
+ Suit::Diamonds => "diamonds",
+ Suit::Hearts => "hearts",
+ Suit::Spades => "spades",
+ }
+}
+
+/// Lowercase full-word rank token used by the bundled-default theme's
+/// SVG filenames (`ace`, `2`..`10`, `jack`, `queen`, `king`). Mirrors
+/// `solitaire_engine::theme::CardKey::manifest_name`.
+pub fn theme_rank_token(rank: Rank) -> &'static str {
+ match rank {
+ Rank::Ace => "ace",
+ Rank::Two => "2",
+ Rank::Three => "3",
+ Rank::Four => "4",
+ Rank::Five => "5",
+ Rank::Six => "6",
+ Rank::Seven => "7",
+ Rank::Eight => "8",
+ Rank::Nine => "9",
+ Rank::Ten => "10",
+ Rank::Jack => "jack",
+ Rank::Queen => "queen",
+ Rank::King => "king",
+ }
+}
+
#[derive(Copy, Clone)]
enum GlyphPaint {
Filled,