@puzzmo/sdk 1.0.28 → 1.0.30

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/dist/analytics.d.ts +52 -0
  2. package/dist/analytics.d.ts.map +1 -0
  3. package/dist/{createSimulator-CC0PhepL.cjs → createSimulator-B7x0QRdO.cjs} +119 -29
  4. package/dist/createSimulator-B7x0QRdO.cjs.map +1 -0
  5. package/dist/{createSimulator-CWwSv8gh.js → createSimulator-DqF2fN_0.js} +526 -330
  6. package/dist/createSimulator-DqF2fN_0.js.map +1 -0
  7. package/dist/editor.d.ts +12 -2
  8. package/dist/editor.d.ts.map +1 -1
  9. package/dist/gameTracker.d.ts +16 -0
  10. package/dist/gameTracker.d.ts.map +1 -0
  11. package/dist/index.cjs +1 -1
  12. package/dist/index.cjs.map +1 -1
  13. package/dist/index.d.ts +2 -2
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +273 -120
  16. package/dist/index.js.map +1 -1
  17. package/dist/inputs/index.cjs +1 -1
  18. package/dist/inputs/index.js +1 -1
  19. package/dist/sdk.d.ts +18 -4
  20. package/dist/sdk.d.ts.map +1 -1
  21. package/dist/settings.spec.d.ts +2 -0
  22. package/dist/settings.spec.d.ts.map +1 -0
  23. package/dist/simulator/createSimulator.d.ts.map +1 -1
  24. package/dist/simulator/index.cjs +1 -1
  25. package/dist/simulator/index.js +1 -1
  26. package/dist/simulator/standalone.cjs +1 -1
  27. package/dist/simulator/standalone.js +1 -1
  28. package/dist/simulator/state.d.ts +2 -0
  29. package/dist/simulator/state.d.ts.map +1 -1
  30. package/dist/simulator/styles.d.ts +1 -1
  31. package/dist/simulator/styles.d.ts.map +1 -1
  32. package/dist/simulator/types.d.ts +5 -1
  33. package/dist/simulator/types.d.ts.map +1 -1
  34. package/dist/simulator/views/SettingsView.d.ts +8 -0
  35. package/dist/simulator/views/SettingsView.d.ts.map +1 -0
  36. package/dist/simulator/views/index.d.ts +1 -0
  37. package/dist/simulator/views/index.d.ts.map +1 -1
  38. package/dist/types.d.ts +76 -0
  39. package/dist/types.d.ts.map +1 -1
  40. package/dist/vite.cjs +2 -2
  41. package/dist/vite.js +18 -18
  42. package/package.json +1 -1
  43. package/dist/createSimulator-CC0PhepL.cjs.map +0 -1
  44. package/dist/createSimulator-CWwSv8gh.js.map +0 -1
  45. /package/dist/{asyncToGenerator-BlxRHn40.cjs → asyncToGenerator-DANjdFmB.cjs} +0 -0
  46. /package/dist/{asyncToGenerator-CPSNHDFw.js → asyncToGenerator-Dn36a-ch.js} +0 -0
  47. /package/dist/{objectSpread2-vLYiAtaU.js → objectSpread2-COovHPnD.js} +0 -0
  48. /package/dist/{objectSpread2-B6tAAMuy.cjs → objectSpread2-CuluYLUL.cjs} +0 -0
@@ -1,5 +1,5 @@
1
- import { t as e } from "./asyncToGenerator-CPSNHDFw.js";
2
- import { t } from "./objectSpread2-vLYiAtaU.js";
1
+ import { t as e } from "./objectSpread2-COovHPnD.js";
2
+ import { t } from "./asyncToGenerator-Dn36a-ch.js";
3
3
  const n = [
4
4
  {
5
5
  name: "Puzzmo (light)",
@@ -230,7 +230,7 @@ const n = [
230
230
  a_infoBG: "#C6C6C6"
231
231
  },
232
232
  {
233
- name: "Outlook Hayesy (beta)",
233
+ name: "Outlook Hayesy",
234
234
  type: "light",
235
235
  key: "#DAB98C",
236
236
  keyFG: "#000000",
@@ -313,9 +313,19 @@ var r = {
313
313
  fixtureCategory: "simulator-fixture-category",
314
314
  fixturePuzzle: "simulator-fixture-puzzle",
315
315
  renderHost: "simulator-render-host",
316
- renderContext: "simulator-render-context"
316
+ renderContext: "simulator-render-context",
317
+ gameSettings: "simulator-game-settings"
317
318
  };
318
319
  function i() {
320
+ let e = localStorage.getItem(r.gameSettings);
321
+ if (!e) return {};
322
+ try {
323
+ let t = JSON.parse(e);
324
+ if (t && typeof t == "object") return t;
325
+ } catch (e) {}
326
+ return {};
327
+ }
328
+ function a() {
319
329
  let e = localStorage.getItem(r.theme);
320
330
  if (e) {
321
331
  let t = n.find((t) => t.name === e);
@@ -323,16 +333,16 @@ function i() {
323
333
  }
324
334
  return n[0];
325
335
  }
326
- function a(e) {
336
+ function o(e) {
327
337
  var t;
328
338
  let n = localStorage.getItem(r.tab);
329
339
  return n && e.includes(n) ? n : (t = e[0]) == null ? "ctrl" : t;
330
340
  }
331
- function o(e) {
341
+ function s(e) {
332
342
  let t = localStorage.getItem(r.collapsed);
333
343
  return t === null ? e : t === "true";
334
344
  }
335
- function s() {
345
+ function c() {
336
346
  let e = localStorage.getItem(r.renderHost);
337
347
  return e && [
338
348
  "game",
@@ -340,7 +350,7 @@ function s() {
340
350
  "opengraph"
341
351
  ].includes(e) ? e : "game";
342
352
  }
343
- function c() {
353
+ function l() {
344
354
  let e = localStorage.getItem(r.renderContext);
345
355
  if (e && [
346
356
  "preview",
@@ -349,50 +359,58 @@ function c() {
349
359
  "timeline"
350
360
  ].includes(e)) return e;
351
361
  }
352
- function l(e, t, n) {
353
- var l, u;
354
- let d = localStorage.getItem(r.fixtureCategory), f = localStorage.getItem(r.fixturePuzzle);
362
+ function u(e, t, n) {
363
+ var u, d;
364
+ let f = localStorage.getItem(r.fixtureCategory), p = localStorage.getItem(r.fixturePuzzle);
355
365
  return {
356
- isCollapsed: o((l = e.collapsed) == null ? !0 : l),
366
+ isCollapsed: s((u = e.collapsed) == null ? !0 : u),
357
367
  isPaused: !1,
358
368
  hasStarted: !1,
359
- activeTab: a(n),
369
+ activeTab: o(n),
360
370
  puzzleData: null,
361
371
  originalPuzzle: "",
362
372
  currentInputStr: "",
363
373
  completionData: null,
364
- selectedTheme: i(),
365
- selectedCategory: d && t.includes(d) ? d : (u = t[0]) == null ? null : u,
366
- selectedPuzzle: f == null ? null : f,
367
- renderHost: s(),
368
- renderContext: c()
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(),
380
+ settingsComponents: null
369
381
  };
370
382
  }
371
- function u(e) {
383
+ function d(e) {
384
+ localStorage.setItem(r.gameSettings, JSON.stringify(e));
385
+ }
386
+ function f() {
387
+ localStorage.removeItem(r.gameSettings);
388
+ }
389
+ function p(e) {
372
390
  localStorage.setItem(r.collapsed, String(e));
373
391
  }
374
- function d(e) {
392
+ function m(e) {
375
393
  localStorage.setItem(r.tab, e);
376
394
  }
377
- function f(e) {
395
+ function h(e) {
378
396
  localStorage.setItem(r.theme, e);
379
397
  }
380
- function p(e) {
398
+ function g(e) {
381
399
  localStorage.setItem(r.fixtureCategory, e);
382
400
  }
383
- function m(e) {
401
+ function _(e) {
384
402
  localStorage.setItem(r.fixturePuzzle, e);
385
403
  }
386
- function h() {
404
+ function ee() {
387
405
  localStorage.removeItem(r.fixturePuzzle);
388
406
  }
389
- function g(e) {
407
+ function v(e) {
390
408
  e ? localStorage.setItem(r.renderHost, e) : localStorage.removeItem(r.renderHost);
391
409
  }
392
- function _(e) {
410
+ function y(e) {
393
411
  e ? localStorage.setItem(r.renderContext, e) : localStorage.removeItem(r.renderContext);
394
412
  }
395
- function ee(e) {
413
+ function te(e) {
396
414
  let t = [];
397
415
  return {
398
416
  log(n, r, i) {
@@ -417,13 +435,13 @@ function ee(e) {
417
435
  }
418
436
  };
419
437
  }
420
- function te(e, t, n) {
438
+ function ne(e, t, n) {
421
439
  console.log("Simulator sending:", e, t), n == null || n.log(e, t, "out"), window.postMessage({
422
440
  type: e,
423
441
  data: t
424
442
  }, "*");
425
443
  }
426
- function ne(e, t) {
444
+ function re(e, t) {
427
445
  let n = (n) => {
428
446
  var r, i, a;
429
447
  if (!(!(n == null || (r = n.data) == null) && r.type)) return;
@@ -433,7 +451,7 @@ function ne(e, t) {
433
451
  return window.addEventListener("message", n), () => window.removeEventListener("message", n);
434
452
  }
435
453
  /** Parse fixture imports into a structured format: { category: { filename: data } } */
436
- function v(e) {
454
+ function ie(e) {
437
455
  let t = /* @__PURE__ */ new Map();
438
456
  console.log("Simulator: Parsing fixtures", Object.keys(e));
439
457
  for (let [o, s] of Object.entries(e)) {
@@ -452,7 +470,7 @@ function v(e) {
452
470
  }), t;
453
471
  }
454
472
  /** Render fixture selector HTML */
455
- function y(e, t) {
473
+ function b(e, t) {
456
474
  return e.length === 0 ? "" : `
457
475
  <div class="simulator-fixtures">
458
476
  <div class="simulator-field">
@@ -469,7 +487,7 @@ function y(e, t) {
469
487
  `;
470
488
  }
471
489
  /** Update puzzle select options based on selected category */
472
- function b(e, t, n, r) {
490
+ function x(e, t, n, r) {
473
491
  let i = t.get(n);
474
492
  if (!i) return null;
475
493
  let a = Array.from(i.keys()), o = r;
@@ -480,11 +498,11 @@ function b(e, t, n, r) {
480
498
  return e.innerHTML = a.map((e) => `<option value="${e}" ${e === o ? "selected" : ""}>${e}</option>`).join(""), o;
481
499
  }
482
500
  /** Get puzzle data from fixtures */
483
- function x(e, t, n) {
501
+ function S(e, t, n) {
484
502
  var r, i;
485
503
  return !t || !n || (r = (i = e.get(t)) == null ? void 0 : i.get(n)) == null ? null : r;
486
504
  }
487
- function re() {
505
+ function ae() {
488
506
  return {
489
507
  id: "ctrl",
490
508
  label: "Ctrl",
@@ -499,19 +517,19 @@ function re() {
499
517
  selectedCategory: e.state.selectedCategory,
500
518
  selectedPuzzle: e.state.selectedPuzzle
501
519
  }), e.fixtures && e.fixtureCategories.length > 0 && i) {
502
- i.innerHTML = y(e.fixtureCategories, e.state.selectedCategory);
520
+ i.innerHTML = b(e.fixtureCategories, e.state.selectedCategory);
503
521
  let t = e.getElement("#simulator-fixture-category"), n = e.getElement("#simulator-fixture-puzzle");
504
522
  if (t && n && e.state.selectedCategory) {
505
- e.state.selectedPuzzle = b(n, e.fixtures, e.state.selectedCategory, e.state.selectedPuzzle);
506
- let r = x(e.fixtures, e.state.selectedCategory, e.state.selectedPuzzle);
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);
507
525
  console.log("Simulator: Loading fixture puzzle", {
508
526
  category: e.state.selectedCategory,
509
527
  puzzle: e.state.selectedPuzzle,
510
528
  hasPuzzleData: !!r
511
- }), r && (e.state.puzzleData = r, e.state.originalPuzzle = r, e.state.selectedCategory && p(e.state.selectedCategory), e.state.selectedPuzzle && m(e.state.selectedPuzzle)), t.addEventListener("change", () => {
512
- console.log("Simulator: Category changed, reloading...", t.value), p(t.value), h(), window.location.reload();
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), ee(), window.location.reload();
513
531
  }), n.addEventListener("change", () => {
514
- console.log("Simulator: Puzzle changed, reloading...", n.value), m(n.value), window.location.reload();
532
+ console.log("Simulator: Puzzle changed, reloading...", n.value), _(n.value), window.location.reload();
515
533
  });
516
534
  }
517
535
  }
@@ -529,9 +547,9 @@ function re() {
529
547
  }
530
548
  };
531
549
  }
532
- var S = "simulator-saved-states";
550
+ var C = "simulator-saved-states";
533
551
  /** Find thumbnail function on globalThis (looks for functions ending in "Thumbnail") */
534
- function C() {
552
+ function w() {
535
553
  let e = globalThis;
536
554
  for (let t of Object.keys(e)) if (t.endsWith("Thumbnail") && typeof e[t] == "function") return {
537
555
  name: t,
@@ -540,8 +558,8 @@ function C() {
540
558
  return null;
541
559
  }
542
560
  /** Generate a small thumbnail SVG for a given input string */
543
- function w(e, t) {
544
- let n = C();
561
+ function T(e, t) {
562
+ let n = w();
545
563
  if (!n) return "";
546
564
  try {
547
565
  var r;
@@ -556,14 +574,14 @@ function w(e, t) {
556
574
  return "";
557
575
  }
558
576
  }
559
- var T = [];
560
- function E(e, t = 8) {
577
+ var E = [];
578
+ function D(e, t = 8) {
561
579
  let n = 14 * t + 8 + 4;
562
580
  e.style.height = "auto";
563
581
  let r = Math.min(Math.max(e.scrollHeight, 40), n);
564
582
  e.style.height = `${r}px`;
565
583
  }
566
- function ie() {
584
+ function oe() {
567
585
  let e = "", t = "";
568
586
  return {
569
587
  id: "data",
@@ -581,102 +599,102 @@ function ie() {
581
599
  let i = n.getElement(".data-view-container");
582
600
  i == null || i.querySelectorAll(".data-subtab-content").forEach((e) => {
583
601
  e.classList.toggle("active", e.id === `data-subtab-${t}`);
584
- }), t === "edit" ? j(n) : t === "history" ? O(n) : t === "saves" && k(n);
602
+ }), t === "edit" ? M(n) : t === "history" ? k(n) : t === "saves" && A(n);
585
603
  });
586
604
  });
587
605
  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");
588
606
  setTimeout(() => {
589
- i && n.state.originalPuzzle && (i.value = n.state.originalPuzzle, e = n.state.originalPuzzle, E(i)), a && n.state.currentInputStr && (a.value = n.state.currentInputStr, t = n.state.currentInputStr, E(a));
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));
590
608
  }, 0), i == null || i.addEventListener("input", () => {
591
- E(i);
609
+ D(i);
592
610
  let t = i.value !== e;
593
611
  s && (s.disabled = !t);
594
612
  }), a == null || a.addEventListener("input", () => {
595
- E(a);
613
+ D(a);
596
614
  let e = a.value !== t;
597
615
  l && (l.disabled = !e);
598
616
  }), o == null || o.addEventListener("click", () => {
599
- i && (i.value = n.state.originalPuzzle, e = n.state.originalPuzzle, E(i), s && (s.disabled = !0));
617
+ i && (i.value = n.state.originalPuzzle, e = n.state.originalPuzzle, D(i), s && (s.disabled = !0));
600
618
  }), s == null || s.addEventListener("click", () => {
601
619
  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);
602
620
  }), c == null || c.addEventListener("click", () => {
603
- a && (a.value = t, E(a), l && (l.disabled = !0));
621
+ a && (a.value = t, D(a), l && (l.disabled = !0));
604
622
  }), l == null || l.addEventListener("click", () => {
605
623
  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);
606
624
  });
607
625
  let f = n.getElement("#simulator-history-clear");
608
626
  f == null || f.addEventListener("click", () => {
609
- T = [], O(n);
627
+ E = [], k(n);
610
628
  });
611
629
  let p = n.getElement("#simulator-save-name"), m = n.getElement("#simulator-save-btn");
612
630
  m == null || m.addEventListener("click", () => {
613
631
  if (!p || !p.value.trim()) return;
614
- let e = D(), t = {
632
+ let e = O(), t = {
615
633
  name: p.value.trim(),
616
634
  puzzleStr: n.state.originalPuzzle,
617
635
  inputStr: n.state.currentInputStr,
618
636
  timestamp: Date.now()
619
637
  };
620
- e.push(t), localStorage.setItem(S, JSON.stringify(e)), p.value = "", k(n);
621
- }), k(n);
638
+ e.push(t), localStorage.setItem(C, JSON.stringify(e)), p.value = "", A(n);
639
+ }), A(n);
622
640
  },
623
641
  onActivate(n) {
624
- e = n.state.originalPuzzle, t = n.state.currentInputStr, j(n), O(n);
642
+ e = n.state.originalPuzzle, t = n.state.currentInputStr, M(n), k(n);
625
643
  },
626
644
  onMessage(e, n, r) {
627
645
  var i, a;
628
646
  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;
629
647
  if (e === "UPLOAD_NEW_GAME_STATE" && c) {
630
- if (r.state.currentInputStr = c, T.length === 0 || T[T.length - 1].value !== c) {
631
- T.push({
648
+ if (r.state.currentInputStr = c, E.length === 0 || E[E.length - 1].value !== c) {
649
+ E.push({
632
650
  value: c,
633
651
  timestamp: Date.now()
634
- }), T.length > 100 && (T = T.slice(-100));
652
+ }), E.length > 100 && (E = E.slice(-100));
635
653
  let e = r.getElement("#data-subtab-history");
636
- e != null && e.classList.contains("active") && O(r);
654
+ e != null && e.classList.contains("active") && k(r);
637
655
  }
638
- o && (o.value = r.state.currentInputStr, t = r.state.currentInputStr, E(o), s && (s.disabled = !0));
656
+ o && (o.value = r.state.currentInputStr, t = r.state.currentInputStr, D(o), s && (s.disabled = !0));
639
657
  }
640
658
  }
641
659
  };
642
660
  }
643
- function D() {
661
+ function O() {
644
662
  try {
645
- let e = localStorage.getItem(S);
663
+ let e = localStorage.getItem(C);
646
664
  return e ? JSON.parse(e) : [];
647
665
  } catch (e) {
648
666
  return [];
649
667
  }
650
668
  }
651
- function O(e) {
669
+ function k(e) {
652
670
  let t = e.getElement("#simulator-history-list");
653
671
  if (t) {
654
- if (t.style.setProperty("--history-thumb-bg", e.state.selectedTheme.a_bg), T.length === 0) {
672
+ if (t.style.setProperty("--history-thumb-bg", e.state.selectedTheme.a_bg), E.length === 0) {
655
673
  t.innerHTML = "<div class=\"simulator-empty\">No history yet</div>";
656
674
  return;
657
675
  }
658
- t.innerHTML = [...T].reverse().map((t, n) => {
659
- let r = T.length - 1 - n, i = new Date(t.timestamp).toLocaleTimeString(), a = t.value.length > 60 ? t.value.slice(0, 60) + "..." : t.value;
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;
660
678
  return `
661
679
  <div class="history-item" data-history-idx="${r}">
662
- <div class="history-item-thumb">${w(e, t.value)}</div>
680
+ <div class="history-item-thumb">${T(e, t.value)}</div>
663
681
  <div class="history-item-content">
664
682
  <div class="history-item-header">
665
683
  <span class="history-item-num">#${r + 1}</span>
666
684
  <span class="history-item-time">${i}</span>
667
685
  <button class="simulator-btn tiny history-restore-btn" data-history-idx="${r}">Restore</button>
668
686
  </div>
669
- <div class="history-item-preview">${A(a)}</div>
687
+ <div class="history-item-preview">${j(a)}</div>
670
688
  </div>
671
689
  </div>
672
690
  `;
673
691
  }).join(""), t.querySelectorAll(".history-restore-btn").forEach((t) => {
674
692
  t.addEventListener("click", (t) => {
675
- let n = parseInt(t.target.getAttribute("data-history-idx") || "0"), r = T[n];
693
+ let n = parseInt(t.target.getAttribute("data-history-idx") || "0"), r = E[n];
676
694
  if (r) {
677
695
  e.state.currentInputStr = r.value;
678
696
  let t = e.getElement("#simulator-input");
679
- t && (t.value = r.value, E(t)), e.updateStatus("Input restored from history", "ready");
697
+ t && (t.value = r.value, D(t)), e.updateStatus("Input restored from history", "ready");
680
698
  let n = e.getElement(".data-subtab[data-subtab=\"edit\"]");
681
699
  n == null || n.click();
682
700
  }
@@ -684,10 +702,10 @@ function O(e) {
684
702
  });
685
703
  }
686
704
  }
687
- function k(e) {
705
+ function A(e) {
688
706
  let t = e.getElement("#simulator-saves-list");
689
707
  if (!t) return;
690
- let n = D();
708
+ let n = O();
691
709
  if (n.length === 0) {
692
710
  t.innerHTML = "<div class=\"simulator-empty\">No saved states</div>";
693
711
  return;
@@ -697,7 +715,7 @@ function k(e) {
697
715
  return `
698
716
  <div class="save-item">
699
717
  <div class="save-item-header">
700
- <span class="save-item-name">${A(e.name)}</span>
718
+ <span class="save-item-name">${j(e.name)}</span>
701
719
  <span class="save-item-time">${i} ${a}</span>
702
720
  </div>
703
721
  <div class="save-item-actions">
@@ -712,7 +730,7 @@ function k(e) {
712
730
  if (r) {
713
731
  e.state.puzzleData = r.puzzleStr, e.state.originalPuzzle = r.puzzleStr, e.state.currentInputStr = r.inputStr;
714
732
  let t = e.getElement("#simulator-puzzle"), n = e.getElement("#simulator-input");
715
- t && (t.value = r.puzzleStr, E(t)), n && (n.value = r.inputStr, E(n)), e.updateStatus(`Loaded: ${r.name}`, "ready");
733
+ t && (t.value = r.puzzleStr, D(t)), n && (n.value = r.inputStr, D(n)), e.updateStatus(`Loaded: ${r.name}`, "ready");
716
734
  let i = e.getElement(".data-subtab[data-subtab=\"edit\"]");
717
735
  i == null || i.click();
718
736
  }
@@ -720,21 +738,21 @@ function k(e) {
720
738
  }), t.querySelectorAll(".save-delete-btn").forEach((t) => {
721
739
  t.addEventListener("click", (t) => {
722
740
  let r = parseInt(t.target.getAttribute("data-save-idx") || "0"), i = n.filter((e, t) => t !== r);
723
- localStorage.setItem(S, JSON.stringify(i)), k(e);
741
+ localStorage.setItem(C, JSON.stringify(i)), A(e);
724
742
  });
725
743
  });
726
744
  }
727
- function A(e) {
745
+ function j(e) {
728
746
  return e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
729
747
  }
730
- function j(e) {
748
+ function M(e) {
731
749
  let t = e.getElement("#simulator-puzzle"), n = e.getElement("#simulator-input"), r = e.getElement("#simulator-puzzle-apply"), i = e.getElement("#simulator-input-apply");
732
- t && e.state.originalPuzzle && (t.value = e.state.originalPuzzle, E(t), r && (r.disabled = !0)), n && (n.value = e.state.currentInputStr, E(n), i && (i.disabled = !0));
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));
733
751
  }
734
- function M(e) {
752
+ function N(e) {
735
753
  return e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
736
754
  }
737
- function ae() {
755
+ function se() {
738
756
  let e = 0;
739
757
  return {
740
758
  id: "msgs",
@@ -761,7 +779,7 @@ function ae() {
761
779
  <span class="simulator-msg-type">${t.direction === "out" ? "→" : "←"} ${t.type}</span>
762
780
  <span class="simulator-msg-time">${t.time}</span>
763
781
  </div>
764
- ${a ? `<div class="simulator-msg-data">${M(a)}</div>` : ""}
782
+ ${a ? `<div class="simulator-msg-data">${N(a)}</div>` : ""}
765
783
  `;
766
784
  let o = i.querySelector(".simulator-msg-data");
767
785
  for (o && o.addEventListener("click", () => {
@@ -772,7 +790,7 @@ function ae() {
772
790
  }
773
791
  };
774
792
  }
775
- function oe() {
793
+ function ce() {
776
794
  return {
777
795
  id: "done",
778
796
  label: "Done",
@@ -809,7 +827,7 @@ function oe() {
809
827
  }
810
828
  };
811
829
  }
812
- function se() {
830
+ function le() {
813
831
  let e = [], t = () => (/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", { hour12: !1 }), n = (e) => {
814
832
  let { checkpointName: t, augConfig: n, time: r } = e, i = n == null ? void 0 : n.deeds;
815
833
  return `
@@ -860,7 +878,7 @@ function se() {
860
878
  };
861
879
  }
862
880
  /** Find thumbnail function on globalThis (looks for functions ending in "Thumbnail") */
863
- function N() {
881
+ function P() {
864
882
  let e = globalThis;
865
883
  for (let t of Object.keys(e)) if (t.endsWith("Thumbnail") && typeof e[t] == "function") return {
866
884
  name: t,
@@ -868,7 +886,7 @@ function N() {
868
886
  };
869
887
  return null;
870
888
  }
871
- function ce() {
889
+ function ue() {
872
890
  return {
873
891
  id: "thumb",
874
892
  label: "Thumb",
@@ -881,10 +899,10 @@ function ce() {
881
899
  let n = e.getElement("#simulator-render-host-select"), r = e.getElement("#simulator-render-context-select"), i = e.getElement("#simulator-render-context-field"), a = () => {
882
900
  i && (i.style.display = e.state.renderHost === "opengraph" ? "block" : "none");
883
901
  };
884
- n && (e.state.renderHost || (e.state.renderHost = "game", g(e.state.renderHost)), n.value = e.state.renderHost || "game", n.addEventListener("change", () => {
885
- e.state.renderHost = n.value, g(e.state.renderHost), a(), e.updateThumbnail();
886
- })), r && (e.state.renderContext || (e.state.renderContext = "preview", _(e.state.renderContext)), r.value = e.state.renderContext || "preview", r.addEventListener("change", () => {
887
- e.state.renderContext = r.value, _(e.state.renderContext), e.updateThumbnail();
902
+ n && (e.state.renderHost || (e.state.renderHost = "game", v(e.state.renderHost)), n.value = e.state.renderHost || "game", n.addEventListener("change", () => {
903
+ e.state.renderHost = n.value, v(e.state.renderHost), a(), e.updateThumbnail();
904
+ })), r && (e.state.renderContext || (e.state.renderContext = "preview", y(e.state.renderContext)), r.value = e.state.renderContext || "preview", r.addEventListener("change", () => {
905
+ e.state.renderContext = r.value, y(e.state.renderContext), e.updateThumbnail();
888
906
  })), a();
889
907
  },
890
908
  onActivate(e) {
@@ -893,7 +911,7 @@ function ce() {
893
911
  updatePreview: (e) => {
894
912
  let t = e.getElement("#simulator-thumb-preview"), n = e.getElement("#simulator-thumb-fn");
895
913
  t == null || t.style.setProperty("--sim-thumb-bg", e.state.selectedTheme.g_bg);
896
- let r = N();
914
+ let r = P();
897
915
  if (!r) {
898
916
  t && (t.innerHTML = "<span class=\"simulator-empty\">No thumbnail function found</span>"), n && (n.textContent = "");
899
917
  return;
@@ -916,7 +934,7 @@ function ce() {
916
934
  };
917
935
  }
918
936
  /** Generate theme preview HTML showing key colors */
919
- function P(e) {
937
+ function F(e) {
920
938
  let t = [
921
939
  e.key,
922
940
  e.subBrand,
@@ -927,7 +945,7 @@ function P(e) {
927
945
  ].map((e) => `<div class="simulator-theme-preview-cell" style="background: ${e}"></div>`).join("");
928
946
  return `<div class="simulator-theme-preview" style="background: ${e.g_bg}">${t}</div>`;
929
947
  }
930
- function le() {
948
+ function de() {
931
949
  return {
932
950
  id: "theme",
933
951
  label: "Theme",
@@ -939,49 +957,49 @@ function le() {
939
957
  t && n.forEach((n) => {
940
958
  let r = document.createElement("div");
941
959
  r.className = `simulator-theme-item${n.name === e.state.selectedTheme.name ? " selected" : ""}`, r.innerHTML = `
942
- ${P(n)}
960
+ ${F(n)}
943
961
  <div class="simulator-theme-name">${n.name}</div>
944
962
  <div class="simulator-theme-type">${n.type}</div>
945
963
  `, r.addEventListener("click", () => {
946
- console.log("Simulator: Theme changed, reloading...", n.name), f(n.name), window.location.reload();
964
+ console.log("Simulator: Theme changed, reloading...", n.name), h(n.name), window.location.reload();
947
965
  }), t.appendChild(r);
948
966
  });
949
967
  }
950
968
  };
951
969
  }
952
- var F = "puzzmo_sim_api_mode", I = "http://localhost:8911", L = "https://api.puzzmo.com", R = () => localStorage.getItem(F) === "dev" ? "dev" : "prod", z = (e) => {
953
- localStorage.setItem(F, e);
954
- }, B = null, V = function() {
955
- var t = e(function* () {
970
+ var I = "puzzmo_sim_api_mode", L = "http://localhost:8911", R = "https://api.puzzmo.com", z = () => localStorage.getItem(I) === "dev" ? "dev" : "prod", fe = (e) => {
971
+ localStorage.setItem(I, e);
972
+ }, B = null, pe = function() {
973
+ var e = t(function* () {
956
974
  if (B !== null) return B;
957
975
  try {
958
- let e = new AbortController(), t = setTimeout(() => e.abort(), 1e3), n = yield fetch(`${I}/healthz`, { signal: e.signal });
976
+ let e = new AbortController(), t = setTimeout(() => e.abort(), 1e3), n = yield fetch(`${L}/healthz`, { signal: e.signal });
959
977
  return clearTimeout(t), B = n.ok, B;
960
978
  } catch (e) {
961
979
  return B = !1, !1;
962
980
  }
963
981
  });
964
982
  return function() {
965
- return t.apply(this, arguments);
983
+ return e.apply(this, arguments);
966
984
  };
967
- }(), H = () => ({
968
- apiURL: R() === "dev" ? I : L,
985
+ }(), V = () => ({
986
+ apiURL: z() === "dev" ? L : R,
969
987
  clientID: "protosdk:oauthclient",
970
988
  redirectUri: `${window.location.origin}/oauth/callback`
971
- }), U = () => {
989
+ }), me = () => {
972
990
  let e = new Uint8Array(32);
973
991
  return crypto.getRandomValues(e), Array.from(e, (e) => e.toString(16).padStart(2, "0")).join("");
974
- }, W = "puzzmo_sim_oauth_token", G = "puzzmo_sim_oauth_refresh_token", ue = (e) => localStorage.setItem(W, e), de = (e) => localStorage.setItem(G, e), K = () => {
975
- let e = localStorage.getItem(W);
992
+ }, H = "puzzmo_sim_oauth_token", U = "puzzmo_sim_oauth_refresh_token", he = (e) => localStorage.setItem(H, e), ge = (e) => localStorage.setItem(U, e), W = () => {
993
+ let e = localStorage.getItem(H);
976
994
  return e && `${e.substring(0, 20)}`, e;
977
- }, q = () => localStorage.getItem(G), J = () => {
978
- localStorage.removeItem(W), localStorage.removeItem(G);
979
- }, fe = () => {
980
- let e = H(), t = U();
995
+ }, G = () => localStorage.getItem(U), K = () => {
996
+ localStorage.removeItem(H), localStorage.removeItem(U);
997
+ }, _e = () => {
998
+ let e = V(), t = me();
981
999
  sessionStorage.setItem("oauth_state", t), sessionStorage.setItem("oauth_return_url", window.location.href);
982
1000
  let n = new URL(`${e.apiURL}/oauth/auth`);
983
1001
  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();
984
- }, pe = (e) => {
1002
+ }, ve = (e) => {
985
1003
  try {
986
1004
  let t = e.split(".");
987
1005
  if (t.length !== 3) return !0;
@@ -990,11 +1008,11 @@ var F = "puzzmo_sim_api_mode", I = "http://localhost:8911", L = "https://api.puz
990
1008
  } catch (e) {
991
1009
  return !0;
992
1010
  }
993
- }, me = function() {
994
- var t = e(function* () {
995
- let e = q();
1011
+ }, ye = function() {
1012
+ var e = t(function* () {
1013
+ let e = G();
996
1014
  if (!e) return !1;
997
- let t = H();
1015
+ let t = V();
998
1016
  try {
999
1017
  let n = new URLSearchParams({
1000
1018
  grant_type: "refresh_token",
@@ -1008,19 +1026,19 @@ var F = "puzzmo_sim_api_mode", I = "http://localhost:8911", L = "https://api.puz
1008
1026
  if (!r.ok) return r.statusText, !1;
1009
1027
  let i = yield r.json(), a = i.access_token || i.accessToken;
1010
1028
  if (!a) return !1;
1011
- ue(a);
1029
+ he(a);
1012
1030
  let o = i.refresh_token || i.refreshToken;
1013
- return o && de(o), !0;
1031
+ return o && ge(o), !0;
1014
1032
  } catch (e) {
1015
1033
  return !1;
1016
1034
  }
1017
1035
  });
1018
1036
  return function() {
1019
- return t.apply(this, arguments);
1037
+ return e.apply(this, arguments);
1020
1038
  };
1021
- }(), he = function() {
1022
- var t = e(function* (e, t) {
1023
- let n = H(), r = sessionStorage.getItem("oauth_state");
1039
+ }(), be = function() {
1040
+ var e = t(function* (e, t) {
1041
+ let n = V(), r = sessionStorage.getItem("oauth_state");
1024
1042
  if (!r || r !== t) return null;
1025
1043
  sessionStorage.removeItem("oauth_state");
1026
1044
  try {
@@ -1039,16 +1057,16 @@ var F = "puzzmo_sim_api_mode", I = "http://localhost:8911", L = "https://api.puz
1039
1057
  return null;
1040
1058
  }
1041
1059
  });
1042
- return function(e, n) {
1043
- return t.apply(this, arguments);
1060
+ return function(t, n) {
1061
+ return e.apply(this, arguments);
1044
1062
  };
1045
- }(), ge = function() {
1046
- var t = e(function* (e, t = {}) {
1047
- let n = H(), r = K();
1063
+ }(), xe = function() {
1064
+ var e = t(function* (e, t = {}) {
1065
+ let n = V(), r = W();
1048
1066
  if (!r) throw Error("Not authenticated");
1049
- if (pe(r)) if (yield me()) {
1050
- if (r = K(), !r) throw Error("Token refresh succeeded but no token available");
1051
- } else throw J(), Error("Session expired. Please log in again.");
1067
+ if (ve(r)) if (yield ye()) {
1068
+ if (r = W(), !r) throw Error("Token refresh succeeded but no token available");
1069
+ } else throw K(), Error("Session expired. Please log in again.");
1052
1070
  let i = yield fetch(`${n.apiURL}/graphql`, {
1053
1071
  method: "POST",
1054
1072
  headers: {
@@ -1064,10 +1082,10 @@ var F = "puzzmo_sim_api_mode", I = "http://localhost:8911", L = "https://api.puz
1064
1082
  if (!i.ok) throw Error(`API request failed: ${i.statusText}`);
1065
1083
  return i.json();
1066
1084
  });
1067
- return function(e) {
1068
- return t.apply(this, arguments);
1085
+ return function(t) {
1086
+ return e.apply(this, arguments);
1069
1087
  };
1070
- }(), _e = (e) => {
1088
+ }(), Se = (e) => {
1071
1089
  try {
1072
1090
  let t = e.split(".");
1073
1091
  return t.length, t.length === 3 ? JSON.parse(atob(t[1])) : null;
@@ -1075,15 +1093,15 @@ var F = "puzzmo_sim_api_mode", I = "http://localhost:8911", L = "https://api.puz
1075
1093
  return null;
1076
1094
  }
1077
1095
  };
1078
- function ve() {
1079
- let t = !1;
1096
+ function Ce() {
1097
+ let e = !1;
1080
1098
  return {
1081
1099
  id: "auth",
1082
1100
  label: "Auth",
1083
1101
  render() {
1084
- let e = K(), t = !!e, n = R(), r = n === "dev" ? I : L, i = `<button class="simulator-btn tiny" id="auth-dev-toggle" style="display: none;">${n === "dev" ? "Using Dev" : "Dev"}</button>`;
1102
+ let e = W(), 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>`;
1085
1103
  if (t) {
1086
- let t = _e(e), n = t != null && t.exp ? (/* @__PURE__ */ new Date(t.exp * 1e3)).toLocaleString() : "Unknown", a = !!q(), o = a ? _e(q()) : null, s = o != null && o.exp ? (/* @__PURE__ */ new Date(o.exp * 1e3)).toLocaleString() : null;
1104
+ let t = Se(e), n = t != null && t.exp ? (/* @__PURE__ */ new Date(t.exp * 1e3)).toLocaleString() : "Unknown", a = !!G(), o = a ? Se(G()) : null, s = o != null && o.exp ? (/* @__PURE__ */ new Date(o.exp * 1e3)).toLocaleString() : null;
1087
1105
  return `
1088
1106
  <div class="simulator-section">
1089
1107
  <div class="simulator-section-title auth-title-row">
@@ -1124,7 +1142,7 @@ function ve() {
1124
1142
  </div>
1125
1143
  <p class="auth-description">
1126
1144
  Login with your Puzzmo account to make authenticated API requests.
1127
- ${n === "dev" ? `<br><strong>Using local dev server:</strong> ${I}` : ""}
1145
+ ${n === "dev" ? `<br><strong>Using local dev server:</strong> ${L}` : ""}
1128
1146
  </p>
1129
1147
  <div class="simulator-row">
1130
1148
  <button class="simulator-btn primary" id="auth-login">Login with Puzzmo</button>
@@ -1135,21 +1153,21 @@ function ve() {
1135
1153
  },
1136
1154
  bind(n) {
1137
1155
  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");
1138
- t ? B && c && (c.style.display = "", R() === "dev" && c.classList.add("active")) : (t = !0, V().then((e) => {
1139
- e && c && (c.style.display = "", R() === "dev" && c.classList.add("active"));
1156
+ e ? B && c && (c.style.display = "", z() === "dev" && c.classList.add("active")) : (e = !0, pe().then((e) => {
1157
+ e && c && (c.style.display = "", z() === "dev" && c.classList.add("active"));
1140
1158
  })), c == null || c.addEventListener("click", () => {
1141
- z(R() === "dev" ? "prod" : "dev"), J(), window.location.reload();
1159
+ fe(z() === "dev" ? "prod" : "dev"), K(), window.location.reload();
1142
1160
  }), r == null || r.addEventListener("click", () => {
1143
- fe();
1161
+ _e();
1144
1162
  }), i == null || i.addEventListener("click", () => {
1145
- J(), window.location.reload();
1146
- }), a == null || a.addEventListener("click", e(function* () {
1147
- a.disabled = !0, a.textContent = "Refreshing...", (yield me()) ? window.location.reload() : (a.textContent = "Refresh Failed", a.disabled = !1);
1148
- })), o == null || o.addEventListener("click", e(function* () {
1163
+ K(), window.location.reload();
1164
+ }), a == null || a.addEventListener("click", t(function* () {
1165
+ a.disabled = !0, a.textContent = "Refreshing...", (yield ye()) ? window.location.reload() : (a.textContent = "Refresh Failed", a.disabled = !1);
1166
+ })), o == null || o.addEventListener("click", t(function* () {
1149
1167
  if (s) {
1150
1168
  s.innerHTML = "<div class=\"loading\">Loading...</div>";
1151
1169
  try {
1152
- let t = yield ge("\n query {\n currentUser {\n id\n username\n usernameID\n name\n }\n }\n ");
1170
+ let t = yield xe("\n query {\n currentUser {\n id\n username\n usernameID\n name\n }\n }\n ");
1153
1171
  if (t.errors) {
1154
1172
  var e;
1155
1173
  s.innerHTML = `<div class="error">Error: ${((e = t.errors[0]) == null ? void 0 : e.message) || "Unknown error"}</div>`;
@@ -1160,38 +1178,38 @@ function ve() {
1160
1178
  }
1161
1179
  }));
1162
1180
  },
1163
- onActivate(t) {
1164
- return e(function* () {
1165
- let e = new URLSearchParams(window.location.search), n = e.get("code"), r = e.get("state"), i = e.get("error");
1181
+ onActivate(e) {
1182
+ return t(function* () {
1183
+ let t = new URLSearchParams(window.location.search), n = t.get("code"), r = t.get("state"), i = t.get("error");
1166
1184
  if (i) {
1167
- let e = t.getElement("#auth-error");
1168
- e && (e.innerHTML = `<div class="error">OAuth error: ${i}</div>`), window.history.replaceState({}, "", window.location.pathname);
1185
+ let t = e.getElement("#auth-error");
1186
+ t && (t.innerHTML = `<div class="error">OAuth error: ${i}</div>`), window.history.replaceState({}, "", window.location.pathname);
1169
1187
  return;
1170
1188
  }
1171
1189
  if (n && r) {
1172
- let e = t.getElement("#auth-status");
1173
- e && (e.innerHTML = "<span class=\"indicator waiting\"></span><span>Exchanging code...</span>");
1174
- let i = yield he(n, r);
1190
+ let t = e.getElement("#auth-status");
1191
+ t && (t.innerHTML = "<span class=\"indicator waiting\"></span><span>Exchanging code...</span>");
1192
+ let i = yield be(n, r);
1175
1193
  if (window.history.replaceState({}, "", window.location.pathname), i) {
1176
1194
  let e = i.access_token || i.accessToken;
1177
1195
  if (e) {
1178
- ue(e);
1196
+ he(e);
1179
1197
  let t = i.refresh_token || i.refreshToken;
1180
- t && de(t);
1198
+ t && ge(t);
1181
1199
  }
1182
1200
  window.location.reload();
1183
1201
  } else {
1184
- let e = t.getElement("#auth-error");
1185
- e && (e.innerHTML = "<div class=\"error\">Failed to exchange code for token</div>");
1202
+ let t = e.getElement("#auth-error");
1203
+ t && (t.innerHTML = "<div class=\"error\">Failed to exchange code for token</div>");
1186
1204
  }
1187
1205
  }
1188
1206
  })();
1189
1207
  }
1190
1208
  };
1191
1209
  }
1192
- var ye = "puzzmo_sim_api_mode", be = "http://localhost:8911", xe = "https://api.puzzmo.com", Y = "puzzmo_sim_oauth_token", X = "puzzmo_sim_oauth_refresh_token", Se = () => localStorage.getItem(ye) === "dev" ? "dev" : "prod", Z = () => localStorage.getItem(Y), Ce = () => localStorage.getItem(X), we = (e) => localStorage.setItem(Y, e), Te = (e) => localStorage.setItem(X, e), Ee = () => {
1193
- localStorage.removeItem(Y), localStorage.removeItem(X);
1194
- }, De = (e) => {
1210
+ var we = "puzzmo_sim_api_mode", Te = "http://localhost:8911", Ee = "https://api.puzzmo.com", q = "puzzmo_sim_oauth_token", J = "puzzmo_sim_oauth_refresh_token", De = () => localStorage.getItem(we) === "dev" ? "dev" : "prod", Y = () => localStorage.getItem(q), Oe = () => localStorage.getItem(J), ke = (e) => localStorage.setItem(q, e), Ae = (e) => localStorage.setItem(J, e), je = () => {
1211
+ localStorage.removeItem(q), localStorage.removeItem(J);
1212
+ }, Me = (e) => {
1195
1213
  try {
1196
1214
  let t = e.split(".");
1197
1215
  if (t.length !== 3) return !0;
@@ -1200,11 +1218,11 @@ var ye = "puzzmo_sim_api_mode", be = "http://localhost:8911", xe = "https://api.
1200
1218
  } catch (e) {
1201
1219
  return !0;
1202
1220
  }
1203
- }, Oe = function() {
1204
- var t = e(function* () {
1205
- let e = Ce();
1221
+ }, Ne = function() {
1222
+ var e = t(function* () {
1223
+ let e = Oe();
1206
1224
  if (!e) return !1;
1207
- let t = Se() === "dev" ? be : xe;
1225
+ let t = De() === "dev" ? Te : Ee;
1208
1226
  try {
1209
1227
  let n = new URLSearchParams({
1210
1228
  grant_type: "refresh_token",
@@ -1218,23 +1236,23 @@ var ye = "puzzmo_sim_api_mode", be = "http://localhost:8911", xe = "https://api.
1218
1236
  if (!r.ok) return !1;
1219
1237
  let i = yield r.json(), a = i.access_token || i.accessToken;
1220
1238
  if (!a) return !1;
1221
- we(a);
1239
+ ke(a);
1222
1240
  let o = i.refresh_token || i.refreshToken;
1223
- return o && Te(o), !0;
1241
+ return o && Ae(o), !0;
1224
1242
  } catch (e) {
1225
1243
  return !1;
1226
1244
  }
1227
1245
  });
1228
1246
  return function() {
1229
- return t.apply(this, arguments);
1247
+ return e.apply(this, arguments);
1230
1248
  };
1231
- }(), ke = function() {
1232
- var t = e(function* (e, t = {}) {
1233
- let n = Se() === "dev" ? be : xe, r = Z();
1249
+ }(), Pe = function() {
1250
+ var e = t(function* (e, t = {}) {
1251
+ let n = De() === "dev" ? Te : Ee, r = Y();
1234
1252
  if (!r) throw Error("Not authenticated");
1235
- if (De(r)) if (yield Oe()) {
1236
- if (r = Z(), !r) throw Error("Token refresh succeeded but no token available");
1237
- } else throw Ee(), Error("Session expired. Please log in again.");
1253
+ if (Me(r)) if (yield Ne()) {
1254
+ if (r = Y(), !r) throw Error("Token refresh succeeded but no token available");
1255
+ } else throw je(), Error("Session expired. Please log in again.");
1238
1256
  let i = yield fetch(`${n}/graphql`, {
1239
1257
  method: "POST",
1240
1258
  headers: {
@@ -1250,22 +1268,22 @@ var ye = "puzzmo_sim_api_mode", be = "http://localhost:8911", xe = "https://api.
1250
1268
  if (!i.ok) throw Error(`API request failed: ${i.statusText}`);
1251
1269
  return i.json();
1252
1270
  });
1253
- return function(e) {
1254
- return t.apply(this, arguments);
1271
+ return function(t) {
1272
+ return e.apply(this, arguments);
1255
1273
  };
1256
- }(), Ae = "\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", je = "\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", Me = (e, t) => {
1274
+ }(), Fe = "\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", Ie = "\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", Le = (e, t) => {
1257
1275
  let n = t - 1, r = Math.floor(n / 31), i = n % 31, a = [...e];
1258
1276
  for (; a.length <= r;) a.push(0);
1259
1277
  return a[r] = a[r] ^ 1 << i, a;
1260
1278
  };
1261
- const Ne = () => !!Z();
1262
- function Pe() {
1279
+ const Re = () => !!Y();
1280
+ function ze() {
1263
1281
  let n = null, r = !1, i = null, a = function() {
1264
- var t = e(function* (e) {
1282
+ var e = t(function* (e) {
1265
1283
  r = !0, i = null;
1266
1284
  try {
1267
1285
  var t;
1268
- let r = yield ke(Ae, { slug: e });
1286
+ let r = yield Pe(Fe, { slug: e });
1269
1287
  if (r.errors) {
1270
1288
  var a;
1271
1289
  i = ((a = r.errors[0]) == null ? void 0 : a.message) || "Unknown error", n = null;
@@ -1276,25 +1294,25 @@ function Pe() {
1276
1294
  r = !1;
1277
1295
  }
1278
1296
  });
1279
- return function(e) {
1280
- return t.apply(this, arguments);
1297
+ return function(t) {
1298
+ return e.apply(this, arguments);
1281
1299
  };
1282
1300
  }(), o = function() {
1283
- var r = e(function* (e) {
1301
+ var r = t(function* (t) {
1284
1302
  if (!n) return;
1285
- let r = Me(n.featuresArr, e);
1303
+ let r = Le(n.featuresArr, t);
1286
1304
  try {
1287
1305
  var i;
1288
- let e = yield ke(je, {
1306
+ let t = yield Pe(Ie, {
1289
1307
  gameSlug: n.slug,
1290
1308
  input: { featuresArr: r }
1291
1309
  });
1292
- if (e.errors) {
1310
+ if (t.errors) {
1293
1311
  var a;
1294
- console.error("Failed to toggle feature:", (a = e.errors[0]) == null ? void 0 : a.message);
1295
- } else (i = e.data) != null && i.updateGame && (n = t(t({}, n), {}, {
1296
- featuresArr: e.data.updateGame.featuresArr,
1297
- gameFeatures: e.data.updateGame.gameFeatures
1312
+ console.error("Failed to toggle feature:", (a = t.errors[0]) == null ? void 0 : a.message);
1313
+ } else (i = t.data) != null && i.updateGame && (n = e(e({}, n), {}, {
1314
+ featuresArr: t.data.updateGame.featuresArr,
1315
+ gameFeatures: t.data.updateGame.gameFeatures
1298
1316
  }));
1299
1317
  } catch (e) {
1300
1318
  console.error("Failed to toggle feature:", e);
@@ -1333,7 +1351,7 @@ function Pe() {
1333
1351
  id: "features",
1334
1352
  label: "Features",
1335
1353
  render() {
1336
- return Ne() ? `
1354
+ return Re() ? `
1337
1355
  <div class="features-view-container">
1338
1356
  <div class="simulator-section">
1339
1357
  <div class="simulator-section-title">Game Features</div>
@@ -1349,32 +1367,32 @@ function Pe() {
1349
1367
  </div>
1350
1368
  ` : "\n <div class=\"features-view-container\">\n <div class=\"simulator-section\">\n <div class=\"simulator-section-title\">Game Features</div>\n <div class=\"features-auth-required\">\n <p>You must be logged in to view and edit game features.</p>\n <p>Go to the <strong>Auth</strong> tab to log in with your Puzzmo account.</p>\n </div>\n </div>\n </div>\n ";
1351
1369
  },
1352
- bind(t) {
1353
- let r = t.getElement("#features-load-btn"), i = t.getElement("#features-game-slug"), c = t.getElement("#features-content"), l = () => {
1370
+ bind(e) {
1371
+ let r = e.getElement("#features-load-btn"), i = e.getElement("#features-game-slug"), c = e.getElement("#features-content"), l = () => {
1354
1372
  c && (c.innerHTML = s(), u());
1355
1373
  }, u = () => {
1356
1374
  var n;
1357
- let r = (n = t.getElement("#features-content")) == null ? void 0 : n.querySelectorAll(".feature-item");
1358
- r == null || r.forEach((t) => {
1359
- t.addEventListener("click", e(function* () {
1360
- let e = parseInt(t.getAttribute("data-feature-id") || "0");
1361
- e > 0 && (t.classList.add("updating"), yield o(e), l());
1375
+ let r = (n = e.getElement("#features-content")) == null ? void 0 : n.querySelectorAll(".feature-item");
1376
+ r == null || r.forEach((e) => {
1377
+ e.addEventListener("click", t(function* () {
1378
+ let t = parseInt(e.getAttribute("data-feature-id") || "0");
1379
+ t > 0 && (e.classList.add("updating"), yield o(t), l());
1362
1380
  }));
1363
1381
  });
1364
1382
  }, d = function() {
1365
- var t = e(function* (e) {
1383
+ var e = t(function* (e) {
1366
1384
  e && (r && (r.disabled = !0, r.textContent = "Loading..."), yield a(e), l(), r && (r.disabled = !1, r.textContent = "Load"));
1367
1385
  });
1368
- return function(e) {
1369
- return t.apply(this, arguments);
1386
+ return function(t) {
1387
+ return e.apply(this, arguments);
1370
1388
  };
1371
1389
  }();
1372
- r == null || r.addEventListener("click", e(function* () {
1390
+ r == null || r.addEventListener("click", t(function* () {
1373
1391
  let e = i == null ? void 0 : i.value.trim();
1374
1392
  e && (yield d(e));
1375
1393
  })), i == null || i.addEventListener("keypress", (e) => {
1376
1394
  e.key === "Enter" && (r == null || r.click());
1377
- }), console.log("[FeaturesView] bind called, ctx.gameSlug:", t.gameSlug, "slugInput:", i), t.gameSlug && i && (i.value = t.gameSlug, Ne() && !n && d(t.gameSlug)), u();
1395
+ }), console.log("[FeaturesView] bind called, ctx.gameSlug:", e.gameSlug, "slugInput:", i), e.gameSlug && i && (i.value = e.gameSlug, Re() && !n && d(e.gameSlug)), u();
1378
1396
  },
1379
1397
  onActivate(e) {
1380
1398
  let t = e.getElement("#simulator-tab-features");
@@ -1383,7 +1401,7 @@ function Pe() {
1383
1401
  };
1384
1402
  }
1385
1403
  /** Renders a single keyboard key as an HTML button string */
1386
- var Fe = (e, t) => {
1404
+ var Be = (e, t) => {
1387
1405
  var n, r;
1388
1406
  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);
1389
1407
  return `<button class="${[
@@ -1394,9 +1412,9 @@ var Fe = (e, t) => {
1394
1412
  c ? "l" : "",
1395
1413
  l ? "grow" : ""
1396
1414
  ].filter(Boolean).join(" ")}" data-key="${e}" ${a ? "disabled" : ""}>${i}</button>`;
1397
- }, Ie = (e) => `<div class="sim-kb">${e.layout.filter((e) => e != null).map((t) => `<div class="sim-kb-row">${[...t].map((t) => Fe(t, e)).join("")}</div>`).join("")}</div>`;
1398
- function Le() {
1399
- let e = null, t = () => e ? Ie(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>";
1415
+ }, Ve = (e) => `<div class="sim-kb">${e.layout.filter((e) => e != null).map((t) => `<div class="sim-kb-row">${[...t].map((t) => Be(t, e)).join("")}</div>`).join("")}</div>`;
1416
+ function He() {
1417
+ let e = null, t = () => e ? Ve(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>";
1400
1418
  return {
1401
1419
  id: "kbd",
1402
1420
  label: "Kbd",
@@ -1410,19 +1428,19 @@ function Le() {
1410
1428
  `;
1411
1429
  },
1412
1430
  bind(e) {
1413
- Q(e);
1431
+ X(e);
1414
1432
  },
1415
1433
  onMessage(n, r, i) {
1416
1434
  var a;
1417
1435
  if (n !== "KEYBOARD_UPDATE_CONFIG") return;
1418
1436
  e = !(!(r == null || (a = r.layout) == null) && a.length) || r.layout.every((e) => !e) ? null : r;
1419
1437
  let o = i.getElement("#sim-kb-content");
1420
- o && (o.innerHTML = t(), Q(i)), i.updateBadge("kbd", void 0);
1438
+ o && (o.innerHTML = t(), X(i)), i.updateBadge("kbd", void 0);
1421
1439
  }
1422
1440
  };
1423
1441
  }
1424
1442
  /** Attach click handlers to all rendered keys */
1425
- function Q(e) {
1443
+ function X(e) {
1426
1444
  var t;
1427
1445
  let n = (t = e.getElement("#sim-kb-content")) == null ? void 0 : t.querySelectorAll(".sim-kb-key");
1428
1446
  n == null || n.forEach((t) => {
@@ -1432,6 +1450,120 @@ function Q(e) {
1432
1450
  });
1433
1451
  });
1434
1452
  }
1453
+ /**
1454
+ * Settings tab — renders the settings UI the game registered via INITIALIZE_SETTINGS, lets you
1455
+ * change values (persisted to localStorage and pushed to the game as SETTINGS_UPDATE, matching the
1456
+ * production host) and reflects UPDATE_SETTINGS_FROM_EMBED writes coming from the game.
1457
+ */
1458
+ function Ue() {
1459
+ let t = (e) => {
1460
+ 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>`;
1462
+ }, n = (e) => {
1463
+ let n = e.getElement("#sim-settings-content");
1464
+ n && (n.innerHTML = t(e), i(e));
1465
+ }, r = (e) => {
1466
+ d(e.state.gameSettings), e.sendToGame("SETTINGS_UPDATE", e.state.gameSettings);
1467
+ }, i = (t) => {
1468
+ var i;
1469
+ let a = t.getElement("#sim-settings-content");
1470
+ a && (a.querySelectorAll("[data-setting]").forEach((n) => {
1471
+ let i = n.getAttribute("data-setting"), a = n.getAttribute("data-setting-type");
1472
+ n.addEventListener("change", () => {
1473
+ let o;
1474
+ o = n instanceof HTMLInputElement && n.type === "checkbox" ? n.checked : a === "number" ? Number(n.value) : n.value, t.state.gameSettings = e(e({}, t.state.gameSettings), {}, { [i]: o }), r(t);
1475
+ });
1476
+ }), (i = a.querySelector("#sim-settings-reset")) == null || i.addEventListener("click", () => {
1477
+ var e;
1478
+ f(), t.state.gameSettings = Ge((e = t.state.settingsComponents) == null ? [] : e), r(t), n(t);
1479
+ }));
1480
+ };
1481
+ return {
1482
+ id: "settings",
1483
+ label: "Set",
1484
+ render() {
1485
+ return "\n <div class=\"settings-view-container\">\n <div id=\"sim-settings-content\"></div>\n </div>\n ";
1486
+ },
1487
+ bind(e) {
1488
+ n(e);
1489
+ },
1490
+ onMessage(t, r, i) {
1491
+ if (t === "INITIALIZE_SETTINGS") {
1492
+ var a;
1493
+ 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);
1494
+ return;
1495
+ }
1496
+ 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));
1497
+ }
1498
+ };
1499
+ }
1500
+ /** Renders a single settings UI component as HTML, reading its current value from `settings` */
1501
+ function We(e, t) {
1502
+ switch (e.type) {
1503
+ case "title": return `<div class="sim-settings-heading">${Q(e.value)}</div>`;
1504
+ case "subtitle": return `<div class="sim-settings-subheading">${Q(e.value)}</div>`;
1505
+ case "paragraph": return `<p class="sim-settings-paragraph">${Q(e.value)}</p>`;
1506
+ case "separator": return "<div class=\"simulator-divider\"></div>";
1507
+ case "split": return `<div class="sim-settings-split">${e.content.map((e) => We(e, t)).join("")}</div>`;
1508
+ case "boolean": {
1509
+ var n;
1510
+ let r = ((n = t[e.name]) == null ? e.defaultValue : n) ? "checked" : "", i = e.subtitle ? `<div class="sim-settings-subtitle">${Q(e.subtitle)}</div>` : "";
1511
+ return `
1512
+ <div class="simulator-field">
1513
+ <label class="sim-settings-row">
1514
+ <input type="checkbox" data-setting="${e.name}" ${r} />
1515
+ <span class="simulator-label">${Q(e.title)}</span>
1516
+ </label>
1517
+ ${i}
1518
+ </div>`;
1519
+ }
1520
+ case "enum": {
1521
+ var r;
1522
+ let n = (r = t[e.name]) == null ? e.defaultValue : r, i = e.values.map((t, r) => {
1523
+ var i;
1524
+ return `<option value="${Q(t)}" ${t === n ? "selected" : ""}>${Q((i = e.displays[r]) == null ? t : i)}</option>`;
1525
+ }).join("");
1526
+ return `
1527
+ <div class="simulator-field">
1528
+ ${Z(e)}
1529
+ <select class="simulator-select" data-setting="${e.name}">${i}</select>
1530
+ </div>`;
1531
+ }
1532
+ case "number": {
1533
+ var i;
1534
+ let n = (i = t[e.name]) == null ? e.defaultValue : i, r = e.values.map((e) => `<option value="${e}" ${e === n ? "selected" : ""}>${e}</option>`).join("");
1535
+ return `
1536
+ <div class="simulator-field">
1537
+ ${Z(e)}
1538
+ <select class="simulator-select" data-setting="${e.name}" data-setting-type="number">${r}</select>
1539
+ </div>`;
1540
+ }
1541
+ case "text": {
1542
+ var a, o;
1543
+ let n = String((a = (o = t[e.name]) == null ? e.defaultValue : o) == null ? "" : a), r = e.textarea ? `<textarea class="simulator-textarea" data-setting="${e.name}">${Q(n)}</textarea>` : `<input class="simulator-input" type="text" data-setting="${e.name}" value="${Q(n)}" />`;
1544
+ return `
1545
+ <div class="simulator-field">
1546
+ ${Z(e)}
1547
+ ${r}
1548
+ </div>`;
1549
+ }
1550
+ default: return `<div class="sim-settings-unsupported">Unsupported component type: ${Q(e.type)}</div>`;
1551
+ }
1552
+ }
1553
+ /** Title + optional subtitle markup for a value-producing component */
1554
+ function Z(e) {
1555
+ let t = e.subtitle ? `<div class="sim-settings-subtitle">${Q(e.subtitle)}</div>` : "";
1556
+ return `<span class="simulator-label">${Q(e.title)}</span>${t}`;
1557
+ }
1558
+ /** Collects name → defaultValue pairs from components, recursing into split groups */
1559
+ function Ge(e) {
1560
+ let t = {};
1561
+ for (let n of e) n.type === "split" ? Object.assign(t, Ge(n.content)) : "name" in n && (t[n.name] = n.defaultValue);
1562
+ return t;
1563
+ }
1564
+ function Q(e) {
1565
+ return e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
1566
+ }
1435
1567
  var $ = null;
1436
1568
  /**
1437
1569
  * Simulator - A development UI for testing games with the Puzzmo Proto SDK.
@@ -1470,24 +1602,25 @@ var $ = null;
1470
1602
  * Fixtures are loaded as raw strings and passed to the game verbatim (any text format works; the game parses it).
1471
1603
  * This will show dropdowns in the Ctrl tab to select category and puzzle.
1472
1604
  */
1473
- function Re(t = {}) {
1605
+ function Ke(e = {}) {
1474
1606
  var n, r;
1475
1607
  if (console.log("[Simulator] createSimulator called with config:", {
1476
- slug: t.slug,
1477
- hasFixtures: !!t.fixtures
1478
- }), $) return t.fixtures && (console.log("[Simulator] Instance already exists, updating fixtures"), $.updateFixtures(t.fixtures)), $;
1479
- let i = (n = t.autoStart) == null ? !0 : n, a = t.fixtures ? v(t.fixtures) : null, o = a ? Array.from(a.keys()).sort() : [], s = ae(), c = ce(), f = [
1480
- re(),
1481
- ie(),
1482
- s,
1608
+ slug: e.slug,
1609
+ hasFixtures: !!e.fixtures
1610
+ }), $) return e.fixtures && (console.log("[Simulator] Instance already exists, updating fixtures"), $.updateFixtures(e.fixtures)), $;
1611
+ let i = (n = e.autoStart) == null ? !0 : n, a = e.fixtures ? ie(e.fixtures) : null, o = a ? Array.from(a.keys()).sort() : [], s = se(), c = ue(), l = [
1612
+ ae(),
1483
1613
  oe(),
1484
- se(),
1485
- c,
1614
+ s,
1615
+ ce(),
1486
1616
  le(),
1487
- ve(),
1488
- Pe(),
1489
- Le()
1490
- ], p = f.map((e) => e.id), m = l(t, o, p), h = {
1617
+ c,
1618
+ de(),
1619
+ Ce(),
1620
+ ze(),
1621
+ He(),
1622
+ Ue()
1623
+ ], d = l.map((e) => e.id), f = u(e, o, d), h = {
1491
1624
  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>",
1492
1625
  play: "<svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"currentColor\"><polygon points=\"2,1 9,5 2,9\"/></svg>",
1493
1626
  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>",
@@ -2664,8 +2797,75 @@ function Re(t = {}) {
2664
2797
  opacity: 0.3;
2665
2798
  cursor: default;
2666
2799
  }
2800
+ /* Settings view styles */
2801
+ .settings-view-container {
2802
+ display: flex;
2803
+ flex-direction: column;
2804
+ height: 100%;
2805
+ overflow-y: auto;
2806
+ }
2807
+ .sim-settings-empty {
2808
+ color: var(--sim-text-dim);
2809
+ font-size: 10px;
2810
+ text-align: center;
2811
+ padding: 20px;
2812
+ line-height: 1.5;
2813
+ }
2814
+ .sim-settings-heading {
2815
+ color: var(--sim-text);
2816
+ font-size: 11px;
2817
+ font-weight: bold;
2818
+ text-transform: uppercase;
2819
+ letter-spacing: 1px;
2820
+ margin: 6px 0 4px;
2821
+ }
2822
+ .sim-settings-subheading {
2823
+ color: var(--sim-text);
2824
+ font-size: 10px;
2825
+ font-weight: bold;
2826
+ margin: 4px 0 2px;
2827
+ }
2828
+ .sim-settings-paragraph {
2829
+ color: var(--sim-text-dim);
2830
+ font-size: 10px;
2831
+ margin: 2px 0 6px;
2832
+ line-height: 1.4;
2833
+ }
2834
+ .sim-settings-subtitle {
2835
+ color: var(--sim-text-dim);
2836
+ font-size: 9px;
2837
+ margin: -2px 0 3px;
2838
+ line-height: 1.3;
2839
+ }
2840
+ .sim-settings-row {
2841
+ display: flex;
2842
+ align-items: baseline;
2843
+ gap: 6px;
2844
+ cursor: pointer;
2845
+ }
2846
+ .sim-settings-row .simulator-label {
2847
+ margin-bottom: 0;
2848
+ }
2849
+ .sim-settings-split {
2850
+ display: flex;
2851
+ gap: 8px;
2852
+ }
2853
+ .sim-settings-split > * {
2854
+ flex: 1;
2855
+ }
2856
+ .sim-settings-unsupported {
2857
+ color: var(--sim-text-dim);
2858
+ font-size: 9px;
2859
+ font-style: italic;
2860
+ margin: 4px 0;
2861
+ }
2862
+ .sim-settings-actions {
2863
+ margin-top: 8px;
2864
+ padding-top: 8px;
2865
+ border-top: 2px solid var(--sim-border);
2866
+ }
2667
2867
  </style>
2668
- <div id="simulator-panel" class="${m.isCollapsed ? "collapsed" : ""}">
2868
+ <div id="simulator-panel" class="${f.isCollapsed ? "collapsed" : ""}">
2669
2869
  <div id="simulator-header">
2670
2870
  <span id="simulator-title">PUZZMO SIMULATOR</span>
2671
2871
  <span class="header-sep">|</span>
@@ -2686,101 +2886,101 @@ function Re(t = {}) {
2686
2886
  </div>
2687
2887
  <div id="simulator-body">
2688
2888
  <div id="simulator-tabs">
2689
- ${f.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("")}
2889
+ ${l.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("")}
2690
2890
  </div>
2691
2891
  <div id="simulator-content" class="hidden">
2692
- ${f.map((e) => `<div id="simulator-tab-${e.id}" class="simulator-tab-content">${e.render()}</div>`).join("")}
2892
+ ${l.map((e) => `<div id="simulator-tab-${e.id}" class="simulator-tab-content">${e.render()}</div>`).join("")}
2693
2893
  </div>
2694
2894
  </div>
2695
2895
  </div>
2696
2896
  `, document.body.appendChild(g);
2697
- let _ = g.querySelector("#simulator-panel"), y = g.querySelector("#simulator-header"), b = g.querySelector("#simulator-header-indicator"), x = g.querySelector("#simulator-header-status-text"), S = g.querySelector("#simulator-header-pause"), C = g.querySelector("#simulator-header-retry"), w = g.querySelector("#simulator-header-settings"), T = g.querySelector("#simulator-toggle"), E = g.querySelector("#simulator-timer"), D = g.querySelector("#simulator-tabs"), O = g.querySelector("#simulator-content"), k = (e) => g.querySelector(e), A = (e) => {
2698
- S.innerHTML = e ? h.play : h.pause, S.title = e ? "Resume" : "Pause";
2699
- }, j = (e, t) => {
2700
- let n = k("#simulator-status .text"), r = k("#simulator-status .indicator"), i = t === "complete" ? "✓" : "";
2701
- n && (n.textContent = e), r && (r.className = `indicator ${t}`, r.textContent = i), b.className = t, b.textContent = i, x.textContent = e;
2702
- }, M = (e, t) => {
2703
- t && t !== "0" ? E.innerHTML = `${e}<span class="penalty">+${t}</span>` : E.textContent = e;
2704
- }, N = (e) => {
2897
+ let _ = g.querySelector("#simulator-panel"), ee = g.querySelector("#simulator-header"), v = g.querySelector("#simulator-header-indicator"), y = g.querySelector("#simulator-header-status-text"), b = g.querySelector("#simulator-header-pause"), x = g.querySelector("#simulator-header-retry"), S = g.querySelector("#simulator-header-settings"), C = g.querySelector("#simulator-toggle"), w = g.querySelector("#simulator-timer"), T = g.querySelector("#simulator-tabs"), E = g.querySelector("#simulator-content"), D = (e) => g.querySelector(e), O = (e) => {
2898
+ b.innerHTML = e ? h.play : h.pause, b.title = e ? "Resume" : "Pause";
2899
+ }, k = (e, t) => {
2900
+ let n = D("#simulator-status .text"), r = D("#simulator-status .indicator"), i = t === "complete" ? "✓" : "";
2901
+ n && (n.textContent = e), r && (r.className = `indicator ${t}`, r.textContent = i), v.className = t, v.textContent = i, y.textContent = e;
2902
+ }, A = (e, t) => {
2903
+ t && t !== "0" ? w.innerHTML = `${e}<span class="penalty">+${t}</span>` : w.textContent = e;
2904
+ }, j = (e) => {
2705
2905
  var t;
2706
- m.activeTab = e, O.classList.remove("hidden"), d(e), D.querySelectorAll(".simulator-tab").forEach((t) => {
2906
+ f.activeTab = e, E.classList.remove("hidden"), m(e), T.querySelectorAll(".simulator-tab").forEach((t) => {
2707
2907
  t.classList.toggle("active", t.getAttribute("data-tab") === e);
2708
2908
  }), g.querySelectorAll(".simulator-tab-content").forEach((t) => {
2709
2909
  t.classList.toggle("active", t.id === `simulator-tab-${e}`);
2710
- }), w.classList.toggle("active", e === "auth");
2711
- let n = f.find((t) => t.id === e);
2712
- n == null || (t = n.onActivate) == null || t.call(n, B);
2713
- }, P = (e) => {
2714
- m.isCollapsed = e, _.classList.toggle("collapsed", e), u(e), e ? (O.classList.add("hidden"), D.querySelectorAll(".simulator-tab").forEach((e) => e.classList.remove("active"))) : N(m.activeTab);
2715
- }, F = () => {
2716
- c.updatePreview(B);
2717
- }, I = function() {
2718
- var t = e(function* () {
2910
+ }), S.classList.toggle("active", e === "auth");
2911
+ let n = l.find((t) => t.id === e);
2912
+ n == null || (t = n.onActivate) == null || t.call(n, R);
2913
+ }, M = (e) => {
2914
+ f.isCollapsed = e, _.classList.toggle("collapsed", e), p(e), e ? (E.classList.add("hidden"), T.querySelectorAll(".simulator-tab").forEach((e) => e.classList.remove("active"))) : j(f.activeTab);
2915
+ }, N = () => {
2916
+ c.updatePreview(R);
2917
+ }, P = function() {
2918
+ var e = t(function* () {
2719
2919
  var e, t;
2720
- if (m.puzzleData) return m.puzzleData;
2920
+ if (f.puzzleData) return f.puzzleData;
2721
2921
  if (!a || a.size === 0) throw Error("No fixtures configured. Add puzzle fixture files (.json or .toml) to a fixtures directory and pass fixturesGlob to the simulator.");
2722
- let n = (e = m.selectedCategory) == null ? o[0] : e, r = n ? a.get(n) : void 0;
2922
+ let n = (e = f.selectedCategory) == null ? o[0] : e, r = n ? a.get(n) : void 0;
2723
2923
  if (!r || r.size === 0) throw Error(`No puzzles found in fixture category "${n}"`);
2724
- let i = (t = m.selectedPuzzle) == null ? r.keys().next().value : t, s = i ? r.get(i) : void 0;
2924
+ let i = (t = f.selectedPuzzle) == null ? r.keys().next().value : t, s = i ? r.get(i) : void 0;
2725
2925
  if (!s) throw Error(`Puzzle "${i}" not found in category "${n}"`);
2726
- m.puzzleData = s, console.log("Simulator: Puzzle loaded from fixtures", {
2926
+ f.puzzleData = s, console.log("Simulator: Puzzle loaded from fixtures", {
2727
2927
  category: n,
2728
2928
  puzzle: i
2729
- }), m.originalPuzzle = s;
2730
- let c = k("#simulator-puzzle");
2731
- return c && (c.value = m.originalPuzzle), m.activeTab === "thumb" && F(), m.puzzleData;
2929
+ }), f.originalPuzzle = s;
2930
+ let c = D("#simulator-puzzle");
2931
+ return c && (c.value = f.originalPuzzle), f.activeTab === "thumb" && N(), f.puzzleData;
2732
2932
  });
2733
2933
  return function() {
2734
- return t.apply(this, arguments);
2934
+ return e.apply(this, arguments);
2735
2935
  };
2736
- }(), L = ee((e) => {
2737
- s.addLogEntry(e, B);
2738
- }), R = (e, t) => {
2739
- te(e, t, L);
2740
- }, z = (e, t) => {
2936
+ }(), F = te((e) => {
2937
+ s.addLogEntry(e, R);
2938
+ }), I = (e, t) => {
2939
+ ne(e, t, F);
2940
+ }, L = (e, t) => {
2741
2941
  let n = g.querySelector(`[data-badge="${e}"]`);
2742
2942
  n && (n.textContent = t && t > 0 ? String(t) : "");
2743
- }, B = {
2744
- state: m,
2745
- getElement: k,
2746
- sendToGame: R,
2747
- logMessage: L.log,
2748
- loadPuzzle: I,
2749
- updateStatus: j,
2750
- updateTimer: M,
2751
- setCollapsed: P,
2752
- switchTab: N,
2753
- updateThumbnail: F,
2754
- updateBadge: z,
2943
+ }, R = {
2944
+ state: f,
2945
+ getElement: D,
2946
+ sendToGame: I,
2947
+ logMessage: F.log,
2948
+ loadPuzzle: P,
2949
+ updateStatus: k,
2950
+ updateTimer: A,
2951
+ setCollapsed: M,
2952
+ switchTab: j,
2953
+ updateThumbnail: N,
2954
+ updateBadge: L,
2755
2955
  fixtures: a,
2756
2956
  fixtureCategories: o,
2757
- gameSlug: (r = t.slug) == null ? null : r
2957
+ gameSlug: (r = e.slug) == null ? null : r
2758
2958
  };
2759
- console.log("[Simulator] Context created with gameSlug:", B.gameSlug), f.forEach((e) => e.bind(B)), D.querySelectorAll(".simulator-tab").forEach((e) => {
2959
+ console.log("[Simulator] Context created with gameSlug:", R.gameSlug), l.forEach((e) => e.bind(R)), T.querySelectorAll(".simulator-tab").forEach((e) => {
2760
2960
  e.addEventListener("click", () => {
2761
2961
  let t = e.getAttribute("data-tab");
2762
- N(t), z(t, 0);
2962
+ j(t), L(t, 0);
2763
2963
  });
2764
- }), T.addEventListener("click", (e) => {
2765
- e.stopPropagation(), P(!0);
2766
- }), S.addEventListener("click", (e) => {
2767
- e.stopPropagation(), m.isPaused ? (R("RESUME_GAME", {}), m.isPaused = !1, A(!1), j("Running", "ready")) : (R("PAUSE_GAME", {}), m.isPaused = !0, A(!0), j("Paused", "paused"));
2768
- let t = k("#simulator-pause");
2769
- t && (t.textContent = m.isPaused ? "Resume" : "Pause");
2770
2964
  }), C.addEventListener("click", (e) => {
2771
- e.stopPropagation(), R("RETRY_PUZZLE", {}), m.hasStarted = !1, m.isPaused = !1, A(!1), S.disabled = !0, j("Ready to retry", "ready");
2772
- let t = k("#simulator-pause"), n = k("#simulator-start");
2965
+ e.stopPropagation(), M(!0);
2966
+ }), b.addEventListener("click", (e) => {
2967
+ e.stopPropagation(), f.isPaused ? (I("RESUME_GAME", {}), f.isPaused = !1, O(!1), k("Running", "ready")) : (I("PAUSE_GAME", {}), f.isPaused = !0, O(!0), k("Paused", "paused"));
2968
+ let t = D("#simulator-pause");
2969
+ t && (t.textContent = f.isPaused ? "Resume" : "Pause");
2970
+ }), x.addEventListener("click", (e) => {
2971
+ e.stopPropagation(), I("RETRY_PUZZLE", {}), f.hasStarted = !1, f.isPaused = !1, O(!1), b.disabled = !0, k("Ready to retry", "ready");
2972
+ let t = D("#simulator-pause"), n = D("#simulator-start");
2773
2973
  t && (t.disabled = !0, t.textContent = "Pause"), n && (n.textContent = "Start");
2774
- }), w.addEventListener("click", (e) => {
2775
- e.stopPropagation(), m.isCollapsed && P(!1), N("auth");
2776
- }), y.addEventListener("click", (e) => {
2777
- m.isCollapsed && e.target !== T && P(!1);
2778
- }), m.isCollapsed || N(m.activeTab);
2779
- let V = new URLSearchParams(window.location.search);
2780
- (V.has("code") || V.has("error")) && (P(!1), N("auth"));
2781
- let H = (e) => ({
2974
+ }), S.addEventListener("click", (e) => {
2975
+ e.stopPropagation(), f.isCollapsed && M(!1), j("auth");
2976
+ }), ee.addEventListener("click", (e) => {
2977
+ f.isCollapsed && e.target !== C && M(!1);
2978
+ }), f.isCollapsed || j(f.activeTab);
2979
+ let z = new URLSearchParams(window.location.search);
2980
+ (z.has("code") || z.has("error")) && (M(!1), j("auth"));
2981
+ let fe = (e) => ({
2782
2982
  userState: {
2783
- gameSettings: {},
2983
+ gameSettings: f.gameSettings,
2784
2984
  id: "simulator-user",
2785
2985
  ownerID: "simulator-owner"
2786
2986
  },
@@ -2795,7 +2995,7 @@ function Re(t = {}) {
2795
2995
  },
2796
2996
  startOrFindGameplay: { gamePlayed: {
2797
2997
  additionalTimeAddedSecs: 0,
2798
- boardState: m.currentInputStr,
2998
+ boardState: f.currentInputStr,
2799
2999
  combinedTimeSecs: 0,
2800
3000
  completed: !1,
2801
3001
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -2817,53 +3017,49 @@ function Re(t = {}) {
2817
3017
  mostRecentDaily: null
2818
3018
  }
2819
3019
  } },
2820
- theme: m.selectedTheme,
3020
+ theme: f.selectedTheme,
2821
3021
  hostContext: [{
2822
3022
  type: "app",
2823
3023
  layout: "desktop",
2824
3024
  host: null
2825
3025
  }],
2826
3026
  appRuntimeContract: "1.0"
2827
- }), U = function() {
2828
- var t = e(function* () {
2829
- j("Loading puzzle...", "waiting");
3027
+ }), B = function() {
3028
+ var e = t(function* () {
3029
+ k("Loading puzzle...", "waiting");
2830
3030
  try {
2831
- let e = H(yield I());
2832
- j("Sending READY_DATA...", "waiting"), R("READY_DATA", e), j("Waiting for game to load...", "waiting");
3031
+ let e = fe(yield P());
3032
+ k("Sending READY_DATA...", "waiting"), I("READY_DATA", e), k("Waiting for game to load...", "waiting");
2833
3033
  } catch (e) {
2834
- j(`Error: ${e}`, "paused");
3034
+ k(`Error: ${e}`, "paused");
2835
3035
  }
2836
3036
  });
2837
3037
  return function() {
2838
- return t.apply(this, arguments);
3038
+ return e.apply(this, arguments);
2839
3039
  };
2840
- }(), W = () => {
2841
- console.log("Simulator: Game loaded, ready to start"), C.disabled = !1, f.forEach((e) => {
3040
+ }(), pe = () => {
3041
+ console.log("Simulator: Game loaded, ready to start"), x.disabled = !1, l.forEach((e) => {
2842
3042
  var t;
2843
- return (t = e.onMessage) == null ? void 0 : t.call(e, "READY_GAME_LOADED", void 0, B);
2844
- }), i && !m.hasStarted && setTimeout(() => {
2845
- let e = k("#simulator-start");
2846
- e == null || e.click(), S.disabled = !1, m.hasStarted = !0, j("Running", "ready");
3043
+ return (t = e.onMessage) == null ? void 0 : t.call(e, "READY_GAME_LOADED", void 0, R);
3044
+ }), i && !f.hasStarted && setTimeout(() => {
3045
+ let e = D("#simulator-start");
3046
+ e == null || e.click(), b.disabled = !1, f.hasStarted = !0, k("Running", "ready");
2847
3047
  }, 100);
2848
3048
  };
2849
- return ne((e, t) => {
3049
+ return re((e, t) => {
2850
3050
  var n, r;
2851
3051
  if (e === "READY") {
2852
- console.log("Simulator: Received READY from game"), U();
2853
- return;
2854
- }
2855
- if (e === "INITIALIZE_SETTINGS") {
2856
- console.log("Simulator: Game initialized settings", t);
3052
+ console.log("Simulator: Received READY from game"), B();
2857
3053
  return;
2858
3054
  }
2859
3055
  if (e === "READY_GAME_LOADED") {
2860
- W();
3056
+ pe();
2861
3057
  return;
2862
3058
  }
2863
3059
  if (e === "TIMER_TICK") {
2864
3060
  if (t != null && t.display) {
2865
3061
  let [e, n] = t.display;
2866
- M(e, n);
3062
+ A(e, n);
2867
3063
  }
2868
3064
  return;
2869
3065
  }
@@ -2872,30 +3068,30 @@ function Re(t = {}) {
2872
3068
  console.log("Simulator: Sidebar update", t);
2873
3069
  return;
2874
3070
  }
2875
- f.forEach((n) => {
3071
+ l.forEach((n) => {
2876
3072
  var r;
2877
- return (r = n.onMessage) == null ? void 0 : r.call(n, e, t, B);
3073
+ return (r = n.onMessage) == null ? void 0 : r.call(n, e, t, R);
2878
3074
  });
2879
3075
  let i = (n = t == null || (r = t.input) == null ? void 0 : r.boardState) == null ? t == null ? void 0 : t.boardState : n;
2880
- e === "UPLOAD_NEW_GAME_STATE" && i && (m.currentInputStr = i, m.activeTab === "thumb" && F(), console.log("Simulator: Game state uploaded", t)), e === "GAME_COMPLETED" && (console.log("Simulator: Game completed!", t), S.disabled = !0, m.hasStarted = !1, j("Completed!", "complete"));
2881
- }, L), console.log("Simulator initialized"), $ = {
3076
+ e === "UPLOAD_NEW_GAME_STATE" && i && (f.currentInputStr = i, f.activeTab === "thumb" && N(), console.log("Simulator: Game state uploaded", t)), e === "GAME_COMPLETED" && (console.log("Simulator: Game completed!", t), b.disabled = !0, f.hasStarted = !1, k("Completed!", "complete"));
3077
+ }, F), console.log("Simulator initialized"), $ = {
2882
3078
  updateFixtures: (e) => {
2883
- a = v(e), o = Array.from(a.keys()).sort(), B.fixtures = a, B.fixtureCategories = o;
3079
+ a = ie(e), o = Array.from(a.keys()).sort(), R.fixtures = a, R.fixtureCategories = o;
2884
3080
  let t = localStorage.getItem("simulator-fixture-category");
2885
- if (!m.selectedCategory || !o.includes(m.selectedCategory)) {
3081
+ if (!f.selectedCategory || !o.includes(f.selectedCategory)) {
2886
3082
  var n;
2887
- m.selectedCategory = t && o.includes(t) ? t : (n = o[0]) == null ? null : n;
3083
+ f.selectedCategory = t && o.includes(t) ? t : (n = o[0]) == null ? null : n;
2888
3084
  }
2889
- let r = f.find((e) => e.id === "ctrl");
2890
- r == null || r.bind(B), console.log("Simulator: Fixtures updated", {
3085
+ let r = l.find((e) => e.id === "ctrl");
3086
+ r == null || r.bind(R), console.log("Simulator: Fixtures updated", {
2891
3087
  categories: o,
2892
- selectedCategory: m.selectedCategory
3088
+ selectedCategory: f.selectedCategory
2893
3089
  });
2894
3090
  },
2895
- sendToGame: R,
2896
- loadPuzzle: I
3091
+ sendToGame: I,
3092
+ loadPuzzle: P
2897
3093
  }, $;
2898
3094
  }
2899
- export { Re as t };
3095
+ export { Ke as t };
2900
3096
 
2901
- //# sourceMappingURL=createSimulator-CWwSv8gh.js.map
3097
+ //# sourceMappingURL=createSimulator-DqF2fN_0.js.map