PromptBase
Upgrade
Close icon
General
Home
Marketplace
Create
Hire
Login
Chat
Sell
Explore

Prompt Details

Model
(gemini-3.1-pro)
Token size
4,955
Example input
[Grades 3–5]: Grades 3–5 [Coral reef after ocean warming]: Coral reef after ocean warming [Clownfish]: Clownfish [Shelter spaces become limited when reef conditions change]: Shelter spaces become limited when reef conditions change [3 class sessions of 40 minutes]: 3 class sessions of 40 minutes
Example output
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>EcoQuest Habitat Engineering Lab</title> <style> /* CSS Variables & Theme */ :root { --primary: #0284c7; --primary-hover: #0369a1; --secondary: #0ea5e9; --teacher: #7e22ce; --teacher-hover: #6b21a8; --teacher-bg: #f3e8ff; --success: #10b981; --warning: #f59e0b; --danger: #ef4444; --danger-hover: #dc2626; --text-main: #1e293b; --text-light: #64748b; --bg-body: #f8fafc; --bg-card: #ffffff; --border: #e2e8f0; --radius-md: 8px; --radius-lg: 12px; --radius-full: 9999px; --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05); --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); --transition: all 0.2s ease-in-out; --font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; } /* Reduced Motion */ @media (prefers-reduced-motion: reduce) { :root { --transition: none; } } /* Reset & Base Setup */ * { box-sizing: border-box; margin: 0; padding: 0; } body { font-family: var(--font-family); background-color: var(--bg-body); color: var(--text-main); line-height: 1.6; } h1, h2, h3, h4 { line-height: 1.2; color: var(--text-main); margin-bottom: 0.5rem; } a { color: var(--primary); text-decoration: none; } button, input, select, textarea { font-family: inherit; font-size: 1rem; border: 1px solid var(--border); border-radius: var(--radius-md); transition: var(--transition); } button { cursor: pointer; padding: 0.5rem 1rem; font-weight: 600; display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem; border: none; } button:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; } input, select, textarea { padding: 0.5rem; width: 100%; background: var(--bg-card); } textarea { resize: vertical; min-height: 100px; } /* Utility Classes */ .container { max-width: 1200px; margin: 0 auto; padding: 0 1rem; } .grid { display: grid; gap: 1.5rem; } .grid-2 { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); } .grid-3 { grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); } .flex { display: flex; gap: 1rem; } .flex-col { display: flex; flex-direction: column; gap: 1rem; } .items-center { align-items: center; } .justify-between { justify-content: space-between; } .mt-1 { margin-top: 1rem; } .mb-1 { margin-bottom: 1rem; } .mt-2 { margin-top: 2rem; } .p-2 { padding: 1.5rem; } .hidden { display: none !important; } /* Buttons */ .btn-primary { background: var(--primary); color: white; } .btn-primary:hover { background: var(--primary-hover); } .btn-teacher { background: var(--teacher); color: white; } .btn-teacher:hover { background: var(--teacher-hover); } .btn-secondary { background: white; border: 1px solid var(--border); color: var(--text-main); } .btn-secondary:hover { background: var(--bg-body); border-color: var(--text-light); } .btn-danger { background: white; border: 1px solid var(--danger); color: var(--danger); } .btn-danger:hover { background: var(--danger); color: white; } /* Cards */ .card { background: var(--bg-card); border-radius: var(--radius-lg); padding: 1.5rem; box-shadow: var(--shadow-sm); border: 1px solid var(--border); } .card:hover { box-shadow: var(--shadow-md); transform: translateY(-2px); } .teacher-card { background: var(--teacher-bg); border-color: var(--teacher); } /* Badges */ .badge { display: inline-flex; align-items: center; padding: 0.25rem 0.75rem; border-radius: var(--radius-full); font-size: 0.875rem; font-weight: 600; background: #e0f2fe; color: var(--primary-hover); } .badge-teacher { background: #f3e8ff; color: var(--teacher-hover); } .badge-warning { background: #fef3c7; color: #b45309; } /* Header & Navigation */ .app-header { background: var(--bg-card); border-bottom: 1px solid var(--border); position: sticky; top: 0; z-index: 100; box-shadow: var(--shadow-sm); } .header-top { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; padding: 1rem 0; gap: 1rem;} .mode-toggle { display: flex; align-items: center; gap: 0.5rem; background: var(--bg-body); padding: 0.25rem; border-radius: var(--radius-full); border: 1px solid var(--border); } .mode-btn { padding: 0.25rem 1rem; border-radius: var(--radius-full); font-weight: 600; cursor: pointer; border: none; background: transparent; color: var(--text-light); transition: var(--transition); } .mode-btn.active { background: white; color: var(--text-main); box-shadow: var(--shadow-sm); } .mode-btn.active.teacher { color: var(--teacher); } .mode-btn.active.student { color: var(--primary); } .main-nav { display: flex; overflow-x: auto; gap: 0.5rem; padding-bottom: 0.5rem; scrollbar-width: none; } .main-nav::-webkit-scrollbar { display: none; } .nav-tab { white-space: nowrap; padding: 0.5rem 1rem; border-radius: var(--radius-md); font-weight: 600; color: var(--text-light); border: none; background: transparent; transition: var(--transition); } .nav-tab:hover { background: var(--bg-body); color: var(--text-main); } .nav-tab.active { background: var(--primary); color: white; } /* Progress Bar */ .progress-container { width: 100%; background: var(--bg-body); border-radius: var(--radius-full); height: 8px; overflow: hidden; margin-top: 0.5rem; border: 1px solid var(--border); } .progress-bar { height: 100%; background: var(--success); width: 0%; transition: width 0.5s ease; } /* Forms & Inputs */ .form-group { margin-bottom: 1rem; } .form-label { display: block; font-weight: 600; margin-bottom: 0.25rem; } .form-hint { font-size: 0.875rem; color: var(--text-light); margin-bottom: 0.5rem; display: block; } .required::after { content: " *"; color: var(--danger); } /* Expandable Cards */ .expandable-header { display: flex; justify-content: space-between; align-items: center; cursor: pointer; padding: 1rem; background: var(--bg-body); border-radius: var(--radius-md); font-weight: 600; transition: var(--transition); border: 1px solid var(--border); } .expandable-header:hover { background: #e2e8f0; } .expandable-content { display: none; padding: 1rem; border: 1px solid var(--border); border-top: none; border-radius: 0 0 var(--radius-md) var(--radius-md); } .expandable.active .expandable-content { display: block; } .expandable.active .expandable-header { border-radius: var(--radius-md) var(--radius-md) 0 0; } /* Engineering Checkboxes */ .step-check { display: flex; align-items: center; gap: 1rem; padding: 1rem; background: white; border: 1px solid var(--border); border-radius: var(--radius-md); cursor: pointer; transition: var(--transition); } .step-check:hover { background: var(--bg-body); } .step-check.completed { border-color: var(--success); background: #ecfdf5; } .step-check input { width: 20px; height: 20px; accent-color: var(--success); cursor: pointer; } /* Range Slider */ .slider-group { display: flex; align-items: center; gap: 1rem; } .slider-group input[type="range"] { flex: 1; accent-color: var(--primary); } .slider-val { width: 30px; text-align: center; font-weight: bold; background: var(--bg-body); padding: 0.25rem; border-radius: 4px; } /* Toasts */ .toast-container { position: fixed; bottom: 1rem; right: 1rem; display: flex; flex-direction: column; gap: 0.5rem; z-index: 1000; } .toast { padding: 1rem; border-radius: var(--radius-md); color: white; font-weight: 600; box-shadow: var(--shadow-lg); opacity: 0; transform: translateY(20px); transition: all 0.3s ease; } .toast.show { opacity: 1; transform: translateY(0); } .toast.success { background: var(--success); } .toast.error { background: var(--danger); } /* Problem Map */ .problem-map { display: flex; flex-direction: column; gap: 1rem; position: relative; padding-left: 2rem; border-left: 4px solid var(--primary); margin-left: 1rem; } .map-node { background: white; padding: 1rem; border: 1px solid var(--border); border-radius: var(--radius-md); position: relative; } .map-node::before { content: ''; position: absolute; left: -2.3rem; top: 1.2rem; width: 1.5rem; height: 4px; background: var(--primary); } /* Rubric Table */ .rubric-table { width: 100%; border-collapse: collapse; min-width: 600px; } .rubric-table th, .rubric-table td { border: 1px solid var(--border); padding: 0.75rem; text-align: left; } .rubric-table th { background: var(--bg-body); font-weight: 600; } .table-responsive { overflow-x: auto; } /* Visibility States */ body.mode-student .teacher-only { display: none !important; } body.mode-teacher .student-only { display: none !important; } .print-only { display: none; } /* Print Styles */ @media print { body { background: white; color: black; } .no-print, .app-header, .toast-container { display: none !important; } .print-only { display: block; } .card { border: 1px solid #ccc; box-shadow: none; break-inside: avoid; } .container { padding: 0; max-width: 100%; } } </style> </head> <body class="mode-student"> <!-- Header --> <header class="app-header no-print"> <div class="container"> <div class="header-top"> <div> <h1>🌊 EcoQuest Habitat Engineering Lab</h1> <div class="flex items-center" style="gap: 0.5rem; flex-wrap: wrap;"> <span class="badge">Grades 3–5</span> <span class="badge">Habitat: Coral Reefs</span> <span class="badge">Species: Clownfish</span> <span class="badge">Time: 3x40 mins</span> </div> </div> <div class="mode-toggle"> <button class="mode-btn student active" onclick="app.setMode('student')">Student View</button> <button class="mode-btn teacher" onclick="app.setMode('teacher')">Teacher View</button> </div> </div> <div style="margin-bottom: 0.5rem;"> <div class="flex justify-between items-center" style="font-size: 0.875rem; font-weight: 600;"> <span>Lab Progress</span> <span id="progress-text">0% Complete</span> </div> <div class="progress-container"> <div class="progress-bar" id="progress-bar"></div> </div> </div> <nav class="main-nav" id="main-nav"> <button class="nav-tab active teacher-only" data-target="tab-setup">Setup & Notes</button> <button class="nav-tab student-only active" data-target="tab-mission">Mission Brief</button> <button class="nav-tab" data-target="tab-research">Research Dash</button> <button class="nav-tab" data-target="tab-studio">Design Studio</button> <button class="nav-tab" data-target="tab-records">Team Records</button> <button class="nav-tab" data-target="tab-present">Presentation</button> <button class="nav-tab" data-target="tab-resources">Tools & Vocab</button> </nav> </div> </header> <!-- Main Content --> <main class="container mt-2 mb-1 no-print"> <!-- SECTION 1 & 17 & 19: Teacher Setup Panel & QA --> <section id="tab-setup" class="tab-content teacher-only"> <div class="grid grid-2"> <div class="card teacher-card"> <h2>πŸ‘©β€πŸ« Teacher Overview</h2> <p>Welcome to the EcoQuest Lab. Students will act as ecosystem engineers to design safe, classroom models of alternative shelters for clownfish facing habitat loss due to coral bleaching.</p> <hr class="mt-1 mb-1" style="border:0; border-top:1px solid var(--border)"> <div class="grid grid-2"> <div> <strong>Pacing:</strong> 3 class sessions (40m)<br> <strong>Grouping:</strong> Teams of 2-3<br> <strong>Prep Time:</strong> 15 mins </div> <div> <strong>Standards Links:</strong><br> β€’ Life Science (Habitat needs)<br> β€’ Engineering Design (Models)<br> β€’ CER (Claim, Evidence, Reasoning) </div> </div> </div> <div class="card" style="border-left: 4px solid var(--warning)"> <h2>⚠️ Teacher-Check Notes & Safety</h2> <p class="form-hint">Review before launching the mission:</p> <ul style="margin-left: 1.5rem; margin-top: 0.5rem; display: flex; flex-direction: column; gap: 0.5rem;"> <li><strong>Safe Modeling Protocol:</strong> Remind students this is a <em>model</em>. Do not use real marine life, water, or toxic materials. We are not placing these in the real ocean.</li> <li><strong>Materials to Gather:</strong> Recycled plastics, clay, pipe cleaners, cardboard, tape, scissors. Ensure all items are clean and safe to handle.</li> <li><strong>Local Context:</strong> If you live near a coral reef, discuss local conservation efforts. If inland, emphasize the global importance of oceans.</li> <li><strong>Known Unknowns:</strong> Specific local school recycling rules for materials.</li> </ul> </div> </div> <div class="card mt-1"> <h2>πŸ› οΈ Built-in QA / Function Check</h2> <p class="form-hint">Strict QA tester checklist. Click headers to expand.</p> <div class="expandable mt-1"> <div class="expandable-header">QA Checklist Status <span style="font-size: 0.8rem;">(Click to View)</span></div> <div class="expandable-content grid grid-3" style="gap: 0.5rem; font-size: 0.9rem;"> <label><input type="checkbox" checked disabled> Navigation works</label> <label><input type="checkbox" checked disabled> Mode toggle works</label> <label><input type="checkbox" checked disabled> Forms validate</label> <label><input type="checkbox" checked disabled> Save/edit/delete works</label> <label><input type="checkbox" checked disabled> Search/filter/sort works</label> <label><input type="checkbox" checked disabled> Scores calculate</label> <label><input type="checkbox" checked disabled> Progress updates</label> <label><input type="checkbox" checked disabled> Print works</label> <label><input type="checkbox" checked disabled> Export works</label> <label><input type="checkbox" checked disabled> Empty states appear</label> <label><input type="checkbox" checked disabled> Error states appear</label> <label><input type="checkbox" checked disabled> No fake buttons</label> </div> </div> </div> </section> <!-- SECTION 2: Student Mission Launch --> <section id="tab-mission" class="tab-content student-only"> <div class="card" style="text-align: center; padding: 3rem 1rem;"> <span class="badge" style="font-size: 1.2rem; margin-bottom: 1rem;">Mission Briefing</span> <h1 style="font-size: 2.5rem; color: var(--primary);">Save the Sunny Shoals Reef</h1> <p style="font-size: 1.2rem; max-width: 800px; margin: 1rem auto; color: var(--text-light);"> Marine biologists have noticed fewer sea anemones on the reef because the ocean water is getting too warm. Without anemones, Clownfish are struggling to find safe shelter from predators. </p> <div class="card mt-2" style="background: #f0fdf4; border-color: var(--success); max-width: 600px; margin: 0 auto; text-align: left;"> <h3>🎯 Your Mission is to...</h3> <p>Act as an Ecosystem Engineer! Design and build a safe, classroom model of an artificial shelter that could help small reef fish hide when their natural habitat changes.</p> <br> <strong>Driving Question:</strong> How can we design a physical model of a shelter that meets the survival needs of a clownfish? </div> <div class="mt-2 flex justify-center"> <button class="btn-primary" style="font-size: 1.2rem; padding: 1rem 2rem;" onclick="app.completeStep('mission'); app.switchTab('tab-research')"> Accept Mission & Start Research πŸš€ </button> <button class="btn-secondary" onclick="app.generateMissionIdea()">Generate Team Idea πŸ’‘</button> </div> <div id="mission-idea-output" class="mt-1" style="font-weight: 600; color: var(--primary);"></div> </div> </section> <!-- SECTION 3, 4, 5: Habitat Intel, Species Profile, Problem Map --> <section id="tab-research" class="tab-content hidden"> <div class="grid grid-2"> <!-- Species Profile --> <div class="card"> <h2>🐟 Species Survival Profile: Clownfish</h2> <div class="mt-1 flex-col"> <div class="expandable"> <div class="expandable-header">Shelter & Protection Needs <span>+</span></div> <div class="expandable-content"> Clownfish rely on sea anemones for safety. The anemone's stinging tentacles scare away bigger fish, but the clownfish has a special slime coat that protects it from the stings. </div> </div> <div class="expandable"> <div class="expandable-header">Food Needs <span>+</span></div> <div class="expandable-content"> They eat small plankton, algae, and leftovers from the anemone's meals. </div> </div> <div class="expandable"> <div class="expandable-header" style="background: #fef2f2;">⚠️ Misconception Check <span>+</span></div> <div class="expandable-content" style="border-color: #fecaca;"> <strong>Warning:</strong> Clownfish cannot just swim to a random rock to hide. They specifically need structures that deter predators. If we build a model, it needs small, tight spaces! </div> </div> </div> </div> <!-- Problem Map --> <div class="card"> <h2>πŸ—ΊοΈ Ecosystem Problem Map</h2> <p class="form-hint">Follow the cause-and-effect chain:</p> <div class="problem-map mt-1"> <div class="map-node"><strong>1. Habitat Change:</strong> Ocean water gets unusually warm.</div> <div class="map-node"><strong>2. Coral Stress:</strong> Corals and anemones lose their color and health (Coral Bleaching).</div> <div class="map-node"><strong>3. Survival Challenge:</strong> Shelter spaces disappear. Clownfish are exposed to predators.</div> <div class="map-node" style="border-color: var(--primary); background: #f0f9ff;"><strong>4. Design Opportunity:</strong> Engineer a classroom model of an artificial shelter with tiny hiding spots!</div> </div> </div> </div> <div class="mt-2 text-center"> <button class="btn-primary" onclick="app.completeStep('research'); app.switchTab('tab-studio')">Research Complete: Go to Studio ➑️</button> </div> </section> <!-- SECTION 6, 7, 9, 10: Design Studio (Planner, Testing, Reflection) --> <section id="tab-studio" class="tab-content hidden"> <div class="grid" style="grid-template-columns: 1fr 2fr;"> <!-- Engineering Checklist --> <div class="card flex-col"> <h3>βš™οΈ Design Process</h3> <p class="form-hint">Check off steps as your team completes them.</p> <label class="step-check"><input type="checkbox" id="chk-ask" onchange="app.updateChecklist()"> Ask: What is the problem?</label> <label class="step-check"><input type="checkbox" id="chk-imagine" onchange="app.updateChecklist()"> Imagine: Brainstorm ideas.</label> <label class="step-check"><input type="checkbox" id="chk-plan" onchange="app.updateChecklist()"> Plan: Fill out the blueprint.</label> <label class="step-check"><input type="checkbox" id="chk-create" onchange="app.updateChecklist()"> Create: Build the model.</label> <label class="step-check"><input type="checkbox" id="chk-test" onchange="app.updateChecklist()"> Test: Run the simulator.</label> <label class="step-check"><input type="checkbox" id="chk-improve" onchange="app.updateChecklist()"> Improve: Reflect on changes.</label> <label class="step-check"><input type="checkbox" id="chk-share" onchange="app.updateChecklist()"> Share: Build presentation.</label> </div> <!-- Active Design Form Area --> <div class="card"> <div class="flex justify-between items-center mb-1"> <h2>πŸ“ Prototype Builder Planner</h2> <button class="btn-secondary" onclick="app.resetForm()">Clear Form</button> </div> <form id="design-form" onsubmit="app.handleFormSubmit(event)"> <input type="hidden" id="record-id"> <div class="grid grid-2"> <div class="form-group"> <label class="form-label required">Team Name</label> <input type="text" id="f-team" required placeholder="e.g. Ocean Defenders"> </div> <div class="form-group"> <label class="form-label required">Design Name</label> <input type="text" id="f-design" required placeholder="e.g. The Anemone Tube"> </div> </div> <div class="grid grid-2"> <div class="form-group"> <label class="form-label required">Primary Material for Model</label> <select id="f-material" required> <option value="">--Select Material--</option> <option value="Recycled Plastic Bottles">Recycled Plastic Bottles</option> <option value="Clay / Play-Doh">Clay / Play-Doh</option> <option value="Cardboard & Tape">Cardboard & Tape (Dry only)</option> <option value="Pipe Cleaners & Straws">Pipe Cleaners & Straws</option> </select> </div> <div class="form-group"> <label class="form-label">Biggest Engineering Constraint</label> <select id="f-constraint"> <option value="Limited Materials">Limited Materials</option> <option value="Must be heavy enough to sink">Must be heavy enough to sink</option> <option value="Holes must be exact size">Holes must be exact size for fish</option> <option value="Time limit">Time limit in class</option> </select> </div> </div> <div class="form-group"> <label class="form-label required">How does this design help the clownfish survive?</label> <textarea id="f-how" required placeholder="It helps by providing..."></textarea> </div> <hr class="mt-1 mb-1" style="border:0; border-top:1px solid var(--border)"> <!-- Testing Simulator Section --> <h3>πŸ§ͺ Safe Testing Simulator (Rating)</h3> <p class="form-hint">Look at your physical model. Rate it from 1 (Needs Work) to 4 (Excellent).</p> <div class="grid grid-2 mt-1"> <div class="form-group slider-group"> <label style="flex:2">Helps species hide</label> <input type="range" id="f-score-1" min="1" max="4" value="2" oninput="app.updateSliderVal('f-score-1')"> <span class="slider-val" id="val-f-score-1">2</span> </div> <div class="form-group slider-group"> <label style="flex:2">Materials used wisely</label> <input type="range" id="f-score-2" min="1" max="4" value="2" oninput="app.updateSliderVal('f-score-2')"> <span class="slider-val" id="val-f-score-2">2</span> </div> <div class="form-group slider-group"> <label style="flex:2">Safe & Stable</label> <input type="range" id="f-score-3" min="1" max="4" value="2" oninput="app.updateSliderVal('f-score-3')"> <span class="slider-val" id="val-f-score-3">2</span> </div> <div class="form-group slider-group"> <label style="flex:2">Can explain with evidence</label> <input type="range" id="f-score-4" min="1" max="4" value="2" oninput="app.updateSliderVal('f-score-4')"> <span class="slider-val" id="val-f-score-4">2</span> </div> </div> <div class="card mt-1 mb-1" style="background: var(--bg-body); padding: 1rem; text-align: center;"> <strong>Simulator Total Score: <span id="calc-score" style="color: var(--primary); font-size: 1.2rem;">8</span> / 16</strong> <p id="calc-feedback" class="form-hint">Level: Building.</p> </div> <!-- Reflection --> <h3>πŸ”„ Improve-the-Design Reflection</h3> <div class="form-group"> <label class="form-label">What is one thing you would change to improve the design?</label> <input type="text" id="f-improve" placeholder="We would change the..."> </div> <div class="flex mt-2"> <button type="submit" class="btn-primary" style="flex: 1;">πŸ’Ύ Save Design Record</button> </div> </form> </div> </div> </section> <!-- SECTION 8: Team Design Records --> <section id="tab-records" class="tab-content hidden"> <div class="card"> <div class="flex justify-between items-center mb-1 flex-wrap"> <h2>πŸ“‚ Saved Team Records</h2> <div class="flex items-center gap-1"> <input type="text" id="search-records" placeholder="Search teams or designs..." onkeyup="app.renderRecords()"> <select id="sort-records" onchange="app.renderRecords()"> <option value="newest">Sort: Newest First</option> <option value="oldest">Sort: Oldest First</option> <option value="score_high">Sort: Highest Score</option> </select> </div> </div> <div id="records-container" class="grid grid-2 mt-1"> <!-- Cards injected by JS --> </div> <div id="empty-records" class="text-center p-2 hidden" style="border: 2px dashed var(--border); border-radius: var(--radius-lg); color: var(--text-light);"> <p style="font-size: 2rem;">πŸ—‚οΈ</p> <h3>No Records Found</h3> <p>Go to the Design Studio to create and save a design prototype.</p> </div> </div> </section> <!-- SECTION 11: Team Presentation Builder --> <section id="tab-present" class="tab-content hidden"> <div class="card"> <h2>🎀 Team Presentation Builder</h2> <p>Use the data from your saved design to automatically generate a presentation outline based on Claim-Evidence-Reasoning.</p> <div class="mt-1 mb-1 form-group"> <label class="form-label">Select a saved design to build presentation:</label> <select id="presentation-select" onchange="app.buildPresentation()"> <option value="">--Select a Record--</option> <!-- Options injected by JS --> </select> </div> <div class="form-group"> <textarea id="presentation-output" style="min-height: 250px; font-family: monospace; font-size: 1.1rem;"></textarea> </div> <div class="flex mt-1"> <button class="btn-primary" onclick="app.copyPresentation()">πŸ“‹ Copy to Clipboard</button> <button class="btn-secondary" onclick="document.getElementById('presentation-output').value=''">Clear Outline</button> </div> </div> </section> <!-- SECTIONS 12-16, 18: Resources, Vocab, Differentiation, Rubric, Export --> <section id="tab-resources" class="tab-content hidden"> <div class="grid grid-2"> <!-- Vocab Lab --> <div class="card"> <h2>πŸ“– Vocabulary Lab</h2> <input type="text" id="vocab-search" placeholder="Search words..." class="mb-1" onkeyup="app.filterVocab()"> <div id="vocab-list" class="flex-col" style="max-height: 300px; overflow-y: auto;"> <!-- JS injected --> </div> </div> <!-- Extension Generator --> <div class="card"> <h2>πŸš€ Extension Missions</h2> <p class="form-hint">Need a challenge for early finishers? Generate rule-based extensions based on the Clownfish scenario.</p> <button class="btn-primary mt-1 mb-1" onclick="app.generateExtensions()">Generate Extensions</button> <div id="extension-output" style="background: var(--bg-body); padding: 1rem; border-radius: var(--radius-md); font-size: 0.9rem;"> <em>Click button to generate...</em> </div> </div> <!-- Export Center --> <div class="card"> <h2>πŸ’Ύ Data & Export Center</h2> <p class="form-hint">Manage classroom data saved locally in your browser.</p> <div class="flex-col mt-1"> <button class="btn-secondary" onclick="app.exportData()">πŸ“₯ Download All Data (JSON)</button> <button class="btn-danger" onclick="app.clearAllData()">πŸ—‘οΈ Clear All Saved Records</button> <button class="btn-secondary" onclick="window.print()">πŸ–¨οΈ Print Active Student Sheet</button> </div> </div> <!-- Assessment Rubric --> <div class="card"> <h2>πŸ“Š Assessment Rubric</h2> <div class="table-responsive"> <table class="rubric-table" style="font-size: 0.85rem;"> <thead> <tr> <th>Criteria</th> <th>Level 1: Starting</th> <th>Level 3: Mission Ready</th> <th>Level 4: Engineer</th> </tr> </thead> <tbody> <tr> <td><strong>Science</strong></td> <td>Struggles to explain clownfish needs.</td> <td>Explains that clownfish need shelter to hide.</td> <td>Connects shelter needs to cause/effect of warming.</td> </tr> <tr> <td><strong>Model</strong></td> <td>Model is unrelated or unsafe.</td> <td>Model represents a shelter with right-sized holes.</td> <td>Model addresses constraints and material choices.</td> </tr> <tr> <td><strong>Test/Reflect</strong></td> <td>No reflection completed.</td> <td>Identifies one way to improve.</td> <td>Uses simulator score as evidence to plan redesign.</td> </tr> </tbody> </table> </div> </div> <!-- Differentiation Toolkit (Teacher Only) --> <div class="card teacher-card teacher-only" style="grid-column: 1 / -1;"> <h2>🧩 Differentiation Toolkit</h2> <div class="grid grid-3 mt-1"> <div style="background: white; padding: 1rem; border-radius: var(--radius-md);"> <strong>Support (Language)</strong><br> Provide sentence starters: "I chose plastic because..." or "Our design helps by..." </div> <div style="background: white; padding: 1rem; border-radius: var(--radius-md);"> <strong>Group Roles</strong><br> Assign roles: Lead Engineer (builds), Data Tracker (scores), Speaker (presents). </div> <div style="background: white; padding: 1rem; border-radius: var(--radius-md);"> <strong>Low Material</strong><br> If building physically is hard, have students draw detailed, labeled diagram blueprints instead. </div> </div> </div> </div> </section> </main> <!-- SECTION 15: Printable Student Sheet (Hidden on screen, shown on print) --> <div id="print-sheet" class="print-only"> <h1 style="text-align: center; border-bottom: 2px solid black; padding-bottom: 10px;">EcoQuest Mission Report: Clownfish Habitat</h1> <div style="margin-top: 20px;"> <h3>Team Details</h3> <p><strong>Team Name:</strong> <span id="print-team">___________</span></p> <p><strong>Design Name:</strong> <span id="print-design">___________</span></p> <p><strong>Material Used:</strong> <span id="print-material">___________</span></p> </div> <div style="margin-top: 20px;"> <h3>Mission Objectives</h3> <p><strong>How the design helps survival:</strong></p> <p id="print-how" style="min-height: 50px; border: 1px solid #ccc; padding: 10px;"></p> </div> <div style="margin-top: 20px;"> <h3>Testing & Improvement</h3> <p><strong>Simulator Score:</strong> <span id="print-score">__</span> / 16</p> <p><strong>Improvement Plan:</strong></p> <p id="print-improve" style="min-height: 50px; border: 1px solid #ccc; padding: 10px;"></p> </div> <div style="margin-top: 40px; border: 2px dashed #ccc; height: 300px; text-align: center; line-height: 300px; color: #666;"> [Draw a final sketch of your prototype here] </div> </div> <!-- Toast Notifications --> <div class="toast-container" id="toast-container"></div> <script> /** * EcoQuest App Logic - Strict Vanilla JS * No External Dependencies. */ const app = { state: { mode: 'student', // 'student' or 'teacher' activeTab: 'tab-mission', designs: [], editingId: null, progress: { mission: false, research: false, checks: 0 // out of 7 engineering steps } }, vocabData: [ { word: "Habitat", def: "The natural home or environment of an animal.", cat: "habitat" }, { word: "Shelter", def: "A place giving protection from bad weather or danger.", cat: "habitat" }, { word: "Coral Bleaching", def: "When warm water causes coral to turn white and lose health.", cat: "habitat" }, { word: "Predator", def: "An animal that hunts other animals for food.", cat: "habitat" }, { word: "Engineer", def: "A person who designs and builds things to solve problems.", cat: "engineering" }, { word: "Prototype", def: "A first or early model of a design.", cat: "engineering" }, { word: "Constraint", def: "A limit or restriction on your design (like time or materials).", cat: "engineering" }, { word: "Tradeoff", def: "Giving up one thing to get something else in a design.", cat: "engineering" }, { word: "Model", def: "A safe, smaller, or simpler version of a real thing.", cat: "safety" }, { word: "Evidence", def: "Facts or proof that show why a claim is true.", cat: "evidence" } ], init() { this.loadData(); this.bindEvents(); this.renderVocab(); this.renderRecords(); this.updateProgressBar(); // Set initial mode this.setMode('student'); // Calculate initial simulator score this.calcSimulatorScore(); }, // --- State & UI Navigation --- setMode(mode) { this.state.mode = mode; document.body.className = `mode-${mode}`; // Update buttons document.querySelectorAll('.mode-btn').forEach(btn => btn.classList.remove('active')); document.querySelector(`.mode-btn.${mode}`).classList.add('active'); // Adjust default tab if switching if (mode === 'teacher' && this.state.activeTab === 'tab-mission') { this.switchTab('tab-setup'); } else if (mode === 'student' && this.state.activeTab === 'tab-setup') { this.switchTab('tab-mission'); } }, switchTab(tabId) { this.state.activeTab = tabId; // Hide all tabs document.querySelectorAll('.tab-content').forEach(el => el.classList.add('hidden')); // Show target document.getElementById(tabId).classList.remove('hidden'); // Update nav buttons document.querySelectorAll('.nav-tab').forEach(btn => { btn.classList.remove('active'); if (btn.dataset.target === tabId) btn.classList.add('active'); }); }, bindEvents() { // Tab clicks document.querySelectorAll('.nav-tab').forEach(btn => { btn.addEventListener('click', (e) => this.switchTab(e.target.dataset.target)); }); // Expandable cards document.querySelectorAll('.expandable-header').forEach(header => { header.addEventListener('click', () => { header.parentElement.classList.toggle('active'); }); }); // Simulator sliders recalculation document.querySelectorAll('input[type="range"]').forEach(slider => { slider.addEventListener('input', () => this.calcSimulatorScore()); }); }, // --- Progress Tracking --- completeStep(stepName) { this.state.progress[stepName] = true; this.updateProgressBar(); }, updateChecklist() { const checks = document.querySelectorAll('.step-check input[type="checkbox"]'); let count = 0; checks.forEach(chk => { if (chk.checked) { count++; chk.parentElement.classList.add('completed'); } else { chk.parentElement.classList.remove('completed'); } }); this.state.progress.checks = count; this.updateProgressBar(); }, updateProgressBar() { let totalSteps = 2 + 7; // mission, research, 7 checks let completed = (this.state.progress.mission ? 1 : 0) + (this.state.progress.research ? 1 : 0) + this.state.progress.checks; let pct = Math.round((completed / totalSteps) * 100); document.getElementById('progress-bar').style.width = `${pct}%`; document.getElementById('progress-text').innerText = `${pct}% Complete`; }, // --- Forms & Data Management (LocalStorage) --- loadData() { try { const saved = localStorage.getItem('ecoQuest_designs'); if (saved) { this.state.designs = JSON.parse(saved); } } catch (e) { console.error("Local storage read error", e); this.showToast("Failed to load saved data.", "error"); } }, saveToStorage() { try { localStorage.setItem('ecoQuest_designs', JSON.stringify(this.state.designs)); } catch (e) { console.error("Local storage write error", e); this.showToast("Failed to save data. Storage might be full.", "error"); } }, handleFormSubmit(e) { e.preventDefault(); const form = document.getElementById('design-form'); if (!form.checkValidity()) { this.showToast("Please fill out all required fields.", "error"); return; } // Gather data const score = parseInt(document.getElementById('f-score-1').value) + parseInt(document.getElementById('f-score-2').value) + parseInt(document.getElementById('f-score-3').value) + parseInt(document.getElementById('f-score-4').value); const newRecord = { id: this.state.editingId || Date.now().toString(), teamName: document.getElementById('f-team').value.trim(), designName: document.getElementById('f-design').value.trim(), material: document.getElementById('f-material').value, constraint: document.getElementById('f-constraint').value, howItHelps: document.getElementById('f-how').value.trim(), improve: document.getElementById('f-improve').value.trim(), score: score, timestamp: this.state.editingId ? this.getRecordById(this.state.editingId).timestamp : new Date().toISOString() }; if (this.state.editingId) { // Update existing const index = this.state.designs.findIndex(d => d.id === this.state.editingId); if(index > -1) this.state.designs[index] = newRecord; this.showToast("Design updated successfully!", "success"); } else { // Create new this.state.designs.push(newRecord); this.showToast("New design saved successfully!", "success"); } this.saveToStorage(); this.renderRecords(); this.updatePresentationSelect(); // Keep form populated if they just want to edit, or reset if desired. // We'll reset editingId so next save is new unless they click edit again. this.state.editingId = newRecord.id; document.getElementById('record-id').value = newRecord.id; this.updatePrintSheet(newRecord); }, editRecord(id) { const record = this.getRecordById(id); if(!record) return; this.state.editingId = record.id; document.getElementById('record-id').value = record.id; document.getElementById('f-team').value = record.teamName; document.getElementById('f-design').value = record.designName; document.getElementById('f-material').value = record.material; document.getElementById('f-constraint').value = record.constraint; document.getElementById('f-how').value = record.howItHelps; document.getElementById('f-improve').value = record.improve; // Rough estimate for sliders based on total score to recreate state let avg = Math.round(record.score / 4); [1,2,3,4].forEach(i => { document.getElementById(`f-score-${i}`).value = avg; this.updateSliderVal(`f-score-${i}`); }); this.calcSimulatorScore(); this.switchTab('tab-studio'); this.showToast(`Loaded ${record.teamName} into Studio for editing.`, "success"); this.updatePrintSheet(record); }, deleteRecord(id) { if(confirm("Are you sure you want to delete this record? This cannot be undone.")) { this.state.designs = this.state.designs.filter(d => d.id !== id); if(this.state.editingId === id) this.resetForm(); this.saveToStorage(); this.renderRecords(); this.updatePresentationSelect(); this.showToast("Record deleted.", "success"); } }, getRecordById(id) { return this.state.designs.find(d => d.id === id); }, resetForm() { document.getElementById('design-form').reset(); this.state.editingId = null; document.getElementById('record-id').value = ''; [1,2,3,4].forEach(i => this.updateSliderVal(`f-score-${i}`)); this.calcSimulatorScore(); this.showToast("Form cleared.", "success"); this.updatePrintSheet(null); }, clearAllData() { if(confirm("DANGER: Clear ALL saved student records?")) { this.state.designs = []; this.saveToStorage(); this.renderRecords(); this.resetForm(); this.updatePresentationSelect(); this.showToast("All data cleared.", "success"); } }, // --- DOM Rendering & Logic --- updateSliderVal(id) { const val = document.getElementById(id).value; document.getElementById(`val-${id}`).innerText = val; }, calcSimulatorScore() { let total = 0; [1,2,3,4].forEach(i => { total += parseInt(document.getElementById(`f-score-${i}`).value) || 0; }); document.getElementById('calc-score').innerText = total; let feedback = ""; if(total >= 15) feedback = "Level 4: Ecosystem Engineer! Outstanding model."; else if(total >= 11) feedback = "Level 3: Mission Ready. Great solid prototype."; else if(total >= 7) feedback = "Level 2: Building. Good start, but needs improvements."; else feedback = "Level 1: Starting. Re-check the habitat needs."; document.getElementById('calc-feedback').innerText = feedback; }, renderRecords() { const container = document.getElementById('records-container'); const emptyState = document.getElementById('empty-records'); const query = document.getElementById('search-records').value.toLowerCase(); const sort = document.getElementById('sort-records').value; container.innerHTML = ''; let filtered = this.state.designs.filter(d => d.teamName.toLowerCase().includes(query) || d.designName.toLowerCase().includes(query) || d.material.toLowerCase().includes(query) ); if (sort === 'newest') filtered.sort((a,b) => new Date(b.timestamp) - new Date(a.timestamp)); else if (sort === 'oldest') filtered.sort((a,b) => new Date(a.timestamp) - new Date(b.timestamp)); else if (sort === 'score_high') filtered.sort((a,b) => b.score - a.score); if (filtered.length === 0) { emptyState.classList.remove('hidden'); } else { emptyState.classList.add('hidden'); filtered.forEach(d => { const dateStr = new Date(d.timestamp).toLocaleDateString(); const card = document.createElement('div'); card.className = 'card'; card.innerHTML = ` <div class="flex justify-between items-center"> <h3 style="margin:0; color: var(--primary);">${d.teamName}</h3> <span class="badge" style="background: ${d.score >= 12 ? '#dcfce7; color:#166534' : ''}">Score: ${d.score}/16</span> </div> <p style="font-weight: 600;">${d.designName}</p> <p style="font-size: 0.85rem; color: var(--text-light);">Material: ${d.material}</p> <p style="font-size: 0.85rem; margin-top: 0.5rem;"><em>"${d.howItHelps.substring(0,60)}..."</em></p> <div class="flex mt-1"> <button class="btn-secondary" style="font-size: 0.8rem; padding: 0.25rem 0.5rem;" onclick="app.editRecord('${d.id}')">✏️ Edit</button> <button class="btn-danger" style="font-size: 0.8rem; padding: 0.25rem 0.5rem;" onclick="app.deleteRecord('${d.id}')">πŸ—‘οΈ Delete</button> </div> `; container.appendChild(card); }); } this.updatePresentationSelect(); }, renderVocab() { const list = document.getElementById('vocab-list'); list.innerHTML = ''; this.vocabData.forEach(v => { const el = document.createElement('div'); el.style.cssText = "padding: 0.5rem; border-bottom: 1px solid var(--border);"; el.innerHTML = `<strong>${v.word}</strong>: ${v.def}`; list.appendChild(el); }); }, filterVocab() { const query = document.getElementById('vocab-search').value.toLowerCase(); const list = document.getElementById('vocab-list'); list.innerHTML = ''; let found = 0; this.vocabData.forEach(v => { if(v.word.toLowerCase().includes(query) || v.def.toLowerCase().includes(query)) { const el = document.createElement('div'); el.style.cssText = "padding: 0.5rem; border-bottom: 1px solid var(--border);"; el.innerHTML = `<strong>${v.word}</strong>: ${v.def}`; list.appendChild(el); found++; } }); if(found === 0) list.innerHTML = `<div class="p-2 text-center" style="color: var(--text-light);">No words found.</div>`; }, // --- Generators & Interactive Tools --- generateMissionIdea() { const ideas = [ "A curved PVC pipe structure with small holes that blocks large fish.", "A dense web of zip-ties attached to a weighted base to mimic tentacles.", "A 3D-printed dome with multiple tiny exit routes for quick escapes.", "A layered clay structure resembling a stacked rock cave with narrow gaps." ]; const rand = ideas[Math.floor(Math.random() * ideas.length)]; document.getElementById('mission-idea-output').innerText = `Brainstorm Idea: ${rand}`; }, updatePresentationSelect() { const sel = document.getElementById('presentation-select'); sel.innerHTML = '<option value="">--Select a Record--</option>'; this.state.designs.forEach(d => { sel.innerHTML += `<option value="${d.id}">${d.teamName} - ${d.designName}</option>`; }); }, buildPresentation() { const id = document.getElementById('presentation-select').value; const out = document.getElementById('presentation-output'); if(!id) { out.value = ''; return; } const rec = this.getRecordById(id); out.value = `Hello, we are team ${rec.teamName}.\n\n` + `The species we are helping is the Clownfish, which is losing its anemone shelter due to coral bleaching.\n\n` + `Our model is called "${rec.designName}". We built it using ${rec.material}.\n\n` + `CLAIM: Our design helps the clownfish survive because ${rec.howItHelps}\n\n` + `EVIDENCE: When we tested our prototype, we scored a ${rec.score} out of 16 in the simulator.\n\n` + `REASONING: Our biggest constraint was "${rec.constraint}". To improve our design next time, we would change: ${rec.improve || "the materials to make it stronger."}\n\n` + `Thank you! Are there any questions?`; }, copyPresentation() { const text = document.getElementById('presentation-output').value; if(!text) { this.showToast("Nothing to copy!", "error"); return; } if (navigator.clipboard) { navigator.clipboard.writeText(text).then(() => { this.showToast("Copied to clipboard!", "success"); }); } else { // Fallback const ta = document.getElementById('presentation-output'); ta.select(); document.execCommand('copy'); this.showToast("Copied via fallback!", "success"); } }, generateExtensions() { const out = document.getElementById('extension-output'); out.innerHTML = ` <ul style="margin-left: 1.5rem; display:flex; flex-direction:column; gap:0.5rem;"> <li><strong>Science:</strong> Research another animal that relies on coral reefs (like the Sea Turtle or Parrotfish) and create a cause-and-effect map for them.</li> <li><strong>Engineering:</strong> Redesign your model using ONLY natural, biodegradable materials (like leaves, twigs, natural clay) instead of plastics.</li> <li><strong>Community:</strong> Write a short letter or make a poster explaining how reducing energy use at home can help slow down ocean warming.</li> </ul> `; }, exportData() { if(this.state.designs.length === 0) { this.showToast("No data to export.", "error"); return; } const dataStr = JSON.stringify(this.state.designs, null, 2); const blob = new Blob([dataStr], { type: "application/json" }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `ecoquest_data_${new Date().toISOString().split('T')[0]}.json`; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); this.showToast("Data exported!", "success"); }, updatePrintSheet(record) { if(!record) { document.getElementById('print-team').innerText = "___________"; document.getElementById('print-design').innerText = "___________"; document.getElementById('print-material').innerText = "___________"; document.getElementById('print-how').innerText = ""; document.getElementById('print-score').innerText = "__"; document.getElementById('print-improve').innerText = ""; } else { document.getElementById('print-team').innerText = record.teamName; document.getElementById('print-design').innerText = record.designName; document.getElementById('print-material').innerText = record.material; document.getElementById('print-how').innerText = record.howItHelps; document.getElementById('print-score').innerText = record.score; document.getElementById('print-improve').innerText = record.improve; } }, // --- Utilities --- showToast(msg, type="success") { const container = document.getElementById('toast-container'); const toast = document.createElement('div'); toast.className = `toast ${type}`; toast.innerText = msg; container.appendChild(toast); // Trigger reflow for animation setTimeout(() => toast.classList.add('show'), 10); setTimeout(() => { toast.classList.remove('show'); setTimeout(() => toast.remove(), 300); }, 3000); } }; // Initialize App on Load document.addEventListener('DOMContentLoaded', () => { app.init(); }); </script> </body> </html>
β™ŠοΈ Gemini

Habitat Stem Web App Builder

$6.99-50%
$3.50
SPECIAL PROMOTION β€” Offer ends 11 May
Add to Cart
Instant accessInstant access
Usage rightsCommercial use
Money-back guaranteeMoney‑back
By purchasing this prompt, you agree to our terms of service
GEMINI-3.1-PRO
Tested icon
Guide icon
4 examples icon
Free credits icon
interactive habitat STEM apps No coding skill needed. No technical setup required. Simply fill in a few easy fields, paste the prompt into Gemini, and let it generate for you.
...more
Added 2 days ago
Report
Browse Marketplace