@unson/brainbase-mcp 0.41.7 → 0.41.9
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/foundation-graph-http.js +5 -1
- package/dist/graph-foundation-reader.d.ts +33 -4
- package/dist/graph-foundation-reader.js +107 -10
- package/package.json +2 -2
- package/ui/foundation-overview.css +1 -8
- package/ui/foundation-overview.js +168 -34
- package/ui/graph-own-share.js +28 -9
- package/ui/outcome-knowledge.css +18 -0
- package/ui/outcome-knowledge.js +265 -9
- package/ui/workspace-kit.css +42 -0
- package/ui/workspace-kit.js +165 -0
- package/ui/world/world-canvas-notes.js +2 -1
- package/ui/world/world-canvas-ui.css +48 -3
- package/ui/world/world-canvas-ui.js +17 -4
- package/ui/world/world-district.js +34 -5
- package/ui/world/world-view.css +6 -0
- package/ui/world/world-view.js +109 -19
- package/ui/world/world-work-rail.js +15 -2
|
@@ -253,13 +253,17 @@ function createFoundationCatalogRoute(readers, scopeId, context) {
|
|
|
253
253
|
const variables = await readers.store.list('variable', context);
|
|
254
254
|
const models = await readers.store.list('model', context);
|
|
255
255
|
const philosophies = await readers.listPhilosophies(context);
|
|
256
|
+
// Philosophies without recorded applicability are still read by the
|
|
257
|
+
// judgment frame catalog; report them separately rather than as absent.
|
|
258
|
+
const philosophiesWithoutApplicability = await readers.listUnscopedPhilosophies(context);
|
|
256
259
|
return jsonResponse(200, {
|
|
257
260
|
contractVersion: FOUNDATION_OVERVIEW_CONTRACT_VERSION,
|
|
258
261
|
scopeId,
|
|
259
262
|
objectives,
|
|
260
263
|
variables,
|
|
261
264
|
models,
|
|
262
|
-
philosophies
|
|
265
|
+
philosophies,
|
|
266
|
+
philosophies_without_applicability: philosophiesWithoutApplicability
|
|
263
267
|
});
|
|
264
268
|
}
|
|
265
269
|
};
|
|
@@ -25,7 +25,7 @@ export declare const GRAPH_FOUNDATION_LATEST_SQL = "\nSELECT\n history.entity_i
|
|
|
25
25
|
* project. The project filter is by canonical project code, which is the
|
|
26
26
|
* scope identifier selected by the organization BFF.
|
|
27
27
|
*/
|
|
28
|
-
export declare const GRAPH_FOUNDATION_LIST_SQL = "\nSELECT\n history.entity_id,\n history.entity_type,\n history.revision,\n history.payload,\n history.project_id,\n history.role_min,\n history.sensitivity,\n history.lifecycle_status,\n history.storage_digest,\n history.captured_at,\n (\n history.storage_digest = 'sha256:' ||\n encode(sha256(convert_to(history.payload::text, 'UTF8')), 'hex')\n ) AS storage_digest_valid,\n current_entity.id AS current_entity_id,\n current_entity.entity_type AS current_entity_type,\n current_entity.payload AS current_payload,\n current_entity.project_id AS current_project_id,\n current_entity.role_min AS current_role_min,\n current_entity.sensitivity AS current_sensitivity,\n current_entity.lifecycle_status AS current_lifecycle_status,\n projects.code AS current_project_code,\n true AS current_visible\nFROM public.graph_entities AS current_entity\nLEFT JOIN public.projects AS projects\n ON projects.id = current_entity.project_id\nLEFT JOIN LATERAL (\n SELECT history.*\n FROM public.graph_foundation_revisions AS history\n WHERE history.entity_id = current_entity.id\n AND history.entity_type = current_entity.entity_type\n ORDER BY history.revision::numeric DESC\n LIMIT 1\n) AS history ON true\nWHERE ($1::text IS NULL OR current_entity.entity_type = $1)\n AND ($2::text IS NULL OR projects.code = $2 OR projects.id IS NULL)\n AND current_entity.entity_type IN ('objective', 'variable', 'model', 'constraint')\nORDER BY current_entity.id, current_entity.entity_type\n";
|
|
28
|
+
export declare const GRAPH_FOUNDATION_LIST_SQL = "\nSELECT\n history.entity_id,\n history.entity_type,\n history.revision,\n history.payload,\n history.project_id,\n history.role_min,\n history.sensitivity,\n history.lifecycle_status,\n history.storage_digest,\n history.captured_at,\n (\n history.storage_digest = 'sha256:' ||\n encode(sha256(convert_to(history.payload::text, 'UTF8')), 'hex')\n ) AS storage_digest_valid,\n current_entity.id AS current_entity_id,\n current_entity.entity_type AS current_entity_type,\n current_entity.payload AS current_payload,\n current_entity.project_id AS current_project_id,\n current_entity.role_min AS current_role_min,\n current_entity.sensitivity AS current_sensitivity,\n current_entity.lifecycle_status AS current_lifecycle_status,\n projects.code AS current_project_code,\n true AS current_visible\nFROM public.graph_entities AS current_entity\nLEFT JOIN public.projects AS projects\n ON projects.id = current_entity.project_id\nLEFT JOIN LATERAL (\n SELECT history.*\n FROM public.graph_foundation_revisions AS history\n WHERE history.entity_id = current_entity.id\n AND history.entity_type = current_entity.entity_type\n ORDER BY history.revision::numeric DESC\n LIMIT 1\n) AS history ON true\nWHERE ($1::text IS NULL OR current_entity.entity_type = $1)\n AND ($2::text IS NULL OR projects.code = $2 OR projects.id IS NULL)\n AND current_entity.entity_type IN ('objective', 'variable', 'model', 'constraint')\n -- A list projects current records only. A retired row is not current, and\n -- reading it would make one replaced record fail the whole list.\n AND current_entity.lifecycle_status = 'active'\nORDER BY current_entity.id, current_entity.entity_type\n";
|
|
29
29
|
/**
|
|
30
30
|
* List the newest immutable revision for each philosophy attached to the
|
|
31
31
|
* selected project. The current Graph row is still the authorization
|
|
@@ -33,7 +33,29 @@ export declare const GRAPH_FOUNDATION_LIST_SQL = "\nSELECT\n history.entity_id,
|
|
|
33
33
|
* Unlike the Foundation list, this query requires a canonical project join so
|
|
34
34
|
* a missing project membership cannot be interpreted as a selected-scope hit.
|
|
35
35
|
*/
|
|
36
|
-
export declare const GRAPH_PHILOSOPHY_LIST_SQL = "\nSELECT\n history.entity_id,\n history.entity_type,\n history.revision,\n history.payload,\n history.project_id,\n history.role_min,\n history.sensitivity,\n history.lifecycle_status,\n history.storage_digest,\n history.captured_at,\n (\n history.storage_digest = 'sha256:' ||\n encode(sha256(convert_to(history.payload::text, 'UTF8')), 'hex')\n ) AS storage_digest_valid,\n current_entity.id AS current_entity_id,\n current_entity.entity_type AS current_entity_type,\n current_entity.payload AS current_payload,\n current_entity.project_id AS current_project_id,\n current_entity.role_min AS current_role_min,\n current_entity.sensitivity AS current_sensitivity,\n current_entity.lifecycle_status AS current_lifecycle_status,\n projects.code AS current_project_code,\n true AS current_visible\nFROM public.graph_entities AS current_entity\nJOIN public.projects AS projects\n ON projects.id = current_entity.project_id\nLEFT JOIN LATERAL (\n SELECT history.*\n FROM public.graph_foundation_revisions AS history\n WHERE history.entity_id = current_entity.id\n AND history.entity_type = current_entity.entity_type\n ORDER BY history.revision::numeric DESC\n LIMIT 1\n) AS history ON true\nWHERE current_entity.entity_type = 'philosophy'\n AND projects.code = $1\n AND current_entity.payload ? 'judgmentApplicability'\nORDER BY current_entity.id\n";
|
|
36
|
+
export declare const GRAPH_PHILOSOPHY_LIST_SQL = "\nSELECT\n history.entity_id,\n history.entity_type,\n history.revision,\n history.payload,\n history.project_id,\n history.role_min,\n history.sensitivity,\n history.lifecycle_status,\n history.storage_digest,\n history.captured_at,\n (\n history.storage_digest = 'sha256:' ||\n encode(sha256(convert_to(history.payload::text, 'UTF8')), 'hex')\n ) AS storage_digest_valid,\n current_entity.id AS current_entity_id,\n current_entity.entity_type AS current_entity_type,\n current_entity.payload AS current_payload,\n current_entity.project_id AS current_project_id,\n current_entity.role_min AS current_role_min,\n current_entity.sensitivity AS current_sensitivity,\n current_entity.lifecycle_status AS current_lifecycle_status,\n projects.code AS current_project_code,\n true AS current_visible\nFROM public.graph_entities AS current_entity\nJOIN public.projects AS projects\n ON projects.id = current_entity.project_id\nLEFT JOIN LATERAL (\n SELECT history.*\n FROM public.graph_foundation_revisions AS history\n WHERE history.entity_id = current_entity.id\n AND history.entity_type = current_entity.entity_type\n ORDER BY history.revision::numeric DESC\n LIMIT 1\n) AS history ON true\nWHERE current_entity.entity_type = 'philosophy'\n AND projects.code = $1\n AND current_entity.lifecycle_status = 'active'\n AND current_entity.payload ? 'judgmentApplicability'\nORDER BY current_entity.id\n";
|
|
37
|
+
/**
|
|
38
|
+
* Current philosophies of the selected project that predate recorded
|
|
39
|
+
* applicability. They are excluded from the verified list above, but the
|
|
40
|
+
* judgment frame catalog still reads them, so the overview must show them as
|
|
41
|
+
* "applicability unrecorded" instead of reporting that none are registered.
|
|
42
|
+
*/
|
|
43
|
+
export declare const GRAPH_UNSCOPED_PHILOSOPHY_LIST_SQL = "\nSELECT\n current_entity.id AS current_entity_id,\n current_entity.entity_type AS current_entity_type,\n current_entity.payload AS current_payload,\n current_entity.project_id AS current_project_id,\n current_entity.lifecycle_status AS current_lifecycle_status,\n current_entity.version AS current_version,\n projects.code AS current_project_code\nFROM public.graph_entities AS current_entity\nJOIN public.projects AS projects\n ON projects.id = current_entity.project_id\nWHERE current_entity.entity_type = 'philosophy'\n AND projects.code = $1\n AND current_entity.lifecycle_status = 'active'\n AND NOT (current_entity.payload ? 'judgmentApplicability')\nORDER BY current_entity.id\n";
|
|
44
|
+
/** A current philosophy whose judgment applicability has never been recorded. */
|
|
45
|
+
export interface UnscopedPhilosophyRecord {
|
|
46
|
+
readonly kind: 'philosophy';
|
|
47
|
+
readonly id: string;
|
|
48
|
+
/** Current Graph version; there is no verified foundation revision. */
|
|
49
|
+
readonly version: number;
|
|
50
|
+
readonly applicability: null;
|
|
51
|
+
readonly applicability_state: 'unrecorded';
|
|
52
|
+
readonly payload: {
|
|
53
|
+
readonly title?: string;
|
|
54
|
+
readonly statement: string;
|
|
55
|
+
readonly summary?: string;
|
|
56
|
+
readonly status?: string;
|
|
57
|
+
};
|
|
58
|
+
}
|
|
37
59
|
/** Flat row shape returned by GRAPH_FOUNDATION_READ_SQL. */
|
|
38
60
|
export interface GraphFoundationHistoryRow {
|
|
39
61
|
readonly entity_id?: unknown;
|
|
@@ -55,6 +77,7 @@ export interface GraphFoundationHistoryRow {
|
|
|
55
77
|
readonly current_role_min?: unknown;
|
|
56
78
|
readonly current_sensitivity?: unknown;
|
|
57
79
|
readonly current_lifecycle_status?: unknown;
|
|
80
|
+
readonly current_version?: unknown;
|
|
58
81
|
readonly current_visible?: unknown;
|
|
59
82
|
}
|
|
60
83
|
export interface GraphFoundationQueryResult {
|
|
@@ -78,15 +101,21 @@ export interface FoundationObjectiveDetails {
|
|
|
78
101
|
readonly evaluator_note?: unknown;
|
|
79
102
|
readonly current_state?: unknown;
|
|
80
103
|
}
|
|
81
|
-
/**
|
|
104
|
+
/** The words a World Model record gives for where it applies. */
|
|
105
|
+
export interface FoundationModelDetails {
|
|
106
|
+
readonly applicability_text?: unknown;
|
|
107
|
+
}
|
|
108
|
+
/** Runtime shape used by the overview contract for Objective and World Model records. */
|
|
82
109
|
export interface FoundationOverviewObjectiveRecord extends FoundationCatalogRecord {
|
|
83
|
-
readonly details?: FoundationObjectiveDetails;
|
|
110
|
+
readonly details?: FoundationObjectiveDetails | FoundationModelDetails;
|
|
84
111
|
}
|
|
85
112
|
export interface GraphFoundationReaders {
|
|
86
113
|
readonly store: Pick<FoundationRevisionStore, 'read' | 'readLatest' | 'list'>;
|
|
87
114
|
readonly philosophyReader: PhilosophyRevisionReader;
|
|
88
115
|
/** List latest, current-visible philosophy revisions for the selected project. */
|
|
89
116
|
readonly listPhilosophies: (context: FoundationStoreContext) => Promise<PhilosophyRevisionRecord[]>;
|
|
117
|
+
/** List current philosophies of the selected project without recorded applicability. */
|
|
118
|
+
readonly listUnscopedPhilosophies: (context: FoundationStoreContext) => Promise<UnscopedPhilosophyRecord[]>;
|
|
90
119
|
}
|
|
91
120
|
/**
|
|
92
121
|
* Create both public read ports over one trusted, transaction-bound context.
|
|
@@ -141,6 +141,9 @@ LEFT JOIN LATERAL (
|
|
|
141
141
|
WHERE ($1::text IS NULL OR current_entity.entity_type = $1)
|
|
142
142
|
AND ($2::text IS NULL OR projects.code = $2 OR projects.id IS NULL)
|
|
143
143
|
AND current_entity.entity_type IN ('objective', 'variable', 'model', 'constraint')
|
|
144
|
+
-- A list projects current records only. A retired row is not current, and
|
|
145
|
+
-- reading it would make one replaced record fail the whole list.
|
|
146
|
+
AND current_entity.lifecycle_status = 'active'
|
|
144
147
|
ORDER BY current_entity.id, current_entity.entity_type
|
|
145
148
|
`;
|
|
146
149
|
/**
|
|
@@ -188,9 +191,34 @@ LEFT JOIN LATERAL (
|
|
|
188
191
|
) AS history ON true
|
|
189
192
|
WHERE current_entity.entity_type = 'philosophy'
|
|
190
193
|
AND projects.code = $1
|
|
194
|
+
AND current_entity.lifecycle_status = 'active'
|
|
191
195
|
AND current_entity.payload ? 'judgmentApplicability'
|
|
192
196
|
ORDER BY current_entity.id
|
|
193
197
|
`;
|
|
198
|
+
/**
|
|
199
|
+
* Current philosophies of the selected project that predate recorded
|
|
200
|
+
* applicability. They are excluded from the verified list above, but the
|
|
201
|
+
* judgment frame catalog still reads them, so the overview must show them as
|
|
202
|
+
* "applicability unrecorded" instead of reporting that none are registered.
|
|
203
|
+
*/
|
|
204
|
+
export const GRAPH_UNSCOPED_PHILOSOPHY_LIST_SQL = `
|
|
205
|
+
SELECT
|
|
206
|
+
current_entity.id AS current_entity_id,
|
|
207
|
+
current_entity.entity_type AS current_entity_type,
|
|
208
|
+
current_entity.payload AS current_payload,
|
|
209
|
+
current_entity.project_id AS current_project_id,
|
|
210
|
+
current_entity.lifecycle_status AS current_lifecycle_status,
|
|
211
|
+
current_entity.version AS current_version,
|
|
212
|
+
projects.code AS current_project_code
|
|
213
|
+
FROM public.graph_entities AS current_entity
|
|
214
|
+
JOIN public.projects AS projects
|
|
215
|
+
ON projects.id = current_entity.project_id
|
|
216
|
+
WHERE current_entity.entity_type = 'philosophy'
|
|
217
|
+
AND projects.code = $1
|
|
218
|
+
AND current_entity.lifecycle_status = 'active'
|
|
219
|
+
AND NOT (current_entity.payload ? 'judgmentApplicability')
|
|
220
|
+
ORDER BY current_entity.id
|
|
221
|
+
`;
|
|
194
222
|
const FOUNDATION_TYPES = ['objective', 'variable', 'model', 'constraint'];
|
|
195
223
|
const REVISION_PATTERN = /^[1-9]\d*$/u;
|
|
196
224
|
const DIGEST_PATTERN = /^sha256:[0-9a-f]{64}$/u;
|
|
@@ -284,7 +312,75 @@ export function createGraphFoundationReaders(options) {
|
|
|
284
312
|
return createPhilosophyRevisionRecord(validated, id, revision, context.principal);
|
|
285
313
|
});
|
|
286
314
|
}
|
|
287
|
-
|
|
315
|
+
async function listUnscopedPhilosophies(suppliedContext) {
|
|
316
|
+
assertTrustedPrincipal(context, suppliedContext);
|
|
317
|
+
if (selectedProjectCode === undefined) {
|
|
318
|
+
throw scopeViolation('A selected project is required to list philosophies');
|
|
319
|
+
}
|
|
320
|
+
let result;
|
|
321
|
+
try {
|
|
322
|
+
result = await query(GRAPH_UNSCOPED_PHILOSOPHY_LIST_SQL, [selectedProjectCode]);
|
|
323
|
+
}
|
|
324
|
+
catch {
|
|
325
|
+
throw corrupt('Graph unscoped philosophy list query failed');
|
|
326
|
+
}
|
|
327
|
+
const rows = Array.isArray(result) ? result
|
|
328
|
+
: 'rows' in result && Array.isArray(result.rows) ? result.rows
|
|
329
|
+
: null;
|
|
330
|
+
if (!rows)
|
|
331
|
+
throw corrupt('Graph unscoped philosophy list query returned an invalid result');
|
|
332
|
+
const seen = new Set();
|
|
333
|
+
const records = [];
|
|
334
|
+
for (const row of rows) {
|
|
335
|
+
const id = requireString(row.current_entity_id, 'Current philosophy id');
|
|
336
|
+
if (row.current_entity_type !== 'philosophy')
|
|
337
|
+
throw corrupt('Graph philosophy list returned another entity type');
|
|
338
|
+
if (row.current_project_code !== selectedProjectCode) {
|
|
339
|
+
throw scopeViolation('The current philosophy project is outside the selected project scope');
|
|
340
|
+
}
|
|
341
|
+
if (seen.has(id))
|
|
342
|
+
throw corrupt('Philosophy list returned duplicate entities');
|
|
343
|
+
seen.add(id);
|
|
344
|
+
const version = Number(row.current_version);
|
|
345
|
+
if (!Number.isSafeInteger(version) || version < 1)
|
|
346
|
+
throw corrupt('Current philosophy version is invalid');
|
|
347
|
+
const payload = requireObject(row.current_payload, 'Current philosophy payload');
|
|
348
|
+
if (Object.hasOwn(payload, 'judgmentApplicability')) {
|
|
349
|
+
throw corrupt('Unscoped philosophy list returned a philosophy with applicability');
|
|
350
|
+
}
|
|
351
|
+
// Private philosophies always carry applicability; an owner-only ACL here
|
|
352
|
+
// is still enforced rather than silently shown.
|
|
353
|
+
assertPrivatePhilosophyRead(payload, context.principal);
|
|
354
|
+
// Mirror the judgment frame catalog: superseded or text-less records are
|
|
355
|
+
// not used for judgment, so they are not shown as usable either.
|
|
356
|
+
const status = optionalText(payload.status);
|
|
357
|
+
if (status && /^(superseded|retired|rejected)/u.test(status))
|
|
358
|
+
continue;
|
|
359
|
+
const statement = optionalText(payload.statement);
|
|
360
|
+
if (!statement)
|
|
361
|
+
continue;
|
|
362
|
+
const title = optionalText(payload.display_name) ?? optionalText(payload.title);
|
|
363
|
+
const summary = optionalText(payload.summary);
|
|
364
|
+
records.push({
|
|
365
|
+
kind: 'philosophy',
|
|
366
|
+
id,
|
|
367
|
+
version,
|
|
368
|
+
applicability: null,
|
|
369
|
+
applicability_state: 'unrecorded',
|
|
370
|
+
payload: {
|
|
371
|
+
...(title ? { title } : {}),
|
|
372
|
+
statement,
|
|
373
|
+
...(summary ? { summary } : {}),
|
|
374
|
+
...(status ? { status } : {})
|
|
375
|
+
}
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
return records;
|
|
379
|
+
}
|
|
380
|
+
return { store, philosophyReader, listPhilosophies, listUnscopedPhilosophies };
|
|
381
|
+
}
|
|
382
|
+
function optionalText(value) {
|
|
383
|
+
return typeof value === 'string' && value.trim() ? value.trim() : undefined;
|
|
288
384
|
}
|
|
289
385
|
function createPhilosophyRevisionRecord(validated, id, revision, principal) {
|
|
290
386
|
return {
|
|
@@ -525,12 +621,10 @@ function validateFoundationRecord(row, reference, context, selectedProjectCode,
|
|
|
525
621
|
definition: cloneFoundationDefinition(history.definition),
|
|
526
622
|
digest: digestFoundationDefinition(history.definition)
|
|
527
623
|
};
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
}
|
|
533
|
-
return record;
|
|
624
|
+
const details = reference.type === 'objective'
|
|
625
|
+
? projectDetails(history.payload, OBJECTIVE_DETAIL_KEYS)
|
|
626
|
+
: reference.type === 'model' ? projectDetails(history.payload, MODEL_DETAIL_KEYS) : undefined;
|
|
627
|
+
return details === undefined ? record : { ...record, details };
|
|
534
628
|
}
|
|
535
629
|
const OBJECTIVE_DETAIL_KEYS = [
|
|
536
630
|
'title',
|
|
@@ -540,15 +634,18 @@ const OBJECTIVE_DETAIL_KEYS = [
|
|
|
540
634
|
'evaluator_note',
|
|
541
635
|
'current_state'
|
|
542
636
|
];
|
|
543
|
-
|
|
637
|
+
// A model's foundation scope carries ids and a registration time; its own words for where it
|
|
638
|
+
// applies live beside the definition.
|
|
639
|
+
const MODEL_DETAIL_KEYS = ['applicability_text'];
|
|
640
|
+
function projectDetails(payload, keys) {
|
|
544
641
|
const nestedDetails = isPlainRecord(payload.details) ? payload.details : undefined;
|
|
545
642
|
const foundation = isPlainRecord(payload.foundation) ? payload.foundation : undefined;
|
|
546
643
|
// Graphify payloads historically carried these descriptive fields at the
|
|
547
644
|
// payload root. Keep the two known nested forms compatible while exposing
|
|
548
|
-
// only the
|
|
645
|
+
// only the listed fields in the overview contract.
|
|
549
646
|
const candidates = [payload, nestedDetails, foundation].filter((candidate) => candidate !== undefined);
|
|
550
647
|
const projected = {};
|
|
551
|
-
for (const key of
|
|
648
|
+
for (const key of keys) {
|
|
552
649
|
const source = candidates.find((candidate) => Object.prototype.hasOwnProperty.call(candidate, key));
|
|
553
650
|
if (source !== undefined && source[key] !== undefined)
|
|
554
651
|
projected[key] = source[key];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unson/brainbase-mcp",
|
|
3
|
-
"version": "0.41.
|
|
3
|
+
"version": "0.41.9",
|
|
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",
|
|
@@ -483,5 +483,5 @@
|
|
|
483
483
|
"engines": {
|
|
484
484
|
"node": ">=20"
|
|
485
485
|
},
|
|
486
|
-
"gitHead": "
|
|
486
|
+
"gitHead": "76bf4ebe18b116379d4687272baecdc4a74dbb35"
|
|
487
487
|
}
|
|
@@ -151,14 +151,6 @@
|
|
|
151
151
|
line-height: 1.55;
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
-
.bb-fov-record-id {
|
|
155
|
-
display: block;
|
|
156
|
-
margin-top: 7px;
|
|
157
|
-
color: var(--bb-color-quiet);
|
|
158
|
-
font-family: var(--bb-font-mono);
|
|
159
|
-
font-size: 10px;
|
|
160
|
-
overflow-wrap: anywhere;
|
|
161
|
-
}
|
|
162
154
|
|
|
163
155
|
.bb-fov-ref-list {
|
|
164
156
|
display: grid;
|
|
@@ -254,4 +246,5 @@
|
|
|
254
246
|
@media (max-width: 760px) { .bb-fov-objective-ledger { overflow-x: auto; } .bb-fov-objective-ledger .bb-ws-ledger-row { min-width: 760px; } }
|
|
255
247
|
@media (max-width: 480px) { .bb-fov-reading .bb-ws-definition { grid-template-columns: 1fr; gap: 4px; } .bb-fov-reading dd { margin-bottom: 12px; } }
|
|
256
248
|
.bb-fov-philosophy-card .bb-fov-original { border-top: 0; padding-top: 0; }
|
|
249
|
+
.bb-fov-model-card .bb-fov-original { margin-top: 12px; padding-top: 10px; overflow-wrap: anywhere; }
|
|
257
250
|
.bb-fov-objective-ledger .bb-ws-ledger-row:focus-visible { outline: 2px solid var(--bb-color-focus); outline-offset: 2px; }
|