easter-egg-quest 1.0.17 → 1.0.19

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.
@@ -57,44 +57,30 @@ const DEFAULT_SCRIPT = {
57
57
  stage2Success: [
58
58
  "movement was the answer",
59
59
  "the second egg appears",
60
- "for those who never stop",
61
- "not stillness this time",
62
- "but life in motion"
60
+ "hold it to collect"
63
61
  ],
64
62
  // ── Stage 3: Rhythm ───────────────────────────────────────────────────
65
63
  stage3Intro: [
66
- "two truths that shouldn’t exist together",
67
64
  "the final riddle:",
68
- "I am the conversation between opposites. Every living thing knows me. You’ve been doing me your whole life without thinking."
65
+ "Every living thing knows it. You’ve been doing it your whole life without thinking."
69
66
  ],
70
67
  stage3Reactions: [
71
- "one truth alone isn’t enough",
72
- "the other alone isn’t either",
73
- "what do all living things share?",
74
- "you already know the answer",
75
- "you’ve been doing it since birth",
76
- "listen to yourself",
77
- "closer...",
78
- "can you feel it?",
79
- "the body remembers",
68
+ "move for a few seconds",
69
+ "then hold still for a moment",
70
+ "don’t rush it",
71
+ "alternate move and pause",
80
72
  "in",
81
73
  "out"
82
74
  ],
83
75
  stage3Success: [
84
76
  "rhythm was the answer",
85
- "not stopping, not rushing",
86
- "but the dance between them",
87
- "the third egg appears",
88
- "for those who breathe"
77
+ "you found the third egg"
89
78
  ],
90
79
  // ── Finale ────────────────────────────────────────────────────────────
91
80
  finale: [
92
- "you were looking for three eggs",
93
- "but you found something else",
94
- "stillness",
95
- "motion",
96
- "rhythm",
97
- "this is where life appears"
81
+ "all three eggs found",
82
+ "stillness, motion, rhythm",
83
+ "that's the whole set"
98
84
  ],
99
85
  // ── Results / Share ───────────────────────────────────────────────────
100
86
  results: [
@@ -336,8 +322,10 @@ class InputTracker {
336
322
  this._prevX = 0;
337
323
  this._prevY = 0;
338
324
  this._prevMoveTs = 0;
339
- this.STILL_THRESHOLD_MS = 400;
340
- this.MIN_PHASE_MS = 300;
325
+ this.DEFAULT_STILL_THRESHOLD_MS = 400;
326
+ this._stillThresholdMs = this.DEFAULT_STILL_THRESHOLD_MS;
327
+ this.DEFAULT_MIN_PHASE_MS = 300;
328
+ this._minPhaseMs = this.DEFAULT_MIN_PHASE_MS;
341
329
  this._stillTimer = null;
342
330
  this._handlers = [];
343
331
  this._active = false;
@@ -476,6 +464,18 @@ class InputTracker {
476
464
  this._snapshot.totalDistance = 0;
477
465
  this._snapshot.maxVelocity = 0;
478
466
  }
467
+ configurePhaseDetection(opts) {
468
+ if (typeof opts.stillThresholdMs === "number") {
469
+ this._stillThresholdMs = Math.max(250, opts.stillThresholdMs);
470
+ }
471
+ if (typeof opts.minPhaseMs === "number") {
472
+ this._minPhaseMs = Math.max(150, opts.minPhaseMs);
473
+ }
474
+ }
475
+ resetPhaseDetection() {
476
+ this._stillThresholdMs = this.DEFAULT_STILL_THRESHOLD_MS;
477
+ this._minPhaseMs = this.DEFAULT_MIN_PHASE_MS;
478
+ }
479
479
  // ─── Movement / Stillness transition logic ─────────────────────────────
480
480
  _registerMove(now) {
481
481
  this._snapshot.lastMoveTime = now;
@@ -488,7 +488,7 @@ class InputTracker {
488
488
  if (this._stillTimer) clearTimeout(this._stillTimer);
489
489
  this._stillTimer = setTimeout(() => {
490
490
  this._becomeStill();
491
- }, this.STILL_THRESHOLD_MS);
491
+ }, this._stillThresholdMs);
492
492
  }
493
493
  _becomeStill() {
494
494
  if (!this._snapshot.isMoving) return;
@@ -502,7 +502,7 @@ class InputTracker {
502
502
  }
503
503
  _completePhase(type, endTime) {
504
504
  const duration = endTime - this._currentPhaseStart;
505
- if (duration >= this.MIN_PHASE_MS) {
505
+ if (duration >= this._minPhaseMs) {
506
506
  this._phases.push({
507
507
  type,
508
508
  startTime: this._currentPhaseStart,
@@ -1317,6 +1317,7 @@ class NarrativeRenderer {
1317
1317
  this.container = null;
1318
1318
  this.currentLine = null;
1319
1319
  this.clearTimer = null;
1320
+ this.awaitingConfirm = false;
1320
1321
  this.config = config;
1321
1322
  }
1322
1323
  mount() {
@@ -1340,14 +1341,22 @@ class NarrativeRenderer {
1340
1341
  this.container.className = "eeq-narrative";
1341
1342
  this.shadow.appendChild(this.container);
1342
1343
  }
1344
+ _removeCurrentLine(immediate = false) {
1345
+ if (!this.currentLine) return;
1346
+ const prev = this.currentLine;
1347
+ this.currentLine = null;
1348
+ if (immediate) {
1349
+ prev.remove();
1350
+ return;
1351
+ }
1352
+ prev.classList.add("eeq-narrative-exit");
1353
+ setTimeout(() => prev.remove(), 750);
1354
+ }
1343
1355
  /** Show a single narrative line. Fades in, replaces any previous line. */
1344
1356
  showLine(text, className = "eeq-line") {
1345
1357
  if (!this.container) return;
1346
- if (this.currentLine) {
1347
- const prev = this.currentLine;
1348
- prev.classList.add("eeq-narrative-exit");
1349
- setTimeout(() => prev.remove(), 750);
1350
- }
1358
+ if (this.awaitingConfirm) return;
1359
+ this._removeCurrentLine(true);
1351
1360
  if (this.clearTimer) {
1352
1361
  clearTimeout(this.clearTimer);
1353
1362
  this.clearTimer = null;
@@ -1376,11 +1385,8 @@ class NarrativeRenderer {
1376
1385
  resolve();
1377
1386
  return;
1378
1387
  }
1379
- if (this.currentLine) {
1380
- const prev = this.currentLine;
1381
- prev.classList.add("eeq-narrative-exit");
1382
- setTimeout(() => prev.remove(), 750);
1383
- }
1388
+ this.awaitingConfirm = true;
1389
+ this._removeCurrentLine(true);
1384
1390
  if (this.clearTimer) {
1385
1391
  clearTimeout(this.clearTimer);
1386
1392
  this.clearTimer = null;
@@ -1392,7 +1398,10 @@ class NarrativeRenderer {
1392
1398
  const btn = document.createElement("button");
1393
1399
  btn.className = "eeq-confirm-btn";
1394
1400
  btn.textContent = "OK";
1395
- btn.addEventListener("click", () => resolve(), { once: true });
1401
+ btn.addEventListener("click", () => {
1402
+ this.awaitingConfirm = false;
1403
+ resolve();
1404
+ }, { once: true });
1396
1405
  line.appendChild(btn);
1397
1406
  requestAnimationFrame(() => {
1398
1407
  requestAnimationFrame(() => {
@@ -1414,22 +1423,19 @@ class NarrativeRenderer {
1414
1423
  this.showLine(text, "eeq-line eeq-celebration");
1415
1424
  }
1416
1425
  /** Clear current narrative text. */
1417
- clear() {
1426
+ clear(force = false) {
1427
+ if (this.awaitingConfirm && !force) return;
1418
1428
  if (this.clearTimer) {
1419
1429
  clearTimeout(this.clearTimer);
1420
1430
  this.clearTimer = null;
1421
1431
  }
1422
- if (this.currentLine) {
1423
- this.currentLine.classList.add("eeq-narrative-exit");
1424
- const ref = this.currentLine;
1425
- setTimeout(() => ref.remove(), 750);
1426
- this.currentLine = null;
1427
- }
1432
+ this._removeCurrentLine(force);
1433
+ this.awaitingConfirm = false;
1428
1434
  }
1429
1435
  /** Remove all DOM. */
1430
1436
  destroy() {
1431
1437
  var _a2;
1432
- this.clear();
1438
+ this.clear(true);
1433
1439
  (_a2 = this.host) == null ? void 0 : _a2.remove();
1434
1440
  this.host = null;
1435
1441
  this.shadow = null;
@@ -3724,16 +3730,16 @@ const _ResultsRenderer = class _ResultsRenderer {
3724
3730
  inner.appendChild(badgesDiv);
3725
3731
  const invite = document.createElement("div");
3726
3732
  invite.className = "eeq-share-invite";
3727
- invite.textContent = "share your result with friends 🥚";
3733
+ invite.textContent = "share or copy your result";
3728
3734
  inner.appendChild(invite);
3729
3735
  const actions = document.createElement("div");
3730
3736
  actions.className = "eeq-results-actions";
3731
3737
  const shareBtn = document.createElement("button");
3732
3738
  shareBtn.className = "eeq-btn eeq-btn-share";
3733
- shareBtn.title = "share result";
3739
+ shareBtn.title = "share or copy result";
3734
3740
  shareBtn.innerHTML = '<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M4.5 10.5a2 2 0 1 1 0-4 2 2 0 0 1 0 4zm7-4a2 2 0 1 1 0-4 2 2 0 0 1 0 4zm0 8a2 2 0 1 1 0-4 2 2 0 0 1 0 4z" stroke="currentColor" stroke-width="1.2"/><path d="M6.3 9.2l3.4 1.6M6.3 7.8l3.4-1.6" stroke="currentColor" stroke-width="1.2"/></svg>';
3735
3741
  const shareLabel = document.createElement("span");
3736
- shareLabel.textContent = "share";
3742
+ shareLabel.textContent = "share / copy";
3737
3743
  shareBtn.appendChild(shareLabel);
3738
3744
  actions.appendChild(shareBtn);
3739
3745
  const finishBtn = document.createElement("button");
@@ -3967,6 +3973,7 @@ const _ResultsRenderer = class _ResultsRenderer {
3967
3973
  _copyShareImage(s) {
3968
3974
  var _a2;
3969
3975
  const canvas = this._renderCard(s);
3976
+ const shareText = this._buildShareText(s);
3970
3977
  const dataUrl = canvas.toDataURL("image/png");
3971
3978
  const byteString = atob(dataUrl.split(",")[1]);
3972
3979
  const ab = new ArrayBuffer(byteString.length);
@@ -3980,17 +3987,35 @@ const _ResultsRenderer = class _ResultsRenderer {
3980
3987
  navigator.share({
3981
3988
  files: [file],
3982
3989
  title: "Easter Egg Quest",
3983
- text: `«${s.behaviorProfile.title}»`
3990
+ text: shareText
3984
3991
  }).catch(() => {
3985
3992
  });
3986
3993
  return;
3987
3994
  }
3995
+ navigator.share({
3996
+ title: "Easter Egg Quest",
3997
+ text: shareText
3998
+ }).catch(() => {
3999
+ });
4000
+ return;
3988
4001
  }
3989
4002
  if (navigator.clipboard && typeof ClipboardItem !== "undefined") {
3990
4003
  navigator.clipboard.write([
3991
4004
  new ClipboardItem({ "image/png": blob })
3992
4005
  ]).then(() => {
3993
- this._flashButton(".eeq-btn-share", "copied!");
4006
+ this._flashButton(".eeq-btn-share", "image copied");
4007
+ }).catch(() => {
4008
+ this._copyShareText(shareText, blob);
4009
+ });
4010
+ return;
4011
+ }
4012
+ this._copyShareText(shareText, blob);
4013
+ }
4014
+ _copyShareText(text, blob) {
4015
+ var _a2;
4016
+ if ((_a2 = navigator.clipboard) == null ? void 0 : _a2.writeText) {
4017
+ navigator.clipboard.writeText(text).then(() => {
4018
+ this._flashButton(".eeq-btn-share", "text copied");
3994
4019
  }).catch(() => {
3995
4020
  this._downloadBlob(blob);
3996
4021
  });
@@ -3998,6 +4023,11 @@ const _ResultsRenderer = class _ResultsRenderer {
3998
4023
  }
3999
4024
  this._downloadBlob(blob);
4000
4025
  }
4026
+ _buildShareText(s) {
4027
+ const time = formatTime(s.totalTime);
4028
+ const eggs = `${s.eggsFound}/3 eggs`;
4029
+ return `Easter Egg Quest: ${s.behaviorProfile.title} • ${time} • ${eggs}`;
4030
+ }
4001
4031
  _downloadBlob(blob) {
4002
4032
  const url = URL.createObjectURL(blob);
4003
4033
  const a = document.createElement("a");
@@ -4077,10 +4107,10 @@ const _ResultsRenderer = class _ResultsRenderer {
4077
4107
  ctx.fillText(labels.join(" · "), W / 2, divY + 92);
4078
4108
  ctx.font = "14px Georgia, serif";
4079
4109
  ctx.fillStyle = "rgba(232,224,214,0.55)";
4080
- ctx.fillText("Happy Easter! 🐰🥚", W / 2, divY + 130);
4110
+ ctx.fillText("All three eggs found", W / 2, divY + 130);
4081
4111
  ctx.font = "11px Georgia, serif";
4082
4112
  ctx.fillStyle = "rgba(232,224,214,0.3)";
4083
- ctx.fillText("Wishing you joy, peace, and light", W / 2, divY + 150);
4113
+ ctx.fillText("Share or copy your result", W / 2, divY + 150);
4084
4114
  ctx.font = "9px Georgia, serif";
4085
4115
  ctx.fillStyle = "rgba(232,224,214,0.12)";
4086
4116
  ctx.fillText("easter egg quest", W / 2, H - 16);
@@ -4550,6 +4580,8 @@ class StillnessStage {
4550
4580
  this._attempts = 1;
4551
4581
  this.input.resetPhases();
4552
4582
  this.input.resetCounts();
4583
+ this.bus.emit("narrative:clear");
4584
+ await this._wait(850);
4553
4585
  this._introPlayed = false;
4554
4586
  const introLines = this.script.stage1Intro;
4555
4587
  for (let i = 0; i < introLines.length; i++) {
@@ -4644,6 +4676,8 @@ class MotionStage {
4644
4676
  this._attempts = 1;
4645
4677
  this.input.resetPhases();
4646
4678
  this.input.resetCounts();
4679
+ this.bus.emit("narrative:clear");
4680
+ await this._wait(850);
4647
4681
  this._introPlayed = false;
4648
4682
  const introLines = this.script.stage2Intro;
4649
4683
  for (let i = 0; i < introLines.length; i++) {
@@ -4743,6 +4777,7 @@ class RhythmStage {
4743
4777
  this._totalCycles = 0;
4744
4778
  this._lastPhaseCount = 0;
4745
4779
  this._bestAccuracy = 0;
4780
+ this._lastGuideTime = 0;
4746
4781
  this.IDEAL_MOVE_MIN = 1800;
4747
4782
  this.IDEAL_MOVE_MAX = 5e3;
4748
4783
  this.IDEAL_PAUSE_MIN = 1200;
@@ -4757,8 +4792,11 @@ class RhythmStage {
4757
4792
  this._attempts = 1;
4758
4793
  this._goodCycles = 0;
4759
4794
  this._totalCycles = 0;
4795
+ this.input.configurePhaseDetection({ stillThresholdMs: 900, minPhaseMs: 500 });
4760
4796
  this.input.resetPhases();
4761
4797
  this.input.resetCounts();
4798
+ this.bus.emit("narrative:clear");
4799
+ await this._wait(850);
4762
4800
  this._introPlayed = false;
4763
4801
  const introLines = this.script.stage3Intro;
4764
4802
  for (let i = 0; i < introLines.length; i++) {
@@ -4774,6 +4812,8 @@ class RhythmStage {
4774
4812
  this.input.resetPhases();
4775
4813
  this._lastPhaseCount = this.input.phases.length;
4776
4814
  this._introPlayed = true;
4815
+ this.bus.emit("narrative:show", "move for a few seconds, then hold still");
4816
+ this._lastGuideTime = Date.now();
4777
4817
  }
4778
4818
  update(_dt) {
4779
4819
  if (this._status === "complete" || !this._introPlayed) return this._status;
@@ -4800,7 +4840,17 @@ class RhythmStage {
4800
4840
  if (accuracy > this._bestAccuracy) this._bestAccuracy = accuracy;
4801
4841
  const progress = Math.min(1, this._goodCycles / requiredCycles);
4802
4842
  this.bus.emit("stage:progress", progress);
4803
- this.bus.emit("rhythm:breathe", { accuracy, isMoving: this.input.snapshot.isMoving });
4843
+ this.bus.emit("rhythm:breathe", {
4844
+ accuracy,
4845
+ isMoving: this.input.snapshot.isMoving,
4846
+ progress,
4847
+ moveDuration: this.input.moveDuration,
4848
+ stillDuration: this.input.stillDuration
4849
+ });
4850
+ if (accuracy === 0 && Date.now() - this._lastGuideTime > 12e3) {
4851
+ this._lastGuideTime = Date.now();
4852
+ this.bus.emit("narrative:show", "try this: move 2-4s, then stay still 1-3s");
4853
+ }
4804
4854
  if (this._goodCycles >= requiredCycles) {
4805
4855
  this._status = "complete";
4806
4856
  this.bus.emit("stage:progress", 1);
@@ -4810,6 +4860,7 @@ class RhythmStage {
4810
4860
  return this._status;
4811
4861
  }
4812
4862
  cleanup() {
4863
+ this.input.resetPhaseDetection();
4813
4864
  }
4814
4865
  getResult() {
4815
4866
  return {
@@ -4829,7 +4880,7 @@ class RhythmStage {
4829
4880
  }
4830
4881
  _showReaction() {
4831
4882
  const now = Date.now();
4832
- if (now - this._lastNarrativeTime > 6e4) {
4883
+ if (now - this._lastNarrativeTime > 12e3) {
4833
4884
  this._lastNarrativeTime = now;
4834
4885
  const reactions = this.script.stage3Reactions;
4835
4886
  const line = reactions[this._narrativeIndex % reactions.length];
@@ -4945,6 +4996,7 @@ class PageBreather {
4945
4996
  this._targetIntensity = 0;
4946
4997
  this._rafId = 0;
4947
4998
  this._overlay = null;
4999
+ this._label = null;
4948
5000
  this._startTime = 0;
4949
5001
  this._isUserMoving = false;
4950
5002
  this._inSync = false;
@@ -4960,9 +5012,16 @@ class PageBreather {
4960
5012
  const shouldMove = phase < 0.5;
4961
5013
  this._inSync = this._accuracy > 0 && shouldMove === this._isUserMoving;
4962
5014
  const baseOpacity = wave * 0.85;
4963
- const syncBonus = this._inSync ? 0.15 : 0;
4964
- const opacity = this._intensity * (baseOpacity + (1 - wave) * 0.05 + syncBonus);
4965
- this._overlay.style.opacity = String(Math.min(1, opacity));
5015
+ const syncBonus = this._inSync ? 0.22 : 0;
5016
+ const opacity = this._intensity * (0.18 + baseOpacity + (1 - wave) * 0.12 + syncBonus);
5017
+ this._overlay.style.opacity = String(Math.min(0.9, opacity));
5018
+ this._overlay.style.transform = `scale(${1 + wave * 0.015})`;
5019
+ if (this._label) {
5020
+ this._label.textContent = shouldMove ? "Move" : "Hold still";
5021
+ this._label.style.opacity = shouldMove === this._isUserMoving ? "0.98" : "0.82";
5022
+ this._label.style.boxShadow = this._inSync ? "0 0 28px rgba(212,165,80,0.4)" : "0 0 20px rgba(255,255,255,0.08)";
5023
+ this._label.style.borderColor = this._inSync ? "rgba(212,165,80,0.55)" : "rgba(255,255,255,0.12)";
5024
+ }
4966
5025
  };
4967
5026
  }
4968
5027
  start() {
@@ -4979,31 +5038,56 @@ class PageBreather {
4979
5038
  "pointer-events:none",
4980
5039
  "z-index:999980",
4981
5040
  "opacity:0",
4982
- "background:radial-gradient(ellipse at center, transparent 30%, rgba(0,0,0,0.7) 100%)",
5041
+ "background:radial-gradient(ellipse at center, rgba(255,255,255,0.03) 0%, rgba(255,255,255,0.02) 24%, rgba(8,12,22,0.18) 46%, rgba(4,6,12,0.82) 100%)",
4983
5042
  "transition:opacity 0.3s ease"
4984
5043
  ].join(";");
4985
5044
  document.body.appendChild(el);
4986
5045
  this._overlay = el;
5046
+ const label = document.createElement("div");
5047
+ label.style.cssText = [
5048
+ "position:fixed",
5049
+ "left:50%",
5050
+ "top:18%",
5051
+ "transform:translateX(-50%)",
5052
+ "pointer-events:none",
5053
+ "z-index:999981",
5054
+ "padding:8px 14px",
5055
+ "border-radius:999px",
5056
+ "font-family:Georgia, Times New Roman, serif",
5057
+ "font-size:12px",
5058
+ "letter-spacing:0.12em",
5059
+ "text-transform:uppercase",
5060
+ "color:rgba(255,248,232,0.95)",
5061
+ "background:rgba(8,10,18,0.36)",
5062
+ "border:1px solid rgba(255,255,255,0.12)",
5063
+ "box-shadow:0 0 20px rgba(255,255,255,0.08)",
5064
+ "opacity:0.78"
5065
+ ].join(";");
5066
+ label.textContent = "Move";
5067
+ document.body.appendChild(label);
5068
+ this._label = label;
4987
5069
  this._tick();
4988
5070
  }
4989
5071
  update(accuracy, isMoving) {
4990
5072
  if (!this._active) return;
4991
5073
  this._isUserMoving = isMoving;
4992
5074
  this._accuracy = accuracy;
4993
- const raw = Math.max(0, Math.min(1, (accuracy - 0.05) / 0.5));
4994
- this._targetIntensity = 0.5 + raw * 0.5;
5075
+ const raw = Math.max(0, Math.min(1, (accuracy - 0.02) / 0.45));
5076
+ this._targetIntensity = 0.68 + raw * 0.32;
4995
5077
  }
4996
5078
  /** Whether the user is currently in sync with the breathing rhythm. */
4997
5079
  isInSync() {
4998
5080
  return this._inSync;
4999
5081
  }
5000
5082
  stop() {
5001
- var _a2;
5083
+ var _a2, _b2;
5002
5084
  if (!this._active) return;
5003
5085
  this._active = false;
5004
5086
  cancelAnimationFrame(this._rafId);
5005
5087
  (_a2 = this._overlay) == null ? void 0 : _a2.remove();
5006
5088
  this._overlay = null;
5089
+ (_b2 = this._label) == null ? void 0 : _b2.remove();
5090
+ this._label = null;
5007
5091
  this._intensity = 0;
5008
5092
  this._targetIntensity = 0;
5009
5093
  this._inSync = false;
@@ -5097,7 +5181,7 @@ class GameController {
5097
5181
  });
5098
5182
  this.bus.on("narrative:clear", () => {
5099
5183
  var _a3;
5100
- return (_a3 = this.narrative) == null ? void 0 : _a3.clear();
5184
+ return (_a3 = this.narrative) == null ? void 0 : _a3.clear(true);
5101
5185
  });
5102
5186
  this.bus.on("egg:reveal", (index) => this._handleEggReveal(index));
5103
5187
  this.bus.on("stage:progress", (p) => this._handleStageProgress(p));
@@ -5109,8 +5193,10 @@ class GameController {
5109
5193
  var _a3, _b3;
5110
5194
  (_a3 = this.eggRenderer) == null ? void 0 : _a3.setBreathIntensity(data.accuracy);
5111
5195
  (_b3 = this.pageBreather) == null ? void 0 : _b3.update(data.accuracy, data.isMoving);
5112
- if (data.accuracy > 0 && this.threeRenderer) {
5113
- this.threeRenderer.showProgressParticles(0.6 + data.accuracy * 0.4);
5196
+ const rhythmSignal = Math.max(data.accuracy, data.progress * 0.75);
5197
+ const hasLiveCycleSignal = data.moveDuration > 1200 || data.stillDuration > 900;
5198
+ if ((rhythmSignal > 0.08 || hasLiveCycleSignal) && this.threeRenderer) {
5199
+ this.threeRenderer.showProgressParticles(0.45 + rhythmSignal * 0.55);
5114
5200
  } else if (this.threeRenderer) {
5115
5201
  this.threeRenderer.fadeOutAmbientParticles();
5116
5202
  }
@@ -5474,7 +5560,7 @@ class GameController {
5474
5560
  (_d = this.narrative) == null ? void 0 : _d.showCelebration(congrats[eggIndex] ?? "egg collected");
5475
5561
  await this._wait(3500);
5476
5562
  (_e = this.narrative) == null ? void 0 : _e.clear();
5477
- await this._wait(400);
5563
+ await this._wait(900);
5478
5564
  if (eggIndex < 2) {
5479
5565
  if (eggIndex === 0) {
5480
5566
  this.fsm.transitionTo("stage2-intro");