@compilr-dev/sdk 0.18.11 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/canvas/assets.d.ts +99 -0
- package/dist/canvas/assets.js +111 -0
- package/dist/canvas/index.d.ts +2 -0
- package/dist/canvas/index.js +6 -0
- package/dist/capabilities/packs.js +6 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/platform/context.d.ts +16 -2
- package/dist/platform/context.js +13 -1
- package/dist/platform/repositories.d.ts +4 -0
- package/dist/platform/sqlite/canvas-repository.d.ts +9 -0
- package/dist/platform/sqlite/canvas-repository.js +52 -0
- package/dist/platform/sqlite/db.js +29 -0
- package/dist/platform/sqlite/schema.d.ts +1 -1
- package/dist/platform/sqlite/schema.js +1 -1
- package/dist/platform/tools/canvas-tools.d.ts +9 -1
- package/dist/platform/tools/canvas-tools.js +208 -2
- package/dist/platform/tools/image-tools.d.ts +9 -2
- package/dist/platform/tools/image-tools.js +4 -2
- package/dist/platform/tools/index.js +10 -2
- package/dist/platform/tools/project-tools.js +3 -2
- package/dist/skills/canvas-exemplars.d.ts +2 -2
- package/dist/skills/canvas-exemplars.js +4 -4
- package/dist/skills/canvas-skills.js +47 -0
- package/dist/team/index.d.ts +2 -1
- package/dist/team/index.js +1 -1
- package/dist/team/team-agent.d.ts +90 -8
- package/dist/team/team-agent.js +117 -20
- package/dist/team/team.d.ts +15 -0
- package/dist/team/team.js +45 -0
- package/dist/team/tool-config.js +3 -0
- package/dist/team/types.d.ts +1 -1
- package/package.json +1 -1
|
@@ -13,6 +13,10 @@
|
|
|
13
13
|
import { defineTool, createSuccessResult, createErrorResult } from '@compilr-dev/agents';
|
|
14
14
|
import { truncateContent } from './truncate.js';
|
|
15
15
|
import { runQualityChecks } from '../../canvas/quality-checks.js';
|
|
16
|
+
import { resolveCanvasAssets, isValidAssetRef, missingAssetRefs, assetPayloadBytes, referencedAssets, ASSET_BUDGET_BYTES, DEFAULT_ASSET_WIDTH, } from '../../canvas/assets.js';
|
|
17
|
+
import { resolveCwd } from '../context.js';
|
|
18
|
+
import * as fsNode from 'node:fs';
|
|
19
|
+
import * as pathNode from 'node:path';
|
|
16
20
|
const PAGE_SIZES = ['16:9', '4:3', '1:1', '4:5', '9:16'];
|
|
17
21
|
import { seedValues } from '../../canvas/types.js';
|
|
18
22
|
import { validateControlManifest } from '../../canvas/validate.js';
|
|
@@ -215,7 +219,7 @@ export function runCanvasChecks(html, type, manifest) {
|
|
|
215
219
|
return issues;
|
|
216
220
|
}
|
|
217
221
|
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
|
218
|
-
export function createCanvasTools(config) {
|
|
222
|
+
export function createCanvasTools(config, imageConfig) {
|
|
219
223
|
const ctx = config.context;
|
|
220
224
|
const canvases = ctx.canvases;
|
|
221
225
|
if (!canvases)
|
|
@@ -585,6 +589,22 @@ export function createCanvasTools(config) {
|
|
|
585
589
|
return createErrorResult('Provide canvas_id (a stored canvas) or html (+ type) to validate.');
|
|
586
590
|
}
|
|
587
591
|
const issues = runCanvasChecks(html, type, manifest);
|
|
592
|
+
/*
|
|
593
|
+
⚠️ The check that makes the asset indirection safe. `asset:typo` is not a real
|
|
594
|
+
scheme — the CSP drops it — so without this a mistyped reference renders a hole
|
|
595
|
+
in the canvas and reports nothing anywhere.
|
|
596
|
+
*/
|
|
597
|
+
if (input.canvas_id !== undefined && canvases.listAssets) {
|
|
598
|
+
const assets = await canvases.listAssets(input.canvas_id);
|
|
599
|
+
for (const ref of missingAssetRefs(html, assets)) {
|
|
600
|
+
issues.push({
|
|
601
|
+
level: 'error',
|
|
602
|
+
message: `The markup references asset:${ref} but no such image is stored on this ` +
|
|
603
|
+
'canvas, so it will not render. Add it with canvas_asset_add, or check the ' +
|
|
604
|
+
'handle with canvas_asset_list.',
|
|
605
|
+
});
|
|
606
|
+
}
|
|
607
|
+
}
|
|
588
608
|
if (issues.length === 0) {
|
|
589
609
|
return createSuccessResult('✓ Passed all static checks — no structural/technical issues. (Visual/aesthetic review is a separate pass.)');
|
|
590
610
|
}
|
|
@@ -636,7 +656,18 @@ export function createCanvasTools(config) {
|
|
|
636
656
|
const c = await canvases.getById(input.canvas_id);
|
|
637
657
|
if (!c)
|
|
638
658
|
return createErrorResult(`Canvas ${String(input.canvas_id)} not found.`);
|
|
639
|
-
|
|
659
|
+
/*
|
|
660
|
+
⚠️ Resolve assets HERE, not in the host renderer. This tool has the canvas id and
|
|
661
|
+
the repository; `renderToImage` receives only html, so pushing substitution into
|
|
662
|
+
the host would mean every host reimplementing it — and the screenshot the review
|
|
663
|
+
gate judges would differ from the canvas the user sees the moment one of them
|
|
664
|
+
drifted.
|
|
665
|
+
*/
|
|
666
|
+
const shotAssets = canvases.listAssets ? await canvases.listAssets(c.id) : [];
|
|
667
|
+
const img = await renderer.renderToImage({
|
|
668
|
+
content: resolveCanvasAssets(c.content, shotAssets),
|
|
669
|
+
type: c.type,
|
|
670
|
+
});
|
|
640
671
|
return {
|
|
641
672
|
success: true,
|
|
642
673
|
result: `Rendered "${c.title}" (${c.type}). Review the image below — check for overflow / cut-off content, ` +
|
|
@@ -728,6 +759,178 @@ export function createCanvasTools(config) {
|
|
|
728
759
|
return Promise.resolve(createSuccessResult(guide.prompt));
|
|
729
760
|
},
|
|
730
761
|
});
|
|
762
|
+
// ---------------------------------------------------------------------------
|
|
763
|
+
// Assets — real images, stored beside the canvas
|
|
764
|
+
// ---------------------------------------------------------------------------
|
|
765
|
+
/*
|
|
766
|
+
⚠️ THIS EXISTS BECAUSE THE AGENT COULD SEE IMAGES AND NOT USE THEM. `view_image` gives
|
|
767
|
+
vision; nothing returned bytes, so an agent asked to mock a page with the user's own
|
|
768
|
+
product photos had no path from "I can see it" to "it is in the canvas" — and said so,
|
|
769
|
+
blaming a sandbox that was not the real obstacle.
|
|
770
|
+
|
|
771
|
+
The bytes do NOT go into the markup. The canvas references `asset:<ref>` and the host
|
|
772
|
+
substitutes a data URI when it renders and when it exports; see `canvas/assets.ts` for
|
|
773
|
+
why inlining would break `canvas_edit`.
|
|
774
|
+
*/
|
|
775
|
+
const canvasAssetAddTool = defineTool({
|
|
776
|
+
name: 'canvas_asset_add',
|
|
777
|
+
description: 'Add a real image to a canvas so its markup can show it. Reads the file, resizes it ' +
|
|
778
|
+
'to display size, stores it against the canvas, and returns the reference to use: ' +
|
|
779
|
+
'write <img src="asset:REF" alt="..."> in the HTML. Use this for a user\'s own ' +
|
|
780
|
+
'photos, logos or screenshots — do NOT paste base64 into the canvas, and do not draw ' +
|
|
781
|
+
'a grey placeholder box when a real image was provided.',
|
|
782
|
+
inputSchema: {
|
|
783
|
+
type: 'object',
|
|
784
|
+
properties: {
|
|
785
|
+
canvas_id: { type: 'number', description: 'The canvas to attach the image to.' },
|
|
786
|
+
path: {
|
|
787
|
+
type: 'string',
|
|
788
|
+
description: 'Image file path (absolute, or relative to the project directory).',
|
|
789
|
+
},
|
|
790
|
+
ref: {
|
|
791
|
+
type: 'string',
|
|
792
|
+
description: 'Short handle used as asset:REF in the markup — lowercase letters, digits and ' +
|
|
793
|
+
'dashes (e.g. "hero", "product-1"). Re-using a handle replaces that image.',
|
|
794
|
+
},
|
|
795
|
+
max_width: {
|
|
796
|
+
type: 'number',
|
|
797
|
+
description: `Resize target in px (default ${String(DEFAULT_ASSET_WIDTH)}). Use the size it ` +
|
|
798
|
+
'is DISPLAYED at — a product card needs ~480, a hero ~1200. Bigger costs the ' +
|
|
799
|
+
'canvas and every export.',
|
|
800
|
+
},
|
|
801
|
+
},
|
|
802
|
+
required: ['canvas_id', 'path', 'ref'],
|
|
803
|
+
},
|
|
804
|
+
execute: async (input) => {
|
|
805
|
+
if (!canvases.addAsset || !canvases.listAssets) {
|
|
806
|
+
return createErrorResult('This host does not support canvas assets (its canvas storage predates them). ' +
|
|
807
|
+
'Draw the layout without the image and tell the user why.');
|
|
808
|
+
}
|
|
809
|
+
if (!isValidAssetRef(input.ref)) {
|
|
810
|
+
return createErrorResult(`Invalid ref "${input.ref}". Use lowercase letters, digits and dashes, e.g. "hero".`);
|
|
811
|
+
}
|
|
812
|
+
const canvas = await canvases.getById(input.canvas_id);
|
|
813
|
+
if (!canvas)
|
|
814
|
+
return createErrorResult(`Canvas ${String(input.canvas_id)} not found.`);
|
|
815
|
+
const filePath = pathNode.isAbsolute(input.path)
|
|
816
|
+
? input.path
|
|
817
|
+
: pathNode.resolve(resolveCwd(config.cwd), input.path);
|
|
818
|
+
if (!fsNode.existsSync(filePath)) {
|
|
819
|
+
return createErrorResult(`File not found: ${input.path} (looked in ${pathNode.dirname(filePath)}). ` +
|
|
820
|
+
'Pass an absolute path if the file is outside the project.');
|
|
821
|
+
}
|
|
822
|
+
const ext = pathNode.extname(filePath).toLowerCase();
|
|
823
|
+
const mediaTypes = {
|
|
824
|
+
'.png': 'image/png',
|
|
825
|
+
'.jpg': 'image/jpeg',
|
|
826
|
+
'.jpeg': 'image/jpeg',
|
|
827
|
+
'.gif': 'image/gif',
|
|
828
|
+
'.webp': 'image/webp',
|
|
829
|
+
};
|
|
830
|
+
const sourceType = mediaTypes[ext];
|
|
831
|
+
if (!sourceType) {
|
|
832
|
+
return createErrorResult(`Unsupported image type "${ext}". Supported: ${Object.keys(mediaTypes).join(', ')}.`);
|
|
833
|
+
}
|
|
834
|
+
let bytes = fsNode.readFileSync(filePath);
|
|
835
|
+
let mediaType = sourceType;
|
|
836
|
+
let width;
|
|
837
|
+
let height;
|
|
838
|
+
/*
|
|
839
|
+
⚠️ Resize where a resizer exists, and say so when it does not. A phone photo is
|
|
840
|
+
several MB; stored raw it is paid again in every export and in the model's own
|
|
841
|
+
reading of the canvas. Without a host resizer the file is stored as-is, and the
|
|
842
|
+
budget below is what stops that being silent.
|
|
843
|
+
*/
|
|
844
|
+
if (imageConfig?.resizer) {
|
|
845
|
+
try {
|
|
846
|
+
const out = await imageConfig.resizer.resize(bytes, input.max_width ?? DEFAULT_ASSET_WIDTH);
|
|
847
|
+
bytes = out.data;
|
|
848
|
+
width = out.width;
|
|
849
|
+
height = out.height;
|
|
850
|
+
mediaType = out.mediaType;
|
|
851
|
+
}
|
|
852
|
+
catch {
|
|
853
|
+
// Keep the original — a failed resize must not lose the image.
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
const data = Buffer.from(bytes).toString('base64');
|
|
857
|
+
const existing = await canvases.listAssets(input.canvas_id);
|
|
858
|
+
const others = existing.filter((a) => a.ref.toLowerCase() !== input.ref.toLowerCase());
|
|
859
|
+
const projected = others.reduce((n, a) => n + a.bytes, 0) + data.length;
|
|
860
|
+
if (projected > ASSET_BUDGET_BYTES) {
|
|
861
|
+
return createErrorResult(`That would put this canvas at ${String(Math.round(projected / 1024))}KB of images, ` +
|
|
862
|
+
`over the ${String(Math.round(ASSET_BUDGET_BYTES / 1024))}KB budget. Re-add with a ` +
|
|
863
|
+
'smaller max_width, or remove an image you are not using with canvas_asset_delete.');
|
|
864
|
+
}
|
|
865
|
+
const asset = await canvases.addAsset({
|
|
866
|
+
canvasId: input.canvas_id,
|
|
867
|
+
ref: input.ref.toLowerCase(),
|
|
868
|
+
mediaType,
|
|
869
|
+
data,
|
|
870
|
+
width,
|
|
871
|
+
height,
|
|
872
|
+
bytes: data.length,
|
|
873
|
+
sourcePath: filePath,
|
|
874
|
+
});
|
|
875
|
+
const dims = width && height ? ` ${String(width)}x${String(height)}` : '';
|
|
876
|
+
return createSuccessResult(`Stored "${asset.ref}"${dims} (${String(Math.round(asset.bytes / 1024))}KB, ` +
|
|
877
|
+
`${asset.mediaType}). Reference it in the canvas as: ` +
|
|
878
|
+
`<img src="asset:${asset.ref}" alt="describe what it shows">`);
|
|
879
|
+
},
|
|
880
|
+
});
|
|
881
|
+
const canvasAssetListTool = defineTool({
|
|
882
|
+
name: 'canvas_asset_list',
|
|
883
|
+
description: 'List the images stored on a canvas, with the reference to use for each and whether ' +
|
|
884
|
+
'the markup currently uses it.',
|
|
885
|
+
inputSchema: {
|
|
886
|
+
type: 'object',
|
|
887
|
+
properties: { canvas_id: { type: 'number', description: 'The canvas.' } },
|
|
888
|
+
required: ['canvas_id'],
|
|
889
|
+
},
|
|
890
|
+
execute: async (input) => {
|
|
891
|
+
if (!canvases.listAssets) {
|
|
892
|
+
return createErrorResult('This host does not support canvas assets.');
|
|
893
|
+
}
|
|
894
|
+
const canvas = await canvases.getById(input.canvas_id);
|
|
895
|
+
if (!canvas)
|
|
896
|
+
return createErrorResult(`Canvas ${String(input.canvas_id)} not found.`);
|
|
897
|
+
const assets = await canvases.listAssets(input.canvas_id);
|
|
898
|
+
if (assets.length === 0) {
|
|
899
|
+
return createSuccessResult('No images on this canvas. Add one with canvas_asset_add.');
|
|
900
|
+
}
|
|
901
|
+
const used = new Set(referencedAssets(canvas.content));
|
|
902
|
+
const lines = assets.map((a) => {
|
|
903
|
+
const dims = a.width && a.height ? `${String(a.width)}x${String(a.height)}` : '—';
|
|
904
|
+
const where = used.has(a.ref) ? 'used' : 'NOT referenced';
|
|
905
|
+
return ` asset:${a.ref} ${dims} ${String(Math.round(a.bytes / 1024))}KB ${where}`;
|
|
906
|
+
});
|
|
907
|
+
const total = assetPayloadBytes(canvas.content, assets);
|
|
908
|
+
return createSuccessResult(`${String(assets.length)} image(s):\n${lines.join('\n')}\n` +
|
|
909
|
+
`In use: ${String(Math.round(total / 1024))}KB of the ` +
|
|
910
|
+
`${String(Math.round(ASSET_BUDGET_BYTES / 1024))}KB budget.`);
|
|
911
|
+
},
|
|
912
|
+
});
|
|
913
|
+
const canvasAssetDeleteTool = defineTool({
|
|
914
|
+
name: 'canvas_asset_delete',
|
|
915
|
+
description: 'Remove an image from a canvas.',
|
|
916
|
+
inputSchema: {
|
|
917
|
+
type: 'object',
|
|
918
|
+
properties: {
|
|
919
|
+
canvas_id: { type: 'number', description: 'The canvas.' },
|
|
920
|
+
ref: { type: 'string', description: 'The asset reference to remove.' },
|
|
921
|
+
},
|
|
922
|
+
required: ['canvas_id', 'ref'],
|
|
923
|
+
},
|
|
924
|
+
execute: async (input) => {
|
|
925
|
+
if (!canvases.deleteAsset) {
|
|
926
|
+
return createErrorResult('This host does not support canvas assets.');
|
|
927
|
+
}
|
|
928
|
+
const gone = await canvases.deleteAsset(input.canvas_id, input.ref.toLowerCase());
|
|
929
|
+
return gone
|
|
930
|
+
? createSuccessResult(`Removed "${input.ref}".`)
|
|
931
|
+
: createErrorResult(`No asset "${input.ref}" on canvas ${String(input.canvas_id)}.`);
|
|
932
|
+
},
|
|
933
|
+
});
|
|
731
934
|
return [
|
|
732
935
|
canvasWriteTool,
|
|
733
936
|
canvasEditTool,
|
|
@@ -737,5 +940,8 @@ export function createCanvasTools(config) {
|
|
|
737
940
|
canvasValidateTool,
|
|
738
941
|
canvasScreenshotTool,
|
|
739
942
|
canvasGuideTool,
|
|
943
|
+
canvasAssetAddTool,
|
|
944
|
+
canvasAssetListTool,
|
|
945
|
+
canvasAssetDeleteTool,
|
|
740
946
|
];
|
|
741
947
|
}
|
|
@@ -25,8 +25,15 @@ export interface ImageResizer {
|
|
|
25
25
|
}>;
|
|
26
26
|
}
|
|
27
27
|
export interface ImageToolsConfig {
|
|
28
|
-
/**
|
|
29
|
-
|
|
28
|
+
/**
|
|
29
|
+
* Working directory for resolving relative paths.
|
|
30
|
+
*
|
|
31
|
+
* ⚠️ A FUNCTION, when the host's working directory can change. Platform tools are
|
|
32
|
+
* built once and memoised, so a string is captured at construction — which in Desktop
|
|
33
|
+
* meant every relative path resolved against whichever project happened to be open
|
|
34
|
+
* first, for the rest of the session. Pass a getter and it is resolved per call.
|
|
35
|
+
*/
|
|
36
|
+
cwd?: string | (() => string | undefined | null);
|
|
30
37
|
/** Optional image resizer (e.g., nativeImage in Electron) */
|
|
31
38
|
resizer?: ImageResizer;
|
|
32
39
|
/** Max dimension for resize (default: 1568) */
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
import * as fs from 'node:fs';
|
|
11
11
|
import * as path from 'node:path';
|
|
12
12
|
import { defineTool, createErrorResult } from '@compilr-dev/agents';
|
|
13
|
+
import { resolveCwd } from '../context.js';
|
|
13
14
|
/** Supported image MIME types */
|
|
14
15
|
const IMAGE_EXTENSIONS = {
|
|
15
16
|
'.png': 'image/png',
|
|
@@ -27,7 +28,6 @@ const MAX_FILE_SIZE = 10 * 1024 * 1024;
|
|
|
27
28
|
export const DEFAULT_MAX_DIMENSION = 1568;
|
|
28
29
|
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
|
29
30
|
export function createImageTools(config = {}) {
|
|
30
|
-
const cwd = config.cwd ?? process.cwd();
|
|
31
31
|
const maxDimension = config.maxDimension ?? DEFAULT_MAX_DIMENSION;
|
|
32
32
|
const viewImageTool = defineTool({
|
|
33
33
|
name: 'view_image',
|
|
@@ -45,7 +45,9 @@ export function createImageTools(config = {}) {
|
|
|
45
45
|
},
|
|
46
46
|
execute: async (input) => {
|
|
47
47
|
// Resolve path
|
|
48
|
-
const filePath = path.isAbsolute(input.path)
|
|
48
|
+
const filePath = path.isAbsolute(input.path)
|
|
49
|
+
? input.path
|
|
50
|
+
: path.resolve(resolveCwd(config.cwd), input.path);
|
|
49
51
|
// Validate file exists
|
|
50
52
|
if (!fs.existsSync(filePath)) {
|
|
51
53
|
return createErrorResult(`File not found: ${input.path}`);
|
|
@@ -29,7 +29,14 @@ export function createPlatformTools(config, options) {
|
|
|
29
29
|
// Backwards compat: options can be ImageToolsConfig (old) or PlatformToolsOptions (new)
|
|
30
30
|
let imageConfig;
|
|
31
31
|
let planCallbacks;
|
|
32
|
-
|
|
32
|
+
/*
|
|
33
|
+
⚠️ DISCRIMINATE ON EITHER KEY. This used to test only `'planModeCallbacks' in options`,
|
|
34
|
+
so a caller passing `{ imageConfig }` alone — the documented new shape, without plan
|
|
35
|
+
mode — fell through to the legacy branch and was read as an ImageToolsConfig whose only
|
|
36
|
+
property was a stray `imageConfig`. The resizer silently went missing, with no type
|
|
37
|
+
error, because every ImageToolsConfig field is optional.
|
|
38
|
+
*/
|
|
39
|
+
if (options && ('planModeCallbacks' in options || 'imageConfig' in options)) {
|
|
33
40
|
imageConfig = options.imageConfig;
|
|
34
41
|
planCallbacks = options.planModeCallbacks;
|
|
35
42
|
}
|
|
@@ -56,7 +63,8 @@ export function createPlatformTools(config, options) {
|
|
|
56
63
|
tools.push(...createEpisodeTools(config));
|
|
57
64
|
}
|
|
58
65
|
if (config.context.canvases) {
|
|
59
|
-
|
|
66
|
+
// The resizer is shared with view_image — canvas_asset_add resizes to display size.
|
|
67
|
+
tools.push(...createCanvasTools(config, imageConfig));
|
|
60
68
|
}
|
|
61
69
|
return tools;
|
|
62
70
|
}
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
* - All repo calls are properly await-ed
|
|
12
12
|
*/
|
|
13
13
|
import { defineTool, createSuccessResult, createErrorResult } from '@compilr-dev/agents';
|
|
14
|
+
import { resolveCwd } from '../context.js';
|
|
14
15
|
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
|
15
16
|
export function createProjectTools(config) {
|
|
16
17
|
const { context: ctx, hooks } = config;
|
|
@@ -55,7 +56,7 @@ export function createProjectTools(config) {
|
|
|
55
56
|
project = await ctx.projects.findByPath(input.path);
|
|
56
57
|
}
|
|
57
58
|
else {
|
|
58
|
-
const cwd = config.cwd
|
|
59
|
+
const cwd = resolveCwd(config.cwd);
|
|
59
60
|
project = await ctx.projects.findByPath(cwd);
|
|
60
61
|
}
|
|
61
62
|
if (!project) {
|
|
@@ -166,7 +167,7 @@ export function createProjectTools(config) {
|
|
|
166
167
|
return createErrorResult(`Project with name "${input.name}" already exists`);
|
|
167
168
|
}
|
|
168
169
|
// Check if a project exists at this path
|
|
169
|
-
const projectPath = input.path ?? config.cwd
|
|
170
|
+
const projectPath = input.path ?? resolveCwd(config.cwd);
|
|
170
171
|
const existingByPath = await ctx.projects.findByPath(projectPath);
|
|
171
172
|
if (existingByPath) {
|
|
172
173
|
return createErrorResult(`A project already exists at path "${projectPath}": ${existingByPath.name}`);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/** The light theme-flat exemplar, ready to adapt. */
|
|
2
|
-
export declare const THEME_FLAT_EXEMPLAR = "<div style=\"--canvas-bg: #E9EAEE; --canvas-fg: #1B1C1F; --canvas-muted: #6B6D75; --canvas-accent: #C2410C; --canvas-card: #FFFFFF; --canvas-border: #D5D7DE; --canvas-surface-1: #FFFFFF; --canvas-surface-2: #F2F3F6; --canvas-hairline: #D5D7DE; width: 1000px; background: var(--canvas-bg); font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif; color: var(--canvas-fg); padding: 40px;\">\n\n <div style=\"display: flex; align-items: baseline; justify-content: space-between; gap: 24px; margin-bottom: 24px;\">\n <div style=\"font-size: 11px; letter-spacing: 0.14em; font-weight: 600; color: var(--canvas-muted);\">Q3 DELIVERY REVIEW · PLATFORM</div>\n <div style=\"font-size: 11px; letter-spacing: 0.08em; color: var(--canvas-muted);\">as of 6 Sep 2026</div>\n </div>\n\n <div style=\"display: grid; grid-template-columns: 1.35fr 1fr; gap: 16px; margin-bottom: 16px;\">\n <div style=\"background: var(--canvas-surface-1, var(--canvas-card)); border: 1px solid var(--canvas-hairline, var(--canvas-border)); padding: 30px 32px;\">\n <div style=\"font-size: 11px; letter-spacing: 0.12em; font-weight: 600; color: var(--canvas-accent); margin-bottom: 16px;\">THE QUARTER IN ONE NUMBER</div>\n <div style=\"font-size: 84px; line-height: 0.94; font-weight: 700; letter-spacing: -0.035em; font-variant-numeric: tabular-nums; margin-bottom: 12px;\">41<span style=\"font-size: 40px; font-weight: 600; color: var(--canvas-muted);\"> of 47</span></div>\n <div style=\"font-size: 20px; line-height: 1.35; font-weight: 600; letter-spacing: -0.01em; margin-bottom: 14px; max-width: 22em;\">commitments shipped, and the six that slipped share one cause.</div>\n <p style=\"font-size: 14px; line-height: 1.65; color: color-mix(in oklab, var(--canvas-fg) 78%, var(--canvas-bg)); margin: 0;\">Every delayed item was blocked on the migration, not on capacity. Team throughput rose 12% over Q2 while the queue behind a single dependency grew, which is why headcount is the wrong lever here.</p>\n </div>\n\n <div style=\"display: grid; grid-template-rows: repeat(3, 1fr); gap: 16px;\">\n <div style=\"background: var(--canvas-surface-1, var(--canvas-card)); border: 1px solid var(--canvas-hairline, var(--canvas-border)); padding: 18px 20px; display: flex; align-items: baseline; justify-content: space-between; gap: 16px;\">\n <div>\n <div style=\"font-size: 10px; letter-spacing: 0.12em; font-weight: 600; color: var(--canvas-muted); margin-bottom: 6px;\">CYCLE TIME</div>\n <div style=\"font-size: 34px; line-height: 1; font-weight: 700; letter-spacing: -0.02em; font-variant-numeric: tabular-nums;\">6.2<span style=\"font-size: 15px; font-weight: 500; color: var(--canvas-muted);\"> days</span></div>\n </div>\n <div style=\"font-size: 13px; font-weight: 600; color: var(--canvas-accent); flex: none;\">▼ 1.8</div>\n </div>\n <div style=\"background: var(--canvas-surface-1, var(--canvas-card)); border: 1px solid var(--canvas-hairline, var(--canvas-border)); padding: 18px 20px; display: flex; align-items: baseline; justify-content: space-between; gap: 16px;\">\n <div>\n <div style=\"font-size: 10px; letter-spacing: 0.12em; font-weight: 600; color: var(--canvas-muted); margin-bottom: 6px;\">ESCAPED DEFECTS</div>\n <div style=\"font-size: 34px; line-height: 1; font-weight: 700; letter-spacing: -0.02em; font-variant-numeric: tabular-nums;\">3</div>\n </div>\n <div style=\"font-size: 13px; font-weight: 600; color: var(--canvas-muted); flex: none;\">▼ 5</div>\n </div>\n <div style=\"background: var(--canvas-surface-1, var(--canvas-card)); border: 1px solid var(--canvas-hairline, var(--canvas-border)); padding: 18px 20px; display: flex; align-items: baseline; justify-content: space-between; gap: 16px;\">\n <div>\n <div style=\"font-size: 10px; letter-spacing: 0.12em; font-weight: 600; color: var(--canvas-muted); margin-bottom: 6px;\">BLOCKED, NOW</div>\n <div style=\"font-size: 34px; line-height: 1; font-weight: 700; letter-spacing: -0.02em; font-variant-numeric: tabular-nums;\">6</div>\n </div>\n <div style=\"font-size: 13px; font-weight: 600; color: var(--canvas-muted); flex: none;\">▲ 4</div>\n </div>\n </div>\n </div>\n\n <div style=\"display: grid; grid-template-columns: 1fr 1fr; gap: 16px;\">\n\n <div style=\"background: var(--canvas-surface-1, var(--canvas-card)); border: 1px solid var(--canvas-hairline, var(--canvas-border)); padding: 22px 24px 20px;\">\n <div style=\"font-size: 10px; letter-spacing: 0.12em; font-weight: 600; color: var(--canvas-muted); margin-bottom: 18px;\">SHIPPED PER SPRINT</div>\n <svg width=\"100%\" height=\"150\" viewBox=\"0 0 420 150\" style=\"display: block; overflow: visible;\">\n <line x1=\"0\" y1=\"126\" x2=\"420\" y2=\"126\" style=\"stroke: var(--canvas-hairline, var(--canvas-border));\" stroke-width=\"1\"></line>\n <rect x=\"10\" y=\"72\" width=\"46\" height=\"54\" style=\"fill: color-mix(in oklab, var(--canvas-fg) 22%, var(--canvas-bg));\"></rect>\n <text x=\"33\" y=\"62\" text-anchor=\"middle\" font-size=\"13\" font-weight=\"700\" style=\"fill: var(--canvas-fg); font-family: system-ui, sans-serif;\">6</text>\n <text x=\"33\" y=\"142\" text-anchor=\"middle\" font-size=\"11\" style=\"fill: var(--canvas-muted); font-family: system-ui, sans-serif;\">S1</text>\n <rect x=\"76\" y=\"45\" width=\"46\" height=\"81\" style=\"fill: color-mix(in oklab, var(--canvas-fg) 22%, var(--canvas-bg));\"></rect>\n <text x=\"99\" y=\"35\" text-anchor=\"middle\" font-size=\"13\" font-weight=\"700\" style=\"fill: var(--canvas-fg); font-family: system-ui, sans-serif;\">9</text>\n <text x=\"99\" y=\"142\" text-anchor=\"middle\" font-size=\"11\" style=\"fill: var(--canvas-muted); font-family: system-ui, sans-serif;\">S2</text>\n <rect x=\"142\" y=\"54\" width=\"46\" height=\"72\" style=\"fill: color-mix(in oklab, var(--canvas-fg) 22%, var(--canvas-bg));\"></rect>\n <text x=\"165\" y=\"44\" text-anchor=\"middle\" font-size=\"13\" font-weight=\"700\" style=\"fill: var(--canvas-fg); font-family: system-ui, sans-serif;\">8</text>\n <text x=\"165\" y=\"142\" text-anchor=\"middle\" font-size=\"11\" style=\"fill: var(--canvas-muted); font-family: system-ui, sans-serif;\">S3</text>\n <rect x=\"208\" y=\"27\" width=\"46\" height=\"99\" style=\"fill: color-mix(in oklab, var(--canvas-fg) 22%, var(--canvas-bg));\"></rect>\n <text x=\"231\" y=\"17\" text-anchor=\"middle\" font-size=\"13\" font-weight=\"700\" style=\"fill: var(--canvas-fg); font-family: system-ui, sans-serif;\">11</text>\n <text x=\"231\" y=\"142\" text-anchor=\"middle\" font-size=\"11\" style=\"fill: var(--canvas-muted); font-family: system-ui, sans-serif;\">S4</text>\n <rect x=\"274\" y=\"99\" width=\"46\" height=\"27\" style=\"fill: var(--canvas-accent);\"></rect>\n <text x=\"297\" y=\"89\" text-anchor=\"middle\" font-size=\"13\" font-weight=\"700\" style=\"fill: var(--canvas-accent); font-family: system-ui, sans-serif;\">3</text>\n <text x=\"297\" y=\"142\" text-anchor=\"middle\" font-size=\"11\" style=\"fill: var(--canvas-muted); font-family: system-ui, sans-serif;\">S5</text>\n <rect x=\"340\" y=\"90\" width=\"46\" height=\"36\" style=\"fill: color-mix(in oklab, var(--canvas-fg) 22%, var(--canvas-bg));\"></rect>\n <text x=\"363\" y=\"80\" text-anchor=\"middle\" font-size=\"13\" font-weight=\"700\" style=\"fill: var(--canvas-fg); font-family: system-ui, sans-serif;\">4</text>\n <text x=\"363\" y=\"142\" text-anchor=\"middle\" font-size=\"11\" style=\"fill: var(--canvas-muted); font-family: system-ui, sans-serif;\">S6</text>\n </svg>\n <div style=\"font-size: 13px; line-height: 1.55; color: color-mix(in oklab, var(--canvas-fg) 78%, var(--canvas-bg)); margin-top: 20px; border-top: 1px solid var(--canvas-hairline, var(--canvas-border)); padding-top: 12px;\">Sprint 5 is when the migration landed in the critical path.</div>\n </div>\n\n <div style=\"background: var(--canvas-surface-1, var(--canvas-card)); border: 1px solid var(--canvas-hairline, var(--canvas-border)); padding: 22px 24px 20px;\">\n <div style=\"font-size: 10px; letter-spacing: 0.12em; font-weight: 600; color: var(--canvas-muted); margin-bottom: 14px;\">THE SIX THAT SLIPPED</div>\n <div style=\"background: var(--canvas-surface-2, var(--canvas-bg)); border: 1px solid var(--canvas-hairline, var(--canvas-border));\">\n <div style=\"display: grid; grid-template-columns: 1fr 88px 74px; gap: 12px; padding: 8px 14px; border-bottom: 1px solid var(--canvas-hairline, var(--canvas-border)); font-size: 10px; letter-spacing: 0.1em; font-weight: 600; color: var(--canvas-muted);\"><span>COMMITMENT</span><span>BLOCKED BY</span><span style=\"text-align: right;\">DAYS</span></div>\n <div style=\"display: grid; grid-template-columns: 1fr 88px 74px; gap: 12px; padding: 10px 14px; border-bottom: 1px solid var(--canvas-hairline, var(--canvas-border)); font-size: 13px; align-items: baseline;\"><span style=\"font-weight: 600;\">Billing export</span><span style=\"color: color-mix(in oklab, var(--canvas-fg) 78%, var(--canvas-bg));\">migration</span><span style=\"text-align: right; font-variant-numeric: tabular-nums;\">21</span></div>\n <div style=\"display: grid; grid-template-columns: 1fr 88px 74px; gap: 12px; padding: 10px 14px; border-bottom: 1px solid var(--canvas-hairline, var(--canvas-border)); font-size: 13px; align-items: baseline;\"><span style=\"font-weight: 600;\">Audit trail</span><span style=\"color: color-mix(in oklab, var(--canvas-fg) 78%, var(--canvas-bg));\">migration</span><span style=\"text-align: right; font-variant-numeric: tabular-nums;\">18</span></div>\n <div style=\"display: grid; grid-template-columns: 1fr 88px 74px; gap: 12px; padding: 10px 14px; border-bottom: 1px solid var(--canvas-hairline, var(--canvas-border)); font-size: 13px; align-items: baseline;\"><span style=\"font-weight: 600;\">SSO for teams</span><span style=\"color: color-mix(in oklab, var(--canvas-fg) 78%, var(--canvas-bg));\">migration</span><span style=\"text-align: right; font-variant-numeric: tabular-nums;\">14</span></div>\n <div style=\"display: grid; grid-template-columns: 1fr 88px 74px; gap: 12px; padding: 10px 14px; border-bottom: 1px solid var(--canvas-hairline, var(--canvas-border)); font-size: 13px; align-items: baseline;\"><span style=\"font-weight: 600;\">Usage alerts</span><span style=\"color: color-mix(in oklab, var(--canvas-fg) 78%, var(--canvas-bg));\">migration</span><span style=\"text-align: right; font-variant-numeric: tabular-nums;\">11</span></div>\n <div style=\"display: grid; grid-template-columns: 1fr 88px 74px; gap: 12px; padding: 10px 14px; border-bottom: 1px solid var(--canvas-hairline, var(--canvas-border)); font-size: 13px; align-items: baseline;\"><span style=\"font-weight: 600;\">Retention job</span><span style=\"color: color-mix(in oklab, var(--canvas-fg) 78%, var(--canvas-bg));\">migration</span><span style=\"text-align: right; font-variant-numeric: tabular-nums;\">9</span></div>\n <div style=\"display: grid; grid-template-columns: 1fr 88px 74px; gap: 12px; padding: 10px 14px; font-size: 13px; align-items: baseline;\"><span style=\"font-weight: 600;\">Region failover</span><span style=\"color: color-mix(in oklab, var(--canvas-fg) 78%, var(--canvas-bg));\">migration</span><span style=\"text-align: right; font-variant-numeric: tabular-nums;\">6</span></div>\n </div>\n <div style=\"font-size: 13px; line-height: 1.55; color: color-mix(in oklab, var(--canvas-fg) 78%, var(--canvas-bg)); margin-top: 16px;\">One dependency, 79 days of accumulated delay.</div>\n </div>\n </div>\n\n <div style=\"border-top: 1px solid var(--canvas-hairline, var(--canvas-border)); margin-top: 26px; padding-top: 14px; display: flex; align-items: baseline; justify-content: space-between; gap: 24px; font-size: 11px; letter-spacing: 0.06em; color: var(--canvas-muted);\">\n <span>PLATFORM · QUARTERLY REVIEW</span>\n <span>Source: delivery board, sprints 1–6</span>\n </div>\n </div>";
|
|
2
|
+
export declare const THEME_FLAT_EXEMPLAR = "<div style=\"--canvas-bg: #E9EAEE; --canvas-fg: #1B1C1F; --canvas-muted: #63656D; --canvas-accent: #C2410C; --canvas-card: #FFFFFF; --canvas-border: #D5D7DE; --canvas-surface-1: #FFFFFF; --canvas-surface-2: #F2F3F6; --canvas-hairline: #D5D7DE; width: 1000px; background: var(--canvas-bg); font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif; color: var(--canvas-fg); padding: 40px;\">\n\n <div style=\"display: flex; align-items: baseline; justify-content: space-between; gap: 24px; margin-bottom: 24px;\">\n <div style=\"font-size: 11px; letter-spacing: 0.14em; font-weight: 600; color: var(--canvas-muted);\">Q3 DELIVERY REVIEW · PLATFORM</div>\n <div style=\"font-size: 11px; letter-spacing: 0.08em; color: var(--canvas-muted);\">as of 6 Sep 2026</div>\n </div>\n\n <div style=\"display: grid; grid-template-columns: 1.35fr 1fr; gap: 16px; margin-bottom: 16px;\">\n <div style=\"background: var(--canvas-surface-1, var(--canvas-card)); border: 1px solid var(--canvas-hairline, var(--canvas-border)); padding: 30px 32px;\">\n <div style=\"font-size: 11px; letter-spacing: 0.12em; font-weight: 600; color: var(--canvas-accent); margin-bottom: 16px;\">THE QUARTER IN ONE NUMBER</div>\n <div style=\"font-size: 84px; line-height: 0.94; font-weight: 700; letter-spacing: -0.035em; font-variant-numeric: tabular-nums; margin-bottom: 12px;\">41<span style=\"font-size: 40px; font-weight: 600; color: var(--canvas-muted);\"> of 47</span></div>\n <div style=\"font-size: 20px; line-height: 1.35; font-weight: 600; letter-spacing: -0.01em; margin-bottom: 14px; max-width: 22em;\">commitments shipped, and the six that slipped share one cause.</div>\n <p style=\"font-size: 14px; line-height: 1.65; color: color-mix(in oklab, var(--canvas-fg) 78%, var(--canvas-bg)); margin: 0;\">Every delayed item was blocked on the migration, not on capacity. Team throughput rose 12% over Q2 while the queue behind a single dependency grew, which is why headcount is the wrong lever here.</p>\n </div>\n\n <div style=\"display: grid; grid-template-rows: repeat(3, 1fr); gap: 16px;\">\n <div style=\"background: var(--canvas-surface-1, var(--canvas-card)); border: 1px solid var(--canvas-hairline, var(--canvas-border)); padding: 18px 20px; display: flex; align-items: baseline; justify-content: space-between; gap: 16px;\">\n <div>\n <div style=\"font-size: 10px; letter-spacing: 0.12em; font-weight: 600; color: var(--canvas-muted); margin-bottom: 6px;\">CYCLE TIME</div>\n <div style=\"font-size: 34px; line-height: 1; font-weight: 700; letter-spacing: -0.02em; font-variant-numeric: tabular-nums;\">6.2<span style=\"font-size: 15px; font-weight: 500; color: var(--canvas-muted);\"> days</span></div>\n </div>\n <div style=\"font-size: 13px; font-weight: 600; color: var(--canvas-accent); flex: none;\">▼ 1.8</div>\n </div>\n <div style=\"background: var(--canvas-surface-1, var(--canvas-card)); border: 1px solid var(--canvas-hairline, var(--canvas-border)); padding: 18px 20px; display: flex; align-items: baseline; justify-content: space-between; gap: 16px;\">\n <div>\n <div style=\"font-size: 10px; letter-spacing: 0.12em; font-weight: 600; color: var(--canvas-muted); margin-bottom: 6px;\">ESCAPED DEFECTS</div>\n <div style=\"font-size: 34px; line-height: 1; font-weight: 700; letter-spacing: -0.02em; font-variant-numeric: tabular-nums;\">3</div>\n </div>\n <div style=\"font-size: 13px; font-weight: 600; color: var(--canvas-muted); flex: none;\">▼ 5</div>\n </div>\n <div style=\"background: var(--canvas-surface-1, var(--canvas-card)); border: 1px solid var(--canvas-hairline, var(--canvas-border)); padding: 18px 20px; display: flex; align-items: baseline; justify-content: space-between; gap: 16px;\">\n <div>\n <div style=\"font-size: 10px; letter-spacing: 0.12em; font-weight: 600; color: var(--canvas-muted); margin-bottom: 6px;\">BLOCKED, NOW</div>\n <div style=\"font-size: 34px; line-height: 1; font-weight: 700; letter-spacing: -0.02em; font-variant-numeric: tabular-nums;\">6</div>\n </div>\n <div style=\"font-size: 13px; font-weight: 600; color: var(--canvas-muted); flex: none;\">▲ 4</div>\n </div>\n </div>\n </div>\n\n <div style=\"display: grid; grid-template-columns: 1fr 1fr; gap: 16px;\">\n\n <div style=\"background: var(--canvas-surface-1, var(--canvas-card)); border: 1px solid var(--canvas-hairline, var(--canvas-border)); padding: 22px 24px 20px;\">\n <div style=\"font-size: 10px; letter-spacing: 0.12em; font-weight: 600; color: var(--canvas-muted); margin-bottom: 18px;\">SHIPPED PER SPRINT</div>\n <svg width=\"100%\" height=\"150\" viewBox=\"0 0 420 150\" style=\"display: block; overflow: visible;\">\n <line x1=\"0\" y1=\"126\" x2=\"420\" y2=\"126\" style=\"stroke: var(--canvas-hairline, var(--canvas-border));\" stroke-width=\"1\"></line>\n <rect x=\"10\" y=\"72\" width=\"46\" height=\"54\" style=\"fill: color-mix(in oklab, var(--canvas-fg) 22%, var(--canvas-bg));\"></rect>\n <text x=\"33\" y=\"62\" text-anchor=\"middle\" font-size=\"13\" font-weight=\"700\" style=\"fill: var(--canvas-fg); font-family: system-ui, sans-serif;\">6</text>\n <text x=\"33\" y=\"142\" text-anchor=\"middle\" font-size=\"11\" style=\"fill: var(--canvas-muted); font-family: system-ui, sans-serif;\">S1</text>\n <rect x=\"76\" y=\"45\" width=\"46\" height=\"81\" style=\"fill: color-mix(in oklab, var(--canvas-fg) 22%, var(--canvas-bg));\"></rect>\n <text x=\"99\" y=\"35\" text-anchor=\"middle\" font-size=\"13\" font-weight=\"700\" style=\"fill: var(--canvas-fg); font-family: system-ui, sans-serif;\">9</text>\n <text x=\"99\" y=\"142\" text-anchor=\"middle\" font-size=\"11\" style=\"fill: var(--canvas-muted); font-family: system-ui, sans-serif;\">S2</text>\n <rect x=\"142\" y=\"54\" width=\"46\" height=\"72\" style=\"fill: color-mix(in oklab, var(--canvas-fg) 22%, var(--canvas-bg));\"></rect>\n <text x=\"165\" y=\"44\" text-anchor=\"middle\" font-size=\"13\" font-weight=\"700\" style=\"fill: var(--canvas-fg); font-family: system-ui, sans-serif;\">8</text>\n <text x=\"165\" y=\"142\" text-anchor=\"middle\" font-size=\"11\" style=\"fill: var(--canvas-muted); font-family: system-ui, sans-serif;\">S3</text>\n <rect x=\"208\" y=\"27\" width=\"46\" height=\"99\" style=\"fill: color-mix(in oklab, var(--canvas-fg) 22%, var(--canvas-bg));\"></rect>\n <text x=\"231\" y=\"17\" text-anchor=\"middle\" font-size=\"13\" font-weight=\"700\" style=\"fill: var(--canvas-fg); font-family: system-ui, sans-serif;\">11</text>\n <text x=\"231\" y=\"142\" text-anchor=\"middle\" font-size=\"11\" style=\"fill: var(--canvas-muted); font-family: system-ui, sans-serif;\">S4</text>\n <rect x=\"274\" y=\"99\" width=\"46\" height=\"27\" style=\"fill: var(--canvas-accent);\"></rect>\n <text x=\"297\" y=\"89\" text-anchor=\"middle\" font-size=\"13\" font-weight=\"700\" style=\"fill: var(--canvas-accent); font-family: system-ui, sans-serif;\">3</text>\n <text x=\"297\" y=\"142\" text-anchor=\"middle\" font-size=\"11\" style=\"fill: var(--canvas-muted); font-family: system-ui, sans-serif;\">S5</text>\n <rect x=\"340\" y=\"90\" width=\"46\" height=\"36\" style=\"fill: color-mix(in oklab, var(--canvas-fg) 22%, var(--canvas-bg));\"></rect>\n <text x=\"363\" y=\"80\" text-anchor=\"middle\" font-size=\"13\" font-weight=\"700\" style=\"fill: var(--canvas-fg); font-family: system-ui, sans-serif;\">4</text>\n <text x=\"363\" y=\"142\" text-anchor=\"middle\" font-size=\"11\" style=\"fill: var(--canvas-muted); font-family: system-ui, sans-serif;\">S6</text>\n </svg>\n <div style=\"font-size: 13px; line-height: 1.55; color: color-mix(in oklab, var(--canvas-fg) 78%, var(--canvas-bg)); margin-top: 20px; border-top: 1px solid var(--canvas-hairline, var(--canvas-border)); padding-top: 12px;\">Sprint 5 is when the migration landed in the critical path.</div>\n </div>\n\n <div style=\"background: var(--canvas-surface-1, var(--canvas-card)); border: 1px solid var(--canvas-hairline, var(--canvas-border)); padding: 22px 24px 20px;\">\n <div style=\"font-size: 10px; letter-spacing: 0.12em; font-weight: 600; color: var(--canvas-muted); margin-bottom: 14px;\">THE SIX THAT SLIPPED</div>\n <div style=\"background: var(--canvas-surface-2, var(--canvas-bg)); border: 1px solid var(--canvas-hairline, var(--canvas-border));\">\n <div style=\"display: grid; grid-template-columns: 1fr 88px 74px; gap: 12px; padding: 8px 14px; border-bottom: 1px solid var(--canvas-hairline, var(--canvas-border)); font-size: 10px; letter-spacing: 0.1em; font-weight: 600; color: var(--canvas-muted);\"><span>COMMITMENT</span><span>BLOCKED BY</span><span style=\"text-align: right;\">DAYS</span></div>\n <div style=\"display: grid; grid-template-columns: 1fr 88px 74px; gap: 12px; padding: 10px 14px; border-bottom: 1px solid var(--canvas-hairline, var(--canvas-border)); font-size: 13px; align-items: baseline;\"><span style=\"font-weight: 600;\">Billing export</span><span style=\"color: color-mix(in oklab, var(--canvas-fg) 78%, var(--canvas-bg));\">migration</span><span style=\"text-align: right; font-variant-numeric: tabular-nums;\">21</span></div>\n <div style=\"display: grid; grid-template-columns: 1fr 88px 74px; gap: 12px; padding: 10px 14px; border-bottom: 1px solid var(--canvas-hairline, var(--canvas-border)); font-size: 13px; align-items: baseline;\"><span style=\"font-weight: 600;\">Audit trail</span><span style=\"color: color-mix(in oklab, var(--canvas-fg) 78%, var(--canvas-bg));\">migration</span><span style=\"text-align: right; font-variant-numeric: tabular-nums;\">18</span></div>\n <div style=\"display: grid; grid-template-columns: 1fr 88px 74px; gap: 12px; padding: 10px 14px; border-bottom: 1px solid var(--canvas-hairline, var(--canvas-border)); font-size: 13px; align-items: baseline;\"><span style=\"font-weight: 600;\">SSO for teams</span><span style=\"color: color-mix(in oklab, var(--canvas-fg) 78%, var(--canvas-bg));\">migration</span><span style=\"text-align: right; font-variant-numeric: tabular-nums;\">14</span></div>\n <div style=\"display: grid; grid-template-columns: 1fr 88px 74px; gap: 12px; padding: 10px 14px; border-bottom: 1px solid var(--canvas-hairline, var(--canvas-border)); font-size: 13px; align-items: baseline;\"><span style=\"font-weight: 600;\">Usage alerts</span><span style=\"color: color-mix(in oklab, var(--canvas-fg) 78%, var(--canvas-bg));\">migration</span><span style=\"text-align: right; font-variant-numeric: tabular-nums;\">11</span></div>\n <div style=\"display: grid; grid-template-columns: 1fr 88px 74px; gap: 12px; padding: 10px 14px; border-bottom: 1px solid var(--canvas-hairline, var(--canvas-border)); font-size: 13px; align-items: baseline;\"><span style=\"font-weight: 600;\">Retention job</span><span style=\"color: color-mix(in oklab, var(--canvas-fg) 78%, var(--canvas-bg));\">migration</span><span style=\"text-align: right; font-variant-numeric: tabular-nums;\">9</span></div>\n <div style=\"display: grid; grid-template-columns: 1fr 88px 74px; gap: 12px; padding: 10px 14px; font-size: 13px; align-items: baseline;\"><span style=\"font-weight: 600;\">Region failover</span><span style=\"color: color-mix(in oklab, var(--canvas-fg) 78%, var(--canvas-bg));\">migration</span><span style=\"text-align: right; font-variant-numeric: tabular-nums;\">6</span></div>\n </div>\n <div style=\"font-size: 13px; line-height: 1.55; color: color-mix(in oklab, var(--canvas-fg) 78%, var(--canvas-bg)); margin-top: 16px;\">One dependency, 79 days of accumulated delay.</div>\n </div>\n </div>\n\n <div style=\"border-top: 1px solid var(--canvas-hairline, var(--canvas-border)); margin-top: 26px; padding-top: 14px; display: flex; align-items: baseline; justify-content: space-between; gap: 24px; font-size: 11px; letter-spacing: 0.06em; color: var(--canvas-muted);\">\n <span>PLATFORM · QUARTERLY REVIEW</span>\n <span>Source: delivery board, sprints 1–6</span>\n </div>\n </div>";
|
|
3
3
|
/** The same markup in dark: only these nine values change. */
|
|
4
4
|
export declare const THEME_FLAT_DARK_TOKENS = "--canvas-bg: #17181C; --canvas-fg: #ECEDF1; --canvas-muted: #9A9CA6; --canvas-accent: #FB7B4B; --canvas-card: #22242A; --canvas-border: #31333B; --canvas-surface-1: #22242A; --canvas-surface-2: #1B1D22; --canvas-hairline: #31333B";
|
|
5
5
|
/** The app-screen exemplar — a single UI screen, four surfaces. */
|
|
6
|
-
export declare const APP_SCREEN_EXEMPLAR = "<div style=\"--canvas-bg: #E9EAEE; --canvas-fg: #1B1C1F; --canvas-muted: #6B6D75; --canvas-accent: #C2410C; --canvas-card: #FFFFFF; --canvas-border: #D5D7DE; --canvas-surface-1: #FFFFFF; --canvas-surface-2: #F2F3F6; --canvas-hairline: #DCDEE4; width: 1000px; background: var(--canvas-surface-1, var(--canvas-card)); font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif; color: var(--canvas-fg); display: grid; grid-template-columns: 232px 1fr;\">\n\n <div style=\"border-right: 1px solid var(--canvas-hairline, var(--canvas-border)); display: flex; flex-direction: column; min-height: 640px;\">\n <div style=\"padding: 18px 18px 16px; display: flex; align-items: center; gap: 10px;\">\n <span style=\"width: 28px; height: 28px; background: var(--canvas-fg); color: var(--canvas-surface-1, var(--canvas-card)); font-size: 11px; font-weight: 700; letter-spacing: 0.02em; display: flex; align-items: center; justify-content: center; flex: none;\">CO</span>\n <span style=\"font-size: 15px; font-weight: 700; letter-spacing: -0.01em;\">Cohort</span>\n </div>\n\n <div style=\"padding: 6px 10px 0; display: flex; flex-direction: column; gap: 1px;\">\n <div style=\"display: flex; align-items: center; gap: 10px; padding: 10px 12px; background: color-mix(in oklab, var(--canvas-accent) 10%, var(--canvas-surface-1, var(--canvas-card))); box-shadow: inset 2px 0 0 var(--canvas-accent); font-size: 13.5px; font-weight: 600;\">\n <span style=\"font-size: 13px; flex: none; color: var(--canvas-accent);\">■</span>Overview\n </div>\n <div style=\"display: flex; align-items: center; gap: 10px; padding: 10px 12px; font-size: 13.5px; color: color-mix(in oklab, var(--canvas-fg) 82%, var(--canvas-bg));\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" style=\"flex: none; color: var(--canvas-muted);\"><circle cx=\"6\" cy=\"6\" r=\"2.5\"></circle><path d=\"M2 13.5c.8-2.2 2.2-3.3 4-3.3s3.2 1.1 4 3.3\"></path><path d=\"M11 4.2a2.5 2.5 0 0 1 0 4.6\"></path></svg>Applicants\n <span style=\"margin-left: auto; font-size: 12px; color: var(--canvas-muted); font-variant-numeric: tabular-nums;\">248</span>\n </div>\n <div style=\"display: flex; align-items: center; gap: 10px; padding: 10px 12px; font-size: 13.5px; color: color-mix(in oklab, var(--canvas-fg) 82%, var(--canvas-bg));\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" style=\"flex: none; color: var(--canvas-muted);\"><rect x=\"2.5\" y=\"3.5\" width=\"11\" height=\"10\" rx=\"1\"></rect><path d=\"M2.5 6.5h11M5.5 2v2.5M10.5 2v2.5\"></path></svg>Interviews\n <span style=\"margin-left: auto; font-size: 12px; color: var(--canvas-muted); font-variant-numeric: tabular-nums;\">67</span>\n </div>\n <div style=\"display: flex; align-items: center; gap: 10px; padding: 10px 12px; font-size: 13.5px; color: color-mix(in oklab, var(--canvas-fg) 82%, var(--canvas-bg));\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" style=\"flex: none; color: var(--canvas-muted);\"><path d=\"M9.5 2H4.5A1.5 1.5 0 0 0 3 3.5v9A1.5 1.5 0 0 0 4.5 14h7a1.5 1.5 0 0 0 1.5-1.5V5.5z\"></path><path d=\"M9.5 2v3.5H13\"></path></svg>Documents\n </div>\n <div style=\"display: flex; align-items: center; gap: 10px; padding: 10px 12px; font-size: 13.5px; color: color-mix(in oklab, var(--canvas-fg) 82%, var(--canvas-bg));\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" style=\"flex: none; color: var(--canvas-muted);\"><path d=\"M2 14h12\"></path><path d=\"M4.5 14V9M8 14V4.5M11.5 14V7\"></path></svg>Reports\n </div>\n <div style=\"display: flex; align-items: center; gap: 10px; padding: 10px 12px; font-size: 13.5px; color: color-mix(in oklab, var(--canvas-fg) 82%, var(--canvas-bg));\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" style=\"flex: none; color: var(--canvas-muted);\"><path d=\"M2 5.5A1.5 1.5 0 0 1 3.5 4h2.2l1.3 1.6h5.5A1.5 1.5 0 0 1 14 7.1v5.4A1.5 1.5 0 0 1 12.5 14h-9A1.5 1.5 0 0 1 2 12.5z\"></path></svg>Programmes\n <span style=\"margin-left: auto; font-size: 12px; color: var(--canvas-muted); font-variant-numeric: tabular-nums;\">12</span>\n </div>\n </div>\n\n <div style=\"margin-top: auto; border-top: 1px solid var(--canvas-hairline, var(--canvas-border)); padding: 12px 22px; font-size: 13.5px; color: color-mix(in oklab, var(--canvas-fg) 82%, var(--canvas-bg));\">Settings</div>\n <div style=\"border-top: 1px solid var(--canvas-hairline, var(--canvas-border)); padding: 14px 18px; display: flex; align-items: center; gap: 10px;\">\n <span style=\"width: 30px; height: 30px; background: var(--canvas-surface-2, var(--canvas-bg)); border: 1px solid var(--canvas-hairline, var(--canvas-border)); font-size: 11px; font-weight: 600; color: var(--canvas-muted); display: flex; align-items: center; justify-content: center; flex: none;\">RM</span>\n <span>\n <span style=\"display: block; font-size: 13px; font-weight: 600;\">Rita Marchetti</span>\n <span style=\"display: block; font-size: 11px; color: var(--canvas-muted);\">Admissions lead</span>\n </span>\n </div>\n </div>\n\n <div style=\"display: flex; flex-direction: column;\">\n <div style=\"padding: 20px 28px 18px; border-bottom: 1px solid var(--canvas-hairline, var(--canvas-border)); display: flex; align-items: flex-end; justify-content: space-between; gap: 24px;\">\n <div>\n <div style=\"font-size: 11px; letter-spacing: 0.06em; color: var(--canvas-muted); margin-bottom: 6px;\">Autumn 2027 / Admissions</div>\n <div style=\"font-size: 26px; font-weight: 700; letter-spacing: -0.022em;\">Overview</div>\n </div>\n <div style=\"display: flex; align-items: center; gap: 8px; flex: none;\">\n <span style=\"font-size: 13px; padding: 8px 14px; border: 1px solid var(--canvas-hairline, var(--canvas-border)); color: color-mix(in oklab, var(--canvas-fg) 82%, var(--canvas-bg));\">Export</span>\n <span style=\"font-size: 13px; font-weight: 600; padding: 9px 15px; background: var(--canvas-fg); color: var(--canvas-surface-1, var(--canvas-card));\">New applicant</span>\n </div>\n </div>\n <div style=\"background: var(--canvas-surface-2, var(--canvas-bg)); padding: 20px 28px 26px; flex: 1; display: flex; flex-direction: column; gap: 16px;\">\n\n <div style=\"display: grid; grid-template-columns: 1.45fr 1fr; gap: 16px;\">\n <div style=\"background: var(--canvas-surface-1, var(--canvas-card)); border: 1px solid var(--canvas-hairline, var(--canvas-border)); padding: 22px 24px;\">\n <div style=\"display: flex; align-items: baseline; justify-content: space-between; gap: 16px; margin-bottom: 14px;\">\n <div style=\"font-size: 10px; letter-spacing: 0.12em; font-weight: 600; color: var(--canvas-accent);\">THIS WEEK</div>\n <div style=\"font-size: 11px; color: var(--canvas-muted);\">updated 4 min ago</div>\n </div>\n <div style=\"font-size: 27px; line-height: 1.2; font-weight: 700; letter-spacing: -0.022em; margin-bottom: 10px; max-width: 20em;\">Interviews are keeping pace. Document review is not.</div>\n <p style=\"font-size: 13.5px; line-height: 1.65; color: color-mix(in oklab, var(--canvas-fg) 78%, var(--canvas-bg)); margin: 0 0 16px;\">248 applicants across 12 programmes, and 67 have reached interview. The queue sits at document review, where 41 files have waited more than five days — two programmes account for 30 of them.</p>\n <span style=\"display: inline-block; font-size: 12.5px; font-weight: 600; color: var(--canvas-accent); border-bottom: 1px solid var(--canvas-accent); padding-bottom: 1px;\">Review the 41 waiting files</span>\n </div>\n\n <div style=\"background: var(--canvas-fg); color: var(--canvas-surface-1, var(--canvas-card)); padding: 20px 22px; display: flex; flex-direction: column; gap: 14px;\">\n <div style=\"display: flex; align-items: baseline; justify-content: space-between; gap: 12px;\">\n <span style=\"font-size: 10px; letter-spacing: 0.12em; font-weight: 600;\">PIPELINE</span>\n <span style=\"font-size: 10px; letter-spacing: 0.06em; opacity: 0.62;\">stage by stage</span>\n </div>\n <div style=\"display: flex; flex-direction: column; gap: 11px;\">\n <div>\n <div style=\"display: flex; align-items: baseline; justify-content: space-between; gap: 10px; font-size: 12px;\"><span style=\"opacity: 0.75;\">Applied</span><span style=\"font-size: 15px; font-weight: 700; font-variant-numeric: tabular-nums;\">248</span></div>\n <div style=\"height: 4px; background: rgba(255,255,255,0.16); margin-top: 5px;\"><div style=\"height: 4px; width: 100%; background: rgba(255,255,255,0.62);\"></div></div>\n </div>\n <div>\n <div style=\"display: flex; align-items: baseline; justify-content: space-between; gap: 10px; font-size: 12px;\"><span style=\"opacity: 0.75;\">Documents in</span><span style=\"font-size: 15px; font-weight: 700; font-variant-numeric: tabular-nums;\">193</span></div>\n <div style=\"height: 4px; background: rgba(255,255,255,0.16); margin-top: 5px;\"><div style=\"height: 4px; width: 78%; background: rgba(255,255,255,0.62);\"></div></div>\n </div>\n <div>\n <div style=\"display: flex; align-items: baseline; justify-content: space-between; gap: 10px; font-size: 12px;\"><span style=\"opacity: 0.75;\">Reviewed</span><span style=\"font-size: 15px; font-weight: 700; font-variant-numeric: tabular-nums;\">152</span></div>\n <div style=\"height: 4px; background: rgba(255,255,255,0.16); margin-top: 5px;\"><div style=\"height: 4px; width: 61%; background: var(--canvas-accent);\"></div></div>\n </div>\n <div>\n <div style=\"display: flex; align-items: baseline; justify-content: space-between; gap: 10px; font-size: 12px;\"><span style=\"opacity: 0.75;\">Interviewed</span><span style=\"font-size: 15px; font-weight: 700; font-variant-numeric: tabular-nums;\">67</span></div>\n <div style=\"height: 4px; background: rgba(255,255,255,0.16); margin-top: 5px;\"><div style=\"height: 4px; width: 27%; background: rgba(255,255,255,0.62);\"></div></div>\n </div>\n </div>\n <div style=\"margin-top: auto; border-top: 1px solid rgba(255,255,255,0.18); padding-top: 11px; font-size: 12px; opacity: 0.82;\">41 files stalled at review</div>\n </div>\n </div>\n\n <div style=\"display: flex; align-items: center; gap: 8px;\">\n <span style=\"font-size: 10px; letter-spacing: 0.12em; font-weight: 600; color: var(--canvas-muted); margin-right: 4px;\">FACULTY</span>\n <span style=\"font-size: 12.5px; font-weight: 600; padding: 6px 12px; background: var(--canvas-surface-1, var(--canvas-card)); border: 1px solid var(--canvas-fg);\">All <span style=\"color: var(--canvas-muted); font-weight: 400;\">12</span></span>\n <span style=\"font-size: 12.5px; padding: 6px 12px; background: var(--canvas-surface-1, var(--canvas-card)); border: 1px solid var(--canvas-hairline, var(--canvas-border)); color: color-mix(in oklab, var(--canvas-fg) 82%, var(--canvas-bg));\">Design <span style=\"color: var(--canvas-muted);\">4</span></span>\n <span style=\"font-size: 12.5px; padding: 6px 12px; background: var(--canvas-surface-1, var(--canvas-card)); border: 1px solid var(--canvas-hairline, var(--canvas-border)); color: color-mix(in oklab, var(--canvas-fg) 82%, var(--canvas-bg));\">Business <span style=\"color: var(--canvas-muted);\">5</span></span>\n <span style=\"font-size: 12.5px; padding: 6px 12px; background: var(--canvas-surface-1, var(--canvas-card)); border: 1px solid var(--canvas-hairline, var(--canvas-border)); color: color-mix(in oklab, var(--canvas-fg) 82%, var(--canvas-bg));\">Engineering <span style=\"color: var(--canvas-muted);\">3</span></span>\n </div>\n\n <div style=\"background: var(--canvas-surface-1, var(--canvas-card)); border: 1px solid var(--canvas-hairline, var(--canvas-border));\">\n <div style=\"padding: 13px 18px; border-bottom: 1px solid var(--canvas-hairline, var(--canvas-border)); display: flex; align-items: baseline; justify-content: space-between; gap: 16px;\">\n <span style=\"font-size: 14px; font-weight: 600;\">Programmes needing attention</span>\n <span style=\"font-size: 12px; color: var(--canvas-muted);\">4 of 12</span>\n </div>\n <div style=\"display: grid; grid-template-columns: 1.6fr 120px 84px 84px 92px; gap: 14px; padding: 9px 18px; background: var(--canvas-surface-2, var(--canvas-bg)); border-bottom: 1px solid var(--canvas-hairline, var(--canvas-border)); font-size: 10px; letter-spacing: 0.1em; font-weight: 600; color: var(--canvas-muted);\">\n <span>PROGRAMME</span><span>REVIEW</span><span style=\"text-align: right;\">APPLIED</span><span style=\"text-align: right;\">OFFERS</span><span style=\"text-align: right;\">WAITING</span>\n </div>\n <div style=\"display: grid; grid-template-columns: 1.6fr 120px 84px 84px 92px; gap: 14px; padding: 12px 18px; border-bottom: 1px solid var(--canvas-hairline, var(--canvas-border)); font-size: 13px; align-items: center;\">\n <span style=\"font-weight: 600;\">MSc Product Design</span>\n <span style=\"height: 5px; background: var(--canvas-surface-2, var(--canvas-bg));\"><span style=\"display: block; height: 5px; width: 38%; background: var(--canvas-accent);\"></span></span>\n <span style=\"text-align: right; font-variant-numeric: tabular-nums;\">31</span>\n <span style=\"text-align: right; font-variant-numeric: tabular-nums;\">4</span>\n <span style=\"text-align: right; font-variant-numeric: tabular-nums; font-weight: 600; color: var(--canvas-accent);\">17</span>\n </div>\n <div style=\"display: grid; grid-template-columns: 1.6fr 120px 84px 84px 92px; gap: 14px; padding: 12px 18px; border-bottom: 1px solid var(--canvas-hairline, var(--canvas-border)); font-size: 13px; align-items: center;\">\n <span style=\"font-weight: 600;\">MBA Sustainable Business</span>\n <span style=\"height: 5px; background: var(--canvas-surface-2, var(--canvas-bg));\"><span style=\"display: block; height: 5px; width: 46%; background: var(--canvas-accent);\"></span></span>\n <span style=\"text-align: right; font-variant-numeric: tabular-nums;\">28</span>\n <span style=\"text-align: right; font-variant-numeric: tabular-nums;\">6</span>\n <span style=\"text-align: right; font-variant-numeric: tabular-nums; font-weight: 600; color: var(--canvas-accent);\">13</span>\n </div>\n <div style=\"display: grid; grid-template-columns: 1.6fr 120px 84px 84px 92px; gap: 14px; padding: 12px 18px; border-bottom: 1px solid var(--canvas-hairline, var(--canvas-border)); font-size: 13px; align-items: center;\">\n <span style=\"font-weight: 600;\">MA Curation</span>\n <span style=\"height: 5px; background: var(--canvas-surface-2, var(--canvas-bg));\"><span style=\"display: block; height: 5px; width: 71%; background: color-mix(in oklab, var(--canvas-fg) 32%, var(--canvas-bg));\"></span></span>\n <span style=\"text-align: right; font-variant-numeric: tabular-nums;\">19</span>\n <span style=\"text-align: right; font-variant-numeric: tabular-nums;\">5</span>\n <span style=\"text-align: right; font-variant-numeric: tabular-nums;\">7</span>\n </div>\n <div style=\"display: grid; grid-template-columns: 1.6fr 120px 84px 84px 92px; gap: 14px; padding: 12px 18px; font-size: 13px; align-items: center;\">\n <span style=\"font-weight: 600;\">MEng Robotics</span>\n <span style=\"height: 5px; background: var(--canvas-surface-2, var(--canvas-bg));\"><span style=\"display: block; height: 5px; width: 83%; background: color-mix(in oklab, var(--canvas-fg) 32%, var(--canvas-bg));\"></span></span>\n <span style=\"text-align: right; font-variant-numeric: tabular-nums;\">24</span>\n <span style=\"text-align: right; font-variant-numeric: tabular-nums;\">9</span>\n <span style=\"text-align: right; font-variant-numeric: tabular-nums;\">4</span>\n </div>\n </div>\n </div>\n </div>\n </div>";
|
|
6
|
+
export declare const APP_SCREEN_EXEMPLAR = "<div style=\"--canvas-bg: #E9EAEE; --canvas-fg: #1B1C1F; --canvas-muted: #63656D; --canvas-accent: #C2410C; --canvas-card: #FFFFFF; --canvas-border: #D5D7DE; --canvas-surface-1: #FFFFFF; --canvas-surface-2: #F2F3F6; --canvas-hairline: #DCDEE4; width: 1000px; background: var(--canvas-surface-1, var(--canvas-card)); font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif; color: var(--canvas-fg); display: grid; grid-template-columns: 232px 1fr;\">\n\n <div style=\"border-right: 1px solid var(--canvas-hairline, var(--canvas-border)); display: flex; flex-direction: column; min-height: 640px;\">\n <div style=\"padding: 18px 18px 16px; display: flex; align-items: center; gap: 10px;\">\n <span style=\"width: 28px; height: 28px; background: var(--canvas-fg); color: var(--canvas-surface-1, var(--canvas-card)); font-size: 11px; font-weight: 700; letter-spacing: 0.02em; display: flex; align-items: center; justify-content: center; flex: none;\">CO</span>\n <span style=\"font-size: 15px; font-weight: 700; letter-spacing: -0.01em;\">Cohort</span>\n </div>\n\n <div style=\"padding: 6px 10px 0; display: flex; flex-direction: column; gap: 1px;\">\n <div style=\"display: flex; align-items: center; gap: 10px; padding: 10px 12px; background: color-mix(in oklab, var(--canvas-accent) 10%, var(--canvas-surface-1, var(--canvas-card))); box-shadow: inset 2px 0 0 var(--canvas-accent); font-size: 13.5px; font-weight: 600;\">\n <span style=\"font-size: 13px; flex: none; color: var(--canvas-accent);\">■</span>Overview\n </div>\n <div style=\"display: flex; align-items: center; gap: 10px; padding: 10px 12px; font-size: 13.5px; color: color-mix(in oklab, var(--canvas-fg) 82%, var(--canvas-bg));\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" style=\"flex: none; color: var(--canvas-muted);\"><circle cx=\"6\" cy=\"6\" r=\"2.5\"></circle><path d=\"M2 13.5c.8-2.2 2.2-3.3 4-3.3s3.2 1.1 4 3.3\"></path><path d=\"M11 4.2a2.5 2.5 0 0 1 0 4.6\"></path></svg>Applicants\n <span style=\"margin-left: auto; font-size: 12px; color: var(--canvas-muted); font-variant-numeric: tabular-nums;\">248</span>\n </div>\n <div style=\"display: flex; align-items: center; gap: 10px; padding: 10px 12px; font-size: 13.5px; color: color-mix(in oklab, var(--canvas-fg) 82%, var(--canvas-bg));\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" style=\"flex: none; color: var(--canvas-muted);\"><rect x=\"2.5\" y=\"3.5\" width=\"11\" height=\"10\" rx=\"1\"></rect><path d=\"M2.5 6.5h11M5.5 2v2.5M10.5 2v2.5\"></path></svg>Interviews\n <span style=\"margin-left: auto; font-size: 12px; color: var(--canvas-muted); font-variant-numeric: tabular-nums;\">67</span>\n </div>\n <div style=\"display: flex; align-items: center; gap: 10px; padding: 10px 12px; font-size: 13.5px; color: color-mix(in oklab, var(--canvas-fg) 82%, var(--canvas-bg));\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" style=\"flex: none; color: var(--canvas-muted);\"><path d=\"M9.5 2H4.5A1.5 1.5 0 0 0 3 3.5v9A1.5 1.5 0 0 0 4.5 14h7a1.5 1.5 0 0 0 1.5-1.5V5.5z\"></path><path d=\"M9.5 2v3.5H13\"></path></svg>Documents\n </div>\n <div style=\"display: flex; align-items: center; gap: 10px; padding: 10px 12px; font-size: 13.5px; color: color-mix(in oklab, var(--canvas-fg) 82%, var(--canvas-bg));\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" style=\"flex: none; color: var(--canvas-muted);\"><path d=\"M2 14h12\"></path><path d=\"M4.5 14V9M8 14V4.5M11.5 14V7\"></path></svg>Reports\n </div>\n <div style=\"display: flex; align-items: center; gap: 10px; padding: 10px 12px; font-size: 13.5px; color: color-mix(in oklab, var(--canvas-fg) 82%, var(--canvas-bg));\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" style=\"flex: none; color: var(--canvas-muted);\"><path d=\"M2 5.5A1.5 1.5 0 0 1 3.5 4h2.2l1.3 1.6h5.5A1.5 1.5 0 0 1 14 7.1v5.4A1.5 1.5 0 0 1 12.5 14h-9A1.5 1.5 0 0 1 2 12.5z\"></path></svg>Programmes\n <span style=\"margin-left: auto; font-size: 12px; color: var(--canvas-muted); font-variant-numeric: tabular-nums;\">12</span>\n </div>\n </div>\n\n <div style=\"margin-top: auto; border-top: 1px solid var(--canvas-hairline, var(--canvas-border)); padding: 12px 22px; font-size: 13.5px; color: color-mix(in oklab, var(--canvas-fg) 82%, var(--canvas-bg));\">Settings</div>\n <div style=\"border-top: 1px solid var(--canvas-hairline, var(--canvas-border)); padding: 14px 18px; display: flex; align-items: center; gap: 10px;\">\n <span style=\"width: 30px; height: 30px; background: var(--canvas-surface-2, var(--canvas-bg)); border: 1px solid var(--canvas-hairline, var(--canvas-border)); font-size: 11px; font-weight: 600; color: var(--canvas-muted); display: flex; align-items: center; justify-content: center; flex: none;\">RM</span>\n <span>\n <span style=\"display: block; font-size: 13px; font-weight: 600;\">Rita Marchetti</span>\n <span style=\"display: block; font-size: 11px; color: var(--canvas-muted);\">Admissions lead</span>\n </span>\n </div>\n </div>\n\n <div style=\"display: flex; flex-direction: column;\">\n <div style=\"padding: 20px 28px 18px; border-bottom: 1px solid var(--canvas-hairline, var(--canvas-border)); display: flex; align-items: flex-end; justify-content: space-between; gap: 24px;\">\n <div>\n <div style=\"font-size: 11px; letter-spacing: 0.06em; color: var(--canvas-muted); margin-bottom: 6px;\">Autumn 2027 / Admissions</div>\n <div style=\"font-size: 26px; font-weight: 700; letter-spacing: -0.022em;\">Overview</div>\n </div>\n <div style=\"display: flex; align-items: center; gap: 8px; flex: none;\">\n <span style=\"font-size: 13px; padding: 8px 14px; border: 1px solid var(--canvas-hairline, var(--canvas-border)); color: color-mix(in oklab, var(--canvas-fg) 82%, var(--canvas-bg));\">Export</span>\n <span style=\"font-size: 13px; font-weight: 600; padding: 9px 15px; background: var(--canvas-fg); color: var(--canvas-surface-1, var(--canvas-card));\">New applicant</span>\n </div>\n </div>\n <div style=\"background: var(--canvas-surface-2, var(--canvas-bg)); padding: 20px 28px 26px; flex: 1; display: flex; flex-direction: column; gap: 16px;\">\n\n <div style=\"display: grid; grid-template-columns: 1.45fr 1fr; gap: 16px;\">\n <div style=\"background: var(--canvas-surface-1, var(--canvas-card)); border: 1px solid var(--canvas-hairline, var(--canvas-border)); padding: 22px 24px;\">\n <div style=\"display: flex; align-items: baseline; justify-content: space-between; gap: 16px; margin-bottom: 14px;\">\n <div style=\"font-size: 10px; letter-spacing: 0.12em; font-weight: 600; color: var(--canvas-accent);\">THIS WEEK</div>\n <div style=\"font-size: 11px; color: var(--canvas-muted);\">updated 4 min ago</div>\n </div>\n <div style=\"font-size: 27px; line-height: 1.2; font-weight: 700; letter-spacing: -0.022em; margin-bottom: 10px; max-width: 20em;\">Interviews are keeping pace. Document review is not.</div>\n <p style=\"font-size: 13.5px; line-height: 1.65; color: color-mix(in oklab, var(--canvas-fg) 78%, var(--canvas-bg)); margin: 0 0 16px;\">248 applicants across 12 programmes, and 67 have reached interview. The queue sits at document review, where 41 files have waited more than five days — two programmes account for 30 of them.</p>\n <span style=\"display: inline-block; font-size: 12.5px; font-weight: 600; color: var(--canvas-accent); border-bottom: 1px solid var(--canvas-accent); padding-bottom: 1px;\">Review the 41 waiting files</span>\n </div>\n\n <div style=\"background: var(--canvas-fg); color: var(--canvas-surface-1, var(--canvas-card)); padding: 20px 22px; display: flex; flex-direction: column; gap: 14px;\">\n <div style=\"display: flex; align-items: baseline; justify-content: space-between; gap: 12px;\">\n <span style=\"font-size: 10px; letter-spacing: 0.12em; font-weight: 600;\">PIPELINE</span>\n <span style=\"font-size: 10px; letter-spacing: 0.06em; opacity: 0.62;\">stage by stage</span>\n </div>\n <div style=\"display: flex; flex-direction: column; gap: 11px;\">\n <div>\n <div style=\"display: flex; align-items: baseline; justify-content: space-between; gap: 10px; font-size: 12px;\"><span style=\"opacity: 0.75;\">Applied</span><span style=\"font-size: 15px; font-weight: 700; font-variant-numeric: tabular-nums;\">248</span></div>\n <div style=\"height: 4px; background: rgba(255,255,255,0.16); margin-top: 5px;\"><div style=\"height: 4px; width: 100%; background: rgba(255,255,255,0.62);\"></div></div>\n </div>\n <div>\n <div style=\"display: flex; align-items: baseline; justify-content: space-between; gap: 10px; font-size: 12px;\"><span style=\"opacity: 0.75;\">Documents in</span><span style=\"font-size: 15px; font-weight: 700; font-variant-numeric: tabular-nums;\">193</span></div>\n <div style=\"height: 4px; background: rgba(255,255,255,0.16); margin-top: 5px;\"><div style=\"height: 4px; width: 78%; background: rgba(255,255,255,0.62);\"></div></div>\n </div>\n <div>\n <div style=\"display: flex; align-items: baseline; justify-content: space-between; gap: 10px; font-size: 12px;\"><span style=\"opacity: 0.75;\">Reviewed</span><span style=\"font-size: 15px; font-weight: 700; font-variant-numeric: tabular-nums;\">152</span></div>\n <div style=\"height: 4px; background: rgba(255,255,255,0.16); margin-top: 5px;\"><div style=\"height: 4px; width: 61%; background: var(--canvas-accent);\"></div></div>\n </div>\n <div>\n <div style=\"display: flex; align-items: baseline; justify-content: space-between; gap: 10px; font-size: 12px;\"><span style=\"opacity: 0.75;\">Interviewed</span><span style=\"font-size: 15px; font-weight: 700; font-variant-numeric: tabular-nums;\">67</span></div>\n <div style=\"height: 4px; background: rgba(255,255,255,0.16); margin-top: 5px;\"><div style=\"height: 4px; width: 27%; background: rgba(255,255,255,0.62);\"></div></div>\n </div>\n </div>\n <div style=\"margin-top: auto; border-top: 1px solid rgba(255,255,255,0.18); padding-top: 11px; font-size: 12px; opacity: 0.82;\">41 files stalled at review</div>\n </div>\n </div>\n\n <div style=\"display: flex; align-items: center; gap: 8px;\">\n <span style=\"font-size: 10px; letter-spacing: 0.12em; font-weight: 600; color: var(--canvas-muted); margin-right: 4px;\">FACULTY</span>\n <span style=\"font-size: 12.5px; font-weight: 600; padding: 6px 12px; background: var(--canvas-surface-1, var(--canvas-card)); border: 1px solid var(--canvas-fg);\">All <span style=\"color: var(--canvas-muted); font-weight: 400;\">12</span></span>\n <span style=\"font-size: 12.5px; padding: 6px 12px; background: var(--canvas-surface-1, var(--canvas-card)); border: 1px solid var(--canvas-hairline, var(--canvas-border)); color: color-mix(in oklab, var(--canvas-fg) 82%, var(--canvas-bg));\">Design <span style=\"color: var(--canvas-muted);\">4</span></span>\n <span style=\"font-size: 12.5px; padding: 6px 12px; background: var(--canvas-surface-1, var(--canvas-card)); border: 1px solid var(--canvas-hairline, var(--canvas-border)); color: color-mix(in oklab, var(--canvas-fg) 82%, var(--canvas-bg));\">Business <span style=\"color: var(--canvas-muted);\">5</span></span>\n <span style=\"font-size: 12.5px; padding: 6px 12px; background: var(--canvas-surface-1, var(--canvas-card)); border: 1px solid var(--canvas-hairline, var(--canvas-border)); color: color-mix(in oklab, var(--canvas-fg) 82%, var(--canvas-bg));\">Engineering <span style=\"color: var(--canvas-muted);\">3</span></span>\n </div>\n\n <div style=\"background: var(--canvas-surface-1, var(--canvas-card)); border: 1px solid var(--canvas-hairline, var(--canvas-border));\">\n <div style=\"padding: 13px 18px; border-bottom: 1px solid var(--canvas-hairline, var(--canvas-border)); display: flex; align-items: baseline; justify-content: space-between; gap: 16px;\">\n <span style=\"font-size: 14px; font-weight: 600;\">Programmes needing attention</span>\n <span style=\"font-size: 12px; color: var(--canvas-muted);\">4 of 12</span>\n </div>\n <div style=\"display: grid; grid-template-columns: 1.6fr 120px 84px 84px 92px; gap: 14px; padding: 9px 18px; background: var(--canvas-surface-2, var(--canvas-bg)); border-bottom: 1px solid var(--canvas-hairline, var(--canvas-border)); font-size: 10px; letter-spacing: 0.1em; font-weight: 600; color: var(--canvas-muted);\">\n <span>PROGRAMME</span><span>REVIEW</span><span style=\"text-align: right;\">APPLIED</span><span style=\"text-align: right;\">OFFERS</span><span style=\"text-align: right;\">WAITING</span>\n </div>\n <div style=\"display: grid; grid-template-columns: 1.6fr 120px 84px 84px 92px; gap: 14px; padding: 12px 18px; border-bottom: 1px solid var(--canvas-hairline, var(--canvas-border)); font-size: 13px; align-items: center;\">\n <span style=\"font-weight: 600;\">MSc Product Design</span>\n <span style=\"height: 5px; background: var(--canvas-surface-2, var(--canvas-bg));\"><span style=\"display: block; height: 5px; width: 38%; background: var(--canvas-accent);\"></span></span>\n <span style=\"text-align: right; font-variant-numeric: tabular-nums;\">31</span>\n <span style=\"text-align: right; font-variant-numeric: tabular-nums;\">4</span>\n <span style=\"text-align: right; font-variant-numeric: tabular-nums; font-weight: 600; color: var(--canvas-accent);\">17</span>\n </div>\n <div style=\"display: grid; grid-template-columns: 1.6fr 120px 84px 84px 92px; gap: 14px; padding: 12px 18px; border-bottom: 1px solid var(--canvas-hairline, var(--canvas-border)); font-size: 13px; align-items: center;\">\n <span style=\"font-weight: 600;\">MBA Sustainable Business</span>\n <span style=\"height: 5px; background: var(--canvas-surface-2, var(--canvas-bg));\"><span style=\"display: block; height: 5px; width: 46%; background: var(--canvas-accent);\"></span></span>\n <span style=\"text-align: right; font-variant-numeric: tabular-nums;\">28</span>\n <span style=\"text-align: right; font-variant-numeric: tabular-nums;\">6</span>\n <span style=\"text-align: right; font-variant-numeric: tabular-nums; font-weight: 600; color: var(--canvas-accent);\">13</span>\n </div>\n <div style=\"display: grid; grid-template-columns: 1.6fr 120px 84px 84px 92px; gap: 14px; padding: 12px 18px; border-bottom: 1px solid var(--canvas-hairline, var(--canvas-border)); font-size: 13px; align-items: center;\">\n <span style=\"font-weight: 600;\">MA Curation</span>\n <span style=\"height: 5px; background: var(--canvas-surface-2, var(--canvas-bg));\"><span style=\"display: block; height: 5px; width: 71%; background: color-mix(in oklab, var(--canvas-fg) 32%, var(--canvas-bg));\"></span></span>\n <span style=\"text-align: right; font-variant-numeric: tabular-nums;\">19</span>\n <span style=\"text-align: right; font-variant-numeric: tabular-nums;\">5</span>\n <span style=\"text-align: right; font-variant-numeric: tabular-nums;\">7</span>\n </div>\n <div style=\"display: grid; grid-template-columns: 1.6fr 120px 84px 84px 92px; gap: 14px; padding: 12px 18px; font-size: 13px; align-items: center;\">\n <span style=\"font-weight: 600;\">MEng Robotics</span>\n <span style=\"height: 5px; background: var(--canvas-surface-2, var(--canvas-bg));\"><span style=\"display: block; height: 5px; width: 83%; background: color-mix(in oklab, var(--canvas-fg) 32%, var(--canvas-bg));\"></span></span>\n <span style=\"text-align: right; font-variant-numeric: tabular-nums;\">24</span>\n <span style=\"text-align: right; font-variant-numeric: tabular-nums;\">9</span>\n <span style=\"text-align: right; font-variant-numeric: tabular-nums;\">4</span>\n </div>\n </div>\n </div>\n </div>\n </div>";
|
|
7
7
|
export declare const canvasExemplarInfographicSkill: import("@compilr-dev/agents").Skill;
|
|
8
8
|
export declare const canvasExemplarAppScreenSkill: import("@compilr-dev/agents").Skill;
|