diff --git a/android/app/build.gradle b/android/app/build.gradle
index 9a2e79e826f9d67385255e09b0072a84f988b6a5..4cb92c930eb8d23153d82b7143a74c5e85c9e724 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.colors"
 
     defaultConfig {
diff --git a/android/gradle.properties b/android/gradle.properties
index 604fc088e204d265443088fe8d1680c63a2b132f..c8bbff9bd599a7c3ffbe76de5a61ead3de90631a 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.38
-app.versionCode=38
+app.versionName=0.0.39
+app.versionCode=39
diff --git a/assets/icons/colors_5.png b/assets/icons/colors_5.png
deleted file mode 100644
index dd0a276e105a79aa25ca36f6cc4d2f69c77df81f..0000000000000000000000000000000000000000
Binary files a/assets/icons/colors_5.png and /dev/null differ
diff --git a/assets/icons/colors_6.png b/assets/icons/colors_6.png
deleted file mode 100644
index 2a63916ed00f0570bedd1647e34706d041fbec44..0000000000000000000000000000000000000000
Binary files a/assets/icons/colors_6.png and /dev/null differ
diff --git a/assets/icons/colors_7.png b/assets/icons/colors_7.png
deleted file mode 100644
index fdc1669a1d89ed225cc4624319ff01558ab987b4..0000000000000000000000000000000000000000
Binary files a/assets/icons/colors_7.png and /dev/null differ
diff --git a/assets/icons/colors_8.png b/assets/icons/colors_8.png
deleted file mode 100644
index b660ef3e29aefc5c940a327aaf7a22d76a73bb23..0000000000000000000000000000000000000000
Binary files a/assets/icons/colors_8.png and /dev/null differ
diff --git a/assets/icons/level_easy.png b/assets/icons/level_easy.png
deleted file mode 100644
index aa9e2485272c12fd99d9e1faae5d71d027ee5431..0000000000000000000000000000000000000000
Binary files a/assets/icons/level_easy.png and /dev/null differ
diff --git a/assets/icons/level_hard.png b/assets/icons/level_hard.png
deleted file mode 100644
index 433c686b984fd22c4966def3dedcaf7384951810..0000000000000000000000000000000000000000
Binary files a/assets/icons/level_hard.png and /dev/null differ
diff --git a/assets/icons/level_medium.png b/assets/icons/level_medium.png
deleted file mode 100644
index 213f2ca844afb0cea47cc4bdd1b865433b068b59..0000000000000000000000000000000000000000
Binary files a/assets/icons/level_medium.png and /dev/null differ
diff --git a/assets/icons/level_nightmare.png b/assets/icons/level_nightmare.png
deleted file mode 100644
index df4182c1e228bbb33c5546d2df38d16ca1edd4f2..0000000000000000000000000000000000000000
Binary files a/assets/icons/level_nightmare.png and /dev/null differ
diff --git a/assets/icons/size_extra.png b/assets/icons/size_extra.png
deleted file mode 100644
index d3401d9dd4df7a871eb7ac88592707f63480d0dc..0000000000000000000000000000000000000000
Binary files a/assets/icons/size_extra.png and /dev/null differ
diff --git a/assets/icons/size_large.png b/assets/icons/size_large.png
deleted file mode 100644
index 18b3420564654a9adf32e5a91d0d41f82fd4e2ce..0000000000000000000000000000000000000000
Binary files a/assets/icons/size_large.png and /dev/null differ
diff --git a/assets/icons/size_medium.png b/assets/icons/size_medium.png
deleted file mode 100644
index 4b4f7754fb46de7cf2ddfc265da900bf77cc0d3e..0000000000000000000000000000000000000000
Binary files a/assets/icons/size_medium.png and /dev/null differ
diff --git a/assets/icons/size_small.png b/assets/icons/size_small.png
deleted file mode 100644
index 2c72840d2dfe2dfb36791973a159869a325de758..0000000000000000000000000000000000000000
Binary files a/assets/icons/size_small.png and /dev/null differ
diff --git a/assets/icons/skin_default.png b/assets/icons/skin_default.png
deleted file mode 100644
index ee53cc12eaad99722e3dd8fadd52e76bdf5ed977..0000000000000000000000000000000000000000
Binary files a/assets/icons/skin_default.png and /dev/null differ
diff --git a/assets/skins/default_0.png b/assets/skins/default_0.png
deleted file mode 100644
index 4d1712540f2a45d43a2aa512132e7274f1daf686..0000000000000000000000000000000000000000
Binary files a/assets/skins/default_0.png and /dev/null differ
diff --git a/assets/skins/default_1.png b/assets/skins/default_1.png
deleted file mode 100644
index 3ca3e7164af5cde6e6750172c2149cb63ebb7165..0000000000000000000000000000000000000000
Binary files a/assets/skins/default_1.png and /dev/null differ
diff --git a/assets/skins/default_2.png b/assets/skins/default_2.png
deleted file mode 100644
index 56ad59eff020c5dd84e9d257ff91c5f8f88e6f33..0000000000000000000000000000000000000000
Binary files a/assets/skins/default_2.png and /dev/null differ
diff --git a/assets/skins/default_3.png b/assets/skins/default_3.png
deleted file mode 100644
index e92c6694a192606905b8119f2a213b8cadf14ba5..0000000000000000000000000000000000000000
Binary files a/assets/skins/default_3.png and /dev/null differ
diff --git a/assets/skins/default_4.png b/assets/skins/default_4.png
deleted file mode 100644
index 74feaa46de20c31c30e28c8c1dd96d5bff212f02..0000000000000000000000000000000000000000
Binary files a/assets/skins/default_4.png and /dev/null differ
diff --git a/assets/skins/default_5.png b/assets/skins/default_5.png
deleted file mode 100644
index abcf897497ebc0ccab435b576985dd854be011fe..0000000000000000000000000000000000000000
Binary files a/assets/skins/default_5.png and /dev/null differ
diff --git a/assets/skins/default_6.png b/assets/skins/default_6.png
deleted file mode 100644
index aee88ace319e14392688b29f92fa0da137bb4339..0000000000000000000000000000000000000000
Binary files a/assets/skins/default_6.png and /dev/null differ
diff --git a/assets/skins/default_7.png b/assets/skins/default_7.png
deleted file mode 100644
index 3e0ac15c6eea57e437afc36ebf81a618b342256e..0000000000000000000000000000000000000000
Binary files a/assets/skins/default_7.png and /dev/null differ
diff --git a/assets/skins/default_8.png b/assets/skins/default_8.png
deleted file mode 100644
index 70b58df7443e74de8523829600b4c6cc19eab5a9..0000000000000000000000000000000000000000
Binary files a/assets/skins/default_8.png and /dev/null differ
diff --git a/assets/translations/en.json b/assets/translations/en.json
index c40bf79ffe85272000814513df69af38c0612b16..92299163019c59771191b4b86fb4a41f0ece93f1 100644
--- a/assets/translations/en.json
+++ b/assets/translations/en.json
@@ -1,8 +1,6 @@
 {
   "app_name": "Colors",
 
-  "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 895e185dafe2587e69063bc03ed5fcd1f8dcc27d..dc7d503692165e64de23d0191442b6ada8bacb6d 100644
--- a/assets/translations/fr.json
+++ b/assets/translations/fr.json
@@ -1,8 +1,6 @@
 {
   "app_name": "Colors",
 
-  "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/39.txt b/fastlane/metadata/android/en-US/changelogs/39.txt
new file mode 100644
index 0000000000000000000000000000000000000000..9bb4c4dee10043312bc54a49a258422743bdc041
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/39.txt
@@ -0,0 +1 @@
+Improve application architecture.
diff --git a/fastlane/metadata/android/fr-FR/changelogs/39.txt b/fastlane/metadata/android/fr-FR/changelogs/39.txt
new file mode 100644
index 0000000000000000000000000000000000000000..5face79935538bfb3371042404b6c3586cc87f31
--- /dev/null
+++ b/fastlane/metadata/android/fr-FR/changelogs/39.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 1817ed00997b8351cf7772ac11dc7dc3c75cde5d..7ea6ed5d23526aa94c9626826ffd4545141a1674 100755
--- a/icons/build_game_icons.sh
+++ b/icons/build_game_icons.sh
@@ -22,31 +22,6 @@ AVAILABLE_GAME_IMAGES="
   game_win
 "
 
-# Settings images
-AVAILABLES_GAME_SETTINGS="
-  colors:5,6,7,8
-  level:easy,medium,hard,nightmare
-  size:small,medium,large,extra
-"
-
-# Skins
-AVAILABLE_SKINS="
-  default
-"
-
-# Images per skin
-SKIN_IMAGES="
-  0
-  1
-  2
-  3
-  4
-  5
-  6
-  7
-  8
-"
-
 #######################################################
 
 # optimize svg
@@ -89,41 +64,13 @@ 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
-    build_icon ${CURRENT_DIR}/skins/${SKIN_CODE}/${SKIN_IMAGE}.svg ${ASSETS_DIR}/skins/${SKIN_CODE}_${SKIN_IMAGE}.png
-  done
-}
-
 #######################################################
 
 # Create output folders
 mkdir -p ${ASSETS_DIR}/icons
-mkdir -p ${ASSETS_DIR}/skins
 
 # Delete existing generated images
 find ${ASSETS_DIR}/icons -type f -name "*.png" -delete
-find ${ASSETS_DIR}/skins -type f -name "*.png" -delete
 
 # build game images
 for GAME_IMAGE in ${AVAILABLE_GAME_IMAGES}
@@ -131,14 +78,3 @@ 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
-  build_icon_for_skin "${SKIN}"
-done
diff --git a/icons/colors_5.svg b/icons/colors_5.svg
deleted file mode 100644
index 2f218e9986906d5f873c0ff7dbfce088b3a102bf..0000000000000000000000000000000000000000
--- a/icons/colors_5.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="#97c05c" stroke="#000" stroke-width="2"/><g transform="translate(-1.0061 .33115)" aria-label="5"><path d="m63.315 55.063q0 2.2656-0.85938 4.2188-0.83984 1.9336-2.4609 3.3203-1.7969 1.4844-4.1406 2.207-2.3242 0.70312-5.3125 0.70312-3.4961-0.01953-5.918-0.56641-2.4023-0.52734-3.9258-1.1914v-6.4258h0.82031q1.7773 1.0547 3.8281 1.7578t4.082 0.70312q1.2305 0 2.6562-0.27344 1.4453-0.29297 2.2852-1.0352 0.66406-0.60547 0.99609-1.2305 0.35156-0.625 0.35156-1.9336 0-1.0156-0.46875-1.7383-0.44922-0.74219-1.1719-1.1914-1.0547-0.64453-2.5391-0.83984-1.4844-0.21484-2.6953-0.21484-1.7578 0-3.3789 0.3125-1.6016 0.29297-2.8125 0.58594h-0.85938v-16.406h20.684v5.5664h-13.633v4.7461q0.60547-0.03906 1.5234-0.05859 0.9375-0.03906 1.6406-0.03906 2.4023 0 4.2773 0.46875 1.8945 0.44922 3.2617 1.2695 1.7773 1.0742 2.7734 2.8516 0.99609 1.7578 0.99609 4.4336z"/></g><rect x="67.01" y="67.01" width="29.323" height="29.323" fill="#ff6f43" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="67.01" y="36.339" width="29.323" height="29.323" fill="#ffce2c" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="67.01" y="5.6672" width="29.323" height="29.323" fill="#359c35" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="36.339" y="5.6672" width="29.323" height="29.323" fill="#708cfd" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="5.6671" y="5.6672" width="29.323" height="29.323" fill="#e63a3f" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/></svg>
diff --git a/icons/colors_6.svg b/icons/colors_6.svg
deleted file mode 100644
index 6df1641a1ea326ff73fc5de9229f6722ac9acd11..0000000000000000000000000000000000000000
--- a/icons/colors_6.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="#f29c38" stroke="#000" stroke-width="2"/><g transform="translate(3.8694 .21001)" aria-label="6"><path d="m59.025 55.399q0 2.2461-0.82031 4.2188t-2.3047 3.3203q-1.582 1.4453-3.6719 2.207-2.0703 0.76172-4.8633 0.76172-2.6172 0-4.7852-0.70312-2.1484-0.72266-3.6914-2.1875-1.7773-1.6797-2.7148-4.3359t-0.9375-6.3477q0-3.8281 0.87891-6.7969t2.8711-5.2539q1.9141-2.1875 4.9609-3.3984 3.0664-1.2109 7.2852-1.2109 1.4258 0 3.125 0.19531t2.207 0.29297v5.7227h-0.74219q-0.52734-0.25391-1.7969-0.56641-1.25-0.33203-2.8516-0.33203-3.75 0-5.8398 1.8359t-2.5195 5.1172q1.5039-0.89844 3.1641-1.4453 1.6797-0.56641 3.6133-0.56641 1.6992 0 3.1445 0.39062 1.4648 0.39062 2.7148 1.25 1.6211 1.1328 2.5977 3.0469 0.97656 1.9141 0.97656 4.7852zm-8.8867 4.3945q0.60547-0.66406 0.95703-1.5625 0.37109-0.91797 0.37109-2.4805 0-1.4258-0.41016-2.3242-0.41016-0.91797-1.1328-1.4648-0.70312-0.54688-1.6602-0.74219-0.95703-0.21484-1.9727-0.21484-0.85938 0-1.7969 0.19531-0.9375 0.19531-1.7188 0.48828 0 0.19531-0.01953 0.64453t-0.01953 1.1328q0 2.4023 0.46875 3.9648 0.48828 1.543 1.2891 2.3633 0.54688 0.60547 1.2891 0.89844 0.74219 0.27344 1.6016 0.27344 0.64453 0 1.4258-0.29297t1.3281-0.87891z"/></g><rect x="36.339" y="67.01" width="29.323" height="29.323" fill="#a13cb1" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="67.01" y="67.01" width="29.323" height="29.323" fill="#ff6f43" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="67.01" y="36.339" width="29.323" height="29.323" fill="#ffce2c" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="67.01" y="5.6672" width="29.323" height="29.323" fill="#359c35" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="36.339" y="5.6672" width="29.323" height="29.323" fill="#708cfd" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="5.6671" y="5.6672" width="29.323" height="29.323" fill="#e63a3f" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/></svg>
diff --git a/icons/colors_7.svg b/icons/colors_7.svg
deleted file mode 100644
index 7870bc74ae13133a080de2f02397413b9d611458..0000000000000000000000000000000000000000
--- a/icons/colors_7.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="#cd5542" stroke="#000" stroke-width="2"/><g transform="translate(3.9378 .2393)" aria-label="7"><path d="m58.459 42.001-13.164 23.301h-8.3594l13.672-23.516h-14.941v-5.5664h22.793z"/></g><rect x="5.6671" y="67.01" width="29.323" height="29.323" fill="#38ffff" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="36.339" y="67.01" width="29.323" height="29.323" fill="#a13cb1" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="67.01" y="67.01" width="29.323" height="29.323" fill="#ff6f43" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="67.01" y="36.339" width="29.323" height="29.323" fill="#ffce2c" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="67.01" y="5.6672" width="29.323" height="29.323" fill="#359c35" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="36.339" y="5.6672" width="29.323" height="29.323" fill="#708cfd" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="5.6671" y="5.6672" width="29.323" height="29.323" fill="#e63a3f" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/></svg>
diff --git a/icons/colors_8.svg b/icons/colors_8.svg
deleted file mode 100644
index 37f394909f7ecc1b5e53a34c304d99742ce6c149..0000000000000000000000000000000000000000
--- a/icons/colors_8.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="#6041b0" stroke="#000" stroke-width="2"/><g transform="translate(4.1624 .2393)" aria-label="8"><path d="m59.123 57.177q0 3.8672-3.3008 6.3281-3.2812 2.4609-9.0234 2.4609-3.2227 0-5.5273-0.66406-2.3047-0.66406-3.8086-1.8359-1.4844-1.1523-2.207-2.6953-0.70312-1.543-0.70312-3.3203 0-2.1875 1.2695-3.8672 1.2891-1.6992 4.4336-2.9688v-0.11719q-2.5391-1.1719-3.7305-2.9492t-1.1914-4.1211q0-3.457 3.2031-5.6641 3.2031-2.207 8.3398-2.207 5.3906 0 8.4375 2.0117 3.0664 1.9922 3.0664 5.332 0 2.0703-1.2891 3.6914t-3.9453 2.7539v0.11719q3.0469 1.1523 4.5117 3.1055t1.4648 4.6094zm-8.0664-13.438q0-1.4844-1.1523-2.3633-1.1328-0.87891-3.0273-0.87891-0.70312 0-1.4453 0.17578-0.72266 0.17578-1.3281 0.50781-0.56641 0.33203-0.9375 0.87891-0.37109 0.52734-0.37109 1.2109 0 1.1523 0.64453 1.7969 0.66406 0.64453 2.1484 1.2891 0.54688 0.23438 1.4844 0.58594 0.95703 0.33203 2.3047 0.76172 0.89844-1.0547 1.2891-1.8945 0.39062-0.83984 0.39062-2.0703zm0.60547 13.77q0-1.4062-0.70312-2.1289t-2.8906-1.6602q-0.64453-0.29297-1.875-0.72266-1.2305-0.42969-2.0703-0.74219-0.83984 0.76172-1.5234 1.8555-0.66406 1.0742-0.66406 2.4219 0 2.0312 1.4453 3.2422 1.4648 1.1914 3.8086 1.1914 0.625 0 1.4648-0.17578 0.83984-0.19531 1.4453-0.58594 0.70312-0.44922 1.1328-1.0547 0.42969-0.60547 0.42969-1.6406z"/></g><rect x="5.6671" y="36.339" width="29.323" height="29.323" fill="#f2739d" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="5.6671" y="67.01" width="29.323" height="29.323" fill="#38ffff" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="36.339" y="67.01" width="29.323" height="29.323" fill="#a13cb1" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="67.01" y="67.01" width="29.323" height="29.323" fill="#ff6f43" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="67.01" y="36.339" width="29.323" height="29.323" fill="#ffce2c" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="67.01" y="5.6672" width="29.323" height="29.323" fill="#359c35" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="36.339" y="5.6672" width="29.323" height="29.323" fill="#708cfd" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="5.6671" y="5.6672" width="29.323" height="29.323" fill="#e63a3f" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/></svg>
diff --git a/icons/level_easy.svg b/icons/level_easy.svg
deleted file mode 100644
index 30048ce976f10fba1ad4233115035786a65d35de..0000000000000000000000000000000000000000
--- a/icons/level_easy.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="#97c05c" stroke="#000" stroke-width="2"/><path d="m50.952 32.393c1.3622-0.0046 4.9652 11.398 6.07 12.195 1.1048 0.79696 13.062 0.61914 13.487 1.9133s-9.3059 8.2444-9.7225 9.5414c-0.41657 1.297 3.4475 12.614 2.3481 13.418-1.0993 0.80441-10.717-6.3028-12.079-6.2982-1.3622 0.0046-10.931 7.1767-12.036 6.3797s2.6827-12.14 2.2574-13.434c-0.42533-1.2941-10.203-8.1785-9.7868-9.4754 0.41657-1.297 12.375-1.2 13.474-2.0044s4.6252-12.231 5.9874-12.236z" fill="#fff" stroke="#030303" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="6" stroke-width="3.3"/></svg>
diff --git a/icons/level_hard.svg b/icons/level_hard.svg
deleted file mode 100644
index 976249e8b0d2274b791d00e128be518d29a03731..0000000000000000000000000000000000000000
--- a/icons/level_hard.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="#cd5542" stroke="#000" stroke-width="2"/><path d="m28.065 11.952c1.3622-0.0046 4.9652 11.398 6.07 12.195 1.1048 0.79696 13.062 0.61914 13.487 1.9133s-9.3059 8.2444-9.7225 9.5414c-0.41657 1.297 3.4475 12.614 2.3481 13.418-1.0993 0.80441-10.717-6.3028-12.079-6.2982-1.3622 0.0046-10.931 7.1767-12.036 6.3797s2.6827-12.14 2.2574-13.434c-0.42533-1.2941-10.203-8.1785-9.7868-9.4754 0.41657-1.297 12.375-1.2 13.474-2.0044s4.6252-12.231 5.9874-12.236z" fill="#fff" stroke="#010101" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="6" stroke-width="3.3"/><path d="m73.839 11.952c1.3622-0.0046 4.9652 11.398 6.07 12.195s13.062 0.61914 13.487 1.9133c0.42533 1.2941-9.3059 8.2444-9.7225 9.5414-0.41657 1.297 3.4475 12.614 2.3481 13.418-1.0993 0.80441-10.717-6.3028-12.079-6.2982-1.3622 0.0046-10.931 7.1767-12.036 6.3797s2.6827-12.14 2.2574-13.434c-0.42533-1.2941-10.203-8.1785-9.7868-9.4754 0.41657-1.297 12.375-1.2 13.474-2.0044 1.0993-0.80441 4.6252-12.231 5.9874-12.236z" fill="#fff" stroke="#010101" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="6" stroke-width="3.3"/><path d="m50.952 52.835c1.3622-0.0046 4.9652 11.398 6.07 12.195 1.1048 0.79696 13.062 0.61914 13.487 1.9133 0.42533 1.2941-9.3059 8.2444-9.7225 9.5414-0.41657 1.297 3.4475 12.614 2.3481 13.418-1.0993 0.80441-10.717-6.3028-12.079-6.2982-1.3622 5e-3 -10.931 7.1767-12.036 6.3797s2.6827-12.14 2.2574-13.434-10.203-8.1785-9.7868-9.4754c0.41657-1.297 12.375-1.2 13.474-2.0044 1.0993-0.80442 4.6252-12.231 5.9874-12.236z" fill="#fff" stroke="#010101" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="6" stroke-width="3.3"/></svg>
diff --git a/icons/level_medium.svg b/icons/level_medium.svg
deleted file mode 100644
index e70fd60d179b05a0db5701e4b7858c214887c6be..0000000000000000000000000000000000000000
--- a/icons/level_medium.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="#f29c38" stroke="#000" stroke-width="2"/><path d="m27.72 32.393c1.3622-0.0046 4.9652 11.398 6.07 12.195 1.1048 0.79696 13.062 0.61914 13.487 1.9133s-9.3059 8.2444-9.7225 9.5414c-0.41657 1.297 3.4475 12.614 2.3481 13.418-1.0993 0.80441-10.717-6.3028-12.079-6.2982-1.3622 0.0046-10.931 7.1767-12.036 6.3797s2.6827-12.14 2.2574-13.434c-0.42533-1.2941-10.203-8.1785-9.7868-9.4754 0.41657-1.297 12.375-1.2 13.474-2.0044s4.6252-12.231 5.9874-12.236z" fill="#fff" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="6" stroke-width="3.3"/><path d="m74.183 32.393c1.3622-0.0046 4.9652 11.398 6.07 12.195s13.062 0.61914 13.487 1.9133-9.3059 8.2444-9.7225 9.5414c-0.41656 1.297 3.4475 12.614 2.3482 13.418-1.0994 0.80441-10.717-6.3028-12.079-6.2982-1.3622 0.0046-10.931 7.1767-12.036 6.3797-1.1048-0.79696 2.6827-12.14 2.2574-13.434s-10.203-8.1785-9.7868-9.4754c0.41657-1.297 12.375-1.2 13.474-2.0044 1.0993-0.80441 4.6252-12.231 5.9874-12.236z" fill="#fff" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="6" stroke-width="3.3"/></svg>
diff --git a/icons/level_nightmare.svg b/icons/level_nightmare.svg
deleted file mode 100644
index 87f28a3defc23c6fe95980cb376efbf56d6885cc..0000000000000000000000000000000000000000
--- a/icons/level_nightmare.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="#6041b0" stroke="#000" stroke-width="2"/><path d="m28.929 11.793c1.3622-0.0046 4.9652 11.398 6.07 12.195 1.1048 0.79696 13.062 0.61914 13.487 1.9133s-9.3059 8.2444-9.7225 9.5414c-0.41657 1.297 3.4475 12.614 2.3481 13.418-1.0993 0.80442-10.717-6.3028-12.079-6.2982-1.3622 0.0046-10.931 7.1767-12.036 6.3797-1.1048-0.79696 2.6827-12.14 2.2574-13.434-0.42533-1.2941-10.203-8.1785-9.7868-9.4754 0.41657-1.297 12.375-1.2 13.474-2.0044 1.0993-0.80441 4.6252-12.231 5.9874-12.236z" fill="#fff" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="6" stroke-width="3.3"/><path d="m73.125 11.861c1.3622-0.0046 4.9652 11.398 6.07 12.195 1.1048 0.79696 13.062 0.61914 13.487 1.9133 0.42533 1.2941-9.3059 8.2444-9.7225 9.5414-0.41657 1.297 3.4475 12.614 2.3481 13.418-1.0993 0.80441-10.717-6.3028-12.079-6.2982-1.3622 0.0046-10.931 7.1767-12.036 6.3797s2.6827-12.14 2.2574-13.434-10.203-8.1785-9.7868-9.4754c0.41657-1.297 12.375-1.2 13.474-2.0044 1.0993-0.80442 4.6252-12.231 5.9874-12.236z" fill="#fff" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="6" stroke-width="3.3"/><path d="m28.778 52.923c1.3622-0.0046 4.9652 11.398 6.07 12.195 1.1048 0.79696 13.062 0.61914 13.487 1.9133 0.42533 1.2941-9.3059 8.2444-9.7225 9.5414s3.4475 12.614 2.3481 13.418c-1.0993 0.80442-10.717-6.3028-12.079-6.2982-1.3622 5e-3 -10.931 7.1767-12.036 6.3797-1.1048-0.79697 2.6827-12.14 2.2574-13.434-0.42533-1.2941-10.203-8.1785-9.7868-9.4754s12.375-1.2 13.474-2.0044c1.0993-0.80441 4.6252-12.231 5.9874-12.236z" fill="#fff" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="6" stroke-width="3.3"/><path d="m73.104 52.992c1.3622-0.0046 4.9652 11.398 6.07 12.195 1.1048 0.79696 13.062 0.61914 13.487 1.9133s-9.3059 8.2444-9.7225 9.5414c-0.41657 1.297 3.4475 12.614 2.3481 13.418-1.0993 0.80442-10.717-6.3028-12.079-6.2982-1.3622 5e-3 -10.931 7.1767-12.036 6.3797-1.1048-0.79697 2.6827-12.14 2.2574-13.434-0.42533-1.2941-10.203-8.1785-9.7868-9.4754s12.375-1.2 13.474-2.0044c1.0993-0.80441 4.6252-12.231 5.9874-12.236z" fill="#fff" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="6" stroke-width="3.3"/></svg>
diff --git a/icons/size_extra.svg b/icons/size_extra.svg
deleted file mode 100644
index fe07dfb952480afa9c7c9e0ab2af9879f9b2ad6a..0000000000000000000000000000000000000000
--- a/icons/size_extra.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="0" fill="#5f41af" stroke="#000" stroke-width="2"/>
-  <g transform="translate(4.4197 1.4084)" fill="#fff" stroke="#282828" stroke-linecap="round" stroke-width="3"><rect x="13.796" y="16.807" width="12.714" height="12.714"/><rect x="26.51" y="16.807" width="12.714" height="12.714"/><rect x="39.223" y="16.807" width="12.714" height="12.714"/><rect x="51.937" y="16.807" width="12.714" height="12.714"/><rect x="64.651" y="16.807" width="12.714" height="12.714"/><rect x="13.796" y="29.521" width="12.714" height="12.714"/><rect x="26.51" y="29.521" width="12.714" height="12.714"/><rect x="39.223" y="29.521" width="12.714" height="12.714"/><rect x="51.937" y="29.521" width="12.714" height="12.714"/><rect x="64.651" y="29.521" width="12.714" height="12.714"/><rect x="13.796" y="42.235" width="12.714" height="12.714"/><rect x="26.51" y="42.235" width="12.714" height="12.714"/><rect x="39.223" y="42.235" width="12.714" height="12.714"/><rect x="51.937" y="42.235" width="12.714" height="12.714"/><rect x="64.651" y="42.235" width="12.714" height="12.714"/><rect x="13.796" y="54.948" width="12.714" height="12.714"/><rect x="26.51" y="54.948" width="12.714" height="12.714"/><rect x="39.223" y="54.948" width="12.714" height="12.714"/><rect x="51.937" y="54.948" width="12.714" height="12.714"/><rect x="64.651" y="54.948" width="12.714" height="12.714"/><rect x="13.796" y="67.662" width="12.714" height="12.714"/><rect x="26.51" y="67.662" width="12.714" height="12.714"/><rect x="39.223" y="67.662" width="12.714" height="12.714"/><rect x="51.937" y="67.662" width="12.714" height="12.714"/><rect x="64.651" y="67.662" width="12.714" height="12.714"/></g></svg>
diff --git a/icons/size_large.svg b/icons/size_large.svg
deleted file mode 100644
index 174a5301a12bf2137b6e5de4cb2431d56ee4f660..0000000000000000000000000000000000000000
--- a/icons/size_large.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="0" fill="#cd5542" stroke="#000" stroke-width="2"/>
-  <g transform="translate(6.2763 8.2075)" fill="#fff" stroke="#282828" stroke-linecap="round" stroke-width="3"><rect x="18.296" y="16.365" width="12.714" height="12.714"/><rect x="31.01" y="16.365" width="12.714" height="12.714"/><rect x="43.724" y="16.365" width="12.714" height="12.714"/><rect x="56.437" y="16.365" width="12.714" height="12.714"/><rect x="18.296" y="29.079" width="12.714" height="12.714"/><rect x="31.01" y="29.079" width="12.714" height="12.714"/><rect x="43.724" y="29.079" width="12.714" height="12.714"/><rect x="56.437" y="29.079" width="12.714" height="12.714"/><rect x="18.296" y="41.792" width="12.714" height="12.714"/><rect x="31.01" y="41.792" width="12.714" height="12.714"/><rect x="43.724" y="41.792" width="12.714" height="12.714"/><rect x="56.437" y="41.792" width="12.714" height="12.714"/><rect x="18.296" y="54.506" width="12.714" height="12.714"/><rect x="31.01" y="54.506" width="12.714" height="12.714"/><rect x="43.724" y="54.506" width="12.714" height="12.714"/><rect x="56.437" y="54.506" width="12.714" height="12.714"/></g></svg>
diff --git a/icons/size_medium.svg b/icons/size_medium.svg
deleted file mode 100644
index bcc2fbaa18cd06829e8f6cfd8ab460c699929e9a..0000000000000000000000000000000000000000
--- a/icons/size_medium.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="0" fill="#f29c38" stroke="#000" stroke-width="2"/>
-  <g transform="translate(11.967 8.1117)" fill="#fff" stroke="#282828" stroke-linecap="round" stroke-width="3"><rect x="18.962" y="22.818" width="12.714" height="12.714"/><rect x="31.676" y="22.818" width="12.714" height="12.714"/><rect x="44.389" y="22.818" width="12.714" height="12.714"/><rect x="18.962" y="35.531" width="12.714" height="12.714"/><rect x="31.676" y="35.531" width="12.714" height="12.714"/><rect x="44.389" y="35.531" width="12.714" height="12.714"/><rect x="18.962" y="48.245" width="12.714" height="12.714"/><rect x="31.676" y="48.245" width="12.714" height="12.714"/><rect x="44.389" y="48.245" width="12.714" height="12.714"/></g></svg>
diff --git a/icons/size_small.svg b/icons/size_small.svg
deleted file mode 100644
index 1ccb6e958123c30999e47b54e784a398205c55d0..0000000000000000000000000000000000000000
--- a/icons/size_small.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="0" fill="#97c05c" stroke="#000" stroke-width="2"/>
-  <g transform="translate(8.8715 12.603)" fill="#fff" stroke="#282828" stroke-linecap="round" stroke-width="3"><rect x="28.415" y="24.683" width="12.714" height="12.714"/><rect x="41.128" y="24.683" width="12.714" height="12.714"/><rect x="28.415" y="37.397" width="12.714" height="12.714"/><rect x="41.128" y="37.397" width="12.714" height="12.714"/></g></svg>
diff --git a/icons/skin_default.svg b/icons/skin_default.svg
deleted file mode 100644
index 18ae839e20048fd621cd23dcac1eabb5f9200223..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="#a4a4a4" stroke="#000" stroke-width="2"/><rect x="-15.387" y="-20.515" width="100" height="100" ry="2" fill="none"/><rect x="5.6673" y="36.339" width="29.323" height="29.323" fill="#f2739d" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="5.6673" y="67.01" width="29.323" height="29.323" fill="#38ffff" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="36.339" y="67.01" width="29.323" height="29.323" fill="#a13cb1" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="67.01" y="67.01" width="29.323" height="29.323" fill="#ff6f43" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="67.01" y="36.339" width="29.323" height="29.323" fill="#ffce2c" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="67.01" y="5.6674" width="29.323" height="29.323" fill="#359c35" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="36.339" y="5.6674" width="29.323" height="29.323" fill="#708cfd" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="5.6673" y="5.6674" width="29.323" height="29.323" fill="#e63a3f" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/></svg>
diff --git a/icons/skins/default/0.svg b/icons/skins/default/0.svg
deleted file mode 100644
index 87a62b1523130f2b611695653a326a4939b1909a..0000000000000000000000000000000000000000
--- a/icons/skins/default/0.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 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="2" fill="none"/><rect width="100" height="100" fill="#fff" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width="0"/></svg>
diff --git a/icons/skins/default/1.svg b/icons/skins/default/1.svg
deleted file mode 100644
index 11201e50147d415106bc969cec7b0f0b7d315fc1..0000000000000000000000000000000000000000
--- a/icons/skins/default/1.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 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="2" fill="none"/><rect width="100" height="100" fill="#E63A3F" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width="0"/></svg>
diff --git a/icons/skins/default/2.svg b/icons/skins/default/2.svg
deleted file mode 100644
index 76e07b77bc5bd1d7ba3f486b3da5c9e5bbd166bb..0000000000000000000000000000000000000000
--- a/icons/skins/default/2.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 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="2" fill="none"/><rect width="100" height="100" fill="#708CFD" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width="0"/></svg>
diff --git a/icons/skins/default/3.svg b/icons/skins/default/3.svg
deleted file mode 100644
index 092dab6667d3016fbf5f131dba44a3d32533d16e..0000000000000000000000000000000000000000
--- a/icons/skins/default/3.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 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="2" fill="none"/><rect width="100" height="100" fill="#359C35" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width="0"/></svg>
diff --git a/icons/skins/default/4.svg b/icons/skins/default/4.svg
deleted file mode 100644
index 57094f502ffe53094c4394f0a8bd56d3748eed63..0000000000000000000000000000000000000000
--- a/icons/skins/default/4.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 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="2" fill="none"/><rect width="100" height="100" fill="#FFCE2C" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width="0"/></svg>
diff --git a/icons/skins/default/5.svg b/icons/skins/default/5.svg
deleted file mode 100644
index e0f4d96e14d57b85fe4fbff8dd294d1896582043..0000000000000000000000000000000000000000
--- a/icons/skins/default/5.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 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="2" fill="none"/><rect width="100" height="100" fill="#FF6F43" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width="0"/></svg>
diff --git a/icons/skins/default/6.svg b/icons/skins/default/6.svg
deleted file mode 100644
index feb210edab0ed136cd3aca43b944f8c5a3a83755..0000000000000000000000000000000000000000
--- a/icons/skins/default/6.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 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="2" fill="none"/><rect width="100" height="100" fill="#A13CB1" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width="0"/></svg>
diff --git a/icons/skins/default/7.svg b/icons/skins/default/7.svg
deleted file mode 100644
index 2b9d0858288a90281d0f9a4184c895da3bb5c3b7..0000000000000000000000000000000000000000
--- a/icons/skins/default/7.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 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="2" fill="none"/><rect width="100" height="100" fill="#38FFFF" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width="0"/></svg>
diff --git a/icons/skins/default/8.svg b/icons/skins/default/8.svg
deleted file mode 100644
index 40b80922783bfa5a4a183eaa14a47fdc7f7a4533..0000000000000000000000000000000000000000
--- a/icons/skins/default/8.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 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="2" fill="none"/><rect width="100" height="100" fill="#F2739D" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width="2.5e-7"/></svg>
diff --git a/lib/config/default_game_settings.dart b/lib/config/default_game_settings.dart
new file mode 100644
index 0000000000000000000000000000000000000000..db8841295f53570f90f2a50ea1e6abbca2ac2403
--- /dev/null
+++ b/lib/config/default_game_settings.dart
@@ -0,0 +1,81 @@
+import 'package:colors/utils/tools.dart';
+
+class DefaultGameSettings {
+  // available game parameters codes
+  static const String parameterCodeDifficultyLevel = 'difficultyLevel';
+  static const String parameterCodeBoardSize = 'boardSize';
+  static const String parameterCodeColorsCount = 'colorsCount';
+  static const List<String> availableParameters = [
+    parameterCodeDifficultyLevel,
+    parameterCodeBoardSize,
+    parameterCodeColorsCount,
+  ];
+
+  // difficulty level: available values
+  static const String difficultyLevelValueEasy = 'easy';
+  static const String difficultyLevelValueMedium = 'medium';
+  static const String difficultyLevelValueHard = 'hard';
+  static const String difficultyLevelValueNightmare = 'nightmare';
+  static const List<String> allowedDifficultyLevelValues = [
+    difficultyLevelValueEasy,
+    difficultyLevelValueMedium,
+    difficultyLevelValueHard,
+    difficultyLevelValueNightmare,
+  ];
+  // difficulty level: default value
+  static const String defaultDifficultyLevelValue = difficultyLevelValueMedium;
+
+  // board size: available values
+  static const String boardSizeValueSmall = 'small';
+  static const String boardSizeValueMedium = 'medium';
+  static const String boardSizeValueLarge = 'large';
+  static const String boardSizeValueExtra = 'extra';
+  static const List<String> allowedBoardSizeValues = [
+    boardSizeValueSmall,
+    boardSizeValueMedium,
+    boardSizeValueLarge,
+    boardSizeValueExtra,
+  ];
+  // board size: default value
+  static const String defaultBoardSizeValue = boardSizeValueMedium;
+
+  // colors count: available values
+  static const String colorsCountValueLow = '5';
+  static const String colorsCountValueMedium = '6';
+  static const String colorsCountValueHigh = '7';
+  static const String colorsCountValueVeryHigh = '8';
+  static const List<String> allowedColorsCountValues = [
+    colorsCountValueLow,
+    colorsCountValueMedium,
+    colorsCountValueHigh,
+    colorsCountValueVeryHigh,
+  ];
+  // colors count: default value
+  static const String defaultColorsCountValue = colorsCountValueMedium;
+
+  // available values from parameter code
+  static List<String> getAvailableValues(String parameterCode) {
+    switch (parameterCode) {
+      case parameterCodeDifficultyLevel:
+        return DefaultGameSettings.allowedDifficultyLevelValues;
+      case parameterCodeBoardSize:
+        return DefaultGameSettings.allowedBoardSizeValues;
+      case parameterCodeColorsCount:
+        return DefaultGameSettings.allowedColorsCountValues;
+    }
+
+    printlog('Did not find any available value for game parameter "$parameterCode".');
+    return [];
+  }
+
+  static int getMovesCountLimitDeltaFromLevelCode(String parameterLevel) {
+    const Map<String, int> values = {
+      difficultyLevelValueEasy: 5,
+      difficultyLevelValueMedium: 3,
+      difficultyLevelValueHard: 1,
+      difficultyLevelValueNightmare: -1,
+    };
+    return values[parameterLevel] ??
+        getMovesCountLimitDeltaFromLevelCode(DefaultGameSettings.defaultDifficultyLevelValue);
+  }
+}
diff --git a/lib/config/default_global_settings.dart b/lib/config/default_global_settings.dart
new file mode 100644
index 0000000000000000000000000000000000000000..3ec1474a9af61c014e5791a793d7205343070dfb
--- /dev/null
+++ b/lib/config/default_global_settings.dart
@@ -0,0 +1,28 @@
+import 'package:colors/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 skinValueColors = 'colors';
+  static const List<String> allowedSkinValues = [
+    skinValueColors,
+  ];
+  // skin: default value
+  static const String defaultSkinValue = skinValueColors;
+
+  // available values from parameter code
+  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 b969ec5c5b74440763eee143c4674cf0a46adffa..2f9395d83564baa03622ecebe7fdc74e7a68c08c 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:colors/ui/screens/about_page.dart';
-import 'package:colors/ui/screens/game_page.dart';
-import 'package:colors/ui/screens/settings_page.dart';
+import 'package:colors/ui/screens/page_about.dart';
+import 'package:colors/ui/screens/page_game.dart';
+import 'package:colors/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..16775c36cca0ee88c6ef2a7470959c51a80dac08
--- /dev/null
+++ b/lib/cubit/game_cubit.dart
@@ -0,0 +1,170 @@
+import 'dart:async';
+import 'dart:math';
+
+import 'package:equatable/equatable.dart';
+import 'package:flutter/foundation.dart';
+import 'package:flutter/material.dart';
+import 'package:hydrated_bloc/hydrated_bloc.dart';
+
+import 'package:colors/models/game.dart';
+import 'package:colors/models/settings_game.dart';
+import 'package:colors/models/settings_global.dart';
+import 'package:colors/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(
+      board: state.currentGame.board,
+      gameSettings: state.currentGame.gameSettings,
+      globalSettings: state.currentGame.globalSettings,
+      isRunning: state.currentGame.isRunning,
+      isFinished: state.currentGame.isFinished,
+      gameWon: state.currentGame.gameWon,
+      movesCount: state.currentGame.movesCount,
+      maxMovesCount: state.currentGame.maxMovesCount,
+      animationInProgress: state.currentGame.animationInProgress,
+      progress: state.currentGame.progress,
+      progressTotal: state.currentGame.progressTotal,
+      progressDelta: state.currentGame.progressDelta,
+    );
+
+    updateState(game);
+  }
+
+  void startNewGame({
+    required GameSettings gameSettings,
+    required GlobalSettings globalSettings,
+  }) {
+    printlog('Starting new game:');
+    printlog('- level: ${gameSettings.difficultyLevel}');
+    printlog('- size: ${gameSettings.parameterSize}');
+    printlog('- colors: ${gameSettings.parameterColorsCount}');
+
+    Game newGame = Game.createNew(
+      gameSettings: gameSettings,
+      globalSettings: globalSettings,
+    );
+
+    newGame.dump();
+
+    updateState(newGame);
+    updateGameIsRunning(true);
+  }
+
+  void quitGame() {
+    state.currentGame.isRunning = false;
+    refresh();
+  }
+
+  void updateCellValue(int col, int row, int value) {
+    state.currentGame.board.cells[row][col].value = value;
+    refresh();
+  }
+
+  void increaseMovesCount() {
+    state.currentGame.movesCount++;
+    refresh();
+  }
+
+  void updateProgressDelta(int progressDelta) {
+    state.currentGame.progressDelta = progressDelta;
+    refresh();
+  }
+
+  void updateProgress(int progress) {
+    state.currentGame.progress = progress;
+    refresh();
+  }
+
+  void updateAnimationInProgress(bool inProgress) {
+    state.currentGame.animationInProgress = inProgress;
+    refresh();
+  }
+
+  void updateGameIsRunning(bool gameIsRunning) {
+    state.currentGame.isRunning = gameIsRunning;
+    refresh();
+  }
+
+  void updateGameIsFinished(bool gameIsFinished) {
+    state.currentGame.isFinished = gameIsFinished;
+    refresh();
+  }
+
+  void updateGameWon(bool gameWon) {
+    state.currentGame.gameWon = gameWon;
+    refresh();
+  }
+
+  fillBoardFromFirstCell(int value) {
+    List<List<int>> cellsToFill = state.currentGame.board.getSiblingFillableCells(0, 0, []);
+    final int progressBeforeMove = cellsToFill.length;
+
+    if (value == state.currentGame.board.getFirstCellValue()) {
+      return;
+    }
+
+    increaseMovesCount();
+
+    // Sort cells from the closest to the furthest, relatively to the top left corner
+    cellsToFill
+        .sort((a, b) => (pow(a[0], 2) + pow(a[1], 2)).compareTo(pow(b[0], 2) + pow(b[1], 2)));
+
+    const interval = Duration(milliseconds: 10);
+    int cellIndex = 0;
+    updateAnimationInProgress(true);
+    Timer.periodic(
+      interval,
+      (Timer timer) {
+        if (cellIndex < cellsToFill.length) {
+          updateCellValue(cellsToFill[cellIndex][1], cellsToFill[cellIndex][0], value);
+          cellIndex++;
+        } else {
+          timer.cancel();
+
+          int progressAfterMove =
+              state.currentGame.board.getSiblingFillableCells(0, 0, []).length;
+          int progressDelta = progressAfterMove - progressBeforeMove;
+          updateProgressDelta(progressDelta);
+          updateProgress(progressAfterMove);
+
+          updateAnimationInProgress(false);
+
+          if (state.currentGame.board.isBoardSolved()) {
+            updateGameWon(true);
+            updateGameIsFinished(true);
+          }
+        }
+      },
+    );
+  }
+
+  @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 f33dca378aa5fabad4b97268304f15ebdc39b26d..a92b2303c3291813fd5b6bade0b64a69839e151f 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:colors/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..f70f2be39c047a76c59c76d016035007a48f8e11
--- /dev/null
+++ b/lib/cubit/settings_game_cubit.dart
@@ -0,0 +1,84 @@
+import 'package:equatable/equatable.dart';
+import 'package:flutter/foundation.dart';
+import 'package:flutter/material.dart';
+import 'package:hydrated_bloc/hydrated_bloc.dart';
+
+import 'package:colors/config/default_game_settings.dart';
+import 'package:colors/models/settings_game.dart';
+
+part 'settings_game_state.dart';
+
+class GameSettingsCubit extends HydratedCubit<GameSettingsState> {
+  GameSettingsCubit() : super(GameSettingsState(settings: GameSettings.createDefault()));
+
+  void setValues({
+    String? difficultyLevel,
+    String? boardSize,
+    String? colorsCount,
+  }) {
+    emit(
+      GameSettingsState(
+        settings: GameSettings(
+          difficultyLevel: difficultyLevel ?? state.settings.difficultyLevel,
+          parameterSize: boardSize ?? state.settings.parameterSize,
+          parameterColorsCount: colorsCount ?? state.settings.parameterColorsCount,
+        ),
+      ),
+    );
+  }
+
+  String getParameterValue(String code) {
+    switch (code) {
+      case DefaultGameSettings.parameterCodeDifficultyLevel:
+        return GameSettings.getLevelValueFromUnsafe(state.settings.difficultyLevel);
+      case DefaultGameSettings.parameterCodeBoardSize:
+        return GameSettings.getSizeValueFromUnsafe(state.settings.parameterSize);
+      case DefaultGameSettings.parameterCodeColorsCount:
+        return GameSettings.getColorsValueFromUnsafe(state.settings.parameterColorsCount);
+    }
+    return '';
+  }
+
+  void setParameterValue(String code, String value) {
+    final String difficultyLevel = (code == DefaultGameSettings.parameterCodeDifficultyLevel)
+        ? value
+        : getParameterValue(DefaultGameSettings.parameterCodeDifficultyLevel);
+    final String boardSize = (code == DefaultGameSettings.parameterCodeBoardSize)
+        ? value
+        : getParameterValue(DefaultGameSettings.parameterCodeBoardSize);
+    final String colorsCount = (code == DefaultGameSettings.parameterCodeColorsCount)
+        ? value
+        : getParameterValue(DefaultGameSettings.parameterCodeColorsCount);
+
+    setValues(
+      difficultyLevel: difficultyLevel,
+      boardSize: boardSize,
+      colorsCount: colorsCount,
+    );
+  }
+
+  @override
+  GameSettingsState? fromJson(Map<String, dynamic> json) {
+    final String difficultyLevel =
+        json[DefaultGameSettings.parameterCodeDifficultyLevel] as String;
+    final String boardSize = json[DefaultGameSettings.parameterCodeBoardSize] as String;
+    final String colorsCount = json[DefaultGameSettings.parameterCodeColorsCount] as String;
+
+    return GameSettingsState(
+      settings: GameSettings(
+        difficultyLevel: difficultyLevel,
+        parameterSize: boardSize,
+        parameterColorsCount: colorsCount,
+      ),
+    );
+  }
+
+  @override
+  Map<String, dynamic>? toJson(GameSettingsState state) {
+    return <String, dynamic>{
+      DefaultGameSettings.parameterCodeDifficultyLevel: state.settings.difficultyLevel,
+      DefaultGameSettings.parameterCodeBoardSize: state.settings.parameterSize,
+      DefaultGameSettings.parameterCodeColorsCount: state.settings.parameterColorsCount,
+    };
+  }
+}
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..41d3f191c94ff81119902bab88d3c8b376a11dff
--- /dev/null
+++ b/lib/cubit/settings_global_cubit.dart
@@ -0,0 +1,61 @@
+import 'package:equatable/equatable.dart';
+import 'package:flutter/foundation.dart';
+import 'package:flutter/material.dart';
+import 'package:hydrated_bloc/hydrated_bloc.dart';
+
+import 'package:colors/config/default_global_settings.dart';
+import 'package:colors/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/entities/cell.dart b/lib/entities/cell.dart
deleted file mode 100644
index 9617e4c86349bda6532141e47c96f79297866184..0000000000000000000000000000000000000000
--- a/lib/entities/cell.dart
+++ /dev/null
@@ -1,37 +0,0 @@
-import 'package:flutter/material.dart';
-
-import 'package:colors/provider/data.dart';
-import 'package:colors/utils/board_utils.dart';
-
-class Cell {
-  int value;
-
-  Cell(
-    this.value,
-  );
-
-  Container interactiveWidget(Data myProvider, ColorScheme colorScheme) {
-    final String imageAsset = 'assets/skins/${myProvider.parameterSkin}_$value.png';
-
-    return Container(
-      margin: const EdgeInsets.all(2),
-      decoration: BoxDecoration(
-        border: Border.all(
-          color: colorScheme.onSurface,
-          width: 4,
-        ),
-      ),
-      child: GestureDetector(
-        child: Image(
-          image: AssetImage(imageAsset),
-          fit: BoxFit.fill,
-        ),
-        onTap: () {
-          if (!myProvider.animationInProgress && myProvider.getFirstCellValue() != value) {
-            BoardUtils.fillBoardFromFirstCell(myProvider, value);
-          }
-        },
-      ),
-    );
-  }
-}
diff --git a/lib/main.dart b/lib/main.dart
index a74262fbb5d6b33e3e73d627917c9e3de41d675d..4ffcc22f036fee392607c109e0a71a7098963cea 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,22 +1,22 @@
 import 'dart:io';
 
 import 'package:easy_localization/easy_localization.dart';
-import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:flutter/material.dart';
 import 'package:hive/hive.dart';
 import 'package:hydrated_bloc/hydrated_bloc.dart';
-import 'package:overlay_support/overlay_support.dart';
 import 'package:path_provider/path_provider.dart';
-import 'package:provider/provider.dart';
 
 import 'package:colors/config/theme.dart';
-import 'package:colors/cubit/bottom_nav_cubit.dart';
+import 'package:colors/cubit/game_cubit.dart';
+import 'package:colors/cubit/nav_cubit.dart';
+import 'package:colors/cubit/settings_game_cubit.dart';
+import 'package:colors/cubit/settings_global_cubit.dart';
 import 'package:colors/cubit/theme_cubit.dart';
-import 'package:colors/provider/data.dart';
 import 'package:colors/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: 'Minehunter',
-                    home: const SkeletonScreen(),
+          return MaterialApp(
+            title: 'Colors',
+            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..5d6ccd91949853ddce74c7965e82722c2e694fb1
--- /dev/null
+++ b/lib/models/board.dart
@@ -0,0 +1,144 @@
+import 'dart:math';
+
+import 'package:colors/models/cell.dart';
+import 'package:colors/models/settings_game.dart';
+import 'package:colors/models/types.dart';
+import 'package:colors/utils/tools.dart';
+
+class Board {
+  final BoardCells cells;
+
+  Board({
+    required this.cells,
+  });
+
+  factory Board.createNull() {
+    return Board(cells: []);
+  }
+
+  factory Board.createRandom(GameSettings gameSettings) {
+    final int boardSizeHorizontal = gameSettings.boardSize;
+    final int boardSizeVertical = gameSettings.boardSize;
+
+    final rand = Random();
+
+    BoardCells cells = [];
+    for (int rowIndex = 0; rowIndex < boardSizeVertical; rowIndex++) {
+      List<Cell> row = [];
+      for (int colIndex = 0; colIndex < boardSizeHorizontal; colIndex++) {
+        final int value = 1 + rand.nextInt(gameSettings.colorsCount);
+        row.add(Cell(value));
+      }
+      cells.add(row);
+    }
+
+    return Board(
+      cells: cells,
+    );
+  }
+
+  int getCellValue(int col, int row) {
+    return cells[row][col].value;
+  }
+
+  int getFirstCellValue() {
+    return cells[0][0].value;
+  }
+
+  List<List<int>> getSiblingFillableCells(
+    int row,
+    int col,
+    List<List<int>> siblingCells,
+  ) {
+    final int boardSize = cells.length;
+
+    if (siblingCells.isEmpty) {
+      siblingCells = [
+        [row, col]
+      ];
+    }
+
+    final int referenceValue = cells[row][col].value;
+
+    for (int deltaRow = -1; deltaRow <= 1; deltaRow++) {
+      for (int deltaCol = -1; deltaCol <= 1; deltaCol++) {
+        if (deltaCol == 0 || deltaRow == 0) {
+          final int candidateRow = row + deltaRow;
+          final int candidateCol = col + deltaCol;
+
+          if ((candidateRow >= 0 && candidateRow < boardSize) &&
+              (candidateCol >= 0 && candidateCol < boardSize)) {
+            if (cells[candidateRow][candidateCol].value == referenceValue) {
+              bool alreadyFound = false;
+              for (int index = 0; index < siblingCells.length; index++) {
+                if ((siblingCells[index][0] == candidateRow) &&
+                    (siblingCells[index][1] == candidateCol)) {
+                  alreadyFound = true;
+                }
+              }
+              if (!alreadyFound) {
+                siblingCells.add([candidateRow, candidateCol]);
+                siblingCells = getSiblingFillableCells(
+                  candidateRow,
+                  candidateCol,
+                  siblingCells,
+                );
+              }
+            }
+          }
+        }
+      }
+    }
+
+    return siblingCells;
+  }
+
+  // check grid contains only one color
+  bool isBoardSolved() {
+    final int firstCellValue = cells[0][0].value;
+    for (int row = 0; row < cells.length; row++) {
+      for (int col = 0; col < cells[row].length; col++) {
+        if (cells[row][col].value != firstCellValue) {
+          return false;
+        }
+      }
+    }
+
+    printlog('-> ok grid fully painted!');
+
+    return true;
+  }
+
+  void dump() {
+    String horizontalRule = '----';
+    for (int i = 0; i < cells[0].length; i++) {
+      horizontalRule += '-';
+    }
+
+    printlog('Board:');
+    printlog(horizontalRule);
+
+    for (int rowIndex = 0; rowIndex < cells.length; rowIndex++) {
+      String row = '| ';
+      for (int colIndex = 0; colIndex < cells[rowIndex].length; colIndex++) {
+        row += cells[rowIndex][colIndex].value.toString();
+      }
+      row += ' |';
+
+      printlog(row);
+    }
+
+    printlog(horizontalRule);
+  }
+
+  @override
+  String toString() {
+    return '$Board(${toJson()})';
+  }
+
+  Map<String, dynamic>? toJson() {
+    return <String, dynamic>{
+      'cells': cells.toString(),
+    };
+  }
+}
diff --git a/lib/models/cell.dart b/lib/models/cell.dart
new file mode 100644
index 0000000000000000000000000000000000000000..54d6e3ad84f10b6b11368f831369fd34798a8b2b
--- /dev/null
+++ b/lib/models/cell.dart
@@ -0,0 +1,18 @@
+class Cell {
+  Cell(
+    this.value,
+  );
+
+  int value;
+
+  @override
+  String toString() {
+    return '$Cell(${toJson()})';
+  }
+
+  Map<String, dynamic>? toJson() {
+    return <String, dynamic>{
+      'value': value,
+    };
+  }
+}
diff --git a/lib/models/game.dart b/lib/models/game.dart
new file mode 100644
index 0000000000000000000000000000000000000000..28b61ead100e1d896811f67e9752e19fc79a9f82
--- /dev/null
+++ b/lib/models/game.dart
@@ -0,0 +1,114 @@
+import 'package:colors/config/default_game_settings.dart';
+import 'package:colors/models/board.dart';
+import 'package:colors/models/settings_game.dart';
+import 'package:colors/models/settings_global.dart';
+import 'package:colors/utils/tools.dart';
+
+class Game {
+  final Board board;
+  final GameSettings gameSettings;
+  final GlobalSettings globalSettings;
+  bool isRunning = false;
+  bool isFinished = false;
+  bool gameWon = false;
+
+  int maxMovesCount = 0;
+  int movesCount = 0;
+
+  int progress = 0;
+  int progressTotal = 0;
+  int progressDelta = 0;
+
+  bool animationInProgress = false;
+
+  Game({
+    required this.board,
+    required this.gameSettings,
+    required this.globalSettings,
+    this.isRunning = false,
+    this.isFinished = false,
+    this.gameWon = false,
+    this.maxMovesCount = 0,
+    this.movesCount = 0,
+    this.progress = 0,
+    this.progressTotal = 0,
+    this.progressDelta = 0,
+    this.animationInProgress = false,
+  });
+
+  factory Game.createNull() {
+    return Game(
+      board: Board.createNull(),
+      gameSettings: GameSettings.createDefault(),
+      globalSettings: GlobalSettings.createDefault(),
+    );
+  }
+
+  factory Game.createNew({
+    GameSettings? gameSettings,
+    GlobalSettings? globalSettings,
+  }) {
+    GameSettings newGameSettings = gameSettings ?? GameSettings.createDefault();
+    GlobalSettings newGlobalSettings = globalSettings ?? GlobalSettings.createDefault();
+
+    final int baseMaxMovesCount =
+        (30 * (newGameSettings.boardSize * newGameSettings.colorsCount) / (17 * 6)).round();
+    final int deltaMovesCountFromLevel =
+        DefaultGameSettings.getMovesCountLimitDeltaFromLevelCode(
+            newGameSettings.difficultyLevel);
+
+    return Game(
+      board: Board.createRandom(newGameSettings),
+      gameSettings: newGameSettings,
+      globalSettings: newGlobalSettings,
+      isRunning: true,
+      isFinished: false,
+      gameWon: false,
+      progress: 1,
+      progressTotal: newGameSettings.boardSize * newGameSettings.boardSize,
+      maxMovesCount: baseMaxMovesCount + deltaMovesCountFromLevel,
+    );
+  }
+
+  void dump() {
+    printlog('');
+    printlog('## Current game dump:');
+    printlog('');
+    gameSettings.dump();
+    globalSettings.dump();
+    printlog('');
+    board.dump();
+    printlog('');
+    printlog('Game: ');
+    printlog('  isRunning: $isRunning');
+    printlog('  isFinished: $isFinished');
+    printlog('  gameWon: $gameWon');
+    printlog('  movesCount: $movesCount');
+    printlog('  maxMovesCount: $maxMovesCount');
+    printlog('  progress: $progress');
+    printlog('  progressTotal: $progressTotal');
+    printlog('  progressDelta: $progressDelta');
+    printlog('');
+  }
+
+  @override
+  String toString() {
+    return '$Game(${toJson()})';
+  }
+
+  Map<String, dynamic>? toJson() {
+    return <String, dynamic>{
+      'board': board.toJson(),
+      'gameSettings': gameSettings.toJson(),
+      'globalSettings': globalSettings.toJson(),
+      'isRunning': isRunning,
+      'isFinished': isFinished,
+      'gameWon': gameWon,
+      'movesCount': movesCount,
+      'maxMovesCount': maxMovesCount,
+      'progress': progress,
+      'progressTotal': progressTotal,
+      'progressDelta': progressDelta,
+    };
+  }
+}
diff --git a/lib/models/settings_game.dart b/lib/models/settings_game.dart
new file mode 100644
index 0000000000000000000000000000000000000000..b5227e80ccf1589646a06dc5e7e186fbc4336e26
--- /dev/null
+++ b/lib/models/settings_game.dart
@@ -0,0 +1,81 @@
+import 'package:colors/config/default_game_settings.dart';
+import 'package:colors/utils/tools.dart';
+
+class GameSettings {
+  String difficultyLevel;
+  String parameterSize;
+  String parameterColorsCount;
+
+  GameSettings({
+    required this.difficultyLevel,
+    required this.parameterSize,
+    required this.parameterColorsCount,
+  });
+
+  static String getLevelValueFromUnsafe(String level) {
+    if (DefaultGameSettings.allowedDifficultyLevelValues.contains(level)) {
+      return level;
+    }
+
+    return DefaultGameSettings.defaultDifficultyLevelValue;
+  }
+
+  static String getSizeValueFromUnsafe(String size) {
+    if (DefaultGameSettings.allowedBoardSizeValues.contains(size)) {
+      return size;
+    }
+
+    return DefaultGameSettings.defaultBoardSizeValue;
+  }
+
+  static String getColorsValueFromUnsafe(String colors) {
+    if (DefaultGameSettings.allowedColorsCountValues.contains(colors)) {
+      return colors;
+    }
+
+    return DefaultGameSettings.defaultColorsCountValue;
+  }
+
+  factory GameSettings.createDefault() {
+    return GameSettings(
+      difficultyLevel: DefaultGameSettings.defaultDifficultyLevelValue,
+      parameterSize: DefaultGameSettings.defaultBoardSizeValue,
+      parameterColorsCount: DefaultGameSettings.defaultColorsCountValue,
+    );
+  }
+
+  int getBoardSizeFromParameter(String parameterSize) {
+    const Map<String, int> values = {
+      DefaultGameSettings.boardSizeValueSmall: 6,
+      DefaultGameSettings.boardSizeValueMedium: 10,
+      DefaultGameSettings.boardSizeValueLarge: 14,
+      DefaultGameSettings.boardSizeValueExtra: 20,
+    };
+    return values[parameterSize] ??
+        getBoardSizeFromParameter(DefaultGameSettings.defaultBoardSizeValue);
+  }
+
+  int get boardSize => getBoardSizeFromParameter(parameterSize);
+  int get colorsCount => int.parse(parameterColorsCount);
+
+  void dump() {
+    printlog('$GameSettings:');
+    printlog('  ${DefaultGameSettings.parameterCodeDifficultyLevel}: $difficultyLevel');
+    printlog('  ${DefaultGameSettings.parameterCodeBoardSize}: $parameterSize');
+    printlog('  ${DefaultGameSettings.parameterCodeColorsCount}: $parameterColorsCount');
+    printlog('');
+  }
+
+  @override
+  String toString() {
+    return '$GameSettings(${toJson()})';
+  }
+
+  Map<String, dynamic>? toJson() {
+    return <String, dynamic>{
+      DefaultGameSettings.parameterCodeDifficultyLevel: difficultyLevel,
+      DefaultGameSettings.parameterCodeBoardSize: parameterSize,
+      DefaultGameSettings.parameterCodeColorsCount: parameterColorsCount,
+    };
+  }
+}
diff --git a/lib/models/settings_global.dart b/lib/models/settings_global.dart
new file mode 100644
index 0000000000000000000000000000000000000000..09994f4124e0761b2da152295f837a0d535514ec
--- /dev/null
+++ b/lib/models/settings_global.dart
@@ -0,0 +1,41 @@
+import 'package:colors/config/default_global_settings.dart';
+import 'package:colors/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..339bfe66331369eb92a4113be046f7a36785b9c6
--- /dev/null
+++ b/lib/models/types.dart
@@ -0,0 +1,3 @@
+import 'package:colors/models/cell.dart';
+
+typedef BoardCells = List<List<Cell>>;
diff --git a/lib/provider/data.dart b/lib/provider/data.dart
deleted file mode 100644
index dfe31360d790bb8775fd4c78343024c10a400ed4..0000000000000000000000000000000000000000
--- a/lib/provider/data.dart
+++ /dev/null
@@ -1,340 +0,0 @@
-import 'package:flutter/foundation.dart';
-import 'package:shared_preferences/shared_preferences.dart';
-
-import 'package:colors/entities/cell.dart';
-
-typedef Board = List<List<Cell>>;
-
-class Data extends ChangeNotifier {
-  // Configuration available parameters
-  final List<String> _availableParameters = ['level', 'size', 'colors', 'skin'];
-  List<String> get availableParameters => _availableParameters;
-
-  // Configuration available values
-  final List<String> _availableLevelValues = ['easy', 'medium', 'hard', 'nightmare'];
-  final List<String> _availableSizeValues = ['small', 'medium', 'large', 'extra'];
-  final List<String> _availableColorsValues = ['5', '6', '7', '8'];
-  final List<String> _availableSkinValues = ['default'];
-
-  List<String> get availableLevelValues => _availableLevelValues;
-  List<String> get availableSizeValues => _availableSizeValues;
-  List<String> get availableColorsValues => _availableColorsValues;
-  List<String> get availableSkinValues => _availableSkinValues;
-
-  // Application default configuration
-  String _parameterLevel = '';
-  final String _parameterLevelDefault = 'medium';
-  String _parameterSize = '';
-  final String _parameterSizeDefault = 'medium';
-  String _parameterColors = '';
-  final String _parameterColorsDefault = '6';
-  String _parameterSkin = '';
-  final String _parameterSkinDefault = 'default';
-
-  // Application current configuration
-  String get parameterLevel => _parameterLevel;
-  String get parameterSize => _parameterSize;
-  String get parameterColors => _parameterColors;
-  String get parameterSkin => _parameterSkin;
-
-  // Game data
-  bool _gameIsRunning = false;
-  bool _animationInProgress = false;
-  bool _gameWon = false;
-  int _boardSize = 0;
-  int _colorsCount = 0;
-  int _movesCount = 0;
-  int _maxMovesCount = 0;
-  Board _board = [];
-
-  int _progress = 0;
-  int _progressTotal = 0;
-  int _progressDelta = 0;
-
-  bool isParameterValueAllowed(String parameterValue, List<String> parametersAllowedValues) {
-    bool found = false;
-    for (String item in parametersAllowedValues) {
-      if (item.contains(parameterValue)) {
-        found = true;
-      }
-    }
-    return found;
-  }
-
-  void updateParameterLevel(String parameterLevel) {
-    if (isParameterValueAllowed(parameterLevel, _availableLevelValues)) {
-      _parameterLevel = parameterLevel;
-    } else {
-      _parameterLevel = _parameterLevelDefault;
-    }
-    notifyListeners();
-  }
-
-  void updateParameterSize(String parameterSize) {
-    if (isParameterValueAllowed(parameterSize, _availableSizeValues)) {
-      _parameterSize = parameterSize;
-    } else {
-      _parameterSize = _parameterSizeDefault;
-    }
-    updateBoardSize(getBoardSizeFromParameter(parameterSize));
-    notifyListeners();
-  }
-
-  void updateParameterColors(String parameterColors) {
-    if (isParameterValueAllowed(parameterColors, _availableColorsValues)) {
-      _parameterColors = parameterColors;
-    } else {
-      _parameterColors = _parameterColorsDefault;
-    }
-    updateColorsCount(getColorsCountFromParameter(parameterColors));
-    notifyListeners();
-  }
-
-  void updateParameterSkin(String parameterSkin) {
-    if (isParameterValueAllowed(parameterSkin, _availableSkinValues)) {
-      _parameterSkin = parameterSkin;
-    } else {
-      _parameterSkin = _parameterSkinDefault;
-    }
-    notifyListeners();
-  }
-
-  String getParameterValue(String parameterCode) {
-    switch (parameterCode) {
-      case 'level':
-        {
-          return _parameterLevel;
-        }
-      case 'size':
-        {
-          return _parameterSize;
-        }
-      case 'colors':
-        {
-          return _parameterColors;
-        }
-      case 'skin':
-        {
-          return _parameterSkin;
-        }
-    }
-    return '';
-  }
-
-  List<String> getParameterAvailableValues(String parameterCode) {
-    switch (parameterCode) {
-      case 'level':
-        {
-          return _availableLevelValues;
-        }
-      case 'size':
-        {
-          return _availableSizeValues;
-        }
-      case 'colors':
-        {
-          return _availableColorsValues;
-        }
-      case 'skin':
-        {
-          return _availableSkinValues;
-        }
-    }
-    return [];
-  }
-
-  void setParameterValue(String parameterCode, String parameterValue) async {
-    switch (parameterCode) {
-      case 'level':
-        {
-          updateParameterLevel(parameterValue);
-        }
-        break;
-      case 'size':
-        {
-          updateParameterSize(parameterValue);
-        }
-        break;
-      case 'colors':
-        {
-          updateParameterColors(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('level', prefs.getString('level') ?? _parameterLevelDefault);
-    setParameterValue('size', prefs.getString('size') ?? _parameterSizeDefault);
-    setParameterValue('colors', prefs.getString('colors') ?? _parameterColorsDefault);
-    setParameterValue('skin', prefs.getString('skin') ?? _parameterSkinDefault);
-  }
-
-  int getBoardSizeFromParameter(String parameterSize) {
-    switch (parameterSize) {
-      case 'small':
-        {
-          return 6;
-        }
-      case 'medium':
-        {
-          return 10;
-        }
-      case 'large':
-        {
-          return 14;
-        }
-      case 'extra':
-        {
-          return 20;
-        }
-    }
-    return getBoardSizeFromParameter(_parameterSizeDefault);
-  }
-
-  int getColorsCountFromParameter(String parameterColors) {
-    switch (parameterColors) {
-      case '5':
-        {
-          return 5;
-        }
-      case '6':
-        {
-          return 6;
-        }
-      case '7':
-        {
-          return 7;
-        }
-      case '8':
-        {
-          return 8;
-        }
-    }
-    return getColorsCountFromParameter(_parameterColorsDefault);
-  }
-
-  int getMovesCountLimitDeltaFromLevelParameter(String parameterLevel) {
-    switch (parameterLevel) {
-      case 'easy':
-        {
-          return 5;
-        }
-      case 'medium':
-        {
-          return 3;
-        }
-      case 'hard':
-        {
-          return 1;
-        }
-      case 'nightmare':
-        {
-          return -1;
-        }
-    }
-    return getMovesCountLimitDeltaFromLevelParameter(_parameterLevelDefault);
-  }
-
-  int get boardSize => _boardSize;
-  void updateBoardSize(int boardSize) {
-    _boardSize = boardSize;
-    _progressTotal = boardSize * boardSize;
-  }
-
-  int get colorsCount => _colorsCount;
-  void updateColorsCount(int colorsCount) {
-    _colorsCount = colorsCount;
-  }
-
-  Board get board => _board;
-  void updateBoard(Board board) {
-    _board = board;
-    notifyListeners();
-  }
-
-  updateCellValue(int col, int row, int value) {
-    _board[row][col].value = value;
-    notifyListeners();
-  }
-
-  int getFirstCellValue() {
-    return _board[0][0].value;
-  }
-
-  int getCellValue(int col, int row) {
-    return _board[row][col].value;
-  }
-
-  int get movesCount => _movesCount;
-  void updateMovesCount(int movesCount) {
-    _movesCount = movesCount;
-    notifyListeners();
-  }
-
-  void incrementMovesCount() {
-    updateMovesCount(movesCount + 1);
-  }
-
-  int get maxMovesCount => _maxMovesCount;
-  void updateMaxMovesCount(int maxMovesCount) {
-    _maxMovesCount = maxMovesCount;
-  }
-
-  int get progress => _progress;
-  int get progressTotal => _progressTotal;
-  int get progressDelta => _progressDelta;
-  void updateProgress(int progress) {
-    _progress = progress;
-    notifyListeners();
-  }
-
-  void updateProgressTotal(int progressTotal) {
-    _progressTotal = progressTotal;
-    notifyListeners();
-  }
-
-  void updateProgressDelta(int progressDelta) {
-    _progressDelta = progressDelta;
-    notifyListeners();
-  }
-
-  bool get gameIsRunning => _gameIsRunning;
-  void updateGameIsRunning(bool gameIsRunning) {
-    _gameIsRunning = gameIsRunning;
-    notifyListeners();
-  }
-
-  bool isGameFinished() {
-    return _gameWon;
-  }
-
-  bool get gameWon => _gameWon;
-  void updateGameWon(bool gameWon) {
-    _gameWon = gameWon;
-    notifyListeners();
-  }
-
-  bool get animationInProgress => _animationInProgress;
-  void updateAnimationInProgress(bool animationInProgress) {
-    _animationInProgress = animationInProgress;
-    notifyListeners();
-  }
-
-  void resetGame() {
-    _gameIsRunning = false;
-    _gameWon = false;
-    _movesCount = 0;
-    _maxMovesCount = 0;
-    _progress = 0;
-    notifyListeners();
-  }
-}
diff --git a/lib/ui/layout/game.dart b/lib/ui/layout/game.dart
deleted file mode 100644
index a91ceafa7578a1b92617b1406348a4d1c2ae4237..0000000000000000000000000000000000000000
--- a/lib/ui/layout/game.dart
+++ /dev/null
@@ -1,42 +0,0 @@
-import 'package:flutter/material.dart';
-
-import 'package:colors/ui/layout/tileset.dart';
-import 'package:colors/provider/data.dart';
-import 'package:colors/ui/widgets/game/indicator_top.dart';
-import 'package:colors/ui/widgets/game/message_game_end.dart';
-import 'package:colors/ui/widgets/game/select_color_bar.dart';
-
-class Game extends StatelessWidget {
-  const Game({
-    super.key,
-    required this.myProvider,
-    required this.boardWidth,
-  });
-
-  final Data myProvider;
-  final double boardWidth;
-
-  @override
-  Widget build(BuildContext context) {
-    final bool gameIsFinished = myProvider.isGameFinished();
-
-    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, boardWidth: boardWidth),
-        ),
-        const SizedBox(height: 2),
-        Container(
-          child: gameIsFinished
-              ? EndGameMessage(myProvider: myProvider)
-              : SelectColorBar(myProvider: myProvider),
-        ),
-      ],
-    );
-  }
-}
diff --git a/lib/ui/layout/parameters.dart b/lib/ui/layout/parameters.dart
deleted file mode 100644
index 34a9a42e93adfc43b9757bc739f0b21d08a01191..0000000000000000000000000000000000000000
--- a/lib/ui/layout/parameters.dart
+++ /dev/null
@@ -1,119 +0,0 @@
-import 'package:flutter/material.dart';
-
-import 'package:colors/ui/widgets/home/button_game_start_new.dart';
-import 'package:colors/provider/data.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 = 3.0;
-  static const double blockPadding = 2.0;
-  static const Color buttonBackgroundColor = Colors.white;
-  static const Color buttonBorderColorActive = Colors.blue;
-  static const Color buttonBorderColorInactive = Colors.white;
-  static const double buttonBorderWidth = 10.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 = [];
-
-    final List<String> parameters = myProvider.availableParameters;
-    for (int index = 0; index < parameters.length; index++) {
-      lines.add(buildParameterSelector(parameters[index]));
-      lines.add(const SizedBox(height: separatorHeight));
-    }
-
-    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),
-        StartNewGameButton(myProvider: myProvider),
-      ],
-    );
-  }
-
-  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('game_win'),
-          onPressed: () {},
-        ),
-      ],
-    );
-  }
-
-  Widget buildParameterSelector(String parameterCode) {
-    final List<String> 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(parameterCode, availableValues[index])],
-              ),
-          ],
-        ),
-      ],
-    );
-  }
-
-  Widget buildParameterButton(String parameterCode, String parameterValue) {
-    final String currentValue = myProvider.getParameterValue(parameterCode).toString();
-
-    final bool isActive = (parameterValue == currentValue);
-    final 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 f18470dfd99d48971a2d63aa2dc4fd38c5672a11..0000000000000000000000000000000000000000
--- a/lib/ui/layout/tileset.dart
+++ /dev/null
@@ -1,50 +0,0 @@
-import 'package:flutter/material.dart';
-
-import 'package:colors/ui/painters/board_painter.dart';
-import 'package:colors/provider/data.dart';
-import 'package:colors/utils/board_utils.dart';
-
-class Tileset extends StatelessWidget {
-  const Tileset({
-    super.key,
-    required this.myProvider,
-    required this.boardWidth,
-  });
-
-  final Data myProvider;
-  final double boardWidth;
-
-  @override
-  Widget build(BuildContext context) {
-    return Container(
-      margin: const EdgeInsets.all(4),
-      padding: const EdgeInsets.all(4),
-      child: Column(
-        children: [
-          Center(
-            child: GestureDetector(
-              onTapUp: (details) {
-                final double xTap = details.localPosition.dx;
-                final double yTap = details.localPosition.dy;
-                final int boardSize = myProvider.boardSize;
-                final int col = xTap ~/ (boardWidth / boardSize);
-                final int row = yTap ~/ (boardWidth / boardSize);
-                final int cellValue = myProvider.getCellValue(col, row);
-                BoardUtils.fillBoardFromFirstCell(myProvider, cellValue);
-              },
-              child: CustomPaint(
-                size: Size(boardWidth, boardWidth),
-                willChange: false,
-                painter: BoardPainter(
-                  myProvider: myProvider,
-                  colorScheme: Theme.of(context).colorScheme,
-                ),
-                isComplex: true,
-              ),
-            ),
-          ),
-        ],
-      ),
-    );
-  }
-}
diff --git a/lib/ui/painters/board_painter.dart b/lib/ui/painters/board_painter.dart
index d1ec5b29629529544e600da0f1cf6807fb0a4a13..42bb2a2a5f7e284f9bc2bd9fb6cda486ea07fe50 100644
--- a/lib/ui/painters/board_painter.dart
+++ b/lib/ui/painters/board_painter.dart
@@ -1,19 +1,23 @@
 import 'package:flutter/material.dart';
 
-import 'package:colors/entities/cell.dart';
+import 'package:colors/models/cell.dart';
+import 'package:colors/models/game.dart';
+import 'package:colors/models/types.dart';
 import 'package:colors/utils/color_theme.dart';
-import 'package:colors/provider/data.dart';
 
 class BoardPainter extends CustomPainter {
-  const BoardPainter({required this.myProvider, required this.colorScheme});
+  const BoardPainter({
+    required this.game,
+    required this.colorScheme,
+  });
 
-  final Data myProvider;
+  final Game game;
   final ColorScheme colorScheme;
 
   @override
   void paint(Canvas canvas, Size size) {
-    final int boardSize = myProvider.boardSize;
-    final Board board = myProvider.board;
+    final int boardSize = game.gameSettings.boardSize;
+    final BoardCells cells = game.board.cells;
     final double cellSize = size.width / boardSize;
 
     // background
@@ -22,9 +26,9 @@ class BoardPainter extends CustomPainter {
       for (var col = 0; col < boardSize; col++) {
         final double x = cellSize * col;
 
-        final Cell cell = board[row][col];
+        final Cell cell = cells[row][col];
         final int cellValue = cell.value;
-        final int colorCode = ColorTheme.getColorCode(myProvider.parameterSkin, cellValue);
+        final int colorCode = ColorTheme.getColorCode(game.globalSettings.skin, cellValue);
 
         final cellPaintBackground = Paint();
         cellPaintBackground.color = Color(colorCode);
@@ -40,7 +44,7 @@ class BoardPainter extends CustomPainter {
     // borders
     const double borderSize = 2;
     final cellPaintBorder = Paint();
-    cellPaintBorder.color = colorScheme.onSurface;
+    cellPaintBorder.color = colorScheme.onBackground;
     cellPaintBorder.strokeWidth = borderSize;
     cellPaintBorder.strokeCap = StrokeCap.round;
 
@@ -49,27 +53,27 @@ class BoardPainter extends CustomPainter {
       for (var col = 0; col < boardSize; col++) {
         final double x = cellSize * col;
 
-        final Cell cell = board[row][col];
+        final Cell cell = cells[row][col];
         final int cellValue = cell.value;
 
-        if ((row == 0) || (row > 1 && cellValue != myProvider.getCellValue(col, row - 1))) {
+        if ((row == 0) || (row > 1 && cellValue != game.board.getCellValue(col, row - 1))) {
           final Offset borderStart = Offset(x, y);
           final Offset borderStop = Offset(x + cellSize, y);
           canvas.drawLine(borderStart, borderStop, cellPaintBorder);
         }
         if ((row == boardSize - 1) ||
-            ((row + 1) < boardSize && cellValue != myProvider.getCellValue(col, row + 1))) {
+            ((row + 1) < boardSize && cellValue != game.board.getCellValue(col, row + 1))) {
           final Offset borderStart = Offset(x, y + cellSize);
           final Offset borderStop = Offset(x + cellSize, y + cellSize);
           canvas.drawLine(borderStart, borderStop, cellPaintBorder);
         }
-        if ((col == 0) || (col > 1 && cellValue != myProvider.getCellValue(col - 1, row))) {
+        if ((col == 0) || (col > 1 && cellValue != game.board.getCellValue(col - 1, row))) {
           final Offset borderStart = Offset(x, y);
           final Offset borderStop = Offset(x, y + cellSize);
           canvas.drawLine(borderStart, borderStop, cellPaintBorder);
         }
         if ((col == boardSize - 1) ||
-            ((col + 1) < boardSize && cellValue != myProvider.getCellValue(col + 1, row))) {
+            ((col + 1) < boardSize && cellValue != game.board.getCellValue(col + 1, row))) {
           final Offset borderStart = Offset(x + cellSize, y);
           final Offset borderStop = Offset(x + cellSize, y + cellSize);
           canvas.drawLine(borderStart, borderStop, cellPaintBorder);
diff --git a/lib/ui/painters/parameter_painter.dart b/lib/ui/painters/parameter_painter.dart
new file mode 100644
index 0000000000000000000000000000000000000000..fb216ed2c3bd02cb57c27c8121ba47de02e637d7
--- /dev/null
+++ b/lib/ui/painters/parameter_painter.dart
@@ -0,0 +1,372 @@
+import 'dart:math';
+
+import 'package:flutter/material.dart';
+
+import 'package:colors/config/default_game_settings.dart';
+import 'package:colors/config/default_global_settings.dart';
+import 'package:colors/models/settings_game.dart';
+import 'package:colors/models/settings_global.dart';
+import 'package:colors/utils/color_extensions.dart';
+import 'package:colors/utils/color_theme.dart';
+import 'package:colors/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 = 20 / 100 * canvasSize;
+    canvas.drawRect(
+        Rect.fromPoints(const Offset(0, 0), Offset(canvasSize, canvasSize)), paint);
+
+    // content
+    switch (code) {
+      case DefaultGameSettings.parameterCodeDifficultyLevel:
+        paintDifficultyLevelParameterItem(value, canvas, canvasSize);
+        break;
+      case DefaultGameSettings.parameterCodeBoardSize:
+        paintBoardSizeParameterItem(value, canvas, canvasSize);
+        break;
+      case DefaultGameSettings.parameterCodeColorsCount:
+        paintColorsCountParameterItem(value, canvas, canvasSize);
+        break;
+      case DefaultGlobalSettings.parameterCodeSkin:
+        paintUnknownParameterItem(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 / 100 * size;
+
+    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,
+    );
+    textPainter.layout();
+    textPainter.paint(
+      canvas,
+      Offset(
+        (size - textPainter.width) * 0.5,
+        (size - textPainter.height) * 0.5,
+      ),
+    );
+  }
+
+  void paintDifficultyLevelParameterItem(
+    final String value,
+    final Canvas canvas,
+    final double size,
+  ) {
+    Color backgroundColor = Colors.grey;
+
+    final List<dynamic> stars = [];
+
+    switch (value) {
+      case DefaultGameSettings.difficultyLevelValueEasy:
+        backgroundColor = Colors.green;
+        stars.add([0.5, 0.5]);
+        break;
+      case DefaultGameSettings.difficultyLevelValueMedium:
+        backgroundColor = Colors.orange;
+        stars.add([0.3, 0.5]);
+        stars.add([0.7, 0.5]);
+        break;
+      case DefaultGameSettings.difficultyLevelValueHard:
+        backgroundColor = Colors.red;
+        stars.add([0.3, 0.3]);
+        stars.add([0.7, 0.3]);
+        stars.add([0.5, 0.7]);
+        break;
+      case DefaultGameSettings.difficultyLevelValueNightmare:
+        backgroundColor = Colors.purple;
+        stars.add([0.3, 0.3]);
+        stars.add([0.7, 0.3]);
+        stars.add([0.3, 0.7]);
+        stars.add([0.7, 0.7]);
+        break;
+      default:
+        printlog('Wrong value for level parameter value: $value');
+    }
+
+    final paint = Paint();
+    paint.strokeJoin = StrokeJoin.round;
+    paint.strokeWidth = 3 / 100 * size;
+
+    // Colored background
+    paint.color = backgroundColor;
+    paint.style = PaintingStyle.fill;
+    canvas.drawRect(Rect.fromPoints(const Offset(0, 0), Offset(size, size)), paint);
+
+    // Stars
+    final textSpan = TextSpan(
+      text: '⭐',
+      style: TextStyle(
+        color: Colors.black,
+        fontSize: size / 3,
+        fontWeight: FontWeight.bold,
+      ),
+    );
+    final textPainter = TextPainter(
+      text: textSpan,
+      textDirection: TextDirection.ltr,
+    );
+    textPainter.layout();
+
+    for (var center in stars) {
+      textPainter.paint(
+        canvas,
+        Offset(
+          size * center[0] - textPainter.width * 0.5,
+          size * center[1] - textPainter.height * 0.5,
+        ),
+      );
+    }
+  }
+
+  void paintBoardSizeParameterItem(
+    final String value,
+    final Canvas canvas,
+    final double size,
+  ) {
+    Color backgroundColor = Colors.grey;
+    int gridWidth = 1;
+
+    switch (value) {
+      case DefaultGameSettings.boardSizeValueSmall:
+        backgroundColor = Colors.green;
+        gridWidth = 2;
+        break;
+      case DefaultGameSettings.boardSizeValueMedium:
+        backgroundColor = Colors.orange;
+        gridWidth = 3;
+        break;
+      case DefaultGameSettings.boardSizeValueLarge:
+        backgroundColor = Colors.red;
+        gridWidth = 4;
+        break;
+      case DefaultGameSettings.boardSizeValueExtra:
+        backgroundColor = Colors.purple;
+        gridWidth = 5;
+        break;
+      default:
+        printlog('Wrong value for boardSize parameter value: $value');
+    }
+
+    final paint = Paint();
+    paint.strokeJoin = StrokeJoin.round;
+    paint.strokeWidth = 3 / 100 * size;
+
+    // Colored background
+    paint.color = backgroundColor;
+    paint.style = PaintingStyle.fill;
+    canvas.drawRect(Rect.fromPoints(const Offset(0, 0), Offset(size, size)), paint);
+
+    // Mini grid
+    final squareBackgroundColor = Colors.grey.shade200;
+    final squareBorderColor = Colors.grey.shade800;
+
+    final double cellSize = size / 7;
+    final double origin = (size - gridWidth * cellSize) / 2;
+
+    for (int row = 0; row < gridWidth; row++) {
+      for (int col = 0; col < gridWidth; col++) {
+        final Offset topLeft = Offset(origin + col * cellSize, origin + row * cellSize);
+        final Offset bottomRight = topLeft + Offset(cellSize, cellSize);
+
+        paint.color = squareBackgroundColor;
+        paint.style = PaintingStyle.fill;
+        canvas.drawRect(Rect.fromPoints(topLeft, bottomRight), paint);
+
+        paint.color = squareBorderColor;
+        paint.style = PaintingStyle.stroke;
+        canvas.drawRect(Rect.fromPoints(topLeft, bottomRight), paint);
+      }
+    }
+  }
+
+  void paintColorsCountParameterItem(
+    final String value,
+    final Canvas canvas,
+    final double size,
+  ) {
+    Color backgroundColor = Colors.grey;
+
+    switch (value) {
+      case DefaultGameSettings.colorsCountValueLow:
+        backgroundColor = Colors.green;
+        break;
+      case DefaultGameSettings.colorsCountValueMedium:
+        backgroundColor = Colors.orange;
+        break;
+      case DefaultGameSettings.colorsCountValueHigh:
+        backgroundColor = Colors.red;
+        break;
+      case DefaultGameSettings.colorsCountValueVeryHigh:
+        backgroundColor = Colors.purple;
+        break;
+      default:
+        printlog('Wrong value for colorsCount parameter value: $value');
+    }
+
+    final paint = Paint();
+    paint.strokeJoin = StrokeJoin.round;
+    paint.strokeWidth = 3 / 100 * size;
+
+    // Colored background
+    paint.color = backgroundColor;
+    paint.style = PaintingStyle.fill;
+    canvas.drawRect(Rect.fromPoints(const Offset(0, 0), Offset(size, size)), paint);
+
+    // Colors preview
+    const List<Offset> positions = [
+      Offset(0, 0),
+      Offset(1, 0),
+      Offset(2, 0),
+      Offset(2, 1),
+      Offset(2, 2),
+      Offset(1, 2),
+      Offset(0, 2),
+      Offset(0, 1),
+    ];
+
+    const skin = DefaultGlobalSettings.defaultSkinValue;
+
+    final double padding = 4 / 100 * size;
+    final double margin = 3 / 100 * size;
+    final double width = ((size - 2 * padding) / 3) - 2 * margin;
+
+    final int maxValue = int.parse(value);
+    for (int colorIndex = 0; colorIndex < maxValue; colorIndex++) {
+      final Offset position = positions[colorIndex];
+
+      final Offset topLeft = Offset(padding + margin + position.dx * (width + 2 * margin),
+          padding + margin + position.dy * (width + 2 * margin));
+
+      final Offset bottomRight = topLeft + Offset(width, width);
+
+      final squareColor = Color(ColorTheme.getColorCode(skin, colorIndex + 1));
+      paint.color = squareColor;
+      paint.style = PaintingStyle.fill;
+      canvas.drawRect(Rect.fromPoints(topLeft, bottomRight), paint);
+
+      final borderColor = squareColor.darken(20);
+      paint.color = borderColor;
+      paint.style = PaintingStyle.stroke;
+      canvas.drawRect(Rect.fromPoints(topLeft, bottomRight), paint);
+    }
+
+    // centered text value
+    final textSpan = TextSpan(
+      text: value.toString(),
+      style: TextStyle(
+        color: Colors.black,
+        fontSize: size / 4,
+        fontWeight: FontWeight.bold,
+      ),
+    );
+    final textPainter = TextPainter(
+      text: textSpan,
+      textDirection: TextDirection.ltr,
+    );
+    textPainter.layout();
+    textPainter.paint(
+      canvas,
+      Offset(
+        (size - textPainter.width) * 0.5,
+        (size - textPainter.height) * 0.5,
+      ),
+    );
+  }
+
+  void paintColorsThemeParameterItem(
+    final String value,
+    final Canvas canvas,
+    final double size,
+  ) {
+    Color backgroundColor = Colors.grey;
+    const int gridWidth = 4;
+
+    final paint = Paint();
+    paint.strokeJoin = StrokeJoin.round;
+    paint.strokeWidth = 3 / 100 * size;
+
+    // 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;
+
+    final double cellSize = size / gridWidth;
+    final double origin = (size - gridWidth * cellSize) / 2;
+
+    for (int row = 0; row < gridWidth; row++) {
+      for (int col = 0; col < gridWidth; col++) {
+        final Offset topLeft = Offset(origin + col * cellSize, origin + row * cellSize);
+        final Offset bottomRight = topLeft + Offset(cellSize, cellSize);
+
+        const squareColor = Colors.pink;
+
+        paint.color = squareColor;
+        paint.style = PaintingStyle.fill;
+        canvas.drawRect(Rect.fromPoints(topLeft, bottomRight), paint);
+
+        paint.color = borderColor;
+        paint.style = PaintingStyle.stroke;
+        canvas.drawRect(Rect.fromPoints(topLeft, bottomRight), paint);
+      }
+    }
+  }
+}
diff --git a/lib/ui/screens/about_page.dart b/lib/ui/screens/about_page.dart
deleted file mode 100644
index 459d008ee58602b8b4fd0a391c7cb491d17f87b4..0000000000000000000000000000000000000000
--- a/lib/ui/screens/about_page.dart
+++ /dev/null
@@ -1,41 +0,0 @@
-import 'package:easy_localization/easy_localization.dart';
-import 'package:flutter/material.dart';
-import 'package:package_info_plus/package_info_plus.dart';
-
-import 'package:colors/ui/widgets/header_app.dart';
-
-class AboutPage extends StatelessWidget {
-  const AboutPage({super.key});
-
-  @override
-  Widget build(BuildContext context) {
-    return Padding(
-      padding: const EdgeInsets.symmetric(horizontal: 8),
-      child: Column(
-        mainAxisAlignment: MainAxisAlignment.start,
-        crossAxisAlignment: CrossAxisAlignment.start,
-        mainAxisSize: MainAxisSize.max,
-        children: <Widget>[
-          const SizedBox(height: 8),
-          const AppHeader(text: 'about_title'),
-          const Text('about_content').tr(),
-          FutureBuilder<PackageInfo>(
-            future: PackageInfo.fromPlatform(),
-            builder: (context, snapshot) {
-              switch (snapshot.connectionState) {
-                case ConnectionState.done:
-                  return const Text('about_version').tr(
-                    namedArgs: {
-                      'version': snapshot.data!.version,
-                    },
-                  );
-                default:
-                  return const SizedBox();
-              }
-            },
-          ),
-        ],
-      ),
-    );
-  }
-}
diff --git a/lib/ui/screens/game_page.dart b/lib/ui/screens/game_page.dart
deleted file mode 100644
index d974148b5edbb75ca28499adb6c2d9075c50ac8a..0000000000000000000000000000000000000000
--- a/lib/ui/screens/game_page.dart
+++ /dev/null
@@ -1,37 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
-
-import 'package:colors/ui/layout/game.dart';
-import 'package:colors/ui/layout/parameters.dart';
-import 'package:colors/provider/data.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();
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    final Data myProvider = Provider.of<Data>(context);
-    final double boardWidth = MediaQuery.of(context).size.width;
-
-    return SafeArea(
-      child: Center(
-        child: myProvider.gameIsRunning
-            ? Game(myProvider: myProvider, boardWidth: boardWidth)
-            : Parameters(myProvider: myProvider),
-      ),
-    );
-  }
-}
diff --git a/lib/ui/screens/page_about.dart b/lib/ui/screens/page_about.dart
new file mode 100644
index 0000000000000000000000000000000000000000..a8602ef37637e6f640625560da6a31e461f11238
--- /dev/null
+++ b/lib/ui/screens/page_about.dart
@@ -0,0 +1,38 @@
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+import 'package:package_info_plus/package_info_plus.dart';
+
+import 'package:colors/ui/widgets/helpers/header_app.dart';
+
+class PageAbout extends StatelessWidget {
+  const PageAbout({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return Column(
+      mainAxisAlignment: MainAxisAlignment.start,
+      crossAxisAlignment: CrossAxisAlignment.start,
+      mainAxisSize: MainAxisSize.max,
+      children: <Widget>[
+        const SizedBox(height: 8),
+        const AppHeader(text: 'about_title'),
+        const Text('about_content').tr(),
+        FutureBuilder<PackageInfo>(
+          future: PackageInfo.fromPlatform(),
+          builder: (context, snapshot) {
+            switch (snapshot.connectionState) {
+              case ConnectionState.done:
+                return const Text('about_version').tr(
+                  namedArgs: {
+                    'version': snapshot.data!.version,
+                  },
+                );
+              default:
+                return const SizedBox();
+            }
+          },
+        ),
+      ],
+    );
+  }
+}
diff --git a/lib/ui/screens/page_game.dart b/lib/ui/screens/page_game.dart
new file mode 100644
index 0000000000000000000000000000000000000000..d3a64ac427c48bfbffc62f0f93e4f2793aaadcd1
--- /dev/null
+++ b/lib/ui/screens/page_game.dart
@@ -0,0 +1,18 @@
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:flutter/material.dart';
+
+import 'package:colors/cubit/game_cubit.dart';
+import 'package:colors/ui/widgets/game/game.dart';
+import 'package:colors/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/page_settings.dart b/lib/ui/screens/page_settings.dart
new file mode 100644
index 0000000000000000000000000000000000000000..d559f9566662c9f3bffaaf35a184e6b79a04feda
--- /dev/null
+++ b/lib/ui/screens/page_settings.dart
@@ -0,0 +1,23 @@
+import 'package:flutter/material.dart';
+
+import 'package:colors/ui/widgets/helpers/header_app.dart';
+import 'package:colors/ui/widgets/settings/settings_form.dart';
+
+class PageSettings extends StatelessWidget {
+  const PageSettings({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return const Column(
+      mainAxisAlignment: MainAxisAlignment.start,
+      crossAxisAlignment: CrossAxisAlignment.start,
+      mainAxisSize: MainAxisSize.max,
+      children: <Widget>[
+        SizedBox(height: 8),
+        AppHeader(text: 'settings_title'),
+        SizedBox(height: 8),
+        SettingsForm(),
+      ],
+    );
+  }
+}
diff --git a/lib/ui/screens/settings_page.dart b/lib/ui/screens/settings_page.dart
deleted file mode 100644
index dc59bbe6eaddffbfb957beef56e24ca3971ff485..0000000000000000000000000000000000000000
--- a/lib/ui/screens/settings_page.dart
+++ /dev/null
@@ -1,26 +0,0 @@
-import 'package:flutter/material.dart';
-
-import 'package:colors/ui/widgets/header_app.dart';
-import 'package:colors/ui/widgets/settings/settings_form.dart';
-
-class SettingsPage extends StatelessWidget {
-  const SettingsPage({super.key});
-
-  @override
-  Widget build(BuildContext context) {
-    return const Padding(
-      padding: EdgeInsets.symmetric(horizontal: 8),
-      child: Column(
-        mainAxisAlignment: MainAxisAlignment.start,
-        crossAxisAlignment: CrossAxisAlignment.start,
-        mainAxisSize: MainAxisSize.max,
-        children: <Widget>[
-          SizedBox(height: 8),
-          AppHeader(text: 'settings_title'),
-          SizedBox(height: 8),
-          SettingsForm(),
-        ],
-      ),
-    );
-  }
-}
diff --git a/lib/ui/skeleton.dart b/lib/ui/skeleton.dart
index a428bc5bc1686928fb37c90d4f449185c666d792..eaec6f6314be0af2e0ecb1a955db10b90b76f4d8 100644
--- a/lib/ui/skeleton.dart
+++ b/lib/ui/skeleton.dart
@@ -1,47 +1,28 @@
-import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:flutter_swipe/flutter_swipe.dart';
-import 'package:provider/provider.dart';
+import 'package:flutter/material.dart';
 
 import 'package:colors/config/menu.dart';
-import 'package:colors/cubit/bottom_nav_cubit.dart';
-import 'package:colors/provider/data.dart';
-import 'package:colors/ui/widgets/app_bar.dart';
-import 'package:colors/ui/widgets/bottom_nav_bar.dart';
+import 'package:colors/cubit/nav_cubit.dart';
+import 'package:colors/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),
-      body: Swiper(
-        itemCount: Menu.itemsCount,
-        itemBuilder: (BuildContext context, int index) {
-          return Menu.getPageWidget(index);
-        },
-        pagination: SwiperPagination(
-          margin: const EdgeInsets.all(0),
-          builder: SwiperCustomPagination(
-            builder: (BuildContext context, SwiperPluginConfig config) {
-              return BottomNavBar(swipeController: config.controller);
-            },
-          ),
+      body: Material(
+        color: Theme.of(context).colorScheme.background,
+        child: BlocBuilder<NavCubit, int>(
+          builder: (BuildContext context, int pageIndex) {
+            return Padding(
+              padding: const EdgeInsets.symmetric(horizontal: 4),
+              child: Menu.getPageWidget(pageIndex),
+            );
+          },
         ),
-        onIndexChanged: (newPageIndex) {
-          BlocProvider.of<BottomNavCubit>(context).updateIndex(newPageIndex);
-        },
-        outer: true,
-        loop: false,
       ),
       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 c998df686de1518562c0be63d4563946595d6b3e..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:colors/provider/data.dart';
-import 'package:colors/ui/widgets/header_app.dart';
-import 'package:colors/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 87e30d5a4fe026469ba6feffa70e84dc67f9a4f8..0000000000000000000000000000000000000000
--- a/lib/ui/widgets/bottom_nav_bar.dart
+++ /dev/null
@@ -1,40 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:flutter_swipe/flutter_swipe.dart';
-
-import 'package:colors/config/menu.dart';
-import 'package:colors/cubit/bottom_nav_cubit.dart';
-
-class BottomNavBar extends StatelessWidget {
-  const BottomNavBar({super.key, required this.swipeController});
-
-  final SwiperController swipeController;
-
-  @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);
-              swipeController.move(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..613d2fb7cbfca7241b2c7fbf788825a92d412141
--- /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:colors/cubit/game_cubit.dart';
+import 'package:colors/cubit/settings_game_cubit.dart';
+import 'package:colors/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/home/button_game_restart.dart b/lib/ui/widgets/game/button_game_restart.dart
similarity index 62%
rename from lib/ui/widgets/home/button_game_restart.dart
rename to lib/ui/widgets/game/button_game_restart.dart
index 364ca072c680b8b3a7afac129dc85d08750f7c5c..dce403b3cfb2690b2f5abcf0bd9e4559654779c6 100644
--- a/lib/ui/widgets/home/button_game_restart.dart
+++ b/lib/ui/widgets/game/button_game_restart.dart
@@ -1,15 +1,15 @@
+import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:flutter/material.dart';
 
-import 'package:colors/provider/data.dart';
-import 'package:colors/utils/game_utils.dart';
+import 'package:colors/cubit/game_cubit.dart';
 
 class RestartGameButton extends StatelessWidget {
-  const RestartGameButton({super.key, required this.myProvider});
-
-  final Data myProvider;
+  const RestartGameButton({super.key});
 
   @override
   Widget build(BuildContext context) {
+    final GameCubit gameCubit = BlocProvider.of<GameCubit>(context);
+
     return TextButton(
       style: ButtonStyle(
         padding: MaterialStateProperty.all<EdgeInsets>(const EdgeInsets.all(0)),
@@ -18,7 +18,7 @@ class RestartGameButton extends StatelessWidget {
         image: AssetImage('assets/icons/button_back.png'),
         fit: BoxFit.fill,
       ),
-      onPressed: () => GameUtils.quitGame(myProvider),
+      onPressed: () => gameCubit.quitGame(),
     );
   }
 }
diff --git a/lib/ui/widgets/game/cell_interactive.dart b/lib/ui/widgets/game/cell_interactive.dart
new file mode 100644
index 0000000000000000000000000000000000000000..40b67d01db9fb21a8b080f5d7ebc3f40bf6dc29d
--- /dev/null
+++ b/lib/ui/widgets/game/cell_interactive.dart
@@ -0,0 +1,55 @@
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:flutter/material.dart';
+
+import 'package:colors/cubit/game_cubit.dart';
+import 'package:colors/models/cell.dart';
+import 'package:colors/models/game.dart';
+import 'package:colors/utils/color_theme.dart';
+
+class InteractiveCell extends StatelessWidget {
+  const InteractiveCell({
+    super.key,
+    required this.cell,
+    required this.colorScheme,
+    required this.currentGame,
+    required this.itemWidth,
+  });
+
+  final Cell cell;
+  final ColorScheme colorScheme;
+  final Game currentGame;
+  final double itemWidth;
+
+  @override
+  Widget build(BuildContext context) {
+    final String skin = currentGame.globalSettings.skin;
+    final squareColor = Color(ColorTheme.getColorCode(skin, cell.value));
+
+    return Container(
+      margin: const EdgeInsets.all(2),
+      decoration: BoxDecoration(
+        border: Border.all(
+          color: colorScheme.onSurface,
+          width: 3,
+        ),
+      ),
+      child: GestureDetector(
+        child: Container(
+          color: squareColor,
+          padding: const EdgeInsets.all(4),
+          child: SizedBox.square(
+            dimension: itemWidth - 19,
+          ),
+        ),
+        onTap: () {
+          final GameCubit gameCubit = BlocProvider.of<GameCubit>(context);
+
+          if (!currentGame.animationInProgress &&
+              currentGame.board.getFirstCellValue() != cell.value) {
+            gameCubit.fillBoardFromFirstCell(cell.value);
+          }
+        },
+      ),
+    );
+  }
+}
diff --git a/lib/ui/widgets/game/game.dart b/lib/ui/widgets/game/game.dart
new file mode 100644
index 0000000000000000000000000000000000000000..870676c265cf9d68145f51223fbcb05494086d8e
--- /dev/null
+++ b/lib/ui/widgets/game/game.dart
@@ -0,0 +1,37 @@
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:flutter/material.dart';
+
+import 'package:colors/cubit/game_cubit.dart';
+import 'package:colors/models/game.dart';
+import 'package:colors/ui/widgets/game/game_board.dart';
+import 'package:colors/ui/widgets/game/game_top_indicator.dart';
+import 'package:colors/ui/widgets/game/message_game_end.dart';
+import 'package:colors/ui/widgets/game/select_color_bar.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;
+
+        return Column(
+          mainAxisAlignment: MainAxisAlignment.start,
+          crossAxisAlignment: CrossAxisAlignment.center,
+          children: [
+            const SizedBox(height: 8),
+            const GameTopIndicatorWidget(),
+            const SizedBox(height: 2),
+            const GameBoard(),
+            const Expanded(
+              child: SizedBox(height: 2),
+            ),
+            currentGame.isFinished ? const EndGameMessage() : const SelectColorBar(),
+          ],
+        );
+      },
+    );
+  }
+}
diff --git a/lib/ui/widgets/game/game_board.dart b/lib/ui/widgets/game/game_board.dart
new file mode 100644
index 0000000000000000000000000000000000000000..385fc17de52368f835b2d83fe25531dc40ce523d
--- /dev/null
+++ b/lib/ui/widgets/game/game_board.dart
@@ -0,0 +1,43 @@
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:flutter/material.dart';
+
+import 'package:colors/cubit/game_cubit.dart';
+import 'package:colors/models/game.dart';
+import 'package:colors/ui/painters/board_painter.dart';
+
+class GameBoard extends StatelessWidget {
+  const GameBoard({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        final Game currentGame = gameState.currentGame;
+        final double boardWidth = MediaQuery.of(context).size.width;
+
+        return GestureDetector(
+          onTapUp: (details) {
+            final double xTap = details.localPosition.dx;
+            final double yTap = details.localPosition.dy;
+            final int boardSize = currentGame.gameSettings.boardSize;
+            final int col = xTap ~/ (boardWidth / boardSize);
+            final int row = yTap ~/ (boardWidth / boardSize);
+            final int cellValue = currentGame.board.getCellValue(col, row);
+
+            final GameCubit gameCubit = BlocProvider.of<GameCubit>(context);
+            gameCubit.fillBoardFromFirstCell(cellValue);
+          },
+          child: CustomPaint(
+            size: Size(boardWidth, boardWidth),
+            willChange: false,
+            painter: BoardPainter(
+              game: currentGame,
+              colorScheme: Theme.of(context).colorScheme,
+            ),
+            isComplex: true,
+          ),
+        );
+      },
+    );
+  }
+}
diff --git a/lib/ui/widgets/game/game_top_indicator.dart b/lib/ui/widgets/game/game_top_indicator.dart
new file mode 100644
index 0000000000000000000000000000000000000000..93948cd0e17629e81e6f7a90ac1b3de091b3969d
--- /dev/null
+++ b/lib/ui/widgets/game/game_top_indicator.dart
@@ -0,0 +1,70 @@
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:flutter/material.dart';
+
+import 'package:colors/cubit/game_cubit.dart';
+import 'package:colors/models/game.dart';
+
+class GameTopIndicatorWidget extends StatelessWidget {
+  const GameTopIndicatorWidget({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        final Game currentGame = gameState.currentGame;
+
+        String progressIndicator = '${currentGame.progress}/${currentGame.progressTotal}';
+
+        if (currentGame.movesCount > 0) {
+          progressIndicator += ' (+${currentGame.progressDelta})';
+        }
+
+        Color maxMovesCountColor = Colors.grey;
+        if (currentGame.movesCount > currentGame.maxMovesCount) {
+          maxMovesCountColor = Colors.red;
+        }
+
+        return Table(
+          children: [
+            TableRow(
+              children: [
+                Column(
+                  children: [
+                    Text(
+                      currentGame.movesCount.toString(),
+                      style: TextStyle(
+                        fontSize: 35,
+                        fontWeight: FontWeight.w600,
+                        color: Theme.of(context).colorScheme.primary,
+                      ),
+                    )
+                  ],
+                ),
+                Column(
+                  children: [
+                    Text(
+                      '(max: ${currentGame.maxMovesCount})',
+                      style: TextStyle(
+                        fontSize: 15,
+                        fontWeight: FontWeight.w600,
+                        color: maxMovesCountColor,
+                      ),
+                    ),
+                    Text(
+                      progressIndicator,
+                      style: const TextStyle(
+                        fontSize: 15,
+                        fontWeight: FontWeight.w600,
+                        color: Colors.green,
+                      ),
+                    ),
+                  ],
+                ),
+              ],
+            ),
+          ],
+        );
+      },
+    );
+  }
+}
diff --git a/lib/ui/widgets/game/indicator_top.dart b/lib/ui/widgets/game/indicator_top.dart
deleted file mode 100644
index 610037e62041a72e5b0cbc246740eb8b35f0e8f4..0000000000000000000000000000000000000000
--- a/lib/ui/widgets/game/indicator_top.dart
+++ /dev/null
@@ -1,64 +0,0 @@
-import 'package:flutter/material.dart';
-
-import 'package:colors/provider/data.dart';
-
-class TopIndicator extends StatelessWidget {
-  const TopIndicator({super.key, required this.myProvider});
-
-  final Data myProvider;
-
-  @override
-  Widget build(BuildContext context) {
-    String progressIndicator = '${myProvider.progress}/${myProvider.progressTotal}';
-
-    if (myProvider.movesCount > 0) {
-      progressIndicator += ' (+${myProvider.progressDelta})';
-    }
-
-    Color maxMovesCountColor = Colors.grey;
-    if (myProvider.movesCount > myProvider.maxMovesCount) {
-      maxMovesCountColor = Colors.red;
-    }
-
-    return Table(
-      children: [
-        TableRow(
-          children: [
-            Column(
-              children: [
-                Text(
-                  myProvider.movesCount.toString(),
-                  style: const TextStyle(
-                    fontSize: 35,
-                    fontWeight: FontWeight.w600,
-                    color: Colors.grey,
-                  ),
-                ),
-              ],
-            ),
-            Column(
-              children: [
-                Text(
-                  '(max: ${myProvider.maxMovesCount})',
-                  style: TextStyle(
-                    fontSize: 15,
-                    fontWeight: FontWeight.w600,
-                    color: maxMovesCountColor,
-                  ),
-                ),
-                Text(
-                  progressIndicator,
-                  style: const TextStyle(
-                    fontSize: 15,
-                    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 4a9cd90d8a48818ea1f44541a02c9cfe406e3d8f..2a5cae825069b95e1c4cc9865c1c6acf678516ee 100644
--- a/lib/ui/widgets/game/message_game_end.dart
+++ b/lib/ui/widgets/game/message_game_end.dart
@@ -1,44 +1,50 @@
+import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:flutter/material.dart';
 
-import 'package:colors/ui/widgets/home/button_game_restart.dart';
-import 'package:colors/provider/data.dart';
+import 'package:colors/cubit/game_cubit.dart';
+import 'package:colors/models/game.dart';
+import 'package:colors/ui/widgets/game/button_game_restart.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/game_fail.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/game_fail.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: [decorationImage]),
-              Column(children: [RestartGameButton(myProvider: myProvider)]),
-              Column(children: [decorationImage]),
-              Column(children: [decorationImage]),
+              TableRow(
+                children: [
+                  Column(children: [decorationImage]),
+                  Column(children: [decorationImage]),
+                  const Column(children: [RestartGameButton()]),
+                  Column(children: [decorationImage]),
+                  Column(children: [decorationImage]),
+                ],
+              ),
             ],
           ),
-        ],
-      ),
+        );
+      },
     );
   }
 }
diff --git a/lib/ui/widgets/game/select_color_bar.dart b/lib/ui/widgets/game/select_color_bar.dart
index 8211b46a9d9d47ab429c4996735c285c26f4aa30..3b8addb9f96cbe10f766008599da87eb98ad518a 100644
--- a/lib/ui/widgets/game/select_color_bar.dart
+++ b/lib/ui/widgets/game/select_color_bar.dart
@@ -1,36 +1,42 @@
+import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:flutter/material.dart';
 
-import 'package:colors/entities/cell.dart';
-import 'package:colors/provider/data.dart';
+import 'package:colors/cubit/game_cubit.dart';
+import 'package:colors/models/cell.dart';
+import 'package:colors/ui/widgets/game/cell_interactive.dart';
 
 class SelectColorBar extends StatelessWidget {
-  const SelectColorBar({super.key, required this.myProvider});
-
-  final Data myProvider;
+  const SelectColorBar({super.key});
 
   @override
   Widget build(BuildContext context) {
-    final int maxValue = myProvider.colorsCount;
-    final ColorScheme colorScheme = Theme.of(context).colorScheme;
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        final double blockWidth = MediaQuery.of(context).size.width;
+        final ColorScheme colorScheme = Theme.of(context).colorScheme;
+        final int maxValue = gameState.currentGame.gameSettings.colorsCount;
 
-    return Container(
-      margin: const EdgeInsets.all(2),
-      padding: const EdgeInsets.all(2),
-      child: Table(
-        defaultColumnWidth: const IntrinsicColumnWidth(),
-        children: [
-          TableRow(
-            children: [
-              for (int value = 1; value <= maxValue; value++)
-                Column(
-                  children: [
-                    Cell(value).interactiveWidget(myProvider, colorScheme),
-                  ],
-                ),
-            ],
-          ),
-        ],
-      ),
+        return Table(
+          defaultColumnWidth: const IntrinsicColumnWidth(),
+          children: [
+            TableRow(
+              children: [
+                for (int value = 1; value <= maxValue; value++)
+                  Column(
+                    children: [
+                      InteractiveCell(
+                        cell: Cell(value),
+                        colorScheme: colorScheme,
+                        currentGame: gameState.currentGame,
+                        itemWidth: blockWidth / maxValue,
+                      ),
+                    ],
+                  ),
+              ],
+            ),
+          ],
+        );
+      },
     );
   }
 }
diff --git a/lib/ui/widgets/global_app_bar.dart b/lib/ui/widgets/global_app_bar.dart
new file mode 100644
index 0000000000000000000000000000000000000000..b3850bef24b8409f46d88e34ffc3907cff006bbc
--- /dev/null
+++ b/lib/ui/widgets/global_app_bar.dart
@@ -0,0 +1,82 @@
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:flutter/material.dart';
+
+import 'package:colors/config/menu.dart';
+import 'package:colors/cubit/game_cubit.dart';
+import 'package:colors/cubit/nav_cubit.dart';
+import 'package:colors/models/game.dart';
+import 'package:colors/ui/widgets/helpers/app_titles.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 GameCubit gameCubit = BlocProvider.of<GameCubit>(context);
+            final Game currentGame = gameState.currentGame;
+
+            final List<Widget> menuActions = [];
+
+            if (currentGame.isRunning) {
+              menuActions.add(TextButton(
+                onPressed: null,
+                onLongPress: () => gameCubit.quitGame(),
+                child: const Image(
+                  image: AssetImage('assets/icons/button_back.png'),
+                  fit: BoxFit.fill,
+                ),
+              ));
+            } 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/helpers/app_titles.dart b/lib/ui/widgets/helpers/app_titles.dart
new file mode 100644
index 0000000000000000000000000000000000000000..7cbbb2030419047b3dcf093a2195a498bd8e8ce9
--- /dev/null
+++ b/lib/ui/widgets/helpers/app_titles.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/header_app.dart b/lib/ui/widgets/helpers/header_app.dart
similarity index 77%
rename from lib/ui/widgets/header_app.dart
rename to lib/ui/widgets/helpers/header_app.dart
index bf54b77375fbd0260f876f2885d0572b71715383..b5c5be05f6636cf488dcdb5bbc4d6f049b98de11 100644
--- a/lib/ui/widgets/header_app.dart
+++ b/lib/ui/widgets/helpers/header_app.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/outlined_text_widget.dart b/lib/ui/widgets/helpers/outlined_text_widget.dart
new file mode 100644
index 0000000000000000000000000000000000000000..8e33709bd71085ea7a64084a231f692953af203d
--- /dev/null
+++ b/lib/ui/widgets/helpers/outlined_text_widget.dart
@@ -0,0 +1,49 @@
+import 'package:flutter/material.dart';
+
+class OutlinedText extends StatelessWidget {
+  const OutlinedText({
+    super.key,
+    required this.text,
+    required this.fontSize,
+    required this.textColor,
+    required this.outlineColor,
+  });
+
+  final String text;
+  final double fontSize;
+  final Color textColor;
+  final Color outlineColor;
+
+  @override
+  Widget build(BuildContext context) {
+    final double delta = fontSize / 35;
+
+    return Text(
+      text,
+      style: TextStyle(
+        inherit: true,
+        fontSize: fontSize,
+        fontWeight: FontWeight.w600,
+        color: textColor,
+        shadows: [
+          Shadow(
+            offset: Offset(-delta, -delta),
+            color: outlineColor,
+          ),
+          Shadow(
+            offset: Offset(delta, -delta),
+            color: outlineColor,
+          ),
+          Shadow(
+            offset: Offset(delta, delta),
+            color: outlineColor,
+          ),
+          Shadow(
+            offset: Offset(-delta, delta),
+            color: outlineColor,
+          ),
+        ],
+      ),
+    );
+  }
+}
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 80466e2cee86a677b4a3b6754cb2426daa06bddd..0000000000000000000000000000000000000000
--- a/lib/ui/widgets/home/button_game_start_new.dart
+++ /dev/null
@@ -1,38 +0,0 @@
-import 'package:flutter/material.dart';
-
-import 'package:colors/provider/data.dart';
-import 'package:colors/ui/layout/parameters.dart';
-import 'package:colors/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..55525a9b2402805ed513f789958c568493f28089
--- /dev/null
+++ b/lib/ui/widgets/parameters.dart
@@ -0,0 +1,121 @@
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:flutter/material.dart';
+
+import 'package:colors/config/default_game_settings.dart';
+import 'package:colors/config/default_global_settings.dart';
+import 'package:colors/cubit/settings_game_cubit.dart';
+import 'package:colors/cubit/settings_global_cubit.dart';
+import 'package:colors/ui/painters/parameter_painter.dart';
+import 'package:colors/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 = [];
+
+    lines.add(SizedBox(height: separatorHeight));
+
+    // 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 - 30;
+
+              return TextButton(
+                child: Container(
+                  margin: const EdgeInsets.all(0),
+                  padding: const EdgeInsets.all(0),
+                  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/ui/widgets/settings/theme_card.dart b/lib/ui/widgets/settings/theme_card.dart
index 5fd7bd79e680c32a419bc9bea0c80e1fdec49348..834c67dbd317b84767c411f3a6b1822cfa1ed9f1 100644
--- a/lib/ui/widgets/settings/theme_card.dart
+++ b/lib/ui/widgets/settings/theme_card.dart
@@ -1,5 +1,5 @@
-import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:flutter/material.dart';
 
 import 'package:colors/cubit/theme_cubit.dart';
 
diff --git a/lib/utils/board_utils.dart b/lib/utils/board_utils.dart
deleted file mode 100644
index 7a63ce83b58e8024c8b31bd36d37276c606c27f4..0000000000000000000000000000000000000000
--- a/lib/utils/board_utils.dart
+++ /dev/null
@@ -1,168 +0,0 @@
-import 'dart:math';
-import 'dart:async';
-
-import 'package:colors/entities/cell.dart';
-import 'package:colors/provider/data.dart';
-import 'package:colors/utils/tools.dart';
-
-class BoardUtils {
-  static printGrid(List board) {
-    const String stringValues = '012345678';
-    printlog('');
-    printlog('-------');
-    for (int rowIndex = 0; rowIndex < board.length; rowIndex++) {
-      String row = '';
-      for (int colIndex = 0; colIndex < board[rowIndex].length; colIndex++) {
-        row += stringValues[board[rowIndex][colIndex].value];
-      }
-      printlog(row);
-    }
-    printlog('-------');
-    printlog('');
-  }
-
-  static createNewBoard(Data myProvider) {
-    final int boardSize = myProvider.boardSize;
-    final int maxValue = myProvider.colorsCount;
-
-    Random rand = Random();
-
-    Board board = [];
-    for (int rowIndex = 0; rowIndex < boardSize; rowIndex++) {
-      List<Cell> row = [];
-      for (int colIndex = 0; colIndex < boardSize; colIndex++) {
-        final int value = 1 + rand.nextInt(maxValue);
-        row.add(Cell(value));
-      }
-      board.add(row);
-    }
-    printGrid(board);
-
-    myProvider.resetGame();
-    myProvider.updateBoard(board);
-    myProvider.updateMaxMovesCount(computeMaxMovesCountLimit(myProvider));
-
-    final int initProgress = BoardUtils.getSiblingFillableCells(myProvider, 0, 0, [
-      [0, 0]
-    ]).length;
-    myProvider.updateProgress(initProgress);
-  }
-
-  static int computeMaxMovesCountLimit(myProvider) {
-    final int boardSize = myProvider.boardSize;
-    final int colorsCount = myProvider.colorsCount;
-
-    final int baseMaxMovesCount = (30 * (boardSize * colorsCount) / (17 * 6)).round();
-    final int deltaFromLevel =
-        myProvider.getMovesCountLimitDeltaFromLevelParameter(myProvider.parameterLevel);
-
-    return baseMaxMovesCount + deltaFromLevel;
-  }
-
-  static fillBoardFromFirstCell(Data myProvider, int value) {
-    List<List<int>> cellsToFill = BoardUtils.getSiblingFillableCells(myProvider, 0, 0, [
-      [0, 0]
-    ]);
-    final int progressBeforeMove = cellsToFill.length;
-
-    myProvider.incrementMovesCount();
-
-    // Sort cells from the closest to the furthest, relatively to the top left corner
-    cellsToFill
-        .sort((a, b) => (pow(a[0], 2) + pow(a[1], 2)).compareTo(pow(b[0], 2) + pow(b[1], 2)));
-
-    const interval = Duration(milliseconds: 10);
-    int cellIndex = 0;
-    myProvider.updateAnimationInProgress(true);
-    Timer.periodic(
-      interval,
-      (Timer timer) {
-        if (cellIndex < cellsToFill.length) {
-          myProvider.updateCellValue(
-              cellsToFill[cellIndex][1], cellsToFill[cellIndex][0], value);
-          cellIndex++;
-        } else {
-          timer.cancel();
-
-          int progressAfterMove = BoardUtils.getSiblingFillableCells(myProvider, 0, 0, [
-            [0, 0]
-          ]).length;
-          int progressDelta = progressAfterMove - progressBeforeMove;
-          myProvider.updateProgressDelta(progressDelta);
-          myProvider.updateProgress(progressAfterMove);
-
-          myProvider.updateAnimationInProgress(false);
-
-          if (BoardUtils.checkBoardIsSolved(myProvider)) {
-            myProvider.updateGameWon(true);
-          }
-        }
-      },
-    );
-  }
-
-  static List<List<int>> getSiblingFillableCells(
-    Data myProvider,
-    int row,
-    int col,
-    List<List<int>> siblingCells,
-  ) {
-    final Board board = myProvider.board;
-    final int boardSize = myProvider.boardSize;
-
-    final int referenceValue = board[row][col].value;
-
-    for (int deltaRow = -1; deltaRow <= 1; deltaRow++) {
-      for (int deltaCol = -1; deltaCol <= 1; deltaCol++) {
-        if (deltaCol == 0 || deltaRow == 0) {
-          final int candidateRow = row + deltaRow;
-          final int candidateCol = col + deltaCol;
-
-          if ((candidateRow >= 0 && candidateRow < boardSize) &&
-              (candidateCol >= 0 && candidateCol < boardSize)) {
-            if (board[candidateRow][candidateCol].value == referenceValue) {
-              bool alreadyFound = false;
-              for (int index = 0; index < siblingCells.length; index++) {
-                if ((siblingCells[index][0] == candidateRow) &&
-                    (siblingCells[index][1] == candidateCol)) {
-                  alreadyFound = true;
-                }
-              }
-              if (!alreadyFound) {
-                siblingCells.add([candidateRow, candidateCol]);
-                siblingCells = getSiblingFillableCells(
-                  myProvider,
-                  candidateRow,
-                  candidateCol,
-                  siblingCells,
-                );
-              }
-            }
-          }
-        }
-      }
-    }
-
-    return siblingCells;
-  }
-
-  static bool checkBoardIsSolved(Data myProvider) {
-    final Board board = myProvider.board;
-    final int boardSize = myProvider.boardSize;
-
-    // check grid is fully completed and does not contain conflict
-    int previousValue = board[0][0].value;
-    for (int row = 0; row < boardSize; row++) {
-      for (int col = 0; col < boardSize; col++) {
-        if (board[row][col].value == 0 || board[row][col].value != previousValue) {
-          return false;
-        }
-        previousValue = board[row][col].value;
-      }
-    }
-
-    printlog('-> ok grid solved!');
-
-    return true;
-  }
-}
diff --git a/lib/utils/color_extensions.dart b/lib/utils/color_extensions.dart
new file mode 100644
index 0000000000000000000000000000000000000000..39c9322574b0fbfae3a7b9ba4eb964942b807d37
--- /dev/null
+++ b/lib/utils/color_extensions.dart
@@ -0,0 +1,35 @@
+import 'dart:ui';
+
+import 'package:flutter/material.dart';
+
+extension ColorExtension on Color {
+  Color darken([int percent = 40]) {
+    assert(1 <= percent && percent <= 100);
+    final value = 1 - percent / 100;
+    return Color.fromARGB(
+      alpha,
+      (red * value).round(),
+      (green * value).round(),
+      (blue * value).round(),
+    );
+  }
+
+  Color lighten([int percent = 40]) {
+    assert(1 <= percent && percent <= 100);
+    final value = percent / 100;
+    return Color.fromARGB(
+      alpha,
+      (red + ((255 - red) * value)).round(),
+      (green + ((255 - green) * value)).round(),
+      (blue + ((255 - blue) * value)).round(),
+    );
+  }
+
+  Color avg(Color other) {
+    final red = (this.red + other.red) ~/ 2;
+    final green = (this.green + other.green) ~/ 2;
+    final blue = (this.blue + other.blue) ~/ 2;
+    final alpha = (this.alpha + other.alpha) ~/ 2;
+    return Color.fromARGB(alpha, red, green, blue);
+  }
+}
diff --git a/lib/utils/color_theme.dart b/lib/utils/color_theme.dart
index 476f82bd0fc18b97835e2dcfc101eff1365b53cb..73d2e37c974ac8b52a94839906e4f73e5246670e 100644
--- a/lib/utils/color_theme.dart
+++ b/lib/utils/color_theme.dart
@@ -1,6 +1,8 @@
+import 'package:colors/config/default_global_settings.dart';
+
 class ColorTheme {
   static const Map<String, List<int>> borderColors = {
-    'default': [
+    DefaultGlobalSettings.skinValueColors: [
       0xffffff,
       0xe63a3f,
       0x708cfd,
diff --git a/lib/utils/game_utils.dart b/lib/utils/game_utils.dart
deleted file mode 100644
index 6b7e2cf53e809c641481d45bf950fa8d0d682d6f..0000000000000000000000000000000000000000
--- a/lib/utils/game_utils.dart
+++ /dev/null
@@ -1,20 +0,0 @@
-import 'package:colors/provider/data.dart';
-import 'package:colors/utils/board_utils.dart';
-import 'package:colors/utils/tools.dart';
-
-class GameUtils {
-  static void quitGame(Data myProvider) {
-    myProvider.updateGameIsRunning(false);
-  }
-
-  static void startNewGame(Data myProvider) {
-    printlog('Starting game');
-    printlog('- level: ${myProvider.parameterLevel}');
-    printlog('- size: ${myProvider.boardSize}');
-    printlog('- colors: ${myProvider.colorsCount}');
-
-    BoardUtils.createNewBoard(myProvider);
-
-    myProvider.updateGameIsRunning(true);
-  }
-}
diff --git a/lib/utils/tools.dart b/lib/utils/tools.dart
index fd48b2b009b80b22248d6e7f08a63e96c4065bd7..8ed7a5313f39ef5257deba3c3119c0f41ab10cd9 100644
--- a/lib/utils/tools.dart
+++ b/lib/utils/tools.dart
@@ -1,7 +1,15 @@
 import 'package:flutter/foundation.dart';
+import 'package:flutter/material.dart';
 
 void printlog(String message) {
   if (!kReleaseMode) {
     debugPrint(message);
   }
 }
+
+Widget buildImageContainerWidget(String imageAssetCode) {
+  return Image(
+    image: AssetImage('assets/icons/$imageAssetCode.png'),
+    fit: BoxFit.fill,
+  );
+}
diff --git a/pubspec.lock b/pubspec.lock
index 2885f1ae8482614c38711b57e048f2bd0e10e178..25b5be0248780b099e0f72fc5dab70bd5ce13f92 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: "432698c31a488dd64c56d4759f20d04844baba5e9e4f2cb1abb9676257918b17"
       url: "https://pub.dev"
     source: hosted
-    version: "3.0.5"
+    version: "3.0.6"
   easy_logger:
     dependency: transitive
     description:
@@ -106,31 +106,23 @@ 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: "9e8c3858111da373efc5aa341de011d9bd23e2c5c5e0c62bccf32438e192d7b1"
       url: "https://pub.dev"
     source: hosted
-    version: "3.0.1"
+    version: "3.0.2"
   flutter_localizations:
     dependency: transitive
     description: flutter
     source: sdk
     version: "0.0.0"
-  flutter_swipe:
-    dependency: "direct main"
-    description:
-      name: flutter_swipe
-      sha256: dc6541bac3a0545ce15a3fa15913f6250532062960bf6b0ad4562d02f14a8545
-      url: "https://pub.dev"
-    source: hosted
-    version: "1.0.1"
   flutter_web_plugins:
     dependency: transitive
     description: flutter
@@ -148,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:
@@ -164,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:
@@ -208,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"
@@ -244,18 +228,18 @@ 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:
@@ -305,7 +289,7 @@ packages:
     source: hosted
     version: "2.1.8"
   provider:
-    dependency: "direct main"
+    dependency: transitive
     description:
       name: provider
       sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c
@@ -313,21 +297,21 @@ 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:
@@ -356,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:
@@ -433,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: "464f5674532865248444b4c3daca12bd9bf2d7c47f759ce2617986e7229494a8"
+      sha256: "0eaf06e3446824099858367950a813472af675116bf63f008a4c2a75ae13e9cb"
       url: "https://pub.dev"
     source: hosted
-    version: "5.2.0"
+    version: "5.5.0"
   xdg_directories:
     dependency: transitive
     description:
@@ -454,5 +438,5 @@ packages:
     source: hosted
     version: "1.0.4"
 sdks:
-  dart: ">=3.3.0-279.1.beta <4.0.0"
-  flutter: ">=3.16.0"
+  dart: ">=3.3.0 <4.0.0"
+  flutter: ">=3.19.0"
diff --git a/pubspec.yaml b/pubspec.yaml
index 5e4adf9edb3365b8d4d013bb786614487cf26b61..e6b8af0dde4d69af11d8f3a645b1418b75662251 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -2,7 +2,7 @@ name: colors
 description: Fill the board, a colorfull game!
 
 publish_to: 'none'
-version: 0.0.38+38
+version: 0.0.39+39
 
 environment:
   sdk: '^3.0.0'
@@ -14,15 +14,10 @@ dependencies:
   easy_localization: ^3.0.1
   equatable: ^2.0.5
   flutter_bloc: ^8.1.1
-  flutter_swipe: ^1.0.1
   hive: ^2.2.3
   hydrated_bloc: ^9.0.0
-  overlay_support: ^2.1.0
-  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
-  provider: ^6.0.5
   unicons: ^2.1.1
 
 dev_dependencies:
@@ -32,7 +27,6 @@ flutter:
   uses-material-design: true
   assets:
     - assets/icons/
-    - assets/skins/
     - assets/translations/
 
   fonts: