@puzzmo/sdk 1.0.32 → 1.0.33

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 (35) hide show
  1. package/dist/{createSimulator-COj3lAeu.js → createSimulator-Bo6J_KC_.js} +419 -294
  2. package/dist/createSimulator-Bo6J_KC_.js.map +1 -0
  3. package/dist/{createSimulator-DIT36V1k.cjs → createSimulator-EBKHk3L6.cjs} +56 -35
  4. package/dist/createSimulator-EBKHk3L6.cjs.map +1 -0
  5. package/dist/fonts.cjs +1 -1
  6. package/dist/fonts.cjs.map +1 -1
  7. package/dist/fonts.d.ts +13 -13
  8. package/dist/fonts.js +1 -1
  9. package/dist/fonts.js.map +1 -1
  10. package/dist/index.d.ts +1 -1
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/simulator/createSimulator.d.ts.map +1 -1
  13. package/dist/simulator/index.cjs +1 -1
  14. package/dist/simulator/index.d.ts +1 -1
  15. package/dist/simulator/index.d.ts.map +1 -1
  16. package/dist/simulator/index.js +1 -1
  17. package/dist/simulator/standalone.cjs +1 -1
  18. package/dist/simulator/standalone.js +1 -1
  19. package/dist/simulator/state.d.ts +3 -1
  20. package/dist/simulator/state.d.ts.map +1 -1
  21. package/dist/simulator/types.d.ts +22 -1
  22. package/dist/simulator/types.d.ts.map +1 -1
  23. package/dist/simulator/views/HostView.d.ts +9 -0
  24. package/dist/simulator/views/HostView.d.ts.map +1 -0
  25. package/dist/simulator/views/index.d.ts +1 -0
  26. package/dist/simulator/views/index.d.ts.map +1 -1
  27. package/dist/types.d.ts +31 -2
  28. package/dist/types.d.ts.map +1 -1
  29. package/dist/vite.cjs.map +1 -1
  30. package/dist/vite.d.ts +19 -0
  31. package/dist/vite.d.ts.map +1 -1
  32. package/dist/vite.js.map +1 -1
  33. package/package.json +1 -1
  34. package/dist/createSimulator-COj3lAeu.js.map +0 -1
  35. package/dist/createSimulator-DIT36V1k.cjs.map +0 -1
@@ -314,9 +314,26 @@ var r = {
314
314
  fixturePuzzle: "simulator-fixture-puzzle",
315
315
  renderHost: "simulator-render-host",
316
316
  renderContext: "simulator-render-context",
317
- gameSettings: "simulator-game-settings"
317
+ gameSettings: "simulator-game-settings",
318
+ hostContext: "simulator-host-context"
318
319
  };
320
+ /** The Host tab's persisted `hostContext` override, or null when the tab hasn't set one. */
319
321
  function i() {
322
+ let e = localStorage.getItem(r.hostContext);
323
+ if (!e) return null;
324
+ try {
325
+ let t = JSON.parse(e);
326
+ if (Array.isArray(t)) return t;
327
+ } catch (e) {}
328
+ return null;
329
+ }
330
+ function a(e) {
331
+ localStorage.setItem(r.hostContext, JSON.stringify(e));
332
+ }
333
+ function o() {
334
+ localStorage.removeItem(r.hostContext);
335
+ }
336
+ function s() {
320
337
  let e = localStorage.getItem(r.gameSettings);
321
338
  if (!e) return {};
322
339
  try {
@@ -325,7 +342,7 @@ function i() {
325
342
  } catch (e) {}
326
343
  return {};
327
344
  }
328
- function a() {
345
+ function c() {
329
346
  let e = localStorage.getItem(r.theme);
330
347
  if (e) {
331
348
  let t = n.find((t) => t.name === e);
@@ -333,16 +350,16 @@ function a() {
333
350
  }
334
351
  return n[0];
335
352
  }
336
- function o(e) {
353
+ function l(e) {
337
354
  var t;
338
355
  let n = localStorage.getItem(r.tab);
339
356
  return n && e.includes(n) ? n : (t = e[0]) == null ? "ctrl" : t;
340
357
  }
341
- function s(e) {
358
+ function u(e) {
342
359
  let t = localStorage.getItem(r.collapsed);
343
360
  return t === null ? e : t === "true";
344
361
  }
345
- function c() {
362
+ function d() {
346
363
  let e = localStorage.getItem(r.renderHost);
347
364
  return e && [
348
365
  "game",
@@ -350,7 +367,7 @@ function c() {
350
367
  "opengraph"
351
368
  ].includes(e) ? e : "game";
352
369
  }
353
- function l() {
370
+ function f() {
354
371
  let e = localStorage.getItem(r.renderContext);
355
372
  if (e && [
356
373
  "preview",
@@ -359,49 +376,55 @@ function l() {
359
376
  "timeline"
360
377
  ].includes(e)) return e;
361
378
  }
362
- function u(e, t, n) {
363
- var u, d;
364
- let f = localStorage.getItem(r.fixtureCategory), p = localStorage.getItem(r.fixturePuzzle);
379
+ function p(e, t, n) {
380
+ var a, o, p;
381
+ let m = localStorage.getItem(r.fixtureCategory), h = localStorage.getItem(r.fixturePuzzle), g = i();
365
382
  return {
366
- isCollapsed: s((u = e.collapsed) == null ? !0 : u),
383
+ hostContext: (a = g == null ? e.hostContext : g) == null ? [{
384
+ type: "app",
385
+ layout: "desktop",
386
+ host: null
387
+ }] : a,
388
+ hostContextIsOverridden: g !== null,
389
+ isCollapsed: u((o = e.collapsed) == null ? !0 : o),
367
390
  isPaused: !1,
368
391
  hasStarted: !1,
369
- activeTab: o(n),
392
+ activeTab: l(n),
370
393
  puzzleData: null,
371
394
  originalPuzzle: "",
372
395
  currentInputStr: "",
373
396
  completionData: null,
374
- selectedTheme: a(),
375
- selectedCategory: f && t.includes(f) ? f : (d = t[0]) == null ? null : d,
376
- selectedPuzzle: p == null ? null : p,
377
- renderHost: c(),
378
- renderContext: l(),
379
- gameSettings: i(),
397
+ selectedTheme: c(),
398
+ selectedCategory: m && t.includes(m) ? m : (p = t[0]) == null ? null : p,
399
+ selectedPuzzle: h == null ? null : h,
400
+ renderHost: d(),
401
+ renderContext: f(),
402
+ gameSettings: s(),
380
403
  settingsComponents: null
381
404
  };
382
405
  }
383
- function d(e) {
406
+ function m(e) {
384
407
  localStorage.setItem(r.gameSettings, JSON.stringify(e));
385
408
  }
386
- function f() {
409
+ function h() {
387
410
  localStorage.removeItem(r.gameSettings);
388
411
  }
389
- function p(e) {
412
+ function g(e) {
390
413
  localStorage.setItem(r.collapsed, String(e));
391
414
  }
392
- function m(e) {
415
+ function ee(e) {
393
416
  localStorage.setItem(r.tab, e);
394
417
  }
395
- function h(e) {
418
+ function te(e) {
396
419
  localStorage.setItem(r.theme, e);
397
420
  }
398
- function g(e) {
421
+ function _(e) {
399
422
  localStorage.setItem(r.fixtureCategory, e);
400
423
  }
401
- function _(e) {
424
+ function v(e) {
402
425
  localStorage.setItem(r.fixturePuzzle, e);
403
426
  }
404
- function v() {
427
+ function ne() {
405
428
  localStorage.removeItem(r.fixturePuzzle);
406
429
  }
407
430
  function y(e) {
@@ -410,7 +433,7 @@ function y(e) {
410
433
  function b(e) {
411
434
  e ? localStorage.setItem(r.renderContext, e) : localStorage.removeItem(r.renderContext);
412
435
  }
413
- function ee(e) {
436
+ function re(e) {
414
437
  let t = [];
415
438
  return {
416
439
  log(n, r, i) {
@@ -435,13 +458,13 @@ function ee(e) {
435
458
  }
436
459
  };
437
460
  }
438
- function te(e, t, n) {
461
+ function ie(e, t, n) {
439
462
  console.log("Simulator sending:", e, t), n == null || n.log(e, t, "out"), window.postMessage({
440
463
  type: e,
441
464
  data: t
442
465
  }, "*");
443
466
  }
444
- function ne(e, t) {
467
+ function ae(e, t) {
445
468
  let n = (n) => {
446
469
  var r, i, a;
447
470
  if (!(!(n == null || (r = n.data) == null) && r.type)) return;
@@ -451,7 +474,7 @@ function ne(e, t) {
451
474
  return window.addEventListener("message", n), () => window.removeEventListener("message", n);
452
475
  }
453
476
  /** Parse fixture imports into a structured format: { category: { filename: data } } */
454
- function re(e) {
477
+ function oe(e) {
455
478
  let t = /* @__PURE__ */ new Map();
456
479
  console.log("Simulator: Parsing fixtures", Object.keys(e));
457
480
  for (let [o, s] of Object.entries(e)) {
@@ -470,7 +493,7 @@ function re(e) {
470
493
  }), t;
471
494
  }
472
495
  /** Render fixture selector HTML */
473
- function ie(e, t) {
496
+ function x(e, t) {
474
497
  return e.length === 0 ? "" : `
475
498
  <div class="simulator-fixtures">
476
499
  <div class="simulator-field">
@@ -487,7 +510,7 @@ function ie(e, t) {
487
510
  `;
488
511
  }
489
512
  /** Update puzzle select options based on selected category */
490
- function x(e, t, n, r) {
513
+ function S(e, t, n, r) {
491
514
  let i = t.get(n);
492
515
  if (!i) return null;
493
516
  let a = Array.from(i.keys()), o = r;
@@ -498,11 +521,11 @@ function x(e, t, n, r) {
498
521
  return e.innerHTML = a.map((e) => `<option value="${e}" ${e === o ? "selected" : ""}>${e}</option>`).join(""), o;
499
522
  }
500
523
  /** Get puzzle data from fixtures */
501
- function S(e, t, n) {
524
+ function C(e, t, n) {
502
525
  var r, i;
503
526
  return !t || !n || (r = (i = e.get(t)) == null ? void 0 : i.get(n)) == null ? null : r;
504
527
  }
505
- function ae() {
528
+ function se() {
506
529
  return {
507
530
  id: "ctrl",
508
531
  label: "Ctrl",
@@ -517,19 +540,19 @@ function ae() {
517
540
  selectedCategory: e.state.selectedCategory,
518
541
  selectedPuzzle: e.state.selectedPuzzle
519
542
  }), e.fixtures && e.fixtureCategories.length > 0 && i) {
520
- i.innerHTML = ie(e.fixtureCategories, e.state.selectedCategory);
543
+ i.innerHTML = x(e.fixtureCategories, e.state.selectedCategory);
521
544
  let t = e.getElement("#simulator-fixture-category"), n = e.getElement("#simulator-fixture-puzzle");
522
545
  if (t && n && e.state.selectedCategory) {
523
- e.state.selectedPuzzle = x(n, e.fixtures, e.state.selectedCategory, e.state.selectedPuzzle);
524
- let r = S(e.fixtures, e.state.selectedCategory, e.state.selectedPuzzle);
546
+ e.state.selectedPuzzle = S(n, e.fixtures, e.state.selectedCategory, e.state.selectedPuzzle);
547
+ let r = C(e.fixtures, e.state.selectedCategory, e.state.selectedPuzzle);
525
548
  console.log("Simulator: Loading fixture puzzle", {
526
549
  category: e.state.selectedCategory,
527
550
  puzzle: e.state.selectedPuzzle,
528
551
  hasPuzzleData: !!r
529
- }), r && (e.state.puzzleData = r, e.state.originalPuzzle = r, e.state.selectedCategory && g(e.state.selectedCategory), e.state.selectedPuzzle && _(e.state.selectedPuzzle)), t.addEventListener("change", () => {
530
- console.log("Simulator: Category changed, reloading...", t.value), g(t.value), v(), window.location.reload();
552
+ }), r && (e.state.puzzleData = r, e.state.originalPuzzle = r, e.state.selectedCategory && _(e.state.selectedCategory), e.state.selectedPuzzle && v(e.state.selectedPuzzle)), t.addEventListener("change", () => {
553
+ console.log("Simulator: Category changed, reloading...", t.value), _(t.value), ne(), window.location.reload();
531
554
  }), n.addEventListener("change", () => {
532
- console.log("Simulator: Puzzle changed, reloading...", n.value), _(n.value), window.location.reload();
555
+ console.log("Simulator: Puzzle changed, reloading...", n.value), v(n.value), window.location.reload();
533
556
  });
534
557
  }
535
558
  }
@@ -547,9 +570,9 @@ function ae() {
547
570
  }
548
571
  };
549
572
  }
550
- var C = "simulator-saved-states";
573
+ var w = "simulator-saved-states";
551
574
  /** Find thumbnail function on globalThis (looks for functions ending in "Thumbnail") */
552
- function w() {
575
+ function T() {
553
576
  let e = globalThis;
554
577
  for (let t of Object.keys(e)) if (t.endsWith("Thumbnail") && typeof e[t] == "function") return {
555
578
  name: t,
@@ -558,8 +581,8 @@ function w() {
558
581
  return null;
559
582
  }
560
583
  /** Generate a small thumbnail SVG for a given input string */
561
- function T(e, t) {
562
- let n = w();
584
+ function E(e, t) {
585
+ let n = T();
563
586
  if (!n) return "";
564
587
  try {
565
588
  var r;
@@ -574,14 +597,14 @@ function T(e, t) {
574
597
  return "";
575
598
  }
576
599
  }
577
- var E = [];
578
- function D(e, t = 8) {
600
+ var D = [];
601
+ function O(e, t = 8) {
579
602
  let n = 14 * t + 8 + 4;
580
603
  e.style.height = "auto";
581
604
  let r = Math.min(Math.max(e.scrollHeight, 40), n);
582
605
  e.style.height = `${r}px`;
583
606
  }
584
- function oe() {
607
+ function ce() {
585
608
  let e = "", t = "";
586
609
  return {
587
610
  id: "data",
@@ -599,102 +622,102 @@ function oe() {
599
622
  let i = n.getElement(".data-view-container");
600
623
  i == null || i.querySelectorAll(".data-subtab-content").forEach((e) => {
601
624
  e.classList.toggle("active", e.id === `data-subtab-${t}`);
602
- }), t === "edit" ? M(n) : t === "history" ? k(n) : t === "saves" && A(n);
625
+ }), t === "edit" ? N(n) : t === "history" ? A(n) : t === "saves" && j(n);
603
626
  });
604
627
  });
605
628
  let i = n.getElement("#simulator-puzzle"), a = n.getElement("#simulator-input"), o = n.getElement("#simulator-puzzle-reset"), s = n.getElement("#simulator-puzzle-apply"), c = n.getElement("#simulator-input-reset"), l = n.getElement("#simulator-input-apply"), u = n.getElement("#simulator-start"), d = n.getElement("#simulator-pause");
606
629
  setTimeout(() => {
607
- i && n.state.originalPuzzle && (i.value = n.state.originalPuzzle, e = n.state.originalPuzzle, D(i)), a && n.state.currentInputStr && (a.value = n.state.currentInputStr, t = n.state.currentInputStr, D(a));
630
+ i && n.state.originalPuzzle && (i.value = n.state.originalPuzzle, e = n.state.originalPuzzle, O(i)), a && n.state.currentInputStr && (a.value = n.state.currentInputStr, t = n.state.currentInputStr, O(a));
608
631
  }, 0), i == null || i.addEventListener("input", () => {
609
- D(i);
632
+ O(i);
610
633
  let t = i.value !== e;
611
634
  s && (s.disabled = !t);
612
635
  }), a == null || a.addEventListener("input", () => {
613
- D(a);
636
+ O(a);
614
637
  let e = a.value !== t;
615
638
  l && (l.disabled = !e);
616
639
  }), o == null || o.addEventListener("click", () => {
617
- i && (i.value = n.state.originalPuzzle, e = n.state.originalPuzzle, D(i), s && (s.disabled = !0));
640
+ i && (i.value = n.state.originalPuzzle, e = n.state.originalPuzzle, O(i), s && (s.disabled = !0));
618
641
  }), s == null || s.addEventListener("click", () => {
619
642
  i && (n.state.puzzleData = i.value, n.state.originalPuzzle = i.value, e = i.value, n.sendToGame("RETRY_PUZZLE", {}), n.state.hasStarted = !1, n.state.isPaused = !1, d && (d.disabled = !0, d.textContent = "Pause"), u && (u.textContent = "Start"), n.updateStatus("Puzzle updated", "ready"), s.disabled = !0);
620
643
  }), c == null || c.addEventListener("click", () => {
621
- a && (a.value = t, D(a), l && (l.disabled = !0));
644
+ a && (a.value = t, O(a), l && (l.disabled = !0));
622
645
  }), l == null || l.addEventListener("click", () => {
623
646
  a && (n.state.currentInputStr = a.value, t = a.value, console.log("Simulator: Input string updated (game restart required to apply)"), n.updateStatus("Input stored", "ready"), l.disabled = !0);
624
647
  });
625
648
  let f = n.getElement("#simulator-history-clear");
626
649
  f == null || f.addEventListener("click", () => {
627
- E = [], k(n);
650
+ D = [], A(n);
628
651
  });
629
652
  let p = n.getElement("#simulator-save-name"), m = n.getElement("#simulator-save-btn");
630
653
  m == null || m.addEventListener("click", () => {
631
654
  if (!p || !p.value.trim()) return;
632
- let e = O(), t = {
655
+ let e = k(), t = {
633
656
  name: p.value.trim(),
634
657
  puzzleStr: n.state.originalPuzzle,
635
658
  inputStr: n.state.currentInputStr,
636
659
  timestamp: Date.now()
637
660
  };
638
- e.push(t), localStorage.setItem(C, JSON.stringify(e)), p.value = "", A(n);
639
- }), A(n);
661
+ e.push(t), localStorage.setItem(w, JSON.stringify(e)), p.value = "", j(n);
662
+ }), j(n);
640
663
  },
641
664
  onActivate(n) {
642
- e = n.state.originalPuzzle, t = n.state.currentInputStr, M(n), k(n);
665
+ e = n.state.originalPuzzle, t = n.state.currentInputStr, N(n), A(n);
643
666
  },
644
667
  onMessage(e, n, r) {
645
668
  var i, a;
646
669
  let o = r.getElement("#simulator-input"), s = r.getElement("#simulator-input-apply"), c = (i = n == null || (a = n.input) == null ? void 0 : a.boardState) == null ? n == null ? void 0 : n.boardState : i;
647
670
  if (e === "UPLOAD_NEW_GAME_STATE" && c) {
648
- if (r.state.currentInputStr = c, E.length === 0 || E[E.length - 1].value !== c) {
649
- E.push({
671
+ if (r.state.currentInputStr = c, D.length === 0 || D[D.length - 1].value !== c) {
672
+ D.push({
650
673
  value: c,
651
674
  timestamp: Date.now()
652
- }), E.length > 100 && (E = E.slice(-100));
675
+ }), D.length > 100 && (D = D.slice(-100));
653
676
  let e = r.getElement("#data-subtab-history");
654
- e != null && e.classList.contains("active") && k(r);
677
+ e != null && e.classList.contains("active") && A(r);
655
678
  }
656
- o && (o.value = r.state.currentInputStr, t = r.state.currentInputStr, D(o), s && (s.disabled = !0));
679
+ o && (o.value = r.state.currentInputStr, t = r.state.currentInputStr, O(o), s && (s.disabled = !0));
657
680
  }
658
681
  }
659
682
  };
660
683
  }
661
- function O() {
684
+ function k() {
662
685
  try {
663
- let e = localStorage.getItem(C);
686
+ let e = localStorage.getItem(w);
664
687
  return e ? JSON.parse(e) : [];
665
688
  } catch (e) {
666
689
  return [];
667
690
  }
668
691
  }
669
- function k(e) {
692
+ function A(e) {
670
693
  let t = e.getElement("#simulator-history-list");
671
694
  if (t) {
672
- if (t.style.setProperty("--history-thumb-bg", e.state.selectedTheme.a_bg), E.length === 0) {
695
+ if (t.style.setProperty("--history-thumb-bg", e.state.selectedTheme.a_bg), D.length === 0) {
673
696
  t.innerHTML = "<div class=\"simulator-empty\">No history yet</div>";
674
697
  return;
675
698
  }
676
- t.innerHTML = [...E].reverse().map((t, n) => {
677
- let r = E.length - 1 - n, i = new Date(t.timestamp).toLocaleTimeString(), a = t.value.length > 60 ? t.value.slice(0, 60) + "..." : t.value;
699
+ t.innerHTML = [...D].reverse().map((t, n) => {
700
+ let r = D.length - 1 - n, i = new Date(t.timestamp).toLocaleTimeString(), a = t.value.length > 60 ? t.value.slice(0, 60) + "..." : t.value;
678
701
  return `
679
702
  <div class="history-item" data-history-idx="${r}">
680
- <div class="history-item-thumb">${T(e, t.value)}</div>
703
+ <div class="history-item-thumb">${E(e, t.value)}</div>
681
704
  <div class="history-item-content">
682
705
  <div class="history-item-header">
683
706
  <span class="history-item-num">#${r + 1}</span>
684
707
  <span class="history-item-time">${i}</span>
685
708
  <button class="simulator-btn tiny history-restore-btn" data-history-idx="${r}">Restore</button>
686
709
  </div>
687
- <div class="history-item-preview">${j(a)}</div>
710
+ <div class="history-item-preview">${M(a)}</div>
688
711
  </div>
689
712
  </div>
690
713
  `;
691
714
  }).join(""), t.querySelectorAll(".history-restore-btn").forEach((t) => {
692
715
  t.addEventListener("click", (t) => {
693
- let n = parseInt(t.target.getAttribute("data-history-idx") || "0"), r = E[n];
716
+ let n = parseInt(t.target.getAttribute("data-history-idx") || "0"), r = D[n];
694
717
  if (r) {
695
718
  e.state.currentInputStr = r.value;
696
719
  let t = e.getElement("#simulator-input");
697
- t && (t.value = r.value, D(t)), e.updateStatus("Input restored from history", "ready");
720
+ t && (t.value = r.value, O(t)), e.updateStatus("Input restored from history", "ready");
698
721
  let n = e.getElement(".data-subtab[data-subtab=\"edit\"]");
699
722
  n == null || n.click();
700
723
  }
@@ -702,10 +725,10 @@ function k(e) {
702
725
  });
703
726
  }
704
727
  }
705
- function A(e) {
728
+ function j(e) {
706
729
  let t = e.getElement("#simulator-saves-list");
707
730
  if (!t) return;
708
- let n = O();
731
+ let n = k();
709
732
  if (n.length === 0) {
710
733
  t.innerHTML = "<div class=\"simulator-empty\">No saved states</div>";
711
734
  return;
@@ -715,7 +738,7 @@ function A(e) {
715
738
  return `
716
739
  <div class="save-item">
717
740
  <div class="save-item-header">
718
- <span class="save-item-name">${j(e.name)}</span>
741
+ <span class="save-item-name">${M(e.name)}</span>
719
742
  <span class="save-item-time">${i} ${a}</span>
720
743
  </div>
721
744
  <div class="save-item-actions">
@@ -730,7 +753,7 @@ function A(e) {
730
753
  if (r) {
731
754
  e.state.puzzleData = r.puzzleStr, e.state.originalPuzzle = r.puzzleStr, e.state.currentInputStr = r.inputStr;
732
755
  let t = e.getElement("#simulator-puzzle"), n = e.getElement("#simulator-input");
733
- t && (t.value = r.puzzleStr, D(t)), n && (n.value = r.inputStr, D(n)), e.updateStatus(`Loaded: ${r.name}`, "ready");
756
+ t && (t.value = r.puzzleStr, O(t)), n && (n.value = r.inputStr, O(n)), e.updateStatus(`Loaded: ${r.name}`, "ready");
734
757
  let i = e.getElement(".data-subtab[data-subtab=\"edit\"]");
735
758
  i == null || i.click();
736
759
  }
@@ -738,21 +761,21 @@ function A(e) {
738
761
  }), t.querySelectorAll(".save-delete-btn").forEach((t) => {
739
762
  t.addEventListener("click", (t) => {
740
763
  let r = parseInt(t.target.getAttribute("data-save-idx") || "0"), i = n.filter((e, t) => t !== r);
741
- localStorage.setItem(C, JSON.stringify(i)), A(e);
764
+ localStorage.setItem(w, JSON.stringify(i)), j(e);
742
765
  });
743
766
  });
744
767
  }
745
- function j(e) {
768
+ function M(e) {
746
769
  return e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
747
770
  }
748
- function M(e) {
771
+ function N(e) {
749
772
  let t = e.getElement("#simulator-puzzle"), n = e.getElement("#simulator-input"), r = e.getElement("#simulator-puzzle-apply"), i = e.getElement("#simulator-input-apply");
750
- t && e.state.originalPuzzle && (t.value = e.state.originalPuzzle, D(t), r && (r.disabled = !0)), n && (n.value = e.state.currentInputStr, D(n), i && (i.disabled = !0));
773
+ t && e.state.originalPuzzle && (t.value = e.state.originalPuzzle, O(t), r && (r.disabled = !0)), n && (n.value = e.state.currentInputStr, O(n), i && (i.disabled = !0));
751
774
  }
752
- function N(e) {
775
+ function P(e) {
753
776
  return e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
754
777
  }
755
- function se() {
778
+ function le() {
756
779
  let e = 0;
757
780
  return {
758
781
  id: "msgs",
@@ -779,7 +802,7 @@ function se() {
779
802
  <span class="simulator-msg-type">${t.direction === "out" ? "→" : "←"} ${t.type}</span>
780
803
  <span class="simulator-msg-time">${t.time}</span>
781
804
  </div>
782
- ${a ? `<div class="simulator-msg-data">${N(a)}</div>` : ""}
805
+ ${a ? `<div class="simulator-msg-data">${P(a)}</div>` : ""}
783
806
  `;
784
807
  let o = i.querySelector(".simulator-msg-data");
785
808
  for (o && o.addEventListener("click", () => {
@@ -790,7 +813,7 @@ function se() {
790
813
  }
791
814
  };
792
815
  }
793
- function ce() {
816
+ function ue() {
794
817
  return {
795
818
  id: "done",
796
819
  label: "Done",
@@ -827,7 +850,7 @@ function ce() {
827
850
  }
828
851
  };
829
852
  }
830
- function le() {
853
+ function de() {
831
854
  let e = [], t = () => (/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", { hour12: !1 }), n = (e) => {
832
855
  let { checkpointName: t, augConfig: n, time: r } = e, i = n == null ? void 0 : n.deeds;
833
856
  return `
@@ -878,7 +901,7 @@ function le() {
878
901
  };
879
902
  }
880
903
  /** Find thumbnail function on globalThis (looks for functions ending in "Thumbnail") */
881
- function P() {
904
+ function F() {
882
905
  let e = globalThis;
883
906
  for (let t of Object.keys(e)) if (t.endsWith("Thumbnail") && typeof e[t] == "function") return {
884
907
  name: t,
@@ -886,7 +909,7 @@ function P() {
886
909
  };
887
910
  return null;
888
911
  }
889
- function ue() {
912
+ function fe() {
890
913
  return {
891
914
  id: "thumb",
892
915
  label: "Thumb",
@@ -911,7 +934,7 @@ function ue() {
911
934
  updatePreview: (e) => {
912
935
  let t = e.getElement("#simulator-thumb-preview"), n = e.getElement("#simulator-thumb-fn");
913
936
  t == null || t.style.setProperty("--sim-thumb-bg", e.state.selectedTheme.g_bg);
914
- let r = P();
937
+ let r = F();
915
938
  if (!r) {
916
939
  t && (t.innerHTML = "<span class=\"simulator-empty\">No thumbnail function found</span>"), n && (n.textContent = "");
917
940
  return;
@@ -934,7 +957,7 @@ function ue() {
934
957
  };
935
958
  }
936
959
  /** Generate theme preview HTML showing key colors */
937
- function F(e) {
960
+ function I(e) {
938
961
  let t = [
939
962
  e.key,
940
963
  e.subBrand,
@@ -945,7 +968,7 @@ function F(e) {
945
968
  ].map((e) => `<div class="simulator-theme-preview-cell" style="background: ${e}"></div>`).join("");
946
969
  return `<div class="simulator-theme-preview" style="background: ${e.g_bg}">${t}</div>`;
947
970
  }
948
- function de() {
971
+ function pe() {
949
972
  return {
950
973
  id: "theme",
951
974
  label: "Theme",
@@ -957,49 +980,154 @@ function de() {
957
980
  t && n.forEach((n) => {
958
981
  let r = document.createElement("div");
959
982
  r.className = `simulator-theme-item${n.name === e.state.selectedTheme.name ? " selected" : ""}`, r.innerHTML = `
960
- ${F(n)}
983
+ ${I(n)}
961
984
  <div class="simulator-theme-name">${n.name}</div>
962
985
  <div class="simulator-theme-type">${n.type}</div>
963
986
  `, r.addEventListener("click", () => {
964
- console.log("Simulator: Theme changed, reloading...", n.name), h(n.name), window.location.reload();
987
+ console.log("Simulator: Theme changed, reloading...", n.name), te(n.name), window.location.reload();
965
988
  }), t.appendChild(r);
966
989
  });
967
990
  }
968
991
  };
969
992
  }
970
- var I = "puzzmo_sim_api_mode", L = "http://localhost:8911", R = "https://api.puzzmo.com", z = () => localStorage.getItem(I) === "dev" ? "dev" : "prod", B = (e) => {
971
- localStorage.setItem(I, e);
972
- }, V = null, fe = function() {
993
+ var L = [
994
+ {
995
+ name: "app (desktop)",
996
+ context: [{
997
+ type: "app",
998
+ layout: "desktop",
999
+ host: null
1000
+ }]
1001
+ },
1002
+ {
1003
+ name: "app (mobile)",
1004
+ context: [{
1005
+ type: "app",
1006
+ layout: "mobile",
1007
+ host: null
1008
+ }]
1009
+ },
1010
+ {
1011
+ name: "app (ios)",
1012
+ context: [{
1013
+ type: "app",
1014
+ layout: "mobile",
1015
+ host: "ios-app"
1016
+ }]
1017
+ },
1018
+ {
1019
+ name: "embed",
1020
+ context: [{ type: "embed" }]
1021
+ },
1022
+ {
1023
+ name: "embed (no UI)",
1024
+ context: [{
1025
+ type: "embed",
1026
+ noUI: !0
1027
+ }]
1028
+ },
1029
+ {
1030
+ name: "sandbox",
1031
+ context: [{ type: "sandbox" }]
1032
+ }
1033
+ ];
1034
+ /**
1035
+ * Host tab — edit the `hostContext` array the simulator sends in READY_DATA, so host-context
1036
+ * dependent features (embed settings, sandbox mode, mobile layout, …) can be exercised locally.
1037
+ * The bootstrap is only read at game boot, so applying a change persists it to localStorage and
1038
+ * restarts (reloads) the page — the same flow as the Theme tab.
1039
+ */
1040
+ function me(e = []) {
1041
+ let t = [...L, ...e];
1042
+ return {
1043
+ id: "host",
1044
+ label: "Host",
1045
+ render() {
1046
+ return `
1047
+ <style>
1048
+ #simulator-tab-host .host-note { opacity: 0.5; font-size: 10px; margin: 4px 0 8px; }
1049
+ #simulator-tab-host .host-error { color: #f66; font-size: 11px; margin-top: 6px; white-space: pre-wrap; }
1050
+ #simulator-tab-host .host-actions { display: flex; gap: 6px; margin-top: 8px; }
1051
+ #simulator-tab-host .simulator-textarea { min-height: 140px; font-family: monospace; }
1052
+ </style>
1053
+ <div class="simulator-section">
1054
+ <div class="simulator-section-title">Host Context</div>
1055
+ <div class="host-note" id="host-source"></div>
1056
+ <select class="simulator-select" id="host-presets">
1057
+ <option value="">Preset…</option>
1058
+ ${t.map((e, t) => `<option value="${t}">${R(e.name)}</option>`).join("")}
1059
+ </select>
1060
+ <textarea class="simulator-textarea" id="host-json" spellcheck="false"></textarea>
1061
+ <div class="host-actions">
1062
+ <button class="simulator-btn primary" id="host-apply">Apply &amp; Restart</button>
1063
+ <button class="simulator-btn subtle" id="host-reset">Reset</button>
1064
+ </div>
1065
+ <div class="host-error" id="host-error"></div>
1066
+ </div>
1067
+ `;
1068
+ },
1069
+ bind(e) {
1070
+ var n, r;
1071
+ let i = e.getElement("#host-json"), s = e.getElement("#host-presets"), c = e.getElement("#host-error"), l = e.getElement("#host-source");
1072
+ !i || !s || !c || !l || (i.value = JSON.stringify(e.state.hostContext, null, 2), l.textContent = e.state.hostContextIsOverridden ? "Using this tab's override. Changes apply on restart." : "Using the vite config / default context. Changes apply on restart.", s.addEventListener("change", () => {
1073
+ let e = t[Number(s.value)];
1074
+ e && (i.value = JSON.stringify(e.context, null, 2));
1075
+ }), (n = e.getElement("#host-apply")) == null || n.addEventListener("click", () => {
1076
+ let e;
1077
+ try {
1078
+ e = JSON.parse(i.value);
1079
+ } catch (e) {
1080
+ c.textContent = `Invalid JSON: ${e.message}`;
1081
+ return;
1082
+ }
1083
+ if (!Array.isArray(e) || !e.every((e) => e && typeof e == "object" && typeof e.type == "string")) {
1084
+ c.textContent = "hostContext must be an array of { type: string, ... } objects";
1085
+ return;
1086
+ }
1087
+ console.log("Simulator: hostContext changed, reloading...", e), a(e), window.location.reload();
1088
+ }), (r = e.getElement("#host-reset")) == null || r.addEventListener("click", () => {
1089
+ o(), window.location.reload();
1090
+ }));
1091
+ }
1092
+ };
1093
+ }
1094
+ /** Minimal HTML-escape so preset names can't break the simulator markup. */
1095
+ function R(e) {
1096
+ return e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
1097
+ }
1098
+ var z = "puzzmo_sim_api_mode", B = "http://localhost:8911", V = "https://api.puzzmo.com", H = () => localStorage.getItem(z) === "dev" ? "dev" : "prod", he = (e) => {
1099
+ localStorage.setItem(z, e);
1100
+ }, U = null, ge = function() {
973
1101
  var e = t(function* () {
974
- if (V !== null) return V;
1102
+ if (U !== null) return U;
975
1103
  try {
976
- let e = new AbortController(), t = setTimeout(() => e.abort(), 1e3), n = yield fetch(`${L}/healthz`, { signal: e.signal });
977
- return clearTimeout(t), V = n.ok, V;
1104
+ let e = new AbortController(), t = setTimeout(() => e.abort(), 1e3), n = yield fetch(`${B}/healthz`, { signal: e.signal });
1105
+ return clearTimeout(t), U = n.ok, U;
978
1106
  } catch (e) {
979
- return V = !1, !1;
1107
+ return U = !1, !1;
980
1108
  }
981
1109
  });
982
1110
  return function() {
983
1111
  return e.apply(this, arguments);
984
1112
  };
985
- }(), H = () => ({
986
- apiURL: z() === "dev" ? L : R,
1113
+ }(), W = () => ({
1114
+ apiURL: H() === "dev" ? B : V,
987
1115
  clientID: "protosdk:oauthclient",
988
1116
  redirectUri: `${window.location.origin}/oauth/callback`
989
- }), pe = () => {
1117
+ }), _e = () => {
990
1118
  let e = new Uint8Array(32);
991
1119
  return crypto.getRandomValues(e), Array.from(e, (e) => e.toString(16).padStart(2, "0")).join("");
992
- }, U = "puzzmo_sim_oauth_token", W = "puzzmo_sim_oauth_refresh_token", me = (e) => localStorage.setItem(U, e), he = (e) => localStorage.setItem(W, e), G = () => {
993
- let e = localStorage.getItem(U);
1120
+ }, G = "puzzmo_sim_oauth_token", K = "puzzmo_sim_oauth_refresh_token", ve = (e) => localStorage.setItem(G, e), ye = (e) => localStorage.setItem(K, e), q = () => {
1121
+ let e = localStorage.getItem(G);
994
1122
  return e && `${e.substring(0, 20)}`, e;
995
- }, K = () => localStorage.getItem(W), q = () => {
996
- localStorage.removeItem(U), localStorage.removeItem(W);
997
- }, ge = () => {
998
- let e = H(), t = pe();
1123
+ }, J = () => localStorage.getItem(K), Y = () => {
1124
+ localStorage.removeItem(G), localStorage.removeItem(K);
1125
+ }, be = () => {
1126
+ let e = W(), t = _e();
999
1127
  sessionStorage.setItem("oauth_state", t), sessionStorage.setItem("oauth_return_url", window.location.href);
1000
1128
  let n = new URL(`${e.apiURL}/oauth/auth`);
1001
1129
  n.searchParams.set("client_id", e.clientID), n.searchParams.set("response_type", "code"), n.searchParams.set("redirect_uri", e.redirectUri), n.searchParams.set("state", t), window.location.href = n.toString();
1002
- }, _e = (e) => {
1130
+ }, xe = (e) => {
1003
1131
  try {
1004
1132
  let t = e.split(".");
1005
1133
  if (t.length !== 3) return !0;
@@ -1008,11 +1136,11 @@ var I = "puzzmo_sim_api_mode", L = "http://localhost:8911", R = "https://api.puz
1008
1136
  } catch (e) {
1009
1137
  return !0;
1010
1138
  }
1011
- }, ve = function() {
1139
+ }, Se = function() {
1012
1140
  var e = t(function* () {
1013
- let e = K();
1141
+ let e = J();
1014
1142
  if (!e) return !1;
1015
- let t = H();
1143
+ let t = W();
1016
1144
  try {
1017
1145
  let n = new URLSearchParams({
1018
1146
  grant_type: "refresh_token",
@@ -1026,9 +1154,9 @@ var I = "puzzmo_sim_api_mode", L = "http://localhost:8911", R = "https://api.puz
1026
1154
  if (!r.ok) return r.statusText, !1;
1027
1155
  let i = yield r.json(), a = i.access_token || i.accessToken;
1028
1156
  if (!a) return !1;
1029
- me(a);
1157
+ ve(a);
1030
1158
  let o = i.refresh_token || i.refreshToken;
1031
- return o && he(o), !0;
1159
+ return o && ye(o), !0;
1032
1160
  } catch (e) {
1033
1161
  return !1;
1034
1162
  }
@@ -1036,9 +1164,9 @@ var I = "puzzmo_sim_api_mode", L = "http://localhost:8911", R = "https://api.puz
1036
1164
  return function() {
1037
1165
  return e.apply(this, arguments);
1038
1166
  };
1039
- }(), ye = function() {
1167
+ }(), Ce = function() {
1040
1168
  var e = t(function* (e, t) {
1041
- let n = H(), r = sessionStorage.getItem("oauth_state");
1169
+ let n = W(), r = sessionStorage.getItem("oauth_state");
1042
1170
  if (!r || r !== t) return null;
1043
1171
  sessionStorage.removeItem("oauth_state");
1044
1172
  try {
@@ -1060,13 +1188,13 @@ var I = "puzzmo_sim_api_mode", L = "http://localhost:8911", R = "https://api.puz
1060
1188
  return function(t, n) {
1061
1189
  return e.apply(this, arguments);
1062
1190
  };
1063
- }(), be = function() {
1191
+ }(), we = function() {
1064
1192
  var e = t(function* (e, t = {}) {
1065
- let n = H(), r = G();
1193
+ let n = W(), r = q();
1066
1194
  if (!r) throw Error("Not authenticated");
1067
- if (_e(r)) if (yield ve()) {
1068
- if (r = G(), !r) throw Error("Token refresh succeeded but no token available");
1069
- } else throw q(), Error("Session expired. Please log in again.");
1195
+ if (xe(r)) if (yield Se()) {
1196
+ if (r = q(), !r) throw Error("Token refresh succeeded but no token available");
1197
+ } else throw Y(), Error("Session expired. Please log in again.");
1070
1198
  let i = yield fetch(`${n.apiURL}/graphql`, {
1071
1199
  method: "POST",
1072
1200
  headers: {
@@ -1085,7 +1213,7 @@ var I = "puzzmo_sim_api_mode", L = "http://localhost:8911", R = "https://api.puz
1085
1213
  return function(t) {
1086
1214
  return e.apply(this, arguments);
1087
1215
  };
1088
- }(), xe = (e) => {
1216
+ }(), Te = (e) => {
1089
1217
  try {
1090
1218
  let t = e.split(".");
1091
1219
  return t.length, t.length === 3 ? JSON.parse(atob(t[1])) : null;
@@ -1093,15 +1221,15 @@ var I = "puzzmo_sim_api_mode", L = "http://localhost:8911", R = "https://api.puz
1093
1221
  return null;
1094
1222
  }
1095
1223
  };
1096
- function Se() {
1224
+ function Ee() {
1097
1225
  let e = !1;
1098
1226
  return {
1099
1227
  id: "auth",
1100
1228
  label: "Auth",
1101
1229
  render() {
1102
- let e = G(), t = !!e, n = z(), r = n === "dev" ? L : R, i = `<button class="simulator-btn tiny" id="auth-dev-toggle" style="display: none;">${n === "dev" ? "Using Dev" : "Dev"}</button>`;
1230
+ let e = q(), t = !!e, n = H(), r = n === "dev" ? B : V, i = `<button class="simulator-btn tiny" id="auth-dev-toggle" style="display: none;">${n === "dev" ? "Using Dev" : "Dev"}</button>`;
1103
1231
  if (t) {
1104
- let t = xe(e), n = t != null && t.exp ? (/* @__PURE__ */ new Date(t.exp * 1e3)).toLocaleString() : "Unknown", a = !!K(), o = a ? xe(K()) : null, s = o != null && o.exp ? (/* @__PURE__ */ new Date(o.exp * 1e3)).toLocaleString() : null;
1232
+ let t = Te(e), n = t != null && t.exp ? (/* @__PURE__ */ new Date(t.exp * 1e3)).toLocaleString() : "Unknown", a = !!J(), o = a ? Te(J()) : null, s = o != null && o.exp ? (/* @__PURE__ */ new Date(o.exp * 1e3)).toLocaleString() : null;
1105
1233
  return `
1106
1234
  <div class="simulator-section">
1107
1235
  <div class="simulator-section-title auth-title-row">
@@ -1142,7 +1270,7 @@ function Se() {
1142
1270
  </div>
1143
1271
  <p class="auth-description">
1144
1272
  Login with your Puzzmo account to make authenticated API requests.
1145
- ${n === "dev" ? `<br><strong>Using local dev server:</strong> ${L}` : ""}
1273
+ ${n === "dev" ? `<br><strong>Using local dev server:</strong> ${B}` : ""}
1146
1274
  </p>
1147
1275
  <div class="simulator-row">
1148
1276
  <button class="simulator-btn primary" id="auth-login">Login with Puzzmo</button>
@@ -1153,21 +1281,21 @@ function Se() {
1153
1281
  },
1154
1282
  bind(n) {
1155
1283
  let r = n.getElement("#auth-login"), i = n.getElement("#auth-logout"), a = n.getElement("#auth-refresh"), o = n.getElement("#auth-test-api"), s = n.getElement("#auth-api-result"), c = n.getElement("#auth-dev-toggle");
1156
- e ? V && c && (c.style.display = "", z() === "dev" && c.classList.add("active")) : (e = !0, fe().then((e) => {
1157
- e && c && (c.style.display = "", z() === "dev" && c.classList.add("active"));
1284
+ e ? U && c && (c.style.display = "", H() === "dev" && c.classList.add("active")) : (e = !0, ge().then((e) => {
1285
+ e && c && (c.style.display = "", H() === "dev" && c.classList.add("active"));
1158
1286
  })), c == null || c.addEventListener("click", () => {
1159
- B(z() === "dev" ? "prod" : "dev"), q(), window.location.reload();
1287
+ he(H() === "dev" ? "prod" : "dev"), Y(), window.location.reload();
1160
1288
  }), r == null || r.addEventListener("click", () => {
1161
- ge();
1289
+ be();
1162
1290
  }), i == null || i.addEventListener("click", () => {
1163
- q(), window.location.reload();
1291
+ Y(), window.location.reload();
1164
1292
  }), a == null || a.addEventListener("click", t(function* () {
1165
- a.disabled = !0, a.textContent = "Refreshing...", (yield ve()) ? window.location.reload() : (a.textContent = "Refresh Failed", a.disabled = !1);
1293
+ a.disabled = !0, a.textContent = "Refreshing...", (yield Se()) ? window.location.reload() : (a.textContent = "Refresh Failed", a.disabled = !1);
1166
1294
  })), o == null || o.addEventListener("click", t(function* () {
1167
1295
  if (s) {
1168
1296
  s.innerHTML = "<div class=\"loading\">Loading...</div>";
1169
1297
  try {
1170
- let t = yield be("\n query {\n currentUser {\n id\n username\n usernameID\n name\n }\n }\n ");
1298
+ let t = yield we("\n query {\n currentUser {\n id\n username\n usernameID\n name\n }\n }\n ");
1171
1299
  if (t.errors) {
1172
1300
  var e;
1173
1301
  s.innerHTML = `<div class="error">Error: ${((e = t.errors[0]) == null ? void 0 : e.message) || "Unknown error"}</div>`;
@@ -1189,13 +1317,13 @@ function Se() {
1189
1317
  if (n && r) {
1190
1318
  let t = e.getElement("#auth-status");
1191
1319
  t && (t.innerHTML = "<span class=\"indicator waiting\"></span><span>Exchanging code...</span>");
1192
- let i = yield ye(n, r);
1320
+ let i = yield Ce(n, r);
1193
1321
  if (window.history.replaceState({}, "", window.location.pathname), i) {
1194
1322
  let e = i.access_token || i.accessToken;
1195
1323
  if (e) {
1196
- me(e);
1324
+ ve(e);
1197
1325
  let t = i.refresh_token || i.refreshToken;
1198
- t && he(t);
1326
+ t && ye(t);
1199
1327
  }
1200
1328
  window.location.reload();
1201
1329
  } else {
@@ -1207,9 +1335,9 @@ function Se() {
1207
1335
  }
1208
1336
  };
1209
1337
  }
1210
- var Ce = "puzzmo_sim_api_mode", we = "http://localhost:8911", Te = "https://api.puzzmo.com", J = "puzzmo_sim_oauth_token", Y = "puzzmo_sim_oauth_refresh_token", Ee = () => localStorage.getItem(Ce) === "dev" ? "dev" : "prod", X = () => localStorage.getItem(J), De = () => localStorage.getItem(Y), Oe = (e) => localStorage.setItem(J, e), ke = (e) => localStorage.setItem(Y, e), Ae = () => {
1211
- localStorage.removeItem(J), localStorage.removeItem(Y);
1212
- }, je = (e) => {
1338
+ var De = "puzzmo_sim_api_mode", Oe = "http://localhost:8911", ke = "https://api.puzzmo.com", X = "puzzmo_sim_oauth_token", Ae = "puzzmo_sim_oauth_refresh_token", je = () => localStorage.getItem(De) === "dev" ? "dev" : "prod", Me = () => localStorage.getItem(X), Ne = () => localStorage.getItem(Ae), Pe = (e) => localStorage.setItem(X, e), Fe = (e) => localStorage.setItem(Ae, e), Ie = () => {
1339
+ localStorage.removeItem(X), localStorage.removeItem(Ae);
1340
+ }, Le = (e) => {
1213
1341
  try {
1214
1342
  let t = e.split(".");
1215
1343
  if (t.length !== 3) return !0;
@@ -1218,11 +1346,11 @@ var Ce = "puzzmo_sim_api_mode", we = "http://localhost:8911", Te = "https://api.
1218
1346
  } catch (e) {
1219
1347
  return !0;
1220
1348
  }
1221
- }, Me = function() {
1349
+ }, Re = function() {
1222
1350
  var e = t(function* () {
1223
- let e = De();
1351
+ let e = Ne();
1224
1352
  if (!e) return !1;
1225
- let t = Ee() === "dev" ? we : Te;
1353
+ let t = je() === "dev" ? Oe : ke;
1226
1354
  try {
1227
1355
  let n = new URLSearchParams({
1228
1356
  grant_type: "refresh_token",
@@ -1236,9 +1364,9 @@ var Ce = "puzzmo_sim_api_mode", we = "http://localhost:8911", Te = "https://api.
1236
1364
  if (!r.ok) return !1;
1237
1365
  let i = yield r.json(), a = i.access_token || i.accessToken;
1238
1366
  if (!a) return !1;
1239
- Oe(a);
1367
+ Pe(a);
1240
1368
  let o = i.refresh_token || i.refreshToken;
1241
- return o && ke(o), !0;
1369
+ return o && Fe(o), !0;
1242
1370
  } catch (e) {
1243
1371
  return !1;
1244
1372
  }
@@ -1246,13 +1374,13 @@ var Ce = "puzzmo_sim_api_mode", we = "http://localhost:8911", Te = "https://api.
1246
1374
  return function() {
1247
1375
  return e.apply(this, arguments);
1248
1376
  };
1249
- }(), Ne = function() {
1377
+ }(), ze = function() {
1250
1378
  var e = t(function* (e, t = {}) {
1251
- let n = Ee() === "dev" ? we : Te, r = X();
1379
+ let n = je() === "dev" ? Oe : ke, r = Me();
1252
1380
  if (!r) throw Error("Not authenticated");
1253
- if (je(r)) if (yield Me()) {
1254
- if (r = X(), !r) throw Error("Token refresh succeeded but no token available");
1255
- } else throw Ae(), Error("Session expired. Please log in again.");
1381
+ if (Le(r)) if (yield Re()) {
1382
+ if (r = Me(), !r) throw Error("Token refresh succeeded but no token available");
1383
+ } else throw Ie(), Error("Session expired. Please log in again.");
1256
1384
  let i = yield fetch(`${n}/graphql`, {
1257
1385
  method: "POST",
1258
1386
  headers: {
@@ -1271,19 +1399,19 @@ var Ce = "puzzmo_sim_api_mode", we = "http://localhost:8911", Te = "https://api.
1271
1399
  return function(t) {
1272
1400
  return e.apply(this, arguments);
1273
1401
  };
1274
- }(), Pe = "\n query GameFeaturesQuery($slug: ID!) {\n game(id: $slug) {\n id\n slug\n displayName\n featuresArr\n gameFeatures {\n slug\n title\n features {\n featureID\n title\n isEnabled\n }\n }\n }\n }\n", Fe = "\n mutation ToggleFeatureMutation($gameSlug: ID!, $input: UpdateGameInput!) {\n updateGame(id: $gameSlug, input: $input) {\n id\n featuresArr\n gameFeatures {\n slug\n title\n features {\n featureID\n title\n isEnabled\n }\n }\n }\n }\n", Ie = (e, t) => {
1402
+ }(), Be = "\n query GameFeaturesQuery($slug: ID!) {\n game(id: $slug) {\n id\n slug\n displayName\n featuresArr\n gameFeatures {\n slug\n title\n features {\n featureID\n title\n isEnabled\n }\n }\n }\n }\n", Ve = "\n mutation ToggleFeatureMutation($gameSlug: ID!, $input: UpdateGameInput!) {\n updateGame(id: $gameSlug, input: $input) {\n id\n featuresArr\n gameFeatures {\n slug\n title\n features {\n featureID\n title\n isEnabled\n }\n }\n }\n }\n", He = (e, t) => {
1275
1403
  let n = t - 1, r = Math.floor(n / 31), i = n % 31, a = [...e];
1276
1404
  for (; a.length <= r;) a.push(0);
1277
1405
  return a[r] = a[r] ^ 1 << i, a;
1278
1406
  };
1279
- const Le = () => !!X();
1280
- function Re() {
1407
+ const Ue = () => !!Me();
1408
+ function We() {
1281
1409
  let n = null, r = !1, i = null, a = function() {
1282
1410
  var e = t(function* (e) {
1283
1411
  r = !0, i = null;
1284
1412
  try {
1285
1413
  var t;
1286
- let r = yield Ne(Pe, { slug: e });
1414
+ let r = yield ze(Be, { slug: e });
1287
1415
  if (r.errors) {
1288
1416
  var a;
1289
1417
  i = ((a = r.errors[0]) == null ? void 0 : a.message) || "Unknown error", n = null;
@@ -1300,10 +1428,10 @@ function Re() {
1300
1428
  }(), o = function() {
1301
1429
  var r = t(function* (t) {
1302
1430
  if (!n) return;
1303
- let r = Ie(n.featuresArr, t);
1431
+ let r = He(n.featuresArr, t);
1304
1432
  try {
1305
1433
  var i;
1306
- let t = yield Ne(Fe, {
1434
+ let t = yield ze(Ve, {
1307
1435
  gameSlug: n.slug,
1308
1436
  input: { featuresArr: r }
1309
1437
  });
@@ -1351,7 +1479,7 @@ function Re() {
1351
1479
  id: "features",
1352
1480
  label: "Features",
1353
1481
  render() {
1354
- return Le() ? `
1482
+ return Ue() ? `
1355
1483
  <div class="features-view-container">
1356
1484
  <div class="simulator-section">
1357
1485
  <div class="simulator-section-title">Game Features</div>
@@ -1392,7 +1520,7 @@ function Re() {
1392
1520
  e && (yield d(e));
1393
1521
  })), i == null || i.addEventListener("keypress", (e) => {
1394
1522
  e.key === "Enter" && (r == null || r.click());
1395
- }), console.log("[FeaturesView] bind called, ctx.gameSlug:", e.gameSlug, "slugInput:", i), e.gameSlug && i && (i.value = e.gameSlug, Le() && !n && d(e.gameSlug)), u();
1523
+ }), console.log("[FeaturesView] bind called, ctx.gameSlug:", e.gameSlug, "slugInput:", i), e.gameSlug && i && (i.value = e.gameSlug, Ue() && !n && d(e.gameSlug)), u();
1396
1524
  },
1397
1525
  onActivate(e) {
1398
1526
  let t = e.getElement("#simulator-tab-features");
@@ -1401,7 +1529,7 @@ function Re() {
1401
1529
  };
1402
1530
  }
1403
1531
  /** Renders a single keyboard key as an HTML button string */
1404
- var ze = (e, t) => {
1532
+ var Ge = (e, t) => {
1405
1533
  var n, r;
1406
1534
  let i = (n = t.symbols[e]) == null ? e : n, a = t.disabled.includes(e), o = t.highlight.includes(e), s = t.xl.includes(e), c = t.l.includes(e), l = (r = t.flexGrowSymbols) == null ? void 0 : r.includes(e);
1407
1535
  return `<button class="${[
@@ -1412,9 +1540,9 @@ var ze = (e, t) => {
1412
1540
  c ? "l" : "",
1413
1541
  l ? "grow" : ""
1414
1542
  ].filter(Boolean).join(" ")}" data-key="${e}" ${a ? "disabled" : ""}>${i}</button>`;
1415
- }, Be = (e) => `<div class="sim-kb">${e.layout.filter((e) => e != null).map((t) => `<div class="sim-kb-row">${[...t].map((t) => ze(t, e)).join("")}</div>`).join("")}</div>`;
1416
- function Ve() {
1417
- let e = null, t = () => e ? Be(e) : "<div class=\"sim-kb-empty\">No keyboard config received from game yet.<br>The game calls <code>sdk.keyboard.show(config)</code> to display a keyboard.</div>";
1543
+ }, Ke = (e) => `<div class="sim-kb">${e.layout.filter((e) => e != null).map((t) => `<div class="sim-kb-row">${[...t].map((t) => Ge(t, e)).join("")}</div>`).join("")}</div>`;
1544
+ function qe() {
1545
+ let e = null, t = () => e ? Ke(e) : "<div class=\"sim-kb-empty\">No keyboard config received from game yet.<br>The game calls <code>sdk.keyboard.show(config)</code> to display a keyboard.</div>";
1418
1546
  return {
1419
1547
  id: "kbd",
1420
1548
  label: "Kbd",
@@ -1428,19 +1556,19 @@ function Ve() {
1428
1556
  `;
1429
1557
  },
1430
1558
  bind(e) {
1431
- He(e);
1559
+ Je(e);
1432
1560
  },
1433
1561
  onMessage(n, r, i) {
1434
1562
  var a;
1435
1563
  if (n !== "KEYBOARD_UPDATE_CONFIG") return;
1436
1564
  e = !(!(r == null || (a = r.layout) == null) && a.length) || r.layout.every((e) => !e) ? null : r;
1437
1565
  let o = i.getElement("#sim-kb-content");
1438
- o && (o.innerHTML = t(), He(i)), i.updateBadge("kbd", void 0);
1566
+ o && (o.innerHTML = t(), Je(i)), i.updateBadge("kbd", void 0);
1439
1567
  }
1440
1568
  };
1441
1569
  }
1442
1570
  /** Attach click handlers to all rendered keys */
1443
- function He(e) {
1571
+ function Je(e) {
1444
1572
  var t;
1445
1573
  let n = (t = e.getElement("#sim-kb-content")) == null ? void 0 : t.querySelectorAll(".sim-kb-key");
1446
1574
  n == null || n.forEach((t) => {
@@ -1455,15 +1583,15 @@ function He(e) {
1455
1583
  * change values (persisted to localStorage and pushed to the game as SETTINGS_UPDATE, matching the
1456
1584
  * production host) and reflects UPDATE_SETTINGS_FROM_EMBED writes coming from the game.
1457
1585
  */
1458
- function Ue() {
1586
+ function Ye() {
1459
1587
  let t = (e) => {
1460
1588
  let t = e.state.settingsComponents;
1461
- return !t || t.length === 0 ? "<div class=\"sim-settings-empty\">No settings registered by the game yet.<br>The game calls <code>sdk.settings.initialize(components)</code> to describe its settings UI.</div>" : `<div class="sim-settings-form">${t.map((t) => We(t, e.state.gameSettings)).join("")}</div><div class="sim-settings-actions"><button class="simulator-btn tiny" id="sim-settings-reset">Reset to defaults</button></div>`;
1589
+ return !t || t.length === 0 ? "<div class=\"sim-settings-empty\">No settings registered by the game yet.<br>The game calls <code>sdk.settings.initialize(components)</code> to describe its settings UI.</div>" : `<div class="sim-settings-form">${t.map((t) => Xe(t, e.state.gameSettings)).join("")}</div><div class="sim-settings-actions"><button class="simulator-btn tiny" id="sim-settings-reset">Reset to defaults</button></div>`;
1462
1590
  }, n = (e) => {
1463
1591
  let n = e.getElement("#sim-settings-content");
1464
1592
  n && (n.innerHTML = t(e), i(e));
1465
1593
  }, r = (e) => {
1466
- d(e.state.gameSettings), e.sendToGame("SETTINGS_UPDATE", e.state.gameSettings);
1594
+ m(e.state.gameSettings), e.sendToGame("SETTINGS_UPDATE", e.state.gameSettings);
1467
1595
  }, i = (t) => {
1468
1596
  var i;
1469
1597
  let a = t.getElement("#sim-settings-content");
@@ -1479,7 +1607,7 @@ function Ue() {
1479
1607
  });
1480
1608
  }), (i = a.querySelector("#sim-settings-reset")) == null || i.addEventListener("click", () => {
1481
1609
  var e;
1482
- f(), t.state.gameSettings = Ge((e = t.state.settingsComponents) == null ? [] : e), r(t), n(t);
1610
+ h(), t.state.gameSettings = Ze((e = t.state.settingsComponents) == null ? [] : e), r(t), n(t);
1483
1611
  }));
1484
1612
  };
1485
1613
  return {
@@ -1494,21 +1622,21 @@ function Ue() {
1494
1622
  onMessage(t, r, i) {
1495
1623
  if (t === "INITIALIZE_SETTINGS") {
1496
1624
  var a;
1497
- i.state.settingsComponents = (a = r == null ? void 0 : r.components) == null ? [] : a, i.state.gameSettings = e(e({}, r == null ? void 0 : r.settings), i.state.gameSettings), d(i.state.gameSettings), n(i);
1625
+ i.state.settingsComponents = (a = r == null ? void 0 : r.components) == null ? [] : a, i.state.gameSettings = e(e({}, r == null ? void 0 : r.settings), i.state.gameSettings), m(i.state.gameSettings), n(i);
1498
1626
  return;
1499
1627
  }
1500
- t === "UPDATE_SETTINGS_FROM_EMBED" && (i.state.gameSettings = e(e({}, i.state.gameSettings), r == null ? void 0 : r.settings), d(i.state.gameSettings), n(i));
1628
+ t === "UPDATE_SETTINGS_FROM_EMBED" && (i.state.gameSettings = e(e({}, i.state.gameSettings), r == null ? void 0 : r.settings), m(i.state.gameSettings), n(i));
1501
1629
  }
1502
1630
  };
1503
1631
  }
1504
1632
  /** Renders a single settings UI component as HTML, reading its current value from `settings` */
1505
- function We(e, t) {
1633
+ function Xe(e, t) {
1506
1634
  switch (e.type) {
1507
1635
  case "title": return `<div class="sim-settings-heading">${Q(e.value)}</div>`;
1508
1636
  case "subtitle": return `<div class="sim-settings-subheading">${Q(e.value)}</div>`;
1509
1637
  case "paragraph": return `<p class="sim-settings-paragraph">${Q(e.value)}</p>`;
1510
1638
  case "separator": return "<div class=\"simulator-divider\"></div>";
1511
- case "split": return `<div class="sim-settings-split">${e.content.map((e) => We(e, t)).join("")}</div>`;
1639
+ case "split": return `<div class="sim-settings-split">${e.content.map((e) => Xe(e, t)).join("")}</div>`;
1512
1640
  case "boolean": {
1513
1641
  var n;
1514
1642
  let r = ((n = t[e.name]) == null ? e.defaultValue : n) ? "checked" : "", i = e.subtitle ? `<div class="sim-settings-subtitle">${Q(e.subtitle)}</div>` : "";
@@ -1576,9 +1704,9 @@ function Z(e) {
1576
1704
  return `<span class="simulator-label">${Q(e.title)}</span>${t}`;
1577
1705
  }
1578
1706
  /** Collects name → defaultValue pairs from components, recursing into split groups */
1579
- function Ge(e) {
1707
+ function Ze(e) {
1580
1708
  let t = {};
1581
- for (let n of e) n.type === "split" ? Object.assign(t, Ge(n.content)) : "name" in n && (t[n.name] = n.defaultValue);
1709
+ for (let n of e) n.type === "split" ? Object.assign(t, Ze(n.content)) : "name" in n && (t[n.name] = n.defaultValue);
1582
1710
  return t;
1583
1711
  }
1584
1712
  function Q(e) {
@@ -1622,34 +1750,35 @@ var $ = null;
1622
1750
  * Fixtures are loaded as raw strings and passed to the game verbatim (any text format works; the game parses it).
1623
1751
  * This will show dropdowns in the Ctrl tab to select category and puzzle.
1624
1752
  */
1625
- function Ke(e = {}) {
1753
+ function Qe(e = {}) {
1626
1754
  var n, r, i;
1627
1755
  if (console.log("[Simulator] createSimulator called with config:", {
1628
1756
  slug: e.slug,
1629
1757
  hasFixtures: !!e.fixtures
1630
1758
  }), $) return e.fixtures && (console.log("[Simulator] Instance already exists, updating fixtures"), $.updateFixtures(e.fixtures)), $;
1631
- let a = (n = e.autoStart) == null ? !0 : n, o = e.fixtures ? re(e.fixtures) : null, s = o ? Array.from(o.keys()).sort() : [], c = se(), l = ue(), d = [
1632
- ae(),
1633
- oe(),
1634
- c,
1759
+ let a = (n = e.autoStart) == null ? !0 : n, o = e.fixtures ? oe(e.fixtures) : null, s = o ? Array.from(o.keys()).sort() : [], c = le(), l = fe(), u = [
1760
+ se(),
1635
1761
  ce(),
1636
- le(),
1637
- l,
1762
+ c,
1763
+ ue(),
1638
1764
  de(),
1639
- Se(),
1640
- Re(),
1641
- Ve(),
1642
- Ue(),
1765
+ l,
1766
+ pe(),
1767
+ me(e.hostContextPresets),
1768
+ Ee(),
1769
+ We(),
1770
+ qe(),
1771
+ Ye(),
1643
1772
  ...(r = e.views) == null ? [] : r
1644
- ], f = d.map((e) => e.id), h = u(e, s, f), g = {
1773
+ ], d = u.map((e) => e.id), f = p(e, s, d), m = {
1645
1774
  pause: "<svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"currentColor\"><rect x=\"1\" y=\"1\" width=\"3\" height=\"8\"/><rect x=\"6\" y=\"1\" width=\"3\" height=\"8\"/></svg>",
1646
1775
  play: "<svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"currentColor\"><polygon points=\"2,1 9,5 2,9\"/></svg>",
1647
1776
  retry: "<svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"currentColor\"><path d=\"M5 1C2.8 1 1 2.8 1 5s1.8 4 4 4c1.8 0 3.3-1.2 3.8-2.8H7.5c-.4.9-1.3 1.5-2.5 1.5-1.5 0-2.7-1.2-2.7-2.7S3.5 2.3 5 2.3c.7 0 1.4.3 1.9.8L5.5 4.5H9V1L7.6 2.4C6.9 1.5 5.9 1 5 1z\"/></svg>",
1648
1777
  cog: "<svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"currentColor\"><path d=\"M9.5 5.8l-.8-.5c0-.2.1-.5.1-.8s0-.5-.1-.8l.8-.5c.1-.1.2-.2.1-.4l-.8-1.4c-.1-.1-.2-.2-.4-.1l-1 .3c-.3-.3-.7-.5-1.1-.6L6.1.2C6.1.1 6 0 5.8 0H4.2c-.2 0-.3.1-.3.2l-.2 1c-.4.1-.7.3-1.1.6l-1-.3c-.2 0-.3 0-.4.1l-.8 1.4c-.1.2 0 .3.1.4l.8.5c0 .2-.1.5-.1.8s0 .5.1.8l-.8.5c-.1.1-.2.2-.1.4l.8 1.4c.1.1.2.2.4.1l1-.3c.3.3.7.5 1.1.6l.2 1c0 .1.1.2.3.2h1.6c.2 0 .3-.1.3-.2l.2-1c.4-.1.7-.3 1.1-.6l1 .3c.2 0 .3 0 .4-.1l.8-1.4c.1-.2 0-.3-.1-.4zM5 6.5c-.8 0-1.5-.7-1.5-1.5S4.2 3.5 5 3.5 6.5 4.2 6.5 5 5.8 6.5 5 6.5z\"/></svg>",
1649
1778
  minimize: "<svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"currentColor\"><rect x=\"1\" y=\"4\" width=\"8\" height=\"2\"/></svg>",
1650
1779
  expand: "<svg width=\"8\" height=\"8\" viewBox=\"0 0 8 8\" fill=\"currentColor\"><polygon points=\"1,1 7,4 1,7\"/></svg>"
1651
- }, _ = document.createElement("div");
1652
- _.id = "simulator", _.innerHTML = `
1780
+ }, h = document.createElement("div");
1781
+ h.id = "simulator", h.innerHTML = `
1653
1782
  <style>
1654
1783
  :root {
1655
1784
  --sim-bg: #1a1a2e;
@@ -2886,15 +3015,15 @@ function Ke(e = {}) {
2886
3015
  border-top: 2px solid var(--sim-border);
2887
3016
  }
2888
3017
  </style>
2889
- <div id="simulator-panel" class="${h.isCollapsed ? "collapsed" : ""}">
3018
+ <div id="simulator-panel" class="${f.isCollapsed ? "collapsed" : ""}">
2890
3019
  <div id="simulator-header">
2891
3020
  <span id="simulator-title">PUZZMO SIMULATOR</span>
2892
3021
  <span class="header-sep">|</span>
2893
3022
  <div id="simulator-timer">--:--</div>
2894
3023
  <span class="header-sep">|</span>
2895
3024
  <div id="simulator-header-controls">
2896
- <button id="simulator-header-pause" class="header-icon-btn" title="Pause" disabled>${g.pause}</button>
2897
- <button id="simulator-header-retry" class="header-icon-btn" title="Retry" disabled>${g.retry}</button>
3025
+ <button id="simulator-header-pause" class="header-icon-btn" title="Pause" disabled>${m.pause}</button>
3026
+ <button id="simulator-header-retry" class="header-icon-btn" title="Retry" disabled>${m.retry}</button>
2898
3027
  </div>
2899
3028
  <span class="header-sep">|</span>
2900
3029
  <div id="simulator-header-status">
@@ -2902,106 +3031,106 @@ function Ke(e = {}) {
2902
3031
  <span id="simulator-header-status-text">Waiting...</span>
2903
3032
  </div>
2904
3033
  <span class="header-spacer"></span>
2905
- <button id="simulator-header-settings" class="header-icon-btn" title="Settings">${g.cog}</button>
2906
- <button id="simulator-toggle" class="header-icon-btn" title="Minimize">${g.minimize}</button>
3034
+ <button id="simulator-header-settings" class="header-icon-btn" title="Settings">${m.cog}</button>
3035
+ <button id="simulator-toggle" class="header-icon-btn" title="Minimize">${m.minimize}</button>
2907
3036
  </div>
2908
3037
  <div id="simulator-body">
2909
3038
  <div id="simulator-tabs">
2910
- ${d.filter((e) => e.id !== "auth").map((e) => `<button class="simulator-tab" data-tab="${e.id}">${e.label}<span class="simulator-tab-badge" data-badge="${e.id}"></span></button>`).join("")}
3039
+ ${u.filter((e) => e.id !== "auth").map((e) => `<button class="simulator-tab" data-tab="${e.id}">${e.label}<span class="simulator-tab-badge" data-badge="${e.id}"></span></button>`).join("")}
2911
3040
  </div>
2912
3041
  <div id="simulator-content" class="hidden">
2913
- ${d.map((e) => `<div id="simulator-tab-${e.id}" class="simulator-tab-content">${e.render()}</div>`).join("")}
3042
+ ${u.map((e) => `<div id="simulator-tab-${e.id}" class="simulator-tab-content">${e.render()}</div>`).join("")}
2914
3043
  </div>
2915
3044
  </div>
2916
3045
  </div>
2917
- `, document.body.appendChild(_);
2918
- let v = _.querySelector("#simulator-panel"), y = _.querySelector("#simulator-header"), b = _.querySelector("#simulator-header-indicator"), ie = _.querySelector("#simulator-header-status-text"), x = _.querySelector("#simulator-header-pause"), S = _.querySelector("#simulator-header-retry"), C = _.querySelector("#simulator-header-settings"), w = _.querySelector("#simulator-toggle"), T = _.querySelector("#simulator-timer"), E = _.querySelector("#simulator-tabs"), D = _.querySelector("#simulator-content"), O = (e) => _.querySelector(e), k = (e) => {
2919
- x.innerHTML = e ? g.play : g.pause, x.title = e ? "Resume" : "Pause";
2920
- }, A = (e, t) => {
2921
- let n = O("#simulator-status .text"), r = O("#simulator-status .indicator"), i = t === "complete" ? "✓" : "";
2922
- n && (n.textContent = e), r && (r.className = `indicator ${t}`, r.textContent = i), b.className = t, b.textContent = i, ie.textContent = e;
2923
- }, j = (e, t) => {
2924
- t && t !== "0" ? T.innerHTML = `${e}<span class="penalty">+${t}</span>` : T.textContent = e;
2925
- }, M = (e) => {
3046
+ `, document.body.appendChild(h);
3047
+ let te = h.querySelector("#simulator-panel"), _ = h.querySelector("#simulator-header"), v = h.querySelector("#simulator-header-indicator"), ne = h.querySelector("#simulator-header-status-text"), y = h.querySelector("#simulator-header-pause"), b = h.querySelector("#simulator-header-retry"), x = h.querySelector("#simulator-header-settings"), S = h.querySelector("#simulator-toggle"), C = h.querySelector("#simulator-timer"), w = h.querySelector("#simulator-tabs"), T = h.querySelector("#simulator-content"), E = (e) => h.querySelector(e), D = (e) => {
3048
+ y.innerHTML = e ? m.play : m.pause, y.title = e ? "Resume" : "Pause";
3049
+ }, O = (e, t) => {
3050
+ let n = E("#simulator-status .text"), r = E("#simulator-status .indicator"), i = t === "complete" ? "✓" : "";
3051
+ n && (n.textContent = e), r && (r.className = `indicator ${t}`, r.textContent = i), v.className = t, v.textContent = i, ne.textContent = e;
3052
+ }, k = (e, t) => {
3053
+ t && t !== "0" ? C.innerHTML = `${e}<span class="penalty">+${t}</span>` : C.textContent = e;
3054
+ }, A = (e) => {
2926
3055
  var t;
2927
- h.activeTab = e, D.classList.remove("hidden"), m(e), E.querySelectorAll(".simulator-tab").forEach((t) => {
3056
+ f.activeTab = e, T.classList.remove("hidden"), ee(e), w.querySelectorAll(".simulator-tab").forEach((t) => {
2928
3057
  t.classList.toggle("active", t.getAttribute("data-tab") === e);
2929
- }), _.querySelectorAll(".simulator-tab-content").forEach((t) => {
3058
+ }), h.querySelectorAll(".simulator-tab-content").forEach((t) => {
2930
3059
  t.classList.toggle("active", t.id === `simulator-tab-${e}`);
2931
- }), C.classList.toggle("active", e === "auth");
2932
- let n = d.find((t) => t.id === e);
2933
- n == null || (t = n.onActivate) == null || t.call(n, z);
2934
- }, N = (e) => {
2935
- h.isCollapsed = e, v.classList.toggle("collapsed", e), p(e), e ? (D.classList.add("hidden"), E.querySelectorAll(".simulator-tab").forEach((e) => e.classList.remove("active"))) : M(h.activeTab);
2936
- }, P = () => {
2937
- l.updatePreview(z);
2938
- }, F = function() {
3060
+ }), x.classList.toggle("active", e === "auth");
3061
+ let n = u.find((t) => t.id === e);
3062
+ n == null || (t = n.onActivate) == null || t.call(n, L);
3063
+ }, j = (e) => {
3064
+ f.isCollapsed = e, te.classList.toggle("collapsed", e), g(e), e ? (T.classList.add("hidden"), w.querySelectorAll(".simulator-tab").forEach((e) => e.classList.remove("active"))) : A(f.activeTab);
3065
+ }, M = () => {
3066
+ l.updatePreview(L);
3067
+ }, N = function() {
2939
3068
  var e = t(function* () {
2940
3069
  var e, t;
2941
- if (h.puzzleData) return h.puzzleData;
3070
+ if (f.puzzleData) return f.puzzleData;
2942
3071
  if (!o || o.size === 0) throw Error("No fixtures configured. Add puzzle fixture files (.json or .toml) to a fixtures directory and pass fixturesGlob to the simulator.");
2943
- let n = (e = h.selectedCategory) == null ? s[0] : e, r = n ? o.get(n) : void 0;
3072
+ let n = (e = f.selectedCategory) == null ? s[0] : e, r = n ? o.get(n) : void 0;
2944
3073
  if (!r || r.size === 0) throw Error(`No puzzles found in fixture category "${n}"`);
2945
- let i = (t = h.selectedPuzzle) == null ? r.keys().next().value : t, a = i ? r.get(i) : void 0;
3074
+ let i = (t = f.selectedPuzzle) == null ? r.keys().next().value : t, a = i ? r.get(i) : void 0;
2946
3075
  if (!a) throw Error(`Puzzle "${i}" not found in category "${n}"`);
2947
- h.puzzleData = a, console.log("Simulator: Puzzle loaded from fixtures", {
3076
+ f.puzzleData = a, console.log("Simulator: Puzzle loaded from fixtures", {
2948
3077
  category: n,
2949
3078
  puzzle: i
2950
- }), h.originalPuzzle = a;
2951
- let c = O("#simulator-puzzle");
2952
- return c && (c.value = h.originalPuzzle), h.activeTab === "thumb" && P(), h.puzzleData;
3079
+ }), f.originalPuzzle = a;
3080
+ let c = E("#simulator-puzzle");
3081
+ return c && (c.value = f.originalPuzzle), f.activeTab === "thumb" && M(), f.puzzleData;
2953
3082
  });
2954
3083
  return function() {
2955
3084
  return e.apply(this, arguments);
2956
3085
  };
2957
- }(), I = ee((e) => {
2958
- c.addLogEntry(e, z);
2959
- }), L = (e, t) => {
2960
- te(e, t, I);
2961
- }, R = (e, t) => {
2962
- let n = _.querySelector(`[data-badge="${e}"]`);
3086
+ }(), P = re((e) => {
3087
+ c.addLogEntry(e, L);
3088
+ }), F = (e, t) => {
3089
+ ie(e, t, P);
3090
+ }, I = (e, t) => {
3091
+ let n = h.querySelector(`[data-badge="${e}"]`);
2963
3092
  n && (n.textContent = t && t > 0 ? String(t) : "");
2964
- }, z = {
2965
- state: h,
2966
- getElement: O,
2967
- sendToGame: L,
2968
- logMessage: I.log,
2969
- loadPuzzle: F,
2970
- updateStatus: A,
2971
- updateTimer: j,
2972
- setCollapsed: N,
2973
- switchTab: M,
2974
- updateThumbnail: P,
2975
- updateBadge: R,
3093
+ }, L = {
3094
+ state: f,
3095
+ getElement: E,
3096
+ sendToGame: F,
3097
+ logMessage: P.log,
3098
+ loadPuzzle: N,
3099
+ updateStatus: O,
3100
+ updateTimer: k,
3101
+ setCollapsed: j,
3102
+ switchTab: A,
3103
+ updateThumbnail: M,
3104
+ updateBadge: I,
2976
3105
  fixtures: o,
2977
3106
  fixtureCategories: s,
2978
3107
  gameSlug: (i = e.slug) == null ? null : i
2979
3108
  };
2980
- console.log("[Simulator] Context created with gameSlug:", z.gameSlug), d.forEach((e) => e.bind(z)), E.querySelectorAll(".simulator-tab").forEach((e) => {
3109
+ console.log("[Simulator] Context created with gameSlug:", L.gameSlug), u.forEach((e) => e.bind(L)), w.querySelectorAll(".simulator-tab").forEach((e) => {
2981
3110
  e.addEventListener("click", () => {
2982
3111
  let t = e.getAttribute("data-tab");
2983
- M(t), R(t, 0);
3112
+ A(t), I(t, 0);
2984
3113
  });
2985
- }), w.addEventListener("click", (e) => {
2986
- e.stopPropagation(), N(!0);
2987
- }), x.addEventListener("click", (e) => {
2988
- e.stopPropagation(), h.isPaused ? (L("RESUME_GAME", {}), h.isPaused = !1, k(!1), A("Running", "ready")) : (L("PAUSE_GAME", {}), h.isPaused = !0, k(!0), A("Paused", "paused"));
2989
- let t = O("#simulator-pause");
2990
- t && (t.textContent = h.isPaused ? "Resume" : "Pause");
2991
3114
  }), S.addEventListener("click", (e) => {
2992
- e.stopPropagation(), L("RETRY_PUZZLE", {}), h.hasStarted = !1, h.isPaused = !1, k(!1), x.disabled = !0, A("Ready to retry", "ready");
2993
- let t = O("#simulator-pause"), n = O("#simulator-start");
2994
- t && (t.disabled = !0, t.textContent = "Pause"), n && (n.textContent = "Start");
2995
- }), C.addEventListener("click", (e) => {
2996
- e.stopPropagation(), h.isCollapsed && N(!1), M("auth");
3115
+ e.stopPropagation(), j(!0);
2997
3116
  }), y.addEventListener("click", (e) => {
2998
- h.isCollapsed && e.target !== w && N(!1);
2999
- }), h.isCollapsed || M(h.activeTab);
3000
- let B = new URLSearchParams(window.location.search);
3001
- (B.has("code") || B.has("error")) && (N(!1), M("auth"));
3002
- let V = (e) => ({
3117
+ e.stopPropagation(), f.isPaused ? (F("RESUME_GAME", {}), f.isPaused = !1, D(!1), O("Running", "ready")) : (F("PAUSE_GAME", {}), f.isPaused = !0, D(!0), O("Paused", "paused"));
3118
+ let t = E("#simulator-pause");
3119
+ t && (t.textContent = f.isPaused ? "Resume" : "Pause");
3120
+ }), b.addEventListener("click", (e) => {
3121
+ e.stopPropagation(), F("RETRY_PUZZLE", {}), f.hasStarted = !1, f.isPaused = !1, D(!1), y.disabled = !0, O("Ready to retry", "ready");
3122
+ let t = E("#simulator-pause"), n = E("#simulator-start");
3123
+ t && (t.disabled = !0, t.textContent = "Pause"), n && (n.textContent = "Start");
3124
+ }), x.addEventListener("click", (e) => {
3125
+ e.stopPropagation(), f.isCollapsed && j(!1), A("auth");
3126
+ }), _.addEventListener("click", (e) => {
3127
+ f.isCollapsed && e.target !== S && j(!1);
3128
+ }), f.isCollapsed || A(f.activeTab);
3129
+ let R = new URLSearchParams(window.location.search);
3130
+ (R.has("code") || R.has("error")) && (j(!1), A("auth"));
3131
+ let z = (e) => ({
3003
3132
  userState: {
3004
- gameSettings: h.gameSettings,
3133
+ gameSettings: f.gameSettings,
3005
3134
  id: "simulator-user",
3006
3135
  ownerID: "simulator-owner"
3007
3136
  },
@@ -3016,7 +3145,7 @@ function Ke(e = {}) {
3016
3145
  },
3017
3146
  startOrFindGameplay: { gamePlayed: {
3018
3147
  additionalTimeAddedSecs: 0,
3019
- boardState: h.currentInputStr,
3148
+ boardState: f.currentInputStr,
3020
3149
  combinedTimeSecs: 0,
3021
3150
  completed: !1,
3022
3151
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -3038,49 +3167,45 @@ function Ke(e = {}) {
3038
3167
  mostRecentDaily: null
3039
3168
  }
3040
3169
  } },
3041
- theme: h.selectedTheme,
3042
- hostContext: [{
3043
- type: "app",
3044
- layout: "desktop",
3045
- host: null
3046
- }],
3170
+ theme: f.selectedTheme,
3171
+ hostContext: f.hostContext,
3047
3172
  appRuntimeContract: "1.0"
3048
- }), fe = function() {
3173
+ }), B = function() {
3049
3174
  var e = t(function* () {
3050
- A("Loading puzzle...", "waiting");
3175
+ O("Loading puzzle...", "waiting");
3051
3176
  try {
3052
- let e = V(yield F());
3053
- A("Sending READY_DATA...", "waiting"), L("READY_DATA", e), A("Waiting for game to load...", "waiting");
3177
+ let e = z(yield N());
3178
+ O("Sending READY_DATA...", "waiting"), F("READY_DATA", e), O("Waiting for game to load...", "waiting");
3054
3179
  } catch (e) {
3055
- A(`Error: ${e}`, "paused");
3180
+ O(`Error: ${e}`, "paused");
3056
3181
  }
3057
3182
  });
3058
3183
  return function() {
3059
3184
  return e.apply(this, arguments);
3060
3185
  };
3061
- }(), H = () => {
3062
- console.log("Simulator: Game loaded, ready to start"), S.disabled = !1, d.forEach((e) => {
3186
+ }(), V = () => {
3187
+ console.log("Simulator: Game loaded, ready to start"), b.disabled = !1, u.forEach((e) => {
3063
3188
  var t;
3064
- return (t = e.onMessage) == null ? void 0 : t.call(e, "READY_GAME_LOADED", void 0, z);
3065
- }), a && !h.hasStarted && setTimeout(() => {
3066
- let e = O("#simulator-start");
3067
- e == null || e.click(), x.disabled = !1, h.hasStarted = !0, A("Running", "ready");
3189
+ return (t = e.onMessage) == null ? void 0 : t.call(e, "READY_GAME_LOADED", void 0, L);
3190
+ }), a && !f.hasStarted && setTimeout(() => {
3191
+ let e = E("#simulator-start");
3192
+ e == null || e.click(), y.disabled = !1, f.hasStarted = !0, O("Running", "ready");
3068
3193
  }, 100);
3069
3194
  };
3070
- return ne((e, t) => {
3195
+ return ae((e, t) => {
3071
3196
  var n, r;
3072
3197
  if (e === "READY") {
3073
- console.log("Simulator: Received READY from game"), fe();
3198
+ console.log("Simulator: Received READY from game"), B();
3074
3199
  return;
3075
3200
  }
3076
3201
  if (e === "READY_GAME_LOADED") {
3077
- H();
3202
+ V();
3078
3203
  return;
3079
3204
  }
3080
3205
  if (e === "TIMER_TICK") {
3081
3206
  if (t != null && t.display) {
3082
3207
  let [e, n] = t.display;
3083
- j(e, n);
3208
+ k(e, n);
3084
3209
  }
3085
3210
  return;
3086
3211
  }
@@ -3089,30 +3214,30 @@ function Ke(e = {}) {
3089
3214
  console.log("Simulator: Sidebar update", t);
3090
3215
  return;
3091
3216
  }
3092
- d.forEach((n) => {
3217
+ u.forEach((n) => {
3093
3218
  var r;
3094
- return (r = n.onMessage) == null ? void 0 : r.call(n, e, t, z);
3219
+ return (r = n.onMessage) == null ? void 0 : r.call(n, e, t, L);
3095
3220
  });
3096
3221
  let i = (n = t == null || (r = t.input) == null ? void 0 : r.boardState) == null ? t == null ? void 0 : t.boardState : n;
3097
- e === "UPLOAD_NEW_GAME_STATE" && i && (h.currentInputStr = i, h.activeTab === "thumb" && P(), console.log("Simulator: Game state uploaded", t)), e === "GAME_COMPLETED" && (console.log("Simulator: Game completed!", t), x.disabled = !0, h.hasStarted = !1, A("Completed!", "complete"));
3098
- }, I), console.log("Simulator initialized"), $ = {
3222
+ e === "UPLOAD_NEW_GAME_STATE" && i && (f.currentInputStr = i, f.activeTab === "thumb" && M(), console.log("Simulator: Game state uploaded", t)), e === "GAME_COMPLETED" && (console.log("Simulator: Game completed!", t), y.disabled = !0, f.hasStarted = !1, O("Completed!", "complete"));
3223
+ }, P), console.log("Simulator initialized"), $ = {
3099
3224
  updateFixtures: (e) => {
3100
- o = re(e), s = Array.from(o.keys()).sort(), z.fixtures = o, z.fixtureCategories = s;
3225
+ o = oe(e), s = Array.from(o.keys()).sort(), L.fixtures = o, L.fixtureCategories = s;
3101
3226
  let t = localStorage.getItem("simulator-fixture-category");
3102
- if (!h.selectedCategory || !s.includes(h.selectedCategory)) {
3227
+ if (!f.selectedCategory || !s.includes(f.selectedCategory)) {
3103
3228
  var n;
3104
- h.selectedCategory = t && s.includes(t) ? t : (n = s[0]) == null ? null : n;
3229
+ f.selectedCategory = t && s.includes(t) ? t : (n = s[0]) == null ? null : n;
3105
3230
  }
3106
- let r = d.find((e) => e.id === "ctrl");
3107
- r == null || r.bind(z), console.log("Simulator: Fixtures updated", {
3231
+ let r = u.find((e) => e.id === "ctrl");
3232
+ r == null || r.bind(L), console.log("Simulator: Fixtures updated", {
3108
3233
  categories: s,
3109
- selectedCategory: h.selectedCategory
3234
+ selectedCategory: f.selectedCategory
3110
3235
  });
3111
3236
  },
3112
- sendToGame: L,
3113
- loadPuzzle: F
3237
+ sendToGame: F,
3238
+ loadPuzzle: N
3114
3239
  }, $;
3115
3240
  }
3116
- export { Ke as t };
3241
+ export { Qe as t };
3117
3242
 
3118
- //# sourceMappingURL=createSimulator-COj3lAeu.js.map
3243
+ //# sourceMappingURL=createSimulator-Bo6J_KC_.js.map