Implement 3D Snake with HTML + JS + CSS. The entire code should be written in a single HTML block with embedded JS and CSS. Don't use any remote assets. After opening the html, user will need to hit space to start / restart the game, the snake will randomly go in one direction at the start and use "wasd" to control the direction of the snake. The game will take place on the surface of a cube the snake will automatically curl around the sides of the cube when it reaches the edge and the cube will always be showing the face with the head of the snake on it. the cube will be see through / transparent so that we can always see what side the apples are on no matter where they spawn. Make it pretty and the background large. 
current issues: snake is trapped on a single face it can move around freely on that face which is nice but when it gets to some of the edges it just stops as if running against a wall. sometimes it can travel to an upper face but once it gets there it just freezes in place being uncontrollable. everything else works great. 
<!DOCTYPE html>
<html>
<head>
    <title>3D Snake Game on Cube Surface</title>
    <style>
        body {
            margin: 0;
            overflow: hidden;
            background: radial-gradient(circle at center, #000428, #004e92);
        }

        #game-container {
            perspective: 1000px;
            width: 100vw;
            height: 100vh;
            position: relative;
        }

        #cube {
            position: absolute;
            top: 50%;
            left: 50%;
            width: 300px;
            height: 300px;
            transform-style: preserve-3d;
            transform: translate(-50%, -50%) rotateX(-20deg) rotateY(45deg);
            transition: transform 0.5s ease-out;
        }

        .face {
            position: absolute;
            width: 300px;
            height: 300px;
            background: rgba(255, 255, 255, 0.1);
            border: 1px solid rgba(255, 255, 255, 0.2);
            box-sizing: border-box;
        }

        /* Position each face */
        #face-0 { /* Front */
            transform: rotateY(0deg) translateZ(150px);
        }
        #face-1 { /* Back */
            transform: rotateY(180deg) translateZ(150px);
        }
        #face-2 { /* Right */
            transform: rotateY(90deg) translateZ(150px);
        }
        #face-3 { /* Left */
            transform: rotateY(-90deg) translateZ(150px);
        }
        #face-4 { /* Top */
            transform: rotateX(90deg) translateZ(150px);
        }
        #face-5 { /* Bottom */
            transform: rotateX(-90deg) translateZ(150px);
        }

        /* Snake and apple cells */
        .cell {
            position: absolute;
            width: 30px; /* Assuming grid size 10x10 */
            height: 30px;
            box-sizing: border-box;
        }

        .snake {
            background: limegreen;
        }

        .apple {
            background: red;
        }

        /* Additional styles */
        #message {
            position: absolute;
            top: 20px;
            width: 100%;
            text-align: center;
            color: white;
            font-family: Arial, sans-serif;
            font-size: 24px;
        }

    </style>
</head>
<body>
    <div id="game-container">
        <div id="cube">
            <div class="face" id="face-0"></div>
            <div class="face" id="face-1"></div>
            <div class="face" id="face-2"></div>
            <div class="face" id="face-3"></div>
            <div class="face" id="face-4"></div>
            <div class="face" id="face-5"></div>
        </div>
        <div id="message">Press SPACE to start the game</div>
    </div>
    <script>
        (function() {
            const gridSize = 10; // 10x10 grid on each face
            const cellSize = 30; // Must match CSS
            const faces = [0,1,2,3,4,5];
            const cube = document.getElementById('cube');
            const faceElements = faces.map(faceIndex => document.getElementById('face-' + faceIndex));

            let snake = [];
            let direction = null;
            let apple = null;
            let gameInterval = null;
            let isGameOver = false;
            let isGameStarted = false;
            const messageElement = document.getElementById('message');

            const faceAdjacency = {
                0: { // Front
                    up: {face:4, x:'x', y: gridSize - 1 - 'x'},
                    down: {face:5, x:'x', y:'x'},
                    left: {face:3, x: gridSize - 1, y:'y'},
                    right: {face:2, x: 0, y:'y'}
                },
                1: { // Back
                    up: {face:4, x: gridSize - 1 - 'x', y: 0},
                    down: {face:5, x: gridSize - 1 - 'x', y: gridSize - 1},
                    left: {face:2, x: gridSize - 1, y: 'y'},
                    right: {face:3, x: 0, y: 'y'}
                },
                2: { // Right
                    up: {face:4, x: 'y', y: 'x'},
                    down: {face:5, x: gridSize - 1 - 'y', y: 'x'},
                    left: {face:0, x: gridSize - 1, y: 'y'},
                    right: {face:1, x: 0, y: 'y'}
                },
                3: { // Left
                    up: {face:4, x: gridSize - 1 - 'y', y: gridSize - 1 - 'x'},
                    down: {face:5, x: 'y', y: gridSize - 1 - 'x'},
                    left: {face:1, x: gridSize - 1, y: 'y'},
                    right: {face:0, x: 0, y: 'y'}
                },
                4: { // Top
                    up: {face:1, x: 'x', y: 0},
                    down: {face:0, x: 'x', y: 0},
                    left: {face:3, x:'x', y:0},
                    right: {face:2, x: 'x', y: 0}
                },
                5: { // Bottom
                    up: {face:0, x: 'x', y: gridSize - 1},
                    down: {face:1, x: 'x', y: gridSize -1},
                    left: {face:3, x:'x', y: gridSize - 1},
                    right: {face:2, x: 'x', y: gridSize -1}
                }
            };

            function initGame() {
                // Clear previous game
                snake.forEach(segment => {
                    removeCell(segment);
                });
                if (apple) removeCell(apple);

                snake = [];
                direction = null;
                isGameOver = false;
                isGameStarted = false;
                messageElement.textContent = "Press SPACE to start the game";

                // Initialize snake starting position
                const startingFace = Math.floor(Math.random() * 6);
                const startingX = Math.floor(gridSize / 2);
                const startingY = Math.floor(gridSize / 2);
                direction = getRandomDirection();

                snake.push({face: startingFace, x: startingX, y: startingY});

                drawCell(snake[0], 'snake');

                spawnApple();
            }

            function getRandomDirection() {
                const dirs = ['up', 'down', 'left', 'right'];
                return dirs[Math.floor(Math.random() * dirs.length)];
            }

            function spawnApple() {
                let validCell = false;
                while (!validCell) {
                    const face = Math.floor(Math.random() * 6);
                    const x = Math.floor(Math.random() * gridSize);
                    const y = Math.floor(Math.random() * gridSize);
                    // Check if apple is on snake
                    if (!snake.some(segment => segment.face === face && segment.x === x && segment.y === y)) {
                        apple = {face, x, y};
                        validCell = true;
                    }
                }
                drawCell(apple, 'apple');
            }

            function drawCell(cell, className) {
                const cellDiv = document.createElement('div');
                cellDiv.classList.add('cell', className);
                cellDiv.style.left = (cell.x * cellSize) + 'px';
                cellDiv.style.top = (cell.y * cellSize) + 'px';
                faceElements[cell.face].appendChild(cellDiv);
                cell.element = cellDiv;
            }

            function removeCell(cell) {
                if (cell.element && cell.element.parentNode) {
                    cell.element.parentNode.removeChild(cell.element);
                    cell.element = null;
                }
            }

            function gameLoop() {
                if (isGameOver) return;

                // Calculate new head position
                const head = snake[0];
                let newHead = {face: head.face, x: head.x, y: head.y};

                switch (direction) {
                    case 'up':
                        newHead.y -=1;
                        break;
                    case 'down':
                        newHead.y +=1;
                        break;
                    case 'left':
                        newHead.x -=1;
                        break;
                    case 'right':
                        newHead.x +=1;
                        break;
                    default:
                        return; // No movement if direction is null
                }

                if (newHead.x < 0 || newHead.x >= gridSize || newHead.y < 0 || newHead.y >= gridSize) {
                    // Need to move to adjacent face
                    const adjacency = faceAdjacency[newHead.face][direction];
                    const adjFace = adjacency.face;
                    let adjX = adjacency.x;
                    let adjY = adjacency.y;

                    adjX = (typeof adjX === 'number') ? adjX : eval(adjX.replace(/'x'/g, head.x).replace(/'y'/g, head.y));
                    adjY = (typeof adjY === 'number') ? adjY : eval(adjY.replace(/'x'/g, head.x).replace(/'y'/g, head.y));

                    newHead.face = adjFace;
                    newHead.x = adjX;
                    newHead.y = adjY;
                }

                // Check collision with self
                if (snake.some(segment => segment.face === newHead.face && segment.x === newHead.x && segment.y === newHead.y)) {
                    gameOver();
                    return;
                }

                // Insert new head
                snake.unshift(newHead);
                drawCell(newHead, 'snake');

                // Check if apple is eaten
                if (apple.face === newHead.face && apple.x === newHead.x && apple.y === newHead.y) {
                    removeCell(apple);
                    spawnApple();
                } else {
                    // Remove tail
                    const tail = snake.pop();
                    removeCell(tail);
                }

                // Rotate cube to show the face with snake's head
                rotateCubeToFace(newHead.face);
            }

            function rotateCubeToFace(face){
                // Reset transform
                cube.style.transform = `translate(-50%, -50%)`;

                // Apply rotation
                let rotationX = 0;
                let rotationY = 0;
                switch(face){
                    case 0: // Front
                        rotationY = 0;
                        break;
                    case 1: // Back
                        rotationY = 180;
                        break;
                    case 2: // Right
                        rotationY = -90;
                        break;
                    case 3: // Left
                        rotationY = 90;
                        break;
                    case 4: // Top
                        rotationX = -90;
                        break;
                    case 5: // Bottom
                        rotationX = 90;
                        break;
                }
                cube.style.transform += ` rotateX(${rotationX}deg) rotateY(${rotationY}deg)`;
            }

            function gameOver() {
                isGameOver = true;
                clearInterval(gameInterval);
                messageElement.textContent = "Game Over! Press SPACE to restart";
            }

            // Handle key input
            document.addEventListener('keydown', function(e) {
                if (isGameOver && e.code === 'Space') {
                    initGame();
                    isGameStarted = true;
                    messageElement.textContent = "";
                    gameInterval = setInterval(gameLoop, 300);
                }

                if (!isGameStarted && e.code === 'Space') {
                    isGameStarted = true;
                    messageElement.textContent = "";
                    gameInterval = setInterval(gameLoop, 300);
                }

                if (e.key === 'w' || e.key === 'ArrowUp') {
                    if (direction !== 'down') direction = 'up';
                } else if (e.key === 's' || e.key === 'ArrowDown') {
                    if (direction !== 'up') direction = 'down';
                } else if (e.key === 'a' || e.key === 'ArrowLeft') {
                    if (direction !== 'right') direction = 'left';
                } else if (e.key === 'd' || e.key === 'ArrowRight') {
                    if (direction !== 'left') direction = 'right';
                }
            });

            // Start the game
            initGame();

        })();
    </script>
</body>
</html>