diff --git a/.editorconfig b/.editorconfig
index 779f99a12b5c71692ad6d6908d6d2fc3bdba485d..8d86e4518e450377768d1de80adafba87984a148 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -8,5 +8,8 @@ charset = utf-8
 trim_trailing_whitespace = true
 insert_final_newline = true
 
+[*.json]
+indent_size = 2
+
 [*.md]
 trim_trailing_whitespace = false
diff --git a/android/gradle.properties b/android/gradle.properties
index de61e662a315af64a533adcc27741867b59691ef..aa6a055392dccdb92b60006f75938118da798cb1 100644
--- a/android/gradle.properties
+++ b/android/gradle.properties
@@ -1,5 +1,5 @@
 org.gradle.jvmargs=-Xmx1536M
 android.useAndroidX=true
 android.enableJetifier=true
-app.versionName=0.1.22
-app.versionCode=71
+app.versionName=0.2.0
+app.versionCode=72
diff --git a/assets/icons/.gitkeep b/assets/icons/.gitkeep
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/assets/skins/.gitkeep b/assets/skins/.gitkeep
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/assets/translations/en.json b/assets/translations/en.json
index fc8780447adc0f8cc8e3a94537001af020a6f7c1..698056d0c6bd17e64befc5e4dd18f66b7fd912a9 100644
--- a/assets/translations/en.json
+++ b/assets/translations/en.json
@@ -1,14 +1,12 @@
 {
   "app_name": "Sudoku",
 
-  "bottom_nav_game": "Game",
-  "bottom_nav_settings": "Settings",
-  "bottom_nav_about": "About",
-
   "settings_title": "Settings",
   "settings_label_theme": "Theme mode",
 
   "about_title": "About",
   "about_content": "Simple Sudoku Game. Easy to play, easy to enjoy.",
-  "about_version": "Version: {version}"
+  "about_version": "Version: {version}",
+
+  "": ""
 }
diff --git a/assets/translations/fr.json b/assets/translations/fr.json
index 64b3b733df7ce21b6b63e66d47e846f2f7684cac..7d1f4e88ae2547e146ee1cc47e4394fd1ca71100 100644
--- a/assets/translations/fr.json
+++ b/assets/translations/fr.json
@@ -1,14 +1,12 @@
 {
   "app_name": "Sudoku",
 
-  "bottom_nav_game": "Jeu",
-  "bottom_nav_settings": "Réglages",
-  "bottom_nav_about": "Infos",
-
   "settings_title": "Réglages",
   "settings_label_theme": "Thème de couleurs",
 
   "about_title": "Informations",
   "about_content": "Jeu de Sudoku simple, facile à jouer, facile à apprécier.",
-  "about_version": "Version : {version}"
+  "about_version": "Version : {version}",
+
+  "": ""
 }
diff --git a/assets/icons/button_back.png b/assets/ui/button_back.png
similarity index 100%
rename from assets/icons/button_back.png
rename to assets/ui/button_back.png
diff --git a/assets/icons/button_delete_saved_game.png b/assets/ui/button_delete_saved_game.png
similarity index 100%
rename from assets/icons/button_delete_saved_game.png
rename to assets/ui/button_delete_saved_game.png
diff --git a/assets/icons/button_help.png b/assets/ui/button_help.png
similarity index 100%
rename from assets/icons/button_help.png
rename to assets/ui/button_help.png
diff --git a/assets/icons/button_resume_game.png b/assets/ui/button_resume_game.png
similarity index 100%
rename from assets/icons/button_resume_game.png
rename to assets/ui/button_resume_game.png
diff --git a/assets/icons/button_show_conflicts.png b/assets/ui/button_show_conflicts.png
similarity index 100%
rename from assets/icons/button_show_conflicts.png
rename to assets/ui/button_show_conflicts.png
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/cell_empty.png b/assets/ui/cell_empty.png
similarity index 100%
rename from assets/icons/cell_empty.png
rename to assets/ui/cell_empty.png
diff --git a/assets/icons/game_win.png b/assets/ui/game_win.png
similarity index 100%
rename from assets/icons/game_win.png
rename to assets/ui/game_win.png
diff --git a/assets/icons/placeholder.png b/assets/ui/placeholder.png
similarity index 100%
rename from assets/icons/placeholder.png
rename to assets/ui/placeholder.png
diff --git a/assets/icons/skin_digits.png b/assets/ui/skin_digits.png
similarity index 100%
rename from assets/icons/skin_digits.png
rename to assets/ui/skin_digits.png
diff --git a/assets/icons/skin_food.png b/assets/ui/skin_food.png
similarity index 100%
rename from assets/icons/skin_food.png
rename to assets/ui/skin_food.png
diff --git a/assets/icons/skin_monsters.png b/assets/ui/skin_monsters.png
similarity index 100%
rename from assets/icons/skin_monsters.png
rename to assets/ui/skin_monsters.png
diff --git a/assets/icons/skin_nature.png b/assets/ui/skin_nature.png
similarity index 100%
rename from assets/icons/skin_nature.png
rename to assets/ui/skin_nature.png
diff --git a/fastlane/metadata/android/en-US/changelogs/72.txt b/fastlane/metadata/android/en-US/changelogs/72.txt
new file mode 100644
index 0000000000000000000000000000000000000000..d4afd512e55b3fd8ffbfd795adb9b00832e5aaef
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/72.txt
@@ -0,0 +1 @@
+Improve/normalize game architecture.
diff --git a/fastlane/metadata/android/fr-FR/changelogs/72.txt b/fastlane/metadata/android/fr-FR/changelogs/72.txt
new file mode 100644
index 0000000000000000000000000000000000000000..6a9871a5eb8eb3c6e9106520f1cbf1f39f9e5ef7
--- /dev/null
+++ b/fastlane/metadata/android/fr-FR/changelogs/72.txt
@@ -0,0 +1 @@
+Amélioration/normalisation de l'architecture du jeu.
diff --git a/lib/config/default_game_settings.dart b/lib/config/default_game_settings.dart
index 2f9ae753d2cd5ef02f1feafda79db96a84a9315b..15e6d1b48f6daf76813776f81c0eebc07ac4372b 100644
--- a/lib/config/default_game_settings.dart
+++ b/lib/config/default_game_settings.dart
@@ -1,40 +1,43 @@
 import 'package:sudoku/utils/tools.dart';
 
 class DefaultGameSettings {
+  // available game parameters codes
   static const String parameterCodeLevel = 'level';
   static const String parameterCodeSize = 'size';
-
   static const List<String> availableParameters = [
     parameterCodeLevel,
     parameterCodeSize,
   ];
 
+  // level: available values
   static const String levelValueEasy = 'easy';
   static const String levelValueMedium = 'medium';
   static const String levelValueHard = 'hard';
   static const String levelValueNightmare = 'nightmare';
-
-  static const String defaultLevelValue = levelValueMedium;
   static const List<String> allowedLevelValues = [
     levelValueEasy,
     levelValueMedium,
     levelValueHard,
     levelValueNightmare,
   ];
+  // level: default value
+  static const String defaultLevelValue = levelValueMedium;
 
+  // size: available values
   static const String sizeValueTiny = '2x2';
   static const String sizeValueSmall = '3x2';
   static const String sizeValueStandard = '3x3';
   static const String sizeValueLarge = '4x4';
-
-  static const String defaultSizeValue = sizeValueStandard;
   static const List<String> allowedSizeValues = [
     sizeValueTiny,
     sizeValueSmall,
     sizeValueStandard,
     sizeValueLarge,
   ];
+  // size: default value
+  static const String defaultSizeValue = sizeValueStandard;
 
+  // available values from parameter code
   static List<String> getAvailableValues(String parameterCode) {
     switch (parameterCode) {
       case parameterCodeLevel:
@@ -46,4 +49,9 @@ class DefaultGameSettings {
     printlog('Did not find any available value for game parameter "$parameterCode".');
     return [];
   }
+
+  // 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 401e3efd5333c35a48da480c6c4443ebb23d3277..86bc0e0c8d4244a2f9cf8904b064d4f0bec94f10 100644
--- a/lib/config/default_global_settings.dart
+++ b/lib/config/default_global_settings.dart
@@ -1,30 +1,33 @@
 import 'package:sudoku/utils/tools.dart';
 
 class DefaultGlobalSettings {
+  // available global parameters codes
   static const String parameterCodeSkin = 'skin';
-
   static const List<String> availableParameters = [
     parameterCodeSkin,
   ];
 
+  // skin: available values
   static const String skinValueDigits = 'digits';
   static const String skinValueFood = 'food';
   static const String skinValueNature = 'nature';
   static const String skinValueMonsters = 'monsters';
-
-  static const String defaultSkinValue = skinValueDigits;
   static const List<String> allowedSkinValues = [
     skinValueDigits,
     skinValueFood,
     skinValueNature,
     skinValueMonsters,
   ];
+  // skin: default value
+  static const String defaultSkinValue = skinValueDigits;
+  // skin: shufflable skins (without order in items)
   static const List<String> shufflableSkins = [
     skinValueFood,
     skinValueNature,
     skinValueMonsters,
   ];
 
+  // available values from parameter code
   static List<String> getAvailableValues(String parameterCode) {
     switch (parameterCode) {
       case parameterCodeSkin:
@@ -35,5 +38,10 @@ class DefaultGlobalSettings {
     return [];
   }
 
+  // parameters displayed with assets (instead of painter)
+  static List<String> displayedWithAssets = [
+    parameterCodeSkin,
+  ];
+
   static const int defaultTipCountDownValueInSeconds = 20;
 }
diff --git a/lib/config/menu.dart b/lib/config/menu.dart
index c092272a55981d01699efbf7eda733e0a67ea368..64fb1ac637edb15b3c81d8724e42e4064defd19c 100644
--- a/lib/config/menu.dart
+++ b/lib/config/menu.dart
@@ -1,17 +1,15 @@
 import 'package:flutter/material.dart';
 import 'package:unicons/unicons.dart';
 
-import 'package:sudoku/ui/screens/about_page.dart';
-import 'package:sudoku/ui/screens/game_page.dart';
-import 'package:sudoku/ui/screens/settings_page.dart';
+import 'package:sudoku/ui/screens/page_about.dart';
+import 'package:sudoku/ui/screens/page_game.dart';
+import 'package:sudoku/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,23 +18,20 @@ class MenuItem {
 class Menu {
   static const indexGame = 0;
   static const menuItemGame = MenuItem(
-    code: 'bottom_nav_game',
     icon: Icon(UniconsLine.home),
-    page: GamePage(),
+    page: PageGame(),
   );
 
   static const indexSettings = 1;
   static const menuItemSettings = MenuItem(
-    code: 'bottom_nav_settings',
     icon: Icon(UniconsLine.setting),
-    page: SettingsPage(),
+    page: PageSettings(),
   );
 
   static const indexAbout = 2;
   static const menuItemAbout = MenuItem(
-    code: 'bottom_nav_about',
     icon: Icon(UniconsLine.info_circle),
-    page: AboutPage(),
+    page: PageAbout(),
   );
 
   static Map<int, MenuItem> items = {
diff --git a/lib/config/theme.dart b/lib/config/theme.dart
index 1732b790ab4f411f084a987bc5e50be2ab408c24..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 = lightTheme;
diff --git a/lib/cubit/game_cubit.dart b/lib/cubit/game_cubit.dart
index bb663d00184762011ee4e39fe14579b9267aa461..1fca0d001544ca665042d18c350f522d767e0e91 100644
--- a/lib/cubit/game_cubit.dart
+++ b/lib/cubit/game_cubit.dart
@@ -5,12 +5,12 @@ import 'package:equatable/equatable.dart';
 import 'package:flutter/material.dart';
 import 'package:hydrated_bloc/hydrated_bloc.dart';
 import 'package:sudoku/config/default_global_settings.dart';
-import 'package:sudoku/models/cell.dart';
 
-import 'package:sudoku/models/cell_location.dart';
-import 'package:sudoku/models/game.dart';
-import 'package:sudoku/models/settings_game.dart';
-import 'package:sudoku/models/settings_global.dart';
+import 'package:sudoku/models/game/cell.dart';
+import 'package:sudoku/models/game/cell_location.dart';
+import 'package:sudoku/models/game/game.dart';
+import 'package:sudoku/models/settings/settings_game.dart';
+import 'package:sudoku/models/settings/settings_global.dart';
 import 'package:sudoku/utils/board_animate.dart';
 
 part 'game_state.dart';
@@ -18,36 +18,43 @@ part 'game_state.dart';
 class GameCubit extends HydratedCubit<GameState> {
   GameCubit()
       : super(GameState(
-          game: Game.createNull(),
+          currentGame: Game.createEmpty(),
         ));
 
   void updateState(Game game) {
     emit(GameState(
-      game: game,
+      currentGame: game,
     ));
   }
 
   void refresh() {
-    updateState(Game(
-      gameSettings: state.game.gameSettings,
-      globalSettings: state.game.globalSettings,
-      board: state.game.board,
-      solvedBoard: state.game.solvedBoard,
-      isRunning: state.game.isRunning,
-      isStarted: state.game.isStarted,
-      isFinished: state.game.isFinished,
-      blockSizeHorizontal: state.game.blockSizeHorizontal,
-      blockSizeVertical: state.game.blockSizeVertical,
-      boardSize: state.game.boardSize,
-      shuffledCellValues: state.game.shuffledCellValues,
-      boardConflicts: state.game.boardConflicts,
-      selectedCell: state.game.selectedCell,
-      showConflicts: state.game.showConflicts,
-      givenTipsCount: state.game.givenTipsCount,
-      buttonTipsCountdown: state.game.buttonTipsCountdown,
-      animationInProgress: state.game.animationInProgress,
-      boardAnimated: state.game.boardAnimated,
-    ));
+    final Game game = Game(
+      // Settings
+      gameSettings: state.currentGame.gameSettings,
+      globalSettings: state.currentGame.globalSettings,
+      // State
+      isRunning: state.currentGame.isRunning,
+      isStarted: state.currentGame.isStarted,
+      isFinished: state.currentGame.isFinished,
+      animationInProgress: state.currentGame.animationInProgress,
+      boardAnimated: state.currentGame.boardAnimated,
+      // Base data
+      board: state.currentGame.board,
+      solvedBoard: state.currentGame.solvedBoard,
+      blockSizeHorizontal: state.currentGame.blockSizeHorizontal,
+      blockSizeVertical: state.currentGame.blockSizeVertical,
+      boardSize: state.currentGame.boardSize,
+      // Game data
+      shuffledCellValues: state.currentGame.shuffledCellValues,
+      boardConflicts: state.currentGame.boardConflicts,
+      selectedCell: state.currentGame.selectedCell,
+      showConflicts: state.currentGame.showConflicts,
+      givenTipsCount: state.currentGame.givenTipsCount,
+      buttonTipsCountdown: state.currentGame.buttonTipsCountdown,
+    );
+    // game.dump();
+
+    updateState(game);
   }
 
   void startNewGame({
@@ -55,6 +62,7 @@ class GameCubit extends HydratedCubit<GameState> {
     required GlobalSettings globalSettings,
   }) {
     final Game newGame = Game.createNew(
+      // Settings
       gameSettings: gameSettings,
       globalSettings: globalSettings,
     );
@@ -68,18 +76,18 @@ class GameCubit extends HydratedCubit<GameState> {
   }
 
   void selectCell(CellLocation location) {
-    state.game.selectedCell = state.game.board.get(location);
+    state.currentGame.selectedCell = state.currentGame.board.get(location);
     refresh();
   }
 
   void unselectCell() {
-    state.game.selectedCell = null;
+    state.currentGame.selectedCell = null;
     refresh();
   }
 
   void updateCellValue(CellLocation location, int value) {
-    if (state.game.board.get(location).isFixed == false) {
-      state.game.board.set(
+    if (state.currentGame.board.get(location).isFixed == false) {
+      state.currentGame.board.set(
         location,
         Cell(
           location: location,
@@ -87,35 +95,37 @@ class GameCubit extends HydratedCubit<GameState> {
           isFixed: false,
         ),
       );
-      state.game.isStarted = true;
+      state.currentGame.isStarted = true;
       refresh();
     }
 
-    if (state.game.checkBoardIsSolved()) {
+    if (state.currentGame.checkBoardIsSolved()) {
       BoardAnimate.startAnimation(this, 'win');
-      state.game.isFinished = true;
+      state.currentGame.isFinished = true;
       refresh();
     }
   }
 
   void toggleShowConflicts() {
-    state.game.showConflicts = !state.game.showConflicts;
+    state.currentGame.showConflicts = !state.currentGame.showConflicts;
     refresh();
   }
 
   void increaseGivenTipsCount() {
-    state.game.givenTipsCount++;
-    state.game.buttonTipsCountdown = DefaultGlobalSettings.defaultTipCountDownValueInSeconds;
+    state.currentGame.givenTipsCount++;
+    state.currentGame.buttonTipsCountdown =
+        DefaultGlobalSettings.defaultTipCountDownValueInSeconds;
     refresh();
 
     const Duration interval = Duration(milliseconds: 500);
     Timer.periodic(
       interval,
       (Timer timer) {
-        if (state.game.buttonTipsCountdown == 0) {
+        if (state.currentGame.buttonTipsCountdown == 0) {
           timer.cancel();
         } else {
-          state.game.buttonTipsCountdown = max(state.game.buttonTipsCountdown - 1, 0);
+          state.currentGame.buttonTipsCountdown =
+              max(state.currentGame.buttonTipsCountdown - 1, 0);
         }
         refresh();
       },
@@ -123,39 +133,39 @@ class GameCubit extends HydratedCubit<GameState> {
   }
 
   void quitGame() {
-    state.game.isRunning = false;
+    state.currentGame.isRunning = false;
     refresh();
   }
 
   void resumeSavedGame() {
-    state.game.isRunning = true;
+    state.currentGame.isRunning = true;
     refresh();
   }
 
   void deleteSavedGame() {
-    state.game.isRunning = false;
-    state.game.isFinished = true;
+    state.currentGame.isRunning = false;
+    state.currentGame.isFinished = true;
     refresh();
   }
 
   void updateAnimationInProgress(bool animationInProgress) {
-    state.game.animationInProgress = animationInProgress;
+    state.currentGame.animationInProgress = animationInProgress;
     refresh();
   }
 
   void setAnimatedBackground(List animatedCellsPattern) {
-    for (int row = 0; row < state.game.boardSize; row++) {
-      for (int col = 0; col < state.game.boardSize; col++) {
-        state.game.boardAnimated[row][col] = animatedCellsPattern[row][col];
+    for (int row = 0; row < state.currentGame.boardSize; row++) {
+      for (int col = 0; col < state.currentGame.boardSize; col++) {
+        state.currentGame.boardAnimated[row][col] = animatedCellsPattern[row][col];
       }
     }
     refresh();
   }
 
   void resetAnimatedBackground() {
-    for (int row = 0; row < state.game.boardSize; row++) {
-      for (int col = 0; col < state.game.boardSize; col++) {
-        state.game.boardAnimated[row][col] = false;
+    for (int row = 0; row < state.currentGame.boardSize; row++) {
+      for (int col = 0; col < state.currentGame.boardSize; col++) {
+        state.currentGame.boardAnimated[row][col] = false;
       }
     }
     refresh();
@@ -163,17 +173,17 @@ class GameCubit extends HydratedCubit<GameState> {
 
   @override
   GameState? fromJson(Map<String, dynamic> json) {
-    Game game = json['game'] as Game;
+    final Game currentGame = json['currentGame'] as Game;
 
     return GameState(
-      game: game,
+      currentGame: currentGame,
     );
   }
 
   @override
   Map<String, dynamic>? toJson(GameState state) {
     return <String, dynamic>{
-      'game': state.game.toJson(),
+      'currentGame': state.currentGame.toJson(),
     };
   }
 }
diff --git a/lib/cubit/game_state.dart b/lib/cubit/game_state.dart
index 8d8f70fc138bd99263f889070f3c929c6fb04e31..00e211668c3269255926939324355792abd61c41 100644
--- a/lib/cubit/game_state.dart
+++ b/lib/cubit/game_state.dart
@@ -3,17 +3,13 @@ part of 'game_cubit.dart';
 @immutable
 class GameState extends Equatable {
   const GameState({
-    required this.game,
+    required this.currentGame,
   });
 
-  final Game game;
+  final Game currentGame;
 
   @override
   List<dynamic> get props => <dynamic>[
-        game,
+        currentGame,
       ];
-
-  Map<String, dynamic> get values => <String, dynamic>{
-        'game': game,
-      };
 }
diff --git a/lib/cubit/settings_game_cubit.dart b/lib/cubit/settings_game_cubit.dart
index fc2840d804f35ae11e58873e7d2194a4747aab3f..2ac251742867c9975bcb28831881942aa226eb0e 100644
--- a/lib/cubit/settings_game_cubit.dart
+++ b/lib/cubit/settings_game_cubit.dart
@@ -1,9 +1,9 @@
 import 'package:equatable/equatable.dart';
 import 'package:flutter/material.dart';
 import 'package:hydrated_bloc/hydrated_bloc.dart';
-import 'package:sudoku/config/default_game_settings.dart';
 
-import 'package:sudoku/models/settings_game.dart';
+import 'package:sudoku/config/default_game_settings.dart';
+import 'package:sudoku/models/settings/settings_game.dart';
 
 part 'settings_game_state.dart';
 
@@ -31,6 +31,7 @@ class GameSettingsCubit extends HydratedCubit<GameSettingsState> {
       case DefaultGameSettings.parameterCodeSize:
         return GameSettings.getSizeValueFromUnsafe(state.settings.size);
     }
+
     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 9dceaa067477ac8ccf58b86afee7f7c4b7b0977f..f14c602e46a2afb8d0c85ad3d65013f9fd50ff22 100644
--- a/lib/cubit/settings_global_cubit.dart
+++ b/lib/cubit/settings_global_cubit.dart
@@ -1,9 +1,9 @@
 import 'package:equatable/equatable.dart';
 import 'package:flutter/material.dart';
 import 'package:hydrated_bloc/hydrated_bloc.dart';
-import 'package:sudoku/config/default_global_settings.dart';
 
-import 'package:sudoku/models/settings_global.dart';
+import 'package:sudoku/config/default_global_settings.dart';
+import 'package:sudoku/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/assets/grids.dart b/lib/data/game_data.dart
similarity index 99%
rename from lib/assets/grids.dart
rename to lib/data/game_data.dart
index c3cea19cbf5228a857f8031578c49d9d7beea3af..3e43fcf57dec3ec411c1bb56563978740ea9e344 100644
--- a/lib/assets/grids.dart
+++ b/lib/data/game_data.dart
@@ -1,4 +1,4 @@
-class SudokuGrids {
+class GameData {
   static const Map<String, Map<String, List<String>>> templates = {
     '2x2': {
       'easy': [
diff --git a/lib/main.dart b/lib/main.dart
index a69d933e51efcc7a7a4e0af2969aa964fa84fdc1..c6929f767649ddf90915e9c7b5d7f20f34606c23 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -2,6 +2,7 @@ import 'dart:io';
 
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:hive/hive.dart';
 import 'package:hydrated_bloc/hydrated_bloc.dart';
@@ -26,18 +27,17 @@ void main() async {
     storageDirectory: tmpDir,
   );
 
-  runApp(
-    EasyLocalization(
-      path: 'assets/translations',
-      supportedLocales: const <Locale>[
-        Locale('en'),
-        Locale('fr'),
-      ],
-      fallbackLocale: const Locale('en'),
-      useFallbackTranslations: true,
-      child: const MyApp(),
-    ),
-  );
+  SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp])
+      .then((value) => runApp(EasyLocalization(
+            path: 'assets/translations',
+            supportedLocales: const <Locale>[
+              Locale('en'),
+              Locale('fr'),
+            ],
+            fallbackLocale: const Locale('en'),
+            useFallbackTranslations: true,
+            child: const MyApp(),
+          )));
 }
 
 class MyApp extends StatelessWidget {
@@ -85,16 +85,18 @@ class MyApp extends StatelessWidget {
 
     final List<String> gameImages = [
       'button_back',
+      'button_delete_saved_game',
       'button_help',
+      'button_resume_game',
       'button_show_conflicts',
       'button_start',
+      'cell_empty',
       'game_win',
       'placeholder',
-      'cell_empty'
     ];
 
     for (String image in gameImages) {
-      assets.add('${'assets/icons/$image'}.png');
+      assets.add('assets/ui/$image.png');
     }
 
     List<String> skinImages = [];
@@ -103,9 +105,9 @@ class MyApp extends StatelessWidget {
     }
 
     for (String skin in DefaultGlobalSettings.allowedSkinValues) {
-      assets.add('assets/icons/skin_$skin.png');
+      assets.add('assets/ui/skin_$skin.png');
       for (String image in skinImages) {
-        assets.add('${'${'assets/skins/$skin'}_$image'}.png');
+        assets.add('assets/skins/${skin}_$image.png');
       }
     }
 
diff --git a/lib/models/board.dart b/lib/models/game/board.dart
similarity index 54%
rename from lib/models/board.dart
rename to lib/models/game/board.dart
index c83989ed1f70bec670d6fe6a565279ff294fdab6..852cc2195c2d58fe4f5517a50cb4de64d43eb309 100644
--- a/lib/models/board.dart
+++ b/lib/models/game/board.dart
@@ -1,8 +1,8 @@
 import 'dart:math';
 
-import 'package:sudoku/models/cell.dart';
-import 'package:sudoku/models/cell_location.dart';
-import 'package:sudoku/models/types.dart';
+import 'package:sudoku/models/game/cell.dart';
+import 'package:sudoku/models/game/cell_location.dart';
+import 'package:sudoku/models/game/types.dart';
 import 'package:sudoku/utils/tools.dart';
 
 class Board {
@@ -26,6 +26,145 @@ class Board {
     );
   }
 
+  factory Board.createFromTemplate({
+    required String template,
+    required bool isSymetric,
+  }) {
+    // Create board cells from size, with "empty" cells
+    BoardCells createEmptyBoard(final int boardSize) {
+      final BoardCells cells = [];
+      for (int rowIndex = 0; rowIndex < boardSize; rowIndex++) {
+        final List<Cell> row = [];
+        for (int colIndex = 0; colIndex < boardSize; colIndex++) {
+          row.add(Cell(
+            location: CellLocation.go(rowIndex, colIndex),
+            value: 0,
+            isFixed: false,
+          ));
+        }
+        cells.add(row);
+      }
+
+      return cells;
+    }
+
+    BoardCells cells = [];
+    final int boardSize = int.parse(pow(template.length, 1 / 2).toStringAsFixed(0));
+
+    const String stringValues = '0123456789ABCDEFG';
+
+    int index = 0;
+    for (int rowIndex = 0; rowIndex < boardSize; rowIndex++) {
+      final List<Cell> row = [];
+      for (int colIndex = 0; colIndex < boardSize; colIndex++) {
+        final String stringValue = template[index++];
+        final int value = stringValues.indexOf(stringValue);
+        row.add(Cell(
+          location: CellLocation.go(rowIndex, colIndex),
+          value: value,
+          isFixed: (value != 0),
+        ));
+      }
+      cells.add(row);
+    }
+
+    const List<String> allowedFlip = ['none', 'horizontal', 'vertical'];
+    List<String> allowedRotate = ['none', 'left', 'right'];
+
+    // Forbid rotation if blocks are not symetric
+    if (!isSymetric) {
+      allowedRotate = ['none'];
+    }
+
+    final Random rand = Random();
+    final String flip = allowedFlip[rand.nextInt(allowedFlip.length)];
+    final String rotate = allowedRotate[rand.nextInt(allowedRotate.length)];
+
+    printlog('flip board: $flip');
+    printlog('rotate board: $rotate');
+
+    switch (flip) {
+      case 'horizontal':
+        {
+          final BoardCells transformedBoard = createEmptyBoard(boardSize);
+          for (int rowIndex = 0; rowIndex < boardSize; rowIndex++) {
+            for (int colIndex = 0; colIndex < boardSize; colIndex++) {
+              transformedBoard[rowIndex][colIndex] = Cell(
+                location: CellLocation.go(rowIndex, colIndex),
+                value: cells[boardSize - rowIndex - 1][colIndex].value,
+                isFixed: false,
+              );
+            }
+          }
+          cells = transformedBoard;
+        }
+        break;
+      case 'vertical':
+        {
+          final BoardCells transformedBoard = createEmptyBoard(boardSize);
+          for (int rowIndex = 0; rowIndex < boardSize; rowIndex++) {
+            for (int colIndex = 0; colIndex < boardSize; colIndex++) {
+              transformedBoard[rowIndex][colIndex] = Cell(
+                location: CellLocation.go(rowIndex, colIndex),
+                value: cells[rowIndex][boardSize - colIndex - 1].value,
+                isFixed: false,
+              );
+            }
+          }
+          cells = transformedBoard;
+        }
+        break;
+    }
+
+    switch (rotate) {
+      case 'left':
+        {
+          final BoardCells transformedBoard = createEmptyBoard(boardSize);
+          for (int rowIndex = 0; rowIndex < boardSize; rowIndex++) {
+            for (int colIndex = 0; colIndex < boardSize; colIndex++) {
+              transformedBoard[rowIndex][colIndex] = Cell(
+                location: CellLocation.go(rowIndex, colIndex),
+                value: cells[colIndex][boardSize - rowIndex - 1].value,
+                isFixed: false,
+              );
+            }
+          }
+          cells = transformedBoard;
+        }
+        break;
+      case 'right':
+        {
+          final BoardCells transformedBoard = createEmptyBoard(boardSize);
+          for (int rowIndex = 0; rowIndex < boardSize; rowIndex++) {
+            for (int colIndex = 0; colIndex < boardSize; colIndex++) {
+              transformedBoard[rowIndex][colIndex] = Cell(
+                location: CellLocation.go(rowIndex, colIndex),
+                value: cells[boardSize - colIndex - 1][rowIndex].value,
+                isFixed: false,
+              );
+            }
+          }
+          cells = transformedBoard;
+        }
+        break;
+    }
+
+    // Fix cells fixed states
+    for (int rowIndex = 0; rowIndex < boardSize; rowIndex++) {
+      for (int colIndex = 0; colIndex < boardSize; colIndex++) {
+        cells[rowIndex][colIndex] = Cell(
+          location: CellLocation.go(rowIndex, colIndex),
+          value: cells[rowIndex][colIndex].value,
+          isFixed: (cells[rowIndex][colIndex].value != 0) ? true : false,
+        );
+      }
+    }
+
+    return Board.createNew(
+      cells: cells,
+    );
+  }
+
   Cell get(CellLocation location) {
     if (location.row < cells.length) {
       if (location.col < cells[location.row].length) {
diff --git a/lib/models/cell.dart b/lib/models/game/cell.dart
similarity index 92%
rename from lib/models/cell.dart
rename to lib/models/game/cell.dart
index c8e07172493e6857ef70558dce37c4071950f88d..8da6e6a28db6151b55d799dc51b67ebdbf828cfb 100644
--- a/lib/models/cell.dart
+++ b/lib/models/game/cell.dart
@@ -1,4 +1,4 @@
-import 'package:sudoku/models/cell_location.dart';
+import 'package:sudoku/models/game/cell_location.dart';
 import 'package:sudoku/utils/tools.dart';
 
 class Cell {
diff --git a/lib/models/cell_location.dart b/lib/models/game/cell_location.dart
similarity index 100%
rename from lib/models/cell_location.dart
rename to lib/models/game/cell_location.dart
diff --git a/lib/models/game.dart b/lib/models/game/game.dart
similarity index 82%
rename from lib/models/game.dart
rename to lib/models/game/game.dart
index 74bc3b486a2f34cf5a4ce781669bab65acf9583f..c59d00101f803503025531a00493b0521fa3fcf4 100644
--- a/lib/models/game.dart
+++ b/lib/models/game/game.dart
@@ -1,78 +1,85 @@
 import 'dart:math';
 
-import 'package:sudoku/assets/grids.dart';
 import 'package:sudoku/config/default_global_settings.dart';
 import 'package:sudoku/cubit/game_cubit.dart';
-import 'package:sudoku/models/board.dart';
-import 'package:sudoku/models/cell.dart';
-import 'package:sudoku/models/cell_location.dart';
-import 'package:sudoku/models/settings_game.dart';
-import 'package:sudoku/models/settings_global.dart';
-import 'package:sudoku/models/types.dart';
-import 'package:sudoku/utils/board_utils.dart';
+import 'package:sudoku/data/game_data.dart';
+import 'package:sudoku/models/game/board.dart';
+import 'package:sudoku/models/game/cell.dart';
+import 'package:sudoku/models/game/cell_location.dart';
+import 'package:sudoku/models/game/types.dart';
+import 'package:sudoku/models/settings/settings_game.dart';
+import 'package:sudoku/models/settings/settings_global.dart';
 import 'package:sudoku/utils/tools.dart';
 
 class Game {
   Game({
+    // Settings
     required this.gameSettings,
     required this.globalSettings,
+
+    // State
+    this.isRunning = false,
+    this.isStarted = false,
+    this.isFinished = false,
+    this.animationInProgress = false,
+    this.boardAnimated = const [],
+
+    // Base data
     required this.board,
     required this.solvedBoard,
-    required this.isRunning,
-    required this.isStarted,
-    required this.isFinished,
+    required this.blockSizeHorizontal,
+    required this.blockSizeVertical,
+    required this.boardSize,
+
+    // Game data
     this.shuffledCellValues = const [],
     this.boardConflicts = const [],
     this.selectedCell,
     this.showConflicts = false,
     this.givenTipsCount = 0,
     this.buttonTipsCountdown = 0,
-    this.animationInProgress = false,
-    this.boardAnimated = const [],
-    required this.blockSizeHorizontal,
-    required this.blockSizeVertical,
-    required this.boardSize,
   });
 
+  // Settings
   final GameSettings gameSettings;
   final GlobalSettings globalSettings;
 
-  bool isRunning = false;
-  bool isStarted = false;
-  bool isFinished = false;
-
-  int blockSizeVertical = 0;
-  int blockSizeHorizontal = 0;
-  int boardSize = 0;
-
-  Board board;
-  Board solvedBoard;
-
-  List<int> shuffledCellValues = [];
+  // State
+  bool isRunning;
+  bool isStarted;
+  bool isFinished;
+  bool animationInProgress;
+  AnimatedBoard boardAnimated;
+
+  // Base data
+  final Board board;
+  final Board solvedBoard;
+  final int blockSizeHorizontal;
+  final int blockSizeVertical;
+  final int boardSize;
+
+  // Game data
+  List<int> shuffledCellValues;
+  ConflictsCount boardConflicts;
   Cell? selectedCell;
+  bool showConflicts;
+  int givenTipsCount;
+  int buttonTipsCountdown;
 
-  int givenTipsCount = 0;
-  int buttonTipsCountdown = 0;
-  bool showConflicts = false;
-  ConflictsCount boardConflicts = [];
-
-  bool animationInProgress = false;
-  AnimatedBoard boardAnimated = [];
-
-  factory Game.createNull() {
+  factory Game.createEmpty() {
     return Game(
+      // Settings
       gameSettings: GameSettings.createDefault(),
       globalSettings: GlobalSettings.createDefault(),
+      // Base data
       board: Board.createEmpty(),
       solvedBoard: Board.createEmpty(),
-      shuffledCellValues: [],
-      isRunning: false,
-      isStarted: false,
-      isFinished: false,
-      givenTipsCount: 0,
       blockSizeHorizontal: 0,
       blockSizeVertical: 0,
       boardSize: 0,
+      // Game data
+      shuffledCellValues: [],
+      givenTipsCount: 0,
     );
   }
 
@@ -106,15 +113,15 @@ class Game {
     }
 
     final List<String> templates =
-        SudokuGrids.templates[newGameSettings.size]?[newGameSettings.level] ?? [];
+        GameData.templates[newGameSettings.size]?[newGameSettings.level] ?? [];
     final String template = templates.elementAt(Random().nextInt(templates.length)).toString();
 
     if (template.length != pow(blockSizeHorizontal * blockSizeVertical, 2)) {
       printlog('Failed to get grid template...');
-      return Game.createNull();
+      return Game.createEmpty();
     }
 
-    final Board board = BoardUtils.createBoardFromTemplate(
+    final Board board = Board.createFromTemplate(
       template: template,
       isSymetric: (blockSizeHorizontal == blockSizeVertical),
     );
@@ -131,26 +138,30 @@ class Game {
     }
 
     return Game(
+      // Settings
       gameSettings: newGameSettings,
       globalSettings: newGlobalSettings,
+      // State
+      isRunning: true,
+      boardAnimated: notAnimatedBoard,
+      // Base data
       board: board,
       solvedBoard: solvedBoard,
-      isRunning: true,
-      isStarted: false,
-      isFinished: false,
-      boardConflicts: nonConflictedBoard,
-      shuffledCellValues: shuffledCellValues,
-      selectedCell: null,
       blockSizeHorizontal: blockSizeHorizontal,
       blockSizeVertical: blockSizeVertical,
       boardSize: boardSize,
-      boardAnimated: notAnimatedBoard,
+      // Game data
+      shuffledCellValues: shuffledCellValues,
+      boardConflicts: nonConflictedBoard,
+      selectedCell: null,
     );
   }
 
-  bool canGiveTip() {
-    return (buttonTipsCountdown == 0);
-  }
+  bool get canBeResumed => isStarted && !isFinished;
+
+  bool get gameWon => isRunning && isStarted && isFinished;
+
+  bool get canGiveTip => (buttonTipsCountdown == 0);
 
   int getTranslatedValueForDisplay(int originalValue) {
     return shuffledCellValues[originalValue - 1];
@@ -274,7 +285,6 @@ class Game {
     // pick one of wrong value cells, if found
     final List<List<int>> wrongValueCells = getCellsWithWrongValue();
     if (wrongValueCells.isNotEmpty) {
-      printlog('will pick from wrongValueCells');
       pickRandomFromList(gameCubit, wrongValueCells);
       return;
     }
@@ -282,7 +292,6 @@ class Game {
     // pick one of conflicting cells, if found
     final List<List<int>> conflictingCells = getCellsWithConflicts();
     if (conflictingCells.isNotEmpty) {
-      printlog('will pick from conflictingCells');
       pickRandomFromList(gameCubit, conflictingCells);
       return;
     }
@@ -290,7 +299,6 @@ class Game {
     //  pick one form cells with unique non-conflicting candidate value
     final List<List<int>> candidateCells = board.getEmptyCellsWithUniqueAvailableValue();
     if (candidateCells.isNotEmpty) {
-      printlog('will pick from candidateCells');
       pickRandomFromList(gameCubit, candidateCells);
       return;
     }
@@ -354,6 +362,35 @@ class Game {
     gameCubit.unselectCell();
   }
 
+  void dump() {
+    printlog('');
+    printlog('## Current game dump:');
+    printlog('');
+    printlog('$Game:');
+    printlog('  Settings');
+    gameSettings.dump();
+    globalSettings.dump();
+    printlog('  State');
+    printlog('    isRunning: $isRunning');
+    printlog('    isStarted: $isStarted');
+    printlog('    isFinished: $isFinished');
+    printlog('    animationInProgress: $animationInProgress');
+    printlog('  Base data');
+    printlog('    blockSizeHorizontal: $blockSizeHorizontal');
+    printlog('    blockSizeVertical: $blockSizeVertical');
+    printlog('    boardSize: $boardSize');
+    printlog('  Game data');
+    printlog('    shuffledCellValues: $shuffledCellValues');
+    printlog('    selectedCell: ${selectedCell?.toString() ?? ''}');
+    printlog('    showConflicts: $showConflicts');
+    printlog('    givenTipsCount: $givenTipsCount');
+    printlog('    buttonTipsCountdown: $buttonTipsCountdown');
+    printlog('');
+
+    printGrid();
+    printlog('');
+  }
+
   printGrid() {
     final BoardCells cells = board.cells;
     final BoardCells solvedCells = solvedBoard.cells;
@@ -374,33 +411,6 @@ class Game {
     printlog('');
   }
 
-  void dump() {
-    printlog('');
-    printlog('## Current game dump:');
-    printlog('');
-    gameSettings.dump();
-    globalSettings.dump();
-    printlog('');
-    printlog('$Game:');
-    printlog('  blockSizeHorizontal: $blockSizeHorizontal');
-    printlog('  blockSizeVertical: $blockSizeVertical');
-    printlog('  boardSize: $boardSize');
-    printlog('  shuffledCellValues: $shuffledCellValues');
-    printlog('');
-    printlog('  isRunning: $isRunning');
-    printlog('  isStarted: $isStarted');
-    printlog('  isFinished: $isFinished');
-    printlog('  selectedCell: ${selectedCell?.toString() ?? ''}');
-    printlog('  showConflicts: $showConflicts');
-    printlog('  givenTipsCount: $givenTipsCount');
-    printlog('  givenTipsCountEnableCountdown: $buttonTipsCountdown');
-    printlog('  animationInProgress: $animationInProgress');
-    printlog('');
-
-    printGrid();
-    printlog('');
-  }
-
   @override
   String toString() {
     return '$Game(${toJson()})';
@@ -408,22 +418,28 @@ class Game {
 
   Map<String, dynamic>? toJson() {
     return <String, dynamic>{
+      // Settings
       'gameSettings': gameSettings.toJson(),
       'globalSettings': globalSettings.toJson(),
+      // State
       'isRunning': isRunning,
+      'isStarted': isStarted,
       'isFinished': isFinished,
+      'animationInProgress': animationInProgress,
+      'boardAnimated': boardAnimated,
+      // Base data
       'board': board.toJson(),
       'solvedBoard': solvedBoard.toJson(),
+      'blockSizeHorizontal': blockSizeHorizontal,
+      'blockSizeVertical': blockSizeVertical,
+      'boardSize': boardSize,
+      // Game data
       'shuffledCellValues': shuffledCellValues,
       'boardConflicts': boardConflicts,
       'selectedCell': selectedCell?.toJson(),
       'showConflicts': showConflicts,
       'givenTipsCount': givenTipsCount,
-      'givenTipsCountEnableCountdown': buttonTipsCountdown,
-      'animationInProgress': animationInProgress,
-      'boardAnimated': boardAnimated,
-      'blockSizeHorizontal': blockSizeHorizontal,
-      'blockSizeVertical': blockSizeVertical,
+      'buttonTipsCountdown': buttonTipsCountdown,
     };
   }
 }
diff --git a/lib/models/types.dart b/lib/models/game/types.dart
similarity index 79%
rename from lib/models/types.dart
rename to lib/models/game/types.dart
index 9f75508834cf3590dbc3ed2f1401b6d04bff3d6b..6fbdd107b12abaf5ba11a24f6dfdd8a6847c01cd 100644
--- a/lib/models/types.dart
+++ b/lib/models/game/types.dart
@@ -1,4 +1,4 @@
-import 'package:sudoku/models/cell.dart';
+import 'package:sudoku/models/game/cell.dart';
 
 typedef BoardCells = List<List<Cell>>;
 typedef ConflictsCount = List<List<int>>;
diff --git a/lib/models/settings_game.dart b/lib/models/settings/settings_game.dart
similarity index 96%
rename from lib/models/settings_game.dart
rename to lib/models/settings/settings_game.dart
index 8786fc9279dc6f3c1893ff606105999b21d501c8..17380bd51c0851df263b635596666cb9f1bd17a7 100644
--- a/lib/models/settings_game.dart
+++ b/lib/models/settings/settings_game.dart
@@ -2,8 +2,8 @@ import 'package:sudoku/config/default_game_settings.dart';
 import 'package:sudoku/utils/tools.dart';
 
 class GameSettings {
-  String level;
-  String size;
+  final String level;
+  final String size;
 
   GameSettings({
     required this.level,
diff --git a/lib/models/settings_global.dart b/lib/models/settings/settings_global.dart
similarity index 100%
rename from lib/models/settings_global.dart
rename to lib/models/settings/settings_global.dart
diff --git a/lib/ui/game/game_bottom.dart b/lib/ui/game/game_bottom.dart
new file mode 100644
index 0000000000000000000000000000000000000000..954defbe05eb232d3bb9f068093795fe7dff31c3
--- /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:sudoku/cubit/game_cubit.dart';
+import 'package:sudoku/models/game/game.dart';
+import 'package:sudoku/ui/widgets/game/bar_select_cell_value.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 SizedBox.shrink() : const SelectCellValueBar();
+      },
+    );
+  }
+}
diff --git a/lib/ui/widgets/message_game_end.dart b/lib/ui/game/game_end.dart
similarity index 63%
rename from lib/ui/widgets/message_game_end.dart
rename to lib/ui/game/game_end.dart
index 8716d31d8ea27bd364cfe71b8c504e6484525e7a..d24db593d3d1ab251e06b5c06bb749679759f3b4 100644
--- a/lib/ui/widgets/message_game_end.dart
+++ b/lib/ui/game/game_end.dart
@@ -2,20 +2,21 @@ import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 
 import 'package:sudoku/cubit/game_cubit.dart';
-import 'package:sudoku/models/game.dart';
-import 'package:sudoku/ui/widgets/button_game_restart.dart';
+import 'package:sudoku/models/game/game.dart';
+import 'package:sudoku/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) {
     return BlocBuilder<GameCubit, GameState>(
       builder: (BuildContext context, GameState gameState) {
-        final Game game = gameState.game;
+        final Game currentGame = gameState.currentGame;
 
-        const Image decorationImage = Image(
-          image: AssetImage('assets/icons/game_win.png'),
+        final Image decorationImage = Image(
+          image: AssetImage(
+              currentGame.gameWon ? 'assets/ui/game_win.png' : 'assets/ui/game_fail.png'),
           fit: BoxFit.fill,
         );
 
@@ -27,17 +28,17 @@ class EndGameMessage extends StatelessWidget {
             children: [
               TableRow(
                 children: [
-                  const Column(
+                  Column(
                     children: [decorationImage],
                   ),
                   Column(
                     children: [
-                      game.animationInProgress == true
+                      currentGame.animationInProgress == true
                           ? decorationImage
-                          : const RestartGameButton()
+                          : const QuitGameButton()
                     ],
                   ),
-                  const Column(
+                  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..5bac69a675b68fae7d3fc6f8ec8f45f37bf9e545
--- /dev/null
+++ b/lib/ui/game/game_top.dart
@@ -0,0 +1,34 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:sudoku/cubit/game_cubit.dart';
+import 'package:sudoku/models/game/game.dart';
+import 'package:sudoku/ui/widgets/game/button_show_conflicts.dart';
+import 'package:sudoku/ui/widgets/game/button_show_tip.dart';
+
+class GameTopWidget extends StatelessWidget {
+  const GameTopWidget({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        final Game currentGame = gameState.currentGame;
+
+        return SizedBox(
+          height: 60,
+          child: (currentGame.isRunning && !currentGame.isFinished)
+              ? const Row(
+                  mainAxisAlignment: MainAxisAlignment.end,
+                  crossAxisAlignment: CrossAxisAlignment.center,
+                  children: [
+                    ButtonShowTip(),
+                    ButtonShowConflicts(),
+                  ],
+                )
+              : const SizedBox.shrink(),
+        );
+      },
+    );
+  }
+}
diff --git a/lib/ui/helpers/app_titles.dart b/lib/ui/helpers/app_titles.dart
new file mode 100644
index 0000000000000000000000000000000000000000..b98107b12fabc3114ebfbec994166b588abcf1ad
--- /dev/null
+++ b/lib/ui/helpers/app_titles.dart
@@ -0,0 +1,32 @@
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+
+class AppHeader extends StatelessWidget {
+  const AppHeader({super.key, required this.text});
+
+  final String text;
+
+  @override
+  Widget build(BuildContext context) {
+    return Text(
+      tr(text),
+      textAlign: TextAlign.start,
+      style: Theme.of(context).textTheme.headlineMedium!.apply(fontWeightDelta: 2),
+    );
+  }
+}
+
+class AppTitle extends StatelessWidget {
+  const AppTitle({super.key, required this.text});
+
+  final String text;
+
+  @override
+  Widget build(BuildContext context) {
+    return Text(
+      tr(text),
+      textAlign: TextAlign.start,
+      style: Theme.of(context).textTheme.titleLarge!.apply(fontWeightDelta: 2),
+    );
+  }
+}
diff --git a/lib/ui/helpers/outlined_text_widget.dart b/lib/ui/helpers/outlined_text_widget.dart
new file mode 100644
index 0000000000000000000000000000000000000000..342eb310db85d9cf969b70003d514441d3794a11
--- /dev/null
+++ b/lib/ui/helpers/outlined_text_widget.dart
@@ -0,0 +1,51 @@
+import 'package:flutter/material.dart';
+
+import 'package:sudoku/utils/color_extensions.dart';
+
+class OutlinedText extends StatelessWidget {
+  const OutlinedText({
+    super.key,
+    required this.text,
+    required this.fontSize,
+    required this.textColor,
+    this.outlineColor,
+  });
+
+  final String text;
+  final double fontSize;
+  final Color textColor;
+  final Color? outlineColor;
+
+  @override
+  Widget build(BuildContext context) {
+    final double delta = fontSize / 30;
+
+    return Text(
+      text,
+      style: TextStyle(
+        inherit: true,
+        fontSize: fontSize,
+        fontWeight: FontWeight.w600,
+        color: textColor,
+        shadows: [
+          Shadow(
+            offset: Offset(-delta, -delta),
+            color: outlineColor ?? textColor.darken(),
+          ),
+          Shadow(
+            offset: Offset(delta, -delta),
+            color: outlineColor ?? textColor.darken(),
+          ),
+          Shadow(
+            offset: Offset(delta, delta),
+            color: outlineColor ?? textColor.darken(),
+          ),
+          Shadow(
+            offset: Offset(-delta, delta),
+            color: outlineColor ?? textColor.darken(),
+          ),
+        ],
+      ),
+    );
+  }
+}
diff --git a/lib/ui/widgets/game.dart b/lib/ui/layouts/game_layout.dart
similarity index 53%
rename from lib/ui/widgets/game.dart
rename to lib/ui/layouts/game_layout.dart
index b9160d1501bfb93262fb30b17dcb4fae3e6048f4..349f9c241d67edea6675543e659e97b473cef748 100644
--- a/lib/ui/widgets/game.dart
+++ b/lib/ui/layouts/game_layout.dart
@@ -2,32 +2,35 @@ import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 
 import 'package:sudoku/cubit/game_cubit.dart';
-import 'package:sudoku/models/game.dart';
-import 'package:sudoku/ui/layout/board.dart';
-import 'package:sudoku/ui/widgets/message_game_end.dart';
-import 'package:sudoku/ui/widgets/bar_select_cell_value.dart';
+import 'package:sudoku/models/game/game.dart';
+import 'package:sudoku/ui/game/game_bottom.dart';
+import 'package:sudoku/ui/game/game_end.dart';
+import 'package:sudoku/ui/game/game_top.dart';
+import 'package:sudoku/ui/widgets/game/game_board.dart';
 
-class GameWidget extends StatelessWidget {
-  const GameWidget({super.key});
+class GameLayout extends StatelessWidget {
+  const GameLayout({super.key});
 
   @override
   Widget build(BuildContext context) {
     return BlocBuilder<GameCubit, GameState>(
       builder: (BuildContext context, GameState gameState) {
-        final Game game = gameState.game;
+        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 BoardLayout(),
+              const GameBoardWidget(),
               const SizedBox(height: 8),
-              game.isFinished ? const SizedBox.shrink() : const SelectCellValueBar(),
+              const GameBottomWidget(),
               const Expanded(child: SizedBox.shrink()),
-              game.isFinished ? const EndGameMessage() : const 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 67%
rename from lib/ui/widgets/parameters.dart
rename to lib/ui/layouts/parameters_layout.dart
index 4018b051e351beb372bea58e5fb69e64b7ec3584..22411b7c9b331536cb1386d0d8107938d2a5ccef 100644
--- a/lib/ui/widgets/parameters.dart
+++ b/lib/ui/layouts/parameters_layout.dart
@@ -5,14 +5,14 @@ import 'package:sudoku/config/default_game_settings.dart';
 import 'package:sudoku/config/default_global_settings.dart';
 import 'package:sudoku/cubit/settings_game_cubit.dart';
 import 'package:sudoku/cubit/settings_global_cubit.dart';
-import 'package:sudoku/ui/painters/parameter_painter.dart';
-import 'package:sudoku/ui/widgets/button_delete_saved_game.dart';
-import 'package:sudoku/ui/widgets/button_game_start_new.dart';
-import 'package:sudoku/ui/widgets/button_resume_saved_game.dart';
-import 'package:sudoku/ui/widgets/parameter_image.dart';
+import 'package:sudoku/ui/parameters/parameter_image.dart';
+import 'package:sudoku/ui/parameters/parameter_painter.dart';
+import 'package:sudoku/ui/widgets/actions/button_delete_saved_game.dart';
+import 'package:sudoku/ui/widgets/actions/button_game_start_new.dart';
+import 'package:sudoku/ui/widgets/actions/button_resume_saved_game.dart';
 
-class Parameters extends StatelessWidget {
-  const Parameters({super.key, required this.canResume});
+class ParametersLayout extends StatelessWidget {
+  const ParametersLayout({super.key, required this.canResume});
 
   final bool canResume;
 
@@ -22,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(
@@ -38,26 +36,35 @@ class Parameters extends StatelessWidget {
     }
 
     lines.add(SizedBox(height: separatorHeight));
-    lines.add(Expanded(
-      child: canResume ? const ResumeSavedGameButton() : const StartNewGameButton(),
-    ));
-    lines.add(SizedBox.square(
-      dimension: MediaQuery.of(context).size.width / 4,
-      child: canResume ? const DeleteSavedGameButton() : const SizedBox.shrink(),
-    ));
+
+    if (canResume == false) {
+      // Start new game
+      lines.add(const Expanded(
+        child: StartNewGameButton(),
+      ));
+    } else {
+      // Resume game
+      lines.add(const Expanded(
+        child: ResumeSavedGameButton(),
+      ));
+      // Delete saved game
+      lines.add(SizedBox.square(
+        dimension: MediaQuery.of(context).size.width / 4,
+        child: const DeleteSavedGameButton(),
+      ));
+    }
+
     lines.add(SizedBox(height: separatorHeight));
 
     // Global settings
     for (String code in DefaultGlobalSettings.availableParameters) {
-      lines.add(
-        Row(
-          mainAxisAlignment: MainAxisAlignment.spaceBetween,
-          children: buildParametersLine(
-            code: code,
-            isGlobal: true,
-          ),
+      lines.add(Row(
+        mainAxisAlignment: MainAxisAlignment.spaceBetween,
+        children: buildParametersLine(
+          code: code,
+          isGlobal: true,
         ),
-      );
+      ));
 
       lines.add(SizedBox(height: separatorHeight));
     }
@@ -77,6 +84,10 @@ class Parameters extends StatelessWidget {
         ? DefaultGlobalSettings.getAvailableValues(code)
         : DefaultGameSettings.getAvailableValues(code);
 
+    if (availableValues.length <= 1) {
+      return [];
+    }
+
     for (String value in availableValues) {
       final Widget parameterButton = BlocBuilder<GameSettingsCubit, GameSettingsState>(
         builder: (BuildContext context, GameSettingsState gameSettingsState) {
@@ -94,14 +105,24 @@ class Parameters extends StatelessWidget {
               final bool isActive = (value == currentValue);
 
               final double displayWidth = MediaQuery.of(context).size.width;
-              final double itemWidth = displayWidth / availableValues.length - 25;
+              final double itemWidth = displayWidth / availableValues.length - 26;
 
-              final bool isPainterOrAsset = (code != DefaultGlobalSettings.parameterCodeSkin);
+              final bool displayedWithAssets =
+                  DefaultGlobalSettings.displayedWithAssets.contains(code) ||
+                      DefaultGameSettings.displayedWithAssets.contains(code);
 
               return TextButton(
                 child: Container(
-                  child: isPainterOrAsset
-                      ? CustomPaint(
+                  child: displayedWithAssets
+                      ? SizedBox.square(
+                          dimension: itemWidth,
+                          child: ParameterImage(
+                            code: code,
+                            value: value,
+                            isSelected: isActive,
+                          ),
+                        )
+                      : CustomPaint(
                           size: Size(itemWidth, itemWidth),
                           willChange: false,
                           painter: ParameterPainter(
@@ -112,19 +133,13 @@ class Parameters extends StatelessWidget {
                             globalSettings: globalSettingsState.settings,
                           ),
                           isComplex: true,
-                        )
-                      : SizedBox.square(
-                          dimension: itemWidth,
-                          child: ParameterImage(
-                            code: code,
-                            value: value,
-                            isSelected: isActive,
-                          ),
                         ),
                 ),
-                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/widgets/parameter_image.dart b/lib/ui/parameters/parameter_image.dart
similarity index 94%
rename from lib/ui/widgets/parameter_image.dart
rename to lib/ui/parameters/parameter_image.dart
index 54787e2c0a15c8f84c218181e7f06b9624a5d88d..fc4b576f85b01158b74548400d11a4d027c57fbe 100644
--- a/lib/ui/widgets/parameter_image.dart
+++ b/lib/ui/parameters/parameter_image.dart
@@ -30,7 +30,7 @@ class ParameterImage extends StatelessWidget {
         ),
       ),
       child: Image(
-        image: AssetImage('assets/icons/${code}_$value.png'),
+        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 95%
rename from lib/ui/painters/parameter_painter.dart
rename to lib/ui/parameters/parameter_painter.dart
index a409d1173f4b93fe5de5b2474d6ea2c7825a012c..714acdc3b9a8c925757fade4a34a4223479b0c01 100644
--- a/lib/ui/painters/parameter_painter.dart
+++ b/lib/ui/parameters/parameter_painter.dart
@@ -3,8 +3,8 @@ import 'dart:math';
 import 'package:flutter/material.dart';
 
 import 'package:sudoku/config/default_game_settings.dart';
-import 'package:sudoku/models/settings_game.dart';
-import 'package:sudoku/models/settings_global.dart';
+import 'package:sudoku/models/settings/settings_game.dart';
+import 'package:sudoku/models/settings/settings_global.dart';
 import 'package:sudoku/utils/tools.dart';
 
 class ParameterPainter extends CustomPainter {
@@ -35,7 +35,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);
 
@@ -66,7 +66,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;
@@ -83,6 +83,7 @@ class ParameterPainter extends CustomPainter {
     final textPainter = TextPainter(
       text: textSpan,
       textDirection: TextDirection.ltr,
+      textAlign: TextAlign.center,
     );
     textPainter.layout();
     textPainter.paint(
@@ -151,6 +152,7 @@ class ParameterPainter extends CustomPainter {
     final textPainter = TextPainter(
       text: textSpan,
       textDirection: TextDirection.ltr,
+      textAlign: TextAlign.center,
     );
     textPainter.layout();
 
@@ -201,7 +203,7 @@ class ParameterPainter extends CustomPainter {
 
     final paint = Paint();
     paint.strokeJoin = StrokeJoin.round;
-    paint.strokeWidth = 5 / 100 * size;
+    paint.strokeWidth = 3;
 
     // Colored background
     paint.color = backgroundColor;
diff --git a/lib/ui/screens/game_page.dart b/lib/ui/screens/game_page.dart
deleted file mode 100644
index 9a8173f5daedae2e2254e2d264c8dfa98acb62ec..0000000000000000000000000000000000000000
--- a/lib/ui/screens/game_page.dart
+++ /dev/null
@@ -1,26 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-
-import 'package:sudoku/cubit/game_cubit.dart';
-import 'package:sudoku/ui/widgets/game.dart';
-import 'package:sudoku/ui/widgets/parameters.dart';
-
-class GamePage extends StatelessWidget {
-  const GamePage({super.key});
-
-  @override
-  Widget build(BuildContext context) {
-    return Material(
-      color: Theme.of(context).colorScheme.background,
-      child: BlocBuilder<GameCubit, GameState>(
-        builder: (BuildContext context, GameState gameState) {
-          return gameState.game.isRunning
-              ? const GameWidget()
-              : Parameters(
-                  canResume: gameState.game.isStarted && !gameState.game.isFinished,
-                );
-        },
-      ),
-    );
-  }
-}
diff --git a/lib/ui/screens/about_page.dart b/lib/ui/screens/page_about.dart
similarity index 86%
rename from lib/ui/screens/about_page.dart
rename to lib/ui/screens/page_about.dart
index ca78fa0052ef629a1b5c93078e17478398ee0ccf..f007546869db855ce8f714854307efd1b733fa7f 100644
--- a/lib/ui/screens/about_page.dart
+++ b/lib/ui/screens/page_about.dart
@@ -2,10 +2,10 @@ import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/material.dart';
 import 'package:package_info_plus/package_info_plus.dart';
 
-import 'package:sudoku/ui/widgets/header_app.dart';
+import 'package:sudoku/ui/helpers/app_titles.dart';
 
-class AboutPage extends StatelessWidget {
-  const AboutPage({super.key});
+class PageAbout extends StatelessWidget {
+  const PageAbout({super.key});
 
   @override
   Widget build(BuildContext context) {
@@ -17,7 +17,7 @@ class AboutPage extends StatelessWidget {
         mainAxisSize: MainAxisSize.max,
         children: <Widget>[
           const SizedBox(height: 8),
-          const AppHeader(text: 'about_title'),
+          const AppTitle(text: 'about_title'),
           const Text('about_content').tr(),
           FutureBuilder<PackageInfo>(
             future: PackageInfo.fromPlatform(),
diff --git a/lib/ui/screens/page_game.dart b/lib/ui/screens/page_game.dart
new file mode 100644
index 0000000000000000000000000000000000000000..e3a72cde236a4f017b9ab6a72abfce22ba0f03f0
--- /dev/null
+++ b/lib/ui/screens/page_game.dart
@@ -0,0 +1,24 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:sudoku/cubit/game_cubit.dart';
+import 'package:sudoku/models/game/game.dart';
+import 'package:sudoku/ui/layouts/game_layout.dart';
+import 'package:sudoku/ui/layouts/parameters_layout.dart';
+
+class PageGame extends StatelessWidget {
+  const PageGame({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        final Game currentGame = gameState.currentGame;
+
+        return currentGame.isRunning
+            ? const GameLayout()
+            : ParametersLayout(canResume: currentGame.canBeResumed);
+      },
+    );
+  }
+}
diff --git a/lib/ui/screens/settings_page.dart b/lib/ui/screens/page_settings.dart
similarity index 66%
rename from lib/ui/screens/settings_page.dart
rename to lib/ui/screens/page_settings.dart
index aea7bd57c4fdb3cd841704474c3f2701d4482886..308e42063b987cc7a00b57f8da4a0d779289e66a 100644
--- a/lib/ui/screens/settings_page.dart
+++ b/lib/ui/screens/page_settings.dart
@@ -1,10 +1,10 @@
 import 'package:flutter/material.dart';
 
-import 'package:sudoku/ui/widgets/header_app.dart';
-import 'package:sudoku/ui/widgets/settings/settings_form.dart';
+import 'package:sudoku/ui/helpers/app_titles.dart';
+import 'package:sudoku/ui/settings/settings_form.dart';
 
-class SettingsPage extends StatelessWidget {
-  const SettingsPage({super.key});
+class PageSettings extends StatelessWidget {
+  const PageSettings({super.key});
 
   @override
   Widget build(BuildContext context) {
@@ -16,7 +16,7 @@ class SettingsPage extends StatelessWidget {
         mainAxisSize: MainAxisSize.max,
         children: <Widget>[
           SizedBox(height: 8),
-          AppHeader(text: 'settings_title'),
+          AppTitle(text: 'settings_title'),
           SizedBox(height: 8),
           SettingsForm(),
         ],
diff --git a/lib/ui/widgets/settings/settings_form.dart b/lib/ui/settings/settings_form.dart
similarity index 96%
rename from lib/ui/widgets/settings/settings_form.dart
rename to lib/ui/settings/settings_form.dart
index 53576c1707629807221d4924c29b9e558f66c05c..bbde015eed9d2a43e0c1fdc0f4cd24314805920e 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:sudoku/ui/widgets/settings/theme_card.dart';
+import 'package:sudoku/ui/settings/theme_card.dart';
 
 class SettingsForm extends StatefulWidget {
   const SettingsForm({super.key});
diff --git a/lib/ui/widgets/settings/theme_card.dart b/lib/ui/settings/theme_card.dart
similarity index 100%
rename from lib/ui/widgets/settings/theme_card.dart
rename to lib/ui/settings/theme_card.dart
diff --git a/lib/ui/skeleton.dart b/lib/ui/skeleton.dart
index 0923b76265684776763e9838abff96bedebd881a..dc4027b379ff137d67d1b97c423f212526d1b8e6 100644
--- a/lib/ui/skeleton.dart
+++ b/lib/ui/skeleton.dart
@@ -13,12 +13,22 @@ class SkeletonScreen extends StatelessWidget {
     return Scaffold(
       appBar: const GlobalAppBar(),
       extendBodyBehindAppBar: false,
-      body: BlocBuilder<NavCubit, int>(
-        builder: (BuildContext context, int pageIndex) {
-          return Menu.getPageWidget(pageIndex);
-        },
+      body: Material(
+        color: Theme.of(context).colorScheme.surface,
+        child: BlocBuilder<NavCubit, int>(
+          builder: (BuildContext context, int pageIndex) {
+            return Padding(
+              padding: const EdgeInsets.only(
+                top: 8,
+                left: 2,
+                right: 2,
+              ),
+              child: Menu.getPageWidget(pageIndex),
+            );
+          },
+        ),
       ),
-      backgroundColor: Theme.of(context).colorScheme.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..403b2fb174f51eeae1caa48524d4c0fc08f0d2c2
--- /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:sudoku/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..c25e7605fbfdf65ff94163c713b7bb4396a0cdc0
--- /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:sudoku/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 6cd2d639331d1a8da0f8a77806faa0d02de97379..619f7673d8ffab3d0f942d07bd31235cb4c4d703 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..216a71e090ccdd45d291c4d27a235dfa187d755c
--- /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:sudoku/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/button_delete_saved_game.dart b/lib/ui/widgets/button_delete_saved_game.dart
deleted file mode 100644
index fa18bcefd95d5d5dce7e8378e5e5c55b11fc0d67..0000000000000000000000000000000000000000
--- a/lib/ui/widgets/button_delete_saved_game.dart
+++ /dev/null
@@ -1,27 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-
-import 'package:sudoku/cubit/game_cubit.dart';
-
-class DeleteSavedGameButton extends StatelessWidget {
-  const DeleteSavedGameButton({super.key});
-
-  @override
-  Widget build(BuildContext context) {
-    return BlocBuilder<GameCubit, GameState>(
-      builder: (BuildContext context, GameState gameState) {
-        final GameCubit gameCubit = BlocProvider.of<GameCubit>(context);
-
-        return TextButton(
-          child: const Image(
-            image: AssetImage('assets/icons/button_delete_saved_game.png'),
-            fit: BoxFit.fill,
-          ),
-          onPressed: () {
-            gameCubit.deleteSavedGame();
-          },
-        );
-      },
-    );
-  }
-}
diff --git a/lib/ui/widgets/button_game_restart.dart b/lib/ui/widgets/button_game_restart.dart
deleted file mode 100644
index 1da7f3934aa4b1e8184e925cbdf207d719f0d9e5..0000000000000000000000000000000000000000
--- a/lib/ui/widgets/button_game_restart.dart
+++ /dev/null
@@ -1,27 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-
-import 'package:sudoku/cubit/game_cubit.dart';
-
-class RestartGameButton extends StatelessWidget {
-  const RestartGameButton({super.key});
-
-  @override
-  Widget build(BuildContext context) {
-    return BlocBuilder<GameCubit, GameState>(
-      builder: (BuildContext context, GameState gameState) {
-        final GameCubit gameCubit = BlocProvider.of<GameCubit>(context);
-
-        return TextButton(
-          child: const Image(
-            image: AssetImage('assets/icons/button_back.png'),
-            fit: BoxFit.fill,
-          ),
-          onPressed: () {
-            gameCubit.quitGame();
-          },
-        );
-      },
-    );
-  }
-}
diff --git a/lib/ui/widgets/button_resume_saved_game.dart b/lib/ui/widgets/button_resume_saved_game.dart
deleted file mode 100644
index 316a318410fc458937a964a5afdd13752cdff72e..0000000000000000000000000000000000000000
--- a/lib/ui/widgets/button_resume_saved_game.dart
+++ /dev/null
@@ -1,27 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-
-import 'package:sudoku/cubit/game_cubit.dart';
-
-class ResumeSavedGameButton extends StatelessWidget {
-  const ResumeSavedGameButton({super.key});
-
-  @override
-  Widget build(BuildContext context) {
-    return BlocBuilder<GameCubit, GameState>(
-      builder: (BuildContext context, GameState gameState) {
-        final GameCubit gameCubit = BlocProvider.of<GameCubit>(context);
-
-        return TextButton(
-          child: const Image(
-            image: AssetImage('assets/icons/button_resume_game.png'),
-            fit: BoxFit.fill,
-          ),
-          onPressed: () {
-            gameCubit.resumeSavedGame();
-          },
-        );
-      },
-    );
-  }
-}
diff --git a/lib/ui/widgets/bar_select_cell_value.dart b/lib/ui/widgets/game/bar_select_cell_value.dart
similarity index 88%
rename from lib/ui/widgets/bar_select_cell_value.dart
rename to lib/ui/widgets/game/bar_select_cell_value.dart
index 7ace4cb54c741ca357ac147567333fe755b6998a..875135122c80fa6765da1446e1eaf55451f556a4 100644
--- a/lib/ui/widgets/bar_select_cell_value.dart
+++ b/lib/ui/widgets/game/bar_select_cell_value.dart
@@ -4,10 +4,10 @@ import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 
 import 'package:sudoku/cubit/game_cubit.dart';
-import 'package:sudoku/models/cell.dart';
-import 'package:sudoku/models/cell_location.dart';
-import 'package:sudoku/models/game.dart';
-import 'package:sudoku/ui/widgets/cell_widget_update.dart';
+import 'package:sudoku/models/game/cell.dart';
+import 'package:sudoku/models/game/cell_location.dart';
+import 'package:sudoku/models/game/game.dart';
+import 'package:sudoku/ui/widgets/game/cell_update.dart';
 
 class SelectCellValueBar extends StatelessWidget {
   const SelectCellValueBar({super.key});
@@ -16,7 +16,7 @@ class SelectCellValueBar extends StatelessWidget {
   Widget build(BuildContext context) {
     return BlocBuilder<GameCubit, GameState>(
       builder: (BuildContext context, GameState gameState) {
-        final Game game = gameState.game;
+        final Game game = gameState.currentGame;
 
         final bool isUpdatableCellSelected =
             (game.selectedCell != null) ? !game.selectedCell!.isFixed : false;
diff --git a/lib/ui/widgets/game/button_show_conflicts.dart b/lib/ui/widgets/game/button_show_conflicts.dart
new file mode 100644
index 0000000000000000000000000000000000000000..5326b64e06c4a2adc92d13b7c260ea2aab4742d4
--- /dev/null
+++ b/lib/ui/widgets/game/button_show_conflicts.dart
@@ -0,0 +1,37 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:sudoku/cubit/game_cubit.dart';
+import 'package:sudoku/models/game/game.dart';
+
+class ButtonShowConflicts extends StatelessWidget {
+  const ButtonShowConflicts({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        final Game currentGame = gameState.currentGame;
+
+        return TextButton(
+          child: Container(
+            decoration: BoxDecoration(
+              borderRadius: BorderRadius.circular(4),
+              border: Border.all(
+                color: currentGame.showConflicts == true ? Colors.blue : Colors.white,
+                width: 3,
+              ),
+            ),
+            child: const Image(
+              image: AssetImage('assets/ui/button_show_conflicts.png'),
+              fit: BoxFit.fill,
+            ),
+          ),
+          onPressed: () {
+            BlocProvider.of<GameCubit>(context).toggleShowConflicts();
+          },
+        );
+      },
+    );
+  }
+}
diff --git a/lib/ui/widgets/game/button_show_tip.dart b/lib/ui/widgets/game/button_show_tip.dart
new file mode 100644
index 0000000000000000000000000000000000000000..842d632abb593992e4ea65b8a6ce008b1a8be1b3
--- /dev/null
+++ b/lib/ui/widgets/game/button_show_tip.dart
@@ -0,0 +1,60 @@
+import 'package:badges/badges.dart' as badges;
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:sudoku/config/default_global_settings.dart';
+import 'package:sudoku/cubit/game_cubit.dart';
+import 'package:sudoku/models/game/game.dart';
+
+class ButtonShowTip extends StatelessWidget {
+  const ButtonShowTip({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        final Game currentGame = gameState.currentGame;
+
+        return TextButton(
+          child: Container(
+            decoration: BoxDecoration(
+              borderRadius: BorderRadius.circular(4),
+              border: Border.all(
+                color: Colors.white,
+                width: 3,
+              ),
+            ),
+            child: badges.Badge(
+              showBadge: currentGame.givenTipsCount == 0 ? false : true,
+              badgeStyle: badges.BadgeStyle(
+                badgeColor: currentGame.givenTipsCount < 10
+                    ? Colors.green
+                    : currentGame.givenTipsCount < 20
+                        ? Colors.orange
+                        : Colors.red,
+              ),
+              badgeContent: Text(
+                currentGame.givenTipsCount == 0 ? '' : currentGame.givenTipsCount.toString(),
+                style: const TextStyle(color: Colors.white),
+              ),
+              child: Container(
+                padding: EdgeInsets.all(15 *
+                    currentGame.buttonTipsCountdown /
+                    DefaultGlobalSettings.defaultTipCountDownValueInSeconds),
+                child: const Image(
+                  image: AssetImage('assets/ui/button_help.png'),
+                  fit: BoxFit.fill,
+                ),
+              ),
+            ),
+          ),
+          onPressed: () {
+            currentGame.canGiveTip
+                ? currentGame.showTip(BlocProvider.of<GameCubit>(context))
+                : null;
+          },
+        );
+      },
+    );
+  }
+}
diff --git a/lib/ui/widgets/cell_widget.dart b/lib/ui/widgets/game/cell.dart
similarity index 96%
rename from lib/ui/widgets/cell_widget.dart
rename to lib/ui/widgets/game/cell.dart
index 6bc02008ddbc0b353bf548705d2366ac8285638c..2a7c4f9bf83217bbd82c7e042dc8b5e67c60e439 100644
--- a/lib/ui/widgets/cell_widget.dart
+++ b/lib/ui/widgets/game/cell.dart
@@ -2,8 +2,8 @@ import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 
 import 'package:sudoku/cubit/game_cubit.dart';
-import 'package:sudoku/models/cell.dart';
-import 'package:sudoku/models/game.dart';
+import 'package:sudoku/models/game/cell.dart';
+import 'package:sudoku/models/game/game.dart';
 
 class CellWidget extends StatelessWidget {
   const CellWidget({super.key, required this.cell});
@@ -14,7 +14,7 @@ class CellWidget extends StatelessWidget {
   Widget build(BuildContext context) {
     return BlocBuilder<GameCubit, GameState>(
       builder: (BuildContext context, GameState gameState) {
-        final Game game = gameState.game;
+        final Game game = gameState.currentGame;
 
         final String imageAsset = getImageAssetName(game);
 
@@ -60,7 +60,7 @@ class CellWidget extends StatelessWidget {
       return 'assets/skins/${game.globalSettings.skin}_$cellValue.png';
     }
 
-    return 'assets/icons/cell_empty.png';
+    return 'assets/ui/cell_empty.png';
   }
 
   // Compute cell background color, from cell state
diff --git a/lib/ui/widgets/cell_widget_update.dart b/lib/ui/widgets/game/cell_update.dart
similarity index 91%
rename from lib/ui/widgets/cell_widget_update.dart
rename to lib/ui/widgets/game/cell_update.dart
index 37371a5278fe3b456e551f2d69d17f5320748d75..629829e3a4a4915a339bd7af9539874421fc8786 100644
--- a/lib/ui/widgets/cell_widget_update.dart
+++ b/lib/ui/widgets/game/cell_update.dart
@@ -2,8 +2,8 @@ import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 
 import 'package:sudoku/cubit/game_cubit.dart';
-import 'package:sudoku/models/cell.dart';
-import 'package:sudoku/models/game.dart';
+import 'package:sudoku/models/game/cell.dart';
+import 'package:sudoku/models/game/game.dart';
 
 class CellWidgetUpdate extends StatelessWidget {
   const CellWidgetUpdate({super.key, this.cell});
@@ -14,7 +14,7 @@ class CellWidgetUpdate extends StatelessWidget {
   Widget build(BuildContext context) {
     return BlocBuilder<GameCubit, GameState>(
       builder: (BuildContext context, GameState gameState) {
-        final Game game = gameState.game;
+        final Game game = gameState.currentGame;
 
         if ((cell?.value ?? 0) < 0) {
           return Container();
@@ -66,6 +66,6 @@ class CellWidgetUpdate extends StatelessWidget {
       return 'assets/skins/${game.globalSettings.skin}_$cellValue.png';
     }
 
-    return 'assets/icons/cell_empty.png';
+    return 'assets/ui/cell_empty.png';
   }
 }
diff --git a/lib/ui/layout/board.dart b/lib/ui/widgets/game/game_board.dart
similarity index 68%
rename from lib/ui/layout/board.dart
rename to lib/ui/widgets/game/game_board.dart
index 188d51c6699e608a8a55ff3a6700d6fa8176b211..559a6c07dd3474b2cecac00f08973e7259fae3bd 100644
--- a/lib/ui/layout/board.dart
+++ b/lib/ui/widgets/game/game_board.dart
@@ -2,20 +2,20 @@ import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 
 import 'package:sudoku/cubit/game_cubit.dart';
-import 'package:sudoku/models/cell_location.dart';
-import 'package:sudoku/models/game.dart';
-import 'package:sudoku/ui/widgets/cell_widget.dart';
+import 'package:sudoku/models/game/cell_location.dart';
+import 'package:sudoku/models/game/game.dart';
+import 'package:sudoku/ui/widgets/game/cell.dart';
 
-class BoardLayout extends StatelessWidget {
-  const BoardLayout({super.key});
+class GameBoardWidget extends StatelessWidget {
+  const GameBoardWidget({super.key});
 
   @override
   Widget build(BuildContext context) {
     return BlocBuilder<GameCubit, GameState>(
       builder: (BuildContext context, GameState gameState) {
-        final Game game = gameState.game;
+        final Game currentGame = gameState.currentGame;
 
-        final Color borderColor = Theme.of(context).colorScheme.onBackground;
+        final Color borderColor = Theme.of(context).colorScheme.onSurface;
 
         return Container(
           margin: const EdgeInsets.all(2),
@@ -33,13 +33,14 @@ class BoardLayout extends StatelessWidget {
               Table(
                 defaultColumnWidth: const IntrinsicColumnWidth(),
                 children: [
-                  for (int row = 0; row < game.boardSize; row++)
+                  for (int row = 0; row < currentGame.boardSize; row++)
                     TableRow(
                       children: [
-                        for (int col = 0; col < game.boardSize; col++)
+                        for (int col = 0; col < currentGame.boardSize; col++)
                           Column(
                             children: [
-                              CellWidget(cell: game.board.get(CellLocation.go(row, col)))
+                              CellWidget(
+                                  cell: currentGame.board.get(CellLocation.go(row, col)))
                             ],
                           ),
                       ],
diff --git a/lib/ui/widgets/global_app_bar.dart b/lib/ui/widgets/global_app_bar.dart
index 7a4df12a7bbb36017b852e637bd10376bcf9f704..8bb1ea1a8a23e00059817440ad720570f2c6a013 100644
--- a/lib/ui/widgets/global_app_bar.dart
+++ b/lib/ui/widgets/global_app_bar.dart
@@ -1,12 +1,10 @@
-import 'package:badges/badges.dart' as badges;
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 
-import 'package:sudoku/config/default_global_settings.dart';
 import 'package:sudoku/config/menu.dart';
 import 'package:sudoku/cubit/game_cubit.dart';
 import 'package:sudoku/cubit/nav_cubit.dart';
-import 'package:sudoku/models/game.dart';
+import 'package:sudoku/models/game/game.dart';
 
 class GlobalAppBar extends StatelessWidget implements PreferredSizeWidget {
   const GlobalAppBar({super.key});
@@ -17,17 +15,15 @@ class GlobalAppBar extends StatelessWidget implements PreferredSizeWidget {
       builder: (BuildContext context, GameState gameState) {
         return BlocBuilder<NavCubit, int>(
           builder: (BuildContext context, int pageIndex) {
-            final Game game = gameState.game;
+            final Game currentGame = gameState.currentGame;
 
             final List<Widget> menuActions = [];
 
-            if (game.isRunning && !game.isFinished) {
-              final GameCubit gameCubit = BlocProvider.of<GameCubit>(context);
-
+            if (currentGame.isRunning && !currentGame.isFinished) {
               menuActions.add(TextButton(
-                onPressed: null,
+                onPressed: () {},
                 onLongPress: () {
-                  gameCubit.quitGame();
+                  BlocProvider.of<GameCubit>(context).quitGame();
                 },
                 child: Container(
                   decoration: BoxDecoration(
@@ -38,69 +34,12 @@ class GlobalAppBar extends StatelessWidget implements PreferredSizeWidget {
                     ),
                   ),
                   child: const Image(
-                    image: AssetImage('assets/icons/button_back.png'),
+                    image: AssetImage('assets/ui/button_back.png'),
                     fit: BoxFit.fill,
                   ),
                 ),
               ));
               menuActions.add(const Spacer(flex: 6));
-              menuActions.add(TextButton(
-                child: Container(
-                  decoration: BoxDecoration(
-                    borderRadius: BorderRadius.circular(4),
-                    border: Border.all(
-                      color: Colors.white,
-                      width: 3,
-                    ),
-                  ),
-                  child: badges.Badge(
-                    showBadge: game.givenTipsCount == 0 ? false : true,
-                    badgeStyle: badges.BadgeStyle(
-                      badgeColor: game.givenTipsCount < 10
-                          ? Colors.green
-                          : game.givenTipsCount < 20
-                              ? Colors.orange
-                              : Colors.red,
-                    ),
-                    badgeContent: Text(
-                      game.givenTipsCount == 0 ? '' : game.givenTipsCount.toString(),
-                      style: const TextStyle(color: Colors.white),
-                    ),
-                    child: Container(
-                      padding: EdgeInsets.all(15 *
-                          game.buttonTipsCountdown /
-                          DefaultGlobalSettings.defaultTipCountDownValueInSeconds),
-                      child: const Image(
-                        image: AssetImage('assets/icons/button_help.png'),
-                        fit: BoxFit.fill,
-                      ),
-                    ),
-                  ),
-                ),
-                onPressed: () {
-                  final GameCubit gameCubit = BlocProvider.of<GameCubit>(context);
-                  game.canGiveTip() ? game.showTip(gameCubit) : null;
-                },
-              ));
-              menuActions.add(const Spacer());
-              menuActions.add(TextButton(
-                child: Container(
-                  decoration: BoxDecoration(
-                    borderRadius: BorderRadius.circular(4),
-                    border: Border.all(
-                      color: game.showConflicts == true ? Colors.blue : Colors.white,
-                      width: 3,
-                    ),
-                  ),
-                  child: const Image(
-                    image: AssetImage('assets/icons/button_show_conflicts.png'),
-                    fit: BoxFit.fill,
-                  ),
-                ),
-                onPressed: () {
-                  gameCubit.toggleShowConflicts();
-                },
-              ));
             } else {
               if (pageIndex == Menu.indexGame) {
                 // go to Settings page
diff --git a/lib/ui/widgets/header_app.dart b/lib/ui/widgets/header_app.dart
deleted file mode 100644
index b5c5be05f6636cf488dcdb5bbc4d6f049b98de11..0000000000000000000000000000000000000000
--- a/lib/ui/widgets/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/utils/board_animate.dart b/lib/utils/board_animate.dart
index 40adc186efb3ecb677b26ea1986d628aad06bb3b..a1a5239e36ad49e7a7dc2e3fc7057239c3ec7c60 100644
--- a/lib/utils/board_animate.dart
+++ b/lib/utils/board_animate.dart
@@ -1,8 +1,8 @@
 import 'dart:async';
 
 import 'package:sudoku/cubit/game_cubit.dart';
-import 'package:sudoku/models/game.dart';
-import 'package:sudoku/models/types.dart';
+import 'package:sudoku/models/game/game.dart';
+import 'package:sudoku/models/game/types.dart';
 
 class BoardAnimate {
   // Start game animation: blinking tiles
@@ -70,7 +70,7 @@ class BoardAnimate {
   }
 
   static void startAnimation(GameCubit gameCubit, String animationType) {
-    final Game game = gameCubit.state.game;
+    final Game game = gameCubit.state.currentGame;
 
     AnimatedBoardSequence patterns = [];
 
diff --git a/lib/utils/board_utils.dart b/lib/utils/board_utils.dart
deleted file mode 100644
index 491c3d1a07e3677aad8aad21b3998ee60ba86690..0000000000000000000000000000000000000000
--- a/lib/utils/board_utils.dart
+++ /dev/null
@@ -1,147 +0,0 @@
-import 'dart:math';
-
-import 'package:sudoku/models/board.dart';
-import 'package:sudoku/models/cell.dart';
-import 'package:sudoku/models/cell_location.dart';
-import 'package:sudoku/models/types.dart';
-import 'package:sudoku/utils/tools.dart';
-
-class BoardUtils {
-  static BoardCells createEmptyBoard(final int boardSize) {
-    final BoardCells cells = [];
-    for (int rowIndex = 0; rowIndex < boardSize; rowIndex++) {
-      final List<Cell> row = [];
-      for (int colIndex = 0; colIndex < boardSize; colIndex++) {
-        row.add(Cell(
-          location: CellLocation.go(rowIndex, colIndex),
-          value: 0,
-          isFixed: false,
-        ));
-      }
-      cells.add(row);
-    }
-
-    return cells;
-  }
-
-  static Board createBoardFromTemplate({
-    required String template,
-    required bool isSymetric,
-  }) {
-    BoardCells cells = [];
-    final int boardSize = int.parse(pow(template.length, 1 / 2).toStringAsFixed(0));
-
-    const String stringValues = '0123456789ABCDEFG';
-
-    int index = 0;
-    for (int rowIndex = 0; rowIndex < boardSize; rowIndex++) {
-      final List<Cell> row = [];
-      for (int colIndex = 0; colIndex < boardSize; colIndex++) {
-        final String stringValue = template[index++];
-        final int value = stringValues.indexOf(stringValue);
-        row.add(Cell(
-          location: CellLocation.go(rowIndex, colIndex),
-          value: value,
-          isFixed: (value != 0),
-        ));
-      }
-      cells.add(row);
-    }
-
-    const List<String> allowedFlip = ['none', 'horizontal', 'vertical'];
-    List<String> allowedRotate = ['none', 'left', 'right'];
-
-    // Forbid rotation if blocks are not symetric
-    if (!isSymetric) {
-      allowedRotate = ['none'];
-    }
-
-    final Random rand = Random();
-    final String flip = allowedFlip[rand.nextInt(allowedFlip.length)];
-    final String rotate = allowedRotate[rand.nextInt(allowedRotate.length)];
-
-    printlog('flip board: $flip');
-    printlog('rotate board: $rotate');
-
-    switch (flip) {
-      case 'horizontal':
-        {
-          final BoardCells transformedBoard = createEmptyBoard(boardSize);
-          for (int rowIndex = 0; rowIndex < boardSize; rowIndex++) {
-            for (int colIndex = 0; colIndex < boardSize; colIndex++) {
-              transformedBoard[rowIndex][colIndex] = Cell(
-                location: CellLocation.go(rowIndex, colIndex),
-                value: cells[boardSize - rowIndex - 1][colIndex].value,
-                isFixed: false,
-              );
-            }
-          }
-          cells = transformedBoard;
-        }
-        break;
-      case 'vertical':
-        {
-          final BoardCells transformedBoard = createEmptyBoard(boardSize);
-          for (int rowIndex = 0; rowIndex < boardSize; rowIndex++) {
-            for (int colIndex = 0; colIndex < boardSize; colIndex++) {
-              transformedBoard[rowIndex][colIndex] = Cell(
-                location: CellLocation.go(rowIndex, colIndex),
-                value: cells[rowIndex][boardSize - colIndex - 1].value,
-                isFixed: false,
-              );
-            }
-          }
-          cells = transformedBoard;
-        }
-        break;
-    }
-
-    switch (rotate) {
-      case 'left':
-        {
-          final BoardCells transformedBoard = createEmptyBoard(boardSize);
-          for (int rowIndex = 0; rowIndex < boardSize; rowIndex++) {
-            for (int colIndex = 0; colIndex < boardSize; colIndex++) {
-              transformedBoard[rowIndex][colIndex] = Cell(
-                location: CellLocation.go(rowIndex, colIndex),
-                value: cells[colIndex][boardSize - rowIndex - 1].value,
-                isFixed: false,
-              );
-            }
-          }
-          cells = transformedBoard;
-        }
-        break;
-      case 'right':
-        {
-          final BoardCells transformedBoard = createEmptyBoard(boardSize);
-          for (int rowIndex = 0; rowIndex < boardSize; rowIndex++) {
-            for (int colIndex = 0; colIndex < boardSize; colIndex++) {
-              transformedBoard[rowIndex][colIndex] = Cell(
-                location: CellLocation.go(rowIndex, colIndex),
-                value: cells[boardSize - colIndex - 1][rowIndex].value,
-                isFixed: false,
-              );
-            }
-          }
-          cells = transformedBoard;
-        }
-        break;
-    }
-
-    // Fix cells fixed states
-    for (int rowIndex = 0; rowIndex < boardSize; rowIndex++) {
-      for (int colIndex = 0; colIndex < boardSize; colIndex++) {
-        cells[rowIndex][colIndex] = Cell(
-          location: CellLocation.go(rowIndex, colIndex),
-          value: cells[rowIndex][colIndex].value,
-          isFixed: (cells[rowIndex][colIndex].value != 0) ? true : false,
-        );
-      }
-    }
-
-    return Board.createNew(
-      cells: cells,
-    );
-  }
-}
diff --git a/lib/utils/color_extensions.dart b/lib/utils/color_extensions.dart
new file mode 100644
index 0000000000000000000000000000000000000000..4e55e338f0d3ed98b233d1ef887b7b3e17e29d97
--- /dev/null
+++ b/lib/utils/color_extensions.dart
@@ -0,0 +1,33 @@
+import 'dart:ui';
+
+extension ColorExtension on Color {
+  Color darken([int percent = 40]) {
+    assert(1 <= percent && percent <= 100);
+    final value = 1 - percent / 100;
+    return Color.fromARGB(
+      alpha,
+      (red * value).round(),
+      (green * value).round(),
+      (blue * value).round(),
+    );
+  }
+
+  Color lighten([int percent = 40]) {
+    assert(1 <= percent && percent <= 100);
+    final value = percent / 100;
+    return Color.fromARGB(
+      alpha,
+      (red + ((255 - red) * value)).round(),
+      (green + ((255 - green) * value)).round(),
+      (blue + ((255 - blue) * value)).round(),
+    );
+  }
+
+  Color avg(Color other) {
+    final red = (this.red + other.red) ~/ 2;
+    final green = (this.green + other.green) ~/ 2;
+    final blue = (this.blue + other.blue) ~/ 2;
+    final alpha = (this.alpha + other.alpha) ~/ 2;
+    return Color.fromARGB(alpha, red, green, blue);
+  }
+}
diff --git a/pubspec.lock b/pubspec.lock
index 5b7acc53497ec595d688d405cbecdb233880c0ab..d7159552791bd038a797ccfabe6b05f68af2c26d 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -69,10 +69,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:
@@ -114,18 +114,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
@@ -172,18 +172,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:
@@ -196,10 +196,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:
@@ -244,18 +244,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:
@@ -284,10 +284,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:
@@ -316,18 +316,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:
@@ -433,10 +433,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:
@@ -446,5 +446,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 e76a64153fc282d639fcc87b05224e9c9f2aad6d..e22d64e6019f7b4a2bd053367d9edc2dea0e4df2 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -3,7 +3,7 @@ description: A sudoku game application.
 
 publish_to: "none"
 
-version: 0.1.22+71
+version: 0.2.0+72
 
 environment:
   sdk: "^3.0.0"
@@ -12,7 +12,7 @@ dependencies:
   flutter:
     sdk: flutter
 
-  badges: ^3.1.2
+  # base
   easy_localization: ^3.0.1
   equatable: ^2.0.5
   flutter_bloc: ^8.1.1
@@ -22,14 +22,17 @@ dependencies:
   path_provider: ^2.0.11
   unicons: ^2.1.1
 
+  # specific
+  badges: ^3.1.2
+
 dev_dependencies:
-  flutter_lints: ^3.0.1
+  flutter_lints: ^4.0.0
 
 flutter:
   uses-material-design: true
   assets:
-    - assets/icons/
     - assets/skins/
+    - assets/ui/
     - assets/translations/
 
   fonts:
@@ -43,3 +46,4 @@ flutter:
           weight: 400
         - asset: assets/fonts/Nunito-Light.ttf
           weight: 300
+
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/icons/build_game_icons.sh b/resources/ui/build_ui_resources.sh
similarity index 54%
rename from icons/build_game_icons.sh
rename to resources/ui/build_ui_resources.sh
index e079a347ee2da4842772d4cb0d6f564cf98c191f..4f365ede7d83140ce6309a3083580f2662b30990 100755
--- a/icons/build_game_icons.sh
+++ b/resources/ui/build_ui_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}")")"
 ASSETS_DIR="${BASE_DIR}/assets"
 
 OPTIPNG_OPTIONS="-preserve -quiet -o7"
@@ -14,46 +14,23 @@ ICON_SIZE=192
 
 #######################################################
 
-# Game images
-AVAILABLE_GAME_IMAGES="
-  button_back
-  button_start
-  button_resume_game
-  button_delete_saved_game
-  button_help
-  button_show_conflicts
-  game_win
-  placeholder
-  cell_empty
-"
-
-# Skins
-AVAILABLE_SKINS="
-  digits
-  food
-  monsters
-  nature
-"
-
-# Images per skin
-SKIN_IMAGES="
-  1
-  2
-  3
-  4
-  5
-  6
-  7
-  8
-  9
-  10
-  11
-  12
-  13
-  14
-  15
-  16
-"
+# 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
 
 #######################################################
 
@@ -75,7 +52,7 @@ function optimize_svg() {
 }
 
 # build icons
-function build_icon() {
+function build_image() {
   SOURCE="$1"
   TARGET="$2"
 
@@ -88,46 +65,46 @@ function build_icon() {
 
   optimize_svg "${SOURCE}"
 
+  mkdir -p "$(dirname "${TARGET}")"
+
   inkscape \
       --export-width=${ICON_SIZE} \
       --export-height=${ICON_SIZE} \
       --export-filename=${TARGET} \
-      ${SOURCE}
+      "${SOURCE}"
 
-  optipng ${OPTIPNG_OPTIONS} ${TARGET}
+  optipng ${OPTIPNG_OPTIONS} "${TARGET}"
 }
 
-function build_icon_for_skin() {
+function build_image_for_skin() {
   SKIN_CODE="$1"
 
-  # skin main image
-  build_icon ${CURRENT_DIR}/skin_${SKIN_CODE}.svg ${ASSETS_DIR}/icons/skin_${SKIN_CODE}.png
-
   # skin images
   for SKIN_IMAGE in ${SKIN_IMAGES}
   do
-    build_icon ${CURRENT_DIR}/skins/${SKIN_CODE}/${SKIN_IMAGE}.svg ${ASSETS_DIR}/skins/${SKIN_CODE}_${SKIN_IMAGE}.png
+    build_image ${CURRENT_DIR}/skins/${SKIN_CODE}/${SKIN_IMAGE}.svg ${ASSETS_DIR}/skins/${SKIN_CODE}_${SKIN_IMAGE}.png
   done
 }
 
 #######################################################
 
-# Create output folders
-mkdir -p ${ASSETS_DIR}/icons
-mkdir -p ${ASSETS_DIR}/skins
-
 # Delete existing generated images
-find ${ASSETS_DIR}/icons -type f -name "*.png" -delete
-find ${ASSETS_DIR}/skins -type f -name "*.png" -delete
+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_icon ${CURRENT_DIR}/${GAME_IMAGE}.svg ${ASSETS_DIR}/icons/${GAME_IMAGE}.png
+  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_icon_for_skin "${SKIN}"
+  build_image_for_skin "${SKIN}"
 done
+
diff --git a/icons/button_back.svg b/resources/ui/images/button_back.svg
similarity index 100%
rename from icons/button_back.svg
rename to resources/ui/images/button_back.svg
diff --git a/icons/button_delete_saved_game.svg b/resources/ui/images/button_delete_saved_game.svg
similarity index 100%
rename from icons/button_delete_saved_game.svg
rename to resources/ui/images/button_delete_saved_game.svg
diff --git a/icons/button_help.svg b/resources/ui/images/button_help.svg
similarity index 100%
rename from icons/button_help.svg
rename to resources/ui/images/button_help.svg
diff --git a/icons/button_resume_game.svg b/resources/ui/images/button_resume_game.svg
similarity index 100%
rename from icons/button_resume_game.svg
rename to resources/ui/images/button_resume_game.svg
diff --git a/icons/button_show_conflicts.svg b/resources/ui/images/button_show_conflicts.svg
similarity index 100%
rename from icons/button_show_conflicts.svg
rename to resources/ui/images/button_show_conflicts.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/cell_empty.svg b/resources/ui/images/cell_empty.svg
similarity index 100%
rename from icons/cell_empty.svg
rename to resources/ui/images/cell_empty.svg
diff --git a/icons/game_win.svg b/resources/ui/images/game_win.svg
similarity index 100%
rename from icons/game_win.svg
rename to resources/ui/images/game_win.svg
diff --git a/icons/placeholder.svg b/resources/ui/images/placeholder.svg
similarity index 100%
rename from icons/placeholder.svg
rename to resources/ui/images/placeholder.svg
diff --git a/icons/skin_digits.svg b/resources/ui/images/skin_digits.svg
similarity index 100%
rename from icons/skin_digits.svg
rename to resources/ui/images/skin_digits.svg
diff --git a/icons/skin_food.svg b/resources/ui/images/skin_food.svg
similarity index 100%
rename from icons/skin_food.svg
rename to resources/ui/images/skin_food.svg
diff --git a/icons/skin_monsters.svg b/resources/ui/images/skin_monsters.svg
similarity index 100%
rename from icons/skin_monsters.svg
rename to resources/ui/images/skin_monsters.svg
diff --git a/icons/skin_nature.svg b/resources/ui/images/skin_nature.svg
similarity index 100%
rename from icons/skin_nature.svg
rename to resources/ui/images/skin_nature.svg
diff --git a/icons/skins/digits/1.svg b/resources/ui/skins/digits/1.svg
similarity index 100%
rename from icons/skins/digits/1.svg
rename to resources/ui/skins/digits/1.svg
diff --git a/icons/skins/digits/10.svg b/resources/ui/skins/digits/10.svg
similarity index 100%
rename from icons/skins/digits/10.svg
rename to resources/ui/skins/digits/10.svg
diff --git a/icons/skins/digits/11.svg b/resources/ui/skins/digits/11.svg
similarity index 100%
rename from icons/skins/digits/11.svg
rename to resources/ui/skins/digits/11.svg
diff --git a/icons/skins/digits/12.svg b/resources/ui/skins/digits/12.svg
similarity index 100%
rename from icons/skins/digits/12.svg
rename to resources/ui/skins/digits/12.svg
diff --git a/icons/skins/digits/13.svg b/resources/ui/skins/digits/13.svg
similarity index 100%
rename from icons/skins/digits/13.svg
rename to resources/ui/skins/digits/13.svg
diff --git a/icons/skins/digits/14.svg b/resources/ui/skins/digits/14.svg
similarity index 100%
rename from icons/skins/digits/14.svg
rename to resources/ui/skins/digits/14.svg
diff --git a/icons/skins/digits/15.svg b/resources/ui/skins/digits/15.svg
similarity index 100%
rename from icons/skins/digits/15.svg
rename to resources/ui/skins/digits/15.svg
diff --git a/icons/skins/digits/16.svg b/resources/ui/skins/digits/16.svg
similarity index 100%
rename from icons/skins/digits/16.svg
rename to resources/ui/skins/digits/16.svg
diff --git a/icons/skins/digits/2.svg b/resources/ui/skins/digits/2.svg
similarity index 100%
rename from icons/skins/digits/2.svg
rename to resources/ui/skins/digits/2.svg
diff --git a/icons/skins/digits/3.svg b/resources/ui/skins/digits/3.svg
similarity index 100%
rename from icons/skins/digits/3.svg
rename to resources/ui/skins/digits/3.svg
diff --git a/icons/skins/digits/4.svg b/resources/ui/skins/digits/4.svg
similarity index 100%
rename from icons/skins/digits/4.svg
rename to resources/ui/skins/digits/4.svg
diff --git a/icons/skins/digits/5.svg b/resources/ui/skins/digits/5.svg
similarity index 100%
rename from icons/skins/digits/5.svg
rename to resources/ui/skins/digits/5.svg
diff --git a/icons/skins/digits/6.svg b/resources/ui/skins/digits/6.svg
similarity index 100%
rename from icons/skins/digits/6.svg
rename to resources/ui/skins/digits/6.svg
diff --git a/icons/skins/digits/7.svg b/resources/ui/skins/digits/7.svg
similarity index 100%
rename from icons/skins/digits/7.svg
rename to resources/ui/skins/digits/7.svg
diff --git a/icons/skins/digits/8.svg b/resources/ui/skins/digits/8.svg
similarity index 100%
rename from icons/skins/digits/8.svg
rename to resources/ui/skins/digits/8.svg
diff --git a/icons/skins/digits/9.svg b/resources/ui/skins/digits/9.svg
similarity index 100%
rename from icons/skins/digits/9.svg
rename to resources/ui/skins/digits/9.svg
diff --git a/icons/skins/food/1.svg b/resources/ui/skins/food/1.svg
similarity index 100%
rename from icons/skins/food/1.svg
rename to resources/ui/skins/food/1.svg
diff --git a/icons/skins/food/10.svg b/resources/ui/skins/food/10.svg
similarity index 100%
rename from icons/skins/food/10.svg
rename to resources/ui/skins/food/10.svg
diff --git a/icons/skins/food/11.svg b/resources/ui/skins/food/11.svg
similarity index 100%
rename from icons/skins/food/11.svg
rename to resources/ui/skins/food/11.svg
diff --git a/icons/skins/food/12.svg b/resources/ui/skins/food/12.svg
similarity index 100%
rename from icons/skins/food/12.svg
rename to resources/ui/skins/food/12.svg
diff --git a/icons/skins/food/13.svg b/resources/ui/skins/food/13.svg
similarity index 100%
rename from icons/skins/food/13.svg
rename to resources/ui/skins/food/13.svg
diff --git a/icons/skins/food/14.svg b/resources/ui/skins/food/14.svg
similarity index 100%
rename from icons/skins/food/14.svg
rename to resources/ui/skins/food/14.svg
diff --git a/icons/skins/food/15.svg b/resources/ui/skins/food/15.svg
similarity index 100%
rename from icons/skins/food/15.svg
rename to resources/ui/skins/food/15.svg
diff --git a/icons/skins/food/16.svg b/resources/ui/skins/food/16.svg
similarity index 100%
rename from icons/skins/food/16.svg
rename to resources/ui/skins/food/16.svg
diff --git a/icons/skins/food/2.svg b/resources/ui/skins/food/2.svg
similarity index 100%
rename from icons/skins/food/2.svg
rename to resources/ui/skins/food/2.svg
diff --git a/icons/skins/food/3.svg b/resources/ui/skins/food/3.svg
similarity index 100%
rename from icons/skins/food/3.svg
rename to resources/ui/skins/food/3.svg
diff --git a/icons/skins/food/4.svg b/resources/ui/skins/food/4.svg
similarity index 100%
rename from icons/skins/food/4.svg
rename to resources/ui/skins/food/4.svg
diff --git a/icons/skins/food/5.svg b/resources/ui/skins/food/5.svg
similarity index 100%
rename from icons/skins/food/5.svg
rename to resources/ui/skins/food/5.svg
diff --git a/icons/skins/food/6.svg b/resources/ui/skins/food/6.svg
similarity index 100%
rename from icons/skins/food/6.svg
rename to resources/ui/skins/food/6.svg
diff --git a/icons/skins/food/7.svg b/resources/ui/skins/food/7.svg
similarity index 100%
rename from icons/skins/food/7.svg
rename to resources/ui/skins/food/7.svg
diff --git a/icons/skins/food/8.svg b/resources/ui/skins/food/8.svg
similarity index 100%
rename from icons/skins/food/8.svg
rename to resources/ui/skins/food/8.svg
diff --git a/icons/skins/food/9.svg b/resources/ui/skins/food/9.svg
similarity index 100%
rename from icons/skins/food/9.svg
rename to resources/ui/skins/food/9.svg
diff --git a/icons/skins/monsters/1.svg b/resources/ui/skins/monsters/1.svg
similarity index 100%
rename from icons/skins/monsters/1.svg
rename to resources/ui/skins/monsters/1.svg
diff --git a/icons/skins/monsters/10.svg b/resources/ui/skins/monsters/10.svg
similarity index 100%
rename from icons/skins/monsters/10.svg
rename to resources/ui/skins/monsters/10.svg
diff --git a/icons/skins/monsters/11.svg b/resources/ui/skins/monsters/11.svg
similarity index 100%
rename from icons/skins/monsters/11.svg
rename to resources/ui/skins/monsters/11.svg
diff --git a/icons/skins/monsters/12.svg b/resources/ui/skins/monsters/12.svg
similarity index 100%
rename from icons/skins/monsters/12.svg
rename to resources/ui/skins/monsters/12.svg
diff --git a/icons/skins/monsters/13.svg b/resources/ui/skins/monsters/13.svg
similarity index 100%
rename from icons/skins/monsters/13.svg
rename to resources/ui/skins/monsters/13.svg
diff --git a/icons/skins/monsters/14.svg b/resources/ui/skins/monsters/14.svg
similarity index 100%
rename from icons/skins/monsters/14.svg
rename to resources/ui/skins/monsters/14.svg
diff --git a/icons/skins/monsters/15.svg b/resources/ui/skins/monsters/15.svg
similarity index 100%
rename from icons/skins/monsters/15.svg
rename to resources/ui/skins/monsters/15.svg
diff --git a/icons/skins/monsters/16.svg b/resources/ui/skins/monsters/16.svg
similarity index 100%
rename from icons/skins/monsters/16.svg
rename to resources/ui/skins/monsters/16.svg
diff --git a/icons/skins/monsters/2.svg b/resources/ui/skins/monsters/2.svg
similarity index 100%
rename from icons/skins/monsters/2.svg
rename to resources/ui/skins/monsters/2.svg
diff --git a/icons/skins/monsters/3.svg b/resources/ui/skins/monsters/3.svg
similarity index 100%
rename from icons/skins/monsters/3.svg
rename to resources/ui/skins/monsters/3.svg
diff --git a/icons/skins/monsters/4.svg b/resources/ui/skins/monsters/4.svg
similarity index 100%
rename from icons/skins/monsters/4.svg
rename to resources/ui/skins/monsters/4.svg
diff --git a/icons/skins/monsters/5.svg b/resources/ui/skins/monsters/5.svg
similarity index 100%
rename from icons/skins/monsters/5.svg
rename to resources/ui/skins/monsters/5.svg
diff --git a/icons/skins/monsters/6.svg b/resources/ui/skins/monsters/6.svg
similarity index 100%
rename from icons/skins/monsters/6.svg
rename to resources/ui/skins/monsters/6.svg
diff --git a/icons/skins/monsters/7.svg b/resources/ui/skins/monsters/7.svg
similarity index 100%
rename from icons/skins/monsters/7.svg
rename to resources/ui/skins/monsters/7.svg
diff --git a/icons/skins/monsters/8.svg b/resources/ui/skins/monsters/8.svg
similarity index 100%
rename from icons/skins/monsters/8.svg
rename to resources/ui/skins/monsters/8.svg
diff --git a/icons/skins/monsters/9.svg b/resources/ui/skins/monsters/9.svg
similarity index 100%
rename from icons/skins/monsters/9.svg
rename to resources/ui/skins/monsters/9.svg
diff --git a/icons/skins/nature/1.svg b/resources/ui/skins/nature/1.svg
similarity index 100%
rename from icons/skins/nature/1.svg
rename to resources/ui/skins/nature/1.svg
diff --git a/icons/skins/nature/10.svg b/resources/ui/skins/nature/10.svg
similarity index 100%
rename from icons/skins/nature/10.svg
rename to resources/ui/skins/nature/10.svg
diff --git a/icons/skins/nature/11.svg b/resources/ui/skins/nature/11.svg
similarity index 100%
rename from icons/skins/nature/11.svg
rename to resources/ui/skins/nature/11.svg
diff --git a/icons/skins/nature/12.svg b/resources/ui/skins/nature/12.svg
similarity index 100%
rename from icons/skins/nature/12.svg
rename to resources/ui/skins/nature/12.svg
diff --git a/icons/skins/nature/13.svg b/resources/ui/skins/nature/13.svg
similarity index 100%
rename from icons/skins/nature/13.svg
rename to resources/ui/skins/nature/13.svg
diff --git a/icons/skins/nature/14.svg b/resources/ui/skins/nature/14.svg
similarity index 100%
rename from icons/skins/nature/14.svg
rename to resources/ui/skins/nature/14.svg
diff --git a/icons/skins/nature/15.svg b/resources/ui/skins/nature/15.svg
similarity index 100%
rename from icons/skins/nature/15.svg
rename to resources/ui/skins/nature/15.svg
diff --git a/icons/skins/nature/16.svg b/resources/ui/skins/nature/16.svg
similarity index 100%
rename from icons/skins/nature/16.svg
rename to resources/ui/skins/nature/16.svg
diff --git a/icons/skins/nature/2.svg b/resources/ui/skins/nature/2.svg
similarity index 100%
rename from icons/skins/nature/2.svg
rename to resources/ui/skins/nature/2.svg
diff --git a/icons/skins/nature/3.svg b/resources/ui/skins/nature/3.svg
similarity index 100%
rename from icons/skins/nature/3.svg
rename to resources/ui/skins/nature/3.svg
diff --git a/icons/skins/nature/4.svg b/resources/ui/skins/nature/4.svg
similarity index 100%
rename from icons/skins/nature/4.svg
rename to resources/ui/skins/nature/4.svg
diff --git a/icons/skins/nature/5.svg b/resources/ui/skins/nature/5.svg
similarity index 100%
rename from icons/skins/nature/5.svg
rename to resources/ui/skins/nature/5.svg
diff --git a/icons/skins/nature/6.svg b/resources/ui/skins/nature/6.svg
similarity index 100%
rename from icons/skins/nature/6.svg
rename to resources/ui/skins/nature/6.svg
diff --git a/icons/skins/nature/7.svg b/resources/ui/skins/nature/7.svg
similarity index 100%
rename from icons/skins/nature/7.svg
rename to resources/ui/skins/nature/7.svg
diff --git a/icons/skins/nature/8.svg b/resources/ui/skins/nature/8.svg
similarity index 100%
rename from icons/skins/nature/8.svg
rename to resources/ui/skins/nature/8.svg
diff --git a/icons/skins/nature/9.svg b/resources/ui/skins/nature/9.svg
similarity index 100%
rename from icons/skins/nature/9.svg
rename to resources/ui/skins/nature/9.svg