/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
// UnicornCell: Represents a single cell in the Sudoku grid
var UnicornCell = Container.expand(function () {
	var self = Container.call(this);
	// Cell background (for selection/highlight)
	var bg = self.attachAsset('cellBg', {
		width: cellSize - 8,
		height: cellSize - 8,
		color: 0xffffff,
		shape: 'box',
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.bg = bg;
	// The unicorn icon (if any)
	self.icon = null;
	self.unicornIndex = null; // 0-8, or null if empty
	// Row, col for logic
	self.row = 0;
	self.col = 0;
	// Is this a given (pre-filled) cell?
	self.isGiven = false;
	// Show error highlight
	self.showError = function (on) {
		if (on) {
			tween(self.bg, {
				color: 0xffaaaa
			}, {
				duration: 200,
				easing: tween.easeIn
			});
		} else {
			tween(self.bg, {
				color: 0xffffff
			}, {
				duration: 200,
				easing: tween.easeOut
			});
		}
	};
	// Set unicorn icon
	self.setUnicorn = function (idx, animate) {
		if (self.icon) {
			self.removeChild(self.icon);
			self.icon = null;
		}
		self.unicornIndex = idx;
		if (idx !== null) {
			var icon = self.attachAsset('unicorn' + idx, {
				width: cellSize * 0.7,
				height: cellSize * 0.7,
				anchorX: 0.5,
				anchorY: 0.5
			});
			self.icon = icon;
			if (animate) {
				icon.scaleX = 0.2;
				icon.scaleY = 0.2;
				tween(icon, {
					scaleX: 1,
					scaleY: 1
				}, {
					duration: 180,
					easing: tween.bounceOut
				});
			}
		}
	};
	// Remove unicorn icon
	self.clearUnicorn = function () {
		if (self.icon) {
			self.removeChild(self.icon);
			self.icon = null;
		}
		self.unicornIndex = null;
	};
	// Selection highlight
	self.setSelected = function (on) {
		if (on) {
			tween(self.bg, {
				color: 0xcce6ff
			}, {
				duration: 120
			});
		} else {
			tween(self.bg, {
				color: 0xffffff
			}, {
				duration: 120
			});
		}
	};
	return self;
});
// UnicornPicker: The row of unicorn icons for selection
var UnicornPicker = Container.expand(function () {
	var self = Container.call(this);
	self.icons = [];
	self.visible = false;
	self.selectedIdx = null;
	// Add vertical space above icons
	var pickerTopPadding = 36; // extra space above icons
	// Create 4 unicorn icons
	for (var i = 0; i < 4; i++) {
		var icon = self.attachAsset('unicorn' + i, {
			width: pickerIconSize,
			height: pickerIconSize,
			anchorX: -1,
			anchorY: -1,
			x: i * (pickerIconSize + pickerGap),
			y: pickerTopPadding // shift icons down by padding
		});
		icon.idx = i;
		self.icons.push(icon);
	}
	// Background
	var pickerBg = self.attachAsset('pickerBg', {
		width: 4 * pickerIconSize + 3 * pickerGap + 32,
		height: pickerIconSize + 32 + pickerTopPadding,
		// increase height for top padding
		color: 0xf7e6ff,
		shape: 'box',
		anchorX: 0,
		anchorY: 0
	});
	pickerBg.x = -16;
	pickerBg.y = -16;
	self.setChildIndex(pickerBg, 0);
	// Highlight selected
	self.setSelected = function (idx) {
		for (var i = 0; i < self.icons.length; i++) {
			self.icons[i].alpha = i === idx ? 1 : 0.7;
			self.icons[i].scaleX = self.icons[i].scaleY = i === idx ? 1.15 : 1;
		}
		self.selectedIdx = idx;
	};
	// Show/hide
	self.show = function (x, y) {
		self.x = x;
		self.y = y;
		self.visible = true;
	};
	self.hide = function () {
		self.visible = false;
	};
	return self;
});
/**** 
* Initialize Game
****/ 
/**** 
* Game Constants
****/ 
// Board layout
// --- Game Initialization ---
var game = new LK.Game({
	backgroundColor: 0xf7e6ff
});
/**** 
* Game Code
****/ 
// Add unicorn image assets (replace with your actual unicorn image asset ids or use placeholder images)
// Board layout
/**** 
* Game Constants
****/ 
// --- Game State ---
var gridSize = 4;
var cellSize = 320; // 4*320 = 1280, fits well in 2048 width
var boardSize = cellSize * gridSize;
var boardOffsetX = (2048 - boardSize) / 2;
var boardOffsetY = 320;
// Picker
var pickerIconSize = 180;
var pickerGap = 32;
// For error highlight
var errorFlashDuration = 400;
// --- Asset Initialization ---
// 4 unicorn icons
for (var i = 0; i < 4; i++) {}
// Cell background
// Picker background
var board = []; // 2D array of UnicornCell
var givenBoard = []; // 2D array of unicorn indices (0-3) or null
var solutionBoard = []; // 2D array of unicorn indices (0-3)
var selectedCell = null;
var picker = null;
var timerTxt = null;
var startTime = null;
var timerInterval = null;
var errorCells = [];
var completed = false;
// --- Sudoku Puzzle Generation ---
// For MVP, use a static puzzle and solution (easy level)
// 4x4 puzzle, unicorn indices 0-3, 2x2 boxes
var staticPuzzle = [[null, 1, null, 2], [3, null, null, null], [null, null, null, 1], [2, null, 3, null]];
// Solution for the above puzzle (0-3 for unicorn indices, valid for 2x2 boxes)
var staticSolution = [[0, 1, 2, 3], [3, 2, 1, 0], [1, 3, 0, 2], [2, 0, 3, 1]];
// --- Helper Functions ---
// Returns true if placing unicornIdx at (row, col) is valid
function isValidMove(row, col, unicornIdx) {
	// Check row
	for (var c = 0; c < gridSize; c++) {
		if (c !== col && board[row][c].unicornIndex === unicornIdx) {
			return false;
		}
	}
	// Check col
	for (var r = 0; r < gridSize; r++) {
		if (r !== row && board[r][col].unicornIndex === unicornIdx) {
			return false;
		}
	}
	// Check 2x2 box for 4x4
	var boxRow = Math.floor(row / 2) * 2;
	var boxCol = Math.floor(col / 2) * 2;
	for (var r = boxRow; r < boxRow + 2; r++) {
		for (var c = boxCol; c < boxCol + 2; c++) {
			if ((r !== row || c !== col) && board[r][c].unicornIndex === unicornIdx) {
				return false;
			}
		}
	}
	return true;
}
// Returns true if the board is completely and correctly filled
function isBoardComplete() {
	for (var r = 0; r < gridSize; r++) {
		for (var c = 0; c < gridSize; c++) {
			var cell = board[r][c];
			if (cell.unicornIndex === null) {
				return false;
			}
			if (!isValidMove(r, c, cell.unicornIndex)) {
				return false;
			}
		}
	}
	return true;
}
// Highlight errors for current board state
function highlightErrors() {
	// Clear previous
	for (var i = 0; i < errorCells.length; i++) {
		errorCells[i].showError(false);
	}
	errorCells = [];
	// Check for errors
	for (var r = 0; r < gridSize; r++) {
		for (var c = 0; c < gridSize; c++) {
			var cell = board[r][c];
			if (cell.unicornIndex === null) {
				continue;
			}
			// Only highlight if not a given
			if (!cell.isGiven && !isValidMove(r, c, cell.unicornIndex)) {
				cell.showError(true);
				errorCells.push(cell);
			}
		}
	}
}
// Deselect all cells
function deselectAllCells() {
	for (var r = 0; r < gridSize; r++) {
		for (var c = 0; c < gridSize; c++) {
			if (typeof board[r][c].setSelected === "function") {
				board[r][c].setSelected(false);
			}
		}
	}
	selectedCell = null;
}
// --- UI Setup ---
// Board container
var boardContainer = new Container();
boardContainer.x = boardOffsetX;
boardContainer.y = boardOffsetY;
game.addChild(boardContainer);
// Draw grid lines (thick for boxes, thin for cells)
for (var i = 0; i <= gridSize; i++) {
	// For 4x4, thick lines at 0, 2, 4 (every 2 cells)
	var isBoxLine = i % 2 === 0;
	var lineW = isBoxLine ? 8 : 3;
	var lineColor = isBoxLine ? 0x9b59b6 : 0xd1b3e0;
	// Vertical
	var vLine = LK.getAsset('vLine' + i, {
		width: lineW,
		height: boardSize,
		color: lineColor,
		shape: 'box',
		anchorX: 0.5,
		anchorY: 0
	});
	vLine.x = i * cellSize;
	vLine.y = 0;
	boardContainer.addChild(vLine);
	// Horizontal
	var hLine = LK.getAsset('hLine' + i, {
		width: boardSize,
		height: lineW,
		color: lineColor,
		shape: 'box',
		anchorX: 0,
		anchorY: 0.5
	});
	hLine.x = 0;
	hLine.y = i * cellSize;
	boardContainer.addChild(hLine);
}
// Create cells
for (var r = 0; r < gridSize; r++) {
	board[r] = [];
	for (var c = 0; c < gridSize; c++) {
		// Ensure UnicornCell is defined before this point and all cells are instances of UnicornCell
		var cell = new UnicornCell();
		cell.x = c * cellSize + cellSize / 2;
		cell.y = r * cellSize + cellSize / 2;
		cell.row = r;
		cell.col = c;
		boardContainer.addChild(cell);
		board[r][c] = cell;
	}
}
// Fill in given cells and solution
for (var r = 0; r < gridSize; r++) {
	givenBoard[r] = [];
	solutionBoard[r] = [];
	for (var c = 0; c < gridSize; c++) {
		var idx = staticPuzzle[r][c];
		var cell = board[r][c];
		if (idx !== null) {
			cell.setUnicorn(idx, false);
			cell.isGiven = true;
			cell.bg.alpha = 0.7;
		}
		givenBoard[r][c] = idx;
		solutionBoard[r][c] = staticSolution[r][c];
	}
}
// --- Picker UI ---
// Place picker at the bottom of the board, centered horizontally, with margin from the board
picker = new UnicornPicker();
picker.visible = false;
// Calculate picker position: center horizontally, below the board with margin
var pickerMargin = 60;
picker.x = boardOffsetX + (boardSize - (9 * pickerIconSize + 8 * pickerGap + 32)) / 2;
picker.y = boardOffsetY + boardSize + pickerMargin;
game.addChild(picker);
// --- Title & Timer UI (side by side) ---
var titleTimerContainer = new Container();
// Title
var titleTxt = new Text2('Unicorn Sudoku', {
	size: 110,
	fill: 0xA569BD
});
titleTxt.anchor.set(0, 0); // left align
titleTxt.x = 0;
titleTxt.y = 0;
titleTimerContainer.addChild(titleTxt);
// Timer
timerTxt = new Text2('00:00', {
	size: 90,
	fill: 0x7D3C98
});
timerTxt.anchor.set(1, 0); // right align
timerTxt.x = 900; // enough space for title, adjust as needed
timerTxt.y = 10;
titleTimerContainer.addChild(timerTxt);
// Set container width and center it
titleTimerContainer.x = (2048 - 900) / 2;
titleTimerContainer.y = 0;
LK.gui.top.addChild(titleTimerContainer);
// --- Instructions UI ---
var instrTxt = new Text2('Tap a cell, then pick a unicorn to fill it!', {
	size: 60,
	fill: 0x7D3C98
});
instrTxt.anchor.set(0.5, 0);
instrTxt.y = 120;
LK.gui.top.addChild(instrTxt);
// --- Event Handlers ---
// Cell tap: select cell and show picker
function onCellDown(x, y, obj) {
	if (completed) {
		return;
	}
	var cell = obj;
	if (cell.isGiven) {
		return;
	}
	// If cell is already filled, do nothing
	if (cell.unicornIndex !== null) {
		return;
	}
	deselectAllCells();
	if (typeof cell.setSelected === "function") {
		cell.setSelected(true);
	}
	selectedCell = cell;
	// Determine possible unicorns for this cell
	var possible = [];
	if (cell.unicornIndex === null) {
		for (var i = 0; i < 4; i++) {
			if (isValidMove(cell.row, cell.col, i)) {
				possible.push(i);
			}
		}
	} else {
		// If cell is not empty, allow all (for clearing)
		for (var i = 0; i < 4; i++) {
			possible.push(i);
		}
	}
	// Show picker below the cell, but keep inside screen
	// Defensive: cell.position may be undefined, so fallback to cell.x/cell.y
	var cellPos = cell && cell.position ? cell.position : {
		x: cell.x,
		y: cell.y
	};
	var global = boardContainer.toGlobal(cellPos);
	var pickerX = Math.max(40, Math.min(global.x - pickerIconSize * 2, 2048 - pickerIconSize * 4 - 40));
	var pickerY = Math.min(global.y + cellSize / 2 + 30, 2732 - pickerIconSize - 80);
	picker.show(pickerX, pickerY);
	picker.setSelected(null);
	// Show only possible unicorns in picker
	for (var i = 0; i < picker.icons.length; i++) {
		picker.icons[i].visible = possible.indexOf(i) !== -1;
	}
}
// Picker tap: set unicorn in selected cell
function onPickerDown(x, y, obj) {
	if (!selectedCell || completed) {
		return;
	}
	var idx = obj.idx;
	if (idx === undefined) {
		return;
	}
	// If already has this unicorn, clear
	if (selectedCell.unicornIndex === idx) {
		selectedCell.clearUnicorn();
		picker.setSelected(null);
	} else {
		// Only allow placing if the unicorn is correct for this cell
		var correctIdx = solutionBoard[selectedCell.row][selectedCell.col];
		if (idx === correctIdx) {
			selectedCell.setUnicorn(idx, true);
			picker.setSelected(idx);
			// Remove this unicorn from picker options for this cell
			picker.icons[idx].visible = false;
		} else {
			// Optionally, flash error or ignore
			selectedCell.showError(true);
			LK.setTimeout(function () {
				selectedCell.showError(false);
			}, errorFlashDuration);
		}
	}
	highlightErrors();
	// Check for win
	if (isBoardComplete()) {
		completed = true;
		picker.hide();
		deselectAllCells();
		LK.effects.flashScreen(0x7d3c98, 800);
		LK.setTimeout(function () {
			LK.showYouWin();
		}, 900);
	}
}
// Hide picker if tap outside
function onGameDown(x, y, obj) {
	// If tap is not on a cell or picker, hide picker and deselect
	if (obj && (obj instanceof UnicornCell || obj === picker || picker.icons.indexOf(obj) !== -1)) {
		return;
	}
	picker.hide();
	deselectAllCells();
}
// --- Attach event handlers ---
// Attach to each cell
for (var r = 0; r < gridSize; r++) {
	for (var c = 0; c < gridSize; c++) {
		var cell = board[r][c];
		cell.down = onCellDown;
	}
}
// Attach to picker icons
for (var i = 0; i < 4; i++) {
	picker.icons[i].down = onPickerDown;
}
// Attach to game for outside tap
game.down = onGameDown;
// --- Timer Logic ---
function formatTime(secs) {
	var m = Math.floor(secs / 60);
	var s = secs % 60;
	return (m < 10 ? '0' : '') + m + ':' + (s < 10 ? '0' : '') + s;
}
function updateTimer() {
	if (completed) {
		return;
	}
	var now = Date.now();
	var elapsed = Math.floor((now - startTime) / 1000);
	timerTxt.setText(formatTime(elapsed));
}
// --- Game Start ---
function startGame() {
	completed = false;
	deselectAllCells();
	picker.hide();
	highlightErrors();
	startTime = Date.now();
	timerTxt.setText('00:00');
	if (timerInterval) {
		LK.clearInterval(timerInterval);
	}
	timerInterval = LK.setInterval(updateTimer, 1000);
}
startGame();
// --- Game Update (not used for logic, but required) ---
game.update = function () {
	// No per-frame logic needed for MVP
}; /**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
// UnicornCell: Represents a single cell in the Sudoku grid
var UnicornCell = Container.expand(function () {
	var self = Container.call(this);
	// Cell background (for selection/highlight)
	var bg = self.attachAsset('cellBg', {
		width: cellSize - 8,
		height: cellSize - 8,
		color: 0xffffff,
		shape: 'box',
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.bg = bg;
	// The unicorn icon (if any)
	self.icon = null;
	self.unicornIndex = null; // 0-8, or null if empty
	// Row, col for logic
	self.row = 0;
	self.col = 0;
	// Is this a given (pre-filled) cell?
	self.isGiven = false;
	// Show error highlight
	self.showError = function (on) {
		if (on) {
			tween(self.bg, {
				color: 0xffaaaa
			}, {
				duration: 200,
				easing: tween.easeIn
			});
		} else {
			tween(self.bg, {
				color: 0xffffff
			}, {
				duration: 200,
				easing: tween.easeOut
			});
		}
	};
	// Set unicorn icon
	self.setUnicorn = function (idx, animate) {
		if (self.icon) {
			self.removeChild(self.icon);
			self.icon = null;
		}
		self.unicornIndex = idx;
		if (idx !== null) {
			var icon = self.attachAsset('unicorn' + idx, {
				width: cellSize * 0.7,
				height: cellSize * 0.7,
				anchorX: 0.5,
				anchorY: 0.5
			});
			self.icon = icon;
			if (animate) {
				icon.scaleX = 0.2;
				icon.scaleY = 0.2;
				tween(icon, {
					scaleX: 1,
					scaleY: 1
				}, {
					duration: 180,
					easing: tween.bounceOut
				});
			}
		}
	};
	// Remove unicorn icon
	self.clearUnicorn = function () {
		if (self.icon) {
			self.removeChild(self.icon);
			self.icon = null;
		}
		self.unicornIndex = null;
	};
	// Selection highlight
	self.setSelected = function (on) {
		if (on) {
			tween(self.bg, {
				color: 0xcce6ff
			}, {
				duration: 120
			});
		} else {
			tween(self.bg, {
				color: 0xffffff
			}, {
				duration: 120
			});
		}
	};
	return self;
});
// UnicornPicker: The row of unicorn icons for selection
var UnicornPicker = Container.expand(function () {
	var self = Container.call(this);
	self.icons = [];
	self.visible = false;
	self.selectedIdx = null;
	// Add vertical space above icons
	var pickerTopPadding = 36; // extra space above icons
	// Create 4 unicorn icons
	for (var i = 0; i < 4; i++) {
		var icon = self.attachAsset('unicorn' + i, {
			width: pickerIconSize,
			height: pickerIconSize,
			anchorX: -1,
			anchorY: -1,
			x: i * (pickerIconSize + pickerGap),
			y: pickerTopPadding // shift icons down by padding
		});
		icon.idx = i;
		self.icons.push(icon);
	}
	// Background
	var pickerBg = self.attachAsset('pickerBg', {
		width: 4 * pickerIconSize + 3 * pickerGap + 32,
		height: pickerIconSize + 32 + pickerTopPadding,
		// increase height for top padding
		color: 0xf7e6ff,
		shape: 'box',
		anchorX: 0,
		anchorY: 0
	});
	pickerBg.x = -16;
	pickerBg.y = -16;
	self.setChildIndex(pickerBg, 0);
	// Highlight selected
	self.setSelected = function (idx) {
		for (var i = 0; i < self.icons.length; i++) {
			self.icons[i].alpha = i === idx ? 1 : 0.7;
			self.icons[i].scaleX = self.icons[i].scaleY = i === idx ? 1.15 : 1;
		}
		self.selectedIdx = idx;
	};
	// Show/hide
	self.show = function (x, y) {
		self.x = x;
		self.y = y;
		self.visible = true;
	};
	self.hide = function () {
		self.visible = false;
	};
	return self;
});
/**** 
* Initialize Game
****/ 
/**** 
* Game Constants
****/ 
// Board layout
// --- Game Initialization ---
var game = new LK.Game({
	backgroundColor: 0xf7e6ff
});
/**** 
* Game Code
****/ 
// Add unicorn image assets (replace with your actual unicorn image asset ids or use placeholder images)
// Board layout
/**** 
* Game Constants
****/ 
// --- Game State ---
var gridSize = 4;
var cellSize = 320; // 4*320 = 1280, fits well in 2048 width
var boardSize = cellSize * gridSize;
var boardOffsetX = (2048 - boardSize) / 2;
var boardOffsetY = 320;
// Picker
var pickerIconSize = 180;
var pickerGap = 32;
// For error highlight
var errorFlashDuration = 400;
// --- Asset Initialization ---
// 4 unicorn icons
for (var i = 0; i < 4; i++) {}
// Cell background
// Picker background
var board = []; // 2D array of UnicornCell
var givenBoard = []; // 2D array of unicorn indices (0-3) or null
var solutionBoard = []; // 2D array of unicorn indices (0-3)
var selectedCell = null;
var picker = null;
var timerTxt = null;
var startTime = null;
var timerInterval = null;
var errorCells = [];
var completed = false;
// --- Sudoku Puzzle Generation ---
// For MVP, use a static puzzle and solution (easy level)
// 4x4 puzzle, unicorn indices 0-3, 2x2 boxes
var staticPuzzle = [[null, 1, null, 2], [3, null, null, null], [null, null, null, 1], [2, null, 3, null]];
// Solution for the above puzzle (0-3 for unicorn indices, valid for 2x2 boxes)
var staticSolution = [[0, 1, 2, 3], [3, 2, 1, 0], [1, 3, 0, 2], [2, 0, 3, 1]];
// --- Helper Functions ---
// Returns true if placing unicornIdx at (row, col) is valid
function isValidMove(row, col, unicornIdx) {
	// Check row
	for (var c = 0; c < gridSize; c++) {
		if (c !== col && board[row][c].unicornIndex === unicornIdx) {
			return false;
		}
	}
	// Check col
	for (var r = 0; r < gridSize; r++) {
		if (r !== row && board[r][col].unicornIndex === unicornIdx) {
			return false;
		}
	}
	// Check 2x2 box for 4x4
	var boxRow = Math.floor(row / 2) * 2;
	var boxCol = Math.floor(col / 2) * 2;
	for (var r = boxRow; r < boxRow + 2; r++) {
		for (var c = boxCol; c < boxCol + 2; c++) {
			if ((r !== row || c !== col) && board[r][c].unicornIndex === unicornIdx) {
				return false;
			}
		}
	}
	return true;
}
// Returns true if the board is completely and correctly filled
function isBoardComplete() {
	for (var r = 0; r < gridSize; r++) {
		for (var c = 0; c < gridSize; c++) {
			var cell = board[r][c];
			if (cell.unicornIndex === null) {
				return false;
			}
			if (!isValidMove(r, c, cell.unicornIndex)) {
				return false;
			}
		}
	}
	return true;
}
// Highlight errors for current board state
function highlightErrors() {
	// Clear previous
	for (var i = 0; i < errorCells.length; i++) {
		errorCells[i].showError(false);
	}
	errorCells = [];
	// Check for errors
	for (var r = 0; r < gridSize; r++) {
		for (var c = 0; c < gridSize; c++) {
			var cell = board[r][c];
			if (cell.unicornIndex === null) {
				continue;
			}
			// Only highlight if not a given
			if (!cell.isGiven && !isValidMove(r, c, cell.unicornIndex)) {
				cell.showError(true);
				errorCells.push(cell);
			}
		}
	}
}
// Deselect all cells
function deselectAllCells() {
	for (var r = 0; r < gridSize; r++) {
		for (var c = 0; c < gridSize; c++) {
			if (typeof board[r][c].setSelected === "function") {
				board[r][c].setSelected(false);
			}
		}
	}
	selectedCell = null;
}
// --- UI Setup ---
// Board container
var boardContainer = new Container();
boardContainer.x = boardOffsetX;
boardContainer.y = boardOffsetY;
game.addChild(boardContainer);
// Draw grid lines (thick for boxes, thin for cells)
for (var i = 0; i <= gridSize; i++) {
	// For 4x4, thick lines at 0, 2, 4 (every 2 cells)
	var isBoxLine = i % 2 === 0;
	var lineW = isBoxLine ? 8 : 3;
	var lineColor = isBoxLine ? 0x9b59b6 : 0xd1b3e0;
	// Vertical
	var vLine = LK.getAsset('vLine' + i, {
		width: lineW,
		height: boardSize,
		color: lineColor,
		shape: 'box',
		anchorX: 0.5,
		anchorY: 0
	});
	vLine.x = i * cellSize;
	vLine.y = 0;
	boardContainer.addChild(vLine);
	// Horizontal
	var hLine = LK.getAsset('hLine' + i, {
		width: boardSize,
		height: lineW,
		color: lineColor,
		shape: 'box',
		anchorX: 0,
		anchorY: 0.5
	});
	hLine.x = 0;
	hLine.y = i * cellSize;
	boardContainer.addChild(hLine);
}
// Create cells
for (var r = 0; r < gridSize; r++) {
	board[r] = [];
	for (var c = 0; c < gridSize; c++) {
		// Ensure UnicornCell is defined before this point and all cells are instances of UnicornCell
		var cell = new UnicornCell();
		cell.x = c * cellSize + cellSize / 2;
		cell.y = r * cellSize + cellSize / 2;
		cell.row = r;
		cell.col = c;
		boardContainer.addChild(cell);
		board[r][c] = cell;
	}
}
// Fill in given cells and solution
for (var r = 0; r < gridSize; r++) {
	givenBoard[r] = [];
	solutionBoard[r] = [];
	for (var c = 0; c < gridSize; c++) {
		var idx = staticPuzzle[r][c];
		var cell = board[r][c];
		if (idx !== null) {
			cell.setUnicorn(idx, false);
			cell.isGiven = true;
			cell.bg.alpha = 0.7;
		}
		givenBoard[r][c] = idx;
		solutionBoard[r][c] = staticSolution[r][c];
	}
}
// --- Picker UI ---
// Place picker at the bottom of the board, centered horizontally, with margin from the board
picker = new UnicornPicker();
picker.visible = false;
// Calculate picker position: center horizontally, below the board with margin
var pickerMargin = 60;
picker.x = boardOffsetX + (boardSize - (9 * pickerIconSize + 8 * pickerGap + 32)) / 2;
picker.y = boardOffsetY + boardSize + pickerMargin;
game.addChild(picker);
// --- Title & Timer UI (side by side) ---
var titleTimerContainer = new Container();
// Title
var titleTxt = new Text2('Unicorn Sudoku', {
	size: 110,
	fill: 0xA569BD
});
titleTxt.anchor.set(0, 0); // left align
titleTxt.x = 0;
titleTxt.y = 0;
titleTimerContainer.addChild(titleTxt);
// Timer
timerTxt = new Text2('00:00', {
	size: 90,
	fill: 0x7D3C98
});
timerTxt.anchor.set(1, 0); // right align
timerTxt.x = 900; // enough space for title, adjust as needed
timerTxt.y = 10;
titleTimerContainer.addChild(timerTxt);
// Set container width and center it
titleTimerContainer.x = (2048 - 900) / 2;
titleTimerContainer.y = 0;
LK.gui.top.addChild(titleTimerContainer);
// --- Instructions UI ---
var instrTxt = new Text2('Tap a cell, then pick a unicorn to fill it!', {
	size: 60,
	fill: 0x7D3C98
});
instrTxt.anchor.set(0.5, 0);
instrTxt.y = 120;
LK.gui.top.addChild(instrTxt);
// --- Event Handlers ---
// Cell tap: select cell and show picker
function onCellDown(x, y, obj) {
	if (completed) {
		return;
	}
	var cell = obj;
	if (cell.isGiven) {
		return;
	}
	// If cell is already filled, do nothing
	if (cell.unicornIndex !== null) {
		return;
	}
	deselectAllCells();
	if (typeof cell.setSelected === "function") {
		cell.setSelected(true);
	}
	selectedCell = cell;
	// Determine possible unicorns for this cell
	var possible = [];
	if (cell.unicornIndex === null) {
		for (var i = 0; i < 4; i++) {
			if (isValidMove(cell.row, cell.col, i)) {
				possible.push(i);
			}
		}
	} else {
		// If cell is not empty, allow all (for clearing)
		for (var i = 0; i < 4; i++) {
			possible.push(i);
		}
	}
	// Show picker below the cell, but keep inside screen
	// Defensive: cell.position may be undefined, so fallback to cell.x/cell.y
	var cellPos = cell && cell.position ? cell.position : {
		x: cell.x,
		y: cell.y
	};
	var global = boardContainer.toGlobal(cellPos);
	var pickerX = Math.max(40, Math.min(global.x - pickerIconSize * 2, 2048 - pickerIconSize * 4 - 40));
	var pickerY = Math.min(global.y + cellSize / 2 + 30, 2732 - pickerIconSize - 80);
	picker.show(pickerX, pickerY);
	picker.setSelected(null);
	// Show only possible unicorns in picker
	for (var i = 0; i < picker.icons.length; i++) {
		picker.icons[i].visible = possible.indexOf(i) !== -1;
	}
}
// Picker tap: set unicorn in selected cell
function onPickerDown(x, y, obj) {
	if (!selectedCell || completed) {
		return;
	}
	var idx = obj.idx;
	if (idx === undefined) {
		return;
	}
	// If already has this unicorn, clear
	if (selectedCell.unicornIndex === idx) {
		selectedCell.clearUnicorn();
		picker.setSelected(null);
	} else {
		// Only allow placing if the unicorn is correct for this cell
		var correctIdx = solutionBoard[selectedCell.row][selectedCell.col];
		if (idx === correctIdx) {
			selectedCell.setUnicorn(idx, true);
			picker.setSelected(idx);
			// Remove this unicorn from picker options for this cell
			picker.icons[idx].visible = false;
		} else {
			// Optionally, flash error or ignore
			selectedCell.showError(true);
			LK.setTimeout(function () {
				selectedCell.showError(false);
			}, errorFlashDuration);
		}
	}
	highlightErrors();
	// Check for win
	if (isBoardComplete()) {
		completed = true;
		picker.hide();
		deselectAllCells();
		LK.effects.flashScreen(0x7d3c98, 800);
		LK.setTimeout(function () {
			LK.showYouWin();
		}, 900);
	}
}
// Hide picker if tap outside
function onGameDown(x, y, obj) {
	// If tap is not on a cell or picker, hide picker and deselect
	if (obj && (obj instanceof UnicornCell || obj === picker || picker.icons.indexOf(obj) !== -1)) {
		return;
	}
	picker.hide();
	deselectAllCells();
}
// --- Attach event handlers ---
// Attach to each cell
for (var r = 0; r < gridSize; r++) {
	for (var c = 0; c < gridSize; c++) {
		var cell = board[r][c];
		cell.down = onCellDown;
	}
}
// Attach to picker icons
for (var i = 0; i < 4; i++) {
	picker.icons[i].down = onPickerDown;
}
// Attach to game for outside tap
game.down = onGameDown;
// --- Timer Logic ---
function formatTime(secs) {
	var m = Math.floor(secs / 60);
	var s = secs % 60;
	return (m < 10 ? '0' : '') + m + ':' + (s < 10 ? '0' : '') + s;
}
function updateTimer() {
	if (completed) {
		return;
	}
	var now = Date.now();
	var elapsed = Math.floor((now - startTime) / 1000);
	timerTxt.setText(formatTime(elapsed));
}
// --- Game Start ---
function startGame() {
	completed = false;
	deselectAllCells();
	picker.hide();
	highlightErrors();
	startTime = Date.now();
	timerTxt.setText('00:00');
	if (timerInterval) {
		LK.clearInterval(timerInterval);
	}
	timerInterval = LK.setInterval(updateTimer, 1000);
}
startGame();
// --- Game Update (not used for logic, but required) ---
game.update = function () {
	// No per-frame logic needed for MVP
};