{"id":751,"date":"2026-03-04T13:32:19","date_gmt":"2026-03-04T13:32:19","guid":{"rendered":"https:\/\/i-cte.org\/robot\/?p=751"},"modified":"2026-03-05T04:19:51","modified_gmt":"2026-03-05T04:19:51","slug":"ai-assisted-reading-summarizing-note-making","status":"publish","type":"post","link":"https:\/\/i-cte.org\/robot\/ai-assisted-reading-summarizing-note-making\/","title":{"rendered":"AI-assisted Reading: Summarizing &amp; Note-making"},"content":{"rendered":"\n<!-- \u2705 UPDATE: Added (1) Conversation section (coach chat) + (2) Prompts section with examples\n     WP-safe single block, two-speaker Google Voices preserved.\n-->\n<div id=\"icte-readingai\">\n\n  <!-- \u2705 TOP MENU -->\n  <nav class=\"icte-menu\" aria-label=\"AI-assisted reading lesson navigation\">\n    <a href=\"#\" class=\"is-current\" data-view=\"overview\">Overview<\/a>\n    <a href=\"#\" data-view=\"conversation\">Conversation<\/a>\n    <a href=\"#\" data-view=\"reading\">Reading<\/a>\n    <a href=\"#\" data-view=\"skills\">Skills Toolkit<\/a>\n    <a href=\"#\" data-view=\"prompts\">Prompts<\/a>\n    <a href=\"#\" data-view=\"listening\">Listening<\/a>\n    <a href=\"#\" data-view=\"lab\">Reading Lab<\/a>\n    <a href=\"#\" data-view=\"progress\">Progress<\/a>\n  <\/nav>\n\n  <section class=\"icte-shell\" aria-label=\"ICTE AI-assisted reading lesson\">\n\n    <!-- \u2705 Header -->\n    <header class=\"icte-hero\">\n      <div class=\"icte-hero__text\">\n        <div class=\"hero-top\">\n          <img decoding=\"async\"\n            class=\"hero-img\"\n            src=\"https:\/\/i-cte.org\/robot\/wp-content\/uploads\/2026\/03\/reading.png\"\n            alt=\"AI-assisted reading lesson banner\"\n            loading=\"lazy\"\n          \/>\n          <div class=\"hero-title\">\n            <h2>AI-assisted Reading: Summarizing &#038; Note-making<\/h2>\n            <p class=\"muted\">\n              Practice <b>structured summaries<\/b>, build a <b>concept map<\/b>, extract <b>claims &#038; evidence<\/b>, and generate a\n              <b>study guide<\/b>. Includes <b>conversation<\/b>, <b>prompt examples<\/b>, <b>reading text<\/b>, <b>MCQ quiz<\/b>,\n              and a <b>two-speaker Google Voices<\/b> dialogue.\n            <\/p>\n          <\/div>\n        <\/div>\n      <\/div>\n\n      <div class=\"icte-hero__controls\">\n        <div class=\"icte-pill\">\n          <span class=\"dot\" id=\"icteMicDot\" aria-hidden=\"true\"><\/span>\n          <span id=\"icteMicStatus\">Mic: Off<\/span>\n        <\/div>\n\n        <div class=\"icte-row\">\n          <button class=\"btn\" id=\"icteStartVoice\" type=\"button\">Start Voice<\/button>\n          <button class=\"btn ghost\" id=\"icteStopVoice\" type=\"button\">Stop<\/button>\n        <\/div>\n\n        <!-- \u2705 Multi-speaker Google Voices -->\n        <div class=\"grid2\" style=\"margin-top:10px;\">\n          <label class=\"icte-label\">\n            Speaker A (Google)\n            <select id=\"voiceA\" class=\"icte-select\" aria-label=\"Speaker A voice\"><\/select>\n          <\/label>\n\n          <label class=\"icte-label\">\n            Speaker B (Google)\n            <select id=\"voiceB\" class=\"icte-select\" aria-label=\"Speaker B voice\"><\/select>\n          <\/label>\n        <\/div>\n\n        <div class=\"icte-row\" style=\"margin-top:10px;\">\n          <button class=\"btn mini ghost\" type=\"button\" id=\"speakActive\">\ud83d\udd0a Read this page<\/button>\n          <button class=\"btn mini ghost\" type=\"button\" id=\"stopSpeak\">\u23f9 Stop audio<\/button>\n        <\/div>\n\n        <div class=\"icte-small muted\">\n          Tip: For best voice options, use Chrome\/Edge. If voices don\u2019t appear yet, click once on the page and wait 2\u20133 seconds.\n        <\/div>\n      <\/div>\n    <\/header>\n\n    <!-- \u2705 Views -->\n    <main class=\"icte-main\">\n\n      <!-- ===================== -->\n      <!-- \u2705 OVERVIEW -->\n      <!-- ===================== -->\n      <section class=\"view is-active\" data-view=\"overview\" aria-label=\"Lesson overview\">\n        <div class=\"card\">\n          <div class=\"card-h\">\n            <h3>1) What you will learn<\/h3>\n            <div class=\"card-actions\">\n              <button class=\"btn mini\" type=\"button\" data-say=\"overview-instr\">\ud83d\udd0a Read instructions<\/button>\n            <\/div>\n          <\/div>\n\n          <div class=\"grid2\">\n            <div class=\"qitem\">\n              <div class=\"qtext\">Core skills<\/div>\n              <ul class=\"ul\">\n                <li><b>Structured summary<\/b> (gist + key points + takeaway)<\/li>\n                <li><b>Claim\u2013Evidence extraction<\/b> (what is asserted vs what supports it)<\/li>\n                <li><b>Concept mapping<\/b> (nodes + labeled links)<\/li>\n                <li><b>Study guide generation<\/b> (questions, key terms, common confusions)<\/li>\n              <\/ul>\n            <\/div>\n            <div class=\"qitem\">\n              <div class=\"qtext\">AI safety rules (non-negotiable)<\/div>\n              <ul class=\"ul\">\n                <li>No invented facts, numbers, or citations.<\/li>\n                <li>Quote only what exists; otherwise paraphrase.<\/li>\n                <li>Label uncertainty (\u201cNot stated in the text\u201d).<\/li>\n                <li>AI is a <b>reading assistant<\/b>, not a source.<\/li>\n              <\/ul>\n            <\/div>\n          <\/div>\n\n          <div class=\"note\">\n            <b>Workflow:<\/b> Read \u2192 extract claims\/evidence \u2192 summarize \u2192 map concepts \u2192 generate study guide \u2192 verify with the text.\n          <\/div>\n        <\/div>\n      <\/section>\n\n      <!-- ===================== -->\n      <!-- \u2705 CONVERSATION (NEW) -->\n      <!-- ===================== -->\n      <section class=\"view\" data-view=\"conversation\" aria-label=\"Conversation coach\">\n        <div class=\"card\">\n          <div class=\"card-h\">\n            <h3>2) Conversation (Reading Coach)<\/h3>\n            <div class=\"card-actions\">\n              <button class=\"btn mini\" type=\"button\" data-say=\"conv-instr\">\ud83d\udd0a Read instructions<\/button>\n              <button class=\"btn mini ghost\" type=\"button\" id=\"convHear\">\ud83d\udd0a Read last question<\/button>\n              <button class=\"btn mini ghost\" type=\"button\" id=\"convReset\">Reset<\/button>\n            <\/div>\n          <\/div>\n\n          <p class=\"muted\">\n            Practice a safe AI-assisted reading workflow. You will answer short prompts about <b>gist<\/b>, <b>key points<\/b>,\n            <b>claims\/evidence<\/b>, and <b>traceability<\/b>.\n          <\/p>\n\n          <div class=\"chat\" id=\"convChat\" aria-live=\"polite\" aria-label=\"Conversation chat log\"><\/div>\n\n          <div class=\"chatbar\">\n            <input id=\"convText\" class=\"input\" type=\"text\" placeholder=\"Type your answer (or use voice)...\" autocomplete=\"off\" \/>\n            <button class=\"btn\" id=\"convSend\" type=\"button\">Send<\/button>\n          <\/div>\n\n          <div class=\"note\">\n            <b>Tip:<\/b> When you use an AI tool for notes, always ask: \u201cWhere in the text is this stated?\u201d\n          <\/div>\n        <\/div>\n      <\/section>\n\n      <!-- ===================== -->\n      <!-- \u2705 READING + QUIZ -->\n      <!-- ===================== -->\n      <section class=\"view\" data-view=\"reading\" aria-label=\"Reading and quiz\">\n        <div class=\"card\">\n          <div class=\"card-h\">\n            <h3>3) Reading + Comprehension Quiz<\/h3>\n            <div class=\"card-actions\">\n              <button class=\"btn mini\" type=\"button\" data-say=\"reading-instr\">\ud83d\udd0a Read instructions<\/button>\n              <button class=\"btn mini ghost\" type=\"button\" id=\"readTextBtn\">\ud83d\udd0a Read the text<\/button>\n              <button class=\"btn mini ghost\" type=\"button\" id=\"quizCheck\">Check answers<\/button>\n            <\/div>\n          <\/div>\n\n          <article class=\"reading\" id=\"readingText\" aria-label=\"Reading text about AI-assisted reading\">\n            <div class=\"reading-title\">Reading: AI-assisted reading for summarizing and note-making<\/div>\n\n            <div class=\"reading-p\">\n              <b>1<\/b> AI tools can support reading by helping learners turn a long text into usable learning materials. However, AI should be treated as\n              an assistant that helps with <b>processing<\/b> rather than as an authority that provides new information. The reader must still verify the output\n              against the original text.\n            <\/div>\n\n            <div class=\"reading-p\">\n              <b>2<\/b> A strong first step is writing a <b>structured summary<\/b>. Instead of a vague overview, a structured summary usually includes:\n              (a) one-sentence gist, (b) three to five key points, and (c) one implication or takeaway. This format helps students keep the main idea while\n              avoiding irrelevant details.\n            <\/div>\n\n            <div class=\"reading-p\">\n              <b>3<\/b> Another essential skill is extracting <b>claims<\/b> and matching them with <b>evidence<\/b>. A claim is what the author argues or concludes.\n              Evidence is the support, such as examples, data, citations, or reasoning. When learners separate claims from evidence, they can better evaluate\n              credibility and avoid repeating opinions as facts.\n            <\/div>\n\n            <div class=\"reading-p\">\n              <b>4<\/b> Learners can also use concept mapping to represent ideas visually. A concept map identifies key concepts as nodes and connects them with\n              labeled links such as \u201cleads to,\u201d \u201cincludes,\u201d or \u201ccontrasts with.\u201d The goal is not decoration but clarity: a map should show how ideas relate,\n              which ideas are central, and where the argument is weak or incomplete.\n            <\/div>\n\n            <div class=\"reading-p\">\n              <b>5<\/b> Finally, AI can generate a study guide from the reader\u2019s notes. A useful guide includes: key terms with simple definitions, common\n              confusions, short-answer questions, and one higher-order question that requires synthesis. The safest practice is to ask AI to cite the exact\n              sentence or paragraph number for each claim it uses; if the evidence cannot be located, the point should be removed.\n            <\/div>\n          <\/article>\n\n          <h4 class=\"h4\" style=\"margin-top:12px;\">Comprehension check (choose the best answer)<\/h4>\n          <div id=\"quiz\" class=\"stack\"><\/div>\n          <div class=\"feedback\" id=\"quizFb\" aria-live=\"polite\"><\/div>\n        <\/div>\n      <\/section>\n\n      <!-- ===================== -->\n      <!-- \u2705 SKILLS TOOLKIT -->\n      <!-- ===================== -->\n      <section class=\"view\" data-view=\"skills\" aria-label=\"Skills toolkit\">\n        <div class=\"card\">\n          <div class=\"card-h\">\n            <h3>4) Skills Toolkit (Templates + Examples)<\/h3>\n            <div class=\"card-actions\">\n              <button class=\"btn mini\" type=\"button\" data-say=\"skills-instr\">\ud83d\udd0a Read instructions<\/button>\n              <button class=\"btn mini ghost\" type=\"button\" id=\"skillsSpeak\">\ud83d\udd0a Read toolkit<\/button>\n            <\/div>\n          <\/div>\n\n          <div class=\"grid2\">\n            <div class=\"qitem\">\n              <div class=\"qtext\">A) Structured summary template<\/div>\n              <pre class=\"pre\" id=\"tplSummary\"><\/pre>\n            <\/div>\n\n            <div class=\"qitem\">\n              <div class=\"qtext\">B) Claim\u2013Evidence table template<\/div>\n              <pre class=\"pre\" id=\"tplClaims\"><\/pre>\n            <\/div>\n          <\/div>\n\n          <div class=\"grid2\" style=\"margin-top:12px;\">\n            <div class=\"qitem\">\n              <div class=\"qtext\">C) Concept map prompt + format<\/div>\n              <pre class=\"pre\" id=\"tplMap\"><\/pre>\n            <\/div>\n\n            <div class=\"qitem\">\n              <div class=\"qtext\">D) Study guide template<\/div>\n              <pre class=\"pre\" id=\"tplGuide\"><\/pre>\n            <\/div>\n          <\/div>\n\n          <div class=\"qitem\" style=\"margin-top:12px;\">\n            <div class=\"qtext\">Worked example (from this reading)<\/div>\n            <pre class=\"pre\" id=\"workedExample\"><\/pre>\n          <\/div>\n        <\/div>\n      <\/section>\n\n      <!-- ===================== -->\n      <!-- \u2705 PROMPTS (NEW) -->\n      <!-- ===================== -->\n      <section class=\"view\" data-view=\"prompts\" aria-label=\"Prompts and examples\">\n        <div class=\"card\">\n          <div class=\"card-h\">\n            <h3>5) Prompts + Examples (Copy &#038; Adapt)<\/h3>\n            <div class=\"card-actions\">\n              <button class=\"btn mini\" type=\"button\" data-say=\"prompts-instr\">\ud83d\udd0a Read instructions<\/button>\n              <button class=\"btn mini ghost\" type=\"button\" id=\"promptsSpeak\">\ud83d\udd0a Read prompts<\/button>\n              <button class=\"btn mini ghost\" type=\"button\" id=\"copyPrompts\">Copy all<\/button>\n            <\/div>\n          <\/div>\n\n          <div class=\"note\">\n            <b>Use rule:<\/b> Ask for <b>traceability<\/b>. If the tool cannot point to where an idea is stated in the text, it must label it \u201cNot stated.\u201d\n          <\/div>\n\n          <div class=\"grid2\">\n            <div class=\"qitem\">\n              <div class=\"qtext\">Prompt 1 \u2014 Structured summary (with paragraph trace)<\/div>\n              <pre class=\"pre\" id=\"p1\"><\/pre>\n            <\/div>\n            <div class=\"qitem\">\n              <div class=\"qtext\">Prompt 2 \u2014 Claims &#038; evidence extraction (table)<\/div>\n              <pre class=\"pre\" id=\"p2\"><\/pre>\n            <\/div>\n          <\/div>\n\n          <div class=\"grid2\" style=\"margin-top:12px;\">\n            <div class=\"qitem\">\n              <div class=\"qtext\">Prompt 3 \u2014 Concept map (nodes + labeled links)<\/div>\n              <pre class=\"pre\" id=\"p3\"><\/pre>\n            <\/div>\n            <div class=\"qitem\">\n              <div class=\"qtext\">Prompt 4 \u2014 Study guide (questions + common confusions)<\/div>\n              <pre class=\"pre\" id=\"p4\"><\/pre>\n            <\/div>\n          <\/div>\n\n          <div class=\"qitem\" style=\"margin-top:12px;\">\n            <div class=\"qtext\">Mini example (input text \u2192 expected output style)<\/div>\n            <pre class=\"pre\" id=\"pExample\"><\/pre>\n          <\/div>\n        <\/div>\n      <\/section>\n\n      <!-- ===================== -->\n      <!-- \u2705 LISTENING (2 voices) -->\n      <!-- ===================== -->\n      <section class=\"view\" data-view=\"listening\" aria-label=\"Two-speaker listening\">\n        <div class=\"card\">\n          <div class=\"card-h\">\n            <h3>6) Listening (Two Google Voices) \u2014 \u201cDon\u2019t let AI hallucinate your notes\u201d<\/h3>\n            <div class=\"card-actions\">\n              <button class=\"btn mini\" type=\"button\" data-say=\"list-instr\">\ud83d\udd0a Read instructions<\/button>\n              <button class=\"btn mini\" type=\"button\" id=\"listenPlay\">\u25b6\ufe0f Play dialogue<\/button>\n              <button class=\"btn mini ghost\" type=\"button\" id=\"listenStop\">\u23f9 Stop<\/button>\n              <button class=\"btn mini ghost\" type=\"button\" id=\"listenCheck\">Check answers<\/button>\n            <\/div>\n          <\/div>\n\n          <p class=\"muted\">\n            Listen to two instructors discussing structured summaries, claims\/evidence, and concept maps. Then answer the questions.\n          <\/p>\n\n          <div id=\"listenQ\" class=\"stack\"><\/div>\n          <div class=\"feedback\" id=\"listenFb\" aria-live=\"polite\"><\/div>\n        <\/div>\n      <\/section>\n\n      <!-- ===================== -->\n      <!-- \u2705 READING LAB -->\n      <!-- ===================== -->\n      <section class=\"view\" data-view=\"lab\" aria-label=\"Reading lab\">\n        <div class=\"card\">\n          <div class=\"card-h\">\n            <h3>7) Reading Lab (Paste a text \u2192 build notes)<\/h3>\n            <div class=\"card-actions\">\n              <button class=\"btn mini\" type=\"button\" data-say=\"lab-instr\">\ud83d\udd0a Read instructions<\/button>\n              <button class=\"btn mini ghost\" type=\"button\" id=\"labGenerate\">Generate outputs<\/button>\n              <button class=\"btn mini ghost\" type=\"button\" id=\"labCopyAll\">Copy all<\/button>\n              <button class=\"btn mini ghost\" type=\"button\" id=\"labScore\">Self-check<\/button>\n            <\/div>\n          <\/div>\n\n          <div class=\"note\">\n            Paste a text and generate: <b>structured summary<\/b>, <b>claims\/evidence<\/b>, <b>concept map<\/b>, and a <b>study guide<\/b>.\n            This demo uses built-in heuristics (no external AI calls). Copy outputs into your AI tool with a safe prompt.\n          <\/div>\n\n          <div class=\"grid2\">\n            <div class=\"qitem\">\n              <div class=\"qtext\">A) Paste your reading text<\/div>\n              <textarea class=\"textarea\" id=\"labText\" rows=\"10\" placeholder=\"Paste a short reading text here (recommended 120\u2013500 words)...\"><\/textarea>\n              <div class=\"icte-small muted\" style=\"margin-top:6px;\">\n                Voice input: If your mic is on, speaking will append text here in the Lab view.\n              <\/div>\n            <\/div>\n\n            <div class=\"qitem\">\n              <div class=\"qtext\">B) Choose output settings<\/div>\n\n              <label class=\"icte-label\">Summary length<\/label>\n              <select class=\"icte-select\" id=\"sumLen\" aria-label=\"Summary length\">\n                <option value=\"short\">Short (1 gist + 3 points)<\/option>\n                <option value=\"medium\" selected>Medium (1 gist + 5 points + implication)<\/option>\n                <option value=\"long\">Long (1 gist + 7 points + implication + limitation)<\/option>\n              <\/select>\n\n              <label class=\"icte-label\">Study guide level<\/label>\n              <select class=\"icte-select\" id=\"guideLevel\" aria-label=\"Study guide level\">\n                <option value=\"b1\">B1\u2013B2 (simple language)<\/option>\n                <option value=\"c1\" selected>C1 (academic)<\/option>\n              <\/select>\n\n              <label class=\"icte-label\">Safety constraints (recommended)<\/label>\n              <div class=\"stack\" id=\"labConstraints\"><\/div>\n            <\/div>\n          <\/div>\n\n          <div class=\"qitem\" style=\"margin-top:12px;\">\n            <div class=\"qtext\">Generated outputs<\/div>\n            <div class=\"grid2\">\n              <div>\n                <div class=\"icte-label\">Structured summary<\/div>\n                <pre class=\"pre\" id=\"outSummary\"><\/pre>\n              <\/div>\n              <div>\n                <div class=\"icte-label\">Claim\u2013Evidence pairs<\/div>\n                <pre class=\"pre\" id=\"outClaims\"><\/pre>\n              <\/div>\n            <\/div>\n\n            <div class=\"grid2\" style=\"margin-top:12px;\">\n              <div>\n                <div class=\"icte-label\">Concept map (text format)<\/div>\n                <pre class=\"pre\" id=\"outMap\"><\/pre>\n              <\/div>\n              <div>\n                <div class=\"icte-label\">Study guide<\/div>\n                <pre class=\"pre\" id=\"outGuide\"><\/pre>\n              <\/div>\n            <\/div>\n          <\/div>\n\n          <div class=\"qitem\" style=\"margin-top:12px;\">\n            <div class=\"qtext\">Safe \u201cAI prompt\u201d you can copy into any tool<\/div>\n            <pre class=\"pre\" id=\"outPrompt\"><\/pre>\n          <\/div>\n\n          <div class=\"feedback\" id=\"labFb\" aria-live=\"polite\"><\/div>\n        <\/div>\n      <\/section>\n\n      <!-- ===================== -->\n      <!-- \u2705 PROGRESS -->\n      <!-- ===================== -->\n      <section class=\"view\" data-view=\"progress\" aria-label=\"Progress tracking\">\n        <div class=\"card\">\n          <div class=\"card-h\">\n            <h3>Progress<\/h3>\n            <div class=\"card-actions\">\n              <button class=\"btn mini ghost\" type=\"button\" id=\"progressReset\">Clear progress<\/button>\n            <\/div>\n          <\/div>\n\n          <div class=\"progress-grid\">\n            <div class=\"pbox\">\n              <div class=\"pnum\" id=\"pDone\">0<\/div>\n              <div class=\"muted\">Activities completed<\/div>\n            <\/div>\n            <div class=\"pbox\">\n              <div class=\"pnum\" id=\"pScore\">0%<\/div>\n              <div class=\"muted\">Average score<\/div>\n            <\/div>\n            <div class=\"pbox\">\n              <div class=\"pnum\" id=\"pChecks\">0<\/div>\n              <div class=\"muted\">Safety checks used<\/div>\n            <\/div>\n          <\/div>\n\n          <div class=\"note\">\n            Saved in your browser (local storage). Switching browsers\/devices resets progress.\n          <\/div>\n\n          <h4 class=\"h4\">Safety &#038; quality checklist bank<\/h4>\n          <div class=\"bank\" id=\"checksBank\"><\/div>\n        <\/div>\n      <\/section>\n\n    <\/main>\n  <\/section>\n\n  <style>\n    \/* ===== WP-SAFE STYLES (scoped) ===== *\/\n    #icte-readingai *{ box-sizing:border-box; }\n    #icte-readingai{\n      --green:#28a745;\n      --dark:#132018;\n      --card:#ffffff;\n      --muted:#6b7280;\n      --line:#e5e7eb;\n      --shadow:0 8px 24px rgba(17,24,39,.08);\n      --radius:16px;\n      font-family: system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif;\n      color:#111827;\n    }\n    #icte-readingai .icte-menu{\n      width:100%;\n      background:var(--green);\n      padding:10px 12px;\n      text-align:center;\n      overflow-x:auto;\n      white-space:nowrap;\n      position:sticky;\n      top:0;\n      z-index:999;\n      box-shadow:0 2px 10px rgba(0,0,0,.12);\n      border-radius:12px;\n      margin-bottom:12px;\n    }\n    #icte-readingai .icte-menu a{\n      display:inline-block;\n      color:#fff;\n      text-decoration:none;\n      font-weight:900;\n      padding:8px 10px;\n      border-radius:999px;\n      margin:0 3px;\n      opacity:.92;\n      transition:.15s;\n    }\n    #icte-readingai .icte-menu a:hover{ opacity:1; background:rgba(255,255,255,.14); }\n    #icte-readingai .icte-menu a.is-current{ background:#fff; color:var(--dark); opacity:1; }\n\n    #icte-readingai .icte-shell{ max-width:1100px; margin:0 auto; }\n    #icte-readingai .icte-hero{\n      display:grid;\n      grid-template-columns: 1.2fr .8fr;\n      gap:14px;\n      background:linear-gradient(135deg,#e9fff0, #ffffff);\n      border:1px solid var(--line);\n      border-radius:var(--radius);\n      padding:16px;\n      box-shadow:var(--shadow);\n      margin-bottom:14px;\n    }\n    @media (max-width: 920px){ #icte-readingai .icte-hero{ grid-template-columns:1fr; } }\n    #icte-readingai h2{ margin:0 0 6px 0; font-size:22px; }\n    #icte-readingai .muted{ color:var(--muted); }\n\n    #icte-readingai .hero-top{ display:flex; gap:12px; align-items:center; }\n    #icte-readingai .hero-img{\n      width:140px;\n      height:auto;\n      border-radius:14px;\n      border:1px solid var(--line);\n      background:#111;\n      box-shadow:var(--shadow);\n    }\n    @media (max-width: 920px){\n      #icte-readingai .hero-top{ flex-direction:column; align-items:flex-start; }\n      #icte-readingai .hero-img{ width:100%; max-width:520px; }\n    }\n\n    #icte-readingai .icte-hero__controls{\n      border-left:1px dashed var(--line);\n      padding-left:14px;\n    }\n    @media (max-width: 920px){\n      #icte-readingai .icte-hero__controls{ border-left:none; padding-left:0; border-top:1px dashed var(--line); padding-top:12px; }\n    }\n\n    #icte-readingai .icte-row{ display:flex; gap:8px; flex-wrap:wrap; }\n    #icte-readingai .icte-label{ display:block; font-size:12px; font-weight:900; margin-top:8px; }\n    #icte-readingai .icte-select{\n      width:100%;\n      padding:10px 10px;\n      border:1px solid var(--line);\n      border-radius:12px;\n      background:#fff;\n      outline:none;\n      margin-top:6px;\n    }\n\n    #icte-readingai .icte-pill{\n      display:flex; align-items:center; gap:8px;\n      padding:10px 12px;\n      border:1px solid var(--line);\n      border-radius:999px;\n      background:#fff;\n      margin-bottom:10px;\n      font-weight:900;\n    }\n    #icte-readingai .dot{\n      width:10px; height:10px; border-radius:50%;\n      background:#9ca3af;\n      box-shadow:0 0 0 4px rgba(156,163,175,.18);\n    }\n    #icte-readingai .dot.on{\n      background:#22c55e;\n      box-shadow:0 0 0 4px rgba(34,197,94,.18);\n    }\n\n    #icte-readingai .btn{\n      border:none;\n      padding:10px 12px;\n      border-radius:12px;\n      background:var(--green);\n      color:#fff;\n      font-weight:900;\n      cursor:pointer;\n      transition:.15s;\n    }\n    #icte-readingai .btn:hover{ filter:brightness(.95); transform:translateY(-1px); }\n    #icte-readingai .btn:active{ transform:translateY(0); }\n    #icte-readingai .btn.ghost{\n      background:#fff;\n      color:#111827;\n      border:1px solid var(--line);\n    }\n    #icte-readingai .btn.mini{ padding:8px 10px; border-radius:10px; font-size:13px; }\n    #icte-readingai .icte-small{ font-size:12px; }\n\n    #icte-readingai .card{\n      background:var(--card);\n      border:1px solid var(--line);\n      border-radius:var(--radius);\n      padding:14px;\n      box-shadow:var(--shadow);\n      margin-bottom:14px;\n    }\n    #icte-readingai .card-h{\n      display:flex; gap:10px; align-items:flex-start; justify-content:space-between;\n      border-bottom:1px solid var(--line);\n      padding-bottom:10px;\n      margin-bottom:10px;\n    }\n    #icte-readingai .card-h h3{ margin:0; font-size:18px; }\n    #icte-readingai .card-actions{ display:flex; gap:8px; flex-wrap:wrap; justify-content:flex-end; }\n\n    #icte-readingai .view{ display:none; }\n    #icte-readingai .view.is-active{ display:block; }\n\n    #icte-readingai .grid2{\n      display:grid;\n      grid-template-columns:1fr 1fr;\n      gap:14px;\n      margin-top:10px;\n    }\n    @media (max-width: 920px){ #icte-readingai .grid2{ grid-template-columns:1fr; } }\n\n    #icte-readingai .stack{ display:flex; flex-direction:column; gap:10px; }\n    #icte-readingai .h4{ margin:0 0 6px 0; font-size:15px; }\n    #icte-readingai .qitem{\n      padding:10px;\n      border:1px solid var(--line);\n      border-radius:14px;\n      background:#fafafa;\n    }\n    #icte-readingai .qtext{ font-weight:900; margin-bottom:8px; }\n\n    #icte-readingai .feedback{\n      margin-top:10px;\n      padding:10px 12px;\n      border-radius:14px;\n      border:1px solid var(--line);\n      background:#f9fafb;\n      font-weight:800;\n      display:none;\n      white-space:pre-line;\n    }\n    #icte-readingai .feedback.ok{ display:block; border-color:rgba(34,197,94,.35); background:#ecfdf5; }\n    #icte-readingai .feedback.bad{ display:block; border-color:rgba(239,68,68,.35); background:#fef2f2; }\n\n    #icte-readingai .note{\n      background:#eff6ff;\n      border:1px solid rgba(59,130,246,.22);\n      padding:10px 12px;\n      border-radius:14px;\n      margin:10px 0;\n    }\n\n    #icte-readingai .reading{\n      border:1px solid var(--line);\n      border-radius:14px;\n      padding:12px;\n      background:#fff;\n      margin-top:10px;\n    }\n    #icte-readingai .reading-title{ font-weight:900; margin-bottom:8px; }\n    #icte-readingai .reading-p{ padding:8px 0; border-top:1px dashed var(--line); }\n    #icte-readingai .reading-p:first-of-type{ border-top:none; }\n\n    #icte-readingai .progress-grid{\n      display:grid;\n      grid-template-columns:repeat(3,1fr);\n      gap:12px;\n      margin-top:10px;\n      margin-bottom:10px;\n    }\n    @media (max-width: 920px){ #icte-readingai .progress-grid{ grid-template-columns:1fr; } }\n    #icte-readingai .pbox{\n      border:1px solid var(--line);\n      border-radius:16px;\n      background:#fff;\n      padding:12px;\n      text-align:center;\n      box-shadow:var(--shadow);\n    }\n    #icte-readingai .pnum{ font-size:28px; font-weight:1000; }\n\n    #icte-readingai .bank{\n      border:1px solid var(--line);\n      border-radius:14px;\n      padding:12px;\n      background:#fff;\n      display:flex;\n      flex-wrap:wrap;\n      gap:8px;\n    }\n    #icte-readingai .tag{\n      border:1px solid var(--line);\n      background:#f9fafb;\n      padding:6px 10px;\n      border-radius:999px;\n      font-weight:900;\n      font-size:13px;\n    }\n\n    #icte-readingai .pre{\n      white-space:pre-wrap;\n      background:#0b1220;\n      color:#e5e7eb;\n      border-radius:12px;\n      padding:12px;\n      border:1px solid rgba(255,255,255,.08);\n      overflow:auto;\n      font-size:13px;\n      line-height:1.45;\n    }\n\n    #icte-readingai .opt{\n      display:flex;\n      gap:10px;\n      align-items:flex-start;\n      padding:8px 10px;\n      border:1px solid var(--line);\n      border-radius:12px;\n      background:#fff;\n    }\n\n    #icte-readingai .ul{ margin:0; padding-left:18px; }\n    #icte-readingai .ul li{ margin:6px 0; }\n\n    #icte-readingai .textarea{\n      width:100%;\n      padding:12px;\n      border:1px solid var(--line);\n      border-radius:12px;\n      outline:none;\n      resize:vertical;\n    }\n\n    \/* Conversation UI *\/\n    #icte-readingai .chat{\n      background:#0b1220;\n      color:#e5e7eb;\n      border-radius:14px;\n      padding:12px;\n      min-height:220px;\n      max-height:420px;\n      overflow:auto;\n      border:1px solid rgba(255,255,255,.08);\n    }\n    #icte-readingai .msg{ margin:10px 0; display:flex; gap:10px; align-items:flex-start; }\n    #icte-readingai .who{\n      min-width:90px;\n      font-weight:900;\n      font-size:12px;\n      color:#93c5fd;\n      text-transform:uppercase;\n      letter-spacing:.06em;\n    }\n    #icte-readingai .bubble{\n      flex:1;\n      background:rgba(255,255,255,.06);\n      padding:10px 10px;\n      border-radius:12px;\n      line-height:1.45;\n      border:1px solid rgba(255,255,255,.06);\n      white-space:pre-line;\n    }\n    #icte-readingai .msg.user .who{ color:#86efac; }\n    #icte-readingai .msg.user .bubble{ background:rgba(34,197,94,.10); border-color:rgba(34,197,94,.18); }\n\n    #icte-readingai .chatbar{\n      margin-top:10px;\n      display:flex;\n      gap:8px;\n      align-items:center;\n    }\n    #icte-readingai .input{\n      flex:1;\n      padding:12px 12px;\n      border:1px solid var(--line);\n      border-radius:12px;\n      outline:none;\n    }\n  <\/style>\n\n  <script>\n    (function(){\n      const root = document.getElementById('icte-readingai');\n      if(!root) return;\n\n      \/* =========================\n         Helpers\n      ========================= *\/\n      const qs = (sel, el=root) => el.querySelector(sel);\n      const qsa = (sel, el=root) => Array.from(el.querySelectorAll(sel));\n      const clamp = (n,min,max)=>Math.max(min,Math.min(max,n));\n      const norm = (s)=> (s||\"\").toString().trim();\n      const esc = (s)=> (s||\"\").replace(\/[&<>\"']\/g, m=>({ \"&\":\"&amp;\",\"<\":\"&lt;\",\">\":\"&gt;\",'\"':\"&quot;\",\"'\":\"&#039;\" }[m]));\n      const splitSentences = (txt)=>{\n        const clean = (txt||\"\").replace(\/\\s+\/g,\" \").trim();\n        if(!clean) return [];\n        return clean.split(\/(?<=[.!?])\\s+(?=[A-Z(])\/).map(s=>s.trim()).filter(Boolean);\n      };\n\n      \/* =========================\n         Navigation\n      ========================= *\/\n      const navLinks = qsa('.icte-menu a');\n      const views = qsa('.view');\n      function showView(name){\n        views.forEach(v=> v.classList.toggle('is-active', v.getAttribute('data-view')===name));\n        navLinks.forEach(a=> a.classList.toggle('is-current', a.getAttribute('data-view')===name));\n        window.scrollTo({top: root.offsetTop - 10, behavior:'smooth'});\n      }\n      navLinks.forEach(a=>{\n        a.addEventListener('click', (e)=>{\n          e.preventDefault();\n          const v = a.getAttribute('data-view');\n          if(v) showView(v);\n        });\n      });\n\n      function activeViewName(){\n        const v = qs('.view.is-active');\n        return v ? v.getAttribute('data-view') : \"overview\";\n      }\n\n      \/* =========================\n         Multi-speaker Google Voices\n      ========================= *\/\n      const voiceASelect = qs('#voiceA');\n      const voiceBSelect = qs('#voiceB');\n\n      let allVoices = [];\n      let googleVoicesEN = [];\n      let voiceA = null;\n      let voiceB = null;\n\n      function isEnglish(v){ return (v.lang||\"\").toLowerCase().startsWith(\"en\"); }\n      function isGoogle(v){ return (v.name||\"\").toLowerCase().includes(\"google\"); }\n      function looksMaleName(name){\n        const n=(name||\"\").toLowerCase();\n        return n.includes(\"male\")||n.includes(\"david\")||n.includes(\"mark\")||n.includes(\"daniel\");\n      }\n      function looksFemaleName(name){\n        const n=(name||\"\").toLowerCase();\n        return n.includes(\"female\")||n.includes(\"susan\")||n.includes(\"amy\")||n.includes(\"emma\");\n      }\n      function pickDefaultVoices(list){\n        const a = list.find(v=>looksFemaleName(v.name)) || list[0] || null;\n        const b = list.find(v=>v!==a && looksMaleName(v.name)) || list.find(v=>v!==a) || a || null;\n        return {a,b};\n      }\n\n      function loadVoices(){\n        if(!window.speechSynthesis) return;\n        allVoices = speechSynthesis.getVoices() || [];\n        const google = allVoices.filter(v => isEnglish(v) && isGoogle(v));\n        const english = allVoices.filter(v => isEnglish(v));\n        googleVoicesEN = google.length ? google : english;\n\n        const buildSelect = (sel, list)=>{\n          sel.innerHTML=\"\";\n          list.forEach((v,i)=>{\n            const opt=document.createElement(\"option\");\n            opt.value=String(i);\n            opt.textContent=`${v.name} (${v.lang})`;\n            sel.appendChild(opt);\n          });\n        };\n\n        buildSelect(voiceASelect, googleVoicesEN);\n        buildSelect(voiceBSelect, googleVoicesEN);\n\n        const picked = pickDefaultVoices(googleVoicesEN);\n        voiceA = picked.a;\n        voiceB = picked.b;\n\n        voiceASelect.value = String(Math.max(0, googleVoicesEN.indexOf(voiceA)));\n        voiceBSelect.value = String(Math.max(0, googleVoicesEN.indexOf(voiceB)));\n\n        voiceASelect.onchange = ()=>{\n          const idx=parseInt(voiceASelect.value,10);\n          voiceA = googleVoicesEN[idx] || voiceA;\n        };\n        voiceBSelect.onchange = ()=>{\n          const idx=parseInt(voiceBSelect.value,10);\n          voiceB = googleVoicesEN[idx] || voiceB;\n        };\n      }\n      if(window.speechSynthesis){\n        loadVoices();\n        speechSynthesis.onvoiceschanged = loadVoices;\n      }\n\n      function stopSpeak(){ if(window.speechSynthesis) speechSynthesis.cancel(); }\n      function speakAs(role, text, opts){\n        const t = norm(text);\n        if(!t || !window.speechSynthesis) return Promise.resolve();\n        const o = opts || {};\n        const u = new SpeechSynthesisUtterance(t);\n        if(role===\"A\" && voiceA) u.voice = voiceA;\n        if(role===\"B\" && voiceB) u.voice = voiceB;\n        u.rate = o.rate ?? 1.02;\n        u.pitch = o.pitch ?? 1.0;\n        u.volume = o.volume ?? 1.0;\n        return new Promise(resolve=>{\n          u.onend=resolve; u.onerror=resolve;\n          speechSynthesis.speak(u);\n        });\n      }\n      async function speakDialogue(lines){\n        stopSpeak();\n        for(const line of lines){\n          await speakAs(line.role, line.text);\n        }\n      }\n\n      qs('#stopSpeak').addEventListener('click', stopSpeak);\n\n      \/* =========================\n         Mic Speech Recognition\n      ========================= *\/\n      const micDot = qs('#icteMicDot');\n      const micStatus = qs('#icteMicStatus');\n      const btnStartVoice = qs('#icteStartVoice');\n      const btnStopVoice = qs('#icteStopVoice');\n\n      let recognition = null;\n      let listening = false;\n\n      function setMicUI(on){\n        listening = on;\n        micDot.classList.toggle('on', on);\n        micStatus.textContent = on ? \"Mic: Listening\u2026\" : \"Mic: Off\";\n      }\n      function initRecognition(){\n        const SR = window.SpeechRecognition || window.webkitSpeechRecognition;\n        if(!SR) return null;\n        const r = new SR();\n        r.lang = 'en-US';\n        r.continuous = true;\n        r.interimResults = false;\n        r.maxAlternatives = 1;\n        return r;\n      }\n      function startListening(){\n        if(listening) return;\n        recognition = recognition || initRecognition();\n        if(!recognition){\n          alert(\"Speech Recognition is not available in this browser. Use Chrome\/Edge, or type.\");\n          return;\n        }\n        recognition.onresult = (e)=>{\n          const res = e.results[e.results.length - 1];\n          const transcript = res && res[0] ? res[0].transcript : \"\";\n          handleVoiceTranscript(transcript);\n        };\n        recognition.onerror = ()=> setMicUI(false);\n        recognition.onend = ()=>{ if(listening){ try{ recognition.start(); }catch(_){ } } };\n        setMicUI(true);\n        try{ recognition.start(); }catch(_){ }\n      }\n      function stopListening(){\n        setMicUI(false);\n        try{ recognition && recognition.stop(); }catch(_){ }\n      }\n      btnStartVoice.addEventListener('click', startListening);\n      btnStopVoice.addEventListener('click', stopListening);\n\n      \/* =========================\n         Progress (localStorage)\n      ========================= *\/\n      const LS_KEY = \"icte_readingai_progress_v2\";\n      const progress = JSON.parse(localStorage.getItem(LS_KEY) || \"{}\");\n\n      function saveProgress(){ localStorage.setItem(LS_KEY, JSON.stringify(progress)); renderProgress(); }\n      function markDone(key, scorePct){\n        progress[key] = { done:true, score: clamp(scorePct,0,100), ts: Date.now() };\n        saveProgress();\n      }\n      function resetProgress(){ localStorage.removeItem(LS_KEY); location.reload(); }\n      qs('#progressReset').addEventListener('click', resetProgress);\n\n      const checks = [\n        {k:\"no_invent\", label:\"No invented facts\"},\n        {k:\"no_cites\", label:\"No invented citations\"},\n        {k:\"traceable\", label:\"Trace to text\"},\n        {k:\"claims_evidence\", label:\"Separate claims\/evidence\"},\n        {k:\"structure\", label:\"Structured summary\"},\n        {k:\"map\", label:\"Concept map\"},\n        {k:\"study_guide\", label:\"Study guide\"}\n      ];\n      qs('#checksBank').innerHTML = checks.map(x=>`<span class=\"tag\">${esc(x.label)}<\/span>`).join(\"\");\n\n      function addCheck(k){\n        progress._checks = progress._checks || {};\n        progress._checks[k] = true;\n        saveProgress();\n      }\n\n      function renderProgress(){\n        const items = Object.values(progress).filter(p=>p && p.done);\n        const done = items.length;\n        const avg = done ? Math.round(items.reduce((s,p)=>s+(p.score||0),0)\/done) : 0;\n        qs('#pDone').textContent = String(done);\n        qs('#pScore').textContent = String(avg) + \"%\";\n        qs('#pChecks').textContent = String(Object.keys(progress._checks || {}).length);\n      }\n\n      \/* =========================\n         Instruction TTS map\n      ========================= *\/\n      const SAY = {\n        \"overview-instr\": \"Overview. Follow the workflow: read, extract claims and evidence, summarize, map concepts, then generate a study guide. Always verify outputs with the text.\",\n        \"conv-instr\": \"Conversation. Answer the coach prompts about gist, key points, claims and evidence, and where in the text each idea is stated.\",\n        \"reading-instr\": \"Reading. Read the text and answer multiple choice questions. Then check your score.\",\n        \"skills-instr\": \"Skills toolkit. Use the templates for structured summaries, claim evidence tables, concept maps, and study guides. Review the worked example.\",\n        \"prompts-instr\": \"Prompts. Copy a prompt, paste your text, and require paragraph or sentence locations for each key point. If something is not stated, it must be labeled not stated.\",\n        \"list-instr\": \"Listening. Play the dialogue with two speakers. Then answer the questions about safe AI-assisted note making.\",\n        \"lab-instr\": \"Reading lab. Paste a text, generate outputs, copy the safe AI prompt, and run a self-check for safety and completeness.\"\n      };\n      qsa('[data-say]').forEach(btn=>{\n        btn.addEventListener('click', async ()=>{\n          const k = btn.getAttribute('data-say');\n          if(SAY[k]) await speakAs(\"A\", SAY[k]);\n        });\n      });\n\n      \/* =========================\n         Read active page summary\n      ========================= *\/\n      qs('#speakActive').addEventListener('click', async ()=>{\n        const v = activeViewName();\n        const map = {\n          overview: \"Overview. You will practice structured summaries, claim and evidence extraction, concept mapping, and study guide generation with safety rules: no invented facts or citations.\",\n          conversation: \"Conversation page. Answer prompts about gist, key points, claims and evidence, and traceability to the text.\",\n          reading: \"Reading page. Read the text and answer multiple choice questions. Then check your score.\",\n          skills: \"Skills toolkit. Use templates for structured summaries, claim evidence tables, concept maps, and study guides. Review the worked example.\",\n          prompts: \"Prompts page. Copy and adapt prompts for summaries, claims and evidence, concept maps, and study guides with traceability requirements.\",\n          listening: \"Listening page. Play the two speaker dialogue and answer questions about safe note making.\",\n          lab: \"Reading lab. Paste a text and generate outputs, then copy a safe prompt for your AI tool.\",\n          progress: \"Progress page. View completed activities and safety checks used.\"\n        };\n        await speakAs(\"A\", map[v] || \"AI-assisted reading lesson.\");\n      });\n\n      \/* =========================\n         Voice transcript routing\n      ========================= *\/\n      function handleVoiceTranscript(t){\n        const text = norm(t);\n        if(!text) return;\n\n        const v = activeViewName();\n        if(v === \"lab\"){\n          const box = qs('#labText');\n          if(box){\n            box.value = (box.value ? (box.value + \" \") : \"\") + text;\n            speakAs(\"A\",\"Added to your lab text.\");\n          }\n          return;\n        }\n        if(v === \"conversation\"){\n          handleConversationInput(text);\n          return;\n        }\n        speakAs(\"A\",\"I heard: \" + text);\n      }\n\n      \/* =========================\n         Conversation coach (NEW)\n      ========================= *\/\n      const convChat = qs('#convChat');\n      const convText = qs('#convText');\n      const convSend = qs('#convSend');\n      const convReset = qs('#convReset');\n      const convHear  = qs('#convHear');\n\n      let convStep = 0;\n      let lastCoachQ = \"\";\n\n      const convSteps = [\n        {\n          bot: \"Step 1: Write a one-sentence gist of the reading. (Keep it faithful to the text.)\",\n          check: (a)=> a.split(\/\\s+\/).length >= 8 && a.length <= 180,\n          tips: \"Aim for 12\u201325 words. Do not add information.\"\n        },\n        {\n          bot: \"Step 2: List THREE key points as bullets (start each bullet with a verb).\",\n          check: (a)=> (a.match(\/^- \/gm)||[]).length >= 3,\n          tips: \"Use bullet format: - Verb \u2026 (three bullets).\"\n        },\n        {\n          bot: \"Step 3: Write ONE claim from the reading and ONE piece of evidence for it. Label them.\",\n          check: (a)=> \/claim:\/i.test(a) && \/evidence:\/i.test(a),\n          tips: \"Format: Claim: \u2026 Evidence: \u2026\"\n        },\n        {\n          bot: \"Step 4: Add traceability. Identify where the evidence appears (e.g., paragraph number).\",\n          check: (a)=> \/(para|paragraph)\\s*\\d\/i.test(a),\n          tips: \"Example: Evidence location: Paragraph 3.\"\n        },\n        {\n          bot: \"Step 5: Write one safety rule for using AI to take notes from texts.\",\n          check: (a)=> \/(do not|don't|no)\\s+(invent|add|hallucinat|make up)\/i.test(a),\n          tips: \"Example: Do not invent facts or citations; label 'Not stated'.\"\n        }\n      ];\n\n      function addMsg(who, text){\n        const div = document.createElement('div');\n        div.className = 'msg ' + (who==='You' ? 'user' : 'bot');\n        div.innerHTML = `<div class=\"who\">${esc(who)}<\/div><div class=\"bubble\">${esc(text)}<\/div>`;\n        convChat.appendChild(div);\n        convChat.scrollTop = convChat.scrollHeight;\n      }\n\n      async function coachAsk(){\n        const step = convSteps[convStep];\n        if(!step){\n          addMsg(\"Coach\",\"\u2705 Great. You used gist \u2192 key points \u2192 claim\/evidence \u2192 traceability \u2192 safety.\");\n          markDone(\"conversation\", 100);\n          await speakAs(\"A\",\"Great. You used gist, key points, claim and evidence, traceability, and safety.\");\n          return;\n        }\n        lastCoachQ = step.bot;\n        addMsg(\"Coach\", step.bot);\n        await speakAs(\"A\", step.bot);\n      }\n\n      async function handleConversationInput(text){\n        const a = norm(text);\n        if(!a) return;\n        addMsg(\"You\", a);\n\n        \/\/ Safety checks inferred\n        if(\/invent|make up|hallucinat\/i.test(a)) addCheck(\"no_invent\");\n        if(\/citation|author\/i.test(a)) addCheck(\"no_cites\");\n        if(\/para|paragraph\\s*\\d\/i.test(a)) addCheck(\"traceable\");\n        if(\/claim:\/i.test(a) && \/evidence:\/i.test(a)) addCheck(\"claims_evidence\");\n        if(\/gist\/i.test(lastCoachQ)) addCheck(\"structure\");\n\n        const step = convSteps[convStep];\n        const ok = step.check(a);\n        const msg = ok ? \"\u2705 Good. Next step.\" : \"\u26a0\ufe0f Try again. \" + step.tips;\n\n        addMsg(\"Coach\", msg);\n        await speakAs(\"A\", msg);\n\n        if(ok){ convStep++; setTimeout(coachAsk, 300); }\n      }\n\n      convSend.addEventListener('click', ()=>{ handleConversationInput(convText.value); convText.value=\"\"; });\n      convText.addEventListener('keydown', (e)=>{\n        if(e.key===\"Enter\"){ e.preventDefault(); handleConversationInput(convText.value); convText.value=\"\"; }\n      });\n      convHear.addEventListener('click', ()=> speakAs(\"A\", lastCoachQ || \"No question yet.\"));\n      convReset.addEventListener('click', ()=>{\n        convChat.innerHTML=\"\";\n        convStep=0;\n        addMsg(\"Coach\",\"Ready. Let\u2019s practice AI-assisted reading safely.\");\n        coachAsk();\n      });\n\n      \/\/ init conversation\n      addMsg(\"Coach\",\"Ready. Let\u2019s practice AI-assisted reading safely.\");\n      coachAsk();\n\n      \/* =========================\n         Reading TTS\n      ========================= *\/\n      qs('#readTextBtn').addEventListener('click', ()=>{\n        const parts = qsa('#readingText .reading-p').map(p=>p.textContent).join(\" \");\n        speakAs(\"A\", \"Reading. \" + parts);\n      });\n\n      \/* =========================\n         Quiz\n      ========================= *\/\n      const quiz = qs('#quiz');\n      const quizFb = qs('#quizFb');\n\n      const quizItems = [\n        { q:\"1) In the reading, AI should be treated mainly as\u2026\",\n          ans:\"An assistant that helps processing, not an authority\",\n          opts:[\n            \"An assistant that helps processing, not an authority\",\n            \"A source that adds new facts\",\n            \"A tool that automatically verifies all claims\",\n            \"A replacement for reading the text\"\n          ]\n        },\n        { q:\"2) A structured summary typically includes\u2026\",\n          ans:\"Gist + key points + implication\/takeaway\",\n          opts:[\n            \"Only the introduction of the text\",\n            \"Gist + key points + implication\/takeaway\",\n            \"All examples copied word-for-word\",\n            \"A new conclusion not in the text\"\n          ]\n        },\n        { q:\"3) A claim is best defined as\u2026\",\n          ans:\"What the author argues or concludes\",\n          opts:[\n            \"Any interesting sentence\",\n            \"What the author argues or concludes\",\n            \"A citation format\",\n            \"A topic word list\"\n          ]\n        },\n        { q:\"4) Evidence refers to\u2026\",\n          ans:\"Support such as examples, data, citations, or reasoning\",\n          opts:[\n            \"Support such as examples, data, citations, or reasoning\",\n            \"The reader\u2019s opinion\",\n            \"A paraphrase that sounds academic\",\n            \"Any transition word\"\n          ]\n        },\n        { q:\"5) The main purpose of a concept map is\u2026\",\n          ans:\"To show relationships among key ideas for clarity\",\n          opts:[\n            \"To decorate notes\",\n            \"To show relationships among key ideas for clarity\",\n            \"To replace reading entirely\",\n            \"To make the text longer\"\n          ]\n        },\n        { q:\"6) A safest practice for study guides is to\u2026\",\n          ans:\"Ask AI to cite where each claim appears in the text\",\n          opts:[\n            \"Ask AI to invent missing information\",\n            \"Ask AI to cite where each claim appears in the text\",\n            \"Remove all paragraph references\",\n            \"Use only generic statements\"\n          ]\n        }\n      ];\n\n      function renderQuiz(){\n        quiz.innerHTML = quizItems.map((it)=>{\n          const options = ['<option value=\"\">Choose\u2026<\/option>']\n            .concat(it.opts.map(o=>`<option value=\"${esc(o)}\">${esc(o)}<\/option>`))\n            .join(\"\");\n          return `\n            <div class=\"qitem\">\n              <div class=\"qtext\">${esc(it.q)}<\/div>\n              <select class=\"icte-select\" data-ans=\"${esc(it.ans)}\">${options}<\/select>\n            <\/div>\n          `;\n        }).join(\"\");\n      }\n      renderQuiz();\n\n      qs('#quizCheck').addEventListener('click', ()=>{\n        const sels = qsa('#quiz select');\n        let correct = 0;\n        sels.forEach(s=>{\n          const ok = s.value === s.getAttribute('data-ans');\n          s.style.borderColor = ok ? \"rgba(34,197,94,.6)\" : \"rgba(239,68,68,.6)\";\n          if(ok) correct++;\n        });\n        const pct = Math.round((correct \/ sels.length) * 100);\n        quizFb.className = \"feedback \" + (pct>=70 ? \"ok\":\"bad\");\n        quizFb.textContent = `Score: ${correct}\/${sels.length} (${pct}%).`;\n        if(pct >= 70){ addCheck(\"structure\"); addCheck(\"traceable\"); }\n        markDone(\"reading_quiz\", pct);\n      });\n\n      \/* =========================\n         Skills toolkit content\n      ========================= *\/\n      qs('#tplSummary').textContent =\n`STRUCTURED SUMMARY\n1) Gist (1 sentence):\n- ...\n\n2) Key points (3\u20137 bullets):\n- ...\n- ...\n- ...\n\n3) Implication \/ takeaway (1 sentence):\n- ...\n\n(Optional) Limitation \/ not stated:\n- ...`;\n\n      qs('#tplClaims').textContent =\n`CLAIM\u2013EVIDENCE NOTES\nClaim 1:\n- Claim (what is asserted):\n- Evidence (what supports it):\n- Location (paragraph\/sentence):\n\nClaim 2:\n- Claim:\n- Evidence:\n- Location:`;\n\n      qs('#tplMap').textContent =\n`CONCEPT MAP (TEXT FORMAT)\nNodes:\n- Concept A\n- Concept B\n- Concept C\n\nLinks (use labeled arrows):\n- Concept A \u2192 (leads to) \u2192 Concept B\n- Concept B \u2192 (includes) \u2192 Concept C\n- Concept A \u2192 (contrasts with) \u2192 Concept C`;\n\n      qs('#tplGuide').textContent =\n`STUDY GUIDE\nKey terms (simple definitions):\n- Term 1:\n- Term 2:\n\nQuick check (short-answer):\n1) ...\n2) ...\n\nHigher-order question (synthesis):\n- ...\n\nCommon confusions:\n- ...\n\nWhat the text does NOT say:\n- ...`;\n\n      qs('#workedExample').textContent =\n`WORKED EXAMPLE (from this lesson reading)\n\nGist:\nAI can support reading by helping learners produce structured notes, but the reader must verify outputs against the original text.\n\nKey points:\n- Structured summaries include gist, key points, and an implication.\n- Claims should be separated from evidence to avoid repeating opinions as facts.\n- Concept maps show relationships among ideas using labeled links.\n- Study guides should include terms, questions, and common confusions.\n- A safety practice is requiring traceable locations for each claim.\n\nImplication:\nAI-assisted notes are most useful when every point is traceable to the text; untraceable points should be removed.\n\nClaim\u2013Evidence example:\nClaim: \u201cAI should be treated as an assistant, not an authority.\u201d\nEvidence: The text says the reader must verify the output against the original text (para 1).`;\n\n      qs('#skillsSpeak').addEventListener('click', ()=>{\n        const txt =\n          \"Skills toolkit. Structured summary equals gist, key points, and implication. Claim evidence notes separate what is asserted from support and record locations. Concept maps list nodes and labeled links. Study guides include terms, questions, and common confusions, plus what the text does not say.\";\n        speakAs(\"A\", txt);\n      });\n\n      \/* =========================\n         Prompts content (NEW)\n      ========================= *\/\n      const p1 = qs('#p1'), p2 = qs('#p2'), p3 = qs('#p3'), p4 = qs('#p4'), pExample = qs('#pExample');\n\n      p1.textContent =\n`PROMPT 1 \u2014 STRUCTURED SUMMARY (TRACEABLE)\nYou are a reading assistant. Create a structured summary of the text below.\n\nRules:\n- Do NOT add facts not in the text.\n- For every key point, add (Para X).\n- If something is not stated, write \u201cNot stated\u201d.\n\nOutput format:\n1) Gist (1 sentence)\n2) Key points (3\u20135 bullets, each with Para #)\n3) Takeaway (1 sentence)\n\nTEXT:\n[PASTE TEXT]`;\n\n      p2.textContent =\n`PROMPT 2 \u2014 CLAIMS & EVIDENCE (TABLE)\nExtract 4\u20136 claims from the text and match each claim with evidence.\n\nRules:\n- Claim = what the author asserts\/concludes.\n- Evidence = examples\/data\/citations\/reasoning in the text.\n- Include exact location: (Para # or Sentence #).\n- If evidence is missing, label: \u201cNot stated\u201d.\n\nOutput table columns:\nClaim | Evidence | Location | Confidence (High\/Medium\/Low)\n\nTEXT:\n[PASTE TEXT]`;\n\n      p3.textContent =\n`PROMPT 3 \u2014 CONCEPT MAP (NODES + LABELED LINKS)\nBuild a concept map from the text.\n\nRules:\n- List 6\u201310 nodes (key concepts).\n- Provide 8\u201312 labeled links using:\n  \u201cleads to,\u201d \u201cincludes,\u201d \u201csupports,\u201d \u201ccontrasts with,\u201d \u201cresults in\u201d\n- Add (Para #) after each link to show where it comes from.\n\nOutput format:\nNodes:\n- ...\nLinks:\n- A \u2192 (leads to) \u2192 B (Para X)\n\nTEXT:\n[PASTE TEXT]`;\n\n      p4.textContent =\n`PROMPT 4 \u2014 STUDY GUIDE (TRACEABLE)\nCreate a study guide from the text.\n\nInclude:\n- Key terms (5\u20138) with brief definitions (Para #)\n- 5 short-answer questions (with answer key + Para #)\n- 1 synthesis question (no single answer)\n- 3 common confusions\/misreadings\n- \u201cWhat the text does NOT say\u201d (2 bullets)\n\nRules:\n- No invented examples, authors, or citations.\n- If unsure, label \u201cNot stated\u201d.\n\nTEXT:\n[PASTE TEXT]`;\n\n      pExample.textContent =\n`MINI EXAMPLE\n\nInput text (very short):\n\u201cAI can help students summarize texts, but learners must verify outputs against the original. Structured summaries include a gist, key points, and a takeaway.\u201d\n\nExpected output style:\nGist:\n- AI supports summarizing, but verification is required. (Para 1)\n\nKey points:\n- Treat AI as an assistant, not an authority. (Para 1)\n- Use a structured summary: gist, key points, takeaway. (Para 1)\n\nTakeaway:\n- Verification prevents inaccurate notes. (Para 1)`;\n\n      qs('#promptsSpeak').addEventListener('click', ()=>{\n        speakAs(\"A\",\"Prompts page. You have four copy and adapt prompts: structured summary, claims and evidence table, concept map with labeled links, and study guide with traceability. Always require paragraph locations and label not stated when the text does not support a point.\");\n      });\n\n      qs('#copyPrompts').addEventListener('click', ()=>{\n        const all =\n`PROMPT 1\n${p1.textContent}\n\nPROMPT 2\n${p2.textContent}\n\nPROMPT 3\n${p3.textContent}\n\nPROMPT 4\n${p4.textContent}\n\nMINI EXAMPLE\n${pExample.textContent}`;\n        navigator.clipboard.writeText(all).then(()=> speakAs(\"A\",\"Copied prompts.\")).catch(()=> alert(\"Clipboard blocked. Copy manually.\"));\n      });\n\n      \/* =========================\n         Listening\n      ========================= *\/\n      const listenFb = qs('#listenFb');\n      const listenQ = qs('#listenQ');\n\n      const dialogue = [\n        {role:\"A\", text:\"When students use AI to take notes, what is the biggest risk?\"},\n        {role:\"B\", text:\"Hallucination. The notes may include claims that do not appear in the text.\"},\n        {role:\"A\", text:\"How do we prevent that?\"},\n        {role:\"B\", text:\"Require traceability. For every claim, the student must point to a sentence or paragraph in the text.\"},\n        {role:\"A\", text:\"What about summaries?\"},\n        {role:\"B\", text:\"Use a structured format: gist, key points, and a takeaway. That keeps the summary faithful and useful.\"},\n        {role:\"A\", text:\"And concept maps?\"},\n        {role:\"B\", text:\"Maps should show relationships with labeled links, not just a list of words.\"},\n        {role:\"A\", text:\"So AI is a tool for processing, and the student verifies.\"},\n        {role:\"B\", text:\"Exactly. Verification keeps reading academic and accurate.\"}\n      ];\n\n      const listenItems = [\n        {q:\"1) What is the biggest risk mentioned?\", ans:\"Notes may include claims not in the text\"},\n        {q:\"2) The main prevention strategy is\u2026\", ans:\"Require traceability to the original text\"},\n        {q:\"3) A structured summary includes\u2026\", ans:\"Gist, key points, and a takeaway\"},\n        {q:\"4) A good concept map should\u2026\", ans:\"Show relationships using labeled links\"}\n      ];\n\n      function renderListenQ(){\n        const optsMap = {\n          \"Notes may include claims not in the text\":[\n            \"Notes may include claims not in the text\",\n            \"The text becomes longer\",\n            \"Students write too many headings\"\n          ],\n          \"Require traceability to the original text\":[\n            \"Require traceability to the original text\",\n            \"Use more difficult vocabulary\",\n            \"Remove paragraph references\"\n          ],\n          \"Gist, key points, and a takeaway\":[\n            \"Gist, key points, and a takeaway\",\n            \"Only examples and quotations\",\n            \"Only the conclusion\"\n          ],\n          \"Show relationships using labeled links\":[\n            \"Show relationships using labeled links\",\n            \"Decorate notes with images\",\n            \"Replace reading with a word list\"\n          ]\n        };\n\n        listenQ.innerHTML = listenItems.map((it)=>{\n          const options = ['<option value=\"\">Choose\u2026<\/option>']\n            .concat((optsMap[it.ans]||[it.ans]).map(o=>`<option value=\"${esc(o)}\">${esc(o)}<\/option>`)).join(\"\");\n          return `\n            <div class=\"qitem\">\n              <div class=\"qtext\">${esc(it.q)}<\/div>\n              <select class=\"icte-select\" data-ans=\"${esc(it.ans)}\">${options}<\/select>\n            <\/div>\n          `;\n        }).join(\"\");\n      }\n      renderListenQ();\n\n      qs('#listenPlay').addEventListener('click', async ()=>{\n        if(googleVoicesEN.length >= 2 && voiceA === voiceB){\n          voiceB = googleVoicesEN.find(v => v !== voiceA) || voiceB;\n          voiceBSelect.value = String(googleVoicesEN.indexOf(voiceB));\n        }\n        await speakDialogue(dialogue);\n      });\n      qs('#listenStop').addEventListener('click', stopSpeak);\n\n      qs('#listenCheck').addEventListener('click', ()=>{\n        const sels = qsa('#listenQ select');\n        let correct = 0;\n        sels.forEach(s=>{\n          const ok = s.value === s.getAttribute('data-ans');\n          s.style.borderColor = ok ? \"rgba(34,197,94,.6)\" : \"rgba(239,68,68,.6)\";\n          if(ok) correct++;\n        });\n        const pct = Math.round((correct \/ sels.length) * 100);\n        listenFb.className = \"feedback \" + (pct>=70 ? \"ok\":\"bad\");\n        listenFb.textContent = `Score: ${correct}\/${sels.length} (${pct}%).`;\n        if(pct >= 70){ addCheck(\"no_invent\"); addCheck(\"traceable\"); }\n        markDone(\"listening\", pct);\n      });\n\n      \/* =========================\n         Lab constraints + generation\n         (same as earlier version, kept)\n      ========================= *\/\n      const labConstraintItems = [\n        {id:\"c_noinvent\", label:\"Do not add facts not in the text\", key:\"no_invent\", on:true},\n        {id:\"c_nocite\", label:\"Do not invent citations or authors\", key:\"no_cites\", on:true},\n        {id:\"c_trace\", label:\"Make every claim traceable to the text\", key:\"traceable\", on:true},\n        {id:\"c_claims\", label:\"Separate claims from evidence\", key:\"claims_evidence\", on:true},\n        {id:\"c_map\", label:\"Include a concept map with labeled links\", key:\"map\", on:false},\n        {id:\"c_guide\", label:\"Generate a study guide (terms + questions)\", key:\"study_guide\", on:false}\n      ];\n      const labConstraintsBox = qs('#labConstraints');\n      labConstraintsBox.innerHTML = labConstraintItems.map(x=>`\n        <label class=\"opt\">\n          <input type=\"checkbox\" id=\"${esc(x.id)}\" ${x.on ? \"checked\":\"\"} \/>\n          <span><b>${esc(x.label)}<\/b><\/span>\n        <\/label>\n      `).join(\"\");\n\n      function selectedConstraintsText(){\n        const selected = labConstraintItems.filter(x => qs(\"#\"+x.id).checked);\n        selected.forEach(x => addCheck(x.key));\n        const lines = selected.map(x => \"- \" + x.label);\n        return lines.length ? lines.join(\"\\n\") : \"- (No constraints selected)\";\n      }\n\n      const labText = qs('#labText');\n      const sumLen = qs('#sumLen');\n      const guideLevel = qs('#guideLevel');\n\n      const outSummary = qs('#outSummary');\n      const outClaims  = qs('#outClaims');\n      const outMap     = qs('#outMap');\n      const outGuide   = qs('#outGuide');\n      const outPrompt  = qs('#outPrompt');\n      const labFb      = qs('#labFb');\n\n      function pickKeySentences(sentences, n){\n        if(sentences.length <= n) return sentences;\n        const signals = \/(however|therefore|because|suggest|argue|conclude|essential|risk|strategy|goal|should|must|results|evidence|claim|concept|map|guide)\/i;\n        const scored = sentences.map(s=>{\n          const len = s.length;\n          const sig = signals.test(s) ? 1 : 0;\n          const mid = (len >= 70 && len <= 180) ? 1 : 0;\n          return {s, score: sig*2 + mid*1 + Math.min(1, len\/250)};\n        }).sort((a,b)=>b.score-a.score);\n        return scored.slice(0,n).map(x=>x.s);\n      }\n\n      function buildStructuredSummary(text){\n        const sentences = splitSentences(text);\n        if(!sentences.length) return \"\";\n        const gist = sentences[0];\n        let pointsN = 5;\n        if(sumLen.value === \"short\") pointsN = 3;\n        if(sumLen.value === \"long\") pointsN = 7;\n\n        const key = pickKeySentences(sentences.slice(1), pointsN);\n        const implication =\n          \"Implication: Notes are strongest when every point can be verified in the text; untraceable points should be removed.\";\n        const limitation =\n          \"Limitation: If evidence is not provided, do not add it\u2014mark it as \u201cNot stated.\u201d\";\n\n        let out =\n`Gist (1 sentence):\n- ${gist}\n\nKey points (${key.length}):\n${key.map(s=>\"- \" + s).join(\"\\n\")}\n\n${implication}`;\n\n        if(sumLen.value === \"long\") out += \"\\n\\n\" + limitation;\n        return out;\n      }\n\n      function extractClaimsEvidence(text){\n        const sentences = splitSentences(text);\n        if(!sentences.length) return \"\";\n        const claimSignals = \/(should|must|can|cannot|risk|goal|essential|argue|conclude|suggest|recommend|safest|practice)\/i;\n        const evidSignals  = \/(for example|such as|data|citation|reasoning|because|evidence|support)\/i;\n\n        const claims = [];\n        for(let i=0;i<sentences.length;i++){\n          const s = sentences[i];\n          if(claimSignals.test(s)){\n            let ev = \"Not stated in the text (no explicit evidence sentence found).\";\n            let loc = `Sentence ${i+1}`;\n            for(let j=i+1;j<Math.min(i+3, sentences.length);j++){\n              if(evidSignals.test(sentences[j])){\n                ev = sentences[j];\n                loc = `Claim: Sentence ${i+1}; Evidence: Sentence ${j+1}`;\n                break;\n              }\n            }\n            if(ev.startsWith(\"Not stated\") &#038;&#038; sentences[i+1]){\n              ev = sentences[i+1];\n              loc = `Claim: Sentence ${i+1}; Possible support: Sentence ${i+2}`;\n            }\n            claims.push({claim:s, evidence:ev, loc});\n          }\n        }\n\n        const top = claims.slice(0,6);\n        if(!top.length){\n          return \"No clear claim signals found. Tip: Look for sentences with should\/must\/argue\/conclude\/recommend.\";\n        }\n        addCheck(\"claims_evidence\");\n        return top.map((c,idx)=>(\n`Claim ${idx+1}:\n- Claim: ${c.claim}\n- Evidence: ${c.evidence}\n- Location: ${c.loc}`\n        )).join(\"\\n\\n\");\n      }\n\n      function buildConceptMap(text){\n        const sentences = splitSentences(text);\n        if(!sentences.length) return \"\";\n        const stop = new Set((\"the a an and or but so because however therefore of to in on for with as is are was were be been being this that these those it they we you i can must should may might not\").split(\" \"));\n        const words = (text||\"\")\n          .toLowerCase()\n          .replace(\/[^a-z0-9\\\\s-]\/g,\" \")\n          .split(\/\\\\s+\/)\n          .filter(w=>w.length>=4 && !stop.has(w));\n\n        const freq = {};\n        words.forEach(w=>freq[w]=(freq[w]||0)+1);\n        const nodes = Object.entries(freq).sort((a,b)=>b[1]-a[1]).slice(0,8).map(x=>x[0]);\n\n        const has = (w)=> (text||\"\").toLowerCase().includes(w);\n        const links = [];\n        if(has(\"summary\") || has(\"summar\")) links.push(\"structured summary \u2192 (supports) \u2192 note-making\");\n        if(has(\"claim\") && has(\"evidence\")) links.push(\"claims \u2192 (require) \u2192 evidence\");\n        if(has(\"concept\") && has(\"map\")) links.push(\"concept map \u2192 (shows) \u2192 relationships\");\n        if(has(\"study\") && has(\"guide\")) links.push(\"study guide \u2192 (includes) \u2192 questions\");\n        links.push(\"verification \u2192 (prevents) \u2192 hallucination\");\n\n        addCheck(\"map\");\n        return `Nodes:\\n- ${nodes.join(\"\\n- \")}\\n\\nLinks:\\n- ${links.join(\"\\n- \")}`;\n      }\n\n      function buildStudyGuide(text){\n        const lvl = guideLevel.value;\n        const sentences = splitSentences(text);\n        if(!sentences.length) return \"\";\n        const keyTerms = [\"structured summary\",\"claim\",\"evidence\",\"concept map\",\"study guide\",\"traceability\",\"verification\",\"hallucination\"]\n          .filter(t => (text||\"\").toLowerCase().includes(t.split(\" \")[0]));\n        const terms = keyTerms.length ? keyTerms : [\"summary\",\"claim\",\"evidence\",\"concept map\",\"verification\"];\n\n        const defs = terms.map(t=>{\n          if(lvl===\"b1\"){\n            return `- ${t}: explain in simple words (check the text).`;\n          }\n          return `- ${t}: define precisely based on the text (no added info).`;\n        }).join(\"\\n\");\n\n        const sa = [\n          \"1) What is the difference between a claim and evidence?\",\n          \"2) What are the parts of a structured summary?\",\n          \"3) Why is traceability important for AI-assisted notes?\"\n        ];\n\n        const higher = \"Higher-order: How can concept mapping and claim\u2013evidence extraction work together to improve critical reading? Use examples from the text.\";\n\n        const conf = [\n          \"- Confusion: treating opinions as facts \u2192 fix by matching claims to evidence.\",\n          \"- Confusion: adding new details \u2192 fix by verifying every point in the text.\"\n        ];\n\n        addCheck(\"study_guide\");\n        return `Key terms:\\n${defs}\\n\\nShort-answer:\\n${sa.map(x=>\"- \"+x).join(\"\\n\")}\\n\\n${higher}\\n\\nCommon confusions:\\n${conf.map(x=>\"- \"+x).join(\"\\n\")}\\n\\nWhat the text does NOT say:\\n- Add \u201cNot stated\u201d for any missing evidence rather than guessing.`;\n      }\n\n      function buildSafePrompt(text){\n        const constraints = selectedConstraintsText();\n        return `ROLE: You are a reading assistant.\n\nTASK:\nConvert the text into study notes: (1) structured summary, (2) claims with evidence, (3) concept map, (4) study guide.\n\nCONSTRAINTS (must follow):\n${constraints}\n\nTRACEABILITY REQUIREMENT:\nFor each claim or key point, include its location (paragraph\/sentence). If you cannot locate support, write \u201cNot stated\u201d and remove it from the final notes.\n\nTEXT:\n${text}`;\n      }\n\n      function labGenerate(){\n        const text = norm(labText.value);\n        if(text.length < 80){\n          labFb.className = \"feedback bad\";\n          labFb.textContent = \"\u26a0\ufe0f Please paste at least ~80 characters of text for meaningful outputs.\";\n          return;\n        }\n\n        outSummary.textContent = buildStructuredSummary(text);\n        outClaims.textContent  = extractClaimsEvidence(text);\n        outMap.textContent     = buildConceptMap(text);\n        outGuide.textContent   = buildStudyGuide(text);\n        outPrompt.textContent  = buildSafePrompt(text);\n\n        labFb.className = \"feedback ok\";\n        labFb.textContent = \"\u2705 Generated. Next: copy the safe prompt into your AI tool for refinement (without adding new content).\";\n\n        const score =\n          (outSummary.textContent ? 25 : 0) +\n          (outClaims.textContent &#038;&#038; !outClaims.textContent.startsWith(\"No clear\") ? 25 : 10) +\n          (outMap.textContent ? 25 : 0) +\n          (outGuide.textContent ? 25 : 0);\n\n        markDone(\"lab\", clamp(score,0,100));\n      }\n\n      function labCopyAll(){\n        const pack =\n`STRUCTURED SUMMARY\n${outSummary.textContent}\n\nCLAIM\u2013EVIDENCE\n${outClaims.textContent}\n\nCONCEPT MAP\n${outMap.textContent}\n\nSTUDY GUIDE\n${outGuide.textContent}\n\nSAFE AI PROMPT\n${outPrompt.textContent}`;\n        if(!pack.trim()){\n          labFb.className = \"feedback bad\";\n          labFb.textContent = \"\u26a0\ufe0f Generate outputs first.\";\n          return;\n        }\n        navigator.clipboard.writeText(pack).then(()=>{\n          labFb.className = \"feedback ok\";\n          labFb.textContent = \"\u2705 Copied all outputs to clipboard.\";\n        }).catch(()=>{\n          labFb.className = \"feedback bad\";\n          labFb.textContent = \"\u26a0\ufe0f Clipboard blocked. Copy manually from the boxes.\";\n        });\n      }\n\n      function labSelfCheck(){\n        const text = norm(labText.value);\n        const hasText = text.length >= 120;\n        const required = [\"c_noinvent\",\"c_nocite\",\"c_trace\",\"c_claims\"].every(id => qs(\"#\"+id).checked);\n        const outputsOk =\n          outSummary.textContent.length > 40 &&\n          outClaims.textContent.length > 40 &&\n          outGuide.textContent.length > 40;\n\n        const pct = Math.round(((hasText?1:0) + (required?1:0) + (outputsOk?1:0)) \/ 3 * 100);\n\n        labFb.className = \"feedback \" + (pct>=70 ? \"ok\":\"bad\");\n        labFb.textContent =\n          `Self-check: ${pct}%\\n` +\n          `- Text length adequate: ${hasText ? \"Yes\" : \"No\"}\\n` +\n          `- Core safeguards selected: ${required ? \"Yes\" : \"No\"}\\n` +\n          `- Outputs generated: ${outputsOk ? \"Yes\" : \"No\"}`;\n\n        markDone(\"lab_selfcheck\", pct);\n      }\n\n      qs('#labGenerate').addEventListener('click', labGenerate);\n      qs('#labCopyAll').addEventListener('click', labCopyAll);\n      qs('#labScore').addEventListener('click', labSelfCheck);\n\n      function updatePromptLive(){\n        const text = norm(labText.value) || \"[PASTE YOUR TEXT HERE]\";\n        outPrompt.textContent = buildSafePrompt(text);\n      }\n      labText.addEventListener('input', updatePromptLive);\n      sumLen.addEventListener('change', ()=>{ if(norm(labText.value)) outSummary.textContent = buildStructuredSummary(norm(labText.value)); });\n      guideLevel.addEventListener('change', ()=>{ if(norm(labText.value)) outGuide.textContent = buildStudyGuide(norm(labText.value)); });\n      qsa('#labConstraints input[type=\"checkbox\"]').forEach(cb => cb.addEventListener('change', updatePromptLive));\n\n      \/\/ Init\n      updatePromptLive();\n      renderProgress();\n\n    })();\n  <\/script>\n\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Overview Conversation Reading Skills Toolkit Prompts Listening Reading Lab Progress AI-assisted Reading: Summarizing &#038; Note-making Practice structured summaries, build a<\/p>\n","protected":false},"author":1,"featured_media":750,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"colormag_page_layout":"default_layout","footnotes":""},"categories":[53,45],"tags":[],"class_list":["post-751","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ai-basics","category-ai-for-teachers"],"_links":{"self":[{"href":"https:\/\/i-cte.org\/robot\/wp-json\/wp\/v2\/posts\/751","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/i-cte.org\/robot\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/i-cte.org\/robot\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/i-cte.org\/robot\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/i-cte.org\/robot\/wp-json\/wp\/v2\/comments?post=751"}],"version-history":[{"count":2,"href":"https:\/\/i-cte.org\/robot\/wp-json\/wp\/v2\/posts\/751\/revisions"}],"predecessor-version":[{"id":753,"href":"https:\/\/i-cte.org\/robot\/wp-json\/wp\/v2\/posts\/751\/revisions\/753"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/i-cte.org\/robot\/wp-json\/wp\/v2\/media\/750"}],"wp:attachment":[{"href":"https:\/\/i-cte.org\/robot\/wp-json\/wp\/v2\/media?parent=751"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/i-cte.org\/robot\/wp-json\/wp\/v2\/categories?post=751"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/i-cte.org\/robot\/wp-json\/wp\/v2\/tags?post=751"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}