@echomem/mcp 1.4.9 → 1.4.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/assets/hud/github.svg +1 -0
  2. package/dist/city/README.md +9 -0
  3. package/dist/city/echo-ai-city-only.html +54 -93
  4. package/dist/context-analysis/claude-native-canonical.js +35 -12
  5. package/dist/context-metrics/calculate.js +2 -15
  6. package/dist/context-metrics/estimator.js +45 -0
  7. package/dist/context-metrics/ledger.js +507 -0
  8. package/dist/context-metrics/parse-claude.js +227 -0
  9. package/dist/context-metrics/parse-codex.js +276 -0
  10. package/dist/hud/adapters.js +69 -198
  11. package/dist/hud/electron-main.js +3 -2
  12. package/dist/hud/fs.js +14 -0
  13. package/dist/hud/metric.js +4 -98
  14. package/dist/hud/monitor.js +1 -12
  15. package/dist/hud/render.js +4 -3
  16. package/dist/hud/server.js +30 -0
  17. package/dist/hud/web.js +409 -186
  18. package/dist/index.js +1 -0
  19. package/dist/setup-page/client-core.js +475 -0
  20. package/dist/setup-page/client-extraction.js +550 -0
  21. package/dist/setup-page/client-lifecycle.js +116 -0
  22. package/dist/setup-page/client-report-audit.js +818 -0
  23. package/dist/setup-page/client-report-city.js +204 -0
  24. package/dist/setup-page/client-report.js +6 -0
  25. package/dist/setup-page/client.js +15 -0
  26. package/dist/setup-page/document.js +37 -0
  27. package/dist/setup-page/styles-city-report.js +880 -0
  28. package/dist/setup-page/styles-context-audit.js +470 -0
  29. package/dist/setup-page/styles-extraction.js +821 -0
  30. package/dist/setup-page/styles-foundation.js +231 -0
  31. package/dist/setup-page/styles.js +11 -0
  32. package/dist/setup-page.js +6 -5623
  33. package/dist/setup.js +24 -10
  34. package/package.json +4 -4
  35. package/dist/city/10-problems-report.html +0 -649
  36. package/dist/city/_live.html +0 -37
  37. package/dist/city/_serve.mjs +0 -45
  38. package/dist/city/card-data.json +0 -15
  39. package/dist/city/chaos-to-clarity-pencil.html +0 -582
  40. package/dist/city/city-data.json +0 -248
  41. package/dist/city/echo-ai-city-only.template.html +0 -2271
  42. package/dist/city/generate-echo-city-only.mjs +0 -112
  43. package/dist/city/pencil-pie-generator.html +0 -883
  44. package/dist/city/pencil-webgl-landscape.html +0 -1239
  45. package/dist/city/spatial-fan-story.html +0 -479
@@ -0,0 +1,821 @@
1
+ // Generated from the prior inline setup page. This content is emitted into one browser IIFE/style tag.
2
+ export const SETUP_PAGE_STYLES_EXTRACTION = String.raw ` /* ---- dashboard (post-auth extraction) ---- */
3
+ .loading-panel, .doctor-copy, .doctor-score, .metric, .extract-panel {
4
+ border: 1px solid var(--line);
5
+ border-radius: 8px;
6
+ background: var(--panel);
7
+ }
8
+ .status-strip {
9
+ display: flex; align-items: flex-start; gap: 12px;
10
+ border: 1px solid #c7d6e5; border-radius: 8px; background: #eef5fb; color: #1e3449;
11
+ padding: 13px 15px; margin-bottom: 18px;
12
+ }
13
+ .status-strip.good { border-color: var(--good-line); background: var(--good-bg); color: #203820; }
14
+ .status-strip.warn { border-color: var(--warn-line); background: var(--warn-bg); color: #5e4300; }
15
+ .status-strip .dot { flex: 0 0 auto; width: 12px; height: 12px; border-radius: 999px; margin-top: 4px; background: currentColor; }
16
+ .status-strip strong { display: block; line-height: 1.25; }
17
+ .status-strip p { margin-top: 3px; color: currentColor; font-size: 14px; }
18
+ .doctor-hero {
19
+ display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(260px, 0.8fr);
20
+ gap: 14px; margin-bottom: 14px; align-items: stretch;
21
+ }
22
+ .doctor-copy, .doctor-score { padding: clamp(18px, 3vw, 26px); }
23
+ .doctor-copy { display: flex; flex-direction: column; justify-content: center; min-height: 240px; }
24
+ .doctor-copy h2 { max-width: 760px; margin-top: 10px; font-size: clamp(30px, 4.4vw, 52px); line-height: 1.02; }
25
+ .doctor-copy p:not(.label):not(.helper) { max-width: 720px; margin-top: 14px; font-size: clamp(15px, 1.5vw, 18px); color: var(--echo-ink-text); }
26
+ .doctor-score { display: grid; align-content: center; gap: 12px; }
27
+ .doctor-score > span { font-family: var(--echo-font-mono); color: var(--echo-ink-mute); font-size: 12px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; }
28
+ .doctor-score > strong { display: block; font-family: var(--echo-font-brand); font-size: clamp(34px, 5.5vw, 60px); font-weight: 900; line-height: 0.95; color: var(--echo-ink-primary); }
29
+ .doctor-mini { display: grid; gap: 8px; margin-top: 12px; }
30
+ .mini-row { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; border-bottom: 1px solid var(--echo-line-soft); padding-bottom: 8px; }
31
+ .mini-row span { color: var(--echo-ink-text); font-size: 14px; }
32
+ .mini-row strong { font-family: var(--echo-font-brand); font-size: 16px; font-weight: 900; color: var(--echo-ink-primary); font-variant-numeric: tabular-nums; white-space: nowrap; }
33
+ .doctor-stat-strip { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 10px; margin-bottom: 14px; }
34
+ .doctor-actions { margin: 0 0 18px; }
35
+ .metric { min-height: 122px; padding: 18px; display: flex; flex-direction: column; justify-content: space-between; }
36
+ .label { margin: 0; font-family: var(--echo-font-mono); color: var(--echo-ink-mute); font-size: 12px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; }
37
+ .value { display: block; font-family: var(--echo-font-brand); font-size: 34px; font-weight: 900; line-height: 1; color: var(--echo-ink-primary); }
38
+ .detail { margin: 0; color: var(--echo-ink-mute); font-size: 14px; line-height: 1.45; }
39
+ .extract-panel { padding: 18px; }
40
+ .bucket-row { align-items: center; display: grid; grid-template-columns: minmax(90px, 1fr) minmax(100px, auto); gap: 12px; }
41
+ .bucket-value { text-align: right; font-weight: 800; white-space: nowrap; }
42
+ .helper { margin-top: 10px; color: var(--echo-ink-mute); font-size: 14px; }
43
+ .notice, .done, .warning, .error { border-radius: 8px; padding: 14px 16px; margin-bottom: 18px; }
44
+ .notice, .done { border: 1px solid var(--good-line); background: var(--good-bg); color: #203820; }
45
+ .warning { border: 1px solid var(--warn-line); background: var(--warn-bg); color: #5e4300; }
46
+ .error { border: 1px solid var(--error-line); background: var(--error-bg); color: #7d2117; }
47
+ .details { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(290px, 100%), 1fr)); gap: 12px; margin-bottom: 18px; }
48
+ dl { margin: 14px 0 0; display: grid; gap: 10px; }
49
+ .row { display: flex; justify-content: space-between; gap: 12px; border-bottom: 1px solid #ecece7; padding-bottom: 8px; }
50
+ dt { color: var(--echo-ink-text); }
51
+ dd { margin: 0; text-align: right; color: var(--echo-ink-text); }
52
+ ol { list-style: none; margin: 14px 0 0; padding: 0; display: grid; gap: 10px; }
53
+ li { display: flex; justify-content: space-between; gap: 10px; }
54
+ .actions { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 18px; }
55
+ button, .button {
56
+ min-height: 44px; display: inline-flex; align-items: center; justify-content: center; gap: 8px;
57
+ border-radius: 8px; border: 1px solid var(--echo-ink-primary); padding: 0 16px;
58
+ font: inherit; font-weight: 800; text-decoration: none; cursor: pointer;
59
+ }
60
+ .primary { background: var(--echo-ink-primary); color: #fff; }
61
+ .secondary { background: #fff; color: var(--echo-ink-primary); }
62
+ button:disabled { cursor: not-allowed; opacity: 0.55; }
63
+ .track { height: 12px; overflow: hidden; border-radius: 999px; background: #e8e8e1; margin: 16px 0 10px; }
64
+ .fill { height: 100%; width: 0%; background: var(--echo-ink-primary); transition: width 180ms ease; }
65
+ /* indeterminate "we're working on it" bar for the prep phase (before job counts move) */
66
+ .track.indef .fill { width: 40%; transition: none; animation: prepSlide 1.2s ease-in-out infinite; }
67
+ @keyframes prepSlide { 0% { transform: translateX(-110%); } 100% { transform: translateX(350%); } }
68
+ .prep-steps { list-style: none; margin: 18px 0 0; padding: 0; display: grid; gap: 11px; }
69
+ .prep-steps li { display: grid; grid-template-columns: 16px 1fr; gap: 11px; align-items: center; font-size: 15px; color: var(--echo-ink-mute); }
70
+ .prep-steps .dot { width: 13px; height: 13px; border-radius: 999px; border: 2px solid #cfcfc6; box-sizing: border-box; }
71
+ .prep-steps li.done { color: var(--echo-ink-text); }
72
+ .prep-steps li.done .dot { background: var(--echo-ink-primary); border-color: var(--echo-ink-primary); }
73
+ .prep-steps li.active { color: var(--echo-ink-primary); font-weight: 700; }
74
+ .prep-steps li.active .dot { border-color: var(--echo-ink-primary); animation: prepDot 1.1s ease-in-out infinite; }
75
+ @keyframes prepDot { 0%, 100% { box-shadow: 0 0 0 0 rgba(26,58,143,0.4); } 60% { box-shadow: 0 0 0 6px rgba(26,58,143,0); } }
76
+ .counts { display: flex; gap: 14px; flex-wrap: wrap; font-family: var(--echo-font-mono); color: var(--echo-ink-mute); font-size: 13px; letter-spacing: 0.02em; margin-bottom: 6px; }
77
+ .finish { display: grid; gap: 6px; place-items: center; text-align: center; padding: clamp(28px, 6vw, 64px) 0; }
78
+ .finishMark { width: 54px; height: 54px; border-radius: 999px; display: grid; place-items: center; font-size: 26px; font-weight: 900; margin-bottom: 8px; }
79
+ .finishMark.ok { background: var(--good-bg); color: #2f7f4f; border: 1px solid var(--good-line); }
80
+ .finishMark.warn { background: var(--warn-bg); color: #5e4300; border: 1px solid var(--warn-line); }
81
+ .finishBig { font-family: var(--echo-font-brand); font-size: clamp(48px, 8vw, 84px); font-weight: 900; line-height: 0.9; color: var(--echo-ink-primary); font-variant-numeric: tabular-nums; }
82
+ .finishLabel { font-family: var(--echo-font-mono); font-size: 12px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--echo-ink-mute); }
83
+ .finish p { max-width: 560px; margin: 12px 0 0; color: var(--echo-ink-text); font-size: 16px; line-height: 1.6; }
84
+ .finish p.helper { color: var(--echo-ink-mute); font-size: 14px; margin-top: 6px; }
85
+ code { font-family: var(--echo-font-mono); font-size: 0.9em; padding: 1px 5px; border-radius: 4px; background: var(--echo-paper-soft); color: var(--echo-ink-primary); }
86
+ .hidden { display: none; }
87
+ @media (max-width: 820px) {
88
+ .heroGrid, .twoCol, .statStrip, .privacy, .doctor-hero, .doctor-stat-strip,
89
+ .explainHero, .insightPills, .explainSections, .explainCta, .ctxFacts { grid-template-columns: 1fr; }
90
+ .doctor-stat-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); }
91
+ .heroCopy h2 { font-size: 34px; }
92
+ .scoreCard { min-height: 220px; }
93
+ .explainCopy h2 { font-size: 38px; }
94
+ .explainCta .promiseActions { width: 100%; }
95
+ .explainCta .primary, .explainCta .secondary { width: 100%; }
96
+ .cityHero { min-height: auto; }
97
+ .cityShell {
98
+ width: 100vw;
99
+ height: 100vh;
100
+ }
101
+ }
102
+ /* extraction dashboard — plate layout */
103
+ .exHero { display: grid; grid-template-columns: minmax(0, 1fr) minmax(300px, 0.95fr); gap: clamp(20px, 3vw, 40px); align-items: center; margin-top: 8px; }
104
+ /* Centered composition: mascot on top, then everything stacked and centered on one axis. */
105
+ .readyDecision {
106
+ width: 100%;
107
+ max-width: min(720px, calc(100vw - clamp(32px, 8vw, 120px)));
108
+ display: grid;
109
+ justify-items: center;
110
+ text-align: center;
111
+ gap: 20px;
112
+ margin: 0 auto;
113
+ }
114
+ .readyHero {
115
+ display: grid;
116
+ justify-items: center;
117
+ gap: 16px;
118
+ margin: 0 auto;
119
+ }
120
+ .readyMascot {
121
+ width: 84px;
122
+ height: 84px;
123
+ object-fit: contain;
124
+ filter: drop-shadow(0 12px 18px rgba(26,58,143,0.18));
125
+ }
126
+ .readyHero .exCopy h2 {
127
+ margin: 0;
128
+ font-size: clamp(32px, 4.6vw, 60px);
129
+ line-height: 0.98;
130
+ }
131
+ .readyHero .exCopy .exSub {
132
+ max-width: 560px;
133
+ margin: 12px auto 0;
134
+ font-size: clamp(16px, 1.45vw, 18px);
135
+ }
136
+ .readyAction {
137
+ display: grid;
138
+ grid-template-columns: minmax(0, 1fr) minmax(210px, auto);
139
+ gap: clamp(18px, 3vw, 34px);
140
+ align-items: end;
141
+ margin-top: 2px;
142
+ padding: 22px 0 24px;
143
+ border-top: 1px solid var(--echo-line-soft);
144
+ border-bottom: 1px solid var(--echo-line-soft);
145
+ }
146
+ .readyRun {
147
+ display: grid;
148
+ grid-template-columns: minmax(220px, 0.8fr) minmax(280px, 1.2fr);
149
+ gap: clamp(18px, 3vw, 34px);
150
+ align-items: start;
151
+ }
152
+ .exHeroReady {
153
+ width: 100%;
154
+ max-width: min(860px, calc(100vw - clamp(36px, 9vw, 140px)));
155
+ grid-template-columns: minmax(0, 1fr);
156
+ justify-content: center;
157
+ justify-items: stretch;
158
+ margin: clamp(8px, 2vh, 24px) auto 0;
159
+ }
160
+ .exHeroReady .exCopy { width: 100%; }
161
+ .exHeroResult {
162
+ width: 100%;
163
+ max-width: min(920px, calc(100vw - clamp(36px, 8vw, 120px)));
164
+ grid-template-columns: minmax(0, 760px);
165
+ justify-content: center;
166
+ justify-items: stretch;
167
+ margin: 0 auto;
168
+ }
169
+ .exHeroResult .exPlate { display: none; }
170
+ .exHeroResult .exCopy { width: 100%; margin: 0 auto; }
171
+ .exCopy h2 { max-width: 620px; margin: 8px 0 0; font-size: clamp(34px, 4.8vw, 58px); line-height: 1.01; }
172
+ .exCopy .exSub { margin: 14px 0 0; max-width: 590px; font-size: clamp(15px, 1.3vw, 17px); line-height: 1.6; color: var(--echo-ink-mute); }
173
+ .exLegend { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 16px; font-family: var(--echo-font-mono); font-size: 12px; color: var(--echo-ink-mute); }
174
+ .exLegend .lgDot { width: 12px; height: 12px; border-radius: 3px; display: inline-block; margin-left: 10px; }
175
+ .exLegend .lgDot:first-child { margin-left: 0; }
176
+ .lgNew { background: #2f6df0; }
177
+ .lgDim { background: #cfc8b8; }
178
+ .exHero .actions { margin-top: 22px; }
179
+ .readyDecision .actions {
180
+ justify-content: center;
181
+ margin-top: 0;
182
+ }
183
+ .readyDecision .actions .primary {
184
+ min-width: 240px;
185
+ min-height: 60px;
186
+ padding: 0 30px;
187
+ font-size: 16px;
188
+ box-shadow: 0 16px 28px -20px rgba(26,58,143,0.55);
189
+ }
190
+ /* Proof strip: one quiet line of evidence (source split), not stat cards. Centered. */
191
+ .proofStrip {
192
+ display: flex;
193
+ flex-wrap: wrap;
194
+ justify-content: center;
195
+ align-items: center;
196
+ gap: 8px 12px;
197
+ min-height: 26px;
198
+ margin-top: 2px;
199
+ font-family: var(--echo-font-mono);
200
+ font-size: 13px;
201
+ color: var(--echo-ink-mute);
202
+ }
203
+ .proofStrip .pf { display: inline-flex; align-items: center; gap: 7px; white-space: nowrap; }
204
+ .proofStrip .pf strong { color: var(--echo-ink-primary); font-weight: 800; font-variant-numeric: tabular-nums; }
205
+ .proofStrip .pfIcon { position: relative; width: 22px; height: 22px; border-radius: 6px; overflow: hidden; background: var(--echo-ink-primary); display: grid; place-items: center; flex: 0 0 auto; }
206
+ .proofStrip .pfIcon img { width: 22px; height: 22px; object-fit: cover; display: block; }
207
+ .proofStrip .pfFallback { display: none; place-items: center; width: 22px; height: 22px; color: #fff; font-size: 8px; font-weight: 900; }
208
+ .proofStrip .pfDot { color: var(--echo-ink-faint); }
209
+ .proofStrip .pfNote { color: var(--echo-ink-faint); font-size: 12px; }
210
+ /* The action block: button first, reassurances attached right under it. Centered. */
211
+ .readyGo { display: grid; gap: 11px; margin-top: 6px; justify-items: center; }
212
+ .ctaMeta { margin: 0; max-width: 480px; display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 4px 9px; font-family: var(--echo-font-mono); font-size: 12px; line-height: 1.5; color: var(--echo-ink-mute); }
213
+ .ctaMeta .cm { white-space: nowrap; }
214
+ .ctaMeta .cmDot { color: var(--echo-ink-faint); }
215
+ .exHint { margin: 0; font-family: var(--echo-font-mono); font-size: 11px; color: var(--echo-ink-faint); }
216
+ .readyFoot {
217
+ display: grid;
218
+ justify-items: center;
219
+ gap: 14px;
220
+ margin-top: clamp(24px, 5vh, 52px);
221
+ opacity: 0.82;
222
+ }
223
+ .readyTime {
224
+ width: 100%;
225
+ display: grid;
226
+ gap: 7px;
227
+ align-content: start;
228
+ padding: 0;
229
+ border: 0;
230
+ background: transparent;
231
+ box-shadow: none;
232
+ }
233
+ .readyTime span {
234
+ font-family: var(--echo-font-mono);
235
+ font-size: 11px;
236
+ font-weight: 800;
237
+ letter-spacing: 0.08em;
238
+ text-transform: uppercase;
239
+ color: var(--echo-ink-mute);
240
+ }
241
+ .readyTime strong {
242
+ font-family: var(--echo-font-brand);
243
+ font-size: clamp(36px, 4vw, 54px);
244
+ font-weight: 900;
245
+ line-height: 0.92;
246
+ color: var(--echo-ink-primary);
247
+ }
248
+ .readyTime em {
249
+ max-width: 390px;
250
+ font-style: normal;
251
+ color: var(--echo-ink-mute);
252
+ font-size: 13px;
253
+ line-height: 1.45;
254
+ }
255
+ .sourceGrid {
256
+ display: grid;
257
+ gap: 8px;
258
+ margin-top: 8px;
259
+ }
260
+ .sourceHeading {
261
+ margin: 0;
262
+ font-family: var(--echo-font-mono);
263
+ font-size: 11px;
264
+ font-weight: 800;
265
+ letter-spacing: 0.08em;
266
+ text-transform: uppercase;
267
+ color: var(--echo-ink-mute);
268
+ }
269
+ .sourceCard {
270
+ display: grid;
271
+ grid-template-columns: 30px minmax(0, 1fr);
272
+ align-items: center;
273
+ gap: 10px;
274
+ border: 1px solid var(--echo-line-soft);
275
+ border-radius: 8px;
276
+ background: var(--echo-paper-soft);
277
+ padding: 8px 11px 8px 8px;
278
+ }
279
+ .sourceIcon {
280
+ width: 30px;
281
+ height: 30px;
282
+ border-radius: 7px;
283
+ overflow: hidden;
284
+ background: var(--echo-ink-primary);
285
+ display: grid;
286
+ place-items: center;
287
+ flex: 0 0 auto;
288
+ }
289
+ .sourceIcon img { width: 30px; height: 30px; object-fit: cover; display: block; }
290
+ .sourceFallback {
291
+ display: none;
292
+ color: #fff;
293
+ font-family: var(--echo-font-mono);
294
+ font-size: 9px;
295
+ font-weight: 900;
296
+ }
297
+ .sourceCard > div {
298
+ min-width: 0;
299
+ display: grid;
300
+ grid-template-columns: auto minmax(0, 1fr);
301
+ align-items: baseline;
302
+ gap: 2px 7px;
303
+ }
304
+ .sourceCard strong {
305
+ font-family: var(--echo-font-brand);
306
+ font-size: 24px;
307
+ font-weight: 900;
308
+ line-height: 1;
309
+ color: var(--echo-ink-primary);
310
+ font-variant-numeric: tabular-nums;
311
+ }
312
+ .sourceCard span {
313
+ font-family: var(--echo-font-mono);
314
+ font-size: 11px;
315
+ font-weight: 800;
316
+ letter-spacing: 0.04em;
317
+ color: var(--echo-ink-mute);
318
+ }
319
+ .sourceCard small {
320
+ display: block;
321
+ grid-column: 1 / -1;
322
+ color: var(--echo-ink-faint);
323
+ font-size: 12px;
324
+ line-height: 1.35;
325
+ }
326
+ .readyExplain {
327
+ max-width: 760px;
328
+ border-top: 1px solid var(--echo-line-soft);
329
+ padding-top: 12px;
330
+ color: var(--echo-ink-mute);
331
+ }
332
+ .readyExplain summary {
333
+ cursor: pointer;
334
+ font-family: var(--echo-font-mono);
335
+ font-size: 11px;
336
+ font-weight: 800;
337
+ letter-spacing: 0.08em;
338
+ text-transform: uppercase;
339
+ color: var(--echo-ink-primary);
340
+ }
341
+ .readyExplain summary::marker { color: var(--echo-ink-faint); }
342
+ .readyExplain p {
343
+ margin: 7px 0 0;
344
+ max-width: 640px;
345
+ color: var(--echo-ink-mute);
346
+ font-size: 14px;
347
+ line-height: 1.55;
348
+ }
349
+ .readySteps {
350
+ display: grid;
351
+ grid-template-columns: repeat(3, minmax(0, 1fr));
352
+ gap: 8px;
353
+ margin-top: 11px;
354
+ }
355
+ .readyStep {
356
+ border: 1px solid var(--echo-line-soft);
357
+ border-radius: 8px;
358
+ background: transparent;
359
+ padding: 10px 11px;
360
+ }
361
+ .readyStep strong {
362
+ display: block;
363
+ font-family: var(--echo-font-mono);
364
+ font-size: 10px;
365
+ font-weight: 800;
366
+ letter-spacing: 0.06em;
367
+ text-transform: uppercase;
368
+ color: var(--echo-ink-primary);
369
+ }
370
+ .readyStep span {
371
+ display: block;
372
+ margin-top: 5px;
373
+ color: var(--echo-ink-faint);
374
+ font-size: 12px;
375
+ line-height: 1.35;
376
+ }
377
+ .exPlate { width: 100%; }
378
+ /* WebGL clay city (echo-extraction-plate.html) — the only plate; no SVG layer */
379
+ .plateStack { position: relative; width: 100%; aspect-ratio: 640 / 470; }
380
+ .plateStack .plateGl { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; background: transparent; }
381
+ .exHeroActive {
382
+ grid-template-columns: minmax(0, 640px);
383
+ justify-content: center;
384
+ justify-items: stretch;
385
+ width: 100%;
386
+ max-width: min(920px, calc(100vw - clamp(36px, 8vw, 120px)));
387
+ margin: 0 auto;
388
+ }
389
+ .exHeroActive .exPlate { display: none; }
390
+ .exHeroActive .exCopy { width: 100%; }
391
+ .workbench { display: grid; gap: 14px; max-width: 640px; }
392
+ .workbench h2 {
393
+ max-width: 520px;
394
+ font-size: clamp(24px, 3vw, 34px);
395
+ line-height: 1.04;
396
+ }
397
+ .exMeter {
398
+ display: flex;
399
+ align-items: baseline;
400
+ justify-content: space-between;
401
+ gap: 14px;
402
+ margin-top: 10px;
403
+ padding-bottom: 8px;
404
+ border-bottom: 1px solid var(--echo-line-soft);
405
+ }
406
+ .exMeter strong {
407
+ font-family: var(--echo-font-brand);
408
+ font-size: clamp(38px, 5vw, 66px);
409
+ font-weight: 900;
410
+ line-height: 0.9;
411
+ color: var(--echo-ink-primary);
412
+ font-variant-numeric: tabular-nums;
413
+ }
414
+ .exMeter span {
415
+ font-family: var(--echo-font-mono);
416
+ font-size: 11px;
417
+ font-weight: 800;
418
+ letter-spacing: 0.07em;
419
+ text-transform: uppercase;
420
+ color: var(--echo-ink-mute);
421
+ }
422
+ .exCurrent {
423
+ display: grid;
424
+ grid-template-columns: auto 1fr;
425
+ gap: 10px;
426
+ align-items: center;
427
+ margin-top: 2px;
428
+ padding: 11px 0;
429
+ border-top: 1px solid var(--echo-line-soft);
430
+ border-bottom: 1px solid var(--echo-line-soft);
431
+ }
432
+ .exCurrent i {
433
+ width: 9px;
434
+ height: 9px;
435
+ border-radius: 999px;
436
+ background: var(--echo-ink-accent);
437
+ box-shadow: 0 0 0 4px rgba(78,205,196,0.15);
438
+ }
439
+ .exCurrent span {
440
+ font-family: var(--echo-font-mono);
441
+ font-size: 11px;
442
+ font-weight: 800;
443
+ letter-spacing: 0.07em;
444
+ text-transform: uppercase;
445
+ color: var(--echo-ink-primary);
446
+ }
447
+ .exCurrent strong {
448
+ display: block;
449
+ margin-top: 3px;
450
+ color: var(--echo-ink-text);
451
+ font-size: 14px;
452
+ line-height: 1.45;
453
+ font-weight: 700;
454
+ }
455
+ .extractFacts {
456
+ margin: 0;
457
+ font-family: var(--echo-font-mono);
458
+ font-size: 12px;
459
+ line-height: 1.5;
460
+ color: var(--echo-ink-mute);
461
+ }
462
+ .extractFacts strong {
463
+ color: var(--echo-ink-primary);
464
+ font-weight: 900;
465
+ }
466
+ .extractEndRow {
467
+ display: flex;
468
+ align-items: center;
469
+ gap: 10px;
470
+ flex-wrap: wrap;
471
+ margin-top: 2px;
472
+ }
473
+ .extractEndRow button {
474
+ min-height: 0;
475
+ border: 0;
476
+ border-radius: 0;
477
+ background: transparent;
478
+ color: var(--echo-ink-primary);
479
+ padding: 0;
480
+ font-family: var(--echo-font-mono);
481
+ font-size: 12px;
482
+ font-weight: 800;
483
+ letter-spacing: 0.04em;
484
+ text-transform: none;
485
+ }
486
+ .extractEndRow button:hover {
487
+ text-decoration: underline;
488
+ }
489
+ .extractEndRow span {
490
+ color: var(--echo-ink-faint);
491
+ font-size: 12px;
492
+ line-height: 1.45;
493
+ }
494
+ .skipStage {
495
+ display: grid;
496
+ gap: 14px;
497
+ max-width: 680px;
498
+ margin: 0 auto;
499
+ text-align: center;
500
+ justify-items: center;
501
+ }
502
+ .skipStage h2 {
503
+ max-width: 620px;
504
+ font-size: clamp(38px, 5vw, 64px);
505
+ line-height: 0.98;
506
+ }
507
+ .skipStage p {
508
+ max-width: 560px;
509
+ margin: 0;
510
+ color: var(--echo-ink-mute);
511
+ font-size: 16px;
512
+ line-height: 1.6;
513
+ }
514
+ .skipStage .seal {
515
+ width: fit-content;
516
+ border: 1px solid var(--echo-line-soft);
517
+ border-radius: 999px;
518
+ background: var(--echo-paper-white);
519
+ padding: 8px 13px;
520
+ font-family: var(--echo-font-mono);
521
+ font-size: 11px;
522
+ font-weight: 800;
523
+ letter-spacing: 0.07em;
524
+ text-transform: uppercase;
525
+ color: var(--echo-ink-primary);
526
+ }
527
+ .resultStage { display: grid; gap: 18px; max-width: 760px; padding: 8px 0 2px; }
528
+ .resultStage .kicker-mono { color: var(--echo-ink-seal); }
529
+ .resultTop {
530
+ display: grid;
531
+ gap: 12px;
532
+ align-items: start;
533
+ }
534
+ .resultTop h2 { margin-top: 6px; font-size: clamp(36px, 5vw, 58px); line-height: 0.98; }
535
+ .resultNumber {
536
+ width: fit-content;
537
+ display: inline-flex;
538
+ align-items: baseline;
539
+ gap: 8px;
540
+ border: 1px solid var(--echo-line-soft);
541
+ border-radius: 999px;
542
+ background: var(--echo-paper-white);
543
+ padding: 7px 12px;
544
+ }
545
+ .resultNumber strong {
546
+ font-family: var(--echo-font-brand);
547
+ font-size: 18px;
548
+ font-weight: 900;
549
+ line-height: 1;
550
+ color: var(--echo-ink-primary);
551
+ font-variant-numeric: tabular-nums;
552
+ }
553
+ .resultNumber span {
554
+ font-family: var(--echo-font-mono);
555
+ font-size: 10px;
556
+ font-weight: 800;
557
+ letter-spacing: 0.07em;
558
+ text-transform: uppercase;
559
+ color: var(--echo-ink-mute);
560
+ text-align: right;
561
+ }
562
+ .memoryReceipt {
563
+ display: grid;
564
+ gap: 10px;
565
+ max-width: 700px;
566
+ padding-top: 2px;
567
+ }
568
+ .memoryReceipt .receiptK {
569
+ margin: 0;
570
+ font-family: var(--echo-font-mono);
571
+ font-size: 10px;
572
+ font-weight: 800;
573
+ letter-spacing: 0.08em;
574
+ text-transform: uppercase;
575
+ color: var(--echo-ink-mute);
576
+ }
577
+ .finishStats {
578
+ display: flex;
579
+ flex-wrap: wrap;
580
+ gap: 6px 18px;
581
+ }
582
+ .finishStat {
583
+ display: inline-flex;
584
+ align-items: baseline;
585
+ gap: 6px;
586
+ border: 0;
587
+ background: transparent;
588
+ padding: 0;
589
+ }
590
+ .finishStat strong {
591
+ font-family: var(--echo-font-brand);
592
+ font-size: 17px;
593
+ font-weight: 900;
594
+ line-height: 1;
595
+ color: var(--echo-ink-primary);
596
+ font-variant-numeric: tabular-nums;
597
+ }
598
+ .finishStat span {
599
+ font-family: var(--echo-font-mono);
600
+ font-size: 10px;
601
+ font-weight: 800;
602
+ letter-spacing: 0.07em;
603
+ text-transform: uppercase;
604
+ color: var(--echo-ink-mute);
605
+ }
606
+ .retryNote {
607
+ margin: 0;
608
+ max-width: 640px;
609
+ font-size: 12px;
610
+ line-height: 1.5;
611
+ color: var(--echo-ink-faint);
612
+ }
613
+ .recon { margin-top: 0; display: inline-block; font-family: var(--echo-font-mono); font-size: 13px; font-weight: 700; color: var(--echo-ink-primary); background: var(--echo-paper-soft); border: 1px solid var(--echo-line-soft); border-radius: 8px; padding: 8px 12px; }
614
+ .exCountdown { margin: 0; font-family: var(--echo-font-mono); font-size: 12px; color: var(--echo-ink-mute); }
615
+ .exCountdown strong { color: var(--echo-ink-primary); font-weight: 700; }
616
+ .exOverdue { margin: 0; max-width: 620px; border: 1px solid rgba(196, 148, 42, 0.45); background: rgba(233, 185, 73, 0.12); border-radius: 8px; padding: 12px 14px; font-size: 13px; line-height: 1.5; color: var(--echo-ink-text); }
617
+ .exOverdue strong { display: block; margin-bottom: 4px; color: var(--echo-ink-primary); }
618
+ .tryCard { margin-top: 2px; max-width: 760px; border: 2px solid var(--echo-ink-primary); border-radius: 8px; background: var(--echo-paper-white); padding: clamp(18px, 3vw, 26px); box-shadow: 0 18px 38px -28px rgba(26,58,143,0.45); }
619
+ .tryCard .tryK { margin: 0 0 10px; font-family: var(--echo-font-mono); font-size: 12px; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; color: var(--echo-ink-primary); }
620
+ .tryCard .tryTitle {
621
+ margin: 0 0 12px;
622
+ font-family: var(--echo-font-brand);
623
+ font-size: clamp(18px, 1.9vw, 23px);
624
+ line-height: 1.15;
625
+ font-weight: 900;
626
+ color: var(--echo-ink-primary);
627
+ }
628
+ .tryCard > .tryTitle { font-size: clamp(30px, 3.8vw, 48px); line-height: 0.98; }
629
+ .promptShell { position: relative; margin-top: 14px; }
630
+ .tryCard pre { margin: 0; white-space: pre-wrap; word-break: break-word; font-family: var(--echo-font-mono); font-size: 12px; line-height: 1.5; color: var(--echo-ink-mute); background: var(--echo-paper-soft); border: 1px solid var(--echo-line-soft); border-radius: 8px; padding: 11px 118px 11px 13px; }
631
+ .promptControls {
632
+ position: absolute;
633
+ top: 8px;
634
+ right: 8px;
635
+ z-index: 2;
636
+ display: flex;
637
+ gap: 6px;
638
+ align-items: center;
639
+ }
640
+ .promptCopyLabel {
641
+ min-height: 28px;
642
+ border: 1px solid var(--echo-line-soft);
643
+ border-radius: 999px;
644
+ background: rgba(255,255,255,0.82);
645
+ color: var(--echo-ink-primary);
646
+ padding: 0 10px;
647
+ font-family: var(--echo-font-mono);
648
+ font-size: 10px;
649
+ font-weight: 800;
650
+ letter-spacing: 0.06em;
651
+ text-transform: uppercase;
652
+ cursor: pointer;
653
+ }
654
+ .promptCopyLabel:hover {
655
+ border-color: rgba(26,58,143,0.35);
656
+ background: var(--echo-paper-white);
657
+ }
658
+ .agentLaunch {
659
+ display: grid;
660
+ grid-template-columns: repeat(2, minmax(0, 1fr));
661
+ gap: 10px;
662
+ margin-top: 18px;
663
+ }
664
+ .agentLaunch button {
665
+ min-height: 72px;
666
+ justify-content: flex-start;
667
+ border-color: var(--echo-line-soft);
668
+ background: var(--echo-paper-white);
669
+ color: var(--echo-ink-primary);
670
+ padding: 10px 14px;
671
+ text-align: left;
672
+ }
673
+ .agentLaunch button:hover { border-color: var(--echo-ink-primary); }
674
+ .agentIcon {
675
+ width: 46px;
676
+ height: 46px;
677
+ display: grid;
678
+ place-items: center;
679
+ flex: 0 0 auto;
680
+ border-radius: 11px;
681
+ background: var(--echo-ink-primary);
682
+ color: #fff;
683
+ font-family: var(--echo-font-mono);
684
+ font-size: 11px;
685
+ font-weight: 900;
686
+ letter-spacing: 0;
687
+ overflow: hidden;
688
+ box-shadow: 0 8px 16px -10px rgba(20,20,20,0.45);
689
+ }
690
+ .agentIcon img {
691
+ width: 100%;
692
+ height: 100%;
693
+ object-fit: cover;
694
+ display: block;
695
+ }
696
+ .agentIcon .agentFallback {
697
+ width: 100%;
698
+ height: 100%;
699
+ display: none;
700
+ place-items: center;
701
+ }
702
+ .copyGlyph {
703
+ position: relative;
704
+ width: 21px;
705
+ height: 25px;
706
+ display: block;
707
+ }
708
+ .copyGlyph::before,
709
+ .copyGlyph::after {
710
+ content: "";
711
+ position: absolute;
712
+ width: 15px;
713
+ height: 18px;
714
+ border: 2px solid #fff;
715
+ border-radius: 4px;
716
+ background: var(--echo-ink-primary);
717
+ }
718
+ .copyGlyph::before { left: 0; top: 0; opacity: 0.72; }
719
+ .copyGlyph::after { right: 0; bottom: 0; }
720
+ .agentText {
721
+ display: block;
722
+ min-width: 0;
723
+ }
724
+ .agentLaunch strong {
725
+ display: block;
726
+ font-family: var(--echo-font-brand);
727
+ font-size: 17px;
728
+ font-weight: 900;
729
+ line-height: 1.1;
730
+ }
731
+ .agentText small {
732
+ display: block;
733
+ margin-top: 2px;
734
+ color: var(--echo-ink-mute);
735
+ font-size: 11px;
736
+ line-height: 1.3;
737
+ font-weight: 600;
738
+ }
739
+ .launchStatus { margin: 9px 0 0; min-height: 18px; font-size: 12px; color: var(--echo-ink-mute); }
740
+ .launchStatus:empty { display: none; }
741
+ .hudTip { margin: 14px 0 0; max-width: 700px; display: grid; grid-template-columns: 52px 1fr; gap: 12px; align-items: center; font-size: 13px; line-height: 1.55; color: var(--echo-ink-mute); }
742
+ .hudTip img { width: 52px; height: 52px; object-fit: contain; filter: drop-shadow(0 10px 16px rgba(26,58,143,0.18)); }
743
+ .hudTip strong { color: var(--echo-ink-primary); }
744
+ .hudTip code { font-family: var(--echo-font-mono); font-size: 12px; background: var(--echo-paper-soft); border: 1px solid var(--echo-line-soft); border-radius: 5px; padding: 1px 5px; }
745
+ .doneCloseNote { margin: clamp(30px, 5vh, 58px) 0 0; max-width: 700px; font-family: var(--echo-font-mono); font-size: 11px; line-height: 1.5; color: var(--echo-ink-faint); }
746
+
747
+ /* ===== Calm redesign: one focal point per state, progressive disclosure ===== */
748
+ .calm { max-width: 640px; }
749
+ /* Ready: a single compact meta strip replaces the giant ETA box + source cards. */
750
+ .readyMeta { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 20px 0 2px; font-family: var(--echo-font-mono); font-size: 12.5px; color: var(--echo-ink-mute); }
751
+ .readyMeta .rm { display: inline-flex; align-items: center; gap: 7px; padding: 6px 12px; border: 1px solid var(--echo-line-soft); border-radius: 999px; background: var(--echo-paper-soft); white-space: nowrap; }
752
+ .readyMeta .rm strong { color: var(--echo-ink-primary); font-weight: 800; }
753
+ .readyMeta .rm img { width: 15px; height: 15px; border-radius: 4px; object-fit: contain; }
754
+ .readyMeta .rm .sf { display: none; width: 15px; height: 15px; border-radius: 4px; background: var(--echo-ink-primary); color: #fff; font-size: 8px; font-weight: 800; align-items: center; justify-content: center; }
755
+ /* Done: the number is the hero; a small ceremonial tick, one supporting line, no duplicate receipt. */
756
+ .doneMark { display: inline-flex; align-items: center; gap: 9px; margin: 0; font-family: var(--echo-font-mono); font-size: 12px; font-weight: 800; letter-spacing: 0.09em; text-transform: uppercase; color: var(--echo-ink-accent-deep); }
757
+ .doneMark .tick { display: grid; place-items: center; width: 24px; height: 24px; border-radius: 50%; background: var(--echo-ink-accent-deep); color: #fff; font-size: 13px; animation: donePop 0.5s cubic-bezier(0.2, 1.5, 0.4, 1) both; }
758
+ @keyframes donePop { from { transform: scale(0); } to { transform: scale(1); } }
759
+ .doneNum { display: flex; align-items: baseline; flex-wrap: wrap; gap: 6px 14px; margin: 14px 0 0; }
760
+ .doneNum strong { font-family: var(--echo-font-brand); font-size: clamp(52px, 9vw, 96px); line-height: 0.9; color: var(--echo-ink-primary); letter-spacing: -0.01em; }
761
+ .doneNum span { font-size: clamp(15px, 1.6vw, 19px); font-weight: 700; color: var(--echo-ink-mute); }
762
+ .doneSub { margin: 16px 0 0; max-width: 560px; font-size: clamp(15px, 1.4vw, 17px); line-height: 1.5; color: var(--echo-ink-text); }
763
+ .savedHeading {
764
+ max-width: 760px;
765
+ display: inline-flex;
766
+ align-items: baseline;
767
+ flex-wrap: wrap;
768
+ gap: 6px 16px;
769
+ }
770
+ .savedHeading .savedMain {
771
+ color: var(--echo-ink-primary);
772
+ }
773
+ .savedHeading strong {
774
+ font-variant-numeric: tabular-nums;
775
+ }
776
+ .viewEchoLink {
777
+ color: var(--echo-ink-mute);
778
+ font-style: normal;
779
+ font-family: var(--echo-font-mono);
780
+ font-size: clamp(12px, 1.15vw, 15px);
781
+ font-weight: 800;
782
+ letter-spacing: 0.06em;
783
+ text-decoration-line: underline;
784
+ text-decoration-thickness: 1px;
785
+ text-underline-offset: 0.18em;
786
+ text-transform: none;
787
+ text-decoration-color: rgba(26,58,143,0.28);
788
+ }
789
+ .viewEchoLink:hover {
790
+ color: var(--echo-ink-primary);
791
+ text-decoration-color: var(--echo-ink-primary);
792
+ }
793
+ /* Collapse the long warm-up prompt behind a disclosure so the buttons lead. */
794
+ .promptPeek { margin: 14px 0 0; }
795
+ .promptPeek summary { cursor: pointer; font-family: var(--echo-font-mono); font-size: 12px; color: var(--echo-ink-mute); list-style: none; }
796
+ .promptPeek summary::-webkit-details-marker { display: none; }
797
+ .promptPeek summary::before { content: "▸ "; color: var(--echo-ink-faint); }
798
+ .promptPeek[open] summary::before { content: "▾ "; }
799
+ .promptPeek pre { margin: 10px 0 0; white-space: pre-wrap; word-break: break-word; font-family: var(--echo-font-mono); font-size: 12px; line-height: 1.6; color: var(--echo-ink-mute); background: var(--echo-paper-soft); border: 1px solid var(--echo-line-soft); border-radius: 8px; padding: 12px 14px; }
800
+
801
+ @media (max-width: 820px) {
802
+ .exHero, .resultTop, .finishStats, .agentLaunch, .sourceGrid, .readySteps, .readyRun, .readyAction { grid-template-columns: 1fr; }
803
+ .readyHero { grid-template-columns: 1fr; }
804
+ .readyMascot { width: 76px; height: 76px; }
805
+ .readyDecision .actions { justify-content: stretch; }
806
+ .readyDecision .actions .primary { width: 100%; }
807
+ .resultNumber span { text-align: left; }
808
+ }
809
+
810
+ /* ===== workspace readout dashboard (Part 2 — replaces explainPage) ===== */
811
+ @keyframes rdoRise { from { opacity: 0; translate: 0 14px; } to { opacity: 1; translate: 0 0; } }
812
+ @keyframes rdoGrow { from { transform: scaleY(0); } to { transform: scaleY(1); } }
813
+ @keyframes rdoDraw { from { transform: scaleX(0); } to { transform: scaleX(1); } }
814
+ @keyframes rdoWipe { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }
815
+ /* Pull the report up toward the city figure — the canvas bottom fades out now,
816
+ so the document can tuck into that empty band without touching the board. */
817
+ body.cityMode .detailsWrap { background: var(--echo-paper-canvas); margin-top: clamp(-120px, -7vw, -56px); }
818
+
819
+ /* Context audit — a printed report sheet on the desk: serif document type, tight rhythm. */
820
+ .context-audit {
821
+ `;