From d27cfa49c9ff756336e208e5a157d22fa435fb9b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Beno=C3=AEt=20Harrault?= <benoit@harrault.fr>
Date: Tue, 30 Apr 2024 15:19:11 +0200
Subject: [PATCH] Improve game architecture

---
 android/app/build.gradle                      |   2 +-
 android/gradle.properties                     |   4 +-
 assets/icons/colors_5.png                     | Bin 1516 -> 0 bytes
 assets/icons/colors_6.png                     | Bin 2010 -> 0 bytes
 assets/icons/colors_7.png                     | Bin 1543 -> 0 bytes
 assets/icons/colors_8.png                     | Bin 2193 -> 0 bytes
 assets/icons/level_easy.png                   | Bin 3055 -> 0 bytes
 assets/icons/level_hard.png                   | Bin 7309 -> 0 bytes
 assets/icons/level_medium.png                 | Bin 5156 -> 0 bytes
 assets/icons/level_nightmare.png              | Bin 9098 -> 0 bytes
 assets/icons/size_extra.png                   | Bin 962 -> 0 bytes
 assets/icons/size_large.png                   | Bin 774 -> 0 bytes
 assets/icons/size_medium.png                  | Bin 661 -> 0 bytes
 assets/icons/size_small.png                   | Bin 480 -> 0 bytes
 assets/icons/skin_default.png                 | Bin 949 -> 0 bytes
 assets/skins/default_0.png                    | Bin 157 -> 0 bytes
 assets/skins/default_1.png                    | Bin 157 -> 0 bytes
 assets/skins/default_2.png                    | Bin 157 -> 0 bytes
 assets/skins/default_3.png                    | Bin 157 -> 0 bytes
 assets/skins/default_4.png                    | Bin 157 -> 0 bytes
 assets/skins/default_5.png                    | Bin 157 -> 0 bytes
 assets/skins/default_6.png                    | Bin 157 -> 0 bytes
 assets/skins/default_7.png                    | Bin 157 -> 0 bytes
 assets/skins/default_8.png                    | Bin 157 -> 0 bytes
 assets/translations/en.json                   |   2 -
 assets/translations/fr.json                   |   2 -
 .../metadata/android/en-US/changelogs/39.txt  |   1 +
 .../metadata/android/fr-FR/changelogs/39.txt  |   1 +
 icons/build_game_icons.sh                     |  64 ---
 icons/colors_5.svg                            |   2 -
 icons/colors_6.svg                            |   2 -
 icons/colors_7.svg                            |   2 -
 icons/colors_8.svg                            |   2 -
 icons/level_easy.svg                          |   2 -
 icons/level_hard.svg                          |   2 -
 icons/level_medium.svg                        |   2 -
 icons/level_nightmare.svg                     |   2 -
 icons/size_extra.svg                          |   3 -
 icons/size_large.svg                          |   3 -
 icons/size_medium.svg                         |   3 -
 icons/size_small.svg                          |   3 -
 icons/skin_default.svg                        |   2 -
 icons/skins/default/0.svg                     |   2 -
 icons/skins/default/1.svg                     |   2 -
 icons/skins/default/2.svg                     |   2 -
 icons/skins/default/3.svg                     |   2 -
 icons/skins/default/4.svg                     |   2 -
 icons/skins/default/5.svg                     |   2 -
 icons/skins/default/6.svg                     |   2 -
 icons/skins/default/7.svg                     |   2 -
 icons/skins/default/8.svg                     |   2 -
 lib/config/default_game_settings.dart         |  81 ++++
 lib/config/default_global_settings.dart       |  28 ++
 lib/config/menu.dart                          |  63 +--
 lib/cubit/game_cubit.dart                     | 170 ++++++++
 lib/cubit/game_state.dart                     |  19 +
 .../{bottom_nav_cubit.dart => nav_cubit.dart} |  22 +-
 lib/cubit/settings_game_cubit.dart            |  84 ++++
 lib/cubit/settings_game_state.dart            |  19 +
 lib/cubit/settings_global_cubit.dart          |  61 +++
 lib/cubit/settings_global_state.dart          |  19 +
 lib/entities/cell.dart                        |  37 --
 lib/main.dart                                 |  50 ++-
 lib/models/board.dart                         | 144 +++++++
 lib/models/cell.dart                          |  18 +
 lib/models/game.dart                          | 114 ++++++
 lib/models/settings_game.dart                 |  81 ++++
 lib/models/settings_global.dart               |  41 ++
 lib/models/types.dart                         |   3 +
 lib/provider/data.dart                        | 340 ----------------
 lib/ui/layout/game.dart                       |  42 --
 lib/ui/layout/parameters.dart                 | 119 ------
 lib/ui/layout/tileset.dart                    |  50 ---
 lib/ui/painters/board_painter.dart            |  32 +-
 lib/ui/painters/parameter_painter.dart        | 372 ++++++++++++++++++
 lib/ui/screens/about_page.dart                |  41 --
 lib/ui/screens/game_page.dart                 |  37 --
 lib/ui/screens/page_about.dart                |  38 ++
 lib/ui/screens/page_game.dart                 |  18 +
 lib/ui/screens/page_settings.dart             |  23 ++
 lib/ui/screens/settings_page.dart             |  26 --
 lib/ui/skeleton.dart                          |  47 +--
 lib/ui/widgets/app_bar.dart                   |  37 --
 lib/ui/widgets/bottom_nav_bar.dart            |  40 --
 lib/ui/widgets/button_game_start_new.dart     |  34 ++
 .../{home => game}/button_game_restart.dart   |  12 +-
 lib/ui/widgets/game/cell_interactive.dart     |  55 +++
 lib/ui/widgets/game/game.dart                 |  37 ++
 lib/ui/widgets/game/game_board.dart           |  43 ++
 lib/ui/widgets/game/game_top_indicator.dart   |  70 ++++
 lib/ui/widgets/game/indicator_top.dart        |  64 ---
 lib/ui/widgets/game/message_game_end.dart     |  64 +--
 lib/ui/widgets/game/select_color_bar.dart     |  56 +--
 lib/ui/widgets/global_app_bar.dart            |  82 ++++
 lib/ui/widgets/helpers/app_titles.dart        |  17 +
 lib/ui/widgets/{ => helpers}/header_app.dart  |   5 +-
 .../widgets/helpers/outlined_text_widget.dart |  49 +++
 .../widgets/home/button_game_start_new.dart   |  38 --
 lib/ui/widgets/parameters.dart                | 121 ++++++
 lib/ui/widgets/settings/theme_card.dart       |   2 +-
 lib/utils/board_utils.dart                    | 168 --------
 lib/utils/color_extensions.dart               |  35 ++
 lib/utils/color_theme.dart                    |   4 +-
 lib/utils/game_utils.dart                     |  20 -
 lib/utils/tools.dart                          |   8 +
 pubspec.lock                                  |  90 ++---
 pubspec.yaml                                  |  10 +-
 107 files changed, 2108 insertions(+), 1416 deletions(-)
 delete mode 100644 assets/icons/colors_5.png
 delete mode 100644 assets/icons/colors_6.png
 delete mode 100644 assets/icons/colors_7.png
 delete mode 100644 assets/icons/colors_8.png
 delete mode 100644 assets/icons/level_easy.png
 delete mode 100644 assets/icons/level_hard.png
 delete mode 100644 assets/icons/level_medium.png
 delete mode 100644 assets/icons/level_nightmare.png
 delete mode 100644 assets/icons/size_extra.png
 delete mode 100644 assets/icons/size_large.png
 delete mode 100644 assets/icons/size_medium.png
 delete mode 100644 assets/icons/size_small.png
 delete mode 100644 assets/icons/skin_default.png
 delete mode 100644 assets/skins/default_0.png
 delete mode 100644 assets/skins/default_1.png
 delete mode 100644 assets/skins/default_2.png
 delete mode 100644 assets/skins/default_3.png
 delete mode 100644 assets/skins/default_4.png
 delete mode 100644 assets/skins/default_5.png
 delete mode 100644 assets/skins/default_6.png
 delete mode 100644 assets/skins/default_7.png
 delete mode 100644 assets/skins/default_8.png
 create mode 100644 fastlane/metadata/android/en-US/changelogs/39.txt
 create mode 100644 fastlane/metadata/android/fr-FR/changelogs/39.txt
 delete mode 100644 icons/colors_5.svg
 delete mode 100644 icons/colors_6.svg
 delete mode 100644 icons/colors_7.svg
 delete mode 100644 icons/colors_8.svg
 delete mode 100644 icons/level_easy.svg
 delete mode 100644 icons/level_hard.svg
 delete mode 100644 icons/level_medium.svg
 delete mode 100644 icons/level_nightmare.svg
 delete mode 100644 icons/size_extra.svg
 delete mode 100644 icons/size_large.svg
 delete mode 100644 icons/size_medium.svg
 delete mode 100644 icons/size_small.svg
 delete mode 100644 icons/skin_default.svg
 delete mode 100644 icons/skins/default/0.svg
 delete mode 100644 icons/skins/default/1.svg
 delete mode 100644 icons/skins/default/2.svg
 delete mode 100644 icons/skins/default/3.svg
 delete mode 100644 icons/skins/default/4.svg
 delete mode 100644 icons/skins/default/5.svg
 delete mode 100644 icons/skins/default/6.svg
 delete mode 100644 icons/skins/default/7.svg
 delete mode 100644 icons/skins/default/8.svg
 create mode 100644 lib/config/default_game_settings.dart
 create mode 100644 lib/config/default_global_settings.dart
 create mode 100644 lib/cubit/game_cubit.dart
 create mode 100644 lib/cubit/game_state.dart
 rename lib/cubit/{bottom_nav_cubit.dart => nav_cubit.dart} (51%)
 create mode 100644 lib/cubit/settings_game_cubit.dart
 create mode 100644 lib/cubit/settings_game_state.dart
 create mode 100644 lib/cubit/settings_global_cubit.dart
 create mode 100644 lib/cubit/settings_global_state.dart
 delete mode 100644 lib/entities/cell.dart
 create mode 100644 lib/models/board.dart
 create mode 100644 lib/models/cell.dart
 create mode 100644 lib/models/game.dart
 create mode 100644 lib/models/settings_game.dart
 create mode 100644 lib/models/settings_global.dart
 create mode 100644 lib/models/types.dart
 delete mode 100644 lib/provider/data.dart
 delete mode 100644 lib/ui/layout/game.dart
 delete mode 100644 lib/ui/layout/parameters.dart
 delete mode 100644 lib/ui/layout/tileset.dart
 create mode 100644 lib/ui/painters/parameter_painter.dart
 delete mode 100644 lib/ui/screens/about_page.dart
 delete mode 100644 lib/ui/screens/game_page.dart
 create mode 100644 lib/ui/screens/page_about.dart
 create mode 100644 lib/ui/screens/page_game.dart
 create mode 100644 lib/ui/screens/page_settings.dart
 delete mode 100644 lib/ui/screens/settings_page.dart
 delete mode 100644 lib/ui/widgets/app_bar.dart
 delete mode 100644 lib/ui/widgets/bottom_nav_bar.dart
 create mode 100644 lib/ui/widgets/button_game_start_new.dart
 rename lib/ui/widgets/{home => game}/button_game_restart.dart (62%)
 create mode 100644 lib/ui/widgets/game/cell_interactive.dart
 create mode 100644 lib/ui/widgets/game/game.dart
 create mode 100644 lib/ui/widgets/game/game_board.dart
 create mode 100644 lib/ui/widgets/game/game_top_indicator.dart
 delete mode 100644 lib/ui/widgets/game/indicator_top.dart
 create mode 100644 lib/ui/widgets/global_app_bar.dart
 create mode 100644 lib/ui/widgets/helpers/app_titles.dart
 rename lib/ui/widgets/{ => helpers}/header_app.dart (77%)
 create mode 100644 lib/ui/widgets/helpers/outlined_text_widget.dart
 delete mode 100644 lib/ui/widgets/home/button_game_start_new.dart
 create mode 100644 lib/ui/widgets/parameters.dart
 delete mode 100644 lib/utils/board_utils.dart
 create mode 100644 lib/utils/color_extensions.dart
 delete mode 100644 lib/utils/game_utils.dart

diff --git a/android/app/build.gradle b/android/app/build.gradle
index 9a2e79e..4cb92c9 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -37,7 +37,7 @@ if (keystorePropertiesFile.exists()) {
 }
 
 android {
-    compileSdkVersion 33
+    compileSdkVersion 34
     namespace "org.benoitharrault.colors"
 
     defaultConfig {
diff --git a/android/gradle.properties b/android/gradle.properties
index 604fc08..c8bbff9 100644
--- a/android/gradle.properties
+++ b/android/gradle.properties
@@ -1,5 +1,5 @@
 org.gradle.jvmargs=-Xmx1536M
 android.useAndroidX=true
 android.enableJetifier=true
-app.versionName=0.0.38
-app.versionCode=38
+app.versionName=0.0.39
+app.versionCode=39
diff --git a/assets/icons/colors_5.png b/assets/icons/colors_5.png
deleted file mode 100644
index dd0a276e105a79aa25ca36f6cc4d2f69c77df81f..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1516
zcmeAS@N?(olHy`uVBq!ia0y~yU^oE69Lx+145>_WOc@v$I14-?iy0WCPk}I_+{y{!
z3=9mCC9V-A!TD(=<%vb94CUqJdYO6I#mR{Use1WE>9gP2NHH)l*#`K8xH2#>FfuYQ
zGBGkSF|x2Sv$8X@aj<Z3v2t*;a`Ccp^Re*=aPSIp@CkD8332iZbMlLD3W{<GiE|4}
z@Q6t9h)VH_%koLc@kuKQ$S4cSstU=e2`OrcC~1o->4+-ph^pv{spyHRgv+aBsi^9U
zt41rT#VD#9NvMY?Xc$RonM!HZYH6EEY1eA&SV-$x%jnz48raGj*~=L@$eTFHn>Z<$
z&M`G}RWx@~vhYx{^i;NvQn&F@vGG;4^;5Nt*0A$avk!=~4^(#y3U>@@bPU#T3T|==
z(QppcbP3aR4fk-3&~l5?_K3Fgh|%#*(DP2w_fIkKPc;ZkGYrZw3d%GJ&NL3rG7iZ$
z4vo_f%{~yCV-l9A6_%tQmTMC3s}<>~85N=xRd6b%)FL)WGd4*rw#+iF!ZNYiI=Rj!
zxz0AV(Jn1TF|Eliz1cpa#Xht7ZDy-OW}8D+ihNePW469Zc86n5r&CUsQ*O6YUbk~z
zk8^&nbAF#oLC@d939dyGU5h5V6;F06aaJvz;$Aw{y<AhJe7a}FOwY<$Ue$BFYqZsB
zb<}F-`_wJ)saxP%ztFdSkzd1Nzs4p0O-^df%L1C02ehsXY+Du7wmPW2Sf+hVP=~8V
z$C}_SH;t}R*{<~=-5Wx>H-`3X3hmt-*1t7;!uE&>J0d3Th?ul9a?-BI$-5&b?~a<X
zCu-{6=&Adnr|pZLwm)Y2fta}(+UtDucIX-H)HgmnPw7mg+1W_5v&)p9S=qlkp!q-F
z`TsecI%U2k3=GT$o-U3d6}R5r`5r9nC~@qgv6zr+;E^t&qkU4YZ&rj@CosBhWN7LV
z4Y3gk?BYslR^W)(=q%(BQT_M!8I8j`J{p}k{ou{&^WTr}esiYwnbFB-dHS>30_Gb>
z&rEyA6v29V4Jgg8Z|E}%;!}*-GEq-aX3IobH-_);bb@9+^*uS;L)CohahJ)rUYRji
zY>wN%G-T!VW2rI<Qv}0Tx1V2XqI)ZoqvHF_OTPLG9tbUD(oc96<n@`6fh6!?Kidu?
z?fd|%)whL(t_ynkY<RsnJ%FpfP*S%>*V=d0hMikG%r>pqx^sfrCZDNGkFPb|?rHi>
zc)_Vp?z->f3f}#Y4645Uo4w%a`FRo>OZhLnuU+`%--2M#1CR5k*g@QKfMJ8-N&ohl
z3~^s=AZ}}@m)MZ__0$TD+lNv&dRm{m|D0oj)GmePt)>TNXP$Gt$B;i+dj_*f@TA%1
z4wsc=&oJIn;xBI4)@z**!25mvl!>dD-Q177KWQBnG->{HDSPb$4;HWR3w4;9x+J&z
zpUbUh`{b-|gl~uqZI~aGW7nX0hT+g=7dDm>Bj%3j2RAL~ly+Ehx*@BqA=+rc6xj!@
zJQ`{26<W;eHZk8wZI~;o;BNJ=(NC3;ccr@3-#4$ecr_Ge)lC%5yybGY;=12YS&`K`
z4wn!0?W((9d_slUPm|}umc-d_KYcqUY8SllK-p5pd&kz<7d?O8SrIWyEbY_Wo@E?Y
z8ST~nHYz5&@fiLoKAWz?@b9*M1@p4%3g)J0mh1y7tPV;U{9E^cM`FV=->2QXuR7Yw
z{BPkps=t1B_w?vL^8c39^nWt9*wdDs`S}dn^i58|S-km%n%iEi&wh8Opy>Lo6&))V
zDjwE#R9v_%^riT`-<2z~PU}_A&Ek%)mi@i-_^+qzQ(kS3UBw_*yY!3Ubxuem5KsPz
zb@<Efl|O}XO8WCjx1NWwD9Ge4v1-w3*vHDiz))f<osl{#(s{-CTK4Okc122MY<USX
N+tbz0Wt~$(699v-Cj|fi

diff --git a/assets/icons/colors_6.png b/assets/icons/colors_6.png
deleted file mode 100644
index 2a63916ed00f0570bedd1647e34706d041fbec44..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 2010
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
V4Izr}6dr-ZJzf1=);T3K0RV)w5hnlu

diff --git a/assets/icons/colors_7.png b/assets/icons/colors_7.png
deleted file mode 100644
index fdc1669a1d89ed225cc4624319ff01558ab987b4..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1543
zcmeAS@N?(olHy`uVBq!ia0y~yU^oE69Lx+145>_WOc@v$I14-?iy0WCPk}I_+{y{!
z3=9mCC9V-A!TD(=<%vb94CUqJdYO6I#mR{Use1WE>9gP2NHH)l*#`K8xH2#>FfuSO
zF)}hUGO{o+vNAETF)^_-GjT98bFwgVu`qM9vhcF9@UgK9u(Jwtu!(ZAi*d3`a&bs=
zbIS8_De!VB@^LHkajRshsPgluty`xqz@sj}tKl!F86>Y+SECgouT`t1EySl?tF7JK
zq$9+q)7qkY=8W#yvwFh(dTz4%!u<Lo{02E$Mxp|yVuGe~OwGgu&BcW*{{Od<5Vn;R
zagr8wmJxOJs(15lbe9$PkQ4W^j`Wt7@R67BHIw(V2=sGz2vC#?FqIE<wh2*|4po*8
z%{~xr;t;9q6s0N~Rd6a=#V$roE><}zR$VSmB|6T)Bwo!pUR^#}LnlR3A;m~J#au5{
zOEFDLF;iP9v-xe7x<a;^LXMeyuC8*fo?@Pka-N=YzP@6<y=;M=N`by|LC@bpeU&0b
z#Ug#xVlU}Zf2ndqwF)EkDn;cgz4mHjjcPNc8e@$*6U};4%?2fv22;&OWz|N5zD85c
zR&(t(E0s=5oi0n=?rf<Z8?`=by*^vDzFg^kYrP3JdXsGQC)w&xw$-0zXE5Dj*>rou
z8TN*=9E@f=7|qqtp66t|&}QQzXOkr^rpsJSSGbw2bTeD!Zob;xe2u&LS`UkLK6>jt
zEjD^uZt}9+>TR{n+iIJS^$tCwo%+VRd~J67+U)kT+3#<=-{0<FfZd@0yTgI@hvz9B
z3A8^NWPdEk;dqe4@nDA&!44;b9Z!Wgo(^$56Y6v(((G)g)7eO~v&)p9S=qlkp!q-F
z`TsecrbiWZ3=GWPo-U3d6}R5re(paxP~`Z>rrTBlce-|@-|bp)LO>+YC2&r|q8*|K
zJDCGR<V2SG9l7RMsJ}or*Y@20vud9XIiEVgIO%!I{qKK$&#9Yd&bl4k&AQMpeXHi#
zTRa;kUdjO_`2P&?i#5zAhL>IPell(DmsX}9-=BA#+PK^3diSZ4o0ElI-hOCjs3>~B
ze_BX}#iJl|F0bBViNMLKy`CRhSoZwXe3>LLq1Gj!Ou!&>;gXdMq=5^I8Sl+G#677`
z^4yUdqD@J{bC1pGoU~}t-i2cEtMfXw)@QGnFn3MH3hn80*BG6CRd{%_RN&UTOe^f}
zK3p}s|BhW@(3N}3-Z99${Za46XDV;F?(d{8Ul$zLX_#HF@)zoqhIQ;URadK4TRfPf
z$(Z}(#o1^5Uox0=o{9%}onlC>`L~lXmEk>yS^W*=AhsLF^%dq#VZ0Z4^UvR`t&ER;
zvc6GEZ8-ig=U?L2Qw)tS|1jxIHgYhWU*8lj`M{fn{f4Jxg7o})OHJlIZ%#jZ|Jg}8
zL2`e?*(E#$?dR=(G#fSKo3PJON^N*t^Dof%6vKP=LI+k&<~0vL>no);sQ>W}_z|4i
zaG<7+G22t}0oVNc2hphw#~#WQG)!UK_W7ss-BS!(|5`rK(qumJ;b%Jg6vlUvQPrLo
z89($tZMeFGCm<p7tEwyOgU14VH(XCKy#Db=@ariC)4di8W=vre`~36x@2QMl(SPQZ
zOfO-)GqL8ML=fAJ<jl{iN53@eVwBm?IfXH7+viD1We1uK_%sw^8UBmd{Xe0W+OS#I
z&WZOD>kpeL=l3^EVKj@lRqOeXAz1gXAnUo$Z%=Ld#y2DTZBW2<y?t5nw%?Yy_)j)D
zU$87aM{vr-cP8gzriV-t&-!_LvPpL563I5@wVxI)IAzja_;~x0_dn&JkwPr>;$lOg
zv8pROqw91QQC3FP`zp5loFCr%2u)2YPt6sb`gGItr`=X>__zLel`ZmA?b9j0s?Ix`
tCfgaEd{w9pD$4(*Zq+=S<+$SVUsiUm)Y%_p|0ja%_H^}gS?83{1OU_kG$a53

diff --git a/assets/icons/colors_8.png b/assets/icons/colors_8.png
deleted file mode 100644
index b660ef3e29aefc5c940a327aaf7a22d76a73bb23..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 2193
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

diff --git a/assets/icons/level_easy.png b/assets/icons/level_easy.png
deleted file mode 100644
index aa9e2485272c12fd99d9e1faae5d71d027ee5431..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 3055
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
XSzn-jOXOAt1_lOCS3j3^P6<r_R}qmZ

diff --git a/assets/icons/level_hard.png b/assets/icons/level_hard.png
deleted file mode 100644
index 433c686b984fd22c4966def3dedcaf7384951810..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 7309
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

diff --git a/assets/icons/level_medium.png b/assets/icons/level_medium.png
deleted file mode 100644
index 213f2ca844afb0cea47cc4bdd1b865433b068b59..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 5156
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
CrMu_=

diff --git a/assets/icons/level_nightmare.png b/assets/icons/level_nightmare.png
deleted file mode 100644
index df4182c1e228bbb33c5546d2df38d16ca1edd4f2..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 9098
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

diff --git a/assets/icons/size_extra.png b/assets/icons/size_extra.png
deleted file mode 100644
index d3401d9dd4df7a871eb7ac88592707f63480d0dc..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 962
zcmeAS@N?(olHy`uVBq!ia0y~yU^oE69Lx+145>_WOc@v$I14-?iy0VXB0!k&?2PAU
z7#J8NOI#yLg7ec#$`gxH8OqDc^)mCai<1)zQuXqS(r3T3kz!zA<O}c#ab*AjMs`+S
z4G_@O)X>({(ACn^)zZ|{($dn_)YsND(AG56*4Eb1GStyB*3r??)iTl5)z#P6H!v_T
z)Uh=*G&C|YGB!3gF)=YSGcz|gx3I9Vw6wIcva+_ewzajjx3_n2aBy;Ra&d8Sb#--f
zb8~lh_wexW@$vEV^Yi!j4+sbd3=9kp508wDjEahij*gCriHVDgi+5ZfA0MBTl$4yD
zoRX4~mX?;4m6e~LUr<m`US3{NQBhM<Q&(5l($do2-rn2W+t=4OVZwxo6DLlYGG*Gd
zX|rd~o-=38ym|B1tXZ>R!-kzZckbD<=g5&G$BrGlaN)w`%a`xmx%1$`gC|d(ynXxj
z<HwKx|NpltwK>kfz+~#_;uunK>+PN6K_ZC~tQQ)Y`}n+s1Y8B$71EA2%qTw4ar1k<
zp!nuLDW)O3y5IHkudZFUdFHzP*}J0G9!t;IaZoaAYt-TG(sLd%FmWg}U?u)}A9(Yz
z{yB$5)GtGWDE7q(Yre={xcAs-b1m~S9+O~3mI4Ka$=Ryv2a8^wZ{BHT!5HRMFE(do
z^T}G4oIjd7najNY%i64Hp7$pF<^5*!(hY(R42&!SaH8M@qwI{^dX~I;)BjmTtZ2?G
zSp6k?K{R{ug_qI>MmL=QdN44uTu@Jt*|l3W{Gi`U`-a)28#wHy{?n`oVULwKUyJH&
zi#-jT5q~3#cx!b2if;&Ie|}*5rTr}DUnPjD{bG9(An(Ay%f2P?U*buj8#;e&FRX2r
zEZF}g{J>GG8SQ27n2{YO;K0z!x+QT_v=OJ6*L~|Ozv~ALH^lt9XTLn{+YYDy?x$>~
zaws&kF)vH_TYggQN6fGFd!L7wZs4h#@=v!Skp1;eek5NCI54!!81Q*pt7<<ed^x|F
zyR?97kJewY9f9oLZ;oqgSYBZla5&5;8&MO!iErMNec!c9R`ON(FN~jFCw*sav+K9V
zrFZU}K#L<bu8cqK&Fs?|m?SI~e4PK@{st#%U?4^5f`ttWAF`#dxccJ{E9;?cSL~-K
Qz5(SZPgg&ebxsLQ0E{1ItN;K2

diff --git a/assets/icons/size_large.png b/assets/icons/size_large.png
deleted file mode 100644
index 18b3420564654a9adf32e5a91d0d41f82fd4e2ce..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 774
zcmeAS@N?(olHy`uVBq!ia0y~yU^oE69Lx+145>_WOc@v$I14-?iy0VXB0!k&?2PAU
z7#J8NOI#yLg7ec#$`gxH8OqDc^)mCai<1)zQuXqS(r3T3kz!zA*c;#z;>y6lz{tSB
z&&H~up`od%simc*t*x!2qhnxTU~Ft`YHDh(qh)SxZmp|rZEbC1V`HbMZLg=};Nalo
z<mBw^?CR?3;o;$BsOx2@=Vz?vXRPn%=ND+KA84W<5)u+>Vi0PoA7y3`7Z(?AZkUje
zkd%~^oSdARnwplDR#H+@QBhG<RaISG-QZx>+uJ*7(xfR<rc9kWb;gVtvu4ejJ$v??
zIdisc+qP%Vo`VMu9y@mIY^c-Ir%ykA{P^k9r~m)|>&2?gU|?W8<>}%WQgQ3;9nWCl
zK#_)vJS?n20y9&2x)ivYj86RcUoZCM?7IAf>l5AQ?*6mu-fF9ruS)jDm8=f^v&EX#
z|F`6Yow^lP40yqNiGok1f8Ow|x_Ls}F0|J0yZ*+6_pNXJq?mbj3(r(!U~pL6u>1F~
zId1>w{`y;T)&BWEU9p&@b>@Nx4ky>1Tm0YmuOWl?PWfX^^(*a>Eiz%b(f9Yf{_D;1
zwf0|6uUvKh$vz?Ox+QkMRJTbppYeU>W5dqCa6ur!_M83g73aUdXkQtBWdDVncdIu(
zNPm@n@wzQLvT65Z69j(OdkCu^&(n{8v2VkI->;e)ooyK$7Mp+k<W>9Y;_sFHaZdiv
z{~7A(EZKMGgYO$lWbGgJGh}c4e=xAtP5t1~EB$WkTZ`uRa?f5V?-F0Uf}Mdu!ajQA
z|F6EaeT)Bl{aqIR_2-@Pq=WOXtY4g8$%kxC54*_!OriMgj0_rL0e{kO-Mfb@i^&#Y
h&nV}bSGM{`B~yZ2+wU_c&Xs}`dAj<!taD0e0stH>9UcGx

diff --git a/assets/icons/size_medium.png b/assets/icons/size_medium.png
deleted file mode 100644
index 4b4f7754fb46de7cf2ddfc265da900bf77cc0d3e..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 661
zcmeAS@N?(olHy`uVBq!ia0y~yU^oE69Lx+145>_WOc@v$I14-?iy0VXB0!k&?2PAU
z7#J8NOI#yLg7ec#$`gxH8OqDc^)mCai<1)zQuXqS(r3T3kz!zASQ_9H;>y6lz{toT
z#KWSYp`oRvrK_uJU|?WrX=!C;Wo>P3Yinz7Z|~sX5bdfH9UUFxrV|qr6B`?w<f)sS
zoSc%9l9iQ}<FA|Jua_I3m!F?sP*6}5tXCYY-<6=>m0-}FsNbDv(3@n?muxU0#c)cR
z;hZ^hR<B;YY15{iJ9qBcv*&Q5$&n*RjvYI8{P^(;7cN}BeEIh6+YcT*c=F`Q+qZ8&
ze*E}pj>Z4~|7W~e{gi=$vCz}SF{I+w+uJAom>fk|0}gNsrn?@EbYUrUdh*}ixAxtx
z6h|j1@AI+urk^?;S-NWSs*p|oTc;JSn%{7%`q)ZF2BN^9$^#F+JumsTuV@zExugp-
zi*f?29#mzn+sVkl5W%s)TIZSGueD3$*ByOe_i{HktBqe*W#>PYm+I1n72dxTk*shy
z+3@+sZE4ZZ0)Oi+^<PW=Fz3tO7y91pIp@Cn?crr$2rzn}@$KEVZp)5+GrzpODj}ox
z*YC^meW197oARISLf77}X@*~4giqSHQ>OXY6lUG&RSXObH;V+Te?Lx|x9@+v>farL
z&DWQ_cdvhH4cExPz+fP)@LOFY&XAEIh5N)m%XjZNkY#bR9o!nSbRUOk-+a#eAu!;3
S`i3cTAjO`pelF{r5}E+3Nbo}d

diff --git a/assets/icons/size_small.png b/assets/icons/size_small.png
deleted file mode 100644
index 2c72840d2dfe2dfb36791973a159869a325de758..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 480
zcmeAS@N?(olHy`uVBq!ia0y~yU^oE69Lx+145>_WOc@v$I14-?iy0VXB0!k&?2PAU
z7#J8NOI#yLg7ec#$`gxH8OqDc^)mCai<1)zQuXqS(r3T3kz!zA@Cfh;ab;j&U}R+A
z=402;(9qP>)Y8(@*4Eb1(J?hOH8(eRa&mHYbxkOBPOfxGsd7n8O--wHEuZ3BHN&rO
zOT_d8F|%gPnmv2=|Ns9*mhx&bFfdAbx;TbZ+<JR!H(!&3h-)C5=uvSEyMO=vLv_?m
zj<xLERaTi1!KygfC$v@nYNNNmLoH_vF9T`dgL=b5o51>-YyP&fU5s<Y<V%?t7&N#p
z+}$*7eeLA;u@f6!+peyBd%I>o6SBcI>;)3{)3=_hnqT|5*7RL_62tHFd|#^>8sZuE
z*gq<pZu-u5-}ctpBmY2w3)lFW=}^3BK{P9af{wzUt*3vY7ztN}o58{8QTiZAbRT<`
WRNXSKx%+!SN<CfuT-G@yGywo@K!HpE

diff --git a/assets/icons/skin_default.png b/assets/icons/skin_default.png
deleted file mode 100644
index ee53cc12eaad99722e3dd8fadd52e76bdf5ed977..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 949
zcmeAS@N?(olHy`uVBq!ia0y~yU^oE69Lx+145>_WOc@v$I14-?iy0WCPk}I_+{y{!
z3=9mCC9V-A!TD(=<%vb94CUqJdYO6I#mR{Use1WE>9gP2NHH)lS_k-qxPnaJ<W$L0
zQ4Lj9Q&UrmR8wndQCqi8JxX1pvr{urQ?t8Ut5!?9tW3LBTldTv-Lq#+=a^dj|8E~)
z?~s`2<elpj(B>5A<P;z89N6LFo$2Y9;2RJfXdD)39vbKn5*QvB7#kbp5fYkxAWAba
z$}cFY;8e6$a<sE^bYM_)n0u^)V{AxJyk|hXmrJ6jV`8LTnrlF&b3kUSac1+|Ty5Rl
zc)fz2zePnw#l^)XB_*Y$rDYEKWo2a*>RMHL?bX%QH8nN0n%ec6I*kT>O)ilw4%)45
zQ5}U!9UUE=&bpnQon2jB-7b3F#Yz(=PMkDp(sYYub2YT*&6_uW{`>_C7A&;cxNzaZ
zMT-_KS+ZoEkKPVFqn-N3J0mI%$J8C3r*tOL>};gj*=5R)vL`>YvVV6#^HcHM|M|}U
z&*}8PH$Tn5!1&wK#WAGf*4ta=;nI#0t%;l|O`d8UDJ*Kwdp1foO*oiv_yE)H(^(#B
zhyVX))$@6nv}$!0|NGnZ>F0ybgqcrPT(u)dZ)xg%2FvM}iWnFee#lQ~37S~Eu}soh
zJac*{f55ys(`IR~*3Mu0t0^da_m%0J*adv&$7<zD&X$)GmO2+5e0N32Rk=#W@P04r
zW6#3(ajt!`c4c;G78?W6;GU_%yc@q3ez|(%-Z{C2=i;*M>H=21>#99`{q6gpZ1sn`
z%67`lTa!8c_PwWhAEI9wT-kp3;lgic53qZ<O<y8rUV7l!r&U)%9#tRNe4XFRzL(En
z|GX*xbSnNkZ8kse^?NEqU;NZ}j6}Pp;S__W{NJT@Wix+0%zm}}cwxEk-k`}F|0+Lr
zQvQ1_M@HlA*`LSm2OeK;wv;WId--#x<*eC#aZ}zsQzqI9h6l0CS<zFndUQp~Tf11Z
zzvWHU+tctVp*^HrQ$lKj6qi@==OE+M`yWg>mnuC^dTUgscS%q9eUW)BBLl;O_?t0a
dr_(yL-sx|cT*6g7f7cq2#h$KyF6*2UngA4;UC{sl

diff --git a/assets/skins/default_0.png b/assets/skins/default_0.png
deleted file mode 100644
index 4d1712540f2a45d43a2aa512132e7274f1daf686..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 157
zcmeAS@N?(olHy`uVBq!ia0y~yU^oE6jLZxS3>iZITo@P_I14-?iy0VXB0!k&?2PAU
z7#J8NOI#yLg7ec#$`gxH8OqDc^)mCai<1)zQuXqS(r3T3kz!zAU=HvJasB`Q|MDZ!
zCm0wQq&;06LnI{M9yDZRU|=|;@Oyb2FMk390|P^Wj?e)H#&-6L??60HS3j3^P6<r_
Dst+uv

diff --git a/assets/skins/default_1.png b/assets/skins/default_1.png
deleted file mode 100644
index 3ca3e7164af5cde6e6750172c2149cb63ebb7165..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 157
zcmeAS@N?(olHy`uVBq!ia0y~yU^oE6jLZxS3>iZITo@P_I14-?iy0VXB0!k&?2PAU
z7#J8NOI#yLg7ec#$`gxH8OqDc^)mCai<1)zQuXqS(r3T3kz!zAU=HvJaeZcGKl4^n
z4+8^(w5N+>h=k<ZgNBR@3=D@9elL&X<xgN>U|=ZF5jw!Y*v@|O9f;@Y>gTe~DWM4f
DQmrc;

diff --git a/assets/skins/default_2.png b/assets/skins/default_2.png
deleted file mode 100644
index 56ad59eff020c5dd84e9d257ff91c5f8f88e6f33..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 157
zcmeAS@N?(olHy`uVBq!ia0y~yU^oE6jLZxS3>iZITo@P_I14-?iy0VXB0!k&?2PAU
z7#J8NOI#yLg7ec#$`gxH8OqDc^)mCai<1)zQuXqS(r3T3kz!zAU=HvJaV_ZiyL=;0
z4g&*&w5N+>h=k<ZgNBR@3=D@9elL&X<xgN>U|=ZF5jw!Y*v@|O9f;@Y>gTe~DWM4f
DRnaRZ

diff --git a/assets/skins/default_3.png b/assets/skins/default_3.png
deleted file mode 100644
index e92c6694a192606905b8119f2a213b8cadf14ba5..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 157
zcmeAS@N?(olHy`uVBq!ia0y~yU^oE6jLZxS3>iZITo@P_I14-?iy0VXB0!k&?2PAU
z7#J8NOI#yLg7ec#$`gxH8OqDc^)mCai<1)zQuXqS(r3T3kz!zAU=HvJaW$P|$~RYf
z3IhX!w5N+>h=k<ZgNBR@3=D@9elL&X<xgN>U|=ZF5jw!Y*v@|O9f;@Y>gTe~DWM4f
D24^X~

diff --git a/assets/skins/default_4.png b/assets/skins/default_4.png
deleted file mode 100644
index 74feaa46de20c31c30e28c8c1dd96d5bff212f02..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 157
zcmeAS@N?(olHy`uVBq!ia0y~yU^oE6jLZxS3>iZITo@P_I14-?iy0VXB0!k&?2PAU
z7#J8NOI#yLg7ec#$`gxH8OqDc^)mCai<1)zQuXqS(r3T3kz!zAU=HvJas7Wzr_Oo4
z2m=Fyw5N+>h=k<ZgNBR@3=D@9elL&X<xgN>U|=ZF5jw!Y*v@|O9f;@Y>gTe~DWM4f
DL%k}>

diff --git a/assets/skins/default_5.png b/assets/skins/default_5.png
deleted file mode 100644
index abcf897497ebc0ccab435b576985dd854be011fe..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 157
zcmeAS@N?(olHy`uVBq!ia0y~yU^oE6jLZxS3>iZITo@P_I14-?iy0VXB0!k&?2PAU
z7#J8NOI#yLg7ec#$`gxH8OqDc^)mCai<1)zQuXqS(r3T3kz!zAU=HvJas8j~EE1Gg
z%D})N?djqeA|d(qpdljz1H&PO-^=58`4boz7#Iq4gbpw;wzFS+2jY3U`njxgN@xNA
DDUm8y

diff --git a/assets/skins/default_6.png b/assets/skins/default_6.png
deleted file mode 100644
index aee88ace319e14392688b29f92fa0da137bb4339..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 157
zcmeAS@N?(olHy`uVBq!ia0y~yU^oE6jLZxS3>iZITo@P_I14-?iy0VXB0!k&?2PAU
z7#J8NOI#yLg7ec#$`gxH8OqDc^)mCai<1)zQuXqS(r3T3kz!zAU=HvJab0M$aYN{b
z3<d@UX-^l&5DCe*2Mrk+7#I#I{9Yc%%b&o&z`#(TBXod)v7P<mI}p#))z4*}Q$iB}
DTV^Xr

diff --git a/assets/skins/default_7.png b/assets/skins/default_7.png
deleted file mode 100644
index 3e0ac15c6eea57e437afc36ebf81a618b342256e..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 157
zcmeAS@N?(olHy`uVBq!ia0y~yU^oE6jLZxS3>iZITo@P_I14-?iy0VXB0!k&?2PAU
z7#J8NOI#yLg7ec#$`gxH8OqDc^)mCai<1)zQuXqS(r3T3kz!zAU=HvJakcpW-&kcf
zF9QREw5N+>h=k<ZgNBR@3=D@9elL&X<xgN>U|=ZF5jw!Y*v@|O9f;@Y>gTe~DWM4f
DHqk1Q

diff --git a/assets/skins/default_8.png b/assets/skins/default_8.png
deleted file mode 100644
index 70b58df7443e74de8523829600b4c6cc19eab5a9..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 157
zcmeAS@N?(olHy`uVBq!ia0y~yU^oE6jLZxS3>iZITo@P_I14-?iy0VXB0!k&?2PAU
z7#J8NOI#yLg7ec#$`gxH8OqDc^)mCai<1)zQuXqS(r3T3kz!zAU=HvJas5<0clNaS
z6$}gv(w;7kArg{r4;nHuFfbfa_`N)imp_4lfq|hwN9X_pV>|oBcOagptDnm{r-UW|
DZOto}

diff --git a/assets/translations/en.json b/assets/translations/en.json
index c40bf79..9229916 100644
--- a/assets/translations/en.json
+++ b/assets/translations/en.json
@@ -1,8 +1,6 @@
 {
   "app_name": "Colors",
 
-  "long_press_to_quit": "Long press to quit game...",
-
   "bottom_nav_home": "Game",
   "bottom_nav_settings": "Settings",
   "bottom_nav_about": "About",
diff --git a/assets/translations/fr.json b/assets/translations/fr.json
index 895e185..dc7d503 100644
--- a/assets/translations/fr.json
+++ b/assets/translations/fr.json
@@ -1,8 +1,6 @@
 {
   "app_name": "Colors",
 
-  "long_press_to_quit": "Appuyer longtemps pour quitter le jeu...",
-
   "bottom_nav_home": "Jeu",
   "bottom_nav_settings": "Réglages",
   "bottom_nav_about": "Infos",
diff --git a/fastlane/metadata/android/en-US/changelogs/39.txt b/fastlane/metadata/android/en-US/changelogs/39.txt
new file mode 100644
index 0000000..9bb4c4d
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/39.txt
@@ -0,0 +1 @@
+Improve application architecture.
diff --git a/fastlane/metadata/android/fr-FR/changelogs/39.txt b/fastlane/metadata/android/fr-FR/changelogs/39.txt
new file mode 100644
index 0000000..5face79
--- /dev/null
+++ b/fastlane/metadata/android/fr-FR/changelogs/39.txt
@@ -0,0 +1 @@
+Amélioration de l'architecture de l'application.
diff --git a/icons/build_game_icons.sh b/icons/build_game_icons.sh
index 1817ed0..7ea6ed5 100755
--- a/icons/build_game_icons.sh
+++ b/icons/build_game_icons.sh
@@ -22,31 +22,6 @@ AVAILABLE_GAME_IMAGES="
   game_win
 "
 
-# Settings images
-AVAILABLES_GAME_SETTINGS="
-  colors:5,6,7,8
-  level:easy,medium,hard,nightmare
-  size:small,medium,large,extra
-"
-
-# Skins
-AVAILABLE_SKINS="
-  default
-"
-
-# Images per skin
-SKIN_IMAGES="
-  0
-  1
-  2
-  3
-  4
-  5
-  6
-  7
-  8
-"
-
 #######################################################
 
 # optimize svg
@@ -89,41 +64,13 @@ function build_icon() {
   optipng ${OPTIPNG_OPTIONS} ${TARGET}
 }
 
-function build_settings_icons() {
-  INPUT_STRING="$1"
-
-  SETTING_NAME="$(echo "${INPUT_STRING}" | cut -d":" -f1)"
-  SETTING_VALUES="$(echo "${INPUT_STRING}" | cut -d":" -f2 | tr "," " ")"
-
-  for SETTING_VALUE in ${SETTING_VALUES}
-  do
-    SETTING_CODE="${SETTING_NAME}_${SETTING_VALUE}"
-    build_icon ${CURRENT_DIR}/${SETTING_CODE}.svg ${ASSETS_DIR}/icons/${SETTING_CODE}.png
-  done
-}
-
-function build_icon_for_skin() {
-  SKIN_CODE="$1"
-
-  # skin main image
-  build_icon ${CURRENT_DIR}/skin_${SKIN_CODE}.svg ${ASSETS_DIR}/icons/skin_${SKIN_CODE}.png
-
-  # skin images
-  for SKIN_IMAGE in ${SKIN_IMAGES}
-  do
-    build_icon ${CURRENT_DIR}/skins/${SKIN_CODE}/${SKIN_IMAGE}.svg ${ASSETS_DIR}/skins/${SKIN_CODE}_${SKIN_IMAGE}.png
-  done
-}
-
 #######################################################
 
 # Create output folders
 mkdir -p ${ASSETS_DIR}/icons
-mkdir -p ${ASSETS_DIR}/skins
 
 # Delete existing generated images
 find ${ASSETS_DIR}/icons -type f -name "*.png" -delete
-find ${ASSETS_DIR}/skins -type f -name "*.png" -delete
 
 # build game images
 for GAME_IMAGE in ${AVAILABLE_GAME_IMAGES}
@@ -131,14 +78,3 @@ do
   build_icon ${CURRENT_DIR}/${GAME_IMAGE}.svg ${ASSETS_DIR}/icons/${GAME_IMAGE}.png
 done
 
-# build settings images
-for GAME_SETTING in ${AVAILABLES_GAME_SETTINGS}
-do
-  build_settings_icons "${GAME_SETTING}"
-done
-
-# build skins images
-for SKIN in ${AVAILABLE_SKINS}
-do
-  build_icon_for_skin "${SKIN}"
-done
diff --git a/icons/colors_5.svg b/icons/colors_5.svg
deleted file mode 100644
index 2f218e9..0000000
--- a/icons/colors_5.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 102 102" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x="1" y="1" width="100" height="100" ry="0" fill="#97c05c" stroke="#000" stroke-width="2"/><g transform="translate(-1.0061 .33115)" aria-label="5"><path d="m63.315 55.063q0 2.2656-0.85938 4.2188-0.83984 1.9336-2.4609 3.3203-1.7969 1.4844-4.1406 2.207-2.3242 0.70312-5.3125 0.70312-3.4961-0.01953-5.918-0.56641-2.4023-0.52734-3.9258-1.1914v-6.4258h0.82031q1.7773 1.0547 3.8281 1.7578t4.082 0.70312q1.2305 0 2.6562-0.27344 1.4453-0.29297 2.2852-1.0352 0.66406-0.60547 0.99609-1.2305 0.35156-0.625 0.35156-1.9336 0-1.0156-0.46875-1.7383-0.44922-0.74219-1.1719-1.1914-1.0547-0.64453-2.5391-0.83984-1.4844-0.21484-2.6953-0.21484-1.7578 0-3.3789 0.3125-1.6016 0.29297-2.8125 0.58594h-0.85938v-16.406h20.684v5.5664h-13.633v4.7461q0.60547-0.03906 1.5234-0.05859 0.9375-0.03906 1.6406-0.03906 2.4023 0 4.2773 0.46875 1.8945 0.44922 3.2617 1.2695 1.7773 1.0742 2.7734 2.8516 0.99609 1.7578 0.99609 4.4336z"/></g><rect x="67.01" y="67.01" width="29.323" height="29.323" fill="#ff6f43" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="67.01" y="36.339" width="29.323" height="29.323" fill="#ffce2c" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="67.01" y="5.6672" width="29.323" height="29.323" fill="#359c35" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="36.339" y="5.6672" width="29.323" height="29.323" fill="#708cfd" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="5.6671" y="5.6672" width="29.323" height="29.323" fill="#e63a3f" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/></svg>
diff --git a/icons/colors_6.svg b/icons/colors_6.svg
deleted file mode 100644
index 6df1641..0000000
--- a/icons/colors_6.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 102 102" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x="1" y="1" width="100" height="100" ry="0" fill="#f29c38" stroke="#000" stroke-width="2"/><g transform="translate(3.8694 .21001)" aria-label="6"><path d="m59.025 55.399q0 2.2461-0.82031 4.2188t-2.3047 3.3203q-1.582 1.4453-3.6719 2.207-2.0703 0.76172-4.8633 0.76172-2.6172 0-4.7852-0.70312-2.1484-0.72266-3.6914-2.1875-1.7773-1.6797-2.7148-4.3359t-0.9375-6.3477q0-3.8281 0.87891-6.7969t2.8711-5.2539q1.9141-2.1875 4.9609-3.3984 3.0664-1.2109 7.2852-1.2109 1.4258 0 3.125 0.19531t2.207 0.29297v5.7227h-0.74219q-0.52734-0.25391-1.7969-0.56641-1.25-0.33203-2.8516-0.33203-3.75 0-5.8398 1.8359t-2.5195 5.1172q1.5039-0.89844 3.1641-1.4453 1.6797-0.56641 3.6133-0.56641 1.6992 0 3.1445 0.39062 1.4648 0.39062 2.7148 1.25 1.6211 1.1328 2.5977 3.0469 0.97656 1.9141 0.97656 4.7852zm-8.8867 4.3945q0.60547-0.66406 0.95703-1.5625 0.37109-0.91797 0.37109-2.4805 0-1.4258-0.41016-2.3242-0.41016-0.91797-1.1328-1.4648-0.70312-0.54688-1.6602-0.74219-0.95703-0.21484-1.9727-0.21484-0.85938 0-1.7969 0.19531-0.9375 0.19531-1.7188 0.48828 0 0.19531-0.01953 0.64453t-0.01953 1.1328q0 2.4023 0.46875 3.9648 0.48828 1.543 1.2891 2.3633 0.54688 0.60547 1.2891 0.89844 0.74219 0.27344 1.6016 0.27344 0.64453 0 1.4258-0.29297t1.3281-0.87891z"/></g><rect x="36.339" y="67.01" width="29.323" height="29.323" fill="#a13cb1" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="67.01" y="67.01" width="29.323" height="29.323" fill="#ff6f43" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="67.01" y="36.339" width="29.323" height="29.323" fill="#ffce2c" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="67.01" y="5.6672" width="29.323" height="29.323" fill="#359c35" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="36.339" y="5.6672" width="29.323" height="29.323" fill="#708cfd" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="5.6671" y="5.6672" width="29.323" height="29.323" fill="#e63a3f" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/></svg>
diff --git a/icons/colors_7.svg b/icons/colors_7.svg
deleted file mode 100644
index 7870bc7..0000000
--- a/icons/colors_7.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 102 102" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x="1" y="1" width="100" height="100" ry="0" fill="#cd5542" stroke="#000" stroke-width="2"/><g transform="translate(3.9378 .2393)" aria-label="7"><path d="m58.459 42.001-13.164 23.301h-8.3594l13.672-23.516h-14.941v-5.5664h22.793z"/></g><rect x="5.6671" y="67.01" width="29.323" height="29.323" fill="#38ffff" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="36.339" y="67.01" width="29.323" height="29.323" fill="#a13cb1" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="67.01" y="67.01" width="29.323" height="29.323" fill="#ff6f43" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="67.01" y="36.339" width="29.323" height="29.323" fill="#ffce2c" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="67.01" y="5.6672" width="29.323" height="29.323" fill="#359c35" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="36.339" y="5.6672" width="29.323" height="29.323" fill="#708cfd" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="5.6671" y="5.6672" width="29.323" height="29.323" fill="#e63a3f" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/></svg>
diff --git a/icons/colors_8.svg b/icons/colors_8.svg
deleted file mode 100644
index 37f3949..0000000
--- a/icons/colors_8.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 102 102" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x="1" y="1" width="100" height="100" ry="0" fill="#6041b0" stroke="#000" stroke-width="2"/><g transform="translate(4.1624 .2393)" aria-label="8"><path d="m59.123 57.177q0 3.8672-3.3008 6.3281-3.2812 2.4609-9.0234 2.4609-3.2227 0-5.5273-0.66406-2.3047-0.66406-3.8086-1.8359-1.4844-1.1523-2.207-2.6953-0.70312-1.543-0.70312-3.3203 0-2.1875 1.2695-3.8672 1.2891-1.6992 4.4336-2.9688v-0.11719q-2.5391-1.1719-3.7305-2.9492t-1.1914-4.1211q0-3.457 3.2031-5.6641 3.2031-2.207 8.3398-2.207 5.3906 0 8.4375 2.0117 3.0664 1.9922 3.0664 5.332 0 2.0703-1.2891 3.6914t-3.9453 2.7539v0.11719q3.0469 1.1523 4.5117 3.1055t1.4648 4.6094zm-8.0664-13.438q0-1.4844-1.1523-2.3633-1.1328-0.87891-3.0273-0.87891-0.70312 0-1.4453 0.17578-0.72266 0.17578-1.3281 0.50781-0.56641 0.33203-0.9375 0.87891-0.37109 0.52734-0.37109 1.2109 0 1.1523 0.64453 1.7969 0.66406 0.64453 2.1484 1.2891 0.54688 0.23438 1.4844 0.58594 0.95703 0.33203 2.3047 0.76172 0.89844-1.0547 1.2891-1.8945 0.39062-0.83984 0.39062-2.0703zm0.60547 13.77q0-1.4062-0.70312-2.1289t-2.8906-1.6602q-0.64453-0.29297-1.875-0.72266-1.2305-0.42969-2.0703-0.74219-0.83984 0.76172-1.5234 1.8555-0.66406 1.0742-0.66406 2.4219 0 2.0312 1.4453 3.2422 1.4648 1.1914 3.8086 1.1914 0.625 0 1.4648-0.17578 0.83984-0.19531 1.4453-0.58594 0.70312-0.44922 1.1328-1.0547 0.42969-0.60547 0.42969-1.6406z"/></g><rect x="5.6671" y="36.339" width="29.323" height="29.323" fill="#f2739d" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="5.6671" y="67.01" width="29.323" height="29.323" fill="#38ffff" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="36.339" y="67.01" width="29.323" height="29.323" fill="#a13cb1" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="67.01" y="67.01" width="29.323" height="29.323" fill="#ff6f43" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="67.01" y="36.339" width="29.323" height="29.323" fill="#ffce2c" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="67.01" y="5.6672" width="29.323" height="29.323" fill="#359c35" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="36.339" y="5.6672" width="29.323" height="29.323" fill="#708cfd" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="5.6671" y="5.6672" width="29.323" height="29.323" fill="#e63a3f" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/></svg>
diff --git a/icons/level_easy.svg b/icons/level_easy.svg
deleted file mode 100644
index 30048ce..0000000
--- a/icons/level_easy.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 102 102" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x="1" y="1" width="100" height="100" ry="0" fill="#97c05c" stroke="#000" stroke-width="2"/><path d="m50.952 32.393c1.3622-0.0046 4.9652 11.398 6.07 12.195 1.1048 0.79696 13.062 0.61914 13.487 1.9133s-9.3059 8.2444-9.7225 9.5414c-0.41657 1.297 3.4475 12.614 2.3481 13.418-1.0993 0.80441-10.717-6.3028-12.079-6.2982-1.3622 0.0046-10.931 7.1767-12.036 6.3797s2.6827-12.14 2.2574-13.434c-0.42533-1.2941-10.203-8.1785-9.7868-9.4754 0.41657-1.297 12.375-1.2 13.474-2.0044s4.6252-12.231 5.9874-12.236z" fill="#fff" stroke="#030303" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="6" stroke-width="3.3"/></svg>
diff --git a/icons/level_hard.svg b/icons/level_hard.svg
deleted file mode 100644
index 976249e..0000000
--- a/icons/level_hard.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 102 102" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x="1" y="1" width="100" height="100" ry="0" fill="#cd5542" stroke="#000" stroke-width="2"/><path d="m28.065 11.952c1.3622-0.0046 4.9652 11.398 6.07 12.195 1.1048 0.79696 13.062 0.61914 13.487 1.9133s-9.3059 8.2444-9.7225 9.5414c-0.41657 1.297 3.4475 12.614 2.3481 13.418-1.0993 0.80441-10.717-6.3028-12.079-6.2982-1.3622 0.0046-10.931 7.1767-12.036 6.3797s2.6827-12.14 2.2574-13.434c-0.42533-1.2941-10.203-8.1785-9.7868-9.4754 0.41657-1.297 12.375-1.2 13.474-2.0044s4.6252-12.231 5.9874-12.236z" fill="#fff" stroke="#010101" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="6" stroke-width="3.3"/><path d="m73.839 11.952c1.3622-0.0046 4.9652 11.398 6.07 12.195s13.062 0.61914 13.487 1.9133c0.42533 1.2941-9.3059 8.2444-9.7225 9.5414-0.41657 1.297 3.4475 12.614 2.3481 13.418-1.0993 0.80441-10.717-6.3028-12.079-6.2982-1.3622 0.0046-10.931 7.1767-12.036 6.3797s2.6827-12.14 2.2574-13.434c-0.42533-1.2941-10.203-8.1785-9.7868-9.4754 0.41657-1.297 12.375-1.2 13.474-2.0044 1.0993-0.80441 4.6252-12.231 5.9874-12.236z" fill="#fff" stroke="#010101" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="6" stroke-width="3.3"/><path d="m50.952 52.835c1.3622-0.0046 4.9652 11.398 6.07 12.195 1.1048 0.79696 13.062 0.61914 13.487 1.9133 0.42533 1.2941-9.3059 8.2444-9.7225 9.5414-0.41657 1.297 3.4475 12.614 2.3481 13.418-1.0993 0.80441-10.717-6.3028-12.079-6.2982-1.3622 5e-3 -10.931 7.1767-12.036 6.3797s2.6827-12.14 2.2574-13.434-10.203-8.1785-9.7868-9.4754c0.41657-1.297 12.375-1.2 13.474-2.0044 1.0993-0.80442 4.6252-12.231 5.9874-12.236z" fill="#fff" stroke="#010101" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="6" stroke-width="3.3"/></svg>
diff --git a/icons/level_medium.svg b/icons/level_medium.svg
deleted file mode 100644
index e70fd60..0000000
--- a/icons/level_medium.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 102 102" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x="1" y="1" width="100" height="100" ry="0" fill="#f29c38" stroke="#000" stroke-width="2"/><path d="m27.72 32.393c1.3622-0.0046 4.9652 11.398 6.07 12.195 1.1048 0.79696 13.062 0.61914 13.487 1.9133s-9.3059 8.2444-9.7225 9.5414c-0.41657 1.297 3.4475 12.614 2.3481 13.418-1.0993 0.80441-10.717-6.3028-12.079-6.2982-1.3622 0.0046-10.931 7.1767-12.036 6.3797s2.6827-12.14 2.2574-13.434c-0.42533-1.2941-10.203-8.1785-9.7868-9.4754 0.41657-1.297 12.375-1.2 13.474-2.0044s4.6252-12.231 5.9874-12.236z" fill="#fff" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="6" stroke-width="3.3"/><path d="m74.183 32.393c1.3622-0.0046 4.9652 11.398 6.07 12.195s13.062 0.61914 13.487 1.9133-9.3059 8.2444-9.7225 9.5414c-0.41656 1.297 3.4475 12.614 2.3482 13.418-1.0994 0.80441-10.717-6.3028-12.079-6.2982-1.3622 0.0046-10.931 7.1767-12.036 6.3797-1.1048-0.79696 2.6827-12.14 2.2574-13.434s-10.203-8.1785-9.7868-9.4754c0.41657-1.297 12.375-1.2 13.474-2.0044 1.0993-0.80441 4.6252-12.231 5.9874-12.236z" fill="#fff" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="6" stroke-width="3.3"/></svg>
diff --git a/icons/level_nightmare.svg b/icons/level_nightmare.svg
deleted file mode 100644
index 87f28a3..0000000
--- a/icons/level_nightmare.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 102 102" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x="1" y="1" width="100" height="100" ry="0" fill="#6041b0" stroke="#000" stroke-width="2"/><path d="m28.929 11.793c1.3622-0.0046 4.9652 11.398 6.07 12.195 1.1048 0.79696 13.062 0.61914 13.487 1.9133s-9.3059 8.2444-9.7225 9.5414c-0.41657 1.297 3.4475 12.614 2.3481 13.418-1.0993 0.80442-10.717-6.3028-12.079-6.2982-1.3622 0.0046-10.931 7.1767-12.036 6.3797-1.1048-0.79696 2.6827-12.14 2.2574-13.434-0.42533-1.2941-10.203-8.1785-9.7868-9.4754 0.41657-1.297 12.375-1.2 13.474-2.0044 1.0993-0.80441 4.6252-12.231 5.9874-12.236z" fill="#fff" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="6" stroke-width="3.3"/><path d="m73.125 11.861c1.3622-0.0046 4.9652 11.398 6.07 12.195 1.1048 0.79696 13.062 0.61914 13.487 1.9133 0.42533 1.2941-9.3059 8.2444-9.7225 9.5414-0.41657 1.297 3.4475 12.614 2.3481 13.418-1.0993 0.80441-10.717-6.3028-12.079-6.2982-1.3622 0.0046-10.931 7.1767-12.036 6.3797s2.6827-12.14 2.2574-13.434-10.203-8.1785-9.7868-9.4754c0.41657-1.297 12.375-1.2 13.474-2.0044 1.0993-0.80442 4.6252-12.231 5.9874-12.236z" fill="#fff" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="6" stroke-width="3.3"/><path d="m28.778 52.923c1.3622-0.0046 4.9652 11.398 6.07 12.195 1.1048 0.79696 13.062 0.61914 13.487 1.9133 0.42533 1.2941-9.3059 8.2444-9.7225 9.5414s3.4475 12.614 2.3481 13.418c-1.0993 0.80442-10.717-6.3028-12.079-6.2982-1.3622 5e-3 -10.931 7.1767-12.036 6.3797-1.1048-0.79697 2.6827-12.14 2.2574-13.434-0.42533-1.2941-10.203-8.1785-9.7868-9.4754s12.375-1.2 13.474-2.0044c1.0993-0.80441 4.6252-12.231 5.9874-12.236z" fill="#fff" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="6" stroke-width="3.3"/><path d="m73.104 52.992c1.3622-0.0046 4.9652 11.398 6.07 12.195 1.1048 0.79696 13.062 0.61914 13.487 1.9133s-9.3059 8.2444-9.7225 9.5414c-0.41657 1.297 3.4475 12.614 2.3481 13.418-1.0993 0.80442-10.717-6.3028-12.079-6.2982-1.3622 5e-3 -10.931 7.1767-12.036 6.3797-1.1048-0.79697 2.6827-12.14 2.2574-13.434-0.42533-1.2941-10.203-8.1785-9.7868-9.4754s12.375-1.2 13.474-2.0044c1.0993-0.80441 4.6252-12.231 5.9874-12.236z" fill="#fff" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="6" stroke-width="3.3"/></svg>
diff --git a/icons/size_extra.svg b/icons/size_extra.svg
deleted file mode 100644
index fe07dfb..0000000
--- a/icons/size_extra.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="0" fill="#5f41af" stroke="#000" stroke-width="2"/>
-  <g transform="translate(4.4197 1.4084)" fill="#fff" stroke="#282828" stroke-linecap="round" stroke-width="3"><rect x="13.796" y="16.807" width="12.714" height="12.714"/><rect x="26.51" y="16.807" width="12.714" height="12.714"/><rect x="39.223" y="16.807" width="12.714" height="12.714"/><rect x="51.937" y="16.807" width="12.714" height="12.714"/><rect x="64.651" y="16.807" width="12.714" height="12.714"/><rect x="13.796" y="29.521" width="12.714" height="12.714"/><rect x="26.51" y="29.521" width="12.714" height="12.714"/><rect x="39.223" y="29.521" width="12.714" height="12.714"/><rect x="51.937" y="29.521" width="12.714" height="12.714"/><rect x="64.651" y="29.521" width="12.714" height="12.714"/><rect x="13.796" y="42.235" width="12.714" height="12.714"/><rect x="26.51" y="42.235" width="12.714" height="12.714"/><rect x="39.223" y="42.235" width="12.714" height="12.714"/><rect x="51.937" y="42.235" width="12.714" height="12.714"/><rect x="64.651" y="42.235" width="12.714" height="12.714"/><rect x="13.796" y="54.948" width="12.714" height="12.714"/><rect x="26.51" y="54.948" width="12.714" height="12.714"/><rect x="39.223" y="54.948" width="12.714" height="12.714"/><rect x="51.937" y="54.948" width="12.714" height="12.714"/><rect x="64.651" y="54.948" width="12.714" height="12.714"/><rect x="13.796" y="67.662" width="12.714" height="12.714"/><rect x="26.51" y="67.662" width="12.714" height="12.714"/><rect x="39.223" y="67.662" width="12.714" height="12.714"/><rect x="51.937" y="67.662" width="12.714" height="12.714"/><rect x="64.651" y="67.662" width="12.714" height="12.714"/></g></svg>
diff --git a/icons/size_large.svg b/icons/size_large.svg
deleted file mode 100644
index 174a530..0000000
--- a/icons/size_large.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="0" fill="#cd5542" stroke="#000" stroke-width="2"/>
-  <g transform="translate(6.2763 8.2075)" fill="#fff" stroke="#282828" stroke-linecap="round" stroke-width="3"><rect x="18.296" y="16.365" width="12.714" height="12.714"/><rect x="31.01" y="16.365" width="12.714" height="12.714"/><rect x="43.724" y="16.365" width="12.714" height="12.714"/><rect x="56.437" y="16.365" width="12.714" height="12.714"/><rect x="18.296" y="29.079" width="12.714" height="12.714"/><rect x="31.01" y="29.079" width="12.714" height="12.714"/><rect x="43.724" y="29.079" width="12.714" height="12.714"/><rect x="56.437" y="29.079" width="12.714" height="12.714"/><rect x="18.296" y="41.792" width="12.714" height="12.714"/><rect x="31.01" y="41.792" width="12.714" height="12.714"/><rect x="43.724" y="41.792" width="12.714" height="12.714"/><rect x="56.437" y="41.792" width="12.714" height="12.714"/><rect x="18.296" y="54.506" width="12.714" height="12.714"/><rect x="31.01" y="54.506" width="12.714" height="12.714"/><rect x="43.724" y="54.506" width="12.714" height="12.714"/><rect x="56.437" y="54.506" width="12.714" height="12.714"/></g></svg>
diff --git a/icons/size_medium.svg b/icons/size_medium.svg
deleted file mode 100644
index bcc2fba..0000000
--- a/icons/size_medium.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="0" fill="#f29c38" stroke="#000" stroke-width="2"/>
-  <g transform="translate(11.967 8.1117)" fill="#fff" stroke="#282828" stroke-linecap="round" stroke-width="3"><rect x="18.962" y="22.818" width="12.714" height="12.714"/><rect x="31.676" y="22.818" width="12.714" height="12.714"/><rect x="44.389" y="22.818" width="12.714" height="12.714"/><rect x="18.962" y="35.531" width="12.714" height="12.714"/><rect x="31.676" y="35.531" width="12.714" height="12.714"/><rect x="44.389" y="35.531" width="12.714" height="12.714"/><rect x="18.962" y="48.245" width="12.714" height="12.714"/><rect x="31.676" y="48.245" width="12.714" height="12.714"/><rect x="44.389" y="48.245" width="12.714" height="12.714"/></g></svg>
diff --git a/icons/size_small.svg b/icons/size_small.svg
deleted file mode 100644
index 1ccb6e9..0000000
--- a/icons/size_small.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="0" fill="#97c05c" stroke="#000" stroke-width="2"/>
-  <g transform="translate(8.8715 12.603)" fill="#fff" stroke="#282828" stroke-linecap="round" stroke-width="3"><rect x="28.415" y="24.683" width="12.714" height="12.714"/><rect x="41.128" y="24.683" width="12.714" height="12.714"/><rect x="28.415" y="37.397" width="12.714" height="12.714"/><rect x="41.128" y="37.397" width="12.714" height="12.714"/></g></svg>
diff --git a/icons/skin_default.svg b/icons/skin_default.svg
deleted file mode 100644
index 18ae839..0000000
--- a/icons/skin_default.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 102 102" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x="1" y="1" width="100" height="100" ry="0" fill="#a4a4a4" stroke="#000" stroke-width="2"/><rect x="-15.387" y="-20.515" width="100" height="100" ry="2" fill="none"/><rect x="5.6673" y="36.339" width="29.323" height="29.323" fill="#f2739d" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="5.6673" y="67.01" width="29.323" height="29.323" fill="#38ffff" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="36.339" y="67.01" width="29.323" height="29.323" fill="#a13cb1" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="67.01" y="67.01" width="29.323" height="29.323" fill="#ff6f43" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="67.01" y="36.339" width="29.323" height="29.323" fill="#ffce2c" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="67.01" y="5.6674" width="29.323" height="29.323" fill="#359c35" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="36.339" y="5.6674" width="29.323" height="29.323" fill="#708cfd" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/><rect x="5.6673" y="5.6674" width="29.323" height="29.323" fill="#e63a3f" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width=".76239"/></svg>
diff --git a/icons/skins/default/0.svg b/icons/skins/default/0.svg
deleted file mode 100644
index 87a62b1..0000000
--- a/icons/skins/default/0.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="2" fill="none"/><rect width="100" height="100" fill="#fff" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width="0"/></svg>
diff --git a/icons/skins/default/1.svg b/icons/skins/default/1.svg
deleted file mode 100644
index 11201e5..0000000
--- a/icons/skins/default/1.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="2" fill="none"/><rect width="100" height="100" fill="#E63A3F" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width="0"/></svg>
diff --git a/icons/skins/default/2.svg b/icons/skins/default/2.svg
deleted file mode 100644
index 76e07b7..0000000
--- a/icons/skins/default/2.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="2" fill="none"/><rect width="100" height="100" fill="#708CFD" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width="0"/></svg>
diff --git a/icons/skins/default/3.svg b/icons/skins/default/3.svg
deleted file mode 100644
index 092dab6..0000000
--- a/icons/skins/default/3.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="2" fill="none"/><rect width="100" height="100" fill="#359C35" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width="0"/></svg>
diff --git a/icons/skins/default/4.svg b/icons/skins/default/4.svg
deleted file mode 100644
index 57094f5..0000000
--- a/icons/skins/default/4.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="2" fill="none"/><rect width="100" height="100" fill="#FFCE2C" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width="0"/></svg>
diff --git a/icons/skins/default/5.svg b/icons/skins/default/5.svg
deleted file mode 100644
index e0f4d96..0000000
--- a/icons/skins/default/5.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="2" fill="none"/><rect width="100" height="100" fill="#FF6F43" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width="0"/></svg>
diff --git a/icons/skins/default/6.svg b/icons/skins/default/6.svg
deleted file mode 100644
index feb210e..0000000
--- a/icons/skins/default/6.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="2" fill="none"/><rect width="100" height="100" fill="#A13CB1" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width="0"/></svg>
diff --git a/icons/skins/default/7.svg b/icons/skins/default/7.svg
deleted file mode 100644
index 2b9d085..0000000
--- a/icons/skins/default/7.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="2" fill="none"/><rect width="100" height="100" fill="#38FFFF" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width="0"/></svg>
diff --git a/icons/skins/default/8.svg b/icons/skins/default/8.svg
deleted file mode 100644
index 40b8092..0000000
--- a/icons/skins/default/8.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="2" fill="none"/><rect width="100" height="100" fill="#F2739D" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width="2.5e-7"/></svg>
diff --git a/lib/config/default_game_settings.dart b/lib/config/default_game_settings.dart
new file mode 100644
index 0000000..db88412
--- /dev/null
+++ b/lib/config/default_game_settings.dart
@@ -0,0 +1,81 @@
+import 'package:colors/utils/tools.dart';
+
+class DefaultGameSettings {
+  // available game parameters codes
+  static const String parameterCodeDifficultyLevel = 'difficultyLevel';
+  static const String parameterCodeBoardSize = 'boardSize';
+  static const String parameterCodeColorsCount = 'colorsCount';
+  static const List<String> availableParameters = [
+    parameterCodeDifficultyLevel,
+    parameterCodeBoardSize,
+    parameterCodeColorsCount,
+  ];
+
+  // difficulty level: available values
+  static const String difficultyLevelValueEasy = 'easy';
+  static const String difficultyLevelValueMedium = 'medium';
+  static const String difficultyLevelValueHard = 'hard';
+  static const String difficultyLevelValueNightmare = 'nightmare';
+  static const List<String> allowedDifficultyLevelValues = [
+    difficultyLevelValueEasy,
+    difficultyLevelValueMedium,
+    difficultyLevelValueHard,
+    difficultyLevelValueNightmare,
+  ];
+  // difficulty level: default value
+  static const String defaultDifficultyLevelValue = difficultyLevelValueMedium;
+
+  // board size: available values
+  static const String boardSizeValueSmall = 'small';
+  static const String boardSizeValueMedium = 'medium';
+  static const String boardSizeValueLarge = 'large';
+  static const String boardSizeValueExtra = 'extra';
+  static const List<String> allowedBoardSizeValues = [
+    boardSizeValueSmall,
+    boardSizeValueMedium,
+    boardSizeValueLarge,
+    boardSizeValueExtra,
+  ];
+  // board size: default value
+  static const String defaultBoardSizeValue = boardSizeValueMedium;
+
+  // colors count: available values
+  static const String colorsCountValueLow = '5';
+  static const String colorsCountValueMedium = '6';
+  static const String colorsCountValueHigh = '7';
+  static const String colorsCountValueVeryHigh = '8';
+  static const List<String> allowedColorsCountValues = [
+    colorsCountValueLow,
+    colorsCountValueMedium,
+    colorsCountValueHigh,
+    colorsCountValueVeryHigh,
+  ];
+  // colors count: default value
+  static const String defaultColorsCountValue = colorsCountValueMedium;
+
+  // available values from parameter code
+  static List<String> getAvailableValues(String parameterCode) {
+    switch (parameterCode) {
+      case parameterCodeDifficultyLevel:
+        return DefaultGameSettings.allowedDifficultyLevelValues;
+      case parameterCodeBoardSize:
+        return DefaultGameSettings.allowedBoardSizeValues;
+      case parameterCodeColorsCount:
+        return DefaultGameSettings.allowedColorsCountValues;
+    }
+
+    printlog('Did not find any available value for game parameter "$parameterCode".');
+    return [];
+  }
+
+  static int getMovesCountLimitDeltaFromLevelCode(String parameterLevel) {
+    const Map<String, int> values = {
+      difficultyLevelValueEasy: 5,
+      difficultyLevelValueMedium: 3,
+      difficultyLevelValueHard: 1,
+      difficultyLevelValueNightmare: -1,
+    };
+    return values[parameterLevel] ??
+        getMovesCountLimitDeltaFromLevelCode(DefaultGameSettings.defaultDifficultyLevelValue);
+  }
+}
diff --git a/lib/config/default_global_settings.dart b/lib/config/default_global_settings.dart
new file mode 100644
index 0000000..3ec1474
--- /dev/null
+++ b/lib/config/default_global_settings.dart
@@ -0,0 +1,28 @@
+import 'package:colors/utils/tools.dart';
+
+class DefaultGlobalSettings {
+  // available global parameters codes
+  static const String parameterCodeSkin = 'skin';
+  static const List<String> availableParameters = [
+    parameterCodeSkin,
+  ];
+
+  // skin: available values
+  static const String skinValueColors = 'colors';
+  static const List<String> allowedSkinValues = [
+    skinValueColors,
+  ];
+  // skin: default value
+  static const String defaultSkinValue = skinValueColors;
+
+  // available values from parameter code
+  static List<String> getAvailableValues(String parameterCode) {
+    switch (parameterCode) {
+      case parameterCodeSkin:
+        return DefaultGlobalSettings.allowedSkinValues;
+    }
+
+    printlog('Did not find any available value for global parameter "$parameterCode".');
+    return [];
+  }
+}
diff --git a/lib/config/menu.dart b/lib/config/menu.dart
index b969ec5..2f9395d 100644
--- a/lib/config/menu.dart
+++ b/lib/config/menu.dart
@@ -1,10 +1,9 @@
-import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/material.dart';
 import 'package:unicons/unicons.dart';
 
-import 'package:colors/ui/screens/about_page.dart';
-import 'package:colors/ui/screens/game_page.dart';
-import 'package:colors/ui/screens/settings_page.dart';
+import 'package:colors/ui/screens/page_about.dart';
+import 'package:colors/ui/screens/page_game.dart';
+import 'package:colors/ui/screens/page_settings.dart';
 
 class MenuItem {
   final String code;
@@ -19,35 +18,39 @@ class MenuItem {
 }
 
 class Menu {
-  static List<MenuItem> items = [
-    const MenuItem(
-      code: 'bottom_nav_home',
-      icon: Icon(UniconsLine.home),
-      page: GamePage(),
-    ),
-    const MenuItem(
-      code: 'bottom_nav_settings',
-      icon: Icon(UniconsLine.setting),
-      page: SettingsPage(),
-    ),
-    const MenuItem(
-      code: 'bottom_nav_about',
-      icon: Icon(UniconsLine.info_circle),
-      page: AboutPage(),
-    ),
-  ];
+  static const indexGame = 0;
+  static const menuItemGame = MenuItem(
+    code: 'bottom_nav_game',
+    icon: Icon(UniconsLine.home),
+    page: PageGame(),
+  );
 
-  static Widget getPageWidget(int pageIndex) {
-    return Menu.items.elementAt(pageIndex).page;
+  static const indexSettings = 1;
+  static const menuItemSettings = MenuItem(
+    code: 'bottom_nav_settings',
+    icon: Icon(UniconsLine.setting),
+    page: PageSettings(),
+  );
+
+  static const indexAbout = 2;
+  static const menuItemAbout = MenuItem(
+    code: 'bottom_nav_about',
+    icon: Icon(UniconsLine.info_circle),
+    page: PageAbout(),
+  );
+
+  static Map<int, MenuItem> items = {
+    indexGame: menuItemGame,
+    indexSettings: menuItemSettings,
+    indexAbout: menuItemAbout,
+  };
+
+  static bool isIndexAllowed(int pageIndex) {
+    return items.keys.contains(pageIndex);
   }
 
-  static List<BottomNavigationBarItem> getMenuItems() {
-    return Menu.items
-        .map((MenuItem item) => BottomNavigationBarItem(
-              icon: item.icon,
-              label: tr(item.code),
-            ))
-        .toList();
+  static Widget getPageWidget(int pageIndex) {
+    return items[pageIndex]?.page ?? menuItemGame.page;
   }
 
   static int itemsCount = Menu.items.length;
diff --git a/lib/cubit/game_cubit.dart b/lib/cubit/game_cubit.dart
new file mode 100644
index 0000000..16775c3
--- /dev/null
+++ b/lib/cubit/game_cubit.dart
@@ -0,0 +1,170 @@
+import 'dart:async';
+import 'dart:math';
+
+import 'package:equatable/equatable.dart';
+import 'package:flutter/foundation.dart';
+import 'package:flutter/material.dart';
+import 'package:hydrated_bloc/hydrated_bloc.dart';
+
+import 'package:colors/models/game.dart';
+import 'package:colors/models/settings_game.dart';
+import 'package:colors/models/settings_global.dart';
+import 'package:colors/utils/tools.dart';
+
+part 'game_state.dart';
+
+class GameCubit extends HydratedCubit<GameState> {
+  GameCubit()
+      : super(GameState(
+          currentGame: Game.createNull(),
+        ));
+
+  void updateState(Game game) {
+    emit(GameState(
+      currentGame: game,
+    ));
+  }
+
+  void refresh() {
+    final Game game = Game(
+      board: state.currentGame.board,
+      gameSettings: state.currentGame.gameSettings,
+      globalSettings: state.currentGame.globalSettings,
+      isRunning: state.currentGame.isRunning,
+      isFinished: state.currentGame.isFinished,
+      gameWon: state.currentGame.gameWon,
+      movesCount: state.currentGame.movesCount,
+      maxMovesCount: state.currentGame.maxMovesCount,
+      animationInProgress: state.currentGame.animationInProgress,
+      progress: state.currentGame.progress,
+      progressTotal: state.currentGame.progressTotal,
+      progressDelta: state.currentGame.progressDelta,
+    );
+
+    updateState(game);
+  }
+
+  void startNewGame({
+    required GameSettings gameSettings,
+    required GlobalSettings globalSettings,
+  }) {
+    printlog('Starting new game:');
+    printlog('- level: ${gameSettings.difficultyLevel}');
+    printlog('- size: ${gameSettings.parameterSize}');
+    printlog('- colors: ${gameSettings.parameterColorsCount}');
+
+    Game newGame = Game.createNew(
+      gameSettings: gameSettings,
+      globalSettings: globalSettings,
+    );
+
+    newGame.dump();
+
+    updateState(newGame);
+    updateGameIsRunning(true);
+  }
+
+  void quitGame() {
+    state.currentGame.isRunning = false;
+    refresh();
+  }
+
+  void updateCellValue(int col, int row, int value) {
+    state.currentGame.board.cells[row][col].value = value;
+    refresh();
+  }
+
+  void increaseMovesCount() {
+    state.currentGame.movesCount++;
+    refresh();
+  }
+
+  void updateProgressDelta(int progressDelta) {
+    state.currentGame.progressDelta = progressDelta;
+    refresh();
+  }
+
+  void updateProgress(int progress) {
+    state.currentGame.progress = progress;
+    refresh();
+  }
+
+  void updateAnimationInProgress(bool inProgress) {
+    state.currentGame.animationInProgress = inProgress;
+    refresh();
+  }
+
+  void updateGameIsRunning(bool gameIsRunning) {
+    state.currentGame.isRunning = gameIsRunning;
+    refresh();
+  }
+
+  void updateGameIsFinished(bool gameIsFinished) {
+    state.currentGame.isFinished = gameIsFinished;
+    refresh();
+  }
+
+  void updateGameWon(bool gameWon) {
+    state.currentGame.gameWon = gameWon;
+    refresh();
+  }
+
+  fillBoardFromFirstCell(int value) {
+    List<List<int>> cellsToFill = state.currentGame.board.getSiblingFillableCells(0, 0, []);
+    final int progressBeforeMove = cellsToFill.length;
+
+    if (value == state.currentGame.board.getFirstCellValue()) {
+      return;
+    }
+
+    increaseMovesCount();
+
+    // Sort cells from the closest to the furthest, relatively to the top left corner
+    cellsToFill
+        .sort((a, b) => (pow(a[0], 2) + pow(a[1], 2)).compareTo(pow(b[0], 2) + pow(b[1], 2)));
+
+    const interval = Duration(milliseconds: 10);
+    int cellIndex = 0;
+    updateAnimationInProgress(true);
+    Timer.periodic(
+      interval,
+      (Timer timer) {
+        if (cellIndex < cellsToFill.length) {
+          updateCellValue(cellsToFill[cellIndex][1], cellsToFill[cellIndex][0], value);
+          cellIndex++;
+        } else {
+          timer.cancel();
+
+          int progressAfterMove =
+              state.currentGame.board.getSiblingFillableCells(0, 0, []).length;
+          int progressDelta = progressAfterMove - progressBeforeMove;
+          updateProgressDelta(progressDelta);
+          updateProgress(progressAfterMove);
+
+          updateAnimationInProgress(false);
+
+          if (state.currentGame.board.isBoardSolved()) {
+            updateGameWon(true);
+            updateGameIsFinished(true);
+          }
+        }
+      },
+    );
+  }
+
+  @override
+  GameState? fromJson(Map<String, dynamic> json) {
+    Game currentGame = json['currentGame'] as Game;
+
+    return GameState(
+      currentGame: currentGame,
+    );
+  }
+
+  @override
+  Map<String, dynamic>? toJson(GameState state) {
+    return <String, dynamic>{
+      'currentGame': state.currentGame.toJson(),
+    };
+  }
+}
diff --git a/lib/cubit/game_state.dart b/lib/cubit/game_state.dart
new file mode 100644
index 0000000..3fd161a
--- /dev/null
+++ b/lib/cubit/game_state.dart
@@ -0,0 +1,19 @@
+part of 'game_cubit.dart';
+
+@immutable
+class GameState extends Equatable {
+  const GameState({
+    required this.currentGame,
+  });
+
+  final Game currentGame;
+
+  @override
+  List<dynamic> get props => <dynamic>[
+        currentGame,
+      ];
+
+  Map<String, dynamic> get values => <String, dynamic>{
+        'currentGame': currentGame,
+      };
+}
diff --git a/lib/cubit/bottom_nav_cubit.dart b/lib/cubit/nav_cubit.dart
similarity index 51%
rename from lib/cubit/bottom_nav_cubit.dart
rename to lib/cubit/nav_cubit.dart
index f33dca3..a92b230 100644
--- a/lib/cubit/bottom_nav_cubit.dart
+++ b/lib/cubit/nav_cubit.dart
@@ -2,26 +2,32 @@ import 'package:hydrated_bloc/hydrated_bloc.dart';
 
 import 'package:colors/config/menu.dart';
 
-class BottomNavCubit extends HydratedCubit<int> {
-  BottomNavCubit() : super(0);
+class NavCubit extends HydratedCubit<int> {
+  NavCubit() : super(0);
 
   void updateIndex(int index) {
-    if (isIndexAllowed(index)) {
+    if (Menu.isIndexAllowed(index)) {
       emit(index);
     } else {
-      goToHomePage();
+      goToGamePage();
     }
   }
 
-  bool isIndexAllowed(int index) {
-    return (index >= 0) && (index < Menu.itemsCount);
+  void goToGamePage() {
+    emit(Menu.indexGame);
   }
 
-  void goToHomePage() => emit(0);
+  void goToSettingsPage() {
+    emit(Menu.indexSettings);
+  }
+
+  void goToAboutPage() {
+    emit(Menu.indexAbout);
+  }
 
   @override
   int fromJson(Map<String, dynamic> json) {
-    return 0;
+    return Menu.indexGame;
   }
 
   @override
diff --git a/lib/cubit/settings_game_cubit.dart b/lib/cubit/settings_game_cubit.dart
new file mode 100644
index 0000000..f70f2be
--- /dev/null
+++ b/lib/cubit/settings_game_cubit.dart
@@ -0,0 +1,84 @@
+import 'package:equatable/equatable.dart';
+import 'package:flutter/foundation.dart';
+import 'package:flutter/material.dart';
+import 'package:hydrated_bloc/hydrated_bloc.dart';
+
+import 'package:colors/config/default_game_settings.dart';
+import 'package:colors/models/settings_game.dart';
+
+part 'settings_game_state.dart';
+
+class GameSettingsCubit extends HydratedCubit<GameSettingsState> {
+  GameSettingsCubit() : super(GameSettingsState(settings: GameSettings.createDefault()));
+
+  void setValues({
+    String? difficultyLevel,
+    String? boardSize,
+    String? colorsCount,
+  }) {
+    emit(
+      GameSettingsState(
+        settings: GameSettings(
+          difficultyLevel: difficultyLevel ?? state.settings.difficultyLevel,
+          parameterSize: boardSize ?? state.settings.parameterSize,
+          parameterColorsCount: colorsCount ?? state.settings.parameterColorsCount,
+        ),
+      ),
+    );
+  }
+
+  String getParameterValue(String code) {
+    switch (code) {
+      case DefaultGameSettings.parameterCodeDifficultyLevel:
+        return GameSettings.getLevelValueFromUnsafe(state.settings.difficultyLevel);
+      case DefaultGameSettings.parameterCodeBoardSize:
+        return GameSettings.getSizeValueFromUnsafe(state.settings.parameterSize);
+      case DefaultGameSettings.parameterCodeColorsCount:
+        return GameSettings.getColorsValueFromUnsafe(state.settings.parameterColorsCount);
+    }
+    return '';
+  }
+
+  void setParameterValue(String code, String value) {
+    final String difficultyLevel = (code == DefaultGameSettings.parameterCodeDifficultyLevel)
+        ? value
+        : getParameterValue(DefaultGameSettings.parameterCodeDifficultyLevel);
+    final String boardSize = (code == DefaultGameSettings.parameterCodeBoardSize)
+        ? value
+        : getParameterValue(DefaultGameSettings.parameterCodeBoardSize);
+    final String colorsCount = (code == DefaultGameSettings.parameterCodeColorsCount)
+        ? value
+        : getParameterValue(DefaultGameSettings.parameterCodeColorsCount);
+
+    setValues(
+      difficultyLevel: difficultyLevel,
+      boardSize: boardSize,
+      colorsCount: colorsCount,
+    );
+  }
+
+  @override
+  GameSettingsState? fromJson(Map<String, dynamic> json) {
+    final String difficultyLevel =
+        json[DefaultGameSettings.parameterCodeDifficultyLevel] as String;
+    final String boardSize = json[DefaultGameSettings.parameterCodeBoardSize] as String;
+    final String colorsCount = json[DefaultGameSettings.parameterCodeColorsCount] as String;
+
+    return GameSettingsState(
+      settings: GameSettings(
+        difficultyLevel: difficultyLevel,
+        parameterSize: boardSize,
+        parameterColorsCount: colorsCount,
+      ),
+    );
+  }
+
+  @override
+  Map<String, dynamic>? toJson(GameSettingsState state) {
+    return <String, dynamic>{
+      DefaultGameSettings.parameterCodeDifficultyLevel: state.settings.difficultyLevel,
+      DefaultGameSettings.parameterCodeBoardSize: state.settings.parameterSize,
+      DefaultGameSettings.parameterCodeColorsCount: state.settings.parameterColorsCount,
+    };
+  }
+}
diff --git a/lib/cubit/settings_game_state.dart b/lib/cubit/settings_game_state.dart
new file mode 100644
index 0000000..b773dc6
--- /dev/null
+++ b/lib/cubit/settings_game_state.dart
@@ -0,0 +1,19 @@
+part of 'settings_game_cubit.dart';
+
+@immutable
+class GameSettingsState extends Equatable {
+  const GameSettingsState({
+    required this.settings,
+  });
+
+  final GameSettings settings;
+
+  @override
+  List<dynamic> get props => <dynamic>[
+        settings,
+      ];
+
+  Map<String, dynamic> get values => <String, dynamic>{
+        'settings': settings,
+      };
+}
diff --git a/lib/cubit/settings_global_cubit.dart b/lib/cubit/settings_global_cubit.dart
new file mode 100644
index 0000000..41d3f19
--- /dev/null
+++ b/lib/cubit/settings_global_cubit.dart
@@ -0,0 +1,61 @@
+import 'package:equatable/equatable.dart';
+import 'package:flutter/foundation.dart';
+import 'package:flutter/material.dart';
+import 'package:hydrated_bloc/hydrated_bloc.dart';
+
+import 'package:colors/config/default_global_settings.dart';
+import 'package:colors/models/settings_global.dart';
+
+part 'settings_global_state.dart';
+
+class GlobalSettingsCubit extends HydratedCubit<GlobalSettingsState> {
+  GlobalSettingsCubit() : super(GlobalSettingsState(settings: GlobalSettings.createDefault()));
+
+  void setValues({
+    String? skin,
+  }) {
+    emit(
+      GlobalSettingsState(
+        settings: GlobalSettings(
+          skin: skin ?? state.settings.skin,
+        ),
+      ),
+    );
+  }
+
+  String getParameterValue(String code) {
+    switch (code) {
+      case DefaultGlobalSettings.parameterCodeSkin:
+        return GlobalSettings.getSkinValueFromUnsafe(state.settings.skin);
+    }
+    return '';
+  }
+
+  void setParameterValue(String code, String value) {
+    final String skin = (code == DefaultGlobalSettings.parameterCodeSkin)
+        ? value
+        : getParameterValue(DefaultGlobalSettings.parameterCodeSkin);
+
+    setValues(
+      skin: skin,
+    );
+  }
+
+  @override
+  GlobalSettingsState? fromJson(Map<String, dynamic> json) {
+    final String skin = json[DefaultGlobalSettings.parameterCodeSkin] as String;
+
+    return GlobalSettingsState(
+      settings: GlobalSettings(
+        skin: skin,
+      ),
+    );
+  }
+
+  @override
+  Map<String, dynamic>? toJson(GlobalSettingsState state) {
+    return <String, dynamic>{
+      DefaultGlobalSettings.parameterCodeSkin: state.settings.skin,
+    };
+  }
+}
diff --git a/lib/cubit/settings_global_state.dart b/lib/cubit/settings_global_state.dart
new file mode 100644
index 0000000..4e4fbdf
--- /dev/null
+++ b/lib/cubit/settings_global_state.dart
@@ -0,0 +1,19 @@
+part of 'settings_global_cubit.dart';
+
+@immutable
+class GlobalSettingsState extends Equatable {
+  const GlobalSettingsState({
+    required this.settings,
+  });
+
+  final GlobalSettings settings;
+
+  @override
+  List<dynamic> get props => <dynamic>[
+        settings,
+      ];
+
+  Map<String, dynamic> get values => <String, dynamic>{
+        'settings': settings,
+      };
+}
diff --git a/lib/entities/cell.dart b/lib/entities/cell.dart
deleted file mode 100644
index 9617e4c..0000000
--- a/lib/entities/cell.dart
+++ /dev/null
@@ -1,37 +0,0 @@
-import 'package:flutter/material.dart';
-
-import 'package:colors/provider/data.dart';
-import 'package:colors/utils/board_utils.dart';
-
-class Cell {
-  int value;
-
-  Cell(
-    this.value,
-  );
-
-  Container interactiveWidget(Data myProvider, ColorScheme colorScheme) {
-    final String imageAsset = 'assets/skins/${myProvider.parameterSkin}_$value.png';
-
-    return Container(
-      margin: const EdgeInsets.all(2),
-      decoration: BoxDecoration(
-        border: Border.all(
-          color: colorScheme.onSurface,
-          width: 4,
-        ),
-      ),
-      child: GestureDetector(
-        child: Image(
-          image: AssetImage(imageAsset),
-          fit: BoxFit.fill,
-        ),
-        onTap: () {
-          if (!myProvider.animationInProgress && myProvider.getFirstCellValue() != value) {
-            BoardUtils.fillBoardFromFirstCell(myProvider, value);
-          }
-        },
-      ),
-    );
-  }
-}
diff --git a/lib/main.dart b/lib/main.dart
index a74262f..4ffcc22 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,22 +1,22 @@
 import 'dart:io';
 
 import 'package:easy_localization/easy_localization.dart';
-import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:flutter/material.dart';
 import 'package:hive/hive.dart';
 import 'package:hydrated_bloc/hydrated_bloc.dart';
-import 'package:overlay_support/overlay_support.dart';
 import 'package:path_provider/path_provider.dart';
-import 'package:provider/provider.dart';
 
 import 'package:colors/config/theme.dart';
-import 'package:colors/cubit/bottom_nav_cubit.dart';
+import 'package:colors/cubit/game_cubit.dart';
+import 'package:colors/cubit/nav_cubit.dart';
+import 'package:colors/cubit/settings_game_cubit.dart';
+import 'package:colors/cubit/settings_global_cubit.dart';
 import 'package:colors/cubit/theme_cubit.dart';
-import 'package:colors/provider/data.dart';
 import 'package:colors/ui/skeleton.dart';
 
 void main() async {
-  /// Initialize packages
+  // Initialize packages
   WidgetsFlutterBinding.ensureInitialized();
   await EasyLocalization.ensureInitialized();
   final Directory tmpDir = await getTemporaryDirectory();
@@ -46,34 +46,28 @@ class MyApp extends StatelessWidget {
   Widget build(BuildContext context) {
     return MultiBlocProvider(
       providers: [
-        BlocProvider<BottomNavCubit>(create: (context) => BottomNavCubit()),
+        BlocProvider<NavCubit>(create: (context) => NavCubit()),
         BlocProvider<ThemeCubit>(create: (context) => ThemeCubit()),
+        BlocProvider<GameCubit>(create: (context) => GameCubit()),
+        BlocProvider<GlobalSettingsCubit>(create: (context) => GlobalSettingsCubit()),
+        BlocProvider<GameSettingsCubit>(create: (context) => GameSettingsCubit()),
       ],
       child: BlocBuilder<ThemeCubit, ThemeModeState>(
         builder: (BuildContext context, ThemeModeState state) {
-          return ChangeNotifierProvider(
-            create: (BuildContext context) => Data(),
-            child: Consumer<Data>(
-              builder: (context, data, child) {
-                return OverlaySupport(
-                  child: MaterialApp(
-                    title: 'Minehunter',
-                    home: const SkeletonScreen(),
+          return MaterialApp(
+            title: 'Colors',
+            home: const SkeletonScreen(),
 
-                    // Theme stuff
-                    theme: lightTheme,
-                    darkTheme: darkTheme,
-                    themeMode: state.themeMode,
+            // Theme stuff
+            theme: lightTheme,
+            darkTheme: darkTheme,
+            themeMode: state.themeMode,
 
-                    // Localization stuff
-                    localizationsDelegates: context.localizationDelegates,
-                    supportedLocales: context.supportedLocales,
-                    locale: context.locale,
-                    debugShowCheckedModeBanner: false,
-                  ),
-                );
-              },
-            ),
+            // Localization stuff
+            localizationsDelegates: context.localizationDelegates,
+            supportedLocales: context.supportedLocales,
+            locale: context.locale,
+            debugShowCheckedModeBanner: false,
           );
         },
       ),
diff --git a/lib/models/board.dart b/lib/models/board.dart
new file mode 100644
index 0000000..5d6ccd9
--- /dev/null
+++ b/lib/models/board.dart
@@ -0,0 +1,144 @@
+import 'dart:math';
+
+import 'package:colors/models/cell.dart';
+import 'package:colors/models/settings_game.dart';
+import 'package:colors/models/types.dart';
+import 'package:colors/utils/tools.dart';
+
+class Board {
+  final BoardCells cells;
+
+  Board({
+    required this.cells,
+  });
+
+  factory Board.createNull() {
+    return Board(cells: []);
+  }
+
+  factory Board.createRandom(GameSettings gameSettings) {
+    final int boardSizeHorizontal = gameSettings.boardSize;
+    final int boardSizeVertical = gameSettings.boardSize;
+
+    final rand = Random();
+
+    BoardCells cells = [];
+    for (int rowIndex = 0; rowIndex < boardSizeVertical; rowIndex++) {
+      List<Cell> row = [];
+      for (int colIndex = 0; colIndex < boardSizeHorizontal; colIndex++) {
+        final int value = 1 + rand.nextInt(gameSettings.colorsCount);
+        row.add(Cell(value));
+      }
+      cells.add(row);
+    }
+
+    return Board(
+      cells: cells,
+    );
+  }
+
+  int getCellValue(int col, int row) {
+    return cells[row][col].value;
+  }
+
+  int getFirstCellValue() {
+    return cells[0][0].value;
+  }
+
+  List<List<int>> getSiblingFillableCells(
+    int row,
+    int col,
+    List<List<int>> siblingCells,
+  ) {
+    final int boardSize = cells.length;
+
+    if (siblingCells.isEmpty) {
+      siblingCells = [
+        [row, col]
+      ];
+    }
+
+    final int referenceValue = cells[row][col].value;
+
+    for (int deltaRow = -1; deltaRow <= 1; deltaRow++) {
+      for (int deltaCol = -1; deltaCol <= 1; deltaCol++) {
+        if (deltaCol == 0 || deltaRow == 0) {
+          final int candidateRow = row + deltaRow;
+          final int candidateCol = col + deltaCol;
+
+          if ((candidateRow >= 0 && candidateRow < boardSize) &&
+              (candidateCol >= 0 && candidateCol < boardSize)) {
+            if (cells[candidateRow][candidateCol].value == referenceValue) {
+              bool alreadyFound = false;
+              for (int index = 0; index < siblingCells.length; index++) {
+                if ((siblingCells[index][0] == candidateRow) &&
+                    (siblingCells[index][1] == candidateCol)) {
+                  alreadyFound = true;
+                }
+              }
+              if (!alreadyFound) {
+                siblingCells.add([candidateRow, candidateCol]);
+                siblingCells = getSiblingFillableCells(
+                  candidateRow,
+                  candidateCol,
+                  siblingCells,
+                );
+              }
+            }
+          }
+        }
+      }
+    }
+
+    return siblingCells;
+  }
+
+  // check grid contains only one color
+  bool isBoardSolved() {
+    final int firstCellValue = cells[0][0].value;
+    for (int row = 0; row < cells.length; row++) {
+      for (int col = 0; col < cells[row].length; col++) {
+        if (cells[row][col].value != firstCellValue) {
+          return false;
+        }
+      }
+    }
+
+    printlog('-> ok grid fully painted!');
+
+    return true;
+  }
+
+  void dump() {
+    String horizontalRule = '----';
+    for (int i = 0; i < cells[0].length; i++) {
+      horizontalRule += '-';
+    }
+
+    printlog('Board:');
+    printlog(horizontalRule);
+
+    for (int rowIndex = 0; rowIndex < cells.length; rowIndex++) {
+      String row = '| ';
+      for (int colIndex = 0; colIndex < cells[rowIndex].length; colIndex++) {
+        row += cells[rowIndex][colIndex].value.toString();
+      }
+      row += ' |';
+
+      printlog(row);
+    }
+
+    printlog(horizontalRule);
+  }
+
+  @override
+  String toString() {
+    return '$Board(${toJson()})';
+  }
+
+  Map<String, dynamic>? toJson() {
+    return <String, dynamic>{
+      'cells': cells.toString(),
+    };
+  }
+}
diff --git a/lib/models/cell.dart b/lib/models/cell.dart
new file mode 100644
index 0000000..54d6e3a
--- /dev/null
+++ b/lib/models/cell.dart
@@ -0,0 +1,18 @@
+class Cell {
+  Cell(
+    this.value,
+  );
+
+  int value;
+
+  @override
+  String toString() {
+    return '$Cell(${toJson()})';
+  }
+
+  Map<String, dynamic>? toJson() {
+    return <String, dynamic>{
+      'value': value,
+    };
+  }
+}
diff --git a/lib/models/game.dart b/lib/models/game.dart
new file mode 100644
index 0000000..28b61ea
--- /dev/null
+++ b/lib/models/game.dart
@@ -0,0 +1,114 @@
+import 'package:colors/config/default_game_settings.dart';
+import 'package:colors/models/board.dart';
+import 'package:colors/models/settings_game.dart';
+import 'package:colors/models/settings_global.dart';
+import 'package:colors/utils/tools.dart';
+
+class Game {
+  final Board board;
+  final GameSettings gameSettings;
+  final GlobalSettings globalSettings;
+  bool isRunning = false;
+  bool isFinished = false;
+  bool gameWon = false;
+
+  int maxMovesCount = 0;
+  int movesCount = 0;
+
+  int progress = 0;
+  int progressTotal = 0;
+  int progressDelta = 0;
+
+  bool animationInProgress = false;
+
+  Game({
+    required this.board,
+    required this.gameSettings,
+    required this.globalSettings,
+    this.isRunning = false,
+    this.isFinished = false,
+    this.gameWon = false,
+    this.maxMovesCount = 0,
+    this.movesCount = 0,
+    this.progress = 0,
+    this.progressTotal = 0,
+    this.progressDelta = 0,
+    this.animationInProgress = false,
+  });
+
+  factory Game.createNull() {
+    return Game(
+      board: Board.createNull(),
+      gameSettings: GameSettings.createDefault(),
+      globalSettings: GlobalSettings.createDefault(),
+    );
+  }
+
+  factory Game.createNew({
+    GameSettings? gameSettings,
+    GlobalSettings? globalSettings,
+  }) {
+    GameSettings newGameSettings = gameSettings ?? GameSettings.createDefault();
+    GlobalSettings newGlobalSettings = globalSettings ?? GlobalSettings.createDefault();
+
+    final int baseMaxMovesCount =
+        (30 * (newGameSettings.boardSize * newGameSettings.colorsCount) / (17 * 6)).round();
+    final int deltaMovesCountFromLevel =
+        DefaultGameSettings.getMovesCountLimitDeltaFromLevelCode(
+            newGameSettings.difficultyLevel);
+
+    return Game(
+      board: Board.createRandom(newGameSettings),
+      gameSettings: newGameSettings,
+      globalSettings: newGlobalSettings,
+      isRunning: true,
+      isFinished: false,
+      gameWon: false,
+      progress: 1,
+      progressTotal: newGameSettings.boardSize * newGameSettings.boardSize,
+      maxMovesCount: baseMaxMovesCount + deltaMovesCountFromLevel,
+    );
+  }
+
+  void dump() {
+    printlog('');
+    printlog('## Current game dump:');
+    printlog('');
+    gameSettings.dump();
+    globalSettings.dump();
+    printlog('');
+    board.dump();
+    printlog('');
+    printlog('Game: ');
+    printlog('  isRunning: $isRunning');
+    printlog('  isFinished: $isFinished');
+    printlog('  gameWon: $gameWon');
+    printlog('  movesCount: $movesCount');
+    printlog('  maxMovesCount: $maxMovesCount');
+    printlog('  progress: $progress');
+    printlog('  progressTotal: $progressTotal');
+    printlog('  progressDelta: $progressDelta');
+    printlog('');
+  }
+
+  @override
+  String toString() {
+    return '$Game(${toJson()})';
+  }
+
+  Map<String, dynamic>? toJson() {
+    return <String, dynamic>{
+      'board': board.toJson(),
+      'gameSettings': gameSettings.toJson(),
+      'globalSettings': globalSettings.toJson(),
+      'isRunning': isRunning,
+      'isFinished': isFinished,
+      'gameWon': gameWon,
+      'movesCount': movesCount,
+      'maxMovesCount': maxMovesCount,
+      'progress': progress,
+      'progressTotal': progressTotal,
+      'progressDelta': progressDelta,
+    };
+  }
+}
diff --git a/lib/models/settings_game.dart b/lib/models/settings_game.dart
new file mode 100644
index 0000000..b5227e8
--- /dev/null
+++ b/lib/models/settings_game.dart
@@ -0,0 +1,81 @@
+import 'package:colors/config/default_game_settings.dart';
+import 'package:colors/utils/tools.dart';
+
+class GameSettings {
+  String difficultyLevel;
+  String parameterSize;
+  String parameterColorsCount;
+
+  GameSettings({
+    required this.difficultyLevel,
+    required this.parameterSize,
+    required this.parameterColorsCount,
+  });
+
+  static String getLevelValueFromUnsafe(String level) {
+    if (DefaultGameSettings.allowedDifficultyLevelValues.contains(level)) {
+      return level;
+    }
+
+    return DefaultGameSettings.defaultDifficultyLevelValue;
+  }
+
+  static String getSizeValueFromUnsafe(String size) {
+    if (DefaultGameSettings.allowedBoardSizeValues.contains(size)) {
+      return size;
+    }
+
+    return DefaultGameSettings.defaultBoardSizeValue;
+  }
+
+  static String getColorsValueFromUnsafe(String colors) {
+    if (DefaultGameSettings.allowedColorsCountValues.contains(colors)) {
+      return colors;
+    }
+
+    return DefaultGameSettings.defaultColorsCountValue;
+  }
+
+  factory GameSettings.createDefault() {
+    return GameSettings(
+      difficultyLevel: DefaultGameSettings.defaultDifficultyLevelValue,
+      parameterSize: DefaultGameSettings.defaultBoardSizeValue,
+      parameterColorsCount: DefaultGameSettings.defaultColorsCountValue,
+    );
+  }
+
+  int getBoardSizeFromParameter(String parameterSize) {
+    const Map<String, int> values = {
+      DefaultGameSettings.boardSizeValueSmall: 6,
+      DefaultGameSettings.boardSizeValueMedium: 10,
+      DefaultGameSettings.boardSizeValueLarge: 14,
+      DefaultGameSettings.boardSizeValueExtra: 20,
+    };
+    return values[parameterSize] ??
+        getBoardSizeFromParameter(DefaultGameSettings.defaultBoardSizeValue);
+  }
+
+  int get boardSize => getBoardSizeFromParameter(parameterSize);
+  int get colorsCount => int.parse(parameterColorsCount);
+
+  void dump() {
+    printlog('$GameSettings:');
+    printlog('  ${DefaultGameSettings.parameterCodeDifficultyLevel}: $difficultyLevel');
+    printlog('  ${DefaultGameSettings.parameterCodeBoardSize}: $parameterSize');
+    printlog('  ${DefaultGameSettings.parameterCodeColorsCount}: $parameterColorsCount');
+    printlog('');
+  }
+
+  @override
+  String toString() {
+    return '$GameSettings(${toJson()})';
+  }
+
+  Map<String, dynamic>? toJson() {
+    return <String, dynamic>{
+      DefaultGameSettings.parameterCodeDifficultyLevel: difficultyLevel,
+      DefaultGameSettings.parameterCodeBoardSize: parameterSize,
+      DefaultGameSettings.parameterCodeColorsCount: parameterColorsCount,
+    };
+  }
+}
diff --git a/lib/models/settings_global.dart b/lib/models/settings_global.dart
new file mode 100644
index 0000000..09994f4
--- /dev/null
+++ b/lib/models/settings_global.dart
@@ -0,0 +1,41 @@
+import 'package:colors/config/default_global_settings.dart';
+import 'package:colors/utils/tools.dart';
+
+class GlobalSettings {
+  String skin;
+
+  GlobalSettings({
+    required this.skin,
+  });
+
+  static String getSkinValueFromUnsafe(String skin) {
+    if (DefaultGlobalSettings.allowedSkinValues.contains(skin)) {
+      return skin;
+    }
+
+    return DefaultGlobalSettings.defaultSkinValue;
+  }
+
+  factory GlobalSettings.createDefault() {
+    return GlobalSettings(
+      skin: DefaultGlobalSettings.defaultSkinValue,
+    );
+  }
+
+  void dump() {
+    printlog('$GlobalSettings: ');
+    printlog('  ${DefaultGlobalSettings.parameterCodeSkin}: $skin');
+    printlog('');
+  }
+
+  @override
+  String toString() {
+    return '$GlobalSettings(${toJson()})';
+  }
+
+  Map<String, dynamic>? toJson() {
+    return <String, dynamic>{
+      DefaultGlobalSettings.parameterCodeSkin: skin,
+    };
+  }
+}
diff --git a/lib/models/types.dart b/lib/models/types.dart
new file mode 100644
index 0000000..339bfe6
--- /dev/null
+++ b/lib/models/types.dart
@@ -0,0 +1,3 @@
+import 'package:colors/models/cell.dart';
+
+typedef BoardCells = List<List<Cell>>;
diff --git a/lib/provider/data.dart b/lib/provider/data.dart
deleted file mode 100644
index dfe3136..0000000
--- a/lib/provider/data.dart
+++ /dev/null
@@ -1,340 +0,0 @@
-import 'package:flutter/foundation.dart';
-import 'package:shared_preferences/shared_preferences.dart';
-
-import 'package:colors/entities/cell.dart';
-
-typedef Board = List<List<Cell>>;
-
-class Data extends ChangeNotifier {
-  // Configuration available parameters
-  final List<String> _availableParameters = ['level', 'size', 'colors', 'skin'];
-  List<String> get availableParameters => _availableParameters;
-
-  // Configuration available values
-  final List<String> _availableLevelValues = ['easy', 'medium', 'hard', 'nightmare'];
-  final List<String> _availableSizeValues = ['small', 'medium', 'large', 'extra'];
-  final List<String> _availableColorsValues = ['5', '6', '7', '8'];
-  final List<String> _availableSkinValues = ['default'];
-
-  List<String> get availableLevelValues => _availableLevelValues;
-  List<String> get availableSizeValues => _availableSizeValues;
-  List<String> get availableColorsValues => _availableColorsValues;
-  List<String> get availableSkinValues => _availableSkinValues;
-
-  // Application default configuration
-  String _parameterLevel = '';
-  final String _parameterLevelDefault = 'medium';
-  String _parameterSize = '';
-  final String _parameterSizeDefault = 'medium';
-  String _parameterColors = '';
-  final String _parameterColorsDefault = '6';
-  String _parameterSkin = '';
-  final String _parameterSkinDefault = 'default';
-
-  // Application current configuration
-  String get parameterLevel => _parameterLevel;
-  String get parameterSize => _parameterSize;
-  String get parameterColors => _parameterColors;
-  String get parameterSkin => _parameterSkin;
-
-  // Game data
-  bool _gameIsRunning = false;
-  bool _animationInProgress = false;
-  bool _gameWon = false;
-  int _boardSize = 0;
-  int _colorsCount = 0;
-  int _movesCount = 0;
-  int _maxMovesCount = 0;
-  Board _board = [];
-
-  int _progress = 0;
-  int _progressTotal = 0;
-  int _progressDelta = 0;
-
-  bool isParameterValueAllowed(String parameterValue, List<String> parametersAllowedValues) {
-    bool found = false;
-    for (String item in parametersAllowedValues) {
-      if (item.contains(parameterValue)) {
-        found = true;
-      }
-    }
-    return found;
-  }
-
-  void updateParameterLevel(String parameterLevel) {
-    if (isParameterValueAllowed(parameterLevel, _availableLevelValues)) {
-      _parameterLevel = parameterLevel;
-    } else {
-      _parameterLevel = _parameterLevelDefault;
-    }
-    notifyListeners();
-  }
-
-  void updateParameterSize(String parameterSize) {
-    if (isParameterValueAllowed(parameterSize, _availableSizeValues)) {
-      _parameterSize = parameterSize;
-    } else {
-      _parameterSize = _parameterSizeDefault;
-    }
-    updateBoardSize(getBoardSizeFromParameter(parameterSize));
-    notifyListeners();
-  }
-
-  void updateParameterColors(String parameterColors) {
-    if (isParameterValueAllowed(parameterColors, _availableColorsValues)) {
-      _parameterColors = parameterColors;
-    } else {
-      _parameterColors = _parameterColorsDefault;
-    }
-    updateColorsCount(getColorsCountFromParameter(parameterColors));
-    notifyListeners();
-  }
-
-  void updateParameterSkin(String parameterSkin) {
-    if (isParameterValueAllowed(parameterSkin, _availableSkinValues)) {
-      _parameterSkin = parameterSkin;
-    } else {
-      _parameterSkin = _parameterSkinDefault;
-    }
-    notifyListeners();
-  }
-
-  String getParameterValue(String parameterCode) {
-    switch (parameterCode) {
-      case 'level':
-        {
-          return _parameterLevel;
-        }
-      case 'size':
-        {
-          return _parameterSize;
-        }
-      case 'colors':
-        {
-          return _parameterColors;
-        }
-      case 'skin':
-        {
-          return _parameterSkin;
-        }
-    }
-    return '';
-  }
-
-  List<String> getParameterAvailableValues(String parameterCode) {
-    switch (parameterCode) {
-      case 'level':
-        {
-          return _availableLevelValues;
-        }
-      case 'size':
-        {
-          return _availableSizeValues;
-        }
-      case 'colors':
-        {
-          return _availableColorsValues;
-        }
-      case 'skin':
-        {
-          return _availableSkinValues;
-        }
-    }
-    return [];
-  }
-
-  void setParameterValue(String parameterCode, String parameterValue) async {
-    switch (parameterCode) {
-      case 'level':
-        {
-          updateParameterLevel(parameterValue);
-        }
-        break;
-      case 'size':
-        {
-          updateParameterSize(parameterValue);
-        }
-        break;
-      case 'colors':
-        {
-          updateParameterColors(parameterValue);
-        }
-        break;
-      case 'skin':
-        {
-          updateParameterSkin(parameterValue);
-        }
-        break;
-    }
-    final prefs = await SharedPreferences.getInstance();
-    prefs.setString(parameterCode, parameterValue);
-  }
-
-  void initParametersValues() async {
-    final prefs = await SharedPreferences.getInstance();
-    setParameterValue('level', prefs.getString('level') ?? _parameterLevelDefault);
-    setParameterValue('size', prefs.getString('size') ?? _parameterSizeDefault);
-    setParameterValue('colors', prefs.getString('colors') ?? _parameterColorsDefault);
-    setParameterValue('skin', prefs.getString('skin') ?? _parameterSkinDefault);
-  }
-
-  int getBoardSizeFromParameter(String parameterSize) {
-    switch (parameterSize) {
-      case 'small':
-        {
-          return 6;
-        }
-      case 'medium':
-        {
-          return 10;
-        }
-      case 'large':
-        {
-          return 14;
-        }
-      case 'extra':
-        {
-          return 20;
-        }
-    }
-    return getBoardSizeFromParameter(_parameterSizeDefault);
-  }
-
-  int getColorsCountFromParameter(String parameterColors) {
-    switch (parameterColors) {
-      case '5':
-        {
-          return 5;
-        }
-      case '6':
-        {
-          return 6;
-        }
-      case '7':
-        {
-          return 7;
-        }
-      case '8':
-        {
-          return 8;
-        }
-    }
-    return getColorsCountFromParameter(_parameterColorsDefault);
-  }
-
-  int getMovesCountLimitDeltaFromLevelParameter(String parameterLevel) {
-    switch (parameterLevel) {
-      case 'easy':
-        {
-          return 5;
-        }
-      case 'medium':
-        {
-          return 3;
-        }
-      case 'hard':
-        {
-          return 1;
-        }
-      case 'nightmare':
-        {
-          return -1;
-        }
-    }
-    return getMovesCountLimitDeltaFromLevelParameter(_parameterLevelDefault);
-  }
-
-  int get boardSize => _boardSize;
-  void updateBoardSize(int boardSize) {
-    _boardSize = boardSize;
-    _progressTotal = boardSize * boardSize;
-  }
-
-  int get colorsCount => _colorsCount;
-  void updateColorsCount(int colorsCount) {
-    _colorsCount = colorsCount;
-  }
-
-  Board get board => _board;
-  void updateBoard(Board board) {
-    _board = board;
-    notifyListeners();
-  }
-
-  updateCellValue(int col, int row, int value) {
-    _board[row][col].value = value;
-    notifyListeners();
-  }
-
-  int getFirstCellValue() {
-    return _board[0][0].value;
-  }
-
-  int getCellValue(int col, int row) {
-    return _board[row][col].value;
-  }
-
-  int get movesCount => _movesCount;
-  void updateMovesCount(int movesCount) {
-    _movesCount = movesCount;
-    notifyListeners();
-  }
-
-  void incrementMovesCount() {
-    updateMovesCount(movesCount + 1);
-  }
-
-  int get maxMovesCount => _maxMovesCount;
-  void updateMaxMovesCount(int maxMovesCount) {
-    _maxMovesCount = maxMovesCount;
-  }
-
-  int get progress => _progress;
-  int get progressTotal => _progressTotal;
-  int get progressDelta => _progressDelta;
-  void updateProgress(int progress) {
-    _progress = progress;
-    notifyListeners();
-  }
-
-  void updateProgressTotal(int progressTotal) {
-    _progressTotal = progressTotal;
-    notifyListeners();
-  }
-
-  void updateProgressDelta(int progressDelta) {
-    _progressDelta = progressDelta;
-    notifyListeners();
-  }
-
-  bool get gameIsRunning => _gameIsRunning;
-  void updateGameIsRunning(bool gameIsRunning) {
-    _gameIsRunning = gameIsRunning;
-    notifyListeners();
-  }
-
-  bool isGameFinished() {
-    return _gameWon;
-  }
-
-  bool get gameWon => _gameWon;
-  void updateGameWon(bool gameWon) {
-    _gameWon = gameWon;
-    notifyListeners();
-  }
-
-  bool get animationInProgress => _animationInProgress;
-  void updateAnimationInProgress(bool animationInProgress) {
-    _animationInProgress = animationInProgress;
-    notifyListeners();
-  }
-
-  void resetGame() {
-    _gameIsRunning = false;
-    _gameWon = false;
-    _movesCount = 0;
-    _maxMovesCount = 0;
-    _progress = 0;
-    notifyListeners();
-  }
-}
diff --git a/lib/ui/layout/game.dart b/lib/ui/layout/game.dart
deleted file mode 100644
index a91ceaf..0000000
--- a/lib/ui/layout/game.dart
+++ /dev/null
@@ -1,42 +0,0 @@
-import 'package:flutter/material.dart';
-
-import 'package:colors/ui/layout/tileset.dart';
-import 'package:colors/provider/data.dart';
-import 'package:colors/ui/widgets/game/indicator_top.dart';
-import 'package:colors/ui/widgets/game/message_game_end.dart';
-import 'package:colors/ui/widgets/game/select_color_bar.dart';
-
-class Game extends StatelessWidget {
-  const Game({
-    super.key,
-    required this.myProvider,
-    required this.boardWidth,
-  });
-
-  final Data myProvider;
-  final double boardWidth;
-
-  @override
-  Widget build(BuildContext context) {
-    final bool gameIsFinished = myProvider.isGameFinished();
-
-    return Column(
-      mainAxisAlignment: MainAxisAlignment.start,
-      crossAxisAlignment: CrossAxisAlignment.center,
-      children: [
-        const SizedBox(height: 8),
-        TopIndicator(myProvider: myProvider),
-        const SizedBox(height: 2),
-        Expanded(
-          child: Tileset(myProvider: myProvider, boardWidth: boardWidth),
-        ),
-        const SizedBox(height: 2),
-        Container(
-          child: gameIsFinished
-              ? EndGameMessage(myProvider: myProvider)
-              : SelectColorBar(myProvider: myProvider),
-        ),
-      ],
-    );
-  }
-}
diff --git a/lib/ui/layout/parameters.dart b/lib/ui/layout/parameters.dart
deleted file mode 100644
index 34a9a42..0000000
--- a/lib/ui/layout/parameters.dart
+++ /dev/null
@@ -1,119 +0,0 @@
-import 'package:flutter/material.dart';
-
-import 'package:colors/ui/widgets/home/button_game_start_new.dart';
-import 'package:colors/provider/data.dart';
-
-class Parameters extends StatelessWidget {
-  const Parameters({super.key, required this.myProvider});
-
-  final Data myProvider;
-
-  static const double separatorHeight = 2.0;
-  static const double blockMargin = 3.0;
-  static const double blockPadding = 2.0;
-  static const Color buttonBackgroundColor = Colors.white;
-  static const Color buttonBorderColorActive = Colors.blue;
-  static const Color buttonBorderColorInactive = Colors.white;
-  static const double buttonBorderWidth = 10.0;
-  static const double buttonBorderRadius = 8.0;
-  static const double buttonPadding = 0.0;
-  static const double buttonMargin = 0.0;
-
-  @override
-  Widget build(BuildContext context) {
-    List<Widget> lines = [];
-
-    final List<String> parameters = myProvider.availableParameters;
-    for (int index = 0; index < parameters.length; index++) {
-      lines.add(buildParameterSelector(parameters[index]));
-      lines.add(const SizedBox(height: separatorHeight));
-    }
-
-    return Column(
-      mainAxisAlignment: MainAxisAlignment.start,
-      crossAxisAlignment: CrossAxisAlignment.center,
-      children: [
-        const SizedBox(height: separatorHeight),
-        Expanded(
-          child: Column(
-            mainAxisSize: MainAxisSize.min,
-            mainAxisAlignment: MainAxisAlignment.center,
-            children: lines,
-          ),
-        ),
-        const SizedBox(height: separatorHeight),
-        StartNewGameButton(myProvider: myProvider),
-      ],
-    );
-  }
-
-  static Image buildImageWidget(String imageAssetCode) {
-    return Image(
-      image: AssetImage('assets/icons/$imageAssetCode.png'),
-      fit: BoxFit.fill,
-    );
-  }
-
-  static Container buildImageContainerWidget(String imageAssetCode) {
-    return Container(
-      child: buildImageWidget(imageAssetCode),
-    );
-  }
-
-  static Column buildDecorationImageWidget() {
-    return Column(
-      children: [
-        TextButton(
-          child: buildImageContainerWidget('game_win'),
-          onPressed: () {},
-        ),
-      ],
-    );
-  }
-
-  Widget buildParameterSelector(String parameterCode) {
-    final List<String> availableValues = myProvider.getParameterAvailableValues(parameterCode);
-
-    if (availableValues.length == 1) {
-      return const SizedBox(height: 0.0);
-    }
-
-    return Table(
-      defaultColumnWidth: const IntrinsicColumnWidth(),
-      children: [
-        TableRow(
-          children: [
-            for (int index = 0; index < availableValues.length; index++)
-              Column(
-                children: [buildParameterButton(parameterCode, availableValues[index])],
-              ),
-          ],
-        ),
-      ],
-    );
-  }
-
-  Widget buildParameterButton(String parameterCode, String parameterValue) {
-    final String currentValue = myProvider.getParameterValue(parameterCode).toString();
-
-    final bool isActive = (parameterValue == currentValue);
-    final String imageAsset = '${parameterCode}_$parameterValue';
-
-    return TextButton(
-      child: Container(
-        margin: const EdgeInsets.all(buttonMargin),
-        padding: const EdgeInsets.all(buttonPadding),
-        decoration: BoxDecoration(
-          color: buttonBackgroundColor,
-          borderRadius: BorderRadius.circular(buttonBorderRadius),
-          border: Border.all(
-            color: isActive ? buttonBorderColorActive : buttonBorderColorInactive,
-            width: buttonBorderWidth,
-          ),
-        ),
-        child: buildImageWidget(imageAsset),
-      ),
-      onPressed: () => myProvider.setParameterValue(parameterCode, parameterValue),
-    );
-  }
-}
diff --git a/lib/ui/layout/tileset.dart b/lib/ui/layout/tileset.dart
deleted file mode 100644
index f18470d..0000000
--- a/lib/ui/layout/tileset.dart
+++ /dev/null
@@ -1,50 +0,0 @@
-import 'package:flutter/material.dart';
-
-import 'package:colors/ui/painters/board_painter.dart';
-import 'package:colors/provider/data.dart';
-import 'package:colors/utils/board_utils.dart';
-
-class Tileset extends StatelessWidget {
-  const Tileset({
-    super.key,
-    required this.myProvider,
-    required this.boardWidth,
-  });
-
-  final Data myProvider;
-  final double boardWidth;
-
-  @override
-  Widget build(BuildContext context) {
-    return Container(
-      margin: const EdgeInsets.all(4),
-      padding: const EdgeInsets.all(4),
-      child: Column(
-        children: [
-          Center(
-            child: GestureDetector(
-              onTapUp: (details) {
-                final double xTap = details.localPosition.dx;
-                final double yTap = details.localPosition.dy;
-                final int boardSize = myProvider.boardSize;
-                final int col = xTap ~/ (boardWidth / boardSize);
-                final int row = yTap ~/ (boardWidth / boardSize);
-                final int cellValue = myProvider.getCellValue(col, row);
-                BoardUtils.fillBoardFromFirstCell(myProvider, cellValue);
-              },
-              child: CustomPaint(
-                size: Size(boardWidth, boardWidth),
-                willChange: false,
-                painter: BoardPainter(
-                  myProvider: myProvider,
-                  colorScheme: Theme.of(context).colorScheme,
-                ),
-                isComplex: true,
-              ),
-            ),
-          ),
-        ],
-      ),
-    );
-  }
-}
diff --git a/lib/ui/painters/board_painter.dart b/lib/ui/painters/board_painter.dart
index d1ec5b2..42bb2a2 100644
--- a/lib/ui/painters/board_painter.dart
+++ b/lib/ui/painters/board_painter.dart
@@ -1,19 +1,23 @@
 import 'package:flutter/material.dart';
 
-import 'package:colors/entities/cell.dart';
+import 'package:colors/models/cell.dart';
+import 'package:colors/models/game.dart';
+import 'package:colors/models/types.dart';
 import 'package:colors/utils/color_theme.dart';
-import 'package:colors/provider/data.dart';
 
 class BoardPainter extends CustomPainter {
-  const BoardPainter({required this.myProvider, required this.colorScheme});
+  const BoardPainter({
+    required this.game,
+    required this.colorScheme,
+  });
 
-  final Data myProvider;
+  final Game game;
   final ColorScheme colorScheme;
 
   @override
   void paint(Canvas canvas, Size size) {
-    final int boardSize = myProvider.boardSize;
-    final Board board = myProvider.board;
+    final int boardSize = game.gameSettings.boardSize;
+    final BoardCells cells = game.board.cells;
     final double cellSize = size.width / boardSize;
 
     // background
@@ -22,9 +26,9 @@ class BoardPainter extends CustomPainter {
       for (var col = 0; col < boardSize; col++) {
         final double x = cellSize * col;
 
-        final Cell cell = board[row][col];
+        final Cell cell = cells[row][col];
         final int cellValue = cell.value;
-        final int colorCode = ColorTheme.getColorCode(myProvider.parameterSkin, cellValue);
+        final int colorCode = ColorTheme.getColorCode(game.globalSettings.skin, cellValue);
 
         final cellPaintBackground = Paint();
         cellPaintBackground.color = Color(colorCode);
@@ -40,7 +44,7 @@ class BoardPainter extends CustomPainter {
     // borders
     const double borderSize = 2;
     final cellPaintBorder = Paint();
-    cellPaintBorder.color = colorScheme.onSurface;
+    cellPaintBorder.color = colorScheme.onBackground;
     cellPaintBorder.strokeWidth = borderSize;
     cellPaintBorder.strokeCap = StrokeCap.round;
 
@@ -49,27 +53,27 @@ class BoardPainter extends CustomPainter {
       for (var col = 0; col < boardSize; col++) {
         final double x = cellSize * col;
 
-        final Cell cell = board[row][col];
+        final Cell cell = cells[row][col];
         final int cellValue = cell.value;
 
-        if ((row == 0) || (row > 1 && cellValue != myProvider.getCellValue(col, row - 1))) {
+        if ((row == 0) || (row > 1 && cellValue != game.board.getCellValue(col, row - 1))) {
           final Offset borderStart = Offset(x, y);
           final Offset borderStop = Offset(x + cellSize, y);
           canvas.drawLine(borderStart, borderStop, cellPaintBorder);
         }
         if ((row == boardSize - 1) ||
-            ((row + 1) < boardSize && cellValue != myProvider.getCellValue(col, row + 1))) {
+            ((row + 1) < boardSize && cellValue != game.board.getCellValue(col, row + 1))) {
           final Offset borderStart = Offset(x, y + cellSize);
           final Offset borderStop = Offset(x + cellSize, y + cellSize);
           canvas.drawLine(borderStart, borderStop, cellPaintBorder);
         }
-        if ((col == 0) || (col > 1 && cellValue != myProvider.getCellValue(col - 1, row))) {
+        if ((col == 0) || (col > 1 && cellValue != game.board.getCellValue(col - 1, row))) {
           final Offset borderStart = Offset(x, y);
           final Offset borderStop = Offset(x, y + cellSize);
           canvas.drawLine(borderStart, borderStop, cellPaintBorder);
         }
         if ((col == boardSize - 1) ||
-            ((col + 1) < boardSize && cellValue != myProvider.getCellValue(col + 1, row))) {
+            ((col + 1) < boardSize && cellValue != game.board.getCellValue(col + 1, row))) {
           final Offset borderStart = Offset(x + cellSize, y);
           final Offset borderStop = Offset(x + cellSize, y + cellSize);
           canvas.drawLine(borderStart, borderStop, cellPaintBorder);
diff --git a/lib/ui/painters/parameter_painter.dart b/lib/ui/painters/parameter_painter.dart
new file mode 100644
index 0000000..fb216ed
--- /dev/null
+++ b/lib/ui/painters/parameter_painter.dart
@@ -0,0 +1,372 @@
+import 'dart:math';
+
+import 'package:flutter/material.dart';
+
+import 'package:colors/config/default_game_settings.dart';
+import 'package:colors/config/default_global_settings.dart';
+import 'package:colors/models/settings_game.dart';
+import 'package:colors/models/settings_global.dart';
+import 'package:colors/utils/color_extensions.dart';
+import 'package:colors/utils/color_theme.dart';
+import 'package:colors/utils/tools.dart';
+
+class ParameterPainter extends CustomPainter {
+  const ParameterPainter({
+    required this.code,
+    required this.value,
+    required this.isSelected,
+    required this.gameSettings,
+    required this.globalSettings,
+  });
+
+  final String code;
+  final String value;
+  final bool isSelected;
+  final GameSettings gameSettings;
+  final GlobalSettings globalSettings;
+
+  @override
+  void paint(Canvas canvas, Size size) {
+    // force square
+    final double canvasSize = min(size.width, size.height);
+
+    const Color borderColorEnabled = Colors.blue;
+    const Color borderColorDisabled = Colors.white;
+
+    // "enabled/disabled" border
+    final paint = Paint();
+    paint.style = PaintingStyle.stroke;
+    paint.color = isSelected ? borderColorEnabled : borderColorDisabled;
+    paint.strokeJoin = StrokeJoin.round;
+    paint.strokeWidth = 20 / 100 * canvasSize;
+    canvas.drawRect(
+        Rect.fromPoints(const Offset(0, 0), Offset(canvasSize, canvasSize)), paint);
+
+    // content
+    switch (code) {
+      case DefaultGameSettings.parameterCodeDifficultyLevel:
+        paintDifficultyLevelParameterItem(value, canvas, canvasSize);
+        break;
+      case DefaultGameSettings.parameterCodeBoardSize:
+        paintBoardSizeParameterItem(value, canvas, canvasSize);
+        break;
+      case DefaultGameSettings.parameterCodeColorsCount:
+        paintColorsCountParameterItem(value, canvas, canvasSize);
+        break;
+      case DefaultGlobalSettings.parameterCodeSkin:
+        paintUnknownParameterItem(value, canvas, canvasSize);
+        break;
+      default:
+        printlog('Unknown parameter: $code/$value');
+        paintUnknownParameterItem(value, canvas, canvasSize);
+    }
+  }
+
+  @override
+  bool shouldRepaint(CustomPainter oldDelegate) {
+    return false;
+  }
+
+  // "unknown" parameter -> simple block with text
+  void paintUnknownParameterItem(
+    final String value,
+    final Canvas canvas,
+    final double size,
+  ) {
+    final paint = Paint();
+    paint.strokeJoin = StrokeJoin.round;
+    paint.strokeWidth = 3 / 100 * size;
+
+    paint.color = Colors.grey;
+    paint.style = PaintingStyle.fill;
+    canvas.drawRect(Rect.fromPoints(const Offset(0, 0), Offset(size, size)), paint);
+
+    final textSpan = TextSpan(
+      text: '?\n$value',
+      style: const TextStyle(
+        color: Colors.black,
+        fontSize: 18,
+        fontWeight: FontWeight.bold,
+      ),
+    );
+    final textPainter = TextPainter(
+      text: textSpan,
+      textDirection: TextDirection.ltr,
+    );
+    textPainter.layout();
+    textPainter.paint(
+      canvas,
+      Offset(
+        (size - textPainter.width) * 0.5,
+        (size - textPainter.height) * 0.5,
+      ),
+    );
+  }
+
+  void paintDifficultyLevelParameterItem(
+    final String value,
+    final Canvas canvas,
+    final double size,
+  ) {
+    Color backgroundColor = Colors.grey;
+
+    final List<dynamic> stars = [];
+
+    switch (value) {
+      case DefaultGameSettings.difficultyLevelValueEasy:
+        backgroundColor = Colors.green;
+        stars.add([0.5, 0.5]);
+        break;
+      case DefaultGameSettings.difficultyLevelValueMedium:
+        backgroundColor = Colors.orange;
+        stars.add([0.3, 0.5]);
+        stars.add([0.7, 0.5]);
+        break;
+      case DefaultGameSettings.difficultyLevelValueHard:
+        backgroundColor = Colors.red;
+        stars.add([0.3, 0.3]);
+        stars.add([0.7, 0.3]);
+        stars.add([0.5, 0.7]);
+        break;
+      case DefaultGameSettings.difficultyLevelValueNightmare:
+        backgroundColor = Colors.purple;
+        stars.add([0.3, 0.3]);
+        stars.add([0.7, 0.3]);
+        stars.add([0.3, 0.7]);
+        stars.add([0.7, 0.7]);
+        break;
+      default:
+        printlog('Wrong value for level parameter value: $value');
+    }
+
+    final paint = Paint();
+    paint.strokeJoin = StrokeJoin.round;
+    paint.strokeWidth = 3 / 100 * size;
+
+    // Colored background
+    paint.color = backgroundColor;
+    paint.style = PaintingStyle.fill;
+    canvas.drawRect(Rect.fromPoints(const Offset(0, 0), Offset(size, size)), paint);
+
+    // Stars
+    final textSpan = TextSpan(
+      text: '⭐',
+      style: TextStyle(
+        color: Colors.black,
+        fontSize: size / 3,
+        fontWeight: FontWeight.bold,
+      ),
+    );
+    final textPainter = TextPainter(
+      text: textSpan,
+      textDirection: TextDirection.ltr,
+    );
+    textPainter.layout();
+
+    for (var center in stars) {
+      textPainter.paint(
+        canvas,
+        Offset(
+          size * center[0] - textPainter.width * 0.5,
+          size * center[1] - textPainter.height * 0.5,
+        ),
+      );
+    }
+  }
+
+  void paintBoardSizeParameterItem(
+    final String value,
+    final Canvas canvas,
+    final double size,
+  ) {
+    Color backgroundColor = Colors.grey;
+    int gridWidth = 1;
+
+    switch (value) {
+      case DefaultGameSettings.boardSizeValueSmall:
+        backgroundColor = Colors.green;
+        gridWidth = 2;
+        break;
+      case DefaultGameSettings.boardSizeValueMedium:
+        backgroundColor = Colors.orange;
+        gridWidth = 3;
+        break;
+      case DefaultGameSettings.boardSizeValueLarge:
+        backgroundColor = Colors.red;
+        gridWidth = 4;
+        break;
+      case DefaultGameSettings.boardSizeValueExtra:
+        backgroundColor = Colors.purple;
+        gridWidth = 5;
+        break;
+      default:
+        printlog('Wrong value for boardSize parameter value: $value');
+    }
+
+    final paint = Paint();
+    paint.strokeJoin = StrokeJoin.round;
+    paint.strokeWidth = 3 / 100 * size;
+
+    // Colored background
+    paint.color = backgroundColor;
+    paint.style = PaintingStyle.fill;
+    canvas.drawRect(Rect.fromPoints(const Offset(0, 0), Offset(size, size)), paint);
+
+    // Mini grid
+    final squareBackgroundColor = Colors.grey.shade200;
+    final squareBorderColor = Colors.grey.shade800;
+
+    final double cellSize = size / 7;
+    final double origin = (size - gridWidth * cellSize) / 2;
+
+    for (int row = 0; row < gridWidth; row++) {
+      for (int col = 0; col < gridWidth; col++) {
+        final Offset topLeft = Offset(origin + col * cellSize, origin + row * cellSize);
+        final Offset bottomRight = topLeft + Offset(cellSize, cellSize);
+
+        paint.color = squareBackgroundColor;
+        paint.style = PaintingStyle.fill;
+        canvas.drawRect(Rect.fromPoints(topLeft, bottomRight), paint);
+
+        paint.color = squareBorderColor;
+        paint.style = PaintingStyle.stroke;
+        canvas.drawRect(Rect.fromPoints(topLeft, bottomRight), paint);
+      }
+    }
+  }
+
+  void paintColorsCountParameterItem(
+    final String value,
+    final Canvas canvas,
+    final double size,
+  ) {
+    Color backgroundColor = Colors.grey;
+
+    switch (value) {
+      case DefaultGameSettings.colorsCountValueLow:
+        backgroundColor = Colors.green;
+        break;
+      case DefaultGameSettings.colorsCountValueMedium:
+        backgroundColor = Colors.orange;
+        break;
+      case DefaultGameSettings.colorsCountValueHigh:
+        backgroundColor = Colors.red;
+        break;
+      case DefaultGameSettings.colorsCountValueVeryHigh:
+        backgroundColor = Colors.purple;
+        break;
+      default:
+        printlog('Wrong value for colorsCount parameter value: $value');
+    }
+
+    final paint = Paint();
+    paint.strokeJoin = StrokeJoin.round;
+    paint.strokeWidth = 3 / 100 * size;
+
+    // Colored background
+    paint.color = backgroundColor;
+    paint.style = PaintingStyle.fill;
+    canvas.drawRect(Rect.fromPoints(const Offset(0, 0), Offset(size, size)), paint);
+
+    // Colors preview
+    const List<Offset> positions = [
+      Offset(0, 0),
+      Offset(1, 0),
+      Offset(2, 0),
+      Offset(2, 1),
+      Offset(2, 2),
+      Offset(1, 2),
+      Offset(0, 2),
+      Offset(0, 1),
+    ];
+
+    const skin = DefaultGlobalSettings.defaultSkinValue;
+
+    final double padding = 4 / 100 * size;
+    final double margin = 3 / 100 * size;
+    final double width = ((size - 2 * padding) / 3) - 2 * margin;
+
+    final int maxValue = int.parse(value);
+    for (int colorIndex = 0; colorIndex < maxValue; colorIndex++) {
+      final Offset position = positions[colorIndex];
+
+      final Offset topLeft = Offset(padding + margin + position.dx * (width + 2 * margin),
+          padding + margin + position.dy * (width + 2 * margin));
+
+      final Offset bottomRight = topLeft + Offset(width, width);
+
+      final squareColor = Color(ColorTheme.getColorCode(skin, colorIndex + 1));
+      paint.color = squareColor;
+      paint.style = PaintingStyle.fill;
+      canvas.drawRect(Rect.fromPoints(topLeft, bottomRight), paint);
+
+      final borderColor = squareColor.darken(20);
+      paint.color = borderColor;
+      paint.style = PaintingStyle.stroke;
+      canvas.drawRect(Rect.fromPoints(topLeft, bottomRight), paint);
+    }
+
+    // centered text value
+    final textSpan = TextSpan(
+      text: value.toString(),
+      style: TextStyle(
+        color: Colors.black,
+        fontSize: size / 4,
+        fontWeight: FontWeight.bold,
+      ),
+    );
+    final textPainter = TextPainter(
+      text: textSpan,
+      textDirection: TextDirection.ltr,
+    );
+    textPainter.layout();
+    textPainter.paint(
+      canvas,
+      Offset(
+        (size - textPainter.width) * 0.5,
+        (size - textPainter.height) * 0.5,
+      ),
+    );
+  }
+
+  void paintColorsThemeParameterItem(
+    final String value,
+    final Canvas canvas,
+    final double size,
+  ) {
+    Color backgroundColor = Colors.grey;
+    const int gridWidth = 4;
+
+    final paint = Paint();
+    paint.strokeJoin = StrokeJoin.round;
+    paint.strokeWidth = 3 / 100 * size;
+
+    // Colored background
+    paint.color = backgroundColor;
+    paint.style = PaintingStyle.fill;
+    canvas.drawRect(Rect.fromPoints(const Offset(0, 0), Offset(size, size)), paint);
+
+    // Mini grid
+    final borderColor = Colors.grey.shade800;
+
+    final double cellSize = size / gridWidth;
+    final double origin = (size - gridWidth * cellSize) / 2;
+
+    for (int row = 0; row < gridWidth; row++) {
+      for (int col = 0; col < gridWidth; col++) {
+        final Offset topLeft = Offset(origin + col * cellSize, origin + row * cellSize);
+        final Offset bottomRight = topLeft + Offset(cellSize, cellSize);
+
+        const squareColor = Colors.pink;
+
+        paint.color = squareColor;
+        paint.style = PaintingStyle.fill;
+        canvas.drawRect(Rect.fromPoints(topLeft, bottomRight), paint);
+
+        paint.color = borderColor;
+        paint.style = PaintingStyle.stroke;
+        canvas.drawRect(Rect.fromPoints(topLeft, bottomRight), paint);
+      }
+    }
+  }
+}
diff --git a/lib/ui/screens/about_page.dart b/lib/ui/screens/about_page.dart
deleted file mode 100644
index 459d008..0000000
--- a/lib/ui/screens/about_page.dart
+++ /dev/null
@@ -1,41 +0,0 @@
-import 'package:easy_localization/easy_localization.dart';
-import 'package:flutter/material.dart';
-import 'package:package_info_plus/package_info_plus.dart';
-
-import 'package:colors/ui/widgets/header_app.dart';
-
-class AboutPage extends StatelessWidget {
-  const AboutPage({super.key});
-
-  @override
-  Widget build(BuildContext context) {
-    return Padding(
-      padding: const EdgeInsets.symmetric(horizontal: 8),
-      child: Column(
-        mainAxisAlignment: MainAxisAlignment.start,
-        crossAxisAlignment: CrossAxisAlignment.start,
-        mainAxisSize: MainAxisSize.max,
-        children: <Widget>[
-          const SizedBox(height: 8),
-          const AppHeader(text: 'about_title'),
-          const Text('about_content').tr(),
-          FutureBuilder<PackageInfo>(
-            future: PackageInfo.fromPlatform(),
-            builder: (context, snapshot) {
-              switch (snapshot.connectionState) {
-                case ConnectionState.done:
-                  return const Text('about_version').tr(
-                    namedArgs: {
-                      'version': snapshot.data!.version,
-                    },
-                  );
-                default:
-                  return const SizedBox();
-              }
-            },
-          ),
-        ],
-      ),
-    );
-  }
-}
diff --git a/lib/ui/screens/game_page.dart b/lib/ui/screens/game_page.dart
deleted file mode 100644
index d974148..0000000
--- a/lib/ui/screens/game_page.dart
+++ /dev/null
@@ -1,37 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
-
-import 'package:colors/ui/layout/game.dart';
-import 'package:colors/ui/layout/parameters.dart';
-import 'package:colors/provider/data.dart';
-
-class GamePage extends StatefulWidget {
-  const GamePage({super.key});
-
-  @override
-  GamePageState createState() => GamePageState();
-}
-
-class GamePageState extends State<GamePage> {
-  @override
-  void initState() {
-    super.initState();
-
-    final Data myProvider = Provider.of<Data>(context, listen: false);
-    myProvider.initParametersValues();
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    final Data myProvider = Provider.of<Data>(context);
-    final double boardWidth = MediaQuery.of(context).size.width;
-
-    return SafeArea(
-      child: Center(
-        child: myProvider.gameIsRunning
-            ? Game(myProvider: myProvider, boardWidth: boardWidth)
-            : Parameters(myProvider: myProvider),
-      ),
-    );
-  }
-}
diff --git a/lib/ui/screens/page_about.dart b/lib/ui/screens/page_about.dart
new file mode 100644
index 0000000..a8602ef
--- /dev/null
+++ b/lib/ui/screens/page_about.dart
@@ -0,0 +1,38 @@
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+import 'package:package_info_plus/package_info_plus.dart';
+
+import 'package:colors/ui/widgets/helpers/header_app.dart';
+
+class PageAbout extends StatelessWidget {
+  const PageAbout({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return Column(
+      mainAxisAlignment: MainAxisAlignment.start,
+      crossAxisAlignment: CrossAxisAlignment.start,
+      mainAxisSize: MainAxisSize.max,
+      children: <Widget>[
+        const SizedBox(height: 8),
+        const AppHeader(text: 'about_title'),
+        const Text('about_content').tr(),
+        FutureBuilder<PackageInfo>(
+          future: PackageInfo.fromPlatform(),
+          builder: (context, snapshot) {
+            switch (snapshot.connectionState) {
+              case ConnectionState.done:
+                return const Text('about_version').tr(
+                  namedArgs: {
+                    'version': snapshot.data!.version,
+                  },
+                );
+              default:
+                return const SizedBox();
+            }
+          },
+        ),
+      ],
+    );
+  }
+}
diff --git a/lib/ui/screens/page_game.dart b/lib/ui/screens/page_game.dart
new file mode 100644
index 0000000..d3a64ac
--- /dev/null
+++ b/lib/ui/screens/page_game.dart
@@ -0,0 +1,18 @@
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:flutter/material.dart';
+
+import 'package:colors/cubit/game_cubit.dart';
+import 'package:colors/ui/widgets/game/game.dart';
+import 'package:colors/ui/widgets/parameters.dart';
+
+class PageGame extends StatelessWidget {
+  const PageGame({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<GameCubit, GameState>(
+        builder: (BuildContext context, GameState gameState) {
+      return gameState.currentGame.isRunning ? const GameWidget() : const Parameters();
+    });
+  }
+}
diff --git a/lib/ui/screens/page_settings.dart b/lib/ui/screens/page_settings.dart
new file mode 100644
index 0000000..d559f95
--- /dev/null
+++ b/lib/ui/screens/page_settings.dart
@@ -0,0 +1,23 @@
+import 'package:flutter/material.dart';
+
+import 'package:colors/ui/widgets/helpers/header_app.dart';
+import 'package:colors/ui/widgets/settings/settings_form.dart';
+
+class PageSettings extends StatelessWidget {
+  const PageSettings({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return const Column(
+      mainAxisAlignment: MainAxisAlignment.start,
+      crossAxisAlignment: CrossAxisAlignment.start,
+      mainAxisSize: MainAxisSize.max,
+      children: <Widget>[
+        SizedBox(height: 8),
+        AppHeader(text: 'settings_title'),
+        SizedBox(height: 8),
+        SettingsForm(),
+      ],
+    );
+  }
+}
diff --git a/lib/ui/screens/settings_page.dart b/lib/ui/screens/settings_page.dart
deleted file mode 100644
index dc59bbe..0000000
--- a/lib/ui/screens/settings_page.dart
+++ /dev/null
@@ -1,26 +0,0 @@
-import 'package:flutter/material.dart';
-
-import 'package:colors/ui/widgets/header_app.dart';
-import 'package:colors/ui/widgets/settings/settings_form.dart';
-
-class SettingsPage extends StatelessWidget {
-  const SettingsPage({super.key});
-
-  @override
-  Widget build(BuildContext context) {
-    return const Padding(
-      padding: EdgeInsets.symmetric(horizontal: 8),
-      child: Column(
-        mainAxisAlignment: MainAxisAlignment.start,
-        crossAxisAlignment: CrossAxisAlignment.start,
-        mainAxisSize: MainAxisSize.max,
-        children: <Widget>[
-          SizedBox(height: 8),
-          AppHeader(text: 'settings_title'),
-          SizedBox(height: 8),
-          SettingsForm(),
-        ],
-      ),
-    );
-  }
-}
diff --git a/lib/ui/skeleton.dart b/lib/ui/skeleton.dart
index a428bc5..eaec6f6 100644
--- a/lib/ui/skeleton.dart
+++ b/lib/ui/skeleton.dart
@@ -1,47 +1,28 @@
-import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:flutter_swipe/flutter_swipe.dart';
-import 'package:provider/provider.dart';
+import 'package:flutter/material.dart';
 
 import 'package:colors/config/menu.dart';
-import 'package:colors/cubit/bottom_nav_cubit.dart';
-import 'package:colors/provider/data.dart';
-import 'package:colors/ui/widgets/app_bar.dart';
-import 'package:colors/ui/widgets/bottom_nav_bar.dart';
+import 'package:colors/cubit/nav_cubit.dart';
+import 'package:colors/ui/widgets/global_app_bar.dart';
 
-class SkeletonScreen extends StatefulWidget {
+class SkeletonScreen extends StatelessWidget {
   const SkeletonScreen({super.key});
 
-  @override
-  State<SkeletonScreen> createState() => _SkeletonScreenState();
-}
-
-class _SkeletonScreenState extends State<SkeletonScreen> {
   @override
   Widget build(BuildContext context) {
-    final Data myProvider = Provider.of<Data>(context);
-
     return Scaffold(
+      appBar: const GlobalAppBar(),
       extendBodyBehindAppBar: false,
-      appBar: StandardAppBar(myProvider: myProvider),
-      body: Swiper(
-        itemCount: Menu.itemsCount,
-        itemBuilder: (BuildContext context, int index) {
-          return Menu.getPageWidget(index);
-        },
-        pagination: SwiperPagination(
-          margin: const EdgeInsets.all(0),
-          builder: SwiperCustomPagination(
-            builder: (BuildContext context, SwiperPluginConfig config) {
-              return BottomNavBar(swipeController: config.controller);
-            },
-          ),
+      body: Material(
+        color: Theme.of(context).colorScheme.background,
+        child: BlocBuilder<NavCubit, int>(
+          builder: (BuildContext context, int pageIndex) {
+            return Padding(
+              padding: const EdgeInsets.symmetric(horizontal: 4),
+              child: Menu.getPageWidget(pageIndex),
+            );
+          },
         ),
-        onIndexChanged: (newPageIndex) {
-          BlocProvider.of<BottomNavCubit>(context).updateIndex(newPageIndex);
-        },
-        outer: true,
-        loop: false,
       ),
       backgroundColor: Theme.of(context).colorScheme.background,
     );
diff --git a/lib/ui/widgets/app_bar.dart b/lib/ui/widgets/app_bar.dart
deleted file mode 100644
index c998df6..0000000
--- a/lib/ui/widgets/app_bar.dart
+++ /dev/null
@@ -1,37 +0,0 @@
-import 'package:easy_localization/easy_localization.dart';
-import 'package:flutter/material.dart';
-import 'package:overlay_support/overlay_support.dart';
-
-import 'package:colors/provider/data.dart';
-import 'package:colors/ui/widgets/header_app.dart';
-import 'package:colors/utils/game_utils.dart';
-
-class StandardAppBar extends StatelessWidget implements PreferredSizeWidget {
-  const StandardAppBar({super.key, required this.myProvider});
-
-  final Data myProvider;
-
-  @override
-  Widget build(BuildContext context) {
-    final List<Widget> menuActions = [];
-
-    if (myProvider.gameIsRunning) {
-      menuActions.add(TextButton(
-        child: const Image(
-          image: AssetImage('assets/icons/button_back.png'),
-          fit: BoxFit.fill,
-        ),
-        onPressed: () => toast(tr('long_press_to_quit')),
-        onLongPress: () => GameUtils.quitGame(myProvider),
-      ));
-    }
-
-    return AppBar(
-      title: const AppHeader(text: 'app_name'),
-      actions: menuActions,
-    );
-  }
-
-  @override
-  Size get preferredSize => const Size.fromHeight(50);
-}
diff --git a/lib/ui/widgets/bottom_nav_bar.dart b/lib/ui/widgets/bottom_nav_bar.dart
deleted file mode 100644
index 87e30d5..0000000
--- a/lib/ui/widgets/bottom_nav_bar.dart
+++ /dev/null
@@ -1,40 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:flutter_swipe/flutter_swipe.dart';
-
-import 'package:colors/config/menu.dart';
-import 'package:colors/cubit/bottom_nav_cubit.dart';
-
-class BottomNavBar extends StatelessWidget {
-  const BottomNavBar({super.key, required this.swipeController});
-
-  final SwiperController swipeController;
-
-  @override
-  Widget build(BuildContext context) {
-    return Card(
-      margin: const EdgeInsets.all(0),
-      elevation: 4,
-      shadowColor: Theme.of(context).colorScheme.shadow,
-      color: Theme.of(context).colorScheme.surfaceVariant,
-      shape: const ContinuousRectangleBorder(),
-      child: BlocBuilder<BottomNavCubit, int>(
-        builder: (BuildContext context, int state) {
-          return BottomNavigationBar(
-            currentIndex: state,
-            onTap: (int index) {
-              context.read<BottomNavCubit>().updateIndex(index);
-              swipeController.move(index);
-            },
-            type: BottomNavigationBarType.fixed,
-            elevation: 0,
-            backgroundColor: Colors.transparent,
-            selectedItemColor: Theme.of(context).colorScheme.primary,
-            unselectedItemColor: Theme.of(context).textTheme.bodySmall!.color,
-            items: Menu.getMenuItems(),
-          );
-        },
-      ),
-    );
-  }
-}
diff --git a/lib/ui/widgets/button_game_start_new.dart b/lib/ui/widgets/button_game_start_new.dart
new file mode 100644
index 0000000..613d2fb
--- /dev/null
+++ b/lib/ui/widgets/button_game_start_new.dart
@@ -0,0 +1,34 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:colors/cubit/game_cubit.dart';
+import 'package:colors/cubit/settings_game_cubit.dart';
+import 'package:colors/cubit/settings_global_cubit.dart';
+
+class StartNewGameButton extends StatelessWidget {
+  const StartNewGameButton({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<GameSettingsCubit, GameSettingsState>(
+      builder: (BuildContext context, GameSettingsState gameSettingsState) {
+        return BlocBuilder<GlobalSettingsCubit, GlobalSettingsState>(
+          builder: (BuildContext context, GlobalSettingsState globalSettingsState) {
+            final GameCubit gameCubit = BlocProvider.of<GameCubit>(context);
+
+            return TextButton(
+              child: const Image(
+                image: AssetImage('assets/icons/button_start.png'),
+                fit: BoxFit.fill,
+              ),
+              onPressed: () => gameCubit.startNewGame(
+                gameSettings: gameSettingsState.settings,
+                globalSettings: globalSettingsState.settings,
+              ),
+            );
+          },
+        );
+      },
+    );
+  }
+}
diff --git a/lib/ui/widgets/home/button_game_restart.dart b/lib/ui/widgets/game/button_game_restart.dart
similarity index 62%
rename from lib/ui/widgets/home/button_game_restart.dart
rename to lib/ui/widgets/game/button_game_restart.dart
index 364ca07..dce403b 100644
--- a/lib/ui/widgets/home/button_game_restart.dart
+++ b/lib/ui/widgets/game/button_game_restart.dart
@@ -1,15 +1,15 @@
+import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:flutter/material.dart';
 
-import 'package:colors/provider/data.dart';
-import 'package:colors/utils/game_utils.dart';
+import 'package:colors/cubit/game_cubit.dart';
 
 class RestartGameButton extends StatelessWidget {
-  const RestartGameButton({super.key, required this.myProvider});
-
-  final Data myProvider;
+  const RestartGameButton({super.key});
 
   @override
   Widget build(BuildContext context) {
+    final GameCubit gameCubit = BlocProvider.of<GameCubit>(context);
+
     return TextButton(
       style: ButtonStyle(
         padding: MaterialStateProperty.all<EdgeInsets>(const EdgeInsets.all(0)),
@@ -18,7 +18,7 @@ class RestartGameButton extends StatelessWidget {
         image: AssetImage('assets/icons/button_back.png'),
         fit: BoxFit.fill,
       ),
-      onPressed: () => GameUtils.quitGame(myProvider),
+      onPressed: () => gameCubit.quitGame(),
     );
   }
 }
diff --git a/lib/ui/widgets/game/cell_interactive.dart b/lib/ui/widgets/game/cell_interactive.dart
new file mode 100644
index 0000000..40b67d0
--- /dev/null
+++ b/lib/ui/widgets/game/cell_interactive.dart
@@ -0,0 +1,55 @@
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:flutter/material.dart';
+
+import 'package:colors/cubit/game_cubit.dart';
+import 'package:colors/models/cell.dart';
+import 'package:colors/models/game.dart';
+import 'package:colors/utils/color_theme.dart';
+
+class InteractiveCell extends StatelessWidget {
+  const InteractiveCell({
+    super.key,
+    required this.cell,
+    required this.colorScheme,
+    required this.currentGame,
+    required this.itemWidth,
+  });
+
+  final Cell cell;
+  final ColorScheme colorScheme;
+  final Game currentGame;
+  final double itemWidth;
+
+  @override
+  Widget build(BuildContext context) {
+    final String skin = currentGame.globalSettings.skin;
+    final squareColor = Color(ColorTheme.getColorCode(skin, cell.value));
+
+    return Container(
+      margin: const EdgeInsets.all(2),
+      decoration: BoxDecoration(
+        border: Border.all(
+          color: colorScheme.onSurface,
+          width: 3,
+        ),
+      ),
+      child: GestureDetector(
+        child: Container(
+          color: squareColor,
+          padding: const EdgeInsets.all(4),
+          child: SizedBox.square(
+            dimension: itemWidth - 19,
+          ),
+        ),
+        onTap: () {
+          final GameCubit gameCubit = BlocProvider.of<GameCubit>(context);
+
+          if (!currentGame.animationInProgress &&
+              currentGame.board.getFirstCellValue() != cell.value) {
+            gameCubit.fillBoardFromFirstCell(cell.value);
+          }
+        },
+      ),
+    );
+  }
+}
diff --git a/lib/ui/widgets/game/game.dart b/lib/ui/widgets/game/game.dart
new file mode 100644
index 0000000..870676c
--- /dev/null
+++ b/lib/ui/widgets/game/game.dart
@@ -0,0 +1,37 @@
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:flutter/material.dart';
+
+import 'package:colors/cubit/game_cubit.dart';
+import 'package:colors/models/game.dart';
+import 'package:colors/ui/widgets/game/game_board.dart';
+import 'package:colors/ui/widgets/game/game_top_indicator.dart';
+import 'package:colors/ui/widgets/game/message_game_end.dart';
+import 'package:colors/ui/widgets/game/select_color_bar.dart';
+
+class GameWidget extends StatelessWidget {
+  const GameWidget({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        final Game currentGame = gameState.currentGame;
+
+        return Column(
+          mainAxisAlignment: MainAxisAlignment.start,
+          crossAxisAlignment: CrossAxisAlignment.center,
+          children: [
+            const SizedBox(height: 8),
+            const GameTopIndicatorWidget(),
+            const SizedBox(height: 2),
+            const GameBoard(),
+            const Expanded(
+              child: SizedBox(height: 2),
+            ),
+            currentGame.isFinished ? const EndGameMessage() : const SelectColorBar(),
+          ],
+        );
+      },
+    );
+  }
+}
diff --git a/lib/ui/widgets/game/game_board.dart b/lib/ui/widgets/game/game_board.dart
new file mode 100644
index 0000000..385fc17
--- /dev/null
+++ b/lib/ui/widgets/game/game_board.dart
@@ -0,0 +1,43 @@
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:flutter/material.dart';
+
+import 'package:colors/cubit/game_cubit.dart';
+import 'package:colors/models/game.dart';
+import 'package:colors/ui/painters/board_painter.dart';
+
+class GameBoard extends StatelessWidget {
+  const GameBoard({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        final Game currentGame = gameState.currentGame;
+        final double boardWidth = MediaQuery.of(context).size.width;
+
+        return GestureDetector(
+          onTapUp: (details) {
+            final double xTap = details.localPosition.dx;
+            final double yTap = details.localPosition.dy;
+            final int boardSize = currentGame.gameSettings.boardSize;
+            final int col = xTap ~/ (boardWidth / boardSize);
+            final int row = yTap ~/ (boardWidth / boardSize);
+            final int cellValue = currentGame.board.getCellValue(col, row);
+
+            final GameCubit gameCubit = BlocProvider.of<GameCubit>(context);
+            gameCubit.fillBoardFromFirstCell(cellValue);
+          },
+          child: CustomPaint(
+            size: Size(boardWidth, boardWidth),
+            willChange: false,
+            painter: BoardPainter(
+              game: currentGame,
+              colorScheme: Theme.of(context).colorScheme,
+            ),
+            isComplex: true,
+          ),
+        );
+      },
+    );
+  }
+}
diff --git a/lib/ui/widgets/game/game_top_indicator.dart b/lib/ui/widgets/game/game_top_indicator.dart
new file mode 100644
index 0000000..93948cd
--- /dev/null
+++ b/lib/ui/widgets/game/game_top_indicator.dart
@@ -0,0 +1,70 @@
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:flutter/material.dart';
+
+import 'package:colors/cubit/game_cubit.dart';
+import 'package:colors/models/game.dart';
+
+class GameTopIndicatorWidget extends StatelessWidget {
+  const GameTopIndicatorWidget({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        final Game currentGame = gameState.currentGame;
+
+        String progressIndicator = '${currentGame.progress}/${currentGame.progressTotal}';
+
+        if (currentGame.movesCount > 0) {
+          progressIndicator += ' (+${currentGame.progressDelta})';
+        }
+
+        Color maxMovesCountColor = Colors.grey;
+        if (currentGame.movesCount > currentGame.maxMovesCount) {
+          maxMovesCountColor = Colors.red;
+        }
+
+        return Table(
+          children: [
+            TableRow(
+              children: [
+                Column(
+                  children: [
+                    Text(
+                      currentGame.movesCount.toString(),
+                      style: TextStyle(
+                        fontSize: 35,
+                        fontWeight: FontWeight.w600,
+                        color: Theme.of(context).colorScheme.primary,
+                      ),
+                    )
+                  ],
+                ),
+                Column(
+                  children: [
+                    Text(
+                      '(max: ${currentGame.maxMovesCount})',
+                      style: TextStyle(
+                        fontSize: 15,
+                        fontWeight: FontWeight.w600,
+                        color: maxMovesCountColor,
+                      ),
+                    ),
+                    Text(
+                      progressIndicator,
+                      style: const TextStyle(
+                        fontSize: 15,
+                        fontWeight: FontWeight.w600,
+                        color: Colors.green,
+                      ),
+                    ),
+                  ],
+                ),
+              ],
+            ),
+          ],
+        );
+      },
+    );
+  }
+}
diff --git a/lib/ui/widgets/game/indicator_top.dart b/lib/ui/widgets/game/indicator_top.dart
deleted file mode 100644
index 610037e..0000000
--- a/lib/ui/widgets/game/indicator_top.dart
+++ /dev/null
@@ -1,64 +0,0 @@
-import 'package:flutter/material.dart';
-
-import 'package:colors/provider/data.dart';
-
-class TopIndicator extends StatelessWidget {
-  const TopIndicator({super.key, required this.myProvider});
-
-  final Data myProvider;
-
-  @override
-  Widget build(BuildContext context) {
-    String progressIndicator = '${myProvider.progress}/${myProvider.progressTotal}';
-
-    if (myProvider.movesCount > 0) {
-      progressIndicator += ' (+${myProvider.progressDelta})';
-    }
-
-    Color maxMovesCountColor = Colors.grey;
-    if (myProvider.movesCount > myProvider.maxMovesCount) {
-      maxMovesCountColor = Colors.red;
-    }
-
-    return Table(
-      children: [
-        TableRow(
-          children: [
-            Column(
-              children: [
-                Text(
-                  myProvider.movesCount.toString(),
-                  style: const TextStyle(
-                    fontSize: 35,
-                    fontWeight: FontWeight.w600,
-                    color: Colors.grey,
-                  ),
-                ),
-              ],
-            ),
-            Column(
-              children: [
-                Text(
-                  '(max: ${myProvider.maxMovesCount})',
-                  style: TextStyle(
-                    fontSize: 15,
-                    fontWeight: FontWeight.w600,
-                    color: maxMovesCountColor,
-                  ),
-                ),
-                Text(
-                  progressIndicator,
-                  style: const TextStyle(
-                    fontSize: 15,
-                    fontWeight: FontWeight.w600,
-                    color: Colors.green,
-                  ),
-                ),
-              ],
-            ),
-          ],
-        ),
-      ],
-    );
-  }
-}
diff --git a/lib/ui/widgets/game/message_game_end.dart b/lib/ui/widgets/game/message_game_end.dart
index 4a9cd90..2a5cae8 100644
--- a/lib/ui/widgets/game/message_game_end.dart
+++ b/lib/ui/widgets/game/message_game_end.dart
@@ -1,44 +1,50 @@
+import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:flutter/material.dart';
 
-import 'package:colors/ui/widgets/home/button_game_restart.dart';
-import 'package:colors/provider/data.dart';
+import 'package:colors/cubit/game_cubit.dart';
+import 'package:colors/models/game.dart';
+import 'package:colors/ui/widgets/game/button_game_restart.dart';
 
 class EndGameMessage extends StatelessWidget {
-  const EndGameMessage({super.key, required this.myProvider});
-
-  final Data myProvider;
+  const EndGameMessage({super.key});
 
   @override
   Widget build(BuildContext context) {
-    String decorationImageAssetName = '';
-    if (myProvider.gameWon) {
-      decorationImageAssetName = 'assets/icons/game_win.png';
-    } else {
-      decorationImageAssetName = 'assets/icons/game_fail.png';
-    }
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        final Game currentGame = gameState.currentGame;
 
-    final Image decorationImage = Image(
-      image: AssetImage(decorationImageAssetName),
-      fit: BoxFit.fill,
-    );
+        String decorationImageAssetName = '';
+        if (currentGame.gameWon) {
+          decorationImageAssetName = 'assets/icons/game_win.png';
+        } else {
+          decorationImageAssetName = 'assets/icons/game_fail.png';
+        }
+
+        final Image decorationImage = Image(
+          image: AssetImage(decorationImageAssetName),
+          fit: BoxFit.fill,
+        );
 
-    return Container(
-      margin: const EdgeInsets.all(2),
-      padding: const EdgeInsets.all(2),
-      child: Table(
-        defaultColumnWidth: const IntrinsicColumnWidth(),
-        children: [
-          TableRow(
+        return Container(
+          margin: const EdgeInsets.all(2),
+          padding: const EdgeInsets.all(2),
+          child: Table(
+            defaultColumnWidth: const IntrinsicColumnWidth(),
             children: [
-              Column(children: [decorationImage]),
-              Column(children: [decorationImage]),
-              Column(children: [RestartGameButton(myProvider: myProvider)]),
-              Column(children: [decorationImage]),
-              Column(children: [decorationImage]),
+              TableRow(
+                children: [
+                  Column(children: [decorationImage]),
+                  Column(children: [decorationImage]),
+                  const Column(children: [RestartGameButton()]),
+                  Column(children: [decorationImage]),
+                  Column(children: [decorationImage]),
+                ],
+              ),
             ],
           ),
-        ],
-      ),
+        );
+      },
     );
   }
 }
diff --git a/lib/ui/widgets/game/select_color_bar.dart b/lib/ui/widgets/game/select_color_bar.dart
index 8211b46..3b8addb 100644
--- a/lib/ui/widgets/game/select_color_bar.dart
+++ b/lib/ui/widgets/game/select_color_bar.dart
@@ -1,36 +1,42 @@
+import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:flutter/material.dart';
 
-import 'package:colors/entities/cell.dart';
-import 'package:colors/provider/data.dart';
+import 'package:colors/cubit/game_cubit.dart';
+import 'package:colors/models/cell.dart';
+import 'package:colors/ui/widgets/game/cell_interactive.dart';
 
 class SelectColorBar extends StatelessWidget {
-  const SelectColorBar({super.key, required this.myProvider});
-
-  final Data myProvider;
+  const SelectColorBar({super.key});
 
   @override
   Widget build(BuildContext context) {
-    final int maxValue = myProvider.colorsCount;
-    final ColorScheme colorScheme = Theme.of(context).colorScheme;
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        final double blockWidth = MediaQuery.of(context).size.width;
+        final ColorScheme colorScheme = Theme.of(context).colorScheme;
+        final int maxValue = gameState.currentGame.gameSettings.colorsCount;
 
-    return Container(
-      margin: const EdgeInsets.all(2),
-      padding: const EdgeInsets.all(2),
-      child: Table(
-        defaultColumnWidth: const IntrinsicColumnWidth(),
-        children: [
-          TableRow(
-            children: [
-              for (int value = 1; value <= maxValue; value++)
-                Column(
-                  children: [
-                    Cell(value).interactiveWidget(myProvider, colorScheme),
-                  ],
-                ),
-            ],
-          ),
-        ],
-      ),
+        return Table(
+          defaultColumnWidth: const IntrinsicColumnWidth(),
+          children: [
+            TableRow(
+              children: [
+                for (int value = 1; value <= maxValue; value++)
+                  Column(
+                    children: [
+                      InteractiveCell(
+                        cell: Cell(value),
+                        colorScheme: colorScheme,
+                        currentGame: gameState.currentGame,
+                        itemWidth: blockWidth / maxValue,
+                      ),
+                    ],
+                  ),
+              ],
+            ),
+          ],
+        );
+      },
     );
   }
 }
diff --git a/lib/ui/widgets/global_app_bar.dart b/lib/ui/widgets/global_app_bar.dart
new file mode 100644
index 0000000..b3850be
--- /dev/null
+++ b/lib/ui/widgets/global_app_bar.dart
@@ -0,0 +1,82 @@
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:flutter/material.dart';
+
+import 'package:colors/config/menu.dart';
+import 'package:colors/cubit/game_cubit.dart';
+import 'package:colors/cubit/nav_cubit.dart';
+import 'package:colors/models/game.dart';
+import 'package:colors/ui/widgets/helpers/app_titles.dart';
+
+class GlobalAppBar extends StatelessWidget implements PreferredSizeWidget {
+  const GlobalAppBar({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        return BlocBuilder<NavCubit, int>(
+          builder: (BuildContext context, int pageIndex) {
+            final GameCubit gameCubit = BlocProvider.of<GameCubit>(context);
+            final Game currentGame = gameState.currentGame;
+
+            final List<Widget> menuActions = [];
+
+            if (currentGame.isRunning) {
+              menuActions.add(TextButton(
+                onPressed: null,
+                onLongPress: () => gameCubit.quitGame(),
+                child: const Image(
+                  image: AssetImage('assets/icons/button_back.png'),
+                  fit: BoxFit.fill,
+                ),
+              ));
+            } else {
+              if (pageIndex == Menu.indexGame) {
+                // go to Settings page
+                menuActions.add(ElevatedButton(
+                  onPressed: () {
+                    context.read<NavCubit>().goToSettingsPage();
+                  },
+                  style: ElevatedButton.styleFrom(
+                    shape: const CircleBorder(),
+                  ),
+                  child: Menu.menuItemSettings.icon,
+                ));
+
+                // go to About page
+                menuActions.add(ElevatedButton(
+                  onPressed: () {
+                    context.read<NavCubit>().goToAboutPage();
+                  },
+                  style: ElevatedButton.styleFrom(
+                    shape: const CircleBorder(),
+                  ),
+                  child: Menu.menuItemAbout.icon,
+                ));
+              } else {
+                // back to Home page
+                menuActions.add(ElevatedButton(
+                  onPressed: () {
+                    context.read<NavCubit>().goToGamePage();
+                  },
+                  style: ElevatedButton.styleFrom(
+                    shape: const CircleBorder(),
+                  ),
+                  child: Menu.menuItemGame.icon,
+                ));
+              }
+            }
+
+            return AppBar(
+              title: const AppTitle(text: 'app_name'),
+              actions: menuActions,
+            );
+          },
+        );
+      },
+    );
+  }
+
+  @override
+  Size get preferredSize => const Size.fromHeight(50);
+}
diff --git a/lib/ui/widgets/helpers/app_titles.dart b/lib/ui/widgets/helpers/app_titles.dart
new file mode 100644
index 0000000..7cbbb20
--- /dev/null
+++ b/lib/ui/widgets/helpers/app_titles.dart
@@ -0,0 +1,17 @@
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+
+class AppTitle extends StatelessWidget {
+  const AppTitle({super.key, required this.text});
+
+  final String text;
+
+  @override
+  Widget build(BuildContext context) {
+    return Text(
+      tr(text),
+      textAlign: TextAlign.start,
+      style: Theme.of(context).textTheme.headlineLarge!.apply(fontWeightDelta: 2),
+    );
+  }
+}
diff --git a/lib/ui/widgets/header_app.dart b/lib/ui/widgets/helpers/header_app.dart
similarity index 77%
rename from lib/ui/widgets/header_app.dart
rename to lib/ui/widgets/helpers/header_app.dart
index bf54b77..b5c5be0 100644
--- a/lib/ui/widgets/header_app.dart
+++ b/lib/ui/widgets/helpers/header_app.dart
@@ -8,15 +8,16 @@ class AppHeader extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    return Row(
+    return Column(
       mainAxisAlignment: MainAxisAlignment.start,
       crossAxisAlignment: CrossAxisAlignment.start,
       children: [
         Text(
           tr(text),
           textAlign: TextAlign.start,
-          style: Theme.of(context).textTheme.headlineMedium!.apply(fontWeightDelta: 2),
+          style: Theme.of(context).textTheme.headlineSmall!.apply(fontWeightDelta: 2),
         ),
+        const SizedBox(height: 8),
       ],
     );
   }
diff --git a/lib/ui/widgets/helpers/outlined_text_widget.dart b/lib/ui/widgets/helpers/outlined_text_widget.dart
new file mode 100644
index 0000000..8e33709
--- /dev/null
+++ b/lib/ui/widgets/helpers/outlined_text_widget.dart
@@ -0,0 +1,49 @@
+import 'package:flutter/material.dart';
+
+class OutlinedText extends StatelessWidget {
+  const OutlinedText({
+    super.key,
+    required this.text,
+    required this.fontSize,
+    required this.textColor,
+    required this.outlineColor,
+  });
+
+  final String text;
+  final double fontSize;
+  final Color textColor;
+  final Color outlineColor;
+
+  @override
+  Widget build(BuildContext context) {
+    final double delta = fontSize / 35;
+
+    return Text(
+      text,
+      style: TextStyle(
+        inherit: true,
+        fontSize: fontSize,
+        fontWeight: FontWeight.w600,
+        color: textColor,
+        shadows: [
+          Shadow(
+            offset: Offset(-delta, -delta),
+            color: outlineColor,
+          ),
+          Shadow(
+            offset: Offset(delta, -delta),
+            color: outlineColor,
+          ),
+          Shadow(
+            offset: Offset(delta, delta),
+            color: outlineColor,
+          ),
+          Shadow(
+            offset: Offset(-delta, delta),
+            color: outlineColor,
+          ),
+        ],
+      ),
+    );
+  }
+}
diff --git a/lib/ui/widgets/home/button_game_start_new.dart b/lib/ui/widgets/home/button_game_start_new.dart
deleted file mode 100644
index 80466e2..0000000
--- a/lib/ui/widgets/home/button_game_start_new.dart
+++ /dev/null
@@ -1,38 +0,0 @@
-import 'package:flutter/material.dart';
-
-import 'package:colors/provider/data.dart';
-import 'package:colors/ui/layout/parameters.dart';
-import 'package:colors/utils/game_utils.dart';
-
-class StartNewGameButton extends StatelessWidget {
-  const StartNewGameButton({super.key, required this.myProvider});
-
-  final Data myProvider;
-
-  @override
-  Widget build(BuildContext context) {
-    return Container(
-      margin: const EdgeInsets.all(Parameters.blockMargin),
-      padding: const EdgeInsets.all(Parameters.blockPadding),
-      child: Table(
-        defaultColumnWidth: const IntrinsicColumnWidth(),
-        children: [
-          TableRow(
-            children: [
-              Parameters.buildDecorationImageWidget(),
-              Column(
-                children: [
-                  TextButton(
-                    child: Parameters.buildImageContainerWidget('button_start'),
-                    onPressed: () => GameUtils.startNewGame(myProvider),
-                  ),
-                ],
-              ),
-              Parameters.buildDecorationImageWidget(),
-            ],
-          ),
-        ],
-      ),
-    );
-  }
-}
diff --git a/lib/ui/widgets/parameters.dart b/lib/ui/widgets/parameters.dart
new file mode 100644
index 0000000..55525a9
--- /dev/null
+++ b/lib/ui/widgets/parameters.dart
@@ -0,0 +1,121 @@
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:flutter/material.dart';
+
+import 'package:colors/config/default_game_settings.dart';
+import 'package:colors/config/default_global_settings.dart';
+import 'package:colors/cubit/settings_game_cubit.dart';
+import 'package:colors/cubit/settings_global_cubit.dart';
+import 'package:colors/ui/painters/parameter_painter.dart';
+import 'package:colors/ui/widgets/button_game_start_new.dart';
+
+class Parameters extends StatelessWidget {
+  const Parameters({super.key});
+
+  final double separatorHeight = 8.0;
+
+  @override
+  Widget build(BuildContext context) {
+    final List<Widget> lines = [];
+
+    lines.add(SizedBox(height: separatorHeight));
+
+    // Game settings
+    for (String code in DefaultGameSettings.availableParameters) {
+      lines.add(Row(
+        mainAxisAlignment: MainAxisAlignment.spaceBetween,
+        children: buildParametersLine(
+          code: code,
+          isGlobal: false,
+        ),
+      ));
+
+      lines.add(SizedBox(height: separatorHeight));
+    }
+
+    lines.add(SizedBox(height: separatorHeight));
+    lines.add(const Expanded(child: StartNewGameButton()));
+    lines.add(SizedBox(height: separatorHeight));
+
+    // Global settings
+    for (String code in DefaultGlobalSettings.availableParameters) {
+      lines.add(Row(
+        mainAxisAlignment: MainAxisAlignment.spaceBetween,
+        children: buildParametersLine(
+          code: code,
+          isGlobal: true,
+        ),
+      ));
+
+      lines.add(SizedBox(height: separatorHeight));
+    }
+
+    return Column(
+      children: lines,
+    );
+  }
+
+  List<Widget> buildParametersLine({
+    required String code,
+    required bool isGlobal,
+  }) {
+    final List<Widget> parameterButtons = [];
+
+    final List<String> availableValues = isGlobal
+        ? DefaultGlobalSettings.getAvailableValues(code)
+        : DefaultGameSettings.getAvailableValues(code);
+
+    if (availableValues.length <= 1) {
+      return [];
+    }
+
+    for (String value in availableValues) {
+      final Widget parameterButton = BlocBuilder<GameSettingsCubit, GameSettingsState>(
+        builder: (BuildContext context, GameSettingsState gameSettingsState) {
+          return BlocBuilder<GlobalSettingsCubit, GlobalSettingsState>(
+            builder: (BuildContext context, GlobalSettingsState globalSettingsState) {
+              final GameSettingsCubit gameSettingsCubit =
+                  BlocProvider.of<GameSettingsCubit>(context);
+              final GlobalSettingsCubit globalSettingsCubit =
+                  BlocProvider.of<GlobalSettingsCubit>(context);
+
+              final String currentValue = isGlobal
+                  ? globalSettingsCubit.getParameterValue(code)
+                  : gameSettingsCubit.getParameterValue(code);
+
+              final bool isActive = (value == currentValue);
+
+              final double displayWidth = MediaQuery.of(context).size.width;
+              final double itemWidth = displayWidth / availableValues.length - 30;
+
+              return TextButton(
+                child: Container(
+                  margin: const EdgeInsets.all(0),
+                  padding: const EdgeInsets.all(0),
+                  child: CustomPaint(
+                    size: Size(itemWidth, itemWidth),
+                    willChange: false,
+                    painter: ParameterPainter(
+                      code: code,
+                      value: value,
+                      isSelected: isActive,
+                      gameSettings: gameSettingsState.settings,
+                      globalSettings: globalSettingsState.settings,
+                    ),
+                    isComplex: true,
+                  ),
+                ),
+                onPressed: () => isGlobal
+                    ? globalSettingsCubit.setParameterValue(code, value)
+                    : gameSettingsCubit.setParameterValue(code, value),
+              );
+            },
+          );
+        },
+      );
+
+      parameterButtons.add(parameterButton);
+    }
+
+    return parameterButtons;
+  }
+}
diff --git a/lib/ui/widgets/settings/theme_card.dart b/lib/ui/widgets/settings/theme_card.dart
index 5fd7bd7..834c67d 100644
--- a/lib/ui/widgets/settings/theme_card.dart
+++ b/lib/ui/widgets/settings/theme_card.dart
@@ -1,5 +1,5 @@
-import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:flutter/material.dart';
 
 import 'package:colors/cubit/theme_cubit.dart';
 
diff --git a/lib/utils/board_utils.dart b/lib/utils/board_utils.dart
deleted file mode 100644
index 7a63ce8..0000000
--- a/lib/utils/board_utils.dart
+++ /dev/null
@@ -1,168 +0,0 @@
-import 'dart:math';
-import 'dart:async';
-
-import 'package:colors/entities/cell.dart';
-import 'package:colors/provider/data.dart';
-import 'package:colors/utils/tools.dart';
-
-class BoardUtils {
-  static printGrid(List board) {
-    const String stringValues = '012345678';
-    printlog('');
-    printlog('-------');
-    for (int rowIndex = 0; rowIndex < board.length; rowIndex++) {
-      String row = '';
-      for (int colIndex = 0; colIndex < board[rowIndex].length; colIndex++) {
-        row += stringValues[board[rowIndex][colIndex].value];
-      }
-      printlog(row);
-    }
-    printlog('-------');
-    printlog('');
-  }
-
-  static createNewBoard(Data myProvider) {
-    final int boardSize = myProvider.boardSize;
-    final int maxValue = myProvider.colorsCount;
-
-    Random rand = Random();
-
-    Board board = [];
-    for (int rowIndex = 0; rowIndex < boardSize; rowIndex++) {
-      List<Cell> row = [];
-      for (int colIndex = 0; colIndex < boardSize; colIndex++) {
-        final int value = 1 + rand.nextInt(maxValue);
-        row.add(Cell(value));
-      }
-      board.add(row);
-    }
-    printGrid(board);
-
-    myProvider.resetGame();
-    myProvider.updateBoard(board);
-    myProvider.updateMaxMovesCount(computeMaxMovesCountLimit(myProvider));
-
-    final int initProgress = BoardUtils.getSiblingFillableCells(myProvider, 0, 0, [
-      [0, 0]
-    ]).length;
-    myProvider.updateProgress(initProgress);
-  }
-
-  static int computeMaxMovesCountLimit(myProvider) {
-    final int boardSize = myProvider.boardSize;
-    final int colorsCount = myProvider.colorsCount;
-
-    final int baseMaxMovesCount = (30 * (boardSize * colorsCount) / (17 * 6)).round();
-    final int deltaFromLevel =
-        myProvider.getMovesCountLimitDeltaFromLevelParameter(myProvider.parameterLevel);
-
-    return baseMaxMovesCount + deltaFromLevel;
-  }
-
-  static fillBoardFromFirstCell(Data myProvider, int value) {
-    List<List<int>> cellsToFill = BoardUtils.getSiblingFillableCells(myProvider, 0, 0, [
-      [0, 0]
-    ]);
-    final int progressBeforeMove = cellsToFill.length;
-
-    myProvider.incrementMovesCount();
-
-    // Sort cells from the closest to the furthest, relatively to the top left corner
-    cellsToFill
-        .sort((a, b) => (pow(a[0], 2) + pow(a[1], 2)).compareTo(pow(b[0], 2) + pow(b[1], 2)));
-
-    const interval = Duration(milliseconds: 10);
-    int cellIndex = 0;
-    myProvider.updateAnimationInProgress(true);
-    Timer.periodic(
-      interval,
-      (Timer timer) {
-        if (cellIndex < cellsToFill.length) {
-          myProvider.updateCellValue(
-              cellsToFill[cellIndex][1], cellsToFill[cellIndex][0], value);
-          cellIndex++;
-        } else {
-          timer.cancel();
-
-          int progressAfterMove = BoardUtils.getSiblingFillableCells(myProvider, 0, 0, [
-            [0, 0]
-          ]).length;
-          int progressDelta = progressAfterMove - progressBeforeMove;
-          myProvider.updateProgressDelta(progressDelta);
-          myProvider.updateProgress(progressAfterMove);
-
-          myProvider.updateAnimationInProgress(false);
-
-          if (BoardUtils.checkBoardIsSolved(myProvider)) {
-            myProvider.updateGameWon(true);
-          }
-        }
-      },
-    );
-  }
-
-  static List<List<int>> getSiblingFillableCells(
-    Data myProvider,
-    int row,
-    int col,
-    List<List<int>> siblingCells,
-  ) {
-    final Board board = myProvider.board;
-    final int boardSize = myProvider.boardSize;
-
-    final int referenceValue = board[row][col].value;
-
-    for (int deltaRow = -1; deltaRow <= 1; deltaRow++) {
-      for (int deltaCol = -1; deltaCol <= 1; deltaCol++) {
-        if (deltaCol == 0 || deltaRow == 0) {
-          final int candidateRow = row + deltaRow;
-          final int candidateCol = col + deltaCol;
-
-          if ((candidateRow >= 0 && candidateRow < boardSize) &&
-              (candidateCol >= 0 && candidateCol < boardSize)) {
-            if (board[candidateRow][candidateCol].value == referenceValue) {
-              bool alreadyFound = false;
-              for (int index = 0; index < siblingCells.length; index++) {
-                if ((siblingCells[index][0] == candidateRow) &&
-                    (siblingCells[index][1] == candidateCol)) {
-                  alreadyFound = true;
-                }
-              }
-              if (!alreadyFound) {
-                siblingCells.add([candidateRow, candidateCol]);
-                siblingCells = getSiblingFillableCells(
-                  myProvider,
-                  candidateRow,
-                  candidateCol,
-                  siblingCells,
-                );
-              }
-            }
-          }
-        }
-      }
-    }
-
-    return siblingCells;
-  }
-
-  static bool checkBoardIsSolved(Data myProvider) {
-    final Board board = myProvider.board;
-    final int boardSize = myProvider.boardSize;
-
-    // check grid is fully completed and does not contain conflict
-    int previousValue = board[0][0].value;
-    for (int row = 0; row < boardSize; row++) {
-      for (int col = 0; col < boardSize; col++) {
-        if (board[row][col].value == 0 || board[row][col].value != previousValue) {
-          return false;
-        }
-        previousValue = board[row][col].value;
-      }
-    }
-
-    printlog('-> ok grid solved!');
-
-    return true;
-  }
-}
diff --git a/lib/utils/color_extensions.dart b/lib/utils/color_extensions.dart
new file mode 100644
index 0000000..39c9322
--- /dev/null
+++ b/lib/utils/color_extensions.dart
@@ -0,0 +1,35 @@
+import 'dart:ui';
+
+import 'package:flutter/material.dart';
+
+extension ColorExtension on Color {
+  Color darken([int percent = 40]) {
+    assert(1 <= percent && percent <= 100);
+    final value = 1 - percent / 100;
+    return Color.fromARGB(
+      alpha,
+      (red * value).round(),
+      (green * value).round(),
+      (blue * value).round(),
+    );
+  }
+
+  Color lighten([int percent = 40]) {
+    assert(1 <= percent && percent <= 100);
+    final value = percent / 100;
+    return Color.fromARGB(
+      alpha,
+      (red + ((255 - red) * value)).round(),
+      (green + ((255 - green) * value)).round(),
+      (blue + ((255 - blue) * value)).round(),
+    );
+  }
+
+  Color avg(Color other) {
+    final red = (this.red + other.red) ~/ 2;
+    final green = (this.green + other.green) ~/ 2;
+    final blue = (this.blue + other.blue) ~/ 2;
+    final alpha = (this.alpha + other.alpha) ~/ 2;
+    return Color.fromARGB(alpha, red, green, blue);
+  }
+}
diff --git a/lib/utils/color_theme.dart b/lib/utils/color_theme.dart
index 476f82b..73d2e37 100644
--- a/lib/utils/color_theme.dart
+++ b/lib/utils/color_theme.dart
@@ -1,6 +1,8 @@
+import 'package:colors/config/default_global_settings.dart';
+
 class ColorTheme {
   static const Map<String, List<int>> borderColors = {
-    'default': [
+    DefaultGlobalSettings.skinValueColors: [
       0xffffff,
       0xe63a3f,
       0x708cfd,
diff --git a/lib/utils/game_utils.dart b/lib/utils/game_utils.dart
deleted file mode 100644
index 6b7e2cf..0000000
--- a/lib/utils/game_utils.dart
+++ /dev/null
@@ -1,20 +0,0 @@
-import 'package:colors/provider/data.dart';
-import 'package:colors/utils/board_utils.dart';
-import 'package:colors/utils/tools.dart';
-
-class GameUtils {
-  static void quitGame(Data myProvider) {
-    myProvider.updateGameIsRunning(false);
-  }
-
-  static void startNewGame(Data myProvider) {
-    printlog('Starting game');
-    printlog('- level: ${myProvider.parameterLevel}');
-    printlog('- size: ${myProvider.boardSize}');
-    printlog('- colors: ${myProvider.colorsCount}');
-
-    BoardUtils.createNewBoard(myProvider);
-
-    myProvider.updateGameIsRunning(true);
-  }
-}
diff --git a/lib/utils/tools.dart b/lib/utils/tools.dart
index fd48b2b..8ed7a53 100644
--- a/lib/utils/tools.dart
+++ b/lib/utils/tools.dart
@@ -1,7 +1,15 @@
 import 'package:flutter/foundation.dart';
+import 'package:flutter/material.dart';
 
 void printlog(String message) {
   if (!kReleaseMode) {
     debugPrint(message);
   }
 }
+
+Widget buildImageContainerWidget(String imageAssetCode) {
+  return Image(
+    image: AssetImage('assets/icons/$imageAssetCode.png'),
+    fit: BoxFit.fill,
+  );
+}
diff --git a/pubspec.lock b/pubspec.lock
index 2885f1a..25b5be0 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -5,10 +5,10 @@ packages:
     dependency: transitive
     description:
       name: args
-      sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596
+      sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a"
       url: "https://pub.dev"
     source: hosted
-    version: "2.4.2"
+    version: "2.5.0"
   async:
     dependency: transitive
     description:
@@ -21,10 +21,10 @@ packages:
     dependency: transitive
     description:
       name: bloc
-      sha256: f53a110e3b48dcd78136c10daa5d51512443cea5e1348c9d80a320095fa2db9e
+      sha256: "106842ad6569f0b60297619e9e0b1885c2fb9bf84812935490e6c5275777804e"
       url: "https://pub.dev"
     source: hosted
-    version: "8.1.3"
+    version: "8.1.4"
   characters:
     dependency: transitive
     description:
@@ -61,10 +61,10 @@ packages:
     dependency: "direct main"
     description:
       name: easy_localization
-      sha256: c145aeb6584aedc7c862ab8c737c3277788f47488bfdf9bae0fe112bd0a4789c
+      sha256: "432698c31a488dd64c56d4759f20d04844baba5e9e4f2cb1abb9676257918b17"
       url: "https://pub.dev"
     source: hosted
-    version: "3.0.5"
+    version: "3.0.6"
   easy_logger:
     dependency: transitive
     description:
@@ -106,31 +106,23 @@ packages:
     dependency: "direct main"
     description:
       name: flutter_bloc
-      sha256: "87325da1ac757fcc4813e6b34ed5dd61169973871fdf181d6c2109dd6935ece1"
+      sha256: f0ecf6e6eb955193ca60af2d5ca39565a86b8a142452c5b24d96fb477428f4d2
       url: "https://pub.dev"
     source: hosted
-    version: "8.1.4"
+    version: "8.1.5"
   flutter_lints:
     dependency: "direct dev"
     description:
       name: flutter_lints
-      sha256: e2a421b7e59244faef694ba7b30562e489c2b489866e505074eb005cd7060db7
+      sha256: "9e8c3858111da373efc5aa341de011d9bd23e2c5c5e0c62bccf32438e192d7b1"
       url: "https://pub.dev"
     source: hosted
-    version: "3.0.1"
+    version: "3.0.2"
   flutter_localizations:
     dependency: transitive
     description: flutter
     source: sdk
     version: "0.0.0"
-  flutter_swipe:
-    dependency: "direct main"
-    description:
-      name: flutter_swipe
-      sha256: dc6541bac3a0545ce15a3fa15913f6250532062960bf6b0ad4562d02f14a8545
-      url: "https://pub.dev"
-    source: hosted
-    version: "1.0.1"
   flutter_web_plugins:
     dependency: transitive
     description: flutter
@@ -148,10 +140,10 @@ packages:
     dependency: transitive
     description:
       name: http
-      sha256: a2bbf9d017fcced29139daa8ed2bba4ece450ab222871df93ca9eec6f80c34ba
+      sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938"
       url: "https://pub.dev"
     source: hosted
-    version: "1.2.0"
+    version: "1.2.1"
   http_parser:
     dependency: transitive
     description:
@@ -164,10 +156,10 @@ packages:
     dependency: "direct main"
     description:
       name: hydrated_bloc
-      sha256: "00a2099680162e74b5a836b8a7f446e478520a9cae9f6032e028ad8129f4432d"
+      sha256: af35b357739fe41728df10bec03aad422cdc725a1e702e03af9d2a41ea05160c
       url: "https://pub.dev"
     source: hosted
-    version: "9.1.4"
+    version: "9.1.5"
   intl:
     dependency: transitive
     description:
@@ -208,32 +200,24 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "1.0.0"
-  overlay_support:
-    dependency: "direct main"
-    description:
-      name: overlay_support
-      sha256: fc39389bfd94e6985e1e13b2a88a125fc4027608485d2d4e2847afe1b2bb339c
-      url: "https://pub.dev"
-    source: hosted
-    version: "2.1.0"
   package_info_plus:
     dependency: "direct main"
     description:
       name: package_info_plus
-      sha256: "88bc797f44a94814f2213db1c9bd5badebafdfb8290ca9f78d4b9ee2a3db4d79"
+      sha256: b93d8b4d624b4ea19b0a5a208b2d6eff06004bc3ce74c06040b120eeadd00ce0
       url: "https://pub.dev"
     source: hosted
-    version: "5.0.1"
+    version: "8.0.0"
   package_info_plus_platform_interface:
     dependency: transitive
     description:
       name: package_info_plus_platform_interface
-      sha256: "9bc8ba46813a4cc42c66ab781470711781940780fd8beddd0c3da62506d3a6c6"
+      sha256: f49918f3433a3146047372f9d4f1f847511f2acd5cd030e1f44fe5a50036b70e
       url: "https://pub.dev"
     source: hosted
-    version: "2.0.1"
+    version: "3.0.0"
   path:
-    dependency: "direct main"
+    dependency: transitive
     description:
       name: path
       sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
@@ -244,18 +228,18 @@ packages:
     dependency: "direct main"
     description:
       name: path_provider
-      sha256: b27217933eeeba8ff24845c34003b003b2b22151de3c908d0e679e8fe1aa078b
+      sha256: c9e7d3a4cd1410877472158bee69963a4579f78b68c65a2b7d40d1a7a88bb161
       url: "https://pub.dev"
     source: hosted
-    version: "2.1.2"
+    version: "2.1.3"
   path_provider_android:
     dependency: transitive
     description:
       name: path_provider_android
-      sha256: "477184d672607c0a3bf68fbbf601805f92ef79c82b64b4d6eb318cbca4c48668"
+      sha256: a248d8146ee5983446bf03ed5ea8f6533129a12b11f12057ad1b4a67a2b3b41d
       url: "https://pub.dev"
     source: hosted
-    version: "2.2.2"
+    version: "2.2.4"
   path_provider_foundation:
     dependency: transitive
     description:
@@ -305,7 +289,7 @@ packages:
     source: hosted
     version: "2.1.8"
   provider:
-    dependency: "direct main"
+    dependency: transitive
     description:
       name: provider
       sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c
@@ -313,21 +297,21 @@ packages:
     source: hosted
     version: "6.1.2"
   shared_preferences:
-    dependency: "direct main"
+    dependency: transitive
     description:
       name: shared_preferences
-      sha256: "81429e4481e1ccfb51ede496e916348668fd0921627779233bd24cc3ff6abd02"
+      sha256: d3bbe5553a986e83980916ded2f0b435ef2e1893dfaa29d5a7a790d0eca12180
       url: "https://pub.dev"
     source: hosted
-    version: "2.2.2"
+    version: "2.2.3"
   shared_preferences_android:
     dependency: transitive
     description:
       name: shared_preferences_android
-      sha256: "8568a389334b6e83415b6aae55378e158fbc2314e074983362d20c562780fb06"
+      sha256: "1ee8bf911094a1b592de7ab29add6f826a7331fb854273d55918693d5364a1f2"
       url: "https://pub.dev"
     source: hosted
-    version: "2.2.1"
+    version: "2.2.2"
   shared_preferences_foundation:
     dependency: transitive
     description:
@@ -356,10 +340,10 @@ packages:
     dependency: transitive
     description:
       name: shared_preferences_web
-      sha256: "7b15ffb9387ea3e237bb7a66b8a23d2147663d391cafc5c8f37b2e7b4bde5d21"
+      sha256: "9aee1089b36bd2aafe06582b7d7817fd317ef05fc30e6ba14bff247d0933042a"
       url: "https://pub.dev"
     source: hosted
-    version: "2.2.2"
+    version: "2.3.0"
   shared_preferences_windows:
     dependency: transitive
     description:
@@ -433,18 +417,18 @@ packages:
     dependency: transitive
     description:
       name: web
-      sha256: "4188706108906f002b3a293509234588823c8c979dc83304e229ff400c996b05"
+      sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27"
       url: "https://pub.dev"
     source: hosted
-    version: "0.4.2"
+    version: "0.5.1"
   win32:
     dependency: transitive
     description:
       name: win32
-      sha256: "464f5674532865248444b4c3daca12bd9bf2d7c47f759ce2617986e7229494a8"
+      sha256: "0eaf06e3446824099858367950a813472af675116bf63f008a4c2a75ae13e9cb"
       url: "https://pub.dev"
     source: hosted
-    version: "5.2.0"
+    version: "5.5.0"
   xdg_directories:
     dependency: transitive
     description:
@@ -454,5 +438,5 @@ packages:
     source: hosted
     version: "1.0.4"
 sdks:
-  dart: ">=3.3.0-279.1.beta <4.0.0"
-  flutter: ">=3.16.0"
+  dart: ">=3.3.0 <4.0.0"
+  flutter: ">=3.19.0"
diff --git a/pubspec.yaml b/pubspec.yaml
index 5e4adf9..e6b8af0 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -2,7 +2,7 @@ name: colors
 description: Fill the board, a colorfull game!
 
 publish_to: 'none'
-version: 0.0.38+38
+version: 0.0.39+39
 
 environment:
   sdk: '^3.0.0'
@@ -14,15 +14,10 @@ dependencies:
   easy_localization: ^3.0.1
   equatable: ^2.0.5
   flutter_bloc: ^8.1.1
-  flutter_swipe: ^1.0.1
   hive: ^2.2.3
   hydrated_bloc: ^9.0.0
-  overlay_support: ^2.1.0
-  shared_preferences: ^2.2.1
-  package_info_plus: ^5.0.1
-  path: ^1.9.0
+  package_info_plus: ^8.0.0
   path_provider: ^2.0.11
-  provider: ^6.0.5
   unicons: ^2.1.1
 
 dev_dependencies:
@@ -32,7 +27,6 @@ flutter:
   uses-material-design: true
   assets:
     - assets/icons/
-    - assets/skins/
     - assets/translations/
 
   fonts:
-- 
GitLab