/**** 
* Classes
****/
// Board class
var Board = Container.expand(function () {
	var self = Container.call(this);
	// Function to shuffle gems around randomly
	Board.prototype.shuffleGems = function () {
		console.log("shuffleGems");
		self.isShuffling = true;
		// Removed usage of Set for compatibility
		for (var i = this.gems.length - 1; i > 0; i--) {
			this.gems[i].newPosition = false;
		}
		for (var i = this.gems.length - 1; i > 0; i--) {
			var j = Math.floor(Math.random() * (i + 1));
			// Swap the gems
			var tempNewPosition = this.gems[i].newPosition || {
				x: this.gems[i].x,
				y: this.gems[i].y
			};
			this.gems[i].newPosition = this.gems[j].newPosition || {
				x: this.gems[j].x,
				y: this.gems[j].y
			};
			this.gems[j].newPosition = tempNewPosition;
		}
		// The rest of your method remains unchanged
		function animateGemToPosition(gem, x, y) {
			var animationDuration = 1000; // Duration of the animation in milliseconds
			var startX = gem.x;
			var startY = gem.y;
			var deltaX = x - startX;
			var deltaY = y - startY;
			var startTime = Date.now();
			var animate = function animate() {
				var now = Date.now();
				var progress = Math.min(1, (now - startTime) / animationDuration);
				gem.x = startX + deltaX * progress;
				gem.y = startY + deltaY * progress;
				if (progress < 1) {
					LK.setTimeout(animate, 16); // Aim for roughly 60fps
				} else {
					gem.x = x;
					gem.y = y;
					self.isShuffling = false;
				}
			};
			LK.setTimeout(animate, 16);
		}
		// Update the positions of the shuffled gems and ensure they have the correct new position in the gems array
		var newGemsArray = new Array(this.gems.length);
		this.gems.forEach(function (gem, index) {
			if (gem.newPosition) {
				var newPositionIndex = this.gems.findIndex(function (g) {
					return g.x === gem.newPosition.x && g.y === gem.newPosition.y;
				});
				var aNewPosition = this.snapToGrid(gem.newPosition.x, gem.newPosition.y);
				animateGemToPosition(gem, aNewPosition.x, aNewPosition.y);
				newGemsArray[newPositionIndex] = gem;
			}
		}.bind(this));
		this.gems = newGemsArray.filter(function (g) {
			return g !== undefined;
		});
		LK.setTimeout(self.checkForMatches, 1000);
	};
	// Method to round or snap any position to the nearest position in the grid made by the 6x8 gems
	this.snapToGrid = function (x, y) {
		// Ensure there is at least one gem in the array before accessing its properties
		var margin = 10;
		var boardWidth = game.width * .9;
		var boardHeight = game.height * .9;
		var gemsPerRow = 6;
		var gemsPerColumn = 8;
		var totalMarginWidth = margin * (gemsPerRow + 1);
		var totalMarginHeight = margin * (gemsPerColumn + 1);
		var availableWidth = boardWidth - totalMarginWidth;
		var availableHeight = boardHeight - totalMarginHeight;
		var scaledGemSize = Math.min(availableWidth / gemsPerRow, availableHeight / gemsPerColumn);
		var xOffset = (game.width - boardWidth) / 2 + scaledGemSize / 2;
		var yOffset = (game.height - boardHeight) / 2 + scaledGemSize / 2 + 80;
		var columnWidth = (boardWidth - margin) / 6;
		var rowHeight = (boardHeight - margin) / 8;
		var snappedX = Math.round((x - xOffset) / columnWidth) * columnWidth + xOffset;
		var snappedY = Math.round((y - yOffset) / rowHeight) * rowHeight + yOffset;
		return {
			x: snappedX,
			y: snappedY
		};
	};
	// Method to show a hint for a possible match
	this.showHint = function () {
		console.log('showHint function started');
		var possibleMatches = this.checkIfAnyMoveCausesMatch();
		if (possibleMatches.length > 0) {
			var animateMove = function animateMove(repeatCount) {
				if (move.gem.isUsed) {
					// Start fade-out effect for hint overlay
					var fadeOutDuration = 500; // Fade out over 500ms
					var startTime = Date.now();
					var fadeStep = function fadeStep() {
						var currentTime = Date.now();
						var progress = (currentTime - startTime) / fadeOutDuration;
						hintOverlay.alpha = 1 - progress; // Fade out effect
						if (progress < 1) {
							LK.setTimeout(fadeStep, 16); // Continue fading
						} else {
							hintOverlay.destroy(); // Destroy after faded out
						}
					};
					fadeStep();
					return;
				}
				var totalDuration = 1000; // Half a second for each back and forth movement
				var repeatLimit = 1; // Repeat the animation three times
				var animationCount = 0;
				var startTime = Date.now();
				var animateStep = function animateStep() {
					if (move.gem.isUsed || !hintOverlay) {
						if (hintOverlay) {
							hintOverlay.destroy();
						}
						return;
					}
					var currentTime = Date.now();
					var progress = (currentTime - startTime) / totalDuration;
					var waveProgress = (Math.sin(progress * Math.PI * 2) + 1) / 2; // Adjusted to ensure it never goes below zero
					hintOverlay.x = move.gemStartPosition.x + moveDirection.dx * moveDistance * waveProgress;
					hintOverlay.y = move.gemStartPosition.y + moveDirection.dy * moveDistance * waveProgress;
					if (progress >= 1) {
						animationCount++;
						if (animationCount < repeatLimit) {
							startTime = Date.now(); // Reset start time for the next cycle
							animateStep(); // Continue animation
						} else {
							hintOverlay.destroy();
						}
					} else {
						LK.setTimeout(animateStep, 16); // Continue animation
					}
				};
				animateStep();
			};
			console.log('Possible matches:', possibleMatches);
			var move = possibleMatches[0];
			var hintOverlay = LK.getAsset('hintOverlay', {});
			self.lastHintOverlay = hintOverlay;
			hintOverlay.anchor.set(0, 0);
			self.addChild(hintOverlay);
			hintOverlay.x = move.gem.x;
			hintOverlay.y = move.gem.y;
			move.gemStartPosition = {
				x: move.gem.x,
				y: move.gem.y
			}; // Track starting position for animation
			var moveDirection = move.move;
			var moveDistance = move.gem.spacing; // Distance to move back and forth
			var moveDuration = 500; // Duration of each move
			animateMove();
		} else {
			console.log("no possible matches");
			if (!self.fillingEmptySpaces && !self.gemsFalling && !self.isShuffling && !isDragoning) {
				triggerDragon();
			}
		}
	};
	// Method to find possible matches on the board
	// Method to find possible matches on the board
	// Method to find possible matches on the board
	this.findPossibleMatches = function () {
		var matches = [];
		var width = 6; // Board width
		var height = 8; // Board height
		for (var i = 0; i < height; i++) {
			for (var j = 0; j < width; j++) {
				var currentGem = this.gems[i * width + j];
				// Check right and down for potential matches
				var directions = [{
					dx: 1,
					dy: 0
				},
				// Right
				{
					dx: 0,
					dy: 1
				} // Down
				];
				directions.forEach(function (dir) {
					var match = [currentGem];
					for (var k = 1; k < 3; k++) {
						var nextGemX = j + dir.dx * k;
						var nextGemY = i + dir.dy * k;
						if (nextGemX < width && nextGemY < height) {
							var nextGem = this.gems[nextGemY * width + nextGemX];
							if (nextGem && currentGem && nextGem.color === currentGem.color) {
								match.push(nextGem);
							} else {
								break;
							}
						}
					}
					if (match.length >= 3) {
						// Allows for matches longer than 3
						matches.push(match);
					}
				}, this);
			}
		}
		return matches;
	};
	// Method to check if moving any gem results in a match
	this.checkIfAnyMoveCausesMatch = function () {
		var matches = [];
		var width = 6; // Board width
		var height = 8; // Board height
		// Simulate moving each gem in all four directions and check for matches
		for (var i = 0; i < height; i++) {
			for (var j = 0; j < width; j++) {
				var currentGem = this.gems[i * width + j];
				if (!currentGem) {
					continue;
				}
				// Possible moves: up, down, left, right
				var moves = [{
					dx: -1,
					dy: 0
				}, {
					dx: 1,
					dy: 0
				}, {
					dx: 0,
					dy: -1
				}, {
					dx: 0,
					dy: 1
				}];
				moves.forEach(function (move) {
					var newX = j + move.dx;
					var newY = i + move.dy;
					// Check if the new position is within the board
					if (newX >= 0 && newX < width && newY >= 0 && newY < height) {
						var targetGem = this.findGemByPosition(currentGem.x + currentGem.spacing * move.dx, currentGem.y + currentGem.spacing * move.dy);
						if (targetGem && this.wouldSwapResultInMatch(currentGem, targetGem)) {
							matches.push({
								gem: currentGem,
								move: move
							});
						}
					}
				}, this);
			}
		}
		return matches;
	};
	// Check if swapping two gems would result in a match
	this.wouldSwapResultInMatch = function (gemA, gemB) {
		var gemAIndex = this.gems.indexOf(gemA);
		var gemBIndex = this.gems.indexOf(gemB);
		this.gems[gemAIndex] = gemB;
		this.gems[gemBIndex] = gemA;
		// Check for matches
		var matchFound = false;
		var matchedGems = [];
		// Check for horizontal matches
		for (var i = 0; i < 8; i++) {
			for (var j = 0; j < 6; j++) {
				// Adjust to allow checks across all columns
				var gem1 = this.gems[i * 6 + j];
				var nowMatchingGems = [];
				for (var k = j; k < 6; k++) {
					var nextGem = this.gems[i * 6 + k];
					if (nextGem && nextGem.color === gem1.color) {
						nowMatchingGems.push(nextGem);
					} else {
						break;
					}
				}
				if (nowMatchingGems.length >= 3) {
					matchFound = true;
					matchedGems = matchedGems.concat(nowMatchingGems.filter(function (gem) {
						return matchedGems.indexOf(gem) === -1;
					}));
				}
			}
		}
		// Check for vertical matches
		for (var i = 0; i < 6; i++) {
			for (var j = 0; j < 8; j++) {
				// Adjust to allow checks across all rows
				var gem1 = this.gems[j * 6 + i];
				var nowMatchingGems = [];
				for (var k = j; k < 8; k++) {
					var nextGem = this.gems[k * 6 + i];
					if (nextGem && nextGem.color === gem1.color) {
						nowMatchingGems.push(nextGem);
					} else {
						break;
					}
				}
				if (nowMatchingGems.length >= 3) {
					matchFound = true;
					matchedGems = matchedGems.concat(nowMatchingGems.filter(function (gem) {
						return matchedGems.indexOf(gem) === -1;
					}));
				}
			}
		}
		// Swap back
		this.gems[gemAIndex] = gemA;
		this.gems[gemBIndex] = gemB;
		return matchFound;
	};
	this.swapGems = function (gem1, gem2) {
		var gem1Index = this.gems.indexOf(gem1);
		var gem2Index = this.gems.indexOf(gem2);
		if (gem1Index !== -1 && gem2Index !== -1) {
			// Animate swap positions with easing
			var swapDuration = 150; // Duration in milliseconds
			var gem1StartPos = {
				x: gem1.x,
				y: gem1.y
			};
			if (!gem2) {
				return;
			} // Prevent TypeError if gem2 is null
			var gem2StartPos = {
				x: gem2.x,
				y: gem2.y
			};
			gem1.isUsed = true;
			gem2.isUsed = true;
			gem1.alpha = 1;
			gem2.alpha = 1;
			var startTime = Date.now();
			var animateSwap = function animateSwap() {
				var currentTime = Date.now();
				var progress = Math.min(1, (currentTime - startTime) / swapDuration);
				var easeInOut = progress < 0.5 ? 2 * progress * progress : -1 + (4 - 2 * progress) * progress;
				gem1.x = gem1StartPos.x + (gem2StartPos.x - gem1StartPos.x) * easeInOut;
				gem1.y = gem1StartPos.y + (gem2StartPos.y - gem1StartPos.y) * easeInOut;
				gem2.x = gem2StartPos.x + (gem1StartPos.x - gem2StartPos.x) * easeInOut;
				gem2.y = gem2StartPos.y + (gem1StartPos.y - gem2StartPos.y) * easeInOut;
				if (progress < 1) {
					LK.setTimeout(animateSwap, 16); // Aim for roughly 60fps
				} else {
					gem1.isUsed = false;
					gem2.isUsed = false;
					var snappedOne = self.snapToGrid(gem1.x, gem1.y);
					gem1.x = snappedOne.x;
					gem1.y = snappedOne.y;
					var snappedOne = self.snapToGrid(gem2.x, gem2.y);
					gem2.x = snappedOne.x;
					gem2.y = snappedOne.y;
					self.checkForMatches();
				}
			};
			animateSwap();
			// Swap in gems array
			this.gems[gem1Index] = gem2;
			this.gems[gem2Index] = gem1;
			// Check for matches after swap
		}
	};
	this.faintSwapGems = function (gem1, gem2, firstFaint) {
		var gem1Index = this.gems.indexOf(gem1);
		var gem2Index = this.gems.indexOf(gem2);
		if (gem1Index !== -1 && gem2Index !== -1) {
			// Animate swap positions with easing
			var swapDuration = 150; // Duration in milliseconds
			var gem1StartPos = {
				x: gem1.x,
				y: gem1.y
			};
			var gem2StartPos = {
				x: gem2.x,
				y: gem2.y
			};
			var startTime = Date.now();
			var animateSwap = function animateSwap() {
				var currentTime = Date.now();
				var progress = Math.min(1, (currentTime - startTime) / swapDuration);
				var easeInOut = progress < 0.5 ? 2 * progress * progress : -1 + (4 - 2 * progress) * progress;
				gem1.x = gem1StartPos.x + (gem2StartPos.x - gem1StartPos.x) * easeInOut;
				gem1.y = gem1StartPos.y + (gem2StartPos.y - gem1StartPos.y) * easeInOut;
				gem2.x = gem2StartPos.x + (gem1StartPos.x - gem2StartPos.x) * easeInOut;
				gem2.y = gem2StartPos.y + (gem1StartPos.y - gem2StartPos.y) * easeInOut;
				if (progress < 1) {
					LK.setTimeout(animateSwap, 16); // Aim for roughly 60fps
				} else if (firstFaint) {
					self.faintSwapGems(gem1, gem2);
				}
			};
			animateSwap();
			// Swap in gems array
			this.gems[gem1Index] = gem2;
			this.gems[gem2Index] = gem1;
		}
	};
	// Find a gem by its position
	this.findGemByPosition = function (x, y, exceptThisGem) {
		for (var i = 0; i < this.gems.length; i++) {
			var gem = this.gems[i];
			if (gem == exceptThisGem) {
				continue;
			}
			if (gem) {
				var tolerance = gem.spacing / 2; // Tolerance in pixels for approximate position
				if (Math.abs(x - gem.x) < tolerance && Math.abs(y - gem.y) < tolerance) {
					return gem;
				}
			}
		}
		return null;
	};
	this.fillEmptySpaces = function () {
		self.fillingEmptySpaces = true;
		var _animateGemDown = function animateGemDown(newGem, finalY, initialY) {
			var snappedOne = self.snapToGrid(newGem.x, finalY);
			finalY = snappedOne.y;
			var animationDuration = 250; // Duration in milliseconds
			var startTime = Date.now();
			var animate = function animate() {
				var currentTime = Date.now();
				var progress = Math.min(1, (currentTime - startTime) / animationDuration);
				// Apply easing for smoother animation
				var easedProgress = Math.sin(progress * Math.PI / 2);
				if (progress < 1) {
					newGem.y = initialY + (finalY - initialY) * easedProgress;
					LK.setTimeout(animate, 16); // Aim for roughly 60fps
				} else {
					newGem.y = finalY; // Ensure final position is accurate
					self.fillingEmptySpaces = false;
				}
			};
			animate();
		};
		for (var i = 0; i < 8; i++) {
			for (var j = 0; j < 6; j++) {
				var index = i * 6 + j;
				if (!self.gems[index]) {
					var possibleColors = ['gemBlue', 'gemGreen', 'gemRed', 'gemPurple', 'gemYellow', 'gemOrange', 'gemCyan'];
					// Filter colors to ensure at least one possible match
					var colors = possibleColors.filter(function (color) {
						return true;
					}, this);
					var color = colors.length > 0 ? colors[Math.floor(Math.random() * colors.length)] : possibleColors[Math.floor(Math.random() * possibleColors.length)];
					var newGem = new Gem(color);
					// Calculate x and y position for new gems when there are no existing gems to reference
					var gemSize = 100;
					var margin = 10;
					var boardWidth = 1800; // Assuming the board width is known
					var boardHeight = 2400; // Assuming the board height is known
					var gemsPerRow = 6;
					var gemsPerColumn = 8;
					var totalMarginWidth = margin * (gemsPerRow + 1);
					var totalMarginHeight = margin * (gemsPerColumn + 1);
					var availableWidth = boardWidth - totalMarginWidth;
					var availableHeight = boardHeight - totalMarginHeight;
					var scaledGemSize = Math.min(availableWidth / gemsPerRow, availableHeight / gemsPerColumn);
					var xOffset = (2048 - boardWidth) / 2 + scaledGemSize / 2; // Assuming game width is 2048
					var yOffset = (2732 - boardHeight) / 2 + scaledGemSize / 2; // Assuming game height is 2732
					var snapped = self.snapToGrid(xOffset + (scaledGemSize + margin) * j, yOffset + (scaledGemSize + margin) * i);
					newGem.x = snapped.x;
					// Calculate initial y position for animation start
					// Calculate initial y position for animation start
					var initialY = -gemSize; // Start above the screen to simulate falling into place
					newGem.y = initialY;
					// Animate gem to its final position
					var finalY = snapped.y;
					_animateGemDown(newGem, finalY, initialY);
					newGem.spacing = scaledGemSize + margin;
					newGem.scale.set(scaledGemSize / gemSize);
					newGem.baseScale = scaledGemSize / gemSize;
					self.addChild(newGem);
					self.gems[index] = newGem;
					self.handleGemClick(newGem);
				}
			}
		}
	};
	self.gems = [];
	this.handleFallingGems = function () {
		console.log("handle Falling gems");
		var didFall = false;
		for (var i = 0; i < 6; i++) {
			for (var j = 7; j >= 0; j--) {
				var index = j * 6 + i;
				if (index >= 0 && index < self.gems.length && !self.gems[index]) {
					var emptySpaces = 1;
					for (var k = j - 1; k >= 0; k--) {
						var aboveIndex = k * 6 + i;
						if (!self.gems[aboveIndex]) {
							emptySpaces++;
						} else {
							var gemAbove = self.gems[aboveIndex];
							var targetIndex = (k + emptySpaces) * 6 + i;
							self.gems[targetIndex] = gemAbove;
							self.gems[aboveIndex] = null;
							// Calculate the new Y position based on the number of empty spaces
							var margin = 10;
							var snapped = self.snapToGrid(gemAbove.x, gemAbove.y + gemAbove.spacing * emptySpaces);
							var newY = snapped.y;
							// Animate the gem moving to the new position
							gemAbove.alpha = 1;
							animateGemToPosition(gemAbove, gemAbove.x, newY);
							didFall = true;
							break;
						}
					}
				}
			}
		}
		if (didFall) {
			self.gemsFalling = true;
			LK.setTimeout(function () {
				self.fillEmptySpaces();
				LK.setTimeout(function () {
					self.gemsFalling = false;
					self.checkForMatches();
				}, 250);
			}, 250);
		} else {
			// Trigger fillEmptySpaces even if no gems fell to ensure no gaps are left
			self.fillEmptySpaces();
			LK.setTimeout(function () {
				self.checkForMatches();
			}, 250);
		}
	};
	function animateGemToPosition(gem, newX, newY) {
		var fallDuration = 500; // Duration for the gem to fall to its new position
		var bounceDuration = 300; // Duration for the bounce effect, slightly longer for realism
		var scaleDuration = 150; // Duration for the scale effect after bouncing
		var startTime = Date.now();
		var animateStep = function animateStep() {
			var currentTime = Date.now();
			var elapsedTime = currentTime - startTime;
			var progress = elapsedTime / fallDuration;
			// First, handle the falling animation with a linear or ease-in effect
			if (progress < 1) {
				var fallProgress = Math.min(1, progress); // Ensure progress doesn't exceed 1
				// Simple linear interpolation for falling
				gem.y = gem.y + (newY - gem.y) * fallProgress;
				if (fallProgress < 1) {
					LK.setTimeout(animateStep, 16); // Continue the fall animation
				} else {
					gem.y = newY;
					gem.isUsed = false;
				}
			}
		};
		animateStep(); // Start the animation with the fall
	}
	this.handleGemMatched = function (gem) {
		if (gem.color == goalGemType) {
			matchedGemCount++;
			goalTxt.setText(matchedGemCount + "/" + goalGemCount);
			if (matchedGemCount >= goalGemCount) {
				game.timer += 10;
				timerTxt.setText(game.timer.toString());
				stopTimer();
				// Show modal pop-up for 10 more seconds
				var modalContainer = new Container();
				LK.gui.center.addChild(modalContainer);
				var modalBackground = LK.getAsset('goalCompleteBg', {});
				modalBackground.anchor.set(.5, .5);
				modalBackground.alpha = .75;
				modalContainer.addChild(modalBackground);
				// Animate scale of the modal container for excitement
				var scaleStartTime = Date.now();
				var scaleDuration = 500; // Scale animation duration in milliseconds
				var animateScale = function animateScale() {
					var currentTime = Date.now();
					var progress = (currentTime - scaleStartTime) / scaleDuration;
					var scale = 1 + 0.1 * Math.sin(progress * Math.PI * 2); // Oscillate scale between 1 and 1.1
					modalContainer.scale.set(scale);
					if (progress < 1) {
						LK.setTimeout(animateScale, 16);
					}
				};
				animateScale();
				// Trigger lots of confetti balls on mission complete
				for (var i = 0; i < 100; i++) {
					var confetti = new ConfettiParticle();
					confetti.init(Math.random() * game.width, Math.random() * game.height);
					game.addChild(confetti);
				}
				showPastGoalSprite = LK.getAsset(goalGemType, {
					// Align with the timer's top margin
					anchorX: .5,
					// Anchor right for right alignment
					anchorY: .5 // Anchor top for top alignment
				});
				goalGemType = false;
				// Add hourglass sprite next to the timer
				var pastGoalBackground = LK.getAsset('newSpriteId', {});
				pastGoalBackground.y = 0;
				pastGoalBackground.x = -100;
				pastGoalBackground.anchor.set(0.5, 0.5); // Align with the timer's top margin
				modalContainer.addChild(pastGoalBackground);
				pastGoalBackground.alpha = .75;
				showPastGoalSprite.y = pastGoalBackground.y;
				showPastGoalSprite.x = pastGoalBackground.x;
				showPastGoalSprite.anchor.set(.5, 0.5); // Align with the timer's top margin
				modalContainer.addChild(showPastGoalSprite);
				showPastGoalSprite.rotation = -.2;
				var showPastGoalText = new Text2(matchedGemCount + "/" + goalGemCount, {
					size: 100,
					weight: 600,
					fill: "#ffffff",
					x: 1024,
					y: 1366,
					anchorX: 0.5,
					anchorY: 0.5,
					dropShadow: true,
					dropShadowColor: '#000000',
					dropShadowBlur: 8,
					dropShadowOffsetX: 4,
					dropShadowOffsetY: 4,
					stroke: true,
					strokeColor: '#000000',
					strokeThickness: 4
				});
				showPastGoalText.y = pastGoalBackground.y;
				showPastGoalText.x = 0;
				showPastGoalText.anchor.set(0, 0.5); // Align with the timer's top margin
				modalContainer.addChild(showPastGoalText);
				var modalInfoText = new Text2('MISSION COMPLETE:', {
					size: 50,
					weight: 600,
					fill: "#ffffff",
					x: 1024,
					y: 1366,
					anchorX: 0.5,
					anchorY: 0.5,
					dropShadow: true,
					dropShadowColor: '#000000',
					dropShadowBlur: 8,
					dropShadowOffsetX: 4,
					dropShadowOffsetY: 4,
					stroke: true,
					strokeColor: '#000000',
					strokeThickness: 2
				});
				modalInfoText.anchor.set(.5);
				modalInfoText.y = -100;
				modalContainer.addChild(modalInfoText);
				var modalText = new Text2('+10 seconds!', {
					size: 100,
					weight: 600,
					fill: "#ffffff",
					x: 1024 + 70,
					// Adjust x position to make space for the hourglass sprite
					y: 1366,
					anchorX: 0.5,
					anchorY: 0.5,
					dropShadow: true,
					dropShadowColor: '#000000',
					dropShadowBlur: 8,
					dropShadowOffsetX: 4,
					dropShadowOffsetY: 4,
					stroke: true,
					strokeColor: '#000000',
					strokeThickness: 2
				});
				modalText.anchor.set(.5);
				modalText.y = 100;
				modalContainer.addChild(modalText);
				// Add hourglass sprite next to the '+10 seconds!' text
				var hourglassSpriteModal = LK.getAsset('hourglass', {
					anchorX: .5,
					anchorY: .5
				});
				hourglassSpriteModal.x = 1024 - 70; // Position hourglass to the left of the text
				hourglassSpriteModal.y = 1366;
				modalContainer.addChild(hourglassSpriteModal);
				var thumbUpSprite = LK.getAsset('thumbUp', {
					// Align with the timer's top margin
					anchorX: .5,
					// Anchor right for right alignment
					anchorY: .5 // Anchor top for top alignment
				});
				thumbUpSprite.y = 0;
				thumbUpSprite.x = -500;
				thumbUpSprite.anchor.set(.5, 0.5); // Align with the timer's top margin
				modalContainer.addChild(thumbUpSprite);
				var thumbUpSprite2 = LK.getAsset('woodLockAcid', {
					// Align with the timer's top margin
					anchorX: .5,
					// Anchor right for right alignment
					anchorY: .5 // Anchor top for top alignment
				});
				thumbUpSprite2.y = 0;
				thumbUpSprite2.x = 500;
				thumbUpSprite2.anchor.set(.5, 0.5); // Align with the timer's top margin
				modalContainer.addChild(thumbUpSprite2);
				var modalText = new Text2('+', {
					size: 120,
					weight: 600,
					fill: "#ffffff",
					x: 1024 + 70,
					// Adjust x position to make space for the hourglass sprite
					y: 1366,
					anchorX: 0.5,
					anchorY: 0.5,
					dropShadow: true,
					dropShadowColor: '#000000',
					dropShadowBlur: 8,
					dropShadowOffsetX: 4,
					dropShadowOffsetY: 4,
					stroke: true,
					strokeColor: '#000000',
					strokeThickness: 2
				});
				modalText.anchor.set(.5);
				modalText.x = 400;
				modalText.y = 0;
				modalContainer.addChild(modalText);
				// Automatically remove the modal and background after 2 seconds
				// Start animation for modal elements
				var duration = 2000; // 3 seconds for the animation
				LK.setTimeout(function () {
					var startTime = Date.now();
					var simpleCountdownInterval = LK.setInterval(function () {
						var currentTime = Date.now();
						var progress = (currentTime - startTime) / duration;
						var moveDistance = 2048; // Move to the right side off-screen
						modalContainer.x += moveDistance * progress;
						if (progress >= 1) {
							LK.clearInterval(simpleCountdownInterval);
							modalContainer.destroy();
							startTimer();
						}
					}, 16);
				}, 2000);
				goalLevel++;
				updateBackground();
				setRandomGoalGemType();
			}
		}
	};
	this.checkForMatches = function (matchFoundPreviously) {
		var matchFound = false;
		var matchedGems = [];
		// Check for horizontal matches
		for (var i = 0; i < 8; i++) {
			for (var j = 0; j < 6; j++) {
				// Adjust to allow checks across all columns
				if (!this.gems || !this.gems[i * 6 + j] || typeof this.gems[i * 6 + j] === 'undefined') {
					continue;
				}
				var gem1 = this.gems[i * 6 + j];
				if (!gem1) {
					continue;
				}
				var gem1 = this.gems[i * 6 + j];
				var nowMatchingGems = [];
				for (var k = j; k < 6; k++) {
					var nextGem = this.gems[i * 6 + k];
					if (nextGem && nextGem.color === gem1.color) {
						nowMatchingGems.push(nextGem);
					} else {
						break;
					}
				}
				if (nowMatchingGems.length >= 3) {
					matchFound = true;
					matchedGems = matchedGems.concat(nowMatchingGems.filter(function (gem) {
						return matchedGems.indexOf(gem) === -1;
					}));
				}
			}
		}
		// Check for vertical matches
		for (var i = 0; i < 6; i++) {
			for (var j = 0; j < 8; j++) {
				// Adjust to allow checks across all rows
				if (!this.gems || !this.gems[j * 6 + i]) {
					continue;
				}
				var gem1 = this.gems[j * 6 + i];
				var nowMatchingGems = [];
				for (var k = j; k < 8; k++) {
					var nextGem = this.gems[k * 6 + i];
					if (nextGem && nextGem.color === gem1.color) {
						nowMatchingGems.push(nextGem);
					} else {
						break;
					}
				}
				if (nowMatchingGems.length >= 3) {
					matchFound = true;
					matchedGems = matchedGems.concat(nowMatchingGems.filter(function (gem) {
						return matchedGems.indexOf(gem) === -1;
					}));
				}
			}
		}
		var matchesHandled = 0;
		matchedGems.forEach(function (gem) {
			if (gem.color == goalGemType) {
				self.handleGemMatched(gem);
				// Move gem to the goalGemSprite instead of destroying it
				matchesHandled++;
				game.addChild(gem);
				var moveGemToGoal = function moveGemToGoal(gem) {
					LK.setTimeout(function () {
						var goalGemSpriteX = currentGoalGemSprite ? currentGoalGemSprite.x + (currentGoalGemSprite.parent ? currentGoalGemSprite.parent.x : 0) : 0;
						var goalGemSpriteY = currentGoalGemSprite ? currentGoalGemSprite.y + (currentGoalGemSprite.parent ? currentGoalGemSprite.parent.y : 0) : 0;
						if (currentGoalGemSprite) {
							var goalGemSpriteScale = currentGoalGemSprite.scale.x;
						}
						var moveDuration = 500 + matchesHandled * 100; // Duration in milliseconds
						var startTime = Date.now();
						var animateMove = function animateMove() {
							var currentTime = Date.now();
							var progress = Math.min(1, (currentTime - startTime) / moveDuration);
							var newX = gem.x + (goalGemSpriteX - gem.x) * progress;
							var newY = gem.y + (goalGemSpriteY - gem.y) * progress;
							var newScale = gem.scale.x + (goalGemSpriteScale - gem.scale.x) * progress;
							gem.x = newX;
							gem.y = newY;
							gem.scale.set(newScale);
							if (progress < 1) {
								LK.setTimeout(animateMove, 16); // Aim for roughly 60fps
							} else {
								gem.destroy(); // Destroy gem after reaching the goal
							}
						};
						animateMove();
					}, matchesHandled * 100);
				};
				moveGemToGoal(gem);
			} else {
				self.handleGemMatched(gem);
				gem.scaleUpAndDisappear();
				// Trigger glowing particles effect at the gem's position
				var glowingParticles = new GlowingParticles();
				glowingParticles.init(gem.x, gem.y);
				self.addChild(glowingParticles);
			}
			var index = self.gems.indexOf(gem);
			if (index > -1) {
				self.gems[index] = false;
				// Increase score based on combo multiplier
				var pointsAwarded = 10 * self.comboMultiplier;
				score += pointsAwarded; // Update score with points awarded based on combo multiplier
				LK.setScore(score);
				// Display points at the gem's location with animation
				var pointsText = new Text2("+" + pointsAwarded.toString(), {
					size: 80,
					weight: 600,
					fill: "#ffffff",
					anchorX: 0.5,
					anchorY: 0.5,
					dropShadow: true,
					dropShadowColor: '#000000',
					dropShadowBlur: 8,
					dropShadowOffsetX: 4,
					dropShadowOffsetY: 4,
					outline: true,
					outlineColor: '#000000',
					outlineThickness: 5
				});
				pointsText.y -= 20; // Make it a little bit higher
				pointsText.anchor.set(.5);
				pointsText.x = gem.x;
				pointsText.y = gem.y;
				game.addChild(pointsText);
				// Animate points text: scale up and fade out
				var scaleUpDuration = 500; // Duration to scale up in milliseconds
				var fadeOutDuration = 500; // Duration to fade out in milliseconds
				var maxScale = 1.5; // Maximum scale factor
				var originalScale = 1; // Original scale
				var startTime = Date.now();
				var animate = function animate() {
					var currentTime = Date.now();
					var progress = Math.min(1, (currentTime - startTime) / scaleUpDuration);
					pointsText.scale.set(originalScale + (maxScale - originalScale) * progress);
					pointsText.alpha = 1 - progress; // Fade out
					if (progress < 1) {
						LK.setTimeout(animate, 16); // Aim for roughly 60fps
					} else {
						pointsText.destroy(); // Destroy text after animation
					}
				};
				animate();
				// Increase combo multiplier for each consecutive match
				self.comboMultiplier++;
				scoreTxt.setText(score.toString()); // Update score display
			}
		});
		if (matchFound) {
			// If no match was found previously and it's not the first check, reset the combo multiplier
			if (!matchFoundPreviously && matchFound) {
				self.comboMultiplier = 1;
			} else if (matchFound) {
				// Increase combo multiplier for each consecutive match
				self.comboMultiplier++;
			}
			self.checkForMatches(true);
		} else if (matchFoundPreviously) {
			LK.setTimeout(function () {
				this.handleFallingGems();
			}.bind(this), 200);
		}
		return matchFound;
	};
	self.handleGemClick = function (gem) {
		gem.on('down', function (obj) {
			self.dragStartGem = gem;
			self.dragStartGemStartPosition = {
				x: gem.x,
				y: gem.y
			};
			var currentPos = obj.event.getLocalPosition(game);
			self.dragStartPos = {
				x: currentPos.x,
				y: currentPos.y
			};
			// Highlight the drag start gem
			self.dragStartGem.alpha = 0.5;
			self.dragStartGem.scale.set(self.dragStartGem.baseScale * 1.1);
		});
		gem.on('move', function (obj) {
			if (!self.dragStartGem) {
				return;
			}
			var currentPos = obj.event.getLocalPosition(game);
			//self.dragStartGem.x = self.dragStartGemStartPosition.x + currentPos.x - self.dragStartPos.x;
			//self.dragStartGem.y = self.dragStartGemStartPosition.y + currentPos.y - self.dragStartPos.y;
			var dx = currentPos.x - self.dragStartPos.x;
			var dy = currentPos.y - self.dragStartPos.y;
			if (Math.abs(dx) > gem.spacing / 2 || Math.abs(dy) > gem.spacing / 2) {
				var directionX = dx > 0 ? 1 : -1;
				var directionY = dy > 0 ? 1 : -1;
				// Correctly identify if we should swap horizontally or vertically
				if (Math.abs(dx) > Math.abs(dy)) {
					// Swap horizontally
					var swapGem = self.findGemByPosition(self.dragStartGem.x + gem.spacing * directionX, self.dragStartGem.y, self.dragStartGem);
				} else {
					// Swap vertically
					var swapGem = self.findGemByPosition(self.dragStartGem.x, self.dragStartGem.y + gem.spacing * directionY, self.dragStartGem);
				}
				if (self.lastHintOverlay) {
					self.lastHintOverlay.destroy();
				}
				if (swapGem && self.wouldSwapResultInMatch(self.dragStartGem, swapGem)) {
					self.swapGems(self.dragStartGem, swapGem);
				} else {
					self.faintSwapGems(self.dragStartGem, swapGem, true);
				}
				self.dragStartGem.alpha = 1;
				self.dragStartGem.scale.set(self.dragStartGem.baseScale * 1);
				self.dragStartGem = null;
				self.dragStartPos = null;
			}
		});
		gem.on('up', function () {
			if (self.dragStartGem) {
				self.dragStartGem.alpha = 1; // Reset alpha to unhighlight the gem
				self.dragStartGem.scale.set(self.dragStartGem.baseScale * 1);
			}
			self.dragStartGem = null;
			self.dragStartPos = null;
		});
	};
	self.initBoard = function () {
		var colors = game.timer > 60 ? ['gemBlue', 'gemGreen', 'gemRed', 'gemPurple', 'gemYellow', 'gemOrange', 'gemCyan'] : ['gemBlue', 'gemGreen', 'gemRed', 'gemPurple', 'gemYellow', 'gemOrange'];
		for (var i = 0; i < 8; i++) {
			for (var j = 0; j < 6; j++) {
				var color = colors[Math.floor(Math.random() * colors.length)];
				var gem = new Gem(color);
				var gem = new Gem(color);
				var gemSize = 100;
				var margin = 10;
				var boardWidth = game.width * .9;
				var boardHeight = game.height * .9;
				var gemsPerRow = 6;
				var gemsPerColumn = 8;
				var totalMarginWidth = margin * (gemsPerRow + 1);
				var totalMarginHeight = margin * (gemsPerColumn + 1);
				var availableWidth = boardWidth - totalMarginWidth;
				var availableHeight = boardHeight - totalMarginHeight;
				var scaledGemSize = Math.min(availableWidth / gemsPerRow, availableHeight / gemsPerColumn);
				var xOffset = (game.width - boardWidth) / 2 + scaledGemSize / 2;
				var yOffset = (game.height - boardHeight) / 2 + scaledGemSize / 2;
				gem.spacing = scaledGemSize + margin;
				self.spacing = gem.spacing;
				var snappedPos = self.snapToGrid(xOffset + (scaledGemSize + margin) * j, yOffset + (scaledGemSize + margin) * i);
				gem.x = snappedPos.x;
				gem.y = snappedPos.y;
				gem.scale.set(scaledGemSize / gemSize);
				gem.scale.set(scaledGemSize / gemSize);
				gem.baseScale = scaledGemSize / gemSize;
				self.addChild(gem);
				self.gems.push(gem);
				self.handleGemClick(gem);
			}
		}
		self.comboMultiplier = 1; // Initialize combo multiplier
		self.checkForMatches();
	};
});
// ChineseRedEnvelope class
var ChineseRedEnvelope = Container.expand(function () {
	var self = Container.call(this);
	var envelopeGraphics = self.attachAsset('redEnvelope', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.init = function (x, y) {
		self.x = x;
		self.y = y;
		var scaleAnimation = function scaleAnimation() {
			var scaleUp = true;
			var scaleValue = 1;
			LK.setInterval(function () {
				if (scaleUp) {
					scaleValue += 0.01;
				} else {
					scaleValue -= 0.01;
				}
				if (scaleValue >= 1.1) {
					scaleUp = false;
				}
				if (scaleValue <= 1) {
					scaleUp = true;
				}
				self.scale.set(scaleValue * 2.0); // Make the envelope significantly larger
			}, 100);
		};
		scaleAnimation();
		self.on('down', function () {
			var targetX = timerTxt.x;
			var targetY = timerTxt.y;
			var moveDuration = 1000; // Duration in milliseconds
			var startTime = Date.now();
			var animateMove = function animateMove() {
				var currentTime = Date.now();
				var progress = Math.min(1, (currentTime - startTime) / moveDuration);
				// Apply a quadratic easing for a smooth curve
				var curveProgress = Math.pow(progress, 2);
				self.x = self.x + (targetX - self.x) * curveProgress;
				self.y = self.y - 75 * Math.sin(Math.PI * progress) + (targetY - self.y) * curveProgress; // Add a sine wave pattern for vertical movement
				if (progress < 1) {
					LK.setTimeout(animateMove, 16);
				} else {
					game.timer += 5; // Grant 5 more seconds
					timerTxt.setText(game.timer.toString()); // Update timer display
					self.destroy(); // Remove the envelope after reaching the timer
				}
			};
			animateMove();
		});
		// Initiate continuous glowing effect
		function glowEffect() {
			var glowParticle = new GlowingParticlesForRedEnvelopes(.3);
			glowParticle.init(0, 0);
			self.addChildAt(glowParticle, 0);
		}
		;
		glowEffect();
		//	LK.setInterval(glowEffect, 500); // Add a glowing particle effect every 500ms
	};
});
// ConfettiParticle class
var ConfettiParticle = Container.expand(function () {
	var self = Container.call(this);
	var confettiColors = ['confettiRed', 'confettiBlue', 'confettiGreen', 'confettiYellow', 'confettiPurple'];
	var randomColor = confettiColors[Math.floor(Math.random() * confettiColors.length)];
	var confettiGraphics = self.attachAsset(randomColor, {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.init = function (x, y) {
		self.x = x;
		self.y = y;
		var angle = Math.random() * Math.PI * 2;
		var speed = 0.5 + Math.random(); // Reduced speed for smoother appearance
		var duration = 1500 + Math.random() * 2500; // Extended duration for smoother fade
		var startTime = Date.now();
		var animate = function animate() {
			var currentTime = Date.now();
			var progress = (currentTime - startTime) / duration;
			self.x += Math.cos(angle) * speed;
			self.y += Math.sin(angle) * speed;
			self.alpha = Math.sin(progress * Math.PI); // Smooth in and out fading effect
			if (progress < 1) {
				LK.setTimeout(animate, 16);
			} else {
				self.destroy();
			}
		};
		animate();
	};
});
// Dragon class
var Dragon = Container.expand(function (gem) {
	var self = Container.call(this);
	var dragonGraphics = self.attachAsset('dragon', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	dragonGraphics.anchor.set(1, .7);
	self.speed = 5;
	var hasTakenGem = false;
	self.move = function () {
		var endX = 2048 + self.width; // Ensure dragon ends off-screen to the right
		var startX = -self.width; // Start off-screen to the left
		var travelDistance = endX - startX;
		var travelTime = 3000; // Time in milliseconds for the dragon to cross the screen
		var startTime = Date.now();
		var particleParts = [];
		function animate() {
			var currentTime = Date.now();
			var elapsedTime = currentTime - startTime;
			var progress = elapsedTime / travelTime;
			self.x = startX + travelDistance * progress;
			if (self.x > gem.x && !hasTakenGem) {
				hasTakenGem = true;
				self.addChild(gem);
				// Animate gem scale upon grabbing
				var scaleAnimationDuration = 300; // Duration of the scale animation in milliseconds
				var scaleAnimationStartTime = Date.now();
				var animateGemScale = function animateGemScale() {
					var currentTime = Date.now();
					var progress = Math.min(1, (currentTime - scaleAnimationStartTime) / scaleAnimationDuration);
					gem.scale.set(gem.baseScale * (.8 + .2 * Math.sin(progress * Math.PI * 2))); // Animate scale
					if (progress < 1) {
						LK.setTimeout(animateGemScale, 16);
					} else {
						gem.scale.set(gem.baseScale * .8);
					}
				};
				animateGemScale();
				gem.x = 50;
				gem.y = 0;
				var index = board.gems.indexOf(gem);
				if (index > -1) {
					if (board.gems[index] == gem) {
						board.gems[index] = false;
					}
				}
				LK.setTimeout(function () {
					board.handleFallingGems();
				}, 200);
			}
			if (hasTakenGem) {
				self.addChild(gem);
				//gem.scale.set(gem.baseScale * .8);
				gem.x = 50;
				gem.y = 0;
			}
			// Generate particle trail
			if (progress < 1) {
				LK.setTimeout(animate, 16); // Aim for roughly 60fps
			} else {
				var fadeoutparticle = function fadeoutparticle(particle) {
					// Start fade out effect
					var fadeOutDuration = 500; // Duration for the fade out in milliseconds
					var fadeStartTime = Date.now();
					var fadeStep = function fadeStep() {
						var currentTime = Date.now();
						var progress = (currentTime - fadeStartTime) / fadeOutDuration;
						particle.alpha = 1 - progress; // Fade out
						if (progress < 1) {
							LK.setTimeout(fadeStep, 16);
						} else {
							particle.destroy(); // Destroy particle after fade out
						}
					};
					fadeStep();
				};
				;
				// Spawn a red envelope at a random position
				//var envelope = new ChineseRedEnvelope();
				//envelope.init(Math.random() * game.width, self.y);
				//game.addChild(envelope);
				// Destroy the dragon instance once it crosses the screen
				isDragoning = false;
				particleParts.forEach(function (particle) {
					fadeoutparticle(particle);
				});
				self.destroy();
			}
		}
		animate();
	};
});
// Gem class
var Gem = Container.expand(function (color) {
	var self = Container.call(this);
	self.scaleUpAndDown = function (delay) {
		LK.setTimeout(function () {
			var scaleUpDuration = 150; // Duration to scale up in milliseconds
			var scaleDownDuration = 150; // Duration to scale down in milliseconds
			var maxScale = self.baseScale * 1.3; // Maximum scale factor
			var originalScale = self.baseScale; // Remember the original scale
			var scaleUp = function scaleUp() {
				var startTime = Date.now();
				var scaleStep = function scaleStep() {
					var currentTime = Date.now();
					var progress = Math.min(1, (currentTime - startTime) / scaleUpDuration);
					self.scale.set(originalScale + (maxScale - originalScale) * progress);
					if (progress < 1) {
						LK.setTimeout(scaleStep, 16);
					} else {
						scaleDown();
					}
				};
				scaleStep();
			};
			var scaleDown = function scaleDown() {
				var startTime = Date.now();
				var scaleStep = function scaleStep() {
					var currentTime = Date.now();
					var progress = Math.min(1, (currentTime - startTime) / scaleDownDuration);
					self.scale.set(maxScale - (maxScale - originalScale) * progress);
					if (progress < 1) {
						LK.setTimeout(scaleStep, 16);
					}
				};
				scaleStep();
			};
			scaleUp();
		}, delay);
	};
	self.scaleUpAndDisappear = function scaleUpAndDisappear() {
		var scaleUpDuration = 100; // Duration to scale up in milliseconds
		var scaleDownDuration = 200; // Duration to scale down to zero
		var maxScale = self.baseScale * 1.2; // Maximum scale factor
		var disappearScale = 0; // Scale factor to disappear
		var originalScale = self.baseScale; // Remember the original scale
		// Animate scale up
		// Start scale up
		var scaleUpDuration = 100; // Duration to scale up in milliseconds
		var disappearDuration = 200; // Duration to scale down to zero
		var maxScale = self.baseScale * 1.2; // Maximum scale factor
		var disappearScale = 0; // Scale factor to disappear
		var originalScale = self.baseScale; // Remember the original scale
		// Animate scale up
		var startTime = Date.now();
		var _scaleStep2 = function _scaleStep() {
			var currentTime = Date.now();
			var progress = Math.min(1, (currentTime - startTime) / scaleUpDuration);
			self.scale.set(originalScale + (maxScale - originalScale) * progress);
			if (progress < 1) {
				LK.setTimeout(_scaleStep2, 16);
			} else {
				// Once scaled up, start disappearing
				startTime = Date.now();
				_scaleStep2 = function scaleStep() {
					var currentTime = Date.now();
					var progress = Math.min(1, (currentTime - startTime) / disappearDuration);
					self.scale.set(maxScale - (maxScale - disappearScale) * progress);
					if (progress < 1) {
						LK.setTimeout(_scaleStep2, 16);
					} else {
						self.destroy();
					}
				};
				_scaleStep2();
			}
		};
		_scaleStep2();
	};
	var gemGraphics = self.attachAsset(color, {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.color = color;
	self.isSelected = false;
	self.toggleSelect = function () {
		self.isSelected = !self.isSelected;
		if (self.isSelected) {
			gemGraphics.alpha = 0.5;
			self.scale.set(self.baseScale * 1.1);
		} else {
			gemGraphics.alpha = 1;
			self.scale.set(self.baseScale);
		}
	};
});
// GlowingParticles class enhancement
var GlowingParticles = Container.expand(function () {
	var self = Container.call(this);
	scaleMultiplier = 1;
	var _animateParticle = function animateParticle(particle) {
		var currentTime = Date.now();
		var elapsedTime = currentTime - particle.startTime;
		var progress = elapsedTime / particle.duration;
		if (progress < 1) {
			particle.x += Math.cos(particle.angle) * particle.speed;
			particle.y += Math.sin(particle.angle) * particle.speed;
			particle.alpha = Math.cos(progress * Math.PI); // Smooth in and out fading effect
			particle.rotation += particle.rotationVelocity; // Add rotation to each particle
			LK.setTimeout(function () {
				_animateParticle(particle);
			}, 16);
		} else {
			particle.destroy();
		}
	};
	self.init = function (x, y) {
		for (var i = 0; i < 50; i++) {
			var particle = self.attachAsset('glowEffect', {
				x: x,
				y: y,
				anchorX: 0.5,
				anchorY: 0.5
			});
			particle.blendMode = 1;
			particle.angle = Math.random() * Math.PI * 2; // Random angle for direction
			particle.speed = 1 + Math.random() * 2.5; // Adjusted speed for varied particle movement
			particle.duration = 500 + Math.random() * 1000; // Keeping the duration dynamic
			// Introduce gravity effect to some particles
			for (var i = 0; i < 50; i++) {
				var particle = self.attachAsset('glowEffect', {
					x: x,
					y: y,
					anchorX: 0.5,
					anchorY: 0.5
				});
				particle.blendMode = 1;
				particle.angle = Math.random() * Math.PI * 2; // Random angle for direction
				particle.speed = 1 + Math.random() * 2.5; // Adjusted speed for varied particle movement
				particle.duration = 500 + Math.random() * 1000; // Keeping the duration dynamic
				particle.gravity = Math.random() > 0.5 ? 0.01 : 0; // Half the particles have a gravity effect
				particle.targetScale = 0.5 + Math.random() * 1.5; // Varied scale for more visual variety
				particle.scale.set(particle.targetScale * scaleMultiplier); // Initial scale set based on the random scale variable
				particle.startTime = Date.now();
				particle.rotationVelocity = -0.1 + Math.random() * .2;
				particle.x += Math.cos(particle.angle) * Math.random() * 80;
				particle.y += Math.sin(particle.angle) * Math.random() * 80;
				_animateParticle(particle);
			}
			particle.targetScale = 0.5 + Math.random() * 1.5; // Varied scale for more visual variety
			particle.scale.set(particle.targetScale * scaleMultiplier); // Initial scale set based on the random scale variable
			particle.startTime = Date.now();
			particle.rotationVelocity = -0.1 + Math.random() * .2;
			particle.x += Math.cos(particle.angle) * Math.random() * 80;
			particle.y += Math.sin(particle.angle) * Math.random() * 80;
			_animateParticle(particle);
		}
	};
});
// Define the GlowingParticlesForRedEnvelope class
var GlowingParticlesForRedEnvelope = Container.expand(function (scaleMultiplier) {
	var self = Container.call(this);
	var _animateParticle = function animateParticle(particle) {
		var currentTime = Date.now();
		var elapsedTime = currentTime - particle.startTime;
		var progress = elapsedTime / particle.duration;
		if (progress < 1) {
			// Update particle properties for movement, fading, and rotation
			particle.x += Math.cos(particle.angle) * particle.speed;
			particle.y += Math.sin(particle.angle) * particle.speed;
			particle.alpha = Math.cos(progress * Math.PI); // Fading effect
			particle.rotation += particle.rotationVelocity;
		} else {
			// Reset particle to create a continuous effect
			particle.startTime = Date.now(); // Reset start time
			// Optionally, re-randomize properties for varied continuous effect
			particle.angle = Math.random() * Math.PI * 2;
			particle.speed = 1 + Math.random() * 1.5;
			particle.duration = 500 + Math.random() * 1000;
			particle.rotationVelocity = -0.1 + Math.random() * 0.2;
			particle.x = particle.initialX + Math.cos(particle.angle) * Math.random() * 50;
			particle.y = particle.initialY + Math.sin(particle.angle) * Math.random() * 50;
		}
		LK.setTimeout(function () {
			_animateParticle(particle);
		}, 16); // Continue animation loop
	};
	self.init = function (x, y) {
		for (var i = 0; i < 50; i++) {
			var particle = self.attachAsset('glowEffect', {
				x: x,
				y: y,
				anchorX: 0.5,
				anchorY: 0.5
			});
			particle.blendMode = 1;
			particle.alpha = 0;
			particle.initialX = x; // Store initial position
			particle.initialY = y;
			particle.angle = Math.random() * Math.PI * 2;
			particle.speed = 1 + Math.random() * 1.5;
			particle.duration = 500 + Math.random() * 1000;
			particle.targetScale = 0.5 + Math.random() * 1.5;
			particle.scale.set(particle.targetScale * scaleMultiplier);
			particle.startTime = Date.now();
			particle.rotationVelocity = -0.1 + Math.random() * 0.2;
			particle.x += Math.cos(particle.angle) * Math.random() * 70;
			particle.y += Math.sin(particle.angle) * Math.random() * 70;
			_animateParticle(particle);
		}
	};
});
var GlowingParticlesForRedEnvelopes = Container.expand(function (scaleMultiplier) {
	var self = Container.call(this);
	var _animateParticle = function animateParticle(particle) {
		var currentTime = Date.now();
		var elapsedTime = currentTime - particle.startTime;
		var progress = elapsedTime / particle.duration;
		if (progress < 1) {
			// Update particle properties for movement, fading, and rotation
			particle.x += Math.cos(particle.angle) * particle.speed;
			particle.y += Math.sin(particle.angle) * particle.speed;
			particle.alpha = Math.cos(progress * Math.PI); // Fading effect
			particle.rotation += particle.rotationVelocity;
		} else {
			// Reset particle to create a continuous effect
			particle.startTime = Date.now(); // Reset start time
			// Optionally, re-randomize properties for varied continuous effect
			particle.angle = Math.random() * Math.PI * 2;
			particle.speed = 1 + Math.random() * 1.5;
			particle.duration = 500 + Math.random() * 1000;
			particle.rotationVelocity = -0.1 + Math.random() * 0.2;
			particle.x = particle.initialX + Math.cos(particle.angle) * Math.random() * 50;
			particle.y = particle.initialY + Math.sin(particle.angle) * Math.random() * 50;
		}
		LK.setTimeout(function () {
			_animateParticle(particle);
		}, 16); // Continue animation loop
	};
	self.init = function (x, y) {
		for (var i = 0; i < 50; i++) {
			var particle = self.attachAsset('glowEffect', {
				x: x,
				y: y,
				anchorX: 0.5,
				anchorY: 0.5
			});
			particle.blendMode = 1;
			particle.alpha = 0;
			particle.initialX = x; // Store initial position
			particle.initialY = y;
			particle.angle = Math.random() * Math.PI * 2;
			particle.speed = 1 + Math.random() * 1.5;
			particle.duration = 500 + Math.random() * 1000;
			particle.targetScale = 0.5 + Math.random() * 1.5;
			particle.scale.set(particle.targetScale * scaleMultiplier);
			particle.startTime = Date.now();
			particle.rotationVelocity = -0.1 + Math.random() * 0.2;
			particle.x += Math.cos(particle.angle) * Math.random() * 70;
			particle.y += Math.sin(particle.angle) * Math.random() * 70;
			_animateParticle(particle);
		}
	};
});
// LineSprite class
var LineSprite = Container.expand(function () {
	var self = Container.call(this);
	self.updateLine = function (startX, startY, endX, endY) {
		var dx = endX - startX;
		var dy = endY - startY;
		var distance = Math.sqrt(dx * dx + dy * dy);
		self.width = distance;
		self.height = 5; // Fixed height for the line
		self.rotation = Math.atan2(dy, dx);
		self.x = startX + dx / 2;
		self.y = startY + dy / 2;
		self.anchorX = 0.5;
		self.anchorY = 0.5;
	};
});
// RowBlasterGem class
var RowBlasterGem = Container.expand(function (color) {
	var self = Container.call(this);
	var gemGraphics = self.attachAsset(color, {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.color = color;
	// Unique behavior for RowBlasterGem
	self.activate = function () {
		// Logic to blast the entire row
		console.log('Blasting row...');
	};
});
/**** 
* Initialize Game
****/
var game = new LK.Game({
	backgroundColor: 0x000000 // Init game with black background
});
/**** 
* Game Code
****/
// SagaMap class
// SagaMap class
// Dragon spawn timer
// Goal gem type and count
// Initialize large countdown at the beginning of the game
// Initialize score
// Initialize 2-minute timer
// Initialize a timer for showing hints
var SagaMap = /*#__PURE__*/function (_Container) {
	_inherits(SagaMap, _Container);
	function SagaMap() {
		var _this;
		_classCallCheck(this, SagaMap);
		_this = _callSuper(this, SagaMap);
		_this.levels = [];
		_this.currentLevel = 0;
		return _this;
	}
	_createClass(SagaMap, [{
		key: "addLevel",
		value: function addLevel(level) {
			this.levels.push(level);
		}
	}, {
		key: "goToLevel",
		value: function goToLevel(index) {
			this.currentLevel = index;
			// Logic to switch to the specified level
			console.log('Switching to level:', index);
		}
	}, {
		key: "nextLevel",
		value: function nextLevel() {
			if (this.currentLevel < this.levels.length - 1) {
				this.goToLevel(this.currentLevel + 1);
			} else {
				console.log('No more levels!');
			}
		}
	}]);
	return SagaMap;
}(Container);
function _typeof2(o) {
	"@babel/helpers - typeof";
	return _typeof2 = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
		return typeof o;
	} : function (o) {
		return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
	}, _typeof2(o);
}
function _classCallCheck(instance, Constructor) {
	if (!(instance instanceof Constructor)) {
		throw new TypeError("Cannot call a class as a function");
	}
}
function _defineProperties(target, props) {
	for (var i = 0; i < props.length; i++) {
		var descriptor = props[i];
		descriptor.enumerable = descriptor.enumerable || false;
		descriptor.configurable = true;
		if ("value" in descriptor) {
			descriptor.writable = true;
		}
		Object.defineProperty(target, _toPropertyKey2(descriptor.key), descriptor);
	}
}
function _createClass(Constructor, protoProps, staticProps) {
	if (protoProps) {
		_defineProperties(Constructor.prototype, protoProps);
	}
	if (staticProps) {
		_defineProperties(Constructor, staticProps);
	}
	Object.defineProperty(Constructor, "prototype", {
		writable: false
	});
	return Constructor;
}
function _toPropertyKey2(t) {
	var i = _toPrimitive2(t, "string");
	return "symbol" == _typeof2(i) ? i : String(i);
}
function _toPrimitive2(t, r) {
	if ("object" != _typeof2(t) || !t) {
		return t;
	}
	var e = t[Symbol.toPrimitive];
	if (void 0 !== e) {
		var i = e.call(t, r || "default");
		if ("object" != _typeof2(i)) {
			return i;
		}
		throw new TypeError("@@toPrimitive must return a primitive value.");
	}
	return ("string" === r ? String : Number)(t);
}
function _callSuper(t, o, e) {
	return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e));
}
function _possibleConstructorReturn(self, call) {
	if (call && (_typeof2(call) === "object" || typeof call === "function")) {
		return call;
	} else if (call !== void 0) {
		throw new TypeError("Derived constructors may only return object or undefined");
	}
	return _assertThisInitialized(self);
}
function _assertThisInitialized(self) {
	if (self === void 0) {
		throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
	}
	return self;
}
function _isNativeReflectConstruct() {
	try {
		var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
	} catch (t) {}
	return (_isNativeReflectConstruct = function _isNativeReflectConstruct() {
		return !!t;
	})();
}
function _getPrototypeOf(o) {
	_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) {
		return o.__proto__ || Object.getPrototypeOf(o);
	};
	return _getPrototypeOf(o);
}
function _inherits(subClass, superClass) {
	if (typeof superClass !== "function" && superClass !== null) {
		throw new TypeError("Super expression must either be null or a function");
	}
	subClass.prototype = Object.create(superClass && superClass.prototype, {
		constructor: {
			value: subClass,
			writable: true,
			configurable: true
		}
	});
	Object.defineProperty(subClass, "prototype", {
		writable: false
	});
	if (superClass) {
		_setPrototypeOf(subClass, superClass);
	}
}
function _setPrototypeOf(o, p) {
	_setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) {
		o.__proto__ = p;
		return o;
	};
	return _setPrototypeOf(o, p);
}
var SagaMap = /*#__PURE__*/function (_Container) {
	_inherits(SagaMap, _Container);
	function SagaMap() {
		var _this;
		_classCallCheck(this, SagaMap);
		_this = _callSuper(this, SagaMap);
		_this.levels = [];
		_this.currentLevel = 0;
		return _this;
	}
	_createClass(SagaMap, [{
		key: "addLevel",
		value: function addLevel(level) {
			this.levels.push(level);
		}
	}, {
		key: "goToLevel",
		value: function goToLevel(index) {
			this.currentLevel = index;
			// Logic to switch to the specified level
			console.log('Switching to level:', index);
		}
	}, {
		key: "nextLevel",
		value: function nextLevel() {
			if (this.currentLevel < this.levels.length - 1) {
				this.goToLevel(this.currentLevel + 1);
			} else {
				console.log('No more levels!');
			}
		}
	}]);
	return SagaMap;
}(Container);
var dragonSpawnTimer;
var isDragoning = false;
function triggerDragon() {
	if (dragonSpawnTimer) {
		LK.clearTimeout(dragonSpawnTimer);
	}
	if (!isDragoning && board && board.gems && board.gems.length > 0) {
		isDragoning = true;
		var randomIndex = Math.floor(Math.random() * board.gems.length);
		var gemToRemove = board.gems[randomIndex];
		if (gemToRemove) {
			var dragon = new Dragon(gemToRemove);
			dragon.x = -100; // Ensure dragon starts off-screen to the left
			dragon.y = gemToRemove.y; // Random y position within game bounds
			game.addChild(dragon);
			dragon.move();
		}
	}
	var nextSpawnTime = 5000 + Math.random() * 10000; // Random interval between 5 to 15 seconds
	dragonSpawnTimer = LK.setTimeout(triggerDragon, nextSpawnTime);
}
triggerDragon();
var goalGemType;
var matchedGemCount = 0;
var hintTimer;
var currentGoalGemSprite = false;
var goalLevel = 0;
// Function to randomly set the goal gem type from the available gem colors
function setRandomGoalGemType() {
	var gemColors = ['gemBlue', 'gemGreen', 'gemRed', 'gemPurple', 'gemYellow', 'gemOrange', 'gemCyan'];
	goalGemType = gemColors[Math.floor(Math.random() * gemColors.length)];
	goalGemCount = 3 + Math.floor(Math.random() * goalLevel);
	matchedGemCount = 0;
	LK.setTimeout(function () {
		// Update the goal text with the chosen gem type
		goalTxt.setText(matchedGemCount + '/' + goalGemCount);
		// Add hourglass sprite next to the timer
		if (currentGoalGemSprite) {
			currentGoalGemSprite.destroy();
		}
		currentGoalGemSprite = LK.getAsset(goalGemType, {
			x: 2048 - 100,
			// Position next to the timer
			y: 50,
			// Align with the timer's top margin
			anchorX: .5,
			// Anchor right for right alignment
			anchorY: .5 // Anchor top for top alignment
		});
		currentGoalGemSprite.y = goalTxt.y;
		currentGoalGemSprite.x = goalBackground.x; // Position next to the timer
		currentGoalGemSprite.anchor.set(0.5, 0.5); // Align with the timer's top margin
		currentGoalGemSprite.rotation = -.2;
		currentGoalGemSprite.scale.set(1.6);
		if (goalBackground.parent) {
			goalBackground.parent.removeChild(goalBackground);
		}
		if (goalTxt.parent) {
			goalTxt.parent.removeChild(goalTxt);
		}
		if (currentGoalGemSprite.parent) {
			currentGoalGemSprite.parent.removeChild(currentGoalGemSprite);
		}
		LK.setTimeout(function () {
			board.addChild(goalBackground);
			game.addChild(goalBackground);
			game.addChild(goalTxt);
			game.addChild(currentGoalGemSprite);
		}, 1000);
	}, 1000);
}
// setRandomGoalGemType(); // Initialize the goal gem type at the start of the game
// This call has been moved to after the definition of goalTxt to fix the bug
// Function to reset and start the hint timer
function resetHintTimer() {
	if (hintTimer) {
		LK.clearTimeout(hintTimer);
	}
	hintTimer = LK.setTimeout(function () {
		board.showHint();
		resetHintTimer();
	}, 5000); // Show hint after 5 seconds of inactivity
}
resetHintTimer();
// Reset the hint timer whenever a move is made
LK.on('tick', function () {
	// This is a placeholder for any game action, e.g., gem swap, that resets the hint timer
	// resetHintTimer();
});
function _typeof(o) {
	"@babel/helpers - typeof";
	return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
		return typeof o;
	} : function (o) {
		return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
	}, _typeof(o);
}
function _defineProperty(obj, key, value) {
	key = _toPropertyKey(key);
	if (key in obj) {
		Object.defineProperty(obj, key, {
			value: value,
			enumerable: true,
			configurable: true,
			writable: true
		});
	} else {
		obj[key] = value;
	}
	return obj;
}
function _toPropertyKey(t) {
	var i = _toPrimitive(t, "string");
	return "symbol" == _typeof(i) ? i : String(i);
}
function _toPrimitive(t, r) {
	if ("object" != _typeof(t) || !t) {
		return t;
	}
	var e = t[Symbol.toPrimitive];
	if (void 0 !== e) {
		var i = e.call(t, r || "default");
		if ("object" != _typeof(i)) {
			return i;
		}
		throw new TypeError("@@toPrimitive must return a primitive value.");
	}
	return ("string" === r ? String : Number)(t);
}
var countdownValue = 3; // Start countdown from 3
var countdownTxt = new Text2(countdownValue.toString(), {
	size: 300,
	fill: "#ffffff",
	x: 1024,
	// Center of the screen
	y: 1366,
	// Middle of the screen
	anchorX: 0.5,
	anchorY: 0.5,
	stroke: true,
	weight: 800,
	dropShadow: true
});
countdownTxt.anchor.set(.5);
LK.gui.center.addChild(countdownTxt); // Add countdown display to the center GUI layer
var countdownInterval = LK.setInterval(function () {
	countdownValue -= 1;
	if (countdownValue > 0) {
		countdownTxt.setText(countdownValue.toString());
		// Bounce effect for countdown numbers
		var scaleUpDuration = 100; // Duration to scale up in milliseconds
		var scaleDownDuration = 100; // Duration to scale down in milliseconds
		var maxScale = 1.2; // Maximum scale factor
		var originalScale = 1; // Remember the original scale
		var scaleUp = function scaleUp() {
			var startTime = Date.now();
			var scaleStep = function scaleStep() {
				var currentTime = Date.now();
				var progress = Math.min(1, (currentTime - startTime) / scaleUpDuration);
				countdownTxt.scale.set(originalScale + (maxScale - originalScale) * progress);
				if (progress < 1) {
					LK.setTimeout(scaleStep, 16);
				} else {
					scaleDown();
				}
			};
			scaleStep();
		};
		var scaleDown = function scaleDown() {
			var startTime = Date.now();
			var scaleStep = function scaleStep() {
				var currentTime = Date.now();
				var progress = Math.min(1, (currentTime - startTime) / scaleDownDuration);
				countdownTxt.scale.set(maxScale - (maxScale - originalScale) * progress);
				if (progress < 1) {
					LK.setTimeout(scaleStep, 16);
				}
			};
			scaleStep();
		};
		scaleUp();
	} else if (countdownValue === 0) {
		countdownTxt.setText('GO!');
		spinHourglass();
		// Bounce effect
		var scaleUpDuration = 200; // Duration to scale up in milliseconds
		var scaleDownDuration = 200; // Duration to scale down in milliseconds
		var maxScale = 1.5; // Maximum scale factor
		var originalScale = 1; // Remember the original scale
		var scaleUp = function scaleUp() {
			var startTime = Date.now();
			var scaleStep = function scaleStep() {
				var currentTime = Date.now();
				var progress = Math.min(1, (currentTime - startTime) / scaleUpDuration);
				countdownTxt.scale.set(originalScale + (maxScale - originalScale) * progress);
				if (progress < 1) {
					LK.setTimeout(scaleStep, 16);
				} else {
					scaleDown();
				}
			};
			scaleStep();
		};
		var scaleDown = function scaleDown() {
			var fadeOutDuration = 500; // Duration for the fade out in milliseconds
			var startTime = Date.now();
			var fadeStep = function fadeStep() {
				var currentTime = Date.now();
				var progress = Math.min(1, (currentTime - startTime) / fadeOutDuration);
				countdownTxt.alpha = 1 - progress; // Fade out
				if (progress < 1) {
					LK.setTimeout(fadeStep, 16);
				} else {
					countdownTxt.destroy(); // Remove countdown text after animation
					LK.clearInterval(countdownInterval);
					setRandomGoalGemType();
				}
			};
			fadeStep();
		};
		scaleUp();
	}
}, 1000); // Update countdown every second
game.timer = 120; // 2 minutes in seconds
// Implement a three second delay before starting the timer text interval
LK.setTimeout(function () {
	// Timer control is now handled inside the modal display logic to pause during the modal display.
}, 3000);
var score = 0; // Starting score
var scoreBg;
var scoreBgNode = LK.getAsset('scoreBg', {
	x: 1024 - 150,
	// Centered based on the background size
	y: 0,
	anchorX: 0.5,
	anchorY: 0
});
scoreBgNode.anchor.set(.5);
scoreBgNode.y = 50;
scoreBgNode.alpha = 1; // Set the background transparency to fully opaque to ensure visibility
LK.gui.top.addChild(scoreBgNode);
var scoreTxt = new Text2(score.toString(), _defineProperty(_defineProperty({
	size: 110,
	weight: 500,
	fill: "#ffffff",
	x: 1024,
	// Center of the screen
	y: 0,
	// Adjusted to be within the background
	anchorX: 0.5,
	// Center horizontally
	anchorY: 0,
	// Anchor at the top
	dropShadow: true,
	dropShadowColor: '#000000',
	shadowBlur: 4,
	shadowOffsetX: 2,
	shadowOffsetY: 2,
	stroke: true,
	strokeColor: '#000000'
}, "stroke", '#000000'), "strokeThickness", 7));
scoreTxt.anchor.set(.5, .5);
scoreTxt.y = 50;
LK.gui.top.addChild(scoreTxt); // Add score display to the top GUI layer
// List of background images for different goal levels
var backgroundImages = ['magicalBackground', 'enchantedForest', 'mysticCave', 'celestialRealm'];
// Function to update the game background according to the current goal level
function updateBackground() {
	var backgroundImageId = backgroundImages[goalLevel % backgroundImages.length];
	var oldBackground = game.background;
	if (oldBackground) {
		LK.setTimeout(function () {
			oldBackground.destroy();
		}, 1000);
	}
	var background = LK.getAsset(backgroundImageId, {
		anchorX: 0.5,
		anchorY: 0.5
	});
	background.x = game.width / 2;
	background.y = game.height / 2;
	background.scale.set(Math.max(game.height / background.height, game.width / background.width));
	background.alpha = 0; // Start fully transparent
	var fadeInDuration = 1000; // Duration for the fade in milliseconds
	var fadeInStartTime = Date.now();
	var fadeInStep = function fadeInStep() {
		var currentTime = Date.now();
		var progress = (currentTime - fadeInStartTime) / fadeInDuration;
		background.alpha = progress; // Fade in
		if (progress < 1) {
			LK.setTimeout(fadeInStep, 16);
		} else {
			background.alpha = 1;
			if (oldBackground) {}
		}
	};
	fadeInStep();
	// This line is removed to prevent script errors related to incorrect usage of addChildAt.
	// Instead, we'll use addChild and manage layering through careful addition order.
	game.addChildAt(background, Math.min(1, game.children.length));
	game.background = background;
}
// Initially set the background
updateBackground();
// Add the game board background to the game
var gameBoardBg = game.addChild(LK.getAsset('gameBoardBg', {
	x: 0,
	y: 0,
	anchorX: 0,
	anchorY: 0
}));
gameBoardBg.width = game.width * 0.9;
gameBoardBg.height = game.height * 0.9;
gameBoardBg.x = (game.width - gameBoardBg.width) / 2;
gameBoardBg.y = (game.height - gameBoardBg.height) / 2 + 80;
gameBoardBg.alpha = 0.6; // Set the background transparency to make it slightly visible
// Initialize the board
// Define assets for the game
var board = new Board();
game.addChild(board);
board.initBoard();
function animateGemsInWave(board) {
	for (var i = 0; i < 8; i++) {
		for (var j = 0; j < 6; j++) {
			var gem = board.gems[i * 6 + j];
			if (gem && typeof gem.scaleUpAndDown === 'function') {
				gem.scaleUpAndDown((i + j) * 50);
			}
		}
	}
}
animateGemsInWave(board);
// Game logic
LK.on('tick', function () {
	// Add game logic that needs to run every frame
	// For example, checking for matches, handling animations, etc.
});
// Add a label with the same styling as the timer text, but with the opposite x-coordinate
var goalTxt = new Text2('', {
	size: 100,
	weight: 500,
	fill: "#ffffff",
	x: 0,
	// Opposite x-coordinate
	y: 50,
	anchorX: 0,
	anchorY: 0,
	dropShadow: true,
	dropShadowColor: '#000000',
	shadowBlur: 4,
	shadowOffsetX: 2,
	shadowOffsetY: 2,
	strokeThickness: 7
});
board.addChild(goalTxt);
goalTxt.anchor.set(0, .5);
goalTxt.y = 100;
goalTxt.x = 450;
// Add hourglass sprite next to the timer
var goalBackground = LK.getAsset('goalBackgroundSprite', {
	x: 2048 - 100,
	// Position next to the timer
	y: 50,
	// Align with the timer's top margin
	anchorX: .5,
	// Anchor right for right alignment
	anchorY: .5 // Anchor top for top alignment
});
goalBackground.y = goalTxt.y;
goalBackground.x = goalTxt.x - 100; // Position next to the timer
goalBackground.anchor.set(0.5, 0.5); // Align with the timer's top margin
goalBackground.alpha = .6;
var timerTxt = new Text2(game.timer.toString(), {
	size: 100,
	// Made the text smaller
	weight: 500,
	fill: "#ffffff",
	x: 2048 - 200,
	y: 50,
	anchorX: 1,
	anchorY: 0,
	dropShadow: true,
	dropShadowColor: '#000000',
	shadowBlur: 4,
	shadowOffsetX: 2,
	shadowOffsetY: 2,
	strokeThickness: 7
});
// Add hourglass sprite next to the timer
var hourglassSprite = LK.getAsset('hourglass', {
	x: 2048 - 100,
	// Position next to the timer
	y: 50,
	// Align with the timer's top margin
	anchorX: .5,
	// Anchor right for right alignment
	anchorY: .5 // Anchor top for top alignment
});
function stopTimer() {
	if (board.timerInterval) {
		LK.clearInterval(board.timerInterval);
	}
}
function startTimer() {
	// Resume the game timer after the modal disappears
	stopTimer();
	board.timerInterval = LK.setInterval(function () {
		game.timer -= 1;
		timerTxt.setText(game.timer.toString());
		if (game.timer <= 0) {
			LK.showGameOver('Final Score: ' + score);
		}
	}, 1000);
}
// Logic to spin the hourglass
var spinHourglass = function spinHourglass() {
	var rotationDuration = 500; // Duration of the spin in milliseconds
	var startTime = Date.now();
	var spinStep = function spinStep() {
		var currentTime = Date.now();
		var progress = (currentTime - startTime) / rotationDuration;
		hourglassSprite.rotation = progress * 2 * Math.PI; // Complete rotation
		if (progress < 1) {
			LK.setTimeout(spinStep, 16); // Aim for roughly 60fps
		} else {
			hourglassSprite.rotation = 0;
			startTimer();
		}
	};
	spinStep();
};
board.addChild(hourglassSprite);
timerTxt.anchor.set(1, .5);
timerTxt.y = 100;
timerTxt.x = 2048 - 240;
board.addChild(timerTxt); // Add timer display to the top GUI layer
hourglassSprite.y = timerTxt.y;
hourglassSprite.x = timerTxt.x + 70; // Position next to the timer
hourglassSprite.anchor.set(0.5, 0.5); // Align with the timer's top margin /**** 
* Classes
****/
// Board class
var Board = Container.expand(function () {
	var self = Container.call(this);
	// Function to shuffle gems around randomly
	Board.prototype.shuffleGems = function () {
		console.log("shuffleGems");
		self.isShuffling = true;
		// Removed usage of Set for compatibility
		for (var i = this.gems.length - 1; i > 0; i--) {
			this.gems[i].newPosition = false;
		}
		for (var i = this.gems.length - 1; i > 0; i--) {
			var j = Math.floor(Math.random() * (i + 1));
			// Swap the gems
			var tempNewPosition = this.gems[i].newPosition || {
				x: this.gems[i].x,
				y: this.gems[i].y
			};
			this.gems[i].newPosition = this.gems[j].newPosition || {
				x: this.gems[j].x,
				y: this.gems[j].y
			};
			this.gems[j].newPosition = tempNewPosition;
		}
		// The rest of your method remains unchanged
		function animateGemToPosition(gem, x, y) {
			var animationDuration = 1000; // Duration of the animation in milliseconds
			var startX = gem.x;
			var startY = gem.y;
			var deltaX = x - startX;
			var deltaY = y - startY;
			var startTime = Date.now();
			var animate = function animate() {
				var now = Date.now();
				var progress = Math.min(1, (now - startTime) / animationDuration);
				gem.x = startX + deltaX * progress;
				gem.y = startY + deltaY * progress;
				if (progress < 1) {
					LK.setTimeout(animate, 16); // Aim for roughly 60fps
				} else {
					gem.x = x;
					gem.y = y;
					self.isShuffling = false;
				}
			};
			LK.setTimeout(animate, 16);
		}
		// Update the positions of the shuffled gems and ensure they have the correct new position in the gems array
		var newGemsArray = new Array(this.gems.length);
		this.gems.forEach(function (gem, index) {
			if (gem.newPosition) {
				var newPositionIndex = this.gems.findIndex(function (g) {
					return g.x === gem.newPosition.x && g.y === gem.newPosition.y;
				});
				var aNewPosition = this.snapToGrid(gem.newPosition.x, gem.newPosition.y);
				animateGemToPosition(gem, aNewPosition.x, aNewPosition.y);
				newGemsArray[newPositionIndex] = gem;
			}
		}.bind(this));
		this.gems = newGemsArray.filter(function (g) {
			return g !== undefined;
		});
		LK.setTimeout(self.checkForMatches, 1000);
	};
	// Method to round or snap any position to the nearest position in the grid made by the 6x8 gems
	this.snapToGrid = function (x, y) {
		// Ensure there is at least one gem in the array before accessing its properties
		var margin = 10;
		var boardWidth = game.width * .9;
		var boardHeight = game.height * .9;
		var gemsPerRow = 6;
		var gemsPerColumn = 8;
		var totalMarginWidth = margin * (gemsPerRow + 1);
		var totalMarginHeight = margin * (gemsPerColumn + 1);
		var availableWidth = boardWidth - totalMarginWidth;
		var availableHeight = boardHeight - totalMarginHeight;
		var scaledGemSize = Math.min(availableWidth / gemsPerRow, availableHeight / gemsPerColumn);
		var xOffset = (game.width - boardWidth) / 2 + scaledGemSize / 2;
		var yOffset = (game.height - boardHeight) / 2 + scaledGemSize / 2 + 80;
		var columnWidth = (boardWidth - margin) / 6;
		var rowHeight = (boardHeight - margin) / 8;
		var snappedX = Math.round((x - xOffset) / columnWidth) * columnWidth + xOffset;
		var snappedY = Math.round((y - yOffset) / rowHeight) * rowHeight + yOffset;
		return {
			x: snappedX,
			y: snappedY
		};
	};
	// Method to show a hint for a possible match
	this.showHint = function () {
		console.log('showHint function started');
		var possibleMatches = this.checkIfAnyMoveCausesMatch();
		if (possibleMatches.length > 0) {
			var animateMove = function animateMove(repeatCount) {
				if (move.gem.isUsed) {
					// Start fade-out effect for hint overlay
					var fadeOutDuration = 500; // Fade out over 500ms
					var startTime = Date.now();
					var fadeStep = function fadeStep() {
						var currentTime = Date.now();
						var progress = (currentTime - startTime) / fadeOutDuration;
						hintOverlay.alpha = 1 - progress; // Fade out effect
						if (progress < 1) {
							LK.setTimeout(fadeStep, 16); // Continue fading
						} else {
							hintOverlay.destroy(); // Destroy after faded out
						}
					};
					fadeStep();
					return;
				}
				var totalDuration = 1000; // Half a second for each back and forth movement
				var repeatLimit = 1; // Repeat the animation three times
				var animationCount = 0;
				var startTime = Date.now();
				var animateStep = function animateStep() {
					if (move.gem.isUsed || !hintOverlay) {
						if (hintOverlay) {
							hintOverlay.destroy();
						}
						return;
					}
					var currentTime = Date.now();
					var progress = (currentTime - startTime) / totalDuration;
					var waveProgress = (Math.sin(progress * Math.PI * 2) + 1) / 2; // Adjusted to ensure it never goes below zero
					hintOverlay.x = move.gemStartPosition.x + moveDirection.dx * moveDistance * waveProgress;
					hintOverlay.y = move.gemStartPosition.y + moveDirection.dy * moveDistance * waveProgress;
					if (progress >= 1) {
						animationCount++;
						if (animationCount < repeatLimit) {
							startTime = Date.now(); // Reset start time for the next cycle
							animateStep(); // Continue animation
						} else {
							hintOverlay.destroy();
						}
					} else {
						LK.setTimeout(animateStep, 16); // Continue animation
					}
				};
				animateStep();
			};
			console.log('Possible matches:', possibleMatches);
			var move = possibleMatches[0];
			var hintOverlay = LK.getAsset('hintOverlay', {});
			self.lastHintOverlay = hintOverlay;
			hintOverlay.anchor.set(0, 0);
			self.addChild(hintOverlay);
			hintOverlay.x = move.gem.x;
			hintOverlay.y = move.gem.y;
			move.gemStartPosition = {
				x: move.gem.x,
				y: move.gem.y
			}; // Track starting position for animation
			var moveDirection = move.move;
			var moveDistance = move.gem.spacing; // Distance to move back and forth
			var moveDuration = 500; // Duration of each move
			animateMove();
		} else {
			console.log("no possible matches");
			if (!self.fillingEmptySpaces && !self.gemsFalling && !self.isShuffling && !isDragoning) {
				triggerDragon();
			}
		}
	};
	// Method to find possible matches on the board
	// Method to find possible matches on the board
	// Method to find possible matches on the board
	this.findPossibleMatches = function () {
		var matches = [];
		var width = 6; // Board width
		var height = 8; // Board height
		for (var i = 0; i < height; i++) {
			for (var j = 0; j < width; j++) {
				var currentGem = this.gems[i * width + j];
				// Check right and down for potential matches
				var directions = [{
					dx: 1,
					dy: 0
				},
				// Right
				{
					dx: 0,
					dy: 1
				} // Down
				];
				directions.forEach(function (dir) {
					var match = [currentGem];
					for (var k = 1; k < 3; k++) {
						var nextGemX = j + dir.dx * k;
						var nextGemY = i + dir.dy * k;
						if (nextGemX < width && nextGemY < height) {
							var nextGem = this.gems[nextGemY * width + nextGemX];
							if (nextGem && currentGem && nextGem.color === currentGem.color) {
								match.push(nextGem);
							} else {
								break;
							}
						}
					}
					if (match.length >= 3) {
						// Allows for matches longer than 3
						matches.push(match);
					}
				}, this);
			}
		}
		return matches;
	};
	// Method to check if moving any gem results in a match
	this.checkIfAnyMoveCausesMatch = function () {
		var matches = [];
		var width = 6; // Board width
		var height = 8; // Board height
		// Simulate moving each gem in all four directions and check for matches
		for (var i = 0; i < height; i++) {
			for (var j = 0; j < width; j++) {
				var currentGem = this.gems[i * width + j];
				if (!currentGem) {
					continue;
				}
				// Possible moves: up, down, left, right
				var moves = [{
					dx: -1,
					dy: 0
				}, {
					dx: 1,
					dy: 0
				}, {
					dx: 0,
					dy: -1
				}, {
					dx: 0,
					dy: 1
				}];
				moves.forEach(function (move) {
					var newX = j + move.dx;
					var newY = i + move.dy;
					// Check if the new position is within the board
					if (newX >= 0 && newX < width && newY >= 0 && newY < height) {
						var targetGem = this.findGemByPosition(currentGem.x + currentGem.spacing * move.dx, currentGem.y + currentGem.spacing * move.dy);
						if (targetGem && this.wouldSwapResultInMatch(currentGem, targetGem)) {
							matches.push({
								gem: currentGem,
								move: move
							});
						}
					}
				}, this);
			}
		}
		return matches;
	};
	// Check if swapping two gems would result in a match
	this.wouldSwapResultInMatch = function (gemA, gemB) {
		var gemAIndex = this.gems.indexOf(gemA);
		var gemBIndex = this.gems.indexOf(gemB);
		this.gems[gemAIndex] = gemB;
		this.gems[gemBIndex] = gemA;
		// Check for matches
		var matchFound = false;
		var matchedGems = [];
		// Check for horizontal matches
		for (var i = 0; i < 8; i++) {
			for (var j = 0; j < 6; j++) {
				// Adjust to allow checks across all columns
				var gem1 = this.gems[i * 6 + j];
				var nowMatchingGems = [];
				for (var k = j; k < 6; k++) {
					var nextGem = this.gems[i * 6 + k];
					if (nextGem && nextGem.color === gem1.color) {
						nowMatchingGems.push(nextGem);
					} else {
						break;
					}
				}
				if (nowMatchingGems.length >= 3) {
					matchFound = true;
					matchedGems = matchedGems.concat(nowMatchingGems.filter(function (gem) {
						return matchedGems.indexOf(gem) === -1;
					}));
				}
			}
		}
		// Check for vertical matches
		for (var i = 0; i < 6; i++) {
			for (var j = 0; j < 8; j++) {
				// Adjust to allow checks across all rows
				var gem1 = this.gems[j * 6 + i];
				var nowMatchingGems = [];
				for (var k = j; k < 8; k++) {
					var nextGem = this.gems[k * 6 + i];
					if (nextGem && nextGem.color === gem1.color) {
						nowMatchingGems.push(nextGem);
					} else {
						break;
					}
				}
				if (nowMatchingGems.length >= 3) {
					matchFound = true;
					matchedGems = matchedGems.concat(nowMatchingGems.filter(function (gem) {
						return matchedGems.indexOf(gem) === -1;
					}));
				}
			}
		}
		// Swap back
		this.gems[gemAIndex] = gemA;
		this.gems[gemBIndex] = gemB;
		return matchFound;
	};
	this.swapGems = function (gem1, gem2) {
		var gem1Index = this.gems.indexOf(gem1);
		var gem2Index = this.gems.indexOf(gem2);
		if (gem1Index !== -1 && gem2Index !== -1) {
			// Animate swap positions with easing
			var swapDuration = 150; // Duration in milliseconds
			var gem1StartPos = {
				x: gem1.x,
				y: gem1.y
			};
			if (!gem2) {
				return;
			} // Prevent TypeError if gem2 is null
			var gem2StartPos = {
				x: gem2.x,
				y: gem2.y
			};
			gem1.isUsed = true;
			gem2.isUsed = true;
			gem1.alpha = 1;
			gem2.alpha = 1;
			var startTime = Date.now();
			var animateSwap = function animateSwap() {
				var currentTime = Date.now();
				var progress = Math.min(1, (currentTime - startTime) / swapDuration);
				var easeInOut = progress < 0.5 ? 2 * progress * progress : -1 + (4 - 2 * progress) * progress;
				gem1.x = gem1StartPos.x + (gem2StartPos.x - gem1StartPos.x) * easeInOut;
				gem1.y = gem1StartPos.y + (gem2StartPos.y - gem1StartPos.y) * easeInOut;
				gem2.x = gem2StartPos.x + (gem1StartPos.x - gem2StartPos.x) * easeInOut;
				gem2.y = gem2StartPos.y + (gem1StartPos.y - gem2StartPos.y) * easeInOut;
				if (progress < 1) {
					LK.setTimeout(animateSwap, 16); // Aim for roughly 60fps
				} else {
					gem1.isUsed = false;
					gem2.isUsed = false;
					var snappedOne = self.snapToGrid(gem1.x, gem1.y);
					gem1.x = snappedOne.x;
					gem1.y = snappedOne.y;
					var snappedOne = self.snapToGrid(gem2.x, gem2.y);
					gem2.x = snappedOne.x;
					gem2.y = snappedOne.y;
					self.checkForMatches();
				}
			};
			animateSwap();
			// Swap in gems array
			this.gems[gem1Index] = gem2;
			this.gems[gem2Index] = gem1;
			// Check for matches after swap
		}
	};
	this.faintSwapGems = function (gem1, gem2, firstFaint) {
		var gem1Index = this.gems.indexOf(gem1);
		var gem2Index = this.gems.indexOf(gem2);
		if (gem1Index !== -1 && gem2Index !== -1) {
			// Animate swap positions with easing
			var swapDuration = 150; // Duration in milliseconds
			var gem1StartPos = {
				x: gem1.x,
				y: gem1.y
			};
			var gem2StartPos = {
				x: gem2.x,
				y: gem2.y
			};
			var startTime = Date.now();
			var animateSwap = function animateSwap() {
				var currentTime = Date.now();
				var progress = Math.min(1, (currentTime - startTime) / swapDuration);
				var easeInOut = progress < 0.5 ? 2 * progress * progress : -1 + (4 - 2 * progress) * progress;
				gem1.x = gem1StartPos.x + (gem2StartPos.x - gem1StartPos.x) * easeInOut;
				gem1.y = gem1StartPos.y + (gem2StartPos.y - gem1StartPos.y) * easeInOut;
				gem2.x = gem2StartPos.x + (gem1StartPos.x - gem2StartPos.x) * easeInOut;
				gem2.y = gem2StartPos.y + (gem1StartPos.y - gem2StartPos.y) * easeInOut;
				if (progress < 1) {
					LK.setTimeout(animateSwap, 16); // Aim for roughly 60fps
				} else if (firstFaint) {
					self.faintSwapGems(gem1, gem2);
				}
			};
			animateSwap();
			// Swap in gems array
			this.gems[gem1Index] = gem2;
			this.gems[gem2Index] = gem1;
		}
	};
	// Find a gem by its position
	this.findGemByPosition = function (x, y, exceptThisGem) {
		for (var i = 0; i < this.gems.length; i++) {
			var gem = this.gems[i];
			if (gem == exceptThisGem) {
				continue;
			}
			if (gem) {
				var tolerance = gem.spacing / 2; // Tolerance in pixels for approximate position
				if (Math.abs(x - gem.x) < tolerance && Math.abs(y - gem.y) < tolerance) {
					return gem;
				}
			}
		}
		return null;
	};
	this.fillEmptySpaces = function () {
		self.fillingEmptySpaces = true;
		var _animateGemDown = function animateGemDown(newGem, finalY, initialY) {
			var snappedOne = self.snapToGrid(newGem.x, finalY);
			finalY = snappedOne.y;
			var animationDuration = 250; // Duration in milliseconds
			var startTime = Date.now();
			var animate = function animate() {
				var currentTime = Date.now();
				var progress = Math.min(1, (currentTime - startTime) / animationDuration);
				// Apply easing for smoother animation
				var easedProgress = Math.sin(progress * Math.PI / 2);
				if (progress < 1) {
					newGem.y = initialY + (finalY - initialY) * easedProgress;
					LK.setTimeout(animate, 16); // Aim for roughly 60fps
				} else {
					newGem.y = finalY; // Ensure final position is accurate
					self.fillingEmptySpaces = false;
				}
			};
			animate();
		};
		for (var i = 0; i < 8; i++) {
			for (var j = 0; j < 6; j++) {
				var index = i * 6 + j;
				if (!self.gems[index]) {
					var possibleColors = ['gemBlue', 'gemGreen', 'gemRed', 'gemPurple', 'gemYellow', 'gemOrange', 'gemCyan'];
					// Filter colors to ensure at least one possible match
					var colors = possibleColors.filter(function (color) {
						return true;
					}, this);
					var color = colors.length > 0 ? colors[Math.floor(Math.random() * colors.length)] : possibleColors[Math.floor(Math.random() * possibleColors.length)];
					var newGem = new Gem(color);
					// Calculate x and y position for new gems when there are no existing gems to reference
					var gemSize = 100;
					var margin = 10;
					var boardWidth = 1800; // Assuming the board width is known
					var boardHeight = 2400; // Assuming the board height is known
					var gemsPerRow = 6;
					var gemsPerColumn = 8;
					var totalMarginWidth = margin * (gemsPerRow + 1);
					var totalMarginHeight = margin * (gemsPerColumn + 1);
					var availableWidth = boardWidth - totalMarginWidth;
					var availableHeight = boardHeight - totalMarginHeight;
					var scaledGemSize = Math.min(availableWidth / gemsPerRow, availableHeight / gemsPerColumn);
					var xOffset = (2048 - boardWidth) / 2 + scaledGemSize / 2; // Assuming game width is 2048
					var yOffset = (2732 - boardHeight) / 2 + scaledGemSize / 2; // Assuming game height is 2732
					var snapped = self.snapToGrid(xOffset + (scaledGemSize + margin) * j, yOffset + (scaledGemSize + margin) * i);
					newGem.x = snapped.x;
					// Calculate initial y position for animation start
					// Calculate initial y position for animation start
					var initialY = -gemSize; // Start above the screen to simulate falling into place
					newGem.y = initialY;
					// Animate gem to its final position
					var finalY = snapped.y;
					_animateGemDown(newGem, finalY, initialY);
					newGem.spacing = scaledGemSize + margin;
					newGem.scale.set(scaledGemSize / gemSize);
					newGem.baseScale = scaledGemSize / gemSize;
					self.addChild(newGem);
					self.gems[index] = newGem;
					self.handleGemClick(newGem);
				}
			}
		}
	};
	self.gems = [];
	this.handleFallingGems = function () {
		console.log("handle Falling gems");
		var didFall = false;
		for (var i = 0; i < 6; i++) {
			for (var j = 7; j >= 0; j--) {
				var index = j * 6 + i;
				if (index >= 0 && index < self.gems.length && !self.gems[index]) {
					var emptySpaces = 1;
					for (var k = j - 1; k >= 0; k--) {
						var aboveIndex = k * 6 + i;
						if (!self.gems[aboveIndex]) {
							emptySpaces++;
						} else {
							var gemAbove = self.gems[aboveIndex];
							var targetIndex = (k + emptySpaces) * 6 + i;
							self.gems[targetIndex] = gemAbove;
							self.gems[aboveIndex] = null;
							// Calculate the new Y position based on the number of empty spaces
							var margin = 10;
							var snapped = self.snapToGrid(gemAbove.x, gemAbove.y + gemAbove.spacing * emptySpaces);
							var newY = snapped.y;
							// Animate the gem moving to the new position
							gemAbove.alpha = 1;
							animateGemToPosition(gemAbove, gemAbove.x, newY);
							didFall = true;
							break;
						}
					}
				}
			}
		}
		if (didFall) {
			self.gemsFalling = true;
			LK.setTimeout(function () {
				self.fillEmptySpaces();
				LK.setTimeout(function () {
					self.gemsFalling = false;
					self.checkForMatches();
				}, 250);
			}, 250);
		} else {
			// Trigger fillEmptySpaces even if no gems fell to ensure no gaps are left
			self.fillEmptySpaces();
			LK.setTimeout(function () {
				self.checkForMatches();
			}, 250);
		}
	};
	function animateGemToPosition(gem, newX, newY) {
		var fallDuration = 500; // Duration for the gem to fall to its new position
		var bounceDuration = 300; // Duration for the bounce effect, slightly longer for realism
		var scaleDuration = 150; // Duration for the scale effect after bouncing
		var startTime = Date.now();
		var animateStep = function animateStep() {
			var currentTime = Date.now();
			var elapsedTime = currentTime - startTime;
			var progress = elapsedTime / fallDuration;
			// First, handle the falling animation with a linear or ease-in effect
			if (progress < 1) {
				var fallProgress = Math.min(1, progress); // Ensure progress doesn't exceed 1
				// Simple linear interpolation for falling
				gem.y = gem.y + (newY - gem.y) * fallProgress;
				if (fallProgress < 1) {
					LK.setTimeout(animateStep, 16); // Continue the fall animation
				} else {
					gem.y = newY;
					gem.isUsed = false;
				}
			}
		};
		animateStep(); // Start the animation with the fall
	}
	this.handleGemMatched = function (gem) {
		if (gem.color == goalGemType) {
			matchedGemCount++;
			goalTxt.setText(matchedGemCount + "/" + goalGemCount);
			if (matchedGemCount >= goalGemCount) {
				game.timer += 10;
				timerTxt.setText(game.timer.toString());
				stopTimer();
				// Show modal pop-up for 10 more seconds
				var modalContainer = new Container();
				LK.gui.center.addChild(modalContainer);
				var modalBackground = LK.getAsset('goalCompleteBg', {});
				modalBackground.anchor.set(.5, .5);
				modalBackground.alpha = .75;
				modalContainer.addChild(modalBackground);
				// Animate scale of the modal container for excitement
				var scaleStartTime = Date.now();
				var scaleDuration = 500; // Scale animation duration in milliseconds
				var animateScale = function animateScale() {
					var currentTime = Date.now();
					var progress = (currentTime - scaleStartTime) / scaleDuration;
					var scale = 1 + 0.1 * Math.sin(progress * Math.PI * 2); // Oscillate scale between 1 and 1.1
					modalContainer.scale.set(scale);
					if (progress < 1) {
						LK.setTimeout(animateScale, 16);
					}
				};
				animateScale();
				// Trigger lots of confetti balls on mission complete
				for (var i = 0; i < 100; i++) {
					var confetti = new ConfettiParticle();
					confetti.init(Math.random() * game.width, Math.random() * game.height);
					game.addChild(confetti);
				}
				showPastGoalSprite = LK.getAsset(goalGemType, {
					// Align with the timer's top margin
					anchorX: .5,
					// Anchor right for right alignment
					anchorY: .5 // Anchor top for top alignment
				});
				goalGemType = false;
				// Add hourglass sprite next to the timer
				var pastGoalBackground = LK.getAsset('newSpriteId', {});
				pastGoalBackground.y = 0;
				pastGoalBackground.x = -100;
				pastGoalBackground.anchor.set(0.5, 0.5); // Align with the timer's top margin
				modalContainer.addChild(pastGoalBackground);
				pastGoalBackground.alpha = .75;
				showPastGoalSprite.y = pastGoalBackground.y;
				showPastGoalSprite.x = pastGoalBackground.x;
				showPastGoalSprite.anchor.set(.5, 0.5); // Align with the timer's top margin
				modalContainer.addChild(showPastGoalSprite);
				showPastGoalSprite.rotation = -.2;
				var showPastGoalText = new Text2(matchedGemCount + "/" + goalGemCount, {
					size: 100,
					weight: 600,
					fill: "#ffffff",
					x: 1024,
					y: 1366,
					anchorX: 0.5,
					anchorY: 0.5,
					dropShadow: true,
					dropShadowColor: '#000000',
					dropShadowBlur: 8,
					dropShadowOffsetX: 4,
					dropShadowOffsetY: 4,
					stroke: true,
					strokeColor: '#000000',
					strokeThickness: 4
				});
				showPastGoalText.y = pastGoalBackground.y;
				showPastGoalText.x = 0;
				showPastGoalText.anchor.set(0, 0.5); // Align with the timer's top margin
				modalContainer.addChild(showPastGoalText);
				var modalInfoText = new Text2('MISSION COMPLETE:', {
					size: 50,
					weight: 600,
					fill: "#ffffff",
					x: 1024,
					y: 1366,
					anchorX: 0.5,
					anchorY: 0.5,
					dropShadow: true,
					dropShadowColor: '#000000',
					dropShadowBlur: 8,
					dropShadowOffsetX: 4,
					dropShadowOffsetY: 4,
					stroke: true,
					strokeColor: '#000000',
					strokeThickness: 2
				});
				modalInfoText.anchor.set(.5);
				modalInfoText.y = -100;
				modalContainer.addChild(modalInfoText);
				var modalText = new Text2('+10 seconds!', {
					size: 100,
					weight: 600,
					fill: "#ffffff",
					x: 1024 + 70,
					// Adjust x position to make space for the hourglass sprite
					y: 1366,
					anchorX: 0.5,
					anchorY: 0.5,
					dropShadow: true,
					dropShadowColor: '#000000',
					dropShadowBlur: 8,
					dropShadowOffsetX: 4,
					dropShadowOffsetY: 4,
					stroke: true,
					strokeColor: '#000000',
					strokeThickness: 2
				});
				modalText.anchor.set(.5);
				modalText.y = 100;
				modalContainer.addChild(modalText);
				// Add hourglass sprite next to the '+10 seconds!' text
				var hourglassSpriteModal = LK.getAsset('hourglass', {
					anchorX: .5,
					anchorY: .5
				});
				hourglassSpriteModal.x = 1024 - 70; // Position hourglass to the left of the text
				hourglassSpriteModal.y = 1366;
				modalContainer.addChild(hourglassSpriteModal);
				var thumbUpSprite = LK.getAsset('thumbUp', {
					// Align with the timer's top margin
					anchorX: .5,
					// Anchor right for right alignment
					anchorY: .5 // Anchor top for top alignment
				});
				thumbUpSprite.y = 0;
				thumbUpSprite.x = -500;
				thumbUpSprite.anchor.set(.5, 0.5); // Align with the timer's top margin
				modalContainer.addChild(thumbUpSprite);
				var thumbUpSprite2 = LK.getAsset('woodLockAcid', {
					// Align with the timer's top margin
					anchorX: .5,
					// Anchor right for right alignment
					anchorY: .5 // Anchor top for top alignment
				});
				thumbUpSprite2.y = 0;
				thumbUpSprite2.x = 500;
				thumbUpSprite2.anchor.set(.5, 0.5); // Align with the timer's top margin
				modalContainer.addChild(thumbUpSprite2);
				var modalText = new Text2('+', {
					size: 120,
					weight: 600,
					fill: "#ffffff",
					x: 1024 + 70,
					// Adjust x position to make space for the hourglass sprite
					y: 1366,
					anchorX: 0.5,
					anchorY: 0.5,
					dropShadow: true,
					dropShadowColor: '#000000',
					dropShadowBlur: 8,
					dropShadowOffsetX: 4,
					dropShadowOffsetY: 4,
					stroke: true,
					strokeColor: '#000000',
					strokeThickness: 2
				});
				modalText.anchor.set(.5);
				modalText.x = 400;
				modalText.y = 0;
				modalContainer.addChild(modalText);
				// Automatically remove the modal and background after 2 seconds
				// Start animation for modal elements
				var duration = 2000; // 3 seconds for the animation
				LK.setTimeout(function () {
					var startTime = Date.now();
					var simpleCountdownInterval = LK.setInterval(function () {
						var currentTime = Date.now();
						var progress = (currentTime - startTime) / duration;
						var moveDistance = 2048; // Move to the right side off-screen
						modalContainer.x += moveDistance * progress;
						if (progress >= 1) {
							LK.clearInterval(simpleCountdownInterval);
							modalContainer.destroy();
							startTimer();
						}
					}, 16);
				}, 2000);
				goalLevel++;
				updateBackground();
				setRandomGoalGemType();
			}
		}
	};
	this.checkForMatches = function (matchFoundPreviously) {
		var matchFound = false;
		var matchedGems = [];
		// Check for horizontal matches
		for (var i = 0; i < 8; i++) {
			for (var j = 0; j < 6; j++) {
				// Adjust to allow checks across all columns
				if (!this.gems || !this.gems[i * 6 + j] || typeof this.gems[i * 6 + j] === 'undefined') {
					continue;
				}
				var gem1 = this.gems[i * 6 + j];
				if (!gem1) {
					continue;
				}
				var gem1 = this.gems[i * 6 + j];
				var nowMatchingGems = [];
				for (var k = j; k < 6; k++) {
					var nextGem = this.gems[i * 6 + k];
					if (nextGem && nextGem.color === gem1.color) {
						nowMatchingGems.push(nextGem);
					} else {
						break;
					}
				}
				if (nowMatchingGems.length >= 3) {
					matchFound = true;
					matchedGems = matchedGems.concat(nowMatchingGems.filter(function (gem) {
						return matchedGems.indexOf(gem) === -1;
					}));
				}
			}
		}
		// Check for vertical matches
		for (var i = 0; i < 6; i++) {
			for (var j = 0; j < 8; j++) {
				// Adjust to allow checks across all rows
				if (!this.gems || !this.gems[j * 6 + i]) {
					continue;
				}
				var gem1 = this.gems[j * 6 + i];
				var nowMatchingGems = [];
				for (var k = j; k < 8; k++) {
					var nextGem = this.gems[k * 6 + i];
					if (nextGem && nextGem.color === gem1.color) {
						nowMatchingGems.push(nextGem);
					} else {
						break;
					}
				}
				if (nowMatchingGems.length >= 3) {
					matchFound = true;
					matchedGems = matchedGems.concat(nowMatchingGems.filter(function (gem) {
						return matchedGems.indexOf(gem) === -1;
					}));
				}
			}
		}
		var matchesHandled = 0;
		matchedGems.forEach(function (gem) {
			if (gem.color == goalGemType) {
				self.handleGemMatched(gem);
				// Move gem to the goalGemSprite instead of destroying it
				matchesHandled++;
				game.addChild(gem);
				var moveGemToGoal = function moveGemToGoal(gem) {
					LK.setTimeout(function () {
						var goalGemSpriteX = currentGoalGemSprite ? currentGoalGemSprite.x + (currentGoalGemSprite.parent ? currentGoalGemSprite.parent.x : 0) : 0;
						var goalGemSpriteY = currentGoalGemSprite ? currentGoalGemSprite.y + (currentGoalGemSprite.parent ? currentGoalGemSprite.parent.y : 0) : 0;
						if (currentGoalGemSprite) {
							var goalGemSpriteScale = currentGoalGemSprite.scale.x;
						}
						var moveDuration = 500 + matchesHandled * 100; // Duration in milliseconds
						var startTime = Date.now();
						var animateMove = function animateMove() {
							var currentTime = Date.now();
							var progress = Math.min(1, (currentTime - startTime) / moveDuration);
							var newX = gem.x + (goalGemSpriteX - gem.x) * progress;
							var newY = gem.y + (goalGemSpriteY - gem.y) * progress;
							var newScale = gem.scale.x + (goalGemSpriteScale - gem.scale.x) * progress;
							gem.x = newX;
							gem.y = newY;
							gem.scale.set(newScale);
							if (progress < 1) {
								LK.setTimeout(animateMove, 16); // Aim for roughly 60fps
							} else {
								gem.destroy(); // Destroy gem after reaching the goal
							}
						};
						animateMove();
					}, matchesHandled * 100);
				};
				moveGemToGoal(gem);
			} else {
				self.handleGemMatched(gem);
				gem.scaleUpAndDisappear();
				// Trigger glowing particles effect at the gem's position
				var glowingParticles = new GlowingParticles();
				glowingParticles.init(gem.x, gem.y);
				self.addChild(glowingParticles);
			}
			var index = self.gems.indexOf(gem);
			if (index > -1) {
				self.gems[index] = false;
				// Increase score based on combo multiplier
				var pointsAwarded = 10 * self.comboMultiplier;
				score += pointsAwarded; // Update score with points awarded based on combo multiplier
				LK.setScore(score);
				// Display points at the gem's location with animation
				var pointsText = new Text2("+" + pointsAwarded.toString(), {
					size: 80,
					weight: 600,
					fill: "#ffffff",
					anchorX: 0.5,
					anchorY: 0.5,
					dropShadow: true,
					dropShadowColor: '#000000',
					dropShadowBlur: 8,
					dropShadowOffsetX: 4,
					dropShadowOffsetY: 4,
					outline: true,
					outlineColor: '#000000',
					outlineThickness: 5
				});
				pointsText.y -= 20; // Make it a little bit higher
				pointsText.anchor.set(.5);
				pointsText.x = gem.x;
				pointsText.y = gem.y;
				game.addChild(pointsText);
				// Animate points text: scale up and fade out
				var scaleUpDuration = 500; // Duration to scale up in milliseconds
				var fadeOutDuration = 500; // Duration to fade out in milliseconds
				var maxScale = 1.5; // Maximum scale factor
				var originalScale = 1; // Original scale
				var startTime = Date.now();
				var animate = function animate() {
					var currentTime = Date.now();
					var progress = Math.min(1, (currentTime - startTime) / scaleUpDuration);
					pointsText.scale.set(originalScale + (maxScale - originalScale) * progress);
					pointsText.alpha = 1 - progress; // Fade out
					if (progress < 1) {
						LK.setTimeout(animate, 16); // Aim for roughly 60fps
					} else {
						pointsText.destroy(); // Destroy text after animation
					}
				};
				animate();
				// Increase combo multiplier for each consecutive match
				self.comboMultiplier++;
				scoreTxt.setText(score.toString()); // Update score display
			}
		});
		if (matchFound) {
			// If no match was found previously and it's not the first check, reset the combo multiplier
			if (!matchFoundPreviously && matchFound) {
				self.comboMultiplier = 1;
			} else if (matchFound) {
				// Increase combo multiplier for each consecutive match
				self.comboMultiplier++;
			}
			self.checkForMatches(true);
		} else if (matchFoundPreviously) {
			LK.setTimeout(function () {
				this.handleFallingGems();
			}.bind(this), 200);
		}
		return matchFound;
	};
	self.handleGemClick = function (gem) {
		gem.on('down', function (obj) {
			self.dragStartGem = gem;
			self.dragStartGemStartPosition = {
				x: gem.x,
				y: gem.y
			};
			var currentPos = obj.event.getLocalPosition(game);
			self.dragStartPos = {
				x: currentPos.x,
				y: currentPos.y
			};
			// Highlight the drag start gem
			self.dragStartGem.alpha = 0.5;
			self.dragStartGem.scale.set(self.dragStartGem.baseScale * 1.1);
		});
		gem.on('move', function (obj) {
			if (!self.dragStartGem) {
				return;
			}
			var currentPos = obj.event.getLocalPosition(game);
			//self.dragStartGem.x = self.dragStartGemStartPosition.x + currentPos.x - self.dragStartPos.x;
			//self.dragStartGem.y = self.dragStartGemStartPosition.y + currentPos.y - self.dragStartPos.y;
			var dx = currentPos.x - self.dragStartPos.x;
			var dy = currentPos.y - self.dragStartPos.y;
			if (Math.abs(dx) > gem.spacing / 2 || Math.abs(dy) > gem.spacing / 2) {
				var directionX = dx > 0 ? 1 : -1;
				var directionY = dy > 0 ? 1 : -1;
				// Correctly identify if we should swap horizontally or vertically
				if (Math.abs(dx) > Math.abs(dy)) {
					// Swap horizontally
					var swapGem = self.findGemByPosition(self.dragStartGem.x + gem.spacing * directionX, self.dragStartGem.y, self.dragStartGem);
				} else {
					// Swap vertically
					var swapGem = self.findGemByPosition(self.dragStartGem.x, self.dragStartGem.y + gem.spacing * directionY, self.dragStartGem);
				}
				if (self.lastHintOverlay) {
					self.lastHintOverlay.destroy();
				}
				if (swapGem && self.wouldSwapResultInMatch(self.dragStartGem, swapGem)) {
					self.swapGems(self.dragStartGem, swapGem);
				} else {
					self.faintSwapGems(self.dragStartGem, swapGem, true);
				}
				self.dragStartGem.alpha = 1;
				self.dragStartGem.scale.set(self.dragStartGem.baseScale * 1);
				self.dragStartGem = null;
				self.dragStartPos = null;
			}
		});
		gem.on('up', function () {
			if (self.dragStartGem) {
				self.dragStartGem.alpha = 1; // Reset alpha to unhighlight the gem
				self.dragStartGem.scale.set(self.dragStartGem.baseScale * 1);
			}
			self.dragStartGem = null;
			self.dragStartPos = null;
		});
	};
	self.initBoard = function () {
		var colors = game.timer > 60 ? ['gemBlue', 'gemGreen', 'gemRed', 'gemPurple', 'gemYellow', 'gemOrange', 'gemCyan'] : ['gemBlue', 'gemGreen', 'gemRed', 'gemPurple', 'gemYellow', 'gemOrange'];
		for (var i = 0; i < 8; i++) {
			for (var j = 0; j < 6; j++) {
				var color = colors[Math.floor(Math.random() * colors.length)];
				var gem = new Gem(color);
				var gem = new Gem(color);
				var gemSize = 100;
				var margin = 10;
				var boardWidth = game.width * .9;
				var boardHeight = game.height * .9;
				var gemsPerRow = 6;
				var gemsPerColumn = 8;
				var totalMarginWidth = margin * (gemsPerRow + 1);
				var totalMarginHeight = margin * (gemsPerColumn + 1);
				var availableWidth = boardWidth - totalMarginWidth;
				var availableHeight = boardHeight - totalMarginHeight;
				var scaledGemSize = Math.min(availableWidth / gemsPerRow, availableHeight / gemsPerColumn);
				var xOffset = (game.width - boardWidth) / 2 + scaledGemSize / 2;
				var yOffset = (game.height - boardHeight) / 2 + scaledGemSize / 2;
				gem.spacing = scaledGemSize + margin;
				self.spacing = gem.spacing;
				var snappedPos = self.snapToGrid(xOffset + (scaledGemSize + margin) * j, yOffset + (scaledGemSize + margin) * i);
				gem.x = snappedPos.x;
				gem.y = snappedPos.y;
				gem.scale.set(scaledGemSize / gemSize);
				gem.scale.set(scaledGemSize / gemSize);
				gem.baseScale = scaledGemSize / gemSize;
				self.addChild(gem);
				self.gems.push(gem);
				self.handleGemClick(gem);
			}
		}
		self.comboMultiplier = 1; // Initialize combo multiplier
		self.checkForMatches();
	};
});
// ChineseRedEnvelope class
var ChineseRedEnvelope = Container.expand(function () {
	var self = Container.call(this);
	var envelopeGraphics = self.attachAsset('redEnvelope', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.init = function (x, y) {
		self.x = x;
		self.y = y;
		var scaleAnimation = function scaleAnimation() {
			var scaleUp = true;
			var scaleValue = 1;
			LK.setInterval(function () {
				if (scaleUp) {
					scaleValue += 0.01;
				} else {
					scaleValue -= 0.01;
				}
				if (scaleValue >= 1.1) {
					scaleUp = false;
				}
				if (scaleValue <= 1) {
					scaleUp = true;
				}
				self.scale.set(scaleValue * 2.0); // Make the envelope significantly larger
			}, 100);
		};
		scaleAnimation();
		self.on('down', function () {
			var targetX = timerTxt.x;
			var targetY = timerTxt.y;
			var moveDuration = 1000; // Duration in milliseconds
			var startTime = Date.now();
			var animateMove = function animateMove() {
				var currentTime = Date.now();
				var progress = Math.min(1, (currentTime - startTime) / moveDuration);
				// Apply a quadratic easing for a smooth curve
				var curveProgress = Math.pow(progress, 2);
				self.x = self.x + (targetX - self.x) * curveProgress;
				self.y = self.y - 75 * Math.sin(Math.PI * progress) + (targetY - self.y) * curveProgress; // Add a sine wave pattern for vertical movement
				if (progress < 1) {
					LK.setTimeout(animateMove, 16);
				} else {
					game.timer += 5; // Grant 5 more seconds
					timerTxt.setText(game.timer.toString()); // Update timer display
					self.destroy(); // Remove the envelope after reaching the timer
				}
			};
			animateMove();
		});
		// Initiate continuous glowing effect
		function glowEffect() {
			var glowParticle = new GlowingParticlesForRedEnvelopes(.3);
			glowParticle.init(0, 0);
			self.addChildAt(glowParticle, 0);
		}
		;
		glowEffect();
		//	LK.setInterval(glowEffect, 500); // Add a glowing particle effect every 500ms
	};
});
// ConfettiParticle class
var ConfettiParticle = Container.expand(function () {
	var self = Container.call(this);
	var confettiColors = ['confettiRed', 'confettiBlue', 'confettiGreen', 'confettiYellow', 'confettiPurple'];
	var randomColor = confettiColors[Math.floor(Math.random() * confettiColors.length)];
	var confettiGraphics = self.attachAsset(randomColor, {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.init = function (x, y) {
		self.x = x;
		self.y = y;
		var angle = Math.random() * Math.PI * 2;
		var speed = 0.5 + Math.random(); // Reduced speed for smoother appearance
		var duration = 1500 + Math.random() * 2500; // Extended duration for smoother fade
		var startTime = Date.now();
		var animate = function animate() {
			var currentTime = Date.now();
			var progress = (currentTime - startTime) / duration;
			self.x += Math.cos(angle) * speed;
			self.y += Math.sin(angle) * speed;
			self.alpha = Math.sin(progress * Math.PI); // Smooth in and out fading effect
			if (progress < 1) {
				LK.setTimeout(animate, 16);
			} else {
				self.destroy();
			}
		};
		animate();
	};
});
// Dragon class
var Dragon = Container.expand(function (gem) {
	var self = Container.call(this);
	var dragonGraphics = self.attachAsset('dragon', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	dragonGraphics.anchor.set(1, .7);
	self.speed = 5;
	var hasTakenGem = false;
	self.move = function () {
		var endX = 2048 + self.width; // Ensure dragon ends off-screen to the right
		var startX = -self.width; // Start off-screen to the left
		var travelDistance = endX - startX;
		var travelTime = 3000; // Time in milliseconds for the dragon to cross the screen
		var startTime = Date.now();
		var particleParts = [];
		function animate() {
			var currentTime = Date.now();
			var elapsedTime = currentTime - startTime;
			var progress = elapsedTime / travelTime;
			self.x = startX + travelDistance * progress;
			if (self.x > gem.x && !hasTakenGem) {
				hasTakenGem = true;
				self.addChild(gem);
				// Animate gem scale upon grabbing
				var scaleAnimationDuration = 300; // Duration of the scale animation in milliseconds
				var scaleAnimationStartTime = Date.now();
				var animateGemScale = function animateGemScale() {
					var currentTime = Date.now();
					var progress = Math.min(1, (currentTime - scaleAnimationStartTime) / scaleAnimationDuration);
					gem.scale.set(gem.baseScale * (.8 + .2 * Math.sin(progress * Math.PI * 2))); // Animate scale
					if (progress < 1) {
						LK.setTimeout(animateGemScale, 16);
					} else {
						gem.scale.set(gem.baseScale * .8);
					}
				};
				animateGemScale();
				gem.x = 50;
				gem.y = 0;
				var index = board.gems.indexOf(gem);
				if (index > -1) {
					if (board.gems[index] == gem) {
						board.gems[index] = false;
					}
				}
				LK.setTimeout(function () {
					board.handleFallingGems();
				}, 200);
			}
			if (hasTakenGem) {
				self.addChild(gem);
				//gem.scale.set(gem.baseScale * .8);
				gem.x = 50;
				gem.y = 0;
			}
			// Generate particle trail
			if (progress < 1) {
				LK.setTimeout(animate, 16); // Aim for roughly 60fps
			} else {
				var fadeoutparticle = function fadeoutparticle(particle) {
					// Start fade out effect
					var fadeOutDuration = 500; // Duration for the fade out in milliseconds
					var fadeStartTime = Date.now();
					var fadeStep = function fadeStep() {
						var currentTime = Date.now();
						var progress = (currentTime - fadeStartTime) / fadeOutDuration;
						particle.alpha = 1 - progress; // Fade out
						if (progress < 1) {
							LK.setTimeout(fadeStep, 16);
						} else {
							particle.destroy(); // Destroy particle after fade out
						}
					};
					fadeStep();
				};
				;
				// Spawn a red envelope at a random position
				//var envelope = new ChineseRedEnvelope();
				//envelope.init(Math.random() * game.width, self.y);
				//game.addChild(envelope);
				// Destroy the dragon instance once it crosses the screen
				isDragoning = false;
				particleParts.forEach(function (particle) {
					fadeoutparticle(particle);
				});
				self.destroy();
			}
		}
		animate();
	};
});
// Gem class
var Gem = Container.expand(function (color) {
	var self = Container.call(this);
	self.scaleUpAndDown = function (delay) {
		LK.setTimeout(function () {
			var scaleUpDuration = 150; // Duration to scale up in milliseconds
			var scaleDownDuration = 150; // Duration to scale down in milliseconds
			var maxScale = self.baseScale * 1.3; // Maximum scale factor
			var originalScale = self.baseScale; // Remember the original scale
			var scaleUp = function scaleUp() {
				var startTime = Date.now();
				var scaleStep = function scaleStep() {
					var currentTime = Date.now();
					var progress = Math.min(1, (currentTime - startTime) / scaleUpDuration);
					self.scale.set(originalScale + (maxScale - originalScale) * progress);
					if (progress < 1) {
						LK.setTimeout(scaleStep, 16);
					} else {
						scaleDown();
					}
				};
				scaleStep();
			};
			var scaleDown = function scaleDown() {
				var startTime = Date.now();
				var scaleStep = function scaleStep() {
					var currentTime = Date.now();
					var progress = Math.min(1, (currentTime - startTime) / scaleDownDuration);
					self.scale.set(maxScale - (maxScale - originalScale) * progress);
					if (progress < 1) {
						LK.setTimeout(scaleStep, 16);
					}
				};
				scaleStep();
			};
			scaleUp();
		}, delay);
	};
	self.scaleUpAndDisappear = function scaleUpAndDisappear() {
		var scaleUpDuration = 100; // Duration to scale up in milliseconds
		var scaleDownDuration = 200; // Duration to scale down to zero
		var maxScale = self.baseScale * 1.2; // Maximum scale factor
		var disappearScale = 0; // Scale factor to disappear
		var originalScale = self.baseScale; // Remember the original scale
		// Animate scale up
		// Start scale up
		var scaleUpDuration = 100; // Duration to scale up in milliseconds
		var disappearDuration = 200; // Duration to scale down to zero
		var maxScale = self.baseScale * 1.2; // Maximum scale factor
		var disappearScale = 0; // Scale factor to disappear
		var originalScale = self.baseScale; // Remember the original scale
		// Animate scale up
		var startTime = Date.now();
		var _scaleStep2 = function _scaleStep() {
			var currentTime = Date.now();
			var progress = Math.min(1, (currentTime - startTime) / scaleUpDuration);
			self.scale.set(originalScale + (maxScale - originalScale) * progress);
			if (progress < 1) {
				LK.setTimeout(_scaleStep2, 16);
			} else {
				// Once scaled up, start disappearing
				startTime = Date.now();
				_scaleStep2 = function scaleStep() {
					var currentTime = Date.now();
					var progress = Math.min(1, (currentTime - startTime) / disappearDuration);
					self.scale.set(maxScale - (maxScale - disappearScale) * progress);
					if (progress < 1) {
						LK.setTimeout(_scaleStep2, 16);
					} else {
						self.destroy();
					}
				};
				_scaleStep2();
			}
		};
		_scaleStep2();
	};
	var gemGraphics = self.attachAsset(color, {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.color = color;
	self.isSelected = false;
	self.toggleSelect = function () {
		self.isSelected = !self.isSelected;
		if (self.isSelected) {
			gemGraphics.alpha = 0.5;
			self.scale.set(self.baseScale * 1.1);
		} else {
			gemGraphics.alpha = 1;
			self.scale.set(self.baseScale);
		}
	};
});
// GlowingParticles class enhancement
var GlowingParticles = Container.expand(function () {
	var self = Container.call(this);
	scaleMultiplier = 1;
	var _animateParticle = function animateParticle(particle) {
		var currentTime = Date.now();
		var elapsedTime = currentTime - particle.startTime;
		var progress = elapsedTime / particle.duration;
		if (progress < 1) {
			particle.x += Math.cos(particle.angle) * particle.speed;
			particle.y += Math.sin(particle.angle) * particle.speed;
			particle.alpha = Math.cos(progress * Math.PI); // Smooth in and out fading effect
			particle.rotation += particle.rotationVelocity; // Add rotation to each particle
			LK.setTimeout(function () {
				_animateParticle(particle);
			}, 16);
		} else {
			particle.destroy();
		}
	};
	self.init = function (x, y) {
		for (var i = 0; i < 50; i++) {
			var particle = self.attachAsset('glowEffect', {
				x: x,
				y: y,
				anchorX: 0.5,
				anchorY: 0.5
			});
			particle.blendMode = 1;
			particle.angle = Math.random() * Math.PI * 2; // Random angle for direction
			particle.speed = 1 + Math.random() * 2.5; // Adjusted speed for varied particle movement
			particle.duration = 500 + Math.random() * 1000; // Keeping the duration dynamic
			// Introduce gravity effect to some particles
			for (var i = 0; i < 50; i++) {
				var particle = self.attachAsset('glowEffect', {
					x: x,
					y: y,
					anchorX: 0.5,
					anchorY: 0.5
				});
				particle.blendMode = 1;
				particle.angle = Math.random() * Math.PI * 2; // Random angle for direction
				particle.speed = 1 + Math.random() * 2.5; // Adjusted speed for varied particle movement
				particle.duration = 500 + Math.random() * 1000; // Keeping the duration dynamic
				particle.gravity = Math.random() > 0.5 ? 0.01 : 0; // Half the particles have a gravity effect
				particle.targetScale = 0.5 + Math.random() * 1.5; // Varied scale for more visual variety
				particle.scale.set(particle.targetScale * scaleMultiplier); // Initial scale set based on the random scale variable
				particle.startTime = Date.now();
				particle.rotationVelocity = -0.1 + Math.random() * .2;
				particle.x += Math.cos(particle.angle) * Math.random() * 80;
				particle.y += Math.sin(particle.angle) * Math.random() * 80;
				_animateParticle(particle);
			}
			particle.targetScale = 0.5 + Math.random() * 1.5; // Varied scale for more visual variety
			particle.scale.set(particle.targetScale * scaleMultiplier); // Initial scale set based on the random scale variable
			particle.startTime = Date.now();
			particle.rotationVelocity = -0.1 + Math.random() * .2;
			particle.x += Math.cos(particle.angle) * Math.random() * 80;
			particle.y += Math.sin(particle.angle) * Math.random() * 80;
			_animateParticle(particle);
		}
	};
});
// Define the GlowingParticlesForRedEnvelope class
var GlowingParticlesForRedEnvelope = Container.expand(function (scaleMultiplier) {
	var self = Container.call(this);
	var _animateParticle = function animateParticle(particle) {
		var currentTime = Date.now();
		var elapsedTime = currentTime - particle.startTime;
		var progress = elapsedTime / particle.duration;
		if (progress < 1) {
			// Update particle properties for movement, fading, and rotation
			particle.x += Math.cos(particle.angle) * particle.speed;
			particle.y += Math.sin(particle.angle) * particle.speed;
			particle.alpha = Math.cos(progress * Math.PI); // Fading effect
			particle.rotation += particle.rotationVelocity;
		} else {
			// Reset particle to create a continuous effect
			particle.startTime = Date.now(); // Reset start time
			// Optionally, re-randomize properties for varied continuous effect
			particle.angle = Math.random() * Math.PI * 2;
			particle.speed = 1 + Math.random() * 1.5;
			particle.duration = 500 + Math.random() * 1000;
			particle.rotationVelocity = -0.1 + Math.random() * 0.2;
			particle.x = particle.initialX + Math.cos(particle.angle) * Math.random() * 50;
			particle.y = particle.initialY + Math.sin(particle.angle) * Math.random() * 50;
		}
		LK.setTimeout(function () {
			_animateParticle(particle);
		}, 16); // Continue animation loop
	};
	self.init = function (x, y) {
		for (var i = 0; i < 50; i++) {
			var particle = self.attachAsset('glowEffect', {
				x: x,
				y: y,
				anchorX: 0.5,
				anchorY: 0.5
			});
			particle.blendMode = 1;
			particle.alpha = 0;
			particle.initialX = x; // Store initial position
			particle.initialY = y;
			particle.angle = Math.random() * Math.PI * 2;
			particle.speed = 1 + Math.random() * 1.5;
			particle.duration = 500 + Math.random() * 1000;
			particle.targetScale = 0.5 + Math.random() * 1.5;
			particle.scale.set(particle.targetScale * scaleMultiplier);
			particle.startTime = Date.now();
			particle.rotationVelocity = -0.1 + Math.random() * 0.2;
			particle.x += Math.cos(particle.angle) * Math.random() * 70;
			particle.y += Math.sin(particle.angle) * Math.random() * 70;
			_animateParticle(particle);
		}
	};
});
var GlowingParticlesForRedEnvelopes = Container.expand(function (scaleMultiplier) {
	var self = Container.call(this);
	var _animateParticle = function animateParticle(particle) {
		var currentTime = Date.now();
		var elapsedTime = currentTime - particle.startTime;
		var progress = elapsedTime / particle.duration;
		if (progress < 1) {
			// Update particle properties for movement, fading, and rotation
			particle.x += Math.cos(particle.angle) * particle.speed;
			particle.y += Math.sin(particle.angle) * particle.speed;
			particle.alpha = Math.cos(progress * Math.PI); // Fading effect
			particle.rotation += particle.rotationVelocity;
		} else {
			// Reset particle to create a continuous effect
			particle.startTime = Date.now(); // Reset start time
			// Optionally, re-randomize properties for varied continuous effect
			particle.angle = Math.random() * Math.PI * 2;
			particle.speed = 1 + Math.random() * 1.5;
			particle.duration = 500 + Math.random() * 1000;
			particle.rotationVelocity = -0.1 + Math.random() * 0.2;
			particle.x = particle.initialX + Math.cos(particle.angle) * Math.random() * 50;
			particle.y = particle.initialY + Math.sin(particle.angle) * Math.random() * 50;
		}
		LK.setTimeout(function () {
			_animateParticle(particle);
		}, 16); // Continue animation loop
	};
	self.init = function (x, y) {
		for (var i = 0; i < 50; i++) {
			var particle = self.attachAsset('glowEffect', {
				x: x,
				y: y,
				anchorX: 0.5,
				anchorY: 0.5
			});
			particle.blendMode = 1;
			particle.alpha = 0;
			particle.initialX = x; // Store initial position
			particle.initialY = y;
			particle.angle = Math.random() * Math.PI * 2;
			particle.speed = 1 + Math.random() * 1.5;
			particle.duration = 500 + Math.random() * 1000;
			particle.targetScale = 0.5 + Math.random() * 1.5;
			particle.scale.set(particle.targetScale * scaleMultiplier);
			particle.startTime = Date.now();
			particle.rotationVelocity = -0.1 + Math.random() * 0.2;
			particle.x += Math.cos(particle.angle) * Math.random() * 70;
			particle.y += Math.sin(particle.angle) * Math.random() * 70;
			_animateParticle(particle);
		}
	};
});
// LineSprite class
var LineSprite = Container.expand(function () {
	var self = Container.call(this);
	self.updateLine = function (startX, startY, endX, endY) {
		var dx = endX - startX;
		var dy = endY - startY;
		var distance = Math.sqrt(dx * dx + dy * dy);
		self.width = distance;
		self.height = 5; // Fixed height for the line
		self.rotation = Math.atan2(dy, dx);
		self.x = startX + dx / 2;
		self.y = startY + dy / 2;
		self.anchorX = 0.5;
		self.anchorY = 0.5;
	};
});
// RowBlasterGem class
var RowBlasterGem = Container.expand(function (color) {
	var self = Container.call(this);
	var gemGraphics = self.attachAsset(color, {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.color = color;
	// Unique behavior for RowBlasterGem
	self.activate = function () {
		// Logic to blast the entire row
		console.log('Blasting row...');
	};
});
/**** 
* Initialize Game
****/
var game = new LK.Game({
	backgroundColor: 0x000000 // Init game with black background
});
/**** 
* Game Code
****/
// SagaMap class
// SagaMap class
// Dragon spawn timer
// Goal gem type and count
// Initialize large countdown at the beginning of the game
// Initialize score
// Initialize 2-minute timer
// Initialize a timer for showing hints
var SagaMap = /*#__PURE__*/function (_Container) {
	_inherits(SagaMap, _Container);
	function SagaMap() {
		var _this;
		_classCallCheck(this, SagaMap);
		_this = _callSuper(this, SagaMap);
		_this.levels = [];
		_this.currentLevel = 0;
		return _this;
	}
	_createClass(SagaMap, [{
		key: "addLevel",
		value: function addLevel(level) {
			this.levels.push(level);
		}
	}, {
		key: "goToLevel",
		value: function goToLevel(index) {
			this.currentLevel = index;
			// Logic to switch to the specified level
			console.log('Switching to level:', index);
		}
	}, {
		key: "nextLevel",
		value: function nextLevel() {
			if (this.currentLevel < this.levels.length - 1) {
				this.goToLevel(this.currentLevel + 1);
			} else {
				console.log('No more levels!');
			}
		}
	}]);
	return SagaMap;
}(Container);
function _typeof2(o) {
	"@babel/helpers - typeof";
	return _typeof2 = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
		return typeof o;
	} : function (o) {
		return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
	}, _typeof2(o);
}
function _classCallCheck(instance, Constructor) {
	if (!(instance instanceof Constructor)) {
		throw new TypeError("Cannot call a class as a function");
	}
}
function _defineProperties(target, props) {
	for (var i = 0; i < props.length; i++) {
		var descriptor = props[i];
		descriptor.enumerable = descriptor.enumerable || false;
		descriptor.configurable = true;
		if ("value" in descriptor) {
			descriptor.writable = true;
		}
		Object.defineProperty(target, _toPropertyKey2(descriptor.key), descriptor);
	}
}
function _createClass(Constructor, protoProps, staticProps) {
	if (protoProps) {
		_defineProperties(Constructor.prototype, protoProps);
	}
	if (staticProps) {
		_defineProperties(Constructor, staticProps);
	}
	Object.defineProperty(Constructor, "prototype", {
		writable: false
	});
	return Constructor;
}
function _toPropertyKey2(t) {
	var i = _toPrimitive2(t, "string");
	return "symbol" == _typeof2(i) ? i : String(i);
}
function _toPrimitive2(t, r) {
	if ("object" != _typeof2(t) || !t) {
		return t;
	}
	var e = t[Symbol.toPrimitive];
	if (void 0 !== e) {
		var i = e.call(t, r || "default");
		if ("object" != _typeof2(i)) {
			return i;
		}
		throw new TypeError("@@toPrimitive must return a primitive value.");
	}
	return ("string" === r ? String : Number)(t);
}
function _callSuper(t, o, e) {
	return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e));
}
function _possibleConstructorReturn(self, call) {
	if (call && (_typeof2(call) === "object" || typeof call === "function")) {
		return call;
	} else if (call !== void 0) {
		throw new TypeError("Derived constructors may only return object or undefined");
	}
	return _assertThisInitialized(self);
}
function _assertThisInitialized(self) {
	if (self === void 0) {
		throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
	}
	return self;
}
function _isNativeReflectConstruct() {
	try {
		var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
	} catch (t) {}
	return (_isNativeReflectConstruct = function _isNativeReflectConstruct() {
		return !!t;
	})();
}
function _getPrototypeOf(o) {
	_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) {
		return o.__proto__ || Object.getPrototypeOf(o);
	};
	return _getPrototypeOf(o);
}
function _inherits(subClass, superClass) {
	if (typeof superClass !== "function" && superClass !== null) {
		throw new TypeError("Super expression must either be null or a function");
	}
	subClass.prototype = Object.create(superClass && superClass.prototype, {
		constructor: {
			value: subClass,
			writable: true,
			configurable: true
		}
	});
	Object.defineProperty(subClass, "prototype", {
		writable: false
	});
	if (superClass) {
		_setPrototypeOf(subClass, superClass);
	}
}
function _setPrototypeOf(o, p) {
	_setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) {
		o.__proto__ = p;
		return o;
	};
	return _setPrototypeOf(o, p);
}
var SagaMap = /*#__PURE__*/function (_Container) {
	_inherits(SagaMap, _Container);
	function SagaMap() {
		var _this;
		_classCallCheck(this, SagaMap);
		_this = _callSuper(this, SagaMap);
		_this.levels = [];
		_this.currentLevel = 0;
		return _this;
	}
	_createClass(SagaMap, [{
		key: "addLevel",
		value: function addLevel(level) {
			this.levels.push(level);
		}
	}, {
		key: "goToLevel",
		value: function goToLevel(index) {
			this.currentLevel = index;
			// Logic to switch to the specified level
			console.log('Switching to level:', index);
		}
	}, {
		key: "nextLevel",
		value: function nextLevel() {
			if (this.currentLevel < this.levels.length - 1) {
				this.goToLevel(this.currentLevel + 1);
			} else {
				console.log('No more levels!');
			}
		}
	}]);
	return SagaMap;
}(Container);
var dragonSpawnTimer;
var isDragoning = false;
function triggerDragon() {
	if (dragonSpawnTimer) {
		LK.clearTimeout(dragonSpawnTimer);
	}
	if (!isDragoning && board && board.gems && board.gems.length > 0) {
		isDragoning = true;
		var randomIndex = Math.floor(Math.random() * board.gems.length);
		var gemToRemove = board.gems[randomIndex];
		if (gemToRemove) {
			var dragon = new Dragon(gemToRemove);
			dragon.x = -100; // Ensure dragon starts off-screen to the left
			dragon.y = gemToRemove.y; // Random y position within game bounds
			game.addChild(dragon);
			dragon.move();
		}
	}
	var nextSpawnTime = 5000 + Math.random() * 10000; // Random interval between 5 to 15 seconds
	dragonSpawnTimer = LK.setTimeout(triggerDragon, nextSpawnTime);
}
triggerDragon();
var goalGemType;
var matchedGemCount = 0;
var hintTimer;
var currentGoalGemSprite = false;
var goalLevel = 0;
// Function to randomly set the goal gem type from the available gem colors
function setRandomGoalGemType() {
	var gemColors = ['gemBlue', 'gemGreen', 'gemRed', 'gemPurple', 'gemYellow', 'gemOrange', 'gemCyan'];
	goalGemType = gemColors[Math.floor(Math.random() * gemColors.length)];
	goalGemCount = 3 + Math.floor(Math.random() * goalLevel);
	matchedGemCount = 0;
	LK.setTimeout(function () {
		// Update the goal text with the chosen gem type
		goalTxt.setText(matchedGemCount + '/' + goalGemCount);
		// Add hourglass sprite next to the timer
		if (currentGoalGemSprite) {
			currentGoalGemSprite.destroy();
		}
		currentGoalGemSprite = LK.getAsset(goalGemType, {
			x: 2048 - 100,
			// Position next to the timer
			y: 50,
			// Align with the timer's top margin
			anchorX: .5,
			// Anchor right for right alignment
			anchorY: .5 // Anchor top for top alignment
		});
		currentGoalGemSprite.y = goalTxt.y;
		currentGoalGemSprite.x = goalBackground.x; // Position next to the timer
		currentGoalGemSprite.anchor.set(0.5, 0.5); // Align with the timer's top margin
		currentGoalGemSprite.rotation = -.2;
		currentGoalGemSprite.scale.set(1.6);
		if (goalBackground.parent) {
			goalBackground.parent.removeChild(goalBackground);
		}
		if (goalTxt.parent) {
			goalTxt.parent.removeChild(goalTxt);
		}
		if (currentGoalGemSprite.parent) {
			currentGoalGemSprite.parent.removeChild(currentGoalGemSprite);
		}
		LK.setTimeout(function () {
			board.addChild(goalBackground);
			game.addChild(goalBackground);
			game.addChild(goalTxt);
			game.addChild(currentGoalGemSprite);
		}, 1000);
	}, 1000);
}
// setRandomGoalGemType(); // Initialize the goal gem type at the start of the game
// This call has been moved to after the definition of goalTxt to fix the bug
// Function to reset and start the hint timer
function resetHintTimer() {
	if (hintTimer) {
		LK.clearTimeout(hintTimer);
	}
	hintTimer = LK.setTimeout(function () {
		board.showHint();
		resetHintTimer();
	}, 5000); // Show hint after 5 seconds of inactivity
}
resetHintTimer();
// Reset the hint timer whenever a move is made
LK.on('tick', function () {
	// This is a placeholder for any game action, e.g., gem swap, that resets the hint timer
	// resetHintTimer();
});
function _typeof(o) {
	"@babel/helpers - typeof";
	return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
		return typeof o;
	} : function (o) {
		return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
	}, _typeof(o);
}
function _defineProperty(obj, key, value) {
	key = _toPropertyKey(key);
	if (key in obj) {
		Object.defineProperty(obj, key, {
			value: value,
			enumerable: true,
			configurable: true,
			writable: true
		});
	} else {
		obj[key] = value;
	}
	return obj;
}
function _toPropertyKey(t) {
	var i = _toPrimitive(t, "string");
	return "symbol" == _typeof(i) ? i : String(i);
}
function _toPrimitive(t, r) {
	if ("object" != _typeof(t) || !t) {
		return t;
	}
	var e = t[Symbol.toPrimitive];
	if (void 0 !== e) {
		var i = e.call(t, r || "default");
		if ("object" != _typeof(i)) {
			return i;
		}
		throw new TypeError("@@toPrimitive must return a primitive value.");
	}
	return ("string" === r ? String : Number)(t);
}
var countdownValue = 3; // Start countdown from 3
var countdownTxt = new Text2(countdownValue.toString(), {
	size: 300,
	fill: "#ffffff",
	x: 1024,
	// Center of the screen
	y: 1366,
	// Middle of the screen
	anchorX: 0.5,
	anchorY: 0.5,
	stroke: true,
	weight: 800,
	dropShadow: true
});
countdownTxt.anchor.set(.5);
LK.gui.center.addChild(countdownTxt); // Add countdown display to the center GUI layer
var countdownInterval = LK.setInterval(function () {
	countdownValue -= 1;
	if (countdownValue > 0) {
		countdownTxt.setText(countdownValue.toString());
		// Bounce effect for countdown numbers
		var scaleUpDuration = 100; // Duration to scale up in milliseconds
		var scaleDownDuration = 100; // Duration to scale down in milliseconds
		var maxScale = 1.2; // Maximum scale factor
		var originalScale = 1; // Remember the original scale
		var scaleUp = function scaleUp() {
			var startTime = Date.now();
			var scaleStep = function scaleStep() {
				var currentTime = Date.now();
				var progress = Math.min(1, (currentTime - startTime) / scaleUpDuration);
				countdownTxt.scale.set(originalScale + (maxScale - originalScale) * progress);
				if (progress < 1) {
					LK.setTimeout(scaleStep, 16);
				} else {
					scaleDown();
				}
			};
			scaleStep();
		};
		var scaleDown = function scaleDown() {
			var startTime = Date.now();
			var scaleStep = function scaleStep() {
				var currentTime = Date.now();
				var progress = Math.min(1, (currentTime - startTime) / scaleDownDuration);
				countdownTxt.scale.set(maxScale - (maxScale - originalScale) * progress);
				if (progress < 1) {
					LK.setTimeout(scaleStep, 16);
				}
			};
			scaleStep();
		};
		scaleUp();
	} else if (countdownValue === 0) {
		countdownTxt.setText('GO!');
		spinHourglass();
		// Bounce effect
		var scaleUpDuration = 200; // Duration to scale up in milliseconds
		var scaleDownDuration = 200; // Duration to scale down in milliseconds
		var maxScale = 1.5; // Maximum scale factor
		var originalScale = 1; // Remember the original scale
		var scaleUp = function scaleUp() {
			var startTime = Date.now();
			var scaleStep = function scaleStep() {
				var currentTime = Date.now();
				var progress = Math.min(1, (currentTime - startTime) / scaleUpDuration);
				countdownTxt.scale.set(originalScale + (maxScale - originalScale) * progress);
				if (progress < 1) {
					LK.setTimeout(scaleStep, 16);
				} else {
					scaleDown();
				}
			};
			scaleStep();
		};
		var scaleDown = function scaleDown() {
			var fadeOutDuration = 500; // Duration for the fade out in milliseconds
			var startTime = Date.now();
			var fadeStep = function fadeStep() {
				var currentTime = Date.now();
				var progress = Math.min(1, (currentTime - startTime) / fadeOutDuration);
				countdownTxt.alpha = 1 - progress; // Fade out
				if (progress < 1) {
					LK.setTimeout(fadeStep, 16);
				} else {
					countdownTxt.destroy(); // Remove countdown text after animation
					LK.clearInterval(countdownInterval);
					setRandomGoalGemType();
				}
			};
			fadeStep();
		};
		scaleUp();
	}
}, 1000); // Update countdown every second
game.timer = 120; // 2 minutes in seconds
// Implement a three second delay before starting the timer text interval
LK.setTimeout(function () {
	// Timer control is now handled inside the modal display logic to pause during the modal display.
}, 3000);
var score = 0; // Starting score
var scoreBg;
var scoreBgNode = LK.getAsset('scoreBg', {
	x: 1024 - 150,
	// Centered based on the background size
	y: 0,
	anchorX: 0.5,
	anchorY: 0
});
scoreBgNode.anchor.set(.5);
scoreBgNode.y = 50;
scoreBgNode.alpha = 1; // Set the background transparency to fully opaque to ensure visibility
LK.gui.top.addChild(scoreBgNode);
var scoreTxt = new Text2(score.toString(), _defineProperty(_defineProperty({
	size: 110,
	weight: 500,
	fill: "#ffffff",
	x: 1024,
	// Center of the screen
	y: 0,
	// Adjusted to be within the background
	anchorX: 0.5,
	// Center horizontally
	anchorY: 0,
	// Anchor at the top
	dropShadow: true,
	dropShadowColor: '#000000',
	shadowBlur: 4,
	shadowOffsetX: 2,
	shadowOffsetY: 2,
	stroke: true,
	strokeColor: '#000000'
}, "stroke", '#000000'), "strokeThickness", 7));
scoreTxt.anchor.set(.5, .5);
scoreTxt.y = 50;
LK.gui.top.addChild(scoreTxt); // Add score display to the top GUI layer
// List of background images for different goal levels
var backgroundImages = ['magicalBackground', 'enchantedForest', 'mysticCave', 'celestialRealm'];
// Function to update the game background according to the current goal level
function updateBackground() {
	var backgroundImageId = backgroundImages[goalLevel % backgroundImages.length];
	var oldBackground = game.background;
	if (oldBackground) {
		LK.setTimeout(function () {
			oldBackground.destroy();
		}, 1000);
	}
	var background = LK.getAsset(backgroundImageId, {
		anchorX: 0.5,
		anchorY: 0.5
	});
	background.x = game.width / 2;
	background.y = game.height / 2;
	background.scale.set(Math.max(game.height / background.height, game.width / background.width));
	background.alpha = 0; // Start fully transparent
	var fadeInDuration = 1000; // Duration for the fade in milliseconds
	var fadeInStartTime = Date.now();
	var fadeInStep = function fadeInStep() {
		var currentTime = Date.now();
		var progress = (currentTime - fadeInStartTime) / fadeInDuration;
		background.alpha = progress; // Fade in
		if (progress < 1) {
			LK.setTimeout(fadeInStep, 16);
		} else {
			background.alpha = 1;
			if (oldBackground) {}
		}
	};
	fadeInStep();
	// This line is removed to prevent script errors related to incorrect usage of addChildAt.
	// Instead, we'll use addChild and manage layering through careful addition order.
	game.addChildAt(background, Math.min(1, game.children.length));
	game.background = background;
}
// Initially set the background
updateBackground();
// Add the game board background to the game
var gameBoardBg = game.addChild(LK.getAsset('gameBoardBg', {
	x: 0,
	y: 0,
	anchorX: 0,
	anchorY: 0
}));
gameBoardBg.width = game.width * 0.9;
gameBoardBg.height = game.height * 0.9;
gameBoardBg.x = (game.width - gameBoardBg.width) / 2;
gameBoardBg.y = (game.height - gameBoardBg.height) / 2 + 80;
gameBoardBg.alpha = 0.6; // Set the background transparency to make it slightly visible
// Initialize the board
// Define assets for the game
var board = new Board();
game.addChild(board);
board.initBoard();
function animateGemsInWave(board) {
	for (var i = 0; i < 8; i++) {
		for (var j = 0; j < 6; j++) {
			var gem = board.gems[i * 6 + j];
			if (gem && typeof gem.scaleUpAndDown === 'function') {
				gem.scaleUpAndDown((i + j) * 50);
			}
		}
	}
}
animateGemsInWave(board);
// Game logic
LK.on('tick', function () {
	// Add game logic that needs to run every frame
	// For example, checking for matches, handling animations, etc.
});
// Add a label with the same styling as the timer text, but with the opposite x-coordinate
var goalTxt = new Text2('', {
	size: 100,
	weight: 500,
	fill: "#ffffff",
	x: 0,
	// Opposite x-coordinate
	y: 50,
	anchorX: 0,
	anchorY: 0,
	dropShadow: true,
	dropShadowColor: '#000000',
	shadowBlur: 4,
	shadowOffsetX: 2,
	shadowOffsetY: 2,
	strokeThickness: 7
});
board.addChild(goalTxt);
goalTxt.anchor.set(0, .5);
goalTxt.y = 100;
goalTxt.x = 450;
// Add hourglass sprite next to the timer
var goalBackground = LK.getAsset('goalBackgroundSprite', {
	x: 2048 - 100,
	// Position next to the timer
	y: 50,
	// Align with the timer's top margin
	anchorX: .5,
	// Anchor right for right alignment
	anchorY: .5 // Anchor top for top alignment
});
goalBackground.y = goalTxt.y;
goalBackground.x = goalTxt.x - 100; // Position next to the timer
goalBackground.anchor.set(0.5, 0.5); // Align with the timer's top margin
goalBackground.alpha = .6;
var timerTxt = new Text2(game.timer.toString(), {
	size: 100,
	// Made the text smaller
	weight: 500,
	fill: "#ffffff",
	x: 2048 - 200,
	y: 50,
	anchorX: 1,
	anchorY: 0,
	dropShadow: true,
	dropShadowColor: '#000000',
	shadowBlur: 4,
	shadowOffsetX: 2,
	shadowOffsetY: 2,
	strokeThickness: 7
});
// Add hourglass sprite next to the timer
var hourglassSprite = LK.getAsset('hourglass', {
	x: 2048 - 100,
	// Position next to the timer
	y: 50,
	// Align with the timer's top margin
	anchorX: .5,
	// Anchor right for right alignment
	anchorY: .5 // Anchor top for top alignment
});
function stopTimer() {
	if (board.timerInterval) {
		LK.clearInterval(board.timerInterval);
	}
}
function startTimer() {
	// Resume the game timer after the modal disappears
	stopTimer();
	board.timerInterval = LK.setInterval(function () {
		game.timer -= 1;
		timerTxt.setText(game.timer.toString());
		if (game.timer <= 0) {
			LK.showGameOver('Final Score: ' + score);
		}
	}, 1000);
}
// Logic to spin the hourglass
var spinHourglass = function spinHourglass() {
	var rotationDuration = 500; // Duration of the spin in milliseconds
	var startTime = Date.now();
	var spinStep = function spinStep() {
		var currentTime = Date.now();
		var progress = (currentTime - startTime) / rotationDuration;
		hourglassSprite.rotation = progress * 2 * Math.PI; // Complete rotation
		if (progress < 1) {
			LK.setTimeout(spinStep, 16); // Aim for roughly 60fps
		} else {
			hourglassSprite.rotation = 0;
			startTimer();
		}
	};
	spinStep();
};
board.addChild(hourglassSprite);
timerTxt.anchor.set(1, .5);
timerTxt.y = 100;
timerTxt.x = 2048 - 240;
board.addChild(timerTxt); // Add timer display to the top GUI layer
hourglassSprite.y = timerTxt.y;
hourglassSprite.x = timerTxt.x + 70; // Position next to the timer
hourglassSprite.anchor.set(0.5, 0.5); // Align with the timer's top margin
:quality(85)/https://cdn.frvr.ai/65cf6ed2068ab7d4a9654ab2.png%3F3) 
 a magical landscape of wonder and joy. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
:quality(85)/https://cdn.frvr.ai/65cf7ae301cc0d9e6d0a3493.png%3F3) 
 Magic, purple gem. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
:quality(85)/https://cdn.frvr.ai/65cfb5efb370066057b9a334.png%3F3) 
 glow. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
:quality(85)/https://cdn.frvr.ai/65d066e4c3cd4d030ad558f9.png%3F3) 
 Hourglass icon white. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
:quality(85)/https://cdn.frvr.ai/65d20e041a671a66cfbe85eb.png%3F3) 
 Glow glare star. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
:quality(85)/https://cdn.frvr.ai/65d2d5c4cd9a1b6ee5942e71.png%3F3) 
 Shiny red envelope bao, chinese new years. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
:quality(85)/https://cdn.frvr.ai/65d345dfcd9a1b6ee5942fa6.png%3F3) 
 Magic greem gem in odd shape. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
:quality(85)/https://cdn.frvr.ai/65d346b3cd9a1b6ee5942fb1.png%3F3) 
 Flying unicorn fullbody sideview. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
:quality(85)/https://cdn.frvr.ai/65d375a88372606f503c071b.png%3F3) 
 Magic Orange Gem. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
:quality(85)/https://cdn.frvr.ai/65d376458372606f503c0727.png%3F3) 
 Magic Blue Drop Shaped Gem. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
:quality(85)/https://cdn.frvr.ai/65d377f48372606f503c073d.png%3F3) 
 remove
:quality(85)/https://cdn.frvr.ai/65d378e88372606f503c074c.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/65d3790e8372606f503c0750.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/65d3792a8372606f503c0754.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/65d3794e8372606f503c0758.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/65d3796b8372606f503c075c.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/65d388a753acf798b193f756.png%3F3) 
 Brilliant Gold Checkmark. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
:quality(85)/https://cdn.frvr.ai/65d49e82d9b8a615ff7ff009.png%3F3) 
 Magic diamond. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
:quality(85)/https://cdn.frvr.ai/65d5a1bf86d309c4969c3c3e.png%3F3) 
 Enchanted forest. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
:quality(85)/https://cdn.frvr.ai/65d5a21386d309c4969c3c49.png%3F3) 
 Celestial reAlm. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
:quality(85)/https://cdn.frvr.ai/65d5a2ea86d309c4969c3c57.png%3F3) 
 Mystic cavern. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
:quality(85)/https://cdn.frvr.ai/65d7204747d3df4dc28de11c.png%3F3)