Models 44

Gemini 3.1 Flash Lite

by GoogleReasoningClean
Open in new window

Running live in a sandboxed frame. Click inside it before using the keyboard.

How it went

Total time
15.0 s
Cost
$0.0081
Output tokens
5,286
Spent thinking
2,386 tokens
Speed
378.4 tok/s
Console errors
0
First token after
990 ms
First visible text after
8.3 s
Prompt tokens
507
Code size
10.2 KB
Finish reason
stop
Served by
Google
Model id
google/gemini-3.1-flash-lite
Reasoning sent
{"effort":"high"}
Max output
65,536 tokens
Generated
Nov 12, 2026

What it was asked

The prompt
Build an interactive Kanban board in vanilla HTML, CSS and JavaScript (no framework, no library). Requirements: - Three columns: "To do", "In progress", "Done", each showing its card count. - Pre-populate the board with 6 realistic cards spread across the columns so the first screenshot looks alive. - Each card has a title and a priority (low / medium / high) shown as a colored badge. - Add a card through a small modal form (title required), and delete a card with a button on it. - Drag and drop cards between columns with the mouse, with a clear visual drop indicator. - A search field that filters cards live by title. - A light / dark theme toggle. - State lives in memory only (no storage APIs).
System prompt, sent with every prompt
You are generating a self-contained web demo. It will be rendered automatically in a sandboxed iframe and compared side by side with the output of other AI models given the exact same task.

Output rules:
- Reply with exactly ONE fenced code block containing the complete file: ```html (or ```svg when the task asks for an SVG). No text before or after the code block.
- Everything must be inline: CSS in <style>, JavaScript in <script>. No external files, images, fonts or network requests, except the CDN URLs explicitly allowed by the task.
- Do not use localStorage, sessionStorage, cookies, IndexedDB, alert(), confirm(), prompt() or window.open(): they are blocked in the sandbox and will throw.
- The page must look right in a 1280×800 viewport and adapt gracefully down to 375px wide. No horizontal scrollbar.
- Something meaningful must be visible on first paint: a screenshot is taken automatically about 3 seconds after load, without any interaction.
- Everything that makes the demo interesting must be visible within the first seconds: nothing hidden behind a high score, a later level or a long play session.
- Games must start in a self-playing demo mode (a simple AI plays) behind a "Click or press a key to start" message, so the game can be judged in action without playing.
- The iframe only receives keyboard events after the user clicks it: if the demo uses the keyboard, display a clear "Click or press a key to start" message.
- The code must run with zero errors in the console of the latest Chrome.

Code run-1.html · 291 lines

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Interactive Kanban Board</title>
    <style>
        :root {
            --bg: #f4f5f7;
            --surface: #ffffff;
            --text: #172b4d;
            --accent: #0052cc;
            --border: #dfe1e6;
            --low: #28a745;
            --medium: #ffc107;
            --high: #dc3545;
            --shadow: 0 1px 3px rgba(0,0,0,0.1);
        }

        .dark-mode {
            --bg: #121212;
            --surface: #1e1e1e;
            --text: #e0e0e0;
            --accent: #4dabf7;
            --border: #333;
            --shadow: 0 1px 3px rgba(0,0,0,0.5);
        }

        body {
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
            background-color: var(--bg);
            color: var(--text);
            margin: 0;
            padding: 20px;
            transition: background 0.3s, color 0.3s;
        }

        #start-overlay {
            position: fixed;
            top: 0; left: 0; width: 100%; height: 100%;
            background: rgba(0,0,0,0.8);
            color: white;
            display: flex;
            align-items: center;
            justify-content: center;
            z-index: 1000;
            cursor: pointer;
            text-align: center;
            font-size: 1.5rem;
        }

        .header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 20px;
            padding-bottom: 20px;
            border-bottom: 1px solid var(--border);
        }

        .controls { display: flex; gap: 10px; }

        input, button {
            padding: 8px 12px;
            border-radius: 4px;
            border: 1px solid var(--border);
            background: var(--surface);
            color: var(--text);
        }

        button { cursor: pointer; background: var(--accent); color: white; border: none; }
        button:hover { opacity: 0.9; }

        .board {
            display: flex;
            gap: 20px;
            align-items: flex-start;
            overflow-x: auto;
            min-height: 500px;
        }

        .column {
            flex: 1;
            min-width: 300px;
            background: var(--surface);
            border-radius: 8px;
            padding: 15px;
            border: 2px solid transparent;
            transition: border 0.2s;
        }

        .column.drag-over { border-color: var(--accent); }

        .column h2 { margin-top: 0; font-size: 1rem; display: flex; justify-content: space-between; }

        .card {
            background: var(--bg);
            padding: 12px;
            border-radius: 6px;
            margin-bottom: 10px;
            cursor: grab;
            border: 1px solid var(--border);
            position: relative;
        }

        .card:active { cursor: grabbing; }

        .card-header { display: flex; justify-content: space-between; align-items: start; margin-bottom: 8px; }
        .card-title { font-weight: 500; }
        .badge { font-size: 0.7rem; padding: 2px 6px; border-radius: 10px; color: white; }
        .badge.low { background: var(--low); }
        .badge.medium { background: var(--medium); color: #000; }
        .badge.high { background: var(--high); }

        .delete-btn {
            background: transparent;
            color: var(--text);
            border: none;
            cursor: pointer;
            font-size: 0.8rem;
            opacity: 0.5;
        }
        .delete-btn:hover { opacity: 1; color: var(--high); }

        /* Modal */
        #modal-overlay {
            display: none;
            position: fixed; top:0; left:0; width:100%; height:100%;
            background: rgba(0,0,0,0.5);
            align-items: center;
            justify-content: center;
            z-index: 500;
        }
        .modal {
            background: var(--surface);
            padding: 20px;
            border-radius: 8px;
            width: 300px;
        }
        .modal input, .modal select { width: 100%; margin-bottom: 10px; box-sizing: border-box; }
    </style>
</head>
<body>

    <div id="start-overlay" onclick="startDemo()">
        <div>
            <h1>Kanban Board</h1>
            <p>Click or press any key to start</p>
        </div>
    </div>

    <div class="header">
        <h1>Board</h1>
        <div class="controls">
            <input type="text" id="search" placeholder="Search tasks..." oninput="filterCards()">
            <button onclick="toggleTheme()">Theme</button>
            <button onclick="openModal()">+ Add Card</button>
        </div>
    </div>

    <div class="board">
        <div class="column" id="col-todo" ondrop="drop(event)" ondragover="allowDrop(event)" ondragenter="dragEnter(event)" ondragleave="dragLeave(event)">
            <h2>To do <span id="count-todo">0</span></h2>
            <div class="cards" id="cards-todo"></div>
        </div>
        <div class="column" id="col-in-progress" ondrop="drop(event)" ondragover="allowDrop(event)" ondragenter="dragEnter(event)" ondragleave="dragLeave(event)">
            <h2>In progress <span id="count-in-progress">0</span></h2>
            <div class="cards" id="cards-in-progress"></div>
        </div>
        <div class="column" id="col-done" ondrop="drop(event)" ondragover="allowDrop(event)" ondragenter="dragEnter(event)" ondragleave="dragLeave(event)">
            <h2>Done <span id="count-done">0</span></h2>
            <div class="cards" id="cards-done"></div>
        </div>
    </div>

    <div id="modal-overlay">
        <div class="modal">
            <h3>Add New Card</h3>
            <input type="text" id="new-title" placeholder="Task Title">
            <select id="new-priority">
                <option value="low">Low</option>
                <option value="medium" selected>Medium</option>
                <option value="high">High</option>
            </select>
            <button onclick="addCard()">Save</button>
            <button onclick="closeModal()" style="background:none; color:inherit;">Cancel</button>
        </div>
    </div>

    <script>
        let state = [
            { id: 1, title: 'Fix CSS bugs', priority: 'high', status: 'todo' },
            { id: 2, title: 'Draft API docs', priority: 'medium', status: 'todo' },
            { id: 3, title: 'Update dependencies', priority: 'low', status: 'in-progress' },
            { id: 4, title: 'Implement login', priority: 'high', status: 'in-progress' },
            { id: 5, title: 'Write tests', priority: 'medium', status: 'done' },
            { id: 6, title: 'Deploy to Vercel', priority: 'low', status: 'done' }
        ];

        let demoMode = false;
        let interacted = false;

        function startDemo() {
            document.getElementById('start-overlay').style.display = 'none';
            interacted = true;
            render();
        }

        window.addEventListener('keydown', startDemo);

        function render() {
            const searchTerm = document.getElementById('search').value.toLowerCase();
            ['todo', 'in-progress', 'done'].forEach(status => {
                const container = document.getElementById(`cards-${status}`);
                const countEl = document.getElementById(`count-${status}`);
                const filtered = state.filter(c => c.status === status && c.title.toLowerCase().includes(searchTerm));
                
                countEl.textContent = `(${filtered.length})`;
                container.innerHTML = '';
                
                filtered.forEach(card => {
                    const el = document.createElement('div');
                    el.className = 'card';
                    el.draggable = true;
                    el.id = `card-${card.id}`;
                    el.ondragstart = drag;
                    el.innerHTML = `
                        <div class="card-header">
                            <span class="card-title">${card.title}</span>
                            <button class="delete-btn" onclick="deleteCard(${card.id})">✕</button>
                        </div>
                        <span class="badge ${card.priority}">${card.priority.toUpperCase()}</span>
                    `;
                    container.appendChild(el);
                });
            });
        }

        function allowDrop(e) { e.preventDefault(); }
        function dragEnter(e) { if(e.target.classList.contains('column')) e.target.classList.add('drag-over'); }
        function dragLeave(e) { if(e.target.classList.contains('column')) e.target.classList.remove('drag-over'); }

        function drag(e) {
            e.dataTransfer.setData("text", e.target.id);
        }

        function drop(e) {
            e.preventDefault();
            const col = e.target.closest('.column');
            col.classList.remove('drag-over');
            const data = e.dataTransfer.getData("text");
            const id = parseInt(data.replace('card-', ''));
            const status = col.id.replace('col-', '');
            
            state = state.map(c => c.id === id ? {...c, status} : c);
            render();
        }

        function addCard() {
            const title = document.getElementById('new-title').value;
            const priority = document.getElementById('new-priority').value;
            if(!title) return;
            state.push({ id: Date.now(), title, priority, status: 'todo' });
            closeModal();
            render();
        }

        function deleteCard(id) {
            state = state.filter(c => c.id !== id);
            render();
        }

        function filterCards() { render(); }
        function openModal() { document.getElementById('modal-overlay').style.display = 'flex'; }
        function closeModal() { document.getElementById('modal-overlay').style.display = 'none'; }
        function toggleTheme() { document.body.classList.toggle('dark-mode'); }

        // Automatic demo for visual sake
        setTimeout(() => {
            if(!interacted) {
                // Perform a simple demo action: move a card
                const id = state[0].id;
                state = state.map(c => c.id === id ? {...c, status: 'in-progress'} : c);
                render();
            }
        }, 3000);

        render();
    </script>
</body>
</html>
Reasoning trace (2,386 tokens)
**Creating My Board**

I'm thinking about how to structure the Kanban board with three columns: To Do, In Progress, and Done. I envision each column displaying a count of its cards, and I've pre-populated it with six initial cards, each featuring a title and a priority badge. Adding new cards will be handled through a modal form.

**Implementing Board Features**

I'm now focusing on interactive elements. I'll be integrating drag-and-drop functionality using the Drag and Drop API for cards and implementing live search for filtering by title. Additionally, I'm exploring how to visually demonstrate interactivity, perhaps through an auto-demo effect, to meet the "self-playing demo" requirement.

**Adding Key Functionality**

I'm diving into the core interactive features now. I plan to implement drag-and-drop for cards between columns and a live search to filter them. I'm also considering how to trigger a self-playing demo after a short period of inactivity.

**Automating Board Actions**

I'm refining the self-playing demo concept. Instead of a complex sequence, I'll now focus on a single, highlighted card move after inactivity to showcase interactivity, fitting the "judged in action" requirement.

**Refining Accessibility & Demo**

I'm prioritizing accessibility by adding button labels and basic focus management, ensuring the solution is self-contained. The automatic demo will now focus on a single card move after inactivity, fulfilling the "judged in action" requirement.