Upload 3 files
Browse files- index.html +51 -19
- script.js +213 -0
- style.css +139 -17
index.html
CHANGED
|
@@ -1,19 +1,51 @@
|
|
| 1 |
-
<!
|
| 2 |
-
<html>
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>Multiplication Farm! 🧑🌾</title>
|
| 7 |
+
<link rel="stylesheet" href="style.css">
|
| 8 |
+
<link href="https://fonts.googleapis.com/css2?family=Lilita+One&display=swap" rel="stylesheet">
|
| 9 |
+
</head>
|
| 10 |
+
<body>
|
| 11 |
+
|
| 12 |
+
<div id="game-wrapper">
|
| 13 |
+
|
| 14 |
+
<h1>Multiplication Farm!</h1>
|
| 15 |
+
|
| 16 |
+
<div id="score-area">
|
| 17 |
+
Score: <span id="score">0</span> / <span id="total-questions">10</span>
|
| 18 |
+
</div>
|
| 19 |
+
|
| 20 |
+
<div id="problem-area">
|
| 21 |
+
<h2>Time to Plant/Gather!</h2>
|
| 22 |
+
<p>Show me this multiplication:</p>
|
| 23 |
+
<div id="multiplication-problem">
|
| 24 |
+
<span id="num1">?</span> x <span id="num2">?</span> = ?
|
| 25 |
+
</div>
|
| 26 |
+
</div>
|
| 27 |
+
|
| 28 |
+
<div id="feedback-area">
|
| 29 |
+
Click the farm plot that matches the problem!
|
| 30 |
+
</div>
|
| 31 |
+
|
| 32 |
+
<div id="farm-options-area">
|
| 33 |
+
<h2>Choose the Correct Farm Plot:</h2>
|
| 34 |
+
<div id="field-choices">
|
| 35 |
+
<!-- Farm plot options will be dynamically added here by JS -->
|
| 36 |
+
<!-- Example of one plot option structure (repeated by JS) -->
|
| 37 |
+
<!--
|
| 38 |
+
<div class="field-option" data-rows="3" data-cols="4">
|
| 39 |
+
<div class="item">🍎</div> <div class="item">🍎</div> <div class="item">🍎</div> <div class="item">🍎</div>
|
| 40 |
+
<div class="item">🍎</div> <div class="item">🍎</div> <div class="item">🍎</div> <div class="item">🍎</div>
|
| 41 |
+
<div class="item">🍎</div> <div class="item">🍎</div> <div class="item">🍎</div> <div class="item">🍎</div>
|
| 42 |
+
</div>
|
| 43 |
+
-->
|
| 44 |
+
</div>
|
| 45 |
+
</div>
|
| 46 |
+
|
| 47 |
+
</div> <!-- End of game-wrapper -->
|
| 48 |
+
|
| 49 |
+
<script src="script.js"></script>
|
| 50 |
+
</body>
|
| 51 |
+
</html>
|
script.js
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
document.addEventListener('DOMContentLoaded', () => {
|
| 2 |
+
const scoreDisplay = document.getElementById('score');
|
| 3 |
+
const totalQuestionsDisplay = document.getElementById('total-questions');
|
| 4 |
+
const num1Display = document.getElementById('num1');
|
| 5 |
+
const num2Display = document.getElementById('num2');
|
| 6 |
+
const feedbackArea = document.getElementById('feedback-area');
|
| 7 |
+
const fieldChoicesContainer = document.getElementById('field-choices');
|
| 8 |
+
|
| 9 |
+
const OPTIONS_COUNT = 3; // Number of plot choices (1 correct, 2 incorrect)
|
| 10 |
+
const MAX_FACTOR = 6; // Maximum number for factors (e.g., up to 6x6)
|
| 11 |
+
const TOTAL_ROUNDS = 10; // Number of questions in a game
|
| 12 |
+
|
| 13 |
+
// --- Items for the Farm ---
|
| 14 |
+
const farmItems = ['🍎', '🥕', '🐔', '🐑', '🌻', '🌽'];
|
| 15 |
+
|
| 16 |
+
// --- Generate Multiplication Problems ---
|
| 17 |
+
let possibleProblems = [];
|
| 18 |
+
function generateProblems() {
|
| 19 |
+
possibleProblems = [];
|
| 20 |
+
for (let i = 1; i <= MAX_FACTOR; i++) {
|
| 21 |
+
// Start j from 1 to include squares and both orders (e.g., 2x3 and 3x2 are distinct visual arrays)
|
| 22 |
+
for (let j = 1; j <= MAX_FACTOR; j++) {
|
| 23 |
+
possibleProblems.push({ num1: i, num2: j, answer: i * j });
|
| 24 |
+
}
|
| 25 |
+
}
|
| 26 |
+
// Remove duplicates might be needed if we consider A*B same as B*A later
|
| 27 |
+
}
|
| 28 |
+
|
| 29 |
+
// --- Game State ---
|
| 30 |
+
let score = 0;
|
| 31 |
+
let currentProblem = null;
|
| 32 |
+
let currentRound = 0;
|
| 33 |
+
let waitingForNext = false;
|
| 34 |
+
|
| 35 |
+
// --- Utility: Get Random Int ---
|
| 36 |
+
function getRandomInt(max) {
|
| 37 |
+
return Math.floor(Math.random() * max);
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
// --- Utility: Shuffle Array ---
|
| 41 |
+
function shuffleArray(array) {
|
| 42 |
+
for (let i = array.length - 1; i > 0; i--) {
|
| 43 |
+
const j = getRandomInt(i + 1);
|
| 44 |
+
[array[i], array[j]] = [array[j], array[i]];
|
| 45 |
+
}
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
// --- Setup a New Round ---
|
| 49 |
+
function setupNewRound() {
|
| 50 |
+
if (currentRound >= TOTAL_ROUNDS) {
|
| 51 |
+
endGame();
|
| 52 |
+
return;
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
+
waitingForNext = false;
|
| 56 |
+
fieldChoicesContainer.innerHTML = '';
|
| 57 |
+
feedbackArea.textContent = "Click the farm plot that matches the problem!";
|
| 58 |
+
feedbackArea.className = '';
|
| 59 |
+
|
| 60 |
+
currentRound++;
|
| 61 |
+
|
| 62 |
+
// 1. Choose a target problem
|
| 63 |
+
if (!possibleProblems || possibleProblems.length === 0) generateProblems(); // Regenerate if empty
|
| 64 |
+
const problemIndex = getRandomInt(possibleProblems.length);
|
| 65 |
+
currentProblem = possibleProblems.splice(problemIndex, 1)[0]; // Pick and remove
|
| 66 |
+
|
| 67 |
+
num1Display.textContent = currentProblem.num1;
|
| 68 |
+
num2Display.textContent = currentProblem.num2;
|
| 69 |
+
|
| 70 |
+
// 2. Create options array (as {rows, cols})
|
| 71 |
+
// Allow commutative property visually (3x4 can be 3 rows of 4 OR 4 rows of 3)
|
| 72 |
+
const correctOption = { rows: currentProblem.num1, cols: currentProblem.num2 };
|
| 73 |
+
const options = [correctOption];
|
| 74 |
+
|
| 75 |
+
// 3. Generate incorrect options
|
| 76 |
+
while (options.length < OPTIONS_COUNT) {
|
| 77 |
+
let wrongRows, wrongCols;
|
| 78 |
+
let isDuplicate = true;
|
| 79 |
+
let attempts = 0; // Prevent infinite loop
|
| 80 |
+
|
| 81 |
+
while(isDuplicate && attempts < 20) {
|
| 82 |
+
// Generate wrong dimensions, make sure at least one is different
|
| 83 |
+
const changeRows = Math.random() > 0.5;
|
| 84 |
+
wrongRows = changeRows ? getRandomInt(MAX_FACTOR) + 1 : correctOption.rows;
|
| 85 |
+
wrongCols = !changeRows ? getRandomInt(MAX_FACTOR) + 1 : correctOption.cols;
|
| 86 |
+
|
| 87 |
+
// Ensure it's actually wrong AND not zero product AND different from target
|
| 88 |
+
if((wrongRows !== correctOption.rows || wrongCols !== correctOption.cols) &&
|
| 89 |
+
(wrongRows * wrongCols > 0) ) {
|
| 90 |
+
|
| 91 |
+
// Check if this combination (or its commutative pair) is already in options
|
| 92 |
+
isDuplicate = options.some(opt =>
|
| 93 |
+
(opt.rows === wrongRows && opt.cols === wrongCols) ||
|
| 94 |
+
(opt.rows === wrongCols && opt.cols === wrongRows)
|
| 95 |
+
);
|
| 96 |
+
} else {
|
| 97 |
+
isDuplicate = true; // Force retry if generated same as correct or zero product
|
| 98 |
+
}
|
| 99 |
+
attempts++;
|
| 100 |
+
}
|
| 101 |
+
// If stuck finding unique, just create a simple wrong one
|
| 102 |
+
if (attempts >= 20) {
|
| 103 |
+
wrongRows = correctOption.rows === 1 ? 2 : correctOption.rows -1;
|
| 104 |
+
wrongCols = correctOption.cols;
|
| 105 |
+
isDuplicate = options.some(opt =>
|
| 106 |
+
(opt.rows === wrongRows && opt.cols === wrongCols) ||
|
| 107 |
+
(opt.rows === wrongCols && opt.cols === wrongRows)
|
| 108 |
+
); // Final check
|
| 109 |
+
}
|
| 110 |
+
|
| 111 |
+
|
| 112 |
+
if (!isDuplicate) {
|
| 113 |
+
options.push({ rows: wrongRows, cols: wrongCols });
|
| 114 |
+
}
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
// 4. Shuffle options
|
| 118 |
+
shuffleArray(options);
|
| 119 |
+
|
| 120 |
+
// 5. Create and display field elements
|
| 121 |
+
options.forEach(plot => {
|
| 122 |
+
const fieldDiv = document.createElement('div');
|
| 123 |
+
fieldDiv.classList.add('field-option');
|
| 124 |
+
fieldDiv.dataset.rows = plot.rows;
|
| 125 |
+
fieldDiv.dataset.cols = plot.cols;
|
| 126 |
+
|
| 127 |
+
// Style the grid layout for items *inside* this field
|
| 128 |
+
fieldDiv.style.gridTemplateColumns = `repeat(${plot.cols}, auto)`; // auto size columns
|
| 129 |
+
fieldDiv.style.gridTemplateRows = `repeat(${plot.rows}, auto)`; // auto size rows
|
| 130 |
+
// Set a max-width to prevent huge single rows/columns
|
| 131 |
+
fieldDiv.style.maxWidth = `${plot.cols * 35}px`; // Approx item size + gap
|
| 132 |
+
|
| 133 |
+
|
| 134 |
+
// Add items (emoji)
|
| 135 |
+
const itemEmoji = farmItems[getRandomInt(farmItems.length)];
|
| 136 |
+
for (let i = 0; i < plot.rows * plot.cols; i++) {
|
| 137 |
+
const itemSpan = document.createElement('span');
|
| 138 |
+
itemSpan.classList.add('item');
|
| 139 |
+
itemSpan.textContent = itemEmoji;
|
| 140 |
+
fieldDiv.appendChild(itemSpan);
|
| 141 |
+
}
|
| 142 |
+
|
| 143 |
+
fieldDiv.addEventListener('click', handleChoiceClick);
|
| 144 |
+
fieldChoicesContainer.appendChild(fieldDiv);
|
| 145 |
+
});
|
| 146 |
+
|
| 147 |
+
console.log("New round setup. Target:", currentProblem);
|
| 148 |
+
}
|
| 149 |
+
|
| 150 |
+
// --- Handle Field Choice Click ---
|
| 151 |
+
function handleChoiceClick(event) {
|
| 152 |
+
if (waitingForNext) return;
|
| 153 |
+
|
| 154 |
+
const clickedField = event.currentTarget;
|
| 155 |
+
const clickedRows = parseInt(clickedField.dataset.rows);
|
| 156 |
+
const clickedCols = parseInt(clickedField.dataset.cols);
|
| 157 |
+
|
| 158 |
+
waitingForNext = true;
|
| 159 |
+
|
| 160 |
+
// Remove listeners
|
| 161 |
+
document.querySelectorAll('.field-option').forEach(opt => {
|
| 162 |
+
const clone = opt.cloneNode(true);
|
| 163 |
+
opt.parentNode.replaceChild(clone, opt);
|
| 164 |
+
});
|
| 165 |
+
|
| 166 |
+
// Check if correct (allow commutative: A x B or B x A)
|
| 167 |
+
const isCorrect = (clickedRows === currentProblem.num1 && clickedCols === currentProblem.num2) ||
|
| 168 |
+
(clickedRows === currentProblem.num2 && clickedCols === currentProblem.num1);
|
| 169 |
+
|
| 170 |
+
if (isCorrect) {
|
| 171 |
+
score++;
|
| 172 |
+
scoreDisplay.textContent = score;
|
| 173 |
+
feedbackArea.textContent = `Yes! ${currentProblem.num1} x ${currentProblem.num2} = ${currentProblem.answer}! 🎉`;
|
| 174 |
+
feedbackArea.className = 'correct-feedback';
|
| 175 |
+
|
| 176 |
+
const newClickedElement = fieldChoicesContainer.querySelector(`.field-option[data-rows="${clickedRows}"][data-cols="${clickedCols}"]`);
|
| 177 |
+
if (newClickedElement) newClickedElement.classList.add('correct-choice');
|
| 178 |
+
|
| 179 |
+
} else {
|
| 180 |
+
feedbackArea.textContent = `Oops! That shows ${clickedRows} x ${clickedCols}. The answer was ${currentProblem.answer}. 🤔`;
|
| 181 |
+
feedbackArea.className = 'incorrect-feedback';
|
| 182 |
+
|
| 183 |
+
const newClickedElement = fieldChoicesContainer.querySelector(`.field-option[data-rows="${clickedRows}"][data-cols="${clickedCols}"]`);
|
| 184 |
+
if (newClickedElement) newClickedElement.classList.add('incorrect-choice');
|
| 185 |
+
|
| 186 |
+
// Highlight the correct answer(s)
|
| 187 |
+
setTimeout(() => {
|
| 188 |
+
const correctElement1 = fieldChoicesContainer.querySelector(`.field-option[data-rows="${currentProblem.num1}"][data-cols="${currentProblem.num2}"]`);
|
| 189 |
+
if (correctElement1) correctElement1.classList.add('correct-choice');
|
| 190 |
+
// Also highlight commutative pair if it exists and is different
|
| 191 |
+
const correctElement2 = fieldChoicesContainer.querySelector(`.field-option[data-rows="${currentProblem.num2}"][data-cols="${currentProblem.num1}"]`);
|
| 192 |
+
if (correctElement2 && correctElement1 !== correctElement2) correctElement2.classList.add('correct-choice');
|
| 193 |
+
}, 300);
|
| 194 |
+
}
|
| 195 |
+
|
| 196 |
+
// Load next round
|
| 197 |
+
setTimeout(setupNewRound, 2500); // Longer delay to see feedback/answer
|
| 198 |
+
}
|
| 199 |
+
|
| 200 |
+
// --- End Game ---
|
| 201 |
+
function endGame() {
|
| 202 |
+
feedbackArea.textContent = `Game Over! Your final score: ${score} / ${TOTAL_ROUNDS}! Great work! 🥳`;
|
| 203 |
+
feedbackArea.className = 'correct-feedback'; // Use correct style for positive end
|
| 204 |
+
fieldChoicesContainer.innerHTML = '<p style="font-size:1.2em; color: #795548;">Refresh the page to play again!</p>'; // Clear options
|
| 205 |
+
// Optionally disable further interaction if needed
|
| 206 |
+
}
|
| 207 |
+
|
| 208 |
+
// --- Initial Game Start ---
|
| 209 |
+
totalQuestionsDisplay.textContent = TOTAL_ROUNDS; // Set total rounds display
|
| 210 |
+
generateProblems(); // Create the initial list of problems
|
| 211 |
+
setupNewRound();
|
| 212 |
+
|
| 213 |
+
}); // End DOMContentLoaded
|
style.css
CHANGED
|
@@ -1,28 +1,150 @@
|
|
| 1 |
body {
|
| 2 |
-
|
| 3 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
}
|
| 5 |
|
| 6 |
h1 {
|
| 7 |
-
|
| 8 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
}
|
| 10 |
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
margin-top: 5px;
|
| 16 |
}
|
| 17 |
|
| 18 |
-
.
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
padding: 16px;
|
| 22 |
-
border: 1px solid lightgray;
|
| 23 |
-
border-radius: 16px;
|
| 24 |
}
|
| 25 |
|
| 26 |
-
|
| 27 |
-
|
|
|
|
|
|
|
| 28 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
body {
|
| 2 |
+
font-family: 'Lilita One', cursive;
|
| 3 |
+
display: flex;
|
| 4 |
+
justify-content: center;
|
| 5 |
+
align-items: flex-start;
|
| 6 |
+
background-color: #c8e6c9; /* Light green background */
|
| 7 |
+
color: #388e3c; /* Darker green */
|
| 8 |
+
padding: 20px;
|
| 9 |
+
margin: 0;
|
| 10 |
+
min-height: 100vh;
|
| 11 |
+
}
|
| 12 |
+
|
| 13 |
+
#game-wrapper {
|
| 14 |
+
background-color: #fffde7; /* Light yellow */
|
| 15 |
+
padding: 20px 30px;
|
| 16 |
+
border-radius: 20px;
|
| 17 |
+
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.15);
|
| 18 |
+
border: 5px solid #795548; /* Brown border */
|
| 19 |
+
max-width: 700px;
|
| 20 |
+
width: 95%;
|
| 21 |
+
text-align: center;
|
| 22 |
}
|
| 23 |
|
| 24 |
h1 {
|
| 25 |
+
color: #fb8c00; /* Orange */
|
| 26 |
+
text-shadow: 2px 2px 2px rgba(0, 0, 0, 0.1);
|
| 27 |
+
margin-bottom: 15px;
|
| 28 |
+
}
|
| 29 |
+
|
| 30 |
+
#score-area {
|
| 31 |
+
font-size: 1.2em;
|
| 32 |
+
font-weight: bold;
|
| 33 |
+
color: #1e88e5; /* Blue */
|
| 34 |
+
background-color: #e3f2fd; /* Light blue */
|
| 35 |
+
padding: 5px 15px;
|
| 36 |
+
border-radius: 10px;
|
| 37 |
+
display: inline-block;
|
| 38 |
+
margin-bottom: 20px;
|
| 39 |
+
border: 2px solid #90caf9; /* Lighter blue border */
|
| 40 |
+
}
|
| 41 |
+
|
| 42 |
+
#problem-area {
|
| 43 |
+
background-color: #ffecb3; /* Light amber */
|
| 44 |
+
border: 3px dashed #ff8f00; /* Amber dashed border */
|
| 45 |
+
padding: 15px;
|
| 46 |
+
border-radius: 15px;
|
| 47 |
+
margin-bottom: 20px;
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
#problem-area h2 {
|
| 51 |
+
margin-top: 0;
|
| 52 |
+
margin-bottom: 5px;
|
| 53 |
+
color: #795548; /* Brown */
|
| 54 |
+
}
|
| 55 |
+
#problem-area p {
|
| 56 |
+
margin-top: 0;
|
| 57 |
+
margin-bottom: 10px;
|
| 58 |
+
font-size: 1.1em;
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
#multiplication-problem {
|
| 63 |
+
font-size: 2.8em; /* Large problem display */
|
| 64 |
+
font-weight: bold;
|
| 65 |
+
color: #e53935; /* Red */
|
| 66 |
+
}
|
| 67 |
+
|
| 68 |
+
#feedback-area {
|
| 69 |
+
margin-bottom: 25px;
|
| 70 |
+
font-size: 1.1em;
|
| 71 |
+
font-weight: bold;
|
| 72 |
+
color: #5d4037; /* Brown */
|
| 73 |
+
min-height: 30px;
|
| 74 |
+
padding: 10px;
|
| 75 |
+
border-radius: 8px;
|
| 76 |
+
background-color: #efebe9; /* Light brown/grey */
|
| 77 |
+
}
|
| 78 |
+
|
| 79 |
+
#feedback-area.correct-feedback {
|
| 80 |
+
color: #2e7d32; /* Dark Green */
|
| 81 |
+
background-color: #c8e6c9; /* Light Green */
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
#feedback-area.incorrect-feedback {
|
| 85 |
+
color: #c62828; /* Dark Red */
|
| 86 |
+
background-color: #ffcdd2; /* Light Red */
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
#farm-options-area h2 {
|
| 90 |
+
color: #795548; /* Brown */
|
| 91 |
+
margin-bottom: 15px;
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
#field-choices {
|
| 95 |
+
display: flex;
|
| 96 |
+
justify-content: space-around;
|
| 97 |
+
align-items: flex-start; /* Align tops of potentially diff height grids */
|
| 98 |
+
flex-wrap: wrap;
|
| 99 |
+
gap: 25px; /* Space between plot options */
|
| 100 |
+
}
|
| 101 |
+
|
| 102 |
+
.field-option {
|
| 103 |
+
cursor: pointer;
|
| 104 |
+
border: 4px solid #a1887f; /* Brownish border */
|
| 105 |
+
background-color: #d7ccc8; /* Light background for field */
|
| 106 |
+
padding: 10px;
|
| 107 |
+
border-radius: 8px;
|
| 108 |
+
transition: border-color 0.2s ease, transform 0.2s ease;
|
| 109 |
+
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
|
| 110 |
+
|
| 111 |
+
/* CSS Grid for items inside */
|
| 112 |
+
display: grid;
|
| 113 |
+
gap: 4px; /* Space between items */
|
| 114 |
+
/* grid-template-columns/rows set by JS */
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
.field-option:hover {
|
| 118 |
+
border-color: #fb8c00; /* Orange hover border */
|
| 119 |
+
transform: translateY(-3px);
|
| 120 |
+
}
|
| 121 |
+
|
| 122 |
+
.field-option .item {
|
| 123 |
+
font-size: 1.8em; /* Size of the emoji/item */
|
| 124 |
+
line-height: 1; /* Prevent extra vertical space */
|
| 125 |
+
display: flex;
|
| 126 |
+
justify-content: center;
|
| 127 |
+
align-items: center;
|
| 128 |
}
|
| 129 |
|
| 130 |
+
/* Feedback Animations */
|
| 131 |
+
.field-option.correct-choice {
|
| 132 |
+
border-color: #4caf50 !important; /* Green border */
|
| 133 |
+
animation: pulse 0.6s;
|
|
|
|
| 134 |
}
|
| 135 |
|
| 136 |
+
.field-option.incorrect-choice {
|
| 137 |
+
border-color: #f44336 !important; /* Red border */
|
| 138 |
+
animation: shake 0.5s;
|
|
|
|
|
|
|
|
|
|
| 139 |
}
|
| 140 |
|
| 141 |
+
@keyframes shake {
|
| 142 |
+
0%, 100% { transform: translateX(0); }
|
| 143 |
+
25% { transform: translateX(-6px); }
|
| 144 |
+
75% { transform: translateX(6px); }
|
| 145 |
}
|
| 146 |
+
@keyframes pulse {
|
| 147 |
+
0% { transform: scale(1); }
|
| 148 |
+
50% { transform: scale(1.05); }
|
| 149 |
+
100% { transform: scale(1); }
|
| 150 |
+
}
|