Models 44

GLM 5.3

by Z.aiReasoningClean
Open in new window

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

How it went

Total time
31.8 s
Cost
$0.016
Output tokens
4,567
Spent thinking
44 tokens
Speed
146.5 tok/s
Console errors
0
First token after
655 ms
First visible text after
1.1 s
Prompt tokens
493
Code size
14.9 KB
Finish reason
stop
Served by
InferenceNet
Model id
z-ai/glm-5.3
Reasoning sent
{"effort":"low"}
Max output
943,718 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 · 363 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:#eef1f6; --board:#e4e8f0; --surface:#ffffff; --text:#1c2333;
    --muted:#6b7280; --border:#d6dbe6; --accent:#5b6cff; --shadow:0 6px 20px rgba(20,30,60,.10);
    --col-hue:215;
  }
  html[data-theme="dark"]{
    --bg:#0e1117; --board:#141926; --surface:#1b2130; --text:#e8ecf6;
    --muted:#8a93a8; --border:#2a3145; --accent:#7d8cff; --shadow:0 6px 20px rgba(0,0,0,.35);
  }
  *{box-sizing:border-box;margin:0;padding:0}
  body{
    font-family:"Avenir Next","Segoe UI",system-ui,-apple-system,sans-serif;
    background:var(--bg); color:var(--text); min-height:100vh;
    transition:background .3s,color .3s;
  }
  header{
    display:flex; align-items:center; gap:16px; flex-wrap:wrap;
    padding:20px 28px;
  }
  h1{font-size:22px; letter-spacing:.5px; font-weight:700}
  h1 span{color:var(--accent)}
  .spacer{flex:1}
  .search{
    position:relative;
  }
  .search input{
    padding:10px 14px 10px 36px; border-radius:10px; border:1px solid var(--border);
    background:var(--surface); color:var(--text); font-size:14px; width:230px;
    outline:none; transition:border-color .2s, box-shadow .2s;
  }
  .search input:focus{border-color:var(--accent); box-shadow:0 0 0 3px color-mix(in srgb, var(--accent) 20%, transparent)}
  .search svg{position:absolute; left:11px; top:50%; transform:translateY(-50%); opacity:.5}
  button{font:inherit; cursor:pointer; border:none; background:none; color:inherit}
  .icon-btn{
    width:38px; height:38px; border-radius:10px; border:1px solid var(--border);
    background:var(--surface); display:grid; place-items:center; transition:transform .15s, border-color .2s;
  }
  .icon-btn:hover{transform:translateY(-1px); border-color:var(--accent)}
  .add-btn{
    padding:10px 18px; border-radius:10px; background:var(--accent); color:#fff; font-weight:600;
    display:flex; align-items:center; gap:8px; box-shadow:var(--shadow); transition:filter .2s, transform .15s;
  }
  .add-btn:hover{filter:brightness(1.1); transform:translateY(-1px)}
  .board{
    display:grid; grid-template-columns:repeat(3,1fr); gap:20px;
    padding:8px 28px 40px; align-items:start;
  }
  .column{
    background:var(--board); border:1px solid var(--border); border-radius:16px;
    padding:14px; min-height:300px; transition:background .25s, border-color .25s;
  }
  .column.drag-over{border-color:var(--accent); background:color-mix(in srgb, var(--accent) 8%, var(--board))}
  .col-head{display:flex; align-items:center; gap:10px; margin:2px 4px 14px}
  .col-dot{width:10px; height:10px; border-radius:50%}
  .col-title{font-weight:700; font-size:15px; text-transform:uppercase; letter-spacing:1.2px}
  .count{
    margin-left:auto; background:var(--surface); border:1px solid var(--border);
    font-size:12px; font-weight:700; padding:2px 10px; border-radius:999px; color:var(--muted);
  }
  .cards{display:flex; flex-direction:column; gap:10px; min-height:60px}
  .card{
    background:var(--surface); border:1px solid var(--border); border-radius:12px;
    padding:12px 14px; box-shadow:var(--shadow); position:relative;
    display:flex; align-items:flex-start; gap:10px;
    animation:pop .25s ease; transition:opacity .2s, transform .15s;
  }
  @keyframes pop{from{opacity:0; transform:translateY(6px) scale(.98)} to{opacity:1; transform:none}}
  .card.dragging{opacity:.35; transform:rotate(1.5deg)}
  .card.hidden-by-search{display:none}
  .card-title{font-size:14px; font-weight:600; line-height:1.4; flex:1}
  .badge{
    font-size:10.5px; font-weight:700; text-transform:uppercase; letter-spacing:.8px;
    padding:3px 8px; border-radius:999px; flex-shrink:0; margin-top:1px;
  }
  .badge.high{background:#fde2e2; color:#b91c1c}
  .badge.medium{background:#fef0d6; color:#92600a}
  .badge.low{background:#d8f0dc; color:#1b6e2f}
  html[data-theme="dark"] .badge.high{background:#4a1f22; color:#ff9d9d}
  html[data-theme="dark"] .badge.medium{background:#4a3a14; color:#f5c66b}
  html[data-theme="dark"] .badge.low{background:#1d3a24; color:#8ce6a3}
  .del{
    opacity:0; border-radius:6px; width:22px; height:22px; display:grid; place-items:center;
    color:var(--muted); flex-shrink:0; transition:opacity .15s, background .15s;
  }
  .card:hover .del{opacity:1}
  .del:hover{background:#fde2e2; color:#b91c1c}
  html[data-theme="dark"] .del:hover{background:#4a1f22; color:#ff9d9d}
  .drop-indicator{
    height:3px; border-radius:99px; background:var(--accent); margin:2px 0;
    box-shadow:0 0 8px var(--accent); animation:pop .15s ease;
  }
  .empty-note{color:var(--muted); font-size:13px; text-align:center; padding:22px 8px; font-style:italic}
  /* modal */
  .overlay{
    position:fixed; inset:0; background:rgba(10,14,25,.5); display:none;
    place-items:center; z-index:50; backdrop-filter:blur(3px);
  }
  .overlay.open{display:grid}
  .modal{
    background:var(--surface); border:1px solid var(--border); border-radius:16px;
    width:min(400px, calc(100vw - 32px)); padding:24px; box-shadow:0 20px 60px rgba(0,0,0,.3);
    animation:pop .2s ease;
  }
  .modal h2{font-size:18px; margin-bottom:18px}
  .modal label{display:block; font-size:12px; font-weight:700; text-transform:uppercase; letter-spacing:1px; color:var(--muted); margin-bottom: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; margin-bottom:16px; outline:none;
  }
  .modal input:focus, .modal select:focus{border-color:var(--accent)}
  .modal-actions{display:flex; gap:10px; justify-content:flex-end; margin-top:6px}
  .btn-ghost{padding:10px 16px; border-radius:10px; border:1px solid var(--border); color:var(--muted)}
  .error{color:#b91c1c; font-size:12.5px; margin:-10px 0 10px; display:none}
  @media (max-width:780px){
    .board{grid-template-columns:1fr; padding:8px 14px 40px}
    header{padding:16px 14px}
    .search input{width:100%}
    .search{flex:1; min-width:140px}
  }
</style>
</head>
<body>

<header>
  <h1><span>◈</span> Flowboard</h1>
  <div class="spacer"></div>
  <div class="search">
    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="7"/><path d="M21 21l-4.3-4.3"/></svg>
    <input id="searchInput" type="text" placeholder="Search cards…">
  </div>
  <button class="icon-btn" id="themeBtn" title="Toggle theme" aria-label="Toggle theme">
    <svg id="themeIcon" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="5"/><path d="M12 1v2M12 21v2M4.2 4.2l1.4 1.4M18.4 18.4l1.4 1.4M1 12h2M21 12h2M4.2 19.8l1.4-1.4M18.4 5.6l1.4-1.4"/></svg>
  </button>
  <button class="add-btn" id="addBtn">
    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M12 5v14M5 12h14"/></svg>
    Add card
  </button>
</header>

<main class="board" id="board"></main>

<div class="overlay" id="overlay">
  <div class="modal">
    <h2>New card</h2>
    <label for="cardTitle">Title *</label>
    <input type="text" id="cardTitleInput" placeholder="e.g. Review pull request" maxlength="80">
    <div class="error" id="titleError">Please enter a title.</div>
    <label for="cardPriority">Priority</label>
    <select id="cardPriority">
      <option value="low">Low</option>
      <option value="medium" selected>Medium</option>
      <option value="high">High</option>
    </select>
    <div class="modal-actions">
      <button class="btn-ghost" id="cancelBtn">Cancel</button>
      <button class="add-btn" id="saveBtn">Add</button>
    </div>
  </div>
</div>

<script>
const COLUMNS = [
  {id:'todo',       title:'To do',       dot:'#f5a623'},
  {id:'inprogress', title:'In progress', dot:'#5b6cff'},
  {id:'done',       title:'Done',        dot:'#2fa96c'},
];

let cards = [
  {id:1, title:'Design new landing page hero section', priority:'high',   col:'todo'},
  {id:2, title:'Write onboarding email sequence',      priority:'medium', col:'todo'},
  {id:3, title:'Fix login redirect loop on Safari',    priority:'high',   col:'inprogress'},
  {id:4, title:'Refactor billing webhook handler',     priority:'low',    col:'inprogress'},
  {id:5, title:'Set up weekly analytics report',        priority:'low',    col:'done'},
  {id:6, title:'Publish v2.0 release notes',           priority:'medium', col:'done'},
];

const board = document.getElementById('board');
const searchInput = document.getElementById('searchInput');
let nextId = 100;
let searchQuery = '';

function render(){
  board.innerHTML = '';
  const q = searchQuery.trim().toLowerCase();
  COLUMNS.forEach(col => {
    const visible = cards.filter(c => c.col === col.id && (!q || c.title.toLowerCase().includes(q)));
    const column = document.createElement('section');
    column.className = 'column';
    column.dataset.col = col.id;
    column.innerHTML = `
      <div class="col-head">
        <span class="col-dot" style="background:${col.dot}"></span>
        <span class="col-title">${col.title}</span>
        <span class="count">${visible.length}</span>
      </div>
      <div class="cards"></div>`;
    const list = column.querySelector('.cards');
    if (visible.length === 0){
      const note = document.createElement('div');
      note.className = 'empty-note';
      note.textContent = q ? 'No matches' : 'Drop cards here';
      list.appendChild(note);
    }
    visible.forEach(card => list.appendChild(makeCardEl(card)));
    board.appendChild(column);
  });
}

function makeCardEl(card){
  const el = document.createElement('div');
  el.className = 'card';
  el.draggable = true;
  el.dataset.id = card.id;
  const badge = document.createElement('span');
  badge.className = 'badge ' + card.priority;
  badge.textContent = card.priority;
  const title = document.createElement('div');
  title.className = 'card-title';
  title.textContent = card.title;
  const del = document.createElement('button');
  del.className = 'del';
  del.title = 'Delete card';
  del.innerHTML = '<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M18 6L6 18M6 6l12 12"/></svg>';
  del.addEventListener('click', () => {
    cards = cards.filter(c => c.id !== card.id);
    render();
  });
  el.append(badge, title, del);

  el.addEventListener('dragstart', e => {
    e.dataTransfer.setData('text/plain', String(card.id));
    e.dataTransfer.effectAllowed = 'move';
    requestAnimationFrame(() => el.classList.add('dragging'));
  });
  el.addEventListener('dragend', () => {
    el.classList.remove('dragging');
    clearIndicators();
  });
  return el;
}

function clearIndicators(){
  document.querySelectorAll('.drop-indicator').forEach(n => n.remove());
  document.querySelectorAll('.drag-over').forEach(n => n.classList.remove('drag-over'));
}

board.addEventListener('dragover', e => {
  e.preventDefault();
  e.dataTransfer.dropEffect = 'move';
  clearIndicators();
  const colEl = e.target.closest('.column');
  if (!colEl) return;
  colEl.classList.add('drag-over');
  const cardsWrap = colEl.querySelector('.cards');
  const cards = [...cardsWrap.querySelectorAll('.card:not(.dragging)')];
  const after = cards.find(c => {
    const r = c.getBoundingClientRect();
    return e.clientY < r.top + r.height / 2;
  });
  const ind = document.createElement('div');
  ind.className = 'drop-indicator';
  cardsWrap.insertBefore(ind, after || cardsWrap.querySelector('.empty-note') || null);
});

board.addEventListener('dragleave', e => {
  if (!e.relatedTarget || !e.relatedTarget.closest('.column')) clearIndicators();
});

board.addEventListener('drop', e => {
  e.preventDefault();
  const id = parseInt(e.dataTransfer.getData('text/plain'), 10);
  const card = cards.find(c => c.id === id);
  const colEl = e.target.closest('.column');
  if (!card || !colEl) return;
  card.col = colEl.dataset.col;
  // reorder within column based on indicator position
  const ind = colEl.querySelector('.drop-indicator');
  const wrap = colEl.querySelector('.cards');
  const idsInCol = [...wrap.children]
    .filter(n => n.classList.contains('card') && n.dataset.id !== String(id))
    .map(n => parseInt(n.dataset.id, 10));
  const beforeCards = ind ? [...wrap.children].slice(0, [...wrap.children].indexOf(ind)) : [];
  let insertIdx = 0;
  for (const node of beforeCards){
    if (node.classList.contains('card')){
      const nid = parseInt(node.dataset.id, 10);
      if (idsInCol.includes(nid)) insertIdx = idsInCol.indexOf(nid) + 1;
    }
  }
  const others = cards.filter(c => c.col === card.col && c.id !== id);
  const ordered = [];
  const usedIds = new Set(idsInCol);
  others.forEach(c => { if (usedIds.has(c.id)) ordered[idsInCol.indexOf(c.id)] = c; });
  const finalList = ordered.filter(Boolean);
  finalList.splice(insertIdx, 0, card);
  cards = cards.filter(c => c.col !== card.col);
  cards.push(...finalList);
  clearIndicators();
  render();
});

/* search */
searchInput.addEventListener('input', () => {
  searchQuery = searchInput.value;
  render();
});

/* theme toggle */
const themeBtn = document.getElementById('themeBtn');
const themeIcon = document.getElementById('themeIcon');
const SUN = '<circle cx="12" cy="12" r="5"/><path d="M12 1v2M12 21v2M4.2 4.2l1.4 1.4M18.4 18.4l1.4 1.4M1 12h2M21 12h2M4.2 19.8l1.4-1.4M18.4 5.6l1.4-1.4"/>';
const MOON = '<path d="M21 12.8A9 9 0 1111.2 3a7 7 0 009.8 9.8z"/>';
themeBtn.addEventListener('click', () => {
  const dark = document.documentElement.dataset.theme === 'dark';
  document.documentElement.dataset.theme = dark ? 'light' : 'dark';
  themeIcon.innerHTML = dark ? SUN : MOON;
});

/* modal */
const overlay = document.getElementById('overlay');
const titleInput = document.getElementById('cardTitleInput');
const priorityInput = document.getElementById('cardPriority');
const errorEl = document.getElementById('titleError');

function openModal(){
  overlay.classList.add('open');
  titleInput.value = '';
  priorityInput.value = 'medium';
  errorEl.style.display = 'none';
  titleInput.focus();
}
function closeModal(){ overlay.classList.remove('open'); }

document.getElementById('addBtn').addEventListener('click', openModal);
document.getElementById('cancelBtn').addEventListener('click', closeModal);
overlay.addEventListener('click', e => { if (e.target === overlay) closeModal(); });
document.addEventListener('keydown', e => { if (e.key === 'Escape') closeModal(); });

function save(){
  const title = titleInput.value.trim();
  if (!title){ errorEl.style.display = 'block'; titleInput.focus(); return; }
  cards.push({id: nextId++, title, priority: priorityInput.value, col: 'todo'});
  searchInput.value = '';
  searchQuery = '';
  closeModal();
  render();
  const newCard = board.querySelector(`.card[data-id="${nextId - 1}"]`);
  if (newCard) newCard.scrollIntoView({behavior:'smooth', block:'nearest'});
}
document.getElementById('saveBtn').addEventListener('click', save);
titleInput.addEventListener('keydown', e => { if (e.key === 'Enter') save(); });

render();
</script>
</body>
</html>
Reasoning trace (44 tokens)
Let me build a polished Kanban board. Design should feel crafted: nice typography, distinct theme, drag-drop with indicator, modal, search, counts, priority badges, theme toggle.

Write compact but complete code.