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
6 min 3 s
Cost
$0.022
Output tokens
44,345
Spent thinking
28,978 tokens
Speed
123.3 tok/s
Console errors
0
First token after
3.4 s
First visible text after
4 min 29 s
Prompt tokens
493
Code size
54.3 KB
Finish reason
stop
Served by
OpenAI
Model id
openai/gpt-6-luna
Reasoning sent
{"effort":"max"}
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 · 2045 lines

<!DOCTYPE html>
<html lang="en" data-theme="light">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Product sprint · Morrow</title>
  <style>
    :root {
      color-scheme: light;
      --canvas: #f6f7fb;
      --header: #ffffff;
      --surface: #ffffff;
      --lane: #f0f2f7;
      --card: #ffffff;
      --text: #202638;
      --muted: #7a8497;
      --quiet: #a2aabc;
      --line: #e4e7ee;
      --line-strong: #d9deea;
      --accent: #6659dc;
      --accent-hover: #574bc9;
      --accent-soft: #f0efff;
      --ring: rgba(102, 89, 220, 0.18);
      --tag-bg: #f1f3f7;
      --tag-text: #687388;
      --card-shadow: 0 2px 4px rgba(27, 35, 57, 0.025), 0 7px 18px rgba(35, 43, 70, 0.045);
      --card-hover-shadow: 0 7px 20px rgba(35, 43, 70, 0.09);
      --modal-shadow: 0 24px 80px rgba(22, 27, 43, 0.22);
      --danger: #c85e58;
      --danger-soft: #fff1f0;
      --drop-bg: #eeecff;
      --drop-shadow: rgba(102, 89, 220, 0.09);

      --high-bg: #fff0ee;
      --high-text: #bf514b;
      --high-dot: #e16b61;
      --medium-bg: #fff6e5;
      --medium-text: #a97720;
      --medium-dot: #e6aa43;
      --low-bg: #eaf7f1;
      --low-text: #32856a;
      --low-dot: #43ad87;
    }

    :root[data-theme="dark"] {
      color-scheme: dark;
      --canvas: #12151f;
      --header: #191d2a;
      --surface: #202637;
      --lane: #1a2030;
      --card: #222a3a;
      --text: #edf0f7;
      --muted: #9ba6ba;
      --quiet: #78849a;
      --line: #2d3548;
      --line-strong: #394359;
      --accent: #938aff;
      --accent-hover: #a59eff;
      --accent-soft: #2d2b4b;
      --ring: rgba(147, 138, 255, 0.24);
      --tag-bg: #2b3445;
      --tag-text: #b1bbcd;
      --card-shadow: 0 3px 8px rgba(0, 0, 0, 0.14);
      --card-hover-shadow: 0 9px 24px rgba(0, 0, 0, 0.25);
      --modal-shadow: 0 24px 80px rgba(0, 0, 0, 0.48);
      --danger: #f08b85;
      --danger-soft: #3b282c;
      --drop-bg: #292744;
      --drop-shadow: rgba(147, 138, 255, 0.11);

      --high-bg: #3d292d;
      --high-text: #f19b92;
      --high-dot: #ef8178;
      --medium-bg: #3b3326;
      --medium-text: #e5bd71;
      --medium-dot: #e2b458;
      --low-bg: #24392f;
      --low-text: #82cfad;
      --low-dot: #61c49b;
    }

    * {
      box-sizing: border-box;
    }

    html {
      min-width: 320px;
      scroll-behavior: smooth;
    }

    body {
      min-width: 320px;
      min-height: 100vh;
      margin: 0;
      overflow-x: hidden;
      background: var(--canvas);
      color: var(--text);
      font-family: Inter, ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
      font-size: 14px;
      -webkit-font-smoothing: antialiased;
      transition: background-color 180ms ease, color 180ms ease;
    }

    button,
    input,
    select {
      font: inherit;
    }

    button {
      color: inherit;
    }

    button:focus-visible,
    input:focus-visible,
    select:focus-visible {
      outline: 3px solid var(--ring);
      outline-offset: 2px;
    }

    .topbar {
      height: 70px;
      background: var(--header);
      border-bottom: 1px solid var(--line);
    }

    .topbar-inner {
      display: flex;
      align-items: center;
      width: 100%;
      max-width: 1400px;
      height: 100%;
      margin: 0 auto;
      padding: 0 38px;
    }

    .brand {
      display: inline-flex;
      flex: 0 0 auto;
      align-items: center;
      gap: 10px;
    }

    .brand-mark {
      display: grid;
      width: 30px;
      height: 30px;
      grid-template-columns: repeat(2, 6px);
      grid-template-rows: repeat(2, 6px);
      align-content: center;
      justify-content: center;
      gap: 4px;
      border-radius: 9px;
      background: linear-gradient(145deg, #8278f2, #5c52cf);
      box-shadow: 0 4px 10px rgba(102, 89, 220, 0.2);
    }

    .brand-mark span {
      width: 6px;
      height: 6px;
      border-radius: 2px;
      background: #fff;
    }

    .brand-mark span:nth-child(2),
    .brand-mark span:nth-child(3) {
      opacity: 0.72;
    }

    .brand-name {
      color: var(--text);
      font-size: 18px;
      font-weight: 750;
      letter-spacing: -0.055em;
    }

    .header-divider {
      width: 1px;
      height: 30px;
      flex: 0 0 auto;
      margin: 0 20px;
      background: var(--line);
    }

    .workspace-context {
      display: flex;
      align-items: center;
      gap: 10px;
    }

    .workspace-icon {
      display: grid;
      width: 31px;
      height: 31px;
      place-items: center;
      border: 1px solid rgba(102, 89, 220, 0.12);
      border-radius: 9px;
      background: var(--accent-soft);
      color: var(--accent);
      font-size: 10px;
      font-weight: 750;
      letter-spacing: 0.02em;
    }

    .workspace-copy {
      display: flex;
      flex-direction: column;
      gap: 2px;
    }

    .workspace-label {
      color: var(--muted);
      font-size: 9px;
      font-weight: 700;
      letter-spacing: 0.12em;
      text-transform: uppercase;
    }

    .workspace-name {
      color: var(--text);
      font-size: 12px;
      font-weight: 650;
    }

    .topbar-spacer {
      flex: 1;
    }

    .topbar-actions {
      display: flex;
      align-items: center;
      gap: 0;
    }

    .team-stack {
      display: flex;
      align-items: center;
      padding-left: 3px;
    }

    .team-avatar,
    .team-more {
      display: grid;
      width: 27px;
      height: 27px;
      flex: 0 0 auto;
      place-items: center;
      margin-left: -5px;
      border: 2px solid var(--header);
      border-radius: 50%;
      font-size: 8px;
      font-weight: 750;
      letter-spacing: -0.03em;
    }

    .team-avatar:first-child {
      margin-left: 0;
    }

    .team-a {
      background: #f3d7c5;
      color: #79523e;
    }

    .team-b {
      background: #d8e6d9;
      color: #42664d;
    }

    .team-c {
      background: #d8ddf8;
      color: #4e568e;
    }

    .team-more {
      background: var(--tag-bg);
      color: var(--muted);
      font-size: 8px;
    }

    .team-divider {
      margin: 0 17px;
    }

    .profile {
      display: flex;
      align-items: center;
      gap: 9px;
    }

    .profile-avatar {
      display: grid;
      width: 31px;
      height: 31px;
      place-items: center;
      border: 1px solid rgba(102, 89, 220, 0.13);
      border-radius: 50%;
      background: linear-gradient(145deg, #eeeaff, #dcd7ff);
      color: #6258bc;
      font-size: 10px;
      font-weight: 750;
    }

    .profile-name {
      color: var(--text);
      font-size: 12px;
      font-weight: 600;
    }

    .main {
      width: 100%;
      max-width: 1360px;
      margin: 0 auto;
      padding: 34px 38px 40px;
    }

    .board-heading {
      display: flex;
      align-items: flex-end;
      justify-content: space-between;
      gap: 26px;
    }

    .heading-copy {
      min-width: 0;
    }

    .eyebrow {
      display: flex;
      align-items: center;
      gap: 8px;
      color: var(--muted);
      font-size: 10px;
      font-weight: 700;
      letter-spacing: 0.12em;
      line-height: 1;
      text-transform: uppercase;
    }

    .eyebrow-mark {
      display: grid;
      width: 18px;
      height: 18px;
      place-items: center;
      border-radius: 6px;
      background: var(--accent-soft);
      color: var(--accent);
    }

    .eyebrow-mark svg {
      width: 12px;
      height: 12px;
    }

    .eyebrow-divider {
      color: var(--quiet);
      font-size: 12px;
    }

    h1 {
      margin: 9px 0 5px;
      color: var(--text);
      font-size: 34px;
      font-weight: 730;
      letter-spacing: -0.055em;
      line-height: 1.12;
    }

    .heading-subtitle {
      margin: 0;
      color: var(--muted);
      font-size: 13px;
      line-height: 1.5;
    }

    .summary-divider {
      margin: 0 7px;
      color: var(--quiet);
    }

    .board-summary {
      color: var(--muted);
      font-weight: 550;
    }

    .toolbar {
      display: flex;
      flex: 0 0 auto;
      align-items: center;
      gap: 9px;
      padding-bottom: 1px;
    }

    .search-box {
      display: flex;
      width: 226px;
      height: 42px;
      align-items: center;
      gap: 9px;
      padding: 0 10px 0 12px;
      border: 1px solid var(--line);
      border-radius: 11px;
      background: var(--surface);
      color: var(--muted);
      transition: border-color 150ms ease, box-shadow 150ms ease;
    }

    .search-box:focus-within {
      border-color: var(--accent);
      box-shadow: 0 0 0 3px var(--ring);
    }

    .search-icon {
      width: 15px;
      height: 15px;
      flex: 0 0 auto;
      color: var(--muted);
    }

    .search-box input {
      width: 100%;
      min-width: 0;
      height: 100%;
      padding: 0;
      border: 0;
      outline: 0;
      background: transparent;
      color: var(--text);
      font-size: 12.5px;
    }

    .search-box input::placeholder {
      color: var(--quiet);
      opacity: 1;
    }

    .search-box input:focus-visible {
      outline: 0;
    }

    .search-shortcut {
      flex: 0 0 auto;
      padding: 3px 5px;
      border: 1px solid var(--line);
      border-radius: 5px;
      background: var(--canvas);
      color: var(--muted);
      font-family: inherit;
      font-size: 9px;
      line-height: 1;
      white-space: nowrap;
    }

    .clear-search {
      display: grid;
      width: 21px;
      height: 24px;
      flex: 0 0 auto;
      place-items: center;
      padding: 0;
      border: 0;
      border-radius: 5px;
      background: transparent;
      color: var(--muted);
      cursor: pointer;
    }

    .clear-search:hover {
      background: var(--tag-bg);
      color: var(--text);
    }

    .clear-search[hidden] {
      display: none;
    }

    .clear-search svg {
      width: 13px;
      height: 13px;
    }

    .theme-toggle,
    .new-task-button {
      display: inline-flex;
      height: 42px;
      align-items: center;
      justify-content: center;
      border-radius: 11px;
      cursor: pointer;
      transition: transform 150ms ease, background-color 150ms ease, border-color 150ms ease, box-shadow 150ms ease;
    }

    .theme-toggle {
      width: 42px;
      flex: 0 0 auto;
      border: 1px solid var(--line);
      background: var(--surface);
      color: var(--muted);
    }

    .theme-toggle:hover {
      border-color: var(--line-strong);
      background: var(--tag-bg);
      color: var(--text);
    }

    .theme-toggle:active,
    .new-task-button:active {
      transform: translateY(1px);
    }

    .theme-toggle svg {
      width: 17px;
      height: 17px;
    }

    .theme-moon {
      display: none;
    }

    :root[data-theme="dark"] .theme-sun {
      display: none;
    }

    :root[data-theme="dark"] .theme-moon {
      display: block;
    }

    .new-task-button {
      gap: 8px;
      padding: 0 15px;
      border: 1px solid var(--accent);
      background: var(--accent);
      box-shadow: 0 3px 8px rgba(102, 89, 220, 0.18);
      color: #fff;
      font-size: 12.5px;
      font-weight: 650;
      white-space: nowrap;
    }

    .new-task-button:hover {
      border-color: var(--accent-hover);
      background: var(--accent-hover);
      box-shadow: 0 5px 12px rgba(102, 89, 220, 0.23);
    }

    .new-task-button svg {
      width: 15px;
      height: 15px;
      flex: 0 0 auto;
    }

    .board-grid {
      display: grid;
      grid-template-columns: repeat(3, minmax(0, 1fr));
      align-items: start;
      gap: 18px;
      margin-top: 29px;
    }

    .board-column {
      min-width: 0;
    }

    .column-header {
      display: flex;
      height: 42px;
      align-items: center;
      justify-content: space-between;
      padding: 0 3px 9px;
    }

    .column-name {
      display: flex;
      min-width: 0;
      align-items: center;
      gap: 9px;
    }

    .status-indicator {
      width: 9px;
      height: 9px;
      flex: 0 0 auto;
      border-radius: 50%;
      box-shadow: 0 0 0 3px color-mix(in srgb, currentColor 10%, transparent);
    }

    [data-status="todo"] .status-indicator {
      background: #8993a6;
      color: #8993a6;
    }

    [data-status="progress"] .status-indicator {
      background: #e8a64c;
      color: #e8a64c;
    }

    [data-status="done"] .status-indicator {
      background: #48ad87;
      color: #48ad87;
    }

    .column-header h2 {
      overflow: hidden;
      margin: 0;
      color: var(--text);
      font-size: 13.5px;
      font-weight: 680;
      letter-spacing: -0.015em;
      text-overflow: ellipsis;
      white-space: nowrap;
    }

    .count-badge {
      display: grid;
      min-width: 23px;
      height: 21px;
      flex: 0 0 auto;
      place-items: center;
      padding: 0 6px;
      border: 1px solid var(--line);
      border-radius: 7px;
      background: var(--surface);
      color: var(--muted);
      font-size: 10px;
      font-weight: 700;
      line-height: 1;
    }

    .column-add {
      display: grid;
      width: 28px;
      height: 28px;
      flex: 0 0 auto;
      place-items: center;
      padding: 0;
      border: 1px solid transparent;
      border-radius: 8px;
      background: transparent;
      color: var(--muted);
      cursor: pointer;
      transition: color 140ms ease, background-color 140ms ease, border-color 140ms ease;
    }

    .column-add:hover {
      border-color: var(--line);
      background: var(--surface);
      color: var(--accent);
    }

    .column-add svg {
      width: 15px;
      height: 15px;
    }

    .card-list {
      display: flex;
      min-height: 386px;
      flex-direction: column;
      gap: 11px;
      padding: 10px;
      border: 1px solid var(--line);
      border-radius: 15px;
      background: var(--lane);
      transition: background-color 150ms ease, border-color 150ms ease, box-shadow 150ms ease;
    }

    .card-list.drop-active {
      border: 1px dashed var(--accent);
      background: var(--drop-bg);
      box-shadow: inset 0 0 0 2px var(--drop-shadow);
    }

    .card-list.drop-active.drop-at-end::after {
      display: block;
      height: 3px;
      flex: 0 0 3px;
      margin: 1px 3px 0;
      border-radius: 4px;
      background: var(--accent);
      box-shadow: 0 0 0 3px var(--ring);
      content: "";
    }

    .task-card {
      position: relative;
      min-width: 0;
      padding: 13px 14px 12px;
      border: 1px solid var(--line);
      border-radius: 11px;
      background: var(--card);
      box-shadow: var(--card-shadow);
      cursor: grab;
      transition: transform 160ms ease, box-shadow 160ms ease, border-color 160ms ease, opacity 160ms ease;
    }

    .task-card:hover {
      z-index: 1;
      transform: translateY(-2px);
      border-color: var(--line-strong);
      box-shadow: var(--card-hover-shadow);
    }

    .task-card:active {
      cursor: grabbing;
    }

    .task-card:focus-visible {
      outline: 3px solid var(--ring);
      outline-offset: 2px;
    }

    .task-card.is-dragging {
      transform: scale(0.985);
      border-style: dashed;
      border-color: var(--accent);
      opacity: 0.36;
      box-shadow: none;
    }

    .task-card.drop-before::before {
      position: absolute;
      z-index: 2;
      top: -7px;
      right: 12px;
      left: 12px;
      height: 3px;
      border-radius: 4px;
      background: var(--accent);
      box-shadow: 0 0 0 3px var(--ring);
      content: "";
    }

    .card-top {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 10px;
    }

    .priority-badge {
      display: inline-flex;
      min-height: 22px;
      align-items: center;
      gap: 6px;
      padding: 3px 8px;
      border-radius: 7px;
      font-size: 10px;
      font-weight: 670;
      line-height: 1;
    }

    .priority-dot {
      width: 6px;
      height: 6px;
      flex: 0 0 auto;
      border-radius: 50%;
      background: currentColor;
    }

    .priority-high {
      background: var(--high-bg);
      color: var(--high-text);
    }

    .priority-high .priority-dot {
      background: var(--high-dot);
    }

    .priority-medium {
      background: var(--medium-bg);
      color: var(--medium-text);
    }

    .priority-medium .priority-dot {
      background: var(--medium-dot);
    }

    .priority-low {
      background: var(--low-bg);
      color: var(--low-text);
    }

    .priority-low .priority-dot {
      background: var(--low-dot);
    }

    .card-actions {
      display: flex;
      align-items: center;
      gap: 3px;
    }

    .drag-grip {
      display: grid;
      width: 15px;
      height: 20px;
      place-items: center;
      color: var(--quiet);
      opacity: 0.72;
    }

    .drag-grip svg {
      width: 10px;
      height: 16px;
    }

    .delete-button {
      display: grid;
      width: 25px;
      height: 25px;
      place-items: center;
      padding: 0;
      border: 1px solid transparent;
      border-radius: 7px;
      background: transparent;
      color: var(--quiet);
      cursor: pointer;
      opacity: 0.78;
      transition: color 140ms ease, background-color 140ms ease, opacity 140ms ease;
    }

    .delete-button:hover {
      background: var(--danger-soft);
      color: var(--danger);
      opacity: 1;
    }

    .delete-button svg {
      width: 14px;
      height: 14px;
    }

    .task-title {
      margin: 9px 0 0;
      color: var(--text);
      font-size: 14px;
      font-weight: 680;
      letter-spacing: -0.025em;
      line-height: 1.35;
      overflow-wrap: anywhere;
    }

    .task-description {
      display: -webkit-box;
      min-height: 36px;
      overflow: hidden;
      margin: 5px 0 0;
      color: var(--muted);
      font-size: 11.7px;
      line-height: 1.55;
      -webkit-box-orient: vertical;
      -webkit-line-clamp: 2;
    }

    .card-footer {
      display: flex;
      min-width: 0;
      align-items: center;
      gap: 8px;
      margin-top: 12px;
    }

    .task-tag {
      display: inline-block;
      max-width: 112px;
      overflow: hidden;
      flex: 0 1 auto;
      padding: 4px 7px;
      border-radius: 6px;
      background: var(--tag-bg);
      color: var(--tag-text);
      font-size: 9.5px;
      font-weight: 620;
      line-height: 1.25;
      text-overflow: ellipsis;
      white-space: nowrap;
    }

    .task-due {
      display: inline-flex;
      min-width: 0;
      align-items: center;
      gap: 4px;
      overflow: hidden;
      color: var(--muted);
      font-size: 9.5px;
      font-weight: 550;
      text-overflow: ellipsis;
      white-space: nowrap;
    }

    .task-due svg {
      width: 12px;
      height: 12px;
      flex: 0 0 auto;
      color: var(--quiet);
    }

    .task-due.due-soon {
      color: var(--high-text);
    }

    .task-due.due-soon svg {
      color: var(--high-dot);
    }

    .task-due.due-complete {
      color: var(--muted);
    }

    .owner-avatar {
      display: grid;
      width: 24px;
      height: 24px;
      flex: 0 0 auto;
      place-items: center;
      margin-left: auto;
      border: 1px solid rgba(29, 35, 52, 0.07);
      border-radius: 50%;
      font-size: 8px;
      font-weight: 750;
      letter-spacing: -0.02em;
    }

    .avatar-peach {
      background: #f5ded1;
      color: #80543f;
    }

    .avatar-green {
      background: #dcece1;
      color: #426c50;
    }

    .avatar-lavender {
      background: #e2ddfa;
      color: #5a5192;
    }

    .avatar-blue {
      background: #dce8f6;
      color: #456486;
    }

    .avatar-sand {
      background: #f2e7ca;
      color: #786234;
    }

    .avatar-rose {
      background: #f5dce4;
      color: #8b5163;
    }

    .avatar-indigo {
      background: #dedbff;
      color: #5148a7;
    }

    .empty-state {
      display: flex;
      min-height: 150px;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      padding: 20px;
      color: var(--muted);
      text-align: center;
    }

    .empty-icon {
      display: grid;
      width: 34px;
      height: 34px;
      place-items: center;
      margin-bottom: 9px;
      border: 1px solid var(--line);
      border-radius: 10px;
      background: var(--surface);
      color: var(--quiet);
    }

    .empty-icon svg {
      width: 17px;
      height: 17px;
    }

    .empty-title {
      color: var(--text);
      font-size: 11.5px;
      font-weight: 650;
    }

    .empty-copy {
      max-width: 185px;
      margin-top: 5px;
      color: var(--muted);
      font-size: 10.5px;
      line-height: 1.45;
    }

    .board-note {
      display: flex;
      align-items: center;
      gap: 8px;
      margin-top: 15px;
      color: var(--muted);
      font-size: 11px;
      line-height: 1.4;
    }

    .board-note svg {
      width: 15px;
      height: 15px;
      flex: 0 0 auto;
      color: var(--accent);
    }

    .sr-only {
      position: absolute;
      width: 1px;
      height: 1px;
      overflow: hidden;
      clip: rect(0, 0, 0, 0);
      white-space: nowrap;
      clip-path: inset(50%);
    }

    .task-dialog {
      width: min(470px, calc(100% - 28px));
      max-width: 470px;
      max-height: calc(100% - 28px);
      overflow: auto;
      padding: 0;
      border: 1px solid var(--line);
      border-radius: 18px;
      background: var(--surface);
      box-shadow: var(--modal-shadow);
      color: var(--text);
    }

    .task-dialog::backdrop {
      background: rgba(20, 24, 38, 0.42);
      backdrop-filter: blur(3px);
    }

    .modal-header {
      display: flex;
      align-items: flex-start;
      justify-content: space-between;
      gap: 16px;
      padding: 22px 23px 17px;
      border-bottom: 1px solid var(--line);
    }

    .modal-eyebrow {
      margin: 0 0 6px;
      color: var(--accent);
      font-size: 9px;
      font-weight: 750;
      letter-spacing: 0.13em;
      text-transform: uppercase;
    }

    .modal-header h2 {
      margin: 0;
      color: var(--text);
      font-size: 21px;
      font-weight: 720;
      letter-spacing: -0.04em;
    }

    .modal-close {
      display: grid;
      width: 30px;
      height: 30px;
      flex: 0 0 auto;
      place-items: center;
      padding: 0;
      border: 1px solid transparent;
      border-radius: 8px;
      background: transparent;
      color: var(--muted);
      cursor: pointer;
    }

    .modal-close:hover {
      border-color: var(--line);
      background: var(--tag-bg);
      color: var(--text);
    }

    .modal-close svg {
      width: 15px;
      height: 15px;
    }

    .modal-body {
      display: flex;
      flex-direction: column;
      gap: 17px;
      padding: 20px 23px 22px;
    }

    .field {
      display: flex;
      min-width: 0;
      flex-direction: column;
      gap: 7px;
    }

    .field-label {
      display: flex;
      align-items: baseline;
      justify-content: space-between;
      gap: 8px;
      color: var(--text);
      font-size: 11.5px;
      font-weight: 650;
    }

    .required-label {
      color: var(--muted);
      font-size: 10px;
      font-weight: 500;
    }

    .field input,
    .field select {
      width: 100%;
      height: 42px;
      min-width: 0;
      padding: 0 11px;
      border: 1px solid var(--line-strong);
      border-radius: 9px;
      background: var(--canvas);
      color: var(--text);
      font-size: 12.5px;
      transition: border-color 140ms ease, box-shadow 140ms ease;
    }

    .field input::placeholder {
      color: var(--quiet);
    }

    .field input:focus,
    .field select:focus {
      border-color: var(--accent);
      outline: 0;
      box-shadow: 0 0 0 3px var(--ring);
    }

    .field-row {
      display: grid;
      grid-template-columns: repeat(2, minmax(0, 1fr));
      gap: 12px;
    }

    .modal-footer {
      display: flex;
      justify-content: flex-end;
      gap: 9px;
      padding: 15px 23px 19px;
      border-top: 1px solid var(--line);
    }

    .modal-button {
      display: inline-flex;
      min-height: 38px;
      align-items: center;
      justify-content: center;
      gap: 7px;
      padding: 0 13px;
      border: 1px solid var(--line);
      border-radius: 9px;
      cursor: pointer;
      font-size: 11.5px;
      font-weight: 650;
      transition: background-color 140ms ease, border-color 140ms ease, transform 140ms ease;
    }

    .modal-button:active {
      transform: translateY(1px);
    }

    .modal-button.secondary {
      background: var(--surface);
      color: var(--muted);
    }

    .modal-button.secondary:hover {
      border-color: var(--line-strong);
      background: var(--tag-bg);
      color: var(--text);
    }

    .modal-button.primary {
      border-color: var(--accent);
      background: var(--accent);
      color: #fff;
    }

    .modal-button.primary:hover {
      border-color: var(--accent-hover);
      background: var(--accent-hover);
    }

    .modal-button.primary svg {
      width: 14px;
      height: 14px;
    }

    @media (max-width: 960px) {
      .main {
        padding-right: 26px;
        padding-left: 26px;
      }

      .board-heading {
        align-items: flex-start;
        flex-direction: column;
        gap: 20px;
      }

      .toolbar {
        width: 100%;
      }

      .search-box {
        width: auto;
        flex: 1 1 auto;
      }

      .topbar-inner {
        padding-right: 26px;
        padding-left: 26px;
      }
    }

    @media (max-width: 760px) {
      .main {
        padding: 27px 22px 35px;
      }

      .board-grid {
        grid-template-columns: minmax(0, 1fr);
        gap: 17px;
        margin-top: 24px;
      }

      .card-list {
        min-height: 0;
      }

      .column-header {
        height: 40px;
      }
    }

    @media (max-width: 560px) {
      .topbar {
        height: 63px;
      }

      .topbar-inner {
        padding: 0 17px;
      }

      .workspace-divider,
      .workspace-context,
      .team-stack,
      .team-divider,
      .profile-name {
        display: none;
      }

      .main {
        padding: 25px 17px 32px;
      }

      h1 {
        margin-top: 8px;
        font-size: 31px;
      }

      .heading-subtitle {
        max-width: 350px;
        font-size: 12.3px;
      }

      .board-heading {
        gap: 19px;
      }

      .toolbar {
        display: grid;
        grid-template-columns: minmax(0, 1fr) 42px auto;
        gap: 8px;
      }

      .search-box {
        width: auto;
        min-width: 0;
        height: 42px;
        gap: 7px;
        padding-right: 8px;
        padding-left: 10px;
      }

      .search-box input {
        font-size: 12px;
      }

      .search-shortcut {
        display: none;
      }

      .theme-toggle {
        width: 42px;
      }

      .new-task-button {
        gap: 6px;
        padding: 0 11px;
        font-size: 11.5px;
      }

      .board-grid {
        margin-top: 22px;
      }

      .card-list {
        padding: 9px;
      }

      .board-note {
        align-items: flex-start;
        font-size: 10.5px;
      }

      .modal-header {
        padding-right: 18px;
        padding-left: 18px;
      }

      .modal-body {
        padding-right: 18px;
        padding-left: 18px;
      }

      .modal-footer {
        padding-right: 18px;
        padding-left: 18px;
      }
    }

    @media (prefers-reduced-motion: reduce) {
      *,
      *::before,
      *::after {
        scroll-behavior: auto !important;
        transition-duration: 0.01ms !important;
      }
    }
  </style>
</head>
<body>
  <header class="topbar">
    <div class="topbar-inner">
      <div class="brand" aria-label="Morrow">
        <span class="brand-mark" aria-hidden="true">
          <span></span><span></span><span></span><span></span>
        </span>
        <span class="brand-name">morrow</span>
      </div>

      <div class="header-divider workspace-divider" aria-hidden="true"></div>

      <div class="workspace-context">
        <span class="workspace-icon" aria-hidden="true">NS</span>
        <span class="workspace-copy">
          <span class="workspace-label">Workspace</span>
          <span class="workspace-name">Northstar Studio</span>
        </span>
      </div>

      <div class="topbar-spacer"></div>

      <div class="topbar-actions">
        <div class="team-stack" role="group" aria-label="Product team members">
          <span class="team-avatar team-a" title="Avery Lee">AL</span>
          <span class="team-avatar team-b" title="Riley Chen">RC</span>
          <span class="team-avatar team-c" title="Jordan Morgan">JM</span>
          <span class="team-more" title="Three more teammates">+3</span>
        </div>
        <div class="header-divider team-divider" aria-hidden="true"></div>
        <div class="profile">
          <span class="profile-avatar" aria-hidden="true">JM</span>
          <span class="profile-name">Jordan Morgan</span>
        </div>
      </div>
    </div>
  </header>

  <main class="main">
    <section class="board-heading" aria-labelledby="page-title">
      <div class="heading-copy">
        <div class="eyebrow">
          <span class="eyebrow-mark" aria-hidden="true">
            <svg viewBox="0 0 16 16" fill="none">
              <path d="M8 1.8 9.35 6.1 13.7 7.5 9.35 8.9 8 13.2 6.65 8.9 2.3 7.5 6.65 6.1 8 1.8Z" stroke="currentColor" stroke-width="1.2" stroke-linejoin="round"/>
            </svg>
          </span>
          <span>Product</span>
          <span class="eyebrow-divider" aria-hidden="true">/</span>
          <span>Sprint 08</span>
        </div>
        <h1 id="page-title">Product sprint</h1>
        <p class="heading-subtitle">
          A focused view of what the team is shipping this week.
          <span class="summary-divider" aria-hidden="true">·</span>
          <span id="boardSummary" class="board-summary">6 tasks across 3 stages</span>
        </p>
      </div>

      <div class="toolbar" aria-label="Board tools">
        <label class="search-box">
          <svg class="search-icon" viewBox="0 0 20 20" fill="none" aria-hidden="true">
            <circle cx="8.8" cy="8.8" r="5.7" stroke="currentColor" stroke-width="1.6"/>
            <path d="m13.1 13.1 4 4" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/>
          </svg>
          <input id="searchInput" type="text" placeholder="Search tasks..." autocomplete="off" aria-label="Search tasks by title">
          <kbd class="search-shortcut" aria-hidden="true">⌘ K</kbd>
          <button class="clear-search" id="clearSearch" type="button" aria-label="Clear search" title="Clear search" hidden>
            <svg viewBox="0 0 16 16" fill="none" aria-hidden="true">
              <path d="m4 4 8 8M12 4l-8 8" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"/>
            </svg>
          </button>
        </label>

        <button class="theme-toggle" id="themeToggle" type="button" aria-label="Switch to dark theme" aria-pressed="false" title="Switch to dark theme">
          <svg class="theme-sun" viewBox="0 0 20 20" fill="none" aria-hidden="true">
            <circle cx="10" cy="10" r="3.3" stroke="currentColor" stroke-width="1.5"/>
            <path d="M10 1.8v2M10 16.2v2M18.2 10h-2M3.8 10h-2m14-5.8-1.4 1.4M5.6 14.4l-1.4 1.4m11.6 0-1.4-1.4M5.6 5.6 4.2 4.2" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
          </svg>
          <svg class="theme-moon" viewBox="0 0 20 20" fill="none" aria-hidden="true">
            <path d="M16.6 12.3A7 7 0 0 1 7.7 3.4a7 7 0 1 0 8.9 8.9Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
            <path d="M13.7 3.1v2.2M12.6 4.2h2.2" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/>
          </svg>
        </button>

        <button class="new-task-button" id="newTaskButton" type="button">
          <svg viewBox="0 0 20 20" fill="none" aria-hidden="true">
            <path d="M10 4v12M4 10h12" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
          </svg>
          <span>New task</span>
        </button>
      </div>
    </section>

    <div class="board-grid" id="board" role="group" aria-label="Kanban board">
      <section class="board-column" data-status="todo" aria-labelledby="heading-todo">
        <div class="column-header">
          <div class="column-name">
            <span class="status-indicator" aria-hidden="true"></span>
            <h2 id="heading-todo">To do</h2>
            <span class="count-badge" id="count-todo" aria-label="2 cards">2</span>
          </div>
          <button class="column-add" type="button" data-action="add" data-status="todo" aria-label="Add a card to To do" title="Add to To do">
            <svg viewBox="0 0 20 20" fill="none" aria-hidden="true">
              <path d="M10 4v12M4 10h12" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/>
            </svg>
          </button>
        </div>
        <div class="card-list" data-status="todo" role="list" aria-label="To do cards"></div>
      </section>

      <section class="board-column" data-status="progress" aria-labelledby="heading-progress">
        <div class="column-header">
          <div class="column-name">
            <span class="status-indicator" aria-hidden="true"></span>
            <h2 id="heading-progress">In progress</h2>
            <span class="count-badge" id="count-progress" aria-label="2 cards">2</span>
          </div>
          <button class="column-add" type="button" data-action="add" data-status="progress" aria-label="Add a card to In progress" title="Add to In progress">
            <svg viewBox="0 0 20 20" fill="none" aria-hidden="true">
              <path d="M10 4v12M4 10h12" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/>
            </svg>
          </button>
        </div>
        <div class="card-list" data-status="progress" role="list" aria-label="In progress cards"></div>
      </section>

      <section class="board-column" data-status="done" aria-labelledby="heading-done">
        <div class="column-header">
          <div class="column-name">
            <span class="status-indicator" aria-hidden="true"></span>
            <h2 id="heading-done">Done</h2>
            <span class="count-badge" id="count-done" aria-label="2 cards">2</span>
          </div>
          <button class="column-add" type="button" data-action="add" data-status="done" aria-label="Add a card to Done" title="Add to Done">
            <svg viewBox="0 0 20 20" fill="none" aria-hidden="true">
              <path d="M10 4v12M4 10h12" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/>
            </svg>
          </button>
        </div>
        <div class="card-list" data-status="done" role="list" aria-label="Done cards"></div>
      </section>
    </div>

    <div class="board-note">
      <svg viewBox="0 0 20 20" fill="none" aria-hidden="true">
        <path d="M4 7h11.5M12.5 4l3 3-3 3M16 13H4.5M7.5 10l-3 3 3 3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
      </svg>
      <span>Drag a card between columns to update its status.</span>
    </div>

    <div id="liveRegion" class="sr-only" aria-live="polite" aria-atomic="true"></div>
  </main>

  <dialog class="task-dialog" id="taskDialog" aria-labelledby="dialogTitle">
    <form id="taskForm">
      <div class="modal-header">
        <div>
          <p class="modal-eyebrow">Add to your sprint</p>
          <h2 id="dialogTitle">Create a task</h2>
        </div>
        <button class="modal-close" type="button" data-close-dialog aria-label="Close dialog" title="Close">
          <svg viewBox="0 0 20 20" fill="none" aria-hidden="true">
            <path d="m5 5 10 10M15 5 5 15" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/>
          </svg>
        </button>
      </div>

      <div class="modal-body">
        <label class="field">
          <span class="field-label">
            <span>Task title</span>
            <span class="required-label">Required</span>
          </span>
          <input id="taskTitle" name="title" type="text" maxlength="100" placeholder="e.g. Review launch metrics" required>
        </label>

        <div class="field-row">
          <label class="field">
            <span class="field-label">Priority</span>
            <select id="taskPriority" name="priority">
              <option value="low">Low</option>
              <option value="medium" selected>Medium</option>
              <option value="high">High</option>
            </select>
          </label>
          <label class="field">
            <span class="field-label">Column</span>
            <select id="taskStatus" name="status">
              <option value="todo" selected>To do</option>
              <option value="progress">In progress</option>
              <option value="done">Done</option>
            </select>
          </label>
        </div>
      </div>

      <div class="modal-footer">
        <button class="modal-button secondary" type="button" data-close-dialog>Cancel</button>
        <button class="modal-button primary" type="submit">
          <svg viewBox="0 0 20 20" fill="none" aria-hidden="true">
            <path d="M10 4v12M4 10h12" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
          </svg>
          Add task
        </button>
      </div>
    </form>
  </dialog>

  <script>
    (() => {
      const columns = [
        { id: "todo", label: "To do" },
        { id: "progress", label: "In progress" },
        { id: "done", label: "Done" }
      ];

      const cardsByStatus = {
        todo: [
          {
            id: "task-1",
            title: "Map first-run friction",
            priority: "high",
            description: "Review the activation funnel and flag the biggest drop-off points.",
            tag: "Research",
            due: "Today",
            dueTone: "soon",
            initials: "AL",
            owner: "Avery Lee",
            avatarClass: "avatar-peach"
          },
          {
            id: "task-2",
            title: "Draft Q3 launch brief",
            priority: "medium",
            description: "Align the launch story, timeline, and checklist with marketing.",
            tag: "Planning",
            due: "Jun 21",
            dueTone: "normal",
            initials: "JM",
            owner: "Jordan Morgan",
            avatarClass: "avatar-lavender"
          }
        ],
        progress: [
          {
            id: "task-3",
            title: "Redesign billing overview",
            priority: "high",
            description: "Simplify plan comparison and surface invoice history.",
            tag: "Product design",
            due: "Tomorrow",
            dueTone: "soon",
            initials: "RC",
            owner: "Riley Chen",
            avatarClass: "avatar-green"
          },
          {
            id: "task-4",
            title: "QA mobile navigation",
            priority: "medium",
            description: "Check menu states on small screens and log any regressions.",
            tag: "Engineering",
            due: "Jun 20",
            dueTone: "normal",
            initials: "JT",
            owner: "Jamie Taylor",
            avatarClass: "avatar-blue"
          }
        ],
        done: [
          {
            id: "task-5",
            title: "Document design tokens",
            priority: "low",
            description: "Publish the updated color, spacing, and type scales.",
            tag: "Design systems",
            due: "Completed Jun 12",
            dueTone: "complete",
            initials: "MS",
            owner: "Morgan Shaw",
            avatarClass: "avatar-sand"
          },
          {
            id: "task-6",
            title: "Share customer interview notes",
            priority: "medium",
            description: "Turn the recurring themes into a short readout for the team.",
            tag: "Research",
            due: "Completed Jun 11",
            dueTone: "complete",
            initials: "AL",
            owner: "Avery Lee",
            avatarClass: "avatar-rose"
          }
        ]
      };

      let nextId = 7;
      let draggedId = null;
      let lastDialogOpener = null;

      const board = document.getElementById("board");
      const searchInput = document.getElementById("searchInput");
      const clearSearchButton = document.getElementById("clearSearch");
      const boardSummary = document.getElementById("boardSummary");
      const liveRegion = document.getElementById("liveRegion");
      const themeToggle = document.getElementById("themeToggle");
      const taskDialog = document.getElementById("taskDialog");
      const taskForm = document.getElementById("taskForm");
      const taskTitleInput = document.getElementById("taskTitle");
      const taskPrioritySelect = document.getElementById("taskPriority");
      const taskStatusSelect = document.getElementById("taskStatus");

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

      function cardTemplate(card) {
        const priority = ["low", "medium", "high"].includes(card.priority) ? card.priority : "medium";
        const priorityLabel = priority.charAt(0).toUpperCase() + priority.slice(1);
        const dueTone = ["soon", "complete"].includes(card.dueTone) ? ` due-${card.dueTone}` : "";
        const allowedAvatarClasses = ["avatar-peach", "avatar-green", "avatar-lavender", "avatar-blue", "avatar-sand", "avatar-rose", "avatar-indigo"];
        const avatarClass = allowedAvatarClasses.includes(card.avatarClass) ? card.avatarClass : "avatar-indigo";
        const safeTitle = escapeHTML(card.title);

        return `
          <article class="task-card" draggable="true" tabindex="0" role="listitem"
            data-id="${escapeHTML(card.id)}"
            aria-label="${safeTitle}, ${priorityLabel.toLowerCase()} priority. Drag to move between columns.">
            <div class="card-top">
              <span class="priority-badge priority-${priority}">
                <span class="priority-dot" aria-hidden="true"></span>${priorityLabel}
              </span>
              <div class="card-actions">
                <span class="drag-grip" aria-hidden="true">
                  <svg viewBox="0 0 10 16" fill="currentColor">
                    <circle cx="3" cy="3" r="1.1"/><circle cx="7" cy="3" r="1.1"/>
                    <circle cx="3" cy="8" r="1.1"/><circle cx="7" cy="8" r="1.1"/>
                    <circle cx="3" cy="13" r="1.1"/><circle cx="7" cy="13" r="1.1"/>
                  </svg>
                </span>
                <button class="delete-button" type="button" data-action="delete" data-id="${escapeHTML(card.id)}"
                  aria-label="Delete task: ${safeTitle}" title="Delete task">
                  <svg viewBox="0 0 20 20" fill="none" aria-hidden="true">
                    <path d="M4.5 6h11M8 6V4.4h4V6m2.5 0-.6 9.1a1.2 1.2 0 0 1-1.2 1.1H7.3a1.2 1.2 0 0 1-1.2-1.1L5.5 6m2.7 3v4.5m3.6-4.5v4.5" stroke="currentColor" stroke-width="1.35" stroke-linecap="round" stroke-linejoin="round"/>
                  </svg>
                </button>
              </div>
            </div>
            <h3 class="task-title">${safeTitle}</h3>
            <p class="task-description">${escapeHTML(card.description || "A new task, ready for the next step.")}</p>
            <div class="card-footer">
              <span class="task-tag" title="${escapeHTML(card.tag || "New")}">${escapeHTML(card.tag || "New")}</span>
              <span class="task-due${dueTone}">
                <svg viewBox="0 0 16 16" fill="none" aria-hidden="true">
                  <rect x="2.5" y="3.5" width="11" height="10" rx="1.7" stroke="currentColor" stroke-width="1.2"/>
                  <path d="M5.2 2.3v2.4m5.6-2.4v2.4M2.8 6.3h10.4" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/>
                </svg>
                <span>${escapeHTML(card.due || "Just added")}</span>
              </span>
              <span class="owner-avatar ${avatarClass}" title="${escapeHTML(card.owner || "Jordan Morgan")}" aria-label="Assigned to ${escapeHTML(card.owner || "Jordan Morgan")}">${escapeHTML(card.initials || "JM")}</span>
            </div>
          </article>
        `;
      }

      function emptyTemplate(searching) {
        if (searching) {
          return `
            <div class="empty-state">
              <span class="empty-icon" aria-hidden="true">
                <svg viewBox="0 0 20 20" fill="none">
                  <circle cx="8.8" cy="8.8" r="5.8" stroke="currentColor" stroke-width="1.4"/>
                  <path d="m13 13 3.6 3.6" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/>
                </svg>
              </span>
              <span class="empty-title">No matching tasks</span>
              <span class="empty-copy">Try another title or clear your search.</span>
            </div>
          `;
        }

        return `
          <div class="empty-state">
            <span class="empty-icon" aria-hidden="true">
              <svg viewBox="0 0 20 20" fill="none">
                <rect x="3.2" y="4.3" width="13.6" height="11.4" rx="2" stroke="currentColor" stroke-width="1.3"/>
                <path d="M3.8 8h12.4M7 11.2h6" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/>
              </svg>
            </span>
            <span class="empty-title">Nothing here yet</span>
            <span class="empty-copy">Drop a card here or add a new task.</span>
          </div>
        `;
      }

      function renderBoard() {
        const query = searchInput.value.trim().toLowerCase();
        const searching = query.length > 0;
        let visibleTotal = 0;
        let total = 0;

        for (const column of columns) {
          const cards = cardsByStatus[column.id];
          total += cards.length;

          const matchingCards = cards.filter(card => card.title.toLowerCase().includes(query));
          visibleTotal += matchingCards.length;

          const list = board.querySelector(`.card-list[data-status="${column.id}"]`);
          const count = document.getElementById(`count-${column.id}`);

          count.textContent = String(matchingCards.length);
          count.setAttribute("aria-label", `${matchingCards.length} ${matchingCards.length === 1 ? "card" : "cards"}`);
          list.setAttribute("aria-label", `${column.label}, ${matchingCards.length} ${matchingCards.length === 1 ? "card" : "cards"}`);

          list.innerHTML = matchingCards.length
            ? matchingCards.map(cardTemplate).join("")
            : emptyTemplate(searching);
        }

        if (searching) {
          boardSummary.textContent = `${visibleTotal} of ${total} tasks ${visibleTotal === 1 ? "matches" : "match"}`;
        } else {
          boardSummary.textContent = `${total} ${total === 1 ? "task" : "tasks"} across 3 stages`;
        }

        clearSearchButton.hidden = searchInput.value.length === 0;
      }

      function announce(message) {
        liveRegion.textContent = message;
      }

      function openTaskDialog(status = "todo") {
        lastDialogOpener = document.activeElement;
        taskStatusSelect.value = columns.some(column => column.id === status) ? status : "todo";
        if (!taskDialog.open) {
          taskDialog.showModal();
          taskTitleInput.focus();
        }
      }

      document.getElementById("newTaskButton").addEventListener("click", () => openTaskDialog("todo"));

      board.addEventListener("click", event => {
        const addButton = event.target.closest('[data-action="add"]');
        if (addButton) {
          openTaskDialog(addButton.dataset.status);
          return;
        }

        const deleteButton = event.target.closest('[data-action="delete"]');
        if (!deleteButton) return;

        const id = deleteButton.dataset.id;
        for (const column of columns) {
          const cardIndex = cardsByStatus[column.id].findIndex(card => card.id === id);
          if (cardIndex !== -1) {
            const [removedCard] = cardsByStatus[column.id].splice(cardIndex, 1);
            renderBoard();
            announce(`${removedCard.title} deleted.`);
            const addToColumn = board.querySelector(`[data-action="add"][data-status="${column.id}"]`);
            if (addToColumn) addToColumn.focus({ preventScroll: true });
            return;
          }
        }
      });

      searchInput.addEventListener("input", renderBoard);

      clearSearchButton.addEventListener("click", () => {
        searchInput.value = "";
        renderBoard();
        searchInput.focus();
      });

      searchInput.addEventListener("keydown", event => {
        if (event.key === "Escape" && searchInput.value) {
          searchInput.value = "";
          renderBoard();
        }
      });

      themeToggle.addEventListener("click", () => {
        const isDark = document.documentElement.dataset.theme !== "dark";
        document.documentElement.dataset.theme = isDark ? "dark" : "light";
        themeToggle.setAttribute("aria-pressed", String(isDark));
        themeToggle.setAttribute("aria-label", `Switch to ${isDark ? "light" : "dark"} theme`);
        themeToggle.title = `Switch to ${isDark ? "light" : "dark"} theme`;
      });

      document.addEventListener("keydown", event => {
        if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === "k" && !taskDialog.open) {
          event.preventDefault();
          searchInput.focus();
          searchInput.select();
        }
      });

      taskTitleInput.addEventListener("input", () => {
        taskTitleInput.setCustomValidity("");
      });

      taskForm.addEventListener("submit", event => {
        event.preventDefault();

        const title = taskTitleInput.value.trim();
        if (!title) {
          taskTitleInput.setCustomValidity("Please enter a task title.");
          taskTitleInput.reportValidity();
          return;
        }

        const status = columns.some(column => column.id === taskStatusSelect.value)
          ? taskStatusSelect.value
          : "todo";

        const newCard = {
          id: `task-${nextId++}`,
          title,
          priority: taskPrioritySelect.value,
          description: "A new task, ready for the next step.",
          tag: "New",
          due: "Just added",
          dueTone: "normal",
          initials: "JM",
          owner: "Jordan Morgan",
          avatarClass: "avatar-indigo"
        };

        cardsByStatus[status].unshift(newCard);
        renderBoard();
        announce(`${title} added to ${columns.find(column => column.id === status).label}.`);
        taskDialog.close();
      });

      taskDialog.addEventListener("click", event => {
        if (event.target.closest("[data-close-dialog]") || event.target === taskDialog) {
          taskDialog.close();
        }
      });

      taskDialog.addEventListener("close", () => {
        taskForm.reset();
        taskTitleInput.setCustomValidity("");
        if (lastDialogOpener && document.contains(lastDialogOpener)) {
          lastDialogOpener.focus({ preventScroll: true });
        }
      });

      function clearDropIndicators() {
        board.querySelectorAll(".card-list").forEach(list => {
          list.classList.remove("drop-active", "drop-at-end");
        });
        board.querySelectorAll(".drop-before").forEach(card => card.classList.remove("drop-before"));
      }

      function cleanUpDrag() {
        draggedId = null;
        document.body.classList.remove("dragging");
        clearDropIndicators();
        board.querySelectorAll(".is-dragging").forEach(card => card.classList.remove("is-dragging"));
      }

      function cardAfterPointer(list, pointerY) {
        const cards = Array.from(list.querySelectorAll(".task-card:not(.is-dragging)"));
        let closest = { offset: Number.NEGATIVE_INFINITY, element: null };

        for (const card of cards) {
          const box = card.getBoundingClientRect();
          const offset = pointerY - box.top - box.height / 2;
          if (offset < 0 && offset > closest.offset) {
            closest = { offset, element: card };
          }
        }

        return closest.element;
      }

      function moveCard(id, targetStatus, beforeId) {
        if (!id || !cardsByStatus[targetStatus]) return;

        let sourceStatus = null;
        let sourceIndex = -1;

        for (const column of columns) {
          const index = cardsByStatus[column.id].findIndex(card => card.id === id);
          if (index !== -1) {
            sourceStatus = column.id;
            sourceIndex = index;
            break;
          }
        }

        if (sourceStatus === null) return;

        const [card] = cardsByStatus[sourceStatus].splice(sourceIndex, 1);
        const destination = cardsByStatus[targetStatus];
        let insertAt = beforeId ? destination.findIndex(item => item.id === beforeId) : -1;

        if (insertAt < 0) insertAt = destination.length;
        destination.splice(insertAt, 0, card);

        const targetColumn = columns.find(column => column.id === targetStatus);
        renderBoard();
        announce(`${card.title} moved to ${targetColumn.label}.`);
      }

      board.addEventListener("dragstart", event => {
        const card = event.target.closest(".task-card");
        if (!card) return;

        if (event.target.closest("button")) {
          event.preventDefault();
          return;
        }

        draggedId = card.dataset.id;
        event.dataTransfer.effectAllowed = "move";
        event.dataTransfer.setData("text/plain", draggedId);
        card.classList.add("is-dragging");
        document.body.classList.add("dragging");
      });

      board.addEventListener("dragover", event => {
        const list = event.target.closest(".card-list");
        if (!list || draggedId === null) return;

        event.preventDefault();
        if (event.dataTransfer) event.dataTransfer.dropEffect = "move";

        clearDropIndicators();
        list.classList.add("drop-active");

        const afterCard = cardAfterPointer(list, event.clientY);
        if (afterCard) {
          afterCard.classList.add("drop-before");
        } else {
          list.classList.add("drop-at-end");
        }
      });

      board.addEventListener("dragleave", event => {
        const list = event.target.closest(".card-list");
        if (!list) return;
        if (event.relatedTarget && list.contains(event.relatedTarget)) return;

        list.classList.remove("drop-active", "drop-at-end");
        list.querySelectorAll(".drop-before").forEach(card => card.classList.remove("drop-before"));
      });

      board.addEventListener("drop", event => {
        const list = event.target.closest(".card-list");
        if (!list) return;

        event.preventDefault();
        const beforeCard = list.querySelector(".drop-before");
        const beforeId = beforeCard ? beforeCard.dataset.id : null;
        const transferredId = event.dataTransfer ? event.dataTransfer.getData("text/plain") : "";
        moveCard(transferredId || draggedId, list.dataset.status, beforeId);
        cleanUpDrag();
      });

      board.addEventListener("dragend", cleanUpDrag);

      renderBoard();
    })();
  </script>
</body>
</html>
Reasoning trace (28,978 tokens)
**Designing a Kanban Board**

I need to focus on producing high-quality, functional code for a Kanban board, making sure it's all self-contained and doesn’t rely on any external resources. I should keep the layout responsive, especially at 1280x800 for desktop and 375 for mobile. I want to include necessary UI elements, like three columns with six realistic cards, a modal, and features like drag-and-drop, live search, and a theme toggle. The cards must have required titles and priority, ensuring a polished, visually appealing design without horizontal scrolling.**Refining the Kanban Board Design**

I’m aiming for a visually engaging and realistic Kanban board with card descriptions, tags, and avatars. Each card should include a title, priority, and additional metadata like labels and due dates. I need to polish the design, ensuring theme toggles for light and dark modes, with light as the default. I'll add a dynamic header displaying the current date. The layout should fit under 800px, featuring two cards per column and staying within a maximum width of 1240. The page background will be a near-white shade, providing a clean aesthetic.**Designing the Kanban Interface**

I need to implement a search function, a theme toggle, and a button for adding tasks. The three columns should have lightly tinted backgrounds to maintain a classic Kanban style, using colors like #f1f4f8. The cards themselves will be white with subtle borders, offering a lift effect on hover. Each card needs to include a priority badge, title, and potentially a description in muted text, along with labels, an avatar in the footer, and a due date. I want to include at least six tasks, two per column.**Designing task board features**

I'm considering features for a task board. There’s the title and a search button, plus a grid layout with margins. Each column should have a header with a colored icon, a count pill, and possibly a "+" button for adding tasks. Adding a global task button that opens a modal preset to "To Do" is smart. The convenience of quick additions could enhance usability. Integrating buttons in column headers might also help users add tasks more easily.**Building a dynamic task column**

I'm designing a column structure with small circles for status and a drop zone. Each column will have a header and a list for cards, dynamically rendered from the state. I need to ensure user input is safe to prevent XSS, so using escapeHTML is essential. Each card will have metadata fields such as title and priority, with a unique ID counter. For the modal, I'll ensure it's accessible, requiring the title, and manage focus for a better user experience.**Utilizing the dialog element**

I’m exploring the use of the `<dialog>` element with the `method="dialog"` attribute for a more seamless modal experience. I'll check compatibility in the latest Chrome and confirm that `dialog.showModal` works as expected. For handling form submissions, I'll need to prevent the default action and close the dialog properly using `close()`. It's crucial to ensure accessibility with attributes like `aria-labelledby`, and I plan to set focus on input fields after opening the dialog to enhance user experience.**Considering metadata layout**

I’m thinking about the metadata row design. On the left, I could have a tiny pill label that says “Discovery,” which is nice! On the right, including a due date like “Jun 18” adds value, but it might look cramped with an avatar. Maybe I’ll simplify by just having the label and avatar. The due date could be smaller and aligned neatly, so it looks clear and organized on the card.**Designing task card functionality**

I’m considering how to set up the task card with a `cursor: grab` on hover and thinking about making the entire card draggable. A subtle 6-dot icon could indicate where to drag. I want to ensure the card includes a priority tag without making titles feel awkward. I’ll use a structured markup for the card, incorporating essential elements like due dates and a delete button, while also thinking about how to highlight urgent deadlines effectively.**Evaluating form handling**

I'm reflecting on how to manage focus with close events, specifically using `dialog.addEventListener('close', focus back)`. I wonder if it's good to reset the form with `form.reset()` after a successful close.

I'm also considering the `form.addEventListener('submit')` logic. There seems to be a whitespace issue — I need to ensure the title is required and trimmed. If the input isn’t valid after that, I should use `setCustomValidity` and call `reportValidity`. Oh, and I should remember to set `maxlength=80` for the title too!**Improving accessibility features**

I need to focus on mouse use and consider how to make the interface keyboard-accessible. Adding keyboard navigation with arrow keys could enhance usability, but it's not strictly required. For cards, I’ll ensure they are `draggable=true` and have a `tabindex of 0`. I can also implement `aria-label` and consider other attributes like `aria-live` for updates and tooltips for descriptions. I'll aim for a well-structured layout, using appropriate roles for better accessibility compliance.**Designing theme styling**

I'm working on styling themes with CSS variables for both light and dark modes. In the `:root`, I've defined colors like background, header, panel, and text, including muted tones and shadows. For dark mode, I need to ensure that the colors contrast well. I'll create specific classes for priority badges using separate CSS variables for different priority levels—high, medium, and low. I'm also considering a toggle for switching themes, which would involve updating the icon dynamically with SVGs.**Evaluating column layout**

I'm considering a breakpoint of 720 for the width of the screen. At that width, three columns seem too small, maybe even switching to a single stack at ≤780. I wonder if I can use two columns at ≤900, as three columns are necessary. It might be manageable to keep three columns until 700, and at tablet width 768, things become tricky with the card layout. I think three vertical columns on a phone could create a long page, which isn't ideal.**Evaluating responsive design breakpoints**

I'm considering using a breakpoint at 760 for a single column, ensuring that the columns stack properly. At this width, I can fit three columns at about 716 and manage the gaps effectively, while also ensuring that at 700, I can keep the layout functional. For tablets around 700, I might switch to three columns but need to monitor how labels may wrap. I'll ensure that at widths below 520, the top bar height and padding are adjusted properly. Cards will remain 100% wide on mobile for a cleaner look.**Adjusting header visibility**

I'm considering what elements to include in the top bar header. It might be helpful to incorporate profile pictures and avatars. I think I could hide the member stack at 650px, which could streamline the layout. Additionally, at a width of 540px, it makes sense to hide the workspace context for a cleaner appearance. I want to ensure that I'm making the interface as user-friendly as possible while maintaining aesthetic appeal.**Considering dark theme implementation**

I'm thinking about setting up a dark color scheme using the ` color-scheme: dark` property, so that form select options look more cohesive. I should utilize CSS variables with `:root` and `:root[data-theme=dark]`. I'll incorporate a theme toggle button and style status dots with specific colors for different states: todo, progress, and done. Also, I need to ensure I add `data-status`, columns, counts, footer labels, and possibly use hardcoded colors for header avatars.**Optimizing card layout**

I’m focusing on counting cards and adding a button to the card list. I need to adjust the `empty-state` display to be centered and aligned properly. For the board note, I think a minimum height of 375 might work, but setting it to 380 feels better overall. I want to ensure the lane has a distinct background with a border. Also, I’m planning to add two cards to utilize the open area nicely. There’s a lot of detailed spacing to consider, like card height and gaps.**Designing a UI Theme**

I'm laying out a design structure that includes specifics like left and right margins, height, and accent. The color theme features dark colors, with shades for elements like the header, surfaces, cards, and texts.

For inputs and selects, I’m ensuring they have defined styles, keeping the native dropdown look but allowing for custom icons. Display properties for modals and dialogs are also being set to ensure they function correctly when opened.

I want everything to work seamlessly together!**Structuring Dialog CSS**

I'm setting up the CSS for a dialog, ensuring it has a minimum width and is centered with auto margins. It's crucial that the dialog only displays when open, following the user agent's default settings.

The backdrop styling will ensure the dialog stays visible and centered. For smaller viewports, I'm calculating max height and handling overflow. I'll also implement autofocus when the modal opens, and have an event listener for clicks outside the dialog to close it. I want it all to function smoothly!**Adjusting accessibility and design**

I'm thinking about enhancing accessibility by setting focus visibility. I won't include any transitions that aren't essential for users preferring reduced motion, which is a good practice. I need to eliminate any horizontal scroll on the page using CSS. Also, it seems important to use `aria-live=polite` for counts, and ensure there's a `data-status` attribute in the list. Plus, I'm working on a card template that allows for ordering and prioritization. This should help users navigate more effectively!**Analyzing modal interactions**

I’m considering the interaction with task cards. It seems like drag-and-drop doesn’t work well with the keyboard shortcuts. I need to make sure that events handle clicks correctly: if I click to delete, it shouldn't add items, and if I click an empty space, it should just search.

I’m thinking about theme management too. If the `aria-pressed` attribute means dark mode is currently on, that's good! When the modal closes, I need to ensure the form resets, and focus is restored correctly afterward. Got to make all these interactions seamless!**Drafting HTML SVG Structure**

I’m focusing on creating valid HTML for the SVG elements. In the top bar, I need to define the brand, which includes a non-interactive logo with the name "morrow." I'll structure the workspace context using an icon and the name "Northstar Studio," but without functional arrows to prevent confusion. The context will simply include the icon and name. I'll also ensure to implement layout considerations for mobile and dark mode styles while using CSS for focus management. Lastly, I’ll render the empty state icon with the same SVG design.**Summarizing Task Elements**

I'm focused on finalizing a summary for the search feature, particularly regarding the footer icon. I’m thinking about using a hand or cursor icon in a drag-and-drop style, which feels intuitive. The note section should clarify that users can move cards forward by dragging them to different columns. For the dynamic card labels, I’ll utilize `escapeHTML` to ensure proper handling of special characters. Also, I’m confirming that priority values are in lower case for consistency and checking avatar classes against an allowlist.**Reviewing code structure**

I need to carefully check this code snippet. I'm working with `sourceCards` from `boardState[sourceStatus]` and using `splice` to extract a `card` at `sourceIndex`. Then, I’m targeting `destination` from `boardState[targetStatus]`. I need to handle the index properly. If `index` is less than 0, it should equal the length of `destination`. Finally, I should ensure that `targetStatus` is valid to avoid any errors. This snippet seems to work well with the same array.**Calculating dialog widths**

I'm checking the widths for my design. For screens under 380, I think one column works best. If the screen is 375, the inner dialog width would be about 343. I’m calculating it: 100% - 24 pixels gives me 351 for the dialog width. The body at 375 means I can use a similar calculation there. It’s a bit confusing, but I’m working through it to ensure everything fits nicely!**Progressing with design tasks**

I’m working on redesigning the billing overview and ensuring quality assurance for mobile navigation. I've completed document design tokens and shared customer interview notes. I’m setting the modal title as “Create a task” with priority options of Low/Medium/High, defaulting to medium. I've decided not to include a task description form and ensuring proper aria handling. I’ll finalize the CSS for owner classes and color adjustments, and I need everything to align with our token limitations. Let's get to the final code now!**Writing detailed code**

I'm preparing to focus on writing the exact code needed. It’s important for me to be thorough and precise to ensure everything functions as intended. I need to consider all the elements involved and make sure to keep track of any dependencies or specific requirements. This attention to detail will make a big difference in the final outcome. Alright, let’s get started on this and see how everything fits together!