@leonarto/spec-embryo 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +156 -0
- package/package.json +48 -0
- package/src/backends/base.ts +18 -0
- package/src/backends/deterministic.ts +105 -0
- package/src/backends/index.ts +26 -0
- package/src/backends/prompt.ts +169 -0
- package/src/backends/subprocess.ts +198 -0
- package/src/cli.ts +111 -0
- package/src/commands/agents.ts +16 -0
- package/src/commands/current.ts +95 -0
- package/src/commands/doctor.ts +12 -0
- package/src/commands/handoff.ts +64 -0
- package/src/commands/init.ts +101 -0
- package/src/commands/reshape.ts +20 -0
- package/src/commands/resume.ts +19 -0
- package/src/commands/spec.ts +108 -0
- package/src/commands/status.ts +98 -0
- package/src/commands/task.ts +190 -0
- package/src/commands/ui.ts +35 -0
- package/src/domain.ts +357 -0
- package/src/engine.ts +290 -0
- package/src/frontmatter.ts +83 -0
- package/src/index.ts +75 -0
- package/src/paths.ts +32 -0
- package/src/repository.ts +807 -0
- package/src/services/adoption.ts +169 -0
- package/src/services/agents.ts +191 -0
- package/src/services/dashboard.ts +776 -0
- package/src/services/details.ts +453 -0
- package/src/services/doctor.ts +452 -0
- package/src/services/layout.ts +420 -0
- package/src/services/spec-answer-evaluation.ts +103 -0
- package/src/services/spec-import.ts +217 -0
- package/src/services/spec-questions.ts +343 -0
- package/src/services/ui.ts +34 -0
- package/src/storage.ts +57 -0
- package/src/templates.ts +270 -0
- package/tsconfig.json +17 -0
- package/web/package.json +24 -0
- package/web/src/app.css +83 -0
- package/web/src/app.d.ts +6 -0
- package/web/src/app.html +11 -0
- package/web/src/lib/components/AnalysisFilters.svelte +293 -0
- package/web/src/lib/components/DocumentBody.svelte +100 -0
- package/web/src/lib/components/MultiSelectDropdown.svelte +280 -0
- package/web/src/lib/components/SelectDropdown.svelte +265 -0
- package/web/src/lib/server/project-root.ts +34 -0
- package/web/src/lib/task-board.ts +20 -0
- package/web/src/routes/+layout.server.ts +57 -0
- package/web/src/routes/+layout.svelte +421 -0
- package/web/src/routes/+layout.ts +1 -0
- package/web/src/routes/+page.svelte +530 -0
- package/web/src/routes/specs/+page.svelte +416 -0
- package/web/src/routes/specs/[specId]/+page.server.ts +81 -0
- package/web/src/routes/specs/[specId]/+page.svelte +675 -0
- package/web/src/routes/tasks/+page.svelte +341 -0
- package/web/src/routes/tasks/[taskId]/+page.server.ts +12 -0
- package/web/src/routes/tasks/[taskId]/+page.svelte +431 -0
- package/web/src/routes/timeline/+page.svelte +1093 -0
- package/web/svelte.config.js +10 -0
- package/web/tsconfig.json +9 -0
- package/web/vite.config.ts +11 -0
|
@@ -0,0 +1,1093 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { page } from "$app/state";
|
|
3
|
+
import {
|
|
4
|
+
Archive,
|
|
5
|
+
ArrowRight,
|
|
6
|
+
ChartNoAxesGantt,
|
|
7
|
+
ChevronRight,
|
|
8
|
+
Clock3,
|
|
9
|
+
Filter,
|
|
10
|
+
FolderKanban,
|
|
11
|
+
GitBranchPlus,
|
|
12
|
+
Link2,
|
|
13
|
+
ListFilter,
|
|
14
|
+
Orbit,
|
|
15
|
+
Radar,
|
|
16
|
+
Sparkles,
|
|
17
|
+
TimerReset,
|
|
18
|
+
X,
|
|
19
|
+
} from "@lucide/svelte";
|
|
20
|
+
import type { DashboardData, DashboardTimelineMode } from "../../../../src/services/dashboard.ts";
|
|
21
|
+
import AnalysisFilters from "../../lib/components/AnalysisFilters.svelte";
|
|
22
|
+
|
|
23
|
+
let { data } = $props();
|
|
24
|
+
const dashboard = $derived(data.dashboard as DashboardData);
|
|
25
|
+
|
|
26
|
+
const totalUnits = $derived(Math.max(dashboard.timeline.totalUnits, 1));
|
|
27
|
+
const ruler = $derived(Array.from({ length: totalUnits }, (_, index) => index + 1));
|
|
28
|
+
const currentSearch = $derived(page.url.searchParams);
|
|
29
|
+
|
|
30
|
+
function timelineModeHref(mode: DashboardTimelineMode): string {
|
|
31
|
+
const params = new URLSearchParams(currentSearch);
|
|
32
|
+
params.set("timeline_mode", mode);
|
|
33
|
+
const search = params.toString();
|
|
34
|
+
return search.length > 0 ? `/timeline?${search}` : "/timeline";
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function timelineSelectionHref(taskId: string): string {
|
|
38
|
+
const params = new URLSearchParams(currentSearch);
|
|
39
|
+
if (dashboard.timeline.selection?.taskId === taskId) {
|
|
40
|
+
params.delete("selected_task");
|
|
41
|
+
} else {
|
|
42
|
+
params.set("selected_task", taskId);
|
|
43
|
+
}
|
|
44
|
+
const search = params.toString();
|
|
45
|
+
return search.length > 0 ? `/timeline?${search}` : "/timeline";
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function clearTimelineSelectionHref(): string {
|
|
49
|
+
const params = new URLSearchParams(currentSearch);
|
|
50
|
+
params.delete("selected_task");
|
|
51
|
+
const search = params.toString();
|
|
52
|
+
return search.length > 0 ? `/timeline?${search}` : "/timeline";
|
|
53
|
+
}
|
|
54
|
+
</script>
|
|
55
|
+
|
|
56
|
+
<svelte:head>
|
|
57
|
+
<title>{dashboard.project.name} Timeline</title>
|
|
58
|
+
</svelte:head>
|
|
59
|
+
|
|
60
|
+
<section class="view-header">
|
|
61
|
+
<div class="header-copy">
|
|
62
|
+
<p class="eyebrow">Deterministic sequence</p>
|
|
63
|
+
<h3>Compact Gantt</h3>
|
|
64
|
+
</div>
|
|
65
|
+
<p class="intro">
|
|
66
|
+
This denser planning surface keeps dependency order and relative effort deterministic, but compresses the scan path so many more rows can fit on screen without turning into generic dashboard clutter.
|
|
67
|
+
</p>
|
|
68
|
+
</section>
|
|
69
|
+
|
|
70
|
+
<AnalysisFilters
|
|
71
|
+
{dashboard}
|
|
72
|
+
title="Timeline slice filters"
|
|
73
|
+
detail="Use spec sets and lifecycle windows to shape the planning slice, then switch between active-only and include-completed display modes below."
|
|
74
|
+
/>
|
|
75
|
+
|
|
76
|
+
<section class="mode-shell">
|
|
77
|
+
<div class="mode-copy">
|
|
78
|
+
<div class="mode-head">
|
|
79
|
+
<span class="icon-pill">
|
|
80
|
+
<ListFilter size={15} strokeWidth={1.9} />
|
|
81
|
+
</span>
|
|
82
|
+
<div>
|
|
83
|
+
<p class="eyebrow">Display mode</p>
|
|
84
|
+
<h4>Planning horizon</h4>
|
|
85
|
+
</div>
|
|
86
|
+
</div>
|
|
87
|
+
<p>
|
|
88
|
+
`Active only` keeps the planner focused on live execution. `Include completed` lets finished and cancelled work recede into the same grouped timeline for broader planning context.
|
|
89
|
+
</p>
|
|
90
|
+
</div>
|
|
91
|
+
|
|
92
|
+
<div class="mode-toggle">
|
|
93
|
+
<a class:active={dashboard.timeline.mode === "active"} href={timelineModeHref("active")}>
|
|
94
|
+
<Orbit size={14} strokeWidth={1.9} />
|
|
95
|
+
Active only
|
|
96
|
+
</a>
|
|
97
|
+
<a class:active={dashboard.timeline.mode === "all"} href={timelineModeHref("all")}>
|
|
98
|
+
<Archive size={14} strokeWidth={1.9} />
|
|
99
|
+
Include completed
|
|
100
|
+
</a>
|
|
101
|
+
</div>
|
|
102
|
+
</section>
|
|
103
|
+
|
|
104
|
+
{#if dashboard.timeline.selection}
|
|
105
|
+
<section class="selection-shell">
|
|
106
|
+
<div class="selection-head">
|
|
107
|
+
<div class="mode-head">
|
|
108
|
+
<span class="icon-pill selection-pill">
|
|
109
|
+
<Radar size={15} strokeWidth={1.9} />
|
|
110
|
+
</span>
|
|
111
|
+
<div>
|
|
112
|
+
<p class="eyebrow">Selected task</p>
|
|
113
|
+
<h4>{dashboard.timeline.selection.taskId} · {dashboard.timeline.selection.title}</h4>
|
|
114
|
+
</div>
|
|
115
|
+
</div>
|
|
116
|
+
|
|
117
|
+
<a class="clear-selection" href={clearTimelineSelectionHref()}>
|
|
118
|
+
<X size={13} strokeWidth={2} />
|
|
119
|
+
Clear trace
|
|
120
|
+
</a>
|
|
121
|
+
</div>
|
|
122
|
+
|
|
123
|
+
<p class="selection-copy">
|
|
124
|
+
The planner is showing upstream dependencies, downstream dependents, and the subset of downstream work that is currently blocked. Related spec groups stay visible so cross-spec entanglement is easy to scan.
|
|
125
|
+
</p>
|
|
126
|
+
|
|
127
|
+
<div class="selection-metrics">
|
|
128
|
+
<span class="cell-meta dependency">
|
|
129
|
+
<Link2 size={12} strokeWidth={1.9} />
|
|
130
|
+
{dashboard.timeline.selection.directDependencyIds.length} direct deps
|
|
131
|
+
</span>
|
|
132
|
+
<span class="cell-meta dependency-soft">
|
|
133
|
+
<Sparkles size={12} strokeWidth={1.9} />
|
|
134
|
+
{dashboard.timeline.selection.transitiveDependencyIds.length} transitive deps
|
|
135
|
+
</span>
|
|
136
|
+
<span class="cell-meta dependent">
|
|
137
|
+
<ArrowRight size={12} strokeWidth={1.9} />
|
|
138
|
+
{dashboard.timeline.selection.directDependentIds.length} direct dependents
|
|
139
|
+
</span>
|
|
140
|
+
<span class="cell-meta dependent-soft">
|
|
141
|
+
<Sparkles size={12} strokeWidth={1.9} />
|
|
142
|
+
{dashboard.timeline.selection.transitiveDependentIds.length} transitive dependents
|
|
143
|
+
</span>
|
|
144
|
+
<span class="cell-meta blocked">
|
|
145
|
+
<ArrowRight size={12} strokeWidth={1.9} />
|
|
146
|
+
{dashboard.timeline.selection.directBlockedDependentIds.length} direct blocked
|
|
147
|
+
</span>
|
|
148
|
+
<span class="cell-meta blocked-soft">
|
|
149
|
+
<Sparkles size={12} strokeWidth={1.9} />
|
|
150
|
+
{dashboard.timeline.selection.transitiveBlockedDependentIds.length} transitive blocked
|
|
151
|
+
</span>
|
|
152
|
+
</div>
|
|
153
|
+
|
|
154
|
+
<div class="selection-specs">
|
|
155
|
+
<div class="selection-spec-group">
|
|
156
|
+
<p class="eyebrow">Directly related specs</p>
|
|
157
|
+
<div class="chip-row">
|
|
158
|
+
{#if dashboard.timeline.selection.directRelatedSpecIds.length === 0}
|
|
159
|
+
<span class="mini-pill neutral">none</span>
|
|
160
|
+
{:else}
|
|
161
|
+
{#each dashboard.timeline.selection.directRelatedSpecIds as specId}
|
|
162
|
+
<a class="mini-pill spec-direct" href={`/specs/${specId}`}>{specId}</a>
|
|
163
|
+
{/each}
|
|
164
|
+
{/if}
|
|
165
|
+
</div>
|
|
166
|
+
</div>
|
|
167
|
+
|
|
168
|
+
<div class="selection-spec-group">
|
|
169
|
+
<p class="eyebrow">Transitively related specs</p>
|
|
170
|
+
<div class="chip-row">
|
|
171
|
+
{#if dashboard.timeline.selection.transitiveRelatedSpecIds.length === 0}
|
|
172
|
+
<span class="mini-pill neutral">none</span>
|
|
173
|
+
{:else}
|
|
174
|
+
{#each dashboard.timeline.selection.transitiveRelatedSpecIds as specId}
|
|
175
|
+
<a class="mini-pill spec-transitive" href={`/specs/${specId}`}>{specId}</a>
|
|
176
|
+
{/each}
|
|
177
|
+
{/if}
|
|
178
|
+
</div>
|
|
179
|
+
</div>
|
|
180
|
+
</div>
|
|
181
|
+
</section>
|
|
182
|
+
{/if}
|
|
183
|
+
|
|
184
|
+
<section class="timeline-shell">
|
|
185
|
+
{#if dashboard.timeline.groups.length === 0}
|
|
186
|
+
<div class="timeline-empty">
|
|
187
|
+
<TimerReset size={16} strokeWidth={1.9} />
|
|
188
|
+
<span>No timeline rows matched the current filters and display mode.</span>
|
|
189
|
+
</div>
|
|
190
|
+
{:else}
|
|
191
|
+
<div class="planner-head">
|
|
192
|
+
<div class="pane-head sticky-pane">
|
|
193
|
+
<span>Spec sequence</span>
|
|
194
|
+
</div>
|
|
195
|
+
<div class="grid-head" style={`--total:${totalUnits}`}>
|
|
196
|
+
{#each ruler as unit}
|
|
197
|
+
<span>{unit}</span>
|
|
198
|
+
{/each}
|
|
199
|
+
</div>
|
|
200
|
+
</div>
|
|
201
|
+
|
|
202
|
+
<div class="planner-body">
|
|
203
|
+
{#each dashboard.timeline.groups as group}
|
|
204
|
+
<section class="group-shell">
|
|
205
|
+
<div class={`group-head sticky-pane ${group.selectionState}`}>
|
|
206
|
+
<div class="group-copy">
|
|
207
|
+
<div class="group-topline">
|
|
208
|
+
<p class="group-id">{group.specId}</p>
|
|
209
|
+
<div class="group-meta">
|
|
210
|
+
<span class="mini-pill neutral">{group.rows.length} rows</span>
|
|
211
|
+
<span class={`mini-pill status ${group.specStatus}`}>{group.specStatus}</span>
|
|
212
|
+
{#if group.selectionState === "related_direct"}
|
|
213
|
+
<span class="mini-pill spec-direct">direct</span>
|
|
214
|
+
{:else if group.selectionState === "related_transitive"}
|
|
215
|
+
<span class="mini-pill spec-transitive">transitive</span>
|
|
216
|
+
{:else if group.selectionState === "selected"}
|
|
217
|
+
<span class="mini-pill selected-pill">selected</span>
|
|
218
|
+
{/if}
|
|
219
|
+
</div>
|
|
220
|
+
</div>
|
|
221
|
+
<h4><a href={`/specs/${group.specId}`} title={group.specTitle}>{group.specTitle}</a></h4>
|
|
222
|
+
</div>
|
|
223
|
+
</div>
|
|
224
|
+
|
|
225
|
+
{#if group.rows.length === 0}
|
|
226
|
+
<div class="empty-group">
|
|
227
|
+
<div class="empty-group-label sticky-pane">
|
|
228
|
+
<span class="mini-pill">No rows in this mode</span>
|
|
229
|
+
</div>
|
|
230
|
+
<div class="empty-group-copy">
|
|
231
|
+
<span>
|
|
232
|
+
<Filter size={12} strokeWidth={1.9} />
|
|
233
|
+
This spec is selected, but no tasks match the current display mode and filters.
|
|
234
|
+
</span>
|
|
235
|
+
</div>
|
|
236
|
+
</div>
|
|
237
|
+
{:else}
|
|
238
|
+
{#each group.rows as row}
|
|
239
|
+
<div class={`planner-row ${row.selectionState}`}>
|
|
240
|
+
<div class={`row-label sticky-pane ${row.selectionState}`}>
|
|
241
|
+
<div class="task-copy">
|
|
242
|
+
<div class="row-topline">
|
|
243
|
+
<a class="task-id" href={`/tasks/${row.taskId}`}>
|
|
244
|
+
<FolderKanban size={13} strokeWidth={1.9} />
|
|
245
|
+
{row.taskId}
|
|
246
|
+
</a>
|
|
247
|
+
<div class="row-meta-pills">
|
|
248
|
+
{#if dashboard.timeline.selection && row.isCrossSpecRelated}
|
|
249
|
+
<span class="cell-meta spec-direct">
|
|
250
|
+
<Link2 size={12} strokeWidth={1.9} />
|
|
251
|
+
cross-spec
|
|
252
|
+
</span>
|
|
253
|
+
{/if}
|
|
254
|
+
<span class={`status-pill ${row.effectiveStatus}`}>{row.statusLabel}</span>
|
|
255
|
+
<span class="cell-meta neutral">
|
|
256
|
+
<Clock3 size={12} strokeWidth={1.9} />
|
|
257
|
+
{row.effort}u
|
|
258
|
+
</span>
|
|
259
|
+
<span class="cell-meta neutral">
|
|
260
|
+
<GitBranchPlus size={12} strokeWidth={1.9} />
|
|
261
|
+
{row.dependencyCount}
|
|
262
|
+
</span>
|
|
263
|
+
</div>
|
|
264
|
+
</div>
|
|
265
|
+
<a class={`task-title ${row.selectionState}`} data-title={row.title} title={row.title} href={timelineSelectionHref(row.taskId)}>
|
|
266
|
+
<span class="task-title-text">{row.title}</span>
|
|
267
|
+
</a>
|
|
268
|
+
<div class="spec-links">
|
|
269
|
+
{#each row.specIds as specId}
|
|
270
|
+
<a href={`/specs/${specId}`}>{specId}</a>
|
|
271
|
+
{/each}
|
|
272
|
+
</div>
|
|
273
|
+
</div>
|
|
274
|
+
</div>
|
|
275
|
+
|
|
276
|
+
<div class="row-grid" style={`--total:${totalUnits}`}>
|
|
277
|
+
<div class="bar-lane">
|
|
278
|
+
<a
|
|
279
|
+
class={`timeline-bar ${row.effectiveStatus} ${row.selectionState} ${row.archivedAt ? "archived" : ""}`}
|
|
280
|
+
href={timelineSelectionHref(row.taskId)}
|
|
281
|
+
style={`left:${(row.start / totalUnits) * 100}%; width:${Math.max(((row.end - row.start) / totalUnits) * 100, 2.4)}%`}
|
|
282
|
+
>
|
|
283
|
+
<span>{row.start}</span>
|
|
284
|
+
<span class="bar-fill"></span>
|
|
285
|
+
<span>{row.end}</span>
|
|
286
|
+
</a>
|
|
287
|
+
</div>
|
|
288
|
+
|
|
289
|
+
<div class="row-notes">
|
|
290
|
+
<span>
|
|
291
|
+
<ArrowRight size={12} strokeWidth={1.9} />
|
|
292
|
+
{row.start} -> {row.end}
|
|
293
|
+
</span>
|
|
294
|
+
{#if row.archivedAt}
|
|
295
|
+
<span class="note-archived">
|
|
296
|
+
<Archive size={12} strokeWidth={1.9} />
|
|
297
|
+
archived
|
|
298
|
+
</span>
|
|
299
|
+
{/if}
|
|
300
|
+
</div>
|
|
301
|
+
</div>
|
|
302
|
+
</div>
|
|
303
|
+
{/each}
|
|
304
|
+
{/if}
|
|
305
|
+
</section>
|
|
306
|
+
{/each}
|
|
307
|
+
</div>
|
|
308
|
+
{/if}
|
|
309
|
+
</section>
|
|
310
|
+
|
|
311
|
+
<style>
|
|
312
|
+
.view-header,
|
|
313
|
+
.mode-shell,
|
|
314
|
+
.planner-head,
|
|
315
|
+
.planner-row,
|
|
316
|
+
.group-head,
|
|
317
|
+
.mode-head,
|
|
318
|
+
.mode-toggle,
|
|
319
|
+
.pane-head,
|
|
320
|
+
.row-notes {
|
|
321
|
+
display: flex;
|
|
322
|
+
gap: 1rem;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
.header-copy,
|
|
326
|
+
.mode-copy,
|
|
327
|
+
.group-copy,
|
|
328
|
+
.task-copy,
|
|
329
|
+
.planner-body,
|
|
330
|
+
.group-shell {
|
|
331
|
+
display: grid;
|
|
332
|
+
gap: 0.35rem;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
.view-header {
|
|
336
|
+
justify-content: space-between;
|
|
337
|
+
align-items: end;
|
|
338
|
+
margin-bottom: 1rem;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
.eyebrow,
|
|
342
|
+
.group-id {
|
|
343
|
+
margin: 0 0 0.28rem;
|
|
344
|
+
text-transform: uppercase;
|
|
345
|
+
letter-spacing: 0.14em;
|
|
346
|
+
font-size: 0.68rem;
|
|
347
|
+
color: var(--muted);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
h3,
|
|
351
|
+
h4,
|
|
352
|
+
p {
|
|
353
|
+
margin: 0;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
h3,
|
|
357
|
+
h4 {
|
|
358
|
+
font-family: var(--display-font);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
h3 {
|
|
362
|
+
font-size: clamp(1.55rem, 1.8vw, 2rem);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
h4 {
|
|
366
|
+
font-size: 1.16rem;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
.intro,
|
|
370
|
+
.mode-copy p,
|
|
371
|
+
.timeline-empty,
|
|
372
|
+
.row-notes {
|
|
373
|
+
color: var(--muted);
|
|
374
|
+
line-height: 1.45;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
.mode-shell,
|
|
378
|
+
.selection-shell,
|
|
379
|
+
.timeline-shell {
|
|
380
|
+
margin-bottom: 1rem;
|
|
381
|
+
padding: 1rem;
|
|
382
|
+
border-radius: var(--radius-xl);
|
|
383
|
+
border: 1px solid var(--line);
|
|
384
|
+
background: var(--panel);
|
|
385
|
+
box-shadow: var(--shadow);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
.mode-shell {
|
|
389
|
+
justify-content: space-between;
|
|
390
|
+
align-items: center;
|
|
391
|
+
flex-wrap: wrap;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
.selection-shell,
|
|
395
|
+
.selection-specs,
|
|
396
|
+
.selection-spec-group {
|
|
397
|
+
display: grid;
|
|
398
|
+
gap: 0.8rem;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
.selection-shell {
|
|
402
|
+
background:
|
|
403
|
+
radial-gradient(circle at top right, rgba(70, 107, 202, 0.12), transparent 18rem),
|
|
404
|
+
linear-gradient(180deg, rgba(255, 253, 248, 0.96), rgba(244, 238, 229, 0.94));
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
.selection-head,
|
|
408
|
+
.selection-metrics {
|
|
409
|
+
display: flex;
|
|
410
|
+
gap: 0.7rem;
|
|
411
|
+
align-items: center;
|
|
412
|
+
justify-content: space-between;
|
|
413
|
+
flex-wrap: wrap;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
.selection-copy {
|
|
417
|
+
color: var(--muted);
|
|
418
|
+
line-height: 1.5;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
.icon-pill {
|
|
422
|
+
display: inline-flex;
|
|
423
|
+
align-items: center;
|
|
424
|
+
justify-content: center;
|
|
425
|
+
width: 2rem;
|
|
426
|
+
height: 2rem;
|
|
427
|
+
border-radius: 0.85rem;
|
|
428
|
+
border: 1px solid var(--line);
|
|
429
|
+
background: rgba(255, 255, 255, 0.84);
|
|
430
|
+
color: var(--muted-soft);
|
|
431
|
+
flex-shrink: 0;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
.selection-pill {
|
|
435
|
+
color: #3456a0;
|
|
436
|
+
border-color: rgba(70, 107, 202, 0.18);
|
|
437
|
+
background: rgba(70, 107, 202, 0.1);
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
.clear-selection {
|
|
441
|
+
display: inline-flex;
|
|
442
|
+
align-items: center;
|
|
443
|
+
gap: 0.38rem;
|
|
444
|
+
padding: 0.52rem 0.74rem;
|
|
445
|
+
border-radius: 999px;
|
|
446
|
+
text-decoration: none;
|
|
447
|
+
border: 1px solid rgba(24, 22, 18, 0.12);
|
|
448
|
+
background: rgba(255, 255, 255, 0.86);
|
|
449
|
+
color: var(--muted-soft);
|
|
450
|
+
box-shadow: var(--shadow-soft);
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
.mode-toggle {
|
|
454
|
+
flex-wrap: wrap;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
.mode-toggle a {
|
|
458
|
+
display: inline-flex;
|
|
459
|
+
align-items: center;
|
|
460
|
+
gap: 0.45rem;
|
|
461
|
+
padding: 0.68rem 0.9rem;
|
|
462
|
+
border-radius: 999px;
|
|
463
|
+
text-decoration: none;
|
|
464
|
+
border: 1px solid var(--line);
|
|
465
|
+
background: rgba(255, 255, 255, 0.84);
|
|
466
|
+
box-shadow: var(--shadow-soft);
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
.mode-toggle a.active {
|
|
470
|
+
border-color: rgba(15, 141, 96, 0.22);
|
|
471
|
+
background: rgba(15, 141, 96, 0.1);
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
.timeline-empty {
|
|
475
|
+
display: inline-flex;
|
|
476
|
+
align-items: center;
|
|
477
|
+
gap: 0.5rem;
|
|
478
|
+
padding: 0.9rem 1rem;
|
|
479
|
+
border-radius: var(--radius-lg);
|
|
480
|
+
border: 1px dashed var(--line-strong);
|
|
481
|
+
background: rgba(255, 255, 255, 0.62);
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
.planner-head,
|
|
485
|
+
.planner-row {
|
|
486
|
+
min-width: 68rem;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
.empty-group {
|
|
490
|
+
display: flex;
|
|
491
|
+
min-width: 68rem;
|
|
492
|
+
border-bottom: 1px solid rgba(24, 22, 18, 0.06);
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
.planner-head {
|
|
496
|
+
position: sticky;
|
|
497
|
+
top: 0;
|
|
498
|
+
z-index: 2;
|
|
499
|
+
background: rgba(247, 241, 232, 0.92);
|
|
500
|
+
border-bottom: 1px solid var(--line);
|
|
501
|
+
backdrop-filter: blur(12px);
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
.sticky-pane {
|
|
505
|
+
width: 24rem;
|
|
506
|
+
min-width: 24rem;
|
|
507
|
+
flex-shrink: 0;
|
|
508
|
+
background: rgba(250, 245, 238, 0.96);
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
.pane-head,
|
|
512
|
+
.group-head,
|
|
513
|
+
.empty-group-label {
|
|
514
|
+
padding: 0.72rem 0.8rem;
|
|
515
|
+
border-right: 1px solid var(--line);
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
.group-head,
|
|
519
|
+
.empty-group-label {
|
|
520
|
+
align-items: flex-start;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
.pane-head {
|
|
524
|
+
align-items: center;
|
|
525
|
+
color: var(--muted);
|
|
526
|
+
font-size: 0.75rem;
|
|
527
|
+
text-transform: uppercase;
|
|
528
|
+
letter-spacing: 0.12em;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
.grid-head {
|
|
532
|
+
display: grid;
|
|
533
|
+
grid-template-columns: repeat(var(--total), minmax(2.2rem, 1fr));
|
|
534
|
+
gap: 0;
|
|
535
|
+
align-items: center;
|
|
536
|
+
flex: 1;
|
|
537
|
+
padding: 0.72rem 0;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
.grid-head span {
|
|
541
|
+
display: inline-flex;
|
|
542
|
+
justify-content: center;
|
|
543
|
+
color: var(--muted);
|
|
544
|
+
font-size: 0.72rem;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
.timeline-shell {
|
|
548
|
+
overflow: auto;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
.planner-body {
|
|
552
|
+
gap: 0;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
.group-shell {
|
|
556
|
+
gap: 0;
|
|
557
|
+
border-bottom: 1px solid rgba(24, 22, 18, 0.08);
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
.group-head {
|
|
561
|
+
padding-top: 1rem;
|
|
562
|
+
padding-bottom: 0.9rem;
|
|
563
|
+
border-bottom: 1px solid rgba(24, 22, 18, 0.08);
|
|
564
|
+
background: linear-gradient(180deg, rgba(255, 254, 250, 0.98), rgba(245, 238, 227, 0.94));
|
|
565
|
+
box-shadow: inset 0 -1px 0 rgba(255, 255, 255, 0.5);
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
.group-head.selected {
|
|
569
|
+
background:
|
|
570
|
+
linear-gradient(180deg, rgba(234, 248, 241, 0.98), rgba(228, 243, 236, 0.96));
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
.group-head.related_direct {
|
|
574
|
+
background:
|
|
575
|
+
linear-gradient(180deg, rgba(242, 247, 255, 0.98), rgba(232, 241, 255, 0.96));
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
.group-head.related_transitive {
|
|
579
|
+
background:
|
|
580
|
+
linear-gradient(180deg, rgba(247, 249, 255, 0.98), rgba(239, 244, 255, 0.95));
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
.group-topline,
|
|
584
|
+
.row-topline,
|
|
585
|
+
.row-label,
|
|
586
|
+
.group-meta {
|
|
587
|
+
display: flex;
|
|
588
|
+
align-items: flex-start;
|
|
589
|
+
justify-content: space-between;
|
|
590
|
+
gap: 0.7rem;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
.group-topline,
|
|
594
|
+
.row-topline {
|
|
595
|
+
width: 100%;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
.group-meta,
|
|
599
|
+
.row-meta-pills {
|
|
600
|
+
display: flex;
|
|
601
|
+
flex-wrap: wrap;
|
|
602
|
+
justify-content: flex-end;
|
|
603
|
+
gap: 0.38rem;
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
.group-copy a,
|
|
607
|
+
.task-id,
|
|
608
|
+
.spec-links a {
|
|
609
|
+
text-decoration: none;
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
.group-copy a:hover,
|
|
613
|
+
.task-id:hover,
|
|
614
|
+
.spec-links a:hover {
|
|
615
|
+
color: var(--accent);
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
.mini-pill,
|
|
619
|
+
.status-pill,
|
|
620
|
+
.cell-meta {
|
|
621
|
+
display: inline-flex;
|
|
622
|
+
align-items: center;
|
|
623
|
+
gap: 0.3rem;
|
|
624
|
+
border-radius: 999px;
|
|
625
|
+
padding: 0.18rem 0.48rem;
|
|
626
|
+
border: 1px solid var(--line);
|
|
627
|
+
background: rgba(255, 255, 255, 0.86);
|
|
628
|
+
box-shadow:
|
|
629
|
+
0 0 0 1px rgba(255, 255, 255, 0.34) inset,
|
|
630
|
+
var(--status-glow, var(--shadow-soft));
|
|
631
|
+
font-size: 0.71rem;
|
|
632
|
+
line-height: 1.1;
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
.mini-pill.neutral,
|
|
636
|
+
.cell-meta.neutral {
|
|
637
|
+
border-color: rgba(24, 22, 18, 0.1);
|
|
638
|
+
background: rgba(255, 255, 255, 0.8);
|
|
639
|
+
--status-glow: 0 10px 20px rgba(24, 22, 18, 0.05);
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
.mini-pill.selected-pill {
|
|
643
|
+
background: rgba(15, 141, 96, 0.12);
|
|
644
|
+
border-color: rgba(15, 141, 96, 0.22);
|
|
645
|
+
color: #0d6e4b;
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
.mini-pill.spec-direct,
|
|
649
|
+
.cell-meta.spec-direct {
|
|
650
|
+
background: rgba(70, 107, 202, 0.12);
|
|
651
|
+
border-color: rgba(70, 107, 202, 0.22);
|
|
652
|
+
color: #3456a0;
|
|
653
|
+
--status-glow: 0 0 0 1px rgba(255, 255, 255, 0.34) inset, 0 0 18px rgba(70, 107, 202, 0.14);
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
.mini-pill.spec-transitive {
|
|
657
|
+
background: rgba(70, 107, 202, 0.08);
|
|
658
|
+
border-color: rgba(70, 107, 202, 0.16);
|
|
659
|
+
color: #5570ad;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
.cell-meta.dependency {
|
|
663
|
+
background: rgba(70, 107, 202, 0.12);
|
|
664
|
+
border-color: rgba(70, 107, 202, 0.22);
|
|
665
|
+
color: #3456a0;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
.cell-meta.dependency-soft {
|
|
669
|
+
background: rgba(70, 107, 202, 0.07);
|
|
670
|
+
border-color: rgba(70, 107, 202, 0.14);
|
|
671
|
+
color: #5570ad;
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
.cell-meta.dependent {
|
|
675
|
+
background: rgba(143, 84, 33, 0.12);
|
|
676
|
+
border-color: rgba(143, 84, 33, 0.22);
|
|
677
|
+
color: #8f5421;
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
.cell-meta.dependent-soft {
|
|
681
|
+
background: rgba(143, 84, 33, 0.07);
|
|
682
|
+
border-color: rgba(143, 84, 33, 0.14);
|
|
683
|
+
color: #9b7147;
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
.cell-meta.blocked {
|
|
687
|
+
background: rgba(151, 45, 45, 0.12);
|
|
688
|
+
border-color: rgba(151, 45, 45, 0.22);
|
|
689
|
+
color: #8d2d2d;
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
.cell-meta.blocked-soft {
|
|
693
|
+
background: rgba(151, 45, 45, 0.08);
|
|
694
|
+
border-color: rgba(151, 45, 45, 0.16);
|
|
695
|
+
color: #9b5b5b;
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
.planner-row {
|
|
699
|
+
align-items: stretch;
|
|
700
|
+
border-bottom: 1px solid rgba(24, 22, 18, 0.06);
|
|
701
|
+
transition: opacity 140ms ease;
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
.planner-row.dimmed {
|
|
705
|
+
opacity: 0.38;
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
.empty-group-copy {
|
|
709
|
+
display: inline-flex;
|
|
710
|
+
align-items: center;
|
|
711
|
+
padding: 0 0.8rem;
|
|
712
|
+
color: var(--muted);
|
|
713
|
+
font-size: 0.78rem;
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
.empty-group-copy span {
|
|
717
|
+
display: inline-flex;
|
|
718
|
+
align-items: center;
|
|
719
|
+
gap: 0.35rem;
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
.row-label {
|
|
723
|
+
display: block;
|
|
724
|
+
min-height: 3.35rem;
|
|
725
|
+
padding: 0.72rem 0.95rem 0.72rem 0.85rem;
|
|
726
|
+
transition:
|
|
727
|
+
background 140ms ease,
|
|
728
|
+
box-shadow 140ms ease,
|
|
729
|
+
opacity 140ms ease;
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
.row-label.selected {
|
|
733
|
+
background: rgba(15, 141, 96, 0.1);
|
|
734
|
+
box-shadow: inset -2px 0 0 rgba(15, 141, 96, 0.22);
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
.row-label.dependency,
|
|
738
|
+
.row-label.dependency_transitive {
|
|
739
|
+
background: rgba(70, 107, 202, 0.08);
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
.row-label.dependent,
|
|
743
|
+
.row-label.dependent_transitive {
|
|
744
|
+
background: rgba(143, 84, 33, 0.07);
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
.row-label.blocked_dependent,
|
|
748
|
+
.row-label.blocked_dependent_transitive {
|
|
749
|
+
background: rgba(151, 45, 45, 0.07);
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
.task-copy {
|
|
753
|
+
min-width: 0;
|
|
754
|
+
width: 100%;
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
.task-id {
|
|
758
|
+
display: inline-flex;
|
|
759
|
+
align-items: center;
|
|
760
|
+
gap: 0.32rem;
|
|
761
|
+
color: var(--muted-soft);
|
|
762
|
+
font-size: 0.76rem;
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
.task-title {
|
|
766
|
+
display: block;
|
|
767
|
+
position: relative;
|
|
768
|
+
cursor: pointer;
|
|
769
|
+
min-width: 0;
|
|
770
|
+
max-width: 100%;
|
|
771
|
+
font-family: var(--body-font);
|
|
772
|
+
font-size: 0.92rem;
|
|
773
|
+
font-weight: 600;
|
|
774
|
+
line-height: 1.25;
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
.task-title-text {
|
|
778
|
+
display: block;
|
|
779
|
+
max-width: 100%;
|
|
780
|
+
white-space: nowrap;
|
|
781
|
+
overflow: hidden;
|
|
782
|
+
text-overflow: ellipsis;
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
.task-title.selected {
|
|
786
|
+
color: #0d6e4b;
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
.task-title.dependency,
|
|
790
|
+
.task-title.dependency_transitive {
|
|
791
|
+
color: #3456a0;
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
.task-title.dependent,
|
|
795
|
+
.task-title.dependent_transitive {
|
|
796
|
+
color: #8f5421;
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
.task-title.blocked_dependent,
|
|
800
|
+
.task-title.blocked_dependent_transitive {
|
|
801
|
+
color: #8d2d2d;
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
.task-title::after {
|
|
805
|
+
content: attr(data-title);
|
|
806
|
+
position: absolute;
|
|
807
|
+
left: 0;
|
|
808
|
+
top: calc(100% + 0.45rem);
|
|
809
|
+
z-index: 6;
|
|
810
|
+
width: max-content;
|
|
811
|
+
max-width: min(28rem, 72vw);
|
|
812
|
+
padding: 0.55rem 0.7rem;
|
|
813
|
+
border-radius: 0.85rem;
|
|
814
|
+
border: 1px solid rgba(24, 22, 18, 0.14);
|
|
815
|
+
background: rgba(255, 252, 247, 0.98);
|
|
816
|
+
box-shadow:
|
|
817
|
+
0 0 0 1px rgba(255, 255, 255, 0.5) inset,
|
|
818
|
+
0 18px 40px rgba(24, 22, 18, 0.14);
|
|
819
|
+
color: var(--ink);
|
|
820
|
+
font-size: 0.82rem;
|
|
821
|
+
font-weight: 500;
|
|
822
|
+
line-height: 1.35;
|
|
823
|
+
white-space: normal;
|
|
824
|
+
opacity: 0;
|
|
825
|
+
pointer-events: none;
|
|
826
|
+
transform: translateY(-0.15rem);
|
|
827
|
+
transition:
|
|
828
|
+
opacity 120ms ease,
|
|
829
|
+
transform 120ms ease;
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
.task-title:hover::after {
|
|
833
|
+
opacity: 1;
|
|
834
|
+
transform: translateY(0);
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
.spec-links {
|
|
838
|
+
display: flex;
|
|
839
|
+
flex-wrap: wrap;
|
|
840
|
+
gap: 0.38rem;
|
|
841
|
+
margin-top: 0.2rem;
|
|
842
|
+
font-size: 0.74rem;
|
|
843
|
+
color: var(--muted);
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
.status-pill {
|
|
847
|
+
box-shadow:
|
|
848
|
+
0 0 0 1px rgba(255, 255, 255, 0.34) inset,
|
|
849
|
+
var(--status-glow, 0 10px 22px rgba(24, 22, 18, 0.05));
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
.mini-pill.status.active,
|
|
853
|
+
.status-pill.in_progress {
|
|
854
|
+
background: rgba(15, 141, 96, 0.14);
|
|
855
|
+
border-color: rgba(15, 141, 96, 0.22);
|
|
856
|
+
color: #0d6e4b;
|
|
857
|
+
--status-glow: 0 0 0 1px rgba(255, 255, 255, 0.34) inset, 0 0 18px rgba(15, 141, 96, 0.16);
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
.mini-pill.status.proposed {
|
|
861
|
+
background: rgba(70, 107, 202, 0.12);
|
|
862
|
+
border-color: rgba(70, 107, 202, 0.2);
|
|
863
|
+
color: #3456a0;
|
|
864
|
+
--status-glow: 0 0 0 1px rgba(255, 255, 255, 0.34) inset, 0 0 18px rgba(70, 107, 202, 0.14);
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
.mini-pill.status.paused {
|
|
868
|
+
background: rgba(125, 96, 58, 0.14);
|
|
869
|
+
border-color: rgba(125, 96, 58, 0.22);
|
|
870
|
+
color: #755733;
|
|
871
|
+
--status-glow: 0 0 0 1px rgba(255, 255, 255, 0.34) inset, 0 0 18px rgba(125, 96, 58, 0.14);
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
.mini-pill.status.done,
|
|
875
|
+
.status-pill.done {
|
|
876
|
+
background: rgba(17, 122, 84, 0.12);
|
|
877
|
+
border-color: rgba(17, 122, 84, 0.18);
|
|
878
|
+
color: #0c6d4a;
|
|
879
|
+
--status-glow: 0 0 0 1px rgba(255, 255, 255, 0.34) inset, 0 0 16px rgba(17, 122, 84, 0.12);
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
.mini-pill.status.archived,
|
|
883
|
+
.status-pill.cancelled {
|
|
884
|
+
background: rgba(117, 92, 58, 0.14);
|
|
885
|
+
border-color: rgba(117, 92, 58, 0.18);
|
|
886
|
+
color: #6e5434;
|
|
887
|
+
--status-glow: 0 0 0 1px rgba(255, 255, 255, 0.34) inset, 0 0 16px rgba(117, 92, 58, 0.12);
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
.status-pill.review {
|
|
891
|
+
background: rgba(143, 84, 33, 0.14);
|
|
892
|
+
border-color: rgba(143, 84, 33, 0.22);
|
|
893
|
+
color: #8f5421;
|
|
894
|
+
--status-glow: 0 0 0 1px rgba(255, 255, 255, 0.34) inset, 0 0 18px rgba(143, 84, 33, 0.16);
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
.status-pill.blocked {
|
|
898
|
+
background: rgba(151, 45, 45, 0.12);
|
|
899
|
+
border-color: rgba(151, 45, 45, 0.22);
|
|
900
|
+
color: #8d2d2d;
|
|
901
|
+
--status-glow: 0 0 0 1px rgba(255, 255, 255, 0.34) inset, 0 0 18px rgba(151, 45, 45, 0.16);
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
.status-pill.todo {
|
|
905
|
+
background: rgba(84, 78, 67, 0.1);
|
|
906
|
+
border-color: rgba(84, 78, 67, 0.14);
|
|
907
|
+
color: #5d5549;
|
|
908
|
+
--status-glow: 0 0 0 1px rgba(255, 255, 255, 0.34) inset, 0 0 14px rgba(84, 78, 67, 0.08);
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
.status-pill.done,
|
|
912
|
+
.status-pill.cancelled {
|
|
913
|
+
opacity: 0.92;
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
.row-grid {
|
|
917
|
+
position: relative;
|
|
918
|
+
display: grid;
|
|
919
|
+
align-items: center;
|
|
920
|
+
grid-template-columns: 1fr auto;
|
|
921
|
+
gap: 0.75rem;
|
|
922
|
+
min-height: 3.35rem;
|
|
923
|
+
padding-right: 0.8rem;
|
|
924
|
+
flex: 1;
|
|
925
|
+
background:
|
|
926
|
+
linear-gradient(90deg, rgba(24, 22, 18, 0.05) 1px, transparent 1px),
|
|
927
|
+
rgba(255, 255, 255, 0.66);
|
|
928
|
+
background-size: calc(100% / var(--total)) 100%;
|
|
929
|
+
transition:
|
|
930
|
+
background 140ms ease,
|
|
931
|
+
opacity 140ms ease;
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
.planner-row.selected .row-grid {
|
|
935
|
+
background:
|
|
936
|
+
linear-gradient(90deg, rgba(15, 141, 96, 0.07) 1px, transparent 1px),
|
|
937
|
+
rgba(242, 251, 246, 0.8);
|
|
938
|
+
background-size: calc(100% / var(--total)) 100%;
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
.planner-row.dependency .row-grid,
|
|
942
|
+
.planner-row.dependency_transitive .row-grid {
|
|
943
|
+
background:
|
|
944
|
+
linear-gradient(90deg, rgba(70, 107, 202, 0.06) 1px, transparent 1px),
|
|
945
|
+
rgba(245, 248, 255, 0.78);
|
|
946
|
+
background-size: calc(100% / var(--total)) 100%;
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
.planner-row.dependent .row-grid,
|
|
950
|
+
.planner-row.dependent_transitive .row-grid {
|
|
951
|
+
background:
|
|
952
|
+
linear-gradient(90deg, rgba(143, 84, 33, 0.05) 1px, transparent 1px),
|
|
953
|
+
rgba(255, 248, 241, 0.8);
|
|
954
|
+
background-size: calc(100% / var(--total)) 100%;
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
.planner-row.blocked_dependent .row-grid,
|
|
958
|
+
.planner-row.blocked_dependent_transitive .row-grid {
|
|
959
|
+
background:
|
|
960
|
+
linear-gradient(90deg, rgba(151, 45, 45, 0.05) 1px, transparent 1px),
|
|
961
|
+
rgba(255, 246, 246, 0.8);
|
|
962
|
+
background-size: calc(100% / var(--total)) 100%;
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
.bar-lane {
|
|
966
|
+
position: relative;
|
|
967
|
+
height: 100%;
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
.timeline-bar {
|
|
971
|
+
position: absolute;
|
|
972
|
+
top: 50%;
|
|
973
|
+
transform: translateY(-50%);
|
|
974
|
+
height: 1.05rem;
|
|
975
|
+
display: inline-flex;
|
|
976
|
+
align-items: center;
|
|
977
|
+
gap: 0.35rem;
|
|
978
|
+
padding: 0 0.38rem;
|
|
979
|
+
border-radius: 999px;
|
|
980
|
+
border: 1px solid rgba(24, 22, 18, 0.12);
|
|
981
|
+
background: rgba(24, 22, 18, 0.12);
|
|
982
|
+
box-shadow: var(--shadow-soft);
|
|
983
|
+
font-size: 0.68rem;
|
|
984
|
+
white-space: nowrap;
|
|
985
|
+
text-decoration: none;
|
|
986
|
+
color: inherit;
|
|
987
|
+
transition:
|
|
988
|
+
opacity 140ms ease,
|
|
989
|
+
transform 140ms ease,
|
|
990
|
+
box-shadow 140ms ease,
|
|
991
|
+
border-color 140ms ease;
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
.timeline-bar .bar-fill {
|
|
995
|
+
flex: 1;
|
|
996
|
+
min-width: 1rem;
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
.timeline-bar.in_progress {
|
|
1000
|
+
background: rgba(15, 141, 96, 0.2);
|
|
1001
|
+
border-color: rgba(15, 141, 96, 0.25);
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
.timeline-bar.review {
|
|
1005
|
+
background: rgba(143, 84, 33, 0.18);
|
|
1006
|
+
border-color: rgba(143, 84, 33, 0.24);
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
.timeline-bar.blocked {
|
|
1010
|
+
background: rgba(151, 45, 45, 0.16);
|
|
1011
|
+
border-color: rgba(151, 45, 45, 0.24);
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
.timeline-bar.done,
|
|
1015
|
+
.timeline-bar.cancelled {
|
|
1016
|
+
opacity: 0.6;
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
.timeline-bar.archived {
|
|
1020
|
+
box-shadow: inset 0 0 0 1px rgba(143, 84, 33, 0.15), var(--shadow-soft);
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
.timeline-bar.selected {
|
|
1024
|
+
transform: translateY(-50%) scaleY(1.08);
|
|
1025
|
+
border-color: rgba(15, 141, 96, 0.34);
|
|
1026
|
+
box-shadow: 0 0 0 1px rgba(15, 141, 96, 0.14), 0 18px 28px rgba(15, 141, 96, 0.18);
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
.timeline-bar.dependency {
|
|
1030
|
+
background: rgba(70, 107, 202, 0.2);
|
|
1031
|
+
border-color: rgba(70, 107, 202, 0.28);
|
|
1032
|
+
box-shadow: 0 14px 24px rgba(70, 107, 202, 0.12);
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
.timeline-bar.dependency_transitive {
|
|
1036
|
+
background: rgba(70, 107, 202, 0.12);
|
|
1037
|
+
border-color: rgba(70, 107, 202, 0.18);
|
|
1038
|
+
box-shadow: 0 12px 20px rgba(70, 107, 202, 0.08);
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
.timeline-bar.dependent {
|
|
1042
|
+
background: rgba(143, 84, 33, 0.18);
|
|
1043
|
+
border-color: rgba(143, 84, 33, 0.26);
|
|
1044
|
+
box-shadow: 0 14px 24px rgba(143, 84, 33, 0.12);
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
.timeline-bar.dependent_transitive {
|
|
1048
|
+
background: rgba(143, 84, 33, 0.11);
|
|
1049
|
+
border-color: rgba(143, 84, 33, 0.18);
|
|
1050
|
+
box-shadow: 0 12px 20px rgba(143, 84, 33, 0.08);
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
.timeline-bar.blocked_dependent {
|
|
1054
|
+
background: rgba(151, 45, 45, 0.18);
|
|
1055
|
+
border-color: rgba(151, 45, 45, 0.28);
|
|
1056
|
+
box-shadow: 0 14px 24px rgba(151, 45, 45, 0.12);
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
.timeline-bar.blocked_dependent_transitive {
|
|
1060
|
+
background: rgba(151, 45, 45, 0.11);
|
|
1061
|
+
border-color: rgba(151, 45, 45, 0.18);
|
|
1062
|
+
box-shadow: 0 12px 20px rgba(151, 45, 45, 0.08);
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
.timeline-bar.dimmed {
|
|
1066
|
+
opacity: 0.38;
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
.row-notes {
|
|
1070
|
+
align-items: center;
|
|
1071
|
+
color: var(--muted);
|
|
1072
|
+
font-size: 0.74rem;
|
|
1073
|
+
white-space: nowrap;
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1076
|
+
.row-notes span {
|
|
1077
|
+
display: inline-flex;
|
|
1078
|
+
align-items: center;
|
|
1079
|
+
gap: 0.28rem;
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1082
|
+
.note-archived {
|
|
1083
|
+
color: var(--warning);
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
@media (max-width: 980px) {
|
|
1087
|
+
.view-header,
|
|
1088
|
+
.mode-shell {
|
|
1089
|
+
flex-direction: column;
|
|
1090
|
+
align-items: start;
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
</style>
|