@astralkit/mcp 1.8.0 → 1.9.1

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.
Files changed (47) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/dist/api.js +2 -2
  3. package/dist/audit.d.ts +22 -0
  4. package/dist/audit.d.ts.map +1 -0
  5. package/dist/audit.js +402 -0
  6. package/dist/audit.js.map +1 -0
  7. package/dist/auth.d.ts +18 -2
  8. package/dist/auth.d.ts.map +1 -1
  9. package/dist/auth.js +21 -13
  10. package/dist/auth.js.map +1 -1
  11. package/dist/browser.d.ts +1686 -0
  12. package/dist/browser.d.ts.map +1 -0
  13. package/dist/browser.js +51 -0
  14. package/dist/browser.js.map +1 -0
  15. package/dist/capture.d.ts +7 -3
  16. package/dist/capture.d.ts.map +1 -1
  17. package/dist/capture.js +17 -53
  18. package/dist/capture.js.map +1 -1
  19. package/dist/data/art-direction.d.ts +2 -0
  20. package/dist/data/art-direction.d.ts.map +1 -0
  21. package/dist/data/art-direction.js +316 -0
  22. package/dist/data/art-direction.js.map +1 -0
  23. package/dist/data/crosswalk.d.ts +1 -1
  24. package/dist/data/crosswalk.d.ts.map +1 -1
  25. package/dist/data/crosswalk.js +135 -2
  26. package/dist/data/crosswalk.js.map +1 -1
  27. package/dist/data/polish.d.ts.map +1 -1
  28. package/dist/data/polish.js +19 -6
  29. package/dist/data/polish.js.map +1 -1
  30. package/dist/data/rules.d.ts +1 -1
  31. package/dist/data/rules.d.ts.map +1 -1
  32. package/dist/data/rules.js +55 -3
  33. package/dist/data/rules.js.map +1 -1
  34. package/dist/data/screens.d.ts.map +1 -1
  35. package/dist/data/screens.js +36 -4
  36. package/dist/data/screens.js.map +1 -1
  37. package/dist/data/theming.d.ts +2 -0
  38. package/dist/data/theming.d.ts.map +1 -0
  39. package/dist/data/theming.js +71 -0
  40. package/dist/data/theming.js.map +1 -0
  41. package/dist/data/visual.d.ts.map +1 -1
  42. package/dist/data/visual.js +25 -0
  43. package/dist/data/visual.js.map +1 -1
  44. package/dist/server.d.ts.map +1 -1
  45. package/dist/server.js +459 -54
  46. package/dist/server.js.map +1 -1
  47. package/package.json +3 -2
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ // Shared browser infrastructure for capture.ts (screenshots) and audit.ts (numerical checks).
2
+ //
3
+ // Uses playwright-core driving the SYSTEM Chrome/Edge — no bundled-browser download.
4
+ // Resolution order: ASTRALKIT_BROWSER_PATH env → Chrome → Edge.
5
+ export class BrowserUnavailableError extends Error {
6
+ constructor(message) {
7
+ super(message);
8
+ this.name = 'BrowserUnavailableError';
9
+ }
10
+ }
11
+ async function loadPlaywright() {
12
+ try {
13
+ return await import('playwright-core');
14
+ }
15
+ catch {
16
+ throw new BrowserUnavailableError('playwright-core is not installed (reinstall @astralkit/mcp, or npm i -g playwright-core).');
17
+ }
18
+ }
19
+ async function launchBrowser(chromium) {
20
+ const envPath = process.env.ASTRALKIT_BROWSER_PATH;
21
+ if (envPath) {
22
+ try {
23
+ return await chromium.launch({ headless: true, executablePath: envPath });
24
+ }
25
+ catch (err) {
26
+ throw new BrowserUnavailableError(`Could not launch the browser at ASTRALKIT_BROWSER_PATH="${envPath}": ${err instanceof Error ? err.message.split('\n')[0] : 'unknown error'}`);
27
+ }
28
+ }
29
+ for (const channel of ['chrome', 'msedge']) {
30
+ try {
31
+ return await chromium.launch({ headless: true, channel });
32
+ }
33
+ catch {
34
+ /* try next channel */
35
+ }
36
+ }
37
+ throw new BrowserUnavailableError('No system Chrome or Edge found. Install Google Chrome or Microsoft Edge, ' +
38
+ 'or set ASTRALKIT_BROWSER_PATH to a Chromium executable.');
39
+ }
40
+ /** Launch a browser, run `fn`, and close — handles cleanup on success or failure. */
41
+ export async function withBrowser(fn) {
42
+ const { chromium } = await loadPlaywright();
43
+ const browser = await launchBrowser(chromium);
44
+ try {
45
+ return await fn(browser);
46
+ }
47
+ finally {
48
+ await browser.close().catch(() => { });
49
+ }
50
+ }
51
+ //# sourceMappingURL=browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,EAAE;AACF,qFAAqF;AACrF,gEAAgE;AAEhE,MAAM,OAAO,uBAAwB,SAAQ,KAAK;IAChD,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;IACxC,CAAC;CACF;AAED,KAAK,UAAU,cAAc;IAC3B,IAAI,CAAC;QACH,OAAO,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAC;IACzC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,uBAAuB,CAC/B,2FAA2F,CAC5F,CAAC;IACJ,CAAC;AACH,CAAC;AAKD,KAAK,UAAU,aAAa,CAAC,QAAkB;IAC7C,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC;IACnD,IAAI,OAAO,EAAE,CAAC;QACZ,IAAI,CAAC;YACH,OAAO,MAAM,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,CAAC,CAAC;QAC5E,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,uBAAuB,CAC/B,2DAA2D,OAAO,MAAM,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe,EAAE,CAC9I,CAAC;QACJ,CAAC;IACH,CAAC;IACD,KAAK,MAAM,OAAO,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAU,EAAE,CAAC;QACpD,IAAI,CAAC;YACH,OAAO,MAAM,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;QAC5D,CAAC;QAAC,MAAM,CAAC;YACP,sBAAsB;QACxB,CAAC;IACH,CAAC;IACD,MAAM,IAAI,uBAAuB,CAC/B,2EAA2E;QAC3E,yDAAyD,CAC1D,CAAC;AACJ,CAAC;AAED,qFAAqF;AACrF,MAAM,CAAC,KAAK,UAAU,WAAW,CAAI,EAAoC;IACvE,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,cAAc,EAAE,CAAC;IAC5C,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,QAAQ,CAAC,CAAC;IAC9C,IAAI,CAAC;QACH,OAAO,MAAM,EAAE,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC;YAAS,CAAC;QACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACxC,CAAC;AACH,CAAC"}
package/dist/capture.d.ts CHANGED
@@ -1,6 +1,4 @@
1
- export declare class BrowserUnavailableError extends Error {
2
- constructor(message: string);
3
- }
1
+ export { BrowserUnavailableError } from './browser.js';
4
2
  export declare class CaptureError extends Error {
5
3
  constructor(message: string);
6
4
  }
@@ -9,6 +7,10 @@ export declare const VIEWPORTS: {
9
7
  readonly width: 1440;
10
8
  readonly height: 900;
11
9
  };
10
+ readonly tablet: {
11
+ readonly width: 768;
12
+ readonly height: 1024;
13
+ };
12
14
  readonly mobile: {
13
15
  readonly width: 390;
14
16
  readonly height: 844;
@@ -22,6 +24,8 @@ export interface CaptureOptions {
22
24
  fullPage?: boolean;
23
25
  /** Optional CSS selector — capture just that element (e.g. the component region inside an app shell). */
24
26
  selector?: string;
27
+ /** Click this selector before capturing — opens dropdowns/modals for interactive state verification. */
28
+ clickSelector?: string;
25
29
  }
26
30
  export interface CaptureResult {
27
31
  base64: string;
@@ -1 +1 @@
1
- {"version":3,"file":"capture.d.ts","sourceRoot":"","sources":["../src/capture.ts"],"names":[],"mappings":"AASA,qBAAa,uBAAwB,SAAQ,KAAK;gBACpC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,YAAa,SAAQ,KAAK;gBACzB,OAAO,EAAE,MAAM;CAI5B;AAED,eAAO,MAAM,SAAS;;;;;;;;;CAGZ,CAAC;AAEX,MAAM,MAAM,YAAY,GAAG,MAAM,OAAO,SAAS,CAAC;AAElD,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,uEAAuE;IACvE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,yGAAyG;IACzG,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,YAAY,CAAC;IACvB,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAC;CACf;AA8CD,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CA8DpF"}
1
+ {"version":3,"file":"capture.d.ts","sourceRoot":"","sources":["../src/capture.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAEvD,qBAAa,YAAa,SAAQ,KAAK;gBACzB,OAAO,EAAE,MAAM;CAI5B;AAED,eAAO,MAAM,SAAS;;;;;;;;;;;;;CAIZ,CAAC;AAEX,MAAM,MAAM,YAAY,GAAG,MAAM,OAAO,SAAS,CAAC;AAElD,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,uEAAuE;IACvE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,yGAAyG;IACzG,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wGAAwG;IACxG,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,YAAY,CAAC;IACvB,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAC;CACf;AAOD,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CAmEpF"}
package/dist/capture.js CHANGED
@@ -1,17 +1,7 @@
1
1
  // Headless screenshot capture for verify_visual / screenshot_ui.
2
- //
3
- // Uses playwright-core driving the SYSTEM Chrome/Edge (no bundled-browser
4
- // download playwright-core is ~3 MB and the browser the user already has does
5
- // the rendering). Resolution order: ASTRALKIT_BROWSER_PATH env override →
6
- // Chrome → Edge. Every failure surfaces as BrowserUnavailableError so the tool
7
- // layer can degrade gracefully (return the rubric + tell the agent to capture
8
- // with its own tooling) instead of hard-failing the verification step.
9
- export class BrowserUnavailableError extends Error {
10
- constructor(message) {
11
- super(message);
12
- this.name = 'BrowserUnavailableError';
13
- }
14
- }
2
+ // Browser infrastructure (launch, error handling) lives in browser.ts.
3
+ import { withBrowser } from './browser.js';
4
+ export { BrowserUnavailableError } from './browser.js';
15
5
  export class CaptureError extends Error {
16
6
  constructor(message) {
17
7
  super(message);
@@ -20,47 +10,15 @@ export class CaptureError extends Error {
20
10
  }
21
11
  export const VIEWPORTS = {
22
12
  desktop: { width: 1440, height: 900 },
13
+ tablet: { width: 768, height: 1024 },
23
14
  mobile: { width: 390, height: 844 },
24
15
  };
25
16
  const NAV_TIMEOUT_MS = 25_000;
26
17
  const SELECTOR_TIMEOUT_MS = 8_000;
27
- /** Let fonts/images/entrance animations settle before the shot. */
28
18
  const SETTLE_MS = 600;
29
- /** Full-page shots taller than this are re-taken viewport-only (a 20k-px landing page as one JPEG is useless to a vision model). */
30
19
  const MAX_FULLPAGE_HEIGHT = 4_500;
31
- async function loadPlaywright() {
32
- try {
33
- return await import('playwright-core');
34
- }
35
- catch {
36
- throw new BrowserUnavailableError('playwright-core is not installed (reinstall @astralkit/mcp, or npm i -g playwright-core).');
37
- }
38
- }
39
- async function launchBrowser(chromium) {
40
- const envPath = process.env.ASTRALKIT_BROWSER_PATH;
41
- if (envPath) {
42
- try {
43
- return await chromium.launch({ headless: true, executablePath: envPath });
44
- }
45
- catch (err) {
46
- throw new BrowserUnavailableError(`Could not launch the browser at ASTRALKIT_BROWSER_PATH="${envPath}": ${err instanceof Error ? err.message.split('\n')[0] : 'unknown error'}`);
47
- }
48
- }
49
- for (const channel of ['chrome', 'msedge']) {
50
- try {
51
- return await chromium.launch({ headless: true, channel });
52
- }
53
- catch {
54
- /* try next channel */
55
- }
56
- }
57
- throw new BrowserUnavailableError('No system Chrome or Edge found. Install Google Chrome or Microsoft Edge, ' +
58
- 'or set ASTRALKIT_BROWSER_PATH to a Chromium executable.');
59
- }
60
20
  export async function captureScreenshot(opts) {
61
- const { chromium } = await loadPlaywright();
62
- const browser = await launchBrowser(chromium);
63
- try {
21
+ return withBrowser(async (browser) => {
64
22
  const viewportName = opts.viewport ?? 'desktop';
65
23
  const page = await browser.newPage({
66
24
  viewport: VIEWPORTS[viewportName],
@@ -73,14 +31,23 @@ export async function captureScreenshot(opts) {
73
31
  }
74
32
  catch (err) {
75
33
  const msg = err instanceof Error ? err.message.split('\n')[0] : 'unknown error';
76
- // networkidle can time out on pages with long-polling/HMR sockets — if the
77
- // load event fired, proceed with what rendered; otherwise it's a real failure.
78
34
  if (!/Timeout/i.test(msg)) {
79
35
  throw new CaptureError(`Could not load ${opts.url}: ${msg}. Is the dev server running? (next dev / vite)`);
80
36
  }
81
37
  }
82
38
  await page.evaluate(() => document.fonts?.ready).catch(() => { });
83
39
  await page.waitForTimeout(SETTLE_MS);
40
+ if (opts.clickSelector) {
41
+ const trigger = page.locator(opts.clickSelector).first();
42
+ try {
43
+ await trigger.waitFor({ state: 'visible', timeout: SELECTOR_TIMEOUT_MS });
44
+ await trigger.click();
45
+ await page.waitForTimeout(SETTLE_MS);
46
+ }
47
+ catch {
48
+ // click target not found — continue with static capture
49
+ }
50
+ }
84
51
  const jpeg = { type: 'jpeg', quality: 80 };
85
52
  let buf;
86
53
  let scope;
@@ -112,9 +79,6 @@ export async function captureScreenshot(opts) {
112
79
  }
113
80
  }
114
81
  return { base64: buf.toString('base64'), mimeType: 'image/jpeg', viewport: viewportName, scope };
115
- }
116
- finally {
117
- await browser.close().catch(() => { });
118
- }
82
+ });
119
83
  }
120
84
  //# sourceMappingURL=capture.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"capture.js","sourceRoot":"","sources":["../src/capture.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"capture.js","sourceRoot":"","sources":["../src/capture.ts"],"names":[],"mappings":"AAAA,iEAAiE;AACjE,uEAAuE;AAEvE,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAEvD,MAAM,OAAO,YAAa,SAAQ,KAAK;IACrC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;IAC7B,CAAC;CACF;AAED,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE;IACrC,MAAM,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE;IACpC,MAAM,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE;CAC3B,CAAC;AAuBX,MAAM,cAAc,GAAG,MAAM,CAAC;AAC9B,MAAM,mBAAmB,GAAG,KAAK,CAAC;AAClC,MAAM,SAAS,GAAG,GAAG,CAAC;AACtB,MAAM,mBAAmB,GAAG,KAAK,CAAC;AAElC,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,IAAoB;IAC1D,OAAO,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;QACnC,MAAM,YAAY,GAAiB,IAAI,CAAC,QAAQ,IAAI,SAAS,CAAC;QAC9D,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC;YACjC,QAAQ,EAAE,SAAS,CAAC,YAAY,CAAC;YACjC,iBAAiB,EAAE,CAAC;YACpB,aAAa,EAAE,eAAe;SAC/B,CAAC,CAAC;QACH,IAAI,CAAC,iBAAiB,CAAC,cAAc,CAAC,CAAC;QAEvC,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,aAAa,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,CAAC;QACnF,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC;YAChF,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC1B,MAAM,IAAI,YAAY,CACpB,kBAAkB,IAAI,CAAC,GAAG,KAAK,GAAG,gDAAgD,CACnF,CAAC;YACJ,CAAC;QACH,CAAC;QAED,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAE,QAAgB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAC1E,MAAM,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;QAErC,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,KAAK,EAAE,CAAC;YACzD,IAAI,CAAC;gBACH,MAAM,OAAO,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,mBAAmB,EAAE,CAAC,CAAC;gBAC1E,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;gBACtB,MAAM,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;YACvC,CAAC;YAAC,MAAM,CAAC;gBACP,wDAAwD;YAC1D,CAAC;QACH,CAAC;QAED,MAAM,IAAI,GAAG,EAAE,IAAI,EAAE,MAAe,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;QACpD,IAAI,GAAW,CAAC;QAChB,IAAI,KAAa,CAAC;QAElB,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,CAAC;YAC/C,IAAI,CAAC;gBACH,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,mBAAmB,EAAE,CAAC,CAAC;YACvE,CAAC;YAAC,MAAM,CAAC;gBACP,MAAM,IAAI,YAAY,CACpB,aAAa,IAAI,CAAC,QAAQ,wCAAwC,IAAI,CAAC,GAAG,IAAI;oBAC9E,qDAAqD,CACtD,CAAC;YACJ,CAAC;YACD,GAAG,GAAG,MAAM,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YAChC,KAAK,GAAG,YAAY,IAAI,CAAC,QAAQ,EAAE,CAAC;QACtC,CAAC;aAAM,IAAI,IAAI,CAAC,QAAQ,KAAK,KAAK,EAAE,CAAC;YACnC,GAAG,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YAClC,KAAK,GAAG,UAAU,CAAC;QACrB,CAAC;aAAM,CAAC;YACN,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;YACnG,IAAI,UAAU,GAAG,mBAAmB,EAAE,CAAC;gBACrC,GAAG,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;gBAClC,KAAK,GAAG,qBAAqB,UAAU,2FAA2F,CAAC;YACrI,CAAC;iBAAM,CAAC;gBACN,GAAG,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,EAAE,GAAG,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;gBACzD,KAAK,GAAG,WAAW,CAAC;YACtB,CAAC;QACH,CAAC;QAED,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;IACnG,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function buildArtDirection(context: string): string;
2
+ //# sourceMappingURL=art-direction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"art-direction.d.ts","sourceRoot":"","sources":["../../src/data/art-direction.ts"],"names":[],"mappings":"AAiTA,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAkCzD"}
@@ -0,0 +1,316 @@
1
+ // Art direction guidance per screen/component context. Powers the get_art_direction tool.
2
+ // The MCP can't generate assets itself, but it can tell the agent exactly what to
3
+ // generate with other connected tools (e.g. Higgsfield) and how to verify the result.
4
+ const ENTRIES = {
5
+ hero: {
6
+ assets: [
7
+ 'Hero photograph or illustration (full-width, 1200px+ wide)',
8
+ 'Product mockup or app screenshot (if SaaS)',
9
+ 'Background texture or gradient overlay',
10
+ ],
11
+ hints: [
12
+ 'Style: clean, modern, high-contrast. Avoid busy backgrounds that compete with headline text.',
13
+ 'Composition: leave clear negative space for the headline and CTA — the image supports the text, not the other way around.',
14
+ 'For SaaS: isometric or perspective product mockups on a clean background read premium.',
15
+ 'For creative/agency: bold photography with a dark overlay + light text.',
16
+ 'Color: match the app palette. If the hero is dark (ak-mesh-dark), generate images with dark/moody tones.',
17
+ ],
18
+ tools: [
19
+ 'generate_image: hero photo, product mockup, or illustration',
20
+ 'generate_video: background video loop (ambient, 5-10s, seamless) for high-impact heroes',
21
+ 'search_logos: brand marks for trust strips below the hero',
22
+ ],
23
+ gates: [
24
+ 'Hero image must be at least 1200px wide (ideally 1920px for full-bleed).',
25
+ 'Image must not clip or distort at any viewport width — use object-cover + object-position.',
26
+ 'Text over images must maintain AAA contrast (use overlay if needed).',
27
+ 'Verify the hero renders with the image loaded — a hero with a missing image looks broken, not minimal.',
28
+ ],
29
+ antiPatterns: [
30
+ 'Placeholder gray boxes or "image coming soon" text — generate or source the image now.',
31
+ 'Stock photo URLs that will 404 in production.',
32
+ 'Images that clash with the color palette (warm photo on a cool-toned app).',
33
+ 'Busy illustrations behind body text — they kill readability.',
34
+ ],
35
+ },
36
+ marketing: {
37
+ assets: [
38
+ 'Feature section illustrations or icons (one per feature, consistent style)',
39
+ 'Trust strip logos (5-8 real brand logos)',
40
+ 'Section divider graphics or background patterns',
41
+ ],
42
+ hints: [
43
+ 'Feature icons: consistent style across all features — either all line, all filled, all isometric 3D. Never mix.',
44
+ 'Illustrations: flat or isometric, clean backgrounds, limited color palette matching the app theme.',
45
+ 'Trust logos: real brand marks via search_logos, displayed at consistent height (h-8 to h-10), desaturated/monochrome.',
46
+ ],
47
+ tools: [
48
+ 'generate_image: feature illustrations, section graphics',
49
+ 'search_logos: trust strip brands, integration partner logos',
50
+ ],
51
+ gates: [
52
+ 'All feature icons must be the same style and approximate size.',
53
+ 'Trust logos must be real (search_logos), not hand-drawn SVGs.',
54
+ 'Section illustrations should support the copy, not distract from it.',
55
+ ],
56
+ antiPatterns: [
57
+ 'Mixing illustration styles (flat + 3D + photo in one section).',
58
+ 'Generic stock illustrations that don\'t relate to the product.',
59
+ 'Oversized decorative graphics that push content below the fold.',
60
+ ],
61
+ },
62
+ pricing: {
63
+ assets: [
64
+ 'Tier comparison icons or illustrations (optional)',
65
+ 'Trust badges or guarantee seals',
66
+ 'Brand logos for social proof ("Trusted by...")',
67
+ ],
68
+ hints: [
69
+ 'Pricing pages are content-first — imagery is secondary to the tier comparison.',
70
+ 'If using tier illustrations, keep them small (64-96px) and at the top of each card.',
71
+ 'Trust elements near the CTA: guarantee badge, security lock, real brand logos.',
72
+ ],
73
+ tools: [
74
+ 'search_logos: customer logos for social proof near CTAs',
75
+ 'generate_image: tier illustrations (only if the design calls for them)',
76
+ ],
77
+ gates: [
78
+ 'Trust logos must be real brands (search_logos).',
79
+ 'Tier illustrations (if any) must be consistent in style and size.',
80
+ ],
81
+ antiPatterns: [
82
+ 'Large hero images on pricing pages — they push the tiers below the fold.',
83
+ 'Decorative graphics that distract from the price comparison.',
84
+ ],
85
+ },
86
+ dashboard: {
87
+ assets: [
88
+ 'Empty-state illustrations (for each data widget when no data exists)',
89
+ 'Avatar images for user lists/activity feeds',
90
+ 'Chart placeholder or sample data visualizations',
91
+ ],
92
+ hints: [
93
+ 'Empty states: friendly, minimal illustrations that convey "nothing here yet" without being sad.',
94
+ 'Avatars: use initials in colored circles (bg-ak-primary/secondary) for placeholder avatars — don\'t generate face images.',
95
+ 'Charts: use ak-chart-1 through ak-chart-6 for data visualization colors.',
96
+ ],
97
+ tools: [
98
+ 'generate_image: empty-state illustrations',
99
+ 'search_logos: integration/service logos for connected-services widgets',
100
+ ],
101
+ gates: [
102
+ 'Every data widget must have an empty-state illustration, not a blank space.',
103
+ 'Avatar placeholders must be consistent (all initials or all icons, not mixed).',
104
+ ],
105
+ antiPatterns: [
106
+ 'Blank white space where empty states should be.',
107
+ 'Generic "no data" text without an illustration or CTA.',
108
+ 'Stock photos for user avatars in demo data.',
109
+ ],
110
+ },
111
+ auth: {
112
+ assets: [
113
+ 'Background image or pattern (split-layout auth pages)',
114
+ 'Brand logo at the top of the form',
115
+ 'Social sign-in provider logos (Google, GitHub, Apple, etc.)',
116
+ ],
117
+ hints: [
118
+ 'Auth pages are focused — minimal imagery. A side panel with a brand photo/illustration works well for split layouts.',
119
+ 'Keep the form panel clean and uncluttered — no background images behind the form itself.',
120
+ 'Social logos must be the official brand marks (search_logos), not hand-drawn.',
121
+ ],
122
+ tools: [
123
+ 'search_logos: social sign-in providers (Google, GitHub, Apple, Microsoft)',
124
+ 'generate_image: side panel illustration or background (for split-layout auth)',
125
+ ],
126
+ gates: [
127
+ 'Social sign-in logos must be official (search_logos).',
128
+ 'Background imagery (if any) must not reduce form readability.',
129
+ 'Brand logo must be properly sized — not stretched, not tiny.',
130
+ ],
131
+ antiPatterns: [
132
+ 'Busy background images that make form labels hard to read.',
133
+ 'Missing social sign-in logos (gray boxes or text-only buttons).',
134
+ 'Oversized brand logos that crowd the form.',
135
+ ],
136
+ },
137
+ onboarding: {
138
+ assets: [
139
+ 'Step illustrations (one per onboarding step, consistent style)',
140
+ 'Welcome/celebration illustration for completion',
141
+ 'Progress indicator graphics',
142
+ ],
143
+ hints: [
144
+ 'Friendly, encouraging tone — illustrations should feel welcoming, not corporate.',
145
+ 'Consistent illustration style across all steps.',
146
+ 'Completion state: a small celebration (confetti, checkmark, thumbs up) — not over the top.',
147
+ ],
148
+ tools: [
149
+ 'generate_image: step illustrations, welcome graphic, completion celebration',
150
+ ],
151
+ gates: [
152
+ 'All step illustrations must be the same style.',
153
+ 'Illustrations should be small enough not to push the form/CTA below the fold on mobile.',
154
+ ],
155
+ antiPatterns: [
156
+ 'Steps with no visual differentiation (identical layouts).',
157
+ 'Heavy illustrations that slow page load.',
158
+ 'Missing completion/success state.',
159
+ ],
160
+ },
161
+ features: {
162
+ assets: [
163
+ 'Feature icons or illustrations (one per feature, consistent set)',
164
+ 'Product screenshots or mockups showing the feature in context',
165
+ ],
166
+ hints: [
167
+ 'Icon set: 24-48px, consistent weight and style. Phosphor duotone weight reads rich for marketing features.',
168
+ 'If using screenshots: add a subtle shadow/border and round the corners (rounded-ak-xl) for a polished look.',
169
+ 'Alternating image/text layout: images should be roughly equal in size and aspect ratio.',
170
+ ],
171
+ tools: [
172
+ 'generate_image: feature illustrations, product screenshots/mockups',
173
+ 'search_logos: integration logos if features include "integrates with X"',
174
+ ],
175
+ gates: [
176
+ 'All feature icons must be from the same set (Phosphor or a generated set, not mixed).',
177
+ 'Product screenshots must show real or realistic UI, not lorem placeholders.',
178
+ ],
179
+ antiPatterns: [
180
+ 'Mixing Phosphor icons with generated illustrations in the same feature grid.',
181
+ 'Feature images with wildly different aspect ratios.',
182
+ 'Screenshots of obviously broken or placeholder UI.',
183
+ ],
184
+ },
185
+ testimonials: {
186
+ assets: [
187
+ 'Customer avatar photos or company logos',
188
+ 'Company logos for attribution',
189
+ ],
190
+ hints: [
191
+ 'Real customer photos are ideal. If not available, use initials in colored circles.',
192
+ 'Company logos via search_logos — display at consistent height, optionally desaturated.',
193
+ 'Don\'t generate fake customer photos — use initials, real photos, or omit.',
194
+ ],
195
+ tools: [
196
+ 'search_logos: customer/company logos',
197
+ ],
198
+ gates: [
199
+ 'Avatars must be consistent: all photos, all initials, or all logos — not mixed.',
200
+ 'Company logos must be real (search_logos).',
201
+ ],
202
+ antiPatterns: [
203
+ 'AI-generated "customer" faces that look uncanny.',
204
+ 'Mixing photo avatars with initial-circle avatars.',
205
+ 'Missing avatars (text-only testimonials feel less credible).',
206
+ ],
207
+ },
208
+ team: {
209
+ assets: [
210
+ 'Team member photos (headshots)',
211
+ 'Company culture/office photos',
212
+ ],
213
+ hints: [
214
+ 'Headshots: consistent crop and aspect ratio. Square or circle crop, same background feel.',
215
+ 'If real photos aren\'t available, use illustrated avatars in a consistent style.',
216
+ 'Culture photos: real is better than staged-looking stock.',
217
+ ],
218
+ tools: [
219
+ 'generate_image: illustrated team avatars (only if real photos are unavailable)',
220
+ ],
221
+ gates: [
222
+ 'All headshots must be the same size and aspect ratio.',
223
+ 'Never generate realistic fake headshots — use illustrations or initials.',
224
+ ],
225
+ antiPatterns: [
226
+ 'AI-generated "team" photos that look like deepfakes.',
227
+ 'Mixed photo sizes/crops that make the grid look messy.',
228
+ 'Stock photos presented as real team members.',
229
+ ],
230
+ },
231
+ landing: {
232
+ assets: [
233
+ 'Hero image or video',
234
+ 'Feature illustrations',
235
+ 'Trust strip logos',
236
+ 'Testimonial avatars',
237
+ 'CTA background or accent graphics',
238
+ ],
239
+ hints: [
240
+ 'A landing page is hero + features + social proof + CTA. Each section needs its own assets.',
241
+ 'Maintain visual consistency across all sections — same illustration style, same photo treatment.',
242
+ 'Generate all assets BEFORE assembling the page so they can be wired in during build.',
243
+ ],
244
+ tools: [
245
+ 'generate_image: hero, feature illustrations, CTA backgrounds',
246
+ 'generate_video: hero background loop (optional, high-impact)',
247
+ 'search_logos: trust strip, integration partners, social proof',
248
+ ],
249
+ gates: [
250
+ 'Every section with an image placeholder must have a real image.',
251
+ 'Trust logos must be real (search_logos).',
252
+ 'Hero image must be full-width capable (1200px+ wide).',
253
+ ],
254
+ antiPatterns: [
255
+ 'A landing page with "placeholder" images or gray boxes in production.',
256
+ 'Inconsistent illustration styles across sections.',
257
+ 'Missing social proof imagery (text-only trust strip).',
258
+ ],
259
+ },
260
+ };
261
+ const GENERAL = {
262
+ assets: [
263
+ 'Contextual imagery appropriate to the component type',
264
+ 'Icons from Phosphor (UI) or generated (decorative)',
265
+ 'Brand logos via search_logos where applicable',
266
+ ],
267
+ hints: [
268
+ 'Match imagery style to the app\'s existing visual language.',
269
+ 'Generate assets BEFORE building the component — wire them in during build, not after.',
270
+ 'Use consistent sizing and aspect ratios for repeating elements (cards, grids).',
271
+ ],
272
+ tools: [
273
+ 'generate_image: contextual illustrations, backgrounds, decorative graphics',
274
+ 'search_logos: brand marks, integration logos',
275
+ ],
276
+ gates: [
277
+ 'All generated images must fit the component layout without distortion.',
278
+ 'Imagery must support the content, not overwhelm it.',
279
+ ],
280
+ antiPatterns: [
281
+ 'Placeholder gray boxes or "image coming soon" text.',
282
+ 'Stock photo URLs that will 404.',
283
+ 'AI-generated faces presented as real people.',
284
+ ],
285
+ };
286
+ export function buildArtDirection(context) {
287
+ const key = context.trim().toLowerCase().replace(/[\s_-]+/g, '-');
288
+ const matchedKey = Object.keys(ENTRIES).find(k => key === k || key.includes(k) || k.includes(key));
289
+ const entry = matchedKey ? ENTRIES[matchedKey] : GENERAL;
290
+ const label = matchedKey ?? 'general';
291
+ const parts = [
292
+ `# Art Direction: ${label}`,
293
+ '',
294
+ '## Assets needed',
295
+ ...entry.assets.map(a => `- ${a}`),
296
+ '',
297
+ '## Generation hints',
298
+ ...entry.hints.map(h => `- ${h}`),
299
+ '',
300
+ '## Tools to use',
301
+ ...entry.tools.map(t => `- ${t}`),
302
+ '',
303
+ '## Quality gates',
304
+ ...entry.gates.map(g => `- ${g}`),
305
+ '',
306
+ '## Anti-patterns',
307
+ ...entry.antiPatterns.map(a => `- ${a}`),
308
+ '',
309
+ '---',
310
+ '**Workflow:** Design the layout FIRST → identify every image/graphic slot → generate assets with the tools above → wire assets into the component → verify_visual/screenshot_ui to confirm they render correctly.',
311
+ 'Generate assets BEFORE building the component, so you can size and position elements knowing the actual asset dimensions.',
312
+ 'If an image generation tool is unavailable, use a semantic placeholder (ak-surface-container with an icon) — but flag it as "needs real imagery" in your response.',
313
+ ];
314
+ return parts.join('\n');
315
+ }
316
+ //# sourceMappingURL=art-direction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"art-direction.js","sourceRoot":"","sources":["../../src/data/art-direction.ts"],"names":[],"mappings":"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"}
@@ -3,5 +3,5 @@
3
3
  * Returns the replacement string, or null if there's no confident mapping.
4
4
  */
5
5
  export declare function nearestToken(cls: string): string | null;
6
- export declare const CROSSWALK = "# Raw Tailwind \u2192 AstralKit Crosswalk (for tokenizing existing UI)\n\nWhen converting a non-AstralKit screen, replace raw Tailwind with the nearest `ak-*` token.\n(`validate_code` also returns the exact suggestion per flagged class \u2014 run it and apply each.)\n\n## Colors\n| Raw Tailwind | AstralKit |\n|---|---|\n| `bg-white`, `bg-gray-50` | `bg-ak-bg` |\n| `bg-gray-100` / `bg-gray-200` | `bg-ak-surface` / `bg-ak-surface-2` |\n| `bg-gray-800`/`-900`/`-950` (dark buttons) | `bg-ak-primary` (+ `hover:bg-ak-primary-hover`, `text-ak-on-primary`) |\n| `text-gray-900` / `-600,-500` / `-400` | `text-ak-text` / `text-ak-text-secondary` / `text-ak-text-muted` |\n| `border-gray-200`, `divide-gray-100` | `border-ak-border`, `divide-ak-border-subtle` |\n| green/emerald/teal `-500` / `-50` / `-700` | `ak-success` / `ak-success-subtle` / `ak-success-text` |\n| red/rose | `ak-danger` (+ `-subtle`/`-text`) |\n| amber/yellow/orange | `ak-warning` (+ `-subtle`/`-text`) |\n| blue/sky/cyan | `ak-info` (+ `-subtle`/`-text`) |\n| indigo/violet/purple (brand accent) | `ak-primary` (AstralKit's accent is monochrome by default \u2014 drop random purples/gradients) |\n\n## Spacing (Tailwind n \u2192 ak)\n`-2`\u2192`ak-1` \u00B7 `-3`\u2192`ak-1_5` \u00B7 `-4`\u2192`ak-2` \u00B7 `-5`\u2192`ak-2_5` \u00B7 `-6`\u2192`ak-3` \u00B7 `-8`\u2192`ak-4` \u00B7 `-10`\u2192`ak-5` \u00B7 `-12`\u2192`ak-6` \u00B7 `-16`\u2192`ak-8`\n(applies to `p* m* gap space-*`; e.g. `p-6`\u2192`p-ak-3`, `gap-4`\u2192`gap-ak-2`)\n\n## Radius / type\n`rounded-lg`\u2192`rounded-ak-lg`, `rounded-xl`\u2192`rounded-ak-xl`, `rounded-full`\u2192`rounded-ak-full` \u00B7 `text-sm`\u2192`text-ak-sm`, `text-2xl`\u2192`text-ak-2xl` (body stays `text-ak-base` min).\n\n## Also when tokenizing\n- Swap any icon library / inline `<svg>` UI icons \u2192 `@phosphor-icons/react` (confirm names via get_icons). Brand logos \u2192 search_logos.\n- Raise sub-16px body text to `text-ak-base`; add `focus-visible` rings and 48px touch targets.\n- Rebuild charts with the chart recipe (definite height + `ak-chart-*`). Add empty/loading/error states.\n";
6
+ export declare const CROSSWALK = "# Raw Tailwind \u2192 AstralKit Crosswalk (for tokenizing existing UI)\n\n**Tokenization = replacing Tailwind utility CLASSES on the JSX elements, NOT writing CSS.**\n\nWhen converting a non-AstralKit screen, replace raw Tailwind classes with the nearest `ak-*`\nutility class directly on the `className` attribute. (`validate_code` also returns the exact\nsuggestion per flagged class \u2014 run it and apply each.)\n\n## \uD83D\uDD34 What tokenization is NOT (the #1 mistake)\nTokenization is NOT writing CSS custom properties (`var(--color-ak-*)`, `var(--spacing-ak-*)`)\ninto a stylesheet. That creates a parallel styling system instead of using the library.\n\n```tsx\n// \u2705 CORRECT \u2014 utility class on the element\n<div className=\"bg-ak-surface p-ak-3 rounded-ak-lg border border-ak-border\">\n\n// \u274C WRONG \u2014 CSS custom property in a stylesheet (globals.css, page.css, etc.)\n// .my-card { background: var(--color-ak-surface); padding: var(--spacing-ak-3); }\n// This is NOT tokenization. This is writing raw CSS that happens to reference ak variables.\n```\n\n**Rules:**\n- NEVER create CSS/stylesheet files (.css) for tokenization \u2014 all styling belongs as\n Tailwind utility classes on the JSX `className`.\n- NEVER use `var(--color-ak-*)`, `var(--spacing-ak-*)`, `var(--radius-ak-*)`, etc. in\n stylesheets \u2014 use the Tailwind class (`bg-ak-surface`, `p-ak-3`, `rounded-ak-lg`).\n- NEVER add `!important` \u2014 if specificity is fighting you, you're in the wrong layer.\n- **When the source already has external stylesheets** (page.css, styles.css, component.css,\n or custom rules in globals.css): READ the stylesheet, EXTRACT each CSS property,\n FIND the equivalent `ak-*` utility class using this crosswalk, APPLY those classes\n to the JSX elements, then DELETE the stylesheet and remove its import. The goal is\n zero custom CSS for visual styling \u2014 all of it lives on `className`.\n- **globals.css should be minimal** \u2014 only AstralKit theme/utilities imports and, at most,\n a few lines of CSS variable overrides (`--color-ak-primary: ...`) to customize the\n palette. Component styling does NOT belong there.\n\n### CSS property \u2192 ak-* class quick-reference (for extracting from stylesheets)\n```\nbackground: var(--color-ak-surface) \u2192 bg-ak-surface\ncolor: var(--color-ak-text) \u2192 text-ak-text\nborder-color: var(--color-ak-border) \u2192 border-ak-border\npadding: var(--spacing-ak-3) \u2192 p-ak-3\ngap: var(--spacing-ak-2) \u2192 gap-ak-2\nborder-radius: var(--radius-ak-lg) \u2192 rounded-ak-lg\nfont-size: var(--text-ak-base) \u2192 text-ak-base\nfont-size: 16px / 1rem \u2192 text-ak-base\nfont-size: 14px / 0.875rem \u2192 text-ak-sm\nmin-height: 3rem / 48px \u2192 min-h-ak-control-lg\nwidth: 3rem / height: 3rem \u2192 size-ak-avatar-lg\n```\n\n## What properly tokenized code looks like\nAstralKit's own library components are the gold standard. In a properly tokenized file:\n- Every element's `className` uses `ak-*` tokens for ALL spacing, colors, radii, typography\n- There is NO external stylesheet \u2014 zero `.css` files for component styling\n- There are NO CSS custom property references (`var(--color-ak-*)`) outside `globals.css`\n- `globals.css` contains ONLY the theme/utilities imports and optional palette overrides\n- All visual nuance lives on the markup via utility classes \u2014 the code reads as a recipe\n\nExample of a properly tokenized stat card:\n```tsx\n<div className=\"rounded-ak-xl border border-ak-border bg-ak-elevated p-ak-3\">\n <p className=\"text-ak-xs font-medium uppercase tracking-ak-wide text-ak-text-secondary\">\n Total Revenue\n </p>\n <p className=\"mt-ak-1 text-ak-3xl font-bold text-ak-text tabular-nums\">$45,231</p>\n <span className=\"mt-ak-0_5 inline-flex rounded-ak-full bg-ak-success-subtle px-ak-1 py-ak-0_5 text-ak-xs font-semibold text-ak-success-text\">\n +20.1%\n </span>\n</div>\n```\n\nThis is the taste level: proper hierarchy (3xl value, xs label), the ak-* rhythm, semantic\nsurfaces and status colors, no raw Tailwind, no CSS file, no inline styles.\n\n### Example: extracting from an existing stylesheet\nIf the source has `import './card.css'` and `card.css` contains:\n```css\n.stat-card { background: #fff; border: 1px solid #e5e5e5; border-radius: 0.75rem; padding: 1rem; }\n.stat-label { font-size: 0.75rem; color: #737373; text-transform: uppercase; letter-spacing: 0.05em; }\n.stat-value { font-size: 1.5rem; font-weight: 700; color: #171717; }\n```\nThe correct tokenization is:\n1. Map each property \u2192 `bg-ak-elevated`, `border border-ak-border`, `rounded-ak-lg`, `p-ak-2`,\n `text-ak-xs text-ak-text-secondary uppercase tracking-ak-wide`, `text-ak-2xl font-bold text-ak-text`\n2. Apply those classes to the JSX elements that used `.stat-card`, `.stat-label`, `.stat-value`\n3. DELETE `card.css` and remove the `import './card.css'` line\n4. The result is zero CSS, all styling on `className`\n\n## Colors\n| Raw Tailwind | AstralKit |\n|---|---|\n| `bg-white`, `bg-gray-50` | `bg-ak-bg` |\n| `bg-black` | `bg-ak-inverse-surface` |\n| `text-white` | `text-ak-text-inverse` |\n| `text-black` | `text-ak-text` |\n| `bg-gray-100` / `bg-gray-200` | `bg-ak-surface` / `bg-ak-surface-2` |\n| `bg-gray-800`/`-900`/`-950` (dark buttons) | `bg-ak-primary` (+ `hover:bg-ak-primary-hover`, `text-ak-on-primary`) |\n| `text-gray-900` / `-600,-500` / `-400` | `text-ak-text` / `text-ak-text-secondary` / `text-ak-text-muted` |\n| `border-gray-200`, `divide-gray-100` | `border-ak-border`, `divide-ak-border-subtle` |\n| green/emerald/teal `-500` / `-50` / `-700` | `ak-success` / `ak-success-subtle` / `ak-success-text` |\n| red/rose | `ak-danger` (+ `-subtle`/`-text`) |\n| amber/yellow/orange | `ak-warning` (+ `-subtle`/`-text`) |\n| blue/sky/cyan | `ak-info` (+ `-subtle`/`-text`) |\n| indigo/violet/purple (brand accent) | `ak-primary` (AstralKit's accent is monochrome by default \u2014 drop random purples/gradients) |\n\n## Spacing (Tailwind n \u2192 ak)\n`-2`\u2192`ak-1` \u00B7 `-3`\u2192`ak-1_5` \u00B7 `-4`\u2192`ak-2` \u00B7 `-5`\u2192`ak-2_5` \u00B7 `-6`\u2192`ak-3` \u00B7 `-8`\u2192`ak-4` \u00B7 `-10`\u2192`ak-5` \u00B7 `-12`\u2192`ak-6` \u00B7 `-16`\u2192`ak-8`\n(applies to `p* m* gap space-*`; e.g. `p-6`\u2192`p-ak-3`, `gap-4`\u2192`gap-ak-2`)\n\n## Radius / type\n`rounded-lg`\u2192`rounded-ak-lg`, `rounded-xl`\u2192`rounded-ak-xl`, `rounded-full`\u2192`rounded-ak-full` \u00B7 `text-sm`\u2192`text-ak-sm`, `text-2xl`\u2192`text-ak-2xl` (body stays `text-ak-base` min).\n\n## Also when tokenizing\n- ALL styling goes on `className` \u2014 never write component styling to globals.css, page.css,\n or any stylesheet. If the source has external stylesheets with visual rules, EXTRACT the\n properties, CONVERT each to the nearest `ak-*` utility class, APPLY them to the JSX\n elements, DELETE the stylesheet file, and remove the import. globals.css keeps only the\n theme/utilities imports + optional palette overrides.\n- Swap any icon library / inline `<svg>` UI icons \u2192 `@phosphor-icons/react` (confirm names via get_icons). Brand logos \u2192 search_logos.\n- Raise sub-16px body text to `text-ak-base`; add `focus-visible` rings and 48px touch targets.\n- Rebuild charts with the chart recipe (definite height + `ak-chart-*`). Add empty/loading/error states.\n\n## Dark mode\nAstralKit themes are structural \u2014 set `data-ak-theme=\"dark\"` on the root (or a section)\nand the SAME semantic tokens flip to dark values automatically. You do NOT need a separate\ndark-mode crosswalk:\n| Token | Light | Dark |\n|---|---|---|\n| `bg-ak-bg` | near-white | near-black |\n| `bg-ak-surface` | light gray | dark gray |\n| `text-ak-text` | near-black | near-white |\n| `border-ak-border` | light gray | dark gray |\nThe mapping is the same: `bg-gray-50` \u2192 `bg-ak-bg` whether the source is a light or dark\napp. The theme attribute does the flipping. **PRESERVE the source theme** \u2014 if the app is dark,\nset `data-ak-theme=\"dark\"` and use the same semantic tokens (they auto-adapt). Never map a\ndark source to light tokens; that breaks the design.\n\n## CSS Modules (`*.module.css`)\nTreat CSS modules exactly like any other stylesheet: READ the file, EXTRACT each CSS property,\nFIND the equivalent `ak-*` utility class, APPLY the classes to the JSX elements, DELETE the\n`.module.css` file, and remove the import + all `styles.*` references. Replace\n`className={styles.card}` with `className=\"bg-ak-elevated rounded-ak-xl ...\"`.\n\n## `@apply` directives\nIf the source uses `@apply` in CSS (e.g. `@apply p-4 bg-white rounded-lg`), extract the\nutilities listed, convert each to its `ak-*` equivalent, apply them to the JSX `className`,\nand delete the CSS rule. NEVER convert `@apply p-4` to `@apply p-ak-2` \u2014 the goal is zero\nCSS for component styling. All styling belongs on the element's `className`.\n";
7
7
  //# sourceMappingURL=crosswalk.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"crosswalk.d.ts","sourceRoot":"","sources":["../../src/data/crosswalk.ts"],"names":[],"mappings":"AA8BA;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAoCvD;AAED,eAAO,MAAM,SAAS,okEA8BrB,CAAC"}
1
+ {"version":3,"file":"crosswalk.d.ts","sourceRoot":"","sources":["../../src/data/crosswalk.ts"],"names":[],"mappings":"AA0CA;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAuCvD;AAED,eAAO,MAAM,SAAS,y1RAqJrB,CAAC"}