Models 44

GPT-6 Luna

by OpenAIReasoningClean
Open in new window

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

How it went

Total time
48.7 s
Cost
$0.0029
Output tokens
5,717
Spent thinking
63 tokens
Speed
124.8 tok/s
Console errors
0
First token after
2.9 s
First visible text after
4.5 s
Prompt tokens
493
Code size
18.2 KB
Finish reason
stop
Served by
OpenAI
Model id
openai/gpt-6-luna
Reasoning sent
{"effort":"low"}
Max output
64,000 tokens
Generated
Nov 10, 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 · 356 lines

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Boardly — Kanban</title>
<style>
  :root {
    color-scheme: light;
    --bg: #f5f6fa;
    --surface: #fff;
    --surface-soft: #f8f9fc;
    --text: #202435;
    --muted: #83899a;
    --line: #e9ebf1;
    --accent: #6259e8;
    --accent-soft: #eeedff;
    --shadow: 0 8px 24px rgba(29, 35, 63, .055);
    --low: #289c75;
    --medium: #d49424;
    --high: #df5c67;
  }
  * { box-sizing: border-box; }
  body {
    margin: 0;
    background: var(--bg);
    color: var(--text);
    font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    font-size: 14px;
    min-height: 100vh;
    transition: background .2s, color .2s;
  }
  body.dark {
    color-scheme: dark;
    --bg: #171923;
    --surface: #20232f;
    --surface-soft: #292c39;
    --text: #f0f1f7;
    --muted: #a0a5b5;
    --line: #343746;
    --accent: #9b94ff;
    --accent-soft: #343149;
    --shadow: 0 8px 24px rgba(0, 0, 0, .18);
    --low: #63c99f;
    --medium: #f0bb55;
    --high: #ff818c;
  }
  button, input { font: inherit; }
  button { color: inherit; }
  .app { max-width: 1190px; margin: 0 auto; padding: 0 30px 52px; }
  .topbar {
    height: 72px; border-bottom: 1px solid var(--line); display: flex;
    align-items: center; justify-content: space-between;
  }
  .brand { display:flex; align-items:center; gap:10px; font-weight:750; letter-spacing:-.4px; font-size:17px; }
  .brand-mark {
    width:30px;height:30px;border-radius:9px;background:var(--accent);color:white;
    display:grid;place-items:center;font-size:16px;box-shadow:0 4px 10px #6259e833;
  }
  .top-right { display:flex;align-items:center;gap:12px; }
  .avatar {
    width:32px;height:32px;border-radius:50%;display:grid;place-items:center;
    background:#ffe3d5;color:#9f553d;font-size:11px;font-weight:750;border:2px solid var(--surface);
  }
  .profile { display:flex;align-items:center;gap:8px;font-size:12px;font-weight:650; }
  .workspace { color:var(--muted);font-size:12px;margin-right:6px; }
  .intro { padding:32px 0 24px; }
  .eyebrow { color:var(--accent);font-size:11px;font-weight:750;letter-spacing:1.3px;text-transform:uppercase;margin-bottom:7px; }
  h1 { font-size:29px;letter-spacing:-1px;margin:0;font-weight:760; }
  .subtitle { color:var(--muted);font-size:13px;margin:7px 0 0; }
  .toolbar { display:flex;align-items:center;justify-content:space-between;gap:14px;margin:0 0 21px; }
  .toolbar-left,.toolbar-right { display:flex;align-items:center;gap:10px; }
  .search-wrap { position:relative; }
  .search-wrap svg { position:absolute;left:12px;top:50%;transform:translateY(-50%);color:var(--muted); }
  .search {
    width:230px;height:39px;border:1px solid var(--line);border-radius:9px;
    background:var(--surface);color:var(--text);padding:0 12px 0 36px;outline:none;
    transition:border .15s, box-shadow .15s;
  }
  .search:focus,.field:focus { border-color:var(--accent);box-shadow:0 0 0 3px color-mix(in srgb, var(--accent) 15%, transparent); }
  .search::placeholder,.field::placeholder { color:#a2a7b4; }
  .button {
    border:1px solid var(--line);height:39px;padding:0 13px;border-radius:9px;
    background:var(--surface);display:inline-flex;align-items:center;justify-content:center;
    gap:8px;font-weight:650;cursor:pointer;transition:transform .15s,background .15s,border .15s;
  }
  .button:hover { background:var(--surface-soft); }
  .button:active { transform:translateY(1px); }
  .button.primary { background:var(--accent);border-color:var(--accent);color:#fff;box-shadow:0 3px 9px color-mix(in srgb,var(--accent) 25%,transparent); }
  .button.primary:hover { filter:brightness(1.06); }
  .icon-button { width:39px;padding:0; }
  .board { display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:18px;align-items:start; }
  .column {
    min-width:0;background:var(--surface-soft);border:1px solid var(--line);
    border-radius:12px;padding:13px 12px 12px;min-height:340px;transition:background .16s,border .16s;
  }
  .column.drag-over { border:1px dashed var(--accent);background:var(--accent-soft); }
  .column-head { display:flex;align-items:center;justify-content:space-between;padding:2px 2px 13px; }
  .col-label { display:flex;align-items:center;gap:9px;font-size:13px;font-weight:720; }
  .dot { width:8px;height:8px;border-radius:50%;background:#9ca2b3; }
  .column[data-status="todo"] .dot { background:#9aa0b2; }
  .column[data-status="progress"] .dot { background:#ebaa49; }
  .column[data-status="done"] .dot { background:#42ad83; }
  .count { font-size:11px;font-weight:700;color:var(--muted);background:var(--surface);border:1px solid var(--line);min-width:23px;height:22px;border-radius:7px;display:grid;place-items:center;padding:0 5px; }
  .add-inline { border:0;background:none;color:var(--muted);cursor:pointer;width:26px;height:26px;border-radius:7px;font-size:19px;line-height:1; }
  .add-inline:hover { color:var(--accent);background:var(--accent-soft); }
  .cards { display:flex;flex-direction:column;gap:10px;min-height:274px; }
  .card {
    background:var(--surface);border:1px solid var(--line);border-radius:10px;
    padding:13px 13px 11px;box-shadow:var(--shadow);cursor:grab;transition:opacity .15s,transform .15s,border .15s;
  }
  .card:hover { border-color:color-mix(in srgb,var(--accent) 30%,var(--line));transform:translateY(-1px); }
  .card.dragging { opacity:.35;transform:scale(.98); }
  .card-top { display:flex;align-items:flex-start;justify-content:space-between;gap:8px; }
  .card-title { font-size:13px;line-height:1.45;font-weight:650;letter-spacing:-.12px; }
  .delete {
    border:0;background:transparent;color:#a0a4b0;cursor:pointer;width:23px;height:23px;
    margin:-4px -5px 0 0;border-radius:6px;display:grid;place-items:center;flex:none;opacity:0;
  }
  .card:hover .delete,.delete:focus-visible { opacity:1; }
  .delete:hover { color:var(--high);background:color-mix(in srgb,var(--high) 12%,transparent); }
  .card-bottom { display:flex;align-items:center;justify-content:space-between;margin-top:13px; }
  .priority { display:inline-flex;align-items:center;gap:5px;border-radius:5px;padding:4px 7px;font-size:10px;font-weight:700; }
  .priority::before { content:"";width:5px;height:5px;border-radius:50%;background:currentColor; }
  .priority.low { color:var(--low);background:color-mix(in srgb,var(--low) 12%,transparent); }
  .priority.medium { color:var(--medium);background:color-mix(in srgb,var(--medium) 13%,transparent); }
  .priority.high { color:var(--high);background:color-mix(in srgb,var(--high) 12%,transparent); }
  .meta { color:var(--muted);font-size:10px;display:flex;align-items:center;gap:5px; }
  .mini-avatar { width:21px;height:21px;border-radius:50%;display:grid;place-items:center;background:#e6e5ff;color:#6259c9;font-size:9px;font-weight:750; }
  .column-empty { color:var(--muted);font-size:12px;text-align:center;padding:26px 8px;border:1px dashed var(--line);border-radius:9px;display:none; }
  .empty-search { text-align:center;color:var(--muted);padding:48px 8px;display:none; }
  .board-footer { display:flex;justify-content:space-between;color:var(--muted);font-size:11px;padding:15px 2px; }
  .footer-key { border:1px solid var(--line);border-radius:4px;padding:2px 5px;background:var(--surface);font-size:10px; }
  .modal-backdrop { position:fixed;inset:0;background:rgba(18,20,33,.48);display:none;align-items:center;justify-content:center;padding:18px;z-index:10; }
  .modal-backdrop.open { display:flex; }
  .modal { width:min(100%,420px);background:var(--surface);border:1px solid var(--line);border-radius:15px;padding:23px;box-shadow:0 20px 60px #0003;animation:pop .16s ease-out; }
  @keyframes pop { from { opacity:0;transform:translateY(7px) scale(.99); } to { opacity:1;transform:none; } }
  .modal-head { display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:20px; }
  .modal h2 { font-size:19px;letter-spacing:-.4px;margin:0 0 5px; }
  .modal-sub { color:var(--muted);font-size:12px; }
  .modal-close { border:0;background:none;color:var(--muted);font-size:21px;cursor:pointer;width:28px;height:28px;border-radius:6px; }
  .modal-close:hover { background:var(--surface-soft); }
  .form-row { margin-bottom:15px; }
  .form-row label { display:block;font-size:12px;font-weight:650;margin:0 0 7px; }
  .field { width:100%;height:40px;border:1px solid var(--line);border-radius:8px;padding:0 11px;background:var(--surface);color:var(--text);outline:none; }
  select.field { cursor:pointer; }
  .modal-actions { display:flex;justify-content:flex-end;gap:9px;margin-top:22px; }
  @media (max-width:760px) {
    .app { padding:0 18px 35px; }
    .board { grid-template-columns:1fr;gap:12px; }
    .column { min-height:0; }
    .cards { min-height:55px; }
    .intro { padding:26px 0 20px; }
    .workspace,.profile-name { display:none; }
    .column-empty { padding:17px 8px; }
  }
  @media (max-width:450px) {
    .app { padding-left:14px;padding-right:14px; }
    .topbar { height:62px; }
    h1 { font-size:25px; }
    .toolbar { align-items:stretch; }
    .toolbar-left { flex:1; }
    .search-wrap { flex:1; }
    .search { width:100%;min-width:0; }
    .toolbar-right { gap:7px; }
    .button { padding:0 10px; }
    .button.primary { font-size:12px; }
    .board-footer { font-size:10px; }
    .delete { opacity:1; }
  }
</style>
</head>
<body>
<div class="app">
  <header class="topbar">
    <div class="brand"><span class="brand-mark">▥</span> boardly</div>
    <div class="top-right">
      <span class="workspace">Product workspace</span>
      <div class="profile"><span class="avatar">AM</span><span class="profile-name">Alex Morgan</span></div>
    </div>
  </header>

  <main>
    <section class="intro">
      <div class="eyebrow">Team workspace</div>
      <h1>Product launch</h1>
      <p class="subtitle">Plan, track, and ship great work together.</p>
    </section>

    <div class="toolbar">
      <div class="toolbar-left">
        <div class="search-wrap">
          <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="7"></circle><path d="m20 20-4-4"></path></svg>
          <input id="search" class="search" type="search" placeholder="Search tasks..." aria-label="Search tasks">
        </div>
      </div>
      <div class="toolbar-right">
        <button class="button icon-button" id="themeToggle" aria-label="Toggle dark theme" title="Toggle theme">
          <svg id="themeIcon" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M20.1 15.4A8.5 8.5 0 0 1 8.6 3.9 8.5 8.5 0 1 0 20.1 15.4Z"></path></svg>
        </button>
        <button class="button primary" id="openModal"><span style="font-size:18px;line-height:0">+</span> Add task</button>
      </div>
    </div>

    <section class="board" id="board" aria-label="Kanban board"></section>
    <div class="board-footer">
      <span>Drag a card to move it between columns</span>
      <span><span class="footer-key">⌘</span> <span class="footer-key">K</span> &nbsp;Search tasks</span>
    </div>
  </main>
</div>

<div class="modal-backdrop" id="backdrop">
  <form class="modal" id="taskForm">
    <div class="modal-head">
      <div><h2>Add a task</h2><div class="modal-sub">Add a new item to your board.</div></div>
      <button type="button" class="modal-close" id="closeModal" aria-label="Close">×</button>
    </div>
    <div class="form-row">
      <label for="taskTitle">Task title</label>
      <input class="field" id="taskTitle" maxlength="90" placeholder="What needs to be done?" required>
    </div>
    <div class="form-row">
      <label for="taskPriority">Priority</label>
      <select class="field" id="taskPriority">
        <option value="medium">Medium</option><option value="low">Low</option><option value="high">High</option>
      </select>
    </div>
    <div class="form-row">
      <label for="taskStatus">Column</label>
      <select class="field" id="taskStatus">
        <option value="todo">To do</option><option value="progress">In progress</option><option value="done">Done</option>
      </select>
    </div>
    <div class="modal-actions">
      <button type="button" class="button" id="cancelModal">Cancel</button>
      <button type="submit" class="button primary">Add task</button>
    </div>
  </form>
</div>

<script>
(() => {
  const statuses = [
    { id: "todo", title: "To do" },
    { id: "progress", title: "In progress" },
    { id: "done", title: "Done" }
  ];
  let cards = [
    { id: 1, title: "Map out onboarding flow", priority: "high", status: "todo", owner: "AM", date: "Today" },
    { id: 2, title: "Write launch announcement", priority: "medium", status: "todo", owner: "JL", date: "Jun 18" },
    { id: 3, title: "Review customer interview notes", priority: "low", status: "todo", owner: "SK", date: "Jun 20" },
    { id: 4, title: "Build responsive pricing page", priority: "high", status: "progress", owner: "AM", date: "Jun 17" },
    { id: 5, title: "QA signup and checkout flow", priority: "medium", status: "progress", owner: "JL", date: "Jun 18" },
    { id: 6, title: "Finalize visual identity", priority: "low", status: "done", owner: "SK", date: "Done" }
  ];
  const board = document.getElementById("board");
  const search = document.getElementById("search");
  const backdrop = document.getElementById("backdrop");
  const titleInput = document.getElementById("taskTitle");
  let draggedId = null;
  let query = "";

  const esc = s => String(s).replace(/[&<>"']/g, c => ({ "&":"&amp;", "<":"&lt;", ">":"&gt;", '"':"&quot;", "'":"&#39;" }[c]));
  function render() {
    board.innerHTML = statuses.map(col => {
      const visible = cards.filter(c => c.status === col.id && c.title.toLowerCase().includes(query));
      const count = cards.filter(c => c.status === col.id).length;
      return `<section class="column" data-status="${col.id}">
        <div class="column-head">
          <div class="col-label"><span class="dot"></span>${col.title}<span class="count">${count}</span></div>
          <button class="add-inline" data-add="${col.id}" title="Add task to ${col.title}" aria-label="Add task to ${col.title}">+</button>
        </div>
        <div class="cards">${visible.length ? visible.map(c => `
          <article class="card" draggable="true" data-id="${c.id}">
            <div class="card-top">
              <div class="card-title">${esc(c.title)}</div>
              <button class="delete" data-delete="${c.id}" title="Delete task" aria-label="Delete ${esc(c.title)}">
                <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M4 7h16M10 11v6m4-6v6M5 7l1 14h12l1-14M9 7V4h6v3"></path></svg>
              </button>
            </div>
            <div class="card-bottom">
              <span class="priority ${c.priority}">${c.priority[0].toUpperCase()+c.priority.slice(1)}</span>
              <span class="meta"><span class="mini-avatar">${esc(c.owner)}</span>${esc(c.date)}</span>
            </div>
          </article>`).join("") : `<div class="column-empty" style="display:block">${query ? "No matching tasks" : "Drop a task here"}</div>`}</div>
      </section>`;
    }).join("");

    board.querySelectorAll(".card").forEach(card => {
      card.addEventListener("dragstart", e => {
        draggedId = Number(card.dataset.id);
        card.classList.add("dragging");
        e.dataTransfer.effectAllowed = "move";
        e.dataTransfer.setData("text/plain", String(draggedId));
      });
      card.addEventListener("dragend", () => {
        card.classList.remove("dragging");
        board.querySelectorAll(".column").forEach(x => x.classList.remove("drag-over"));
        draggedId = null;
      });
    });
    board.querySelectorAll(".column").forEach(col => {
      col.addEventListener("dragover", e => { e.preventDefault(); col.classList.add("drag-over"); });
      col.addEventListener("dragleave", e => { if (!col.contains(e.relatedTarget)) col.classList.remove("drag-over"); });
      col.addEventListener("drop", e => {
        e.preventDefault(); col.classList.remove("drag-over");
        const id = draggedId || Number(e.dataTransfer.getData("text/plain"));
        const card = cards.find(c => c.id === id);
        if (card) { card.status = col.dataset.status; render(); }
      });
    });
    board.querySelectorAll("[data-delete]").forEach(btn => btn.addEventListener("click", () => {
      cards = cards.filter(c => c.id !== Number(btn.dataset.delete)); render();
    }));
    board.querySelectorAll("[data-add]").forEach(btn => btn.addEventListener("click", () => openForm(btn.dataset.add)));
  }

  function openForm(status = "todo") {
    document.getElementById("taskStatus").value = status;
    backdrop.classList.add("open");
    titleInput.value = "";
    setTimeout(() => titleInput.focus(), 40);
  }
  function closeForm() { backdrop.classList.remove("open"); }
  document.getElementById("openModal").addEventListener("click", () => openForm());
  document.getElementById("closeModal").addEventListener("click", closeForm);
  document.getElementById("cancelModal").addEventListener("click", closeForm);
  backdrop.addEventListener("click", e => { if (e.target === backdrop) closeForm(); });
  document.addEventListener("keydown", e => {
    if (e.key === "Escape") closeForm();
    if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "k") { e.preventDefault(); search.focus(); }
  });
  document.getElementById("taskForm").addEventListener("submit", e => {
    e.preventDefault();
    const title = titleInput.value.trim();
    if (!title) return;
    cards.unshift({
      id: Date.now(), title, priority: document.getElementById("taskPriority").value,
      status: document.getElementById("taskStatus").value, owner: "AM", date: "Today"
    });
    closeForm(); render();
  });
  search.addEventListener("input", () => { query = search.value.trim().toLowerCase(); render(); });

  document.getElementById("themeToggle").addEventListener("click", () => {
    document.body.classList.toggle("dark");
    document.getElementById("themeIcon").innerHTML = document.body.classList.contains("dark")
      ? '<circle cx="12" cy="12" r="4"></circle><path d="M12 2v2m0 16v2M4.93 4.93l1.42 1.42m11.3 11.3 1.42 1.42M2 12h2m16 0h2M4.93 19.07l1.42-1.42m11.3-11.3 1.42-1.42"></path>'
      : '<path d="M20.1 15.4A8.5 8.5 0 0 1 8.6 3.9 8.5 8.5 0 1 0 20.1 15.4Z"></path>';
  });
  render();
})();
</script>
</body>
</html>
Reasoning trace (63 tokens)
**Planning UI features**

I need to produce a polished full HTML, focusing on drag-and-drop functionality, modals, search options, and theming. I want the layout to be clear, using screenshots for reference. The app UI should be crisp and mobile-friendly, possibly with a toolbar. I’ll incorporate inline icons, either through Unicode or SVG. Card actions will include delete options, and I’m considering a three-column layout along with an empty state and a drag indicator. I’ll rely on JS and CSS for this.