@andespindola/brainlink 0.1.0-beta.163 → 0.1.0-beta.165
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 +14 -4
- package/dist/application/build-context.js +105 -11
- package/dist/application/frontend/client-css.js +37 -31
- package/dist/application/frontend/client-js.js +103 -37
- package/dist/application/server/routes.js +17 -3
- package/dist/cli/commands/read-commands.js +39 -3
- package/dist/cli/commands/write-commands.js +4 -2
- package/dist/infrastructure/config.js +11 -2
- package/dist/infrastructure/context-packs.js +122 -0
- package/dist/mcp/server.js +8 -3
- package/dist/mcp/tools.js +82 -7
- package/docs/AGENT_USAGE.md +8 -1
- package/docs/ARCHITECTURE.md +6 -0
- package/docs/QUICKSTART.md +2 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -71,6 +71,7 @@ Legacy `.jsonl.gz` packs are upgraded to `.blpk` automatically on first search/c
|
|
|
71
71
|
- Full-text, semantic and hybrid retrieval on a local file index.
|
|
72
72
|
- Middle-out context assembly around the strongest chunk per document.
|
|
73
73
|
- In-process index and context caching with automatic invalidation on index updates.
|
|
74
|
+
- Optional CAG context packs at `.brainlink/context-packs/*.json`, derived from the current index signature and reusable across repeated context calls.
|
|
74
75
|
- HTTP graph server caches generated frontend assets and graph-layout JSON payloads by signature, and skips layout serialization when ETag returns `304`.
|
|
75
76
|
- Compressed-space prefiltering for `.blpk` packs before decryption and scan.
|
|
76
77
|
- Incremental indexing that reprocesses only changed markdown files and reuses existing chunks/embeddings for unchanged notes.
|
|
@@ -529,8 +530,9 @@ Available tools:
|
|
|
529
530
|
|
|
530
531
|
- `brainlink_bootstrap`: plug-and-play entrypoint that runs index + health checks and can return context in one call.
|
|
531
532
|
- `brainlink_policy`: read or update bootstrap/context-first policy, including presets (`preset: "fully-auto" | "strict"`).
|
|
532
|
-
- `brainlink_recommendations`: return an automatic action plan so agents can run Brainlink in the recommended order.
|
|
533
|
-
- `brainlink_context`: read indexed context for a task or question.
|
|
533
|
+
- `brainlink_recommendations`: return an automatic action plan so agents can run Brainlink in the recommended order, including RAG/CAG context strategy guidance.
|
|
534
|
+
- `brainlink_context`: read indexed context for a task or question; pass `strategy: "rag"` for fresh retrieval assembly, `strategy: "cag"` for persisted context packs or `strategy: "auto"` for CAG hits with RAG fallback.
|
|
535
|
+
- `brainlink_context_packs`: list or clear persisted CAG context packs.
|
|
534
536
|
- `brainlink_search`: search indexed notes.
|
|
535
537
|
- `brainlink_dedupe`: detect duplicate candidates using exact hash + semantic similarity scores.
|
|
536
538
|
- `brainlink_resolve_duplicate`: resolve duplicate pairs (`merge`, `link`, `ignore`) with connectivity-safe fallback edges.
|
|
@@ -555,6 +557,7 @@ By default, Brainlink enforces bootstrap and auto-runs it for read tools when se
|
|
|
555
557
|
If you disable `autoBootstrapOnRead` through `brainlink_policy`, read tools return a preflight instruction with suggested `brainlink_bootstrap` arguments.
|
|
556
558
|
`brainlink_bootstrap`, `brainlink_policy` and preflight responses include structured `nextActions` so MCP clients can continue automatically without custom parsing.
|
|
557
559
|
For one-call planning, use `brainlink_recommendations` to get the recommended tool sequence for the current vault/agent/query.
|
|
560
|
+
The MCP context tools are plug-and-play by default: omit `strategy` to use the configured default (`rag` unless changed), pass `strategy: "cag"` for repeated/stable task context, or pass `strategy: "auto"` so Brainlink chooses CAG on fresh pack hits and RAG otherwise. `brainlink_recommendations`, preflight responses and policy next actions include executable context arguments so clients can continue without custom parsing.
|
|
558
561
|
|
|
559
562
|
The same linking rule applies through MCP: `brainlink_context` is read-only, and real graph links require Markdown notes with explicit `## Context Links` sections. `brainlink_add_note` and `brainlink_add_file` reindex by default and include index + `writeConnectivity` metadata. Brainlink does not auto-link new notes to fallback hubs.
|
|
560
563
|
|
|
@@ -864,10 +867,15 @@ Context selection uses a middle-out strategy: it starts from the strongest chunk
|
|
|
864
867
|
blink context "question" --vault ./vault --limit 12 --tokens 2000
|
|
865
868
|
blink context "question" --vault ./vault --agent coding-agent --json
|
|
866
869
|
blink context "question" --vault ./vault --agent coding-agent --mode hybrid --json
|
|
870
|
+
blink context "question" --vault ./vault --agent coding-agent --strategy cag --json
|
|
871
|
+
blink context "question" --vault ./vault --agent coding-agent --strategy auto --json
|
|
872
|
+
blink context-packs --vault ./vault --json
|
|
873
|
+
blink context-packs --vault ./vault --stale --clear
|
|
867
874
|
```
|
|
868
875
|
|
|
869
876
|
Builds a compact context package for an agent.
|
|
870
877
|
Repeated calls with the same vault, agent, query, mode and token/limit settings are served from a short in-memory cache while the index is unchanged.
|
|
878
|
+
The default strategy is configured by `defaultContextStrategy` and starts as `rag`, which retrieves and assembles context from the current index. `--strategy cag` enables cache-augmented context generation by reading or refreshing a persisted context pack under `.brainlink/context-packs`; `--strategy auto` uses CAG when a fresh pack exists and RAG otherwise, refreshing a pack for future calls. Context responses include `cache`, `metrics`, `requestedStrategy` and `recommendedStrategy` metadata. Packs are derived artifacts and become stale when the index or volatile memory signature changes.
|
|
871
879
|
|
|
872
880
|
### `links`
|
|
873
881
|
|
|
@@ -1010,6 +1018,7 @@ If no `vault` is configured and no `--vault` flag is passed, Brainlink uses `$HO
|
|
|
1010
1018
|
"autoCanonicalContextLinks": true,
|
|
1011
1019
|
"defaultSearchLimit": 10,
|
|
1012
1020
|
"defaultContextTokens": 2000,
|
|
1021
|
+
"defaultContextStrategy": "rag",
|
|
1013
1022
|
"embeddingProvider": "local",
|
|
1014
1023
|
"defaultSearchMode": "hybrid",
|
|
1015
1024
|
"chunkSize": 1200,
|
|
@@ -1024,7 +1033,8 @@ If no `vault` is configured and no `--vault` flag is passed, Brainlink uses `$HO
|
|
|
1024
1033
|
"coding-agent": {
|
|
1025
1034
|
"defaultSearchMode": "semantic",
|
|
1026
1035
|
"defaultSearchLimit": 8,
|
|
1027
|
-
"defaultContextTokens": 2400
|
|
1036
|
+
"defaultContextTokens": 2400,
|
|
1037
|
+
"defaultContextStrategy": "auto"
|
|
1028
1038
|
},
|
|
1029
1039
|
"*": {
|
|
1030
1040
|
"defaultSearchMode": "hybrid"
|
|
@@ -1034,7 +1044,7 @@ If no `vault` is configured and no `--vault` flag is passed, Brainlink uses `$HO
|
|
|
1034
1044
|
```
|
|
1035
1045
|
|
|
1036
1046
|
`defaultAgent` is optional. When set, CLI and MCP calls that omit `--agent`/`agent` use this value automatically. If not set, behavior remains as before.
|
|
1037
|
-
`agentProfiles` is optional. When present, CLI and MCP resolve `mode`, `limit` and `
|
|
1047
|
+
`agentProfiles` is optional. When present, CLI and MCP resolve `mode`, `limit`, `tokens` and context `strategy` per agent automatically, then fallback to global defaults.
|
|
1038
1048
|
|
|
1039
1049
|
`autoIndexOnWrite` is optional and defaults to `true`. Set it to `false` to defer indexing after writes.
|
|
1040
1050
|
`autoCanonicalContextLinks` is optional and defaults to `true`. When enabled, `blink add`, `brainlink_add_note` and `brainlink_add_file` add a canonical `## Context Links` entry to the inferred context hub, creating that hub when needed.
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { stat } from 'node:fs/promises';
|
|
2
|
+
import { performance } from 'node:perf_hooks';
|
|
2
3
|
import { formatContextPackage, selectContextSections } from '../domain/context.js';
|
|
4
|
+
import { readContextPack, writeContextPack } from '../infrastructure/context-packs.js';
|
|
3
5
|
import { indexStoragePath } from '../infrastructure/file-index.js';
|
|
4
6
|
import { searchVolatileMemory, volatileMemoryStoragePath } from '../infrastructure/volatile-memory.js';
|
|
5
7
|
import { searchKnowledge } from './search-knowledge.js';
|
|
@@ -15,14 +17,19 @@ const readFileSignature = async (path) => {
|
|
|
15
17
|
return '0:0';
|
|
16
18
|
}
|
|
17
19
|
};
|
|
18
|
-
const readContextDataSignature = async (vaultPath) => `${await readFileSignature(indexStoragePath(vaultPath))}|${await readFileSignature(volatileMemoryStoragePath(vaultPath))}`;
|
|
19
|
-
const toCacheKey = (vaultPath, query, limit, maxTokens, agentId, mode) => JSON.stringify({
|
|
20
|
+
export const readContextDataSignature = async (vaultPath) => `${await readFileSignature(indexStoragePath(vaultPath))}|${await readFileSignature(volatileMemoryStoragePath(vaultPath))}`;
|
|
21
|
+
const toCacheKey = (vaultPath, query, limit, maxTokens, agentId, mode, strategy) => JSON.stringify({
|
|
20
22
|
vaultPath,
|
|
21
23
|
query: query.trim().toLowerCase(),
|
|
22
24
|
limit,
|
|
23
25
|
maxTokens,
|
|
24
26
|
agentId: agentId?.trim().toLowerCase() ?? '*',
|
|
25
|
-
mode: mode ?? 'default'
|
|
27
|
+
mode: mode ?? 'default',
|
|
28
|
+
strategy
|
|
29
|
+
});
|
|
30
|
+
const withCacheMetadata = (context, cache) => ({
|
|
31
|
+
...context,
|
|
32
|
+
cache
|
|
26
33
|
});
|
|
27
34
|
const contextCacheGet = (key, dataSignature) => {
|
|
28
35
|
const entry = contextCache.get(key);
|
|
@@ -34,7 +41,11 @@ const contextCacheGet = (key, dataSignature) => {
|
|
|
34
41
|
contextCache.delete(key);
|
|
35
42
|
return undefined;
|
|
36
43
|
}
|
|
37
|
-
return entry.context
|
|
44
|
+
return withCacheMetadata(entry.context, {
|
|
45
|
+
storage: 'memory',
|
|
46
|
+
status: 'hit',
|
|
47
|
+
dataSignature
|
|
48
|
+
});
|
|
38
49
|
};
|
|
39
50
|
const contextCacheSet = (entry) => {
|
|
40
51
|
contextCache.set(entry.key, entry);
|
|
@@ -45,32 +56,115 @@ const contextCacheSet = (entry) => {
|
|
|
45
56
|
const keys = Array.from(contextCache.keys()).slice(0, overflow);
|
|
46
57
|
keys.forEach((key) => contextCache.delete(key));
|
|
47
58
|
};
|
|
48
|
-
|
|
49
|
-
|
|
59
|
+
const elapsedMs = (start) => Math.round((performance.now() - start) * 1000) / 1000;
|
|
60
|
+
const estimateSectionTokens = (context) => Math.ceil(context.content.length / 4);
|
|
61
|
+
const emptyMetrics = (context, totalMs, overrides = {}) => ({
|
|
62
|
+
totalMs,
|
|
63
|
+
packReadMs: 0,
|
|
64
|
+
searchMs: 0,
|
|
65
|
+
selectionMs: 0,
|
|
66
|
+
volatileMs: 0,
|
|
67
|
+
packWriteMs: 0,
|
|
68
|
+
sectionCount: context.sections.length,
|
|
69
|
+
volatileSectionCount: context.volatileSections?.length ?? 0,
|
|
70
|
+
estimatedTokens: estimateSectionTokens(context),
|
|
71
|
+
...overrides
|
|
72
|
+
});
|
|
73
|
+
export const buildContextPackage = async (vaultPath, query, limit, maxTokens, agentId, mode, strategy = 'rag') => {
|
|
74
|
+
const totalStart = performance.now();
|
|
75
|
+
const cacheKey = toCacheKey(vaultPath, query, limit, maxTokens, agentId, mode, strategy);
|
|
50
76
|
const dataSignature = await readContextDataSignature(vaultPath);
|
|
51
77
|
const cached = contextCacheGet(cacheKey, dataSignature);
|
|
52
78
|
if (cached) {
|
|
53
79
|
return cached;
|
|
54
80
|
}
|
|
81
|
+
const shouldUseContextPack = strategy === 'cag' || strategy === 'auto';
|
|
82
|
+
let packReadMs = 0;
|
|
83
|
+
if (shouldUseContextPack) {
|
|
84
|
+
const packReadStart = performance.now();
|
|
85
|
+
const pack = await readContextPack(vaultPath, { query, limit, maxTokens, agentId, mode }, dataSignature);
|
|
86
|
+
packReadMs = elapsedMs(packReadStart);
|
|
87
|
+
if (pack.status === 'hit') {
|
|
88
|
+
const contextFromPack = {
|
|
89
|
+
...pack.context,
|
|
90
|
+
strategy: 'cag',
|
|
91
|
+
requestedStrategy: strategy,
|
|
92
|
+
recommendedStrategy: {
|
|
93
|
+
strategy: 'cag',
|
|
94
|
+
reason: strategy === 'auto'
|
|
95
|
+
? 'A fresh context pack exists, so auto selected CAG.'
|
|
96
|
+
: 'The requested CAG context pack is fresh.'
|
|
97
|
+
},
|
|
98
|
+
metrics: emptyMetrics(pack.context, elapsedMs(totalStart), { packReadMs })
|
|
99
|
+
};
|
|
100
|
+
contextCacheSet({
|
|
101
|
+
key: cacheKey,
|
|
102
|
+
createdAt: Date.now(),
|
|
103
|
+
dataSignature,
|
|
104
|
+
strategy,
|
|
105
|
+
context: contextFromPack
|
|
106
|
+
});
|
|
107
|
+
return contextFromPack;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
const searchStart = performance.now();
|
|
55
111
|
const results = await searchKnowledge(vaultPath, query, limit, agentId, mode);
|
|
112
|
+
const searchMs = elapsedMs(searchStart);
|
|
113
|
+
const selectionStart = performance.now();
|
|
56
114
|
const durableSections = selectContextSections(results, maxTokens);
|
|
115
|
+
const selectionMs = elapsedMs(selectionStart);
|
|
116
|
+
const volatileStart = performance.now();
|
|
57
117
|
const volatileSections = await searchVolatileMemory(vaultPath, query, Math.min(3, limit), agentId, mode ?? 'hybrid');
|
|
118
|
+
const volatileMs = elapsedMs(volatileStart);
|
|
58
119
|
const sections = [...volatileSections, ...durableSections];
|
|
120
|
+
const effectiveStrategy = strategy === 'cag' ? 'cag' : 'rag';
|
|
59
121
|
const context = {
|
|
60
122
|
query,
|
|
61
123
|
sections,
|
|
62
124
|
content: formatContextPackage(query, sections),
|
|
63
|
-
...(volatileSections.length > 0 ? { volatileSections } : {})
|
|
125
|
+
...(volatileSections.length > 0 ? { volatileSections } : {}),
|
|
126
|
+
strategy: effectiveStrategy,
|
|
127
|
+
requestedStrategy: strategy,
|
|
128
|
+
recommendedStrategy: {
|
|
129
|
+
strategy: effectiveStrategy,
|
|
130
|
+
reason: strategy === 'auto'
|
|
131
|
+
? 'No fresh context pack was available, so auto selected fresh RAG assembly and refreshed a pack for future reuse.'
|
|
132
|
+
: effectiveStrategy === 'cag'
|
|
133
|
+
? 'CAG was requested; Brainlink refreshed the context pack from current retrieval results.'
|
|
134
|
+
: 'RAG was requested; Brainlink assembled context directly from current retrieval results.'
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
const packWriteStart = performance.now();
|
|
138
|
+
const packPath = shouldUseContextPack
|
|
139
|
+
? await writeContextPack(vaultPath, { query, limit, maxTokens, agentId, mode }, dataSignature, context)
|
|
140
|
+
: undefined;
|
|
141
|
+
const packWriteMs = packPath ? elapsedMs(packWriteStart) : 0;
|
|
142
|
+
const contextWithMetadata = withCacheMetadata(context, {
|
|
143
|
+
storage: shouldUseContextPack ? 'context-pack' : 'memory',
|
|
144
|
+
status: shouldUseContextPack ? 'refresh' : 'miss',
|
|
145
|
+
dataSignature,
|
|
146
|
+
...(packPath ? { path: packPath } : {})
|
|
147
|
+
});
|
|
148
|
+
const contextWithMetrics = {
|
|
149
|
+
...contextWithMetadata,
|
|
150
|
+
metrics: emptyMetrics(contextWithMetadata, elapsedMs(totalStart), {
|
|
151
|
+
packReadMs,
|
|
152
|
+
searchMs,
|
|
153
|
+
selectionMs,
|
|
154
|
+
volatileMs,
|
|
155
|
+
packWriteMs
|
|
156
|
+
})
|
|
64
157
|
};
|
|
65
158
|
contextCacheSet({
|
|
66
159
|
key: cacheKey,
|
|
67
160
|
createdAt: Date.now(),
|
|
68
161
|
dataSignature,
|
|
69
|
-
|
|
162
|
+
strategy,
|
|
163
|
+
context: contextWithMetrics
|
|
70
164
|
});
|
|
71
|
-
return
|
|
165
|
+
return contextWithMetrics;
|
|
72
166
|
};
|
|
73
|
-
export const buildContext = async (vaultPath, query, limit, maxTokens, agentId, mode) => {
|
|
74
|
-
const contextPackage = await buildContextPackage(vaultPath, query, limit, maxTokens, agentId, mode);
|
|
167
|
+
export const buildContext = async (vaultPath, query, limit, maxTokens, agentId, mode, strategy) => {
|
|
168
|
+
const contextPackage = await buildContextPackage(vaultPath, query, limit, maxTokens, agentId, mode, strategy);
|
|
75
169
|
return contextPackage.content;
|
|
76
170
|
};
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
export const createClientCss = () => `:root {
|
|
2
|
-
color-scheme:
|
|
3
|
-
--bg: #
|
|
4
|
-
--panel: #
|
|
5
|
-
--panel-strong: #
|
|
6
|
-
--line:
|
|
7
|
-
--text: #
|
|
8
|
-
--muted: #
|
|
9
|
-
--accent: #
|
|
10
|
-
--accent-weak: rgba(
|
|
11
|
-
--danger: #
|
|
2
|
+
color-scheme: dark;
|
|
3
|
+
--bg: #071019;
|
|
4
|
+
--panel: #0d1823;
|
|
5
|
+
--panel-strong: #112130;
|
|
6
|
+
--line: rgba(143, 172, 204, 0.18);
|
|
7
|
+
--text: #edf4ff;
|
|
8
|
+
--muted: #97a9bd;
|
|
9
|
+
--accent: #5aa8ff;
|
|
10
|
+
--accent-weak: rgba(90, 168, 255, 0.18);
|
|
11
|
+
--danger: #ff6b6b;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
* {
|
|
@@ -63,8 +63,8 @@ select {
|
|
|
63
63
|
min-height: 72px;
|
|
64
64
|
padding: 10px 16px;
|
|
65
65
|
border-bottom: 1px solid var(--line);
|
|
66
|
-
background: rgba(
|
|
67
|
-
box-shadow: 0 1px
|
|
66
|
+
background: rgba(9, 18, 28, 0.92);
|
|
67
|
+
box-shadow: 0 1px 14px rgba(1, 6, 13, 0.42);
|
|
68
68
|
backdrop-filter: blur(8px);
|
|
69
69
|
}
|
|
70
70
|
|
|
@@ -82,10 +82,14 @@ select {
|
|
|
82
82
|
position: relative;
|
|
83
83
|
width: 100%;
|
|
84
84
|
height: 100%;
|
|
85
|
+
touch-action: none;
|
|
86
|
+
user-select: none;
|
|
87
|
+
-webkit-user-select: none;
|
|
85
88
|
background:
|
|
86
|
-
linear-gradient(rgba(
|
|
87
|
-
linear-gradient(90deg, rgba(
|
|
88
|
-
|
|
89
|
+
linear-gradient(rgba(164, 197, 230, 0.05) 1px, transparent 1px),
|
|
90
|
+
linear-gradient(90deg, rgba(164, 197, 230, 0.05) 1px, transparent 1px),
|
|
91
|
+
radial-gradient(circle at top, rgba(43, 93, 143, 0.22), transparent 44%),
|
|
92
|
+
#08131d;
|
|
89
93
|
background-size: 28px 28px, 28px 28px, auto;
|
|
90
94
|
overflow: hidden;
|
|
91
95
|
}
|
|
@@ -96,6 +100,7 @@ select {
|
|
|
96
100
|
inset: 0;
|
|
97
101
|
width: 100%;
|
|
98
102
|
height: 100%;
|
|
103
|
+
touch-action: none;
|
|
99
104
|
}
|
|
100
105
|
|
|
101
106
|
#graph {
|
|
@@ -131,21 +136,21 @@ select {
|
|
|
131
136
|
max-width: 220px;
|
|
132
137
|
transform: translate(-50%, calc(-100% - 12px));
|
|
133
138
|
padding: 4px 8px;
|
|
134
|
-
border: 1px solid rgba(
|
|
139
|
+
border: 1px solid rgba(143, 172, 204, 0.18);
|
|
135
140
|
border-radius: 6px;
|
|
136
|
-
background: rgba(
|
|
141
|
+
background: rgba(7, 16, 25, 0.92);
|
|
137
142
|
color: var(--text);
|
|
138
143
|
font-size: 11px;
|
|
139
144
|
line-height: 1.25;
|
|
140
145
|
white-space: nowrap;
|
|
141
146
|
overflow: hidden;
|
|
142
147
|
text-overflow: ellipsis;
|
|
143
|
-
box-shadow: 0
|
|
148
|
+
box-shadow: 0 12px 28px rgba(1, 6, 13, 0.36);
|
|
144
149
|
}
|
|
145
150
|
|
|
146
151
|
.graph-label.is-focused {
|
|
147
|
-
border-color: rgba(
|
|
148
|
-
color: #
|
|
152
|
+
border-color: rgba(90, 168, 255, 0.56);
|
|
153
|
+
color: #d7e9ff;
|
|
149
154
|
}
|
|
150
155
|
|
|
151
156
|
.graph-tooltip {
|
|
@@ -155,12 +160,12 @@ select {
|
|
|
155
160
|
padding: 8px 10px;
|
|
156
161
|
border: 1px solid var(--line);
|
|
157
162
|
border-radius: 6px;
|
|
158
|
-
background: rgba(
|
|
163
|
+
background: rgba(9, 18, 28, 0.96);
|
|
159
164
|
color: var(--text);
|
|
160
165
|
font-size: 12px;
|
|
161
166
|
line-height: 1.35;
|
|
162
167
|
pointer-events: none;
|
|
163
|
-
box-shadow: 0
|
|
168
|
+
box-shadow: 0 18px 44px rgba(1, 6, 13, 0.42);
|
|
164
169
|
}
|
|
165
170
|
|
|
166
171
|
.graph-tooltip strong,
|
|
@@ -182,10 +187,10 @@ select {
|
|
|
182
187
|
z-index: 3;
|
|
183
188
|
width: 180px;
|
|
184
189
|
height: 120px;
|
|
185
|
-
border: 1px solid rgba(
|
|
190
|
+
border: 1px solid rgba(143, 172, 204, 0.18);
|
|
186
191
|
border-radius: 8px;
|
|
187
|
-
background: rgba(
|
|
188
|
-
box-shadow: 0
|
|
192
|
+
background: rgba(8, 19, 29, 0.84);
|
|
193
|
+
box-shadow: 0 18px 40px rgba(1, 6, 13, 0.36);
|
|
189
194
|
}
|
|
190
195
|
|
|
191
196
|
.eyebrow {
|
|
@@ -218,7 +223,7 @@ select {
|
|
|
218
223
|
border: 1px solid var(--line);
|
|
219
224
|
border-radius: 8px;
|
|
220
225
|
outline: none;
|
|
221
|
-
background: rgba(
|
|
226
|
+
background: rgba(12, 24, 36, 0.94);
|
|
222
227
|
color: var(--text);
|
|
223
228
|
padding: 0 14px;
|
|
224
229
|
}
|
|
@@ -239,7 +244,7 @@ select {
|
|
|
239
244
|
height: 38px;
|
|
240
245
|
border: 1px solid var(--line);
|
|
241
246
|
border-radius: 8px;
|
|
242
|
-
background: rgba(
|
|
247
|
+
background: rgba(12, 24, 36, 0.94);
|
|
243
248
|
color: var(--text);
|
|
244
249
|
cursor: pointer;
|
|
245
250
|
}
|
|
@@ -260,7 +265,7 @@ select {
|
|
|
260
265
|
padding: 10px 12px;
|
|
261
266
|
border: 1px solid var(--line);
|
|
262
267
|
border-radius: 10px;
|
|
263
|
-
background: rgba(
|
|
268
|
+
background: rgba(12, 24, 36, 0.94);
|
|
264
269
|
display: grid;
|
|
265
270
|
gap: 3px;
|
|
266
271
|
}
|
|
@@ -335,7 +340,7 @@ li small {
|
|
|
335
340
|
padding: 12px;
|
|
336
341
|
border: 1px solid var(--line);
|
|
337
342
|
border-radius: 8px;
|
|
338
|
-
background: #
|
|
343
|
+
background: #091521;
|
|
339
344
|
color: var(--text);
|
|
340
345
|
white-space: pre-wrap;
|
|
341
346
|
overflow: auto;
|
|
@@ -366,6 +371,7 @@ li small {
|
|
|
366
371
|
background: var(--panel);
|
|
367
372
|
color: var(--text);
|
|
368
373
|
box-shadow: 0 24px 80px rgba(23, 32, 51, 0.22);
|
|
374
|
+
backdrop-filter: blur(10px);
|
|
369
375
|
overflow: hidden;
|
|
370
376
|
}
|
|
371
377
|
|
|
@@ -469,7 +475,7 @@ li small {
|
|
|
469
475
|
padding: 10px;
|
|
470
476
|
border: 1px solid var(--line);
|
|
471
477
|
border-radius: 8px;
|
|
472
|
-
background: #
|
|
478
|
+
background: #091521;
|
|
473
479
|
display: grid;
|
|
474
480
|
grid-template-rows: auto minmax(0, 1fr);
|
|
475
481
|
gap: 8px;
|
|
@@ -509,7 +515,7 @@ li small {
|
|
|
509
515
|
display: flex;
|
|
510
516
|
align-items: center;
|
|
511
517
|
justify-content: center;
|
|
512
|
-
background:
|
|
518
|
+
background: linear-gradient(180deg, rgba(7, 16, 25, 0), rgba(7, 16, 25, 0.84));
|
|
513
519
|
}
|
|
514
520
|
|
|
515
521
|
.app-footer small {
|