codexmeter 1.0.0 → 1.0.2

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.
@@ -0,0 +1,244 @@
1
+ const AUTO = 'auto';
2
+
3
+ /**
4
+ * Overview ingest animation control panel.
5
+ *
6
+ * This is the single source of truth for:
7
+ * - Overview client-side presentation timing
8
+ * - Overview ECharts timing defaults
9
+ * - Overview server-side tail pacing
10
+ *
11
+ * `speed` scales the main timings:
12
+ * - `1` = baseline
13
+ * - `2` = 2x faster
14
+ * - `0.5` = 2x slower
15
+ *
16
+ * Per-chart overrides use:
17
+ * - `'auto'` to inherit the scaled main value
18
+ * - a number to force an explicit value in ms
19
+ */
20
+ export const OVERVIEW_INGEST_ANIMATION = {
21
+ speed: 1,
22
+ main: {
23
+ presentationDurationMs: 190,
24
+ chartAppearDurationMs: 0,
25
+ chartUpdateDurationMs: 200,
26
+ easing: 'linear',
27
+ easingUpdate: 'linear',
28
+ },
29
+ tail: {
30
+ // Master switch for the end-of-ingest slowdown behavior.
31
+ enabled: true,
32
+ // Progress threshold where the tail mode starts, expressed from 0..1.
33
+ startPercent: 0.85,
34
+ // Fixed presentation duration in ms during the tail; use AUTO to derive it from main.durationScale.
35
+ durationMs: AUTO,
36
+ // Multiplier applied to the normal presentation duration when durationMs is AUTO.
37
+ durationScale: 100,
38
+ // Shared easing applied by the Overview presentation animator during the tail.
39
+ easing: 'cubicOut',
40
+ // Backend Overview live-update cadence during the tail, in patches per second.
41
+ overviewHz: 5,
42
+ },
43
+ daily: {
44
+ chartAppearDurationMs: AUTO,
45
+ chartUpdateDurationMs: 30,
46
+ easing: AUTO,
47
+ easingUpdate: AUTO,
48
+ },
49
+ bars: {
50
+ chartAppearDurationMs: AUTO,
51
+ chartUpdateDurationMs: 20,
52
+ easing: AUTO,
53
+ easingUpdate: AUTO,
54
+ },
55
+ donuts: {
56
+ chartAppearDurationMs: AUTO,
57
+ chartUpdateDurationMs: AUTO,
58
+ easing: AUTO,
59
+ easingUpdate: 'linear',
60
+ seriesAnimation: false,
61
+ },
62
+ heatmap: {
63
+ /** Duration (ms) of the pop animation when a cell gets new data during ingest */
64
+ popDurationMs: 380,
65
+ /** Don't trigger pop when ingest progress is above this (avoids burst at settle) */
66
+ settleThreshold: 0.998,
67
+ /** Min relative intensity rise (0–1) to trigger pop – e.g. 0.08 = cell turning white */
68
+ intensityRiseThreshold: 0.08,
69
+ /** Relative intensity (0–1) that counts as "white" – crossing this triggers pop */
70
+ whiteThreshold: 0.88,
71
+ /** Cell is "new winner" if val >= maxVal * this when max increased */
72
+ nearMaxRatio: 0.985,
73
+ },
74
+ videoExport: {
75
+ width: 1080,
76
+ height: 864,
77
+ fps: 60,
78
+ introDurationMs: 900,
79
+ replayDurationMs: 8000,
80
+ tailDurationMs: 5000,
81
+ tailReplayFraction: 0.72,
82
+ captureFormat: 'png',
83
+ jpegQuality: 92,
84
+ crf: 10,
85
+ encoderPreset: 'veryfast',
86
+ },
87
+ };
88
+
89
+ /** Shared ECharts animation defaults for non-Overview charts */
90
+ export const ECHARTS_ANIMATION = {
91
+ animationDuration: 750,
92
+ animationDurationUpdate: 220,
93
+ animationEasing: 'cubicOut',
94
+ animationEasingUpdate: 'cubicOut',
95
+ };
96
+
97
+ /** Label animation - fade in after chart finishes */
98
+ export const ECHARTS_LABEL_ANIMATION = {
99
+ show: true,
100
+ animationDuration: 250,
101
+ animationDurationUpdate: 220,
102
+ animationDelay: 250,
103
+ animationDelayUpdate: 180,
104
+ animationEasing: 'cubicOut',
105
+ animationEasingUpdate: 'cubicOut',
106
+ };
107
+
108
+ /** Detail donut charts (Repos/Models/Daily) */
109
+ export const ECHARTS_DONUT_ANIMATION = {
110
+ ...ECHARTS_ANIMATION,
111
+ animationDurationUpdate: 200,
112
+ animationDelayUpdate: 0,
113
+ animationEasingUpdate: 'cubicOut',
114
+ };
115
+
116
+ /** Detail bar charts (Repos/Models/Daily) */
117
+ export const ECHARTS_DETAIL_BAR_ANIMATION = {
118
+ animationDuration: 700,
119
+ animationDurationUpdate: 220,
120
+ animationDelay: 250,
121
+ animationDelayUpdate: 140,
122
+ animationEasing: 'cubicOut',
123
+ animationEasingUpdate: 'cubicOut',
124
+ };
125
+
126
+ /** Detail bar labels */
127
+ export const ECHARTS_DETAIL_BAR_LABEL_ANIMATION = {
128
+ ...ECHARTS_LABEL_ANIMATION,
129
+ animationDelay: 950,
130
+ animationDelayUpdate: 360,
131
+ };
132
+
133
+ function safeSpeed(value) {
134
+ return Number.isFinite(value) && value > 0 ? value : 1;
135
+ }
136
+
137
+ function scaledMainDuration(ms) {
138
+ return Math.max(0, Math.round(ms / safeSpeed(OVERVIEW_INGEST_ANIMATION.speed)));
139
+ }
140
+
141
+ function resolveOverviewValue(overrideValue, mainValue) {
142
+ return overrideValue === AUTO ? scaledMainDuration(mainValue) : overrideValue;
143
+ }
144
+
145
+ function resolveOverviewString(overrideValue, mainValue) {
146
+ return overrideValue === AUTO ? mainValue : overrideValue;
147
+ }
148
+
149
+ function buildOverviewChartAnimation(overrides) {
150
+ return {
151
+ animation: true,
152
+ animationDuration: resolveOverviewValue(
153
+ overrides.chartAppearDurationMs,
154
+ OVERVIEW_INGEST_ANIMATION.main.chartAppearDurationMs
155
+ ),
156
+ animationDurationUpdate: resolveOverviewValue(
157
+ overrides.chartUpdateDurationMs,
158
+ OVERVIEW_INGEST_ANIMATION.main.chartUpdateDurationMs
159
+ ),
160
+ animationEasing: resolveOverviewString(
161
+ overrides.easing,
162
+ OVERVIEW_INGEST_ANIMATION.main.easing
163
+ ),
164
+ animationEasingUpdate: resolveOverviewString(
165
+ overrides.easingUpdate,
166
+ OVERVIEW_INGEST_ANIMATION.main.easingUpdate
167
+ ),
168
+ };
169
+ }
170
+
171
+ export const OVERVIEW_PRESENTATION_DURATION_MS = scaledMainDuration(
172
+ OVERVIEW_INGEST_ANIMATION.main.presentationDurationMs
173
+ );
174
+
175
+ export function resolveOverviewPresentationDuration(progress = 0, isIngestActive = false) {
176
+ const base = OVERVIEW_PRESENTATION_DURATION_MS;
177
+ const tail = OVERVIEW_INGEST_ANIMATION.tail;
178
+
179
+ if (!isIngestActive || !tail?.enabled) return base;
180
+
181
+ const start = Math.min(Math.max(tail.startPercent ?? 0.9, 0), 0.999);
182
+ const clampedProgress = Math.min(Math.max(progress || 0, 0), 1);
183
+ if (clampedProgress <= start) return base;
184
+
185
+ const normalized = (clampedProgress - start) / Math.max(1 - start, 0.001);
186
+ const durationTarget = tail.durationMs === AUTO
187
+ ? Math.round(base * Math.max(tail.durationScale || 1, 1))
188
+ : tail.durationMs;
189
+
190
+ return Math.round(base + (durationTarget - base) * cubicOut(normalized));
191
+ }
192
+
193
+ export function resolveOverviewPresentationEasing(progress = 0, isIngestActive = false) {
194
+ const tail = OVERVIEW_INGEST_ANIMATION.tail;
195
+ if (!isIngestActive || !tail?.enabled) return 'linear';
196
+
197
+ const start = Math.min(Math.max(tail.startPercent ?? 0.9, 0), 0.999);
198
+ const clampedProgress = Math.min(Math.max(progress || 0, 0), 1);
199
+ if (clampedProgress <= start) return 'linear';
200
+
201
+ return tail.easing || 'cubicOut';
202
+ }
203
+
204
+ export function isOverviewTailActive(progress = 0, isIngestActive = false) {
205
+ const tail = OVERVIEW_INGEST_ANIMATION.tail;
206
+ if (!isIngestActive || !tail?.enabled) return false;
207
+
208
+ const start = Math.min(Math.max(tail.startPercent ?? 0.9, 0), 0.999);
209
+ const clampedProgress = Math.min(Math.max(progress || 0, 0), 1);
210
+ return clampedProgress > start;
211
+ }
212
+
213
+ /** Overview page - resolved main animation config */
214
+ export const ECHARTS_OVERVIEW_ANIMATION = buildOverviewChartAnimation({
215
+ chartAppearDurationMs: AUTO,
216
+ chartUpdateDurationMs: AUTO,
217
+ easing: AUTO,
218
+ easingUpdate: AUTO,
219
+ });
220
+
221
+ /** Overview DailySpark - compact stacked bar */
222
+ export const ECHARTS_OVERVIEW_DAILY = buildOverviewChartAnimation(
223
+ OVERVIEW_INGEST_ANIMATION.daily
224
+ );
225
+
226
+ /** Overview Top Repos - horizontal bar chart */
227
+ export const ECHARTS_OVERVIEW_BARS = buildOverviewChartAnimation(
228
+ OVERVIEW_INGEST_ANIMATION.bars
229
+ );
230
+
231
+ /** Overview Work Type & Models - donut charts */
232
+ export const ECHARTS_OVERVIEW_DONUTS = buildOverviewChartAnimation(
233
+ OVERVIEW_INGEST_ANIMATION.donuts
234
+ );
235
+
236
+ export const ECHARTS_OVERVIEW_DONUT_SERIES_ANIMATION =
237
+ OVERVIEW_INGEST_ANIMATION.donuts.seriesAnimation;
238
+
239
+ export { AUTO as OVERVIEW_ANIMATION_AUTO };
240
+
241
+ function cubicOut(t) {
242
+ const x = Math.min(Math.max(t, 0), 1);
243
+ return 1 - Math.pow(1 - x, 3);
244
+ }
@@ -1 +0,0 @@
1
- :root{--bg-base: #06080f;--bg-surface: #0d1117;--bg-card: #161b22;--bg-card-hover: #1c2333;--bg-elevated: #21262d;--border: #30363d;--border-accent: rgba(99, 102, 241, .25);--text-primary: #e6edf3;--text-secondary: #8b949e;--text-muted: #484f58;--accent: #6366f1;--accent-dim: rgba(99, 102, 241, .12);--green: #3fb950;--yellow: #d29922;--red: #f85149;--orange: #f97316;--cyan: #39d2f5;--pink: #f472b6;--font-sans: "Inter", -apple-system, BlinkMacSystemFont, sans-serif;--font-mono: "JetBrains Mono", "Fira Code", monospace;--radius: 8px;--radius-lg: 12px}*{box-sizing:border-box;margin:0;padding:0}body{font-family:var(--font-sans);background:var(--bg-base);color:var(--text-primary);line-height:1.6;-webkit-font-smoothing:antialiased}.app{min-height:100vh;display:flex;flex-direction:column}.app-content{opacity:0;display:flex;flex-direction:column;min-height:100vh}.app-content-revealed{opacity:1;animation:contentReveal .5s ease forwards}@keyframes contentReveal{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}.navbar{background:var(--bg-surface);border-bottom:1px solid var(--border);position:sticky;top:0;z-index:100;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px)}.navbar-inner{display:flex;align-items:center;gap:1.5rem;padding:0 2rem;height:48px;max-width:1400px;margin:0 auto;width:100%;box-sizing:border-box}.navbar-brand{font-weight:700;font-size:.95rem;letter-spacing:-.03em;background:linear-gradient(135deg,#818cf8,#6366f1);-webkit-background-clip:text;-webkit-text-fill-color:transparent}.navbar-tabs{display:flex;gap:2px}.navbar-tab{padding:.35rem .85rem;border-radius:6px;cursor:pointer;font-size:.8rem;font-weight:500;color:var(--text-secondary);background:none;border:none;transition:all .15s}.navbar-tab:hover{color:var(--text-primary);background:var(--bg-card)}.navbar-tab.active{color:#fff;background:var(--accent)}.navbar-meta{margin-left:auto;display:flex;align-items:center;gap:.75rem;flex:1;min-width:0}.navbar-ingest-wrap{display:flex;align-items:center;gap:.75rem;flex:1;min-width:0;transition:opacity .3s ease}.navbar-ingest-wrap.navbar-ingest-fade-out{opacity:0;pointer-events:none}.navbar-date-wrap{display:flex;align-items:center;gap:.75rem;margin-left:auto;flex-shrink:0;transition:opacity .3s ease}.navbar-date-wrap-dimmed{opacity:.5;pointer-events:none}.navbar-date{display:inline-block;width:22ch;min-width:22ch;font-variant-numeric:tabular-nums;text-align:right;overflow:hidden;text-overflow:ellipsis}.navbar-progress-wrap{flex:1;height:4px;background:var(--bg-elevated);border-radius:2px;overflow:hidden}.navbar-progress-bar{height:100%;background:linear-gradient(90deg,var(--accent),#818cf8);border-radius:2px;transition:width .4s ease}.navbar-status{font-size:.7rem;color:var(--text-muted);font-family:var(--font-mono)}.main-content{flex:1;padding:1.5rem 2rem 3rem;max-width:1400px;margin:0 auto;width:100%;min-width:0;container-type:inline-size;container-name:main}.app-footer{padding:.75rem 2rem 1rem;font-size:.7rem;color:var(--text-muted);text-align:center;max-width:1400px;margin:auto auto 0;width:100%;box-sizing:border-box}.section-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:1.25rem}.section-title{font-size:1rem;font-weight:600;letter-spacing:-.01em}.stat-row{display:flex;flex-wrap:wrap;gap:1rem;align-items:stretch;margin-bottom:1.5rem}.stat-cards{display:grid;grid-template-columns:repeat(4,minmax(160px,1fr));gap:.75rem;flex:0 0 auto;min-width:0}@media(max-width:920px){.stat-cards{flex:1 1 auto;grid-template-columns:repeat(2,minmax(160px,1fr))}}@media(max-width:500px){.stat-cards{grid-template-columns:1fr}}.stat-card{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius);padding:1rem 1.1rem;transition:border-color .2s}.stat-card:hover{border-color:var(--border-accent)}.stat-label{font-size:.65rem;font-weight:600;text-transform:uppercase;letter-spacing:.06em;color:var(--text-muted);margin-bottom:.35rem}.stat-value{font-size:1.6rem;font-weight:700;font-family:var(--font-mono);letter-spacing:-.03em;line-height:1.1}.stat-sub{font-size:.72rem;color:var(--text-muted);margin-top:.2rem}.stat-per-day{font-size:.72rem;color:var(--text-muted);margin-top:.25rem;font-family:var(--font-mono)}.stat-per-day .stat-per-day-value{font-weight:600;color:var(--text-secondary)}.range-toggle{display:inline-flex;background:var(--bg-card);border:1px solid var(--border);border-radius:6px;overflow:hidden}.range-btn{padding:.3rem .7rem;font-size:.72rem;font-weight:600;color:var(--text-muted);background:none;border:none;cursor:pointer;transition:all .15s}.range-btn:hover{color:var(--text-secondary)}.range-btn.active{color:#fff;background:var(--accent)}.heatmap-wrap{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius-lg);padding:1.25rem;margin-bottom:1.5rem;overflow-x:auto}.heatmap-grid{display:grid;grid-auto-flow:column;grid-template-rows:repeat(7,1fr);gap:3px}.heatmap-cell{width:13px;height:13px;border-radius:2px;background:var(--bg-elevated);opacity:.4;transform:scale(.82);transition:background .18s ease,opacity .22s ease,transform .22s ease}.heatmap-cell.active{opacity:1;transform:scale(1)}.heatmap-cell:hover{outline:1px solid var(--text-muted)}.heatmap-labels{display:flex;justify-content:space-between;margin-top:.5rem;font-size:.65rem;color:var(--text-muted)}.chart-card{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius-lg);padding:1.25rem;margin-bottom:1.5rem;position:relative}.chart-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:.75rem}.chart-title{font-size:.85rem;font-weight:600}.chart-badge{font-size:.62rem;color:var(--yellow);background:#d299221a;padding:.15rem .5rem;border-radius:4px}.export-btn{position:absolute;top:.75rem;right:.75rem;padding:.25rem .5rem;border-radius:4px;border:1px solid var(--border);background:var(--bg-surface);color:var(--text-muted);font-size:.65rem;cursor:pointer;opacity:0;transition:all .15s;z-index:2}.chart-card:hover .export-btn{opacity:.7}.export-btn:hover{opacity:1!important;color:var(--text-primary);border-color:var(--accent)}.grid-2{display:grid;grid-template-columns:1fr 1fr;gap:1.25rem;margin-bottom:1.5rem;min-width:0}.grid-3{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:1.25rem;margin-bottom:1.5rem;min-width:0}.grid-3>.chart-card{min-width:0;overflow:hidden}@media(max-width:900px){.grid-2,.grid-3{grid-template-columns:1fr}}.btn-group{display:flex;gap:2px}.btn{padding:.3rem .65rem;border-radius:5px;border:1px solid var(--border);background:var(--bg-surface);color:var(--text-muted);font-size:.72rem;font-weight:500;cursor:pointer;transition:all .12s}.btn:hover{color:var(--text-secondary);border-color:var(--text-muted)}.btn.active{color:#fff;background:var(--accent);border-color:var(--accent)}.icon-btn{width:28px;height:28px;display:inline-flex;align-items:center;justify-content:center;border-radius:6px;border:1px solid var(--border);background:var(--bg-card);color:var(--text-muted);font-size:.9rem;line-height:1;cursor:pointer;transition:color .12s,border-color .12s,background .12s,transform .12s}.icon-btn:hover:not(:disabled){color:var(--text-primary);border-color:var(--accent);background:var(--bg-elevated);transform:rotate(20deg)}.icon-btn:disabled{opacity:.55;cursor:wait}.overview-daily-spark{flex:1 1 140px;min-width:140px;min-height:0;position:relative;background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius-lg);overflow:visible}.overview-daily-spark-title{position:absolute;top:1rem;left:1.1rem;font-size:.65rem;font-weight:600;text-transform:uppercase;letter-spacing:.06em;color:var(--text-muted);z-index:1;pointer-events:none}.overview-daily-spark-chart{position:absolute;top:0;right:0;bottom:0;left:0;overflow:hidden}.overview-daily-spark-empty{display:flex;align-items:center;justify-content:center}.overview-daily-spark-empty-text{font-size:.7rem;color:var(--text-muted)}@media(max-width:920px){.overview-daily-spark{flex:1 1 100%;min-width:100%;min-height:140px}}.table-wrap{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius-lg);overflow:hidden}.model-detail-wrap{display:flex;flex-direction:column;gap:.85rem}.model-detail-note{color:var(--text-muted);font-size:.74rem;line-height:1.4}.model-detail-footer{display:flex;justify-content:flex-start;margin-top:.25rem}.model-detail-toggle{display:inline-flex;align-items:center;gap:.35rem;width:fit-content;padding:.35rem .6rem;font-size:.72rem;font-weight:500;color:var(--text-muted);background:#ffffff0a;border:1px solid var(--border);border-radius:6px;cursor:pointer;transition:color .2s,background .2s,border-color .2s}.model-detail-toggle:hover{color:var(--text-secondary);background:#ffffff0f;border-color:#6366f14d}.model-detail-toggle-text{font-family:var(--font-sans)}.model-detail-toggle-arrow{font-size:.6rem;opacity:.8;transition:transform .25s ease}.model-detail-toggle-arrow.expanded{transform:rotate(180deg)}.model-detail-charts{display:flex;gap:.25rem;flex-wrap:wrap;align-items:flex-start;width:100%;overflow:visible;position:relative;z-index:10}.model-detail-donut{flex:0 0 200px;width:200px;min-width:200px;height:200px;overflow:visible;z-index:10;display:flex;flex-direction:column}.model-detail-donut .chart-title{flex-shrink:0}.model-detail-donut .echarts-for-react{flex:1;min-height:0}.model-detail-wrap .model-detail-donut{flex:0 0 340px;width:340px;min-width:340px;height:220px}.model-detail-donut .echarts-for-react,.model-detail-donut .echarts-for-react>div,.model-detail-bar .echarts-for-react,.model-detail-bar .echarts-for-react>div{overflow:visible!important}.model-detail-bar{flex:1 1 300px;min-width:300px;height:200px;overflow:visible;display:flex;flex-direction:column}.model-detail-bar .chart-title{flex-shrink:0}.model-detail-bar .echarts-for-react{flex:1;min-height:0}.model-detail-summary-wrap{max-height:0;overflow:hidden;transition:max-height .2s ease-out}.model-detail-summary-wrap.expanded{max-height:400px}.model-detail-summary{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:.6rem;padding-top:.5rem}.model-detail-summary-card{background:#ffffff05;border:1px solid var(--border);border-radius:10px;padding:.65rem .75rem}.model-detail-summary-head{display:flex;align-items:center;gap:.45rem;margin-bottom:.45rem;font-size:.76rem;font-weight:600;color:var(--text-primary);text-transform:capitalize;min-width:0}.model-detail-summary-head .model-detail-summary-name{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.model-detail-swatch{width:9px;height:9px;border-radius:999px;flex:0 0 auto}.model-detail-summary-line{font-size:.72rem;color:var(--text-muted);line-height:1.45}.detail-summary-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:.75rem;margin-bottom:1rem}.detail-summary-stat{background:#ffffff08;border:1px solid var(--border);border-radius:10px;padding:.8rem .9rem}.detail-summary-label{font-size:.68rem;text-transform:uppercase;letter-spacing:.05em;color:var(--text-muted);margin-bottom:.25rem}.detail-summary-value{font-size:1.1rem;font-family:var(--font-mono);color:var(--text-primary)}.table-search{padding:.75rem 1rem;border-bottom:1px solid var(--border)}.table-search input{width:100%;padding:.5rem .85rem;border-radius:6px;border:1px solid var(--border);background:var(--bg-surface);color:var(--text-primary);font-size:.82rem;font-family:var(--font-sans);outline:none}.table-search input:focus{border-color:var(--accent)}.table-search input::placeholder{color:var(--text-muted)}table{width:100%;border-collapse:collapse;font-size:.78rem}th{text-align:left;padding:.55rem .85rem;font-weight:600;color:var(--text-muted);border-bottom:1px solid var(--border);font-size:.68rem;text-transform:uppercase;letter-spacing:.05em;cursor:pointer;-webkit-user-select:none;user-select:none;white-space:nowrap}td{padding:.5rem .85rem;border-bottom:1px solid rgba(48,54,61,.5);color:var(--text-secondary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:240px}tr:hover td{color:var(--text-primary);background:#6366f108}.tag{display:inline-block;padding:.1rem .4rem;border-radius:4px;font-size:.66rem;font-family:var(--font-mono);font-weight:500}.tag-review{background:#06b6d41f;color:var(--cyan)}.tag-exploration{background:#f973161f;color:var(--orange)}.tag-planning{background:#eab3081f;color:var(--yellow)}.tag-memory{background:#ec48991f;color:var(--pink)}.tag-generic{background:#64748b1f;color:var(--text-secondary)}.loading-overlay{position:fixed;top:0;right:0;bottom:0;left:0;background:#06080feb;-webkit-backdrop-filter:blur(20px);backdrop-filter:blur(20px);display:flex;flex-direction:column;align-items:center;justify-content:center;z-index:999;transition:opacity .6s ease}.loading-overlay.fading{opacity:0;pointer-events:none}.loading-logo{font-size:1.5rem;font-weight:700;background:linear-gradient(135deg,#818cf8,#6366f1);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;margin-bottom:1.5rem}.loading-bar-wrap{width:260px;height:4px;background:var(--bg-elevated);border-radius:2px;overflow:hidden;margin-bottom:1rem}.loading-bar{height:100%;background:linear-gradient(90deg,var(--accent),#818cf8);border-radius:2px;transition:width .4s ease}.loading-phase{font-size:.82rem;font-weight:500;color:var(--text-secondary);margin-bottom:.2rem}.loading-detail{font-family:var(--font-mono);font-size:.72rem;color:var(--text-muted)}.loading-footer{position:absolute;bottom:1.5rem;font-size:.7rem;color:var(--text-muted)}.loading-heart{color:#f43f5e}.coverage-subtle{display:flex;align-items:center;gap:1.5rem;font-size:.68rem;color:var(--text-muted);padding:.5rem 0;margin-bottom:1rem}.coverage-item{display:flex;align-items:center;gap:.35rem;font-variant-numeric:tabular-nums}.coverage-nums{display:inline-block;min-width:9ch;text-align:right}.coverage-nums-single{min-width:4ch}.coverage-dot{width:6px;height:6px;border-radius:50%}html{scrollbar-width:none}::-webkit-scrollbar{display:none;width:0;height:0}@keyframes fadeUp{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.animate-in{animation:fadeUp .35s ease forwards}@keyframes pulse{0%,to{opacity:1}50%{opacity:.5}}.incomplete-badge{font-size:.65rem;color:var(--yellow);background:#d299221a;padding:.12rem .45rem;border-radius:3px;animation:pulse 2s infinite}.ingesting-badge .ingesting-pct{display:inline-block;min-width:4ch;text-align:right;font-variant-numeric:tabular-nums}.echarts-tooltip,[class*=ec-component-tooltip]{max-width:90vw!important;max-height:80vh!important;overflow:auto!important}