opencastle 0.32.3 → 0.32.5
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/dist/cli/bootstrap.js +1 -1
- package/dist/cli/bootstrap.js.map +1 -1
- package/dist/cli/bootstrap.test.js +16 -0
- package/dist/cli/bootstrap.test.js.map +1 -1
- package/dist/cli/convoy/engine.d.ts +1 -0
- package/dist/cli/convoy/engine.d.ts.map +1 -1
- package/dist/cli/convoy/engine.js +17 -2
- package/dist/cli/convoy/engine.js.map +1 -1
- package/dist/cli/convoy/pipeline.d.ts +1 -0
- package/dist/cli/convoy/pipeline.d.ts.map +1 -1
- package/dist/cli/convoy/pricing.d.ts +3 -0
- package/dist/cli/convoy/pricing.d.ts.map +1 -0
- package/dist/cli/convoy/pricing.js +52 -0
- package/dist/cli/convoy/pricing.js.map +1 -0
- package/dist/cli/convoy/pricing.test.d.ts +2 -0
- package/dist/cli/convoy/pricing.test.d.ts.map +1 -0
- package/dist/cli/convoy/pricing.test.js +63 -0
- package/dist/cli/convoy/pricing.test.js.map +1 -0
- package/dist/cli/convoy/store.d.ts +1 -1
- package/dist/cli/convoy/store.d.ts.map +1 -1
- package/dist/cli/convoy/store.js +1 -1
- package/dist/cli/convoy/store.js.map +1 -1
- package/dist/cli/init.test.js +38 -0
- package/dist/cli/init.test.js.map +1 -1
- package/dist/cli/run/adapters/opencode.js +1 -1
- package/dist/cli/run/adapters/opencode.js.map +1 -1
- package/dist/cli/run.d.ts.map +1 -1
- package/dist/cli/run.js +10 -2
- package/dist/cli/run.js.map +1 -1
- package/dist/cli/stack-config-update.test.js +18 -0
- package/dist/cli/stack-config-update.test.js.map +1 -1
- package/dist/cli/stack-config.d.ts.map +1 -1
- package/dist/cli/stack-config.js +1 -0
- package/dist/cli/stack-config.js.map +1 -1
- package/dist/cli/types.d.ts +1 -1
- package/dist/cli/types.d.ts.map +1 -1
- package/dist/orchestrator/plugins/index.d.ts.map +1 -1
- package/dist/orchestrator/plugins/index.js +4 -0
- package/dist/orchestrator/plugins/index.js.map +1 -1
- package/dist/orchestrator/plugins/notion/config.d.ts +3 -0
- package/dist/orchestrator/plugins/notion/config.d.ts.map +1 -0
- package/dist/orchestrator/plugins/notion/config.js +46 -0
- package/dist/orchestrator/plugins/notion/config.js.map +1 -0
- package/dist/orchestrator/plugins/trello/config.d.ts +3 -0
- package/dist/orchestrator/plugins/trello/config.d.ts.map +1 -0
- package/dist/orchestrator/plugins/trello/config.js +43 -0
- package/dist/orchestrator/plugins/trello/config.js.map +1 -0
- package/dist/orchestrator/plugins/types.d.ts +1 -1
- package/dist/orchestrator/plugins/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/cli/bootstrap.test.ts +21 -0
- package/src/cli/bootstrap.ts +1 -1
- package/src/cli/convoy/engine.ts +18 -3
- package/src/cli/convoy/pipeline.ts +1 -1
- package/src/cli/convoy/pricing.test.ts +78 -0
- package/src/cli/convoy/pricing.ts +62 -0
- package/src/cli/convoy/store.ts +3 -3
- package/src/cli/init.test.ts +46 -0
- package/src/cli/run/adapters/opencode.ts +1 -1
- package/src/cli/run.ts +10 -2
- package/src/cli/stack-config-update.test.ts +20 -0
- package/src/cli/stack-config.ts +1 -0
- package/src/cli/types.ts +1 -1
- package/src/dashboard/dist/_astro/index.wyN9vmjZ.css +1 -0
- package/src/dashboard/dist/index.html +4 -4
- package/src/dashboard/node_modules/.vite/deps/_metadata.json +6 -6
- package/src/dashboard/src/pages/index.astro +5 -3
- package/src/dashboard/src/styles/dashboard.css +6 -0
- package/src/orchestrator/customizations/agents/skill-matrix.json +8 -4
- package/src/orchestrator/customizations/agents/skill-matrix.md +20 -0
- package/src/orchestrator/plugins/index.ts +4 -0
- package/src/orchestrator/plugins/notion/SKILL.md +205 -0
- package/src/orchestrator/plugins/notion/config.ts +47 -0
- package/src/orchestrator/plugins/trello/SKILL.md +151 -0
- package/src/orchestrator/plugins/trello/config.ts +44 -0
- package/src/orchestrator/plugins/types.ts +1 -1
- package/src/dashboard/dist/_astro/index.D6quLrA6.css +0 -1
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: notion-knowledge-management
|
|
3
|
+
description: "Notion workspace patterns for knowledge capture, research documentation, architectural decisions, and spec management. Use when capturing research findings, writing specs, documenting decisions, or managing a team knowledge base."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<!-- ⚠️ This file is managed by OpenCastle. Edits will be overwritten on update. Customize in the .opencastle/ directory instead. -->
|
|
7
|
+
|
|
8
|
+
# Knowledge Management with Notion
|
|
9
|
+
|
|
10
|
+
Conventions for working with the team's Notion workspace via the official Notion MCP server. Covers page and database operations, research capture, decision documentation, and permission-aware workflows.
|
|
11
|
+
|
|
12
|
+
## MCP Server
|
|
13
|
+
|
|
14
|
+
| Field | Value |
|
|
15
|
+
|-------|-------|
|
|
16
|
+
| **Endpoint** | `https://mcp.notion.com/mcp` (HTTP, remote) |
|
|
17
|
+
| **Auth** | OAuth — users authenticate via Notion account when the MCP connection is established |
|
|
18
|
+
| **Type** | HTTP MCP (no local process to spawn) |
|
|
19
|
+
|
|
20
|
+
### Authentication
|
|
21
|
+
|
|
22
|
+
The Notion MCP server uses OAuth. When the MCP connection is first opened in your IDE, you will be prompted to authorise access to your Notion workspace. No API key or token is required in `.env`.
|
|
23
|
+
|
|
24
|
+
> **Scope:** The integration is granted access only to pages and databases explicitly shared with it. Before using MCP tools, ensure the relevant pages/databases are shared with the OpenCastle integration in Notion.
|
|
25
|
+
|
|
26
|
+
## Available MCP Tools
|
|
27
|
+
|
|
28
|
+
| Tool | Description |
|
|
29
|
+
|------|-------------|
|
|
30
|
+
| `search` | Search pages and databases across the workspace by keyword |
|
|
31
|
+
| `create_page` | Create a new page (standalone or inside a parent page/database) |
|
|
32
|
+
| `update_page` | Update page properties or archive a page |
|
|
33
|
+
| `append_block_children` | Append content blocks (paragraphs, headings, bullets, code) to a page |
|
|
34
|
+
| `query_database` | Query a Notion database with filters and sorts |
|
|
35
|
+
|
|
36
|
+
## Working with Pages and Databases
|
|
37
|
+
|
|
38
|
+
### Page Hierarchy Hygiene
|
|
39
|
+
|
|
40
|
+
Keep the workspace navigable by placing new pages in the right location:
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
Workspace root
|
|
44
|
+
├── Engineering/
|
|
45
|
+
│ ├── Architecture Decisions/ ← ADRs go here
|
|
46
|
+
│ ├── Specs/ ← Feature specs go here
|
|
47
|
+
│ └── Research/ ← Research notes go here
|
|
48
|
+
├── Team/
|
|
49
|
+
│ ├── Meeting Notes/ ← Meeting intelligence
|
|
50
|
+
│ └── Decisions Log/ ← Key team decisions
|
|
51
|
+
└── Project: <name>/ ← Per-project space
|
|
52
|
+
├── Roadmap
|
|
53
|
+
├── Known Issues
|
|
54
|
+
└── Release Notes/
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
- Always use `search` first to check if a page already exists before creating a new one.
|
|
58
|
+
- Create pages as children of the appropriate parent — never at the workspace root unless explicitly requested.
|
|
59
|
+
- Use databases (not flat pages) for collections that need filtering, sorting, or status tracking (e.g., ADRs, specs).
|
|
60
|
+
|
|
61
|
+
### Page Creation Pattern
|
|
62
|
+
|
|
63
|
+
When creating a page:
|
|
64
|
+
|
|
65
|
+
1. `search` for an existing page with a similar title to avoid duplicates
|
|
66
|
+
2. `create_page` with `parent` set to the correct parent page or database
|
|
67
|
+
3. `append_block_children` to add structured content
|
|
68
|
+
|
|
69
|
+
```json
|
|
70
|
+
// Example: Create a spec page
|
|
71
|
+
{
|
|
72
|
+
"parent": { "page_id": "<Engineering/Specs parent ID>" },
|
|
73
|
+
"properties": {
|
|
74
|
+
"title": [{ "type": "text", "text": { "content": "[Spec] Price Range Filter" } }]
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Capturing Research and Decisions
|
|
80
|
+
|
|
81
|
+
### Research Note Structure
|
|
82
|
+
|
|
83
|
+
Use this outline when capturing research findings:
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
# [Research] <Topic>
|
|
87
|
+
|
|
88
|
+
## Summary
|
|
89
|
+
One-paragraph overview of findings.
|
|
90
|
+
|
|
91
|
+
## Sources
|
|
92
|
+
- <URL or reference> — <why it is relevant>
|
|
93
|
+
|
|
94
|
+
## Key Findings
|
|
95
|
+
- Finding 1
|
|
96
|
+
- Finding 2
|
|
97
|
+
|
|
98
|
+
## Implications
|
|
99
|
+
How these findings affect the current task or architecture.
|
|
100
|
+
|
|
101
|
+
## Open Questions
|
|
102
|
+
- Question 1
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Architectural Decision Record (ADR) Structure
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
# ADR-NNN: <Short title>
|
|
109
|
+
|
|
110
|
+
**Status:** Proposed | Accepted | Deprecated | Superseded
|
|
111
|
+
**Date:** YYYY-MM-DD
|
|
112
|
+
|
|
113
|
+
## Context
|
|
114
|
+
What is the problem or decision to be made?
|
|
115
|
+
|
|
116
|
+
## Decision
|
|
117
|
+
What was decided?
|
|
118
|
+
|
|
119
|
+
## Consequences
|
|
120
|
+
What tradeoffs or follow-on work does this create?
|
|
121
|
+
|
|
122
|
+
## Alternatives Considered
|
|
123
|
+
- Option A — why rejected
|
|
124
|
+
- Option B — why rejected
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Spec-to-Implementation Link
|
|
128
|
+
|
|
129
|
+
When a spec page drives implementation, add an **Implementation** section at the bottom:
|
|
130
|
+
|
|
131
|
+
```
|
|
132
|
+
## Implementation
|
|
133
|
+
- **Branch:** `feat/price-range-filter`
|
|
134
|
+
- **PR:** <link>
|
|
135
|
+
- **Tracker:** <Linear/Jira/Trello card link>
|
|
136
|
+
- **Status:** In Progress / Done
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
This closes the loop between the knowledge base and the task tracker.
|
|
140
|
+
|
|
141
|
+
## Meeting Intelligence
|
|
142
|
+
|
|
143
|
+
When capturing meeting notes, use the following structure:
|
|
144
|
+
|
|
145
|
+
```
|
|
146
|
+
# Meeting: <Title> — YYYY-MM-DD
|
|
147
|
+
|
|
148
|
+
**Attendees:** Name1, Name2
|
|
149
|
+
**Type:** Planning / Review / Retrospective / Decision
|
|
150
|
+
|
|
151
|
+
## Summary
|
|
152
|
+
|
|
153
|
+
## Decisions Made
|
|
154
|
+
- Decision 1 (owner: Name)
|
|
155
|
+
|
|
156
|
+
## Action Items
|
|
157
|
+
- [ ] Action item (owner: Name, due: YYYY-MM-DD)
|
|
158
|
+
|
|
159
|
+
## Context / Discussion Notes
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
After the meeting, add action items to the task tracker.
|
|
163
|
+
|
|
164
|
+
## Permission-Aware Workflows
|
|
165
|
+
|
|
166
|
+
Notion access is page-scoped. Follow these rules to avoid permission errors:
|
|
167
|
+
|
|
168
|
+
1. **Before writing** — run `search` to verify you can see the target page. If it does not appear, the integration has not been granted access.
|
|
169
|
+
2. **Sharing** — ask the user to share the relevant page or database with the OpenCastle integration before running MCP tools against it.
|
|
170
|
+
3. **Databases vs pages** — use `query_database` only on pages that are databases. Use `append_block_children` to add content to regular pages.
|
|
171
|
+
4. **Archived pages** — `search` does not return archived pages. If a page is missing, it may have been archived. Ask the user to restore it.
|
|
172
|
+
|
|
173
|
+
## Database Query Patterns
|
|
174
|
+
|
|
175
|
+
### Filter by Status
|
|
176
|
+
|
|
177
|
+
```json
|
|
178
|
+
{
|
|
179
|
+
"filter": {
|
|
180
|
+
"property": "Status",
|
|
181
|
+
"select": { "equals": "In Progress" }
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Sort by Last Edited
|
|
187
|
+
|
|
188
|
+
```json
|
|
189
|
+
{
|
|
190
|
+
"sorts": [
|
|
191
|
+
{ "timestamp": "last_edited_time", "direction": "descending" }
|
|
192
|
+
]
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Agent Usage Guidelines
|
|
197
|
+
|
|
198
|
+
| Agent | Primary Use |
|
|
199
|
+
|-------|-------------|
|
|
200
|
+
| **Team Lead** | Create spec pages, capture decisions, link tracker issues to specs |
|
|
201
|
+
| **Researcher** | Capture research notes, query databases for prior art, document findings |
|
|
202
|
+
| **Documentation Writer** | Write and update documentation pages, maintain page hierarchy |
|
|
203
|
+
| **Architect** | Write ADRs, create technical specs, link specs to implementation PRs |
|
|
204
|
+
|
|
205
|
+
**Never** delete pages via MCP — use `update_page` with `archived: true` if a page needs to be removed, and confirm with the user first.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { PluginConfig } from '../types.js';
|
|
2
|
+
|
|
3
|
+
export const config: PluginConfig = {
|
|
4
|
+
id: 'notion',
|
|
5
|
+
name: 'Notion',
|
|
6
|
+
category: 'team',
|
|
7
|
+
subCategory: 'knowledge-management',
|
|
8
|
+
label: 'Notion',
|
|
9
|
+
hint: 'Workspace knowledge base and documentation hub',
|
|
10
|
+
skillName: 'notion-knowledge-management',
|
|
11
|
+
mcpServerKey: 'Notion',
|
|
12
|
+
mcpConfig: {
|
|
13
|
+
type: 'http',
|
|
14
|
+
url: 'https://mcp.notion.com/mcp',
|
|
15
|
+
},
|
|
16
|
+
authType: 'oauth',
|
|
17
|
+
envVars: [],
|
|
18
|
+
agentToolMap: {
|
|
19
|
+
'team-lead': [
|
|
20
|
+
'Notion/search',
|
|
21
|
+
'Notion/create_page',
|
|
22
|
+
'Notion/update_page',
|
|
23
|
+
'Notion/query_database',
|
|
24
|
+
'Notion/append_block_children',
|
|
25
|
+
],
|
|
26
|
+
'researcher': [
|
|
27
|
+
'Notion/search',
|
|
28
|
+
'Notion/create_page',
|
|
29
|
+
'Notion/append_block_children',
|
|
30
|
+
'Notion/query_database',
|
|
31
|
+
],
|
|
32
|
+
'documentation-writer': [
|
|
33
|
+
'Notion/search',
|
|
34
|
+
'Notion/create_page',
|
|
35
|
+
'Notion/update_page',
|
|
36
|
+
'Notion/append_block_children',
|
|
37
|
+
],
|
|
38
|
+
'architect': [
|
|
39
|
+
'Notion/search',
|
|
40
|
+
'Notion/create_page',
|
|
41
|
+
'Notion/update_page',
|
|
42
|
+
'Notion/query_database',
|
|
43
|
+
],
|
|
44
|
+
},
|
|
45
|
+
docsUrl: 'https://www.opencastle.dev/docs/plugins#notion',
|
|
46
|
+
officialDocs: 'https://developers.notion.com/docs/mcp',
|
|
47
|
+
};
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: trello-task-management
|
|
3
|
+
description: "Trello board conventions for tracking feature work — board/list/card workflow, checklist-driven task breakdown, due dates, and when to use comments vs checklist items. Use when decomposing features into cards or resuming interrupted sessions."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<!-- ⚠️ This file is managed by OpenCastle. Edits will be overwritten on update. Customize in the .opencastle/ directory instead. -->
|
|
7
|
+
|
|
8
|
+
# Task Management with Trello
|
|
9
|
+
|
|
10
|
+
Conventions for tracking feature work on Trello boards via MCP tools. For project-specific board IDs and list IDs, see [tracker-config.md](../../.opencastle/project/tracker-config.md).
|
|
11
|
+
|
|
12
|
+
## MCP Server
|
|
13
|
+
|
|
14
|
+
| Field | Value |
|
|
15
|
+
|-------|-------|
|
|
16
|
+
| **Package** | [`@delorenj/mcp-server-trello`](https://www.npmjs.com/package/@delorenj/mcp-server-trello) |
|
|
17
|
+
| **Type** | stdio (spawned via `npx -y @delorenj/mcp-server-trello`) |
|
|
18
|
+
| **Auth** | API key + token via `TRELLO_API_KEY` and `TRELLO_TOKEN` env vars |
|
|
19
|
+
|
|
20
|
+
### Authentication
|
|
21
|
+
|
|
22
|
+
1. Get your API key at [trello.com/app-key](https://trello.com/app-key) → **API Key**
|
|
23
|
+
2. On the same page, click **"Generate a Token"** to get your token
|
|
24
|
+
3. Add both to your `.env` file:
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
TRELLO_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
28
|
+
TRELLO_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Available MCP Tools
|
|
32
|
+
|
|
33
|
+
| Tool | Description |
|
|
34
|
+
|------|-------------|
|
|
35
|
+
| `get_boards` | List all boards accessible to the authenticated user |
|
|
36
|
+
| `get_lists` | Get all lists on a board (by board ID) |
|
|
37
|
+
| `get_cards_by_list_id` | Get all cards in a specific list |
|
|
38
|
+
| `get_card_details` | Get full details of a single card |
|
|
39
|
+
| `create_card` | Create a new card in a list |
|
|
40
|
+
| `update_card` | Update card fields (name, description, due date, list) |
|
|
41
|
+
| `add_checklist_to_card` | Add a checklist with items to a card |
|
|
42
|
+
| `add_comment_to_card` | Post a comment on a card |
|
|
43
|
+
|
|
44
|
+
## Discovered Issues (Bug Tickets)
|
|
45
|
+
|
|
46
|
+
When an agent encounters a pre-existing bug or issue unrelated to the current task, it must be tracked:
|
|
47
|
+
|
|
48
|
+
1. **Check** existing cards on the board to see if it is already tracked
|
|
49
|
+
2. **If tracked** — skip it, continue with current work
|
|
50
|
+
3. **If NOT tracked:**
|
|
51
|
+
- **Unfixable limitation** — add to known issues with severity, evidence, and root cause
|
|
52
|
+
- **Fixable bug** — create a Trello card:
|
|
53
|
+
- **Name:** `[Bug] Short description of the symptom`
|
|
54
|
+
- **List:** `Backlog` (or the equivalent list in your project)
|
|
55
|
+
- **Description:** Include symptoms, reproduction steps, affected files, and any error messages
|
|
56
|
+
- **Due date:** Set only if it is blocking current work
|
|
57
|
+
|
|
58
|
+
## Card Naming
|
|
59
|
+
|
|
60
|
+
Use `[Area] Short description` format:
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
[Schema] Add priceRange field to place type
|
|
64
|
+
[DB] Add price_range column and migration
|
|
65
|
+
[UI] Build PriceRangeFilter component
|
|
66
|
+
[API] Add price filter endpoint
|
|
67
|
+
[Test] Unit tests for price filter
|
|
68
|
+
[Docs] Update data model documentation
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**Area prefixes:** `[Schema]`, `[DB]`, `[Query]`, `[UI]`, `[Page]`, `[API]`, `[Auth]`, `[Test]`, `[Docs]`, `[Deploy]`, `[Data]`, `[Perf]`, `[Security]`, `[Bug]`
|
|
72
|
+
|
|
73
|
+
## Board and List Workflow
|
|
74
|
+
|
|
75
|
+
### Typical List Structure
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
Backlog → To Do → In Progress → In Review → Done
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
- **Backlog** — Captured but not yet planned
|
|
82
|
+
- **To Do** — Planned and ready to start
|
|
83
|
+
- **In Progress** — Actively being worked on
|
|
84
|
+
- **In Review** — PR open, awaiting review or merge
|
|
85
|
+
- **Done** — Completed and verified
|
|
86
|
+
|
|
87
|
+
### Agent-Driven Card Transitions (via MCP)
|
|
88
|
+
|
|
89
|
+
| From | To | When |
|
|
90
|
+
|------|----|------|
|
|
91
|
+
| Backlog / To Do | In Progress | Agent starts working on the card |
|
|
92
|
+
| In Progress | Done | Non-PR task is verified (docs, config) |
|
|
93
|
+
| Any | Backlog | Task is deferred |
|
|
94
|
+
|
|
95
|
+
## Checklist-Driven Task Breakdown
|
|
96
|
+
|
|
97
|
+
Use checklists for **subtask decomposition within a single card**. This keeps related work together without cluttering the board with micro-cards.
|
|
98
|
+
|
|
99
|
+
### When to Use a Checklist vs a Separate Card
|
|
100
|
+
|
|
101
|
+
| Use a **checklist item** when… | Use a **separate card** when… |
|
|
102
|
+
|-------------------------------|------------------------------|
|
|
103
|
+
| Steps are sequential and tightly coupled | Work can be assigned independently |
|
|
104
|
+
| Total effort fits in one session | Each step spans multiple sessions |
|
|
105
|
+
| Steps share the same assignee | Steps need different labels/due dates |
|
|
106
|
+
| Internal implementation details | Distinct deliverables that need review |
|
|
107
|
+
|
|
108
|
+
### Checklist Pattern for Feature Decomposition
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
Card: [Feature] Add price range filter
|
|
112
|
+
Checklist: Implementation Steps
|
|
113
|
+
☐ Add priceRange field to schema
|
|
114
|
+
☐ Create DB migration
|
|
115
|
+
☐ Update GROQ/API query
|
|
116
|
+
☐ Build UI component
|
|
117
|
+
☐ Wire into page
|
|
118
|
+
☐ Write unit tests
|
|
119
|
+
☐ Update documentation
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Due and Start Dates
|
|
123
|
+
|
|
124
|
+
Trello cards support both a **start date** and a **due date**.
|
|
125
|
+
|
|
126
|
+
- **Due date** — The deadline for the card to move to Done. Set for tasks on the critical path.
|
|
127
|
+
- **Start date** — When work is expected to begin. Useful for pipeline planning.
|
|
128
|
+
- **Due time** — Be explicit with time only for time-sensitive deliverables (e.g., scheduled releases).
|
|
129
|
+
- **Format:** Trello API uses ISO 8601: `2026-03-20T14:00:00.000Z`
|
|
130
|
+
|
|
131
|
+
## Comments vs Checklist Items
|
|
132
|
+
|
|
133
|
+
| Use **comments** for… | Use **checklist items** for… |
|
|
134
|
+
|-----------------------|------------------------------|
|
|
135
|
+
| Progress updates visible to the team | Actionable steps with completion state |
|
|
136
|
+
| Blocking issues or decisions | Pre-defined subtask decomposition |
|
|
137
|
+
| Links to PRs, builds, external docs | Typed acceptance criteria |
|
|
138
|
+
| Questions or async approvals | Implementation sub-steps |
|
|
139
|
+
| Post-implementation notes | QA verification steps |
|
|
140
|
+
|
|
141
|
+
**Rule of thumb:** If it needs to be *checked off*, it's a checklist item. If it needs to be *read*, it's a comment.
|
|
142
|
+
|
|
143
|
+
## Session Continuity
|
|
144
|
+
|
|
145
|
+
At the start of each work session:
|
|
146
|
+
|
|
147
|
+
1. `get_boards` — confirm the right board is active
|
|
148
|
+
2. `get_lists` — identify current list structure
|
|
149
|
+
3. `get_cards_by_list_id` for **In Progress** — find cards already in flight
|
|
150
|
+
4. Resume work on the relevant card, updating the checklist as steps complete
|
|
151
|
+
5. Move the card to the next list when the current phase is done
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { PluginConfig } from '../types.js';
|
|
2
|
+
|
|
3
|
+
export const config: PluginConfig = {
|
|
4
|
+
id: 'trello',
|
|
5
|
+
name: 'Trello',
|
|
6
|
+
category: 'team',
|
|
7
|
+
subCategory: 'task-management',
|
|
8
|
+
label: 'Trello',
|
|
9
|
+
hint: 'Visual board task management via MCP',
|
|
10
|
+
skillName: 'trello-task-management',
|
|
11
|
+
mcpServerKey: 'Trello',
|
|
12
|
+
mcpConfig: {
|
|
13
|
+
type: 'stdio',
|
|
14
|
+
command: 'npx',
|
|
15
|
+
args: ['-y', '@delorenj/mcp-server-trello'],
|
|
16
|
+
envFile: '${workspaceFolder}/.env',
|
|
17
|
+
},
|
|
18
|
+
authType: 'env-token',
|
|
19
|
+
envVars: [
|
|
20
|
+
{
|
|
21
|
+
name: 'TRELLO_API_KEY',
|
|
22
|
+
hint: 'Create at trello.com/app-key -> API Key',
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
name: 'TRELLO_TOKEN',
|
|
26
|
+
hint: 'Generate at trello.com/app-key -> Token (click "Generate a Token")',
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
agentToolMap: {
|
|
30
|
+
'team-lead': [
|
|
31
|
+
'Trello/get_boards',
|
|
32
|
+
'Trello/get_lists',
|
|
33
|
+
'Trello/get_cards_by_list_id',
|
|
34
|
+
'Trello/get_card_details',
|
|
35
|
+
'Trello/create_card',
|
|
36
|
+
'Trello/update_card',
|
|
37
|
+
'Trello/add_checklist_to_card',
|
|
38
|
+
'Trello/add_comment_to_card',
|
|
39
|
+
],
|
|
40
|
+
},
|
|
41
|
+
docsUrl: 'https://www.opencastle.dev/docs/plugins#trello',
|
|
42
|
+
officialDocs: 'https://developer.atlassian.com/cloud/trello/',
|
|
43
|
+
mcpPackage: '@delorenj/mcp-server-trello',
|
|
44
|
+
};
|
|
@@ -13,7 +13,7 @@ export interface PluginConfig {
|
|
|
13
13
|
category: 'tech' | 'team';
|
|
14
14
|
|
|
15
15
|
/** Sub-category for grouping */
|
|
16
|
-
subCategory: 'cms' | 'database' | 'deployment' | 'framework' | 'codebase-tool' | 'task-management' | 'notifications' | 'testing' | 'e2e-testing' | 'design' | 'email';
|
|
16
|
+
subCategory: 'cms' | 'database' | 'deployment' | 'framework' | 'codebase-tool' | 'task-management' | 'knowledge-management' | 'notifications' | 'testing' | 'e2e-testing' | 'design' | 'email';
|
|
17
17
|
|
|
18
18
|
/** Label shown in the `npx opencastle init` multiselect */
|
|
19
19
|
label: string;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
:root{--bg-primary: #0a0a0f;--bg-secondary: #111118;--bg-tertiary: #1a1a24;--bg-card: rgba(255, 255, 255, .03);--bg-card-hover: rgba(255, 255, 255, .06);--text-primary: #f0f0f5;--text-secondary: #8a8a9a;--text-tertiary: #7a7a8e;--text-accent: #a78bfa;--gradient-accent: linear-gradient(135deg, #a78bfa 0%, #6366f1 50%, #3b82f6 100%);--gradient-glow: radial-gradient(ellipse 800px 400px at 50% 0%, rgba(99, 102, 241, .12) 0%, transparent 70%);--border-color: rgba(255, 255, 255, .06);--border-accent: rgba(167, 139, 250, .3);--color-success: #22c55e;--color-partial: #f59e0b;--color-failed: #ef4444;--color-redirected: #64748b;--color-premium: #f59e0b;--color-standard: #a78bfa;--color-utility: #3b82f6;--color-economy: #64748b;--accent-blue: #3b82f6;--accent-purple: #a78bfa;--accent-indigo: #6366f1;--max-width: 1280px;--transition-fast: .15s cubic-bezier(.4, 0, .2, 1);--transition-base: .3s cubic-bezier(.4, 0, .2, 1)}*,*:before,*:after{box-sizing:border-box;margin:0;padding:0}html{font-size:16px;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Inter,Roboto,Helvetica,Arial,sans-serif;background-color:var(--bg-primary);color:var(--text-primary);line-height:1.6;overflow-x:hidden;min-height:100vh}.dash-header{position:sticky;top:0;z-index:50;background:#0a0a0fd9;backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);border-bottom:1px solid var(--border-color)}.dash-header__inner{max-width:var(--max-width);margin:0 auto;padding:0 24px;height:56px;display:flex;align-items:center;justify-content:space-between}.dash-header__brand{display:flex;align-items:center;gap:10px}.dash-header__icon{width:32px;height:32px;border-radius:8px;object-fit:contain}.dash-header__title{font-size:1rem;font-weight:600;color:var(--text-primary)}.dash-layout{display:flex;max-width:var(--max-width);margin:0 auto;position:relative}.dash-sidebar{position:sticky;top:56px;height:calc(100vh - 56px);width:180px;flex-shrink:0;padding:24px 0 24px 24px;overflow-y:auto;display:none}@media(min-width:1024px){.dash-sidebar{display:block}}.dash-sidebar__list{list-style:none;display:flex;flex-direction:column;gap:2px}.dash-sidebar__link{display:block;padding:8px 16px;font-size:.8125rem;font-weight:500;color:var(--text-tertiary);text-decoration:none;border-radius:8px;transition:color var(--transition-fast),background var(--transition-fast)}.dash-sidebar__link:hover{color:var(--text-secondary);background:#ffffff0a}.dash-sidebar__link--active{color:var(--text-accent);background:#a78bfa14;font-weight:600}.dash-main{flex:1;min-width:0;max-width:var(--max-width);margin:0 auto;padding:24px;display:flex;flex-direction:column;gap:20px;position:relative}.dash-main:before{content:"";position:fixed;top:0;left:50%;transform:translate(-50%);width:100%;height:600px;background:var(--gradient-glow);pointer-events:none;z-index:0}.dash-main>*{position:relative;z-index:1}[data-nav-section]{scroll-margin-top:72px}.kpi-row{display:grid;grid-template-columns:1fr;gap:12px}@media(min-width:480px){.kpi-row{grid-template-columns:repeat(2,1fr)}}@media(min-width:960px){.kpi-row{grid-template-columns:repeat(auto-fit,minmax(160px,1fr))}}.kpi-card{background:var(--bg-secondary);border:1px solid var(--border-color);border-radius:12px;padding:20px 24px;display:flex;flex-direction:column;gap:4px;transition:border-color var(--transition-fast)}.kpi-card:hover{border-color:#ffffff1a}.kpi-card__label{font-size:.75rem;font-weight:500;color:var(--text-tertiary);text-transform:uppercase;letter-spacing:.05em}.kpi-card__value{font-size:2rem;font-weight:700;color:var(--text-primary);line-height:1.2;letter-spacing:-.02em}.kpi-card__sub{font-size:.75rem;color:var(--text-secondary);display:flex;align-items:center;gap:4px}.kpi-trend{font-weight:600}.kpi-trend--up{color:var(--color-success)}.kpi-trend--down{color:var(--color-failed)}.kpi-trend--neutral{color:var(--text-tertiary)}.chart-card{background:var(--bg-secondary);border:1px solid var(--border-color);border-radius:12px;transition:border-color var(--transition-fast)}.chart-card:hover{border-color:#ffffff1a}.chart-card__header{padding:20px 24px 8px;display:flex;flex-wrap:wrap;align-items:baseline;gap:6px}.chart-card__title{font-size:.9375rem;font-weight:600;color:var(--text-primary)}.chart-card__desc{font-size:.75rem;color:var(--text-tertiary);margin-top:2px;width:100%}.chart-card__body{padding:16px 24px 24px;min-height:120px}.chart-card__body--table{padding:0}.charts-row{display:grid;grid-template-columns:1fr;gap:20px}@media(min-width:768px){.charts-row{grid-template-columns:repeat(2,1fr)}}.bar-row{display:flex;align-items:center;gap:12px;padding:6px 0}.bar-row+.bar-row{border-top:1px solid rgba(255,255,255,.03)}.bar-label{font-size:.8125rem;color:var(--text-secondary);width:130px;flex-shrink:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.bar-track{flex:1;height:24px;background:var(--bg-tertiary);border-radius:6px;display:flex;overflow:hidden}.bar-segment{height:100%;transition:width .8s cubic-bezier(.4,0,.2,1);min-width:0}.bar--success{background:var(--color-success)}.bar--partial{background:var(--color-partial)}.bar--failed{background:var(--color-failed)}.bar--premium{background:var(--color-premium)}.bar--standard{background:var(--color-standard)}.bar--utility{background:var(--color-utility)}.bar--economy{background:var(--color-economy)}.bar--accent{background:var(--accent-blue)}.bar-value{font-size:.8125rem;font-weight:600;color:var(--text-primary);width:36px;text-align:right;flex-shrink:0;font-variant-numeric:tabular-nums}.donut-container{display:flex;align-items:center;justify-content:center;gap:32px;flex-wrap:wrap}.donut-wrap{position:relative;width:180px;height:180px;flex-shrink:0}.donut-svg{width:100%;height:100%}.donut-svg circle{transition:stroke-dasharray .8s cubic-bezier(.4,0,.2,1),stroke-dashoffset .8s cubic-bezier(.4,0,.2,1)}.donut-center{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);text-align:center}.donut-total{display:block;font-size:1.5rem;font-weight:700;color:var(--text-primary);line-height:1}.donut-total-label{display:block;font-size:.6875rem;color:var(--text-tertiary);text-transform:uppercase;letter-spacing:.08em;margin-top:2px}.donut-legend{display:flex;flex-direction:column;gap:10px}.legend-item{display:flex;align-items:center;gap:8px;font-size:.8125rem}.legend-dot{width:10px;height:10px;border-radius:3px;flex-shrink:0}.legend-name{color:var(--text-secondary);text-transform:capitalize}.legend-count{color:var(--text-tertiary);font-variant-numeric:tabular-nums;margin-left:auto}.timeline-svg{width:100%;height:auto;display:block}.timeline-svg text{font-family:inherit}.timeline-legend{display:flex;gap:16px;justify-content:center;margin-top:12px}.timeline-legend__item{display:flex;align-items:center;gap:6px;font-size:.75rem;color:var(--text-tertiary)}.timeline-legend__dot{width:8px;height:8px;border-radius:2px}.pipeline{display:flex;align-items:stretch;gap:0;overflow-x:auto;padding:8px 0}.pipeline-stage{flex:1;min-width:140px;display:flex;flex-direction:column;align-items:center;gap:8px;padding:16px 12px;position:relative}.pipeline-stage:not(:last-child):after{content:"";position:absolute;right:-1px;top:50%;transform:translateY(-50%);width:2px;height:40%;background:var(--border-color)}.pipeline-stage__icon{width:40px;height:40px;border-radius:10px;display:flex;align-items:center;justify-content:center;font-size:1rem}.pipeline-stage__icon--pending{background:#64748b26;color:#94a3b8;border:1px solid rgba(100,116,139,.2)}.pipeline-stage__icon--active{background:#3b82f626;color:#60a5fa;border:1px solid rgba(59,130,246,.3);animation:pulse-glow 2s ease-in-out infinite}.pipeline-stage__icon--review{background:#f59e0b26;color:#fbbf24;border:1px solid rgba(245,158,11,.3)}.pipeline-stage__icon--done{background:#22c55e26;color:#4ade80;border:1px solid rgba(34,197,94,.3)}@keyframes pulse-glow{0%,to{box-shadow:0 0 #3b82f633}50%{box-shadow:0 0 12px 4px #3b82f626}}.pipeline-stage__count{font-size:1.5rem;font-weight:700;color:var(--text-primary);line-height:1}.pipeline-stage__label{font-size:.75rem;color:var(--text-tertiary);text-transform:uppercase;letter-spacing:.04em;font-weight:500}.pipeline-arrow{display:flex;align-items:center;color:var(--text-tertiary);font-size:1.25rem;padding:0 4px;flex-shrink:0}.exec-log{display:flex;flex-direction:column}.exec-step{display:flex;gap:16px;padding:14px 0;position:relative}.exec-step+.exec-step{border-top:1px solid rgba(255,255,255,.03)}.exec-step__indicator{display:flex;flex-direction:column;align-items:center;flex-shrink:0;width:32px}.exec-step__dot{width:24px;height:24px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:.6875rem;font-weight:700;flex-shrink:0}.exec-step__dot--success{background:#22c55e26;color:var(--color-success);border:1.5px solid rgba(34,197,94,.3)}.exec-step__dot--partial{background:#f59e0b26;color:var(--color-partial);border:1.5px solid rgba(245,158,11,.3)}.exec-step__dot--failed{background:#ef444426;color:var(--color-failed);border:1.5px solid rgba(239,68,68,.3)}.exec-step__line{flex:1;width:1.5px;background:var(--border-color);margin-top:4px}.exec-step__content{flex:1;min-width:0}.exec-step__header{display:flex;align-items:center;gap:8px;flex-wrap:wrap}.exec-step__agent{font-size:.875rem;font-weight:600;color:var(--text-primary)}.exec-step__badge{display:inline-flex;align-items:center;padding:2px 8px;font-size:.6875rem;font-weight:600;border-radius:100px;text-transform:capitalize}.exec-step__badge--success{background:#22c55e1f;color:var(--color-success);border:1px solid rgba(34,197,94,.2)}.exec-step__badge--partial{background:#f59e0b1f;color:var(--color-partial);border:1px solid rgba(245,158,11,.2)}.exec-step__badge--failed{background:#ef44441f;color:var(--color-failed);border:1px solid rgba(239,68,68,.2)}.exec-step__task{font-size:.8125rem;color:var(--text-secondary);margin-top:4px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.exec-step__meta{display:flex;gap:16px;margin-top:6px;font-size:.6875rem;color:var(--text-tertiary)}.exec-step__meta-item{display:flex;align-items:center;gap:4px}.panel-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:12px}.panel-item{background:var(--bg-tertiary);border-radius:8px;padding:16px;display:flex;flex-direction:column;gap:8px;border:1px solid transparent;transition:border-color var(--transition-fast)}.panel-item:hover{border-color:var(--border-color)}.panel-item__header{display:flex;align-items:center;justify-content:space-between}.panel-item__key{font-size:.8125rem;font-weight:600;color:var(--text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.panel-item__verdict{font-size:.6875rem;font-weight:700;padding:2px 8px;border-radius:4px;text-transform:uppercase;letter-spacing:.04em}.panel-item__verdict--pass{background:#22c55e26;color:var(--color-success)}.panel-item__verdict--block{background:#ef444426;color:var(--color-failed)}.panel-item__votes{display:flex;gap:4px}.panel-item__vote{width:24px;height:24px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:.625rem;font-weight:700}.panel-item__vote--pass{background:#22c55e1f;color:var(--color-success);border:1px solid rgba(34,197,94,.2)}.panel-item__vote--block{background:#ef44441f;color:var(--color-failed);border:1px solid rgba(239,68,68,.2)}.panel-item__fixes{font-size:.6875rem;color:var(--text-tertiary)}.panel-item__meta{display:flex;flex-wrap:wrap;gap:8px;margin-top:8px;padding-top:8px;border-top:1px solid var(--border-color)}.panel-item__meta-item{font-size:.625rem;color:var(--text-tertiary);white-space:nowrap}.sessions-table{width:100%;border-collapse:collapse;font-size:.8125rem}.sessions-table thead{position:sticky;top:0}.sessions-table th{padding:12px 16px;font-size:.6875rem;font-weight:600;color:var(--text-tertiary);text-align:left;text-transform:uppercase;letter-spacing:.06em;background:var(--bg-tertiary);border-bottom:1px solid var(--border-color)}.sessions-table th:last-child,.sessions-table td:last-child{text-align:right}.sessions-table th:nth-child(5),.sessions-table td:nth-child(5){text-align:right}.sessions-table td{padding:10px 16px;color:var(--text-secondary);border-bottom:1px solid rgba(255,255,255,.03);white-space:nowrap}.sessions-table tr:hover td{background:#ffffff05}.sessions-table .td-agent{font-weight:500;color:var(--text-primary)}.sessions-table .td-task{max-width:260px;overflow:hidden;text-overflow:ellipsis}.outcome-badge{display:inline-flex;align-items:center;padding:3px 10px;font-size:.6875rem;font-weight:600;border-radius:100px;text-transform:capitalize}.outcome-badge--success{background:#22c55e1f;color:var(--color-success);border:1px solid rgba(34,197,94,.2)}.outcome-badge--partial{background:#f59e0b1f;color:var(--color-partial);border:1px solid rgba(245,158,11,.2)}.outcome-badge--failed{background:#ef44441f;color:var(--color-failed);border:1px solid rgba(239,68,68,.2)}.td-num{font-variant-numeric:tabular-nums;text-align:right}.td-issue{font-size:.75rem;color:var(--text-accent);font-weight:500;font-variant-numeric:tabular-nums}.loading-skeleton{display:flex;align-items:center;justify-content:center;min-height:200px;color:var(--text-tertiary);font-size:.8125rem}.loading-skeleton:after{content:"Loading data…";animation:fade-pulse 1.5s ease-in-out infinite}@keyframes fade-pulse{0%,to{opacity:.4}50%{opacity:1}}.empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:48px 24px;text-align:center;gap:12px}.empty-state__icon{font-size:2rem;opacity:.4}.empty-state__text{font-size:.875rem;color:var(--text-tertiary);max-width:320px}.empty-state--enhanced{padding:56px 32px;gap:16px;border:1px dashed rgba(167,139,250,.15);border-radius:12px;background:radial-gradient(ellipse 300px 200px at 50% 30%,rgba(99,102,241,.04) 0%,transparent 70%),var(--bg-tertiary);position:relative;overflow:hidden}.empty-state--enhanced:before{content:"";position:absolute;inset:0;background:repeating-linear-gradient(0deg,transparent,transparent 23px,rgba(255,255,255,.015) 23px,rgba(255,255,255,.015) 24px);pointer-events:none}.empty-state__icon-wrap{width:64px;height:64px;display:flex;align-items:center;justify-content:center;border-radius:16px;background:#a78bfa0f;border:1px solid rgba(167,139,250,.12);color:var(--text-accent);animation:empty-breathe 4s ease-in-out infinite}@keyframes empty-breathe{0%,to{box-shadow:0 0 #a78bfa14;transform:scale(1)}50%{box-shadow:0 0 20px 4px #a78bfa0f;transform:scale(1.03)}}.empty-state__title{font-size:.9375rem;font-weight:600;color:var(--text-secondary);letter-spacing:-.01em}.empty-state__desc{font-size:.8125rem;color:var(--text-tertiary);max-width:380px;line-height:1.55}.kpi-card__hint{color:var(--text-tertiary);font-style:italic;font-size:.6875rem}.kpi-row--empty .kpi-card{border-style:dashed;border-color:#ffffff0a}.kpi-row--empty .kpi-card__value{color:var(--text-tertiary);opacity:.5}.welcome-banner{position:relative;background:var(--bg-secondary);border:1px solid transparent;border-radius:16px;padding:48px 40px;overflow:hidden;z-index:1}.welcome-banner:before{content:"";position:absolute;inset:-1px;border-radius:16px;padding:1px;background:linear-gradient(135deg,#a78bfa4d,#6366f126,#3b82f61a 60%,#a78bfa33);-webkit-mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);-webkit-mask-composite:xor;mask-composite:exclude;pointer-events:none;z-index:0}.welcome-banner__glow{position:absolute;top:-60px;left:50%;transform:translate(-50%);width:500px;height:300px;background:radial-gradient(ellipse at center,rgba(167,139,250,.08) 0%,rgba(99,102,241,.04) 40%,transparent 70%);pointer-events:none;z-index:0}.welcome-banner__content{position:relative;z-index:1;display:flex;flex-direction:column;align-items:center;text-align:center;gap:20px}.welcome-banner__icon{width:72px;height:72px;display:flex;align-items:center;justify-content:center;border-radius:20px;background:#a78bfa14;border:1px solid rgba(167,139,250,.15);color:var(--text-accent);animation:welcome-float 6s ease-in-out infinite}@keyframes welcome-float{0%,to{transform:translateY(0);box-shadow:0 8px 32px #a78bfa14}50%{transform:translateY(-6px);box-shadow:0 16px 48px #a78bfa1f}}.welcome-banner__title{font-size:1.375rem;font-weight:700;color:var(--text-primary);letter-spacing:-.02em;line-height:1.3}.welcome-banner__subtitle{font-size:.9375rem;color:var(--text-secondary);max-width:480px;line-height:1.6}.welcome-banner__steps{display:flex;gap:20px;margin-top:12px;flex-wrap:wrap;justify-content:center}.welcome-step{display:flex;align-items:flex-start;gap:12px;text-align:left;padding:16px 20px;background:#ffffff05;border:1px solid rgba(255,255,255,.05);border-radius:12px;min-width:200px;max-width:220px;transition:border-color var(--transition-fast),background var(--transition-fast)}.welcome-step:hover{border-color:#a78bfa26;background:#ffffff08}.welcome-step__num{width:28px;height:28px;border-radius:8px;display:flex;align-items:center;justify-content:center;font-size:.75rem;font-weight:700;color:var(--text-accent);background:#a78bfa1a;border:1px solid rgba(167,139,250,.2);flex-shrink:0}.welcome-step__text{display:flex;flex-direction:column;gap:3px}.welcome-step__text strong{font-size:.8125rem;font-weight:600;color:var(--text-primary)}.welcome-step__text span{font-size:.75rem;color:var(--text-tertiary);line-height:1.4}@media(max-width:640px){.welcome-banner{padding:32px 24px}.welcome-banner__steps{flex-direction:column;align-items:center}.welcome-step{max-width:100%;width:100%}}@keyframes slide-up{0%{opacity:0;transform:translateY(12px)}to{opacity:1;transform:translateY(0)}}.dash-main>*{animation:slide-up .5s ease-out backwards}.dash-main>*:nth-child(1){animation-delay:0ms}.dash-main>*:nth-child(2){animation-delay:60ms}.dash-main>*:nth-child(3){animation-delay:.12s}.dash-main>*:nth-child(4){animation-delay:.18s}.dash-main>*:nth-child(5){animation-delay:.24s}.dash-main>*:nth-child(6){animation-delay:.3s}.dash-main>*:nth-child(7){animation-delay:.36s}.dash-main>*:nth-child(8){animation-delay:.42s}.dash-main>*:nth-child(9){animation-delay:.48s}.dash-main>*:nth-child(10){animation-delay:.54s}.dash-main>*:nth-child(11){animation-delay:.6s}@media(max-width:640px){.bar-label{width:90px;font-size:.75rem}.donut-container{flex-direction:column;align-items:center}.donut-wrap{width:150px;height:150px}.pipeline{gap:0}.pipeline-stage{min-width:100px;padding:12px 8px}.panel-grid{grid-template-columns:1fr}.sessions-table th:nth-child(3),.sessions-table td:nth-child(3){display:none}}.filter-bar{display:flex;flex-wrap:wrap;gap:12px;align-items:flex-end;padding:16px 20px;background:var(--bg-secondary);border:1px solid var(--border-color);border-radius:12px}.filter-group{display:flex;flex-direction:column;gap:4px;min-width:0}.filter-label{font-size:.6875rem;font-weight:500;color:var(--text-tertiary);text-transform:uppercase;letter-spacing:.05em}.filter-input,.filter-select{height:34px;padding:0 10px;font-size:.8125rem;color:var(--text-primary);background:var(--bg-tertiary);border:1px solid var(--border-color);border-radius:8px;outline:none;transition:border-color var(--transition-fast);font-family:inherit}.filter-input:focus,.filter-select:focus{border-color:var(--border-accent)}.filter-input{width:140px;color-scheme:dark}.filter-select{min-width:140px;cursor:pointer;appearance:none;-webkit-appearance:none;background-image:url("data:image/svg+xml,%3Csvg width='10' height='6' viewBox='0 0 10 6' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%235a5a6e' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 10px center;padding-right:28px}.filter-reset{height:34px;font-size:.75rem}.dash-btn{display:inline-flex;align-items:center;gap:6px;padding:6px 14px;font-size:.8125rem;font-weight:500;font-family:inherit;border:none;border-radius:8px;cursor:pointer;transition:background var(--transition-fast),color var(--transition-fast)}.dash-btn--ghost{color:var(--text-secondary);background:#ffffff0f}.dash-btn--ghost:hover{color:var(--text-primary);background:#ffffff1a}.dash-header__actions{display:flex;align-items:center;gap:8px}@media(max-width:480px){.dash-header__inner{padding:0 12px}.dash-main{padding:12px;gap:12px}.kpi-card,.chart-card__header{padding:14px 16px}.chart-card__body{padding:12px 16px 16px}.filter-bar{padding:12px;gap:8px}.filter-input,.filter-select{width:100%;min-width:unset}.filter-group{flex:1 1 calc(50% - 4px)}.filter-reset{width:100%}.dash-header__title{font-size:.875rem}.exec-step__meta{flex-direction:column;gap:2px}.sessions-table th:nth-child(5),.sessions-table td:nth-child(5),.sessions-table th:nth-child(6),.sessions-table td:nth-child(6),.sessions-table th:nth-child(7),.sessions-table td:nth-child(7),.sessions-table th:nth-child(8),.sessions-table td:nth-child(8){display:none}}@media(max-width:768px){.charts-row{grid-template-columns:1fr}.pipeline{flex-wrap:wrap;gap:8px}.pipeline-arrow{display:none}.pipeline-stage{flex:1 1 calc(50% - 4px);min-width:100px}.tier-chart .donut-container,.donut-container{flex-direction:column;align-items:center}.sessions-table{font-size:.75rem}.sessions-table th,.sessions-table td{padding:8px 6px}}.convoy-overview{display:flex;flex-wrap:wrap;gap:24px;margin-bottom:20px}.convoy-stat{display:flex;flex-direction:column;gap:4px}.convoy-stat__label{font-size:.75rem;color:var(--text-tertiary);text-transform:uppercase;letter-spacing:.05em}.convoy-stat__value{font-size:.95rem;color:var(--text-primary)}.convoy-stat__value--error{color:var(--color-failed)}.convoy-progress{display:flex;align-items:center;gap:12px;margin-bottom:20px}.convoy-progress__bar{flex:1;height:8px;background:var(--bg-tertiary);border-radius:4px;overflow:hidden}.convoy-progress__fill{height:100%;background:var(--gradient-accent);border-radius:4px;transition:width var(--transition-base)}.convoy-progress__label{font-size:.8rem;color:var(--text-secondary);white-space:nowrap}.convoy-tasks{margin-top:8px}.convoy-chain{display:flex;align-items:stretch;gap:0;overflow-x:auto;padding:1rem 0 1.5rem;scrollbar-width:thin;scrollbar-color:var(--border-color) transparent}.convoy-chain::-webkit-scrollbar{height:4px}.convoy-chain::-webkit-scrollbar-track{background:transparent}.convoy-chain::-webkit-scrollbar-thumb{background:var(--border-color);border-radius:2px}.convoy-chain__connector{display:flex;align-items:center;padding:0 .5rem;color:var(--text-tertiary);font-size:1.1rem;flex-shrink:0}.convoy-chain__node{display:flex;flex-direction:column;align-items:center;gap:6px;padding:12px 16px;background:var(--bg-tertiary);border:1px solid var(--border-color);border-radius:10px;min-width:140px;cursor:pointer;transition:background var(--transition-fast),border-color var(--transition-fast),transform var(--transition-fast),box-shadow var(--transition-fast);flex-shrink:0}.convoy-chain__node:hover{background:var(--bg-card-hover);transform:translateY(-2px);box-shadow:0 4px 12px #0000004d}.convoy-chain__node-name{font-size:.8rem;font-weight:600;color:var(--text-primary);text-align:center;word-break:break-word;max-width:120px}.convoy-chain__node-meta{font-size:.72rem;color:var(--text-tertiary);text-align:center}.convoy-chain__node--active{border-color:var(--accent-purple);box-shadow:0 0 0 1px var(--accent-purple),0 0 12px #a78bfa33;animation:convoy-pulse 2s ease-in-out infinite}.convoy-chain__node--done{border-color:#22c55e4d}.convoy-chain__node--failed{border-color:#ef44444d}.convoy-chain__node--pending{opacity:.6}@keyframes convoy-pulse{0%,to{box-shadow:0 0 0 1px var(--accent-purple),0 0 8px #a78bfa26}50%{box-shadow:0 0 0 1px var(--accent-purple),0 0 18px #a78bfa59}}@media(max-width:768px){.convoy-chain{flex-wrap:wrap;gap:8px}.convoy-chain__connector{display:none}.convoy-chain__node{flex:1 1 calc(50% - 4px);min-width:120px}}.convoy-selector{display:flex;align-items:center;gap:.5rem}.convoy-selector__label{font-size:.75rem;text-transform:uppercase;letter-spacing:.05em;color:var(--text-secondary)}.convoy-selector__select{appearance:none;background:var(--bg-tertiary);border:1px solid rgba(255,255,255,.08);border-radius:6px;color:var(--text-primary);font-size:.8125rem;padding:.375rem 2rem .375rem .75rem;cursor:pointer;max-width:320px;background-image:url("data:image/svg+xml,%3Csvg width='10' height='6' viewBox='0 0 10 6' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%238a8a9a' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right .75rem center;transition:border-color .15s}.convoy-selector__select:hover{border-color:#ffffff26}.convoy-selector__select:focus{outline:2px solid var(--accent-purple);outline-offset:2px}.overall-stats{margin-bottom:0;padding:1.25rem;background:var(--bg-secondary);border-radius:12px;border:1px solid rgba(255,255,255,.06)}.overall-stats__header{display:flex;align-items:center;gap:.5rem;margin-bottom:1rem}.overall-stats__title{font-size:1rem;font-weight:600;color:var(--text-primary);margin:0}.overall-stats__grid{display:grid;grid-template-columns:repeat(6,1fr);gap:.75rem}.overall-kpi{display:flex;flex-direction:column;gap:.25rem;padding:.75rem;background:var(--bg-tertiary);border-radius:8px;border:1px solid rgba(255,255,255,.04);transition:border-color .15s}.overall-kpi:hover{border-color:#ffffff1a}.overall-kpi__label{font-size:.6875rem;text-transform:uppercase;letter-spacing:.05em;color:var(--text-secondary);display:flex;align-items:center;gap:.25rem}.overall-kpi__value{font-size:1.375rem;font-weight:700;color:var(--text-primary);font-variant-numeric:tabular-nums}.convoy-detail-header{padding:1.25rem;background:var(--bg-secondary);border-radius:12px;border:1px solid rgba(255,255,255,.06)}.convoy-detail-header__top{display:flex;align-items:center;gap:.75rem;margin-bottom:.75rem}.convoy-detail-header__name{font-size:1.25rem;font-weight:700;color:var(--text-primary);margin:0}.convoy-detail-header__meta{display:flex;flex-wrap:wrap;gap:1rem}.convoy-meta__item{font-size:.8125rem;color:var(--text-secondary)}.status-badge{display:inline-flex;align-items:center;padding:.125rem .625rem;border-radius:999px;font-size:.6875rem;font-weight:600;text-transform:uppercase;letter-spacing:.05em}.status-badge--done{background:#22c55e26;color:var(--color-success)}.status-badge--running{background:#3b82f626;color:var(--accent-blue)}.status-badge--failed{background:#ef444426;color:var(--color-failed)}.status-badge--gate-failed,.status-badge--gate_failed{background:#f59e0b26;color:var(--color-partial)}.tooltip-trigger{position:relative;cursor:help;font-size:.75rem;opacity:.5;transition:opacity .15s}.tooltip-trigger:hover{opacity:1}.tooltip-trigger:hover:after{content:attr(data-tooltip);position:absolute;bottom:100%;left:50%;transform:translate(-50%);padding:.5rem .875rem;background:var(--bg-primary);border:1px solid rgba(255,255,255,.12);border-radius:6px;font-size:.8125rem;color:var(--text-primary);max-width:420px;min-width:180px;white-space:normal;text-align:left;line-height:1.5;word-break:break-word;z-index:100;pointer-events:none;box-shadow:0 4px 12px #0006;text-transform:none}.tooltip-trigger:focus{opacity:1;outline:2px solid var(--accent-blue);outline-offset:2px;border-radius:2px}.tooltip-trigger:focus:after,.tooltip-trigger:focus-visible:after{content:attr(data-tooltip);position:absolute;bottom:100%;left:50%;transform:translate(-50%);padding:.5rem .875rem;background:var(--bg-primary);border:1px solid rgba(255,255,255,.12);border-radius:6px;font-size:.8125rem;color:var(--text-primary);max-width:420px;min-width:180px;white-space:normal;text-align:left;line-height:1.5;word-break:break-word;z-index:100;pointer-events:none;box-shadow:0 4px 12px #0006;text-transform:none}.status-badge--pending{background:#64748b26;color:#94a3b8}.status-badge--assigned{background:#3b82f61a;color:#60a5fa}.status-badge--timed-out{background:#ef44441f;color:#f87171}.status-badge--review-blocked{background:#f59e0b1f;color:#fbbf24}.status-badge--skipped{background:#64748b1a;color:#64748b}.status-badge--hook-failed{background:#ef44441a;color:#f87171}.status-badge--disputed{background:#a78bfa26;color:var(--accent-purple)}.status-badge--wait-for-input{background:#f59e0b1a;color:var(--color-partial)}.task-summary-cards{display:flex;gap:12px;flex-wrap:wrap;margin-bottom:20px}.task-summary-card{flex:1 1 140px;display:flex;flex-direction:column;gap:8px;padding:14px 16px;background:var(--bg-card);border:1px solid var(--border-color);border-radius:10px;transition:border-color .15s}.task-summary-card:hover{border-color:#ffffff1f}.task-summary-card__label{font-size:.6875rem;font-weight:600;text-transform:uppercase;letter-spacing:.06em;color:var(--text-tertiary)}.task-summary-card__value{font-size:1.75rem;font-weight:700;line-height:1;color:var(--text-primary)}.task-summary-card--done{border-left:3px solid var(--color-success)}.task-summary-card--running{border-left:3px solid var(--accent-blue)}.task-summary-card--errors{border-left:3px solid var(--color-failed)}.task-summary-card--waiting{border-left:3px solid #94a3b8}.task-summary-card--input{border-left:3px solid var(--color-partial)}.task-table-wrap{overflow-x:auto}.task-table .td-num{text-align:right}.sortable-th{cursor:pointer;user-select:none}.sortable-th:hover{color:var(--text-secondary)}.sortable-th--active{color:var(--text-primary)}.sort-indicator{margin-left:4px;font-size:.5625rem;opacity:.5}.sortable-th--active .sort-indicator{opacity:1;color:var(--accent-blue)}.phase-breakdown{display:flex;flex-direction:column;gap:8px;margin-bottom:20px}.phase-breakdown__row{display:flex;align-items:center;gap:12px}.phase-breakdown__label{font-size:.75rem;font-weight:600;color:var(--text-tertiary);min-width:60px}.phase-breakdown__bar{flex:1;height:10px;background:#ffffff0a;border-radius:5px;overflow:hidden;display:flex}.phase-breakdown__seg{height:100%;transition:width .3s ease}.phase-breakdown__seg--done{background:var(--color-success)}.phase-breakdown__seg--running{background:var(--accent-blue)}.phase-breakdown__seg--waiting{background:#475569}.phase-breakdown__seg--failed{background:var(--color-failed)}.phase-breakdown__count{font-size:.6875rem;color:var(--text-tertiary);min-width:52px;text-align:right}@media(max-width:960px){.overall-stats__grid{grid-template-columns:repeat(3,1fr)}}@media(max-width:640px){.overall-stats__grid{grid-template-columns:repeat(2,1fr)}.convoy-detail-header__name{font-size:1rem}.convoy-selector__select{max-width:200px}}@media(max-width:480px){.overall-stats__grid{grid-template-columns:1fr}}.reliability-empty{font-size:.875rem;color:var(--text-tertiary);padding:12px 0;margin:0}.secret-leak-banner{display:flex;align-items:flex-start;gap:12px;padding:14px 16px;background:#f59e0b1a;border:1px solid rgba(245,158,11,.3);border-radius:8px;margin-top:16px}.secret-leak-banner__icon{font-size:1.25rem;flex-shrink:0;line-height:1.4}.secret-leak-banner__text{display:flex;flex-direction:column;gap:4px}.secret-leak-banner__text strong{font-size:.875rem;font-weight:600;color:var(--color-partial)}.secret-leak-banner__text span{font-size:.8125rem;color:var(--text-secondary)}.artifact-type-badge{display:inline-block;padding:2px 8px;border-radius:4px;font-size:.75rem;font-weight:600;color:#fff;text-transform:uppercase;letter-spacing:.03em}.timeline-filters{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:16px}.timeline-filter-chip{display:inline-flex;align-items:center;padding:6px 14px;border-radius:20px;border:1px solid var(--border);background:transparent;color:var(--text-secondary);font-size:.8125rem;font-weight:500;cursor:pointer;transition:all .15s ease}.timeline-filter-chip:hover{border-color:var(--accent);color:var(--text-primary)}.timeline-filter-chip--active{background:var(--accent);border-color:var(--accent);color:#fff}.event-timeline-row{padding:12px 16px;border-bottom:1px solid var(--border);cursor:pointer;transition:background .15s ease}.event-timeline-row:hover{background:#a78bfa0d}.event-timeline-row--expanded{background:#a78bfa14}.event-timeline-row__main{display:flex;align-items:center;gap:12px;flex-wrap:wrap}.event-timeline-ts{font-size:.8125rem;color:var(--text-secondary);min-width:140px;font-variant-numeric:tabular-nums}.event-type-badge{display:inline-block;padding:2px 8px;border-radius:4px;font-size:.6875rem;font-weight:600;color:#fff;text-transform:uppercase;letter-spacing:.03em}.event-timeline-context{font-size:.8125rem;color:var(--text-tertiary, #6b7280);font-family:var(--font-mono, "SF Mono", "Fira Code", monospace)}.event-timeline-detail{margin-top:8px;padding:12px;background:var(--bg-card, #111118);border-radius:6px;border:1px solid var(--border)}.event-timeline-json{font-size:.75rem;color:var(--text-secondary);white-space:pre-wrap;word-break:break-all;margin:0;font-family:var(--font-mono, "SF Mono", "Fira Code", monospace);max-height:300px;overflow-y:auto}@media(max-width:640px){.event-timeline-ts{min-width:auto;font-size:.75rem}.event-timeline-row__main{gap:8px}.timeline-filter-chip{padding:4px 10px;font-size:.75rem}}.dash-btn:focus-visible,.convoy-selector__select:focus-visible,.filter-select:focus-visible,.filter-input:focus-visible,.dash-sidebar__link:focus-visible,.timeline-filter-chip:focus-visible{outline:2px solid var(--accent-blue);outline-offset:2px}.convoy-status-explanation{font-size:.8125rem;color:var(--text-secondary);margin-top:.25rem;margin-bottom:.5rem;font-style:italic}.view-home,.view-convoy-detail{display:flex;flex-direction:column;gap:20px}[data-view-hidden]{display:none!important}.breadcrumbs{display:flex;align-items:center;gap:6px;font-size:.8125rem;color:var(--text-tertiary);flex-wrap:wrap;padding:0;margin-bottom:-8px}.breadcrumbs__link{color:var(--text-secondary);text-decoration:none;transition:color var(--transition-fast);border-bottom:1px solid transparent}.breadcrumbs__link:hover{color:var(--text-accent);border-bottom-color:#a78bfa66}.breadcrumbs__link:focus-visible{outline:2px solid var(--accent-blue);outline-offset:2px;border-radius:2px}.breadcrumbs__separator{color:var(--text-tertiary);opacity:.5;user-select:none;font-size:.75rem}.breadcrumbs__current{color:var(--text-accent);font-weight:500;max-width:320px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.convoy-list-section{background:var(--bg-secondary);border:1px solid var(--border-color);border-radius:12px;transition:border-color var(--transition-fast)}.convoy-list-section:hover{border-color:#ffffff1a}.convoy-list-section__header{padding:20px 24px 12px;border-bottom:1px solid var(--border-color)}.convoy-list-section__header h2,.convoy-list-section__header .convoy-list-section__title{font-size:.9375rem;font-weight:600;color:var(--text-primary);margin:0}.convoy-list-section__desc{font-size:.75rem;color:var(--text-tertiary);margin-top:2px}.convoy-list-filters{display:flex;flex-wrap:wrap;gap:10px;align-items:flex-end;padding:14px 24px;background:#ffffff03;border-bottom:1px solid var(--border-color)}.convoy-list-filters__group{display:flex;flex-direction:column;gap:4px}.convoy-list-filters__group label{font-size:.6875rem;font-weight:500;color:var(--text-tertiary);text-transform:uppercase;letter-spacing:.05em}.convoy-list-filters__input,.convoy-list-filters__select,.convoy-list-filters__date{height:34px;padding:0 10px;font-size:.8125rem;color:var(--text-primary);background:var(--bg-tertiary);border:1px solid var(--border-color);border-radius:8px;outline:none;font-family:inherit;transition:border-color var(--transition-fast);color-scheme:dark}.convoy-list-filters__input:focus,.convoy-list-filters__select:focus,.convoy-list-filters__date:focus{border-color:var(--border-accent)}.convoy-list-filters__input{width:180px}.convoy-list-filters__date{width:150px}.convoy-list-filters__select{min-width:140px;cursor:pointer;appearance:none;-webkit-appearance:none;background-image:url("data:image/svg+xml,%3Csvg width='10' height='6' viewBox='0 0 10 6' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%235a5a6e' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 10px center;padding-right:28px}.convoy-list-filters__reset{height:34px;padding:0 14px;font-size:.75rem;font-weight:500;font-family:inherit;color:var(--text-secondary);background:#ffffff0f;border:none;border-radius:8px;cursor:pointer;transition:background var(--transition-fast),color var(--transition-fast);align-self:flex-end;white-space:nowrap}.convoy-list-filters__reset:hover{background:#ffffff1a;color:var(--text-primary)}.convoy-list-filters__reset:focus-visible{outline:2px solid var(--accent-blue);outline-offset:2px}.convoy-list-table{width:100%;border-collapse:collapse;font-size:.8125rem}.convoy-list-table thead{position:sticky;top:0}.convoy-list-table th{padding:10px 16px;font-size:.6875rem;font-weight:600;color:var(--text-tertiary);text-align:left;text-transform:uppercase;letter-spacing:.06em;background:var(--bg-tertiary);border-bottom:1px solid var(--border-color);white-space:nowrap}.convoy-list-table td{padding:10px 16px;color:var(--text-secondary);border-bottom:1px solid rgba(255,255,255,.03);white-space:nowrap}.convoy-list-table tr{cursor:pointer;transition:background var(--transition-fast)}.convoy-list-table tbody tr:hover td{background:#a78bfa0d;color:var(--text-primary)}.convoy-list-table tbody tr:hover td:first-child{color:var(--text-accent)}.convoy-list-table .td-convoy-name{font-weight:600;color:var(--text-primary);max-width:240px;overflow:hidden;text-overflow:ellipsis}.convoy-list-pagination{display:flex;align-items:center;justify-content:center;gap:12px;padding:16px 0;margin-top:4px}.convoy-list-pagination__info{font-size:.8125rem;color:var(--text-secondary);min-width:100px;text-align:center}.convoy-list-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;padding:48px 24px;text-align:center;color:var(--text-tertiary)}.convoy-list-empty__icon{font-size:2rem;opacity:.35}.convoy-list-empty__text{font-size:.875rem;color:var(--text-tertiary);max-width:300px;line-height:1.5}.convoy-detail-hero{display:flex;flex-direction:column;gap:12px;padding:24px;background:var(--bg-secondary);border:1px solid var(--border-color);border-radius:12px;position:relative}.convoy-detail-hero:before{content:"";position:absolute;top:0;left:0;right:0;height:2px;background:var(--gradient-accent);opacity:.6;pointer-events:none}.convoy-detail-hero__top{display:flex;align-items:center;gap:14px;flex-wrap:wrap;justify-content:space-between}.convoy-chain-toggle{cursor:pointer;user-select:none;font-size:.75rem;margin-right:6px;opacity:.6}.convoy-chain-row{background:#a78bfa0a}.convoy-chain-row td:first-child{font-weight:600}.convoy-chain-child td:first-child{padding-left:28px}.convoy-chain-child td:first-child:before{content:"└ ";opacity:.4}.convoy-detail-hero__title{font-size:1.5rem;font-weight:700;color:var(--text-primary);letter-spacing:-.02em;line-height:1.25;margin:0}.convoy-detail-hero__status{flex-shrink:0}.convoy-detail-hero__status .status-badge{padding:.25rem .875rem;font-size:.75rem;border-radius:8px}.convoy-detail-hero__meta{display:flex;flex-wrap:wrap;gap:20px;padding-top:4px;border-top:1px solid var(--border-color)}.convoy-detail-hero__meta-item{display:flex;flex-direction:column;gap:2px}.convoy-detail-hero__meta-label{font-size:.6875rem;font-weight:500;color:var(--text-tertiary);text-transform:uppercase;letter-spacing:.05em}.convoy-detail-hero__meta-value{font-size:.875rem;color:var(--text-secondary);font-variant-numeric:tabular-nums}.task-row--clickable{cursor:pointer;transition:background var(--transition-fast)}.task-row--clickable:hover td{background:#a78bfa0a}.task-row--clickable td:first-child{position:relative}.task-row--clickable td:first-child:before{content:"";position:absolute;left:0;top:0;bottom:0;width:2px;background:transparent;transition:background var(--transition-fast)}.task-row--clickable:hover td:first-child:before{background:var(--border-accent)}.task-detail-expand{background:var(--bg-tertiary);border-bottom:1px solid var(--border-color)}.task-detail-expand__inner{padding:16px 20px}.task-detail-expand__grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:12px 24px}.task-detail-expand__field{display:flex;flex-direction:column;gap:3px}.task-detail-expand__label{font-size:.6875rem;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--text-tertiary)}.task-detail-expand__value{font-size:.8125rem;color:var(--text-secondary);word-break:break-word;font-variant-numeric:tabular-nums}.task-detail-expand__value code{font-family:SF Mono,Fira Code,Cascadia Code,monospace;font-size:.75rem;background:#ffffff0f;padding:1px 6px;border-radius:4px;color:var(--text-accent)}@media(max-width:768px){.convoy-list-filters{padding:12px 16px;gap:8px}.convoy-list-filters__input,.convoy-list-filters__select,.convoy-list-filters__date{width:100%;min-width:unset}.convoy-list-filters__group{flex:1 1 calc(50% - 4px)}.convoy-list-filters__reset{flex:1 1 100%;width:100%}.convoy-list-section__header{padding:16px 16px 12px}}@media(max-width:480px){.convoy-list-filters__group{flex:1 1 100%}.convoy-detail-hero__title{font-size:1.25rem}.convoy-detail-hero{padding:16px}.task-detail-expand__grid{grid-template-columns:1fr}.breadcrumbs__current{max-width:180px}}.waiting-banner{text-align:center;padding:3rem 2rem;margin-bottom:2rem;border-radius:var(--radius-lg, 12px);background:var(--bg-surface, #1e1e2e);border:1px solid var(--border-subtle, rgba(255,255,255,.06))}.waiting-banner__content{display:flex;flex-direction:column;align-items:center;gap:.75rem}.waiting-banner__spinner{width:32px;height:32px;border:3px solid var(--border-subtle, rgba(255,255,255,.1));border-top-color:var(--accent, #60a5fa);border-radius:50%;animation:spin 1s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}.waiting-banner__title{font-size:1.25rem;font-weight:600;margin:0;color:var(--text-primary, #e2e8f0)}.waiting-banner__subtitle{font-size:.875rem;color:var(--text-muted, #94a3b8);margin:0}.pipeline-chain-nav{display:flex;align-items:center;gap:.5rem;padding:.5rem 0;margin-bottom:.5rem;flex-wrap:wrap}.pipeline-chain__label{font-size:.75rem;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--text-muted, #94a3b8);margin-right:.25rem}.pipeline-chain__item{display:inline-flex;align-items:center;gap:.375rem;padding:.25rem .625rem;font-size:.8125rem;border-radius:var(--radius-sm, 6px);border:1px solid var(--border-subtle, rgba(255,255,255,.06));background:var(--bg-surface, #1e1e2e);color:var(--text-secondary, #cbd5e1);cursor:pointer;transition:border-color .15s,background .15s}.pipeline-chain__item:hover{border-color:var(--border-hover, rgba(255,255,255,.15));background:var(--bg-hover, rgba(255,255,255,.04))}.pipeline-chain__item--active{border-color:var(--accent, #60a5fa);background:#60a5fa14;color:var(--text-primary, #e2e8f0)}.pipeline-chain__dot{display:inline-block;width:8px;height:8px;border-radius:50%;flex-shrink:0}.activity-timeline{display:flex;flex-direction:column;gap:4px}
|