@m0xoo/openboard 1.0.13 → 1.0.15

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.
@@ -6,8 +6,8 @@
6
6
  <title>OpenBoard</title>
7
7
  <meta name="description" content="A local project management board — create boards, columns, and tickets." />
8
8
  <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
9
- <script type="module" crossorigin src="/assets/index-BVnFqWqB.js"></script>
10
- <link rel="stylesheet" crossorigin href="/assets/index-B8sYFX2d.css">
9
+ <script type="module" crossorigin src="/assets/index-UoAzXFQl.js"></script>
10
+ <link rel="stylesheet" crossorigin href="/assets/index-A8hU3crn.css">
11
11
  </head>
12
12
  <body>
13
13
  <div id="root"></div>
@@ -51,6 +51,7 @@ export async function setupOpencodeEventListener(events, opencodeClient, session
51
51
  const processedMessages = new Set();
52
52
  const processedTools = new Set();
53
53
  const activeParts = new Map();
54
+ let rawSessionCost = 0;
54
55
  try {
55
56
  for await (const event of events.stream) {
56
57
  // FILTER for events belonging solely to THIS session
@@ -121,6 +122,9 @@ export async function setupOpencodeEventListener(events, opencodeClient, session
121
122
  // Handle Text Messages (Wait for assistant message to complete)
122
123
  if (event.type === 'message.updated') {
123
124
  const info = event.properties.info;
125
+ if (info.cost) {
126
+ rawSessionCost += info.cost;
127
+ }
124
128
  if (info.role === 'assistant' && info.time?.completed && !processedMessages.has(info.id)) {
125
129
  processedMessages.add(info.id);
126
130
  try {
@@ -128,12 +132,22 @@ export async function setupOpencodeEventListener(events, opencodeClient, session
128
132
  if (messagesRes.data) {
129
133
  const targetMsg = messagesRes.data.find((m) => m.info.id === info.id);
130
134
  if (targetMsg && targetMsg.parts) {
135
+ let combinedText = '';
131
136
  for (const part of targetMsg.parts) {
132
137
  if (part.type === 'text' && part.text?.trim()) {
138
+ combinedText += (combinedText ? '\n\n' : '') + part.text.trim();
139
+ }
140
+ }
141
+ if (combinedText) {
142
+ const existing = activeParts.get(info.id); // info.id is messageID
143
+ if (existing) {
144
+ commentRepository.update(existing.commentId, combinedText);
145
+ }
146
+ else {
133
147
  commentRepository.create({
134
148
  ticketId: ticket.id,
135
149
  author: 'opencode',
136
- content: part.text.trim()
150
+ content: combinedText
137
151
  });
138
152
  }
139
153
  }
@@ -146,33 +160,19 @@ export async function setupOpencodeEventListener(events, opencodeClient, session
146
160
  }
147
161
  }
148
162
  // Handle Tool Completions and Reasoning Real-Time
163
+ // (WE NOW IGNORE THESE AS PER USER REQUEST TO ONLY SHOW IMPORTANT COMMENTS)
149
164
  if (event.type === 'message.part.updated') {
150
165
  const part = event.properties.part;
151
- // 1. Handle tool executions
152
- if (part.type === 'tool' && part.state?.status === 'completed' && !processedTools.has(part.id)) {
153
- processedTools.add(part.id);
154
- let content = `Executed \`${part.tool}\``;
155
- if (part.state.title)
156
- content += `\n*${part.state.title}*`;
157
- commentRepository.create({
158
- ticketId: ticket.id,
159
- author: 'opencode',
160
- content: content
161
- });
162
- }
163
- // 2. Handle final reasoning/thoughts block (if not caught by deltas)
164
- if (part.type === 'reasoning' && !processedTools.has(part.id)) {
165
- processedTools.add(part.id);
166
- // If we already tracked this via deltas, don't recreate it
167
- if (!activeParts.has(part.id) && part.text && part.text.trim()) {
168
- commentRepository.create({
169
- ticketId: ticket.id,
170
- author: 'opencode (thought)',
171
- content: part.text.trim()
172
- });
173
- }
166
+ if (part.type === 'step-finish' && part.cost) {
167
+ rawSessionCost += part.cost;
174
168
  }
175
169
  }
170
+ /*
171
+ if (event.type === 'message.part.updated') {
172
+ const part = event.properties.part;
173
+ // ... logic removed ...
174
+ }
175
+ */
176
176
  // Handle Session Idle (Task Completed)
177
177
  if (event.type === 'session.idle') {
178
178
  console.log(`[opencode-agent] Agent task completed (idle) for ticket ${ticket.id}.`);
@@ -188,7 +188,8 @@ export async function setupOpencodeEventListener(events, opencodeClient, session
188
188
  agent_type: agentType,
189
189
  status: 'done',
190
190
  port: 4096,
191
- url: agentUrl
191
+ url: agentUrl,
192
+ total_cost: rawSessionCost > 0 ? Number(rawSessionCost.toFixed(4)) : undefined
192
193
  });
193
194
  if (agentType === 'code_review') {
194
195
  try {
@@ -313,7 +314,7 @@ export async function setupOpencodeEventListener(events, opencodeClient, session
313
314
  commentRepository.create({
314
315
  ticketId: ticket.id,
315
316
  author: 'System',
316
- content: `🚀 **Pull Request Updated**\n\nThe agent has updated the existing PR:\n${prUrl}`
317
+ content: `🚀 **Pull Request Updated**\n\nThe agent has updated the existing PR:\n${prUrl}${rawSessionCost > 0 ? `\n\n**Total Cost:** $${rawSessionCost.toFixed(4)}` : ''}`
317
318
  });
318
319
  }
319
320
  else {
@@ -322,7 +323,7 @@ export async function setupOpencodeEventListener(events, opencodeClient, session
322
323
  commentRepository.create({
323
324
  ticketId: ticket.id,
324
325
  author: 'System',
325
- content: `🚀 **Pull Request Created**\n\nThe agent has proposed the following changes in a PR. Check it out:\n${prUrl}`
326
+ content: `🚀 **Pull Request Created**\n\nThe agent has proposed the following changes in a PR. Check it out:\n${prUrl}${rawSessionCost > 0 ? `\n\n**Total Cost:** $${rawSessionCost.toFixed(4)}` : ''}`
326
327
  });
327
328
  }
328
329
  // Add PR URL to the active agent session so the UI displays the code review button
@@ -332,7 +333,9 @@ export async function setupOpencodeEventListener(events, opencodeClient, session
332
333
  status: 'done',
333
334
  port: 4096,
334
335
  url: agentUrl,
335
- pr_url: prUrl
336
+ pr_url: prUrl,
337
+ pr_status: 'OPEN',
338
+ total_cost: rawSessionCost > 0 ? Number(rawSessionCost.toFixed(4)) : undefined
336
339
  });
337
340
  }
338
341
  else {
@@ -340,7 +343,7 @@ export async function setupOpencodeEventListener(events, opencodeClient, session
340
343
  commentRepository.create({
341
344
  ticketId: ticket.id,
342
345
  author: 'System',
343
- content: `ℹ️ **Task Completed (No Changes)**\n\nThe agent finished the task but did not make any code changes.`
346
+ content: `ℹ️ **Task Completed (No Changes)**\n\nThe agent finished the task but did not make any code changes.${rawSessionCost > 0 ? `\n\n**Total Cost:** $${rawSessionCost.toFixed(4)}` : ''}`
344
347
  });
345
348
  }
346
349
  }
@@ -376,8 +379,12 @@ export async function setupOpencodeEventListener(events, opencodeClient, session
376
379
  if (event.type === 'message.part.delta') {
377
380
  const partID = event.properties.partID;
378
381
  const delta = event.properties.delta;
379
- if (delta) {
380
- let tracking = activeParts.get(partID);
382
+ // To know if this part is 'text', we check if we've seen it as text in a part.updated
383
+ // or if it belongs to an assistant message we want to track.
384
+ // However, to satisfy "one comment per section", we should group by messageID.
385
+ const messageID = event.properties.messageID;
386
+ if (delta && messageID) {
387
+ let tracking = activeParts.get(messageID);
381
388
  if (!tracking) {
382
389
  // create initial comment
383
390
  const comment = commentRepository.create({
@@ -386,7 +393,7 @@ export async function setupOpencodeEventListener(events, opencodeClient, session
386
393
  content: delta
387
394
  });
388
395
  tracking = { commentId: comment.id, fullText: delta };
389
- activeParts.set(partID, tracking);
396
+ activeParts.set(messageID, tracking);
390
397
  }
391
398
  else {
392
399
  // update existing comment
@@ -0,0 +1,82 @@
1
+ import { ticketRepository } from './repositories/ticket.repository.js';
2
+ import { commentRepository } from './repositories/comment.repository.js';
3
+ import { execFile } from 'child_process';
4
+ import { promisify } from 'util';
5
+ import { getDb } from './db/database.js';
6
+ const execFileAsync = promisify(execFile);
7
+ export class GhWorker {
8
+ interval = null;
9
+ isPolling = false;
10
+ start() {
11
+ console.log('[gh-worker] Starting GitHub PR status worker...');
12
+ this.poll();
13
+ this.interval = setInterval(() => this.poll(), 10_000); // Every 60 seconds
14
+ }
15
+ stop() {
16
+ if (this.interval) {
17
+ clearInterval(this.interval);
18
+ this.interval = null;
19
+ }
20
+ }
21
+ async poll() {
22
+ if (this.isPolling)
23
+ return;
24
+ this.isPolling = true;
25
+ try {
26
+ // Find all tickets with a PR URL that isn't merged or closed
27
+ const db = getDb();
28
+ const rows = db.prepare('SELECT * FROM tickets').all();
29
+ for (const row of rows) {
30
+ let sessions = [];
31
+ try {
32
+ sessions = JSON.parse(row.agent_sessions);
33
+ }
34
+ catch {
35
+ continue;
36
+ }
37
+ if (!sessions || sessions.length === 0)
38
+ continue;
39
+ for (let i = sessions.length - 1; i >= 0; i--) {
40
+ const session = sessions[i];
41
+ if (session.pr_url && (!session.pr_status || session.pr_status === 'OPEN')) {
42
+ try {
43
+ const { stdout } = await execFileAsync('gh', ['pr', 'view', session.pr_url, '--json', 'state'], { shell: true });
44
+ const data = JSON.parse(stdout);
45
+ const newState = data.state; // 'OPEN', 'MERGED', 'CLOSED'
46
+ if (newState && newState !== session.pr_status) {
47
+ console.log(`[gh-worker] PR status changed from ${session.pr_status} to ${newState} for ticket ${row.id}`);
48
+ // Update this specific session
49
+ session.pr_status = newState;
50
+ ticketRepository.updateAgentSession(row.id, session);
51
+ if (newState === 'MERGED') {
52
+ commentRepository.create({
53
+ ticketId: row.id,
54
+ author: 'System',
55
+ content: `🎉 **Pull Request Merged!**\n\nThe PR [${session.pr_url}](${session.pr_url}) has been merged.`
56
+ });
57
+ }
58
+ else if (newState === 'CLOSED') {
59
+ commentRepository.create({
60
+ ticketId: row.id,
61
+ author: 'System',
62
+ content: `🚫 **Pull Request Closed**\n\nThe PR [${session.pr_url}](${session.pr_url}) was closed without merging.`
63
+ });
64
+ }
65
+ }
66
+ }
67
+ catch (e) {
68
+ console.warn(`[gh-worker] Failed to check PR status for ${session.pr_url}: ${e.message}`);
69
+ }
70
+ }
71
+ }
72
+ }
73
+ }
74
+ catch (err) {
75
+ console.error('[gh-worker] Polling error:', err);
76
+ }
77
+ finally {
78
+ this.isPolling = false;
79
+ }
80
+ }
81
+ }
82
+ export const ghWorker = new GhWorker();
@@ -6,6 +6,7 @@ import { columnsRouter } from './routes/columns.router.js';
6
6
  import { ticketsRouter } from './routes/tickets.router.js';
7
7
  import { columnConfigRouter } from './routes/column-config.router.js';
8
8
  import { sseManager } from './sse.js';
9
+ import { ghWorker } from './gh-worker.js';
9
10
  import path from 'path';
10
11
  import { fileURLToPath } from 'url';
11
12
  const __filename = fileURLToPath(import.meta.url);
@@ -14,6 +15,7 @@ const PORT = process.env.PORT ?? 3001;
14
15
  async function start() {
15
16
  await initDb();
16
17
  console.log('[openboard] Database ready');
18
+ ghWorker.start();
17
19
  const app = express();
18
20
  app.use(cors({ origin: process.env.CLIENT_ORIGIN ? process.env.CLIENT_ORIGIN.split(',') : ['http://localhost:5173', 'http://localhost:4173'] }));
19
21
  app.use(express.json());
@@ -1 +0,0 @@
1
- @import"https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap";:root,[data-theme=dark]{--color-bg: #0a0a0a;--color-surface: #111111;--color-surface-2: #1a1a1a;--color-surface-3: #222222;--color-border: rgba(255, 255, 255, .08);--color-border-hover: rgba(255, 255, 255, .16);--color-text-primary: #ededed;--color-text-secondary: #a1a1aa;--color-text-muted: #52525b;--color-text-on-accent: #ffffff;--color-accent: #5e6ad2;--color-accent-hover: #6b7ae2;--color-accent-subtle: rgba(94, 106, 210, .15);--color-priority-low: #3b82f6;--color-priority-medium: #f59e0b;--color-priority-high: #f97316;--color-priority-urgent: #ef4444;--color-success: #22c55e;--color-error: #ef4444;--shadow-sm: 0 1px 2px rgba(0, 0, 0, .5);--shadow-md: 0 4px 12px rgba(0, 0, 0, .6);--shadow-lg: 0 8px 32px rgba(0, 0, 0, .7);--scrollbar-thumb: rgba(255, 255, 255, .1);--scrollbar-track: transparent}[data-theme=light]{--color-bg: #f4f4f5;--color-surface: #ffffff;--color-surface-2: #f4f4f5;--color-surface-3: #e4e4e7;--color-border: rgba(0, 0, 0, .08);--color-border-hover: rgba(0, 0, 0, .16);--color-text-primary: #09090b;--color-text-secondary: #52525b;--color-text-muted: #a1a1aa;--color-text-on-accent: #ffffff;--color-accent: #5e6ad2;--color-accent-hover: #4f59c2;--color-accent-subtle: rgba(94, 106, 210, .1);--color-priority-low: #2563eb;--color-priority-medium: #d97706;--color-priority-high: #ea580c;--color-priority-urgent: #dc2626;--color-success: #16a34a;--color-error: #dc2626;--shadow-sm: 0 1px 2px rgba(0, 0, 0, .06);--shadow-md: 0 4px 12px rgba(0, 0, 0, .08);--shadow-lg: 0 8px 32px rgba(0, 0, 0, .12);--scrollbar-thumb: rgba(0, 0, 0, .12);--scrollbar-track: transparent}:root{--space-1: 4px;--space-2: 8px;--space-3: 12px;--space-4: 16px;--space-5: 20px;--space-6: 24px;--space-8: 32px;--space-10: 40px;--space-12: 48px;--radius-sm: 4px;--radius-md: 6px;--radius-lg: 10px;--radius-xl: 16px;--radius-full: 9999px;--font-sans: "Inter", system-ui, -apple-system, sans-serif;--font-mono: "Fira Code", "Cascadia Code", monospace;--text-xs: 11px;--text-sm: 13px;--text-base: 14px;--text-md: 15px;--text-lg: 17px;--text-xl: 20px;--text-2xl: 24px;--line-height-tight: 1.25;--line-height-normal: 1.5;--transition-fast: 80ms ease;--transition-normal: .15s ease;--transition-slow: .25s ease;--sidebar-width: 220px;--topbar-height: 48px;--column-width: 280px}*,*:before,*:after{box-sizing:border-box;margin:0;padding:0}html{font-size:16px;-webkit-text-size-adjust:100%}body{font-family:var(--font-sans);font-size:var(--text-base);line-height:var(--line-height-normal);background-color:var(--color-bg);color:var(--color-text-primary);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;overflow:hidden}::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background:var(--scrollbar-track)}::-webkit-scrollbar-thumb{background:var(--scrollbar-thumb);border-radius:var(--radius-full)}::-webkit-scrollbar-thumb:hover{background:var(--color-border-hover)}.text-primary{color:var(--color-text-primary)}.text-secondary{color:var(--color-text-secondary)}.text-muted{color:var(--color-text-muted)}.text-xs{font-size:var(--text-xs)}.text-sm{font-size:var(--text-sm)}.text-base{font-size:var(--text-base)}.text-md{font-size:var(--text-md)}.text-lg{font-size:var(--text-lg)}.font-medium{font-weight:500}.font-semibold{font-weight:600}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.flex{display:flex}.flex-col{flex-direction:column}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-1{gap:var(--space-1)}.gap-2{gap:var(--space-2)}.gap-3{gap:var(--space-3)}.gap-4{gap:var(--space-4)}.flex-1{flex:1}.min-w-0{min-width:0}.overflow-hidden{overflow:hidden}.overflow-auto{overflow:auto}.w-full{width:100%}.h-full{height:100%}button{font-family:inherit;cursor:pointer;border:none;background:none;outline:none;transition:background var(--transition-normal),color var(--transition-normal),opacity var(--transition-fast)}button:disabled{opacity:.4;cursor:not-allowed}input,textarea{font-family:inherit;color:inherit;background:none;border:none;outline:none}a{color:inherit;text-decoration:none}:focus-visible{outline:2px solid var(--color-accent);outline-offset:2px;border-radius:var(--radius-sm)}._sidebar_1y03c_1{width:var(--sidebar-width);height:100vh;background:var(--color-surface);border-right:1px solid var(--color-border);display:flex;flex-direction:column;flex-shrink:0;overflow:hidden}._header_1y03c_23{height:var(--topbar-height);display:flex;align-items:center;padding:0 var(--space-4);border-bottom:1px solid var(--color-border)}._logo_1y03c_39{display:flex;align-items:center;gap:var(--space-2);font-size:var(--text-sm);font-weight:600;color:var(--color-text-primary);letter-spacing:-.01em}._logo_1y03c_39 svg{color:var(--color-accent)}._section_1y03c_67{display:flex;align-items:center;justify-content:space-between;padding:var(--space-4) var(--space-4) var(--space-2)}._sectionLabel_1y03c_81{font-size:var(--text-xs);font-weight:500;color:var(--color-text-muted);text-transform:uppercase;letter-spacing:.06em}._newBtn_1y03c_97{width:20px;height:20px;border-radius:var(--radius-sm);display:flex;align-items:center;justify-content:center;color:var(--color-text-muted);transition:background var(--transition-normal),color var(--transition-normal)}._newBtn_1y03c_97:hover{background:var(--color-surface-2);color:var(--color-text-primary)}._nav_1y03c_129{flex:1;overflow-y:auto;padding:var(--space-1) var(--space-2)}._boardItem_1y03c_141{position:relative;border-radius:var(--radius-md);margin-bottom:1px}._boardBtn_1y03c_153{width:100%;display:flex;align-items:center;gap:var(--space-2);padding:var(--space-2) var(--space-3);border-radius:var(--radius-md);font-size:var(--text-sm);color:var(--color-text-secondary);text-align:left;transition:background var(--transition-normal),color var(--transition-normal)}._boardBtn_1y03c_153:hover{background:var(--color-surface-2);color:var(--color-text-primary)}._boardItem_1y03c_141._active_1y03c_189 ._boardBtn_1y03c_153{background:var(--color-accent-subtle);color:var(--color-text-primary)}._boardDot_1y03c_199{width:6px;height:6px;border-radius:50%;background:var(--color-text-muted);flex-shrink:0;transition:background var(--transition-normal)}._boardItem_1y03c_141._active_1y03c_189 ._boardDot_1y03c_199{background:var(--color-accent)}._actions_1y03c_225{position:absolute;right:var(--space-2);top:50%;transform:translateY(-50%);display:flex;gap:2px}._action_1y03c_225{width:22px;height:22px;display:flex;align-items:center;justify-content:center;border-radius:var(--radius-sm);color:var(--color-text-muted);transition:background var(--transition-fast),color var(--transition-fast)}._action_1y03c_225:hover{background:var(--color-surface-3);color:var(--color-text-primary)}._inlineEdit_1y03c_275{width:100%;padding:var(--space-2) var(--space-3);font-size:var(--text-sm);color:var(--color-text-primary);background:var(--color-surface-2);border-radius:var(--radius-md);border:1px solid var(--color-accent)}._overlay_1kuf8_1{position:fixed;top:0;right:0;bottom:0;left:0;background:#0009;display:flex;align-items:center;justify-content:center;z-index:100;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);animation:_fadeIn_1kuf8_1 .15s ease}@keyframes _fadeIn_1kuf8_1{0%{opacity:0}to{opacity:1}}._dialog_1kuf8_45{background:var(--color-surface-2);border:1px solid var(--color-border);border-radius:var(--radius-lg);padding:var(--space-6);max-width:340px;width:90%;box-shadow:var(--shadow-lg);animation:_slideIn_1kuf8_1 .15s ease}@keyframes _slideIn_1kuf8_1{0%{transform:translateY(-8px);opacity:0}to{transform:translateY(0);opacity:1}}._message_1kuf8_91{font-size:var(--text-sm);color:var(--color-text-secondary);line-height:var(--line-height-normal);margin-bottom:var(--space-6)}._actions_1kuf8_105{display:flex;justify-content:flex-end;gap:var(--space-2)}._cancel_1kuf8_117{padding:var(--space-2) var(--space-4);border-radius:var(--radius-md);font-size:var(--text-sm);font-weight:500;color:var(--color-text-secondary);border:1px solid var(--color-border);background:transparent;transition:background var(--transition-normal),color var(--transition-normal)}._cancel_1kuf8_117:hover{background:var(--color-surface-3);color:var(--color-text-primary)}._confirm_1kuf8_149{padding:var(--space-2) var(--space-4);border-radius:var(--radius-md);font-size:var(--text-sm);font-weight:500;color:#fff;background:var(--color-error);transition:opacity var(--transition-fast)}._confirm_1kuf8_149:hover{opacity:.85}._overlay_e33j2_1{position:fixed;top:0;right:0;bottom:0;left:0;background:#000000a6;display:flex;align-items:flex-start;justify-content:center;padding-top:80px;z-index:100;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);animation:_fadeIn_e33j2_1 .15s ease}@keyframes _fadeIn_e33j2_1{0%{opacity:0}to{opacity:1}}._modal_e33j2_47{background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-xl);width:600px;max-width:calc(100vw - 32px);max-height:calc(100vh - 120px);overflow-y:auto;box-shadow:var(--shadow-lg);animation:_slideIn_e33j2_1 .15s cubic-bezier(.16,1,.3,1);display:flex;flex-direction:column}@keyframes _slideIn_e33j2_1{0%{transform:translateY(-16px);opacity:0}to{transform:translateY(0);opacity:1}}._header_e33j2_99{display:flex;align-items:center;justify-content:space-between;padding:var(--space-6) var(--space-8);border-bottom:1px solid var(--color-border)}._header_e33j2_99 h2{margin:0;font-size:var(--text-lg);font-weight:600;color:var(--color-text-primary)}._closeBtn_e33j2_129{width:28px;height:28px;display:flex;align-items:center;justify-content:center;border-radius:var(--radius-md);color:var(--color-text-muted);background:transparent;border:none;cursor:pointer;transition:background var(--transition-fast),color var(--transition-fast)}._closeBtn_e33j2_129:hover{background:var(--color-surface-2);color:var(--color-text-primary)}._content_e33j2_167{padding:var(--space-8);display:flex;flex-direction:column;gap:var(--space-6)}._field_e33j2_181{display:flex;flex-direction:column;gap:var(--space-2)}._field_e33j2_181 label{font-size:var(--text-xs);font-weight:500;color:var(--color-text-muted);text-transform:uppercase;letter-spacing:.06em}._input_e33j2_209{width:100%;padding:var(--space-3) var(--space-4);background:var(--color-surface-2);border:1px solid var(--color-border);border-radius:var(--radius-md);font-size:var(--text-sm);color:var(--color-text-primary);transition:border-color var(--transition-fast)}._input_e33j2_209:focus{outline:none;border-color:var(--color-accent)}._workspacesSection_e33j2_241{display:flex;flex-direction:column;gap:var(--space-4)}._sectionHeader_e33j2_253{display:flex;justify-content:space-between;align-items:center}._sectionHeader_e33j2_253 h3{margin:0;font-size:var(--text-xs);font-weight:500;color:var(--color-text-muted);text-transform:uppercase;letter-spacing:.06em}._addBtn_e33j2_283{display:flex;align-items:center;gap:var(--space-1);font-size:var(--text-xs);font-weight:500;color:var(--color-accent);background:transparent;border:none;cursor:pointer;padding:var(--space-1) var(--space-2);border-radius:var(--radius-sm);transition:background var(--transition-fast)}._addBtn_e33j2_283:hover{background:color-mix(in srgb,var(--color-accent) 10%,transparent)}._workspaceList_e33j2_321{display:flex;flex-direction:column;gap:var(--space-3)}._workspaceRow_e33j2_333{display:flex;gap:var(--space-2);align-items:center}._select_e33j2_345{padding:var(--space-2) var(--space-3);background:var(--color-surface-2);border:1px solid var(--color-border);border-radius:var(--radius-md);font-size:var(--text-xs);color:var(--color-text-primary);cursor:pointer}._pathInputWrapper_e33j2_365{flex:1;display:flex;align-items:center;gap:var(--space-2);padding:0 var(--space-3);background:var(--color-surface-2);border:1px solid var(--color-border);border-radius:var(--radius-md);transition:border-color var(--transition-fast)}._pathInputWrapper_e33j2_365:focus-within{border-color:var(--color-accent)}._pathInputWrapper_e33j2_365 svg{color:var(--color-text-muted)}._pathInput_e33j2_365{flex:1;padding:var(--space-2) 0;background:transparent;border:none;font-size:var(--text-sm);color:var(--color-text-primary)}._pathInput_e33j2_365:focus{outline:none}._removeBtn_e33j2_431{width:28px;height:28px;display:flex;align-items:center;justify-content:center;border-radius:var(--radius-md);color:var(--color-text-muted);background:transparent;border:none;cursor:pointer;transition:background var(--transition-fast),color var(--transition-fast)}._removeBtn_e33j2_431:hover{background:color-mix(in srgb,var(--color-error) 12%,transparent);color:var(--color-error)}._footer_e33j2_469{display:flex;align-items:center;justify-content:flex-end;gap:var(--space-2);padding:var(--space-6) var(--space-8);border-top:1px solid var(--color-border)}._cancelBtn_e33j2_487{padding:var(--space-2) var(--space-4);border-radius:var(--radius-md);font-size:var(--text-sm);font-weight:500;color:var(--color-text-secondary);border:1px solid var(--color-border);background:transparent;cursor:pointer;transition:background var(--transition-normal)}._cancelBtn_e33j2_487:hover{background:var(--color-surface-2)}._saveBtn_e33j2_519{padding:var(--space-2) var(--space-4);border-radius:var(--radius-md);font-size:var(--text-sm);font-weight:500;color:var(--color-text-on-accent);background:var(--color-accent);border:none;cursor:pointer;transition:opacity var(--transition-fast)}._saveBtn_e33j2_519:hover:not(:disabled){opacity:.85}._saveBtn_e33j2_519:disabled{opacity:.4;cursor:not-allowed}._badge_1qhnp_1{display:inline-flex;align-items:center;border-radius:var(--radius-full);font-weight:500;background:color-mix(in srgb,var(--priority-color) 15%,transparent);color:var(--priority-color);white-space:nowrap}._sm_1qhnp_21{font-size:var(--text-xs);padding:2px 7px}._md_1qhnp_31{font-size:var(--text-sm);padding:var(--space-1) var(--space-3)}._card_mtqwy_1{background:var(--color-surface-2);border:1px solid var(--color-border);border-radius:var(--radius-md);padding:var(--space-3);cursor:pointer;transition:background var(--transition-fast),border-color var(--transition-fast),box-shadow var(--transition-fast),transform var(--transition-fast);-webkit-user-select:none;user-select:none;position:relative}._card_mtqwy_1:hover{background:var(--color-surface-3);border-color:var(--color-border-hover);box-shadow:var(--shadow-sm)}._card_mtqwy_1._dragging_mtqwy_37{box-shadow:var(--shadow-md);cursor:grabbing}._needsApprovalCard_mtqwy_47{border-color:#f59e0b99!important;background:linear-gradient(to bottom right,rgba(245,158,11,.05),var(--color-surface-2))!important;animation:_pulseBorder_mtqwy_1 2s infinite ease-in-out}._needsApprovalCard_mtqwy_47:hover{border-color:#f59e0b!important;background:linear-gradient(to bottom right,rgba(245,158,11,.08),var(--color-surface-3))!important}@keyframes _pulseBorder_mtqwy_1{0%{box-shadow:0 0 #f59e0b66}70%{box-shadow:0 0 0 6px #f59e0b00}to{box-shadow:0 0 #f59e0b00}}._title_mtqwy_97{font-size:var(--text-sm);font-weight:500;color:var(--color-text-primary);line-height:var(--line-height-tight);margin-bottom:var(--space-1)}._titleWithPr_mtqwy_113{padding-right:64px}._prButtonOverlay_mtqwy_121{position:absolute;top:var(--space-2);right:var(--space-2);z-index:10}._description_mtqwy_135{font-size:var(--text-xs);color:var(--color-text-muted);line-height:var(--line-height-normal);margin-bottom:var(--space-2);display:-webkit-box;-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}._footer_mtqwy_159{display:flex;align-items:center;justify-content:space-between;margin-top:var(--space-2)}._left_mtqwy_173{display:flex;align-items:center;gap:var(--space-2)}._inspectBtn_mtqwy_185{display:inline-flex;align-items:center;gap:var(--space-1);font-size:var(--text-xs);font-weight:500;padding:var(--space-1) var(--space-2);border-radius:var(--radius-sm);text-decoration:none;transition:background var(--transition-fast),color var(--transition-fast)}._processingBtn_mtqwy_209{color:var(--color-accent);background:rgba(var(--color-accent-rgb),.1)}._processingBtn_mtqwy_209:hover{background:rgba(var(--color-accent-rgb),.2)}._doneBtn_mtqwy_227{color:#10b981;background:#10b9811a}._doneBtn_mtqwy_227:hover{background:#10b98133}._blockedBtn_mtqwy_245{color:#ef4444;background:#ef44441a}._blockedBtn_mtqwy_245:hover{background:#ef444433}._needsApprovalBtn_mtqwy_263{color:#f59e0b;background:#f59e0b1a}._needsApprovalBtn_mtqwy_263:hover{background:#f59e0b33}._processingIcon_mtqwy_281{animation:_pulse_mtqwy_1 2s infinite ease-in-out}@keyframes _pulse_mtqwy_1{0%{opacity:.4}50%{opacity:1}to{opacity:.4}}._overlay_1ypt0_1{position:fixed;top:0;right:0;bottom:0;left:0;background:#000000a6;display:flex;align-items:flex-start;justify-content:center;padding-top:80px;z-index:50;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);animation:_fadeIn_1ypt0_1 .15s ease}@keyframes _fadeIn_1ypt0_1{0%{opacity:0}to{opacity:1}}._modal_1ypt0_47{background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-xl);width:600px;max-width:calc(100vw - 32px);max-height:calc(100vh - 120px);display:flex;flex-direction:column;overflow:hidden;box-shadow:var(--shadow-lg);animation:_slideIn_1ypt0_1 .15s cubic-bezier(.16,1,.3,1)}._content_1ypt0_75{overflow-y:auto;flex:1}@keyframes _slideIn_1ypt0_1{0%{transform:translateY(-16px);opacity:0}to{transform:translateY(0);opacity:1}}._header_1ypt0_109{display:flex;align-items:center;justify-content:space-between;padding:var(--space-6) var(--space-8);border-bottom:1px solid var(--color-border);flex-shrink:0}._meta_1ypt0_127{display:flex;align-items:center;gap:var(--space-2)}._statusBadge_1ypt0_151{display:flex;align-items:center;gap:4px;font-size:var(--text-xs);font-weight:500;padding:2px 8px;border-radius:var(--radius-full);text-decoration:none;transition:background var(--transition-fast),color var(--transition-fast)}._statusBadge_1ypt0_151._processing_1ypt0_175{color:var(--color-accent);background:rgba(var(--color-accent-rgb),.1)}._statusBadge_1ypt0_151._processing_1ypt0_175:hover{background:rgba(var(--color-accent-rgb),.2)}._statusBadge_1ypt0_151._done_1ypt0_193{color:#10b981;background:#10b9811a}._statusBadge_1ypt0_151._done_1ypt0_193:hover{background:#10b98133}._statusBadge_1ypt0_151._blocked_1ypt0_211{color:#ef4444;background:#ef44441a}._statusBadge_1ypt0_151._blocked_1ypt0_211:hover{background:#ef444433}._statusBadge_1ypt0_151._needsApproval_1ypt0_229{color:#f59e0b;background:#f59e0b1a}._statusBadge_1ypt0_151._needsApproval_1ypt0_229:hover{background:#f59e0b33}._columnTag_1ypt0_247{font-size:var(--text-xs);color:var(--color-text-muted);font-weight:500;background:var(--color-surface-2);border:1px solid var(--color-border);border-radius:var(--radius-full);padding:2px 8px}._closeBtn_1ypt0_267{width:28px;height:28px;display:flex;align-items:center;justify-content:center;border-radius:var(--radius-md);color:var(--color-text-muted);transition:background var(--transition-fast),color var(--transition-fast)}._closeBtn_1ypt0_267:hover{background:var(--color-surface-2);color:var(--color-text-primary)}._headerRight_1ypt0_299{display:flex;align-items:center;gap:var(--space-3)}._sessionBtn_1ypt0_311{display:inline-flex;align-items:center;gap:var(--space-1);font-size:var(--text-xs);font-weight:500;color:var(--color-text-secondary);background:var(--color-surface-2);border:1px solid var(--color-border);padding:var(--space-1) var(--space-3);border-radius:var(--radius-md);text-decoration:none;transition:all var(--transition-fast)}._sessionBtn_1ypt0_311:hover{background:var(--color-surface-3);color:var(--color-text-primary);border-color:var(--color-border-hover)}._body_1ypt0_353{padding:var(--space-8);display:flex;flex-direction:column}._titleInput_1ypt0_365{width:100%;padding:var(--space-2) var(--space-4) 2px;font-size:var(--text-xl);font-weight:600;color:var(--color-text-primary);line-height:var(--line-height-tight);background:transparent;border:none;resize:none;display:block;border-radius:var(--radius-md);transition:background var(--transition-fast)}._titleInput_1ypt0_365:focus{background:var(--color-surface-2);outline:none}._titleInput_1ypt0_365::placeholder{color:var(--color-text-muted)}._descInput_1ypt0_413{width:100%;padding:var(--space-2) var(--space-4) var(--space-3);margin-top:var(--space-1);font-size:var(--text-sm);color:var(--color-text-secondary);line-height:var(--line-height-normal);background:transparent;resize:vertical;border:none;display:block;border-radius:var(--radius-md);transition:background var(--transition-fast)}._descInput_1ypt0_413:focus{background:var(--color-surface-2);outline:none}._descInput_1ypt0_413::placeholder{color:var(--color-text-muted)}._section_1ypt0_461{padding:var(--space-6) var(--space-8);border-top:1px solid var(--color-border)}._sectionLabel_1ypt0_471{font-size:var(--text-xs);font-weight:500;color:var(--color-text-muted);text-transform:uppercase;letter-spacing:.06em;margin-bottom:var(--space-2);display:block}._priorities_1ypt0_491{display:flex;gap:var(--space-2);flex-wrap:wrap}._priorityBtn_1ypt0_503{padding:var(--space-1) var(--space-3);border-radius:var(--radius-full);font-size:var(--text-xs);font-weight:500;color:var(--color-text-secondary);border:1px solid var(--color-border);transition:all var(--transition-fast)}._priorityBtn_1ypt0_503:hover{border-color:var(--priority-color);color:var(--priority-color)}._priorityBtn_1ypt0_503._selected_1ypt0_533{background:color-mix(in srgb,var(--priority-color) 15%,transparent);border-color:var(--priority-color);color:var(--priority-color)}._footer_1ypt0_545{display:flex;align-items:center;justify-content:space-between;padding:var(--space-6) var(--space-8);border-top:1px solid var(--color-border);flex-shrink:0}._footerActions_1ypt0_563{display:flex;gap:var(--space-2)}._deleteBtn_1ypt0_573{display:flex;align-items:center;gap:var(--space-1);font-size:var(--text-sm);color:var(--color-text-muted);padding:var(--space-2) var(--space-3);border-radius:var(--radius-md);transition:background var(--transition-fast),color var(--transition-fast)}._deleteBtn_1ypt0_573:hover{background:color-mix(in srgb,var(--color-error) 12%,transparent);color:var(--color-error)}._cancelBtn_1ypt0_605{padding:var(--space-2) var(--space-4);border-radius:var(--radius-md);font-size:var(--text-sm);font-weight:500;color:var(--color-text-secondary);border:1px solid var(--color-border);transition:background var(--transition-normal)}._cancelBtn_1ypt0_605:hover{background:var(--color-surface-2)}._saveBtn_1ypt0_633{padding:var(--space-2) var(--space-4);border-radius:var(--radius-md);font-size:var(--text-sm);font-weight:500;color:var(--color-text-on-accent);background:var(--color-accent);transition:opacity var(--transition-fast)}._saveBtn_1ypt0_633:hover:not(:disabled){opacity:.85}._saveBtn_1ypt0_633:disabled{opacity:.4;cursor:not-allowed}._commentsSection_1ypt0_671{padding:var(--space-8);border-top:1px solid var(--color-border);display:flex;flex-direction:column;gap:var(--space-6)}._commentList_1ypt0_687{display:flex;flex-direction:column;gap:12px;max-height:250px;overflow-y:auto;padding-right:4px}._comment_1ypt0_671{background:var(--color-surface-2);padding:var(--space-4) var(--space-5);border-radius:var(--radius-lg);border:1px solid var(--color-border)}._commentHeader_1ypt0_719{display:flex;justify-content:space-between;align-items:center;margin-bottom:var(--space-1);font-size:var(--text-xs)}._commentAuthor_1ypt0_735{font-weight:600;color:var(--color-text-main);display:flex;align-items:center;gap:4px}._botIcon_1ypt0_751{color:var(--color-accent)}._commentDate_1ypt0_759{color:var(--color-text-muted)}._commentContent_1ypt0_767{font-size:.875rem;line-height:1.4;white-space:pre-wrap;word-break:break-word}._noComments_1ypt0_781{text-align:center;padding:24px;color:var(--color-text-muted);font-size:.875rem;font-style:italic}._addComment_1ypt0_797{display:flex;gap:8px;margin-top:8px}._commentInput_1ypt0_809{flex:1;background:var(--color-surface-2);border:1px solid var(--color-border);border-radius:var(--radius-md);padding:var(--space-3) var(--space-4);font-size:var(--text-sm);color:var(--color-text-primary);outline:none;transition:all var(--transition-fast)}._commentInput_1ypt0_809:focus{border-color:var(--color-accent)}._sendBtn_1ypt0_841{background:var(--color-accent);color:var(--color-text-on-accent);border:none;border-radius:6px;width:36px;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:opacity var(--transition-fast)}._sendBtn_1ypt0_841:disabled{opacity:.5;cursor:not-allowed}._sendBtn_1ypt0_841:not(:disabled):hover{opacity:.9}._agentHistoryList_1ypt0_887{display:flex;flex-direction:column;gap:var(--space-3);margin-top:var(--space-3)}._historyItem_1ypt0_901{background:var(--color-surface-2);border:1px solid var(--color-border);border-radius:var(--radius-md);padding:var(--space-3);display:flex;flex-direction:column;gap:var(--space-2)}._historyMeta_1ypt0_921{display:flex;align-items:center;justify-content:space-between}._historyCol_1ypt0_933{font-size:var(--text-sm);font-weight:500;color:var(--color-text-primary)}._historyStatus_1ypt0_945{font-size:var(--text-xs);font-weight:600;text-transform:uppercase;letter-spacing:.05em;padding:2px 6px;border-radius:var(--radius-sm)}._historyStatus_1ypt0_945._processing_1ypt0_175{background:rgba(var(--color-accent-rgb),.15);color:var(--color-accent)}._historyStatus_1ypt0_945._done_1ypt0_193{background:#10b98126;color:#10b981}._historyStatus_1ypt0_945._blocked_1ypt0_211{background:#ef444426;color:#ef4444}._historyStatus_1ypt0_945._needs_approval_1ypt0_993{background:#f59e0b26;color:#f59e0b}._historyLinks_1ypt0_1003{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-3)}._historyLink_1ypt0_1003{align-self:flex-start;display:inline-flex;align-items:center;gap:4px;font-size:var(--text-xs);font-weight:500;color:var(--color-accent);text-decoration:none;transition:opacity var(--transition-fast)}._historyLink_1ypt0_1003:hover{opacity:.8;text-decoration:underline}._historyError_1ypt0_1051{font-size:var(--text-xs);color:var(--color-error);background:color-mix(in srgb,var(--color-error) 10%,transparent);padding:var(--space-2);border-radius:var(--radius-sm);white-space:pre-wrap;word-break:break-all}._overlay_9jvqp_1{position:fixed;top:0;right:0;bottom:0;left:0;background:#000000a6;display:flex;align-items:flex-start;justify-content:center;padding-top:80px;z-index:50;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);animation:_fadeIn_9jvqp_1 .15s ease}@keyframes _fadeIn_9jvqp_1{0%{opacity:0}to{opacity:1}}._modal_9jvqp_47{background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-xl);width:500px;max-width:calc(100vw - 32px);box-shadow:var(--shadow-lg);animation:_slideIn_9jvqp_1 .15s cubic-bezier(.16,1,.3,1)}@keyframes _slideIn_9jvqp_1{0%{transform:translateY(-16px);opacity:0}to{transform:translateY(0);opacity:1}}._header_9jvqp_91{display:flex;align-items:center;justify-content:space-between;padding:var(--space-6) var(--space-8);border-bottom:1px solid var(--color-border);font-size:var(--text-lg);font-weight:600}._closeBtn_9jvqp_111{width:28px;height:28px;display:flex;align-items:center;justify-content:center;border-radius:var(--radius-md);color:var(--color-text-muted);transition:background var(--transition-fast),color var(--transition-fast)}._closeBtn_9jvqp_111:hover{background:var(--color-surface-2);color:var(--color-text-primary)}._body_9jvqp_143{padding:var(--space-8);display:flex;flex-direction:column;gap:var(--space-6)}._formGroup_9jvqp_157{display:flex;flex-direction:column;gap:var(--space-2)}._label_9jvqp_169{font-size:var(--text-sm);font-weight:500;color:var(--color-text-primary)}._select_9jvqp_181,._input_9jvqp_183{width:100%;background:var(--color-surface-2);border:1px solid var(--color-border);border-radius:var(--radius-md);padding:var(--space-3) var(--space-4);font-size:var(--text-sm);color:var(--color-text-primary);outline:none;transition:all var(--transition-fast)}._select_9jvqp_181:focus,._input_9jvqp_183:focus{border-color:var(--color-accent)}._footer_9jvqp_217{display:flex;align-items:center;justify-content:flex-end;padding:var(--space-6) var(--space-8);border-top:1px solid var(--color-border);gap:var(--space-3)}._cancelBtn_9jvqp_235{padding:var(--space-2) var(--space-4);border-radius:var(--radius-md);font-size:var(--text-sm);font-weight:500;color:var(--color-text-secondary);border:1px solid var(--color-border);transition:background var(--transition-normal)}._cancelBtn_9jvqp_235:hover{background:var(--color-surface-2)}._saveBtn_9jvqp_263{padding:var(--space-2) var(--space-4);border-radius:var(--radius-md);font-size:var(--text-sm);font-weight:500;color:var(--color-text-on-accent);background:var(--color-accent);transition:opacity var(--transition-fast)}._saveBtn_9jvqp_263:hover:not(:disabled){opacity:.85}._saveBtn_9jvqp_263:disabled{opacity:.4;cursor:not-allowed}._column_1sqby_1{width:var(--column-width);flex-shrink:0;display:flex;flex-direction:column;background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-lg);max-height:calc(100vh - var(--topbar-height) - 48px)}._header_1sqby_25{position:relative;padding:var(--space-3) var(--space-3) var(--space-2);border-bottom:1px solid var(--color-border);flex-shrink:0}._headerRow_1sqby_39{display:flex;align-items:center;gap:var(--space-2)}._name_1sqby_51{font-size:var(--text-sm);font-weight:600;color:var(--color-text-primary);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}._count_1sqby_73{font-size:var(--text-xs);color:var(--color-text-muted);background:var(--color-surface-2);border-radius:var(--radius-full);padding:1px 7px;font-weight:500}._headerActions_1sqby_91{display:flex;gap:2px}._iconBtn_1sqby_101{width:24px;height:24px;display:flex;align-items:center;justify-content:center;border-radius:var(--radius-sm);color:var(--color-text-muted);transition:background var(--transition-fast),color var(--transition-fast)}._iconBtn_1sqby_101:hover{background:var(--color-surface-2);color:var(--color-text-primary)}._headerInput_1sqby_133{width:100%;font-size:var(--text-sm);font-weight:600;color:var(--color-text-primary);background:var(--color-surface-2);border:1px solid var(--color-accent);border-radius:var(--radius-sm);padding:var(--space-1) var(--space-2)}._menu_1sqby_155{position:absolute;top:calc(100% + 4px);right:var(--space-2);background:var(--color-surface-2);border:1px solid var(--color-border);border-radius:var(--radius-md);box-shadow:var(--shadow-md);z-index:20;min-width:160px;overflow:hidden;animation:_menuIn_1sqby_1 .1s ease}@keyframes _menuIn_1sqby_1{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}._menuItem_1sqby_207{display:flex;align-items:center;gap:var(--space-2);width:100%;padding:var(--space-2) var(--space-3);font-size:var(--text-sm);color:var(--color-text-secondary);text-align:left;transition:background var(--transition-fast),color var(--transition-fast)}._menuItem_1sqby_207:hover{background:var(--color-surface-3);color:var(--color-text-primary)}._menuItem_1sqby_207._danger_1sqby_241:hover{background:color-mix(in srgb,var(--color-error) 12%,transparent);color:var(--color-error)}._body_1sqby_251{flex:1;overflow-y:auto;overflow-x:hidden;padding:var(--space-2);display:flex;flex-direction:column;gap:var(--space-2);min-height:80px;scroll-behavior:smooth;-webkit-overflow-scrolling:touch}._empty_1sqby_281{font-size:var(--text-xs);color:var(--color-text-muted);text-align:center;padding:var(--space-8) 0}._addTicketInput_1sqby_295{padding:2px}._ticketInput_1sqby_303{width:100%;padding:var(--space-2) var(--space-3);font-size:var(--text-sm);color:var(--color-text-primary);background:var(--color-surface-2);border:1px solid var(--color-accent);border-radius:var(--radius-md)}._addBtn_1sqby_323{display:flex;align-items:center;gap:var(--space-2);padding:var(--space-3);width:100%;font-size:var(--text-sm);color:var(--color-text-muted);border-top:1px solid var(--color-border);border-radius:0 0 var(--radius-lg) var(--radius-lg);transition:background var(--transition-fast),color var(--transition-fast);flex-shrink:0}._addBtn_1sqby_323:hover{background:var(--color-surface-2);color:var(--color-text-primary)}._botIcon_1sqby_361{color:var(--color-accent);margin-right:4px;animation:_pulse_1sqby_1 2s infinite ease-in-out}@keyframes _pulse_1sqby_1{0%{opacity:.6}50%{opacity:1}to{opacity:.6}}._settingsPanel_1sqby_401{position:absolute;top:calc(100% + 4px);left:var(--space-2);right:var(--space-2);background:var(--color-surface-2);border:1px solid var(--color-border);border-radius:var(--radius-md);box-shadow:var(--shadow-lg);z-index:30;padding:var(--space-3);display:flex;flex-direction:column;gap:var(--space-3);animation:_menuIn_1sqby_1 .15s ease-out}._settingsHeader_1sqby_435{display:flex;align-items:center;gap:var(--space-2);font-size:var(--text-xs);font-weight:700;text-transform:uppercase;letter-spacing:.5px;color:var(--color-text-muted);border-bottom:1px solid var(--color-border);padding-bottom:var(--space-2)}._settingGroup_1sqby_461{display:flex;flex-direction:column;gap:var(--space-1)}._settingLabel_1sqby_473{font-size:10px;font-weight:600;color:var(--color-text-muted)}._settingSelect_1sqby_485{width:100%;background:var(--color-surface-3);border:1px solid var(--color-border);border-radius:var(--radius-sm);padding:var(--space-1) var(--space-2);font-size:var(--text-xs);color:var(--color-text-primary);outline:none}._onFinishRow_1sqby_507{display:flex;align-items:center;gap:var(--space-1);color:var(--color-text-muted)}._wrapper_1i3ou_1{display:flex;flex-direction:column;height:100vh;overflow:hidden}._topbar_1i3ou_15{height:var(--topbar-height);display:flex;align-items:center;padding:0 var(--space-6);border-bottom:1px solid var(--color-border);flex-shrink:0;gap:var(--space-4)}._boardName_1i3ou_35{font-size:var(--text-md);font-weight:600;color:var(--color-text-primary);letter-spacing:-.01em}._spacer_1i3ou_49{flex:1}._configBtn_1i3ou_57{display:flex;align-items:center;justify-content:center;width:32px;height:32px;border-radius:var(--radius-md);color:var(--color-text-muted);transition:all var(--transition-normal);cursor:pointer}._configBtn_1i3ou_57:hover{background:var(--color-surface-hover);color:var(--color-text-primary)}._columnsArea_1i3ou_91{display:flex;gap:var(--space-4);padding:var(--space-4) var(--space-6);overflow-x:auto;overflow-y:hidden;flex:1;align-items:flex-start}._addColBtn_1i3ou_111{display:flex;align-items:center;gap:var(--space-2);flex-shrink:0;padding:var(--space-3) var(--space-4);font-size:var(--text-sm);font-weight:500;color:var(--color-text-muted);border:1px dashed var(--color-border);border-radius:var(--radius-lg);width:180px;transition:border-color var(--transition-normal),color var(--transition-normal),background var(--transition-normal);white-space:nowrap;align-self:flex-start}._addColBtn_1i3ou_111:hover{border-color:var(--color-accent);color:var(--color-accent);background:var(--color-accent-subtle)}._newColumn_1i3ou_159{flex-shrink:0;width:200px;align-self:flex-start}._newColumnInput_1i3ou_171{width:100%;padding:var(--space-3) var(--space-4);font-size:var(--text-sm);font-weight:500;color:var(--color-text-primary);background:var(--color-surface);border:1px solid var(--color-accent);border-radius:var(--radius-lg)}._emptyView_1i3ou_195{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--space-4);color:var(--color-text-muted)}._emptyTitle_1i3ou_215{font-size:var(--text-lg);font-weight:600;color:var(--color-text-secondary)}._emptySubtitle_1i3ou_227{font-size:var(--text-sm);color:var(--color-text-muted);max-width:280px;text-align:center;line-height:var(--line-height-normal)}._loadingColumns_1i3ou_245{display:flex;gap:var(--space-4)}._skeleton_1i3ou_255{width:var(--column-width);height:300px;background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-lg);animation:_pulse_1i3ou_1 1.5s ease-in-out infinite}@keyframes _pulse_1i3ou_1{0%,to{opacity:1}50%{opacity:.4}}._switcher_vhltw_1{display:flex;align-items:center;gap:var(--space-1);padding:var(--space-1) var(--space-3);border-radius:var(--radius-md);font-size:var(--text-xs);font-weight:500;color:var(--color-text-muted);border:1px solid var(--color-border);transition:background var(--transition-fast),color var(--transition-fast)}._switcher_vhltw_1:hover{background:var(--color-surface-2);color:var(--color-text-primary)}._shell_8hnwn_1{display:flex;height:100vh;width:100vw;overflow:hidden}._main_8hnwn_15{flex:1;display:flex;flex-direction:column;min-width:0;overflow:hidden}._topBar_8hnwn_31{height:var(--topbar-height);display:flex;align-items:center;justify-content:flex-end;padding:0 var(--space-4);border-bottom:1px solid var(--color-border);flex-shrink:0}._spacer_8hnwn_51{flex:1}._content_8hnwn_59{flex:1;overflow:hidden;display:flex;flex-direction:column}