@compilr-dev/sdk 0.18.11 → 0.19.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.
@@ -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
- const img = await renderer.renderToImage({ content: c.content, type: c.type });
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
- /** Working directory for resolving relative paths */
29
- cwd?: string;
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) ? input.path : path.resolve(cwd, 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
- if (options && 'planModeCallbacks' in options) {
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
- tools.push(...createCanvasTools(config));
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 ?? process.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 ?? process.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 &nbsp;&middot;&nbsp; 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;\">&#9660; 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;\">&#9660; 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;\">&#9650; 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 &nbsp;&middot;&nbsp; QUARTERLY REVIEW</span>\n <span>Source: delivery board, sprints 1&ndash;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 &nbsp;&middot;&nbsp; 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;\">&#9660; 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;\">&#9660; 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;\">&#9650; 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 &nbsp;&middot;&nbsp; QUARTERLY REVIEW</span>\n <span>Source: delivery board, sprints 1&ndash;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);\">&#9632;</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 &nbsp;/&nbsp; 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 &mdash; 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);\">&#9632;</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 &nbsp;/&nbsp; 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 &mdash; 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;