loadout-ai 0.4.1 → 0.5.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 +40 -0
- package/MASTER_PLAN.md +106 -33
- package/README.md +57 -19
- package/catalog/discovered.json +8422 -6957
- package/catalog/packages.json +26 -0
- package/dist/src/cli.js +140 -68
- package/dist/src/core/active-policy.js +48 -8
- package/dist/src/core/active-set.js +1 -1
- package/dist/src/core/adopt.js +1 -1
- package/dist/src/core/catalog-coverage.js +2 -1
- package/dist/src/core/catalog-install.js +23 -8
- package/dist/src/core/cli-guide.js +5 -2
- package/dist/src/core/codex-mcp.js +49 -5
- package/dist/src/core/completion.js +0 -3
- package/dist/src/core/health.js +19 -11
- package/dist/src/core/install.js +3 -3
- package/dist/src/core/mcp-recipes.js +13 -4
- package/dist/src/core/mcp.js +6 -5
- package/dist/src/core/model-config.js +1 -1
- package/dist/src/core/portable.js +1 -1
- package/dist/src/core/recommend.js +34 -18
- package/dist/src/core/remove.js +28 -2
- package/dist/src/core/runtime-tool-recipe.js +2 -2
- package/dist/src/core/runtime-tools.js +15 -4
- package/dist/src/core/snapshot.js +20 -0
- package/dist/src/core/state.js +9 -0
- package/dist/src/core/sync.js +1 -1
- package/dist/src/core/transaction.js +2 -1
- package/dist/src/shared/schemas.js +1 -0
- package/docs/CATALOG.md +3 -2
- package/docs/DISCOVERED.md +253 -255
- package/docs/FEATURE_TEST_MATRIX.md +19 -32
- package/docs/GITHUB_AUTHORIZATION.md +2 -2
- package/docs/TESTING.md +3 -16
- package/docs/USER_TEST_GUIDE.md +23 -9
- package/docs/assets/loadout-workflow.png +0 -0
- package/docs/evidence/readme-claims.json +0 -8
- package/docs/superpowers/plans/2026-07-20-loadout-readme-explainer.md +116 -0
- package/docs/superpowers/specs/2026-07-20-loadout-readme-explainer-design.md +55 -0
- package/package.json +4 -6
- package/dashboard/app.js +0 -607
- package/dashboard/index.html +0 -249
- package/dashboard/styles.css +0 -384
- package/dist/src/core/demo.js +0 -136
- package/dist/src/dashboard.js +0 -421
package/dashboard/index.html
DELETED
|
@@ -1,249 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="utf-8" />
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
-
<title>Loadout dashboard</title>
|
|
7
|
-
<link rel="stylesheet" href="/styles.css" />
|
|
8
|
-
</head>
|
|
9
|
-
<body>
|
|
10
|
-
<a class="skip-link" href="#dashboard-content">Skip to dashboard content</a>
|
|
11
|
-
<main id="dashboard-content" tabindex="-1">
|
|
12
|
-
<header aria-labelledby="page-title">
|
|
13
|
-
<p class="eyebrow">LOADOUT</p>
|
|
14
|
-
<h1 id="page-title">Your agent control center.</h1>
|
|
15
|
-
<p class="subhead">
|
|
16
|
-
Evidence health, safe updates, policy setups, and real packages from
|
|
17
|
-
this machine.
|
|
18
|
-
</p>
|
|
19
|
-
<nav class="dashboard-nav" aria-label="Dashboard views">
|
|
20
|
-
<a href="#home" data-route="home">Home</a>
|
|
21
|
-
<a href="#discover" data-route="discover">Discover</a>
|
|
22
|
-
<a href="#installed" data-route="installed">Installed</a>
|
|
23
|
-
<a href="#updates" data-route="updates">Updates</a>
|
|
24
|
-
</nav>
|
|
25
|
-
<div class="refresh-row">
|
|
26
|
-
<button
|
|
27
|
-
id="refresh-dashboard"
|
|
28
|
-
type="button"
|
|
29
|
-
aria-describedby="refresh-help"
|
|
30
|
-
>
|
|
31
|
-
Refresh dashboard
|
|
32
|
-
</button>
|
|
33
|
-
<span id="refresh-help" class="muted"
|
|
34
|
-
>Reads local Loadout data only. It does not install, update, or send
|
|
35
|
-
anything.</span
|
|
36
|
-
>
|
|
37
|
-
</div>
|
|
38
|
-
<p
|
|
39
|
-
id="dashboard-notice"
|
|
40
|
-
class="sr-only"
|
|
41
|
-
role="status"
|
|
42
|
-
aria-live="polite"
|
|
43
|
-
></p>
|
|
44
|
-
</header>
|
|
45
|
-
|
|
46
|
-
<section id="home" data-screen aria-labelledby="status-heading">
|
|
47
|
-
<div class="section-title">
|
|
48
|
-
<h2 id="status-heading">Agent status</h2>
|
|
49
|
-
</div>
|
|
50
|
-
<div
|
|
51
|
-
id="status"
|
|
52
|
-
class="state"
|
|
53
|
-
role="status"
|
|
54
|
-
aria-live="polite"
|
|
55
|
-
aria-busy="true"
|
|
56
|
-
>
|
|
57
|
-
Loading agent status…
|
|
58
|
-
</div>
|
|
59
|
-
</section>
|
|
60
|
-
|
|
61
|
-
<section data-screen="home" aria-labelledby="sync-heading">
|
|
62
|
-
<div class="section-title">
|
|
63
|
-
<h2 id="sync-heading">Synchronize</h2>
|
|
64
|
-
<span>Explicit approval required</span>
|
|
65
|
-
</div>
|
|
66
|
-
<div
|
|
67
|
-
class="action-bar"
|
|
68
|
-
role="group"
|
|
69
|
-
aria-label="Synchronize manifest actions"
|
|
70
|
-
>
|
|
71
|
-
<button id="preview-sync" type="button" aria-describedby="sync-help">
|
|
72
|
-
Preview manifest
|
|
73
|
-
</button>
|
|
74
|
-
<button id="apply-sync" type="button" disabled>
|
|
75
|
-
Apply safe plan
|
|
76
|
-
</button>
|
|
77
|
-
<button id="rollback-sync" class="secondary" type="button" disabled>
|
|
78
|
-
Undo last dashboard change
|
|
79
|
-
</button>
|
|
80
|
-
</div>
|
|
81
|
-
<p id="sync-help" class="muted">
|
|
82
|
-
Preview is read-only. Applying remains disabled until a safe plan is
|
|
83
|
-
reviewed and acknowledged.
|
|
84
|
-
</p>
|
|
85
|
-
<label class="approval-control" for="sync-acknowledgement"
|
|
86
|
-
><input id="sync-acknowledgement" type="checkbox" disabled /> I
|
|
87
|
-
reviewed this safe plan and want to apply it.</label
|
|
88
|
-
>
|
|
89
|
-
<div id="sync-result" class="state" role="status" aria-live="polite">
|
|
90
|
-
Preview <code>loadout.json</code> before applying anything.
|
|
91
|
-
</div>
|
|
92
|
-
</section>
|
|
93
|
-
|
|
94
|
-
<section data-screen="home" aria-labelledby="health-heading">
|
|
95
|
-
<div class="section-title">
|
|
96
|
-
<h2 id="health-heading">Health</h2>
|
|
97
|
-
<span id="health-label"></span>
|
|
98
|
-
</div>
|
|
99
|
-
<div
|
|
100
|
-
id="health"
|
|
101
|
-
class="state"
|
|
102
|
-
role="status"
|
|
103
|
-
aria-live="polite"
|
|
104
|
-
aria-busy="true"
|
|
105
|
-
>
|
|
106
|
-
Checking setup health…
|
|
107
|
-
</div>
|
|
108
|
-
</section>
|
|
109
|
-
|
|
110
|
-
<section id="updates" data-screen aria-labelledby="updates-heading">
|
|
111
|
-
<div class="section-title">
|
|
112
|
-
<h2 id="updates-heading">Updates</h2>
|
|
113
|
-
<span id="updates-count"></span>
|
|
114
|
-
</div>
|
|
115
|
-
<div
|
|
116
|
-
id="updates-list"
|
|
117
|
-
class="state"
|
|
118
|
-
role="status"
|
|
119
|
-
aria-live="polite"
|
|
120
|
-
aria-busy="true"
|
|
121
|
-
>
|
|
122
|
-
Checking installed packages…
|
|
123
|
-
</div>
|
|
124
|
-
</section>
|
|
125
|
-
|
|
126
|
-
<section data-screen="home" aria-labelledby="recommendations-heading">
|
|
127
|
-
<div class="section-title">
|
|
128
|
-
<h2 id="recommendations-heading">Rule-based project suggestions</h2>
|
|
129
|
-
<span id="project-signals"></span>
|
|
130
|
-
</div>
|
|
131
|
-
<div
|
|
132
|
-
id="recommendations"
|
|
133
|
-
class="grid state"
|
|
134
|
-
role="status"
|
|
135
|
-
aria-live="polite"
|
|
136
|
-
aria-busy="true"
|
|
137
|
-
>
|
|
138
|
-
Reading local project signals…
|
|
139
|
-
</div>
|
|
140
|
-
</section>
|
|
141
|
-
|
|
142
|
-
<section data-screen="home" aria-labelledby="profiles-heading">
|
|
143
|
-
<div class="section-title">
|
|
144
|
-
<h2 id="profiles-heading">Loadout policy profiles</h2>
|
|
145
|
-
<span>Preview only</span>
|
|
146
|
-
</div>
|
|
147
|
-
<div
|
|
148
|
-
id="profiles"
|
|
149
|
-
class="grid state"
|
|
150
|
-
role="status"
|
|
151
|
-
aria-live="polite"
|
|
152
|
-
aria-busy="true"
|
|
153
|
-
>
|
|
154
|
-
Loading profiles…
|
|
155
|
-
</div>
|
|
156
|
-
</section>
|
|
157
|
-
|
|
158
|
-
<section id="discover" data-screen aria-labelledby="catalog-heading">
|
|
159
|
-
<div class="section-title">
|
|
160
|
-
<h2 id="catalog-heading">Discover packages</h2>
|
|
161
|
-
<span id="catalog-count"></span>
|
|
162
|
-
</div>
|
|
163
|
-
<p class="muted">
|
|
164
|
-
Browse verified catalog records already available in this local
|
|
165
|
-
checkout. Package details are read-only; add a package to
|
|
166
|
-
<code>loadout.json</code>, then preview it before any write.
|
|
167
|
-
</p>
|
|
168
|
-
<div
|
|
169
|
-
class="catalog-filters"
|
|
170
|
-
role="search"
|
|
171
|
-
aria-label="Filter catalog packages"
|
|
172
|
-
>
|
|
173
|
-
<label for="catalog-search"
|
|
174
|
-
>Search
|
|
175
|
-
<input
|
|
176
|
-
id="catalog-search"
|
|
177
|
-
type="search"
|
|
178
|
-
autocomplete="off"
|
|
179
|
-
placeholder="Name, category, or repository"
|
|
180
|
-
/></label>
|
|
181
|
-
<label for="catalog-tier"
|
|
182
|
-
>Trust tier
|
|
183
|
-
<select id="catalog-tier">
|
|
184
|
-
<option value="">All tiers</option>
|
|
185
|
-
<option value="official">Official</option>
|
|
186
|
-
<option value="stable">Stable</option>
|
|
187
|
-
<option value="trending">Trending</option>
|
|
188
|
-
<option value="community">Community</option>
|
|
189
|
-
</select></label
|
|
190
|
-
>
|
|
191
|
-
<label for="catalog-category"
|
|
192
|
-
>Outcome
|
|
193
|
-
<select id="catalog-category">
|
|
194
|
-
<option value="">All outcomes</option>
|
|
195
|
-
</select></label
|
|
196
|
-
>
|
|
197
|
-
</div>
|
|
198
|
-
<div
|
|
199
|
-
id="catalog"
|
|
200
|
-
class="grid state"
|
|
201
|
-
role="status"
|
|
202
|
-
aria-live="polite"
|
|
203
|
-
aria-busy="true"
|
|
204
|
-
>
|
|
205
|
-
Loading catalog…
|
|
206
|
-
</div>
|
|
207
|
-
</section>
|
|
208
|
-
|
|
209
|
-
<section data-screen="discover" aria-labelledby="registry-heading">
|
|
210
|
-
<div class="section-title">
|
|
211
|
-
<h2 id="registry-heading">Local registry</h2>
|
|
212
|
-
<span id="registry-count"></span>
|
|
213
|
-
</div>
|
|
214
|
-
<div
|
|
215
|
-
id="registry"
|
|
216
|
-
class="grid state"
|
|
217
|
-
role="status"
|
|
218
|
-
aria-live="polite"
|
|
219
|
-
aria-busy="true"
|
|
220
|
-
>
|
|
221
|
-
Loading locally published packages…
|
|
222
|
-
</div>
|
|
223
|
-
</section>
|
|
224
|
-
|
|
225
|
-
<section id="installed" data-screen aria-labelledby="installed-heading">
|
|
226
|
-
<div class="section-title">
|
|
227
|
-
<h2 id="installed-heading">Installed packages</h2>
|
|
228
|
-
<span id="installed-count"></span>
|
|
229
|
-
</div>
|
|
230
|
-
<p id="last-snapshot" class="muted"></p>
|
|
231
|
-
<div
|
|
232
|
-
id="installed-list"
|
|
233
|
-
class="grid state"
|
|
234
|
-
role="status"
|
|
235
|
-
aria-live="polite"
|
|
236
|
-
aria-busy="true"
|
|
237
|
-
>
|
|
238
|
-
Reading managed package state…
|
|
239
|
-
</div>
|
|
240
|
-
</section>
|
|
241
|
-
|
|
242
|
-
<footer>
|
|
243
|
-
Dashboard mutations require a private session token, an explicit
|
|
244
|
-
preview, and acknowledgement. Risky plans remain CLI-only.
|
|
245
|
-
</footer>
|
|
246
|
-
</main>
|
|
247
|
-
<script type="module" src="/app.js"></script>
|
|
248
|
-
</body>
|
|
249
|
-
</html>
|
package/dashboard/styles.css
DELETED
|
@@ -1,384 +0,0 @@
|
|
|
1
|
-
:root {
|
|
2
|
-
color-scheme: dark;
|
|
3
|
-
font-family: Inter, ui-sans-serif, system-ui, sans-serif;
|
|
4
|
-
background: #101114;
|
|
5
|
-
color: #f4f4f5;
|
|
6
|
-
}
|
|
7
|
-
body {
|
|
8
|
-
margin: 0;
|
|
9
|
-
line-height: 1.5;
|
|
10
|
-
}
|
|
11
|
-
main {
|
|
12
|
-
max-width: 960px;
|
|
13
|
-
margin: 0 auto;
|
|
14
|
-
padding: 64px 24px;
|
|
15
|
-
}
|
|
16
|
-
header {
|
|
17
|
-
margin-bottom: 44px;
|
|
18
|
-
}
|
|
19
|
-
.eyebrow {
|
|
20
|
-
color: #a78bfa;
|
|
21
|
-
letter-spacing: 0.18em;
|
|
22
|
-
font-size: 12px;
|
|
23
|
-
font-weight: 700;
|
|
24
|
-
}
|
|
25
|
-
h1 {
|
|
26
|
-
font-size: clamp(2.3rem, 7vw, 5rem);
|
|
27
|
-
line-height: 0.98;
|
|
28
|
-
max-width: 720px;
|
|
29
|
-
margin: 12px 0;
|
|
30
|
-
}
|
|
31
|
-
.subhead {
|
|
32
|
-
color: #a1a1aa;
|
|
33
|
-
font-size: 18px;
|
|
34
|
-
}
|
|
35
|
-
h2 {
|
|
36
|
-
font-size: 24px;
|
|
37
|
-
}
|
|
38
|
-
.dashboard-nav {
|
|
39
|
-
display: flex;
|
|
40
|
-
flex-wrap: wrap;
|
|
41
|
-
gap: 8px;
|
|
42
|
-
margin-top: 24px;
|
|
43
|
-
}
|
|
44
|
-
.dashboard-nav a {
|
|
45
|
-
border: 1px solid #3f3f46;
|
|
46
|
-
border-radius: 999px;
|
|
47
|
-
color: #d4d4d8;
|
|
48
|
-
padding: 7px 12px;
|
|
49
|
-
text-decoration: none;
|
|
50
|
-
}
|
|
51
|
-
.dashboard-nav a[aria-current="page"] {
|
|
52
|
-
border-color: #8b5cf6;
|
|
53
|
-
background: #2e1065;
|
|
54
|
-
color: #ede9fe;
|
|
55
|
-
}
|
|
56
|
-
.dashboard-nav a:focus-visible {
|
|
57
|
-
outline: 3px solid #c4b5fd;
|
|
58
|
-
outline-offset: 2px;
|
|
59
|
-
}
|
|
60
|
-
.skip-link {
|
|
61
|
-
position: fixed;
|
|
62
|
-
z-index: 10;
|
|
63
|
-
top: 12px;
|
|
64
|
-
left: 12px;
|
|
65
|
-
transform: translateY(-160%);
|
|
66
|
-
border-radius: 8px;
|
|
67
|
-
background: #f4f4f5;
|
|
68
|
-
color: #18181b;
|
|
69
|
-
padding: 8px 12px;
|
|
70
|
-
font-weight: 700;
|
|
71
|
-
text-decoration: none;
|
|
72
|
-
}
|
|
73
|
-
.skip-link:focus {
|
|
74
|
-
transform: translateY(0);
|
|
75
|
-
outline: 3px solid #c4b5fd;
|
|
76
|
-
outline-offset: 2px;
|
|
77
|
-
}
|
|
78
|
-
.sr-only {
|
|
79
|
-
position: absolute;
|
|
80
|
-
width: 1px;
|
|
81
|
-
height: 1px;
|
|
82
|
-
padding: 0;
|
|
83
|
-
margin: -1px;
|
|
84
|
-
overflow: hidden;
|
|
85
|
-
clip: rect(0, 0, 0, 0);
|
|
86
|
-
white-space: nowrap;
|
|
87
|
-
border: 0;
|
|
88
|
-
}
|
|
89
|
-
.section-title {
|
|
90
|
-
display: flex;
|
|
91
|
-
align-items: baseline;
|
|
92
|
-
justify-content: space-between;
|
|
93
|
-
}
|
|
94
|
-
.section-title span,
|
|
95
|
-
small,
|
|
96
|
-
.muted {
|
|
97
|
-
color: #b4b4bc;
|
|
98
|
-
}
|
|
99
|
-
.state {
|
|
100
|
-
border: 1px solid #27272a;
|
|
101
|
-
border-radius: 14px;
|
|
102
|
-
padding: 18px;
|
|
103
|
-
color: #a1a1aa;
|
|
104
|
-
display: flex;
|
|
105
|
-
gap: 12px;
|
|
106
|
-
flex-wrap: wrap;
|
|
107
|
-
}
|
|
108
|
-
.success {
|
|
109
|
-
border-color: #14532d;
|
|
110
|
-
color: #bbf7d0;
|
|
111
|
-
}
|
|
112
|
-
.error {
|
|
113
|
-
border-color: #7f1d1d;
|
|
114
|
-
color: #fecaca;
|
|
115
|
-
}
|
|
116
|
-
.attention {
|
|
117
|
-
border-color: #854d0e;
|
|
118
|
-
color: #fef3c7;
|
|
119
|
-
}
|
|
120
|
-
.grid {
|
|
121
|
-
display: grid;
|
|
122
|
-
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
|
123
|
-
gap: 14px;
|
|
124
|
-
}
|
|
125
|
-
section[hidden] {
|
|
126
|
-
display: none;
|
|
127
|
-
}
|
|
128
|
-
article {
|
|
129
|
-
border: 1px solid #27272a;
|
|
130
|
-
border-radius: 14px;
|
|
131
|
-
padding: 18px;
|
|
132
|
-
background: #18181b;
|
|
133
|
-
}
|
|
134
|
-
article h3 {
|
|
135
|
-
margin: 0 0 8px;
|
|
136
|
-
}
|
|
137
|
-
article p {
|
|
138
|
-
min-height: 42px;
|
|
139
|
-
color: #d4d4d8;
|
|
140
|
-
line-height: 1.4;
|
|
141
|
-
}
|
|
142
|
-
small {
|
|
143
|
-
font-size: 12px;
|
|
144
|
-
}
|
|
145
|
-
.updates-grid {
|
|
146
|
-
display: grid;
|
|
147
|
-
gap: 12px;
|
|
148
|
-
}
|
|
149
|
-
.update-heading {
|
|
150
|
-
display: flex;
|
|
151
|
-
align-items: center;
|
|
152
|
-
justify-content: space-between;
|
|
153
|
-
gap: 12px;
|
|
154
|
-
}
|
|
155
|
-
.card-heading {
|
|
156
|
-
display: flex;
|
|
157
|
-
align-items: center;
|
|
158
|
-
justify-content: space-between;
|
|
159
|
-
gap: 12px;
|
|
160
|
-
}
|
|
161
|
-
.update-heading h3 {
|
|
162
|
-
margin: 0;
|
|
163
|
-
}
|
|
164
|
-
.badge {
|
|
165
|
-
border-radius: 999px;
|
|
166
|
-
padding: 4px 9px;
|
|
167
|
-
font-size: 11px;
|
|
168
|
-
color: #d4d4d8;
|
|
169
|
-
background: #27272a;
|
|
170
|
-
}
|
|
171
|
-
.badge.official {
|
|
172
|
-
background: #164e63;
|
|
173
|
-
color: #cffafe;
|
|
174
|
-
}
|
|
175
|
-
.badge.stable,
|
|
176
|
-
.badge.native {
|
|
177
|
-
background: #14532d;
|
|
178
|
-
color: #bbf7d0;
|
|
179
|
-
}
|
|
180
|
-
.badge.trending,
|
|
181
|
-
.badge.adapted {
|
|
182
|
-
background: #713f12;
|
|
183
|
-
color: #fef3c7;
|
|
184
|
-
}
|
|
185
|
-
.badge.community,
|
|
186
|
-
.badge.unsupported {
|
|
187
|
-
background: #3f3f46;
|
|
188
|
-
color: #e4e4e7;
|
|
189
|
-
}
|
|
190
|
-
.update-available {
|
|
191
|
-
border-color: #854d0e;
|
|
192
|
-
}
|
|
193
|
-
.update-available .badge {
|
|
194
|
-
color: #fef3c7;
|
|
195
|
-
background: #713f12;
|
|
196
|
-
}
|
|
197
|
-
.up-to-date .badge {
|
|
198
|
-
color: #bbf7d0;
|
|
199
|
-
background: #14532d;
|
|
200
|
-
}
|
|
201
|
-
.error-text {
|
|
202
|
-
color: #fecaca !important;
|
|
203
|
-
min-height: auto;
|
|
204
|
-
}
|
|
205
|
-
details {
|
|
206
|
-
margin-top: 10px;
|
|
207
|
-
color: #d4d4d8;
|
|
208
|
-
}
|
|
209
|
-
summary {
|
|
210
|
-
cursor: pointer;
|
|
211
|
-
}
|
|
212
|
-
summary:focus-visible {
|
|
213
|
-
outline: 3px solid #c4b5fd;
|
|
214
|
-
outline-offset: 3px;
|
|
215
|
-
border-radius: 4px;
|
|
216
|
-
}
|
|
217
|
-
li {
|
|
218
|
-
margin: 5px 0;
|
|
219
|
-
}
|
|
220
|
-
dl {
|
|
221
|
-
display: grid;
|
|
222
|
-
grid-template-columns: max-content 1fr;
|
|
223
|
-
gap: 6px 12px;
|
|
224
|
-
margin: 12px 0;
|
|
225
|
-
}
|
|
226
|
-
dt {
|
|
227
|
-
color: #a1a1aa;
|
|
228
|
-
}
|
|
229
|
-
dd {
|
|
230
|
-
margin: 0;
|
|
231
|
-
overflow-wrap: anywhere;
|
|
232
|
-
}
|
|
233
|
-
.safety {
|
|
234
|
-
border-left: 3px solid #f59e0b;
|
|
235
|
-
padding-left: 10px;
|
|
236
|
-
}
|
|
237
|
-
.health-list {
|
|
238
|
-
border: 1px solid #27272a;
|
|
239
|
-
border-radius: 14px;
|
|
240
|
-
padding: 18px;
|
|
241
|
-
}
|
|
242
|
-
.health-list p {
|
|
243
|
-
margin: 10px 0 0;
|
|
244
|
-
color: #d4d4d8;
|
|
245
|
-
}
|
|
246
|
-
.metric-row {
|
|
247
|
-
display: flex;
|
|
248
|
-
align-items: baseline;
|
|
249
|
-
gap: 8px;
|
|
250
|
-
flex-wrap: wrap;
|
|
251
|
-
}
|
|
252
|
-
.metric-row strong {
|
|
253
|
-
font-size: 24px;
|
|
254
|
-
}
|
|
255
|
-
.metric-row span {
|
|
256
|
-
color: #a1a1aa;
|
|
257
|
-
margin-right: 14px;
|
|
258
|
-
}
|
|
259
|
-
.finding-level {
|
|
260
|
-
display: inline-block;
|
|
261
|
-
min-width: 58px;
|
|
262
|
-
color: #a1a1aa;
|
|
263
|
-
text-transform: uppercase;
|
|
264
|
-
font-size: 10px;
|
|
265
|
-
letter-spacing: 0.08em;
|
|
266
|
-
}
|
|
267
|
-
section {
|
|
268
|
-
margin-top: 36px;
|
|
269
|
-
}
|
|
270
|
-
footer {
|
|
271
|
-
margin-top: 52px;
|
|
272
|
-
padding-top: 18px;
|
|
273
|
-
border-top: 1px solid #27272a;
|
|
274
|
-
color: #71717a;
|
|
275
|
-
font-size: 13px;
|
|
276
|
-
}
|
|
277
|
-
.action-bar {
|
|
278
|
-
display: flex;
|
|
279
|
-
flex-wrap: wrap;
|
|
280
|
-
gap: 10px;
|
|
281
|
-
margin-bottom: 12px;
|
|
282
|
-
}
|
|
283
|
-
.refresh-row {
|
|
284
|
-
display: flex;
|
|
285
|
-
align-items: center;
|
|
286
|
-
flex-wrap: wrap;
|
|
287
|
-
gap: 12px;
|
|
288
|
-
margin-top: 20px;
|
|
289
|
-
}
|
|
290
|
-
.refresh-row .muted {
|
|
291
|
-
max-width: 560px;
|
|
292
|
-
font-size: 13px;
|
|
293
|
-
}
|
|
294
|
-
.catalog-filters {
|
|
295
|
-
display: flex;
|
|
296
|
-
flex-wrap: wrap;
|
|
297
|
-
gap: 12px;
|
|
298
|
-
margin: 12px 0 16px;
|
|
299
|
-
}
|
|
300
|
-
.catalog-filters label {
|
|
301
|
-
display: grid;
|
|
302
|
-
gap: 5px;
|
|
303
|
-
color: #d4d4d8;
|
|
304
|
-
font-size: 13px;
|
|
305
|
-
}
|
|
306
|
-
input[type="search"],
|
|
307
|
-
select {
|
|
308
|
-
border: 1px solid #3f3f46;
|
|
309
|
-
border-radius: 8px;
|
|
310
|
-
background: #18181b;
|
|
311
|
-
color: #f4f4f5;
|
|
312
|
-
font: inherit;
|
|
313
|
-
min-height: 38px;
|
|
314
|
-
padding: 0 10px;
|
|
315
|
-
}
|
|
316
|
-
input[type="search"] {
|
|
317
|
-
min-width: min(300px, 75vw);
|
|
318
|
-
}
|
|
319
|
-
.approval-control {
|
|
320
|
-
display: flex;
|
|
321
|
-
align-items: flex-start;
|
|
322
|
-
gap: 8px;
|
|
323
|
-
margin: 14px 0;
|
|
324
|
-
color: #d4d4d8;
|
|
325
|
-
}
|
|
326
|
-
.approval-control input {
|
|
327
|
-
width: 18px;
|
|
328
|
-
height: 18px;
|
|
329
|
-
margin-top: 2px;
|
|
330
|
-
accent-color: #8b5cf6;
|
|
331
|
-
}
|
|
332
|
-
button {
|
|
333
|
-
appearance: none;
|
|
334
|
-
border: 1px solid #7c3aed;
|
|
335
|
-
border-radius: 10px;
|
|
336
|
-
background: #7c3aed;
|
|
337
|
-
color: white;
|
|
338
|
-
padding: 10px 14px;
|
|
339
|
-
font: inherit;
|
|
340
|
-
font-weight: 650;
|
|
341
|
-
cursor: pointer;
|
|
342
|
-
}
|
|
343
|
-
button.secondary {
|
|
344
|
-
background: transparent;
|
|
345
|
-
color: #d4d4d8;
|
|
346
|
-
border-color: #3f3f46;
|
|
347
|
-
}
|
|
348
|
-
button:disabled {
|
|
349
|
-
cursor: not-allowed;
|
|
350
|
-
opacity: 0.45;
|
|
351
|
-
}
|
|
352
|
-
button:focus-visible,
|
|
353
|
-
input:focus-visible {
|
|
354
|
-
outline: 3px solid #c4b5fd;
|
|
355
|
-
outline-offset: 2px;
|
|
356
|
-
}
|
|
357
|
-
code {
|
|
358
|
-
color: #c4b5fd;
|
|
359
|
-
}
|
|
360
|
-
@media (max-width: 560px) {
|
|
361
|
-
main {
|
|
362
|
-
padding: 42px 16px;
|
|
363
|
-
}
|
|
364
|
-
.section-title {
|
|
365
|
-
align-items: flex-start;
|
|
366
|
-
flex-direction: column;
|
|
367
|
-
gap: 2px;
|
|
368
|
-
}
|
|
369
|
-
.section-title h2 {
|
|
370
|
-
margin-bottom: 0;
|
|
371
|
-
}
|
|
372
|
-
.refresh-row {
|
|
373
|
-
align-items: flex-start;
|
|
374
|
-
flex-direction: column;
|
|
375
|
-
}
|
|
376
|
-
.catalog-filters label,
|
|
377
|
-
input[type="search"],
|
|
378
|
-
select {
|
|
379
|
-
width: 100%;
|
|
380
|
-
}
|
|
381
|
-
.action-bar > button {
|
|
382
|
-
flex: 1 1 180px;
|
|
383
|
-
}
|
|
384
|
-
}
|