superbee 0.1.3 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -0
- package/SKILL.md +4 -2
- package/dist/publication/bridge-entry.d.ts +5 -0
- package/dist/publication/bridge.d.ts +9 -0
- package/dist/publication/canonical-json.d.ts +3 -0
- package/dist/publication/capture.d.ts +4 -0
- package/dist/publication/errors.d.ts +22 -0
- package/dist/publication/generated/publication-snapshot-v1.d.ts +125 -0
- package/dist/publication/index.d.ts +7 -0
- package/dist/publication/schema/publication-snapshot-v1.schema.json +146 -0
- package/dist/publication/schema.d.ts +3 -0
- package/dist/publication/snapshot-backend.d.ts +33 -0
- package/dist/publication/types.d.ts +44 -0
- package/dist/publication-bridge.mjs +6165 -0
- package/dist/publication.mjs +44039 -0
- package/dist/superbee.mjs +2856 -1202
- package/package.json +16 -6
- package/references/views/about.html +30 -13
- package/references/views/pulse.html +69 -43
- package/references/views/roadmap.html +48 -33
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "superbee",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Agent-facing Superbee CLI for reading and writing local OKF knowledge bundles: context notes, docs, cross-links, and live bundle Views.",
|
|
6
6
|
"keywords": [
|
|
@@ -24,6 +24,17 @@
|
|
|
24
24
|
"bin": {
|
|
25
25
|
"superbee": "dist/superbee.mjs"
|
|
26
26
|
},
|
|
27
|
+
"exports": {
|
|
28
|
+
".": "./dist/superbee.mjs",
|
|
29
|
+
"./publication": {
|
|
30
|
+
"types": "./dist/publication/index.d.ts",
|
|
31
|
+
"default": "./dist/publication.mjs"
|
|
32
|
+
},
|
|
33
|
+
"./publication/bridge": {
|
|
34
|
+
"types": "./dist/publication/bridge-entry.d.ts",
|
|
35
|
+
"default": "./dist/publication-bridge.mjs"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
27
38
|
"files": [
|
|
28
39
|
"dist",
|
|
29
40
|
"SKILL.md",
|
|
@@ -36,16 +47,14 @@
|
|
|
36
47
|
"engines": {
|
|
37
48
|
"node": ">=20"
|
|
38
49
|
},
|
|
39
|
-
"os": [
|
|
40
|
-
"!win32"
|
|
41
|
-
],
|
|
42
50
|
"scripts": {
|
|
43
51
|
"build": "node build.mjs local-dev",
|
|
44
52
|
"build:npm-package": "node build.mjs npm-package",
|
|
45
53
|
"typecheck": "tsc --noEmit",
|
|
46
54
|
"pretest": "node build.mjs local-dev",
|
|
47
|
-
"test": "
|
|
48
|
-
"
|
|
55
|
+
"test:host-class": "node scripts/run-test-command.mjs node --test --import ./test/ts-loader.mjs ./test/private-state-bundle-boundary.test.ts ./test/filesystem-cross-process-cas.test.ts ./test/link.test.ts ./test/promote-pull.test.ts ./test/recipe-source.test.ts",
|
|
56
|
+
"test": "node scripts/run-test-command.mjs node --test --import ./test/ts-loader.mjs ./test/*.test.ts",
|
|
57
|
+
"mutation": "node scripts/run-test-command.mjs npm-exec stryker run",
|
|
49
58
|
"gen:skill": "node scripts/gen-skill.mjs",
|
|
50
59
|
"check:skill": "node scripts/gen-skill.mjs --check",
|
|
51
60
|
"prepublishOnly": "node -e \"console.error('superbee is released by .github/workflows/release.yml (npm stage publish); do not run npm publish here'); process.exit(1)\""
|
|
@@ -56,6 +65,7 @@
|
|
|
56
65
|
"@superbee/core": "*",
|
|
57
66
|
"@superbee/markdown-renderer": "*",
|
|
58
67
|
"@superbee/mcp-app": "*",
|
|
68
|
+
"@superbee/publication": "*",
|
|
59
69
|
"@superbee/server": "*",
|
|
60
70
|
"@superbee/ui-server": "*",
|
|
61
71
|
"@toon-format/toon": "2.3.0",
|
|
@@ -5,44 +5,61 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
6
|
<title>About this bundle</title>
|
|
7
7
|
<style>
|
|
8
|
+
/* Superbee View theme — mirrors the launcher shell, so a View framed inside it reads as
|
|
9
|
+
one surface rather than a foreign document.
|
|
10
|
+
|
|
11
|
+
TWO accent roles, not three. --structure carries structure AND state: "active" is the
|
|
12
|
+
same hue at full intensity, never a second colour, because hue should carry kind and
|
|
13
|
+
intensity should carry state. --signal carries liveness and the revealed answer. There
|
|
14
|
+
is deliberately no teal. Quiet metadata takes --slate, not an accent.
|
|
15
|
+
|
|
16
|
+
Fonts: a View is sandboxed under `font-src data:`, so it CANNOT load the shell's
|
|
17
|
+
self-hosted woff2 by URL. The brand faces are named first and resolve for anyone who
|
|
18
|
+
has them installed locally; the stacks behind them are the real fallback. Do not embed
|
|
19
|
+
a data: font — that is ~100KB in every View for a marginal gain. */
|
|
8
20
|
:root {
|
|
9
|
-
--bg
|
|
10
|
-
--
|
|
11
|
-
--
|
|
21
|
+
--bg:#F3F7FA; --card:#FFFFFF; --alt:#E9EFF4; --rule:#DADEE2;
|
|
22
|
+
--ink:#0F1A24; --slate:#4A5D6E; --ghost:#9AAAB8;
|
|
23
|
+
--structure:#0073B0; --signal:#956300; --danger:#B00020;
|
|
24
|
+
--radius:2px;
|
|
25
|
+
--display:"Space Grotesk", system-ui, -apple-system, "Segoe UI", sans-serif;
|
|
26
|
+
--sans:"DM Sans", -apple-system, "Segoe UI", system-ui, sans-serif;
|
|
27
|
+
--mono:"JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
|
|
12
28
|
}
|
|
13
29
|
@media (prefers-color-scheme: dark) {
|
|
14
30
|
:root {
|
|
15
|
-
--bg
|
|
16
|
-
--
|
|
31
|
+
--bg:#0B1926; --card:#0F2A3F; --alt:#12314A; --rule:#26323D;
|
|
32
|
+
--ink:#F8F6F2; --slate:#B7C4D1; --ghost:#7E8FA0;
|
|
33
|
+
--structure:#3CAEF9; --signal:#E09707; --danger:#F2707A;
|
|
17
34
|
}
|
|
18
35
|
}
|
|
19
36
|
* { box-sizing: border-box; margin: 0; }
|
|
20
37
|
html, body { height: 100%; }
|
|
21
38
|
body {
|
|
22
|
-
font: 15px/1.6
|
|
39
|
+
font: 15px/1.6 var(--sans);
|
|
23
40
|
background: var(--bg); color: var(--ink);
|
|
24
41
|
}
|
|
25
42
|
main { max-width: 40rem; margin: 0 auto; padding: 2.5rem 1.5rem 4rem; }
|
|
26
|
-
h1 { font-size: 1.5rem; font-weight: 650; letter-spacing: -0.01em; margin-bottom: 0.4rem; }
|
|
43
|
+
h1 { font-family: var(--display); font-size: 1.5rem; font-weight: 650; letter-spacing: -0.01em; margin-bottom: 0.4rem; }
|
|
27
44
|
.kicker {
|
|
28
|
-
color: var(--
|
|
45
|
+
color: var(--structure); font-family: var(--mono); font-size: 0.8rem;
|
|
29
46
|
text-transform: uppercase; letter-spacing: 0.06em; margin-bottom: 0.6rem;
|
|
30
47
|
}
|
|
31
|
-
p { color: var(--
|
|
48
|
+
p { color: var(--slate); margin-bottom: 1rem; }
|
|
32
49
|
p strong { color: var(--ink); font-weight: 600; }
|
|
33
50
|
.card {
|
|
34
|
-
background: var(--
|
|
51
|
+
background: var(--card); border: 1px solid var(--rule); border-radius: 10px;
|
|
35
52
|
padding: 1rem 1.2rem; margin: 1.5rem 0;
|
|
36
53
|
}
|
|
37
54
|
.card h2 { font-size: 0.95rem; margin-bottom: 0.5rem; }
|
|
38
|
-
.card ul { margin: 0; padding-left: 1.2rem; color: var(--
|
|
55
|
+
.card ul { margin: 0; padding-left: 1.2rem; color: var(--slate); }
|
|
39
56
|
.card li { margin-bottom: 0.35rem; }
|
|
40
57
|
code {
|
|
41
|
-
font-family: var(--mono); background: var(--
|
|
58
|
+
font-family: var(--mono); background: var(--alt); color: var(--ink);
|
|
42
59
|
padding: 0.1rem 0.35rem; border-radius: 5px; font-size: 0.85em;
|
|
43
60
|
}
|
|
44
61
|
#toggle, #open-roadmap {
|
|
45
|
-
border: 1px solid var(--
|
|
62
|
+
border: 1px solid var(--rule); background: var(--card); color: var(--ink);
|
|
46
63
|
border-radius: 8px; padding: 0.4rem 0.9rem; font-size: 0.85rem; cursor: pointer;
|
|
47
64
|
}
|
|
48
65
|
#detail { display: none; margin-top: 0.75rem; }
|
|
@@ -5,106 +5,129 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
6
|
<title>Pulse</title>
|
|
7
7
|
<style>
|
|
8
|
+
/* Superbee View theme — mirrors the launcher shell, so a View framed inside it reads as
|
|
9
|
+
one surface rather than a foreign document.
|
|
10
|
+
|
|
11
|
+
TWO accent roles, not three. --structure carries structure AND state: "active" is the
|
|
12
|
+
same hue at full intensity, never a second colour, because hue should carry kind and
|
|
13
|
+
intensity should carry state. --signal carries liveness and the revealed answer. There
|
|
14
|
+
is deliberately no teal. Quiet metadata takes --slate, not an accent.
|
|
15
|
+
|
|
16
|
+
Fonts: a View is sandboxed under `font-src data:`, so it CANNOT load the shell's
|
|
17
|
+
self-hosted woff2 by URL. The brand faces are named first and resolve for anyone who
|
|
18
|
+
has them installed locally; the stacks behind them are the real fallback. Do not embed
|
|
19
|
+
a data: font — that is ~100KB in every View for a marginal gain. */
|
|
8
20
|
:root {
|
|
9
|
-
--bg
|
|
10
|
-
--
|
|
11
|
-
--
|
|
12
|
-
--
|
|
21
|
+
--bg:#F3F7FA; --card:#FFFFFF; --alt:#E9EFF4; --rule:#DADEE2;
|
|
22
|
+
--ink:#0F1A24; --slate:#4A5D6E; --ghost:#9AAAB8;
|
|
23
|
+
--structure:#0073B0; --signal:#956300; --danger:#B00020;
|
|
24
|
+
--radius:2px;
|
|
25
|
+
--display:"Space Grotesk", system-ui, -apple-system, "Segoe UI", sans-serif;
|
|
26
|
+
--sans:"DM Sans", -apple-system, "Segoe UI", system-ui, sans-serif;
|
|
27
|
+
--mono:"JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
|
|
13
28
|
}
|
|
14
29
|
@media (prefers-color-scheme: dark) {
|
|
15
30
|
:root {
|
|
16
|
-
--bg
|
|
17
|
-
--
|
|
18
|
-
--
|
|
31
|
+
--bg:#0B1926; --card:#0F2A3F; --alt:#12314A; --rule:#26323D;
|
|
32
|
+
--ink:#F8F6F2; --slate:#B7C4D1; --ghost:#7E8FA0;
|
|
33
|
+
--structure:#3CAEF9; --signal:#E09707; --danger:#F2707A;
|
|
19
34
|
}
|
|
20
35
|
}
|
|
36
|
+
|
|
37
|
+
/* Functional status colours, NOT brand accents. The kit has no green; these exist so a
|
|
38
|
+
dashboard can say good/warning/bad, and they are deliberately kept out of the palette
|
|
39
|
+
vocabulary above so nobody mistakes them for brand colours. */
|
|
40
|
+
:root { --ok:#0F7B3F; --warn:#956300; --bad:#B00020; }
|
|
41
|
+
@media (prefers-color-scheme: dark) {
|
|
42
|
+
:root { --ok:#3FBF74; --warn:#E09707; --bad:#F2707A; }
|
|
43
|
+
}
|
|
21
44
|
* { box-sizing: border-box; margin: 0; }
|
|
22
45
|
html, body { height: 100%; }
|
|
23
46
|
body {
|
|
24
|
-
font: 14px/1.5
|
|
47
|
+
font: 14px/1.5 var(--sans);
|
|
25
48
|
background: var(--bg); color: var(--ink); display: flex; flex-direction: column;
|
|
26
49
|
}
|
|
27
50
|
header {
|
|
28
51
|
display: flex; align-items: center; gap: 10px; padding: 10px 16px;
|
|
29
|
-
border-bottom: 1px solid var(--
|
|
52
|
+
border-bottom: 1px solid var(--rule); background: var(--card); flex-wrap: wrap;
|
|
30
53
|
}
|
|
31
|
-
header h1 { font-size: 15px; font-weight: 650; letter-spacing: .01em; }
|
|
32
|
-
header .bundle { color: var(--
|
|
54
|
+
header h1 { font-family: var(--display); font-size: 15px; font-weight: 650; letter-spacing: .01em; }
|
|
55
|
+
header .bundle { color: var(--slate); font-size: 12px; font-family: var(--mono); }
|
|
33
56
|
#search {
|
|
34
|
-
margin-left: auto; background: var(--
|
|
57
|
+
margin-left: auto; background: var(--alt); border: 1px solid var(--rule); color: var(--ink);
|
|
35
58
|
border-radius: 8px; padding: 5px 10px; font-size: 13px; width: 200px; outline: none;
|
|
36
59
|
}
|
|
37
|
-
#search:focus { border-color: var(--
|
|
60
|
+
#search:focus { border-color: var(--structure); }
|
|
38
61
|
#follow {
|
|
39
|
-
border: 1px solid var(--
|
|
62
|
+
border: 1px solid var(--rule); background: var(--alt); color: var(--slate); border-radius: 999px;
|
|
40
63
|
padding: 5px 12px; font-size: 12px; cursor: pointer; user-select: none; white-space: nowrap;
|
|
41
64
|
}
|
|
42
|
-
#follow.on { background: var(--
|
|
65
|
+
#follow.on { background: var(--alt); color: var(--structure); border-color: var(--structure); }
|
|
43
66
|
#follow.on .dot { animation: blink 1.2s infinite; }
|
|
44
67
|
#follow .dot { display: inline-block; width: 7px; height: 7px; border-radius: 50%; background: currentColor; margin-right: 6px; }
|
|
45
68
|
@keyframes blink { 50% { opacity: .25; } }
|
|
46
|
-
#typebar { display: flex; gap: 6px; padding: 8px 16px; border-bottom: 1px solid var(--
|
|
69
|
+
#typebar { display: flex; gap: 6px; padding: 8px 16px; border-bottom: 1px solid var(--rule); overflow-x: auto; background: var(--card); }
|
|
47
70
|
.tchip {
|
|
48
|
-
font-size: 12px; padding: 3px 10px; border-radius: 999px; border: 1px solid var(--
|
|
49
|
-
background: var(--
|
|
71
|
+
font-size: 12px; padding: 3px 10px; border-radius: 999px; border: 1px solid var(--rule);
|
|
72
|
+
background: var(--alt); color: var(--slate); cursor: pointer; white-space: nowrap;
|
|
50
73
|
}
|
|
51
|
-
.tchip.on { background: var(--
|
|
74
|
+
.tchip.on { background: var(--alt); color: var(--structure); border-color: var(--structure); font-weight: 600; }
|
|
52
75
|
main { flex: 1; display: flex; min-height: 0; }
|
|
53
|
-
#feed { flex: 0 0 44%; max-width: 560px; overflow-y: auto; border-right: 1px solid var(--
|
|
76
|
+
#feed { flex: 0 0 44%; max-width: 560px; overflow-y: auto; border-right: 1px solid var(--rule); padding: 8px 0 40px; }
|
|
54
77
|
.group-label {
|
|
55
78
|
position: sticky; top: 0; z-index: 1; font-size: 11px; font-weight: 700; text-transform: uppercase;
|
|
56
|
-
letter-spacing: .08em; color: var(--
|
|
79
|
+
letter-spacing: .08em; color: var(--slate); background: var(--bg); padding: 10px 16px 4px;
|
|
57
80
|
}
|
|
58
81
|
.item {
|
|
59
82
|
display: block; width: 100%; text-align: left; border: 0; background: none; color: inherit; font: inherit;
|
|
60
83
|
padding: 9px 16px; cursor: pointer; border-left: 3px solid transparent;
|
|
61
84
|
}
|
|
62
|
-
.item:hover { background: var(--
|
|
63
|
-
.item.sel { background: var(--
|
|
85
|
+
.item:hover { background: var(--alt); }
|
|
86
|
+
.item.sel { background: var(--alt); border-left-color: var(--structure); }
|
|
64
87
|
.item.fresh { animation: land 1.6s ease-out; }
|
|
65
|
-
@keyframes land { 0% { background: var(--
|
|
88
|
+
@keyframes land { 0% { background: var(--alt); transform: translateX(-4px); } 100% { background: none; transform: none; } }
|
|
66
89
|
.item .row1 { display: flex; align-items: baseline; gap: 8px; }
|
|
67
90
|
.item .title { font-weight: 570; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; }
|
|
68
|
-
.item .when { color: var(--
|
|
69
|
-
.item .row2 { display: flex; align-items: center; gap: 8px; margin-top: 2px; font-size: 12px; color: var(--
|
|
91
|
+
.item .when { color: var(--slate); font-size: 11.5px; flex: none; }
|
|
92
|
+
.item .row2 { display: flex; align-items: center; gap: 8px; margin-top: 2px; font-size: 12px; color: var(--slate); }
|
|
70
93
|
.item .id { font-family: var(--mono); font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
71
94
|
.dotc { width: 8px; height: 8px; border-radius: 50%; flex: none; display: inline-block; }
|
|
72
|
-
.badge { font-size: 10.5px; font-weight: 650; padding: 1px 7px; border-radius: 999px; background: var(--
|
|
73
|
-
.badge.st-todo { color: var(--
|
|
95
|
+
.badge { font-size: 10.5px; font-weight: 650; padding: 1px 7px; border-radius: 999px; background: var(--alt); color: var(--slate); flex: none; }
|
|
96
|
+
.badge.st-todo { color: var(--slate); }
|
|
74
97
|
.badge.st-in_progress { color: var(--warn); background: color-mix(in srgb, var(--warn) 12%, transparent); }
|
|
75
98
|
.badge.st-blocked, .badge.st-canceled { color: var(--bad); background: color-mix(in srgb, var(--bad) 10%, transparent); }
|
|
76
99
|
.badge.st-done, .badge.st-active { color: var(--ok); background: color-mix(in srgb, var(--ok) 10%, transparent); }
|
|
77
100
|
#detail { flex: 1; overflow-y: auto; padding: 20px 28px 60px; }
|
|
78
|
-
#detail .empty { color: var(--
|
|
101
|
+
#detail .empty { color: var(--slate); text-align: center; margin-top: 18vh; }
|
|
79
102
|
#detail .empty .big { font-size: 40px; margin-bottom: 12px; }
|
|
80
|
-
#crumbs { display: flex; gap: 4px; align-items: center; font-size: 12px; color: var(--
|
|
81
|
-
#crumbs button { border: 0; background: none; color: var(--
|
|
103
|
+
#crumbs { display: flex; gap: 4px; align-items: center; font-size: 12px; color: var(--slate); margin-bottom: 10px; flex-wrap: wrap; }
|
|
104
|
+
#crumbs button { border: 0; background: none; color: var(--structure); cursor: pointer; font: inherit; font-family: var(--mono); padding: 0; }
|
|
82
105
|
#crumbs .sep { opacity: .5; }
|
|
83
106
|
.doc h2 { font-size: 20px; margin-bottom: 2px; }
|
|
84
107
|
.doc .meta { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 8px 0 14px; }
|
|
85
108
|
.kv {
|
|
86
109
|
display: grid; grid-template-columns: max-content 1fr; gap: 3px 14px; font-size: 12.5px;
|
|
87
|
-
background: var(--
|
|
110
|
+
background: var(--card); border: 1px solid var(--rule); border-radius: 10px; padding: 10px 14px; margin-bottom: 16px;
|
|
88
111
|
}
|
|
89
|
-
.kv .k { color: var(--
|
|
112
|
+
.kv .k { color: var(--slate); font-family: var(--mono); }
|
|
90
113
|
.kv .v { word-break: break-word; }
|
|
91
|
-
.kv .v.ver { font-family: var(--mono); font-size: 11px; color: var(--
|
|
114
|
+
.kv .v.ver { font-family: var(--mono); font-size: 11px; color: var(--slate); }
|
|
92
115
|
.body { max-width: 72ch; }
|
|
93
116
|
.body h1, .body h2, .body h3 { margin: 18px 0 6px; line-height: 1.25; }
|
|
94
|
-
.body h1 { font-size: 18px; } .body h2 { font-size: 16px; } .body h3 { font-size: 14.5px; }
|
|
117
|
+
.body h1 { font-family: var(--display); font-size: 18px; } .body h2 { font-size: 16px; } .body h3 { font-size: 14.5px; }
|
|
95
118
|
.body p, .body ul, .body ol { margin: 8px 0; }
|
|
96
119
|
.body li { margin: 3px 0 3px 18px; }
|
|
97
|
-
.body code { font-family: var(--mono); font-size: 12.5px; background: var(--
|
|
98
|
-
.body pre { background: var(--
|
|
120
|
+
.body code { font-family: var(--mono); font-size: 12.5px; background: var(--alt); border-radius: 4px; padding: 1px 5px; }
|
|
121
|
+
.body pre { background: var(--alt); border: 1px solid var(--rule); border-radius: 8px; padding: 10px 12px; overflow-x: auto; margin: 10px 0; }
|
|
99
122
|
.body pre code { background: none; padding: 0; }
|
|
100
|
-
.body a.doclink { color: var(--
|
|
101
|
-
.body .extlink { color: var(--
|
|
123
|
+
.body a.doclink { color: var(--structure); text-decoration: none; border-bottom: 1px dashed var(--structure); cursor: pointer; }
|
|
124
|
+
.body .extlink { color: var(--slate); border-bottom: 1px dotted var(--slate); cursor: help; }
|
|
102
125
|
.doc .live-note {
|
|
103
|
-
font-size: 12px; color: var(--
|
|
126
|
+
font-size: 12px; color: var(--structure); background: var(--alt); border-radius: 8px;
|
|
104
127
|
padding: 6px 10px; margin-bottom: 12px; display: none;
|
|
105
128
|
}
|
|
106
|
-
footer { padding: 6px 16px; border-top: 1px solid var(--
|
|
107
|
-
footer .keys span { font-family: var(--mono); background: var(--
|
|
129
|
+
footer { padding: 6px 16px; border-top: 1px solid var(--rule); background: var(--card); font-size: 11.5px; color: var(--slate); display: flex; gap: 14px; }
|
|
130
|
+
footer .keys span { font-family: var(--mono); background: var(--alt); border-radius: 4px; padding: 0 5px; margin: 0 2px; }
|
|
108
131
|
</style>
|
|
109
132
|
</head>
|
|
110
133
|
<body>
|
|
@@ -191,7 +214,10 @@
|
|
|
191
214
|
"use strict";
|
|
192
215
|
var docs = [], selId = null, typeFilter = null, textFilter = "", follow = false;
|
|
193
216
|
var freshIds = new Set(), crumbs = [];
|
|
194
|
-
|
|
217
|
+
// Categorical series colours. Brand-first: series 1 and 2 are --structure and --signal,
|
|
218
|
+
// so the common case is on-theme; the rest are distinguishable hues, because a chart
|
|
219
|
+
// needs separable series more than it needs a two-colour palette.
|
|
220
|
+
var PALETTE = ["#0073B0","#956300","#0D7A6F","#7A3FA8","#B00020","#0891B2","#4F46E5","#8A6D00"];
|
|
195
221
|
var typeColor = {};
|
|
196
222
|
function colorFor(t) {
|
|
197
223
|
if (!typeColor[t]) typeColor[t] = PALETTE[Object.keys(typeColor).length % PALETTE.length];
|
|
@@ -5,51 +5,66 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
6
|
<title>Roadmap</title>
|
|
7
7
|
<style>
|
|
8
|
+
/* Superbee View theme — mirrors the launcher shell, so a View framed inside it reads as
|
|
9
|
+
one surface rather than a foreign document.
|
|
10
|
+
|
|
11
|
+
TWO accent roles, not three. --structure carries structure AND state: "active" is the
|
|
12
|
+
same hue at full intensity, never a second colour, because hue should carry kind and
|
|
13
|
+
intensity should carry state. --signal carries liveness and the revealed answer. There
|
|
14
|
+
is deliberately no teal. Quiet metadata takes --slate, not an accent.
|
|
15
|
+
|
|
16
|
+
Fonts: a View is sandboxed under `font-src data:`, so it CANNOT load the shell's
|
|
17
|
+
self-hosted woff2 by URL. The brand faces are named first and resolve for anyone who
|
|
18
|
+
has them installed locally; the stacks behind them are the real fallback. Do not embed
|
|
19
|
+
a data: font — that is ~100KB in every View for a marginal gain. */
|
|
8
20
|
:root {
|
|
9
|
-
--
|
|
21
|
+
--bg:#F3F7FA; --card:#FFFFFF; --alt:#E9EFF4; --rule:#DADEE2;
|
|
10
22
|
--ink:#0F1A24; --slate:#4A5D6E; --ghost:#9AAAB8;
|
|
11
|
-
--
|
|
23
|
+
--structure:#0073B0; --signal:#956300; --danger:#B00020;
|
|
12
24
|
--radius:2px;
|
|
13
|
-
--
|
|
14
|
-
--sans: -apple-system, "Segoe UI", system-ui, sans-serif;
|
|
15
|
-
--mono: ui-monospace, "SF Mono", Menlo, monospace;
|
|
25
|
+
--display:"Space Grotesk", system-ui, -apple-system, "Segoe UI", sans-serif;
|
|
26
|
+
--sans:"DM Sans", -apple-system, "Segoe UI", system-ui, sans-serif;
|
|
27
|
+
--mono:"JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
|
|
16
28
|
}
|
|
17
29
|
@media (prefers-color-scheme: dark) {
|
|
18
|
-
:root {
|
|
19
|
-
--
|
|
30
|
+
:root {
|
|
31
|
+
--bg:#0B1926; --card:#0F2A3F; --alt:#12314A; --rule:#26323D;
|
|
32
|
+
--ink:#F8F6F2; --slate:#B7C4D1; --ghost:#7E8FA0;
|
|
33
|
+
--structure:#3CAEF9; --signal:#E09707; --danger:#F2707A;
|
|
34
|
+
}
|
|
20
35
|
}
|
|
21
36
|
* { box-sizing:border-box; margin:0; }
|
|
22
|
-
body { background:var(--
|
|
23
|
-
header { padding:22px 32px 14px; border-bottom:1px solid var(--rule); background:var(--
|
|
24
|
-
header h1 { font-family:var(--
|
|
25
|
-
header h1 .chev { color:var(--
|
|
37
|
+
body { background:var(--bg); color:var(--ink); font:15px/1.55 var(--sans); }
|
|
38
|
+
header { padding:22px 32px 14px; border-bottom:1px solid var(--rule); background:var(--card); }
|
|
39
|
+
header h1 { font-family:var(--display); font-weight:500; font-size:30px; letter-spacing:.01em; display:flex; align-items:baseline; gap:12px; }
|
|
40
|
+
header h1 .chev { color:var(--structure); font-family:var(--sans); font-weight:700; }
|
|
26
41
|
header .sub { color:var(--slate); font-size:13px; margin-top:2px; }
|
|
27
|
-
header .live { float:right; font-size:11.5px; color:var(--
|
|
28
|
-
header .live .dot { display:inline-block; width:7px; height:7px; border-radius:50%; background:var(--
|
|
42
|
+
header .live { float:right; font-size:11.5px; color:var(--signal); font-family:var(--mono); }
|
|
43
|
+
header .live .dot { display:inline-block; width:7px; height:7px; border-radius:50%; background:var(--signal); margin-right:5px; animation:pulse 1.4s infinite; }
|
|
29
44
|
@keyframes pulse { 50%{opacity:.3} }
|
|
30
45
|
main { max-width:900px; margin:0 auto; padding:26px 32px 80px; }
|
|
31
46
|
.group { margin-bottom:34px; }
|
|
32
47
|
.group > h2 { font-family:var(--sans); font-size:12px; font-weight:700; text-transform:uppercase; letter-spacing:.09em; color:var(--slate); display:flex; align-items:center; gap:9px; margin-bottom:4px; }
|
|
33
48
|
.group > h2 .swatch { width:10px; height:10px; border-radius:2px; }
|
|
34
49
|
.group > .note { font-size:12px; color:var(--ghost); margin-bottom:12px; }
|
|
35
|
-
.item { background:var(--
|
|
36
|
-
.item.active { border-left-color:var(--
|
|
37
|
-
.item.committed { border-left-color:var(--
|
|
38
|
-
.item.candidate { border-left-color:var(--
|
|
50
|
+
.item { background:var(--card); border:1px solid var(--rule); border-radius:var(--radius); border-left:3px solid var(--rule); margin-bottom:10px; overflow:hidden; }
|
|
51
|
+
.item.active { border-left-color:var(--structure); }
|
|
52
|
+
.item.committed { border-left-color:var(--structure); }
|
|
53
|
+
.item.candidate { border-left-color:var(--signal); }
|
|
39
54
|
.item .head { display:flex; align-items:center; gap:12px; padding:13px 16px; cursor:pointer; }
|
|
40
|
-
.item .head:hover { background:var(--
|
|
41
|
-
.item .title { font-family:var(--
|
|
55
|
+
.item .head:hover { background:var(--alt); }
|
|
56
|
+
.item .title { font-family:var(--display); font-size:19px; font-weight:500; flex:1; line-height:1.2; }
|
|
42
57
|
.item .caret { color:var(--ghost); font-size:12px; transition:transform .15s; }
|
|
43
58
|
.item.open .caret { transform:rotate(90deg); }
|
|
44
59
|
.badge { font-family:var(--sans); font-size:10.5px; font-weight:600; padding:2px 8px; border-radius:999px; white-space:nowrap; letter-spacing:.02em; }
|
|
45
|
-
.badge.active { color:var(--
|
|
46
|
-
.badge.queued { color:var(--slate); background:var(--
|
|
47
|
-
.badge.candidate { color:var(--
|
|
48
|
-
.badge.done { color:var(--slate); background:var(--
|
|
60
|
+
.badge.active { color:var(--structure); background:color-mix(in srgb,var(--structure) 13%,transparent); }
|
|
61
|
+
.badge.queued { color:var(--slate); background:var(--alt); }
|
|
62
|
+
.badge.candidate { color:var(--signal); background:color-mix(in srgb,var(--signal) 15%,transparent); }
|
|
63
|
+
.badge.done { color:var(--slate); background:var(--alt); }
|
|
49
64
|
.roll { display:flex; align-items:center; gap:9px; padding:0 16px 12px; }
|
|
50
|
-
.bar { flex:1; height:5px; background:var(--
|
|
65
|
+
.bar { flex:1; height:5px; background:var(--alt); border-radius:3px; overflow:hidden; display:flex; }
|
|
51
66
|
.bar i { height:100%; display:block; }
|
|
52
|
-
.bar i.done { background:var(--
|
|
67
|
+
.bar i.done { background:var(--structure); } .bar i.prog { background:var(--signal); } .bar i.open { background:var(--rule); }
|
|
53
68
|
.roll .count { font-family:var(--mono); font-size:11.5px; color:var(--slate); white-space:nowrap; }
|
|
54
69
|
.roll .none { font-size:11.5px; color:var(--ghost); font-style:italic; }
|
|
55
70
|
.body { display:none; padding:2px 16px 14px; border-top:1px solid var(--rule); }
|
|
@@ -57,16 +72,16 @@
|
|
|
57
72
|
.desc { font-size:13.5px; color:var(--slate); margin:12px 0; max-width:70ch; }
|
|
58
73
|
.tasks { display:flex; flex-direction:column; gap:1px; }
|
|
59
74
|
.task { display:flex; align-items:center; gap:10px; padding:6px 8px; border-radius:2px; }
|
|
60
|
-
.task:hover { background:var(--
|
|
75
|
+
.task:hover { background:var(--alt); }
|
|
61
76
|
.task .tdot { width:7px; height:7px; border-radius:50%; flex:none; }
|
|
62
77
|
.task .ttitle { flex:1; font-size:13.5px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
|
|
63
78
|
.task .tid { font-family:var(--mono); font-size:11px; color:var(--ghost); }
|
|
64
|
-
.st-todo{color:var(--slate)} .st-in_progress{color:var(--
|
|
65
|
-
.d-todo{background:var(--ghost)} .d-in_progress{background:var(--
|
|
79
|
+
.st-todo{color:var(--slate)} .st-in_progress{color:var(--signal)} .st-blocked,.st-canceled{color:var(--danger)} .st-done{color:var(--structure)}
|
|
80
|
+
.d-todo{background:var(--ghost)} .d-in_progress{background:var(--signal)} .d-blocked,.d-canceled{background:var(--danger)} .d-done{background:var(--structure)}
|
|
66
81
|
.item.fresh { animation:land 1.8s ease-out; }
|
|
67
|
-
@keyframes land { 0%{background:color-mix(in srgb,var(--
|
|
82
|
+
@keyframes land { 0%{background:color-mix(in srgb,var(--signal) 18%,var(--card))} 100%{background:var(--card)} }
|
|
68
83
|
footer { text-align:center; color:var(--ghost); font-size:11.5px; padding:20px; font-family:var(--mono); }
|
|
69
|
-
.empty { color:var(--ghost); text-align:center; margin-top:16vh; font-family:var(--
|
|
84
|
+
.empty { color:var(--ghost); text-align:center; margin-top:16vh; font-family:var(--display); font-size:20px; }
|
|
70
85
|
</style>
|
|
71
86
|
</head>
|
|
72
87
|
<body>
|
|
@@ -140,9 +155,9 @@
|
|
|
140
155
|
return (fm(it).sequence!=null && String(fm(it).sequence).trim()!=="") ? "committed" : "candidate";
|
|
141
156
|
}
|
|
142
157
|
var GROUPS=[
|
|
143
|
-
{key:"active", label:"In motion", swatch:"var(--
|
|
144
|
-
{key:"committed",label:"Committed", swatch:"var(--
|
|
145
|
-
{key:"candidate",label:"Candidate", swatch:"var(--
|
|
158
|
+
{key:"active", label:"In motion", swatch:"var(--structure)", note:"actively being worked"},
|
|
159
|
+
{key:"committed",label:"Committed", swatch:"var(--structure)", note:"sequenced, not yet started"},
|
|
160
|
+
{key:"candidate",label:"Candidate", swatch:"var(--signal)",note:"recognized direction — not yet committed or sequenced (queued + no sequence). Awaiting a founders' decision."},
|
|
146
161
|
{key:"done", label:"Done", swatch:"var(--slate)",note:""}
|
|
147
162
|
];
|
|
148
163
|
|