@unson/brainbase-mcp 0.23.6 → 0.23.8
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/dist/canonical-task-service.d.ts +11 -0
- package/dist/canonical-task-service.js +45 -0
- package/dist/world-extension.js +1 -1
- package/package.json +2 -2
- package/ui/world/world-canvas-notes.js +31 -0
- package/ui/world/world-canvas-ui.css +352 -0
- package/ui/world/world-canvas-ui.js +467 -0
- package/ui/world/world-district.js +78 -10
- package/ui/world/world-view.css +2 -0
- package/ui/world/world-view.js +238 -62
|
@@ -12,6 +12,14 @@ export interface CanonicalTaskContext extends JsonRecord {
|
|
|
12
12
|
/** Opaque host-policy scope, not authority or task input. */
|
|
13
13
|
storageScope?: string;
|
|
14
14
|
}
|
|
15
|
+
/** Conditions to review; this metadata is not evidence of completion. */
|
|
16
|
+
export interface CanonicalTaskCompletionContract {
|
|
17
|
+
goal: string;
|
|
18
|
+
criteria: Array<{
|
|
19
|
+
id: string;
|
|
20
|
+
condition: string;
|
|
21
|
+
}>;
|
|
22
|
+
}
|
|
15
23
|
export interface CanonicalTaskRecord extends JsonRecord {
|
|
16
24
|
id: string;
|
|
17
25
|
version: number;
|
|
@@ -29,11 +37,13 @@ export interface CanonicalTaskRecord extends JsonRecord {
|
|
|
29
37
|
project_codes?: string[];
|
|
30
38
|
/** What the work is for, in a few words (one per task); null when unlabelled. */
|
|
31
39
|
purpose_label?: string | null;
|
|
40
|
+
completion_contract?: CanonicalTaskCompletionContract | null;
|
|
32
41
|
created_at?: string | null;
|
|
33
42
|
updated_at?: string | null;
|
|
34
43
|
web_url?: string | null;
|
|
35
44
|
}
|
|
36
45
|
export interface CanonicalTaskCreateInput extends JsonRecord {
|
|
46
|
+
completion_contract?: unknown;
|
|
37
47
|
title: string;
|
|
38
48
|
description?: string | null;
|
|
39
49
|
priority?: CanonicalTaskPriority | string | null;
|
|
@@ -46,6 +56,7 @@ export interface CanonicalTaskCreateInput extends JsonRecord {
|
|
|
46
56
|
purpose_label?: string | null;
|
|
47
57
|
}
|
|
48
58
|
export interface CanonicalTaskUpdateInput extends JsonRecord {
|
|
59
|
+
completion_contract?: unknown;
|
|
49
60
|
title?: string;
|
|
50
61
|
description?: string | null;
|
|
51
62
|
priority?: CanonicalTaskPriority | string | null;
|
|
@@ -26,6 +26,7 @@ const DEFAULT_LIMIT = 20;
|
|
|
26
26
|
const MAX_LIMIT = 100;
|
|
27
27
|
const RESERVED_IDEMPOTENCY_PREFIXES = ['api:', 'workflow:'];
|
|
28
28
|
const CREATE_FIELDS = new Set([
|
|
29
|
+
'completion_contract',
|
|
29
30
|
'title',
|
|
30
31
|
'description',
|
|
31
32
|
'priority',
|
|
@@ -38,6 +39,7 @@ const CREATE_FIELDS = new Set([
|
|
|
38
39
|
'purpose_label',
|
|
39
40
|
]);
|
|
40
41
|
const MUTABLE_FIELDS = new Set([
|
|
42
|
+
'completion_contract',
|
|
41
43
|
'expected_version',
|
|
42
44
|
'title',
|
|
43
45
|
'description',
|
|
@@ -79,6 +81,39 @@ const MAX_PURPOSE_LABEL_LENGTH = 30;
|
|
|
79
81
|
function normalizePurposeLabel(value) {
|
|
80
82
|
return normalizeString(value, 'purpose_label', { max: MAX_PURPOSE_LABEL_LENGTH });
|
|
81
83
|
}
|
|
84
|
+
function normalizeCompletionContract(value) {
|
|
85
|
+
if (value == null)
|
|
86
|
+
return null;
|
|
87
|
+
const object = (candidate, keys) => {
|
|
88
|
+
if (!candidate || typeof candidate !== 'object' || Array.isArray(candidate)
|
|
89
|
+
|| ![Object.prototype, null].includes(Object.getPrototypeOf(candidate))
|
|
90
|
+
|| Object.keys(candidate).some((key) => !keys.includes(key))) {
|
|
91
|
+
fail('validation_error', 'completion_contract contains an invalid object');
|
|
92
|
+
}
|
|
93
|
+
return candidate;
|
|
94
|
+
};
|
|
95
|
+
const text = (candidate, field) => {
|
|
96
|
+
if (typeof candidate !== 'string')
|
|
97
|
+
fail('validation_error', `${field} must be a string`);
|
|
98
|
+
return normalizeString(candidate, field, { required: true, max: 2000, multiline: true });
|
|
99
|
+
};
|
|
100
|
+
const contract = object(value, ['goal', 'criteria']);
|
|
101
|
+
const goal = text(contract.goal, 'completion_contract.goal');
|
|
102
|
+
if (!Array.isArray(contract.criteria) || contract.criteria.length < 1 || contract.criteria.length > 50) {
|
|
103
|
+
fail('validation_error', 'completion_contract.criteria must contain 1 to 50 conditions');
|
|
104
|
+
}
|
|
105
|
+
const ids = new Set();
|
|
106
|
+
const criteria = Array.from(contract.criteria, (candidate) => {
|
|
107
|
+
const criterion = object(candidate, ['id', 'condition']);
|
|
108
|
+
if (typeof criterion.id !== 'string' || !/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/u.test(criterion.id)
|
|
109
|
+
|| ids.has(criterion.id)) {
|
|
110
|
+
fail('validation_error', 'completion_contract criterion id is invalid or duplicated');
|
|
111
|
+
}
|
|
112
|
+
ids.add(criterion.id);
|
|
113
|
+
return { id: criterion.id, condition: text(criterion.condition, 'completion_contract.criteria.condition') };
|
|
114
|
+
});
|
|
115
|
+
return { goal, criteria };
|
|
116
|
+
}
|
|
82
117
|
function normalizeIsoDate(value, field) {
|
|
83
118
|
const text = normalizeString(value, field);
|
|
84
119
|
if (text == null)
|
|
@@ -635,7 +670,9 @@ export class CanonicalTaskService {
|
|
|
635
670
|
if (!isCanonicalTaskPriority(priority))
|
|
636
671
|
fail('validation_error', 'priority is invalid', 400, { field: 'priority' });
|
|
637
672
|
const purposeLabel = normalizePurposeLabel(input.purpose_label);
|
|
673
|
+
const completionContract = normalizeCompletionContract(input.completion_contract);
|
|
638
674
|
return {
|
|
675
|
+
...(completionContract ? { completion_contract: completionContract } : {}),
|
|
639
676
|
title,
|
|
640
677
|
description: normalizeString(input.description, 'description', { max: 10000, multiline: true }),
|
|
641
678
|
priority,
|
|
@@ -656,6 +693,8 @@ export class CanonicalTaskService {
|
|
|
656
693
|
if (unknownFields.length > 0)
|
|
657
694
|
fail('validation_error', 'Task update contains unsupported fields', 400, { fields: unknownFields });
|
|
658
695
|
const patch = {};
|
|
696
|
+
if ('completion_contract' in input)
|
|
697
|
+
patch.completion_contract = normalizeCompletionContract(input.completion_contract);
|
|
659
698
|
if ('title' in input)
|
|
660
699
|
patch.title = normalizeString(input.title, 'title', { required: true, max: MAX_TITLE_LENGTH });
|
|
661
700
|
if ('description' in input)
|
|
@@ -857,6 +896,12 @@ export class CanonicalTaskService {
|
|
|
857
896
|
response.project_codes = [];
|
|
858
897
|
if (response.purpose_label === undefined)
|
|
859
898
|
response.purpose_label = null;
|
|
899
|
+
try {
|
|
900
|
+
response.completion_contract = normalizeCompletionContract(response.completion_contract);
|
|
901
|
+
}
|
|
902
|
+
catch {
|
|
903
|
+
fail('task_store_invalid', 'Stored Task completion contract is invalid', 503);
|
|
904
|
+
}
|
|
860
905
|
return response;
|
|
861
906
|
}
|
|
862
907
|
}
|
package/dist/world-extension.js
CHANGED
|
@@ -347,7 +347,7 @@ export function createWorldExtension(options = {}) {
|
|
|
347
347
|
return {
|
|
348
348
|
id: WORLD_EXTENSION_ID,
|
|
349
349
|
uiDir: fileURLToPath(new URL('../ui/world/', import.meta.url)),
|
|
350
|
-
uiFiles: ['world-view.js', 'world-view.css', 'world-vendor.js', 'world-placement.js', 'world-work-rail.js', 'world-district.js', 'world-scenery.js'],
|
|
350
|
+
uiFiles: ['world-view.js', 'world-view.css', 'world-canvas-ui.js', 'world-canvas-ui.css', 'world-canvas-notes.js', 'world-vendor.js', 'world-placement.js', 'world-work-rail.js', 'world-district.js', 'world-scenery.js'],
|
|
351
351
|
screenEntry: 'world-view.js',
|
|
352
352
|
// P17: the world sits above the home and opens first.
|
|
353
353
|
navPosition: 'first',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unson/brainbase-mcp",
|
|
3
|
-
"version": "0.23.
|
|
3
|
+
"version": "0.23.8",
|
|
4
4
|
"description": "Local-first Brainbase judgment OS that lets supported AI agents reuse a user's approved goals, priorities, decisions, and judgment criteria.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -423,5 +423,5 @@
|
|
|
423
423
|
"engines": {
|
|
424
424
|
"node": ">=20"
|
|
425
425
|
},
|
|
426
|
-
"gitHead": "
|
|
426
|
+
"gitHead": "14fca779f1164269b86adef697693647db57df9a"
|
|
427
427
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** Compact notices are projections of the same source-read states as the full rail.
|
|
2
|
+
* A task's needs_check is a record gap, never an unavailable read or failed job.
|
|
3
|
+
*/
|
|
4
|
+
import { readReasonText, shortTime } from './world-work-rail.js';
|
|
5
|
+
|
|
6
|
+
const READ_LABELS = Object.freeze({ tasks: '仕事', persons: '人物', decisions: '方針の決定', relations: '関係' });
|
|
7
|
+
const STATE_TEXT = Object.freeze({ partial: '一部だけ読めた', failed: '読込失敗', forbidden: '権限がなく読めない', not_connected: '未接続', unavailable: '読めない' });
|
|
8
|
+
|
|
9
|
+
export function workCanvasNotes(work) {
|
|
10
|
+
if (!work) return [];
|
|
11
|
+
if (work.status !== 'ok') {
|
|
12
|
+
const state = STATE_TEXT[work.status] ?? '読めない';
|
|
13
|
+
return [{ label: '区画の仕事', tone: 'warning', summary: `仕事:${state}(0件ではありません)`, text: `仕事は${state}。${readReasonText(work.reason) ?? '理由不明'}。仕事が0件という意味ではありません。` }];
|
|
14
|
+
}
|
|
15
|
+
const notes = [];
|
|
16
|
+
for (const [key, label] of Object.entries(READ_LABELS)) {
|
|
17
|
+
const read = work.reads?.[key];
|
|
18
|
+
if (!read || read.state !== 'complete') {
|
|
19
|
+
const state = STATE_TEXT[read?.state] ?? '状態不明';
|
|
20
|
+
notes.push({ label: `区画の${label}`, tone: 'warning', summary: `${label}:${state}`, text: `${label}は${state}。${readReasonText(read?.reason) ?? '理由不明'}。読めていない記録は0件とは限りません。` });
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
const summary = work.summary;
|
|
24
|
+
if (summary?.state === 'complete' || summary?.state === 'partial') {
|
|
25
|
+
const needs = summary.needs_check?.length;
|
|
26
|
+
if (needs > 0) notes.push({ label: '記録の確認', tone: 'attention', summary: `記録の要確認 ${needs}件`, text: `読めた未完了の仕事のうち${needs}件に、記録から把握できていないことがあります。仕事が止まっているという意味ではありません。詳細の絞り込みから根拠を確認できます。` });
|
|
27
|
+
}
|
|
28
|
+
const at = work.reads?.tasks?.read_at;
|
|
29
|
+
notes.push({ label: '区画の時点', tone: 'info', text: `仕事の読み込み:${shortTime(at) ?? '時点不明'}。表示は読み込んだ時点の記録です。` });
|
|
30
|
+
return notes;
|
|
31
|
+
}
|
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
/* Only the opt-in canvas presentation and overlay subtree are styled here. */
|
|
2
|
+
.bb-world.bb-world--canvas {
|
|
3
|
+
width: 100%;
|
|
4
|
+
height: 100%;
|
|
5
|
+
min-height: 0;
|
|
6
|
+
gap: 0;
|
|
7
|
+
}
|
|
8
|
+
.bb-world.bb-world--canvas > .bb-world-stage {
|
|
9
|
+
flex: 1 1 auto;
|
|
10
|
+
width: 100%;
|
|
11
|
+
height: 100%;
|
|
12
|
+
min-height: 0;
|
|
13
|
+
border: 0;
|
|
14
|
+
border-radius: 0;
|
|
15
|
+
box-shadow: none;
|
|
16
|
+
}
|
|
17
|
+
.bb-world.bb-world--canvas .bb-world-fallback {
|
|
18
|
+
position: absolute;
|
|
19
|
+
inset: 76px 24px 52px 16px;
|
|
20
|
+
overflow: auto;
|
|
21
|
+
overscroll-behavior: contain;
|
|
22
|
+
padding: 12px 16px;
|
|
23
|
+
background: rgb(255 255 255 / 88%);
|
|
24
|
+
border-radius: 8px;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.bb-world-canvas-ui {
|
|
28
|
+
--bb-world-panel-width: min(360px, calc(100% - 24px));
|
|
29
|
+
--bb-world-right-inset: 16px;
|
|
30
|
+
--bb-world-toolbar-top: 16px;
|
|
31
|
+
--bb-world-panel-top: 76px;
|
|
32
|
+
position: absolute;
|
|
33
|
+
inset: 0;
|
|
34
|
+
z-index: 6;
|
|
35
|
+
pointer-events: none;
|
|
36
|
+
color: #0d192e;
|
|
37
|
+
font-family: var(--bb-font-sans, sans-serif);
|
|
38
|
+
font-size: 12px;
|
|
39
|
+
line-height: 1.65;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.bb-world-canvas-ui *,
|
|
43
|
+
.bb-world-canvas-ui *::before,
|
|
44
|
+
.bb-world-canvas-ui *::after { box-sizing: border-box; }
|
|
45
|
+
.bb-world-canvas-ui [hidden] { display: none !important; }
|
|
46
|
+
.bb-world-canvas-ui button,
|
|
47
|
+
.bb-world-canvas-ui select { font-family: inherit; }
|
|
48
|
+
.bb-world-canvas-ui button { cursor: pointer; }
|
|
49
|
+
.bb-world-canvas-ui :focus-visible { outline: 2px solid #0d192e; outline-offset: 3px; }
|
|
50
|
+
|
|
51
|
+
.bb-world-canvas-ui .bb-world-canvas-toolbar {
|
|
52
|
+
position: absolute;
|
|
53
|
+
top: var(--bb-world-toolbar-top);
|
|
54
|
+
right: 0;
|
|
55
|
+
width: var(--bb-world-panel-width);
|
|
56
|
+
padding-right: var(--bb-world-right-inset);
|
|
57
|
+
display: grid;
|
|
58
|
+
grid-template-columns: auto minmax(0, 1fr) 40px;
|
|
59
|
+
gap: 8px;
|
|
60
|
+
align-items: center;
|
|
61
|
+
pointer-events: auto;
|
|
62
|
+
}
|
|
63
|
+
.bb-world-canvas-ui .bb-world-canvas-control {
|
|
64
|
+
min-width: 0;
|
|
65
|
+
height: 40px;
|
|
66
|
+
padding: 8px 10px;
|
|
67
|
+
border: 1px solid rgb(13 25 46 / 12%);
|
|
68
|
+
border-radius: 8px;
|
|
69
|
+
background: rgb(255 255 255 / 94%);
|
|
70
|
+
color: #0d192e;
|
|
71
|
+
font-size: 12px;
|
|
72
|
+
line-height: 20px;
|
|
73
|
+
box-shadow: 0 2px 8px #0d192e0a;
|
|
74
|
+
}
|
|
75
|
+
.bb-world-canvas-ui .bb-world-canvas-control:hover { background: #e5f8e1; }
|
|
76
|
+
.bb-world-canvas-ui .bb-world-canvas-reset { white-space: nowrap; }
|
|
77
|
+
.bb-world-canvas-ui .bb-world-canvas-city { width: 100%; text-overflow: ellipsis; }
|
|
78
|
+
.bb-world-canvas-ui .bb-world-canvas-city:disabled { cursor: default; opacity: .65; }
|
|
79
|
+
.bb-world-canvas-ui .bb-world-canvas-sky { display: grid; place-items: center; padding: 0; }
|
|
80
|
+
.bb-world-canvas-ui .bb-world-canvas-sky-icon { font-size: 22px; line-height: 1; }
|
|
81
|
+
.bb-world-canvas-ui .bb-world-canvas-sky-menu {
|
|
82
|
+
position: absolute;
|
|
83
|
+
top: calc(var(--bb-world-toolbar-top) + 48px);
|
|
84
|
+
right: var(--bb-world-right-inset);
|
|
85
|
+
min-width: 150px;
|
|
86
|
+
padding: 5px;
|
|
87
|
+
border: 1px solid rgb(13 25 46 / 18%);
|
|
88
|
+
border-radius: 9px;
|
|
89
|
+
background: #fff;
|
|
90
|
+
box-shadow: 0 8px 25px #0d192e22;
|
|
91
|
+
pointer-events: auto;
|
|
92
|
+
}
|
|
93
|
+
.bb-world-canvas-ui .bb-world-canvas-sky-option {
|
|
94
|
+
display: block;
|
|
95
|
+
width: 100%;
|
|
96
|
+
padding: 8px 10px;
|
|
97
|
+
border: 0;
|
|
98
|
+
border-radius: 5px;
|
|
99
|
+
background: transparent;
|
|
100
|
+
color: inherit;
|
|
101
|
+
font-size: 12px;
|
|
102
|
+
text-align: left;
|
|
103
|
+
}
|
|
104
|
+
.bb-world-canvas-ui .bb-world-canvas-sky-option:hover,
|
|
105
|
+
.bb-world-canvas-ui .bb-world-canvas-sky-option[aria-checked="true"] { background: #e5f8e1; }
|
|
106
|
+
|
|
107
|
+
.bb-world-canvas-ui .bb-world-canvas-quests {
|
|
108
|
+
position: absolute;
|
|
109
|
+
top: 16px;
|
|
110
|
+
left: 16px;
|
|
111
|
+
display: grid;
|
|
112
|
+
justify-items: start;
|
|
113
|
+
gap: 6px;
|
|
114
|
+
max-width: max(0px, calc(100% - 400px));
|
|
115
|
+
pointer-events: none;
|
|
116
|
+
}
|
|
117
|
+
.bb-world-canvas-ui .bb-world-canvas-quest {
|
|
118
|
+
display: flex;
|
|
119
|
+
align-items: center;
|
|
120
|
+
gap: 8px;
|
|
121
|
+
max-width: 100%;
|
|
122
|
+
min-width: 0;
|
|
123
|
+
margin: 0;
|
|
124
|
+
padding: 7px 10px 7px 8px;
|
|
125
|
+
border: 1px solid rgb(255 255 255 / 18%);
|
|
126
|
+
border-left: 3px solid #9be891;
|
|
127
|
+
border-radius: 4px;
|
|
128
|
+
background: linear-gradient(110deg, rgb(13 25 46 / 88%), rgb(13 25 46 / 72%));
|
|
129
|
+
color: #fff;
|
|
130
|
+
font-size: 12px;
|
|
131
|
+
line-height: 18px;
|
|
132
|
+
box-shadow: 0 3px 12px #0d192e18;
|
|
133
|
+
backdrop-filter: blur(5px);
|
|
134
|
+
}
|
|
135
|
+
.bb-world-canvas-ui .bb-world-canvas-quest-symbol {
|
|
136
|
+
display: grid;
|
|
137
|
+
place-items: center;
|
|
138
|
+
flex: none;
|
|
139
|
+
width: 18px;
|
|
140
|
+
height: 18px;
|
|
141
|
+
border: 1px solid #9be89170;
|
|
142
|
+
border-radius: 3px;
|
|
143
|
+
background: #9be89112;
|
|
144
|
+
color: #b5f2ab;
|
|
145
|
+
font-size: 11px;
|
|
146
|
+
font-weight: 700;
|
|
147
|
+
}
|
|
148
|
+
.bb-world-canvas-ui .bb-world-canvas-quest-text { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
|
|
149
|
+
|
|
150
|
+
.bb-world-canvas-ui .bb-world-canvas-edge {
|
|
151
|
+
position: absolute;
|
|
152
|
+
top: calc(var(--bb-world-panel-top) + 8px);
|
|
153
|
+
right: 0;
|
|
154
|
+
bottom: 24px;
|
|
155
|
+
width: 20px;
|
|
156
|
+
padding: 0;
|
|
157
|
+
border: 0;
|
|
158
|
+
background: transparent;
|
|
159
|
+
pointer-events: auto;
|
|
160
|
+
}
|
|
161
|
+
.bb-world-canvas-ui .bb-world-canvas-edge::after {
|
|
162
|
+
content: '';
|
|
163
|
+
position: absolute;
|
|
164
|
+
right: 4px;
|
|
165
|
+
top: 50%;
|
|
166
|
+
width: 3px;
|
|
167
|
+
height: 38px;
|
|
168
|
+
border-radius: 4px;
|
|
169
|
+
background: #0d192e50;
|
|
170
|
+
}
|
|
171
|
+
.bb-world-canvas-ui .bb-world-canvas-edge:focus-visible { outline-offset: -2px; background: #ffffff70; }
|
|
172
|
+
.bb-world-canvas-ui .bb-world-canvas-drawer,
|
|
173
|
+
.bb-world-canvas-ui .bb-world-canvas-help,
|
|
174
|
+
.bb-world-canvas-ui .bb-world-canvas-task {
|
|
175
|
+
position: absolute;
|
|
176
|
+
display: flex;
|
|
177
|
+
flex-direction: column;
|
|
178
|
+
min-height: 0;
|
|
179
|
+
border: 1px solid rgb(13 25 46 / 16%);
|
|
180
|
+
border-radius: 12px;
|
|
181
|
+
background: rgb(255 255 255 / 98%);
|
|
182
|
+
box-shadow: 0 8px 35px #0d192e22;
|
|
183
|
+
pointer-events: none;
|
|
184
|
+
visibility: hidden;
|
|
185
|
+
}
|
|
186
|
+
.bb-world-canvas-ui .bb-world-canvas-drawer {
|
|
187
|
+
top: var(--bb-world-panel-top);
|
|
188
|
+
right: var(--bb-world-right-inset);
|
|
189
|
+
bottom: 14px;
|
|
190
|
+
width: calc(var(--bb-world-panel-width) - var(--bb-world-right-inset));
|
|
191
|
+
overflow: hidden;
|
|
192
|
+
transform: translateX(calc(100% + 20px));
|
|
193
|
+
transition: transform .24s ease, visibility .24s;
|
|
194
|
+
}
|
|
195
|
+
.bb-world-canvas-ui .bb-world-canvas-drawer.is-open { transform: translateX(0); }
|
|
196
|
+
.bb-world-canvas-ui .bb-world-canvas-panel-top {
|
|
197
|
+
display: flex;
|
|
198
|
+
flex: none;
|
|
199
|
+
align-items: center;
|
|
200
|
+
gap: 8px;
|
|
201
|
+
padding: 8px 12px;
|
|
202
|
+
border-bottom: 1px solid rgb(13 25 46 / 12%);
|
|
203
|
+
}
|
|
204
|
+
.bb-world-canvas-ui .bb-world-canvas-panel-top h2 { margin: 0; font-size: 14px; font-weight: 600; }
|
|
205
|
+
.bb-world-canvas-ui .bb-world-canvas-close {
|
|
206
|
+
display: grid;
|
|
207
|
+
place-items: center;
|
|
208
|
+
flex: none;
|
|
209
|
+
width: 32px;
|
|
210
|
+
height: 32px;
|
|
211
|
+
margin-left: auto;
|
|
212
|
+
padding: 0;
|
|
213
|
+
border: 0;
|
|
214
|
+
border-radius: 7px;
|
|
215
|
+
background: transparent;
|
|
216
|
+
color: inherit;
|
|
217
|
+
font-size: 22px;
|
|
218
|
+
line-height: 1;
|
|
219
|
+
}
|
|
220
|
+
.bb-world-canvas-ui .bb-world-canvas-close:hover { background: #e5f8e1; }
|
|
221
|
+
.bb-world-canvas-ui .bb-world-canvas-rail-body,
|
|
222
|
+
.bb-world-canvas-ui .bb-world-canvas-task-body,
|
|
223
|
+
.bb-world-canvas-ui .bb-world-canvas-help-body {
|
|
224
|
+
min-height: 0;
|
|
225
|
+
overflow: auto;
|
|
226
|
+
overscroll-behavior: contain;
|
|
227
|
+
overflow-wrap: anywhere;
|
|
228
|
+
scrollbar-width: thin;
|
|
229
|
+
padding: 14px 18px;
|
|
230
|
+
}
|
|
231
|
+
.bb-world-canvas-ui .bb-world-canvas-rail-body h2 { font-size: 18px; }
|
|
232
|
+
.bb-world-canvas-ui .bb-world-canvas-rail-body h3 { font-size: 13px; }
|
|
233
|
+
.bb-world-canvas-ui .bb-world-canvas-rail-body .bb-ws-rail-block { padding: 14px 0; }
|
|
234
|
+
.bb-world-canvas-ui .bb-world-canvas-rail-body .bb-ws-definition,
|
|
235
|
+
.bb-world-canvas-ui .bb-world-canvas-rail-body .bb-world-rail-note,
|
|
236
|
+
.bb-world-canvas-ui .bb-world-canvas-rail-body p,
|
|
237
|
+
.bb-world-canvas-ui .bb-world-canvas-rail-body button { font-size: 12px; }
|
|
238
|
+
|
|
239
|
+
.bb-world-canvas-ui .bb-world-canvas-task { width: 330px; background: #fffdf9; border-radius: 10px; }
|
|
240
|
+
.bb-world-canvas-ui .bb-world-canvas-task::after {
|
|
241
|
+
content: '';
|
|
242
|
+
position: absolute;
|
|
243
|
+
left: var(--bb-world-task-pointer-x, 50%);
|
|
244
|
+
bottom: -7px;
|
|
245
|
+
width: 12px;
|
|
246
|
+
height: 12px;
|
|
247
|
+
background: #fffdf9;
|
|
248
|
+
border-right: 1px solid rgb(13 25 46 / 16%);
|
|
249
|
+
border-bottom: 1px solid rgb(13 25 46 / 16%);
|
|
250
|
+
transform: translateX(-50%) rotate(45deg);
|
|
251
|
+
pointer-events: none;
|
|
252
|
+
}
|
|
253
|
+
.bb-world-canvas-ui .bb-world-canvas-task.is-below::after { top: -7px; bottom: auto; transform: translateX(-50%) rotate(225deg); }
|
|
254
|
+
.bb-world-canvas-ui .bb-world-canvas-task .bb-world-canvas-panel-top { padding: 3px 8px; border: 0; }
|
|
255
|
+
.bb-world-canvas-ui .bb-world-canvas-task .bb-world-canvas-close { width: 28px; height: 28px; font-size: 20px; }
|
|
256
|
+
.bb-world-canvas-ui .bb-world-canvas-task-body { padding: 0 16px 16px; }
|
|
257
|
+
.bb-world-canvas-ui .bb-world-canvas-task-body h2 { font-size: 15px; line-height: 1.5; }
|
|
258
|
+
.bb-world-canvas-ui .bb-world-canvas-task-body h3,
|
|
259
|
+
.bb-world-canvas-ui .bb-world-canvas-task-body p,
|
|
260
|
+
.bb-world-canvas-ui .bb-world-canvas-task-body .bb-ws-definition,
|
|
261
|
+
.bb-world-canvas-ui .bb-world-canvas-task-body .bb-ws-rail-block { font-size: 12px; line-height: 1.65; }
|
|
262
|
+
.bb-world-canvas-ui .bb-world-canvas-task-body .bb-ws-rail-block { padding: 12px 0; }
|
|
263
|
+
.bb-world-canvas-ui .bb-world-canvas-task-body .bb-ws-kicker { font-size: 10px; }
|
|
264
|
+
|
|
265
|
+
.bb-world-canvas-ui .bb-world-canvas-help-button {
|
|
266
|
+
position: absolute;
|
|
267
|
+
bottom: 14px;
|
|
268
|
+
left: 14px;
|
|
269
|
+
display: grid;
|
|
270
|
+
place-items: center;
|
|
271
|
+
width: 28px;
|
|
272
|
+
height: 28px;
|
|
273
|
+
padding: 0;
|
|
274
|
+
border: 1px solid #0d192e20;
|
|
275
|
+
border-radius: 50%;
|
|
276
|
+
background: #ffffffb8;
|
|
277
|
+
color: #0d192eb3;
|
|
278
|
+
font-size: 14px;
|
|
279
|
+
pointer-events: auto;
|
|
280
|
+
}
|
|
281
|
+
.bb-world-canvas-ui .bb-world-canvas-help-button:hover { color: #0d192e; background: #fff; }
|
|
282
|
+
.bb-world-canvas-ui .bb-world-canvas-help {
|
|
283
|
+
left: 14px;
|
|
284
|
+
bottom: 54px;
|
|
285
|
+
width: min(340px, calc(100% - 28px));
|
|
286
|
+
max-height: calc(100% - 138px);
|
|
287
|
+
overflow: hidden;
|
|
288
|
+
opacity: 0;
|
|
289
|
+
transform: translateY(24px);
|
|
290
|
+
transition: transform .24s ease, opacity .24s ease, visibility .24s;
|
|
291
|
+
}
|
|
292
|
+
.bb-world-canvas-ui .bb-world-canvas-help.is-open { opacity: 1; transform: translateY(0); }
|
|
293
|
+
.bb-world-canvas-ui .bb-world-canvas-help-body,
|
|
294
|
+
.bb-world-canvas-ui .bb-world-canvas-help-body h3,
|
|
295
|
+
.bb-world-canvas-ui .bb-world-canvas-help-body p { font-size: 12px; line-height: 1.7; }
|
|
296
|
+
.bb-world-canvas-ui .bb-world-canvas-help-body h3 { margin: 14px 0 6px; }
|
|
297
|
+
.bb-world-canvas-ui .bb-world-canvas-help-body p { margin: 0 0 10px; }
|
|
298
|
+
.bb-world-canvas-ui .bb-world-canvas-note { margin-top: 14px; padding-top: 4px; border-top: 1px solid rgb(13 25 46 / 12%); }
|
|
299
|
+
.bb-world-canvas-ui .bb-world-canvas-drawer.is-open,
|
|
300
|
+
.bb-world-canvas-ui .bb-world-canvas-help.is-open,
|
|
301
|
+
.bb-world-canvas-ui .bb-world-canvas-task.is-open { visibility: visible; pointer-events: auto; }
|
|
302
|
+
|
|
303
|
+
@media (max-width: 900px) {
|
|
304
|
+
.bb-world-canvas-ui .bb-world-canvas-quests { top: 70px; left: 12px; max-width: calc(100% - 40px); }
|
|
305
|
+
}
|
|
306
|
+
@media (max-width: 460px) {
|
|
307
|
+
.bb-world-canvas-ui {
|
|
308
|
+
--bb-world-right-inset: 10px;
|
|
309
|
+
--bb-world-toolbar-top: 12px;
|
|
310
|
+
--bb-world-panel-top: 72px;
|
|
311
|
+
}
|
|
312
|
+
.bb-world-canvas-ui .bb-world-canvas-toolbar { grid-template-columns: auto minmax(0, 1fr) 34px; }
|
|
313
|
+
.bb-world-canvas-ui .bb-world-canvas-control { height: 36px; padding: 6px; font-size: 10px; }
|
|
314
|
+
.bb-world-canvas-ui .bb-world-canvas-sky { padding: 0; }
|
|
315
|
+
.bb-world-canvas-ui .bb-world-canvas-sky-icon { font-size: 20px; }
|
|
316
|
+
.bb-world-canvas-ui .bb-world-canvas-quest { font-size: 10px; gap: 6px; padding: 6px 8px; }
|
|
317
|
+
.bb-world-canvas-ui .bb-world-canvas-help-button { left: 12px; bottom: 12px; }
|
|
318
|
+
.bb-world-canvas-ui .bb-world-canvas-help { left: 12px; bottom: 52px; width: calc(100% - 24px); }
|
|
319
|
+
}
|
|
320
|
+
@media (hover: none) {
|
|
321
|
+
.bb-world-canvas-ui .bb-world-canvas-edge { width: 28px; }
|
|
322
|
+
.bb-world-canvas-ui .bb-world-canvas-edge::after { width: 4px; background: #0d192e70; }
|
|
323
|
+
.bb-world-canvas-ui .bb-world-canvas-help-button { width: 36px; height: 36px; }
|
|
324
|
+
.bb-world-canvas-ui .bb-world-canvas-close { width: 36px; height: 36px; }
|
|
325
|
+
}
|
|
326
|
+
.bb-world-canvas-ui.is-reduced-motion .bb-world-canvas-help,
|
|
327
|
+
.bb-world-canvas-ui.is-reduced-motion .bb-world-canvas-drawer { transition: none; }
|
|
328
|
+
@media (prefers-reduced-motion: reduce) {
|
|
329
|
+
.bb-world-canvas-ui .bb-world-canvas-help,
|
|
330
|
+
.bb-world-canvas-ui .bb-world-canvas-drawer { transition: none; }
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/* The same real legend nodes also serve the standard presentation. */
|
|
334
|
+
.bb-world-canvas-ui .bb-world-canvas-help-content .bb-world-legend,
|
|
335
|
+
.bb-world-canvas-ui .bb-world-canvas-help-content .bb-world-district-legend {
|
|
336
|
+
position: static;
|
|
337
|
+
inset: auto;
|
|
338
|
+
display: flex;
|
|
339
|
+
flex-wrap: wrap;
|
|
340
|
+
gap: 6px;
|
|
341
|
+
margin: 10px 0;
|
|
342
|
+
font-size: 12px;
|
|
343
|
+
}
|
|
344
|
+
.bb-world-canvas-ui .bb-world-canvas-help-content .bb-world-district-notice {
|
|
345
|
+
position: static;
|
|
346
|
+
inset: auto;
|
|
347
|
+
margin: 10px 0;
|
|
348
|
+
font-size: 12px;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/* A real record without a visible lot remains readable as detached details. */
|
|
352
|
+
.bb-world-canvas-ui .bb-world-canvas-task.is-unanchored::after { display: none; }
|