@bitmagic/cli 0.1.59-dev.2 → 0.1.59-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 (48) hide show
  1. package/README.md +99 -0
  2. package/dist/assets/materials.d.ts +165 -0
  3. package/dist/assets/materials.js +395 -0
  4. package/dist/assets/materials.js.map +1 -0
  5. package/dist/assets/vxl-summary.js +12 -5
  6. package/dist/assets/vxl-summary.js.map +1 -1
  7. package/dist/cli.d.ts +1 -0
  8. package/dist/cli.js +2 -0
  9. package/dist/cli.js.map +1 -1
  10. package/dist/commands/assets.d.ts +25 -0
  11. package/dist/commands/assets.js +245 -2
  12. package/dist/commands/assets.js.map +1 -1
  13. package/dist/commands/generate.d.ts +4 -0
  14. package/dist/commands/generate.js +33 -2
  15. package/dist/commands/generate.js.map +1 -1
  16. package/dist/commands/theme.d.ts +3 -0
  17. package/dist/commands/theme.js +201 -0
  18. package/dist/commands/theme.js.map +1 -0
  19. package/dist/scaffold/project-files.d.ts +1 -0
  20. package/dist/scaffold/project-files.js +47 -1
  21. package/dist/scaffold/project-files.js.map +1 -1
  22. package/dist/scaffold/project.js +2 -1
  23. package/dist/scaffold/project.js.map +1 -1
  24. package/dist/theme/hud-theme-catalog.d.ts +236 -0
  25. package/dist/theme/hud-theme-catalog.js +386 -0
  26. package/dist/theme/hud-theme-catalog.js.map +1 -0
  27. package/dist/theme/theme-color-math.d.ts +21 -0
  28. package/dist/theme/theme-color-math.js +99 -0
  29. package/dist/theme/theme-color-math.js.map +1 -0
  30. package/dist/theme/theme-io.d.ts +49 -0
  31. package/dist/theme/theme-io.js +190 -0
  32. package/dist/theme/theme-io.js.map +1 -0
  33. package/dist/theme/theme-merge.d.ts +36 -0
  34. package/dist/theme/theme-merge.js +81 -0
  35. package/dist/theme/theme-merge.js.map +1 -0
  36. package/dist/theme/theme-report.d.ts +28 -0
  37. package/dist/theme/theme-report.js +142 -0
  38. package/dist/theme/theme-report.js.map +1 -0
  39. package/dist/theme/theme-stored.d.ts +21 -0
  40. package/dist/theme/theme-stored.js +50 -0
  41. package/dist/theme/theme-stored.js.map +1 -0
  42. package/dist/theme/theme-validate.d.ts +41 -0
  43. package/dist/theme/theme-validate.js +406 -0
  44. package/dist/theme/theme-validate.js.map +1 -0
  45. package/dist/verify/hud-theme.d.ts +5 -3
  46. package/dist/verify/hud-theme.js +5 -3
  47. package/dist/verify/hud-theme.js.map +1 -1
  48. package/package.json +4 -4
@@ -0,0 +1,386 @@
1
+ // Agent-side mirror of the engine's HUD theme catalog. Kept in sync by hand —
2
+ // agent tools can't import from `game/src/engine/` because the two projects
3
+ // have separate tsconfig include sets. When you add a font/decoration/preset
4
+ // in `game/src/engine/hud/`, mirror it here so the agent's catalog tool and
5
+ // validator see it.
6
+ //
7
+ // What the agent uses these for:
8
+ // - `get_hud_catalog` returns this verbatim so the agent can list what's
9
+ // available without reading source files.
10
+ // - `write_hud_theme` validates that font/decoration references resolve
11
+ // against this catalog before writing to world.json.
12
+ //
13
+ // What's NOT here:
14
+ // - Full theme schema validation (the engine's `resolveWorldTheme` falls
15
+ // back to the default look with a console warning if a written theme is structurally
16
+ // bad — that's the safety net).
17
+ // - Per-decoration SVG markup (not needed at write time).
18
+ export const HUD_PRESETS = [
19
+ 'rift-raider',
20
+ 'village-keep',
21
+ 'nexus',
22
+ 'simulator',
23
+ 'racing',
24
+ ];
25
+ // Agent-only choose-metadata: one-line vibe per preset so the agent can match a
26
+ // user's brief to a preset without trial and error (same species as the fonts'
27
+ // `evokes` labels). The engine has no counterpart field — deliberately NOT part
28
+ // of the drift-checked mirror surface.
29
+ /**
30
+ * The five presets' ACTUAL token values, mirrored from `game/src/engine/hud/themes/*.ts`.
31
+ *
32
+ * This exists because the promoted customization flow — "preset X but with
33
+ * orange accents" — was unimplementable without it. `read-hud-theme` returns a
34
+ * preset's NAME, `write-hud-theme` does a full replace rather than a merge, and
35
+ * the engine source that holds the values is not readable from the hosted agent.
36
+ * So an agent asked to tweak an active preset had nothing to patch and had to
37
+ * invent a whole theme "in that preset's spirit", which is how a tweak request
38
+ * silently became a redesign.
39
+ *
40
+ * Each entry is the RAW preset data, which is the same shape as an inline theme
41
+ * — so it can be spread, edited and written straight back through
42
+ * `write-hud-theme`. Use `presetTheme(name)` rather than reading this directly:
43
+ * it strips `evokes`, which is authoring metadata and not a theme token.
44
+ *
45
+ * Hand-mirrored and drift-checked by `scripts/check-hud-catalog.ts`, which deep
46
+ * compares every value against the engine modules.
47
+ */
48
+ export const HUD_PRESET_THEMES = {
49
+ "rift-raider": {
50
+ name: 'Rift Raider',
51
+ evokes: 'Mobile action-RPG — cast-gold medallion frames on dark indigo glass, chunky cream type with a dark ink ring, royal borders (Diablo-style)',
52
+ font: {
53
+ key: 'baloo-2',
54
+ case: 'upper',
55
+ weightBody: 500,
56
+ weightHeading: 700,
57
+ trackingLabel: 0.8,
58
+ outlineWidth: 2,
59
+ },
60
+ colors: {
61
+ primary: '#F0B23A',
62
+ danger: '#D6332E',
63
+ warning: '#E07A28',
64
+ success: '#5FB35A',
65
+ background: '#0B0716',
66
+ surface: '#191228',
67
+ text: '#FFF6E2',
68
+ textMuted: '#B9A889',
69
+ outline: '#5A3D0C',
70
+ },
71
+ shape: {
72
+ radiusPill: 14,
73
+ radiusCard: 14,
74
+ glow: 'gold',
75
+ imageRendering: 'auto',
76
+ borderWidth: 2,
77
+ bevel: 0.85,
78
+ },
79
+ decorations: {
80
+ progressBar: {
81
+ borderImage: 'royal-frame',
82
+ },
83
+ healthBar: {
84
+ borderImage: 'royal-frame',
85
+ },
86
+ toast: {
87
+ borderImage: 'royal-frame',
88
+ },
89
+ controls: {
90
+ backdrop: 'grain-texture',
91
+ },
92
+ },
93
+ },
94
+ "village-keep": {
95
+ name: 'Village Keep',
96
+ 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)',
97
+ font: {
98
+ key: 'fredoka',
99
+ case: 'upper',
100
+ weightBody: 500,
101
+ weightHeading: 700,
102
+ trackingLabel: 0.6,
103
+ outlineWidth: 2,
104
+ },
105
+ colors: {
106
+ primary: '#9BDB4F',
107
+ danger: '#FFA898',
108
+ warning: '#FFC46B',
109
+ success: '#A5E27E',
110
+ background: '#E9E1CE',
111
+ surface: '#6E5C44',
112
+ text: '#413A2C',
113
+ textMuted: '#585040',
114
+ outline: '#3A6212',
115
+ },
116
+ shape: {
117
+ radiusPill: 14,
118
+ radiusCard: 18,
119
+ glow: 'none',
120
+ imageRendering: 'auto',
121
+ borderWidth: 3,
122
+ bevel: 0.9,
123
+ },
124
+ decorations: {
125
+ toast: {
126
+ backdrop: 'candy-gloss',
127
+ },
128
+ },
129
+ elements: {
130
+ progressBar: {
131
+ colors: {
132
+ background: '#3A3126',
133
+ },
134
+ },
135
+ healthBar: {
136
+ colors: {
137
+ background: '#3A3126',
138
+ danger: '#E2452F',
139
+ warning: '#E89A2A',
140
+ },
141
+ },
142
+ },
143
+ },
144
+ "nexus": {
145
+ name: 'Nexus',
146
+ 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)',
147
+ font: {
148
+ key: 'chakra-petch',
149
+ case: 'upper',
150
+ weightBody: 500,
151
+ weightHeading: 700,
152
+ trackingLabel: 1.4,
153
+ outlineWidth: 0,
154
+ },
155
+ colors: {
156
+ primary: '#4FD8E8',
157
+ danger: '#FF6B4A',
158
+ warning: '#F0A22E',
159
+ success: '#6FD9A4',
160
+ background: '#04070C',
161
+ surface: '#0A121A',
162
+ text: '#E6F6FA',
163
+ textMuted: '#9DBBC8',
164
+ outline: '#2E9FB5',
165
+ },
166
+ shape: {
167
+ radiusPill: 6,
168
+ radiusCard: 4,
169
+ glow: 'cyan',
170
+ imageRendering: 'auto',
171
+ borderWidth: 2,
172
+ bevel: 0.5,
173
+ },
174
+ decorations: {
175
+ progressBar: {
176
+ borderImage: 'bracket-frame',
177
+ },
178
+ counter: {
179
+ borderImage: 'bracket-frame',
180
+ },
181
+ reticle: {
182
+ backdrop: 'glow-aura',
183
+ },
184
+ },
185
+ },
186
+ "simulator": {
187
+ name: 'Simulator',
188
+ 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)',
189
+ font: {
190
+ key: 'ibm-plex-sans',
191
+ case: 'upper',
192
+ weightBody: 400,
193
+ weightHeading: 700,
194
+ trackingLabel: 0.8,
195
+ outlineWidth: 0,
196
+ },
197
+ colors: {
198
+ primary: '#2E9BDB',
199
+ danger: '#C8453F',
200
+ warning: '#D8A32E',
201
+ success: '#4E9E57',
202
+ background: '#0E141B',
203
+ surface: '#161E27',
204
+ text: '#DDE5EC',
205
+ textMuted: '#A2B0BE',
206
+ outline: '#46586A',
207
+ },
208
+ shape: {
209
+ radiusPill: 4,
210
+ radiusCard: 2,
211
+ glow: 'none',
212
+ imageRendering: 'auto',
213
+ borderWidth: 1,
214
+ bevel: 0.35,
215
+ },
216
+ },
217
+ "racing": {
218
+ name: 'Racing',
219
+ evokes: 'Motorsport telemetry — white line-art chrome on black with red reserved for state, tall narrow gothic caps, amber caution / green sector',
220
+ font: {
221
+ key: 'archivo-narrow',
222
+ case: 'upper',
223
+ weightBody: 500,
224
+ weightHeading: 700,
225
+ trackingLabel: 1.2,
226
+ outlineWidth: 0,
227
+ },
228
+ colors: {
229
+ primary: '#E8EDF2',
230
+ danger: '#FF4D3A',
231
+ warning: '#FFB000',
232
+ success: '#22C55E',
233
+ background: '#07090C',
234
+ surface: '#0E1319',
235
+ text: '#F2F5F8',
236
+ textMuted: '#9BA4AE',
237
+ outline: '#C9D2DA',
238
+ },
239
+ shape: {
240
+ radiusPill: 4,
241
+ radiusCard: 2,
242
+ glow: 'none',
243
+ imageRendering: 'auto',
244
+ borderWidth: 2,
245
+ bevel: 0.5,
246
+ },
247
+ },
248
+ };
249
+ /**
250
+ * A preset's tokens as a writable inline theme — the mirror entry minus the
251
+ * `evokes` label, which describes the style rather than rendering it.
252
+ *
253
+ * The intended patch flow: `const base = presetTheme('nexus')`, apply the user's
254
+ * change, then `write-hud-theme` the result.
255
+ */
256
+ export function presetTheme(name) {
257
+ const { evokes: _evokes, ...tokens } = HUD_PRESET_THEMES[name];
258
+ return structuredClone(tokens);
259
+ }
260
+ /**
261
+ * The one-line mood label per preset, DERIVED from the mirrored preset data
262
+ * above rather than kept as a second hand-written list.
263
+ *
264
+ * It used to be an independent map explicitly excluded from the drift gate, on
265
+ * the grounds that the engine had no counterpart. It then rotted: three of five
266
+ * labels described styles that had since been retuned, and this is the field an
267
+ * agent picks a preset BY. The engine presets carry `evokes` beside their tokens
268
+ * now, so the description and the style are one edit and one check.
269
+ */
270
+ export const HUD_PRESET_INFO = Object.fromEntries(Object.keys(HUD_PRESET_THEMES).map((n) => [n, { evokes: HUD_PRESET_THEMES[n].evokes }]));
271
+ export const HUD_FONTS = {
272
+ 'red-hat-display': { family: 'Red Hat Display', weights: [300, 400, 500, 700], suitsCase: ['upper', 'normal'], evokes: 'Default Bitmagic — warm, technical, modern sans' },
273
+ 'chakra-petch': { family: 'Chakra Petch', weights: [300, 400, 500, 600, 700], suitsCase: ['upper', 'normal'], evokes: 'Chamfered techno sans — holographic HUD, sci-fi console, cut corners' },
274
+ 'ibm-plex-sans': { family: 'IBM Plex Sans', weights: [300, 400, 500, 600, 700], suitsCase: ['upper', 'normal'], evokes: 'Engineered humanist sans — instrument panel, operator console, tabular data' },
275
+ 'archivo-narrow': { family: 'Archivo Narrow', weights: [400, 500, 600, 700], suitsCase: ['upper', 'normal'], evokes: 'Narrow gothic that keeps its ink — motorsport telemetry, broadcast overlay' },
276
+ 'bebas-neue': { family: 'Bebas Neue', weights: [400], suitsCase: ['upper', 'normal'], evokes: 'Tall, bold display — sports, action, news ticker' },
277
+ 'press-start-2p': { family: 'Press Start 2P', weights: [400], suitsCase: ['upper', 'normal'], evokes: 'Retro arcade pixel — 8-bit, NES, chiptune' },
278
+ 'creepster': { family: 'Creepster', weights: [400], suitsCase: ['normal'], evokes: 'Horror, halloween, dripping — already display-styled' },
279
+ 'pacifico': { family: 'Pacifico', weights: [400], suitsCase: ['normal'], evokes: 'Handwritten cursive — tropical, beachy, casual' },
280
+ 'space-grotesk': { family: 'Space Grotesk', weights: [400, 500, 700], suitsCase: ['upper', 'normal'], evokes: 'Geometric sans — sci-fi, technical, modern' },
281
+ 'rubik-mono-one': { family: 'Rubik Mono One', weights: [400], suitsCase: ['upper', 'normal'], evokes: 'Heavy, slabby display — bold, blocky, attention-grabbing' },
282
+ 'vt323': { family: 'VT323', weights: [400], suitsCase: ['upper', 'normal'], evokes: 'CRT terminal monospace — retro computer, hacker, glitch' },
283
+ 'orbitron': { family: 'Orbitron', weights: [400, 500, 700, 900], suitsCase: ['upper', 'normal'], evokes: 'Futuristic geometric — sci-fi, cyber, racing HUD' },
284
+ 'shrikhand': { family: 'Shrikhand', weights: [400], suitsCase: ['normal'], evokes: 'Italic display — celebratory, party, energetic' },
285
+ 'baloo-2': { family: 'Baloo 2', weights: [400, 500, 600, 700, 800], suitsCase: ['upper', 'normal'], evokes: 'Rounded chunky sans with a real weight range — mobile action-RPG chrome' },
286
+ 'lilita-one': { family: 'Lilita One', weights: [400], suitsCase: ['upper', 'normal'], evokes: 'Chunky rounded comic display — cartoon battler, toon town' },
287
+ 'fredoka': { family: 'Fredoka', weights: [300, 400, 500, 700], suitsCase: ['upper', 'normal'], evokes: 'Soft rounded bubble sans — candy, casual mobile, sweet' },
288
+ 'grenze-gotisch': { family: 'Grenze Gotisch', weights: [400, 500, 700, 900], suitsCase: ['normal'], evokes: 'Readable blackletter — dark fantasy, gothic dungeon' },
289
+ 'cinzel': { family: 'Cinzel', weights: [400, 500, 700, 900], suitsCase: ['upper', 'normal'], evokes: 'Carved Roman caps — epic fantasy, ancient temple' },
290
+ };
291
+ export const HUD_DECORATIONS = {
292
+ 'drip-border': { suitsSlots: ['borderImage', 'decorationAfter'], evokes: 'Horror drips on edges' },
293
+ 'pixel-corners': { suitsSlots: ['borderImage'], evokes: '8-bit pixel corner brackets' },
294
+ 'scanline': { suitsSlots: ['backdrop'], evokes: 'CRT scanlines tiled across the surface' },
295
+ 'vine-corner': { suitsSlots: ['borderImage', 'decorationBefore'], evokes: 'Tropical vines / leaves in corners' },
296
+ 'glow-aura': { suitsSlots: ['backdrop', 'decorationBefore', 'decorationAfter'], evokes: 'Soft radial glow halo behind the element' },
297
+ 'bracket-frame': { suitsSlots: ['borderImage'], evokes: 'Sci-fi targeting brackets on each corner' },
298
+ 'ribbon-edge': { suitsSlots: ['decorationAfter', 'decorationBefore'], evokes: 'Bunting / banner saw-tooth edge' },
299
+ 'circuit-trace': { suitsSlots: ['backdrop'], evokes: 'PCB / circuit board trace pattern' },
300
+ 'candy-gloss': { suitsSlots: ['backdrop', 'decorationBefore'], evokes: 'Glossy sugar highlight across the top — candy button shine' },
301
+ 'ornate-corner': { suitsSlots: ['borderImage'], evokes: 'Gothic filigree corner frame — dark fantasy, dungeon' },
302
+ 'royal-frame': { suitsSlots: ['borderImage'], evokes: 'Double gold-trim picture frame with corner studs — epic fantasy' },
303
+ 'hazard-stripes': { suitsSlots: ['backdrop'], evokes: 'Faint diagonal caution stripes — military / sci-fi warning panel' },
304
+ 'pixel-frame': { suitsSlots: ['borderImage'], evokes: 'NES dialog double-ring pixel border' },
305
+ 'grain-texture': { suitsSlots: ['backdrop'], evokes: 'Subtle parchment / leather grain tooth' },
306
+ };
307
+ // The engine's DEFAULT theme (bitmagic) as raw preset data — the base a patch
308
+ // applies to when the game has no theme set. Mirrors BITMAGIC_THEME_DATA in
309
+ // game/src/engine/hud/themes/bitmagic.ts, drift-checked like the presets. It is
310
+ // deliberately NOT in HUD_PRESET_THEMES: bitmagic is the fallback, not a
311
+ // selectable preset, and listing it would put it back in the catalog the agent
312
+ // offers users.
313
+ export const DEFAULT_THEME_TOKENS = {
314
+ name: 'Bitmagic',
315
+ font: {
316
+ key: 'red-hat-display',
317
+ case: 'upper',
318
+ weightBody: 400,
319
+ weightHeading: 700,
320
+ trackingLabel: 1.6,
321
+ },
322
+ colors: {
323
+ primary: '#A0DAB9',
324
+ danger: '#E0218A',
325
+ warning: '#FF8200',
326
+ success: '#F9E547',
327
+ background: '#0b0b0b',
328
+ surface: '#181818',
329
+ text: '#ffffff',
330
+ textMuted: '#b3b3b3',
331
+ },
332
+ shape: {
333
+ radiusPill: 500,
334
+ radiusCard: 8,
335
+ glow: 'aqua',
336
+ imageRendering: 'auto',
337
+ },
338
+ };
339
+ // The curated decorations' SVG SOURCE, verbatim from game/src/engine/hud/
340
+ // decorations.ts and drift-checked byte-for-byte. Exposed through
341
+ // get-hud-catalog's decorationSvg input as ADAPTATION REFERENCE: an agent
342
+ // authoring a custom inline decoration copies the closest curated one and
343
+ // edits, instead of inventing SVG from nothing — sizing rules included.
344
+ export const HUD_DECORATION_SVGS = {
345
+ 'drip-border': "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 60 60\" preserveAspectRatio=\"none\"><rect x=\"0\" y=\"0\" width=\"60\" height=\"2\" fill=\"__primary__\"/><rect x=\"0\" y=\"0\" width=\"2\" height=\"60\" fill=\"__primary__\"/><rect x=\"58\" y=\"0\" width=\"2\" height=\"60\" fill=\"__primary__\"/><path d=\"M0,58 L60,58 L60,50 Q54,60 48,52 Q42,62 36,53 Q30,64 24,54 Q18,60 12,52 Q6,62 0,52 Z\" fill=\"__primary__\"/></svg>",
346
+ 'pixel-corners': "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 12 12\" shape-rendering=\"crispEdges\"><path d=\"M0,0 H4 V2 H2 V4 H0 Z M8,0 H12 V4 H10 V2 H8 Z M0,8 H2 V10 H4 V12 H0 Z M10,8 H12 V12 H8 V10 H10 Z\" fill=\"__primary__\"/></svg>",
347
+ 'scanline': "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 4 4\" preserveAspectRatio=\"none\"><rect width=\"4\" height=\"1\" fill=\"__primary__\" opacity=\"0.15\"/></svg>",
348
+ 'vine-corner': "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 40 40\"><path d=\"M0,40 Q0,20 8,12 Q16,4 24,8 Q20,16 12,16 Q4,20 4,40 Z\" fill=\"__success__\" opacity=\"0.7\"/><circle cx=\"10\" cy=\"14\" r=\"2\" fill=\"__success__\"/><circle cx=\"16\" cy=\"10\" r=\"1.5\" fill=\"__success__\"/></svg>",
349
+ 'glow-aura': "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 100 100\"><defs><radialGradient id=\"g\"><stop offset=\"0%\" stop-color=\"__primary__\" stop-opacity=\"0.5\"/><stop offset=\"60%\" stop-color=\"__primary__\" stop-opacity=\"0.1\"/><stop offset=\"100%\" stop-color=\"__primary__\" stop-opacity=\"0\"/></radialGradient></defs><rect width=\"100\" height=\"100\" fill=\"url(#g)\"/></svg>",
350
+ 'bracket-frame': "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><path d=\"M0,0 H8 V1 H1 V8 H0 Z M16,0 H24 V8 H23 V1 H16 Z M0,16 H1 V23 H8 V24 H0 Z M16,24 V23 H23 V16 H24 V24 Z\" fill=\"__primary__\"/></svg>",
351
+ 'ribbon-edge': "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 30 8\" preserveAspectRatio=\"none\"><path d=\"M0,0 L30,0 L30,4 L26,8 L22,4 L18,8 L14,4 L10,8 L6,4 L2,8 L0,4 Z\" fill=\"__primary__\"/></svg>",
352
+ 'circuit-trace': "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 32 32\"><path d=\"M0,16 H10 M22,16 H32 M16,0 V10 M16,22 V32\" stroke=\"__primary__\" stroke-width=\"1\" fill=\"none\"/><circle cx=\"16\" cy=\"16\" r=\"2\" fill=\"none\" stroke=\"__primary__\" stroke-width=\"1\"/></svg>",
353
+ 'candy-gloss': "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 100 40\" preserveAspectRatio=\"none\"><radialGradient id=\"cgh\" cx=\".5\" cy=\".28\" r=\".72\"><stop offset=\"0\" stop-color=\"#fff\" stop-opacity=\".38\"/><stop offset=\".55\" stop-color=\"#fff\" stop-opacity=\".15\"/><stop offset=\"1\" stop-color=\"#fff\" stop-opacity=\"0\"/></radialGradient><ellipse cx=\"50\" cy=\"8\" rx=\"48\" ry=\"13\" fill=\"url(#cgh)\"/></svg>",
354
+ 'ornate-corner': "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 48 48\"><defs><g id=\"f\"><path d=\"M2 14 Q2 2 14 2\" fill=\"none\" stroke=\"__primary__\" stroke-width=\"2\"/><path d=\"M8 8 L11 5 L14 8 L11 11 Z\" fill=\"__primary__\"/></g></defs><rect x=\"5\" y=\"5\" width=\"38\" height=\"38\" fill=\"none\" stroke=\"__primary__\" stroke-width=\"1.5\"/><use href=\"#f\"/><use href=\"#f\" transform=\"rotate(90 24 24)\"/><use href=\"#f\" transform=\"rotate(180 24 24)\"/><use href=\"#f\" transform=\"rotate(270 24 24)\"/></svg>",
355
+ 'royal-frame': "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 48 48\"><rect x=\"3\" y=\"3\" width=\"42\" height=\"42\" rx=\"6\" fill=\"none\" stroke=\"__primary__\" stroke-width=\"2\"/><rect x=\"8\" y=\"8\" width=\"32\" height=\"32\" rx=\"3\" fill=\"none\" stroke=\"__primary__\" stroke-width=\"1\" opacity=\"0.6\"/><circle cx=\"6\" cy=\"6\" r=\"2.4\" fill=\"__primary__\"/><circle cx=\"42\" cy=\"6\" r=\"2.4\" fill=\"__primary__\"/><circle cx=\"6\" cy=\"42\" r=\"2.4\" fill=\"__primary__\"/><circle cx=\"42\" cy=\"42\" r=\"2.4\" fill=\"__primary__\"/></svg>",
356
+ 'hazard-stripes': "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\"><path d=\"M-4 4 L4 -4 M0 16 L16 0 M12 20 L20 12\" stroke=\"__warning__\" stroke-width=\"4\" opacity=\"0.12\" fill=\"none\"/></svg>",
357
+ 'pixel-frame': "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\" shape-rendering=\"crispEdges\"><path fill-rule=\"evenodd\" d=\"M0 0 H16 V16 H0 Z M1 1 V15 H15 V1 Z\" fill=\"__text__\"/><path fill-rule=\"evenodd\" d=\"M3 3 H13 V13 H3 Z M4 4 V12 H12 V4 Z\" fill=\"__primary__\"/></svg>",
358
+ 'grain-texture': "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 40 40\"><g fill=\"__text__\" opacity=\"0.07\"><rect x=\"3\" y=\"5\" width=\"1\" height=\"1\"/><rect x=\"11\" y=\"2\" width=\"1\" height=\"1\"/><rect x=\"19\" y=\"9\" width=\"1\" height=\"1\"/><rect x=\"27\" y=\"4\" width=\"1\" height=\"1\"/><rect x=\"35\" y=\"12\" width=\"1\" height=\"1\"/><rect x=\"6\" y=\"17\" width=\"1\" height=\"1\"/><rect x=\"15\" y=\"22\" width=\"1\" height=\"1\"/><rect x=\"24\" y=\"18\" width=\"1\" height=\"1\"/><rect x=\"33\" y=\"26\" width=\"1\" height=\"1\"/><rect x=\"2\" y=\"29\" width=\"1\" height=\"1\"/><rect x=\"12\" y=\"34\" width=\"1\" height=\"1\"/><rect x=\"22\" y=\"31\" width=\"1\" height=\"1\"/><rect x=\"30\" y=\"37\" width=\"1\" height=\"1\"/><rect x=\"38\" y=\"33\" width=\"1\" height=\"1\"/></g></svg>",
359
+ };
360
+ export const HUD_GLOW_KEYS = ['aqua', 'pink', 'warm', 'horror-red', 'gold', 'cyan', 'none'];
361
+ export const HUD_ELEMENT_CLASSES = ['progressBar', 'healthBar', 'counter', 'iconText', 'timer', 'toast', 'controls', 'reticle', 'mobileControls'];
362
+ // ThemeShape's field names, for the drift gate's membership check — a new shape
363
+ // token added engine-side without reaching this list (and the validator, and
364
+ // get-hud-catalog's ranges) is a loud CI failure instead of a knob agents
365
+ // cannot see.
366
+ export const HUD_SHAPE_TOKENS = ['radiusPill', 'radiusCard', 'glow', 'imageRendering', 'borderWidth', 'bevel', 'gloss', 'glowColor'];
367
+ export const HUD_COLOR_TOKENS = ['primary', 'danger', 'warning', 'success', 'background', 'surface', 'text', 'textMuted', 'outline'];
368
+ export const HUD_REQUIRED_COLORS = ['primary', 'danger', 'background', 'surface', 'text'];
369
+ export const HUD_DECORATION_SLOTS = ['borderImage', 'backdrop', 'decorationBefore', 'decorationAfter'];
370
+ // Built-in icon slots a theme can override with custom SVG markup. Each value
371
+ // is inline SVG (≤16kb). SVGs may use `currentColor` so the icon follows the
372
+ // surrounding text color, OR the same `__primary__` / `__danger__` / etc.
373
+ // color tokens that decorations use — the engine substitutes them at apply time.
374
+ export const HUD_ICON_SLOTS = [
375
+ { key: 'heart', description: 'Health label icon (shown next to "HP" on the player health bar). Default: filled heart.' },
376
+ { key: 'mouse', description: 'Pointer-lock overlay icon ("Click to play" screen). Default: outlined mouse.' },
377
+ { key: 'arrow', description: 'Movement-key arrow used in the controls overlay. ONE SVG — CSS rotates it for down/left/right. Default: thin chevron pointing up.' },
378
+ ];
379
+ export const HUD_ICON_KEYS = HUD_ICON_SLOTS.map(s => s.key);
380
+ // The strict validator lives in theme-validate.ts — everything the old
381
+ // lightValidateTheme checked plus glow keys, numeric ranges, the elements
382
+ // block, slot suitability and decoration size/position/repeat. Re-exported
383
+ // under the old name so existing imports keep working; new code should import
384
+ // validateThemeStrict directly.
385
+ export { validateThemeStrict, validateThemeStrict as lightValidateTheme, isEngineFatalIssue, suggestClosest } from './theme-validate.js';
386
+ //# sourceMappingURL=hud-theme-catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hud-theme-catalog.js","sourceRoot":"","sources":["../../src/theme/hud-theme-catalog.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Hand-mirror of game/src/engine/hud/colorMath.ts — the WCAG arithmetic behind
3
+ * the derived HUD inks. The theme report computes its contrast pairings with
4
+ * EXACTLY the maths the engine will apply, so a SUBSTITUTED line in the report
5
+ * is a promise about what will render, not an estimate.
6
+ *
7
+ * Mirrored by hand because agent tools cannot import engine source (separate
8
+ * tsconfig include sets). Drift-checked BEHAVIOURALLY by scripts/
9
+ * check-hud-catalog.ts: the gate imports both copies under tsx and compares
10
+ * their outputs over every preset palette plus adversarial pairs, so a changed
11
+ * threshold or mix factor on either side goes red in CI.
12
+ */
13
+ export declare function relLuminance(hex: string): number;
14
+ export declare function contrastRatio(a: string, b: string): number;
15
+ export declare function mixHex(from: string, to: string, amount: number): string;
16
+ export declare function readableTextColor(hex: string): string;
17
+ export declare const ON_SURFACE_MIN_CONTRAST = 3;
18
+ export declare function inkOnSurface(surface: string, preferred: string): string;
19
+ export declare const ACCENT_INK_MIN_CONTRAST = 4.5;
20
+ export declare function accentInkOn(ground: string, accent: string): string | null;
21
+ export declare function mutedInkOnSurface(surface: string, preferred: string): string;
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Hand-mirror of game/src/engine/hud/colorMath.ts — the WCAG arithmetic behind
3
+ * the derived HUD inks. The theme report computes its contrast pairings with
4
+ * EXACTLY the maths the engine will apply, so a SUBSTITUTED line in the report
5
+ * is a promise about what will render, not an estimate.
6
+ *
7
+ * Mirrored by hand because agent tools cannot import engine source (separate
8
+ * tsconfig include sets). Drift-checked BEHAVIOURALLY by scripts/
9
+ * check-hud-catalog.ts: the gate imports both copies under tsx and compares
10
+ * their outputs over every preset palette plus adversarial pairs, so a changed
11
+ * threshold or mix factor on either side goes red in CI.
12
+ */
13
+ export function relLuminance(hex) {
14
+ const lin = (v) => (v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4));
15
+ return 0.2126 * lin(parseInt(hex.slice(1, 3), 16) / 255)
16
+ + 0.7152 * lin(parseInt(hex.slice(3, 5), 16) / 255)
17
+ + 0.0722 * lin(parseInt(hex.slice(5, 7), 16) / 255);
18
+ }
19
+ export function contrastRatio(a, b) {
20
+ const la = relLuminance(a);
21
+ const lb = relLuminance(b);
22
+ return (Math.max(la, lb) + 0.05) / (Math.min(la, lb) + 0.05);
23
+ }
24
+ export function mixHex(from, to, amount) {
25
+ const channel = (i) => {
26
+ const f = parseInt(from.slice(i, i + 2), 16);
27
+ const t = parseInt(to.slice(i, i + 2), 16);
28
+ return Math.round(f * amount + t * (1 - amount)).toString(16).padStart(2, '0');
29
+ };
30
+ return `#${channel(1)}${channel(3)}${channel(5)}`;
31
+ }
32
+ export function readableTextColor(hex) {
33
+ if (!/^#[0-9a-fA-F]{6}$/.test(hex))
34
+ return '#ffffff';
35
+ return relLuminance(hex) > 0.5 ? '#000000' : '#ffffff';
36
+ }
37
+ // The ink for anything painted ON `surface`, plus its muted companion.
38
+ //
39
+ // Same species as --hud-color-on-primary: the engine picks the readable pair so a
40
+ // theme author does not have to hand-author contrast per element. It exists
41
+ // because `text` carries TWO jobs that only agree on a uniformly dark theme. It is
42
+ // the ink on the `background` canvas — a game's own dialogs paint themselves with
43
+ // that pair — AND the ink on every counter, timer, toast, bubble and panel filled
44
+ // with `surface`. A style whose big UI is a light canvas and whose HUD furniture is
45
+ // darker cannot satisfy both from one value: with a single ink the furniture caps
46
+ // out around #9E9276, which is 1.4:1 against a sunny world and so not furniture at
47
+ // all. Village Keep spent three rounds oscillating between a washed-out HUD and a
48
+ // uniformly dark one for exactly this reason.
49
+ //
50
+ // It PREFERS the theme's own ink, because a tinted parchment or a cold cyan is part
51
+ // of a style's identity and must survive. It substitutes only where the declared
52
+ // pairing is unusable — below 3:1, the WCAG floor for large text, and far below
53
+ // every pairing in the catalog: the presets measure 9.6 to 17.8 for `text` and 5.7
54
+ // to 9.3 for `textMuted`, so this cannot fire on a theme that was already coherent.
55
+ export const ON_SURFACE_MIN_CONTRAST = 3;
56
+ export function inkOnSurface(surface, preferred) {
57
+ if (!/^#[0-9a-fA-F]{6}$/.test(surface) || !/^#[0-9a-fA-F]{6}$/.test(preferred))
58
+ return preferred;
59
+ if (contrastRatio(preferred, surface) >= ON_SURFACE_MIN_CONTRAST)
60
+ return preferred;
61
+ return readableTextColor(surface);
62
+ }
63
+ // Target 4.5:1 rather than the 3:1 the on-surface inks use: this one paints
64
+ // headings and status lines, which are body-scale on some surfaces, and the
65
+ // margin is free — the lowest any shipped preset measures is 6.02:1, so raising
66
+ // the bar cannot make the token fire on a theme that was already fine.
67
+ export const ACCENT_INK_MIN_CONTRAST = 4.5;
68
+ export function accentInkOn(ground, accent) {
69
+ if (!/^#[0-9a-fA-F]{6}$/.test(ground) || !/^#[0-9a-fA-F]{6}$/.test(accent))
70
+ return null;
71
+ if (contrastRatio(accent, ground) >= ACCENT_INK_MIN_CONTRAST)
72
+ return null;
73
+ // Walk the accent toward the ground's opposite pole and stop at the FIRST value
74
+ // that clears, so the result keeps as much of the accent as the ground allows.
75
+ // Mixing toward black or white preserves the HUE, which is the part that makes
76
+ // an accent an accent: village-keep's candy lime lands on a forest green rather
77
+ // than on brown, and a forest green on parchment is what the reference draws.
78
+ const pole = relLuminance(ground) > 0.5 ? '#000000' : '#ffffff';
79
+ for (let keep = 0.95; keep > 0.05; keep -= 0.05) {
80
+ const candidate = mixHex(accent, pole, keep);
81
+ if (contrastRatio(candidate, ground) >= ACCENT_INK_MIN_CONTRAST)
82
+ return candidate;
83
+ }
84
+ return readableTextColor(ground);
85
+ }
86
+ export function mutedInkOnSurface(surface, preferred) {
87
+ if (!/^#[0-9a-fA-F]{6}$/.test(surface) || !/^#[0-9a-fA-F]{6}$/.test(preferred))
88
+ return preferred;
89
+ if (contrastRatio(preferred, surface) >= ON_SURFACE_MIN_CONTRAST)
90
+ return preferred;
91
+ // A secondary label steps BACK toward its own backdrop rather than taking the
92
+ // full-strength ink — otherwise the substitution would make muted text the
93
+ // loudest thing on the element it was meant to sit quietly on. 0.78 is the
94
+ // point where it still clears AA on the lightest surface that can reach this
95
+ // branch at all (a mid-brown at 4.65:1) while reading as clearly quieter than
96
+ // the full ink beside it.
97
+ return mixHex(readableTextColor(surface), surface, 0.78);
98
+ }
99
+ //# sourceMappingURL=theme-color-math.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme-color-math.js","sourceRoot":"","sources":["../../src/theme/theme-color-math.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ import type { JsonObject } from '../project/world-json.js';
2
+ export interface StoredTheme {
3
+ kind: 'preset' | 'custom' | 'none' | 'unknown-preset';
4
+ stored: unknown;
5
+ /** The tokens the engine renders for this stored value. */
6
+ effective: Record<string, unknown>;
7
+ /** Human-readable description of where `effective` came from. */
8
+ label: string;
9
+ }
10
+ /** worldProfileData.hud.theme — the ONLY path the engine reads a theme from. */
11
+ export declare function readStoredTheme(world: JsonObject): StoredTheme;
12
+ /**
13
+ * Parse a `set`/`patch` argument: a preset name, inline JSON, `@file`, or (for
14
+ * `set`) the literal `null`. Files keep long inline themes off the shell line,
15
+ * where quoting mangles them.
16
+ */
17
+ export declare function parseThemeArgument(raw: string, readFile: (path: string) => string): {
18
+ kind: 'preset';
19
+ name: string;
20
+ } | {
21
+ kind: 'reset';
22
+ } | {
23
+ kind: 'object';
24
+ value: Record<string, unknown>;
25
+ };
26
+ export interface PreparedWrite {
27
+ /** What to store at worldProfileData.hud.theme. */
28
+ value: unknown;
29
+ /** The tokens that value renders as (for the report). */
30
+ effective: Record<string, unknown>;
31
+ baseLabel: string;
32
+ warnings: Array<{
33
+ path: string;
34
+ message: string;
35
+ suggestion?: string;
36
+ }>;
37
+ }
38
+ /** `set`: full replace with a preset name, inline object, or null. */
39
+ export declare function prepareSet(argument: ReturnType<typeof parseThemeArgument>, current: StoredTheme): PreparedWrite;
40
+ /** `patch`: merge onto the current effective theme, validate the whole result. */
41
+ export declare function preparePatch(patch: Record<string, unknown>, current: StoredTheme): PreparedWrite;
42
+ /** The report both lanes print — identical text to the hosted tool's. */
43
+ export declare function themeReport(prepared: PreparedWrite, before: StoredTheme): string;
44
+ /** `check`/`show`: verdict + report for what is stored right now. */
45
+ export declare function checkStoredTheme(current: StoredTheme): {
46
+ valid: boolean;
47
+ problems: string[];
48
+ report: string;
49
+ };