Mistral Small 4
by MistralReasoningClean
Running live in a sandboxed frame. Click inside it before using the keyboard.
How it went
- Total time
- 25.6 s
- Cost
- $0.0032
- Output tokens
- 5,201
- Spent thinking
- 0 tokens
- Speed
- 207.9 tok/s
- Console errors
- 0
- First token after
- 564 ms
- First visible text after
- 564 ms
- Prompt tokens
- 514
- Code size
- 19.6 KB
- Finish reason
- stop
- Served by
- Mistral
- Model id
mistralai/mistral-small-2603- Reasoning sent
model default- Max output
- 209,715 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 · 721 lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Kanban Board</title>
<style>
:root {
--bg-primary: #f5f5f5;
--bg-secondary: #ffffff;
--text-primary: #333333;
--text-secondary: #666666;
--border-color: #dddddd;
--shadow-color: rgba(0, 0, 0, 0.1);
--card-bg: #ffffff;
--card-border: #e0e0e0;
--priority-low: #4caf50;
--priority-medium: #ff9800;
--priority-high: #f44336;
--column-bg: #f9f9f9;
}
[data-theme="dark"] {
--bg-primary: #1a1a1a;
--bg-secondary: #2d2d2d;
--text-primary: #f0f0f0;
--text-secondary: #cccccc;
--border-color: #444444;
--shadow-color: rgba(0, 0, 0, 0.3);
--card-bg: #333333;
--card-border: #555555;
--column-bg: #222222;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: var(--bg-primary);
color: var(--text-primary);
line-height: 1.6;
padding: 20px;
min-height: 100vh;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 30px;
flex-wrap: wrap;
gap: 20px;
}
.header h1 {
font-size: 2rem;
font-weight: 600;
}
.search-container {
position: relative;
flex: 1;
min-width: 250px;
}
.search-container input {
width: 100%;
padding: 12px 15px 12px 40px;
border: 1px solid var(--border-color);
border-radius: 6px;
background-color: var(--bg-secondary);
color: var(--text-primary);
font-size: 1rem;
transition: box-shadow 0.2s;
}
.search-container input:focus {
outline: none;
box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.25);
}
.search-icon {
position: absolute;
left: 15px;
top: 50%;
transform: translateY(-50%);
color: var(--text-secondary);
pointer-events: none;
}
.theme-toggle {
background: none;
border: none;
padding: 10px 15px;
border-radius: 6px;
cursor: pointer;
font-size: 1rem;
transition: background-color 0.2s;
}
.theme-toggle:hover {
background-color: rgba(0, 0, 0, 0.1);
}
[data-theme="dark"] .theme-toggle:hover {
background-color: rgba(255, 255, 255, 0.1);
}
.board {
display: flex;
gap: 20px;
overflow-x: auto;
padding-bottom: 10px;
}
.column {
flex: 1;
min-width: 280px;
background-color: var(--column-bg);
border-radius: 8px;
padding: 15px;
box-shadow: 0 2px 8px var(--shadow-color);
}
.column-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
padding-bottom: 10px;
border-bottom: 1px solid var(--border-color);
}
.column-title {
font-size: 1.1rem;
font-weight: 600;
color: var(--text-primary);
}
.card-count {
background-color: var(--bg-secondary);
color: var(--text-secondary);
padding: 4px 8px;
border-radius: 12px;
font-size: 0.85rem;
font-weight: 500;
}
.add-card-btn {
width: 100%;
padding: 10px;
background-color: var(--bg-secondary);
border: 2px dashed var(--border-color);
border-radius: 6px;
color: var(--text-secondary);
cursor: pointer;
font-size: 0.9rem;
transition: all 0.2s;
}
.add-card-btn:hover {
border-color: var(--text-secondary);
color: var(--text-primary);
}
.cards-container {
display: flex;
flex-direction: column;
gap: 12px;
}
.card {
background-color: var(--card-bg);
border: 1px solid var(--card-border);
border-radius: 6px;
padding: 12px;
cursor: grab;
transition: all 0.2s;
position: relative;
}
.card:hover {
box-shadow: 0 2px 8px var(--shadow-color);
transform: translateY(-2px);
}
.card.dragging {
opacity: 0.5;
background-color: var(--bg-secondary);
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
}
.card-title {
font-weight: 500;
color: var(--text-primary);
}
.priority-badge {
padding: 4px 8px;
border-radius: 12px;
font-size: 0.75rem;
font-weight: 600;
color: white;
}
.priority-low {
background-color: var(--priority-low);
}
.priority-medium {
background-color: var(--priority-medium);
}
.priority-high {
background-color: var(--priority-high);
}
.delete-btn {
background: none;
border: none;
color: var(--text-secondary);
cursor: pointer;
padding: 4px;
margin-left: 8px;
transition: color 0.2s;
}
.delete-btn:hover {
color: var(--priority-high);
}
.modal-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
}
.modal {
background-color: var(--bg-secondary);
border-radius: 8px;
padding: 25px;
width: 100%;
max-width: 400px;
box-shadow: 0 4px 20px var(--shadow-color);
}
.modal h2 {
margin-bottom: 20px;
font-size: 1.3rem;
color: var(--text-primary);
}
.form-group {
margin-bottom: 15px;
}
.form-group label {
display: block;
margin-bottom: 5px;
font-weight: 500;
color: var(--text-primary);
}
.form-group input {
width: 100%;
padding: 10px;
border: 1px solid var(--border-color);
border-radius: 4px;
background-color: var(--bg-primary);
color: var(--text-primary);
font-size: 1rem;
}
.form-group input:focus {
outline: none;
border-color: #007bff;
box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.25);
}
.priority-selector {
display: flex;
gap: 10px;
margin-bottom: 20px;
}
.priority-option {
flex: 1;
padding: 10px;
border-radius: 4px;
text-align: center;
cursor: pointer;
font-weight: 500;
transition: all 0.2s;
}
.priority-option.selected {
color: white;
}
.priority-low.selected {
background-color: var(--priority-low);
}
.priority-medium.selected {
background-color: var(--priority-medium);
}
.priority-high.selected {
background-color: var(--priority-high);
}
.modal-buttons {
display: flex;
justify-content: flex-end;
gap: 10px;
margin-top: 20px;
}
.btn {
padding: 10px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
font-weight: 500;
transition: all 0.2s;
}
.btn-primary {
background-color: #007bff;
color: white;
}
.btn-primary:hover {
background-color: #0056b3;
}
.btn-secondary {
background-color: var(--bg-primary);
color: var(--text-primary);
border: 1px solid var(--border-color);
}
.btn-secondary:hover {
background-color: var(--border-color);
}
.drop-indicator {
height: 4px;
background-color: #007bff;
margin-bottom: 8px;
border-radius: 2px;
display: none;
}
.column.drop-target {
background-color: rgba(0, 123, 255, 0.1);
}
@media (max-width: 768px) {
.board {
flex-direction: column;
}
.column {
min-width: 100%;
}
.header {
flex-direction: column;
align-items: stretch;
}
.search-container {
order: -1;
}
}
</style>
</head>
<body>
<div class="header">
<h1>Kanban Board</h1>
<div class="search-container">
<span class="search-icon">🔍</span>
<input type="text" id="search-input" placeholder="Search cards...">
</div>
<button class="theme-toggle" id="theme-toggle">🌓 Toggle Theme</button>
</div>
<div class="board" id="board">
<div class="column" id="todo-column">
<div class="column-header">
<span class="column-title">To do</span>
<span class="card-count" id="todo-count">0</span>
</div>
<div class="drop-indicator" id="todo-drop-indicator"></div>
<div class="cards-container" id="todo-cards"></div>
<button class="add-card-btn" id="add-todo-card">+ Add Card</button>
</div>
<div class="column" id="inprogress-column">
<div class="column-header">
<span class="column-title">In progress</span>
<span class="card-count" id="inprogress-count">0</span>
</div>
<div class="drop-indicator" id="inprogress-drop-indicator"></div>
<div class="cards-container" id="inprogress-cards"></div>
<button class="add-card-btn" id="add-inprogress-card">+ Add Card</button>
</div>
<div class="column" id="done-column">
<div class="column-header">
<span class="column-title">Done</span>
<span class="card-count" id="done-count">0</span>
</div>
<div class="drop-indicator" id="done-drop-indicator"></div>
<div class="cards-container" id="done-cards"></div>
<button class="add-card-btn" id="add-done-card">+ Add Card</button>
</div>
</div>
<div class="modal-overlay" id="modal-overlay">
<div class="modal">
<h2>Add New Card</h2>
<form id="card-form">
<div class="form-group">
<label for="card-title">Title*</label>
<input type="text" id="card-title" required>
</div>
<div class="form-group">
<label>Priority</label>
<div class="priority-selector">
<div class="priority-option" data-priority="low">Low</div>
<div class="priority-option" data-priority="medium">Medium</div>
<div class="priority-option" data-priority="high">High</div>
</div>
</div>
<input type="hidden" id="selected-priority" value="medium">
<div class="modal-buttons">
<button type="button" class="btn btn-secondary" id="cancel-btn">Cancel</button>
<button type="submit" class="btn btn-primary">Add Card</button>
</div>
</form>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
// State
let cards = [
{ id: 1, title: 'Implement login page', priority: 'high', column: 'todo' },
{ id: 2, title: 'Design database schema', priority: 'medium', column: 'inprogress' },
{ id: 3, title: 'Write API documentation', priority: 'low', column: 'done' },
{ id: 4, title: 'Fix mobile navigation bug', priority: 'high', column: 'inprogress' },
{ id: 5, title: 'Update project README', priority: 'medium', column: 'todo' },
{ id: 6, title: 'Test payment integration', priority: 'low', column: 'done' }
];
let draggedCard = null;
let searchQuery = '';
// DOM elements
const board = document.getElementById('board');
const modalOverlay = document.getElementById('modal-overlay');
const cardForm = document.getElementById('card-form');
const cardTitleInput = document.getElementById('card-title');
const selectedPriorityInput = document.getElementById('selected-priority');
const cancelBtn = document.getElementById('cancel-btn');
const themeToggle = document.getElementById('theme-toggle');
const searchInput = document.getElementById('search-input');
const todoColumn = document.getElementById('todo-column');
const inprogressColumn = document.getElementById('inprogress-column');
const doneColumn = document.getElementById('done-column');
const todoCardsContainer = document.getElementById('todo-cards');
const inprogressCardsContainer = document.getElementById('inprogress-cards');
const doneCardsContainer = document.getElementById('done-cards');
const todoCount = document.getElementById('todo-count');
const inprogressCount = document.getElementById('inprogress-count');
const doneCount = document.getElementById('done-count');
// Initialize
renderCards();
updateCounts();
// Event listeners
themeToggle.addEventListener('click', toggleTheme);
searchInput.addEventListener('input', handleSearch);
cardForm.addEventListener('submit', handleAddCard);
cancelBtn.addEventListener('click', closeModal);
// Add card buttons
document.getElementById('add-todo-card').addEventListener('click', () => openModal('todo'));
document.getElementById('add-inprogress-card').addEventListener('click', () => openModal('inprogress'));
document.getElementById('add-done-card').addEventListener('click', () => openModal('done'));
// Priority selector
const priorityOptions = document.querySelectorAll('.priority-option');
priorityOptions.forEach(option => {
option.addEventListener('click', function() {
priorityOptions.forEach(opt => opt.classList.remove('selected'));
this.classList.add('selected');
selectedPriorityInput.value = this.dataset.priority;
});
});
// Drag and drop setup
document.addEventListener('dragstart', handleDragStart);
document.addEventListener('dragover', handleDragOver);
document.addEventListener('dragleave', handleDragLeave);
document.addEventListener('drop', handleDrop);
document.addEventListener('dragend', handleDragEnd);
// Functions
function toggleTheme() {
const html = document.documentElement;
const currentTheme = html.getAttribute('data-theme');
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
html.setAttribute('data-theme', newTheme);
}
function handleSearch(e) {
searchQuery = e.target.value.toLowerCase();
renderCards();
}
function openModal(column) {
document.getElementById('selected-priority').value = 'medium';
priorityOptions.forEach(opt => opt.classList.remove('selected'));
priorityOptions[1].classList.add('selected');
modalOverlay.style.display = 'flex';
cardTitleInput.focus();
}
function closeModal() {
modalOverlay.style.display = 'none';
cardForm.reset();
}
function handleAddCard(e) {
e.preventDefault();
const title = cardTitleInput.value.trim();
if (!title) return;
const priority = selectedPriorityInput.value;
const column = document.querySelector('.modal-overlay').dataset.column || 'todo';
const newCard = {
id: Date.now(),
title,
priority,
column
};
cards.push(newCard);
renderCards();
updateCounts();
closeModal();
}
function handleDragStart(e) {
if (e.target.classList.contains('card')) {
draggedCard = e.target;
e.target.classList.add('dragging');
e.dataTransfer.setData('text/plain', e.target.dataset.cardId);
}
}
function handleDragOver(e) {
e.preventDefault();
if (e.target.classList.contains('column') || e.target.classList.contains('cards-container')) {
clearDropIndicators();
e.target.classList.add('drop-target');
const columnId = e.target.id;
const dropIndicator = document.getElementById(`${columnId.replace('-column', '')}-drop-indicator`);
dropIndicator.style.display = 'block';
}
}
function handleDragLeave(e) {
if (e.target.classList.contains('column') || e.target.classList.contains('cards-container')) {
e.target.classList.remove('drop-target');
clearDropIndicators();
}
}
function handleDrop(e) {
e.preventDefault();
if (e.target.classList.contains('column') || e.target.classList.contains('cards-container')) {
const columnId = e.target.id;
const targetColumn = columnId.replace('-column', '');
const cardId = draggedCard.dataset.cardId;
const cardIndex = cards.findIndex(card => card.id == cardId);
if (cardIndex !== -1) {
cards[cardIndex].column = targetColumn;
renderCards();
updateCounts();
}
}
}
function handleDragEnd(e) {
if (e.target.classList.contains('card')) {
e.target.classList.remove('dragging');
clearDropIndicators();
}
}
function clearDropIndicators() {
document.querySelectorAll('.drop-indicator').forEach(indicator => {
indicator.style.display = 'none';
});
document.querySelectorAll('.column').forEach(column => {
column.classList.remove('drop-target');
});
}
function renderCards() {
// Filter cards by search query
const filteredCards = cards.filter(card =>
card.title.toLowerCase().includes(searchQuery)
);
// Clear containers
todoCardsContainer.innerHTML = '';
inprogressCardsContainer.innerHTML = '';
doneCardsContainer.innerHTML = '';
// Group cards by column
const columns = {
todo: [],
inprogress: [],
done: []
};
filteredCards.forEach(card => {
columns[card.column].push(card);
});
// Render cards for each column
renderColumnCards(todoCardsContainer, columns.todo, 'todo');
renderColumnCards(inprogressCardsContainer, columns.inprogress, 'inprogress');
renderColumnCards(doneCardsContainer, columns.done, 'done');
}
function renderColumnCards(container, cards, columnId) {
cards.forEach(card => {
const cardElement = createCardElement(card);
container.appendChild(cardElement);
});
}
function createCardElement(card) {
const cardElement = document.createElement('div');
cardElement.className = 'card';
cardElement.draggable = true;
cardElement.dataset.cardId = card.id;
const priorityClass = `priority-${card.priority}`;
cardElement.innerHTML = `
<div class="card-header">
<span class="card-title">${escapeHtml(card.title)}</span>
<button class="delete-btn" data-card-id="${card.id}">✕</button>
</div>
<span class="priority-badge ${priorityClass}">${card.priority}</span>
`;
// Add delete event listener
cardElement.querySelector('.delete-btn').addEventListener('click', (e) => {
e.stopPropagation();
cards = cards.filter(c => c.id !== card.id);
renderCards();
updateCounts();
});
return cardElement;
}
function updateCounts() {
const todoCountValue = cards.filter(card => card.column === 'todo').length;
const inprogressCountValue = cards.filter(card => card.column === 'inprogress').length;
const doneCountValue = cards.filter(card => card.column === 'done').length;
todoCount.textContent = todoCountValue;
inprogressCount.textContent = inprogressCountValue;
doneCount.textContent = doneCountValue;
}
function escapeHtml(unsafe) {
return unsafe
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
});
</script>
</body>
</html>