@bitmagic/cli 0.1.83-dev.2 → 0.1.83-dev.4

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 (160) hide show
  1. package/README.md +34 -3
  2. package/assets/metahuman/src/work/metahuman/MetaHumanMaterials.ts +4 -0
  3. package/assets/metahuman/src/work/metahuman/StudioEnvironment.ts +4 -0
  4. package/assets/optimizing-assets/SKILL.md +3 -2
  5. package/assets/optimizing-assets/references/tools.md +1 -1
  6. package/dist/assets/vxl-summary.js +1 -1
  7. package/dist/assets/vxl-summary.js.map +1 -1
  8. package/dist/cli.d.ts +9 -0
  9. package/dist/commands/steam-upload.js +6 -4
  10. package/dist/commands/steam-upload.js.map +1 -1
  11. package/dist/commands/steam.js +4 -2
  12. package/dist/commands/steam.js.map +1 -1
  13. package/dist/commands/upgrade.d.ts +18 -0
  14. package/dist/commands/upgrade.js +94 -1
  15. package/dist/commands/upgrade.js.map +1 -1
  16. package/dist/config/environments.d.ts +1 -1
  17. package/dist/editor/animation-preview-page.js +20 -0
  18. package/dist/editor/animation-preview-page.js.map +1 -1
  19. package/dist/editor/asset-viewer.js +4 -0
  20. package/dist/editor/asset-viewer.js.map +1 -1
  21. package/dist/editor/design.d.ts +2 -2
  22. package/dist/editor/design.js +2 -2
  23. package/dist/editor/design.js.map +1 -1
  24. package/dist/editor/hud-replay-page.js +5 -0
  25. package/dist/editor/hud-replay-page.js.map +1 -1
  26. package/dist/editor/recording-sink.js +1 -1
  27. package/dist/editor/runtime-token.d.ts +61 -0
  28. package/dist/editor/runtime-token.js +74 -0
  29. package/dist/editor/runtime-token.js.map +1 -0
  30. package/dist/editor/save.d.ts +2 -2
  31. package/dist/editor/server.js +39 -12
  32. package/dist/editor/server.js.map +1 -1
  33. package/dist/editor/shell-page.d.ts +12 -8
  34. package/dist/editor/shell-page.js +69 -10
  35. package/dist/editor/shell-page.js.map +1 -1
  36. package/dist/forge/browser-host.d.ts +1 -1
  37. package/dist/forge/browser-host.js +14 -11
  38. package/dist/forge/browser-host.js.map +1 -1
  39. package/dist/generate/model.js +4 -1
  40. package/dist/generate/model.js.map +1 -1
  41. package/dist/generate/prop.js +4 -1
  42. package/dist/generate/prop.js.map +1 -1
  43. package/dist/http/signed-upload.d.ts +6 -4
  44. package/dist/http/signed-upload.js +37 -14
  45. package/dist/http/signed-upload.js.map +1 -1
  46. package/dist/mobile/rewrite-shim.js +1 -1
  47. package/dist/project/published-three.js +4 -6
  48. package/dist/project/published-three.js.map +1 -1
  49. package/dist/publish/game-exchange.js +9 -3
  50. package/dist/publish/game-exchange.js.map +1 -1
  51. package/dist/scaffold/blender-level-skill-files.js +2 -2
  52. package/dist/scaffold/game-migration.d.ts +88 -0
  53. package/dist/scaffold/game-migration.js +492 -0
  54. package/dist/scaffold/game-migration.js.map +1 -0
  55. package/dist/scaffold/import-codemod.d.ts +51 -0
  56. package/dist/scaffold/import-codemod.js +117 -0
  57. package/dist/scaffold/import-codemod.js.map +1 -0
  58. package/dist/scaffold/legacy-game-baselines.d.ts +14 -0
  59. package/dist/scaffold/legacy-game-baselines.js +218 -0
  60. package/dist/scaffold/legacy-game-baselines.js.map +1 -0
  61. package/dist/scaffold/project-files.d.ts +1 -1
  62. package/dist/scaffold/project-files.js +13 -47
  63. package/dist/scaffold/project-files.js.map +1 -1
  64. package/dist/scaffold/project.js +8 -17
  65. package/dist/scaffold/project.js.map +1 -1
  66. package/dist/smoke/run.js +8 -1
  67. package/dist/smoke/run.js.map +1 -1
  68. package/dist/steam/art-generate.js +2 -1
  69. package/dist/steam/art-generate.js.map +1 -1
  70. package/dist/steam/art-render.js.map +1 -1
  71. package/dist/steam/art.js +1 -1
  72. package/dist/steam/art.js.map +1 -1
  73. package/dist/steam/check.js.map +1 -1
  74. package/dist/steam/electron-cache.d.ts +1 -1
  75. package/dist/steam/electron-cache.js +2 -2
  76. package/dist/steam/electron-cache.js.map +1 -1
  77. package/dist/steam/fuses.js +1 -1
  78. package/dist/steam/fuses.js.map +1 -1
  79. package/dist/steam/media.js +6 -2
  80. package/dist/steam/media.js.map +1 -1
  81. package/dist/steam/package-windows.d.ts +1 -2
  82. package/dist/steam/package-windows.js +1 -2
  83. package/dist/steam/package-windows.js.map +1 -1
  84. package/dist/steam/paths.d.ts +0 -2
  85. package/dist/steam/paths.js +0 -1
  86. package/dist/steam/paths.js.map +1 -1
  87. package/dist/steam/portal.js +1 -1
  88. package/dist/steam/portal.js.map +1 -1
  89. package/dist/steam/raster.d.ts +0 -1
  90. package/dist/steam/raster.js +1 -1
  91. package/dist/steam/raster.js.map +1 -1
  92. package/dist/steam/store-copy.d.ts +0 -1
  93. package/dist/steam/store-copy.js +3 -10
  94. package/dist/steam/store-copy.js.map +1 -1
  95. package/dist/steam/tags.js +6 -3
  96. package/dist/steam/tags.js.map +1 -1
  97. package/dist/theme/kernel.d.ts +14 -0
  98. package/dist/theme/kernel.js +15 -0
  99. package/dist/theme/kernel.js.map +1 -0
  100. package/dist/theme/theme-io.js +11 -16
  101. package/dist/theme/theme-io.js.map +1 -1
  102. package/dist/trailer/record-session.d.ts +1 -1
  103. package/dist/trailer/record-session.js +5 -8
  104. package/dist/trailer/record-session.js.map +1 -1
  105. package/dist/trailer/vendored-recorder.d.ts +8 -0
  106. package/dist/trailer/vendored-recorder.js +26 -0
  107. package/dist/trailer/vendored-recorder.js.map +1 -0
  108. package/dist/vendor/hud-theme/catalog.js +71 -0
  109. package/dist/vendor/hud-theme/engine/hud/ThemeTokens.js +115 -0
  110. package/dist/{theme/theme-color-math.js → vendor/hud-theme/engine/hud/colorMath.js} +13 -14
  111. package/dist/vendor/hud-theme/engine/hud/decorations.js +179 -0
  112. package/dist/vendor/hud-theme/engine/hud/fonts.js +147 -0
  113. package/dist/vendor/hud-theme/engine/hud/presets.js +80 -0
  114. package/dist/vendor/hud-theme/engine/hud/resolveWorldTheme.js +66 -0
  115. package/dist/vendor/hud-theme/engine/hud/themes/bitmagic.js +29 -0
  116. package/dist/vendor/hud-theme/engine/hud/themes/nexus.js +69 -0
  117. package/dist/vendor/hud-theme/engine/hud/themes/racing.js +57 -0
  118. package/dist/vendor/hud-theme/engine/hud/themes/rift-raider.js +63 -0
  119. package/dist/vendor/hud-theme/engine/hud/themes/simulator.js +55 -0
  120. package/dist/vendor/hud-theme/engine/hud/themes/village-keep.js +108 -0
  121. package/dist/vendor/hud-theme/engine/hud/validateTheme.js +535 -0
  122. package/dist/vendor/hud-theme/index.js +26 -0
  123. package/dist/{theme/theme-merge.js → vendor/hud-theme/merge.js} +0 -1
  124. package/dist/{theme/theme-report.js → vendor/hud-theme/report.js} +8 -9
  125. package/dist/{theme/theme-stored.js → vendor/hud-theme/stored.js} +6 -9
  126. package/dist/{theme/theme-validate.js → vendor/hud-theme/validate-strict.js} +102 -164
  127. package/dist/verify/browser.d.ts +6 -0
  128. package/dist/verify/browser.js +30 -3
  129. package/dist/verify/browser.js.map +1 -1
  130. package/dist/verify/categories.d.ts +1 -1
  131. package/dist/verify/categories.js +1 -0
  132. package/dist/verify/categories.js.map +1 -1
  133. package/dist/verify/classify.d.ts +7 -0
  134. package/dist/verify/classify.js +7 -0
  135. package/dist/verify/classify.js.map +1 -1
  136. package/dist/verify/hud-theme.d.ts +19 -14
  137. package/dist/verify/hud-theme.js +23 -17
  138. package/dist/verify/hud-theme.js.map +1 -1
  139. package/dist/verify/mobile-parity.d.ts +1 -1
  140. package/dist/verify/mobile-parity.js +1 -1
  141. package/dist/verify/model-downloads.d.ts +47 -0
  142. package/dist/verify/model-downloads.js +127 -0
  143. package/dist/verify/model-downloads.js.map +1 -0
  144. package/dist/verify/start.d.ts +3 -2
  145. package/dist/verify/start.js +1 -1
  146. package/dist/verify/start.js.map +1 -1
  147. package/package.json +11 -7
  148. package/dist/theme/hud-theme-catalog.d.ts +0 -235
  149. package/dist/theme/hud-theme-catalog.js +0 -389
  150. package/dist/theme/hud-theme-catalog.js.map +0 -1
  151. package/dist/theme/theme-color-math.d.ts +0 -21
  152. package/dist/theme/theme-color-math.js.map +0 -1
  153. package/dist/theme/theme-merge.d.ts +0 -36
  154. package/dist/theme/theme-merge.js.map +0 -1
  155. package/dist/theme/theme-report.d.ts +0 -28
  156. package/dist/theme/theme-report.js.map +0 -1
  157. package/dist/theme/theme-stored.d.ts +0 -21
  158. package/dist/theme/theme-stored.js.map +0 -1
  159. package/dist/theme/theme-validate.d.ts +0 -41
  160. package/dist/theme/theme-validate.js.map +0 -1
@@ -0,0 +1,80 @@
1
+ import { BITMAGIC_THEME_DATA } from './themes/bitmagic.js';
2
+ import { RIFT_RAIDER_THEME_DATA } from './themes/rift-raider.js';
3
+ import { VILLAGE_KEEP_THEME_DATA } from './themes/village-keep.js';
4
+ import { NEXUS_THEME_DATA } from './themes/nexus.js';
5
+ import { SIMULATOR_THEME_DATA } from './themes/simulator.js';
6
+ import { RACING_THEME_DATA } from './themes/racing.js';
7
+ import { validateAndResolveTheme } from './validateTheme.js';
8
+ // Built-in theme presets — THE FIVE SELECTABLE STYLES. Each preset's raw data
9
+ // lives in its own TS module (themes/*.ts) and goes through
10
+ // validateAndResolveTheme — so the same path that user themes go through
11
+ // catches preset bugs at engine boot.
12
+ //
13
+ // `bitmagic` is deliberately NOT in this set. It is the engine's DEFAULT/
14
+ // FALLBACK look (what a game with no `hud.theme` — or an invalid one — renders
15
+ // with), exported as DEFAULT_HUD_THEME. Listing it as a preset made every "cycle
16
+ // all styles" feature show six looks and every agent catalogue advertise a
17
+ // style that is really the absence of one.
18
+ //
19
+ // Built-in presets are TS modules, not .json files, because the engine runtime
20
+ // loads modules from /dist/ where tsc doesn't copy non-TS files. User-authored
21
+ // themes ship as theme.json on disk (next to world.json) and are fetched +
22
+ // validated at game load time.
23
+ /** The five selectable presets, in catalogue order. `PresetName` is derived from this list. */
24
+ export const PRESET_NAMES = ['rift-raider', 'village-keep', 'nexus', 'simulator', 'racing'];
25
+ /**
26
+ * Each preset's RAW data — the inline-theme shape, plus its `evokes` label — before
27
+ * validation. Tools that patch a preset start from this ("preset X but with orange
28
+ * accents"): it can be spread, edited and written back as an inline theme.
29
+ */
30
+ export const PRESET_THEME_DATA = {
31
+ 'rift-raider': RIFT_RAIDER_THEME_DATA,
32
+ 'village-keep': VILLAGE_KEEP_THEME_DATA,
33
+ nexus: NEXUS_THEME_DATA,
34
+ simulator: SIMULATOR_THEME_DATA,
35
+ racing: RACING_THEME_DATA,
36
+ };
37
+ /** The default look's raw data (`bitmagic`) — the patch base when a game sets no theme. */
38
+ export const DEFAULT_THEME_DATA = BITMAGIC_THEME_DATA;
39
+ /**
40
+ * The one-line mood label each preset carries beside its tokens.
41
+ *
42
+ * Exported separately because `evokes` is deliberately NOT part of `ThemeTokens`
43
+ * — it is authoring metadata for whoever (or whatever) is choosing a preset, not
44
+ * a rendering token, and `validateAndResolveTheme` drops it on the way through.
45
+ * The agent's catalogue reads it from here, so a style and its description are
46
+ * one edit.
47
+ */
48
+ export const PRESET_EVOKES = {
49
+ 'rift-raider': PRESET_THEME_DATA['rift-raider'].evokes,
50
+ 'village-keep': PRESET_THEME_DATA['village-keep'].evokes,
51
+ nexus: PRESET_THEME_DATA.nexus.evokes,
52
+ simulator: PRESET_THEME_DATA.simulator.evokes,
53
+ racing: PRESET_THEME_DATA.racing.evokes,
54
+ };
55
+ function resolvePreset(raw, name) {
56
+ const result = validateAndResolveTheme(raw);
57
+ if (!result.ok) {
58
+ throw new Error(`Built-in preset "${name}" failed validation: ` +
59
+ result.errors.map(e => `${e.path}: ${e.message}`).join('; '));
60
+ }
61
+ return result.theme;
62
+ }
63
+ /**
64
+ * The engine's default look — applied when a game sets no `hud.theme`, and the
65
+ * fallback when a theme is unknown or fails validation. Not a selectable preset.
66
+ */
67
+ export const BITMAGIC_THEME = resolvePreset(BITMAGIC_THEME_DATA, 'bitmagic');
68
+ export const DEFAULT_HUD_THEME = BITMAGIC_THEME;
69
+ export const RIFT_RAIDER_THEME = resolvePreset(RIFT_RAIDER_THEME_DATA, 'rift-raider');
70
+ export const VILLAGE_KEEP_THEME = resolvePreset(VILLAGE_KEEP_THEME_DATA, 'village-keep');
71
+ export const NEXUS_THEME = resolvePreset(NEXUS_THEME_DATA, 'nexus');
72
+ export const SIMULATOR_THEME = resolvePreset(SIMULATOR_THEME_DATA, 'simulator');
73
+ export const RACING_THEME = resolvePreset(RACING_THEME_DATA, 'racing');
74
+ export const HUD_PRESETS = {
75
+ 'rift-raider': RIFT_RAIDER_THEME,
76
+ 'village-keep': VILLAGE_KEEP_THEME,
77
+ nexus: NEXUS_THEME,
78
+ simulator: SIMULATOR_THEME,
79
+ racing: RACING_THEME,
80
+ };
@@ -0,0 +1,66 @@
1
+ import { DEFAULT_HUD_THEME, HUD_PRESETS } from './presets.js';
2
+ import { suggestClosest, validateAndResolveTheme } from './validateTheme.js';
3
+ // Resolve a `hud.theme` value from world.json into a ThemeTokens.
4
+ //
5
+ // - undefined / null / unknown shape → DEFAULT_HUD_THEME (the engine's default look)
6
+ // - string matching a preset name → the preset
7
+ // - string not matching any preset → DEFAULT_HUD_THEME + console warning
8
+ // (this includes legacy names such as
9
+ // 'bitmagic' and 'horror' — the first
10
+ // IS the default, so it is visually a
11
+ // no-op; the second no longer ships)
12
+ // - object → validateAndResolveTheme(obj). On success,
13
+ // the resolved theme. On failure, DEFAULT_HUD_THEME
14
+ // + console warning that includes field paths.
15
+ //
16
+ // This is the single integration point: don't bypass it. The engine calls it
17
+ // once per loadGame() after world data is parsed. Failures never block the game
18
+ // from loading — a broken theme is recoverable; failing the load is not.
19
+ /**
20
+ * The marker on every theme-resolution console warning, and the two phrases that say which
21
+ * failure it was. `bitmagic verify` parses them out of the console (it imports these constants
22
+ * through `@bitmagic/hud-theme`), and it reads warnings from engines of every vendored version, so
23
+ * the wording is frozen: never reword these, only append detail after them.
24
+ */
25
+ export const HUD_THEME_LOG_MARKER = '[HUD]';
26
+ /** The phrase after the marker when `hud.theme` is a string that names no preset. */
27
+ export const HUD_UNKNOWN_PRESET_PHRASE = 'Unknown theme preset';
28
+ /** The phrase after the marker when `hud.theme` is an object the validator rejected. */
29
+ export const HUD_INVALID_THEME_PHRASE = 'Custom theme failed validation';
30
+ function isPresetName(value) {
31
+ return value in HUD_PRESETS;
32
+ }
33
+ export function resolveWorldTheme(value) {
34
+ if (value === undefined || value === null)
35
+ return DEFAULT_HUD_THEME;
36
+ if (typeof value === 'string') {
37
+ if (isPresetName(value))
38
+ return HUD_PRESETS[value];
39
+ // The closest-match hint catches the two real spelling traps: the
40
+ // unhyphenated internal style keys (`riftraider`) and plain typos.
41
+ const close = suggestClosest(value, Object.keys(HUD_PRESETS));
42
+ console.warn(`${HUD_THEME_LOG_MARKER} ${HUD_UNKNOWN_PRESET_PHRASE} "${value}". Known presets: ${Object.keys(HUD_PRESETS).join(', ')}.`
43
+ + `${close ? ` Closest match: "${close}".` : ''} Falling back to the default theme.`);
44
+ return DEFAULT_HUD_THEME;
45
+ }
46
+ const result = validateAndResolveTheme(value);
47
+ // Suggestions ride in parentheses INSIDE each issue. The validator's
48
+ // `suggestion` field carries the actionable half of every message — the
49
+ // closest-match name, the font-case remedy — and this warn used to format
50
+ // only `path: message`, so the hint was computed and then thrown away at
51
+ // the last hop. This console line is the ONLY channel the CLI lane has
52
+ // (`bitmagic verify` parses it; there is no write-tool there to return
53
+ // suggestions), so dropping it here dropped it everywhere.
54
+ // The marker and the two leading phrases are `bitmagic verify`'s parse
55
+ // contract (see the constants above) — the suggestion text extends the
56
+ // detail and must never reword them.
57
+ const formatIssue = (issue) => `${issue.path}: ${issue.message}${issue.suggestion ? ` (${issue.suggestion})` : ''}`;
58
+ if (!result.ok) {
59
+ console.warn(`${HUD_THEME_LOG_MARKER} ${HUD_INVALID_THEME_PHRASE}; falling back to the default theme. Errors:`, result.errors.map(formatIssue).join('; '));
60
+ return DEFAULT_HUD_THEME;
61
+ }
62
+ if (result.warnings.length > 0) {
63
+ console.warn(`${HUD_THEME_LOG_MARKER} Custom theme has warnings:`, result.warnings.map(formatIssue).join('; '));
64
+ }
65
+ return result.theme;
66
+ }
@@ -0,0 +1,29 @@
1
+ // Bitmagic theme — the default. Mirrors creator/DESIGN.md (Aquamarine primary,
2
+ // Shocking Pink danger, etc.). Goes through validateAndResolveTheme in presets.ts
3
+ // so any drift between this object and the schema fails at engine boot.
4
+ export const BITMAGIC_THEME_DATA = {
5
+ name: 'Bitmagic',
6
+ font: {
7
+ key: 'red-hat-display',
8
+ case: 'upper',
9
+ weightBody: 400,
10
+ weightHeading: 700,
11
+ trackingLabel: 1.6,
12
+ },
13
+ colors: {
14
+ primary: '#A0DAB9',
15
+ danger: '#E0218A',
16
+ warning: '#FF8200',
17
+ success: '#F9E547',
18
+ background: '#0b0b0b',
19
+ surface: '#181818',
20
+ text: '#ffffff',
21
+ textMuted: '#b3b3b3',
22
+ },
23
+ shape: {
24
+ radiusPill: 500,
25
+ radiusCard: 8,
26
+ glow: 'aqua',
27
+ imageRendering: 'auto',
28
+ },
29
+ };
@@ -0,0 +1,69 @@
1
+ // Nexus theme — holographic sci-fi conventions (the "Nexus" kit style):
2
+ // hairline cyan on near-black, chamfer-small radii, wide-tracked tech caps,
3
+ // corner brackets and a circuitry backdrop. Depth is carried by glow alone —
4
+ // hairline PANELS; buttons carry a bevel and a 2px rim. Threat states run orange.
5
+ export const NEXUS_THEME_DATA = {
6
+ name: 'Nexus',
7
+ // One-line mood label, read by the agent catalogue so an AI picks the right
8
+ // preset without trying each one. It lives HERE, beside the tokens it
9
+ // describes, so that changing the style and changing its description are the
10
+ // same edit — it drifted badly when it lived only in the agent mirror. The
11
+ // engine validator ignores unknown top-level keys, so this never reaches
12
+ // ThemeTokens; `PRESET_EVOKES` in presets.ts is what exposes it.
13
+ evokes: 'Holographic sci-fi — hairline cyan on near-black, corner brackets, lit teal plate buttons with a graded cyan bezel, depth by glow (Mass Effect-style)',
14
+ font: {
15
+ key: 'chakra-petch',
16
+ case: 'upper',
17
+ weightBody: 500,
18
+ weightHeading: 700,
19
+ // 1.4, not 2.5: orbitron is the widest face in the catalogue and at
20
+ // 2.5px per glyph a label like "RIFT PROGRESS" nearly fills the corner
21
+ // anchor budget on a phone, breaking mid-word. Wide tracking also costs
22
+ // word cohesion at HUD sizes — the opposite defect from the lab's Nexus.
23
+ trackingLabel: 1.4,
24
+ outlineWidth: 0,
25
+ },
26
+ colors: {
27
+ primary: '#4FD8E8',
28
+ danger: '#FF6B4A',
29
+ warning: '#F0A22E',
30
+ success: '#6FD9A4',
31
+ background: '#04070C',
32
+ surface: '#0A121A',
33
+ text: '#E6F6FA',
34
+ // Lifted from '#7EA3B2'. Checked against the panel's LIT header band
35
+ // rather than its nominal face — a secondary label that clears on the
36
+ // flat colour can still miss where the face gradient is brightest.
37
+ textMuted: '#9DBBC8',
38
+ outline: '#2E9FB5',
39
+ },
40
+ shape: {
41
+ // Buttons are OBJECTS even when the panels are flat: `bevel` paints the
42
+ // white-top/dark-bottom gradient over buttons, counters and bars, and a
43
+ // 2px border in colors.outline follows the radius. The plates keep their
44
+ // hairline language — only the controls gain relief.
45
+ radiusPill: 6,
46
+ radiusCard: 4,
47
+ glow: 'cyan',
48
+ imageRendering: 'auto',
49
+ borderWidth: 2,
50
+ bevel: 0.5,
51
+ },
52
+ // NO `controls` backdrop. `circuit-trace` used to sit here and rendered as
53
+ // GIANT CROSSHAIRS across the controls overlay rather than the fine PCB
54
+ // texture it is meant to be — see the sizing note on the decoration itself.
55
+ // The pattern is fixed now, but this style does not need it: the corner
56
+ // brackets already carry the scanner language, and a texture behind the
57
+ // control hints competed with the type sitting on top of it.
58
+ decorations: {
59
+ progressBar: { borderImage: 'bracket-frame' },
60
+ counter: { borderImage: 'bracket-frame' },
61
+ // `backdrop`, not `decorationBefore`. The before/after slots are 12px
62
+ // strips hung OUTSIDE the element, so what this asked for was a glow
63
+ // floating above the crosshair rather than around it — and glow-aura's
64
+ // whole intent is "soft radial glow halo BEHIND the element". It never
65
+ // showed either way, because the slot itself could not render (see
66
+ // buildSlotCss), so the mistake was invisible until the slot was fixed.
67
+ reticle: { backdrop: 'glow-aura' },
68
+ },
69
+ };
@@ -0,0 +1,57 @@
1
+ // Racing theme — motorsport telemetry conventions (the "Racing" kit style):
2
+ // white line-art structure on near-black, red reserved for STATE, tall condensed
3
+ // display caps, hard corners, nothing glazed. Danger is a hot red-orange kept
4
+ // distinct from the crimson brand; caution is amber; sectors are green.
5
+ export const RACING_THEME_DATA = {
6
+ name: 'Racing',
7
+ // One-line mood label, read by the agent catalogue so an AI picks the right
8
+ // preset without trying each one. It lives HERE, beside the tokens it
9
+ // describes, so that changing the style and changing its description are the
10
+ // same edit — it drifted badly when it lived only in the agent mirror. The
11
+ // engine validator ignores unknown top-level keys, so this never reaches
12
+ // ThemeTokens; `PRESET_EVOKES` in presets.ts is what exposes it.
13
+ evokes: 'Motorsport telemetry — white line-art chrome on black with red reserved for state, tall narrow gothic caps, amber caution / green sector',
14
+ font: {
15
+ key: 'archivo-narrow',
16
+ case: 'upper',
17
+ weightBody: 500,
18
+ weightHeading: 700,
19
+ trackingLabel: 1.2,
20
+ outlineWidth: 0,
21
+ },
22
+ colors: {
23
+ // NOT red. The engine spends `primary` on both FILLS and accent TYPE —
24
+ // 13 `color: var(--hud-color-primary)` sites in hudBaseStyles/modalCard
25
+ // (lobby title + status, success toast, reticle, counters, modal title)
26
+ // plus whatever the game's own panels use it for. Any red here is red
27
+ // TYPE on a near-black HUD, which is what kept getting reported, and no
28
+ // saturated red can be fixed by tuning: even pure #FF0000 tops out at
29
+ // 4.87:1 on this surface.
30
+ //
31
+ // So Racing takes the OTHER half of its own reference: white line-art
32
+ // chrome, with red reserved for state. Red did not leave the style — it
33
+ // moved to `danger` below, where it means the redline, a failed run and
34
+ // critical health, which is exactly how a real timing board uses it.
35
+ primary: '#E8EDF2',
36
+ danger: '#FF4D3A',
37
+ warning: '#FFB000',
38
+ success: '#22C55E',
39
+ background: '#07090C',
40
+ surface: '#0E1319',
41
+ text: '#F2F5F8',
42
+ textMuted: '#9BA4AE', // 5.99:1 -> 7.39:1 under bebas-neue's narrow strokes
43
+ outline: '#C9D2DA',
44
+ },
45
+ shape: {
46
+ // Buttons are OBJECTS even when the panels are flat: `bevel` paints the
47
+ // white-top/dark-bottom gradient over buttons, counters and bars, and a
48
+ // 2px border in colors.outline follows the radius. The plates keep their
49
+ // hairline language — only the controls gain relief.
50
+ radiusPill: 4,
51
+ radiusCard: 2,
52
+ glow: 'none',
53
+ imageRendering: 'auto',
54
+ borderWidth: 2,
55
+ bevel: 0.5,
56
+ },
57
+ };
@@ -0,0 +1,63 @@
1
+ // Rift Raider theme — mobile action-RPG conventions (the "Rift Raider" kit
2
+ // style): cast-gold medallion frames on dark INDIGO glass, cream display type
3
+ // with a dark bronze stroke, ornate royal borders and a leather-grain backdrop.
4
+ // The outline token is the dark keyline, not the gold: it edges gold buttons AND
5
+ // strokes cream text, and both read right in bronze.
6
+ //
7
+ // The reference's material law is that GOLD IS TRIM, NOT FILL — it belongs to
8
+ // the band around a dark face, never to the face itself. `primary` stays gold
9
+ // because the engine spends it on frames, rules and accent type; the faces it
10
+ // sits against come from `surface`.
11
+ export const RIFT_RAIDER_THEME_DATA = {
12
+ name: 'Rift Raider',
13
+ // One-line mood label, read by the agent catalogue so an AI picks the right
14
+ // preset without trying each one. It lives HERE, beside the tokens it
15
+ // describes, so that changing the style and changing its description are the
16
+ // same edit — it drifted badly when it lived only in the agent mirror. The
17
+ // engine validator ignores unknown top-level keys, so this never reaches
18
+ // ThemeTokens; `PRESET_EVOKES` in presets.ts is what exposes it.
19
+ evokes: 'Mobile action-RPG — cast-gold medallion frames on dark indigo glass, chunky cream type with a dark ink ring, royal borders (Diablo-style)',
20
+ font: {
21
+ // Baloo 2, not lilita-one: Google serves Lilita One at a single weight,
22
+ // so `weightBody` and `weightHeading` both collapsed to 400 and this
23
+ // preset had NO type hierarchy at all — the one thing a HUD needs to
24
+ // separate a label from the value it labels. Baloo 2 is the same
25
+ // rounded chunky voice and ships 400-800, and it is the face the kit
26
+ // half of this style already uses.
27
+ key: 'baloo-2',
28
+ case: 'upper',
29
+ weightBody: 500,
30
+ weightHeading: 700,
31
+ trackingLabel: 0.8,
32
+ outlineWidth: 2,
33
+ },
34
+ colors: {
35
+ primary: '#F0B23A',
36
+ danger: '#D6332E',
37
+ warning: '#E07A28',
38
+ success: '#5FB35A',
39
+ // The dark ladder sits at hue ~256, not the old ~217. This style's
40
+ // violet accents live at 269, and against a hue-217 navy the surfaces
41
+ // and the accents read as two unrelated colour families sharing a
42
+ // screen. Lightness is held; only hue moves.
43
+ background: '#0B0716',
44
+ surface: '#191228',
45
+ text: '#FFF6E2',
46
+ textMuted: '#B9A889',
47
+ outline: '#5A3D0C',
48
+ },
49
+ shape: {
50
+ radiusPill: 14,
51
+ radiusCard: 14,
52
+ glow: 'gold',
53
+ imageRendering: 'auto',
54
+ borderWidth: 2,
55
+ bevel: 0.85,
56
+ },
57
+ decorations: {
58
+ progressBar: { borderImage: 'royal-frame' },
59
+ healthBar: { borderImage: 'royal-frame' },
60
+ toast: { borderImage: 'royal-frame' },
61
+ controls: { backdrop: 'grain-texture' },
62
+ },
63
+ };
@@ -0,0 +1,55 @@
1
+ // Simulator theme — instrument-panel conventions (the "Simulator" kit style):
2
+ // flat slate plates, hard corners, neutral grey-blue structure and ONE azure
3
+ // accent reserved for state. No glow and no decoration on the plates — the seriousness
4
+ // IS the absence of jewellery. Bars run semantic green / amber / red.
5
+ export const SIMULATOR_THEME_DATA = {
6
+ name: 'Simulator',
7
+ // One-line mood label, read by the agent catalogue so an AI picks the right
8
+ // preset without trying each one. It lives HERE, beside the tokens it
9
+ // describes, so that changing the style and changing its description are the
10
+ // same edit — it drifted badly when it lived only in the agent mirror. The
11
+ // engine validator ignores unknown top-level keys, so this never reaches
12
+ // ThemeTokens; `PRESET_EVOKES` in presets.ts is what exposes it.
13
+ evokes: 'Serious instrument panel — flat slate, hard corners, one azure accent for state, thin meters and a bare dial, no glow or ornament (flight/truck sim)',
14
+ font: {
15
+ key: 'ibm-plex-sans',
16
+ case: 'upper',
17
+ weightBody: 400,
18
+ weightHeading: 700,
19
+ trackingLabel: 0.8,
20
+ outlineWidth: 0,
21
+ },
22
+ colors: {
23
+ primary: '#2E9BDB',
24
+ danger: '#C8453F',
25
+ warning: '#D8A32E',
26
+ success: '#4E9E57',
27
+ background: '#0E141B',
28
+ surface: '#161E27',
29
+ text: '#DDE5EC',
30
+ textMuted: '#A2B0BE', // 4.84:1 -> 7.60:1; 4.5:1 is a 12-14px bar, not a 10px one
31
+ outline: '#46586A',
32
+ },
33
+ shape: {
34
+ // CONTOURED, NOT MOULDED — and that split is deliberate.
35
+ //
36
+ // The reference has neither: across eight screens of the Farming
37
+ // Simulator UI there is not one moulded control, and the first pass
38
+ // took it literally and set `bevel: 0`. Dead flat read as underdrawn
39
+ // next to the rest of the kit, so the call was made to depart from the
40
+ // reference here: `bevel` is what paints the white-top/dark-bottom
41
+ // gradient over buttons, counters and bars, and a modest 0.35 gives the
42
+ // fill and edge some depth.
43
+ //
44
+ // What stays gone is the SILHOUETTE moulding — the lip, the dome, the
45
+ // cast shadow — which is what made this style look like a mobile game
46
+ // wearing a simulator's palette. `borderWidth` stays 1: the edge here is
47
+ // a hairline, not the 2px rim the four physical styles carry.
48
+ radiusPill: 4,
49
+ radiusCard: 2,
50
+ glow: 'none',
51
+ imageRendering: 'auto',
52
+ borderWidth: 1,
53
+ bevel: 0.35,
54
+ },
55
+ };
@@ -0,0 +1,108 @@
1
+ // Village Keep theme — cartoon-strategy conventions (the "Village Keep" kit
2
+ // style): a light parchment ground for the big UI, darker moulded furniture for
3
+ // the HUD itself, candy-green buttons, rounded everything, maximum gloss and
4
+ // zero glow.
5
+ //
6
+ // THREE LEVELS, and they are the whole point of this preset:
7
+ //
8
+ // background #E9E1CE the light ground the BIG UI stands on — a game's own
9
+ // dialogs and panels paint themselves with this, and the
10
+ // lobby's text input is a light well because of it.
11
+ // surface #6E5C44 the HUD FURNITURE — counters, timers, toasts, the
12
+ // controls box, bubbles. 4.92:1 darker than the ground it
13
+ // sits on and 3.29:1 against a sunny-green world, so it
14
+ // reads as an object laid over the field rather than a
15
+ // patch of it.
16
+ // trough #3A3126 per-element, for the two bars: a channel has to be the
17
+ // darkest thing in the widget or the fill cannot be the
18
+ // brightest.
19
+ //
20
+ // Getting those three apart needed an engine token. `text` used to carry two
21
+ // jobs — ink on the light ground AND ink on the furniture — which only agree on a
22
+ // uniformly dark theme. With one ink the furniture caps out around #9E9276, which
23
+ // is 1.4:1 against grass and so is not furniture at all; that ceiling is why this
24
+ // style spent three rounds flipping between a washed-out HUD and a uniformly dark
25
+ // one. `--hud-color-on-surface` (see ThemeManager) derives the second ink, so the
26
+ // ground can stay light while the furniture goes as dark as it needs to. Here it
27
+ // resolves to white at 6.41:1, and its muted companion to #DEDAD5 at 4.65:1.
28
+ //
29
+ // What the palette still has to solve by hand:
30
+ //
31
+ // - `primary`, `danger` and `warning` are each a FILL colour and an accent TYPE
32
+ // colour, and on this style the type sits on `surface` (five of the six
33
+ // `color: var(--hud-color-primary)` rules do). Type wants a light value,
34
+ // which is the opposite of the usual instinct for a fill — but going light
35
+ // lets `--hud-color-on-primary` / `--hud-color-on-danger` derive BLACK, and a
36
+ // dark label on a bright candy fill clears far more than white on a mid one.
37
+ // Both jobs come out ahead.
38
+ // - the one place that trade does NOT hold is the health bar, whose fill sits in
39
+ // a near-black trough where a pale salmon reads as neither red nor alarming.
40
+ // That is what the per-element overrides at the bottom are for.
41
+ export const VILLAGE_KEEP_THEME_DATA = {
42
+ name: 'Village Keep',
43
+ // One-line mood label, read by the agent catalogue so an AI picks the right
44
+ // preset without trying each one. It lives HERE, beside the tokens it
45
+ // describes, so that changing the style and changing its description are the
46
+ // same edit — it drifted badly when it lived only in the agent mirror. The
47
+ // engine validator ignores unknown top-level keys, so this never reaches
48
+ // ThemeTokens; `PRESET_EVOKES` in presets.ts is what exposes it.
49
+ evokes: 'Cartoon strategy — light parchment panels with darker moulded HUD chips over a sunny world, candy-green glossy buttons, ink-outlined type, zero glow (Clash-style)',
50
+ font: {
51
+ key: 'fredoka',
52
+ case: 'upper',
53
+ weightBody: 500,
54
+ weightHeading: 700,
55
+ trackingLabel: 0.6,
56
+ // Light type on the furniture wants a dark ring — the pairing the ink
57
+ // ring was invented for, and what keeps the bar's inside-value legible
58
+ // where it crosses its own fill.
59
+ outlineWidth: 2,
60
+ },
61
+ colors: {
62
+ primary: '#9BDB4F', // 3.86:1 as accent type on the furniture; auto-label black 12.64
63
+ danger: '#FFA898', // 3.45:1 as type; auto-label black 11.31
64
+ warning: '#FFC46B', // 4.08:1 as type; the mobile button's black label 13.36
65
+ success: '#A5E27E', // 4.20:1 as type
66
+ background: '#E9E1CE',
67
+ surface: '#6E5C44',
68
+ text: '#413A2C', // 8.64:1 on the ground — this ink is for the BIG UI
69
+ textMuted: '#585040', // 6.12:1 on the ground
70
+ outline: '#3A6212', // dark forest edge: the button's ring and the panel's border
71
+ },
72
+ shape: {
73
+ radiusPill: 14,
74
+ radiusCard: 18,
75
+ glow: 'none',
76
+ imageRendering: 'auto',
77
+ borderWidth: 3,
78
+ bevel: 0.9,
79
+ },
80
+ decorations: {
81
+ // The gloss is on the small pill only. On a near-black surface it cost
82
+ // nothing to put it on the controls box as well, but against mid-brown
83
+ // furniture the highlight lifts the backdrop under the first key rows far
84
+ // enough to take their muted label from 4.65:1 to 3.88:1 — and a
85
+ // highlight is a button-and-chip device in the reference anyway, not
86
+ // something laid across an information panel.
87
+ toast: { backdrop: 'candy-gloss' },
88
+ },
89
+ elements: {
90
+ // `background` is the light ground now, and `hudBaseStyles` paints a bar
91
+ // TRACK with it — which would put a light fill inside a light channel and
92
+ // leave the reading to guesswork. The reference settles it the same way:
93
+ // its resource meters are near-black troughs precisely so the coloured
94
+ // fill is the brightest thing in the bar.
95
+ progressBar: { colors: { background: '#3A3126' } },
96
+ healthBar: {
97
+ colors: {
98
+ background: '#3A3126',
99
+ // Deeper than the global values, which are tuned to be legible as
100
+ // TYPE on the mid-brown furniture. In a near-black trough that
101
+ // tuning inverts: a pale salmon is 1.9:1 there and reads as
102
+ // neither red nor urgent, where this is 3.11:1 and unmistakable.
103
+ danger: '#E2452F',
104
+ warning: '#E89A2A',
105
+ },
106
+ },
107
+ },
108
+ };