codexmeter 1.0.2 → 1.0.3
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/README.md +2 -1
- package/dist/assets/index-CBnwoOLi.js +117 -0
- package/dist/assets/index-DhDq9dI8.css +1 -0
- package/dist/index.html +2 -2
- package/package.json +1 -1
- package/server/aggregator.js +9 -5
- package/server/export-video.js +501 -44
- package/server/index.js +17 -2
- package/server/live-state.js +9 -6
- package/src/utils/animationsDefault.js +42 -6
- package/dist/assets/index-C0qLYGUY.css +0 -1
- package/dist/assets/index-M87czq50.js +0 -113
package/server/index.js
CHANGED
|
@@ -2,12 +2,13 @@ import express from 'express';
|
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { fileURLToPath } from 'url';
|
|
4
4
|
import { attachLiveSubscriber, createIngestState, detachLiveSubscriber, getLatestReplay, restartIngest, runIngest } from './ingest.js';
|
|
5
|
-
import { createJobSummary, createVideoExportManager, getActiveVideoExportJob, getVideoExportJob, startOverviewVideoExport } from './export-video.js';
|
|
5
|
+
import { createJobSummary, createVideoExportManager, getActiveVideoExportJob, getVideoExportJob, getVideoExportSupport, startOverviewVideoExport } from './export-video.js';
|
|
6
6
|
|
|
7
7
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
8
8
|
|
|
9
9
|
export function createServer(codexHome, opts = {}) {
|
|
10
10
|
const app = express();
|
|
11
|
+
app.use(express.json());
|
|
11
12
|
const state = createIngestState();
|
|
12
13
|
const exportManager = createVideoExportManager();
|
|
13
14
|
const distDir = path.join(__dirname, '..', 'dist');
|
|
@@ -80,6 +81,11 @@ export function createServer(codexHome, opts = {}) {
|
|
|
80
81
|
app.get('/api/families', wrap('families'));
|
|
81
82
|
|
|
82
83
|
app.post('/api/export/overview-video', async (req, res) => {
|
|
84
|
+
const activeJob = getActiveVideoExportJob(exportManager);
|
|
85
|
+
if (activeJob) {
|
|
86
|
+
res.status(409).json({ error: 'Another export job is already running.' });
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
83
89
|
const replay = getLatestReplay(state);
|
|
84
90
|
if (!replay) {
|
|
85
91
|
res.status(409).json({ error: 'No completed ingest replay is available yet.' });
|
|
@@ -96,7 +102,12 @@ export function createServer(codexHome, opts = {}) {
|
|
|
96
102
|
heatmap: { data: state.aggregates.heatmap },
|
|
97
103
|
} : null;
|
|
98
104
|
try {
|
|
99
|
-
const job = await startOverviewVideoExport(exportManager, {
|
|
105
|
+
const job = await startOverviewVideoExport(exportManager, {
|
|
106
|
+
replay,
|
|
107
|
+
settledEnvelope,
|
|
108
|
+
appBaseUrl,
|
|
109
|
+
installPortableBrowser: Boolean(req.body?.install_portable_browser),
|
|
110
|
+
});
|
|
100
111
|
res.status(202).json(createJobSummary(job, `${req.protocol}://${req.get('host')}`));
|
|
101
112
|
} catch (err) {
|
|
102
113
|
res.status(err.statusCode || 500).json({ error: err.message || String(err) });
|
|
@@ -112,6 +123,10 @@ export function createServer(codexHome, opts = {}) {
|
|
|
112
123
|
res.json({ job: createJobSummary(job, `${req.protocol}://${req.get('host')}`) });
|
|
113
124
|
});
|
|
114
125
|
|
|
126
|
+
app.get('/api/export/support', async (_req, res) => {
|
|
127
|
+
res.json(await getVideoExportSupport());
|
|
128
|
+
});
|
|
129
|
+
|
|
115
130
|
app.get('/api/export/:jobId/status', (req, res) => {
|
|
116
131
|
const job = getVideoExportJob(exportManager, req.params.jobId);
|
|
117
132
|
if (!job) {
|
package/server/live-state.js
CHANGED
|
@@ -82,7 +82,7 @@ export function buildLiveBootstrap(live) {
|
|
|
82
82
|
export function buildLivePatch(live, patch) {
|
|
83
83
|
return {
|
|
84
84
|
overview: Object.fromEntries(
|
|
85
|
-
[...patch.overview].map((rangeKey) => [rangeKey, serializeOverviewBucket(live.overview[rangeKey])])
|
|
85
|
+
[...patch.overview].map((rangeKey) => [rangeKey, serializeOverviewBucket(live.overview[rangeKey], live.lowerBounds[rangeKey])])
|
|
86
86
|
),
|
|
87
87
|
repos: serializePatchedTopRanges(live.repos, live.repoTopKeys, patch.repos, serializeRepoSummary),
|
|
88
88
|
models: serializePatchedTopRanges(live.models, live.modelTopKeys, patch.models, serializeModelSummary),
|
|
@@ -352,14 +352,17 @@ function ensureHeatmapDay(dayMap, dayKey) {
|
|
|
352
352
|
|
|
353
353
|
function serializeOverview(live) {
|
|
354
354
|
return {
|
|
355
|
-
total: serializeOverviewBucket(live.overview.total),
|
|
356
|
-
d7: serializeOverviewBucket(live.overview.d7),
|
|
357
|
-
d30: serializeOverviewBucket(live.overview.d30),
|
|
355
|
+
total: serializeOverviewBucket(live.overview.total, live.lowerBounds.total),
|
|
356
|
+
d7: serializeOverviewBucket(live.overview.d7, live.lowerBounds.d7),
|
|
357
|
+
d30: serializeOverviewBucket(live.overview.d30, live.lowerBounds.d30),
|
|
358
358
|
cost_assumptions: CACHE_ASSUMPTIONS,
|
|
359
359
|
};
|
|
360
360
|
}
|
|
361
361
|
|
|
362
|
-
function serializeOverviewBucket(bucket) {
|
|
362
|
+
function serializeOverviewBucket(bucket, lowerBound = 0) {
|
|
363
|
+
const boundedFrom = bucket.earliest === Infinity
|
|
364
|
+
? null
|
|
365
|
+
: Math.max(bucket.earliest, lowerBound || 0);
|
|
363
366
|
return {
|
|
364
367
|
total_tokens: bucket.total_tokens,
|
|
365
368
|
total_cost: bucket.total_cost,
|
|
@@ -368,7 +371,7 @@ function serializeOverviewBucket(bucket) {
|
|
|
368
371
|
active_models: bucket.modelSet.size,
|
|
369
372
|
total_elapsed_seconds: bucket.total_elapsed_seconds,
|
|
370
373
|
date_range: {
|
|
371
|
-
from:
|
|
374
|
+
from: boundedFrom,
|
|
372
375
|
to: bucket.latest === -Infinity ? null : bucket.latest,
|
|
373
376
|
},
|
|
374
377
|
coverage: {
|
|
@@ -20,7 +20,7 @@ const AUTO = 'auto';
|
|
|
20
20
|
export const OVERVIEW_INGEST_ANIMATION = {
|
|
21
21
|
speed: 1,
|
|
22
22
|
main: {
|
|
23
|
-
presentationDurationMs:
|
|
23
|
+
presentationDurationMs: 300,
|
|
24
24
|
chartAppearDurationMs: 0,
|
|
25
25
|
chartUpdateDurationMs: 200,
|
|
26
26
|
easing: 'linear',
|
|
@@ -34,7 +34,7 @@ export const OVERVIEW_INGEST_ANIMATION = {
|
|
|
34
34
|
// Fixed presentation duration in ms during the tail; use AUTO to derive it from main.durationScale.
|
|
35
35
|
durationMs: AUTO,
|
|
36
36
|
// Multiplier applied to the normal presentation duration when durationMs is AUTO.
|
|
37
|
-
durationScale:
|
|
37
|
+
durationScale: 20,
|
|
38
38
|
// Shared easing applied by the Overview presentation animator during the tail.
|
|
39
39
|
easing: 'cubicOut',
|
|
40
40
|
// Backend Overview live-update cadence during the tail, in patches per second.
|
|
@@ -72,16 +72,52 @@ export const OVERVIEW_INGEST_ANIMATION = {
|
|
|
72
72
|
nearMaxRatio: 0.985,
|
|
73
73
|
},
|
|
74
74
|
videoExport: {
|
|
75
|
+
// Video export settings
|
|
75
76
|
width: 1080,
|
|
76
77
|
height: 864,
|
|
77
78
|
fps: 60,
|
|
78
|
-
|
|
79
|
-
|
|
79
|
+
frontloadSettledFrameCount: 1,
|
|
80
|
+
|
|
81
|
+
// Intro fade-in effect
|
|
82
|
+
introFadeEnabled: true,
|
|
83
|
+
introFadeStartOpacity: 0.95,
|
|
84
|
+
introContentStartOpacity: 0.05,
|
|
85
|
+
introFadeDurationMs: 400,
|
|
86
|
+
introFadeDelayMs: 0,
|
|
87
|
+
introFadeEasing: 'cubicOut',
|
|
88
|
+
|
|
89
|
+
// Start Delay for the animation
|
|
90
|
+
startHoldDurationMs: 100,
|
|
91
|
+
|
|
92
|
+
// Replay duration
|
|
93
|
+
replayDurationMs: 10000,
|
|
94
|
+
|
|
95
|
+
// Tail Settings
|
|
80
96
|
tailDurationMs: 5000,
|
|
81
|
-
|
|
97
|
+
replayEasing: 'cubicIn',
|
|
98
|
+
tailSourceFraction: 0.55,
|
|
99
|
+
tailEasing: 'cubicOut',
|
|
100
|
+
finalHoldDurationMs: 5000,
|
|
101
|
+
|
|
102
|
+
// Final Flash Settings
|
|
103
|
+
finalFlashDurationMs: 1000,
|
|
104
|
+
finalFlashMaxOpacity: 0.35,
|
|
105
|
+
|
|
106
|
+
// Display Tween Settings
|
|
107
|
+
displayTweenStartMs: 200,
|
|
108
|
+
displayTweenBaseMs: 240,
|
|
109
|
+
displayTweenLateMs: 420,
|
|
110
|
+
displayTweenLateWindowMs: 2200,
|
|
111
|
+
barsChartUpdateDurationMs: 50,
|
|
112
|
+
barsChartTailUpdateDurationMs: 240,
|
|
113
|
+
donutsChartUpdateDurationMs: 50,
|
|
114
|
+
donutsChartTailUpdateDurationMs: 240,
|
|
115
|
+
|
|
116
|
+
// Render settings
|
|
117
|
+
supersampleScale: 2,
|
|
82
118
|
captureFormat: 'png',
|
|
83
119
|
jpegQuality: 92,
|
|
84
|
-
crf:
|
|
120
|
+
crf: 5,
|
|
85
121
|
encoderPreset: 'veryfast',
|
|
86
122
|
},
|
|
87
123
|
};
|
|
@@ -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,opacity .35s ease}.navbar-tab:hover{color:var(--text-primary);background:var(--bg-card)}.navbar-tab.active{color:#fff;background:var(--accent)}.navbar-tab.navbar-tab-dimmed,.navbar-tab.navbar-tab-dimmed:hover{opacity:.4;color:var(--text-muted)}.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 1.25rem;max-width:1400px;margin:0 auto;width:100%;min-width:0;container-type:inline-size;container-name:main}.app-footer{padding:.5rem 2rem .75rem;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-cell.heatmap-cell-pop{animation:heatmap-cell-pop .38s cubic-bezier(.34,1.56,.64,1)}@keyframes heatmap-cell-pop{0%{transform:scale(1);box-shadow:none}40%{transform:scale(1.4);box-shadow:0 0 10px #6366f1b3,0 0 0 1.5px #0003}70%{transform:scale(1.1);box-shadow:0 0 4px #6366f159,0 0 0 .5px #0000001a}to{transform:scale(1);box-shadow:none}}.heatmap-cell.heatmap-cell-pop-dim{animation:heatmap-cell-pop-dim .32s cubic-bezier(.34,1.56,.64,1)}@keyframes heatmap-cell-pop-dim{0%{transform:scale(1)}50%{transform:scale(.85)}to{transform:scale(1)}}.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:.25rem 0;margin-top:-.5rem;margin-bottom:.5rem}.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}
|