pi-mega-compact 0.13.7 → 0.14.1
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 +13 -6
- package/dist/extensions/dashboard-server/api-contracts/endpoints/registry.js +6 -0
- package/dist/extensions/dashboard-server/index-reader.js +49 -26
- package/dist/extensions/dashboard-server/routes-cache.js +17 -5
- package/dist/extensions/dashboard-server/routes-rag-settings-helpers.js +7 -0
- package/dist/extensions/dashboard-server/routes-raptor.js +60 -0
- package/dist/extensions/dashboard-server/routes.js +1 -1
- package/dist/extensions/dashboard-server/server.js +3 -1
- package/dist/extensions/mega-pipeline/recall.js +24 -16
- package/dist/extensions/mega-runtime/capture-model.js +15 -2
- package/dist/extensions/mega-runtime/runtime-snapshot.js +26 -0
- package/dist/extensions/mega-runtime/runtime.js +1 -0
- package/dist/src/config/dedup.js +2 -1
- package/dist/src/costApi.js +113 -0
- package/dist/src/dedup/raptor/incremental.js +31 -3
- package/dist/src/dedup/raptor/index.js +10 -6
- package/dist/src/vector-search.js +3 -3
- package/extensions/dashboard-client/dist/assets/{AreaChart-j2VOSRp6.js → AreaChart-BUUketyS.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{AreaChart-j2VOSRp6.js.map → AreaChart-BUUketyS.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{CacheTab-Dr1HeMfc.js → CacheTab-VNFZSdRr.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{CacheTab-Dr1HeMfc.js.map → CacheTab-VNFZSdRr.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{EventsTab-DRG2k7FS.js → EventsTab-Dr7RDBy2.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{EventsTab-DRG2k7FS.js.map → EventsTab-Dr7RDBy2.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{HealthTab-DGE9PpW3.js → HealthTab-B8VZ8gbb.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{HealthTab-DGE9PpW3.js.map → HealthTab-B8VZ8gbb.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MaintenanceTab-DeYRhF4q.js → MaintenanceTab-DMtrXRcn.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MaintenanceTab-DeYRhF4q.js.map → MaintenanceTab-DMtrXRcn.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/MemoryMapTab-PFrMdLOm.js +2 -0
- package/extensions/dashboard-client/dist/assets/{MemoryMapTab-DSnSO3nG.js.map → MemoryMapTab-PFrMdLOm.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MetricsTab-RIzNc1Uj.js → MetricsTab-Dd1kXuvg.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MetricsTab-RIzNc1Uj.js.map → MetricsTab-Dd1kXuvg.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{OverviewTab-_1BJ4Bmh.js → OverviewTab-DOpObVA9.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{OverviewTab-_1BJ4Bmh.js.map → OverviewTab-DOpObVA9.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{ReposTab-DkU7ywZB.js → ReposTab-D6pEUtEJ.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{ReposTab-DkU7ywZB.js.map → ReposTab-D6pEUtEJ.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{SessionsTab-Bq_F_aOk.js → SessionsTab-CcFzDJ7W.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{SessionsTab-Bq_F_aOk.js.map → SessionsTab-CcFzDJ7W.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{SetupTab-BkBD2Y97.js → SetupTab-YCt5NGB5.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{SetupTab-BkBD2Y97.js.map → SetupTab-YCt5NGB5.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{TimeSavedCard-BXzFKU7C.js → TimeSavedCard-BsLNhOOj.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{TimeSavedCard-BXzFKU7C.js.map → TimeSavedCard-BsLNhOOj.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{TurnsTab-Bjpp3vBH.js → TurnsTab-C1jpVZrH.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{TurnsTab-Bjpp3vBH.js.map → TurnsTab-C1jpVZrH.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{WikiTab-dBN2EA5G.js → WikiTab-RHoVt95g.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{WikiTab-dBN2EA5G.js.map → WikiTab-RHoVt95g.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{button-Bt0b5QVp.js → button-DSZI4aZ5.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{button-Bt0b5QVp.js.map → button-DSZI4aZ5.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{card-D5CafXtg.js → card-CsZzIyPW.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{card-D5CafXtg.js.map → card-CsZzIyPW.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{index-GPHRnEN7.js → index-B1_J_Y0b.js} +11 -11
- package/extensions/dashboard-client/dist/assets/index-B1_J_Y0b.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/index-C5TGTOd6.css +1 -0
- package/extensions/dashboard-client/dist/assets/{switch-CY5Gwj1o.js → switch-DOIA1Nxu.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{switch-CY5Gwj1o.js.map → switch-DOIA1Nxu.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{toggle-C9HpkIfH.js → toggle-CyS6PHCO.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{toggle-C9HpkIfH.js.map → toggle-CyS6PHCO.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{useSSE-2JFrLDlE.js → useSSE-CY7UIUzm.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{useSSE-2JFrLDlE.js.map → useSSE-CY7UIUzm.js.map} +1 -1
- package/extensions/dashboard-client/dist/index.html +2 -2
- package/extensions/dashboard-client/src/api/client.ts +10 -0
- package/extensions/dashboard-client/src/components/layout/AppShell.tsx +1 -1
- package/extensions/dashboard-client/src/styles/base.css +2 -4
- package/extensions/dashboard-client/src/tabs/MemoryMapTab/RaptorTreeView.tsx +58 -4
- package/extensions/dashboard-client/tailwind.config.js +1 -1
- package/extensions/dashboard-server/api-contracts/endpoints/registry.ts +9 -1
- package/extensions/dashboard-server/api-contracts/index.ts +2 -2
- package/extensions/dashboard-server/api-contracts/raptor.ts +19 -0
- package/extensions/dashboard-server/index-reader.ts +28 -5
- package/extensions/dashboard-server/routes-cache.ts +17 -5
- package/extensions/dashboard-server/routes-rag-settings-helpers.ts +17 -0
- package/extensions/dashboard-server/routes-raptor.ts +88 -1
- package/extensions/dashboard-server/routes.ts +1 -1
- package/extensions/dashboard-server/server.ts +2 -0
- package/extensions/mega-pipeline/recall.ts +30 -21
- package/extensions/mega-runtime/capture-model.ts +14 -2
- package/extensions/mega-runtime/runtime-snapshot.ts +40 -0
- package/extensions/mega-runtime/runtime.ts +1 -0
- package/package.json +1 -1
- package/src/config/dedup.ts +2 -1
- package/src/costApi.ts +131 -0
- package/src/dedup/raptor/incremental.ts +48 -3
- package/src/dedup/raptor/index.ts +10 -6
- package/src/vector-search.ts +3 -3
- package/extensions/dashboard-client/dist/assets/MemoryMapTab-DSnSO3nG.js +0 -2
- package/extensions/dashboard-client/dist/assets/index-CUA6EDRF.css +0 -1
- package/extensions/dashboard-client/dist/assets/index-GPHRnEN7.js.map +0 -1
package/src/costApi.ts
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* costApi.ts — optional model pricing lookup from an external API.
|
|
3
|
+
*
|
|
4
|
+
* PREVENT-PI-004 EXEMPTION: This module makes network calls to fetch model
|
|
5
|
+
* pricing data. It is disabled by default and must be explicitly opted in via
|
|
6
|
+
* MEGACOMPACT_COST_API_ENABLED=true + MEGACOMPACT_COST_API_URL=<url>.
|
|
7
|
+
*
|
|
8
|
+
* The dashboard server uses this to enrich the inputRate/outputRate fields
|
|
9
|
+
* when the local pricing table (pricing.ts) has no data for a model.
|
|
10
|
+
*
|
|
11
|
+
* Results are cached for 1 hour to minimize network calls.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { spawnSync } from "node:child_process"; // guardrails-allow PREVENT-PI-004: user-opted-in cost API — fetches model pricing from a user-configured endpoint, never called unless MEGACOMPACT_COST_API_ENABLED=true
|
|
15
|
+
|
|
16
|
+
export interface ModelPricing {
|
|
17
|
+
inputRate: number | null;
|
|
18
|
+
outputRate: number | null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface CostApiConfig {
|
|
22
|
+
enabled: boolean;
|
|
23
|
+
url: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
let _cache: { timestamp: number; data: Map<string, ModelPricing> } | null = null;
|
|
27
|
+
const CACHE_TTL_MS = 60 * 60 * 1000; // 1 hour
|
|
28
|
+
|
|
29
|
+
export function costApiConfig(): CostApiConfig {
|
|
30
|
+
const enabled =
|
|
31
|
+
process.env.MEGACOMPACT_COST_API_ENABLED === "true" ||
|
|
32
|
+
process.env.MEGACOMPACT_COST_API_ENABLED === "1";
|
|
33
|
+
const url = process.env.MEGACOMPACT_COST_API_URL ?? "";
|
|
34
|
+
return { enabled, url };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Fetch model pricing from the configured API endpoint.
|
|
39
|
+
*
|
|
40
|
+
* Expects a JSON response of shape:
|
|
41
|
+
* { "data": [{ "id": "model-name", "pricing": { "prompt": "0.000003", "completion": "0.000015" } }] }
|
|
42
|
+
* (OpenRouter-compatible format). Values are USD per token as strings.
|
|
43
|
+
*
|
|
44
|
+
* Returns a map keyed by lowercase model id → { inputRate, outputRate }.
|
|
45
|
+
* Returns an empty map on any error. Never throws.
|
|
46
|
+
*/
|
|
47
|
+
export function fetchModelPricing(): Map<string, ModelPricing> {
|
|
48
|
+
const cfg = costApiConfig();
|
|
49
|
+
if (!cfg.enabled || !cfg.url) return new Map();
|
|
50
|
+
|
|
51
|
+
// Return cached data if fresh.
|
|
52
|
+
if (_cache && Date.now() - _cache.timestamp < CACHE_TTL_MS) {
|
|
53
|
+
return _cache.data;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const result = _doFetch(cfg.url);
|
|
57
|
+
_cache = { timestamp: Date.now(), data: result };
|
|
58
|
+
return result;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function _doFetch(url: string): Map<string, ModelPricing> {
|
|
62
|
+
// Synchronous bridge: spawnSync an inline worker so the call blocks without
|
|
63
|
+
// deadlocking fetch (mirrors HttpEmbedder / RAPTOR summarizer pattern).
|
|
64
|
+
const WORKER = String.raw`
|
|
65
|
+
try {
|
|
66
|
+
const r = await fetch(process.env.COST_API_URL, { // guardrails-allow PREVENT-PI-004: user-opted-in cost API — fetches model pricing from a user-configured endpoint
|
|
67
|
+
method: "GET",
|
|
68
|
+
headers: { "accept": "application/json" },
|
|
69
|
+
});
|
|
70
|
+
const j = await r.json();
|
|
71
|
+
process.stdout.write(JSON.stringify({ ok: r.ok, data: j }));
|
|
72
|
+
} catch (e) {
|
|
73
|
+
process.stdout.write(JSON.stringify({ ok: false, error: String(e && e.message ? e.message : e) }));
|
|
74
|
+
}
|
|
75
|
+
`;
|
|
76
|
+
const res = spawnSync(process.execPath, ["-e", WORKER], {
|
|
77
|
+
encoding: "utf8",
|
|
78
|
+
timeout: 15_000,
|
|
79
|
+
env: { ...process.env, COST_API_URL: url },
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
const out = new Map<string, ModelPricing>();
|
|
83
|
+
|
|
84
|
+
let parsed: { ok: boolean; data?: unknown; error?: string };
|
|
85
|
+
try {
|
|
86
|
+
parsed = JSON.parse(res.stdout);
|
|
87
|
+
} catch {
|
|
88
|
+
return out;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (!parsed.ok || !parsed.data) return out;
|
|
92
|
+
|
|
93
|
+
// OpenRouter-compatible: { data: [{ id, pricing: { prompt, completion } }] }
|
|
94
|
+
const models = (parsed.data as { data?: Array<{ id?: string; pricing?: { prompt?: string; completion?: string } }> })?.data;
|
|
95
|
+
if (!Array.isArray(models)) return out;
|
|
96
|
+
|
|
97
|
+
for (const m of models) {
|
|
98
|
+
if (!m.id) continue;
|
|
99
|
+
const prompt = m.pricing?.prompt;
|
|
100
|
+
const completion = m.pricing?.completion;
|
|
101
|
+
const inputRate = prompt != null ? parseFloat(prompt) : null;
|
|
102
|
+
const outputRate = completion != null ? parseFloat(completion) : null;
|
|
103
|
+
if (inputRate != null || outputRate != null) {
|
|
104
|
+
out.set(m.id.toLowerCase(), { inputRate, outputRate });
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return out;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Look up pricing for a model name from the cost API cache.
|
|
113
|
+
* Tries exact match, then prefix match (same pattern as lookupModelInputRate).
|
|
114
|
+
*/
|
|
115
|
+
export function lookupCostApiPricing(model: string): ModelPricing | null {
|
|
116
|
+
const data = fetchModelPricing();
|
|
117
|
+
if (data.size === 0) return null;
|
|
118
|
+
const lower = model.toLowerCase();
|
|
119
|
+
// Exact match.
|
|
120
|
+
if (data.has(lower)) return data.get(lower) ?? null;
|
|
121
|
+
// Prefix match.
|
|
122
|
+
for (const [key, pricing] of data) {
|
|
123
|
+
if (lower.startsWith(key)) return pricing;
|
|
124
|
+
}
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/** Clear the pricing cache (useful for testing). */
|
|
129
|
+
export function clearCostApiCache(): void {
|
|
130
|
+
_cache = null;
|
|
131
|
+
}
|
|
@@ -13,10 +13,12 @@
|
|
|
13
13
|
import type { Embedder, Vector } from "../../embedder.js";
|
|
14
14
|
import { cosineSimilarity } from "../../embedder.js";
|
|
15
15
|
import { defaultEmbedder as getDefaultEmbedder } from "../../embedder.js";
|
|
16
|
+
import type { EngineMessage } from "../../types.js";
|
|
16
17
|
import { buildRaptorTree, type Leaf, type RaptorTree } from "./tree.js";
|
|
17
18
|
import type { QualityMarker } from "./guardrails.js";
|
|
19
|
+
import { applyHallucinationGuardrails, sourceTokenSet } from "./guardrails.js";
|
|
18
20
|
import { meanVector } from "./kmeans.js";
|
|
19
|
-
import { summarizeCluster } from "./summarizer.js";
|
|
21
|
+
import { summarizeCluster, extractiveClusterSummary } from "./summarizer.js";
|
|
20
22
|
import type { Logger } from "../../log.js";
|
|
21
23
|
import {
|
|
22
24
|
saveRaptorTree,
|
|
@@ -27,6 +29,38 @@ import {
|
|
|
27
29
|
/** When >FRESH_THRESHOLD of existing leaves are new, a full rebuild is cheaper. */
|
|
28
30
|
const FRESH_THRESHOLD = 0.5;
|
|
29
31
|
|
|
32
|
+
/**
|
|
33
|
+
* Summarize + apply hallucination guardrails (mirrors tree.ts:summarizeInto).
|
|
34
|
+
* If the guardrail marks the summary as extractive_fallback (drift/hallucination),
|
|
35
|
+
* re-summarize with the deterministic extractive path so we never serve a
|
|
36
|
+
* drifted LLM summary from an incremental update.
|
|
37
|
+
*/
|
|
38
|
+
function summarizeGuarded(
|
|
39
|
+
messages: EngineMessage[],
|
|
40
|
+
centroid: Vector,
|
|
41
|
+
embedder: Embedder,
|
|
42
|
+
consistencyThreshold?: number,
|
|
43
|
+
): { summary: string; tokenEstimate: number; qualityMarker: QualityMarker } {
|
|
44
|
+
let cs = summarizeCluster(messages);
|
|
45
|
+
const sources = messages.map((m) => m.text);
|
|
46
|
+
const guard = applyHallucinationGuardrails({
|
|
47
|
+
summary: cs.summary,
|
|
48
|
+
sources,
|
|
49
|
+
centroid,
|
|
50
|
+
embedder,
|
|
51
|
+
sourceTokens: sourceTokenSet(sources),
|
|
52
|
+
consistencyThreshold,
|
|
53
|
+
});
|
|
54
|
+
if (guard.marker === "extractive_fallback") {
|
|
55
|
+
cs = extractiveClusterSummary(messages);
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
summary: cs.summary,
|
|
59
|
+
tokenEstimate: cs.tokenEstimate,
|
|
60
|
+
qualityMarker: guard.marker === "extractive_fallback" ? "low" : guard.marker,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
30
64
|
/**
|
|
31
65
|
* Incrementally update a persisted RAPTOR tree with new leaves.
|
|
32
66
|
*
|
|
@@ -173,6 +207,7 @@ export function incrementRaptorTree(
|
|
|
173
207
|
for (const l of reallyNewLeaves) leafMap.set(l.id, l);
|
|
174
208
|
|
|
175
209
|
// Recompute affected Level-0 nodes.
|
|
210
|
+
const embedder = opts.embedder ?? getDefaultEmbedder();
|
|
176
211
|
for (const nid of affectedNodeIds) {
|
|
177
212
|
const node = tree.nodes.get(nid);
|
|
178
213
|
if (!node) continue;
|
|
@@ -186,7 +221,12 @@ export function incrementRaptorTree(
|
|
|
186
221
|
// Summarize: flatten messages from all covered leaves.
|
|
187
222
|
const messages = coveredLeaves.flatMap((l) => l.messages);
|
|
188
223
|
if (messages.length > 0) {
|
|
189
|
-
const cs =
|
|
224
|
+
const cs = summarizeGuarded(
|
|
225
|
+
messages,
|
|
226
|
+
node.embedding,
|
|
227
|
+
embedder,
|
|
228
|
+
opts.consistencyThreshold,
|
|
229
|
+
);
|
|
190
230
|
node.summary = cs.summary;
|
|
191
231
|
node.tokenEstimate = cs.tokenEstimate;
|
|
192
232
|
}
|
|
@@ -215,7 +255,12 @@ export function incrementRaptorTree(
|
|
|
215
255
|
);
|
|
216
256
|
const messages = covered.flatMap((l) => l.messages);
|
|
217
257
|
if (messages.length > 0) {
|
|
218
|
-
const cs =
|
|
258
|
+
const cs = summarizeGuarded(
|
|
259
|
+
messages,
|
|
260
|
+
node.embedding,
|
|
261
|
+
embedder,
|
|
262
|
+
opts.consistencyThreshold,
|
|
263
|
+
);
|
|
219
264
|
node.summary = cs.summary;
|
|
220
265
|
node.tokenEstimate = cs.tokenEstimate;
|
|
221
266
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* index.ts — RAPTOR orchestrator (Sprint 13, Phase 6).
|
|
2
|
+
* index.ts — RAPTOR orchestrator (Sprint 13, Phase 6 → promoted to live in S42B).
|
|
3
3
|
*
|
|
4
4
|
* Entry point that turns a session's leaves into a hierarchical summary tree.
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* The tree is BUILT, PERSISTED to raptor_nodes, and SERVED in recall queries
|
|
6
|
+
* when RAPTOR_ENABLED=true (default). Set RAPTOR_SHADOW_MODE=true to build +
|
|
7
|
+
* persist only without serving (transition/eval use).
|
|
8
8
|
*
|
|
9
9
|
* PREVENT-PI-004: no network here. Any Ollama call lives in summarizer.ts
|
|
10
10
|
* (localhost-only, annotated). This module is pure orchestration.
|
|
@@ -20,9 +20,13 @@ import { saveRaptorTree, listRaptorNodes } from "../../store/sqlite.js";
|
|
|
20
20
|
import { insertBuildHistory, computeCoherenceScore } from "./buildHistory.js";
|
|
21
21
|
import { loadDedupConfig } from "../../config/dedup.js";
|
|
22
22
|
|
|
23
|
-
/**
|
|
23
|
+
/**
|
|
24
|
+
* Shadow mode default OFF: the tree is built, persisted, AND served when
|
|
25
|
+
* RAPTOR_ENABLED=true (the Setup tab toggle). Set RAPTOR_SHADOW_MODE=true to
|
|
26
|
+
* build + persist only (transition/eval use without serving live recall).
|
|
27
|
+
*/
|
|
24
28
|
export function isShadowMode(): boolean {
|
|
25
|
-
return process.env.RAPTOR_SHADOW_MODE
|
|
29
|
+
return process.env.RAPTOR_SHADOW_MODE === "true";
|
|
26
30
|
}
|
|
27
31
|
|
|
28
32
|
export interface RaptorOrchestratorOptions {
|
package/src/vector-search.ts
CHANGED
|
@@ -64,9 +64,9 @@ function raptorSearchHits(
|
|
|
64
64
|
const embedder = store.embedder;
|
|
65
65
|
const record = store.record;
|
|
66
66
|
|
|
67
|
-
// S25 gate (a): honor
|
|
68
|
-
// built + persisted
|
|
69
|
-
//
|
|
67
|
+
// S25 gate (a): honor shadow mode at SERVE time. When RAPTOR_SHADOW_MODE=true,
|
|
68
|
+
// the tree is built + persisted but NOT merged into recall (transition/eval).
|
|
69
|
+
// Default is live: shadow mode is opt-in, not the default.
|
|
70
70
|
if (isShadowMode()) return [];
|
|
71
71
|
// S25 gate (b): freshness + fallback guards with per-session cache.
|
|
72
72
|
// The cache avoids O(n·leaves) rehydrate on every search when the tree
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{j as e,r as i,X as B}from"./index-GPHRnEN7.js";import{T as I}from"./toggle-C9HpkIfH.js";const T={checkpoint:"#6366f1",turn:"#58a6ff","turn-content":"#22c55e",memory:"#f59e0b"},z={checkpoint:"Checkpoint",turn:"Turn","turn-content":"Turn Content",memory:"Memory"};function U(t,n){return`M 0,-${n} L ${t},0 L 0,${n} L -${t},0 Z`}function Y(t){return!t||t==="active"?1:.5}function Q(t,n,c,d,s,u,a){const p=u?T[d]??"#6366f1":"#d1d5db",m=s?"#ef4444":"none",h=Y(a);switch(d){case"checkpoint":return e.jsx("circle",{cx:t,cy:n,r:s?c+3:c,fill:p,opacity:h,stroke:m,strokeWidth:s?2:0});case"turn":return e.jsx("circle",{cx:t,cy:n,r:s?c+3:c,fill:"none",stroke:p,strokeWidth:2.5,opacity:h});case"turn-content":return e.jsxs("g",{children:[e.jsx("circle",{cx:t,cy:n,r:s?c+3:c,fill:"none",stroke:p,strokeWidth:2.5,opacity:h}),e.jsx("circle",{cx:t,cy:n,r:Math.max(3,c*.3),fill:p,opacity:h})]});case"memory":const g=c*.85,j=c*.85;return e.jsx("path",{d:U(g,j),transform:`translate(${t}, ${n})`,fill:p,opacity:h,stroke:m,strokeWidth:s?2:0})}}const X=5e3,P=.005,O=.01,D=.9,Z=.1,L=50;function J(t){const n=t.nodes.map((s,u)=>{const a=2*Math.PI*u/Math.max(t.nodes.length,1),p=200;return{...s,pos:{x:Math.cos(a)*p+300,y:Math.sin(a)*p+200},vx:0,vy:0,pinned:!1}}),c=new Map;n.forEach((s,u)=>c.set(s.id,u));const d=t.edges.map(s=>{const u=c.get(s.source),a=c.get(s.target);return u===void 0||a===void 0||u===a?null:{source:u,target:a,weight:s.weight,type:s.type}}).filter(s=>s!==null);return{nodes:n,edges:d}}function K(t){const{nodes:n,edges:c}=t,d=n.length;if(d!==0)for(let s=0;s<d;s++){if(n[s].pinned)continue;let u=0,a=0;for(let m=0;m<d;m++){if(s===m)continue;const h=n[s].pos.x-n[m].pos.x,g=n[s].pos.y-n[m].pos.y,j=h*h+g*g||1,v=X/j,b=Math.sqrt(j);u+=h/b*v,a+=g/b*v}for(const m of c){let h;if(m.source===s)h=m.target;else if(m.target===s)h=m.source;else continue;const g=n[h].pos.x-n[s].pos.x,j=n[h].pos.y-n[s].pos.y;u+=g*P*m.weight,a+=j*P*m.weight}u-=n[s].pos.x*O,a-=n[s].pos.y*O,n[s].vx=(n[s].vx+u)*D,n[s].vy=(n[s].vy+a)*D;const p=Math.sqrt(n[s].vx*n[s].vx+n[s].vy*n[s].vy);p>L&&(n[s].vx=n[s].vx/p*L,n[s].vy=n[s].vy/p*L),p>Z&&(n[s].pos.x+=n[s].vx,n[s].pos.y+=n[s].vy)}}const ee=300,te=.3,k=900,w=600,x=40;function M(t){switch(t){case"temporal":return"#6366f1";case"semantic":return"#22c55e";case"raptor_parent":return"#f59e0b"}}const N=({color:t,shape:n,label:c})=>{const d={display:"inline-block",width:"10px",height:"10px",verticalAlign:"middle",marginRight:"3px",borderRadius:n.startsWith("hollow")||n==="filled-circle"?"50%":void 0};let s;return n==="line"?e.jsx("span",{style:{color:t,marginRight:"6px"},children:c}):(n==="filled-circle"?s=e.jsx("span",{style:{...d,backgroundColor:t}}):n==="hollow-circle"?s=e.jsx("span",{style:{...d,border:`2px solid ${t}`,backgroundColor:"transparent"}}):n==="hollow-ring"?s=e.jsx("span",{style:{...d,border:`2px solid ${t}`,backgroundColor:"transparent",position:"relative"},children:e.jsx("span",{style:{display:"block",width:"4px",height:"4px",borderRadius:"50%",backgroundColor:t,margin:"2px auto"}})}):s=e.jsx("span",{style:{...d,clipPath:"polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%)",backgroundColor:t}}),e.jsxs(e.Fragment,{children:[e.jsxs("span",{className:"memory-map-legend-item",children:[s,c]})," "]}))},re=()=>{const[t,n]=i.useState(null),[c,d]=i.useState(!0),[s,u]=i.useState(null),[a,p]=i.useState(null),[m,h]=i.useState(""),[g]=i.useState(""),[j,v]=i.useState(0),b=i.useRef(null),S=i.useRef(0);i.useEffect(()=>{let r=!1;const o=new URLSearchParams;return g&&o.set("sessionId",g),o.set("threshold","0.7"),o.set("maxEdgesPerNode","4"),d(!0),u(null),fetch(`/api/memory-map?${o.toString()}`).then(l=>{if(!l.ok)throw new Error(`HTTP ${l.status}`);return l.json()}).then(l=>{r||(n(l),b.current=J(l),v(1),d(!1))}).catch(l=>{r||(u(l instanceof Error?l.message:"Unknown error"),d(!1))}),()=>{r=!0,cancelAnimationFrame(S.current)}},[g]),i.useEffect(()=>{if(!b.current||j===0)return;const r=b.current;let o=0;const l=()=>{o>=ee||(K(r),o++,v(o),S.current=requestAnimationFrame(l))};return S.current=requestAnimationFrame(l),()=>cancelAnimationFrame(S.current)},[j]);const W=i.useCallback((r,o)=>{const l=b.current;l&&(l.nodes[o].pinned=!l.nodes[o].pinned,l.nodes[o].pinned||(l.nodes[o].vx=0,l.nodes[o].vy=0),p(f=>f?.id===r.id?null:r),v(f=>f+1))},[]),$=i.useMemo(()=>{const r=b.current;if(!r||!m)return null;const o=m.toLowerCase();return new Set(r.nodes.map((l,f)=>l.summaryTruncated.toLowerCase().includes(o)||l.label.toLowerCase().includes(o)?f:-1).filter(l=>l>=0))},[m]),R=i.useMemo(()=>{const r=t?.validation;return r?r.gatesPassed<r.gatesRun?{level:"red",label:"Gate failure"}:r.warnings.length>0?{level:"yellow",label:`${r.warnings.length} warning(s)`}:{level:"green",label:"Healthy"}:{level:"yellow",label:"No validation"}},[t?.validation]),F={green:"#22c55e",yellow:"#eab308",red:"#ef4444"},G=i.useMemo(()=>{const r=t?.validation;if(!r)return`${t?.metadata.totalNodes??0} nodes`;const o=[];return r.sources.checkpoint>0&&o.push(`${r.sources.checkpoint} checkpoints`),r.sources.turn>0&&o.push(`${r.sources.turn} turns`),r.sources.turnContent>0&&o.push(`${r.sources.turnContent} turn-content`),r.sources.memory>0&&o.push(`${r.sources.memory} memories`),o.length===0&&o.push(`${t?.metadata.totalNodes??0} nodes`),o.join(" · ")},[t?.validation,t?.metadata.totalNodes]),A=i.useMemo(()=>{const r=t?.validation;if(!r)return"";const o=[];return o.push(r.sources.checkpoint>0?"✓ checkpoints":"✗ checkpoints"),o.push(r.sources.turn>0?"✓ turns":"✗ turns"),o.push(r.sources.turnContent>0?"✓ turn-content":"✗ turn-content"),o.push(r.sources.memory>0?"✓ memories":"✗ memories"),o.join(" | ")},[t?.validation]),H=i.useMemo(()=>{const r=t?.validation;return r?r.sources.checkpoint===0&&r.sources.turn===0&&r.sources.turnContent===0&&r.sources.memory===0:t?.metadata.totalNodes===0},[t?.validation,t?.metadata.totalNodes]);if(c)return e.jsx("div",{className:"rounded-lg border border-border bg-bg-card p-6 text-center text-sm text-muted-foreground",children:"Loading memory graph..."});if(s)return e.jsxs("div",{className:"rounded-lg border border-border bg-bg-card p-6 text-center text-sm",children:[e.jsxs("p",{className:"text-red-400",children:["Failed to load memory map: ",s]}),e.jsx("button",{className:"mt-3 rounded-md border border-border px-3 py-1.5 text-sm transition-colors hover:bg-bg-elevated hover:text-foreground",onClick:()=>v(r=>r+1),children:"Retry"})]});if(!t||!b.current||H)return e.jsx("div",{className:"rounded-lg border border-border bg-bg-card p-6 text-sm text-muted-foreground",children:e.jsx("p",{children:"Memories appear after your first compaction. The graph shows checkpoints (compaction summaries) linked by semantic similarity and time. Run a longer session or lower the compaction tier to see it sooner."})});const y=b.current;return e.jsxs("div",{className:"flex flex-col gap-3",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[e.jsx("input",{type:"text",placeholder:"Search memories...",value:m,onInput:r=>h(r.target.value),className:"w-56 rounded-md border border-border bg-bg-elevated/50 px-3 py-2 text-sm outline-none transition-colors focus:border-primary"}),e.jsxs("span",{className:"text-xs text-muted-foreground",children:[e.jsx("span",{children:G})," · ",e.jsxs("span",{children:[t.edges.length," edges"]})]}),e.jsx("span",{className:"ml-auto rounded-full px-2 py-1 text-[11px] font-semibold text-white",style:{backgroundColor:F[R.level]??"#6b7280"},title:`Validation: ${R.label}`,children:R.level==="green"?"Healthy":R.level==="yellow"?"Warnings":"Critical"})]}),A?e.jsx("div",{className:"text-[11px] text-muted-foreground",children:A}):null,e.jsxs("div",{className:"flex flex-wrap items-center gap-x-4 gap-y-1 rounded-lg border border-border/60 bg-bg-card px-3 py-2 text-xs",children:[e.jsx("span",{className:"font-semibold text-muted-foreground",children:"Nodes:"}),e.jsx(N,{type:"node",color:T.checkpoint,shape:"filled-circle",label:"Checkpoint"}),e.jsx(N,{type:"node",color:T.turn,shape:"hollow-circle",label:"Turn"}),e.jsx(N,{type:"node",color:T["turn-content"],shape:"hollow-ring",label:"Turn Content"}),e.jsx(N,{type:"node",color:T.memory,shape:"diamond",label:"Memory"}),e.jsx("span",{className:"font-semibold text-muted-foreground",children:"Edges:"}),e.jsx(N,{type:"edge",color:M("semantic"),shape:"line",label:"Semantic"}),e.jsx(N,{type:"edge",color:M("temporal"),shape:"line",label:"Temporal"}),e.jsx(N,{type:"edge",color:M("raptor_parent"),shape:"line",label:"Raptor"})]}),e.jsxs("svg",{width:k,height:w,viewBox:`0 0 ${k} ${w}`,className:"memory-map-svg",children:[y.edges.map((r,o)=>{const l=y.nodes[r.source],f=y.nodes[r.target],C=M(r.type),E=Math.max(1,r.weight*2.5);return e.jsx("line",{x1:x+l.pos.x/(y.nodes.length||1)*(k-2*x),y1:x+l.pos.y/(y.nodes.length||1)*(w-2*x),x2:x+f.pos.x/(y.nodes.length||1)*(k-2*x),y2:x+f.pos.y/(y.nodes.length||1)*(w-2*x),stroke:C,strokeWidth:E,opacity:te},`edge-${o}`)}),y.nodes.map((r,o)=>{const l=x+r.pos.x/(y.nodes.length||1)*(k-2*x),f=x+r.pos.y/(y.nodes.length||1)*(w-2*x),C=Math.min(20,8+r.tokenEstimate/500),E=$?$.has(o):!0,q=a?.id===r.id,V=r.label.length>20?r.label.slice(0,18)+"...":r.label;return e.jsxs("g",{className:"memory-map-node-group",onClick:()=>W(r,o),style:{cursor:"pointer"},children:[Q(l,f,C,r.nodeType,q,E,r.dedupStatus),e.jsx("text",{x:l,y:f+C+12,textAnchor:"middle",fontSize:"9px",fill:"#374151",className:"memory-map-label",children:V})]},`node-${o}`)})]}),a?e.jsxs("div",{className:"rounded-lg border border-border/60 bg-bg-card p-4 text-sm",children:[e.jsxs("h3",{className:"font-heading text-base font-semibold",children:[e.jsx("span",{className:"mr-1.5 text-xs font-normal text-muted-foreground",children:z[a.nodeType]}),a.label]}),e.jsx("p",{className:"mt-1",children:a.summaryTruncated}),a.topicSummary?e.jsxs("p",{className:"mt-1",children:["Topic: ",a.topicSummary]}):null,e.jsxs("p",{className:"mt-1",children:["Tokens: ",a.tokenEstimate," | Decisions: ",a.decisionCount]}),e.jsxs("p",{children:["Session: ",a.sessionId]}),e.jsxs("p",{children:["Raptor Level: ",a.raptorLevel]}),e.jsx("p",{className:"mt-1 text-muted-foreground",children:a.textSnippet})]}):null]})};function se(t){return t===0?"#d4a017":t===1?"#3b82f6":"#14b8a6"}function _(t){return t?new Date(t).toLocaleString():"—"}function ne({node:t}){const n=se(t.level),c=t.children.length>0?`${t.children.length} child${t.children.length===1?"":"ren"}`:"leaf";return e.jsxs("div",{style:{background:"#14142b",border:`1px solid ${n}`,borderRadius:"8px",padding:"0.75rem 1rem",marginBottom:"0.6rem",marginLeft:t.level*24,maxWidth:"90%"},children:[e.jsxs("div",{style:{display:"flex",gap:"0.75rem",alignItems:"center",marginBottom:"0.35rem"},children:[e.jsxs("span",{style:{display:"inline-block",background:n,color:"#fff",borderRadius:"10px",padding:"1px 8px",fontSize:"11px",fontWeight:600},children:["L",t.level]}),e.jsxs("span",{style:{fontSize:"12px",color:"#6b7280"},children:[c," · ",t.tokenEstimate," tok · ",t.qualityMarker]}),e.jsx("span",{style:{fontSize:"12px",color:"#6b7280",marginLeft:"auto"},children:_(t.builtAt)})]}),e.jsx("div",{style:{fontSize:"0.92rem",color:"#e5e7eb"},children:t.summary})]})}function oe(){const[t,n]=i.useState(null),[c,d]=i.useState(!0),[s,u]=i.useState(null);return i.useEffect(()=>{let a=!1;return d(!0),u(null),B().then(p=>{a||(n(p),d(!1))}).catch(p=>{a||(u(p instanceof Error?p.message:"Unknown error"),d(!1))}),()=>{a=!0}},[]),c?e.jsx("div",{className:"rounded-lg border border-border bg-bg-card p-6 text-center text-sm text-muted-foreground",children:"Loading RAPTOR tree..."}):s?e.jsx("div",{className:"rounded-lg border border-dashed border-border bg-bg-card p-8 text-center text-sm",children:e.jsxs("p",{className:"text-red-400",children:["Failed to load RAPTOR tree: ",s]})}):!t||t.empty||t.nodes.length===0?e.jsx("div",{className:"rounded-lg border border-dashed border-border bg-bg-card p-8 text-center text-sm text-muted-foreground",children:e.jsx("p",{children:"No RAPTOR tree built yet — run a compaction (the tree builds during compaction)."})}):e.jsxs("div",{className:"w-full p-4",children:[e.jsxs("div",{className:"mb-4 flex items-center gap-6 text-sm text-muted-foreground",children:[e.jsxs("span",{children:[e.jsx("strong",{children:t.nodes.length})," nodes"]}),e.jsxs("span",{children:[e.jsx("strong",{children:t.levels+1})," levels"]}),e.jsxs("span",{children:["Built ",_(t.builtAt??0)]})]}),t.nodes.map(a=>e.jsx(ne,{node:a},a.id))]})}const ce=()=>{const[t,n]=i.useState("map");return e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsxs("nav",{className:"flex gap-2 border-b border-border pb-2 pt-2","aria-label":"Memory map sections",children:[e.jsx(I,{pressed:t==="map",onClick:()=>n("map"),"aria-label":"Memory Map view",children:"Memory Map"}),e.jsx(I,{pressed:t==="raptor",onClick:()=>n("raptor"),"aria-label":"RAPTOR Tree view",children:"RAPTOR Tree"})]}),t==="map"&&e.jsx(re,{}),t==="raptor"&&e.jsx(oe,{})]})};export{ce as default};
|
|
2
|
-
//# sourceMappingURL=MemoryMapTab-DSnSO3nG.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:Inter,ui-sans-serif,system-ui,sans-serif;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:JetBrains Mono,ui-monospace,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}:root{--bg: 222 47% 5%;--bg-card: 222 32% 8%;--bg-elevated: 222 28% 12%;--border: 217 33% 17%;--foreground: 210 40% 98%;--muted: 215 20% 65%;--primary: 217 91% 60%;--primary-glow: 217 91% 60%;--success: 142 71% 45%;--warning: 38 92% 50%;--danger: 0 84% 60%;--accent: 280 100% 70%;--radius: .75rem}*{border-color:hsl(var(--border))}html{background-color:hsl(var(--bg));color:hsl(var(--foreground));-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body{background-color:hsl(var(--bg));font-family:Inter,ui-sans-serif,system-ui,sans-serif;color:hsl(var(--foreground));margin:0}h1,h2,h3,h4,h5,h6{font-family:JetBrains Mono,ui-monospace,monospace}:where(button,[role=tab],a):focus-visible{outline:2px solid hsl(var(--primary) / .6);outline-offset:2px}.container{width:100%;margin-right:auto;margin-left:auto;padding-right:1.5rem;padding-left:1.5rem}@media (min-width: 1600px){.container{max-width:1600px}}.glass-panel{position:relative;border-radius:var(--radius);border-width:1px;border-color:hsl(var(--border));background-color:hsl(var(--bg-card) / .7);--tw-backdrop-blur: blur(12px);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);box-shadow:inset 0 1px hsl(var(--border) / .5),var(--tw-shadow, 0 8px 30px -12px hsl(var(--bg) / .6))}.electric-hover{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s}.electric-hover:hover{--tw-translate-y: -.125rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));border-color:hsl(var(--primary) / .7);box-shadow:0 0 20px -4px hsl(var(--primary-glow) / .45)}.electric-hover:focus-visible{outline:2px solid hsl(var(--primary) / .6);outline-offset:2px}.glow-primary{box-shadow:0 0 20px -4px hsl(var(--primary-glow) / .5)}.text-neon{color:hsl(var(--primary))}.gradient-text{background:linear-gradient(120deg,hsl(var(--primary)),hsl(var(--accent)));-webkit-background-clip:text;background-clip:text;color:transparent}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.collapse{visibility:collapse}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.inset-x-3{left:.75rem;right:.75rem}.bottom-16{bottom:4rem}.bottom-3{bottom:.75rem}.left-2{left:.5rem}.right-2{right:.5rem}.top-0{top:0}.z-40{z-index:40}.z-50{z-index:50}.mx-auto{margin-left:auto;margin-right:auto}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.ml-2{margin-left:.5rem}.ml-auto{margin-left:auto}.mr-1{margin-right:.25rem}.mr-1\.5{margin-right:.375rem}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.line-clamp-3{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-0\.5{height:.125rem}.h-1\.5{height:.375rem}.h-10{height:2.5rem}.h-2{height:.5rem}.h-3\.5{height:.875rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-8{height:2rem}.h-9{height:2.25rem}.h-full{height:100%}.max-h-40{max-height:10rem}.max-h-48{max-height:12rem}.max-h-56{max-height:14rem}.max-h-72{max-height:18rem}.max-h-96{max-height:24rem}.max-h-\[85vh\]{max-height:85vh}.min-h-screen{min-height:100vh}.w-1\.5{width:.375rem}.w-1\/3{width:33.333333%}.w-16{width:4rem}.w-2{width:.5rem}.w-20{width:5rem}.w-24{width:6rem}.w-3\.5{width:.875rem}.w-4{width:1rem}.w-40{width:10rem}.w-5{width:1.25rem}.w-56{width:14rem}.w-6{width:1.5rem}.w-64{width:16rem}.w-9{width:2.25rem}.w-full{width:100%}.min-w-0{min-width:0px}.min-w-\[8rem\]{min-width:8rem}.max-w-3xl{max-width:48rem}.max-w-\[1600px\]{max-width:1600px}.max-w-md{max-width:28rem}.max-w-sm{max-width:24rem}.max-w-xl{max-width:36rem}.flex-1{flex:1 1 0%}.shrink-0{flex-shrink:0}.table-fixed{table-layout:fixed}.border-collapse{border-collapse:collapse}.rotate-180{--tw-rotate: 180deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-pointer{cursor:pointer}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.list-decimal{list-style-type:decimal}.list-disc{list-style-type:disc}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-row{flex-direction:row}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.items-baseline{align-items:baseline}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.justify-around{justify-content:space-around}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-6{gap:1.5rem}.gap-x-4{-moz-column-gap:1rem;column-gap:1rem}.gap-y-0\.5{row-gap:.125rem}.gap-y-1{row-gap:.25rem}.gap-y-2{row-gap:.5rem}.space-y-0>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(0px * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(0px * var(--tw-space-y-reverse))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * var(--tw-space-y-reverse))}.space-y-1\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.375rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.375rem * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse))}.divide-border>:not([hidden])~:not([hidden]){border-color:hsl(var(--border))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:var(--radius)}.rounded-md{border-radius:calc(var(--radius) - 2px)}.rounded-sm{border-radius:calc(var(--radius) - 4px)}.rounded-xl{border-radius:.75rem}.rounded-t-xl{border-top-left-radius:.75rem;border-top-right-radius:.75rem}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-t{border-top-width:1px}.border-dashed{border-style:dashed}.border-accent\/40{border-color:hsl(var(--accent) / .4)}.border-amber-500\/30{border-color:#f59e0b4d}.border-border{border-color:hsl(var(--border))}.border-border\/40{border-color:hsl(var(--border) / .4)}.border-border\/50{border-color:hsl(var(--border) / .5)}.border-border\/60{border-color:hsl(var(--border) / .6)}.border-danger\/40{border-color:hsl(var(--danger) / .4)}.border-green-500{--tw-border-opacity: 1;border-color:rgb(34 197 94 / var(--tw-border-opacity, 1))}.border-primary\/40{border-color:hsl(var(--primary) / .4)}.border-primary\/50{border-color:hsl(var(--primary) / .5)}.border-red-500\/50{border-color:#ef444480}.border-success\/40{border-color:hsl(var(--success) / .4)}.border-transparent{border-color:transparent}.border-warning\/40{border-color:hsl(var(--warning) / .4)}.bg-accent\/15{background-color:hsl(var(--accent) / .15)}.bg-amber-500{--tw-bg-opacity: 1;background-color:rgb(245 158 11 / var(--tw-bg-opacity, 1))}.bg-amber-500\/5{background-color:#f59e0b0d}.bg-background{background-color:hsl(var(--bg))}.bg-bg-card{background-color:hsl(var(--bg-card))}.bg-bg-elevated{background-color:hsl(var(--bg-elevated))}.bg-bg-elevated\/20{background-color:hsl(var(--bg-elevated) / .2)}.bg-bg-elevated\/40{background-color:hsl(var(--bg-elevated) / .4)}.bg-bg-elevated\/50{background-color:hsl(var(--bg-elevated) / .5)}.bg-bg-elevated\/60{background-color:hsl(var(--bg-elevated) / .6)}.bg-black\/50{background-color:#00000080}.bg-black\/60{background-color:#0009}.bg-current{background-color:currentColor}.bg-danger{background-color:hsl(var(--danger))}.bg-danger\/15{background-color:hsl(var(--danger) / .15)}.bg-foreground,.bg-muted-foreground{background-color:hsl(var(--foreground))}.bg-primary{background-color:hsl(var(--primary))}.bg-primary\/10{background-color:hsl(var(--primary) / .1)}.bg-primary\/15{background-color:hsl(var(--primary) / .15)}.bg-success{background-color:hsl(var(--success))}.bg-success\/15{background-color:hsl(var(--success) / .15)}.bg-transparent{background-color:transparent}.bg-warning\/10{background-color:hsl(var(--warning) / .1)}.bg-warning\/15{background-color:hsl(var(--warning) / .15)}.p-1{padding:.25rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.p-8{padding:2rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-8{padding-left:2rem;padding-right:2rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.pb-2{padding-bottom:.5rem}.pb-20{padding-bottom:5rem}.pl-5{padding-left:1.25rem}.pl-8{padding-left:2rem}.pr-2{padding-right:.5rem}.pr-3{padding-right:.75rem}.pt-2{padding-top:.5rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.align-top{vertical-align:top}.font-heading,.font-mono{font-family:JetBrains Mono,ui-monospace,monospace}.text-2xl{font-size:1.5rem;line-height:2rem}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.tracking-tight{letter-spacing:-.025em}.tracking-wide{letter-spacing:.025em}.tracking-widest{letter-spacing:.1em}.text-accent{color:hsl(var(--accent))}.text-amber-400{--tw-text-opacity: 1;color:rgb(251 191 36 / var(--tw-text-opacity, 1))}.text-danger{color:hsl(var(--danger))}.text-emerald-400{--tw-text-opacity: 1;color:rgb(52 211 153 / var(--tw-text-opacity, 1))}.text-foreground{color:hsl(var(--foreground))}.text-foreground\/90{color:hsl(var(--foreground) / .9)}.text-muted{color:hsl(var(--muted))}.text-muted-foreground{color:hsl(var(--foreground))}.text-muted-foreground\/60{color:hsl(var(--foreground) / .6)}.text-primary-foreground{--tw-text-opacity: 1;color:hsl(222 47% 5% / var(--tw-text-opacity, 1))}.text-red-400{--tw-text-opacity: 1;color:rgb(248 113 113 / var(--tw-text-opacity, 1))}.text-success{color:hsl(var(--success))}.text-warning{color:hsl(var(--warning))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.underline{text-decoration-line:underline}.accent-primary{accent-color:hsl(var(--primary))}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-panel{--tw-shadow: 0 8px 30px -12px hsl(var(--bg) / .6);--tw-shadow-colored: 0 8px 30px -12px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.outline-none{outline:2px solid transparent;outline-offset:2px}.outline{outline-style:solid}.ring{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.focus\:text-neon:focus{color:hsl(var(--primary))}.data-\[state\=active\]\:text-neon[data-state=active]{color:hsl(var(--primary))}.placeholder\:text-muted-foreground::-moz-placeholder{color:hsl(var(--foreground))}.placeholder\:text-muted-foreground::placeholder{color:hsl(var(--foreground))}.last\:border-0:last-child{border-width:0px}.hover\:bg-bg-elevated:hover{background-color:hsl(var(--bg-elevated))}.hover\:bg-bg-elevated\/40:hover{background-color:hsl(var(--bg-elevated) / .4)}.hover\:bg-primary\/90:hover{background-color:hsl(var(--primary) / .9)}.hover\:bg-red-500\/10:hover{background-color:#ef44441a}.hover\:text-foreground:hover{color:hsl(var(--foreground))}.hover\:text-red-300:hover{--tw-text-opacity: 1;color:rgb(252 165 165 / var(--tw-text-opacity, 1))}.focus\:border-primary:focus{border-color:hsl(var(--primary))}.focus\:bg-primary\/15:focus{background-color:hsl(var(--primary) / .15)}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-2:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-primary\/60:focus{--tw-ring-color: hsl(var(--primary) / .6)}.focus-visible\:outline-none:focus-visible{outline:2px solid transparent;outline-offset:2px}.focus-visible\:ring-2:focus-visible{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus-visible\:ring-primary\/60:focus-visible{--tw-ring-color: hsl(var(--primary) / .6)}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}.data-\[disabled\]\:pointer-events-none[data-disabled]{pointer-events:none}.data-\[state\=checked\]\:translate-x-4[data-state=checked]{--tw-translate-x: 1rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.data-\[state\=unchecked\]\:translate-x-0\.5[data-state=unchecked]{--tw-translate-x: .125rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.data-\[state\=active\]\:bg-primary\/15[data-state=active]{background-color:hsl(var(--primary) / .15)}.data-\[state\=checked\]\:bg-primary[data-state=checked]{background-color:hsl(var(--primary))}.data-\[state\=unchecked\]\:bg-bg-elevated[data-state=unchecked]{background-color:hsl(var(--bg-elevated))}.data-\[disabled\]\:opacity-50[data-disabled]{opacity:.5}@media (min-width: 640px){.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}@media (min-width: 768px){.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}}@media (min-width: 1024px){.lg\:flex{display:flex}.lg\:hidden{display:none}.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}.lg\:pb-4{padding-bottom:1rem}}@media (min-width: 1280px){.xl\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.xl\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}}.\[\&_svg\]\:pointer-events-none svg{pointer-events:none}.\[\&_svg\]\:size-4 svg{width:1rem;height:1rem}.\[\&_svg\]\:shrink-0 svg{flex-shrink:0}:root{--bg: #0d1117;--panel: #161b22;--border: #30363d;--text: #e6edf3;--muted: #8b949e;--accent: #58a6ff;--ok: #3fb950;--warn: #d29922;--err: #f85149;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;font-size:clamp(13px,.9vw,16px)}*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--text)}.dashboard-app{max-width:min(1600px,96vw);margin:0 auto;padding:clamp(8px,2vw,24px)}.card-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,320px),1fr));gap:clamp(8px,1.5vw,16px)}.dashboard-header h1{font-size:clamp(16px,1.4vw,22px);font-weight:600;margin:0 0 clamp(8px,1vw,16px)}.dashboard-header .tier,.dashboard-header .version-pill{display:inline-block;margin-left:8px;padding:2px 8px;font-size:clamp(10px,.8vw,12px);border-radius:10px;background:var(--panel);border:1px solid var(--border);color:var(--muted)}.dashboard-header .tier{color:var(--accent)}.tab-bar{display:flex;gap:4px;border-bottom:1px solid var(--border);margin-bottom:clamp(8px,1vw,16px);overflow-x:auto;flex-wrap:nowrap}.tab-bar button{background:none;border:none;color:var(--muted);padding:8px 14px;cursor:pointer;font-size:clamp(12px,.85vw,14px);border-bottom:2px solid transparent;white-space:nowrap}.tab-bar button.active{color:var(--text);border-bottom-color:var(--accent)}.tab-bar button:hover{color:var(--text)}.tab-bar .advanced-toggle{background:none;border:none;color:var(--muted);padding:8px 14px;cursor:pointer;font-size:clamp(12px,.85vw,14px);border-bottom:2px solid transparent;white-space:nowrap;margin-left:6px}.tab-bar .advanced-toggle:hover{color:var(--text)}.tab-bar .advanced-toggle[aria-expanded=true]{color:var(--text);border-bottom-color:var(--border)}.tab-bar .advanced-tabs{display:flex;gap:4px;flex-basis:100%;border-top:1px dashed var(--border);padding-top:6px;margin-top:-1px}.dashboard-content{min-height:400px}.loading-spinner{display:flex;align-items:center;justify-content:center;padding:48px;color:var(--muted)}.error-fallback{padding:24px;border:1px solid var(--err);border-radius:8px;background:#f8514914}.error-fallback button{margin-top:12px;padding:6px 14px;background:var(--panel);border:1px solid var(--border);color:var(--text);border-radius:6px;cursor:pointer}.tab-stub{padding:32px;color:var(--muted);border:1px dashed var(--border);border-radius:8px;text-align:center}.repos{width:100%;border-collapse:collapse;font-size:clamp(12px,.8vw,14px)}.repos th,.repos td{padding:6px 10px;border-bottom:1px solid var(--border-soft, var(--border));text-align:left}.repos th{background:var(--bg);position:sticky;top:0}.table-wrap{overflow-x:auto}@media (max-width: 640px){.card-grid{grid-template-columns:1fr}.tab-bar button{padding:6px 10px;font-size:12px}}@media (min-width: 641px) and (max-width: 1024px){.card-grid{grid-template-columns:repeat(2,1fr)}}@media (min-width: 1025px){.card-grid{grid-template-columns:repeat(auto-fit,minmax(320px,1fr))}}@media (min-width: 1601px){.dashboard-app{max-width:min(1800px,96vw)}.card-grid{grid-template-columns:repeat(4,1fr)}}.overview-tab{display:flex;flex-direction:column;gap:12px}.overview-header{display:flex;align-items:center;gap:12px}.tier-pill{padding:2px 10px;font-size:12px;border-radius:10px;background:var(--panel);border:1px solid var(--border);color:var(--accent)}.updated{color:var(--muted);font-size:12px}.card-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:12px}.card{padding:14px 16px;background:var(--panel);border:1px solid var(--border);border-radius:8px}.card h3{margin:0 0 10px;font-size:13px;color:var(--muted);font-weight:600}.gauge-bar{height:10px;background:var(--bg);border-radius:5px;overflow:hidden;border:1px solid var(--border)}.gauge-fill{height:100%;transition:width .4s ease}.gauge-green .gauge-fill{background:var(--ok)}.gauge-yellow .gauge-fill{background:var(--warn)}.gauge-red .gauge-fill{background:var(--err)}.gauge-label{margin:8px 0 0;font-size:12px;color:var(--muted)}.stat-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:8px}.stat{display:flex;flex-direction:column;gap:2px}.stat-label{font-size:11px;color:var(--muted);text-transform:uppercase}.stat-value{font-size:16px;font-weight:600}.stat-highlight .stat-value{color:var(--ok)}.bullet-row{display:flex;gap:14px;margin-bottom:8px}.bullet{display:flex;align-items:center;gap:6px;font-size:13px}.bullet-dot{width:8px;height:8px;border-radius:50%;background:var(--muted)}.bullet-on .bullet-dot{background:var(--ok);box-shadow:0 0 6px var(--ok)}.bullet-off .bullet-dot{background:var(--border)}.bullet-on .bullet-label{color:var(--text)}.bullet-off .bullet-label{color:var(--muted)}.trigger-detail{margin:4px 0;font-size:12px;color:var(--muted)}.state-badge{display:inline-block;padding:2px 10px;font-size:12px;border-radius:10px;background:var(--bg);border:1px solid var(--border)}.state-idle,.state-none{color:var(--muted)}.state-compacting{color:var(--warn);border-color:var(--warn)}.persisted-tag{margin-left:8px;font-size:11px;color:var(--ok)}.events-tab{display:flex;flex-direction:column;gap:10px}.events-header{display:flex;align-items:center;gap:14px}.sse-status{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:var(--muted)}.sse-dot{width:8px;height:8px;border-radius:50%;background:var(--muted)}.sse-connected .sse-dot{background:var(--ok);box-shadow:0 0 6px var(--ok)}.sse-connecting .sse-dot{background:var(--warn)}.sse-disconnected .sse-dot,.sse-error .sse-dot{background:var(--err)}.event-count{color:var(--muted);font-size:12px}.event-filters{display:flex;flex-wrap:wrap;gap:6px;align-items:center;margin-bottom:8px}.filter-chip{padding:3px 10px;font-size:11px;border:1px solid var(--border);background:var(--bg);color:var(--muted);border-radius:12px;cursor:pointer}.filter-chip.active{color:var(--text);border-color:var(--accent);background:var(--panel)}.event-list{list-style:none;margin:0;padding:0;max-height:60vh;overflow-y:auto}.event-row{display:grid;grid-template-columns:70px 150px 1fr;gap:8px;padding:6px 10px;border-bottom:1px solid var(--border);font-size:12px;cursor:pointer}.event-row:hover{background:var(--panel)}.ev-time{color:var(--muted)}.ev-type{font-size:11px;padding:1px 6px;border-radius:8px;background:var(--bg);border:1px solid var(--border);color:var(--muted);text-align:center}.ev-compact .ev-type{color:var(--accent);border-color:var(--accent)}.ev-trigger .ev-type{color:var(--warn);border-color:var(--warn)}.ev-tier .ev-type{color:var(--muted)}.ev-checkpoint .ev-type{color:var(--ok);border-color:var(--ok)}.ev-recall .ev-type{color:#d2a8ff;border-color:#d2a8ff}.ev-config .ev-type{color:var(--text)}.ev-crew .ev-type{color:#79c0ff;border-color:#79c0ff}.ev-game .ev-type{color:var(--warn)}.ev-summary{color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ev-detail{grid-column:1 / -1;margin:6px 0 0;padding:8px;background:var(--bg);border-radius:4px;font-size:11px;color:var(--muted);white-space:pre-wrap}.event-empty{padding:24px;color:var(--muted);text-align:center}@media (max-width: 768px){.card-grid{grid-template-columns:1fr}.event-row{grid-template-columns:60px 110px 1fr;font-size:11px}}.summary-tiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:10px;margin-bottom:16px}.tile{display:flex;flex-direction:column;gap:4px;padding:12px 14px;background:var(--panel);border:1px solid var(--border);border-radius:8px}.tile-label{font-size:11px;color:var(--muted);text-transform:uppercase}.tile-value{font-size:20px;font-weight:600}.tile-highlight .tile-value{color:var(--ok)}.repo-table-wrap{overflow-x:auto}.repo-search{width:100%;padding:8px 10px;margin-bottom:10px;background:var(--panel);border:1px solid var(--border);border-radius:6px;color:var(--text);font-size:13px}.repo-table{width:100%;border-collapse:collapse;font-size:13px}.repo-table th{text-align:left;padding:6px 10px;border-bottom:1px solid var(--border)}.repo-table td{padding:8px 10px;border-bottom:1px solid var(--border)}.repo-table tr{cursor:pointer}.repo-table tbody tr:hover{background:var(--panel)}.sort-header{background:none;border:none;color:var(--muted);font-size:12px;font-weight:600;cursor:pointer;padding:0}.sort-header.active-asc,.sort-header.active-desc{color:var(--text)}.sort-arrow{color:var(--accent)}.repo-name{font-weight:600}.repo-model{color:var(--muted)}.modal-backdrop{position:fixed;inset:0;background:#0009;display:flex;align-items:center;justify-content:center;z-index:100}.modal-card{background:var(--panel);border:1px solid var(--border);border-radius:10px;padding:20px 24px;max-width:560px;width:90%;max-height:80vh;overflow-y:auto}.modal-header{display:flex;justify-content:space-between;align-items:center}.modal-header h2{margin:0;font-size:18px}.modal-close{background:none;border:none;color:var(--muted);font-size:22px;cursor:pointer;padding:0 4px}.modal-close:hover{color:var(--text)}.modal-path{font-size:11px;color:var(--muted);margin:4px 0 12px;word-break:break-all}.modal-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-bottom:16px}.modal-stat{display:flex;flex-direction:column;gap:2px}.modal-label{font-size:11px;color:var(--muted);text-transform:uppercase}.modal-value{font-size:16px;font-weight:600}.modal-highlight .modal-value{color:var(--ok)}.modal-card h3{font-size:13px;color:var(--muted);margin:16px 0 6px}.modal-dl{display:grid;grid-template-columns:130px 1fr;gap:4px 12px;margin:0}.modal-dl dt{color:var(--muted);font-size:12px}.modal-dl dd{margin:0;font-size:13px}.model-badge{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,160px),1fr));gap:8px;padding:12px 14px;background:var(--panel);border:1px solid var(--border);border-radius:8px;margin-bottom:12px}.model-field{display:flex;flex-direction:column;gap:2px}.model-field-label{font-size:11px;color:var(--muted);text-transform:uppercase}.model-field-value{font-size:14px;font-weight:600}.perf-chart{display:flex;flex-direction:column;gap:12px}.perf-header{display:flex;justify-content:space-between;align-items:center}.perf-header h3{margin:0;font-size:13px;color:var(--muted)}.perf-window{font-size:11px;color:var(--muted)}.perf-grid,.perf-resources{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:10px}.perf-resources{padding-top:10px;border-top:1px solid var(--border)}.perf-metric{display:flex;flex-direction:column;gap:4px;padding:10px 12px;background:var(--panel);border:1px solid var(--border);border-radius:6px}.perf-label{font-size:11px;color:var(--muted)}.perf-value{font-size:15px;font-weight:600}.perf-bar-track{height:6px;background:var(--bg);border-radius:3px;overflow:hidden}.perf-bar-fill{height:100%;transition:width .4s ease}.perf-blue .perf-bar-fill{background:var(--accent)}.perf-purple .perf-bar-fill{background:#d2a8ff}.perf-green .perf-bar-fill{background:var(--ok)}.perf-yellow .perf-bar-fill{background:var(--warn)}.perf-diag{display:flex;flex-wrap:wrap;gap:14px;padding-top:10px;border-top:1px solid var(--border)}@media (max-width: 768px){.modal-grid,.model-badge{grid-template-columns:1fr 1fr}}.section-header{font-size:13px;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);margin:20px 0 10px;font-weight:600}.table-scroll{overflow-x:auto;-webkit-overflow-scrolling:touch}.active-repos-table,.savings-table{width:100%;border-collapse:collapse;font-size:13px}.active-repos-table th,.savings-table th{text-align:left;padding:6px 10px;border-bottom:1px solid var(--border);white-space:nowrap}.active-repos-table th.num,.savings-table th.num{text-align:right}.active-repos-table td,.savings-table td{padding:6px 10px;border-bottom:1px solid var(--border);white-space:nowrap}.active-repos-table td.num,.savings-table td.num{text-align:right;font-family:monospace}.active-repos-table tbody tr:hover,.savings-table tbody tr:hover{background:var(--panel)}.savings-table .repo-model{font-weight:600}.repo-empty{text-align:center;color:var(--muted);padding:24px}.active-repos-section{margin-bottom:8px}.savings-by-model{margin-bottom:16px}@media (max-width: 640px){.active-repos-table{min-width:900px}.savings-table{min-width:1200px}}@media (min-width: 641px) and (max-width: 1024px){.savings-table{min-width:1000px}}.overview-card-grid{grid-template-columns:repeat(auto-fit,minmax(min(100%,320px),1fr))}.ov-stat-row{display:flex;justify-content:space-between;align-items:baseline;padding:4px 0;border-bottom:1px solid var(--border);font-size:clamp(13px,1vw,17px)}.ov-stat-label{color:var(--muted);font-size:12px;cursor:help}.ov-stat-value{font-weight:600;color:var(--text);font-family:monospace}.ov-stat-value-green{color:var(--ok)}.ov-stat-value-yellow{color:var(--warn)}.ov-stat-value-red{color:var(--err)}.ov-value-ok{color:var(--ok)!important}.ov-compression-meter{margin-top:10px}.meter-track{height:clamp(6px,.6vw,10px);background:var(--bg);border-radius:5px;overflow:hidden;border:1px solid var(--border)}.meter-fill{height:100%;transition:width .4s ease;border-radius:4px}.meter-green{background:var(--ok)}.meter-yellow{background:var(--warn)}.meter-red{background:var(--err)}.meter-sub{display:block;margin-top:4px;font-size:11px;color:var(--muted)}.bullet-na .bullet-dot{background:var(--warn);box-shadow:0 0 6px var(--warn)}.bullet-na .bullet-label{color:var(--warn)}.trigger-state-text{margin:6px 0 0;font-size:12px;color:var(--muted)}.data-safety-card .safe-note{margin:10px 0 0;padding:8px;font-size:11px;color:var(--muted);background:#3fb9500f;border-radius:6px;border:1px solid rgba(63,185,80,.2)}.model-cost-card .ov-cost-usd{font-size:clamp(16px,1.4vw,22px);font-weight:700;color:#a371f7;margin-bottom:2px}.model-cost-card .ov-cost-sub{font-size:12px;color:var(--muted);margin-bottom:8px}.crew-card .ov-stat-value{font-family:inherit}.legend-card{grid-column:1 / -1}.legend-card details{cursor:pointer}.legend-card summary{font-size:13px;color:var(--muted);font-weight:600;margin-bottom:4px}.legend-list{margin:8px 0;padding-left:20px;font-size:12px;color:var(--muted);line-height:1.6}.legend-list li{margin-bottom:4px}.legend-list b{color:var(--text)}.legend-note{font-size:11px;color:var(--dim);font-style:italic}.cache-tab{display:flex;flex-direction:column;gap:12px}@media (max-width: 640px){.overview-card-grid{grid-template-columns:1fr}}@media (min-width: 1025px){.overview-card-grid{grid-template-columns:repeat(3,1fr)}}@media (min-width: 1601px){.overview-card-grid{grid-template-columns:repeat(4,1fr);font-size:clamp(13px,.9vw,16px)}}.config-tab{display:flex;flex-direction:column;gap:16px}.config-settings,.config-display{padding:14px 16px;background:var(--panel);border:1px solid var(--border);border-radius:8px}.config-settings h3,.config-display h3{margin:0 0 12px;font-size:clamp(12px,1vw,14px);color:var(--muted);font-weight:600;text-transform:uppercase;letter-spacing:.5px}.settings-row{margin-bottom:10px}.settings-row:last-child{margin-bottom:0}.settings-row label{display:flex;align-items:center;gap:8px;font-size:clamp(13px,.9vw,15px);color:var(--text);cursor:pointer}.settings-row select{padding:4px 8px;font-size:clamp(12px,.85vw,14px);background:var(--bg);color:var(--text);border:1px solid var(--border);border-radius:4px;cursor:pointer}.settings-row select:disabled{opacity:.5;cursor:not-allowed}.settings-row input[type=checkbox]{width:16px;height:16px;cursor:pointer}.config-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,200px),1fr));gap:10px}.config-item{display:flex;flex-direction:column;gap:3px;padding:8px 10px;background:var(--bg);border:1px solid var(--border);border-radius:6px}.config-label{font-size:clamp(11px,.75vw,13px);color:var(--muted);text-transform:uppercase;letter-spacing:.4px}.config-value{font-size:clamp(13px,1vw,16px);font-weight:600;color:var(--text)}.event-category-filter{display:flex;flex-wrap:wrap;gap:6px;align-items:center}.category-chip{padding:3px 10px;font-size:clamp(11px,.75vw,13px);border:1px solid var(--border);background:var(--bg);color:var(--muted);border-radius:12px;cursor:pointer;text-transform:capitalize;transition:color .15s,border-color .15s,background .15s}.category-chip:hover{color:var(--text)}.category-chip.active{color:var(--text);border-color:var(--accent);background:var(--panel)}@media (max-width: 640px){.config-grid{grid-template-columns:1fr}.settings-row label{flex-direction:column;align-items:flex-start;gap:4px}.settings-row select{width:100%}}:root{--mega: #f0883e;--mega-gold: #ffd700;--game-blue: #1f6feb;--game-purple: #a371f7}.game-tab{display:flex;flex-direction:column;gap:12px}.game-mode-on{--accent: var(--mega)}.mega-cache-banner{display:block;background:linear-gradient(135deg,var(--mega),var(--mega-gold));color:#1a1006;font-weight:700;padding:10px 14px;border-radius:8px;margin:12px 0;font-size:clamp(13px,1vw,16px);animation:mega-banner-shimmer 3s ease-in-out infinite}@keyframes mega-banner-shimmer{0%,to{filter:brightness(1)}50%{filter:brightness(1.15)}}.mega-cache-toast{display:none;position:fixed;top:16px;left:50%;transform:translate(-50%);background:var(--mega);color:#1a1006;font-weight:700;padding:10px 18px;border-radius:8px;z-index:1000;box-shadow:0 4px 20px #0008;max-width:92vw}.mega-cache-toast.show{display:block;animation:mega-flash .6s ease-in-out 2}@keyframes mega-flash{0%{background:transparent}25%{background:var(--mega-gold)}to{background:transparent}}.achievement-tile{display:none;background:linear-gradient(135deg,var(--mega),var(--mega-gold));color:#1a1006;font-weight:700;padding:12px 16px;border-radius:8px;margin:12px 0;box-shadow:0 0 16px #f0883e88;font-size:clamp(13px,1vw,16px)}.achievement-tile.unlocked{display:block}.achievement-tile .ach-detail{display:block;font-weight:500;font-size:12px;margin-top:4px}.game-leaderboards{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-top:16px}.lb-card{background:var(--panel);border:1px solid var(--border);border-radius:8px;padding:14px}.lb-card h3{font-size:12px;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);margin:0 0 10px;font-weight:600;display:flex;align-items:center;gap:4px}.lb-card table{width:100%;border-collapse:collapse;font-size:13px}.lb-card td{padding:4px 8px;border-bottom:1px solid var(--border)}.lb-card td.num{text-align:right;font-family:monospace;color:var(--text);font-weight:600}.lb-card .lb-meta{color:var(--muted);font-size:11px;margin-left:6px}.lb-empty{color:var(--muted);font-size:12px;padding:8px 0}.lvl-badge{display:inline-block;background:var(--game-blue);color:#fff;font-size:11px;font-weight:700;padding:2px 8px;border-radius:10px;margin-left:8px}.repos-badge-line{margin-top:8px}.repos-badge{display:inline-block;background:var(--game-blue);color:#fff;font-size:11px;font-weight:700;padding:2px 8px;border-radius:10px}.game-empty{color:var(--muted);font-style:italic;padding:12px 0}.ach-section{position:relative}.ach-tiles{display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:8px;margin:8px 0 16px}.ach-tile{padding:10px 12px;border-radius:8px;border:1px solid var(--border);font-size:12px;background:var(--panel)}.ach-tile.unlocked{background:linear-gradient(135deg,var(--mega),var(--mega-gold));color:#1a1006;font-weight:700;box-shadow:0 0 12px #f0883e66}.ach-tile.locked{opacity:.55}.ach-tile.just-unlocked{animation:ach-unlock-pulse .6s ease-out}.ach-tile .ach-detail{display:block;font-weight:500;font-size:11px;margin-top:3px}@keyframes ach-unlock-pulse{0%{transform:scale(.9);opacity:.4}60%{transform:scale(1.05)}to{transform:scale(1);opacity:1}}.ach-toast{display:none;position:fixed;top:16px;left:50%;transform:translate(-50%);background:var(--game-blue);color:#fff;font-weight:700;padding:10px 18px;border-radius:8px;z-index:1000;box-shadow:0 4px 20px #0008;max-width:92vw}.ach-toast.show{display:block}.achievements-tab{display:flex;flex-direction:column;gap:12px}.achievements-tab h2{font-size:clamp(16px,1.4vw,22px);margin:0}@media (max-width: 640px){.game-leaderboards{grid-template-columns:1fr}}@media (min-width: 1601px){.game-leaderboards{gap:20px}}.sessions-tab{display:flex;flex-direction:column;gap:14px}.sessions-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:8px;padding:8px 0}.sessions-toolbar h2{margin:0;font-size:14px;font-weight:600;color:var(--text)}.sessions-window-select{display:inline-flex;gap:2px;padding:2px;background:var(--panel);border:1px solid var(--border);border-radius:6px}.sessions-window-btn{padding:4px 10px;background:transparent;border:none;border-radius:4px;color:var(--muted);font-size:12px;cursor:pointer;transition:background .15s,color .15s}.sessions-window-btn:hover{color:var(--text)}.sessions-window-btn.active{background:var(--accent);color:#0d1117;font-weight:600}.sessions-summary-tiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:10px}.sessions-chart{background:var(--panel);border:1px solid var(--border);border-radius:8px;padding:12px}.sessions-chart-empty,.sessions-empty{display:flex;align-items:center;justify-content:center;min-height:160px;color:var(--muted);font-size:14px;background:var(--panel);border:1px solid var(--border);border-radius:8px;padding:32px;text-align:center}.sessions-table-scroll{overflow-x:auto;background:var(--panel);border:1px solid var(--border);border-radius:8px}.sessions-table{width:100%;border-collapse:collapse;font-size:13px}.sessions-table th,.sessions-table td{padding:8px 10px;text-align:left;border-bottom:1px solid var(--border);white-space:nowrap}.sessions-table th{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);background:#ffffff05;position:sticky;top:0}.sessions-table td.num{text-align:right;font-variant-numeric:tabular-nums}.sessions-table tr:last-child td{border-bottom:none}.sessions-table tr:hover td{background:#58a6ff0f}.sessions-empty-row td{color:var(--muted);font-style:italic;text-align:center}.sessions-pct-pill{display:inline-block;padding:2px 8px;border-radius:10px;font-size:11px;font-weight:600;font-variant-numeric:tabular-nums}.sessions-pct-ok{background:#3fb95026;color:var(--ok)}.sessions-pct-warn{background:#d2992226;color:var(--warn)}.sessions-pct-err{background:#f8514926;color:var(--err)}.sessions-sparkline{display:inline-block;vertical-align:middle}.sessions-sparkline-empty{color:var(--muted);font-size:11px}.sessions-meta{font-size:11px;color:var(--muted)}.sessions-footer{font-size:11px;color:var(--muted);margin-top:6px}@media (max-width: 640px){.sessions-summary-tiles{grid-template-columns:1fr}.sessions-table th,.sessions-table td{font-size:12px;padding:6px 8px}}.repo-stack-card{display:flex;flex-direction:column;gap:10px}.repo-stack-card h3{margin:0;font-size:14px;font-weight:600;color:var(--text)}.repo-stack-bar{display:flex;width:100%;height:22px;border-radius:6px;overflow:hidden;border:1px solid var(--border);background:var(--bg)}.repo-stack-segment{height:100%;min-width:2px;transition:opacity .15s,filter .15s}.repo-stack-segment:hover{opacity:.85;filter:brightness(1.15)}.repo-stack-total{font-size:13px;color:var(--text);font-variant-numeric:tabular-nums}.repo-stack-total .pct{color:var(--muted)}.repo-stack-legend{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:6px}.repo-stack-legend-item{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--muted);font-variant-numeric:tabular-nums}.repo-stack-legend-swatch{flex-shrink:0;width:12px;height:12px;border-radius:3px;border:1px solid var(--border)}.repo-stack-legend-name{color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}@media (max-width: 640px){.repo-stack-legend{grid-template-columns:1fr}}.session-gauges-card{grid-column:1 / -1}.session-gauges-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:14px}.session-gauge{display:flex;flex-direction:column;gap:6px;padding:10px 12px;background:var(--bg);border:1px solid var(--border);border-radius:6px}.session-gauge-self{border-color:var(--accent);box-shadow:0 0 0 1px var(--accent);background:color-mix(in srgb,var(--accent) 8%,var(--bg))}.session-gauge-head{display:flex;justify-content:space-between;align-items:baseline;gap:6px}.session-gauge-label{font-size:12px;font-weight:600;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:70%}.session-gauge-self .session-gauge-label{color:var(--accent)}.session-gauge-pct{font-size:12px;font-weight:600;color:var(--muted);white-space:nowrap}.session-gauges-grid .gauge-bar{height:8px}.session-gauge-sub{margin:0}.session-gauge-meta{margin:0;font-size:11px;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}@media (max-width: 640px){.session-gauges-grid{grid-template-columns:1fr}}.maintenance-tab{display:flex;flex-direction:column;gap:12px}.card-header{font-size:13px;font-weight:600;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);margin-bottom:10px;display:flex;align-items:center;gap:8px}.card-body{font-size:13px}.stat-section{margin-bottom:12px}.stat-section:last-child{margin-bottom:0}.stat-label{font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:.4px;margin-bottom:4px}.stat-row{display:flex;justify-content:space-between;align-items:baseline;padding:3px 0;border-bottom:1px solid var(--border);font-size:13px}.num{text-align:right;font-family:monospace;font-weight:600}.compact-table{width:100%;border-collapse:collapse;font-size:13px}.compact-table th{text-align:left;padding:4px 6px;border-bottom:1px solid var(--border);font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.4px;color:var(--muted)}.compact-table th.num{text-align:right}.compact-table td{padding:3px 6px;border-bottom:1px solid var(--border)}.compact-table td.num{text-align:right;font-family:monospace;font-weight:600}.compact-table tbody tr:last-child td{border-bottom:none}.text-muted{color:var(--muted)}.text-error{color:var(--err)}.text-ok{color:var(--ok)}.text-warn{color:var(--warn)}.text-mono{font-family:monospace;font-size:12px}.badge{display:inline-block;padding:1px 8px;font-size:10px;font-weight:700;border-radius:8px;text-transform:uppercase;letter-spacing:.3px}.badge-ok{background:color-mix(in srgb,var(--ok) 20%,transparent);color:var(--ok);border:1px solid var(--ok)}.badge-bad{background:color-mix(in srgb,var(--err) 20%,transparent);color:var(--err);border:1px solid var(--err)}.badge-warn{background:color-mix(in srgb,var(--warn) 20%,transparent);color:var(--warn);border:1px solid var(--warn)}.action-grid{display:grid;grid-template-columns:1fr;gap:8px}.action-item{display:flex;justify-content:space-between;align-items:center;gap:12px;padding:10px 12px;background:var(--bg);border:1px solid var(--border);border-radius:6px}.action-info{display:flex;flex-direction:column;gap:2px;flex:1;min-width:0}.action-label{font-size:13px;font-weight:600;color:var(--text);display:flex;align-items:center;gap:6px}.action-desc{font-size:11px;color:var(--muted)}.action-result{font-size:11px;margin-top:2px}.action-controls{display:flex;align-items:center;gap:8px;flex-shrink:0}.btn{padding:5px 14px;font-size:12px;font-weight:600;border:none;border-radius:6px;cursor:pointer;white-space:nowrap;transition:opacity .15s}.btn:disabled{opacity:.5;cursor:not-allowed}.btn-primary{background:var(--accent);color:#0d1117}.btn-danger{background:var(--err);color:#fff}.days-input{width:60px;padding:4px 6px;font-size:12px;background:var(--panel);border:1px solid var(--border);border-radius:4px;color:var(--text);text-align:center}.days-input:disabled{opacity:.5}@media (max-width: 640px){.action-item{flex-direction:column;align-items:stretch;gap:8px}.action-controls{justify-content:flex-end}}.ov-stripe-health-summary{display:flex;gap:12px;align-items:center;margin-bottom:12px;font-size:clamp(11px,.85vw,14px);flex-wrap:wrap}.ov-stripe-health-badge{display:inline-block;padding:2px 10px;border-radius:10px;background:var(--panel);border:1px solid var(--border);font-weight:600;text-transform:capitalize}.ov-text-green{color:var(--ok)}.ov-text-yellow{color:var(--warn)}.ov-text-orange{color:#d4761e}.ov-text-red{color:var(--err)}.ov-text-gray,.ov-stripe-health-score,.ov-stripe-churn,.ov-stripe-total{color:var(--muted)}.ov-stripe-bars{display:flex;flex-direction:column;gap:6px}.ov-stripe-row{display:grid;grid-template-columns:80px 1fr 40px 48px;align-items:center;gap:8px;font-size:clamp(11px,.8vw,13px)}.ov-stripe-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--text)}.ov-bar-track{height:18px;background:var(--bg);border-radius:4px;overflow:hidden;position:relative}.ov-bar-fill{height:100%;border-radius:4px;transition:width .5s ease;min-width:2px}.ov-bar-green{background:var(--ok)}.ov-bar-blue{background:var(--accent)}.ov-bar-teal{background:#3d9cb0}.ov-bar-yellow{background:var(--warn)}.ov-bar-gray{background:var(--muted)}.ov-bar-red{background:var(--err)}.ov-bar-orange{background:#d4761e}.ov-bar-latest{box-shadow:0 0 6px #ffffff80}.ov-stripe-count{text-align:right;color:var(--text);font-variant-numeric:tabular-nums}.ov-stripe-stability{color:var(--muted);font-size:clamp(10px,.75vw,12px)}.ov-stripe-footer{margin-top:10px;font-size:clamp(10px,.75vw,12px);color:var(--muted);display:flex;gap:8px}.ov-perf-summary{display:flex;gap:14px;align-items:center;margin-bottom:10px;font-size:clamp(11px,.85vw,14px);flex-wrap:wrap}.ov-perf-stat strong{font-variant-numeric:tabular-nums}.ov-sparkline{display:flex;align-items:flex-end;gap:3px;height:60px;padding:4px 2px;margin-bottom:6px}.ov-sparkline-bar{flex:1;min-width:4px;border-radius:2px 2px 0 0;transition:height .4s ease}.ov-empty-state{font-size:clamp(11px,.8vw,13px);color:var(--muted);padding:16px 0;text-align:center}.ov-card-footer{font-size:clamp(10px,.75vw,12px);color:var(--muted);margin-top:4px}.ov-card{background:var(--panel);border:1px solid var(--border);border-radius:8px;padding:clamp(8px,1.5vw,16px)}.ov-card-title{margin:0 0 10px;font-size:clamp(13px,.9vw,15px);font-weight:600}
|