fraim-framework 2.0.124 → 2.0.127
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/bin/fraim.js +1 -1
- package/dist/src/ai-hub/catalog.js +280 -44
- package/dist/src/ai-hub/desktop-main.js +2 -2
- package/dist/src/ai-hub/hosts.js +384 -10
- package/dist/src/ai-hub/server.js +255 -9
- package/dist/src/cli/commands/add-ide.js +4 -3
- package/dist/src/cli/commands/first-run.js +61 -0
- package/dist/src/cli/commands/hub.js +4 -4
- package/dist/src/cli/commands/init-project.js +4 -4
- package/dist/src/cli/commands/setup.js +4 -3
- package/dist/src/cli/commands/sync.js +21 -2
- package/dist/src/cli/doctor/checks/ide-config-checks.js +20 -2
- package/dist/src/cli/fraim.js +2 -0
- package/dist/src/cli/mcp/ide-formats.js +29 -1
- package/dist/src/cli/mcp/mcp-server-registry.js +1 -0
- package/dist/src/cli/setup/auto-mcp-setup.js +14 -8
- package/dist/src/cli/setup/ide-detector.js +32 -1
- package/dist/src/cli/setup/ide-global-integration.js +5 -1
- package/dist/src/cli/setup/ide-invocation-surfaces.js +70 -17
- package/dist/src/cli/setup/mcp-config-generator.js +12 -1
- package/dist/src/cli/utils/agent-adapters.js +12 -2
- package/dist/src/cli/utils/project-bootstrap.js +4 -3
- package/dist/src/core/quality-evidence.js +81 -8
- package/dist/src/core/utils/git-utils.js +32 -7
- package/dist/src/core/utils/job-aliases.js +47 -0
- package/dist/src/core/utils/workflow-parser.js +3 -5
- package/dist/src/first-run/install-state.js +68 -0
- package/dist/src/first-run/server.js +153 -0
- package/dist/src/first-run/session-service.js +302 -0
- package/dist/src/first-run/types.js +40 -0
- package/dist/src/local-mcp-server/agent-token-prices.js +114 -0
- package/dist/src/local-mcp-server/codex-token-adapter.js +232 -0
- package/dist/src/local-mcp-server/learning-context-builder.js +21 -8
- package/dist/src/local-mcp-server/otlp-metrics-receiver.js +7 -1
- package/dist/src/local-mcp-server/stdio-server.js +70 -17
- package/dist/src/local-mcp-server/token-adapter-registry.js +64 -0
- package/dist/src/local-mcp-server/usage-collector.js +25 -0
- package/index.js +83 -83
- package/package.json +7 -1
- package/public/ai-hub/index.html +149 -102
- package/public/ai-hub/script.js +1154 -271
- package/public/ai-hub/styles.css +753 -450
- package/public/first-run/index.html +221 -0
- package/public/first-run/script.js +361 -0
- package/dist/src/cli/services/device-flow-service.js +0 -83
- package/dist/src/local-mcp-server/prometheus-scraper.js +0 -152
package/public/ai-hub/styles.css
CHANGED
|
@@ -1,568 +1,871 @@
|
|
|
1
1
|
:root {
|
|
2
2
|
color-scheme: light;
|
|
3
|
-
--
|
|
4
|
-
--visa-gold: #f7b600;
|
|
5
|
-
--ink: #10233f;
|
|
6
|
-
--muted: #607089;
|
|
3
|
+
--bg: #f4f6f2;
|
|
7
4
|
--surface: #ffffff;
|
|
8
|
-
--
|
|
9
|
-
--
|
|
10
|
-
--
|
|
11
|
-
--
|
|
12
|
-
--
|
|
13
|
-
--
|
|
14
|
-
--
|
|
15
|
-
--
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
|
|
5
|
+
--soft: #f7faf6;
|
|
6
|
+
--line: #e3e8df;
|
|
7
|
+
--text: #1f2a24;
|
|
8
|
+
--muted: #6b7a72;
|
|
9
|
+
--accent: #3d8a6e;
|
|
10
|
+
--accent-strong: #2f7359;
|
|
11
|
+
--accent-soft: #eaf3ee;
|
|
12
|
+
--warn: #b08442;
|
|
13
|
+
--warn-soft: #fffaf0;
|
|
14
|
+
--danger: #a24747;
|
|
15
|
+
--shadow: 0 1px 2px rgba(20, 40, 30, 0.04);
|
|
16
|
+
--shadow-lg: 0 12px 36px rgba(20, 40, 30, 0.18);
|
|
17
|
+
/* Issue #347 — picker group dots. Decorative only; the picker uses
|
|
18
|
+
these to scan groups by color without adding semantic weight. Kept
|
|
19
|
+
as variables so future themes flow through here. */
|
|
20
|
+
--picker-delegation: #5b7eb0;
|
|
21
|
+
--picker-learning: #8b5fbf;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
* { box-sizing: border-box; }
|
|
25
|
+
html, body { margin: 0; padding: 0; }
|
|
26
|
+
[hidden] { display: none !important; }
|
|
27
|
+
|
|
28
|
+
html, body { height: 100%; }
|
|
27
29
|
body {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
overflow
|
|
36
|
-
overflow-y: auto;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
button,
|
|
40
|
-
input,
|
|
41
|
-
textarea {
|
|
42
|
-
font: inherit;
|
|
30
|
+
font-family: -apple-system, "Segoe UI", "Helvetica Neue", Arial, sans-serif;
|
|
31
|
+
color: var(--text);
|
|
32
|
+
background: var(--bg);
|
|
33
|
+
line-height: 1.5;
|
|
34
|
+
font-size: 15px;
|
|
35
|
+
/* Issue #339 fix: bound the page to the viewport. The conversation
|
|
36
|
+
pane scrolls internally instead of growing the entire page. */
|
|
37
|
+
overflow: hidden;
|
|
43
38
|
}
|
|
44
39
|
|
|
45
|
-
|
|
46
|
-
color: var(--visa-blue);
|
|
47
|
-
}
|
|
40
|
+
button { font: inherit; cursor: pointer; }
|
|
48
41
|
|
|
49
|
-
.
|
|
50
|
-
max-width:
|
|
42
|
+
.page {
|
|
43
|
+
max-width: 1080px;
|
|
51
44
|
margin: 0 auto;
|
|
52
|
-
padding:
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
.app-header {
|
|
60
|
-
display: grid;
|
|
61
|
-
grid-template-columns: minmax(0, 1fr) minmax(360px, 440px);
|
|
62
|
-
gap: 18px;
|
|
63
|
-
align-items: stretch;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
.brand-lockup {
|
|
67
|
-
padding: 18px 0 8px;
|
|
68
|
-
display: grid;
|
|
69
|
-
gap: 4px;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
.brand-title {
|
|
73
|
-
font-size: 32px;
|
|
74
|
-
line-height: 1.05;
|
|
75
|
-
font-weight: 800;
|
|
76
|
-
color: var(--ink);
|
|
45
|
+
padding: 24px;
|
|
46
|
+
display: flex;
|
|
47
|
+
flex-direction: column;
|
|
48
|
+
gap: 20px;
|
|
49
|
+
height: 100vh;
|
|
50
|
+
min-height: 0;
|
|
77
51
|
}
|
|
78
52
|
|
|
79
|
-
|
|
80
|
-
.
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
53
|
+
/* Header */
|
|
54
|
+
.header {
|
|
55
|
+
display: flex;
|
|
56
|
+
align-items: center;
|
|
57
|
+
justify-content: space-between;
|
|
58
|
+
gap: 16px;
|
|
84
59
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
font-
|
|
88
|
-
|
|
89
|
-
letter-spacing: 0;
|
|
90
|
-
text-transform: uppercase;
|
|
60
|
+
.header h1 {
|
|
61
|
+
font-size: 22px;
|
|
62
|
+
font-weight: 600;
|
|
63
|
+
margin: 0;
|
|
64
|
+
letter-spacing: -0.01em;
|
|
91
65
|
}
|
|
92
|
-
|
|
93
|
-
.section-label {
|
|
66
|
+
.project-button {
|
|
94
67
|
display: inline-flex;
|
|
95
68
|
align-items: center;
|
|
96
69
|
gap: 8px;
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
h1,
|
|
100
|
-
h2,
|
|
101
|
-
p {
|
|
102
|
-
margin: 0;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
.topbar-card,
|
|
106
|
-
.card {
|
|
107
|
-
background: var(--surface-soft);
|
|
108
|
-
backdrop-filter: blur(16px);
|
|
70
|
+
background: var(--surface);
|
|
109
71
|
border: 1px solid var(--line);
|
|
110
|
-
border-radius:
|
|
72
|
+
border-radius: 10px;
|
|
73
|
+
padding: 8px 14px;
|
|
74
|
+
color: var(--text);
|
|
111
75
|
box-shadow: var(--shadow);
|
|
76
|
+
max-width: 360px;
|
|
112
77
|
}
|
|
113
|
-
|
|
114
|
-
.
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
.workspace-card {
|
|
124
|
-
align-self: stretch;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
.workspace-section {
|
|
128
|
-
display: grid;
|
|
129
|
-
gap: 10px;
|
|
78
|
+
.project-button:hover { background: var(--soft); }
|
|
79
|
+
.project-button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
|
80
|
+
.project-button .folder { color: var(--muted); font-size: 13px; }
|
|
81
|
+
.project-button strong {
|
|
82
|
+
font-weight: 600;
|
|
83
|
+
white-space: nowrap;
|
|
84
|
+
overflow: hidden;
|
|
85
|
+
text-overflow: ellipsis;
|
|
130
86
|
}
|
|
131
87
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
88
|
+
/* Welcome line */
|
|
89
|
+
.welcome {
|
|
90
|
+
background: var(--surface);
|
|
91
|
+
border: 1px solid var(--line);
|
|
92
|
+
border-radius: 14px;
|
|
93
|
+
padding: 18px 24px;
|
|
94
|
+
box-shadow: var(--shadow);
|
|
95
|
+
font-size: 15px;
|
|
96
|
+
line-height: 1.7;
|
|
97
|
+
color: var(--muted);
|
|
135
98
|
}
|
|
136
|
-
|
|
137
|
-
.
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
.composer-actions {
|
|
142
|
-
display: flex;
|
|
143
|
-
flex-wrap: wrap;
|
|
144
|
-
gap: 10px;
|
|
99
|
+
.welcome strong.you { color: var(--text); font-weight: 600; }
|
|
100
|
+
.welcome .concept {
|
|
101
|
+
position: relative;
|
|
102
|
+
font-weight: 600;
|
|
103
|
+
color: var(--accent);
|
|
145
104
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
border-radius:
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
105
|
+
.welcome .info {
|
|
106
|
+
display: inline-flex;
|
|
107
|
+
align-items: center;
|
|
108
|
+
justify-content: center;
|
|
109
|
+
width: 16px;
|
|
110
|
+
height: 16px;
|
|
111
|
+
border-radius: 50%;
|
|
112
|
+
background: var(--accent-soft);
|
|
113
|
+
color: var(--accent);
|
|
114
|
+
font-size: 11px;
|
|
115
|
+
font-weight: 700;
|
|
116
|
+
margin-left: 3px;
|
|
117
|
+
margin-right: 1px;
|
|
157
118
|
cursor: pointer;
|
|
158
|
-
|
|
119
|
+
vertical-align: 1px;
|
|
120
|
+
border: none;
|
|
121
|
+
font-family: serif;
|
|
122
|
+
font-style: italic;
|
|
123
|
+
}
|
|
124
|
+
.welcome .info:hover { background: var(--accent); color: #fff; }
|
|
125
|
+
.welcome .info:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
|
126
|
+
.popover {
|
|
127
|
+
position: absolute;
|
|
128
|
+
top: calc(100% + 10px);
|
|
129
|
+
left: 0;
|
|
130
|
+
width: 320px;
|
|
131
|
+
/* Hard cap + internal scroll so a verbose explanation never clips off
|
|
132
|
+
the bottom of the viewport (was a real bug — popover content used to
|
|
133
|
+
run past the bottom edge with no way to read it). */
|
|
134
|
+
max-height: min(60vh, 480px);
|
|
135
|
+
overflow-y: auto;
|
|
136
|
+
background: var(--surface);
|
|
137
|
+
border: 1px solid var(--line);
|
|
138
|
+
border-radius: 12px;
|
|
139
|
+
padding: 14px 16px;
|
|
140
|
+
box-shadow: var(--shadow-lg);
|
|
141
|
+
z-index: 50;
|
|
142
|
+
font-weight: 400;
|
|
143
|
+
font-size: 14px;
|
|
144
|
+
color: var(--text);
|
|
145
|
+
line-height: 1.5;
|
|
146
|
+
display: none;
|
|
159
147
|
}
|
|
160
|
-
|
|
161
|
-
.
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
transform: translateY(-1px);
|
|
148
|
+
.popover.open { display: block; }
|
|
149
|
+
.popover .pop-title {
|
|
150
|
+
display: block;
|
|
151
|
+
font-weight: 600;
|
|
152
|
+
color: var(--text);
|
|
153
|
+
margin-bottom: 6px;
|
|
167
154
|
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
155
|
+
.popover .pop-link {
|
|
156
|
+
display: inline-block;
|
|
157
|
+
margin-top: 10px;
|
|
158
|
+
color: var(--accent);
|
|
159
|
+
font-size: 13px;
|
|
160
|
+
text-decoration: none;
|
|
161
|
+
font-weight: 500;
|
|
175
162
|
}
|
|
176
|
-
|
|
177
|
-
.
|
|
178
|
-
|
|
163
|
+
.popover .pop-link:hover { text-decoration: underline; }
|
|
164
|
+
.popover .pop-jobs {
|
|
165
|
+
display: none;
|
|
166
|
+
margin-top: 10px;
|
|
167
|
+
padding-top: 10px;
|
|
168
|
+
border-top: 1px solid var(--line);
|
|
179
169
|
}
|
|
180
|
-
|
|
181
|
-
.
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
font-weight: 700;
|
|
186
|
-
box-shadow: 0 12px 24px rgba(20, 52, 203, 0.2);
|
|
170
|
+
.popover .pop-jobs.open { display: grid; gap: 8px; }
|
|
171
|
+
.popover .pop-jobs .job-row {
|
|
172
|
+
display: grid;
|
|
173
|
+
gap: 1px;
|
|
174
|
+
font-size: 13px;
|
|
187
175
|
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
opacity: 0.45;
|
|
192
|
-
cursor: not-allowed;
|
|
176
|
+
.popover .pop-jobs .job-row strong {
|
|
177
|
+
color: var(--accent);
|
|
178
|
+
font-weight: 600;
|
|
193
179
|
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
display: grid;
|
|
197
|
-
grid-template-columns: 340px minmax(0, 1fr);
|
|
198
|
-
gap: 18px;
|
|
199
|
-
align-items: start;
|
|
180
|
+
.popover .pop-jobs .job-row span {
|
|
181
|
+
color: var(--muted);
|
|
200
182
|
}
|
|
201
183
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
padding: 18px 20px;
|
|
184
|
+
/* Layout */
|
|
185
|
+
.layout {
|
|
205
186
|
display: grid;
|
|
206
|
-
grid-template-columns: minmax(0, 1fr)
|
|
207
|
-
gap:
|
|
208
|
-
align-items:
|
|
187
|
+
grid-template-columns: 260px minmax(0, 1fr);
|
|
188
|
+
gap: 20px;
|
|
189
|
+
align-items: stretch;
|
|
190
|
+
flex: 1;
|
|
191
|
+
min-height: 0;
|
|
209
192
|
}
|
|
210
193
|
|
|
211
|
-
|
|
212
|
-
.
|
|
194
|
+
/* Left rail */
|
|
195
|
+
.rail {
|
|
213
196
|
display: grid;
|
|
214
|
-
|
|
197
|
+
grid-template-columns: minmax(0, 1fr);
|
|
198
|
+
grid-auto-rows: min-content;
|
|
199
|
+
gap: 8px;
|
|
200
|
+
min-width: 0;
|
|
201
|
+
align-self: start;
|
|
202
|
+
max-height: 100%;
|
|
203
|
+
overflow-y: auto;
|
|
215
204
|
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
205
|
+
.new-conv {
|
|
206
|
+
width: 100%;
|
|
207
|
+
background: var(--accent);
|
|
208
|
+
color: #fff;
|
|
209
|
+
border: none;
|
|
210
|
+
border-radius: 10px;
|
|
211
|
+
padding: 10px 14px;
|
|
212
|
+
font-weight: 600;
|
|
213
|
+
box-shadow: var(--shadow);
|
|
219
214
|
}
|
|
220
|
-
|
|
221
|
-
.
|
|
222
|
-
.
|
|
215
|
+
.new-conv:hover { background: var(--accent-strong); }
|
|
216
|
+
.new-conv:focus-visible { outline: 2px solid var(--accent-strong); outline-offset: 2px; }
|
|
217
|
+
.conv-list {
|
|
223
218
|
display: grid;
|
|
224
|
-
|
|
219
|
+
grid-template-columns: minmax(0, 1fr);
|
|
220
|
+
gap: 4px;
|
|
221
|
+
margin-top: 4px;
|
|
222
|
+
min-width: 0;
|
|
225
223
|
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
align
|
|
224
|
+
.conv-item {
|
|
225
|
+
width: 100%;
|
|
226
|
+
text-align: left;
|
|
227
|
+
background: transparent;
|
|
228
|
+
border: 1px solid transparent;
|
|
229
|
+
border-radius: 10px;
|
|
230
|
+
padding: 10px 12px;
|
|
231
|
+
display: flex;
|
|
232
|
+
align-items: center;
|
|
233
|
+
justify-content: space-between;
|
|
234
|
+
gap: 8px;
|
|
235
|
+
color: var(--text);
|
|
229
236
|
}
|
|
230
|
-
|
|
231
|
-
.
|
|
232
|
-
|
|
237
|
+
.conv-item:hover { background: var(--soft); }
|
|
238
|
+
.conv-item.active {
|
|
239
|
+
background: var(--surface);
|
|
240
|
+
border-color: var(--line);
|
|
241
|
+
box-shadow: var(--shadow);
|
|
233
242
|
}
|
|
234
|
-
|
|
235
|
-
.
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
243
|
+
.conv-title { font-weight: 500; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
244
|
+
.conv-status {
|
|
245
|
+
font-size: 12px;
|
|
246
|
+
color: var(--muted);
|
|
247
|
+
font-weight: 500;
|
|
248
|
+
flex-shrink: 0;
|
|
239
249
|
}
|
|
250
|
+
.conv-status.running { color: var(--accent); }
|
|
251
|
+
.conv-status.attention { color: var(--warn); }
|
|
252
|
+
.conv-status.failed { color: var(--danger); }
|
|
240
253
|
|
|
241
|
-
.
|
|
254
|
+
/* Conversation pane — fills the layout column vertically. Inner regions
|
|
255
|
+
manage their own height; the .messages list is the only scrollable area. */
|
|
256
|
+
.conversation {
|
|
257
|
+
background: var(--surface);
|
|
258
|
+
border: 1px solid var(--line);
|
|
259
|
+
border-radius: 14px;
|
|
260
|
+
box-shadow: var(--shadow);
|
|
261
|
+
padding: 18px 20px;
|
|
262
|
+
display: flex;
|
|
263
|
+
flex-direction: column;
|
|
264
|
+
gap: 14px;
|
|
265
|
+
min-height: 0;
|
|
266
|
+
min-width: 0;
|
|
267
|
+
height: 100%;
|
|
268
|
+
overflow: hidden;
|
|
269
|
+
}
|
|
270
|
+
.empty-state {
|
|
242
271
|
display: grid;
|
|
243
|
-
gap:
|
|
272
|
+
gap: 8px;
|
|
273
|
+
place-items: center;
|
|
274
|
+
text-align: center;
|
|
275
|
+
color: var(--muted);
|
|
276
|
+
padding: 80px 16px;
|
|
244
277
|
}
|
|
278
|
+
.empty-state h3 { margin: 0; color: var(--text); font-weight: 600; font-size: 17px; }
|
|
279
|
+
.empty-state p { margin: 0; max-width: 320px; }
|
|
245
280
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
281
|
+
#active-conv {
|
|
282
|
+
display: flex;
|
|
283
|
+
flex-direction: column;
|
|
284
|
+
gap: 12px;
|
|
285
|
+
min-width: 0;
|
|
286
|
+
flex: 1;
|
|
287
|
+
min-height: 0;
|
|
250
288
|
}
|
|
251
289
|
|
|
252
|
-
.
|
|
253
|
-
|
|
254
|
-
|
|
290
|
+
.conv-header,
|
|
291
|
+
.coach,
|
|
292
|
+
.micro,
|
|
293
|
+
.progress {
|
|
294
|
+
flex-shrink: 0;
|
|
295
|
+
}
|
|
296
|
+
.conv-header {
|
|
297
|
+
display: flex;
|
|
298
|
+
flex-wrap: wrap;
|
|
299
|
+
align-items: baseline;
|
|
300
|
+
column-gap: 12px;
|
|
301
|
+
row-gap: 4px;
|
|
255
302
|
}
|
|
303
|
+
.conv-header h2 { flex: 1 1 auto; min-width: 0; }
|
|
304
|
+
#artifact-slot { flex: 0 0 auto; }
|
|
256
305
|
|
|
257
|
-
.
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
306
|
+
.conv-header h2 { margin: 0; font-size: 18px; font-weight: 600; }
|
|
307
|
+
.conv-job { color: var(--muted); font-size: 14px; margin-top: 2px; }
|
|
308
|
+
|
|
309
|
+
.section-title {
|
|
310
|
+
font-size: 13px;
|
|
311
|
+
font-weight: 600;
|
|
312
|
+
color: var(--muted);
|
|
313
|
+
text-transform: uppercase;
|
|
314
|
+
letter-spacing: 0.05em;
|
|
315
|
+
margin-bottom: 8px;
|
|
264
316
|
}
|
|
265
317
|
|
|
266
|
-
|
|
267
|
-
|
|
318
|
+
/* Progress is now a single-line status strip (was a tall card) so the
|
|
319
|
+
messages region gets the vertical space it needs. */
|
|
320
|
+
.progress {
|
|
321
|
+
background: var(--soft);
|
|
322
|
+
border: 1px solid var(--line);
|
|
323
|
+
border-radius: 8px;
|
|
324
|
+
padding: 8px 12px;
|
|
325
|
+
font-size: 13px;
|
|
268
326
|
display: flex;
|
|
269
327
|
align-items: center;
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
cursor: pointer;
|
|
274
|
-
font-weight: 600;
|
|
328
|
+
gap: 10px;
|
|
329
|
+
min-width: 0;
|
|
330
|
+
overflow: hidden;
|
|
275
331
|
}
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
332
|
+
.progress .stage {
|
|
333
|
+
font-weight: 600;
|
|
334
|
+
color: var(--text);
|
|
335
|
+
flex-shrink: 0;
|
|
279
336
|
}
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
max-width: 180px;
|
|
337
|
+
.progress .latest {
|
|
338
|
+
color: var(--muted);
|
|
339
|
+
white-space: nowrap;
|
|
284
340
|
overflow: hidden;
|
|
285
341
|
text-overflow: ellipsis;
|
|
286
|
-
|
|
287
|
-
color: var(--muted);
|
|
288
|
-
font-size: 13px;
|
|
289
|
-
font-weight: 500;
|
|
342
|
+
min-width: 0;
|
|
290
343
|
}
|
|
291
|
-
|
|
292
|
-
|
|
344
|
+
.progress .stage::before {
|
|
345
|
+
content: "";
|
|
346
|
+
display: inline-block;
|
|
347
|
+
width: 7px;
|
|
348
|
+
height: 7px;
|
|
349
|
+
border-radius: 50%;
|
|
350
|
+
background: var(--accent);
|
|
351
|
+
margin-right: 6px;
|
|
352
|
+
vertical-align: 1px;
|
|
353
|
+
animation: pulse 1.4s infinite;
|
|
354
|
+
}
|
|
355
|
+
.progress.done .stage::before { background: #6cb39a; animation: none; }
|
|
356
|
+
.progress.attention .stage::before { background: var(--warn); animation: none; }
|
|
357
|
+
.progress.failed .stage::before { background: var(--danger); animation: none; }
|
|
358
|
+
@keyframes pulse {
|
|
359
|
+
0%, 100% { opacity: 1; transform: scale(1); }
|
|
360
|
+
50% { opacity: 0.5; transform: scale(0.8); }
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
.messages {
|
|
293
364
|
display: grid;
|
|
294
|
-
|
|
295
|
-
|
|
365
|
+
grid-template-columns: minmax(0, 1fr);
|
|
366
|
+
gap: 10px;
|
|
367
|
+
margin-top: 12px;
|
|
368
|
+
min-width: 0;
|
|
369
|
+
/* Scroll messages here, not the page. */
|
|
370
|
+
flex: 1;
|
|
371
|
+
min-height: 0;
|
|
372
|
+
overflow-y: auto;
|
|
373
|
+
padding-right: 4px;
|
|
296
374
|
}
|
|
297
|
-
|
|
298
|
-
.
|
|
299
|
-
|
|
300
|
-
|
|
375
|
+
.message { word-wrap: break-word; overflow-wrap: anywhere; }
|
|
376
|
+
.message {
|
|
377
|
+
border-radius: 10px;
|
|
378
|
+
padding: 10px 14px;
|
|
379
|
+
font-size: 14px;
|
|
380
|
+
line-height: 1.5;
|
|
381
|
+
animation: slidein 280ms ease;
|
|
382
|
+
}
|
|
383
|
+
@keyframes slidein {
|
|
384
|
+
from { opacity: 0; transform: translateY(6px); }
|
|
385
|
+
to { opacity: 1; transform: translateY(0); }
|
|
386
|
+
}
|
|
387
|
+
.message.manager {
|
|
388
|
+
background: var(--accent-soft);
|
|
389
|
+
border: 1px solid #c5dcd0;
|
|
390
|
+
color: var(--text);
|
|
391
|
+
}
|
|
392
|
+
.message.employee {
|
|
393
|
+
background: var(--soft);
|
|
301
394
|
border: 1px solid var(--line);
|
|
302
|
-
|
|
303
|
-
background: var(--surface-muted);
|
|
304
|
-
padding: 11px 12px;
|
|
305
|
-
color: var(--ink);
|
|
395
|
+
color: var(--text);
|
|
306
396
|
}
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
397
|
+
.message .who {
|
|
398
|
+
font-size: 11px;
|
|
399
|
+
font-weight: 600;
|
|
400
|
+
text-transform: uppercase;
|
|
401
|
+
letter-spacing: 0.04em;
|
|
402
|
+
color: var(--muted);
|
|
403
|
+
display: block;
|
|
404
|
+
margin-bottom: 4px;
|
|
312
405
|
}
|
|
313
406
|
|
|
314
|
-
.
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
407
|
+
/* Inline artifact pill that sits in the .conv-header next to the title.
|
|
408
|
+
Compact so it never crowds Coach or Micro-manage. Hover reveals the
|
|
409
|
+
path so the user can locate the file. */
|
|
410
|
+
.artifact {
|
|
411
|
+
display: inline-flex;
|
|
412
|
+
align-items: center;
|
|
413
|
+
gap: 6px;
|
|
414
|
+
background: var(--warn-soft);
|
|
415
|
+
border: 1px solid #ecd9b0;
|
|
416
|
+
border-radius: 999px;
|
|
417
|
+
padding: 4px 10px;
|
|
418
|
+
font-size: 12px;
|
|
419
|
+
color: var(--text);
|
|
420
|
+
max-width: 320px;
|
|
421
|
+
animation: slidein 280ms ease;
|
|
422
|
+
}
|
|
423
|
+
.artifact-dot {
|
|
424
|
+
width: 6px;
|
|
425
|
+
height: 6px;
|
|
426
|
+
border-radius: 50%;
|
|
427
|
+
background: var(--warn);
|
|
428
|
+
flex-shrink: 0;
|
|
429
|
+
}
|
|
430
|
+
.artifact-label {
|
|
431
|
+
font-weight: 600;
|
|
432
|
+
color: var(--warn);
|
|
433
|
+
text-transform: uppercase;
|
|
434
|
+
letter-spacing: 0.04em;
|
|
435
|
+
font-size: 10px;
|
|
436
|
+
margin-right: 2px;
|
|
318
437
|
}
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
overflow:
|
|
324
|
-
|
|
438
|
+
.artifact-name {
|
|
439
|
+
font-weight: 500;
|
|
440
|
+
white-space: nowrap;
|
|
441
|
+
overflow: hidden;
|
|
442
|
+
text-overflow: ellipsis;
|
|
443
|
+
min-width: 0;
|
|
325
444
|
}
|
|
445
|
+
.artifact-where { display: none; } /* full path lives in tooltip via title attr */
|
|
326
446
|
|
|
327
|
-
.
|
|
447
|
+
.coach textarea {
|
|
328
448
|
width: 100%;
|
|
329
|
-
|
|
330
|
-
|
|
449
|
+
min-height: 56px;
|
|
450
|
+
max-height: 30vh;
|
|
451
|
+
resize: vertical;
|
|
331
452
|
border: 1px solid var(--line);
|
|
332
|
-
|
|
333
|
-
padding:
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
.job-list button:hover {
|
|
340
|
-
transform: translateY(-1px);
|
|
341
|
-
border-color: rgba(20, 52, 203, 0.32);
|
|
453
|
+
border-radius: 10px;
|
|
454
|
+
padding: 10px 14px;
|
|
455
|
+
font: inherit;
|
|
456
|
+
color: var(--text);
|
|
457
|
+
background: var(--surface);
|
|
342
458
|
}
|
|
343
|
-
|
|
344
|
-
.
|
|
345
|
-
|
|
346
|
-
background: var(--
|
|
459
|
+
.coach textarea:focus { outline: none; border-color: var(--accent); }
|
|
460
|
+
.coach-actions { display: flex; justify-content: flex-end; margin-top: 10px; }
|
|
461
|
+
.send-button {
|
|
462
|
+
background: var(--accent);
|
|
463
|
+
color: #fff;
|
|
464
|
+
border: none;
|
|
465
|
+
border-radius: 10px;
|
|
466
|
+
padding: 10px 18px;
|
|
467
|
+
font-weight: 600;
|
|
347
468
|
}
|
|
469
|
+
.send-button:hover { background: var(--accent-strong); }
|
|
470
|
+
.send-button:focus-visible { outline: 2px solid var(--accent-strong); outline-offset: 2px; }
|
|
471
|
+
.send-button:disabled { background: #c5d2cb; cursor: not-allowed; }
|
|
348
472
|
|
|
349
|
-
.
|
|
350
|
-
|
|
351
|
-
|
|
473
|
+
.micro {
|
|
474
|
+
border-top: 1px solid var(--line);
|
|
475
|
+
padding-top: 16px;
|
|
352
476
|
}
|
|
353
|
-
|
|
354
|
-
|
|
477
|
+
.micro summary {
|
|
478
|
+
cursor: pointer;
|
|
355
479
|
color: var(--muted);
|
|
356
|
-
line-height: 1.45;
|
|
357
480
|
font-size: 14px;
|
|
481
|
+
list-style: none;
|
|
482
|
+
display: flex;
|
|
483
|
+
align-items: center;
|
|
484
|
+
gap: 6px;
|
|
485
|
+
}
|
|
486
|
+
.micro summary::-webkit-details-marker { display: none; }
|
|
487
|
+
.micro summary::before {
|
|
488
|
+
content: "▸";
|
|
489
|
+
font-size: 11px;
|
|
490
|
+
transition: transform 100ms;
|
|
491
|
+
}
|
|
492
|
+
.micro[open] summary::before { transform: rotate(90deg); }
|
|
493
|
+
.micro-log {
|
|
494
|
+
margin-top: 12px;
|
|
495
|
+
background: #1f2a24;
|
|
496
|
+
color: #c5d2cb;
|
|
497
|
+
border-radius: 8px;
|
|
498
|
+
padding: 12px 14px;
|
|
499
|
+
font-family: Consolas, Menlo, monospace;
|
|
500
|
+
font-size: 12px;
|
|
501
|
+
line-height: 1.6;
|
|
502
|
+
white-space: pre-wrap;
|
|
503
|
+
max-height: 220px;
|
|
504
|
+
overflow-y: auto;
|
|
358
505
|
}
|
|
359
506
|
|
|
360
|
-
.
|
|
361
|
-
display: grid;
|
|
362
|
-
gap: 8px;
|
|
507
|
+
.status-line {
|
|
363
508
|
margin: 0;
|
|
364
|
-
padding-left: 18px;
|
|
365
509
|
color: var(--muted);
|
|
510
|
+
font-size: 13px;
|
|
511
|
+
text-align: center;
|
|
512
|
+
min-height: 1.2em;
|
|
366
513
|
}
|
|
514
|
+
.status-line.error { color: var(--danger); }
|
|
367
515
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
516
|
+
/* Modal */
|
|
517
|
+
.modal-backdrop {
|
|
518
|
+
position: fixed;
|
|
519
|
+
inset: 0;
|
|
520
|
+
background: rgba(20, 40, 30, 0.36);
|
|
521
|
+
display: none;
|
|
522
|
+
align-items: center;
|
|
523
|
+
justify-content: center;
|
|
524
|
+
z-index: 100;
|
|
525
|
+
padding: 20px;
|
|
526
|
+
animation: fade 180ms ease;
|
|
527
|
+
}
|
|
528
|
+
.modal-backdrop.open { display: flex; }
|
|
529
|
+
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }
|
|
530
|
+
|
|
531
|
+
.modal {
|
|
532
|
+
background: var(--surface);
|
|
533
|
+
border-radius: 16px;
|
|
534
|
+
box-shadow: var(--shadow-lg);
|
|
535
|
+
width: 100%;
|
|
536
|
+
max-width: 540px;
|
|
537
|
+
max-height: 90vh;
|
|
375
538
|
display: flex;
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
border-bottom: 1px solid rgba(216, 225, 240, 0.8);
|
|
539
|
+
flex-direction: column;
|
|
540
|
+
overflow: hidden;
|
|
541
|
+
animation: rise 220ms ease;
|
|
542
|
+
min-height: 0;
|
|
381
543
|
}
|
|
382
|
-
|
|
383
|
-
.
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
544
|
+
/* Each step IS the modal's main content — make it a flex column too so
|
|
545
|
+
.modal-body can actually scroll inside the bounded .modal height
|
|
546
|
+
instead of pushing the modal past 90vh. */
|
|
547
|
+
#step1, #step2 {
|
|
548
|
+
display: flex;
|
|
549
|
+
flex-direction: column;
|
|
550
|
+
flex: 1;
|
|
551
|
+
min-height: 0;
|
|
552
|
+
overflow: hidden;
|
|
387
553
|
}
|
|
388
|
-
|
|
389
|
-
|
|
554
|
+
@keyframes rise {
|
|
555
|
+
from { opacity: 0; transform: translateY(12px); }
|
|
556
|
+
to { opacity: 1; transform: translateY(0); }
|
|
557
|
+
}
|
|
558
|
+
.modal-header { padding: 22px 24px 12px; border-bottom: 1px solid var(--line); }
|
|
559
|
+
.modal-header h2 { margin: 0; font-size: 19px; font-weight: 600; }
|
|
560
|
+
.modal-header p { margin: 4px 0 0; color: var(--muted); font-size: 14px; }
|
|
561
|
+
.modal-body { padding: 18px 24px; overflow-y: auto; flex: 1; }
|
|
562
|
+
.modal-footer {
|
|
563
|
+
padding: 14px 24px 18px;
|
|
564
|
+
border-top: 1px solid var(--line);
|
|
390
565
|
display: flex;
|
|
566
|
+
justify-content: space-between;
|
|
391
567
|
align-items: center;
|
|
568
|
+
gap: 12px;
|
|
392
569
|
}
|
|
570
|
+
.modal-footer .left { color: var(--muted); font-size: 13px; }
|
|
571
|
+
.modal-footer .right { display: flex; gap: 10px; }
|
|
393
572
|
|
|
394
|
-
.
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
573
|
+
.ghost {
|
|
574
|
+
background: transparent;
|
|
575
|
+
border: 1px solid var(--line);
|
|
576
|
+
border-radius: 10px;
|
|
577
|
+
padding: 9px 14px;
|
|
578
|
+
color: var(--text);
|
|
579
|
+
font-weight: 500;
|
|
399
580
|
}
|
|
581
|
+
.ghost:hover { background: var(--soft); }
|
|
582
|
+
.ghost:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
|
400
583
|
|
|
401
|
-
.
|
|
402
|
-
|
|
403
|
-
|
|
584
|
+
.search {
|
|
585
|
+
width: 100%;
|
|
586
|
+
border: 1px solid var(--line);
|
|
587
|
+
border-radius: 10px;
|
|
588
|
+
padding: 10px 14px;
|
|
589
|
+
font: inherit;
|
|
590
|
+
margin-bottom: 14px;
|
|
404
591
|
}
|
|
592
|
+
.search:focus { outline: none; border-color: var(--accent); }
|
|
405
593
|
|
|
406
|
-
.
|
|
407
|
-
|
|
408
|
-
|
|
594
|
+
.job-category { margin-bottom: 16px; }
|
|
595
|
+
.job-category h4 {
|
|
596
|
+
font-size: 12px;
|
|
597
|
+
font-weight: 600;
|
|
598
|
+
color: var(--muted);
|
|
599
|
+
text-transform: uppercase;
|
|
600
|
+
letter-spacing: 0.05em;
|
|
601
|
+
margin: 0 0 8px;
|
|
409
602
|
}
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
overflow: auto;
|
|
415
|
-
display: grid;
|
|
416
|
-
gap: 12px;
|
|
417
|
-
padding: 4px;
|
|
418
|
-
align-content: start;
|
|
603
|
+
.job-option {
|
|
604
|
+
width: 100%;
|
|
605
|
+
text-align: left;
|
|
606
|
+
background: transparent;
|
|
419
607
|
border: 1px solid var(--line);
|
|
420
|
-
border-radius:
|
|
421
|
-
|
|
608
|
+
border-radius: 10px;
|
|
609
|
+
padding: 10px 14px;
|
|
610
|
+
margin-bottom: 6px;
|
|
611
|
+
display: grid;
|
|
612
|
+
gap: 2px;
|
|
613
|
+
color: var(--text);
|
|
614
|
+
}
|
|
615
|
+
.job-option:hover { background: var(--soft); border-color: var(--accent); }
|
|
616
|
+
.job-option:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
|
617
|
+
.job-option.selected { background: var(--accent-soft); border-color: var(--accent); }
|
|
618
|
+
.job-option strong { font-weight: 600; }
|
|
619
|
+
.job-option span { color: var(--muted); font-size: 13px; }
|
|
620
|
+
|
|
621
|
+
.step2 .assigned-job {
|
|
622
|
+
background: var(--accent-soft);
|
|
623
|
+
border: 1px solid #c5dcd0;
|
|
624
|
+
border-radius: 10px;
|
|
625
|
+
padding: 12px 14px;
|
|
626
|
+
margin-bottom: 14px;
|
|
627
|
+
}
|
|
628
|
+
.step2 .assigned-job .label {
|
|
629
|
+
font-size: 11px;
|
|
630
|
+
font-weight: 600;
|
|
631
|
+
color: var(--accent);
|
|
632
|
+
text-transform: uppercase;
|
|
633
|
+
letter-spacing: 0.04em;
|
|
422
634
|
}
|
|
423
|
-
|
|
424
|
-
.
|
|
635
|
+
.step2 .assigned-job .name { font-weight: 600; margin-top: 2px; }
|
|
636
|
+
.step2 .assigned-job .desc { color: var(--muted); font-size: 13px; margin-top: 2px; }
|
|
637
|
+
.step2 textarea {
|
|
638
|
+
width: 100%;
|
|
639
|
+
min-height: 140px;
|
|
640
|
+
resize: vertical;
|
|
425
641
|
border: 1px solid var(--line);
|
|
426
|
-
border-radius:
|
|
427
|
-
padding: 14px
|
|
428
|
-
|
|
642
|
+
border-radius: 10px;
|
|
643
|
+
padding: 12px 14px;
|
|
644
|
+
font: inherit;
|
|
429
645
|
}
|
|
646
|
+
.step2 textarea:focus { outline: none; border-color: var(--accent); }
|
|
430
647
|
|
|
431
|
-
.
|
|
432
|
-
|
|
433
|
-
|
|
648
|
+
.employee-line {
|
|
649
|
+
display: flex;
|
|
650
|
+
align-items: center;
|
|
651
|
+
gap: 10px;
|
|
652
|
+
margin-top: 12px;
|
|
653
|
+
font-size: 13px;
|
|
654
|
+
color: var(--muted);
|
|
434
655
|
}
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
656
|
+
.employee-select {
|
|
657
|
+
border: 1px solid var(--line);
|
|
658
|
+
border-radius: 8px;
|
|
659
|
+
padding: 6px 10px;
|
|
660
|
+
background: var(--surface);
|
|
661
|
+
color: var(--text);
|
|
662
|
+
}
|
|
663
|
+
.employee-select:focus { outline: none; border-color: var(--accent); }
|
|
664
|
+
|
|
665
|
+
@media (max-width: 820px) {
|
|
666
|
+
/* Single-column reflow — the rigid 100vh layout doesn't make sense at
|
|
667
|
+
mobile width because the rail stacks above the conversation. Let the
|
|
668
|
+
page scroll naturally and bound the messages section to keep the
|
|
669
|
+
coach + micro-manage reachable at the bottom. */
|
|
670
|
+
html, body { height: auto; }
|
|
671
|
+
body { overflow: auto; }
|
|
672
|
+
.page { height: auto; min-height: 100vh; }
|
|
673
|
+
.layout { grid-template-columns: 1fr; flex: initial; }
|
|
674
|
+
.rail { max-height: none; overflow-y: visible; }
|
|
675
|
+
.conversation { height: auto; min-height: 60vh; overflow: visible; }
|
|
676
|
+
#active-conv { flex: initial; }
|
|
677
|
+
.conv-stream { flex: initial; }
|
|
678
|
+
.messages { flex: initial; max-height: 60vh; }
|
|
679
|
+
.header { flex-wrap: wrap; }
|
|
680
|
+
.popover { width: min(320px, calc(100vw - 60px)); }
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
/* ---------------------------------------------------------------- */
|
|
684
|
+
/* Issue #347 — Pizza tracker (R1), template picker (R2), totals (R4) */
|
|
685
|
+
/* ---------------------------------------------------------------- */
|
|
686
|
+
|
|
687
|
+
.tracker {
|
|
688
|
+
padding: 12px 4px 14px;
|
|
689
|
+
border-top: 1px solid var(--line);
|
|
690
|
+
border-bottom: 1px solid var(--line);
|
|
691
|
+
}
|
|
692
|
+
.tracker-rows {
|
|
693
|
+
display: flex;
|
|
694
|
+
flex-direction: column;
|
|
695
|
+
gap: 14px;
|
|
438
696
|
}
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
697
|
+
.tracker-row {
|
|
698
|
+
display: flex;
|
|
699
|
+
align-items: center;
|
|
700
|
+
gap: 0;
|
|
701
|
+
position: relative;
|
|
442
702
|
}
|
|
443
|
-
|
|
444
|
-
.message-meta {
|
|
703
|
+
.tracker .stage {
|
|
445
704
|
display: flex;
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
705
|
+
flex-direction: column;
|
|
706
|
+
align-items: center;
|
|
707
|
+
gap: 6px;
|
|
708
|
+
flex: 1 1 0;
|
|
709
|
+
min-width: 0;
|
|
710
|
+
position: relative;
|
|
711
|
+
z-index: 2;
|
|
712
|
+
}
|
|
713
|
+
/* Connector segment to the previous stage in the same row. The fill
|
|
714
|
+
color flips green when the previous stage is done or the current
|
|
715
|
+
stage is current — that produces the "fill bar threads through
|
|
716
|
+
completed stages" effect without an SVG path. */
|
|
717
|
+
.tracker .stage::before {
|
|
718
|
+
content: '';
|
|
719
|
+
position: absolute;
|
|
720
|
+
top: 13px;
|
|
721
|
+
left: -50%;
|
|
722
|
+
right: 50%;
|
|
723
|
+
height: 3px;
|
|
724
|
+
background: var(--line);
|
|
725
|
+
z-index: 0;
|
|
726
|
+
}
|
|
727
|
+
.tracker .tracker-row .stage:first-child::before { display: none; }
|
|
728
|
+
.tracker .stage.done::before,
|
|
729
|
+
.tracker .stage.current::before { background: var(--accent); }
|
|
730
|
+
.tracker .stage-circle {
|
|
731
|
+
width: 26px; height: 26px;
|
|
732
|
+
border-radius: 50%;
|
|
733
|
+
background: var(--surface);
|
|
734
|
+
border: 2px solid var(--line);
|
|
735
|
+
display: inline-flex;
|
|
736
|
+
align-items: center;
|
|
737
|
+
justify-content: center;
|
|
738
|
+
font-size: 11px;
|
|
450
739
|
color: var(--muted);
|
|
740
|
+
font-weight: 600;
|
|
741
|
+
position: relative;
|
|
742
|
+
z-index: 2;
|
|
451
743
|
}
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
color:
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
.message-text {
|
|
459
|
-
white-space: pre-wrap;
|
|
460
|
-
line-height: 1.55;
|
|
744
|
+
.tracker .stage.done .stage-circle {
|
|
745
|
+
background: var(--accent);
|
|
746
|
+
border-color: var(--accent);
|
|
747
|
+
color: #fff;
|
|
461
748
|
}
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
border-radius: 8px;
|
|
468
|
-
background: rgba(247, 249, 253, 0.72);
|
|
469
|
-
border: 1px solid var(--line);
|
|
749
|
+
.tracker .stage.current .stage-circle {
|
|
750
|
+
background: var(--accent-soft);
|
|
751
|
+
border-color: var(--accent);
|
|
752
|
+
color: var(--accent-strong);
|
|
753
|
+
box-shadow: 0 0 0 4px rgba(61, 138, 110, 0.10);
|
|
470
754
|
}
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
755
|
+
.tracker .stage-label {
|
|
756
|
+
font-size: 11px;
|
|
757
|
+
color: var(--muted);
|
|
758
|
+
text-align: center;
|
|
759
|
+
white-space: nowrap;
|
|
760
|
+
overflow: hidden;
|
|
761
|
+
text-overflow: ellipsis;
|
|
762
|
+
max-width: 100%;
|
|
475
763
|
}
|
|
476
|
-
|
|
477
|
-
|
|
764
|
+
.tracker .stage.current .stage-label {
|
|
765
|
+
color: var(--text);
|
|
478
766
|
font-weight: 600;
|
|
479
767
|
}
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
padding: 0 18px;
|
|
483
|
-
box-shadow: var(--shadow-soft);
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
.micro-manage summary {
|
|
487
|
-
padding: 16px 0;
|
|
488
|
-
cursor: pointer;
|
|
489
|
-
font-weight: 700;
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
.micro-manage-body {
|
|
493
|
-
padding: 0 0 18px;
|
|
494
|
-
max-height: 240px;
|
|
495
|
-
overflow: auto;
|
|
496
|
-
display: grid;
|
|
497
|
-
gap: 8px;
|
|
498
|
-
font-family: Consolas, "Courier New", monospace;
|
|
768
|
+
.tracker-note {
|
|
769
|
+
margin-top: 10px;
|
|
499
770
|
font-size: 12px;
|
|
500
771
|
color: var(--muted);
|
|
772
|
+
text-align: center;
|
|
501
773
|
}
|
|
774
|
+
.tracker-note .glyph { color: var(--accent); margin-right: 4px; }
|
|
502
775
|
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
776
|
+
/* Active-stage label that lives outside the rows. Always rendered by
|
|
777
|
+
JS; hidden by default and shown only at narrow viewports where the
|
|
778
|
+
per-stage labels are too cramped to read (spec R1.4 acceptance). */
|
|
779
|
+
.tracker-active-label {
|
|
780
|
+
display: none;
|
|
781
|
+
margin-top: 8px;
|
|
782
|
+
font-size: 12px;
|
|
783
|
+
color: var(--text);
|
|
784
|
+
font-weight: 600;
|
|
785
|
+
text-align: center;
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
/* Narrow-viewport label collapse (spec R1.4 acceptance). At ≤ 640px,
|
|
789
|
+
per-stage labels disappear; the standalone active label below the
|
|
790
|
+
rows tells the manager which stage is current. Numbered circles
|
|
791
|
+
keep the journey visible. */
|
|
792
|
+
@media (max-width: 640px) {
|
|
793
|
+
.tracker .stage .stage-label { display: none; }
|
|
794
|
+
.tracker-active-label { display: block; }
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
/* Template picker popover (R2). Absolute-positioned inside .coach-actions
|
|
798
|
+
so opening it does not push the textarea down. */
|
|
799
|
+
.coach-actions { position: relative; }
|
|
800
|
+
.template-popover {
|
|
801
|
+
position: absolute;
|
|
802
|
+
bottom: 44px;
|
|
803
|
+
right: 0;
|
|
804
|
+
width: 320px;
|
|
805
|
+
max-height: 360px;
|
|
806
|
+
overflow: auto;
|
|
807
|
+
background: var(--surface);
|
|
507
808
|
border: 1px solid var(--line);
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
.
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
809
|
+
border-radius: 12px;
|
|
810
|
+
box-shadow: var(--shadow-lg);
|
|
811
|
+
padding: 12px;
|
|
812
|
+
z-index: 10;
|
|
813
|
+
}
|
|
814
|
+
.template-popover .group {
|
|
815
|
+
padding: 6px 0;
|
|
816
|
+
border-bottom: 1px solid var(--line);
|
|
817
|
+
}
|
|
818
|
+
.template-popover .group:last-child { border-bottom: none; }
|
|
819
|
+
.template-popover .group-label {
|
|
820
|
+
font-size: 11px;
|
|
821
|
+
color: var(--accent-strong);
|
|
822
|
+
text-transform: uppercase;
|
|
823
|
+
letter-spacing: 0.06em;
|
|
824
|
+
font-weight: 600;
|
|
825
|
+
margin: 0 0 4px 0;
|
|
826
|
+
padding: 4px 10px;
|
|
827
|
+
display: flex;
|
|
828
|
+
align-items: center;
|
|
829
|
+
gap: 6px;
|
|
830
|
+
}
|
|
831
|
+
.template-popover .group-label .group-dot {
|
|
832
|
+
width: 8px; height: 8px;
|
|
833
|
+
border-radius: 50%;
|
|
834
|
+
background: var(--accent);
|
|
835
|
+
display: inline-block;
|
|
836
|
+
}
|
|
837
|
+
.template-popover .group.delegation .group-dot { background: var(--picker-delegation); }
|
|
838
|
+
.template-popover .group.coaching .group-dot { background: var(--accent); }
|
|
839
|
+
.template-popover .group.verification .group-dot { background: var(--warn); }
|
|
840
|
+
.template-popover .group.learning .group-dot { background: var(--picker-learning); }
|
|
841
|
+
.template-popover .template-row {
|
|
842
|
+
display: flex;
|
|
843
|
+
flex-direction: column;
|
|
844
|
+
gap: 2px;
|
|
845
|
+
padding: 8px 10px;
|
|
846
|
+
border-radius: 8px;
|
|
847
|
+
cursor: pointer;
|
|
848
|
+
background: none;
|
|
849
|
+
border: none;
|
|
850
|
+
text-align: left;
|
|
851
|
+
width: 100%;
|
|
852
|
+
font: inherit;
|
|
853
|
+
color: var(--text);
|
|
540
854
|
}
|
|
855
|
+
.template-popover .template-row:hover { background: var(--accent-soft); }
|
|
856
|
+
.template-popover .template-row strong { font-size: 13px; font-weight: 500; }
|
|
857
|
+
.template-popover .template-row span { font-size: 12px; color: var(--muted); }
|
|
541
858
|
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
.interaction-head {
|
|
552
|
-
display: grid;
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
.workspace,
|
|
556
|
-
.app-header {
|
|
557
|
-
gap: 18px;
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
.timeline {
|
|
561
|
-
min-height: 280px;
|
|
562
|
-
max-height: 380px;
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
.panel-intro {
|
|
566
|
-
font-size: 16px;
|
|
567
|
-
}
|
|
859
|
+
/* Totals line (R4). 12px muted, no border, single row that wraps if it
|
|
860
|
+
absolutely must. Discoverable via hover tooltips per spec R4.4. */
|
|
861
|
+
.totals {
|
|
862
|
+
font-size: 12px;
|
|
863
|
+
color: var(--muted);
|
|
864
|
+
padding-top: 4px;
|
|
865
|
+
display: flex;
|
|
866
|
+
gap: 14px;
|
|
867
|
+
flex-wrap: wrap;
|
|
568
868
|
}
|
|
869
|
+
.totals span { cursor: help; }
|
|
870
|
+
.totals .sep { color: var(--line); }
|
|
871
|
+
.totals strong { color: var(--text); font-weight: 600; }
|