@cwim/kanban 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +232 -0
- package/dashboard/dist/assets/index-DJjqRfkX.css +1 -0
- package/dashboard/dist/assets/index-Hgs2aA9B.js +18 -0
- package/dashboard/dist/index.html +13 -0
- package/dist/cli/commands.d.ts +3 -0
- package/dist/cli/commands.d.ts.map +1 -0
- package/dist/cli/commands.js +195 -0
- package/dist/cli/commands.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/server.d.ts +3 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +254 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/server/http.d.ts +4 -0
- package/dist/server/http.d.ts.map +1 -0
- package/dist/server/http.js +88 -0
- package/dist/server/http.js.map +1 -0
- package/dist/storage/store.d.ts +22 -0
- package/dist/storage/store.d.ts.map +1 -0
- package/dist/storage/store.js +160 -0
- package/dist/storage/store.js.map +1 -0
- package/dist/types.d.ts +26 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +14 -0
- package/dist/types.js.map +1 -0
- package/package.json +63 -0
package/README.md
ADDED
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
# CWIM Kanban
|
|
2
|
+
|
|
3
|
+
> Minimal Kanban task tracking with MCP integration for Claude Code. Local-first, zero-config, and purpose-built for long-running AI-assisted workflows.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
CWIM Kanban is a complementary package to CWIM (Context Window Intelligence Manager) that adds visual task tracking to your Claude Code sessions. It consists of:
|
|
8
|
+
|
|
9
|
+
- **MCP Server** — Exposes Kanban operations as Claude Code tools (`task_create`, `task_move`, `task_list`, etc.)
|
|
10
|
+
- **Web Dashboard** — A clean, dark-themed Kanban board served locally at `http://localhost:3456`
|
|
11
|
+
- **CLI** — Full command-line interface for managing tasks outside of Claude
|
|
12
|
+
- **Local JSON Storage** — All data stored in `~/.kanban/tasks.json`, no cloud or database needed
|
|
13
|
+
|
|
14
|
+
As Claude works through complex multi-step tasks, it can create cards, move them across columns, and you watch progress unfold in real time on the board.
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# Install globally
|
|
20
|
+
npm install -g @cwim/kanban
|
|
21
|
+
|
|
22
|
+
# Or run directly with npx
|
|
23
|
+
npx @cwim/kanban
|
|
24
|
+
|
|
25
|
+
# Short command (after global install)
|
|
26
|
+
kanban
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Claude Code Integration (MCP)
|
|
30
|
+
|
|
31
|
+
Add CWIM Kanban to your Claude Code MCP configuration:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
# Add to your Claude Code config (e.g., ~/.claude/config.json)
|
|
35
|
+
{
|
|
36
|
+
"mcpServers": {
|
|
37
|
+
"kanban": {
|
|
38
|
+
"command": "npx",
|
|
39
|
+
"args": ["@cwim/kanban", "mcp"]
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Once connected, Claude can use these tools during your sessions:
|
|
46
|
+
|
|
47
|
+
| Tool | Purpose |
|
|
48
|
+
|------|---------|
|
|
49
|
+
| `task_create` | Create a new task card |
|
|
50
|
+
| `task_update` | Edit task title, description, tags |
|
|
51
|
+
| `task_move` | Move a task to another column |
|
|
52
|
+
| `task_delete` | Remove a task |
|
|
53
|
+
| `task_list` | List all tasks (optionally filtered) |
|
|
54
|
+
| `task_get` | Show details of a specific task |
|
|
55
|
+
|
|
56
|
+
Claude will automatically detect the tools and use them to track progress on complex tasks. Tasks created via MCP are tagged with source "claude" so you can distinguish them from manually created ones.
|
|
57
|
+
|
|
58
|
+
## CLI Commands
|
|
59
|
+
|
|
60
|
+
### `kanban` (default) — Launch Dashboard
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
# Start dashboard server and open browser
|
|
64
|
+
kanban
|
|
65
|
+
|
|
66
|
+
# Custom port
|
|
67
|
+
kanban --port 8080
|
|
68
|
+
|
|
69
|
+
# Don't auto-open browser
|
|
70
|
+
kanban --no-open
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### `kanban mcp` — Start MCP Server
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
# Run in MCP mode (stdio transport for Claude Code)
|
|
77
|
+
kanban mcp
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### `kanban add` — Create Task
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
# Simple task
|
|
84
|
+
kanban add "Fix auth middleware"
|
|
85
|
+
|
|
86
|
+
# With description and tags
|
|
87
|
+
kanban add "Refactor database layer" -d "Extract connection pooling" -t refactor,db
|
|
88
|
+
|
|
89
|
+
# Direct to a column
|
|
90
|
+
kanban add "Write tests" -s in-progress
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### `kanban list` — List Tasks
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
# All tasks
|
|
97
|
+
kanban list
|
|
98
|
+
|
|
99
|
+
# Filter by status
|
|
100
|
+
kanban list --status done
|
|
101
|
+
|
|
102
|
+
# Filter by tag
|
|
103
|
+
kanban list --tag refactor
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### `kanban done` — Mark Complete
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
kanban done tf-abc123
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### `kanban move` — Change Status
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
# Move to any column
|
|
116
|
+
kanban move tf-abc123 blocked
|
|
117
|
+
kanban move tf-abc123 in-progress
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### `kanban status` — Board Overview
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
# Quick summary of all columns
|
|
124
|
+
kanban status
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### `kanban show` — Task Details
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
kanban show tf-abc123
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### `kanban remove` — Delete Task
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
kanban remove tf-abc123
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### `kanban init` — Initialize Storage
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
# Creates ~/.kanban/ directory and empty tasks.json
|
|
143
|
+
kanban init
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Dashboard Features
|
|
147
|
+
|
|
148
|
+
- **Real-time updates** — Board refreshes every 2 seconds, showing changes as Claude moves tasks
|
|
149
|
+
- **4 columns** — To Do, In Progress, Done, Blocked
|
|
150
|
+
- **Visual indicators** — Color-coded borders, pulsing LIVE badge, flash animation on task moves
|
|
151
|
+
- **Session linking** — Auto-detects active Claude Code session and shows it in the header
|
|
152
|
+
- **Tag support** — Tasks show tags as badges for quick categorization
|
|
153
|
+
- **Source tracking** — Distinguishes between Claude-created and manually-created tasks
|
|
154
|
+
- **Keyboard shortcuts** — `r` to refresh, `1-4` to filter columns
|
|
155
|
+
- **New task toast** — Brief notification when a new task appears
|
|
156
|
+
|
|
157
|
+
## Data Storage
|
|
158
|
+
|
|
159
|
+
All data is stored locally in `~/.kanban/tasks.json`:
|
|
160
|
+
|
|
161
|
+
```json
|
|
162
|
+
{
|
|
163
|
+
"version": 1,
|
|
164
|
+
"updatedAt": "2026-05-23T10:30:00Z",
|
|
165
|
+
"session": {
|
|
166
|
+
"name": "my-project",
|
|
167
|
+
"path": "/home/user/.claude/projects/my-project"
|
|
168
|
+
},
|
|
169
|
+
"tasks": [
|
|
170
|
+
{
|
|
171
|
+
"id": "tf-001",
|
|
172
|
+
"title": "Refactor auth middleware",
|
|
173
|
+
"description": "Extract JWT validation into separate module",
|
|
174
|
+
"status": "in-progress",
|
|
175
|
+
"tags": ["refactor", "auth"],
|
|
176
|
+
"source": "claude",
|
|
177
|
+
"createdAt": "2026-05-23T10:15:00Z",
|
|
178
|
+
"updatedAt": "2026-05-23T10:20:00Z"
|
|
179
|
+
}
|
|
180
|
+
]
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
- **Local-first** — No cloud services, no accounts, no network required
|
|
185
|
+
- **Human-readable** — JSON format you can edit directly if needed
|
|
186
|
+
- **Session-aware** — Links tasks to Claude Code sessions when available
|
|
187
|
+
- **Portable** — Back up or version-control your `~/.kanban/` directory
|
|
188
|
+
|
|
189
|
+
## Programmatic API
|
|
190
|
+
|
|
191
|
+
Core functions are exported for custom integrations:
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
import { createTask, listTasks, moveTask, getAllData } from '@cwim/kanban';
|
|
195
|
+
|
|
196
|
+
// Create a task programmatically
|
|
197
|
+
const task = await createTask({
|
|
198
|
+
title: 'My task',
|
|
199
|
+
description: 'Optional details',
|
|
200
|
+
status: 'todo',
|
|
201
|
+
tags: ['api'],
|
|
202
|
+
source: 'manual'
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
// Get all data
|
|
206
|
+
const data = await getAllData();
|
|
207
|
+
console.log(data.tasks);
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
See `src/index.ts` for all available exports.
|
|
211
|
+
|
|
212
|
+
## Architecture
|
|
213
|
+
|
|
214
|
+
```
|
|
215
|
+
Claude Code → MCP Server (stdio) → tasks.json ← HTTP Server ← Dashboard UI
|
|
216
|
+
↑ ↑
|
|
217
|
+
task_create, move, etc. polling /api/tasks
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
- **MCP Server** and **HTTP Server** are separate processes
|
|
221
|
+
- They communicate through the shared JSON file, not sockets or IPC
|
|
222
|
+
- The dashboard polls `/api/tasks` every 2 seconds
|
|
223
|
+
- All mutations go through the MCP tools or CLI commands
|
|
224
|
+
|
|
225
|
+
## Requirements
|
|
226
|
+
|
|
227
|
+
- Node.js 18+
|
|
228
|
+
- Claude Code (optional — dashboard works independently)
|
|
229
|
+
|
|
230
|
+
## License
|
|
231
|
+
|
|
232
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}*{--tw-border-opacity: 1;border-color:rgb(42 42 58 / var(--tw-border-opacity, 1))}body{--tw-bg-opacity: 1;background-color:rgb(10 10 15 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(232 232 240 / var(--tw-text-opacity, 1));-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:Inter,ui-sans-serif,system-ui,-apple-system,sans-serif}::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:#2a2a3a;border-radius:3px}::-webkit-scrollbar-thumb:hover{background:#3d3d5c}.\!visible{visibility:visible!important}.visible{visibility:visible}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.bottom-3{bottom:.75rem}.bottom-6{bottom:1.5rem}.left-1\/2{left:50%}.right-4{right:1rem}.z-50{z-index:50}.mb-1\.5{margin-bottom:.375rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.ml-auto{margin-left:auto}.mt-4{margin-top:1rem}.line-clamp-2{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2}.inline-block{display:inline-block}.flex{display:flex}.inline-flex{display:inline-flex}.h-11{height:2.75rem}.h-14{height:3.5rem}.h-2{height:.5rem}.h-5{height:1.25rem}.h-full{height:100%}.h-screen{height:100vh}.min-h-0{min-height:0px}.w-2{width:.5rem}.w-5{width:1.25rem}.w-full{width:100%}.min-w-\[300px\]{min-width:300px}.min-w-max{min-width:-moz-max-content;min-width:max-content}.flex-1{flex:1 1 0%}.shrink-0{flex-shrink:0}.-translate-x-1\/2{--tw-translate-x: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-default{cursor:default}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-6{gap:1.5rem}.space-y-2\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.625rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.625rem * var(--tw-space-y-reverse))}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.overflow-y-hidden{overflow-y:hidden}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rounded{border-radius:.25rem}.rounded-\[10px\]{border-radius:10px}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:var(--radius)}.rounded-md{border-radius:calc(var(--radius) - 2px)}.rounded-xl{border-radius:calc(var(--radius) + 4px)}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-l-\[3px\]{border-left-width:3px}.border-\[\#2A2A3A\]{--tw-border-opacity: 1;border-color:rgb(42 42 58 / var(--tw-border-opacity, 1))}.border-\[\#2A2A3A\]\/50{border-color:#2a2a3a80}.border-\[\#3D3D5C\]{--tw-border-opacity: 1;border-color:rgb(61 61 92 / var(--tw-border-opacity, 1))}.bg-\[\#0A0A0F\]{--tw-bg-opacity: 1;background-color:rgb(10 10 15 / var(--tw-bg-opacity, 1))}.bg-\[\#10B981\]{--tw-bg-opacity: 1;background-color:rgb(16 185 129 / var(--tw-bg-opacity, 1))}.bg-\[\#111118\]{--tw-bg-opacity: 1;background-color:rgb(17 17 24 / var(--tw-bg-opacity, 1))}.bg-\[\#1E1E2A\]{--tw-bg-opacity: 1;background-color:rgb(30 30 42 / var(--tw-bg-opacity, 1))}.bg-\[\#27273A\]{--tw-bg-opacity: 1;background-color:rgb(39 39 58 / var(--tw-bg-opacity, 1))}.p-3{padding:.75rem}.p-4{padding:1rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-12{padding-top:3rem;padding-bottom:3rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.text-center{text-align:center}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[13px\]{font-size:13px}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.leading-relaxed{line-height:1.625}.leading-snug{line-height:1.375}.tracking-\[0\.05em\]{letter-spacing:.05em}.tracking-tight{letter-spacing:-.025em}.tracking-wide{letter-spacing:.025em}.text-\[\#22D3EE\]{--tw-text-opacity: 1;color:rgb(34 211 238 / var(--tw-text-opacity, 1))}.text-\[\#555570\]{--tw-text-opacity: 1;color:rgb(85 85 112 / var(--tw-text-opacity, 1))}.text-\[\#8A8AA3\]{--tw-text-opacity: 1;color:rgb(138 138 163 / var(--tw-text-opacity, 1))}.text-\[\#E8E8F0\]{--tw-text-opacity: 1;color:rgb(232 232 240 / var(--tw-text-opacity, 1))}.text-\[\#EF4444\]{--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity, 1))}.opacity-20{opacity:.2}.shadow-\[0_1px_3px_rgba\(0\,0\,0\,0\.3\)\,0_0_0_1px_rgba\(255\,255\,255\,0\.03\)\]{--tw-shadow: 0 1px 3px rgba(0,0,0,.3),0 0 0 1px rgba(255,255,255,.03);--tw-shadow-colored: 0 1px 3px var(--tw-shadow-color), 0 0 0 1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-\[inset_0_1px_0_rgba\(255\,255\,255\,0\.04\)\]{--tw-shadow: inset 0 1px 0 rgba(255,255,255,.04);--tw-shadow-colored: inset 0 1px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-200{transition-duration:.2s}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}@keyframes enter{0%{opacity:var(--tw-enter-opacity, 1);transform:translate3d(var(--tw-enter-translate-x, 0),var(--tw-enter-translate-y, 0),0) scale3d(var(--tw-enter-scale, 1),var(--tw-enter-scale, 1),var(--tw-enter-scale, 1)) rotate(var(--tw-enter-rotate, 0))}}@keyframes exit{to{opacity:var(--tw-exit-opacity, 1);transform:translate3d(var(--tw-exit-translate-x, 0),var(--tw-exit-translate-y, 0),0) scale3d(var(--tw-exit-scale, 1),var(--tw-exit-scale, 1),var(--tw-exit-scale, 1)) rotate(var(--tw-exit-rotate, 0))}}.duration-200{animation-duration:.2s}.ease-out{animation-timing-function:cubic-bezier(0,0,.2,1)}@keyframes cardEnter{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.animate-card-enter{animation:cardEnter .3s cubic-bezier(.16,1,.3,1) forwards}@keyframes columnFlash{0%{border-left-width:3px;box-shadow:none}30%{border-left-width:6px}to{border-left-width:3px;box-shadow:none}}.animate-column-flash-todo{animation:columnFlash .6s ease-out;border-left-color:#f59e0b;box-shadow:0 0 8px #f59e0b66}.animate-column-flash-inprogress{animation:columnFlash .6s ease-out;border-left-color:#3b82f6;box-shadow:0 0 8px #3b82f666}.animate-column-flash-done{animation:columnFlash .6s ease-out;border-left-color:#10b981;box-shadow:0 0 8px #10b98166}.animate-column-flash-blocked{animation:columnFlash .6s ease-out;border-left-color:#ef4444;box-shadow:0 0 8px #ef444466}@keyframes toastIn{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}@keyframes toastOut{0%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(20px)}}.animate-toast-in{animation:toastIn .3s cubic-bezier(.16,1,.3,1) forwards}@keyframes pulseRing{0%{transform:scale(1);opacity:.6}to{transform:scale(2.5);opacity:0}}.animate-pulse-ring{animation:pulseRing 2s ease-out infinite}@keyframes emptyFade{0%{opacity:0}to{opacity:1}}.animate-empty-fade{animation:emptyFade .2s ease forwards}.hover\:bg-\[\#1A1A24\]:hover{--tw-bg-opacity: 1;background-color:rgb(26 26 36 / var(--tw-bg-opacity, 1))}.hover\:bg-\[\#27273A\]:hover{--tw-bg-opacity: 1;background-color:rgb(39 39 58 / var(--tw-bg-opacity, 1))}.hover\:shadow-\[0_4px_12px_rgba\(0\,0\,0\,0\.4\)\,0_0_0_1px_rgba\(255\,255\,255\,0\.05\)\]:hover{--tw-shadow: 0 4px 12px rgba(0,0,0,.4),0 0 0 1px rgba(255,255,255,.05);--tw-shadow-colored: 0 4px 12px var(--tw-shadow-color), 0 0 0 1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}
|