{"id":767,"date":"2026-03-04T15:32:06","date_gmt":"2026-03-04T15:32:06","guid":{"rendered":"https:\/\/i-cte.org\/robot\/?p=767"},"modified":"2026-03-04T15:46:31","modified_gmt":"2026-03-04T15:46:31","slug":"reference-checking-apa-7th","status":"publish","type":"post","link":"https:\/\/i-cte.org\/robot\/reference-checking-apa-7th\/","title":{"rendered":"Reference Checking &amp; APA 7th"},"content":{"rendered":"\n<!-- \u2705 ICTE Teacher Micro-Lesson \u2014 Reference Checking & APA 7th Workflows\n     WP-safe single block, Multi-speaker Google Voices (2 voices)\n     Includes: Conversation + Reading + Quiz + Toolkit + Prompts + Listening + Reference Audit Lab + Problem-solving\n     Focus: verify in-text citations vs reference list, DOIs\/URLs, missing metadata, consistency checks (APA 7).\n-->\n<div id=\"icte-apa7\">\n\n  <!-- \u2705 TOP MENU -->\n  <nav class=\"icte-menu\" aria-label=\"APA 7 reference checking 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=\"toolkit\">APA Toolkit<\/a>\n    <a href=\"#\" data-view=\"prompts\">Prompts<\/a>\n    <a href=\"#\" data-view=\"listening\">Listening<\/a>\n    <a href=\"#\" data-view=\"lab\">Reference Audit Lab<\/a>\n    <a href=\"#\" data-view=\"problem\">Problem-solving<\/a>\n    <a href=\"#\" data-view=\"progress\">Progress<\/a>\n  <\/nav>\n\n  <section class=\"icte-shell\" aria-label=\"ICTE APA reference checking 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\/Screenshot-2026-03-04-at-22.30.46.png\"\n            alt=\"Reference checking and APA 7 workflows banner\"\n            loading=\"lazy\"\n          \/>\n          <div class=\"hero-title\">\n            <h2>Reference Checking &#038; APA 7th<\/h2>\n            <p class=\"muted\">\n              Use AI safely to verify <b>in-text citations vs. reference list<\/b>, detect <b>missing items<\/b>,\n              find <b>DOIs\/URLs<\/b> and <b>missing metadata<\/b>, and improve <b>APA 7<\/b> consistency.\n              Includes a <b>Reference Audit Lab<\/b> and an end-of-lesson <b>problem-solving<\/b> task.\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) Outcomes<\/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\">By the end, you can\u2026<\/div>\n              <ul class=\"ul\">\n                <li>Check <b>every in-text citation<\/b> has a matching reference (and vice versa).<\/li>\n                <li>Spot common APA 7 issues: <b>author\/year mismatches<\/b>, <b>missing DOI\/URL<\/b>, <b>missing publisher<\/b>, <b>missing journal details<\/b>.<\/li>\n                <li>Use AI prompts for <b>metadata completion<\/b> (then verify in Google Scholar \/ publisher pages).<\/li>\n                <li>Run a quick <b>consistency audit<\/b> before submission.<\/li>\n              <\/ul>\n            <\/div>\n\n            <div class=\"qitem\">\n              <div class=\"qtext\">Safety rules (important)<\/div>\n              <ul class=\"ul\">\n                <li>AI can suggest fixes, but <b>you must verify<\/b> DOIs and bibliographic details.<\/li>\n                <li>Do not allow AI to invent references. Anything \u201cfound\u201d must be confirmed.<\/li>\n                <li>For final accuracy, cross-check with <b>Google Scholar<\/b> and the <b>publisher page<\/b>.<\/li>\n                <li>Keep a revision log: what changed, why, and the source you verified.<\/li>\n              <\/ul>\n            <\/div>\n          <\/div>\n\n          <div class=\"note\">\n            <b>Workflow:<\/b> Extract in-text citations \u2192 normalize (author\/year) \u2192 match to reference list \u2192 flag missing\/unused \u2192\n            check DOI\/URL + missing metadata \u2192 fix formatting \u2192 final scan for consistency.\n          <\/div>\n        <\/div>\n      <\/section>\n\n      <!-- ===================== -->\n      <!-- \u2705 CONVERSATION -->\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 (APA 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            Build a safe AI workflow for APA 7 reference checking: scope, constraints, what to preserve, and verification steps.\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> Your prompts should explicitly forbid invention: \u201cIf you cannot verify a DOI, mark it unknown.\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 APA 7 reference checking\">\n            <div class=\"reading-title\">Reading: Using AI for reference checking (APA 7) without losing accuracy<\/div>\n\n            <div class=\"reading-p\">\n              <b>1<\/b> A common reason manuscripts are returned is inconsistent referencing. The fastest reliability improvement is to verify that\n              every <b>in-text citation<\/b> matches an item in the <b>reference list<\/b>, including author spelling and year. This also means the reverse:\n              every reference should be cited in the text unless it is intentionally included (e.g., a background bibliography, which is uncommon).\n            <\/div>\n\n            <div class=\"reading-p\">\n              <b>2<\/b> AI can help by extracting citation keys (author + year) and highlighting mismatches. However, AI should not be used to invent\n              missing references. When metadata is incomplete, a safe approach is to ask AI to list what is missing (DOI, journal issue, page range),\n              and then verify details using Google Scholar or the publisher\u2019s official page.\n            <\/div>\n\n            <div class=\"reading-p\">\n              <b>3<\/b> APA 7 consistency checks include: correct author order, year format (including a\/b for same-year works), correct title capitalization,\n              journal volume\/issue, page range, and DOI format. For web sources, include a stable URL. For DOIs, APA prefers the URL form\n              (https:\/\/doi.org\/&#8230;). A manuscript audit should prioritize correctness over \u201cpretty formatting.\u201d\n            <\/div>\n\n            <div class=\"reading-p\">\n              <b>4<\/b> A practical workflow is: (a) run a mismatch audit, (b) fix missing\/unused items, (c) complete metadata, (d) standardize formatting,\n              and (e) do a final scan. Document changes so you can explain your process if reviewers raise concerns.\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 TOOLKIT -->\n      <!-- ===================== -->\n      <section class=\"view\" data-view=\"toolkit\" aria-label=\"APA toolkit\">\n        <div class=\"card\">\n          <div class=\"card-h\">\n            <h3>4) APA 7 Toolkit (What to check)<\/h3>\n            <div class=\"card-actions\">\n              <button class=\"btn mini\" type=\"button\" data-say=\"toolkit-instr\">\ud83d\udd0a Read instructions<\/button>\n              <button class=\"btn mini ghost\" type=\"button\" id=\"toolkitSpeak\">\ud83d\udd0a Read toolkit<\/button>\n            <\/div>\n          <\/div>\n\n          <div class=\"grid2\">\n            <div class=\"qitem\">\n              <div class=\"qtext\">Mismatch audit checklist<\/div>\n              <pre class=\"pre\" id=\"tkMismatch\"><\/pre>\n            <\/div>\n            <div class=\"qitem\">\n              <div class=\"qtext\">Metadata checklist (what\u2019s often missing)<\/div>\n              <pre class=\"pre\" id=\"tkMeta\"><\/pre>\n            <\/div>\n          <\/div>\n\n          <div class=\"grid2\" style=\"margin-top:12px;\">\n            <div class=\"qitem\">\n              <div class=\"qtext\">APA 7 quick rules (high-frequency)<\/div>\n              <pre class=\"pre\" id=\"tkRules\"><\/pre>\n            <\/div>\n            <div class=\"qitem\">\n              <div class=\"qtext\">DOI\/URL checks<\/div>\n              <pre class=\"pre\" id=\"tkDoi\"><\/pre>\n            <\/div>\n          <\/div>\n\n          <div class=\"qitem\" style=\"margin-top:12px;\">\n            <div class=\"qtext\">Worked mini example (common fixes)<\/div>\n            <pre class=\"pre\" id=\"tkExample\"><\/pre>\n          <\/div>\n        <\/div>\n      <\/section>\n\n      <!-- ===================== -->\n      <!-- \u2705 PROMPTS -->\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            Use AI to <b>identify<\/b> problems and propose a plan. Then verify each DOI\/metadata in <b>Google Scholar<\/b> or publisher pages.\n          <\/div>\n\n          <div class=\"grid2\">\n            <div class=\"qitem\">\n              <div class=\"qtext\">Prompt 1 \u2014 In-text vs reference list audit<\/div>\n              <pre class=\"pre\" id=\"p1\"><\/pre>\n            <\/div>\n            <div class=\"qitem\">\n              <div class=\"qtext\">Prompt 2 \u2014 Missing metadata checklist + fill plan<\/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 DOI\/URL verification workflow<\/div>\n              <pre class=\"pre\" id=\"p3\"><\/pre>\n            <\/div>\n            <div class=\"qitem\">\n              <div class=\"qtext\">Prompt 4 \u2014 APA 7 formatting standardization<\/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 (expected output structure)<\/div>\n            <pre class=\"pre\" id=\"pExample\"><\/pre>\n          <\/div>\n        <\/div>\n      <\/section>\n\n      <!-- ===================== -->\n      <!-- \u2705 LISTENING -->\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 \u201cAI checks, you verify\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\">Listen to two editors discussing APA 7 consistency and DOI verification. Then answer the questions.<\/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 LAB -->\n      <!-- ===================== -->\n      <section class=\"view\" data-view=\"lab\" aria-label=\"Reference audit lab\">\n        <div class=\"card\">\n          <div class=\"card-h\">\n            <h3>7) Reference Audit Lab (Paste \u2192 detect mismatches)<\/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=\"labRun\">Run audit<\/button>\n              <button class=\"btn mini ghost\" type=\"button\" id=\"labCopy\">Copy report<\/button>\n              <button class=\"btn mini ghost\" type=\"button\" id=\"labReset\">Reset<\/button>\n            <\/div>\n          <\/div>\n\n          <div class=\"note\">\n            Paste (A) your manuscript text (or a section) and (B) your reference list. This tool will:\n            <b>extract (Author, Year)<\/b> from in-text citations, match to references, flag missing\/unused items,\n            and check for <b>DOI\/URL presence<\/b> and some common missing metadata.\n          <\/div>\n\n          <div class=\"grid2\">\n            <div class=\"qitem\">\n              <div class=\"qtext\">A) Manuscript text (in-text citations)<\/div>\n              <textarea class=\"textarea\" id=\"manuscript\" rows=\"12\" placeholder=\"Paste your manuscript text here...\"><\/textarea>\n              <div class=\"icte-small muted\" style=\"margin-top:6px;\">\n                Tip: Include the section where most citations appear (literature review).\n              <\/div>\n            <\/div>\n\n            <div class=\"qitem\">\n              <div class=\"qtext\">B) Reference list (APA 7)<\/div>\n              <textarea class=\"textarea\" id=\"reflist\" rows=\"12\" placeholder=\"Paste your reference list here (one entry per paragraph if possible)...\"><\/textarea>\n              <div class=\"icte-small muted\" style=\"margin-top:6px;\">\n                Tip: Separate entries by blank lines to improve detection.\n              <\/div>\n            <\/div>\n          <\/div>\n\n          <div class=\"qitem\" style=\"margin-top:12px;\">\n            <div class=\"qtext\">Audit report<\/div>\n            <pre class=\"pre\" id=\"report\"><\/pre>\n          <\/div>\n\n          <div class=\"qitem\" style=\"margin-top:12px;\">\n            <div class=\"qtext\">Safe AI prompt (to fix issues after you audit)<\/div>\n            <pre class=\"pre\" id=\"aiPrompt\"><\/pre>\n          <\/div>\n\n          <div class=\"feedback\" id=\"labFb\" aria-live=\"polite\"><\/div>\n        <\/div>\n      <\/section>\n\n      <!-- ===================== -->\n      <!-- \u2705 PROBLEM-SOLVING -->\n      <!-- ===================== -->\n      <section class=\"view\" data-view=\"problem\" aria-label=\"Problem solving task\">\n        <div class=\"card\">\n          <div class=\"card-h\">\n            <h3>8) Problem-solving<\/h3>\n            <div class=\"card-actions\">\n              <button class=\"btn mini\" type=\"button\" data-say=\"problem-instr\">\ud83d\udd0a Read instructions<\/button>\n              <button class=\"btn mini ghost\" type=\"button\" id=\"psCheck\">Check my solution<\/button>\n              <button class=\"btn mini ghost\" type=\"button\" id=\"psReset\">Reset<\/button>\n            <\/div>\n          <\/div>\n\n          <div class=\"note\">\n            <b>Scenario:<\/b> You are submitting a paper. The editor reports:\n            <ul class=\"ul\">\n              <li>Several in-text citations have <b>no matching references<\/b>.<\/li>\n              <li>Several references are <b>never cited<\/b> in the manuscript.<\/li>\n              <li>Multiple references are missing <b>DOI\/URL<\/b> or key fields (volume\/issue\/pages).<\/li>\n              <li>Some author\/year pairs differ (e.g., <b>2020<\/b> in text but <b>2019<\/b> in list).<\/li>\n            <\/ul>\n            Your task: write a <b>fix plan<\/b>, propose <b>3 verification steps<\/b> (Google Scholar \/ publisher), and rewrite <b>one corrected reference<\/b> in APA 7 format (include DOI\/URL if available).\n          <\/div>\n\n          <div class=\"grid2\">\n            <div class=\"qitem\">\n              <div class=\"qtext\">A) Fix plan (5\u20138 bullets)<\/div>\n              <textarea class=\"textarea\" id=\"psPlan\" rows=\"9\" placeholder=\"- Run mismatch audit...&#10;- Fix missing references...&#10;- Remove uncited references (if not needed)...&#10;- Verify DOI in Google Scholar...\"><\/textarea>\n            <\/div>\n            <div class=\"qitem\">\n              <div class=\"qtext\">B) Verification steps (3 bullets)<\/div>\n              <textarea class=\"textarea\" id=\"psVerify\" rows=\"9\" placeholder=\"- Search exact title in Google Scholar...&#10;- Open publisher page to confirm DOI...&#10;- Cross-check author order and year...\"><\/textarea>\n            <\/div>\n          <\/div>\n\n          <div class=\"qitem\" style=\"margin-top:12px;\">\n            <div class=\"qtext\">C) One corrected APA 7 reference (include DOI\/URL if known)<\/div>\n            <textarea class=\"textarea\" id=\"psRef\" rows=\"5\" placeholder=\"Author, A. A., &#038; Author, B. B. (Year). Title of article. Title of Journal, volume(issue), pages. https:\/\/doi.org\/...\"><\/textarea>\n          <\/div>\n\n          <div class=\"feedback\" id=\"psFb\" 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\">Checklist items used<\/div>\n            <\/div>\n          <\/div>\n\n          <div class=\"note\">Saved locally in your browser (local storage).<\/div>\n\n          <h4 class=\"h4\">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-apa7 *{ box-sizing:border-box; }\n    #icte-apa7{\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-apa7 .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-apa7 .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-apa7 .icte-menu a:hover{ opacity:1; background:rgba(255,255,255,.14); }\n    #icte-apa7 .icte-menu a.is-current{ background:#fff; color:var(--dark); opacity:1; }\n\n    #icte-apa7 .icte-shell{ max-width:1100px; margin:0 auto; }\n    #icte-apa7 .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-apa7 .icte-hero{ grid-template-columns:1fr; } }\n    #icte-apa7 h2{ margin:0 0 6px 0; font-size:22px; }\n    #icte-apa7 .muted{ color:var(--muted); }\n\n    #icte-apa7 .hero-top{ display:flex; gap:12px; align-items:center; }\n    #icte-apa7 .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-apa7 .hero-top{ flex-direction:column; align-items:flex-start; }\n      #icte-apa7 .hero-img{ width:100%; max-width:520px; }\n    }\n\n    #icte-apa7 .icte-hero__controls{\n      border-left:1px dashed var(--line);\n      padding-left:14px;\n    }\n    @media (max-width: 920px){\n      #icte-apa7 .icte-hero__controls{ border-left:none; padding-left:0; border-top:1px dashed var(--line); padding-top:12px; }\n    }\n\n    #icte-apa7 .icte-row{ display:flex; gap:8px; flex-wrap:wrap; }\n    #icte-apa7 .icte-label{ display:block; font-size:12px; font-weight:900; margin-top:8px; }\n    #icte-apa7 .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-apa7 .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-apa7 .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-apa7 .dot.on{\n      background:#22c55e;\n      box-shadow:0 0 0 4px rgba(34,197,94,.18);\n    }\n\n    #icte-apa7 .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-apa7 .btn:hover{ filter:brightness(.95); transform:translateY(-1px); }\n    #icte-apa7 .btn:active{ transform:translateY(0); }\n    #icte-apa7 .btn.ghost{\n      background:#fff;\n      color:#111827;\n      border:1px solid var(--line);\n    }\n    #icte-apa7 .btn.mini{ padding:8px 10px; border-radius:10px; font-size:13px; }\n    #icte-apa7 .icte-small{ font-size:12px; }\n\n    #icte-apa7 .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-apa7 .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-apa7 .card-h h3{ margin:0; font-size:18px; }\n    #icte-apa7 .card-actions{ display:flex; gap:8px; flex-wrap:wrap; justify-content:flex-end; }\n\n    #icte-apa7 .view{ display:none; }\n    #icte-apa7 .view.is-active{ display:block; }\n\n    #icte-apa7 .grid2{\n      display:grid;\n      grid-template-columns:1fr 1fr;\n      gap:14px;\n      margin-top:10px;\n    }\n    @media (max-width: 920px){ #icte-apa7 .grid2{ grid-template-columns:1fr; } }\n\n    #icte-apa7 .stack{ display:flex; flex-direction:column; gap:10px; }\n    #icte-apa7 .h4{ margin:0 0 6px 0; font-size:15px; }\n    #icte-apa7 .qitem{\n      padding:10px;\n      border:1px solid var(--line);\n      border-radius:14px;\n      background:#fafafa;\n    }\n    #icte-apa7 .qtext{ font-weight:900; margin-bottom:8px; }\n\n    #icte-apa7 .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-apa7 .feedback.ok{ display:block; border-color:rgba(34,197,94,.35); background:#ecfdf5; }\n    #icte-apa7 .feedback.bad{ display:block; border-color:rgba(239,68,68,.35); background:#fef2f2; }\n\n    #icte-apa7 .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-apa7 .reading{\n      border:1px solid var(--line);\n      border-radius:14px;\n      padding:12px;\n      background:#fff;\n      margin-top:10px;\n    }\n    #icte-apa7 .reading-title{ font-weight:900; margin-bottom:8px; }\n    #icte-apa7 .reading-p{ padding:8px 0; border-top:1px dashed var(--line); }\n    #icte-apa7 .reading-p:first-of-type{ border-top:none; }\n\n    #icte-apa7 .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-apa7 .progress-grid{ grid-template-columns:1fr; } }\n    #icte-apa7 .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-apa7 .pnum{ font-size:28px; font-weight:1000; }\n\n    #icte-apa7 .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-apa7 .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-apa7 .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-apa7 .ul{ margin:0; padding-left:18px; }\n    #icte-apa7 .ul li{ margin:6px 0; }\n\n    #icte-apa7 .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-apa7 .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-apa7 .msg{ margin:10px 0; display:flex; gap:10px; align-items:flex-start; }\n    #icte-apa7 .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-apa7 .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-apa7 .msg.user .who{ color:#86efac; }\n    #icte-apa7 .msg.user .bubble{ background:rgba(34,197,94,.10); border-color:rgba(34,197,94,.18); }\n\n    #icte-apa7 .chatbar{\n      margin-top:10px;\n      display:flex;\n      gap:8px;\n      align-items:center;\n    }\n    #icte-apa7 .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-apa7');\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\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      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 (optional)\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_apa7_progress_v1\";\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:\"match\", label:\"Text \u2194 list matching\"},\n        {k:\"missing\", label:\"Missing references\"},\n        {k:\"unused\", label:\"Unused references\"},\n        {k:\"doi\", label:\"DOI\/URL present\"},\n        {k:\"meta\", label:\"Metadata completeness\"},\n        {k:\"year\", label:\"Year consistency\"},\n        {k:\"apa\", label:\"APA 7 formatting\"},\n        {k:\"verify\", label:\"Verified externally\"}\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. You will check in-text citations against the reference list, detect missing or unused items, and verify DOI and metadata using an APA 7 workflow.\",\n        \"conv-instr\":\"Conversation. Build a safe prompt and workflow for APA reference checking. Forbid invented citations and require external verification.\",\n        \"reading-instr\":\"Reading. Read the text and answer the quiz questions.\",\n        \"toolkit-instr\":\"Toolkit. Review mismatch checks, metadata checks, APA 7 high-frequency rules, and DOI and URL checks.\",\n        \"prompts-instr\":\"Prompts. Copy prompts for auditing citations, completing metadata, verifying DOI, and standardizing APA 7 formatting.\",\n        \"list-instr\":\"Listening. Two editors discuss AI checking versus human verification.\",\n        \"lab-instr\":\"Lab. Paste manuscript text and references. Run the audit report and use the safe AI prompt for follow-up fixes.\",\n        \"problem-instr\":\"Problem-solving. Write a fix plan, verification steps, and one corrected APA 7 reference.\"\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      qs('#speakActive').addEventListener('click', async ()=>{\n        const v = activeViewName();\n        const map = {\n          overview:\"Overview page. Outcomes and safety rules for APA 7 reference checking.\",\n          conversation:\"Conversation page. Build a safe AI workflow and prompt constraints.\",\n          reading:\"Reading page. Read and answer quiz questions.\",\n          toolkit:\"Toolkit page. What to check for mismatches, missing metadata, and DOI or URL.\",\n          prompts:\"Prompts page. Copy and adapt prompts for auditing and fixing references.\",\n          listening:\"Listening page. Two editors discuss verification workflow.\",\n          lab:\"Lab page. Paste text and reference list and run the audit report.\",\n          problem:\"Problem-solving page. Create a plan and correct one reference.\",\n          progress:\"Progress page.\"\n        };\n        await speakAs(\"A\", map[v] || \"APA 7 reference checking lesson.\");\n      });\n\n      \/* =========================\n         Voice transcript routing\n      ========================= *\/\n      function handleVoiceTranscript(t){\n        const text = norm(t);\n        if(!text) return;\n        const v = activeViewName();\n        if(v===\"conversation\"){ handleConversationInput(text); return; }\n        if(v===\"lab\"){\n          const box = qs('#manuscript');\n          box.value = (box.value ? (box.value + \" \") : \"\") + text;\n          speakAs(\"A\",\"Added to manuscript text.\");\n          return;\n        }\n        if(v===\"problem\"){\n          const box = qs('#psPlan');\n          box.value = (box.value ? (box.value + \"\\n\") : \"\") + \"- \" + text;\n          speakAs(\"A\",\"Added to your fix plan.\");\n          return;\n        }\n        speakAs(\"A\",\"I heard: \" + text);\n      }\n\n      \/* =========================\n         Conversation coach\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        { bot:\"Step 1: What is your scope? (e.g., audit: in-text \u2194 references + DOIs + missing metadata).\",\n          check:(a)=>\/(audit|in-text|reference|doi|metadata|consisten)\/i.test(a),\n          tips:\"Mention at least 2: in-text vs list, DOI\/URL, metadata, consistency.\"\n        },\n        { bot:\"Step 2: Add a non-invention rule. Write one sentence forbidding invented citations.\",\n          check:(a)=>\/(do not|don't|never)\\s+(invent|make up|fabricat)\/i.test(a),\n          tips:\"Example: Do not invent references or DOIs.\"\n        },\n        { bot:\"Step 3: Write one verification rule (Google Scholar \/ publisher page).\",\n          check:(a)=>\/(google scholar|publisher|springer|elsevier|taylor|sage|crossref|doi\\.org)\/i.test(a),\n          tips:\"Example: Verify DOI on Google Scholar or the publisher page.\"\n        },\n        { bot:\"Step 4: What outputs should AI provide? (list missing\/unused + suggestions + flagged fields).\",\n          check:(a)=>\/(missing|unused|flag|fields|report|table)\/i.test(a),\n          tips:\"Include: missing\/unused and a structured report.\"\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 Done. You defined scope, forbade invention, required verification, and specified structured outputs.\");\n          markDone(\"conversation\", 100);\n          addCheck(\"verify\");\n          await speakAs(\"A\",\"Done. You defined scope, forbade invention, required verification, and specified structured outputs.\");\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        if(\/in-text|reference|audit\/i.test(a)) addCheck(\"match\");\n        if(\/doi|url\/i.test(a)) addCheck(\"doi\");\n        if(\/metadata|volume|issue|pages|publisher\/i.test(a)) addCheck(\"meta\");\n        if(\/year\/i.test(a)) addCheck(\"year\");\n        if(\/apa\/i.test(a)) addCheck(\"apa\");\n        if(\/google scholar|publisher|doi\\.org|springer|elsevier|taylor|sage\/i.test(a)) addCheck(\"verify\");\n\n        const step = convSteps[convStep];\n        const ok = step.check(a);\n        const msg = ok ? \"\u2705 Good. Next.\" : \"\u26a0\ufe0f Try again. \" + step.tips;\n\n        addMsg(\"Coach\", msg);\n        await speakAs(\"A\", msg);\n\n        if(ok){ convStep++; setTimeout(coachAsk, 250); }\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 build your APA 7 reference-checking workflow.\");\n        coachAsk();\n      });\n\n      addMsg(\"Coach\",\"Ready. Let\u2019s build your APA 7 reference-checking workflow.\");\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) The most basic reliability improvement is to\u2026\",\n          ans:\"Match every in-text citation to the reference list (and vice versa)\",\n          opts:[\n            \"Change all citations to et al.\",\n            \"Match every in-text citation to the reference list (and vice versa)\",\n            \"Add more references to look scholarly\",\n            \"Remove DOIs to avoid errors\"\n          ]\n        },\n        { q:\"2) AI should NOT be used to\u2026\",\n          ans:\"Invent missing references or DOIs\",\n          opts:[\n            \"Extract author-year keys\",\n            \"Flag missing metadata\",\n            \"Invent missing references or DOIs\",\n            \"List mismatches for review\"\n          ]\n        },\n        { q:\"3) A safe approach to missing metadata is to\u2026\",\n          ans:\"List what is missing and verify via Google Scholar or publisher page\",\n          opts:[\n            \"Guess the missing fields\",\n            \"List what is missing and verify via Google Scholar or publisher page\",\n            \"Delete the reference\",\n            \"Replace it with a random newer article\"\n          ]\n        },\n        { q:\"4) APA prefers DOI formatted as\u2026\",\n          ans:\"A URL (https:\/\/doi.org\/...)\",\n          opts:[\n            \"doi:10.xxxx (no URL)\",\n            \"A URL (https:\/\/doi.org\/...)\",\n            \"Only a journal homepage link\",\n            \"No DOI even if available\"\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(\"match\"); addCheck(\"doi\"); }\n        markDone(\"reading_quiz\", pct);\n      });\n\n      \/* =========================\n         Toolkit content\n      ========================= *\/\n      qs('#tkMismatch').textContent =\n`Mismatch audit:\n- In-text citation has no reference entry\n- Reference entry is never cited\n- Author spelling differs (Nguyen vs. Nguyenh)\n- Year differs (2020 in text, 2019 in list)\n- Same author + same year needs a\/b (2021a, 2021b)\n- et al. used in text but reference author list differs`;\n\n      qs('#tkMeta').textContent =\n`Often missing:\n- DOI or stable URL\n- Journal volume(issue)\n- Page range \/ article number\n- Publisher (books)\n- Editors (chapters)\n- Conference name\/location (proceedings)\n- Retrieval date (only for changing content)\n- Exact title capitalization (APA style)`;\n\n      qs('#tkRules').textContent =\n`APA 7 quick rules:\n- In-text: (Author, Year) or Author (Year)\n- Same author + year: 2020a, 2020b\n- DOI as URL: https:\/\/doi.org\/...\n- Journal titles and volume are italicized (formatting later)\n- Titles: sentence case for article\/book titles\n- Reference list: alphabetical by first author`;\n\n      qs('#tkDoi').textContent =\n`DOI \/ URL checks:\n- DOI pattern often starts with 10.\n- Prefer https:\/\/doi.org\/xxxxx\n- If no DOI: use stable publisher URL (avoid long tracking links)\n- If neither exists: keep as-is but flag for manual verification\n- Never \u201cmake up\u201d a DOI; verify via Scholar\/publisher`;\n\n      qs('#tkExample').textContent =\n`Common fixes:\n1) In-text: (Smith & Lee, 2021) but reference shows Lee & Smith (2021).\n   \u2192 Fix author order in the reference list to match the source.\n\n2) Reference missing DOI:\n   \u2192 Find DOI on publisher page; add as https:\/\/doi.org\/...\n\n3) Reference in list never cited:\n   \u2192 Either cite it in text (if used) or remove it (if not needed).`;\n\n      qs('#toolkitSpeak').addEventListener('click', ()=>{\n        speakAs(\"A\",\"Toolkit. Run mismatch audits, check missing metadata like DOI, volume, issue, pages, and apply APA 7 high frequency rules. Verify DOIs using Google Scholar and publisher pages.\");\n      });\n\n      \/* =========================\n         Prompts content\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 IN-TEXT \u2194 REFERENCE LIST AUDIT (NO INVENTION)\nYou are an APA 7 reference auditor.\n\nTask:\n1) Extract all in-text citations as (Author, Year).\n2) Extract all reference entries as (FirstAuthor, Year).\n3) Report:\n   - In-text citations missing in reference list\n   - Reference entries never cited in text\n   - Author\/year mismatches you suspect\n\nRules:\n- Do NOT invent any references.\n- If uncertain, label: \"needs verification\".\n\nInputs:\nA) Manuscript text: [PASTE]\nB) Reference list: [PASTE]`;\n\n      p2.textContent =\n`PROMPT 2 \u2014 MISSING METADATA CHECKLIST\nFrom the reference list below, create a table:\nReference | Missing fields (DOI\/URL, volume, issue, pages, publisher, editors, etc.) | Action\n\nRules:\n- Do NOT add metadata unless you can point to a verifiable source.\n- Suggest where to verify (Google Scholar vs publisher page).\n\nReference list:\n[PASTE]`;\n\n      p3.textContent =\n`PROMPT 3 \u2014 DOI\/URL VERIFICATION WORKFLOW\nFor each reference below:\n- Provide the expected DOI\/URL field (if known)\n- Tell me exactly how to verify it (Google Scholar query string + publisher page check)\n- If not verifiable, mark as UNKNOWN\n\nRules:\n- No invented DOIs.\n- Prefer DOI as https:\/\/doi.org\/...\n\nReferences:\n[PASTE]`;\n\n      p4.textContent =\n`PROMPT 4 \u2014 APA 7 STANDARDIZATION (SAFE)\nStandardize formatting to APA 7 while preserving:\n- author order\n- year\n- title wording\n- journal\/book details\n- DOI\/URL exactly as provided\n\nRules:\n- Do NOT change bibliographic facts.\n- Only fix punctuation, casing, italics markers (if needed), spacing.\n- Flag entries that appear incomplete.\n\nReference list:\n[PASTE]`;\n\n      pExample.textContent =\n`EXPECTED OUTPUT STRUCTURE (example snippet)\nMissing in reference list:\n- (Garcia, 2020)\n- (Nguyen & Tran, 2021a)\n\nUnused references:\n- Lee, J. (2019). ...\n\nPossible mismatches:\n- In-text: (Smith, 2022) but list: Smith (2021) \u2192 verify year\n\nMissing metadata:\n- Brown, T. (2020). ... Missing DOI, volume(issue), pages`;\n\n      qs('#promptsSpeak').addEventListener('click', ()=>{\n        speakAs(\"A\",\"Prompts page. Use prompts to audit in-text citations versus reference list, identify missing metadata, verify DOI and URLs safely, and standardize APA 7 formatting without changing facts.\");\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\\nEXAMPLE\\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:\"I used AI to fix my references, but I\u2019m worried it might invent details.\"},\n        {role:\"B\", text:\"Good concern. AI should only flag missing fields and mismatches. You must verify DOIs and metadata in Google Scholar or on the publisher page.\"},\n        {role:\"A\", text:\"What\u2019s the first check you run?\"},\n        {role:\"B\", text:\"Match in-text citations to the reference list and find unused references. That removes most editorial problems.\"},\n        {role:\"A\", text:\"What about years and author spellings?\"},\n        {role:\"B\", text:\"Those must be consistent. If they differ, mark them for verification rather than guessing.\"},\n        {role:\"A\", text:\"So AI helps me see problems faster, but I remain responsible for accuracy.\"},\n        {role:\"B\", text:\"Exactly. Think of AI as a high-speed checklist, not a source of truth.\"}\n      ];\n\n      const listenItems = [\n        {q:\"1) AI should primarily\u2026\", ans:\"Flag issues; the researcher verifies details\"},\n        {q:\"2) The first check is\u2026\", ans:\"Match in-text citations to the reference list\"},\n        {q:\"3) If years differ, you should\u2026\", ans:\"Verify rather than guess\"},\n        {q:\"4) AI is best seen as\u2026\", ans:\"A high-speed checklist, not a source of truth\"}\n      ];\n\n      function renderListenQ(){\n        const optsMap = {\n          \"Flag issues; the researcher verifies details\":[\n            \"Flag issues; the researcher verifies details\",\n            \"Invent missing DOIs automatically\",\n            \"Replace all references with newer ones\"\n          ],\n          \"Match in-text citations to the reference list\":[\n            \"Match in-text citations to the reference list\",\n            \"Delete the reference list\",\n            \"Only check punctuation\"\n          ],\n          \"Verify rather than guess\":[\n            \"Verify rather than guess\",\n            \"Always change to the newest year\",\n            \"Ignore the mismatch\"\n          ],\n          \"A high-speed checklist, not a source of truth\":[\n            \"A high-speed checklist, not a source of truth\",\n            \"A database index\",\n            \"A publisher website\"\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(\"verify\"); addCheck(\"match\"); }\n        markDone(\"listening\", pct);\n      });\n\n      \/* =========================\n         LAB: Reference audit heuristics\n      ========================= *\/\n\n      const DOI_RE = \/\\b10\\.\\d{4,9}\\\/[-._;()\/:A-Z0-9]+\\b\/i;\n      const DOI_URL_RE = \/https?:\\\/\\\/doi\\.org\\\/10\\.\\d{4,9}\\\/[-._;()\/:A-Z0-9]+\/i;\n      const URL_RE = \/https?:\\\/\\\/[^\\s)]+\/i;\n\n      function normalizeAuthorKey(s){\n        \/\/ pick first author surname-ish: up to comma or ampersand or \"et al.\"\n        const t = (s||\"\").trim();\n        if(!t) return \"\";\n        \/\/ remove initials, keep letters\/hyphen\/apostrophe\n        return t.toLowerCase()\n          .replace(\/&\/g,\"and\")\n          .replace(\/et al\\.?\/g,\"\")\n          .replace(\/[^a-z\\u00C0-\\u017F' -]\/g,\" \")\n          .trim()\n          .split(\/\\s+\/)[0] || \"\";\n      }\n\n      function extractInTextCitations(text){\n        const t = text || \"\";\n        const found = [];\n\n        \/\/ Parenthetical patterns: (Author, 2020) \/ (Author & Author, 2020) \/ (Author et al., 2020)\n        const paren = \/\\(([^()]*?\\b\\d{4}[a-z]?\\b[^()]*)\\)\/gi;\n        let m;\n        while((m = paren.exec(t)) !== null){\n          const inside = m[1];\n          \/\/ split on ; for multiple citations\n          inside.split(\";\").forEach(chunk=>{\n            const c = chunk.trim();\n            const ym = c.match(\/\\b(19|20)\\d{2}[a-z]?\\b\/);\n            if(!ym) return;\n            const year = ym[0];\n            const beforeYear = c.slice(0, ym.index).replace(\/[,()]\/g,\" \").trim();\n            \/\/ take first surname-ish token\n            const authorKey = normalizeAuthorKey(beforeYear);\n            if(authorKey) found.push({authorKey, year, raw:c});\n          });\n        }\n\n        \/\/ Narrative patterns: Author (2020)\n        const narr = \/([A-Z][A-Za-z\\u00C0-\\u017F' -]+?)\\s*\\(\\s*((19|20)\\d{2}[a-z]?)\\s*\\)\/g;\n        while((m = narr.exec(t)) !== null){\n          const authorKey = normalizeAuthorKey(m[1]);\n          const year = m[2];\n          if(authorKey) found.push({authorKey, year, raw:`${m[1]} (${year})`});\n        }\n\n        \/\/ de-dup by key\n        const map = new Map();\n        found.forEach(x=>{\n          const k = `${x.authorKey}|${x.year}`;\n          if(!map.has(k)) map.set(k, x);\n        });\n        return Array.from(map.values()).sort((a,b)=> (a.authorKey+a.year).localeCompare(b.authorKey+b.year));\n      }\n\n      function splitReferences(text){\n        \/\/ Prefer blank lines as separators; fallback to newline groups.\n        const raw = (text||\"\").trim();\n        if(!raw) return [];\n        const blocks = raw.split(\/\\n\\s*\\n+\/).map(b=>b.trim()).filter(Boolean);\n        if(blocks.length >= 2) return blocks;\n        \/\/ fallback: each line as entry\n        return raw.split(\/\\n+\/).map(b=>b.trim()).filter(Boolean);\n      }\n\n      function extractReferenceKeys(refEntries){\n        \/\/ Try to get first author surname + year in parentheses: Author, A. A. (2020).\n        const refs = [];\n        refEntries.forEach(entry=>{\n          const e = entry.trim();\n          if(!e) return;\n          const y = e.match(\/\\((19|20)\\d{2}[a-z]?\\)\/);\n          const year = y ? y[0].replace(\/[()]\/g,\"\") : \"\";\n          \/\/ first chunk before comma\n          const firstChunk = e.split(\",\")[0] || \"\";\n          const authorKey = normalizeAuthorKey(firstChunk);\n          const hasDOI = DOI_URL_RE.test(e) || DOI_RE.test(e);\n          const hasURL = URL_RE.test(e);\n          \/\/ crude \"missing meta\" checks\n          const isJournalLike = \/\\.\\s*[A-Z].+?,\\s*\\d+\/m.test(e) || \/\\d+\\(\\d+\\)\/.test(e); \/\/ volume(issue)\n          const hasPages = \/\\b\\d+\\s*[-\u2013]\\s*\\d+\\b\/.test(e) || \/\\b(e\\d+)\\b\/i.test(e); \/\/ pages or e-locator\n          refs.push({authorKey, year, entry:e, hasDOI, hasURL, isJournalLike, hasPages});\n        });\n\n        \/\/ de-dup by authorKey|year but keep the first occurrence\n        const map = new Map();\n        refs.forEach(r=>{\n          const k = `${r.authorKey}|${r.year}`;\n          if(!map.has(k)) map.set(k, r);\n        });\n        return Array.from(map.values()).filter(r=>r.authorKey && r.year);\n      }\n\n      function buildAuditReport(manuscriptText, refText){\n        const citations = extractInTextCitations(manuscriptText);\n        const refEntries = splitReferences(refText);\n        const refs = extractReferenceKeys(refEntries);\n\n        const citeSet = new Set(citations.map(c=>`${c.authorKey}|${c.year}`));\n        const refSet  = new Set(refs.map(r=>`${r.authorKey}|${r.year}`));\n\n        const missingInRefs = citations.filter(c=>!refSet.has(`${c.authorKey}|${c.year}`));\n        const unusedRefs = refs.filter(r=>!citeSet.has(`${r.authorKey}|${r.year}`));\n\n        \/\/ DOI\/URL missing flags\n        const noDoiOrUrl = refs.filter(r=>!r.hasDOI && !r.hasURL);\n        const likelyMetaMissing = refs.filter(r=>{\n          \/\/ if looks like journal but missing pages or missing DOI\/URL\n          return (r.isJournalLike && !r.hasPages) || (r.isJournalLike && !r.hasDOI && !r.hasURL);\n        });\n\n        \/\/ score (rough)\n        const totalC = citations.length || 1;\n        const totalR = refs.length || 1;\n        const matchRate = 1 - (missingInRefs.length\/totalC);\n        const unusedRate = 1 - (unusedRefs.length\/totalR);\n        const doiRate = 1 - (noDoiOrUrl.length\/totalR);\n        const pct = Math.round(clamp((matchRate*0.5 + unusedRate*0.2 + doiRate*0.3)*100, 0, 100));\n\n        \/\/ checks\n        addCheck(\"match\");\n        if(missingInRefs.length) addCheck(\"missing\");\n        if(unusedRefs.length) addCheck(\"unused\");\n        if(noDoiOrUrl.length === 0) addCheck(\"doi\");\n        if(likelyMetaMissing.length) addCheck(\"meta\");\n\n        const lines = [];\n        lines.push(`APA 7 REFERENCE AUDIT (heuristic)\\nScore: ${pct}%\\n`);\n        lines.push(`In-text citations found: ${citations.length}`);\n        lines.push(`Reference entries detected (keyed by first author + year): ${refs.length}\\n`);\n\n        lines.push(`1) In-text citations MISSING from reference list (${missingInRefs.length})`);\n        if(missingInRefs.length){\n          missingInRefs.slice(0,30).forEach(c=>{\n            lines.push(`- (${c.authorKey}, ${c.year})  | source: ${c.raw}`);\n          });\n          if(missingInRefs.length>30) lines.push(`... +${missingInRefs.length-30} more`);\n        } else {\n          lines.push(`- None detected \u2705`);\n        }\n\n        lines.push(`\\n2) References NOT cited in the manuscript (${unusedRefs.length})`);\n        if(unusedRefs.length){\n          unusedRefs.slice(0,20).forEach(r=>{\n            lines.push(`- (${r.authorKey}, ${r.year})  | ${r.entry.slice(0,110)}${r.entry.length>110?\"\u2026\":\"\"}`);\n          });\n          if(unusedRefs.length>20) lines.push(`... +${unusedRefs.length-20} more`);\n        } else {\n          lines.push(`- None detected \u2705`);\n        }\n\n        lines.push(`\\n3) References missing DOI\/URL (${noDoiOrUrl.length})`);\n        if(noDoiOrUrl.length){\n          noDoiOrUrl.slice(0,20).forEach(r=>{\n            lines.push(`- (${r.authorKey}, ${r.year})  | add DOI\/URL after verification`);\n          });\n          if(noDoiOrUrl.length>20) lines.push(`... +${noDoiOrUrl.length-20} more`);\n        } else {\n          lines.push(`- None detected \u2705`);\n        }\n\n        lines.push(`\\n4) Likely missing metadata (journal pages\/locator or DOI\/URL) (${likelyMetaMissing.length})`);\n        if(likelyMetaMissing.length){\n          likelyMetaMissing.slice(0,20).forEach(r=>{\n            const flags = [];\n            if(r.isJournalLike && !r.hasPages) flags.push(\"pages\/locator?\");\n            if(r.isJournalLike && !r.hasDOI && !r.hasURL) flags.push(\"DOI\/URL?\");\n            lines.push(`- (${r.authorKey}, ${r.year})  | missing: ${flags.join(\", \") || \"check\"}  | ${r.entry.slice(0,90)}${r.entry.length>90?\"\u2026\":\"\"}`);\n          });\n          if(likelyMetaMissing.length>20) lines.push(`... +${likelyMetaMissing.length-20} more`);\n        } else {\n          lines.push(`- None detected \u2705`);\n        }\n\n        lines.push(`\\n5) Next actions (recommended)`);\n        lines.push(`- For each missing in-text citation: add the correct reference OR correct the in-text author\/year.`);\n        lines.push(`- For each unused reference: remove it OR add the citation where it is actually used.`);\n        lines.push(`- For DOI\/URL: verify via Google Scholar (search exact title) and confirm on publisher page; then add https:\/\/doi.org\/...`);\n        lines.push(`- Final pass: standardize APA 7 punctuation\/casing without changing bibliographic facts.`);\n\n        return {text: lines.join(\"\\n\"), score:pct, citations, refs, missingInRefs, unusedRefs, noDoiOrUrl, likelyMetaMissing};\n      }\n\n      function buildSafePromptFromAudit(audit){\n        return `ROLE: You are an APA 7 reference editor.\n\nTASK:\nHelp me fix my manuscript\u2019s citations and reference list based on the audit report.\n\nSTRICT RULES:\n- Do NOT invent references, DOIs, or metadata.\n- If DOI\/URL is unknown, write UNKNOWN and tell me how to verify it (Google Scholar query + publisher check).\n- Do NOT change bibliographic facts (author order, year, title wording) unless I confirm they are wrong.\n\nOUTPUT:\n1) List of missing references to add (with verification steps for each).\n2) List of unused references to remove (or where to cite them).\n3) For references missing DOI\/URL: provide verification steps and placeholders.\n4) Provide corrected APA 7 formatting for entries I confirm.\n\nAUDIT REPORT:\n${audit.text}`;\n      }\n\n      const manuscript = qs('#manuscript');\n      const reflist = qs('#reflist');\n      const report = qs('#report');\n      const aiPrompt = qs('#aiPrompt');\n      const labFb = qs('#labFb');\n\n      function labReset(){\n        manuscript.value = \"\";\n        reflist.value = \"\";\n        report.textContent = \"\";\n        aiPrompt.textContent = \"\";\n        labFb.className = \"feedback\";\n        labFb.textContent = \"\";\n      }\n      qs('#labReset').addEventListener('click', labReset);\n\n      qs('#labRun').addEventListener('click', ()=>{\n        const m = norm(manuscript.value);\n        const r = norm(reflist.value);\n        if(m.length < 40 || r.length < 40){\n          labFb.className = \"feedback bad\";\n          labFb.textContent = \"\u26a0\ufe0f Please paste both manuscript text and reference list (at least ~40 characters each).\";\n          return;\n        }\n        const audit = buildAuditReport(m, r);\n        report.textContent = audit.text;\n        aiPrompt.textContent = buildSafePromptFromAudit(audit);\n\n        \/\/ progress\n        markDone(\"lab\", audit.score);\n        if(audit.score >= 70) labFb.className = \"feedback ok\";\n        else labFb.className = \"feedback bad\";\n        labFb.textContent = `Audit complete. Score: ${audit.score}%. Fix mismatches first, then DOI\/metadata, then formatting.`;\n      });\n\n      qs('#labCopy').addEventListener('click', async ()=>{\n        const pack = `AUDIT REPORT\\n${report.textContent}\\n\\nSAFE AI PROMPT\\n${aiPrompt.textContent}`;\n        if(!pack.trim()){\n          labFb.className = \"feedback bad\";\n          labFb.textContent = \"\u26a0\ufe0f Run the audit first.\";\n          return;\n        }\n        try{\n          await navigator.clipboard.writeText(pack);\n          labFb.className = \"feedback ok\";\n          labFb.textContent = \"\u2705 Copied report + prompt.\";\n        }catch(_){\n          labFb.className = \"feedback bad\";\n          labFb.textContent = \"\u26a0\ufe0f Clipboard blocked. Copy manually from the boxes.\";\n        }\n      });\n\n      \/* =========================\n         Problem-solving checker\n      ========================= *\/\n      const psPlan = qs('#psPlan');\n      const psVerify = qs('#psVerify');\n      const psRef = qs('#psRef');\n      const psFb = qs('#psFb');\n\n      function countBullets(txt){ return (txt.match(\/^\\s*[-\u2022]\/gm)||[]).length; }\n      function looksApaRef(txt){\n        const t = (txt||\"\").trim();\n        const hasYear = \/\\(\\s*(19|20)\\d{2}[a-z]?\\s*\\)\/.test(t);\n        const hasTitleDot = \/\\)\\.\\s+.+\\.\/.test(t); \/\/ after year, has title ending with a period\n        const hasDoiOrUrl = \/https?:\\\/\\\/doi\\.org\\\/\/i.test(t) || \/https?:\\\/\\\/\\S+\/i.test(t);\n        return hasYear && hasTitleDot && hasDoiOrUrl;\n      }\n\n      qs('#psCheck').addEventListener('click', ()=>{\n        const planOk = countBullets(psPlan.value) >= 5;\n        const verOk = countBullets(psVerify.value) >= 3 && \/(google scholar|publisher|doi\\.org|springer|elsevier|taylor|sage)\/i.test(psVerify.value);\n        const refOk = looksApaRef(psRef.value);\n\n        const pct = Math.round(((planOk?1:0) + (verOk?1:0) + (refOk?1:0)) \/ 3 * 100);\n\n        psFb.className = \"feedback \" + (pct>=70 ? \"ok\":\"bad\");\n        psFb.textContent =\n          `Check: ${pct}%\\n` +\n          `- Fix plan (>=5 bullets): ${planOk ? \"Yes\" : \"No\"}\\n` +\n          `- Verification steps (>=3 + mentions Scholar\/publisher\/DOI): ${verOk ? \"Yes\" : \"No\"}\\n` +\n          `- Corrected reference looks APA-like (+ DOI\/URL): ${refOk ? \"Yes\" : \"No\"}`;\n\n        markDone(\"problem_solving\", pct);\n        addCheck(\"verify\");\n        addCheck(\"apa\");\n      });\n\n      qs('#psReset').addEventListener('click', ()=>{\n        psPlan.value = \"\";\n        psVerify.value = \"\";\n        psRef.value = \"\";\n        psFb.className = \"feedback\";\n        psFb.textContent = \"\";\n      });\n\n      \/* =========================\n         Start state\n      ========================= *\/\n      renderProgress();\n\n    })();\n  <\/script>\n\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Overview Conversation Reading APA Toolkit Prompts Listening Reference Audit Lab Problem-solving Progress Reference Checking &#038; APA 7th Use AI safely<\/p>\n","protected":false},"author":1,"featured_media":768,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"colormag_page_layout":"default_layout","footnotes":""},"categories":[52,45],"tags":[],"class_list":["post-767","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ai-for-research","category-ai-for-teachers"],"_links":{"self":[{"href":"https:\/\/i-cte.org\/robot\/wp-json\/wp\/v2\/posts\/767","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=767"}],"version-history":[{"count":2,"href":"https:\/\/i-cte.org\/robot\/wp-json\/wp\/v2\/posts\/767\/revisions"}],"predecessor-version":[{"id":770,"href":"https:\/\/i-cte.org\/robot\/wp-json\/wp\/v2\/posts\/767\/revisions\/770"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/i-cte.org\/robot\/wp-json\/wp\/v2\/media\/768"}],"wp:attachment":[{"href":"https:\/\/i-cte.org\/robot\/wp-json\/wp\/v2\/media?parent=767"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/i-cte.org\/robot\/wp-json\/wp\/v2\/categories?post=767"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/i-cte.org\/robot\/wp-json\/wp\/v2\/tags?post=767"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}