{"id":878,"date":"2026-03-12T09:09:35","date_gmt":"2026-03-12T09:09:35","guid":{"rendered":"https:\/\/i-cte.org\/robot\/?p=878"},"modified":"2026-03-12T09:09:35","modified_gmt":"2026-03-12T09:09:35","slug":"spanish-interaction-school","status":"publish","type":"post","link":"https:\/\/i-cte.org\/robot\/spanish-interaction-school\/","title":{"rendered":"Spanish: Interaction &#8211; School"},"content":{"rendered":"\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\" \/>\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" \/>\n  <title>Learn Spanish: School Q&#038;A Practice<\/title>\n  <style>\n    * { box-sizing: border-box; }\n\n    body {\n      font-family: Arial, sans-serif;\n      background-color: #f4f6f8;\n      margin: 0;\n      padding: 0;\n      display: flex;\n      flex-direction: column;\n      min-height: 100vh;\n    }\n\n    .menu {\n      width: 100%;\n      background-color: #28a745;\n      padding: 10px;\n      text-align: center;\n      box-shadow: 0 2px 5px rgba(0,0,0,0.1);\n      margin-bottom: 10px;\n      overflow-x: auto;\n      white-space: nowrap;\n    }\n\n    .menu a {\n      color: #fff;\n      text-decoration: none;\n      margin: 0 8px;\n      font-weight: bold;\n      font-size: 14px;\n      display: inline-block;\n      cursor: pointer;\n      padding: 5px 8px;\n      border-radius: 6px;\n    }\n\n    .menu a.active {\n      background: #fff;\n      color: #28a745;\n    }\n\n    .menu a:hover,\n    .menu a:focus {\n      text-decoration: underline;\n      outline: 2px dashed #fff;\n      outline-offset: 4px;\n    }\n\n    .container {\n      display: flex;\n      flex-direction: column;\n      align-items: center;\n      padding: 10px;\n      flex: 1 0 auto;\n      width: 100%;\n    }\n\n    .image-chat-wrapper {\n      display: flex;\n      flex-direction: column;\n      width: 100%;\n      max-width: 1120px;\n      flex: 1;\n      gap: 16px;\n    }\n\n    .image-container {\n      flex: 1;\n      text-align: center;\n      margin-bottom: 15px;\n      background: #ffffff;\n      border-radius: 15px;\n      box-shadow: 0 0 8px rgba(0,0,0,0.1);\n      padding: 14px;\n    }\n\n    .sentence-text {\n      margin: 10px 0;\n      font-weight: bold;\n      color: #333;\n      font-size: 16px;\n    }\n\n    .word-box {\n      margin-top: 10px;\n      padding: 10px;\n      background-color: #fff;\n      border: 2px solid #28a745;\n      border-radius: 8px;\n      box-shadow: 0 0 8px rgba(0,0,0,0.1);\n      font-size: 15px;\n      font-weight: bold;\n      color: #28a745;\n      text-align: left;\n      max-height: 300px;\n      overflow-y: auto;\n      line-height: 1.7;\n    }\n\n    .chat-container {\n      background-color: #28a745;\n      border-radius: 15px;\n      box-shadow: 0 0 8px rgba(0,0,0,0.1);\n      overflow: hidden;\n      display: flex;\n      flex-direction: column;\n      max-height: 760px;\n      flex: 1;\n    }\n\n    .chat-header {\n      background-color: #1e7e34;\n      color: #fff;\n      padding: 12px;\n      text-align: center;\n      border-bottom: 1px solid #155724;\n      position: relative;\n    }\n\n    .chat-header h2 {\n      margin: 0;\n      font-size: 18px;\n    }\n\n    .chat-header .loader {\n      position: absolute;\n      right: 20px;\n      top: 50%;\n      transform: translateY(-50%);\n      display: none;\n    }\n\n    .chat-messages {\n      padding: 12px;\n      overflow-y: auto;\n      flex: 1;\n      background-color: #fff;\n      max-height: 470px;\n    }\n\n    .message {\n      margin-bottom: 10px;\n      padding: 10px;\n      border-radius: 6px;\n      font-size: 14px;\n      line-height: 1.5;\n      white-space: pre-line;\n    }\n\n    .user-message {\n      background-color: #ffc107;\n      color: #fff;\n      text-align: right;\n    }\n\n    .bot-message {\n      background-color: #17a2b8;\n      color: #fff;\n      text-align: left;\n    }\n\n    .chat-input {\n      display: flex;\n      align-items: center;\n      background-color: #c3e6cb;\n      padding: 10px;\n      justify-content: space-between;\n      flex-wrap: wrap;\n      gap: 8px;\n    }\n\n    .send-button, .stop-button {\n      background-color: #17a2b8;\n      color: #fff;\n      font-weight: bold;\n      border: none;\n      border-radius: 5px;\n      padding: 12px 16px;\n      cursor: pointer;\n      transition: background-color 0.3s;\n      flex: 1;\n      margin: 4px;\n      max-width: 170px;\n      font-size: 16px;\n    }\n\n    .stop-button { background-color: #dc3545; }\n\n    .send-button:hover,\n    .stop-button:hover,\n    .send-button:focus,\n    .stop-button:focus {\n      background-color: #218838;\n      outline: none;\n    }\n\n    .voice-selection {\n      margin: 10px 0;\n      width: 100%;\n      max-width: 320px;\n    }\n\n    .voice-selection label {\n      display: block;\n      margin-bottom: 5px;\n      font-weight: bold;\n      color: #333;\n    }\n\n    .voice-selection select {\n      width: 100%;\n      padding: 8px;\n      border-radius: 5px;\n      border: 1px solid #ccc;\n      font-size: 14px;\n    }\n\n    .loader {\n      border: 4px solid #f3f3f3;\n      border-top: 4px solid #17a2b8;\n      border-radius: 50%;\n      width: 20px;\n      height: 20px;\n      animation: spin 1s linear infinite;\n      display: inline-block;\n      margin-left: 10px;\n    }\n\n    @keyframes spin {\n      0% { transform: translateY(-50%) rotate(0deg); }\n      100% { transform: translateY(-50%) rotate(360deg); }\n    }\n\n    .face-panel {\n      width: 100%;\n      min-height: 330px;\n      display: flex;\n      flex-direction: column;\n      align-items: center;\n      justify-content: center;\n      background: radial-gradient(circle at center, #111 0%, #000 70%);\n      border-radius: 15px;\n      padding: 16px 10px;\n      overflow: hidden;\n      position: relative;\n    }\n\n    .speech-bubble {\n      position: relative;\n      background: white;\n      color: #111;\n      border-radius: 20px;\n      padding: 12px 18px;\n      max-width: 340px;\n      opacity: 0;\n      transform: translateY(10px) scale(0.92);\n      transition: all 0.25s ease;\n      box-shadow: 0 10px 30px rgba(255,255,255,0.08);\n      margin-bottom: 12px;\n      font-weight: 600;\n    }\n\n    .speech-bubble.visible {\n      opacity: 1;\n      transform: translateY(0) scale(1);\n    }\n\n    .speech-bubble::after {\n      content: '';\n      position: absolute;\n      bottom: -15px;\n      left: 50%;\n      transform: translateX(-50%);\n      border: 10px solid transparent;\n      border-top-color: white;\n    }\n\n    .face-container {\n      filter: drop-shadow(0 0 45px rgba(255,255,255,0.08));\n      transition: transform 0.15s ease;\n      will-change: transform;\n    }\n\n    .face-shell {\n      transition: transform 0.2s ease;\n      transform-origin: 150px 150px;\n    }\n\n    .eye-white,\n    .pupil,\n    .eyebrow,\n    .mouth-path,\n    .cheek,\n    .tear,\n    .eyelid,\n    .sparkle {\n      transition: all 0.18s ease;\n    }\n\n    @media (orientation: portrait) {\n      .image-chat-wrapper { flex-direction: column; }\n      .image-container, .chat-container { width: 100%; max-width: 100%; }\n    }\n\n    @media (orientation: landscape) and (min-width: 700px) {\n      .image-chat-wrapper {\n        flex-direction: row;\n        justify-content: space-between;\n        gap: 20px;\n      }\n\n      .image-container, .chat-container {\n        width: 48%;\n        max-width: 48%;\n      }\n\n      .word-box { max-height: 240px; }\n      .chat-header h2 { font-size: 20px; }\n      .message { font-size: 15px; }\n      .send-button, .stop-button {\n        font-size: 18px;\n        padding: 14px 20px;\n        max-width: 200px;\n      }\n    }\n\n    @media (max-width: 768px) {\n      .chat-header h2 { font-size: 16px; }\n      .message { font-size: 14px; }\n      .send-button, .stop-button {\n        font-size: 16px;\n        padding: 12px 16px;\n        max-width: 150px;\n      }\n      .word-box { font-size: 15px; }\n      .voice-selection select { font-size: 14px; }\n    }\n  <\/style>\n<\/head>\n<body>\n  <div class=\"menu\">\n    <a href=\"#\" class=\"menu-link active\" data-section=\"classroom\">In class<\/a>\n    <a href=\"#\" class=\"menu-link\" data-section=\"supplies\">School supplies<\/a>\n    <a href=\"#\" class=\"menu-link\" data-section=\"help\">Asking for help<\/a>\n    <a href=\"#\" class=\"menu-link\" data-section=\"teacher\">Teacher-student talk<\/a>\n    <a href=\"#\" class=\"menu-link\" data-section=\"homework\">Homework time<\/a>\n    <a href=\"#\" class=\"menu-link\" data-section=\"library\">Library language<\/a>\n    <a href=\"#\" class=\"menu-link\" data-section=\"meeting\">Meeting people at school<\/a>\n    <a href=\"#\" class=\"menu-link\" data-section=\"study\">Study habits<\/a>\n  <\/div>\n\n  <div class=\"container\">\n    <div class=\"image-chat-wrapper\">\n      <div class=\"image-container\">\n        <div class=\"face-panel\">\n          <div id=\"face-speech-bubble\" class=\"speech-bubble\">\n            <p id=\"face-speech-text\"><\/p>\n          <\/div>\n\n          <div class=\"face-container\" id=\"face-container\">\n            <svg width=\"300\" height=\"300\" viewBox=\"0 0 300 300\" id=\"face-svg\" aria-label=\"Expressive face\">\n              <defs>\n                <radialGradient id=\"faceGlow\" cx=\"50%\" cy=\"40%\" r=\"70%\">\n                  <stop offset=\"0%\" stop-color=\"rgba(255,255,255,0.12)\" \/>\n                  <stop offset=\"100%\" stop-color=\"rgba(255,255,255,0.02)\" \/>\n                <\/radialGradient>\n                <radialGradient id=\"cheekGlow\" cx=\"50%\" cy=\"50%\" r=\"60%\">\n                  <stop offset=\"0%\" stop-color=\"rgba(255,160,160,0.8)\" \/>\n                  <stop offset=\"100%\" stop-color=\"rgba(255,160,160,0)\" \/>\n                <\/radialGradient>\n              <\/defs>\n\n              <g id=\"face-shell\" class=\"face-shell\">\n                <ellipse cx=\"150\" cy=\"150\" rx=\"120\" ry=\"140\" fill=\"url(#faceGlow)\" stroke=\"rgba(255,255,255,0.15)\" stroke-width=\"2\"\/>\n                <path id=\"left-eyebrow\" class=\"eyebrow\" d=\"M 60 80 Q 90 75 120 80\" fill=\"none\" stroke=\"white\" stroke-width=\"4\" stroke-linecap=\"round\"\/>\n                <path id=\"right-eyebrow\" class=\"eyebrow\" d=\"M 180 80 Q 210 75 240 80\" fill=\"none\" stroke=\"white\" stroke-width=\"4\" stroke-linecap=\"round\"\/>\n                <ellipse id=\"left-blush\" class=\"cheek\" cx=\"70\" cy=\"165\" rx=\"24\" ry=\"12\" fill=\"url(#cheekGlow)\" opacity=\"0\"\/>\n                <ellipse id=\"right-blush\" class=\"cheek\" cx=\"230\" cy=\"165\" rx=\"24\" ry=\"12\" fill=\"url(#cheekGlow)\" opacity=\"0\"\/>\n\n                <g id=\"left-eye-group\">\n                  <ellipse id=\"left-eye-white\" class=\"eye-white\" cx=\"90\" cy=\"110\" rx=\"30\" ry=\"24\" fill=\"white\"\/>\n                  <ellipse id=\"left-eye-lid\" class=\"eyelid\" cx=\"90\" cy=\"110\" rx=\"30\" ry=\"0\" fill=\"black\"\/>\n                  <circle id=\"left-pupil\" class=\"pupil\" cx=\"90\" cy=\"110\" r=\"11.5\" fill=\"black\"\/>\n                  <circle id=\"left-sparkle\" class=\"sparkle\" cx=\"96\" cy=\"104\" r=\"4.2\" fill=\"white\" opacity=\"0.95\"\/>\n                <\/g>\n\n                <g id=\"right-eye-group\">\n                  <ellipse id=\"right-eye-white\" class=\"eye-white\" cx=\"210\" cy=\"110\" rx=\"30\" ry=\"24\" fill=\"white\"\/>\n                  <ellipse id=\"right-eye-lid\" class=\"eyelid\" cx=\"210\" cy=\"110\" rx=\"30\" ry=\"0\" fill=\"black\"\/>\n                  <circle id=\"right-pupil\" class=\"pupil\" cx=\"210\" cy=\"110\" r=\"11.5\" fill=\"black\"\/>\n                  <circle id=\"right-sparkle\" class=\"sparkle\" cx=\"216\" cy=\"104\" r=\"4.2\" fill=\"white\" opacity=\"0.95\"\/>\n                <\/g>\n\n                <path id=\"mouth\" class=\"mouth-path\" d=\"M 100 220 Q 150 232 200 220\" fill=\"none\" stroke=\"white\" stroke-width=\"5\" stroke-linecap=\"round\"\/>\n                <ellipse id=\"mouth-inner\" cx=\"150\" cy=\"225\" rx=\"0\" ry=\"0\" fill=\"rgba(120,0,0,0.75)\" opacity=\"0\"\/>\n                <rect id=\"teeth\" x=\"122\" y=\"220\" width=\"56\" height=\"10\" rx=\"4\" fill=\"white\" opacity=\"0\"\/>\n                <path id=\"left-tear\" class=\"tear\" d=\"M 75 140 Q 69 160 75 171 Q 81 160 75 140\" fill=\"rgba(100,200,255,0)\" \/>\n                <path id=\"right-tear\" class=\"tear\" d=\"M 225 140 Q 219 160 225 171 Q 231 160 225 140\" fill=\"rgba(100,200,255,0)\" \/>\n              <\/g>\n            <\/svg>\n          <\/div>\n        <\/div>\n\n        <div class=\"sentence-text\">\n          Listen to the question and answer in Spanish.\n        <\/div>\n        <div id=\"word-box\" class=\"word-box\"><\/div>\n      <\/div>\n\n      <div class=\"chat-container\">\n        <div class=\"chat-header\">\n          <h2 id=\"section-title\">In class<\/h2>\n          <div class=\"loader\" id=\"synthesis-loader\"><\/div>\n        <\/div>\n        <div class=\"chat-messages\" id=\"chat-messages\"><\/div>\n        <div class=\"chat-input\">\n          <div class=\"voice-selection\">\n            <label for=\"spanish-voice-select\">Choose Spanish Voice:<\/label>\n            <select id=\"spanish-voice-select\" aria-label=\"Select Spanish Voice\">\n              <option value=\"\">Loading Spanish voices&#8230;<\/option>\n            <\/select>\n          <\/div>\n          <button id=\"start-btn\" class=\"send-button\">Start<\/button>\n          <button id=\"stop-btn\" class=\"stop-button\">Stop<\/button>\n        <\/div>\n      <\/div>\n    <\/div>\n  <\/div>\n\n  <div class=\"menu\">\n    <a href=\"#\" class=\"menu-link active\" data-section=\"classroom\">In class<\/a>\n    <a href=\"#\" class=\"menu-link\" data-section=\"supplies\">School supplies<\/a>\n    <a href=\"#\" class=\"menu-link\" data-section=\"help\">Asking for help<\/a>\n    <a href=\"#\" class=\"menu-link\" data-section=\"teacher\">Teacher-student talk<\/a>\n    <a href=\"#\" class=\"menu-link\" data-section=\"homework\">Homework time<\/a>\n    <a href=\"#\" class=\"menu-link\" data-section=\"library\">Library language<\/a>\n    <a href=\"#\" class=\"menu-link\" data-section=\"meeting\">Meeting people at school<\/a>\n    <a href=\"#\" class=\"menu-link\" data-section=\"study\">Study habits<\/a>\n  <\/div>\n\n  <script>\n    const sectionData = {\n      classroom: {\n        title: \"In class\",\n        intro: \"Hoy vamos a practicar preguntas sobre la clase.\",\n        items: [\n          {\n            questionEs: \"\u00bfQu\u00e9 haces en clase?\",\n            questionEn: \"What do you do in class?\",\n            suggestedAnswer: \"Escucho al profesor.\",\n            keywords: [\"escucho\", \"profesor\", \"leo\", \"escribo\", \"clase\", \"estudio\"]\n          },\n          {\n            questionEs: \"\u00bfLees en voz alta?\",\n            questionEn: \"Do you read aloud?\",\n            suggestedAnswer: \"S\u00ed, leo en voz alta.\",\n            keywords: [\"s\u00ed\", \"si\", \"leo\", \"voz\", \"alta\", \"no\"]\n          },\n          {\n            questionEs: \"\u00bfMiras la pizarra?\",\n            questionEn: \"Do you look at the board?\",\n            suggestedAnswer: \"S\u00ed, miro la pizarra.\",\n            keywords: [\"s\u00ed\", \"si\", \"miro\", \"pizarra\", \"no\"]\n          },\n          {\n            questionEs: \"\u00bfEscribes en clase hoy?\",\n            questionEn: \"Do you write in class today?\",\n            suggestedAnswer: \"S\u00ed, escribo en clase.\",\n            keywords: [\"s\u00ed\", \"si\", \"escribo\", \"clase\", \"hoy\", \"no\"]\n          }\n        ]\n      },\n      supplies: {\n        title: \"School supplies\",\n        intro: \"Hoy vamos a practicar \u00fatiles escolares.\",\n        items: [\n          {\n            questionEs: \"\u00bfQu\u00e9 tienes en tu mochila?\",\n            questionEn: \"What do you have in your backpack?\",\n            suggestedAnswer: \"Tengo un libro y l\u00e1piz.\",\n            keywords: [\"tengo\", \"libro\", \"l\u00e1piz\", \"lapiz\", \"cuaderno\", \"regla\", \"bol\u00edgrafo\", \"boligrafo\"]\n          },\n          {\n            questionEs: \"\u00bfUsas un cuaderno grande?\",\n            questionEn: \"Do you use a big notebook?\",\n            suggestedAnswer: \"S\u00ed, uso un cuaderno grande.\",\n            keywords: [\"s\u00ed\", \"si\", \"uso\", \"cuaderno\", \"grande\", \"no\"]\n          },\n          {\n            questionEs: \"\u00bfNecesitas papel hoy?\",\n            questionEn: \"Do you need paper today?\",\n            suggestedAnswer: \"S\u00ed, necesito papel hoy.\",\n            keywords: [\"s\u00ed\", \"si\", \"necesito\", \"papel\", \"hoy\", \"no\"]\n          },\n          {\n            questionEs: \"\u00bfBuscas tu l\u00e1piz ahora?\",\n            questionEn: \"Are you looking for your pencil now?\",\n            suggestedAnswer: \"S\u00ed, busco mi l\u00e1piz.\",\n            keywords: [\"s\u00ed\", \"si\", \"busco\", \"l\u00e1piz\", \"lapiz\", \"ahora\", \"no\"]\n          }\n        ]\n      },\n      help: {\n        title: \"Asking for help\",\n        intro: \"Hoy vamos a practicar c\u00f3mo pedir ayuda.\",\n        items: [\n          {\n            questionEs: \"\u00bfNecesitas ayuda ahora?\",\n            questionEn: \"Do you need help now?\",\n            suggestedAnswer: \"S\u00ed, necesito ayuda ahora.\",\n            keywords: [\"s\u00ed\", \"si\", \"necesito\", \"ayuda\", \"ahora\", \"no\"]\n          },\n          {\n            questionEs: \"\u00bfEntiendes esta pregunta?\",\n            questionEn: \"Do you understand this question?\",\n            suggestedAnswer: \"No, no entiendo esta pregunta.\",\n            keywords: [\"no\", \"entiendo\", \"pregunta\", \"s\u00ed\", \"si\"]\n          },\n          {\n            questionEs: \"\u00bfPuedes repetir eso despacio?\",\n            questionEn: \"Can you repeat that slowly?\",\n            suggestedAnswer: \"S\u00ed, puede repetir despacio.\",\n            keywords: [\"s\u00ed\", \"si\", \"repetir\", \"despacio\", \"puede\"]\n          },\n          {\n            questionEs: \"\u00bfPides ayuda al profesor?\",\n            questionEn: \"Do you ask the teacher for help?\",\n            suggestedAnswer: \"S\u00ed, pido ayuda al profesor.\",\n            keywords: [\"s\u00ed\", \"si\", \"pido\", \"ayuda\", \"profesor\", \"no\"]\n          }\n        ]\n      },\n      teacher: {\n        title: \"Teacher-student talk\",\n        intro: \"Hoy vamos a practicar conversaciones con el profesor.\",\n        items: [\n          {\n            questionEs: \"\u00bfTienes una pregunta hoy?\",\n            questionEn: \"Do you have a question today?\",\n            suggestedAnswer: \"S\u00ed, tengo una pregunta.\",\n            keywords: [\"s\u00ed\", \"si\", \"tengo\", \"pregunta\", \"hoy\", \"no\"]\n          },\n          {\n            questionEs: \"\u00bfEntiendes la lecci\u00f3n ahora?\",\n            questionEn: \"Do you understand the lesson now?\",\n            suggestedAnswer: \"S\u00ed, entiendo la lecci\u00f3n.\",\n            keywords: [\"s\u00ed\", \"si\", \"entiendo\", \"lecci\u00f3n\", \"leccion\", \"ahora\", \"no\"]\n          },\n          {\n            questionEs: \"\u00bfDas tu tarea al profesor?\",\n            questionEn: \"Do you give your homework to the teacher?\",\n            suggestedAnswer: \"S\u00ed, doy mi tarea.\",\n            keywords: [\"s\u00ed\", \"si\", \"doy\", \"tarea\", \"profesor\", \"no\"]\n          },\n          {\n            questionEs: \"\u00bfDas gracias por la ayuda?\",\n            questionEn: \"Do you say thank you for the help?\",\n            suggestedAnswer: \"S\u00ed, gracias por su ayuda.\",\n            keywords: [\"s\u00ed\", \"si\", \"gracias\", \"ayuda\", \"no\"]\n          }\n        ]\n      },\n      homework: {\n        title: \"Homework time\",\n        intro: \"Hoy vamos a practicar preguntas sobre la tarea.\",\n        items: [\n          {\n            questionEs: \"\u00bfHaces tu tarea solo?\",\n            questionEn: \"Do you do your homework alone?\",\n            suggestedAnswer: \"S\u00ed, hago mi tarea solo.\",\n            keywords: [\"s\u00ed\", \"si\", \"hago\", \"tarea\", \"solo\", \"no\"]\n          },\n          {\n            questionEs: \"\u00bfLees este texto hoy?\",\n            questionEn: \"Do you read this text today?\",\n            suggestedAnswer: \"S\u00ed, leo este texto.\",\n            keywords: [\"s\u00ed\", \"si\", \"leo\", \"texto\", \"hoy\", \"no\"]\n          },\n          {\n            questionEs: \"\u00bfEscribes respuestas aqu\u00ed?\",\n            questionEn: \"Do you write answers here?\",\n            suggestedAnswer: \"S\u00ed, escribo respuestas aqu\u00ed.\",\n            keywords: [\"s\u00ed\", \"si\", \"escribo\", \"respuestas\", \"aqu\u00ed\", \"aqui\", \"no\"]\n          },\n          {\n            questionEs: \"\u00bfRevisas tu trabajo final?\",\n            questionEn: \"Do you check your final work?\",\n            suggestedAnswer: \"S\u00ed, reviso mi trabajo.\",\n            keywords: [\"s\u00ed\", \"si\", \"reviso\", \"trabajo\", \"final\", \"no\"]\n          }\n        ]\n      },\n      library: {\n        title: \"Library language\",\n        intro: \"Hoy vamos a practicar preguntas sobre la biblioteca.\",\n        items: [\n          {\n            questionEs: \"\u00bfBuscas un libro interesante?\",\n            questionEn: \"Are you looking for an interesting book?\",\n            suggestedAnswer: \"S\u00ed, busco un libro interesante.\",\n            keywords: [\"s\u00ed\", \"si\", \"busco\", \"libro\", \"interesante\", \"no\"]\n          },\n          {\n            questionEs: \"\u00bfLees en silencio aqu\u00ed?\",\n            questionEn: \"Do you read silently here?\",\n            suggestedAnswer: \"S\u00ed, leo en silencio.\",\n            keywords: [\"s\u00ed\", \"si\", \"leo\", \"silencio\", \"aqu\u00ed\", \"aqui\", \"no\"]\n          },\n          {\n            questionEs: \"\u00bfEstudias en la biblioteca?\",\n            questionEn: \"Do you study in the library?\",\n            suggestedAnswer: \"S\u00ed, estudio en biblioteca.\",\n            keywords: [\"s\u00ed\", \"si\", \"estudio\", \"biblioteca\", \"no\"]\n          },\n          {\n            questionEs: \"\u00bfDevuelves el libro ma\u00f1ana?\",\n            questionEn: \"Do you return the book tomorrow?\",\n            suggestedAnswer: \"S\u00ed, devuelvo el libro ma\u00f1ana.\",\n            keywords: [\"s\u00ed\", \"si\", \"devuelvo\", \"libro\", \"ma\u00f1ana\", \"manana\", \"no\"]\n          }\n        ]\n      },\n      meeting: {\n        title: \"Meeting people at school\",\n        intro: \"Hoy vamos a practicar conocer personas en la escuela.\",\n        items: [\n          {\n            questionEs: \"\u00bfC\u00f3mo te llamas?\",\n            questionEn: \"What is your name?\",\n            suggestedAnswer: \"Me llamo Ana.\",\n            keywords: [\"llamo\", \"soy\", \"nombre\"]\n          },\n          {\n            questionEs: \"\u00bfEres nuevo en la escuela?\",\n            questionEn: \"Are you new at school?\",\n            suggestedAnswer: \"S\u00ed, soy nuevo aqu\u00ed.\",\n            keywords: [\"s\u00ed\", \"si\", \"soy\", \"nuevo\", \"escuela\", \"aqu\u00ed\", \"aqui\", \"no\"]\n          },\n          {\n            questionEs: \"\u00bfEstudias aqu\u00ed con amigos?\",\n            questionEn: \"Do you study here with friends?\",\n            suggestedAnswer: \"S\u00ed, estudio con amigos.\",\n            keywords: [\"s\u00ed\", \"si\", \"estudio\", \"amigos\", \"aqu\u00ed\", \"aqui\", \"no\"]\n          },\n          {\n            questionEs: \"\u00bfVas a clase juntos?\",\n            questionEn: \"Do you go to class together?\",\n            suggestedAnswer: \"S\u00ed, vamos a clase juntos.\",\n            keywords: [\"s\u00ed\", \"si\", \"vamos\", \"clase\", \"juntos\", \"no\"]\n          }\n        ]\n      },\n      study: {\n        title: \"Study habits\",\n        intro: \"Hoy vamos a practicar h\u00e1bitos de estudio.\",\n        items: [\n          {\n            questionEs: \"\u00bfEstudias cada d\u00eda?\",\n            questionEn: \"Do you study every day?\",\n            suggestedAnswer: \"S\u00ed, estudio cada d\u00eda.\",\n            keywords: [\"s\u00ed\", \"si\", \"estudio\", \"cada\", \"d\u00eda\", \"dia\", \"no\"]\n          },\n          {\n            questionEs: \"\u00bfLees tus notas siempre?\",\n            questionEn: \"Do you always read your notes?\",\n            suggestedAnswer: \"S\u00ed, leo mis notas.\",\n            keywords: [\"s\u00ed\", \"si\", \"leo\", \"notas\", \"siempre\", \"no\"]\n          },\n          {\n            questionEs: \"\u00bfPracticas por la noche?\",\n            questionEn: \"Do you practice at night?\",\n            suggestedAnswer: \"S\u00ed, practico por noche.\",\n            keywords: [\"s\u00ed\", \"si\", \"practico\", \"noche\", \"no\"]\n          },\n          {\n            questionEs: \"\u00bfAprendes palabras nuevas r\u00e1pido?\",\n            questionEn: \"Do you learn new words quickly?\",\n            suggestedAnswer: \"S\u00ed, aprendo palabras nuevas.\",\n            keywords: [\"s\u00ed\", \"si\", \"aprendo\", \"palabras\", \"nuevas\", \"r\u00e1pido\", \"rapido\", \"no\"]\n          }\n        ]\n      }\n    };\n\n    const positiveFeedback = [\n      \"Muy bien. Tu respuesta es relevante.\",\n      \"Excelente. Tu respuesta es clara.\",\n      \"Muy bien hecho. Respondiste correctamente.\",\n      \"Buen trabajo. Tu idea coincide con la pregunta.\",\n      \"Muy bien. Seguiste el tema correctamente.\"\n    ];\n\n    const partialFeedback = [\n      \"Bien. Tu respuesta tiene una buena idea, pero puedes a\u00f1adir m\u00e1s detalles.\",\n      \"Buen intento. Trata de usar una respuesta m\u00e1s completa.\",\n      \"Tu respuesta va en la direcci\u00f3n correcta. A\u00f1ade una palabra clave m\u00e1s.\",\n      \"Bien. Intenta responder con una frase m\u00e1s clara.\",\n      \"Buen trabajo. Puedes mejorar con m\u00e1s informaci\u00f3n.\"\n    ];\n\n    const constructiveFeedback = [\n      \"Intenta responder con palabras relacionadas con la pregunta.\",\n      \"Escucha la pregunta otra vez y usa una respuesta sencilla en espa\u00f1ol.\",\n      \"Trata de incluir palabras clave importantes en tu respuesta.\",\n      \"Tu respuesta necesita m\u00e1s relaci\u00f3n con la pregunta.\",\n      \"Intenta usar una oraci\u00f3n corta y clara en espa\u00f1ol.\"\n    ];\n\n    const stopKeywords = [\"goodbye\", \"bye\", \"stop\", \"end lesson\", \"adi\u00f3s\", \"adios\"];\n\n    let currentSection = \"classroom\";\n    let lessons = sectionData[currentSection].items;\n    let currentLessonIndex = 0;\n    let isLessonActive = false;\n    let speechRecognitionActive = false;\n    let pendingNextQuestionTimeout = null;\n    let retryCount = 0;\n    const maxRetriesPerQuestion = 2;\n\n    const speechSynthesisSupported = 'speechSynthesis' in window;\n    const SpeechRecognitionClass = window.SpeechRecognition || window.webkitSpeechRecognition;\n    const speechRecognitionSupported = !!SpeechRecognitionClass;\n\n    let voices = [];\n    let spanishVoices = [];\n    let selectedSpanishVoice = null;\n    let recognition = null;\n    let micAccessGranted = false;\n    let currentListeningItem = null;\n\n    let currentEmotion = 'neutral';\n    let isFaceTalking = false;\n    let faceTalkTimer = null;\n    let faceBubbleTimer = null;\n    let blinkTimer = null;\n    let saccadeTimer = null;\n    let breatheRAF = null;\n\n    const faceContainer = document.getElementById('face-container');\n    const faceShell = document.getElementById('face-shell');\n    const mouth = document.getElementById('mouth');\n    const mouthInner = document.getElementById('mouth-inner');\n    const teeth = document.getElementById('teeth');\n    const leftEyeWhite = document.getElementById('left-eye-white');\n    const rightEyeWhite = document.getElementById('right-eye-white');\n    const leftLid = document.getElementById('left-eye-lid');\n    const rightLid = document.getElementById('right-eye-lid');\n    const leftPupil = document.getElementById('left-pupil');\n    const rightPupil = document.getElementById('right-pupil');\n    const leftSparkle = document.getElementById('left-sparkle');\n    const rightSparkle = document.getElementById('right-sparkle');\n    const leftEyebrow = document.getElementById('left-eyebrow');\n    const rightEyebrow = document.getElementById('right-eyebrow');\n    const leftBlush = document.getElementById('left-blush');\n    const rightBlush = document.getElementById('right-blush');\n    const leftTear = document.getElementById('left-tear');\n    const rightTear = document.getElementById('right-tear');\n    const faceSpeechBubble = document.getElementById('face-speech-bubble');\n    const faceSpeechText = document.getElementById('face-speech-text');\n\n    function initialize() {\n      loadVoices();\n      setFaceEmotion('neutral');\n      scheduleBlink();\n      scheduleSaccade();\n      startFaceBreathing();\n      bindSectionMenus();\n      createRecognitionInstance();\n      updateSectionUI();\n      clearWordBox();\n      addSectionHelp();\n\n      appendMessage(\"Click Start to begin the Spanish speaking practice.\", \"bot\");\n\n      document.getElementById('start-btn').onclick = async function() {\n        if (isLessonActive) return;\n        if (!speechSynthesisSupported || !speechRecognitionSupported) {\n          appendMessage(\"Your browser needs speech synthesis and speech recognition.\", \"bot\");\n          return;\n        }\n\n        clearChat();\n        clearWordBox();\n        addSectionHelp();\n        stopAllAudioAndRecognition();\n        clearPendingTimeout();\n\n        const micOk = await requestMicrophoneOnce();\n        if (!micOk) {\n          appendMessage(\"Microphone access is required for speaking practice.\", \"bot\");\n          return;\n        }\n\n        isLessonActive = true;\n        currentLessonIndex = 0;\n        retryCount = 0;\n\n        appendMessage(sectionData[currentSection].intro, 'bot');\n        faceSpeak(sectionData[currentSection].intro, \"happy\");\n        showSynthesisLoader(true);\n\n        speakSpanish(sectionData[currentSection].intro).then(() => {\n          showSynthesisLoader(false);\n          startLesson();\n        });\n      };\n\n      document.getElementById('stop-btn').onclick = function() {\n        endLesson(true);\n      };\n    }\n\n    function setFaceEmotion(emotion) {\n      const presets = {\n        neutral: {\n          mouth: 'M 100 220 Q 150 232 200 220',\n          leftEyebrow: 'M 60 80 Q 90 75 120 80',\n          rightEyebrow: 'M 180 80 Q 210 75 240 80',\n          eyeRY: 24,\n          blush: 0,\n          tears: 0,\n          teeth: 0,\n          innerOpacity: 0,\n          innerRx: 0,\n          innerRy: 0\n        },\n        happy: {\n          mouth: 'M 92 212 Q 150 278 208 212',\n          leftEyebrow: 'M 60 75 Q 90 66 120 75',\n          rightEyebrow: 'M 180 75 Q 210 66 240 75',\n          eyeRY: 17,\n          blush: 0.48,\n          tears: 0,\n          teeth: 0.92,\n          innerOpacity: 0.25,\n          innerRx: 24,\n          innerRy: 8\n        },\n        sad: {\n          mouth: 'M 112 240 Q 150 203 188 240',\n          leftEyebrow: 'M 68 72 Q 90 88 120 76',\n          rightEyebrow: 'M 180 76 Q 210 88 232 72',\n          eyeRY: 15,\n          blush: 0,\n          tears: 0.78,\n          teeth: 0,\n          innerOpacity: 0,\n          innerRx: 0,\n          innerRy: 0\n        },\n        confused: {\n          mouth: 'M 110 224 Q 140 230 160 221 Q 182 236 190 226',\n          leftEyebrow: 'M 60 86 Q 90 68 120 80',\n          rightEyebrow: 'M 180 70 Q 210 86 240 76',\n          eyeRY: 22,\n          blush: 0,\n          tears: 0,\n          teeth: 0,\n          innerOpacity: 0,\n          innerRx: 0,\n          innerRy: 0\n        }\n      };\n\n      const preset = presets[emotion] || presets.neutral;\n      currentEmotion = emotion;\n      mouth.setAttribute('d', preset.mouth);\n      leftEyebrow.setAttribute('d', preset.leftEyebrow);\n      rightEyebrow.setAttribute('d', preset.rightEyebrow);\n      leftEyeWhite.setAttribute('ry', preset.eyeRY);\n      rightEyeWhite.setAttribute('ry', preset.eyeRY);\n      leftBlush.setAttribute('opacity', preset.blush);\n      rightBlush.setAttribute('opacity', preset.blush);\n      leftTear.setAttribute('fill', `rgba(100,200,255,${preset.tears})`);\n      rightTear.setAttribute('fill', `rgba(100,200,255,${preset.tears})`);\n      teeth.setAttribute('opacity', preset.teeth);\n      mouthInner.setAttribute('opacity', preset.innerOpacity);\n      mouthInner.setAttribute('rx', preset.innerRx);\n      mouthInner.setAttribute('ry', preset.innerRy);\n    }\n\n    function blinkFace(duration = 110) {\n      const currentL = parseFloat(leftEyeWhite.getAttribute('ry'));\n      const currentR = parseFloat(rightEyeWhite.getAttribute('ry'));\n      leftLid.setAttribute('ry', currentL + 1);\n      rightLid.setAttribute('ry', currentR + 1);\n      setTimeout(() => {\n        leftLid.setAttribute('ry', 0);\n        rightLid.setAttribute('ry', 0);\n      }, duration);\n    }\n\n    function scheduleBlink() {\n      clearTimeout(blinkTimer);\n      const next = 1500 + Math.random() * 3500;\n      blinkTimer = setTimeout(() => {\n        blinkFace(90 + Math.random() * 80);\n        scheduleBlink();\n      }, next);\n    }\n\n    function idleSaccade() {\n      if (isFaceTalking) return;\n      const dx = (Math.random() * 2 - 1) * 4.5;\n      const dy = (Math.random() * 2 - 1) * 3.2;\n      leftPupil.setAttribute('cx', 90 + dx);\n      leftPupil.setAttribute('cy', 110 + dy);\n      rightPupil.setAttribute('cx', 210 + dx);\n      rightPupil.setAttribute('cy', 110 + dy);\n      leftSparkle.setAttribute('cx', 96 + dx * 0.6);\n      leftSparkle.setAttribute('cy', 104 + dy * 0.6);\n      rightSparkle.setAttribute('cx', 216 + dx * 0.6);\n      rightSparkle.setAttribute('cy', 104 + dy * 0.6);\n    }\n\n    function scheduleSaccade() {\n      clearTimeout(saccadeTimer);\n      const next = 900 + Math.random() * 1800;\n      saccadeTimer = setTimeout(() => {\n        idleSaccade();\n        scheduleSaccade();\n      }, next);\n    }\n\n    function startFaceBreathing() {\n      let t0 = performance.now();\n      function frame(now) {\n        const t = (now - t0) \/ 1000;\n        const breathe = Math.sin(t * 1.8) * 1.8;\n        const sway = Math.sin(t * 0.9) * 1.4;\n        const tilt = Math.sin(t * 0.75) * 0.8;\n        if (!isFaceTalking) {\n          faceShell.setAttribute(\n            'transform',\n            `translate(${sway.toFixed(2)}, ${breathe.toFixed(2)}) rotate(${tilt.toFixed(2)} 150 150)`\n          );\n        }\n        breatheRAF = requestAnimationFrame(frame);\n      }\n      cancelAnimationFrame(breatheRAF);\n      breatheRAF = requestAnimationFrame(frame);\n    }\n\n    function showFaceBubble(text, duration) {\n      faceSpeechText.textContent = text;\n      faceSpeechBubble.classList.add('visible');\n      clearTimeout(faceBubbleTimer);\n      faceBubbleTimer = setTimeout(() => {\n        faceSpeechBubble.classList.remove('visible');\n      }, duration + 600);\n    }\n\n    function stopFaceTalking() {\n      isFaceTalking = false;\n      clearInterval(faceTalkTimer);\n      faceTalkTimer = null;\n      setFaceEmotion(currentEmotion);\n    }\n\n    function talkingFrame(emotion) {\n      const shapes = {\n        neutral: [\n          { d: 'M 102 220 Q 150 240 198 220', rx: 14, ry: 7, teeth: 0.1, inner: 0.25 },\n          { d: 'M 96 214 Q 150 262 204 214', rx: 22, ry: 11, teeth: 0.28, inner: 0.45 }\n        ],\n        happy: [\n          { d: 'M 92 212 Q 150 280 208 212', rx: 24, ry: 10, teeth: 0.9, inner: 0.35 },\n          { d: 'M 96 216 Q 150 266 204 216', rx: 18, ry: 8, teeth: 0.75, inner: 0.28 }\n        ],\n        sad: [\n          { d: 'M 112 238 Q 150 212 188 238', rx: 10, ry: 4, teeth: 0, inner: 0.1 }\n        ],\n        confused: [\n          { d: 'M 110 224 Q 140 230 160 221 Q 182 236 190 226', rx: 10, ry: 4, teeth: 0, inner: 0.1 }\n        ]\n      };\n\n      const list = shapes[emotion] || shapes.neutral;\n      const chosen = list[Math.floor(Math.random() * list.length)];\n      mouth.setAttribute('d', chosen.d);\n      mouthInner.setAttribute('opacity', chosen.inner);\n      mouthInner.setAttribute('rx', chosen.rx);\n      mouthInner.setAttribute('ry', chosen.ry);\n      teeth.setAttribute('opacity', chosen.teeth);\n    }\n\n    function faceSpeak(text, emotion = \"neutral\", durationHint = null) {\n      const clean = (text || \"\").trim();\n      if (!clean) return;\n      clearInterval(faceTalkTimer);\n      isFaceTalking = true;\n      setFaceEmotion(emotion);\n      const duration = durationHint || Math.max(1600, clean.length * 70);\n      showFaceBubble(clean, duration);\n      faceTalkTimer = setInterval(() => talkingFrame(emotion), 120);\n      setTimeout(() => stopFaceTalking(), duration);\n    }\n\n    function bindSectionMenus() {\n      document.querySelectorAll('.menu-link').forEach(link => {\n        link.addEventListener('click', function(e) {\n          e.preventDefault();\n          switchSection(this.dataset.section);\n        });\n      });\n    }\n\n    function switchSection(section) {\n      if (!sectionData[section]) return;\n      stopAllAudioAndRecognition();\n      isLessonActive = false;\n      currentListeningItem = null;\n      currentSection = section;\n      lessons = sectionData[currentSection].items;\n      currentLessonIndex = 0;\n      retryCount = 0;\n      clearChat();\n      clearWordBox();\n      updateSectionUI();\n      addSectionHelp();\n      appendMessage(`Section changed to ${sectionData[currentSection].title}. Click Start to begin.`, 'bot');\n    }\n\n    function updateSectionUI() {\n      document.getElementById('section-title').textContent = sectionData[currentSection].title;\n      document.querySelectorAll('.menu-link').forEach(link => {\n        link.classList.toggle('active', link.dataset.section === currentSection);\n      });\n    }\n\n    function addSectionHelp() {\n      addSentenceToBox(`Section: ${sectionData[currentSection].title}`);\n      addSentenceToBox(`Answer the questions in Spanish.`);\n      addSentenceToBox(`Use simple Spanish words related to school.`);\n      addSentenceToBox(`--------------------`);\n    }\n\n    async function requestMicrophoneOnce() {\n      if (micAccessGranted) return true;\n      if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {\n        appendMessage(\"Your browser does not support microphone access.\", \"bot\");\n        return false;\n      }\n      try {\n        const stream = await navigator.mediaDevices.getUserMedia({ audio: true });\n        stream.getTracks().forEach(track => track.stop());\n        micAccessGranted = true;\n        return true;\n      } catch (error) {\n        appendMessage(\"Microphone access was blocked. Please allow microphone access and try again.\", \"bot\");\n        faceSpeak(\"Micr\u00f3fono bloqueado.\", \"sad\");\n        return false;\n      }\n    }\n\n    function createRecognitionInstance() {\n      if (!speechRecognitionSupported) return;\n\n      recognition = new SpeechRecognitionClass();\n      recognition.lang = 'es-ES';\n      recognition.interimResults = false;\n      recognition.continuous = false;\n      recognition.maxAlternatives = 1;\n\n      recognition.onresult = function(event) {\n        if (!isLessonActive || !speechRecognitionActive || !currentListeningItem) return;\n\n        const transcript = event.results[0][0].transcript.trim();\n        const formattedInput = formatSentence(transcript);\n\n        speechRecognitionActive = false;\n        showRecognitionLoader(false);\n        appendMessage(formattedInput, 'user');\n\n        if (checkStopKeywords(formattedInput.toLowerCase())) {\n          endLesson(true);\n          return;\n        }\n\n        const feedback = analyzeResponse(formattedInput, currentListeningItem.keywords);\n        appendMessage(feedback.message, 'bot');\n        faceSpeak(feedback.shortFaceText, feedback.emotion);\n        showSynthesisLoader(true);\n\n        speakSpanish(feedback.message).then(() => {\n          showSynthesisLoader(false);\n          if (!isLessonActive) return;\n          currentLessonIndex++;\n          clearPendingTimeout();\n          pendingNextQuestionTimeout = setTimeout(() => startLesson(), 1600);\n        });\n      };\n\n      recognition.onspeechend = function() {\n        if (speechRecognitionActive && recognition) {\n          try { recognition.stop(); } catch (e) {}\n        }\n      };\n\n      recognition.onerror = function(event) {\n        speechRecognitionActive = false;\n        showRecognitionLoader(false);\n        if (!isLessonActive || !currentListeningItem) return;\n\n        if (event.error === \"not-allowed\") {\n          micAccessGranted = false;\n          const msg = \"Microphone access was blocked. Please allow microphone access and try again.\";\n          appendMessage(msg, \"bot\");\n          faceSpeak(\"Micr\u00f3fono bloqueado.\", \"sad\");\n          return;\n        }\n\n        if (event.error === \"no-speech\") {\n          retryCount++;\n          if (retryCount <= maxRetriesPerQuestion) {\n            const msg = \"No escuch\u00e9 tu respuesta. Intenta otra vez en espa\u00f1ol.\";\n            appendMessage(msg, \"bot\");\n            faceSpeak(\"Intenta otra vez.\", \"confused\");\n            showSynthesisLoader(true);\n            speakSpanish(msg).then(() => {\n              showSynthesisLoader(false);\n              listenUserResponse(currentListeningItem);\n            });\n          } else {\n            const msg = \"Vamos a la siguiente pregunta.\";\n            appendMessage(msg, \"bot\");\n            faceSpeak(\"Siguiente pregunta.\", \"neutral\");\n            showSynthesisLoader(true);\n            speakSpanish(msg).then(() => {\n              showSynthesisLoader(false);\n              currentLessonIndex++;\n              startLesson();\n            });\n          }\n          return;\n        }\n\n        const msg = \"Hubo un error de voz. Intenta responder otra vez.\";\n        appendMessage(msg, \"bot\");\n        faceSpeak(\"Intenta otra vez.\", \"sad\");\n        showSynthesisLoader(true);\n        speakSpanish(msg).then(() => {\n          showSynthesisLoader(false);\n          listenUserResponse(currentListeningItem);\n        });\n      };\n\n      recognition.onend = function() {\n        speechRecognitionActive = false;\n        showRecognitionLoader(false);\n      };\n    }\n\n    function loadVoices() {\n      const fillVoices = () => {\n        voices = window.speechSynthesis.getVoices();\n        spanishVoices = voices.filter(v =>\n          \/^es(-|_)\/i.test(v.lang) || \/spanish|espa\u00f1ol\/i.test(v.name)\n        );\n\n        spanishVoices.sort((a, b) => getSpanishVoicePriority(a) - getSpanishVoicePriority(b));\n        selectedSpanishVoice = spanishVoices[0] || null;\n        populateSpanishVoiceList();\n      };\n\n      fillVoices();\n      if (typeof speechSynthesis !== \"undefined\") {\n        speechSynthesis.onvoiceschanged = fillVoices;\n      }\n    }\n\n    function getSpanishVoicePriority(voice) {\n      const name = voice.name.toLowerCase();\n      if (name.includes(\"google\") && (name.includes(\"espa\u00f1ol\") || name.includes(\"spanish\"))) return 1;\n      if (name.includes(\"microsoft\") && (name.includes(\"espa\u00f1ol\") || name.includes(\"spanish\"))) return 2;\n      if (name.includes(\"spanish\") || name.includes(\"espa\u00f1ol\")) return 3;\n      return 10;\n    }\n\n    function populateSpanishVoiceList() {\n      const voiceSelect = document.getElementById('spanish-voice-select');\n      voiceSelect.innerHTML = '';\n\n      if (!spanishVoices.length) {\n        const option = document.createElement('option');\n        option.value = \"\";\n        option.textContent = \"No Spanish voices available\";\n        voiceSelect.appendChild(option);\n        voiceSelect.disabled = true;\n        selectedSpanishVoice = null;\n        return;\n      }\n\n      spanishVoices.forEach((voice, index) => {\n        const option = document.createElement('option');\n        option.value = String(index);\n        option.textContent = `${voice.name} (${voice.lang})`;\n        voiceSelect.appendChild(option);\n      });\n\n      selectedSpanishVoice = spanishVoices[0];\n      voiceSelect.value = \"0\";\n      voiceSelect.disabled = false;\n\n      voiceSelect.onchange = () => {\n        const index = parseInt(voiceSelect.value, 10);\n        selectedSpanishVoice = spanishVoices[index] || spanishVoices[0];\n      };\n    }\n\n    function startLesson() {\n      if (!isLessonActive) return;\n      if (currentLessonIndex >= lessons.length) {\n        endLesson(false);\n        return;\n      }\n      retryCount = 0;\n      askCurrentQuestion();\n    }\n\n    function askCurrentQuestion() {\n      if (!isLessonActive) return;\n\n      const item = lessons[currentLessonIndex];\n      const questionNumber = currentLessonIndex + 1;\n\n      const displayText = `Question ${questionNumber}\\nSpanish: ${item.questionEs}\\nEnglish: ${item.questionEn}`;\n      appendMessage(displayText, 'bot');\n\n      addSentenceToBox(`Question: ${item.questionEs}`);\n      addSentenceToBox(`Meaning: ${item.questionEn}`);\n      addSentenceToBox(`Sample answer: ${item.suggestedAnswer}`);\n      addSentenceToBox(`--------------------`);\n\n      faceSpeak(item.questionEs, \"neutral\");\n      showSynthesisLoader(true);\n\n      speakSpanish(item.questionEs).then(() => {\n        showSynthesisLoader(false);\n        listenUserResponse(item);\n      });\n    }\n\n    function listenUserResponse(item) {\n      if (!isLessonActive || !recognition) return;\n\n      stopRecognitionOnly();\n      currentListeningItem = item;\n      recognition.lang = 'es-ES';\n      speechRecognitionActive = true;\n      showRecognitionLoader(true);\n      appendMessage(\"Listening... Please answer in Spanish.\", \"bot\");\n      faceSpeak(\"Responde en espa\u00f1ol.\", \"neutral\", 1400);\n\n      try {\n        recognition.start();\n      } catch (err) {\n        speechRecognitionActive = false;\n        showRecognitionLoader(false);\n        appendMessage(\"The microphone could not start. Please try again.\", \"bot\");\n        faceSpeak(\"Intenta otra vez.\", \"sad\");\n      }\n    }\n\n    function analyzeResponse(userInput, keywords) {\n      const input = userInput.toLowerCase();\n      let matchCount = 0;\n\n      keywords.forEach(keyword => {\n        if (input.includes(keyword.toLowerCase())) matchCount++;\n      });\n\n      const wordCount = input.split(\/\\s+\/).filter(Boolean).length;\n\n      if (matchCount >= 2 || (matchCount >= 1 && wordCount >= 4)) {\n        return {\n          message: pickRandom(positiveFeedback),\n          emotion: \"happy\",\n          shortFaceText: \"Muy bien\"\n        };\n      }\n\n      if (matchCount === 1 || wordCount >= 3) {\n        return {\n          message: pickRandom(partialFeedback),\n          emotion: \"neutral\",\n          shortFaceText: \"Bien\"\n        };\n      }\n\n      return {\n        message: pickRandom(constructiveFeedback),\n        emotion: \"confused\",\n        shortFaceText: \"Intenta otra vez\"\n      };\n    }\n\n    function checkStopKeywords(userInput) {\n      const pattern = new RegExp(\"\\\\b(\" + stopKeywords.map(escapeRegex).join(\"|\") + \")\\\\b\", \"i\");\n      return pattern.test(userInput);\n    }\n\n    function formatSentence(text) {\n      if (!text) return \"\";\n      text = text.trim();\n      text = text.charAt(0).toUpperCase() + text.slice(1);\n      if (!\/[.?!]$\/.test(text)) text += \".\";\n      return text;\n    }\n\n    function addSentenceToBox(sentence) {\n      const wordBox = document.getElementById('word-box');\n      const sentenceElement = document.createElement('div');\n      sentenceElement.innerText = sentence;\n      wordBox.appendChild(sentenceElement);\n      wordBox.scrollTop = wordBox.scrollHeight;\n    }\n\n    function clearWordBox() {\n      document.getElementById('word-box').innerHTML = \"\";\n    }\n\n    function clearChat() {\n      document.getElementById('chat-messages').innerHTML = \"\";\n    }\n\n    function endLesson(userStopped = false) {\n      stopAllAudioAndRecognition();\n      isLessonActive = false;\n      currentListeningItem = null;\n\n      const message = userStopped\n        ? \"Gracias. Adi\u00f3s.\"\n        : `Excelente. Terminaste la secci\u00f3n ${sectionData[currentSection].title}. Sigue practicando.`;\n\n      appendMessage(message, \"bot\");\n      faceSpeak(message, userStopped ? \"neutral\" : \"happy\");\n      showSynthesisLoader(true);\n      speakSpanish(message).then(() => showSynthesisLoader(false));\n    }\n\n    function speakText(text, lang, voiceObj) {\n      return new Promise(resolve => {\n        if (!speechSynthesisSupported) {\n          resolve();\n          return;\n        }\n        window.speechSynthesis.cancel();\n        const utterance = new SpeechSynthesisUtterance(text);\n        utterance.lang = lang;\n        utterance.rate = 0.9;\n        utterance.pitch = 1.0;\n        if (voiceObj) utterance.voice = voiceObj;\n        utterance.onend = () => resolve();\n        utterance.onerror = () => resolve();\n        window.speechSynthesis.speak(utterance);\n      });\n    }\n\n    function speakSpanish(text) {\n      return speakText(text, \"es-ES\", selectedSpanishVoice);\n    }\n\n    function appendMessage(text, sender) {\n      const messageContainer = document.getElementById('chat-messages');\n      const messageElement = document.createElement('div');\n      messageElement.classList.add('message');\n      messageElement.classList.add(sender === 'bot' ? 'bot-message' : 'user-message');\n      messageElement.innerText = text;\n      messageContainer.appendChild(messageElement);\n      messageContainer.scrollTop = messageContainer.scrollHeight;\n    }\n\n    function showSynthesisLoader(show) {\n      const loader = document.getElementById('synthesis-loader');\n      loader.style.display = show ? 'inline-block' : 'none';\n      loader.style.borderTop = '4px solid #17a2b8';\n    }\n\n    function showRecognitionLoader(show) {\n      const loader = document.getElementById('synthesis-loader');\n      loader.style.display = show ? 'inline-block' : 'none';\n      loader.style.borderTop = show ? '4px solid #ffc107' : '4px solid #17a2b8';\n    }\n\n    function clearPendingTimeout() {\n      if (pendingNextQuestionTimeout) {\n        clearTimeout(pendingNextQuestionTimeout);\n        pendingNextQuestionTimeout = null;\n      }\n    }\n\n    function stopRecognitionOnly() {\n      if (recognition) {\n        try { recognition.stop(); } catch (e) {}\n      }\n      speechRecognitionActive = false;\n      showRecognitionLoader(false);\n    }\n\n    function stopAllAudioAndRecognition() {\n      clearPendingTimeout();\n      stopRecognitionOnly();\n      if (speechSynthesisSupported) window.speechSynthesis.cancel();\n      showSynthesisLoader(false);\n      stopFaceTalking();\n      faceSpeechBubble.classList.remove('visible');\n    }\n\n    function pickRandom(arr) {\n      return arr[Math.floor(Math.random() * arr.length)];\n    }\n\n    function escapeRegex(str) {\n      return str.replace(\/[.*+?^${}()|[\\]\\\\]\/g, \"\\\\$&\");\n    }\n\n    window.onload = initialize;\n  <\/script>\n<\/body>\n<\/html>\n","protected":false},"excerpt":{"rendered":"<p>Learn Spanish: School Q&#038;A Practice In class School supplies Asking for help Teacher-student talk Homework time Library language Meeting people<\/p>\n","protected":false},"author":1,"featured_media":249,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"colormag_page_layout":"default_layout","footnotes":""},"categories":[65,54],"tags":[],"class_list":["post-878","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-advanced","category-spanish"],"_links":{"self":[{"href":"https:\/\/i-cte.org\/robot\/wp-json\/wp\/v2\/posts\/878","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=878"}],"version-history":[{"count":1,"href":"https:\/\/i-cte.org\/robot\/wp-json\/wp\/v2\/posts\/878\/revisions"}],"predecessor-version":[{"id":879,"href":"https:\/\/i-cte.org\/robot\/wp-json\/wp\/v2\/posts\/878\/revisions\/879"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/i-cte.org\/robot\/wp-json\/wp\/v2\/media\/249"}],"wp:attachment":[{"href":"https:\/\/i-cte.org\/robot\/wp-json\/wp\/v2\/media?parent=878"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/i-cte.org\/robot\/wp-json\/wp\/v2\/categories?post=878"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/i-cte.org\/robot\/wp-json\/wp\/v2\/tags?post=878"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}