avtc-pi-featyard 1.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.
Files changed (153) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +194 -0
  3. package/agents/fy-design-reviewer.md +77 -0
  4. package/agents/fy-feature-verifier.md +24 -0
  5. package/agents/fy-general-reviewer.md +81 -0
  6. package/agents/fy-guidelines-reviewer.md +46 -0
  7. package/agents/fy-implementer.md +20 -0
  8. package/agents/fy-performance-reviewer.md +46 -0
  9. package/agents/fy-plan-reviewer.md +74 -0
  10. package/agents/fy-plan-verifier.md +44 -0
  11. package/agents/fy-quality-reviewer.md +50 -0
  12. package/agents/fy-requirements-reviewer.md +46 -0
  13. package/agents/fy-researcher.md +6 -0
  14. package/agents/fy-security-reviewer.md +46 -0
  15. package/agents/fy-task-verifier.md +42 -0
  16. package/agents/fy-testing-reviewer.md +60 -0
  17. package/assets/images/kanban-board.png +0 -0
  18. package/assets/images/settings-dropdown.png +0 -0
  19. package/assets/images/settings.png +0 -0
  20. package/assets/images/widget.png +0 -0
  21. package/docs/CONFIGURATION.md +266 -0
  22. package/index.ts +8 -0
  23. package/package.json +85 -0
  24. package/skills/fy-design/SKILL.md +108 -0
  25. package/skills/fy-design-review/SKILL.md +45 -0
  26. package/skills/fy-finish/SKILL.md +28 -0
  27. package/skills/fy-implement/SKILL.md +36 -0
  28. package/skills/fy-plan/SKILL.md +77 -0
  29. package/skills/fy-plan-review/SKILL.md +45 -0
  30. package/skills/fy-research/SKILL.md +38 -0
  31. package/skills/fy-review/SKILL.md +88 -0
  32. package/skills/fy-verify/SKILL.md +23 -0
  33. package/src/commands/auto-agent-commands.ts +748 -0
  34. package/src/commands/kanban-commands.ts +278 -0
  35. package/src/commands/workflow-commands.ts +531 -0
  36. package/src/compaction/compact-handler.ts +371 -0
  37. package/src/compaction/compact-message.ts +52 -0
  38. package/src/compaction/compact-trigger.ts +121 -0
  39. package/src/compaction/safe-editor-write.ts +18 -0
  40. package/src/events/agent/agent-end.ts +19 -0
  41. package/src/events/agent/agent-settled.ts +20 -0
  42. package/src/events/agent/agent-start.ts +18 -0
  43. package/src/events/agent/turn-end.ts +20 -0
  44. package/src/events/agent/turn-start.ts +19 -0
  45. package/src/events/event-deps.ts +33 -0
  46. package/src/events/index.ts +91 -0
  47. package/src/events/input/input.ts +143 -0
  48. package/src/events/session/context.ts +68 -0
  49. package/src/events/session/model-select.ts +20 -0
  50. package/src/events/session/session-compact.ts +20 -0
  51. package/src/events/session/session-shutdown.ts +26 -0
  52. package/src/events/session/session-start.ts +45 -0
  53. package/src/events/session/session-tree.ts +17 -0
  54. package/src/events/tool/tool-call.ts +58 -0
  55. package/src/events/tool/tool-result.ts +54 -0
  56. package/src/git/git-queries.ts +154 -0
  57. package/src/git/resolve-base-branch.ts +173 -0
  58. package/src/git/worktrees/worktree-helpers.ts +142 -0
  59. package/src/git/worktrees/worktree-interception.ts +66 -0
  60. package/src/git/worktrees/worktree-lifecycle.ts +380 -0
  61. package/src/guardrails/completion-gating.ts +63 -0
  62. package/src/guardrails/file-classifier.ts +461 -0
  63. package/src/guardrails/force-add-guard.ts +312 -0
  64. package/src/guardrails/guardrail-tracker.ts +73 -0
  65. package/src/guardrails/guardrail-violations.ts +47 -0
  66. package/src/guardrails/guardrails-engine.ts +663 -0
  67. package/src/guardrails/session-guardrails.ts +75 -0
  68. package/src/guardrails/shell-decompose.ts +285 -0
  69. package/src/guardrails/tdd-enforcement.ts +122 -0
  70. package/src/guardrails/test-output.ts +272 -0
  71. package/src/index.ts +598 -0
  72. package/src/integrations/parallel-work-guardrail-integration.ts +29 -0
  73. package/src/integrations/subagent-integration.ts +166 -0
  74. package/src/integrations/todo-integration.ts +58 -0
  75. package/src/kanban/auto-agent/auto-agent-cleanup.ts +37 -0
  76. package/src/kanban/auto-agent/auto-agent-events.ts +142 -0
  77. package/src/kanban/auto-agent/auto-agent-grace-period.ts +83 -0
  78. package/src/kanban/auto-agent/auto-agent-lifecycle.ts +497 -0
  79. package/src/kanban/auto-agent/auto-agent-notify.ts +43 -0
  80. package/src/kanban/auto-agent/auto-agent-pause.ts +44 -0
  81. package/src/kanban/auto-agent/auto-agent-state-machine.ts +629 -0
  82. package/src/kanban/data/kanban-database.ts +851 -0
  83. package/src/kanban/data/kanban-db-schema.ts +137 -0
  84. package/src/kanban/data/kanban-detect-project.ts +43 -0
  85. package/src/kanban/data/kanban-move-feature.ts +43 -0
  86. package/src/kanban/data/kanban-types.ts +64 -0
  87. package/src/kanban/ensure-feature.ts +226 -0
  88. package/src/kanban/kanban-board-ui/app.js +1125 -0
  89. package/src/kanban/kanban-board-ui/csv-parser.d.ts +5 -0
  90. package/src/kanban/kanban-board-ui/csv-parser.js +80 -0
  91. package/src/kanban/kanban-board-ui/index.html +127 -0
  92. package/src/kanban/kanban-board-ui/style.css +820 -0
  93. package/src/kanban/kanban-bridge.ts +216 -0
  94. package/src/kanban/kanban-context.ts +43 -0
  95. package/src/kanban/kanban-events.ts +34 -0
  96. package/src/kanban/kanban-generate-title.ts +259 -0
  97. package/src/kanban/kanban-generate-topic.ts +170 -0
  98. package/src/kanban/kanban-operations.ts +170 -0
  99. package/src/kanban/kanban-server.ts +931 -0
  100. package/src/kanban/kanban-turn-handlers.ts +55 -0
  101. package/src/kanban/model-capture.ts +34 -0
  102. package/src/log.ts +47 -0
  103. package/src/phases/env-sync.ts +64 -0
  104. package/src/phases/execution-mode.ts +79 -0
  105. package/src/phases/implement-to-verify.ts +31 -0
  106. package/src/phases/phase-progression.ts +249 -0
  107. package/src/phases/phase-transitions.ts +226 -0
  108. package/src/phases/workflow-router.ts +98 -0
  109. package/src/prompts/finish-instructions.ts +143 -0
  110. package/src/prompts/skill-block-builder.ts +73 -0
  111. package/src/prompts/skill-expansion.ts +262 -0
  112. package/src/prompts/task-gate-skill.ts +83 -0
  113. package/src/prompts/template-engine.ts +433 -0
  114. package/src/prompts/text-blocks.ts +279 -0
  115. package/src/review/review-context.ts +56 -0
  116. package/src/review/review-counter.ts +66 -0
  117. package/src/review/review-empty-loop-tracking.ts +52 -0
  118. package/src/review/review-loops.ts +217 -0
  119. package/src/review/review-report.ts +101 -0
  120. package/src/settings/model-overrides.ts +269 -0
  121. package/src/settings/settings-schema.ts +458 -0
  122. package/src/settings/settings-types.ts +81 -0
  123. package/src/settings/settings-ui.ts +222 -0
  124. package/src/shared/errors.ts +24 -0
  125. package/src/shared/global.d.ts +22 -0
  126. package/src/shared/session-entries.ts +24 -0
  127. package/src/shared/types.ts +195 -0
  128. package/src/shared/workflow-refs.ts +253 -0
  129. package/src/shared/workflow-types.ts +180 -0
  130. package/src/snippets/vendored/subscribe-to-dialog-coordinator.ts +98 -0
  131. package/src/snippets/vendored/subscribe-to-notifications.ts +150 -0
  132. package/src/snippets/vendored/subscribe-to-parallel-work-guardrail.ts +35 -0
  133. package/src/snippets/vendored/subscribe-to-subagent.ts +67 -0
  134. package/src/snippets/vendored/subscribe-to-todo.ts +63 -0
  135. package/src/state/archive-artifacts.ts +602 -0
  136. package/src/state/artifact-junction.ts +462 -0
  137. package/src/state/artifact-paths.ts +230 -0
  138. package/src/state/feature-activation.ts +239 -0
  139. package/src/state/feature-management.ts +325 -0
  140. package/src/state/feature-record-store.ts +39 -0
  141. package/src/state/feature-session.ts +263 -0
  142. package/src/state/feature-state.ts +439 -0
  143. package/src/state/post-turn-dispatch.ts +106 -0
  144. package/src/state/session-lifecycle.ts +346 -0
  145. package/src/state/state-persistence.ts +122 -0
  146. package/src/state/worth-notes.ts +89 -0
  147. package/src/tools/add-to-backlog.ts +117 -0
  148. package/src/tools/phase-ready.ts +742 -0
  149. package/src/tools/task-ready-advance.ts +235 -0
  150. package/src/tools/text-result.ts +15 -0
  151. package/src/ui/featyard-widget.ts +250 -0
  152. package/src/ui/manage-features-dialog.ts +246 -0
  153. package/src/ui/select-dialog.ts +27 -0
@@ -0,0 +1,820 @@
1
+ :root {
2
+ --lane-backlog: #6b7280;
3
+ --lane-design: #8b5cf6;
4
+ --lane-design-approval: #f59e0b;
5
+ --lane-ready: #3b82f6;
6
+ --lane-in-progress: #10b981;
7
+ --lane-uat: #ec4899;
8
+ --lane-done: #6366f1;
9
+ }
10
+
11
+ * {
12
+ margin: 0;
13
+ padding: 0;
14
+ box-sizing: border-box;
15
+ }
16
+
17
+ body {
18
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
19
+ background: #0f172a;
20
+ color: #e2e8f0;
21
+ min-height: 100vh;
22
+ }
23
+
24
+ #app {
25
+ display: flex;
26
+ flex-direction: column;
27
+ height: 100vh;
28
+ }
29
+
30
+ header {
31
+ display: flex;
32
+ align-items: center;
33
+ justify-content: space-between;
34
+ padding: 12px 20px;
35
+ background: #1e293b;
36
+ border-bottom: 1px solid #334155;
37
+ }
38
+
39
+ header h1 {
40
+ font-size: 1.2rem;
41
+ font-weight: 600;
42
+ }
43
+
44
+ .controls {
45
+ display: flex;
46
+ gap: 8px;
47
+ align-items: center;
48
+ position: relative;
49
+ }
50
+
51
+ #project-select {
52
+ padding: 6px 10px;
53
+ background: #334155;
54
+ color: #e2e8f0;
55
+ border: 1px solid #475569;
56
+ border-radius: 4px;
57
+ font-size: 0.9rem;
58
+ }
59
+
60
+ #refresh-btn {
61
+ padding: 6px 12px;
62
+ background: #334155;
63
+ color: #e2e8f0;
64
+ border: 1px solid #475569;
65
+ border-radius: 4px;
66
+ cursor: pointer;
67
+ font-size: 1rem;
68
+ }
69
+
70
+ #refresh-btn:hover {
71
+ background: #475569;
72
+ }
73
+
74
+ #board {
75
+ display: flex;
76
+ gap: 12px;
77
+ padding: 16px;
78
+ flex: 1;
79
+ overflow-x: auto;
80
+ }
81
+
82
+ .lane {
83
+ min-width: 140px;
84
+ flex: 1 1 0;
85
+ display: flex;
86
+ flex-direction: column;
87
+ background: #1e293b;
88
+ border-radius: 8px;
89
+ border-top: 3px solid var(--lane-color, #475569);
90
+ }
91
+
92
+ .lane-header {
93
+ padding: 10px 12px;
94
+ font-weight: 600;
95
+ font-size: 0.85rem;
96
+ text-transform: uppercase;
97
+ letter-spacing: 0.05em;
98
+ color: #94a3b8;
99
+ display: flex;
100
+ justify-content: space-between;
101
+ align-items: center;
102
+ }
103
+
104
+ .lane-count {
105
+ background: #334155;
106
+ padding: 2px 8px;
107
+ border-radius: 10px;
108
+ font-size: 0.75rem;
109
+ }
110
+
111
+ .lane-cards {
112
+ flex: 1;
113
+ padding: 8px;
114
+ overflow-y: auto;
115
+ min-height: 60px;
116
+ }
117
+
118
+ .lane-cards.drag-over {
119
+ background: #334155;
120
+ border-radius: 4px;
121
+ }
122
+
123
+ .card {
124
+ background: #334155;
125
+ border-radius: 6px;
126
+ padding: 10px 12px;
127
+ margin-bottom: 8px;
128
+ cursor: grab;
129
+ transition:
130
+ transform 0.1s,
131
+ box-shadow 0.1s;
132
+ }
133
+
134
+ .card:hover {
135
+ transform: translateY(-1px);
136
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
137
+ }
138
+
139
+ .card.dragging {
140
+ opacity: 0.4;
141
+ }
142
+
143
+ .card-title {
144
+ font-size: 0.9rem;
145
+ font-weight: 500;
146
+ margin-bottom: 4px;
147
+ }
148
+
149
+ .card-slug {
150
+ font-size: 0.75rem;
151
+ color: #94a3b8;
152
+ }
153
+
154
+ .card-id {
155
+ font-size: 0.65rem;
156
+ color: #475569;
157
+ margin-top: 2px;
158
+ font-family: monospace;
159
+ }
160
+
161
+ .card-priority {
162
+ font-size: 0.7rem;
163
+ color: #64748b;
164
+ margin-top: 4px;
165
+ }
166
+
167
+ .card.locked {
168
+ border-left: 3px solid #f59e0b;
169
+ }
170
+
171
+ .card.overlay-waiting-for-response {
172
+ border-left: 3px solid #f97316;
173
+ position: relative;
174
+ }
175
+
176
+ .card .overlay-indicator {
177
+ font-size: 0.7rem;
178
+ color: #f97316;
179
+ margin-top: 2px;
180
+ animation: pulse 2s ease-in-out infinite;
181
+ }
182
+
183
+ @keyframes pulse {
184
+ 0%,
185
+ 100% {
186
+ opacity: 1;
187
+ }
188
+ 50% {
189
+ opacity: 0.5;
190
+ }
191
+ }
192
+
193
+ .card .lock-indicator {
194
+ font-size: 0.7rem;
195
+ color: #f59e0b;
196
+ margin-top: 2px;
197
+ }
198
+
199
+ /* Release button */
200
+ .release-btn {
201
+ display: block;
202
+ width: 100%;
203
+ margin-top: 12px;
204
+ padding: 8px 16px;
205
+ background: #dc2626;
206
+ color: white;
207
+ border: none;
208
+ border-radius: 6px;
209
+ cursor: pointer;
210
+ font-size: 0.85rem;
211
+ font-weight: 500;
212
+ transition: background 0.2s;
213
+ }
214
+
215
+ .release-btn:hover {
216
+ background: #b91c1c;
217
+ }
218
+
219
+ .release-btn:disabled {
220
+ background: #6b7280;
221
+ cursor: not-allowed;
222
+ }
223
+
224
+ /* Lock button */
225
+ .lock-btn {
226
+ display: block;
227
+ width: 100%;
228
+ margin-top: 12px;
229
+ padding: 8px 16px;
230
+ background: #d97706;
231
+ color: white;
232
+ border: none;
233
+ border-radius: 6px;
234
+ cursor: pointer;
235
+ font-size: 0.85rem;
236
+ font-weight: 500;
237
+ transition: background 0.2s;
238
+ }
239
+
240
+ .lock-btn:hover {
241
+ background: #b45309;
242
+ }
243
+
244
+ .lock-btn:disabled {
245
+ background: #6b7280;
246
+ cursor: not-allowed;
247
+ }
248
+
249
+ /* Modal */
250
+ .modal {
251
+ position: fixed;
252
+ inset: 0;
253
+ background: rgba(0, 0, 0, 0.6);
254
+ display: flex;
255
+ align-items: center;
256
+ justify-content: center;
257
+ z-index: 100;
258
+ }
259
+
260
+ .modal.hidden {
261
+ display: none;
262
+ }
263
+
264
+ .modal-content {
265
+ background: #1e293b;
266
+ border-radius: 12px;
267
+ padding: 24px;
268
+ max-width: 500px;
269
+ width: 90%;
270
+ position: relative;
271
+ }
272
+
273
+ .modal-close {
274
+ position: absolute;
275
+ top: 12px;
276
+ right: 16px;
277
+ background: none;
278
+ border: none;
279
+ color: #94a3b8;
280
+ font-size: 1.5rem;
281
+ cursor: pointer;
282
+ }
283
+
284
+ .modal-close:hover {
285
+ color: #e2e8f0;
286
+ }
287
+
288
+ /* Detail modal — large, nearly full board size */
289
+ .detail-modal-content {
290
+ max-width: 90vw;
291
+ width: 90vw;
292
+ max-height: 90vh;
293
+ height: 90vh;
294
+ display: flex;
295
+ flex-direction: column;
296
+ overflow: hidden;
297
+ }
298
+
299
+ #detail-title {
300
+ margin-bottom: 2px;
301
+ padding-right: 40px;
302
+ flex-shrink: 0;
303
+ }
304
+
305
+ #detail-id {
306
+ font-size: 0.75rem;
307
+ color: #64748b;
308
+ font-family: monospace;
309
+ margin-bottom: 10px;
310
+ flex-shrink: 0;
311
+ }
312
+
313
+ /* Compact meta row */
314
+ .detail-meta {
315
+ display: flex;
316
+ gap: 16px;
317
+ margin-bottom: 14px;
318
+ font-size: 0.78rem;
319
+ color: #64748b;
320
+ flex-shrink: 0;
321
+ }
322
+
323
+ .detail-meta span {
324
+ color: #94a3b8;
325
+ }
326
+
327
+ /* Tabs */
328
+ .detail-tabs {
329
+ display: flex;
330
+ gap: 0;
331
+ border-bottom: 1px solid #334155;
332
+ margin-bottom: 14px;
333
+ flex-shrink: 0;
334
+ }
335
+
336
+ .detail-tab {
337
+ padding: 8px 16px;
338
+ background: none;
339
+ border: none;
340
+ color: #94a3b8;
341
+ font-size: 0.85rem;
342
+ cursor: pointer;
343
+ border-bottom: 2px solid transparent;
344
+ transition:
345
+ color 0.15s,
346
+ border-color 0.15s;
347
+ }
348
+
349
+ .detail-tab:hover {
350
+ color: #e2e8f0;
351
+ }
352
+
353
+ .detail-tab.active {
354
+ color: #e2e8f0;
355
+ border-bottom-color: #3b82f6;
356
+ }
357
+
358
+ .detail-tab-content {
359
+ display: none;
360
+ flex: 1;
361
+ min-height: 0;
362
+ overflow-y: auto;
363
+ }
364
+
365
+ .detail-tab-content.active {
366
+ display: flex;
367
+ flex-direction: column;
368
+ }
369
+
370
+ /* Description textarea */
371
+ .detail-description-label {
372
+ font-size: 0.8rem;
373
+ color: #94a3b8;
374
+ font-weight: 500;
375
+ display: block;
376
+ margin-bottom: 6px;
377
+ flex-shrink: 0;
378
+ }
379
+
380
+ #detail-description {
381
+ width: 100%;
382
+ flex: 1;
383
+ min-height: 120px;
384
+ padding: 12px;
385
+ background: #0f172a;
386
+ color: #e2e8f0;
387
+ border: 1px solid #475569;
388
+ border-radius: 6px;
389
+ font-size: 0.9rem;
390
+ font-family: inherit;
391
+ resize: none;
392
+ line-height: 1.6;
393
+ }
394
+
395
+ #detail-description.editable {
396
+ border-color: #475569;
397
+ }
398
+
399
+ #detail-description.editable:focus {
400
+ outline: none;
401
+ border-color: #3b82f6;
402
+ box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.15);
403
+ }
404
+
405
+ #detail-description.readonly {
406
+ background: #1a2332;
407
+ color: #cbd5e1;
408
+ border-color: #2d3a4d;
409
+ cursor: default;
410
+ resize: none;
411
+ }
412
+
413
+ .detail-save-btn {
414
+ margin-top: 10px;
415
+ flex-shrink: 0;
416
+ }
417
+
418
+ /* Detail rows (status, lock) */
419
+ .detail-row {
420
+ display: flex;
421
+ justify-content: space-between;
422
+ padding: 8px 0;
423
+ border-bottom: 1px solid #334155;
424
+ font-size: 0.9rem;
425
+ flex-shrink: 0;
426
+ }
427
+
428
+ .detail-label {
429
+ color: #94a3b8;
430
+ }
431
+ .detail-value {
432
+ font-weight: 500;
433
+ }
434
+
435
+ /* History tab scrollable area */
436
+ .detail-history-scroll {
437
+ flex: 1;
438
+ overflow-y: auto;
439
+ padding-right: 4px;
440
+ }
441
+
442
+ .history-entry {
443
+ padding: 6px 0;
444
+ font-size: 0.8rem;
445
+ color: #94a3b8;
446
+ border-bottom: 1px solid #1e293b;
447
+ }
448
+
449
+ .history-entry .lane-change {
450
+ color: #e2e8f0;
451
+ }
452
+
453
+ /* Title input with generate button */
454
+ .title-input-row {
455
+ display: flex;
456
+ gap: 6px;
457
+ align-items: center;
458
+ }
459
+
460
+ .title-input-row input {
461
+ flex: 1;
462
+ padding: 8px 10px;
463
+ background: #334155;
464
+ color: #e2e8f0;
465
+ border: 1px solid #475569;
466
+ border-radius: 4px;
467
+ font-size: 0.9rem;
468
+ font-family: inherit;
469
+ }
470
+
471
+ .title-input-row input:focus {
472
+ outline: none;
473
+ border-color: #3b82f6;
474
+ }
475
+
476
+ .generate-title-btn {
477
+ flex-shrink: 0;
478
+ width: 36px;
479
+ height: 36px;
480
+ padding: 0;
481
+ background: #334155;
482
+ color: #e2e8f0;
483
+ border: 1px solid #475569;
484
+ border-radius: 4px;
485
+ cursor: pointer;
486
+ font-size: 1rem;
487
+ line-height: 1;
488
+ transition:
489
+ background 0.2s,
490
+ border-color 0.2s;
491
+ }
492
+
493
+ .generate-title-btn:hover:not(:disabled) {
494
+ background: #475569;
495
+ border-color: #64748b;
496
+ }
497
+
498
+ .generate-title-btn:disabled {
499
+ opacity: 0.5;
500
+ cursor: not-allowed;
501
+ }
502
+
503
+ /* Add feature button */
504
+ #add-btn {
505
+ padding: 6px 12px;
506
+ background: #334155;
507
+ color: #e2e8f0;
508
+ border: 1px solid #475569;
509
+ border-radius: 4px;
510
+ cursor: pointer;
511
+ font-size: 1rem;
512
+ }
513
+
514
+ #add-btn:hover:not(:disabled) {
515
+ background: #475569;
516
+ }
517
+
518
+ #add-btn:disabled {
519
+ opacity: 0.4;
520
+ cursor: not-allowed;
521
+ }
522
+
523
+ /* Add feature form */
524
+ .add-form {
525
+ display: flex;
526
+ flex-direction: column;
527
+ gap: 14px;
528
+ margin-top: 16px;
529
+ }
530
+
531
+ .form-group {
532
+ display: flex;
533
+ flex-direction: column;
534
+ gap: 4px;
535
+ }
536
+
537
+ .form-group label {
538
+ font-size: 0.8rem;
539
+ color: #94a3b8;
540
+ font-weight: 500;
541
+ }
542
+
543
+ .form-group input,
544
+ .form-group textarea,
545
+ .form-group select {
546
+ padding: 8px 10px;
547
+ background: #334155;
548
+ color: #e2e8f0;
549
+ border: 1px solid #475569;
550
+ border-radius: 4px;
551
+ font-size: 0.9rem;
552
+ font-family: inherit;
553
+ }
554
+
555
+ .form-group input:focus,
556
+ .form-group textarea:focus,
557
+ .form-group select:focus {
558
+ outline: none;
559
+ border-color: #3b82f6;
560
+ }
561
+
562
+ .form-row {
563
+ display: flex;
564
+ gap: 12px;
565
+ }
566
+
567
+ .form-row .form-group {
568
+ flex: 1;
569
+ }
570
+
571
+ .submit-btn {
572
+ padding: 10px 16px;
573
+ background: #3b82f6;
574
+ color: white;
575
+ border: none;
576
+ border-radius: 6px;
577
+ cursor: pointer;
578
+ font-size: 0.9rem;
579
+ font-weight: 500;
580
+ transition: background 0.2s;
581
+ }
582
+
583
+ .submit-btn:hover:not(:disabled) {
584
+ background: #2563eb;
585
+ }
586
+
587
+ .submit-btn:disabled {
588
+ background: #6b7280;
589
+ cursor: not-allowed;
590
+ }
591
+
592
+ /* Import/Export buttons */
593
+ #import-btn,
594
+ #export-btn {
595
+ padding: 6px 12px;
596
+ background: #334155;
597
+ color: #e2e8f0;
598
+ border: 1px solid #475569;
599
+ border-radius: 4px;
600
+ cursor: pointer;
601
+ font-size: 0.85rem;
602
+ }
603
+
604
+ #import-btn:hover:not(:disabled),
605
+ #export-btn:hover:not(:disabled) {
606
+ background: #475569;
607
+ }
608
+
609
+ #import-btn:disabled,
610
+ #export-btn:disabled {
611
+ opacity: 0.4;
612
+ cursor: not-allowed;
613
+ }
614
+
615
+ /* Import progress banner */
616
+ .import-banner {
617
+ padding: 10px 20px;
618
+ background: #1e293b;
619
+ border-bottom: 1px solid #3b82f6;
620
+ color: #93c5fd;
621
+ font-size: 0.9rem;
622
+ text-align: center;
623
+ }
624
+ .import-banner.hidden {
625
+ display: none;
626
+ }
627
+ .import-banner.success {
628
+ border-bottom-color: #10b981;
629
+ color: #6ee7b7;
630
+ }
631
+ .import-banner.warning {
632
+ border-bottom-color: #f59e0b;
633
+ color: #fcd34d;
634
+ }
635
+
636
+ /* Export dropdown — positioned relative to header */
637
+ .export-dropdown {
638
+ position: absolute;
639
+ top: 100%;
640
+ right: 0;
641
+ z-index: 200;
642
+ }
643
+ .export-dropdown.hidden {
644
+ display: none;
645
+ }
646
+ .export-dropdown-content {
647
+ background: #1e293b;
648
+ border: 1px solid #475569;
649
+ border-radius: 8px;
650
+ padding: 12px;
651
+ min-width: 200px;
652
+ }
653
+ .export-dropdown-header {
654
+ display: flex;
655
+ justify-content: space-between;
656
+ align-items: center;
657
+ margin-bottom: 8px;
658
+ font-size: 0.85rem;
659
+ color: #94a3b8;
660
+ }
661
+ .export-toggle-btn {
662
+ background: none;
663
+ border: none;
664
+ color: #3b82f6;
665
+ cursor: pointer;
666
+ font-size: 0.8rem;
667
+ }
668
+ .export-dropdown label {
669
+ display: block;
670
+ padding: 4px 0;
671
+ font-size: 0.85rem;
672
+ color: #e2e8f0;
673
+ }
674
+
675
+ /* Skipped rows modal */
676
+ .skipped-details {
677
+ background: #0f172a;
678
+ color: #f87171;
679
+ padding: 12px;
680
+ border-radius: 6px;
681
+ font-size: 0.8rem;
682
+ max-height: 300px;
683
+ overflow-y: auto;
684
+ white-space: pre-wrap;
685
+ word-break: break-word;
686
+ }
687
+
688
+ /* Context menu */
689
+ .context-menu {
690
+ position: fixed;
691
+ background: #1e293b;
692
+ border: 1px solid #475569;
693
+ border-radius: 8px;
694
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
695
+ min-width: 160px;
696
+ z-index: 50;
697
+ padding: 4px 0;
698
+ }
699
+
700
+ .context-menu.hidden {
701
+ display: none;
702
+ }
703
+
704
+ .context-menu-item {
705
+ padding: 8px 16px;
706
+ cursor: pointer;
707
+ font-size: 0.85rem;
708
+ color: #e2e8f0;
709
+ transition: background 0.1s;
710
+ }
711
+
712
+ .context-menu-item:hover {
713
+ background: #334155;
714
+ }
715
+
716
+ .context-menu-item.danger {
717
+ color: #f87171;
718
+ }
719
+
720
+ .context-menu-item.danger:hover {
721
+ background: rgba(248, 113, 113, 0.1);
722
+ }
723
+
724
+ .context-menu-item.disabled {
725
+ color: #475569;
726
+ pointer-events: none;
727
+ opacity: 0.5;
728
+ }
729
+
730
+ /* Delete button in detail modal */
731
+ .delete-btn {
732
+ display: block;
733
+ width: 100%;
734
+ margin-top: 8px;
735
+ padding: 8px 16px;
736
+ background: transparent;
737
+ color: #f87171;
738
+ border: 1px solid #f87171;
739
+ border-radius: 6px;
740
+ cursor: pointer;
741
+ font-size: 0.85rem;
742
+ font-weight: 500;
743
+ transition:
744
+ background 0.2s,
745
+ color 0.2s;
746
+ }
747
+
748
+ .delete-btn:hover {
749
+ background: #dc2626;
750
+ color: white;
751
+ }
752
+
753
+ .delete-btn:disabled {
754
+ pointer-events: none;
755
+ border-color: #475569;
756
+ color: #475569;
757
+ opacity: 0.5;
758
+ }
759
+
760
+ /* ---- Within-lane reorder drag styles ---- */
761
+
762
+ .insertion-line {
763
+ position: absolute;
764
+ left: 4px;
765
+ right: 4px;
766
+ height: 2px;
767
+ background-color: var(--lane-color, #3b82f6);
768
+ pointer-events: none;
769
+ z-index: 10;
770
+ animation: insertion-line-appear 150ms ease-out;
771
+ }
772
+
773
+ @keyframes insertion-line-appear {
774
+ from {
775
+ opacity: 0;
776
+ transform: scaleX(0.5);
777
+ }
778
+ to {
779
+ opacity: 1;
780
+ transform: scaleX(1);
781
+ }
782
+ }
783
+
784
+ .insertion-line.hidden {
785
+ display: none;
786
+ }
787
+
788
+ /* Add modal position toggle */
789
+ .position-toggle {
790
+ display: inline-flex;
791
+ gap: 0;
792
+ border: 1px solid #475569;
793
+ border-radius: 6px;
794
+ overflow: hidden;
795
+ }
796
+
797
+ .position-toggle-btn {
798
+ padding: 6px 16px;
799
+ border: none;
800
+ background: #334155;
801
+ color: #e2e8f0;
802
+ cursor: pointer;
803
+ font-size: 13px;
804
+ transition:
805
+ background 0.15s,
806
+ color 0.15s;
807
+ }
808
+
809
+ .position-toggle-btn:not(:last-child) {
810
+ border-right: 1px solid #475569;
811
+ }
812
+
813
+ .position-toggle-btn.active {
814
+ background: #3b82f6;
815
+ color: #fff;
816
+ }
817
+
818
+ .position-toggle-btn:hover:not(.active) {
819
+ background: #475569;
820
+ }