@bitmagic/cli 0.1.41 → 0.1.42

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.
@@ -10,8 +10,13 @@
10
10
  * Same template-literal rules as its host: **no backticks**, and a backslash in a regex has to be
11
11
  * doubled to survive the literal.
12
12
  */
13
- /** Styles for `#asset-overlay`, appended to the shell's stylesheet. */
14
- export declare const ASSET_DETAIL_CSS = "\n /* Modelled on #hq-overlay, deliberately: the dev view has one modal idiom and this is it. */\n #asset-overlay { display: none; position: fixed; inset: 0; background: rgba(8,8,12,.78);\n align-items: center; justify-content: center; z-index: 11; }\n #asset-overlay.show { display: flex; }\n #asset-dialog { display: flex; width: min(1100px, 94vw); height: min(760px, 88vh);\n background: #17171d; border: 1px solid #34343f; border-radius: 8px;\n overflow: hidden; }\n /* The viewer takes the room. Everything else is a caption. */\n #asset-view { flex: 1; min-width: 0; position: relative; background: #1e293b; }\n #asset-view iframe { display: block; width: 100%; height: 100%; border: 0; }\n #asset-view img { display: block; width: 100%; height: 100%; object-fit: contain;\n background: #101014; }\n #asset-view audio { position: absolute; left: 50%; top: 50%; width: min(420px, 80%);\n transform: translate(-50%, -50%); }\n #asset-note { position: absolute; inset: auto 0 0 0; padding: 10px 12px; background: #101014e6;\n color: #e0938e; font-size: 12px; }\n #asset-note.hidden, #asset-view > .hidden { display: none; }\n #asset-meta { width: 268px; flex: none; padding: 14px; overflow-y: auto;\n border-left: 1px solid #26262e; }\n #asset-meta h2 { margin: 0 0 2px; font-size: 15px; word-break: break-word; }\n #asset-meta .sub { color: #6a6a7a; font-size: 11px; margin-bottom: 12px; }\n #asset-facts { display: grid; grid-template-columns: auto 1fr; gap: 4px 10px; font-size: 12px; }\n #asset-facts dt { color: #6a6a7a; }\n #asset-facts dd { margin: 0; color: #d9d9e2; word-break: break-word; }\n #asset-facts dd.mono { font-family: ui-monospace, monospace; font-size: 11px; }\n #asset-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }\n #asset-close { margin-left: auto; }\n";
13
+ /**
14
+ * Styles for `#asset-overlay`, appended to the shell's stylesheet.
15
+ *
16
+ * The surface, the pills and the modal backdrop come from `design.ts` (`.bm-overlay`,
17
+ * `.bm-dialog`, `.bm-pill`); only what is specific to this dialog's layout lives here.
18
+ */
19
+ export declare const ASSET_DETAIL_CSS = "\n /* Above #hq-overlay, which sits at 10 \u2014 a preview opened from a row must cover it. */\n #asset-overlay { z-index: 11; }\n #asset-dialog { display: flex; width: min(1100px, 94vw); height: min(760px, 88vh);\n overflow: hidden; }\n /* The viewer takes the room. Everything else is a caption. The near-black ground is the\n brand's: a creation is the only thing on this surface that carries colour. */\n #asset-view { flex: 1; min-width: 0; position: relative; background: var(--bm-bg); }\n #asset-view iframe { display: block; width: 100%; height: 100%; border: 0; }\n #asset-view img { display: block; width: 100%; height: 100%; object-fit: contain;\n background: var(--bm-bg); }\n #asset-view audio { position: absolute; left: 50%; top: 50%; width: min(420px, 80%);\n transform: translate(-50%, -50%); }\n /* A note here is always a failure or a wait that has gone on too long \u2014 the negative accent. */\n #asset-note { position: absolute; inset: auto 0 0 0; padding: 10px 12px;\n background: var(--bm-scrim); color: var(--bm-pink-hover); font-size: 12px; }\n #asset-note.hidden, #asset-view > .hidden { display: none; }\n /* Wide enough for the three action pills to sit on one row: uppercase tracked labels are\n wider than the sentence-case ones this panel used to have. */\n #asset-meta { width: 360px; flex: none; padding: 16px; overflow-y: auto;\n border-left: 1px solid var(--bm-border-muted); }\n #asset-meta h2 { margin: 0 0 4px; word-break: break-word; }\n #asset-meta .sub { color: var(--bm-text-dim); font-size: 12px; margin-bottom: 16px; }\n #asset-facts { display: grid; grid-template-columns: auto 1fr; gap: 6px 12px; font-size: 12px; }\n #asset-facts dt { color: var(--bm-text-dim); }\n #asset-facts dd { margin: 0; color: var(--bm-text); word-break: break-word; }\n #asset-facts dd.mono { font-family: var(--bm-font-mono); }\n #asset-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 16px; }\n #asset-close { margin-left: auto; }\n";
15
20
  /**
16
21
  * The overlay itself.
17
22
  *
@@ -19,4 +24,4 @@ export declare const ASSET_DETAIL_CSS = "\n /* Modelled on #hq-overlay, deliber
19
24
  * controls because its player sits in a 46px row, and here there is a whole dialog. A creator
20
25
  * checking a sound effect wants the scrubber.
21
26
  */
22
- export declare const ASSET_DETAIL_HTML = "\n <div id=\"asset-overlay\">\n <div id=\"asset-dialog\">\n <div id=\"asset-view\">\n <iframe id=\"asset-frame\" class=\"hidden\" title=\"Asset preview\"></iframe>\n <img id=\"asset-image\" class=\"hidden\" alt=\"\">\n <audio id=\"asset-audio\" class=\"hidden\" controls preload=\"none\"></audio>\n <div id=\"asset-note\" class=\"hidden\"></div>\n </div>\n <aside id=\"asset-meta\">\n <h2 id=\"asset-name\"></h2>\n <div class=\"sub\" id=\"asset-sub\"></div>\n <dl id=\"asset-facts\"></dl>\n <div id=\"asset-actions\">\n <button id=\"asset-reset\" type=\"button\" title=\"Back to the angle the thumbnail uses\">Reset view</button>\n <button id=\"asset-copy\" type=\"button\" title=\"Copy this asset's id\">Copy id</button>\n <button id=\"asset-close\" type=\"button\">Close</button>\n </div>\n </aside>\n </div>\n </div>\n";
27
+ export declare const ASSET_DETAIL_HTML = "\n <div id=\"asset-overlay\" class=\"bm-overlay\">\n <div id=\"asset-dialog\" class=\"bm-dialog\">\n <div id=\"asset-view\">\n <iframe id=\"asset-frame\" class=\"hidden\" title=\"Asset preview\"></iframe>\n <img id=\"asset-image\" class=\"hidden\" alt=\"\">\n <audio id=\"asset-audio\" class=\"hidden\" controls preload=\"none\"></audio>\n <div id=\"asset-note\" class=\"hidden\"></div>\n </div>\n <aside id=\"asset-meta\">\n <h2 id=\"asset-name\"></h2>\n <div class=\"sub\" id=\"asset-sub\"></div>\n <dl id=\"asset-facts\"></dl>\n <div id=\"asset-actions\">\n <button id=\"asset-reset\" class=\"bm-pill\" type=\"button\" title=\"Back to the angle the thumbnail uses\">Reset view</button>\n <button id=\"asset-copy\" class=\"bm-pill\" type=\"button\" title=\"Copy this asset's id\">Copy id</button>\n <button id=\"asset-close\" class=\"bm-pill bm-pill--ghost\" type=\"button\">Close</button>\n </div>\n </aside>\n </div>\n </div>\n";
@@ -10,34 +10,40 @@
10
10
  * Same template-literal rules as its host: **no backticks**, and a backslash in a regex has to be
11
11
  * doubled to survive the literal.
12
12
  */
13
- /** Styles for `#asset-overlay`, appended to the shell's stylesheet. */
13
+ /**
14
+ * Styles for `#asset-overlay`, appended to the shell's stylesheet.
15
+ *
16
+ * The surface, the pills and the modal backdrop come from `design.ts` (`.bm-overlay`,
17
+ * `.bm-dialog`, `.bm-pill`); only what is specific to this dialog's layout lives here.
18
+ */
14
19
  export const ASSET_DETAIL_CSS = `
15
- /* Modelled on #hq-overlay, deliberately: the dev view has one modal idiom and this is it. */
16
- #asset-overlay { display: none; position: fixed; inset: 0; background: rgba(8,8,12,.78);
17
- align-items: center; justify-content: center; z-index: 11; }
18
- #asset-overlay.show { display: flex; }
20
+ /* Above #hq-overlay, which sits at 10 a preview opened from a row must cover it. */
21
+ #asset-overlay { z-index: 11; }
19
22
  #asset-dialog { display: flex; width: min(1100px, 94vw); height: min(760px, 88vh);
20
- background: #17171d; border: 1px solid #34343f; border-radius: 8px;
21
23
  overflow: hidden; }
22
- /* The viewer takes the room. Everything else is a caption. */
23
- #asset-view { flex: 1; min-width: 0; position: relative; background: #1e293b; }
24
+ /* The viewer takes the room. Everything else is a caption. The near-black ground is the
25
+ brand's: a creation is the only thing on this surface that carries colour. */
26
+ #asset-view { flex: 1; min-width: 0; position: relative; background: var(--bm-bg); }
24
27
  #asset-view iframe { display: block; width: 100%; height: 100%; border: 0; }
25
28
  #asset-view img { display: block; width: 100%; height: 100%; object-fit: contain;
26
- background: #101014; }
29
+ background: var(--bm-bg); }
27
30
  #asset-view audio { position: absolute; left: 50%; top: 50%; width: min(420px, 80%);
28
31
  transform: translate(-50%, -50%); }
29
- #asset-note { position: absolute; inset: auto 0 0 0; padding: 10px 12px; background: #101014e6;
30
- color: #e0938e; font-size: 12px; }
32
+ /* A note here is always a failure or a wait that has gone on too long — the negative accent. */
33
+ #asset-note { position: absolute; inset: auto 0 0 0; padding: 10px 12px;
34
+ background: var(--bm-scrim); color: var(--bm-pink-hover); font-size: 12px; }
31
35
  #asset-note.hidden, #asset-view > .hidden { display: none; }
32
- #asset-meta { width: 268px; flex: none; padding: 14px; overflow-y: auto;
33
- border-left: 1px solid #26262e; }
34
- #asset-meta h2 { margin: 0 0 2px; font-size: 15px; word-break: break-word; }
35
- #asset-meta .sub { color: #6a6a7a; font-size: 11px; margin-bottom: 12px; }
36
- #asset-facts { display: grid; grid-template-columns: auto 1fr; gap: 4px 10px; font-size: 12px; }
37
- #asset-facts dt { color: #6a6a7a; }
38
- #asset-facts dd { margin: 0; color: #d9d9e2; word-break: break-word; }
39
- #asset-facts dd.mono { font-family: ui-monospace, monospace; font-size: 11px; }
40
- #asset-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }
36
+ /* Wide enough for the three action pills to sit on one row: uppercase tracked labels are
37
+ wider than the sentence-case ones this panel used to have. */
38
+ #asset-meta { width: 360px; flex: none; padding: 16px; overflow-y: auto;
39
+ border-left: 1px solid var(--bm-border-muted); }
40
+ #asset-meta h2 { margin: 0 0 4px; word-break: break-word; }
41
+ #asset-meta .sub { color: var(--bm-text-dim); font-size: 12px; margin-bottom: 16px; }
42
+ #asset-facts { display: grid; grid-template-columns: auto 1fr; gap: 6px 12px; font-size: 12px; }
43
+ #asset-facts dt { color: var(--bm-text-dim); }
44
+ #asset-facts dd { margin: 0; color: var(--bm-text); word-break: break-word; }
45
+ #asset-facts dd.mono { font-family: var(--bm-font-mono); }
46
+ #asset-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 16px; }
41
47
  #asset-close { margin-left: auto; }
42
48
  `;
43
49
  /**
@@ -48,8 +54,8 @@ export const ASSET_DETAIL_CSS = `
48
54
  * checking a sound effect wants the scrubber.
49
55
  */
50
56
  export const ASSET_DETAIL_HTML = `
51
- <div id="asset-overlay">
52
- <div id="asset-dialog">
57
+ <div id="asset-overlay" class="bm-overlay">
58
+ <div id="asset-dialog" class="bm-dialog">
53
59
  <div id="asset-view">
54
60
  <iframe id="asset-frame" class="hidden" title="Asset preview"></iframe>
55
61
  <img id="asset-image" class="hidden" alt="">
@@ -61,9 +67,9 @@ export const ASSET_DETAIL_HTML = `
61
67
  <div class="sub" id="asset-sub"></div>
62
68
  <dl id="asset-facts"></dl>
63
69
  <div id="asset-actions">
64
- <button id="asset-reset" type="button" title="Back to the angle the thumbnail uses">Reset view</button>
65
- <button id="asset-copy" type="button" title="Copy this asset's id">Copy id</button>
66
- <button id="asset-close" type="button">Close</button>
70
+ <button id="asset-reset" class="bm-pill" type="button" title="Back to the angle the thumbnail uses">Reset view</button>
71
+ <button id="asset-copy" class="bm-pill" type="button" title="Copy this asset's id">Copy id</button>
72
+ <button id="asset-close" class="bm-pill bm-pill--ghost" type="button">Close</button>
67
73
  </div>
68
74
  </aside>
69
75
  </div>
@@ -1 +1 @@
1
- {"version":3,"file":"asset-detail-panel.js","sourceRoot":"","sources":["../../src/editor/asset-detail-panel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,uEAAuE;AACvE,MAAM,CAAC,MAAM,gBAAgB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4B/B,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG;;;;;;;;;;;;;;;;;;;;;CAqBhC,CAAC"}
1
+ {"version":3,"file":"asset-detail-panel.js","sourceRoot":"","sources":["../../src/editor/asset-detail-panel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6B/B,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG;;;;;;;;;;;;;;;;;;;;;CAqBhC,CAAC"}
@@ -18,6 +18,7 @@
18
18
  */
19
19
  import { CDN_IMPORTS } from '../scaffold/project-files.js';
20
20
  import { importMapEntries } from '../scaffold/aliases.js';
21
+ import { BITMAGIC_FONT_LINK, BITMAGIC_TOKENS_CSS } from './design.js';
21
22
  /** Attribute- and script-safe: these land inside a `<script type="importmap">` block. */
22
23
  function importMapFor(gamePort) {
23
24
  const origin = `http://localhost:${gamePort}`;
@@ -31,17 +32,25 @@ export function renderAssetPreviewPage(options) {
31
32
  <head>
32
33
  <meta charset="utf-8">
33
34
  <title>Asset preview</title>
35
+ ${BITMAGIC_FONT_LINK}
34
36
  <style>
35
- html, body { margin: 0; height: 100%; background: #1e293b; overflow: hidden;
36
- font: 12px/1.5 system-ui, -apple-system, sans-serif; color: #c8c8d4; }
37
+ ${BITMAGIC_TOKENS_CSS}
38
+ /* The ground before the canvas exists, and the type over it once it does. Brand near-black, so
39
+ a viewer that is still loading looks like part of the dialog around it rather than a blank
40
+ window. The RENDER surface stays the slate asset-viewer.ts clears to — that is the colour the
41
+ engine bakes the thumbnails on, and a tile and its preview must not disagree. */
42
+ html, body { margin: 0; height: 100%; background: var(--bm-bg); overflow: hidden;
43
+ font: 400 12px/1.5 var(--bm-font); color: var(--bm-text-muted); }
37
44
  #stage { position: absolute; inset: 0; }
38
45
  #stage canvas { display: block; width: 100%; height: 100%; }
39
46
  /* Sits over the canvas rather than beside it: the dialog gives this iframe every pixel, and a
40
47
  status line that reserved space would shrink the thing being looked at. */
41
- #status { position: absolute; left: 0; right: 0; top: 0; padding: 10px 12px;
42
- background: linear-gradient(#1e293bcc, #1e293b00); pointer-events: none; }
43
- #status.failed { color: #e0938e; }
44
- #hint { position: absolute; left: 12px; bottom: 10px; color: #7d8595; pointer-events: none; }
48
+ #status { position: absolute; left: 0; right: 0; top: 0; padding: 12px;
49
+ background: linear-gradient(var(--bm-scrim), transparent);
50
+ pointer-events: none; }
51
+ #status.failed { color: var(--bm-pink-hover); }
52
+ #hint { position: absolute; left: 12px; bottom: 12px; color: var(--bm-text-dim);
53
+ pointer-events: none; }
45
54
  #hint.hidden, #status.hidden { display: none; }
46
55
  </style>
47
56
  </head>
@@ -1 +1 @@
1
- {"version":3,"file":"asset-preview-page.js","sourceRoot":"","sources":["../../src/editor/asset-preview-page.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAQ1D,yFAAyF;AACzF,SAAS,YAAY,CAAC,QAAgB;IACpC,MAAM,MAAM,GAAG,oBAAoB,QAAQ,EAAE,CAAC;IAC9C,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,CAC/B,MAAM,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,GAAG,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC,CACzF,CAAC;IACF,OAAO,EAAE,GAAG,WAAW,EAAE,GAAG,MAAM,EAAE,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,OAAgC;IACrE,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACrF,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;EAyBP,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+CR,CAAC;AACF,CAAC"}
1
+ {"version":3,"file":"asset-preview-page.js","sourceRoot":"","sources":["../../src/editor/asset-preview-page.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAQtE,yFAAyF;AACzF,SAAS,YAAY,CAAC,QAAgB;IACpC,MAAM,MAAM,GAAG,oBAAoB,QAAQ,EAAE,CAAC;IAC9C,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,CAC/B,MAAM,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,GAAG,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC,CACzF,CAAC;IACF,OAAO,EAAE,GAAG,WAAW,EAAE,GAAG,MAAM,EAAE,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,OAAgC;IACrE,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACrF,OAAO;;;;;EAKP,kBAAkB;;EAElB,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;EA0BnB,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+CR,CAAC;AACF,CAAC"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * The Bitmagic design system, for the pages `bitmagic dev` serves.
3
+ *
4
+ * The dev view is a Bitmagic product surface — for a pro-lane creator it is the only one they ever
5
+ * look at — so it follows `creator/DESIGN.md` the way the Creator and the in-engine editor do.
6
+ * It cannot import the Creator's `BitmagicDesign.css`: this package ships on npm on its own, and
7
+ * both pages are strings assembled in TypeScript rather than bundled documents. So it re-declares
8
+ * the same tokens, exactly as `game/src/editor/editor-styles.ts` does for the engine's editor
9
+ * dialogs — three copies of the palette, one source of truth in DESIGN.md.
10
+ *
11
+ * **No backticks in anything exported here.** These constants are interpolated into the pages'
12
+ * template literals, and a backtick would end the literal somewhere else entirely (there is a test
13
+ * for it: `__tests__/shell-page.test.ts`).
14
+ */
15
+ /** Hex tokens for TS-side use — the same set `game/src/editor/editor-styles.ts` exposes. */
16
+ export declare const BM: {
17
+ readonly bg: "#0b0b0b";
18
+ readonly surface: "#181818";
19
+ readonly surfaceAlt: "#1f1f1f";
20
+ readonly surfaceCard: "#252525";
21
+ readonly textPrimary: "#ffffff";
22
+ readonly textMuted: "#b3b3b3";
23
+ readonly textDim: "#7c7c7c";
24
+ readonly textOnAccent: "#000000";
25
+ readonly border: "#4d4d4d";
26
+ readonly borderMuted: "#2a2a2a";
27
+ readonly aqua: "#A0DAB9";
28
+ readonly aquaHover: "#B8E4CA";
29
+ readonly aquaPressed: "#7DC29C";
30
+ readonly pink: "#E0218A";
31
+ readonly pinkHover: "#F04AA4";
32
+ readonly pinkPressed: "#B3176D";
33
+ readonly pumpkin: "#FF8200";
34
+ readonly canary: "#F9E547";
35
+ readonly shadowDialog: "0 8px 24px rgba(0, 0, 0, 0.5)";
36
+ readonly shadowCard: "0 8px 8px rgba(0, 0, 0, 0.3)";
37
+ readonly glowAqua: "0 0 24px rgba(160, 218, 185, 0.45)";
38
+ readonly glowPink: "0 0 24px rgba(224, 33, 138, 0.4)";
39
+ readonly insetBorderDim: "inset 0 0 0 1px #7c7c7c";
40
+ readonly insetBorderFocus: "inset 0 0 0 1px #ffffff, 0 0 0 2px rgba(160, 218, 185, 0.45)";
41
+ readonly font: "\"Red Hat Display\", \"Helvetica Neue\", Helvetica, Arial, system-ui, sans-serif";
42
+ readonly fontMono: "ui-monospace, SFMono-Regular, Menlo, monospace";
43
+ };
44
+ /**
45
+ * Red Hat Display, from the same Google Fonts URL `creator/index.html` uses.
46
+ *
47
+ * A dev machine with no network gets the fallback stack and a page that is otherwise identical —
48
+ * every rule below sizes and weights type rather than depending on the family's metrics.
49
+ */
50
+ export declare const BITMAGIC_FONT_LINK = "<link rel=\"preconnect\" href=\"https://fonts.googleapis.com\">\n<link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin>\n<link rel=\"stylesheet\" href=\"https://fonts.googleapis.com/css2?family=Red+Hat+Display:wght@300;400;500;700&display=swap\">";
51
+ /** The palette as custom properties, so page-specific rules can `var(--bm-*)` them. */
52
+ export declare const BITMAGIC_TOKENS_CSS: string;
53
+ /**
54
+ * The component primitives both served pages use: pill buttons, inputs, badges, modal surfaces.
55
+ *
56
+ * Label voice is UPPERCASE Bold with tracking and content voice is sentence-case Regular, per the
57
+ * brand type guideline — which is why every button here is uppercase and nothing else is.
58
+ */
59
+ export declare const BITMAGIC_CONTROLS_CSS: string;
@@ -0,0 +1,217 @@
1
+ /**
2
+ * The Bitmagic design system, for the pages `bitmagic dev` serves.
3
+ *
4
+ * The dev view is a Bitmagic product surface — for a pro-lane creator it is the only one they ever
5
+ * look at — so it follows `creator/DESIGN.md` the way the Creator and the in-engine editor do.
6
+ * It cannot import the Creator's `BitmagicDesign.css`: this package ships on npm on its own, and
7
+ * both pages are strings assembled in TypeScript rather than bundled documents. So it re-declares
8
+ * the same tokens, exactly as `game/src/editor/editor-styles.ts` does for the engine's editor
9
+ * dialogs — three copies of the palette, one source of truth in DESIGN.md.
10
+ *
11
+ * **No backticks in anything exported here.** These constants are interpolated into the pages'
12
+ * template literals, and a backtick would end the literal somewhere else entirely (there is a test
13
+ * for it: `__tests__/shell-page.test.ts`).
14
+ */
15
+ /** Hex tokens for TS-side use — the same set `game/src/editor/editor-styles.ts` exposes. */
16
+ export const BM = {
17
+ bg: '#0b0b0b',
18
+ surface: '#181818',
19
+ surfaceAlt: '#1f1f1f',
20
+ surfaceCard: '#252525',
21
+ textPrimary: '#ffffff',
22
+ textMuted: '#b3b3b3',
23
+ textDim: '#7c7c7c',
24
+ textOnAccent: '#000000',
25
+ border: '#4d4d4d',
26
+ borderMuted: '#2a2a2a',
27
+ aqua: '#A0DAB9',
28
+ aquaHover: '#B8E4CA',
29
+ aquaPressed: '#7DC29C',
30
+ pink: '#E0218A',
31
+ pinkHover: '#F04AA4',
32
+ pinkPressed: '#B3176D',
33
+ pumpkin: '#FF8200',
34
+ canary: '#F9E547',
35
+ shadowDialog: '0 8px 24px rgba(0, 0, 0, 0.5)',
36
+ shadowCard: '0 8px 8px rgba(0, 0, 0, 0.3)',
37
+ glowAqua: '0 0 24px rgba(160, 218, 185, 0.45)',
38
+ glowPink: '0 0 24px rgba(224, 33, 138, 0.4)',
39
+ insetBorderDim: 'inset 0 0 0 1px #7c7c7c',
40
+ insetBorderFocus: 'inset 0 0 0 1px #ffffff, 0 0 0 2px rgba(160, 218, 185, 0.45)',
41
+ font: '"Red Hat Display", "Helvetica Neue", Helvetica, Arial, system-ui, sans-serif',
42
+ fontMono: 'ui-monospace, SFMono-Regular, Menlo, monospace',
43
+ };
44
+ /**
45
+ * Red Hat Display, from the same Google Fonts URL `creator/index.html` uses.
46
+ *
47
+ * A dev machine with no network gets the fallback stack and a page that is otherwise identical —
48
+ * every rule below sizes and weights type rather than depending on the family's metrics.
49
+ */
50
+ export const BITMAGIC_FONT_LINK = `<link rel="preconnect" href="https://fonts.googleapis.com">
51
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
52
+ <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Red+Hat+Display:wght@300;400;500;700&display=swap">`;
53
+ /** The palette as custom properties, so page-specific rules can `var(--bm-*)` them. */
54
+ export const BITMAGIC_TOKENS_CSS = `
55
+ :root {
56
+ color-scheme: dark;
57
+ --bm-bg: ${BM.bg};
58
+ --bm-surface: ${BM.surface};
59
+ --bm-surface-alt: ${BM.surfaceAlt};
60
+ --bm-surface-card: ${BM.surfaceCard};
61
+ --bm-text: ${BM.textPrimary};
62
+ --bm-text-muted: ${BM.textMuted};
63
+ --bm-text-dim: ${BM.textDim};
64
+ --bm-border: ${BM.border};
65
+ --bm-border-muted: ${BM.borderMuted};
66
+ --bm-aqua: ${BM.aqua};
67
+ --bm-aqua-hover: ${BM.aquaHover};
68
+ --bm-pink: ${BM.pink};
69
+ --bm-pink-hover: ${BM.pinkHover};
70
+ --bm-pumpkin: ${BM.pumpkin};
71
+ --bm-canary: ${BM.canary};
72
+ /* Accent washes. An accent at full strength behind body copy would be a coloured surface,
73
+ which DESIGN.md does not do — these are the same five accents at banner strength. */
74
+ --bm-tint-warning: rgba(255, 130, 0, .12);
75
+ --bm-tint-negative: rgba(224, 33, 138, .12);
76
+ --bm-tint-success: rgba(160, 218, 185, .18);
77
+ --bm-scrim: rgba(11, 11, 11, .78);
78
+ --bm-shadow-dialog: ${BM.shadowDialog};
79
+ --bm-shadow-card: ${BM.shadowCard};
80
+ --bm-glow-aqua: ${BM.glowAqua};
81
+ --bm-glow-pink: ${BM.glowPink};
82
+ --bm-font: ${BM.font};
83
+ --bm-font-mono: ${BM.fontMono};
84
+ }
85
+ `;
86
+ /**
87
+ * The component primitives both served pages use: pill buttons, inputs, badges, modal surfaces.
88
+ *
89
+ * Label voice is UPPERCASE Bold with tracking and content voice is sentence-case Regular, per the
90
+ * brand type guideline — which is why every button here is uppercase and nothing else is.
91
+ */
92
+ export const BITMAGIC_CONTROLS_CSS = `
93
+ /* === Pill buttons =========================================================================
94
+ Secondary dark pill is the default: the toolbar is chrome, and DESIGN.md allows one primary
95
+ accent per screen. Aquamarine is spent on the active tab and on a dialog's confirm. */
96
+ .bm-pill {
97
+ background: var(--bm-surface-alt);
98
+ color: var(--bm-text);
99
+ border: 1px solid var(--bm-border);
100
+ border-radius: 9999px;
101
+ padding: 5px 14px;
102
+ font-family: var(--bm-font);
103
+ font-size: 12px;
104
+ font-weight: 700;
105
+ line-height: 1;
106
+ text-transform: uppercase;
107
+ letter-spacing: 1.4px;
108
+ cursor: pointer;
109
+ transition: background .15s ease, border-color .15s ease, color .15s ease,
110
+ box-shadow .15s ease, transform .15s ease;
111
+ }
112
+ .bm-pill:hover:not(:disabled) { background: var(--bm-surface-card); border-color: var(--bm-text-dim); }
113
+ .bm-pill:focus-visible { outline: none; box-shadow: 0 0 0 2px rgba(160, 218, 185, .45); }
114
+ .bm-pill:disabled { opacity: .5; cursor: default; }
115
+
116
+ /* Primary — the one creative action on a surface. Dark text: DESIGN.md forbids white on the
117
+ lighter accents. */
118
+ .bm-pill--primary {
119
+ background: var(--bm-aqua);
120
+ border-color: var(--bm-aqua);
121
+ color: #000000;
122
+ letter-spacing: 1.6px;
123
+ padding: 7px 20px;
124
+ }
125
+ .bm-pill--primary:hover:not(:disabled) {
126
+ background: var(--bm-aqua-hover);
127
+ border-color: var(--bm-aqua-hover);
128
+ transform: scale(1.03);
129
+ box-shadow: var(--bm-glow-aqua);
130
+ }
131
+
132
+ /* Destructive — Shocking Pink, and only ever for discard / delete / reset. */
133
+ .bm-pill--destructive {
134
+ background: var(--bm-pink);
135
+ border-color: var(--bm-pink);
136
+ color: var(--bm-text);
137
+ letter-spacing: 1.6px;
138
+ }
139
+ .bm-pill--destructive:hover:not(:disabled) {
140
+ background: var(--bm-pink-hover);
141
+ border-color: var(--bm-pink-hover);
142
+ transform: scale(1.03);
143
+ box-shadow: var(--bm-glow-pink);
144
+ }
145
+
146
+ /* Outlined — tertiary ("Cancel", "Close"). */
147
+ .bm-pill--ghost { background: transparent; border-color: var(--bm-text-dim); color: var(--bm-text-muted); }
148
+ .bm-pill--ghost:hover:not(:disabled) { background: transparent; border-color: var(--bm-text); color: var(--bm-text); }
149
+
150
+ /* === Input ================================================================================ */
151
+ .bm-input {
152
+ background: var(--bm-surface-alt);
153
+ color: var(--bm-text);
154
+ border: none;
155
+ box-shadow: ${BM.insetBorderDim};
156
+ border-radius: 6px;
157
+ padding: 10px 12px;
158
+ font-family: var(--bm-font);
159
+ font-size: 14px;
160
+ outline: none;
161
+ }
162
+ .bm-input:focus { box-shadow: ${BM.insetBorderFocus}; }
163
+ .bm-input::placeholder { color: var(--bm-text-muted); }
164
+
165
+ /* === Badge ================================================================================ */
166
+ .bm-badge {
167
+ display: inline-block;
168
+ border-radius: 9999px;
169
+ padding: 1px 7px;
170
+ font-size: 10.5px;
171
+ font-weight: 700;
172
+ line-height: 1.33;
173
+ text-transform: uppercase;
174
+ letter-spacing: 1.4px;
175
+ vertical-align: 1px;
176
+ background: var(--bm-surface-card);
177
+ color: var(--bm-text-muted);
178
+ }
179
+ /* Success / featured, and warning. Never both on one row — an asset is one or the other. */
180
+ .bm-badge--success { background: var(--bm-aqua); color: #000000; }
181
+ .bm-badge--warning { background: var(--bm-pumpkin); color: #000000; }
182
+
183
+ /* === Label voice ==========================================================================
184
+ Section headers and anything else speaking as a label rather than as content. */
185
+ .bm-label {
186
+ font-size: 12px;
187
+ font-weight: 700;
188
+ text-transform: uppercase;
189
+ letter-spacing: 1.4px;
190
+ color: var(--bm-text-muted);
191
+ }
192
+
193
+ /* === Modal ================================================================================ */
194
+ .bm-overlay {
195
+ display: none;
196
+ position: fixed;
197
+ inset: 0;
198
+ background: var(--bm-scrim);
199
+ align-items: center;
200
+ justify-content: center;
201
+ }
202
+ .bm-overlay.show { display: flex; }
203
+ .bm-dialog {
204
+ background: var(--bm-surface);
205
+ border: 1px solid var(--bm-border-muted);
206
+ border-radius: 8px;
207
+ box-shadow: var(--bm-shadow-dialog);
208
+ }
209
+ .bm-dialog h2 {
210
+ margin: 0 0 6px;
211
+ font-size: 16px;
212
+ font-weight: 700;
213
+ text-transform: uppercase;
214
+ letter-spacing: .5px;
215
+ }
216
+ `;
217
+ //# sourceMappingURL=design.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"design.js","sourceRoot":"","sources":["../../src/editor/design.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,4FAA4F;AAC5F,MAAM,CAAC,MAAM,EAAE,GAAG;IAChB,EAAE,EAAE,SAAS;IACb,OAAO,EAAE,SAAS;IAClB,UAAU,EAAE,SAAS;IACrB,WAAW,EAAE,SAAS;IAEtB,WAAW,EAAE,SAAS;IACtB,SAAS,EAAE,SAAS;IACpB,OAAO,EAAE,SAAS;IAClB,YAAY,EAAE,SAAS;IAEvB,MAAM,EAAE,SAAS;IACjB,WAAW,EAAE,SAAS;IAEtB,IAAI,EAAE,SAAS;IACf,SAAS,EAAE,SAAS;IACpB,WAAW,EAAE,SAAS;IACtB,IAAI,EAAE,SAAS;IACf,SAAS,EAAE,SAAS;IACpB,WAAW,EAAE,SAAS;IACtB,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,SAAS;IAEjB,YAAY,EAAE,+BAA+B;IAC7C,UAAU,EAAE,8BAA8B;IAC1C,QAAQ,EAAE,oCAAoC;IAC9C,QAAQ,EAAE,kCAAkC;IAC5C,cAAc,EAAE,yBAAyB;IACzC,gBAAgB,EAAE,8DAA8D;IAEhF,IAAI,EAAE,8EAA8E;IACpF,QAAQ,EAAE,gDAAgD;CAClD,CAAC;AAEX;;;;;GAKG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG;;0HAEwF,CAAC;AAE3H,uFAAuF;AACvF,MAAM,CAAC,MAAM,mBAAmB,GAAG;;;eAGpB,EAAE,CAAC,EAAE;oBACA,EAAE,CAAC,OAAO;wBACN,EAAE,CAAC,UAAU;yBACZ,EAAE,CAAC,WAAW;iBACtB,EAAE,CAAC,WAAW;uBACR,EAAE,CAAC,SAAS;qBACd,EAAE,CAAC,OAAO;mBACZ,EAAE,CAAC,MAAM;yBACH,EAAE,CAAC,WAAW;iBACtB,EAAE,CAAC,IAAI;uBACD,EAAE,CAAC,SAAS;iBAClB,EAAE,CAAC,IAAI;uBACD,EAAE,CAAC,SAAS;oBACf,EAAE,CAAC,OAAO;mBACX,EAAE,CAAC,MAAM;;;;;;;0BAOF,EAAE,CAAC,YAAY;wBACjB,EAAE,CAAC,UAAU;sBACf,EAAE,CAAC,QAAQ;sBACX,EAAE,CAAC,QAAQ;iBAChB,EAAE,CAAC,IAAI;sBACF,EAAE,CAAC,QAAQ;;CAEhC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA+DnB,EAAE,CAAC,cAAc;;;;;;;kCAOD,EAAE,CAAC,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsDpD,CAAC"}
@@ -51,6 +51,7 @@
51
51
  import { decodeForgeMapHeights, renderForgeMapRgba, } from '@bitmagic/world-forger/pipeline/forge-map-render.js';
52
52
  import { FORGE_MAP_PALETTE } from '@bitmagic/world-forger/pipeline/layout-map.js';
53
53
  import { ASSET_DETAIL_CSS, ASSET_DETAIL_HTML } from './asset-detail-panel.js';
54
+ import { BITMAGIC_CONTROLS_CSS, BITMAGIC_FONT_LINK, BITMAGIC_TOKENS_CSS } from './design.js';
54
55
  /** How often the shell asks the engine whether anything changed. A `Set` read; effectively free. */
55
56
  const POLL_INTERVAL_MS = 500;
56
57
  /**
@@ -104,134 +105,143 @@ export function renderEditorShell(options) {
104
105
  <head>
105
106
  <meta charset="utf-8">
106
107
  <title>bitmagic dev — ${escapeAttr(options.gameId)}</title>
108
+ ${BITMAGIC_FONT_LINK}
107
109
  <style>
108
- :root { color-scheme: dark; }
110
+ ${BITMAGIC_TOKENS_CSS}
111
+ ${BITMAGIC_CONTROLS_CSS}
109
112
  * { box-sizing: border-box; }
110
113
  /* Flex column rather than calc() heights: the banners come and go, and three of them at once
111
114
  must not push the viewport into a scrollbar. */
112
115
  body { margin: 0; height: 100vh; display: flex; flex-direction: column;
113
- background: #101014; color: #e6e6ea; font: 13px/1.45 ui-sans-serif, system-ui, sans-serif; }
114
- #bar { display: flex; align-items: center; gap: 12px; height: 36px; flex: none; padding: 0 12px;
115
- background: #17171d; border-bottom: 1px solid #26262e; }
116
- #bar .id { color: #8a8a99; font-family: ui-monospace, monospace; }
116
+ background: var(--bm-bg); color: var(--bm-text); font: 400 14px/1.5 var(--bm-font); }
117
+ #bar { display: flex; align-items: center; gap: 12px; height: 44px; flex: none; padding: 0 16px;
118
+ background: var(--bm-surface); border-bottom: 1px solid var(--bm-border-muted); }
119
+ /* The wordmark speaks in the brand's headline voice: uppercase, bold, tracked. */
120
+ #bar .wordmark { font-size: 14px; font-weight: 700; text-transform: uppercase;
121
+ letter-spacing: 1.6px; }
122
+ #bar .id { color: var(--bm-text-dim); font-family: var(--bm-font-mono); font-size: 12px; }
117
123
  #bar .spacer { flex: 1; }
118
- #tabs { display: flex; gap: 2px; background: #101014; border: 1px solid #26262e; border-radius: 6px;
119
- padding: 2px; }
120
- .tab { background: transparent; border: 0; border-radius: 4px; color: #9a9aab; padding: 3px 14px;
121
- font: inherit; cursor: pointer; }
122
- .tab:hover { color: #e6e6ea; background: #22222a; }
123
- .tab.active { background: #3352c4; color: #fff; }
124
- #status { display: flex; align-items: center; gap: 6px; }
125
- #dot { width: 8px; height: 8px; border-radius: 50%; background: #4a4a57; }
126
- #dot.saving { background: #d9a441; }
127
- #dot.saved { background: #4caf72; }
128
- #dot.error { background: #e0564f; }
129
- #auto { display: flex; align-items: center; gap: 5px; color: #8a8a99; cursor: pointer; }
130
- #auto input { margin: 0; }
131
- button { background: #26262e; color: #e6e6ea; border: 1px solid #34343f; border-radius: 5px;
132
- padding: 4px 10px; font: inherit; cursor: pointer; }
133
- button:hover { background: #30303a; }
134
- button:disabled { opacity: .5; cursor: default; background: #26262e; }
135
- /* .tab:hover is declared after .tab.active and would otherwise win on an active tab. */
136
- #tabs .tab.active:hover { background: #3352c4; }
137
- .banner { display: none; align-items: center; gap: 12px; flex: none; padding: 8px 12px;
138
- background: #3a2c12; border-bottom: 1px solid #574018; color: #f0d9a8; }
124
+ #tabs { display: flex; gap: 4px; background: var(--bm-surface-alt); border-radius: 9999px;
125
+ padding: 3px; }
126
+ /* A tab is a .bm-pill that starts invisible; the ACTIVE one is what the accent is for —
127
+ DESIGN.md gives Aquamarine to primary actions and active states alike. */
128
+ .tab { background: transparent; border-color: transparent; color: var(--bm-text-muted); }
129
+ .tab:hover:not(.active) { background: var(--bm-surface-card); border-color: transparent;
130
+ color: var(--bm-text); }
131
+ .tab.active, .tab.active:hover { background: var(--bm-aqua); border-color: var(--bm-aqua);
132
+ color: #000000; }
133
+ #status { display: flex; align-items: center; gap: 8px; font-size: 12px;
134
+ color: var(--bm-text-muted); }
135
+ /* Working is Pumpkin, done is Aquamarine, failed is Shocking Pink the same three the steps,
136
+ the progress bar and the banners below use, so one colour never means two things. */
137
+ #dot { width: 8px; height: 8px; border-radius: 50%; background: var(--bm-border); }
138
+ #dot.saving { background: var(--bm-pumpkin); }
139
+ #dot.saved { background: var(--bm-aqua); }
140
+ #dot.error { background: var(--bm-pink); }
141
+ #auto { display: flex; align-items: center; gap: 6px; font-size: 12px;
142
+ color: var(--bm-text-muted); cursor: pointer; }
143
+ #auto input { margin: 0; accent-color: var(--bm-aqua); }
144
+ .banner { display: none; align-items: center; gap: 12px; flex: none; padding: 10px 16px;
145
+ background: var(--bm-tint-warning); border-bottom: 1px solid var(--bm-pumpkin);
146
+ color: var(--bm-text); }
139
147
  .banner.show { display: flex; }
140
- #terrain-banner, #build-banner { background: #3d1f1c; border-bottom-color: #6b2f28; color: #f3c3bd; }
141
- #build-banner code { font-family: ui-monospace, monospace; }
148
+ /* A lost edit and a broken build are worse than out-of-date, and read as negative states. */
149
+ #terrain-banner, #build-banner { background: var(--bm-tint-negative);
150
+ border-bottom-color: var(--bm-pink); }
151
+ #build-banner code, #terrain-banner code { font-family: var(--bm-font-mono); }
142
152
  /* The game and the panel share one row, so the panel takes width from the game rather than
143
153
  overlaying it — an overlay would cover the thing you opened the panel to watch. */
144
154
  #stage { flex: 1; display: flex; min-height: 0; }
145
155
  #frame { display: block; flex: 1; border: 0; min-width: 0; height: 100%; }
146
- #assets { width: 264px; flex: none; overflow-y: auto; background: #131318;
147
- border-left: 1px solid #26262e; }
156
+ #assets { width: 280px; flex: none; overflow-y: auto; background: var(--bm-surface);
157
+ border-left: 1px solid var(--bm-border-muted); }
148
158
  body.assets-closed #assets { display: none; }
149
- #assets-head { position: sticky; top: 0; display: flex; align-items: center; gap: 8px;
150
- padding: 8px 10px; background: #17171d; border-bottom: 1px solid #26262e;
151
- font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: #8a8a99; }
152
- #assets-head .count { margin-left: auto; color: #6a6a7a; letter-spacing: 0; }
153
- #assets-empty { padding: 14px 10px; color: #6a6a7a; }
154
- .row { display: flex; gap: 9px; padding: 8px 10px; border-bottom: 1px solid #1e1e26; }
159
+ #assets-head { position: sticky; top: 0; display: flex; align-items: center; gap: 8px; z-index: 1;
160
+ padding: 12px; background: var(--bm-surface-alt);
161
+ border-bottom: 1px solid var(--bm-border-muted); }
162
+ #assets-head .count { margin-left: auto; color: var(--bm-text-dim); letter-spacing: 0; }
163
+ #assets-empty { padding: 16px 12px; color: var(--bm-text-dim); font-size: 12px; }
164
+ .row { display: flex; gap: 12px; padding: 10px 12px;
165
+ border-bottom: 1px solid var(--bm-border-muted); }
155
166
  .row.clickable { cursor: pointer; }
156
- .row.clickable:hover, .row.clickable:focus-visible { background: #1b1b23; outline: none; }
157
- .row .thumb { width: 46px; height: 46px; flex: none; border-radius: 4px; background: #1e1e26;
158
- display: flex; align-items: center; justify-content: center; font-size: 18px;
159
- color: #55556a; overflow: hidden; }
167
+ .row.clickable:hover, .row.clickable:focus-visible { background: var(--bm-surface-card);
168
+ outline: none; }
169
+ .row .thumb { width: 48px; height: 48px; flex: none; border-radius: 6px;
170
+ background: var(--bm-surface-alt); display: flex; align-items: center;
171
+ justify-content: center; font-size: 18px; color: var(--bm-text-dim);
172
+ overflow: hidden; }
160
173
  .row .thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
161
174
  .row .body { min-width: 0; flex: 1; }
162
- .row .name { color: #e6e6ea; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
163
- .row .meta { color: #6a6a7a; font-size: 11px; overflow: hidden; text-overflow: ellipsis;
175
+ .row .name { color: var(--bm-text); overflow: hidden; text-overflow: ellipsis;
164
176
  white-space: nowrap; }
165
- .row .chip { display: inline-block; margin-left: 5px; padding: 0 5px; border-radius: 3px;
166
- font-size: 10px; background: #2a2a34; color: #9a9aab; vertical-align: 1px; }
167
- .row .chip.hq { background: #1f3a2a; color: #8fd0a4; }
168
- .row .chip.placeholder { background: #3a3320; color: #d9c08a; }
169
- /* A new asset during a forge is the whole show, so it announces itself and then settles. */
177
+ .row .name .bm-badge { margin-left: 6px; }
178
+ .row .meta { color: var(--bm-text-dim); font-size: 12px; overflow: hidden;
179
+ text-overflow: ellipsis; white-space: nowrap; }
180
+ /* A new asset during a forge is the whole show, so it announces itself with the Aquamarine
181
+ "something landed" flourish and then settles. */
170
182
  .row.fresh { animation: landed 2.4s ease-out; }
171
- @keyframes landed { from { background: #22314f; } to { background: transparent; } }
172
- .row.job .thumb { color: #d9a441; }
173
- .row.job .message { color: #9a9aab; font-size: 11px; overflow: hidden; text-overflow: ellipsis;
174
- white-space: nowrap; }
183
+ @keyframes landed { from { background: var(--bm-tint-success); } to { background: transparent; } }
184
+ .row.job .thumb { color: var(--bm-pumpkin); }
185
+ .row.job .message { color: var(--bm-text-muted); font-size: 12px; overflow: hidden;
186
+ text-overflow: ellipsis; white-space: nowrap; }
175
187
  /* The forge's five steps. A whole run is half an hour, so this is what the panel is for. */
176
- .steps { margin-top: 5px; font-size: 11px; }
177
- .step { display: flex; align-items: baseline; gap: 5px; color: #55556a; line-height: 1.6; }
178
- .step.running { color: #d9d9e2; }
179
- .step.done { color: #7c8f7f; }
180
- .step .glyph { width: 9px; flex: none; text-align: center; }
188
+ .steps { margin-top: 6px; font-size: 12px; }
189
+ .step { display: flex; align-items: baseline; gap: 6px; color: var(--bm-text-dim);
190
+ line-height: 1.6; }
191
+ .step.running { color: var(--bm-text); }
192
+ .step.done { color: var(--bm-aqua); }
193
+ .step .glyph { width: 10px; flex: none; text-align: center; }
181
194
  .step .label { flex: none; }
182
195
  .step .tail { min-width: 0; flex: 1; overflow: hidden; text-overflow: ellipsis;
183
- white-space: nowrap; color: #6a6a7a; }
184
- .step.running .tail { color: #9a9aab; }
185
- .bar { height: 3px; margin: 3px 0 4px 14px; border-radius: 2px; background: #26262e;
186
- overflow: hidden; }
187
- .bar .fill { height: 100%; background: #d9a441; }
196
+ white-space: nowrap; color: var(--bm-text-dim); }
197
+ .step.running .tail { color: var(--bm-text-muted); }
198
+ .bar { height: 3px; margin: 4px 0 4px 16px; border-radius: 2px;
199
+ background: var(--bm-surface-card); overflow: hidden; }
200
+ .bar .fill { height: 100%; background: var(--bm-pumpkin); }
188
201
  /* The level's shape, drawn from the forge artifact — twenty-plus minutes before it is playable.
189
202
  image-rendering: pixelated because the canvas is drawn at an integer multiple of the raster
190
203
  and any further scaling should keep the object dots as dots. */
191
- .job-map { margin-top: 7px; }
192
- .job-map canvas { display: block; width: 100%; height: auto; border-radius: 4px;
193
- border: 1px solid #26262e; image-rendering: pixelated; }
204
+ .job-map { margin-top: 8px; }
205
+ .job-map canvas { display: block; width: 100%; height: auto; border-radius: 6px;
206
+ border: 1px solid var(--bm-border-muted); image-rendering: pixelated; }
194
207
  /* What the level being built contains — known minutes before the level itself exists. */
195
- .job-summary { margin-top: 6px; padding-top: 6px; border-top: 1px solid #1e1e26;
196
- color: #8a8a99; font-size: 11px; line-height: 1.6; }
197
- .job-summary .objects { color: #6a6a7a; overflow: hidden; text-overflow: ellipsis;
208
+ .job-summary { margin-top: 8px; padding-top: 8px;
209
+ border-top: 1px solid var(--bm-border-muted); color: var(--bm-text-muted);
210
+ font-size: 12px; line-height: 1.6; }
211
+ .job-summary .objects { color: var(--bm-text-dim); overflow: hidden; text-overflow: ellipsis;
198
212
  white-space: nowrap; }
199
213
  .spin { display: inline-block; animation: spin 1.4s linear infinite; }
200
214
  @keyframes spin { to { transform: rotate(360deg); } }
201
- #hq-overlay { display: none; position: fixed; inset: 0; background: rgba(8,8,12,.72);
202
- align-items: center; justify-content: center; z-index: 10; }
203
- #hq-overlay.show { display: flex; }
204
- #hq-dialog { width: min(560px, 92vw); background: #17171d; border: 1px solid #34343f;
205
- border-radius: 8px; padding: 18px; }
206
- #hq-dialog h2 { margin: 0 0 6px; font-size: 15px; }
207
- #hq-dialog p { margin: 0 0 12px; color: #9a9aab; }
208
- #hq-prompt { width: 100%; min-height: 88px; resize: vertical; padding: 8px; border-radius: 6px;
209
- background: #101014; color: #e6e6ea; border: 1px solid #34343f; font: inherit; }
210
- #hq-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 12px; }
211
- #hq-confirm { background: #3352c4; border-color: #3f61d8; }
212
- #hq-note { display: none; margin-top: 10px; padding: 10px; border-radius: 6px;
213
- background: #101014; border: 1px solid #26262e; }
215
+ #hq-overlay { z-index: 10; }
216
+ #hq-dialog { width: min(560px, 92vw); padding: 20px; }
217
+ #hq-dialog p { margin: 0 0 16px; color: var(--bm-text-muted); }
218
+ #hq-prompt { width: 100%; min-height: 88px; resize: vertical; }
219
+ #hq-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 16px; }
220
+ #hq-note { display: none; margin-top: 12px; padding: 12px; border-radius: 6px; font-size: 12px;
221
+ background: var(--bm-surface-alt); border: 1px solid var(--bm-border-muted);
222
+ color: var(--bm-text-muted); }
214
223
  #hq-note.show { display: block; }
215
- #hq-note code { display: block; margin-top: 6px; color: #9fd0a8; word-break: break-all; }
224
+ #hq-note code { display: block; margin-top: 6px; color: var(--bm-aqua);
225
+ font-family: var(--bm-font-mono); word-break: break-all; }
216
226
  ${ASSET_DETAIL_CSS}
217
227
  </style>
218
228
  </head>
219
229
  <body>
220
230
  <div id="bar">
221
- <strong>bitmagic dev</strong>
231
+ <span class="wordmark">bitmagic dev</span>
222
232
  <span class="id">${escapeAttr(options.gameId)}</span>
223
233
  <div id="tabs">
224
- <button class="tab active" type="button" data-tab="game">Game</button>
225
- <button class="tab" type="button" data-tab="editor">Editor</button>
234
+ <button class="tab bm-pill active" type="button" data-tab="game">Game</button>
235
+ <button class="tab bm-pill" type="button" data-tab="editor">Editor</button>
226
236
  </div>
227
237
  <span class="spacer"></span>
228
238
  <label id="auto" title="Reload the game when the project changes on disk">
229
239
  <input id="auto-toggle" type="checkbox" checked> Auto-reload
230
240
  </label>
231
241
  <span id="status"><span id="dot"></span><span id="status-text">Loading…</span></span>
232
- <button id="assets-toggle" type="button" title="Show the assets in this project and what is being generated">Assets</button>
233
- <button id="shot" type="button" title="Copy the current frame to the clipboard">Screenshot</button>
234
- <button id="reload" type="button">Reload</button>
242
+ <button id="assets-toggle" class="bm-pill" type="button" title="Show the assets in this project and what is being made">Assets</button>
243
+ <button id="shot" class="bm-pill" type="button" title="Copy the current frame to the clipboard">Screenshot</button>
244
+ <button id="reload" class="bm-pill" type="button">Reload</button>
235
245
  </div>
236
246
  <div id="build-banner" class="banner">
237
247
  <span id="build-message"></span>
@@ -239,32 +249,32 @@ ${ASSET_DETAIL_CSS}
239
249
  </div>
240
250
  <div id="banner" class="banner">
241
251
  <span>src/work/world.json changed on disk — this scene is out of date.</span>
242
- <button id="banner-reload" type="button">Reload scene</button>
252
+ <button id="banner-reload" class="bm-pill" type="button">Reload scene</button>
243
253
  </div>
244
254
  <div id="terrain-banner" class="banner">
245
255
  <span><strong>Terrain edits are not saved yet.</strong>
246
256
  Sculpting the ground needs an asset upload that <code>bitmagic dev</code> does not do — these
247
257
  voxel changes will be lost. Discard them, or press Cancel in the terrain toolbar.</span>
248
- <button id="terrain-discard" type="button">Discard terrain edits</button>
258
+ <button id="terrain-discard" class="bm-pill bm-pill--destructive" type="button">Discard terrain edits</button>
249
259
  </div>
250
260
  <div id="stage">
251
261
  <iframe id="frame" allow="autoplay; fullscreen; xr-spatial-tracking; clipboard-write"></iframe>
252
262
  <aside id="assets">
253
- <div id="assets-head">Assets<span class="count" id="assets-count"></span></div>
263
+ <div id="assets-head" class="bm-label">Assets<span class="count" id="assets-count"></span></div>
254
264
  <div id="assets-jobs"></div>
255
265
  <div id="assets-list"></div>
256
- <div id="assets-empty">Nothing yet. Assets appear here as they are generated.</div>
266
+ <div id="assets-empty">Nothing yet. Assets appear here as they are made.</div>
257
267
  </aside>
258
268
  </div>
259
- <div id="hq-overlay">
260
- <div id="hq-dialog">
261
- <h2>Generate a high-quality <span id="hq-name"></span></h2>
269
+ <div id="hq-overlay" class="bm-overlay">
270
+ <div id="hq-dialog" class="bm-dialog">
271
+ <h2>Make a high-quality <span id="hq-name"></span></h2>
262
272
  <p>Describe what this object should be. The text is saved as the asset's description and
263
- used as the generation prompt.</p>
264
- <textarea id="hq-prompt" placeholder="e.g. a weathered stone archway covered in moss"></textarea>
273
+ used as the prompt it is made from.</p>
274
+ <textarea id="hq-prompt" class="bm-input" placeholder="e.g. a weathered stone archway covered in moss"></textarea>
265
275
  <div id="hq-actions">
266
- <button id="hq-cancel" type="button">Close</button>
267
- <button id="hq-confirm" type="button">Generate</button>
276
+ <button id="hq-cancel" class="bm-pill bm-pill--ghost" type="button">Close</button>
277
+ <button id="hq-confirm" class="bm-pill bm-pill--primary" type="button">Make it</button>
268
278
  </div>
269
279
  <div id="hq-note">
270
280
  <span id="hq-note-text"></span>
@@ -1101,8 +1111,9 @@ ${ASSET_DETAIL_HTML}
1101
1111
 
1102
1112
  var body = el('div', 'body');
1103
1113
  var name = el('div', 'name', asset.name || asset.id || 'unnamed');
1104
- if (asset.hqGeneratedAt) name.appendChild(el('span', 'chip hq', 'HQ'));
1105
- else if (asset.placeholder === true) name.appendChild(el('span', 'chip placeholder', 'placeholder'));
1114
+ // Success and warning, never both: an asset is either the good version or standing in for it.
1115
+ if (asset.hqGeneratedAt) name.appendChild(el('span', 'bm-badge bm-badge--success', 'HQ'));
1116
+ else if (asset.placeholder === true) name.appendChild(el('span', 'bm-badge bm-badge--warning', 'placeholder'));
1106
1117
  body.appendChild(name);
1107
1118
  var bits = [asset.type || 'unknown'];
1108
1119
  var size = formatSize(asset.size);
@@ -1 +1 @@
1
- {"version":3,"file":"shell-page.js","sourceRoot":"","sources":["../../src/editor/shell-page.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"shell-page.js","sourceRoot":"","sources":["../../src/editor/shell-page.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bitmagic/cli",
3
- "version": "0.1.41",
3
+ "version": "0.1.42",
4
4
  "description": "Build Bitmagic games from your own agent tool",
5
5
  "type": "module",
6
6
  "bin": {