diff --git a/android/gradle.properties b/android/gradle.properties
index 3b4960c1971a8b84a921046012e24eefff6ad4e7..5b52231bd50fd20f2ed25aab85f3ba90e51a05e8 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.1.19
-app.versionCode=40
+app.versionName=0.2.0
+app.versionCode=41
diff --git a/assets/icons/button_start.png b/assets/icons/button_start.png
deleted file mode 100644
index f0ead9744e59874fa15d70d7e5e49336a15009dd..0000000000000000000000000000000000000000
Binary files a/assets/icons/button_start.png and /dev/null differ
diff --git a/assets/icons/level_easy.png b/assets/icons/level_easy.png
deleted file mode 100644
index 9d3456d576604e1ac79281132bc958851eb7ee13..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 c0205b11bf6ab02f8c18542cd395c44dbead210b..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 a1ab48924779cbe1c30ff0fde110b6be827720ed..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 2077c8358db7ce531b3634f3a40e96c2032b4851..0000000000000000000000000000000000000000
Binary files a/assets/icons/level_nightmare.png and /dev/null differ
diff --git a/assets/icons/size_10x10.png b/assets/icons/size_10x10.png
deleted file mode 100644
index d374f1bc3acf0dafd1d6e03c7a0af4fab71aea89..0000000000000000000000000000000000000000
Binary files a/assets/icons/size_10x10.png and /dev/null differ
diff --git a/assets/icons/size_15x15.png b/assets/icons/size_15x15.png
deleted file mode 100644
index b18f855d5b116dbc06f9fba1298ba84db538b1b5..0000000000000000000000000000000000000000
Binary files a/assets/icons/size_15x15.png and /dev/null differ
diff --git a/assets/icons/size_20x20.png b/assets/icons/size_20x20.png
deleted file mode 100644
index 547ba1ec72fc2175ef32d91f99587f4201ad9840..0000000000000000000000000000000000000000
Binary files a/assets/icons/size_20x20.png and /dev/null differ
diff --git a/assets/icons/skin_default.png b/assets/icons/skin_default.png
deleted file mode 100644
index 43dc59805c9f2d9d171b9e54bdccb8c82728d18b..0000000000000000000000000000000000000000
Binary files a/assets/icons/skin_default.png and /dev/null differ
diff --git a/assets/translations/en.json b/assets/translations/en.json
index e1e319186b59acfb7adcf7d8fcbb0b37dfe7f21c..0348cd0a3fe70f153cf9062cf63c55803b5baba3 100644
--- a/assets/translations/en.json
+++ b/assets/translations/en.json
@@ -1,16 +1,12 @@
 {
   "app_name": "Minehunter",
 
-  "long_press_to_quit": "Long press to quit game...",
-
-  "bottom_nav_home": "Game",
-  "bottom_nav_settings": "Settings",
-  "bottom_nav_about": "About",
-
   "settings_title": "Settings",
   "settings_label_theme": "Theme mode",
 
   "about_title": "About",
   "about_content": "Minehunter.",
-  "about_version": "Version: {version}"
+  "about_version": "Version: {version}",
+
+  "": ""
 }
diff --git a/assets/translations/fr.json b/assets/translations/fr.json
index 9243b745c43ec3c9f03af8f7127d356dd7a3fa85..08923674f984262ce593f327dce8da7ef22ab79f 100644
--- a/assets/translations/fr.json
+++ b/assets/translations/fr.json
@@ -1,16 +1,12 @@
 {
   "app_name": "Démineur",
 
-  "long_press_to_quit": "Appuyer longtemps pour quitter le jeu...",
-
-  "bottom_nav_home": "Jeu",
-  "bottom_nav_settings": "Réglages",
-  "bottom_nav_about": "Infos",
-
   "settings_title": "Réglages",
   "settings_label_theme": "Thème de couleurs",
 
   "about_title": "Informations",
   "about_content": "Démineur.",
-  "about_version": "Version : {version}"
+  "about_version": "Version : {version}",
+
+  "": ""
 }
diff --git a/assets/icons/button_back.png b/assets/ui/button_back.png
similarity index 100%
rename from assets/icons/button_back.png
rename to assets/ui/button_back.png
diff --git a/assets/icons/button_delete_saved_game.png b/assets/ui/button_delete_saved_game.png
similarity index 100%
rename from assets/icons/button_delete_saved_game.png
rename to assets/ui/button_delete_saved_game.png
diff --git a/assets/icons/button_resume_game.png b/assets/ui/button_resume_game.png
similarity index 100%
rename from assets/icons/button_resume_game.png
rename to assets/ui/button_resume_game.png
diff --git a/assets/ui/button_start.png b/assets/ui/button_start.png
new file mode 100644
index 0000000000000000000000000000000000000000..6845e2f5c21598ab61f1684d2075aeec0334bf23
Binary files /dev/null and b/assets/ui/button_start.png differ
diff --git a/assets/icons/game_fail.png b/assets/ui/game_fail.png
similarity index 100%
rename from assets/icons/game_fail.png
rename to assets/ui/game_fail.png
diff --git a/assets/icons/game_win.png b/assets/ui/game_win.png
similarity index 100%
rename from assets/icons/game_win.png
rename to assets/ui/game_win.png
diff --git a/assets/icons/placeholder.png b/assets/ui/placeholder.png
similarity index 100%
rename from assets/icons/placeholder.png
rename to assets/ui/placeholder.png
diff --git a/fastlane/metadata/android/en-US/changelogs/41.txt b/fastlane/metadata/android/en-US/changelogs/41.txt
new file mode 100644
index 0000000000000000000000000000000000000000..d4afd512e55b3fd8ffbfd795adb9b00832e5aaef
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/41.txt
@@ -0,0 +1 @@
+Improve/normalize game architecture.
diff --git a/fastlane/metadata/android/fr-FR/changelogs/41.txt b/fastlane/metadata/android/fr-FR/changelogs/41.txt
new file mode 100644
index 0000000000000000000000000000000000000000..6a9871a5eb8eb3c6e9106520f1cbf1f39f9e5ef7
--- /dev/null
+++ b/fastlane/metadata/android/fr-FR/changelogs/41.txt
@@ -0,0 +1 @@
+Amélioration/normalisation de l'architecture du jeu.
diff --git a/icons/build_game_icons.sh b/icons/build_game_icons.sh
deleted file mode 100755
index 150bc83cd966790990f2d668f43b809b375aad59..0000000000000000000000000000000000000000
--- a/icons/build_game_icons.sh
+++ /dev/null
@@ -1,159 +0,0 @@
-#! /bin/bash
-
-# Check dependencies
-command -v inkscape >/dev/null 2>&1 || { echo >&2 "I require inkscape but it's not installed. Aborting."; exit 1; }
-command -v scour >/dev/null 2>&1 || { echo >&2 "I require scour but it's not installed. Aborting."; exit 1; }
-command -v optipng >/dev/null 2>&1 || { echo >&2 "I require optipng but it's not installed. Aborting."; exit 1; }
-
-CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
-BASE_DIR="$(dirname "${CURRENT_DIR}")"
-ASSETS_DIR="${BASE_DIR}/assets"
-
-OPTIPNG_OPTIONS="-preserve -quiet -o7"
-ICON_SIZE=192
-
-#######################################################
-
-# Game images
-AVAILABLE_GAME_IMAGES="
-  button_back
-  button_start
-  button_resume_game
-  button_delete_saved_game
-  game_fail
-  game_win
-  placeholder
-"
-
-# Settings images
-AVAILABLES_GAME_SETTINGS="
-  level:easy,medium,hard,nightmare
-  size:10x10,15x15,20x20
-"
-
-# Skins
-AVAILABLE_SKINS="
-  default
-"
-
-# Images per skin
-SKIN_IMAGES="
-  empty
-  tile_0
-  tile_1
-  tile_2
-  tile_3
-  tile_4
-  tile_5
-  tile_6
-  tile_7
-  tile_8
-  tile_flag_ko
-  tile_flag_ok
-  tile_flag
-  tile_mine_not_found
-  tile_mine
-  tile_unknown
-  button_mark_mine_on
-  button_mark_mine_off
-  indicator_report_on
-  indicator_report_off
-  indicator_walk_on
-  indicator_walk_off
-"
-
-#######################################################
-
-# optimize svg
-function optimize_svg() {
-  SOURCE="$1"
-
-  cp ${SOURCE} ${SOURCE}.tmp
-  scour \
-      --remove-descriptive-elements \
-      --enable-id-stripping \
-      --enable-viewboxing \
-      --enable-comment-stripping \
-      --nindent=4 \
-      --quiet \
-      -i ${SOURCE}.tmp \
-      -o ${SOURCE}
-  rm ${SOURCE}.tmp
-}
-
-# build icons
-function build_icon() {
-  SOURCE="$1"
-  TARGET="$2"
-
-  echo "Building ${TARGET}"
-
-  if [ ! -f "${SOURCE}" ]; then
-    echo "Missing file: ${SOURCE}"
-    exit 1
-  fi
-
-  optimize_svg "${SOURCE}"
-
-  inkscape \
-      --export-width=${ICON_SIZE} \
-      --export-height=${ICON_SIZE} \
-      --export-filename=${TARGET} \
-      ${SOURCE}
-
-  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}
-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/button_start.svg b/icons/button_start.svg
deleted file mode 100644
index 633a63410502bc516703555911588df2143957f1..0000000000000000000000000000000000000000
--- a/icons/button_start.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 93.665 93.676" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x=".44662" y=".89101" width="92.772" height="91.894" ry="11.689" fill="#49a1ee" stroke="#fff" stroke-width=".238"/><g transform="matrix(.8268 0 0 .8268 9.0269 8.3829)" fill="#fefeff" stroke-linecap="round" stroke-linejoin="round"><path d="m34.852 25.44c-1.1248-1.1302-4.0012-1.1302-4.0012 0v45.921c0 1.1316 2.8832 1.1316 4.0121 0l37.693-20.918c1.1289-1.1248 1.1479-2.9551 0.02171-4.084z" stroke="#105ca1" stroke-width="8.257"/><path d="m36.382 28.754c-0.96243-0.96706-3.4236-0.96706-3.4236 0v39.292c0 0.96825 2.467 0.96825 3.4329 0l32.252-17.898c0.96594-0.96243 0.9822-2.5285 0.01858-3.4945z" stroke="#feffff" stroke-width="4.314"/></g></svg>
diff --git a/icons/level_easy.svg b/icons/level_easy.svg
deleted file mode 100644
index 3702968ed134ed5aaecbba1550056ce2ddeeb268..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"/><g transform="matrix(.47655 0 0 .47655 27.173 27.173)" fill="#fff" stroke="#000" stroke-width="4.1968"><path d="m92.148 55.869c-0.626-0.939-1.482-1.519-2.568-1.739l-6.792-1.242c0.368-5.669-0.727-11.035-3.286-16.096l5.853-4.224c0.939-0.663 1.491-1.574 1.657-2.733 0.202-1.086-0.037-2.071-0.718-2.954l-0.469-0.718c-0.626-0.883-1.537-1.427-2.733-1.629-1.031-0.166-2.016 0.092-2.954 0.773l-5.632 4.059c-3.81-4.215-8.347-7.206-13.611-8.973l1.27-7.731c0.202-1.104-0.037-2.126-0.718-3.065-0.626-0.883-1.482-1.427-2.568-1.629l-0.856-0.166c-1.104-0.147-2.126 0.092-3.065 0.718-0.884 0.681-1.427 1.565-1.629 2.65l-1.16 7.427c-2.503-0.221-4.951-0.175-7.344 0.138-1.362 0.055-2.641 0.294-3.838 0.718-0.626 0.147-1.224 0.331-1.795 0.552l-3.451-7.51c-0.46-0.994-1.215-1.693-2.264-2.098-1.031-0.423-2.043-0.405-3.037 0.055l-0.773 0.414c-0.994 0.405-1.73 1.16-2.209 2.264-0.368 1.031-0.313 2.043 0.166 3.037l3.506 7.648c-0.202 0.11-0.405 0.249-0.607 0.414-5.264 3.681-9.019 8.31-11.265 13.888l-6.958-1.546c-1.086-0.276-2.098-0.074-3.037 0.607-0.994 0.534-1.592 1.344-1.795 2.43l-0.246 0.772c-0.203 1.104-0.018 2.172 0.552 3.203 0.626 0.883 1.491 1.463 2.595 1.739l6.626 1.546c-0.736 5.835 0.101 11.329 2.512 16.483l-5.411 3.672c-0.939 0.626-1.537 1.491-1.795 2.595-0.147 1.086 0.092 2.098 0.718 3.037l0.469 0.635c0.626 0.939 1.454 1.537 2.485 1.795 1.16 0.147 2.209-0.092 3.147-0.718l5.135-3.424c3.7 4.583 8.255 7.887 13.667 9.912l-1.242 6.323c-0.202 1.104 9e-3 2.154 0.635 3.147 0.626 0.883 1.482 1.427 2.568 1.629l0.801 0.166c1.086 0.258 2.098 0.101 3.037-0.469 0.939-0.681 1.509-1.574 1.712-2.678l1.242-6.074c6 0.626 11.651-0.285 16.952-2.733l4.003 6.074c0.626 0.939 1.509 1.518 2.651 1.739 1.049 0.258 2.043 0.074 2.982-0.552l0.69-0.387c0.939-0.626 1.537-1.518 1.795-2.678 0.203-1.086-9e-3 -2.098-0.635-3.037l-3.81-5.936c4.583-3.7 7.841-8.255 9.774-13.667l6.875 1.242c1.086 0.202 2.098-9e-3 3.037-0.635 0.883-0.607 1.427-1.463 1.629-2.568l0.166-0.773c0.202-1.103-0.01-2.143-0.636-3.119z" fill="#fff" stroke="#000" stroke-width="4.1968"/></g></svg>
diff --git a/icons/level_hard.svg b/icons/level_hard.svg
deleted file mode 100644
index 9b592568b6ddbf92ecc017fb4cb315d8e1721e8a..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"/><g transform="matrix(.47655 0 0 .47655 4.2858 6.7324)" fill="#fff" stroke="#000" stroke-width="4.1968"><path d="m92.148 55.869c-0.626-0.939-1.482-1.519-2.568-1.739l-6.792-1.242c0.368-5.669-0.727-11.035-3.286-16.096l5.853-4.224c0.939-0.663 1.491-1.574 1.657-2.733 0.202-1.086-0.037-2.071-0.718-2.954l-0.469-0.718c-0.626-0.883-1.537-1.427-2.733-1.629-1.031-0.166-2.016 0.092-2.954 0.773l-5.632 4.059c-3.81-4.215-8.347-7.206-13.611-8.973l1.27-7.731c0.202-1.104-0.037-2.126-0.718-3.065-0.626-0.883-1.482-1.427-2.568-1.629l-0.856-0.166c-1.104-0.147-2.126 0.092-3.065 0.718-0.884 0.681-1.427 1.565-1.629 2.65l-1.16 7.427c-2.503-0.221-4.951-0.175-7.344 0.138-1.362 0.055-2.641 0.294-3.838 0.718-0.626 0.147-1.224 0.331-1.795 0.552l-3.451-7.51c-0.46-0.994-1.215-1.693-2.264-2.098-1.031-0.423-2.043-0.405-3.037 0.055l-0.773 0.414c-0.994 0.405-1.73 1.16-2.209 2.264-0.368 1.031-0.313 2.043 0.166 3.037l3.506 7.648c-0.202 0.11-0.405 0.249-0.607 0.414-5.264 3.681-9.019 8.31-11.265 13.888l-6.958-1.546c-1.086-0.276-2.098-0.074-3.037 0.607-0.994 0.534-1.592 1.344-1.795 2.43l-0.246 0.772c-0.203 1.104-0.018 2.172 0.552 3.203 0.626 0.883 1.491 1.463 2.595 1.739l6.626 1.546c-0.736 5.835 0.101 11.329 2.512 16.483l-5.411 3.672c-0.939 0.626-1.537 1.491-1.795 2.595-0.147 1.086 0.092 2.098 0.718 3.037l0.469 0.635c0.626 0.939 1.454 1.537 2.485 1.795 1.16 0.147 2.209-0.092 3.147-0.718l5.135-3.424c3.7 4.583 8.255 7.887 13.667 9.912l-1.242 6.323c-0.202 1.104 9e-3 2.154 0.635 3.147 0.626 0.883 1.482 1.427 2.568 1.629l0.801 0.166c1.086 0.258 2.098 0.101 3.037-0.469 0.939-0.681 1.509-1.574 1.712-2.678l1.242-6.074c6 0.626 11.651-0.285 16.952-2.733l4.003 6.074c0.626 0.939 1.509 1.518 2.651 1.739 1.049 0.258 2.043 0.074 2.982-0.552l0.69-0.387c0.939-0.626 1.537-1.518 1.795-2.678 0.203-1.086-9e-3 -2.098-0.635-3.037l-3.81-5.936c4.583-3.7 7.841-8.255 9.774-13.667l6.875 1.242c1.086 0.202 2.098-9e-3 3.037-0.635 0.883-0.607 1.427-1.463 1.629-2.568l0.166-0.773c0.202-1.103-0.01-2.143-0.636-3.119z" fill="#fff" stroke="#000" stroke-width="4.1968"/></g><g transform="matrix(.47655 0 0 .47655 50.06 6.7324)" fill="#fff" stroke="#000" stroke-width="4.1968"><path d="m92.148 55.869c-0.626-0.939-1.482-1.519-2.568-1.739l-6.792-1.242c0.368-5.669-0.727-11.035-3.286-16.096l5.853-4.224c0.939-0.663 1.491-1.574 1.657-2.733 0.202-1.086-0.037-2.071-0.718-2.954l-0.469-0.718c-0.626-0.883-1.537-1.427-2.733-1.629-1.031-0.166-2.016 0.092-2.954 0.773l-5.632 4.059c-3.81-4.215-8.347-7.206-13.611-8.973l1.27-7.731c0.202-1.104-0.037-2.126-0.718-3.065-0.626-0.883-1.482-1.427-2.568-1.629l-0.856-0.166c-1.104-0.147-2.126 0.092-3.065 0.718-0.884 0.681-1.427 1.565-1.629 2.65l-1.16 7.427c-2.503-0.221-4.951-0.175-7.344 0.138-1.362 0.055-2.641 0.294-3.838 0.718-0.626 0.147-1.224 0.331-1.795 0.552l-3.451-7.51c-0.46-0.994-1.215-1.693-2.264-2.098-1.031-0.423-2.043-0.405-3.037 0.055l-0.773 0.414c-0.994 0.405-1.73 1.16-2.209 2.264-0.368 1.031-0.313 2.043 0.166 3.037l3.506 7.648c-0.202 0.11-0.405 0.249-0.607 0.414-5.264 3.681-9.019 8.31-11.265 13.888l-6.958-1.546c-1.086-0.276-2.098-0.074-3.037 0.607-0.994 0.534-1.592 1.344-1.795 2.43l-0.246 0.772c-0.203 1.104-0.018 2.172 0.552 3.203 0.626 0.883 1.491 1.463 2.595 1.739l6.626 1.546c-0.736 5.835 0.101 11.329 2.512 16.483l-5.411 3.672c-0.939 0.626-1.537 1.491-1.795 2.595-0.147 1.086 0.092 2.098 0.718 3.037l0.469 0.635c0.626 0.939 1.454 1.537 2.485 1.795 1.16 0.147 2.209-0.092 3.147-0.718l5.135-3.424c3.7 4.583 8.255 7.887 13.667 9.912l-1.242 6.323c-0.202 1.104 9e-3 2.154 0.635 3.147 0.626 0.883 1.482 1.427 2.568 1.629l0.801 0.166c1.086 0.258 2.098 0.101 3.037-0.469 0.939-0.681 1.509-1.574 1.712-2.678l1.242-6.074c6 0.626 11.651-0.285 16.952-2.733l4.003 6.074c0.626 0.939 1.509 1.518 2.651 1.739 1.049 0.258 2.043 0.074 2.982-0.552l0.69-0.387c0.939-0.626 1.537-1.518 1.795-2.678 0.203-1.086-9e-3 -2.098-0.635-3.037l-3.81-5.936c4.583-3.7 7.841-8.255 9.774-13.667l6.875 1.242c1.086 0.202 2.098-9e-3 3.037-0.635 0.883-0.607 1.427-1.463 1.629-2.568l0.166-0.773c0.202-1.103-0.01-2.143-0.636-3.119z" fill="#fff" stroke="#000" stroke-width="4.1968"/></g><g transform="matrix(.47655 0 0 .47655 27.173 47.615)" fill="#fff" stroke="#000" stroke-width="4.1968"><path d="m92.148 55.869c-0.626-0.939-1.482-1.519-2.568-1.739l-6.792-1.242c0.368-5.669-0.727-11.035-3.286-16.096l5.853-4.224c0.939-0.663 1.491-1.574 1.657-2.733 0.202-1.086-0.037-2.071-0.718-2.954l-0.469-0.718c-0.626-0.883-1.537-1.427-2.733-1.629-1.031-0.166-2.016 0.092-2.954 0.773l-5.632 4.059c-3.81-4.215-8.347-7.206-13.611-8.973l1.27-7.731c0.202-1.104-0.037-2.126-0.718-3.065-0.626-0.883-1.482-1.427-2.568-1.629l-0.856-0.166c-1.104-0.147-2.126 0.092-3.065 0.718-0.884 0.681-1.427 1.565-1.629 2.65l-1.16 7.427c-2.503-0.221-4.951-0.175-7.344 0.138-1.362 0.055-2.641 0.294-3.838 0.718-0.626 0.147-1.224 0.331-1.795 0.552l-3.451-7.51c-0.46-0.994-1.215-1.693-2.264-2.098-1.031-0.423-2.043-0.405-3.037 0.055l-0.773 0.414c-0.994 0.405-1.73 1.16-2.209 2.264-0.368 1.031-0.313 2.043 0.166 3.037l3.506 7.648c-0.202 0.11-0.405 0.249-0.607 0.414-5.264 3.681-9.019 8.31-11.265 13.888l-6.958-1.546c-1.086-0.276-2.098-0.074-3.037 0.607-0.994 0.534-1.592 1.344-1.795 2.43l-0.246 0.772c-0.203 1.104-0.018 2.172 0.552 3.203 0.626 0.883 1.491 1.463 2.595 1.739l6.626 1.546c-0.736 5.835 0.101 11.329 2.512 16.483l-5.411 3.672c-0.939 0.626-1.537 1.491-1.795 2.595-0.147 1.086 0.092 2.098 0.718 3.037l0.469 0.635c0.626 0.939 1.454 1.537 2.485 1.795 1.16 0.147 2.209-0.092 3.147-0.718l5.135-3.424c3.7 4.583 8.255 7.887 13.667 9.912l-1.242 6.323c-0.202 1.104 9e-3 2.154 0.635 3.147 0.626 0.883 1.482 1.427 2.568 1.629l0.801 0.166c1.086 0.258 2.098 0.101 3.037-0.469 0.939-0.681 1.509-1.574 1.712-2.678l1.242-6.074c6 0.626 11.651-0.285 16.952-2.733l4.003 6.074c0.626 0.939 1.509 1.518 2.651 1.739 1.049 0.258 2.043 0.074 2.982-0.552l0.69-0.387c0.939-0.626 1.537-1.518 1.795-2.678 0.203-1.086-9e-3 -2.098-0.635-3.037l-3.81-5.936c4.583-3.7 7.841-8.255 9.774-13.667l6.875 1.242c1.086 0.202 2.098-9e-3 3.037-0.635 0.883-0.607 1.427-1.463 1.629-2.568l0.166-0.773c0.202-1.103-0.01-2.143-0.636-3.119z" fill="#fff" stroke="#000" stroke-width="4.1968"/></g></svg>
diff --git a/icons/level_medium.svg b/icons/level_medium.svg
deleted file mode 100644
index 34401cc3d6b6509d6aa5f0792549763014d5d1d3..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"/><g transform="matrix(.47655 0 0 .47655 3.9408 27.173)" fill="#fff" stroke="#000" stroke-width="4.1968"><path d="m92.148 55.869c-0.626-0.939-1.482-1.519-2.568-1.739l-6.792-1.242c0.368-5.669-0.727-11.035-3.286-16.096l5.853-4.224c0.939-0.663 1.491-1.574 1.657-2.733 0.202-1.086-0.037-2.071-0.718-2.954l-0.469-0.718c-0.626-0.883-1.537-1.427-2.733-1.629-1.031-0.166-2.016 0.092-2.954 0.773l-5.632 4.059c-3.81-4.215-8.347-7.206-13.611-8.973l1.27-7.731c0.202-1.104-0.037-2.126-0.718-3.065-0.626-0.883-1.482-1.427-2.568-1.629l-0.856-0.166c-1.104-0.147-2.126 0.092-3.065 0.718-0.884 0.681-1.427 1.565-1.629 2.65l-1.16 7.427c-2.503-0.221-4.951-0.175-7.344 0.138-1.362 0.055-2.641 0.294-3.838 0.718-0.626 0.147-1.224 0.331-1.795 0.552l-3.451-7.51c-0.46-0.994-1.215-1.693-2.264-2.098-1.031-0.423-2.043-0.405-3.037 0.055l-0.773 0.414c-0.994 0.405-1.73 1.16-2.209 2.264-0.368 1.031-0.313 2.043 0.166 3.037l3.506 7.648c-0.202 0.11-0.405 0.249-0.607 0.414-5.264 3.681-9.019 8.31-11.265 13.888l-6.958-1.546c-1.086-0.276-2.098-0.074-3.037 0.607-0.994 0.534-1.592 1.344-1.795 2.43l-0.246 0.772c-0.203 1.104-0.018 2.172 0.552 3.203 0.626 0.883 1.491 1.463 2.595 1.739l6.626 1.546c-0.736 5.835 0.101 11.329 2.512 16.483l-5.411 3.672c-0.939 0.626-1.537 1.491-1.795 2.595-0.147 1.086 0.092 2.098 0.718 3.037l0.469 0.635c0.626 0.939 1.454 1.537 2.485 1.795 1.16 0.147 2.209-0.092 3.147-0.718l5.135-3.424c3.7 4.583 8.255 7.887 13.667 9.912l-1.242 6.323c-0.202 1.104 9e-3 2.154 0.635 3.147 0.626 0.883 1.482 1.427 2.568 1.629l0.801 0.166c1.086 0.258 2.098 0.101 3.037-0.469 0.939-0.681 1.509-1.574 1.712-2.678l1.242-6.074c6 0.626 11.651-0.285 16.952-2.733l4.003 6.074c0.626 0.939 1.509 1.518 2.651 1.739 1.049 0.258 2.043 0.074 2.982-0.552l0.69-0.387c0.939-0.626 1.537-1.518 1.795-2.678 0.203-1.086-9e-3 -2.098-0.635-3.037l-3.81-5.936c4.583-3.7 7.841-8.255 9.774-13.667l6.875 1.242c1.086 0.202 2.098-9e-3 3.037-0.635 0.883-0.607 1.427-1.463 1.629-2.568l0.166-0.773c0.202-1.103-0.01-2.143-0.636-3.119z" fill="#fff" stroke="#000" stroke-width="4.1968"/></g><g transform="matrix(.47655 0 0 .47655 50.404 27.173)" fill="#fff" stroke="#000" stroke-width="4.1968"><path d="m92.148 55.869c-0.626-0.939-1.482-1.519-2.568-1.739l-6.792-1.242c0.368-5.669-0.727-11.035-3.286-16.096l5.853-4.224c0.939-0.663 1.491-1.574 1.657-2.733 0.202-1.086-0.037-2.071-0.718-2.954l-0.469-0.718c-0.626-0.883-1.537-1.427-2.733-1.629-1.031-0.166-2.016 0.092-2.954 0.773l-5.632 4.059c-3.81-4.215-8.347-7.206-13.611-8.973l1.27-7.731c0.202-1.104-0.037-2.126-0.718-3.065-0.626-0.883-1.482-1.427-2.568-1.629l-0.856-0.166c-1.104-0.147-2.126 0.092-3.065 0.718-0.884 0.681-1.427 1.565-1.629 2.65l-1.16 7.427c-2.503-0.221-4.951-0.175-7.344 0.138-1.362 0.055-2.641 0.294-3.838 0.718-0.626 0.147-1.224 0.331-1.795 0.552l-3.451-7.51c-0.46-0.994-1.215-1.693-2.264-2.098-1.031-0.423-2.043-0.405-3.037 0.055l-0.773 0.414c-0.994 0.405-1.73 1.16-2.209 2.264-0.368 1.031-0.313 2.043 0.166 3.037l3.506 7.648c-0.202 0.11-0.405 0.249-0.607 0.414-5.264 3.681-9.019 8.31-11.265 13.888l-6.958-1.546c-1.086-0.276-2.098-0.074-3.037 0.607-0.994 0.534-1.592 1.344-1.795 2.43l-0.246 0.772c-0.203 1.104-0.018 2.172 0.552 3.203 0.626 0.883 1.491 1.463 2.595 1.739l6.626 1.546c-0.736 5.835 0.101 11.329 2.512 16.483l-5.411 3.672c-0.939 0.626-1.537 1.491-1.795 2.595-0.147 1.086 0.092 2.098 0.718 3.037l0.469 0.635c0.626 0.939 1.454 1.537 2.485 1.795 1.16 0.147 2.209-0.092 3.147-0.718l5.135-3.424c3.7 4.583 8.255 7.887 13.667 9.912l-1.242 6.323c-0.202 1.104 9e-3 2.154 0.635 3.147 0.626 0.883 1.482 1.427 2.568 1.629l0.801 0.166c1.086 0.258 2.098 0.101 3.037-0.469 0.939-0.681 1.509-1.574 1.712-2.678l1.242-6.074c6 0.626 11.651-0.285 16.952-2.733l4.003 6.074c0.626 0.939 1.509 1.518 2.651 1.739 1.049 0.258 2.043 0.074 2.982-0.552l0.69-0.387c0.939-0.626 1.537-1.518 1.795-2.678 0.203-1.086-9e-3 -2.098-0.635-3.037l-3.81-5.936c4.583-3.7 7.841-8.255 9.774-13.667l6.875 1.242c1.086 0.202 2.098-9e-3 3.037-0.635 0.883-0.607 1.427-1.463 1.629-2.568l0.166-0.773c0.202-1.103-0.01-2.143-0.636-3.119z" fill="#fff" stroke="#000" stroke-width="4.1968"/></g></svg>
diff --git a/icons/level_nightmare.svg b/icons/level_nightmare.svg
deleted file mode 100644
index 491ec918aae53c8ea05f2e3f6048e3ea90082ea5..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"/><g transform="matrix(.47655 0 0 .47655 5.1498 6.5734)" fill="#fff" stroke="#000" stroke-width="4.1968"><path d="m92.148 55.869c-0.626-0.939-1.482-1.519-2.568-1.739l-6.792-1.242c0.368-5.669-0.727-11.035-3.286-16.096l5.853-4.224c0.939-0.663 1.491-1.574 1.657-2.733 0.202-1.086-0.037-2.071-0.718-2.954l-0.469-0.718c-0.626-0.883-1.537-1.427-2.733-1.629-1.031-0.166-2.016 0.092-2.954 0.773l-5.632 4.059c-3.81-4.215-8.347-7.206-13.611-8.973l1.27-7.731c0.202-1.104-0.037-2.126-0.718-3.065-0.626-0.883-1.482-1.427-2.568-1.629l-0.856-0.166c-1.104-0.147-2.126 0.092-3.065 0.718-0.884 0.681-1.427 1.565-1.629 2.65l-1.16 7.427c-2.503-0.221-4.951-0.175-7.344 0.138-1.362 0.055-2.641 0.294-3.838 0.718-0.626 0.147-1.224 0.331-1.795 0.552l-3.451-7.51c-0.46-0.994-1.215-1.693-2.264-2.098-1.031-0.423-2.043-0.405-3.037 0.055l-0.773 0.414c-0.994 0.405-1.73 1.16-2.209 2.264-0.368 1.031-0.313 2.043 0.166 3.037l3.506 7.648c-0.202 0.11-0.405 0.249-0.607 0.414-5.264 3.681-9.019 8.31-11.265 13.888l-6.958-1.546c-1.086-0.276-2.098-0.074-3.037 0.607-0.994 0.534-1.592 1.344-1.795 2.43l-0.246 0.772c-0.203 1.104-0.018 2.172 0.552 3.203 0.626 0.883 1.491 1.463 2.595 1.739l6.626 1.546c-0.736 5.835 0.101 11.329 2.512 16.483l-5.411 3.672c-0.939 0.626-1.537 1.491-1.795 2.595-0.147 1.086 0.092 2.098 0.718 3.037l0.469 0.635c0.626 0.939 1.454 1.537 2.485 1.795 1.16 0.147 2.209-0.092 3.147-0.718l5.135-3.424c3.7 4.583 8.255 7.887 13.667 9.912l-1.242 6.323c-0.202 1.104 9e-3 2.154 0.635 3.147 0.626 0.883 1.482 1.427 2.568 1.629l0.801 0.166c1.086 0.258 2.098 0.101 3.037-0.469 0.939-0.681 1.509-1.574 1.712-2.678l1.242-6.074c6 0.626 11.651-0.285 16.952-2.733l4.003 6.074c0.626 0.939 1.509 1.518 2.651 1.739 1.049 0.258 2.043 0.074 2.982-0.552l0.69-0.387c0.939-0.626 1.537-1.518 1.795-2.678 0.203-1.086-9e-3 -2.098-0.635-3.037l-3.81-5.936c4.583-3.7 7.841-8.255 9.774-13.667l6.875 1.242c1.086 0.202 2.098-9e-3 3.037-0.635 0.883-0.607 1.427-1.463 1.629-2.568l0.166-0.773c0.202-1.103-0.01-2.143-0.636-3.119z" fill="#fff" stroke="#000" stroke-width="4.1968"/></g><g transform="matrix(.47655 0 0 .47655 49.346 6.6426)" fill="#fff" stroke="#000" stroke-width="4.1968"><path d="m92.148 55.869c-0.626-0.939-1.482-1.519-2.568-1.739l-6.792-1.242c0.368-5.669-0.727-11.035-3.286-16.096l5.853-4.224c0.939-0.663 1.491-1.574 1.657-2.733 0.202-1.086-0.037-2.071-0.718-2.954l-0.469-0.718c-0.626-0.883-1.537-1.427-2.733-1.629-1.031-0.166-2.016 0.092-2.954 0.773l-5.632 4.059c-3.81-4.215-8.347-7.206-13.611-8.973l1.27-7.731c0.202-1.104-0.037-2.126-0.718-3.065-0.626-0.883-1.482-1.427-2.568-1.629l-0.856-0.166c-1.104-0.147-2.126 0.092-3.065 0.718-0.884 0.681-1.427 1.565-1.629 2.65l-1.16 7.427c-2.503-0.221-4.951-0.175-7.344 0.138-1.362 0.055-2.641 0.294-3.838 0.718-0.626 0.147-1.224 0.331-1.795 0.552l-3.451-7.51c-0.46-0.994-1.215-1.693-2.264-2.098-1.031-0.423-2.043-0.405-3.037 0.055l-0.773 0.414c-0.994 0.405-1.73 1.16-2.209 2.264-0.368 1.031-0.313 2.043 0.166 3.037l3.506 7.648c-0.202 0.11-0.405 0.249-0.607 0.414-5.264 3.681-9.019 8.31-11.265 13.888l-6.958-1.546c-1.086-0.276-2.098-0.074-3.037 0.607-0.994 0.534-1.592 1.344-1.795 2.43l-0.246 0.772c-0.203 1.104-0.018 2.172 0.552 3.203 0.626 0.883 1.491 1.463 2.595 1.739l6.626 1.546c-0.736 5.835 0.101 11.329 2.512 16.483l-5.411 3.672c-0.939 0.626-1.537 1.491-1.795 2.595-0.147 1.086 0.092 2.098 0.718 3.037l0.469 0.635c0.626 0.939 1.454 1.537 2.485 1.795 1.16 0.147 2.209-0.092 3.147-0.718l5.135-3.424c3.7 4.583 8.255 7.887 13.667 9.912l-1.242 6.323c-0.202 1.104 9e-3 2.154 0.635 3.147 0.626 0.883 1.482 1.427 2.568 1.629l0.801 0.166c1.086 0.258 2.098 0.101 3.037-0.469 0.939-0.681 1.509-1.574 1.712-2.678l1.242-6.074c6 0.626 11.651-0.285 16.952-2.733l4.003 6.074c0.626 0.939 1.509 1.518 2.651 1.739 1.049 0.258 2.043 0.074 2.982-0.552l0.69-0.387c0.939-0.626 1.537-1.518 1.795-2.678 0.203-1.086-9e-3 -2.098-0.635-3.037l-3.81-5.936c4.583-3.7 7.841-8.255 9.774-13.667l6.875 1.242c1.086 0.202 2.098-9e-3 3.037-0.635 0.883-0.607 1.427-1.463 1.629-2.568l0.166-0.773c0.202-1.103-0.01-2.143-0.636-3.119z" fill="#fff" stroke="#000" stroke-width="4.1968"/></g><g transform="matrix(.47655 0 0 .47655 4.9988 47.703)" fill="#fff" stroke="#000" stroke-width="4.1968"><path d="m92.148 55.869c-0.626-0.939-1.482-1.519-2.568-1.739l-6.792-1.242c0.368-5.669-0.727-11.035-3.286-16.096l5.853-4.224c0.939-0.663 1.491-1.574 1.657-2.733 0.202-1.086-0.037-2.071-0.718-2.954l-0.469-0.718c-0.626-0.883-1.537-1.427-2.733-1.629-1.031-0.166-2.016 0.092-2.954 0.773l-5.632 4.059c-3.81-4.215-8.347-7.206-13.611-8.973l1.27-7.731c0.202-1.104-0.037-2.126-0.718-3.065-0.626-0.883-1.482-1.427-2.568-1.629l-0.856-0.166c-1.104-0.147-2.126 0.092-3.065 0.718-0.884 0.681-1.427 1.565-1.629 2.65l-1.16 7.427c-2.503-0.221-4.951-0.175-7.344 0.138-1.362 0.055-2.641 0.294-3.838 0.718-0.626 0.147-1.224 0.331-1.795 0.552l-3.451-7.51c-0.46-0.994-1.215-1.693-2.264-2.098-1.031-0.423-2.043-0.405-3.037 0.055l-0.773 0.414c-0.994 0.405-1.73 1.16-2.209 2.264-0.368 1.031-0.313 2.043 0.166 3.037l3.506 7.648c-0.202 0.11-0.405 0.249-0.607 0.414-5.264 3.681-9.019 8.31-11.265 13.888l-6.958-1.546c-1.086-0.276-2.098-0.074-3.037 0.607-0.994 0.534-1.592 1.344-1.795 2.43l-0.246 0.772c-0.203 1.104-0.018 2.172 0.552 3.203 0.626 0.883 1.491 1.463 2.595 1.739l6.626 1.546c-0.736 5.835 0.101 11.329 2.512 16.483l-5.411 3.672c-0.939 0.626-1.537 1.491-1.795 2.595-0.147 1.086 0.092 2.098 0.718 3.037l0.469 0.635c0.626 0.939 1.454 1.537 2.485 1.795 1.16 0.147 2.209-0.092 3.147-0.718l5.135-3.424c3.7 4.583 8.255 7.887 13.667 9.912l-1.242 6.323c-0.202 1.104 9e-3 2.154 0.635 3.147 0.626 0.883 1.482 1.427 2.568 1.629l0.801 0.166c1.086 0.258 2.098 0.101 3.037-0.469 0.939-0.681 1.509-1.574 1.712-2.678l1.242-6.074c6 0.626 11.651-0.285 16.952-2.733l4.003 6.074c0.626 0.939 1.509 1.518 2.651 1.739 1.049 0.258 2.043 0.074 2.982-0.552l0.69-0.387c0.939-0.626 1.537-1.518 1.795-2.678 0.203-1.086-9e-3 -2.098-0.635-3.037l-3.81-5.936c4.583-3.7 7.841-8.255 9.774-13.667l6.875 1.242c1.086 0.202 2.098-9e-3 3.037-0.635 0.883-0.607 1.427-1.463 1.629-2.568l0.166-0.773c0.202-1.103-0.01-2.143-0.636-3.119z" fill="#fff" stroke="#000" stroke-width="4.1968"/></g><g transform="matrix(.47655 0 0 .47655 49.325 47.772)" fill="#fff" stroke="#000" stroke-width="4.1968"><path d="m92.148 55.869c-0.626-0.939-1.482-1.519-2.568-1.739l-6.792-1.242c0.368-5.669-0.727-11.035-3.286-16.096l5.853-4.224c0.939-0.663 1.491-1.574 1.657-2.733 0.202-1.086-0.037-2.071-0.718-2.954l-0.469-0.718c-0.626-0.883-1.537-1.427-2.733-1.629-1.031-0.166-2.016 0.092-2.954 0.773l-5.632 4.059c-3.81-4.215-8.347-7.206-13.611-8.973l1.27-7.731c0.202-1.104-0.037-2.126-0.718-3.065-0.626-0.883-1.482-1.427-2.568-1.629l-0.856-0.166c-1.104-0.147-2.126 0.092-3.065 0.718-0.884 0.681-1.427 1.565-1.629 2.65l-1.16 7.427c-2.503-0.221-4.951-0.175-7.344 0.138-1.362 0.055-2.641 0.294-3.838 0.718-0.626 0.147-1.224 0.331-1.795 0.552l-3.451-7.51c-0.46-0.994-1.215-1.693-2.264-2.098-1.031-0.423-2.043-0.405-3.037 0.055l-0.773 0.414c-0.994 0.405-1.73 1.16-2.209 2.264-0.368 1.031-0.313 2.043 0.166 3.037l3.506 7.648c-0.202 0.11-0.405 0.249-0.607 0.414-5.264 3.681-9.019 8.31-11.265 13.888l-6.958-1.546c-1.086-0.276-2.098-0.074-3.037 0.607-0.994 0.534-1.592 1.344-1.795 2.43l-0.246 0.772c-0.203 1.104-0.018 2.172 0.552 3.203 0.626 0.883 1.491 1.463 2.595 1.739l6.626 1.546c-0.736 5.835 0.101 11.329 2.512 16.483l-5.411 3.672c-0.939 0.626-1.537 1.491-1.795 2.595-0.147 1.086 0.092 2.098 0.718 3.037l0.469 0.635c0.626 0.939 1.454 1.537 2.485 1.795 1.16 0.147 2.209-0.092 3.147-0.718l5.135-3.424c3.7 4.583 8.255 7.887 13.667 9.912l-1.242 6.323c-0.202 1.104 9e-3 2.154 0.635 3.147 0.626 0.883 1.482 1.427 2.568 1.629l0.801 0.166c1.086 0.258 2.098 0.101 3.037-0.469 0.939-0.681 1.509-1.574 1.712-2.678l1.242-6.074c6 0.626 11.651-0.285 16.952-2.733l4.003 6.074c0.626 0.939 1.509 1.518 2.651 1.739 1.049 0.258 2.043 0.074 2.982-0.552l0.69-0.387c0.939-0.626 1.537-1.518 1.795-2.678 0.203-1.086-9e-3 -2.098-0.635-3.037l-3.81-5.936c4.583-3.7 7.841-8.255 9.774-13.667l6.875 1.242c1.086 0.202 2.098-9e-3 3.037-0.635 0.883-0.607 1.427-1.463 1.629-2.568l0.166-0.773c0.202-1.103-0.01-2.143-0.636-3.119z" fill="#fff" stroke="#000" stroke-width="4.1968"/></g></svg>
diff --git a/icons/size_10x10.svg b/icons/size_10x10.svg
deleted file mode 100644
index 7729c4bed977f04ce8965362de2b7f63156a54ed..0000000000000000000000000000000000000000
--- a/icons/size_10x10.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="matrix(.61667 0 0 .61667 19.166 8.0878)"><rect x="27.579" y="45.549" width="43.928" height="43.924" fill="#fff"/><path d="m22.09 40.056v55.821h55.821v-55.821zm49.417 49.417h-19.218v-19.218h19.218zm-0.0022-24.706h-19.217v-19.218h19.218zm-43.926-19.218h19.218v19.218h-19.218zm0 24.71h19.218v19.218h-19.218z" stroke-width="2.7453"/></g></svg>
diff --git a/icons/size_15x15.svg b/icons/size_15x15.svg
deleted file mode 100644
index 8f03f28c93750af237f770416425f8b4a795d98d..0000000000000000000000000000000000000000
--- a/icons/size_15x15.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(0 -19.83)"><rect x="25.631" y="45.406" width="48.427" height="48.427" fill="#fefdfd"/><path d="m21.909 41.68v56.301h56.182v-56.301zm35.388 20.489v14.901h-14.901v-14.901zm-14.901-3.7252v-13.038h14.901v13.038zm31.662 35.389h-13.038v-13.038h13.038zm0-16.762h-13.038v-14.901h13.038zm-16.762 3.7252v13.038h-14.901v-13.038zm16.762-22.352h-13.038v-13.038h13.038zm-48.427-13.038h13.038v13.038h-13.038zm0 16.762h13.038v14.901h-13.038zm0 18.627h13.038v13.038h-13.038z" stroke-width="1.8627"/></g></svg>
diff --git a/icons/size_20x20.svg b/icons/size_20x20.svg
deleted file mode 100644
index 591d8628449c45eb6103a10e519fafc2fa224dfb..0000000000000000000000000000000000000000
--- a/icons/size_20x20.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="matrix(1.2319 0 0 1.2319 -11.595 -34.78)"><rect x="25.882" y="43.926" width="48" height="49.184" fill="#fff"/><path d="m23.09 41.131v55.377h53.819v-55.377zm25.359 15.368v11.176h-9.9925v-11.176zm-9.9925-2.794v-9.7789h9.9925v9.7789zm35.426 39.405h-9.7789v-9.7789h9.7789zm0-12.862h-9.7789v-9.7789h9.7789zm-12.862 0h-9.7789v-9.7789h9.7789zm0 3.0824v9.7789h-9.7789v-9.7789zm12.862-15.655h-9.7789v-11.176h9.7789zm-12.862 0h-9.7789v-11.176h9.7789zm-12.572 2.794v9.7789h-9.9925v-9.7789zm0 12.862v9.7789h-9.9925v-9.7789zm25.434-39.405v9.7789h-9.7789v-9.7789zm-12.862 9.7789h-9.7789v-9.7789h9.7789zm-35.138-9.7789h9.7789v9.7789h-9.7789zm0 12.572h9.7789v11.176h-9.7789zm0 13.971h9.7789v9.7789h-9.7789zm0 12.862h9.7789v9.7789h-9.7789z" stroke-width="1.3971"/></g></svg>
diff --git a/icons/skin_default.svg b/icons/skin_default.svg
deleted file mode 100644
index bb34f915009a3b22734bec8c85090bcb036d3e63..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"/></svg>
diff --git a/lib/config/default_game_settings.dart b/lib/config/default_game_settings.dart
new file mode 100644
index 0000000000000000000000000000000000000000..b1784bcd2b39f5c7567a5b4a79134cb5cb60e169
--- /dev/null
+++ b/lib/config/default_game_settings.dart
@@ -0,0 +1,63 @@
+import 'package:minehunter/utils/tools.dart';      
+
+class DefaultGameSettings {
+  // available game parameters codes
+  static const String parameterCodeLevel = 'level';
+  static const String parameterCodeSize = 'size';
+  static const List<String> availableParameters = [
+    parameterCodeLevel,
+    parameterCodeSize,
+  ];
+
+  // level: available values
+  static const String levelValueEasy = 'easy';
+  static const String levelValueMedium = 'medium';
+  static const String levelValueHard = 'hard';
+  static const String levelValueNightmare = 'nightmare';
+  static const List<String> allowedLevelValues = [
+    levelValueEasy,
+    levelValueMedium,
+    levelValueHard,
+    levelValueNightmare,
+  ];
+  // level: default value
+  static const String defaultLevelValue = levelValueMedium;
+
+  // size: available values
+  static const String sizeValueSmall = '10x10';
+  static const String sizeValueMedium = '15x15';
+  static const String sizeValueLarge = '20x20';
+  static const List<String> allowedSizeValues = [
+    sizeValueSmall,
+    sizeValueMedium,
+    sizeValueLarge,
+  ];
+  // size: default value
+  static const String defaultSizeValue = sizeValueMedium;
+
+  // available values from parameter code
+  static List<String> getAvailableValues(String parameterCode) {
+    switch (parameterCode) {
+      case parameterCodeLevel:
+        return DefaultGameSettings.allowedLevelValues;
+      case parameterCodeSize:
+        return DefaultGameSettings.allowedSizeValues;
+    }
+
+    printlog('Did not find any available value for game parameter "$parameterCode".');
+    return [];
+  }
+
+  // parameters displayed with assets (instead of painter)
+  static List<String> displayedWithAssets = [
+    //
+  ];
+
+  // how many mines? (per 100 tiles)
+  static const Map<String, int> minesCountRatios = {
+    DefaultGameSettings.levelValueEasy: 5,
+    DefaultGameSettings.levelValueMedium: 10,
+    DefaultGameSettings.levelValueHard: 15,
+    DefaultGameSettings.levelValueNightmare: 20,
+  };
+}
diff --git a/lib/config/default_global_settings.dart b/lib/config/default_global_settings.dart
new file mode 100644
index 0000000000000000000000000000000000000000..3742f45ff113289a66e6015195b10fcaa4246834
--- /dev/null
+++ b/lib/config/default_global_settings.dart
@@ -0,0 +1,33 @@
+import 'package:minehunter/utils/tools.dart';      
+
+class DefaultGlobalSettings {
+  // available global parameters codes
+  static const String parameterCodeSkin = 'skin';
+  static const List<String> availableParameters = [
+    parameterCodeSkin,
+  ];
+
+  // skin: available values
+  static const String skinValueDefault = 'default';
+  static const List<String> allowedSkinValues = [
+    skinValueDefault,
+  ];
+  // skin: default value
+  static const String defaultSkinValue = skinValueDefault;
+
+  // 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 [];
+  }
+
+  // parameters displayed with assets (instead of painter)
+  static List<String> displayedWithAssets = [
+    //
+  ];
+}
diff --git a/lib/config/menu.dart b/lib/config/menu.dart
index 09df83be163fa0d2f965c982b46749e27060e8fe..3cac643a13f9d34db64aafb36e0bf43643e737cf 100644
--- a/lib/config/menu.dart
+++ b/lib/config/menu.dart
@@ -1,53 +1,51 @@
-import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/material.dart';
-
-import 'package:minehunter/ui/screens/about_page.dart';
-import 'package:minehunter/ui/screens/game_page.dart';
-import 'package:minehunter/ui/screens/settings_page.dart';
 import 'package:unicons/unicons.dart';
 
+import 'package:minehunter/ui/screens/page_about.dart';
+import 'package:minehunter/ui/screens/page_game.dart';
+import 'package:minehunter/ui/screens/page_settings.dart';
+
 class MenuItem {
-  final String code;
   final Icon icon;
   final Widget page;
 
   const MenuItem({
-    required this.code,
     required this.icon,
     required this.page,
   });
 }
 
 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(
+    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(
+    icon: Icon(UniconsLine.setting),
+    page: PageSettings(),
+  );
+
+  static const indexAbout = 2;
+  static const menuItemAbout = MenuItem(
+    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/config/theme.dart b/lib/config/theme.dart
index 138460e58f89bc93afb0899d6cfe8f8e662a466f..74f532fd5abf693979118609564d29167e902009 100644
--- a/lib/config/theme.dart
+++ b/lib/config/theme.dart
@@ -188,5 +188,3 @@ final ThemeData darkTheme = lightTheme.copyWith(
     ),
   ),
 );
-
-final ThemeData appTheme = darkTheme;
diff --git a/lib/cubit/game_cubit.dart b/lib/cubit/game_cubit.dart
new file mode 100644
index 0000000000000000000000000000000000000000..46715d8ff4f76fcb31ddc404bad3d4f0d9863e32
--- /dev/null
+++ b/lib/cubit/game_cubit.dart
@@ -0,0 +1,272 @@
+import 'package:equatable/equatable.dart';
+import 'package:flutter/material.dart';
+import 'package:hydrated_bloc/hydrated_bloc.dart';
+
+import 'package:minehunter/models/game/cell.dart';
+import 'package:minehunter/models/game/game.dart';
+import 'package:minehunter/models/settings/settings_game.dart';
+import 'package:minehunter/models/settings/settings_global.dart';
+import 'package:minehunter/models/types.dart';
+import 'package:minehunter/utils/tools.dart';
+
+part 'game_state.dart';
+
+class GameCubit extends HydratedCubit<GameState> {
+  GameCubit()
+      : super(GameState(
+          currentGame: Game.createEmpty(),
+        ));
+
+  void updateState(Game game) {
+    emit(GameState(
+      currentGame: game,
+    ));
+  }
+
+  void refresh() {
+    final Game game = Game(
+      // Settings
+      gameSettings: state.currentGame.gameSettings,
+      globalSettings: state.currentGame.globalSettings,
+      // State
+      isRunning: state.currentGame.isRunning,
+      isStarted: state.currentGame.isStarted,
+      isFinished: state.currentGame.isFinished,
+      animationInProgress: state.currentGame.animationInProgress,
+      // Base data
+      board: state.currentGame.board,
+      sizeHorizontal: state.currentGame.sizeHorizontal,
+      sizeVertical: state.currentGame.sizeVertical,
+      isBoardMined: state.currentGame.isBoardMined,
+      // Game data
+      minesCount: state.currentGame.minesCount,
+      reportMode: state.currentGame.reportMode,
+      gameWin: state.currentGame.gameWin,
+      gameFail: state.currentGame.gameFail,
+    );
+    // game.dump();
+
+    updateState(game);
+  }
+
+  void startNewGame({
+    required GameSettings gameSettings,
+    required GlobalSettings globalSettings,
+  }) {
+    final Game newGame = Game.createNew(
+      // Settings
+      gameSettings: gameSettings,
+      globalSettings: globalSettings,
+    );
+
+    newGame.dump();
+
+    updateState(newGame);
+    refresh();
+  }
+
+  void quitGame() {
+    state.currentGame.isRunning = false;
+    refresh();
+  }
+
+  void resumeSavedGame() {
+    state.currentGame.isRunning = true;
+    refresh();
+  }
+
+  void deleteSavedGame() {
+    state.currentGame.isRunning = false;
+    state.currentGame.isFinished = true;
+    refresh();
+  }
+
+  void updateBoard(Board board) {
+    state.currentGame.board = board;
+    refresh();
+  }
+
+  void addMines({
+    required int forbiddenRow,
+    required int forbiddenCol,
+  }) {
+    state.currentGame.isStarted = true;
+    state.currentGame.addMines(
+      forbiddenRow: forbiddenRow,
+      forbiddenCol: forbiddenCol,
+    );
+    state.currentGame.isBoardMined = true;
+    refresh();
+  }
+
+  void reportCell({
+    required int row,
+    required int col,
+  }) {
+    if (!state.currentGame.board[row][col].isExplored) {
+      toggleCellMark(row, col);
+    }
+  }
+
+  void walkOnCell({
+    required int row,
+    required int col,
+  }) {
+    setCellAsExplored(row, col);
+
+    if (state.currentGame.board[row][col].minesCountAround == 0) {
+      final List<List<int>> safeCells = getAllSafeCellsAround(row, col);
+      for (int safeCellIndex = 0; safeCellIndex < safeCells.length; safeCellIndex++) {
+        final int safeCellRow = safeCells[safeCellIndex][0];
+        final int safeCellCol = safeCells[safeCellIndex][1];
+        if (!state.currentGame.board[safeCellRow][safeCellCol].isExplored) {
+          walkOnCell(
+            row: safeCellRow,
+            col: safeCellCol,
+          );
+        }
+      }
+    }
+  }
+
+  List<List<int>> getAllSafeCellsAround(int row, int col) {
+    final List<List<Cell>> board = state.currentGame.board;
+    final int sizeHorizontal = board.length;
+    final int sizeVertical = board[0].length;
+
+    final List<List<int>> safeCellsCoordinates = [];
+
+    if (board[row][col].minesCountAround == 0) {
+      for (int deltaRow = -1; deltaRow <= 1; deltaRow++) {
+        for (int deltaCol = -1; deltaCol <= 1; deltaCol++) {
+          final int candidateRow = row + deltaRow;
+          final int candidateCol = col + deltaCol;
+          if ((candidateRow >= 0 && candidateRow < sizeVertical) &&
+              (candidateCol >= 0 && candidateCol < sizeHorizontal) &&
+              !board[candidateRow][candidateCol].isExplored) {
+            safeCellsCoordinates.add([candidateRow, candidateCol]);
+          }
+        }
+      }
+    }
+
+    return safeCellsCoordinates;
+  }
+
+  void setCellAsExplored(int row, int col) {
+    state.currentGame.board[row][col].isExplored = true;
+    state.currentGame.board[row][col].isMarked = false;
+
+    // Boom?
+    if (state.currentGame.board[row][col].isMined) {
+      // Boom!
+      state.currentGame.board[row][col].isExploded = true;
+    }
+
+    refresh();
+  }
+
+  void toggleCellMark(int row, int col) {
+    state.currentGame.board[row][col].isMarked = !state.currentGame.board[row][col].isMarked;
+    refresh();
+  }
+
+  void updateReportMode(bool reportMode) {
+    state.currentGame.reportMode = reportMode;
+    refresh();
+  }
+
+  bool checkGameIsFinished() {
+    final Game currentGame = state.currentGame;
+
+    final Board board = currentGame.board;
+    final int sizeHorizontal = board.length;
+    final int sizeVertical = board[0].length;
+
+    currentGame.printGrid();
+
+    updateGameWin(false);
+    updateGameFail(false);
+
+    for (int row = 0; row < sizeVertical; row++) {
+      for (int col = 0; col < sizeHorizontal; col++) {
+        // Walked on a mine
+        if (board[row][col].isExploded == true) {
+          updateGameFail(true);
+          return true;
+        }
+      }
+    }
+
+    for (int row = 0; row < sizeVertical; row++) {
+      for (int col = 0; col < sizeHorizontal; col++) {
+        if (
+            // Mine not already found
+            (board[row][col].isMined == true && board[row][col].isMarked == false) ||
+                // Safe cell marked as mined
+                (board[row][col].isMined == false && board[row][col].isMarked == true)) {
+          return false;
+        }
+      }
+    }
+
+    printlog('-> ok all mines found!');
+    updateGameWin(true);
+
+    return true;
+  }
+
+  void updateGameWin(bool value) {
+    state.currentGame.gameWin = value;
+    if (true == value) {
+      state.currentGame.isFinished = true;
+    }
+    refresh();
+  }
+
+  void updateGameFail(bool value) {
+    state.currentGame.gameFail = value;
+    if (true == value) {
+      state.currentGame.isFinished = true;
+    }
+    refresh();
+  }
+
+  void updateAnimationInProgress(bool animationInProgress) {
+    state.currentGame.animationInProgress = animationInProgress;
+    refresh();
+  }
+
+  void setAnimatedBackground(List animatedCellsPattern) {
+    for (int row = 0; row < state.currentGame.sizeVertical; row++) {
+      for (int col = 0; col < state.currentGame.sizeHorizontal; col++) {
+        state.currentGame.board[row][col].isAnimated = animatedCellsPattern[row][col];
+      }
+    }
+    refresh();
+  }
+
+  void resetAnimatedBackground() {
+    for (int row = 0; row < state.currentGame.sizeVertical; row++) {
+      for (int col = 0; col < state.currentGame.sizeHorizontal; col++) {
+        state.currentGame.board[row][col].isAnimated = false;
+      }
+    }
+  }
+
+  @override
+  GameState? fromJson(Map<String, dynamic> json) {
+    final 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..00e211668c3269255926939324355792abd61c41
--- /dev/null
+++ b/lib/cubit/game_state.dart
@@ -0,0 +1,15 @@
+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,
+      ];
+}
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 487ffb2870c6bdcc8df87afbe7059837f25fa2ca..e927ae1675fb1b80282d6cbac0bf2b236dc87f67 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:minehunter/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..fcb19a33e9e4e1869741e2a2d8f417a5806cb3ba
--- /dev/null
+++ b/lib/cubit/settings_game_cubit.dart
@@ -0,0 +1,72 @@
+import 'package:equatable/equatable.dart';
+import 'package:flutter/material.dart';
+import 'package:hydrated_bloc/hydrated_bloc.dart';
+
+import 'package:minehunter/config/default_game_settings.dart';
+import 'package:minehunter/models/settings/settings_game.dart';
+
+part 'settings_game_state.dart';
+
+class GameSettingsCubit extends HydratedCubit<GameSettingsState> {
+  GameSettingsCubit() : super(GameSettingsState(settings: GameSettings.createDefault()));
+
+  void setValues({
+    String? itemsCount,
+    String? timerValue,
+  }) {
+    emit(
+      GameSettingsState(
+        settings: GameSettings(
+          level: itemsCount ?? state.settings.level,
+          size: timerValue ?? state.settings.size,
+        ),
+      ),
+    );
+  }
+
+  String getParameterValue(String code) {
+    switch (code) {
+      case DefaultGameSettings.parameterCodeLevel:
+        return GameSettings.getLevelValueFromUnsafe(state.settings.level);
+      case DefaultGameSettings.parameterCodeSize:
+        return GameSettings.getSizeValueFromUnsafe(state.settings.size);
+    }
+
+    return '';
+  }
+
+  void setParameterValue(String code, String value) {
+    final String itemsCount = code == DefaultGameSettings.parameterCodeLevel
+        ? value
+        : getParameterValue(DefaultGameSettings.parameterCodeLevel);
+    final String timerValue = code == DefaultGameSettings.parameterCodeSize
+        ? value
+        : getParameterValue(DefaultGameSettings.parameterCodeSize);
+
+    setValues(
+      itemsCount: itemsCount,
+      timerValue: timerValue,
+    );
+  }
+
+  @override
+  GameSettingsState? fromJson(Map<String, dynamic> json) {
+    final String itemsCount = json[DefaultGameSettings.parameterCodeLevel] as String;
+    final String timerValue = json[DefaultGameSettings.parameterCodeSize] as String;
+
+    return GameSettingsState(
+      settings: GameSettings(
+        level: itemsCount,
+        size: timerValue,
+      ),
+    );
+  }
+
+  @override
+  Map<String, dynamic>? toJson(GameSettingsState state) {
+    return <String, dynamic>{
+      DefaultGameSettings.parameterCodeLevel: state.settings.level,
+      DefaultGameSettings.parameterCodeSize: state.settings.size,
+    };
+  }
+}
diff --git a/lib/cubit/settings_game_state.dart b/lib/cubit/settings_game_state.dart
new file mode 100644
index 0000000000000000000000000000000000000000..5acd85b44ba541e1c5e9c26af1c4be26a385b9ed
--- /dev/null
+++ b/lib/cubit/settings_game_state.dart
@@ -0,0 +1,15 @@
+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,
+      ];
+}
diff --git a/lib/cubit/settings_global_cubit.dart b/lib/cubit/settings_global_cubit.dart
new file mode 100644
index 0000000000000000000000000000000000000000..66d6f6d6bd6c46639ef91293c6e16a385ff36ca2
--- /dev/null
+++ b/lib/cubit/settings_global_cubit.dart
@@ -0,0 +1,60 @@
+import 'package:equatable/equatable.dart';
+import 'package:flutter/material.dart';
+import 'package:hydrated_bloc/hydrated_bloc.dart';
+
+import 'package:minehunter/config/default_global_settings.dart';
+import 'package:minehunter/models/settings/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..ebcddd700f252257223ca8e16c85202b04f3ff24
--- /dev/null
+++ b/lib/cubit/settings_global_state.dart
@@ -0,0 +1,15 @@
+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,
+      ];
+}
diff --git a/lib/entities/cell.dart b/lib/entities/cell.dart
deleted file mode 100644
index a70bd021e8aabb1e925c180f40e23930518992df..0000000000000000000000000000000000000000
--- a/lib/entities/cell.dart
+++ /dev/null
@@ -1,147 +0,0 @@
-import 'package:flutter/material.dart';
-
-import 'package:minehunter/provider/data.dart';
-import 'package:minehunter/utils/board_animate.dart';
-import 'package:minehunter/utils/board_utils.dart';
-
-class Cell {
-  bool isMined = false;
-  bool isExplored = false;
-  bool isMarked = false;
-  bool isExploded = false;
-  int minesCountAround = 0;
-
-  bool isAnimated = false;
-
-  Cell(
-    this.isMined,
-  );
-
-  /*
-  * Build widget for board cell, with interactions
-  */
-  Container widget(Data myProvider, int row, int col) {
-    String imageAsset = getImageAssetName(myProvider);
-
-    return Container(
-      decoration: BoxDecoration(
-        color: getBackgroundColor(myProvider),
-        border: getCellBorders(myProvider, row, col),
-      ),
-      child: GestureDetector(
-        child: AnimatedSwitcher(
-          duration: const Duration(milliseconds: 100),
-          transitionBuilder: (Widget child, Animation<double> animation) {
-            return ScaleTransition(scale: animation, child: child);
-          },
-          child: Image(
-            image: AssetImage(imageAsset),
-            fit: BoxFit.fill,
-            key: ValueKey<int>(imageAsset.hashCode),
-          ),
-        ),
-        onTap: () {
-          // Set mines on board after first player try
-          if (!myProvider.isBoardMined) {
-            myProvider.updateBoard(BoardUtils.createBoard(myProvider, row, col));
-            myProvider.updateIsBoardMined(true);
-          }
-
-          if (!(myProvider.gameWin || myProvider.gameFail)) {
-            if (myProvider.reportMode) {
-              BoardUtils.reportCell(myProvider, row, col);
-            } else {
-              BoardUtils.walkOnCell(myProvider, row, col);
-            }
-            if (BoardUtils.checkGameIsFinished(myProvider)) {
-              myProvider.updateReportMode(false);
-              BoardAnimate.startAnimation(myProvider, myProvider.gameWin ? 'win' : 'fail');
-            }
-          }
-        },
-      ),
-    );
-  }
-
-  /*
-  * Compute image asset name, from skin and cell value/state
-  */
-  String getImageAssetName(Data myProvider) {
-    String imageAsset = 'assets/skins/${myProvider.parameterSkin}_tile_unknown.png';
-
-    bool showSolution = myProvider.gameWin || myProvider.gameFail;
-    if (!showSolution) {
-      // Running game
-      if (isExplored) {
-        if (isMined) {
-          // Boom
-          imageAsset = 'assets/skins/${myProvider.parameterSkin}_tile_mine.png';
-        } else {
-          // Show mines count around
-          imageAsset = 'assets/skins/${myProvider.parameterSkin}_tile_$minesCountAround.png';
-        }
-      } else {
-        if (isMarked) {
-          // Danger!
-          imageAsset = 'assets/skins/${myProvider.parameterSkin}_tile_flag.png';
-        }
-      }
-    } else {
-      // Finished game
-      if (isMined) {
-        if (isExploded) {
-          // Mine exploded
-          imageAsset = 'assets/skins/${myProvider.parameterSkin}_tile_mine.png';
-        } else {
-          // Mine not found
-          imageAsset = 'assets/skins/${myProvider.parameterSkin}_tile_mine_not_found.png';
-        }
-      } else {
-        // Show all mines counts
-        imageAsset = 'assets/skins/${myProvider.parameterSkin}_tile_$minesCountAround.png';
-      }
-    }
-
-    return imageAsset;
-  }
-
-  // Compute cell background color, from cell state
-  Color getBackgroundColor(Data myProvider) {
-    if (myProvider.gameWin) {
-      return isAnimated ? Colors.green.shade400 : Colors.green.shade500;
-    }
-    if (myProvider.gameFail) {
-      return isAnimated ? Colors.pink.shade200 : Colors.pink.shade400;
-    }
-
-    return isAnimated ? Colors.white : Colors.grey.shade200;
-  }
-
-  // Compute cell borders, from board size and cell state
-  Border getCellBorders(Data myProvider, int row, int col) {
-    Color cellBorderColor = Colors.grey.shade500;
-    double cellBorderWidth = 4;
-
-    // Reduce cell border width on big boards
-    int boardSize = myProvider.sizeHorizontal;
-    if (boardSize > 8) {
-      cellBorderWidth = 2;
-      if (boardSize > 10) {
-        cellBorderWidth = 1;
-      }
-    }
-
-    if (myProvider.gameWin) {
-      cellBorderColor = Colors.green.shade700;
-    } else if (myProvider.gameFail) {
-      cellBorderColor = Colors.pink.shade300;
-    }
-
-    Border borders = Border.all(
-      color: cellBorderColor,
-      width: cellBorderWidth,
-    );
-
-    return borders;
-  }
-}
diff --git a/lib/main.dart b/lib/main.dart
index d1bb46add6222a3492b308b3ff35f6ff275d524e..2427470ae3d2ea20f3e02d80acaefe7e110abf45 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -2,20 +2,23 @@ import 'dart:io';
 
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:hive/hive.dart';
 import 'package:hydrated_bloc/hydrated_bloc.dart';
 import 'package:path_provider/path_provider.dart';
-import 'package:provider/provider.dart';
 
+import 'package:minehunter/config/default_global_settings.dart';
 import 'package:minehunter/config/theme.dart';
-import 'package:minehunter/cubit/bottom_nav_cubit.dart';
+import 'package:minehunter/cubit/game_cubit.dart';
+import 'package:minehunter/cubit/nav_cubit.dart';
+import 'package:minehunter/cubit/settings_game_cubit.dart';
+import 'package:minehunter/cubit/settings_global_cubit.dart';
 import 'package:minehunter/cubit/theme_cubit.dart';
-import 'package:minehunter/provider/data.dart';
 import 'package:minehunter/ui/skeleton.dart';
 
 void main() async {
-  /// Initialize packages
+  // Initialize packages
   WidgetsFlutterBinding.ensureInitialized();
   await EasyLocalization.ensureInitialized();
   final Directory tmpDir = await getTemporaryDirectory();
@@ -24,18 +27,17 @@ void main() async {
     storageDirectory: tmpDir,
   );
 
-  runApp(
-    EasyLocalization(
-      path: 'assets/translations',
-      supportedLocales: const <Locale>[
-        Locale('en'),
-        Locale('fr'),
-      ],
-      fallbackLocale: const Locale('en'),
-      useFallbackTranslations: true,
-      child: const MyApp(),
-    ),
-  );
+  SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp])
+      .then((value) => runApp(EasyLocalization(
+            path: 'assets/translations',
+            supportedLocales: const <Locale>[
+              Locale('en'),
+              Locale('fr'),
+            ],
+            fallbackLocale: const Locale('en'),
+            useFallbackTranslations: true,
+            child: const MyApp(),
+          )));
 }
 
 class MyApp extends StatelessWidget {
@@ -43,37 +45,83 @@ class MyApp extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
+    final List<String> assets = getImagesAssets();
+    for (String asset in assets) {
+      precacheImage(AssetImage(asset), 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 MaterialApp(
-                  title: 'Minehunter',
-                  home: const SkeletonScreen(),
+          return MaterialApp(
+            title: 'Minehunter',
+            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,
           );
         },
       ),
     );
   }
+
+  List<String> getImagesAssets() {
+    final List<String> assets = [];
+
+    final List<String> gameImages = [
+      'button_back',
+      'button_delete_saved_game',
+      'button_resume_game',
+      'button_start',
+      'game_fail',
+      'game_win',
+      'placeholder',
+    ];
+
+    for (String image in gameImages) {
+      assets.add('assets/ui/$image.png');
+    }
+
+    final List<String> skinImages = [
+      'button_mark_mine_off',
+      'button_mark_mine_on',
+      'empty',
+      'indicator_report_off',
+      'indicator_report_on',
+      'indicator_walk_off',
+      'indicator_walk_on',
+      'tile_flag_ko',
+      'tile_flag_ok',
+      'tile_flag',
+      'tile_mine_not_found',
+      'tile_mine',
+      'tile_unknown',
+    ];
+    for (int value = 0; value <= 8; value++) {
+      skinImages.add('tile_$value');
+    }
+
+    for (String skin in DefaultGlobalSettings.allowedSkinValues) {
+      for (String image in skinImages) {
+        assets.add('assets/skins/${skin}_$image.png');
+      }
+    }
+
+    return assets;
+  }
 }
diff --git a/lib/models/game/cell.dart b/lib/models/game/cell.dart
new file mode 100644
index 0000000000000000000000000000000000000000..e9b85b10757e0f14fe0d13f41744d3eb03b35343
--- /dev/null
+++ b/lib/models/game/cell.dart
@@ -0,0 +1,29 @@
+class Cell {
+  Cell(
+    this.isMined,
+  );
+
+  bool isMined = false;
+  bool isExplored = false;
+  bool isMarked = false;
+  bool isExploded = false;
+  int minesCountAround = 0;
+
+  bool isAnimated = false;
+
+  @override
+  String toString() {
+    return '$Cell(${toJson()})';
+  }
+
+  Map<String, dynamic>? toJson() {
+    return <String, dynamic>{
+      'isMined': isMined,
+      'isExplored': isExplored,
+      'isMarked': isMarked,
+      'isExploded': isExploded,
+      'minesCountAround': minesCountAround,
+      'isAnimated': isAnimated,
+    };
+  }
+}
diff --git a/lib/models/game/game.dart b/lib/models/game/game.dart
new file mode 100644
index 0000000000000000000000000000000000000000..40056896d01620c84136a7bb1f5a20115185c03f
--- /dev/null
+++ b/lib/models/game/game.dart
@@ -0,0 +1,267 @@
+import 'package:minehunter/config/default_game_settings.dart';
+import 'package:minehunter/models/game/cell.dart';
+import 'package:minehunter/models/settings/settings_game.dart';
+import 'package:minehunter/models/settings/settings_global.dart';
+import 'package:minehunter/models/types.dart';
+import 'package:minehunter/utils/tools.dart';
+
+class Game {
+  Game({
+    // Settings
+    required this.gameSettings,
+    required this.globalSettings,
+
+    // State
+    this.isRunning = false,
+    this.isStarted = false,
+    this.isFinished = false,
+    this.animationInProgress = false,
+
+    // Base data
+    required this.board,
+    required this.sizeHorizontal,
+    required this.sizeVertical,
+    this.isBoardMined = false,
+
+    // Game data
+    this.minesCount = 0,
+    this.reportMode = false,
+    this.gameWin = false,
+    this.gameFail = false,
+  });
+
+  // Settings
+  final GameSettings gameSettings;
+  final GlobalSettings globalSettings;
+
+  // State
+  bool isRunning;
+  bool isStarted;
+  bool isFinished;
+  bool animationInProgress;
+
+  // Base data
+  Board board;
+  final int sizeHorizontal;
+  final int sizeVertical;
+  bool isBoardMined;
+
+  // Game data
+  int minesCount;
+  bool reportMode;
+  bool gameWin;
+  bool gameFail;
+
+  factory Game.createEmpty() {
+    return Game(
+      // Settings
+      gameSettings: GameSettings.createDefault(),
+      globalSettings: GlobalSettings.createDefault(),
+      // Base data
+      board: [],
+      sizeHorizontal: 0,
+      sizeVertical: 0,
+    );
+  }
+
+  factory Game.createNew({
+    GameSettings? gameSettings,
+    GlobalSettings? globalSettings,
+  }) {
+    final GameSettings newGameSettings = gameSettings ?? GameSettings.createDefault();
+    final GlobalSettings newGlobalSettings = globalSettings ?? GlobalSettings.createDefault();
+
+    final int sizeHorizontal = int.parse(newGameSettings.size.split('x')[0]);
+    final int sizeVertical = int.parse(newGameSettings.size.split('x')[1]);
+
+    // Create empty board (it will be mined after first hit)
+    final Board board = [];
+    for (int rowIndex = 0; rowIndex < sizeVertical; rowIndex++) {
+      final List<Cell> row = [];
+      for (int colIndex = 0; colIndex < sizeHorizontal; colIndex++) {
+        row.add(Cell(false));
+      }
+      board.add(row);
+    }
+
+    final int minesCountRatio =
+        DefaultGameSettings.minesCountRatios[newGameSettings.level] ?? 1;
+    final int minesCount = ((sizeHorizontal * sizeVertical) * minesCountRatio / 100).round();
+    printlog('Mines count: $minesCount');
+
+    return Game(
+      // Settings
+      gameSettings: newGameSettings,
+      globalSettings: newGlobalSettings,
+      // State
+      isRunning: true,
+      // Base data
+      board: board,
+      sizeHorizontal: sizeHorizontal,
+      sizeVertical: sizeVertical,
+      // Game data
+      minesCount: minesCount,
+    );
+  }
+
+  void addMines({
+    required int forbiddenRow,
+    required int forbiddenCol,
+  }) {
+    // Shuffle cells to put random mines, except on currently selected one
+    final List<List<int>> allowedCells = [];
+    for (int row = 0; row < sizeVertical; row++) {
+      for (int col = 0; col < sizeHorizontal; col++) {
+        if (!((forbiddenRow == row) && (forbiddenCol == col))) {
+          allowedCells.add([row, col]);
+        }
+      }
+    }
+    allowedCells.shuffle();
+
+    // Put random mines on board
+    for (int mineIndex = 0; mineIndex < minesCount; mineIndex++) {
+      board[allowedCells[mineIndex][0]][allowedCells[mineIndex][1]].isMined = true;
+    }
+
+    // Compute all mines counts on cells
+    for (int row = 0; row < sizeVertical; row++) {
+      for (int col = 0; col < sizeHorizontal; col++) {
+        board[row][col].minesCountAround = getMinesCountAround(row, col);
+      }
+    }
+
+    printGrid();
+  }
+
+  int getMinesCountAround(int row, int col) {
+    final int sizeHorizontal = board.length;
+    final int sizeVertical = board[0].length;
+
+    int minesCountAround = 0;
+    for (int deltaRow = -1; deltaRow <= 1; deltaRow++) {
+      for (int deltaCol = -1; deltaCol <= 1; deltaCol++) {
+        if ((row + deltaRow >= 0 && row + deltaRow < sizeVertical) &&
+            (col + deltaCol >= 0 && col + deltaCol < sizeHorizontal) &&
+            (board[row + deltaRow][col + deltaCol].isMined)) {
+          minesCountAround++;
+        }
+      }
+    }
+
+    return minesCountAround;
+  }
+
+  int countFlaggedCells() {
+    int count = 0;
+
+    final int sizeHorizontal = board.length;
+    final int sizeVertical = board[0].length;
+    for (int row = 0; row < sizeVertical; row++) {
+      for (int col = 0; col < sizeHorizontal; col++) {
+        if (board[row][col].isMarked == true) {
+          count++;
+        }
+      }
+    }
+
+    return count;
+  }
+
+  bool get canBeResumed => isStarted && !isFinished;
+  bool get gameWon => isRunning && isStarted && isFinished;
+
+  void dump() {
+    printlog('');
+    printlog('## Current game dump:');
+    printlog('');
+    printlog('$Game:');
+    printlog('  Settings');
+    gameSettings.dump();
+    globalSettings.dump();
+    printlog('  State');
+    printlog('    isRunning: $isRunning');
+    printlog('    isStarted: $isStarted');
+    printlog('    isFinished: $isFinished');
+    printlog('    animationInProgress: $animationInProgress');
+    printlog('  Base data');
+    printGrid();
+    printlog('    sizeHorizontal: $sizeHorizontal');
+    printlog('    sizeVertical: $sizeVertical');
+    printlog('    isBoardMined: $isBoardMined');
+    printlog('  Game data');
+    printlog('    minesCount: $minesCount');
+    printlog('    reportMode: $reportMode');
+    printlog('    gameWin: $gameWin');
+    printlog('    gameFail: $gameFail');
+    printlog('');
+  }
+
+  void printGrid() {
+    const String isMined = 'X';
+    const String isSafe = '.';
+
+    const String mineFound = '#';
+    const String wrongMarkedCell = '0';
+    const String exploredSafeCell = '.';
+    const String unkownState = ' ';
+
+    printlog('');
+    String line = '--';
+    for (int i = 0; i < board[0].length; i++) {
+      line += '-';
+    }
+    printlog('$line  $line');
+    for (int rowIndex = 0; rowIndex < board.length; rowIndex++) {
+      String currentLine = '';
+      String solvedLine = '';
+      for (int colIndex = 0; colIndex < board[rowIndex].length; colIndex++) {
+        solvedLine += board[rowIndex][colIndex].isMined ? isMined : isSafe;
+
+        String cellString = unkownState;
+        if (board[rowIndex][colIndex].isExplored) {
+          cellString = exploredSafeCell;
+        }
+        if (board[rowIndex][colIndex].isMarked) {
+          if (board[rowIndex][colIndex].isMined) {
+            cellString = mineFound;
+          } else {
+            cellString = wrongMarkedCell;
+          }
+        }
+        currentLine += cellString;
+      }
+      printlog('|$currentLine|  |$solvedLine|');
+    }
+    printlog('$line  $line');
+    printlog('');
+  }
+
+  @override
+  String toString() {
+    return '$Game(${toJson()})';
+  }
+
+  Map<String, dynamic>? toJson() {
+    return <String, dynamic>{
+      // Settings
+      'gameSettings': gameSettings.toJson(),
+      'globalSettings': globalSettings.toJson(),
+      // State
+      'isRunning': isRunning,
+      'isStarted': isStarted,
+      'isFinished': isFinished,
+      'animationInProgress': animationInProgress,
+      // Base data
+      'board': board,
+      'sizeHorizontal': sizeHorizontal,
+      'sizeVertical': sizeVertical,
+      'isBoardMined': isBoardMined,
+      // Game data
+      'minesCount': minesCount,
+      'reportMode': reportMode,
+      'gameWin': gameWin,
+      'gameFail': gameFail,
+    };
+  }
+}
diff --git a/lib/models/settings/settings_game.dart b/lib/models/settings/settings_game.dart
new file mode 100644
index 0000000000000000000000000000000000000000..f2b3b56b9b7d1fe970e7181bab85acfeb92cc7e9
--- /dev/null
+++ b/lib/models/settings/settings_game.dart
@@ -0,0 +1,54 @@
+import 'package:minehunter/config/default_game_settings.dart';
+import 'package:minehunter/utils/tools.dart';  
+
+class GameSettings {
+  final String level;
+  final String size;
+
+  GameSettings({
+    required this.level,
+    required this.size,
+  });
+
+  static String getLevelValueFromUnsafe(String level) {
+    if (DefaultGameSettings.allowedLevelValues.contains(level)) {
+      return level;
+    }
+
+    return DefaultGameSettings.defaultLevelValue;
+  }
+
+  static String getSizeValueFromUnsafe(String size) {
+    if (DefaultGameSettings.allowedSizeValues.contains(size)) {
+      return size;
+    }
+
+    return DefaultGameSettings.defaultSizeValue;
+  }
+
+  factory GameSettings.createDefault() {
+    return GameSettings(
+      level: DefaultGameSettings.defaultLevelValue,
+      size: DefaultGameSettings.defaultSizeValue,
+    );
+  }
+
+  void dump() {
+    printlog('$GameSettings:');
+    printlog('  ${DefaultGameSettings.parameterCodeLevel}: $level');
+    printlog('  ${DefaultGameSettings.parameterCodeSize}: $size');
+    printlog('');
+  }
+
+  @override
+  String toString() {
+    return '$GameSettings(${toJson()})';
+  }
+
+  Map<String, dynamic>? toJson() {
+    return <String, dynamic>{
+      DefaultGameSettings.parameterCodeLevel: level,
+      DefaultGameSettings.parameterCodeSize: size,
+    };
+  }
+}
diff --git a/lib/models/settings/settings_global.dart b/lib/models/settings/settings_global.dart
new file mode 100644
index 0000000000000000000000000000000000000000..9900685f127517bf6c5c700be997f178fde37958
--- /dev/null
+++ b/lib/models/settings/settings_global.dart
@@ -0,0 +1,41 @@
+import 'package:minehunter/config/default_global_settings.dart';
+import 'package:minehunter/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..5b6aee12bf30231f630550de6425ce0ef1262184
--- /dev/null
+++ b/lib/models/types.dart
@@ -0,0 +1,5 @@
+import 'package:minehunter/models/game/cell.dart';
+
+typedef Board = List<List<Cell>>;
+typedef AnimatedBoard = List<List<bool>>;
+typedef AnimatedBoardSequence = List<AnimatedBoard>;
diff --git a/lib/provider/data.dart b/lib/provider/data.dart
deleted file mode 100644
index 0ab77100d03abc731f0b42d95f90ddace2436c3d..0000000000000000000000000000000000000000
--- a/lib/provider/data.dart
+++ /dev/null
@@ -1,292 +0,0 @@
-import 'dart:convert';
-
-import 'package:flutter/foundation.dart';
-import 'package:shared_preferences/shared_preferences.dart';
-
-import 'package:minehunter/entities/cell.dart';
-
-typedef Board = List<List<Cell>>;
-typedef AnimatedBoard = List<List<bool>>;
-typedef AnimatedBoardSequence = List<AnimatedBoard>;
-
-class Data extends ChangeNotifier {
-  // Configuration available parameters
-  final List<String> _availableParameters = ['level', 'size', 'skin'];
-  List<String> get availableParameters => _availableParameters;
-
-  // Configuration available values
-  final List<String> _availableLevelValues = ['easy', 'medium', 'hard', 'nightmare'];
-  final List<String> _availableSizeValues = ['10x10', '15x15', '20x20'];
-  final List<String> _availableSkinValues = ['default'];
-
-  List<String> get availableLevelValues => _availableLevelValues;
-  List<String> get availableSizeValues => _availableSizeValues;
-  List<String> get availableSkinValues => _availableSkinValues;
-
-  // Application default configuration
-  String _parameterLevel = '';
-  final String _parameterLevelDefault = 'medium';
-  String _parameterSize = '';
-  final String _parameterSizeDefault = '15x15';
-  String _parameterSkin = '';
-  final String _parameterSkinDefault = 'default';
-
-  // Application current configuration
-  String get parameterLevel => _parameterLevel;
-  String get parameterSize => _parameterSize;
-  String get parameterSkin => _parameterSkin;
-
-  // Game data
-  bool _assetsPreloaded = false;
-  bool _gameIsRunning = false;
-  bool _animationInProgress = false;
-  int _sizeVertical = 0;
-  int _sizeHorizontal = 0;
-  Board _board = [];
-  bool _isBoardMined = false;
-  int _minesCount = 0;
-  bool _reportMode = false;
-  bool _gameWin = false;
-  bool _gameFail = false;
-  String _currentState = '';
-
-  void updateParameterLevel(String parameterLevel) {
-    _parameterLevel = parameterLevel;
-    notifyListeners();
-  }
-
-  int get sizeVertical => _sizeVertical;
-  int get sizeHorizontal => _sizeHorizontal;
-  void updateParameterSize(String parameterSize) {
-    _parameterSize = parameterSize;
-    _sizeHorizontal = int.parse(_parameterSize.split('x')[0]);
-    _sizeVertical = int.parse(_parameterSize.split('x')[1]);
-    notifyListeners();
-  }
-
-  void updateParameterSkin(String parameterSkin) {
-    _parameterSkin = parameterSkin;
-    notifyListeners();
-  }
-
-  String getParameterValue(String parameterCode) {
-    switch (parameterCode) {
-      case 'level':
-        {
-          return _parameterLevel;
-        }
-      case 'size':
-        {
-          return _parameterSize;
-        }
-
-      case 'skin':
-        {
-          return _parameterSkin;
-        }
-    }
-    return '';
-  }
-
-  List<String> getParameterAvailableValues(String parameterCode) {
-    switch (parameterCode) {
-      case 'level':
-        {
-          return _availableLevelValues;
-        }
-
-      case 'size':
-        {
-          return _availableSizeValues;
-        }
-
-      case 'skin':
-        {
-          return _availableSkinValues;
-        }
-    }
-    return [];
-  }
-
-  setParameterValue(String parameterCode, String parameterValue) async {
-    switch (parameterCode) {
-      case 'level':
-        {
-          updateParameterLevel(parameterValue);
-        }
-        break;
-      case 'size':
-        {
-          updateParameterSize(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('skin', prefs.getString('skin') ?? _parameterSkinDefault);
-  }
-
-  String get currentState => _currentState;
-
-  String computeCurrentGameState() {
-    String cellsValues = '';
-    for (int rowIndex = 0; rowIndex < _board.length; rowIndex++) {
-      for (int colIndex = 0; colIndex < _board[rowIndex].length; colIndex++) {
-        cellsValues += _board[rowIndex][colIndex].isMined ? 'X' : ' ';
-        cellsValues += _board[rowIndex][colIndex].isExplored ? 'E' : ' ';
-        cellsValues += _board[rowIndex][colIndex].isMarked ? 'P' : ' ';
-        cellsValues += _board[rowIndex][colIndex].isExploded ? '*' : ' ';
-        cellsValues += _board[rowIndex][colIndex].minesCountAround.toString();
-        cellsValues += ';';
-      }
-    }
-
-    var currentState = {
-      'level': _parameterLevel,
-      'size': _parameterSize,
-      'skin': _parameterSkin,
-      'board': cellsValues,
-    };
-
-    return json.encode(currentState);
-  }
-
-  void saveCurrentGameState() async {
-    if (_gameIsRunning) {
-      _currentState = computeCurrentGameState();
-
-      final prefs = await SharedPreferences.getInstance();
-      prefs.setString('savedState', _currentState);
-    } else {
-      resetCurrentSavedState();
-    }
-  }
-
-  void resetCurrentSavedState() async {
-    _currentState = '';
-
-    final prefs = await SharedPreferences.getInstance();
-    prefs.setString('savedState', _currentState);
-    notifyListeners();
-  }
-
-  void loadCurrentSavedState() async {
-    final prefs = await SharedPreferences.getInstance();
-    _currentState = prefs.getString('savedState') ?? '';
-  }
-
-  bool hasCurrentSavedState() {
-    return (_currentState != '');
-  }
-
-  Map<String, dynamic> getCurrentSavedState() {
-    if (_currentState != '') {
-      Map<String, dynamic> savedState = json.decode(_currentState);
-      if (savedState.isNotEmpty) {
-        return savedState;
-      }
-    }
-    return {};
-  }
-
-  bool get gameIsRunning => _gameIsRunning;
-  void updateGameIsRunning(bool gameIsRunning) {
-    _gameIsRunning = gameIsRunning;
-    updateGameWin(false);
-    updateGameFail(false);
-    updateReportMode(false);
-    notifyListeners();
-  }
-
-  bool get gameWin => _gameWin;
-  void updateGameWin(bool gameWin) {
-    _gameWin = gameWin;
-    notifyListeners();
-  }
-
-  bool get gameFail => _gameFail;
-  void updateGameFail(bool gameFail) {
-    _gameFail = gameFail;
-    notifyListeners();
-  }
-
-  Board get board => _board;
-  void updateBoard(Board board) {
-    _board = board;
-    notifyListeners();
-  }
-
-  void setCellAsExplored(int row, int col) {
-    _board[row][col].isExplored = true;
-    _board[row][col].isMarked = false;
-    if (_board[row][col].isMined) {
-      _board[row][col].isExploded = true;
-    }
-
-    saveCurrentGameState();
-    notifyListeners();
-  }
-
-  void toggleCellMark(int row, int col) {
-    _board[row][col].isMarked = !_board[row][col].isMarked;
-
-    saveCurrentGameState();
-    notifyListeners();
-  }
-
-  bool get assetsPreloaded => _assetsPreloaded;
-  void updateAssetsPreloaded(bool assetsPreloaded) {
-    _assetsPreloaded = assetsPreloaded;
-  }
-
-  bool get isBoardMined => _isBoardMined;
-  void updateIsBoardMined(bool isBoardMined) {
-    _isBoardMined = isBoardMined;
-    notifyListeners();
-  }
-
-  int get minesCount => _minesCount;
-  void updateMinesCount(int minesCount) {
-    _minesCount = minesCount;
-  }
-
-  bool get reportMode => _reportMode;
-  void updateReportMode(bool reportMode) {
-    _reportMode = reportMode;
-    notifyListeners();
-  }
-
-  bool get animationInProgress => _animationInProgress;
-  void updateAnimationInProgress(bool animationInProgress) {
-    _animationInProgress = animationInProgress;
-    notifyListeners();
-  }
-
-  void setAnimatedBackground(List animatedCellsPattern) {
-    for (int row = 0; row < _sizeVertical; row++) {
-      for (int col = 0; col < _sizeHorizontal; col++) {
-        _board[row][col].isAnimated = animatedCellsPattern[row][col];
-      }
-    }
-    notifyListeners();
-  }
-
-  void resetAnimatedBackground() {
-    for (int row = 0; row < _sizeVertical; row++) {
-      for (int col = 0; col < _sizeHorizontal; col++) {
-        _board[row][col].isAnimated = false;
-      }
-    }
-  }
-}
diff --git a/lib/ui/game/game_bottom.dart b/lib/ui/game/game_bottom.dart
new file mode 100644
index 0000000000000000000000000000000000000000..6e1e63bf1f36b4bf85a4104db466caae0fd2c882
--- /dev/null
+++ b/lib/ui/game/game_bottom.dart
@@ -0,0 +1,21 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:minehunter/cubit/game_cubit.dart';
+import 'package:minehunter/models/game/game.dart';
+import 'package:minehunter/ui/widgets/game/mode_toggle.dart';
+
+class GameBottomWidget extends StatelessWidget {
+  const GameBottomWidget({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        final Game currentGame = gameState.currentGame;
+
+        return !currentGame.isFinished ? const ToggleGameMode() : const SizedBox.shrink();
+      },
+    );
+  }
+}
diff --git a/lib/ui/game/game_end.dart b/lib/ui/game/game_end.dart
new file mode 100644
index 0000000000000000000000000000000000000000..d6f07b1cbd81bba9cd179e142fae8602337431c3
--- /dev/null
+++ b/lib/ui/game/game_end.dart
@@ -0,0 +1,55 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:minehunter/cubit/game_cubit.dart';
+import 'package:minehunter/models/game/game.dart';
+import 'package:minehunter/ui/widgets/actions/button_game_quit.dart';
+
+class GameEndWidget extends StatelessWidget {
+  const GameEndWidget({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        final Game currentGame = gameState.currentGame;
+
+        final Image decorationImage = Image(
+          image: AssetImage(currentGame.gameWin
+              ? 'assets/ui/game_win.png'
+              : currentGame.gameFail
+                  ? 'assets/ui/game_fail.png'
+                  : ''),
+          fit: BoxFit.fill,
+        );
+
+        return Container(
+          margin: const EdgeInsets.all(2),
+          padding: const EdgeInsets.all(2),
+          child: Table(
+            defaultColumnWidth: const IntrinsicColumnWidth(),
+            children: [
+              TableRow(
+                children: [
+                  Column(
+                    children: [decorationImage],
+                  ),
+                  Column(
+                    children: [
+                      currentGame.animationInProgress
+                          ? decorationImage
+                          : const QuitGameButton()
+                    ],
+                  ),
+                  Column(
+                    children: [decorationImage],
+                  ),
+                ],
+              ),
+            ],
+          ),
+        );
+      },
+    );
+  }
+}
diff --git a/lib/ui/game/game_top.dart b/lib/ui/game/game_top.dart
new file mode 100644
index 0000000000000000000000000000000000000000..6b60094966fa6a7bb35b8830520426a6237304d5
--- /dev/null
+++ b/lib/ui/game/game_top.dart
@@ -0,0 +1,12 @@
+import 'package:flutter/material.dart';
+import 'package:minehunter/ui/widgets/indicators/indicator_top.dart';
+
+
+class GameTopWidget extends StatelessWidget {
+  const GameTopWidget({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return const TopIndicator();
+  }
+}
diff --git a/lib/ui/helpers/app_titles.dart b/lib/ui/helpers/app_titles.dart
new file mode 100644
index 0000000000000000000000000000000000000000..b98107b12fabc3114ebfbec994166b588abcf1ad
--- /dev/null
+++ b/lib/ui/helpers/app_titles.dart
@@ -0,0 +1,32 @@
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+
+class AppHeader extends StatelessWidget {
+  const AppHeader({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.headlineMedium!.apply(fontWeightDelta: 2),
+    );
+  }
+}
+
+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.titleLarge!.apply(fontWeightDelta: 2),
+    );
+  }
+}
diff --git a/lib/ui/helpers/outlined_text_widget.dart b/lib/ui/helpers/outlined_text_widget.dart
new file mode 100644
index 0000000000000000000000000000000000000000..b450f6b1c6323e0d645059e4d367ec4987891258
--- /dev/null
+++ b/lib/ui/helpers/outlined_text_widget.dart
@@ -0,0 +1,51 @@
+import 'package:flutter/material.dart';
+
+import 'package:minehunter/utils/color_extensions.dart';
+
+class OutlinedText extends StatelessWidget {
+  const OutlinedText({
+    super.key,
+    required this.text,
+    required this.fontSize,
+    required this.textColor,
+    this.outlineColor,
+  });
+
+  final String text;
+  final double fontSize;
+  final Color textColor;
+  final Color? outlineColor;
+
+  @override
+  Widget build(BuildContext context) {
+    final double delta = fontSize / 30;
+
+    return Text(
+      text,
+      style: TextStyle(
+        inherit: true,
+        fontSize: fontSize,
+        fontWeight: FontWeight.w600,
+        color: textColor,
+        shadows: [
+          Shadow(
+            offset: Offset(-delta, -delta),
+            color: outlineColor ?? textColor.darken(),
+          ),
+          Shadow(
+            offset: Offset(delta, -delta),
+            color: outlineColor ?? textColor.darken(),
+          ),
+          Shadow(
+            offset: Offset(delta, delta),
+            color: outlineColor ?? textColor.darken(),
+          ),
+          Shadow(
+            offset: Offset(-delta, delta),
+            color: outlineColor ?? textColor.darken(),
+          ),
+        ],
+      ),
+    );
+  }
+}
diff --git a/lib/ui/layout/game.dart b/lib/ui/layout/game.dart
deleted file mode 100644
index 36796492ca10e14dc7f8d78aa8251118ec275ced..0000000000000000000000000000000000000000
--- a/lib/ui/layout/game.dart
+++ /dev/null
@@ -1,38 +0,0 @@
-import 'package:flutter/material.dart';
-
-import 'package:minehunter/provider/data.dart';
-import 'package:minehunter/ui/layout/tileset.dart';
-import 'package:minehunter/ui/widgets/game/indicator_top.dart';
-import 'package:minehunter/ui/widgets/game/message_game_end.dart';
-import 'package:minehunter/ui/widgets/game/mode_toggle.dart';
-
-class Game extends StatelessWidget {
-  const Game({super.key, required this.myProvider});
-
-  final Data myProvider;
-
-  @override
-  Widget build(BuildContext context) {
-    final bool gameIsFinished = myProvider.gameWin || myProvider.gameFail;
-
-    return Column(
-      mainAxisAlignment: MainAxisAlignment.start,
-      crossAxisAlignment: CrossAxisAlignment.center,
-      children: [
-        const SizedBox(height: 8),
-        TopIndicator(myProvider: myProvider),
-        const SizedBox(height: 2),
-        Expanded(
-          child: Tileset(myProvider: myProvider),
-        ),
-        const SizedBox(height: 2),
-        Container(
-          child: gameIsFinished
-              ? EndGameMessage(myProvider: myProvider)
-              : ToggleGameMode(myProvider: myProvider),
-        ),
-        const SizedBox(height: 8),
-      ],
-    );
-  }
-}
diff --git a/lib/ui/layout/parameters.dart b/lib/ui/layout/parameters.dart
deleted file mode 100644
index ee2502a4129b96df781a6d66b1156d56ee17f9a3..0000000000000000000000000000000000000000
--- a/lib/ui/layout/parameters.dart
+++ /dev/null
@@ -1,129 +0,0 @@
-import 'package:flutter/material.dart';
-
-import 'package:minehunter/provider/data.dart';
-import 'package:minehunter/ui/widgets/home/button_game_resume.dart';
-import 'package:minehunter/ui/widgets/home/button_game_start_new.dart';
-
-class Parameters extends StatelessWidget {
-  const Parameters({super.key, required this.myProvider});
-
-  final Data myProvider;
-
-  static const double separatorHeight = 2.0;
-  static const double blockMargin = 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(myProvider, parameters[index]));
-      lines.add(const SizedBox(height: separatorHeight));
-    }
-
-    myProvider.loadCurrentSavedState();
-    Widget buttonsBlock = myProvider.hasCurrentSavedState()
-        ? ResumeGameButton(myProvider: myProvider)
-        : StartNewGameButton(myProvider: myProvider);
-
-    return Column(
-      mainAxisAlignment: MainAxisAlignment.start,
-      crossAxisAlignment: CrossAxisAlignment.center,
-      children: [
-        const SizedBox(height: separatorHeight),
-        Expanded(
-          child: Column(
-            mainAxisSize: MainAxisSize.min,
-            mainAxisAlignment: MainAxisAlignment.center,
-            children: lines,
-          ),
-        ),
-        const SizedBox(height: separatorHeight),
-        Container(
-          child: buttonsBlock,
-        ),
-      ],
-    );
-  }
-
-  static Image buildImageWidget(String imageAssetCode) {
-    return Image(
-      image: AssetImage('assets/icons/$imageAssetCode.png'),
-      fit: BoxFit.fill,
-    );
-  }
-
-  static Container buildImageContainerWidget(String imageAssetCode) {
-    return Container(
-      child: buildImageWidget(imageAssetCode),
-    );
-  }
-
-  static Column buildDecorationImageWidget() {
-    return Column(
-      children: [
-        TextButton(
-          child: buildImageContainerWidget('placeholder'),
-          onPressed: () {},
-        ),
-      ],
-    );
-  }
-
-  Widget buildParameterSelector(Data myProvider, String parameterCode) {
-    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(myProvider, parameterCode, availableValues[index])
-                ],
-              ),
-          ],
-        ),
-      ],
-    );
-  }
-
-  Widget buildParameterButton(Data myProvider, 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 f5986aab892ea72467bd80636da3ee85c1cf600f..0000000000000000000000000000000000000000
--- a/lib/ui/layout/tileset.dart
+++ /dev/null
@@ -1,50 +0,0 @@
-import 'package:flutter/material.dart';
-
-import 'package:minehunter/provider/data.dart';
-
-class Tileset extends StatelessWidget {
-  const Tileset({super.key, required this.myProvider});
-
-  final Data myProvider;
-
-  @override
-  Widget build(BuildContext context) {
-    final Board board = myProvider.board;
-    final Color borderColor = myProvider.reportMode ? Colors.blue : Colors.black;
-
-    return Container(
-      margin: const EdgeInsets.all(2),
-      padding: const EdgeInsets.all(2),
-      child: Column(
-        children: [
-          Container(
-            decoration: BoxDecoration(
-              color: borderColor,
-              borderRadius: BorderRadius.circular(2),
-              border: Border.all(
-                color: borderColor,
-                width: 2,
-              ),
-            ),
-            child: Table(
-              defaultColumnWidth: const IntrinsicColumnWidth(),
-              children: [
-                for (int row = 0; row < myProvider.sizeVertical; row++)
-                  TableRow(
-                    children: [
-                      for (int col = 0; col < myProvider.sizeHorizontal; col++)
-                        Column(
-                          children: [
-                            board[row][col].widget(myProvider, row, col),
-                          ],
-                        ),
-                    ],
-                  ),
-              ],
-            ),
-          ),
-        ],
-      ),
-    );
-  }
-}
diff --git a/lib/ui/layouts/game_layout.dart b/lib/ui/layouts/game_layout.dart
new file mode 100644
index 0000000000000000000000000000000000000000..05180ea903dbd732ab93a4b7875692928f3d5495
--- /dev/null
+++ b/lib/ui/layouts/game_layout.dart
@@ -0,0 +1,40 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:minehunter/cubit/game_cubit.dart';
+import 'package:minehunter/models/game/game.dart';
+import 'package:minehunter/ui/game/game_bottom.dart';
+import 'package:minehunter/ui/game/game_end.dart';
+import 'package:minehunter/ui/game/game_top.dart';
+import 'package:minehunter/ui/widgets/game/game_board.dart';
+
+class GameLayout extends StatelessWidget {
+  const GameLayout({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        final Game currentGame = gameState.currentGame;
+
+        return Container(
+          alignment: AlignmentDirectional.topCenter,
+          padding: const EdgeInsets.all(4),
+          child: Column(
+            mainAxisAlignment: MainAxisAlignment.start,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              const GameTopWidget(),
+              const SizedBox(height: 8),
+              const GameBoardWidget(),
+              const SizedBox(height: 8),
+              const GameBottomWidget(),
+              const Expanded(child: SizedBox.shrink()),
+              currentGame.isFinished ? const GameEndWidget() : const SizedBox.shrink(),
+            ],
+          ),
+        );
+      },
+    );
+  }
+}
diff --git a/lib/ui/layouts/parameters_layout.dart b/lib/ui/layouts/parameters_layout.dart
new file mode 100644
index 0000000000000000000000000000000000000000..de36efd4e35431508ac96eed770cbe4376bee78d
--- /dev/null
+++ b/lib/ui/layouts/parameters_layout.dart
@@ -0,0 +1,154 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:minehunter/config/default_game_settings.dart';
+import 'package:minehunter/config/default_global_settings.dart';
+import 'package:minehunter/cubit/settings_game_cubit.dart';
+import 'package:minehunter/cubit/settings_global_cubit.dart';
+import 'package:minehunter/ui/parameters/parameter_image.dart';
+import 'package:minehunter/ui/parameters/parameter_painter.dart';
+import 'package:minehunter/ui/widgets/actions/button_delete_saved_game.dart';
+import 'package:minehunter/ui/widgets/actions/button_game_start_new.dart';
+import 'package:minehunter/ui/widgets/actions/button_resume_saved_game.dart';
+
+class ParametersLayout extends StatelessWidget {
+  const ParametersLayout({super.key, required this.canResume});
+
+  final bool canResume;
+
+  final double separatorHeight = 8.0;
+
+  @override
+  Widget build(BuildContext context) {
+    final List<Widget> lines = [];
+
+    // Game settings
+    for (String code in DefaultGameSettings.availableParameters) {
+      lines.add(Row(
+        mainAxisAlignment: MainAxisAlignment.spaceBetween,
+        children: buildParametersLine(
+          code: code,
+          isGlobal: false,
+        ),
+      ));
+
+      lines.add(SizedBox(height: separatorHeight));
+    }
+
+    lines.add(SizedBox(height: separatorHeight));
+
+    if (canResume == false) {
+      // Start new game
+      lines.add(const Expanded(
+        child: StartNewGameButton(),
+      ));
+    } else {
+      // Resume game
+      lines.add(const Expanded(
+        child: ResumeSavedGameButton(),
+      ));
+      // Delete saved game
+      lines.add(SizedBox.square(
+        dimension: MediaQuery.of(context).size.width / 4,
+        child: const DeleteSavedGameButton(),
+      ));
+    }
+
+    lines.add(SizedBox(height: separatorHeight));
+
+    // Global settings
+    for (String code in DefaultGlobalSettings.availableParameters) {
+      lines.add(Row(
+        mainAxisAlignment: MainAxisAlignment.spaceBetween,
+        children: buildParametersLine(
+          code: code,
+          isGlobal: true,
+        ),
+      ));
+
+      lines.add(SizedBox(height: separatorHeight));
+    }
+
+    return Column(
+      children: lines,
+    );
+  }
+
+  List<Widget> buildParametersLine({
+    required String code,
+    required bool isGlobal,
+  }) {
+    final List<Widget> parameterButtons = [];
+
+    final List<String> availableValues = isGlobal
+        ? DefaultGlobalSettings.getAvailableValues(code)
+        : DefaultGameSettings.getAvailableValues(code);
+
+    if (availableValues.length <= 1) {
+      return [];
+    }
+
+    for (String value in availableValues) {
+      final Widget parameterButton = BlocBuilder<GameSettingsCubit, GameSettingsState>(
+        builder: (BuildContext context, GameSettingsState gameSettingsState) {
+          return BlocBuilder<GlobalSettingsCubit, GlobalSettingsState>(
+            builder: (BuildContext context, GlobalSettingsState globalSettingsState) {
+              final GameSettingsCubit gameSettingsCubit =
+                  BlocProvider.of<GameSettingsCubit>(context);
+              final GlobalSettingsCubit globalSettingsCubit =
+                  BlocProvider.of<GlobalSettingsCubit>(context);
+
+              final String currentValue = isGlobal
+                  ? globalSettingsCubit.getParameterValue(code)
+                  : gameSettingsCubit.getParameterValue(code);
+
+              final bool isActive = (value == currentValue);
+
+              final double displayWidth = MediaQuery.of(context).size.width;
+              final double itemWidth = displayWidth / availableValues.length - 26;
+
+              final bool displayedWithAssets =
+                  DefaultGlobalSettings.displayedWithAssets.contains(code) ||
+                      DefaultGameSettings.displayedWithAssets.contains(code);
+
+              return TextButton(
+                child: Container(
+                  child: displayedWithAssets
+                      ? SizedBox.square(
+                          dimension: itemWidth,
+                          child: ParameterImage(
+                            code: code,
+                            value: value,
+                            isSelected: isActive,
+                          ),
+                        )
+                      : 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/parameters/parameter_image.dart b/lib/ui/parameters/parameter_image.dart
new file mode 100644
index 0000000000000000000000000000000000000000..fc4b576f85b01158b74548400d11a4d027c57fbe
--- /dev/null
+++ b/lib/ui/parameters/parameter_image.dart
@@ -0,0 +1,38 @@
+import 'package:flutter/material.dart';
+
+class ParameterImage extends StatelessWidget {
+  const ParameterImage({
+    super.key,
+    required this.code,
+    required this.value,
+    required this.isSelected,
+  });
+
+  final String code;
+  final String value;
+  final bool isSelected;
+
+  static const Color buttonBackgroundColor = Colors.white;
+  static const Color buttonBorderColorActive = Colors.blue;
+  static const Color buttonBorderColorInactive = Colors.white;
+  static const double buttonBorderWidth = 8.0;
+  static const double buttonBorderRadius = 8.0;
+
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      decoration: BoxDecoration(
+        color: buttonBackgroundColor,
+        borderRadius: BorderRadius.circular(buttonBorderRadius),
+        border: Border.all(
+          color: isSelected ? buttonBorderColorActive : buttonBorderColorInactive,
+          width: buttonBorderWidth,
+        ),
+      ),
+      child: Image(
+        image: AssetImage('assets/ui/${code}_$value.png'),
+        fit: BoxFit.fill,
+      ),
+    );
+  }
+}
diff --git a/lib/ui/parameters/parameter_painter.dart b/lib/ui/parameters/parameter_painter.dart
new file mode 100644
index 0000000000000000000000000000000000000000..e00cf06d4cdfad6d3e62e345e0d7007e16ec5a90
--- /dev/null
+++ b/lib/ui/parameters/parameter_painter.dart
@@ -0,0 +1,226 @@
+import 'dart:math';
+
+import 'package:flutter/material.dart';
+
+import 'package:minehunter/config/default_game_settings.dart';
+import 'package:minehunter/models/settings/settings_game.dart';
+import 'package:minehunter/models/settings/settings_global.dart';
+import 'package:minehunter/utils/tools.dart';
+
+class ParameterPainter extends CustomPainter {
+  const ParameterPainter({
+    required this.code,
+    required this.value,
+    required this.isSelected,
+    required this.gameSettings,
+    required this.globalSettings,
+  });
+
+  final String code;
+  final String value;
+  final bool isSelected;
+  final GameSettings gameSettings;
+  final GlobalSettings globalSettings;
+
+  @override
+  void paint(Canvas canvas, Size size) {
+    // force square
+    final double canvasSize = min(size.width, size.height);
+
+    const Color borderColorEnabled = Colors.blue;
+    const Color borderColorDisabled = Colors.white;
+
+    // "enabled/disabled" border
+    final paint = Paint();
+    paint.style = PaintingStyle.stroke;
+    paint.color = isSelected ? borderColorEnabled : borderColorDisabled;
+    paint.strokeJoin = StrokeJoin.round;
+    paint.strokeWidth = 10;
+    canvas.drawRect(
+        Rect.fromPoints(const Offset(0, 0), Offset(canvasSize, canvasSize)), paint);
+
+    // content
+    switch (code) {
+      case DefaultGameSettings.parameterCodeLevel:
+        paintLevelParameterItem(value, canvas, canvasSize);
+        break;
+      case DefaultGameSettings.parameterCodeSize:
+        paintSizeParameterItem(value, canvas, canvasSize);
+        break;
+      default:
+        printlog('Unknown parameter: $code/$value');
+        paintUnknownParameterItem(value, canvas, canvasSize);
+    }
+  }
+
+  @override
+  bool shouldRepaint(CustomPainter oldDelegate) {
+    return false;
+  }
+
+  // "unknown" parameter -> simple block with text
+  void paintUnknownParameterItem(
+    final String value,
+    final Canvas canvas,
+    final double size,
+  ) {
+    final paint = Paint();
+    paint.strokeJoin = StrokeJoin.round;
+    paint.strokeWidth = 3;
+
+    paint.color = Colors.grey;
+    paint.style = PaintingStyle.fill;
+    canvas.drawRect(Rect.fromPoints(const Offset(0, 0), Offset(size, size)), paint);
+
+    final textSpan = TextSpan(
+      text: '?\n$value',
+      style: const TextStyle(
+        color: Colors.black,
+        fontSize: 18,
+        fontWeight: FontWeight.bold,
+      ),
+    );
+    final textPainter = TextPainter(
+      text: textSpan,
+      textDirection: TextDirection.ltr,
+      textAlign: TextAlign.center,
+    );
+    textPainter.layout();
+    textPainter.paint(
+      canvas,
+      Offset(
+        (size - textPainter.width) * 0.5,
+        (size - textPainter.height) * 0.5,
+      ),
+    );
+  }
+
+  void paintLevelParameterItem(
+    final String value,
+    final Canvas canvas,
+    final double size,
+  ) {
+    Color backgroundColor = Colors.grey;
+
+    final List<dynamic> stars = [];
+
+    switch (value) {
+      case DefaultGameSettings.levelValueEasy:
+        backgroundColor = Colors.green;
+        stars.add([0.5, 0.5]);
+        break;
+      case DefaultGameSettings.levelValueMedium:
+        backgroundColor = Colors.orange;
+        stars.add([0.3, 0.5]);
+        stars.add([0.7, 0.5]);
+        break;
+      case DefaultGameSettings.levelValueHard:
+        backgroundColor = Colors.red;
+        stars.add([0.3, 0.3]);
+        stars.add([0.7, 0.3]);
+        stars.add([0.5, 0.7]);
+        break;
+      case DefaultGameSettings.levelValueNightmare:
+        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,
+      textAlign: TextAlign.center,
+    );
+    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 paintSizeParameterItem(
+    final String value,
+    final Canvas canvas,
+    final double size,
+  ) {
+    Color backgroundColor = Colors.grey;
+    int gridWidth = 1;
+
+    switch (value) {
+      case DefaultGameSettings.sizeValueSmall:
+        backgroundColor = Colors.green;
+        gridWidth = 2;
+        break;
+      case DefaultGameSettings.sizeValueMedium:
+        backgroundColor = Colors.orange;
+        gridWidth = 3;
+        break;
+      case DefaultGameSettings.sizeValueLarge:
+        backgroundColor = Colors.red;
+        gridWidth = 4;
+        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 squareColor = Colors.grey.shade200;
+    final borderColor = 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 = 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/game_page.dart b/lib/ui/screens/game_page.dart
deleted file mode 100644
index cce017474d37d22a29b137981cbdd6e2bd3eb8ae..0000000000000000000000000000000000000000
--- a/lib/ui/screens/game_page.dart
+++ /dev/null
@@ -1,91 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
-
-import 'package:minehunter/provider/data.dart';
-import 'package:minehunter/ui/layout/game.dart';
-import 'package:minehunter/ui/layout/parameters.dart';
-
-class GamePage extends StatefulWidget {
-  const GamePage({super.key});
-
-  @override
-  GamePageState createState() => GamePageState();
-}
-
-class GamePageState extends State<GamePage> {
-  @override
-  void initState() {
-    super.initState();
-
-    final Data myProvider = Provider.of<Data>(context, listen: false);
-    myProvider.initParametersValues();
-  }
-
-  List<String> getImagesAssets(Data myProvider) {
-    final List<String> assets = [];
-
-    final List<String> gameImages = [
-      'button_back',
-      'button_start',
-      'game_fail',
-      'game_win',
-    ];
-    for (String level in myProvider.availableLevelValues) {
-      gameImages.add('level_$level');
-    }
-    for (String size in myProvider.availableSizeValues) {
-      gameImages.add('size_$size');
-    }
-
-    for (String image in gameImages) {
-      assets.add('${'assets/icons/$image'}.png');
-    }
-
-    final List<String> skinImages = [
-      'button_mark_mine_off',
-      'button_mark_mine_on',
-      'indicator_report_on',
-      'indicator_report_off',
-      'indicator_walk_on',
-      'indicator_walk_off',
-      'tile_flag_ko',
-      'tile_flag_ok',
-      'tile_flag',
-      'tile_mine_not_found',
-      'tile_mine',
-      'tile_unknown',
-    ];
-    for (int value = 0; value < 9; value++) {
-      skinImages.add('tile_$value');
-    }
-
-    for (String image in skinImages) {
-      assets.add('${'assets/skins/default_$image'}.png');
-    }
-
-    assets.add('assets/skins/default_empty.png');
-
-    return assets;
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    final Data myProvider = Provider.of<Data>(context);
-
-    if (!myProvider.assetsPreloaded) {
-      final List<String> assets = getImagesAssets(myProvider);
-      for (String asset in assets) {
-        precacheImage(AssetImage(asset), context);
-      }
-      myProvider.updateAssetsPreloaded(true);
-    }
-
-    return SafeArea(
-      child: Center(
-        child: myProvider.gameIsRunning
-            ? Game(myProvider: myProvider)
-            : Parameters(myProvider: myProvider),
-      ),
-    );
-  }
-}
diff --git a/lib/ui/screens/about_page.dart b/lib/ui/screens/page_about.dart
similarity index 86%
rename from lib/ui/screens/about_page.dart
rename to lib/ui/screens/page_about.dart
index 39efd8cc91f36d4d43227ff614a00e5bb1c60ddf..11329edb6e31fd66565b6747923c97e6c6694196 100644
--- a/lib/ui/screens/about_page.dart
+++ b/lib/ui/screens/page_about.dart
@@ -2,10 +2,10 @@ import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/material.dart';
 import 'package:package_info_plus/package_info_plus.dart';
 
-import 'package:minehunter/ui/widgets/header_app.dart';
+import 'package:minehunter/ui/helpers/app_titles.dart';
 
-class AboutPage extends StatelessWidget {
-  const AboutPage({super.key});
+class PageAbout extends StatelessWidget {
+  const PageAbout({super.key});
 
   @override
   Widget build(BuildContext context) {
@@ -17,7 +17,7 @@ class AboutPage extends StatelessWidget {
         mainAxisSize: MainAxisSize.max,
         children: <Widget>[
           const SizedBox(height: 8),
-          const AppHeader(text: 'about_title'),
+          const AppTitle(text: 'about_title'),
           const Text('about_content').tr(),
           FutureBuilder<PackageInfo>(
             future: PackageInfo.fromPlatform(),
diff --git a/lib/ui/screens/page_game.dart b/lib/ui/screens/page_game.dart
new file mode 100644
index 0000000000000000000000000000000000000000..5598d23f6f77146a895e5e58ff488a52af9f324a
--- /dev/null
+++ b/lib/ui/screens/page_game.dart
@@ -0,0 +1,24 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:minehunter/cubit/game_cubit.dart';
+import 'package:minehunter/models/game/game.dart';
+import 'package:minehunter/ui/layouts/game_layout.dart';
+import 'package:minehunter/ui/layouts/parameters_layout.dart';
+
+class PageGame extends StatelessWidget {
+  const PageGame({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        final Game currentGame = gameState.currentGame;
+
+        return currentGame.isRunning
+            ? const GameLayout()
+            : ParametersLayout(canResume: currentGame.canBeResumed);
+      },
+    );
+  }
+}
diff --git a/lib/ui/screens/settings_page.dart b/lib/ui/screens/page_settings.dart
similarity index 66%
rename from lib/ui/screens/settings_page.dart
rename to lib/ui/screens/page_settings.dart
index 7f2146872b3e8a613ea407c3d3517d6c540e026e..3953586f9b1665d6c75ffc1901678963605c26d4 100644
--- a/lib/ui/screens/settings_page.dart
+++ b/lib/ui/screens/page_settings.dart
@@ -1,10 +1,10 @@
 import 'package:flutter/material.dart';
 
-import 'package:minehunter/ui/widgets/header_app.dart';
-import 'package:minehunter/ui/widgets/settings/settings_form.dart';
+import 'package:minehunter/ui/helpers/app_titles.dart';
+import 'package:minehunter/ui/settings/settings_form.dart';
 
-class SettingsPage extends StatelessWidget {
-  const SettingsPage({super.key});
+class PageSettings extends StatelessWidget {
+  const PageSettings({super.key});
 
   @override
   Widget build(BuildContext context) {
@@ -16,7 +16,7 @@ class SettingsPage extends StatelessWidget {
         mainAxisSize: MainAxisSize.max,
         children: <Widget>[
           SizedBox(height: 8),
-          AppHeader(text: 'settings_title'),
+          AppTitle(text: 'settings_title'),
           SizedBox(height: 8),
           SettingsForm(),
         ],
diff --git a/lib/ui/widgets/settings/settings_form.dart b/lib/ui/settings/settings_form.dart
similarity index 96%
rename from lib/ui/widgets/settings/settings_form.dart
rename to lib/ui/settings/settings_form.dart
index 910c9507b2d9f4778e2e046faa35c93af55a6377..6806beafd9c70f66bbfbdc1ddffdb07bc7555e60 100644
--- a/lib/ui/widgets/settings/settings_form.dart
+++ b/lib/ui/settings/settings_form.dart
@@ -2,7 +2,7 @@ import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/material.dart';
 import 'package:unicons/unicons.dart';
 
-import 'package:minehunter/ui/widgets/settings/theme_card.dart';
+import 'package:minehunter/ui/settings/theme_card.dart';
 
 class SettingsForm extends StatefulWidget {
   const SettingsForm({super.key});
diff --git a/lib/ui/widgets/settings/theme_card.dart b/lib/ui/settings/theme_card.dart
similarity index 100%
rename from lib/ui/widgets/settings/theme_card.dart
rename to lib/ui/settings/theme_card.dart
diff --git a/lib/ui/skeleton.dart b/lib/ui/skeleton.dart
index 34421224675da8740c9671342bad6c11e08699cb..0b0885a06d673ce7c762d5ae9446769b5d075619 100644
--- a/lib/ui/skeleton.dart
+++ b/lib/ui/skeleton.dart
@@ -1,42 +1,34 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:provider/provider.dart';
 
 import 'package:minehunter/config/menu.dart';
-import 'package:minehunter/cubit/bottom_nav_cubit.dart';
-import 'package:minehunter/provider/data.dart';
-import 'package:minehunter/ui/widgets/app_bar.dart';
-import 'package:minehunter/ui/widgets/bottom_nav_bar.dart';
+import 'package:minehunter/cubit/nav_cubit.dart';
+import 'package:minehunter/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: BlocBuilder<BottomNavCubit, int>(
-        builder: (BuildContext context, int pageIndex) {
-          return Padding(
-            padding: const EdgeInsets.only(
-              top: 8,
-              left: 2,
-              right: 2,
-            ),
-            child: Menu.getPageWidget(pageIndex),
-          );
-        },
+      body: Material(
+        color: Theme.of(context).colorScheme.surface,
+        child: BlocBuilder<NavCubit, int>(
+          builder: (BuildContext context, int pageIndex) {
+            return Padding(
+              padding: const EdgeInsets.only(
+                top: 8,
+                left: 2,
+                right: 2,
+              ),
+              child: Menu.getPageWidget(pageIndex),
+            );
+          },
+        ),
       ),
       backgroundColor: Theme.of(context).colorScheme.surface,
-      bottomNavigationBar: const BottomNavBar(),
     );
   }
 }
diff --git a/lib/ui/widgets/actions/button_delete_saved_game.dart b/lib/ui/widgets/actions/button_delete_saved_game.dart
new file mode 100644
index 0000000000000000000000000000000000000000..8254982478b514fa7d7d9803f24f8d0b2a0d60d8
--- /dev/null
+++ b/lib/ui/widgets/actions/button_delete_saved_game.dart
@@ -0,0 +1,21 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:minehunter/cubit/game_cubit.dart';
+
+class DeleteSavedGameButton extends StatelessWidget {
+  const DeleteSavedGameButton({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return TextButton(
+      child: const Image(
+        image: AssetImage('assets/ui/button_delete_saved_game.png'),
+        fit: BoxFit.fill,
+      ),
+      onPressed: () {
+        BlocProvider.of<GameCubit>(context).deleteSavedGame();
+      },
+    );
+  }
+}
diff --git a/lib/ui/widgets/actions/button_game_quit.dart b/lib/ui/widgets/actions/button_game_quit.dart
new file mode 100644
index 0000000000000000000000000000000000000000..544470bc63c2ea0fc7a268d44460a9d6e0d5215e
--- /dev/null
+++ b/lib/ui/widgets/actions/button_game_quit.dart
@@ -0,0 +1,21 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:minehunter/cubit/game_cubit.dart';
+
+class QuitGameButton extends StatelessWidget {
+  const QuitGameButton({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return TextButton(
+      child: const Image(
+        image: AssetImage('assets/ui/button_back.png'),
+        fit: BoxFit.fill,
+      ),
+      onPressed: () {
+        BlocProvider.of<GameCubit>(context).quitGame();
+      },
+    );
+  }
+}
diff --git a/lib/ui/widgets/actions/button_game_start_new.dart b/lib/ui/widgets/actions/button_game_start_new.dart
new file mode 100644
index 0000000000000000000000000000000000000000..f2d6de12474b57d6603762af1601a209aba0a53e
--- /dev/null
+++ b/lib/ui/widgets/actions/button_game_start_new.dart
@@ -0,0 +1,34 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:minehunter/cubit/game_cubit.dart';
+import 'package:minehunter/cubit/settings_game_cubit.dart';
+import 'package:minehunter/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) {
+            return TextButton(
+              child: const Image(
+                image: AssetImage('assets/ui/button_start.png'),
+                fit: BoxFit.fill,
+              ),
+              onPressed: () {
+                BlocProvider.of<GameCubit>(context).startNewGame(
+                  gameSettings: gameSettingsState.settings,
+                  globalSettings: globalSettingsState.settings,
+                );
+              },
+            );
+          },
+        );
+      },
+    );
+  }
+}
diff --git a/lib/ui/widgets/actions/button_resume_saved_game.dart b/lib/ui/widgets/actions/button_resume_saved_game.dart
new file mode 100644
index 0000000000000000000000000000000000000000..803c9360b3ffea80e4e3ace196cbf97c2d26772d
--- /dev/null
+++ b/lib/ui/widgets/actions/button_resume_saved_game.dart
@@ -0,0 +1,21 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:minehunter/cubit/game_cubit.dart';
+
+class ResumeSavedGameButton extends StatelessWidget {
+  const ResumeSavedGameButton({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return TextButton(
+      child: const Image(
+        image: AssetImage('assets/ui/button_resume_game.png'),
+        fit: BoxFit.fill,
+      ),
+      onPressed: () {
+        BlocProvider.of<GameCubit>(context).resumeSavedGame();
+      },
+    );
+  }
+}
diff --git a/lib/ui/widgets/app_bar.dart b/lib/ui/widgets/app_bar.dart
deleted file mode 100644
index ae49c5c103d4e1a58e35cd3ffcb9024c28381478..0000000000000000000000000000000000000000
--- a/lib/ui/widgets/app_bar.dart
+++ /dev/null
@@ -1,35 +0,0 @@
-import 'package:flutter/material.dart';
-
-import 'package:minehunter/provider/data.dart';
-import 'package:minehunter/ui/widgets/header_app.dart';
-import 'package:minehunter/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(
-        onPressed: null,
-        onLongPress: () => GameUtils.quitGame(myProvider),
-        child: const Image(
-          image: AssetImage('assets/icons/button_back.png'),
-          fit: BoxFit.fill,
-        ),
-      ));
-    }
-
-    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 58d476c10fc3ca45e8409cb59a1448e2728f1c97..0000000000000000000000000000000000000000
--- a/lib/ui/widgets/bottom_nav_bar.dart
+++ /dev/null
@@ -1,36 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-
-import 'package:minehunter/config/menu.dart';
-import 'package:minehunter/cubit/bottom_nav_cubit.dart';
-
-class BottomNavBar extends StatelessWidget {
-  const BottomNavBar({super.key});
-
-  @override
-  Widget build(BuildContext context) {
-    return Card(
-      margin: const EdgeInsets.all(0),
-      elevation: 4,
-      shadowColor: Theme.of(context).colorScheme.shadow,
-      color: Theme.of(context).colorScheme.surfaceContainerHighest,
-      shape: const ContinuousRectangleBorder(),
-      child: BlocBuilder<BottomNavCubit, int>(
-        builder: (BuildContext context, int state) {
-          return BottomNavigationBar(
-            currentIndex: state,
-            onTap: (int index) {
-              context.read<BottomNavCubit>().updateIndex(index);
-            },
-            type: BottomNavigationBarType.fixed,
-            elevation: 0,
-            backgroundColor: Colors.transparent,
-            selectedItemColor: Theme.of(context).colorScheme.primary,
-            unselectedItemColor: Theme.of(context).textTheme.bodySmall!.color,
-            items: Menu.getMenuItems(),
-          );
-        },
-      ),
-    );
-  }
-}
diff --git a/lib/ui/widgets/game/cell.dart b/lib/ui/widgets/game/cell.dart
new file mode 100644
index 0000000000000000000000000000000000000000..89279eeb5d3d4389bb9cff998eb5c36f4517d1b9
--- /dev/null
+++ b/lib/ui/widgets/game/cell.dart
@@ -0,0 +1,176 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:minehunter/cubit/game_cubit.dart';
+import 'package:minehunter/models/game/cell.dart';
+import 'package:minehunter/models/game/game.dart';
+import 'package:minehunter/utils/board_animate.dart';
+
+class CellWidget extends StatelessWidget {
+  const CellWidget({
+    super.key,
+    required this.cell,
+    required this.row,
+    required this.col,
+  });
+
+  final Cell cell;
+  final int row;
+  final int col;
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        final Game currentGame = gameState.currentGame;
+        final GameCubit gameCubit = BlocProvider.of<GameCubit>(context);
+
+        String imageAsset = getImageAssetName(
+          currentGame: currentGame,
+        );
+
+        return Container(
+          decoration: BoxDecoration(
+            color: getBackgroundColor(currentGame),
+            border: getCellBorders(
+              currentGame: currentGame,
+              row: row,
+              col: col,
+            ),
+          ),
+          child: GestureDetector(
+            child: AnimatedSwitcher(
+              duration: const Duration(milliseconds: 100),
+              transitionBuilder: (Widget child, Animation<double> animation) {
+                return ScaleTransition(scale: animation, child: child);
+              },
+              child: Image(
+                image: AssetImage(imageAsset),
+                fit: BoxFit.fill,
+                key: ValueKey<int>(imageAsset.hashCode),
+              ),
+            ),
+            onTap: () {
+              // Set mines on board after first player try
+              if (!currentGame.isBoardMined) {
+                gameCubit.addMines(forbiddenRow: row, forbiddenCol: col);
+              }
+
+              if (!(currentGame.gameWin || currentGame.gameFail)) {
+                if (currentGame.reportMode) {
+                  gameCubit.reportCell(
+                    row: row,
+                    col: col,
+                  );
+                } else {
+                  gameCubit.walkOnCell(
+                    row: row,
+                    col: col,
+                  );
+                }
+                if (gameCubit.checkGameIsFinished()) {
+                  gameCubit.updateReportMode(false);
+                  BoardAnimate.startAnimation(
+                    gameCubit: gameCubit,
+                    currentGame: currentGame,
+                    animationType: currentGame.gameWin ? 'win' : 'fail',
+                  );
+                }
+              }
+            },
+          ),
+        );
+      },
+    );
+  }
+
+  /*
+  * Compute image asset name, from skin and cell value/state
+  */
+  String getImageAssetName({
+    required Game currentGame,
+  }) {
+    final String skin = currentGame.globalSettings.skin;
+
+    String imageAsset = 'assets/skins/${skin}_tile_unknown.png';
+
+    bool showSolution = currentGame.gameWin || currentGame.gameFail;
+    if (!showSolution) {
+      // Running game
+      if (cell.isExplored) {
+        if (cell.isMined) {
+          // Boom
+          imageAsset = 'assets/skins/${skin}_tile_mine.png';
+        } else {
+          // Show mines count around
+          imageAsset = 'assets/skins/${skin}_tile_${cell.minesCountAround}.png';
+        }
+      } else {
+        if (cell.isMarked) {
+          // Danger!
+          imageAsset = 'assets/skins/${skin}_tile_flag.png';
+        }
+      }
+    } else {
+      // Finished game
+      if (cell.isMined) {
+        if (cell.isExploded) {
+          // Mine exploded
+          imageAsset = 'assets/skins/${skin}_tile_mine.png';
+        } else {
+          // Mine not found
+          imageAsset = 'assets/skins/${skin}_tile_mine_not_found.png';
+        }
+      } else {
+        // Show all mines counts
+        imageAsset = 'assets/skins/${skin}_tile_${cell.minesCountAround}.png';
+      }
+    }
+
+    return imageAsset;
+  }
+
+  // Compute cell background color, from cell state
+  Color getBackgroundColor(currentGame) {
+    if (currentGame.gameWin) {
+      return cell.isAnimated ? Colors.green.shade400 : Colors.green.shade500;
+    }
+    if (currentGame.gameFail) {
+      return cell.isAnimated ? Colors.pink.shade200 : Colors.pink.shade400;
+    }
+
+    return cell.isAnimated ? Colors.white : Colors.grey.shade200;
+  }
+
+  // Compute cell borders, from board size and cell state
+  Border getCellBorders({
+    required Game currentGame,
+    required int row,
+    required int col,
+  }) {
+    Color cellBorderColor = Colors.grey.shade500;
+    double cellBorderWidth = 4;
+
+    // Reduce cell border width on big boards
+    int boardSize = currentGame.sizeHorizontal;
+    if (boardSize > 8) {
+      cellBorderWidth = 2;
+      if (boardSize > 10) {
+        cellBorderWidth = 1;
+      }
+    }
+
+    if (currentGame.gameWin) {
+      cellBorderColor = Colors.green.shade700;
+    } else if (currentGame.gameFail) {
+      cellBorderColor = Colors.pink.shade300;
+    }
+
+    Border borders = Border.all(
+      color: cellBorderColor,
+      width: cellBorderWidth,
+    );
+
+    return borders;
+  }
+}
diff --git a/lib/ui/widgets/game/game_board.dart b/lib/ui/widgets/game/game_board.dart
new file mode 100644
index 0000000000000000000000000000000000000000..52a7c90764c3ff74a09212ce4918c7f2ce93738d
--- /dev/null
+++ b/lib/ui/widgets/game/game_board.dart
@@ -0,0 +1,58 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:minehunter/cubit/game_cubit.dart';
+import 'package:minehunter/models/game/game.dart';
+import 'package:minehunter/models/types.dart';
+import 'package:minehunter/ui/widgets/game/cell.dart';
+
+class GameBoardWidget extends StatelessWidget {
+  const GameBoardWidget({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        final Game currentGame = gameState.currentGame;
+
+        final Board board = currentGame.board;
+        final Color borderColor = currentGame.reportMode ? Colors.blue : Colors.black;
+
+        return Container(
+          margin: const EdgeInsets.all(2),
+          padding: const EdgeInsets.all(2),
+          child: Column(
+            children: [
+              Container(
+                decoration: BoxDecoration(
+                  color: borderColor,
+                  borderRadius: BorderRadius.circular(2),
+                  border: Border.all(
+                    color: borderColor,
+                    width: 2,
+                  ),
+                ),
+                child: Table(
+                  defaultColumnWidth: const IntrinsicColumnWidth(),
+                  children: [
+                    for (int row = 0; row < currentGame.sizeVertical; row++)
+                      TableRow(
+                        children: [
+                          for (int col = 0; col < currentGame.sizeHorizontal; col++)
+                            Column(
+                              children: [
+                                CellWidget(cell: board[row][col], row: row, col: col)
+                              ],
+                            ),
+                        ],
+                      ),
+                  ],
+                ),
+              ),
+            ],
+          ),
+        );
+      },
+    );
+  }
+}
diff --git a/lib/ui/widgets/game/indicator_top.dart b/lib/ui/widgets/game/indicator_top.dart
deleted file mode 100644
index bf9ea9af42c4b24332880420b92b73d0db0a97dd..0000000000000000000000000000000000000000
--- a/lib/ui/widgets/game/indicator_top.dart
+++ /dev/null
@@ -1,64 +0,0 @@
-import 'package:flutter/material.dart';
-
-import 'package:minehunter/provider/data.dart';
-import 'package:minehunter/utils/board_utils.dart';
-
-class TopIndicator extends StatelessWidget {
-  const TopIndicator({super.key, required this.myProvider});
-
-  final Data myProvider;
-
-  @override
-  Widget build(BuildContext context) {
-    final int flaggedCellsCount = BoardUtils.countFlaggedCells(myProvider.board);
-    final int minesCount = myProvider.minesCount;
-    const double blockSize = 40;
-
-    final Image flagIconBlock = Image(
-      image: AssetImage('assets/skins/${myProvider.parameterSkin}_tile_flag.png'),
-      fit: BoxFit.fill,
-      height: blockSize,
-      width: blockSize,
-    );
-    final Image mineIconBlock = Image(
-      image: AssetImage('assets/skins/${myProvider.parameterSkin}_tile_mine.png'),
-      fit: BoxFit.fill,
-      height: blockSize,
-      width: blockSize,
-    );
-    final Text markedMinesCountBlock = Text(
-      flaggedCellsCount.toString(),
-      style: TextStyle(
-        fontSize: blockSize,
-        fontWeight: FontWeight.bold,
-        color: Theme.of(context).colorScheme.primary,
-      ),
-    );
-    final Text placedMinesCountBlock = Text(
-      minesCount.toString(),
-      style: TextStyle(
-        fontSize: blockSize,
-        fontWeight: FontWeight.bold,
-        color: Theme.of(context).colorScheme.primary,
-      ),
-    );
-
-    return Column(
-      mainAxisAlignment: MainAxisAlignment.center,
-      crossAxisAlignment: CrossAxisAlignment.center,
-      children: [
-        Row(
-          mainAxisAlignment: MainAxisAlignment.center,
-          crossAxisAlignment: CrossAxisAlignment.center,
-          children: [
-            markedMinesCountBlock,
-            flagIconBlock,
-            const SizedBox(width: blockSize * 2),
-            mineIconBlock,
-            placedMinesCountBlock,
-          ],
-        )
-      ],
-    );
-  }
-}
diff --git a/lib/ui/widgets/game/message_game_end.dart b/lib/ui/widgets/game/message_game_end.dart
deleted file mode 100644
index 9eff7f183a81f104fd60228649a1a8745c525a2a..0000000000000000000000000000000000000000
--- a/lib/ui/widgets/game/message_game_end.dart
+++ /dev/null
@@ -1,49 +0,0 @@
-import 'package:flutter/material.dart';
-
-import 'package:minehunter/provider/data.dart';
-import 'package:minehunter/ui/widgets/home/button_game_restart.dart';
-
-class EndGameMessage extends StatelessWidget {
-  const EndGameMessage({super.key, required this.myProvider});
-
-  final Data myProvider;
-
-  @override
-  Widget build(BuildContext context) {
-    final Image decorationImage = Image(
-      image: AssetImage(myProvider.gameWin
-          ? 'assets/icons/game_win.png'
-          : myProvider.gameFail
-              ? 'assets/icons/game_fail.png'
-              : ''),
-      fit: BoxFit.fill,
-    );
-
-    return Container(
-      margin: const EdgeInsets.all(2),
-      padding: const EdgeInsets.all(2),
-      child: Table(
-        defaultColumnWidth: const IntrinsicColumnWidth(),
-        children: [
-          TableRow(
-            children: [
-              Column(
-                children: [decorationImage],
-              ),
-              Column(
-                children: [
-                  myProvider.animationInProgress
-                      ? decorationImage
-                      : RestartGameButton(myProvider: myProvider)
-                ],
-              ),
-              Column(
-                children: [decorationImage],
-              ),
-            ],
-          ),
-        ],
-      ),
-    );
-  }
-}
diff --git a/lib/ui/widgets/game/mode_button_toggle.dart b/lib/ui/widgets/game/mode_button_toggle.dart
index 7f6f7aae3c52a5725871fc8839a07e5c03f4582d..492e1b36806c9e4537171e951d8a2a2f3459462d 100644
--- a/lib/ui/widgets/game/mode_button_toggle.dart
+++ b/lib/ui/widgets/game/mode_button_toggle.dart
@@ -1,23 +1,31 @@
 import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
 
-import 'package:minehunter/provider/data.dart';
+import 'package:minehunter/cubit/game_cubit.dart';
+import 'package:minehunter/models/game/game.dart';
 
 class ToggleGameModeButton extends StatelessWidget {
-  const ToggleGameModeButton({super.key, required this.myProvider});
-
-  final Data myProvider;
+  const ToggleGameModeButton({super.key});
 
   @override
   Widget build(BuildContext context) {
-    final String reportModeSuffix = myProvider.reportMode ? 'on' : 'off';
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        final Game currentGame = gameState.currentGame;
+
+        final String skin = currentGame.globalSettings.skin;
+        final String reportModeSuffix = currentGame.reportMode ? 'on' : 'off';
 
-    return TextButton(
-      child: Image(
-        image: AssetImage(
-            'assets/skins/${myProvider.parameterSkin}_button_mark_mine_$reportModeSuffix.png'),
-        fit: BoxFit.fill,
-      ),
-      onPressed: () => myProvider.updateReportMode(!myProvider.reportMode),
+        return TextButton(
+          child: Image(
+            image: AssetImage('assets/skins/${skin}_button_mark_mine_$reportModeSuffix.png'),
+            fit: BoxFit.fill,
+          ),
+          onPressed: () {
+            BlocProvider.of<GameCubit>(context).updateReportMode(!currentGame.reportMode);
+          },
+        );
+      },
     );
   }
 }
diff --git a/lib/ui/widgets/game/mode_indicator_report.dart b/lib/ui/widgets/game/mode_indicator_report.dart
index 6387149c844be9c5e056aa06ad143ca820082866..29af1fdd62deeca2497755bb5ce172b9bd147536 100644
--- a/lib/ui/widgets/game/mode_indicator_report.dart
+++ b/lib/ui/widgets/game/mode_indicator_report.dart
@@ -1,23 +1,31 @@
 import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
 
-import 'package:minehunter/provider/data.dart';
+import 'package:minehunter/cubit/game_cubit.dart';
+import 'package:minehunter/models/game/game.dart';
 
 class GameModeIndicatorReport extends StatelessWidget {
-  const GameModeIndicatorReport({super.key, required this.myProvider});
-
-  final Data myProvider;
+  const GameModeIndicatorReport({super.key});
 
   @override
   Widget build(BuildContext context) {
-    final String reportModeSuffix = myProvider.reportMode ? 'on' : 'off';
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        final Game currentGame = gameState.currentGame;
+
+        final String skin = currentGame.globalSettings.skin;
+        final String reportModeSuffix = currentGame.reportMode ? 'on' : 'off';
 
-    return TextButton(
-      child: Image(
-        image: AssetImage(
-            'assets/skins/${myProvider.parameterSkin}_indicator_report_$reportModeSuffix.png'),
-        fit: BoxFit.fill,
-      ),
-      onPressed: () => myProvider.updateReportMode(true),
+        return TextButton(
+          child: Image(
+            image: AssetImage('assets/skins/${skin}_indicator_report_$reportModeSuffix.png'),
+            fit: BoxFit.fill,
+          ),
+          onPressed: () {
+            BlocProvider.of<GameCubit>(context).updateReportMode(true);
+          },
+        );
+      },
     );
   }
 }
diff --git a/lib/ui/widgets/game/mode_indicator_walk.dart b/lib/ui/widgets/game/mode_indicator_walk.dart
index be4cef83e9adce5e990bbc0106f8267b7c22d1ed..d374d0b48f0f8e9f05154f9a1b7364780cdd8677 100644
--- a/lib/ui/widgets/game/mode_indicator_walk.dart
+++ b/lib/ui/widgets/game/mode_indicator_walk.dart
@@ -1,23 +1,31 @@
 import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
 
-import 'package:minehunter/provider/data.dart';
+import 'package:minehunter/cubit/game_cubit.dart';
+import 'package:minehunter/models/game/game.dart';
 
 class GameModeIndicatorWalk extends StatelessWidget {
-  const GameModeIndicatorWalk({super.key, required this.myProvider});
-
-  final Data myProvider;
+  const GameModeIndicatorWalk({super.key});
 
   @override
   Widget build(BuildContext context) {
-    final String reportModeSuffix = myProvider.reportMode ? 'off' : 'on';
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        final Game currentGame = gameState.currentGame;
+
+        final String skin = currentGame.globalSettings.skin;
+        final String reportModeSuffix = currentGame.reportMode ? 'off' : 'on';
 
-    return TextButton(
-      child: Image(
-        image: AssetImage(
-            'assets/skins/${myProvider.parameterSkin}_indicator_walk_$reportModeSuffix.png'),
-        fit: BoxFit.fill,
-      ),
-      onPressed: () => myProvider.updateReportMode(false),
+        return TextButton(
+          child: Image(
+            image: AssetImage('assets/skins/${skin}_indicator_walk_$reportModeSuffix.png'),
+            fit: BoxFit.fill,
+          ),
+          onPressed: () {
+            BlocProvider.of<GameCubit>(context).updateReportMode(false);
+          },
+        );
+      },
     );
   }
 }
diff --git a/lib/ui/widgets/game/mode_toggle.dart b/lib/ui/widgets/game/mode_toggle.dart
index 6a438d6cf16a4791366f4cba64574ea2f73287d6..38b2cde9db83e7c30576d5124bdfdff8163334d1 100644
--- a/lib/ui/widgets/game/mode_toggle.dart
+++ b/lib/ui/widgets/game/mode_toggle.dart
@@ -1,35 +1,43 @@
 import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
 
-import 'package:minehunter/provider/data.dart';
+import 'package:minehunter/cubit/game_cubit.dart';
+import 'package:minehunter/models/game/game.dart';
 import 'package:minehunter/ui/widgets/game/mode_button_toggle.dart';
 import 'package:minehunter/ui/widgets/game/mode_indicator_report.dart';
 import 'package:minehunter/ui/widgets/game/mode_indicator_walk.dart';
 
 class ToggleGameMode extends StatelessWidget {
-  const ToggleGameMode({super.key, required this.myProvider});
-
-  final Data myProvider;
+  const ToggleGameMode({super.key});
 
   @override
   Widget build(BuildContext context) {
-    final Image paddingBlock = Image(
-      image: AssetImage('assets/skins/${myProvider.parameterSkin}_empty.png'),
-      fit: BoxFit.fill,
-    );
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        final Game currentGame = gameState.currentGame;
+
+        final String skin = currentGame.globalSettings.skin;
+
+        final Image paddingBlock = Image(
+          image: AssetImage('assets/skins/${skin}_empty.png'),
+          fit: BoxFit.fill,
+        );
 
-    return Table(
-      defaultColumnWidth: const IntrinsicColumnWidth(),
-      children: [
-        TableRow(
+        return Table(
+          defaultColumnWidth: const IntrinsicColumnWidth(),
           children: [
-            TableCell(child: paddingBlock),
-            TableCell(child: GameModeIndicatorWalk(myProvider: myProvider)),
-            TableCell(child: ToggleGameModeButton(myProvider: myProvider)),
-            TableCell(child: GameModeIndicatorReport(myProvider: myProvider)),
-            TableCell(child: paddingBlock),
+            TableRow(
+              children: [
+                TableCell(child: paddingBlock),
+                const TableCell(child: GameModeIndicatorWalk()),
+                const TableCell(child: ToggleGameModeButton()),
+                const TableCell(child: GameModeIndicatorReport()),
+                TableCell(child: paddingBlock),
+              ],
+            ),
           ],
-        ),
-      ],
+        );
+      },
     );
   }
 }
diff --git a/lib/ui/widgets/global_app_bar.dart b/lib/ui/widgets/global_app_bar.dart
new file mode 100644
index 0000000000000000000000000000000000000000..94b7b64b419e85b61c8b69b8bce8aab5346e4bdf
--- /dev/null
+++ b/lib/ui/widgets/global_app_bar.dart
@@ -0,0 +1,83 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:minehunter/config/menu.dart';
+import 'package:minehunter/cubit/game_cubit.dart';
+import 'package:minehunter/cubit/nav_cubit.dart';
+import 'package:minehunter/models/game/game.dart';
+import 'package:minehunter/ui/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 Game currentGame = gameState.currentGame;
+
+            final List<Widget> menuActions = [];
+
+            if (currentGame.isRunning && !currentGame.isFinished) {
+              menuActions.add(TextButton(
+                child: const Image(
+                  image: AssetImage('assets/ui/button_back.png'),
+                  fit: BoxFit.fill,
+                ),
+                onPressed: () {},
+                onLongPress: () {
+                  BlocProvider.of<GameCubit>(context).quitGame();
+                },
+              ));
+            } else {
+              if (pageIndex == Menu.indexGame) {
+                // go to Settings page
+                menuActions.add(ElevatedButton(
+                  onPressed: () {
+                    context.read<NavCubit>().goToSettingsPage();
+                  },
+                  style: ElevatedButton.styleFrom(
+                    shape: const CircleBorder(),
+                  ),
+                  child: Menu.menuItemSettings.icon,
+                ));
+
+                // go to About page
+                menuActions.add(ElevatedButton(
+                  onPressed: () {
+                    context.read<NavCubit>().goToAboutPage();
+                  },
+                  style: ElevatedButton.styleFrom(
+                    shape: const CircleBorder(),
+                  ),
+                  child: Menu.menuItemAbout.icon,
+                ));
+              } else {
+                // back to Home page
+                menuActions.add(ElevatedButton(
+                  onPressed: () {
+                    context.read<NavCubit>().goToGamePage();
+                  },
+                  style: ElevatedButton.styleFrom(
+                    shape: const CircleBorder(),
+                  ),
+                  child: Menu.menuItemGame.icon,
+                ));
+              }
+            }
+
+            return AppBar(
+              title: const AppHeader(text: 'app_name'),
+              actions: menuActions,
+            );
+          },
+        );
+      },
+    );
+  }
+
+  @override
+  Size get preferredSize => const Size.fromHeight(50);
+}
diff --git a/lib/ui/widgets/header_app.dart b/lib/ui/widgets/header_app.dart
deleted file mode 100644
index bf54b77375fbd0260f876f2885d0572b71715383..0000000000000000000000000000000000000000
--- a/lib/ui/widgets/header_app.dart
+++ /dev/null
@@ -1,23 +0,0 @@
-import 'package:easy_localization/easy_localization.dart';
-import 'package:flutter/material.dart';
-
-class AppHeader extends StatelessWidget {
-  const AppHeader({super.key, required this.text});
-
-  final String text;
-
-  @override
-  Widget build(BuildContext context) {
-    return Row(
-      mainAxisAlignment: MainAxisAlignment.start,
-      crossAxisAlignment: CrossAxisAlignment.start,
-      children: [
-        Text(
-          tr(text),
-          textAlign: TextAlign.start,
-          style: Theme.of(context).textTheme.headlineMedium!.apply(fontWeightDelta: 2),
-        ),
-      ],
-    );
-  }
-}
diff --git a/lib/ui/widgets/home/button_game_restart.dart b/lib/ui/widgets/home/button_game_restart.dart
deleted file mode 100644
index 2fecb871a622f85764e40a512fbed7948da3a53a..0000000000000000000000000000000000000000
--- a/lib/ui/widgets/home/button_game_restart.dart
+++ /dev/null
@@ -1,21 +0,0 @@
-import 'package:flutter/material.dart';
-
-import 'package:minehunter/provider/data.dart';
-import 'package:minehunter/utils/game_utils.dart';
-
-class RestartGameButton extends StatelessWidget {
-  const RestartGameButton({super.key, required this.myProvider});
-
-  final Data myProvider;
-
-  @override
-  Widget build(BuildContext context) {
-    return TextButton(
-      child: const Image(
-        image: AssetImage('assets/icons/button_back.png'),
-        fit: BoxFit.fill,
-      ),
-      onPressed: () => GameUtils.quitGame(myProvider),
-    );
-  }
-}
diff --git a/lib/ui/widgets/home/button_game_resume.dart b/lib/ui/widgets/home/button_game_resume.dart
deleted file mode 100644
index 2a1cc71f359762fe09962f62b787912cb7ddf351..0000000000000000000000000000000000000000
--- a/lib/ui/widgets/home/button_game_resume.dart
+++ /dev/null
@@ -1,42 +0,0 @@
-import 'package:flutter/material.dart';
-
-import 'package:minehunter/ui/layout/parameters.dart';
-import 'package:minehunter/utils/game_utils.dart';
-
-class ResumeGameButton extends Parameters {
-  const ResumeGameButton({super.key, required super.myProvider});
-
-  @override
-  Widget build(BuildContext context) {
-    return Container(
-      margin: const EdgeInsets.all(Parameters.blockMargin),
-      padding: const EdgeInsets.all(Parameters.blockPadding),
-      child: Table(
-        defaultColumnWidth: const IntrinsicColumnWidth(),
-        children: [
-          TableRow(
-            children: [
-              Column(
-                children: [
-                  TextButton(
-                    child: Parameters.buildImageContainerWidget('button_delete_saved_game'),
-                    onPressed: () => GameUtils.deleteSavedGame(myProvider),
-                  ),
-                ],
-              ),
-              Column(
-                children: [
-                  TextButton(
-                    child: Parameters.buildImageContainerWidget('button_resume_game'),
-                    onPressed: () => GameUtils.resumeSavedGame(myProvider),
-                  ),
-                ],
-              ),
-              Parameters.buildDecorationImageWidget(),
-            ],
-          ),
-        ],
-      ),
-    );
-  }
-}
diff --git a/lib/ui/widgets/home/button_game_start_new.dart b/lib/ui/widgets/home/button_game_start_new.dart
deleted file mode 100644
index 1d58c490152db767a5a0a64c5a5ce5655f2ef6ec..0000000000000000000000000000000000000000
--- a/lib/ui/widgets/home/button_game_start_new.dart
+++ /dev/null
@@ -1,38 +0,0 @@
-import 'package:flutter/material.dart';
-
-import 'package:minehunter/provider/data.dart';
-import 'package:minehunter/ui/layout/parameters.dart';
-import 'package:minehunter/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/indicators/indicator_top.dart b/lib/ui/widgets/indicators/indicator_top.dart
new file mode 100644
index 0000000000000000000000000000000000000000..3f4cdfda0ecc6dc40aaa495c80ca29ac3df0cc28
--- /dev/null
+++ b/lib/ui/widgets/indicators/indicator_top.dart
@@ -0,0 +1,71 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:minehunter/cubit/game_cubit.dart';
+import 'package:minehunter/models/game/game.dart';
+
+class TopIndicator extends StatelessWidget {
+  const TopIndicator({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        final Game currentGame = gameState.currentGame;
+
+        final String skin = currentGame.globalSettings.skin;
+
+        final int flaggedCellsCount = currentGame.countFlaggedCells();
+        final int minesCount = currentGame.minesCount;
+        const double blockSize = 40;
+
+        final Image flagIconBlock = Image(
+          image: AssetImage('assets/skins/${skin}_tile_flag.png'),
+          fit: BoxFit.fill,
+          height: blockSize,
+          width: blockSize,
+        );
+        final Image mineIconBlock = Image(
+          image: AssetImage('assets/skins/${skin}_tile_mine.png'),
+          fit: BoxFit.fill,
+          height: blockSize,
+          width: blockSize,
+        );
+        final Text markedMinesCountBlock = Text(
+          flaggedCellsCount.toString(),
+          style: TextStyle(
+            fontSize: blockSize,
+            fontWeight: FontWeight.bold,
+            color: Theme.of(context).colorScheme.primary,
+          ),
+        );
+        final Text placedMinesCountBlock = Text(
+          minesCount.toString(),
+          style: TextStyle(
+            fontSize: blockSize,
+            fontWeight: FontWeight.bold,
+            color: Theme.of(context).colorScheme.primary,
+          ),
+        );
+
+        return Column(
+          mainAxisAlignment: MainAxisAlignment.center,
+          crossAxisAlignment: CrossAxisAlignment.center,
+          children: [
+            Row(
+              mainAxisAlignment: MainAxisAlignment.center,
+              crossAxisAlignment: CrossAxisAlignment.center,
+              children: [
+                markedMinesCountBlock,
+                flagIconBlock,
+                const SizedBox(width: blockSize * 2),
+                mineIconBlock,
+                placedMinesCountBlock,
+              ],
+            )
+          ],
+        );
+      },
+    );
+  }
+}
diff --git a/lib/utils/board_animate.dart b/lib/utils/board_animate.dart
index 45e1352a3469ffe2331713491cb2291c53f3dbd4..69a3fa456b07de17807332a8e589316ff92bf0ec 100644
--- a/lib/utils/board_animate.dart
+++ b/lib/utils/board_animate.dart
@@ -1,16 +1,20 @@
 import 'dart:async';
 import 'dart:math';
 
-import 'package:minehunter/provider/data.dart';
+import 'package:minehunter/cubit/game_cubit.dart';
+import 'package:minehunter/models/game/game.dart';
+import 'package:minehunter/models/types.dart';
 
 class BoardAnimate {
   // Start game animation: blinking tiles
-  static AnimatedBoardSequence createStartGameAnimationPatterns(Data myProvider) {
+  static AnimatedBoardSequence createStartGameAnimationPatterns({
+    required Game currentGame,
+  }) {
     final AnimatedBoardSequence patterns = [];
 
     const int patternsCount = 4;
-    final int sizeHorizontal = myProvider.sizeHorizontal;
-    final int sizeVertical = myProvider.sizeVertical;
+    final int sizeHorizontal = currentGame.sizeHorizontal;
+    final int sizeVertical = currentGame.sizeVertical;
 
     for (int patternIndex = 0; patternIndex < patternsCount; patternIndex++) {
       final AnimatedBoard pattern = [];
@@ -28,16 +32,18 @@ class BoardAnimate {
   }
 
   // Failed game animation: explosions blowing from exploded mines
-  static AnimatedBoardSequence createExplosionAnimationPatterns(Data myProvider) {
+  static AnimatedBoardSequence createExplosionAnimationPatterns({
+    required Game currentGame,
+  }) {
     final AnimatedBoardSequence patterns = [];
 
-    final int sizeHorizontal = myProvider.sizeHorizontal;
-    final int sizeVertical = myProvider.sizeVertical;
+    final int sizeHorizontal = currentGame.sizeHorizontal;
+    final int sizeVertical = currentGame.sizeVertical;
 
     final List<List<int>> explodedMines = [];
     for (int row = 0; row < sizeVertical; row++) {
       for (int col = 0; col < sizeHorizontal; col++) {
-        if (myProvider.board[row][col].isExploded) {
+        if (currentGame.board[row][col].isExploded) {
           explodedMines.add([row, col]);
         }
       }
@@ -70,12 +76,14 @@ class BoardAnimate {
   }
 
   // Win game animation: rotating rays from center
-  static AnimatedBoardSequence createWinGameAnimationPatterns(Data myProvider) {
+  static AnimatedBoardSequence createWinGameAnimationPatterns({
+    required Game currentGame,
+  }) {
     final AnimatedBoardSequence patterns = [];
 
     const int patternsCount = 20;
-    final int sizeHorizontal = myProvider.sizeHorizontal;
-    final int sizeVertical = myProvider.sizeVertical;
+    final int sizeHorizontal = currentGame.sizeHorizontal;
+    final int sizeVertical = currentGame.sizeVertical;
 
     for (int patternIndex = 0; patternIndex < patternsCount; patternIndex++) {
       AnimatedBoard pattern = [];
@@ -94,12 +102,14 @@ class BoardAnimate {
   }
 
   // Default multi-purpose animation: sliding stripes, from top left to right bottom
-  static AnimatedBoardSequence createDefaultAnimationPatterns(Data myProvider) {
+  static AnimatedBoardSequence createDefaultAnimationPatterns({
+    required Game currentGame,
+  }) {
     final AnimatedBoardSequence patterns = [];
 
     const int patternsCount = 16;
-    final int sizeHorizontal = myProvider.sizeHorizontal;
-    final int sizeVertical = myProvider.sizeVertical;
+    final int sizeHorizontal = currentGame.sizeHorizontal;
+    final int sizeVertical = currentGame.sizeVertical;
 
     for (int patternIndex = 0; patternIndex < patternsCount; patternIndex++) {
       final AnimatedBoard pattern = [];
@@ -116,26 +126,38 @@ class BoardAnimate {
     return patterns;
   }
 
-  static void startAnimation(Data myProvider, String animationType) {
+  static void startAnimation({
+    required GameCubit gameCubit,
+    required Game currentGame,
+    required String animationType,
+  }) {
     AnimatedBoardSequence patterns = [];
 
     switch (animationType) {
       case 'start':
-        patterns = createStartGameAnimationPatterns(myProvider);
+        patterns = createStartGameAnimationPatterns(
+          currentGame: currentGame,
+        );
         break;
       case 'win':
-        patterns = createWinGameAnimationPatterns(myProvider);
+        patterns = createWinGameAnimationPatterns(
+          currentGame: currentGame,
+        );
         break;
       case 'fail':
-        patterns = createExplosionAnimationPatterns(myProvider);
+        patterns = createExplosionAnimationPatterns(
+          currentGame: currentGame,
+        );
         break;
       default:
-        patterns = createDefaultAnimationPatterns(myProvider);
+        patterns = createDefaultAnimationPatterns(
+          currentGame: currentGame,
+        );
     }
 
     int patternIndex = patterns.length;
 
-    myProvider.updateAnimationInProgress(true);
+    gameCubit.updateAnimationInProgress(true);
 
     const interval = Duration(milliseconds: 200);
     Timer.periodic(
@@ -143,11 +165,11 @@ class BoardAnimate {
       (Timer timer) {
         if (patternIndex == 0) {
           timer.cancel();
-          myProvider.resetAnimatedBackground();
-          myProvider.updateAnimationInProgress(false);
+          gameCubit.resetAnimatedBackground();
+          gameCubit.updateAnimationInProgress(false);
         } else {
           patternIndex--;
-          myProvider.setAnimatedBackground(patterns[patternIndex]);
+          gameCubit.setAnimatedBackground(patterns[patternIndex]);
         }
       },
     );
diff --git a/lib/utils/board_utils.dart b/lib/utils/board_utils.dart
deleted file mode 100644
index 695d5bf72c84b1a53c86b7ea1785e5da9e520e1d..0000000000000000000000000000000000000000
--- a/lib/utils/board_utils.dart
+++ /dev/null
@@ -1,280 +0,0 @@
-import 'dart:math';
-
-import 'package:minehunter/entities/cell.dart';
-import 'package:minehunter/provider/data.dart';
-import 'package:minehunter/utils/tools.dart';
-
-class BoardUtils {
-  static printGrid(List cells) {
-    const String isMined = 'X';
-    const String isSafe = '.';
-
-    const String mineFound = '#';
-    const String wrongMarkedCell = '0';
-    const String exploredSafeCell = '.';
-    const String unkownState = ' ';
-
-    printlog('');
-    String line = '--';
-    for (int i = 0; i < cells[0].length; i++) {
-      line += '-';
-    }
-    printlog('$line  $line');
-    for (int rowIndex = 0; rowIndex < cells.length; rowIndex++) {
-      String currentLine = '';
-      String solvedLine = '';
-      for (int colIndex = 0; colIndex < cells[rowIndex].length; colIndex++) {
-        solvedLine += cells[rowIndex][colIndex].isMined ? isMined : isSafe;
-
-        String cellString = unkownState;
-        if (cells[rowIndex][colIndex].isExplored) {
-          cellString = exploredSafeCell;
-        }
-        if (cells[rowIndex][colIndex].isMarked) {
-          if (cells[rowIndex][colIndex].isMined) {
-            cellString = mineFound;
-          } else {
-            cellString = wrongMarkedCell;
-          }
-        }
-        currentLine += cellString;
-      }
-      printlog('|$currentLine|  |$solvedLine|');
-    }
-    printlog('$line  $line');
-    printlog('');
-  }
-
-  static Board createEmptyBoard(int sizeHorizontal, int sizeVertical) {
-    final Board board = [];
-    for (int rowIndex = 0; rowIndex < sizeVertical; rowIndex++) {
-      final List<Cell> row = [];
-      for (int colIndex = 0; colIndex < sizeHorizontal; colIndex++) {
-        row.add(Cell(false));
-      }
-      board.add(row);
-    }
-
-    return board;
-  }
-
-  static int getMinesCount(int sizeHorizontal, int sizeVertical, String level) {
-    int minesCountRatio = 0;
-    switch (level) {
-      case 'easy':
-        {
-          minesCountRatio = 5;
-        }
-        break;
-      case 'medium':
-        {
-          minesCountRatio = 10;
-        }
-        break;
-      case 'hard':
-        {
-          minesCountRatio = 15;
-        }
-        break;
-      case 'nightmare':
-        {
-          minesCountRatio = 20;
-        }
-        break;
-    }
-
-    final int minesCount = ((sizeHorizontal * sizeVertical) * minesCountRatio / 100).round();
-
-    printlog('Mines count: $minesCount');
-
-    return minesCount;
-  }
-
-  static void createInitialEmptyBoard(Data myProvider) {
-    myProvider.updateIsBoardMined(false);
-    myProvider
-        .updateBoard(createEmptyBoard(myProvider.sizeHorizontal, myProvider.sizeVertical));
-  }
-
-  static Board createBoard(Data myProvider, int forbiddenRow, int forbiddenCol) {
-    final Board board = myProvider.board;
-    final int sizeHorizontal = myProvider.sizeHorizontal;
-    final int sizeVertical = myProvider.sizeVertical;
-
-    // Shuffle cells to put random mines, except on currently selected one
-    final List<List<int>> allowedCells = [];
-    for (int row = 0; row < sizeVertical; row++) {
-      for (int col = 0; col < sizeHorizontal; col++) {
-        if (!((forbiddenRow == row) && (forbiddenCol == col))) {
-          allowedCells.add([row, col]);
-        }
-      }
-    }
-    allowedCells.shuffle();
-
-    // Put random mines on board
-    for (int mineIndex = 0; mineIndex < myProvider.minesCount; mineIndex++) {
-      board[allowedCells[mineIndex][0]][allowedCells[mineIndex][1]].isMined = true;
-    }
-
-    // Compute all mines counts on cells
-    for (int row = 0; row < sizeVertical; row++) {
-      for (int col = 0; col < sizeHorizontal; col++) {
-        board[row][col].minesCountAround = getMinesCountAround(board, row, col);
-      }
-    }
-
-    printGrid(board);
-
-    return board;
-  }
-
-  static Board createBoardFromSavedState(Data myProvider, String savedBoard) {
-    final Board board = [];
-    final int boardSize = pow((savedBoard.length / 6), 1 / 2).round();
-    final String boardSizeAsString = '${boardSize}x$boardSize';
-    myProvider.updateParameterSize(boardSizeAsString);
-
-    int index = 0;
-    for (int rowIndex = 0; rowIndex < boardSize; rowIndex++) {
-      final List<Cell> row = [];
-      for (int colIndex = 0; colIndex < boardSize; colIndex++) {
-        final bool isMined = (savedBoard[index++] == 'X');
-        final bool isExplored = (savedBoard[index++] == 'E');
-        final bool isMarked = (savedBoard[index++] == 'P');
-        final bool isExploded = (savedBoard[index++] == '*');
-        final int minesCountAround = int.parse(savedBoard[index++]);
-        index++; // ";"
-
-        Cell cell = Cell(isMined);
-        cell.isExplored = isExplored;
-        cell.isMarked = isMarked;
-        cell.isExploded = isExploded;
-        cell.minesCountAround = minesCountAround;
-
-        row.add(cell);
-      }
-      board.add(row);
-    }
-
-    printGrid(board);
-
-    return board;
-  }
-
-  static void reportCell(Data myProvider, int row, int col) {
-    if (!myProvider.board[row][col].isExplored) {
-      myProvider.toggleCellMark(row, col);
-    }
-  }
-
-  static void walkOnCell(Data myProvider, int row, int col) {
-    myProvider.setCellAsExplored(row, col);
-
-    if (myProvider.board[row][col].minesCountAround == 0) {
-      final List<List<int>> safeCells = getAllSafeCellsAround(myProvider.board, row, col);
-      for (int safeCellIndex = 0; safeCellIndex < safeCells.length; safeCellIndex++) {
-        final int safeCellRow = safeCells[safeCellIndex][0];
-        final int safeCellCol = safeCells[safeCellIndex][1];
-        if (!myProvider.board[safeCellRow][safeCellCol].isExplored) {
-          walkOnCell(myProvider, safeCellRow, safeCellCol);
-        }
-      }
-    }
-  }
-
-  static List<List<int>> getAllSafeCellsAround(List cells, int row, int col) {
-    final int sizeHorizontal = cells.length;
-    final int sizeVertical = cells[0].length;
-
-    final List<List<int>> safeCellsCoordinates = [];
-
-    if (cells[row][col].minesCountAround == 0) {
-      for (int deltaRow = -1; deltaRow <= 1; deltaRow++) {
-        for (int deltaCol = -1; deltaCol <= 1; deltaCol++) {
-          final int candidateRow = row + deltaRow;
-          final int candidateCol = col + deltaCol;
-          if ((candidateRow >= 0 && candidateRow < sizeVertical) &&
-              (candidateCol >= 0 && candidateCol < sizeHorizontal) &&
-              !cells[candidateRow][candidateCol].isExplored) {
-            safeCellsCoordinates.add([candidateRow, candidateCol]);
-          }
-        }
-      }
-    }
-
-    return safeCellsCoordinates;
-  }
-
-  static int getMinesCountAround(List cells, int row, int col) {
-    final int sizeHorizontal = cells.length;
-    final int sizeVertical = cells[0].length;
-
-    int minesCountAround = 0;
-    for (int deltaRow = -1; deltaRow <= 1; deltaRow++) {
-      for (int deltaCol = -1; deltaCol <= 1; deltaCol++) {
-        if ((row + deltaRow >= 0 && row + deltaRow < sizeVertical) &&
-            (col + deltaCol >= 0 && col + deltaCol < sizeHorizontal) &&
-            (cells[row + deltaRow][col + deltaCol].isMined)) {
-          minesCountAround++;
-        }
-      }
-    }
-
-    return minesCountAround;
-  }
-
-  static bool checkGameIsFinished(Data myProvider) {
-    final Board board = myProvider.board;
-    final int sizeHorizontal = board.length;
-    final int sizeVertical = board[0].length;
-
-    printGrid(board);
-
-    myProvider.updateGameWin(false);
-    myProvider.updateGameFail(false);
-
-    for (int row = 0; row < sizeVertical; row++) {
-      for (int col = 0; col < sizeHorizontal; col++) {
-        // Walked on a mine
-        if (board[row][col].isExploded == true) {
-          myProvider.updateGameFail(true);
-          return true;
-        }
-      }
-    }
-
-    for (int row = 0; row < sizeVertical; row++) {
-      for (int col = 0; col < sizeHorizontal; col++) {
-        if (
-            // Mine not already found
-            (board[row][col].isMined == true && board[row][col].isMarked == false) ||
-                // Safe cell marked as mined
-                (board[row][col].isMined == false && board[row][col].isMarked == true)) {
-          return false;
-        }
-      }
-    }
-
-    printlog('-> ok all mines found!');
-    myProvider.updateGameWin(true);
-
-    return true;
-  }
-
-  static int countFlaggedCells(List cells) {
-    int count = 0;
-
-    final int sizeHorizontal = cells.length;
-    final int sizeVertical = cells[0].length;
-    for (int row = 0; row < sizeVertical; row++) {
-      for (int col = 0; col < sizeHorizontal; col++) {
-        if (cells[row][col].isMarked == true) {
-          count++;
-        }
-      }
-    }
-
-    return count;
-  }
-}
diff --git a/lib/utils/color_extensions.dart b/lib/utils/color_extensions.dart
new file mode 100644
index 0000000000000000000000000000000000000000..4e55e338f0d3ed98b233d1ef887b7b3e17e29d97
--- /dev/null
+++ b/lib/utils/color_extensions.dart
@@ -0,0 +1,33 @@
+import 'dart:ui';
+
+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/game_utils.dart b/lib/utils/game_utils.dart
deleted file mode 100644
index c173564b8f2348763847dfa7d0bf9faabdccec89..0000000000000000000000000000000000000000
--- a/lib/utils/game_utils.dart
+++ /dev/null
@@ -1,51 +0,0 @@
-import 'package:minehunter/provider/data.dart';
-import 'package:minehunter/utils/board_animate.dart';
-import 'package:minehunter/utils/board_utils.dart';
-import 'package:minehunter/utils/tools.dart';
-
-class GameUtils {
-  static quitGame(Data myProvider) {
-    myProvider.updateGameIsRunning(false);
-    if (BoardUtils.checkGameIsFinished(myProvider)) {
-      myProvider.resetCurrentSavedState();
-    }
-  }
-
-  static void startNewGame(Data myProvider) {
-    printlog('Starting game: ${myProvider.parameterSize} - ${myProvider.parameterLevel}');
-    myProvider.updateParameterSize(myProvider.parameterSize);
-    myProvider.updateMinesCount(BoardUtils.getMinesCount(
-        myProvider.sizeHorizontal, myProvider.sizeVertical, myProvider.parameterLevel));
-    myProvider.updateGameIsRunning(true);
-    BoardUtils.createInitialEmptyBoard(myProvider);
-    BoardAnimate.startAnimation(myProvider, 'start');
-  }
-
-  static void deleteSavedGame(Data myProvider) {
-    myProvider.resetCurrentSavedState();
-  }
-
-  static void resumeSavedGame(Data myProvider) {
-    Map<String, dynamic> savedState = myProvider.getCurrentSavedState();
-    if (savedState.isNotEmpty) {
-      try {
-        myProvider.setParameterValue('level', savedState['level']);
-        myProvider.setParameterValue('size', savedState['size']);
-        myProvider.setParameterValue('skin', savedState['skin']);
-
-        myProvider.updateBoard(
-            BoardUtils.createBoardFromSavedState(myProvider, savedState['board']));
-        myProvider.updateGameIsRunning(true);
-      } catch (e) {
-        printlog('Failed to resume game. Will start new one instead.');
-        myProvider.resetCurrentSavedState();
-        myProvider.initParametersValues();
-        startNewGame(myProvider);
-      }
-    } else {
-      myProvider.resetCurrentSavedState();
-      myProvider.initParametersValues();
-      startNewGame(myProvider);
-    }
-  }
-}
diff --git a/pubspec.lock b/pubspec.lock
index 086064193c8ae5ca1019e066b4b108e7da2b6d13..e0ab96ebb656b1260018d45af586d9ec14ba4a7e 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -106,10 +106,10 @@ packages:
     dependency: "direct main"
     description:
       name: flutter_bloc
-      sha256: f0ecf6e6eb955193ca60af2d5ca39565a86b8a142452c5b24d96fb477428f4d2
+      sha256: b594505eac31a0518bdcb4b5b79573b8d9117b193cc80cc12e17d639b10aa27a
       url: "https://pub.dev"
     source: hosted
-    version: "8.1.5"
+    version: "8.1.6"
   flutter_lints:
     dependency: "direct dev"
     description:
@@ -217,7 +217,7 @@ packages:
     source: hosted
     version: "3.0.0"
   path:
-    dependency: "direct main"
+    dependency: transitive
     description:
       name: path
       sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
@@ -236,10 +236,10 @@ packages:
     dependency: transitive
     description:
       name: path_provider_android
-      sha256: a248d8146ee5983446bf03ed5ea8f6533129a12b11f12057ad1b4a67a2b3b41d
+      sha256: "9c96da072b421e98183f9ea7464898428e764bc0ce5567f27ec8693442e72514"
       url: "https://pub.dev"
     source: hosted
-    version: "2.2.4"
+    version: "2.2.5"
   path_provider_foundation:
     dependency: transitive
     description:
@@ -276,10 +276,10 @@ packages:
     dependency: transitive
     description:
       name: platform
-      sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec"
+      sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65"
       url: "https://pub.dev"
     source: hosted
-    version: "3.1.4"
+    version: "3.1.5"
   plugin_platform_interface:
     dependency: transitive
     description:
@@ -289,7 +289,7 @@ packages:
     source: hosted
     version: "2.1.8"
   provider:
-    dependency: "direct main"
+    dependency: transitive
     description:
       name: provider
       sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c
@@ -297,7 +297,7 @@ packages:
     source: hosted
     version: "6.1.2"
   shared_preferences:
-    dependency: "direct main"
+    dependency: transitive
     description:
       name: shared_preferences
       sha256: d3bbe5553a986e83980916ded2f0b435ef2e1893dfaa29d5a7a790d0eca12180
@@ -308,10 +308,10 @@ packages:
     dependency: transitive
     description:
       name: shared_preferences_android
-      sha256: "1ee8bf911094a1b592de7ab29add6f826a7331fb854273d55918693d5364a1f2"
+      sha256: "93d0ec9dd902d85f326068e6a899487d1f65ffcd5798721a95330b26c8131577"
       url: "https://pub.dev"
     source: hosted
-    version: "2.2.2"
+    version: "2.2.3"
   shared_preferences_foundation:
     dependency: transitive
     description:
@@ -439,4 +439,4 @@ packages:
     version: "1.0.4"
 sdks:
   dart: ">=3.4.0 <4.0.0"
-  flutter: ">=3.19.0"
+  flutter: ">=3.22.0"
diff --git a/pubspec.yaml b/pubspec.yaml
index eedbd4cd9dae9e739394f1ce70e1b21ae09fbc2b..635202eacd52b8961e5d5d785d7c18ad3c6e3164 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,36 +1,38 @@
 name: minehunter
 description: A minehunter game application.
 
-publish_to: 'none'
-version: 0.1.19+40
+publish_to: "none"
+
+version: 0.2.0+41
 
 environment:
-  sdk: '^3.0.0'
+  sdk: "^3.0.0"
 
 dependencies:
   flutter:
     sdk: flutter
 
+  # base
   easy_localization: ^3.0.1
   equatable: ^2.0.5
   flutter_bloc: ^8.1.1
   hive: ^2.2.3
   hydrated_bloc: ^9.0.0
-  provider: ^6.0.5
-  shared_preferences: ^2.2.1
   package_info_plus: ^8.0.0
-  path: ^1.9.0
   path_provider: ^2.0.11
   unicons: ^2.1.1
 
+  # specific
+  # (none)
+
 dev_dependencies:
   flutter_lints: ^4.0.0
 
 flutter:
   uses-material-design: true
   assets:
-    - assets/icons/
     - assets/skins/
+    - assets/ui/
     - assets/translations/
 
   fonts:
diff --git a/icons/build_application_icons.sh b/resources/app/build_application_resources.sh
similarity index 98%
rename from icons/build_application_icons.sh
rename to resources/app/build_application_resources.sh
index 27dbe2647fe4e6d562fbd99451716d1b7d448570..6d67b8f4f9eca701d1aed7331ef41dfb0bd44f20 100755
--- a/icons/build_application_icons.sh
+++ b/resources/app/build_application_resources.sh
@@ -6,7 +6,7 @@ command -v scour >/dev/null 2>&1 || { echo >&2 "I require scour but it's not ins
 command -v optipng >/dev/null 2>&1 || { echo >&2 "I require optipng but it's not installed. Aborting."; exit 1; }
 
 CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
-BASE_DIR="$(dirname "${CURRENT_DIR}")"
+BASE_DIR="$(dirname "$(dirname "${CURRENT_DIR}")")"
 
 SOURCE_ICON="${CURRENT_DIR}/icon.svg"
 SOURCE_FASTLANE="${CURRENT_DIR}/featureGraphic.svg"
diff --git a/icons/featureGraphic.svg b/resources/app/featureGraphic.svg
similarity index 100%
rename from icons/featureGraphic.svg
rename to resources/app/featureGraphic.svg
diff --git a/icons/icon.svg b/resources/app/icon.svg
similarity index 100%
rename from icons/icon.svg
rename to resources/app/icon.svg
diff --git a/resources/build_resources.sh b/resources/build_resources.sh
new file mode 100755
index 0000000000000000000000000000000000000000..659697a1c043cfe1c7654635cfaec3e4a0ff8a1a
--- /dev/null
+++ b/resources/build_resources.sh
@@ -0,0 +1,7 @@
+#! /bin/bash
+
+CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
+
+${CURRENT_DIR}/app/build_application_resources.sh
+${CURRENT_DIR}/ui/build_ui_resources.sh
+
diff --git a/resources/ui/build_ui_resources.sh b/resources/ui/build_ui_resources.sh
new file mode 100755
index 0000000000000000000000000000000000000000..4f365ede7d83140ce6309a3083580f2662b30990
--- /dev/null
+++ b/resources/ui/build_ui_resources.sh
@@ -0,0 +1,110 @@
+#! /bin/bash
+
+# Check dependencies
+command -v inkscape >/dev/null 2>&1 || { echo >&2 "I require inkscape but it's not installed. Aborting."; exit 1; }
+command -v scour >/dev/null 2>&1 || { echo >&2 "I require scour but it's not installed. Aborting."; exit 1; }
+command -v optipng >/dev/null 2>&1 || { echo >&2 "I require optipng but it's not installed. Aborting."; exit 1; }
+
+CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
+BASE_DIR="$(dirname "$(dirname "${CURRENT_DIR}")")"
+ASSETS_DIR="${BASE_DIR}/assets"
+
+OPTIPNG_OPTIONS="-preserve -quiet -o7"
+ICON_SIZE=192
+
+#######################################################
+
+# Game images (svg files found in `images` folder)
+AVAILABLE_GAME_IMAGES=""
+if [ -d "${CURRENT_DIR}/images" ]; then
+  AVAILABLE_GAME_IMAGES="$(find "${CURRENT_DIR}/images" -type f -name "*.svg" | awk -F/ '{print $NF}' | cut -d"." -f1 | sort)"
+fi
+
+# Skins (subfolders found in `skins` folder)
+AVAILABLE_SKINS=""
+if [ -d "${CURRENT_DIR}/skins" ]; then
+  AVAILABLE_SKINS="$(find "${CURRENT_DIR}/skins" -mindepth 1 -type d | awk -F/ '{print $NF}')"
+fi
+
+# Images per skin (svg files found recursively in `skins` folder and subfolders)
+SKIN_IMAGES=""
+if [ -d "${CURRENT_DIR}/skins" ]; then
+  SKIN_IMAGES="$(find "${CURRENT_DIR}/skins" -type f -name "*.svg" | awk -F/ '{print $NF}' | cut -d"." -f1 | sort | uniq)"
+fi
+
+#######################################################
+
+# optimize svg
+function optimize_svg() {
+  SOURCE="$1"
+
+  cp ${SOURCE} ${SOURCE}.tmp
+  scour \
+      --remove-descriptive-elements \
+      --enable-id-stripping \
+      --enable-viewboxing \
+      --enable-comment-stripping \
+      --nindent=4 \
+      --quiet \
+      -i ${SOURCE}.tmp \
+      -o ${SOURCE}
+  rm ${SOURCE}.tmp
+}
+
+# build icons
+function build_image() {
+  SOURCE="$1"
+  TARGET="$2"
+
+  echo "Building ${TARGET}"
+
+  if [ ! -f "${SOURCE}" ]; then
+    echo "Missing file: ${SOURCE}"
+    exit 1
+  fi
+
+  optimize_svg "${SOURCE}"
+
+  mkdir -p "$(dirname "${TARGET}")"
+
+  inkscape \
+      --export-width=${ICON_SIZE} \
+      --export-height=${ICON_SIZE} \
+      --export-filename=${TARGET} \
+      "${SOURCE}"
+
+  optipng ${OPTIPNG_OPTIONS} "${TARGET}"
+}
+
+function build_image_for_skin() {
+  SKIN_CODE="$1"
+
+  # skin images
+  for SKIN_IMAGE in ${SKIN_IMAGES}
+  do
+    build_image ${CURRENT_DIR}/skins/${SKIN_CODE}/${SKIN_IMAGE}.svg ${ASSETS_DIR}/skins/${SKIN_CODE}_${SKIN_IMAGE}.png
+  done
+}
+
+#######################################################
+
+# Delete existing generated images
+if [ -d "${ASSETS_DIR}/ui" ]; then
+  find ${ASSETS_DIR}/ui -type f -name "*.png" -delete
+fi
+if [ -d "${ASSETS_DIR}/skins" ]; then
+  find ${ASSETS_DIR}/skins -type f -name "*.png" -delete
+fi
+
+# build game images
+for GAME_IMAGE in ${AVAILABLE_GAME_IMAGES}
+do
+  build_image ${CURRENT_DIR}/images/${GAME_IMAGE}.svg ${ASSETS_DIR}/ui/${GAME_IMAGE}.png
+done
+
+# build skins images
+for SKIN in ${AVAILABLE_SKINS}
+do
+  build_image_for_skin "${SKIN}"
+done
+
diff --git a/icons/button_back.svg b/resources/ui/images/button_back.svg
similarity index 100%
rename from icons/button_back.svg
rename to resources/ui/images/button_back.svg
diff --git a/icons/button_delete_saved_game.svg b/resources/ui/images/button_delete_saved_game.svg
similarity index 100%
rename from icons/button_delete_saved_game.svg
rename to resources/ui/images/button_delete_saved_game.svg
diff --git a/icons/button_resume_game.svg b/resources/ui/images/button_resume_game.svg
similarity index 100%
rename from icons/button_resume_game.svg
rename to resources/ui/images/button_resume_game.svg
diff --git a/resources/ui/images/button_start.svg b/resources/ui/images/button_start.svg
new file mode 100644
index 0000000000000000000000000000000000000000..e9d49d2172b9a0305db82779971e3c1e12f34a70
--- /dev/null
+++ b/resources/ui/images/button_start.svg
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 93.665 93.676" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x=".44662" y=".89101" width="92.772" height="91.894" ry="11.689" fill="#49a1ee" stroke="#fff" stroke-width=".238"/><path d="m34.852 25.44c-1.1248-1.1302-4.0012-1.1302-4.0012 0v45.921c0 1.1316 2.8832 1.1316 4.0121 0l37.693-20.918c1.1289-1.1248 1.1479-2.9551 0.02171-4.084z" fill="#fefeff" stroke="#105ca1" stroke-linecap="round" stroke-linejoin="round" stroke-width="8.257"/><path d="m36.382 28.754c-0.96243-0.96706-3.4236-0.96706-3.4236 0v39.292c0 0.96825 2.467 0.96825 3.4329 0l32.252-17.898c0.96594-0.96243 0.9822-2.5285 0.01858-3.4945z" fill="#fefeff" stroke="#feffff" stroke-linecap="round" stroke-linejoin="round" stroke-width="4.314"/></svg>
diff --git a/icons/game_fail.svg b/resources/ui/images/game_fail.svg
similarity index 100%
rename from icons/game_fail.svg
rename to resources/ui/images/game_fail.svg
diff --git a/icons/game_win.svg b/resources/ui/images/game_win.svg
similarity index 100%
rename from icons/game_win.svg
rename to resources/ui/images/game_win.svg
diff --git a/icons/placeholder.svg b/resources/ui/images/placeholder.svg
similarity index 100%
rename from icons/placeholder.svg
rename to resources/ui/images/placeholder.svg
diff --git a/icons/skins/default/button_mark_mine_off.svg b/resources/ui/skins/default/button_mark_mine_off.svg
similarity index 100%
rename from icons/skins/default/button_mark_mine_off.svg
rename to resources/ui/skins/default/button_mark_mine_off.svg
diff --git a/icons/skins/default/button_mark_mine_on.svg b/resources/ui/skins/default/button_mark_mine_on.svg
similarity index 100%
rename from icons/skins/default/button_mark_mine_on.svg
rename to resources/ui/skins/default/button_mark_mine_on.svg
diff --git a/icons/skins/default/empty.svg b/resources/ui/skins/default/empty.svg
similarity index 100%
rename from icons/skins/default/empty.svg
rename to resources/ui/skins/default/empty.svg
diff --git a/icons/skins/default/indicator_report_off.svg b/resources/ui/skins/default/indicator_report_off.svg
similarity index 100%
rename from icons/skins/default/indicator_report_off.svg
rename to resources/ui/skins/default/indicator_report_off.svg
diff --git a/icons/skins/default/indicator_report_on.svg b/resources/ui/skins/default/indicator_report_on.svg
similarity index 100%
rename from icons/skins/default/indicator_report_on.svg
rename to resources/ui/skins/default/indicator_report_on.svg
diff --git a/icons/skins/default/indicator_walk_off.svg b/resources/ui/skins/default/indicator_walk_off.svg
similarity index 100%
rename from icons/skins/default/indicator_walk_off.svg
rename to resources/ui/skins/default/indicator_walk_off.svg
diff --git a/icons/skins/default/indicator_walk_on.svg b/resources/ui/skins/default/indicator_walk_on.svg
similarity index 100%
rename from icons/skins/default/indicator_walk_on.svg
rename to resources/ui/skins/default/indicator_walk_on.svg
diff --git a/icons/skins/default/tile_0.svg b/resources/ui/skins/default/tile_0.svg
similarity index 100%
rename from icons/skins/default/tile_0.svg
rename to resources/ui/skins/default/tile_0.svg
diff --git a/icons/skins/default/tile_1.svg b/resources/ui/skins/default/tile_1.svg
similarity index 100%
rename from icons/skins/default/tile_1.svg
rename to resources/ui/skins/default/tile_1.svg
diff --git a/icons/skins/default/tile_2.svg b/resources/ui/skins/default/tile_2.svg
similarity index 100%
rename from icons/skins/default/tile_2.svg
rename to resources/ui/skins/default/tile_2.svg
diff --git a/icons/skins/default/tile_3.svg b/resources/ui/skins/default/tile_3.svg
similarity index 100%
rename from icons/skins/default/tile_3.svg
rename to resources/ui/skins/default/tile_3.svg
diff --git a/icons/skins/default/tile_4.svg b/resources/ui/skins/default/tile_4.svg
similarity index 100%
rename from icons/skins/default/tile_4.svg
rename to resources/ui/skins/default/tile_4.svg
diff --git a/icons/skins/default/tile_5.svg b/resources/ui/skins/default/tile_5.svg
similarity index 100%
rename from icons/skins/default/tile_5.svg
rename to resources/ui/skins/default/tile_5.svg
diff --git a/icons/skins/default/tile_6.svg b/resources/ui/skins/default/tile_6.svg
similarity index 100%
rename from icons/skins/default/tile_6.svg
rename to resources/ui/skins/default/tile_6.svg
diff --git a/icons/skins/default/tile_7.svg b/resources/ui/skins/default/tile_7.svg
similarity index 100%
rename from icons/skins/default/tile_7.svg
rename to resources/ui/skins/default/tile_7.svg
diff --git a/icons/skins/default/tile_8.svg b/resources/ui/skins/default/tile_8.svg
similarity index 100%
rename from icons/skins/default/tile_8.svg
rename to resources/ui/skins/default/tile_8.svg
diff --git a/icons/skins/default/tile_flag.svg b/resources/ui/skins/default/tile_flag.svg
similarity index 100%
rename from icons/skins/default/tile_flag.svg
rename to resources/ui/skins/default/tile_flag.svg
diff --git a/icons/skins/default/tile_flag_ko.svg b/resources/ui/skins/default/tile_flag_ko.svg
similarity index 100%
rename from icons/skins/default/tile_flag_ko.svg
rename to resources/ui/skins/default/tile_flag_ko.svg
diff --git a/icons/skins/default/tile_flag_ok.svg b/resources/ui/skins/default/tile_flag_ok.svg
similarity index 100%
rename from icons/skins/default/tile_flag_ok.svg
rename to resources/ui/skins/default/tile_flag_ok.svg
diff --git a/icons/skins/default/tile_mine.svg b/resources/ui/skins/default/tile_mine.svg
similarity index 100%
rename from icons/skins/default/tile_mine.svg
rename to resources/ui/skins/default/tile_mine.svg
diff --git a/icons/skins/default/tile_mine_not_found.svg b/resources/ui/skins/default/tile_mine_not_found.svg
similarity index 100%
rename from icons/skins/default/tile_mine_not_found.svg
rename to resources/ui/skins/default/tile_mine_not_found.svg
diff --git a/icons/skins/default/tile_unknown.svg b/resources/ui/skins/default/tile_unknown.svg
similarity index 100%
rename from icons/skins/default/tile_unknown.svg
rename to resources/ui/skins/default/tile_unknown.svg