Claude Sonnet 5.5
by Anthropicreasoning defaultClean
Running live in a sandboxed frame. Click inside it before using the keyboard.
How it went
- Total time
- 45.2 s
- Cost
- $0.079
- Output tokens
- 7,776
- Spent thinking
- 981 tokens
- Speed
- 180.9 tok/s
- Console errors
- 0
- First token after
- 2.2 s
- First visible text after
- 10.4 s
- Prompt tokens
- 745
- Code size
- 15.4 KB
- Finish reason
- stop
- Served by
- Claude Platform on AWS
- Model id
anthropic/claude-sonnet-5.5- Reasoning sent
model default- Max output
- 128,000 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 · 312 lines
<!DOCTYPE html>
<html lang="en" data-theme="light">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Kanban Board</title>
<style>
:root{
--bg:#f3f4f8; --surface:#ffffff; --col:#e8eaf1; --text:#1c2033; --muted:#6b7190;
--border:#d9dce8; --accent:#5b5bf0; --accent-t:#fff; --shadow:0 1px 2px rgba(20,24,50,.08),0 4px 12px rgba(20,24,50,.06);
--low-bg:#dcf5e5; --low-fg:#17753d;
--med-bg:#fff0cc; --med-fg:#8a5a00;
--high-bg:#ffdcdc; --high-fg:#b3202a;
--danger:#e5484d;
}
[data-theme="dark"]{
--bg:#0f111a; --surface:#1d2132; --col:#161927; --text:#e9ebf5; --muted:#8e94b3;
--border:#2c3148; --accent:#7c7cff; --accent-t:#0f111a; --shadow:0 1px 2px rgba(0,0,0,.4),0 6px 16px rgba(0,0,0,.25);
--low-bg:#14392395; --low-fg:#6fdc99;
--med-bg:#4a380d95; --med-fg:#f5c555;
--high-bg:#53191d95; --high-fg:#ff8a90;
}
*{box-sizing:border-box}
html,body{margin:0;min-height:100%}
body{
background:var(--bg); color:var(--text);
font:15px/1.4 system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
transition:background .25s,color .25s;
display:flex; flex-direction:column; min-height:100vh; overflow-x:hidden;
}
header{
display:flex; flex-wrap:wrap; align-items:center; gap:12px;
padding:18px 24px;
}
.brand{display:flex; align-items:center; gap:10px; font-weight:700; font-size:20px; margin-right:auto}
.logo{width:30px;height:30px;border-radius:8px;background:linear-gradient(135deg,var(--accent),#e05fd0);display:grid;place-items:center;color:#fff;font-size:16px}
.search{position:relative; flex:0 1 280px; min-width:140px}
.search input{
width:100%; padding:9px 12px 9px 34px; border-radius:10px; border:1px solid var(--border);
background:var(--surface); color:var(--text); font:inherit; outline:none;
}
.search input:focus,.modal input[type=text]:focus{border-color:var(--accent); box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 25%,transparent)}
.search svg{position:absolute;left:10px;top:50%;transform:translateY(-50%);width:16px;height:16px;color:var(--muted)}
button{font:inherit;color:inherit;cursor:pointer}
.btn{padding:9px 16px;border-radius:10px;border:1px solid var(--border);background:var(--surface);font-weight:600}
.btn:hover{border-color:var(--accent)}
.btn.primary{background:var(--accent);color:var(--accent-t);border-color:var(--accent)}
.btn.primary:hover{filter:brightness(1.08)}
.icon-btn{width:38px;height:38px;border-radius:10px;border:1px solid var(--border);background:var(--surface);display:grid;place-items:center;font-size:17px}
.icon-btn:hover{border-color:var(--accent)}
main{
flex:1; display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:18px;
padding:6px 24px 24px; align-items:start;
}
.column{
background:var(--col); border:2px solid transparent; border-radius:16px; padding:12px;
transition:border-color .15s, background .15s; min-height:200px;
}
.column.over{border-color:var(--accent); background:color-mix(in srgb,var(--accent) 8%,var(--col))}
.col-head{display:flex;align-items:center;gap:8px;padding:4px 6px 12px}
.dot{width:10px;height:10px;border-radius:50%}
.col-head h2{font-size:14px;letter-spacing:.04em;text-transform:uppercase;margin:0;font-weight:700}
.count{margin-left:auto;background:var(--surface);border:1px solid var(--border);color:var(--muted);
min-width:26px;text-align:center;padding:1px 8px;border-radius:99px;font-size:13px;font-weight:700}
.list{display:flex;flex-direction:column;gap:10px;min-height:80px}
.card{
background:var(--surface); border:1px solid var(--border); border-radius:12px; padding:12px 12px 12px 14px;
box-shadow:var(--shadow); cursor:grab; position:relative;
display:flex; flex-direction:column; gap:10px; animation:pop .25s ease;
transition:transform .15s, box-shadow .15s;
}
.card:hover{transform:translateY(-1px)}
.card:active{cursor:grabbing}
.card.dragging{opacity:.35}
.card::before{content:"";position:absolute;left:0;top:10px;bottom:10px;width:3px;border-radius:3px;background:var(--pc)}
.card.low{--pc:var(--low-fg)} .card.medium{--pc:var(--med-fg)} .card.high{--pc:var(--high-fg)}
.card-top{display:flex;gap:8px;align-items:flex-start}
.card-title{flex:1;font-weight:600;word-break:break-word}
.del{border:none;background:transparent;color:var(--muted);width:24px;height:24px;border-radius:6px;font-size:16px;line-height:1;opacity:.6;flex:none}
.del:hover{background:var(--high-bg);color:var(--high-fg);opacity:1}
.badge{align-self:flex-start;font-size:12px;font-weight:700;padding:2px 10px;border-radius:99px;text-transform:capitalize}
.badge.low{background:var(--low-bg);color:var(--low-fg)}
.badge.medium{background:var(--med-bg);color:var(--med-fg)}
.badge.high{background:var(--high-bg);color:var(--high-fg)}
.indicator{height:4px;border-radius:4px;background:var(--accent);box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 28%,transparent);margin:2px 0;flex:none}
.empty{color:var(--muted);text-align:center;padding:22px 8px;border:2px dashed var(--border);border-radius:12px;font-size:14px}
@keyframes pop{from{opacity:0;transform:scale(.96)}to{opacity:1;transform:none}}
.overlay{position:fixed;inset:0;background:rgba(10,12,25,.5);display:none;align-items:center;justify-content:center;padding:16px;z-index:10;backdrop-filter:blur(2px)}
.overlay.open{display:flex}
.modal{background:var(--surface);border:1px solid var(--border);border-radius:16px;padding:22px;width:100%;max-width:400px;box-shadow:0 20px 50px rgba(0,0,0,.35);animation:pop .2s ease}
.modal h3{margin:0 0 14px;font-size:18px}
.modal label.l{display:block;font-size:13px;font-weight:600;color:var(--muted);margin:12px 0 6px}
.modal input[type=text],.modal select{width:100%;padding:10px 12px;border-radius:10px;border:1px solid var(--border);background:var(--bg);color:var(--text);font:inherit;outline:none}
.seg{display:flex;gap:8px}
.seg label{flex:1;position:relative}
.seg input{position:absolute;opacity:0}
.seg span{display:block;text-align:center;padding:8px 0;border-radius:10px;border:1px solid var(--border);cursor:pointer;font-weight:600;text-transform:capitalize;font-size:14px}
.seg input:checked+span{border-color:var(--accent);background:color-mix(in srgb,var(--accent) 15%,transparent)}
.seg input:focus-visible+span{box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 35%,transparent)}
.err{color:var(--danger);font-size:13px;min-height:18px;margin-top:6px}
.actions{display:flex;justify-content:flex-end;gap:10px;margin-top:10px}
@media (max-width:820px){
main{grid-template-columns:1fr;padding:6px 14px 20px}
header{padding:14px}
.search{order:5;flex:1 1 100%}
}
</style>
</head>
<body>
<header>
<div class="brand"><div class="logo">▦</div>Sprint Board</div>
<div class="search">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"><circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/></svg>
<input id="q" type="search" placeholder="Search cards…" aria-label="Search cards by title" autocomplete="off">
</div>
<button class="btn primary" id="addBtn">+ Add card</button>
<button class="icon-btn" id="themeBtn" aria-label="Toggle theme" title="Toggle theme">🌙</button>
</header>
<main id="board"></main>
<div class="overlay" id="overlay">
<form class="modal" id="form" role="dialog" aria-modal="true" aria-labelledby="mt" novalidate>
<h3 id="mt">New card</h3>
<label class="l" for="title">Title *</label>
<input type="text" id="title" maxlength="90" placeholder="e.g. Write release notes" autocomplete="off">
<div class="err" id="err"></div>
<label class="l">Priority</label>
<div class="seg">
<label><input type="radio" name="prio" value="low"><span>low</span></label>
<label><input type="radio" name="prio" value="medium" checked><span>medium</span></label>
<label><input type="radio" name="prio" value="high"><span>high</span></label>
</div>
<label class="l" for="colSel">Column</label>
<select id="colSel"></select>
<div class="actions">
<button type="button" class="btn" id="cancel">Cancel</button>
<button type="submit" class="btn primary">Add card</button>
</div>
</form>
</div>
<script>
(function(){
const COLS = [
{id:'todo', name:'To do', color:'#8e94b3'},
{id:'doing', name:'In progress', color:'#f5a524'},
{id:'done', name:'Done', color:'#2fb869'}
];
let nextId = 1;
const mk = (title, priority, col) => ({id:'c'+(nextId++), title, priority, col});
let cards = [
mk('Design onboarding email sequence','medium','todo'),
mk('Fix checkout crash on Safari 17','high','todo'),
mk('Migrate analytics to new event schema','medium','doing'),
mk('Review accessibility audit findings','low','doing'),
mk('Set up CI pipeline for staging','high','done'),
mk('Update pricing page copy','low','done')
];
let query = '';
let dragId = null;
const board = document.getElementById('board');
const indicator = document.createElement('div');
indicator.className = 'indicator';
function render(){
board.innerHTML = '';
const q = query.trim().toLowerCase();
COLS.forEach(col => {
const all = cards.filter(c => c.col === col.id);
const shown = all.filter(c => c.title.toLowerCase().includes(q));
const sec = document.createElement('section');
sec.className = 'column'; sec.dataset.col = col.id;
const head = document.createElement('div'); head.className = 'col-head';
head.innerHTML = '<span class="dot"></span><h2></h2><span class="count"></span>';
head.querySelector('.dot').style.background = col.color;
head.querySelector('h2').textContent = col.name;
const cnt = head.querySelector('.count');
cnt.textContent = q ? shown.length + '/' + all.length : all.length;
cnt.title = all.length + ' card' + (all.length===1?'':'s');
sec.appendChild(head);
const list = document.createElement('div'); list.className = 'list';
shown.forEach(c => list.appendChild(cardEl(c)));
if(!shown.length){
const e = document.createElement('div'); e.className = 'empty';
e.textContent = q && all.length ? 'No matching cards' : 'Drop cards here';
list.appendChild(e);
}
sec.appendChild(list);
bindColumn(sec, list);
board.appendChild(sec);
});
}
function cardEl(c){
const el = document.createElement('article');
el.className = 'card ' + c.priority; el.draggable = true; el.dataset.id = c.id;
const top = document.createElement('div'); top.className = 'card-top';
const t = document.createElement('div'); t.className = 'card-title'; t.textContent = c.title;
const d = document.createElement('button'); d.className = 'del'; d.type = 'button';
d.innerHTML = '×'; d.setAttribute('aria-label','Delete card: ' + c.title); d.title = 'Delete';
d.addEventListener('click', () => { cards = cards.filter(x => x.id !== c.id); render(); });
d.addEventListener('mousedown', e => e.stopPropagation());
top.append(t, d);
const b = document.createElement('span'); b.className = 'badge ' + c.priority; b.textContent = c.priority;
el.append(top, b);
el.addEventListener('dragstart', e => {
dragId = c.id;
e.dataTransfer.effectAllowed = 'move';
e.dataTransfer.setData('text/plain', c.id);
setTimeout(() => el.classList.add('dragging'), 0);
});
el.addEventListener('dragend', () => { dragId = null; clearDrag(); el.classList.remove('dragging'); });
return el;
}
function clearDrag(){
indicator.remove();
document.querySelectorAll('.column.over').forEach(c => c.classList.remove('over'));
}
function bindColumn(sec, list){
sec.addEventListener('dragover', e => {
if(!dragId) return;
e.preventDefault(); e.dataTransfer.dropEffect = 'move';
document.querySelectorAll('.column.over').forEach(c => { if(c !== sec) c.classList.remove('over'); });
sec.classList.add('over');
const items = [...list.querySelectorAll('.card:not(.dragging)')];
let before = null;
for(const it of items){
const r = it.getBoundingClientRect();
if(e.clientY < r.top + r.height/2){ before = it; break; }
}
const empty = list.querySelector('.empty');
if(before){ if(indicator.nextSibling !== before || indicator.parentNode !== list) list.insertBefore(indicator, before); }
else if(empty){ if(indicator.nextSibling !== empty || indicator.parentNode !== list) list.insertBefore(indicator, empty); }
else if(list.lastElementChild !== indicator) list.appendChild(indicator);
});
sec.addEventListener('dragleave', e => {
if(!sec.contains(e.relatedTarget)){ sec.classList.remove('over'); if(indicator.parentNode === list) indicator.remove(); }
});
sec.addEventListener('drop', e => {
if(!dragId) return;
e.preventDefault();
const next = indicator.parentNode === list ? indicator.nextElementSibling : null;
const beforeId = next && next.dataset ? next.dataset.id : null;
const moving = cards.find(c => c.id === dragId);
if(!moving) return;
cards = cards.filter(c => c !== moving);
moving.col = sec.dataset.col;
let idx;
if(beforeId && cards.some(c => c.id === beforeId)){
idx = cards.findIndex(c => c.id === beforeId);
} else {
let last = -1;
cards.forEach((c,i) => { if(c.col === moving.col) last = i; });
idx = last + 1;
if(last === -1) idx = cards.length;
}
cards.splice(idx, 0, moving);
dragId = null; clearDrag(); render();
});
}
/* Search */
document.getElementById('q').addEventListener('input', e => { query = e.target.value; render(); });
/* Theme */
const themeBtn = document.getElementById('themeBtn');
themeBtn.addEventListener('click', () => {
const dark = document.documentElement.dataset.theme !== 'dark';
document.documentElement.dataset.theme = dark ? 'dark' : 'light';
themeBtn.textContent = dark ? '☀️' : '🌙';
});
/* Modal */
const overlay = document.getElementById('overlay');
const form = document.getElementById('form');
const titleIn = document.getElementById('title');
const err = document.getElementById('err');
const colSel = document.getElementById('colSel');
COLS.forEach(c => { const o = document.createElement('option'); o.value = c.id; o.textContent = c.name; colSel.appendChild(o); });
function openModal(){
form.reset(); err.textContent = ''; colSel.value = 'todo';
overlay.classList.add('open'); setTimeout(() => titleIn.focus(), 0);
}
function closeModal(){ overlay.classList.remove('open'); document.getElementById('addBtn').focus(); }
document.getElementById('addBtn').addEventListener('click', openModal);
document.getElementById('cancel').addEventListener('click', closeModal);
overlay.addEventListener('mousedown', e => { if(e.target === overlay) closeModal(); });
document.addEventListener('keydown', e => { if(e.key === 'Escape' && overlay.classList.contains('open')) closeModal(); });
form.addEventListener('submit', e => {
e.preventDefault();
const title = titleIn.value.trim();
if(!title){ err.textContent = 'Please enter a title.'; titleIn.focus(); return; }
const prio = form.querySelector('input[name=prio]:checked').value;
cards.push(mk(title, prio, colSel.value));
overlay.classList.remove('open');
render();
});
titleIn.addEventListener('input', () => err.textContent = '');
render();
})();
</script>
</body>
</html>Reasoning trace (981 tokens)
I'm putting together a single-file Kanban board with columns that show card counts, six starter cards, and priority badges. I also want an add modal, delete, drag and drop with a drop indicator between cards, a search filter, and a theme toggle, and I'm weighing whether HTML5 drag and drop or pointer events will work best inside the sandbox. I'm settling on HTML5 drag and drop with a placeholder line between cards, calculating the drop position from card midpoints and updating the card array when a drop lands. I'll re-render only after the drop, with cleanup on dragend, and keep the search filter working alongside it. Next I'm setting the theme to CSS variables with a light default, and laying out the header, a three-column board that stacks on narrow screens, and a modal with a priority selector. Then I'll write the code, using textContent for user-entered text. For drag and drop, I'll set the card's data on dragstart and show a placeholder indicator while dragging over a column. I'm adding a delete button on each card, plus a "+ Add card" action that opens the modal with a column selector.