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.
Files changed (86) hide show
  1. package/README.md +13 -6
  2. package/dist/extensions/dashboard-server/api-contracts/endpoints/registry.js +6 -0
  3. package/dist/extensions/dashboard-server/index-reader.js +49 -26
  4. package/dist/extensions/dashboard-server/routes-cache.js +17 -5
  5. package/dist/extensions/dashboard-server/routes-rag-settings-helpers.js +7 -0
  6. package/dist/extensions/dashboard-server/routes-raptor.js +60 -0
  7. package/dist/extensions/dashboard-server/routes.js +1 -1
  8. package/dist/extensions/dashboard-server/server.js +3 -1
  9. package/dist/extensions/mega-pipeline/recall.js +24 -16
  10. package/dist/extensions/mega-runtime/capture-model.js +15 -2
  11. package/dist/extensions/mega-runtime/runtime-snapshot.js +26 -0
  12. package/dist/extensions/mega-runtime/runtime.js +1 -0
  13. package/dist/src/config/dedup.js +2 -1
  14. package/dist/src/costApi.js +113 -0
  15. package/dist/src/dedup/raptor/incremental.js +31 -3
  16. package/dist/src/dedup/raptor/index.js +10 -6
  17. package/dist/src/vector-search.js +3 -3
  18. package/extensions/dashboard-client/dist/assets/{AreaChart-j2VOSRp6.js → AreaChart-BUUketyS.js} +2 -2
  19. package/extensions/dashboard-client/dist/assets/{AreaChart-j2VOSRp6.js.map → AreaChart-BUUketyS.js.map} +1 -1
  20. package/extensions/dashboard-client/dist/assets/{CacheTab-Dr1HeMfc.js → CacheTab-VNFZSdRr.js} +2 -2
  21. package/extensions/dashboard-client/dist/assets/{CacheTab-Dr1HeMfc.js.map → CacheTab-VNFZSdRr.js.map} +1 -1
  22. package/extensions/dashboard-client/dist/assets/{EventsTab-DRG2k7FS.js → EventsTab-Dr7RDBy2.js} +2 -2
  23. package/extensions/dashboard-client/dist/assets/{EventsTab-DRG2k7FS.js.map → EventsTab-Dr7RDBy2.js.map} +1 -1
  24. package/extensions/dashboard-client/dist/assets/{HealthTab-DGE9PpW3.js → HealthTab-B8VZ8gbb.js} +2 -2
  25. package/extensions/dashboard-client/dist/assets/{HealthTab-DGE9PpW3.js.map → HealthTab-B8VZ8gbb.js.map} +1 -1
  26. package/extensions/dashboard-client/dist/assets/{MaintenanceTab-DeYRhF4q.js → MaintenanceTab-DMtrXRcn.js} +2 -2
  27. package/extensions/dashboard-client/dist/assets/{MaintenanceTab-DeYRhF4q.js.map → MaintenanceTab-DMtrXRcn.js.map} +1 -1
  28. package/extensions/dashboard-client/dist/assets/MemoryMapTab-PFrMdLOm.js +2 -0
  29. package/extensions/dashboard-client/dist/assets/{MemoryMapTab-DSnSO3nG.js.map → MemoryMapTab-PFrMdLOm.js.map} +1 -1
  30. package/extensions/dashboard-client/dist/assets/{MetricsTab-RIzNc1Uj.js → MetricsTab-Dd1kXuvg.js} +2 -2
  31. package/extensions/dashboard-client/dist/assets/{MetricsTab-RIzNc1Uj.js.map → MetricsTab-Dd1kXuvg.js.map} +1 -1
  32. package/extensions/dashboard-client/dist/assets/{OverviewTab-_1BJ4Bmh.js → OverviewTab-DOpObVA9.js} +2 -2
  33. package/extensions/dashboard-client/dist/assets/{OverviewTab-_1BJ4Bmh.js.map → OverviewTab-DOpObVA9.js.map} +1 -1
  34. package/extensions/dashboard-client/dist/assets/{ReposTab-DkU7ywZB.js → ReposTab-D6pEUtEJ.js} +2 -2
  35. package/extensions/dashboard-client/dist/assets/{ReposTab-DkU7ywZB.js.map → ReposTab-D6pEUtEJ.js.map} +1 -1
  36. package/extensions/dashboard-client/dist/assets/{SessionsTab-Bq_F_aOk.js → SessionsTab-CcFzDJ7W.js} +2 -2
  37. package/extensions/dashboard-client/dist/assets/{SessionsTab-Bq_F_aOk.js.map → SessionsTab-CcFzDJ7W.js.map} +1 -1
  38. package/extensions/dashboard-client/dist/assets/{SetupTab-BkBD2Y97.js → SetupTab-YCt5NGB5.js} +2 -2
  39. package/extensions/dashboard-client/dist/assets/{SetupTab-BkBD2Y97.js.map → SetupTab-YCt5NGB5.js.map} +1 -1
  40. package/extensions/dashboard-client/dist/assets/{TimeSavedCard-BXzFKU7C.js → TimeSavedCard-BsLNhOOj.js} +2 -2
  41. package/extensions/dashboard-client/dist/assets/{TimeSavedCard-BXzFKU7C.js.map → TimeSavedCard-BsLNhOOj.js.map} +1 -1
  42. package/extensions/dashboard-client/dist/assets/{TurnsTab-Bjpp3vBH.js → TurnsTab-C1jpVZrH.js} +2 -2
  43. package/extensions/dashboard-client/dist/assets/{TurnsTab-Bjpp3vBH.js.map → TurnsTab-C1jpVZrH.js.map} +1 -1
  44. package/extensions/dashboard-client/dist/assets/{WikiTab-dBN2EA5G.js → WikiTab-RHoVt95g.js} +2 -2
  45. package/extensions/dashboard-client/dist/assets/{WikiTab-dBN2EA5G.js.map → WikiTab-RHoVt95g.js.map} +1 -1
  46. package/extensions/dashboard-client/dist/assets/{button-Bt0b5QVp.js → button-DSZI4aZ5.js} +2 -2
  47. package/extensions/dashboard-client/dist/assets/{button-Bt0b5QVp.js.map → button-DSZI4aZ5.js.map} +1 -1
  48. package/extensions/dashboard-client/dist/assets/{card-D5CafXtg.js → card-CsZzIyPW.js} +2 -2
  49. package/extensions/dashboard-client/dist/assets/{card-D5CafXtg.js.map → card-CsZzIyPW.js.map} +1 -1
  50. package/extensions/dashboard-client/dist/assets/{index-GPHRnEN7.js → index-B1_J_Y0b.js} +11 -11
  51. package/extensions/dashboard-client/dist/assets/index-B1_J_Y0b.js.map +1 -0
  52. package/extensions/dashboard-client/dist/assets/index-C5TGTOd6.css +1 -0
  53. package/extensions/dashboard-client/dist/assets/{switch-CY5Gwj1o.js → switch-DOIA1Nxu.js} +2 -2
  54. package/extensions/dashboard-client/dist/assets/{switch-CY5Gwj1o.js.map → switch-DOIA1Nxu.js.map} +1 -1
  55. package/extensions/dashboard-client/dist/assets/{toggle-C9HpkIfH.js → toggle-CyS6PHCO.js} +2 -2
  56. package/extensions/dashboard-client/dist/assets/{toggle-C9HpkIfH.js.map → toggle-CyS6PHCO.js.map} +1 -1
  57. package/extensions/dashboard-client/dist/assets/{useSSE-2JFrLDlE.js → useSSE-CY7UIUzm.js} +2 -2
  58. package/extensions/dashboard-client/dist/assets/{useSSE-2JFrLDlE.js.map → useSSE-CY7UIUzm.js.map} +1 -1
  59. package/extensions/dashboard-client/dist/index.html +2 -2
  60. package/extensions/dashboard-client/src/api/client.ts +10 -0
  61. package/extensions/dashboard-client/src/components/layout/AppShell.tsx +1 -1
  62. package/extensions/dashboard-client/src/styles/base.css +2 -4
  63. package/extensions/dashboard-client/src/tabs/MemoryMapTab/RaptorTreeView.tsx +58 -4
  64. package/extensions/dashboard-client/tailwind.config.js +1 -1
  65. package/extensions/dashboard-server/api-contracts/endpoints/registry.ts +9 -1
  66. package/extensions/dashboard-server/api-contracts/index.ts +2 -2
  67. package/extensions/dashboard-server/api-contracts/raptor.ts +19 -0
  68. package/extensions/dashboard-server/index-reader.ts +28 -5
  69. package/extensions/dashboard-server/routes-cache.ts +17 -5
  70. package/extensions/dashboard-server/routes-rag-settings-helpers.ts +17 -0
  71. package/extensions/dashboard-server/routes-raptor.ts +88 -1
  72. package/extensions/dashboard-server/routes.ts +1 -1
  73. package/extensions/dashboard-server/server.ts +2 -0
  74. package/extensions/mega-pipeline/recall.ts +30 -21
  75. package/extensions/mega-runtime/capture-model.ts +14 -2
  76. package/extensions/mega-runtime/runtime-snapshot.ts +40 -0
  77. package/extensions/mega-runtime/runtime.ts +1 -0
  78. package/package.json +1 -1
  79. package/src/config/dedup.ts +2 -1
  80. package/src/costApi.ts +131 -0
  81. package/src/dedup/raptor/incremental.ts +48 -3
  82. package/src/dedup/raptor/index.ts +10 -6
  83. package/src/vector-search.ts +3 -3
  84. package/extensions/dashboard-client/dist/assets/MemoryMapTab-DSnSO3nG.js +0 -2
  85. package/extensions/dashboard-client/dist/assets/index-CUA6EDRF.css +0 -1
  86. 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 = summarizeCluster(messages);
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 = summarizeCluster(messages);
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
- * Shadow mode (RAPTOR_SHADOW_MODE default true): the tree is BUILT and PERSISTED
6
- * to raptor_nodes + logged, but is NOT used to serve retrieval. The live
7
- * vectorStore.search path is untouched until Sprint 14 promotes RAPTOR.
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
- /** Shadow mode is on by default; set RAPTOR_SHADOW_MODE=false to serve live. */
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 !== "false";
29
+ return process.env.RAPTOR_SHADOW_MODE === "true";
26
30
  }
27
31
 
28
32
  export interface RaptorOrchestratorOptions {
@@ -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 the shadow contract at SERVE time. The tree is still
68
- // built + persisted (logging-only) but NOT merged into recall while
69
- // RAPTOR_SHADOW_MODE is anything other than "false".
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}