<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    
    <meta name="viewport" content="
        width=device-width,
        initial-scale=1.0,
        maximum-scale=1.0,
        user-scalable=no,
        viewport-fit=cover">
        
    <link rel="shortcut icon"
        href="
        https://upload.wikimedia.org/wikipedia/commons/thumb/c/cf/UZ_road_sign_1.25.2.svg/960px-UZ_road_sign_1.25.2.svg.png"
        type="image/svg+xml">
        
    <title>404 not found</title>
    
    <style>
        /* ==========================================
           BASE LAYOUT & TYPOGRAPHY
           ========================================== */
        body {
            margin: 0;
            padding: 0;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100dvh;
            
            /* Background gradient outside the game container */
            background: linear-gradient(to bottom, #64b3f4, #c2e59c);
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            overflow: hidden;
            
            /* Prevents accidental text selection or zooming 
               while frantically tapping the screen */
            touch-action: none;
            -webkit-touch-callout: none;
            -webkit-user-select: none;
            user-select: none;
        }

        /* ==========================================
           GAME CONTAINER & CANVAS
           ========================================== */
        .game-container {
            position: relative;
            box-shadow: 0 10px 40px rgba(0, 0, 0, 0.6);
            overflow: hidden;
            
            /* Maintains a standard portrait aspect ratio */
            aspect-ratio: 360 / 640;
            width: 90vw;
            height: 90dvh;
            max-width: 90%;
            max-height: 90%;
            border-radius: 16px;
            container-type: inline-size;
        }

        /* Adjusts sizing for desktop monitors */
        @media (min-width: 600px) {
            .game-container {
                height: 95dvh;
                max-height: 95%;
                width: auto;
                border-radius: 16px;
            }
        }

        canvas {
            display: block;
            width: 100%;
            height: 100%;
            background: #70c5ce;
        }

        /* ==========================================
           USER INTERFACE (UI) OVERLAY
           ========================================== */
        /* Acts as a transparent layer sitting on top of the 
           HTML5 canvas to hold our HTML text and buttons */
        .ui-overlay {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            color: white;
            text-align: center;
            
            /* Allows clicks to pass through the overlay 
               and hit the canvas behind it */
            pointer-events: none;
            box-sizing: border-box;
            padding: 4cqw;
        }

        /* Groups the different UI screens */
        #startScreen, #gameOverScreen, #gameUI {
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            width: 100%;
        }

        .game-title {
            font-size: 13cqw;
            font-weight: 800;
            margin: 0 0 4cqw 0;
            text-shadow: 0 0.8cqw 2cqw rgba(0,0,0,0.6);
            line-height: 1.1;
        }

        .score-display {
            font-size: 16cqw;
            font-weight: bold;
            text-shadow: 0 0.6cqw 2cqw rgba(0, 0, 0, 0.5);
            margin-top: 2cqw;
        }

        .message {
            background: rgba(0, 0, 0, 0.75);
            padding: 4cqw 6cqw;
            border-radius: 3cqw;
            font-size: 6cqw;
            width: 85%;
            box-sizing: border-box;
            margin-bottom: 4cqw;
            box-shadow: 0 1cqw 3cqw rgba(0, 0, 0, 0.3);
            border: 2px solid rgba(255,255,255,0.1);
        }

        .instructions {
            background: rgba(0, 0, 0, 0.6);
            padding: 3.5cqw 5cqw;
            border-radius: 2cqw;
            font-size: 4.5cqw;
            margin-top: 3cqw;
            width: 85%;
            box-sizing: border-box;
        }

        button {
            background: #f1c40f;
            border: none;
            padding: 4cqw 10cqw;
            font-size: 6.5cqw;
            border-radius: 10cqw;
            cursor: pointer;
            font-weight: 900;
            color: #2c3e50;
            box-shadow: 0 1.5cqw 4cqw rgba(0, 0, 0, 0.4);
            transition: transform 0.1s;
            
            /* Re-enables clicking specifically for buttons */
            pointer-events: auto;
            margin-top: 2cqw;
        }

        /* Adds a slight physical "press" effect when clicked */
        button:active { 
            transform: scale(0.92);
        }

        /* ==========================================
           LEADERBOARD & HIGHSCORE CSS
           ========================================== */
        input[type="text"] {
            background: rgba(255, 255, 255, 0.95);
            border: 2px solid #2c3e50;
            padding: 2.5cqw 4cqw;
            border-radius: 2cqw;
            font-size: 5cqw;
            font-family: inherit;
            font-weight: bold;
            color: #2c3e50;
            text-align: center;
            width: 60%;
            margin-bottom: 3cqw;
            text-transform: uppercase;
            outline: none;
            
            /* Re-enables clicking and typing for the input box */
            pointer-events: auto;
            touch-action: manipulation;
        }

        input[type="text"]:focus {
            border-color: #f1c40f;
            box-shadow: 0 0 10px rgba(241, 196, 15, 0.5);
        }

        .leaderboard-row {
            display: flex;
            justify-content: space-between;
            margin-bottom: 1.5cqw;
            border-bottom: 1px solid rgba(255,255,255,0.2);
            padding-bottom: 1cqw;
        }

        /* Utility class to easily hide UI elements */
        .hidden { 
            display: none !important;
        }
    </style>
</head>

<body>
    <div class="game-container">
        <canvas id="gameCanvas" width="360" height="640"></canvas>
        
        <div class="ui-overlay">
            
            <div id="startScreen">
                <h1 class="game-title">404 error<br>page not found</h1>
                <div class="message">
                    Tap the screen or<br>
                    click the mouse or<br>
                    hit spacebar to<br>
                    "flap your wings"
                </div>
                <button id="startButton">START GAME</button>
                <div class="instructions">
                    Avoid the pipes and<br>
                    don't hit the ground!
                </div>
            </div>
            
            <div id="gameOverScreen" class="hidden">
                <div class="message" style="font-size: 8cqw;
                        font-weight:bold;
                        color: #ff4757;
                        margin-bottom: 2cqw;">
                        GAME OVER
                </div>
                <div class="score-display" style="margin-top: 0;
                        margin-bottom: 2cqw;">
                        Score: <span id="finalScore">0</span>
                </div>

                <div id="highscoreEntry" class="hidden" style="display: flex;
                        flex-direction: column;
                        align-items: center;
                        width: 100%;">
                    <div style="font-size: 5cqw;
                        margin-bottom: 2cqw;
                        color: #f1c40f;
                        font-weight: bold;
                        text-shadow: 0 2px 4px rgba(0,0,0,0.5);">
                        🎉 NEW HIGH SCORE 🏆
                    </div>
                    <input type="text" id="playerName" placeholder="YOUR NAME" maxlength="13">
                    <button id="saveScoreButton" style="font-size: 5cqw;
                        padding: 2.5cqw 8cqw;">
                        SAVE SCORE
                    </button>
                </div>

                <div id="leaderboard" class="instructions" style="margin-top: 2cqw;
                    font-size: 4.5cqw;">
                    <div style="font-weight: 900;
                        margin-bottom: 3cqw;                    
                        text-align: center;
                        color: #f1c40f;">
                        TOP 5 SCORES
                    </div>
                    <div id="leaderboardList" style="text-align: left;">
                    </div>
                </div>

                <button id="restartButton" style="margin-top: 3cqw;">
                    TRY AGAIN
                </button>
            </div>
            
            <div id="gameUI" class="hidden">
                <div class="score-display" id="score">0</div>
            </div>
        </div>
    </div>

    <script>
        // ==========================================
        // 1. DOM ELEMENT BINDINGS
        // ==========================================
        // Grabbing references to HTML elements so we can 
        // manipulate them via JavaScript later.
        const canvas = document.getElementById('gameCanvas');
        const ctx = canvas.getContext('2d');
        const startScreen = document.getElementById('startScreen');
        const gameOverScreen = document.getElementById('gameOverScreen');
        const gameUI = document.getElementById('gameUI');
        const scoreDisplay = document.getElementById('score');
        const finalScoreDisplay = document.getElementById('finalScore');
        const startButton = document.getElementById('startButton');
        const restartButton = document.getElementById('restartButton');

        // ==========================================
        // 2. GLOBAL GAME STATE & TRACKERS
        // ==========================================
        // Tracks the current menu/game phase.
        let gameState = 'start';

        // Current session score.
        let score = 0;

        // Array to hold {name, score} objects for the leaderboard.
        let highscores = [];


        // Time and Speed setup for smooth animations.
        let lastTime = 0;
        let pipeSpawnTimer = 0;

        // NEW: Party popper 🎉 
        let confettiParticles = [];
        
        // Target pixel distance between pipes. Ensures that when 
        // the game speeds up, the horizontal gap stays identical.
        const PIPE_DISTANCE = 220;

        // Starting speed in pixels per second.
        const BASE_SPEED = 120;

        // How much faster to go every 10 points.
        const SPEED_INCREMENT = 15;


        // ==========================================
        // 3. GAME ENTITIES (BIRD & PIPES)
        // ==========================================

        const bird = {
            // Position and dimensions
            x: 50,
            y: canvas.height / 2 - 10,
            width: 34,
            height: 24,
            
            // Physics variables tuned by the user
            gravity: 20,  
            velocity: 0,
            jump: -500,   

            // Renders the bird using basic Canvas shapes
            draw: function() {
                // Body (Yellow Circle)
                ctx.fillStyle = '#FFD700';
                ctx.beginPath();
                ctx.arc(this.x, this.y, 15, 0, Math.PI * 2);
                ctx.fill();

                // Eye (Black Dot)
                ctx.fillStyle = 'black';
                ctx.beginPath();
                ctx.arc(this.x + 8, this.y - 3, 4, 0, Math.PI * 2);
                ctx.fill();

                // Beak (Orange Triangle)
                ctx.fillStyle = '#FF8C00';
                ctx.beginPath();
                ctx.moveTo(this.x + 15, this.y);
                ctx.lineTo(this.x + 30, this.y);
                ctx.lineTo(this.x + 15, this.y + 8);
                ctx.fill();

                // Wing (Darker Orange Ellipse)
                ctx.fillStyle = '#FFA500';
                ctx.beginPath();
                ctx.ellipse(this.x - 5, this.y + 5, 10, 7, 0, 0, Math.PI * 2);
                ctx.fill();
            },

            // Applies physics to the bird's vertical position
            update: function(dt) {
                if (gameState === 'playing') {
                    // Apply gravity over time
                    this.velocity += this.gravity * dt * 60;

                    // Move the bird by the current velocity
                    this.y += this.velocity * dt;

                    // Floor collision check
                    if (this.y + this.height/2 >= canvas.height - groundHeight) {
                        this.y = canvas.height - groundHeight - this.height/2;
                        if (gameState === 'playing') gameOver();
                    }

                    // Ceiling collision check
                    if (this.y - this.height/2 <= 0) {
                        this.y = this.height/2;
                        // Hitting the ceiling stops upward momentum
                        this.velocity = 0;
                    }
                }
            },

            // Triggers a jump by applying negative velocity
            flap: function() { 
                this.velocity = this.jump;
            },

            // Resets bird position for a new game
            reset: function() {
                this.y = canvas.height / 2 - 10;
                this.velocity = 0;
            }
        };

        const pipes = {
            // Array to store active pipes currently on screen
            position: [],
            // Vertical gap between the top and bottom pipe
            gap: 180,
            // Defines how high the top pipe can randomly spawn
            maxYPos: -150,
            // Current horizontal speed (dx)
            dx: BASE_SPEED, 

            // Renders all active pipes in the array
            draw: function() {
                for (let i = 0; i < this.position.length; i++) {
                    let p = this.position[i];

                    // Draw Top Pipe
                    ctx.fillStyle = '#2ECC71';
                    ctx.fillRect(p.x, p.y, p.width, p.height);

                    // Draw Top Pipe Cap
                    ctx.fillStyle = '#27AE60';
                    ctx.fillRect(p.x - 3, p.y + p.height - 20, p.width + 6, 20);

                    // Draw Bottom Pipe
                    ctx.fillStyle = '#2ECC71';
                    ctx.fillRect(p.x, p.y + p.height + this.gap, p.width, canvas.height);

                    // Draw Bottom Pipe Cap
                    ctx.fillStyle = '#27AE60';
                    ctx.fillRect(p.x - 3, p.y + p.height + this.gap, p.width + 6, 20);
                }
            },

            // Handles spawning, moving, scoring, and pipe collision
            update: function(dt) {
                if (gameState !== 'playing') return;

                // Advance the timer by delta time
                pipeSpawnTimer += dt;
                
                // Calculate time required to travel the target distance 
                // at the current speed, keeping gaps consistent.
                let currentSpawnInterval = PIPE_DISTANCE / this.dx;

                // Spawn a new pipe if enough time has passed
                if (pipeSpawnTimer >= currentSpawnInterval) {
                    this.position.push({
                        x: canvas.width,
                        y: this.maxYPos * (Math.random() + 1),
                        width: 60,
                        height: 300
                    });
                    // Reset timer after spawning
                    pipeSpawnTimer = 0;
                }

                // Update positions and check collisions
                for (let i = 0; i < this.position.length; i++) {
                    let p = this.position[i];

                    // Move pipe to the left
                    p.x -= this.dx * dt;

                    // If pipe moves entirely off-screen to the left:
                    // Remove it, add a point, and check for speed up.
                    if (p.x + p.width <= 0) {
                        this.position.splice(i, 1);
                        score++;
                        scoreDisplay.innerHTML = score;
                        
                        // Increase difficulty speed every 10 points
                        if (score > 0 && score % 10 === 0) { 
                            this.dx += SPEED_INCREMENT;
                        }
                        // Move to the next pipe in the loop
                        continue;
                    }

                    // COLLISION LOGIC
                    // Check collision with the TOP pipe
                    if (
                        bird.x + bird.width/2 > p.x &&
                        bird.x - bird.width/2 < p.x + p.width &&
                        bird.y - bird.height/2 < p.y + p.height
                    ) {
                        gameOver();
                    }
                    // Check collision with the BOTTOM pipe
                    if (
                        bird.x + bird.width/2 > p.x &&
                        bird.x - bird.width/2 < p.x + p.width &&
                        bird.y + bird.height/2 > p.y + p.height + this.gap
                    ) {
                        gameOver();
                    }
                }
            },

            // Clears pipes and resets speed for a new game
            reset: function() {
                this.position = [];
                this.dx = BASE_SPEED;
                pipeSpawnTimer = 0;
            }
        };

        // ==========================================
        // 4. ENVIRONMENT RENDERING
        // ==========================================
        const groundHeight = 80;

        function drawGround() {
            // Main ground color
            ctx.fillStyle = '#DAA520';
            ctx.fillRect(0, canvas.height - groundHeight, canvas.width, groundHeight);
            
            // Green grass line on top of the ground
            ctx.fillStyle = '#2ECC71';
            ctx.fillRect(0, canvas.height - groundHeight, canvas.width, 20);
            
            // Small brown decorative dashes across the ground
            ctx.fillStyle = '#8B4513';
            for (let i = 0; i < canvas.width; i += 30) {
                ctx.fillRect(i, canvas.height - groundHeight + 20, 15, 10);
            }
        }

        function drawBackground() {
            // Create a sky gradient from top to bottom
            const skyGradient = ctx.createLinearGradient(0, 0, 0, canvas.height);
            skyGradient.addColorStop(0, '#70c5ce');
            skyGradient.addColorStop(1, '#e0f7fa');
            
            // Fill background with gradient
            ctx.fillStyle = skyGradient;
            ctx.fillRect(0, 0, canvas.width, canvas.height);

            // Draw decorative clouds using overlapping arcs
            ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';
            
            // Cloud 1
            ctx.beginPath();
            ctx.arc(100, 80, 30, 0, Math.PI * 2);
            ctx.arc(130, 70, 35, 0, Math.PI * 2);
            ctx.arc(160, 80, 25, 0, Math.PI * 2);
            ctx.fill();
            
            // Cloud 2
            ctx.beginPath();
            ctx.arc(300, 120, 30, 0, Math.PI * 2);
            ctx.arc(330, 110, 35, 0, Math.PI * 2);
            ctx.arc(360, 120, 25, 0, Math.PI * 2);
            ctx.fill();
        }

        // ==========================================
        // 5. HIGHSCORE & LEADERBOARD LOGIC
        // ==========================================

        // Iterates through the highscores array and updates the DOM
        function renderLeaderboard() {
            const list = document.getElementById('leaderboardList');
            
            // Display empty state if no scores exist
            if (highscores.length === 0) {
                list.innerHTML = "<div style='text-align:center;'>No scores yet!</div>";
                return;
            }
            
            // Map the array into HTML strings for display
            list.innerHTML = highscores.map((entry, i) => 
                `<div class="leaderboard-row">
                    <span>${i + 1}. ${entry.name}</span>
                    <span style="color: #f1c40f; font-weight: bold;">${entry.score}</span>
                </div>`
            ).join('');
        }

        // Handles saving a new highscore when the user clicks submit
        document.getElementById('saveScoreButton').addEventListener('click', () => {
            const nameInput = document.getElementById('playerName');
            
            // Get value, trim spaces, make uppercase. 
            // Fallback to 'ANONYMOUS' if left empty.
            const name = nameInput.value.trim().toUpperCase() || 'ANONYMOUS';
            
            // Push the new score object into the array
            highscores.push({ name, score });
            
            // Sort the array in descending order based on score
            highscores.sort((a, b) => b.score - a.score);
            
            // Enforce a maximum of 5 entries in the leaderboard
            if (highscores.length > 5) {
                highscores.pop();
            }
            
            // Hide the input form and show the try again button
            document.getElementById('highscoreEntry').classList.add('hidden');
            document.getElementById('restartButton').classList.remove('hidden');
            
            // Clear the input box for the next session
            nameInput.value = '';
            
            // Re-render the visual list
            renderLeaderboard();
        });

        // ==========================================
        // 6. GAME FLOW CONTROLS
        // ==========================================

        // Triggers the end sequence when the bird crashes
        function gameOver() {
            gameState = 'gameover';
            finalScoreDisplay.innerHTML = score;
            
            // Check if the current score qualifies for the top 5
            const isHighScore = score > 0 && 
                (highscores.length < 5 || score > highscores[highscores.length - 1].score);
            
            if (isHighScore) {
                spawnConfetti();
                // Show input block, force user to save before restarting
                document.getElementById('highscoreEntry').classList.remove('hidden');
                document.getElementById('restartButton').classList.add('hidden');
            } else {
                // Skip input block, just show standard restart button
                document.getElementById('highscoreEntry').classList.add('hidden');
                document.getElementById('restartButton').classList.remove('hidden');
            }

            // Ensure leaderboard is updated visually
            renderLeaderboard();
            
            // Switch UI screens
            gameOverScreen.classList.remove('hidden');
            gameUI.classList.add('hidden');
        }

        // Resets variables to start a fresh run
        function resetGame() {
            score = 0;
            bird.reset();
            pipes.reset();
            scoreDisplay.innerHTML = score;
        }

        // Begins the active game loop
        function startGame() {
            gameState = 'playing';
            
            // Hide menus, show in-game overlay
            startScreen.classList.add('hidden');
            gameOverScreen.classList.add('hidden');
            gameUI.classList.remove('hidden');
            
            resetGame();
        }

        // Function to create the confetti particles
        function spawnConfetti() {
            for (let i = 0; i < 150; i++) {
                confettiParticles.push({
                    x: Math.random() * canvas.width,
                    y: -10, // Start just above the screen
                    vx: (Math.random() - 0.5) * 4, // Horizontal drift
                    vy: Math.random() * 3 + 2,     // Speed falling
                    rotation: Math.random() * Math.PI * 2, // Starting angle
                    rotationSpeed: (Math.random() - 0.5) * 0.2, // How fast it spins
                    color: `hsl(${Math.random() * 360}, 100%, 50%)`,
                    life: 200 // Lasts a bit longer
                });
            }
        }

        // Function to update and draw confetti particles
        function updateAndDrawConfetti() {
            confettiParticles.forEach((p, i) => {
                p.x += p.vx;
                p.y += p.vy;
                p.rotation += p.rotationSpeed; // Update the angle
                p.life--;

                ctx.save(); // Save the current canvas state
        
                // Move to the particle's position and rotate
                ctx.translate(p.x, p.y);
                ctx.rotate(p.rotation);
                
                // Draw the Rhomboid centered at 0,0
                ctx.fillStyle = p.color;
                ctx.beginPath();
                const w = 6;  // Width
                const h = 10; // Height
                ctx.moveTo(0, -h / 2); // Top
                ctx.lineTo(w / 2, 0);  // Right
                ctx.lineTo(0, h / 2);  // Bottom
                ctx.lineTo(-w / 2, 0); // Left
                ctx.closePath();
                ctx.fill();

                ctx.restore(); // Restore state so the rest of the game draws normally

                if (p.life <= 0) confettiParticles.splice(i, 1);
            });
        }

        // ==========================================
        // 7. CORE RENDER & UPDATE LOOP
        // ==========================================

        // Master draw function that executes in visual order (back to front)
        function draw() {
            drawBackground();
            pipes.draw();
            drawGround();
            bird.draw();
            // Draw confetti on top of everything
            updateAndDrawConfetti();
        }

        // Master update function that processes physics
        function update(dt) {
            bird.update(dt);
            pipes.update(dt);
        }

        // The main game engine loop triggered by requestAnimationFrame
        function loop(timestamp) {
            // Calculate delta time (dt) in seconds.
            // This ensures smooth movement regardless of framerate.
            let dt = (timestamp - lastTime) / 1000;
            lastTime = timestamp;
            
            // Cap delta time to prevent physics glitches if the tab is backgrounded
            if (dt > 0.1) dt = 0.1;

            update(dt);
            draw();

            // Recursively call the loop for the next frame
            requestAnimationFrame(loop);
        }

        // ==========================================
        // 8. INPUT LISTENERS
        // ==========================================

        // Wrapper function to process bird flapping
        function flapBird() {
            if (gameState === 'playing') {
                bird.flap();
            }
        }

        // Touchscreen input processing
        canvas.addEventListener('touchstart', function(e) {
            // Only prevent default zooming behavior during active gameplay.
            // This allows the highscore form typing to work normally.
            if (gameState === 'playing') {
                e.preventDefault();
                flapBird();
            }
        }, { passive: false });

        // Mouse click input processing
        canvas.addEventListener('mousedown', flapBird);
        
        // Keyboard spacebar input processing
        document.addEventListener('keydown', function(e) {
            if (e.code === 'Space') {
                // Prevent jumping if the user is currently typing their name
                if (document.activeElement.id !== 'playerName') {
                    flapBird();
                    e.preventDefault();
                }
            }
        });

        // UI button bindings
        startButton.addEventListener('click', startGame);
        restartButton.addEventListener('click', startGame);

        // Prevents double-tap zooming on iOS devices during active play
        let lastTouchEnd = 0;
        document.addEventListener('touchend', function(e) {
            if (gameState === 'playing') {
                const now = (new Date()).getTime();
                if (now - lastTouchEnd <= 300) {
                    e.preventDefault();
                }
                lastTouchEnd = now;
            }
        }, { passive: false });

        // Initializes the game loop upon loading the script
        requestAnimationFrame((timestamp) => {
            lastTime = timestamp;
            requestAnimationFrame(loop);
        });
    </script>
</body>
</html>
