@yemi33/squad 0.1.19 → 0.1.21

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/dashboard.html CHANGED
@@ -10,90 +10,111 @@
10
10
  --bg: #0d1117; --surface: #161b22; --surface2: #21262d; --border: #30363d;
11
11
  --text: #e6edf3; --muted: #8b949e; --green: #3fb950; --yellow: #d29922;
12
12
  --blue: #58a6ff; --purple: #bc8cff; --red: #f85149; --orange: #e3b341;
13
+
14
+ /* Spacing scale */
15
+ --space-1: 2px; --space-2: 4px; --space-3: 6px; --space-4: 8px;
16
+ --space-5: 10px; --space-6: 12px; --space-7: 16px; --space-8: 20px; --space-9: 24px;
17
+
18
+ /* Typography scale */
19
+ --text-xs: 9px; --text-sm: 10px; --text-base: 11px;
20
+ --text-md: 12px; --text-lg: 13px; --text-xl: 14px; --text-2xl: 16px;
21
+ --text-stat: 20px; --text-stat-lg: 24px;
22
+
23
+ /* Border radius */
24
+ --radius-sm: 4px; --radius-md: 6px; --radius-lg: 8px; --radius-xl: 10px; --radius-full: 50%;
25
+
26
+ /* Shadows */
27
+ --shadow-sm: 0 1px 3px rgba(0,0,0,0.2);
28
+ --shadow-md: 0 2px 8px rgba(0,0,0,0.3);
29
+ --shadow-lg: 0 4px 16px rgba(0,0,0,0.4);
30
+
31
+ /* Transitions */
32
+ --transition-fast: 0.15s; --transition-base: 0.2s; --transition-slow: 0.3s;
13
33
  }
14
34
  * { box-sizing: border-box; margin: 0; padding: 0; }
15
- body { background: var(--bg); color: var(--text); font-family: 'Segoe UI', system-ui, sans-serif; font-size: 14px; overflow-x: hidden; }
35
+ body { background: var(--bg); color: var(--text); font-family: 'Segoe UI', system-ui, sans-serif; font-size: var(--text-xl); overflow-x: hidden; }
16
36
 
17
37
  header {
18
38
  background: var(--surface); border-bottom: 1px solid var(--border);
19
- padding: 12px 24px; display: flex; align-items: center; justify-content: space-between;
39
+ padding: var(--space-6) var(--space-9); display: flex; align-items: center; justify-content: space-between;
20
40
  position: sticky; top: 0; z-index: 100;
21
41
  }
22
- header h1 { font-size: 16px; font-weight: 600; color: var(--blue); letter-spacing: 0.5px; }
23
- header h1 span { color: var(--muted); font-weight: 400; font-size: 13px; margin-left: 8px; }
24
- .pulse { width: 8px; height: 8px; border-radius: 50%; background: var(--green); display: inline-block; margin-right: 6px; animation: pulse 2s infinite; }
42
+ header h1 { font-size: var(--text-2xl); font-weight: 600; color: var(--blue); letter-spacing: 0.5px; }
43
+ header h1 span { color: var(--muted); font-weight: 400; font-size: var(--text-lg); margin-left: var(--space-4); }
44
+ .pulse { width: 8px; height: 8px; border-radius: var(--radius-full); background: var(--green); display: inline-block; margin-right: var(--space-3); animation: pulse 2s infinite; }
25
45
  @keyframes pulse { 0%,100%{opacity:1} 50%{opacity:0.3} }
26
- .timestamp { color: var(--muted); font-size: 12px; font-variant-numeric: tabular-nums; }
46
+ .timestamp { color: var(--muted); font-size: var(--text-md); font-variant-numeric: tabular-nums; }
27
47
 
28
48
  .layout { display: grid; grid-template-columns: 1fr 1fr; gap: 0; max-width: 100vw; overflow-x: hidden; }
29
- section { padding: 20px 24px; border-bottom: 1px solid var(--border); overflow: hidden; min-width: 0; }
49
+ section { padding: var(--space-8) var(--space-9); border-bottom: 1px solid var(--border); overflow: hidden; min-width: 0; }
30
50
  section:nth-child(odd) { border-right: 1px solid var(--border); }
31
- section h2 { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 1px; color: var(--muted); margin-bottom: 14px; display: flex; align-items: center; gap: 8px; }
32
- section h2 .count { background: var(--surface2); border: 1px solid var(--border); border-radius: 10px; padding: 1px 7px; font-size: 11px; color: var(--text); }
51
+ section h2 { font-size: var(--text-base); font-weight: 600; text-transform: uppercase; letter-spacing: 1px; color: var(--muted); margin-bottom: 14px; display: flex; align-items: center; gap: var(--space-4); }
52
+ section h2 .count { background: var(--surface2); border: 1px solid var(--border); border-radius: var(--radius-xl); padding: var(--space-1) 7px; font-size: var(--text-base); color: var(--text); }
33
53
 
34
- .agents { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
54
+ .agents { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-5); }
35
55
  .agent-card {
36
- background: var(--surface2); border: 1px solid var(--border); border-radius: 8px;
37
- padding: 12px 14px; transition: all 0.3s; cursor: pointer;
56
+ background: var(--surface2); border: 1px solid var(--border); border-radius: var(--radius-lg);
57
+ padding: var(--space-6) var(--space-7); transition: all var(--transition-slow); cursor: pointer;
38
58
  }
39
- .agent-card:hover { border-color: var(--blue); transform: translateY(-1px); box-shadow: 0 4px 12px rgba(0,0,0,0.3); }
59
+ .agent-card:hover { border-color: var(--blue); transform: translateY(-1px); box-shadow: var(--shadow-md); }
40
60
  .agent-card.working { border-color: var(--yellow); }
41
61
  .agent-card.done { border-color: var(--green); }
42
- .agent-card-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 6px; }
43
- .agent-name { font-weight: 600; font-size: 14px; }
44
- .agent-role { font-size: 11px; color: var(--muted); margin-bottom: 8px; }
45
- .status-badge { font-size: 10px; font-weight: 600; padding: 2px 8px; border-radius: 10px; text-transform: uppercase; letter-spacing: 0.5px; }
62
+ .agent-card-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--space-3); }
63
+ .agent-name { font-weight: 600; font-size: var(--text-xl); }
64
+ .agent-role { font-size: var(--text-base); color: var(--muted); margin-bottom: var(--space-4); }
65
+ .status-badge { font-size: var(--text-sm); font-weight: 600; padding: var(--space-1) var(--space-4); border-radius: var(--radius-xl); text-transform: uppercase; letter-spacing: 0.5px; }
46
66
  .status-badge.idle { background: var(--surface); color: var(--muted); border: 1px solid var(--border); }
47
67
  .status-badge.working { background: rgba(210,153,34,0.15); color: var(--yellow); border: 1px solid var(--yellow); animation: pulse 1.5s infinite; }
48
68
  .status-badge.done { background: rgba(63,185,80,0.15); color: var(--green); border: 1px solid var(--green); }
49
- .agent-action { font-size: 11px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
50
- .modal-qa { border-top: 1px solid var(--border); padding: 10px 20px; }
51
- .modal-qa-thread { max-height: 200px; overflow-y: auto; margin-bottom: 8px; }
52
- .modal-qa-q { font-size: 12px; color: var(--blue); margin-bottom: 4px; font-weight: 600; }
53
- .modal-qa-q .selection-ref { font-weight: 400; color: var(--muted); font-style: italic; display: block; font-size: 10px; margin-top: 2px; }
54
- .modal-qa-a { font-size: 12px; color: var(--text); margin-bottom: 12px; padding: 8px 10px; background: var(--surface2); border-radius: 6px; border-left: 2px solid var(--blue); white-space: pre-wrap; word-break: break-word; line-height: 1.5; }
55
- .modal-qa-loading { font-size: 11px; color: var(--muted); padding: 8px 10px; display: flex; align-items: center; gap: 8px; }
69
+ .agent-action { font-size: var(--text-base); color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
70
+ .modal-qa { border-top: 1px solid var(--border); padding: var(--space-5) var(--space-8); }
71
+ .modal-qa-thread { max-height: 200px; overflow-y: auto; margin-bottom: var(--space-4); }
72
+ .modal-qa-q { font-size: var(--text-md); color: var(--blue); margin-bottom: var(--space-2); font-weight: 600; }
73
+ .modal-qa-q .selection-ref { font-weight: 400; color: var(--muted); font-style: italic; display: block; font-size: var(--text-sm); margin-top: var(--space-1); }
74
+ .modal-qa-a { font-size: var(--text-md); color: var(--text); margin-bottom: var(--space-6); padding: var(--space-4) var(--space-5); background: var(--surface2); border-radius: var(--radius-md); border-left: 2px solid var(--blue); white-space: pre-wrap; word-break: break-word; line-height: 1.5; }
75
+ .modal-qa-loading { font-size: var(--text-base); color: var(--muted); padding: var(--space-4) var(--space-5); display: flex; align-items: center; gap: var(--space-4); }
56
76
  .modal-qa-loading .dot-pulse { display: inline-flex; gap: 3px; }
57
77
  .modal-qa-loading .dot-pulse span { width: 5px; height: 5px; background: var(--blue); border-radius: 50%; animation: dotPulse 1.2s infinite; }
58
78
  .modal-qa-loading .dot-pulse span:nth-child(2) { animation-delay: 0.2s; }
59
79
  .modal-qa-loading .dot-pulse span:nth-child(3) { animation-delay: 0.4s; }
60
80
  @keyframes dotPulse { 0%, 80%, 100% { opacity: 0.3; transform: scale(0.8); } 40% { opacity: 1; transform: scale(1); } }
61
- .modal-qa-selection-pill { display: flex; align-items: center; gap: 6px; padding: 4px 8px; margin-bottom: 6px; background: rgba(88,166,255,0.08); border: 1px solid rgba(88,166,255,0.25); border-radius: 4px; font-size: 11px; }
81
+ .modal-qa-selection-pill { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-2) var(--space-4); margin-bottom: var(--space-3); background: rgba(88,166,255,0.08); border: 1px solid rgba(88,166,255,0.25); border-radius: var(--radius-sm); font-size: var(--text-base); }
62
82
  .modal-qa-selection-pill .pill-label { color: var(--blue); font-weight: 600; white-space: nowrap; }
63
83
  .modal-qa-selection-pill .pill-text { color: var(--muted); flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-style: italic; }
64
84
  .modal-qa-selection-pill .pill-clear { background: none; border: none; color: var(--muted); cursor: pointer; font-size: 14px; padding: 0 2px; line-height: 1; }
65
85
  .modal-qa-selection-pill .pill-clear:hover { color: var(--red); }
66
86
  .modal-qa-input-wrap { display: flex; gap: 6px; }
67
- .modal-qa-input { flex: 1; background: var(--bg); border: 1px solid var(--border); border-radius: 4px; padding: 6px 10px; font-size: 12px; color: var(--text); font-family: inherit; }
87
+ .modal-qa-input { flex: 1; background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: var(--space-3) var(--space-5); font-size: var(--text-md); color: var(--text); font-family: inherit; }
68
88
  .modal-qa-input:focus { border-color: var(--blue); outline: none; }
69
- .modal-qa-btn { background: var(--blue); color: #fff; border: none; border-radius: 4px; padding: 6px 14px; font-size: 12px; cursor: pointer; }
89
+ .modal-qa-btn { background: var(--blue); color: #fff; border: none; border-radius: var(--radius-sm); padding: var(--space-3) var(--space-7); font-size: var(--text-md); cursor: pointer; }
70
90
  .modal-qa-btn:hover { opacity: 0.9; }
71
91
  .modal-qa-btn:disabled { opacity: 0.4; cursor: not-allowed; }
72
- .ask-selection-btn { display: none; position: fixed; z-index: 500; background: var(--blue); color: #fff; font-size: 11px; padding: 5px 12px; border-radius: 4px; cursor: pointer; box-shadow: 0 2px 8px rgba(0,0,0,0.3); }
92
+ .ask-selection-btn { display: none; position: fixed; z-index: 500; background: var(--blue); color: #fff; font-size: var(--text-base); padding: 5px var(--space-6); border-radius: var(--radius-sm); cursor: pointer; box-shadow: var(--shadow-md); }
73
93
  .ask-selection-btn:hover { opacity: 0.9; }
74
- .plan-card { background: var(--surface2); border: 1px solid var(--border); border-radius: 6px; padding: 12px; margin-bottom: 8px; }
75
- .plan-card.awaiting { border-left: 3px solid var(--yellow, #d29922); }
94
+ .plan-card { background: var(--surface2); border: 1px solid var(--border); border-radius: var(--radius-md); padding: var(--space-6); margin-bottom: var(--space-4); transition: border-color var(--transition-base); }
95
+ .plan-card:hover { border-color: var(--blue); }
96
+ .plan-card.awaiting { border-left: 3px solid var(--yellow); }
76
97
  .plan-card.approved { border-left: 3px solid var(--green); }
77
98
  .plan-card.rejected { border-left: 3px solid var(--red); opacity: 0.6; }
78
- .plan-card.revision-requested { border-left: 3px solid var(--purple, #a855f7); }
79
- .plan-card-header { display: flex; justify-content: space-between; align-items: flex-start; gap: 8px; }
80
- .plan-card-title { font-size: 13px; font-weight: 600; color: var(--text); }
81
- .plan-card-meta { font-size: 10px; color: var(--muted); margin-top: 4px; display: flex; gap: 8px; flex-wrap: wrap; }
82
- .plan-card-actions { display: flex; gap: 4px; margin-top: 8px; flex-wrap: wrap; }
83
- .plan-btn { font-size: 11px; padding: 4px 10px; border-radius: 4px; cursor: pointer; border: 1px solid var(--border); background: var(--surface); color: var(--text); transition: all 0.15s; }
99
+ .plan-card.revision-requested { border-left: 3px solid var(--purple); }
100
+ .plan-card-header { display: flex; justify-content: space-between; align-items: flex-start; gap: var(--space-4); }
101
+ .plan-card-title { font-size: var(--text-lg); font-weight: 600; color: var(--text); }
102
+ .plan-card-meta { font-size: var(--text-sm); color: var(--muted); margin-top: var(--space-2); display: flex; gap: var(--space-4); flex-wrap: wrap; }
103
+ .plan-card-actions { display: flex; gap: var(--space-2); margin-top: var(--space-4); flex-wrap: wrap; }
104
+ .plan-btn { font-size: var(--text-base); padding: var(--space-2) var(--space-5); border-radius: var(--radius-sm); cursor: pointer; border: 1px solid var(--border); background: var(--surface); color: var(--text); transition: all var(--transition-fast); position: relative; z-index: 1; }
84
105
  .plan-btn:hover { border-color: var(--text); }
85
106
  .plan-btn.approve { color: var(--green); border-color: var(--green); }
86
107
  .plan-btn.approve:hover { background: rgba(63,185,80,0.1); }
87
- .plan-btn.revise { color: var(--yellow, #d29922); border-color: var(--yellow, #d29922); }
108
+ .plan-btn.revise { color: var(--yellow); border-color: var(--yellow); }
88
109
  .plan-btn.revise:hover { background: rgba(210,153,34,0.1); }
89
110
  .plan-btn.reject { color: var(--red); border-color: var(--red); }
90
111
  .plan-btn.reject:hover { background: rgba(248,81,73,0.1); }
91
- .plan-feedback-input { width: 100%; margin-top: 6px; padding: 6px 8px; font-size: 11px; background: var(--bg); border: 1px solid var(--border); border-radius: 4px; color: var(--text); font-family: inherit; resize: vertical; min-height: 50px; }
92
- .token-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 8px; margin-bottom: 12px; }
93
- .token-tile { background: var(--surface2); border: 1px solid var(--border); border-radius: 6px; padding: 10px 12px; }
94
- .token-tile-label { font-size: 10px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.5px; }
95
- .token-tile-value { font-size: 20px; font-weight: 700; color: var(--text); margin-top: 2px; }
96
- .token-tile-sub { font-size: 10px; color: var(--muted); margin-top: 2px; }
112
+ .plan-feedback-input { width: 100%; margin-top: var(--space-3); padding: var(--space-3) var(--space-4); font-size: var(--text-base); background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius-sm); color: var(--text); font-family: inherit; resize: vertical; min-height: 50px; }
113
+ .token-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: var(--space-4); margin-bottom: var(--space-6); }
114
+ .token-tile { background: var(--surface2); border: 1px solid var(--border); border-radius: var(--radius-md); padding: var(--space-5) var(--space-6); }
115
+ .token-tile-label { font-size: var(--text-sm); color: var(--muted); text-transform: uppercase; letter-spacing: 0.5px; }
116
+ .token-tile-value { font-size: var(--text-stat); font-weight: 700; color: var(--text); margin-top: var(--space-1); }
117
+ .token-tile-sub { font-size: var(--text-sm); color: var(--muted); margin-top: var(--space-1); }
97
118
  .token-chart { display: flex; align-items: flex-end; gap: 3px; height: 80px; margin: 8px 0; }
98
119
  .token-bar { flex: 1; min-width: 8px; max-width: 24px; background: var(--blue); border-radius: 2px 2px 0 0; position: relative; cursor: default; transition: background 0.15s; }
99
120
  .token-bar:hover { background: var(--green); }
@@ -101,89 +122,89 @@
101
122
  .token-bar:hover .token-bar-tip { display: block; }
102
123
  .token-chart-labels { display: flex; gap: 3px; }
103
124
  .token-chart-labels span { flex: 1; min-width: 8px; max-width: 24px; font-size: 8px; color: var(--muted); text-align: center; overflow: hidden; }
104
- .token-agent-table { width: 100%; margin-top: 10px; }
105
- .token-agent-table th { text-align: left; font-size: 10px; color: var(--muted); font-weight: 500; padding: 4px 8px; border-bottom: 1px solid var(--border); }
106
- .token-agent-table td { font-size: 11px; padding: 4px 8px; }
107
- .kb-tabs { display: flex; gap: 4px; flex-wrap: wrap; margin-bottom: 8px; }
108
- .kb-tab { background: var(--surface2); border: 1px solid var(--border); color: var(--muted); font-size: 11px; cursor: pointer; padding: 3px 10px; border-radius: 4px; transition: all 0.2s; }
125
+ .token-agent-table { width: 100%; margin-top: var(--space-5); }
126
+ .token-agent-table th { text-align: left; font-size: var(--text-sm); color: var(--muted); font-weight: 500; padding: var(--space-2) var(--space-4); border-bottom: 1px solid var(--border); }
127
+ .token-agent-table td { font-size: var(--text-base); padding: var(--space-2) var(--space-4); }
128
+ .kb-tabs { display: flex; gap: var(--space-2); flex-wrap: wrap; margin-bottom: var(--space-4); }
129
+ .kb-tab { background: var(--surface2); border: 1px solid var(--border); color: var(--muted); font-size: var(--text-base); cursor: pointer; padding: var(--space-1) var(--space-5); border-radius: var(--radius-sm); transition: all var(--transition-base); }
109
130
  .kb-tab:hover { color: var(--text); border-color: var(--text); }
110
131
  .kb-tab.active { color: var(--blue); border-color: var(--blue); background: rgba(88,166,255,0.08); }
111
- .kb-tab .badge { background: var(--border); color: var(--text); font-size: 9px; padding: 0 5px; border-radius: 8px; margin-left: 4px; }
132
+ .kb-tab .badge { background: var(--border); color: var(--text); font-size: var(--text-xs); padding: 0 5px; border-radius: var(--radius-lg); margin-left: var(--space-2); }
112
133
  .kb-list { max-height: 400px; overflow-y: auto; }
113
- .kb-item { display: flex; align-items: flex-start; gap: 10px; padding: 8px 0; border-bottom: 1px solid var(--border); cursor: pointer; transition: background 0.1s; }
134
+ .kb-item { display: flex; align-items: flex-start; gap: var(--space-5); padding: var(--space-4) 0; border-bottom: 1px solid var(--border); cursor: pointer; transition: background var(--transition-fast); }
114
135
  .kb-item:hover { background: var(--surface2); }
115
136
  .kb-item:last-child { border-bottom: none; }
116
137
  .kb-item-body { flex: 1; min-width: 0; }
117
- .kb-item-title { font-size: 12px; color: var(--text); font-weight: 500; }
118
- .kb-item-meta { font-size: 10px; color: var(--muted); margin-top: 2px; display: flex; gap: 8px; }
119
- .kb-item-preview { font-size: 10px; color: var(--muted); margin-top: 3px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
120
- .agent-result { font-size: 10px; color: var(--text); background: var(--surface2); padding: 6px 8px; border-radius: 4px; margin-top: 6px; white-space: pre-wrap; word-break: break-word; max-height: 80px; overflow-y: auto; line-height: 1.4; border-left: 2px solid var(--blue); }
138
+ .kb-item-title { font-size: var(--text-md); color: var(--text); font-weight: 500; }
139
+ .kb-item-meta { font-size: var(--text-sm); color: var(--muted); margin-top: var(--space-1); display: flex; gap: var(--space-4); }
140
+ .kb-item-preview { font-size: var(--text-sm); color: var(--muted); margin-top: var(--space-1); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
141
+ .agent-result { font-size: var(--text-sm); color: var(--text); background: var(--surface2); padding: var(--space-3) var(--space-4); border-radius: var(--radius-sm); margin-top: var(--space-3); white-space: pre-wrap; word-break: break-word; max-height: 80px; overflow-y: auto; line-height: 1.4; border-left: 2px solid var(--blue); }
121
142
  .agent-card { min-width: 0; }
122
- .agent-emoji { font-size: 20px; margin-right: 4px; }
123
- .click-hint { font-size: 10px; color: var(--border); margin-top: 6px; }
143
+ .agent-emoji { font-size: var(--text-stat); margin-right: var(--space-2); }
144
+ .click-hint { font-size: var(--text-sm); color: var(--border); margin-top: var(--space-3); }
124
145
 
125
- .inbox-list { display: flex; flex-direction: column; gap: 8px; max-height: 320px; overflow-y: auto; }
146
+ .inbox-list { display: flex; flex-direction: column; gap: var(--space-4); max-height: 320px; overflow-y: auto; }
126
147
 
127
148
  /* PRD Progress */
128
- .prd-progress-bar { width: 100%; height: 20px; background: var(--bg); border-radius: 10px; overflow: hidden; display: flex; margin-bottom: 12px; border: 1px solid var(--border); }
149
+ .prd-progress-bar { width: 100%; height: 20px; background: var(--bg); border-radius: var(--radius-xl); overflow: hidden; display: flex; margin-bottom: var(--space-6); border: 1px solid var(--border); }
129
150
  .prd-progress-bar .seg { height: 100%; transition: width 0.5s ease; }
130
151
  .prd-progress-bar .seg.complete { background: var(--green); }
131
152
  .prd-progress-bar .seg.pr-created { background: #2ea043; }
132
153
  .prd-progress-bar .seg.in-progress { background: var(--yellow); }
133
154
  .prd-progress-bar .seg.planned { background: var(--blue); opacity: 0.4; }
134
155
  .prd-progress-bar .seg.missing { background: var(--border); }
135
- .prd-progress-pct { font-size: 22px; font-weight: 700; color: var(--green); margin-bottom: 8px; }
136
- .prd-progress-legend { display: flex; flex-wrap: wrap; gap: 12px; margin-bottom: 12px; }
137
- .prd-legend-item { display: flex; align-items: center; gap: 5px; font-size: 11px; color: var(--muted); }
156
+ .prd-progress-pct { font-size: 22px; font-weight: 700; color: var(--green); margin-bottom: var(--space-4); }
157
+ .prd-progress-legend { display: flex; flex-wrap: wrap; gap: var(--space-6); margin-bottom: var(--space-6); }
158
+ .prd-legend-item { display: flex; align-items: center; gap: 5px; font-size: var(--text-base); color: var(--muted); }
138
159
  .prd-legend-dot { width: 10px; height: 10px; border-radius: 2px; }
139
160
  .prd-legend-dot.complete { background: var(--green); }
140
161
  .prd-legend-dot.pr-created { background: #2ea043; }
141
162
  .prd-legend-dot.in-progress { background: var(--yellow); }
142
163
  .prd-legend-dot.planned { background: var(--blue); opacity: 0.4; }
143
164
  .prd-legend-dot.missing { background: var(--border); }
144
- .prd-items-list { display: flex; flex-direction: column; gap: 4px; max-height: 200px; overflow-y: auto; }
145
- .prd-item-row { display: flex; align-items: center; gap: 8px; padding: 5px 8px; border-radius: 4px; font-size: 11px; background: var(--surface2); border: 1px solid var(--border); }
165
+ .prd-items-list { display: flex; flex-direction: column; gap: var(--space-2); max-height: 200px; overflow-y: auto; }
166
+ .prd-item-row { display: flex; align-items: center; gap: var(--space-4); padding: 5px var(--space-4); border-radius: var(--radius-sm); font-size: var(--text-base); background: var(--surface2); border: 1px solid var(--border); }
146
167
  .prd-item-id { font-family: Consolas, monospace; color: var(--blue); min-width: 36px; }
147
168
  .prd-item-name { flex: 1; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
148
- .prd-item-priority { font-size: 10px; padding: 1px 6px; border-radius: 8px; }
169
+ .prd-item-priority { font-size: var(--text-sm); padding: var(--space-1) var(--space-3); border-radius: var(--radius-lg); }
149
170
  .prd-item-priority.high { background: rgba(248,81,73,0.15); color: var(--red); }
150
171
  .prd-item-priority.medium { background: rgba(210,153,34,0.15); color: var(--yellow); }
151
172
  .prd-item-priority.low { background: rgba(139,148,158,0.15); color: var(--muted); }
152
- .prd-project-badge { font-size: 9px; padding: 1px 5px; border-radius: 6px; background: rgba(56,139,253,0.12); color: var(--blue); border: 1px solid rgba(56,139,253,0.25); white-space: nowrap; }
173
+ .prd-project-badge { font-size: var(--text-xs); padding: var(--space-1) 5px; border-radius: var(--radius-md); background: rgba(56,139,253,0.12); color: var(--blue); border: 1px solid rgba(56,139,253,0.25); white-space: nowrap; }
153
174
 
154
- .notes-preview { max-height: 400px; overflow-y: auto; font-size: 12px; line-height: 1.6; color: var(--muted); font-family: Consolas, monospace; white-space: pre-wrap; word-wrap: break-word; background: var(--surface2); border: 1px solid var(--border); border-radius: 6px; padding: 12px 14px; cursor: pointer; transition: border-color 0.2s; }
175
+ .notes-preview { max-height: 400px; overflow-y: auto; font-size: var(--text-md); line-height: 1.6; color: var(--muted); font-family: Consolas, monospace; white-space: pre-wrap; word-wrap: break-word; background: var(--surface2); border: 1px solid var(--border); border-radius: var(--radius-md); padding: var(--space-6) var(--space-7); cursor: pointer; transition: border-color var(--transition-base); }
155
176
  .notes-preview:hover { border-color: var(--blue); }
156
- .inbox-item { background: var(--surface2); border: 1px solid var(--border); border-left: 3px solid var(--purple); border-radius: 4px; padding: 10px 12px; cursor: pointer; }
177
+ .inbox-item { background: var(--surface2); border: 1px solid var(--border); border-left: 3px solid var(--purple); border-radius: var(--radius-sm); padding: var(--space-5) var(--space-6); cursor: pointer; }
157
178
  .inbox-item:hover { border-color: var(--blue); border-left-color: var(--blue); }
158
- .inbox-name { font-weight: 500; font-size: 12px; color: var(--purple); margin-bottom: 4px; display: flex; justify-content: space-between; }
159
- .inbox-preview { font-size: 11px; color: var(--muted); line-height: 1.5; max-height: 60px; overflow: hidden; }
179
+ .inbox-name { font-weight: 500; font-size: var(--text-md); color: var(--purple); margin-bottom: var(--space-2); display: flex; justify-content: space-between; }
180
+ .inbox-preview { font-size: var(--text-base); color: var(--muted); line-height: 1.5; max-height: 60px; overflow: hidden; }
160
181
 
161
182
  .prd-panel, .pr-panel { grid-column: 1 / -1; border-bottom: 1px solid var(--border); overflow: visible; min-width: 0; }
162
183
  .prd-inner { display: flex; gap: 16px; align-items: flex-start; }
163
184
  .prd-stats { display: flex; gap: 16px; }
164
- .prd-stat { text-align: center; background: var(--surface2); border: 1px solid var(--border); border-radius: 8px; padding: 12px 20px; }
185
+ .prd-stat { text-align: center; background: var(--surface2); border: 1px solid var(--border); border-radius: var(--radius-lg); padding: var(--space-6) var(--space-8); }
165
186
  .prd-stat-num { font-size: 28px; font-weight: 700; color: var(--blue); }
166
187
  .prd-stat-num.green { color: var(--green); }
167
188
  .prd-stat-num.red { color: var(--red); }
168
189
  .prd-stat-num.orange { color: var(--orange); }
169
- .prd-stat-label { font-size: 11px; color: var(--muted); margin-top: 2px; }
170
- .prd-summary { flex: 1; font-size: 13px; color: var(--muted); line-height: 1.6; background: var(--surface2); border: 1px solid var(--border); border-radius: 8px; padding: 14px; }
190
+ .prd-stat-label { font-size: var(--text-base); color: var(--muted); margin-top: var(--space-1); }
191
+ .prd-summary { flex: 1; font-size: var(--text-lg); color: var(--muted); line-height: 1.6; background: var(--surface2); border: 1px solid var(--border); border-radius: var(--radius-lg); padding: 14px; }
171
192
  .prd-pending { color: var(--yellow); font-style: italic; }
172
193
 
173
194
  /* PR Tracker */
174
195
  .pr-table-wrap { overflow-x: auto; }
175
- .pr-table { width: 100%; border-collapse: collapse; font-size: 12px; table-layout: auto; }
196
+ .pr-table { width: 100%; border-collapse: collapse; font-size: var(--text-md); table-layout: auto; }
176
197
  .pr-table th:last-child, .pr-table td:last-child { width: 36px; min-width: 36px; text-align: center; }
177
- .pr-table th { text-align: left; color: var(--muted); font-weight: 500; font-size: 11px; text-transform: uppercase; letter-spacing: 0.5px; padding: 8px 10px; border-bottom: 1px solid var(--border); }
178
- .pr-table td { padding: 10px; border-bottom: 1px solid var(--border); vertical-align: middle; white-space: nowrap; }
198
+ .pr-table th { text-align: left; color: var(--muted); font-weight: 500; font-size: var(--text-base); text-transform: uppercase; letter-spacing: 0.5px; padding: var(--space-4) var(--space-5); border-bottom: 1px solid var(--border); }
199
+ .pr-table td { padding: var(--space-5); border-bottom: 1px solid var(--border); vertical-align: middle; white-space: nowrap; }
179
200
  .pr-table tr:last-child td { border-bottom: none; }
180
201
  .pr-table tr:hover { background: var(--surface2); }
181
202
  .pr-title { color: var(--blue); text-decoration: none; font-weight: 500; }
182
203
  .pr-title:hover { text-decoration: underline; }
183
- .pr-id { color: var(--muted); font-family: Consolas, monospace; font-size: 11px; }
184
- .pr-agent { font-size: 11px; color: var(--text); }
185
- .pr-branch { font-family: Consolas, monospace; font-size: 10px; color: var(--muted); background: var(--bg); padding: 2px 6px; border-radius: 3px; border: 1px solid var(--border); }
186
- .pr-badge { font-size: 10px; font-weight: 600; padding: 2px 8px; border-radius: 10px; text-transform: uppercase; letter-spacing: 0.5px; white-space: nowrap; }
204
+ .pr-id { color: var(--muted); font-family: Consolas, monospace; font-size: var(--text-base); }
205
+ .pr-agent { font-size: var(--text-base); color: var(--text); }
206
+ .pr-branch { font-family: Consolas, monospace; font-size: var(--text-sm); color: var(--muted); background: var(--bg); padding: var(--space-1) var(--space-3); border-radius: 3px; border: 1px solid var(--border); }
207
+ .pr-badge { font-size: var(--text-sm); font-weight: 600; padding: var(--space-1) var(--space-4); border-radius: var(--radius-xl); text-transform: uppercase; letter-spacing: 0.5px; white-space: nowrap; }
187
208
  .pr-badge.draft { background: rgba(139,148,158,0.15); color: var(--muted); border: 1px solid var(--border); }
188
209
  .pr-badge.active { background: rgba(88,166,255,0.15); color: var(--blue); border: 1px solid var(--blue); }
189
210
  .pr-badge.approved { background: rgba(63,185,80,0.15); color: var(--green); border: 1px solid var(--green); }
@@ -193,55 +214,118 @@
193
214
  .pr-badge.build-pass { background: rgba(63,185,80,0.15); color: var(--green); border: 1px solid var(--green); }
194
215
  .pr-badge.build-fail { background: rgba(248,81,73,0.15); color: var(--red); border: 1px solid var(--red); }
195
216
  .pr-badge.no-build { background: var(--surface); color: var(--muted); border: 1px solid var(--border); }
196
- .error-details-btn { font-size: 9px; padding: 1px 6px; margin-left: 4px; background: rgba(248,81,73,0.15); color: var(--red); border: 1px solid var(--red); border-radius: 8px; cursor: pointer; font-weight: 600; text-transform: uppercase; letter-spacing: 0.3px; }
217
+ .error-details-btn { font-size: var(--text-xs); padding: var(--space-1) var(--space-3); margin-left: var(--space-2); background: rgba(248,81,73,0.15); color: var(--red); border: 1px solid var(--red); border-radius: var(--radius-lg); cursor: pointer; font-weight: 600; text-transform: uppercase; letter-spacing: 0.3px; }
197
218
  .error-details-btn:hover { background: rgba(248,81,73,0.3); }
198
- .pr-empty { color: var(--muted); font-style: italic; font-size: 12px; padding: 12px 0; }
219
+ .pr-empty { color: var(--muted); font-style: italic; font-size: var(--text-md); padding: var(--space-6) 0; }
199
220
  .pr-pager { display: flex; align-items: center; justify-content: space-between; margin-top: 10px; }
200
221
  .pr-pager-btns { display: flex; gap: 6px; }
201
222
  .pr-pager-btn {
202
223
  background: var(--surface2); border: 1px solid var(--border); color: var(--muted);
203
- font-size: 11px; padding: 4px 10px; border-radius: 4px; cursor: pointer; transition: all 0.2s;
224
+ font-size: var(--text-base); padding: var(--space-2) var(--space-5); border-radius: var(--radius-sm); cursor: pointer; transition: all var(--transition-base);
204
225
  }
205
226
  .pr-pager-btn:hover { color: var(--text); border-color: var(--text); }
206
227
  .pr-pager-btn.disabled { opacity: 0.3; pointer-events: none; }
207
228
  .pr-pager-btn.see-all { color: var(--blue); border-color: var(--blue); }
208
229
  .pr-pager-btn.see-all:hover { background: rgba(88,166,255,0.1); }
209
- .pr-page-info { font-size: 11px; color: var(--muted); }
210
- .pr-date { font-size: 11px; color: var(--muted); }
230
+ .pr-page-info { font-size: var(--text-base); color: var(--muted); }
231
+ .pr-date { font-size: var(--text-base); color: var(--muted); }
211
232
 
212
233
  .archive-btn {
213
234
  background: var(--surface2); border: 1px solid var(--border); color: var(--muted);
214
- font-size: 11px; padding: 4px 10px; border-radius: 4px; cursor: pointer; transition: all 0.2s; margin-left: auto;
235
+ font-size: var(--text-base); padding: var(--space-2) var(--space-5); border-radius: var(--radius-sm); cursor: pointer; transition: all var(--transition-base); margin-left: auto;
215
236
  }
216
237
  .archive-btn:hover { color: var(--purple); border-color: var(--purple); }
217
- .archive-list { display: flex; flex-direction: column; gap: 8px; }
218
- .archive-card { background: var(--surface2); border: 1px solid var(--border); border-radius: 6px; padding: 12px 14px; cursor: pointer; transition: all 0.2s; }
238
+ .archive-list { display: flex; flex-direction: column; gap: var(--space-4); }
239
+ .archive-card { background: var(--surface2); border: 1px solid var(--border); border-radius: var(--radius-md); padding: var(--space-6) var(--space-7); cursor: pointer; transition: all var(--transition-base); }
219
240
  .archive-card:hover { border-color: var(--purple); }
220
- .archive-card h4 { color: var(--purple); font-size: 13px; margin-bottom: 6px; }
221
- .archive-card p { font-size: 11px; color: var(--muted); line-height: 1.5; }
222
- .archive-detail-section { margin-bottom: 16px; }
223
- .archive-detail-section h4 { color: var(--blue); font-size: 13px; margin-bottom: 8px; font-family: 'Segoe UI', sans-serif; }
224
- .archive-feature { background: var(--surface2); border: 1px solid var(--border); border-radius: 4px; padding: 10px 12px; margin-bottom: 6px; }
225
- .archive-feature .feat-id { font-family: Consolas, monospace; color: var(--blue); font-size: 11px; }
226
- .archive-feature .feat-name { font-weight: 600; font-size: 12px; color: var(--text); margin: 4px 0; }
227
- .archive-feature .feat-desc { font-size: 11px; color: var(--muted); line-height: 1.5; }
228
- .archive-feature .feat-meta { font-size: 10px; color: var(--muted); margin-top: 6px; display: flex; gap: 12px; }
229
- .archive-question { background: var(--surface2); border: 1px solid var(--border); border-left: 3px solid var(--orange); border-radius: 4px; padding: 10px 12px; margin-bottom: 6px; }
230
- .archive-question .q-id { font-family: Consolas, monospace; color: var(--orange); font-size: 11px; }
231
- .archive-question .q-text { font-size: 12px; color: var(--text); margin: 4px 0; }
232
- .archive-question .q-context { font-size: 11px; color: var(--muted); line-height: 1.5; }
241
+ .archive-card h4 { color: var(--purple); font-size: var(--text-lg); margin-bottom: var(--space-3); }
242
+ .archive-card p { font-size: var(--text-base); color: var(--muted); line-height: 1.5; }
243
+ .archive-detail-section { margin-bottom: var(--space-7); }
244
+ .archive-detail-section h4 { color: var(--blue); font-size: var(--text-lg); margin-bottom: var(--space-4); font-family: 'Segoe UI', sans-serif; }
245
+ .archive-feature { background: var(--surface2); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: var(--space-5) var(--space-6); margin-bottom: var(--space-3); }
246
+ .archive-feature .feat-id { font-family: Consolas, monospace; color: var(--blue); font-size: var(--text-base); }
247
+ .archive-feature .feat-name { font-weight: 600; font-size: var(--text-md); color: var(--text); margin: var(--space-2) 0; }
248
+ .archive-feature .feat-desc { font-size: var(--text-base); color: var(--muted); line-height: 1.5; }
249
+ .archive-feature .feat-meta { font-size: var(--text-sm); color: var(--muted); margin-top: var(--space-3); display: flex; gap: var(--space-6); }
250
+ .archive-question { background: var(--surface2); border: 1px solid var(--border); border-left: 3px solid var(--orange); border-radius: var(--radius-sm); padding: var(--space-5) var(--space-6); margin-bottom: var(--space-3); }
251
+ .archive-question .q-id { font-family: Consolas, monospace; color: var(--orange); font-size: var(--text-base); }
252
+ .archive-question .q-text { font-size: var(--text-md); color: var(--text); margin: var(--space-2) 0; }
253
+ .archive-question .q-context { font-size: var(--text-base); color: var(--muted); line-height: 1.5; }
254
+
255
+ /* ── Base component classes ────────────────────────────────────────── */
256
+
257
+ /* Card — unified card base */
258
+ .card {
259
+ background: var(--surface2); border: 1px solid var(--border);
260
+ border-radius: var(--radius-lg); padding: var(--space-6) var(--space-7);
261
+ transition: border-color var(--transition-base);
262
+ }
263
+ .card:hover { border-color: var(--blue); }
264
+ .card.clickable { cursor: pointer; }
265
+
266
+ /* Button — unified button base */
267
+ .btn {
268
+ font-size: var(--text-base); padding: var(--space-2) var(--space-5);
269
+ border-radius: var(--radius-sm); border: 1px solid var(--border);
270
+ background: var(--surface); color: var(--text); cursor: pointer;
271
+ transition: all var(--transition-fast);
272
+ }
273
+ .btn:hover { border-color: var(--text); }
274
+ .btn:disabled { opacity: 0.4; cursor: not-allowed; }
275
+ .btn-primary { background: var(--blue); color: #fff; border: none; }
276
+ .btn-primary:hover { opacity: 0.9; }
277
+ .btn-sm { font-size: var(--text-xs); padding: var(--space-1) var(--space-3); }
278
+ .btn-success { color: var(--green); border-color: var(--green); }
279
+ .btn-danger { color: var(--red); border-color: var(--red); }
280
+ .btn-warning { color: var(--yellow); border-color: var(--yellow); }
281
+
282
+ /* Badge — unified badge/pill base */
283
+ .badge {
284
+ font-size: var(--text-sm); font-weight: 600;
285
+ padding: var(--space-1) var(--space-4);
286
+ border-radius: var(--radius-xl); text-transform: uppercase; white-space: nowrap;
287
+ }
288
+ .badge-blue { background: rgba(88,166,255,0.15); color: var(--blue); border: 1px solid var(--blue); }
289
+ .badge-green { background: rgba(63,185,80,0.15); color: var(--green); border: 1px solid var(--green); }
290
+ .badge-red { background: rgba(248,81,73,0.15); color: var(--red); border: 1px solid var(--red); }
291
+ .badge-yellow { background: rgba(210,153,34,0.15); color: var(--yellow); border: 1px solid var(--yellow); }
292
+ .badge-purple { background: rgba(188,140,255,0.15); color: var(--purple); border: 1px solid var(--purple); }
293
+ .badge-muted { background: var(--surface); color: var(--muted); border: 1px solid var(--border); }
294
+
295
+ /* Table — unified table base */
296
+ .table { width: 100%; border-collapse: collapse; font-size: var(--text-md); }
297
+ .table th { font-size: var(--text-sm); text-transform: uppercase; letter-spacing: 0.5px; color: var(--muted); padding: var(--space-4); border-bottom: 1px solid var(--border); text-align: left; font-weight: 500; }
298
+ .table td { padding: var(--space-4) var(--space-5); border-bottom: 1px solid var(--border); }
299
+ .table tr:hover { background: var(--surface2); }
300
+
301
+ /* ── Utility classes ───────────────────────────────────────────────── */
302
+ .text-muted { color: var(--muted); }
303
+ .text-sm { font-size: var(--text-sm); }
304
+ .text-xs { font-size: var(--text-xs); }
305
+ .text-md { font-size: var(--text-md); }
306
+ .text-green { color: var(--green); }
307
+ .text-red { color: var(--red); }
308
+ .text-blue { color: var(--blue); }
309
+ .text-yellow { color: var(--yellow); }
310
+ .text-purple { color: var(--purple); }
311
+ .flex-row { display: flex; gap: var(--space-4); align-items: center; }
312
+ .flex-col { display: flex; flex-direction: column; gap: var(--space-4); }
313
+ .flex-wrap { flex-wrap: wrap; }
314
+ .mono { font-family: Consolas, monospace; }
315
+ .font-bold { font-weight: 600; }
316
+ .truncate { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
233
317
 
234
318
  ::-webkit-scrollbar { width: 6px; }
235
319
  ::-webkit-scrollbar-track { background: var(--bg); }
236
320
  ::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
237
- .empty { color: var(--muted); font-style: italic; font-size: 12px; padding: 8px 0; }
321
+ .empty { color: var(--muted); font-style: italic; font-size: var(--text-md); padding: var(--space-4) 0; }
238
322
 
239
323
  /* Command Center — Unified Input */
240
324
  .cmd-center { grid-column: 1 / -1; overflow: visible !important; }
241
325
  .cmd-input-wrap {
242
326
  position: relative; display: flex; align-items: flex-start; gap: 0;
243
- background: var(--bg); border: 2px solid var(--border); border-radius: 10px;
244
- transition: border-color 0.2s, box-shadow 0.2s; padding: 0;
327
+ background: var(--bg); border: 2px solid var(--border); border-radius: var(--radius-xl);
328
+ transition: border-color var(--transition-base), box-shadow var(--transition-base); padding: 0;
245
329
  }
246
330
  .cmd-input-wrap:focus-within { border-color: var(--blue); box-shadow: 0 0 0 3px rgba(88,166,255,0.12); }
247
331
  .cmd-highlight-layer {
@@ -263,10 +347,10 @@
263
347
  }
264
348
  .cmd-input-wrap textarea::placeholder { color: var(--muted); }
265
349
  .cmd-send-btn {
266
- background: transparent; color: var(--blue); border: 1px solid var(--blue); padding: 10px 18px;
267
- border-radius: 0 8px 8px 0; font-size: 13px; font-weight: 600; cursor: pointer;
268
- transition: opacity 0.2s; white-space: nowrap; align-self: stretch; min-height: 48px;
269
- display: flex; align-items: center; gap: 6px;
350
+ background: transparent; color: var(--blue); border: 1px solid var(--blue); padding: var(--space-5) 18px;
351
+ border-radius: 0 var(--radius-lg) var(--radius-lg) 0; font-size: var(--text-lg); font-weight: 600; cursor: pointer;
352
+ transition: opacity var(--transition-base); white-space: nowrap; align-self: stretch; min-height: 48px;
353
+ display: flex; align-items: center; gap: var(--space-3);
270
354
  }
271
355
  .cmd-send-btn:hover { background: rgba(88,166,255,0.1); }
272
356
  .cmd-send-btn:disabled { opacity: 0.4; cursor: not-allowed; }
@@ -275,9 +359,9 @@
275
359
  /* Intent & meta chips */
276
360
  .cmd-meta { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 4px; align-items: center; min-height: 0; }
277
361
  .cmd-chip {
278
- display: inline-flex; align-items: center; gap: 4px; padding: 3px 10px;
279
- border-radius: 12px; font-size: 11px; font-weight: 500; border: 1px solid var(--border);
280
- background: var(--surface2); color: var(--muted); cursor: default; transition: all 0.2s;
362
+ display: inline-flex; align-items: center; gap: var(--space-2); padding: var(--space-1) var(--space-5);
363
+ border-radius: var(--radius-xl); font-size: var(--text-base); font-weight: 500; border: 1px solid var(--border);
364
+ background: var(--surface2); color: var(--muted); cursor: default; transition: all var(--transition-base);
281
365
  }
282
366
  .cmd-chip.intent { color: var(--blue); border-color: rgba(88,166,255,0.3); background: rgba(88,166,255,0.08); }
283
367
  .cmd-chip.agent-chip { color: var(--purple); border-color: rgba(188,140,255,0.3); background: rgba(188,140,255,0.08); }
@@ -297,9 +381,9 @@
297
381
 
298
382
  /* @ mention autocomplete */
299
383
  .cmd-mention-popup {
300
- display: none; position: relative; left: 0; margin-top: 4px;
301
- background: var(--surface); border: 1px solid var(--border); border-radius: 8px;
302
- padding: 4px 0; min-width: 280px; box-shadow: 0 8px 24px rgba(0,0,0,0.4);
384
+ display: none; position: relative; left: 0; margin-top: var(--space-2);
385
+ background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg);
386
+ padding: var(--space-2) 0; min-width: 280px; box-shadow: var(--shadow-lg);
303
387
  z-index: 200; max-height: 320px; overflow-y: auto;
304
388
  scrollbar-width: thin; scrollbar-color: var(--border) transparent;
305
389
  }
@@ -307,28 +391,28 @@
307
391
  .cmd-mention-popup::-webkit-scrollbar-thumb { background: var(--border); border-radius: 4px; }
308
392
  .cmd-mention-popup.visible { display: block; }
309
393
  .cmd-mention-item {
310
- padding: 8px 14px; font-size: 12px; cursor: pointer; display: flex;
311
- align-items: center; gap: 8px; transition: background 0.15s;
394
+ padding: var(--space-4) var(--space-7); font-size: var(--text-md); cursor: pointer; display: flex;
395
+ align-items: center; gap: var(--space-4); transition: background var(--transition-fast);
312
396
  }
313
397
  .cmd-mention-item:hover { background: var(--surface2); }
314
398
  .cmd-mention-item.active { background: rgba(88,166,255,0.15); border-left: 2px solid var(--blue); }
315
- .cmd-mention-item .mention-emoji { font-size: 16px; }
399
+ .cmd-mention-item .mention-emoji { font-size: var(--text-2xl); }
316
400
  .cmd-mention-item .mention-name { font-weight: 600; color: var(--purple); }
317
- .cmd-mention-item .mention-role { color: var(--muted); font-size: 11px; }
401
+ .cmd-mention-item .mention-role { color: var(--muted); font-size: var(--text-base); }
318
402
 
319
403
  /* Hints bar */
320
404
  .cmd-hints {
321
- display: flex; gap: 12px; margin-top: 4px; font-size: 10px; color: var(--muted);
322
- letter-spacing: 0.2px; padding: 0 4px; overflow-x: auto; white-space: nowrap;
405
+ display: flex; gap: var(--space-6); margin-top: var(--space-2); font-size: var(--text-sm); color: var(--muted);
406
+ letter-spacing: 0.2px; padding: 0 var(--space-2); overflow-x: auto; white-space: nowrap;
323
407
  scrollbar-width: thin; scrollbar-color: var(--border) transparent;
324
408
  }
325
409
  .cmd-hints::-webkit-scrollbar { height: 3px; }
326
410
  .cmd-hints::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
327
- .cmd-hints code { color: var(--blue); font-size: 10px; background: var(--surface2); padding: 1px 5px; border-radius: 3px; }
411
+ .cmd-hints code { color: var(--blue); font-size: var(--text-sm); background: var(--surface2); padding: var(--space-1) 5px; border-radius: 3px; }
328
412
 
329
413
  .cmd-history-btn {
330
- background: none; border: 1px solid var(--border); color: var(--muted); font-size: 11px;
331
- cursor: pointer; padding: 3px 10px; border-radius: 4px; transition: all 0.2s;
414
+ background: none; border: 1px solid var(--border); color: var(--muted); font-size: var(--text-base);
415
+ cursor: pointer; padding: var(--space-1) var(--space-5); border-radius: var(--radius-sm); transition: all var(--transition-base);
332
416
  }
333
417
  .cmd-history-btn:hover { color: var(--text); border-color: var(--text); }
334
418
  .cmd-history-list { list-style: none; padding: 0; margin: 0; }
@@ -338,42 +422,42 @@
338
422
  }
339
423
  .cmd-history-item:last-child { border-bottom: none; }
340
424
  .cmd-history-item-body { flex: 1; min-width: 0; }
341
- .cmd-history-item-text { font-size: 12px; color: var(--text); white-space: pre-wrap; word-break: break-word; font-family: Consolas, monospace; }
342
- .cmd-history-item-meta { font-size: 10px; color: var(--muted); margin-top: 3px; display: flex; gap: 8px; }
343
- .cmd-history-item-meta .chip { background: var(--surface2); padding: 1px 6px; border-radius: 3px; }
425
+ .cmd-history-item-text { font-size: var(--text-md); color: var(--text); white-space: pre-wrap; word-break: break-word; font-family: Consolas, monospace; }
426
+ .cmd-history-item-meta { font-size: var(--text-sm); color: var(--muted); margin-top: var(--space-1); display: flex; gap: var(--space-4); }
427
+ .cmd-history-item-meta .chip { background: var(--surface2); padding: var(--space-1) var(--space-3); border-radius: 3px; }
344
428
  .cmd-history-resubmit {
345
429
  background: var(--surface2); border: 1px solid var(--border); color: var(--blue);
346
- font-size: 11px; cursor: pointer; padding: 4px 10px; border-radius: 4px; white-space: nowrap;
347
- transition: all 0.2s; flex-shrink: 0;
430
+ font-size: var(--text-base); cursor: pointer; padding: var(--space-2) var(--space-5); border-radius: var(--radius-sm); white-space: nowrap;
431
+ transition: all var(--transition-base); flex-shrink: 0;
348
432
  }
349
433
  .cmd-history-resubmit:hover { background: rgba(88,166,255,0.1); border-color: var(--blue); }
350
- .cmd-history-empty { color: var(--muted); font-size: 12px; padding: 20px 0; text-align: center; }
434
+ .cmd-history-empty { color: var(--muted); font-size: var(--text-md); padding: var(--space-8) 0; text-align: center; }
351
435
  .cmd-toast {
352
- display: none; padding: 8px 14px; border-radius: 4px; font-size: 12px;
353
- margin-top: 10px; animation: fadeIn 0.3s;
436
+ display: none; padding: var(--space-4) var(--space-7); border-radius: var(--radius-sm); font-size: var(--text-md);
437
+ margin-top: var(--space-5); animation: fadeIn 0.3s;
354
438
  }
355
439
  .cmd-toast.success { display: block; background: rgba(63,185,80,0.15); color: var(--green); border: 1px solid var(--green); }
356
440
  .cmd-toast.error { display: block; background: rgba(248,81,73,0.15); color: var(--red); border: 1px solid var(--red); }
357
441
  @keyframes fadeIn { from{opacity:0;transform:translateY(-4px)} to{opacity:1;transform:translateY(0)} }
358
442
 
359
443
  /* Engine Status */
360
- .engine-badge { padding: 4px 12px; border-radius: 12px; font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; margin-right: 12px; }
444
+ .engine-badge { padding: var(--space-2) var(--space-6); border-radius: var(--radius-xl); font-size: var(--text-base); font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; margin-right: var(--space-6); }
361
445
  .engine-badge.running { background: rgba(63,185,80,0.15); color: var(--green); border: 1px solid var(--green); }
362
446
  .engine-badge.paused { background: rgba(210,153,34,0.15); color: var(--yellow); border: 1px solid var(--yellow); }
363
447
  .engine-badge.stopped { background: rgba(248,81,73,0.15); color: var(--red); border: 1px solid var(--red); }
364
448
 
365
449
  /* Dispatch Queue */
366
- .dispatch-stats { display: flex; gap: 16px; margin-bottom: 14px; }
367
- .dispatch-stat { text-align: center; background: var(--surface2); border: 1px solid var(--border); border-radius: 8px; padding: 10px 18px; }
368
- .dispatch-stat-num { font-size: 24px; font-weight: 700; }
450
+ .dispatch-stats { display: flex; gap: var(--space-7); margin-bottom: 14px; }
451
+ .dispatch-stat { text-align: center; background: var(--surface2); border: 1px solid var(--border); border-radius: var(--radius-lg); padding: var(--space-5) 18px; }
452
+ .dispatch-stat-num { font-size: var(--text-stat-lg); font-weight: 700; }
369
453
  .dispatch-stat-num.blue { color: var(--blue); }
370
454
  .dispatch-stat-num.green { color: var(--green); }
371
455
  .dispatch-stat-num.yellow { color: var(--yellow); }
372
456
  .dispatch-stat-num.muted { color: var(--muted); }
373
- .dispatch-stat-label { font-size: 10px; color: var(--muted); margin-top: 2px; text-transform: uppercase; letter-spacing: 0.5px; }
374
- .dispatch-list { display: flex; flex-direction: column; gap: 6px; }
375
- .dispatch-item { display: flex; align-items: center; gap: 8px; padding: 8px 10px; background: var(--surface2); border: 1px solid var(--border); border-radius: 6px; font-size: 12px; }
376
- .dispatch-type { font-size: 10px; font-weight: 600; padding: 2px 8px; border-radius: 8px; text-transform: uppercase; white-space: nowrap; }
457
+ .dispatch-stat-label { font-size: var(--text-sm); color: var(--muted); margin-top: var(--space-1); text-transform: uppercase; letter-spacing: 0.5px; }
458
+ .dispatch-list { display: flex; flex-direction: column; gap: var(--space-3); }
459
+ .dispatch-item { display: flex; align-items: center; gap: var(--space-4); padding: var(--space-4) var(--space-5); background: var(--surface2); border: 1px solid var(--border); border-radius: var(--radius-md); font-size: var(--text-md); }
460
+ .dispatch-type { font-size: var(--text-sm); font-weight: 600; padding: var(--space-1) var(--space-4); border-radius: var(--radius-lg); text-transform: uppercase; white-space: nowrap; }
377
461
  .dispatch-type.implement { background: rgba(88,166,255,0.15); color: var(--blue); }
378
462
  .dispatch-type.implement\:large { background: rgba(88,166,255,0.25); color: var(--blue); }
379
463
  .dispatch-type.review { background: rgba(188,140,255,0.15); color: var(--purple); }
@@ -387,11 +471,11 @@
387
471
  .dispatch-type.manual { background: rgba(139,148,158,0.15); color: var(--muted); }
388
472
  .dispatch-agent { font-weight: 600; color: var(--text); }
389
473
  .dispatch-task { flex: 1; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
390
- .dispatch-time { font-size: 10px; color: var(--border); }
474
+ .dispatch-time { font-size: var(--text-sm); color: var(--border); }
391
475
 
392
476
  /* Engine Log */
393
- .log-list { max-height: 280px; overflow-y: auto; display: flex; flex-direction: column; gap: 2px; }
394
- .log-entry { font-size: 11px; padding: 4px 8px; border-bottom: 1px solid rgba(48,54,61,0.4); font-family: Consolas, monospace; }
477
+ .log-list { max-height: 280px; overflow-y: auto; display: flex; flex-direction: column; gap: var(--space-1); }
478
+ .log-entry { font-size: var(--text-base); padding: var(--space-2) var(--space-4); border-bottom: 1px solid rgba(48,54,61,0.4); font-family: Consolas, monospace; }
395
479
  .log-ts { color: var(--muted); }
396
480
  .log-level-info { color: var(--blue); }
397
481
  .log-level-warn { color: var(--yellow); }
@@ -408,41 +492,41 @@
408
492
  }
409
493
  .detail-panel.open { transform: translateX(0); }
410
494
  .detail-header {
411
- padding: 16px 20px; border-bottom: 1px solid var(--border);
495
+ padding: var(--space-7) var(--space-8); border-bottom: 1px solid var(--border);
412
496
  display: flex; justify-content: space-between; align-items: center; flex-shrink: 0;
413
497
  }
414
- .detail-header h3 { font-size: 16px; color: var(--blue); display: flex; align-items: center; gap: 8px; }
415
- .detail-close { background: none; border: 1px solid var(--border); color: var(--muted); font-size: 12px; cursor: pointer; padding: 4px 12px; border-radius: 4px; }
498
+ .detail-header h3 { font-size: var(--text-2xl); color: var(--blue); display: flex; align-items: center; gap: var(--space-4); }
499
+ .detail-close { background: none; border: 1px solid var(--border); color: var(--muted); font-size: var(--text-md); cursor: pointer; padding: var(--space-2) var(--space-6); border-radius: var(--radius-sm); }
416
500
  .detail-close:hover { color: var(--text); border-color: var(--text); }
417
501
  .detail-body { flex: 1; overflow-y: auto; padding: 0; }
418
502
  .detail-tabs { display: flex; border-bottom: 1px solid var(--border); flex-shrink: 0; background: var(--bg); }
419
503
  .detail-tab {
420
- padding: 10px 16px; font-size: 12px; font-weight: 500; color: var(--muted);
421
- cursor: pointer; border-bottom: 2px solid transparent; transition: all 0.2s;
504
+ padding: var(--space-5) var(--space-7); font-size: var(--text-md); font-weight: 500; color: var(--muted);
505
+ cursor: pointer; border-bottom: 2px solid transparent; transition: all var(--transition-base);
422
506
  }
423
507
  .detail-tab:hover { color: var(--text); }
424
508
  .detail-tab.active { color: var(--blue); border-bottom-color: var(--blue); }
425
509
  .detail-content {
426
- padding: 16px 20px; font-size: 12px; line-height: 1.7;
510
+ padding: var(--space-7) var(--space-8); font-size: var(--text-md); line-height: 1.7;
427
511
  white-space: pre-wrap; word-wrap: break-word; font-family: Consolas, monospace; color: var(--muted);
428
512
  }
429
- .detail-content h4 { color: var(--text); font-size: 13px; margin: 12px 0 6px 0; font-family: 'Segoe UI', sans-serif; }
430
- .detail-content .section { margin-bottom: 16px; padding: 12px; background: var(--surface2); border: 1px solid var(--border); border-radius: 6px; }
431
- .status-line { display: flex; align-items: center; gap: 10px; padding: 10px 16px; background: var(--bg); border-bottom: 1px solid var(--border); font-size: 12px; }
513
+ .detail-content h4 { color: var(--text); font-size: var(--text-lg); margin: var(--space-6) 0 var(--space-3) 0; font-family: 'Segoe UI', sans-serif; }
514
+ .detail-content .section { margin-bottom: var(--space-7); padding: var(--space-6); background: var(--surface2); border: 1px solid var(--border); border-radius: var(--radius-md); }
515
+ .status-line { display: flex; align-items: center; gap: var(--space-5); padding: var(--space-5) var(--space-7); background: var(--bg); border-bottom: 1px solid var(--border); font-size: var(--text-md); }
432
516
 
433
517
  /* Modal for inbox detail */
434
518
  .modal-bg { display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.75); z-index: 400; align-items: center; justify-content: center; }
435
519
  .modal-bg.open { display: flex; }
436
- .modal { background: var(--surface); border: 1px solid var(--border); border-radius: 10px; width: 95%; max-width: 1100px; max-height: 80vh; display: flex; flex-direction: column; }
437
- .modal-header { padding: 16px 20px; border-bottom: 1px solid var(--border); display: flex; justify-content: space-between; align-items: center; }
438
- .modal-header h3 { font-size: 14px; color: var(--blue); }
439
- .modal-header-actions { display: flex; align-items: center; gap: 8px; }
440
- .modal-copy { background: var(--surface2); border: 1px solid var(--border); color: var(--muted); font-size: 11px; cursor: pointer; padding: 4px 10px; border-radius: 4px; display: flex; align-items: center; gap: 4px; transition: all 0.2s; }
520
+ .modal { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-xl); width: 95%; max-width: 1100px; max-height: 80vh; display: flex; flex-direction: column; }
521
+ .modal-header { padding: var(--space-7) var(--space-8); border-bottom: 1px solid var(--border); display: flex; justify-content: space-between; align-items: center; }
522
+ .modal-header h3 { font-size: var(--text-xl); color: var(--blue); }
523
+ .modal-header-actions { display: flex; align-items: center; gap: var(--space-4); }
524
+ .modal-copy { background: var(--surface2); border: 1px solid var(--border); color: var(--muted); font-size: var(--text-base); cursor: pointer; padding: var(--space-2) var(--space-5); border-radius: var(--radius-sm); display: flex; align-items: center; gap: var(--space-2); transition: all var(--transition-base); }
441
525
  .modal-copy:hover { color: var(--text); border-color: var(--text); }
442
526
  .modal-copy.copied { color: var(--green); border-color: var(--green); }
443
- .modal-close { background: none; border: none; color: var(--muted); font-size: 18px; cursor: pointer; padding: 4px 8px; }
527
+ .modal-close { background: none; border: none; color: var(--muted); font-size: 18px; cursor: pointer; padding: var(--space-2) var(--space-4); }
444
528
  .modal-close:hover { color: var(--text); }
445
- .modal-body { padding: 16px 20px; overflow-y: auto; white-space: pre-wrap; font-size: 12px; line-height: 1.7; color: var(--muted); font-family: Consolas, monospace; }
529
+ .modal-body { padding: var(--space-7) var(--space-8); overflow-y: auto; white-space: pre-wrap; font-size: var(--text-md); line-height: 1.7; color: var(--muted); font-family: Consolas, monospace; }
446
530
 
447
531
  /* Responsive: tablet / narrow window */
448
532
  @media (max-width: 1100px) {
@@ -637,8 +721,8 @@
637
721
  <button class="pill-clear" onclick="clearQaSelection()" title="Clear selection">&times;</button>
638
722
  </div>
639
723
  <div class="modal-qa-input-wrap">
640
- <input type="text" class="modal-qa-input" id="modal-qa-input" placeholder="Ask about this document (or select text first)..." onkeydown="if(event.key==='Enter')modalAskSubmit()">
641
- <button class="modal-qa-btn" id="modal-qa-btn" onclick="modalAskSubmit()">Ask</button>
724
+ <input type="text" class="modal-qa-input" id="modal-qa-input" placeholder="Ask a question or give an edit instruction..." onkeydown="if(event.key==='Enter')modalSend()">
725
+ <button class="modal-qa-btn" id="modal-send-btn" onclick="modalSend()">Send</button>
642
726
  </div>
643
727
  </div>
644
728
  </div>
@@ -967,7 +1051,9 @@ function openNotesModal() {
967
1051
  document.getElementById('modal-body').style.whiteSpace = 'pre-wrap';
968
1052
  _modalDocContext = { title: 'Team Notes', content, selection: '' };
969
1053
  _modalEditable = 'notes.md';
1054
+ _modalFilePath = 'notes.md';
970
1055
  document.getElementById('modal-edit-btn').style.display = '';
1056
+ // steer btn removed — unified send
971
1057
  document.getElementById('modal').classList.add('open');
972
1058
  }
973
1059
 
@@ -1133,15 +1219,26 @@ function openModal(i) {
1133
1219
  }
1134
1220
  function closeModal() {
1135
1221
  document.getElementById('modal').classList.remove('open');
1136
- // Clear Q&A state
1222
+ // Save Q&A session for this document (persist across modal open/close)
1223
+ if (_qaSessionKey && (_qaHistory.length > 0 || _qaQueue.length > 0)) {
1224
+ _qaSessions.set(_qaSessionKey, {
1225
+ history: _qaHistory,
1226
+ threadHtml: document.getElementById('modal-qa-thread').innerHTML,
1227
+ docContext: { ..._modalDocContext },
1228
+ filePath: _modalFilePath,
1229
+ });
1230
+ }
1231
+ // Reset UI state but don't kill processing/queue — they run in background
1137
1232
  _modalDocContext = { title: '', content: '', selection: '' };
1138
- document.getElementById('modal-qa-thread').innerHTML = '';
1233
+ _qaSessionKey = '';
1139
1234
  document.getElementById('modal-qa-input').value = '';
1140
1235
  document.getElementById('modal-qa-input').placeholder = 'Ask about this document (or select text first)...';
1141
1236
  document.getElementById('modal-qa-pill').style.display = 'none';
1142
1237
  document.getElementById('ask-selection-btn').style.display = 'none';
1143
- // Clear edit state
1238
+ // Clear edit/steer state
1144
1239
  _modalEditable = null;
1240
+ _modalFilePath = null;
1241
+ // steer btn removed — unified send
1145
1242
  const body = document.getElementById('modal-body');
1146
1243
  body.contentEditable = 'false';
1147
1244
  body.style.border = '';
@@ -2230,6 +2327,12 @@ async function cmdSubmitPrd(parsed) {
2230
2327
  // ─── Modal Q&A (Ask about document) ──────────────────────────────────────────
2231
2328
 
2232
2329
  let _modalDocContext = { title: '', content: '', selection: '' };
2330
+ let _modalFilePath = null; // file path for steering (null = read-only Q&A only)
2331
+ let _qaHistory = []; // multi-turn conversation history [{role:'user',text:''},{role:'assistant',text:''}]
2332
+ let _qaProcessing = false; // true while waiting for Haiku response
2333
+ let _qaQueue = []; // queued messages while processing
2334
+ let _qaSessionKey = ''; // key for current conversation (title or filePath)
2335
+ const _qaSessions = new Map(); // persist conversations across modal open/close {key → {history, threadHtml}}
2233
2336
 
2234
2337
  // Track text selection anywhere in content areas for the floating "Ask about this" button
2235
2338
  document.addEventListener('mouseup', function(e) {
@@ -2306,10 +2409,10 @@ function clearQaSelection() {
2306
2409
  document.getElementById('modal-qa-input').placeholder = 'Ask about this document (or select text first)...';
2307
2410
  }
2308
2411
 
2309
- async function modalAskSubmit() {
2412
+ function modalSend() {
2310
2413
  const input = document.getElementById('modal-qa-input');
2311
- const question = input.value.trim();
2312
- if (!question) return;
2414
+ const message = input.value.trim();
2415
+ if (!message) return;
2313
2416
 
2314
2417
  // Capture content from modal body if not already set
2315
2418
  if (!_modalDocContext.content) {
@@ -2320,38 +2423,144 @@ async function modalAskSubmit() {
2320
2423
  }
2321
2424
  }
2322
2425
  if (!_modalDocContext.content) {
2323
- showToast('cmd-toast', 'No document content to ask about', false);
2426
+ showToast('cmd-toast', 'No document content', false);
2324
2427
  return;
2325
2428
  }
2326
2429
 
2327
2430
  const thread = document.getElementById('modal-qa-thread');
2328
- const btn = document.getElementById('modal-qa-btn');
2431
+ const selection = _modalDocContext.selection || '';
2432
+
2433
+ // Show message in thread immediately
2434
+ let qHtml = '<div class="modal-qa-q">' + escHtml(message);
2435
+ if (selection) {
2436
+ qHtml += '<span class="selection-ref">Re: "' + escHtml(selection.slice(0, 100)) + ((selection.length > 100) ? '...' : '') + '"</span>';
2437
+ }
2438
+ qHtml += '</div>';
2439
+ thread.innerHTML += qHtml;
2440
+ thread.scrollTop = thread.scrollHeight;
2441
+
2442
+ // Clear input immediately so user can type next message
2443
+ input.value = '';
2444
+ _modalDocContext.selection = '';
2445
+ document.getElementById('modal-qa-pill').style.display = 'none';
2446
+
2447
+ if (_qaProcessing) {
2448
+ // Queue the message — show it as "queued" in the thread
2449
+ _qaQueue.push({ message, selection });
2450
+ thread.innerHTML += '<div class="modal-qa-loading" style="color:var(--muted);font-size:10px">Queued — will send after current response</div>';
2451
+ thread.scrollTop = thread.scrollHeight;
2452
+ return;
2453
+ }
2454
+
2455
+ _processQaMessage(message, selection);
2456
+ }
2457
+
2458
+ async function _processQaMessage(message, selection) {
2459
+ const thread = document.getElementById('modal-qa-thread');
2460
+ const btn = document.getElementById('modal-send-btn');
2461
+ _qaProcessing = true;
2462
+
2463
+ const loadingId = 'chat-loading-' + Date.now();
2464
+ thread.innerHTML += '<div class="modal-qa-loading" id="' + loadingId + '"><div class="dot-pulse"><span></span><span></span><span></span></div> Thinking...</div>';
2465
+ thread.scrollTop = thread.scrollHeight;
2466
+
2467
+ try {
2468
+ const res = await fetch('/api/doc-chat', {
2469
+ method: 'POST',
2470
+ headers: { 'Content-Type': 'application/json' },
2471
+ body: JSON.stringify({
2472
+ message,
2473
+ document: _modalDocContext.content,
2474
+ title: _modalDocContext.title,
2475
+ selection: selection,
2476
+ filePath: _modalFilePath || null,
2477
+ history: _qaHistory,
2478
+ }),
2479
+ });
2480
+ const data = await res.json();
2481
+ const loadingEl = document.getElementById(loadingId);
2482
+ if (loadingEl) loadingEl.remove();
2483
+
2484
+ if (data.ok) {
2485
+ const borderColor = data.edited ? 'var(--green)' : 'var(--blue)';
2486
+ const suffix = data.edited ? '\n\n✓ Document saved.' : '';
2487
+ thread.innerHTML += '<div class="modal-qa-a" style="border-left-color:' + borderColor + '">' + escHtml(data.answer + suffix) + '</div>';
2329
2488
 
2330
- // Show question
2331
- let qHtml = '<div class="modal-qa-q">' + escHtml(question);
2489
+ // Track conversation history
2490
+ _qaHistory.push({ role: 'user', text: message });
2491
+ _qaHistory.push({ role: 'assistant', text: data.answer });
2492
+
2493
+ // Refresh modal body if document was edited
2494
+ if (data.edited && data.content) {
2495
+ const display = data.content.replace(/^---[\s\S]*?---\n*/m, '');
2496
+ document.getElementById('modal-body').textContent = display;
2497
+ _modalDocContext.content = display;
2498
+ }
2499
+ } else {
2500
+ thread.innerHTML += '<div class="modal-qa-a" style="color:var(--red)">Error: ' + escHtml(data.error || 'Failed') + '</div>';
2501
+ }
2502
+ } catch (e) {
2503
+ const loadingEl = document.getElementById(loadingId);
2504
+ if (loadingEl) loadingEl.remove();
2505
+ thread.innerHTML += '<div class="modal-qa-a" style="color:var(--red)">Error: ' + escHtml(e.message) + '</div>';
2506
+ }
2507
+
2508
+ _qaProcessing = false;
2509
+ thread.scrollTop = thread.scrollHeight;
2510
+
2511
+ // Process next queued message
2512
+ if (_qaQueue.length > 0) {
2513
+ const next = _qaQueue.shift();
2514
+ // Remove the "Queued" indicator
2515
+ const queuedEls = thread.querySelectorAll('.modal-qa-loading');
2516
+ for (const el of queuedEls) {
2517
+ if (el.textContent.includes('Queued')) { el.remove(); break; }
2518
+ }
2519
+ _processQaMessage(next.message, next.selection);
2520
+ } else {
2521
+ document.getElementById('modal-qa-input').focus();
2522
+ }
2523
+ }
2524
+
2525
+ // Override closeModal to clear Q&A state
2526
+ const _origCloseModal = typeof closeModal === 'function' ? closeModal : null;
2527
+
2528
+ async function modalSteerSubmit() {
2529
+ const input = document.getElementById('modal-qa-input');
2530
+ const instruction = input.value.trim();
2531
+ if (!instruction) return;
2532
+ if (!_modalFilePath) {
2533
+ showToast('cmd-toast', 'This document is read-only (no file path)', false);
2534
+ return;
2535
+ }
2536
+
2537
+ const thread = document.getElementById('modal-qa-thread');
2538
+ const btn = document.getElementById('modal-steer-btn');
2539
+
2540
+ // Show instruction
2541
+ let qHtml = '<div class="modal-qa-q" style="color:var(--green)">Edit: ' + escHtml(instruction);
2332
2542
  if (_modalDocContext.selection) {
2333
- qHtml += '<span class="selection-ref">Re: "' + escHtml(_modalDocContext.selection.slice(0, 100)) + ((_modalDocContext.selection.length > 100) ? '...' : '') + '"</span>';
2543
+ qHtml += '<span class="selection-ref">On: "' + escHtml(_modalDocContext.selection.slice(0, 100)) + '"</span>';
2334
2544
  }
2335
2545
  qHtml += '</div>';
2336
2546
  thread.innerHTML += qHtml;
2337
2547
 
2338
2548
  // Show loading
2339
- const loadingId = 'qa-loading-' + Date.now();
2340
- thread.innerHTML += '<div class="modal-qa-loading" id="' + loadingId + '"><div class="dot-pulse"><span></span><span></span><span></span></div> Thinking...</div>';
2549
+ const loadingId = 'steer-loading-' + Date.now();
2550
+ thread.innerHTML += '<div class="modal-qa-loading" id="' + loadingId + '"><div class="dot-pulse"><span></span><span></span><span></span></div> Editing...</div>';
2341
2551
  thread.scrollTop = thread.scrollHeight;
2342
2552
 
2343
2553
  input.value = '';
2344
- input.placeholder = 'Ask another question...';
2345
2554
  btn.disabled = true;
2555
+ document.getElementById('modal-qa-btn').disabled = true;
2346
2556
 
2347
2557
  try {
2348
- const res = await fetch('/api/ask-about', {
2558
+ const res = await fetch('/api/steer-document', {
2349
2559
  method: 'POST',
2350
2560
  headers: { 'Content-Type': 'application/json' },
2351
2561
  body: JSON.stringify({
2352
- question,
2353
- document: _modalDocContext.content,
2354
- title: _modalDocContext.title,
2562
+ instruction,
2563
+ filePath: _modalFilePath,
2355
2564
  selection: _modalDocContext.selection || '',
2356
2565
  }),
2357
2566
  });
@@ -2359,10 +2568,17 @@ async function modalAskSubmit() {
2359
2568
  const loadingEl = document.getElementById(loadingId);
2360
2569
  if (loadingEl) loadingEl.remove();
2361
2570
 
2362
- if (data.ok && data.answer) {
2363
- thread.innerHTML += '<div class="modal-qa-a">' + escHtml(data.answer) + '</div>';
2571
+ if (data.ok) {
2572
+ thread.innerHTML += '<div class="modal-qa-a" style="border-left-color:var(--green)">' + escHtml(data.answer) + (data.updated ? '\n\n✓ Document saved.' : '') + '</div>';
2573
+
2574
+ // Refresh the modal body with updated content
2575
+ if (data.updated && data.content) {
2576
+ const display = data.content.replace(/^---[\s\S]*?---\n*/m, '');
2577
+ document.getElementById('modal-body').textContent = display;
2578
+ _modalDocContext.content = display;
2579
+ }
2364
2580
  } else {
2365
- thread.innerHTML += '<div class="modal-qa-a" style="color:var(--red)">Error: ' + escHtml(data.error || 'No answer') + '</div>';
2581
+ thread.innerHTML += '<div class="modal-qa-a" style="color:var(--red)">Error: ' + escHtml(data.error || 'Failed') + '</div>';
2366
2582
  }
2367
2583
  } catch (e) {
2368
2584
  const loadingEl = document.getElementById(loadingId);
@@ -2370,17 +2586,14 @@ async function modalAskSubmit() {
2370
2586
  thread.innerHTML += '<div class="modal-qa-a" style="color:var(--red)">Error: ' + escHtml(e.message) + '</div>';
2371
2587
  }
2372
2588
 
2373
- _modalDocContext.selection = ''; // Clear selection after asking
2589
+ _modalDocContext.selection = '';
2374
2590
  document.getElementById('modal-qa-pill').style.display = 'none';
2375
- document.getElementById('modal-qa-input').placeholder = 'Ask another question...';
2376
2591
  btn.disabled = false;
2592
+ document.getElementById('modal-qa-btn').disabled = false;
2377
2593
  thread.scrollTop = thread.scrollHeight;
2378
2594
  input.focus();
2379
2595
  }
2380
2596
 
2381
- // Override closeModal to clear Q&A state
2382
- const _origCloseModal = typeof closeModal === 'function' ? closeModal : null;
2383
-
2384
2597
  // ─── Plans (Approval Gate) ────────────────────────────────────────────────────
2385
2598
 
2386
2599
  async function refreshPlans() {
@@ -2411,11 +2624,10 @@ function renderPlans(plans) {
2411
2624
 
2412
2625
  let actions = '';
2413
2626
  if (needsAction) {
2414
- actions = '<div class="plan-card-actions">' +
2627
+ actions = '<div class="plan-card-actions" onclick="event.stopPropagation()">' +
2415
2628
  '<button class="plan-btn approve" onclick="planApprove(\'' + escHtml(p.file) + '\')">Approve</button>' +
2416
2629
  '<button class="plan-btn" style="color:var(--blue);border-color:var(--blue)" onclick="planDiscuss(\'' + escHtml(p.file) + '\')">Discuss &amp; Revise</button>' +
2417
2630
  '<button class="plan-btn reject" onclick="planReject(\'' + escHtml(p.file) + '\')">Reject</button>' +
2418
- '<button class="plan-btn" onclick="planView(\'' + escHtml(p.file) + '\')">View Full Plan</button>' +
2419
2631
  '</div>' +
2420
2632
  '<div id="revise-input-' + escHtml(p.file).replace(/\./g, '-') + '" style="display:none">' +
2421
2633
  '<textarea class="plan-feedback-input" placeholder="What should be changed? Be specific..." id="revise-feedback-' + escHtml(p.file).replace(/\./g, '-') + '"></textarea>' +
@@ -2426,11 +2638,10 @@ function renderPlans(plans) {
2426
2638
  '</div>';
2427
2639
  } else if (isRevision) {
2428
2640
  actions = '<div class="plan-card-meta" style="margin-top:6px;color:var(--purple,#a855f7)">Revision in progress: ' + escHtml((p.revisionFeedback || '').slice(0, 100)) + '</div>';
2429
- } else if (status === 'approved' || status === 'active') {
2430
- actions = '<div class="plan-card-actions"><button class="plan-btn" onclick="planView(\'' + escHtml(p.file) + '\')">View</button></div>';
2431
2641
  }
2642
+ // No else needed — whole card is clickable
2432
2643
 
2433
- return '<div class="plan-card ' + statusClass(status) + '">' +
2644
+ return '<div class="plan-card ' + statusClass(status) + '" style="cursor:pointer" onclick="planView(\'' + escHtml(p.file) + '\')">' +
2434
2645
  '<div class="plan-card-header">' +
2435
2646
  '<div><div class="plan-card-title">' + escHtml(p.summary || p.file) + '</div>' +
2436
2647
  '<div class="plan-card-meta">' +
@@ -2517,19 +2728,41 @@ async function planDiscuss(file) {
2517
2728
 
2518
2729
  async function planView(file) {
2519
2730
  try {
2520
- const plan = await fetch('/api/plans/' + encodeURIComponent(file)).then(r => r.json());
2521
- const items = (plan.missing_features || []).map((f, i) =>
2522
- (i + 1) + '. [' + f.id + '] ' + f.name + ' (' + f.estimated_complexity + ', ' + f.priority + ')' +
2523
- (f.depends_on?.length ? ' → depends on: ' + f.depends_on.join(', ') : '') +
2524
- '\n ' + (f.description || '').slice(0, 150)
2525
- ).join('\n\n');
2526
- const text = 'Project: ' + plan.project + '\nStrategy: ' + (plan.branch_strategy || 'parallel') +
2527
- '\nBranch: ' + (plan.feature_branch || 'per-item') +
2528
- '\nStatus: ' + (plan.status || 'active') +
2529
- '\n\n--- Items ---\n\n' + items +
2530
- (plan.open_questions?.length ? '\n\n--- Open Questions ---\n\n' + plan.open_questions.join('\n') : '');
2531
- document.getElementById('modal-title').textContent = plan.plan_summary || file;
2731
+ const raw = await fetch('/api/plans/' + encodeURIComponent(file)).then(r => r.text());
2732
+ let title = file;
2733
+ let text = '';
2734
+
2735
+ if (file.endsWith('.json')) {
2736
+ // PRD JSON — format nicely
2737
+ const plan = JSON.parse(raw);
2738
+ title = plan.plan_summary || file;
2739
+ const items = (plan.missing_features || []).map((f, i) =>
2740
+ (i + 1) + '. [' + f.id + '] ' + f.name + ' (' + (f.estimated_complexity || '?') + ', ' + (f.priority || '?') + ')' +
2741
+ (f.depends_on?.length ? ' depends on: ' + f.depends_on.join(', ') : '') +
2742
+ '\n ' + (f.description || '').slice(0, 200) +
2743
+ (f.acceptance_criteria?.length ? '\n Criteria: ' + f.acceptance_criteria.join('; ') : '')
2744
+ ).join('\n\n');
2745
+ text = 'Project: ' + (plan.project || '?') +
2746
+ '\nStrategy: ' + (plan.branch_strategy || 'parallel') +
2747
+ '\nBranch: ' + (plan.feature_branch || 'per-item') +
2748
+ '\nStatus: ' + (plan.status || 'active') +
2749
+ '\nGenerated by: ' + (plan.generated_by || '?') + ' on ' + (plan.generated_at || '?') +
2750
+ '\n\n--- Items (' + (plan.missing_features || []).length + ') ---\n\n' + items +
2751
+ (plan.open_questions?.length ? '\n\n--- Open Questions ---\n\n' + plan.open_questions.map(q => '• ' + q).join('\n') : '');
2752
+ } else {
2753
+ // Markdown plan — show as-is
2754
+ text = raw;
2755
+ const titleMatch = raw.match(/^#\s+(?:Plan:\s*)?(.+)/m);
2756
+ if (titleMatch) title = titleMatch[1];
2757
+ }
2758
+
2759
+ document.getElementById('modal-title').textContent = title;
2532
2760
  document.getElementById('modal-body').textContent = text;
2761
+ document.getElementById('modal-body').style.fontFamily = 'Consolas, monospace';
2762
+ document.getElementById('modal-body').style.whiteSpace = 'pre-wrap';
2763
+ _modalDocContext = { title, content: text, selection: '' };
2764
+ _modalFilePath = 'plans/' + file;
2765
+ // steer btn removed — unified send
2533
2766
  document.getElementById('modal').classList.add('open');
2534
2767
  } catch (e) { console.error(e); }
2535
2768
  }
@@ -2627,10 +2860,12 @@ function kbSetTab(tab) {
2627
2860
  async function kbOpenItem(category, file) {
2628
2861
  try {
2629
2862
  const content = await fetch('/api/knowledge/' + category + '/' + encodeURIComponent(file)).then(r => r.text());
2630
- // Strip frontmatter for display
2631
2863
  const display = content.replace(/^---[\s\S]*?---\n*/m, '');
2632
2864
  document.getElementById('modal-title').textContent = file;
2633
2865
  document.getElementById('modal-body').textContent = display;
2866
+ _modalDocContext = { title: file, content: display, selection: '' };
2867
+ _modalFilePath = 'knowledge/' + category + '/' + file;
2868
+ // steer btn removed — unified send
2634
2869
  document.getElementById('modal').classList.add('open');
2635
2870
  } catch (e) {
2636
2871
  console.error('Failed to load KB item:', e);