Models 44

Muse Ember

Open in new window

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

How it went

Total time
24.4 s
Cost
$0.0069
Output tokens
13,683
Spent thinking
3,887 tokens
Speed
616.5 tok/s
Console errors
0
First token after
2.2 s
First visible text after
11.4 s
Prompt tokens
511
Code size
32.2 KB
Finish reason
stop
Served by
Meta
Model id
meta/muse-ember
Reasoning sent
{"effort":"xhigh"}
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 · 680 lines

<!DOCTYPE html>
<html lang="en" data-theme="light">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>FlowBoard — Kanban Board</title>
<style>
*{box-sizing:border-box;margin:0;padding:0}
:root{
  --bg:#f3f5fb;--bg2:#eef1f9;--surface:#ffffff;--surface2:#f8fafc;--surface3:#eef2f7;
  --text:#0f172a;--muted:#64748b;--muted2:#94a3b8;--border:#e2e8f0;--border2:#cbd5e1;
  --accent:#6366f1;--accent2:#8b5cf6;--accent-soft:#eef2ff;
  --low-bg:#dcfce7;--low-text:#166534;--low-dot:#22c55e;
  --med-bg:#fef3c7;--med-text:#92400e;--med-dot:#f59e0b;
  --high-bg:#fee2e2;--high-text:#991b1b;--high-dot:#ef4444;
  --shadow:0 1px 2px rgba(15,23,42,.05),0 8px 24px rgba(15,23,42,.06);
  --shadow2:0 12px 32px rgba(15,23,42,.12);
  --header-bg:rgba(255,255,255,.82);
}
[data-theme="dark"]{
  --bg:#0b1220;--bg2:#0f172a;--surface:#131c30;--surface2:#0f172a;--surface3:#1a2742;
  --text:#e5e7eb;--muted:#94a3b8;--muted2:#64748b;--border:#1f2a44;--border2:#2a3a5c;
  --accent:#818cf8;--accent2:#a78bfa;--accent-soft:#1e1b4b;
  --low-bg:rgba(34,197,94,.18);--low-text:#86efac;--low-dot:#22c55e;
  --med-bg:rgba(245,158,11,.18);--med-text:#fcd34d;--med-dot:#f59e0b;
  --high-bg:rgba(239,68,68,.18);--high-text:#fca5a5;--high-dot:#ef4444;
  --shadow:0 1px 2px rgba(0,0,0,.3),0 8px 24px rgba(0,0,0,.25);
  --shadow2:0 12px 32px rgba(0,0,0,.45);
  --header-bg:rgba(11,18,32,.82);
}
html{scroll-behavior:smooth}
body{
  font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Inter,Roboto,Helvetica,Arial,sans-serif;
  background:
    radial-gradient(700px 400px at 15% -10%, rgba(99,102,241,.14), transparent 60%),
    radial-gradient(700px 400px at 90% 0%, rgba(139,92,246,.10), transparent 55%),
    var(--bg);
  color:var(--text);min-height:100vh;overflow-x:hidden;transition:background .3s,color .3s;
  -webkit-font-smoothing:antialiased;
}
button{font-family:inherit;cursor:pointer;border:none;background:none;color:inherit}
input,textarea,select{font-family:inherit;color:inherit}

/* HEADER */
header{
  position:sticky;top:0;z-index:40;backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);
  background:var(--header-bg);border-bottom:1px solid var(--border);
}
.header-inner{max-width:1280px;margin:0 auto;padding:14px 22px;display:flex;align-items:center;gap:16px;flex-wrap:wrap}
.logo{display:flex;align-items:center;gap:11px;min-width:0}
.logo-tile{
  width:40px;height:40px;border-radius:11px;flex:0 0 40px;display:grid;place-items:center;color:#fff;
  background:linear-gradient(135deg,#6366f1,#8b5cf6 55%,#ec4899);
  box-shadow:0 6px 16px rgba(99,102,241,.35);font-size:19px;font-weight:800;
}
.logo h1{font-size:20px;letter-spacing:-.03em;line-height:1}
.logo p{font-size:11.5px;color:var(--muted);margin-top:3px;font-weight:500}
.search-wrap{position:relative;flex:1 1 280px;max-width:460px;margin-left:auto}
.search-wrap svg{position:absolute;left:12px;top:50%;transform:translateY(-50%);width:17px;height:17px;color:var(--muted2);pointer-events:none}
#searchInput{
  width:100%;height:42px;border-radius:999px;border:1px solid var(--border);background:var(--surface);
  padding:0 38px 0 40px;font-size:14px;outline:none;transition:.2s;box-shadow:0 1px 2px rgba(0,0,0,.03);
}
#searchInput::placeholder{color:var(--muted2)}
#searchInput:focus{border-color:var(--accent);box-shadow:0 0 0 4px color-mix(in srgb,var(--accent) 16%,transparent)}
#clearSearch{
  position:absolute;right:6px;top:50%;transform:translateY(-50%);width:28px;height:28px;border-radius:50%;
  display:none;place-items:center;color:var(--muted);font-size:16px;line-height:1;
}
#clearSearch:hover{background:var(--surface3);color:var(--text)}
#clearSearch.show{display:grid}
.icon-btn{
  width:42px;height:42px;border-radius:50%;border:1px solid var(--border);background:var(--surface);
  display:grid;place-items:center;font-size:17px;flex:0 0 42px;transition:.2s;box-shadow:var(--shadow);
}
.icon-btn:hover{transform:translateY(-1px);border-color:var(--border2)}
.btn-primary{
  height:42px;padding:0 18px;border-radius:999px;color:#fff;font-weight:700;font-size:14px;
  background:linear-gradient(135deg,#6366f1,#8b5cf6);box-shadow:0 8px 20px rgba(99,102,241,.32);
  display:inline-flex;align-items:center;gap:7px;transition:.2s;white-space:nowrap;
}
.btn-primary:hover{transform:translateY(-1px);box-shadow:0 10px 24px rgba(99,102,241,.4)}
.btn-primary:active{transform:translateY(0)}

/* MAIN */
main{max-width:1280px;margin:0 auto;padding:24px 22px 40px}
.hero{display:flex;align-items:flex-end;justify-content:space-between;gap:20px;flex-wrap:wrap;margin-bottom:20px}
.hero h2{font-size:30px;letter-spacing:-.04em;line-height:1.05}
.hero h2 span{background:linear-gradient(90deg,var(--accent),var(--accent2));-webkit-background-clip:text;background-clip:text;color:transparent}
.hero-sub{color:var(--muted);font-size:14px;margin-top:7px}
.progress-card{
  background:var(--surface);border:1px solid var(--border);border-radius:16px;padding:14px 16px;
  box-shadow:var(--shadow);min-width:280px;flex:0 1 340px;
}
.progress-card-row{display:flex;justify-content:space-between;align-items:baseline;margin-bottom:9px}
.progress-card strong{font-size:13px;letter-spacing:-.01em}
.progress-card span{font-size:12px;color:var(--muted);font-weight:600}
.progress-track{height:8px;border-radius:999px;background:var(--surface3);overflow:hidden}
.progress-fill{height:100%;width:0%;border-radius:999px;background:linear-gradient(90deg,#22c55e,#10b981);transition:width .5s cubic-bezier(.2,.8,.2,1)}
.progress-meta{display:flex;gap:14px;margin-top:9px;font-size:12px;color:var(--muted);font-weight:500}
.progress-meta b{color:var(--text)}
#searchMeta{font-size:12.5px;color:var(--muted);margin:-6px 0 14px;display:none}
#searchMeta.show{display:block}
#searchMeta b{color:var(--accent)}

/* BOARD */
.board{display:grid;grid-template-columns:repeat(3,1fr);gap:18px;align-items:start}
.column{
  background:color-mix(in srgb,var(--surface) 72%,transparent);border:1px solid var(--border);border-radius:18px;
  padding:14px;box-shadow:var(--shadow);transition:.2s;min-width:0;
}
.column.drag-active{border-color:var(--accent);background:color-mix(in srgb,var(--accent-soft) 55%,var(--surface));box-shadow:0 0 0 4px color-mix(in srgb,var(--accent) 12%,transparent),var(--shadow2)}
.col-head{display:flex;align-items:center;gap:9px;padding:2px 4px 13px;border-bottom:1px dashed var(--border);margin-bottom:12px}
.col-dot{width:9px;height:9px;border-radius:50%;flex:0 0 9px}
.col-todo .col-dot{background:#3b82f6;box-shadow:0 0 0 4px rgba(59,130,246,.16)}
.col-progress .col-dot{background:#f59e0b;box-shadow:0 0 0 4px rgba(245,158,11,.16)}
.col-done .col-dot{background:#22c55e;box-shadow:0 0 0 4px rgba(34,197,94,.16)}
.col-head h3{font-size:15px;letter-spacing:-.02em}
.count-pill{
  margin-left:auto;min-width:26px;height:24px;padding:0 8px;border-radius:999px;display:grid;place-items:center;
  background:var(--surface3);border:1px solid var(--border);font-size:12.5px;font-weight:800;color:var(--muted);
}
.col-add{width:28px;height:28px;border-radius:50%;display:grid;place-items:center;font-size:18px;color:var(--muted);transition:.15s;line-height:1}
.col-add:hover{background:var(--accent);color:#fff;transform:rotate(90deg)}
.cards-list{min-height:150px;display:flex;flex-direction:column;gap:11px}
.cards-list.drag-over{background:color-mix(in srgb,var(--accent) 5%,transparent);border-radius:10px}

/* CARD */
.card{
  background:var(--surface);border:1px solid var(--border);border-radius:14px;padding:14px 14px 12px;
  box-shadow:var(--shadow);cursor:grab;position:relative;transition:transform .18s,box-shadow .18s,border-color .18s;
  animation:fadeUp .45s both;
}
@keyframes fadeUp{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}
.card:hover{transform:translateY(-2px);box-shadow:var(--shadow2);border-color:var(--border2)}
.card:active{cursor:grabbing}
.card.dragging{opacity:.38;transform:rotate(2deg) scale(.98);box-shadow:none;border-style:dashed}
.card-top{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:9px}
.badge{display:inline-flex;align-items:center;gap:6px;height:22px;padding:0 9px;border-radius:999px;font-size:10.5px;font-weight:800;letter-spacing:.06em;text-transform:uppercase}
.badge::before{content:"";width:6px;height:6px;border-radius:50%;background:currentColor}
.badge-low{background:var(--low-bg);color:var(--low-text)}
.badge-medium{background:var(--med-bg);color:var(--med-text)}
.badge-high{background:var(--high-bg);color:var(--high-text)}
.delete-btn{
  width:26px;height:26px;border-radius:50%;display:grid;place-items:center;color:var(--muted2);font-size:15px;line-height:1;
  opacity:0;transition:.15s;flex:0 0 26px;
}
.card:hover .delete-btn,.card:focus-within .delete-btn{opacity:1}
.delete-btn:hover{background:#fee2e2;color:#dc2626;transform:scale(1.08)}
[data-theme="dark"] .delete-btn:hover{background:rgba(239,68,68,.2);color:#fca5a5}
.card h4{font-size:15px;line-height:1.3;letter-spacing:-.015em;margin-bottom:6px;padding-right:4px}
.card p{font-size:12.8px;line-height:1.5;color:var(--muted);margin-bottom:12px}
.card-bottom{display:flex;align-items:center;justify-content:space-between;gap:8px}
.assignee{display:flex;align-items:center;gap:7px;font-size:12px;color:var(--muted);font-weight:600;min-width:0}
.avatar{width:26px;height:26px;border-radius:50%;display:grid;place-items:center;color:#fff;font-size:10px;font-weight:800;flex:0 0 26px;letter-spacing:.02em}
.due{font-size:11.5px;color:var(--muted2);font-weight:600;white-space:nowrap;display:flex;align-items:center;gap:4px}
.empty-state{
  border:1.5px dashed var(--border2);border-radius:14px;padding:22px 14px;text-align:center;color:var(--muted2);
  font-size:13px;line-height:1.5;
}
.empty-state .big{font-size:20px;display:block;margin-bottom:5px;opacity:.7}
.drop-indicator{
  height:4px;border-radius:999px;background:linear-gradient(90deg,var(--accent),var(--accent2));
  box-shadow:0 0 0 4px color-mix(in srgb,var(--accent) 18%,transparent),0 4px 14px rgba(99,102,241,.45);
  margin:2px 2px;position:relative;flex:0 0 4px;animation:pulse 1s ease-in-out infinite;
}
@keyframes pulse{0%,100%{transform:scaleX(1)}50%{transform:scaleX(.96)}}
.col-foot{width:100%;margin-top:12px;height:38px;border-radius:10px;color:var(--muted);font-size:13px;font-weight:600;transition:.15s}
.col-foot:hover{background:var(--surface3);color:var(--accent)}

/* MODAL */
.modal-overlay{
  position:fixed;inset:0;background:rgba(15,23,42,.48);backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
  display:none;align-items:center;justify-content:center;padding:18px;z-index:100;
}
.modal-overlay.open{display:flex}
.modal{
  width:100%;max-width:460px;background:var(--surface);border:1px solid var(--border);border-radius:20px;
  box-shadow:0 24px 60px rgba(0,0,0,.28);padding:22px;animation:pop .25s cubic-bezier(.2,.9,.3,1.2);
  max-height:calc(100vh - 36px);overflow-y:auto;
}
@keyframes pop{from{opacity:0;transform:translateY(14px) scale(.97)}to{opacity:1;transform:translateY(0) scale(1)}}
.modal-head{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;margin-bottom:4px}
.modal-head h3{font-size:19px;letter-spacing:-.03em}
.modal-head p{font-size:13px;color:var(--muted);margin-top:4px}
.modal-close{width:32px;height:32px;border-radius:50%;display:grid;place-items:center;color:var(--muted);font-size:16px;flex:0 0 32px}
.modal-close:hover{background:var(--surface3);color:var(--text)}
.field{margin-top:16px}
.field label{display:block;font-size:12px;font-weight:800;letter-spacing:.05em;text-transform:uppercase;color:var(--muted);margin-bottom:7px}
.field input[type="text"],.field textarea{
  width:100%;border:1px solid var(--border);background:var(--surface2);border-radius:11px;padding:11px 13px;font-size:14px;outline:none;transition:.2s;resize:vertical;
}
.field input:focus,.field textarea:focus{border-color:var(--accent);box-shadow:0 0 0 4px color-mix(in srgb,var(--accent) 14%,transparent);background:var(--surface)}
.field input.error{border-color:#ef4444;box-shadow:0 0 0 4px rgba(239,68,68,.14);animation:shake .3s}
@keyframes shake{0%,100%{transform:translateX(0)}25%{transform:translateX(-5px)}75%{transform:translateX(5px)}}
.error-msg{display:none;color:#dc2626;font-size:12.5px;font-weight:600;margin-top:6px}
.error-msg.show{display:block}
.pills{display:flex;gap:8px;flex-wrap:wrap}
.pill{
  height:36px;padding:0 15px;border-radius:999px;border:1px solid var(--border);background:var(--surface2);
  font-size:13px;font-weight:700;color:var(--muted);display:inline-flex;align-items:center;gap:7px;transition:.15s;
}
.pill::before{content:"";width:8px;height:8px;border-radius:50%}
.pill[data-priority="low"]::before{background:var(--low-dot)}
.pill[data-priority="medium"]::before{background:var(--med-dot)}
.pill[data-priority="high"]::before{background:var(--high-dot)}
.pill.active[data-priority="low"]{background:var(--low-bg);color:var(--low-text);border-color:var(--low-dot)}
.pill.active[data-priority="medium"]{background:var(--med-bg);color:var(--med-text);border-color:var(--med-dot)}
.pill.active[data-priority="high"]{background:var(--high-bg);color:var(--high-text);border-color:var(--high-dot)}
.pill.col-pill::before{display:none}
.pill.col-pill.active{background:var(--accent-soft);color:var(--accent);border-color:var(--accent)}
.modal-actions{display:flex;gap:10px;margin-top:22px}
.btn-cancel{flex:1;height:44px;border-radius:11px;border:1px solid var(--border);background:var(--surface2);font-weight:700;font-size:14px;transition:.15s}
.btn-cancel:hover{background:var(--surface3)}
.btn-submit{flex:1.4;height:44px;border-radius:11px;color:#fff;font-weight:700;font-size:14px;background:linear-gradient(135deg,#6366f1,#8b5cf6);box-shadow:0 8px 20px rgba(99,102,241,.3);transition:.15s}
.btn-submit:hover{transform:translateY(-1px)}

/* TOAST */
.toast{
  position:fixed;left:50%;bottom:22px;transform:translate(-50%,20px);background:#0f172a;color:#fff;
  padding:11px 18px;border-radius:999px;font-size:13.5px;font-weight:600;box-shadow:0 14px 34px rgba(0,0,0,.3);
  opacity:0;pointer-events:none;transition:.3s;z-index:200;display:flex;align-items:center;gap:8px;max-width:calc(100vw - 32px);text-align:center;
}
.toast.show{opacity:1;transform:translate(-50%,0)}
footer{text-align:center;color:var(--muted2);font-size:12px;padding:6px 20px 26px}

@media(max-width:900px){
  .board{grid-template-columns:1fr}
  .search-wrap{margin-left:0;max-width:none;order:3;flex-basis:100%}
  .hero h2{font-size:25px}
  .progress-card{flex-basis:100%}
}
@media(max-width:480px){
  .header-inner{padding:12px 14px;gap:10px}
  main{padding:18px 14px 30px}
  .logo p{display:none}
  .btn-primary{padding:0 14px;font-size:13px}
  .modal{padding:18px}
  .modal-actions{flex-direction:column}
}
</style>
</head>
<body>

<header>
  <div class="header-inner">
    <div class="logo">
      <div class="logo-tile">◧</div>
      <div>
        <h1>FlowBoard</h1>
        <p>Kanban · Sprint 24</p>
      </div>
    </div>

    <div class="search-wrap">
      <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="M21 21l-4.3-4.3"/></svg>
      <input id="searchInput" type="text" placeholder="Search cards by title…" aria-label="Search cards by title" autocomplete="off">
      <button id="clearSearch" aria-label="Clear search">×</button>
    </div>

    <button class="icon-btn" id="themeToggle" aria-label="Toggle light / dark theme" title="Toggle theme">🌙</button>
    <button class="btn-primary" id="addCardBtn"><span style="font-size:17px;line-height:1">+</span> Add card</button>
  </div>
</header>

<main>
  <div class="hero">
    <div>
      <h2>Project <span>Board</span></h2>
      <p class="hero-sub">Drag cards between columns to update progress. Click + to add, × to delete.</p>
    </div>
    <div class="progress-card">
      <div class="progress-card-row"><strong>Sprint progress</strong><span id="progressLabel">0 of 0 done</span></div>
      <div class="progress-track"><div class="progress-fill" id="progressFill"></div></div>
      <div class="progress-meta"><span><b id="statTodo">0</b> to do</span><span><b id="statProg">0</b> in progress</span><span><b id="statDone">0</b> done</span></div>
    </div>
  </div>

  <p id="searchMeta"></p>

  <section class="board" id="board">
    <div class="column col-todo" data-col="todo">
      <div class="col-head"><span class="col-dot"></span><h3>To do</h3><span class="count-pill" id="count-todo">0</span><button class="col-add" data-add-col="todo" aria-label="Add card to To do">+</button></div>
      <div class="cards-list" data-col="todo"></div>
      <button class="col-foot" data-add-col="todo">+ Add a card</button>
    </div>

    <div class="column col-progress" data-col="progress">
      <div class="col-head"><span class="col-dot"></span><h3>In progress</h3><span class="count-pill" id="count-progress">0</span><button class="col-add" data-add-col="progress" aria-label="Add card to In progress">+</button></div>
      <div class="cards-list" data-col="progress"></div>
      <button class="col-foot" data-add-col="progress">+ Add a card</button>
    </div>

    <div class="column col-done" data-col="done">
      <div class="col-head"><span class="col-dot"></span><h3>Done</h3><span class="count-pill" id="count-done">0</span><button class="col-add" data-add-col="done" aria-label="Add card to Done">+</button></div>
      <div class="cards-list" data-col="done"></div>
      <button class="col-foot" data-add-col="done">+ Add a card</button>
    </div>
  </section>
</main>

<footer>FlowBoard · Built with vanilla HTML, CSS &amp; JavaScript · State in memory only</footer>

<!-- MODAL -->
<div class="modal-overlay" id="modalOverlay" role="dialog" aria-modal="true" aria-labelledby="modalTitle">
  <form class="modal" id="cardForm" novalidate>
    <div class="modal-head">
      <div><h3 id="modalTitle">Add a new card</h3><p>Fill in the details — title is required.</p></div>
      <button type="button" class="modal-close" id="modalClose" aria-label="Close">✕</button>
    </div>

    <div class="field">
      <label for="cardTitle">Title *</label>
      <input type="text" id="cardTitle" placeholder="e.g. Design onboarding flow" maxlength="80">
      <div class="error-msg" id="titleError">Please enter a title for this card.</div>
    </div>

    <div class="field">
      <label for="cardDesc">Description <span style="text-transform:none;letter-spacing:0;font-weight:500">(optional)</span></label>
      <textarea id="cardDesc" rows="2" placeholder="Short description…" maxlength="140"></textarea>
    </div>

    <div class="field">
      <label>Priority</label>
      <div class="pills" id="priorityPills">
        <button type="button" class="pill" data-priority="low">Low</button>
        <button type="button" class="pill active" data-priority="medium">Medium</button>
        <button type="button" class="pill" data-priority="high">High</button>
      </div>
    </div>

    <div class="field">
      <label>Column</label>
      <div class="pills" id="columnPills">
        <button type="button" class="pill col-pill active" data-col="todo">To do</button>
        <button type="button" class="pill col-pill" data-col="progress">In progress</button>
        <button type="button" class="pill col-pill" data-col="done">Done</button>
      </div>
    </div>

    <div class="modal-actions">
      <button type="button" class="btn-cancel" id="modalCancel">Cancel</button>
      <button type="submit" class="btn-submit">Add card</button>
    </div>
  </form>
</div>

<div class="toast" id="toast"></div>

<script>
(function(){
  "use strict";

  var COLUMNS = [
    {id:"todo", name:"To do"},
    {id:"progress", name:"In progress"},
    {id:"done", name:"Done"}
  ];

  var AVATAR_COLORS = ["#6366f1","#ec4899","#f59e0b","#10b981","#3b82f6","#8b5cf6","#ef4444","#14b8a6"];

  var cards = [
    {id:1, title:"Design new landing page hero", desc:"Create 3 concepts and pick one for the spring campaign.", priority:"high", column:"todo", assignee:"Maya Chen", due:"Mar 14"},
    {id:2, title:"Write API documentation", desc:"Document the new billing endpoints with request examples.", priority:"medium", column:"todo", assignee:"Alex Rivera", due:"Mar 18"},
    {id:3, title:"Refactor authentication flow", desc:"Migrate to OAuth 2.0 and add login rate-limiting.", priority:"medium", column:"progress", assignee:"Sara Kim", due:"Mar 12"},
    {id:4, title:"Build onboarding email sequence", desc:"5-step drip for trial users — first draft ready for review.", priority:"low", column:"progress", assignee:"Jordan Lee", due:"Mar 20"},
    {id:5, title:"Set up CI/CD pipeline", desc:"GitHub Actions for staging deploys on every merge.", priority:"high", column:"done", assignee:"Priya Nair", due:"Mar 5"},
    {id:6, title:"Update brand color palette", desc:"Refreshed tokens across the design system and docs.", priority:"low", column:"done", assignee:"Leo Martins", due:"Mar 2"}
  ];

  var searchQuery = "";
  var draggedId = null;
  var dropTarget = {col:null, index:0};
  var selectedPriority = "medium";
  var selectedColumn = "todo";

  var board = document.getElementById("board");
  var searchInput = document.getElementById("searchInput");
  var clearSearch = document.getElementById("clearSearch");
  var searchMeta = document.getElementById("searchMeta");
  var themeToggle = document.getElementById("themeToggle");
  var modalOverlay = document.getElementById("modalOverlay");
  var cardForm = document.getElementById("cardForm");
  var cardTitle = document.getElementById("cardTitle");
  var cardDesc = document.getElementById("cardDesc");
  var titleError = document.getElementById("titleError");
  var toastEl = document.getElementById("toast");

  var indicator = document.createElement("div");
  indicator.className = "drop-indicator";

  var toastTimer = null;
  function showToast(msg){
    toastEl.textContent = "✓  " + msg;
    toastEl.classList.add("show");
    clearTimeout(toastTimer);
    toastTimer = setTimeout(function(){ toastEl.classList.remove("show"); }, 2400);
  }

  function esc(str){
    return String(str).replace(/[&<>"']/g, function(c){
      return {"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"}[c];
    });
  }
  function initials(name){
    return name.split(" ").map(function(w){return w[0];}).join("").slice(0,2).toUpperCase();
  }
  function avatarColor(name){
    var n = 0;
    for(var i=0;i<name.length;i++) n += name.charCodeAt(i);
    return AVATAR_COLORS[n % AVATAR_COLORS.length];
  }
  function colName(id){
    for(var i=0;i<COLUMNS.length;i++) if(COLUMNS[i].id===id) return COLUMNS[i].name;
    return id;
  }

  function render(){
    var q = searchQuery.trim().toLowerCase();
    var visibleTotal = 0;

    COLUMNS.forEach(function(col){
      var list = board.querySelector('[data-col="'+col.id+'"].cards-list');
      var visible = cards.filter(function(c){
        return c.column === col.id && c.title.toLowerCase().indexOf(q) !== -1;
      });
      visibleTotal += visible.length;

      document.getElementById("count-" + col.id).textContent = visible.length;

      if(visible.length === 0){
        list.innerHTML = '<div class="empty-state"><span class="big">' +
          (q ? "🔍" : "📭") + '</span>' +
          (q ? 'No cards match “' + esc(searchQuery.trim()) + '”.' : "No cards here yet.<br>Drag one in or add a new card.") +
          '</div>';
      } else {
        list.innerHTML = visible.map(function(c, i){
          return '' +
          '<article class="card" draggable="true" data-id="' + c.id + '" style="animation-delay:' + (i*55) + 'ms" tabindex="0">' +
            '<div class="card-top">' +
              '<span class="badge badge-' + c.priority + '">' + c.priority + '</span>' +
              '<button class="delete-btn" data-delete="' + c.id + '" aria-label="Delete card: ' + esc(c.title) + '" title="Delete card">×</button>' +
            '</div>' +
            '<h4>' + esc(c.title) + '</h4>' +
            (c.desc ? '<p>' + esc(c.desc) + '</p>' : '') +
            '<div class="card-bottom">' +
              '<span class="assignee"><span class="avatar" style="background:' + avatarColor(c.assignee) + '">' + initials(c.assignee) + '</span>' + esc(c.assignee) + '</span>' +
              '<span class="due">📅 ' + esc(c.due) + '</span>' +
            '</div>' +
          '</article>';
        }).join("");
      }
    });

    // Stats + progress (based on all cards, not filtered)
    var total = cards.length;
    var done = cards.filter(function(c){return c.column==="done";}).length;
    var prog = cards.filter(function(c){return c.column==="progress";}).length;
    var todo = cards.filter(function(c){return c.column==="todo";}).length;
    document.getElementById("statTodo").textContent = todo;
    document.getElementById("statProg").textContent = prog;
    document.getElementById("statDone").textContent = done;
    document.getElementById("progressLabel").textContent = done + " of " + total + " done";
    document.getElementById("progressFill").style.width = (total ? Math.round(done/total*100) : 0) + "%";

    if(q){
      searchMeta.innerHTML = "Showing <b>" + visibleTotal + "</b> of <b>" + total + "</b> cards matching “" + esc(searchQuery.trim()) + "”";
      searchMeta.classList.add("show");
    } else {
      searchMeta.classList.remove("show");
    }
    clearSearch.classList.toggle("show", searchInput.value.length > 0);
  }

  /* SEARCH — live filter by title */
  searchInput.addEventListener("input", function(){
    searchQuery = searchInput.value;
    render();
  });
  clearSearch.addEventListener("click", function(){
    searchInput.value = "";
    searchQuery = "";
    render();
    searchInput.focus();
  });

  /* DELETE — delegated */
  board.addEventListener("click", function(e){
    var del = e.target.closest("[data-delete]");
    if(del){
      var id = Number(del.getAttribute("data-delete"));
      var card = null;
      for(var i=0;i<cards.length;i++) if(cards[i].id===id) card = cards[i];
      cards = cards.filter(function(c){return c.id!==id;});
      render();
      if(card) showToast("Deleted “" + card.title + "”");
      return;
    }
    var add = e.target.closest("[data-add-col]");
    if(add){ openModal(add.getAttribute("data-add-col")); }
  });

  /* DRAG & DROP */
  function getDragAfterElement(list, y){
    var els = Array.prototype.slice.call(list.querySelectorAll(".card:not(.dragging)"));
    for(var i=0;i<els.length;i++){
      var r = els[i].getBoundingClientRect();
      if(y < r.top + r.height/2) return els[i];
    }
    return null;
  }

  board.addEventListener("dragstart", function(e){
    var cardEl = e.target.closest(".card");
    if(!cardEl) return;
    draggedId = Number(cardEl.getAttribute("data-id"));
    cardEl.classList.add("dragging");
    try{ e.dataTransfer.effectAllowed = "move"; e.dataTransfer.setData("text/plain", String(draggedId)); }catch(err){}
    setTimeout(function(){ cardEl.classList.add("dragging"); }, 0);
  });

  board.addEventListener("dragover", function(e){
    var list = e.target.closest(".cards-list");
    if(!list || draggedId === null) return;
    e.preventDefault();
    try{ e.dataTransfer.dropEffect = "move"; }catch(err){}

    document.querySelectorAll(".column").forEach(function(c){ c.classList.remove("drag-active"); });
    list.closest(".column").classList.add("drag-active");
    list.classList.add("drag-over");

    var empty = list.querySelector(".empty-state");
    if(empty) empty.style.display = "none";

    var after = getDragAfterElement(list, e.clientY);
    var cardsEls = Array.prototype.slice.call(list.querySelectorAll(".card:not(.dragging)"));
    if(after === null){
      list.appendChild(indicator);
      dropTarget = {col:list.getAttribute("data-col"), index:cardsEls.length};
    } else {
      list.insertBefore(indicator, after);
      dropTarget = {col:list.getAttribute("data-col"), index:cardsEls.indexOf(after)};
    }
  });

  board.addEventListener("dragleave", function(e){
    var list = e.target.closest(".cards-list");
    if(list && !list.contains(e.relatedTarget)){
      list.classList.remove("drag-over");
      var col = list.closest(".column");
      if(col) col.classList.remove("drag-active");
    }
  });

  board.addEventListener("drop", function(e){
    var list = e.target.closest(".cards-list");
    if(!list || draggedId === null) return;
    e.preventDefault();
    var col = list.getAttribute("data-col");
    var index = dropTarget.index;
    moveCard(draggedId, col, index);
    cleanupDrag();
    render();
    showToast("Moved to " + colName(col));
  });

  board.addEventListener("dragend", function(){
    cleanupDrag();
  });

  function cleanupDrag(){
    draggedId = null;
    indicator.remove();
    document.querySelectorAll(".column").forEach(function(c){ c.classList.remove("drag-active"); });
    document.querySelectorAll(".cards-list").forEach(function(l){ l.classList.remove("drag-over"); });
    document.querySelectorAll(".card.dragging").forEach(function(c){ c.classList.remove("dragging"); });
  }

  function moveCard(id, col, index){
    var moving = null, i;
    for(i=0;i<cards.length;i++) if(cards[i].id===id){ moving = cards[i]; break; }
    if(!moving) return;
    cards = cards.filter(function(c){return c.id!==id;});
    moving.column = col;
    var colCards = cards.filter(function(c){return c.column===col;});
    if(index >= colCards.length){
      if(colCards.length){
        var lastId = colCards[colCards.length-1].id;
        var pos = -1;
        for(i=0;i<cards.length;i++) if(cards[i].id===lastId) pos = i;
        cards.splice(pos+1, 0, moving);
      } else {
        cards.push(moving);
      }
    } else {
      var beforeId = colCards[index].id;
      var pos2 = -1;
      for(i=0;i<cards.length;i++) if(cards[i].id===beforeId) pos2 = i;
      cards.splice(pos2, 0, moving);
    }
  }

  /* MODAL */
  function setPills(containerId, attr, value){
    var pills = document.querySelectorAll("#" + containerId + " .pill");
    pills.forEach(function(p){ p.classList.toggle("active", p.getAttribute(attr) === value); });
  }
  function openModal(col){
    selectedColumn = col || "todo";
    selectedPriority = "medium";
    setPills("priorityPills", "data-priority", selectedPriority);
    setPills("columnPills", "data-col", selectedColumn);
    cardTitle.value = "";
    cardDesc.value = "";
    cardTitle.classList.remove("error");
    titleError.classList.remove("show");
    modalOverlay.classList.add("open");
    setTimeout(function(){ cardTitle.focus(); }, 60);
  }
  function closeModal(){ modalOverlay.classList.remove("open"); }

  document.getElementById("addCardBtn").addEventListener("click", function(){ openModal("todo"); });
  document.getElementById("modalClose").addEventListener("click", closeModal);
  document.getElementById("modalCancel").addEventListener("click", closeModal);
  modalOverlay.addEventListener("click", function(e){ if(e.target === modalOverlay) closeModal(); });
  document.addEventListener("keydown", function(e){ if(e.key === "Escape") closeModal(); });

  document.getElementById("priorityPills").addEventListener("click", function(e){
    var p = e.target.closest(".pill"); if(!p) return;
    selectedPriority = p.getAttribute("data-priority");
    setPills("priorityPills", "data-priority", selectedPriority);
  });
  document.getElementById("columnPills").addEventListener("click", function(e){
    var p = e.target.closest(".pill"); if(!p) return;
    selectedColumn = p.getAttribute("data-col");
    setPills("columnPills", "data-col", selectedColumn);
  });

  cardTitle.addEventListener("input", function(){
    cardTitle.classList.remove("error");
    titleError.classList.remove("show");
  });

  cardForm.addEventListener("submit", function(e){
    e.preventDefault();
    var title = cardTitle.value.trim();
    if(!title){
      cardTitle.classList.add("error");
      titleError.classList.add("show");
      cardTitle.focus();
      return;
    }
    cards.push({
      id: Date.now(),
      title: title,
      desc: cardDesc.value.trim(),
      priority: selectedPriority,
      column: selectedColumn,
      assignee: "You",
      due: "Today"
    });
    closeModal();
    render();
    showToast("Added “" + title + "” to " + colName(selectedColumn));
  });

  /* THEME TOGGLE — in-memory only */
  themeToggle.addEventListener("click", function(){
    var html = document.documentElement;
    var isDark = html.getAttribute("data-theme") === "dark";
    html.setAttribute("data-theme", isDark ? "light" : "dark");
    themeToggle.textContent = isDark ? "🌙" : "☀️";
    themeToggle.setAttribute("aria-label", isDark ? "Switch to dark theme" : "Switch to light theme");
  });

  render();
})();
</script>
</body>
</html>
Reasoning trace (3,887 tokens)
Implementing a vanilla HTML CSS JS Kanban board with drag-and-drop, modal form, search, theme toggle, and in-memory state.Extending the layout with responsive constraints, drag-and-drop indicators, modal validation, and live search filtering.Adding visible count badges, theme toggle, and drag-and-drop logic with modal and state rendering.Implementing drag-and-drop reordering with DOM insertion logic and state array updates.Adding delegation for drag events and rendering UI states for search, empty, and theme without storage.