Models 44

GPT-6.1 Terra

by OpenAIReasoningClean
Open in new window

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

How it went

Total time
1 min 48 s
Cost
$0.049
Output tokens
9,734
Spent thinking
891 tokens
Speed
94.6 tok/s
Console errors
0
First token after
5.3 s
First visible text after
20.8 s
Prompt tokens
493
Code size
27.5 KB
Finish reason
stop
Served by
OpenAI
Model id
openai/gpt-6.1-terra
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 · 439 lines

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Project board</title>
<style>
  :root {
    color-scheme: light;
    --page: #f8f9fb;
    --surface: #fff;
    --sidebar: #fff;
    --column: #f2f3f6;
    --text: #20232f;
    --muted: #898d9b;
    --subtle: #b4b7c2;
    --line: #ebecf0;
    --purple: #7058df;
    --purple-soft: #f0edff;
    --shadow: 0 2px 6px rgba(32,35,47,.035), 0 1px 2px rgba(32,35,47,.04);
    --card-border: #eceef2;
    --input: #fff;
  }
  [data-theme="dark"] {
    color-scheme: dark;
    --page: #171821;
    --surface: #252630;
    --sidebar: #1e1f29;
    --column: #20212b;
    --text: #f1f0f6;
    --muted: #aaaab9;
    --subtle: #777988;
    --line: #343540;
    --purple: #a18bff;
    --purple-soft: #37304f;
    --shadow: 0 2px 7px rgba(0,0,0,.16);
    --card-border: #373843;
    --input: #282933;
  }
  * { box-sizing: border-box; }
  body {
    margin: 0;
    font-family: Inter, ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    color: var(--text);
    background: var(--page);
    font-size: 14px;
    transition: background .2s, color .2s;
  }
  button, input, select { font: inherit; }
  button { cursor: pointer; }
  button:focus-visible, input:focus-visible, select:focus-visible, [tabindex]:focus-visible {
    outline: 3px solid #aa9af7; outline-offset: 2px;
  }
  .icon { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; flex: none; }
  .app { min-height: 100vh; display: flex; }
  .sidebar {
    width: 228px; flex: 0 0 228px; background: var(--sidebar);
    border-right: 1px solid var(--line); display: flex; flex-direction: column;
    padding: 26px 16px 18px;
  }
  .brand { display: flex; align-items: center; gap: 10px; padding: 0 8px 34px; font-size: 18px; font-weight: 750; letter-spacing: -.6px; }
  .brand-mark { width: 30px; height: 30px; border-radius: 9px; background: #7058df; color: white; display: grid; place-items: center; }
  .brand-mark .icon { width: 19px; height: 19px; stroke-width: 2.3; }
  .side-label { font-size: 10px; font-weight: 750; letter-spacing: 1.25px; color: var(--subtle); padding: 0 12px; margin: 0 0 12px; }
  .nav { display: grid; gap: 4px; margin-bottom: 35px; }
  .nav-item { color: var(--muted); display: flex; gap: 12px; align-items: center; padding: 11px 12px; border-radius: 8px; font-weight: 550; }
  .nav-item.active { color: var(--purple); background: var(--purple-soft); font-weight: 700; }
  .nav-item .icon { width: 17px; height: 17px; }
  .project-list { display: grid; gap: 4px; }
  .project-item { padding: 10px 12px; display: flex; gap: 11px; align-items: center; color: var(--muted); font-size: 13px; }
  .project-item.current { color: var(--text); font-weight: 650; }
  .project-dot { width: 9px; height: 9px; border-radius: 3px; background: #8c79e8; }
  .project-dot.peach { background: #e9ac85; }
  .project-dot.blue { background: #8dbbd8; }
  .sidebar-bottom { margin-top: auto; padding: 15px 8px 0; border-top: 1px solid var(--line); display: flex; align-items: center; gap: 10px; }
  .workspace-icon { width: 34px; height: 34px; border-radius: 9px; background: #25283b; color: #fff; display: grid; place-items: center; font-weight: 700; }
  .workspace-name { font-size: 12px; font-weight: 700; }
  .workspace-sub { font-size: 11px; color: var(--muted); margin-top: 3px; }
  .main { min-width: 0; flex: 1; }
  .topbar { height: 70px; border-bottom: 1px solid var(--line); background: var(--surface); display: flex; align-items: center; justify-content: space-between; padding: 0 38px; }
  .breadcrumbs { display: flex; align-items: center; gap: 11px; color: var(--muted); font-size: 13px; }
  .breadcrumbs strong { color: var(--text); font-weight: 650; }
  .slash { color: var(--subtle); }
  .top-actions { display: flex; align-items: center; gap: 17px; }
  .icon-button { border: 0; color: var(--muted); background: transparent; display: grid; place-items: center; border-radius: 8px; width: 34px; height: 34px; padding: 0; }
  .icon-button:hover { background: var(--column); color: var(--text); }
  .avatar { width: 31px; height: 31px; border-radius: 50%; display: grid; place-items: center; font-size: 10px; font-weight: 750; color: #67523d; background: #ead2ba; border: 2px solid var(--surface); }
  .content { padding: 39px 38px 50px; max-width: 1500px; margin: auto; }
  .project-heading { display: flex; justify-content: space-between; align-items: flex-end; gap: 20px; }
  .eyebrow { display: flex; gap: 7px; align-items: center; color: var(--purple); font-size: 10px; font-weight: 800; letter-spacing: 1.2px; margin-bottom: 11px; }
  .eyebrow-dot { width: 7px; height: 7px; background: #8b76e7; border-radius: 50%; }
  h1 { margin: 0; font-size: 27px; line-height: 1.2; letter-spacing: -.9px; font-weight: 750; }
  .subtitle { color: var(--muted); margin: 9px 0 0; font-size: 13px; line-height: 1.5; }
  .primary { background: #7058df; color: white; border: 1px solid #7058df; border-radius: 8px; padding: 10px 14px; display: inline-flex; align-items: center; justify-content: center; gap: 8px; font-size: 12px; font-weight: 700; white-space: nowrap; box-shadow: 0 3px 8px rgba(112,88,223,.16); }
  .primary:hover { background: #604ac9; }
  .primary .icon { width: 16px; height: 16px; }
  .toolbar { display: flex; justify-content: space-between; align-items: center; gap: 15px; border-bottom: 1px solid var(--line); margin-top: 31px; }
  .view-tabs { display: flex; align-self: stretch; gap: 24px; }
  .view-tab { display: flex; align-items: center; gap: 8px; color: var(--purple); border-bottom: 2px solid var(--purple); padding: 0 1px 15px; font-size: 12px; font-weight: 700; }
  .view-tab .icon { width: 16px; height: 16px; }
  .toolbar-right { display: flex; align-items: center; gap: 10px; padding-bottom: 13px; }
  .search { height: 35px; width: 190px; display: flex; align-items: center; gap: 8px; border: 1px solid var(--line); background: var(--surface); border-radius: 7px; padding: 0 10px; color: var(--muted); }
  .search .icon { width: 15px; height: 15px; }
  .search input { width: 100%; min-width: 0; border: 0; outline: 0; background: transparent; color: var(--text); font-size: 12px; }
  .search input::placeholder { color: var(--subtle); }
  .search:focus-within { border-color: var(--purple); }
  .filter { height: 35px; border: 1px solid var(--line); border-radius: 7px; background: var(--surface); color: var(--muted); padding: 0 9px; font-size: 12px; max-width: 125px; }
  .board { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; margin-top: 23px; align-items: start; }
  .column { background: var(--column); border: 1px solid transparent; border-radius: 11px; padding: 14px 11px 11px; min-width: 0; transition: border-color .15s, background .15s; }
  .column.drag-over { border-color: #9c8aea; background: var(--purple-soft); }
  .column-head { display: flex; align-items: center; gap: 8px; padding: 1px 3px 14px; }
  .status-dot { width: 8px; height: 8px; border-radius: 50%; background: #a7aab6; }
  .column[data-column="progress"] .status-dot { background: #e6ae54; }
  .column[data-column="done"] .status-dot { background: #69bb96; }
  .column-title { font-size: 12px; font-weight: 750; margin: 0; }
  .count { font-size: 10px; color: var(--muted); background: var(--surface); min-width: 20px; height: 20px; padding: 0 5px; display: grid; place-items: center; border-radius: 5px; font-weight: 700; }
  .column-add { margin-left: auto; width: 24px; height: 24px; }
  .column-add .icon { width: 16px; height: 16px; }
  .cards { min-height: 65px; display: flex; flex-direction: column; gap: 10px; }
  .task-card { background: var(--surface); border: 1px solid var(--card-border); box-shadow: var(--shadow); border-radius: 8px; padding: 14px 14px 12px; cursor: grab; min-width: 0; }
  .task-card:active { cursor: grabbing; }
  .task-card.dragging { opacity: .38; }
  .card-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 9px; }
  .category { color: var(--muted); font-size: 10px; font-weight: 700; letter-spacing: .15px; }
  .delete { width: 25px; height: 25px; margin: -5px -5px -5px 0; color: var(--subtle); }
  .delete .icon { width: 14px; height: 14px; }
  .delete:hover { color: #df6868; background: #fff0f0; }
  .card-title { font-size: 13px; font-weight: 750; line-height: 1.4; margin: 0 0 6px; overflow-wrap: anywhere; }
  .card-description { color: var(--muted); font-size: 11px; line-height: 1.5; margin: 0; min-height: 32px; }
  .card-bottom { border-top: 1px solid var(--line); margin-top: 14px; padding-top: 11px; display: flex; align-items: center; gap: 7px; }
  .priority { display: inline-flex; align-items: center; gap: 5px; border-radius: 5px; padding: 5px 7px; font-size: 10px; font-weight: 700; }
  .priority::before { content: ""; width: 5px; height: 5px; border-radius: 50%; background: currentColor; }
  .priority.high { color: #cf6d63; background: #fff0ed; }
  .priority.medium { color: #ba8840; background: #fff6e6; }
  .priority.low { color: #5d9d7e; background: #eaf7f0; }
  [data-theme="dark"] .priority.high { background: #49302f; color: #f1a49b; }
  [data-theme="dark"] .priority.medium { background: #453b2c; color: #e8c181; }
  [data-theme="dark"] .priority.low { background: #293e36; color: #94d5b1; }
  .due { margin-left: auto; color: var(--muted); font-size: 10px; white-space: nowrap; }
  .card-avatar { width: 25px; height: 25px; border-radius: 50%; display: grid; place-items: center; font-size: 9px; font-weight: 750; background: #e5dbf7; color: #745fa5; flex: none; }
  .card-avatar.a2 { background: #d7e9e4; color: #588679; }
  .card-avatar.a3 { background: #f1dfd2; color: #a47358; }
  .drop-placeholder { height: 76px; border: 2px dashed #a28fe9; background: rgba(138,115,231,.08); border-radius: 8px; }
  .empty { color: var(--muted); text-align: center; font-size: 11px; padding: 22px 8px; line-height: 1.5; }
  .add-row { margin-top: 10px; width: 100%; border: 0; background: transparent; color: var(--muted); border-radius: 7px; display: flex; align-items: center; gap: 8px; padding: 9px 5px; font-size: 11px; font-weight: 650; text-align: left; }
  .add-row:hover { color: var(--purple); background: var(--surface); }
  .add-row .icon { width: 15px; height: 15px; }
  .board-note { color: var(--subtle); font-size: 11px; margin: 18px 2px 0; display: flex; align-items: center; gap: 7px; }
  .board-note .icon { width: 14px; height: 14px; }
  .modal-backdrop { position: fixed; inset: 0; z-index: 10; background: rgba(25, 25, 38, .48); display: grid; place-items: center; padding: 20px; }
  .modal-backdrop[hidden] { display: none; }
  .modal { width: min(100%, 440px); background: var(--surface); border-radius: 14px; box-shadow: 0 20px 70px rgba(0,0,0,.2); padding: 24px; }
  .modal-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 10px; margin-bottom: 23px; }
  .modal h2 { font-size: 19px; letter-spacing: -.4px; margin: 0 0 6px; }
  .modal p { color: var(--muted); font-size: 12px; margin: 0; }
  .field { display: block; margin-bottom: 17px; }
  .field > span { display: block; font-size: 12px; font-weight: 700; margin-bottom: 8px; }
  .field input, .field select { display: block; width: 100%; height: 40px; border: 1px solid var(--line); border-radius: 7px; color: var(--text); background: var(--input); padding: 0 11px; font-size: 13px; }
  .field input::placeholder { color: var(--subtle); }
  .field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
  .modal-actions { display: flex; justify-content: flex-end; gap: 9px; margin-top: 24px; }
  .secondary { border: 1px solid var(--line); background: var(--surface); color: var(--text); border-radius: 8px; padding: 10px 14px; font-size: 12px; font-weight: 700; }
  .secondary:hover { background: var(--column); }
  @media (max-width: 900px) {
    .sidebar { width: 190px; flex-basis: 190px; }
    .content { padding: 32px 24px 45px; }
    .topbar { padding: 0 24px; }
    .board { gap: 10px; }
    .card-description { min-height: 48px; }
  }
  @media (max-width: 700px) {
    .sidebar { display: none; }
    .topbar { height: 60px; padding: 0 20px; }
    .content { padding: 27px 20px 40px; }
    .project-heading { align-items: flex-start; }
    h1 { font-size: 24px; }
    .board { grid-template-columns: 1fr; }
    .card-description { min-height: 0; }
    .toolbar { flex-wrap: wrap; margin-top: 25px; }
    .toolbar-right { flex: 1; justify-content: flex-end; }
    .search { width: min(190px, 100%); }
  }
  @media (max-width: 420px) {
    .breadcrumbs { font-size: 12px; gap: 7px; }
    .top-actions { gap: 8px; }
    .project-heading { gap: 10px; }
    .project-heading .primary { padding: 9px 10px; }
    .subtitle { max-width: 210px; }
    .filter { max-width: 105px; }
    .toolbar-right { gap: 6px; }
    .search { width: 135px; }
  }
</style>
</head>
<body>
<svg width="0" height="0" style="position:absolute" aria-hidden="true">
  <symbol id="i-grid" viewBox="0 0 24 24"><rect x="3" y="3" width="7" height="7" rx="1"/><rect x="14" y="3" width="7" height="7" rx="1"/><rect x="3" y="14" width="7" height="7" rx="1"/><rect x="14" y="14" width="7" height="7" rx="1"/></symbol>
  <symbol id="i-board" viewBox="0 0 24 24"><rect x="3" y="4" width="18" height="16" rx="2"/><path d="M9 4v16M15 4v16"/></symbol>
  <symbol id="i-calendar" viewBox="0 0 24 24"><rect x="3" y="5" width="18" height="16" rx="2"/><path d="M7 3v4M17 3v4M3 10h18"/></symbol>
  <symbol id="i-users" viewBox="0 0 24 24"><circle cx="9" cy="8" r="3"/><path d="M3 20v-2a6 6 0 0 1 12 0v2M16 5a3 3 0 0 1 0 6M17 14a5 5 0 0 1 4 5v1"/></symbol>
  <symbol id="i-plus" viewBox="0 0 24 24"><path d="M12 5v14M5 12h14"/></symbol>
  <symbol id="i-search" viewBox="0 0 24 24"><circle cx="10.5" cy="10.5" r="6.5"/><path d="m16 16 4 4"/></symbol>
  <symbol id="i-trash" viewBox="0 0 24 24"><path d="M4 7h16M10 11v6M14 11v6M6 7l1 13h10l1-13M9 7V4h6v3"/></symbol>
  <symbol id="i-moon" viewBox="0 0 24 24"><path d="M20.5 14.5A8.5 8.5 0 0 1 9.5 3.5 8.5 8.5 0 1 0 20.5 14.5Z"/></symbol>
  <symbol id="i-sun" viewBox="0 0 24 24"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.93 4.93l1.42 1.42M17.65 17.65l1.42 1.42M2 12h2M20 12h2M4.93 19.07l1.42-1.42M17.65 6.35l1.42-1.42"/></symbol>
  <symbol id="i-close" viewBox="0 0 24 24"><path d="M6 6l12 12M18 6 6 18"/></symbol>
  <symbol id="i-move" viewBox="0 0 24 24"><path d="M12 2v20M2 12h20M9 5l3-3 3 3M9 19l3 3 3-3M5 9l-3 3 3 3M19 9l3 3-3 3"/></symbol>
</svg>

<div class="app">
  <aside class="sidebar">
    <div class="brand"><span class="brand-mark"><svg class="icon"><use href="#i-board"/></svg></span>mosaic<span style="color:#8a75e9">.</span></div>
    <p class="side-label">WORKSPACE</p>
    <nav class="nav" aria-label="Workspace">
      <div class="nav-item"><svg class="icon"><use href="#i-grid"/></svg> Overview</div>
      <div class="nav-item active"><svg class="icon"><use href="#i-board"/></svg> Board</div>
      <div class="nav-item"><svg class="icon"><use href="#i-calendar"/></svg> Calendar</div>
      <div class="nav-item"><svg class="icon"><use href="#i-users"/></svg> Team</div>
    </nav>
    <p class="side-label">YOUR PROJECTS</p>
    <div class="project-list">
      <div class="project-item current"><span class="project-dot"></span> Website redesign</div>
      <div class="project-item"><span class="project-dot peach"></span> Brand identity</div>
      <div class="project-item"><span class="project-dot blue"></span> Mobile app</div>
    </div>
    <div class="sidebar-bottom">
      <div class="workspace-icon">S</div>
      <div><div class="workspace-name">Studio workspace</div><div class="workspace-sub">Free plan</div></div>
    </div>
  </aside>

  <main class="main">
    <header class="topbar">
      <div class="breadcrumbs"><span>Workspace</span><span class="slash">/</span><strong>Website redesign</strong></div>
      <div class="top-actions">
        <button class="icon-button" id="theme-toggle" type="button" aria-label="Switch to dark theme" title="Switch theme"><svg class="icon"><use id="theme-icon" href="#i-moon"/></svg></button>
        <div class="avatar" title="Alex Morgan">AM</div>
      </div>
    </header>

    <div class="content">
      <div class="project-heading">
        <div>
          <div class="eyebrow"><span class="eyebrow-dot"></span> PROJECT BOARD</div>
          <h1>Website redesign</h1>
          <p class="subtitle">A little progress every day adds up to big results.</p>
        </div>
        <button class="primary" id="new-task" type="button"><svg class="icon"><use href="#i-plus"/></svg> Add task</button>
      </div>

      <div class="toolbar">
        <div class="view-tabs"><div class="view-tab"><svg class="icon"><use href="#i-board"/></svg> Board view</div></div>
        <div class="toolbar-right">
          <label class="search"><svg class="icon"><use href="#i-search"/></svg><input id="search" type="search" placeholder="Search tasks..." aria-label="Search tasks"></label>
          <select class="filter" id="priority-filter" aria-label="Filter by priority">
            <option value="all">All priorities</option>
            <option value="high">High</option>
            <option value="medium">Medium</option>
            <option value="low">Low</option>
          </select>
        </div>
      </div>

      <section class="board" aria-label="Kanban board">
        <section class="column" data-column="todo">
          <div class="column-head"><span class="status-dot"></span><h2 class="column-title">To do</h2><span class="count">0</span><button class="icon-button column-add" type="button" aria-label="Add task to To do"><svg class="icon"><use href="#i-plus"/></svg></button></div>
          <div class="cards"></div>
          <button class="add-row" type="button"><svg class="icon"><use href="#i-plus"/></svg> Add a task</button>
        </section>
        <section class="column" data-column="progress">
          <div class="column-head"><span class="status-dot"></span><h2 class="column-title">In progress</h2><span class="count">0</span><button class="icon-button column-add" type="button" aria-label="Add task to In progress"><svg class="icon"><use href="#i-plus"/></svg></button></div>
          <div class="cards"></div>
          <button class="add-row" type="button"><svg class="icon"><use href="#i-plus"/></svg> Add a task</button>
        </section>
        <section class="column" data-column="done">
          <div class="column-head"><span class="status-dot"></span><h2 class="column-title">Done</h2><span class="count">0</span><button class="icon-button column-add" type="button" aria-label="Add task to Done"><svg class="icon"><use href="#i-plus"/></svg></button></div>
          <div class="cards"></div>
          <button class="add-row" type="button"><svg class="icon"><use href="#i-plus"/></svg> Add a task</button>
        </section>
      </section>
      <p class="board-note"><svg class="icon"><use href="#i-move"/></svg> Drag and drop tasks to update their status</p>
    </div>
  </main>
</div>

<div class="modal-backdrop" id="modal" hidden>
  <div class="modal" role="dialog" aria-modal="true" aria-labelledby="modal-title">
    <div class="modal-head">
      <div><h2 id="modal-title">Create a task</h2><p>Add something new to your project board.</p></div>
      <button class="icon-button" id="close-modal" type="button" aria-label="Close"><svg class="icon"><use href="#i-close"/></svg></button>
    </div>
    <form id="task-form">
      <label class="field"><span>Task title</span><input id="task-title" type="text" maxlength="90" placeholder="What needs to be done?" required></label>
      <div class="field-row">
        <label class="field"><span>Priority</span><select id="task-priority"><option value="low">Low</option><option value="medium" selected>Medium</option><option value="high">High</option></select></label>
        <label class="field"><span>Status</span><select id="task-status"><option value="todo">To do</option><option value="progress">In progress</option><option value="done">Done</option></select></label>
      </div>
      <div class="modal-actions"><button class="secondary" id="cancel-modal" type="button">Cancel</button><button class="primary" type="submit"><svg class="icon"><use href="#i-plus"/></svg> Create task</button></div>
    </form>
  </div>
</div>

<script>
(() => {
  let tasks = [
    { id: 1, column: 'todo', title: 'Write homepage copy', priority: 'high', category: 'CONTENT', description: 'Craft a clear story for our new homepage.', due: 'May 24', avatar: 'AM', avatarClass: '' },
    { id: 2, column: 'todo', title: 'Gather inspiration', priority: 'low', category: 'RESEARCH', description: 'Collect references for the visual direction.', due: 'May 26', avatar: 'JL', avatarClass: 'a2' },
    { id: 3, column: 'progress', title: 'Design landing page', priority: 'high', category: 'DESIGN', description: 'Bring the new homepage wireframes to life.', due: 'May 22', avatar: 'SK', avatarClass: 'a3' },
    { id: 4, column: 'progress', title: 'Build component library', priority: 'medium', category: 'DEVELOPMENT', description: 'Create reusable elements for the new site.', due: 'May 28', avatar: 'JL', avatarClass: 'a2' },
    { id: 5, column: 'done', title: 'Project kickoff', priority: 'medium', category: 'PLANNING', description: 'Align on goals, timeline, and next steps.', due: 'May 12', avatar: 'AM', avatarClass: '' },
    { id: 6, column: 'done', title: 'Audit current website', priority: 'low', category: 'RESEARCH', description: 'Review what works and what needs improving.', due: 'May 16', avatar: 'SK', avatarClass: 'a3' }
  ];
  let nextId = 7;
  let draggedId = null;
  let returnFocus = null;
  const modal = document.getElementById('modal');
  const form = document.getElementById('task-form');
  const titleInput = document.getElementById('task-title');
  const search = document.getElementById('search');
  const filter = document.getElementById('priority-filter');
  const columns = [...document.querySelectorAll('.column')];
  const placeholder = document.createElement('div');
  placeholder.className = 'drop-placeholder';
  placeholder.setAttribute('aria-hidden', 'true');

  const escapeHTML = value => String(value).replace(/[&<>"']/g, char => ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[char]));
  const icon = name => `<svg class="icon" aria-hidden="true"><use href="#i-${name}"></use></svg>`;

  function render() {
    const query = search.value.trim().toLowerCase();
    columns.forEach(column => {
      const list = column.querySelector('.cards');
      const visible = tasks.filter(task => task.column === column.dataset.column && task.title.toLowerCase().includes(query) && (filter.value === 'all' || task.priority === filter.value));
      column.querySelector('.count').textContent = visible.length;
      list.innerHTML = visible.length ? visible.map(task => `
        <article class="task-card" draggable="true" data-id="${task.id}">
          <div class="card-top"><span class="category">${escapeHTML(task.category)}</span><button class="icon-button delete" type="button" aria-label="Delete ${escapeHTML(task.title)}" title="Delete task">${icon('trash')}</button></div>
          <h3 class="card-title">${escapeHTML(task.title)}</h3>
          <p class="card-description">${escapeHTML(task.description)}</p>
          <div class="card-bottom"><span class="priority ${task.priority}">${task.priority[0].toUpperCase() + task.priority.slice(1)}</span><span class="due">${escapeHTML(task.due)}</span><span class="card-avatar ${task.avatarClass}">${escapeHTML(task.avatar)}</span></div>
        </article>`).join('') : `<div class="empty">${query || filter.value !== 'all' ? 'No matching tasks' : 'No tasks yet'}</div>`;
    });
  }

  function openModal(status, trigger) {
    returnFocus = trigger || document.activeElement;
    form.reset();
    document.getElementById('task-status').value = status || 'todo';
    modal.hidden = false;
    titleInput.focus();
  }
  function closeModal() {
    modal.hidden = true;
    if (returnFocus) returnFocus.focus();
  }
  document.getElementById('new-task').addEventListener('click', e => openModal('todo', e.currentTarget));
  document.getElementById('close-modal').addEventListener('click', closeModal);
  document.getElementById('cancel-modal').addEventListener('click', closeModal);
  modal.addEventListener('click', e => { if (e.target === modal) closeModal(); });
  document.addEventListener('keydown', e => { if (e.key === 'Escape' && !modal.hidden) closeModal(); });
  form.addEventListener('submit', e => {
    e.preventDefault();
    const title = titleInput.value.trim();
    if (!title) { titleInput.value = ''; titleInput.focus(); return; }
    tasks.push({ id: nextId++, column: document.getElementById('task-status').value, title, priority: document.getElementById('task-priority').value, category: 'NEW TASK', description: 'Ready for the next step.', due: 'No date', avatar: 'AM', avatarClass: '' });
    search.value = '';
    filter.value = 'all';
    render();
    closeModal();
  });
  search.addEventListener('input', render);
  filter.addEventListener('change', render);

  columns.forEach(column => {
    column.querySelectorAll('.column-add, .add-row').forEach(button => button.addEventListener('click', () => openModal(column.dataset.column, button)));
    column.addEventListener('click', e => {
      const button = e.target.closest('.delete');
      if (!button) return;
      const card = button.closest('.task-card');
      tasks = tasks.filter(task => task.id !== Number(card.dataset.id));
      render();
    });
    column.addEventListener('dragstart', e => {
      const card = e.target.closest('.task-card');
      if (!card) return;
      draggedId = Number(card.dataset.id);
      e.dataTransfer.effectAllowed = 'move';
      e.dataTransfer.setData('text/plain', String(draggedId));
      requestAnimationFrame(() => card.classList.add('dragging'));
    });
    column.addEventListener('dragover', e => {
      if (draggedId === null) return;
      e.preventDefault();
      e.dataTransfer.dropEffect = 'move';
      columns.forEach(c => c.classList.toggle('drag-over', c === column));
      const list = column.querySelector('.cards');
      const cards = [...list.querySelectorAll('.task-card:not(.dragging)')];
      const next = cards.find(card => e.clientY < card.getBoundingClientRect().top + card.offsetHeight / 2);
      if (next) list.insertBefore(placeholder, next);
      else list.appendChild(placeholder);
    });
    column.addEventListener('drop', e => {
      if (draggedId === null) return;
      e.preventDefault();
      const taskIndex = tasks.findIndex(task => task.id === draggedId);
      if (taskIndex !== -1) {
        const task = tasks.splice(taskIndex, 1)[0];
        task.column = column.dataset.column;
        let next = placeholder.nextElementSibling;
        while (next && !next.classList.contains('task-card')) next = next.nextElementSibling;
        const beforeIndex = next ? tasks.findIndex(item => item.id === Number(next.dataset.id)) : -1;
        if (beforeIndex >= 0) tasks.splice(beforeIndex, 0, task);
        else tasks.push(task);
      }
      draggedId = null;
      placeholder.remove();
      columns.forEach(c => c.classList.remove('drag-over'));
      render();
    });
    column.addEventListener('dragend', () => {
      draggedId = null;
      placeholder.remove();
      columns.forEach(c => c.classList.remove('drag-over'));
      render();
    });
  });

  const themeButton = document.getElementById('theme-toggle');
  themeButton.addEventListener('click', () => {
    const dark = document.documentElement.dataset.theme !== 'dark';
    document.documentElement.dataset.theme = dark ? 'dark' : 'light';
    document.getElementById('theme-icon').setAttribute('href', dark ? '#i-sun' : '#i-moon');
    themeButton.setAttribute('aria-label', dark ? 'Switch to light theme' : 'Switch to dark theme');
  });
  render();
})();
</script>
</body>
</html>
Reasoning trace (891 tokens)
**Designing a project board**

I need to produce code for a polished design at 1280x800. The project board will have a cream background with purple accents and a header sidebar. I’m planning a workspace setup that includes a main centered area, sidebar width of about 210, and three columns with six cards for task organization. Each card needs a title, optional metadata, and buttons. I also need to ensure a good mobile layout and a white-on-off-white color scheme. Alright, let's dive in!**Designing the sidebar and cards**

I’m setting up a sidebar with navigation items like overview, board, calendar, team, and project sections. I need to make sure everything feels interactive without any weird decorative labels. For the cards, I’ll include category labels, titles, descriptions, priorities, and due dates, along with a visible deletion button. I'll add a modal for card creation, ensuring it’s user-friendly with proper focus handling. Also, I'll implement drag-and-drop functionality with clear visuals for users to navigate tasks effectively. Alright, let’s get to work!**Improving task management**

I’m considering simplifying the drop functionality by determining the next element sibling as a placeholder for moving tasks between columns. This involves managing task categories, unique IDs, and ensuring safe rendering via textContent or escape methods to avoid XSS attacks. I should create tasks with realistic titles and descriptions using a modal form with dropdowns for priority, represented by colored badges. I’ll also include a search input and consider showing a toast notification after a deletion, though no undo action is needed. Let’s work on this!**Designing layout elements**

I'm thinking about the utility layout, with a top right decorative sidebar and an activity callout in the main lower area. The board should extend to about 700 pixels, with the header properly spaced for various elements. It’s nice to visualize card heights at around 160 pixels, arranged with two cards per column. I’ll implement icons and SVGs where necessary. Also, there might not be a need for a header dropdown; the focus will be on the project title, description, and functionality like search and filtering features.**Refining task functionality**

I need to ensure that the search empty indicator div doesn’t interfere with insertion. Should I render the empty state separately? The placeholder logic indicates checking cards and dropping before the nearest one. I'll manage task insertion with global IDs, pushing to the end when necessary. The placeholder should sit outside the data. Using document creation for elements and event delegation makes sense. Additionally, I have to ensure the drag and drop feature works seamlessly, with correct filtering and display states. Finally, there’s a need for a modal form for task details with specific constraints.