{"id":880,"date":"2026-03-12T11:55:42","date_gmt":"2026-03-12T11:55:42","guid":{"rendered":"https:\/\/i-cte.org\/robot\/?p=880"},"modified":"2026-03-12T11:55:42","modified_gmt":"2026-03-12T11:55:42","slug":"spanish-interaction-home","status":"publish","type":"post","link":"https:\/\/i-cte.org\/robot\/spanish-interaction-home\/","title":{"rendered":"Spanish interaction &#8211; Home"},"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: Home 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=\"kitchen\">In the kitchen<\/a>\n    <a href=\"#\" class=\"menu-link\" data-section=\"bedroom\">In the bedroom<\/a>\n    <a href=\"#\" class=\"menu-link\" data-section=\"cleaning\">Cleaning the house<\/a>\n    <a href=\"#\" class=\"menu-link\" data-section=\"bathroom\">Bath time<\/a>\n    <a href=\"#\" class=\"menu-link\" data-section=\"weekend\">Weekend activities<\/a>\n    <a href=\"#\" class=\"menu-link\" data-section=\"hobbies\">Hobbies<\/a>\n    <a href=\"#\" class=\"menu-link\" data-section=\"pets\">Pets<\/a>\n    <a href=\"#\" class=\"menu-link\" data-section=\"tv\">Watching TV<\/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 the kitchen<\/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=\"kitchen\">In the kitchen<\/a>\n    <a href=\"#\" class=\"menu-link\" data-section=\"bedroom\">In the bedroom<\/a>\n    <a href=\"#\" class=\"menu-link\" data-section=\"cleaning\">Cleaning the house<\/a>\n    <a href=\"#\" class=\"menu-link\" data-section=\"bathroom\">Bath time<\/a>\n    <a href=\"#\" class=\"menu-link\" data-section=\"weekend\">Weekend activities<\/a>\n    <a href=\"#\" class=\"menu-link\" data-section=\"hobbies\">Hobbies<\/a>\n    <a href=\"#\" class=\"menu-link\" data-section=\"pets\">Pets<\/a>\n    <a href=\"#\" class=\"menu-link\" data-section=\"tv\">Watching TV<\/a>\n  <\/div>\n\n  <script>\n    const sectionData = {\n      kitchen: {\n        title: \"In the kitchen\",\n        intro: \"Hoy vamos a practicar preguntas sobre la cocina.\",\n        items: [\n          {\n            questionEs: \"\u00bfQu\u00e9 haces en la cocina?\",\n            questionEn: \"What do you do in the kitchen?\",\n            suggestedAnswer: \"Cocino arroz en casa.\",\n            keywords: [\"cocino\", \"arroz\", \"cocina\", \"lavo\", \"platos\", \"mesa\", \"pan\"]\n          },\n          {\n            questionEs: \"\u00bfLavas los platos ahora?\",\n            questionEn: \"Do you wash the dishes now?\",\n            suggestedAnswer: \"S\u00ed, lavo los platos.\",\n            keywords: [\"s\u00ed\", \"si\", \"lavo\", \"platos\", \"ahora\", \"no\"]\n          },\n          {\n            questionEs: \"\u00bfQu\u00e9 preparas para comer?\",\n            questionEn: \"What do you prepare to eat?\",\n            suggestedAnswer: \"Preparo arroz y sopa.\",\n            keywords: [\"preparo\", \"arroz\", \"sopa\", \"pan\", \"comida\", \"pollo\"]\n          },\n          {\n            questionEs: \"\u00bfPones la mesa bien?\",\n            questionEn: \"Do you set the table well?\",\n            suggestedAnswer: \"S\u00ed, pongo la mesa.\",\n            keywords: [\"s\u00ed\", \"si\", \"pongo\", \"mesa\", \"bien\", \"no\"]\n          }\n        ]\n      },\n      bedroom: {\n        title: \"In the bedroom\",\n        intro: \"Hoy vamos a practicar preguntas sobre el dormitorio.\",\n        items: [\n          {\n            questionEs: \"\u00bfQu\u00e9 haces en tu dormitorio?\",\n            questionEn: \"What do you do in your bedroom?\",\n            suggestedAnswer: \"Duermo y descanso aqu\u00ed.\",\n            keywords: [\"duermo\", \"descanso\", \"cama\", \"leo\", \"ropa\", \"ventana\"]\n          },\n          {\n            questionEs: \"\u00bfHaces tu cama temprano?\",\n            questionEn: \"Do you make your bed early?\",\n            suggestedAnswer: \"S\u00ed, hago mi cama.\",\n            keywords: [\"s\u00ed\", \"si\", \"hago\", \"cama\", \"temprano\", \"no\"]\n          },\n          {\n            questionEs: \"\u00bfAbres la ventana hoy?\",\n            questionEn: \"Do you open the window today?\",\n            suggestedAnswer: \"S\u00ed, abro la ventana.\",\n            keywords: [\"s\u00ed\", \"si\", \"abro\", \"ventana\", \"hoy\", \"no\"]\n          },\n          {\n            questionEs: \"\u00bfBuscas tu ropa limpia?\",\n            questionEn: \"Do you look for your clean clothes?\",\n            suggestedAnswer: \"S\u00ed, busco mi ropa.\",\n            keywords: [\"s\u00ed\", \"si\", \"busco\", \"ropa\", \"limpia\", \"no\"]\n          }\n        ]\n      },\n      cleaning: {\n        title: \"Cleaning the house\",\n        intro: \"Hoy vamos a practicar preguntas sobre limpiar la casa.\",\n        items: [\n          {\n            questionEs: \"\u00bfLimpias la casa hoy?\",\n            questionEn: \"Do you clean the house today?\",\n            suggestedAnswer: \"S\u00ed, limpio la casa.\",\n            keywords: [\"s\u00ed\", \"si\", \"limpio\", \"casa\", \"hoy\", \"no\"]\n          },\n          {\n            questionEs: \"\u00bfBarres el piso ahora?\",\n            questionEn: \"Do you sweep the floor now?\",\n            suggestedAnswer: \"S\u00ed, barro el piso.\",\n            keywords: [\"s\u00ed\", \"si\", \"barro\", \"piso\", \"ahora\", \"no\"]\n          },\n          {\n            questionEs: \"\u00bfLavas la ropa blanca?\",\n            questionEn: \"Do you wash the white clothes?\",\n            suggestedAnswer: \"S\u00ed, lavo la ropa.\",\n            keywords: [\"s\u00ed\", \"si\", \"lavo\", \"ropa\", \"blanca\", \"no\"]\n          },\n          {\n            questionEs: \"\u00bfSacas la basura afuera?\",\n            questionEn: \"Do you take the trash outside?\",\n            suggestedAnswer: \"S\u00ed, saco la basura.\",\n            keywords: [\"s\u00ed\", \"si\", \"saco\", \"basura\", \"afuera\", \"no\"]\n          }\n        ]\n      },\n      bathroom: {\n        title: \"Bath time\",\n        intro: \"Hoy vamos a practicar preguntas sobre el ba\u00f1o.\",\n        items: [\n          {\n            questionEs: \"\u00bfQu\u00e9 haces en el ba\u00f1o?\",\n            questionEn: \"What do you do in the bathroom?\",\n            suggestedAnswer: \"Me lavo la cara.\",\n            keywords: [\"lavo\", \"cara\", \"ducha\", \"dientes\", \"pelo\", \"ba\u00f1o\"]\n          },\n          {\n            questionEs: \"\u00bfTe cepillas los dientes?\",\n            questionEn: \"Do you brush your teeth?\",\n            suggestedAnswer: \"S\u00ed, me cepillo dientes.\",\n            keywords: [\"s\u00ed\", \"si\", \"cepillo\", \"dientes\", \"no\"]\n          },\n          {\n            questionEs: \"\u00bfTomas una ducha larga?\",\n            questionEn: \"Do you take a long shower?\",\n            suggestedAnswer: \"S\u00ed, tomo una ducha.\",\n            keywords: [\"s\u00ed\", \"si\", \"tomo\", \"ducha\", \"larga\", \"no\"]\n          },\n          {\n            questionEs: \"\u00bfLavas tu pelo hoy?\",\n            questionEn: \"Do you wash your hair today?\",\n            suggestedAnswer: \"S\u00ed, lavo mi pelo.\",\n            keywords: [\"s\u00ed\", \"si\", \"lavo\", \"pelo\", \"hoy\", \"no\"]\n          }\n        ]\n      },\n      weekend: {\n        title: \"Weekend activities\",\n        intro: \"Hoy vamos a practicar actividades del fin de semana.\",\n        items: [\n          {\n            questionEs: \"\u00bfQu\u00e9 haces el fin de semana?\",\n            questionEn: \"What do you do on the weekend?\",\n            suggestedAnswer: \"Descanso en casa mucho.\",\n            keywords: [\"descanso\", \"casa\", \"salgo\", \"familia\", \"cine\", \"juego\"]\n          },\n          {\n            questionEs: \"\u00bfSales con amigos hoy?\",\n            questionEn: \"Do you go out with friends today?\",\n            suggestedAnswer: \"S\u00ed, salgo con amigos.\",\n            keywords: [\"s\u00ed\", \"si\", \"salgo\", \"amigos\", \"hoy\", \"no\"]\n          },\n          {\n            questionEs: \"\u00bfVisitas a tu familia?\",\n            questionEn: \"Do you visit your family?\",\n            suggestedAnswer: \"S\u00ed, visito mi familia.\",\n            keywords: [\"s\u00ed\", \"si\", \"visito\", \"familia\", \"no\"]\n          },\n          {\n            questionEs: \"\u00bfJuegas todo el d\u00eda?\",\n            questionEn: \"Do you play all day?\",\n            suggestedAnswer: \"S\u00ed, juego todo d\u00eda.\",\n            keywords: [\"s\u00ed\", \"si\", \"juego\", \"d\u00eda\", \"dia\", \"no\"]\n          }\n        ]\n      },\n      hobbies: {\n        title: \"Hobbies\",\n        intro: \"Hoy vamos a practicar preguntas sobre pasatiempos.\",\n        items: [\n          {\n            questionEs: \"\u00bfQu\u00e9 te gusta hacer?\",\n            questionEn: \"What do you like to do?\",\n            suggestedAnswer: \"Me gusta leer libros.\",\n            keywords: [\"gusta\", \"leer\", \"libros\", \"bailar\", \"cantar\", \"pintar\", \"correr\"]\n          },\n          {\n            questionEs: \"\u00bfTe gusta pintar flores?\",\n            questionEn: \"Do you like painting flowers?\",\n            suggestedAnswer: \"S\u00ed, me gusta pintar.\",\n            keywords: [\"s\u00ed\", \"si\", \"gusta\", \"pintar\", \"flores\", \"no\"]\n          },\n          {\n            questionEs: \"\u00bfTe gusta cantar canciones?\",\n            questionEn: \"Do you like singing songs?\",\n            suggestedAnswer: \"S\u00ed, me gusta cantar.\",\n            keywords: [\"s\u00ed\", \"si\", \"gusta\", \"cantar\", \"canciones\", \"no\"]\n          },\n          {\n            questionEs: \"\u00bfTe gusta correr fuera?\",\n            questionEn: \"Do you like running outside?\",\n            suggestedAnswer: \"S\u00ed, me gusta correr.\",\n            keywords: [\"s\u00ed\", \"si\", \"gusta\", \"correr\", \"fuera\", \"no\"]\n          }\n        ]\n      },\n      pets: {\n        title: \"Pets\",\n        intro: \"Hoy vamos a practicar preguntas sobre mascotas.\",\n        items: [\n          {\n            questionEs: \"\u00bfTienes una mascota?\",\n            questionEn: \"Do you have a pet?\",\n            suggestedAnswer: \"S\u00ed, tengo un perro.\",\n            keywords: [\"s\u00ed\", \"si\", \"tengo\", \"perro\", \"gato\", \"mascota\", \"no\"]\n          },\n          {\n            questionEs: \"\u00bfQu\u00e9 animal tienes?\",\n            questionEn: \"What animal do you have?\",\n            suggestedAnswer: \"Tengo un gato blanco.\",\n            keywords: [\"tengo\", \"gato\", \"perro\", \"blanco\", \"peque\u00f1o\", \"pequeno\"]\n          },\n          {\n            questionEs: \"\u00bfDas comida al perro?\",\n            questionEn: \"Do you give food to the dog?\",\n            suggestedAnswer: \"S\u00ed, doy comida perro.\",\n            keywords: [\"s\u00ed\", \"si\", \"doy\", \"comida\", \"perro\", \"no\"]\n          },\n          {\n            questionEs: \"\u00bfTu gato duerme aqu\u00ed?\",\n            questionEn: \"Does your cat sleep here?\",\n            suggestedAnswer: \"S\u00ed, mi gato duerme.\",\n            keywords: [\"s\u00ed\", \"si\", \"gato\", \"duerme\", \"aqu\u00ed\", \"aqui\", \"no\"]\n          }\n        ]\n      },\n      tv: {\n        title: \"Watching TV\",\n        intro: \"Hoy vamos a practicar preguntas sobre ver televisi\u00f3n.\",\n        items: [\n          {\n            questionEs: \"\u00bfVes la televisi\u00f3n ahora?\",\n            questionEn: \"Are you watching television now?\",\n            suggestedAnswer: \"S\u00ed, veo la televisi\u00f3n.\",\n            keywords: [\"s\u00ed\", \"si\", \"veo\", \"televisi\u00f3n\", \"television\", \"ahora\", \"no\"]\n          },\n          {\n            questionEs: \"\u00bfQu\u00e9 programa te gusta?\",\n            questionEn: \"What program do you like?\",\n            suggestedAnswer: \"Me gusta este programa.\",\n            keywords: [\"gusta\", \"programa\", \"pel\u00edcula\", \"pelicula\", \"serie\"]\n          },\n          {\n            questionEs: \"\u00bfCambias el canal r\u00e1pido?\",\n            questionEn: \"Do you change the channel quickly?\",\n            suggestedAnswer: \"S\u00ed, cambio el canal.\",\n            keywords: [\"s\u00ed\", \"si\", \"cambio\", \"canal\", \"r\u00e1pido\", \"rapido\", \"no\"]\n          },\n          {\n            questionEs: \"\u00bfApagas la tele tarde?\",\n            questionEn: \"Do you turn off the TV late?\",\n            suggestedAnswer: \"S\u00ed, apago la tele.\",\n            keywords: [\"s\u00ed\", \"si\", \"apago\", \"tele\", \"tarde\", \"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 = \"kitchen\";\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 home.`);\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: Home Q&#038;A Practice In the kitchen In the bedroom Cleaning the house Bath time Weekend activities Hobbies Pets<\/p>\n","protected":false},"author":1,"featured_media":597,"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-880","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\/880","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=880"}],"version-history":[{"count":1,"href":"https:\/\/i-cte.org\/robot\/wp-json\/wp\/v2\/posts\/880\/revisions"}],"predecessor-version":[{"id":881,"href":"https:\/\/i-cte.org\/robot\/wp-json\/wp\/v2\/posts\/880\/revisions\/881"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/i-cte.org\/robot\/wp-json\/wp\/v2\/media\/597"}],"wp:attachment":[{"href":"https:\/\/i-cte.org\/robot\/wp-json\/wp\/v2\/media?parent=880"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/i-cte.org\/robot\/wp-json\/wp\/v2\/categories?post=880"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/i-cte.org\/robot\/wp-json\/wp\/v2\/tags?post=880"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}