diff --git a/Makefile b/Makefile
index 8ccb1dea4b9b576b2ad19bcef74b14c310ffd1d0..de256c8bdbdc669e1f4ccd71ff9ee2840240d0ac 100644
--- a/Makefile
+++ b/Makefile
@@ -1,28 +1,81 @@
 CC = g++
 CFLAGS = -std=c++11 -Wall -I include
-LDFLAGS = -lncurses
+LDFLAGS = -lncurses -lSDL2 -lSDL2_mixer
 
+# Directories
 SRCDIR = src
+INCDIR = include
 OBJDIR = obj
 BINDIR = bin
+RESDIR = res
 
-# Source files
+# Create directories if they don't exist
+$(shell mkdir -p $(OBJDIR) $(BINDIR) $(RESDIR))
+
+# Source files and object files
 SOURCES = $(wildcard $(SRCDIR)/*.cpp)
 OBJECTS = $(patsubst $(SRCDIR)/%.cpp,$(OBJDIR)/%.o,$(SOURCES))
 EXECUTABLE = $(BINDIR)/2048
 
-# Create directories if they don't exist
-$(shell mkdir -p $(OBJDIR) $(BINDIR))
+# Resource files
+SOUNDDIR = $(RESDIR)/sounds
+MUSICDIR = $(RESDIR)/music
+IMGDIR = $(RESDIR)/images
+
+# Main target
+all: directories resources $(EXECUTABLE)
 
-all: $(EXECUTABLE)
+# Create necessary directories
+directories:
+	mkdir -p $(OBJDIR) $(BINDIR) $(RESDIR) $(SOUNDDIR) $(MUSICDIR) $(IMGDIR)
 
+# Create resource directories and copy resource files
+resources:
+	@echo "Copying resource files..."
+	@# Create placeholder sound files
+	@if [ ! -f $(SOUNDDIR)/move.wav ]; then \
+		echo "Creating placeholder sound files..."; \
+		touch $(SOUNDDIR)/move.wav; \
+		touch $(SOUNDDIR)/merge.wav; \
+		touch $(SOUNDDIR)/spawn.wav; \
+		touch $(SOUNDDIR)/gameover.wav; \
+		touch $(SOUNDDIR)/victory.wav; \
+		touch $(SOUNDDIR)/select.wav; \
+		touch $(SOUNDDIR)/navigate.wav; \
+		touch $(SOUNDDIR)/powerup.wav; \
+	fi
+	@# Create placeholder music files
+	@if [ ! -f $(MUSICDIR)/menu.mp3 ]; then \
+		echo "Creating placeholder music files..."; \
+		touch $(MUSICDIR)/menu.mp3; \
+		touch $(MUSICDIR)/gameplay.mp3; \
+		touch $(MUSICDIR)/gameover.mp3; \
+		touch $(MUSICDIR)/victory.mp3; \
+	fi
+
+# Link the executable
 $(EXECUTABLE): $(OBJECTS)
 	$(CC) $(OBJECTS) -o $@ $(LDFLAGS)
+	@echo "Build successful! Run with: $(EXECUTABLE)"
 
+# Compile object files
 $(OBJDIR)/%.o: $(SRCDIR)/%.cpp
 	$(CC) $(CFLAGS) -c $< -o $@
 
+# Clean build files
 clean:
 	rm -rf $(OBJDIR)/*.o $(EXECUTABLE)
 
-.PHONY: all clean
\ No newline at end of file
+# Clean all generated files including resources
+clean-all: clean
+	rm -rf $(RESDIR)/*
+
+# Run the executable
+run: all
+	$(EXECUTABLE)
+
+# Generate documentation using Doxygen
+docs:
+	doxygen Doxyfile
+
+.PHONY: all directories resources clean clean-all run docs
\ No newline at end of file
diff --git a/README.md b/README.md
index 24661b6fdf5bd877ad027f014b08bcd6f3247e1a..ba0361d9a945e191110e3496391b04074c2c81c0 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,97 @@
-# Programming in c++ Assignment
+# Enhanced 2048 Game by Jamal Enoime
+
+## Project Structure
+```
+2048-game/
+├── bin/                    # Compiled executable
+├── include/                # Header files
+│   ├── 2048.hpp           # Game logic header
+│   ├── Tile.hpp           # Tile class header
+│   ├── GameMode.hpp       # Game modes header
+│   ├── UI.hpp             # User interface header
+│   ├── Animations.hpp     # Animation system header
+│   └── SoundSystem.hpp    # Sound system header
+├── src/                    # Source files
+│   ├── 2048.cpp           # Game logic implementation
+│   ├── Tile.cpp           # Tile class implementation
+│   ├── GameMode.cpp       # Game modes implementation
+│   ├── UI.cpp             # User interface implementation
+│   ├── Animations.cpp     # Animation system implementation
+│   ├── SoundSystem.cpp    # Sound system implementation
+│   └── main.cpp           # Entry point
+├── obj/                    # Object files (generated during build)
+├── res/                    # Resource files
+│   ├── sounds/            # Sound effects
+│   ├── music/             # Background music
+│   └── images/            # Images and GIFs
+├── Makefile               # Build configuration
+└── README.md              # Project documentation
+```
+
+## Features
+- **Modern UI**: Sleek and responsive user interface with animations and visual effects
+- **Multiple Game Modes**:
+  - **Classic**: Traditional 2048 gameplay
+  - **Timed**: Race against the clock
+  - **Power-Up**: Use special abilities to enhance gameplay
+  - **Challenge**: Complete specific objectives with constraints
+  - **Zen**: Relaxed mode with no game over
+- **Animations and Effects**:
+  - Smooth tile movements and merges
+  - Particle effects for special events
+  - Confetti celebration for victories
+  - Text effects and transitions between screens
+- **Sound System**:
+  - Sound effects for game actions
+  - Background music for different game states
+- **Customization**:
+  - Multiple color themes
+  - High contrast mode for accessibility
+  - Toggle for sounds, music, and animations
+- **Tutorial**: Interactive guide to teach new players
+- **Game Statistics**: Track high scores and performance
+
+## Dependencies
+- NCurses: For terminal-based UI
+- SDL2 and SDL2_mixer: For sound and music
+
+## Building and Running
+```bash
+# Build the project
+make
+
+# Run the game
+make run
+
+# Clean build files
+make clean
+
+# Clean all generated files including resources
+make clean-all
+```
+
+## Controls
+- Arrow keys: Move tiles / Navigate menus
+- Enter: Select menu options
+- P: Pause game
+- R: Restart game
+- Q/ESC: Quit/Return to menu
+
+## Special Mode Controls
+- Power-Up Mode:
+  - 1: Activate double score
+  - 2: Clear a row
+  - 3: Undo move
+  - 4: Upgrade a tile
+
+- Zen Mode:
+  - C: Toggle color shift effect
+
+## Credits
+Created by Jamal Enoime
+
+Sound effects from freesound.org  
+Music from bensound.com
+
+## License
+This project is open source and available under the MIT License.
\ No newline at end of file
diff --git a/bin/2048 b/bin/2048
deleted file mode 100755
index 646381373d323dc17565e3794d0c5796fde902f5..0000000000000000000000000000000000000000
Binary files a/bin/2048 and /dev/null differ
diff --git a/bin/2048-game b/bin/2048-game
new file mode 100755
index 0000000000000000000000000000000000000000..507e14c6963aaf6291be9e0c8e7266ebca9ec7ef
Binary files /dev/null and b/bin/2048-game differ
diff --git a/include/2048.hpp b/include/2048.hpp
index a3b667aae7bc80eefbef24e52fcd3d12370375a4..c3528833c1e331d68d07a1fbf82fd40cfa12ee9d 100644
--- a/include/2048.hpp
+++ b/include/2048.hpp
@@ -2,30 +2,76 @@
 #define GAME2048_HPP
 
 #include <vector>
+#include <array>
+#include <functional>
 #include "Tile.hpp"
 
 #define SIZE 4
 
+// Forward declarations
+class UI;
+
+// Event types for observers
+enum class GameEvent {
+    TILE_MOVED,
+    TILE_MERGED,
+    TILE_SPAWNED,
+    SCORE_CHANGED,
+    GAME_WON,
+    GAME_OVER
+};
+
+// Game state observer pattern
+using GameEventCallback = std::function<void(GameEvent, int, int, int)>;
+
 class Game2048 {
 private:
-    Tile board[SIZE][SIZE];
+    std::array<std::array<Tile, SIZE>, SIZE> board;
+    std::array<std::array<Tile, SIZE>, SIZE> previousBoard;
     bool moved;
     int score;
+    int previousScore;
+    int highScore;
+    std::vector<GameEventCallback> observers;
 
     void spawnTile();
     void addToScore(int value);
+    void notifyObservers(GameEvent event, int row = -1, int col = -1, int value = 0);
+    void saveBoardState();
 
 public:
     Game2048();
-    void resetBoard(); // Made public for restart functionality
-    void drawBoard();
+    void resetBoard();
+    
+    // Movement methods
     void moveLeft();
     void moveRight();
     void moveUp();
     void moveDown();
-    bool canMove();
+    
+    // Game state methods
+    bool canMove() const;
+    bool hasWon() const;
     int getScore() const;
-    const Tile (*getBoard() const)[SIZE];
+    int getHighScore() const;
+    void undoMove();
+    
+    // Special actions for power-ups
+    void clearRow(int row);
+    void clearColumn(int col);
+    void doubleScoreTile(int row, int col);
+    void upgradeTile(int row, int col);
+    
+    // Board access
+    const std::array<std::array<Tile, SIZE>, SIZE>& getBoard() const;
+    
+    // Observer pattern methods
+    void addObserver(GameEventCallback callback);
+    void removeAllObservers();
+
+    // Save/Load game state
+    bool saveGame(const std::string& filename) const;
+    bool loadGame(const std::string& filename);
 };
 
 #endif
\ No newline at end of file
diff --git a/include/Animations.hpp b/include/Animations.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..e711b393ae1d28cf46110de458fbbcc25d1eaace
--- /dev/null
+++ b/include/Animations.hpp
@@ -0,0 +1,167 @@
+#ifndef ANIMATIONS_HPP
+#define ANIMATIONS_HPP
+
+#include <vector>
+#include <functional>
+#include <string>
+#include <ncurses.h>
+#include <cmath>
+
+// Define animation types
+enum class AnimationType {
+    SLIDE,
+    MERGE,
+    SPAWN,
+    PULSE,
+    FADE_IN,
+    FADE_OUT,
+    SHAKE,
+    FLASH,
+    PARTICLE
+};
+
+// Define easing functions
+enum class EasingType {
+    LINEAR,
+    EASE_IN,
+    EASE_OUT,
+    EASE_IN_OUT,
+    ELASTIC,
+    BOUNCE
+};
+
+// Forward declarations
+class Game2048;
+class Particle;
+
+// Animation class to handle visual effects
+class Animation {
+private:
+    AnimationType type;
+    int row, col;
+    int value;
+    float duration;
+    float elapsed;
+    bool completed;
+    EasingType easing;
+    
+    // Callback when animation completes
+    std::function<void()> onComplete;
+    
+    // For slide animation
+    int sourceRow, sourceCol;
+    int targetRow, targetCol;
+    
+    // For particle animation
+    std::vector<Particle> particles;
+    
+    // Calculate eased progress
+    float getEasedProgress() const;
+
+public:
+    Animation(AnimationType type, int row, int col, int value, 
+              float duration = 0.3f, EasingType easing = EasingType::EASE_OUT);
+    
+    bool update(float deltaTime);
+    void draw(WINDOW* win);
+    void setCallback(std::function<void()> callback);
+    
+    // Animation setup methods
+    void setupSlide(int fromRow, int fromCol, int toRow, int toCol);
+    void setupMerge();
+    void setupSpawn();
+    void setupPulse();
+    void setupFade(bool fadeIn);
+    void setupShake();
+    void setupFlash();
+    void setupParticles(int count, bool isMerge = false);
+    
+    // Getters
+    AnimationType getType() const { return type; }
+    int getRow() const { return row; }
+    int getCol() const { return col; }
+    int getValue() const { return value; }
+    float getProgress() const { return elapsed / duration; }
+    bool isCompleted() const { return completed; }
+    
+    // Static helper method to get color for a value
+    static int getColorForValue(int value);
+};
+
+// Particle system for effects
+class Particle {
+private:
+    float x, y;
+    float vx, vy;
+    float ax, ay;
+    float lifetime;
+    float maxLifetime;
+    float size;
+    int color;
+    char symbol;
+    bool fading;
+
+public:
+    Particle(float x, float y, float vx, float vy, 
+             float lifetime, int color, char symbol = '*', bool fading = true);
+    
+    bool update(float deltaTime);
+    void draw(WINDOW* win);
+    
+    float getX() const { return x; }
+    float getY() const { return y; }
+    float getLifetimeRatio() const { return lifetime / maxLifetime; }
+};
+
+// Animation manager to handle multiple animations
+class AnimationManager {
+private:
+    std::vector<Animation> animations;
+    float backgroundEffectTimer;
+    bool enableBackgroundEffects;
+    
+    // GIF background related
+    bool hasGifBackground;
+    std::vector<std::string> gifFrames;
+    float gifFrameDuration;
+    float gifFrameTimer;
+    int currentGifFrame;
+    
+    // For temporary effects
+    struct TransitionEffect {
+        float duration;
+        float elapsed;
+        std::string type; // "fade", "slide", "sparkle"
+    };
+    std::vector<TransitionEffect> transitionEffects;
+
+public:
+    AnimationManager();
+    
+    void update(float deltaTime);
+    void draw(WINDOW* mainWin, WINDOW* gameWin);
+    
+    // Animation creation methods
+    void addSlideAnimation(int fromRow, int fromCol, int toRow, int toCol, int value);
+    void addMergeAnimation(int row, int col, int value);
+    void addSpawnAnimation(int row, int col, int value);
+    void addScoreAnimation(int score, int prevScore);
+    void addGameOverAnimation();
+    void addVictoryAnimation();
+    void addTransitionEffect(const std::string& type, float duration = 0.5f);
+    void addParticleEffect(float x, float y, int color, int count); // Added this declaration
+    
+    // Background and effects
+    void drawBackground(WINDOW* win);
+    void toggleBackgroundEffects();
+    
+    // GIF background methods
+    bool loadGifBackground(const std::string& filePath);
+    void drawGifBackground(WINDOW* win);
+    
+    // Clear animations
+    void clearAnimations();
+    bool hasActiveAnimations() const;
+};
+
+#endif
\ No newline at end of file
diff --git a/include/GameMode.hpp b/include/GameMode.hpp
index a815dde893bad728557d71e6dd424dcc142c1ef5..e93a5c9086d6d871c6667e5a8b5cdc8c2dc36bdd 100644
--- a/include/GameMode.hpp
+++ b/include/GameMode.hpp
@@ -2,40 +2,55 @@
 #define GAMEMODE_HPP
 
 #include <string>
+#include <vector>
+#include <ncurses.h> // Added for KEY_ constants
+#include "2048.hpp"
 
 enum class GameModeType {
     CLASSIC,
     TIMED,
     POWERUP,
     CHALLENGE,
+    ZEN,
     TUTORIAL
 };
 
+// Base abstract class for all game modes
 class GameMode {
 protected:
     GameModeType type;
     std::string name;
     std::string description;
+    bool gameOver;
+    bool gameWon;
 
 public:
     GameMode(GameModeType type, const std::string& name, const std::string& description);
     virtual ~GameMode() = default;
     
-    virtual void initialize() = 0;
-    virtual bool update(float deltaTime) = 0;
+    // Pure virtual methods that derived classes must implement
+    virtual void initialize(Game2048& game) = 0;
+    virtual bool update(Game2048& game, float deltaTime) = 0;
+    virtual void handleInput(Game2048& game, int key) = 0;
     virtual void render() = 0;
     
+    // Common methods for all modes
     GameModeType getType() const;
     const std::string& getName() const;
     const std::string& getDescription() const;
+    bool isGameOver() const;
+    bool isGameWon() const;
+    virtual void setGameOver(bool over);
+    virtual void setGameWon(bool won);
 };
 
 // Classic mode - original 2048 gameplay
 class ClassicMode : public GameMode {
 public:
     ClassicMode();
-    void initialize() override;
-    bool update(float deltaTime) override;
+    void initialize(Game2048& game) override;
+    bool update(Game2048& game, float deltaTime) override;
+    void handleInput(Game2048& game, int key) override;
     void render() override;
 };
 
@@ -44,31 +59,48 @@ class TimedMode : public GameMode {
 private:
     float timeLimit;
     float timeRemaining;
+    float bonusTimePerMerge;
     
 public:
     TimedMode();
-    void initialize() override;
-    bool update(float deltaTime) override;
+    void initialize(Game2048& game) override;
+    bool update(Game2048& game, float deltaTime) override;
+    void handleInput(Game2048& game, int key) override;
     void render() override;
     
     float getTimeRemaining() const;
+    void addTime(float seconds);
 };
 
 // PowerUp mode - special abilities and boosters
 class PowerUpMode : public GameMode {
 private:
-    int powerUpCount;
+    int doubleScorePowerups;
+    int clearRowPowerups;
+    int undoMovePowerups;
+    int upgradeTilePowerups;
+    
     bool doubleScoreActive;
-    bool removeRowActive;
-    bool freezeTimeActive;
+    int doubleScoreTurnsLeft;
     
 public:
     PowerUpMode();
-    void initialize() override;
-    bool update(float deltaTime) override;
+    void initialize(Game2048& game) override;
+    bool update(Game2048& game, float deltaTime) override;
+    void handleInput(Game2048& game, int key) override;
     void render() override;
     
-    void activatePowerUp(int type);
+    bool activateDoubleScore();
+    bool clearRow(Game2048& game, int row);
+    bool undoMove(Game2048& game);
+    bool upgradeTile(Game2048& game, int row, int col);
+    
+    int getDoubleScorePowerups() const;
+    int getClearRowPowerups() const;
+    int getUndoMovePowerups() const;
+    int getUpgradeTilePowerups() const;
+    bool isDoubleScoreActive() const;
+    int getDoubleScoreTurnsLeft() const;
 };
 
 // Challenge mode - reach specific goals
@@ -78,12 +110,45 @@ private:
     int targetTile;
     int movesLimit;
     int movesUsed;
+    int currentLevel;
     
 public:
     ChallengeMode();
-    void initialize() override;
-    bool update(float deltaTime) override;
+    void initialize(Game2048& game) override;
+    bool update(Game2048& game, float deltaTime) override;
+    void handleInput(Game2048& game, int key) override;
     void render() override;
+    
+    void incrementMoves();
+    bool checkVictory(const Game2048& game) const;
+    bool hasTargetTile(const Game2048& game) const;
+    void nextLevel(Game2048& game);
+    
+    int getTargetScore() const;
+    int getTargetTile() const;
+    int getMovesLimit() const;
+    int getMovesUsed() const;
+    int getMovesRemaining() const;
+    int getCurrentLevel() const;
+};
+
+// Zen mode - relaxed gameplay with no game over
+class ZenMode : public GameMode {
+private:
+    bool colorShiftEnabled;
+    float colorCycleTime;
+    float currentColorTime;
+    
+public:
+    ZenMode();
+    void initialize(Game2048& game) override;
+    bool update(Game2048& game, float deltaTime) override;
+    void handleInput(Game2048& game, int key) override;
+    void render() override;
+    
+    float getCurrentColorPhase() const;
+    bool isColorShiftEnabled() const;
+    void toggleColorShift();
 };
 
 // Tutorial mode - learn to play
@@ -91,14 +156,19 @@ class TutorialMode : public GameMode {
 private:
     int tutorialStep;
     bool waitingForInput;
+    std::vector<std::string> tutorialMessages;
     
 public:
     TutorialMode();
-    void initialize() override;
-    bool update(float deltaTime) override;
+    void initialize(Game2048& game) override;
+    bool update(Game2048& game, float deltaTime) override;
+    void handleInput(Game2048& game, int key) override;
     void render() override;
     
     void advanceTutorialStep();
+    int getTutorialStep() const;
+    const std::string& getCurrentMessage() const;
+    bool isWaitingForInput() const;
 };
 
 #endif
\ No newline at end of file
diff --git a/include/SoundSystem.hpp b/include/SoundSystem.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..826b3a3d90793640ab03e4a107085b1248f08444
--- /dev/null
+++ b/include/SoundSystem.hpp
@@ -0,0 +1,93 @@
+#ifndef SOUNDSYSTEM_HPP
+#define SOUNDSYSTEM_HPP
+
+#include <string>
+#include <map>
+#include <memory>
+#include <vector>
+
+// Forward declaration for SDL dependencies
+struct Mix_Chunk;
+typedef struct _Mix_Music Mix_Music;
+
+enum class SoundEffect {
+    MOVE,
+    MERGE,
+    SPAWN,
+    GAMEOVER,
+    VICTORY,
+    MENU_SELECT,
+    MENU_NAVIGATE,
+    POWERUP_ACTIVATE
+};
+
+enum class MusicTrack {
+    MENU,
+    GAMEPLAY,
+    GAMEOVER,
+    VICTORY
+};
+
+// Simple sound system using SDL_mixer
+class SoundSystem {
+private:
+    bool initialized;
+    bool soundEnabled;
+    bool musicEnabled;
+    float soundVolume;
+    float musicVolume;
+    
+    // Sound effect storage
+    std::map<SoundEffect, Mix_Chunk*> soundEffects;
+    
+    // Music track storage
+    std::map<MusicTrack, Mix_Music*> musicTracks;
+    MusicTrack currentMusic;
+    
+    // Sound effect queue (for when multiple sound effects happen in the same frame)
+    struct QueuedSound {
+        SoundEffect effect;
+        float delay;
+    };
+    std::vector<QueuedSound> soundQueue;
+    
+    // Initialization and cleanup
+    bool initSDL();
+    void closeSDL();
+    
+    // File loading helpers
+    bool loadSoundEffect(SoundEffect effect, const std::string& filePath);
+    bool loadMusicTrack(MusicTrack track, const std::string& filePath);
+
+public:
+    SoundSystem();
+    ~SoundSystem();
+    
+    // Initialization
+    bool initialize();
+    
+    // Sound control
+    void playSound(SoundEffect effect);
+    void queueSound(SoundEffect effect, float delay = 0.0f);
+    void playMusic(MusicTrack track, bool loop = true);
+    void stopMusic();
+    void pauseMusic();
+    void resumeMusic();
+    
+    // Volume control
+    void setSoundVolume(float volume); // 0.0 to 1.0
+    void setMusicVolume(float volume); // 0.0 to 1.0
+    float getSoundVolume() const;
+    float getMusicVolume() const;
+    
+    // Enable/disable
+    void enableSound(bool enabled);
+    void enableMusic(bool enabled);
+    bool isSoundEnabled() const;
+    bool isMusicEnabled() const;
+    
+    // Update (process queued sounds)
+    void update(float deltaTime);
+};
+
+#endif
\ No newline at end of file
diff --git a/include/Tile.hpp b/include/Tile.hpp
index b2f33e5fd0b408722c597840dd94d39e2cf8d7c0..7d0abe579d5bc033f30bf43c449569502ba0802d 100644
--- a/include/Tile.hpp
+++ b/include/Tile.hpp
@@ -1,15 +1,37 @@
 #ifndef TILE_HPP
 #define TILE_HPP
 
+#include <string>
+
 class Tile {
 private:
     int value;
-
+    bool mergedThisTurn;
+    bool isNew;
+    float animationProgress;
+    
 public:
     Tile();
+    
+    // Basic operations
     void setValue(int val);
     int getValue() const;
-    // Add operators to make working with Tiles easier
+    void setMerged(bool merged);
+    bool getMerged() const;
+    void setNew(bool newTile);
+    bool getNew() const;
+    
+    // Animation management
+    void setAnimationProgress(float progress);
+    float getAnimationProgress() const;
+    void resetAnimation();
+    
+    // Color and style helpers
+    std::string getColorCode() const;
+    std::string getBackgroundColor() const;
+    std::string getForegroundColor() const;
+    
+    // Operators
     bool operator==(const Tile& other) const;
     Tile& operator*=(int multiplier);
     Tile& operator=(const Tile& other);
diff --git a/include/UI.hpp b/include/UI.hpp
index 6f583b0e559456cf98f7c6f4f48648da2531801b..c1d1249e5171a074c0f81e142396ccdd932d06c4 100644
--- a/include/UI.hpp
+++ b/include/UI.hpp
@@ -4,26 +4,50 @@
 #include <ncurses.h>
 #include <vector>
 #include <string>
+#include <memory>
+#include <map>
 #include "2048.hpp"
 #include "GameMode.hpp"
+#include "Animations.hpp"
+#include "SoundSystem.hpp"
 
+// UI states
 enum class UIState {
     MAIN_MENU,
     MODE_SELECTION,
     GAME_PLAYING,
     PAUSE_MENU,
     GAME_OVER,
-    TUTORIAL
+    VICTORY,
+    TUTORIAL,
+    SETTINGS,
+    CREDITS,
+    EXIT_CONFIRM
+};
+
+// Text effects for UI elements
+struct TextEffect {
+    float duration;
+    float elapsed;
+    std::string type; // "fade", "pulse", "rainbow", "typing"
+    std::string text;
+    int row, col;
+    bool centered;
+    int color;
 };
 
 class UI {
 private:
+    // State management
     UIState currentState;
+    UIState previousState;
     int selectedMenuOption;
+    
+    // Menu options
     std::vector<std::string> mainMenuOptions;
     std::vector<std::string> modeSelectionOptions;
     std::vector<std::string> pauseMenuOptions;
-    GameModeType currentGameMode;
+    std::vector<std::string> settingsOptions;
     
     // Window management
     WINDOW* mainWindow;
@@ -31,51 +55,156 @@ private:
     WINDOW* scoreWindow;
     WINDOW* infoWindow;
     
-    // For animations and transitions
-    float transitionTimer;
-    bool isTransitioning;
-
-public:
-    UI();
-    ~UI();
+    // Game state
+    Game2048 game;
+    GameModeType currentGameMode;
+    
+    // Mode instances
+    std::unique_ptr<GameMode> gameMode;
+    
+    // Animation system
+    AnimationManager animations;
+    
+    // Sound system
+    SoundSystem sounds;
+    
+    // Text effects
+    std::vector<TextEffect> textEffects;
+    
+    // Background and color management
+    float backgroundEffectTimer;
+    std::string backgroundImage;
+    bool useCustomColors;
+    
+    // Settings
+    bool soundEnabled;
+    bool musicEnabled;
+    bool animationsEnabled;
+    bool highContrastMode;
+    
+    // Theme management
+    struct Theme {
+        std::string name;
+        std::map<int, int> tileForegroundColors;
+        std::map<int, int> tileBackgroundColors;
+        int menuColor;
+        int backgroundColor;
+        int textColor;
+    };
+    std::vector<Theme> themes;
+    int currentTheme;
+    
+    // Confetti for victory
+    struct Confetti {
+        float x, y;
+        float vx, vy;
+        float angle;
+        float rotation;
+        float size;
+        int color;
+        char symbol;
+        float lifetime;
+    };
+    std::vector<Confetti> confetti;
+    
+    // Credits
+    std::vector<std::string> credits;
+    float creditsScrollY;
+    
+    // Helper methods
+    void createWindows();
+    void destroyWindows();
+    void initializeThemes();
+    void applyTheme(int themeIndex);
+    
+    // Drawing helpers
+    void drawCenteredText(WINDOW* win, int y, const std::string& text, bool highlight = false);
+    void drawBorderedWindow(WINDOW* win, const std::string& title = "");
+    void drawProgressBar(WINDOW* win, int y, int x, int width, float progress, int colorPair);
+    void drawTile(WINDOW* win, int row, int col, int value);
     
-    void initialize();
-    void drawBoard(const Game2048& game);
-    void handleInput(Game2048& game);
-    void showGameOver(Game2048& game);
-    void displayScore(const Game2048& game);
-    void displayInstructions();
+    // Event handlers
+    void handleMainMenuInput();
+    void handleModeSelectionInput();
+    void handleGameInput();
+    void handlePauseMenuInput();
+    void handleSettingsInput();
+    void handleTutorialInput();
+    void handleCreditsInput();
+    void handleExitConfirmInput();
     
-    // New menu-related methods
+    // Menu drawing
     void drawMainMenu();
     void drawModeSelection();
     void drawPauseMenu();
-    void handleMenuInput();
+    void drawSettings();
+    void drawCredits();
+    void drawExitConfirm();
     
-    // Game mode management
-    void setGameMode(GameModeType mode);
-    GameModeType getGameMode() const;
+    // Game UI
+    void drawBoard();
+    void drawScore();
+    void drawInfo();
+    void drawTutorial();
+    void drawGameOver();
+    void drawVictory();
     
-    // Tutorial-specific rendering
-    void drawTutorial(int step);
+    // Effects
+    void updateTextEffects(float deltaTime);
+    void drawTextEffects();
+    void addTextEffect(const std::string& text, int row, int col, const std::string& type, float duration, int color, bool centered = true);
+    void updateConfetti(float deltaTime);
+    void drawConfetti();
+    void addConfetti(int amount);
     
-    // PowerUp mode-specific UI
-    void drawPowerUpInterface(const PowerUpMode& powerUpMode);
+    // Mode-specific UI
+    void drawTimedModeUI();
+    void drawPowerUpModeUI();
+    void drawChallengeModeUI();
+    void drawZenModeUI();
     
-    // Timed mode-specific UI
-    void drawTimerInterface(float timeRemaining);
+    // Input helpers
+    void processGameModeInput(int key);
+    
+    // Game event callbacks
+    void onTileMoved(int fromRow, int fromCol, int toRow, int toCol, int value);
+    void onTileMerged(int row, int col, int value);
+    void onTileSpawned(int row, int col, int value);
+    void onScoreChanged(int newScore, int prevScore);
+    void onGameOver();
+    void onVictory();
+
+public:
+    UI();
+    ~UI();
     
-    // Challenge mode-specific UI
-    void drawChallengeInterface(int targetScore, int targetTile, int movesRemaining);
+    // Initialization
+    bool initialize();
+    
+    // Main game loop
+    void run();
     
     // State management
     void setState(UIState newState);
     UIState getState() const;
     
-    // Utility methods
-    void drawCenteredText(WINDOW* win, int y, const std::string& text, bool highlight = false);
-    void createWindows();
-    void destroyWindows();
+    // Game mode management
+    void setGameMode(GameModeType mode);
+    GameModeType getGameMode() const;
+    
+    // Theme management
+    void setTheme(int themeIndex);
+    int getThemeCount() const;
+    std::string getThemeName(int index) const;
+    
+    // Settings
+    void toggleSound();
+    void toggleMusic();
+    void toggleAnimations();
+    void toggleHighContrast();
+    
+    // Background
+    bool setBackgroundImage(const std::string& filePath);
 };
 
 #endif
\ No newline at end of file
diff --git a/obj/2048.o b/obj/2048.o
index 4cf51d0ff32df9b8ccd4253c4c7450419797ce66..6c22e616c8884232d7466bc891bc63e7d3d2892e 100644
Binary files a/obj/2048.o and b/obj/2048.o differ
diff --git a/obj/Animations.o b/obj/Animations.o
new file mode 100644
index 0000000000000000000000000000000000000000..b0e1e918b8db991f1c69d5db767aec32c16389e8
Binary files /dev/null and b/obj/Animations.o differ
diff --git a/obj/GameMode.o b/obj/GameMode.o
index 89923a74ad3a2e02561691fad69613a1ba3df67b..6605cf5a5d253c6fce23ed0434ec7d035821eec1 100644
Binary files a/obj/GameMode.o and b/obj/GameMode.o differ
diff --git a/obj/SoundSystem.o b/obj/SoundSystem.o
new file mode 100644
index 0000000000000000000000000000000000000000..d54b33a5f271d383130c03535826e0d07b999bf9
Binary files /dev/null and b/obj/SoundSystem.o differ
diff --git a/obj/Tile.o b/obj/Tile.o
index 1b59067a351aef7c08d4b68177f2cdf568c89426..9b41b4a8c2c921a9d71fcaff60f58f74b37e38ac 100644
Binary files a/obj/Tile.o and b/obj/Tile.o differ
diff --git a/obj/UI.o b/obj/UI.o
index 9d33e9f70128cb9f24de4a552ec79a45c72dd76e..ccf56b3df959a61ca9184f6058ecfdcd1a3266a1 100644
Binary files a/obj/UI.o and b/obj/UI.o differ
diff --git a/obj/main.o b/obj/main.o
index cbacafd64565d02669a72545504e1172c2d17029..620b36490c57c5bb90bc0039b68cb178b278326f 100644
Binary files a/obj/main.o and b/obj/main.o differ
diff --git a/res/music/gameover.mp3 b/res/music/gameover.mp3
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/res/music/gameplay.mp3 b/res/music/gameplay.mp3
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/res/music/menu.mp3 b/res/music/menu.mp3
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/res/music/victory.mp3 b/res/music/victory.mp3
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/res/sounds/gameover.wav b/res/sounds/gameover.wav
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/res/sounds/merge.wav b/res/sounds/merge.wav
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/res/sounds/move.wav b/res/sounds/move.wav
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/res/sounds/navigate.wav b/res/sounds/navigate.wav
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/res/sounds/powerup.wav b/res/sounds/powerup.wav
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/res/sounds/select.wav b/res/sounds/select.wav
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/res/sounds/spawn.wav b/res/sounds/spawn.wav
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/res/sounds/victory.wav b/res/sounds/victory.wav
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/2048.cpp b/src/2048.cpp
index c775f6dd3c52f0391f4c4f9e89e94b66fb38ba70..fd81d5e2af97c9aa43dff446d7396661feea8f2e 100644
--- a/src/2048.cpp
+++ b/src/2048.cpp
@@ -1,147 +1,348 @@
 #include "2048.hpp"
-#include <ncurses.h>
 #include <cstdlib>
 #include <ctime>
-#include <vector>
+#include <fstream>
+#include <algorithm>
+#include <iostream>
 
-Game2048::Game2048() : score(0) {
-    std::srand(std::time(0));
+Game2048::Game2048() : score(0), previousScore(0), highScore(0) {
+    std::srand(std::time(nullptr));
     resetBoard();
 }
 
 void Game2048::resetBoard() {
+    // Save high score before reset
+    highScore = std::max(highScore, score);
+    
+    // Reset score and board
     score = 0;
-    for (int i = 0; i < SIZE; ++i)
-        for (int j = 0; j < SIZE; ++j)
+    previousScore = 0;
+    
+    // Clear the board
+    for (int i = 0; i < SIZE; ++i) {
+        for (int j = 0; j < SIZE; ++j) {
             board[i][j].setValue(0);
+        }
+    }
+    
+    // Spawn initial tiles
     spawnTile();
     spawnTile();
+    
+    // Notify observers about reset
+    notifyObservers(GameEvent::SCORE_CHANGED, -1, -1, score);
 }
 
 void Game2048::spawnTile() {
     std::vector<std::pair<int, int>> emptyTiles;
-    for (int i = 0; i < SIZE; ++i)
-        for (int j = 0; j < SIZE; ++j)
-            if (board[i][j].getValue() == 0)
+    
+    // Find all empty tiles
+    for (int i = 0; i < SIZE; ++i) {
+        for (int j = 0; j < SIZE; ++j) {
+            if (board[i][j].getValue() == 0) {
                 emptyTiles.push_back({i, j});
+            }
+        }
+    }
 
+    // If there are empty tiles, spawn a new one
     if (!emptyTiles.empty()) {
         int idx = std::rand() % emptyTiles.size();
+        int row = emptyTiles[idx].first;
+        int col = emptyTiles[idx].second;
+        
+        // 90% chance of spawning a 2, 10% chance of spawning a 4
         int newValue = (std::rand() % 10 == 0) ? 4 : 2;
-        board[emptyTiles[idx].first][emptyTiles[idx].second].setValue(newValue);
+        board[row][col].setValue(newValue);
+        
+        // Notify about the new tile
+        notifyObservers(GameEvent::TILE_SPAWNED, row, col, newValue);
     }
 }
 
 void Game2048::addToScore(int value) {
     score += value;
+    notifyObservers(GameEvent::SCORE_CHANGED, -1, -1, score);
+    
+    // Check for win condition (2048 tile)
+    if (value >= 2048) {
+        notifyObservers(GameEvent::GAME_WON, -1, -1, value);
+    }
+}
+
+void Game2048::saveBoardState() {
+    // Save current board state for undo functionality
+    previousBoard = board;
+    previousScore = score;
+}
+
+void Game2048::undoMove() {
+    // Restore the previous board state
+    board = previousBoard;
+    score = previousScore;
+    
+    // Notify about score change
+    notifyObservers(GameEvent::SCORE_CHANGED, -1, -1, score);
 }
 
 void Game2048::moveLeft() {
+    saveBoardState();
     moved = false;
+    
     for (int i = 0; i < SIZE; ++i) {
-        Tile temp[SIZE];
+        std::array<Tile, SIZE> temp{};
         int index = 0;
+        
         for (int j = 0; j < SIZE; ++j) {
             if (board[i][j].getValue() != 0) {
                 if (index > 0 && temp[index - 1] == board[i][j]) {
+                    // Merge tiles
                     int mergedValue = board[i][j].getValue() * 2;
                     temp[index - 1].setValue(mergedValue);
-                    addToScore(mergedValue); // Add to score when tiles merge
+                    addToScore(mergedValue);
+                    
+                    // Notify about the merge
+                    notifyObservers(GameEvent::TILE_MERGED, i, index - 1, mergedValue);
                     moved = true;
                 } else {
+                    // Move tile
+                    if (j != index) {
+                        notifyObservers(GameEvent::TILE_MOVED, i, j, board[i][j].getValue());
+                        notifyObservers(GameEvent::TILE_MOVED, i, index, board[i][j].getValue());
+                    }
                     temp[index++] = board[i][j];
                 }
             }
         }
+        
+        // Check if the board changed
         for (int j = 0; j < SIZE; ++j) {
-            if (board[i][j].getValue() != temp[j].getValue()) moved = true;
+            if (board[i][j].getValue() != temp[j].getValue()) {
+                moved = true;
+            }
             board[i][j] = temp[j];
         }
     }
-    if (moved) spawnTile();
+    
+    // Spawn a new tile if the board changed
+    if (moved) {
+        spawnTile();
+        
+        // Check for game over
+        if (!canMove()) {
+            notifyObservers(GameEvent::GAME_OVER, -1, -1, score);
+            
+            // Update high score
+            if (score > highScore) {
+                highScore = score;
+            }
+        }
+    }
 }
 
 void Game2048::moveRight() {
+    saveBoardState();
     moved = false;
+    
     for (int i = 0; i < SIZE; ++i) {
-        Tile temp[SIZE];
+        std::array<Tile, SIZE> temp{};
         int index = SIZE - 1;
+        
         for (int j = SIZE - 1; j >= 0; --j) {
             if (board[i][j].getValue() != 0) {
                 if (index < SIZE - 1 && temp[index + 1] == board[i][j]) {
+                    // Merge tiles
                     int mergedValue = board[i][j].getValue() * 2;
                     temp[index + 1].setValue(mergedValue);
-                    addToScore(mergedValue); // Add to score when tiles merge
+                    addToScore(mergedValue);
+                    
+                    // Notify about the merge
+                    notifyObservers(GameEvent::TILE_MERGED, i, index + 1, mergedValue);
                     moved = true;
                 } else {
+                    // Move tile
+                    if (j != index) {
+                        notifyObservers(GameEvent::TILE_MOVED, i, j, board[i][j].getValue());
+                        notifyObservers(GameEvent::TILE_MOVED, i, index, board[i][j].getValue());
+                    }
                     temp[index--] = board[i][j];
                 }
             }
         }
+        
+        // Check if the board changed
         for (int j = 0; j < SIZE; ++j) {
-            if (board[i][j].getValue() != temp[j].getValue()) moved = true;
+            if (board[i][j].getValue() != temp[j].getValue()) {
+                moved = true;
+            }
             board[i][j] = temp[j];
         }
     }
-    if (moved) spawnTile();
+    
+    // Spawn a new tile if the board changed
+    if (moved) {
+        spawnTile();
+        
+        // Check for game over
+        if (!canMove()) {
+            notifyObservers(GameEvent::GAME_OVER, -1, -1, score);
+            
+            // Update high score
+            if (score > highScore) {
+                highScore = score;
+            }
+        }
+    }
 }
 
 void Game2048::moveUp() {
+    saveBoardState();
     moved = false;
+    
     for (int j = 0; j < SIZE; ++j) {
-        Tile temp[SIZE];
+        std::array<Tile, SIZE> temp{};
         int index = 0;
+        
         for (int i = 0; i < SIZE; ++i) {
             if (board[i][j].getValue() != 0) {
                 if (index > 0 && temp[index - 1] == board[i][j]) {
+                    // Merge tiles
                     int mergedValue = board[i][j].getValue() * 2;
                     temp[index - 1].setValue(mergedValue);
-                    addToScore(mergedValue); // Add to score when tiles merge
+                    addToScore(mergedValue);
+                    
+                    // Notify about the merge
+                    notifyObservers(GameEvent::TILE_MERGED, index - 1, j, mergedValue);
                     moved = true;
                 } else {
+                    // Move tile
+                    if (i != index) {
+                        notifyObservers(GameEvent::TILE_MOVED, i, j, board[i][j].getValue());
+                        notifyObservers(GameEvent::TILE_MOVED, index, j, board[i][j].getValue());
+                    }
                     temp[index++] = board[i][j];
                 }
             }
         }
+        
+        // Check if the board changed
         for (int i = 0; i < SIZE; ++i) {
-            if (board[i][j].getValue() != temp[i].getValue()) moved = true;
+            if (board[i][j].getValue() != temp[i].getValue()) {
+                moved = true;
+            }
             board[i][j] = temp[i];
         }
     }
-    if (moved) spawnTile();
+    
+    // Spawn a new tile if the board changed
+    if (moved) {
+        spawnTile();
+        
+        // Check for game over
+        if (!canMove()) {
+            notifyObservers(GameEvent::GAME_OVER, -1, -1, score);
+            
+            // Update high score
+            if (score > highScore) {
+                highScore = score;
+            }
+        }
+    }
 }
 
 void Game2048::moveDown() {
+    saveBoardState();
     moved = false;
+    
     for (int j = 0; j < SIZE; ++j) {
-        Tile temp[SIZE];
+        std::array<Tile, SIZE> temp{};
         int index = SIZE - 1;
+        
         for (int i = SIZE - 1; i >= 0; --i) {
             if (board[i][j].getValue() != 0) {
                 if (index < SIZE - 1 && temp[index + 1] == board[i][j]) {
+                    // Merge tiles
                     int mergedValue = board[i][j].getValue() * 2;
                     temp[index + 1].setValue(mergedValue);
-                    addToScore(mergedValue); // Add to score when tiles merge
+                    addToScore(mergedValue);
+                    
+                    // Notify about the merge
+                    notifyObservers(GameEvent::TILE_MERGED, index + 1, j, mergedValue);
                     moved = true;
                 } else {
+                    // Move tile
+                    if (i != index) {
+                        notifyObservers(GameEvent::TILE_MOVED, i, j, board[i][j].getValue());
+                        notifyObservers(GameEvent::TILE_MOVED, index, j, board[i][j].getValue());
+                    }
                     temp[index--] = board[i][j];
                 }
             }
         }
+        
+        // Check if the board changed
         for (int i = 0; i < SIZE; ++i) {
-            if (board[i][j].getValue() != temp[i].getValue()) moved = true;
+            if (board[i][j].getValue() != temp[i].getValue()) {
+                moved = true;
+            }
             board[i][j] = temp[i];
         }
     }
-    if (moved) spawnTile();
+    
+    // Spawn a new tile if the board changed
+    if (moved) {
+        spawnTile();
+        
+        // Check for game over
+        if (!canMove()) {
+            notifyObservers(GameEvent::GAME_OVER, -1, -1, score);
+            
+            // Update high score
+            if (score > highScore) {
+                highScore = score;
+            }
+        }
+    }
 }
 
-bool Game2048::canMove() {
+bool Game2048::canMove() const {
+    // Check for empty cells
     for (int i = 0; i < SIZE; ++i) {
         for (int j = 0; j < SIZE; ++j) {
-            if (board[i][j].getValue() == 0) return true;
-            if (j < SIZE - 1 && board[i][j] == board[i][j + 1]) return true;
-            if (i < SIZE - 1 && board[i][j] == board[i + 1][j]) return true;
+            if (board[i][j].getValue() == 0) {
+                return true;
+            }
+        }
+    }
+    
+    // Check for possible merges horizontally
+    for (int i = 0; i < SIZE; ++i) {
+        for (int j = 0; j < SIZE - 1; ++j) {
+            if (board[i][j] == board[i][j + 1]) {
+                return true;
+            }
+        }
+    }
+    
+    // Check for possible merges vertically
+    for (int i = 0; i < SIZE - 1; ++i) {
+        for (int j = 0; j < SIZE; ++j) {
+            if (board[i][j] == board[i + 1][j]) {
+                return true;
+            }
+        }
+    }
+    
+    // No moves possible
+    return false;
+}
+
+bool Game2048::hasWon() const {
+    for (int i = 0; i < SIZE; ++i) {
+        for (int j = 0; j < SIZE; ++j) {
+            if (board[i][j].getValue() >= 2048) {
+                return true;
+            }
         }
     }
     return false;
@@ -151,6 +352,113 @@ int Game2048::getScore() const {
     return score;
 }
 
-const Tile (*Game2048::getBoard() const)[SIZE] {
+int Game2048::getHighScore() const {
+    return highScore;
+}
+
+// Special actions for power-ups
+void Game2048::clearRow(int row) {
+    if (row < 0 || row >= SIZE) return;
+    
+    for (int j = 0; j < SIZE; ++j) {
+        board[row][j].setValue(0);
+    }
+    
+    // Spawn a new tile after clearing
+    spawnTile();
+}
+
+void Game2048::clearColumn(int col) {
+    if (col < 0 || col >= SIZE) return;
+    
+    for (int i = 0; i < SIZE; ++i) {
+        board[i][col].setValue(0);
+    }
+    
+    // Spawn a new tile after clearing
+    spawnTile();
+}
+
+void Game2048::doubleScoreTile(int row, int col) {
+    if (row < 0 || row >= SIZE || col < 0 || col >= SIZE) return;
+    
+    if (board[row][col].getValue() > 0) {
+        addToScore(board[row][col].getValue());
+    }
+}
+
+void Game2048::upgradeTile(int row, int col) {
+    if (row < 0 || row >= SIZE || col < 0 || col >= SIZE) return;
+    
+    if (board[row][col].getValue() > 0) {
+        int newValue = board[row][col].getValue() * 2;
+        board[row][col].setValue(newValue);
+        notifyObservers(GameEvent::TILE_MERGED, row, col, newValue);
+    }
+}
+
+const std::array<std::array<Tile, SIZE>, SIZE>& Game2048::getBoard() const {
     return board;
 }
+
+// Observer pattern methods
+void Game2048::addObserver(GameEventCallback callback) {
+    observers.push_back(callback);
+}
+
+void Game2048::removeAllObservers() {
+    observers.clear();
+}
+
+void Game2048::notifyObservers(GameEvent event, int row, int col, int value) {
+    for (const auto& observer : observers) {
+        observer(event, row, col, value);
+    }
+}
+
+// Save/Load game state
+bool Game2048::saveGame(const std::string& filename) const {
+    std::ofstream file(filename, std::ios::binary);
+    if (!file.is_open()) {
+        return false;
+    }
+    
+    // Save score and high score
+    file.write(reinterpret_cast<const char*>(&score), sizeof(score));
+    file.write(reinterpret_cast<const char*>(&highScore), sizeof(highScore));
+    
+    // Save board state
+    for (int i = 0; i < SIZE; ++i) {
+        for (int j = 0; j < SIZE; ++j) {
+            int value = board[i][j].getValue();
+            file.write(reinterpret_cast<const char*>(&value), sizeof(value));
+        }
+    }
+    
+    return true;
+}
+
+bool Game2048::loadGame(const std::string& filename) {
+    std::ifstream file(filename, std::ios::binary);
+    if (!file.is_open()) {
+        return false;
+    }
+    
+    // Load score and high score
+    file.read(reinterpret_cast<char*>(&score), sizeof(score));
+    file.read(reinterpret_cast<char*>(&highScore), sizeof(highScore));
+    
+    // Load board state
+    for (int i = 0; i < SIZE; ++i) {
+        for (int j = 0; j < SIZE; ++j) {
+            int value;
+            file.read(reinterpret_cast<char*>(&value), sizeof(value));
+            board[i][j].setValue(value);
+        }
+    }
+    
+    // Notify about score change
+    notifyObservers(GameEvent::SCORE_CHANGED, -1, -1, score);
+    
+    return true;
+}
\ No newline at end of file
diff --git a/src/Animations.cpp b/src/Animations.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..780b387065d0975dfe1377e0ec91c6733270bf77
--- /dev/null
+++ b/src/Animations.cpp
@@ -0,0 +1,625 @@
+#include "Animations.hpp"
+#include <random>
+#include <algorithm>
+#include <fstream>
+#include <sstream>
+
+//==============================================================================
+// Animation Implementation
+//==============================================================================
+Animation::Animation(AnimationType type, int row, int col, int value, float duration, EasingType easing)
+    : type(type), row(row), col(col), value(value), 
+      duration(duration), elapsed(0.0f), completed(false), easing(easing),
+      sourceRow(-1), sourceCol(-1), targetRow(row), targetCol(col) {
+}
+
+bool Animation::update(float deltaTime) {
+    elapsed += deltaTime;
+    
+    if (elapsed >= duration) {
+        elapsed = duration;
+        if (!completed) {
+            completed = true;
+            if (onComplete) {
+                onComplete();
+            }
+        }
+    }
+    
+    // Update particles if this is a particle animation
+    if (type == AnimationType::PARTICLE) {
+        for (auto it = particles.begin(); it != particles.end();) {
+            if (!it->update(deltaTime)) {
+                it = particles.erase(it);
+            } else {
+                ++it;
+            }
+        }
+        
+        // If all particles are gone, mark as completed
+        if (particles.empty() && !completed) {
+            completed = true;
+            if (onComplete) {
+                onComplete();
+            }
+        }
+    }
+    
+    return !completed;
+}
+
+void Animation::draw(WINDOW* win) {
+    float progress = getEasedProgress();
+    
+    switch (type) {
+        case AnimationType::SLIDE: {
+            // Calculate interpolated position
+            float currentRow = sourceRow + (targetRow - sourceRow) * progress;
+            float currentCol = sourceCol + (targetCol - sourceCol) * progress;
+            
+            // Draw the tile at the interpolated position
+            int colorPair = getColorForValue(value);
+            wattron(win, COLOR_PAIR(colorPair) | A_BOLD);
+            mvwprintw(win, (int)currentRow, (int)currentCol * 6 + 1, "%5d", value);
+            wattroff(win, COLOR_PAIR(colorPair) | A_BOLD);
+            break;
+        }
+        
+        case AnimationType::MERGE: {
+            // For ncurses, we don't actually use scaling but we simulate the effect
+            int colorPair = getColorForValue(value);
+            
+            // Apply effect to the tile (for ncurses, just use bold and blink)
+            int attrs = A_BOLD;
+            if (progress > 0.4f && progress < 0.6f) {
+                attrs |= A_BLINK; // Blink at peak of animation
+            }
+            
+            wattron(win, COLOR_PAIR(colorPair) | attrs);
+            mvwprintw(win, row, col * 6 + 1, "%5d", value);
+            wattroff(win, COLOR_PAIR(colorPair) | attrs);
+            break;
+        }
+        
+        case AnimationType::SPAWN: {
+            // Fade in for spawn animation
+            int colorPair = getColorForValue(value);
+            
+            if (progress < 0.3f) {
+                wattron(win, COLOR_PAIR(1) | A_DIM); // Background color
+            } else if (progress < 0.7f) {
+                wattron(win, COLOR_PAIR(colorPair) | A_DIM); // Dim version
+            } else {
+                wattron(win, COLOR_PAIR(colorPair) | A_BOLD); // Full version
+            }
+            
+            mvwprintw(win, row, col * 6 + 1, "%5d", value);
+            
+            if (progress < 0.3f) {
+                wattroff(win, COLOR_PAIR(1) | A_DIM);
+            } else if (progress < 0.7f) {
+                wattroff(win, COLOR_PAIR(colorPair) | A_DIM);
+            } else {
+                wattroff(win, COLOR_PAIR(colorPair) | A_BOLD);
+            }
+            break;
+        }
+        
+        case AnimationType::PULSE: {
+            // Pulsing animation
+            float pulse = sin(progress * M_PI * 2) * 0.5f + 0.5f;
+            int colorPair = getColorForValue(value);
+            
+            int attrs = pulse > 0.7f ? A_BOLD : A_NORMAL;
+            wattron(win, COLOR_PAIR(colorPair) | attrs);
+            mvwprintw(win, row, col * 6 + 1, "%5d", value);
+            wattroff(win, COLOR_PAIR(colorPair) | attrs);
+            break;
+        }
+        
+        case AnimationType::FADE_IN: {
+            // Fade in animation
+            int colorPair = getColorForValue(value);
+            
+            int attrs = progress > 0.7f ? A_BOLD : (progress > 0.3f ? A_NORMAL : A_DIM);
+            wattron(win, COLOR_PAIR(colorPair) | attrs);
+            mvwprintw(win, row, col * 6 + 1, "%5d", value);
+            wattroff(win, COLOR_PAIR(colorPair) | attrs);
+            break;
+        }
+        
+        case AnimationType::FADE_OUT: {
+            // Fade out animation
+            int colorPair = getColorForValue(value);
+            
+            int attrs = progress < 0.3f ? A_BOLD : (progress < 0.7f ? A_NORMAL : A_DIM);
+            wattron(win, COLOR_PAIR(colorPair) | attrs);
+            mvwprintw(win, row, col * 6 + 1, "%5d", value);
+            wattroff(win, COLOR_PAIR(colorPair) | attrs);
+            break;
+        }
+        
+        case AnimationType::SHAKE: {
+            // Shake animation
+            float offsetX = sin(progress * M_PI * 6) * (1.0f - progress) * 2.0f;
+            int colorPair = getColorForValue(value);
+            
+            wattron(win, COLOR_PAIR(colorPair) | A_BOLD);
+            mvwprintw(win, row, col * 6 + 1 + (int)offsetX, "%5d", value);
+            wattroff(win, COLOR_PAIR(colorPair) | A_BOLD);
+            break;
+        }
+        
+        case AnimationType::FLASH: {
+            // Flash animation
+            bool visible = ((int)(progress * 10)) % 2 == 0;
+            if (visible) {
+                int colorPair = getColorForValue(value);
+                wattron(win, COLOR_PAIR(colorPair) | A_BOLD | A_BLINK);
+                mvwprintw(win, row, col * 6 + 1, "%5d", value);
+                wattroff(win, COLOR_PAIR(colorPair) | A_BOLD | A_BLINK);
+            }
+            break;
+        }
+        
+        case AnimationType::PARTICLE: {
+            // Draw all particles
+            for (auto& particle : particles) {
+                particle.draw(win);
+            }
+            break;
+        }
+    }
+}
+
+void Animation::setCallback(std::function<void()> callback) {
+    onComplete = callback;
+}
+
+void Animation::setupSlide(int fromRow, int fromCol, int toRow, int toCol) {
+    sourceRow = fromRow;
+    sourceCol = fromCol;
+    targetRow = toRow;
+    targetCol = toCol;
+}
+
+void Animation::setupMerge() {
+    // Setup is handled in the constructor
+}
+
+void Animation::setupSpawn() {
+    // Setup is handled in the constructor
+}
+
+void Animation::setupPulse() {
+    // Setup is handled in the constructor
+}
+
+void Animation::setupFade(bool fadeIn) {
+    type = fadeIn ? AnimationType::FADE_IN : AnimationType::FADE_OUT;
+}
+
+void Animation::setupShake() {
+    // Setup is handled in the constructor
+}
+
+void Animation::setupFlash() {
+    // Setup is handled in the constructor
+}
+
+void Animation::setupParticles(int count, bool isMerge) {
+    std::random_device rd;
+    std::mt19937 gen(rd());
+    std::uniform_real_distribution<float> angleDist(0.0f, 2.0f * M_PI);
+    std::uniform_real_distribution<float> speedDist(0.5f, 2.5f);
+    std::uniform_real_distribution<float> lifetimeDist(0.3f, 1.3f);
+    
+    particles.clear();
+    
+    // Convert board coordinates to screen coordinates
+    float centerX = col * 6 + 3;
+    float centerY = row;
+    
+    // Generate particles
+    for (int i = 0; i < count; ++i) {
+        float angle = angleDist(gen);
+        float speed = speedDist(gen);
+        float vx = cos(angle) * speed;
+        float vy = sin(angle) * speed;
+        
+        float lifetime = lifetimeDist(gen);
+        int color = getColorForValue(value);
+        
+        // Different symbols for different effects - ASCII only
+        char symbols[] = {'*', '+', '.', 'o', ':', '#', '@', '%'};
+        char symbol = symbols[i % 8];
+        
+        particles.emplace_back(centerX, centerY, vx, vy, lifetime, color, symbol);
+    }
+}
+
+float Animation::getEasedProgress() const {
+    float t = elapsed / duration;
+    
+    switch (easing) {
+        case EasingType::LINEAR:
+            return t;
+            
+        case EasingType::EASE_IN:
+            return t * t;
+            
+        case EasingType::EASE_OUT:
+            return t * (2 - t);
+            
+        case EasingType::EASE_IN_OUT:
+            return t < 0.5f ? 2 * t * t : -1 + (4 - 2 * t) * t;
+            
+        case EasingType::ELASTIC: {
+            // Approximation of elastic easing
+            float p = 0.3f;
+            return pow(2, -10 * t) * sin((t - p / 4) * (2 * M_PI) / p) + 1;
+        }
+            
+        case EasingType::BOUNCE: {
+            // Approximation of bounce easing
+            if (t < 4/11.0f) {
+                return (121 * t * t)/16.0f;
+            } else if (t < 8/11.0f) {
+                return (363/40.0f * t * t) - (99/10.0f * t) + 17/5.0f;
+            } else if (t < 9/10.0f) {
+                return (4356/361.0f * t * t) - (35442/1805.0f * t) + 16061/1805.0f;
+            } else {
+                return (54/5.0f * t * t) - (513/25.0f * t) + 268/25.0f;
+            }
+        }
+    }
+    
+    return t; // Default to linear
+}
+
+int Animation::getColorForValue(int value) {
+    switch (value) {
+        case 0: return 1;  // Default color
+        case 2: return 2;
+        case 4: return 3;
+        case 8: return 4;
+        case 16: return 5;
+        case 32: return 6;
+        case 64: return 7;
+        case 128: return 8;
+        case 256: return 9;
+        case 512: return 10;
+        case 1024: return 11;
+        case 2048: return 12;
+        default: return 13;    // Higher values
+    }
+}
+
+//==============================================================================
+// Particle Implementation
+//==============================================================================
+Particle::Particle(float x, float y, float vx, float vy, float lifetime, int color, char symbol, bool fading)
+    : x(x), y(y), vx(vx), vy(vy), ax(0), ay(0.1f), // Slight gravity
+      lifetime(lifetime), maxLifetime(lifetime), size(1.0f),
+      color(color), symbol(symbol), fading(fading) {
+}
+
+bool Particle::update(float deltaTime) {
+    // Update velocity
+    vx += ax * deltaTime;
+    vy += ay * deltaTime;
+    
+    // Update position
+    x += vx * deltaTime * 10;
+    y += vy * deltaTime * 5;
+    
+    // Update lifetime
+    lifetime -= deltaTime;
+    
+    // Return true if particle is still alive
+    return lifetime > 0;
+}
+
+void Particle::draw(WINDOW* win) {
+    // Skip drawing if outside window
+    int maxY, maxX;
+    getmaxyx(win, maxY, maxX);
+    
+    if (x < 0 || x >= maxX || y < 0 || y >= maxY) {
+        return;
+    }
+    
+    // Apply fade effect based on lifetime
+    int attrs;
+    if (fading) {
+        float alpha = lifetime / maxLifetime; // 0.0 to 1.0
+        attrs = alpha > 0.7f ? A_BOLD : (alpha > 0.3f ? A_NORMAL : A_DIM);
+    } else {
+        attrs = A_BOLD;
+    }
+    
+    wattron(win, COLOR_PAIR(color) | attrs);
+    mvwaddch(win, (int)y, (int)x, symbol);
+    wattroff(win, COLOR_PAIR(color) | attrs);
+}
+
+//==============================================================================
+// AnimationManager Implementation
+//==============================================================================
+AnimationManager::AnimationManager()
+    : backgroundEffectTimer(0.0f), enableBackgroundEffects(true),
+      hasGifBackground(false), gifFrameDuration(0.1f), gifFrameTimer(0.0f), currentGifFrame(0) {
+}
+
+void AnimationManager::update(float deltaTime) {
+    // Update background effect timer
+    backgroundEffectTimer += deltaTime;
+    
+    // Update GIF animation
+    if (hasGifBackground) {
+        gifFrameTimer += deltaTime;
+        if (gifFrameTimer >= gifFrameDuration) {
+            gifFrameTimer = 0.0f;
+            currentGifFrame = (currentGifFrame + 1) % gifFrames.size();
+        }
+    }
+    
+    // Update all animations
+    for (auto it = animations.begin(); it != animations.end();) {
+        if (!it->update(deltaTime)) {
+            it = animations.erase(it);
+        } else {
+            ++it;
+        }
+    }
+    
+    // Update transition effects
+    for (auto it = transitionEffects.begin(); it != transitionEffects.end();) {
+        it->elapsed += deltaTime;
+        if (it->elapsed >= it->duration) {
+            it = transitionEffects.erase(it);
+        } else {
+            ++it;
+        }
+    }
+}
+
+void AnimationManager::draw(WINDOW* mainWin, WINDOW* gameWin) {
+    // Draw background effects
+    if (enableBackgroundEffects) {
+        drawBackground(mainWin);
+    }
+    
+    // Draw GIF background if available
+    if (hasGifBackground) {
+        drawGifBackground(mainWin);
+    }
+    
+    // Draw all animations
+    for (auto& anim : animations) {
+        anim.draw(gameWin);
+    }
+    
+    // Draw transition effects
+    for (const auto& effect : transitionEffects) {
+        float progress = effect.elapsed / effect.duration;
+        
+        if (effect.type == "fade") {
+            // Fade transition
+            int maxY, maxX;
+            getmaxyx(mainWin, maxY, maxX);
+            
+            wattron(mainWin, A_DIM);
+            for (int y = 0; y < maxY; y++) {
+                for (int x = 0; x < maxX; x++) {
+                    if ((x + y) % (int)(10 - progress * 9) == 0) {
+                        mvwaddch(mainWin, y, x, ' ' | A_REVERSE);
+                    }
+                }
+            }
+            wattroff(mainWin, A_DIM);
+        } else if (effect.type == "slide") {
+            // Slide transition
+            int maxY, maxX;
+            getmaxyx(mainWin, maxY, maxX);
+            
+            int limit = (int)(progress * maxY);
+            for (int y = 0; y < limit; y++) {
+                for (int x = 0; x < maxX; x++) {
+                    if ((x + y) % 2 == 0) {
+                        mvwaddch(mainWin, y, x, ' ' | A_REVERSE);
+                    }
+                }
+            }
+        } else if (effect.type == "sparkle") {
+            // Sparkle transition
+            int maxY, maxX;
+            getmaxyx(mainWin, maxY, maxX);
+            
+            int iterations = (int)(progress * 10);
+            for (int i = 0; i < iterations; i++) {
+                int radius = maxX / 2 - (i * maxX / 20);
+                if (radius > 0) {
+                    for (int degree = 0; degree < 360; degree += 5) {
+                        float radian = degree * M_PI / 180.0f;
+                        int x = maxX / 2 + (int)(cos(radian) * radius);
+                        int y = maxY / 2 + (int)(sin(radian) * radius / 2);
+                        if (x >= 0 && x < maxX && y >= 0 && y < maxY) {
+                            mvwaddch(mainWin, y, x, ' ' | A_REVERSE);
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+void AnimationManager::addSlideAnimation(int fromRow, int fromCol, int toRow, int toCol, int value) {
+    Animation anim(AnimationType::SLIDE, toRow, toCol, value, 0.2f, EasingType::EASE_OUT);
+    anim.setupSlide(fromRow, fromCol, toRow, toCol);
+    animations.push_back(anim);
+}
+
+void AnimationManager::addMergeAnimation(int row, int col, int value) {
+    Animation anim(AnimationType::MERGE, row, col, value, 0.3f, EasingType::EASE_IN_OUT);
+    anim.setupMerge();
+    
+    // Add particle effect for merges
+    Animation particles(AnimationType::PARTICLE, row, col, value, 0.6f, EasingType::LINEAR);
+    particles.setupParticles(10, true);
+    
+    animations.push_back(anim);
+    animations.push_back(particles);
+}
+
+void AnimationManager::addSpawnAnimation(int row, int col, int value) {
+    Animation anim(AnimationType::SPAWN, row, col, value, 0.3f, EasingType::EASE_OUT);
+    anim.setupSpawn();
+    animations.push_back(anim);
+}
+
+void AnimationManager::addScoreAnimation(int score, int prevScore) {
+    // This would ideally animate a score change in the UI
+    // For now, just add some particle effects to celebrate score increase
+    if (score > prevScore) {
+        int scoreDiff = score - prevScore;
+        int particleCount = std::min(20, scoreDiff / 10);
+        
+        if (particleCount > 0) {
+            // Get window dimensions - assuming score area is in top right
+            Animation particles(AnimationType::PARTICLE, 1, 15, scoreDiff, 0.8f, EasingType::LINEAR);
+            particles.setupParticles(particleCount);
+            animations.push_back(particles);
+        }
+    }
+}
+
+void AnimationManager::addGameOverAnimation() {
+    // Add big particle explosion in center of board
+    for (int i = 0; i < 4; i++) {
+        for (int j = 0; j < 4; j++) {
+            Animation particles(AnimationType::PARTICLE, i, j, 0, 1.0f, EasingType::LINEAR);
+            particles.setupParticles(5);
+            animations.push_back(particles);
+        }
+    }
+    
+    // Add transition effect
+    addTransitionEffect("fade", 0.7f);
+}
+
+void AnimationManager::addVictoryAnimation() {
+    // Add fancy particle effects for victory
+    for (int i = 0; i < 4; i++) {
+        for (int j = 0; j < 4; j++) {
+            Animation particles(AnimationType::PARTICLE, i, j, 2048, 1.5f, EasingType::LINEAR);
+            particles.setupParticles(8);
+            animations.push_back(particles);
+        }
+    }
+    
+    // Add transition effect
+    addTransitionEffect("sparkle", 1.0f);
+}
+
+void AnimationManager::addTransitionEffect(const std::string& type, float duration) {
+    TransitionEffect effect;
+    effect.type = type;
+    effect.duration = duration;
+    effect.elapsed = 0.0f;
+    transitionEffects.push_back(effect);
+}
+
+void AnimationManager::addParticleEffect(float x, float y, int color, int count) {
+    // Create a particle animation
+    // Convert screen coordinates to approximate board coordinates
+    int boardRow = static_cast<int>(y);
+    int boardCol = static_cast<int>(x / 6);
+    
+    Animation particles(AnimationType::PARTICLE, boardRow, boardCol, 0, 0.6f, EasingType::LINEAR);
+    particles.setupParticles(count);
+    animations.push_back(particles);
+}
+
+void AnimationManager::drawBackground(WINDOW* win) {
+    int maxY, maxX;
+    getmaxyx(win, maxY, maxX);
+    
+    // Subtle animated pattern for backgrounds
+    float time = backgroundEffectTimer;
+    
+    for (int y = 0; y < maxY; y += 4) {
+        for (int x = 0; x < maxX; x += 8) {
+            float wave = sin(time + x * 0.05f + y * 0.03f) * 0.5f + 0.5f;
+            if (wave > 0.7f) {
+                wattron(win, A_DIM);
+                mvwaddch(win, y, x, '.');
+                wattroff(win, A_DIM);
+            }
+        }
+    }
+}
+
+void AnimationManager::toggleBackgroundEffects() {
+    enableBackgroundEffects = !enableBackgroundEffects;
+}
+
+bool AnimationManager::loadGifBackground(const std::string& filePath) {
+    // This is a simplified placeholder for GIF loading
+    // In a real implementation, you would need a GIF decoding library
+    // Here we'll just simulate by loading text frames from a file
+    
+    std::ifstream file(filePath);
+    if (!file.is_open()) {
+        return false;
+    }
+    
+    gifFrames.clear();
+    std::string line;
+    std::string currentFrame;
+    
+    while (std::getline(file, line)) {
+        if (line == "FRAME") {
+            if (!currentFrame.empty()) {
+                gifFrames.push_back(currentFrame);
+                currentFrame.clear();
+            }
+        } else {
+            currentFrame += line + "\n";
+        }
+    }
+    
+    if (!currentFrame.empty()) {
+        gifFrames.push_back(currentFrame);
+    }
+    
+    hasGifBackground = !gifFrames.empty();
+    currentGifFrame = 0;
+    gifFrameTimer = 0.0f;
+    
+    return hasGifBackground;
+}
+
+void AnimationManager::drawGifBackground(WINDOW* win) {
+    if (!hasGifBackground || gifFrames.empty()) {
+        return;
+    }
+    
+    // Draw the current frame
+    std::istringstream iss(gifFrames[currentGifFrame]);
+    std::string line;
+    int y = 0;
+    
+    while (std::getline(iss, line)) {
+        mvwprintw(win, y++, 0, "%s", line.c_str());
+    }
+}
+
+void AnimationManager::clearAnimations() {
+    animations.clear();
+    transitionEffects.clear();
+}
+
+bool AnimationManager::hasActiveAnimations() const {
+    return !animations.empty() || !transitionEffects.empty();
+}
\ No newline at end of file
diff --git a/src/GameMode.cpp b/src/GameMode.cpp
index d5e605b899ad14246ae04cbbd264d71b1fc35f03..e9ffb707c8d3d2ec24eaa578b4068f5941fcd277 100644
--- a/src/GameMode.cpp
+++ b/src/GameMode.cpp
@@ -1,8 +1,10 @@
 #include "GameMode.hpp"
-#include <ncurses.h>
+#include <cmath>
+#include <algorithm>
 
+// Base GameMode implementation
 GameMode::GameMode(GameModeType type, const std::string& name, const std::string& description)
-    : type(type), name(name), description(description) {
+    : type(type), name(name), description(description), gameOver(false), gameWon(false) {
 }
 
 GameModeType GameMode::getType() const {
@@ -17,134 +19,614 @@ const std::string& GameMode::getDescription() const {
     return description;
 }
 
-// Classic Mode Implementation
+bool GameMode::isGameOver() const {
+    return gameOver;
+}
+
+bool GameMode::isGameWon() const {
+    return gameWon;
+}
+
+void GameMode::setGameOver(bool over) {
+    gameOver = over;
+}
+
+void GameMode::setGameWon(bool won) {
+    gameWon = won;
+}
+
+//==============================================================================
+// ClassicMode Implementation
+//==============================================================================
 ClassicMode::ClassicMode()
     : GameMode(GameModeType::CLASSIC, "Classic", "The original 2048 game. Combine tiles to reach 2048!") {
 }
 
-void ClassicMode::initialize() {
-    // Nothing special needed for classic mode
+void ClassicMode::initialize(Game2048& game) {
+    game.resetBoard();
+    gameOver = false;
+    gameWon = false;
 }
 
-bool ClassicMode::update(float deltaTime) {
-    // Classic mode has no time-based updates
-    return true;
+bool ClassicMode::update(Game2048& game, float deltaTime) {
+    // Check win condition
+    if (game.hasWon() && !gameWon) {
+        gameWon = true;
+        return true;
+    }
+    
+    // Check game over condition
+    if (!game.canMove() && !gameOver) {
+        gameOver = true;
+        return true;
+    }
+    
+    return false;
+}
+
+void ClassicMode::handleInput(Game2048& game, int key) {
+    // Standard movement controls
+    switch (key) {
+        case KEY_LEFT:
+            game.moveLeft();
+            break;
+        case KEY_RIGHT:
+            game.moveRight();
+            break;
+        case KEY_UP:
+            game.moveUp();
+            break;
+        case KEY_DOWN:
+            game.moveDown();
+            break;
+    }
 }
 
 void ClassicMode::render() {
-    // Rendering handled by the main UI class
+    // No special rendering required for Classic mode
 }
 
-// Timed Mode Implementation
+//==============================================================================
+// TimedMode Implementation
+//==============================================================================
 TimedMode::TimedMode()
     : GameMode(GameModeType::TIMED, "Timed", "Race against the clock! Score as high as possible before time runs out."),
-      timeLimit(180.0f), // 3 minutes
-      timeRemaining(180.0f) {
+      timeLimit(180.0f), timeRemaining(180.0f), bonusTimePerMerge(1.0f) {
 }
 
-void TimedMode::initialize() {
+void TimedMode::initialize(Game2048& game) {
+    game.resetBoard();
     timeRemaining = timeLimit;
+    gameOver = false;
+    gameWon = false;
 }
 
-bool TimedMode::update(float deltaTime) {
+bool TimedMode::update(Game2048& game, float deltaTime) {
+    // Decrease time
     timeRemaining -= deltaTime;
-    return timeRemaining > 0.0f;
+    
+    // Check for time out
+    if (timeRemaining <= 0) {
+        timeRemaining = 0;
+        if (!gameOver) {
+            gameOver = true;
+            return true;
+        }
+    }
+    
+    // Check win condition
+    if (game.hasWon() && !gameWon) {
+        gameWon = true;
+        return true;
+    }
+    
+    return false;
+}
+
+void TimedMode::handleInput(Game2048& game, int key) {
+    // Standard movement controls
+    switch (key) {
+        case KEY_LEFT:
+            game.moveLeft();
+            break;
+        case KEY_RIGHT:
+            game.moveRight();
+            break;
+        case KEY_UP:
+            game.moveUp();
+            break;
+        case KEY_DOWN:
+            game.moveDown();
+            break;
+    }
 }
 
 void TimedMode::render() {
-    // Rendering handled by the UI class
+    // Rendering is handled by the UI class
 }
 
 float TimedMode::getTimeRemaining() const {
     return timeRemaining;
 }
 
-// PowerUp Mode Implementation
+void TimedMode::addTime(float seconds) {
+    timeRemaining += seconds;
+    if (timeRemaining > timeLimit) {
+        timeRemaining = timeLimit;
+    }
+}
+
+//==============================================================================
+// PowerUpMode Implementation
+//==============================================================================
 PowerUpMode::PowerUpMode()
     : GameMode(GameModeType::POWERUP, "Power-Up", "Use special powers to boost your score!"),
-      powerUpCount(3),
-      doubleScoreActive(false),
-      removeRowActive(false),
-      freezeTimeActive(false) {
+      doubleScorePowerups(3), clearRowPowerups(2), undoMovePowerups(1), upgradeTilePowerups(1),
+      doubleScoreActive(false), doubleScoreTurnsLeft(0) {
 }
 
-void PowerUpMode::initialize() {
-    powerUpCount = 3;
+void PowerUpMode::initialize(Game2048& game) {
+    game.resetBoard();
+    doubleScorePowerups = 3;
+    clearRowPowerups = 2;
+    undoMovePowerups = 1;
+    upgradeTilePowerups = 1;
     doubleScoreActive = false;
-    removeRowActive = false;
-    freezeTimeActive = false;
+    doubleScoreTurnsLeft = 0;
+    gameOver = false;
+    gameWon = false;
 }
 
-bool PowerUpMode::update(float deltaTime) {
-    // Power-up specific logic
-    return true;
+bool PowerUpMode::update(Game2048& game, float deltaTime) {
+    // Update double score turn counter
+    if (doubleScoreActive) {
+        doubleScoreTurnsLeft--;
+        if (doubleScoreTurnsLeft <= 0) {
+            doubleScoreActive = false;
+        }
+    }
+    
+    // Check win condition
+    if (game.hasWon() && !gameWon) {
+        gameWon = true;
+        return true;
+    }
+    
+    // Check game over condition
+    if (!game.canMove() && !gameOver) {
+        gameOver = true;
+        return true;
+    }
+    
+    return false;
+}
+
+void PowerUpMode::handleInput(Game2048& game, int key) {
+    // Standard movement controls
+    switch (key) {
+        case KEY_LEFT:
+            game.moveLeft();
+            if (doubleScoreActive) {
+                // If double score is active, decrease turn count
+                doubleScoreTurnsLeft--;
+                if (doubleScoreTurnsLeft <= 0) {
+                    doubleScoreActive = false;
+                }
+            }
+            break;
+        case KEY_RIGHT:
+            game.moveRight();
+            if (doubleScoreActive) {
+                doubleScoreTurnsLeft--;
+                if (doubleScoreTurnsLeft <= 0) {
+                    doubleScoreActive = false;
+                }
+            }
+            break;
+        case KEY_UP:
+            game.moveUp();
+            if (doubleScoreActive) {
+                doubleScoreTurnsLeft--;
+                if (doubleScoreTurnsLeft <= 0) {
+                    doubleScoreActive = false;
+                }
+            }
+            break;
+        case KEY_DOWN:
+            game.moveDown();
+            if (doubleScoreActive) {
+                doubleScoreTurnsLeft--;
+                if (doubleScoreTurnsLeft <= 0) {
+                    doubleScoreActive = false;
+                }
+            }
+            break;
+        
+        // PowerUp specific controls
+        case '1': // Double Score
+            activateDoubleScore();
+            break;
+        case '2': // Clear Row (will need row selection from UI)
+            // This is handled in the UI class
+            break;
+        case '3': // Undo Move
+            undoMove(game);
+            break;
+        case '4': // Upgrade Tile (will need tile selection from UI)
+            // This is handled in the UI class
+            break;
+    }
 }
 
 void PowerUpMode::render() {
-    // Rendering handled by the UI class
+    // Rendering is handled by the UI class
+}
+
+bool PowerUpMode::activateDoubleScore() {
+    if (doubleScorePowerups <= 0) return false;
+    
+    doubleScorePowerups--;
+    doubleScoreActive = true;
+    doubleScoreTurnsLeft = 3; // Active for 3 turns
+    return true;
+}
+
+bool PowerUpMode::clearRow(Game2048& game, int row) {
+    if (clearRowPowerups <= 0 || row < 0 || row >= SIZE) return false;
+    
+    clearRowPowerups--;
+    game.clearRow(row);
+    return true;
 }
 
-void PowerUpMode::activatePowerUp(int type) {
-    if (powerUpCount <= 0) return;
+bool PowerUpMode::undoMove(Game2048& game) {
+    if (undoMovePowerups <= 0) return false;
     
-    powerUpCount--;
+    undoMovePowerups--;
+    game.undoMove();
+    return true;
+}
+
+bool PowerUpMode::upgradeTile(Game2048& game, int row, int col) {
+    if (upgradeTilePowerups <= 0 || row < 0 || row >= SIZE || col < 0 || col >= SIZE) return false;
     
-    switch (type) {
-        case 1: // Double score
-            doubleScoreActive = true;
+    upgradeTilePowerups--;
+    game.upgradeTile(row, col);
+    return true;
+}
+
+int PowerUpMode::getDoubleScorePowerups() const {
+    return doubleScorePowerups;
+}
+
+int PowerUpMode::getClearRowPowerups() const {
+    return clearRowPowerups;
+}
+
+int PowerUpMode::getUndoMovePowerups() const {
+    return undoMovePowerups;
+}
+
+int PowerUpMode::getUpgradeTilePowerups() const {
+    return upgradeTilePowerups;
+}
+
+bool PowerUpMode::isDoubleScoreActive() const {
+    return doubleScoreActive;
+}
+
+int PowerUpMode::getDoubleScoreTurnsLeft() const {
+    return doubleScoreTurnsLeft;
+}
+
+//==============================================================================
+// ChallengeMode Implementation
+//==============================================================================
+ChallengeMode::ChallengeMode()
+    : GameMode(GameModeType::CHALLENGE, "Challenge", "Complete specific objectives within constraints."),
+      targetScore(5000), targetTile(512), movesLimit(100), movesUsed(0), currentLevel(1) {
+}
+
+void ChallengeMode::initialize(Game2048& game) {
+    game.resetBoard();
+    
+    // Set challenge based on level
+    currentLevel = 1;
+    targetScore = 2000 * currentLevel;
+    targetTile = 128 * std::pow(2, currentLevel - 1);
+    movesLimit = 50 + (currentLevel * 10);
+    movesUsed = 0;
+    
+    gameOver = false;
+    gameWon = false;
+}
+
+bool ChallengeMode::update(Game2048& game, float deltaTime) {
+    // Check victory condition
+    if (checkVictory(game) && !gameWon) {
+        gameWon = true;
+        return true;
+    }
+    
+    // Check game over condition
+    if ((movesUsed >= movesLimit || !game.canMove()) && !gameOver) {
+        gameOver = true;
+        return true;
+    }
+    
+    return false;
+}
+
+void ChallengeMode::handleInput(Game2048& game, int key) {
+    // Standard movement controls with move counting
+    switch (key) {
+        case KEY_LEFT:
+            game.moveLeft();
+            incrementMoves();
             break;
-        case 2: // Remove row
-            removeRowActive = true;
+        case KEY_RIGHT:
+            game.moveRight();
+            incrementMoves();
             break;
-        case 3: // Freeze time
-            freezeTimeActive = true;
+        case KEY_UP:
+            game.moveUp();
+            incrementMoves();
+            break;
+        case KEY_DOWN:
+            game.moveDown();
+            incrementMoves();
             break;
     }
 }
 
-// Challenge Mode Implementation
-ChallengeMode::ChallengeMode()
-    : GameMode(GameModeType::CHALLENGE, "Challenge", "Complete specific objectives within constraints."),
-      targetScore(5000),
-      targetTile(512),
-      movesLimit(100),
-      movesUsed(0) {
+void ChallengeMode::render() {
+    // Rendering is handled by the UI class
+}
+
+void ChallengeMode::incrementMoves() {
+    movesUsed++;
+}
+
+bool ChallengeMode::checkVictory(const Game2048& game) const {
+    // Victory if either score target or tile target is reached
+    return (game.getScore() >= targetScore) || hasTargetTile(game);
 }
 
-void ChallengeMode::initialize() {
+bool ChallengeMode::hasTargetTile(const Game2048& game) const {
+    const auto& board = game.getBoard();
+    for (int i = 0; i < SIZE; ++i) {
+        for (int j = 0; j < SIZE; ++j) {
+            if (board[i][j].getValue() >= targetTile) {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+void ChallengeMode::nextLevel(Game2048& game) {
+    // Advance to next level
+    currentLevel++;
+    
+    // Update targets based on level
+    targetScore = 2000 * currentLevel;
+    targetTile = 128 * std::pow(2, currentLevel - 1);
+    movesLimit = 50 + (currentLevel * 10);
     movesUsed = 0;
+    
+    // Reset game state
+    game.resetBoard();
+    gameOver = false;
+    gameWon = false;
 }
 
-bool ChallengeMode::update(float deltaTime) {
-    return movesUsed < movesLimit;
+int ChallengeMode::getTargetScore() const {
+    return targetScore;
 }
 
-void ChallengeMode::render() {
-    // Rendering handled by the UI class
+int ChallengeMode::getTargetTile() const {
+    return targetTile;
+}
+
+int ChallengeMode::getMovesLimit() const {
+    return movesLimit;
+}
+
+int ChallengeMode::getMovesUsed() const {
+    return movesUsed;
+}
+
+int ChallengeMode::getMovesRemaining() const {
+    return movesLimit - movesUsed;
+}
+
+int ChallengeMode::getCurrentLevel() const {
+    return currentLevel;
+}
+
+//==============================================================================
+// ZenMode Implementation
+//==============================================================================
+ZenMode::ZenMode()
+    : GameMode(GameModeType::ZEN, "Zen", "Relaxed gameplay with no game over. Enjoy at your own pace."),
+      colorShiftEnabled(true), colorCycleTime(10.0f), currentColorTime(0.0f) {
+}
+
+void ZenMode::initialize(Game2048& game) {
+    game.resetBoard();
+    colorShiftEnabled = true;
+    currentColorTime = 0.0f;
+    gameOver = false;
+    gameWon = false;
+}
+
+bool ZenMode::update(Game2048& game, float deltaTime) {
+    // Update color cycle time
+    if (colorShiftEnabled) {
+        currentColorTime += deltaTime;
+        if (currentColorTime > colorCycleTime) {
+            currentColorTime -= colorCycleTime;
+        }
+    }
+    
+    // Check win condition but don't end game
+    if (game.hasWon() && !gameWon) {
+        gameWon = true;
+        return true;
+    }
+    
+    // No game over in Zen mode, just spawn a new tile if no moves possible
+    if (!game.canMove()) {
+        game.resetBoard();
+    }
+    
+    return false;
+}
+
+void ZenMode::handleInput(Game2048& game, int key) {
+    // Standard movement controls
+    switch (key) {
+        case KEY_LEFT:
+            game.moveLeft();
+            break;
+        case KEY_RIGHT:
+            game.moveRight();
+            break;
+        case KEY_UP:
+            game.moveUp();
+            break;
+        case KEY_DOWN:
+            game.moveDown();
+            break;
+        case 'c': // Toggle color shift
+            toggleColorShift();
+            break;
+    }
+}
+
+void ZenMode::render() {
+    // Rendering is handled by the UI class
+}
+
+float ZenMode::getCurrentColorPhase() const {
+    return currentColorTime / colorCycleTime;
+}
+
+bool ZenMode::isColorShiftEnabled() const {
+    return colorShiftEnabled;
+}
+
+void ZenMode::toggleColorShift() {
+    colorShiftEnabled = !colorShiftEnabled;
 }
 
-// Tutorial Mode Implementation
+//==============================================================================
+// TutorialMode Implementation
+//==============================================================================
 TutorialMode::TutorialMode()
     : GameMode(GameModeType::TUTORIAL, "Tutorial", "Learn how to play 2048."),
-      tutorialStep(0),
-      waitingForInput(true) {
+      tutorialStep(0), waitingForInput(true) {
+    
+    // Initialize tutorial messages
+    tutorialMessages = {
+        "Welcome to 2048! In this game, you'll combine tiles with the same number to create larger numbers.",
+        "Use the arrow keys to move all tiles in that direction. When two tiles with the same number touch, they merge!",
+        "The goal is to create a tile with the value 2048. Let's start by making your first move. Press an arrow key.",
+        "Great! Notice how tiles slide in the direction you pressed, and a new tile appears.",
+        "Try to create your first merge by moving tiles so that two equal numbers touch.",
+        "Excellent! When you merge tiles, their values add together. Keep merging to reach higher numbers.",
+        "Strategy tip: Try to keep your highest value tile in a corner, and build from there.",
+        "Another tip: Think ahead about what will happen when you make a move.",
+        "You're doing great! Keep practicing. Press any key to return to the main menu when you're ready."
+    };
 }
 
-void TutorialMode::initialize() {
+void TutorialMode::initialize(Game2048& game) {
+    game.resetBoard();
     tutorialStep = 0;
     waitingForInput = true;
+    gameOver = false;
+    gameWon = false;
 }
 
-bool TutorialMode::update(float deltaTime) {
-    // Tutorial is not time-based
-    return true;
+bool TutorialMode::update(Game2048& game, float deltaTime) {
+    // Tutorial mode is mostly waiting for input, not much to update
+    return false;
+}
+
+void TutorialMode::handleInput(Game2048& game, int key) {
+    // Progress through tutorial based on input
+    switch (tutorialStep) {
+        case 0: // Welcome
+        case 1: // Explaining controls
+            advanceTutorialStep();
+            break;
+        case 2: // First move
+            if (key == KEY_LEFT || key == KEY_RIGHT || key == KEY_UP || key == KEY_DOWN) {
+                // Process the move
+                if (key == KEY_LEFT) game.moveLeft();
+                else if (key == KEY_RIGHT) game.moveRight();
+                else if (key == KEY_UP) game.moveUp();
+                else game.moveDown();
+                
+                advanceTutorialStep();
+            }
+            break;
+        case 3: // Observed first move
+        case 4: // Try to merge
+            if (key == KEY_LEFT || key == KEY_RIGHT || key == KEY_UP || key == KEY_DOWN) {
+                // Process the move
+                if (key == KEY_LEFT) game.moveLeft();
+                else if (key == KEY_RIGHT) game.moveRight();
+                else if (key == KEY_UP) game.moveUp();
+                else game.moveDown();
+                
+                // Check if a merge happened
+                // This would require tracking of merges which we simulate here
+                if (tutorialStep == 4 && (rand() % 3 == 0)) { // Simulate detecting a merge
+                    advanceTutorialStep();
+                } else if (tutorialStep == 3) {
+                    advanceTutorialStep();
+                }
+            }
+            break;
+        case 5: // Merged successful
+        case 6: // Strategy tip 1
+        case 7: // Strategy tip 2
+        case 8: // Final message
+            advanceTutorialStep();
+            // Fix for signed/unsigned comparison warning
+            if (tutorialStep >= static_cast<int>(tutorialMessages.size())) {
+                // End of tutorial
+                gameOver = true;
+            }
+            break;
+    }
 }
 
 void TutorialMode::render() {
-    // Rendering handled by the UI class
+    // Rendering is handled by the UI class
 }
 
 void TutorialMode::advanceTutorialStep() {
     tutorialStep++;
     waitingForInput = true;
+}
+
+int TutorialMode::getTutorialStep() const {
+    return tutorialStep;
+}
+
+const std::string& TutorialMode::getCurrentMessage() const {
+    static const std::string endMessage = "Tutorial complete! You are now ready to play.";
+    
+    // Fix for signed/unsigned comparison warning
+    if (tutorialStep < static_cast<int>(tutorialMessages.size())) {
+        return tutorialMessages[tutorialStep];
+    }
+    return endMessage;
+}
+
+bool TutorialMode::isWaitingForInput() const {
+    return waitingForInput;
 }
\ No newline at end of file
diff --git a/src/SoundSystem.cpp b/src/SoundSystem.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..efaeb57686694931a2f7edf02b90a8321969ce62
--- /dev/null
+++ b/src/SoundSystem.cpp
@@ -0,0 +1,93 @@
+#include "SoundSystem.hpp"
+#include <iostream>
+
+// Mock implementation that doesn't use SDL2
+SoundSystem::SoundSystem()
+    : initialized(false), soundEnabled(false), musicEnabled(false),
+      soundVolume(0.0f), musicVolume(0.0f), currentMusic(MusicTrack::MENU) {
+}
+
+SoundSystem::~SoundSystem() {
+    // Nothing to do
+}
+
+bool SoundSystem::initialize() {
+    std::cout << "Sound system disabled (SDL2 not available)\n";
+    return false;
+}
+
+bool SoundSystem::initSDL() {
+    return false;
+}
+
+void SoundSystem::closeSDL() {
+    // Nothing to do
+}
+
+bool SoundSystem::loadSoundEffect(SoundEffect effect, const std::string& filePath) {
+    return false;
+}
+
+bool SoundSystem::loadMusicTrack(MusicTrack track, const std::string& filePath) {
+    return false;
+}
+
+void SoundSystem::playSound(SoundEffect effect) {
+    // Nothing to do
+}
+
+void SoundSystem::queueSound(SoundEffect effect, float delay) {
+    // Nothing to do
+}
+
+void SoundSystem::playMusic(MusicTrack track, bool loop) {
+    // Nothing to do
+}
+
+void SoundSystem::stopMusic() {
+    // Nothing to do
+}
+
+void SoundSystem::pauseMusic() {
+    // Nothing to do
+}
+
+void SoundSystem::resumeMusic() {
+    // Nothing to do
+}
+
+void SoundSystem::setSoundVolume(float volume) {
+    soundVolume = volume;
+}
+
+void SoundSystem::setMusicVolume(float volume) {
+    musicVolume = volume;
+}
+
+float SoundSystem::getSoundVolume() const {
+    return soundVolume;
+}
+
+float SoundSystem::getMusicVolume() const {
+    return musicVolume;
+}
+
+void SoundSystem::enableSound(bool enabled) {
+    soundEnabled = enabled;
+}
+
+void SoundSystem::enableMusic(bool enabled) {
+    musicEnabled = enabled;
+}
+
+bool SoundSystem::isSoundEnabled() const {
+    return soundEnabled;
+}
+
+bool SoundSystem::isMusicEnabled() const {
+    return musicEnabled;
+}
+
+void SoundSystem::update(float deltaTime) {
+    // Nothing to do
+}
\ No newline at end of file
diff --git a/src/Tile.cpp b/src/Tile.cpp
index 5a169ff090452a6c5c765382448c987bfe250676..bb9ebe0781a20acb1ce18ba58ccda8c34884df60 100644
--- a/src/Tile.cpp
+++ b/src/Tile.cpp
@@ -1,17 +1,103 @@
 #include "Tile.hpp"
 
-Tile::Tile() : value(0) {}
+Tile::Tile() : value(0), mergedThisTurn(false), isNew(false), animationProgress(0.0f) {}
 
 void Tile::setValue(int val) {
     value = val;
+    if (val > 0) {
+        isNew = true;
+    }
 }
 
 int Tile::getValue() const {
     return value;
 }
 
+void Tile::setMerged(bool merged) {
+    mergedThisTurn = merged;
+}
+
+bool Tile::getMerged() const {
+    return mergedThisTurn;
+}
+
+void Tile::setNew(bool newTile) {
+    isNew = newTile;
+}
+
+bool Tile::getNew() const {
+    return isNew;
+}
+
+void Tile::setAnimationProgress(float progress) {
+    animationProgress = progress;
+    if (progress >= 1.0f) {
+        // Reset flags when animation completes
+        isNew = false;
+        mergedThisTurn = false;
+    }
+}
+
+float Tile::getAnimationProgress() const {
+    return animationProgress;
+}
+
+void Tile::resetAnimation() {
+    animationProgress = 0.0f;
+    isNew = false;
+    mergedThisTurn = false;
+}
+
+std::string Tile::getBackgroundColor() const {
+    // Return appropriate background color based on tile value
+    switch (value) {
+        case 0: return "#CDC1B4";       // Empty tile color
+        case 2: return "#EEE4DA";       // 2 tile color
+        case 4: return "#EDE0C8";       // 4 tile color
+        case 8: return "#F2B179";       // 8 tile color
+        case 16: return "#F59563";      // 16 tile color
+        case 32: return "#F67C5F";      // 32 tile color
+        case 64: return "#F65E3B";      // 64 tile color
+        case 128: return "#EDCF72";     // 128 tile color
+        case 256: return "#EDCC61";     // 256 tile color
+        case 512: return "#EDC850";     // 512 tile color
+        case 1024: return "#EDC53F";    // 1024 tile color
+        case 2048: return "#EDC22E";    // 2048 tile color
+        default: return "#3C3A32";      // Higher value tiles
+    }
+}
+
+std::string Tile::getForegroundColor() const {
+    // Return appropriate text color based on tile value
+    if (value <= 4) {
+        return "#776E65";   // Dark text for low value tiles
+    } else {
+        return "#F9F6F2";   // Light text for high value tiles
+    }
+}
+
+std::string Tile::getColorCode() const {
+    // Return ncurses compatible color pair
+    if (value == 0) return "1";  // Default color
+    
+    switch (value) {
+        case 2: return "2";
+        case 4: return "3";
+        case 8: return "4";
+        case 16: return "5";
+        case 32: return "6";
+        case 64: return "7";
+        case 128: return "8";
+        case 256: return "9";
+        case 512: return "10";
+        case 1024: return "11";
+        case 2048: return "12";
+        default: return "13";    // Higher values
+    }
+}
+
 bool Tile::operator==(const Tile& other) const {
-    return value == other.value;
+    return value == other.value && value != 0;
 }
 
 Tile& Tile::operator*=(int multiplier) {
diff --git a/src/UI.cpp b/src/UI.cpp
index 3486cb957467fe2b8726820ea6568291f560e777..702a4914f0cdd70c3714fc3f32e8de53405d0173 100644
--- a/src/UI.cpp
+++ b/src/UI.cpp
@@ -1,27 +1,138 @@
 #include "UI.hpp"
-#include "2048.hpp"
-#include "Extra.hpp"
-#include "GameMode.hpp"
-#include <ncurses.h>
-#include <cstdlib>
+#include <cmath>
+#include <algorithm>
 #include <chrono>
+#include <thread>
+#include <fstream>
+#include <sstream>
+#include <ctime>
 
-UI::UI() : currentState(UIState::MAIN_MENU), selectedMenuOption(0), 
-    mainWindow(nullptr), gameWindow(nullptr), scoreWindow(nullptr), infoWindow(nullptr),
-    transitionTimer(0.0f), isTransitioning(false), currentGameMode(GameModeType::CLASSIC) {
+// Credit text with author name
+const std::string CREDIT_TEXT = "2048 Game - Created by Jamal Enoime";
+
+UI::UI()
+    : currentState(UIState::MAIN_MENU), previousState(UIState::MAIN_MENU), selectedMenuOption(0),
+      mainWindow(nullptr), gameWindow(nullptr), scoreWindow(nullptr), infoWindow(nullptr),
+      currentGameMode(GameModeType::CLASSIC), backgroundEffectTimer(0.0f),
+      soundEnabled(true), musicEnabled(true), animationsEnabled(true), highContrastMode(false),
+      currentTheme(0), creditsScrollY(0.0f) {
     
     // Initialize menu options
-    mainMenuOptions = {"Play Game", "Select Mode", "Tutorial", "Quit"};
-    modeSelectionOptions = {"Classic", "Timed", "Power-Up", "Challenge", "Back"};
-    pauseMenuOptions = {"Resume", "Restart", "Main Menu", "Quit"};
+    mainMenuOptions = {"Play Game", "Select Mode", "Settings", "Tutorial", "Credits", "Quit"};
+    modeSelectionOptions = {"Classic", "Timed", "Power-Up", "Challenge", "Zen", "Back"};
+    pauseMenuOptions = {"Resume", "Restart", "Settings", "Main Menu", "Quit"};
+    settingsOptions = {"Sound: ON", "Music: ON", "Animations: ON", "High Contrast: OFF", "Theme: Default", "Back"};
+    
+    // Initialize credits
+    credits = {
+        "2048 Game",
+        "",
+        "Created by Jamal Enoime",
+        "",
+        "Game Design",
+        "Jamal Enoime",
+        "",
+        "Programming",
+        "Jamal Enoime",
+        "",
+        "Graphics & UI",
+        "Jamal Enoime",
+        "",
+        "Sound Effects",
+        "freesound.org",
+        "",
+        "Music",
+        "bensound.com",
+        "",
+        "Special Thanks",
+        "To all the players!",
+        "",
+        "© 2025 Jamal Enoime"
+    };
+    
+    // Initialize themes
+    initializeThemes();
 }
 
 UI::~UI() {
     destroyWindows();
 }
 
-void UI::initialize() {
+bool UI::initialize() {
+    // Initialize ncurses
+    initscr();
+    start_color();
+    cbreak();
+    noecho();
+    keypad(stdscr, TRUE);
+    curs_set(0);  // Hide cursor
+    timeout(16);  // Non-blocking input with ~60fps refresh rate
+    
+    // Initialize color pairs
+    init_pair(1, COLOR_BLACK, COLOR_WHITE);      // Default
+    init_pair(2, COLOR_BLACK, COLOR_GREEN);      // 2
+    init_pair(3, COLOR_BLACK, COLOR_CYAN);       // 4
+    init_pair(4, COLOR_BLACK, COLOR_BLUE);       // 8
+    init_pair(5, COLOR_BLACK, COLOR_MAGENTA);    // 16
+    init_pair(6, COLOR_BLACK, COLOR_RED);        // 32
+    init_pair(7, COLOR_WHITE, COLOR_BLUE);       // 64
+    init_pair(8, COLOR_WHITE, COLOR_MAGENTA);    // 128
+    init_pair(9, COLOR_WHITE, COLOR_RED);        // 256
+    init_pair(10, COLOR_WHITE, COLOR_YELLOW);    // 512
+    init_pair(11, COLOR_BLACK, COLOR_YELLOW);    // 1024
+    init_pair(12, COLOR_WHITE, COLOR_GREEN);     // 2048
+    init_pair(13, COLOR_WHITE, COLOR_RED);       // Higher
+    init_pair(14, COLOR_YELLOW, COLOR_BLACK);    // Gold text
+    init_pair(15, COLOR_CYAN, COLOR_BLACK);      // Cyan text
+    init_pair(16, COLOR_MAGENTA, COLOR_BLACK);   // Magenta text
+    init_pair(17, COLOR_RED, COLOR_BLACK);       // Red text
+    init_pair(18, COLOR_GREEN, COLOR_BLACK);     // Green text
+    init_pair(19, COLOR_BLUE, COLOR_BLACK);      // Blue text
+    init_pair(20, COLOR_WHITE, COLOR_BLUE);      // White on blue
+    
+    // Initialize game
+    game = Game2048();
+    
+    // Initialize animations
+    animations = AnimationManager();
+    
+    // Initialize sound system
+    sounds.initialize();
+    if (musicEnabled) {
+        sounds.playMusic(MusicTrack::MENU, true);
+    }
+    
+    // Create windows
     createWindows();
+    
+    // Set up game callbacks
+    game.addObserver([this](GameEvent event, int row, int col, int value) {
+        switch (event) {
+            case GameEvent::TILE_MOVED:
+                // This event needs start and end positions - handled separately
+                break;
+            case GameEvent::TILE_MERGED:
+                onTileMerged(row, col, value);
+                break;
+            case GameEvent::TILE_SPAWNED:
+                onTileSpawned(row, col, value);
+                break;
+            case GameEvent::SCORE_CHANGED:
+                onScoreChanged(value, game.getScore() - value);
+                break;
+            case GameEvent::GAME_WON:
+                onVictory();
+                break;
+            case GameEvent::GAME_OVER:
+                onGameOver();
+                break;
+        }
+    });
+    
+    // Set default game mode
+    setGameMode(GameModeType::CLASSIC);
+    
+    return true;
 }
 
 void UI::createWindows() {
@@ -34,15 +145,12 @@ void UI::createWindows() {
     
     // Game window for the actual 2048 board
     gameWindow = newwin(SIZE * 2 + 2, SIZE * 6 + 2, 2, (maxX - (SIZE * 6 + 2)) / 2);
-    box(gameWindow, 0, 0);
     
     // Score window for displaying score and other game info
     scoreWindow = newwin(3, 20, 2, maxX - 25);
-    box(scoreWindow, 0, 0);
     
     // Info window for instructions and status messages
     infoWindow = newwin(5, maxX - 4, maxY - 6, 2);
-    box(infoWindow, 0, 0);
 }
 
 void UI::destroyWindows() {
@@ -52,20 +160,324 @@ void UI::destroyWindows() {
     if (infoWindow) delwin(infoWindow);
 }
 
+void UI::initializeThemes() {
+    // Default theme (original 2048 colors)
+    Theme defaultTheme;
+    defaultTheme.name = "Default";
+    defaultTheme.menuColor = 14; // Gold text
+    defaultTheme.backgroundColor = 1; // White background
+    defaultTheme.textColor = 0; // Black text
+    
+    // Neon theme
+    Theme neonTheme;
+    neonTheme.name = "Neon";
+    neonTheme.menuColor = 15; // Cyan text
+    neonTheme.backgroundColor = 0; // Black background
+    neonTheme.textColor = 15; // Cyan text
+    
+    // Dark theme
+    Theme darkTheme;
+    darkTheme.name = "Dark";
+    darkTheme.menuColor = 18; // Green text
+    darkTheme.backgroundColor = 0; // Black background
+    darkTheme.textColor = 7; // White text
+    
+    // Pastel theme
+    Theme pastelTheme;
+    pastelTheme.name = "Pastel";
+    pastelTheme.menuColor = 16; // Magenta text
+    pastelTheme.backgroundColor = 11; // Yellow background
+    pastelTheme.textColor = 4; // Blue text
+    
+    // Add themes to the list
+    themes.push_back(defaultTheme);
+    themes.push_back(neonTheme);
+    themes.push_back(darkTheme);
+    themes.push_back(pastelTheme);
+}
+
+void UI::applyTheme(int themeIndex) {
+    if (themeIndex < 0 || themeIndex >= static_cast<int>(themes.size())) {
+        return;
+    }
+    
+    currentTheme = themeIndex;
+    
+    // Apply theme colors
+    const Theme& theme = themes[currentTheme];
+    
+    // Update settings menu
+    settingsOptions[4] = "Theme: " + theme.name;
+}
+
+void UI::run() {
+    auto lastTime = std::chrono::high_resolution_clock::now();
+    
+    while (currentState != UIState::EXIT_CONFIRM) {
+        // Calculate delta time
+        auto currentTime = std::chrono::high_resolution_clock::now();
+        std::chrono::duration<float> duration = currentTime - lastTime;
+        float deltaTime = duration.count();
+        lastTime = currentTime;
+        
+        // Update background effect timer
+        backgroundEffectTimer += deltaTime;
+        
+        // Update animations
+        if (animationsEnabled) {
+            animations.update(deltaTime);
+            updateTextEffects(deltaTime);
+            updateConfetti(deltaTime);
+        }
+        
+        // Update sound system
+        sounds.update(deltaTime);
+        
+        // Update game mode
+        if (currentState == UIState::GAME_PLAYING && gameMode) {
+            gameMode->update(game, deltaTime);
+        }
+        
+        // Draw UI based on current state
+        switch (currentState) {
+            case UIState::MAIN_MENU:
+                drawMainMenu();
+                handleMainMenuInput();
+                break;
+                
+            case UIState::MODE_SELECTION:
+                drawModeSelection();
+                handleModeSelectionInput();
+                break;
+                
+            case UIState::GAME_PLAYING:
+                drawBoard();
+                drawScore();
+                drawInfo();
+                handleGameInput();
+                break;
+                
+            case UIState::PAUSE_MENU:
+                drawBoard(); // Draw board in background
+                drawPauseMenu();
+                handlePauseMenuInput();
+                break;
+                
+            case UIState::GAME_OVER:
+                drawBoard(); // Draw board in background
+                drawGameOver();
+                handlePauseMenuInput(); // Reusing pause menu input handler
+                break;
+                
+            case UIState::VICTORY:
+                drawBoard(); // Draw board in background
+                drawVictory();
+                handlePauseMenuInput(); // Reusing pause menu input handler
+                break;
+                
+            case UIState::TUTORIAL:
+                drawTutorial();
+                handleTutorialInput();
+                break;
+                
+            case UIState::SETTINGS:
+                drawSettings();
+                handleSettingsInput();
+                break;
+                
+            case UIState::CREDITS:
+                drawCredits();
+                handleCreditsInput();
+                break;
+                
+            case UIState::EXIT_CONFIRM:
+                drawExitConfirm();
+                handleExitConfirmInput();
+                break;
+        }
+        
+        // Limit frame rate to reduce CPU usage
+        std::this_thread::sleep_for(std::chrono::milliseconds(16)); // ~60 FPS
+    }
+    
+    // Clean up and exit
+    endwin();
+}
+
 void UI::setState(UIState newState) {
+    previousState = currentState;
     currentState = newState;
     selectedMenuOption = 0;
-    isTransitioning = true;
-    transitionTimer = 0.5f;
+    
+    // Add transition effect
+    if (animationsEnabled) {
+        if (newState == UIState::GAME_PLAYING) {
+            animations.addTransitionEffect("sparkle", 0.5f);
+        } else if (newState == UIState::GAME_OVER) {
+            animations.addTransitionEffect("fade", 0.7f);
+        } else if (newState == UIState::VICTORY) {
+            animations.addTransitionEffect("sparkle", 1.0f);
+            addConfetti(100);
+        } else {
+            animations.addTransitionEffect("slide", 0.3f);
+        }
+    }
+    
+    // Play sound effects
+    if (newState == UIState::GAME_PLAYING) {
+        sounds.playSound(SoundEffect::MENU_SELECT);
+        if (musicEnabled) {
+            sounds.playMusic(MusicTrack::GAMEPLAY);
+        }
+    } else if (newState == UIState::MAIN_MENU) {
+        sounds.playSound(SoundEffect::MENU_SELECT);
+        if (musicEnabled) {
+            sounds.playMusic(MusicTrack::MENU);
+        }
+    } else if (newState == UIState::GAME_OVER) {
+        sounds.playSound(SoundEffect::GAMEOVER);
+        if (musicEnabled) {
+            sounds.playMusic(MusicTrack::GAMEOVER);
+        }
+    } else if (newState == UIState::VICTORY) {
+        sounds.playSound(SoundEffect::VICTORY);
+        if (musicEnabled) {
+            sounds.playMusic(MusicTrack::VICTORY);
+        }
+    }
 }
 
 UIState UI::getState() const {
     return currentState;
 }
 
+void UI::setGameMode(GameModeType mode) {
+    currentGameMode = mode;
+    
+    // Create appropriate game mode instance using C++11 compatible syntax
+    switch (mode) {
+        case GameModeType::CLASSIC:
+            gameMode.reset(new ClassicMode());
+            break;
+        case GameModeType::TIMED:
+            gameMode.reset(new TimedMode());
+            break;
+        case GameModeType::POWERUP:
+            gameMode.reset(new PowerUpMode());
+            break;
+        case GameModeType::CHALLENGE:
+            gameMode.reset(new ChallengeMode());
+            break;
+        case GameModeType::ZEN:
+            gameMode.reset(new ZenMode());
+            break;
+        case GameModeType::TUTORIAL:
+            gameMode.reset(new TutorialMode());
+            break;
+    }
+    
+    // Initialize the game mode
+    if (gameMode) {
+        gameMode->initialize(game);
+    }
+}
+
+GameModeType UI::getGameMode() const {
+    return currentGameMode;
+}
+
+void UI::setTheme(int themeIndex) {
+    applyTheme(themeIndex);
+}
+
+int UI::getThemeCount() const {
+    return static_cast<int>(themes.size());
+}
+
+std::string UI::getThemeName(int index) const {
+    if (index >= 0 && index < static_cast<int>(themes.size())) {
+        return themes[index].name;
+    }
+    return "Unknown";
+}
+
+void UI::toggleSound() {
+    soundEnabled = !soundEnabled;
+    sounds.enableSound(soundEnabled);
+    settingsOptions[0] = std::string("Sound: ") + (soundEnabled ? "ON" : "OFF");
+}
+
+void UI::toggleMusic() {
+    musicEnabled = !musicEnabled;
+    sounds.enableMusic(musicEnabled);
+    settingsOptions[1] = std::string("Music: ") + (musicEnabled ? "ON" : "OFF");
+}
+
+void UI::toggleAnimations() {
+    animationsEnabled = !animationsEnabled;
+    settingsOptions[2] = std::string("Animations: ") + (animationsEnabled ? "ON" : "OFF");
+    
+    if (!animationsEnabled) {
+        animations.clearAnimations();
+        textEffects.clear();
+        confetti.clear();
+    }
+}
+
+void UI::toggleHighContrast() {
+    highContrastMode = !highContrastMode;
+    settingsOptions[3] = std::string("High Contrast: ") + (highContrastMode ? "ON" : "OFF");
+    
+    // Apply high contrast mode settings
+    if (highContrastMode) {
+        // Use high contrast colors
+        init_pair(1, COLOR_WHITE, COLOR_BLACK);
+        init_pair(2, COLOR_BLACK, COLOR_WHITE);
+        init_pair(3, COLOR_WHITE, COLOR_BLACK);
+        init_pair(4, COLOR_BLACK, COLOR_WHITE);
+        init_pair(5, COLOR_WHITE, COLOR_BLACK);
+        init_pair(6, COLOR_BLACK, COLOR_WHITE);
+        init_pair(7, COLOR_WHITE, COLOR_BLACK);
+        init_pair(8, COLOR_BLACK, COLOR_WHITE);
+        init_pair(9, COLOR_WHITE, COLOR_BLACK);
+        init_pair(10, COLOR_BLACK, COLOR_WHITE);
+        init_pair(11, COLOR_WHITE, COLOR_BLACK);
+        init_pair(12, COLOR_BLACK, COLOR_WHITE);
+        init_pair(13, COLOR_WHITE, COLOR_BLACK);
+    } else {
+        // Restore original colors
+        init_pair(1, COLOR_BLACK, COLOR_WHITE);
+        init_pair(2, COLOR_BLACK, COLOR_GREEN);
+        init_pair(3, COLOR_BLACK, COLOR_CYAN);
+        init_pair(4, COLOR_BLACK, COLOR_BLUE);
+        init_pair(5, COLOR_BLACK, COLOR_MAGENTA);
+        init_pair(6, COLOR_BLACK, COLOR_RED);
+        init_pair(7, COLOR_WHITE, COLOR_BLUE);
+        init_pair(8, COLOR_WHITE, COLOR_MAGENTA);
+        init_pair(9, COLOR_WHITE, COLOR_RED);
+        init_pair(10, COLOR_WHITE, COLOR_YELLOW);
+        init_pair(11, COLOR_BLACK, COLOR_YELLOW);
+        init_pair(12, COLOR_WHITE, COLOR_GREEN);
+        init_pair(13, COLOR_WHITE, COLOR_RED);
+    }
+}
+
+bool UI::setBackgroundImage(const std::string& filePath) {
+    backgroundImage = filePath;
+    
+    // In a real implementation, you would load the image here
+    // Since ncurses doesn't support images directly, this would require
+    // additional libraries or a custom solution
+    
+    return true;
+}
+
+// Drawing helpers
 void UI::drawCenteredText(WINDOW* win, int y, const std::string& text, bool highlight) {
-    int maxX, maxY;
+    int maxY, maxX;
     getmaxyx(win, maxY, maxX);
+    (void)maxY; // Explicitly mark maxY as unused to avoid warning
+    
     int x = (maxX - text.length()) / 2;
     
     if (highlight) wattron(win, A_REVERSE);
@@ -73,27 +485,194 @@ void UI::drawCenteredText(WINDOW* win, int y, const std::string& text, bool high
     if (highlight) wattroff(win, A_REVERSE);
 }
 
+void UI::drawBorderedWindow(WINDOW* win, const std::string& title) {
+    int maxY, maxX;
+    getmaxyx(win, maxY, maxX);
+    (void)maxY; // Explicitly mark maxY as unused to avoid warning
+    
+    // Draw the border
+    wborder(win, ACS_VLINE, ACS_VLINE, ACS_HLINE, ACS_HLINE, 
+            ACS_ULCORNER, ACS_URCORNER, ACS_LLCORNER, ACS_LRCORNER);
+    
+    // Draw the title if provided
+    if (!title.empty()) {
+        int titleX = (maxX - title.length()) / 2;
+        wattron(win, A_BOLD);
+        mvwprintw(win, 0, titleX, " %s ", title.c_str());
+        wattroff(win, A_BOLD);
+    }
+}
+
+void UI::drawProgressBar(WINDOW* win, int y, int x, int width, float progress, int colorPair) {
+    int filledWidth = static_cast<int>(width * std::min(1.0f, std::max(0.0f, progress)));
+    
+    wattron(win, COLOR_PAIR(colorPair) | A_BOLD);
+    for (int i = 0; i < filledWidth; i++) {
+        mvwaddch(win, y, x + i, ACS_BLOCK);
+    }
+    wattroff(win, COLOR_PAIR(colorPair) | A_BOLD);
+    
+    wattron(win, A_DIM);
+    for (int i = filledWidth; i < width; i++) {
+        mvwaddch(win, y, x + i, ACS_HLINE);
+    }
+    wattroff(win, A_DIM);
+}
+
+void UI::drawTile(WINDOW* win, int row, int col, int value) {
+    int colorPair;
+    switch (value) {
+        case 0: colorPair = 1; break;   // Empty tile
+        case 2: colorPair = 2; break;
+        case 4: colorPair = 3; break;
+        case 8: colorPair = 4; break;
+        case 16: colorPair = 5; break;
+        case 32: colorPair = 6; break;
+        case 64: colorPair = 7; break;
+        case 128: colorPair = 8; break;
+        case 256: colorPair = 9; break;
+        case 512: colorPair = 10; break;
+        case 1024: colorPair = 11; break;
+        case 2048: colorPair = 12; break;
+        default: colorPair = 13; break; // Higher values
+    }
+    
+    // Calculate screen position
+    int yPos = row * 2 + 1;
+    int xPos = col * 6 + 1;
+    
+    // Draw empty cell background
+    wattron(win, COLOR_PAIR(1));
+    mvwprintw(win, yPos, xPos, "     ");
+    wattroff(win, COLOR_PAIR(1));
+    
+    // Draw the tile with color if not empty
+    if (value != 0) {
+        // Add shadow effect for non-zero tiles
+        wattron(win, COLOR_PAIR(1) | A_DIM);
+        mvwprintw(win, yPos + 1, xPos + 1, "     ");
+        wattroff(win, COLOR_PAIR(1) | A_DIM);
+        
+        wattron(win, COLOR_PAIR(colorPair) | A_BOLD);
+        mvwprintw(win, yPos, xPos, "%5d", value);
+        wattroff(win, COLOR_PAIR(colorPair) | A_BOLD);
+        
+        // Add highlight to tiles with high values
+        if (value >= 128) {
+            wattron(win, A_DIM);
+            mvwaddch(win, yPos-1, xPos-1, '*');
+            mvwaddch(win, yPos-1, xPos+5, '*');
+            wattroff(win, A_DIM);
+        }
+    }
+}
+
+// Menu drawing functions
 void UI::drawMainMenu() {
     werase(mainWindow);
     
     int maxY, maxX;
     getmaxyx(mainWindow, maxY, maxX);
     
-    // Title with color
-    wattron(mainWindow, COLOR_PAIR(COLOR_PAIR_2048) | A_BOLD);
-    drawCenteredText(mainWindow, maxY / 4, "2048 GAME", false);
-    wattroff(mainWindow, COLOR_PAIR(COLOR_PAIR_2048) | A_BOLD);
+    // Draw animated background
+    if (animationsEnabled) {
+        animations.drawBackground(mainWindow);
+    }
     
-    // Menu options
-    for (size_t i = 0; i < mainMenuOptions.size(); i++) {
-        drawCenteredText(mainWindow, maxY / 3 + i * 2, mainMenuOptions[i], i == selectedMenuOption);
+    // Draw decorative frame around the title
+    int titleY = maxY / 4;
+    std::string title = "2048 GAME";
+    int titleLen = title.length();
+    int startX = (maxX - titleLen - 4) / 2;
+    
+    // Draw animated title frame with pulsing effect
+    float pulseEffect = sin(backgroundEffectTimer * 4) * 0.5f + 0.5f; // 0.0 to 1.0 pulsing
+    
+    for (int i = -2; i <= titleLen + 1; i++) {
+        if (pulseEffect > 0.7f || (i % 2 == 0 && pulseEffect > 0.3f)) {
+            mvwaddch(mainWindow, titleY - 1, startX + i, ACS_HLINE | A_BOLD);
+            mvwaddch(mainWindow, titleY + 1, startX + i, ACS_HLINE | A_BOLD);
+        }
+    }
+    
+    for (int i = -1; i <= 1; i++) {
+        if (pulseEffect > 0.7f || (i % 2 == 0 && pulseEffect > 0.3f)) {
+            mvwaddch(mainWindow, titleY + i, startX - 2, ACS_VLINE | A_BOLD);
+            mvwaddch(mainWindow, titleY + i, startX + titleLen + 1, ACS_VLINE | A_BOLD);
+        }
+    }
+    
+    // Draw corners with different characters based on animation
+    if (pulseEffect > 0.7f) {
+        mvwaddch(mainWindow, titleY - 1, startX - 2, ACS_ULCORNER | A_BOLD);
+        mvwaddch(mainWindow, titleY - 1, startX + titleLen + 1, ACS_URCORNER | A_BOLD);
+        mvwaddch(mainWindow, titleY + 1, startX - 2, ACS_LLCORNER | A_BOLD);
+        mvwaddch(mainWindow, titleY + 1, startX + titleLen + 1, ACS_LRCORNER | A_BOLD);
     }
     
-    // Footer
+    // Title with color and pulse effect
+    int colorPair = 14; // Gold color
+    if (pulseEffect > 0.8f) colorPair = 13; // Flash the title with red
+    
+    wattron(mainWindow, COLOR_PAIR(colorPair) | A_BOLD);
+    drawCenteredText(mainWindow, titleY, title, false);
+    wattroff(mainWindow, COLOR_PAIR(colorPair) | A_BOLD);
+    
+    // Subtitle with fade-in effect
+    std::string subtitle = "The Addictive Puzzle Game";
     wattron(mainWindow, A_DIM);
-    drawCenteredText(mainWindow, maxY - 2, "Use UP/DOWN to navigate, ENTER to select", false);
+    drawCenteredText(mainWindow, titleY + 3, subtitle, false);
     wattroff(mainWindow, A_DIM);
     
+    // Author credit
+    wattron(mainWindow, COLOR_PAIR(15) | A_DIM);
+    drawCenteredText(mainWindow, titleY + 4, "by Jamal Enoime", false);
+    wattroff(mainWindow, COLOR_PAIR(15) | A_DIM);
+    
+    // Menu options with animation and highlights
+    for (size_t i = 0; i < mainMenuOptions.size(); i++) {
+        int y = maxY / 3 + i * 2 + 5;
+        
+        // Add hover effects to selected option
+        if (static_cast<int>(i) == selectedMenuOption) {
+            // Draw animated arrows next to selected option
+            std::string menuText = ">> " + mainMenuOptions[i] + " <<";
+            
+            // Pulse effect for selected item
+            wattron(mainWindow, COLOR_PAIR(2) | A_BOLD);
+            drawCenteredText(mainWindow, y, menuText, true);
+            wattroff(mainWindow, COLOR_PAIR(2) | A_BOLD);
+            
+            // Add particle effects around selected menu item if animations enabled
+            if (animationsEnabled && rand() % 10 == 0) {
+                float centerX = maxX / 2;
+                animations.addParticleEffect(centerX, y, 2, 1);
+            }
+        } else {
+            // Normal style for non-selected items
+            wattron(mainWindow, A_NORMAL);
+            drawCenteredText(mainWindow, y, mainMenuOptions[i], false);
+            wattroff(mainWindow, A_NORMAL);
+        }
+    }
+    
+    // Footer with animation
+    float footerPulse = sin(backgroundEffectTimer * 2) * 0.5f + 0.5f;
+    int footerAttr = footerPulse > 0.7f ? A_BOLD : A_DIM;
+    
+    wattron(mainWindow, footerAttr);
+    drawCenteredText(mainWindow, maxY - 2, "Use UP/DOWN to navigate, ENTER to select", false);
+    wattroff(mainWindow, footerAttr);
+    
+    // Version info
+    mvwprintw(mainWindow, maxY - 1, 1, "v1.0");
+    
+    // Draw text effects and particles if animations enabled
+    if (animationsEnabled) {
+        drawTextEffects();
+        animations.draw(mainWindow, mainWindow); // Second window is ignored in main menu
+    }
+    
     wrefresh(mainWindow);
 }
 
@@ -103,45 +682,124 @@ void UI::drawModeSelection() {
     int maxY, maxX;
     getmaxyx(mainWindow, maxY, maxX);
     
-    // Title
-    wattron(mainWindow, COLOR_PAIR(COLOR_PAIR_1024) | A_BOLD);
+    // Draw animated background
+    if (animationsEnabled) {
+        animations.drawBackground(mainWindow);
+    }
+    
+    // Animated title with glow effect
+    float pulseEffect = sin(backgroundEffectTimer * 3) * 0.5f + 0.5f;
+    int colorPair = pulseEffect > 0.7f ? 11 : 10; // Alternate between yellow shades
+    
+    wattron(mainWindow, COLOR_PAIR(colorPair) | A_BOLD);
     drawCenteredText(mainWindow, maxY / 4, "SELECT GAME MODE", false);
-    wattroff(mainWindow, COLOR_PAIR(COLOR_PAIR_1024) | A_BOLD);
+    wattroff(mainWindow, COLOR_PAIR(colorPair) | A_BOLD);
     
-    // Mode options
+    // Mode options with animation
     for (size_t i = 0; i < modeSelectionOptions.size(); i++) {
-        drawCenteredText(mainWindow, maxY / 3 + i * 2, modeSelectionOptions[i], i == selectedMenuOption);
+        int y = maxY / 3 + i * 2 + 2;
+        
+        if (static_cast<int>(i) == selectedMenuOption) {
+            // Selected option gets special treatment
+            std::string optionText = "> " + modeSelectionOptions[i] + " <";
+            
+            // Determine appropriate color for the game mode
+            int modeColor;
+            switch (i) {
+                case 0: modeColor = 2; break; // Classic - Green
+                case 1: modeColor = 3; break; // Timed - Cyan
+                case 2: modeColor = 4; break; // Power-Up - Blue
+                case 3: modeColor = 5; break; // Challenge - Magenta
+                case 4: modeColor = 12; break; // Zen - White on Green
+                default: modeColor = 1; break; // Back - Default
+            }
+            
+            wattron(mainWindow, COLOR_PAIR(modeColor) | A_BOLD);
+            drawCenteredText(mainWindow, y, optionText, true);
+            wattroff(mainWindow, COLOR_PAIR(modeColor) | A_BOLD);
+            
+            // Add particle effects to selected option if animations enabled
+            if (animationsEnabled && rand() % 15 == 0) {
+                float centerX = maxX / 2;
+                animations.addParticleEffect(centerX, y, modeColor, 1);
+            }
+        } else {
+            // Non-selected options
+            wattron(mainWindow, A_NORMAL);
+            drawCenteredText(mainWindow, y, modeSelectionOptions[i], false);
+            wattroff(mainWindow, A_NORMAL);
+        }
     }
     
-    // Mode description (if one is selected)
-    if (selectedMenuOption < 4) {
+    // Mode description
+    if (selectedMenuOption < 5) {
         std::string description;
+        int descColor;
+        
         switch (selectedMenuOption) {
-            case 0: description = "Classic 2048 - Combine tiles to reach 2048!"; break;
-            case 1: description = "Timed Mode - Race against the clock!"; break;
-            case 2: description = "Power-Up Mode - Use special abilities!"; break;
-            case 3: description = "Challenge Mode - Complete specific objectives!"; break;
+            case 0: 
+                description = "Classic 2048 - Combine tiles to reach 2048!";
+                descColor = 2;
+                break;
+            case 1: 
+                description = "Timed Mode - Race against the clock!";
+                descColor = 3;
+                break;
+            case 2: 
+                description = "Power-Up Mode - Use special abilities!";
+                descColor = 4;
+                break;
+            case 3: 
+                description = "Challenge Mode - Complete specific objectives!";
+                descColor = 5;
+                break;
+            case 4:
+                description = "Zen Mode - Relaxed gameplay with no game over.";
+                descColor = 12;
+                break;
         }
         
-        wattron(mainWindow, A_DIM);
-        drawCenteredText(mainWindow, maxY / 3 + modeSelectionOptions.size() * 2 + 2, description, false);
-        wattroff(mainWindow, A_DIM);
+        // Animated reveal of description
+        static float descriptionReveal = 0.0f;
+        descriptionReveal += 0.05f;
+        if (descriptionReveal > 1.0f) descriptionReveal = 1.0f;
+        
+        int revealLength = static_cast<int>(description.length() * descriptionReveal);
+        
+        wattron(mainWindow, COLOR_PAIR(descColor) | A_DIM);
+        drawCenteredText(mainWindow, maxY / 3 + static_cast<int>(modeSelectionOptions.size()) * 2 + 4, 
+                        description.substr(0, revealLength), false);
+        wattroff(mainWindow, COLOR_PAIR(descColor) | A_DIM);
     }
     
-    // Navigation help
-    wattron(mainWindow, A_DIM);
+    // Navigation help with pulsing effect
+    float helpPulse = sin(backgroundEffectTimer * 2) * 0.5f + 0.5f;
+    int helpAttr = helpPulse > 0.7f ? A_NORMAL : A_DIM;
+    
+    wattron(mainWindow, helpAttr);
     drawCenteredText(mainWindow, maxY - 2, "Use UP/DOWN to navigate, ENTER to select", false);
-    wattroff(mainWindow, A_DIM);
+    wattroff(mainWindow, helpAttr);
+    
+    // Draw text effects and particles if animations enabled
+    if (animationsEnabled) {
+        drawTextEffects();
+        animations.draw(mainWindow, mainWindow);
+    }
     
     wrefresh(mainWindow);
 }
 
 void UI::drawPauseMenu() {
-    // Dim the background
+    // Semi-transparent overlay for the background
     wattron(mainWindow, A_DIM);
+    
+    // Create a pattern based on time
     for (int y = 0; y < getmaxy(mainWindow); y++) {
         for (int x = 0; x < getmaxx(mainWindow); x++) {
-            mvwaddch(mainWindow, y, x, ' ');
+            float wave = sin(backgroundEffectTimer * 2 + x * 0.05f + y * 0.05f) * 0.5f + 0.5f;
+            if ((x + y) % 4 == static_cast<int>(wave * 4)) {
+                mvwaddch(mainWindow, y, x, ' ' | A_REVERSE);
+            }
         }
     }
     wattroff(mainWindow, A_DIM);
@@ -150,407 +808,1287 @@ void UI::drawPauseMenu() {
     int maxY, maxX;
     getmaxyx(mainWindow, maxY, maxX);
     
-    int boxHeight = pauseMenuOptions.size() * 2 + 4;
-    int boxWidth = 20;
+    int boxHeight = static_cast<int>(pauseMenuOptions.size()) * 2 + 4;
+    int boxWidth = 25;
     int boxY = (maxY - boxHeight) / 2;
     int boxX = (maxX - boxWidth) / 2;
     
-    WINDOW* pauseWin = subwin(mainWindow, boxHeight, boxWidth, boxY, boxX);
-    box(pauseWin, 0, 0);
+    // Draw an animated border
+    wattron(mainWindow, A_BOLD);
+    for (int y = boxY; y < boxY + boxHeight; y++) {
+        for (int x = boxX; x < boxX + boxWidth; x++) {
+            if (y == boxY || y == boxY + boxHeight - 1 || 
+                x == boxX || x == boxX + boxWidth - 1) {
+                
+                // Make border pulse with time
+                float borderPulse = sin(backgroundEffectTimer * 4 + (x + y) * 0.2f) * 0.5f + 0.5f;
+                int borderChar = (borderPulse > 0.7f) ? '#' : 
+                                (borderPulse > 0.4f) ? ACS_BLOCK : 
+                                (x == boxX || x == boxX + boxWidth - 1) ? ACS_VLINE : ACS_HLINE;
+                    
+                mvwaddch(mainWindow, y, x, borderChar);
+            } else {
+                // Fill the background of the menu
+                mvwaddch(mainWindow, y, x, ' ');
+            }
+        }
+    }
+    wattroff(mainWindow, A_BOLD);
     
-    // Title
-    wattron(pauseWin, A_BOLD);
-    drawCenteredText(pauseWin, 1, "PAUSED", false);
-    wattroff(pauseWin, A_BOLD);
+    // Title with animation
+    wattron(mainWindow, COLOR_PAIR(13) | A_BOLD);
+    float titlePulse = sin(backgroundEffectTimer * 3) * 0.5f + 0.5f;
+    if (titlePulse > 0.7f) {
+        wattron(mainWindow, A_BLINK);
+    }
+    mvwprintw(mainWindow, boxY + 1, boxX + (boxWidth - 6) / 2, "PAUSED");
+    if (titlePulse > 0.7f) {
+        wattroff(mainWindow, A_BLINK);
+    }
+    wattroff(mainWindow, COLOR_PAIR(13) | A_BOLD);
     
-    // Menu options
+    // Menu options with animation effects
     for (size_t i = 0; i < pauseMenuOptions.size(); i++) {
-        drawCenteredText(pauseWin, 3 + i * 2, pauseMenuOptions[i], i == selectedMenuOption);
+        if (static_cast<int>(i) == selectedMenuOption) {
+            // Animated selected option
+            wattron(mainWindow, COLOR_PAIR(2) | A_BOLD);
+            std::string menuText = "> " + pauseMenuOptions[i] + " <";
+            
+            // Make the selected option "breathe"
+            float selectedPulse = sin(backgroundEffectTimer * 4) * 0.5f + 0.5f;
+            if (selectedPulse > 0.7f) {
+                wattron(mainWindow, A_BLINK);
+            }
+            
+            mvwprintw(mainWindow, boxY + 3 + static_cast<int>(i) * 2, 
+                     boxX + (boxWidth - static_cast<int>(menuText.length())) / 2, "%s", menuText.c_str());
+            
+            if (selectedPulse > 0.7f) {
+                wattroff(mainWindow, A_BLINK);
+            }
+            wattroff(mainWindow, COLOR_PAIR(2) | A_BOLD);
+        } else {
+            // Non-selected options
+            mvwprintw(mainWindow, boxY + 3 + static_cast<int>(i) * 2, 
+                     boxX + (boxWidth - static_cast<int>(pauseMenuOptions[i].length())) / 2, 
+                     "%s", pauseMenuOptions[i].c_str());
+        }
     }
     
-    wrefresh(pauseWin);
-    delwin(pauseWin);
+    // Draw text effects and particles if animations enabled
+    if (animationsEnabled) {
+        drawTextEffects();
+        animations.draw(mainWindow, mainWindow);
+    }
+    
+    wrefresh(mainWindow);
 }
 
-void UI::drawBoard(const Game2048& game) {
-    if (currentState != UIState::GAME_PLAYING) return;
+void UI::drawSettings() {
+    werase(mainWindow);
     
-    werase(gameWindow);
-    box(gameWindow, 0, 0);
+    int maxY, maxX;
+    getmaxyx(mainWindow, maxY, maxX);
     
-    // Display the board
-    for (int i = 0; i < SIZE; ++i) {
-        for (int j = 0; j < SIZE; ++j) {
-            int value = game.getBoard()[i][j].getValue();
-            int colorPair = getTileColorPair(value);
+    // Draw animated background
+    if (animationsEnabled) {
+        animations.drawBackground(mainWindow);
+    }
+    
+    // Title
+    wattron(mainWindow, COLOR_PAIR(15) | A_BOLD);
+    drawCenteredText(mainWindow, maxY / 4, "SETTINGS", false);
+    wattroff(mainWindow, COLOR_PAIR(15) | A_BOLD);
+    
+    // Settings options
+    for (size_t i = 0; i < settingsOptions.size(); i++) {
+        int y = maxY / 3 + static_cast<int>(i) * 2 + 2;
+        
+        if (static_cast<int>(i) == selectedMenuOption) {
+            // Selected option
+            std::string optionText = "> " + settingsOptions[i] + " <";
             
-            // Calculate position for the tile
-            int yPos = i * 2 + 1;
-            int xPos = j * 6 + 1;
+            wattron(mainWindow, COLOR_PAIR(3) | A_BOLD);
+            drawCenteredText(mainWindow, y, optionText, true);
+            wattroff(mainWindow, COLOR_PAIR(3) | A_BOLD);
             
-            // Draw the tile with color
-            wattron(gameWindow, COLOR_PAIR(colorPair) | A_BOLD);
-            if (value != 0) {
-                mvwprintw(gameWindow, yPos, xPos, "%5d", value);
-            } else {
-                mvwprintw(gameWindow, yPos, xPos, "     "); // Empty tile
+            // Add particle effects if animations enabled
+            if (animationsEnabled && rand() % 15 == 0) {
+                float centerX = maxX / 2;
+                animations.addParticleEffect(centerX, y, 3, 1);
             }
-            wattroff(gameWindow, COLOR_PAIR(colorPair) | A_BOLD);
+        } else {
+            // Non-selected options
+            wattron(mainWindow, A_NORMAL);
+            drawCenteredText(mainWindow, y, settingsOptions[i], false);
+            wattroff(mainWindow, A_NORMAL);
         }
     }
     
-    wrefresh(gameWindow);
-    
-    // Update score window
-    werase(scoreWindow);
-    box(scoreWindow, 0, 0);
-    
-    wattron(scoreWindow, COLOR_PAIR(COLOR_PAIR_HIGHER) | A_BOLD);
-    mvwprintw(scoreWindow, 1, 2, "Score: %d", game.getScore());
-    wattroff(scoreWindow, COLOR_PAIR(COLOR_PAIR_HIGHER) | A_BOLD);
-    
-    wrefresh(scoreWindow);
-    
-    // Update info window
-    werase(infoWindow);
-    box(infoWindow, 0, 0);
-    
-    mvwprintw(infoWindow, 1, 2, "Controls: Arrow keys to move");
-    mvwprintw(infoWindow, 2, 2, "P: Pause, R: Restart, Q: Quit");
+    // Navigation help
+    wattron(mainWindow, A_DIM);
+    drawCenteredText(mainWindow, maxY - 2, "Use UP/DOWN to navigate, ENTER to toggle, ESC to return", false);
+    wattroff(mainWindow, A_DIM);
     
-    if (currentGameMode == GameModeType::TIMED) {
-        mvwprintw(infoWindow, 3, 2, "Time left: %.1f", 180.0f); // Placeholder value
-    } else if (currentGameMode == GameModeType::POWERUP) {
-        mvwprintw(infoWindow, 3, 2, "Power-ups: 3  (1-3 to use)");
-    } else if (currentGameMode == GameModeType::CHALLENGE) {
-        mvwprintw(infoWindow, 3, 2, "Target: 512  Moves: 50/100");
+    // Draw text effects and particles if animations enabled
+    if (animationsEnabled) {
+        drawTextEffects();
+        animations.draw(mainWindow, mainWindow);
     }
     
-    wrefresh(infoWindow);
-}
-
-void UI::drawTimerInterface(float timeRemaining) {
-    mvwprintw(infoWindow, 3, 2, "Time left: %.1f", timeRemaining);
-    wrefresh(infoWindow);
-}
-
-void UI::drawPowerUpInterface(const PowerUpMode& powerUpMode) {
-    mvwprintw(infoWindow, 3, 2, "Power-ups available: %d", 3); // Placeholder
-    mvwprintw(infoWindow, 4, 2, "1: Double Score, 2: Clear Row, 3: Undo");
-    wrefresh(infoWindow);
-}
-
-void UI::drawChallengeInterface(int targetScore, int targetTile, int movesRemaining) {
-    mvwprintw(infoWindow, 3, 2, "Target: %d tile  Score: %d", targetTile, targetScore);
-    mvwprintw(infoWindow, 4, 2, "Moves remaining: %d", movesRemaining);
-    wrefresh(infoWindow);
+    wrefresh(mainWindow);
 }
 
-void UI::drawTutorial(int step) {
+void UI::drawCredits() {
     werase(mainWindow);
     
     int maxY, maxX;
     getmaxyx(mainWindow, maxY, maxX);
     
+    // Draw animated background
+    if (animationsEnabled) {
+        animations.drawBackground(mainWindow);
+    }
+    
     // Title
-    wattron(mainWindow, COLOR_PAIR(COLOR_PAIR_16) | A_BOLD);
-    drawCenteredText(mainWindow, 2, "TUTORIAL", false);
-    wattroff(mainWindow, COLOR_PAIR(COLOR_PAIR_16) | A_BOLD);
-    
-    // Tutorial content
-    std::string content;
-    switch (step) {
-        case 0:
-            content = "Welcome to 2048!";
-            mvwprintw(mainWindow, 5, 5, "In this game, you combine tiles with the same number");
-            mvwprintw(mainWindow, 6, 5, "to create a tile with the sum of those numbers.");
-            mvwprintw(mainWindow, 8, 5, "The goal is to create a tile with the value 2048.");
-            break;
-        case 1:
-            content = "Controls";
-            mvwprintw(mainWindow, 5, 5, "Use the arrow keys to move all tiles in that direction.");
-            mvwprintw(mainWindow, 6, 5, "When two tiles with the same number touch, they merge!");
-            mvwprintw(mainWindow, 8, 5, "Press 'r' to restart and 'q' to quit.");
-            break;
-        case 2:
-            content = "Game Modes";
-            mvwprintw(mainWindow, 5, 5, "Classic: Traditional 2048 gameplay");
-            mvwprintw(mainWindow, 6, 5, "Timed: Race against the clock");
-            mvwprintw(mainWindow, 7, 5, "Power-Up: Use special abilities");
-            mvwprintw(mainWindow, 8, 5, "Challenge: Meet specific objectives");
-            break;
-        case 3:
-            content = "Strategy";
-            mvwprintw(mainWindow, 5, 5, "Try to keep your highest tile in a corner.");
-            mvwprintw(mainWindow, 6, 5, "Plan your moves ahead. Don't make hasty decisions.");
-            mvwprintw(mainWindow, 7, 5, "Sometimes it's better to not merge tiles immediately.");
-            mvwprintw(mainWindow, 8, 5, "Focus on building up one corner of the board.");
-            break;
-        case 4:
-            content = "Ready to Play!";
-            mvwprintw(mainWindow, 5, 5, "You've completed the tutorial!");
-            mvwprintw(mainWindow, 6, 5, "Now it's time to play the game and reach 2048!");
-            mvwprintw(mainWindow, 8, 5, "Good luck!");
-            break;
-        default:
-            content = "End of Tutorial";
-            mvwprintw(mainWindow, 5, 5, "You're ready to play 2048!");
-            break;
+    wattron(mainWindow, COLOR_PAIR(14) | A_BOLD);
+    drawCenteredText(mainWindow, 2, "CREDITS", false);
+    wattroff(mainWindow, COLOR_PAIR(14) | A_BOLD);
+    
+    // Scroll credits
+    creditsScrollY += 0.05f;
+    if (creditsScrollY > credits.size() + maxY) {
+        creditsScrollY = 0;
     }
     
-    wattron(mainWindow, A_BOLD);
-    drawCenteredText(mainWindow, 3, content, false);
-    wattroff(mainWindow, A_BOLD);
+    for (size_t i = 0; i < credits.size(); i++) {
+        int y = 5 + static_cast<int>(i) - static_cast<int>(creditsScrollY);
+        
+        if (y >= 4 && y < maxY - 2) {
+            // Determine text style based on content
+            if (credits[i].empty()) {
+                // Empty line
+                continue;
+            } else if (i > 0 && credits[i-1].empty() && i+1 < credits.size() && !credits[i+1].empty()) {
+                // Section header
+                wattron(mainWindow, COLOR_PAIR(15) | A_BOLD);
+                drawCenteredText(mainWindow, y, credits[i], false);
+                wattroff(mainWindow, COLOR_PAIR(15) | A_BOLD);
+            } else if (credits[i] == "Jamal Enoime" || credits[i] == "Created by Jamal Enoime") {
+                // Author name with special styling
+                wattron(mainWindow, COLOR_PAIR(14) | A_BOLD);
+                drawCenteredText(mainWindow, y, credits[i], false);
+                wattroff(mainWindow, COLOR_PAIR(14) | A_BOLD);
+                
+                // Add sparkle effects around the author name if animations enabled
+                if (animationsEnabled && rand() % 10 == 0) {
+                    animations.addParticleEffect(maxX / 2, y, 14, 2);
+                }
+            } else {
+                // Regular text
+                drawCenteredText(mainWindow, y, credits[i], false);
+            }
+        }
+    }
     
-    // Navigation
+    // Navigation help
     wattron(mainWindow, A_DIM);
-    if (step < 4) {
-        drawCenteredText(mainWindow, maxY - 2, "Press SPACE to continue or ESC to exit", false);
-    } else {
-        drawCenteredText(mainWindow, maxY - 2, "Press ESC to return to main menu", false);
-    }
+    drawCenteredText(mainWindow, maxY - 2, "Press ESC to return to main menu", false);
     wattroff(mainWindow, A_DIM);
     
+    // Draw text effects and particles if animations enabled
+    if (animationsEnabled) {
+        drawTextEffects();
+        animations.draw(mainWindow, mainWindow);
+    }
+    
     wrefresh(mainWindow);
 }
 
-void UI::handleInput(Game2048& game) {
-    switch (currentState) {
-        case UIState::MAIN_MENU:
-            handleMenuInput();
-            break;
-            
-        case UIState::MODE_SELECTION:
-            handleMenuInput();
-            break;
-            
-        case UIState::GAME_PLAYING: {
-            int ch = wgetch(mainWindow);
-            switch (ch) {
-                case KEY_LEFT: game.moveLeft(); break;
-                case KEY_RIGHT: game.moveRight(); break;
-                case KEY_UP: game.moveUp(); break;
-                case KEY_DOWN: game.moveDown(); break;
-                case 'r': case 'R': game.resetBoard(); break;
-                case 'p': case 'P': setState(UIState::PAUSE_MENU); break;
-                case 'q': case 'Q': setState(UIState::MAIN_MENU); break;
-                    
-                // PowerUp mode specific keys
-                case '1':
-                    if (currentGameMode == GameModeType::POWERUP) {
-                        // Activate power-up 1 (would need PowerUpMode instance)
-                    }
-                    break;
-                case '2':
-                    if (currentGameMode == GameModeType::POWERUP) {
-                        // Activate power-up 2
-                    }
-                    break;
-                case '3':
-                    if (currentGameMode == GameModeType::POWERUP) {
-                        // Activate power-up 3
-                    }
-                    break;
-            }
-            break;
-        }
-            
-        case UIState::PAUSE_MENU:
-            handleMenuInput();
+void UI::drawExitConfirm() {
+    // Semi-transparent overlay
+    wattron(mainWindow, A_DIM);
+    
+    int maxY, maxX;
+    getmaxyx(mainWindow, maxY, maxX);
+    
+    for (int y = 0; y < maxY; y++) {
+        for (int x = 0; x < maxX; x++) {
+            mvwaddch(mainWindow, y, x, ' ' | A_REVERSE);
+        }
+    }
+    wattroff(mainWindow, A_DIM);
+    
+    // Confirmation box
+    int boxHeight = 7;
+    int boxWidth = 40;
+    int boxY = (maxY - boxHeight) / 2;
+    int boxX = (maxX - boxWidth) / 2;
+    
+    // Draw box with border
+    wattron(mainWindow, A_BOLD);
+    for (int y = boxY; y < boxY + boxHeight; y++) {
+        for (int x = boxX; x < boxX + boxWidth; x++) {
+            if (y == boxY || y == boxY + boxHeight - 1 || x == boxX || x == boxX + boxWidth - 1) {
+                mvwaddch(mainWindow, y, x, ACS_BLOCK);
+            } else {
+                mvwaddch(mainWindow, y, x, ' ');
+            }
+        }
+    }
+    wattroff(mainWindow, A_BOLD);
+    
+    // Question
+    wattron(mainWindow, COLOR_PAIR(17) | A_BOLD);
+    mvwprintw(mainWindow, boxY + 2, boxX + (boxWidth - 29) / 2, "Are you sure you want to quit?");
+    wattroff(mainWindow, COLOR_PAIR(17) | A_BOLD);
+    
+    // Options
+    std::string yes = "Yes";
+    std::string no = "No";
+    
+    // Highlight the selected option
+    if (selectedMenuOption == 0) {
+        wattron(mainWindow, COLOR_PAIR(17) | A_BOLD | A_REVERSE);
+        mvwprintw(mainWindow, boxY + 4, boxX + boxWidth / 3 - 2, "%s", yes.c_str());
+        wattroff(mainWindow, COLOR_PAIR(17) | A_BOLD | A_REVERSE);
+        
+        wattron(mainWindow, COLOR_PAIR(18) | A_BOLD);
+        mvwprintw(mainWindow, boxY + 4, boxX + 2 * boxWidth / 3 - 2, "%s", no.c_str());
+        wattroff(mainWindow, COLOR_PAIR(18) | A_BOLD);
+    } else {
+        wattron(mainWindow, COLOR_PAIR(17) | A_BOLD);
+        mvwprintw(mainWindow, boxY + 4, boxX + boxWidth / 3 - 2, "%s", yes.c_str());
+        wattroff(mainWindow, COLOR_PAIR(17) | A_BOLD);
+        
+        wattron(mainWindow, COLOR_PAIR(18) | A_BOLD | A_REVERSE);
+        mvwprintw(mainWindow, boxY + 4, boxX + 2 * boxWidth / 3 - 2, "%s", no.c_str());
+        wattroff(mainWindow, COLOR_PAIR(18) | A_BOLD | A_REVERSE);
+    }
+    
+    // Draw text effects and particles if animations enabled
+    if (animationsEnabled) {
+        drawTextEffects();
+        animations.draw(mainWindow, mainWindow);
+    }
+    
+    wrefresh(mainWindow);
+}
+
+void UI::drawBoard() {
+    if (currentState != UIState::GAME_PLAYING && 
+        currentState != UIState::PAUSE_MENU && 
+        currentState != UIState::GAME_OVER && 
+        currentState != UIState::VICTORY) {
+        return;
+    }
+    
+    werase(gameWindow);
+    
+    // Draw fancy border with double lines
+    drawBorderedWindow(gameWindow, "2048");
+    
+    // Display the board (static tiles, animations are drawn separately)
+    const auto& board = game.getBoard();
+    for (int i = 0; i < SIZE; ++i) {
+        for (int j = 0; j < SIZE; ++j) {
+            int value = board[i][j].getValue();
+            drawTile(gameWindow, i, j, value);
+        }
+    }
+    
+    // Draw animations if enabled
+    if (animationsEnabled) {
+        animations.draw(mainWindow, gameWindow);
+    }
+    
+    // Draw confetti for victory state
+    if (currentState == UIState::VICTORY && animationsEnabled) {
+        drawConfetti();
+    }
+    
+    wrefresh(gameWindow);
+}
+
+void UI::drawScore() {
+    werase(scoreWindow);
+    
+    // Draw border
+    drawBorderedWindow(scoreWindow, "Score");
+    
+    // Current score with animation
+    wattron(scoreWindow, COLOR_PAIR(13) | A_BOLD);
+    mvwprintw(scoreWindow, 1, 2, "%d", game.getScore());
+    wattroff(scoreWindow, COLOR_PAIR(13) | A_BOLD);
+    
+    // High score
+    wattron(scoreWindow, COLOR_PAIR(14) | A_NORMAL);
+    mvwprintw(scoreWindow, 2, 2, "Best: %d", game.getHighScore());
+    wattroff(scoreWindow, COLOR_PAIR(14) | A_NORMAL);
+    
+    wrefresh(scoreWindow);
+}
+
+void UI::drawInfo() {
+    werase(infoWindow);
+    
+    // Draw border
+    drawBorderedWindow(infoWindow, "Info");
+    
+    // Add a title to info window
+    wattron(infoWindow, A_BOLD);
+    mvwprintw(infoWindow, 1, 2, "Controls:");
+    wattroff(infoWindow, A_BOLD);
+    mvwprintw(infoWindow, 1, 12, "↑↓←→ to move");
+    
+    mvwprintw(infoWindow, 2, 2, "P: Pause  R: Restart  Q: Quit");
+    
+    // Draw mode-specific info
+    if (gameMode) {
+        switch (currentGameMode) {
+            case GameModeType::TIMED:
+                drawTimedModeUI();
+                break;
+            case GameModeType::POWERUP:
+                drawPowerUpModeUI();
+                break;
+            case GameModeType::CHALLENGE:
+                drawChallengeModeUI();
+                break;
+            case GameModeType::ZEN:
+                drawZenModeUI();
+                break;
+            case GameModeType::CLASSIC:
+            default:
+                // Classic mode - show goal
+                wattron(infoWindow, COLOR_PAIR(12) | A_BOLD);
+                mvwprintw(infoWindow, 3, 2, "🏆 Goal: Reach 2048 tile!");
+                wattroff(infoWindow, COLOR_PAIR(12) | A_BOLD);
+                break;
+        }
+    }
+    
+    wrefresh(infoWindow);
+}
+
+void UI::drawTimedModeUI() {
+    TimedMode* timedMode = dynamic_cast<TimedMode*>(gameMode.get());
+    if (!timedMode) return;
+    
+    // Get time remaining
+    float timeRemaining = timedMode->getTimeRemaining();
+    
+    // Choose color based on time remaining
+    int colorPair;
+    if (timeRemaining > 60.0f) {
+        colorPair = 2; // Green - plenty of time
+    } else if (timeRemaining > 30.0f) {
+        colorPair = 11; // Yellow - getting low
+    } else if (timeRemaining > 10.0f) {
+        colorPair = 6; // Red - very low
+    } else {
+        // Flash red when time is critical (under 10 seconds)
+        colorPair = 13; 
+        wattron(infoWindow, A_BLINK);
+    }
+    
+    // Draw time remaining
+    wattron(infoWindow, COLOR_PAIR(colorPair) | A_BOLD);
+    mvwprintw(infoWindow, 3, 2, "⏱ Time left: %.1f", timeRemaining);
+    wattroff(infoWindow, COLOR_PAIR(colorPair) | A_BOLD);
+    
+    if (timeRemaining <= 10.0f) {
+        wattroff(infoWindow, A_BLINK);
+    }
+    
+    // Draw progress bar
+    int barWidth = 30;
+    float progress = timeRemaining / 180.0f; // Assuming 180 seconds total
+    drawProgressBar(infoWindow, 4, 2, barWidth, progress, colorPair);
+}
+
+void UI::drawPowerUpModeUI() {
+    PowerUpMode* powerUpMode = dynamic_cast<PowerUpMode*>(gameMode.get());
+    if (!powerUpMode) return;
+    
+    // Get powerup counts
+    int doubleScorePowerups = powerUpMode->getDoubleScorePowerups();
+    int clearRowPowerups = powerUpMode->getClearRowPowerups();
+    int undoMovePowerups = powerUpMode->getUndoMovePowerups();
+    int upgradeTilePowerups = powerUpMode->getUpgradeTilePowerups();
+    
+    // Draw powerup information
+    wattron(infoWindow, COLOR_PAIR(4) | A_BOLD);
+    mvwprintw(infoWindow, 3, 2, "✨ PowerUps:");
+    wattroff(infoWindow, COLOR_PAIR(4) | A_BOLD);
+    
+    // Double score powerup
+    wattron(infoWindow, doubleScorePowerups > 0 ? A_NORMAL : A_DIM);
+    mvwprintw(infoWindow, 4, 2, "1:2xScore(%d)", doubleScorePowerups);
+    wattroff(infoWindow, doubleScorePowerups > 0 ? A_NORMAL : A_DIM);
+    
+    // Clear row powerup
+    wattron(infoWindow, clearRowPowerups > 0 ? A_NORMAL : A_DIM);
+    mvwprintw(infoWindow, 4, 15, "2:Clear(%d)", clearRowPowerups);
+    wattroff(infoWindow, clearRowPowerups > 0 ? A_NORMAL : A_DIM);
+    
+    // Undo move powerup
+    wattron(infoWindow, undoMovePowerups > 0 ? A_NORMAL : A_DIM);
+    mvwprintw(infoWindow, 4, 28, "3:Undo(%d)", undoMovePowerups);
+    wattroff(infoWindow, undoMovePowerups > 0 ? A_NORMAL : A_DIM);
+    
+    // Upgrade tile powerup
+    wattron(infoWindow, upgradeTilePowerups > 0 ? A_NORMAL : A_DIM);
+    mvwprintw(infoWindow, 4, 40, "4:Upgrade(%d)", upgradeTilePowerups);
+    wattroff(infoWindow, upgradeTilePowerups > 0 ? A_NORMAL : A_DIM);
+    
+    // Display if double score is active
+    if (powerUpMode->isDoubleScoreActive()) {
+        wattron(infoWindow, COLOR_PAIR(11) | A_BOLD | A_BLINK);
+        mvwprintw(infoWindow, 3, 15, "2X SCORE ACTIVE! (%d turns)", 
+                 powerUpMode->getDoubleScoreTurnsLeft());
+        wattroff(infoWindow, COLOR_PAIR(11) | A_BOLD | A_BLINK);
+    }
+}
+
+void UI::drawChallengeModeUI() {
+    ChallengeMode* challengeMode = dynamic_cast<ChallengeMode*>(gameMode.get());
+    if (!challengeMode) return;
+    
+    // Get challenge targets
+    int targetScore = challengeMode->getTargetScore();
+    int targetTile = challengeMode->getTargetTile();
+    int movesRemaining = challengeMode->getMovesRemaining();
+    int currentLevel = challengeMode->getCurrentLevel();
+    
+    // Draw challenge information
+    wattron(infoWindow, COLOR_PAIR(5) | A_BOLD);
+    mvwprintw(infoWindow, 3, 2, "🎯 Level %d Challenge:", currentLevel);
+    wattroff(infoWindow, COLOR_PAIR(5) | A_BOLD);
+    
+    // Draw target score
+    mvwprintw(infoWindow, 4, 2, "Score: %d/%d", game.getScore(), targetScore);
+    
+    // Draw progress bar for score
+    float scoreProgress = std::min(1.0f, static_cast<float>(game.getScore()) / targetScore);
+    drawProgressBar(infoWindow, 4, 20, 15, scoreProgress, 5);
+    
+    // Draw target tile
+    mvwprintw(infoWindow, 4, 37, "Tile: %d", targetTile);
+    
+    // Draw moves remaining
+    int moveColor = movesRemaining > 10 ? 2 : (movesRemaining > 5 ? 11 : 13);
+    wattron(infoWindow, COLOR_PAIR(moveColor) | A_BOLD);
+    mvwprintw(infoWindow, 3, 23, "Moves: %d", movesRemaining);
+    wattroff(infoWindow, COLOR_PAIR(moveColor) | A_BOLD);
+}
+
+void UI::drawZenModeUI() {
+    ZenMode* zenMode = dynamic_cast<ZenMode*>(gameMode.get());
+    if (!zenMode) return;
+    
+    // Draw zen mode information
+    wattron(infoWindow, COLOR_PAIR(12) | A_BOLD);
+    mvwprintw(infoWindow, 3, 2, "☯ Zen Mode - Relax and enjoy");
+    wattroff(infoWindow, COLOR_PAIR(12) | A_BOLD);
+    
+    // Draw color shift info
+    mvwprintw(infoWindow, 4, 2, "Press C to %s color shift", 
+             zenMode->isColorShiftEnabled() ? "disable" : "enable");
+}
+
+void UI::drawTutorial() {
+    werase(mainWindow);
+    
+    int maxY, maxX;
+    getmaxyx(mainWindow, maxY, maxX);
+    
+    // Draw animated background
+    if (animationsEnabled) {
+        animations.drawBackground(mainWindow);
+    }
+    
+    TutorialMode* tutorialMode = dynamic_cast<TutorialMode*>(gameMode.get());
+    if (!tutorialMode) {
+        // Create new tutorial mode if needed (use C++11 style here too)
+        tutorialMode = new TutorialMode();
+        tutorialMode->initialize(game);
+    }
+    
+    // Title with animated underline
+    wattron(mainWindow, COLOR_PAIR(5) | A_BOLD);
+    drawCenteredText(mainWindow, 2, "TUTORIAL", false);
+    wattroff(mainWindow, COLOR_PAIR(5) | A_BOLD);
+    
+    // Animated underline
+    int titleWidth = 8; // "TUTORIAL" length
+    int startX = (maxX - titleWidth) / 2;
+    float underlinePulse = sin(backgroundEffectTimer * 3) * 0.5f + 0.5f;
+    
+    wattron(mainWindow, COLOR_PAIR(5) | (underlinePulse > 0.7 ? A_BOLD : A_NORMAL));
+    for (int x = 0; x < titleWidth; x++) {
+        if (underlinePulse > 0.3 || x % 2 == 0) {
+            mvwaddch(mainWindow, 3, startX + x, ACS_HLINE);
+        }
+    }
+    wattroff(mainWindow, COLOR_PAIR(5) | (underlinePulse > 0.7 ? A_BOLD : A_NORMAL));
+    
+    // Tutorial progress
+    int step = tutorialMode->getTutorialStep();
+    
+    // Step indicator
+    std::string stepText = "Step " + std::to_string(step + 1) + " of 9";
+    wattron(mainWindow, A_DIM);
+    mvwprintw(mainWindow, 5, 5, "%s", stepText.c_str());
+    wattroff(mainWindow, A_DIM);
+    
+    // Progress bar
+    int progressWidth = maxX - 10;
+    float progress = (step + 1) / 9.0f;
+    drawProgressBar(mainWindow, 6, 5, progressWidth, progress, 5);
+    
+    // Display the tutorial message
+    const std::string& message = tutorialMode->getCurrentMessage();
+    
+    // Add a text box for the message
+    int msgBoxY = 8;
+    int msgBoxHeight = 6;
+    int msgBoxWidth = maxX - 10;
+    int msgBoxX = 5;
+    
+    // Draw box
+    for (int y = msgBoxY; y < msgBoxY + msgBoxHeight; y++) {
+        for (int x = msgBoxX; x < msgBoxX + msgBoxWidth; x++) {
+            if (y == msgBoxY || y == msgBoxY + msgBoxHeight - 1 ||
+                x == msgBoxX || x == msgBoxX + msgBoxWidth - 1) {
+                mvwaddch(mainWindow, y, x, ACS_BLOCK);
+            } else {
+                mvwaddch(mainWindow, y, x, ' ');
+            }
+        }
+    }
+    
+    // Display message with word wrapping
+    std::istringstream iss(message);
+    std::string word;
+    std::string line;
+    int lineY = msgBoxY + 1;
+    int lineX = msgBoxX + 2;
+    int maxLineWidth = msgBoxWidth - 4;
+    
+    while (iss >> word) {
+        if (static_cast<int>(line.length() + word.length() + 1) > maxLineWidth) {
+            mvwprintw(mainWindow, lineY++, lineX, "%s", line.c_str());
+            line = word;
+        } else {
+            if (!line.empty()) line += " ";
+            line += word;
+        }
+    }
+    
+    if (!line.empty()) {
+        mvwprintw(mainWindow, lineY, lineX, "%s", line.c_str());
+    }
+    
+    // Display game board if needed for tutorial
+    if (step >= 2) {
+        drawBoard();
+    }
+    
+    // Navigation instructions
+    wattron(mainWindow, A_DIM);
+    if (step < 8) {
+        drawCenteredText(mainWindow, maxY - 2, "Press SPACE to continue or ESC to exit", false);
+    } else {
+        float finalPulse = sin(backgroundEffectTimer * 3) * 0.5f + 0.5f;
+        if (finalPulse > 0.7) {
+            wattron(mainWindow, A_BOLD);
+        }
+        drawCenteredText(mainWindow, maxY - 2, "Press any key to return to main menu", false);
+        if (finalPulse > 0.7) {
+            wattroff
+            (mainWindow, A_BOLD);
+        }
+    }
+    wattroff(mainWindow, A_DIM);
+    
+    // Draw animations if enabled
+    if (animationsEnabled) {
+        animations.draw(mainWindow, gameWindow);
+    }
+    
+    wrefresh(mainWindow);
+    if (step >= 2) {
+        wrefresh(gameWindow);
+    }
+}
+
+void UI::drawGameOver() {
+    int maxY, maxX;
+    getmaxyx(mainWindow, maxY, maxX);
+    
+    // Display game over overlay
+    int boxHeight = 7;
+    int boxWidth = 30;
+    int boxY = (maxY - boxHeight) / 2;
+    int boxX = (maxX - boxWidth) / 2;
+    
+    // Draw semi-transparent background
+    for (int y = 0; y < maxY; y++) {
+        for (int x = 0; x < maxX; x++) {
+            if ((y + x) % 2 == 0) {
+                wattron(mainWindow, A_DIM);
+                mvwaddch(mainWindow, y, x, ' ' | A_REVERSE);
+                wattroff(mainWindow, A_DIM);
+            }
+        }
+    }
+    
+    // Draw game over box
+    for (int y = boxY; y < boxY + boxHeight; y++) {
+        for (int x = boxX; x < boxX + boxWidth; x++) {
+            if (y == boxY || y == boxY + boxHeight - 1 || 
+                x == boxX || x == boxX + boxWidth - 1) {
+                wattron(mainWindow, COLOR_PAIR(13) | A_BOLD);
+                mvwaddch(mainWindow, y, x, ACS_BLOCK);
+                wattroff(mainWindow, COLOR_PAIR(13) | A_BOLD);
+            } else {
+                mvwaddch(mainWindow, y, x, ' ');
+            }
+        }
+    }
+    
+    // Draw game over message
+    wattron(mainWindow, COLOR_PAIR(13) | A_BOLD);
+    mvwprintw(mainWindow, boxY + 2, boxX + (boxWidth - 9) / 2, "GAME OVER");
+    wattroff(mainWindow, COLOR_PAIR(13) | A_BOLD);
+    
+    // Draw final score
+    wattron(mainWindow, COLOR_PAIR(15) | A_BOLD);
+    std::string scoreText = "Final Score: " + std::to_string(game.getScore());
+    mvwprintw(mainWindow, boxY + 4, boxX + (boxWidth - static_cast<int>(scoreText.length())) / 2, 
+             "%s", scoreText.c_str());
+    wattroff(mainWindow, COLOR_PAIR(15) | A_BOLD);
+    
+    // Instruction to continue
+    wattron(mainWindow, A_DIM);
+    mvwprintw(mainWindow, boxY + 6, boxX + 2, "Press any key to continue");
+    wattroff(mainWindow, A_DIM);
+}
+
+void UI::drawVictory() {
+    int maxY, maxX;
+    getmaxyx(mainWindow, maxY, maxX);
+    
+    // Display victory overlay
+    int boxHeight = 9;
+    int boxWidth = 40;
+    int boxY = (maxY - boxHeight) / 2;
+    int boxX = (maxX - boxWidth) / 2;
+    
+    // Draw animated background
+    for (int y = 0; y < maxY; y++) {
+        for (int x = 0; x < maxX; x++) {
+            float wave = sin(backgroundEffectTimer * 3 + (x + y) * 0.1f) * 0.5f + 0.5f;
+            if (wave > 0.7f) {
+                wattron(mainWindow, COLOR_PAIR(14) | A_DIM);
+                mvwaddch(mainWindow, y, x, '*');
+                wattroff(mainWindow, COLOR_PAIR(14) | A_DIM);
+            }
+        }
+    }
+    
+    // Draw victory box
+    for (int y = boxY; y < boxY + boxHeight; y++) {
+        for (int x = boxX; x < boxX + boxWidth; x++) {
+            if (y == boxY || y == boxY + boxHeight - 1 || 
+                x == boxX || x == boxX + boxWidth - 1) {
+                wattron(mainWindow, COLOR_PAIR(12) | A_BOLD);
+                mvwaddch(mainWindow, y, x, ACS_BLOCK);
+                wattroff(mainWindow, COLOR_PAIR(12) | A_BOLD);
+            } else {
+                mvwaddch(mainWindow, y, x, ' ');
+            }
+        }
+    }
+    
+    // Victory message with pulsing animation
+    float pulse = sin(backgroundEffectTimer * 4) * 0.5f + 0.5f;
+    int colorPair = pulse > 0.7f ? 12 : 14;
+    
+    wattron(mainWindow, COLOR_PAIR(colorPair) | A_BOLD);
+    mvwprintw(mainWindow, boxY + 2, boxX + (boxWidth - 18) / 2, "VICTORY! YOU WIN!");
+    wattroff(mainWindow, COLOR_PAIR(colorPair) | A_BOLD);
+    
+    // Congratulatory message
+    wattron(mainWindow, COLOR_PAIR(15) | A_NORMAL);
+    mvwprintw(mainWindow, boxY + 4, boxX + 2, "Congratulations! You've reached 2048!");
+    wattroff(mainWindow, COLOR_PAIR(15) | A_NORMAL);
+    
+    // Draw final score
+    wattron(mainWindow, COLOR_PAIR(14) | A_BOLD);
+    std::string scoreText = "Final Score: " + std::to_string(game.getScore());
+    mvwprintw(mainWindow, boxY + 6, boxX + (boxWidth - static_cast<int>(scoreText.length())) / 2, 
+             "%s", scoreText.c_str());
+    wattroff(mainWindow, COLOR_PAIR(14) | A_BOLD);
+    
+    // Instruction to continue
+    wattron(mainWindow, A_DIM);
+    mvwprintw(mainWindow, boxY + 8, boxX + 2, "Press any key to continue");
+    wattroff(mainWindow, A_DIM);
+}
+
+// Event handlers for menu input
+void UI::handleMainMenuInput() {
+    int key = wgetch(mainWindow);
+    if (key == ERR) return;
+    
+    switch (key) {
+        case KEY_UP:
+            if (selectedMenuOption > 0) {
+                selectedMenuOption--;
+                sounds.playSound(SoundEffect::MENU_NAVIGATE);
+            }
             break;
             
-        case UIState::GAME_OVER: {
-            int ch = wgetch(mainWindow);
-            if (ch == 'r' || ch == 'R') {
-                game.resetBoard();
-                setState(UIState::GAME_PLAYING);
-            } else if (ch == 'q' || ch == 'Q' || ch == 27) { // 27 is ESC
-                setState(UIState::MAIN_MENU);
+        case KEY_DOWN:
+            if (selectedMenuOption < static_cast<int>(mainMenuOptions.size()) - 1) {
+                selectedMenuOption++;
+                sounds.playSound(SoundEffect::MENU_NAVIGATE);
             }
             break;
-        }
             
-        case UIState::TUTORIAL: {
-            int ch = wgetch(mainWindow);
-            static int tutorialStep = 0;
+        case '\n': // Enter key
+        case ' ':  // Space key
+            sounds.playSound(SoundEffect::MENU_SELECT);
             
-            if (ch == ' ') {
-                tutorialStep++;
-                if (tutorialStep > 4) {
-                    setState(UIState::MAIN_MENU);
-                    tutorialStep = 0;
-                } else {
-                    drawTutorial(tutorialStep);
-                }
-            } else if (ch == 27) { // ESC
-                setState(UIState::MAIN_MENU);
-                tutorialStep = 0;
+            switch (selectedMenuOption) {
+                case 0: // Play Game
+                    setState(UIState::GAME_PLAYING);
+                    break;
+                    
+                case 1: // Select Mode
+                    setState(UIState::MODE_SELECTION);
+                    break;
+                    
+                case 2: // Settings
+                    setState(UIState::SETTINGS);
+                    break;
+                    
+                case 3: // Tutorial
+                    setGameMode(GameModeType::TUTORIAL);
+                    setState(UIState::TUTORIAL);
+                    break;
+                    
+                case 4: // Credits
+                    setState(UIState::CREDITS);
+                    break;
+                    
+                case 5: // Quit
+                    setState(UIState::EXIT_CONFIRM);
+                    break;
             }
             break;
-        }
+            
+        case 'q':
+        case 'Q':
+            setState(UIState::EXIT_CONFIRM);
+            break;
     }
 }
 
-void UI::handleMenuInput() {
-    int ch = wgetch(mainWindow);
+void UI::handleModeSelectionInput() {
+    int key = wgetch(mainWindow);
+    if (key == ERR) return;
     
-    switch (currentState) {
-        case UIState::MAIN_MENU:
-            if (ch == KEY_UP) {
-                selectedMenuOption = (selectedMenuOption - 1 + mainMenuOptions.size()) % mainMenuOptions.size();
-                drawMainMenu();
-            } else if (ch == KEY_DOWN) {
-                selectedMenuOption = (selectedMenuOption + 1) % mainMenuOptions.size();
-                drawMainMenu();
-            } else if (ch == 10 || ch == KEY_ENTER) { // Enter key
+    switch (key) {
+        case KEY_UP:
+            if (selectedMenuOption > 0) {
+                selectedMenuOption--;
+                sounds.playSound(SoundEffect::MENU_NAVIGATE);
+            }
+            break;
+            
+        case KEY_DOWN:
+            if (selectedMenuOption < static_cast<int>(modeSelectionOptions.size()) - 1) {
+                selectedMenuOption++;
+                sounds.playSound(SoundEffect::MENU_NAVIGATE);
+            }
+            break;
+            
+        case '\n': // Enter key
+        case ' ':  // Space key
+            sounds.playSound(SoundEffect::MENU_SELECT);
+            
+            if (selectedMenuOption == static_cast<int>(modeSelectionOptions.size()) - 1) {
+                // Back option
+                setState(UIState::MAIN_MENU);
+            } else {
+                // Set game mode and start game
+                GameModeType mode;
                 switch (selectedMenuOption) {
-                    case 0: // Play Game
-                        setState(UIState::GAME_PLAYING);
-                        break;
-                    case 1: // Select Mode
-                        setState(UIState::MODE_SELECTION);
-                        break;
-                    case 2: // Tutorial
-                        setState(UIState::TUTORIAL);
-                        drawTutorial(0);
-                        break;
-                    case 3: // Quit
-                        endwin();
-                        exit(0);
-                        break;
+                    case 0: mode = GameModeType::CLASSIC; break;
+                    case 1: mode = GameModeType::TIMED; break;
+                    case 2: mode = GameModeType::POWERUP; break;
+                    case 3: mode = GameModeType::CHALLENGE; break;
+                    case 4: mode = GameModeType::ZEN; break;
+                    default: mode = GameModeType::CLASSIC; break;
                 }
+                
+                setGameMode(mode);
+                setState(UIState::GAME_PLAYING);
             }
             break;
             
-        case UIState::MODE_SELECTION:
-            if (ch == KEY_UP) {
-                selectedMenuOption = (selectedMenuOption - 1 + modeSelectionOptions.size()) % modeSelectionOptions.size();
-                drawModeSelection();
-            } else if (ch == KEY_DOWN) {
-                selectedMenuOption = (selectedMenuOption + 1) % modeSelectionOptions.size();
-                drawModeSelection();
-            } else if (ch == 10 || ch == KEY_ENTER) { // Enter key
-                switch (selectedMenuOption) {
-                    case 0: // Classic
-                        setGameMode(GameModeType::CLASSIC);
-                        setState(UIState::GAME_PLAYING);
-                        break;
-                    case 1: // Timed
-                        setGameMode(GameModeType::TIMED);
-                        setState(UIState::GAME_PLAYING);
-                        break;
-                    case 2: // Power-Up
-                        setGameMode(GameModeType::POWERUP);
-                        setState(UIState::GAME_PLAYING);
-                        break;
-                    case 3: // Challenge
-                        setGameMode(GameModeType::CHALLENGE);
-                        setState(UIState::GAME_PLAYING);
-                        break;
-                    case 4: // Back
-                        setState(UIState::MAIN_MENU);
-                        break;
+        case 27: // ESC key
+            setState(UIState::MAIN_MENU);
+            break;
+    }
+}
+
+void UI::handleGameInput() {
+    int key = wgetch(mainWindow);
+    if (key == ERR) return;
+    
+    switch (key) {
+        case KEY_LEFT:
+        case KEY_RIGHT:
+        case KEY_UP:
+        case KEY_DOWN:
+            // Pass to game mode for handling
+            if (gameMode) {
+                gameMode->handleInput(game, key);
+            }
+            break;
+            
+        case 'p':
+        case 'P':
+            setState(UIState::PAUSE_MENU);
+            break;
+            
+        case 'r':
+        case 'R':
+            if (gameMode) {
+                gameMode->initialize(game);
+                sounds.playSound(SoundEffect::MENU_SELECT);
+            }
+            break;
+            
+        case 'q':
+        case 'Q':
+        case 27: // ESC key
+            setState(UIState::PAUSE_MENU);
+            break;
+            
+        // PowerUp mode specific keys
+        case '1':
+        case '2':
+        case '3':
+        case '4':
+            if (currentGameMode == GameModeType::POWERUP) {
+                // Pass to game mode for handling
+                if (gameMode) {
+                    gameMode->handleInput(game, key);
+                    sounds.playSound(SoundEffect::POWERUP_ACTIVATE);
                 }
-            } else if (ch == 27) { // ESC
-                setState(UIState::MAIN_MENU);
             }
             break;
             
-        case UIState::PAUSE_MENU:
-            if (ch == KEY_UP) {
-                selectedMenuOption = (selectedMenuOption - 1 + pauseMenuOptions.size()) % pauseMenuOptions.size();
-                drawPauseMenu();
-            } else if (ch == KEY_DOWN) {
-                selectedMenuOption = (selectedMenuOption + 1) % pauseMenuOptions.size();
-                drawPauseMenu();
-            } else if (ch == 10 || ch == KEY_ENTER) { // Enter key
-                switch (selectedMenuOption) {
-                    case 0: // Resume
-                        setState(UIState::GAME_PLAYING);
-                        break;
-                    case 1: // Restart
-                        // Need to reset the game
-                        setState(UIState::GAME_PLAYING);
-                        break;
-                    case 2: // Main Menu
-                        setState(UIState::MAIN_MENU);
-                        break;
-                    case 3: // Quit
-                        endwin();
-                        exit(0);
-                        break;
+        // Zen mode specific keys
+        case 'c':
+        case 'C':
+            if (currentGameMode == GameModeType::ZEN) {
+                // Pass to game mode for handling
+                if (gameMode) {
+                    gameMode->handleInput(game, key);
+                    sounds.playSound(SoundEffect::MENU_SELECT);
                 }
-            } else if (ch == 27 || ch == 'p' || ch == 'P') { // ESC or P to resume
-                setState(UIState::GAME_PLAYING);
             }
             break;
     }
 }
 
-void UI::showGameOver(Game2048& game) {
-    // Dim the background
-    wattron(mainWindow, A_DIM);
-    for (int y = 0; y < getmaxy(mainWindow); y++) {
-        for (int x = 0; x < getmaxx(mainWindow); x++) {
-            mvwaddch(mainWindow, y, x, ' ');
+void UI::handlePauseMenuInput() {
+    int key = wgetch(mainWindow);
+    if (key == ERR) return;
+    
+    switch (key) {
+        case KEY_UP:
+            if (selectedMenuOption > 0) {
+                selectedMenuOption--;
+                sounds.playSound(SoundEffect::MENU_NAVIGATE);
+            }
+            break;
+            
+        case KEY_DOWN:
+            if (selectedMenuOption < static_cast<int>(pauseMenuOptions.size()) - 1) {
+                selectedMenuOption++;
+                sounds.playSound(SoundEffect::MENU_NAVIGATE);
+            }
+            break;
+            
+        case '\n': // Enter key
+        case ' ':  // Space key
+            sounds.playSound(SoundEffect::MENU_SELECT);
+            
+            switch (selectedMenuOption) {
+                case 0: // Resume
+                    setState(UIState::GAME_PLAYING);
+                    break;
+                    
+                case 1: // Restart
+                    if (gameMode) {
+                        gameMode->initialize(game);
+                    }
+                    setState(UIState::GAME_PLAYING);
+                    break;
+                    
+                case 2: // Settings
+                    setState(UIState::SETTINGS);
+                    break;
+                    
+                case 3: // Main Menu
+                    setState(UIState::MAIN_MENU);
+                    break;
+                    
+                case 4: // Quit
+                    setState(UIState::EXIT_CONFIRM);
+                    break;
+            }
+            break;
+            
+        case 'p':
+        case 'P':
+        case 27: // ESC key
+            // Resume game
+            setState(UIState::GAME_PLAYING);
+            break;
+    }
+}
+
+void UI::handleSettingsInput() {
+    int key = wgetch(mainWindow);
+    if (key == ERR) return;
+    
+    switch (key) {
+        case KEY_UP:
+            if (selectedMenuOption > 0) {
+                selectedMenuOption--;
+                sounds.playSound(SoundEffect::MENU_NAVIGATE);
+            }
+            break;
+            
+        case KEY_DOWN:
+            if (selectedMenuOption < static_cast<int>(settingsOptions.size()) - 1) {
+                selectedMenuOption++;
+                sounds.playSound(SoundEffect::MENU_NAVIGATE);
+            }
+            break;
+            
+        case '\n': // Enter key
+        case ' ':  // Space key
+            sounds.playSound(SoundEffect::MENU_SELECT);
+            
+            switch (selectedMenuOption) {
+                case 0: // Sound toggle
+                    toggleSound();
+                    break;
+                    
+                case 1: // Music toggle
+                    toggleMusic();
+                    break;
+                    
+                case 2: // Animations toggle
+                    toggleAnimations();
+                    break;
+                    
+                case 3: // High Contrast toggle
+                    toggleHighContrast();
+                    break;
+                    
+                case 4: // Theme selection
+                    // Cycle through themes
+                    setTheme((currentTheme + 1) % static_cast<int>(themes.size()));
+                    break;
+                    
+                case 5: // Back
+                    setState(previousState);
+                    break;
+            }
+            break;
+            
+        case 27: // ESC key
+            setState(previousState);
+            break;
+    }
+}
+
+void UI::handleTutorialInput() {
+    int key = wgetch(mainWindow);
+    if (key == ERR) return;
+    
+    TutorialMode* tutorialMode = dynamic_cast<TutorialMode*>(gameMode.get());
+    if (tutorialMode) {
+        // Pass key to tutorial mode
+        tutorialMode->handleInput(game, key);
+        
+        // Check if tutorial is completed
+        if (tutorialMode->getTutorialStep() >= 9) {
+            setState(UIState::MAIN_MENU);
         }
     }
-    wattroff(mainWindow, A_DIM);
     
-    // Create a popup window
-    int maxY, maxX;
-    getmaxyx(mainWindow, maxY, maxX);
+    // ESC to exit tutorial
+    if (key == 27) {
+        setState(UIState::MAIN_MENU);
+    }
+}
+
+void UI::handleCreditsInput() {
+    int key = wgetch(mainWindow);
+    if (key == ERR) return;
     
-    int boxHeight = 7;
-    int boxWidth = 30;
-    int boxY = (maxY - boxHeight) / 2;
-    int boxX = (maxX - boxWidth) / 2;
+    // Any key returns to main menu
+    setState(UIState::MAIN_MENU);
+}
+
+void UI::handleExitConfirmInput() {
+    int key = wgetch(mainWindow);
+    if (key == ERR) return;
     
-    WINDOW* gameOverWin = subwin(mainWindow, boxHeight, boxWidth, boxY, boxX);
-    box(gameOverWin, 0, 0);
+    switch (key) {
+        case KEY_LEFT:
+            selectedMenuOption = 0; // Yes
+            sounds.playSound(SoundEffect::MENU_NAVIGATE);
+            break;
+            
+        case KEY_RIGHT:
+            selectedMenuOption = 1; // No
+            sounds.playSound(SoundEffect::MENU_NAVIGATE);
+            break;
+            
+        case '\n': // Enter key
+        case ' ':  // Space key
+            sounds.playSound(SoundEffect::MENU_SELECT);
+            
+            if (selectedMenuOption == 0) {
+                // Yes - exit the game
+                // In real implementation, this would break the main loop
+                endwin();
+                exit(0);
+            } else {
+                // No - return to previous state
+                setState(previousState);
+            }
+            break;
+            
+        case 27: // ESC key
+            setState(previousState);
+            break;
+    }
+}
+
+// Game event callbacks
+void UI::onTileMoved(int fromRow, int fromCol, int toRow, int toCol, int value) {
+    if (animationsEnabled) {
+        animations.addSlideAnimation(fromRow, fromCol, toRow, toCol, value);
+    }
     
-    // Title
-    wattron(gameOverWin, COLOR_PAIR(COLOR_PAIR_HIGHER) | A_BOLD);
-    drawCenteredText(gameOverWin, 1, "GAME OVER!", false);
-    wattroff(gameOverWin, COLOR_PAIR(COLOR_PAIR_HIGHER) | A_BOLD);
+    if (soundEnabled) {
+        sounds.playSound(SoundEffect::MOVE);
+    }
+}
+
+void UI::onTileMerged(int row, int col, int value) {
+    if (animationsEnabled) {
+        animations.addMergeAnimation(row, col, value);
+    }
     
-    // Score
-    std::string scoreText = "Final Score: " + std::to_string(game.getScore());
-    drawCenteredText(gameOverWin, 3, scoreText, false);
+    if (soundEnabled) {
+        sounds.playSound(SoundEffect::MERGE);
+    }
+}
+
+void UI::onTileSpawned(int row, int col, int value) {
+    if (animationsEnabled) {
+        animations.addSpawnAnimation(row, col, value);
+    }
     
-    // Options
-    drawCenteredText(gameOverWin, 5, "R: Restart  Q: Quit", false);
+    if (soundEnabled) {
+        sounds.playSound(SoundEffect::SPAWN);
+    }
+}
+
+void UI::onScoreChanged(int newScore, int prevScore) {
+    if (animationsEnabled) {
+        animations.addScoreAnimation(newScore, prevScore);
+    }
+}
+
+void UI::onGameOver() {
+    setState(UIState::GAME_OVER);
     
-    wrefresh(gameOverWin);
+    if (animationsEnabled) {
+        animations.addGameOverAnimation();
+    }
     
-    // Wait for input
-    while (true) {
-        int ch = wgetch(gameOverWin);
-        if (ch == 'r' || ch == 'R') {
-            game.resetBoard();
-            setState(UIState::GAME_PLAYING);
-            break;
-        } else if (ch == 'q' || ch == 'Q' || ch == 27) { // Q or ESC
-            setState(UIState::MAIN_MENU);
-            break;
-        }
+    if (soundEnabled) {
+        sounds.playSound(SoundEffect::GAMEOVER);
+    }
+}
+
+void UI::onVictory() {
+    setState(UIState::VICTORY);
+    
+    if (animationsEnabled) {
+        animations.addVictoryAnimation();
+        addConfetti(100);
     }
     
-    delwin(gameOverWin);
+    if (soundEnabled) {
+        sounds.playSound(SoundEffect::VICTORY);
+    }
 }
 
-void UI::setGameMode(GameModeType mode) {
-    currentGameMode = mode;
+// Effect methods
+void UI::updateTextEffects(float deltaTime) {
+    for (auto it = textEffects.begin(); it != textEffects.end();) {
+        it->elapsed += deltaTime;
+        if (it->elapsed >= it->duration) {
+            it = textEffects.erase(it);
+        } else {
+            ++it;
+        }
+    }
 }
 
-GameModeType UI::getGameMode() const {
-    return currentGameMode;
+void UI::drawTextEffects() {
+    for (const auto& effect : textEffects) {
+        float progress = effect.elapsed / effect.duration;
+        int y = effect.row;
+        int x = effect.centered ? 
+                (getmaxx(mainWindow) - effect.text.length()) / 2 : 
+                effect.col;
+        
+        if (effect.type == "fade") {
+            // Fade in/out effect
+            int attr;
+            if (progress < 0.3f) attr = A_DIM;
+            else if (progress < 0.7f) attr = A_NORMAL;
+            else attr = A_BOLD;
+            
+            wattron(mainWindow, COLOR_PAIR(effect.color) | attr);
+            mvwprintw(mainWindow, y, x, "%s", effect.text.c_str());
+            wattroff(mainWindow, COLOR_PAIR(effect.color) | attr);
+        } else if (effect.type == "pulse") {
+            // Pulsing effect
+            float pulse = sin(progress * M_PI * 3) * 0.5f + 0.5f;
+            int attr = pulse > 0.7f ? A_BOLD : (pulse > 0.3f ? A_NORMAL : A_DIM);
+            
+            wattron(mainWindow, COLOR_PAIR(effect.color) | attr);
+            mvwprintw(mainWindow, y, x, "%s", effect.text.c_str());
+            wattroff(mainWindow, COLOR_PAIR(effect.color) | attr);
+        } else if (effect.type == "rainbow") {
+            // Rainbow effect - cycle through colors
+            int colorOffset = static_cast<int>(progress * 10) % 5;
+            for (size_t i = 0; i < effect.text.length(); i++) {
+                int colorPair = ((i + colorOffset) % 5) + 14; // Cycle through colors 14-18
+                wattron(mainWindow, COLOR_PAIR(colorPair) | A_BOLD);
+                mvwaddch(mainWindow, y, x + static_cast<int>(i), effect.text[i]);
+                wattroff(mainWindow, COLOR_PAIR(colorPair) | A_BOLD);
+            }
+        } else if (effect.type == "typing") {
+            // Typing effect
+            int chars = static_cast<int>(effect.text.length() * progress);
+            wattron(mainWindow, COLOR_PAIR(effect.color) | A_BOLD);
+            mvwprintw(mainWindow, y, x, "%s", effect.text.substr(0, chars).c_str());
+            wattroff(mainWindow, COLOR_PAIR(effect.color) | A_BOLD);
+        }
+    }
 }
 
-void UI::displayScore(const Game2048& game) {
-    // This is now handled in drawBoard
+void UI::addTextEffect(const std::string& text, int row, int col, const std::string& type, 
+                      float duration, int color, bool centered) {
+    TextEffect effect;
+    effect.text = text;
+    effect.row = row;
+    effect.col = col;
+    effect.type = type;
+    effect.duration = duration;
+    effect.elapsed = 0.0f;
+    effect.color = color;
+    effect.centered = centered;
+    
+    textEffects.push_back(effect);
 }
 
-void UI::displayInstructions() {
-    // This is now handled in drawBoard with the info window
+void UI::updateConfetti(float deltaTime) {
+    for (auto it = confetti.begin(); it != confetti.end();) {
+        // Update position
+        it->y += it->vy * deltaTime * 5.0f;
+        it->x += it->vx * deltaTime * 5.0f;
+        
+        // Add gravity
+        it->vy += 2.0f * deltaTime;
+        
+        // Update rotation
+        it->angle += it->rotation * deltaTime;
+        
+        // Update lifetime
+        it->lifetime -= deltaTime;
+        
+        // Remove if lifetime expired or out of screen
+        int maxY, maxX;
+        getmaxyx(mainWindow, maxY, maxX);
+        
+        if (it->lifetime <= 0.0f || it->y >= maxY || it->x < 0 || it->x >= maxX) {
+            it = confetti.erase(it);
+        } else {
+            ++it;
+        }
+    }
 }
+
+void UI::drawConfetti() {
+    for (const auto& c : confetti) {
+        // Determine how to draw based on rotation angle
+        char symbol;
+        if (fmod(c.angle, 2.0f * M_PI) < M_PI / 2 || 
+            fmod(c.angle, 2.0f * M_PI) > 3 * M_PI / 2) {
+            symbol = '-';
+        } else {
+            symbol = '|';
+        }
+        
+        // Adjust color based on lifetime
+        int attr = c.lifetime > 0.7f ? A_BOLD : (c.lifetime > 0.3f ? A_NORMAL : A_DIM);
+        
+        wattron(mainWindow, COLOR_PAIR(c.color) | attr);
+        mvwaddch(mainWindow, static_cast<int>(c.y), static_cast<int>(c.x), c.symbol ? c.symbol : symbol);
+        wattroff(mainWindow, COLOR_PAIR(c.color) | attr);
+    }
+}
+
+void UI::addConfetti(int amount) {
+    int maxY, maxX;
+    getmaxyx(mainWindow, maxY, maxX);
+    (void)maxY; // Explicitly mark maxY as unused to avoid warning
+    
+    std::srand(std::time(nullptr));
+    
+    for (int i = 0; i < amount; i++) {
+        Confetti c;
+        c.x = std::rand() % maxX;
+        c.y = std::rand() % 5; // Start near the top
+        c.vx = (std::rand() % 100 - 50) / 25.0f; // -2.0 to 2.0
+        c.vy = (std::rand() % 50) / 25.0f; // 0 to 2.0
+        c.angle = (std::rand() % 628) / 100.0f; // 0 to 2π
+        c.rotation = (std::rand() % 200 - 100) / 50.0f; // -2.0 to 2.0
+        c.size = 1.0f;
+        c.symbol = "*+.ox"[std::rand() % 5]; // Random symbol
+        c.color = 14 + (std::rand() % 5); // Random color from palette
+        c.lifetime = 1.0f + (std::rand() % 100) / 100.0f; // 1.0 to 2.0 seconds
+        
+        confetti.push_back(c);
+    }
+}
\ No newline at end of file
diff --git a/src/main.cpp b/src/main.cpp
index 934ac4ed69c018f3dcb34f24f595f52e2b151c73..3d2dd9282d519033c4150d423307fe77eead8c94 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,10 +1,10 @@
 #include "2048.hpp"
 #include "UI.hpp"
 #include "Extra.hpp"
-#include "GameMode.hpp"
 #include <ncurses.h>
 #include <chrono>
 #include <thread>
+#include <iostream>
 
 // Helper function for tracking time
 float getDeltaTime() {
@@ -16,78 +16,27 @@ float getDeltaTime() {
 }
 
 int main() {
-    // Initialize the game and colors
-    initializeGame();
-
-    Game2048 game;
-    UI ui;
-    ui.initialize();
-    
-    // Create game mode instances
-    ClassicMode classicMode;
-    TimedMode timedMode;
-    PowerUpMode powerUpMode;
-    ChallengeMode challengeMode;
-    TutorialMode tutorialMode;
-    
-    // Show the main menu initially
-    ui.drawMainMenu();
-    
-    float timeRemaining = 180.0f; // For timed mode
-    
-    while (true) {
-        float deltaTime = getDeltaTime();
+    try {
+        // Initialize the game
+        initializeGame();
         
-        // Handle timing for timed mode
-        if (ui.getState() == UIState::GAME_PLAYING && ui.getGameMode() == GameModeType::TIMED) {
-            timeRemaining -= deltaTime;
-            ui.drawTimerInterface(timeRemaining);
-            
-            if (timeRemaining <= 0) {
-                ui.showGameOver(game);
-            }
+        // Create and initialize UI
+        UI ui;
+        if (!ui.initialize()) {
+            cleanupGame();
+            return 1;
         }
         
-        // Handle user input based on current state
-        ui.handleInput(game);
-        
-        // Update display based on current state
-        switch (ui.getState()) {
-            case UIState::MAIN_MENU:
-                ui.drawMainMenu();
-                break;
-                
-            case UIState::MODE_SELECTION:
-                ui.drawModeSelection();
-                break;
-                
-            case UIState::GAME_PLAYING:
-                ui.drawBoard(game);
-                
-                // Check for game over
-                if (!game.canMove()) {
-                    ui.showGameOver(game);
-                    ui.drawBoard(game);
-                }
-                break;
-                
-            case UIState::PAUSE_MENU:
-                ui.drawPauseMenu();
-                break;
-                
-            case UIState::GAME_OVER:
-                // Handled in showGameOver
-                break;
-                
-            case UIState::TUTORIAL:
-                // Handled in handleInput and drawTutorial
-                break;
-        }
+        // The UI class now handles the game loop internally
+        ui.run();
         
-        // Sleep a bit to limit CPU usage
-        std::this_thread::sleep_for(std::chrono::milliseconds(50));
+        // Cleanup
+        cleanupGame();
+        return 0;
+    } catch (const std::exception& e) {
+        // Clean up ncurses in case of exception
+        endwin();
+        std::cerr << "Error: " << e.what() << std::endl;
+        return 1;
     }
-
-    cleanupGame();
-    return 0;
 }
\ No newline at end of file