diff --git a/android/app/build.gradle b/android/app/build.gradle
index 9e2643e56e910f0a8ff4a8b88a7d0968232c0bf3..c3c8f6672ba313bb98c44122715d166f56e0d829 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -37,7 +37,7 @@ if (keystorePropertiesFile.exists()) {
 }
 
 android {
-    compileSdkVersion 33
+    compileSdkVersion 34
     namespace "org.benoitharrault.solitaire"
 
     defaultConfig {
diff --git a/android/gradle.properties b/android/gradle.properties
index cd2d833ca96b3d1ada4a39df51dc5f5ee67665b7..30298b3b3f04073678e48519b8c043edba635df8 100644
--- a/android/gradle.properties
+++ b/android/gradle.properties
@@ -1,5 +1,5 @@
 org.gradle.jvmargs=-Xmx1536M
 android.useAndroidX=true
 android.enableJetifier=true
-app.versionName=0.0.17
-app.versionCode=17
+app.versionName=0.0.18
+app.versionCode=18
diff --git a/assets/icons/button_delete_saved_game.png b/assets/icons/button_delete_saved_game.png
deleted file mode 100644
index 5e4f217689b11e444b7163557d7e5d68f3bbfe7d..0000000000000000000000000000000000000000
Binary files a/assets/icons/button_delete_saved_game.png and /dev/null differ
diff --git a/assets/icons/button_resume_game.png b/assets/icons/button_resume_game.png
deleted file mode 100644
index b2ea0a02d05e42377eb551a4b51428b511a32f5d..0000000000000000000000000000000000000000
Binary files a/assets/icons/button_resume_game.png and /dev/null differ
diff --git a/assets/icons/game_fail.png b/assets/icons/game_fail.png
deleted file mode 100644
index 93f2801f9d6bb2ce508e1293cd64d6ff2e9970ec..0000000000000000000000000000000000000000
Binary files a/assets/icons/game_fail.png and /dev/null differ
diff --git a/assets/icons/layout_diamond.png b/assets/icons/layout_diamond.png
deleted file mode 100644
index d20c4ea546b070361e0d0d3aeb6682bca69273a6..0000000000000000000000000000000000000000
Binary files a/assets/icons/layout_diamond.png and /dev/null differ
diff --git a/assets/icons/layout_english.png b/assets/icons/layout_english.png
deleted file mode 100644
index 3ca9c27286c0fc3ec7d3808cd23118965b95892d..0000000000000000000000000000000000000000
Binary files a/assets/icons/layout_english.png and /dev/null differ
diff --git a/assets/icons/layout_french.png b/assets/icons/layout_french.png
deleted file mode 100644
index 71837c08f529075e14fce4db01f166cf9ac36d6c..0000000000000000000000000000000000000000
Binary files a/assets/icons/layout_french.png and /dev/null differ
diff --git a/assets/icons/layout_german.png b/assets/icons/layout_german.png
deleted file mode 100644
index 37c51ca8fdb173b33d06b23435a806fdb215b9bd..0000000000000000000000000000000000000000
Binary files a/assets/icons/layout_german.png and /dev/null differ
diff --git a/assets/icons/skin_default.png b/assets/icons/skin_default.png
deleted file mode 100644
index fbe9cb151a27e54b848f7cd48e397cd308f51dad..0000000000000000000000000000000000000000
Binary files a/assets/icons/skin_default.png and /dev/null differ
diff --git a/assets/translations/en.json b/assets/translations/en.json
index edfb95a30bace7bf5b2c37e3946e068ccbea735e..13da5fcbf5903240f481642c2ef432873c7a3d7c 100644
--- a/assets/translations/en.json
+++ b/assets/translations/en.json
@@ -1,8 +1,6 @@
 {
   "app_name": "Solitaire",
 
-  "long_press_to_quit": "Long press to quit game...",
-
   "bottom_nav_home": "Game",
   "bottom_nav_settings": "Settings",
   "bottom_nav_about": "About",
diff --git a/assets/translations/fr.json b/assets/translations/fr.json
index a4e231eb9e29deab5b2082bfcd0e981020be4b9e..0d43876a4b6ebfadf9222ed4ac88d5c53d5064ef 100644
--- a/assets/translations/fr.json
+++ b/assets/translations/fr.json
@@ -1,8 +1,6 @@
 {
   "app_name": "Solitaire",
 
-  "long_press_to_quit": "Appuyer longtemps pour quitter le jeu...",
-
   "bottom_nav_home": "Jeu",
   "bottom_nav_settings": "Réglages",
   "bottom_nav_about": "Infos",
diff --git a/fastlane/metadata/android/en-US/changelogs/18.txt b/fastlane/metadata/android/en-US/changelogs/18.txt
new file mode 100644
index 0000000000000000000000000000000000000000..9bb4c4dee10043312bc54a49a258422743bdc041
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/18.txt
@@ -0,0 +1 @@
+Improve application architecture.
diff --git a/fastlane/metadata/android/fr-FR/changelogs/18.txt b/fastlane/metadata/android/fr-FR/changelogs/18.txt
new file mode 100644
index 0000000000000000000000000000000000000000..5face79935538bfb3371042404b6c3586cc87f31
--- /dev/null
+++ b/fastlane/metadata/android/fr-FR/changelogs/18.txt
@@ -0,0 +1 @@
+Amélioration de l'architecture de l'application.
diff --git a/icons/build_game_icons.sh b/icons/build_game_icons.sh
index 4a9ca31a5b6aa7eee2cde162eecb09d0c2b0ce81..2191261bef769712d228d7a08e5dc97a727ee484 100755
--- a/icons/build_game_icons.sh
+++ b/icons/build_game_icons.sh
@@ -18,18 +18,10 @@ ICON_SIZE=192
 AVAILABLE_GAME_IMAGES="
   button_back
   button_start
-  button_resume_game
-  button_delete_saved_game
-  game_fail
   game_win
   placeholder
 "
 
-# Settings images
-AVAILABLES_GAME_SETTINGS="
-  layout:french,german,english,diamond
-"
-
 # Skins
 AVAILABLE_SKINS="
   default
@@ -84,25 +76,9 @@ function build_icon() {
   optipng ${OPTIPNG_OPTIONS} ${TARGET}
 }
 
-function build_settings_icons() {
-  INPUT_STRING="$1"
-
-  SETTING_NAME="$(echo "${INPUT_STRING}" | cut -d":" -f1)"
-  SETTING_VALUES="$(echo "${INPUT_STRING}" | cut -d":" -f2 | tr "," " ")"
-
-  for SETTING_VALUE in ${SETTING_VALUES}
-  do
-    SETTING_CODE="${SETTING_NAME}_${SETTING_VALUE}"
-    build_icon ${CURRENT_DIR}/${SETTING_CODE}.svg ${ASSETS_DIR}/icons/${SETTING_CODE}.png
-  done
-}
-
 function build_icon_for_skin() {
   SKIN_CODE="$1"
 
-  # skin main image
-  build_icon ${CURRENT_DIR}/skin_${SKIN_CODE}.svg ${ASSETS_DIR}/icons/skin_${SKIN_CODE}.png
-
   # skin images
   for SKIN_IMAGE in ${SKIN_IMAGES}
   do
@@ -126,12 +102,6 @@ do
   build_icon ${CURRENT_DIR}/${GAME_IMAGE}.svg ${ASSETS_DIR}/icons/${GAME_IMAGE}.png
 done
 
-# build settings images
-for GAME_SETTING in ${AVAILABLES_GAME_SETTINGS}
-do
-  build_settings_icons "${GAME_SETTING}"
-done
-
 # build skins images
 for SKIN in ${AVAILABLE_SKINS}
 do
diff --git a/icons/button_delete_saved_game.svg b/icons/button_delete_saved_game.svg
deleted file mode 100644
index ac7eefef476f761903fe781b8c86d0c94323550a..0000000000000000000000000000000000000000
--- a/icons/button_delete_saved_game.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 93.665 93.676" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x=".44662" y=".89101" width="92.772" height="91.894" ry="11.689" fill="#ee7d49" stroke="#fff" stroke-width=".238"/><path d="m61.07 35.601-1.7399 27.837c-0.13442 2.1535-1.9205 3.8312-4.0781 3.8312h-16.84c-2.1576 0-3.9437-1.6777-4.0781-3.8312l-1.7399-27.837h-2.6176c-0.84621 0-1.5323-0.68613-1.5323-1.5323 0-0.84655 0.68613-1.5323 1.5323-1.5323h33.711c0.84621 0 1.5323 0.68578 1.5323 1.5323 0 0.84621-0.68613 1.5323-1.5323 1.5323zm-3.2617 0h-21.953l1.4715 26.674c0.05985 1.0829 0.95531 1.9305 2.0403 1.9305h14.929c1.085 0 1.9804-0.84757 2.0403-1.9305zm-10.977 3.0647c0.78977 0 1.4301 0.6403 1.4301 1.4301v19.614c0 0.78977-0.6403 1.4301-1.4301 1.4301s-1.4301-0.6403-1.4301-1.4301v-19.614c0-0.78977 0.6403-1.4301 1.4301-1.4301zm-6.1293 0c0.80004 0 1.4588 0.62935 1.495 1.4286l0.89647 19.719c0.03182 0.70016-0.50998 1.2933-1.2101 1.3255-0.01915 7.02e-4 -0.03831 1e-3 -0.05781 1e-3 -0.74462 0-1.3596-0.58215-1.4003-1.3261l-1.0757-19.719c-0.0407-0.74701 0.53188-1.3852 1.2786-1.4259 0.02462-0.0014 0.04926-2e-3 0.07388-2e-3zm12.259 0c0.74804 0 1.3541 0.60609 1.3541 1.3541 0 0.02462-3.28e-4 0.04926-0.0017 0.07388l-1.0703 19.618c-0.04379 0.80106-0.70597 1.4281-1.5081 1.4281-0.74804 0-1.3541-0.60609-1.3541-1.3541 0-0.02462 3.49e-4 -0.04925 0.0017-0.07388l1.0703-19.618c0.04379-0.80106 0.70597-1.4281 1.5081-1.4281zm-10.216-12.259h8.1728c2.2567 0 4.086 1.8293 4.086 4.086v2.0433h-16.344v-2.0433c0-2.2567 1.8293-4.086 4.086-4.086zm0.20453 3.0647c-0.67725 0-1.2259 0.54863-1.2259 1.2259v1.8388h10.215v-1.8388c0-0.67725-0.54863-1.2259-1.2259-1.2259z" fill="#fff" fill-rule="evenodd" stroke="#bd4812" stroke-width=".75383"/></svg>
diff --git a/icons/button_resume_game.svg b/icons/button_resume_game.svg
deleted file mode 100644
index 6ad8b64202d0e70f898c16c520e756fe8a934add..0000000000000000000000000000000000000000
--- a/icons/button_resume_game.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 93.665 93.676" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x=".44662" y=".89101" width="92.772" height="91.894" ry="11.689" fill="#49a1ee" stroke="#fff" stroke-width=".238"/><path d="m39.211 31.236c-0.84086-0.84489-2.9911-0.84489-2.9911 0v34.329c0 0.84594 2.1554 0.84594 2.9993 0l28.178-15.637c0.84392-0.84086 0.85812-2.2091 0.01623-3.053z" fill="#fefeff" stroke="#105ca1" stroke-linecap="round" stroke-linejoin="round" stroke-width="6.1726"/><path d="m40.355 33.714c-0.71948-0.72294-2.5594-0.72294-2.5594 0v29.373c0 0.72383 1.8442 0.72383 2.5663 0l24.11-13.38c0.7221-0.71948 0.73426-1.8902 0.01389-2.6124z" fill="#fefeff" stroke="#feffff" stroke-linecap="round" stroke-linejoin="round" stroke-width="3.225"/><path d="m28.369 66.919v-37.591" fill="#105ca2" stroke="#105ca2" stroke-linecap="round" stroke-width="4.0337"/></svg>
diff --git a/icons/game_fail.svg b/icons/game_fail.svg
deleted file mode 100644
index 2922fd7adc2bd2e813836c728f095376c73d4143..0000000000000000000000000000000000000000
--- a/icons/game_fail.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 93.665 93.676" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x=".44662" y=".89101" width="92.772" height="91.894" ry="11.689" fill="#d11717" stroke="#fff" stroke-width=".238"/><path d="m71.624 59.304c3.5089 3.5089 3.5089 9.0561 0 12.565-1.6976 1.6976-3.9623 2.6034-6.2261 2.6034s-4.5275-0.90569-6.2261-2.6034l-12.452-12.452-12.452 12.452c-1.6976 1.6976-3.9623 2.6034-6.2261 2.6034s-4.5275-0.90569-6.2261-2.6034c-3.5089-3.5089-3.5089-9.0561 0-12.565l12.452-12.452-12.452-12.452c-3.5089-3.5089-3.5089-9.0561 0-12.565s9.0561-3.5089 12.565 0l12.452 12.452 12.452-12.452c3.5089-3.5089 9.0561-3.5089 12.565 0s3.5089 9.0561 0 12.565l-12.452 12.452z" fill="#e7e7e7" stroke-width=".20213"/></svg>
diff --git a/icons/layout_diamond.svg b/icons/layout_diamond.svg
deleted file mode 100644
index 31d08b4ff97e2030eabc1e993e33647cda998c63..0000000000000000000000000000000000000000
--- a/icons/layout_diamond.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 102 102" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x="1" y="1" width="100" height="100" ry="0" fill="#6ade70" stroke="#000" stroke-width="2"/><g transform="matrix(.8379 0 0 .8379 -396.44 -4.3017)"><g transform="translate(180 48)"><rect x="300" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(228 96)"><rect x="300" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(228 3.624e-5)"><rect x="300" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(276 48)"><rect x="300" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(276 72)"><rect x="276" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(228 72)"><rect x="276" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(228 24)"><rect x="276" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(276 24)"><rect x="276" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(240 60)"><rect x="276" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(240 60)"><rect x="288" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(240 60)"><rect x="300" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(192 48)"><rect x="300" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(192 48)"><rect x="300" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(192 36)"><rect x="300" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(204 48)"><rect x="300" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(204 48)"><rect x="300" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(204 36)"><rect x="300" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(276 48)"><rect x="276" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(276 48)"><rect x="288" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(276 48)"><rect x="276" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(276 48)"><rect x="288" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(276 36)"><rect x="276" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(276 36)"><rect x="288" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(240 48)"><rect x="276" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(240 48)"><rect x="288" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(240 48)"><rect x="300" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(240 48)"><rect x="276" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><rect x="528" y="60" width="12" height="12" fill="#babdb6" stroke="#000"/><g transform="translate(240 48)"><rect x="300" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(240 48)"><rect x="276" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(240 48)"><rect x="288" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(240 48)"><rect x="300" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(240 12)"><rect x="276" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(240 12)"><rect x="288" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(240 12)"><rect x="300" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(240 12)"><rect x="276" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(240 12)"><rect x="288" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(240 12)"><rect x="300" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(240 12)"><rect x="276" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(240 12)"><rect x="288" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(240 12)"><rect x="300" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g></g></svg>
diff --git a/icons/layout_english.svg b/icons/layout_english.svg
deleted file mode 100644
index c819ca663895daf475c3f9b5a16857ed11ead466..0000000000000000000000000000000000000000
--- a/icons/layout_english.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 102 102" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x="1" y="1" width="100" height="100" ry="0" fill="#6ade70" stroke="#000" stroke-width="2"/><g transform="translate(-363 -3)"><g transform="translate(120 48)"><rect x="276" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(120 48)"><rect x="288" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(120 48)"><rect x="300" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(72 36)"><rect x="300" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(72 36)"><rect x="300" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(72 24)"><rect x="300" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(84 36)"><rect x="300" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(84 36)"><rect x="300" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(84 24)"><rect x="300" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(156 36)"><rect x="276" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(156 36)"><rect x="288" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(156 36)"><rect x="276" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(156 36)"><rect x="288" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(156 24)"><rect x="276" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(156 24)"><rect x="288" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(120 36)"><rect x="276" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(120 36)"><rect x="288" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(120 36)"><rect x="300" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(120 36)"><rect x="276" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><rect x="408" y="48" width="12" height="12" fill="#babdb6" stroke="#000"/><g transform="translate(120 36)"><rect x="300" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(120 36)"><rect x="276" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(120 36)"><rect x="288" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(120 36)"><rect x="300" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(86.461 -21.272)"><g transform="translate(33.539 21.272)"><rect x="276" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(33.539 21.272)"><rect x="288" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(33.539 21.272)"><rect x="300" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(33.539 21.272)"><rect x="276" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(33.539 21.272)"><rect x="288" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(33.539 21.272)"><rect x="300" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(33.539 21.272)"><rect x="276" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(33.539 21.272)"><rect x="288" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(33.539 21.272)"><rect x="300" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g></g></g></svg>
diff --git a/icons/layout_french.svg b/icons/layout_french.svg
deleted file mode 100644
index 1ff5efe0fe2c5bd4dccca0ab48ff15e650ca23d3..0000000000000000000000000000000000000000
--- a/icons/layout_french.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 102 102" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x="1" y="1" width="100" height="100" ry="0" fill="#6ade70" stroke="#000" stroke-width="2"/><g transform="translate(-3 -15)"><g transform="translate(-204 72)"><rect x="276" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-252 72)"><rect x="276" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-252 24)"><rect x="276" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-204 24)"><rect x="276" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-240 60)"><rect x="276" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-240 60)"><rect x="288" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-240 60)"><rect x="300" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-288 48)"><rect x="300" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-288 48)"><rect x="300" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-288 36)"><rect x="300" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-276 48)"><rect x="300" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-276 48)"><rect x="300" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-276 36)"><rect x="300" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-204 48)"><rect x="276" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-204 48)"><rect x="288" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-204 48)"><rect x="276" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-204 48)"><rect x="288" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-204 36)"><rect x="276" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-204 36)"><rect x="288" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-240 48)"><rect x="276" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-240 48)"><rect x="288" y="24" width="12" height="12" fill="#babdb6" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-240 48)"><rect x="300" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-240 48)"><rect x="276" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-240 48)"><rect x="300" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-240 48)"><rect x="276" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-240 48)"><rect x="288" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-240 48)"><rect x="300" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-240 12)"><rect x="276" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-240 12)"><rect x="288" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-240 12)"><rect x="300" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-240 12)"><rect x="276" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-240 12)"><rect x="288" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-240 12)"><rect x="300" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-240 12)"><rect x="276" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><rect x="48" y="48" width="12" height="12" fill="#fff" stroke="#000"/><rect x="48" y="60" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 -100.3 35.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/><g transform="translate(-240 12)"><rect x="300" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g></g></svg>
diff --git a/icons/layout_german.svg b/icons/layout_german.svg
deleted file mode 100644
index e8266691daa33fd1a19d35cbab1ff6d6993dfd48..0000000000000000000000000000000000000000
--- a/icons/layout_german.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 102 102" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x="1" y="1" width="100" height="100" ry="0" fill="#6ade70" stroke="#000" stroke-width="2"/><g transform="matrix(.84066 0 0 .84066 -95.275 -4.4834)"><g transform="translate(-168 36)"><rect x="288" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-168 36)"><rect x="288" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-168 36)"><rect x="288" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 72)"><rect x="276" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 72)"><rect x="288" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 72)"><rect x="300" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 72)"><rect x="276" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 72)"><rect x="288" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 72)"><rect x="300" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 72)"><rect x="276" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 72)"><rect x="288" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 72)"><rect x="300" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 3.0518e-5)"><rect x="276" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 3.0518e-5)"><rect x="288" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 3.0518e-5)"><rect x="300" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 3.0518e-5)"><rect x="276" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 3.0518e-5)"><rect x="288" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 3.0518e-5)"><rect x="300" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 3.0518e-5)"><rect x="276" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 3.0518e-5)"><rect x="288" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 3.0518e-5)"><rect x="300" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-156 36)"><rect x="288" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-156 36)"><rect x="300" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-156 36)"><rect x="288" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-156 36)"><rect x="300" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-156 36)"><rect x="288" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-156 36)"><rect x="300" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 36)"><rect x="276" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><rect x="168" y="60" width="12" height="12" fill="#babdb6" stroke="#000"/><g transform="translate(-120 36)"><rect x="300" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 36)"><rect x="276" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 36)"><rect x="288" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 36)"><rect x="300" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 36)"><rect x="276" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 36)"><rect x="288" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-120 36)"><rect x="300" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-84 36)"><rect x="276" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-84 36)"><rect x="288" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-84 36)"><rect x="300" y="24" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -.3088)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-84 36)"><rect x="276" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-84 36)"><rect x="288" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-84 36)"><rect x="300" y="12" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 -12.309)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-84 36)"><rect x="276" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 127.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-84 36)"><rect x="288" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 139.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g><g transform="translate(-84 36)"><rect x="300" y="36" width="12" height="12" fill="#fff" stroke="#000"/><circle transform="matrix(.5381 0 0 .5381 151.7 11.691)" cx="286.74" cy="56.325" r="7.4335" fill="#c17d11"/></g></g></svg>
diff --git a/icons/skin_default.svg b/icons/skin_default.svg
deleted file mode 100644
index f7344d57776c1eb3ca5699290db81c999f83cc0a..0000000000000000000000000000000000000000
--- a/icons/skin_default.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 102 102" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x="1" y="1" width="100" height="100" ry="0" fill="#be6ade" stroke="#000" stroke-width="2"/></svg>
diff --git a/lib/config/default_game_settings.dart b/lib/config/default_game_settings.dart
new file mode 100644
index 0000000000000000000000000000000000000000..6ac27dcf613094e37f638ebe8d69573e4219deca
--- /dev/null
+++ b/lib/config/default_game_settings.dart
@@ -0,0 +1,33 @@
+import 'package:solitaire/utils/tools.dart';
+
+class DefaultGameSettings {
+  // available game parameters codes
+  static const String parameterCodeLayout = 'layout';
+  static const List<String> availableParameters = [
+    parameterCodeLayout,
+  ];
+
+  // layout: available values
+  static const String layoutValueFrench = 'french';
+  static const String layoutValueGerman = 'german';
+  static const String layoutValueEnglish = 'english';
+  static const String layoutValueDiamond = 'diamond';
+  static const List<String> allowedLayoutValues = [
+    layoutValueFrench,
+    layoutValueGerman,
+    layoutValueEnglish,
+    layoutValueDiamond,
+  ];
+  // layout: default value
+  static const String defaultLayoutValue = layoutValueEnglish;
+
+  static List<String> getAvailableValues(String parameterCode) {
+    switch (parameterCode) {
+      case parameterCodeLayout:
+        return DefaultGameSettings.allowedLayoutValues;
+    }
+
+    printlog('Did not find any available value for game parameter "$parameterCode".');
+    return [];
+  }
+}
diff --git a/lib/config/default_global_settings.dart b/lib/config/default_global_settings.dart
new file mode 100644
index 0000000000000000000000000000000000000000..622a8b66d293815ec6ce9d50f7cefd9701606f1d
--- /dev/null
+++ b/lib/config/default_global_settings.dart
@@ -0,0 +1,27 @@
+import 'package:solitaire/utils/tools.dart';
+
+class DefaultGlobalSettings {
+  // available global parameters codes
+  static const String parameterCodeSkin = 'skin';
+  static const List<String> availableParameters = [
+    parameterCodeSkin,
+  ];
+
+  // skin: available values
+  static const String skinValueDefault = 'default';
+  static const List<String> allowedSkinValues = [
+    skinValueDefault,
+  ];
+  // skin: default value
+  static const String defaultSkinValue = skinValueDefault;
+
+  static List<String> getAvailableValues(String parameterCode) {
+    switch (parameterCode) {
+      case parameterCodeSkin:
+        return DefaultGlobalSettings.allowedSkinValues;
+    }
+
+    printlog('Did not find any available value for global parameter "$parameterCode".');
+    return [];
+  }
+}
diff --git a/lib/config/menu.dart b/lib/config/menu.dart
index ca5d227fee343cb63c211fd9904fd9d1a48477b1..3d2fcfacf3e2ca175870530e2f4e33f74264bb79 100644
--- a/lib/config/menu.dart
+++ b/lib/config/menu.dart
@@ -1,10 +1,9 @@
-import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/material.dart';
 import 'package:unicons/unicons.dart';
 
-import 'package:solitaire/ui/screens/about_page.dart';
-import 'package:solitaire/ui/screens/game_page.dart';
-import 'package:solitaire/ui/screens/settings_page.dart';
+import 'package:solitaire/ui/screens/page_about.dart';
+import 'package:solitaire/ui/screens/page_game.dart';
+import 'package:solitaire/ui/screens/page_settings.dart';
 
 class MenuItem {
   final String code;
@@ -19,35 +18,39 @@ class MenuItem {
 }
 
 class Menu {
-  static List<MenuItem> items = [
-    const MenuItem(
-      code: 'bottom_nav_home',
-      icon: Icon(UniconsLine.home),
-      page: GamePage(),
-    ),
-    const MenuItem(
-      code: 'bottom_nav_settings',
-      icon: Icon(UniconsLine.setting),
-      page: SettingsPage(),
-    ),
-    const MenuItem(
-      code: 'bottom_nav_about',
-      icon: Icon(UniconsLine.info_circle),
-      page: AboutPage(),
-    ),
-  ];
+  static const indexGame = 0;
+  static const menuItemGame = MenuItem(
+    code: 'bottom_nav_game',
+    icon: Icon(UniconsLine.home),
+    page: PageGame(),
+  );
 
-  static Widget getPageWidget(int pageIndex) {
-    return Menu.items.elementAt(pageIndex).page;
+  static const indexSettings = 1;
+  static const menuItemSettings = MenuItem(
+    code: 'bottom_nav_settings',
+    icon: Icon(UniconsLine.setting),
+    page: PageSettings(),
+  );
+
+  static const indexAbout = 2;
+  static const menuItemAbout = MenuItem(
+    code: 'bottom_nav_about',
+    icon: Icon(UniconsLine.info_circle),
+    page: PageAbout(),
+  );
+
+  static Map<int, MenuItem> items = {
+    indexGame: menuItemGame,
+    indexSettings: menuItemSettings,
+    indexAbout: menuItemAbout,
+  };
+
+  static bool isIndexAllowed(int pageIndex) {
+    return items.keys.contains(pageIndex);
   }
 
-  static List<BottomNavigationBarItem> getMenuItems() {
-    return Menu.items
-        .map((MenuItem item) => BottomNavigationBarItem(
-              icon: item.icon,
-              label: tr(item.code),
-            ))
-        .toList();
+  static Widget getPageWidget(int pageIndex) {
+    return items[pageIndex]?.page ?? menuItemGame.page;
   }
 
   static int itemsCount = Menu.items.length;
diff --git a/lib/cubit/game_cubit.dart b/lib/cubit/game_cubit.dart
new file mode 100644
index 0000000000000000000000000000000000000000..aba2472b6c5e923a383e4da46abd8a1611a43e88
--- /dev/null
+++ b/lib/cubit/game_cubit.dart
@@ -0,0 +1,127 @@
+import 'package:equatable/equatable.dart';
+import 'package:flutter/material.dart';
+import 'package:hydrated_bloc/hydrated_bloc.dart';
+
+import 'package:solitaire/models/cell_location.dart';
+import 'package:solitaire/models/game.dart';
+import 'package:solitaire/models/settings_game.dart';
+import 'package:solitaire/models/settings_global.dart';
+import 'package:solitaire/utils/tools.dart';
+
+part 'game_state.dart';
+
+class GameCubit extends HydratedCubit<GameState> {
+  GameCubit()
+      : super(GameState(
+          currentGame: Game.createNull(),
+        ));
+
+  void updateState(Game game) {
+    emit(GameState(
+      currentGame: game,
+    ));
+  }
+
+  void refresh() {
+    final Game game = Game(
+      gameSettings: state.currentGame.gameSettings,
+      globalSettings: state.currentGame.globalSettings,
+      board: state.currentGame.board,
+      isRunning: state.currentGame.isRunning,
+      isFinished: state.currentGame.isFinished,
+      movesCount: state.currentGame.movesCount,
+      remainingPegsCount: state.currentGame.remainingPegsCount,
+      allowedMovesCount: state.currentGame.allowedMovesCount,
+    );
+    // game.dump();
+
+    updateState(game);
+  }
+
+  void startNewGame({
+    required GameSettings gameSettings,
+    required GlobalSettings globalSettings,
+  }) {
+    Game newGame = Game.createNew(
+      gameSettings: gameSettings,
+      globalSettings: globalSettings,
+    );
+
+    newGame.dump();
+
+    updateState(newGame);
+
+    updateRemainingPegsCount(newGame.countRemainingPegs());
+    updateAllowedMovesCount(newGame.countAllowedMoves());
+
+    refresh();
+  }
+
+  void quitGame() {
+    state.currentGame.isRunning = false;
+    refresh();
+  }
+
+  void updatePegValue(CellLocation location, bool hasPeg) {
+    state.currentGame.board.cells[location.row][location.col].hasPeg = hasPeg;
+    refresh();
+  }
+
+  void incrementMovesCount() {
+    state.currentGame.movesCount++;
+    refresh();
+  }
+
+  void updateRemainingPegsCount(int count) {
+    state.currentGame.remainingPegsCount = count;
+    refresh();
+  }
+
+  void updateAllowedMovesCount(int count) {
+    state.currentGame.allowedMovesCount = count;
+    if (count == 0) {
+      state.currentGame.isFinished = true;
+    }
+
+    refresh();
+  }
+
+  void move({
+    required Game currentGame,
+    required List<int> source,
+    required List<int> target,
+  }) {
+    printlog('Move from $source to $target');
+    final int sourceCol = source[0];
+    final int sourceRow = source[1];
+    final int targetCol = target[0];
+    final int targetRow = target[1];
+
+    final int middleRow = (sourceRow + ((targetRow - sourceRow) / 2)).round();
+    final int middleCol = (sourceCol + ((targetCol - sourceCol) / 2)).round();
+
+    updatePegValue(CellLocation.go(sourceRow, sourceCol), false);
+    updatePegValue(CellLocation.go(targetRow, targetCol), true);
+    updatePegValue(CellLocation.go(middleRow, middleCol), false);
+
+    incrementMovesCount();
+    updateRemainingPegsCount(currentGame.countRemainingPegs());
+    updateAllowedMovesCount(currentGame.countAllowedMoves());
+  }
+
+  @override
+  GameState? fromJson(Map<String, dynamic> json) {
+    Game currentGame = json['currentGame'] as Game;
+
+    return GameState(
+      currentGame: currentGame,
+    );
+  }
+
+  @override
+  Map<String, dynamic>? toJson(GameState state) {
+    return <String, dynamic>{
+      'currentGame': state.currentGame.toJson(),
+    };
+  }
+}
diff --git a/lib/cubit/game_state.dart b/lib/cubit/game_state.dart
new file mode 100644
index 0000000000000000000000000000000000000000..3fd161a0915313722b7a15c55c7cf538a7e3b6e1
--- /dev/null
+++ b/lib/cubit/game_state.dart
@@ -0,0 +1,19 @@
+part of 'game_cubit.dart';
+
+@immutable
+class GameState extends Equatable {
+  const GameState({
+    required this.currentGame,
+  });
+
+  final Game currentGame;
+
+  @override
+  List<dynamic> get props => <dynamic>[
+        currentGame,
+      ];
+
+  Map<String, dynamic> get values => <String, dynamic>{
+        'currentGame': currentGame,
+      };
+}
diff --git a/lib/cubit/bottom_nav_cubit.dart b/lib/cubit/nav_cubit.dart
similarity index 51%
rename from lib/cubit/bottom_nav_cubit.dart
rename to lib/cubit/nav_cubit.dart
index 8f04dffa9682eb52139e44fcb2ab9a4d75a613a8..9d4541c6273c625de7e6b7eadf4efd170223879f 100644
--- a/lib/cubit/bottom_nav_cubit.dart
+++ b/lib/cubit/nav_cubit.dart
@@ -2,26 +2,32 @@ import 'package:hydrated_bloc/hydrated_bloc.dart';
 
 import 'package:solitaire/config/menu.dart';
 
-class BottomNavCubit extends HydratedCubit<int> {
-  BottomNavCubit() : super(0);
+class NavCubit extends HydratedCubit<int> {
+  NavCubit() : super(0);
 
   void updateIndex(int index) {
-    if (isIndexAllowed(index)) {
+    if (Menu.isIndexAllowed(index)) {
       emit(index);
     } else {
-      goToHomePage();
+      goToGamePage();
     }
   }
 
-  bool isIndexAllowed(int index) {
-    return (index >= 0) && (index < Menu.itemsCount);
+  void goToGamePage() {
+    emit(Menu.indexGame);
   }
 
-  void goToHomePage() => emit(0);
+  void goToSettingsPage() {
+    emit(Menu.indexSettings);
+  }
+
+  void goToAboutPage() {
+    emit(Menu.indexAbout);
+  }
 
   @override
   int fromJson(Map<String, dynamic> json) {
-    return 0;
+    return Menu.indexGame;
   }
 
   @override
diff --git a/lib/cubit/settings_game_cubit.dart b/lib/cubit/settings_game_cubit.dart
new file mode 100644
index 0000000000000000000000000000000000000000..7399314684c139542eb3559b67e6dceeb9641bde
--- /dev/null
+++ b/lib/cubit/settings_game_cubit.dart
@@ -0,0 +1,64 @@
+import 'package:equatable/equatable.dart';
+import 'package:flutter/material.dart';
+import 'package:hydrated_bloc/hydrated_bloc.dart';
+
+import 'package:solitaire/config/default_game_settings.dart';
+import 'package:solitaire/models/settings_game.dart';
+import 'package:solitaire/utils/tools.dart';
+
+part 'settings_game_state.dart';
+
+class GameSettingsCubit extends HydratedCubit<GameSettingsState> {
+  GameSettingsCubit() : super(GameSettingsState(settings: GameSettings.createDefault()));
+
+  void setValues({
+    String? layout,
+  }) {
+    emit(
+      GameSettingsState(
+        settings: GameSettings(
+          layout: layout ?? state.settings.layout,
+        ),
+      ),
+    );
+  }
+
+  String getParameterValue(String code) {
+    switch (code) {
+      case DefaultGameSettings.parameterCodeLayout:
+        return GameSettings.getLayoutValueFromUnsafe(state.settings.layout);
+    }
+    return '';
+  }
+
+  void setParameterValue(String code, String value) {
+    printlog('GameSettingsCubit.setParameterValue');
+    printlog('code: $code  / value: $value');
+
+    String layout = code == DefaultGameSettings.parameterCodeLayout
+        ? value
+        : getParameterValue(DefaultGameSettings.parameterCodeLayout);
+
+    setValues(
+      layout: layout,
+    );
+  }
+
+  @override
+  GameSettingsState? fromJson(Map<String, dynamic> json) {
+    String layout = json[DefaultGameSettings.parameterCodeLayout] as String;
+
+    return GameSettingsState(
+      settings: GameSettings(
+        layout: layout,
+      ),
+    );
+  }
+
+  @override
+  Map<String, dynamic>? toJson(GameSettingsState state) {
+    return <String, dynamic>{
+      DefaultGameSettings.parameterCodeLayout: state.settings.layout,
+    };
+  }
+}
diff --git a/lib/cubit/settings_game_state.dart b/lib/cubit/settings_game_state.dart
new file mode 100644
index 0000000000000000000000000000000000000000..b773dc69be12673b158e880e2d7e6e7bec465506
--- /dev/null
+++ b/lib/cubit/settings_game_state.dart
@@ -0,0 +1,19 @@
+part of 'settings_game_cubit.dart';
+
+@immutable
+class GameSettingsState extends Equatable {
+  const GameSettingsState({
+    required this.settings,
+  });
+
+  final GameSettings settings;
+
+  @override
+  List<dynamic> get props => <dynamic>[
+        settings,
+      ];
+
+  Map<String, dynamic> get values => <String, dynamic>{
+        'settings': settings,
+      };
+}
diff --git a/lib/cubit/settings_global_cubit.dart b/lib/cubit/settings_global_cubit.dart
new file mode 100644
index 0000000000000000000000000000000000000000..274c113cff2bfa94e9e3ea492e9359ca11d149ca
--- /dev/null
+++ b/lib/cubit/settings_global_cubit.dart
@@ -0,0 +1,60 @@
+import 'package:equatable/equatable.dart';
+import 'package:flutter/material.dart';
+import 'package:hydrated_bloc/hydrated_bloc.dart';
+
+import 'package:solitaire/config/default_global_settings.dart';
+import 'package:solitaire/models/settings_global.dart';
+
+part 'settings_global_state.dart';
+
+class GlobalSettingsCubit extends HydratedCubit<GlobalSettingsState> {
+  GlobalSettingsCubit() : super(GlobalSettingsState(settings: GlobalSettings.createDefault()));
+
+  void setValues({
+    String? skin,
+  }) {
+    emit(
+      GlobalSettingsState(
+        settings: GlobalSettings(
+          skin: skin ?? state.settings.skin,
+        ),
+      ),
+    );
+  }
+
+  String getParameterValue(String code) {
+    switch (code) {
+      case DefaultGlobalSettings.parameterCodeSkin:
+        return GlobalSettings.getSkinValueFromUnsafe(state.settings.skin);
+    }
+    return '';
+  }
+
+  void setParameterValue(String code, String value) {
+    final String skin = (code == DefaultGlobalSettings.parameterCodeSkin)
+        ? value
+        : getParameterValue(DefaultGlobalSettings.parameterCodeSkin);
+
+    setValues(
+      skin: skin,
+    );
+  }
+
+  @override
+  GlobalSettingsState? fromJson(Map<String, dynamic> json) {
+    final String skin = json[DefaultGlobalSettings.parameterCodeSkin] as String;
+
+    return GlobalSettingsState(
+      settings: GlobalSettings(
+        skin: skin,
+      ),
+    );
+  }
+
+  @override
+  Map<String, dynamic>? toJson(GlobalSettingsState state) {
+    return <String, dynamic>{
+      DefaultGlobalSettings.parameterCodeSkin: state.settings.skin,
+    };
+  }
+}
diff --git a/lib/cubit/settings_global_state.dart b/lib/cubit/settings_global_state.dart
new file mode 100644
index 0000000000000000000000000000000000000000..4e4fbdf707b4e805f2092d0ca6a68a2de1c957c6
--- /dev/null
+++ b/lib/cubit/settings_global_state.dart
@@ -0,0 +1,19 @@
+part of 'settings_global_cubit.dart';
+
+@immutable
+class GlobalSettingsState extends Equatable {
+  const GlobalSettingsState({
+    required this.settings,
+  });
+
+  final GlobalSettings settings;
+
+  @override
+  List<dynamic> get props => <dynamic>[
+        settings,
+      ];
+
+  Map<String, dynamic> get values => <String, dynamic>{
+        'settings': settings,
+      };
+}
diff --git a/lib/data/game_data.dart b/lib/data/game_data.dart
new file mode 100644
index 0000000000000000000000000000000000000000..711256b874d00c3facc3eb99eb79a80d78bba2bc
--- /dev/null
+++ b/lib/data/game_data.dart
@@ -0,0 +1,44 @@
+class GameData {
+  static const Map<String, List<String>> templates = {
+    'french': [
+      '  ooo  ',
+      ' ooooo ',
+      'ooo·ooo',
+      'ooooooo',
+      'ooooooo',
+      ' ooooo ',
+      '  ooo  ',
+    ],
+    'german': [
+      '   ooo   ',
+      '   ooo   ',
+      '   ooo   ',
+      'ooooooooo',
+      'oooo·oooo',
+      'ooooooooo',
+      '   ooo   ',
+      '   ooo   ',
+      '   ooo   ',
+    ],
+    'english': [
+      '  ooo  ',
+      '  ooo  ',
+      'ooooooo',
+      'ooo·ooo',
+      'ooooooo',
+      '  ooo  ',
+      '  ooo  ',
+    ],
+    'diamond': [
+      '    o    ',
+      '   ooo   ',
+      '  ooooo  ',
+      ' ooooooo ',
+      'oooo·oooo',
+      ' ooooooo ',
+      '  ooooo  ',
+      '   ooo   ',
+      '    o    ',
+    ]
+  };
+}
diff --git a/lib/entities/tile.dart b/lib/entities/tile.dart
deleted file mode 100644
index 5f88b97058b643f3b357bd60efdfc7bca2fe0e26..0000000000000000000000000000000000000000
--- a/lib/entities/tile.dart
+++ /dev/null
@@ -1,82 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:solitaire/provider/data.dart';
-import 'package:solitaire/utils/game_utils.dart';
-
-class Tile {
-  int currentRow;
-  int currentCol;
-  bool hasPeg;
-
-  Tile(
-    this.currentRow,
-    this.currentCol,
-    this.hasPeg,
-  );
-
-  Widget render(Data myProvider) {
-    List<Widget> stack = [
-      hole(myProvider),
-    ];
-
-    if (hasPeg) {
-      stack.add(draggable(myProvider));
-    }
-
-    return Stack(
-      alignment: Alignment.center,
-      children: stack,
-    );
-  }
-
-  Widget hole(Data myProvider) {
-    String image = 'assets/skins/${myProvider.parameterSkin}_hole.png';
-
-    return DragTarget<List<int>>(
-      builder: (
-        BuildContext context,
-        List<dynamic> accepted,
-        List<dynamic> rejected,
-      ) {
-        return Image(
-          image: AssetImage(image),
-          width: myProvider.tileSize,
-          height: myProvider.tileSize,
-          fit: BoxFit.fill,
-        );
-      },
-      onAcceptWithDetails: (DragTargetDetails<List<int>> source) {
-        List<int> target = [currentCol, currentRow];
-        // printlog('(drag) Pick from ' + source.toString() + ' and drop on ' + target.toString());
-        if (GameUtils.isMoveAllowed(myProvider, source.data, target)) {
-          GameUtils.move(myProvider, source.data, target);
-        }
-      },
-    );
-  }
-
-  Widget draggable(Data myProvider) {
-    return Draggable<List<int>>(
-      data: [currentCol, currentRow],
-
-      // Widget when draggable is being dragged
-      feedback: peg(myProvider),
-
-      // Widget to display on original place when being dragged
-      childWhenDragging: Container(),
-
-      // Widget when draggable is stationary
-      child: peg(myProvider),
-    );
-  }
-
-  Widget peg(Data myProvider) {
-    String image = 'assets/skins/${myProvider.parameterSkin}_peg.png';
-
-    return Image(
-      image: AssetImage(image),
-      width: myProvider.tileSize,
-      height: myProvider.tileSize,
-      fit: BoxFit.fill,
-    );
-  }
-}
diff --git a/lib/main.dart b/lib/main.dart
index e84151f467ffe84165623e79580b02b340e2aa35..d507c2d5d0495158dbf6f02d6a0fb3ba4a6faaa8 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -6,17 +6,17 @@ import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:hive/hive.dart';
 import 'package:hydrated_bloc/hydrated_bloc.dart';
 import 'package:path_provider/path_provider.dart';
-import 'package:provider/provider.dart';
-import 'package:overlay_support/overlay_support.dart';
 
 import 'package:solitaire/config/theme.dart';
-import 'package:solitaire/cubit/bottom_nav_cubit.dart';
+import 'package:solitaire/cubit/game_cubit.dart';
+import 'package:solitaire/cubit/nav_cubit.dart';
+import 'package:solitaire/cubit/settings_game_cubit.dart';
+import 'package:solitaire/cubit/settings_global_cubit.dart';
 import 'package:solitaire/cubit/theme_cubit.dart';
-import 'package:solitaire/provider/data.dart';
 import 'package:solitaire/ui/skeleton.dart';
 
 void main() async {
-  /// Initialize packages
+  // Initialize packages
   WidgetsFlutterBinding.ensureInitialized();
   await EasyLocalization.ensureInitialized();
   final Directory tmpDir = await getTemporaryDirectory();
@@ -46,34 +46,28 @@ class MyApp extends StatelessWidget {
   Widget build(BuildContext context) {
     return MultiBlocProvider(
       providers: [
-        BlocProvider<BottomNavCubit>(create: (context) => BottomNavCubit()),
+        BlocProvider<NavCubit>(create: (context) => NavCubit()),
         BlocProvider<ThemeCubit>(create: (context) => ThemeCubit()),
+        BlocProvider<GameCubit>(create: (context) => GameCubit()),
+        BlocProvider<GlobalSettingsCubit>(create: (context) => GlobalSettingsCubit()),
+        BlocProvider<GameSettingsCubit>(create: (context) => GameSettingsCubit()),
       ],
       child: BlocBuilder<ThemeCubit, ThemeModeState>(
         builder: (BuildContext context, ThemeModeState state) {
-          return ChangeNotifierProvider(
-            create: (BuildContext context) => Data(),
-            child: Consumer<Data>(
-              builder: (context, data, child) {
-                return OverlaySupport(
-                  child: MaterialApp(
-                    title: 'Solitaire',
-                    home: const SkeletonScreen(),
+          return MaterialApp(
+            title: 'Solitaire',
+            home: const SkeletonScreen(),
 
-                    // Theme stuff
-                    theme: lightTheme,
-                    darkTheme: darkTheme,
-                    themeMode: state.themeMode,
+            // Theme stuff
+            theme: lightTheme,
+            darkTheme: darkTheme,
+            themeMode: state.themeMode,
 
-                    // Localization stuff
-                    localizationsDelegates: context.localizationDelegates,
-                    supportedLocales: context.supportedLocales,
-                    locale: context.locale,
-                    debugShowCheckedModeBanner: false,
-                  ),
-                );
-              },
-            ),
+            // Localization stuff
+            localizationsDelegates: context.localizationDelegates,
+            supportedLocales: context.supportedLocales,
+            locale: context.locale,
+            debugShowCheckedModeBanner: false,
           );
         },
       ),
diff --git a/lib/models/board.dart b/lib/models/board.dart
new file mode 100644
index 0000000000000000000000000000000000000000..eb1ce73259a307e58116df681052bb81b551d6b2
--- /dev/null
+++ b/lib/models/board.dart
@@ -0,0 +1,169 @@
+import 'package:solitaire/data/game_data.dart';
+import 'package:solitaire/models/cell.dart';
+import 'package:solitaire/models/cell_location.dart';
+import 'package:solitaire/models/settings_game.dart';
+import 'package:solitaire/utils/tools.dart';
+
+typedef BoardCells = List<List<Cell>>;
+
+class Board {
+  Board({
+    required this.cells,
+  });
+
+  BoardCells cells = const [];
+
+  factory Board.createEmpty() {
+    return Board(
+      cells: [],
+    );
+  }
+
+  factory Board.createNew({
+    required GameSettings gameSettings,
+  }) {
+    final List<String>? template = GameData.templates[gameSettings.layout];
+
+    final BoardCells grid = [];
+
+    int row = 0;
+    template?.forEach((String line) {
+      final List<Cell> gridLine = [];
+      int col = 0;
+      line.split("").forEach((String tileCode) {
+        gridLine.add(tileCode == ' '
+            ? Cell.none
+            : Cell(
+                location: CellLocation.go(row, col),
+                hasHole: true,
+                hasPeg: (tileCode == 'o'),
+              ));
+        col++;
+      });
+      row++;
+      grid.add(gridLine);
+    });
+
+    return Board(
+      cells: grid,
+    );
+  }
+
+  int get boardSize => cells.length;
+
+  Cell get(CellLocation location) {
+    if (location.row < cells.length) {
+      if (location.col < cells[location.row].length) {
+        return cells[location.row][location.col];
+      }
+    }
+
+    return Cell.none;
+  }
+
+  void set(CellLocation location, Cell cell) {
+    cells[location.row][location.col] = cell;
+  }
+
+  bool isMoveAllowed({
+    required List<int> source,
+    required List<int> target,
+  }) {
+    // printlog('(test) Pick from ' + source.toString() + ' and drop on ' + target.toString());
+    final int sourceCol = source[0];
+    final int sourceRow = source[1];
+    final int targetCol = target[0];
+    final int targetRow = target[1];
+
+    // ensure source and target are inside range
+    if (sourceRow < 0 ||
+        sourceRow > (boardSize - 1) ||
+        sourceCol < 0 ||
+        sourceCol > (boardSize - 1)) {
+      // printlog('move forbidden: source is out of board');
+      return false;
+    }
+    if (targetRow < 0 ||
+        targetRow > (boardSize - 1) ||
+        targetCol < 0 ||
+        targetCol > (boardSize - 1)) {
+      // printlog('move forbidden: target is out of board');
+      return false;
+    }
+
+    // ensure source exists and has a peg
+    if (cells[sourceRow][sourceCol].hasPeg == false) {
+      // printlog('move forbidden: source peg does not exist');
+      return false;
+    }
+
+    // ensure target exists and is empty
+    if (cells[targetRow][targetCol].hasPeg == true) {
+      // printlog('move forbidden: target does not exist or already with a peg');
+      return false;
+    }
+
+    // ensure source and target are in the same line/column
+    if ((targetCol != sourceCol) && (targetRow != sourceRow)) {
+      // printlog('move forbidden: source and target are not in the same line or column');
+      return false;
+    }
+
+    // ensure source and target are separated by exactly one tile
+    if (((targetCol == sourceCol) && ((targetRow - sourceRow).abs() != 2)) ||
+        ((targetRow == sourceRow) && ((targetCol - sourceCol).abs() != 2))) {
+      // printlog('move forbidden: source and target must be separated by exactly one tile');
+      return false;
+    }
+
+    // ensure middle tile exists and has a peg
+    final int middleRow = (sourceRow + ((targetRow - sourceRow) / 2)).round();
+    final int middleCol = (sourceCol + ((targetCol - sourceCol) / 2)).round();
+    if (cells[middleRow][middleCol].hasPeg == false) {
+      // printlog('move forbidden: tile between source and target does not contain a peg');
+      return false;
+    }
+
+    // ok, move is allowed
+    return true;
+  }
+
+  void printGrid() {
+    String textBoard = ' ';
+    String textHole = '·';
+    String textPeg = 'o';
+
+    printlog('');
+    printlog('-------');
+    for (int rowIndex = 0; rowIndex < cells.length; rowIndex++) {
+      String row = '';
+      for (int colIndex = 0; colIndex < cells[rowIndex].length; colIndex++) {
+        String textCell = textBoard;
+        Cell tile = cells[rowIndex][colIndex];
+        textCell = tile.hasPeg ? textPeg : textHole;
+        row += textCell;
+      }
+      printlog(row);
+    }
+    printlog('-------');
+    printlog('');
+  }
+
+  void dump() {
+    printlog('');
+    printlog('$Board:');
+    printGrid();
+    printlog('');
+  }
+
+  @override
+  String toString() {
+    return '$Board(${toJson()})';
+  }
+
+  Map<String, dynamic>? toJson() {
+    return <String, dynamic>{
+      'cells': cells,
+    };
+  }
+}
diff --git a/lib/models/cell.dart b/lib/models/cell.dart
new file mode 100644
index 0000000000000000000000000000000000000000..127c3006372ae606f25206aa7ef1209ec78a1ecc
--- /dev/null
+++ b/lib/models/cell.dart
@@ -0,0 +1,41 @@
+import 'package:solitaire/models/cell_location.dart';
+import 'package:solitaire/utils/tools.dart';
+
+class Cell {
+  Cell({
+    required this.location,
+    required this.hasHole,
+    required this.hasPeg,
+  });
+
+  final CellLocation location;
+  bool hasHole;
+  bool hasPeg;
+
+  static Cell none = Cell(
+    location: CellLocation.go(0, 0),
+    hasHole: false,
+    hasPeg: false,
+  );
+
+  void dump() {
+    printlog('$Cell:');
+    printlog('  location: $location');
+    printlog('  hasHole: $hasHole');
+    printlog('  hasPeg: $hasPeg');
+    printlog('');
+  }
+
+  @override
+  String toString() {
+    return '$Cell(${toJson()})';
+  }
+
+  Map<String, dynamic>? toJson() {
+    return <String, dynamic>{
+      'location': location,
+      'hasHole': hasHole,
+      'hasPeg': hasPeg,
+    };
+  }
+}
diff --git a/lib/models/cell_location.dart b/lib/models/cell_location.dart
new file mode 100644
index 0000000000000000000000000000000000000000..f9b90220feff4828ca6fa846d4933cac195608b2
--- /dev/null
+++ b/lib/models/cell_location.dart
@@ -0,0 +1,34 @@
+import 'package:solitaire/utils/tools.dart';
+
+class CellLocation {
+  final int col;
+  final int row;
+
+  CellLocation({
+    required this.col,
+    required this.row,
+  });
+
+  factory CellLocation.go(int row, int col) {
+    return CellLocation(col: col, row: row);
+  }
+
+  void dump() {
+    printlog('$CellLocation:');
+    printlog('  col: $col');
+    printlog('  row: $row');
+    printlog('');
+  }
+
+  @override
+  String toString() {
+    return '$CellLocation(${toJson()})';
+  }
+
+  Map<String, dynamic>? toJson() {
+    return <String, dynamic>{
+      'col': col,
+      'row': row,
+    };
+  }
+}
diff --git a/lib/models/game.dart b/lib/models/game.dart
new file mode 100644
index 0000000000000000000000000000000000000000..009ff4f3b07ce3370c5b6764f89e8c3f2256fea2
--- /dev/null
+++ b/lib/models/game.dart
@@ -0,0 +1,142 @@
+import 'package:solitaire/models/board.dart';
+import 'package:solitaire/models/cell.dart';
+import 'package:solitaire/models/settings_game.dart';
+import 'package:solitaire/models/settings_global.dart';
+import 'package:solitaire/utils/tools.dart';
+
+class Game {
+  Game({
+    required this.gameSettings,
+    required this.globalSettings,
+    required this.board,
+    this.isRunning = false,
+    this.isFinished = false,
+    this.movesCount = 0,
+    this.remainingPegsCount = 0,
+    this.allowedMovesCount = 0,
+  });
+
+  final GameSettings gameSettings;
+  final GlobalSettings globalSettings;
+
+  bool isRunning = false;
+  bool isFinished = false;
+
+  Board board;
+
+  int movesCount = 0;
+  int remainingPegsCount = 0;
+  int allowedMovesCount = 0;
+
+  factory Game.createNull() {
+    return Game(
+      gameSettings: GameSettings.createDefault(),
+      globalSettings: GlobalSettings.createDefault(),
+      board: Board.createEmpty(),
+    );
+  }
+
+  factory Game.createNew({
+    GameSettings? gameSettings,
+    GlobalSettings? globalSettings,
+  }) {
+    GameSettings newGameSettings = gameSettings ?? GameSettings.createDefault();
+    GlobalSettings newGlobalSettings = globalSettings ?? GlobalSettings.createDefault();
+
+    return Game(
+      gameSettings: newGameSettings,
+      globalSettings: newGlobalSettings,
+      board: Board.createNew(
+        gameSettings: newGameSettings,
+      ),
+      isRunning: true,
+    );
+  }
+
+  int get boardSize => board.boardSize;
+
+  bool get gameWon => (isFinished && (remainingPegsCount == 1));
+
+  List<Cell> listRemainingPegs() {
+    final List<Cell> pegs = [];
+
+    final BoardCells cells = board.cells;
+    for (int rowIndex = 0; rowIndex < cells.length; rowIndex++) {
+      for (int colIndex = 0; colIndex < cells[rowIndex].length; colIndex++) {
+        Cell tile = cells[rowIndex][colIndex];
+        if (tile.hasPeg == true) {
+          pegs.add(tile);
+        }
+      }
+    }
+
+    return pegs;
+  }
+
+  int countRemainingPegs() {
+    return listRemainingPegs().length;
+  }
+
+  int countAllowedMoves() {
+    int allowedMovesCount = 0;
+    final List<Cell> pegs = listRemainingPegs();
+    for (Cell tile in pegs) {
+      final int row = tile.location.row;
+      final int col = tile.location.col;
+      final List<int> source = [col, row];
+      final List<List<int>> targets = [
+        [col - 2, row],
+        [col + 2, row],
+        [col, row - 2],
+        [col, row + 2],
+      ];
+      for (List<int> target in targets) {
+        if (board.isMoveAllowed(
+          source: source,
+          target: target,
+        )) {
+          allowedMovesCount++;
+        }
+      }
+    }
+
+    return allowedMovesCount;
+  }
+
+  void dump() {
+    printlog('');
+    printlog('## Current game dump:');
+    printlog('');
+    gameSettings.dump();
+    globalSettings.dump();
+    printlog('');
+    printlog('');
+    printlog('$Game: ');
+    printlog('  isRunning: $isRunning');
+    printlog('  isFinished: $isFinished');
+    printlog('  movesCount: $movesCount');
+    printlog('  remainingPegsCount: $remainingPegsCount');
+    printlog('  allowedMovesCount: $allowedMovesCount');
+    printlog('');
+    board.dump();
+    printlog('');
+  }
+
+  @override
+  String toString() {
+    return '$Game(${toJson()})';
+  }
+
+  Map<String, dynamic>? toJson() {
+    return <String, dynamic>{
+      'gameSettings': gameSettings.toJson(),
+      'globalSettings': globalSettings.toJson(),
+      'board': board.toJson(),
+      'isRunning': isRunning,
+      'isFinished': isFinished,
+      'movesCount': movesCount,
+      'remainingPegsCount': remainingPegsCount,
+      'allowedMovesCount': allowedMovesCount,
+    };
+  }
+}
diff --git a/lib/models/settings_game.dart b/lib/models/settings_game.dart
new file mode 100644
index 0000000000000000000000000000000000000000..cb00bc94a4ce5dab5065076202e0215e1cd21b97
--- /dev/null
+++ b/lib/models/settings_game.dart
@@ -0,0 +1,41 @@
+import 'package:solitaire/config/default_game_settings.dart';
+import 'package:solitaire/utils/tools.dart';
+
+class GameSettings {
+  final String layout;
+
+  GameSettings({
+    required this.layout,
+  });
+
+  static String getLayoutValueFromUnsafe(String layout) {
+    if (DefaultGameSettings.allowedLayoutValues.contains(layout)) {
+      return layout;
+    }
+
+    return DefaultGameSettings.defaultLayoutValue;
+  }
+
+  factory GameSettings.createDefault() {
+    return GameSettings(
+      layout: DefaultGameSettings.defaultLayoutValue,
+    );
+  }
+
+  void dump() {
+    printlog('$GameSettings: ');
+    printlog('  ${DefaultGameSettings.parameterCodeLayout}: $layout');
+    printlog('');
+  }
+
+  @override
+  String toString() {
+    return '$GameSettings(${toJson()})';
+  }
+
+  Map<String, dynamic>? toJson() {
+    return <String, dynamic>{
+      DefaultGameSettings.parameterCodeLayout: layout,
+    };
+  }
+}
diff --git a/lib/models/settings_global.dart b/lib/models/settings_global.dart
new file mode 100644
index 0000000000000000000000000000000000000000..dd4b7c86673d9ed4e43f5cdbb0f8e9a0bd10f851
--- /dev/null
+++ b/lib/models/settings_global.dart
@@ -0,0 +1,41 @@
+import 'package:solitaire/config/default_global_settings.dart';
+import 'package:solitaire/utils/tools.dart';
+
+class GlobalSettings {
+  String skin;
+
+  GlobalSettings({
+    required this.skin,
+  });
+
+  static String getSkinValueFromUnsafe(String skin) {
+    if (DefaultGlobalSettings.allowedSkinValues.contains(skin)) {
+      return skin;
+    }
+
+    return DefaultGlobalSettings.defaultSkinValue;
+  }
+
+  factory GlobalSettings.createDefault() {
+    return GlobalSettings(
+      skin: DefaultGlobalSettings.defaultSkinValue,
+    );
+  }
+
+  void dump() {
+    printlog('$GlobalSettings: ');
+    printlog('  ${DefaultGlobalSettings.parameterCodeSkin}: $skin');
+    printlog('');
+  }
+
+  @override
+  String toString() {
+    return '$GlobalSettings(${toJson()})';
+  }
+
+  Map<String, dynamic>? toJson() {
+    return <String, dynamic>{
+      DefaultGlobalSettings.parameterCodeSkin: skin,
+    };
+  }
+}
diff --git a/lib/models/types.dart b/lib/models/types.dart
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/lib/provider/data.dart b/lib/provider/data.dart
deleted file mode 100644
index 9c18e794f5d5eb7045d31de5a7a7c3b26582a444..0000000000000000000000000000000000000000
--- a/lib/provider/data.dart
+++ /dev/null
@@ -1,239 +0,0 @@
-import 'dart:convert';
-
-import 'package:flutter/foundation.dart';
-import 'package:shared_preferences/shared_preferences.dart';
-import 'package:solitaire/entities/tile.dart';
-import 'package:solitaire/utils/game_utils.dart';
-
-typedef Board = List<List<Tile?>>;
-
-class Data extends ChangeNotifier {
-  // Configuration available values
-  final List<String> _availableParameters = ['layout', 'skin'];
-
-  final List<String> _availableLayoutValues = ['french', 'german', 'english', 'diamond'];
-  final List<String> _availableSkinValues = ['default'];
-
-  List<String> get availableParameters => _availableParameters;
-  List<String> get availableLayoutValues => _availableLayoutValues;
-  List<String> get availableSkinValues => _availableSkinValues;
-
-  // Application default configuration
-  String _parameterLayout = '';
-  String _parameterSkin = '';
-  final String _parameterLayoutDefault = 'english';
-  final String _parameterSkinDefault = 'default';
-
-  // Application current configuration
-  String get parameterLayout => _parameterLayout;
-  String get parameterSkin => _parameterSkin;
-
-  // Game data
-  bool _assetsPreloaded = false;
-  bool _gameIsRunning = false;
-  bool _gameIsFinished = false;
-  Board _board = [];
-  int _boardSize = 0;
-  double _tileSize = 0;
-  int _movesCount = 0;
-  int _remainingPegsCount = 0;
-  int _allowedMovesCount = 0;
-  String _currentState = '';
-
-  void updateParameterLayout(String parameterLayout) {
-    _parameterLayout = parameterLayout;
-    notifyListeners();
-  }
-
-  void updateParameterSkin(String parameterSkin) {
-    _parameterSkin = parameterSkin;
-    notifyListeners();
-  }
-
-  String getParameterValue(String parameterCode) {
-    switch (parameterCode) {
-      case 'layout':
-        return _parameterLayout;
-      case 'skin':
-        return _parameterSkin;
-    }
-    return '';
-  }
-
-  List getParameterAvailableValues(String parameterCode) {
-    switch (parameterCode) {
-      case 'layout':
-        return _availableLayoutValues;
-      case 'skin':
-        return _availableSkinValues;
-    }
-    return [];
-  }
-
-  void setParameterValue(String parameterCode, String parameterValue) async {
-    switch (parameterCode) {
-      case 'layout':
-        updateParameterLayout(parameterValue);
-        break;
-      case 'skin':
-        updateParameterSkin(parameterValue);
-        break;
-    }
-    final prefs = await SharedPreferences.getInstance();
-    prefs.setString(parameterCode, parameterValue);
-  }
-
-  void initParametersValues() async {
-    final prefs = await SharedPreferences.getInstance();
-    setParameterValue('layout', prefs.getString('layout') ?? _parameterLayoutDefault);
-    setParameterValue('skin', prefs.getString('skin') ?? _parameterSkinDefault);
-  }
-
-  String get currentState => _currentState;
-
-  String computeCurrentGameState() {
-    String boardValues = '';
-
-    String textBoard = ' ';
-    String textHole = '·';
-    String textPeg = 'o';
-    for (int rowIndex = 0; rowIndex < _board.length; rowIndex++) {
-      for (int colIndex = 0; colIndex < _board[rowIndex].length; colIndex++) {
-        String cellValue = textBoard;
-        if (_board[rowIndex][colIndex] != null) {
-          cellValue = (_board[rowIndex][colIndex]?.hasPeg ?? false) ? textPeg : textHole;
-        }
-        boardValues += cellValue;
-      }
-    }
-
-    var currentState = {
-      'layout': _parameterLayout,
-      'skin': _parameterSkin,
-      'movesCount': _movesCount.toString(),
-      'boardValues': boardValues,
-    };
-
-    return json.encode(currentState);
-  }
-
-  void saveCurrentGameState() async {
-    if (_gameIsRunning) {
-      _currentState = computeCurrentGameState();
-
-      final prefs = await SharedPreferences.getInstance();
-      prefs.setString('savedState', _currentState);
-    } else {
-      resetCurrentSavedState();
-    }
-  }
-
-  void resetCurrentSavedState() async {
-    _currentState = '';
-
-    final prefs = await SharedPreferences.getInstance();
-    prefs.setString('savedState', _currentState);
-    notifyListeners();
-  }
-
-  void loadCurrentSavedState() async {
-    final prefs = await SharedPreferences.getInstance();
-    _currentState = prefs.getString('savedState') ?? '';
-  }
-
-  bool hasCurrentSavedState() {
-    return (_currentState != '');
-  }
-
-  Map<String, dynamic> getCurrentSavedState() {
-    if (_currentState != '') {
-      final Map<String, dynamic> savedState = json.decode(_currentState);
-      if (savedState.isNotEmpty) {
-        return savedState;
-      }
-    }
-    return {};
-  }
-
-  bool get assetsPreloaded => _assetsPreloaded;
-  void updateAssetsPreloaded(bool assetsPreloaded) {
-    _assetsPreloaded = assetsPreloaded;
-  }
-
-  double get tileSize => _tileSize;
-  void updateTileSize(double tileSize) {
-    _tileSize = tileSize;
-  }
-
-  int get boardSize => _boardSize;
-  void updateBoardSize(int boardSize) {
-    _boardSize = boardSize;
-  }
-
-  Board get board => _board;
-  void updateBoard(Board board) {
-    _board = board;
-    updateBoardSize(board.length);
-    updateRemainingPegsCount(GameUtils.countRemainingPegs(this));
-    updateAllowedMovesCount(GameUtils.countAllowedMoves(this));
-    notifyListeners();
-  }
-
-  updatePegValue(int row, int col, bool hasPeg) {
-    if (_board[row][col] != null) {
-      _board[row][col]?.hasPeg = hasPeg;
-
-      saveCurrentGameState();
-      notifyListeners();
-    }
-  }
-
-  int get movesCount => _movesCount;
-  void updateMovesCount(int movesCount) {
-    _movesCount = movesCount;
-    notifyListeners();
-  }
-
-  void incrementMovesCount() {
-    updateMovesCount(movesCount + 1);
-  }
-
-  int get remainingPegsCount => _remainingPegsCount;
-  void updateRemainingPegsCount(int remainingPegsCount) {
-    _remainingPegsCount = remainingPegsCount;
-    notifyListeners();
-  }
-
-  int get allowedMovesCount => _allowedMovesCount;
-  void updateAllowedMovesCount(int allowedMovesCount) {
-    _allowedMovesCount = allowedMovesCount;
-    if (allowedMovesCount == 0) {
-      updateGameIsFinished(true);
-    }
-    notifyListeners();
-  }
-
-  bool get gameIsRunning => _gameIsRunning;
-  bool get gameIsFinished => _gameIsFinished;
-  void updateGameIsRunning(bool gameIsRunning) {
-    _gameIsRunning = gameIsRunning;
-    notifyListeners();
-  }
-
-  void updateGameIsFinished(bool gameIsFinished) {
-    _gameIsFinished = gameIsFinished;
-    notifyListeners();
-  }
-
-  bool gameWon() {
-    return gameIsFinished && (remainingPegsCount == 1);
-  }
-
-  void resetGame() {
-    _gameIsRunning = false;
-    _gameIsFinished = false;
-    _movesCount = 0;
-    _remainingPegsCount = 0;
-    notifyListeners();
-  }
-}
diff --git a/lib/ui/layout/game.dart b/lib/ui/layout/game.dart
deleted file mode 100644
index aa9d47c9fdf68e5c14eff6121c3108ceb10376bb..0000000000000000000000000000000000000000
--- a/lib/ui/layout/game.dart
+++ /dev/null
@@ -1,36 +0,0 @@
-import 'package:flutter/material.dart';
-
-import 'package:solitaire/provider/data.dart';
-import 'package:solitaire/ui/layout/tileset.dart';
-import 'package:solitaire/ui/widgets/game/indicator_top.dart';
-import 'package:solitaire/ui/widgets/game/message_game_end.dart';
-
-class Game extends StatelessWidget {
-  const Game({super.key, required this.myProvider});
-
-  final Data myProvider;
-
-  @override
-  Widget build(BuildContext context) {
-    final bool gameIsFinished = myProvider.gameIsFinished;
-
-    return Column(
-      mainAxisAlignment: MainAxisAlignment.start,
-      crossAxisAlignment: CrossAxisAlignment.center,
-      children: [
-        const SizedBox(height: 8),
-        TopIndicator(myProvider: myProvider),
-        const SizedBox(height: 2),
-        Expanded(
-          child: Tileset(myProvider: myProvider),
-        ),
-        const SizedBox(height: 2),
-        Container(
-          child: gameIsFinished
-              ? EndGameMessage(myProvider: myProvider)
-              : const SizedBox(height: 2),
-        ),
-      ],
-    );
-  }
-}
diff --git a/lib/ui/layout/parameters.dart b/lib/ui/layout/parameters.dart
deleted file mode 100644
index 68d9ac836bb4c5bfc6c5017ec291fe3da4819f03..0000000000000000000000000000000000000000
--- a/lib/ui/layout/parameters.dart
+++ /dev/null
@@ -1,129 +0,0 @@
-import 'package:flutter/material.dart';
-
-import 'package:solitaire/provider/data.dart';
-import 'package:solitaire/ui/widgets/home/button_game_resume.dart';
-import 'package:solitaire/ui/widgets/home/button_game_start_new.dart';
-
-class Parameters extends StatelessWidget {
-  const Parameters({super.key, required this.myProvider});
-
-  final Data myProvider;
-
-  static const double separatorHeight = 2.0;
-  static const double blockMargin = 0.0;
-  static const double blockPadding = 0.0;
-  static const Color buttonBackgroundColor = Colors.white;
-  static const Color buttonBorderColorActive = Colors.blue;
-  static const Color buttonBorderColorInactive = Colors.white;
-  static const double buttonBorderWidth = 6.0;
-  static const double buttonBorderRadius = 8.0;
-  static const double buttonPadding = 0.0;
-  static const double buttonMargin = 0.0;
-
-  @override
-  Widget build(BuildContext context) {
-    List<Widget> lines = [];
-
-    List parameters = myProvider.availableParameters;
-    for (int index = 0; index < parameters.length; index++) {
-      lines.add(buildParameterSelector(myProvider, parameters[index]));
-      lines.add(const SizedBox(height: separatorHeight));
-    }
-
-    myProvider.loadCurrentSavedState();
-    Widget buttonsBlock = myProvider.hasCurrentSavedState()
-        ? ResumeGameButton(myProvider: myProvider)
-        : StartNewGameButton(myProvider: myProvider);
-
-    return Column(
-      mainAxisAlignment: MainAxisAlignment.start,
-      crossAxisAlignment: CrossAxisAlignment.center,
-      children: [
-        const SizedBox(height: separatorHeight),
-        Expanded(
-          child: Column(
-            mainAxisSize: MainAxisSize.min,
-            mainAxisAlignment: MainAxisAlignment.center,
-            children: lines,
-          ),
-        ),
-        const SizedBox(height: separatorHeight),
-        Container(
-          child: buttonsBlock,
-        ),
-      ],
-    );
-  }
-
-  static Image buildImageWidget(String imageAssetCode) {
-    return Image(
-      image: AssetImage('assets/icons/$imageAssetCode.png'),
-      fit: BoxFit.fill,
-    );
-  }
-
-  static Container buildImageContainerWidget(String imageAssetCode) {
-    return Container(
-      child: buildImageWidget(imageAssetCode),
-    );
-  }
-
-  static Column buildDecorationImageWidget() {
-    return Column(
-      children: [
-        TextButton(
-          child: buildImageContainerWidget('placeholder'),
-          onPressed: () {},
-        ),
-      ],
-    );
-  }
-
-  Widget buildParameterSelector(Data myProvider, String parameterCode) {
-    List availableValues = myProvider.getParameterAvailableValues(parameterCode);
-
-    if (availableValues.length == 1) {
-      return const SizedBox(height: 0.0);
-    }
-
-    return Table(
-      defaultColumnWidth: const IntrinsicColumnWidth(),
-      children: [
-        TableRow(
-          children: [
-            for (int index = 0; index < availableValues.length; index++)
-              Column(
-                children: [
-                  buildParameterButton(myProvider, parameterCode, availableValues[index])
-                ],
-              ),
-          ],
-        ),
-      ],
-    );
-  }
-
-  Widget buildParameterButton(Data myProvider, String parameterCode, String parameterValue) {
-    String currentValue = myProvider.getParameterValue(parameterCode).toString();
-
-    bool isActive = (parameterValue == currentValue);
-    String imageAsset = '${parameterCode}_$parameterValue';
-
-    return TextButton(
-      child: Container(
-        margin: const EdgeInsets.all(buttonMargin),
-        padding: const EdgeInsets.all(buttonPadding),
-        decoration: BoxDecoration(
-          color: buttonBackgroundColor,
-          borderRadius: BorderRadius.circular(buttonBorderRadius),
-          border: Border.all(
-            color: isActive ? buttonBorderColorActive : buttonBorderColorInactive,
-            width: buttonBorderWidth,
-          ),
-        ),
-        child: buildImageWidget(imageAsset),
-      ),
-      onPressed: () => myProvider.setParameterValue(parameterCode, parameterValue),
-    );
-  }
-}
diff --git a/lib/ui/layout/tileset.dart b/lib/ui/layout/tileset.dart
deleted file mode 100644
index 4fe85a743bfc7cb8ccb3035a3dddd9c32d6b210c..0000000000000000000000000000000000000000
--- a/lib/ui/layout/tileset.dart
+++ /dev/null
@@ -1,42 +0,0 @@
-import 'package:flutter/material.dart';
-
-import 'package:solitaire/provider/data.dart';
-
-class Tileset extends StatelessWidget {
-  const Tileset({super.key, required this.myProvider});
-
-  final Data myProvider;
-
-  @override
-  Widget build(BuildContext context) {
-    final Board board = myProvider.board;
-
-    Widget boardTileWithoutHole = Image(
-      image: AssetImage('assets/skins/${myProvider.parameterSkin}_board.png'),
-      width: myProvider.tileSize,
-      height: myProvider.tileSize,
-      fit: BoxFit.fill,
-    );
-
-    return Column(
-      children: [
-        Table(
-          defaultColumnWidth: const IntrinsicColumnWidth(),
-          children: [
-            for (int row = 0; row < board.length; row++)
-              TableRow(
-                children: [
-                  for (int col = 0; col < board[row].length; col++)
-                    TableCell(
-                      child: board[row][col] != null
-                          ? (board[row][col]?.render(myProvider) ?? Container())
-                          : boardTileWithoutHole,
-                    ),
-                ],
-              ),
-          ],
-        ),
-      ],
-    );
-  }
-}
diff --git a/lib/ui/painters/parameter_painter.dart b/lib/ui/painters/parameter_painter.dart
new file mode 100644
index 0000000000000000000000000000000000000000..4ed92d7734eb935bbe24925a49fcab2864476d33
--- /dev/null
+++ b/lib/ui/painters/parameter_painter.dart
@@ -0,0 +1,190 @@
+import 'dart:math';
+
+import 'package:flutter/material.dart';
+
+import 'package:solitaire/config/default_game_settings.dart';
+import 'package:solitaire/data/game_data.dart';
+import 'package:solitaire/models/board.dart';
+import 'package:solitaire/models/cell.dart';
+import 'package:solitaire/models/cell_location.dart';
+import 'package:solitaire/models/settings_game.dart';
+import 'package:solitaire/models/settings_global.dart';
+import 'package:solitaire/utils/tools.dart';
+
+class ParameterPainter extends CustomPainter {
+  const ParameterPainter({
+    required this.code,
+    required this.value,
+    required this.isSelected,
+    required this.gameSettings,
+    required this.globalSettings,
+  });
+
+  final String code;
+  final String value;
+  final bool isSelected;
+  final GameSettings gameSettings;
+  final GlobalSettings globalSettings;
+
+  @override
+  void paint(Canvas canvas, Size size) {
+    // force square
+    final double canvasSize = min(size.width, size.height);
+
+    const Color borderColorEnabled = Colors.blue;
+    const Color borderColorDisabled = Colors.white;
+
+    // "enabled/disabled" border
+    final paint = Paint();
+    paint.style = PaintingStyle.stroke;
+    paint.color = isSelected ? borderColorEnabled : borderColorDisabled;
+    paint.strokeJoin = StrokeJoin.round;
+    paint.strokeWidth = 10;
+    canvas.drawRect(
+        Rect.fromPoints(const Offset(0, 0), Offset(canvasSize, canvasSize)), paint);
+
+    // content
+    switch (code) {
+      case DefaultGameSettings.parameterCodeLayout:
+        paintLayoutParameterItem(value, canvas, canvasSize);
+        break;
+      default:
+        printlog('Unknown parameter: $code/$value');
+        paintUnknownParameterItem(value, canvas, canvasSize);
+    }
+  }
+
+  @override
+  bool shouldRepaint(CustomPainter oldDelegate) {
+    return false;
+  }
+
+  // "unknown" parameter -> simple block with text
+  void paintUnknownParameterItem(
+    final String value,
+    final Canvas canvas,
+    final double size,
+  ) {
+    final paint = Paint();
+    paint.strokeJoin = StrokeJoin.round;
+    paint.strokeWidth = 3;
+
+    paint.color = Colors.grey;
+    paint.style = PaintingStyle.fill;
+    canvas.drawRect(Rect.fromPoints(const Offset(0, 0), Offset(size, size)), paint);
+
+    final textSpan = TextSpan(
+      text: '?\n$value',
+      style: const TextStyle(
+        color: Colors.black,
+        fontSize: 18,
+        fontWeight: FontWeight.bold,
+      ),
+    );
+    final textPainter = TextPainter(
+      text: textSpan,
+      textDirection: TextDirection.ltr,
+      textAlign: TextAlign.center,
+    );
+    textPainter.layout();
+    textPainter.paint(
+      canvas,
+      Offset(
+        (size - textPainter.width) * 0.5,
+        (size - textPainter.height) * 0.5,
+      ),
+    );
+  }
+
+  void paintLayoutParameterItem(
+    final String value,
+    final Canvas canvas,
+    final double size,
+  ) {
+    {
+      const Color backgroundColor = Colors.white;
+
+      Color gridBackgroundColor = Colors.grey;
+
+      switch (value) {
+        case DefaultGameSettings.layoutValueFrench:
+          gridBackgroundColor = Colors.green;
+          break;
+        case DefaultGameSettings.layoutValueGerman:
+          gridBackgroundColor = Colors.orange;
+          break;
+        case DefaultGameSettings.layoutValueEnglish:
+          gridBackgroundColor = Colors.red;
+          break;
+        case DefaultGameSettings.layoutValueDiamond:
+          gridBackgroundColor = Colors.purple;
+          break;
+        default:
+          printlog('Wrong value for size parameter value: $value');
+      }
+
+      final paint = Paint();
+      paint.strokeJoin = StrokeJoin.round;
+      paint.strokeWidth = 3;
+
+      // Colored background
+      paint.color = backgroundColor;
+      paint.style = PaintingStyle.fill;
+      canvas.drawRect(Rect.fromPoints(const Offset(0, 0), Offset(size, size)), paint);
+
+      // Mini grid
+      final borderColor = Colors.grey.shade800;
+
+      // Get board data from named templates
+      final List<String>? template = GameData.templates[value];
+      final BoardCells grid = [];
+
+      int row = 0;
+      template?.forEach((String line) {
+        final List<Cell> gridLine = [];
+        int col = 0;
+        line.split("").forEach((String tileCode) {
+          gridLine.add(tileCode == ' '
+              ? Cell.none
+              : Cell(
+                  location: CellLocation.go(row, col),
+                  hasHole: true,
+                  hasPeg: (tileCode == 'o'),
+                ));
+          col++;
+        });
+        row++;
+        grid.add(gridLine);
+      });
+
+      final int gridWidth = grid.length;
+      final int gridHeight = grid.first.length;
+      paint.strokeWidth = 2;
+
+      final double cellSize = (size * .9) / max(gridWidth, gridHeight);
+      final double originX = (size - gridWidth * cellSize) / 2;
+      final double originY = (size - gridHeight * cellSize) / 2;
+
+      for (int row = 0; row < gridHeight; row++) {
+        for (int col = 0; col < gridWidth; col++) {
+          final Offset topLeft = Offset(originX + col * cellSize, originY + row * cellSize);
+          final Offset bottomRight = topLeft + Offset(cellSize, cellSize);
+
+          paint.color = Colors.white;
+          paint.style = PaintingStyle.fill;
+
+          if (grid[row][col].hasPeg) {
+            paint.color = gridBackgroundColor;
+          }
+          canvas.drawRect(Rect.fromPoints(topLeft, bottomRight), paint);
+
+          if (grid[row][col].hasHole) {
+            paint.color = borderColor;
+            paint.style = PaintingStyle.stroke;
+            canvas.drawRect(Rect.fromPoints(topLeft, bottomRight), paint);
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/lib/ui/screens/game_page.dart b/lib/ui/screens/game_page.dart
deleted file mode 100644
index 9171fc2ac981a36123338eedce6cd09105852e5f..0000000000000000000000000000000000000000
--- a/lib/ui/screens/game_page.dart
+++ /dev/null
@@ -1,85 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
-
-import 'package:solitaire/provider/data.dart';
-import 'package:solitaire/ui/layout/game.dart';
-import 'package:solitaire/ui/layout/parameters.dart';
-
-class GamePage extends StatefulWidget {
-  const GamePage({super.key});
-
-  @override
-  GamePageState createState() => GamePageState();
-}
-
-class GamePageState extends State<GamePage> {
-  @override
-  void initState() {
-    super.initState();
-
-    final Data myProvider = Provider.of<Data>(context, listen: false);
-    myProvider.initParametersValues();
-    myProvider.loadCurrentSavedState();
-  }
-
-  List<String> getImagesAssets(Data myProvider) {
-    final List<String> assets = [];
-
-    final List<String> gameImages = [
-      'button_back',
-      'button_delete_saved_game',
-      'button_resume_game',
-      'button_start',
-      'game_fail',
-      'game_win',
-      'placeholder',
-    ];
-    for (String layout in myProvider.availableLayoutValues) {
-      gameImages.add('layout_$layout');
-    }
-    for (String skin in myProvider.availableSkinValues) {
-      gameImages.add('skin_$skin');
-    }
-
-    for (String image in gameImages) {
-      assets.add('${'assets/icons/$image'}.png');
-    }
-
-    const List<String> skinImages = [
-      'board',
-      'hole',
-      'peg',
-    ];
-
-    for (String skin in myProvider.availableSkinValues) {
-      for (String image in skinImages) {
-        assets.add('${'${'assets/skins/$skin'}_$image'}.png');
-      }
-    }
-
-    return assets;
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    final Data myProvider = Provider.of<Data>(context);
-
-    if (!myProvider.assetsPreloaded) {
-      final List<String> assets = getImagesAssets(myProvider);
-      for (String asset in assets) {
-        precacheImage(AssetImage(asset), context);
-      }
-      myProvider.updateAssetsPreloaded(true);
-    }
-
-    myProvider.updateTileSize((MediaQuery.of(context).size.width - 40) / myProvider.boardSize);
-
-    return SafeArea(
-      child: Center(
-        child: myProvider.gameIsRunning
-            ? Game(myProvider: myProvider)
-            : Parameters(myProvider: myProvider),
-      ),
-    );
-  }
-}
diff --git a/lib/ui/screens/about_page.dart b/lib/ui/screens/page_about.dart
similarity index 89%
rename from lib/ui/screens/about_page.dart
rename to lib/ui/screens/page_about.dart
index f22e2adbcf2c3fbf29b74937ef251a5ab64db479..f63e1530869dd9aaf2a093e2610f326c3050589f 100644
--- a/lib/ui/screens/about_page.dart
+++ b/lib/ui/screens/page_about.dart
@@ -2,10 +2,10 @@ import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/material.dart';
 import 'package:package_info_plus/package_info_plus.dart';
 
-import 'package:solitaire/ui/widgets/header_app.dart';
+import 'package:solitaire/ui/widgets/helpers/app_header.dart';
 
-class AboutPage extends StatelessWidget {
-  const AboutPage({super.key});
+class PageAbout extends StatelessWidget {
+  const PageAbout({super.key});
 
   @override
   Widget build(BuildContext context) {
diff --git a/lib/ui/screens/page_game.dart b/lib/ui/screens/page_game.dart
new file mode 100644
index 0000000000000000000000000000000000000000..287a3832dc66424363f99183602f6b3faf4785fd
--- /dev/null
+++ b/lib/ui/screens/page_game.dart
@@ -0,0 +1,19 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:solitaire/cubit/game_cubit.dart';
+import 'package:solitaire/ui/widgets/game/game_widget.dart';
+import 'package:solitaire/ui/widgets/parameters.dart';
+
+class PageGame extends StatelessWidget {
+  const PageGame({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        return gameState.currentGame.isRunning ? const GameWidget() : const Parameters();
+      },
+    );
+  }
+}
diff --git a/lib/ui/screens/settings_page.dart b/lib/ui/screens/page_settings.dart
similarity index 80%
rename from lib/ui/screens/settings_page.dart
rename to lib/ui/screens/page_settings.dart
index 63cb3f2c502e952d128108dceff49b16dce7a10d..ae65ab921d0840b9d014f098187ae4b02076a9b2 100644
--- a/lib/ui/screens/settings_page.dart
+++ b/lib/ui/screens/page_settings.dart
@@ -1,10 +1,10 @@
 import 'package:flutter/material.dart';
 
-import 'package:solitaire/ui/widgets/header_app.dart';
+import 'package:solitaire/ui/widgets/helpers/app_header.dart';
 import 'package:solitaire/ui/widgets/settings/settings_form.dart';
 
-class SettingsPage extends StatelessWidget {
-  const SettingsPage({super.key});
+class PageSettings extends StatelessWidget {
+  const PageSettings({super.key});
 
   @override
   Widget build(BuildContext context) {
diff --git a/lib/ui/skeleton.dart b/lib/ui/skeleton.dart
index 36cd48520de4304219d8273481aecd572b181e5f..c57f5c2ce6db287ee0efbcde7f0f0dfd7afd59fd 100644
--- a/lib/ui/skeleton.dart
+++ b/lib/ui/skeleton.dart
@@ -1,32 +1,33 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:provider/provider.dart';
 
 import 'package:solitaire/config/menu.dart';
-import 'package:solitaire/cubit/bottom_nav_cubit.dart';
-import 'package:solitaire/provider/data.dart';
-import 'package:solitaire/ui/widgets/app_bar.dart';
-import 'package:solitaire/ui/widgets/bottom_nav_bar.dart';
+import 'package:solitaire/cubit/nav_cubit.dart';
+import 'package:solitaire/ui/widgets/global_app_bar.dart';
 
-class SkeletonScreen extends StatefulWidget {
+class SkeletonScreen extends StatelessWidget {
   const SkeletonScreen({super.key});
 
-  @override
-  State<SkeletonScreen> createState() => _SkeletonScreenState();
-}
-
-class _SkeletonScreenState extends State<SkeletonScreen> {
   @override
   Widget build(BuildContext context) {
-    final Data myProvider = Provider.of<Data>(context);
-
     return Scaffold(
+      appBar: const GlobalAppBar(),
       extendBodyBehindAppBar: false,
-      appBar: StandardAppBar(myProvider: myProvider),
-      bottomNavigationBar: const BottomNavBar(),
-      body: BlocBuilder<BottomNavCubit, int>(builder: (BuildContext context, int state) {
-        return Menu.getPageWidget(state);
-      }),
+      body: Material(
+        color: Theme.of(context).colorScheme.background,
+        child: BlocBuilder<NavCubit, int>(
+          builder: (BuildContext context, int pageIndex) {
+            return Padding(
+              padding: const EdgeInsets.only(
+                top: 8,
+                left: 2,
+                right: 2,
+              ),
+              child: Menu.getPageWidget(pageIndex),
+            );
+          },
+        ),
+      ),
       backgroundColor: Theme.of(context).colorScheme.background,
     );
   }
diff --git a/lib/ui/widgets/app_bar.dart b/lib/ui/widgets/app_bar.dart
deleted file mode 100644
index 1dc274e7c430ae5822e3c01d400e16ee1844227f..0000000000000000000000000000000000000000
--- a/lib/ui/widgets/app_bar.dart
+++ /dev/null
@@ -1,37 +0,0 @@
-import 'package:easy_localization/easy_localization.dart';
-import 'package:flutter/material.dart';
-import 'package:overlay_support/overlay_support.dart';
-
-import 'package:solitaire/provider/data.dart';
-import 'package:solitaire/ui/widgets/header_app.dart';
-import 'package:solitaire/utils/game_utils.dart';
-
-class StandardAppBar extends StatelessWidget implements PreferredSizeWidget {
-  const StandardAppBar({super.key, required this.myProvider});
-
-  final Data myProvider;
-
-  @override
-  Widget build(BuildContext context) {
-    final List<Widget> menuActions = [];
-
-    if (myProvider.gameIsRunning) {
-      menuActions.add(TextButton(
-        child: const Image(
-          image: AssetImage('assets/icons/button_back.png'),
-          fit: BoxFit.fill,
-        ),
-        onPressed: () => toast(tr('long_press_to_quit')),
-        onLongPress: () => GameUtils.quitGame(myProvider),
-      ));
-    }
-
-    return AppBar(
-      title: const AppHeader(text: 'app_name'),
-      actions: menuActions,
-    );
-  }
-
-  @override
-  Size get preferredSize => const Size.fromHeight(50);
-}
diff --git a/lib/ui/widgets/bottom_nav_bar.dart b/lib/ui/widgets/bottom_nav_bar.dart
deleted file mode 100644
index 7e3d4717dfcaff4a58173b18531da62361a389b8..0000000000000000000000000000000000000000
--- a/lib/ui/widgets/bottom_nav_bar.dart
+++ /dev/null
@@ -1,36 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-
-import 'package:solitaire/config/menu.dart';
-import 'package:solitaire/cubit/bottom_nav_cubit.dart';
-
-class BottomNavBar extends StatelessWidget {
-  const BottomNavBar({super.key});
-
-  @override
-  Widget build(BuildContext context) {
-    return Card(
-      margin: const EdgeInsets.all(0),
-      elevation: 4,
-      shadowColor: Theme.of(context).colorScheme.shadow,
-      color: Theme.of(context).colorScheme.surfaceVariant,
-      shape: const ContinuousRectangleBorder(),
-      child: BlocBuilder<BottomNavCubit, int>(
-        builder: (BuildContext context, int state) {
-          return BottomNavigationBar(
-            currentIndex: state,
-            onTap: (int index) {
-              context.read<BottomNavCubit>().updateIndex(index);
-            },
-            type: BottomNavigationBarType.fixed,
-            elevation: 0,
-            backgroundColor: Colors.transparent,
-            selectedItemColor: Theme.of(context).colorScheme.primary,
-            unselectedItemColor: Theme.of(context).textTheme.bodySmall!.color,
-            items: Menu.getMenuItems(),
-          );
-        },
-      ),
-    );
-  }
-}
diff --git a/lib/ui/widgets/button_game_start_new.dart b/lib/ui/widgets/button_game_start_new.dart
new file mode 100644
index 0000000000000000000000000000000000000000..cd4b8f01caebb1ed5195e2e702b62d01806cfc01
--- /dev/null
+++ b/lib/ui/widgets/button_game_start_new.dart
@@ -0,0 +1,34 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:solitaire/cubit/game_cubit.dart';
+import 'package:solitaire/cubit/settings_game_cubit.dart';
+import 'package:solitaire/cubit/settings_global_cubit.dart';
+
+class StartNewGameButton extends StatelessWidget {
+  const StartNewGameButton({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<GameSettingsCubit, GameSettingsState>(
+      builder: (BuildContext context, GameSettingsState gameSettingsState) {
+        return BlocBuilder<GlobalSettingsCubit, GlobalSettingsState>(
+          builder: (BuildContext context, GlobalSettingsState globalSettingsState) {
+            final GameCubit gameCubit = BlocProvider.of<GameCubit>(context);
+
+            return TextButton(
+              child: const Image(
+                image: AssetImage('assets/icons/button_start.png'),
+                fit: BoxFit.fill,
+              ),
+              onPressed: () => gameCubit.startNewGame(
+                gameSettings: gameSettingsState.settings,
+                globalSettings: globalSettingsState.settings,
+              ),
+            );
+          },
+        );
+      },
+    );
+  }
+}
diff --git a/lib/ui/widgets/game/game_widget.dart b/lib/ui/widgets/game/game_widget.dart
new file mode 100644
index 0000000000000000000000000000000000000000..e2c7cafae7bcbca07d3309d47a967452329e4b1b
--- /dev/null
+++ b/lib/ui/widgets/game/game_widget.dart
@@ -0,0 +1,38 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:solitaire/cubit/game_cubit.dart';
+import 'package:solitaire/models/game.dart';
+import 'package:solitaire/ui/widgets/game/indicator_top.dart';
+import 'package:solitaire/ui/widgets/game/message_game_end.dart';
+import 'package:solitaire/ui/widgets/game/tileset.dart';
+
+class GameWidget extends StatelessWidget {
+  const GameWidget({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        final Game currentGame = gameState.currentGame;
+
+        final bool gameIsFinished = currentGame.isFinished;
+
+        return Column(
+          mainAxisAlignment: MainAxisAlignment.start,
+          crossAxisAlignment: CrossAxisAlignment.center,
+          children: [
+            const SizedBox(height: 8),
+            const TopIndicator(),
+            const SizedBox(height: 2),
+            const Expanded(
+              child: Tileset(),
+            ),
+            const SizedBox(height: 2),
+            gameIsFinished ? const EndGameMessage() : const SizedBox(height: 2),
+          ],
+        );
+      },
+    );
+  }
+}
diff --git a/lib/ui/widgets/game/indicator_top.dart b/lib/ui/widgets/game/indicator_top.dart
index 7ce0c3ef4fe6cfeab481697472e822a1823768cd..bc66f795fb1c03308aa1a4492367d87c9cb89dd4 100644
--- a/lib/ui/widgets/game/indicator_top.dart
+++ b/lib/ui/widgets/game/indicator_top.dart
@@ -1,47 +1,51 @@
 import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
 
-import 'package:solitaire/provider/data.dart';
+import 'package:solitaire/cubit/game_cubit.dart';
+import 'package:solitaire/models/game.dart';
 
 class TopIndicator extends StatelessWidget {
-  const TopIndicator({super.key, required this.myProvider});
-
-  final Data myProvider;
+  const TopIndicator({super.key});
 
   @override
   Widget build(BuildContext context) {
-    final int allowedMovesCount = myProvider.allowedMovesCount;
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        final Game currentGame = gameState.currentGame;
 
-    return Table(
-      children: [
-        TableRow(
+        return Table(
           children: [
-            Column(
+            TableRow(
               children: [
-                Text(
-                  '♟️ ${myProvider.remainingPegsCount}',
-                  style: const TextStyle(
-                    fontSize: 40,
-                    fontWeight: FontWeight.w600,
-                    color: Colors.black,
-                  ),
+                Column(
+                  children: [
+                    Text(
+                      '♟️ ${currentGame.remainingPegsCount}',
+                      style: const TextStyle(
+                        fontSize: 40,
+                        fontWeight: FontWeight.w600,
+                        color: Colors.black,
+                      ),
+                    ),
+                  ],
                 ),
-              ],
-            ),
-            Column(
-              children: [
-                Text(
-                  allowedMovesCount.toString(),
-                  style: const TextStyle(
-                    fontSize: 20,
-                    fontWeight: FontWeight.w600,
-                    color: Colors.green,
-                  ),
+                Column(
+                  children: [
+                    Text(
+                      currentGame.allowedMovesCount.toString(),
+                      style: const TextStyle(
+                        fontSize: 20,
+                        fontWeight: FontWeight.w600,
+                        color: Colors.green,
+                      ),
+                    ),
+                  ],
                 ),
               ],
             ),
           ],
-        ),
-      ],
+        );
+      },
     );
   }
 }
diff --git a/lib/ui/widgets/game/message_game_end.dart b/lib/ui/widgets/game/message_game_end.dart
index cd6ca3ad64384a7cf48e93a3c91519bd04ffe06f..b1b4faa4d361a8c7ddff40d35028c381d2378c58 100644
--- a/lib/ui/widgets/game/message_game_end.dart
+++ b/lib/ui/widgets/game/message_game_end.dart
@@ -1,42 +1,56 @@
 import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
 
-import 'package:solitaire/provider/data.dart';
-import 'package:solitaire/ui/widgets/home/button_game_restart.dart';
+import 'package:solitaire/cubit/game_cubit.dart';
+import 'package:solitaire/models/game.dart';
 
 class EndGameMessage extends StatelessWidget {
-  const EndGameMessage({super.key, required this.myProvider});
-
-  final Data myProvider;
+  const EndGameMessage({super.key});
 
   @override
   Widget build(BuildContext context) {
-    String decorationImageAssetName = '';
-    if (myProvider.gameWon()) {
-      decorationImageAssetName = 'assets/icons/game_win.png';
-    } else {
-      decorationImageAssetName = 'assets/icons/placeholder.png';
-    }
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        final Game currentGame = gameState.currentGame;
 
-    final Image decorationImage = Image(
-      image: AssetImage(decorationImageAssetName),
-      fit: BoxFit.fill,
-    );
+        String decorationImageAssetName = '';
+        if (currentGame.gameWon) {
+          decorationImageAssetName = 'assets/icons/game_win.png';
+        } else {
+          decorationImageAssetName = 'assets/icons/placeholder.png';
+        }
+
+        final Image decorationImage = Image(
+          image: AssetImage(decorationImageAssetName),
+          fit: BoxFit.fill,
+        );
 
-    return Container(
-      margin: const EdgeInsets.all(2),
-      padding: const EdgeInsets.all(2),
-      child: Table(
-        defaultColumnWidth: const IntrinsicColumnWidth(),
-        children: [
-          TableRow(
+        return Container(
+          margin: const EdgeInsets.all(2),
+          padding: const EdgeInsets.all(2),
+          child: Table(
+            defaultColumnWidth: const IntrinsicColumnWidth(),
             children: [
-              Column(children: [decorationImage]),
-              Column(children: [RestartGameButton(myProvider: myProvider)]),
-              Column(children: [decorationImage]),
+              TableRow(
+                children: [
+                  Column(children: [decorationImage]),
+                  TextButton(
+                    child: const Image(
+                      image: AssetImage('assets/icons/button_back.png'),
+                      fit: BoxFit.fill,
+                    ),
+                    onPressed: () {
+                      final GameCubit gameCubit = BlocProvider.of<GameCubit>(context);
+                      gameCubit.quitGame();
+                    },
+                  ),
+                  Column(children: [decorationImage]),
+                ],
+              ),
             ],
           ),
-        ],
-      ),
+        );
+      },
     );
   }
 }
diff --git a/lib/ui/widgets/game/tile_widget.dart b/lib/ui/widgets/game/tile_widget.dart
new file mode 100644
index 0000000000000000000000000000000000000000..7d71df58bb998882634777b00081a0ce99d0be6a
--- /dev/null
+++ b/lib/ui/widgets/game/tile_widget.dart
@@ -0,0 +1,135 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:solitaire/cubit/game_cubit.dart';
+import 'package:solitaire/models/cell.dart';
+import 'package:solitaire/models/game.dart';
+
+class TileWidget extends StatelessWidget {
+  const TileWidget({
+    super.key,
+    required this.tile,
+    required this.tileSize,
+  });
+
+  final Cell tile;
+  final double tileSize;
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        final Game currentGame = gameState.currentGame;
+
+        final GameCubit gameCubit = BlocProvider.of<GameCubit>(context);
+
+        if (tile.hasHole) {
+          return render(
+            currentGame: currentGame,
+            gameCubit: gameCubit,
+          );
+        } else {
+          return Image(
+            image: AssetImage('assets/skins/${currentGame.globalSettings.skin}_board.png'),
+            width: tileSize,
+            height: tileSize,
+            fit: BoxFit.fill,
+          );
+        }
+      },
+    );
+  }
+
+  Widget render({
+    required Game currentGame,
+    required GameCubit gameCubit,
+  }) {
+    List<Widget> stack = [
+      hole(
+        currentGame: currentGame,
+        gameCubit: gameCubit,
+      ),
+    ];
+
+    if (tile.hasPeg) {
+      stack.add(draggable(
+        currentGame: currentGame,
+      ));
+    }
+
+    return Stack(
+      alignment: Alignment.center,
+      children: stack,
+    );
+  }
+
+  Widget hole({
+    required Game currentGame,
+    required GameCubit gameCubit,
+  }) {
+    String image = 'assets/skins/${currentGame.globalSettings.skin}_hole.png';
+
+    return DragTarget<List<int>>(
+      builder: (
+        BuildContext context,
+        List<dynamic> accepted,
+        List<dynamic> rejected,
+      ) {
+        return Image(
+          image: AssetImage(image),
+          width: tileSize,
+          height: tileSize,
+          fit: BoxFit.fill,
+        );
+      },
+      onAcceptWithDetails: (DragTargetDetails<List<int>> source) {
+        List<int> target = [tile.location.col, tile.location.row];
+        // printlog('(drag) Pick from ' + source.toString() + ' and drop on ' + target.toString());
+        if (currentGame.board.isMoveAllowed(
+          source: source.data,
+          target: target,
+        )) {
+          gameCubit.move(
+            currentGame: currentGame,
+            source: source.data,
+            target: target,
+          );
+        }
+      },
+    );
+  }
+
+  Widget draggable({
+    required Game currentGame,
+  }) {
+    return Draggable<List<int>>(
+      data: [tile.location.col, tile.location.row],
+
+      // Widget when draggable is being dragged
+      feedback: peg(
+        currentGame: currentGame,
+      ),
+
+      // Widget to display on original place when being dragged
+      childWhenDragging: Container(),
+
+      // Widget when draggable is stationary
+      child: peg(
+        currentGame: currentGame,
+      ),
+    );
+  }
+
+  Widget peg({
+    required Game currentGame,
+  }) {
+    String image = 'assets/skins/${currentGame.globalSettings.skin}_peg.png';
+
+    return Image(
+      image: AssetImage(image),
+      width: tileSize,
+      height: tileSize,
+      fit: BoxFit.fill,
+    );
+  }
+}
diff --git a/lib/ui/widgets/game/tileset.dart b/lib/ui/widgets/game/tileset.dart
new file mode 100644
index 0000000000000000000000000000000000000000..5462a796ad34ad7fc042d41dea00fabc0faf35fd
--- /dev/null
+++ b/lib/ui/widgets/game/tileset.dart
@@ -0,0 +1,45 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:solitaire/cubit/game_cubit.dart';
+import 'package:solitaire/models/board.dart';
+import 'package:solitaire/ui/widgets/game/tile_widget.dart';
+
+class Tileset extends StatelessWidget {
+  const Tileset({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        final Board board = gameState.currentGame.board;
+        final BoardCells cells = board.cells;
+
+        final boardSize = gameState.currentGame.boardSize;
+        final double tileSize = (MediaQuery.of(context).size.width - 40) / boardSize;
+
+        return Column(
+          children: [
+            Table(
+              defaultColumnWidth: const IntrinsicColumnWidth(),
+              children: [
+                for (int row = 0; row < cells.length; row++)
+                  TableRow(
+                    children: [
+                      for (int col = 0; col < cells[row].length; col++)
+                        TableCell(
+                          child: TileWidget(
+                            tile: cells[row][col],
+                            tileSize: tileSize,
+                          ),
+                        ),
+                    ],
+                  ),
+              ],
+            ),
+          ],
+        );
+      },
+    );
+  }
+}
diff --git a/lib/ui/widgets/global_app_bar.dart b/lib/ui/widgets/global_app_bar.dart
new file mode 100644
index 0000000000000000000000000000000000000000..82121035102232012623d4532250a5c551412535
--- /dev/null
+++ b/lib/ui/widgets/global_app_bar.dart
@@ -0,0 +1,84 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:solitaire/config/menu.dart';
+import 'package:solitaire/cubit/game_cubit.dart';
+import 'package:solitaire/cubit/nav_cubit.dart';
+import 'package:solitaire/models/game.dart';
+import 'package:solitaire/ui/widgets/helpers/app_title.dart';
+
+class GlobalAppBar extends StatelessWidget implements PreferredSizeWidget {
+  const GlobalAppBar({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        return BlocBuilder<NavCubit, int>(
+          builder: (BuildContext context, int pageIndex) {
+            final Game currentGame = gameState.currentGame;
+
+            final List<Widget> menuActions = [];
+
+            if (currentGame.isRunning) {
+              menuActions.add(TextButton(
+                child: const Image(
+                  image: AssetImage('assets/icons/button_back.png'),
+                  fit: BoxFit.fill,
+                ),
+                onPressed: () {},
+                onLongPress: () {
+                  final GameCubit gameCubit = BlocProvider.of<GameCubit>(context);
+                  gameCubit.quitGame();
+                },
+              ));
+            } else {
+              if (pageIndex == Menu.indexGame) {
+                // go to Settings page
+                menuActions.add(ElevatedButton(
+                  onPressed: () {
+                    context.read<NavCubit>().goToSettingsPage();
+                  },
+                  style: ElevatedButton.styleFrom(
+                    shape: const CircleBorder(),
+                  ),
+                  child: Menu.menuItemSettings.icon,
+                ));
+
+                // go to About page
+                menuActions.add(ElevatedButton(
+                  onPressed: () {
+                    context.read<NavCubit>().goToAboutPage();
+                  },
+                  style: ElevatedButton.styleFrom(
+                    shape: const CircleBorder(),
+                  ),
+                  child: Menu.menuItemAbout.icon,
+                ));
+              } else {
+                // back to Home page
+                menuActions.add(ElevatedButton(
+                  onPressed: () {
+                    context.read<NavCubit>().goToGamePage();
+                  },
+                  style: ElevatedButton.styleFrom(
+                    shape: const CircleBorder(),
+                  ),
+                  child: Menu.menuItemGame.icon,
+                ));
+              }
+            }
+
+            return AppBar(
+              title: const AppTitle(text: 'app_name'),
+              actions: menuActions,
+            );
+          },
+        );
+      },
+    );
+  }
+
+  @override
+  Size get preferredSize => const Size.fromHeight(50);
+}
diff --git a/lib/ui/widgets/header_app.dart b/lib/ui/widgets/helpers/app_header.dart
similarity index 77%
rename from lib/ui/widgets/header_app.dart
rename to lib/ui/widgets/helpers/app_header.dart
index bf54b77375fbd0260f876f2885d0572b71715383..b5c5be05f6636cf488dcdb5bbc4d6f049b98de11 100644
--- a/lib/ui/widgets/header_app.dart
+++ b/lib/ui/widgets/helpers/app_header.dart
@@ -8,15 +8,16 @@ class AppHeader extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    return Row(
+    return Column(
       mainAxisAlignment: MainAxisAlignment.start,
       crossAxisAlignment: CrossAxisAlignment.start,
       children: [
         Text(
           tr(text),
           textAlign: TextAlign.start,
-          style: Theme.of(context).textTheme.headlineMedium!.apply(fontWeightDelta: 2),
+          style: Theme.of(context).textTheme.headlineSmall!.apply(fontWeightDelta: 2),
         ),
+        const SizedBox(height: 8),
       ],
     );
   }
diff --git a/lib/ui/widgets/helpers/app_title.dart b/lib/ui/widgets/helpers/app_title.dart
new file mode 100644
index 0000000000000000000000000000000000000000..7cbbb2030419047b3dcf093a2195a498bd8e8ce9
--- /dev/null
+++ b/lib/ui/widgets/helpers/app_title.dart
@@ -0,0 +1,17 @@
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+
+class AppTitle extends StatelessWidget {
+  const AppTitle({super.key, required this.text});
+
+  final String text;
+
+  @override
+  Widget build(BuildContext context) {
+    return Text(
+      tr(text),
+      textAlign: TextAlign.start,
+      style: Theme.of(context).textTheme.headlineLarge!.apply(fontWeightDelta: 2),
+    );
+  }
+}
diff --git a/lib/ui/widgets/home/button_game_restart.dart b/lib/ui/widgets/home/button_game_restart.dart
deleted file mode 100644
index 48dfc3438732370f607b916c7f15a4c1b6968673..0000000000000000000000000000000000000000
--- a/lib/ui/widgets/home/button_game_restart.dart
+++ /dev/null
@@ -1,21 +0,0 @@
-import 'package:flutter/material.dart';
-
-import 'package:solitaire/provider/data.dart';
-import 'package:solitaire/utils/game_utils.dart';
-
-class RestartGameButton extends StatelessWidget {
-  const RestartGameButton({super.key, required this.myProvider});
-
-  final Data myProvider;
-
-  @override
-  Widget build(BuildContext context) {
-    return TextButton(
-      child: const Image(
-        image: AssetImage('assets/icons/button_back.png'),
-        fit: BoxFit.fill,
-      ),
-      onPressed: () => GameUtils.quitAndDeleteCurrentGame(myProvider),
-    );
-  }
-}
diff --git a/lib/ui/widgets/home/button_game_resume.dart b/lib/ui/widgets/home/button_game_resume.dart
deleted file mode 100644
index 185c92f9c1fc6d607c9d947804700a74f8ae4a84..0000000000000000000000000000000000000000
--- a/lib/ui/widgets/home/button_game_resume.dart
+++ /dev/null
@@ -1,42 +0,0 @@
-import 'package:flutter/material.dart';
-
-import 'package:solitaire/ui/layout/parameters.dart';
-import 'package:solitaire/utils/game_utils.dart';
-
-class ResumeGameButton extends Parameters {
-  const ResumeGameButton({super.key, required super.myProvider});
-
-  @override
-  Widget build(BuildContext context) {
-    return Container(
-      margin: const EdgeInsets.all(Parameters.blockMargin),
-      padding: const EdgeInsets.all(Parameters.blockPadding),
-      child: Table(
-        defaultColumnWidth: const IntrinsicColumnWidth(),
-        children: [
-          TableRow(
-            children: [
-              Column(
-                children: [
-                  TextButton(
-                    child: Parameters.buildImageContainerWidget('button_delete_saved_game'),
-                    onPressed: () => GameUtils.deleteSavedGame(myProvider),
-                  ),
-                ],
-              ),
-              Column(
-                children: [
-                  TextButton(
-                    child: Parameters.buildImageContainerWidget('button_resume_game'),
-                    onPressed: () => GameUtils.resumeSavedGame(myProvider),
-                  ),
-                ],
-              ),
-              Parameters.buildDecorationImageWidget(),
-            ],
-          ),
-        ],
-      ),
-    );
-  }
-}
diff --git a/lib/ui/widgets/home/button_game_start_new.dart b/lib/ui/widgets/home/button_game_start_new.dart
deleted file mode 100644
index 2de0c55bc99e5830965595bde7dd09617add80a2..0000000000000000000000000000000000000000
--- a/lib/ui/widgets/home/button_game_start_new.dart
+++ /dev/null
@@ -1,38 +0,0 @@
-import 'package:flutter/material.dart';
-
-import 'package:solitaire/provider/data.dart';
-import 'package:solitaire/ui/layout/parameters.dart';
-import 'package:solitaire/utils/game_utils.dart';
-
-class StartNewGameButton extends StatelessWidget {
-  const StartNewGameButton({super.key, required this.myProvider});
-
-  final Data myProvider;
-
-  @override
-  Widget build(BuildContext context) {
-    return Container(
-      margin: const EdgeInsets.all(Parameters.blockMargin),
-      padding: const EdgeInsets.all(Parameters.blockPadding),
-      child: Table(
-        defaultColumnWidth: const IntrinsicColumnWidth(),
-        children: [
-          TableRow(
-            children: [
-              Parameters.buildDecorationImageWidget(),
-              Column(
-                children: [
-                  TextButton(
-                    child: Parameters.buildImageContainerWidget('button_start'),
-                    onPressed: () => GameUtils.startNewGame(myProvider),
-                  ),
-                ],
-              ),
-              Parameters.buildDecorationImageWidget(),
-            ],
-          ),
-        ],
-      ),
-    );
-  }
-}
diff --git a/lib/ui/widgets/parameters.dart b/lib/ui/widgets/parameters.dart
new file mode 100644
index 0000000000000000000000000000000000000000..11b080d42b81d7c750212791a67537e8979818ba
--- /dev/null
+++ b/lib/ui/widgets/parameters.dart
@@ -0,0 +1,115 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:solitaire/config/default_game_settings.dart';
+import 'package:solitaire/config/default_global_settings.dart';
+import 'package:solitaire/cubit/settings_game_cubit.dart';
+import 'package:solitaire/cubit/settings_global_cubit.dart';
+import 'package:solitaire/ui/painters/parameter_painter.dart';
+import 'package:solitaire/ui/widgets/button_game_start_new.dart';
+
+class Parameters extends StatelessWidget {
+  const Parameters({super.key});
+
+  final double separatorHeight = 8.0;
+
+  @override
+  Widget build(BuildContext context) {
+    final List<Widget> lines = [];
+
+    // Game settings
+    for (String code in DefaultGameSettings.availableParameters) {
+      lines.add(Row(
+        mainAxisAlignment: MainAxisAlignment.spaceBetween,
+        children: buildParametersLine(
+          code: code,
+          isGlobal: false,
+        ),
+      ));
+
+      lines.add(SizedBox(height: separatorHeight));
+    }
+
+    lines.add(SizedBox(height: separatorHeight));
+    lines.add(const Expanded(child: StartNewGameButton()));
+    lines.add(SizedBox(height: separatorHeight));
+
+    // Global settings
+    for (String code in DefaultGlobalSettings.availableParameters) {
+      lines.add(Row(
+        mainAxisAlignment: MainAxisAlignment.spaceBetween,
+        children: buildParametersLine(
+          code: code,
+          isGlobal: true,
+        ),
+      ));
+
+      lines.add(SizedBox(height: separatorHeight));
+    }
+
+    return Column(
+      children: lines,
+    );
+  }
+
+  List<Widget> buildParametersLine({
+    required String code,
+    required bool isGlobal,
+  }) {
+    final List<Widget> parameterButtons = [];
+
+    final List<String> availableValues = isGlobal
+        ? DefaultGlobalSettings.getAvailableValues(code)
+        : DefaultGameSettings.getAvailableValues(code);
+
+    if (availableValues.length <= 1) {
+      return [];
+    }
+
+    for (String value in availableValues) {
+      final Widget parameterButton = BlocBuilder<GameSettingsCubit, GameSettingsState>(
+        builder: (BuildContext context, GameSettingsState gameSettingsState) {
+          return BlocBuilder<GlobalSettingsCubit, GlobalSettingsState>(
+            builder: (BuildContext context, GlobalSettingsState globalSettingsState) {
+              final GameSettingsCubit gameSettingsCubit =
+                  BlocProvider.of<GameSettingsCubit>(context);
+              final GlobalSettingsCubit globalSettingsCubit =
+                  BlocProvider.of<GlobalSettingsCubit>(context);
+
+              final String currentValue = isGlobal
+                  ? globalSettingsCubit.getParameterValue(code)
+                  : gameSettingsCubit.getParameterValue(code);
+
+              final bool isActive = (value == currentValue);
+
+              final double displayWidth = MediaQuery.of(context).size.width;
+              final double itemWidth = displayWidth / availableValues.length - 26;
+
+              return TextButton(
+                child: CustomPaint(
+                  size: Size(itemWidth, itemWidth),
+                  willChange: false,
+                  painter: ParameterPainter(
+                    code: code,
+                    value: value,
+                    isSelected: isActive,
+                    gameSettings: gameSettingsState.settings,
+                    globalSettings: globalSettingsState.settings,
+                  ),
+                  isComplex: true,
+                ),
+                onPressed: () => isGlobal
+                    ? globalSettingsCubit.setParameterValue(code, value)
+                    : gameSettingsCubit.setParameterValue(code, value),
+              );
+            },
+          );
+        },
+      );
+
+      parameterButtons.add(parameterButton);
+    }
+
+    return parameterButtons;
+  }
+}
diff --git a/lib/utils/board_utils.dart b/lib/utils/board_utils.dart
deleted file mode 100644
index 349b05dd4e48f223109bb7647591e9bcbb27a12b..0000000000000000000000000000000000000000
--- a/lib/utils/board_utils.dart
+++ /dev/null
@@ -1,120 +0,0 @@
-import 'dart:math';
-
-import 'package:solitaire/entities/tile.dart';
-import 'package:solitaire/provider/data.dart';
-import 'package:solitaire/utils/tools.dart';
-
-class BoardUtils {
-  static printGrid(List cells) {
-    String textBoard = ' ';
-    String textHole = '·';
-    String textPeg = 'o';
-
-    printlog('');
-    printlog('-------');
-    for (int rowIndex = 0; rowIndex < cells.length; rowIndex++) {
-      String row = '';
-      for (int colIndex = 0; colIndex < cells[rowIndex].length; colIndex++) {
-        String textCell = textBoard;
-        Tile? tile = cells[rowIndex][colIndex];
-        if (tile != null) {
-          textCell = tile.hasPeg ? textPeg : textHole;
-        }
-        row += textCell;
-      }
-      printlog(row);
-    }
-    printlog('-------');
-    printlog('');
-  }
-
-  static Board createBoardFromSavedState(Data myProvider, String savedBoard) {
-    Board board = [];
-    int boardSize = pow((savedBoard.length), 1 / 2).round();
-    myProvider.updateBoardSize(boardSize);
-
-    String textBoard = ' ';
-    String textPeg = 'o';
-
-    int index = 0;
-    for (int rowIndex = 0; rowIndex < boardSize; rowIndex++) {
-      List<Tile?> row = [];
-      for (int colIndex = 0; colIndex < boardSize; colIndex++) {
-        String stringValue = savedBoard[index++];
-        if (stringValue == textBoard) {
-          row.add(null);
-        } else {
-          row.add(Tile(rowIndex, colIndex, (stringValue == textPeg)));
-        }
-      }
-      board.add(row);
-    }
-
-    return board;
-  }
-
-  static createNewBoard(Data myProvider) {
-    Map<String, List<String>> templates = {
-      'french': [
-        '  ooo  ',
-        ' ooooo ',
-        'ooo·ooo',
-        'ooooooo',
-        'ooooooo',
-        ' ooooo ',
-        '  ooo  ',
-      ],
-      'german': [
-        '   ooo   ',
-        '   ooo   ',
-        '   ooo   ',
-        'ooooooooo',
-        'oooo·oooo',
-        'ooooooooo',
-        '   ooo   ',
-        '   ooo   ',
-        '   ooo   ',
-      ],
-      'english': [
-        '  ooo  ',
-        '  ooo  ',
-        'ooooooo',
-        'ooo·ooo',
-        'ooooooo',
-        '  ooo  ',
-        '  ooo  ',
-      ],
-      'diamond': [
-        '    o    ',
-        '   ooo   ',
-        '  ooooo  ',
-        ' ooooooo ',
-        'oooo·oooo',
-        ' ooooooo ',
-        '  ooooo  ',
-        '   ooo   ',
-        '    o    ',
-      ]
-    };
-
-    List<String>? template = templates[myProvider.parameterLayout];
-
-    Board grid = [];
-    int row = 0;
-    template?.forEach((String line) {
-      List<Tile?> gridLine = [];
-      int col = 0;
-      line.split("").forEach((String tileCode) {
-        gridLine.add(tileCode == ' ' ? null : Tile(row, col, (tileCode == 'o')));
-        col++;
-      });
-      row++;
-      grid.add(gridLine);
-    });
-
-    printGrid(grid);
-
-    myProvider.resetGame();
-    myProvider.updateBoard(grid);
-  }
-}
diff --git a/lib/utils/game_utils.dart b/lib/utils/game_utils.dart
deleted file mode 100644
index 69b0f4f014abb036969d43e86a62c94f405540e3..0000000000000000000000000000000000000000
--- a/lib/utils/game_utils.dart
+++ /dev/null
@@ -1,180 +0,0 @@
-import 'package:solitaire/entities/tile.dart';
-import 'package:solitaire/provider/data.dart';
-import 'package:solitaire/utils/board_utils.dart';
-import 'package:solitaire/utils/tools.dart';
-
-class GameUtils {
-  static Future<void> quitGame(Data myProvider) async {
-    myProvider.updateGameIsRunning(false);
-  }
-
-  static Future<void> quitAndDeleteCurrentGame(Data myProvider) async {
-    quitGame(myProvider);
-    myProvider.resetCurrentSavedState();
-  }
-
-  static Future<void> startNewGame(Data myProvider) async {
-    printlog('Starting game');
-
-    BoardUtils.createNewBoard(myProvider);
-
-    myProvider.updateGameIsRunning(true);
-  }
-
-  static void deleteSavedGame(Data myProvider) {
-    myProvider.resetCurrentSavedState();
-  }
-
-  static void resumeSavedGame(Data myProvider) {
-    Map<String, dynamic> savedState = myProvider.getCurrentSavedState();
-    if (savedState.isNotEmpty) {
-      try {
-        myProvider.setParameterValue('layout', savedState['layout']);
-        myProvider.setParameterValue('skin', savedState['skin']);
-        myProvider.updateMovesCount(int.parse(savedState['movesCount']));
-        myProvider.updateBoard(
-            BoardUtils.createBoardFromSavedState(myProvider, savedState['boardValues']));
-
-        myProvider.updateGameIsRunning(true);
-      } catch (e) {
-        printlog('Failed to resume game. Will start new one instead.');
-        myProvider.resetCurrentSavedState();
-        myProvider.initParametersValues();
-        startNewGame(myProvider);
-      }
-    } else {
-      myProvider.resetCurrentSavedState();
-      myProvider.initParametersValues();
-      startNewGame(myProvider);
-    }
-  }
-
-  static bool isMoveAllowed(Data myProvider, List<int> source, List<int> target) {
-    // printlog('(test) Pick from ' + source.toString() + ' and drop on ' + target.toString());
-    final Board board = myProvider.board;
-    final int sourceCol = source[0];
-    final int sourceRow = source[1];
-    final int targetCol = target[0];
-    final int targetRow = target[1];
-
-    // ensure source and target are inside range
-    if (sourceRow < 0 ||
-        sourceRow > (myProvider.boardSize - 1) ||
-        sourceCol < 0 ||
-        sourceCol > (myProvider.boardSize - 1)) {
-      // printlog('move forbidden: source is out of board');
-      return false;
-    }
-    if (targetRow < 0 ||
-        targetRow > (myProvider.boardSize - 1) ||
-        targetCol < 0 ||
-        targetCol > (myProvider.boardSize - 1)) {
-      // printlog('move forbidden: target is out of board');
-      return false;
-    }
-
-    // ensure source exists and has a peg
-    if (board[sourceRow][sourceCol] == null || board[sourceRow][sourceCol]?.hasPeg == false) {
-      // printlog('move forbidden: source peg does not exist');
-      return false;
-    }
-
-    // ensure target exists and is empty
-    if (board[targetRow][targetCol] == null || board[targetRow][targetCol]?.hasPeg == true) {
-      // printlog('move forbidden: target does not exist or already with a peg');
-      return false;
-    }
-
-    // ensure source and target are in the same line/column
-    if ((targetCol != sourceCol) && (targetRow != sourceRow)) {
-      // printlog('move forbidden: source and target are not in the same line or column');
-      return false;
-    }
-
-    // ensure source and target are separated by exactly one tile
-    if (((targetCol == sourceCol) && ((targetRow - sourceRow).abs() != 2)) ||
-        ((targetRow == sourceRow) && ((targetCol - sourceCol).abs() != 2))) {
-      // printlog('move forbidden: source and target must be separated by exactly one tile');
-      return false;
-    }
-
-    // ensure middle tile exists and has a peg
-    final int middleRow = (sourceRow + ((targetRow - sourceRow) / 2)).round();
-    final int middleCol = (sourceCol + ((targetCol - sourceCol) / 2)).round();
-    if (board[middleRow][middleCol] == null || board[middleRow][middleCol]?.hasPeg == false) {
-      // printlog('move forbidden: tile between source and target does not contain a peg');
-      return false;
-    }
-
-    // ok, move is allowed
-    return true;
-  }
-
-  static void move(Data myProvider, List<int> source, List<int> target) {
-    printlog('Move from $source to $target');
-    final int sourceCol = source[0];
-    final int sourceRow = source[1];
-    final int targetCol = target[0];
-    final int targetRow = target[1];
-
-    final int middleRow = (sourceRow + ((targetRow - sourceRow) / 2)).round();
-    final int middleCol = (sourceCol + ((targetCol - sourceCol) / 2)).round();
-
-    // remove peg from source
-    myProvider.updatePegValue(sourceRow, sourceCol, false);
-    // put peg in target
-    myProvider.updatePegValue(targetRow, targetCol, true);
-    // remove peg from middle tile
-    myProvider.updatePegValue(middleRow, middleCol, false);
-
-    // increment moves count
-    myProvider.incrementMovesCount();
-    // update remaining pegs count
-    myProvider.updateRemainingPegsCount(GameUtils.countRemainingPegs(myProvider));
-    // update allowed moves count
-    myProvider.updateAllowedMovesCount(GameUtils.countAllowedMoves(myProvider));
-  }
-
-  static List<Tile> listRemainingPegs(Data myProvider) {
-    List<Tile> pegs = [];
-
-    Board board = myProvider.board;
-    for (int rowIndex = 0; rowIndex < board.length; rowIndex++) {
-      for (int colIndex = 0; colIndex < board[rowIndex].length; colIndex++) {
-        Tile? tile = board[rowIndex][colIndex];
-        if (tile != null && tile.hasPeg == true) {
-          pegs.add(tile);
-        }
-      }
-    }
-
-    return pegs;
-  }
-
-  static int countRemainingPegs(Data myProvider) {
-    return GameUtils.listRemainingPegs(myProvider).length;
-  }
-
-  static int countAllowedMoves(Data myProvider) {
-    int allowedMovesCount = 0;
-    List<Tile> pegs = GameUtils.listRemainingPegs(myProvider);
-    for (Tile tile in pegs) {
-      final int row = tile.currentRow;
-      final int col = tile.currentCol;
-      final List<int> source = [col, row];
-      final List<List<int>> targets = [
-        [col - 2, row],
-        [col + 2, row],
-        [col, row - 2],
-        [col, row + 2],
-      ];
-      for (List<int> target in targets) {
-        if (GameUtils.isMoveAllowed(myProvider, source, target)) {
-          allowedMovesCount++;
-        }
-      }
-    }
-
-    return allowedMovesCount;
-  }
-}
diff --git a/pubspec.lock b/pubspec.lock
index 12d429bb18ac218313d455ba71028cdbb3234bb9..bdba0ef12aaa5e28404023f4cff3d604ec53b942 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -5,10 +5,10 @@ packages:
     dependency: transitive
     description:
       name: args
-      sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596
+      sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a"
       url: "https://pub.dev"
     source: hosted
-    version: "2.4.2"
+    version: "2.5.0"
   async:
     dependency: transitive
     description:
@@ -21,10 +21,10 @@ packages:
     dependency: transitive
     description:
       name: bloc
-      sha256: f53a110e3b48dcd78136c10daa5d51512443cea5e1348c9d80a320095fa2db9e
+      sha256: "106842ad6569f0b60297619e9e0b1885c2fb9bf84812935490e6c5275777804e"
       url: "https://pub.dev"
     source: hosted
-    version: "8.1.3"
+    version: "8.1.4"
   characters:
     dependency: transitive
     description:
@@ -61,10 +61,10 @@ packages:
     dependency: "direct main"
     description:
       name: easy_localization
-      sha256: c145aeb6584aedc7c862ab8c737c3277788f47488bfdf9bae0fe112bd0a4789c
+      sha256: fa59bcdbbb911a764aa6acf96bbb6fa7a5cf8234354fc45ec1a43a0349ef0201
       url: "https://pub.dev"
     source: hosted
-    version: "3.0.5"
+    version: "3.0.7"
   easy_logger:
     dependency: transitive
     description:
@@ -106,18 +106,18 @@ packages:
     dependency: "direct main"
     description:
       name: flutter_bloc
-      sha256: "87325da1ac757fcc4813e6b34ed5dd61169973871fdf181d6c2109dd6935ece1"
+      sha256: f0ecf6e6eb955193ca60af2d5ca39565a86b8a142452c5b24d96fb477428f4d2
       url: "https://pub.dev"
     source: hosted
-    version: "8.1.4"
+    version: "8.1.5"
   flutter_lints:
     dependency: "direct dev"
     description:
       name: flutter_lints
-      sha256: e2a421b7e59244faef694ba7b30562e489c2b489866e505074eb005cd7060db7
+      sha256: "3f41d009ba7172d5ff9be5f6e6e6abb4300e263aab8866d2a0842ed2a70f8f0c"
       url: "https://pub.dev"
     source: hosted
-    version: "3.0.1"
+    version: "4.0.0"
   flutter_localizations:
     dependency: transitive
     description: flutter
@@ -140,10 +140,10 @@ packages:
     dependency: transitive
     description:
       name: http
-      sha256: a2bbf9d017fcced29139daa8ed2bba4ece450ab222871df93ca9eec6f80c34ba
+      sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938"
       url: "https://pub.dev"
     source: hosted
-    version: "1.2.0"
+    version: "1.2.1"
   http_parser:
     dependency: transitive
     description:
@@ -156,10 +156,10 @@ packages:
     dependency: "direct main"
     description:
       name: hydrated_bloc
-      sha256: "00a2099680162e74b5a836b8a7f446e478520a9cae9f6032e028ad8129f4432d"
+      sha256: af35b357739fe41728df10bec03aad422cdc725a1e702e03af9d2a41ea05160c
       url: "https://pub.dev"
     source: hosted
-    version: "9.1.4"
+    version: "9.1.5"
   intl:
     dependency: transitive
     description:
@@ -172,10 +172,10 @@ packages:
     dependency: transitive
     description:
       name: lints
-      sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290
+      sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235"
       url: "https://pub.dev"
     source: hosted
-    version: "3.0.0"
+    version: "4.0.0"
   material_color_utilities:
     dependency: transitive
     description:
@@ -200,32 +200,24 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "1.0.0"
-  overlay_support:
-    dependency: "direct main"
-    description:
-      name: overlay_support
-      sha256: fc39389bfd94e6985e1e13b2a88a125fc4027608485d2d4e2847afe1b2bb339c
-      url: "https://pub.dev"
-    source: hosted
-    version: "2.1.0"
   package_info_plus:
     dependency: "direct main"
     description:
       name: package_info_plus
-      sha256: "88bc797f44a94814f2213db1c9bd5badebafdfb8290ca9f78d4b9ee2a3db4d79"
+      sha256: b93d8b4d624b4ea19b0a5a208b2d6eff06004bc3ce74c06040b120eeadd00ce0
       url: "https://pub.dev"
     source: hosted
-    version: "5.0.1"
+    version: "8.0.0"
   package_info_plus_platform_interface:
     dependency: transitive
     description:
       name: package_info_plus_platform_interface
-      sha256: "9bc8ba46813a4cc42c66ab781470711781940780fd8beddd0c3da62506d3a6c6"
+      sha256: f49918f3433a3146047372f9d4f1f847511f2acd5cd030e1f44fe5a50036b70e
       url: "https://pub.dev"
     source: hosted
-    version: "2.0.1"
+    version: "3.0.0"
   path:
-    dependency: "direct main"
+    dependency: transitive
     description:
       name: path
       sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
@@ -236,26 +228,26 @@ packages:
     dependency: "direct main"
     description:
       name: path_provider
-      sha256: b27217933eeeba8ff24845c34003b003b2b22151de3c908d0e679e8fe1aa078b
+      sha256: c9e7d3a4cd1410877472158bee69963a4579f78b68c65a2b7d40d1a7a88bb161
       url: "https://pub.dev"
     source: hosted
-    version: "2.1.2"
+    version: "2.1.3"
   path_provider_android:
     dependency: transitive
     description:
       name: path_provider_android
-      sha256: "477184d672607c0a3bf68fbbf601805f92ef79c82b64b4d6eb318cbca4c48668"
+      sha256: a248d8146ee5983446bf03ed5ea8f6533129a12b11f12057ad1b4a67a2b3b41d
       url: "https://pub.dev"
     source: hosted
-    version: "2.2.2"
+    version: "2.2.4"
   path_provider_foundation:
     dependency: transitive
     description:
       name: path_provider_foundation
-      sha256: "5a7999be66e000916500be4f15a3633ebceb8302719b47b9cc49ce924125350f"
+      sha256: f234384a3fdd67f989b4d54a5d73ca2a6c422fa55ae694381ae0f4375cd1ea16
       url: "https://pub.dev"
     source: hosted
-    version: "2.3.2"
+    version: "2.4.0"
   path_provider_linux:
     dependency: transitive
     description:
@@ -297,7 +289,7 @@ packages:
     source: hosted
     version: "2.1.8"
   provider:
-    dependency: "direct main"
+    dependency: transitive
     description:
       name: provider
       sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c
@@ -305,29 +297,29 @@ packages:
     source: hosted
     version: "6.1.2"
   shared_preferences:
-    dependency: "direct main"
+    dependency: transitive
     description:
       name: shared_preferences
-      sha256: "81429e4481e1ccfb51ede496e916348668fd0921627779233bd24cc3ff6abd02"
+      sha256: d3bbe5553a986e83980916ded2f0b435ef2e1893dfaa29d5a7a790d0eca12180
       url: "https://pub.dev"
     source: hosted
-    version: "2.2.2"
+    version: "2.2.3"
   shared_preferences_android:
     dependency: transitive
     description:
       name: shared_preferences_android
-      sha256: "8568a389334b6e83415b6aae55378e158fbc2314e074983362d20c562780fb06"
+      sha256: "1ee8bf911094a1b592de7ab29add6f826a7331fb854273d55918693d5364a1f2"
       url: "https://pub.dev"
     source: hosted
-    version: "2.2.1"
+    version: "2.2.2"
   shared_preferences_foundation:
     dependency: transitive
     description:
       name: shared_preferences_foundation
-      sha256: "7708d83064f38060c7b39db12aefe449cb8cdc031d6062280087bc4cdb988f5c"
+      sha256: "0a8a893bf4fd1152f93fec03a415d11c27c74454d96e2318a7ac38dd18683ab7"
       url: "https://pub.dev"
     source: hosted
-    version: "2.3.5"
+    version: "2.4.0"
   shared_preferences_linux:
     dependency: transitive
     description:
@@ -348,10 +340,10 @@ packages:
     dependency: transitive
     description:
       name: shared_preferences_web
-      sha256: "7b15ffb9387ea3e237bb7a66b8a23d2147663d391cafc5c8f37b2e7b4bde5d21"
+      sha256: "9aee1089b36bd2aafe06582b7d7817fd317ef05fc30e6ba14bff247d0933042a"
       url: "https://pub.dev"
     source: hosted
-    version: "2.2.2"
+    version: "2.3.0"
   shared_preferences_windows:
     dependency: transitive
     description:
@@ -425,18 +417,18 @@ packages:
     dependency: transitive
     description:
       name: web
-      sha256: "4188706108906f002b3a293509234588823c8c979dc83304e229ff400c996b05"
+      sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27"
       url: "https://pub.dev"
     source: hosted
-    version: "0.4.2"
+    version: "0.5.1"
   win32:
     dependency: transitive
     description:
       name: win32
-      sha256: "8cb58b45c47dcb42ab3651533626161d6b67a2921917d8d429791f76972b3480"
+      sha256: "0eaf06e3446824099858367950a813472af675116bf63f008a4c2a75ae13e9cb"
       url: "https://pub.dev"
     source: hosted
-    version: "5.3.0"
+    version: "5.5.0"
   xdg_directories:
     dependency: transitive
     description:
@@ -447,4 +439,4 @@ packages:
     version: "1.0.4"
 sdks:
   dart: ">=3.3.0 <4.0.0"
-  flutter: ">=3.16.0"
+  flutter: ">=3.19.0"
diff --git a/pubspec.yaml b/pubspec.yaml
index 5c4cd59b3a02df9bff6342803c1f8201562af795..5c638793da858ad6a393a3f36a889d1a87ab3897 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,11 +1,12 @@
 name: solitaire
 description: Solitaire Game
 
-publish_to: 'none'
-version: 0.0.17+17
+publish_to: "none"
+
+version: 0.0.18+18
 
 environment:
-  sdk: '^3.0.0'
+  sdk: "^3.0.0"
 
 dependencies:
   flutter:
@@ -16,16 +17,12 @@ dependencies:
   flutter_bloc: ^8.1.1
   hive: ^2.2.3
   hydrated_bloc: ^9.0.0
-  overlay_support: ^2.1.0
-  provider: ^6.0.5
-  shared_preferences: ^2.2.1
-  package_info_plus: ^5.0.1
-  path: ^1.9.0
+  package_info_plus: ^8.0.0
   path_provider: ^2.0.11
   unicons: ^2.1.1
 
 dev_dependencies:
-  flutter_lints: ^3.0.1
+  flutter_lints: ^4.0.0
 
 flutter:
   uses-material-design: true
@@ -45,4 +42,3 @@ flutter:
           weight: 400
         - asset: assets/fonts/Nunito-Light.ttf
           weight: 300
-