Do these changes : 
- Spacebar show a pause message the screen trop but the game still continue in the background. When I unpause the screen is refresh with the new state. Really pause everything. Including the music.
- When a piece appear at the top it seams to be appearing outside the grid. The whole piece should be visible in the grid when it is added to the screen
- When I hold the down arrow the piece keep going down. Do the same thing for left and right, holding the arrows keep the piece moving in the direction of the arrow.

import pygame
import random
import os

# Initialize Pygame and Mixer for sounds
pygame.init()
pygame.mixer.init()

# Define grid size
GRID_WIDTH = 10    # Standard Tetris has 10 columns
GRID_HEIGHT = 20   # Standard Tetris has 20 rows
BLOCK_SIZE = 30    # Size of the grid block

# Define margins and offsets
TITLE_HEIGHT = 80
SIDE_PANEL_MARGIN_TOP = 100
SIDE_PANEL_MARGIN_LEFT = GRID_WIDTH * BLOCK_SIZE + 40  # 10 columns * 30 + 40 for margin

# Screen dimensions (grid + side panel + margins)
SIDE_PANEL_WIDTH = 200
SCREEN_WIDTH = GRID_WIDTH * BLOCK_SIZE + SIDE_PANEL_WIDTH + 60  # Additional margin for aesthetics
SCREEN_HEIGHT = TITLE_HEIGHT + GRID_HEIGHT * BLOCK_SIZE + 40   # Additional margin for aesthetics

# Set up the display
win = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption('Tetris')

# Load Sounds (Ensure you have these sound files in a 'Sounds' directory)
MOVE_SOUND = pygame.mixer.Sound(os.path.join('Sounds', 'move.wav'))
ROTATE_SOUND = pygame.mixer.Sound(os.path.join('Sounds', 'rotate.wav'))
CLEAR_SOUND = pygame.mixer.Sound(os.path.join('Sounds', 'clear.wav'))
GAME_OVER_SOUND = pygame.mixer.Sound(os.path.join('Sounds', 'game_over.wav'))
BACKGROUND_MUSIC = os.path.join('Sounds', 'game.mp3')  # Path to background music

# Define paths for high score
HIGHSCORE_FILE = 'high_score.txt'

# Initialize high_score globally
high_score = 0

# Define shapes and their rotations
SHAPES = [
    [['.....',
      '..0..',
      '..0..',
      '..0..',
      '..0..'],
     ['.....',
      '0000.',
      '.....',
      '.....',
      '.....']],

    [['.....',
      '..00.',
      '..00.',
      '.....',
      '.....']],

    [['.....',
      '...0.',
      '.000.',
      '.....',
      '.....'],
     ['.....',
      '..0..',
      '..0..',
      '..00.',
      '.....'],
     ['.....',
      '.....',
      '.000.',
      '.0...',
      '.....'],
     ['.....',
      '.00..',
      '..0..',
      '..0..',
      '.....']],

    [['.....',
      '.0...',
      '.000.',
      '.....',
      '.....'],
     ['.....',
      '..00.',
      '..0..',
      '..0..',
      '.....'],
     ['.....',
      '.....',
      '.000.',
      '...0.',
      '.....'],
     ['.....',
      '..0..',
      '..0..',
      '.00..',
      '.....']],

    [['.....',
      '..0..',
      '.000.',
      '.....',
      '.....'],
     ['.....',
      '..0..',
      '..00.',
      '..0..',
      '.....'],
     ['.....',
      '.....',
      '.000.',
      '..0..',
      '.....'],
     ['.....',
      '..0..',
      '.00..',
      '..0..',
      '.....']],

    [['.....',
      '..0..',
      '..00.',
      '...0.',
      '.....'],
     ['.....',
      '...00',
      '..00.',
      '.....',
      '.....']],

    [['.....',
      '...0.',
      '..00.',
      '..0..',
      '.....'],
     ['.....',
      '..00.',
      '...00',
      '.....',
      '.....']]
]

# Define colors for each shape
SHAPE_COLORS = [
    (0, 255, 255),   # Cyan
    (255, 255, 0),   # Yellow
    (255, 165, 0),   # Orange
    (0, 0, 255),     # Blue
    (128, 0, 128),   # Purple
    (0, 255, 0),     # Green
    (255, 0, 0)       # Red
]

# Volume settings (0-10 scale)
music_volume = 5
sfx_volume = 5

class Piece:
    def __init__(self, x, y, shape):
        self.x = x
        self.y = y
        self.shape = shape
        self.color = SHAPE_COLORS[SHAPES.index(shape)]
        self.rotation = 0

def load_high_score():
    global high_score
    if os.path.exists(HIGHSCORE_FILE):
        with open(HIGHSCORE_FILE, 'r') as file:
            try:
                high_score = int(file.read())
            except:
                high_score = 0
    else:
        high_score = 0
    return high_score

def save_high_score(high_score):
    with open(HIGHSCORE_FILE, 'w') as file:
        file.write(str(high_score))

def create_grid(locked_positions={}):
    grid = [[(0, 0, 0) for _ in range(GRID_WIDTH)] for _ in range(GRID_HEIGHT)]

    for (j, i) in locked_positions:
        if 0 <= i < GRID_HEIGHT and 0 <= j < GRID_WIDTH:
            grid[i][j] = locked_positions[(j, i)]
    return grid

def convert_shape_format(piece):
    positions = []
    format = piece.shape[piece.rotation % len(piece.shape)]

    for i, line in enumerate(format):
        row = list(line)
        for j, column in enumerate(row):
            if column == '0':
                positions.append((piece.x + j - 2, piece.y + i - 4))

    # Normalize positions
    for i, pos in enumerate(positions):
        positions[i] = (pos[0], pos[1])

    return positions

def valid_space(piece, grid):
    accepted_positions = [[(j, i) for j in range(GRID_WIDTH) if grid[i][j] == (0, 0, 0)] for i in range(GRID_HEIGHT)]
    accepted_positions = [j for sub in accepted_positions for j in sub]

    formatted = convert_shape_format(piece)

    for pos in formatted:
        if pos not in accepted_positions:
            if pos[1] > -1:
                return False
    return True

def check_lost(positions):
    for pos in positions:
        x, y = pos
        if y < 1:
            return True
    return False

def get_shape():
    return Piece(GRID_WIDTH // 2, 0, random.choice(SHAPES))

def draw_text_middle(text, size, color, surface, y_offset=0):
    font = pygame.font.SysFont('comicsans', size, bold=True)
    label = font.render(text, 1, color)

    surface.blit(label, (
        (SCREEN_WIDTH / 2) - (label.get_width() / 2),
        (SCREEN_HEIGHT / 2) - (label.get_height() / 2) + y_offset
    ))

def draw_grid(surface, grid, offset_y=80):
    for i in range(GRID_HEIGHT):
        # Horizontal lines
        pygame.draw.line(surface, (128, 128, 128), 
                         (20, i * BLOCK_SIZE + offset_y), 
                         (20 + GRID_WIDTH * BLOCK_SIZE, i * BLOCK_SIZE + offset_y))
        for j in range(GRID_WIDTH):
            # Vertical lines
            pygame.draw.line(surface, (128, 128, 128), 
                             (j * BLOCK_SIZE + 20, offset_y), 
                             (j * BLOCK_SIZE + 20, GRID_HEIGHT * BLOCK_SIZE + offset_y))

def clear_rows(grid, locked):
    inc = 0
    lines_cleared = 0
    for i in range(len(grid)-1, -1, -1):
        row = grid[i]
        if (0, 0, 0) not in row:
            inc += 1
            lines_cleared += 1
            ind = i
            for j in range(len(row)):
                try:
                    del locked[(j, i)]
                except:
                    continue
    if inc > 0:
        # Play line clear sound
        CLEAR_SOUND.play()
        # Shift rows down
        for key in sorted(list(locked), key=lambda x: x[1])[::-1]:
            x, y = key
            if y < ind:
                newKey = (x, y + inc)
                locked[newKey] = locked.pop(key)
    return lines_cleared

def draw_next_shape(piece, surface):
    font = pygame.font.SysFont('comicsans', 30)
    label = font.render('Next Shape', 1, (255, 255, 255))

    sx = SIDE_PANEL_MARGIN_LEFT + 20
    sy = SIDE_PANEL_MARGIN_TOP + 100
    format = piece.shape[piece.rotation % len(piece.shape)]

    surface.blit(label, (sx, sy))
    
    for i, line in enumerate(format):
        row = list(line)
        for j, column in enumerate(row):
            if column == '0':
                # Draw block with shading
                block_rect = pygame.Rect(sx + j * BLOCK_SIZE, sy + 40 + i * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE)
                pygame.draw.rect(surface, piece.color, block_rect)
                pygame.draw.rect(surface, (0,0,0), block_rect, 2)  # Border for better visibility

def draw_window(surface, grid, lines_cleared, level, _):
    surface.fill((30, 30, 30))  # Dark background for better contrast
    
    # Draw the "Tetris" title above the grid
    font_title = pygame.font.SysFont('comicsans', 60, bold=True)
    label_title = font_title.render('Tetris', 1, (255, 255, 255))
    surface.blit(label_title, (SIDE_PANEL_MARGIN_LEFT // 2 - label_title.get_width() / 2, 10))
    
    # Display Score and Level in the side panel
    font_small = pygame.font.SysFont('comicsans', 30, bold=True)
    label_score = font_small.render(f'Score: {lines_cleared}', 1, (255, 255, 255))
    label_level = font_small.render(f'Level: {level}', 1, (255, 255, 255))
    surface.blit(label_score, (SIDE_PANEL_MARGIN_LEFT + 20, SIDE_PANEL_MARGIN_TOP))
    surface.blit(label_level, (SIDE_PANEL_MARGIN_LEFT + 20, SIDE_PANEL_MARGIN_TOP + 50))
    
    # Draw the grid blocks
    for i in range(len(grid)):
        for j in range(len(grid[i])):
            pygame.draw.rect(surface, grid[i][j], 
                             (j * BLOCK_SIZE + 20, i * BLOCK_SIZE + TITLE_HEIGHT, BLOCK_SIZE, BLOCK_SIZE), 0)
            # Add shading to blocks for 3D effect
            if grid[i][j] != (0,0,0):
                pygame.draw.rect(surface, (0,0,0), 
                                 (j * BLOCK_SIZE + 20, i * BLOCK_SIZE + TITLE_HEIGHT, BLOCK_SIZE, BLOCK_SIZE), 2)
    
    draw_grid(surface, grid, offset_y=TITLE_HEIGHT)
    
    # Draw border around the grid
    pygame.draw.rect(surface, (255, 255, 255), 
                     (20, TITLE_HEIGHT, GRID_WIDTH * BLOCK_SIZE, GRID_HEIGHT * BLOCK_SIZE), 5)
    
    # Draw border around side panel
    pygame.draw.rect(surface, (255, 255, 255), 
                     (SIDE_PANEL_MARGIN_LEFT, 0, SIDE_PANEL_WIDTH, SCREEN_HEIGHT), 5)

def play_background_music():
    if os.path.exists(BACKGROUND_MUSIC):
        pygame.mixer.music.load(BACKGROUND_MUSIC)
        pygame.mixer.music.set_volume(music_volume / 10)  # Adjust volume as needed
        pygame.mixer.music.play(-1)  # -1 for infinite loop
    else:
        print(f"Background music file not found: {BACKGROUND_MUSIC}")

def stop_background_music():
    pygame.mixer.music.stop()

# Slider Class for Options Menu
class Slider:
    def __init__(self, x, y, width, height, min_val, max_val, start_val=5, label=''):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.min_val = min_val
        self.max_val = max_val
        self.value = start_val
        self.knob_radius = height // 2
        self.knob_x = self.x + (self.value - self.min_val) / (self.max_val - self.min_val) * self.width
        self.knob_y = self.y + self.height // 2
        self.dragging = False
        self.label = label
    
    def draw(self, surface):
        # Draw the bar
        pygame.draw.rect(surface, (200,200,200), (self.x, self.y + self.height//4, self.width, self.height//2))
        # Draw the knob
        pygame.draw.circle(surface, (255, 255, 255), (int(self.knob_x), int(self.knob_y)), self.knob_radius)
        # Draw value
        font = pygame.font.SysFont('comicsans', 20)
        label = font.render(str(int(self.value)), 1, (255,255,255))
        surface.blit(label, (self.x + self.width + 10, self.y - self.height//2))
        # Draw slider label
        if self.label:
            label_text = font.render(self.label, 1, (255,255,255))
            surface.blit(label_text, (self.x, self.y - 30))  # Position above the slider
    
    def handle_event(self, event):
        if event.type == pygame.MOUSEBUTTONDOWN:
            mouse_x, mouse_y = event.pos
            distance = ((mouse_x - self.knob_x)**2 + (mouse_y - self.knob_y)**2)**0.5
            if distance <= self.knob_radius:
                self.dragging = True
        elif event.type == pygame.MOUSEBUTTONUP:
            self.dragging = False
        elif event.type == pygame.MOUSEMOTION:
            if self.dragging:
                mouse_x = event.pos[0]
                # Clamp mouse_x to the slider bar
                self.knob_x = max(self.x, min(mouse_x, self.x + self.width))
                # Update value accordingly
                ratio = (self.knob_x - self.x) / self.width
                self.value = self.min_val + ratio * (self.max_val - self.min_val)
                # Round to nearest integer
                self.value = int(round(self.value))

def set_sfx_volume(volume):
    global sfx_volume
    sfx_volume = volume
    MOVE_SOUND.set_volume(sfx_volume / 10)
    ROTATE_SOUND.set_volume(sfx_volume / 10)
    CLEAR_SOUND.set_volume(sfx_volume / 10)
    GAME_OVER_SOUND.set_volume(sfx_volume / 10)

def set_music_volume(volume):
    global music_volume
    music_volume = volume
    pygame.mixer.music.set_volume(music_volume / 10)

def main():
    global high_score
    locked_positions = {}
    grid = create_grid(locked_positions)

    change_piece = False
    run = True
    current_piece = get_shape()
    next_piece = get_shape()
    clock = pygame.time.Clock()
    fall_time = 0

    BASE_FALL_SPEED = 0.5  # Base fall speed in seconds
    fall_speed = BASE_FALL_SPEED
    lines_cleared = 0  # Initialize lines cleared counter
    level = 1  # Initialize level

    paused = False  # Game paused state

    # Load high score
    high_score = load_high_score()

    the_music_started = False  # To ensure music starts only once

    while run:
        grid = create_grid(locked_positions)
        fall_time += clock.get_rawtime()
        clock.tick()

        # Calculate current level based on lines cleared
        new_level = (lines_cleared // 10) + 1
        if new_level != level:
            level = new_level
            fall_speed *= 1.15  # Increase speed by 15% each level

        # Adjust fall speed
        current_fall_speed = fall_speed
        keys = pygame.key.get_pressed()

        if keys[pygame.K_DOWN]:
            current_fall_speed = 0.05  # Fast fall when down key is held

        if fall_time / 1000 >= current_fall_speed:
            fall_time = 0
            current_piece.y += 1
            if not valid_space(current_piece, grid) and current_piece.y > 0:
                current_piece.y -= 1
                change_piece = True
                MOVE_SOUND.play()

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
                pygame.display.quit()
                quit()

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    current_piece.x -= 1
                    if not valid_space(current_piece, grid):
                        current_piece.x += 1
                    else:
                        MOVE_SOUND.play()
                elif event.key == pygame.K_RIGHT:
                    current_piece.x += 1
                    if not valid_space(current_piece, grid):
                        current_piece.x -= 1
                    else:
                        MOVE_SOUND.play()
                elif event.key == pygame.K_DOWN:
                    current_piece.y += 1
                    if not valid_space(current_piece, grid):
                        current_piece.y -= 1
                elif event.key == pygame.K_UP:
                    current_piece.rotation = (current_piece.rotation + 1) % len(current_piece.shape)
                    if not valid_space(current_piece, grid):
                        current_piece.rotation = (current_piece.rotation - 1) % len(current_piece.shape)
                    else:
                        ROTATE_SOUND.play()
                elif event.key == pygame.K_SPACE:
                    paused = not paused  # Toggle pause

        if paused:
            pause_screen(win)
            continue  # Skip the rest of the loop to effectively pause

        shape_pos = convert_shape_format(current_piece)

        # Add piece to the grid for drawing
        for i in range(len(shape_pos)):
            x, y = shape_pos[i]
            if y > -1:
                if 0 <= x < GRID_WIDTH and 0 <= y < GRID_HEIGHT:
                    grid[y][x] = current_piece.color

        if change_piece:
            for pos in shape_pos:
                p = (pos[0], pos[1])
                if 0 <= p[0] < GRID_WIDTH and 0 <= p[1] < GRID_HEIGHT:
                    locked_positions[p] = current_piece.color
            current_piece = next_piece
            next_piece = get_shape()
            change_piece = False

            cleared = clear_rows(grid, locked_positions)
            lines_cleared += cleared  # Update lines cleared

        # Start background music once when the game starts
        if not the_music_started:
            play_background_music()
            the_music_started = True

        # Draw window without passing high_score (no display during game)
        draw_window(win, grid, lines_cleared, level, high_score)  # Modify the function to ignore high_score
        draw_next_shape(next_piece, win)
        pygame.display.update()

        if check_lost(locked_positions):
            GAME_OVER_SOUND.play()
            pygame.time.delay(500)
            run = False
            stop_background_music()
            update_high_score_if_needed(lines_cleared)

    game_over_screen(win, lines_cleared, high_score)

def update_high_score_if_needed(current_score):
    global high_score
    if current_score > high_score:
        high_score = current_score
        save_high_score(high_score)

def game_over_screen(surface, final_score, _):
    # Update high score if necessary
    if final_score > high_score:
        high_score = final_score
        save_high_score(high_score)

    pygame.mixer.music.stop()  # Ensure music is stopped on game over

    while True:
        surface.fill((0, 0, 0))
        draw_text_middle("YOU LOST!", 60, (255, 255, 255), surface, y_offset=-50)
        
        # Display final score
        font_small = pygame.font.SysFont('comicsans', 30)
        score_label = font_small.render(f'Your Score: {final_score}', 1, (255, 255, 255))
        surface.blit(score_label, ((SCREEN_WIDTH / 2) - (score_label.get_width() / 2), (SCREEN_HEIGHT / 2) - 10))
        
        # Prompt to return to menu
        prompt_label = font_small.render('Press Space to return to the menu.', 1, (255, 255, 255))
        surface.blit(prompt_label, ((SCREEN_WIDTH / 2) - (prompt_label.get_width() / 2), (SCREEN_HEIGHT / 2) + 30))
        
        pygame.display.update()
        
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    main_menu()  # Return to main menu

def pause_screen(surface):
    pause_font = pygame.font.SysFont('comicsans', 40, bold=True)
    pause_label = pause_font.render('Game Paused', 1, (255, 255, 255))
    prompt_font = pygame.font.SysFont('comicsans', 20)
    prompt_label = prompt_font.render('Press Space to Resume', 1, (255, 255, 255))
    
    surface.blit(pause_label, ((SCREEN_WIDTH / 2) - (pause_label.get_width() / 2), SCREEN_HEIGHT / 2 - 30))
    surface.blit(prompt_label, ((SCREEN_WIDTH / 2) - (prompt_label.get_width() / 2), SCREEN_HEIGHT / 2 + 10))
    pygame.display.update()

def main_menu():
    global high_score
    load_high_score()  # Ensure high_score is loaded before displaying menu
    run = True
    while run:
        win.fill((0, 0, 0))
        
        # Draw the "Tetris" title
        font_title = pygame.font.SysFont('comicsans', 60, bold=True)
        title_label = font_title.render('Tetris', 1, (255, 255, 255))
        win.blit(title_label, (SCREEN_WIDTH / 2 - title_label.get_width() / 2, 100))
        
        # Display High Score
        font_high = pygame.font.SysFont('comicsans', 30, bold=True)
        high_label = font_high.render(f'High Score: {high_score}', 1, (255, 255, 255))
        win.blit(high_label, (SCREEN_WIDTH / 2 - high_label.get_width() / 2, 200))
        
        # Display menu options
        font_options = pygame.font.SysFont('comicsans', 30)
        option1 = font_options.render('1: New Game', 1, (255, 255, 255))
        option2 = font_options.render('2: Options', 1, (255, 255, 255))
        option3 = font_options.render('3: Exit', 1, (255, 255, 255))
        
        win.blit(option1, (SCREEN_WIDTH / 2 - option1.get_width() / 2, 300))
        win.blit(option2, (SCREEN_WIDTH / 2 - option2.get_width() / 2, 350))
        win.blit(option3, (SCREEN_WIDTH / 2 - option3.get_width() / 2, 400))
        
        pygame.display.update()
        
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
                pygame.quit()
                quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_1:
                    main()  # Start new game
                elif event.key == pygame.K_2:
                    options_menu()  # Open options menu
                elif event.key == pygame.K_3:
                    run = False
                    pygame.quit()
                    quit()
    pygame.quit()

def options_menu():
    global music_volume, sfx_volume
    run = True
    # Create sliders: (x, y, width, height, min_val, max_val, start_val, label)
    music_slider = Slider(SCREEN_WIDTH / 2 - 100, 150, 200, 20, 0, 10, music_volume, 'Music Volume')
    sfx_slider = Slider(SCREEN_WIDTH / 2 - 100, 250, 200, 20, 0, 10, sfx_volume, 'SFX Volume')
    
    while run:
        win.fill((0, 0, 0))
        
        # Draw the "Options" title
        font_title = pygame.font.SysFont('comicsans', 60, bold=True)
        title_label = font_title.render('Options', 1, (255, 255, 255))
        win.blit(title_label, (SCREEN_WIDTH / 2 - title_label.get_width() / 2, 50))
        
        # Draw sliders
        music_slider.draw(win)
        sfx_slider.draw(win)
        
        # Instructions to return to main menu
        font_instruct = pygame.font.SysFont('comicsans', 25)
        instruct_label = font_instruct.render('Press Esc to return to the main menu.', 1, (255, 255, 255))
        win.blit(instruct_label, (SCREEN_WIDTH / 2 - instruct_label.get_width() / 2, 400))
        
        pygame.display.update()
        
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
                pygame.display.quit()
                quit()
            # Handle slider events
            music_slider.handle_event(event)
            sfx_slider.handle_event(event)
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    # Update volume settings
                    set_music_volume(music_slider.value)
                    set_sfx_volume(sfx_slider.value)
                    run = False  # Exit options_menu
    # Do NOT call pygame.quit() here. Instead, return to main_menu
    # pygame.quit()  # Removed to prevent crashing

def set_sfx_volume(volume):
    global sfx_volume
    sfx_volume = volume
    MOVE_SOUND.set_volume(sfx_volume / 10)
    ROTATE_SOUND.set_volume(sfx_volume / 10)
    CLEAR_SOUND.set_volume(sfx_volume / 10)
    GAME_OVER_SOUND.set_volume(sfx_volume / 10)

def set_music_volume(volume):
    global music_volume
    music_volume = volume
    pygame.mixer.music.set_volume(music_volume / 10)

def main():
    global high_score
    locked_positions = {}
    grid = create_grid(locked_positions)

    change_piece = False
    run = True
    current_piece = get_shape()
    next_piece = get_shape()
    clock = pygame.time.Clock()
    fall_time = 0

    BASE_FALL_SPEED = 0.5  # Base fall speed in seconds
    fall_speed = BASE_FALL_SPEED
    lines_cleared = 0  # Initialize lines cleared counter
    level = 1  # Initialize level

    paused = False  # Game paused state

    the_music_started = False  # To ensure music starts only once

    while run:
        grid = create_grid(locked_positions)
        fall_time += clock.get_rawtime()
        clock.tick()

        # Calculate current level based on lines cleared
        new_level = (lines_cleared // 10) + 1
        if new_level != level:
            level = new_level
            fall_speed *= 1.15  # Increase speed by 15% each level

        # Adjust fall speed
        current_fall_speed = fall_speed
        keys = pygame.key.get_pressed()

        if keys[pygame.K_DOWN]:
            current_fall_speed = 0.05  # Fast fall when down key is held

        if fall_time / 1000 >= current_fall_speed:
            fall_time = 0
            current_piece.y += 1
            if not valid_space(current_piece, grid) and current_piece.y > 0:
                current_piece.y -= 1
                change_piece = True
                MOVE_SOUND.play()

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
                pygame.display.quit()
                quit()

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    current_piece.x -= 1
                    if not valid_space(current_piece, grid):
                        current_piece.x += 1
                    else:
                        MOVE_SOUND.play()
                elif event.key == pygame.K_RIGHT:
                    current_piece.x += 1
                    if not valid_space(current_piece, grid):
                        current_piece.x -= 1
                    else:
                        MOVE_SOUND.play()
                elif event.key == pygame.K_DOWN:
                    current_piece.y += 1
                    if not valid_space(current_piece, grid):
                        current_piece.y -= 1
                elif event.key == pygame.K_UP:
                    current_piece.rotation = (current_piece.rotation + 1) % len(current_piece.shape)
                    if not valid_space(current_piece, grid):
                        current_piece.rotation = (current_piece.rotation - 1) % len(current_piece.shape)
                    else:
                        ROTATE_SOUND.play()
                elif event.key == pygame.K_SPACE:
                    paused = not paused  # Toggle pause

        if paused:
            pause_screen(win)
            continue  # Skip the rest of the loop to effectively pause

        shape_pos = convert_shape_format(current_piece)

        # Add piece to the grid for drawing
        for i in range(len(shape_pos)):
            x, y = shape_pos[i]
            if y > -1:
                if 0 <= x < GRID_WIDTH and 0 <= y < GRID_HEIGHT:
                    grid[y][x] = current_piece.color

        if change_piece:
            for pos in shape_pos:
                p = (pos[0], pos[1])
                if 0 <= p[0] < GRID_WIDTH and 0 <= p[1] < GRID_HEIGHT:
                    locked_positions[p] = current_piece.color
            current_piece = next_piece
            next_piece = get_shape()
            change_piece = False

            cleared = clear_rows(grid, locked_positions)
            lines_cleared += cleared  # Update lines cleared

        # Start background music once when the game starts
        if not the_music_started:
            play_background_music()
            the_music_started = True

        draw_window(win, grid, lines_cleared, level, high_score)
        draw_next_shape(next_piece, win)
        pygame.display.update()

        if check_lost(locked_positions):
            GAME_OVER_SOUND.play()
            pygame.time.delay(500)
            run = False
            stop_background_music()
            update_high_score_if_needed(lines_cleared)

    game_over_screen(win, lines_cleared, high_score)

def update_high_score_if_needed(current_score):
    global high_score
    if current_score > high_score:
        high_score = current_score
        save_high_score(high_score)

def game_over_screen(surface, final_score, _):
    # Update high score if necessary
    if final_score > high_score:
        high_score = final_score
        save_high_score(high_score)

    pygame.mixer.music.stop()  # Ensure music is stopped on game over

    while True:
        surface.fill((0, 0, 0))
        draw_text_middle("YOU LOST!", 60, (255, 255, 255), surface, y_offset=-50)
        
        # Display final score
        font_small = pygame.font.SysFont('comicsans', 30)
        score_label = font_small.render(f'Your Score: {final_score}', 1, (255, 255, 255))
        surface.blit(score_label, ((SCREEN_WIDTH / 2) - (score_label.get_width() / 2), (SCREEN_HEIGHT / 2) - 10))
        
        # Prompt to return to menu
        prompt_label = font_small.render('Press Space to return to the menu.', 1, (255, 255, 255))
        surface.blit(prompt_label, ((SCREEN_WIDTH / 2) - (prompt_label.get_width() / 2), (SCREEN_HEIGHT / 2) + 30))
        
        pygame.display.update()
        
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    main_menu()  # Return to main menu

def pause_screen(surface):
    pause_font = pygame.font.SysFont('comicsans', 40, bold=True)
    pause_label = pause_font.render('Game Paused', 1, (255, 255, 255))
    prompt_font = pygame.font.SysFont('comicsans', 20)
    prompt_label = prompt_font.render('Press Space to Resume', 1, (255, 255, 255))
    
    surface.blit(pause_label, ((SCREEN_WIDTH / 2) - (pause_label.get_width() / 2), SCREEN_HEIGHT / 2 - 30))
    surface.blit(prompt_label, ((SCREEN_WIDTH / 2) - (prompt_label.get_width() / 2), SCREEN_HEIGHT / 2 + 10))
    pygame.display.update()

def main_menu():
    global high_score
    load_high_score()  # Ensure high_score is loaded before displaying menu
    run = True
    while run:
        win.fill((0, 0, 0))
        
        # Draw the "Tetris" title
        font_title = pygame.font.SysFont('comicsans', 60, bold=True)
        title_label = font_title.render('Tetris', 1, (255, 255, 255))
        win.blit(title_label, (SCREEN_WIDTH / 2 - title_label.get_width() / 2, 100))
        
        # Display High Score
        font_high = pygame.font.SysFont('comicsans', 30, bold=True)
        high_label = font_high.render(f'High Score: {high_score}', 1, (255, 255, 255))
        win.blit(high_label, (SCREEN_WIDTH / 2 - high_label.get_width() / 2, 200))
        
        # Display menu options
        font_options = pygame.font.SysFont('comicsans', 30)
        option1 = font_options.render('1: New Game', 1, (255, 255, 255))
        option2 = font_options.render('2: Options', 1, (255, 255, 255))
        option3 = font_options.render('3: Exit', 1, (255, 255, 255))
        
        win.blit(option1, (SCREEN_WIDTH / 2 - option1.get_width() / 2, 300))
        win.blit(option2, (SCREEN_WIDTH / 2 - option2.get_width() / 2, 350))
        win.blit(option3, (SCREEN_WIDTH / 2 - option3.get_width() / 2, 400))
        
        pygame.display.update()
        
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
                pygame.quit()
                quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_1:
                    main()  # Start new game
                elif event.key == pygame.K_2:
                    options_menu()  # Open options menu
                elif event.key == pygame.K_3:
                    run = False
                    pygame.quit()
                    quit()
    pygame.quit()

def options_menu():
    global music_volume, sfx_volume
    run = True
    # Create sliders: (x, y, width, height, min_val, max_val, start_val, label)
    music_slider = Slider(SCREEN_WIDTH / 2 - 100, 150, 200, 20, 0, 10, music_volume, 'Music Volume')
    sfx_slider = Slider(SCREEN_WIDTH / 2 - 100, 250, 200, 20, 0, 10, sfx_volume, 'SFX Volume')
    
    while run:
        win.fill((0, 0, 0))
        
        # Draw the "Options" title
        font_title = pygame.font.SysFont('comicsans', 60, bold=True)
        title_label = font_title.render('Options', 1, (255, 255, 255))
        win.blit(title_label, (SCREEN_WIDTH / 2 - title_label.get_width() / 2, 50))
        
        # Draw sliders
        music_slider.draw(win)
        sfx_slider.draw(win)
        
        # Instructions to return to main menu
        font_instruct = pygame.font.SysFont('comicsans', 25)
        instruct_label = font_instruct.render('Press Esc to return to the main menu.', 1, (255, 255, 255))
        win.blit(instruct_label, (SCREEN_WIDTH / 2 - instruct_label.get_width() / 2, 400))
        
        pygame.display.update()
        
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
                pygame.display.quit()
                quit()
            # Handle slider events
            music_slider.handle_event(event)
            sfx_slider.handle_event(event)
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    # Update volume settings
                    set_music_volume(music_slider.value)
                    set_sfx_volume(sfx_slider.value)
                    run = False  # Exit options_menu
    # Do NOT call pygame.quit() here. Instead, return to main_menu
    # pygame.quit()  # Removed to prevent crashing

def set_sfx_volume(volume):
    global sfx_volume
    sfx_volume = volume
    MOVE_SOUND.set_volume(sfx_volume / 10)
    ROTATE_SOUND.set_volume(sfx_volume / 10)
    CLEAR_SOUND.set_volume(sfx_volume / 10)
    GAME_OVER_SOUND.set_volume(sfx_volume / 10)

def set_music_volume(volume):
    global music_volume
    music_volume = volume
    pygame.mixer.music.set_volume(music_volume / 10)

def main():
    global high_score
    locked_positions = {}
    grid = create_grid(locked_positions)

    change_piece = False
    run = True
    current_piece = get_shape()
    next_piece = get_shape()
    clock = pygame.time.Clock()
    fall_time = 0

    BASE_FALL_SPEED = 0.5  # Base fall speed in seconds
    fall_speed = BASE_FALL_SPEED
    lines_cleared = 0  # Initialize lines cleared counter
    level = 1  # Initialize level

    paused = False  # Game paused state

    the_music_started = False  # To ensure music starts only once

    while run:
        grid = create_grid(locked_positions)
        fall_time += clock.get_rawtime()
        clock.tick()

        # Calculate current level based on lines cleared
        new_level = (lines_cleared // 10) + 1
        if new_level != level:
            level = new_level
            fall_speed *= 1.15  # Increase speed by 15% each level

        # Adjust fall speed
        current_fall_speed = fall_speed
        keys = pygame.key.get_pressed()

        if keys[pygame.K_DOWN]:
            current_fall_speed = 0.05  # Fast fall when down key is held

        if fall_time / 1000 >= current_fall_speed:
            fall_time = 0
            current_piece.y += 1
            if not valid_space(current_piece, grid) and current_piece.y > 0:
                current_piece.y -= 1
                change_piece = True
                MOVE_SOUND.play()

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
                pygame.display.quit()
                quit()

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    current_piece.x -= 1
                    if not valid_space(current_piece, grid):
                        current_piece.x += 1
                    else:
                        MOVE_SOUND.play()
                elif event.key == pygame.K_RIGHT:
                    current_piece.x += 1
                    if not valid_space(current_piece, grid):
                        current_piece.x -= 1
                    else:
                        MOVE_SOUND.play()
                elif event.key == pygame.K_DOWN:
                    current_piece.y += 1
                    if not valid_space(current_piece, grid):
                        current_piece.y -= 1
                elif event.key == pygame.K_UP:
                    current_piece.rotation = (current_piece.rotation + 1) % len(current_piece.shape)
                    if not valid_space(current_piece, grid):
                        current_piece.rotation = (current_piece.rotation - 1) % len(current_piece.shape)
                    else:
                        ROTATE_SOUND.play()
                elif event.key == pygame.K_SPACE:
                    paused = not paused  # Toggle pause

        if paused:
            pause_screen(win)
            continue  # Skip the rest of the loop to effectively pause

        shape_pos = convert_shape_format(current_piece)

        # Add piece to the grid for drawing
        for i in range(len(shape_pos)):
            x, y = shape_pos[i]
            if y > -1:
                if 0 <= x < GRID_WIDTH and 0 <= y < GRID_HEIGHT:
                    grid[y][x] = current_piece.color

        if change_piece:
            for pos in shape_pos:
                p = (pos[0], pos[1])
                if 0 <= p[0] < GRID_WIDTH and 0 <= p[1] < GRID_HEIGHT:
                    locked_positions[p] = current_piece.color
            current_piece = next_piece
            next_piece = get_shape()
            change_piece = False

            cleared = clear_rows(grid, locked_positions)
            lines_cleared += cleared  # Update lines cleared

        # Start background music once when the game starts
        if not the_music_started:
            play_background_music()
            the_music_started = True

        draw_window(win, grid, lines_cleared, level, high_score)  # Removed high_score from in-game display
        draw_next_shape(next_piece, win)
        pygame.display.update()

        if check_lost(locked_positions):
            GAME_OVER_SOUND.play()
            pygame.time.delay(500)
            run = False
            stop_background_music()
            update_high_score_if_needed(lines_cleared)

    game_over_screen(win, lines_cleared, high_score)

def update_high_score_if_needed(current_score):
    global high_score
    if current_score > high_score:
        high_score = current_score
        save_high_score(high_score)

def game_over_screen(surface, final_score, _):
    # Update high score if necessary
    if final_score > high_score:
        high_score = final_score
        save_high_score(high_score)

    pygame.mixer.music.stop()  # Ensure music is stopped on game over

    while True:
        surface.fill((0, 0, 0))
        draw_text_middle("YOU LOST!", 60, (255, 255, 255), surface, y_offset=-50)
        
        # Display final score
        font_small = pygame.font.SysFont('comicsans', 30)
        score_label = font_small.render(f'Your Score: {final_score}', 1, (255, 255, 255))
        surface.blit(score_label, ((SCREEN_WIDTH / 2) - (score_label.get_width() / 2), (SCREEN_HEIGHT / 2) - 10))
        
        # Prompt to return to menu
        prompt_label = font_small.render('Press Space to return to the menu.', 1, (255, 255, 255))
        surface.blit(prompt_label, ((SCREEN_WIDTH / 2) - (prompt_label.get_width() / 2), (SCREEN_HEIGHT / 2) + 30))
        
        pygame.display.update()
        
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    main_menu()  # Return to main menu

def pause_screen(surface):
    pause_font = pygame.font.SysFont('comicsans', 40, bold=True)
    pause_label = pause_font.render('Game Paused', 1, (255, 255, 255))
    prompt_font = pygame.font.SysFont('comicsans', 20)
    prompt_label = prompt_font.render('Press Space to Resume', 1, (255, 255, 255))
    
    surface.blit(pause_label, ((SCREEN_WIDTH / 2) - (pause_label.get_width() / 2), SCREEN_HEIGHT / 2 - 30))
    surface.blit(prompt_label, ((SCREEN_WIDTH / 2) - (prompt_label.get_width() / 2), SCREEN_HEIGHT / 2 + 10))
    pygame.display.update()

def main_menu():
    global high_score
    load_high_score()  # Ensure high_score is loaded before displaying menu
    run = True
    while run:
        win.fill((0, 0, 0))
        
        # Draw the "Tetris" title
        font_title = pygame.font.SysFont('comicsans', 60, bold=True)
        title_label = font_title.render('Tetris', 1, (255, 255, 255))
        win.blit(title_label, (SCREEN_WIDTH / 2 - title_label.get_width() / 2, 100))
        
        # Display High Score
        font_high = pygame.font.SysFont('comicsans', 30, bold=True)
        high_label = font_high.render(f'High Score: {high_score}', 1, (255, 255, 255))
        win.blit(high_label, (SCREEN_WIDTH / 2 - high_label.get_width() / 2, 200))
        
        # Display menu options
        font_options = pygame.font.SysFont('comicsans', 30)
        option1 = font_options.render('1: New Game', 1, (255, 255, 255))
        option2 = font_options.render('2: Options', 1, (255, 255, 255))
        option3 = font_options.render('3: Exit', 1, (255, 255, 255))
        
        win.blit(option1, (SCREEN_WIDTH / 2 - option1.get_width() / 2, 300))
        win.blit(option2, (SCREEN_WIDTH / 2 - option2.get_width() / 2, 350))
        win.blit(option3, (SCREEN_WIDTH / 2 - option3.get_width() / 2, 400))
        
        pygame.display.update()
        
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
                pygame.quit()
                quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_1:
                    main()  # Start new game
                elif event.key == pygame.K_2:
                    options_menu()  # Open options menu
                elif event.key == pygame.K_3:
                    run = False
                    pygame.quit()
                    quit()
    pygame.quit()

def options_menu():
    global music_volume, sfx_volume
    run = True
    # Create sliders: (x, y, width, height, min_val, max_val, start_val, label)
    music_slider = Slider(SCREEN_WIDTH / 2 - 100, 150, 200, 20, 0, 10, music_volume, 'Music Volume')
    sfx_slider = Slider(SCREEN_WIDTH / 2 - 100, 250, 200, 20, 0, 10, sfx_volume, 'SFX Volume')
    
    while run:
        win.fill((0, 0, 0))
        
        # Draw the "Options" title
        font_title = pygame.font.SysFont('comicsans', 60, bold=True)
        title_label = font_title.render('Options', 1, (255, 255, 255))
        win.blit(title_label, (SCREEN_WIDTH / 2 - title_label.get_width() / 2, 50))
        
        # Draw sliders
        music_slider.draw(win)
        sfx_slider.draw(win)
        
        # Instructions to return to main menu
        font_instruct = pygame.font.SysFont('comicsans', 25)
        instruct_label = font_instruct.render('Press Esc to return to the main menu.', 1, (255, 255, 255))
        win.blit(instruct_label, (SCREEN_WIDTH / 2 - instruct_label.get_width() / 2, 400))
        
        pygame.display.update()
        
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
                pygame.display.quit()
                quit()
            # Handle slider events
            music_slider.handle_event(event)
            sfx_slider.handle_event(event)
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    # Update volume settings
                    set_music_volume(music_slider.value)
                    set_sfx_volume(sfx_slider.value)
                    run = False  # Exit options_menu
    # Do NOT call pygame.quit() here. Instead, return to main_menu
    # pygame.quit()  # Removed to prevent crashing

def set_sfx_volume(volume):
    global sfx_volume
    sfx_volume = volume
    MOVE_SOUND.set_volume(sfx_volume / 10)
    ROTATE_SOUND.set_volume(sfx_volume / 10)
    CLEAR_SOUND.set_volume(sfx_volume / 10)
    GAME_OVER_SOUND.set_volume(sfx_volume / 10)

def set_music_volume(volume):
    global music_volume
    music_volume = volume
    pygame.mixer.music.set_volume(music_volume / 10)

def main():
    global high_score
    locked_positions = {}
    grid = create_grid(locked_positions)

    change_piece = False
    run = True
    current_piece = get_shape()
    next_piece = get_shape()
    clock = pygame.time.Clock()
    fall_time = 0

    BASE_FALL_SPEED = 0.5  # Base fall speed in seconds
    fall_speed = BASE_FALL_SPEED
    lines_cleared = 0  # Initialize lines cleared counter
    level = 1  # Initialize level

    paused = False  # Game paused state

    the_music_started = False  # To ensure music starts only once

    while run:
        grid = create_grid(locked_positions)
        fall_time += clock.get_rawtime()
        clock.tick()

        # Calculate current level based on lines cleared
        new_level = (lines_cleared // 10) + 1
        if new_level != level:
            level = new_level
            fall_speed *= 1.15  # Increase speed by 15% each level

        # Adjust fall speed
        current_fall_speed = fall_speed
        keys = pygame.key.get_pressed()

        if keys[pygame.K_DOWN]:
            current_fall_speed = 0.05  # Fast fall when down key is held

        if fall_time / 1000 >= current_fall_speed:
            fall_time = 0
            current_piece.y += 1
            if not valid_space(current_piece, grid) and current_piece.y > 0:
                current_piece.y -= 1
                change_piece = True
                MOVE_SOUND.play()

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
                pygame.display.quit()
                quit()

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    current_piece.x -= 1
                    if not valid_space(current_piece, grid):
                        current_piece.x += 1
                    else:
                        MOVE_SOUND.play()
                elif event.key == pygame.K_RIGHT:
                    current_piece.x += 1
                    if not valid_space(current_piece, grid):
                        current_piece.x -= 1
                    else:
                        MOVE_SOUND.play()
                elif event.key == pygame.K_DOWN:
                    current_piece.y += 1
                    if not valid_space(current_piece, grid):
                        current_piece.y -= 1
                elif event.key == pygame.K_UP:
                    current_piece.rotation = (current_piece.rotation + 1) % len(current_piece.shape)
                    if not valid_space(current_piece, grid):
                        current_piece.rotation = (current_piece.rotation - 1) % len(current_piece.shape)
                    else:
                        ROTATE_SOUND.play()
                elif event.key == pygame.K_SPACE:
                    paused = not paused  # Toggle pause

        if paused:
            pause_screen(win)
            continue  # Skip the rest of the loop to effectively pause

        shape_pos = convert_shape_format(current_piece)

        # Add piece to the grid for drawing
        for i in range(len(shape_pos)):
            x, y = shape_pos[i]
            if y > -1:
                if 0 <= x < GRID_WIDTH and 0 <= y < GRID_HEIGHT:
                    grid[y][x] = current_piece.color

        if change_piece:
            for pos in shape_pos:
                p = (pos[0], pos[1])
                if 0 <= p[0] < GRID_WIDTH and 0 <= p[1] < GRID_HEIGHT:
                    locked_positions[p] = current_piece.color
            current_piece = next_piece
            next_piece = get_shape()
            change_piece = False

            cleared = clear_rows(grid, locked_positions)
            lines_cleared += cleared  # Update lines cleared

        # Start background music once when the game starts
        if not the_music_started:
            play_background_music()
            the_music_started = True

        draw_window(win, grid, lines_cleared, level, high_score)  # Removed high_score from in-game display
        draw_next_shape(next_piece, win)
        pygame.display.update()

        if check_lost(locked_positions):
            GAME_OVER_SOUND.play()
            pygame.time.delay(500)
            run = False
            stop_background_music()
            update_high_score_if_needed(lines_cleared)

    game_over_screen(win, lines_cleared, high_score)

def update_high_score_if_needed(current_score):
    global high_score
    if current_score > high_score:
        high_score = current_score
        save_high_score(high_score)

def game_over_screen(surface, final_score, _):
    global high_score
    # Update high score if necessary
    if final_score > high_score:
        high_score = final_score
        save_high_score(high_score)

    pygame.mixer.music.stop()  # Ensure music is stopped on game over

    while True:
        surface.fill((0, 0, 0))
        draw_text_middle("YOU LOST!", 60, (255, 255, 255), surface, y_offset=-50)
        
        # Display final score
        font_small = pygame.font.SysFont('comicsans', 30)
        score_label = font_small.render(f'Your Score: {final_score}', 1, (255, 255, 255))
        surface.blit(score_label, ((SCREEN_WIDTH / 2) - (score_label.get_width() / 2), (SCREEN_HEIGHT / 2) - 10))
        
        # Prompt to return to menu
        prompt_label = font_small.render('Press Space to return to the menu.', 1, (255, 255, 255))
        surface.blit(prompt_label, ((SCREEN_WIDTH / 2) - (prompt_label.get_width() / 2), (SCREEN_HEIGHT / 2) + 30))
        
        pygame.display.update()
        
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    main_menu()  # Return to main menu

def pause_screen(surface):
    pause_font = pygame.font.SysFont('comicsans', 40, bold=True)
    pause_label = pause_font.render('Game Paused', 1, (255, 255, 255))
    prompt_font = pygame.font.SysFont('comicsans', 20)
    prompt_label = prompt_font.render('Press Space to Resume', 1, (255, 255, 255))
    
    surface.blit(pause_label, ((SCREEN_WIDTH / 2) - (pause_label.get_width() / 2), SCREEN_HEIGHT / 2 - 30))
    surface.blit(prompt_label, ((SCREEN_WIDTH / 2) - (prompt_label.get_width() / 2), SCREEN_HEIGHT / 2 + 10))
    pygame.display.update()

def main_menu():
    global high_score
    load_high_score()  # Ensure high_score is loaded before displaying menu
    run = True
    while run:
        win.fill((0, 0, 0))
        
        # Draw the "Tetris" title
        font_title = pygame.font.SysFont('comicsans', 60, bold=True)
        title_label = font_title.render('Tetris', 1, (255, 255, 255))
        win.blit(title_label, (SCREEN_WIDTH / 2 - title_label.get_width() / 2, 100))
        
        # Display High Score
        font_high = pygame.font.SysFont('comicsans', 30, bold=True)
        high_label = font_high.render(f'High Score: {high_score}', 1, (255, 255, 255))
        win.blit(high_label, (SCREEN_WIDTH / 2 - high_label.get_width() / 2, 200))
        
        # Display menu options
        font_options = pygame.font.SysFont('comicsans', 30)
        option1 = font_options.render('1: New Game', 1, (255, 255, 255))
        option2 = font_options.render('2: Options', 1, (255, 255, 255))
        option3 = font_options.render('3: Exit', 1, (255, 255, 255))
        
        win.blit(option1, (SCREEN_WIDTH / 2 - option1.get_width() / 2, 300))
        win.blit(option2, (SCREEN_WIDTH / 2 - option2.get_width() / 2, 350))
        win.blit(option3, (SCREEN_WIDTH / 2 - option3.get_width() / 2, 400))
        
        pygame.display.update()
        
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
                pygame.quit()
                quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_1:
                    main()  # Start new game
                elif event.key == pygame.K_2:
                    options_menu()  # Open options menu
                elif event.key == pygame.K_3:
                    run = False
                    pygame.quit()
                    quit()
    pygame.quit()

def options_menu():
    global music_volume, sfx_volume
    run = True
    # Create sliders: (x, y, width, height, min_val, max_val, start_val, label)
    music_slider = Slider(SCREEN_WIDTH / 2 - 100, 150, 200, 20, 0, 10, music_volume, 'Music Volume')
    sfx_slider = Slider(SCREEN_WIDTH / 2 - 100, 250, 200, 20, 0, 10, sfx_volume, 'SFX Volume')
    
    while run:
        win.fill((0, 0, 0))
        
        # Draw the "Options" title
        font_title = pygame.font.SysFont('comicsans', 60, bold=True)
        title_label = font_title.render('Options', 1, (255, 255, 255))
        win.blit(title_label, (SCREEN_WIDTH / 2 - title_label.get_width() / 2, 50))
        
        # Draw sliders
        music_slider.draw(win)
        sfx_slider.draw(win)
        
        # Instructions to return to main menu
        font_instruct = pygame.font.SysFont('comicsans', 25)
        instruct_label = font_instruct.render('Press Esc to return to the main menu.', 1, (255, 255, 255))
        win.blit(instruct_label, (SCREEN_WIDTH / 2 - instruct_label.get_width() / 2, 400))
        
        pygame.display.update()
        
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
                pygame.display.quit()
                quit()
            # Handle slider events
            music_slider.handle_event(event)
            sfx_slider.handle_event(event)
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    # Update volume settings
                    set_music_volume(music_slider.value)
                    set_sfx_volume(sfx_slider.value)
                    run = False  # Exit options_menu
    # Do NOT call pygame.quit() here. Instead, return to main_menu
    # pygame.quit()  # Removed to prevent crashing

def set_sfx_volume(volume):
    global sfx_volume
    sfx_volume = volume
    MOVE_SOUND.set_volume(sfx_volume / 10)
    ROTATE_SOUND.set_volume(sfx_volume / 10)
    CLEAR_SOUND.set_volume(sfx_volume / 10)
    GAME_OVER_SOUND.set_volume(sfx_volume / 10)

def set_music_volume(volume):
    global music_volume
    music_volume = volume
    pygame.mixer.music.set_volume(music_volume / 10)

def main():
    global high_score
    locked_positions = {}
    grid = create_grid(locked_positions)

    change_piece = False
    run = True
    current_piece = get_shape()
    next_piece = get_shape()
    clock = pygame.time.Clock()
    fall_time = 0

    BASE_FALL_SPEED = 0.5  # Base fall speed in seconds
    fall_speed = BASE_FALL_SPEED
    lines_cleared = 0  # Initialize lines cleared counter
    level = 1  # Initialize level

    paused = False  # Game paused state

    the_music_started = False  # To ensure music starts only once

    while run:
        grid = create_grid(locked_positions)
        fall_time += clock.get_rawtime()
        clock.tick()

        # Calculate current level based on lines cleared
        new_level = (lines_cleared // 10) + 1
        if new_level != level:
            level = new_level
            fall_speed *= 1.15  # Increase speed by 15% each level

        # Adjust fall speed
        current_fall_speed = fall_speed
        keys = pygame.key.get_pressed()

        if keys[pygame.K_DOWN]:
            current_fall_speed = 0.05  # Fast fall when down key is held

        if fall_time / 1000 >= current_fall_speed:
            fall_time = 0
            current_piece.y += 1
            if not valid_space(current_piece, grid) and current_piece.y > 0:
                current_piece.y -= 1
                change_piece = True
                MOVE_SOUND.play()

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
                pygame.display.quit()
                quit()

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    current_piece.x -= 1
                    if not valid_space(current_piece, grid):
                        current_piece.x += 1
                    else:
                        MOVE_SOUND.play()
                elif event.key == pygame.K_RIGHT:
                    current_piece.x += 1
                    if not valid_space(current_piece, grid):
                        current_piece.x -= 1
                    else:
                        MOVE_SOUND.play()
                elif event.key == pygame.K_DOWN:
                    current_piece.y += 1
                    if not valid_space(current_piece, grid):
                        current_piece.y -= 1
                elif event.key == pygame.K_UP:
                    current_piece.rotation = (current_piece.rotation + 1) % len(current_piece.shape)
                    if not valid_space(current_piece, grid):
                        current_piece.rotation = (current_piece.rotation - 1) % len(current_piece.shape)
                    else:
                        ROTATE_SOUND.play()
                elif event.key == pygame.K_SPACE:
                    paused = not paused  # Toggle pause

        if paused:
            pause_screen(win)
            continue  # Skip the rest of the loop to effectively pause

        shape_pos = convert_shape_format(current_piece)

        # Add piece to the grid for drawing
        for i in range(len(shape_pos)):
            x, y = shape_pos[i]
            if y > -1:
                if 0 <= x < GRID_WIDTH and 0 <= y < GRID_HEIGHT:
                    grid[y][x] = current_piece.color

        if change_piece:
            for pos in shape_pos:
                p = (pos[0], pos[1])
                if 0 <= p[0] < GRID_WIDTH and 0 <= p[1] < GRID_HEIGHT:
                    locked_positions[p] = current_piece.color
            current_piece = next_piece
            next_piece = get_shape()
            change_piece = False

            cleared = clear_rows(grid, locked_positions)
            lines_cleared += cleared  # Update lines cleared

        # Start background music once when the game starts
        if not the_music_started:
            play_background_music()
            the_music_started = True

        draw_window(win, grid, lines_cleared, level, high_score)  # Removed high_score from in-game display
        draw_next_shape(next_piece, win)
        pygame.display.update()

        if check_lost(locked_positions):
            GAME_OVER_SOUND.play()
            pygame.time.delay(500)
            run = False
            stop_background_music()
            update_high_score_if_needed(lines_cleared)

    game_over_screen(win, lines_cleared, high_score)

def update_high_score_if_needed(current_score):
    global high_score
    if current_score > high_score:
        high_score = current_score
        save_high_score(high_score)

def game_over_screen(surface, final_score, _):
    global high_score
    # Update high score if necessary
    if final_score > high_score:
        high_score = final_score
        save_high_score(high_score)

    pygame.mixer.music.stop()  # Ensure music is stopped on game over

    while True:
        surface.fill((0, 0, 0))
        draw_text_middle("YOU LOST!", 60, (255, 255, 255), surface, y_offset=-50)
        
        # Display final score
        font_small = pygame.font.SysFont('comicsans', 30)
        score_label = font_small.render(f'Your Score: {final_score}', 1, (255, 255, 255))
        surface.blit(score_label, ((SCREEN_WIDTH / 2) - (score_label.get_width() / 2), (SCREEN_HEIGHT / 2) - 10))
        
        # Prompt to return to menu
        prompt_label = font_small.render('Press Space to return to the menu.', 1, (255, 255, 255))
        surface.blit(prompt_label, ((SCREEN_WIDTH / 2) - (prompt_label.get_width() / 2), (SCREEN_HEIGHT / 2) + 30))
        
        pygame.display.update()
        
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    main_menu()  # Return to main menu

def pause_screen(surface):
    pause_font = pygame.font.SysFont('comicsans', 40, bold=True)
    pause_label = pause_font.render('Game Paused', 1, (255, 255, 255))
    prompt_font = pygame.font.SysFont('comicsans', 20)
    prompt_label = prompt_font.render('Press Space to Resume', 1, (255, 255, 255))
    
    surface.blit(pause_label, ((SCREEN_WIDTH / 2) - (pause_label.get_width() / 2), SCREEN_HEIGHT / 2 - 30))
    surface.blit(prompt_label, ((SCREEN_WIDTH / 2) - (prompt_label.get_width() / 2), SCREEN_HEIGHT / 2 + 10))
    pygame.display.update()

def main_menu():
    global high_score
    load_high_score()  # Ensure high_score is loaded before displaying menu
    run = True
    while run:
        win.fill((0, 0, 0))
        
        # Draw the "Tetris" title
        font_title = pygame.font.SysFont('comicsans', 60, bold=True)
        title_label = font_title.render('Tetris', 1, (255, 255, 255))
        win.blit(title_label, (SCREEN_WIDTH / 2 - title_label.get_width() / 2, 100))
        
        # Display High Score
        font_high = pygame.font.SysFont('comicsans', 30, bold=True)
        high_label = font_high.render(f'High Score: {high_score}', 1, (255, 255, 255))
        win.blit(high_label, (SCREEN_WIDTH / 2 - high_label.get_width() / 2, 200))
        
        # Display menu options
        font_options = pygame.font.SysFont('comicsans', 30)
        option1 = font_options.render('1: New Game', 1, (255, 255, 255))
        option2 = font_options.render('2: Options', 1, (255, 255, 255))
        option3 = font_options.render('3: Exit', 1, (255, 255, 255))
        
        win.blit(option1, (SCREEN_WIDTH / 2 - option1.get_width() / 2, 300))
        win.blit(option2, (SCREEN_WIDTH / 2 - option2.get_width() / 2, 350))
        win.blit(option3, (SCREEN_WIDTH / 2 - option3.get_width() / 2, 400))
        
        pygame.display.update()
        
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
                pygame.quit()
                quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_1:
                    main()  # Start new game
                elif event.key == pygame.K_2:
                    options_menu()  # Open options menu
                elif event.key == pygame.K_3:
                    run = False
                    pygame.quit()
                    quit()
    pygame.quit()

def options_menu():
    global music_volume, sfx_volume
    run = True
    # Create sliders: (x, y, width, height, min_val, max_val, start_val, label)
    music_slider = Slider(SCREEN_WIDTH / 2 - 100, 150, 200, 20, 0, 10, music_volume, 'Music Volume')
    sfx_slider = Slider(SCREEN_WIDTH / 2 - 100, 250, 200, 20, 0, 10, sfx_volume, 'SFX Volume')
    
    while run:
        win.fill((0, 0, 0))
        
        # Draw the "Options" title
        font_title = pygame.font.SysFont('comicsans', 60, bold=True)
        title_label = font_title.render('Options', 1, (255, 255, 255))
        win.blit(title_label, (SCREEN_WIDTH / 2 - title_label.get_width() / 2, 50))
        
        # Draw sliders
        music_slider.draw(win)
        sfx_slider.draw(win)
        
        # Instructions to return to main menu
        font_instruct = pygame.font.SysFont('comicsans', 25)
        instruct_label = font_instruct.render('Press Esc to return to the main menu.', 1, (255, 255, 255))
        win.blit(instruct_label, (SCREEN_WIDTH / 2 - instruct_label.get_width() / 2, 400))
        
        pygame.display.update()
        
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
                pygame.display.quit()
                quit()
            # Handle slider events
            music_slider.handle_event(event)
            sfx_slider.handle_event(event)
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    # Update volume settings
                    set_music_volume(music_slider.value)
                    set_sfx_volume(sfx_slider.value)
                    run = False  # Exit options_menu
    # Do NOT call pygame.quit() here. Instead, return to main_menu
    # pygame.quit()  # Removed to prevent crashing

def set_sfx_volume(volume):
    global sfx_volume
    sfx_volume = volume
    MOVE_SOUND.set_volume(sfx_volume / 10)
    ROTATE_SOUND.set_volume(sfx_volume / 10)
    CLEAR_SOUND.set_volume(sfx_volume / 10)
    GAME_OVER_SOUND.set_volume(sfx_volume / 10)

def set_music_volume(volume):
    global music_volume
    music_volume = volume
    pygame.mixer.music.set_volume(music_volume / 10)

def main():
    global high_score
    locked_positions = {}
    grid = create_grid(locked_positions)

    change_piece = False
    run = True
    current_piece = get_shape()
    next_piece = get_shape()
    clock = pygame.time.Clock()
    fall_time = 0

    BASE_FALL_SPEED = 0.5  # Base fall speed in seconds
    fall_speed = BASE_FALL_SPEED
    lines_cleared = 0  # Initialize lines cleared counter
    level = 1  # Initialize level

    paused = False  # Game paused state

    the_music_started = False  # To ensure music starts only once

    while run:
        grid = create_grid(locked_positions)
        fall_time += clock.get_rawtime()
        clock.tick()

        # Calculate current level based on lines cleared
        new_level = (lines_cleared // 10) + 1
        if new_level != level:
            level = new_level
            fall_speed *= 1.15  # Increase speed by 15% each level

        # Adjust fall speed
        current_fall_speed = fall_speed
        keys = pygame.key.get_pressed()

        if keys[pygame.K_DOWN]:
            current_fall_speed = 0.05  # Fast fall when down key is held

        if fall_time / 1000 >= current_fall_speed:
            fall_time = 0
            current_piece.y += 1
            if not valid_space(current_piece, grid) and current_piece.y > 0:
                current_piece.y -= 1
                change_piece = True
                MOVE_SOUND.play()

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
                pygame.display.quit()
                quit()

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    current_piece.x -= 1
                    if not valid_space(current_piece, grid):
                        current_piece.x += 1
                    else:
                        MOVE_SOUND.play()
                elif event.key == pygame.K_RIGHT:
                    current_piece.x += 1
                    if not valid_space(current_piece, grid):
                        current_piece.x -= 1
                    else:
                        MOVE_SOUND.play()
                elif event.key == pygame.K_DOWN:
                    current_piece.y += 1
                    if not valid_space(current_piece, grid):
                        current_piece.y -= 1
                elif event.key == pygame.K_UP:
                    current_piece.rotation = (current_piece.rotation + 1) % len(current_piece.shape)
                    if not valid_space(current_piece, grid):
                        current_piece.rotation = (current_piece.rotation - 1) % len(current_piece.shape)
                    else:
                        ROTATE_SOUND.play()
                elif event.key == pygame.K_SPACE:
                    paused = not paused  # Toggle pause

        if paused:
            pause_screen(win)
            continue  # Skip the rest of the loop to effectively pause

        shape_pos = convert_shape_format(current_piece)

        # Add piece to the grid for drawing
        for i in range(len(shape_pos)):
            x, y = shape_pos[i]
            if y > -1:
                if 0 <= x < GRID_WIDTH and 0 <= y < GRID_HEIGHT:
                    grid[y][x] = current_piece.color

        if change_piece:
            for pos in shape_pos:
                p = (pos[0], pos[1])
                if 0 <= p[0] < GRID_WIDTH and 0 <= p[1] < GRID_HEIGHT:
                    locked_positions[p] = current_piece.color
            current_piece = next_piece
            next_piece = get_shape()
            change_piece = False

            cleared = clear_rows(grid, locked_positions)
            lines_cleared += cleared  # Update lines cleared

        # Start background music once when the game starts
        if not the_music_started:
            play_background_music()
            the_music_started = True

        draw_window(win, grid, lines_cleared, level, high_score)  # Removed high_score from in-game display
        draw_next_shape(next_piece, win)
        pygame.display.update()

        if check_lost(locked_positions):
            GAME_OVER_SOUND.play()
            pygame.time.delay(500)
            run = False
            stop_background_music()
            update_high_score_if_needed(lines_cleared)

    game_over_screen(win, lines_cleared, high_score)

def update_high_score_if_needed(current_score):
    global high_score
    if current_score > high_score:
        high_score = current_score
        save_high_score(high_score)

def game_over_screen(surface, final_score, _):
    global high_score
    # Update high score if necessary
    if final_score > high_score:
        high_score = final_score
        save_high_score(high_score)

    pygame.mixer.music.stop()  # Ensure music is stopped on game over

    while True:
        surface.fill((0, 0, 0))
        draw_text_middle("YOU LOST!", 60, (255, 255, 255), surface, y_offset=-50)
        
        # Display final score
        font_small = pygame.font.SysFont('comicsans', 30)
        score_label = font_small.render(f'Your Score: {final_score}', 1, (255, 255, 255))
        surface.blit(score_label, ((SCREEN_WIDTH / 2) - (score_label.get_width() / 2), (SCREEN_HEIGHT / 2) - 10))
        
        # Prompt to return to menu
        prompt_label = font_small.render('Press Space to return to the menu.', 1, (255, 255, 255))
        surface.blit(prompt_label, ((SCREEN_WIDTH / 2) - (prompt_label.get_width() / 2), (SCREEN_HEIGHT / 2) + 30))
        
        pygame.display.update()
        
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    main_menu()  # Return to main menu

def pause_screen(surface):
    pause_font = pygame.font.SysFont('comicsans', 40, bold=True)
    pause_label = pause_font.render('Game Paused', 1, (255, 255, 255))
    prompt_font = pygame.font.SysFont('comicsans', 20)
    prompt_label = prompt_font.render('Press Space to Resume', 1, (255, 255, 255))
    
    surface.blit(pause_label, ((SCREEN_WIDTH / 2) - (pause_label.get_width() / 2), SCREEN_HEIGHT / 2 - 30))
    surface.blit(prompt_label, ((SCREEN_WIDTH / 2) - (prompt_label.get_width() / 2), SCREEN_HEIGHT / 2 + 10))
    pygame.display.update()

def main_menu():
    global high_score
    load_high_score()  # Ensure high_score is loaded before displaying menu
    run = True
    while run:
        win.fill((0, 0, 0))
        
        # Draw the "Tetris" title
        font_title = pygame.font.SysFont('comicsans', 60, bold=True)
        title_label = font_title.render('Tetris', 1, (255, 255, 255))
        win.blit(title_label, (SCREEN_WIDTH / 2 - title_label.get_width() / 2, 100))
        
        # Display High Score
        font_high = pygame.font.SysFont('comicsans', 30, bold=True)
        high_label = font_high.render(f'High Score: {high_score}', 1, (255, 255, 255))
        win.blit(high_label, (SCREEN_WIDTH / 2 - high_label.get_width() / 2, 200))
        
        # Display menu options
        font_options = pygame.font.SysFont('comicsans', 30)
        option1 = font_options.render('1: New Game', 1, (255, 255, 255))
        option2 = font_options.render('2: Options', 1, (255, 255, 255))
        option3 = font_options.render('3: Exit', 1, (255, 255, 255))
        
        win.blit(option1, (SCREEN_WIDTH / 2 - option1.get_width() / 2, 300))
        win.blit(option2, (SCREEN_WIDTH / 2 - option2.get_width() / 2, 350))
        win.blit(option3, (SCREEN_WIDTH / 2 - option3.get_width() / 2, 400))
        
        pygame.display.update()
        
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
                pygame.quit()
                quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_1:
                    main()  # Start new game
                elif event.key == pygame.K_2:
                    options_menu()  # Open options menu
                elif event.key == pygame.K_3:
                    run = False
                    pygame.quit()
                    quit()
    pygame.quit()

def options_menu():
    global music_volume, sfx_volume
    run = True
    # Create sliders: (x, y, width, height, min_val, max_val, start_val, label)
    music_slider = Slider(SCREEN_WIDTH / 2 - 100, 150, 200, 20, 0, 10, music_volume, 'Music Volume')
    sfx_slider = Slider(SCREEN_WIDTH / 2 - 100, 250, 200, 20, 0, 10, sfx_volume, 'SFX Volume')
    
    while run:
        win.fill((0, 0, 0))
        
        # Draw the "Options" title
        font_title = pygame.font.SysFont('comicsans', 60, bold=True)
        title_label = font_title.render('Options', 1, (255, 255, 255))
        win.blit(title_label, (SCREEN_WIDTH / 2 - title_label.get_width() / 2, 50))
        
        # Draw sliders
        music_slider.draw(win)
        sfx_slider.draw(win)
        
        # Instructions to return to main menu
        font_instruct = pygame.font.SysFont('comicsans', 25)
        instruct_label = font_instruct.render('Press Esc to return to the main menu.', 1, (255, 255, 255))
        win.blit(instruct_label, (SCREEN_WIDTH / 2 - instruct_label.get_width() / 2, 400))
        
        pygame.display.update()
        
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
                pygame.display.quit()
                quit()
            # Handle slider events
            music_slider.handle_event(event)
            sfx_slider.handle_event(event)
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    # Update volume settings
                    set_music_volume(music_slider.value)
                    set_sfx_volume(sfx_slider.value)
                    run = False  # Exit options_menu
    # Do NOT call pygame.quit() here. Instead, return to main_menu
    # pygame.quit()  # Removed to prevent crashing

def set_sfx_volume(volume):
    global sfx_volume
    sfx_volume = volume
    MOVE_SOUND.set_volume(sfx_volume / 10)
    ROTATE_SOUND.set_volume(sfx_volume / 10)
    CLEAR_SOUND.set_volume(sfx_volume / 10)
    GAME_OVER_SOUND.set_volume(sfx_volume / 10)

def set_music_volume(volume):
    global music_volume
    music_volume = volume
    pygame.mixer.music.set_volume(music_volume / 10)

def main():
    global high_score
    locked_positions = {}
    grid = create_grid(locked_positions)

    change_piece = False
    run = True
    current_piece = get_shape()
    next_piece = get_shape()
    clock = pygame.time.Clock()
    fall_time = 0

    BASE_FALL_SPEED = 0.5  # Base fall speed in seconds
    fall_speed = BASE_FALL_SPEED
    lines_cleared = 0  # Initialize lines cleared counter
    level = 1  # Initialize level

    paused = False  # Game paused state

    the_music_started = False  # To ensure music starts only once

    while run:
        grid = create_grid(locked_positions)
        fall_time += clock.get_rawtime()
        clock.tick()

        # Calculate current level based on lines cleared
        new_level = (lines_cleared // 10) + 1
        if new_level != level:
            level = new_level
            fall_speed *= 1.15  # Increase speed by 15% each level

        # Adjust fall speed
        current_fall_speed = fall_speed
        keys = pygame.key.get_pressed()

        if keys[pygame.K_DOWN]:
            current_fall_speed = 0.05  # Fast fall when down key is held

        if fall_time / 1000 >= current_fall_speed:
            fall_time = 0
            current_piece.y += 1
            if not valid_space(current_piece, grid) and current_piece.y > 0:
                current_piece.y -= 1
                change_piece = True
                MOVE_SOUND.play()

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
                pygame.display.quit()
                quit()

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    current_piece.x -= 1
                    if not valid_space(current_piece, grid):
                        current_piece.x += 1
                    else:
                        MOVE_SOUND.play()
                elif event.key == pygame.K_RIGHT:
                    current_piece.x += 1
                    if not valid_space(current_piece, grid):
                        current_piece.x -= 1
                    else:
                        MOVE_SOUND.play()
                elif event.key == pygame.K_DOWN:
                    current_piece.y += 1
                    if not valid_space(current_piece, grid):
                        current_piece.y -= 1
                elif event.key == pygame.K_UP:
                    current_piece.rotation = (current_piece.rotation + 1) % len(current_piece.shape)
                    if not valid_space(current_piece, grid):
                        current_piece.rotation = (current_piece.rotation - 1) % len(current_piece.shape)
                    else:
                        ROTATE_SOUND.play()
                elif event.key == pygame.K_SPACE:
                    paused = not paused  # Toggle pause

        if paused:
            pause_screen(win)
            continue  # Skip the rest of the loop to effectively pause

        shape_pos = convert_shape_format(current_piece)

        # Add piece to the grid for drawing
        for i in range(len(shape_pos)):
            x, y = shape_pos[i]
            if y > -1:
                if 0 <= x < GRID_WIDTH and 0 <= y < GRID_HEIGHT:
                    grid[y][x] = current_piece.color

        if change_piece:
            for pos in shape_pos:
                p = (pos[0], pos[1])
                if 0 <= p[0] < GRID_WIDTH and 0 <= p[1] < GRID_HEIGHT:
                    locked_positions[p] = current_piece.color
            current_piece = next_piece
            next_piece = get_shape()
            change_piece = False

            cleared = clear_rows(grid, locked_positions)
            lines_cleared += cleared  # Update lines cleared

        # Start background music once when the game starts
        if not the_music_started:
            play_background_music()
            the_music_started = True

        draw_window(win, grid, lines_cleared, level, high_score)  # Removed high_score from in-game display
        draw_next_shape(next_piece, win)
        pygame.display.update()

        if check_lost(locked_positions):
            GAME_OVER_SOUND.play()
            pygame.time.delay(500)
            run = False
            stop_background_music()
            update_high_score_if_needed(lines_cleared)

    game_over_screen(win, lines_cleared, high_score)

def update_high_score_if_needed(current_score):
    global high_score
    if current_score > high_score:
        high_score = current_score
        save_high_score(high_score)

def game_over_screen(surface, final_score, _):
    global high_score
    # Update high score if necessary
    if final_score > high_score:
        high_score = final_score
        save_high_score(high_score)

    pygame.mixer.music.stop()  # Ensure music is stopped on game over

    while True:
        surface.fill((0, 0, 0))
        draw_text_middle("YOU LOST!", 60, (255, 255, 255), surface, y_offset=-50)
        
        # Display final score
        font_small = pygame.font.SysFont('comicsans', 30)
        score_label = font_small.render(f'Your Score: {final_score}', 1, (255, 255, 255))
        surface.blit(score_label, ((SCREEN_WIDTH / 2) - (score_label.get_width() / 2), (SCREEN_HEIGHT / 2) - 10))
        
        # Prompt to return to menu
        prompt_label = font_small.render('Press Space to return to the menu.', 1, (255, 255, 255))
        surface.blit(prompt_label, ((SCREEN_WIDTH / 2) - (prompt_label.get_width() / 2), (SCREEN_HEIGHT / 2) + 30))
        
        pygame.display.update()
        
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    main_menu()  # Return to main menu

def pause_screen(surface):
    pause_font = pygame.font.SysFont('comicsans', 40, bold=True)
    pause_label = pause_font.render('Game Paused', 1, (255, 255, 255))
    prompt_font = pygame.font.SysFont('comicsans', 20)
    prompt_label = prompt_font.render('Press Space to Resume', 1, (255, 255, 255))
    
    surface.blit(pause_label, ((SCREEN_WIDTH / 2) - (pause_label.get_width() / 2), SCREEN_HEIGHT / 2 - 30))
    surface.blit(prompt_label, ((SCREEN_WIDTH / 2) - (prompt_label.get_width() / 2), SCREEN_HEIGHT / 2 + 10))
    pygame.display.update()

def main_menu():
    global high_score
    load_high_score()  # Ensure high_score is loaded before displaying menu
    run = True
    while run:
        win.fill((0, 0, 0))
        
        # Draw the "Tetris" title
        font_title = pygame.font.SysFont('comicsans', 60, bold=True)
        title_label = font_title.render('Tetris', 1, (255, 255, 255))
        win.blit(title_label, (SCREEN_WIDTH / 2 - title_label.get_width() / 2, 100))
        
        # Display High Score
        font_high = pygame.font.SysFont('comicsans', 30, bold=True)
        high_label = font_high.render(f'High Score: {high_score}', 1, (255, 255, 255))
        win.blit(high_label, (SCREEN_WIDTH / 2 - high_label.get_width() / 2, 200))
        
        # Display menu options
        font_options = pygame.font.SysFont('comicsans', 30)
        option1 = font_options.render('1: New Game', 1, (255, 255, 255))
        option2 = font_options.render('2: Options', 1, (255, 255, 255))
        option3 = font_options.render('3: Exit', 1, (255, 255, 255))
        
        win.blit(option1, (SCREEN_WIDTH / 2 - option1.get_width() / 2, 300))
        win.blit(option2, (SCREEN_WIDTH / 2 - option2.get_width() / 2, 350))
        win.blit(option3, (SCREEN_WIDTH / 2 - option3.get_width() / 2, 400))
        
        pygame.display.update()
        
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
                pygame.quit()
                quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_1:
                    main()  # Start new game
                elif event.key == pygame.K_2:
                    options_menu()  # Open options menu
                elif event.key == pygame.K_3:
                    run = False
                    pygame.quit()
                    quit()
    pygame.quit()

if __name__ == '__main__':
    main_menu()