<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Infinite Craft Clone</title>
    <style>
        /* ----------------------------
           Reset and Basic Styles
        ----------------------------- */
        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
        }
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            display: flex;
            height: 100vh;
            background-color: #121212;
            color: #e0e0e0;
            overflow: hidden;
            position: relative;
        }

        /* ----------------------------
           Sidebar Styles (Moved to Right)
        ----------------------------- */
        #sidebar {
            width: 320px;
            background-color: #1e1e1e;
            padding: 20px;
            overflow-y: auto;
            border-left: 1px solid #333;
            transition: width 0.3s;
            display: flex;
            flex-direction: column;
            gap: 15px;
        }
        #sidebar h2 {
            color: #ffffff;
            text-align: center;
            font-size: 1.8em;
            letter-spacing: 1px;
            margin-bottom: 10px;
        }
        #search-bar {
            padding: 10px 15px;
            border: 2px solid #333;
            border-radius: 8px;
            font-size: 1em;
            outline: none;
            background-color: #2c2c2c;
            color: #ffffff;
            transition: border-color 0.3s;
        }
        #search-bar::placeholder {
            color: #b0b0b0;
        }
        #search-bar:focus {
            border-color: #6200ea;
        }
        #discoveries-counter {
            color: #b0b0b0;
            font-size: 1em;
            text-align: center;
            margin-top: 10px;
        }
        #elements-container {
            display: grid;
            grid-template-columns: repeat(2, 1fr);
            grid-auto-rows: auto;
            gap: 10px;
        }
        .element {
            background-color: #2d2d2d;
            color: #e0e0e0;
            padding: 12px 20px;
            border-radius: 8px;
            cursor: grab;
            text-align: center;
            transition: background-color 0.3s, transform 0.2s, box-shadow 0.3s, opacity 0.3s;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 1.1em;
            box-shadow: 0 4px 6px rgba(0,0,0,0.3);
            opacity: 1;
            animation: fadeIn 0.5s ease forwards;
        }
        .element.hidden {
            display: none;
        }
        .element:hover {
            background-color: #6200ea;
            transform: translateY(-2px);
            box-shadow: 0 6px 10px rgba(0,0,0,0.4);
        }
        .element.newly-discovered {
            animation: highlight 2s ease;
        }
        @keyframes highlight {
            0%, 100% {
                box-shadow: 0 0 10px #03dac5;
            }
            50% {
                box-shadow: 0 0 20px #03dac5;
            }
        }
        @keyframes fadeIn {
            from { opacity: 0; transform: scale(0.95); }
            to { opacity: 1; transform: scale(1); }
        }

        /* ----------------------------
           Game Area Styles
        ----------------------------- */
        #game-area {
            flex: 1;
            position: relative;
            background-color: #121212;
            display: flex;
            align-items: center;
            justify-content: center;
            overflow: hidden;
            padding: 20px;
            transition: background-color 0.3s;
        }
        #canvas {
            width: 100%;
            height: 100%;
            background: radial-gradient(circle at center, #1e1e1e, #2c2c2c);
            border: 2px solid #333;
            border-radius: 15px;
            position: relative;
            overflow: hidden;
            box-shadow: 0 8px 16px rgba(0,0,0,0.5);
            transition: background 0.5s ease;
            background-size: 400% 400%;
            animation: gradientAnimation 20s ease infinite;
        }

        @keyframes gradientAnimation {
            0% { background-position: 0% 50%; }
            50% { background-position: 100% 50%; }
            100% { background-position: 0% 50%; }
        }

        /* ----------------------------
           Draggable Item Styles
        ----------------------------- */
        .draggable {
            position: absolute;
            padding: 10px 15px;
            background-color: #6200ea;
            color: #ffffff;
            border-radius: 50px;
            cursor: grab;
            transition: transform 0.2s, opacity 0.2s, box-shadow 0.3s;
            user-select: none;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 1.2em;
            box-shadow: 0 4px 6px rgba(0,0,0,0.3);
            z-index: 1;
        }
        .draggable.dragging {
            opacity: 0.7;
            cursor: grabbing;
            transform: scale(1.05);
            box-shadow: 0 6px 10px rgba(0,0,0,0.4);
            z-index: 2;
        }

        /* ----------------------------
           Overlay for Canvas Interactions
        ----------------------------- */
        #canvas::after {
            content: '';
            position: absolute;
            width: 150%;
            height: 150%;
            top: -25%;
            left: -25%;
            background: rgba(255,255,255,0);
            pointer-events: none;
            transition: background 0.3s;
        }
        #canvas:hover::after {
            background: rgba(255,255,255, 0.05);
        }

        /* ----------------------------
           Result Modal Styles
        ----------------------------- */
        #result-modal {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: rgba(0, 0, 0, 0.8);
            display: flex;
            align-items: center;
            justify-content: center;
            visibility: hidden;
            opacity: 0;
            transition: opacity 0.3s, visibility 0.3s;
            z-index: 1000;
        }
        #result-content {
            background-color: #1e1e1e;
            padding: 30px 40px;
            border-radius: 15px;
            text-align: center;
            max-width: 400px;
            box-shadow: 0 10px 20px rgba(0,0,0,0.5);
            animation: popIn 0.3s ease-out;
        }
        @keyframes popIn {
            from { transform: scale(0.8); opacity: 0; }
            to { transform: scale(1); opacity: 1; }
        }
        #result-content h3 {
            margin-bottom: 20px;
            color: #bb86fc;
            font-size: 1.5em;
        }
        #result-content p {
            font-size: 1.3em;
            color: #e0e0e0;
            margin-bottom: 25px;
        }
        #close-modal {
            padding: 10px 20px;
            background-color: #03dac5;
            color: #1e1e1e;
            border: none;
            border-radius: 8px;
            cursor: pointer;
            transition: background-color 0.3s;
            font-size: 1em;
        }
        #close-modal:hover {
            background-color: #018786;
        }

        /* ----------------------------
           API Key Modal Styles
        ----------------------------- */
        #api-key-modal {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: rgba(0, 0, 0, 0.95);
            display: flex;
            align-items: center;
            justify-content: center;
            visibility: hidden;
            opacity: 0;
            transition: opacity 0.3s, visibility 0.3s;
            z-index: 2000;
        }
        #api-key-content {
            background-color: #1e1e1e;
            padding: 30px 40px;
            border-radius: 15px;
            text-align: center;
            max-width: 400px;
            box-shadow: 0 10px 20px rgba(0,0,0,0.5);
            animation: fadeIn 0.3s ease-out;
        }
        @keyframes fadeIn {
            from { opacity: 0; transform: translateY(-20px); }
            to { opacity: 1; transform: translateY(0); }
        }
        #api-key-content h3 {
            margin-bottom: 20px;
            color: #bb86fc;
            font-size: 1.5em;
        }
        #api-key-input {
            width: 100%;
            padding: 12px 15px;
            margin-bottom: 20px;
            border: 2px solid #333;
            border-radius: 8px;
            font-size: 1em;
            outline: none;
            background-color: #2c2c2c;
            color: #ffffff;
            transition: border-color 0.3s;
        }
        #api-key-input::placeholder {
            color: #b0b0b0;
        }
        #api-key-input:focus {
            border-color: #6200ea;
        }
        #save-api-key-btn {
            padding: 12px 25px;
            background-color: #bb86fc;
            color: #1e1e1e;
            border: none;
            border-radius: 8px;
            cursor: pointer;
            transition: background-color 0.3s;
            font-size: 1em;
        }
        #save-api-key-btn:hover {
            background-color: #9b59b6;
        }
        #api-key-warning {
            margin-top: 15px;
            font-size: 0.9em;
            color: #cf6679;
        }

        /* ----------------------------
           Responsive Design
        ----------------------------- */
        @media (max-width: 768px) {
            #sidebar {
                width: 280px;
            }
            .element {
                padding: 10px 15px;
                font-size: 1em;
            }
            #result-content, #api-key-content {
                padding: 20px 25px;
            }
            #result-content h3, #api-key-content h3 {
                font-size: 1.3em;
            }
            #result-content p {
                font-size: 1.1em;
            }
            #save-api-key-btn, #close-modal {
                padding: 10px 18px;
                font-size: 0.9em;
            }
        }

        @media (max-width: 480px) {
            #sidebar {
                width: 220px;
            }
            .element {
                padding: 8px 12px;
                font-size: 0.9em;
            }
            #canvas {
                border-radius: 10px;
            }
            #elements-container {
                grid-template-columns: repeat(2, 1fr);
            }
        }

    </style>
</head>
<body>

    <!-- Game Area -->
    <div id="game-area">
        <div id="canvas"></div>
    </div>

    <!-- Sidebar with Elements (Moved to Right) -->
    <div id="sidebar">
        <h2>Elements</h2>
        <input type="text" id="search-bar" placeholder="Search elements...">
        <div id="elements-container">
            <!-- Elements will be dynamically added here -->
        </div>
        <div id="discoveries-counter">Discoveries: 0</div>
    </div>

    <!-- Result Modal -->
    <div id="result-modal">
        <div id="result-content">
            <h3>New Item Created!</h3>
            <p id="result-text"></p>
            <button id="close-modal">Close</button>
        </div>
    </div>

    <!-- API Key Modal -->
    <div id="api-key-modal">
        <div id="api-key-content">
            <h3>Enter OpenAI API Key</h3>
            <input type="password" id="api-key-input" placeholder="sk-...">
            <button id="save-api-key-btn">Save API Key</button>
            <p id="api-key-warning">⚠️ Your API key will be stored in the browser's local storage. This is insecure.</p>
        </div>
    </div>

    <script>
        // ----------------------------
        // Predefined Elements with Emojis
        // ----------------------------
        const availableElements = [
            { name: 'Fire', emoji: '🔥' },
            { name: 'Water', emoji: '💧' },
            { name: 'Wind', emoji: '💨' },
            { name: 'Earth', emoji: '🌍' }
        ];

        let apiKey = '';
        let draggableId = 0; // Unique ID for each draggable item
        let discoveriesCount = 0; // Counter for discoveries

        // DOM Elements
        const sidebar = document.getElementById('sidebar');
        const elementsContainer = document.getElementById('elements-container');
        const searchBar = document.getElementById('search-bar');
        const discoveriesCounter = document.getElementById('discoveries-counter');
        const canvas = document.getElementById('canvas');
        const resultModal = document.getElementById('result-modal');
        const resultText = document.getElementById('result-text');
        const closeModalBtn = document.getElementById('close-modal');
        const apiKeyModal = document.getElementById('api-key-modal');
        const apiKeyInput = document.getElementById('api-key-input');
        const saveApiKeyBtn = document.getElementById('save-api-key-btn');

        // Initialize Application
        window.onload = () => {
            // Check if API key exists in localStorage
            const storedKey = localStorage.getItem('openai_api_key');
            if (storedKey) {
                apiKey = storedKey;
                loadElements();
            } else {
                showApiKeyModal();
            }

            // Event listeners for combining elements within the canvas
            canvas.addEventListener('dragover', (e) => e.preventDefault());
            canvas.addEventListener('drop', handleDropOnCanvas);

            // Event listener for searching elements
            searchBar.addEventListener('input', handleSearch);
        };

        // Show API Key Modal
        function showApiKeyModal() {
            apiKeyModal.style.visibility = 'visible';
            apiKeyModal.style.opacity = '1';
        }

        // Hide API Key Modal
        function hideApiKeyModal() {
            apiKeyModal.style.visibility = 'hidden';
            apiKeyModal.style.opacity = '0';
        }

        // Save API Key
        saveApiKeyBtn.addEventListener('click', () => {
            const key = apiKeyInput.value.trim();
            if (key.startsWith('sk-') && key.length > 20) { // Basic validation
                apiKey = key;
                localStorage.setItem('openai_api_key', apiKey);
                hideApiKeyModal();
                loadElements();
            } else {
                alert('Please enter a valid OpenAI API key.');
            }
        });

        // Load Elements into Sidebar
        function loadElements() {
            availableElements.forEach(element => {
                addElementToSidebar(element);
            });
        }

        // Adds an element to the sidebar
        function addElementToSidebar(element, isNew = false) {
            const elemDiv = document.createElement('div');
            elemDiv.classList.add('element');
            if (isNew) elemDiv.classList.add('newly-discovered');
            elemDiv.setAttribute('draggable', 'true');
            elemDiv.innerHTML = `<span style="margin-right:8px;">${element.emoji}</span>${element.name}`;
            elemDiv.addEventListener('dragstart', dragStart);
            elementsContainer.appendChild(elemDiv);

            if (isNew) {
                setTimeout(() => {
                    elemDiv.classList.remove('newly-discovered');
                }, 2000); // Remove animation class after animation duration
            }
        }

        // Drag Start Handler
        function dragStart(e) {
            const data = {
                name: e.target.textContent.trim(),
                emoji: e.target.querySelector('span') ? e.target.querySelector('span').textContent.trim() : ''
            };
            e.dataTransfer.setData('application/json', JSON.stringify(data));
            setTimeout(() => {
                e.target.classList.add('dragging');
            }, 0);
        }

        // Drag End Handler to remove dragging class
        document.addEventListener('dragend', (e) => {
            const elements = document.querySelectorAll('.dragging');
            elements.forEach(el => el.classList.remove('dragging'));
        });

        // Handle Drop on Canvas for Adding or Combining Elements
        async function handleDropOnCanvas(e) {
            e.preventDefault();
            const data = e.dataTransfer.getData('application/json');
            if (data) {
                const draggedItem = JSON.parse(data);
                const dropX = e.clientX - canvas.getBoundingClientRect().left;
                const dropY = e.clientY - canvas.getBoundingClientRect().top;

                // Find if there's an existing draggable under the drop position
                const elementsUnderDrop = document.elementsFromPoint(e.clientX, e.clientY);
                const target = elementsUnderDrop.find(el => el.classList && el.classList.contains('draggable') && el.parentElement === canvas);

                if (target) {
                    const targetData = JSON.parse(target.getAttribute('data-item'));
                    // Combine draggedItem and targetData
                    const elementsToCombine = [draggedItem, targetData];
                    const newItem = await combineElements(elementsToCombine);

                    if (newItem) {
                        // Parse the new item to extract emoji and name
                        const parsedItem = parseNewItem(newItem);

                        if (parsedItem) {
                            // Check if the item already exists
                            const exists = availableElements.some(el => el.name === parsedItem.name && el.emoji === parsedItem.emoji);

                            if (!exists) {
                                // Add new item to sidebar and elements list
                                addElementToSidebar(parsedItem, true);
                                availableElements.push(parsedItem);
                                discoveriesCount++;
                                updateDiscoveriesCounter();
                                // Show result modal
                                showResultModal(newItem);
                            }

                            // Remove the combined elements from canvas
                            canvas.removeChild(target);
                        }
                    }
                } else {
                    // Simply place the dragged item without combining
                    createDraggableElement(`${draggedItem.emoji} ${draggedItem.name}`, dropX, dropY);
                }
            }
        }

        // Handle Search Functionality
        function handleSearch(e) {
            const query = e.target.value.toLowerCase();
            const elements = document.querySelectorAll('.element');
            elements.forEach(el => {
                const name = el.textContent.trim().toLowerCase();
                if (name.includes(query)) {
                    el.classList.remove('hidden');
                } else {
                    el.classList.add('hidden');
                }
            });
        }

        // Create Draggable Element in Canvas
        function createDraggableElement(content, x, y) {
            const draggable = document.createElement('div');
            draggable.classList.add('draggable');
            draggable.innerHTML = content;
            draggable.style.left = `${x - 40}px`; // Adjust for centering
            draggable.style.top = `${y - 20}px`;
            draggable.setAttribute('draggable', 'true');
            draggable.setAttribute('id', `draggable-${draggableId++}`);
            draggable.setAttribute('data-item', JSON.stringify({
                name: content.split(' ').slice(1).join(' '),
                emoji: content.split(' ')[0]
            }));

            // Drag Event Listeners for Combining with Other Canvas Items
            draggable.addEventListener('dragstart', (event) => {
                event.dataTransfer.setData('text/plain', event.target.id);
                setTimeout(() => {
                    draggable.classList.add('dragging');
                }, 0);
            });

            draggable.addEventListener('dragend', (event) => {
                draggable.classList.remove('dragging');
                const rect = canvas.getBoundingClientRect();
                const newX = event.clientX - rect.left - 40;
                const newY = event.clientY - rect.top - 20;
                draggable.style.left = `${newX}px`;
                draggable.style.top = `${newY}px`;
            });

            canvas.appendChild(draggable);
        }

        // Close Result Modal
        closeModalBtn.addEventListener('click', () => {
            resultModal.style.visibility = 'hidden';
            resultModal.style.opacity = '0';
        });

        // Show Result Modal
        function showResultModal(newItem) {
            resultText.textContent = newItem;
            resultModal.style.visibility = 'visible';
            resultModal.style.opacity = '1';
        }

        // Parse New Item to Extract Emoji and Name
        function parseNewItem(newItem) {
            const regex = /^([\p{Emoji_Presentation}\p{Emoji}\uFE0F]+)\s+([\p{L}\s]+)$/u;
            const match = newItem.match(regex);
            if (match) {
                return {
                    name: match[2],
                    emoji: match[1]
                };
            } else {
                console.warn('Failed to parse new item:', newItem);
                return null;
            }
        }

        // Update Discoveries Counter
        function updateDiscoveriesCounter() {
            discoveriesCounter.textContent = `Discoveries: ${discoveriesCount}`;
        }

        // Attempt to Combine Elements by Calling OpenAI API
        async function combineElements(elements) {
            const elementNames = elements.map(el => el.name);
            const prompt = `Combine the following elements: ${elementNames.join(', ')}. What is the resulting item? Provide just the name of the new item with an appropriate emoji, e.g., "🪨 Boulder". Keep the result simple and logical.`;

            try {
                const response = await fetch('https://api.openai.com/v1/chat/completions', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                        'Authorization': `Bearer ${apiKey}`
                    },
                    body: JSON.stringify({
                        model: 'gpt-3.5-turbo',
                        messages: [
                            { role: 'system', content: 'You are an assistant that combines elements to create new items in a crafting system. Respond with only an emoji followed by the item name, e.g., "🪨 Boulder". Do not include any equations or additional text. Keep the result simple and logical.' },
                            { role: 'user', content: prompt }
                        ],
                        max_tokens: 15,
                        temperature: 0.3
                    })
                });

                if (!response.ok) {
                    const errorData = await response.json();
                    throw new Error(errorData.error.message || `API Error: ${response.status}`);
                }

                const data = await response.json();
                const newItem = data.choices[0].message.content.trim();

                // Enhanced Validation: Allow multiple emojis
                const emojiRegex = /^([\p{Emoji_Presentation}\p{Emoji}\uFE0F]+)\s+[\p{L}\s]+$/u;
                if (emojiRegex.test(newItem)) {
                    return newItem;
                    console.warn('Generated item failed regex validation:', newItem);
                    return null;
                }

            } catch (error) {
                console.error(error);
                alert(`Error: ${error.message}`);
                return null;
            }
        }

        // Enable Combining Existing Canvas Items by Dragging One Over Another
        canvas.addEventListener('drop', async (e) => {
            e.preventDefault();
            const draggedId = e.dataTransfer.getData('text/plain');
            const draggedElement = document.getElementById(draggedId);

            if (draggedElement) {
                const dropX = e.clientX - canvas.getBoundingClientRect().left;
                const dropY = e.clientY - canvas.getBoundingClientRect().top;

                // Find if there's an existing draggable under the drop position
                const elementsUnderDrop = document.elementsFromPoint(e.clientX, e.clientY);
                const target = elementsUnderDrop.find(el => el.classList && el.classList.contains('draggable') && el.parentElement === canvas && el.id !== draggedId);

                if (target) {
                    const targetData = JSON.parse(target.getAttribute('data-item'));
                    const draggedData = JSON.parse(draggedElement.getAttribute('data-item'));
                    // Combine draggedData and targetData
                    const elementsToCombine = [draggedData, targetData];
                    const newItem = await combineElements(elementsToCombine);

                    if (newItem) {
                        // Parse the new item to extract emoji and name
                        const parsedItem = parseNewItem(newItem);

                        if (parsedItem) {
                            // Check if the item already exists
                            const exists = availableElements.some(el => el.name === parsedItem.name && el.emoji === parsedItem.emoji);

                            if (!exists) {
                                // Add new item to sidebar and elements list
                                addElementToSidebar(parsedItem, true);
                                availableElements.push(parsedItem);
                                discoveriesCount++;
                                updateDiscoveriesCounter();
                                // Show result modal
                                showResultModal(newItem);
                            }

                            // Remove the combined elements from canvas
                            canvas.removeChild(target);
                            canvas.removeChild(draggedElement);
                        }
                    }
                }
            }
        });

    </script>
</body>
</html>

Keep this, just add the options menu, sound effects and toggle, and galaxy background not video or image from google.