Interactive Classroom Seating Game

This prompt describes a single, all-in-one HTML page for teachers. It functions as an interactive tool to create, save, and load classroom layouts, add student names and photos, and play a game to memorize them.

EducationCode

Prompt

Create a single, complete HTML page that serves as an interactive tool for teachers to create a classroom floor plan and learn student names. The page should contain all HTML, CSS, and JavaScript in a single file.

Tool Goal:
A teacher should be able to build a floor plan, assign names and photos to tables, save this arrangement as a file, and play a game to practice the names.

### General Structure and Style

Layout: The interface consists of a top control panel and a large "classroom" area below.

Styling: Use the "Poppins" font from Google Fonts and Font Awesome for all icons. The style should be modern and clean, with a color palette of blue (primary), orange/yellow (accent), and green (success). Use soft shadows for depth.

Help Sidebar: There is a help button with an info icon. Clicking this button causes a sidebar with instructions to slide in from the left side of the screen. Clicking again hides the sidebar.

### Visual Components (UI)

Control panel (top):
Button to show/hide the help sidebar.
Buttons to add elements: 'Student desk' (<i class="fa-solid fa-user-graduate"></i>), 'Teacher desk' (<i class="fa-solid fa-chalkboard-user"></i>), and 'Blackboard' (<i class="fa-solid fa-person-chalkboard"></i>).
A 'Remove mode' button (<i class="fa-solid fa-eraser"></i>).
A dropdown menu with standard layouts: 'Bus layout', 'Groups', 'U-shape'.

File manager:
A 'Download' button (<i class="fa-solid fa-download"></i>) to save the floor plan as a file. An 'Upload' button (<i class="fa-solid fa-upload"></i>) to load a saved file.
A 'Clear' button (<i class="fa-solid fa-trash"></i>).
A 'Start Game' button.
A score counter in the top right corner.

Classroom Elements:
Student Desk: A simple rectangular desk without a chair.

Teacher Desk: A larger, slightly darker desk without a chair.

Blackboard: A thin, white rectangle with a dark border.

### Functionality in Setup Mode (default)

Add & Drag: Users can click the buttons to add elements. All elements in the classroom should be draggable.

Select & Remove:
A single click on an element selects it and gives it a clear blue border.
Once an element is selected, it can be removed with the 'Delete' or 'Backspace' key. The 'Delete Mode' button activates a mode in which clicking any element immediately deletes it.

Adding Names: Double-clicking a student table makes its name editable. If no name has been created yet, a pencil icon should appear in the center of the table.
Adding Photos: When the user hovers the mouse over a student table, a camera icon appears. Clicking this opens a dialog box to select an image file. The photo is resized and saved as a data URI, and appears as the table's background.

Default Layouts:
Choosing a layout from the dropdown menu should replace the current floor plan (after confirmation).
The 'Bus Layout' must consist exactly of a board at the top, a teacher's desk on the left, and 30 student tables in three columns of pairs (table...table), five rows deep.
The tool starts with this bus layout by default.

Download & Upload:
The 'Download' button should save the complete state of the classroom (positions, names, and photos as data URIs) to a .json file that the user can download.
The 'Upload' button should open a dialog box where the user can select this .json file. After selection, the floor plan will be fully restored.

### Functionality in Game Mode

Start: The 'Start Game' button starts the mode. All named tables flip over with a 3D flip effect. The back shows the student's photo, or a question mark if there is no photo. All editing buttons are disabled.

Play:
Clicking on a flipped table opens a custom pop-up (modal) in the center of the screen, not a browser prompt.
The modal asks "Who sits here?" and has an input field and two buttons: 'Cancel' and 'Guess!'.

Feedback:
Correct answer: A green "toast" notification appears in the bottom right corner with a congratulatory message. The score increases by 1. The selected table permanently flips back to the front (with name and photo).
Incorrect answer: A red "toast" notification appears, revealing the correct name. The table does NOT flip. Instead, the element gets a short "shake" animation as visual feedback that the answer was incorrect. The table remains on its question mark side.
Reset: The "Start Game" button changes to "Reset Game." Clicking this ends the game mode, flips all tables back, resets the score to 0, and reactivates all editing buttons.

Example Output

<!DOCTYPE html>
<html lang="nl">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Klaslokaal Pro - Namen Leren</title>
    <!-- Google Fonts & Font Awesome Icons -->
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700&display=swap" rel="stylesheet">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css">
    <link rel="icon" type="image/png" href="/images/favicon1.png">
    <style>
        :root {
            --primary-color: #4A90E2; --secondary-color: #50E3C2; --accent-color: #F5A623;
            --dark-color: #4A4A4A; --light-color: #FDFDFD; --floor-color: #F4F1E8;
            --desk-color: #D2B48C; --desk-border: #8B5A2B;
            --success-color: #28a745; --error-color: #dc3545; --selection-color: #007bff;
        }

        /* --- Algemene Styling & App Container --- */
        body {
            font-family: 'Poppins', sans-serif; display: flex; flex-direction: column;
            align-items: center; background-color: #e9e9e9; margin: 0; padding: 20px;
            box-sizing: border-box;
        }
        .app-container {
            width: 100%; max-width: 1600px; background: var(--light-color); border-radius: 12px;
            box-shadow: 0 8px 30px rgba(0,0,0,0.15); overflow: hidden; display: flex; flex-direction: column;
        }

        /* --- Bedieningspaneel --- */
        .controls {
            padding: 15px 25px; background-color: var(--primary-color); color: white; display: flex;
            flex-wrap: wrap; align-items: center; gap: 15px; z-index: 10;
        }
        .control-group { display: flex; align-items: center; gap: 10px; padding-right: 15px; border-right: 1px solid rgba(255,255,255,0.2); }
        .control-group:last-of-type { border-right: none; }
        .controls button, .controls select {
            padding: 8px 15px; border: none; border-radius: 6px; font-family: 'Poppins', sans-serif;
            font-weight: 600; cursor: pointer; transition: all 0.2s ease-in-out;
            background-color: rgba(255,255,255,0.2); color: white;
        }
        .controls button:hover { background-color: rgba(255,255,255,0.4); transform: translateY(-2px); }
        .controls button.active { background-color: var(--accent-color); color: var(--dark-color); }
        #game-button { background-color: var(--secondary-color); color: var(--dark-color); }
        .score-display { margin-left: auto; font-size: 1.3em; font-weight: 700; background-color: rgba(0,0,0,0.1); padding: 5px 15px; border-radius: 6px; }

        /* --- Hoofdgedeelte & Zijbalk --- */
        .main-content { display: flex; position: relative; }
        .sidebar {
            width: 280px; padding: 20px; background-color: #f8f9fa; border-right: 1px solid #dee2e6;
            position: absolute; top: 0; left: 0; bottom: 0; z-index: 5;
            transform: translateX(-100%); transition: transform 0.3s ease-in-out;
        }
        .sidebar.visible { transform: translateX(0); }
        .sidebar h3 { margin-top: 0; color: var(--primary-color); } .sidebar ul { padding-left: 20px; font-size: 0.9em; color: #6c757d; } .sidebar li { margin-bottom: 10px; }
        
        .classroom-container { flex-grow: 1; transition: margin-left 0.3s ease-in-out; }
        .sidebar.visible + .classroom-container { margin-left: 300px; }
        
        .classroom-area {
            position: relative; min-height: 80vh; background-color: var(--floor-color);
            background-image: linear-gradient(rgba(0,0,0,0.02) 1px, transparent 1px), linear-gradient(90deg, rgba(0,0,0,0.02) 1px, transparent 1px);
            background-size: 20px 20px; overflow: hidden;
        }
        .app-container.delete-mode .class-element { cursor: crosshair !important; }

        /* --- Klas-elementen --- */
        .class-element { position: absolute; box-sizing: border-box; user-select: none; cursor: grab; }
        .class-element.selected { outline: 3px solid var(--selection-color); border-radius: 4px; }
        .class-element.dragging { cursor: grabbing; opacity: 0.7; z-index: 1000; }
        .class-element.shaking { animation: shake 0.5s ease-in-out; }
        
        .desk { width: 100px; height: 60px; }
        .teacher-desk { width: 150px; height: 70px; background-color: #a0522d; border: 2px solid #8B5A2B; border-radius: 4px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); }
        .whiteboard { width: 300px; height: 15px; background-color: #fff; border: 4px solid #333; box-shadow: 0 5px 10px rgba(0,0,0,0.2); }
        
        /* Leerlingtafel - Interactief deel */
        .desk .table-top { perspective: 1000px; background-color: transparent; border: none; box-shadow: none; width: 100%; height: 100%;}
        .desk-inner { position: relative; width: 100%; height: 100%; transition: transform 0.6s; transform-style: preserve-3d; }
        .desk.flipped .desk-inner { transform: rotateY(180deg); }
        .desk-front, .desk-back {
            position: absolute; width: 100%; height: 100%; backface-visibility: hidden; border: 2px solid var(--desk-border);
            border-radius: 4px; display: flex; justify-content: center; align-items: center;
            box-sizing: border-box; box-shadow: 0 4px 6px rgba(0,0,0,0.1); overflow: hidden;
            background-size: cover; background-position: center;
        }
        .desk-front { background-color: var(--desk-color); }
        .desk-back { background-color: var(--desk-border); color: white; transform: rotateY(180deg); font-size: 2.5em; font-weight: bold; }
        
        .desk-name {
            padding: 2px 8px; width: 100%; text-align: center; overflow: hidden; text-overflow: ellipsis;
            white-space: nowrap; font-weight: 600; color: var(--dark-color); position: absolute; bottom: 0; left: 0;
            background: rgba(255, 255, 255, 0.7); backdrop-filter: blur(2px);
        }
        .desk-front.has-photo .desk-name { color: white; background: rgba(0, 0, 0, 0.5); }
        .desk-name input { width: 90%; border: 1px solid #ccc; text-align: center; font-family: 'Poppins', sans-serif; }
        
        .photo-upload-icon {
            position: absolute; top: 5px; right: 5px; font-size: 16px; color: white; background-color: rgba(0,0,0,0.5);
            width: 24px; height: 24px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
            cursor: pointer; opacity: 0; transition: opacity 0.2s; z-index: 10;
        }
        .edit-icon { top: 50%; left: 50%; transform: translate(-50%, -50%); opacity: 1; color: var(--desk-border); background: none; font-size: 24px; }
        
        .app-container:not(.game-mode) .desk:hover .photo-upload-icon { opacity: 1; }
        .desk-front.has-name .edit-icon { display: none; }

        /* --- Custom Modal & Toast Notificaties --- */
        .modal-overlay {
            position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.6); z-index: 2000;
            display: flex; justify-content: center; align-items: center; opacity: 0; visibility: hidden; transition: all 0.3s;
        }
        .modal-overlay.visible { opacity: 1; visibility: visible; }
        .modal-content {
            background: white; padding: 30px; border-radius: 12px; box-shadow: 0 10px 40px rgba(0,0,0,0.2);
            text-align: center; width: 90%; max-width: 400px; transform: scale(0.9); transition: all 0.3s;
        }
        .modal-overlay.visible .modal-content { transform: scale(1); }
        .modal-content h3 { margin-top: 0; color: var(--dark-color); }
        .modal-content input { width: 100%; padding: 12px; border-radius: 6px; border: 1px solid #ccc; font-size: 1em; margin-bottom: 20px; box-sizing: border-box; }
        .modal-buttons { display: flex; gap: 10px; justify-content: center; }
        .modal-buttons button { padding: 10px 20px; width: 120px; font-weight: 600; border-radius: 6px; cursor: pointer; border: none; }
        #modal-confirm { background-color: var(--secondary-color); color: var(--dark-color); } #modal-cancel { background-color: #ddd; }
        .toast-container { position: fixed; bottom: 20px; right: 20px; z-index: 3000; }
        .toast {
            padding: 15px 20px; margin-bottom: 10px; border-radius: 8px; color: white;
            font-weight: 600; box-shadow: 0 4px 15px rgba(0,0,0,0.2);
            opacity: 0; transform: translateX(100%); animation: slideIn 0.5s forwards;
        }
        .toast.success { background-color: var(--success-color); } .toast.error { background-color: var(--error-color); }
        
        @keyframes slideIn { to { opacity: 1; transform: translateX(0); } }
        @keyframes shake {
            10%, 90% { transform: translateX(-2px); }
            20%, 80% { transform: translateX(2px); }
            30%, 50%, 70% { transform: translateX(-4px); }
            40%, 60% { transform: translateX(4px); }
        }
    </style>
</head>
<body>

    <div id="app" class="app-container">
        <div class="controls">
            <button id="toggle-help" title="Toon/verberg help"><i class="fa-solid fa-circle-info"></i></button>
            <div class="control-group">
                <button id="add-desk" title="Voeg leerlingtafel toe"><i class="fa-solid fa-user-graduate"></i></button>
                <button id="add-teacher-desk" title="Voeg lerarenbureau toe"><i class="fa-solid fa-chalkboard-user"></i></button>
                <button id="add-whiteboard" title="Voeg schoolbord toe"><i class="fa-solid fa-person-chalkboard"></i></button>
                <button id="delete-mode-btn" title="Verwijder-modus (of selecteer & druk 'Del')"><i class="fa-solid fa-eraser"></i></button>
            </div>
            <div class="control-group">
                <select id="layout-select">
                    <option value="">Kies opstelling (30 plekken)...</option>
                    <option value="bus">Busopstelling</option>
                    <option value="groups">Groepjes</option>
                    <option value="u-shape">U-vorm</option>
                </select>
                <button id="download-layout-btn" title="Download opstelling als bestand"><i class="fa-solid fa-download"></i> Download</button>
                <button id="upload-layout-btn" title="Upload opstelling uit bestand"><i class="fa-solid fa-upload"></i> Upload</button>
                <button id="clear-layout" title="Maak lokaal leeg"><i class="fa-solid fa-trash"></i></button>
            </div>
            <button id="game-button"><i class="fa-solid fa-play"></i> Start Spel</button>
            <div class="score-display">Score: <span id="score">0</span></div>
        </div>

        <div class="main-content">
            <div id="sidebar" class="sidebar">
                <h3>Hoe het werkt</h3>
                <ul>
                    <li><strong>Bouwen:</strong> Voeg elementen toe en sleep ze naar de juiste plek.</li>
                    <li><strong>Selecteren:</strong> Klik op een element om het te selecteren.</li>
                    <li><strong>Verwijderen:</strong> Selecteer een element en druk op 'Delete', of activeer de Verwijder-modus (<i class="fa-solid fa-eraser"></i>).</li>
                    <li><strong>Namen:</strong> Dubbelklik op een leerlingtafel om een naam in te voeren.</li>
                    <li><strong>Foto's:</strong> Beweeg over een leerlingtafel en klik op <i class="fa-solid fa-camera"></i>.</li>
                    <li><strong>Opslaan:</strong> Klik op 'Download' om je opstelling als een bestand op te slaan.</li>
                    <li><strong>Laden:</strong> Klik op 'Upload' om een eerder opgeslagen bestand te laden.</li>
                    <li><strong>Spelen:</strong> Klik op 'Start Spel' om te oefenen!</li>
                </ul>
            </div>
            <div class="classroom-container">
                <div id="classroom" class="classroom-area"></div>
            </div>
        </div>
    </div>
    
    <div id="guess-modal" class="modal-overlay">
        <div class="modal-content">
            <h3>Wie zit hier?</h3>
            <input type="text" id="guess-input" placeholder="Naam...">
            <div class="modal-buttons">
                <button id="modal-cancel">Annuleren</button>
                <button id="modal-confirm">Raad!</button>
            </div>
        </div>
    </div>
    <div id="toast-container" class="toast-container"></div>
    <input type="file" id="photo-uploader" accept="image/*" style="display: none;">
    <input type="file" id="layout-uploader" accept=".json" style="display: none;">

    <script>
    document.addEventListener('DOMContentLoaded', () => {
        // --- SELECTORS & STATE ---
        const app = document.getElementById('app');
        const classroom = document.getElementById('classroom');
        const sidebar = document.getElementById('sidebar');
        const photoUploader = document.getElementById('photo-uploader');
        const layoutUploader = document.getElementById('layout-uploader');
        const scoreDisplay = document.getElementById('score');
        const gameButton = document.getElementById('game-button');
        const addButtons = document.querySelectorAll('#add-desk, #add-teacher-desk, #add-whiteboard');
        const deleteModeBtn = document.getElementById('delete-mode-btn');
        const guessModal = document.getElementById('guess-modal');
        const guessInput = document.getElementById('guess-input');
        const modalConfirm = document.getElementById('modal-confirm');
        const modalCancel = document.getElementById('modal-cancel');
        
        let score = 0, gameMode = false, deleteMode = false, elementIdCounter = 0;
        let draggedElement = null, selectedElement = null, activeDeskForPhoto = null, activeDeskForGuess = null;
        let offsetX, offsetY;

        // --- PRESET LAYOUTS ---
        const PRESET_LAYOUTS = {
            bus: [
                { type: 'whiteboard', top: '2%', left: 'calc(50% - 150px)' },
                { type: 'teacher-desk', top: '12%', left: '5%' },
                ...Array.from({ length: 30 }, (_, i) => {
                    const row = Math.floor(i / 6); const col_pair_index = Math.floor((i % 6) / 2);
                    const is_left_in_pair = (i % 2) === 0; const col_base_x = [15, 45, 75][col_pair_index];
                    const left = col_base_x + (is_left_in_pair ? 0 : 12); const top = 30 + row * 13;
                    return { type: 'desk', top: `${top}%`, left: `${left}%` };
                })
            ],
            groups: [
                 { type: 'whiteboard', top: '1%', left: 'calc(50% - 150px)' },
                ...Array.from({ length: 6 }, (_, i) => {
                    const groupX = (i % 2) * 50 + 12; const groupY = Math.floor(i / 2) * 30 + 15;
                    return [
                        { type: 'desk', top: `${groupY}%`, left: `${groupX}%` }, { type: 'desk', top: `${groupY}%`, left: `${groupX + 15}%` },
                        { type: 'desk', top: `${groupY + 10}%`, left: `${groupX}%` }, { type: 'desk', top: `${groupY + 10}%`, left: `${groupX + 15}%` },
                        { type: 'desk', top: `${groupY + 5}%`, left: `${groupX + 7.5}%` },
                    ];
                }).flat()
            ],
            'u-shape': [
                { type: 'whiteboard', top: '1%', left: 'calc(50% - 150px)' }, { type: 'teacher-desk', top: '15%', left: 'calc(50% - 75px)' },
                ...Array.from({ length: 30 }, (_, i) => {
                    let top, left;
                    if (i < 11) { top = `${10 + i * 8}%`; left = '5%'; } 
                    else if (i < 19) { top = `90%`; left = `${15 + (i - 11) * 10}%`; } 
                    else { top = `${10 + (29 - i) * 8}%`; left = '85%'; }
                    return { type: 'desk', top, left };
                })
            ]
        };

        // --- LAYOUT & FILE FUNCTIONS ---
        function downloadLayout() {
            const layoutData = Array.from(classroom.children).map(el => ({
                type: el.dataset.type, left: el.style.left, top: el.style.top,
                name: el.dataset.name || '', photo: el.dataset.photo || ''
            }));
            const jsonString = JSON.stringify(layoutData, null, 2);
            const blob = new Blob([jsonString], { type: 'application/json' });
            const url = URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            a.download = 'klaslokaal-opstelling.json';
            document.body.appendChild(a);
            a.click();
            document.body.removeChild(a);
            URL.revokeObjectURL(url);
            showToast('Opstelling gedownload!', 'success');
        }

        layoutUploader.addEventListener('change', (e) => {
            const file = e.target.files[0];
            if (!file) return;

            const reader = new FileReader();
            reader.onload = (event) => {
                try {
                    const layoutData = JSON.parse(event.target.result);
                    if (!Array.isArray(layoutData)) { throw new Error('Invalid format'); }
                    renderLayout(layoutData);
                    showToast('Opstelling succesvol geladen!', 'success');
                } catch (error) {
                    showToast('Fout bij laden. Ongeldig bestand.', 'error');
                }
            };
            reader.readAsText(file);
            e.target.value = ''; // Reset for re-uploading same file
        });
        
        function renderLayout(layoutData) {
            classroom.innerHTML = ''; elementIdCounter = 0;
            if (layoutData) {
                layoutData.forEach(item => createElement(item || {}));
            }
        }

        // --- ELEMENT CREATION ---
        function createElement({type, left = '50px', top = '50px', name = '', photo = ''}) {
            const element = document.createElement('div');
            element.id = `el-${elementIdCounter++}`;
            element.className = `class-element ${type}`;
            element.dataset.type = type;
            element.style.left = left;
            element.style.top = top;
            
            if (type === 'desk') {
                element.innerHTML = `
                    <div class="table-top">
                        <div class="desk-inner">
                            <div class="desk-front">
                                <i class="fa-solid fa-pencil edit-icon" title="Dubbelklik om naam toe te voegen"></i>
                                <i class="fa-solid fa-camera photo-upload-icon" title="Foto uploaden"></i>
                                <span class="desk-name"></span>
                            </div>
                            <div class="desk-back">?</div>
                        </div>
                    </div>`;
                updateDeskAppearance(element, name, photo);
                element.querySelector('.photo-upload-icon').addEventListener('click', (e) => { e.stopPropagation(); activeDeskForPhoto = element; photoUploader.click(); });
            }

            element.addEventListener('dblclick', handleDoubleClick);
            classroom.appendChild(element);
            return element;
        }

        function updateDeskAppearance(desk, name, photo) {
            desk.dataset.name = name || '';
            desk.dataset.photo = photo || '';
            const nameSpan = desk.querySelector('.desk-name');
            const front = desk.querySelector('.desk-front');
            const back = desk.querySelector('.desk-back');
            nameSpan.textContent = name;
            front.classList.toggle('has-name', !!name);
            if (photo) {
                front.style.backgroundImage = `url(${photo})`; front.classList.add('has-photo');
                back.style.backgroundImage = `url(${photo})`; back.textContent = '';
            } else {
                front.style.backgroundImage = 'none'; front.classList.remove('has-photo');
                back.style.backgroundImage = 'none'; back.textContent = '?';
            }
        }

        // --- PHOTO UPLOAD LOGIC ---
        photoUploader.addEventListener('change', (e) => {
            const file = e.target.files[0];
            if (!file || !activeDeskForPhoto) return;
            const reader = new FileReader();
            reader.onload = (event) => {
                const img = new Image();
                img.onload = () => {
                    const canvas = document.createElement('canvas');
                    const MAX_WIDTH = 200;
                    const scaleSize = MAX_WIDTH / img.width;
                    canvas.width = MAX_WIDTH; canvas.height = img.height * scaleSize;
                    const ctx = canvas.getContext('2d');
                    ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
                    const dataUrl = canvas.toDataURL('image/jpeg', 0.85);
                    updateDeskAppearance(activeDeskForPhoto, activeDeskForPhoto.dataset.name, dataUrl);
                };
                img.src = event.target.result;
            };
            reader.readAsDataURL(file);
        });

        // --- EVENT HANDLERS (Select, Delete, Drag, DoubleClick) ---
        function selectElement(element) {
            if (selectedElement) selectedElement.classList.remove('selected');
            if (element) element.classList.add('selected');
            selectedElement = element;
        }

        function deleteSelectedElement() {
            if (selectedElement) {
                selectedElement.remove();
                showToast('Element verwijderd.', 'success');
                selectedElement = null;
            }
        }
        
        deleteModeBtn.addEventListener('click', () => {
            deleteMode = !deleteMode;
            app.classList.toggle('delete-mode', deleteMode);
            deleteModeBtn.classList.toggle('active', deleteMode);
            if (deleteMode) selectElement(null);
        });

        document.addEventListener('keydown', (e) => {
            if ((e.key === 'Delete' || e.key === 'Backspace') && selectedElement && !gameMode) {
                e.preventDefault();
                deleteSelectedElement();
            }
        });
        
        classroom.addEventListener('mousedown', (e) => {
            if (gameMode) return;
            const targetElement = e.target.closest('.class-element');
            if (deleteMode) {
                if (targetElement) { targetElement.remove(); showToast('Element verwijderd.', 'success'); }
                return;
            }
            selectElement(targetElement);
            if (!targetElement) return;
            draggedElement = targetElement;
            draggedElement.classList.add('dragging');
            const rect = draggedElement.getBoundingClientRect();
            offsetX = e.clientX - rect.left;
            offsetY = e.clientY - rect.top;
        });

        document.addEventListener('mousemove', (e) => {
            if (!draggedElement) return;
            e.preventDefault();
            const classroomRect = classroom.getBoundingClientRect();
            let x = e.clientX - classroomRect.left - offsetX;
            let y = e.clientY - classroomRect.top - offsetY;
            draggedElement.style.left = `${Math.max(0, Math.min(x, classroomRect.width - draggedElement.offsetWidth))}px`;
            draggedElement.style.top = `${Math.max(0, Math.min(y, classroomRect.height - draggedElement.offsetHeight))}px`;
        });

        document.addEventListener('mouseup', () => {
            if (draggedElement) { draggedElement.classList.remove('dragging'); draggedElement = null; }
        });

        function handleDoubleClick(e) {
            if (gameMode) return;
            const element = e.currentTarget;
            if (element.dataset.type === 'desk') {
                handleNameEdit(element);
            }
        }

        function handleNameEdit(desk) {
            const nameSpan = desk.querySelector('.desk-name');
            const currentName = desk.dataset.name || '';
            nameSpan.innerHTML = `<input type="text" value="${currentName}" />`;
            const input = nameSpan.querySelector('input');
            input.focus(); input.select();
            const saveName = () => {
                const newName = input.value.trim();
                updateDeskAppearance(desk, newName, desk.dataset.photo);
            };
            input.addEventListener('blur', saveName);
            input.addEventListener('keydown', (ev) => { if (ev.key === 'Enter') input.blur(); });
        }
        
        // --- GAME LOGIC ---
        gameButton.addEventListener('click', () => {
            gameMode = !gameMode;
            app.classList.toggle('game-mode', gameMode);
            if (gameMode) {
                gameButton.innerHTML = '<i class="fa-solid fa-stop"></i> Reset Spel';
                document.querySelectorAll('.desk').forEach(desk => { if (desk.dataset.name) desk.classList.add('flipped'); });
                [...addButtons, deleteModeBtn, document.getElementById('download-layout-btn'), document.getElementById('upload-layout-btn'), document.getElementById('clear-layout'), document.getElementById('layout-select')].forEach(btn => btn.disabled = true);
            } else {
                gameButton.innerHTML = '<i class="fa-solid fa-play"></i> Start Spel';
                score = 0; updateScore();
                document.querySelectorAll('.desk').forEach(desk => desk.classList.remove('flipped'));
                [...addButtons, deleteModeBtn, document.getElementById('download-layout-btn'), document.getElementById('upload-layout-btn'), document.getElementById('clear-layout'), document.getElementById('layout-select')].forEach(btn => btn.disabled = false);
            }
        });

        function handleGuessClick(e) {
            const desk = e.currentTarget;
            if (!gameMode || !desk.classList.contains('flipped') || !desk.dataset.name) return;
            activeDeskForGuess = desk; showModal();
        }
        classroom.addEventListener('click', (e) => {
            const desk = e.target.closest('.desk');
            if (desk) handleGuessClick({currentTarget: desk});
        });

        function processGuess() {
            if (!activeDeskForGuess) return;
            const guess = guessInput.value.trim();
            const correctName = activeDeskForGuess.dataset.name;
            if (guess.toLowerCase() === correctName.toLowerCase()) {
                showToast(`Correct! Dat is ${correctName}.`, 'success');
                score++; updateScore();
                activeDeskForGuess.classList.remove('flipped');
            } else {
                showToast(`Helaas, het juiste antwoord was: ${correctName}`, 'error');
                activeDeskForGuess.classList.add('shaking');
                setTimeout(() => { if(activeDeskForGuess) activeDeskForGuess.classList.remove('shaking'); }, 500);
            }
            hideModal();
        }

        function showModal() { guessModal.classList.add('visible'); guessInput.value = ''; setTimeout(() => guessInput.focus(), 100); }
        function hideModal() { guessModal.classList.remove('visible'); activeDeskForGuess = null; }
        function updateScore() { scoreDisplay.textContent = score; }

        // --- INIT & MISC LISTENERS ---
        document.getElementById('toggle-help').addEventListener('click', () => sidebar.classList.toggle('visible'));
        document.getElementById('download-layout-btn').addEventListener('click', downloadLayout);
        document.getElementById('upload-layout-btn').addEventListener('click', () => layoutUploader.click());
        document.getElementById('clear-layout').addEventListener('click', () => { if (confirm('Weet je zeker dat je het hele lokaal wilt leegmaken?')) renderLayout([]); });
        document.getElementById('layout-select').addEventListener('change', (e) => {
            const selected = e.target.value;
            if (selected && PRESET_LAYOUTS[selected]) {
                if (classroom.children.length > 0 && !confirm('Huidige opstelling wordt overschreven. Doorgaan?')) { e.target.value = ""; return; }
                renderLayout(PRESET_LAYOUTS[selected]);
            }
        });
        document.getElementById('add-desk').addEventListener('click', () => selectElement(createElement({type: 'desk'})));
        document.getElementById('add-teacher-desk').addEventListener('click', () => selectElement(createElement({type: 'teacher-desk'})));
        document.getElementById('add-whiteboard').addEventListener('click', () => selectElement(createElement({type: 'whiteboard'})));
        
        modalConfirm.addEventListener('click', processGuess);
        modalCancel.addEventListener('click', hideModal);
        guessInput.addEventListener('keydown', (e) => { if (e.key === 'Enter') processGuess(); });
        guessModal.addEventListener('click', (e) => { if (e.target === guessModal) hideModal(); });

        function showToast(message, type = 'info') {
            const toast = document.createElement('div');
            toast.className = `toast ${type}`;
            toast.textContent = message;
            document.getElementById('toast-container').appendChild(toast);
            setTimeout(() => { toast.remove(); }, 3000);
        }

        renderLayout(PRESET_LAYOUTS.bus);
    });
    </script>
</body>
</html>