dsh-background-by-model 0.4.1 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -1
- package/README.zh.md +28 -1
- package/lib/client.js +1652 -2
- package/lib/client.js.map +1 -1
- package/lib/host-scan-BDh0upIQ.js +1160 -0
- package/lib/host-scan.js +2 -0
- package/lib/index.js +24 -0
- package/lib/testing.js +560 -0
- package/package.json +128 -122
- package/scripts/host-contract-scan.mjs +182 -0
- package/test/host-check.test.mjs +296 -0
package/lib/host-scan.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { a as thisPluginDir, c as DSH_FLOOR, i as resolveHostRoots, l as HOST_CONTRACTS, n as listHostPackages, o as versionOf, r as meetsFloor, t as checkHostOnDisk } from "./host-scan-BDh0upIQ.js";
|
|
2
|
+
export { DSH_FLOOR, HOST_CONTRACTS, checkHostOnDisk, listHostPackages, meetsFloor, resolveHostRoots, thisPluginDir, versionOf };
|
package/lib/index.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { t as checkHostOnDisk } from "./host-scan-BDh0upIQ.js";
|
|
1
2
|
import { access, mkdir, readFile, readdir, rename, rm, writeFile } from "node:fs/promises";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
2
4
|
import { dshHomePath } from "@deepseek-ai/dsh-home-paths";
|
|
3
5
|
//#region src/schema.ts
|
|
4
6
|
/** Every accepted `bgMode`, in UI order. */
|
|
@@ -420,6 +422,24 @@ function defaultModel(ctx) {
|
|
|
420
422
|
} catch {}
|
|
421
423
|
return null;
|
|
422
424
|
}
|
|
425
|
+
/**
|
|
426
|
+
* The installed-host half of the self-check.
|
|
427
|
+
*
|
|
428
|
+
* The browser probe behind the "Host check" tab already answers "does this host
|
|
429
|
+
* still provide what I use"; this adds the two facts only the node half can know:
|
|
430
|
+
* the host's own version, and whether the packages on disk still contain the
|
|
431
|
+
* literals the plugin depends on. Reading it costs a handful of file reads, and
|
|
432
|
+
* it is only ever called while that tab is open.
|
|
433
|
+
*/
|
|
434
|
+
let pluginDir = null;
|
|
435
|
+
function thisPluginDir() {
|
|
436
|
+
if (pluginDir === null) pluginDir = fileURLToPath(new URL("..", import.meta.url));
|
|
437
|
+
return pluginDir;
|
|
438
|
+
}
|
|
439
|
+
async function hostCheck(payload) {
|
|
440
|
+
const lang = payload?.lang === "en" ? "en" : "zh";
|
|
441
|
+
return await checkHostOnDisk(thisPluginDir(), lang);
|
|
442
|
+
}
|
|
423
443
|
const NS = "dshBackgroundByModel";
|
|
424
444
|
const RPC_CHANNEL = "/dsh-background-by-model";
|
|
425
445
|
const RPC_BODY_MAX = 314572800;
|
|
@@ -485,6 +505,10 @@ async function handleRpcMethod(ctx, endpoint, payload) {
|
|
|
485
505
|
ok: true,
|
|
486
506
|
value: defaultModel(ctx)
|
|
487
507
|
};
|
|
508
|
+
case "hostCheck": return {
|
|
509
|
+
ok: true,
|
|
510
|
+
value: await hostCheck(payload)
|
|
511
|
+
};
|
|
488
512
|
default: return {
|
|
489
513
|
ok: false,
|
|
490
514
|
error: {
|
package/lib/testing.js
ADDED
|
@@ -0,0 +1,560 @@
|
|
|
1
|
+
import { c as DSH_FLOOR, d as reportToMarkdown, f as symptomOf, i as resolveHostRoots, l as HOST_CONTRACTS, o as versionOf, p as verdictOf, r as meetsFloor, s as CONTRACT_GROUPS, t as checkHostOnDisk, u as labelOf } from "./host-scan-BDh0upIQ.js";
|
|
2
|
+
//#region src/client/judge.ts
|
|
3
|
+
/** The real browser environment. */
|
|
4
|
+
function browserEnv(ctx) {
|
|
5
|
+
return {
|
|
6
|
+
querySelector: (selector) => document.querySelector(selector),
|
|
7
|
+
computedValue: (token, on) => {
|
|
8
|
+
if (typeof document === "undefined") return "";
|
|
9
|
+
const host = on ?? document.documentElement;
|
|
10
|
+
return getComputedStyle(host).getPropertyValue(token).trim();
|
|
11
|
+
},
|
|
12
|
+
styleSheets: () => typeof document === "undefined" ? [] : Array.from(document.styleSheets),
|
|
13
|
+
ctx
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
const ANCHORS = {
|
|
17
|
+
settingsClosed: "div[role=\"dialog\"][aria-modal=\"true\"][aria-labelledby]",
|
|
18
|
+
chatNotMounted: "[data-chat-flow],[data-conversation-scroll]",
|
|
19
|
+
trajectoryNotMounted: "[data-conversation-composer-overlay]",
|
|
20
|
+
noRightPanel: "div[data-sidebar-right-panel],[data-dockkit-strip],[data-dockkit-pane]",
|
|
21
|
+
cordisClosed: "[data-cordis-panel]"
|
|
22
|
+
};
|
|
23
|
+
function mounted(env, anchorId) {
|
|
24
|
+
const sel = ANCHORS[anchorId];
|
|
25
|
+
if (sel === void 0) return true;
|
|
26
|
+
try {
|
|
27
|
+
return env.querySelector(sel) !== null;
|
|
28
|
+
} catch {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/** Walk a dotted path off a root object, tolerating a missing first hop. */
|
|
33
|
+
function walkPath(root, path) {
|
|
34
|
+
let cur = root;
|
|
35
|
+
for (const key of path.split(".")) {
|
|
36
|
+
if (cur === null || cur === void 0) return void 0;
|
|
37
|
+
cur = cur[key];
|
|
38
|
+
}
|
|
39
|
+
return cur;
|
|
40
|
+
}
|
|
41
|
+
function looksObservable(v) {
|
|
42
|
+
return typeof v === "object" && v !== null && typeof v.subscribe === "function" && typeof v.getSnapshot === "function";
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* A stylesheet mention of a literal.
|
|
46
|
+
*
|
|
47
|
+
* The host's rules are the only place a renamed token still answers honestly:
|
|
48
|
+
* a token can be *declared* by this plugin while the host's rule that consumed
|
|
49
|
+
* it is gone. Cross-origin sheets (none on a local dsh, but the probe must not
|
|
50
|
+
* throw if one ever appears) are skipped.
|
|
51
|
+
*/
|
|
52
|
+
function ruleMentioned(env, literal) {
|
|
53
|
+
for (const sheet of env.styleSheets()) {
|
|
54
|
+
if (sheet.ownerNode?.dataset?.plugin !== void 0) continue;
|
|
55
|
+
let rules = null;
|
|
56
|
+
try {
|
|
57
|
+
rules = sheet.cssRules;
|
|
58
|
+
} catch {
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
if (rules === null) continue;
|
|
62
|
+
for (const rule of Array.from(rules)) {
|
|
63
|
+
const text = rule.cssText;
|
|
64
|
+
if (typeof text === "string" && text.includes(literal)) return true;
|
|
65
|
+
const inner = rule.cssRules;
|
|
66
|
+
if (inner === void 0 || inner === null) continue;
|
|
67
|
+
for (const child of Array.from(inner)) {
|
|
68
|
+
const childText = child.cssText;
|
|
69
|
+
if (typeof childText === "string" && childText.includes(literal)) return true;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
/** Whether any reachable host stylesheet could be read (false ⇒ the check is blind). */
|
|
76
|
+
function stylesReadable(env) {
|
|
77
|
+
for (const sheet of env.styleSheets()) try {
|
|
78
|
+
if (sheet.cssRules !== null) return true;
|
|
79
|
+
} catch {}
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
function evaluate(env, check) {
|
|
83
|
+
switch (check.kind) {
|
|
84
|
+
case "service": {
|
|
85
|
+
let svc;
|
|
86
|
+
try {
|
|
87
|
+
svc = env.ctx.get(check.id);
|
|
88
|
+
} catch {
|
|
89
|
+
svc = void 0;
|
|
90
|
+
}
|
|
91
|
+
return svc === void 0 || svc === null ? {
|
|
92
|
+
status: "fail",
|
|
93
|
+
name: `ctx.get('${check.id}')`,
|
|
94
|
+
detail: "service not published",
|
|
95
|
+
reason: `the host does not publish the "${check.id}" service`
|
|
96
|
+
} : {
|
|
97
|
+
status: "pass",
|
|
98
|
+
name: `ctx.get('${check.id}')`,
|
|
99
|
+
detail: "service present"
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
case "path": {
|
|
103
|
+
let svc;
|
|
104
|
+
try {
|
|
105
|
+
svc = env.ctx.get(check.service);
|
|
106
|
+
} catch {
|
|
107
|
+
svc = void 0;
|
|
108
|
+
}
|
|
109
|
+
if (svc === void 0 || svc === null) return {
|
|
110
|
+
status: "skip",
|
|
111
|
+
name: `${check.service}.${check.path}`,
|
|
112
|
+
detail: "service not published yet"
|
|
113
|
+
};
|
|
114
|
+
const value = walkPath(svc, check.path);
|
|
115
|
+
const name = `${check.service}.${check.path}`;
|
|
116
|
+
if (check.expect === "function") return typeof value === "function" ? {
|
|
117
|
+
status: "pass",
|
|
118
|
+
name,
|
|
119
|
+
detail: "is a function"
|
|
120
|
+
} : {
|
|
121
|
+
status: "fail",
|
|
122
|
+
name,
|
|
123
|
+
detail: `expected a function, got ${typeof value}`,
|
|
124
|
+
reason: `"${name}" is not a function on this host`
|
|
125
|
+
};
|
|
126
|
+
if (check.expect === "observable") return looksObservable(value) ? {
|
|
127
|
+
status: "pass",
|
|
128
|
+
name,
|
|
129
|
+
detail: "is an observable face"
|
|
130
|
+
} : {
|
|
131
|
+
status: "fail",
|
|
132
|
+
name,
|
|
133
|
+
detail: "not an observable face",
|
|
134
|
+
reason: `"${name}" no longer exposes subscribe()/getSnapshot()`
|
|
135
|
+
};
|
|
136
|
+
return value === void 0 ? {
|
|
137
|
+
status: "fail",
|
|
138
|
+
name,
|
|
139
|
+
detail: "undefined",
|
|
140
|
+
reason: `"${name}" is gone`
|
|
141
|
+
} : {
|
|
142
|
+
status: "pass",
|
|
143
|
+
name,
|
|
144
|
+
detail: typeof value
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
case "selector": {
|
|
148
|
+
const present = env.querySelector(check.selector) !== null;
|
|
149
|
+
const name = `querySelector(${JSON.stringify(check.selector)})`;
|
|
150
|
+
if (present) return {
|
|
151
|
+
status: "pass",
|
|
152
|
+
name,
|
|
153
|
+
detail: "element found"
|
|
154
|
+
};
|
|
155
|
+
if (check.optionalWhen !== void 0 && !mounted(env, check.optionalWhen)) return {
|
|
156
|
+
status: "skip",
|
|
157
|
+
name,
|
|
158
|
+
detail: "not on screen right now"
|
|
159
|
+
};
|
|
160
|
+
return {
|
|
161
|
+
status: "fail",
|
|
162
|
+
name,
|
|
163
|
+
detail: "no element matches",
|
|
164
|
+
reason: `no element matches ${check.selector} while its surface is on screen`
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
case "attr": {
|
|
168
|
+
const present = env.querySelector(`[${check.attr}]`) !== null;
|
|
169
|
+
const name = `querySelector([${check.attr}])`;
|
|
170
|
+
if (present) return {
|
|
171
|
+
status: "pass",
|
|
172
|
+
name,
|
|
173
|
+
detail: "attribute found"
|
|
174
|
+
};
|
|
175
|
+
if (check.optionalWhen !== void 0 && !mounted(env, check.optionalWhen)) return {
|
|
176
|
+
status: "skip",
|
|
177
|
+
name,
|
|
178
|
+
detail: "not on screen right now"
|
|
179
|
+
};
|
|
180
|
+
return {
|
|
181
|
+
status: "fail",
|
|
182
|
+
name,
|
|
183
|
+
detail: "no element carries it",
|
|
184
|
+
reason: `nothing in the DOM carries ${check.attr} while its surface is on screen`
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
case "computed": {
|
|
188
|
+
const host = check.on !== void 0 ? env.querySelector(check.on) : null;
|
|
189
|
+
const name = `computed(${check.token}${check.on !== void 0 ? ` on ${check.on}` : ""})`;
|
|
190
|
+
if (check.on !== void 0 && host === null) return {
|
|
191
|
+
status: "skip",
|
|
192
|
+
name,
|
|
193
|
+
detail: `${check.on} not mounted`
|
|
194
|
+
};
|
|
195
|
+
const value = env.computedValue(check.token, host);
|
|
196
|
+
return value !== "" ? {
|
|
197
|
+
status: "pass",
|
|
198
|
+
name,
|
|
199
|
+
detail: value
|
|
200
|
+
} : {
|
|
201
|
+
status: "fail",
|
|
202
|
+
name,
|
|
203
|
+
detail: "resolves to nothing",
|
|
204
|
+
reason: `${check.token} resolves to an empty value`
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
case "rule": {
|
|
208
|
+
const name = `stylesheet includes ${JSON.stringify(check.match)}`;
|
|
209
|
+
if (!stylesReadable(env)) return {
|
|
210
|
+
status: "skip",
|
|
211
|
+
name,
|
|
212
|
+
detail: "no stylesheet is readable"
|
|
213
|
+
};
|
|
214
|
+
return ruleMentioned(env, check.match) ? {
|
|
215
|
+
status: "pass",
|
|
216
|
+
name,
|
|
217
|
+
detail: "declared by a host rule"
|
|
218
|
+
} : {
|
|
219
|
+
status: "fail",
|
|
220
|
+
name,
|
|
221
|
+
detail: "no rule mentions it",
|
|
222
|
+
reason: `no stylesheet declares ${check.match}`
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
default: return {
|
|
226
|
+
status: "fail",
|
|
227
|
+
name: "unknown check",
|
|
228
|
+
detail: String(check)
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
/** A contract with no checks is documentation only (a legacy alias we still accept). */
|
|
233
|
+
function noChecks(c, lang) {
|
|
234
|
+
return {
|
|
235
|
+
id: c.id,
|
|
236
|
+
label: labelOf(c, lang),
|
|
237
|
+
symptom: symptomOf(c, lang),
|
|
238
|
+
status: "info",
|
|
239
|
+
detail: lang === "zh" ? "无需运行时检查 —— 仅记录兼容用法" : "no runtime check — accepted for compatibility",
|
|
240
|
+
target: c.target,
|
|
241
|
+
sources: c.sources,
|
|
242
|
+
usedBy: c.usedBy,
|
|
243
|
+
checks: []
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Run every contract against a probe environment.
|
|
248
|
+
*
|
|
249
|
+
* Only the FIRST failing check of a contract is reported: the later ones usually
|
|
250
|
+
* depend on it (no service ⇒ no methods on it), so listing them all would turn
|
|
251
|
+
* one rename into five red lines.
|
|
252
|
+
*/
|
|
253
|
+
function probeContracts(env, lang) {
|
|
254
|
+
return HOST_CONTRACTS.map((c) => {
|
|
255
|
+
const result = {
|
|
256
|
+
id: c.id,
|
|
257
|
+
label: labelOf(c, lang),
|
|
258
|
+
symptom: symptomOf(c, lang),
|
|
259
|
+
status: "pass",
|
|
260
|
+
detail: "",
|
|
261
|
+
target: c.target,
|
|
262
|
+
sources: c.sources,
|
|
263
|
+
usedBy: c.usedBy,
|
|
264
|
+
checks: []
|
|
265
|
+
};
|
|
266
|
+
if (c.checks.length === 0) return noChecks(c, lang);
|
|
267
|
+
const outcomes = [];
|
|
268
|
+
let firstFail;
|
|
269
|
+
for (const check of c.checks) {
|
|
270
|
+
let outcome;
|
|
271
|
+
try {
|
|
272
|
+
outcome = evaluate(env, check);
|
|
273
|
+
} catch (e) {
|
|
274
|
+
outcome = {
|
|
275
|
+
status: "fail",
|
|
276
|
+
name: check.kind,
|
|
277
|
+
detail: String(e),
|
|
278
|
+
reason: `${check.kind} check threw`
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
outcomes.push(outcome);
|
|
282
|
+
if (outcome.status === "fail" && firstFail === void 0) firstFail = outcome;
|
|
283
|
+
}
|
|
284
|
+
result.checks = outcomes.map((o) => `${o.status} · ${o.name} — ${o.detail}`);
|
|
285
|
+
if (firstFail !== void 0) {
|
|
286
|
+
result.status = "fail";
|
|
287
|
+
result.detail = `${firstFail.name} — ${firstFail.detail}`;
|
|
288
|
+
result.reason = firstFail.reason;
|
|
289
|
+
return result;
|
|
290
|
+
}
|
|
291
|
+
const ran = outcomes.filter((o) => o.status !== "skip");
|
|
292
|
+
if (ran.length === 0) {
|
|
293
|
+
result.status = "skip";
|
|
294
|
+
result.detail = outcomes.map((o) => `${o.name} — ${o.detail}`).join("; ");
|
|
295
|
+
return result;
|
|
296
|
+
}
|
|
297
|
+
result.status = ran.some((o) => o.status === "info") && ran.every((o) => o.status === "info") ? "info" : "pass";
|
|
298
|
+
const last = ran[ran.length - 1];
|
|
299
|
+
result.detail = `${last.name} — ${last.detail}`;
|
|
300
|
+
return result;
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
const UI_CSS = `
|
|
304
|
+
/* The section is rendered INLINE inside the host settings dialog's content
|
|
305
|
+
* column: the host provides the modal chrome (backdrop, centering, closing).
|
|
306
|
+
* These classes style only the embedded shell; transient fixed layers (toast,
|
|
307
|
+
* color picker, background editor) escape through Portals on <html>. */
|
|
308
|
+
.dab-root{position:relative;color:var(--dsw-alias-label-primary);animation:dab-fade-in .35s ease both;container-type:inline-size;display:flex;flex-direction:column;align-items:center;width:100%;min-width:0;--dab-mono:ui-monospace,"Cascadia Mono","SF Mono",Consolas,"Courier New",monospace}
|
|
309
|
+
.dab-root *,.dab-root *::before,.dab-root *::after{box-sizing:border-box}
|
|
310
|
+
.dab-root button{font-family:inherit}
|
|
311
|
+
|
|
312
|
+
/* ── shell: nav rail + page body ─────────────────────────────────────────── */
|
|
313
|
+
.dab-shell{display:grid;grid-template-columns:158px minmax(0,1fr);gap:26px;align-items:start;padding-bottom:8px;width:100%;max-width:980px;margin:0 auto}
|
|
314
|
+
.dab-nav{position:sticky;top:0;display:flex;flex-direction:column;gap:18px}
|
|
315
|
+
.dab-brand{display:flex;align-items:center;gap:10px;padding:2px 6px}
|
|
316
|
+
.dab-brand-tile{width:30px;height:30px;flex:none;border-radius:9px;display:grid;place-items:center;color:var(--dsw-alias-brand-text);background:var(--dsw-alias-brand-primary);box-shadow:0 4px 14px -4px var(--dsw-alias-brand-primary)}
|
|
317
|
+
.dab-brand-name{font-size:13px;font-weight:650;letter-spacing:.01em;line-height:1.25}
|
|
318
|
+
.dab-brand-tag{font-size:9px;letter-spacing:.16em;font-weight:600;color:var(--dsw-alias-label-quaternary,var(--dsw-alias-label-tertiary));text-transform:uppercase}
|
|
319
|
+
.dab-nav-list{position:relative;display:flex;flex-direction:column;gap:4px}
|
|
320
|
+
.dab-nav-ind{position:absolute;left:0;right:0;top:0;height:38px;border-radius:11px;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);background:color-mix(in srgb,var(--dsw-alias-brand-primary) 13%,transparent);border-color:color-mix(in srgb,var(--dsw-alias-brand-primary) 25%,transparent);transition:transform .38s cubic-bezier(.22,1,.36,1)}
|
|
321
|
+
.dab-nav-item{position:relative;z-index:1;display:flex;align-items:center;gap:10px;height:38px;padding:0 12px;border:0;background:none;border-radius:11px;color:var(--dsw-alias-label-tertiary);font-size:13px;cursor:pointer;text-align:left;transition:color .22s ease}
|
|
322
|
+
.dab-nav-item:hover{color:var(--dsw-alias-label-primary)}
|
|
323
|
+
.dab-nav-item.is-active{color:var(--dsw-alias-brand-primary);font-weight:600}
|
|
324
|
+
.dab-nav-item svg{flex:none;transition:transform .3s cubic-bezier(.34,1.56,.64,1)}
|
|
325
|
+
.dab-nav-item:hover svg{transform:scale(1.14) rotate(-5deg)}
|
|
326
|
+
|
|
327
|
+
/* ── page chrome ─────────────────────────────────────────────────────────── */
|
|
328
|
+
.dab-page{animation:dab-page-in .4s cubic-bezier(.22,1,.36,1) both;min-width:0;display:flex;flex-direction:column;gap:13px}
|
|
329
|
+
.dab-head{margin:2px 0 5px}
|
|
330
|
+
.dab-overline{font-size:10.5px;font-weight:700;letter-spacing:.18em;text-transform:uppercase;color:var(--dsw-alias-brand-primary);opacity:.9}
|
|
331
|
+
.dab-h1{margin:4px 0 0;font-size:21px;font-weight:700;letter-spacing:-.01em}
|
|
332
|
+
.dab-desc{margin:6px 0 0;font-size:12.5px;line-height:1.55;color:var(--dsw-alias-label-tertiary);max-width:56ch}
|
|
333
|
+
.dab-card{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);border-radius:16px;padding:18px}
|
|
334
|
+
.dab-card-hover{transition:transform .28s ease,box-shadow .28s ease,border-color .28s ease}
|
|
335
|
+
.dab-card-hover:hover{transform:translateY(-2px);box-shadow:0 10px 28px -12px rgba(0,0,0,.28)}
|
|
336
|
+
.dab-rise{animation:dab-rise-in .55s cubic-bezier(.22,1,.36,1) both;animation-delay:calc(var(--d,0) * 62ms)}
|
|
337
|
+
|
|
338
|
+
/* ── accent hero (color orb) ─────────────────────────────────────────────── */
|
|
339
|
+
.dab-hero-accent{display:flex;align-items:center;gap:24px;flex-wrap:wrap}
|
|
340
|
+
.dab-orb-wrap{position:relative;width:118px;height:118px;flex:none}
|
|
341
|
+
.dab-orb{position:absolute;inset:11px;border-radius:50%;background:radial-gradient(circle at 32% 28%,rgba(255,255,255,.5),rgba(255,255,255,0) 44%),var(--c,#888);box-shadow:0 16px 36px -10px var(--c-soft,transparent),inset 0 -10px 20px rgba(0,0,0,.16);animation:dab-orb-in .7s cubic-bezier(.22,1,.36,1) both}
|
|
342
|
+
.dab-orb-ring{position:absolute;inset:0;border-radius:50%;background:conic-gradient(from 0deg,transparent 0 30%,var(--c,#888) 46%,transparent 62%,transparent 76%,var(--c,#888) 90%,transparent 100%);-webkit-mask:radial-gradient(farthest-side,transparent calc(100% - 3.5px),#000 calc(100% - 2.5px));mask:radial-gradient(farthest-side,transparent calc(100% - 3.5px),#000 calc(100% - 2.5px));animation:dab-spin 7s linear infinite;opacity:.9}
|
|
343
|
+
.dab-hex-caption{font-size:11px;color:var(--dsw-alias-label-tertiary);letter-spacing:.04em}
|
|
344
|
+
.dab-hex{font-family:var(--dab-mono);font-size:24px;font-weight:600;letter-spacing:.02em;line-height:1.2;margin-top:2px}
|
|
345
|
+
.dab-hsl-row{display:flex;gap:16px;margin-top:7px;font-family:var(--dab-mono);font-size:11px;color:var(--dsw-alias-label-tertiary)}
|
|
346
|
+
.dab-hsl-row b{font-weight:600;color:var(--dsw-alias-label-secondary,var(--dsw-alias-label-tertiary))}
|
|
347
|
+
|
|
348
|
+
/* ── swatches ────────────────────────────────────────────────────────────── */
|
|
349
|
+
.dab-swatch-title{font-size:12px;font-weight:600;margin-bottom:10px;color:var(--dsw-alias-label-secondary,var(--dsw-alias-label-tertiary))}
|
|
350
|
+
.dab-swatches{display:flex;flex-wrap:wrap;gap:9px}
|
|
351
|
+
.dab-swatch{width:25px;height:25px;border-radius:50%;border:0;padding:0;cursor:pointer;box-shadow:inset 0 0 0 1px rgba(0,0,0,.1);transition:transform .22s cubic-bezier(.34,1.56,.64,1),box-shadow .22s ease}
|
|
352
|
+
.dab-swatch:hover{transform:scale(1.2)}
|
|
353
|
+
.dab-swatch.is-on{box-shadow:0 0 0 2px var(--dsw-alias-bg-layer-1),0 0 0 4px var(--dsw-alias-brand-primary)}
|
|
354
|
+
|
|
355
|
+
/* ── wheel card ──────────────────────────────────────────────────────────── */
|
|
356
|
+
.dab-wheel-card{position:relative;display:flex;align-items:center;justify-content:center;gap:28px;flex-wrap:wrap;padding:24px 18px}
|
|
357
|
+
.dab-wheel-glow{position:absolute;width:230px;height:230px;border-radius:50%;filter:blur(48px);opacity:.2;background:var(--c,#888);pointer-events:none;transition:background .4s ease}
|
|
358
|
+
.dab-wheel{position:relative;cursor:crosshair;border-radius:50%;box-shadow:0 12px 32px -14px rgba(0,0,0,.4)}
|
|
359
|
+
.dab-hint{font-size:11.5px;line-height:1.55;color:var(--dsw-alias-label-tertiary);padding:0 4px}
|
|
360
|
+
|
|
361
|
+
/* ── precise color inputs ────────────────────────────────────────────────── */
|
|
362
|
+
.dab-inputs{display:flex;flex-direction:column;gap:10px;min-width:172px}
|
|
363
|
+
.dab-field{display:flex;align-items:center;gap:8px}
|
|
364
|
+
.dab-field-label{width:14px;text-align:center;font-family:var(--dab-mono);font-size:11px;font-weight:600;color:var(--dsw-alias-label-tertiary)}
|
|
365
|
+
.dab-num{flex:1;min-width:0;height:30px;padding:0 10px;border-radius:9px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font-family:var(--dab-mono);font-size:12px;outline:none;transition:border-color .2s,box-shadow .2s}
|
|
366
|
+
.dab-num:focus{border-color:var(--dsw-alias-brand-primary);box-shadow:0 0 0 3px color-mix(in srgb,var(--dsw-alias-brand-primary) 18%,transparent)}
|
|
367
|
+
.dab-num::-webkit-outer-spin-button,.dab-num::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
|
|
368
|
+
.dab-num{-moz-appearance:textfield;appearance:textfield}
|
|
369
|
+
.dab-urlinput{flex:1;min-width:180px;height:34px;padding:0 12px;border-radius:10px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font-size:12.5px;outline:none;transition:border-color .2s}
|
|
370
|
+
.dab-urlinput::placeholder{color:var(--dsw-alias-label-quaternary)}
|
|
371
|
+
.dab-urlinput:focus{border-color:var(--dsw-alias-brand-primary);box-shadow:0 0 0 3px color-mix(in srgb,var(--dsw-alias-brand-primary) 18%,transparent)}
|
|
372
|
+
.dab-swatch-lg{height:38px;border-radius:10px;border:1px solid var(--dsw-alias-border-l2);box-shadow:inset 0 0 14px rgba(0,0,0,.1);transition:transform .3s ease}
|
|
373
|
+
.dab-swatch-lg:hover{transform:scale(1.02)}
|
|
374
|
+
|
|
375
|
+
/* ── buttons & chips ─────────────────────────────────────────────────────── */
|
|
376
|
+
.dab-btn{display:inline-flex;align-items:center;justify-content:center;gap:7px;height:34px;padding:0 14px;border-radius:10px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-button-elevated-fill);color:var(--dsw-alias-label-primary);font-size:12.5px;font-weight:550;cursor:pointer;transition:transform .18s ease,box-shadow .18s ease,border-color .18s ease,opacity .18s ease,background .18s ease}
|
|
377
|
+
.dab-btn:hover:not(:disabled){transform:translateY(-1px);box-shadow:0 5px 14px -6px rgba(0,0,0,.32)}
|
|
378
|
+
.dab-btn:active:not(:disabled){transform:translateY(0) scale(.97);box-shadow:none}
|
|
379
|
+
.dab-btn:disabled{opacity:.5;cursor:not-allowed}
|
|
380
|
+
.dab-btn-primary{background:var(--dsw-alias-brand-primary);color:var(--dsw-alias-brand-text);border-color:transparent}
|
|
381
|
+
.dab-btn-danger{color:var(--dsw-alias-state-error-primary)}
|
|
382
|
+
.dab-btn-ghost{background:transparent;border-color:transparent;color:var(--dsw-alias-label-secondary,var(--dsw-alias-label-tertiary))}
|
|
383
|
+
.dab-btn-ghost:hover:not(:disabled){background:var(--dsw-alias-bg-layer-2);box-shadow:none}
|
|
384
|
+
.dab-btn:focus-visible,.dab-nav-item:focus-visible,.dab-seg-item:focus-visible,.dab-swatch:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}
|
|
385
|
+
.dab-chip-row{display:flex;flex-wrap:wrap;gap:8px}
|
|
386
|
+
.dab-chip{height:30px;padding:0 14px;border-radius:99px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-secondary,var(--dsw-alias-label-tertiary));font-size:12px;cursor:pointer;display:inline-flex;align-items:center;gap:6px;transition:all .22s ease}
|
|
387
|
+
.dab-chip:hover{border-color:var(--dsw-alias-brand-primary);color:var(--dsw-alias-label-primary)}
|
|
388
|
+
.dab-chip.is-active{background:var(--dsw-alias-brand-primary);color:var(--dsw-alias-brand-text);border-color:transparent}
|
|
389
|
+
|
|
390
|
+
/* ── sliders ─────────────────────────────────────────────────────────────── */
|
|
391
|
+
.dab-slider-block{display:flex;flex-direction:column;gap:6px}
|
|
392
|
+
.dab-slider-block + .dab-slider-block{margin-top:13px}
|
|
393
|
+
.dab-slider-label{font-size:12px;font-weight:550;color:var(--dsw-alias-label-secondary,var(--dsw-alias-label-tertiary))}
|
|
394
|
+
.dab-slider-val{font-family:var(--dab-mono);font-size:11px;color:var(--dsw-alias-label-tertiary);min-width:44px;text-align:right}
|
|
395
|
+
.dab-slider{-webkit-appearance:none;appearance:none;flex:1;min-width:0;height:4px;border-radius:99px;outline:none;cursor:pointer;margin:5px 0;background:linear-gradient(to right,var(--dsw-alias-brand-primary) calc(var(--pct,50) * 1%),var(--dsw-alias-border-l2) calc(var(--pct,50) * 1%));transition:height .15s ease}
|
|
396
|
+
.dab-slider:hover{height:5px}
|
|
397
|
+
.dab-slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:15px;height:15px;border-radius:50%;background:var(--dsw-alias-button-elevated-fill,#fff);border:2px solid var(--dsw-alias-brand-primary);box-shadow:0 1px 5px rgba(0,0,0,.28);transition:transform .16s cubic-bezier(.34,1.56,.64,1)}
|
|
398
|
+
.dab-slider:hover::-webkit-slider-thumb,.dab-slider:focus-visible::-webkit-slider-thumb{transform:scale(1.22)}
|
|
399
|
+
.dab-slider:active::-webkit-slider-thumb{transform:scale(1.34)}
|
|
400
|
+
.dab-slider::-moz-range-thumb{width:13px;height:13px;border-radius:50%;background:var(--dsw-alias-button-elevated-fill,#fff);border:2px solid var(--dsw-alias-brand-primary)}
|
|
401
|
+
|
|
402
|
+
/* ── interface part cards ────────────────────────────────────────────────── */
|
|
403
|
+
.dab-grid-parts{display:grid;grid-template-columns:repeat(auto-fill,minmax(256px,1fr));gap:13px}
|
|
404
|
+
.dab-part-head{display:flex;align-items:center;gap:11px;margin-bottom:14px}
|
|
405
|
+
.dab-part-ico{width:32px;height:32px;flex:none;border-radius:10px;display:grid;place-items:center;color:var(--dsw-alias-brand-primary);background:var(--dsw-alias-bg-layer-2);background:color-mix(in srgb,var(--dsw-alias-brand-primary) 12%,transparent)}
|
|
406
|
+
.dab-part-name{font-size:13.5px;font-weight:600}
|
|
407
|
+
.dab-part-badge{margin-left:auto;font-family:var(--dab-mono);font-size:11px;color:var(--dsw-alias-label-tertiary);background:var(--dsw-alias-bg-layer-2);border-radius:99px;padding:3px 9px}
|
|
408
|
+
|
|
409
|
+
/* ── segmented control ───────────────────────────────────────────────────── */
|
|
410
|
+
.dab-seg{position:relative;display:inline-flex;padding:3px;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);border-radius:11px}
|
|
411
|
+
.dab-seg-thumb{position:absolute;top:3px;bottom:3px;left:3px;width:var(--w,96px);border-radius:8px;background:var(--dsw-alias-button-elevated-fill);box-shadow:0 2px 8px -2px rgba(0,0,0,.28);transition:transform .32s cubic-bezier(.22,1,.36,1)}
|
|
412
|
+
.dab-seg-item{position:relative;z-index:1;display:inline-flex;align-items:center;justify-content:center;gap:6px;width:var(--w,96px);height:30px;border:0;background:none;border-radius:8px;color:var(--dsw-alias-label-tertiary);font-size:12.5px;cursor:pointer;transition:color .25s ease}
|
|
413
|
+
.dab-seg-item.is-active{color:var(--dsw-alias-label-primary);font-weight:600}
|
|
414
|
+
|
|
415
|
+
/* ── toggle switch ───────────────────────────────────────────────────────── */
|
|
416
|
+
.dab-toggle{position:relative;width:42px;height:24px;flex:none;border-radius:99px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);cursor:pointer;padding:0;transition:background .28s ease,border-color .28s ease}
|
|
417
|
+
.dab-toggle-knob{position:absolute;top:2.5px;left:2.5px;width:17px;height:17px;border-radius:50%;background:var(--dsw-alias-label-secondary,#999);box-shadow:0 1px 3px rgba(0,0,0,.3);transition:transform .28s cubic-bezier(.22,1,.36,1),background .28s ease}
|
|
418
|
+
.dab-toggle.is-on{background:var(--dsw-alias-brand-primary);border-color:var(--dsw-alias-brand-primary)}
|
|
419
|
+
.dab-toggle.is-on .dab-toggle-knob{transform:translateX(18px);background:#fff}
|
|
420
|
+
|
|
421
|
+
/* ── background preview hero ─────────────────────────────────────────────── */
|
|
422
|
+
.dab-hero{position:relative;border-radius:16px;overflow:hidden;aspect-ratio:16/9;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2)}
|
|
423
|
+
.dab-hero-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;transition:transform .5s cubic-bezier(.22,1,.36,1)}
|
|
424
|
+
.dab-hero:hover .dab-hero-img{transform:scale(1.03)}
|
|
425
|
+
.dab-hero-empty{position:absolute;inset:6px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;color:var(--dsw-alias-label-tertiary);font-size:12.5px;border:1.5px dashed var(--dsw-alias-border-l2);border-radius:12px;cursor:pointer;background:transparent;transition:border-color .25s,color .25s,background .25s;width:auto;height:auto}
|
|
426
|
+
.dab-hero-empty:hover{border-color:var(--dsw-alias-brand-primary);color:var(--dsw-alias-brand-primary)}
|
|
427
|
+
.dab-hero-empty.is-over{border-color:var(--dsw-alias-brand-primary);color:var(--dsw-alias-brand-primary);background:color-mix(in srgb,var(--dsw-alias-brand-primary) 8%,transparent)}
|
|
428
|
+
.dab-hero-badge{position:absolute;top:10px;left:10px;display:inline-flex;align-items:center;gap:5px;height:24px;padding:0 11px;border-radius:99px;background:rgba(0,0,0,.45);color:#fff;font-size:11px;backdrop-filter:blur(6px);pointer-events:none}
|
|
429
|
+
.dab-hero-veil{position:absolute;left:0;right:0;bottom:0;padding:34px 12px 12px;display:flex;align-items:flex-end;justify-content:flex-end;gap:8px;background:linear-gradient(to top,rgba(0,0,0,.55),rgba(0,0,0,0));opacity:0;transform:translateY(6px);transition:opacity .3s ease,transform .3s ease}
|
|
430
|
+
.dab-hero:hover .dab-hero-veil{opacity:1;transform:none}
|
|
431
|
+
.dab-hero-veil .dab-btn{background:rgba(255,255,255,.94);color:#14161a;border-color:transparent;height:30px;font-size:12px}
|
|
432
|
+
.dab-hero-veil .dab-btn-danger{color:#dc2626}
|
|
433
|
+
|
|
434
|
+
/* ── profile page ────────────────────────────────────────────────────────── */
|
|
435
|
+
.dab-profile-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(238px,1fr));gap:13px}
|
|
436
|
+
.dab-profile-ico{width:38px;height:38px;border-radius:11px;display:grid;place-items:center;margin-bottom:13px;color:var(--dsw-alias-brand-primary);background:var(--dsw-alias-bg-layer-2);background:color-mix(in srgb,var(--dsw-alias-brand-primary) 12%,transparent)}
|
|
437
|
+
.dab-profile-title{font-size:14px;font-weight:650}
|
|
438
|
+
.dab-profile-desc{font-size:12px;color:var(--dsw-alias-label-tertiary);line-height:1.55;margin:5px 0 15px}
|
|
439
|
+
.dab-footer{margin-top:6px;padding:14px 4px 0;border-top:1px solid var(--dsw-alias-border-l2);display:flex;align-items:center;justify-content:space-between;font-size:11px;color:var(--dsw-alias-label-tertiary)}
|
|
440
|
+
.dab-footer-mono{font-family:var(--dab-mono);letter-spacing:.02em}
|
|
441
|
+
|
|
442
|
+
/* ── toast ───────────────────────────────────────────────────────────────── */
|
|
443
|
+
.dab-toast{position:fixed;left:50%;bottom:30px;transform:translateX(-50%);display:flex;align-items:center;gap:8px;height:38px;padding:0 16px;border-radius:99px;background:var(--dsw-alias-bg-layer-3,var(--dsw-alias-bg-layer-2));border:1px solid var(--dsw-alias-border-l2);box-shadow:0 10px 30px -8px rgba(0,0,0,.38);font-size:12.5px;z-index:10001;animation:dab-toast-in .32s cubic-bezier(.22,1,.36,1) both}
|
|
444
|
+
.dab-toast-ok{color:var(--dsw-alias-brand-primary);display:grid;place-items:center}
|
|
445
|
+
.dab-toast-err{color:var(--dsw-alias-state-error-primary);display:grid;place-items:center}
|
|
446
|
+
|
|
447
|
+
/* ── modals (editor / eyedropper / crash) ────────────────────────────────── */
|
|
448
|
+
/* Pin to the viewport explicitly with vw/vh so ancestor padding/margins on
|
|
449
|
+
* body cannot shift or clip the overlay; keep it above host sidebar chrome.
|
|
450
|
+
* pointer-events:auto re-enables interaction: these overlays render inside a
|
|
451
|
+
* Portal root that is pointer-events:none so it never blocks the page alone. */
|
|
452
|
+
.dab-overlay{position:fixed;left:0;top:0;width:100vw;height:100vh;z-index:999999;background:rgba(8,10,14,.62);backdrop-filter:blur(8px);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:14px;animation:dab-fade-in .25s ease both;pointer-events:auto}
|
|
453
|
+
.dab-overlay-title{color:#fff;font-size:15px;font-weight:600}
|
|
454
|
+
.dab-overlay-hint{color:rgba(255,255,255,.62);font-size:12px}
|
|
455
|
+
.dab-modal-card{animation:dab-zoom-in .3s cubic-bezier(.22,1,.36,1) both;max-width:calc(100vw - 40px);max-height:calc(100vh - 120px);overflow:auto}
|
|
456
|
+
.dab-overlay .dab-btn{background:rgba(255,255,255,.94);color:#14161a;border-color:transparent}
|
|
457
|
+
.dab-overlay .dab-btn-primary{background:var(--dsw-alias-brand-primary);color:var(--dsw-alias-brand-text)}
|
|
458
|
+
.dab-crash{display:flex;flex-direction:column;gap:10px;align-items:center;padding:28px 18px;border:1px solid var(--dsw-alias-border-l2);border-radius:16px}
|
|
459
|
+
.dab-crash-title{font-size:15px;font-weight:650}
|
|
460
|
+
.dab-crash-desc{font-size:12px;color:var(--dsw-alias-label-tertiary);text-align:center;line-height:1.5}
|
|
461
|
+
|
|
462
|
+
/* ── model rules ─────────────────────────────────────────────────────────── */
|
|
463
|
+
.dab-rules{display:flex;flex-direction:column;gap:12px}
|
|
464
|
+
.dab-rule{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);border-radius:16px;padding:14px;transition:border-color .25s,box-shadow .25s,opacity .25s}
|
|
465
|
+
.dab-rule.is-active{border-color:var(--dsw-alias-brand-primary);box-shadow:0 0 0 3px color-mix(in srgb,var(--dsw-alias-brand-primary) 16%,transparent)}
|
|
466
|
+
.dab-rule.is-off{opacity:.55}
|
|
467
|
+
.dab-rule-head{display:flex;align-items:center;gap:9px;flex-wrap:wrap}
|
|
468
|
+
.dab-rule-num{font-family:var(--dab-mono);font-size:11px;font-weight:700;color:var(--dsw-alias-label-tertiary);min-width:16px}
|
|
469
|
+
.dab-rule-badge{font-size:10px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--dsw-alias-brand-primary);background:color-mix(in srgb,var(--dsw-alias-brand-primary) 14%,transparent);border-radius:99px;padding:2px 8px}
|
|
470
|
+
.dab-rule-match{flex:1;min-width:150px;height:32px;padding:0 11px;border-radius:9px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font-family:var(--dab-mono);font-size:12.5px;outline:none;transition:border-color .2s,box-shadow .2s}
|
|
471
|
+
.dab-rule-match::placeholder{color:var(--dsw-alias-label-quaternary)}
|
|
472
|
+
.dab-rule-match:focus{border-color:var(--dsw-alias-brand-primary);box-shadow:0 0 0 3px color-mix(in srgb,var(--dsw-alias-brand-primary) 18%,transparent)}
|
|
473
|
+
.dab-icon-btn{width:28px;height:28px;flex:none;display:grid;place-items:center;border-radius:8px;border:1px solid var(--dsw-alias-border-l2);background:transparent;color:var(--dsw-alias-label-tertiary);cursor:pointer;transition:color .2s,border-color .2s,background .2s}
|
|
474
|
+
.dab-icon-btn:hover:not(:disabled){color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-brand-primary)}
|
|
475
|
+
.dab-icon-btn:disabled{opacity:.35;cursor:not-allowed}
|
|
476
|
+
.dab-icon-btn-danger:hover:not(:disabled){color:var(--dsw-alias-state-error-primary);border-color:var(--dsw-alias-state-error-primary)}
|
|
477
|
+
.dab-rule-body{margin-top:13px;display:flex;flex-direction:column;gap:13px}
|
|
478
|
+
.dab-rule-thumb{position:relative;border-radius:12px;overflow:hidden;aspect-ratio:16/9;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);cursor:pointer}
|
|
479
|
+
.dab-rule-thumb img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
|
|
480
|
+
.dab-rule-thumb-empty{position:absolute;inset:5px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;border:1.5px dashed var(--dsw-alias-border-l2);border-radius:9px;color:var(--dsw-alias-label-tertiary);font-size:12px;text-align:center;padding:0 10px}
|
|
481
|
+
.dab-rule-thumb.is-over .dab-rule-thumb-empty{border-color:var(--dsw-alias-brand-primary);color:var(--dsw-alias-brand-primary)}
|
|
482
|
+
.dab-rule-cols{display:grid;grid-template-columns:minmax(0,1.15fr) minmax(0,1fr);gap:18px;align-items:start}
|
|
483
|
+
.dab-rule-section-title{font-size:12px;font-weight:600;margin-bottom:9px;color:var(--dsw-alias-label-secondary,var(--dsw-alias-label-tertiary))}
|
|
484
|
+
@container (max-width:760px){.dab-rule-cols{grid-template-columns:1fr}}
|
|
485
|
+
|
|
486
|
+
/* ── host self-check ─────────────────────────────────────────────────────── */
|
|
487
|
+
.dab-verdict{display:flex;flex-direction:column;gap:14px;position:relative;overflow:hidden}
|
|
488
|
+
.dab-verdict::after{content:'';position:absolute;inset:0;pointer-events:none;opacity:.5;background:linear-gradient(120deg,transparent 55%,color-mix(in srgb,var(--dab-verdict-tone,transparent) 26%,transparent))}
|
|
489
|
+
.dab-verdict-ok{--dab-verdict-tone:var(--dsw-alias-state-success-primary,var(--dsw-alias-brand-primary));border-color:color-mix(in srgb,var(--dsw-alias-state-success-primary,var(--dsw-alias-brand-primary)) 38%,var(--dsw-alias-border-l2))}
|
|
490
|
+
.dab-verdict-partial,.dab-verdict-broken{--dab-verdict-tone:var(--dsw-alias-state-error-primary);border-color:color-mix(in srgb,var(--dsw-alias-state-error-primary) 40%,var(--dsw-alias-border-l2))}
|
|
491
|
+
.dab-verdict-unknown{--dab-verdict-tone:var(--dsw-alias-label-tertiary)}
|
|
492
|
+
.dab-verdict-head{display:flex;align-items:center;gap:13px;flex-wrap:wrap}
|
|
493
|
+
.dab-verdict-ico{width:34px;height:34px;flex:none;border-radius:11px;display:grid;place-items:center;color:var(--dsw-alias-label-tertiary);background:var(--dsw-alias-bg-layer-2)}
|
|
494
|
+
.dab-verdict-ico-ok{color:var(--dsw-alias-state-success-primary,var(--dsw-alias-brand-primary));background:color-mix(in srgb,var(--dsw-alias-state-success-primary,var(--dsw-alias-brand-primary)) 14%,transparent)}
|
|
495
|
+
.dab-verdict-ico-partial,.dab-verdict-ico-broken{color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 14%,transparent)}
|
|
496
|
+
.dab-verdict-text{flex:1;min-width:170px}
|
|
497
|
+
.dab-verdict-title{font-size:14.5px;font-weight:650}
|
|
498
|
+
.dab-verdict-sub{margin-top:4px;font-size:12px;color:var(--dsw-alias-label-tertiary)}
|
|
499
|
+
.dab-verdict-actions{display:flex;gap:8px;flex-wrap:wrap;margin-left:auto}
|
|
500
|
+
.dab-facts{display:flex;flex-wrap:wrap;gap:8px;position:relative;z-index:1}
|
|
501
|
+
.dab-fact{display:inline-flex;align-items:center;gap:7px;height:27px;padding:0 11px;border-radius:99px;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);max-width:100%}
|
|
502
|
+
.dab-fact.is-bad{border-color:color-mix(in srgb,var(--dsw-alias-state-error-primary) 45%,transparent);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 10%,transparent)}
|
|
503
|
+
.dab-fact-k{font-size:10.5px;font-weight:650;letter-spacing:.06em;text-transform:uppercase;color:var(--dsw-alias-label-tertiary);white-space:nowrap}
|
|
504
|
+
.dab-fact-v{font-family:var(--dab-mono);font-size:11.5px;color:var(--dsw-alias-label-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:32ch}
|
|
505
|
+
.dab-check-group-title{display:flex;align-items:center;gap:9px;font-size:12.5px;font-weight:650;margin-bottom:11px}
|
|
506
|
+
.dab-check-group-count{margin-left:auto;font-family:var(--dab-mono);font-size:11px;font-weight:500;color:var(--dsw-alias-label-tertiary);background:var(--dsw-alias-bg-layer-2);border-radius:99px;padding:3px 9px}
|
|
507
|
+
.dab-checks{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:2px}
|
|
508
|
+
.dab-check{display:flex;gap:10px;padding:9px 10px;border-radius:11px;transition:background .2s ease}
|
|
509
|
+
.dab-check:hover{background:var(--dsw-alias-bg-layer-2)}
|
|
510
|
+
.dab-check-ico{width:19px;height:19px;flex:none;margin-top:1px;border-radius:50%;display:grid;place-items:center;color:var(--dsw-alias-label-tertiary);background:var(--dsw-alias-bg-layer-2)}
|
|
511
|
+
.dab-check-ico-pass{color:var(--dsw-alias-state-success-primary,var(--dsw-alias-brand-primary));background:color-mix(in srgb,var(--dsw-alias-state-success-primary,var(--dsw-alias-brand-primary)) 15%,transparent)}
|
|
512
|
+
.dab-check-ico-fail{color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 15%,transparent)}
|
|
513
|
+
.dab-check-dot{width:5px;height:5px;border-radius:50%;background:currentColor;opacity:.65}
|
|
514
|
+
.dab-check-body{min-width:0;flex:1;display:flex;flex-direction:column;gap:3px}
|
|
515
|
+
.dab-check-head{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap}
|
|
516
|
+
.dab-check-label{font-size:12.5px;font-weight:600}
|
|
517
|
+
.dab-check-status{font-size:10px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;padding:1px 7px;border-radius:99px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-tertiary)}
|
|
518
|
+
.dab-check-status-pass{color:var(--dsw-alias-state-success-primary,var(--dsw-alias-brand-primary));background:color-mix(in srgb,var(--dsw-alias-state-success-primary,var(--dsw-alias-brand-primary)) 14%,transparent)}
|
|
519
|
+
.dab-check-status-fail{color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 14%,transparent)}
|
|
520
|
+
.dab-check-target{font-family:var(--dab-mono);font-size:10.5px;color:var(--dsw-alias-label-tertiary);background:var(--dsw-alias-bg-layer-2);border-radius:6px;padding:1px 6px;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
521
|
+
.dab-check-detail{font-family:var(--dab-mono);font-size:11px;color:var(--dsw-alias-label-tertiary);line-height:1.5;overflow-wrap:anywhere}
|
|
522
|
+
.dab-check-reason{display:flex;flex-direction:column;gap:5px;font-size:12px;line-height:1.55;color:var(--dsw-alias-label-secondary,var(--dsw-alias-label-tertiary))}
|
|
523
|
+
.dab-check-symptom{color:var(--dsw-alias-state-error-primary)}
|
|
524
|
+
.dab-check-where{display:flex;gap:7px;align-items:baseline;flex-wrap:wrap;font-size:11px;color:var(--dsw-alias-label-tertiary)}
|
|
525
|
+
.dab-check-where code{font-family:var(--dab-mono);font-size:10.5px;overflow-wrap:anywhere}
|
|
526
|
+
.dab-check-note{margin:12px 0 0;font-size:11.5px;line-height:1.55;color:var(--dsw-alias-label-tertiary);position:relative;z-index:1}
|
|
527
|
+
|
|
528
|
+
/* ── keyframes ───────────────────────────────────────────────────────────── */
|
|
529
|
+
@keyframes dab-fade-in{from{opacity:0}to{opacity:1}}
|
|
530
|
+
@keyframes dab-page-in{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}
|
|
531
|
+
@keyframes dab-rise-in{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
|
|
532
|
+
@keyframes dab-orb-in{from{opacity:0;transform:scale(.82)}to{opacity:1;transform:none}}
|
|
533
|
+
@keyframes dab-spin{to{transform:rotate(360deg)}}
|
|
534
|
+
@keyframes dab-rotate{to{transform:rotate(360deg)}}
|
|
535
|
+
@keyframes dab-toast-in{from{opacity:0;transform:translate(-50%,10px)}to{opacity:1;transform:translate(-50%,0)}}
|
|
536
|
+
@keyframes dab-zoom-in{from{opacity:0;transform:scale(.94) translateY(8px)}to{opacity:1;transform:none}}
|
|
537
|
+
@keyframes dab-flow{to{background-position:300% 50%}}
|
|
538
|
+
|
|
539
|
+
/* ── responsive & motion preferences ─────────────────────────────────────── */
|
|
540
|
+
@container (max-width:620px){
|
|
541
|
+
.dab-shell{grid-template-columns:1fr;gap:14px}
|
|
542
|
+
.dab-nav{position:static;flex-direction:row;align-items:center;justify-content:space-between;gap:10px}
|
|
543
|
+
.dab-nav-list{flex-direction:row;overflow-x:auto;scrollbar-width:none}
|
|
544
|
+
.dab-nav-list::-webkit-scrollbar{display:none}
|
|
545
|
+
.dab-nav-ind{display:none}
|
|
546
|
+
.dab-nav-item{flex:none;padding:0 10px}
|
|
547
|
+
.dab-nav-item.is-active{background:var(--dsw-alias-bg-layer-2)}
|
|
548
|
+
.dab-types{grid-template-columns:1fr}
|
|
549
|
+
.dab-verdict-actions{margin-left:0;width:100%}
|
|
550
|
+
.dab-verdict-actions .dab-btn{flex:1}
|
|
551
|
+
}
|
|
552
|
+
@container (min-width:621px){
|
|
553
|
+
.dab-shell{grid-template-columns:158px minmax(0,1fr);gap:26px}
|
|
554
|
+
}
|
|
555
|
+
@media (prefers-reduced-motion:reduce){
|
|
556
|
+
.dab-root *,.dab-root *::before,.dab-root *::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}
|
|
557
|
+
}
|
|
558
|
+
`;
|
|
559
|
+
//#endregion
|
|
560
|
+
export { CONTRACT_GROUPS, DSH_FLOOR, HOST_CONTRACTS, UI_CSS, browserEnv, checkHostOnDisk, labelOf, meetsFloor, probeContracts, reportToMarkdown, resolveHostRoots, symptomOf, verdictOf, versionOf };
|