Gemini Games

Size Sequencing Game body { font-family: ‘Inter’, Arial, sans-serif; background-color: #f1f5f9; /* slate-100 */ margin: 0; padding: 16px; min-height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: center; box-sizing: border-box; overscroll-behavior: none; } ::selection { background-color: #7dd3fc; /* sky-300 */ } #game-container { background-color: #ffffff; /* white */ padding: 24px; /* roughly p-6 */ border-radius: 12px; /* rounded-xl */ box-shadow: 0 20px 25px -5px rgba(0,0,0,0.1), 0 10px 10px -5px rgba(0,0,0,0.04); /* shadow-2xl */ width: 100%; max-width: 672px; /* max-w-2xl */ box-sizing: border-box; } header { margin-bottom: 24px; /* mb-6 */ text-align: center; } #activity-title { font-size: 24px; /* roughly text-2xl */ font-weight: bold; color: #334155; /* slate-700 */ } #instruction { color: #64748b; /* slate-500 */ margin-top: 4px; /* mt-1 */ font-size: 14px; /* roughly text-sm */ } #target-zones-container { margin-bottom: 32px; /* mb-8 */ padding: 8px; /* p-2 */ background-color: #f8fafc; /* slate-50 */ border-radius: 8px; /* rounded-lg */ } #target-zones { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; /* gap-4 */ } .drop-zone { border: 2px dashed #cbd5e1; /* cool-gray-300 */ min-height: 100px; /* Adjusted from 120px to fit better */ aspect-ratio: 1 / 1; display: flex; flex-direction: column; align-items: center; justify-content: center; transition: background-color 0.2s ease; position: relative; padding-bottom: 20px; border-radius: 6px; /* rounded-md */ box-sizing: border-box; } .drop-zone-label { position: absolute; bottom: 4px; font-size: 0.75rem; color: #64748b; /* slate-500 */ user-select: none; } .drop-zone-hover { background-color: #e2e8f0; /* cool-gray-200 */ } .drop-zone.occupied { border-style: solid; border-color: #94a3b8; /* cool-gray-400 */ } .drop-zone .draggable-item { flex-shrink: 0; margin-top: auto; margin-bottom: auto; } #source-objects-container { padding: 12px; /* p-3 */ background-color: #e2e8f0; /* slate-200 */ border-radius: 8px; /* rounded-lg */ min-height: 120px; /* Adjusted */ display: flex; align-items: center; justify-content: center; } #source-placeholder { color: #64748b; /* slate-500 */ font-style: italic; } #source-objects { display: flex; flex-wrap: wrap; gap: 12px; /* roughly gap-3/gap-4 */ align-items: center; justify-content: center; } .draggable-item { touch-action: none; cursor: grab; display: flex; align-items: center; justify-content: center; border: 2px solid transparent; transition: transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out; box-shadow: 0 1px 3px 0 rgba(0,0,0,0.1), 0 1px 2px 0 rgba(0,0,0,0.06); /* shadow */ } .draggable-item:active { cursor: grabbing; transform: scale(1.1); box-shadow: 0 4px 6px -1px rgba(0,0,0,0.1), 0 2px 4px -1px rgba(0,0,0,0.06); /* shadow-md */ z-index: 1000; } .dragging { opacity: 0.5; } /* Shape specific styles */ .shape-circle { border-radius: 50%; } .shape-oval { border-radius: 50%; } .shape-square { border-radius: 0.375rem; } /* 6px */ .shape-rectangle { border-radius: 0.375rem; } /* 6px */ .shape-star { background: transparent !important; border: none !important; box-shadow: none !important; color: #f59e0b; /* amber-500 for star color */ } /* Item background colors (approximations) */ .bg-blue-500 { background-color: #3b82f6; } .bg-yellow-400 { background-color: #facc15; } .bg-red-500 { background-color: #ef4444; } .bg-green-500 { background-color: #22c55e; } .bg-purple-500 { background-color: #a855f7; } .bg-orange-500 { background-color: #f97316; } .bg-teal-500 { background-color: #14b8a6; } .bg-pink-500 { background-color: #ec4899; } .bg-indigo-500 { background-color: #6366f1; } .bg-cyan-500 { background-color: #06b6d4; } .bg-lime-500 { background-color: #84cc16; } .bg-rose-500 { background-color: #f43f5e; } /* Star text colors are handled by .shape-star, font sizes by specific text classes if needed */ .text-xl { font-size: 1.25rem; } .text-3xl { font-size: 1.875rem; } .text-5xl { font-size: 3rem; } footer { margin-top: 32px; /* mt-8 */ text-align: center; } #feedback-message { min-height: 2em; /* Ensure space for message */ font-size: 1.125rem; /* text-lg */ font-weight: 500; /* font-medium */ margin-bottom: 16px; /* mb-4 */ } .text-green-600 { color: #16a34a; } .text-red-600 { color: #dc2626; } button { color: white; font-weight: 600; /* font-semibold */ padding: 10px 20px; /* py-2/2.5 px-4/5 */ border-radius: 8px; /* rounded-lg */ box-shadow: 0 1px 3px 0 rgba(0,0,0,0.1), 0 1px 2px 0 rgba(0,0,0,0.06); /* shadow */ transition: background-color 0.15s ease; cursor: pointer; border: none; } button:disabled { opacity: 0.7; cursor: not-allowed; } #reset-activity-button { background-color: #f59e0b; /* amber-500 */ margin-right: 8px; /* mr-2 */ } #reset-activity-button:hover { background-color: #d97706; /* amber-600 */ } #next-activity-button { background-color: #0ea5e9; /* sky-500 */ } #next-activity-button:hover { background-color: #0284c7; /* sky-600 */ } .hidden { display: none !important; } /* !important to override other display styles */ #all-activities-complete { font-size: 1.5rem; /* text-2xl */ font-weight: bold; color: #16a34a; /* green-600 */ margin-top: 16px; /* mt-4 */ } /* Modal styles */ .modal { display: none; position: fixed; z-index: 1001; left: 0; top: 0; width: 100%; height: 100%; overflow: auto; background-color: rgba(0,0,0,0.5); justify-content: center; align-items: center; } .modal-content { background-color: #ffffff; margin: auto; padding: 32px; /* p-8 */ border-radius: 0.5rem; text-align: center; box-shadow: 0 10px 15px -3px rgba(0,0,0,0.1), 0 4px 6px -2px rgba(0,0,0,0.05); width: 90%; max-width: 320px; } #success-emoji-display { font-size: 4rem; line-height: 1; display: block; animation: emoji-pop 0.6s cubic-bezier(0.68, -0.55, 0.27, 1.55); } @keyframes emoji-pop { 0% { transform: scale(0.5) rotate(-15deg); opacity: 0; } 60% { transform: scale(1.2) rotate(10deg); } 100% { transform: scale(1) rotate(0deg); opacity: 1; } } #success-message-modal { font-size: 1.25rem; /* text-xl */ font-weight: 600; /* font-semibold */ color: #334155; /* slate-700 */ margin-top: 16px; /* mt-4 */ } #modal-close-button { margin-top: 24px; /* mt-6 */ background-color: #0ea5e9; /* sky-500 */ } #modal-close-button:hover { background-color: #0284c7; /* sky-600 */ } @media (min-width: 640px) { /* sm breakpoint */ #activity-title { font-size: 30px; } /* sm:text-3xl */ #instruction { font-size: 1rem; } /* sm:text-base */ button { padding: 12px 24px; } /* sm:py-3 sm:px-6 */ #target-zones { gap: 16px; } /* sm:gap-4 */ #source-objects-container { min-height: 140px; } }

Loading Activity…

Drag the shapes from the bottom and drop them into the boxes above, from smallest to biggest.

Small
Medium
Big

Objects will appear here.

 
Reset Activity Next Activity
const activities = [ { name: “Activity 1: Order the Circles”, items: [ { id: ‘a1_s’, sizeLabel: ‘small’, width: ’40px’, height: ’40px’, color: ‘bg-blue-500’, shape: ‘circle’, originalIndex: 0 }, { id: ‘a1_m’, sizeLabel: ‘medium’, width: ’65px’, height: ’65px’, color: ‘bg-yellow-400’, shape: ‘circle’, originalIndex: 1 }, { id: ‘a1_b’, sizeLabel: ‘big’, width: ’90px’, height: ’90px’, color: ‘bg-red-500’, shape: ‘circle’, originalIndex: 2 } ], correctSequence: [‘small’, ‘medium’, ‘big’] }, { name: “Activity 2: Sort the Squares”, items: [ { id: ‘a2_s’, sizeLabel: ‘small’, width: ’35px’, height: ’35px’, color: ‘bg-green-500’, shape: ‘square’, originalIndex: 0 }, { id: ‘a2_m’, sizeLabel: ‘medium’, width: ’60px’, height: ’60px’, color: ‘bg-purple-500’, shape: ‘square’, originalIndex: 1 }, { id: ‘a2_b’, sizeLabel: ‘big’, width: ’85px’, height: ’85px’, color: ‘bg-orange-500’, shape: ‘square’, originalIndex: 2 } ], correctSequence: [‘small’, ‘medium’, ‘big’] }, { name: “Activity 3: Arrange the Rectangles”, items: [ { id: ‘a3_s’, sizeLabel: ‘small’, width: ’30px’, height: ’50px’, color: ‘bg-teal-500’, shape: ‘rectangle’, originalIndex: 0 }, { id: ‘a3_m’, sizeLabel: ‘medium’, width: ’40px’, height: ’75px’, color: ‘bg-pink-500’, shape: ‘rectangle’, originalIndex: 1 }, { id: ‘a3_b’, sizeLabel: ‘big’, width: ’50px’, height: ‘100px’, color: ‘bg-indigo-500’, shape: ‘rectangle’, originalIndex: 2 } ], correctSequence: [‘small’, ‘medium’, ‘big’] }, { name: “Activity 4: Order the Ovals”, items: [ { id: ‘a4_s’, sizeLabel: ‘small’, width: ’50px’, height: ’30px’, color: ‘bg-cyan-500’, shape: ‘oval’, originalIndex: 0 }, { id: ‘a4_m’, sizeLabel: ‘medium’, width: ’75px’, height: ’45px’, color: ‘bg-lime-500’, shape: ‘oval’, originalIndex: 1 }, { id: ‘a4_b’, sizeLabel: ‘big’, width: ‘100px’, height: ’60px’, color: ‘bg-rose-500’, shape: ‘oval’, originalIndex: 2 } ], correctSequence: [‘small’, ‘medium’, ‘big’] }, { name: “Activity 5: Size the Stars”, items: [ { id: ‘a5_s’, sizeLabel: ‘small’, width: ’40px’, height: ’40px’, shape: ‘star’, content: ‘⭐’, fontSize: ‘text-xl’, originalIndex: 0 }, { id: ‘a5_m’, sizeLabel: ‘medium’, width: ’60px’, height: ’60px’, shape: ‘star’, content: ‘⭐’, fontSize: ‘text-3xl’, originalIndex: 1 }, { id: ‘a5_b’, sizeLabel: ‘big’, width: ’80px’, height: ’80px’, shape: ‘star’, content: ‘⭐’, fontSize: ‘text-5xl’, originalIndex: 2 } ], correctSequence: [‘small’, ‘medium’, ‘big’] } ]; let currentActivityIndex = 0; let draggedItem = null; const successEmojis = [‘πŸŽ‰’, ‘πŸ₯³’, ‘🀩’, ‘πŸ‘’, ‘✨’, ‘🌟’, ‘πŸ’―’, ‘🎈’, ‘🎊’]; const activityTitleEl = document.getElementById(‘activity-title’); const sourceObjectsEl = document.getElementById(‘source-objects’); const sourcePlaceholderEl = document.getElementById(‘source-placeholder’); const targetZones = [ document.getElementById(‘target-1’), document.getElementById(‘target-2’), document.getElementById(‘target-3’) ]; const feedbackMessageEl = document.getElementById(‘feedback-message’); const resetActivityButton = document.getElementById(‘reset-activity-button’); const nextActivityButton = document.getElementById(‘next-activity-button’); const allActivitiesCompleteEl = document.getElementById(‘all-activities-complete’); const successModal = document.getElementById(‘success-modal’); const successEmojiDisplay = document.getElementById(‘success-emoji-display’); const successMessageModalEl = document.getElementById(‘success-message-modal’); const modalCloseButton = document.getElementById(‘modal-close-button’); function shuffleArray(array) { for (let i = array.length – 1; i > 0; i–) { const j = Math.floor(Math.random() * (i + 1)); [array[i], array[j]] = [array[j], array[i]]; } } function createDraggableItem(itemData) { const itemEl = document.createElement(‘div’); itemEl.id = itemData.id; itemEl.classList.add(‘draggable-item’); if (itemData.shape === ‘star’) { itemEl.classList.add(‘shape-star’); itemEl.textContent = itemData.content; if (itemData.fontSize === ‘text-xl’) itemEl.style.fontSize = ‘1.25rem’; if (itemData.fontSize === ‘text-3xl’) itemEl.style.fontSize = ‘1.875rem’; if (itemData.fontSize === ‘text-5xl’) itemEl.style.fontSize = ‘3rem’; } else { itemEl.classList.add(itemData.color, `shape-${itemData.shape}`); } itemEl.style.width = itemData.width; itemEl.style.height = itemData.height; itemEl.draggable = true; itemEl.dataset.sizeLabel = itemData.sizeLabel; itemEl.addEventListener(‘dragstart’, (e) => { draggedItem = itemEl; e.dataTransfer.setData(‘text/plain’, itemEl.id); e.dataTransfer.effectAllowed = ‘move’; // Using a timeout for class addition can sometimes be tricky with CSPs if not careful, // but arrow functions are generally fine. Let’s ensure this is not an issue. // The ‘dragging’ class is for visual feedback and not critical if it causes CSP issues. // For now, assume it’s okay as it’s not string evaluation. setTimeout(() => itemEl.classList.add(‘dragging’), 0); if (itemEl.parentElement.classList.contains(‘drop-zone’)) { itemEl.parentElement.dataset.droppedSize = ”; itemEl.parentElement.dataset.itemId = ”; itemEl.parentElement.classList.remove(‘occupied’); } }); itemEl.addEventListener(‘dragend’, () => { if (draggedItem) { draggedItem.classList.remove(‘dragging’); } draggedItem = null; }); return itemEl; } function getDraggableItemFromZone(zone) { for (let child of zone.children) { if (child.classList.contains(‘draggable-item’)) { return child; } } return null; } function loadActivity(index) { if (index >= activities.length) { allActivitiesCompleteEl.textContent = “πŸŽ‰ Congratulations! You’ve completed all activities! πŸŽ‰”; allActivitiesCompleteEl.classList.remove(‘hidden’); activityTitleEl.textContent = “All Done!”; sourceObjectsEl.innerHTML = ”; sourcePlaceholderEl.classList.remove(‘hidden’); sourcePlaceholderEl.textContent = “No more items!”; targetZones.forEach(zone => { const item = getDraggableItemFromZone(zone); if (item) item.remove(); zone.classList.remove(‘occupied’); zone.dataset.droppedSize = ”; zone.dataset.itemId = ”; }); feedbackMessageEl.innerHTML = ‘ ‘; resetActivityButton.classList.add(‘hidden’); nextActivityButton.classList.add(‘hidden’); document.getElementById(‘instruction’).classList.add(‘hidden’); return; } const activity = activities[index]; activityTitleEl.textContent = activity.name; feedbackMessageEl.innerHTML = ‘ ‘; nextActivityButton.classList.add(‘hidden’); resetActivityButton.classList.remove(‘hidden’); resetActivityButton.disabled = false; allActivitiesCompleteEl.classList.add(‘hidden’); document.getElementById(‘instruction’).classList.remove(‘hidden’); sourceObjectsEl.innerHTML = ”; targetZones.forEach(zone => { const item = getDraggableItemFromZone(zone); if (item) item.remove(); zone.classList.remove(‘occupied’); zone.dataset.droppedSize = ”; zone.dataset.itemId = ”; }); const itemsToDisplay = […activity.items]; shuffleArray(itemsToDisplay); if (itemsToDisplay.length > 0) { sourcePlaceholderEl.classList.add(‘hidden’); } else { sourcePlaceholderEl.classList.remove(‘hidden’); } itemsToDisplay.forEach(itemData => { const itemEl = createDraggableItem(itemData); sourceObjectsEl.appendChild(itemEl); }); setItemsDraggable(true); } function setItemsDraggable(isDraggable) { document.querySelectorAll(‘.draggable-item’).forEach(item => { item.draggable = isDraggable; item.style.cursor = isDraggable ? ‘grab’ : ‘default’; }); } targetZones.forEach(targetZoneElement => { targetZoneElement.addEventListener(‘dragover’, (e) => { e.preventDefault(); const currentItemInZone = getDraggableItemFromZone(targetZoneElement); if (!currentItemInZone || (currentItemInZone && currentItemInZone !== draggedItem)) { targetZoneElement.classList.add(‘drop-zone-hover’); } e.dataTransfer.dropEffect = ‘move’; }); targetZoneElement.addEventListener(‘dragleave’, () => { targetZoneElement.classList.remove(‘drop-zone-hover’); }); targetZoneElement.addEventListener(‘drop’, (e) => { e.preventDefault(); // console.log(‘Drop event fired on target:’, targetZoneElement.id, ‘Dragged item ID:’, draggedItem ? draggedItem.id : ‘null’); targetZoneElement.classList.remove(‘drop-zone-hover’); if (!draggedItem) { // console.error(‘draggedItem is null in drop event.’); return; } const itemToDrop = draggedItem; const targetZone = targetZoneElement; const currentItemInTargetZone = getDraggableItemFromZone(targetZone); if (currentItemInTargetZone && currentItemInTargetZone !== itemToDrop) { sourceObjectsEl.appendChild(currentItemInTargetZone); } targetZone.appendChild(itemToDrop); targetZone.dataset.droppedSize = itemToDrop.dataset.sizeLabel; targetZone.dataset.itemId = itemToDrop.id; targetZone.classList.add(‘occupied’); checkSequence(); }); }); function checkSequence() { const droppedItemsCount = targetZones.reduce((count, zone) => count + (getDraggableItemFromZone(zone) ? 1 : 0), 0); if (droppedItemsCount === 3) { const currentSequence = targetZones.map(zone => zone.dataset.droppedSize); const correctSequence = activities[currentActivityIndex].correctSequence; let isCorrect = true; for (let i = 0; i < correctSequence.length; i++) { if (currentSequence[i] !== correctSequence[i]) { isCorrect = false; break; } } if (isCorrect) { feedbackMessageEl.textContent = 'Excellent! That\'s the right order!'; feedbackMessageEl.classList.remove('text-red-600'); feedbackMessageEl.classList.add('text-green-600'); const randomEmoji = successEmojis[Math.floor(Math.random() * successEmojis.length)]; successEmojiDisplay.textContent = randomEmoji; successMessageModalEl.textContent = "Great Job!"; successModal.style.display = 'flex'; setItemsDraggable(false); resetActivityButton.disabled = true; // Disable reset when correct if (currentActivityIndex { if (resetActivityButton.disabled) return; targetZones.forEach(zone => { const item = getDraggableItemFromZone(zone); if (item) { sourceObjectsEl.appendChild(item); zone.dataset.droppedSize = ”; zone.dataset.itemId = ”; zone.classList.remove(‘occupied’); } }); loadActivity(currentActivityIndex); feedbackMessageEl.innerHTML = ‘ ‘; setItemsDraggable(true); }); modalCloseButton.addEventListener(‘click’, () => { successModal.style.display = ‘none’; }); nextActivityButton.addEventListener(‘click’, () => { currentActivityIndex++; loadActivity(currentActivityIndex); nextActivityButton.classList.add(‘hidden’); resetActivityButton.classList.remove(‘hidden’); resetActivityButton.disabled = false; }); // Initial load loadActivity(currentActivityIndex);