penthera 1.7.0 → 1.8.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/CHANGELOG.md +315 -0
- package/README.md +139 -76
- package/SECURITY.md +8 -6
- package/docs/examples/pr-dependency-review.yml +1 -1
- package/lib/adaptive-probes.js +3 -3
- package/lib/advisories/evidence.js +248 -0
- package/lib/advisories/index.js +228 -0
- package/lib/advisories/products.js +83 -0
- package/lib/advisories/versions.js +65 -0
- package/lib/agents/hidden-content.js +122 -11
- package/lib/agents/index.js +26 -6
- package/lib/agents/lock.js +33 -5
- package/lib/agents/rules.js +33 -4
- package/lib/compliance/index.js +4 -4
- package/lib/crawler.js +12 -15
- package/lib/deps/capabilities.js +21 -5
- package/lib/deps/findings.js +309 -0
- package/lib/deps/index.js +13 -272
- package/lib/deps/iocs.js +74 -0
- package/lib/deps/lockfile.js +3 -8
- package/lib/deps/online.js +8 -3
- package/lib/deps/popular-packages.json.gz +0 -0
- package/lib/deps/popular-pypi.json.gz +0 -0
- package/lib/deps/python/capabilities.js +16 -3
- package/lib/deps/python/index.js +5 -1
- package/lib/deps/python/lockfiles.js +11 -5
- package/lib/deps/python/source.js +75 -26
- package/lib/deps/python/toml.js +15 -3
- package/lib/deps/source.js +28 -9
- package/lib/deps/typosquat.js +30 -5
- package/lib/fix/apply.js +253 -34
- package/lib/fix/index.js +7 -4
- package/lib/fix/model.js +25 -5
- package/lib/fix/util.js +6 -2
- package/lib/fuzzer.js +3 -3
- package/lib/git.js +65 -0
- package/lib/hook/index.js +157 -73
- package/lib/hook/policy.js +10 -4
- package/lib/install/index.js +4 -7
- package/lib/machine.js +0 -13
- package/lib/memory/store.js +11 -4
- package/lib/nuclei-loader.js +0 -25
- package/lib/owasp-wstg.js +4 -0
- package/lib/plugins.js +1 -1
- package/lib/provenance.js +1 -0
- package/lib/recon.js +12 -31
- package/lib/references.json +224 -0
- package/lib/retirejs.js +4 -4
- package/lib/rules/advisories/advisories.json +186 -0
- package/lib/rules/advisories/eol.json +413 -0
- package/lib/rules/advisories/pack.json +20 -0
- package/lib/rules/advisories/pack.json.sig +6 -0
- package/lib/rules/allowed_signers +13 -0
- package/lib/rules/core/agent-exec.json +29 -0
- package/lib/rules/core/agent-instructions.json +17 -0
- package/lib/rules/core/pack.json +30 -0
- package/lib/rules/core/pack.json.sig +6 -0
- package/lib/rules/core/secrets.json +161 -0
- package/lib/rules/core/templates.json +52 -0
- package/lib/rules/index.js +107 -0
- package/lib/rules/ioc-2025-2026/files.json +43 -0
- package/lib/rules/ioc-2025-2026/hosts.json +35 -0
- package/lib/rules/ioc-2025-2026/pack.json +25 -0
- package/lib/rules/ioc-2025-2026/pack.json.sig +6 -0
- package/lib/rules/ioc-2025-2026/packages.json +1048 -0
- package/lib/rules/pack.js +452 -0
- package/lib/rules/regex-guard.js +81 -9
- package/lib/rules/sshsig.js +205 -0
- package/lib/templates.js +24 -20
- package/lib/tmp.js +21 -0
- package/lib/whitebox/frameworks.js +1 -1
- package/lib/whitebox/secrets.js +117 -41
- package/package.json +12 -4
- package/scripts/rules/build-pack.mjs +80 -0
- package/scripts/rules/check-bundled.mjs +30 -0
- package/scripts/rules/sign-pack.sh +32 -0
- package/skills/penthera/SKILL.md +16 -15
- package/src/agent/git.js +147 -14
- package/src/agent/loop.js +165 -46
- package/src/cli/agent.js +11 -5
- package/src/cli/deps.js +0 -2
- package/src/cli/detect.js +14 -7
- package/src/cli/fix.js +26 -8
- package/src/cli/hook.js +2 -1
- package/src/cli/onboarding.js +14 -6
- package/src/cli/report-outputs.js +1 -0
- package/src/cli/rules.js +144 -0
- package/src/cli/ui.js +43 -10
- package/src/cli.js +24 -1
- package/src/report/evidence.js +105 -21
- package/src/report/footer.js +1 -1
- package/src/report/md-escape.js +8 -0
- package/src/scan-repo.js +6 -0
- package/src/scan-url.js +11 -3
- package/src/ui/api/data.js +39 -6
- package/src/ui/api/routes.js +44 -11
- package/src/ui/api/runs.js +32 -7
- package/src/ui/security.js +20 -23
- package/src/ui/server.js +52 -27
- package/src/ui/static/app.css +583 -213
- package/src/ui/static/favicon.svg +1 -1
- package/src/ui/static/fonts/DepartureMono-LICENSE.txt +93 -0
- package/src/ui/static/fonts/DepartureMono-Regular.woff2 +0 -0
- package/src/ui/static/index.html +5 -4
- package/src/ui/static/js/api.js +114 -6
- package/src/ui/static/js/app.js +81 -42
- package/src/ui/static/js/center.js +246 -133
- package/src/ui/static/js/charts.js +99 -18
- package/src/ui/static/js/copy.js +68 -9
- package/src/ui/static/js/dialog.js +152 -0
- package/src/ui/static/js/left.js +23 -60
- package/src/ui/static/js/menubar.js +170 -0
- package/src/ui/static/js/onboarding.js +104 -0
- package/src/ui/static/js/panels.js +186 -0
- package/src/ui/static/js/right.js +69 -188
- package/src/ui/static/js/state.js +36 -5
- package/src/ui/static/logo.svg +10 -0
- package/src/ui/static/mark.svg +3 -0
- package/src/utils/http.js +162 -13
- package/docs/METHODOLOGY.md +0 -375
- package/docs/commands/README.md +0 -24
- package/docs/commands/action.md +0 -21
- package/docs/commands/agents.md +0 -38
- package/docs/commands/deps.md +0 -115
- package/docs/commands/fix.md +0 -53
- package/docs/commands/hook.md +0 -69
- package/docs/commands/init.md +0 -114
- package/docs/commands/install.md +0 -53
- package/docs/commands/scan.md +0 -100
- package/docs/commands/skill.md +0 -58
- package/docs/compare/README.md +0 -25
- package/docs/compare/github.md +0 -60
- package/docs/compare/semgrep.md +0 -54
- package/docs/compare/snyk.md +0 -62
- package/docs/compare/socket.md +0 -78
- package/docs/compare/zap.md +0 -59
- package/docs/compliance-cra.md +0 -141
- package/docs/compliance-nis2.md +0 -168
- package/docs/dashboard.md +0 -187
- package/docs/evidence.md +0 -162
- package/docs/funding/due-diligence-checklist.md +0 -79
- package/docs/funding/nlnet-ngi-zero-draft.md +0 -273
- package/docs/funding/partner-one-pager.md +0 -84
- package/docs/funding/sponsor-tiers.md +0 -81
- package/docs/index.md +0 -81
- package/docs/internal-audit.md +0 -83
- package/docs/local-loop.md +0 -276
- package/docs/marketing.md +0 -151
- package/docs/owasp-wstg-coverage.md +0 -79
- package/docs/plan.md +0 -102
- package/docs/privacy.md +0 -38
- package/docs/references.bib +0 -559
- package/docs/references.md +0 -119
- package/docs/release-plan.md +0 -228
- package/docs/research/socket-positioning-notes.md +0 -183
- package/docs/use-cases/README.md +0 -14
- package/docs/use-cases/agencies.md +0 -71
- package/docs/use-cases/ai-coding-teams.md +0 -81
- package/docs/use-cases/eu-sme-compliance.md +0 -68
- package/docs/use-cases/open-source-maintainers.md +0 -75
- package/docs/use-cases/solo-founder.md +0 -65
- package/lib/deps/popular-packages.json +0 -1
- package/lib/deps/popular-pypi.json +0 -1
package/src/ui/static/app.css
CHANGED
|
@@ -1,29 +1,45 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* penthera ui ::
|
|
2
|
+
* penthera ui :: System 1-bit, blue ink.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* the
|
|
9
|
-
*
|
|
10
|
-
*
|
|
4
|
+
* A menu bar over three tiled windows on a dotted desktop: projects on the
|
|
5
|
+
* left, the document (a project's five tabs, or a run) in the centre, the
|
|
6
|
+
* inspector on the right. Every pane is a
|
|
7
|
+
* window: a 1px ink frame and a title bar. The window that holds focus gets
|
|
8
|
+
* the solid ink title bar; the others are outlined, so you can always see
|
|
9
|
+
* which pane j / k / Esc will act on. Only dialogs float (hard 2px shadow),
|
|
10
|
+
* and the approval dialog alone is pinstriped: pinstripes mean "waiting on you".
|
|
11
|
+
*
|
|
12
|
+
* Colour: ink, paper and #0000ed. No flat greys: shades are dither patterns
|
|
13
|
+
* (solid, hatched, half, sparse, dotted, empty). Blue has four jobs only ::
|
|
14
|
+
* selection, the default button, the focus ring, chart lines and links.
|
|
15
|
+
* Green is retired: OK is a ✓ and a word.
|
|
16
|
+
*
|
|
17
|
+
* Type, three roles:
|
|
18
|
+
* --px Departure Mono (OFL, self-hosted) at 11 / 22px :: chrome, labels, numbers
|
|
19
|
+
* --mono ui-monospace :: data, paths, diffs, evidence, transcripts
|
|
20
|
+
* --sans system-ui :: sentences for people (In plain words, notes, empty states)
|
|
11
21
|
*
|
|
12
22
|
* One theming system: [data-theme] on <html>, set before paint by
|
|
13
|
-
* /js/theme.js (localStorage, else prefers-color-scheme).
|
|
14
|
-
*
|
|
23
|
+
* /js/theme.js (localStorage, else prefers-color-scheme). Both themes are
|
|
24
|
+
* first-class; every token has a paper and an ink value.
|
|
15
25
|
*
|
|
16
26
|
* Contrast, measured (WCAG 2.x, on the ground):
|
|
17
|
-
* dark #000: text-1 21.0 · text-2 (ink .72) 10.3 · text-3 (ink .
|
|
18
|
-
*
|
|
27
|
+
* dark #000: text-1 21.0 · text-2 (ink .72) 10.3 · text-3 (ink .56) 6.4 · accent-ink #7a7aff 6.06
|
|
28
|
+
* white on #0000ed 9.45 · focus #7a7aff 6.06 (>=3 non-text)
|
|
19
29
|
* light #fdfdfa: text-1 19.4 · text-2 (ink .72) 8.0 · text-3 (ink .6) 5.24 · #0000ed 9.27
|
|
20
|
-
*
|
|
21
|
-
* #0000ed
|
|
22
|
-
*
|
|
23
|
-
* The canonical ink ladder's 0.5 step measures 3.6:1 on the light ground, so
|
|
24
|
-
* light text-3 is 0.6, not 0.5. Same ladder, measured per polarity.
|
|
30
|
+
* white on #0000ed 9.27
|
|
31
|
+
* #0000ed is 2.22:1 on black, so in the dark theme it is only ever a fill
|
|
32
|
+
* (with white on it), never text and never a 1px line.
|
|
25
33
|
*/
|
|
26
34
|
|
|
35
|
+
@font-face {
|
|
36
|
+
font-family: "Departure Mono";
|
|
37
|
+
src: url("/fonts/DepartureMono-Regular.woff2") format("woff2");
|
|
38
|
+
font-weight: 400;
|
|
39
|
+
font-style: normal;
|
|
40
|
+
font-display: swap;
|
|
41
|
+
}
|
|
42
|
+
|
|
27
43
|
:root,
|
|
28
44
|
:root[data-theme="dark"] {
|
|
29
45
|
color-scheme: dark;
|
|
@@ -31,23 +47,19 @@
|
|
|
31
47
|
--ink-rgb: 255, 255, 255;
|
|
32
48
|
--text-1: rgb(var(--ink-rgb));
|
|
33
49
|
--text-2: rgba(var(--ink-rgb), 0.72);
|
|
34
|
-
--text-3: rgba(var(--ink-rgb), 0.
|
|
50
|
+
--text-3: rgba(var(--ink-rgb), 0.56);
|
|
35
51
|
--text-4: rgba(var(--ink-rgb), 0.3); /* ornament only, never text you must read */
|
|
36
|
-
--rule: rgba(var(--ink-rgb), 0.
|
|
37
|
-
--hair: rgba(var(--ink-rgb), 0.
|
|
52
|
+
--rule: rgba(var(--ink-rgb), 0.34);
|
|
53
|
+
--hair: rgba(var(--ink-rgb), 0.16);
|
|
38
54
|
--frame: rgb(var(--ink-rgb));
|
|
39
|
-
--wash: rgba(var(--ink-rgb), 0.06);
|
|
40
55
|
--accent: #0000ed;
|
|
41
56
|
--accent-hover: #2a2aff;
|
|
42
57
|
--accent-ink: #7a7aff; /* same hue, 6.06:1 on black */
|
|
43
58
|
--on-accent: #ffffff;
|
|
44
59
|
--focus: #7a7aff;
|
|
45
60
|
--series: #7a7aff;
|
|
46
|
-
--
|
|
47
|
-
--
|
|
48
|
-
--glow: 0 0 6px rgba(85, 255, 0, 0.6);
|
|
49
|
-
--logo-glow: 0 0 10px rgba(0, 0, 237, 0.95), 0 0 26px rgba(0, 0, 237, 0.6);
|
|
50
|
-
--scan: rgba(255, 255, 255, 0.035);
|
|
61
|
+
--desk: rgba(var(--ink-rgb), 0.42); /* desktop dots */
|
|
62
|
+
--scrim: rgba(0, 0, 0, 0.6);
|
|
51
63
|
}
|
|
52
64
|
|
|
53
65
|
:root[data-theme="light"] {
|
|
@@ -58,31 +70,40 @@
|
|
|
58
70
|
--text-2: rgba(var(--ink-rgb), 0.72);
|
|
59
71
|
--text-3: rgba(var(--ink-rgb), 0.6);
|
|
60
72
|
--text-4: rgba(var(--ink-rgb), 0.3);
|
|
61
|
-
--rule: rgba(var(--ink-rgb), 0.
|
|
62
|
-
--hair: rgba(var(--ink-rgb), 0.
|
|
73
|
+
--rule: rgba(var(--ink-rgb), 0.4);
|
|
74
|
+
--hair: rgba(var(--ink-rgb), 0.16);
|
|
63
75
|
--frame: rgb(var(--ink-rgb));
|
|
64
|
-
--wash: rgba(var(--ink-rgb), 0.045);
|
|
65
76
|
--accent: #0000ed;
|
|
66
77
|
--accent-hover: #2a2aff;
|
|
67
78
|
--accent-ink: #0000ed;
|
|
68
79
|
--on-accent: #ffffff;
|
|
69
80
|
--focus: #0000ed;
|
|
70
81
|
--series: #0000ed;
|
|
71
|
-
--
|
|
72
|
-
--
|
|
73
|
-
--glow: none; /* no glow on paper */
|
|
74
|
-
--logo-glow: none;
|
|
75
|
-
--scan: transparent; /* no scanlines on paper */
|
|
82
|
+
--desk: rgba(var(--ink-rgb), 0.55);
|
|
83
|
+
--scrim: rgba(10, 10, 10, 0.35);
|
|
76
84
|
}
|
|
77
85
|
|
|
78
86
|
:root {
|
|
87
|
+
--px: "Departure Mono", ui-monospace, "SF Mono", Menlo, monospace;
|
|
79
88
|
--mono: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, Consolas, "Liberation Mono", monospace;
|
|
89
|
+
--sans: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
80
90
|
--fs: 13px;
|
|
81
|
-
--
|
|
82
|
-
--
|
|
91
|
+
--bar-h: 28px; /* window title bars */
|
|
92
|
+
--desk-gap: 6px; /* desktop showing between windows */
|
|
83
93
|
--left-w: 288px;
|
|
84
|
-
--right-w:
|
|
94
|
+
--right-w: 392px;
|
|
85
95
|
--target: 28px; /* WCAG 2.5.8 floor is 24; coarse pointers get 44 below */
|
|
96
|
+
--press: 100ms;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/* ── Dither patterns: the only greys ───────────────────────────────────── */
|
|
100
|
+
/* Each is a background on currentColor-free tokens, so they invert with the theme. */
|
|
101
|
+
:root {
|
|
102
|
+
--pt-solid: linear-gradient(var(--frame), var(--frame));
|
|
103
|
+
--pt-hatch: repeating-linear-gradient(45deg, var(--frame) 0 1.5px, transparent 1.5px 3px);
|
|
104
|
+
--pt-half: conic-gradient(from 90deg at 1px 1px, transparent 50%, var(--frame) 0 75%, transparent 0) 0 0 / 2px 2px, conic-gradient(var(--frame) 25%, transparent 0) 0 0 / 2px 2px;
|
|
105
|
+
--pt-sparse: conic-gradient(from 90deg at 1px 1px, transparent 75%, var(--frame) 0) 0 0 / 3px 3px;
|
|
106
|
+
--pt-desk: conic-gradient(from 90deg at 1px 1px, transparent 75%, var(--desk) 0) 0 0 / 4px 4px;
|
|
86
107
|
}
|
|
87
108
|
|
|
88
109
|
* { box-sizing: border-box; }
|
|
@@ -97,6 +118,8 @@ body {
|
|
|
97
118
|
font-variant-numeric: tabular-nums lining-nums;
|
|
98
119
|
-webkit-font-smoothing: antialiased;
|
|
99
120
|
overflow: hidden;
|
|
121
|
+
display: flex;
|
|
122
|
+
flex-direction: column;
|
|
100
123
|
}
|
|
101
124
|
::selection { background: var(--accent); color: var(--on-accent); }
|
|
102
125
|
a { color: var(--accent-ink); text-underline-offset: 3px; }
|
|
@@ -106,32 +129,201 @@ a:hover { background: var(--accent); color: var(--on-accent); text-decoration: n
|
|
|
106
129
|
.skip { position: absolute; left: 8px; top: -40px; z-index: 100; background: var(--accent); color: var(--on-accent); padding: 4px 8px; }
|
|
107
130
|
.skip:focus { top: 8px; }
|
|
108
131
|
.pad { padding: 16px; }
|
|
132
|
+
code { font: inherit; }
|
|
109
133
|
|
|
110
|
-
/* ── The three
|
|
134
|
+
/* ── The desktop and its three windows ─────────────────────────────────── */
|
|
111
135
|
|
|
112
136
|
.app {
|
|
113
137
|
display: grid;
|
|
114
138
|
grid-template-columns: var(--left-w) minmax(0, 1fr) var(--right-w);
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
.left {
|
|
123
|
-
.right {
|
|
124
|
-
.
|
|
139
|
+
grid-template-areas: "left center right";
|
|
140
|
+
gap: var(--desk-gap);
|
|
141
|
+
padding: var(--desk-gap);
|
|
142
|
+
flex: 1;
|
|
143
|
+
min-height: 0;
|
|
144
|
+
background: var(--pt-desk), var(--ground);
|
|
145
|
+
}
|
|
146
|
+
.app.no-left { grid-template-columns: minmax(0, 1fr) var(--right-w); grid-template-areas: "center right"; }
|
|
147
|
+
.app.no-right { grid-template-columns: var(--left-w) minmax(0, 1fr); grid-template-areas: "left center"; }
|
|
148
|
+
.app.no-left.no-right { grid-template-columns: minmax(0, 1fr); grid-template-areas: "center"; }
|
|
149
|
+
.app.no-left .left, .app.no-right .right { display: none; }
|
|
150
|
+
.left { grid-area: left; }
|
|
151
|
+
.center { grid-area: center; }
|
|
152
|
+
.right { grid-area: right; }
|
|
153
|
+
|
|
154
|
+
.pane {
|
|
155
|
+
min-width: 0;
|
|
156
|
+
min-height: 0;
|
|
157
|
+
display: flex;
|
|
158
|
+
flex-direction: column;
|
|
159
|
+
background: var(--ground);
|
|
160
|
+
border: 1px solid var(--frame);
|
|
161
|
+
overflow: hidden;
|
|
162
|
+
}
|
|
163
|
+
.pane-body { flex: 1; min-height: 0; overflow-y: auto; overflow-x: hidden; }
|
|
164
|
+
.left .pane-body { display: flex; flex-direction: column; }
|
|
165
|
+
.center { outline: none; }
|
|
125
166
|
.scrim { display: none; }
|
|
126
167
|
|
|
127
|
-
/*
|
|
168
|
+
/* Title bar. Outlined at rest; solid ink on the window that holds focus (the
|
|
169
|
+
centre one when nothing does). */
|
|
170
|
+
.win-bar {
|
|
171
|
+
flex: none;
|
|
172
|
+
display: flex;
|
|
173
|
+
align-items: center;
|
|
174
|
+
gap: 6px;
|
|
175
|
+
height: var(--bar-h);
|
|
176
|
+
padding: 0 4px 0 8px;
|
|
177
|
+
border-bottom: 1px solid var(--frame);
|
|
178
|
+
background: var(--ground);
|
|
179
|
+
color: var(--text-1);
|
|
180
|
+
font: 11px / 1 var(--px);
|
|
181
|
+
white-space: nowrap;
|
|
182
|
+
}
|
|
183
|
+
.pane:focus-within > .win-bar,
|
|
184
|
+
.app:not(:focus-within) .center > .win-bar {
|
|
185
|
+
background: var(--frame);
|
|
186
|
+
color: var(--ground);
|
|
187
|
+
}
|
|
188
|
+
.win-bar .title { overflow: hidden; text-overflow: ellipsis; min-width: 0; }
|
|
189
|
+
.win-bar .grow { flex: 1; }
|
|
190
|
+
.win-bar .icon { color: inherit; min-width: 22px; min-height: 22px; }
|
|
191
|
+
.win-bar .icon:hover { background: var(--ground); color: var(--text-1); box-shadow: inset 0 0 0 1px var(--frame); }
|
|
192
|
+
.pane:focus-within > .win-bar .icon:hover,
|
|
193
|
+
.app:not(:focus-within) .center > .win-bar .icon:hover { background: var(--ground); color: var(--text-1); box-shadow: none; }
|
|
194
|
+
.win-bar input[type="search"] {
|
|
195
|
+
height: 20px;
|
|
196
|
+
min-height: 20px;
|
|
197
|
+
width: 200px;
|
|
198
|
+
padding: 0 6px;
|
|
199
|
+
font: 11px / 1 var(--px);
|
|
200
|
+
border: 1px solid var(--frame);
|
|
201
|
+
background: var(--ground);
|
|
202
|
+
color: var(--text-1);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/* The logo: the serif mark and wordmark as masks, so they take the text colour
|
|
206
|
+
(paper on an active title bar, ink everywhere else). */
|
|
207
|
+
.mark, .logotype {
|
|
208
|
+
display: inline-block;
|
|
209
|
+
flex: none;
|
|
210
|
+
background: currentColor;
|
|
211
|
+
-webkit-mask: var(--src) center / contain no-repeat;
|
|
212
|
+
mask: var(--src) center / contain no-repeat;
|
|
213
|
+
}
|
|
214
|
+
.mark { --src: url("/mark.svg"); width: 7px; height: 14px; }
|
|
215
|
+
.logotype { --src: url("/logo.svg"); width: 58px; height: 13px; }
|
|
216
|
+
.logotype.xl { width: 223px; height: 50px; }
|
|
217
|
+
|
|
218
|
+
/*
|
|
219
|
+
* Which logo where. One appearance per surface, never the mark and the
|
|
220
|
+
* wordmark side by side:
|
|
221
|
+
* menu bar, top left the horizontal wordmark; the P mark below 760px
|
|
222
|
+
* favicon / tab the P mark on a blue tile (favicon.svg)
|
|
223
|
+
* About window the wordmark, large
|
|
224
|
+
* first run (empty) the wordmark, large (phase 4)
|
|
225
|
+
* window title bars never: they name the window, not the product
|
|
226
|
+
*/
|
|
227
|
+
|
|
228
|
+
/* ── Menu bar ──────────────────────────────────────────────────────────── */
|
|
128
229
|
|
|
129
|
-
.
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
230
|
+
.menubar {
|
|
231
|
+
flex: none;
|
|
232
|
+
position: relative;
|
|
233
|
+
z-index: 40;
|
|
234
|
+
display: flex;
|
|
235
|
+
align-items: stretch;
|
|
236
|
+
height: 26px;
|
|
237
|
+
padding: 0 6px;
|
|
238
|
+
border-bottom: 1px solid var(--frame);
|
|
239
|
+
background: var(--ground);
|
|
240
|
+
color: var(--text-1);
|
|
241
|
+
font: 11px / 1 var(--px);
|
|
242
|
+
}
|
|
243
|
+
.menubar .grow { flex: 1; }
|
|
244
|
+
.menus { display: flex; list-style: none; margin: 0; padding: 0; }
|
|
245
|
+
.menu-wrap { position: relative; }
|
|
246
|
+
.menu-title {
|
|
247
|
+
height: 100%;
|
|
248
|
+
display: inline-flex;
|
|
249
|
+
align-items: center;
|
|
250
|
+
padding: 0 10px;
|
|
251
|
+
border: 0;
|
|
252
|
+
background: none;
|
|
253
|
+
color: var(--text-1);
|
|
254
|
+
font: inherit;
|
|
255
|
+
cursor: default;
|
|
256
|
+
}
|
|
257
|
+
.menu-title:hover, .menu-title[aria-expanded="true"] { background: var(--frame); color: var(--ground); }
|
|
258
|
+
.menu-title:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
|
|
259
|
+
.menu-title.logo { padding: 0 12px 0 8px; }
|
|
260
|
+
.menu-title.logo .logotype { width: 54px; height: 12px; }
|
|
261
|
+
.menu-title.logo .mark { display: none; width: 6px; height: 13px; }
|
|
262
|
+
.menu {
|
|
263
|
+
position: absolute;
|
|
264
|
+
top: 100%;
|
|
265
|
+
left: 0;
|
|
266
|
+
min-width: 232px;
|
|
267
|
+
margin: 0;
|
|
268
|
+
padding: 3px 0;
|
|
269
|
+
list-style: none;
|
|
270
|
+
background: var(--ground);
|
|
271
|
+
border: 1px solid var(--frame);
|
|
272
|
+
box-shadow: 3px 3px 0 var(--frame);
|
|
273
|
+
}
|
|
274
|
+
.menu-item {
|
|
275
|
+
display: flex;
|
|
276
|
+
align-items: center;
|
|
277
|
+
gap: 4px;
|
|
278
|
+
width: 100%;
|
|
279
|
+
min-height: 24px;
|
|
280
|
+
padding: 0 10px 0 4px;
|
|
281
|
+
border: 0;
|
|
282
|
+
background: none;
|
|
283
|
+
color: var(--text-1);
|
|
284
|
+
font: inherit;
|
|
285
|
+
text-align: left;
|
|
286
|
+
text-decoration: none;
|
|
287
|
+
white-space: nowrap;
|
|
288
|
+
cursor: default;
|
|
289
|
+
}
|
|
290
|
+
.menu-item .check { width: 14px; text-align: center; }
|
|
291
|
+
.menu-item .grow { flex: 1; }
|
|
292
|
+
.menu-item kbd { border: 0; padding: 0; color: var(--text-3); margin-left: 16px; }
|
|
293
|
+
.menu-item:hover, .menu-item:focus-visible { background: var(--frame); color: var(--ground); outline: none; }
|
|
294
|
+
.menu-item:hover kbd, .menu-item:focus-visible kbd { color: var(--ground); }
|
|
295
|
+
.menu-item[disabled] { color: var(--text-4); background: none; }
|
|
296
|
+
.menu-item[disabled] kbd { color: var(--text-4); }
|
|
297
|
+
.menu .sep { margin: 3px 0; border-top: 1px dotted var(--rule); }
|
|
298
|
+
|
|
299
|
+
.statuses { display: flex; align-items: stretch; gap: 2px; }
|
|
300
|
+
.status {
|
|
301
|
+
display: inline-flex;
|
|
302
|
+
align-items: center;
|
|
303
|
+
gap: 7px;
|
|
304
|
+
padding: 0 10px;
|
|
305
|
+
border: 0;
|
|
306
|
+
background: none;
|
|
307
|
+
color: var(--text-1);
|
|
308
|
+
font: inherit;
|
|
309
|
+
cursor: default;
|
|
310
|
+
white-space: nowrap;
|
|
311
|
+
}
|
|
312
|
+
button.status:hover { background: var(--frame); color: var(--ground); }
|
|
313
|
+
button.status:hover .lamp { border-color: var(--ground); }
|
|
314
|
+
.status.dim { color: var(--text-3); }
|
|
315
|
+
.status.waiting { background: var(--accent); color: var(--on-accent); }
|
|
316
|
+
.status.waiting .lamp { border-color: var(--on-accent); }
|
|
317
|
+
.lamp { width: 8px; height: 8px; border: 1px solid var(--frame); flex: none; }
|
|
318
|
+
.lamp.on { background: var(--frame); }
|
|
319
|
+
.lamp.live { background: var(--pt-half); animation: blink 1s steps(1, end) infinite; }
|
|
320
|
+
.status.waiting .lamp.live { background: var(--on-accent); }
|
|
321
|
+
|
|
322
|
+
/* ── Left: projects and runs ───────────────────────────────────────────── */
|
|
323
|
+
|
|
324
|
+
.new-scan { margin: 10px 10px 8px; justify-content: space-between; }
|
|
325
|
+
.new-scan kbd { border-color: currentColor; }
|
|
326
|
+
.side-label { margin: 14px 12px 6px; font: 11px / 1 var(--px); text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-3); display: flex; justify-content: space-between; }
|
|
135
327
|
.side-list { list-style: none; margin: 0; padding: 0 6px; display: grid; gap: 1px; }
|
|
136
328
|
.item {
|
|
137
329
|
all: unset;
|
|
@@ -143,143 +335,159 @@ a:hover { background: var(--accent); color: var(--on-accent); text-decoration: n
|
|
|
143
335
|
width: 100%;
|
|
144
336
|
min-height: 40px;
|
|
145
337
|
padding: 6px 8px;
|
|
146
|
-
|
|
147
|
-
cursor: pointer;
|
|
338
|
+
cursor: default;
|
|
148
339
|
color: var(--text-1);
|
|
149
340
|
}
|
|
150
|
-
.item:hover {
|
|
341
|
+
.item:hover { box-shadow: inset 0 0 0 1px var(--rule); }
|
|
151
342
|
.item:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
|
|
152
|
-
.item[aria-current="true"] { background: var(--
|
|
343
|
+
.item[aria-current="true"] { background: var(--accent); color: var(--on-accent); box-shadow: none; }
|
|
344
|
+
.item[aria-current="true"] .sub, .item[aria-current="true"] .count { color: var(--on-accent); }
|
|
345
|
+
.item[aria-current="true"] .grade { border-color: var(--on-accent); color: var(--on-accent); background: none; }
|
|
346
|
+
.item[aria-current="true"] .grade-F, .item[aria-current="true"] .grade-D { background: var(--on-accent); color: var(--accent); }
|
|
347
|
+
.item[aria-current="true"] .dot { border-color: var(--on-accent); }
|
|
153
348
|
.item .name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
154
349
|
.item .sub { grid-column: 2 / -1; font-size: 11px; color: var(--text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
155
|
-
.item .count { font
|
|
156
|
-
.item .dot { width:
|
|
157
|
-
.item .dot.live { background: var(--
|
|
350
|
+
.item .count { font: 11px / 1 var(--px); color: var(--text-2); }
|
|
351
|
+
.item .dot { width: 9px; height: 9px; border: 1px solid var(--frame); }
|
|
352
|
+
.item .dot.live { background: var(--pt-half); animation: blink 1s steps(1, end) infinite; }
|
|
158
353
|
.item .dot.done { background: var(--frame); }
|
|
159
|
-
.
|
|
160
|
-
.
|
|
161
|
-
.side-foot .grow { flex: 1; }
|
|
354
|
+
.item[aria-current="true"] .dot.done { background: var(--on-accent); }
|
|
355
|
+
.group-h { padding: 8px 10px 2px; font: 11px / 1.3 var(--px); color: var(--text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
162
356
|
|
|
163
|
-
/* ──
|
|
357
|
+
/* ── Controls ──────────────────────────────────────────────────────────── */
|
|
164
358
|
|
|
165
359
|
.icon {
|
|
166
|
-
font:
|
|
360
|
+
font: 13px / 1 var(--mono);
|
|
167
361
|
display: inline-grid;
|
|
168
362
|
place-items: center;
|
|
169
363
|
min-width: 28px;
|
|
170
364
|
min-height: 28px;
|
|
171
|
-
padding: 0
|
|
172
|
-
border:
|
|
173
|
-
border-radius:
|
|
365
|
+
padding: 0 5px;
|
|
366
|
+
border: 0;
|
|
367
|
+
border-radius: 0;
|
|
174
368
|
background: none;
|
|
175
369
|
color: var(--text-2);
|
|
176
|
-
cursor:
|
|
370
|
+
cursor: default;
|
|
177
371
|
}
|
|
178
|
-
.icon:hover {
|
|
179
|
-
.icon
|
|
372
|
+
.icon:hover { color: var(--text-1); box-shadow: inset 0 0 0 1px var(--frame); }
|
|
373
|
+
.icon:active { background: var(--frame); color: var(--ground); }
|
|
374
|
+
.icon[aria-pressed="true"] { color: var(--text-1); box-shadow: inset 0 0 0 1px var(--frame); }
|
|
375
|
+
/* The close box: an empty square at the left of a title bar. */
|
|
376
|
+
.icon.close-box { min-width: 22px; min-height: 22px; padding: 0; }
|
|
377
|
+
.icon.close-box::before { content: ""; width: 11px; height: 11px; border: 1px solid currentColor; background: var(--ground); }
|
|
378
|
+
.icon.close-box:hover::before { background: currentColor; }
|
|
180
379
|
|
|
380
|
+
/* Push buttons: square, 1px ink. Pressed inverts, instantly. The default
|
|
381
|
+
button is blue with the classic outer ring. */
|
|
181
382
|
.btn {
|
|
182
|
-
font:
|
|
383
|
+
font: 11px / 1 var(--px);
|
|
384
|
+
letter-spacing: 0.02em;
|
|
183
385
|
display: inline-flex;
|
|
184
386
|
align-items: center;
|
|
185
|
-
gap:
|
|
387
|
+
gap: 8px;
|
|
186
388
|
min-height: var(--target);
|
|
187
|
-
padding:
|
|
389
|
+
padding: 0 12px;
|
|
188
390
|
color: var(--text-1);
|
|
189
391
|
background: var(--ground);
|
|
190
|
-
border: 1px solid var(--
|
|
191
|
-
border-radius:
|
|
192
|
-
cursor:
|
|
392
|
+
border: 1px solid var(--frame);
|
|
393
|
+
border-radius: 0;
|
|
394
|
+
cursor: default;
|
|
193
395
|
white-space: nowrap;
|
|
194
396
|
text-decoration: none;
|
|
195
397
|
}
|
|
196
|
-
.btn:hover {
|
|
398
|
+
.btn:hover { box-shadow: inset 0 0 0 1px var(--frame); background: var(--ground); color: var(--text-1); }
|
|
197
399
|
.btn:active { background: var(--frame); color: var(--ground); }
|
|
198
|
-
.btn[disabled] { color: var(--text-4); border-color: var(--
|
|
199
|
-
.btn.primary {
|
|
400
|
+
.btn[disabled] { color: var(--text-4); border-color: var(--text-4); box-shadow: none; background: var(--ground); }
|
|
401
|
+
.btn.primary {
|
|
402
|
+
background: var(--accent);
|
|
403
|
+
color: var(--on-accent);
|
|
404
|
+
border-color: var(--frame);
|
|
405
|
+
box-shadow: 0 0 0 2px var(--ground), 0 0 0 3px var(--frame);
|
|
406
|
+
margin: 3px;
|
|
407
|
+
}
|
|
200
408
|
.btn.primary:hover { background: var(--accent-hover); color: var(--on-accent); }
|
|
201
409
|
.btn.primary:active { background: var(--frame); color: var(--ground); }
|
|
202
|
-
.btn.primary[disabled] { background: var(--ground); color: var(--text-4); border-color: var(--
|
|
203
|
-
.btn.small { min-height: 24px; padding: 0 8px;
|
|
204
|
-
.btn .k { opacity: 0.
|
|
410
|
+
.btn.primary[disabled] { background: var(--ground); color: var(--text-4); border-color: var(--text-4); box-shadow: 0 0 0 2px var(--ground), 0 0 0 3px var(--text-4); }
|
|
411
|
+
.btn.small { min-height: 24px; padding: 0 8px; }
|
|
412
|
+
.btn .k { opacity: 0.75; }
|
|
205
413
|
|
|
206
|
-
.chip { display: inline-block; border: 1px solid var(--
|
|
207
|
-
.chip.on {
|
|
414
|
+
.chip { display: inline-block; border: 1px solid var(--frame); padding: 1px 5px; font: 11px / 1.2 var(--px); color: var(--text-1); white-space: nowrap; }
|
|
415
|
+
.chip.on { background: var(--frame); color: var(--ground); }
|
|
208
416
|
.chip.inv { background: var(--frame); color: var(--ground); border-color: var(--frame); }
|
|
209
|
-
.chip.blue { background: var(--accent); color: var(--on-accent); border-color: var(--
|
|
417
|
+
.chip.blue { background: var(--accent); color: var(--on-accent); border-color: var(--frame); }
|
|
210
418
|
|
|
211
419
|
input[type="text"], input[type="search"], select {
|
|
212
420
|
font: inherit;
|
|
213
421
|
color: var(--text-1);
|
|
214
422
|
background: var(--ground);
|
|
215
|
-
border: 1px solid var(--
|
|
216
|
-
border-radius:
|
|
423
|
+
border: 1px solid var(--frame);
|
|
424
|
+
border-radius: 0;
|
|
217
425
|
padding: 4px 8px;
|
|
218
426
|
min-height: var(--target);
|
|
219
427
|
min-width: 0;
|
|
220
428
|
}
|
|
221
429
|
input::placeholder { color: var(--text-3); }
|
|
222
|
-
input:focus-visible, select:focus-visible { outline: 2px solid var(--focus); outline-offset: 0;
|
|
430
|
+
input:focus-visible, select:focus-visible { outline: 2px solid var(--focus); outline-offset: 0; }
|
|
223
431
|
input[type="checkbox"], input[type="radio"] { accent-color: var(--accent); width: 14px; height: 14px; margin: 0 6px 0 0; vertical-align: -2px; }
|
|
224
432
|
|
|
225
|
-
/* ── Severity, grade, bars
|
|
433
|
+
/* ── Severity, grade, bars ─────────────────────────────────────────────── */
|
|
226
434
|
|
|
227
|
-
.sev { white-space: nowrap; font
|
|
435
|
+
.sev { white-space: nowrap; font: 11px / 1 var(--px); text-transform: uppercase; letter-spacing: 0.05em; display: inline-flex; align-items: center; gap: 6px; color: var(--text-1); }
|
|
228
436
|
.sev::before { content: ""; display: inline-block; width: 9px; height: 9px; border: 1px solid var(--frame); flex: none; }
|
|
229
437
|
.sev-critical::before { background: var(--frame); }
|
|
230
|
-
.sev-high::before { background:
|
|
231
|
-
.sev-medium::before { background:
|
|
232
|
-
.sev-low::before { background:
|
|
438
|
+
.sev-high::before { background: var(--pt-hatch); }
|
|
439
|
+
.sev-medium::before { background: var(--pt-half); }
|
|
440
|
+
.sev-low::before { background: var(--pt-sparse); }
|
|
233
441
|
.sev-info::before { background: transparent; }
|
|
234
|
-
.sev-critical { font-weight: 700; }
|
|
235
442
|
.sev-low, .sev-info { color: var(--text-2); }
|
|
236
|
-
.sw { display: inline-block; width: 9px; height: 9px; border: 1px solid var(--frame); }
|
|
443
|
+
.sw { display: inline-block; width: 9px; height: 9px; border: 1px solid var(--frame); flex: none; }
|
|
237
444
|
.sw.sev-critical { background: var(--frame); }
|
|
445
|
+
.sw.sev-high { background: var(--pt-hatch); }
|
|
446
|
+
.sw.sev-medium { background: var(--pt-half); }
|
|
447
|
+
.sw.sev-low { background: var(--pt-sparse); }
|
|
238
448
|
|
|
239
|
-
.grade { display: inline-grid; place-items: center; min-width: 22px; height: 20px; padding: 0 3px; border: 1px solid var(--frame); color: var(--text-1); font
|
|
449
|
+
.grade { display: inline-grid; place-items: center; min-width: 22px; height: 20px; padding: 0 3px; border: 1px solid var(--frame); color: var(--text-1); font: 11px / 1 var(--px); }
|
|
240
450
|
.grade-F, .grade-D { background: var(--frame); color: var(--ground); }
|
|
241
|
-
.grade.lg { min-width:
|
|
451
|
+
.grade.lg { min-width: 44px; height: 44px; font-size: 22px; }
|
|
242
452
|
|
|
243
453
|
.shade { color: var(--text-1); }
|
|
244
454
|
.shade.track { color: var(--text-4); }
|
|
245
455
|
.bars { display: grid; grid-template-columns: max-content minmax(0, 1fr) max-content; gap: 3px 10px; align-items: baseline; }
|
|
246
|
-
.bars .bar { white-space: pre; overflow: hidden; letter-spacing: -0.04em; }
|
|
456
|
+
.bars .bar { white-space: pre; overflow: hidden; letter-spacing: -0.04em; line-height: 1.3; max-height: 1.3em; }
|
|
457
|
+
.bars .num { font: 11px / 1 var(--px); }
|
|
247
458
|
.stackbar { white-space: pre; overflow: hidden; letter-spacing: -0.04em; color: var(--text-1); line-height: 1.2; }
|
|
248
459
|
svg.spark { display: block; width: 140px; max-width: 100%; height: 26px; }
|
|
249
460
|
.spark .s-line { fill: none; stroke: var(--series); stroke-width: 1.5; }
|
|
250
461
|
.spark .s-dot { fill: var(--series); }
|
|
462
|
+
svg.chart { display: block; width: 100%; height: auto; }
|
|
251
463
|
.chart .grid-line { stroke: var(--hair); stroke-width: 1; }
|
|
464
|
+
.chart .axis { stroke: var(--frame); stroke-width: 1; }
|
|
465
|
+
.chart .tick { fill: var(--text-3); font: 11px var(--px); }
|
|
466
|
+
.chart .area-total { fill: url(#pt-hatch); }
|
|
467
|
+
.chart .line-total { fill: none; stroke: var(--series); stroke-width: 1.5; }
|
|
468
|
+
.chart .line-severe { fill: none; stroke: var(--frame); stroke-width: 1; stroke-dasharray: 3 3; }
|
|
469
|
+
.chart .dot { fill: var(--ground); stroke: var(--series); stroke-width: 1.5; }
|
|
252
470
|
.hatch-line { stroke: var(--series); stroke-width: 1; opacity: 0.55; }
|
|
253
471
|
.dither-dot { fill: var(--frame); }
|
|
254
472
|
.hatch-ink { stroke: var(--frame); stroke-width: 1; }
|
|
255
473
|
|
|
256
|
-
/* ── Centre
|
|
474
|
+
/* ── Centre: the document ──────────────────────────────────────────────── */
|
|
257
475
|
|
|
258
|
-
.
|
|
259
|
-
display: flex;
|
|
260
|
-
align-items: center;
|
|
261
|
-
gap: 8px;
|
|
262
|
-
min-height: 48px;
|
|
263
|
-
padding: 8px 14px;
|
|
264
|
-
border-bottom: 1px solid var(--rule);
|
|
265
|
-
}
|
|
266
|
-
.toolbar .title { color: var(--text-1); font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
|
|
267
|
-
.toolbar .grow { flex: 1; }
|
|
268
|
-
.toolbar input[type="search"] { width: 220px; }
|
|
269
|
-
.stream { flex: 1; overflow-y: auto; }
|
|
476
|
+
.stream { flex: 1; min-height: 0; overflow-y: auto; }
|
|
270
477
|
.col { max-width: 920px; margin: 0 auto; padding: 22px 24px 40px; }
|
|
271
478
|
|
|
272
479
|
.head { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 6px 16px; align-items: center; margin-bottom: 18px; }
|
|
273
|
-
.head h1 { margin: 0; font
|
|
480
|
+
.head h1 { margin: 0; font: 22px / 1.1 var(--px); color: var(--text-1); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
274
481
|
.head .meta { grid-column: 2; color: var(--text-3); font-size: 12px; }
|
|
275
482
|
.head .right-bits { grid-row: 1 / span 2; grid-column: 3; display: grid; justify-items: end; gap: 4px; }
|
|
276
|
-
.head .counts { color: var(--text-2); font
|
|
277
|
-
.head .counts b { color: var(--text-1); }
|
|
483
|
+
.head .counts { color: var(--text-2); font: 11px / 1 var(--px); }
|
|
484
|
+
.head .counts b { color: var(--text-1); font-weight: 400; }
|
|
278
485
|
|
|
279
|
-
.section { margin-top:
|
|
280
|
-
.section > h2 { margin: 0 0 8px; font
|
|
281
|
-
.rows { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--
|
|
486
|
+
.section { margin-top: 24px; }
|
|
487
|
+
.section > h2 { margin: 0 0 8px; font: 11px / 1 var(--px); text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-3); display: flex; justify-content: space-between; gap: 12px; }
|
|
488
|
+
.rows { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--frame); }
|
|
282
489
|
.rows > li { border-bottom: 1px solid var(--hair); }
|
|
490
|
+
.rows > li:last-child { border-bottom-color: var(--frame); }
|
|
283
491
|
.row {
|
|
284
492
|
all: unset;
|
|
285
493
|
box-sizing: border-box;
|
|
@@ -289,37 +497,74 @@ svg.spark { display: block; width: 140px; max-width: 100%; height: 26px; }
|
|
|
289
497
|
align-items: baseline;
|
|
290
498
|
width: 100%;
|
|
291
499
|
padding: 8px 8px;
|
|
292
|
-
cursor:
|
|
500
|
+
cursor: default;
|
|
293
501
|
color: var(--text-1);
|
|
294
502
|
}
|
|
295
|
-
.row:hover {
|
|
503
|
+
.row:hover { box-shadow: inset 0 0 0 1px var(--rule); }
|
|
296
504
|
.row:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
|
|
297
|
-
.row[aria-current="true"] { background: var(--accent); color: var(--on-accent); }
|
|
505
|
+
.row[aria-current="true"] { background: var(--accent); color: var(--on-accent); box-shadow: none; }
|
|
298
506
|
.row[aria-current="true"] * { color: var(--on-accent) !important; }
|
|
299
507
|
.row[aria-current="true"] .sev::before { border-color: var(--on-accent); }
|
|
508
|
+
.row[aria-current="true"] .sev-critical::before { background: var(--on-accent); }
|
|
509
|
+
.row[aria-current="true"] .sev-high::before { background: repeating-linear-gradient(45deg, var(--on-accent) 0 1.5px, transparent 1.5px 3px); }
|
|
300
510
|
.row .where { grid-column: 2 / -1; color: var(--text-3); font-size: 12px; overflow-wrap: anywhere; }
|
|
301
|
-
.row .tag { color: var(--text-3); font
|
|
511
|
+
.row .tag { color: var(--text-3); font: 11px / 1 var(--px); }
|
|
302
512
|
.row.b .t { font-weight: 700; }
|
|
513
|
+
.row.static { cursor: auto; }
|
|
514
|
+
.row.static:hover { box-shadow: none; }
|
|
515
|
+
|
|
516
|
+
/* Folder tabs: the selected one opens onto the page below it. */
|
|
517
|
+
.tabs { display: flex; align-items: flex-end; margin: 6px 0 4px; overflow-x: auto; scrollbar-width: none; }
|
|
518
|
+
.tab { flex: none; }
|
|
519
|
+
.tab {
|
|
520
|
+
font: 11px / 1 var(--px);
|
|
521
|
+
min-height: 28px;
|
|
522
|
+
padding: 0 14px;
|
|
523
|
+
margin-right: -1px;
|
|
524
|
+
border: 1px solid var(--frame);
|
|
525
|
+
background: var(--ground);
|
|
526
|
+
color: var(--text-2);
|
|
527
|
+
cursor: default;
|
|
528
|
+
white-space: nowrap;
|
|
529
|
+
}
|
|
530
|
+
.tab:hover { color: var(--text-1); box-shadow: inset 0 0 0 1px var(--frame); }
|
|
531
|
+
.tab[aria-selected="true"] { color: var(--ground); background: var(--frame); box-shadow: none; }
|
|
532
|
+
.tab:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; position: relative; z-index: 1; }
|
|
533
|
+
.tab-rest { flex: 1; border-bottom: 1px solid var(--frame); align-self: stretch; }
|
|
534
|
+
.tab-panel { min-height: 200px; }
|
|
535
|
+
.section .label { font: 11px / 1 var(--px); text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-3); margin: 14px 0 6px; }
|
|
536
|
+
.tab-panel > .section:first-child { margin-top: 18px; }
|
|
537
|
+
.actions.start { justify-content: flex-start; }
|
|
303
538
|
.cols2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 24px; }
|
|
304
539
|
.mini { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; }
|
|
305
540
|
.mini li { display: flex; gap: 8px; align-items: baseline; min-width: 0; color: var(--text-1); }
|
|
306
541
|
.mini li .grow { flex: 1; min-width: 0; overflow-wrap: anywhere; }
|
|
542
|
+
.mini li.stacked { display: grid; gap: 3px; }
|
|
543
|
+
.chips { display: flex; flex-wrap: wrap; gap: 3px; }
|
|
307
544
|
.muted { color: var(--text-3); }
|
|
308
545
|
.t1 { color: var(--text-1); }
|
|
309
|
-
.ok { color: var(--
|
|
546
|
+
.ok { color: var(--text-1); }
|
|
310
547
|
.bad { color: var(--text-1); font-weight: 700; }
|
|
311
548
|
.blue { color: var(--accent-ink); }
|
|
312
549
|
.empty { color: var(--text-3); margin: 6px 0; }
|
|
313
550
|
|
|
314
|
-
/*
|
|
315
|
-
.
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
.
|
|
321
|
-
|
|
322
|
-
|
|
551
|
+
/* Sentences for people get the sans. */
|
|
552
|
+
.prose, .empty, .plain p, .start > p, .start .step p, .detail section > p, .dialog-body p.prose {
|
|
553
|
+
font-family: var(--sans);
|
|
554
|
+
font-size: 14px;
|
|
555
|
+
line-height: 1.45;
|
|
556
|
+
}
|
|
557
|
+
.empty { font-size: 13px; }
|
|
558
|
+
|
|
559
|
+
/* First run: the wordmark large, a quiet field, one primary action. */
|
|
560
|
+
.start { display: grid; gap: 14px; }
|
|
561
|
+
.start > .logotype.xl { width: 279px; height: 63px; color: var(--text-1); margin-top: 12px; }
|
|
562
|
+
.start > .halftone-wrap { height: 120px; border-block: 1px solid var(--frame); }
|
|
563
|
+
.start > p { margin: 0; }
|
|
564
|
+
.start h1 { margin: 6px 0 0; font: 22px / 1.1 var(--px); color: var(--text-1); }
|
|
565
|
+
.start .steps { display: grid; gap: 0; margin-top: 18px; border-top: 1px solid var(--frame); }
|
|
566
|
+
.start .step { display: grid; grid-template-columns: 3ch minmax(0, 1fr) auto; gap: 2px 12px; align-items: baseline; padding: 12px 0; border-bottom: 1px solid var(--hair); }
|
|
567
|
+
.start .step .n { color: var(--text-3); font-family: var(--px); }
|
|
323
568
|
.start .step h3 { margin: 0; font-size: 13px; color: var(--text-1); }
|
|
324
569
|
.start .step p { grid-column: 2; margin: 0; color: var(--text-3); }
|
|
325
570
|
|
|
@@ -327,123 +572,248 @@ svg.spark { display: block; width: 140px; max-width: 100%; height: 26px; }
|
|
|
327
572
|
.transcript { font-size: 12.5px; line-height: 1.55; }
|
|
328
573
|
.transcript .ln { white-space: pre-wrap; overflow-wrap: anywhere; min-height: 1.55em; color: var(--text-2); }
|
|
329
574
|
.transcript .ln.cmd { color: var(--text-1); font-weight: 700; margin-top: 4px; }
|
|
330
|
-
.transcript .ln.cmd::before { content: "$ "; color: var(--
|
|
575
|
+
.transcript .ln.cmd::before { content: "$ "; color: var(--text-3); }
|
|
331
576
|
.transcript .ln.dim::before { content: "▸ "; color: var(--text-3); }
|
|
332
|
-
.transcript .ln.ok { color: var(--
|
|
577
|
+
.transcript .ln.ok { color: var(--text-1); }
|
|
578
|
+
.transcript .ln.ok::before { content: "✓ "; }
|
|
333
579
|
.transcript .ln.bad { color: var(--text-1); font-weight: 700; }
|
|
334
580
|
.transcript .ln.bad::before { content: "[!] "; }
|
|
335
581
|
.transcript .ln.hl { color: var(--text-1); font-weight: 700; margin-top: 10px; }
|
|
336
|
-
.cursor { display: inline-block; width: 1ch; height: 1.15em; vertical-align: text-bottom; background: var(--
|
|
582
|
+
.cursor { display: inline-block; width: 1ch; height: 1.15em; vertical-align: text-bottom; background: var(--accent-ink); margin-left: 1px; animation: blink 1s steps(1, end) infinite; }
|
|
337
583
|
@keyframes blink { 50% { opacity: 0; } }
|
|
338
584
|
.run-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 14px; }
|
|
339
|
-
.run-head h1 { margin: 0; font
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
.dialog
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
.dialog-
|
|
585
|
+
.run-head h1 { margin: 0; font: 22px / 1.1 var(--px); color: var(--text-1); }
|
|
586
|
+
.run-head .grow, .actions .grow { flex: 1; }
|
|
587
|
+
|
|
588
|
+
/* The approval: a floating dialog, pinstriped because it waits on you. */
|
|
589
|
+
.dialog { margin: 14px 3px 14px 0; border: 1px solid var(--frame); box-shadow: 3px 3px 0 var(--frame); background: var(--ground); }
|
|
590
|
+
.dialog-bar { height: 22px; border-bottom: 1px solid var(--frame); display: flex; justify-content: center; align-items: center;
|
|
591
|
+
background: repeating-linear-gradient(to bottom, var(--frame) 0 1px, transparent 1px 2px) 0 5px / 100% 11px no-repeat, var(--ground); }
|
|
592
|
+
.dialog-bar span { padding: 0 10px; background: var(--ground); color: var(--text-1); font: 11px / 1 var(--px); }
|
|
593
|
+
.dialog-body { padding: 12px 14px; display: grid; gap: 8px; grid-template-columns: minmax(0, 1fr); }
|
|
594
|
+
.dialog-body > * { min-width: 0; }
|
|
347
595
|
.dialog-body h3 { margin: 0; font-size: 13px; color: var(--text-1); }
|
|
348
596
|
.dialog-body p { margin: 0; }
|
|
349
|
-
.actions { display: flex; flex-wrap: wrap; gap: 8px; justify-content: flex-end; }
|
|
597
|
+
.actions { display: flex; flex-wrap: wrap; gap: 8px; justify-content: flex-end; align-items: center; }
|
|
350
598
|
.kv { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 3px 14px; margin: 0; }
|
|
351
|
-
.kv dt { color: var(--text-3); }
|
|
599
|
+
.kv dt { color: var(--text-3); font: 11px / 1.6 var(--px); }
|
|
352
600
|
.kv dd { margin: 0; min-width: 0; overflow-wrap: anywhere; color: var(--text-1); }
|
|
353
|
-
pre.block { margin: 6px 0 0; padding: 10px 12px; border: 1px solid var(--
|
|
601
|
+
pre.block { margin: 6px 0 0; padding: 10px 12px; border: 1px solid var(--frame); background: var(--ground); white-space: pre-wrap; overflow-wrap: anywhere; color: var(--text-1); max-height: 320px; overflow: auto; font: 12px / 1.5 var(--mono); }
|
|
354
602
|
pre.diff { white-space: pre; overflow-x: auto; }
|
|
355
603
|
.diff .add { color: var(--text-1); font-weight: 700; }
|
|
356
604
|
.diff .del { color: var(--text-3); text-decoration: line-through; text-decoration-color: var(--text-4); }
|
|
357
605
|
.diff .hunk { color: var(--accent-ink); }
|
|
358
606
|
.diff .meta { color: var(--text-3); }
|
|
359
607
|
|
|
360
|
-
/*
|
|
361
|
-
|
|
362
|
-
.
|
|
363
|
-
.
|
|
364
|
-
.bar form:focus-within { outline: 2px solid var(--focus); outline-offset: 1px; }
|
|
365
|
-
.bar input[type="text"] { border: 0; padding: 4px 0; min-height: 28px; width: 100%; background: transparent; }
|
|
366
|
-
.bar input[type="text"]:focus-visible { outline: none; }
|
|
367
|
-
.bar .modes { display: flex; gap: 4px; flex-wrap: wrap; margin-bottom: 8px; align-items: center; }
|
|
368
|
-
.mode { font: inherit; font-size: 12px; min-height: 26px; padding: 0 10px; border: 1px solid var(--rule); border-radius: var(--radius-btn); background: var(--ground); color: var(--text-2); cursor: pointer; }
|
|
369
|
-
.mode:hover { color: var(--text-1); border-color: var(--frame); }
|
|
370
|
-
.mode[aria-pressed="true"] { background: var(--frame); color: var(--ground); border-color: var(--frame); }
|
|
371
|
-
.bar .note { font-size: 11px; color: var(--text-3); margin-left: auto; }
|
|
372
|
-
.bar .confirm { display: flex; gap: 8px; align-items: center; margin-top: 8px; font-size: 12px; color: var(--text-1); flex-wrap: wrap; }
|
|
373
|
-
.bar .confirm input { flex: 1; min-width: 160px; }
|
|
374
|
-
.bar .err { margin: 8px 0 0; color: var(--text-1); font-size: 12px; }
|
|
375
|
-
.bar .err::before { content: "[!] "; font-weight: 700; }
|
|
376
|
-
|
|
377
|
-
/* ── Right panel: stacked cards ────────────────────────────────────────── */
|
|
378
|
-
|
|
379
|
-
.cards { display: grid; }
|
|
380
|
-
.card { border-bottom: 1px solid var(--rule); }
|
|
381
|
-
.card > summary { list-style: none; display: flex; align-items: center; gap: 8px; padding: 12px 14px; cursor: pointer; color: var(--text-1); font-weight: 700; font-size: 12px; }
|
|
382
|
-
.card > summary::-webkit-details-marker { display: none; }
|
|
383
|
-
.card > summary::before { content: "▸"; color: var(--text-3); font-weight: 400; }
|
|
384
|
-
.card[open] > summary::before { content: "▾"; }
|
|
385
|
-
.card > summary .aside { margin-left: auto; font-weight: 400; color: var(--text-3); font-size: 11px; }
|
|
386
|
-
.card > summary:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
|
|
387
|
-
.card-body { padding: 0 14px 14px; display: grid; gap: 8px; min-width: 0; }
|
|
388
|
-
.card-body .label { font-size: 11px; text-transform: uppercase; letter-spacing: 0.1em; color: var(--text-3); margin: 6px 0 0; }
|
|
389
|
-
.detail-head { display: flex; align-items: center; gap: 8px; padding: 10px 14px; border-bottom: 1px solid var(--rule); }
|
|
390
|
-
.detail-head .grow { flex: 1; }
|
|
391
|
-
.detail { padding: 14px; display: grid; gap: 12px; }
|
|
608
|
+
/* ── Right: the inspector ──────────────────────────────────────────────── */
|
|
609
|
+
|
|
610
|
+
.detail { padding: 14px; display: grid; gap: 14px; grid-template-columns: minmax(0, 1fr); align-content: start; }
|
|
611
|
+
.detail > * { min-width: 0; }
|
|
392
612
|
.detail h2 { margin: 0; font-size: 14px; color: var(--text-1); }
|
|
393
|
-
.detail section > .label { font
|
|
394
|
-
.
|
|
395
|
-
.plain
|
|
613
|
+
.detail section > .label { font: 11px / 1 var(--px); text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-3); margin: 0 0 6px; }
|
|
614
|
+
.detail section > p { margin: 0; color: var(--text-1); }
|
|
615
|
+
.plain { border: 1px solid var(--frame); box-shadow: 3px 3px 0 var(--frame); padding: 10px 12px; display: grid; gap: 8px; margin-right: 3px; }
|
|
616
|
+
.plain p { margin: 0; color: var(--text-1); }
|
|
396
617
|
.plain b { color: var(--text-1); }
|
|
397
|
-
.seg { display: inline-flex; border: 1px solid var(--
|
|
398
|
-
.seg label { position: relative; cursor:
|
|
399
|
-
.seg label + label { border-left: 1px solid var(--
|
|
618
|
+
.seg { display: inline-flex; border: 1px solid var(--frame); }
|
|
619
|
+
.seg label { position: relative; cursor: default; }
|
|
620
|
+
.seg label + label { border-left: 1px solid var(--frame); }
|
|
400
621
|
.seg input { position: absolute; opacity: 0; width: 1px; height: 1px; margin: 0; }
|
|
401
|
-
.seg span { display: flex; align-items: center; min-height: 28px; padding: 0 12px; color: var(--text-1); }
|
|
622
|
+
.seg span { display: flex; align-items: center; min-height: 28px; padding: 0 12px; color: var(--text-1); font: 11px / 1 var(--px); }
|
|
402
623
|
.seg input:checked + span { background: var(--frame); color: var(--ground); }
|
|
403
624
|
.seg input:focus-visible + span { outline: 2px solid var(--focus); outline-offset: -4px; }
|
|
404
|
-
.switch { font:
|
|
405
|
-
.switch
|
|
406
|
-
|
|
625
|
+
.switch { font: 11px / 1 var(--px); display: inline-flex; gap: 10px; align-items: center; min-height: 28px; padding: 0 4px 0 12px; background: var(--ground); color: var(--text-1); border: 1px solid var(--frame); border-radius: 0; cursor: default; }
|
|
626
|
+
.switch .state { padding: 4px 8px; border: 1px solid var(--frame); }
|
|
627
|
+
.switch[aria-checked="true"] .state { background: var(--frame); color: var(--ground); }
|
|
628
|
+
kbd { font: 11px / 1 var(--px); border: 1px solid var(--frame); padding: 1px 4px; color: var(--text-1); }
|
|
407
629
|
|
|
408
|
-
* { scrollbar-color: var(--
|
|
630
|
+
* { scrollbar-color: var(--frame) var(--ground); scrollbar-width: thin; }
|
|
409
631
|
|
|
410
|
-
/* ── Narrow: side
|
|
632
|
+
/* ── Narrow: side windows become drawers ───────────────────────────────── */
|
|
411
633
|
|
|
412
634
|
@media (max-width: 1180px) {
|
|
413
|
-
.app, .app.no-right { grid-template-columns: var(--left-w) minmax(0, 1fr); }
|
|
414
|
-
.app.no-left, .app.no-left.no-right { grid-template-columns:
|
|
415
|
-
.right { position: fixed; top:
|
|
416
|
-
.app.no-right .
|
|
417
|
-
|
|
635
|
+
.app, .app.no-right { grid-template-columns: var(--left-w) minmax(0, 1fr); grid-template-areas: "left center"; }
|
|
636
|
+
.app.no-left, .app.no-left.no-right { grid-template-columns: minmax(0, 1fr); grid-template-areas: "center"; }
|
|
637
|
+
.right { position: fixed; top: calc(27px + var(--desk-gap)); right: var(--desk-gap); bottom: var(--desk-gap); width: min(420px, 92vw); z-index: 30; box-shadow: 3px 3px 0 var(--frame); }
|
|
638
|
+
.app:not(.no-right) .scrim { display: block; position: fixed; inset: 0; z-index: 25; background: var(--scrim); }
|
|
639
|
+
}
|
|
640
|
+
/* ── Floating windows: New scan, About ─────────────────────────────────── */
|
|
641
|
+
|
|
642
|
+
dialog.window {
|
|
643
|
+
width: min(560px, calc(100vw - 32px));
|
|
644
|
+
max-height: calc(100dvh - 64px);
|
|
645
|
+
padding: 0;
|
|
646
|
+
border: 1px solid var(--frame);
|
|
647
|
+
background: var(--ground);
|
|
648
|
+
color: var(--text-2);
|
|
649
|
+
box-shadow: 3px 3px 0 var(--frame);
|
|
650
|
+
overflow: hidden;
|
|
651
|
+
display: flex;
|
|
652
|
+
flex-direction: column;
|
|
418
653
|
}
|
|
654
|
+
dialog.window:not([open]) { display: none; }
|
|
655
|
+
/* A heavy blur behind every floating window: the page is there, but out of reach. */
|
|
656
|
+
dialog.window::backdrop {
|
|
657
|
+
background: rgba(0, 0, 0, 0.35);
|
|
658
|
+
-webkit-backdrop-filter: blur(48px) saturate(0.6);
|
|
659
|
+
backdrop-filter: blur(48px) saturate(0.6);
|
|
660
|
+
}
|
|
661
|
+
:root[data-theme="light"] dialog.window::backdrop { background: rgba(253, 253, 250, 0.35); }
|
|
662
|
+
@media (prefers-reduced-transparency: reduce) {
|
|
663
|
+
dialog.window::backdrop { -webkit-backdrop-filter: none; backdrop-filter: none; background: rgba(0, 0, 0, 0.7); }
|
|
664
|
+
}
|
|
665
|
+
dialog.window > .win-bar { background: var(--frame); color: var(--ground); padding-left: 4px; }
|
|
666
|
+
dialog.window > .win-bar .icon.close-box::before { background: var(--frame); border-color: var(--ground); }
|
|
667
|
+
dialog.window > .win-bar .icon.close-box:hover::before { background: var(--ground); }
|
|
668
|
+
.window-body { padding: 14px 16px 16px; overflow-y: auto; }
|
|
669
|
+
.form fieldset { margin: 0; padding: 0; border: 0; min-width: 0; }
|
|
670
|
+
.form legend, .form .field > label { display: block; margin: 0 0 6px; padding: 0; font: 11px / 1 var(--px); text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-3); }
|
|
671
|
+
.form .field > label .muted { text-transform: none; letter-spacing: 0; }
|
|
672
|
+
.form .field.confirm > label { text-transform: none; letter-spacing: 0; font: 14px / 1.45 var(--sans); color: var(--text-1); }
|
|
673
|
+
.choices { display: grid; border: 1px solid var(--frame); }
|
|
674
|
+
.choice { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 2px 8px; align-items: baseline; padding: 8px 10px; cursor: default; }
|
|
675
|
+
.choice + .choice { border-top: 1px solid var(--hair); }
|
|
676
|
+
.choice:hover { box-shadow: inset 0 0 0 1px var(--rule); }
|
|
677
|
+
.choice:has(input:checked) { box-shadow: inset 0 0 0 1px var(--frame); }
|
|
678
|
+
.choice .t1, .check .t1 { font-weight: 700; }
|
|
679
|
+
.note { display: block; color: var(--text-3); font-size: 13px; }
|
|
680
|
+
.field { display: grid; gap: 4px; margin-top: 14px; }
|
|
681
|
+
.field select, .field input { width: 100%; }
|
|
682
|
+
.field p { margin: 0; }
|
|
683
|
+
.check { display: flex; align-items: baseline; gap: 2px; margin-top: 14px; }
|
|
684
|
+
.check .note { display: inline; }
|
|
685
|
+
.form .actions { margin-top: 18px; }
|
|
686
|
+
.err { margin: 12px 0 0; color: var(--text-1); }
|
|
687
|
+
.err::before { content: "[!] "; font-weight: 700; }
|
|
688
|
+
.about { display: grid; gap: 14px; justify-items: start; }
|
|
689
|
+
.about .logotype.xl { color: var(--text-1); margin: 6px 0 2px; }
|
|
690
|
+
.about p { margin: 0; }
|
|
691
|
+
.about .actions { justify-self: stretch; }
|
|
692
|
+
|
|
419
693
|
@media (max-width: 760px) {
|
|
420
|
-
.app, .app.no-left, .app.no-right, .app.no-left.no-right { grid-template-columns: minmax(0, 1fr); }
|
|
421
|
-
.left { position: fixed; top:
|
|
422
|
-
.app.no-left .
|
|
423
|
-
.app:not(.no-left) .scrim { display: block; position: fixed; inset: 0; z-index: 25; background: rgba(0, 0, 0, 0.45); }
|
|
694
|
+
.app, .app.no-left, .app.no-right, .app.no-left.no-right { grid-template-columns: minmax(0, 1fr); grid-template-areas: "center"; }
|
|
695
|
+
.left { position: fixed; top: calc(27px + var(--desk-gap)); left: var(--desk-gap); bottom: var(--desk-gap); width: min(320px, 88vw); z-index: 30; box-shadow: 3px 3px 0 var(--frame); }
|
|
696
|
+
.app:not(.no-left) .scrim { display: block; position: fixed; inset: 0; z-index: 25; background: var(--scrim); }
|
|
424
697
|
.col { padding: 16px 14px 28px; }
|
|
425
|
-
.
|
|
426
|
-
.toolbar input[type="search"] { width: 120px; }
|
|
698
|
+
.win-bar input[type="search"] { width: 110px; }
|
|
427
699
|
.row { grid-template-columns: minmax(0, 1fr) auto; }
|
|
428
700
|
.row .sev { grid-column: 1 / -1; }
|
|
429
701
|
.row .where { grid-column: 1 / -1; }
|
|
430
702
|
.cols2 { grid-template-columns: minmax(0, 1fr); }
|
|
431
703
|
.head { grid-template-columns: auto minmax(0, 1fr); }
|
|
432
704
|
.head .right-bits { grid-row: auto; grid-column: 1 / -1; justify-items: start; }
|
|
433
|
-
.
|
|
705
|
+
.menu-title.logo .logotype { display: none; }
|
|
706
|
+
.menu-title.logo .mark { display: inline-block; }
|
|
707
|
+
.menu-title { padding: 0 7px; }
|
|
708
|
+
.status.dim { display: none; }
|
|
434
709
|
}
|
|
435
710
|
@media (pointer: coarse) {
|
|
436
|
-
:root { --target: 44px; }
|
|
711
|
+
:root { --target: 44px; --bar-h: 44px; }
|
|
437
712
|
.item, .row { min-height: 44px; }
|
|
438
713
|
}
|
|
439
714
|
@media (prefers-reduced-motion: reduce) {
|
|
440
715
|
*, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; }
|
|
441
|
-
.cursor { opacity: 1; }
|
|
716
|
+
.cursor, .item .dot.live { opacity: 1; }
|
|
442
717
|
}
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
.
|
|
449
|
-
.
|
|
718
|
+
|
|
719
|
+
/* ── Phase 3: verdict, simple list, triage matrix, setup, approval ────── */
|
|
720
|
+
|
|
721
|
+
/* The verdict: one sentence and one button. Critical inverts the box, so the
|
|
722
|
+
loudest state is the one with the most at stake. */
|
|
723
|
+
.verdict { margin: 0 3px 8px 0; padding: 14px 16px; border: 1px solid var(--frame); box-shadow: 3px 3px 0 var(--frame); display: grid; gap: 6px; }
|
|
724
|
+
.verdict p { margin: 0; }
|
|
725
|
+
.verdict-text { font: 600 20px / 1.3 var(--sans); color: var(--text-1); }
|
|
726
|
+
.verdict-sub { font: 13px / 1.4 var(--sans); }
|
|
727
|
+
.verdict .actions { margin-top: 6px; }
|
|
728
|
+
.verdict.v-stop { background: var(--frame); }
|
|
729
|
+
.verdict.v-stop .verdict-text { color: var(--ground); }
|
|
730
|
+
.verdict.v-stop .verdict-sub { color: var(--ground); opacity: 0.75; }
|
|
731
|
+
.verdict.v-stop .btn:not(.primary) { border-color: var(--ground); }
|
|
732
|
+
.verdict.v-stop .btn.primary { box-shadow: 0 0 0 2px var(--frame), 0 0 0 3px var(--ground); }
|
|
733
|
+
|
|
734
|
+
.rows.simple .row { grid-template-columns: 9em minmax(0, 1fr) auto; padding: 12px 8px; align-items: center; }
|
|
735
|
+
.rows.simple .row .t { font: 15px / 1.35 var(--sans); }
|
|
736
|
+
.rows.simple .row.b .t { font-weight: 600; }
|
|
737
|
+
p.more { margin-top: 28px; font-size: 13px; }
|
|
738
|
+
details.more { display: grid; gap: 10px; }
|
|
739
|
+
details.more > summary { cursor: default; font: 11px / 1 var(--px); text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-1); padding: 8px 0; list-style: none; }
|
|
740
|
+
details.more > summary::-webkit-details-marker { display: none; }
|
|
741
|
+
details.more > summary::before { content: "▸ "; }
|
|
742
|
+
details.more[open] > summary::before { content: "▾ "; }
|
|
743
|
+
details.more > summary:hover { text-decoration: underline; }
|
|
744
|
+
details.more[open] > * + * { margin-top: 10px; }
|
|
745
|
+
.linkish { font: inherit; text-transform: inherit; letter-spacing: inherit; color: var(--text-1); background: none; border: 0; padding: 0; text-decoration: underline; cursor: default; }
|
|
746
|
+
|
|
747
|
+
/* Triage matrix: severity down, how sure across. */
|
|
748
|
+
.matrix { border-collapse: collapse; width: 100%; max-width: 560px; }
|
|
749
|
+
.matrix th { font: 11px / 1 var(--px); color: var(--text-3); font-weight: 400; text-align: left; padding: 0 8px 6px 0; }
|
|
750
|
+
.matrix thead th { text-align: center; }
|
|
751
|
+
.matrix tbody th { padding: 0 12px 0 0; white-space: nowrap; }
|
|
752
|
+
.matrix td { padding: 0; border: 1px solid var(--frame); }
|
|
753
|
+
.matrix .cell { display: grid; place-items: center; width: 100%; height: 36px; border: 0; background: var(--ground); color: var(--text-1); cursor: default; }
|
|
754
|
+
.matrix .cell[disabled] { color: var(--text-4); }
|
|
755
|
+
.matrix .cell .n { font: 11px / 1 var(--px); padding: 3px 6px; background: var(--ground); }
|
|
756
|
+
.matrix .cell.fill-critical { background: var(--pt-solid); }
|
|
757
|
+
.matrix .cell.fill-high { background: var(--pt-hatch); }
|
|
758
|
+
.matrix .cell.fill-medium { background: var(--pt-half); }
|
|
759
|
+
.matrix .cell.fill-low { background: var(--pt-sparse); }
|
|
760
|
+
.matrix .cell:not([disabled]):hover .n { background: var(--frame); color: var(--ground); }
|
|
761
|
+
.matrix .cell[aria-pressed="true"] { box-shadow: inset 0 0 0 3px var(--accent); }
|
|
762
|
+
.matrix .cell[aria-pressed="true"] .n { background: var(--accent); color: var(--on-accent); }
|
|
763
|
+
.matrix .cell:focus-visible { outline: 2px solid var(--focus); outline-offset: -4px; }
|
|
764
|
+
|
|
765
|
+
/* Setup: three screens in one window. */
|
|
766
|
+
dialog.window.wide { width: min(640px, calc(100vw - 32px)); }
|
|
767
|
+
.setup { display: grid; gap: 14px; justify-items: stretch; }
|
|
768
|
+
.setup > .logotype.xl { justify-self: start; color: var(--text-1); margin: 4px 0 2px; }
|
|
769
|
+
.setup h2 { margin: 0; font: 600 20px / 1.3 var(--sans); color: var(--text-1); }
|
|
770
|
+
.setup p { margin: 0; }
|
|
771
|
+
.setup .gate { border-left: 3px solid var(--frame); padding-left: 10px; color: var(--text-1); }
|
|
772
|
+
.setup .form .field:first-child { margin-top: 0; }
|
|
773
|
+
.choice.big { padding: 14px 12px; }
|
|
774
|
+
.choice.big .t1 { font: 600 16px / 1.3 var(--sans); }
|
|
775
|
+
.win-bar .progress { font: 11px / 1 var(--px); padding-right: 6px; }
|
|
776
|
+
|
|
777
|
+
/* The approval window: pinstripes mean it waits on you. */
|
|
778
|
+
.win-bar.striped,
|
|
779
|
+
dialog.window > .win-bar.striped {
|
|
780
|
+
background: repeating-linear-gradient(to bottom, var(--frame) 0 1px, transparent 1px 2px) 0 8px / 100% 11px no-repeat, var(--ground);
|
|
781
|
+
color: var(--text-1);
|
|
782
|
+
}
|
|
783
|
+
.win-bar.striped .title { background: var(--ground); padding: 0 8px; margin: 0 auto; }
|
|
784
|
+
dialog.window > .win-bar.striped .icon.close-box::before { background: var(--ground); border-color: var(--frame); }
|
|
785
|
+
dialog.window > .win-bar.striped .icon.close-box { background: var(--ground); }
|
|
786
|
+
.approval { display: grid; gap: 10px; grid-template-columns: minmax(0, 1fr); }
|
|
787
|
+
.approval > * { min-width: 0; }
|
|
788
|
+
.approval h3 { margin: 0; font: 600 16px / 1.35 var(--sans); color: var(--text-1); }
|
|
789
|
+
.approval p { margin: 0; }
|
|
790
|
+
.approval .actions { margin-top: 6px; }
|
|
791
|
+
.approval kbd, .btn kbd { border-color: currentColor; }
|
|
792
|
+
.wait-note { display: flex; align-items: center; gap: 10px; margin: 14px 3px 14px 0; padding: 10px 12px; border: 1px solid var(--frame); box-shadow: 3px 3px 0 var(--frame); color: var(--text-1); flex-wrap: wrap; }
|
|
793
|
+
|
|
794
|
+
/* Step gutter: every line done gets a filled square; the line being worked on is hollow. */
|
|
795
|
+
.transcript.gutter { padding-left: 20px; }
|
|
796
|
+
.transcript.gutter .ln { position: relative; }
|
|
797
|
+
.transcript.gutter .ln::after { content: ""; position: absolute; left: -20px; top: 0.4em; width: 9px; height: 9px; border: 1px solid var(--frame); background: var(--frame); }
|
|
798
|
+
.transcript.gutter:not(.done) .ln:last-child::after { background: none; animation: blink 1s steps(1, end) infinite; }
|
|
799
|
+
|
|
800
|
+
@media (max-width: 760px) {
|
|
801
|
+
.rows.simple .row { grid-template-columns: minmax(0, 1fr) auto; }
|
|
802
|
+
.verdict-text { font-size: 18px; }
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
/* ── Phase 4: the halftone field ───────────────────────────────────────── */
|
|
806
|
+
|
|
807
|
+
.halftone-wrap { position: relative; min-height: 0; overflow: hidden; }
|
|
808
|
+
.halftone { position: absolute; inset: 0; width: 100%; height: 100%; color: var(--frame); }
|
|
809
|
+
.inspector-empty { display: flex; flex-direction: column; gap: 14px; }
|
|
810
|
+
.inspector-empty > .halftone-wrap { flex: 1; min-height: 160px; margin: 0 -14px; border-block: 1px solid var(--frame); }
|
|
811
|
+
.field-note { margin: 0; font-size: 12px; }
|
|
812
|
+
|
|
813
|
+
/* The desktop between the windows: denser dots for more serious open risk,
|
|
814
|
+
plain paper when nothing is open. */
|
|
815
|
+
.app[data-risk="0"] { background: var(--ground); }
|
|
816
|
+
.app[data-risk="1"] { background: conic-gradient(from 90deg at 1px 1px, transparent 75%, var(--desk) 0) 0 0 / 6px 6px, var(--ground); }
|
|
817
|
+
.app[data-risk="2"] { background: conic-gradient(from 90deg at 1px 1px, transparent 75%, var(--desk) 0) 0 0 / 4px 4px, var(--ground); }
|
|
818
|
+
.app[data-risk="3"] { background: conic-gradient(from 90deg at 1px 1px, transparent 75%, var(--desk) 0) 0 0 / 3px 3px, var(--ground); }
|
|
819
|
+
.app[data-risk="4"] { background: conic-gradient(from 90deg at 1px 1px, transparent 50%, var(--desk) 0 75%, transparent 0) 0 0 / 2px 2px, conic-gradient(var(--desk) 25%, transparent 0) 0 0 / 2px 2px, var(--ground); }
|