@bongos/core 1.19.454 → 1.19.456
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 +116 -51
- package/docs/adr/0047-discord-bugs-intake-anti-abuse.md +1 -0
- package/docs/copy-inventory.md +231 -228
- package/docs/copy-registry.json +352 -312
- package/docs/module-api-changelog.md +4 -0
- package/modules/discord/db.js +0 -3
- package/modules/discord/discord-bot.js +8 -1
- package/modules/discord/discord-bugs.js +133 -74
- package/modules/discord/module.json +1 -1
- package/modules/hall-ui/public/atlas.css +41 -32
- package/modules/hall-ui/public/atlas.html +8 -0
- package/modules/hall-ui/public/atlas.states.json +60 -0
- package/modules/hall-ui/public/collab.css +2 -2
- package/modules/hall-ui/public/collab.html +7 -1
- package/modules/hall-ui/public/collab.states.json +60 -0
- package/modules/hall-ui/public/copy-desk.css +21 -16
- package/modules/hall-ui/public/copy-desk.html +9 -1
- package/modules/hall-ui/public/copy-desk.states.json +59 -0
- package/modules/hall-ui/public/drachmae.html +38 -5
- package/modules/hall-ui/public/drachmae.js +20 -2
- package/modules/hall-ui/public/drachmae.states.json +64 -0
- package/modules/hall-ui/public/gate.css +20 -25
- package/modules/hall-ui/public/gate.html +9 -1
- package/modules/hall-ui/public/gate.states.json +60 -0
- package/modules/hall-ui/public/goals-lib.js +22 -5
- package/modules/hall-ui/public/goals-render.js +27 -5
- package/modules/hall-ui/public/goals.css +141 -60
- package/modules/hall-ui/public/goals.html +8 -1
- package/modules/hall-ui/public/goals.states.json +74 -0
- package/modules/hall-ui/public/government.css +35 -36
- package/modules/hall-ui/public/government.html +9 -1
- package/modules/hall-ui/public/government.states.json +59 -0
- package/modules/hall-ui/public/harbor.css +23 -26
- package/modules/hall-ui/public/harbor.html +9 -1
- package/modules/hall-ui/public/harbor.states.json +59 -0
- package/modules/hall-ui/public/modules.css +22 -21
- package/modules/hall-ui/public/modules.html +9 -1
- package/modules/hall-ui/public/modules.states.json +73 -0
- package/modules/hall-ui/public/people.html +7 -1
- package/modules/hall-ui/public/people.states.json +59 -0
- package/modules/hall-ui/public/scouting.html +7 -1
- package/modules/hall-ui/public/scouting.states.json +54 -0
- package/modules/hall-ui/public/sessions.css +1 -1
- package/modules/hall-ui/public/sessions.html +9 -1
- package/modules/hall-ui/public/sessions.states.json +58 -0
- package/modules/hall-ui/public/style.css +125 -5
- package/modules/hall-ui/public/watch.css +36 -39
- package/modules/hall-ui/public/watch.html +9 -1
- package/modules/hall-ui/public/watch.states.json +60 -0
- package/modules/lifecycle/goal-suggest.js +70 -2
- package/modules/lifecycle/lifecycle.js +7 -0
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/src/module-api.js +1 -1
- package/tests/discord_bugs.mjs +110 -31
- package/tests/filing_abuse_matrix.mjs +59 -20
- package/tests/goal_subtitle.mjs +14 -8
- package/tests/goal_suggest.mjs +107 -1
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
emptyStateHtml, skeletonRows } = window.OTBKit;
|
|
29
29
|
const { DONE_STATUSES, CUT_STATUSES, isTodoStatus, ring, memberName,
|
|
30
30
|
readinessOf, EMPTY_ROLLUP, goalRollLine, matchesTodoSearch,
|
|
31
|
-
msOf, taskActivityMs, subtitleAttr, applyGoalProse } = window.OTBGoalsLib;
|
|
31
|
+
msOf, taskActivityMs, subtitleAttr, subtitleLine, applyGoalProse } = window.OTBGoalsLib;
|
|
32
32
|
|
|
33
33
|
const CONFLICT_CAP = 3;
|
|
34
34
|
// task 1828 — the band's Completion / Members / Conflicts columns each cap
|
|
@@ -150,21 +150,43 @@
|
|
|
150
150
|
right = `<span class="gr-quiet">No tasks yet</span>`;
|
|
151
151
|
}
|
|
152
152
|
const metaHtml = `#${escapeHtml(String(g.id))} · ${escapeHtml(g.version_id || '')}${(achieved || g.status === 'open') ? '' : ' · ' + escapeHtml(g.status)}${goalStampHtml(g)}`;
|
|
153
|
+
// task 1003307 — the archetype's fact line: the goal's STATE as a pill, then
|
|
154
|
+
// one chip per scope module and one for the version. The mock argues rows
|
|
155
|
+
// over cards precisely because a goal carries this many facts; the row was
|
|
156
|
+
// showing two of them as one run of grey text.
|
|
157
|
+
const stampHtml = goalStampHtml(g);
|
|
158
|
+
const idHtml = `<span class="gr-title__id">#${escapeHtml(String(g.id))}</span>`;
|
|
159
|
+
const chips = [];
|
|
160
|
+
for (const m of (Array.isArray(g.scope_modules) ? g.scope_modules : []).slice(0, 3)) {
|
|
161
|
+
chips.push(`<span class="fact-chip">${escapeHtml(String(m))}</span>`);
|
|
162
|
+
}
|
|
163
|
+
if (g.version_id) chips.push(`<span class="fact-chip">${escapeHtml(g.version_id)}</span>`);
|
|
164
|
+
const factsHtml = `<div class="gr-facts">`
|
|
165
|
+
+ `<span class="fact-pill fact-pill--${escapeHtml(g.status || 'open')}">${escapeHtml(g.status || 'open')}</span>`
|
|
166
|
+
+ chips.join('')
|
|
167
|
+
+ `</div>`;
|
|
153
168
|
// task 1003276 — the category chip. Computed here with the rest of the facts
|
|
154
169
|
// so the row and the card (task 1003136) cannot drift on it.
|
|
155
170
|
const catHtml = categoryChip(g.category);
|
|
156
|
-
return { r, achieved, ringHtml, goalHref, right, metaHtml, catHtml };
|
|
171
|
+
return { r, achieved, ringHtml, goalHref, right, metaHtml, catHtml, idHtml, stampHtml, factsHtml };
|
|
157
172
|
}
|
|
158
173
|
function goalRowHtml(g) {
|
|
159
|
-
const { r, achieved, ringHtml, goalHref, right,
|
|
174
|
+
const { r, achieved, ringHtml, goalHref, right, catHtml, idHtml, stampHtml, factsHtml } = goalRenderFacts(g, 44);
|
|
160
175
|
// NOTE: a rollup row nests real links (title → goal, Claim → task overlay,
|
|
161
176
|
// drill → goal), so the row itself is a <div>, not an <a> — nested anchors
|
|
162
177
|
// are invalid. Only the explicit links navigate.
|
|
178
|
+
// task 1003307 — the archetype's row (mock .goal): the id rides INSIDE the
|
|
179
|
+
// title, mono and quiet, so the name starts at the same x on every row; the
|
|
180
|
+
// subtitle is a real line; the state and the scope are pills and chips
|
|
181
|
+
// rather than a grey run-on. The sort stamp is all that is left of .gr-meta,
|
|
182
|
+
// and it renders only while a date sort is active.
|
|
163
183
|
return `<div class="gr-row" data-goal-id="${escapeHtml(String(g.id))}">
|
|
164
184
|
<div class="gr-ringcol">${ringHtml}</div>
|
|
165
185
|
<div class="gr-main">
|
|
166
|
-
<a class="gr-title" href="${goalHref}"
|
|
167
|
-
|
|
186
|
+
<a class="gr-title" href="${goalHref}">${idHtml}${escapeHtml(g.title || 'Untitled goal')}</a>
|
|
187
|
+
${subtitleLine(g)}
|
|
188
|
+
${factsHtml}
|
|
189
|
+
${stampHtml ? `<div class="gr-meta">${stampHtml.replace(/^ · /, '')}${catHtml}</div>` : (catHtml ? `<div class="gr-meta">${catHtml}</div>` : '')}
|
|
168
190
|
${achieved ? '' : goalRollLine(r)}
|
|
169
191
|
</div>
|
|
170
192
|
<div class="gr-right">${right}</div>
|
|
@@ -3,8 +3,27 @@
|
|
|
3
3
|
shared kit doesn't carry lives here: goal cards, the detail band, criteria /
|
|
4
4
|
member / conflict lists, the invite + pending panels. Shared pieces —
|
|
5
5
|
.pager--paged, .count-pill, .kit-tabs, .filters, .empty-state, .kit-skel —
|
|
6
|
-
are in style.css's hall-kit section.
|
|
7
|
-
|
|
6
|
+
are in style.css's hall-kit section.
|
|
7
|
+
|
|
8
|
+
RE-SKINNED INTO THE CHROME WORLD, task 1003307 (goal 1000081). Goals is the
|
|
9
|
+
LIST ARCHETYPE the governance-and-lists pass applies across thirteen pages,
|
|
10
|
+
so this sheet is the reference the other twelve are held against. The
|
|
11
|
+
archetype is v3 "the glass hall", the owner's pick from the composition round
|
|
12
|
+
— docs/design/hall-direction-v2.md §6.
|
|
13
|
+
|
|
14
|
+
Three rules this sheet now keeps, and the next editor has to keep too:
|
|
15
|
+
- NO COMPAT ALIAS. --surface / --surface-2 / --border / --border-strong /
|
|
16
|
+
--accent-weak / --accent-text still resolve, because pages nobody has
|
|
17
|
+
re-skinned need them to. Spending one HERE is legal CSS that quietly opts
|
|
18
|
+
this sheet back out of the world. The real names are --bg-card / --glass /
|
|
19
|
+
--rule-soft / --rule / --accent-tint / --accent-ink.
|
|
20
|
+
- --line IS A WIDTH (1px), not a colour. The hairline's colour is --rule or
|
|
21
|
+
--rule-soft. A "border: var(--line) solid var(--rule-soft)" reads as one
|
|
22
|
+
idea; "1px solid var(--border)" reads as two guesses.
|
|
23
|
+
- THE PANEL HAS NO EDGE. v3 separates by tone: --bg-card at the full
|
|
24
|
+
--radius, its border transparent so focus and state have somewhere to go.
|
|
25
|
+
The ch unit is the zero glyph's width, not a character — the body measure is
|
|
26
|
+
--measure (48ch, measured at ~60 characters), never fresh ch arithmetic. */
|
|
8
27
|
|
|
9
28
|
/* ---- goal-card grid (the CARDS view) ----
|
|
10
29
|
task 2171 density pass: minmax 300→230 (four across at desktop width),
|
|
@@ -15,11 +34,12 @@
|
|
|
15
34
|
.goal-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 10px; }
|
|
16
35
|
.goal-card {
|
|
17
36
|
display: flex; flex-direction: column; gap: 7px;
|
|
18
|
-
background: var(--
|
|
37
|
+
background: var(--bg-card); border: var(--line) solid transparent;
|
|
19
38
|
border-radius: var(--radius); padding: 10px 12px;
|
|
20
39
|
color: var(--ink);
|
|
21
40
|
}
|
|
22
|
-
|
|
41
|
+
/* Hover lifts the tone; the transparent edge is what focus lands on. */
|
|
42
|
+
a.goal-card:hover { text-decoration: none; background: var(--glass); }
|
|
23
43
|
.goal-card__head { display: flex; align-items: flex-start; gap: 9px; }
|
|
24
44
|
/* task 1003136: the task-1760 drag handle/priority/dragging rules that lived
|
|
25
45
|
here are deleted with wireDragReorder (see goals-page.js) — the revived
|
|
@@ -34,10 +54,10 @@ a.goal-card:hover { text-decoration: none; border-color: var(--border-strong); b
|
|
|
34
54
|
/* task 2163 — the real goal id, shown as a monospace #NNN token so it reads as
|
|
35
55
|
an identifier and never gets confused with the priority ordinal on the left. */
|
|
36
56
|
.goal-card__id, .goal-detail__id {
|
|
37
|
-
font-family:
|
|
57
|
+
font-family: var(--font-mono);
|
|
38
58
|
font-variant-numeric: tabular-nums; font-weight: 600; color: var(--ink-faint);
|
|
39
59
|
}
|
|
40
|
-
.goal-card__id { padding: 0 5px; border:
|
|
60
|
+
.goal-card__id { padding: 0 5px; border: var(--line) solid var(--rule-soft); border-radius: var(--radius-sm); }
|
|
41
61
|
.goal-detail__id { font-size: 0.72em; vertical-align: 0.12em; margin-right: 4px; }
|
|
42
62
|
.goal-card__foot { display: flex; flex-wrap: wrap; gap: 4px 10px; font-size: 11.5px; color: var(--ink-soft); }
|
|
43
63
|
.goal-card__foot strong { font-variant-numeric: tabular-nums; }
|
|
@@ -49,8 +69,15 @@ a.goal-card:hover { text-decoration: none; border-color: var(--border-strong); b
|
|
|
49
69
|
|
|
50
70
|
/* ---- detail view ---- */
|
|
51
71
|
.goal-detail__head { display: flex; align-items: flex-start; gap: 20px; flex-wrap: wrap; }
|
|
52
|
-
|
|
53
|
-
|
|
72
|
+
/* The goal's name is the subject of the detail view, so it takes the display
|
|
73
|
+
voice (Manrope 300, tight, sentence case) rather than a heavy UI weight —
|
|
74
|
+
v3's own divergence from the mono-label archetypes. */
|
|
75
|
+
.goal-detail__title {
|
|
76
|
+
font-family: var(--font-display); font-weight: 300;
|
|
77
|
+
font-size: clamp(22px, 2.4vw, 28px); line-height: 1.15; letter-spacing: -0.03em;
|
|
78
|
+
color: var(--ink); text-shadow: var(--type-halo); margin: 0;
|
|
79
|
+
}
|
|
80
|
+
.goal-detail__desc { color: var(--ink-soft); font-size: 13.5px; max-width: var(--measure); margin: 6px 0 0; }
|
|
54
81
|
.goal-detail__actions { margin-left: auto; display: flex; gap: 8px; align-items: center; }
|
|
55
82
|
/* task 1888/1828 — Completion | Members | Conflicts share ONE card. Wide:
|
|
56
83
|
three columns split by vertical rules. Narrow: they stack, split by
|
|
@@ -59,10 +86,10 @@ a.goal-card:hover { text-decoration: none; border-color: var(--border-strong); b
|
|
|
59
86
|
work list can no longer push them off the bottom of the page. */
|
|
60
87
|
.goal-band { padding: 0; margin-top: 20px; display: grid; grid-template-columns: 1fr; }
|
|
61
88
|
.goal-band__col { padding: 14px 18px; min-width: 0; }
|
|
62
|
-
.goal-band__col + .goal-band__col { border-top:
|
|
89
|
+
.goal-band__col + .goal-band__col { border-top: var(--line) solid var(--rule-soft); }
|
|
63
90
|
@media (min-width: 900px) {
|
|
64
91
|
.goal-band { grid-template-columns: repeat(3, minmax(0, 1fr)); }
|
|
65
|
-
.goal-band__col + .goal-band__col { border-top: none; border-left:
|
|
92
|
+
.goal-band__col + .goal-band__col { border-top: none; border-left: var(--line) solid var(--rule-soft); }
|
|
66
93
|
}
|
|
67
94
|
|
|
68
95
|
/* Live conflicts: the band COLUMN can't own the card border, so it gets a
|
|
@@ -70,26 +97,26 @@ a.goal-card:hover { text-decoration: none; border-color: var(--border-strong); b
|
|
|
70
97
|
(Count pills on these headers are the shared .count-pill.) */
|
|
71
98
|
.goal-conflicts-card--live { background: color-mix(in srgb, var(--warn) 6%, transparent); }
|
|
72
99
|
.goal-conflicts-card--live .count-pill { background: var(--warn-weak); color: var(--warn); }
|
|
73
|
-
#goal-conflicts-view-card.goal-conflicts-card--live { background: var(--
|
|
100
|
+
#goal-conflicts-view-card.goal-conflicts-card--live { background: var(--bg-card); border-color: color-mix(in srgb, var(--warn) 42%, transparent); }
|
|
74
101
|
|
|
75
102
|
/* task 1828 — inline Claim on a ready To-do row + the conflicts "view all". */
|
|
76
103
|
.goal-claim-btn {
|
|
77
104
|
display: inline-flex; align-items: center; justify-content: center;
|
|
78
105
|
height: 24px; padding: 0 12px; border-radius: var(--radius-sm);
|
|
79
|
-
border:
|
|
106
|
+
border: var(--line) solid var(--accent); background: var(--accent); color: var(--accent-on);
|
|
80
107
|
font-size: 12px; font-weight: 600; cursor: pointer; white-space: nowrap;
|
|
81
108
|
}
|
|
82
|
-
.goal-claim-btn:hover:not(:disabled) { background: var(--accent-
|
|
109
|
+
.goal-claim-btn:hover:not(:disabled) { background: var(--accent-lift); }
|
|
83
110
|
.goal-claim-btn:disabled { opacity: 0.55; cursor: default; }
|
|
84
111
|
/* task 1828 — Release on the viewer's OWN active claim (ghost, not accent —
|
|
85
112
|
it's the undo of a claim); a muted label for another builder's claim. */
|
|
86
113
|
.goal-release-btn {
|
|
87
114
|
display: inline-flex; align-items: center; justify-content: center;
|
|
88
115
|
height: 24px; padding: 0 12px; border-radius: var(--radius-sm);
|
|
89
|
-
border:
|
|
116
|
+
border: var(--line) solid var(--rule); background: var(--bg-card); color: var(--ink-soft);
|
|
90
117
|
font-size: 12px; font-weight: 600; cursor: pointer; white-space: nowrap;
|
|
91
118
|
}
|
|
92
|
-
.goal-release-btn:hover:not(:disabled) { background: var(--
|
|
119
|
+
.goal-release-btn:hover:not(:disabled) { background: var(--glass); color: var(--ink); }
|
|
93
120
|
.goal-release-btn:disabled { opacity: 0.55; cursor: default; }
|
|
94
121
|
.ledger__claimed { font-size: 12px; color: var(--ink-faint); white-space: nowrap; }
|
|
95
122
|
.ledger__action { text-align: right; white-space: nowrap; }
|
|
@@ -121,8 +148,8 @@ a.goal-card:hover { text-decoration: none; border-color: var(--border-strong); b
|
|
|
121
148
|
.goal-work__tabs .kit-tabs { margin: 0; }
|
|
122
149
|
.conflict__sev {
|
|
123
150
|
display: inline-flex; align-items: center; height: 18px; padding: 0 7px; margin-left: 8px;
|
|
124
|
-
border-radius:
|
|
125
|
-
background: var(--
|
|
151
|
+
border-radius: var(--radius-pill); font-size: 10.5px; font-weight: 600; vertical-align: 1px;
|
|
152
|
+
background: var(--glass); color: var(--ink-soft);
|
|
126
153
|
}
|
|
127
154
|
.conflict__sev--high { background: var(--danger-weak); color: var(--danger); }
|
|
128
155
|
.conflict__sev--medium { background: var(--warn-weak); color: var(--warn); }
|
|
@@ -130,10 +157,13 @@ a.goal-card:hover { text-decoration: none; border-color: var(--border-strong); b
|
|
|
130
157
|
.crit-list { list-style: none; margin: 10px 0 0; padding: 0; display: flex; flex-direction: column; }
|
|
131
158
|
/* task 1002164 — a third trailing column holds the per-criterion Confirm action;
|
|
132
159
|
it collapses to zero width on the rows that have none. */
|
|
133
|
-
.crit { display: grid; grid-template-columns: 22px minmax(0,1fr) auto; gap: 10px; padding: 6px 0; border-bottom:
|
|
160
|
+
.crit { display: grid; grid-template-columns: 22px minmax(0,1fr) auto; gap: 10px; padding: 6px 0; border-bottom: var(--line) solid var(--rule-soft); font-size: 13px; }
|
|
134
161
|
.crit:last-child { border-bottom: none; }
|
|
135
|
-
.crit__mark { width: 18px; height: 18px; border-radius: 50%; border: 1.5px solid var(--
|
|
136
|
-
|
|
162
|
+
.crit__mark { width: 18px; height: 18px; border-radius: 50%; border: 1.5px solid var(--rule); display: flex; align-items: center; justify-content: center; font-size: 11px; color: var(--ink-faint); }
|
|
163
|
+
/* The tick reads ON the ok fill, so it takes the card ground: near-white in
|
|
164
|
+
light where --ok is a deep green, near-black in dark where --ok is a light
|
|
165
|
+
one. A fixed #fff was legible in one mode only. */
|
|
166
|
+
.crit--done .crit__mark { background: var(--ok); border-color: var(--ok); color: var(--bg-card); }
|
|
137
167
|
.crit--done .crit__text { color: var(--ink-soft); }
|
|
138
168
|
|
|
139
169
|
/* task 1002164 — "met, awaiting confirmation": every linked task shipped but the
|
|
@@ -143,33 +173,33 @@ a.goal-card:hover { text-decoration: none; border-color: var(--border-strong); b
|
|
|
143
173
|
.crit__act { display: flex; align-items: center; }
|
|
144
174
|
.crit-list--full .crit__act { align-self: start; padding-top: 1px; }
|
|
145
175
|
.crit__confirm {
|
|
146
|
-
cursor: pointer; white-space: nowrap; padding: 3px 10px; border-radius:
|
|
147
|
-
border:
|
|
148
|
-
font: inherit; font-size: 11.5px; font-weight: 600;
|
|
176
|
+
cursor: pointer; white-space: nowrap; padding: 3px 10px; border-radius: var(--radius-pill);
|
|
177
|
+
border: var(--line) solid var(--ok); background: transparent; color: var(--ok);
|
|
178
|
+
font: inherit; font-size: 11.5px; font-weight: 600; min-height: 24px;
|
|
149
179
|
}
|
|
150
|
-
.crit__confirm:hover:not(:disabled) { background: var(--ok); color:
|
|
180
|
+
.crit__confirm:hover:not(:disabled) { background: var(--ok); color: var(--bg-card); }
|
|
151
181
|
.crit__confirm:disabled { opacity: .6; cursor: default; }
|
|
152
182
|
.crit__flag {
|
|
153
|
-
white-space: nowrap; padding: 2px 8px; border-radius:
|
|
183
|
+
white-space: nowrap; padding: 2px 8px; border-radius: var(--radius-pill);
|
|
154
184
|
background: var(--warn-weak); color: var(--warn); font-size: 10.5px; font-weight: 600;
|
|
155
185
|
}
|
|
156
186
|
/* BV1.R79: per-criterion expand in the capped band — short label, full text on
|
|
157
187
|
click (matches the Roadmap page's .vbar__crit-d pattern). */
|
|
158
188
|
.crit-d { min-width: 0; }
|
|
159
|
-
.crit-d > summary { cursor: pointer; list-style: none; text-decoration: underline dotted var(--
|
|
189
|
+
.crit-d > summary { cursor: pointer; list-style: none; min-height: 24px; text-decoration: underline dotted var(--rule); text-underline-offset: 3px; }
|
|
160
190
|
.crit-d > summary::-webkit-details-marker { display: none; }
|
|
161
191
|
.crit-d[open] > summary { text-decoration: none; font-weight: 500; }
|
|
162
192
|
.crit-d .crit__detail { margin-top: 4px; }
|
|
163
193
|
|
|
164
194
|
.member-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
|
|
165
|
-
.member { display: flex; align-items: center; gap: 10px; padding: 6px 0; border-bottom:
|
|
195
|
+
.member { display: flex; align-items: center; gap: 10px; padding: 6px 0; border-bottom: var(--line) solid var(--rule-soft); font-size: 13px; }
|
|
166
196
|
.member:last-child { border-bottom: none; }
|
|
167
|
-
.member__avatar { width: 24px; height: 24px; border-radius: 50%; background: var(--accent-
|
|
197
|
+
.member__avatar { width: 24px; height: 24px; border-radius: 50%; background: var(--accent-tint); color: var(--accent-ink); font-size: 10px; font-weight: 600; display: flex; align-items: center; justify-content: center; overflow: hidden; flex-shrink: 0; }
|
|
168
198
|
.member__avatar img { width: 100%; height: 100%; object-fit: cover; border-radius: 50%; }
|
|
169
199
|
.member__name { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
170
200
|
.member__name small { color: var(--ink-faint); }
|
|
171
|
-
.member-pill { display: inline-flex; align-items: center; height: 20px; padding: 0 9px; border-radius:
|
|
172
|
-
.member-pill--lead { background: var(--accent-
|
|
201
|
+
.member-pill { display: inline-flex; align-items: center; height: 20px; padding: 0 9px; border-radius: var(--radius-pill); font-size: 11px; font-weight: 600; background: var(--glass); color: var(--ink-soft); }
|
|
202
|
+
.member-pill--lead { background: var(--accent-tint); color: var(--accent-ink); }
|
|
173
203
|
|
|
174
204
|
/* task 1762/1877 — owner/manager invite control (goal member admission),
|
|
175
205
|
collapsed behind "+ Invite" (disclosure, closed by default — task 2171). */
|
|
@@ -181,17 +211,21 @@ a.goal-card:hover { text-decoration: none; border-color: var(--border-strong); b
|
|
|
181
211
|
pending invite/join-request queue (manager view, next to the invite box). */
|
|
182
212
|
.goal-badge--locked { background: var(--warn-weak); color: var(--warn); }
|
|
183
213
|
.goal-pending { margin: 4px 0 10px; display: flex; flex-direction: column; gap: 10px; }
|
|
184
|
-
.pending-group__h {
|
|
214
|
+
.pending-group__h {
|
|
215
|
+
font-family: var(--label-face); font-size: var(--label-size); font-weight: 400;
|
|
216
|
+
letter-spacing: var(--label-space); text-transform: var(--label-case);
|
|
217
|
+
color: var(--ink-faint); margin: 0 0 4px; display: flex; align-items: center; gap: 6px;
|
|
218
|
+
}
|
|
185
219
|
.pending-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
|
|
186
|
-
.pending-row { display: flex; align-items: center; gap: 8px; padding: 6px 0; border-bottom:
|
|
220
|
+
.pending-row { display: flex; align-items: center; gap: 8px; padding: 6px 0; border-bottom: var(--line) solid var(--rule-soft); font-size: 13px; flex-wrap: wrap; }
|
|
187
221
|
.pending-row:last-child { border-bottom: none; }
|
|
188
222
|
.pending-row__who { font-weight: 600; }
|
|
189
223
|
.pending-row__note { color: var(--ink-faint); font-size: 12px; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
190
224
|
.pending-row__actions { display: flex; gap: 6px; margin-left: auto; }
|
|
191
225
|
|
|
192
|
-
.conflict { border:
|
|
226
|
+
.conflict { border: var(--line) solid color-mix(in srgb, var(--warn) 42%, transparent); background: var(--warn-weak); border-radius: var(--radius-sm); padding: 8px 12px; font-size: 12.5px; margin: 8px 0 0; }
|
|
193
227
|
.conflict__pair { font-weight: 600; }
|
|
194
|
-
.conflict__paths { font-family:
|
|
228
|
+
.conflict__paths { font-family: var(--font-mono); font-size: 11.5px; color: var(--ink-soft); margin-top: 4px; word-break: break-all; }
|
|
195
229
|
.conflict-note { font-size: 12px; color: var(--ink-faint); margin: 10px 0 0; }
|
|
196
230
|
|
|
197
231
|
/* Filtered-count line under the kit filter bar (list view). */
|
|
@@ -214,37 +248,84 @@ a.goal-card:hover { text-decoration: none; border-color: var(--border-strong); b
|
|
|
214
248
|
.gr-sm b { font-size: 20px; font-weight: 700; letter-spacing: -.02em; color: var(--ink); font-variant-numeric: tabular-nums; }
|
|
215
249
|
.gr-sm__dot { width: 8px; height: 8px; border-radius: 50%; align-self: center; }
|
|
216
250
|
|
|
217
|
-
|
|
218
|
-
|
|
251
|
+
/* The group head sits on a --rule hairline (the archetype's .group__head): a
|
|
252
|
+
heavier line than the rows' --rule-soft, so the groups read as the outer
|
|
253
|
+
division and the rows as the inner one. */
|
|
254
|
+
.gr-sec { display: flex; align-items: center; gap: 12px; margin: 26px 0 0; padding: 0 0 10px; border-bottom: var(--line) solid var(--rule); }
|
|
255
|
+
/* The section name is the label voice — take the tokens, never the family:
|
|
256
|
+
--label-face is mono in light and the body face in dark, because mono caps
|
|
257
|
+
read as precise on paper and as thin and technical on black. */
|
|
258
|
+
.gr-sec b {
|
|
259
|
+
font-family: var(--label-face); font-size: var(--label-size); font-weight: 400;
|
|
260
|
+
letter-spacing: var(--label-space); text-transform: var(--label-case);
|
|
261
|
+
color: var(--ink-faint);
|
|
262
|
+
}
|
|
219
263
|
.gr-sec__n { font-size: 12px; color: var(--ink-faint); font-variant-numeric: tabular-nums; }
|
|
220
264
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
.
|
|
224
|
-
|
|
265
|
+
/* The rollup list is one panel, not a stack of bordered rows: --bg-card at the
|
|
266
|
+
full radius with a transparent edge, and the rows' own hairlines doing the
|
|
267
|
+
dividing. The padding is the panel's, so the first and last rows breathe
|
|
268
|
+
against it rather than against their own borders. */
|
|
269
|
+
.gr-list { border: var(--line) solid transparent; border-radius: var(--radius); background: var(--bg-card); padding: 4px 0; overflow: hidden; }
|
|
270
|
+
/* The archetype's row (mock .goal): the air is the loosest of the three
|
|
271
|
+
versions, the columns are ring / content / right, and the rule sits on TOP so
|
|
272
|
+
the first row can drop it and start flush against the panel's own padding. */
|
|
273
|
+
.gr-row { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 24px; align-items: start; padding: 20px 22px; border-top: var(--line) solid var(--rule-soft); }
|
|
274
|
+
.gr-row:first-child { border-top: 0; }
|
|
275
|
+
.gr-row:hover { background: var(--glass); }
|
|
225
276
|
.gr-ringcol { flex: none; }
|
|
226
277
|
.gr-crit-none { display: inline-grid; place-items: center; width: 44px; height: 44px; border-radius: 50%; border: 2px solid var(--rule); color: var(--ink-faint); font-size: 13px; }
|
|
227
278
|
.gr-main { min-width: 0; }
|
|
228
|
-
|
|
229
|
-
.
|
|
230
|
-
|
|
231
|
-
|
|
279
|
+
/* The goal's name is the way into the goal, so it is a control and owes the
|
|
280
|
+
24px floor on BOTH axes. Its 15px/1.3 line box measured 20px tall (the kit's
|
|
281
|
+
controls-24px finding, 26 rows at 1440); the padding buys the height and the
|
|
282
|
+
equal negative margin hands the space back so the row does not re-space. */
|
|
283
|
+
/* The name at the archetype's weight: 17px/500, not 15px/650. A heavy small
|
|
284
|
+
title reads as a label; this reads as the thing itself. It is also the way
|
|
285
|
+
into the goal, so it owes the 24px floor on both axes — the padding buys the
|
|
286
|
+
height and the equal negative margin hands the space back. */
|
|
287
|
+
.gr-title {
|
|
288
|
+
display: inline-block; font-size: 17px; font-weight: 500; letter-spacing: -.014em;
|
|
289
|
+
color: var(--ink); line-height: 1.3; text-decoration: none;
|
|
290
|
+
min-height: 24px; min-width: 24px; padding: 3px 4px; margin: 0 -4px;
|
|
291
|
+
}
|
|
292
|
+
.gr-title:hover { color: var(--accent-ink); text-decoration: underline; text-underline-offset: 3px; }
|
|
293
|
+
/* The id rides INSIDE the title rather than on the meta line below it, so every
|
|
294
|
+
row's name starts at the same x and the id never competes for the second line
|
|
295
|
+
the subtitle now wants. */
|
|
296
|
+
.gr-title__id { font-family: var(--font-mono); font-size: 12px; font-variant-numeric: tabular-nums; color: var(--ink-faint); margin-right: 9px; }
|
|
297
|
+
|
|
298
|
+
/* The goal's own one-line explanation. Task 1003224 made this a tooltip; task
|
|
299
|
+
1003307 gives it the line back on the owner's call, because 35 of 72 goals
|
|
300
|
+
carry one and a tooltip does not exist on a touch screen. Empty goals render
|
|
301
|
+
no element at all, so a row without a subtitle simply closes up. */
|
|
302
|
+
.gr-sub { margin: 5px 0 0; color: var(--ink-soft); font-size: 14px; line-height: 1.5; max-width: var(--measure); }
|
|
303
|
+
|
|
304
|
+
/* The fact line: the state, then what the goal is scoped to. The pill and the
|
|
305
|
+
chip themselves are the shell's .fact-pill / .fact-chip — this row only says
|
|
306
|
+
how they sit together. */
|
|
307
|
+
.gr-facts { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; margin: 12px 0 0; }
|
|
308
|
+
/* What is left of the old meta run-on: the sort stamp, and only while a date
|
|
309
|
+
sort is active. The id moved into the title, the version became a chip and the
|
|
310
|
+
status became a pill. */
|
|
311
|
+
.gr-meta { font-size: 12px; color: var(--ink-faint); margin-top: 8px; font-variant-numeric: tabular-nums; }
|
|
312
|
+
.gr-roll { display: flex; flex-wrap: wrap; gap: 8px 18px; margin-top: 12px; }
|
|
232
313
|
.gr-d { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--ink-soft); font-variant-numeric: tabular-nums; }
|
|
233
314
|
.gr-d i { width: 7px; height: 7px; border-radius: 50%; }
|
|
234
315
|
.gr-d b { color: var(--ink); font-weight: 600; }
|
|
235
|
-
.gr-right { text-align: right; min-width: 150px; display: flex; flex-direction: column; align-items: flex-end; gap:
|
|
316
|
+
.gr-right { text-align: right; min-width: 150px; max-width: 244px; display: flex; flex-direction: column; align-items: flex-end; gap: 10px; }
|
|
236
317
|
.gr-next { display: flex; flex-direction: column; align-items: flex-end; gap: 8px; max-width: 230px; }
|
|
237
318
|
.gr-next__t { font-size: 12.5px; color: var(--ink-soft); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 230px; }
|
|
238
|
-
.gr-claim { background: var(--accent); color:
|
|
319
|
+
.gr-claim { background: var(--accent); color: var(--accent-on); border-radius: var(--radius-sm); padding: 6px 14px; font-size: 12.5px; font-weight: 650; white-space: nowrap; }
|
|
239
320
|
.gr-claim:hover { background: var(--accent-deep); }
|
|
240
|
-
.gr-drill { font-size: 12.5px; color: var(--ink-faint); display: inline-flex; align-items: center; gap: 5px; }
|
|
241
|
-
.gr-drill:hover { color: var(--accent-
|
|
321
|
+
.gr-drill { font-size: 12.5px; color: var(--ink-faint); display: inline-flex; align-items: center; min-height: 24px; gap: 5px; }
|
|
322
|
+
.gr-drill:hover { color: var(--accent-ink); }
|
|
242
323
|
.gr-met { font-size: 12.5px; font-weight: 600; color: var(--ok); }
|
|
243
324
|
.gr-quiet { font-size: 12.5px; color: var(--ink-faint); }
|
|
244
325
|
|
|
245
326
|
.gr-pills { display: flex; flex-wrap: wrap; gap: 8px; }
|
|
246
|
-
.gr-pill { display: inline-flex; align-items: center; gap: 8px; background: var(--bg-card); border:
|
|
247
|
-
.gr-pill:hover {
|
|
327
|
+
.gr-pill { display: inline-flex; align-items: center; gap: 8px; background: var(--bg-card); border: var(--line) solid var(--rule); border-radius: var(--radius-pill); padding: 6px 13px 6px 8px; color: var(--ink-soft); font-size: 12.5px; min-height: 24px; }
|
|
328
|
+
.gr-pill:hover { background: var(--glass); }
|
|
248
329
|
.gr-pill b { color: var(--ink); font-weight: 600; }
|
|
249
330
|
.gr-pill__ok { width: 17px; height: 17px; border-radius: 50%; background: var(--ok-weak); color: var(--ok); display: grid; place-items: center; font-size: 10px; font-weight: 800; }
|
|
250
331
|
.gr-pill__id { color: var(--ink-faint); font-variant-numeric: tabular-nums; }
|
|
@@ -266,25 +347,26 @@ a.goal-card:hover { text-decoration: none; border-color: var(--border-strong); b
|
|
|
266
347
|
subordinate; the bulk prose Claude writes is behind a disclosure and absent
|
|
267
348
|
from the default reading path until someone asks for it.
|
|
268
349
|
Tokens only from style.css's real set (--ink-soft, --ink-faint, --rule,
|
|
269
|
-
--
|
|
350
|
+
--glass, --radius-sm) — inventing one renders as nothing, which is how
|
|
270
351
|
copy-desk.css ended up with invisible fallbacks (idea 1000821). */
|
|
271
352
|
.goal-detail__subtitle {
|
|
272
353
|
color: var(--ink-soft);
|
|
273
354
|
font-size: 13px;
|
|
274
355
|
font-weight: 400;
|
|
275
356
|
line-height: 1.45;
|
|
276
|
-
max-width:
|
|
357
|
+
max-width: var(--measure);
|
|
277
358
|
margin: 3px 0 0;
|
|
278
359
|
}
|
|
279
360
|
|
|
280
361
|
/* The disclosure is deliberately quiet: a row someone can ignore. */
|
|
281
362
|
.claude-text {
|
|
282
363
|
margin: 10px 0 0;
|
|
283
|
-
max-width:
|
|
284
|
-
border-top:
|
|
364
|
+
max-width: var(--measure);
|
|
365
|
+
border-top: var(--line) solid var(--rule);
|
|
285
366
|
padding-top: 8px;
|
|
286
367
|
}
|
|
287
368
|
|
|
369
|
+
/* A <summary> is a control: the floor applies. It measured 162x19. */
|
|
288
370
|
.claude-text__toggle {
|
|
289
371
|
color: var(--ink-faint);
|
|
290
372
|
font-size: 12px;
|
|
@@ -293,6 +375,7 @@ a.goal-card:hover { text-decoration: none; border-color: var(--border-strong); b
|
|
|
293
375
|
user-select: none;
|
|
294
376
|
display: inline-flex;
|
|
295
377
|
align-items: center;
|
|
378
|
+
min-height: 24px;
|
|
296
379
|
gap: 6px;
|
|
297
380
|
}
|
|
298
381
|
|
|
@@ -305,18 +388,16 @@ a.goal-card:hover { text-decoration: none; border-color: var(--border-strong); b
|
|
|
305
388
|
}
|
|
306
389
|
.claude-text[open] > .claude-text__toggle::before { transform: rotate(90deg); }
|
|
307
390
|
.claude-text__toggle:hover { color: var(--ink-soft); }
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
border-radius: var(--radius-sm);
|
|
312
|
-
}
|
|
391
|
+
/* The shell already rings :focus-visible in the world's two-tone recipe; a
|
|
392
|
+
page-local ring here would be a second, thinner one. Removed with the
|
|
393
|
+
re-skin — style.css:...:focus-visible owns it. */
|
|
313
394
|
|
|
314
395
|
/* Set apart once opened, so it reads as a machine's notes rather than as the
|
|
315
396
|
goal's own definition. */
|
|
316
397
|
.claude-text__body {
|
|
317
398
|
margin: 8px 0 0;
|
|
318
399
|
padding: 8px 10px;
|
|
319
|
-
background: var(--
|
|
400
|
+
background: var(--glass);
|
|
320
401
|
border-radius: var(--radius-sm);
|
|
321
402
|
color: var(--ink-soft);
|
|
322
403
|
font-size: 13px;
|
|
@@ -30,7 +30,14 @@
|
|
|
30
30
|
<div class="app-body">
|
|
31
31
|
<header class="app-topbar" id="app-topbar"></header>
|
|
32
32
|
<div class="app-content">
|
|
33
|
-
|
|
33
|
+
<!-- task 1003307: the board page head. goals.html shipped with NO <h1>
|
|
34
|
+
at all (the platform floor one-header-main-h1 measured 0), so the
|
|
35
|
+
re-skin carries the structural fix rather than porting the hole. The
|
|
36
|
+
heading is the label voice, not a display line: the goals ARE the
|
|
37
|
+
page, and a 22px title above them would be the loudest thing on a
|
|
38
|
+
surface whose content is rows. -->
|
|
39
|
+
<div class="page-head page-head--board">
|
|
40
|
+
<h1 class="page-head__h">Goals</h1>
|
|
34
41
|
<p class="page-head__sub" id="goals-sub">Loading goals…</p>
|
|
35
42
|
</div>
|
|
36
43
|
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_": "The hall's Goals list + goal detail through modules/ui-design/kit/render.js (task 1003307). Goals is the LIST ARCHETYPE the governance-and-lists re-skin applies across thirteen pages, so its floors are measured first and the rest are held against them. Populated look: node scripts/hall-preview/server.js --port 4620 --fixture-me, then --base-in/--base-out at that origin.",
|
|
3
|
+
"page": "/builders/goals",
|
|
4
|
+
"surface": "hall-ui",
|
|
5
|
+
"stub": {
|
|
6
|
+
"prefix": "/builders/"
|
|
7
|
+
},
|
|
8
|
+
"modeQuery": false,
|
|
9
|
+
"_feeds": "The kit's own stub carries no goal feed, so against it the page renders its EMPTY and SKELETON states — which is deliberate: an empty board is a state the floors must hold in. Against the hall-preview harness the same states render populated. The feed 404s are declared here, never hidden. work-categories and goals/rollups have no checked-in fixture, so the harness answers 404: declared here, not hidden.",
|
|
10
|
+
"ignoreRequests": [
|
|
11
|
+
"/api/(gds|bongos)/me$",
|
|
12
|
+
"/api/(gds|bongos)/me/",
|
|
13
|
+
"/api/(gds|bongos)/goals",
|
|
14
|
+
"/api/(gds|bongos)/tasks",
|
|
15
|
+
"/api/(gds|bongos)/versions",
|
|
16
|
+
"/api/(gds|bongos)/inbox/",
|
|
17
|
+
"/api/(gds|bongos)/work-categories"
|
|
18
|
+
],
|
|
19
|
+
"ignoreConsole": [
|
|
20
|
+
"/api/(gds|bongos)/",
|
|
21
|
+
"\b401\b",
|
|
22
|
+
"\b404\b",
|
|
23
|
+
"Unauthorized",
|
|
24
|
+
"Not Found",
|
|
25
|
+
"load failed"
|
|
26
|
+
],
|
|
27
|
+
"states": {
|
|
28
|
+
"list": {
|
|
29
|
+
"auth": true,
|
|
30
|
+
"actions": [
|
|
31
|
+
[
|
|
32
|
+
"wait",
|
|
33
|
+
600
|
|
34
|
+
]
|
|
35
|
+
],
|
|
36
|
+
"expect": {
|
|
37
|
+
"visible": [
|
|
38
|
+
"#goals-list-view",
|
|
39
|
+
"#goals-filters"
|
|
40
|
+
],
|
|
41
|
+
"hidden": [
|
|
42
|
+
"#goal-detail-view"
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
"detail": {
|
|
47
|
+
"auth": true,
|
|
48
|
+
"url": "/builders/goals#/goal/1000081",
|
|
49
|
+
"actions": [
|
|
50
|
+
[
|
|
51
|
+
"wait",
|
|
52
|
+
800
|
|
53
|
+
]
|
|
54
|
+
],
|
|
55
|
+
"expect": {
|
|
56
|
+
"visible": [
|
|
57
|
+
"#goal-detail-view"
|
|
58
|
+
]
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
"out": {
|
|
62
|
+
"auth": false
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
"reducedMotion": {
|
|
66
|
+
"auth": true,
|
|
67
|
+
"actions": [
|
|
68
|
+
[
|
|
69
|
+
"wait",
|
|
70
|
+
600
|
|
71
|
+
]
|
|
72
|
+
]
|
|
73
|
+
}
|
|
74
|
+
}
|