diff --git a/android/gradle.properties b/android/gradle.properties
index c8bbff9bd599a7c3ffbe76de5a61ead3de90631a..a22054ee50f7b42877fcabc148c89078687808c9 100644
--- a/android/gradle.properties
+++ b/android/gradle.properties
@@ -1,5 +1,5 @@
 org.gradle.jvmargs=-Xmx1536M
 android.useAndroidX=true
 android.enableJetifier=true
-app.versionName=0.0.39
-app.versionCode=39
+app.versionName=0.1.0
+app.versionCode=40
diff --git a/assets/translations/en.json b/assets/translations/en.json
index 92299163019c59771191b4b86fb4a41f0ece93f1..f44610149e211750a2eb1877ce42da67d7b8ce98 100644
--- a/assets/translations/en.json
+++ b/assets/translations/en.json
@@ -1,14 +1,12 @@
 {
   "app_name": "Colors",
 
-  "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": "Colors, a colorful flood game.",
-  "about_version": "Version: {version}"
+  "about_version": "Version: {version}",
+
+  "": ""
 }
diff --git a/assets/translations/fr.json b/assets/translations/fr.json
index dc7d503692165e64de23d0191442b6ada8bacb6d..312f2f2999310b07279ecda043f30508dd6711cf 100644
--- a/assets/translations/fr.json
+++ b/assets/translations/fr.json
@@ -1,14 +1,12 @@
 {
-  "app_name": "Colors",
-
-  "bottom_nav_home": "Jeu",
-  "bottom_nav_settings": "Réglages",
-  "bottom_nav_about": "Infos",
+  "app_name": "Couleurs",
 
   "settings_title": "Réglages",
   "settings_label_theme": "Thème de couleurs",
 
   "about_title": "Informations",
   "about_content": "Colors, un jeu de remplissage haut en couleurs.",
-  "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/ui/button_delete_saved_game.png b/assets/ui/button_delete_saved_game.png
new file mode 100644
index 0000000000000000000000000000000000000000..5e4f217689b11e444b7163557d7e5d68f3bbfe7d
Binary files /dev/null and b/assets/ui/button_delete_saved_game.png differ
diff --git a/assets/ui/button_resume_game.png b/assets/ui/button_resume_game.png
new file mode 100644
index 0000000000000000000000000000000000000000..b2ea0a02d05e42377eb551a4b51428b511a32f5d
Binary files /dev/null and b/assets/ui/button_resume_game.png differ
diff --git a/assets/icons/button_start.png b/assets/ui/button_start.png
similarity index 100%
rename from assets/icons/button_start.png
rename to assets/ui/button_start.png
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/ui/placeholder.png b/assets/ui/placeholder.png
new file mode 100644
index 0000000000000000000000000000000000000000..814df31be6ddc4275ebe4490c79365578dbef1f0
Binary files /dev/null and b/assets/ui/placeholder.png differ
diff --git a/fastlane/metadata/android/en-US/changelogs/40.txt b/fastlane/metadata/android/en-US/changelogs/40.txt
new file mode 100644
index 0000000000000000000000000000000000000000..d4afd512e55b3fd8ffbfd795adb9b00832e5aaef
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/40.txt
@@ -0,0 +1 @@
+Improve/normalize game architecture.
diff --git a/fastlane/metadata/android/fr-FR/changelogs/40.txt b/fastlane/metadata/android/fr-FR/changelogs/40.txt
new file mode 100644
index 0000000000000000000000000000000000000000..6a9871a5eb8eb3c6e9106520f1cbf1f39f9e5ef7
--- /dev/null
+++ b/fastlane/metadata/android/fr-FR/changelogs/40.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 7ea6ed5d23526aa94c9626826ffd4545141a1674..0000000000000000000000000000000000000000
--- a/icons/build_game_icons.sh
+++ /dev/null
@@ -1,80 +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
-  game_fail
-  game_win
-"
-
-#######################################################
-
-# 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}
-}
-
-#######################################################
-
-# Create output folders
-mkdir -p ${ASSETS_DIR}/icons
-
-# Delete existing generated images
-find ${ASSETS_DIR}/icons -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
-
diff --git a/lib/utils/color_theme.dart b/lib/config/color_theme.dart
similarity index 100%
rename from lib/utils/color_theme.dart
rename to lib/config/color_theme.dart
diff --git a/lib/config/default_game_settings.dart b/lib/config/default_game_settings.dart
index db8841295f53570f90f2a50ea1e6abbca2ac2403..de6450104bf828e5e6ade5e037e4c5e27c0638fd 100644
--- a/lib/config/default_game_settings.dart
+++ b/lib/config/default_game_settings.dart
@@ -1,4 +1,4 @@
-import 'package:colors/utils/tools.dart';
+import 'package:colors/utils/tools.dart';         
 
 class DefaultGameSettings {
   // available game parameters codes
@@ -78,4 +78,9 @@ class DefaultGameSettings {
     return values[parameterLevel] ??
         getMovesCountLimitDeltaFromLevelCode(DefaultGameSettings.defaultDifficultyLevelValue);
   }
+
+  // parameters displayed with assets (instead of painter)
+  static List<String> displayedWithAssets = [
+    //
+  ];
 }
diff --git a/lib/config/default_global_settings.dart b/lib/config/default_global_settings.dart
index 3ec1474a9af61c014e5791a793d7205343070dfb..d49140267e05b12c1de03dae5698ec4ecc7548bf 100644
--- a/lib/config/default_global_settings.dart
+++ b/lib/config/default_global_settings.dart
@@ -1,4 +1,4 @@
-import 'package:colors/utils/tools.dart';
+import 'package:colors/utils/tools.dart';         
 
 class DefaultGlobalSettings {
   // available global parameters codes
@@ -25,4 +25,9 @@ class DefaultGlobalSettings {
     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 2f9395d83564baa03622ecebe7fdc74e7a68c08c..37dd0750d2aba417738c0b2371becb23c3b3355a 100644
--- a/lib/config/menu.dart
+++ b/lib/config/menu.dart
@@ -6,12 +6,10 @@ import 'package:colors/ui/screens/page_game.dart';
 import 'package:colors/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,
   });
@@ -20,21 +18,18 @@ class MenuItem {
 class Menu {
   static const indexGame = 0;
   static const menuItemGame = MenuItem(
-    code: 'bottom_nav_game',
     icon: Icon(UniconsLine.home),
     page: PageGame(),
   );
 
   static const indexSettings = 1;
   static const menuItemSettings = MenuItem(
-    code: 'bottom_nav_settings',
     icon: Icon(UniconsLine.setting),
     page: PageSettings(),
   );
 
   static const indexAbout = 2;
   static const menuItemAbout = MenuItem(
-    code: 'bottom_nav_about',
     icon: Icon(UniconsLine.info_circle),
     page: PageAbout(),
   );
diff --git a/lib/config/theme.dart b/lib/config/theme.dart
index be390348c7868e7c63387df13e13c46de43f8a23..74f532fd5abf693979118609564d29167e902009 100644
--- a/lib/config/theme.dart
+++ b/lib/config/theme.dart
@@ -39,11 +39,9 @@ final ColorScheme lightColorScheme = ColorScheme.light(
   secondary: primarySwatch.shade500,
   onSecondary: Colors.white,
   error: errorColor,
-  background: textSwatch.shade200,
-  onBackground: textSwatch.shade500,
   onSurface: textSwatch.shade500,
   surface: textSwatch.shade50,
-  surfaceVariant: Colors.white,
+  surfaceContainerHighest: Colors.white,
   shadow: textSwatch.shade900.withOpacity(.1),
 );
 
@@ -52,11 +50,9 @@ final ColorScheme darkColorScheme = ColorScheme.dark(
   secondary: primarySwatch.shade500,
   onSecondary: Colors.white,
   error: errorColor,
-  background: const Color(0xFF171724),
-  onBackground: textSwatch.shade400,
   onSurface: textSwatch.shade300,
   surface: const Color(0xFF262630),
-  surfaceVariant: const Color(0xFF282832),
+  surfaceContainerHighest: const Color(0xFF282832),
   shadow: textSwatch.shade900.withOpacity(.2),
 );
 
@@ -192,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
index 16775c36cca0ee88c6ef2a7470959c51a80dac08..798724273b3c0d7f19a7e5a8f59c180f246571a1 100644
--- a/lib/cubit/game_cubit.dart
+++ b/lib/cubit/game_cubit.dart
@@ -6,17 +6,16 @@ import 'package:flutter/foundation.dart';
 import 'package:flutter/material.dart';
 import 'package:hydrated_bloc/hydrated_bloc.dart';
 
-import 'package:colors/models/game.dart';
-import 'package:colors/models/settings_game.dart';
-import 'package:colors/models/settings_global.dart';
-import 'package:colors/utils/tools.dart';
+import 'package:colors/models/game/game.dart';
+import 'package:colors/models/settings/settings_game.dart';
+import 'package:colors/models/settings/settings_global.dart';
 
 part 'game_state.dart';
 
 class GameCubit extends HydratedCubit<GameState> {
   GameCubit()
       : super(GameState(
-          currentGame: Game.createNull(),
+          currentGame: Game.createEmpty(),
         ));
 
   void updateState(Game game) {
@@ -27,19 +26,25 @@ class GameCubit extends HydratedCubit<GameState> {
 
   void refresh() {
     final Game game = Game(
-      board: state.currentGame.board,
+      // Settings
       gameSettings: state.currentGame.gameSettings,
       globalSettings: state.currentGame.globalSettings,
+      // State
       isRunning: state.currentGame.isRunning,
+      isStarted: state.currentGame.isStarted,
       isFinished: state.currentGame.isFinished,
-      gameWon: state.currentGame.gameWon,
-      movesCount: state.currentGame.movesCount,
-      maxMovesCount: state.currentGame.maxMovesCount,
       animationInProgress: state.currentGame.animationInProgress,
+      // Base data
+      board: state.currentGame.board,
+      // Game data
+      maxMovesCount: state.currentGame.maxMovesCount,
+      movesCount: state.currentGame.movesCount,
       progress: state.currentGame.progress,
       progressTotal: state.currentGame.progressTotal,
       progressDelta: state.currentGame.progressDelta,
+      gameWon: state.currentGame.gameWon,
     );
+    // game.dump();
 
     updateState(game);
   }
@@ -48,12 +53,8 @@ class GameCubit extends HydratedCubit<GameState> {
     required GameSettings gameSettings,
     required GlobalSettings globalSettings,
   }) {
-    printlog('Starting new game:');
-    printlog('- level: ${gameSettings.difficultyLevel}');
-    printlog('- size: ${gameSettings.parameterSize}');
-    printlog('- colors: ${gameSettings.parameterColorsCount}');
-
-    Game newGame = Game.createNew(
+    final Game newGame = Game.createNew(
+      // Settings
       gameSettings: gameSettings,
       globalSettings: globalSettings,
     );
@@ -62,6 +63,8 @@ class GameCubit extends HydratedCubit<GameState> {
 
     updateState(newGame);
     updateGameIsRunning(true);
+
+    refresh();
   }
 
   void quitGame() {
@@ -69,6 +72,17 @@ class GameCubit extends HydratedCubit<GameState> {
     refresh();
   }
 
+  void resumeSavedGame() {
+    state.currentGame.isRunning = true;
+    refresh();
+  }
+
+  void deleteSavedGame() {
+    state.currentGame.isRunning = false;
+    state.currentGame.isFinished = true;
+    refresh();
+  }
+
   void updateCellValue(int col, int row, int value) {
     state.currentGame.board.cells[row][col].value = value;
     refresh();
@@ -99,6 +113,11 @@ class GameCubit extends HydratedCubit<GameState> {
     refresh();
   }
 
+  void updateGameIsStarted(bool gameIsStarted) {
+    state.currentGame.isStarted = gameIsStarted;
+    refresh();
+  }
+
   void updateGameIsFinished(bool gameIsFinished) {
     state.currentGame.isFinished = gameIsFinished;
     refresh();
@@ -110,6 +129,8 @@ class GameCubit extends HydratedCubit<GameState> {
   }
 
   fillBoardFromFirstCell(int value) {
+    updateGameIsStarted(true);
+
     List<List<int>> cellsToFill = state.currentGame.board.getSiblingFillableCells(0, 0, []);
     final int progressBeforeMove = cellsToFill.length;
 
@@ -154,7 +175,7 @@ class GameCubit extends HydratedCubit<GameState> {
 
   @override
   GameState? fromJson(Map<String, dynamic> json) {
-    Game currentGame = json['currentGame'] as Game;
+    final Game currentGame = json['currentGame'] as Game;
 
     return GameState(
       currentGame: currentGame,
diff --git a/lib/cubit/game_state.dart b/lib/cubit/game_state.dart
index 3fd161a0915313722b7a15c55c7cf538a7e3b6e1..00e211668c3269255926939324355792abd61c41 100644
--- a/lib/cubit/game_state.dart
+++ b/lib/cubit/game_state.dart
@@ -12,8 +12,4 @@ class GameState extends Equatable {
   List<dynamic> get props => <dynamic>[
         currentGame,
       ];
-
-  Map<String, dynamic> get values => <String, dynamic>{
-        'currentGame': currentGame,
-      };
 }
diff --git a/lib/cubit/settings_game_cubit.dart b/lib/cubit/settings_game_cubit.dart
index f70f2be39c047a76c59c76d016035007a48f8e11..8b61a56a1f8a041b97cf4d20abb9ed78a28e31e6 100644
--- a/lib/cubit/settings_game_cubit.dart
+++ b/lib/cubit/settings_game_cubit.dart
@@ -1,10 +1,9 @@
 import 'package:equatable/equatable.dart';
-import 'package:flutter/foundation.dart';
 import 'package:flutter/material.dart';
 import 'package:hydrated_bloc/hydrated_bloc.dart';
 
 import 'package:colors/config/default_game_settings.dart';
-import 'package:colors/models/settings_game.dart';
+import 'package:colors/models/settings/settings_game.dart';
 
 part 'settings_game_state.dart';
 
@@ -36,6 +35,7 @@ class GameSettingsCubit extends HydratedCubit<GameSettingsState> {
       case DefaultGameSettings.parameterCodeColorsCount:
         return GameSettings.getColorsValueFromUnsafe(state.settings.parameterColorsCount);
     }
+
     return '';
   }
 
diff --git a/lib/cubit/settings_game_state.dart b/lib/cubit/settings_game_state.dart
index b773dc69be12673b158e880e2d7e6e7bec465506..5acd85b44ba541e1c5e9c26af1c4be26a385b9ed 100644
--- a/lib/cubit/settings_game_state.dart
+++ b/lib/cubit/settings_game_state.dart
@@ -12,8 +12,4 @@ class GameSettingsState extends Equatable {
   List<dynamic> get props => <dynamic>[
         settings,
       ];
-
-  Map<String, dynamic> get values => <String, dynamic>{
-        'settings': settings,
-      };
 }
diff --git a/lib/cubit/settings_global_cubit.dart b/lib/cubit/settings_global_cubit.dart
index 41d3f191c94ff81119902bab88d3c8b376a11dff..360d535b818b56bb35f930da0d0ca8091ae93293 100644
--- a/lib/cubit/settings_global_cubit.dart
+++ b/lib/cubit/settings_global_cubit.dart
@@ -1,10 +1,9 @@
 import 'package:equatable/equatable.dart';
-import 'package:flutter/foundation.dart';
 import 'package:flutter/material.dart';
 import 'package:hydrated_bloc/hydrated_bloc.dart';
 
 import 'package:colors/config/default_global_settings.dart';
-import 'package:colors/models/settings_global.dart';
+import 'package:colors/models/settings/settings_global.dart';
 
 part 'settings_global_state.dart';
 
diff --git a/lib/cubit/settings_global_state.dart b/lib/cubit/settings_global_state.dart
index 4e4fbdf707b4e805f2092d0ca6a68a2de1c957c6..ebcddd700f252257223ca8e16c85202b04f3ff24 100644
--- a/lib/cubit/settings_global_state.dart
+++ b/lib/cubit/settings_global_state.dart
@@ -12,8 +12,4 @@ class GlobalSettingsState extends Equatable {
   List<dynamic> get props => <dynamic>[
         settings,
       ];
-
-  Map<String, dynamic> get values => <String, dynamic>{
-        'settings': settings,
-      };
 }
diff --git a/lib/main.dart b/lib/main.dart
index 4ffcc22f036fee392607c109e0a71a7098963cea..e9c7a92cec06c586428a291485fd750c2030731e 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,19 +1,20 @@
 import 'dart:io';
 
 import 'package:easy_localization/easy_localization.dart';
-import 'package:flutter_bloc/flutter_bloc.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:colors/ui/skeleton.dart';
 import 'package:colors/config/theme.dart';
 import 'package:colors/cubit/game_cubit.dart';
 import 'package:colors/cubit/nav_cubit.dart';
 import 'package:colors/cubit/settings_game_cubit.dart';
 import 'package:colors/cubit/settings_global_cubit.dart';
 import 'package:colors/cubit/theme_cubit.dart';
-import 'package:colors/ui/skeleton.dart';
 
 void main() async {
   // Initialize packages
@@ -25,18 +26,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 {
@@ -44,6 +44,11 @@ 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<NavCubit>(create: (context) => NavCubit()),
@@ -73,4 +78,24 @@ class MyApp extends StatelessWidget {
       ),
     );
   }
+
+  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');
+    }
+
+    return assets;
+  }
 }
diff --git a/lib/models/board.dart b/lib/models/game/board.dart
similarity index 95%
rename from lib/models/board.dart
rename to lib/models/game/board.dart
index 5d6ccd91949853ddce74c7965e82722c2e694fb1..8b7ff01a8c7fe388a3703326d85f9d6c4c7b2379 100644
--- a/lib/models/board.dart
+++ b/lib/models/game/board.dart
@@ -1,10 +1,11 @@
 import 'dart:math';
 
-import 'package:colors/models/cell.dart';
-import 'package:colors/models/settings_game.dart';
-import 'package:colors/models/types.dart';
+import 'package:colors/models/game/cell.dart';
+import 'package:colors/models/settings/settings_game.dart';
 import 'package:colors/utils/tools.dart';
 
+typedef BoardCells = List<List<Cell>>;
+
 class Board {
   final BoardCells cells;
 
@@ -12,7 +13,7 @@ class Board {
     required this.cells,
   });
 
-  factory Board.createNull() {
+  factory Board.createEmpty() {
     return Board(cells: []);
   }
 
diff --git a/lib/models/cell.dart b/lib/models/game/cell.dart
similarity index 100%
rename from lib/models/cell.dart
rename to lib/models/game/cell.dart
diff --git a/lib/models/game.dart b/lib/models/game/game.dart
similarity index 56%
rename from lib/models/game.dart
rename to lib/models/game/game.dart
index 28b61ead100e1d896811f67e9752e19fc79a9f82..23ffeb5efd6ea2d10a6e576ee32080ba2ea3ca64 100644
--- a/lib/models/game.dart
+++ b/lib/models/game/game.dart
@@ -1,46 +1,61 @@
 import 'package:colors/config/default_game_settings.dart';
-import 'package:colors/models/board.dart';
-import 'package:colors/models/settings_game.dart';
-import 'package:colors/models/settings_global.dart';
+import 'package:colors/models/game/board.dart';
+import 'package:colors/models/settings/settings_game.dart';
+import 'package:colors/models/settings/settings_global.dart';
 import 'package:colors/utils/tools.dart';
 
 class Game {
-  final Board board;
-  final GameSettings gameSettings;
-  final GlobalSettings globalSettings;
-  bool isRunning = false;
-  bool isFinished = false;
-  bool gameWon = false;
-
-  int maxMovesCount = 0;
-  int movesCount = 0;
-
-  int progress = 0;
-  int progressTotal = 0;
-  int progressDelta = 0;
-
-  bool animationInProgress = false;
-
   Game({
-    required this.board,
+    // Settings
     required this.gameSettings,
     required this.globalSettings,
+
+    // State
     this.isRunning = false,
+    this.isStarted = false,
     this.isFinished = false,
-    this.gameWon = false,
+    this.animationInProgress = false,
+
+    // Base data
+    required this.board,
+
+    // Game data
     this.maxMovesCount = 0,
     this.movesCount = 0,
     this.progress = 0,
     this.progressTotal = 0,
     this.progressDelta = 0,
-    this.animationInProgress = false,
+    this.gameWon = false,
   });
 
-  factory Game.createNull() {
+  // Settings
+  final GameSettings gameSettings;
+  final GlobalSettings globalSettings;
+
+  // State
+  bool isRunning;
+  bool isStarted;
+  bool isFinished;
+  bool animationInProgress;
+
+  // Base data
+  final Board board;
+
+  // Game data
+  int maxMovesCount;
+  int movesCount;
+  int progress;
+  int progressTotal;
+  int progressDelta;
+  bool gameWon;
+
+  factory Game.createEmpty() {
     return Game(
-      board: Board.createNull(),
+      // Settings
       gameSettings: GameSettings.createDefault(),
       globalSettings: GlobalSettings.createDefault(),
+      // Base data
+      board: Board.createEmpty(),
     );
   }
 
@@ -48,8 +63,8 @@ class Game {
     GameSettings? gameSettings,
     GlobalSettings? globalSettings,
   }) {
-    GameSettings newGameSettings = gameSettings ?? GameSettings.createDefault();
-    GlobalSettings newGlobalSettings = globalSettings ?? GlobalSettings.createDefault();
+    final GameSettings newGameSettings = gameSettings ?? GameSettings.createDefault();
+    final GlobalSettings newGlobalSettings = globalSettings ?? GlobalSettings.createDefault();
 
     final int baseMaxMovesCount =
         (30 * (newGameSettings.boardSize * newGameSettings.colorsCount) / (17 * 6)).round();
@@ -58,36 +73,44 @@ class Game {
             newGameSettings.difficultyLevel);
 
     return Game(
-      board: Board.createRandom(newGameSettings),
+      // Settings
       gameSettings: newGameSettings,
       globalSettings: newGlobalSettings,
+      // State
       isRunning: true,
-      isFinished: false,
-      gameWon: false,
+      // Base data
+      board: Board.createRandom(newGameSettings),
+      // Game data
       progress: 1,
       progressTotal: newGameSettings.boardSize * newGameSettings.boardSize,
       maxMovesCount: baseMaxMovesCount + deltaMovesCountFromLevel,
     );
   }
 
+  bool get canBeResumed => isStarted && !isFinished;
+
   void dump() {
     printlog('');
     printlog('## Current game dump:');
     printlog('');
+    printlog('$Game:');
+    printlog('  Settings');
     gameSettings.dump();
     globalSettings.dump();
-    printlog('');
+    printlog('  State');
+    printlog('    isRunning: $isRunning');
+    printlog('    isStarted: $isStarted');
+    printlog('    isFinished: $isFinished');
+    printlog('    animationInProgress: $animationInProgress');
+    printlog('  Base data');
     board.dump();
-    printlog('');
-    printlog('Game: ');
-    printlog('  isRunning: $isRunning');
-    printlog('  isFinished: $isFinished');
-    printlog('  gameWon: $gameWon');
-    printlog('  movesCount: $movesCount');
-    printlog('  maxMovesCount: $maxMovesCount');
-    printlog('  progress: $progress');
-    printlog('  progressTotal: $progressTotal');
-    printlog('  progressDelta: $progressDelta');
+    printlog('  Game data');
+    printlog('    maxMovesCount: $maxMovesCount');
+    printlog('    movesCount: $movesCount');
+    printlog('    progress: $progress');
+    printlog('    progressTotal: $progressTotal');
+    printlog('    progressDelta: $progressDelta');
+    printlog('    gameWon: $gameWon');
     printlog('');
   }
 
@@ -98,17 +121,23 @@ class Game {
 
   Map<String, dynamic>? toJson() {
     return <String, dynamic>{
-      'board': board.toJson(),
+      // Settings
       'gameSettings': gameSettings.toJson(),
       'globalSettings': globalSettings.toJson(),
+      // State
       'isRunning': isRunning,
+      'isStarted': isStarted,
       'isFinished': isFinished,
-      'gameWon': gameWon,
-      'movesCount': movesCount,
+      'animationInProgress': animationInProgress,
+      // Base data
+      'board': board.toJson(),
+      // Game data
       'maxMovesCount': maxMovesCount,
+      'movesCount': movesCount,
       'progress': progress,
       'progressTotal': progressTotal,
       'progressDelta': progressDelta,
+      'gameWon': gameWon,
     };
   }
 }
diff --git a/lib/models/settings_game.dart b/lib/models/settings/settings_game.dart
similarity index 98%
rename from lib/models/settings_game.dart
rename to lib/models/settings/settings_game.dart
index b5227e80ccf1589646a06dc5e7e186fbc4336e26..2c5cc8e9a222f2cae56b5622030ac1d024f78845 100644
--- a/lib/models/settings_game.dart
+++ b/lib/models/settings/settings_game.dart
@@ -1,5 +1,5 @@
 import 'package:colors/config/default_game_settings.dart';
-import 'package:colors/utils/tools.dart';
+import 'package:colors/utils/tools.dart';     
 
 class GameSettings {
   String difficultyLevel;
diff --git a/lib/models/settings_global.dart b/lib/models/settings/settings_global.dart
similarity index 94%
rename from lib/models/settings_global.dart
rename to lib/models/settings/settings_global.dart
index 09994f4124e0761b2da152295f837a0d535514ec..4dd791da096642331f4741c50e50a70734707a02 100644
--- a/lib/models/settings_global.dart
+++ b/lib/models/settings/settings_global.dart
@@ -1,5 +1,5 @@
 import 'package:colors/config/default_global_settings.dart';
-import 'package:colors/utils/tools.dart';
+import 'package:colors/utils/tools.dart';     
 
 class GlobalSettings {
   String skin;
diff --git a/lib/models/types.dart b/lib/models/types.dart
deleted file mode 100644
index 339bfe66331369eb92a4113be046f7a36785b9c6..0000000000000000000000000000000000000000
--- a/lib/models/types.dart
+++ /dev/null
@@ -1,3 +0,0 @@
-import 'package:colors/models/cell.dart';
-
-typedef BoardCells = List<List<Cell>>;
diff --git a/lib/ui/game/game_bottom.dart b/lib/ui/game/game_bottom.dart
new file mode 100644
index 0000000000000000000000000000000000000000..309ee2b4fc189d544b39efa70a0eed05ae0c3af6
--- /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:colors/cubit/game_cubit.dart';
+import 'package:colors/models/game/game.dart';
+import 'package:colors/ui/widgets/game/select_color_bar.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 SelectColorBar() : const SizedBox.shrink();
+      },
+    );
+  }
+}
diff --git a/lib/ui/widgets/game/message_game_end.dart b/lib/ui/game/game_end.dart
similarity index 51%
rename from lib/ui/widgets/game/message_game_end.dart
rename to lib/ui/game/game_end.dart
index 2a5cae825069b95e1c4cc9865c1c6acf678516ee..c5847410d75818a2acdce36315a20fd1e84b0fcf 100644
--- a/lib/ui/widgets/game/message_game_end.dart
+++ b/lib/ui/game/game_end.dart
@@ -1,12 +1,12 @@
-import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
 
 import 'package:colors/cubit/game_cubit.dart';
-import 'package:colors/models/game.dart';
-import 'package:colors/ui/widgets/game/button_game_restart.dart';
+import 'package:colors/models/game/game.dart';
+import 'package:colors/ui/widgets/actions/button_game_quit.dart';
 
-class EndGameMessage extends StatelessWidget {
-  const EndGameMessage({super.key});
+class GameEndWidget extends StatelessWidget {
+  const GameEndWidget({super.key});
 
   @override
   Widget build(BuildContext context) {
@@ -14,15 +14,9 @@ class EndGameMessage extends StatelessWidget {
       builder: (BuildContext context, GameState gameState) {
         final Game currentGame = gameState.currentGame;
 
-        String decorationImageAssetName = '';
-        if (currentGame.gameWon) {
-          decorationImageAssetName = 'assets/icons/game_win.png';
-        } else {
-          decorationImageAssetName = 'assets/icons/game_fail.png';
-        }
-
         final Image decorationImage = Image(
-          image: AssetImage(decorationImageAssetName),
+          image: AssetImage(
+              currentGame.gameWon ? 'assets/ui/game_win.png' : 'assets/ui/game_fail.png'),
           fit: BoxFit.fill,
         );
 
@@ -34,11 +28,19 @@ class EndGameMessage extends StatelessWidget {
             children: [
               TableRow(
                 children: [
-                  Column(children: [decorationImage]),
-                  Column(children: [decorationImage]),
-                  const Column(children: [RestartGameButton()]),
-                  Column(children: [decorationImage]),
-                  Column(children: [decorationImage]),
+                  Column(
+                    children: [decorationImage],
+                  ),
+                  Column(
+                    children: [
+                      currentGame.animationInProgress == true
+                          ? 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..b9d6970944d7fc3cf6b580a42432f08f9796326c
--- /dev/null
+++ b/lib/ui/game/game_top.dart
@@ -0,0 +1,32 @@
+import 'package:flutter/material.dart';
+
+import 'package:colors/ui/widgets/indicators/indicator_max_moves.dart';
+import 'package:colors/ui/widgets/indicators/indicator_moves_count.dart';
+import 'package:colors/ui/widgets/indicators/indicator_progress.dart';
+
+class GameTopWidget extends StatelessWidget {
+  const GameTopWidget({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return Table(
+      children: const [
+        TableRow(
+          children: [
+            Column(
+              children: [
+                GameIndicatorMovesCount(),
+              ],
+            ),
+            Column(
+              children: [
+                GameIndicatorMaxMovesCount(),
+                GameIndicatorProgress(),
+              ],
+            ),
+          ],
+        ),
+      ],
+    );
+  }
+}
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/widgets/helpers/outlined_text_widget.dart b/lib/ui/helpers/outlined_text_widget.dart
similarity index 69%
rename from lib/ui/widgets/helpers/outlined_text_widget.dart
rename to lib/ui/helpers/outlined_text_widget.dart
index 8e33709bd71085ea7a64084a231f692953af203d..7f5d58b79526f42799105fbee3b37d8c1ec1d983 100644
--- a/lib/ui/widgets/helpers/outlined_text_widget.dart
+++ b/lib/ui/helpers/outlined_text_widget.dart
@@ -1,22 +1,24 @@
 import 'package:flutter/material.dart';
 
+import 'package:colors/utils/color_extensions.dart';
+
 class OutlinedText extends StatelessWidget {
   const OutlinedText({
     super.key,
     required this.text,
     required this.fontSize,
     required this.textColor,
-    required this.outlineColor,
+    this.outlineColor,
   });
 
   final String text;
   final double fontSize;
   final Color textColor;
-  final Color outlineColor;
+  final Color? outlineColor;
 
   @override
   Widget build(BuildContext context) {
-    final double delta = fontSize / 35;
+    final double delta = fontSize / 30;
 
     return Text(
       text,
@@ -28,19 +30,19 @@ class OutlinedText extends StatelessWidget {
         shadows: [
           Shadow(
             offset: Offset(-delta, -delta),
-            color: outlineColor,
+            color: outlineColor ?? textColor.darken(),
           ),
           Shadow(
             offset: Offset(delta, -delta),
-            color: outlineColor,
+            color: outlineColor ?? textColor.darken(),
           ),
           Shadow(
             offset: Offset(delta, delta),
-            color: outlineColor,
+            color: outlineColor ?? textColor.darken(),
           ),
           Shadow(
             offset: Offset(-delta, delta),
-            color: outlineColor,
+            color: outlineColor ?? textColor.darken(),
           ),
         ],
       ),
diff --git a/lib/ui/layouts/game_layout.dart b/lib/ui/layouts/game_layout.dart
new file mode 100644
index 0000000000000000000000000000000000000000..2645e80aaf465bc04ebc357a65a99571e476bdfb
--- /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:colors/cubit/game_cubit.dart';
+import 'package:colors/models/game/game.dart';
+import 'package:colors/ui/game/game_bottom.dart';
+import 'package:colors/ui/game/game_end.dart';
+import 'package:colors/ui/game/game_top.dart';
+import 'package:colors/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/widgets/parameters.dart b/lib/ui/layouts/parameters_layout.dart
similarity index 55%
rename from lib/ui/widgets/parameters.dart
rename to lib/ui/layouts/parameters_layout.dart
index 55525a9b2402805ed513f789958c568493f28089..a1bbda5d4eb8ef04e4d7349124b9433241fcf2f4 100644
--- a/lib/ui/widgets/parameters.dart
+++ b/lib/ui/layouts/parameters_layout.dart
@@ -1,15 +1,20 @@
-import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
 
 import 'package:colors/config/default_game_settings.dart';
 import 'package:colors/config/default_global_settings.dart';
 import 'package:colors/cubit/settings_game_cubit.dart';
 import 'package:colors/cubit/settings_global_cubit.dart';
-import 'package:colors/ui/painters/parameter_painter.dart';
-import 'package:colors/ui/widgets/button_game_start_new.dart';
+import 'package:colors/ui/parameters/parameter_image.dart';
+import 'package:colors/ui/parameters/parameter_painter.dart';
+import 'package:colors/ui/widgets/actions/button_delete_saved_game.dart';
+import 'package:colors/ui/widgets/actions/button_game_start_new.dart';
+import 'package:colors/ui/widgets/actions/button_resume_saved_game.dart';
+
+class ParametersLayout extends StatelessWidget {
+  const ParametersLayout({super.key, required this.canResume});
 
-class Parameters extends StatelessWidget {
-  const Parameters({super.key});
+  final bool canResume;
 
   final double separatorHeight = 8.0;
 
@@ -17,8 +22,6 @@ class Parameters extends StatelessWidget {
   Widget build(BuildContext context) {
     final List<Widget> lines = [];
 
-    lines.add(SizedBox(height: separatorHeight));
-
     // Game settings
     for (String code in DefaultGameSettings.availableParameters) {
       lines.add(Row(
@@ -33,7 +36,24 @@ class Parameters extends StatelessWidget {
     }
 
     lines.add(SizedBox(height: separatorHeight));
-    lines.add(const Expanded(child: StartNewGameButton()));
+
+    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
@@ -85,28 +105,41 @@ class Parameters extends StatelessWidget {
               final bool isActive = (value == currentValue);
 
               final double displayWidth = MediaQuery.of(context).size.width;
-              final double itemWidth = displayWidth / availableValues.length - 30;
+              final double itemWidth = displayWidth / availableValues.length - 26;
+
+              final bool displayedWithAssets =
+                  DefaultGlobalSettings.displayedWithAssets.contains(code) ||
+                      DefaultGameSettings.displayedWithAssets.contains(code);
 
               return TextButton(
                 child: Container(
-                  margin: const EdgeInsets.all(0),
-                  padding: const EdgeInsets.all(0),
-                  child: CustomPaint(
-                    size: Size(itemWidth, itemWidth),
-                    willChange: false,
-                    painter: ParameterPainter(
-                      code: code,
-                      value: value,
-                      isSelected: isActive,
-                      gameSettings: gameSettingsState.settings,
-                      globalSettings: globalSettingsState.settings,
-                    ),
-                    isComplex: true,
-                  ),
+                  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),
+                onPressed: () {
+                  isGlobal
+                      ? globalSettingsCubit.setParameterValue(code, value)
+                      : gameSettingsCubit.setParameterValue(code, value);
+                },
               );
             },
           );
diff --git a/lib/ui/painters/board_painter.dart b/lib/ui/painters/board_painter.dart
index 42bb2a2a5f7e284f9bc2bd9fb6cda486ea07fe50..2dfb282ee6b100ee2166d539a362dc5a4b521ac6 100644
--- a/lib/ui/painters/board_painter.dart
+++ b/lib/ui/painters/board_painter.dart
@@ -1,9 +1,9 @@
 import 'package:flutter/material.dart';
 
-import 'package:colors/models/cell.dart';
-import 'package:colors/models/game.dart';
-import 'package:colors/models/types.dart';
-import 'package:colors/utils/color_theme.dart';
+import 'package:colors/config/color_theme.dart';
+import 'package:colors/models/game/board.dart';
+import 'package:colors/models/game/cell.dart';
+import 'package:colors/models/game/game.dart';
 
 class BoardPainter extends CustomPainter {
   const BoardPainter({
@@ -19,6 +19,7 @@ class BoardPainter extends CustomPainter {
     final int boardSize = game.gameSettings.boardSize;
     final BoardCells cells = game.board.cells;
     final double cellSize = size.width / boardSize;
+    const double borderSize = 3;
 
     // background
     for (var row = 0; row < boardSize; row++) {
@@ -34,17 +35,17 @@ class BoardPainter extends CustomPainter {
         cellPaintBackground.color = Color(colorCode);
         cellPaintBackground.style = PaintingStyle.fill;
 
-        final Rect cellBackground =
-            Rect.fromPoints(Offset(x - 1, y - 1), Offset(x + cellSize + 2, y + cellSize + 2));
+        final Rect cellBackground = Rect.fromPoints(
+            Offset(x - (borderSize / 2), y - (borderSize / 2)),
+            Offset(x + (borderSize / 2) + cellSize, y + (borderSize / 2) + cellSize));
 
         canvas.drawRect(cellBackground, cellPaintBackground);
       }
     }
 
     // borders
-    const double borderSize = 2;
     final cellPaintBorder = Paint();
-    cellPaintBorder.color = colorScheme.onBackground;
+    cellPaintBorder.color = colorScheme.onSurface;
     cellPaintBorder.strokeWidth = borderSize;
     cellPaintBorder.strokeCap = StrokeCap.round;
 
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/painters/parameter_painter.dart b/lib/ui/parameters/parameter_painter.dart
similarity index 96%
rename from lib/ui/painters/parameter_painter.dart
rename to lib/ui/parameters/parameter_painter.dart
index fb216ed2c3bd02cb57c27c8121ba47de02e637d7..4d9273cf11baedc2f8703e60044f86a9a476b6f3 100644
--- a/lib/ui/painters/parameter_painter.dart
+++ b/lib/ui/parameters/parameter_painter.dart
@@ -2,12 +2,12 @@ import 'dart:math';
 
 import 'package:flutter/material.dart';
 
+import 'package:colors/config/color_theme.dart';
 import 'package:colors/config/default_game_settings.dart';
 import 'package:colors/config/default_global_settings.dart';
-import 'package:colors/models/settings_game.dart';
-import 'package:colors/models/settings_global.dart';
+import 'package:colors/models/settings/settings_game.dart';
+import 'package:colors/models/settings/settings_global.dart';
 import 'package:colors/utils/color_extensions.dart';
-import 'package:colors/utils/color_theme.dart';
 import 'package:colors/utils/tools.dart';
 
 class ParameterPainter extends CustomPainter {
@@ -38,7 +38,7 @@ class ParameterPainter extends CustomPainter {
     paint.style = PaintingStyle.stroke;
     paint.color = isSelected ? borderColorEnabled : borderColorDisabled;
     paint.strokeJoin = StrokeJoin.round;
-    paint.strokeWidth = 20 / 100 * canvasSize;
+    paint.strokeWidth = 10;
     canvas.drawRect(
         Rect.fromPoints(const Offset(0, 0), Offset(canvasSize, canvasSize)), paint);
 
@@ -75,7 +75,7 @@ class ParameterPainter extends CustomPainter {
   ) {
     final paint = Paint();
     paint.strokeJoin = StrokeJoin.round;
-    paint.strokeWidth = 3 / 100 * size;
+    paint.strokeWidth = 3;
 
     paint.color = Colors.grey;
     paint.style = PaintingStyle.fill;
@@ -92,6 +92,7 @@ class ParameterPainter extends CustomPainter {
     final textPainter = TextPainter(
       text: textSpan,
       textDirection: TextDirection.ltr,
+      textAlign: TextAlign.center,
     );
     textPainter.layout();
     textPainter.paint(
@@ -160,6 +161,7 @@ class ParameterPainter extends CustomPainter {
     final textPainter = TextPainter(
       text: textSpan,
       textDirection: TextDirection.ltr,
+      textAlign: TextAlign.center,
     );
     textPainter.layout();
 
@@ -261,7 +263,7 @@ class ParameterPainter extends CustomPainter {
 
     final paint = Paint();
     paint.strokeJoin = StrokeJoin.round;
-    paint.strokeWidth = 3 / 100 * size;
+    paint.strokeWidth = 3;
 
     // Colored background
     paint.color = backgroundColor;
@@ -318,6 +320,7 @@ class ParameterPainter extends CustomPainter {
     final textPainter = TextPainter(
       text: textSpan,
       textDirection: TextDirection.ltr,
+      textAlign: TextAlign.center,
     );
     textPainter.layout();
     textPainter.paint(
@@ -339,7 +342,7 @@ class ParameterPainter extends CustomPainter {
 
     final paint = Paint();
     paint.strokeJoin = StrokeJoin.round;
-    paint.strokeWidth = 3 / 100 * size;
+    paint.strokeWidth = 3;
 
     // Colored background
     paint.color = backgroundColor;
diff --git a/lib/ui/screens/page_about.dart b/lib/ui/screens/page_about.dart
index a8602ef37637e6f640625560da6a31e461f11238..0a67bb7eaefeef5ae0f20d0a3b203b32577943cc 100644
--- a/lib/ui/screens/page_about.dart
+++ b/lib/ui/screens/page_about.dart
@@ -2,37 +2,40 @@ import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/material.dart';
 import 'package:package_info_plus/package_info_plus.dart';
 
-import 'package:colors/ui/widgets/helpers/header_app.dart';
+import 'package:colors/ui/helpers/app_titles.dart';
 
 class PageAbout extends StatelessWidget {
   const PageAbout({super.key});
 
   @override
   Widget build(BuildContext context) {
-    return Column(
-      mainAxisAlignment: MainAxisAlignment.start,
-      crossAxisAlignment: CrossAxisAlignment.start,
-      mainAxisSize: MainAxisSize.max,
-      children: <Widget>[
-        const SizedBox(height: 8),
-        const AppHeader(text: 'about_title'),
-        const Text('about_content').tr(),
-        FutureBuilder<PackageInfo>(
-          future: PackageInfo.fromPlatform(),
-          builder: (context, snapshot) {
-            switch (snapshot.connectionState) {
-              case ConnectionState.done:
-                return const Text('about_version').tr(
-                  namedArgs: {
-                    'version': snapshot.data!.version,
-                  },
-                );
-              default:
-                return const SizedBox();
-            }
-          },
-        ),
-      ],
+    return Padding(
+      padding: const EdgeInsets.symmetric(horizontal: 8),
+      child: Column(
+        mainAxisAlignment: MainAxisAlignment.start,
+        crossAxisAlignment: CrossAxisAlignment.start,
+        mainAxisSize: MainAxisSize.max,
+        children: <Widget>[
+          const SizedBox(height: 8),
+          const AppTitle(text: 'about_title'),
+          const Text('about_content').tr(),
+          FutureBuilder<PackageInfo>(
+            future: PackageInfo.fromPlatform(),
+            builder: (context, snapshot) {
+              switch (snapshot.connectionState) {
+                case ConnectionState.done:
+                  return const Text('about_version').tr(
+                    namedArgs: {
+                      'version': snapshot.data!.version,
+                    },
+                  );
+                default:
+                  return const SizedBox();
+              }
+            },
+          ),
+        ],
+      ),
     );
   }
 }
diff --git a/lib/ui/screens/page_game.dart b/lib/ui/screens/page_game.dart
index d3a64ac427c48bfbffc62f0f93e4f2793aaadcd1..78a33e0315250296f10d591780838974c7cac6ff 100644
--- a/lib/ui/screens/page_game.dart
+++ b/lib/ui/screens/page_game.dart
@@ -1,9 +1,10 @@
-import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
 
 import 'package:colors/cubit/game_cubit.dart';
-import 'package:colors/ui/widgets/game/game.dart';
-import 'package:colors/ui/widgets/parameters.dart';
+import 'package:colors/models/game/game.dart';
+import 'package:colors/ui/layouts/game_layout.dart';
+import 'package:colors/ui/layouts/parameters_layout.dart';
 
 class PageGame extends StatelessWidget {
   const PageGame({super.key});
@@ -11,8 +12,13 @@ class PageGame extends StatelessWidget {
   @override
   Widget build(BuildContext context) {
     return BlocBuilder<GameCubit, GameState>(
-        builder: (BuildContext context, GameState gameState) {
-      return gameState.currentGame.isRunning ? const GameWidget() : const Parameters();
-    });
+      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/page_settings.dart b/lib/ui/screens/page_settings.dart
index d559f9566662c9f3bffaaf35a184e6b79a04feda..c1771c7a53821bfb96d8db81f15cecf818770c39 100644
--- a/lib/ui/screens/page_settings.dart
+++ b/lib/ui/screens/page_settings.dart
@@ -1,23 +1,26 @@
 import 'package:flutter/material.dart';
 
-import 'package:colors/ui/widgets/helpers/header_app.dart';
-import 'package:colors/ui/widgets/settings/settings_form.dart';
+import 'package:colors/ui/helpers/app_titles.dart';
+import 'package:colors/ui/settings/settings_form.dart';
 
 class PageSettings extends StatelessWidget {
   const PageSettings({super.key});
 
   @override
   Widget build(BuildContext context) {
-    return const Column(
-      mainAxisAlignment: MainAxisAlignment.start,
-      crossAxisAlignment: CrossAxisAlignment.start,
-      mainAxisSize: MainAxisSize.max,
-      children: <Widget>[
-        SizedBox(height: 8),
-        AppHeader(text: 'settings_title'),
-        SizedBox(height: 8),
-        SettingsForm(),
-      ],
+    return const Padding(
+      padding: EdgeInsets.symmetric(horizontal: 8),
+      child: Column(
+        mainAxisAlignment: MainAxisAlignment.start,
+        crossAxisAlignment: CrossAxisAlignment.start,
+        mainAxisSize: MainAxisSize.max,
+        children: <Widget>[
+          SizedBox(height: 8),
+          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 69d9cebaa83e6ac8d4a222ff5bdaa08a900c3fa7..9c360cc67be68635eb3957d0709f73a15e986f53 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:colors/ui/widgets/settings/theme_card.dart';
+import 'package:colors/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
index 834c67dbd317b84767c411f3a6b1822cfa1ed9f1..5fd7bd79e680c32a419bc9bea0c80e1fdec49348 100644
--- a/lib/ui/widgets/settings/theme_card.dart
+++ b/lib/ui/settings/theme_card.dart
@@ -1,5 +1,5 @@
-import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
 
 import 'package:colors/cubit/theme_cubit.dart';
 
diff --git a/lib/ui/skeleton.dart b/lib/ui/skeleton.dart
index eaec6f6314be0af2e0ecb1a955db10b90b76f4d8..182e5fc0cc1cf09fc4086c0e957c082f7a2dde85 100644
--- a/lib/ui/skeleton.dart
+++ b/lib/ui/skeleton.dart
@@ -1,5 +1,5 @@
-import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
 
 import 'package:colors/config/menu.dart';
 import 'package:colors/cubit/nav_cubit.dart';
@@ -14,17 +14,21 @@ class SkeletonScreen extends StatelessWidget {
       appBar: const GlobalAppBar(),
       extendBodyBehindAppBar: false,
       body: Material(
-        color: Theme.of(context).colorScheme.background,
+        color: Theme.of(context).colorScheme.surface,
         child: BlocBuilder<NavCubit, int>(
           builder: (BuildContext context, int pageIndex) {
             return Padding(
-              padding: const EdgeInsets.symmetric(horizontal: 4),
+              padding: const EdgeInsets.only(
+                top: 8,
+                left: 2,
+                right: 2,
+              ),
               child: Menu.getPageWidget(pageIndex),
             );
           },
         ),
       ),
-      backgroundColor: Theme.of(context).colorScheme.background,
+      backgroundColor: Theme.of(context).colorScheme.surface,
     );
   }
 }
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..6fc2c16f62fe5275b80f733273a49613e4b49d30
--- /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:colors/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..7d07274378b9b71588dfda2e23f71c4256212482
--- /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:colors/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/button_game_start_new.dart b/lib/ui/widgets/actions/button_game_start_new.dart
similarity index 72%
rename from lib/ui/widgets/button_game_start_new.dart
rename to lib/ui/widgets/actions/button_game_start_new.dart
index 613d2fb7cbfca7241b2c7fbf788825a92d412141..2a94abe91c33186c930d2181d98956b4ef803d2d 100644
--- a/lib/ui/widgets/button_game_start_new.dart
+++ b/lib/ui/widgets/actions/button_game_start_new.dart
@@ -14,17 +14,17 @@ class StartNewGameButton extends StatelessWidget {
       builder: (BuildContext context, GameSettingsState gameSettingsState) {
         return BlocBuilder<GlobalSettingsCubit, GlobalSettingsState>(
           builder: (BuildContext context, GlobalSettingsState globalSettingsState) {
-            final GameCubit gameCubit = BlocProvider.of<GameCubit>(context);
-
             return TextButton(
               child: const Image(
-                image: AssetImage('assets/icons/button_start.png'),
+                image: AssetImage('assets/ui/button_start.png'),
                 fit: BoxFit.fill,
               ),
-              onPressed: () => gameCubit.startNewGame(
-                gameSettings: gameSettingsState.settings,
-                globalSettings: globalSettingsState.settings,
-              ),
+              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..fe603c1c1012fe8429f796a8d884a8e2f46310ae
--- /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:colors/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/game/button_game_restart.dart b/lib/ui/widgets/game/button_game_restart.dart
deleted file mode 100644
index dce403b3cfb2690b2f5abcf0bd9e4559654779c6..0000000000000000000000000000000000000000
--- a/lib/ui/widgets/game/button_game_restart.dart
+++ /dev/null
@@ -1,24 +0,0 @@
-import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:flutter/material.dart';
-
-import 'package:colors/cubit/game_cubit.dart';
-
-class RestartGameButton extends StatelessWidget {
-  const RestartGameButton({super.key});
-
-  @override
-  Widget build(BuildContext context) {
-    final GameCubit gameCubit = BlocProvider.of<GameCubit>(context);
-
-    return TextButton(
-      style: ButtonStyle(
-        padding: MaterialStateProperty.all<EdgeInsets>(const EdgeInsets.all(0)),
-      ),
-      child: const Image(
-        image: AssetImage('assets/icons/button_back.png'),
-        fit: BoxFit.fill,
-      ),
-      onPressed: () => gameCubit.quitGame(),
-    );
-  }
-}
diff --git a/lib/ui/widgets/game/cell.dart b/lib/ui/widgets/game/cell.dart
new file mode 100644
index 0000000000000000000000000000000000000000..2120b645a789d5c320a94b63f1f790e8614a8904
--- /dev/null
+++ b/lib/ui/widgets/game/cell.dart
@@ -0,0 +1,56 @@
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:flutter/material.dart';
+
+import 'package:colors/config/color_theme.dart';
+import 'package:colors/cubit/game_cubit.dart';
+import 'package:colors/models/game/cell.dart';
+import 'package:colors/models/game/game.dart';
+
+class CellWidget extends StatelessWidget {
+  const CellWidget({
+    super.key,
+    required this.cell,
+    required this.itemWidth,
+  });
+
+  final Cell cell;
+  final double itemWidth;
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        final Game currentGame = gameState.currentGame;
+
+        final ColorScheme colorScheme = Theme.of(context).colorScheme;
+
+        final String skin = currentGame.globalSettings.skin;
+        final squareColor = Color(ColorTheme.getColorCode(skin, cell.value));
+
+        return Container(
+          decoration: BoxDecoration(
+            border: Border.all(
+              color: colorScheme.onSurface,
+              width: 4,
+            ),
+          ),
+          child: GestureDetector(
+            child: Container(
+              color: squareColor,
+              padding: const EdgeInsets.all(3),
+              child: SizedBox.square(
+                dimension: itemWidth - 19,
+              ),
+            ),
+            onTap: () {
+              if (!currentGame.animationInProgress &&
+                  currentGame.board.getFirstCellValue() != cell.value) {
+                BlocProvider.of<GameCubit>(context).fillBoardFromFirstCell(cell.value);
+              }
+            },
+          ),
+        );
+      },
+    );
+  }
+}
diff --git a/lib/ui/widgets/game/cell_interactive.dart b/lib/ui/widgets/game/cell_interactive.dart
deleted file mode 100644
index 40b67d01db9fb21a8b080f5d7ebc3f40bf6dc29d..0000000000000000000000000000000000000000
--- a/lib/ui/widgets/game/cell_interactive.dart
+++ /dev/null
@@ -1,55 +0,0 @@
-import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:flutter/material.dart';
-
-import 'package:colors/cubit/game_cubit.dart';
-import 'package:colors/models/cell.dart';
-import 'package:colors/models/game.dart';
-import 'package:colors/utils/color_theme.dart';
-
-class InteractiveCell extends StatelessWidget {
-  const InteractiveCell({
-    super.key,
-    required this.cell,
-    required this.colorScheme,
-    required this.currentGame,
-    required this.itemWidth,
-  });
-
-  final Cell cell;
-  final ColorScheme colorScheme;
-  final Game currentGame;
-  final double itemWidth;
-
-  @override
-  Widget build(BuildContext context) {
-    final String skin = currentGame.globalSettings.skin;
-    final squareColor = Color(ColorTheme.getColorCode(skin, cell.value));
-
-    return Container(
-      margin: const EdgeInsets.all(2),
-      decoration: BoxDecoration(
-        border: Border.all(
-          color: colorScheme.onSurface,
-          width: 3,
-        ),
-      ),
-      child: GestureDetector(
-        child: Container(
-          color: squareColor,
-          padding: const EdgeInsets.all(4),
-          child: SizedBox.square(
-            dimension: itemWidth - 19,
-          ),
-        ),
-        onTap: () {
-          final GameCubit gameCubit = BlocProvider.of<GameCubit>(context);
-
-          if (!currentGame.animationInProgress &&
-              currentGame.board.getFirstCellValue() != cell.value) {
-            gameCubit.fillBoardFromFirstCell(cell.value);
-          }
-        },
-      ),
-    );
-  }
-}
diff --git a/lib/ui/widgets/game/game.dart b/lib/ui/widgets/game/game.dart
deleted file mode 100644
index 870676c265cf9d68145f51223fbcb05494086d8e..0000000000000000000000000000000000000000
--- a/lib/ui/widgets/game/game.dart
+++ /dev/null
@@ -1,37 +0,0 @@
-import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:flutter/material.dart';
-
-import 'package:colors/cubit/game_cubit.dart';
-import 'package:colors/models/game.dart';
-import 'package:colors/ui/widgets/game/game_board.dart';
-import 'package:colors/ui/widgets/game/game_top_indicator.dart';
-import 'package:colors/ui/widgets/game/message_game_end.dart';
-import 'package:colors/ui/widgets/game/select_color_bar.dart';
-
-class GameWidget extends StatelessWidget {
-  const GameWidget({super.key});
-
-  @override
-  Widget build(BuildContext context) {
-    return BlocBuilder<GameCubit, GameState>(
-      builder: (BuildContext context, GameState gameState) {
-        final Game currentGame = gameState.currentGame;
-
-        return Column(
-          mainAxisAlignment: MainAxisAlignment.start,
-          crossAxisAlignment: CrossAxisAlignment.center,
-          children: [
-            const SizedBox(height: 8),
-            const GameTopIndicatorWidget(),
-            const SizedBox(height: 2),
-            const GameBoard(),
-            const Expanded(
-              child: SizedBox(height: 2),
-            ),
-            currentGame.isFinished ? const EndGameMessage() : const SelectColorBar(),
-          ],
-        );
-      },
-    );
-  }
-}
diff --git a/lib/ui/widgets/game/game_board.dart b/lib/ui/widgets/game/game_board.dart
index 385fc17de52368f835b2d83fe25531dc40ce523d..694b1be28e8596191a8a5c36d839a0f4efac1aa3 100644
--- a/lib/ui/widgets/game/game_board.dart
+++ b/lib/ui/widgets/game/game_board.dart
@@ -2,11 +2,11 @@ import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:flutter/material.dart';
 
 import 'package:colors/cubit/game_cubit.dart';
-import 'package:colors/models/game.dart';
+import 'package:colors/models/game/game.dart';
 import 'package:colors/ui/painters/board_painter.dart';
 
-class GameBoard extends StatelessWidget {
-  const GameBoard({super.key});
+class GameBoardWidget extends StatelessWidget {
+  const GameBoardWidget({super.key});
 
   @override
   Widget build(BuildContext context) {
@@ -24,8 +24,7 @@ class GameBoard extends StatelessWidget {
             final int row = yTap ~/ (boardWidth / boardSize);
             final int cellValue = currentGame.board.getCellValue(col, row);
 
-            final GameCubit gameCubit = BlocProvider.of<GameCubit>(context);
-            gameCubit.fillBoardFromFirstCell(cellValue);
+            BlocProvider.of<GameCubit>(context).fillBoardFromFirstCell(cellValue);
           },
           child: CustomPaint(
             size: Size(boardWidth, boardWidth),
diff --git a/lib/ui/widgets/game/game_top_indicator.dart b/lib/ui/widgets/game/game_top_indicator.dart
deleted file mode 100644
index 93948cd0e17629e81e6f7a90ac1b3de091b3969d..0000000000000000000000000000000000000000
--- a/lib/ui/widgets/game/game_top_indicator.dart
+++ /dev/null
@@ -1,70 +0,0 @@
-import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:flutter/material.dart';
-
-import 'package:colors/cubit/game_cubit.dart';
-import 'package:colors/models/game.dart';
-
-class GameTopIndicatorWidget extends StatelessWidget {
-  const GameTopIndicatorWidget({super.key});
-
-  @override
-  Widget build(BuildContext context) {
-    return BlocBuilder<GameCubit, GameState>(
-      builder: (BuildContext context, GameState gameState) {
-        final Game currentGame = gameState.currentGame;
-
-        String progressIndicator = '${currentGame.progress}/${currentGame.progressTotal}';
-
-        if (currentGame.movesCount > 0) {
-          progressIndicator += ' (+${currentGame.progressDelta})';
-        }
-
-        Color maxMovesCountColor = Colors.grey;
-        if (currentGame.movesCount > currentGame.maxMovesCount) {
-          maxMovesCountColor = Colors.red;
-        }
-
-        return Table(
-          children: [
-            TableRow(
-              children: [
-                Column(
-                  children: [
-                    Text(
-                      currentGame.movesCount.toString(),
-                      style: TextStyle(
-                        fontSize: 35,
-                        fontWeight: FontWeight.w600,
-                        color: Theme.of(context).colorScheme.primary,
-                      ),
-                    )
-                  ],
-                ),
-                Column(
-                  children: [
-                    Text(
-                      '(max: ${currentGame.maxMovesCount})',
-                      style: TextStyle(
-                        fontSize: 15,
-                        fontWeight: FontWeight.w600,
-                        color: maxMovesCountColor,
-                      ),
-                    ),
-                    Text(
-                      progressIndicator,
-                      style: const TextStyle(
-                        fontSize: 15,
-                        fontWeight: FontWeight.w600,
-                        color: Colors.green,
-                      ),
-                    ),
-                  ],
-                ),
-              ],
-            ),
-          ],
-        );
-      },
-    );
-  }
-}
diff --git a/lib/ui/widgets/game/select_color_bar.dart b/lib/ui/widgets/game/select_color_bar.dart
index 3b8addb9f96cbe10f766008599da87eb98ad518a..7f927e70fc9f7ee5ca2c6a6fed3e9fb2b1806905 100644
--- a/lib/ui/widgets/game/select_color_bar.dart
+++ b/lib/ui/widgets/game/select_color_bar.dart
@@ -2,8 +2,9 @@ import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:flutter/material.dart';
 
 import 'package:colors/cubit/game_cubit.dart';
-import 'package:colors/models/cell.dart';
-import 'package:colors/ui/widgets/game/cell_interactive.dart';
+import 'package:colors/models/game/cell.dart';
+import 'package:colors/models/game/game.dart';
+import 'package:colors/ui/widgets/game/cell.dart';
 
 class SelectColorBar extends StatelessWidget {
   const SelectColorBar({super.key});
@@ -12,28 +13,21 @@ class SelectColorBar extends StatelessWidget {
   Widget build(BuildContext context) {
     return BlocBuilder<GameCubit, GameState>(
       builder: (BuildContext context, GameState gameState) {
+        final Game currentGame = gameState.currentGame;
+
+        final int colorsCount = currentGame.gameSettings.colorsCount;
         final double blockWidth = MediaQuery.of(context).size.width;
-        final ColorScheme colorScheme = Theme.of(context).colorScheme;
-        final int maxValue = gameState.currentGame.gameSettings.colorsCount;
+        final double itemWidth = blockWidth / colorsCount;
 
-        return Table(
-          defaultColumnWidth: const IntrinsicColumnWidth(),
+        return Row(
+          mainAxisAlignment: MainAxisAlignment.spaceBetween,
+          crossAxisAlignment: CrossAxisAlignment.center,
           children: [
-            TableRow(
-              children: [
-                for (int value = 1; value <= maxValue; value++)
-                  Column(
-                    children: [
-                      InteractiveCell(
-                        cell: Cell(value),
-                        colorScheme: colorScheme,
-                        currentGame: gameState.currentGame,
-                        itemWidth: blockWidth / maxValue,
-                      ),
-                    ],
-                  ),
-              ],
-            ),
+            for (int value = 1; value <= colorsCount; value++)
+              CellWidget(
+                cell: Cell(value),
+                itemWidth: itemWidth,
+              ),
           ],
         );
       },
diff --git a/lib/ui/widgets/global_app_bar.dart b/lib/ui/widgets/global_app_bar.dart
index b3850bef24b8409f46d88e34ffc3907cff006bbc..227a3da94a022dad77380baf737da52cf2d0076f 100644
--- a/lib/ui/widgets/global_app_bar.dart
+++ b/lib/ui/widgets/global_app_bar.dart
@@ -1,11 +1,11 @@
-import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
 
 import 'package:colors/config/menu.dart';
 import 'package:colors/cubit/game_cubit.dart';
 import 'package:colors/cubit/nav_cubit.dart';
-import 'package:colors/models/game.dart';
-import 'package:colors/ui/widgets/helpers/app_titles.dart';
+import 'package:colors/models/game/game.dart';
+import 'package:colors/ui/helpers/app_titles.dart';
 
 class GlobalAppBar extends StatelessWidget implements PreferredSizeWidget {
   const GlobalAppBar({super.key});
@@ -16,19 +16,20 @@ class GlobalAppBar extends StatelessWidget implements PreferredSizeWidget {
       builder: (BuildContext context, GameState gameState) {
         return BlocBuilder<NavCubit, int>(
           builder: (BuildContext context, int pageIndex) {
-            final GameCubit gameCubit = BlocProvider.of<GameCubit>(context);
             final Game currentGame = gameState.currentGame;
 
             final List<Widget> menuActions = [];
 
-            if (currentGame.isRunning) {
+            if (currentGame.isRunning && !currentGame.isFinished) {
               menuActions.add(TextButton(
-                onPressed: null,
-                onLongPress: () => gameCubit.quitGame(),
                 child: const Image(
-                  image: AssetImage('assets/icons/button_back.png'),
+                  image: AssetImage('assets/ui/button_back.png'),
                   fit: BoxFit.fill,
                 ),
+                onPressed: () {},
+                onLongPress: () {
+                  BlocProvider.of<GameCubit>(context).quitGame();
+                },
               ));
             } else {
               if (pageIndex == Menu.indexGame) {
@@ -68,7 +69,7 @@ class GlobalAppBar extends StatelessWidget implements PreferredSizeWidget {
             }
 
             return AppBar(
-              title: const AppTitle(text: 'app_name'),
+              title: const AppHeader(text: 'app_name'),
               actions: menuActions,
             );
           },
diff --git a/lib/ui/widgets/helpers/app_titles.dart b/lib/ui/widgets/helpers/app_titles.dart
deleted file mode 100644
index 7cbbb2030419047b3dcf093a2195a498bd8e8ce9..0000000000000000000000000000000000000000
--- a/lib/ui/widgets/helpers/app_titles.dart
+++ /dev/null
@@ -1,17 +0,0 @@
-import 'package:easy_localization/easy_localization.dart';
-import 'package:flutter/material.dart';
-
-class AppTitle extends StatelessWidget {
-  const AppTitle({super.key, required this.text});
-
-  final String text;
-
-  @override
-  Widget build(BuildContext context) {
-    return Text(
-      tr(text),
-      textAlign: TextAlign.start,
-      style: Theme.of(context).textTheme.headlineLarge!.apply(fontWeightDelta: 2),
-    );
-  }
-}
diff --git a/lib/ui/widgets/helpers/header_app.dart b/lib/ui/widgets/helpers/header_app.dart
deleted file mode 100644
index b5c5be05f6636cf488dcdb5bbc4d6f049b98de11..0000000000000000000000000000000000000000
--- a/lib/ui/widgets/helpers/header_app.dart
+++ /dev/null
@@ -1,24 +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 Column(
-      mainAxisAlignment: MainAxisAlignment.start,
-      crossAxisAlignment: CrossAxisAlignment.start,
-      children: [
-        Text(
-          tr(text),
-          textAlign: TextAlign.start,
-          style: Theme.of(context).textTheme.headlineSmall!.apply(fontWeightDelta: 2),
-        ),
-        const SizedBox(height: 8),
-      ],
-    );
-  }
-}
diff --git a/lib/ui/widgets/indicators/indicator_max_moves.dart b/lib/ui/widgets/indicators/indicator_max_moves.dart
new file mode 100644
index 0000000000000000000000000000000000000000..8af0991284c128fe8324f031e2ac853078e8af78
--- /dev/null
+++ b/lib/ui/widgets/indicators/indicator_max_moves.dart
@@ -0,0 +1,32 @@
+import 'package:colors/cubit/game_cubit.dart';
+import 'package:colors/models/game/game.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+
+class GameIndicatorMaxMovesCount extends StatelessWidget {
+  const GameIndicatorMaxMovesCount({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        final Game currentGame = gameState.currentGame;
+
+        Color maxMovesCountColor = Colors.grey;
+        if (currentGame.movesCount > currentGame.maxMovesCount) {
+          maxMovesCountColor = Colors.red;
+        }
+
+        return Text(
+          '(max: ${currentGame.maxMovesCount})',
+          style: TextStyle(
+            fontSize: 15,
+            fontWeight: FontWeight.w600,
+            color: maxMovesCountColor,
+          ),
+        );
+      },
+    );
+  }
+}
diff --git a/lib/ui/widgets/indicators/indicator_moves_count.dart b/lib/ui/widgets/indicators/indicator_moves_count.dart
new file mode 100644
index 0000000000000000000000000000000000000000..010ad60711c918af3d8d837c959bf0aec1a46ae5
--- /dev/null
+++ b/lib/ui/widgets/indicators/indicator_moves_count.dart
@@ -0,0 +1,27 @@
+import 'package:colors/cubit/game_cubit.dart';
+import 'package:colors/models/game/game.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+
+class GameIndicatorMovesCount extends StatelessWidget {
+  const GameIndicatorMovesCount({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        final Game currentGame = gameState.currentGame;
+
+        return Text(
+          currentGame.movesCount.toString(),
+          style: TextStyle(
+            fontSize: 35,
+            fontWeight: FontWeight.w600,
+            color: Theme.of(context).colorScheme.primary,
+          ),
+        );
+      },
+    );
+  }
+}
diff --git a/lib/ui/widgets/indicators/indicator_progress.dart b/lib/ui/widgets/indicators/indicator_progress.dart
new file mode 100644
index 0000000000000000000000000000000000000000..1259fb0ccf51e3c844ad499dd9af3ace02d11a91
--- /dev/null
+++ b/lib/ui/widgets/indicators/indicator_progress.dart
@@ -0,0 +1,33 @@
+import 'package:colors/cubit/game_cubit.dart';
+import 'package:colors/models/game/game.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+
+class GameIndicatorProgress extends StatelessWidget {
+  const GameIndicatorProgress({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        final Game currentGame = gameState.currentGame;
+
+        String progressIndicator = '${currentGame.progress}/${currentGame.progressTotal}';
+
+        if (currentGame.movesCount > 0) {
+          progressIndicator += ' (+${currentGame.progressDelta})';
+        }
+
+        return Text(
+          progressIndicator,
+          style: const TextStyle(
+            fontSize: 15,
+            fontWeight: FontWeight.w600,
+            color: Colors.green,
+          ),
+        );
+      },
+    );
+  }
+}
diff --git a/lib/utils/color_extensions.dart b/lib/utils/color_extensions.dart
index 39c9322574b0fbfae3a7b9ba4eb964942b807d37..4e55e338f0d3ed98b233d1ef887b7b3e17e29d97 100644
--- a/lib/utils/color_extensions.dart
+++ b/lib/utils/color_extensions.dart
@@ -1,7 +1,5 @@
 import 'dart:ui';
 
-import 'package:flutter/material.dart';
-
 extension ColorExtension on Color {
   Color darken([int percent = 40]) {
     assert(1 <= percent && percent <= 100);
diff --git a/lib/utils/tools.dart b/lib/utils/tools.dart
index 8ed7a5313f39ef5257deba3c3119c0f41ab10cd9..fd48b2b009b80b22248d6e7f08a63e96c4065bd7 100644
--- a/lib/utils/tools.dart
+++ b/lib/utils/tools.dart
@@ -1,15 +1,7 @@
 import 'package:flutter/foundation.dart';
-import 'package:flutter/material.dart';
 
 void printlog(String message) {
   if (!kReleaseMode) {
     debugPrint(message);
   }
 }
-
-Widget buildImageContainerWidget(String imageAssetCode) {
-  return Image(
-    image: AssetImage('assets/icons/$imageAssetCode.png'),
-    fit: BoxFit.fill,
-  );
-}
diff --git a/pubspec.lock b/pubspec.lock
index 25b5be0248780b099e0f72fc5dab70bd5ce13f92..e0ab96ebb656b1260018d45af586d9ec14ba4a7e 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -61,10 +61,10 @@ packages:
     dependency: "direct main"
     description:
       name: easy_localization
-      sha256: "432698c31a488dd64c56d4759f20d04844baba5e9e4f2cb1abb9676257918b17"
+      sha256: fa59bcdbbb911a764aa6acf96bbb6fa7a5cf8234354fc45ec1a43a0349ef0201
       url: "https://pub.dev"
     source: hosted
-    version: "3.0.6"
+    version: "3.0.7"
   easy_logger:
     dependency: transitive
     description:
@@ -106,18 +106,18 @@ 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:
       name: flutter_lints
-      sha256: "9e8c3858111da373efc5aa341de011d9bd23e2c5c5e0c62bccf32438e192d7b1"
+      sha256: "3f41d009ba7172d5ff9be5f6e6e6abb4300e263aab8866d2a0842ed2a70f8f0c"
       url: "https://pub.dev"
     source: hosted
-    version: "3.0.2"
+    version: "4.0.0"
   flutter_localizations:
     dependency: transitive
     description: flutter
@@ -164,18 +164,18 @@ packages:
     dependency: transitive
     description:
       name: intl
-      sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d"
+      sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf
       url: "https://pub.dev"
     source: hosted
-    version: "0.18.1"
+    version: "0.19.0"
   lints:
     dependency: transitive
     description:
       name: lints
-      sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290
+      sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235"
       url: "https://pub.dev"
     source: hosted
-    version: "3.0.0"
+    version: "4.0.0"
   material_color_utilities:
     dependency: transitive
     description:
@@ -188,10 +188,10 @@ packages:
     dependency: transitive
     description:
       name: meta
-      sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04
+      sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
       url: "https://pub.dev"
     source: hosted
-    version: "1.11.0"
+    version: "1.12.0"
   nested:
     dependency: transitive
     description:
@@ -236,18 +236,18 @@ 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:
       name: path_provider_foundation
-      sha256: "5a7999be66e000916500be4f15a3633ebceb8302719b47b9cc49ce924125350f"
+      sha256: f234384a3fdd67f989b4d54a5d73ca2a6c422fa55ae694381ae0f4375cd1ea16
       url: "https://pub.dev"
     source: hosted
-    version: "2.3.2"
+    version: "2.4.0"
   path_provider_linux:
     dependency: transitive
     description:
@@ -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:
@@ -308,18 +308,18 @@ 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:
       name: shared_preferences_foundation
-      sha256: "7708d83064f38060c7b39db12aefe449cb8cdc031d6062280087bc4cdb988f5c"
+      sha256: "0a8a893bf4fd1152f93fec03a415d11c27c74454d96e2318a7ac38dd18683ab7"
       url: "https://pub.dev"
     source: hosted
-    version: "2.3.5"
+    version: "2.4.0"
   shared_preferences_linux:
     dependency: transitive
     description:
@@ -425,10 +425,10 @@ packages:
     dependency: transitive
     description:
       name: win32
-      sha256: "0eaf06e3446824099858367950a813472af675116bf63f008a4c2a75ae13e9cb"
+      sha256: a79dbe579cb51ecd6d30b17e0cae4e0ea15e2c0e66f69ad4198f22a6789e94f4
       url: "https://pub.dev"
     source: hosted
-    version: "5.5.0"
+    version: "5.5.1"
   xdg_directories:
     dependency: transitive
     description:
@@ -438,5 +438,5 @@ packages:
     source: hosted
     version: "1.0.4"
 sdks:
-  dart: ">=3.3.0 <4.0.0"
-  flutter: ">=3.19.0"
+  dart: ">=3.4.0 <4.0.0"
+  flutter: ">=3.22.0"
diff --git a/pubspec.yaml b/pubspec.yaml
index e6b8af0dde4d69af11d8f3a645b1418b75662251..498d8abc1014e0a1eff0e5069391c3c8b31adc8f 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,16 +1,18 @@
 name: colors
 description: Fill the board, a colorfull game!
 
-publish_to: 'none'
-version: 0.0.39+39
+publish_to: "none"
+
+version: 0.1.0+40
 
 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
@@ -20,13 +22,16 @@ dependencies:
   path_provider: ^2.0.11
   unicons: ^2.1.1
 
+  # specific
+  # (none)
+
 dev_dependencies:
-  flutter_lints: ^3.0.1
+  flutter_lints: ^4.0.0
 
 flutter:
   uses-material-design: true
   assets:
-    - assets/icons/
+    - 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/resources/ui/images/button_delete_saved_game.svg b/resources/ui/images/button_delete_saved_game.svg
new file mode 100644
index 0000000000000000000000000000000000000000..ac7eefef476f761903fe781b8c86d0c94323550a
--- /dev/null
+++ b/resources/ui/images/button_delete_saved_game.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="#ee7d49" stroke="#fff" stroke-width=".238"/><path d="m61.07 35.601-1.7399 27.837c-0.13442 2.1535-1.9205 3.8312-4.0781 3.8312h-16.84c-2.1576 0-3.9437-1.6777-4.0781-3.8312l-1.7399-27.837h-2.6176c-0.84621 0-1.5323-0.68613-1.5323-1.5323 0-0.84655 0.68613-1.5323 1.5323-1.5323h33.711c0.84621 0 1.5323 0.68578 1.5323 1.5323 0 0.84621-0.68613 1.5323-1.5323 1.5323zm-3.2617 0h-21.953l1.4715 26.674c0.05985 1.0829 0.95531 1.9305 2.0403 1.9305h14.929c1.085 0 1.9804-0.84757 2.0403-1.9305zm-10.977 3.0647c0.78977 0 1.4301 0.6403 1.4301 1.4301v19.614c0 0.78977-0.6403 1.4301-1.4301 1.4301s-1.4301-0.6403-1.4301-1.4301v-19.614c0-0.78977 0.6403-1.4301 1.4301-1.4301zm-6.1293 0c0.80004 0 1.4588 0.62935 1.495 1.4286l0.89647 19.719c0.03182 0.70016-0.50998 1.2933-1.2101 1.3255-0.01915 7.02e-4 -0.03831 1e-3 -0.05781 1e-3 -0.74462 0-1.3596-0.58215-1.4003-1.3261l-1.0757-19.719c-0.0407-0.74701 0.53188-1.3852 1.2786-1.4259 0.02462-0.0014 0.04926-2e-3 0.07388-2e-3zm12.259 0c0.74804 0 1.3541 0.60609 1.3541 1.3541 0 0.02462-3.28e-4 0.04926-0.0017 0.07388l-1.0703 19.618c-0.04379 0.80106-0.70597 1.4281-1.5081 1.4281-0.74804 0-1.3541-0.60609-1.3541-1.3541 0-0.02462 3.49e-4 -0.04925 0.0017-0.07388l1.0703-19.618c0.04379-0.80106 0.70597-1.4281 1.5081-1.4281zm-10.216-12.259h8.1728c2.2567 0 4.086 1.8293 4.086 4.086v2.0433h-16.344v-2.0433c0-2.2567 1.8293-4.086 4.086-4.086zm0.20453 3.0647c-0.67725 0-1.2259 0.54863-1.2259 1.2259v1.8388h10.215v-1.8388c0-0.67725-0.54863-1.2259-1.2259-1.2259z" fill="#fff" fill-rule="evenodd" stroke="#bd4812" stroke-width=".75383"/></svg>
diff --git a/resources/ui/images/button_resume_game.svg b/resources/ui/images/button_resume_game.svg
new file mode 100644
index 0000000000000000000000000000000000000000..6ad8b64202d0e70f898c16c520e756fe8a934add
--- /dev/null
+++ b/resources/ui/images/button_resume_game.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="m39.211 31.236c-0.84086-0.84489-2.9911-0.84489-2.9911 0v34.329c0 0.84594 2.1554 0.84594 2.9993 0l28.178-15.637c0.84392-0.84086 0.85812-2.2091 0.01623-3.053z" fill="#fefeff" stroke="#105ca1" stroke-linecap="round" stroke-linejoin="round" stroke-width="6.1726"/><path d="m40.355 33.714c-0.71948-0.72294-2.5594-0.72294-2.5594 0v29.373c0 0.72383 1.8442 0.72383 2.5663 0l24.11-13.38c0.7221-0.71948 0.73426-1.8902 0.01389-2.6124z" fill="#fefeff" stroke="#feffff" stroke-linecap="round" stroke-linejoin="round" stroke-width="3.225"/><path d="m28.369 66.919v-37.591" fill="#105ca2" stroke="#105ca2" stroke-linecap="round" stroke-width="4.0337"/></svg>
diff --git a/icons/button_start.svg b/resources/ui/images/button_start.svg
similarity index 100%
rename from icons/button_start.svg
rename to resources/ui/images/button_start.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/resources/ui/images/placeholder.svg b/resources/ui/images/placeholder.svg
new file mode 100644
index 0000000000000000000000000000000000000000..23ace81fbb82a8409cc0710c0f7bddd6381f7256
--- /dev/null
+++ b/resources/ui/images/placeholder.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 102 102" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"/>