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
2 min 23 s
Cost
$0.0072
Output tokens
14,293
Spent thinking
3,093 tokens
Speed
126.2 tok/s
Console errors
0
First token after
29.9 s
First visible text after
51.7 s
Prompt tokens
493
Code size
35.1 KB
Finish reason
stop
Served by
OpenAI
Model id
openai/gpt-6-luna
Reasoning sent
{"effort":"high"}
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 · 830 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>Orbit — Product launch board</title>
<style>
  * { box-sizing: border-box; }
  :root {
    color-scheme: light;
    --page: #f5f7fb;
    --surface: #ffffff;
    --surface-soft: #f8f9fc;
    --column: #eef1f7;
    --text: #20283a;
    --muted: #8490a4;
    --line: #e7eaf1;
    --accent: #6158e8;
    --accent-soft: #eeedff;
    --shadow: 0 8px 24px rgba(34, 45, 75, .055);
  }
  html[data-theme="dark"] {
    color-scheme: dark;
    --page: #151923;
    --surface: #1d2330;
    --surface-soft: #202736;
    --column: #202736;
    --text: #edf0f8;
    --muted: #9aa6bc;
    --line: #30394b;
    --accent: #9c96ff;
    --accent-soft: #302e50;
    --shadow: 0 10px 26px rgba(0, 0, 0, .18);
  }
  body {
    margin: 0;
    min-width: 320px;
    min-height: 100vh;
    background: var(--page);
    color: var(--text);
    font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    font-size: 14px;
    -webkit-font-smoothing: antialiased;
  }
  button, input, select { font: inherit; }
  button { color: inherit; }
  .app-shell { min-height: 100vh; }
  .sidebar {
    position: fixed;
    inset: 0 auto 0 0;
    width: 228px;
    display: flex;
    flex-direction: column;
    padding: 24px 15px 17px;
    background: var(--surface);
    border-right: 1px solid var(--line);
    z-index: 2;
  }
  .brand {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 0 10px;
    margin-bottom: 37px;
    color: var(--text);
    font-size: 20px;
    font-weight: 760;
    letter-spacing: -.8px;
  }
  .brand-mark {
    width: 30px; height: 30px;
    display: grid; place-items: center;
    color: #fff;
    background: linear-gradient(140deg, #8d7afa, #564fe0);
    border-radius: 10px;
    box-shadow: 0 5px 12px rgba(97, 88, 232, .25);
  }
  .side-label {
    padding: 0 10px;
    margin: 0 0 10px;
    color: var(--muted);
    font-size: 10px;
    font-weight: 750;
    letter-spacing: 1.1px;
    text-transform: uppercase;
  }
  .workspace-switch {
    display: flex; align-items: center; gap: 10px;
    width: 100%;
    border: 1px solid var(--line);
    border-radius: 10px;
    background: var(--surface-soft);
    padding: 9px 10px;
    margin-bottom: 29px;
    text-align: left;
  }
  .workspace-logo {
    display: grid; place-items: center;
    width: 31px; height: 31px; flex: none;
    border-radius: 9px;
    background: #e8f3ff;
    color: #3c82d6;
    font-weight: 750;
    font-size: 13px;
  }
  .workspace-name { min-width: 0; flex: 1; }
  .workspace-name strong { display: block; font-size: 12px; font-weight: 690; }
  .workspace-name span { display: block; margin-top: 2px; color: var(--muted); font-size: 10px; }
  .nav-list { display: grid; gap: 5px; }
  .nav-item {
    display: flex; align-items: center; gap: 12px;
    height: 40px;
    padding: 0 11px;
    border-radius: 8px;
    text-decoration: none;
    color: #758198;
    font-size: 13px;
    font-weight: 570;
  }
  html[data-theme="dark"] .nav-item { color: var(--muted); }
  .nav-item svg { width: 17px; height: 17px; }
  .nav-item.active {
    background: var(--accent-soft);
    color: var(--accent);
    font-weight: 670;
  }
  .nav-count {
    margin-left: auto;
    font-size: 11px;
    color: var(--muted);
  }
  .sidebar-bottom { margin-top: auto; }
  .upgrade-card {
    padding: 13px;
    margin: 0 3px 17px;
    border: 1px solid var(--line);
    border-radius: 11px;
    background: var(--surface-soft);
  }
  .upgrade-card strong { display: block; font-size: 12px; }
  .upgrade-card p { margin: 6px 0 10px; color: var(--muted); font-size: 11px; line-height: 1.5; }
  .upgrade-card button {
    border: 0; padding: 0; background: none;
    color: var(--accent); font-size: 11px; font-weight: 700; cursor: pointer;
  }
  .profile {
    display: flex; align-items: center; gap: 10px;
    padding: 12px 8px 0;
    border-top: 1px solid var(--line);
  }
  .avatar {
    width: 33px; height: 33px; flex: none;
    display: grid; place-items: center;
    border-radius: 50%;
    color: #735045;
    background: #f5d6c7;
    font-size: 11px; font-weight: 750;
  }
  .profile-info { min-width: 0; flex: 1; }
  .profile-info strong { display: block; font-size: 11px; }
  .profile-info span { color: var(--muted); font-size: 10px; }

  .main-area { margin-left: 228px; min-height: 100vh; }
  .topbar {
    height: 65px;
    display: flex; align-items: center; justify-content: space-between;
    padding: 0 33px;
    background: var(--surface);
    border-bottom: 1px solid var(--line);
  }
  .crumbs { display: flex; align-items: center; gap: 9px; color: var(--muted); font-size: 12px; }
  .crumbs strong { color: var(--text); font-weight: 620; }
  .crumbs svg { width: 13px; height: 13px; }
  .top-actions { display: flex; align-items: center; gap: 13px; }
  .icon-button {
    width: 35px; height: 35px;
    display: grid; place-items: center;
    border: 1px solid var(--line);
    border-radius: 9px;
    background: var(--surface);
    cursor: pointer;
    color: var(--muted);
    transition: background .15s, color .15s;
  }
  .icon-button:hover { background: var(--surface-soft); color: var(--text); }
  .icon-button svg { width: 17px; height: 17px; }
  .top-avatar {
    width: 32px; height: 32px;
    display: grid; place-items: center;
    border-radius: 50%;
    background: #dce8ff; color: #4866a1;
    font-size: 10px; font-weight: 750;
  }
  .content { max-width: 1600px; margin: 0 auto; padding: 29px 32px 35px; }
  .page-heading {
    display: flex; align-items: flex-start; justify-content: space-between;
    margin-bottom: 23px;
  }
  .eyebrow {
    display: flex; align-items: center; gap: 7px;
    margin-bottom: 7px;
    color: var(--muted); font-size: 11px; font-weight: 570;
  }
  .eyebrow .dot { width: 7px; height: 7px; border-radius: 50%; background: #50c79b; }
  h1 { margin: 0; font-size: 25px; line-height: 1.2; letter-spacing: -.85px; font-weight: 730; }
  .subtitle { margin: 7px 0 0; color: var(--muted); font-size: 12px; }
  .heading-meta {
    display: flex; align-items: center; gap: 9px;
    color: var(--muted); font-size: 11px;
    padding-top: 19px;
  }
  .mini-avatars { display: flex; padding-left: 5px; }
  .mini-avatars span {
    width: 25px; height: 25px; margin-left: -6px;
    display: grid; place-items: center; border: 2px solid var(--page);
    border-radius: 50%; font-size: 8px; font-weight: 750;
  }
  .mini-avatars span:nth-child(1) { background: #f1d9ca; color: #885844; }
  .mini-avatars span:nth-child(2) { background: #d5e7f7; color: #456d8f; }
  .mini-avatars span:nth-child(3) { background: #e5dcff; color: #6753a8; }
  .mini-avatars span:nth-child(4) { background: #d9efdf; color: #46734d; }
  .board-toolbar {
    display: flex; align-items: center; justify-content: space-between;
    gap: 14px;
    margin-bottom: 17px;
  }
  .board-mode {
    display: flex; align-items: center; gap: 8px;
    color: var(--text); font-size: 12px; font-weight: 660;
  }
  .board-mode svg { width: 16px; height: 16px; color: var(--accent); }
  .board-actions { display: flex; align-items: center; gap: 9px; }
  .search-wrap {
    width: 220px; height: 36px;
    display: flex; align-items: center; gap: 8px;
    padding: 0 10px;
    border: 1px solid var(--line);
    border-radius: 8px;
    background: var(--surface);
    color: var(--muted);
  }
  .search-wrap svg { width: 15px; height: 15px; flex: none; }
  .search-wrap input {
    width: 100%; min-width: 0;
    border: 0; outline: 0; background: transparent;
    color: var(--text); font-size: 11px;
  }
  .search-wrap input::placeholder { color: #a2aabc; }
  .primary-button {
    height: 36px;
    display: inline-flex; align-items: center; justify-content: center; gap: 7px;
    padding: 0 13px;
    border: 0; border-radius: 8px;
    background: #6158e8; color: #fff;
    font-size: 11px; font-weight: 670;
    box-shadow: 0 3px 8px rgba(97, 88, 232, .2);
    cursor: pointer;
    transition: background .15s, transform .15s;
  }
  .primary-button:hover { background: #5047d3; transform: translateY(-1px); }
  .primary-button svg { width: 15px; height: 15px; }
  .board {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    align-items: stretch;
    gap: 16px;
  }
  .column {
    min-width: 0;
    min-height: 515px;
    display: flex; flex-direction: column;
    padding: 12px 11px 13px;
    border-radius: 11px;
    background: var(--column);
    border: 1px solid transparent;
    transition: border-color .15s, background .15s;
  }
  .column.is-drop-target {
    border-color: #8d86f5;
    background: color-mix(in srgb, var(--column) 90%, #9b95ff 10%);
  }
  .column-header {
    display: flex; align-items: center; justify-content: space-between;
    padding: 1px 3px 12px;
  }
  .column-title-wrap { display: flex; align-items: center; gap: 8px; }
  .status-dot { width: 8px; height: 8px; border-radius: 50%; }
  .todo-dot { background: #8b94a8; }
  .progress-dot { background: #6688ed; }
  .done-dot { background: #4ab98b; }
  .column-title { margin: 0; font-size: 12px; font-weight: 700; letter-spacing: -.1px; }
  .count {
    min-width: 21px; height: 20px;
    display: grid; place-items: center;
    padding: 0 6px;
    border-radius: 6px;
    background: rgba(126, 138, 161, .13);
    color: var(--muted); font-size: 10px; font-weight: 700;
  }
  .column-menu {
    width: 25px; height: 25px;
    display: grid; place-items: center;
    border: 0; border-radius: 6px; background: transparent;
    color: var(--muted); cursor: pointer;
  }
  .column-menu:hover { background: rgba(128, 138, 160, .12); }
  .column-menu svg { width: 16px; height: 16px; }
  .card-list { display: flex; flex: 1; flex-direction: column; gap: 10px; min-height: 110px; }
  .task-card {
    position: relative;
    padding: 13px 13px 11px;
    border: 1px solid var(--line);
    border-radius: 9px;
    background: var(--surface);
    box-shadow: 0 2px 5px rgba(35, 47, 74, .025);
    cursor: grab;
    transition: box-shadow .15s, transform .15s, opacity .15s;
  }
  .task-card:hover { transform: translateY(-1px); box-shadow: var(--shadow); }
  .task-card:active { cursor: grabbing; }
  .task-card.is-dragging { opacity: .38; }
  .task-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
  .priority {
    display: inline-flex; align-items: center; gap: 5px;
    padding: 4px 7px;
    border-radius: 5px;
    font-size: 9px; font-weight: 680;
    letter-spacing: .1px;
    text-transform: capitalize;
  }
  .priority::before { content: ""; width: 5px; height: 5px; border-radius: 50%; background: currentColor; }
  .priority-high { color: #d75d69; background: #fff0f1; }
  .priority-medium { color: #c58b2d; background: #fff6e6; }
  .priority-low { color: #3c9a78; background: #eaf8f1; }
  html[data-theme="dark"] .priority-high { background: #442b35; color: #ff9aa3; }
  html[data-theme="dark"] .priority-medium { background: #403724; color: #f2c36b; }
  html[data-theme="dark"] .priority-low { background: #233d36; color: #74d2ad; }
  .delete-card {
    width: 25px; height: 25px; display: grid; place-items: center;
    border: 0; border-radius: 6px; background: transparent;
    color: #a5adbb; opacity: .62; cursor: pointer;
  }
  .delete-card:hover { color: #d95362; background: rgba(217, 83, 98, .09); opacity: 1; }
  .delete-card svg { width: 14px; height: 14px; }
  .task-card h3 {
    margin: 7px 0 5px;
    color: var(--text);
    font-size: 12px; line-height: 1.42; font-weight: 680; letter-spacing: -.1px;
  }
  .task-card p {
    margin: 0;
    color: var(--muted);
    font-size: 10px; line-height: 1.5;
  }
  .task-footer {
    display: flex; align-items: center; justify-content: space-between; gap: 7px;
    margin-top: 12px; padding-top: 9px;
    border-top: 1px solid var(--line);
  }
  .task-tag {
    max-width: 58%;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    padding: 4px 6px;
    border-radius: 4px;
    background: var(--surface-soft);
    color: #8791a4;
    font-size: 9px; font-weight: 570;
  }
  .task-meta { display: flex; align-items: center; gap: 5px; color: var(--muted); font-size: 9px; white-space: nowrap; }
  .task-meta svg { width: 12px; height: 12px; }
  .drop-marker {
    height: 4px; min-height: 4px; flex: none;
    margin: 0 3px;
    border-radius: 4px;
    background: #786ff0;
    box-shadow: 0 0 0 3px rgba(120, 111, 240, .12);
  }
  .empty-state {
    display: grid; place-items: center;
    min-height: 92px; flex: 1;
    color: var(--muted); font-size: 11px; text-align: center;
    border: 1px dashed rgba(132, 144, 164, .32);
    border-radius: 8px;
  }

  .modal-backdrop {
    position: fixed; inset: 0; z-index: 10;
    display: none; align-items: center; justify-content: center;
    padding: 18px;
    background: rgba(19, 24, 38, .48);
    backdrop-filter: blur(3px);
  }
  .modal-backdrop.open { display: flex; }
  .modal {
    width: min(100%, 420px);
    padding: 23px;
    border: 1px solid var(--line);
    border-radius: 14px;
    background: var(--surface);
    box-shadow: 0 24px 80px rgba(10, 15, 30, .24);
    animation: modal-in .18s ease-out;
  }
  @keyframes modal-in { from { opacity: 0; transform: translateY(7px) scale(.99); } to { opacity: 1; transform: none; } }
  .modal-heading { display: flex; align-items: flex-start; justify-content: space-between; margin-bottom: 20px; }
  .modal-heading h2 { margin: 0; font-size: 18px; letter-spacing: -.35px; }
  .modal-heading p { margin: 5px 0 0; color: var(--muted); font-size: 11px; }
  .close-modal {
    width: 29px; height: 29px; display: grid; place-items: center;
    border: 0; border-radius: 7px; background: var(--surface-soft); color: var(--muted); cursor: pointer;
  }
  .close-modal svg { width: 15px; height: 15px; }
  .form-field { display: grid; gap: 7px; margin-bottom: 15px; }
  .form-field label { font-size: 11px; font-weight: 660; }
  .form-field input, .form-field select {
    width: 100%; height: 39px; padding: 0 11px;
    border: 1px solid var(--line); border-radius: 8px;
    outline: 0; background: var(--surface); color: var(--text); font-size: 12px;
  }
  .form-field input:focus, .form-field select:focus { border-color: #8c85f1; box-shadow: 0 0 0 3px rgba(97, 88, 232, .11); }
  .form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
  .modal-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 22px; }
  .secondary-button {
    height: 36px; padding: 0 13px; border: 1px solid var(--line); border-radius: 8px;
    background: var(--surface); color: var(--text); font-size: 11px; font-weight: 620; cursor: pointer;
  }
  .form-error { display: none; margin-top: -5px; color: #d95362; font-size: 10px; }
  .form-error.visible { display: block; }

  @media (max-width: 1000px) {
    .sidebar { width: 205px; }
    .main-area { margin-left: 205px; }
    .content { padding-left: 22px; padding-right: 22px; }
    .topbar { padding: 0 22px; }
    .board { gap: 11px; }
    .column { padding-left: 9px; padding-right: 9px; }
    .task-card { padding-left: 11px; padding-right: 11px; }
  }
  @media (max-width: 760px) {
    .sidebar { display: none; }
    .main-area { margin-left: 0; }
    .topbar { height: 57px; padding: 0 18px; }
    .content { padding: 24px 18px 30px; }
    .board { grid-template-columns: minmax(0, 1fr); gap: 13px; }
    .column { min-height: 0; padding: 12px; }
    .card-list { min-height: 85px; }
    .heading-meta { display: none; }
    .page-heading { margin-bottom: 19px; }
    .column-header { padding-bottom: 10px; }
    .empty-state { min-height: 64px; }
  }
  @media (max-width: 460px) {
    .content { padding: 20px 14px 28px; }
    .topbar { padding: 0 14px; }
    .crumbs { font-size: 11px; gap: 6px; }
    .top-actions { gap: 8px; }
    h1 { font-size: 23px; }
    .subtitle { font-size: 11px; }
    .board-toolbar { align-items: stretch; flex-direction: column; gap: 11px; }
    .board-actions { width: 100%; }
    .search-wrap { flex: 1; width: auto; }
    .primary-button { padding: 0 11px; white-space: nowrap; }
    .column { min-height: 0; }
  }
</style>
</head>
<body>
<div class="app-shell">
  <aside class="sidebar">
    <div class="brand">
      <span class="brand-mark">
        <svg width="18" height="18" viewBox="0 0 24 24" fill="none" aria-hidden="true"><path d="M5 16.5 12 4l7 12.5H5Z" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/><path d="M8.2 16.5 12 10l3.8 6.5" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/></svg>
      </span>
      orbit
    </div>
    <p class="side-label">Workspace</p>
    <button class="workspace-switch" type="button" aria-label="Current workspace: Studio North">
      <span class="workspace-logo">SN</span>
      <span class="workspace-name"><strong>Studio North</strong><span>Free workspace</span></span>
      <svg width="14" height="14" viewBox="0 0 24 24" fill="none" aria-hidden="true"><path d="m7 10 5 5 5-5" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg>
    </button>
    <p class="side-label">Workspace</p>
    <nav class="nav-list" aria-label="Main navigation">
      <a class="nav-item active" href="#" aria-current="page">
        <svg viewBox="0 0 24 24" fill="none" aria-hidden="true"><rect x="3.5" y="4" width="7" height="7" rx="1.5" stroke="currentColor" stroke-width="1.7"/><rect x="13.5" y="4" width="7" height="7" rx="1.5" stroke="currentColor" stroke-width="1.7"/><rect x="3.5" y="14" width="7" height="7" rx="1.5" stroke="currentColor" stroke-width="1.7"/><rect x="13.5" y="14" width="7" height="7" rx="1.5" stroke="currentColor" stroke-width="1.7"/></svg>
        Projects <span class="nav-count">8</span>
      </a>
      <a class="nav-item" href="#">
        <svg viewBox="0 0 24 24" fill="none" aria-hidden="true"><path d="M4 19.5h16M6 16V8m6 8V4m6 12v-5" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/><path d="M4 19.5h16" stroke="currentColor" stroke-width="1.8"/></svg>
        Roadmap
      </a>
      <a class="nav-item" href="#">
        <svg viewBox="0 0 24 24" fill="none" aria-hidden="true"><rect x="3.5" y="5" width="17" height="15.5" rx="2" stroke="currentColor" stroke-width="1.7"/><path d="M7.5 3.5v3M16.5 3.5v3M4 9.5h16" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"/></svg>
        Calendar
      </a>
      <a class="nav-item" href="#">
        <svg viewBox="0 0 24 24" fill="none" aria-hidden="true"><circle cx="10.8" cy="10.8" r="6.8" stroke="currentColor" stroke-width="1.7"/><path d="m16 16 4.5 4.5" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"/></svg>
        Discover
      </a>
    </nav>
    <div class="sidebar-bottom">
      <div class="upgrade-card">
        <strong>Make room for more</strong>
        <p>Bring your team's work together and keep every project moving.</p>
        <button type="button">Explore plans <span aria-hidden="true">→</span></button>
      </div>
      <div class="profile">
        <div class="avatar">MK</div>
        <div class="profile-info"><strong>Morgan Kim</strong><span>morgan@studionorth.co</span></div>
        <svg width="15" height="15" viewBox="0 0 24 24" fill="none" aria-hidden="true" style="color:var(--muted)"><path d="m9 18 6-6-6-6" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg>
      </div>
    </div>
  </aside>

  <div class="main-area">
    <header class="topbar">
      <div class="crumbs">
        <span>Projects</span>
        <svg viewBox="0 0 24 24" fill="none" aria-hidden="true"><path d="m9 18 6-6-6-6" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg>
        <strong>Product launch</strong>
      </div>
      <div class="top-actions">
        <button class="icon-button" id="themeToggle" type="button" aria-label="Switch to dark theme" title="Toggle theme">
          <svg id="themeIcon" viewBox="0 0 24 24" fill="none" aria-hidden="true"><circle cx="12" cy="12" r="4" stroke="currentColor" stroke-width="1.7"/><path d="M12 2.5v2M12 19.5v2M4.7 4.7l1.4 1.4m11.8 11.8 1.4 1.4M2.5 12h2m15 0h2M4.7 19.3l1.4-1.4M17.9 6.1l1.4-1.4" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"/></svg>
        </button>
        <div class="top-avatar" aria-label="Morgan Kim">MK</div>
      </div>
    </header>

    <main class="content">
      <div class="page-heading">
        <div>
          <div class="eyebrow"><span class="dot"></span> Studio North <span aria-hidden="true">/</span> Active project</div>
          <h1>Product launch</h1>
          <p class="subtitle">Plan, track, and ship your next big thing.</p>
        </div>
        <div class="heading-meta">
          <div class="mini-avatars" aria-label="4 project members"><span>AL</span><span>JT</span><span>MK</span><span>+1</span></div>
          <span>4 members</span>
        </div>
      </div>

      <div class="board-toolbar">
        <div class="board-mode">
          <svg viewBox="0 0 24 24" fill="none" aria-hidden="true"><rect x="3.5" y="4" width="5" height="16" rx="1.3" stroke="currentColor" stroke-width="1.7"/><rect x="10" y="4" width="5" height="11" rx="1.3" stroke="currentColor" stroke-width="1.7"/><rect x="16.5" y="4" width="4" height="13" rx="1.3" stroke="currentColor" stroke-width="1.7"/></svg>
          Board view
        </div>
        <div class="board-actions">
          <label class="search-wrap">
            <svg viewBox="0 0 24 24" fill="none" aria-hidden="true"><circle cx="10.8" cy="10.8" r="6.8" stroke="currentColor" stroke-width="1.8"/><path d="m16 16 4.5 4.5" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg>
            <input id="searchInput" type="search" placeholder="Search tasks..." aria-label="Search cards by title">
          </label>
          <button class="primary-button" id="openModal" type="button">
            <svg viewBox="0 0 24 24" fill="none" aria-hidden="true"><path d="M12 5v14M5 12h14" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>
            Add task
          </button>
        </div>
      </div>

      <section class="board" id="board" aria-label="Kanban board">
        <section class="column" data-column="todo" aria-labelledby="heading-todo">
          <header class="column-header">
            <div class="column-title-wrap"><span class="status-dot todo-dot"></span><h2 class="column-title" id="heading-todo">To do</h2><span class="count" data-count="todo">0</span></div>
            <button class="column-menu" type="button" aria-label="To do column options"><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><circle cx="5" cy="12" r="1.6"/><circle cx="12" cy="12" r="1.6"/><circle cx="19" cy="12" r="1.6"/></svg></button>
          </header>
          <div class="card-list" data-list="todo"></div>
        </section>
        <section class="column" data-column="progress" aria-labelledby="heading-progress">
          <header class="column-header">
            <div class="column-title-wrap"><span class="status-dot progress-dot"></span><h2 class="column-title" id="heading-progress">In progress</h2><span class="count" data-count="progress">0</span></div>
            <button class="column-menu" type="button" aria-label="In progress column options"><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><circle cx="5" cy="12" r="1.6"/><circle cx="12" cy="12" r="1.6"/><circle cx="19" cy="12" r="1.6"/></svg></button>
          </header>
          <div class="card-list" data-list="progress"></div>
        </section>
        <section class="column" data-column="done" aria-labelledby="heading-done">
          <header class="column-header">
            <div class="column-title-wrap"><span class="status-dot done-dot"></span><h2 class="column-title" id="heading-done">Done</h2><span class="count" data-count="done">0</span></div>
            <button class="column-menu" type="button" aria-label="Done column options"><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><circle cx="5" cy="12" r="1.6"/><circle cx="12" cy="12" r="1.6"/><circle cx="19" cy="12" r="1.6"/></svg></button>
          </header>
          <div class="card-list" data-list="done"></div>
        </section>
      </section>
    </main>
  </div>
</div>

<div class="modal-backdrop" id="modalBackdrop" role="presentation">
  <section class="modal" role="dialog" aria-modal="true" aria-labelledby="modalTitle">
    <div class="modal-heading">
      <div><h2 id="modalTitle">Add a task</h2><p>Give your team a clear next step.</p></div>
      <button class="close-modal" id="closeModal" type="button" aria-label="Close dialog"><svg viewBox="0 0 24 24" fill="none" aria-hidden="true"><path d="m6 6 12 12M18 6 6 18" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg></button>
    </div>
    <form id="taskForm">
      <div class="form-field">
        <label for="taskTitle">Task title <span style="color:#d95362">*</span></label>
        <input id="taskTitle" name="title" type="text" maxlength="100" placeholder="e.g. Prepare launch announcement" required>
        <div class="form-error" id="formError">Please enter a task title.</div>
      </div>
      <div class="form-row">
        <div class="form-field">
          <label for="taskPriority">Priority</label>
          <select id="taskPriority" name="priority">
            <option value="low">Low</option><option value="medium" selected>Medium</option><option value="high">High</option>
          </select>
        </div>
        <div class="form-field">
          <label for="taskColumn">Column</label>
          <select id="taskColumn" name="column">
            <option value="todo" selected>To do</option><option value="progress">In progress</option><option value="done">Done</option>
          </select>
        </div>
      </div>
      <div class="modal-actions">
        <button class="secondary-button" id="cancelModal" type="button">Cancel</button>
        <button class="primary-button" type="submit">Create task</button>
      </div>
    </form>
  </section>
</div>

<script>
(() => {
  const boardState = {
    todo: [
      { id: "t1", title: "Finalize launch messaging", description: "Align the key story across web, email, and social.", priority: "high", tag: "Marketing", date: "Due Jun 18" },
      { id: "t2", title: "QA signup flow on mobile", description: "Check the complete onboarding path on iOS and Android.", priority: "medium", tag: "Product", date: "Due Jun 20" }
    ],
    progress: [
      { id: "t3", title: "Design landing page", description: "Polish the hero section and responsive layouts.", priority: "high", tag: "Design", date: "Due Jun 17" },
      { id: "t4", title: "Set up launch analytics", description: "Define events and build a lightweight launch dashboard.", priority: "medium", tag: "Engineering", date: "Due Jun 19" }
    ],
    done: [
      { id: "t5", title: "Confirm launch date", description: "Lock the release window with product and sales.", priority: "low", tag: "Planning", date: "Completed" },
      { id: "t6", title: "Collect customer quotes", description: "Gather approved testimonials for the campaign.", priority: "low", tag: "Research", date: "Completed" }
    ]
  };
  const columns = ["todo", "progress", "done"];
  const board = document.getElementById("board");
  const searchInput = document.getElementById("searchInput");
  const backdrop = document.getElementById("modalBackdrop");
  const form = document.getElementById("taskForm");
  const titleInput = document.getElementById("taskTitle");
  const formError = document.getElementById("formError");
  let draggedId = null;
  let idCounter = 7;

  const escapeHTML = (value) => String(value).replace(/[&<>"']/g, char => ({
    "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;"
  })[char]);

  function cardMarkup(task) {
    const priority = ["low", "medium", "high"].includes(task.priority) ? task.priority : "medium";
    return `<article class="task-card" draggable="true" data-id="${escapeHTML(task.id)}" aria-label="${escapeHTML(task.title)}">
      <div class="task-top">
        <span class="priority priority-${priority}">${priority}</span>
        <button class="delete-card" type="button" aria-label="Delete ${escapeHTML(task.title)}" title="Delete task">
          <svg viewBox="0 0 24 24" fill="none" aria-hidden="true"><path d="M4.5 7h15M9 7V4.5h6V7m-8 0 .8 13h8.4L17 7m-5 3v6m-3-6 .4 6m6.6-6-.4 6" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/></svg>
        </button>
      </div>
      <h3>${escapeHTML(task.title)}</h3>
      ${task.description ? `<p>${escapeHTML(task.description)}</p>` : ""}
      <div class="task-footer">
        <span class="task-tag">${escapeHTML(task.tag || "General")}</span>
        <span class="task-meta">
          <svg viewBox="0 0 24 24" fill="none" aria-hidden="true"><rect x="4" y="5" width="16" height="15" rx="2" stroke="currentColor" stroke-width="1.6"/><path d="M8 3.5v3M16 3.5v3M4.5 9h15" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/></svg>
          ${escapeHTML(task.date || "Added just now")}
        </span>
      </div>
    </article>`;
  }

  function renderBoard() {
    const query = searchInput.value.trim().toLowerCase();
    columns.forEach(key => {
      const list = board.querySelector(`[data-list="${key}"]`);
      const visible = boardState[key].filter(task => task.title.toLowerCase().includes(query));
      board.querySelector(`[data-count="${key}"]`).textContent = visible.length;
      list.innerHTML = visible.length
        ? visible.map(cardMarkup).join("")
        : `<div class="empty-state">${query ? "No matching tasks" : "Drop a task here"}</div>`;
    });
  }

  function openModal() {
    backdrop.classList.add("open");
    formError.classList.remove("visible");
    titleInput.value = "";
    document.getElementById("taskPriority").value = "medium";
    document.getElementById("taskColumn").value = "todo";
    requestAnimationFrame(() => titleInput.focus());
  }
  function closeModal() {
    backdrop.classList.remove("open");
    document.getElementById("openModal").focus();
  }

  document.getElementById("openModal").addEventListener("click", openModal);
  document.getElementById("closeModal").addEventListener("click", closeModal);
  document.getElementById("cancelModal").addEventListener("click", closeModal);
  backdrop.addEventListener("click", event => { if (event.target === backdrop) closeModal(); });
  document.addEventListener("keydown", event => {
    if (event.key === "Escape" && backdrop.classList.contains("open")) closeModal();
  });
  form.addEventListener("submit", event => {
    event.preventDefault();
    const title = titleInput.value.trim();
    if (!title) {
      formError.classList.add("visible");
      titleInput.focus();
      return;
    }
    const key = document.getElementById("taskColumn").value;
    boardState[key].push({
      id: `t${idCounter++}`,
      title,
      description: "A new task for the product launch.",
      priority: document.getElementById("taskPriority").value,
      tag: "New task",
      date: "Added just now"
    });
    renderBoard();
    closeModal();
  });
  searchInput.addEventListener("input", renderBoard);

  board.addEventListener("click", event => {
    const button = event.target.closest(".delete-card");
    if (!button) return;
    const card = button.closest(".task-card");
    if (!card) return;
    const id = card.dataset.id;
    columns.forEach(key => { boardState[key] = boardState[key].filter(task => task.id !== id); });
    renderBoard();
  });

  board.addEventListener("dragstart", event => {
    const card = event.target.closest(".task-card");
    if (!card) return;
    draggedId = card.dataset.id;
    event.dataTransfer.effectAllowed = "move";
    event.dataTransfer.setData("text/plain", draggedId);
    requestAnimationFrame(() => card.classList.add("is-dragging"));
  });

  board.addEventListener("dragover", event => {
    const list = event.target.closest(".card-list");
    if (!list || !draggedId) return;
    event.preventDefault();
    event.dataTransfer.dropEffect = "move";
    board.querySelectorAll(".column.is-drop-target").forEach(column => column.classList.remove("is-drop-target"));
    list.closest(".column").classList.add("is-drop-target");

    let marker = board.querySelector(".drop-marker");
    if (!marker) {
      marker = document.createElement("div");
      marker.className = "drop-marker";
      marker.setAttribute("aria-hidden", "true");
    }
    if (marker.parentElement !== list) list.appendChild(marker);

    const cards = Array.from(list.querySelectorAll(".task-card")).filter(card => card.dataset.id !== draggedId);
    let before = null;
    for (const card of cards) {
      const rect = card.getBoundingClientRect();
      if (event.clientY < rect.top + rect.height / 2) { before = card; break; }
    }
    if (before) list.insertBefore(marker, before);
    else list.appendChild(marker);
  });

  board.addEventListener("dragleave", event => {
    const list = event.target.closest(".card-list");
    if (list && (!event.relatedTarget || !list.contains(event.relatedTarget))) {
      list.closest(".column").classList.remove("is-drop-target");
    }
  });

  board.addEventListener("drop", event => {
    const list = event.target.closest(".card-list");
    if (!list || !draggedId) return;
    event.preventDefault();
    const destination = list.dataset.list;
    const marker = list.querySelector(".drop-marker");
    let nextCard = marker ? marker.nextElementSibling : null;
    while (nextCard && (!nextCard.classList.contains("task-card") || nextCard.dataset.id === draggedId)) {
      nextCard = nextCard.nextElementSibling;
    }

    let movedTask = null;
    columns.forEach(key => {
      const index = boardState[key].findIndex(task => task.id === draggedId);
      if (index !== -1) movedTask = boardState[key].splice(index, 1)[0];
    });
    if (movedTask) {
      let insertionIndex = nextCard
        ? boardState[destination].findIndex(task => task.id === nextCard.dataset.id)
        : boardState[destination].length;
      if (insertionIndex < 0) insertionIndex = boardState[destination].length;
      boardState[destination].splice(insertionIndex, 0, movedTask);
    }
    draggedId = null;
    clearDragStyles();
    renderBoard();
  });

  board.addEventListener("dragend", () => {
    draggedId = null;
    clearDragStyles();
  });

  function clearDragStyles() {
    board.querySelectorAll(".drop-marker").forEach(marker => marker.remove());
    board.querySelectorAll(".is-dragging").forEach(card => card.classList.remove("is-dragging"));
    board.querySelectorAll(".is-drop-target").forEach(column => column.classList.remove("is-drop-target"));
  }

  const themeToggle = document.getElementById("themeToggle");
  themeToggle.addEventListener("click", () => {
    const dark = document.documentElement.dataset.theme !== "dark";
    document.documentElement.dataset.theme = dark ? "dark" : "light";
    themeToggle.setAttribute("aria-label", dark ? "Switch to light theme" : "Switch to dark theme");
    document.getElementById("themeIcon").innerHTML = dark
      ? '<path d="M20.2 15.3A8.5 8.5 0 0 1 8.7 3.8 8.7 8.7 0 1 0 20.2 15.3Z" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"/>'
      : '<circle cx="12" cy="12" r="4" stroke="currentColor" stroke-width="1.7"/><path d="M12 2.5v2M12 19.5v2M4.7 4.7l1.4 1.4m11.8 11.8 1.4 1.4M2.5 12h2m15 0h2M4.7 19.3l1.4-1.4M17.9 6.1l1.4-1.4" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"/>';
  });

  renderBoard();
})();
</script>
</body>
</html>
Reasoning trace (3,093 tokens)
**Evaluating responsive design**

I’m considering a layout where the sidebar is 224 pixels wide, meaning the main content is 1056 pixels wide. The padding and gap are carefully calculated too. At a viewport of 375 pixels, I wonder if I should hide the sidebar entirely for better mobile usability. I think it’s necessary to stack the columns vertically for mobile to avoid horizontal scrolling. Overall, I need to ensure the board can adapt without a minimum width.**Considering task card details**

I'm thinking about having six task cards, each about 156 pixels high, with two cards per column. I need to make sure to inject the icon SVG directly into the string, which seems fine. I'll also include an aria-label for the delete button and add a colored badge for priority, complete with a dot and text. Cards should have a hover transition, and I need to consider how to show filtered counts and handle search no-results views. Maybe the task cards should be both clickable and draggable, with a delete click opening a modal backdrop for confirmation. Plus, I need to ensure the drag and sorting styles have a marker after inserting items.**Considering data transfer logic**

I’m focusing on handling data transfer during a drag-and-drop action. First, I check if there’s a valid dragged item and if the closest target is a list. If either is missing, I want to exit early. Then I’ll use preventDefault to control the drop effect. I plan to add a class to the parent element to highlight it as a drop target, and I need to make sure a marker is properly placed in the list.**Implementing user interface features**

I’m thinking through some design elements for our user interface. I'll ensure that every keystroke is rendered properly without needing to rerender the input. The top bar should display the brand and include a navigation workspace while the responsive side rail can be hidden. I want to keep dark colors for backgrounds and surfaces. It's important that all cards look evident in screenshots, and I’ll implement icon paths without any external resources.