{"id":734,"date":"2026-03-04T09:38:41","date_gmt":"2026-03-04T09:38:41","guid":{"rendered":"https:\/\/i-cte.org\/robot\/?p=734"},"modified":"2026-03-04T09:38:41","modified_gmt":"2026-03-04T09:38:41","slug":"at-home","status":"publish","type":"post","link":"https:\/\/i-cte.org\/robot\/at-home\/","title":{"rendered":"At home"},"content":{"rendered":"\n<!-- \u2705 ICTE Chatbot Lesson \u2014 Personal Best (B1) Unit 11 (WP-safe single block) -->\n<div id=\"icte-u11\">\n\n  <!-- \u2705 TOP MENU -->\n  <nav class=\"icte-menu\" aria-label=\"Unit 11 lesson navigation\">\n    <a href=\"#\" class=\"is-current\" data-view=\"conversation\">Conversation<\/a>\n    <a href=\"#\" data-view=\"vocab\">Vocabulary<\/a>\n    <a href=\"#\" data-view=\"grammar\">Grammar<\/a>\n    <a href=\"#\" data-view=\"discussion\">Discussion<\/a>\n    <a href=\"#\" data-view=\"reading\">Reading<\/a>\n    <a href=\"#\" data-view=\"listening\">Listening<\/a>\n    <a href=\"#\" data-view=\"problemsolving\">Problem-solving<\/a>\n    <a href=\"#\" data-view=\"progress\">Progress<\/a>\n  <\/nav>\n\n  <section class=\"icte-shell\" aria-label=\"ICTE Unit 11 practice\">\n\n    <!-- \u2705 Header -->\n    <header class=\"icte-hero\">\n      <div class=\"icte-hero__text\">\n        <h2>Unit 11 \u2014 At home<\/h2>\n        <p class=\"muted\">\n          Practice <b>-ing \/ infinitive verb patterns<\/b>, <b>household items<\/b>, <b>housework<\/b>,\n          <b>articles (a \/ an \/ the \/ \u2014)<\/b>, and vocabulary for <b>materials &#038; clothes<\/b>.\n          Listening skill: <b>omission of words<\/b>.\n        <\/p>\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        <label class=\"icte-label\">\n          Voice (Narrator)\n          <select id=\"icteVoiceSelect\" class=\"icte-select\" aria-label=\"Voice selection\"><\/select>\n        <\/label>\n\n        <div class=\"icte-small muted\">\n          Tip: If you don\u2019t see voices yet, click anywhere once and wait 2\u20133 seconds.\n        <\/div>\n      <\/div>\n    <\/header>\n\n    <!-- \u2705 Views -->\n    <main class=\"icte-main\">\n\n      <!-- ===================== -->\n      <!-- \u2705 1) CONVERSATION -->\n      <!-- ===================== -->\n      <section class=\"view is-active\" data-view=\"conversation\" aria-label=\"Conversation practice\">\n        <div class=\"card\">\n          <div class=\"card-h\">\n            <h3>1) Conversation (Voice Interactive)<\/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=\"convReset\">Reset<\/button>\n            <\/div>\n          <\/div>\n\n          <p class=\"muted\">\n            Speak your answers. Try to use <b>-ing \/ infinitive patterns<\/b> (e.g., <i>enjoy + -ing<\/i>, <i>want + to<\/i>)\n            and Unit 11 vocabulary (<i>dishwasher, closet, mop the floor, take out the trash, cotton, leather\u2026<\/i>).\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 (optional)...\" autocomplete=\"off\" \/>\n            <button class=\"btn\" id=\"convSend\" type=\"button\">Send<\/button>\n            <button class=\"btn ghost\" id=\"convHear\" type=\"button\">\ud83d\udd0a Read last question<\/button>\n          <\/div>\n\n          <div class=\"muted icte-small\">\n            Targets: Dream home + housework + wearable technology.\n          <\/div>\n        <\/div>\n      <\/section>\n\n      <!-- ===================== -->\n      <!-- \u2705 2) VOCABULARY -->\n      <!-- ===================== -->\n      <section class=\"view\" data-view=\"vocab\" aria-label=\"Vocabulary practice\">\n        <div class=\"card\">\n          <div class=\"card-h\">\n            <h3>2) Vocabulary (Household items + Housework + Materials)<\/h3>\n            <div class=\"card-actions\">\n              <button class=\"btn mini\" type=\"button\" data-say=\"vocab-instr\">\ud83d\udd0a Read instructions<\/button>\n              <button class=\"btn mini ghost\" type=\"button\" id=\"vocabReset\">Reset<\/button>\n            <\/div>\n          <\/div>\n\n          <p class=\"muted\">\n            Match the words to the meanings, then complete the sentences using the same vocabulary.\n          <\/p>\n\n          <div class=\"grid2\">\n            <div>\n              <h4 class=\"h4\">A) Matching<\/h4>\n              <div id=\"vocabMatch\" class=\"stack\"><\/div>\n              <button class=\"btn\" id=\"vocabCheck\" type=\"button\">Check<\/button>\n              <div class=\"feedback\" id=\"vocabFb\" aria-live=\"polite\"><\/div>\n            <\/div>\n\n            <div>\n              <h4 class=\"h4\">B) Use the words (Fill in the blanks)<\/h4>\n              <div id=\"vocabUse\" class=\"stack\"><\/div>\n              <button class=\"btn\" id=\"vocabUseCheck\" type=\"button\">Check<\/button>\n              <div class=\"feedback\" id=\"vocabUseFb\" aria-live=\"polite\"><\/div>\n            <\/div>\n          <\/div>\n        <\/div>\n      <\/section>\n\n      <!-- ===================== -->\n      <!-- \u2705 3) GRAMMAR -->\n      <!-- ===================== -->\n      <section class=\"view\" data-view=\"grammar\" aria-label=\"Grammar practice\">\n        <div class=\"card\">\n          <div class=\"card-h\">\n            <h3>3) Grammar \u2014 Verb patterns + Articles<\/h3>\n            <div class=\"card-actions\">\n              <button class=\"btn mini\" type=\"button\" data-say=\"gram-instr\">\ud83d\udd0a Read instructions<\/button>\n              <button class=\"btn mini ghost\" type=\"button\" id=\"gramReset\">Reset<\/button>\n            <\/div>\n          <\/div>\n\n          <div class=\"note\">\n            <b>Verb patterns:<\/b> Some verbs take <b>-ing<\/b> (enjoy, imagine), some take <b>to + infinitive<\/b> (want, decide), and some can take both (start).<br>\n            <b>Articles:<\/b> Use <b>a\/an<\/b> for first mention, <b>the<\/b> for specific\/second mention, and <b>\u2014<\/b> for general plural\/uncountable or some places (at home).\n          <\/div>\n\n          <div id=\"gramQuiz\" class=\"stack\"><\/div>\n          <button class=\"btn\" id=\"gramCheck\" type=\"button\">Check<\/button>\n          <div class=\"feedback\" id=\"gramFb\" aria-live=\"polite\"><\/div>\n        <\/div>\n      <\/section>\n\n      <!-- ===================== -->\n      <!-- \u2705 4) DISCUSSION -->\n      <!-- ===================== -->\n      <section class=\"view\" data-view=\"discussion\" aria-label=\"Discussion practice\">\n        <div class=\"card\">\n          <div class=\"card-h\">\n            <h3>4) Discussion (Voice or typing)<\/h3>\n            <div class=\"card-actions\">\n              <button class=\"btn mini\" type=\"button\" data-say=\"disc-instr\">\ud83d\udd0a Read instructions<\/button>\n              <button class=\"btn mini ghost\" type=\"button\" id=\"discNext\">Next question<\/button>\n            <\/div>\n          <\/div>\n\n          <p class=\"muted\">\n            Answer with reasons. Try to include at least <b>2 vocabulary items<\/b> and at least <b>one<\/b> grammar target:\n            <b>-ing\/infinitive<\/b> or <b>articles<\/b>.\n          <\/p>\n\n          <div class=\"qa\">\n            <div class=\"q\" id=\"discQ\">Click <b>Next question<\/b> to begin.<\/div>\n            <textarea id=\"discA\" class=\"textarea\" rows=\"4\" placeholder=\"Write your answer here...\"><\/textarea>\n            <div class=\"row\">\n              <button class=\"btn\" id=\"discCheck\" type=\"button\">Check my language<\/button>\n              <button class=\"btn ghost\" id=\"discSpeakQ\" type=\"button\">\ud83d\udd0a Read question<\/button>\n            <\/div>\n            <div class=\"feedback\" id=\"discFb\" aria-live=\"polite\"><\/div>\n          <\/div>\n        <\/div>\n      <\/section>\n\n      <!-- ===================== -->\n      <!-- \u2705 5) READING -->\n      <!-- ===================== -->\n      <section class=\"view\" data-view=\"reading\" aria-label=\"Reading comprehension\">\n        <div class=\"card\">\n          <div class=\"card-h\">\n            <h3>5) Reading \u2014 \u201cLiving the dream\u201d (Desert island home)<\/h3>\n            <div class=\"card-actions\">\n              <button class=\"btn mini\" type=\"button\" data-say=\"read-instr\">\ud83d\udd0a Read instructions<\/button>\n              <button class=\"btn mini\" type=\"button\" id=\"readTextBtn\">\ud83d\udd0a Read the text<\/button>\n            <\/div>\n          <\/div>\n\n          <p class=\"muted\">\n            Read the text, then answer the questions (main idea + details + vocabulary).\n          <\/p>\n\n          <article class=\"reading\" id=\"readingText\">\n            <div class=\"reading-title\">Living the dream (shortened)<\/div>\n            <div class=\"reading-p\"><b>1<\/b> Karyn von Engelbrechten became tired of a long commute, so she left her job in London and moved with her family to a tiny island in the South Pacific.<\/div>\n            <div class=\"reading-p\"><b>2<\/b> They built a house using materials from the island. They used solar panels for electricity and collected rainwater for the kitchen and bathrooms.<\/div>\n            <div class=\"reading-p\"><b>3<\/b> Their home is now a guesthouse. The kitchen is basic, but it includes a refrigerator and an oven. You can sit on the balcony and watch whales and turtles.<\/div>\n            <div class=\"reading-p\"><b>4<\/b> There is no air-conditioning, but the bedrooms are comfortable. There are extra blankets and comforters in the closet for colder months.<\/div>\n            <div class=\"reading-p\"><b>5<\/b> There are disadvantages: the nearest store is a three-hour boat trip away, and the island is near a volcano with earthquakes and tropical storms.<\/div>\n            <div class=\"reading-p\"><b>6<\/b> However, the message is clear: if you\u2019re tired of your routine, follow your dreams.<\/div>\n          <\/article>\n\n          <div class=\"grid2\">\n            <div>\n              <h4 class=\"h4\">A) Main idea<\/h4>\n              <div class=\"qitem\">\n                <div class=\"qtext\">1) What is the main purpose of the text?<\/div>\n                <select class=\"icte-select\" id=\"rQ1\">\n                  <option value=\"\">Choose\u2026<\/option>\n                  <option value=\"A\">A: To explain how to buy a dishwasher.<\/option>\n                  <option value=\"B\">B: To describe a family\u2019s dream home and the pros\/cons of island life.<\/option>\n                  <option value=\"C\">C: To review wearable technology.<\/option>\n                <\/select>\n              <\/div>\n\n              <h4 class=\"h4\" style=\"margin-top:14px;\">B) Headings \u2192 Paragraphs<\/h4>\n              <div id=\"readMatch\" class=\"stack\"><\/div>\n\n              <button class=\"btn\" id=\"readCheck\" type=\"button\">Check<\/button>\n              <div class=\"feedback\" id=\"readFb\" aria-live=\"polite\"><\/div>\n            <\/div>\n\n            <div>\n              <h4 class=\"h4\">C) Find evidence (short answers)<\/h4>\n              <div id=\"readShort\" class=\"stack\"><\/div>\n              <button class=\"btn\" id=\"readShortCheck\" type=\"button\">Check<\/button>\n              <div class=\"feedback\" id=\"readShortFb\" aria-live=\"polite\"><\/div>\n            <\/div>\n          <\/div>\n        <\/div>\n      <\/section>\n\n      <!-- ===================== -->\n      <!-- \u2705 6) LISTENING -->\n      <!-- ===================== -->\n      <section class=\"view\" data-view=\"listening\" aria-label=\"Listening comprehension\">\n        <div class=\"card\">\n          <div class=\"card-h\">\n            <h3>6) Listening \u2014 \u201cThe truth about housework\u201d (Learning Curve)<\/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 listening (TTS)<\/button>\n              <button class=\"btn mini ghost\" type=\"button\" id=\"listenStop\">\u23f9 Stop<\/button>\n            <\/div>\n          <\/div>\n\n          <p class=\"muted\">\n            Click <b>Play listening<\/b>. Listen and complete the gaps. Focus on key ideas and \u201cmissing words\u201d (omission).\n          <\/p>\n\n          <div class=\"note\">\n            Listening skill: speakers sometimes omit small words because the meaning is obvious (e.g., \u201c(I\u2019m) Just doing a bit of dusting\u2026\u201d).\n          <\/div>\n\n          <div id=\"listenGaps\" class=\"stack\"><\/div>\n          <button class=\"btn\" id=\"listenCheck\" type=\"button\">Check<\/button>\n          <div class=\"feedback\" id=\"listenFb\" aria-live=\"polite\"><\/div>\n        <\/div>\n      <\/section>\n\n      <!-- ===================== -->\n      <!-- \u2705 7) PROBLEM-SOLVING -->\n      <!-- ===================== -->\n      <section class=\"view\" data-view=\"problemsolving\" aria-label=\"Problem-solving tasks\">\n        <div class=\"card\">\n          <div class=\"card-h\">\n            <h3>7) Problem-solving (Home + Housework + Tech)<\/h3>\n            <div class=\"card-actions\">\n              <button class=\"btn mini\" type=\"button\" data-say=\"prob-instr\">\ud83d\udd0a Read instructions<\/button>\n              <button class=\"btn mini ghost\" type=\"button\" id=\"probReset\">Reset<\/button>\n            <\/div>\n          <\/div>\n\n          <p class=\"muted\">\n            Choose the best solution. Then write one sentence using <b>-ing\/infinitive<\/b> or <b>articles<\/b>.\n          <\/p>\n\n          <div id=\"probSet\" class=\"stack\"><\/div>\n          <button class=\"btn\" id=\"probCheck\" type=\"button\">Check<\/button>\n          <div class=\"feedback\" id=\"probFb\" aria-live=\"polite\"><\/div>\n        <\/div>\n      <\/section>\n\n      <!-- ===================== -->\n      <!-- \u2705 8) 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=\"pVocab\">0<\/div>\n              <div class=\"muted\">Vocab used (detected)<\/div>\n            <\/div>\n          <\/div>\n\n          <div class=\"note\">\n            Completion is saved in your browser (local storage). If you change device\/browser, progress resets.\n          <\/div>\n\n          <h4 class=\"h4\">Vocabulary Bank (Unit 11)<\/h4>\n          <div class=\"bank\" id=\"vocabBank\"><\/div>\n        <\/div>\n      <\/section>\n\n    <\/main>\n  <\/section>\n\n  <style>\n    \/* ===== WP-SAFE STYLES (scoped) ===== *\/\n    #icte-u11 *{ box-sizing:border-box; }\n    #icte-u11{\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-u11 .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-u11 .icte-menu a{\n      display:inline-block;\n      color:#fff;\n      text-decoration:none;\n      font-weight:700;\n      padding:8px 10px;\n      border-radius:999px;\n      margin:0 3px;\n      opacity:.92;\n      transition:.15s;\n    }\n    #icte-u11 .icte-menu a:hover{ opacity:1; background:rgba(255,255,255,.14); }\n    #icte-u11 .icte-menu a.is-current{ background:#fff; color:var(--dark); opacity:1; }\n\n    #icte-u11 .icte-shell{ max-width:1100px; margin:0 auto; }\n    #icte-u11 .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-u11 .icte-hero{ grid-template-columns:1fr; } }\n\n    #icte-u11 h2{ margin:0 0 6px 0; font-size:22px; }\n    #icte-u11 .muted{ color:var(--muted); }\n\n    #icte-u11 .icte-hero__controls{\n      border-left:1px dashed var(--line);\n      padding-left:14px;\n    }\n    @media (max-width: 920px){\n      #icte-u11 .icte-hero__controls{ border-left:none; padding-left:0; border-top:1px dashed var(--line); padding-top:12px; }\n    }\n\n    #icte-u11 .icte-row{ display:flex; gap:8px; flex-wrap:wrap; }\n    #icte-u11 .icte-label{ display:block; font-size:12px; font-weight:800; margin-top:10px; }\n    #icte-u11 .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-u11 .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:800;\n    }\n    #icte-u11 .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-u11 .dot.on{\n      background:#22c55e;\n      box-shadow:0 0 0 4px rgba(34,197,94,.18);\n    }\n\n    #icte-u11 .btn{\n      border:none;\n      padding:10px 12px;\n      border-radius:12px;\n      background:var(--green);\n      color:#fff;\n      font-weight:800;\n      cursor:pointer;\n      transition:.15s;\n    }\n    #icte-u11 .btn:hover{ filter:brightness(.95); transform:translateY(-1px); }\n    #icte-u11 .btn:active{ transform:translateY(0); }\n    #icte-u11 .btn.ghost{\n      background:#fff;\n      color:#111827;\n      border:1px solid var(--line);\n    }\n    #icte-u11 .btn.mini{ padding:8px 10px; border-radius:10px; font-size:13px; }\n    #icte-u11 .icte-small{ font-size:12px; }\n\n    #icte-u11 .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-u11 .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-u11 .card-h h3{ margin:0; font-size:18px; }\n    #icte-u11 .card-actions{ display:flex; gap:8px; flex-wrap:wrap; justify-content:flex-end; }\n\n    #icte-u11 .view{ display:none; }\n    #icte-u11 .view.is-active{ display:block; }\n\n    #icte-u11 .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-u11 .msg{ margin:10px 0; display:flex; gap:10px; align-items:flex-start; }\n    #icte-u11 .who{\n      min-width:72px;\n      font-weight:900;\n      font-size:12px;\n      color:#93c5fd;\n      text-transform:uppercase;\n      letter-spacing:.06em;\n    }\n    #icte-u11 .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    }\n    #icte-u11 .msg.user .who{ color:#86efac; }\n    #icte-u11 .msg.user .bubble{ background:rgba(34,197,94,.10); border-color:rgba(34,197,94,.18); }\n\n    #icte-u11 .chatbar{\n      margin-top:10px;\n      display:flex;\n      gap:8px;\n      align-items:center;\n    }\n    #icte-u11 .input{\n      flex:1;\n      padding:12px 12px;\n      border:1px solid var(--line);\n      border-radius:12px;\n      outline:none;\n    }\n    #icte-u11 .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    #icte-u11 .grid2{\n      display:grid;\n      grid-template-columns:1fr 1fr;\n      gap:14px;\n      margin-top:10px;\n    }\n    @media (max-width: 920px){ #icte-u11 .grid2{ grid-template-columns:1fr; } }\n\n    #icte-u11 .stack{ display:flex; flex-direction:column; gap:10px; }\n    #icte-u11 .h4{ margin:0 0 6px 0; font-size:15px; }\n    #icte-u11 .qitem{\n      padding:10px;\n      border:1px solid var(--line);\n      border-radius:14px;\n      background:#fafafa;\n    }\n    #icte-u11 .qtext{ font-weight:800; margin-bottom:8px; }\n    #icte-u11 .row{ display:flex; gap:8px; flex-wrap:wrap; margin-top:10px; }\n\n    #icte-u11 .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:700;\n      display:none;\n      white-space:pre-line;\n    }\n    #icte-u11 .feedback.ok{ display:block; border-color:rgba(34,197,94,.35); background:#ecfdf5; }\n    #icte-u11 .feedback.bad{ display:block; border-color:rgba(239,68,68,.35); background:#fef2f2; }\n\n    #icte-u11 .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-u11 .reading{\n      border:1px solid var(--line);\n      border-radius:14px;\n      padding:12px;\n      background:#fff;\n      margin-top:10px;\n    }\n    #icte-u11 .reading-title{ font-weight:900; margin-bottom:8px; }\n    #icte-u11 .reading-p{ padding:8px 0; border-top:1px dashed var(--line); }\n    #icte-u11 .reading-p:first-of-type{ border-top:none; }\n\n    #icte-u11 .qa .q{\n      padding:12px;\n      border-radius:14px;\n      border:1px solid var(--line);\n      background:#fff;\n      font-weight:900;\n    }\n\n    #icte-u11 .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-u11 .progress-grid{ grid-template-columns:1fr; } }\n    #icte-u11 .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-u11 .pnum{ font-size:28px; font-weight:1000; }\n\n    #icte-u11 .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-u11 .tag{\n      border:1px solid var(--line);\n      background:#f9fafb;\n      padding:6px 10px;\n      border-radius:999px;\n      font-weight:800;\n      font-size:13px;\n    }\n  <\/style>\n\n  <script>\n    (function(){\n      const root = document.getElementById('icte-u11');\n      if(!root) return;\n\n      \/* ========= Helpers ========= *\/\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 lower = (s)=> norm(s).toLowerCase();\n      const esc = (s)=> (s||\"\").replace(\/[&<>\"']\/g, m=>({ \"&\":\"&amp;\",\"<\":\"&lt;\",\">\":\"&gt;\",'\"':\"&quot;\",\"'\":\"&#039;\" }[m]));\n      const shuffle = (arr)=> arr.map(v=>({v, r:Math.random()})).sort((a,b)=>a.r-b.r).map(o=>o.v);\n\n      \/* ========= Navigation ========= *\/\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      \/* ========= Speech (TTS + ASR) ========= *\/\n      const micDot = qs('#icteMicDot');\n      const micStatus = qs('#icteMicStatus');\n      const voiceSel = qs('#icteVoiceSelect');\n      const btnStartVoice = qs('#icteStartVoice');\n      const btnStopVoice = qs('#icteStopVoice');\n\n      let chosenVoice = null;\n      let recognition = null;\n      let listening = false;\n      let lastPromptSpoken = \"\";\n\n      function loadVoices(){\n        if(!window.speechSynthesis) return;\n        const all = speechSynthesis.getVoices() || [];\n        let list = all.filter(v => (v.lang||\"\").toLowerCase().startsWith(\"en\"));\n        if(list.length === 0) list = all;\n\n        voiceSel.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          voiceSel.appendChild(opt);\n        });\n\n        chosenVoice = list[0] || null;\n        voiceSel.onchange = ()=>{\n          const idx = parseInt(voiceSel.value,10);\n          chosenVoice = list[idx] || chosenVoice;\n        };\n      }\n      if(window.speechSynthesis){\n        loadVoices();\n        speechSynthesis.onvoiceschanged = loadVoices;\n      }\n\n      function speak(text){\n        const t = norm(text);\n        if(!t || !window.speechSynthesis) return;\n        speechSynthesis.cancel();\n        const u = new SpeechSynthesisUtterance(t);\n        if(chosenVoice) u.voice = chosenVoice;\n        u.rate = 1.02; u.pitch = 1.0; u.volume = 1.0;\n        speechSynthesis.speak(u);\n      }\n      function stopSpeak(){ if(window.speechSynthesis) speechSynthesis.cancel(); }\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\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\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 your answers.\");\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 = ()=>{\n          if(listening){ try{ recognition.start(); }catch(_){ } }\n        };\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      \/* ========= Progress ========= *\/\n      const LS_KEY = \"icte_u11_progress_v1\";\n      const progress = JSON.parse(localStorage.getItem(LS_KEY) || \"{}\");\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      \/* ========= Content: Vocabulary ========= *\/\n      const vocabItems = [\n        {word:\"refrigerator\", def:\"a machine that keeps food cold\"},\n        {word:\"oven\", def:\"a kitchen appliance for baking\/cooking\"},\n        {word:\"dishwasher\", def:\"a machine that washes dishes\"},\n        {word:\"washing machine\", def:\"a machine that washes clothes\"},\n        {word:\"iron\", def:\"a device for making clothes flat\"},\n        {word:\"closet\", def:\"a space\/cupboard for clothes\"},\n        {word:\"blanket\", def:\"a warm cover for sleeping\"},\n        {word:\"comforter\", def:\"a thick warm bed cover\"},\n        {word:\"faucet\", def:\"a tap where water comes out\"},\n        {word:\"balcony\", def:\"an outside platform attached to a building\"}\n      ];\n\n      const vocabHousework = [\n        {word:\"wash the dishes\", def:\"clean plates and cups\"},\n        {word:\"load the dishwasher\", def:\"put dirty dishes into the dishwasher\"},\n        {word:\"do the ironing\", def:\"make clothes flat with an iron\"},\n        {word:\"do the laundry\", def:\"wash clothes\"},\n        {word:\"clear the table\", def:\"remove things from the table\"},\n        {word:\"water the plants\", def:\"give plants water\"},\n        {word:\"take out the trash\", def:\"remove rubbish\/garbage\"},\n        {word:\"mop the floor\", def:\"clean the floor with a mop\"},\n        {word:\"vacuum the carpet\", def:\"clean using a vacuum cleaner\"},\n        {word:\"dust the furniture\", def:\"clean dust from surfaces\"}\n      ];\n\n      const vocabMaterials = [\n        {word:\"cotton\", def:\"soft natural fabric\"},\n        {word:\"denim\", def:\"strong fabric used for jeans\"},\n        {word:\"leather\", def:\"material made from animal skin\"},\n        {word:\"metal\", def:\"hard material like steel\"},\n        {word:\"wood\", def:\"material from trees\"},\n        {word:\"wool\", def:\"warm fabric from sheep\"}\n      ];\n\n      const vocabAll = [...vocabItems, ...vocabHousework, ...vocabMaterials];\n\n      \/\/ render bank\n      const bank = qs('#vocabBank');\n      bank.innerHTML = vocabAll.map(v=>`<span class=\"tag\" title=\"${esc(v.def)}\">${esc(v.word)}<\/span>`).join(\"\");\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\n        qs('#pDone').textContent = String(done);\n        qs('#pScore').textContent = String(avg) + \"%\";\n\n        const used = new Set();\n        const txt = (progress._vocabUsedText||\"\");\n        vocabAll.forEach(w=>{\n          if(lower(txt).includes(lower(w.word))) used.add(w.word);\n        });\n        qs('#pVocab').textContent = String(used.size);\n      }\n\n      \/* ========= Instruction TTS ========= *\/\n      const SAY = {\n        \"conv-instr\": \"Conversation. Answer using enjoy plus ing, want plus to, and Unit 11 home vocabulary. Try to mention one household item and one housework chore.\",\n        \"vocab-instr\": \"Vocabulary. Match words to meanings, then complete the sentences using the same words.\",\n        \"gram-instr\": \"Grammar. Choose the correct verb pattern: ing or to. Then choose the correct article: a, an, the, or no article.\",\n        \"disc-instr\": \"Discussion. Use at least two vocabulary items and one grammar target: ing or infinitive, or articles.\",\n        \"read-instr\": \"Reading. Read about a family who moved to an island and built a home. Answer main idea and evidence questions.\",\n        \"list-instr\": \"Listening. Listen to Learning Curve about housework and robots. Fill the gaps. Notice omitted words.\",\n        \"prob-instr\": \"Problem-solving. Choose the best option, then write one sentence using verb patterns or articles.\"\n      };\n      qsa('[data-say]').forEach(btn=>{\n        btn.addEventListener('click', ()=>{\n          const k = btn.getAttribute('data-say');\n          if(SAY[k]) speak(SAY[k]);\n        });\n      });\n\n      \/* ========= 1) Conversation ========= *\/\n      const convChat = qs('#convChat');\n      const convText = qs('#convText');\n      const convSend = qs('#convSend');\n      const convHear = qs('#convHear');\n      const convReset = qs('#convReset');\n\n      let convStep = 0;\n      const convSteps = [\n        {\n          bot: \"Hi! Welcome to Unit 11. Describe your home in two sentences. Mention two household items.\",\n          check: (a)=> {\n            const t = lower(a);\n            const hits = [\"refrigerator\",\"oven\",\"dishwasher\",\"washing machine\",\"iron\",\"closet\",\"blanket\",\"comforter\",\"faucet\",\"balcony\"]\n              .filter(w=>t.includes(w));\n            return a.length >= 16 && hits.length >= 2;\n          },\n          tips: \"Use two household items (refrigerator, oven, dishwasher, closet, etc.).\"\n        },\n        {\n          bot: \"Housework: What do you hate doing? Use: I hate + -ing.\",\n          check: (a)=> \/\\bi hate\\b\/i.test(a) && \/ing\\b\/i.test(a),\n          tips: \"Example: I hate doing the ironing. \/ I hate washing the dishes.\"\n        },\n        {\n          bot: \"Now use enjoy + -ing: What do you enjoy doing at home?\",\n          check: (a)=> \/\\benjoy\\b\/i.test(a) && \/ing\\b\/i.test(a),\n          tips: \"Example: I enjoy cooking. I enjoy watching movies.\"\n        },\n        {\n          bot: \"Dream home: What do you want to change? Use: I want to + verb.\",\n          check: (a)=> \/\\bi want to\\b\/i.test(a),\n          tips: \"Example: I want to buy a dishwasher. I want to change the kitchen.\"\n        },\n        {\n          bot: \"Wearable tech: Describe one item of clothing using a material word (cotton, denim, leather, wool, metal, wood).\",\n          check: (a)=> \/(cotton|denim|leather|wool|metal|wood)\/i.test(a) && a.length >= 10,\n          tips: \"Example: I have a denim jacket. \/ I wear a leather belt.\"\n        },\n        {\n          bot: \"Final: Do you want a robot to do your housework? Answer using: prefer + -ing or would rather + base verb.\",\n          check: (a)=> \/\\bprefer\\b\/i.test(a) || \/\\bwould rather\\b\/i.test(a),\n          tips: \"Example: I\u2019d rather relax, so I prefer using a robot.\"\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      function botAsk(){\n        const step = convSteps[convStep];\n        if(!step){\n          addMsg(\"Bot\",\"Great work! You finished Unit 11 conversation. Try other sections.\");\n          speak(\"Great work! You finished Unit 11 conversation. Try other sections.\");\n          markDone(\"conversation\", 100);\n          return;\n        }\n        addMsg(\"Bot\", step.bot);\n        lastPromptSpoken = step.bot;\n        speak(step.bot);\n      }\n\n      function scoreAnswer(a){\n        const step = convSteps[convStep];\n        if(!step) return {ok:true, msg:\"\"};\n        const ok = step.check(norm(a));\n        const msg = ok ? \"\u2705 Good. Nice use of the target language.\" : \"\u26a0\ufe0f Try again. \" + step.tips;\n        return {ok, msg};\n      }\n\n      function handleConversationInput(text){\n        const a = norm(text);\n        if(!a) return;\n        addMsg(\"You\", a);\n\n        progress._vocabUsedText = (progress._vocabUsedText||\"\") + \" \" + a;\n        saveProgress();\n\n        const {ok, msg} = scoreAnswer(a);\n        addMsg(\"Bot\", msg);\n        speak(msg);\n\n        if(ok){ convStep++; setTimeout(botAsk, 450); }\n        else { setTimeout(()=> speak(\"Please try again. \" + convSteps[convStep].bot), 450); }\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', ()=> speak(lastPromptSpoken || \"No question yet.\"));\n      convReset.addEventListener('click', ()=>{\n        convChat.innerHTML = \"\";\n        convStep = 0;\n        addMsg(\"Bot\",\"Ready! Start Voice (optional) and answer. Let\u2019s begin.\");\n        botAsk();\n      });\n\n      addMsg(\"Bot\",\"Ready! Start Voice (optional) and answer. Let\u2019s begin.\");\n      botAsk();\n\n      \/* ========= Route voice transcripts ========= *\/\n      function activeViewName(){\n        const v = qs('.view.is-active');\n        return v ? v.getAttribute('data-view') : \"conversation\";\n      }\n      function handleVoiceTranscript(t){\n        const text = norm(t);\n        if(!text) return;\n\n        const v = activeViewName();\n        if(v === \"conversation\"){ handleConversationInput(text); return; }\n        if(v === \"discussion\"){\n          const ta = qs('#discA');\n          ta.value = (ta.value ? (ta.value + \" \") : \"\") + text;\n          speak(\"I heard: \" + text);\n          return;\n        }\n        const input = qs('.view.is-active input.input');\n        if(input){ input.value = text; speak(\"I heard: \" + text); return; }\n        speak(\"I heard: \" + text);\n      }\n\n      \/* ========= 2) Vocabulary ========= *\/\n      const vocabMatch = qs('#vocabMatch');\n      const vocabFb = qs('#vocabFb');\n      const vocabUse = qs('#vocabUse');\n      const vocabUseFb = qs('#vocabUseFb');\n\n      const matchSet = shuffle([\n        {word:\"dishwasher\", def:\"a machine that washes dishes\"},\n        {word:\"washing machine\", def:\"a machine that washes clothes\"},\n        {word:\"closet\", def:\"a space\/cupboard for clothes\"},\n        {word:\"comforter\", def:\"a thick warm bed cover\"},\n        {word:\"clear the table\", def:\"remove things from the table\"},\n        {word:\"take out the trash\", def:\"remove rubbish\/garbage\"},\n        {word:\"mop the floor\", def:\"clean the floor with a mop\"},\n        {word:\"dust the furniture\", def:\"clean dust from surfaces\"},\n        {word:\"denim\", def:\"strong fabric used for jeans\"},\n        {word:\"leather\", def:\"material made from animal skin\"}\n      ]);\n\n      function renderVocabMatching(){\n        const defs = shuffle(matchSet.map(x=>x.def));\n        vocabMatch.innerHTML = matchSet.map((x,i)=>{\n          const options = ['<option value=\"\">Choose meaning\u2026<\/option>']\n            .concat(defs.map(d=>`<option value=\"${esc(d)}\">${esc(d)}<\/option>`))\n            .join(\"\");\n          return `\n            <div class=\"qitem\">\n              <div class=\"qtext\">${i+1}) <b>${esc(x.word)}<\/b><\/div>\n              <select class=\"icte-select\" data-ans=\"${esc(x.def)}\">${options}<\/select>\n            <\/div>\n          `;\n        }).join(\"\");\n      }\n      renderVocabMatching();\n\n      qs('#vocabCheck').addEventListener('click', ()=>{\n        const sels = qsa('#vocabMatch 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        vocabFb.className = \"feedback \" + (pct>=70 ? \"ok\":\"bad\");\n        vocabFb.textContent = `Score: ${correct}\/${sels.length} (${pct}%).`;\n        markDone(\"vocab_match\", pct);\n      });\n\n      const useItems = [\n        {sent:\"Please ____ before you go to bed.\", ans:\"clear the table\"},\n        {sent:\"I don\u2019t mind ____ because it makes the kitchen clean.\", ans:\"wash the dishes\"},\n        {sent:\"We need to ____ because it smells bad.\", ans:\"take out the trash\"},\n        {sent:\"On weekends, I ____ and clean the tiles.\", ans:\"mop the floor\"},\n        {sent:\"My jeans are made of ____.\", ans:\"denim\"},\n        {sent:\"This belt is made of ____.\", ans:\"leather\"}\n      ];\n\n      function renderVocabUse(){\n        const bank2 = shuffle(useItems.map(x=>x.ans));\n        vocabUse.innerHTML = useItems.map((x,i)=>{\n          const opts = ['<option value=\"\">Choose\u2026<\/option>']\n            .concat(bank2.map(w=>`<option value=\"${esc(w)}\">${esc(w)}<\/option>`)).join(\"\");\n          return `\n            <div class=\"qitem\">\n              <div class=\"qtext\">${i+1}) ${esc(x.sent)}<\/div>\n              <select class=\"icte-select\" data-ans=\"${esc(x.ans)}\">${opts}<\/select>\n            <\/div>\n          `;\n        }).join(\"\");\n      }\n      renderVocabUse();\n\n      qs('#vocabUseCheck').addEventListener('click', ()=>{\n        const sels = qsa('#vocabUse 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        vocabUseFb.className = \"feedback \" + (pct>=70 ? \"ok\":\"bad\");\n        vocabUseFb.textContent = `Score: ${correct}\/${sels.length} (${pct}%).`;\n        markDone(\"vocab_use\", pct);\n      });\n\n      qs('#vocabReset').addEventListener('click', ()=>{\n        renderVocabMatching();\n        renderVocabUse();\n        vocabFb.style.display=\"none\";\n        vocabUseFb.style.display=\"none\";\n      });\n\n      \/* ========= 3) Grammar ========= *\/\n      const gramQuiz = qs('#gramQuiz');\n      const gramFb = qs('#gramFb');\n\n      const gramItems = [\n        {q:\"Have you ever imagined ____ city life? (escape)\", opts:[\"to escape\",\"escaping\"], ans:\"escaping\"},\n        {q:\"Karyn wanted ____ the world. (travel)\", opts:[\"traveling\",\"to travel\"], ans:\"to travel\"},\n        {q:\"She decided ____ a new adventure. (start)\", opts:[\"to start\",\"starting\"], ans:\"to start\"},\n        {q:\"You can sit and enjoy ____ whales and turtles. (watch)\", opts:[\"watching\",\"to watch\"], ans:\"watching\"},\n        {q:\"It started ____ \/ ____ . (rain)\", opts:[\"to rain\",\"raining\",\"to raining\"], ans:\"to rain\"},\n        {q:\"Choose the second correct option: It started to rain = It started ____ .\", opts:[\"raining\",\"rain\",\"to raining\"], ans:\"raining\"},\n\n        {q:\"Complete with article: The solution is Wristify, ____ bracelet.\", opts:[\"a\",\"an\",\"the\",\"\u2014\"], ans:\"a\"},\n        {q:\"Complete with article: Perfect for a trip to ____ gym.\", opts:[\"a\",\"an\",\"the\",\"\u2014\"], ans:\"the\"},\n        {q:\"Complete with article: ...when ____ sun is shining.\", opts:[\"a\",\"an\",\"the\",\"\u2014\"], ans:\"the\"},\n        {q:\"Complete with article: People love ____ technology. (general)\", opts:[\"a\",\"an\",\"the\",\"\u2014\"], ans:\"\u2014\"}\n      ];\n\n      function renderGrammar(){\n        gramQuiz.innerHTML = gramItems.map((it,i)=>{\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\">${i+1}) ${esc(it.q)}<\/div>\n              <select class=\"icte-select\" data-ans=\"${esc(it.ans)}\">${options}<\/select>\n            <\/div>\n          `;\n        }).join(\"\");\n      }\n      renderGrammar();\n\n      qs('#gramCheck').addEventListener('click', ()=>{\n        const sels = qsa('#gramQuiz 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        gramFb.className = \"feedback \" + (pct>=70 ? \"ok\":\"bad\");\n        gramFb.textContent = `Score: ${correct}\/${sels.length} (${pct}%).`;\n        markDone(\"grammar\", pct);\n      });\n\n      qs('#gramReset').addEventListener('click', ()=>{\n        renderGrammar();\n        gramFb.style.display=\"none\";\n      });\n\n      \/* ========= 4) Discussion ========= *\/\n      const discQ = qs('#discQ');\n      const discA = qs('#discA');\n      const discFb = qs('#discFb');\n\n      const discQs = [\n        \"Do you enjoy doing housework or do you hate it? Use: enjoy + -ing \/ hate + -ing.\",\n        \"What\u2019s your dream home like? Use: want to + verb. Mention 2 household items.\",\n        \"Would you buy a cleaning robot? Why or why not? Use at least two housework verbs.\",\n        \"Describe something you wear using materials (cotton\/denim\/leather\/wool\/metal\/wood). Use articles correctly.\",\n        \"Write 2 short sentences with omission (missing words) like: (I\u2019m) Just doing a bit of dusting.\"\n      ];\n      let discIdx = -1;\n\n      function nextDiscQ(){\n        discIdx = (discIdx + 1) % discQs.length;\n        discQ.textContent = discQs[discIdx];\n        discA.value = \"\";\n        discFb.style.display = \"none\";\n        speak(discQs[discIdx]);\n      }\n      qs('#discNext').addEventListener('click', nextDiscQ);\n      qs('#discSpeakQ').addEventListener('click', ()=> speak(discQs[Math.max(0,discIdx)] || \"Click next question to begin.\"));\n\n      function detectTargets(text){\n        const t = lower(text);\n        const vocabHits = vocabAll.filter(v => t.includes(lower(v.word))).map(v=>v.word);\n        const hasIngInf = \/\\b(enjoy|hate|like|don\u2019t mind|would rather|prefer)\\b\/i.test(text) || \/\\bwant to\\b\/i.test(text) || \/\\bdecided to\\b\/i.test(text);\n        const hasArticles = \/\\b(a|an|the)\\b\/i.test(text);\n        return { vocabHits, hasIngInf, hasArticles };\n      }\n\n      qs('#discCheck').addEventListener('click', ()=>{\n        const ans = norm(discA.value);\n        if(!ans){\n          discFb.className = \"feedback bad\";\n          discFb.textContent = \"Please write or speak an answer first.\";\n          return;\n        }\n\n        progress._vocabUsedText = (progress._vocabUsedText||\"\") + \" \" + ans;\n        saveProgress();\n\n        const {vocabHits, hasIngInf, hasArticles} = detectTargets(ans);\n        const okV = vocabHits.length >= 2;\n        const okG = hasIngInf || hasArticles;\n\n        let score = 0;\n        if(okV) score += 50;\n        if(okG) score += 50;\n\n        discFb.className = \"feedback \" + (score>=70 ? \"ok\":\"bad\");\n        discFb.textContent =\n          `Detected vocab: ${vocabHits.slice(0,10).join(\", \") || \"none\"}\\n` +\n          `Grammar: ${okG ? \"\u2705 verb pattern or articles detected\" : \"\u26a0\ufe0f add enjoy + -ing \/ want to \/ or articles\"}\\n` +\n          `Score: ${score}%`;\n\n        markDone(\"discussion\", score);\n      });\n\n      \/* ========= 5) Reading ========= *\/\n      const readMatch = qs('#readMatch');\n      const readFb = qs('#readFb');\n      const readShort = qs('#readShort');\n      const readShortFb = qs('#readShortFb');\n\n      const headings = [\n        \"Where they moved\",\n        \"How they built the house\",\n        \"What the home has\",\n        \"Comfort in the bedrooms\",\n        \"Disadvantages and risks\",\n        \"Message to the reader\"\n      ];\n      const headAns = {\n        \"Where they moved\":\"1\",\n        \"How they built the house\":\"2\",\n        \"What the home has\":\"3\",\n        \"Comfort in the bedrooms\":\"4\",\n        \"Disadvantages and risks\":\"5\",\n        \"Message to the reader\":\"6\"\n      };\n\n      function renderReadMatch(){\n        readMatch.innerHTML = headings.map(h=>{\n          return `\n            <div class=\"qitem\">\n              <div class=\"qtext\">${esc(h)}<\/div>\n              <select class=\"icte-select\" data-ans=\"${esc(headAns[h])}\">\n                <option value=\"\">Paragraph\u2026<\/option>\n                <option>1<\/option><option>2<\/option><option>3<\/option><option>4<\/option><option>5<\/option><option>6<\/option>\n              <\/select>\n            <\/div>\n          `;\n        }).join(\"\");\n      }\n      renderReadMatch();\n\n      const shortItems = [\n        {q:\"Which paragraph mentions solar panels and rainwater?\", ans:\"2\"},\n        {q:\"Which paragraph mentions refrigerator and oven?\", ans:\"3\"},\n        {q:\"Which paragraph mentions volcano and storms?\", ans:\"5\"},\n        {q:\"Which paragraph gives advice to follow your dreams?\", ans:\"6\"}\n      ];\n\n      function renderReadShort(){\n        readShort.innerHTML = shortItems.map((it,i)=>`\n          <div class=\"qitem\">\n            <div class=\"qtext\">${i+1}) ${esc(it.q)}<\/div>\n            <select class=\"icte-select\" data-ans=\"${esc(it.ans)}\">\n              <option value=\"\">Choose\u2026<\/option>\n              <option>1<\/option><option>2<\/option><option>3<\/option><option>4<\/option><option>5<\/option><option>6<\/option>\n            <\/select>\n          <\/div>\n        `).join(\"\");\n      }\n      renderReadShort();\n\n      qs('#readCheck').addEventListener('click', ()=>{\n        let score = 0;\n        const q1 = qs('#rQ1');\n        const ok1 = q1.value === \"B\";\n        if(ok1) score += 40;\n        q1.style.borderColor = ok1 ? \"rgba(34,197,94,.6)\" : \"rgba(239,68,68,.6)\";\n\n        const sels = qsa('#readMatch 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        score += Math.round((correct \/ sels.length) * 60);\n\n        readFb.className = \"feedback \" + (score>=70 ? \"ok\":\"bad\");\n        readFb.textContent = `Score: ${score}%.`;\n        markDone(\"reading\", score);\n      });\n\n      qs('#readShortCheck').addEventListener('click', ()=>{\n        const sels = qsa('#readShort 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        readShortFb.className = \"feedback \" + (pct>=70 ? \"ok\":\"bad\");\n        readShortFb.textContent = `Score: ${correct}\/${sels.length} (${pct}%).`;\n        markDone(\"reading_evidence\", pct);\n      });\n\n      qs('#readTextBtn').addEventListener('click', ()=>{\n        const text = qsa('#readingText .reading-p').map(p=>p.textContent).join(\" \");\n        speak(\"Reading text. \" + text);\n      });\n\n      \/* ========= 6) Listening ========= *\/\n      const listeningScript =\n        \"Simon: Oh, hello there. Just doing a bit of dusting in the studio. Today we discuss housework. \" +\n        \"Kate says a lot of people dislike cleaning. Most people would prefer to spend time doing other things. \" +\n        \"Simon says that today, cleaning robots are a reality. At Columbia University, engineers built a robot that can iron your clothes. \" +\n        \"In Florida, a company designed a human-like robot named Atlas that cleans the house. It can vacuum, sweep, and pick up rubbish. \" +\n        \"In Japan, there is a robot with arms and legs that can lift and move heavy objects, and also a robot mop. \" +\n        \"Then Julie says she hates housework because she has a full-time job and would rather be with her kids on weekends. \" +\n        \"Axel buys a cleaning robot because it will give him more free time, and he says his dishwasher works very well. \" +\n        \"Roberta loves housework and says a robot mop does a better job than she can.\";\n\n      const gapItems = [\n        {q:\"1) Kate says a lot of people dislike ____.\", ans:\"cleaning\"},\n        {q:\"2) Most people would prefer to spend time doing other ____.\", ans:\"things\"},\n        {q:\"3) Today, cleaning ____ are a reality.\", ans:\"robots\"},\n        {q:\"4) At Columbia University, engineers built a robot that can ____ clothes.\", ans:\"iron\"},\n        {q:\"5) In Florida, a robot named ____ cleans the house.\", ans:\"Atlas\"},\n        {q:\"6) In Japan, a robot can lift and move heavy ____.\", ans:\"objects\"},\n        {q:\"7) Julie would rather be with her ____ on weekends.\", ans:\"kids\"},\n        {q:\"8) Axel says the robot will give him more free ____.\", ans:\"time\"},\n        {q:\"9) Axel says his ____ works very well.\", ans:\"dishwasher\"},\n        {q:\"10) Roberta says a robot mop does a better ____ than she can.\", ans:\"job\"}\n      ];\n\n      const listenGaps = qs('#listenGaps');\n      const listenFb = qs('#listenFb');\n\n      function renderListeningGaps(){\n        const wordBank = shuffle([\"cleaning\",\"things\",\"robots\",\"iron\",\"Atlas\",\"objects\",\"kids\",\"time\",\"dishwasher\",\"job\"]);\n        listenGaps.innerHTML =\n          `<div class=\"note\"><b>Word bank:<\/b> ${wordBank.map(w=>`<span class=\"tag\">${esc(w)}<\/span>`).join(\" \")}<\/div>` +\n          gapItems.map((it)=>{\n            const opts = ['<option value=\"\">Choose\u2026<\/option>']\n              .concat(wordBank.map(w=>`<option value=\"${esc(w)}\">${esc(w)}<\/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)}\">${opts}<\/select>\n              <\/div>\n            `;\n          }).join(\"\");\n      }\n      renderListeningGaps();\n\n      qs('#listenPlay').addEventListener('click', ()=> speak(listeningScript));\n      qs('#listenStop').addEventListener('click', stopSpeak);\n\n      qs('#listenCheck').addEventListener('click', ()=>{\n        const sels = qsa('#listenGaps 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        markDone(\"listening\", pct);\n      });\n\n      \/* ========= 7) Problem-solving ========= *\/\n      const probSet = qs('#probSet');\n      const probFb = qs('#probFb');\n\n      const problems = [\n        {\n          scenario: \"Scenario 1: Two roommates argue because one never does the chores. What\u2019s the best solution?\",\n          choices: [\n            \"Do everything yourself and never talk about it.\",\n            \"Make a schedule (clear the table, take out the trash, mop the floor) and agree on it.\",\n            \"Buy only a new oven and ignore the problem.\"\n          ],\n          correct: 1,\n          followup: \"Write ONE sentence using: decide to \/ want to \/ enjoy + -ing (e.g., We decided to make a schedule.).\"\n        },\n        {\n          scenario: \"Scenario 2: Your friend says, \u201cDishwasher\u2019s broken.\u201d What is the best response?\",\n          choices: [\n            \"Ignore it and leave the dirty dishes.\",\n            \"Offer help and use articles correctly: I can help fix the dishwasher \/ buy a new one.\",\n            \"Say: \u201cI hate to help you.\u201d\"\n          ],\n          correct: 1,\n          followup: \"Write ONE sentence with an article: a \/ an \/ the \/ \u2014 (e.g., The dishwasher is broken.).\"\n        },\n        {\n          scenario: \"Scenario 3: You want to write a house-exchange description. What should you include?\",\n          choices: [\n            \"Only one adjective: nice.\",\n            \"A variety of adjectives, synonyms, and linkers like but\/although\/however, plus where + example.\",\n            \"No details, because it\u2019s boring.\"\n          ],\n          correct: 1,\n          followup: \"Write ONE sentence using where + example (e.g., a balcony where you can have breakfast.).\"\n        }\n      ];\n\n      function renderProblems(){\n        probSet.innerHTML = problems.map((p,idx)=>{\n          const opts = p.choices.map((c,i)=>`\n            <label class=\"opt\" style=\"display:flex;gap:10px;align-items:flex-start;padding:8px 10px;border:1px solid var(--line);border-radius:12px;background:#fff;\">\n              <input type=\"radio\" name=\"prob_${idx}\" value=\"${i}\">\n              <span>${esc(c)}<\/span>\n            <\/label>\n          `).join(\"\");\n          return `\n            <div class=\"qitem\">\n              <div class=\"qtext\">${idx+1}) ${esc(p.scenario)}<\/div>\n              <div class=\"stack\" style=\"gap:8px;margin-top:8px\">${opts}<\/div>\n              <div class=\"muted icte-small\" style=\"margin-top:8px\">${esc(p.followup)}<\/div>\n              <textarea class=\"textarea\" rows=\"2\" data-followup=\"${idx}\" placeholder=\"Write your sentence here...\"><\/textarea>\n            <\/div>\n          `;\n        }).join(\"\");\n      }\n      renderProblems();\n\n      function okFollowup(idx, txt){\n        const t = txt.trim();\n        if(idx === 0) return (\/\\bdecided to\\b|\\bwant to\\b|\\benjoy\\b\/i.test(t)) && t.length >= 12;\n        if(idx === 1) return (\/\\b(a|an|the)\\b\/i.test(t) || \/\\bdishwasher\\b\/i.test(t)) && t.length >= 10;\n        return \/\\bwhere you can\\b\/i.test(t) && t.length >= 12;\n      }\n\n      qs('#probCheck').addEventListener('click', ()=>{\n        let score = 0;\n        const total = problems.length * 2;\n\n        problems.forEach((p,idx)=>{\n          const sel = qs(`input[name=\"prob_${idx}\"]:checked`);\n          const okChoice = sel && parseInt(sel.value,10) === p.correct;\n          if(okChoice) score++;\n\n          const ta = qs(`textarea[data-followup=\"${idx}\"]`);\n          const txt = norm(ta.value);\n          const okSentence = okFollowup(idx, txt);\n          if(okSentence) score++;\n\n          ta.style.borderColor = okSentence ? \"rgba(34,197,94,.6)\" : \"rgba(239,68,68,.6)\";\n        });\n\n        const pct = Math.round((score \/ total) * 100);\n        probFb.className = \"feedback \" + (pct>=70 ? \"ok\":\"bad\");\n        probFb.textContent =\n          `Score: ${score}\/${total} (${pct}%).\\nTip: Follow-up must match the grammar target (verb patterns \/ articles \/ where clause).`;\n        markDone(\"problemsolving\", pct);\n      });\n\n      qs('#probReset').addEventListener('click', ()=>{\n        renderProblems();\n        probFb.style.display=\"none\";\n      });\n\n      \/* ========= Init ========= *\/\n      renderProgress();\n\n    })();\n  <\/script>\n\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Conversation Vocabulary Grammar Discussion Reading Listening Problem-solving Progress Unit 11 \u2014 At home Practice -ing \/ infinitive verb patterns, household<\/p>\n","protected":false},"author":1,"featured_media":735,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"colormag_page_layout":"default_layout","footnotes":""},"categories":[37],"tags":[],"class_list":["post-734","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-b1"],"_links":{"self":[{"href":"https:\/\/i-cte.org\/robot\/wp-json\/wp\/v2\/posts\/734","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=734"}],"version-history":[{"count":1,"href":"https:\/\/i-cte.org\/robot\/wp-json\/wp\/v2\/posts\/734\/revisions"}],"predecessor-version":[{"id":736,"href":"https:\/\/i-cte.org\/robot\/wp-json\/wp\/v2\/posts\/734\/revisions\/736"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/i-cte.org\/robot\/wp-json\/wp\/v2\/media\/735"}],"wp:attachment":[{"href":"https:\/\/i-cte.org\/robot\/wp-json\/wp\/v2\/media?parent=734"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/i-cte.org\/robot\/wp-json\/wp\/v2\/categories?post=734"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/i-cte.org\/robot\/wp-json\/wp\/v2\/tags?post=734"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}