Individual Oral (IO) Assessment Creation Guide

Develop your Individual Oral in three connected stages, starting with your IDEAs. Your fields save in this browser; download your work for your teacher and retain the process record.

✅ Auto-saved
Version history:

Use your own classwork and annotations. Open the stage you need; your Global Issue and thesis remain available in the evidence panel.

All your work is auto-saved in your browser (localStorage). Download to keep a permanent copy.

🧠 L&L Deliberate Practice AI examiner-trained
Ask me about the IO, Global Issues, deconstruction, or any part of the IO Creator guide. I'll point you to the right stage and resources.
📤 Chat popped out. Use the pop‑out window.
'; var blob = new Blob([html], { type: 'text/html' }); var url = URL.createObjectURL(blob); var a = document.createElement('a'); a.href = url; a.download = 'IO_Plan_' + new Date().toISOString().slice(0,10) + '.html'; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); } function downloadJSON() { var data = getCurrentData(); data['_exportedAt'] = new Date().toISOString(); var blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' }); var url = URL.createObjectURL(blob); var a = document.createElement('a'); a.href = url; a.download = 'IO_Plan_' + new Date().toISOString().slice(0,10) + '.json'; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); } function clearAll() { if (!confirm('Are you sure you want to clear ALL your work? This cannot be undone.')) return; localStorage.removeItem('io_creator_data'); var fields = document.querySelectorAll('[contenteditable="true"][data-field]'); fields.forEach(function(field) { field.innerHTML = ''; }); if(window.ioRestoreWorking)window.ioRestoreWorking({}); var status = document.getElementById('saveStatus'); status.textContent = '🗑️ Cleared'; status.className = 'save-status'; updateProgress(); setTimeout(function() { status.textContent = '✅ Auto-saved'; status.className = 'save-status saved'; }, 2000); } // ============================================================ // SCROLL SPY // ============================================================ function setupScrollSpy() { var links = document.querySelectorAll('.side-nav .step-link'); var sections = document.querySelectorAll('.step-accordion'); window.addEventListener('scroll', function() { var current = ''; sections.forEach(function(section) { var rect = section.getBoundingClientRect(); if (rect.top <= 150) current = section.id; }); links.forEach(function(link) { link.classList.toggle('active', link.getAttribute('href').substring(1) === current); }); }); } // ============================================================ // ACCORDION TOGGLES (FIXED) // ============================================================ function setupAccordions() { // Step accordions document.querySelectorAll('.step-accordion-header').forEach(function(header) { header.addEventListener('click', function() { var accordion = this.closest('.step-accordion'); if (accordion) accordion.classList.toggle('open'); }); }); // Resource accordions document.querySelectorAll('.resource-accordion-header').forEach(function(header) { header.addEventListener('click', function(e) { e.stopPropagation(); // prevent step accordion from toggling var accordion = this.closest('.resource-accordion'); if (accordion) accordion.classList.toggle('open'); }); }); // Mini accordions document.querySelectorAll('.mini-accordion-header').forEach(function(header) { header.addEventListener('click', function(e) { e.stopPropagation(); var accordion = this.closest('.mini-accordion'); if (accordion) accordion.classList.toggle('open'); }); }); } // ============================================================ // AI CHAT WIDGET – STAGE-AWARE, RESIZABLE, POPOUT (UPDATED) // ============================================================ (function() { var API_BASE = '/p1_api/api'; var messages = document.getElementById('aiChatMessages'); var input = document.getElementById('aiChatInput'); var sendBtn = document.getElementById('aiChatSend'); var toggleBtn = document.getElementById('aiChatToggleBtn'); var resetBtn = document.getElementById('aiChatReset'); var popoutBtn = document.getElementById('aiChatPopout'); var header = document.getElementById('aiChatToggle'); var widget = document.getElementById('aiChatWidget'); var resizeHandle = document.getElementById('aiChatResize'); var chatHistory = []; var popoutWindow = null; var popoutActive = false; window.SiteBeforeClearSavedWork=function(){if(popoutWindow&&!popoutWindow.closed)popoutWindow.close();}; // Distinct conversations for each panel, as in the HL Essay workspace. var HISTORY_KEY = 'io_creator_chat_history_v128'; var LEGACY_HISTORY_KEY = 'io_creator_chat_history'; var stageHistories = {landing:[],argument:[],analysis:[],outline:[]}; var activeHistoryKey = 'landing'; function historyKey() { var current = window.ioCurrentContext ? window.ioCurrentContext() : {}; return ['argument','analysis','outline'].includes(current.panel) ? current.panel : 'landing'; } function loadHistory() { try { var stored = JSON.parse(localStorage.getItem(HISTORY_KEY) || 'null'); if (stored && !Array.isArray(stored) && typeof stored === 'object') { Object.keys(stageHistories).forEach(function(k){ if(Array.isArray(stored[k])) stageHistories[k]=stored[k]; }); } else { var legacy=JSON.parse(localStorage.getItem(LEGACY_HISTORY_KEY)||'[]'); if(Array.isArray(legacy))stageHistories.landing=legacy; } } catch(e) {} chatHistory=stageHistories.landing; } function saveHistory() { if(window.SiteClearingSavedWork)return; try { var latest=JSON.parse(localStorage.getItem(HISTORY_KEY)||'{}'); if(!latest||typeof latest!=='object'||Array.isArray(latest))latest={}; latest.landing=stageHistories.landing; localStorage.setItem(HISTORY_KEY, JSON.stringify(latest)); } catch(e) {if(window.SiteSaveFailure)window.SiteSaveFailure();} } function selectHistory() { var next=historyKey(); if(next===activeHistoryKey)return; activeHistoryKey=next; chatHistory=stageHistories[next]; renderMessages(); } window.ioSelectConversation=selectHistory; loadHistory(); // ============================================================ // RESOURCE IMAGE RENDERER (new) // ============================================================ function renderResourceImages(text) { // Method names stay in the prose. Only an explicit resource link is rendered. return String(text || '').replace(/\[([^\]]+)\]\(((?:https?:\/\/lazilyefficientibenglish\.com)?\/?images\/[A-Za-z0-9_.\/-]+)\)/gi, function(_, label, url) { return '' + label + ''; }); } function formatTeacherMessage(text) { if(window.SiteAIMarkdown)return window.SiteAIMarkdown(text); if (!text) return ''; var escaped = text; escaped = escaped.replace(/\n/g, '
'); escaped = escaped.replace(/\*\*(.*?)\*\*/g, '$1'); escaped = escaped.replace(/\*(.*?)\*/g, '$1'); escaped = escaped.replace(/^[•\-*]\s+(.*?)$/gm, '
  • $1
  • '); escaped = escaped.replace(/(
  • .*?<\/li>)/gs, function(match) { return ''; }); escaped = escaped.replace(/