@bongos/core 1.17.3 → 1.18.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/.bongos-core.json +161 -91
- package/.devcontainer/healthcheck.sh +0 -0
- package/.devcontainer/init-firewall.sh +0 -0
- package/.devcontainer/post-create.sh +0 -0
- package/GOVERNANCE.md +1 -1
- package/README.md +26 -22
- package/bin/bongos.js +0 -0
- package/docker-entrypoint.sh +0 -0
- package/docs/adr/0139-platform-history-migration-to-cloudbongos.md +94 -0
- package/docs/adr/0140-cloudbongos-standalone-reprovision.md +43 -0
- package/docs/adr/README.md +3 -0
- package/docs/api/openapi.json +4 -345
- package/docs/api-reference.md +5 -17
- package/docs/file-map.md +7 -25
- package/docs/onboarding/diagrams/05-versioning.mmd +4 -6
- package/docs/onboarding/diagrams/assertions.json +5 -9
- package/modules/hall-ui/public/builders.js +37 -0
- package/modules/hall-ui/public/goals-page.js +98 -176
- package/modules/hall-ui/public/goals.css +183 -0
- package/modules/hall-ui/public/goals.html +35 -261
- package/modules/hall-ui/public/goals.js +7 -2
- package/modules/hall-ui/public/hall-widgets.js +12 -4
- package/modules/hall-ui/public/settings.css +355 -0
- package/modules/hall-ui/public/settings.html +86 -414
- package/modules/hall-ui/public/settings.js +96 -35
- package/modules/hall-ui/public/style.css +31 -0
- package/modules/hall-ui/public/watch.css +184 -0
- package/modules/hall-ui/public/watch.html +111 -285
- package/modules/hall-ui/public/watch.js +59 -21
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/public-landing/create.html +83 -7
- package/public-landing/index.html +11 -76
- package/scripts/cron/style_guide_audit.sh +0 -0
- package/scripts/gds/api.js +0 -0
- package/scripts/gds/architect-audit.js +0 -0
- package/scripts/gds/audit-authorship.sh +0 -0
- package/scripts/gds/audit-replay.sh +0 -0
- package/scripts/gds/box.js +0 -0
- package/scripts/gds/capture.js +0 -0
- package/scripts/gds/conductor-dispatch.js +0 -0
- package/scripts/gds/coreB-carve-proof.sh +0 -0
- package/scripts/gds/db-backup-nightly.sh +0 -0
- package/scripts/gds/db-backup-offsite.sh +0 -0
- package/scripts/gds/doctor.js +0 -0
- package/scripts/gds/grade-smoke.js +0 -0
- package/scripts/gds/hooks/pre-push.js +0 -0
- package/scripts/gds/install-git-hooks.js +0 -0
- package/scripts/gds/main-audit.js +0 -0
- package/scripts/gds/oauth-secret.js +0 -0
- package/scripts/gds/onboarding-analyze.js +0 -0
- package/scripts/gds/onboarding-ship.js +0 -0
- package/scripts/gds/paste-token.js +0 -0
- package/scripts/gds/portability-smoke-art.sh +0 -0
- package/scripts/gds/portability-smoke-memory.sh +0 -0
- package/scripts/gds/provision.js +125 -4
- package/scripts/gds/push-main.js +0 -0
- package/scripts/gds/render-ideas.js +0 -0
- package/scripts/gds/security-baseline-check.sh +0 -0
- package/scripts/gds/session.js +0 -0
- package/scripts/gds/ship.js +11 -1
- package/scripts/gds/smoke-batch-claim.sh +0 -0
- package/scripts/gds/smoke-batch-release.sh +0 -0
- package/scripts/gds/smoke-box.sh +0 -0
- package/scripts/gds/smoke-claim-consistency.sh +0 -0
- package/scripts/gds/smoke-dependencies.sh +0 -0
- package/scripts/gds/smoke-write.sh +0 -0
- package/scripts/hall-preview/fixtures/access-requests.json +20 -1
- package/scripts/hall-preview/fixtures/audit-log.json +68 -1
- package/scripts/hall-preview/fixtures/blockers__detail.json +12 -0
- package/scripts/hall-preview/fixtures/box__me.json +5 -0
- package/scripts/hall-preview/fixtures/boxes__cost-ledger.json +69 -1
- package/scripts/hall-preview/fixtures/builders__roster.json +48 -1
- package/scripts/hall-preview/fixtures/grades__by-builder.json +32 -1
- package/scripts/hall-preview/fixtures/inbox__detail.json +15 -0
- package/scripts/hall-preview/fixtures/me__art-key__own.json +6 -0
- package/scripts/hall-preview/fixtures/me__event-sound-prefs.json +209 -0
- package/scripts/hall-preview/fixtures/me__render.json +5 -0
- package/scripts/hall-preview/fixtures/me__skill-prefs.json +143 -0
- package/scripts/hall-preview/fixtures/me__sound-prefs.json +67 -0
- package/scripts/hall-preview/fixtures/me__wandering.json +43 -0
- package/scripts/hall-preview/fixtures/override-requests.json +15 -1
- package/scripts/hall-preview/fixtures/security__docs.json +10 -1
- package/scripts/hall-preview/fixtures/security__reports.json +31 -1
- package/scripts/hall-preview/fixtures/sessions__search.json +9 -1
- package/scripts/hall-preview/server.js +18 -1
- package/scripts/migrate.sh +0 -0
- package/scripts/migrate_cost_ledger.sh +0 -0
- package/scripts/render-diagrams.sh +0 -0
- package/scripts/security/dep-audit.js +0 -0
- package/scripts/setup-builder.js +0 -0
- package/scripts/setup-builder.sh +0 -0
- package/scripts/snapshots/maybe-render-on-deploy.sh +0 -0
- package/src/module-api.js +20 -1
- package/tests/provision.mjs +69 -0
|
@@ -1026,8 +1026,8 @@
|
|
|
1026
1026
|
renderArtKeyCard(res.data);
|
|
1027
1027
|
wireArtKeyCard();
|
|
1028
1028
|
$('#art-key').hidden = false;
|
|
1029
|
-
//
|
|
1030
|
-
|
|
1029
|
+
// The hall's "Add your key" action / CLI nudge deep link (#art-key) is
|
|
1030
|
+
// landed by load()'s final applyHash() once every section has revealed.
|
|
1031
1031
|
} catch (err) {
|
|
1032
1032
|
console.error('[settings] failed to load art key', err);
|
|
1033
1033
|
$('#art-key').hidden = false;
|
|
@@ -1068,49 +1068,100 @@
|
|
|
1068
1068
|
}
|
|
1069
1069
|
}
|
|
1070
1070
|
|
|
1071
|
-
// ---- section rail (grouped sub-nav, task 1723)
|
|
1071
|
+
// ---- section rail (grouped sub-nav, task 1723 → kit, task 2172) -----------
|
|
1072
1072
|
//
|
|
1073
|
-
// The sections sit in six groups behind a left rail (#settings-rail)
|
|
1074
|
-
//
|
|
1075
|
-
//
|
|
1076
|
-
//
|
|
1077
|
-
// first, so
|
|
1078
|
-
|
|
1079
|
-
|
|
1073
|
+
// The sections sit in six groups behind a left rail (#settings-rail), built by
|
|
1074
|
+
// OTBKit.makeSectionRail in switch mode — the idiom this page originated. CSS
|
|
1075
|
+
// shows only the active group (.settings-groups[data-active]); a section's own
|
|
1076
|
+
// [hidden] attribute still wins, so the per-section reveal logic above is
|
|
1077
|
+
// unchanged. Deep links activate their group first, so scrollIntoView lands on
|
|
1078
|
+
// a visible section.
|
|
1079
|
+
|
|
1080
|
+
// The Dev box group (box panel, desktop app, pairing) exists only where the
|
|
1081
|
+
// dev-box module runs — a vanilla instance has no boxes to manage, so the
|
|
1082
|
+
// whole group (rail entry included) stays out rather than showing an empty
|
|
1083
|
+
// shell. RAIL_GROUPS derives from the items so a #dev-box anchor no-ops too.
|
|
1084
|
+
const RAIL_ITEMS = [
|
|
1085
|
+
{ id: 'account', label: 'Account' },
|
|
1086
|
+
{ id: 'access', label: 'Access & keys' },
|
|
1087
|
+
...(window.OTB.moduleOn('dev-box') ? [{ id: 'devbox', label: 'Dev box' }] : []),
|
|
1088
|
+
{ id: 'preferences', label: 'Preferences' },
|
|
1089
|
+
{ id: 'sound', label: 'Sound' },
|
|
1090
|
+
];
|
|
1091
|
+
const RAIL_GROUPS = RAIL_ITEMS.map((i) => i.id).concat('extensions');
|
|
1092
|
+
let rail = null;
|
|
1093
|
+
|
|
1094
|
+
// task 2172 — stable per-panel anchors (/settings#cli, /settings#dev-box, …)
|
|
1095
|
+
// so skills and docs can deep-link a panel without depending on internal
|
|
1096
|
+
// section ids. #art-key predates the map and IS its section id (the hall's
|
|
1097
|
+
// "Add your key" action + the CLI nudge target it) — kept verbatim.
|
|
1098
|
+
const PANEL_ANCHORS = {
|
|
1099
|
+
'connections': 'connections-scroll',
|
|
1100
|
+
'display-name': 'display-name-scroll',
|
|
1101
|
+
'disciplines': 'craft-scroll',
|
|
1102
|
+
'cli': 'cli-scroll',
|
|
1103
|
+
'art-key': 'art-key',
|
|
1104
|
+
'dev-box': 'box-scroll',
|
|
1105
|
+
'dev-box-app': 'boxapp-scroll',
|
|
1106
|
+
'pairing': 'pairing-scroll',
|
|
1107
|
+
'wandering': 'wandering-scroll',
|
|
1108
|
+
'rendering': 'render-scroll',
|
|
1109
|
+
'voices': 'voices-scroll',
|
|
1110
|
+
'sounds': 'sounds-scroll',
|
|
1111
|
+
'event-sounds': 'event-sounds-scroll',
|
|
1112
|
+
};
|
|
1080
1113
|
|
|
1081
1114
|
function activateGroup(group, opts) {
|
|
1082
1115
|
if (!RAIL_GROUPS.includes(group)) return;
|
|
1083
1116
|
const groups = document.getElementById('settings-groups');
|
|
1084
1117
|
if (!groups) return;
|
|
1085
1118
|
groups.dataset.active = group;
|
|
1086
|
-
|
|
1087
|
-
a.classList.toggle('rail-link--active', a.dataset.group === group);
|
|
1088
|
-
});
|
|
1119
|
+
rail?.activate(group);
|
|
1089
1120
|
if (!opts || opts.scroll !== false) window.scrollTo({ top: 0 });
|
|
1090
1121
|
}
|
|
1091
1122
|
|
|
1092
|
-
//
|
|
1093
|
-
// of an element inside a grouped section (#art-key
|
|
1094
|
-
function
|
|
1123
|
+
// Resolve a #hash to { group, el }: a group name itself (#access), a panel
|
|
1124
|
+
// anchor (#cli), or the id of an element inside a grouped section (#art-key).
|
|
1125
|
+
function resolveHash(hash) {
|
|
1095
1126
|
const id = String(hash || '').replace(/^#/, '');
|
|
1096
1127
|
if (!id) return null;
|
|
1097
|
-
if (RAIL_GROUPS.includes(id)) return id;
|
|
1098
|
-
const el = document.getElementById(id);
|
|
1128
|
+
if (RAIL_GROUPS.includes(id)) return { group: id, el: null };
|
|
1129
|
+
const el = document.getElementById(PANEL_ANCHORS[id] || id);
|
|
1099
1130
|
const grouped = el && el.closest ? el.closest('[data-group]') : null;
|
|
1100
|
-
return grouped ? grouped.getAttribute('data-group') : null;
|
|
1131
|
+
return grouped ? { group: grouped.getAttribute('data-group'), el } : null;
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
// Activate the hash's group; for a panel anchor also scroll the panel into
|
|
1135
|
+
// view (rail highlight = the group). Runs on load, after data lands (late-
|
|
1136
|
+
// revealed sections), and on hashchange.
|
|
1137
|
+
function applyHash(opts) {
|
|
1138
|
+
const t = resolveHash(window.location.hash);
|
|
1139
|
+
if (!t) return;
|
|
1140
|
+
activateGroup(t.group, { scroll: false });
|
|
1141
|
+
if (t.el && (!opts || opts.scroll !== false)) {
|
|
1142
|
+
t.el.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
1143
|
+
} else if (!t.el) {
|
|
1144
|
+
window.scrollTo({ top: 0 });
|
|
1145
|
+
}
|
|
1101
1146
|
}
|
|
1102
1147
|
|
|
1103
1148
|
function wireRail() {
|
|
1104
|
-
const
|
|
1105
|
-
if (!
|
|
1106
|
-
rail.
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1149
|
+
const mount = document.getElementById('settings-rail');
|
|
1150
|
+
if (!mount || !window.OTBKit) return;
|
|
1151
|
+
rail = window.OTBKit.makeSectionRail({
|
|
1152
|
+
mount,
|
|
1153
|
+
items: RAIL_ITEMS,
|
|
1154
|
+
mode: 'switch',
|
|
1155
|
+
onSwitch: (key) => {
|
|
1156
|
+
activateGroup(key);
|
|
1157
|
+
// Reflect the group in the URL so the view is shareable; replaceState
|
|
1158
|
+
// keeps Back for leaving the page, not retracing rail clicks.
|
|
1159
|
+
history.replaceState(null, '', window.location.pathname + window.location.search + `#${key}`);
|
|
1160
|
+
},
|
|
1111
1161
|
});
|
|
1112
|
-
|
|
1113
|
-
|
|
1162
|
+
rail.activate('account');
|
|
1163
|
+
applyHash({ scroll: false });
|
|
1164
|
+
window.addEventListener('hashchange', () => applyHash());
|
|
1114
1165
|
}
|
|
1115
1166
|
|
|
1116
1167
|
// Hide the rail + groups entirely while the not-signed-in gate is showing —
|
|
@@ -1166,10 +1217,14 @@
|
|
|
1166
1217
|
|
|
1167
1218
|
// DEV BOX — full box management (online terminal + SSH + close), #807.
|
|
1168
1219
|
setupBox();
|
|
1169
|
-
// DEV BOX APP
|
|
1170
|
-
//
|
|
1171
|
-
|
|
1172
|
-
|
|
1220
|
+
// DEV BOX APP + PAIRING — revealed once we know the viewer is a real builder,
|
|
1221
|
+
// and only where the dev-box module runs (the group's rail entry is gated
|
|
1222
|
+
// the same way above — task 2172).
|
|
1223
|
+
if (window.OTB.moduleOn('dev-box')) {
|
|
1224
|
+
$('#boxapp-scroll').hidden = false;
|
|
1225
|
+
$('#pairing-scroll').hidden = false;
|
|
1226
|
+
loadDevboxLatestVersion(); // #924: best-effort "latest version: X" courtesy line
|
|
1227
|
+
}
|
|
1173
1228
|
// CONNECTIONS — Discord (hidden unless the server has Discord configured).
|
|
1174
1229
|
setupConnections(me && me.discord ? me.discord : null);
|
|
1175
1230
|
// CLI ACCESS — re-issue a CLI bearer from this browser session.
|
|
@@ -1177,10 +1232,13 @@
|
|
|
1177
1232
|
// MODULE PANELS — render any Settings panels modules contributed via the
|
|
1178
1233
|
// seam (BV1.R42). None today; ready for dev-box/discord/art once they leave core.
|
|
1179
1234
|
mountContributedPanels();
|
|
1180
|
-
// Reveal the Extensions rail entry only when a module actually contributed
|
|
1235
|
+
// Reveal the Extensions rail entry only when a module actually contributed:
|
|
1236
|
+
// the kit rail re-renders from the item list, then re-marks the active group.
|
|
1181
1237
|
const contributed = $('#contributed-panels');
|
|
1182
|
-
|
|
1183
|
-
|
|
1238
|
+
if (rail && contributed && contributed.children.length > 0) {
|
|
1239
|
+
rail.refresh([...RAIL_ITEMS, { id: 'extensions', label: 'Extensions' }]);
|
|
1240
|
+
rail.activate($('#settings-groups')?.dataset.active || 'account');
|
|
1241
|
+
}
|
|
1184
1242
|
|
|
1185
1243
|
// Voices loads independently — its own endpoint + its own try/catch.
|
|
1186
1244
|
await loadVoices();
|
|
@@ -1195,6 +1253,9 @@
|
|
|
1195
1253
|
// Image key (per-builder Gemini key, task 1013) — own try/catch; `me` carries
|
|
1196
1254
|
// the `needs` art_key item that drives the covered/action-needed banner.
|
|
1197
1255
|
await loadArtKey(me);
|
|
1256
|
+
// Every section has now loaded/revealed — land any panel-anchor deep link
|
|
1257
|
+
// (/settings#cli, #dev-box, …) on its visible section.
|
|
1258
|
+
applyHash();
|
|
1198
1259
|
}
|
|
1199
1260
|
|
|
1200
1261
|
// #924: show the current published Dev Box app version next to the download
|
|
@@ -1914,3 +1914,34 @@ a.stat-tile:hover {
|
|
|
1914
1914
|
.proj-head .scroll__h { margin: 0; }
|
|
1915
1915
|
/* The over-budget "More" row — one quiet line, not a card. */
|
|
1916
1916
|
.home-more { margin: 0; font-size: 13px; color: var(--ink-soft); }
|
|
1917
|
+
|
|
1918
|
+
/* task 2184: two-column main zone on wide screens — Home reads as a
|
|
1919
|
+
dashboard, not a stack. The attention inbox (and the More row) span both
|
|
1920
|
+
columns; the work + Projects cards sit side by side. Mirrors the
|
|
1921
|
+
.view-zone--band grid idiom (cards drop their own margins inside a grid). */
|
|
1922
|
+
#zone-home-main { display: grid; grid-template-columns: minmax(0, 1fr); gap: 20px; align-items: start; }
|
|
1923
|
+
#zone-home-main > .scroll { margin: 0; }
|
|
1924
|
+
@media (min-width: 1024px) {
|
|
1925
|
+
#zone-home-main { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
1926
|
+
#zone-home-main > #attention-scroll,
|
|
1927
|
+
#zone-home-main > #home-more-row,
|
|
1928
|
+
#zone-home-main > #zone-home-overflow { grid-column: 1 / -1; }
|
|
1929
|
+
}
|
|
1930
|
+
|
|
1931
|
+
/* task 2184: the "Next up" slice in the Your-work card — the page's answer to
|
|
1932
|
+
"what's my next action". Quiet rows, accented title, one foot link. */
|
|
1933
|
+
.next-up { list-style: none; margin: 0 0 4px; padding: 0; display: flex; flex-direction: column; gap: 8px; }
|
|
1934
|
+
.next-up__item {
|
|
1935
|
+
display: flex;
|
|
1936
|
+
flex-direction: column;
|
|
1937
|
+
gap: 2px;
|
|
1938
|
+
padding: 9px 12px;
|
|
1939
|
+
border: 1px solid var(--border);
|
|
1940
|
+
border-left: 3px solid color-mix(in srgb, var(--accent) 55%, var(--border));
|
|
1941
|
+
border-radius: var(--radius-sm);
|
|
1942
|
+
background: var(--surface-2);
|
|
1943
|
+
}
|
|
1944
|
+
.next-up__title { font-weight: 600; font-size: 13.5px; color: var(--ink); }
|
|
1945
|
+
.next-up__title:hover { color: var(--accent-text); }
|
|
1946
|
+
.next-up__meta { font-size: 12px; color: var(--ink-faint); font-variant-numeric: tabular-nums; }
|
|
1947
|
+
.next-up__foot { margin: 0 0 14px; font-size: 13px; }
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/* watch.css — page-local styles for Watch (task 2173; extracted from
|
|
2
|
+
watch.html's old inline <style> per the hall placement rules). Built on the
|
|
3
|
+
shared design system's derived tokens; class names are load-bearing
|
|
4
|
+
(watch.js writes them). The attention row is the shared .stat-row/.stat-tile;
|
|
5
|
+
tabs/pager/empty states come from style.css's hall-kit section. */
|
|
6
|
+
|
|
7
|
+
/* task 2173 — the attention row sits above the tabs; a touch tighter than the
|
|
8
|
+
Home tiles (this is a dashboard header, not a landing zone). */
|
|
9
|
+
.watch-attention { margin: 0 0 14px; }
|
|
10
|
+
.watch-attention .stat-tile { min-height: 76px; padding: 12px 16px; }
|
|
11
|
+
.watch-attention .stat-tile__num { font-size: 23px; }
|
|
12
|
+
|
|
13
|
+
/* task 2173 density pass — panels stack inside tab panes. */
|
|
14
|
+
[id^="pane-"] .scroll { padding: 16px 18px; margin: 0 0 14px; }
|
|
15
|
+
|
|
16
|
+
.watch-stats {
|
|
17
|
+
display: grid;
|
|
18
|
+
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
|
|
19
|
+
gap: 12px;
|
|
20
|
+
margin-top: 6px;
|
|
21
|
+
}
|
|
22
|
+
.watch-stat {
|
|
23
|
+
background: var(--surface);
|
|
24
|
+
border: 1px solid var(--border);
|
|
25
|
+
border-radius: var(--radius-sm);
|
|
26
|
+
padding: 12px 14px;
|
|
27
|
+
text-align: center;
|
|
28
|
+
}
|
|
29
|
+
.watch-stat__num {
|
|
30
|
+
font-family: var(--font-display);
|
|
31
|
+
font-size: 1.5rem;
|
|
32
|
+
font-weight: 650;
|
|
33
|
+
color: var(--ink);
|
|
34
|
+
line-height: 1.2;
|
|
35
|
+
font-variant-numeric: tabular-nums;
|
|
36
|
+
}
|
|
37
|
+
.watch-stat__label {
|
|
38
|
+
font-size: 11px;
|
|
39
|
+
font-weight: 600;
|
|
40
|
+
color: var(--ink-faint);
|
|
41
|
+
text-transform: uppercase;
|
|
42
|
+
letter-spacing: 0.06em;
|
|
43
|
+
margin-top: 4px;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.watch-table-wrap { overflow-x: auto; margin-top: 6px; }
|
|
47
|
+
table.watch {
|
|
48
|
+
width: 100%;
|
|
49
|
+
border-collapse: collapse;
|
|
50
|
+
font-size: 13px;
|
|
51
|
+
color: var(--ink);
|
|
52
|
+
}
|
|
53
|
+
table.watch th, table.watch td {
|
|
54
|
+
padding: 6px 10px;
|
|
55
|
+
text-align: left;
|
|
56
|
+
border-bottom: 1px solid var(--border);
|
|
57
|
+
vertical-align: top;
|
|
58
|
+
}
|
|
59
|
+
table.watch th {
|
|
60
|
+
font-size: 11px;
|
|
61
|
+
font-weight: 600;
|
|
62
|
+
text-transform: uppercase;
|
|
63
|
+
letter-spacing: 0.06em;
|
|
64
|
+
color: var(--ink-faint);
|
|
65
|
+
border-bottom: 1px solid var(--border-strong);
|
|
66
|
+
white-space: nowrap;
|
|
67
|
+
}
|
|
68
|
+
table.watch td.num { text-align: right; font-variant-numeric: tabular-nums; }
|
|
69
|
+
table.watch td.warn { color: var(--danger); font-weight: 600; }
|
|
70
|
+
table.watch tr:hover td { background: var(--surface-2); }
|
|
71
|
+
/* the kit ledger (audit log) shares the same numeric-cell affordances */
|
|
72
|
+
.ledger td.num { text-align: right; font-variant-numeric: tabular-nums; }
|
|
73
|
+
.ledger td.num.warn { color: var(--danger); font-weight: 600; }
|
|
74
|
+
.watch-mono { font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 0.84rem; color: var(--info); }
|
|
75
|
+
.watch-empty { color: var(--ink-faint); font-size: 13px; padding: 10px 0; }
|
|
76
|
+
.watch-note { color: var(--ink-faint); font-size: 12.5px; margin-top: 10px; }
|
|
77
|
+
.watch-rank { font-size: 12px; color: var(--ink-faint); }
|
|
78
|
+
.watch-doc {
|
|
79
|
+
white-space: pre-wrap;
|
|
80
|
+
word-break: break-word;
|
|
81
|
+
font-family: ui-monospace, "SF Mono", Menlo, monospace;
|
|
82
|
+
font-size: 0.8rem;
|
|
83
|
+
line-height: 1.5;
|
|
84
|
+
max-height: 60vh;
|
|
85
|
+
overflow-y: auto;
|
|
86
|
+
padding: 12px;
|
|
87
|
+
margin-top: 8px;
|
|
88
|
+
background: var(--surface-2);
|
|
89
|
+
border: 1px solid var(--border);
|
|
90
|
+
border-radius: var(--radius-sm);
|
|
91
|
+
}
|
|
92
|
+
.watch-sub-h, .watch-subh {
|
|
93
|
+
font-family: var(--font-display);
|
|
94
|
+
font-size: 14px;
|
|
95
|
+
font-weight: 600;
|
|
96
|
+
color: var(--ink);
|
|
97
|
+
margin: 16px 0 4px;
|
|
98
|
+
}
|
|
99
|
+
.watch-sub-h:first-of-type { margin-top: 8px; }
|
|
100
|
+
|
|
101
|
+
/* Severity / status badges. */
|
|
102
|
+
.badge {
|
|
103
|
+
display: inline-block;
|
|
104
|
+
font-size: 11px;
|
|
105
|
+
font-weight: 600;
|
|
106
|
+
letter-spacing: 0.04em;
|
|
107
|
+
text-transform: uppercase;
|
|
108
|
+
padding: 2px 8px;
|
|
109
|
+
border-radius: 999px;
|
|
110
|
+
border: 1px solid var(--border-strong);
|
|
111
|
+
color: var(--ink-soft);
|
|
112
|
+
white-space: nowrap;
|
|
113
|
+
}
|
|
114
|
+
.badge--sev-critical { background: var(--danger-weak); color: var(--danger); border-color: color-mix(in srgb, var(--danger) 35%, transparent); }
|
|
115
|
+
.badge--sev-high { background: var(--warn-weak); color: var(--warn); border-color: color-mix(in srgb, var(--warn) 35%, transparent); }
|
|
116
|
+
.badge--sev-medium { background: var(--info-weak); color: var(--info); border-color: color-mix(in srgb, var(--info) 30%, transparent); }
|
|
117
|
+
.badge--sev-low { background: var(--surface-2); color: var(--ink-soft); }
|
|
118
|
+
.badge--status { background: var(--surface-2); color: var(--ink-soft); }
|
|
119
|
+
|
|
120
|
+
/* Row action buttons + selects. */
|
|
121
|
+
.watch-actions { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
|
|
122
|
+
.watch-btn {
|
|
123
|
+
font-family: var(--font-body);
|
|
124
|
+
font-size: 12.5px;
|
|
125
|
+
font-weight: 500;
|
|
126
|
+
padding: 4px 12px;
|
|
127
|
+
border: 1px solid var(--border-strong);
|
|
128
|
+
background: var(--surface);
|
|
129
|
+
color: var(--ink-soft);
|
|
130
|
+
border-radius: var(--radius-sm);
|
|
131
|
+
cursor: pointer;
|
|
132
|
+
}
|
|
133
|
+
.watch-btn:hover:not(:disabled) { background: var(--surface-2); color: var(--ink); }
|
|
134
|
+
.watch-btn:disabled { opacity: 0.45; cursor: default; }
|
|
135
|
+
.watch-btn--danger { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 40%, var(--border-strong)); }
|
|
136
|
+
.watch-select {
|
|
137
|
+
font-family: var(--font-body);
|
|
138
|
+
font-size: 13px;
|
|
139
|
+
padding: 4px 6px;
|
|
140
|
+
border: 1px solid var(--border-strong);
|
|
141
|
+
background: var(--surface);
|
|
142
|
+
color: var(--ink);
|
|
143
|
+
border-radius: var(--radius-sm);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.watch-req {
|
|
147
|
+
border-bottom: 1px solid var(--border);
|
|
148
|
+
padding: 10px 0;
|
|
149
|
+
display: flex; gap: 14px; flex-wrap: wrap;
|
|
150
|
+
align-items: flex-start; justify-content: space-between;
|
|
151
|
+
}
|
|
152
|
+
.watch-req__who { font-weight: 600; color: var(--ink); }
|
|
153
|
+
.watch-req__meta { color: var(--ink-faint); font-size: 12.5px; margin-top: 2px; }
|
|
154
|
+
.watch-req__note { color: var(--ink); font-size: 13.5px; margin-top: 6px; max-width: 56ch; }
|
|
155
|
+
|
|
156
|
+
.watch-unavailable { color: var(--ink-faint); font-size: 13px; padding: 8px 0; }
|
|
157
|
+
|
|
158
|
+
.watch-trend { display: flex; flex-direction: column; gap: 4px; margin-top: 8px; }
|
|
159
|
+
.watch-trend__row {
|
|
160
|
+
display: grid; grid-template-columns: 84px 1fr 64px;
|
|
161
|
+
gap: 10px; align-items: center;
|
|
162
|
+
font-size: 13px; color: var(--ink);
|
|
163
|
+
}
|
|
164
|
+
.watch-trend__bar-track {
|
|
165
|
+
background: var(--surface-2); border-radius: 3px; height: 12px; overflow: hidden;
|
|
166
|
+
border: 1px solid var(--border);
|
|
167
|
+
}
|
|
168
|
+
.watch-trend__bar-fill { background: var(--accent); height: 100%; display: block; }
|
|
169
|
+
.watch-trend__val { text-align: right; font-variant-numeric: tabular-nums; color: var(--ink-soft); }
|
|
170
|
+
|
|
171
|
+
.watch-list { list-style: none; padding: 0; margin: 8px 0 0; }
|
|
172
|
+
.watch-list li {
|
|
173
|
+
display: flex; justify-content: space-between; gap: 12px;
|
|
174
|
+
padding: 5px 0; border-bottom: 1px solid var(--border);
|
|
175
|
+
font-size: 13px;
|
|
176
|
+
}
|
|
177
|
+
.watch-list li .k { color: var(--ink); }
|
|
178
|
+
.watch-list li .v { color: var(--ink-soft); font-variant-numeric: tabular-nums; }
|
|
179
|
+
|
|
180
|
+
.watch-foot-link {
|
|
181
|
+
display: inline-block; margin-top: 12px;
|
|
182
|
+
font-size: 13px; font-weight: 500;
|
|
183
|
+
color: var(--accent-text);
|
|
184
|
+
}
|