qa-engineer 0.10.0 → 0.12.0
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 +167 -59
- package/package.json +1 -1
- package/packages/engine/bin/qa-engine.mjs +232 -8
- package/packages/engine/lib/analysis/har.mjs +34 -0
- package/packages/engine/lib/analysis/network.mjs +237 -0
- package/packages/engine/lib/analysis/report-html.mjs +47 -734
- package/packages/engine/lib/artifacts/manager.mjs +453 -0
- package/packages/engine/lib/artifacts/mime.mjs +109 -0
- package/packages/engine/lib/artifacts/zip-write.mjs +143 -0
- package/packages/engine/lib/report/components/charts.mjs +424 -0
- package/packages/engine/lib/report/components/evidence.mjs +207 -0
- package/packages/engine/lib/report/components/findings.mjs +258 -0
- package/packages/engine/lib/report/components/nav.mjs +99 -0
- package/packages/engine/lib/report/components/primitives.mjs +246 -0
- package/packages/engine/lib/report/components/runtime.mjs +246 -0
- package/packages/engine/lib/report/components/timeline.mjs +65 -0
- package/packages/engine/lib/report/core/model.mjs +270 -0
- package/packages/engine/lib/report/core/normalize.mjs +226 -0
- package/packages/engine/lib/report/core/sections.mjs +978 -0
- package/packages/engine/lib/report/export/bundle.mjs +293 -0
- package/packages/engine/lib/report/export/html.mjs +183 -0
- package/packages/engine/lib/report/export/machine.mjs +290 -0
- package/packages/engine/lib/report/export/markdown.mjs +323 -0
- package/packages/engine/lib/report/schemas/qa-report.schema.json +555 -0
- package/packages/engine/lib/report/theme/css.mjs +529 -0
- package/packages/engine/lib/report/theme/tokens.mjs +137 -0
- package/packages/engine/lib/report/version.mjs +78 -0
- package/packages/engine/package.json +2 -2
- package/packages/installer/lib/agents/targets.mjs +90 -0
- package/packages/installer/lib/agents/user-level.mjs +80 -0
- package/packages/installer/lib/cli/flags.mjs +20 -2
- package/packages/installer/lib/commands/doctor.mjs +6 -4
- package/packages/installer/lib/commands/install.mjs +134 -93
- package/packages/installer/lib/commands/repair.mjs +10 -6
- package/packages/installer/lib/commands/self-test.mjs +4 -3
- package/packages/installer/lib/commands/uninstall.mjs +14 -8
- package/packages/installer/lib/commands/update.mjs +9 -4
- package/packages/installer/lib/commands/verify.mjs +13 -12
- package/packages/installer/lib/constants.mjs +13 -0
- package/packages/installer/lib/core/conflict.mjs +5 -4
- package/packages/installer/lib/core/fs-safe.mjs +146 -6
- package/packages/installer/lib/core/integrity.mjs +59 -0
- package/packages/installer/lib/core/lockfile.mjs +19 -3
- package/packages/installer/lib/core/plan.mjs +213 -0
- package/packages/installer/lib/core/qa-home.mjs +145 -0
- package/packages/installer/lib/core/scope.mjs +274 -0
- package/packages/installer/lib/core/validate-install.mjs +37 -12
- package/packages/installer/package.json +1 -1
- package/packages/installer/schemas/qa-lock.schema.json +119 -21
- package/shared/tooling/qa-tool.mjs +41 -5
- package/skills/qa-api/scripts/qa-tool.mjs +41 -5
- package/skills/qa-audit/scripts/qa-tool.mjs +41 -5
- package/skills/qa-debug/SKILL.md +3 -0
- package/skills/qa-debug/references/failure-handoff.md +44 -0
- package/skills/qa-debug/scripts/qa-tool.mjs +41 -5
- package/skills/qa-explore/SKILL.md +26 -10
- package/skills/qa-explore/contracts/explore-result.schema.json +517 -11
- package/skills/qa-explore/references/api-replay.md +40 -1
- package/skills/qa-explore/references/report-pipeline.md +265 -95
- package/skills/qa-explore/scripts/qa-tool.mjs +41 -5
- package/skills/qa-fix/scripts/qa-tool.mjs +41 -5
- package/skills/qa-flaky/scripts/qa-tool.mjs +41 -5
- package/skills/qa-init/scripts/qa-tool.mjs +41 -5
- package/skills/qa-report/scripts/qa-tool.mjs +41 -5
- package/skills/qa-run/README.md +7 -0
- package/skills/qa-run/SKILL.md +12 -7
- package/skills/qa-run/contracts/execution-result.schema.json +77 -0
- package/skills/qa-run/examples/execute-playwright.md +42 -10
- package/skills/qa-run/examples/plan-a-run.md +5 -3
- package/skills/qa-run/references/artifact-collector.md +2 -1
- package/skills/qa-run/references/command-builder.md +18 -1
- package/skills/qa-run/references/execution-strategy.md +2 -0
- package/skills/qa-run/references/failure-handoff.md +44 -0
- package/skills/qa-run/references/playwright-artifacts.md +3 -1
- package/skills/qa-run/references/playwright-execution.md +14 -1
- package/skills/qa-run/scripts/qa-tool.mjs +41 -5
|
@@ -0,0 +1,529 @@
|
|
|
1
|
+
// The report stylesheet, emitted as one inline <style>.
|
|
2
|
+
//
|
|
3
|
+
// Inline and self-contained is a hard requirement, not a preference: a QA report is
|
|
4
|
+
// forwarded as an attachment and opened on a plane, from a `file://` path, inside a
|
|
5
|
+
// corporate mail client that blocks remote content. A CDN stylesheet or a web font
|
|
6
|
+
// turns a premium report into unstyled text at exactly the moment it is being read
|
|
7
|
+
// by the person who matters most.
|
|
8
|
+
//
|
|
9
|
+
// So: system font stack, no @import, no external asset, and every colour derived
|
|
10
|
+
// from tokens.mjs so the badges, the charts, and the score gauges cannot disagree.
|
|
11
|
+
//
|
|
12
|
+
// ## Three renderings, one document
|
|
13
|
+
//
|
|
14
|
+
// screen light — the default, driven by prefers-color-scheme
|
|
15
|
+
// screen dark — the same tokens at a different luminance
|
|
16
|
+
// print — glass and shadow removed, cards forced open, links given their href
|
|
17
|
+
//
|
|
18
|
+
// The theme toggle writes `data-theme` on <html>, and those rules are last so a
|
|
19
|
+
// reader's explicit choice beats their OS setting in both directions.
|
|
20
|
+
|
|
21
|
+
import { SEVERITY, STATUS, TONE, SEVERITY_ORDER } from './tokens.mjs';
|
|
22
|
+
|
|
23
|
+
/** Per-severity badge and accent rules, generated so a new severity cannot be missed. */
|
|
24
|
+
function severityRules() {
|
|
25
|
+
const out = [];
|
|
26
|
+
for (const key of SEVERITY_ORDER) {
|
|
27
|
+
const { light, dark } = SEVERITY[key];
|
|
28
|
+
out.push(
|
|
29
|
+
`.sev-${key}{--sev-fg:${light.fg};--sev-bg:${light.bg};--sev-border:${light.border};--sev-solid:${light.solid}}`,
|
|
30
|
+
);
|
|
31
|
+
out.push(
|
|
32
|
+
`[data-theme="dark"] .sev-${key}{--sev-fg:${dark.fg};--sev-bg:${dark.bg};--sev-border:${dark.border};--sev-solid:${dark.solid}}`,
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
out.push('@media (prefers-color-scheme:dark){');
|
|
36
|
+
for (const key of SEVERITY_ORDER) {
|
|
37
|
+
const { dark } = SEVERITY[key];
|
|
38
|
+
out.push(
|
|
39
|
+
`:root:not([data-theme="light"]) .sev-${key}{--sev-fg:${dark.fg};--sev-bg:${dark.bg};--sev-border:${dark.border};--sev-solid:${dark.solid}}`,
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
out.push('}');
|
|
43
|
+
return out.join('');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** The same treatment for pass/fail/blocked/skipped chips. */
|
|
47
|
+
function statusRules() {
|
|
48
|
+
const out = [];
|
|
49
|
+
for (const [key, value] of Object.entries(STATUS)) {
|
|
50
|
+
out.push(`.st-${key}{--st-fg:${value.light.fg};--st-bg:${value.light.bg};--st-solid:${value.light.solid}}`);
|
|
51
|
+
out.push(`[data-theme="dark"] .st-${key}{--st-fg:${value.dark.fg};--st-bg:${value.dark.bg};--st-solid:${value.dark.solid}}`);
|
|
52
|
+
}
|
|
53
|
+
out.push('@media (prefers-color-scheme:dark){');
|
|
54
|
+
for (const [key, value] of Object.entries(STATUS)) {
|
|
55
|
+
out.push(`:root:not([data-theme="light"]) .st-${key}{--st-fg:${value.dark.fg};--st-bg:${value.dark.bg};--st-solid:${value.dark.solid}}`);
|
|
56
|
+
}
|
|
57
|
+
out.push('}');
|
|
58
|
+
return out.join('');
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** Tone rules for scores, gauges, and the verdict surface. */
|
|
62
|
+
function toneRules() {
|
|
63
|
+
const out = [];
|
|
64
|
+
for (const [key, value] of Object.entries(TONE)) {
|
|
65
|
+
out.push(`.tone-${key}{--tone:${value.light}}`);
|
|
66
|
+
out.push(`[data-theme="dark"] .tone-${key}{--tone:${value.dark}}`);
|
|
67
|
+
}
|
|
68
|
+
out.push('@media (prefers-color-scheme:dark){');
|
|
69
|
+
for (const [key, value] of Object.entries(TONE)) {
|
|
70
|
+
out.push(`:root:not([data-theme="light"]) .tone-${key}{--tone:${value.dark}}`);
|
|
71
|
+
}
|
|
72
|
+
out.push('}');
|
|
73
|
+
return out.join('');
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const LIGHT_TOKENS = `
|
|
77
|
+
--bg:#f4f5f8;
|
|
78
|
+
--bg-mesh-a:rgba(83,68,232,.10);
|
|
79
|
+
--bg-mesh-b:rgba(11,165,236,.09);
|
|
80
|
+
--bg-mesh-c:rgba(238,70,188,.06);
|
|
81
|
+
--surface:rgba(255,255,255,.76);
|
|
82
|
+
--surface-solid:#ffffff;
|
|
83
|
+
--surface-raised:rgba(255,255,255,.92);
|
|
84
|
+
--surface-sunken:rgba(16,24,40,.03);
|
|
85
|
+
--border:rgba(16,24,40,.09);
|
|
86
|
+
--border-strong:rgba(16,24,40,.16);
|
|
87
|
+
--text:#0d1117;
|
|
88
|
+
--text-soft:#3c4658;
|
|
89
|
+
--text-muted:#667085;
|
|
90
|
+
--accent:#5344e8;
|
|
91
|
+
--accent-soft:rgba(83,68,232,.10);
|
|
92
|
+
--accent-contrast:#ffffff;
|
|
93
|
+
--shadow-sm:0 1px 2px rgba(16,24,40,.05);
|
|
94
|
+
--shadow-md:0 4px 16px -4px rgba(16,24,40,.10),0 2px 4px -2px rgba(16,24,40,.05);
|
|
95
|
+
--shadow-lg:0 20px 44px -12px rgba(16,24,40,.16);
|
|
96
|
+
--code-bg:rgba(16,24,40,.05);
|
|
97
|
+
--pre-bg:#10141c;
|
|
98
|
+
--pre-fg:#dfe4ec;
|
|
99
|
+
--glass-blur:saturate(180%) blur(18px);
|
|
100
|
+
`;
|
|
101
|
+
|
|
102
|
+
const DARK_TOKENS = `
|
|
103
|
+
--bg:#080b12;
|
|
104
|
+
--bg-mesh-a:rgba(83,68,232,.22);
|
|
105
|
+
--bg-mesh-b:rgba(11,165,236,.16);
|
|
106
|
+
--bg-mesh-c:rgba(238,70,188,.10);
|
|
107
|
+
--surface:rgba(20,26,38,.68);
|
|
108
|
+
--surface-solid:#111725;
|
|
109
|
+
--surface-raised:rgba(28,35,50,.82);
|
|
110
|
+
--surface-sunken:rgba(255,255,255,.035);
|
|
111
|
+
--border:rgba(255,255,255,.10);
|
|
112
|
+
--border-strong:rgba(255,255,255,.20);
|
|
113
|
+
--text:#eef1f7;
|
|
114
|
+
--text-soft:#b9c2d3;
|
|
115
|
+
--text-muted:#8792a8;
|
|
116
|
+
--accent:#9b8afb;
|
|
117
|
+
--accent-soft:rgba(155,138,251,.16);
|
|
118
|
+
--accent-contrast:#0b0e16;
|
|
119
|
+
--shadow-sm:0 1px 2px rgba(0,0,0,.4);
|
|
120
|
+
--shadow-md:0 8px 24px -8px rgba(0,0,0,.6);
|
|
121
|
+
--shadow-lg:0 24px 56px -16px rgba(0,0,0,.7);
|
|
122
|
+
--code-bg:rgba(255,255,255,.07);
|
|
123
|
+
--pre-bg:#05070c;
|
|
124
|
+
--pre-fg:#d5dcea;
|
|
125
|
+
--glass-blur:saturate(150%) blur(18px);
|
|
126
|
+
`;
|
|
127
|
+
|
|
128
|
+
/** The complete stylesheet. */
|
|
129
|
+
export function stylesheet() {
|
|
130
|
+
return `
|
|
131
|
+
*,*::before,*::after{box-sizing:border-box}
|
|
132
|
+
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth;scroll-padding-top:1.5rem}
|
|
133
|
+
:root{
|
|
134
|
+
${LIGHT_TOKENS}
|
|
135
|
+
--radius-sm:8px;--radius:14px;--radius-lg:20px;
|
|
136
|
+
--sp-1:.25rem;--sp-2:.5rem;--sp-3:.75rem;--sp-4:1rem;--sp-5:1.5rem;--sp-6:2rem;--sp-7:3rem;
|
|
137
|
+
--font:-apple-system,BlinkMacSystemFont,"Segoe UI",Inter,Roboto,"Helvetica Neue",Arial,sans-serif;
|
|
138
|
+
--mono:ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,"Liberation Mono",monospace;
|
|
139
|
+
--ease:cubic-bezier(.22,.61,.36,1);
|
|
140
|
+
--sidebar-w:16rem;
|
|
141
|
+
color-scheme:light dark;
|
|
142
|
+
}
|
|
143
|
+
[data-theme="dark"]{${DARK_TOKENS}}
|
|
144
|
+
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]){${DARK_TOKENS}}}
|
|
145
|
+
${severityRules()}
|
|
146
|
+
${statusRules()}
|
|
147
|
+
${toneRules()}
|
|
148
|
+
|
|
149
|
+
body{
|
|
150
|
+
margin:0;background:var(--bg);color:var(--text);
|
|
151
|
+
font:400 15px/1.65 var(--font);letter-spacing:-.005em;
|
|
152
|
+
-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;
|
|
153
|
+
text-rendering:optimizeLegibility;
|
|
154
|
+
}
|
|
155
|
+
/* A single painted mesh rather than three stacked elements: it is decorative, it
|
|
156
|
+
must not intercept a click, and it must vanish for print. */
|
|
157
|
+
body::before{
|
|
158
|
+
content:"";position:fixed;inset:0;z-index:-1;pointer-events:none;
|
|
159
|
+
background:
|
|
160
|
+
radial-gradient(60rem 40rem at 12% -8%,var(--bg-mesh-a),transparent 60%),
|
|
161
|
+
radial-gradient(50rem 36rem at 96% 4%,var(--bg-mesh-b),transparent 58%),
|
|
162
|
+
radial-gradient(44rem 34rem at 50% 108%,var(--bg-mesh-c),transparent 62%);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/* ── Layout ─────────────────────────────────────────────────────────────── */
|
|
166
|
+
.shell{display:grid;grid-template-columns:var(--sidebar-w) minmax(0,1fr);gap:var(--sp-6);
|
|
167
|
+
max-width:96rem;margin:0 auto;padding:var(--sp-5) var(--sp-5) var(--sp-7)}
|
|
168
|
+
.main{min-width:0}
|
|
169
|
+
.section{scroll-margin-top:1.5rem;margin-bottom:var(--sp-7)}
|
|
170
|
+
.section:last-child{margin-bottom:var(--sp-5)}
|
|
171
|
+
|
|
172
|
+
/* ── Sidebar ────────────────────────────────────────────────────────────── */
|
|
173
|
+
.sidebar{position:sticky;top:var(--sp-5);align-self:start;max-height:calc(100vh - 3rem);
|
|
174
|
+
display:flex;flex-direction:column;gap:var(--sp-4);overflow:auto;padding-bottom:var(--sp-4)}
|
|
175
|
+
.sidebar-brand{display:flex;align-items:center;gap:.625rem;padding:0 .375rem}
|
|
176
|
+
.sidebar-mark{width:1.75rem;height:1.75rem;border-radius:9px;flex:none;
|
|
177
|
+
background:linear-gradient(135deg,var(--accent),#0ba5ec);
|
|
178
|
+
display:grid;place-items:center;color:#fff;font-weight:800;font-size:.75rem;letter-spacing:0}
|
|
179
|
+
.sidebar-name{font-weight:650;font-size:.875rem;letter-spacing:-.01em}
|
|
180
|
+
.sidebar-sub{font-size:.6875rem;color:var(--text-muted)}
|
|
181
|
+
nav.toc{display:flex;flex-direction:column;gap:1px}
|
|
182
|
+
nav.toc a{display:flex;align-items:center;justify-content:space-between;gap:.5rem;
|
|
183
|
+
padding:.4375rem .625rem;border-radius:var(--radius-sm);color:var(--text-soft);
|
|
184
|
+
text-decoration:none;font-size:.8125rem;font-weight:500;
|
|
185
|
+
transition:background .16s var(--ease),color .16s var(--ease)}
|
|
186
|
+
nav.toc a:hover{background:var(--surface-sunken);color:var(--text)}
|
|
187
|
+
nav.toc a.active{background:var(--accent-soft);color:var(--accent);font-weight:600}
|
|
188
|
+
nav.toc .n{font-variant-numeric:tabular-nums;font-size:.6875rem;color:var(--text-muted);
|
|
189
|
+
background:var(--surface-sunken);border-radius:20px;padding:.0625rem .375rem;min-width:1.375rem;text-align:center}
|
|
190
|
+
nav.toc a.active .n{background:transparent;color:inherit}
|
|
191
|
+
|
|
192
|
+
/* ── Glass surfaces ─────────────────────────────────────────────────────── */
|
|
193
|
+
.card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);
|
|
194
|
+
box-shadow:var(--shadow-sm);backdrop-filter:var(--glass-blur);-webkit-backdrop-filter:var(--glass-blur)}
|
|
195
|
+
.card+.card{margin-top:var(--sp-3)}
|
|
196
|
+
.card-body{padding:var(--sp-5)}
|
|
197
|
+
.card-tight{padding:var(--sp-4)}
|
|
198
|
+
|
|
199
|
+
/* ── Masthead ───────────────────────────────────────────────────────────── */
|
|
200
|
+
.masthead{position:relative;overflow:hidden;border-radius:var(--radius-lg);
|
|
201
|
+
border:1px solid var(--border);background:var(--surface-raised);
|
|
202
|
+
backdrop-filter:var(--glass-blur);-webkit-backdrop-filter:var(--glass-blur);
|
|
203
|
+
box-shadow:var(--shadow-md);padding:var(--sp-6);margin-bottom:var(--sp-5)}
|
|
204
|
+
.masthead::after{content:"";position:absolute;inset:0;pointer-events:none;
|
|
205
|
+
background:linear-gradient(120deg,var(--accent-soft),transparent 42%)}
|
|
206
|
+
.masthead>*{position:relative;z-index:1}
|
|
207
|
+
.eyebrow{display:inline-flex;align-items:center;gap:.5rem;font-size:.6875rem;font-weight:700;
|
|
208
|
+
letter-spacing:.1em;text-transform:uppercase;color:var(--accent)}
|
|
209
|
+
.eyebrow::before{content:"";width:.4375rem;height:.4375rem;border-radius:50%;background:currentColor;
|
|
210
|
+
box-shadow:0 0 0 3px var(--accent-soft)}
|
|
211
|
+
h1{margin:.75rem 0 .5rem;font-size:clamp(1.75rem,3.4vw,2.75rem);line-height:1.08;
|
|
212
|
+
letter-spacing:-.033em;font-weight:750}
|
|
213
|
+
.subject{color:var(--text-soft);font-size:1.0625rem;margin:0 0 var(--sp-4);max-width:56ch}
|
|
214
|
+
.subject a{color:var(--accent);text-decoration:none;border-bottom:1px solid var(--accent-soft)}
|
|
215
|
+
.subject a:hover{border-bottom-color:currentColor}
|
|
216
|
+
.factbar{display:flex;flex-wrap:wrap;gap:var(--sp-5) var(--sp-6);
|
|
217
|
+
padding-top:var(--sp-4);border-top:1px solid var(--border)}
|
|
218
|
+
.fact{min-width:7rem}
|
|
219
|
+
.fact dt{font-size:.625rem;font-weight:700;letter-spacing:.09em;text-transform:uppercase;
|
|
220
|
+
color:var(--text-muted);margin:0 0 .1875rem}
|
|
221
|
+
.fact dd{margin:0;font-size:.9375rem;font-weight:600;letter-spacing:-.01em}
|
|
222
|
+
|
|
223
|
+
/* ── Verdict ────────────────────────────────────────────────────────────── */
|
|
224
|
+
.verdict{display:flex;flex-wrap:wrap;align-items:center;gap:var(--sp-4);
|
|
225
|
+
margin:var(--sp-5) 0 0;padding:var(--sp-4) var(--sp-5);border-radius:var(--radius);
|
|
226
|
+
border:1px solid color-mix(in srgb,var(--tone) 38%,transparent);
|
|
227
|
+
background:color-mix(in srgb,var(--tone) 10%,transparent)}
|
|
228
|
+
.verdict-label{display:flex;align-items:center;gap:.5rem;font-size:1.0625rem;font-weight:750;
|
|
229
|
+
letter-spacing:-.015em;color:var(--tone)}
|
|
230
|
+
.verdict-dot{width:.625rem;height:.625rem;border-radius:50%;background:var(--tone);flex:none;
|
|
231
|
+
box-shadow:0 0 0 4px color-mix(in srgb,var(--tone) 22%,transparent)}
|
|
232
|
+
.verdict-blurb{color:var(--text-soft);font-size:.9375rem;flex:1 1 16rem;min-width:0}
|
|
233
|
+
.verdict-confidence{font-size:.75rem;color:var(--text-muted);font-variant-numeric:tabular-nums}
|
|
234
|
+
|
|
235
|
+
/* ── KPI grid ───────────────────────────────────────────────────────────── */
|
|
236
|
+
.kpis{display:grid;gap:var(--sp-3);grid-template-columns:repeat(auto-fill,minmax(9.5rem,1fr))}
|
|
237
|
+
.kpi{position:relative;overflow:hidden;padding:var(--sp-4);border-radius:var(--radius);
|
|
238
|
+
border:1px solid var(--border);background:var(--surface);
|
|
239
|
+
backdrop-filter:var(--glass-blur);-webkit-backdrop-filter:var(--glass-blur);
|
|
240
|
+
transition:transform .18s var(--ease),box-shadow .18s var(--ease),border-color .18s var(--ease)}
|
|
241
|
+
.kpi:hover{transform:translateY(-2px);box-shadow:var(--shadow-md);border-color:var(--border-strong)}
|
|
242
|
+
.kpi::before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;
|
|
243
|
+
background:var(--kpi-accent,var(--border-strong))}
|
|
244
|
+
.kpi.sev .kpi-n{color:var(--sev-solid)}
|
|
245
|
+
.kpi.sev{--kpi-accent:var(--sev-solid)}
|
|
246
|
+
.kpi.st .kpi-n{color:var(--st-solid)}
|
|
247
|
+
.kpi.st{--kpi-accent:var(--st-solid)}
|
|
248
|
+
.kpi-n{display:block;font-size:1.875rem;font-weight:750;line-height:1.05;letter-spacing:-.03em;
|
|
249
|
+
font-variant-numeric:tabular-nums}
|
|
250
|
+
.kpi-l{display:block;margin-top:.25rem;font-size:.6875rem;font-weight:650;letter-spacing:.07em;
|
|
251
|
+
text-transform:uppercase;color:var(--text-muted)}
|
|
252
|
+
.kpi-sub{display:block;margin-top:.1875rem;font-size:.75rem;color:var(--text-muted)}
|
|
253
|
+
.kpi-zero .kpi-n{color:var(--text-muted);opacity:.55}
|
|
254
|
+
|
|
255
|
+
/* ── Score gauges ───────────────────────────────────────────────────────── */
|
|
256
|
+
.scores{display:grid;gap:var(--sp-3);grid-template-columns:repeat(auto-fill,minmax(10rem,1fr))}
|
|
257
|
+
.score{display:flex;align-items:center;gap:var(--sp-3);padding:var(--sp-4);
|
|
258
|
+
border:1px solid var(--border);border-radius:var(--radius);background:var(--surface);
|
|
259
|
+
backdrop-filter:var(--glass-blur);-webkit-backdrop-filter:var(--glass-blur)}
|
|
260
|
+
.score svg{flex:none}
|
|
261
|
+
.score-l{font-size:.8125rem;font-weight:600}
|
|
262
|
+
.score-b{font-size:.6875rem;color:var(--text-muted);text-transform:uppercase;letter-spacing:.06em}
|
|
263
|
+
|
|
264
|
+
/* ── Headings ───────────────────────────────────────────────────────────── */
|
|
265
|
+
h2{margin:0 0 var(--sp-4);font-size:1.25rem;font-weight:700;letter-spacing:-.022em;
|
|
266
|
+
display:flex;align-items:baseline;gap:.625rem;flex-wrap:wrap}
|
|
267
|
+
h2 .count{font-size:.75rem;font-weight:600;color:var(--text-muted);
|
|
268
|
+
background:var(--surface-sunken);border:1px solid var(--border);
|
|
269
|
+
border-radius:20px;padding:.125rem .5rem;letter-spacing:0}
|
|
270
|
+
h3{margin:0;font-size:1rem;font-weight:650;letter-spacing:-.014em;line-height:1.4}
|
|
271
|
+
h4{margin:0 0 var(--sp-2);font-size:.6875rem;font-weight:700;letter-spacing:.09em;
|
|
272
|
+
text-transform:uppercase;color:var(--text-muted)}
|
|
273
|
+
.section-note{margin:calc(var(--sp-4) * -1 + .25rem) 0 var(--sp-4);color:var(--text-muted);
|
|
274
|
+
font-size:.875rem;max-width:70ch}
|
|
275
|
+
p{margin:0 0 var(--sp-3);max-width:78ch}
|
|
276
|
+
p:last-child{margin-bottom:0}
|
|
277
|
+
a{color:var(--accent)}
|
|
278
|
+
|
|
279
|
+
/* ── Badges & chips ─────────────────────────────────────────────────────── */
|
|
280
|
+
.badge{display:inline-flex;align-items:center;gap:.3125rem;padding:.1875rem .5rem;
|
|
281
|
+
border-radius:6px;font-size:.6875rem;font-weight:750;letter-spacing:.045em;
|
|
282
|
+
text-transform:uppercase;white-space:nowrap;
|
|
283
|
+
color:var(--sev-fg);background:var(--sev-bg);border:1px solid var(--sev-border)}
|
|
284
|
+
.badge::before{content:"";width:.375rem;height:.375rem;border-radius:50%;background:var(--sev-solid)}
|
|
285
|
+
.pill{display:inline-flex;align-items:center;gap:.3125rem;padding:.1875rem .5rem;border-radius:20px;
|
|
286
|
+
font-size:.6875rem;font-weight:650;white-space:nowrap;
|
|
287
|
+
color:var(--st-fg);background:var(--st-bg);border:1px solid transparent}
|
|
288
|
+
.chip{display:inline-flex;align-items:center;gap:.3125rem;padding:.1875rem .5rem;
|
|
289
|
+
border-radius:6px;background:var(--surface-sunken);border:1px solid var(--border);
|
|
290
|
+
color:var(--text-muted);font-size:.6875rem;font-weight:600;white-space:nowrap}
|
|
291
|
+
|
|
292
|
+
/* ── Toolbar ────────────────────────────────────────────────────────────── */
|
|
293
|
+
.toolbar{position:sticky;top:0;z-index:20;display:flex;flex-wrap:wrap;gap:var(--sp-2);
|
|
294
|
+
align-items:center;margin-bottom:var(--sp-4);padding:var(--sp-3);
|
|
295
|
+
border:1px solid var(--border);border-radius:var(--radius);background:var(--surface-raised);
|
|
296
|
+
backdrop-filter:var(--glass-blur);-webkit-backdrop-filter:var(--glass-blur);box-shadow:var(--shadow-sm)}
|
|
297
|
+
.search{flex:1 1 14rem;min-width:0;display:flex;align-items:center;gap:.5rem;
|
|
298
|
+
padding:.4375rem .625rem;border-radius:var(--radius-sm);
|
|
299
|
+
border:1px solid var(--border);background:var(--surface-sunken)}
|
|
300
|
+
.search svg{flex:none;color:var(--text-muted)}
|
|
301
|
+
.search input{flex:1;min-width:0;border:0;background:transparent;color:inherit;
|
|
302
|
+
font:inherit;font-size:.875rem;outline:none}
|
|
303
|
+
.search input::placeholder{color:var(--text-muted)}
|
|
304
|
+
.filters{display:flex;flex-wrap:wrap;gap:.25rem}
|
|
305
|
+
.filter{display:inline-flex;align-items:center;gap:.3125rem;padding:.3125rem .5625rem;
|
|
306
|
+
border-radius:20px;border:1px solid var(--border);background:transparent;color:var(--text-soft);
|
|
307
|
+
font:inherit;font-size:.75rem;font-weight:600;cursor:pointer;
|
|
308
|
+
transition:background .14s var(--ease),border-color .14s var(--ease),color .14s var(--ease)}
|
|
309
|
+
.filter:hover{border-color:var(--border-strong);background:var(--surface-sunken)}
|
|
310
|
+
.filter[aria-pressed="true"]{background:var(--accent);border-color:var(--accent);color:var(--accent-contrast)}
|
|
311
|
+
.filter .dot{width:.4375rem;height:.4375rem;border-radius:50%;background:var(--sev-solid,var(--text-muted))}
|
|
312
|
+
.filter[aria-pressed="true"] .dot{background:currentColor}
|
|
313
|
+
.iconbtn{display:inline-grid;place-items:center;width:2rem;height:2rem;flex:none;
|
|
314
|
+
border-radius:var(--radius-sm);border:1px solid var(--border);background:transparent;
|
|
315
|
+
color:var(--text-soft);cursor:pointer;transition:background .14s var(--ease),color .14s var(--ease)}
|
|
316
|
+
.iconbtn:hover{background:var(--surface-sunken);color:var(--text)}
|
|
317
|
+
.match-count{font-size:.75rem;color:var(--text-muted);font-variant-numeric:tabular-nums;
|
|
318
|
+
margin-left:auto;padding-left:.5rem}
|
|
319
|
+
|
|
320
|
+
/* ── Findings ───────────────────────────────────────────────────────────── */
|
|
321
|
+
.finding{border:1px solid var(--border);border-radius:var(--radius);background:var(--surface);
|
|
322
|
+
backdrop-filter:var(--glass-blur);-webkit-backdrop-filter:var(--glass-blur);
|
|
323
|
+
margin-bottom:var(--sp-3);overflow:hidden;scroll-margin-top:5rem;
|
|
324
|
+
transition:border-color .18s var(--ease),box-shadow .18s var(--ease)}
|
|
325
|
+
.finding:hover{border-color:var(--border-strong)}
|
|
326
|
+
.finding[open]{box-shadow:var(--shadow-md);border-color:var(--border-strong)}
|
|
327
|
+
.finding[hidden]{display:none}
|
|
328
|
+
.finding>summary{display:flex;align-items:flex-start;gap:var(--sp-3);padding:var(--sp-4);
|
|
329
|
+
cursor:pointer;list-style:none;user-select:none}
|
|
330
|
+
.finding>summary::-webkit-details-marker{display:none}
|
|
331
|
+
.finding>summary:focus-visible{outline:2px solid var(--accent);outline-offset:-2px;border-radius:var(--radius)}
|
|
332
|
+
.finding-grow{flex:1;min-width:0}
|
|
333
|
+
.finding-title{display:block;font-size:1rem;font-weight:650;letter-spacing:-.014em;line-height:1.4}
|
|
334
|
+
.finding-meta{display:flex;flex-wrap:wrap;align-items:center;gap:.375rem;margin-top:.4375rem}
|
|
335
|
+
.finding-id{font-family:var(--mono);font-size:.6875rem;color:var(--text-muted);letter-spacing:0}
|
|
336
|
+
.caret{flex:none;margin-top:.1875rem;color:var(--text-muted);transition:transform .2s var(--ease)}
|
|
337
|
+
.finding[open] .caret{transform:rotate(90deg)}
|
|
338
|
+
.finding-body{padding:0 var(--sp-4) var(--sp-4);border-top:1px solid var(--border)}
|
|
339
|
+
.finding-body>*:first-child{margin-top:var(--sp-4)}
|
|
340
|
+
|
|
341
|
+
.behaviour{margin:0;display:grid;grid-template-columns:minmax(7.5rem,auto) minmax(0,1fr);
|
|
342
|
+
gap:var(--sp-3) var(--sp-5)}
|
|
343
|
+
.behaviour dt{font-size:.625rem;font-weight:750;letter-spacing:.09em;text-transform:uppercase;
|
|
344
|
+
color:var(--text-muted);padding-top:.1875rem}
|
|
345
|
+
.behaviour dd{margin:0;min-width:0}
|
|
346
|
+
.rail{border-left:2px solid var(--rail,var(--border-strong));padding-left:var(--sp-3)}
|
|
347
|
+
.rail-now{--rail:var(--tone-bad,#f04438)}
|
|
348
|
+
.rail-want{--rail:#17b26a}
|
|
349
|
+
.rail-fix{--rail:var(--accent)}
|
|
350
|
+
.rail-impact{--rail:#f79009}
|
|
351
|
+
.rail-cause{--rail:#0ba5ec}
|
|
352
|
+
[data-theme="dark"] .rail-now{--rail:#f97066}
|
|
353
|
+
[data-theme="dark"] .rail-want{--rail:#47cd89}
|
|
354
|
+
@media (prefers-color-scheme:dark){
|
|
355
|
+
:root:not([data-theme="light"]) .rail-now{--rail:#f97066}
|
|
356
|
+
:root:not([data-theme="light"]) .rail-want{--rail:#47cd89}
|
|
357
|
+
}
|
|
358
|
+
ol.steps,ol.chain{margin:0;padding-left:1.25rem}
|
|
359
|
+
ol.steps li,ol.chain li{margin:.1875rem 0}
|
|
360
|
+
ol.chain li::marker{color:var(--text-muted);font-variant-numeric:tabular-nums}
|
|
361
|
+
ul.clean{margin:0;padding-left:1.125rem}
|
|
362
|
+
ul.clean li{margin:.25rem 0}
|
|
363
|
+
.subgrid{display:grid;gap:var(--sp-3);grid-template-columns:repeat(auto-fit,minmax(13rem,1fr));
|
|
364
|
+
margin-top:var(--sp-4)}
|
|
365
|
+
.panel{border:1px solid var(--border);border-radius:var(--radius-sm);padding:var(--sp-3);
|
|
366
|
+
background:var(--surface-sunken)}
|
|
367
|
+
.panel p{font-size:.875rem}
|
|
368
|
+
|
|
369
|
+
/* ── Tables ─────────────────────────────────────────────────────────────── */
|
|
370
|
+
.table-wrap{overflow-x:auto;border:1px solid var(--border);border-radius:var(--radius);
|
|
371
|
+
background:var(--surface);backdrop-filter:var(--glass-blur);-webkit-backdrop-filter:var(--glass-blur)}
|
|
372
|
+
table{border-collapse:collapse;width:100%;font-size:.8125rem;min-width:26rem}
|
|
373
|
+
th,td{text-align:left;padding:.625rem .75rem;border-bottom:1px solid var(--border);vertical-align:top}
|
|
374
|
+
th{font-size:.625rem;text-transform:uppercase;letter-spacing:.08em;color:var(--text-muted);
|
|
375
|
+
font-weight:750;background:var(--surface-sunken);position:sticky;top:0;white-space:nowrap}
|
|
376
|
+
tbody tr:last-child td{border-bottom:0}
|
|
377
|
+
tbody tr{transition:background .12s var(--ease)}
|
|
378
|
+
tbody tr:hover{background:var(--surface-sunken)}
|
|
379
|
+
td.num{text-align:right;font-variant-numeric:tabular-nums}
|
|
380
|
+
tr[hidden]{display:none}
|
|
381
|
+
.bar-cell{min-width:8rem}
|
|
382
|
+
.bar{height:.375rem;border-radius:3px;background:var(--surface-sunken);overflow:hidden}
|
|
383
|
+
.bar>span{display:block;height:100%;border-radius:3px;background:var(--bar,var(--accent))}
|
|
384
|
+
|
|
385
|
+
code{font-family:var(--mono);font-size:.8125em;background:var(--code-bg);
|
|
386
|
+
padding:.0625rem .3125rem;border-radius:5px;word-break:break-word}
|
|
387
|
+
pre{margin:0;background:var(--pre-bg);color:var(--pre-fg);padding:var(--sp-4);
|
|
388
|
+
border-radius:var(--radius-sm);overflow-x:auto;font:.75rem/1.6 var(--mono);
|
|
389
|
+
border:1px solid var(--border)}
|
|
390
|
+
pre code{background:none;padding:0;font-size:inherit;color:inherit}
|
|
391
|
+
|
|
392
|
+
/* ── Charts ─────────────────────────────────────────────────────────────── */
|
|
393
|
+
.chart-grid{display:grid;gap:var(--sp-3);grid-template-columns:repeat(auto-fit,minmax(18rem,1fr))}
|
|
394
|
+
.chart{padding:var(--sp-4);border:1px solid var(--border);border-radius:var(--radius);
|
|
395
|
+
background:var(--surface);backdrop-filter:var(--glass-blur);-webkit-backdrop-filter:var(--glass-blur)}
|
|
396
|
+
.chart h4{margin-bottom:var(--sp-3)}
|
|
397
|
+
.chart svg{display:block;width:100%;height:auto;overflow:visible}
|
|
398
|
+
.legend{display:flex;flex-wrap:wrap;gap:.5rem .875rem;margin-top:var(--sp-3);font-size:.75rem}
|
|
399
|
+
.legend span{display:inline-flex;align-items:center;gap:.375rem;color:var(--text-soft)}
|
|
400
|
+
.legend i{width:.625rem;height:.625rem;border-radius:3px;flex:none}
|
|
401
|
+
.legend b{font-weight:650;font-variant-numeric:tabular-nums;color:var(--text)}
|
|
402
|
+
.axis{font-size:10px;fill:var(--text-muted)}
|
|
403
|
+
.gridline{stroke:var(--border);stroke-width:1}
|
|
404
|
+
|
|
405
|
+
/* ── Timeline ───────────────────────────────────────────────────────────── */
|
|
406
|
+
.timeline{position:relative;margin:0;padding:0 0 0 1.375rem;list-style:none}
|
|
407
|
+
.timeline::before{content:"";position:absolute;left:.3125rem;top:.375rem;bottom:.375rem;width:2px;
|
|
408
|
+
background:linear-gradient(180deg,var(--accent),transparent)}
|
|
409
|
+
.timeline li{position:relative;padding:0 0 var(--sp-4)}
|
|
410
|
+
.timeline li:last-child{padding-bottom:0}
|
|
411
|
+
.timeline li::before{content:"";position:absolute;left:-1.375rem;top:.4375rem;width:.75rem;height:.75rem;
|
|
412
|
+
border-radius:50%;background:var(--surface-solid);border:2px solid var(--tl,var(--accent))}
|
|
413
|
+
.tl-ok{--tl:#17b26a}.tl-warned{--tl:#f79009}.tl-failed{--tl:#f04438}.tl-skipped{--tl:#98a2b3}
|
|
414
|
+
.tl-head{display:flex;flex-wrap:wrap;align-items:baseline;gap:.5rem}
|
|
415
|
+
.tl-label{font-weight:600;font-size:.9375rem}
|
|
416
|
+
.tl-dur{font-size:.75rem;color:var(--text-muted);font-variant-numeric:tabular-nums}
|
|
417
|
+
.tl-detail{font-size:.8125rem;color:var(--text-muted);margin-top:.125rem}
|
|
418
|
+
|
|
419
|
+
/* ── Evidence ───────────────────────────────────────────────────────────── */
|
|
420
|
+
.evidence{display:grid;gap:var(--sp-3);grid-template-columns:repeat(auto-fill,minmax(15rem,1fr));
|
|
421
|
+
margin-top:var(--sp-4)}
|
|
422
|
+
figure.shot{margin:0;border:1px solid var(--border);border-radius:var(--radius-sm);
|
|
423
|
+
overflow:hidden;background:var(--surface-sunken)}
|
|
424
|
+
figure.shot img,figure.shot video{display:block;width:100%;height:auto;background:var(--surface-sunken)}
|
|
425
|
+
figure.shot img{cursor:zoom-in;transition:opacity .16s var(--ease)}
|
|
426
|
+
figure.shot img:hover{opacity:.92}
|
|
427
|
+
figcaption{padding:.5rem .625rem;font-size:.6875rem;color:var(--text-muted);
|
|
428
|
+
border-top:1px solid var(--border);display:flex;flex-wrap:wrap;gap:.375rem;align-items:center}
|
|
429
|
+
figcaption .name{font-weight:650;color:var(--text-soft)}
|
|
430
|
+
figcaption code{font-size:.6875rem}
|
|
431
|
+
.shot-actions{margin-left:auto;display:flex;gap:.375rem}
|
|
432
|
+
.shot-actions a{font-size:.6875rem;font-weight:650;text-decoration:none;color:var(--accent)}
|
|
433
|
+
.shot-actions a:hover{text-decoration:underline}
|
|
434
|
+
/* The whole reason this module exists: a file that is not there is stated, never
|
|
435
|
+
left to a browser's broken-image glyph. */
|
|
436
|
+
.artifact-missing{display:flex;align-items:flex-start;gap:.625rem;padding:var(--sp-4);
|
|
437
|
+
border:1px dashed var(--border-strong);border-radius:var(--radius-sm);
|
|
438
|
+
background:var(--surface-sunken);color:var(--text-muted);font-size:.8125rem}
|
|
439
|
+
.artifact-missing svg{flex:none;margin-top:.125rem;opacity:.7}
|
|
440
|
+
.artifact-missing .why{display:block;font-weight:650;color:var(--text-soft);margin-bottom:.125rem}
|
|
441
|
+
.artifact-missing code{font-size:.6875rem}
|
|
442
|
+
.compare{display:grid;gap:var(--sp-2);grid-template-columns:1fr 1fr;align-items:start}
|
|
443
|
+
.compare figcaption .name::before{content:attr(data-side) " · ";color:var(--accent)}
|
|
444
|
+
|
|
445
|
+
/* ── Lightbox ───────────────────────────────────────────────────────────── */
|
|
446
|
+
.lightbox{position:fixed;inset:0;z-index:100;display:none;place-items:center;
|
|
447
|
+
padding:var(--sp-5);background:rgba(6,9,14,.86);backdrop-filter:blur(8px)}
|
|
448
|
+
.lightbox[open],.lightbox.on{display:grid}
|
|
449
|
+
.lightbox img{max-width:100%;max-height:86vh;border-radius:var(--radius);
|
|
450
|
+
box-shadow:var(--shadow-lg);cursor:zoom-out;transition:transform .2s var(--ease);transform-origin:center}
|
|
451
|
+
.lightbox.zoomed img{cursor:move;transform:scale(2)}
|
|
452
|
+
.lightbox-bar{position:absolute;top:var(--sp-4);left:var(--sp-5);right:var(--sp-5);
|
|
453
|
+
display:flex;align-items:center;gap:var(--sp-3);color:#e8ecf4;font-size:.8125rem}
|
|
454
|
+
.lightbox-bar .grow{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
455
|
+
.lightbox-bar button,.lightbox-bar a{background:rgba(255,255,255,.12);border:1px solid rgba(255,255,255,.2);
|
|
456
|
+
color:#fff;border-radius:var(--radius-sm);padding:.3125rem .625rem;font:inherit;font-size:.75rem;
|
|
457
|
+
font-weight:600;cursor:pointer;text-decoration:none}
|
|
458
|
+
.lightbox-bar button:hover,.lightbox-bar a:hover{background:rgba(255,255,255,.2)}
|
|
459
|
+
|
|
460
|
+
/* ── Misc ───────────────────────────────────────────────────────────────── */
|
|
461
|
+
.empty{color:var(--text-muted);font-style:italic}
|
|
462
|
+
.muted{color:var(--text-muted)}
|
|
463
|
+
.tabular{font-variant-numeric:tabular-nums}
|
|
464
|
+
.no-results{display:none;padding:var(--sp-6);text-align:center;color:var(--text-muted)}
|
|
465
|
+
.no-results.on{display:block}
|
|
466
|
+
.skip{position:absolute;left:-9999px;top:0;padding:.5rem .875rem;background:var(--accent);
|
|
467
|
+
color:var(--accent-contrast);border-radius:0 0 var(--radius-sm) 0;z-index:200;font-weight:650}
|
|
468
|
+
.skip:focus{left:0}
|
|
469
|
+
:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:4px}
|
|
470
|
+
.qa-pack-attribution{margin-top:var(--sp-6)}
|
|
471
|
+
|
|
472
|
+
/* ── Responsive ─────────────────────────────────────────────────────────── */
|
|
473
|
+
@media (max-width:72rem){
|
|
474
|
+
.shell{grid-template-columns:1fr;gap:var(--sp-4);padding:var(--sp-4)}
|
|
475
|
+
.sidebar{position:static;max-height:none;flex-direction:row;flex-wrap:wrap;align-items:center;
|
|
476
|
+
gap:var(--sp-3);padding:var(--sp-3);border:1px solid var(--border);
|
|
477
|
+
border-radius:var(--radius);background:var(--surface)}
|
|
478
|
+
nav.toc{flex-direction:row;flex-wrap:wrap;gap:.25rem}
|
|
479
|
+
nav.toc .n{display:none}
|
|
480
|
+
.sidebar-sub{display:none}
|
|
481
|
+
}
|
|
482
|
+
@media (max-width:40rem){
|
|
483
|
+
.shell{padding:var(--sp-3)}
|
|
484
|
+
.masthead{padding:var(--sp-4);border-radius:var(--radius)}
|
|
485
|
+
.card-body{padding:var(--sp-4)}
|
|
486
|
+
.behaviour{grid-template-columns:1fr;gap:.375rem}
|
|
487
|
+
.behaviour dt{padding-top:.625rem}
|
|
488
|
+
.kpis{grid-template-columns:repeat(auto-fill,minmax(7.5rem,1fr))}
|
|
489
|
+
.evidence,.compare{grid-template-columns:1fr}
|
|
490
|
+
.factbar{gap:var(--sp-4)}
|
|
491
|
+
.toolbar{position:static}
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
/* ── Motion ─────────────────────────────────────────────────────────────── */
|
|
495
|
+
@media (prefers-reduced-motion:no-preference){
|
|
496
|
+
.reveal{opacity:0;transform:translateY(8px);animation:rise .5s var(--ease) forwards}
|
|
497
|
+
@keyframes rise{to{opacity:1;transform:none}}
|
|
498
|
+
}
|
|
499
|
+
@media (prefers-reduced-motion:reduce){
|
|
500
|
+
*,*::before,*::after{animation-duration:.001ms !important;animation-iteration-count:1 !important;
|
|
501
|
+
transition-duration:.001ms !important;scroll-behavior:auto !important}
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
/* ── Print ──────────────────────────────────────────────────────────────── */
|
|
505
|
+
@media print{
|
|
506
|
+
@page{margin:14mm}
|
|
507
|
+
html{scroll-behavior:auto}
|
|
508
|
+
body{background:#fff;color:#000;font-size:10.5pt}
|
|
509
|
+
body::before,.sidebar,.toolbar,.lightbox,.skip,.shot-actions,.caret{display:none !important}
|
|
510
|
+
.shell{display:block;max-width:none;padding:0}
|
|
511
|
+
.card,.finding,.chart,.kpi,.masthead,.score,.table-wrap{
|
|
512
|
+
background:#fff !important;box-shadow:none !important;backdrop-filter:none !important;
|
|
513
|
+
-webkit-backdrop-filter:none !important;border-color:#d0d5dd !important;break-inside:avoid}
|
|
514
|
+
.masthead::after{display:none}
|
|
515
|
+
/* Collapsed findings print as headings with no content, which is how a printed
|
|
516
|
+
report loses the half of itself that matters. */
|
|
517
|
+
.finding>.finding-body{display:block !important}
|
|
518
|
+
.finding{break-inside:avoid}
|
|
519
|
+
.section{break-before:auto;margin-bottom:1.25rem}
|
|
520
|
+
h1{font-size:22pt}h2{font-size:13pt;break-after:avoid}h3{font-size:11pt;break-after:avoid}
|
|
521
|
+
.reveal{opacity:1 !important;transform:none !important;animation:none !important}
|
|
522
|
+
figure.shot img{max-height:9cm;object-fit:contain}
|
|
523
|
+
/* A printed link that only says "here" is a dead end. */
|
|
524
|
+
.subject a[href]::after{content:" (" attr(href) ")";font-size:8pt;color:#475467;word-break:break-all}
|
|
525
|
+
thead{display:table-header-group}
|
|
526
|
+
tr,img,figure{break-inside:avoid}
|
|
527
|
+
}
|
|
528
|
+
`.trim();
|
|
529
|
+
}
|