{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./app/javascript/packs/landing_conversation.js"],"names":["installedModules","__webpack_require__","moduleId","exports","module","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","document","addEventListener","console","log","isChrome","test","navigator","userAgent","vendor","isMobile","currentLanguage","isRecording","mediaRecorder","audioChunks","messageCount","miniConversationContainer","getElementById","messagesContainer","querySelector","recordButton","languageButtons","querySelectorAll","conversationOverlay","e","stopPropagation","selectionExplainBtn","style","display","selection","window","getSelection","rangeCount","node","anchorNode","body","classList","contains","parentNode","conversationInterface","frenchButton","add","loadInitialMessage","initializeRecordButton","textContent","remove","onclick","showSignUpOverlay","startRecording","languageCode","concat","innerHTML","fetch","method","headers","content","then","response","ok","Error","status","json","data","aiMessageElement","createElement","className","message","appendChild","audio_url","audioElement","src","audioControls","listenButton","marginTop","marginRight","cursor","stopButton","explainButton","title","playAudio","stopAudio","miniConversationStates","messages","buttonState","text","hasClass","error","mediaDevices","getUserMedia","audio","stream","stop","MediaRecorder","event","push","audioBlob","formData","FormData","append","userMessageElement","scrollTop","scrollHeight","transcription","controlsContainer","getAIResponse","message_limit_reached","sendAudioToServer","Blob","type","getTracks","forEach","track","start","alert","success","ai_message","currentlyPlayingAudio","pause","currentTime","previousMessage","closest","previousListenBtn","previousStopBtn","listenBtn","stopBtn","play","onended","id","disabled","preventDefault","button","newLanguage","this","getAttribute","btn","trim"],"mappings":"aACE,IAAIA,EAAmB,CAAC,EAGxB,SAASC,EAAoBC,GAG5B,GAAGF,EAAiBE,GACnB,OAAOF,EAAiBE,GAAUC,QAGnC,IAAIC,EAASJ,EAAiBE,GAAY,CACzCG,EAAGH,EACHI,GAAG,EACHH,QAAS,CAAC,GAUX,OANAI,EAAQL,GAAUM,KAAKJ,EAAOD,QAASC,EAAQA,EAAOD,QAASF,GAG/DG,EAAOE,GAAI,EAGJF,EAAOD,OACf,CAIAF,EAAoBQ,EAAIF,EAGxBN,EAAoBS,EAAIV,EAGxBC,EAAoBU,EAAI,SAASR,EAASS,EAAMC,GAC3CZ,EAAoBa,EAAEX,EAASS,IAClCG,OAAOC,eAAeb,EAASS,EAAM,CAAEK,YAAY,EAAMC,IAAKL,GAEhE,EAGAZ,EAAoBkB,EAAI,SAAShB,GACX,qBAAXiB,QAA0BA,OAAOC,aAC1CN,OAAOC,eAAeb,EAASiB,OAAOC,YAAa,CAAEC,MAAO,WAE7DP,OAAOC,eAAeb,EAAS,aAAc,CAAEmB,OAAO,GACvD,EAOArB,EAAoBsB,EAAI,SAASD,EAAOE,GAEvC,GADU,EAAPA,IAAUF,EAAQrB,EAAoBqB,IAC/B,EAAPE,EAAU,OAAOF,EACpB,GAAW,EAAPE,GAA8B,kBAAVF,GAAsBA,GAASA,EAAMG,WAAY,OAAOH,EAChF,IAAII,EAAKX,OAAOY,OAAO,MAGvB,GAFA1B,EAAoBkB,EAAEO,GACtBX,OAAOC,eAAeU,EAAI,UAAW,CAAET,YAAY,EAAMK,MAAOA,IACtD,EAAPE,GAA4B,iBAATF,EAAmB,IAAI,IAAIM,KAAON,EAAOrB,EAAoBU,EAAEe,EAAIE,EAAK,SAASA,GAAO,OAAON,EAAMM,EAAM,EAAEC,KAAK,KAAMD,IAC9I,OAAOF,CACR,EAGAzB,EAAoB6B,EAAI,SAAS1B,GAChC,IAAIS,EAAST,GAAUA,EAAOqB,WAC7B,WAAwB,OAAOrB,EAAgB,OAAG,EAClD,WAA8B,OAAOA,CAAQ,EAE9C,OADAH,EAAoBU,EAAEE,EAAQ,IAAKA,GAC5BA,CACR,EAGAZ,EAAoBa,EAAI,SAASiB,EAAQC,GAAY,OAAOjB,OAAOkB,UAAUC,eAAe1B,KAAKuB,EAAQC,EAAW,EAGpH/B,EAAoBkC,EAAI,UAIjBlC,EAAoBA,EAAoBmC,EAAI,E,mBChFrDC,SAASC,iBAAiB,oBAAoB,WAC5CC,QAAQC,IAAI,sCAGZ,IAAMC,EAAW,SAASC,KAAKC,UAAUC,YAAc,aAAaF,KAAKC,UAAUE,QAC7EC,EAAW,iEAAiEJ,KAAKC,UAAUC,WAEjGL,QAAQC,IAAI,qBAAsB,CAAEC,WAAUK,aAG9C,IAAIC,EAAkB,KAClBC,GAAc,EACdC,EAAgB,KAChBC,EAAc,GACdC,EAAe,EAKbC,EAA4Bf,SAASgB,eAAe,+BACpDC,EAAoBjB,SAASkB,cAAc,4BAC3CC,EAAenB,SAASgB,eAAe,sBACvCI,EAAkBpB,SAASqB,iBAAiB,oBAC9CC,EAAsBtB,SAASgB,eAAe,6BAmClD,GAhCAhB,SAASkB,cAAc,gCAAgCjB,iBAAiB,WAAW,SAASsB,GAE1FA,EAAEC,kBAGF,IAAMC,EAAsBzB,SAASkB,cAAc,0BAC/CO,IACFA,EAAoBC,MAAMC,QAAU,OAExC,IAAG,GAGH3B,SAASC,iBAAiB,mBAAmB,SAASsB,GAEpD,IAAMK,EAAYC,OAAOC,eACzB,GAAKF,EAAUG,WAGf,IADA,IAAIC,EAAOJ,EAAUK,WACdD,GAAQA,IAAShC,SAASkC,MAAM,CACrC,GAAIF,EAAKG,WAAaH,EAAKG,UAAUC,SAAS,+BAAgC,CAE5E,IAAMX,EAAsBzB,SAASkB,cAAc,0BAC/CO,IACFA,EAAoBC,MAAMC,QAAU,QAEtC,KACF,CACAK,EAAOA,EAAKK,UACd,CACF,IAGItB,EAA2B,CAC7Bb,QAAQC,IAAI,oDACZY,EAA0BW,MAAMC,QAAU,OAG1C,IAAMW,EAAwBtC,SAASkB,cAAc,2BACjDoB,IACFA,EAAsBZ,MAAMC,QAAU,QAIxC,IAAMY,EAAevC,SAASkB,cAAc,wCACxCqB,IACFA,EAAaJ,UAAUK,IAAI,YAC3BC,EAAmB,MAEvB,MACEvC,QAAQC,IAAI,yCAsFd,SAASuC,IACPxC,QAAQC,IAAI,8BACZQ,GAAc,EACdQ,EAAawB,YAAc,SAC3BxB,EAAagB,UAAUS,OAAO,mBAC9BzB,EAAagB,UAAUS,OAAO,aAG9BzB,EAAa0B,QAAU,WAErB,GADA3C,QAAQC,IAAI,iCACRW,GA5Ja,EA+Jf,OAFAZ,QAAQC,IAAI,0EACZ2C,IAKFC,GACF,CACF,CAGA,SAASN,EAAmBO,GAC1B9C,QAAQC,IAAI,yCAAD8C,OAA0CD,IAGrD/B,EAAkBiC,UAAY,mDAG9BC,MAAM,0CAADF,OAA2CD,GAAgB,CAC9DI,OAAQ,MACRC,QAAS,CACP,eAAgBrD,SAASkB,cAAc,2BAA2BoC,WAGnEC,MAAK,SAAAC,GACJ,IAAKA,EAASC,GACZ,MAAM,IAAIC,MAAM,iCAADT,OAAkCO,EAASG,SAE5D,OAAOH,EAASI,MAClB,IACCL,MAAK,SAAAM,GAEJ,IAAMC,EAAmB9D,SAAS+D,cAAc,OAShD,GARAD,EAAiBE,UAAY,qBAC7BF,EAAiBZ,UAAS,MAAAD,OAASY,EAAKI,QAAO,QAG/ChD,EAAkBiC,UAAY,GAC9BjC,EAAkBiD,YAAYJ,GAG1BD,EAAKM,UAAW,CAElB,IAAMC,EAAepE,SAAS+D,cAAc,SAC5CK,EAAa1C,MAAMC,QAAU,OAC7ByC,EAAaC,IAAMR,EAAKM,UAGxBL,EAAiBI,YAAYE,GAG7B,IAAME,EAAgBtE,SAAS+D,cAAc,OAC7CO,EAAcN,UAAY,iBAG1B,IAAMO,EAAevE,SAAS+D,cAAc,QAC5CQ,EAAaP,UAAY,mBACzBO,EAAarB,UAAY,eACzBqB,EAAa7C,MAAM8C,UAAY,MAC/BD,EAAa7C,MAAM+C,YAAc,OACjCF,EAAa7C,MAAMgD,OAAS,UAG5B,IAAMC,EAAa3E,SAAS+D,cAAc,QAC1CY,EAAWX,UAAY,iBACvBW,EAAWzB,UAAY,eACvByB,EAAWjD,MAAMC,QAAU,OAC3BgD,EAAWjD,MAAM8C,UAAY,MAC7BG,EAAWjD,MAAM+C,YAAc,OAC/BE,EAAWjD,MAAMgD,OAAS,UAG1B,IAAME,EAAgB5E,SAAS+D,cAAc,QAC7Ca,EAAcZ,UAAY,cAC1BY,EAAc1B,UAAY,SAC1B0B,EAAclD,MAAM8C,UAAY,MAChCI,EAAclD,MAAMgD,OAAS,UAC7BE,EAAcC,MAAQ,wCAGtBP,EAAcJ,YAAYK,GAC1BD,EAAcJ,YAAYS,GAC1BL,EAAcJ,YAAYU,GAG1Bd,EAAiBI,YAAYI,GAG7BC,EAAatE,iBAAiB,SAAS,WACrC6E,EAAUV,EACZ,IACAO,EAAW1E,iBAAiB,SAAS,WACnC8E,EAAUX,EACZ,IACAQ,EAAc3E,iBAAiB,SAAS,WACtC6C,GACF,IAGAgC,EAAUV,EACZ,CAGKvC,OAAOmD,yBACVnD,OAAOmD,uBAAyB,CAAC,GAEnCnD,OAAOmD,uBAAuBtE,GAAmB,CAC/CuE,SAAUhE,EAAkBiC,UAC5BgC,YAAa,CACXC,KAAMhE,EAAawB,YACnBhC,YAAaA,EACbyE,SAAUjE,EAAagB,UAAUC,SAAS,oBAGhD,IAAE,OACK,SAAAiD,GACLnF,QAAQmF,MAAM,iCAAkCA,GAChDpE,EAAkBiC,UAAY,qGAChC,GACJ,CAGA,SAASH,IACP7C,QAAQC,IAAI,sBAEZG,UAAUgF,aAAaC,aAAa,CAAEC,OAAO,IAC1CjC,MAAK,SAAAkC,GAEJ9E,GAAc,EACdQ,EAAawB,YAAc,OAC3BxB,EAAagB,UAAUK,IAAI,aAG3BrB,EAAa0B,QAAU,WACrB3C,QAAQC,IAAI,uBAoCdS,GAAiBD,IAEnBA,GAAc,EACdQ,EAAawB,YAAc,aAC3BxB,EAAagB,UAAUS,OAAO,aAG9BhC,EAAc8E,OAzCZ,EAGA9E,EAAgB,IAAI+E,cAAcF,GAClC5E,EAAc,GAGdD,EAAcX,iBAAiB,iBAAiB,SAAA2F,GAC9C/E,EAAYgF,KAAKD,EAAM/B,KACzB,IAGAjD,EAAcX,iBAAiB,QAAQ,YAkC7C,SAA2B6F,GACzB5F,QAAQC,IAAI,4BAEZ,IAAM4F,EAAW,IAAIC,SACrBD,EAASE,OAAO,QAASH,GACzBC,EAASE,OAAO,gBAAiBvF,GAGjC,IAAMwF,EAAqBlG,SAAS+D,cAAc,OAClDmC,EAAmBlC,UAAY,uBAC/BkC,EAAmBhD,UAAY,aAC/BjC,EAAkBiD,YAAYgC,GAG9BjF,EAAkBkF,UAAYlF,EAAkBmF,aAGhDjD,MAAM,mBAAoB,CACxBC,OAAQ,OACRC,QAAS,CACP,eAAgBrD,SAASkB,cAAc,2BAA2BoC,SAEpEpB,KAAM6D,IAELxC,MAAK,SAAAC,GACJ,GAAwB,MAApBA,EAASG,OAKX,MAHAzD,QAAQC,IAAI,wDACZ+F,EAAmBtD,SACnBE,IACM,IAAIY,MAAM,yBAGlB,IAAKF,EAASC,GACZ,MAAM,IAAIC,MAAM,iCAADT,OAAkCO,EAASG,SAE5D,OAAOH,EAASI,MAClB,IACCL,MAAK,SAAAM,GACJ,GAAIA,EAAKwC,cAAe,CACtBnG,QAAQC,IAAI,kDAEZ+F,EAAmBhD,UAAS,MAAAD,OAASY,EAAKwC,cAAa,QAGvD,IAAMzB,EAAgB5E,SAAS+D,cAAc,QAC7Ca,EAAcZ,UAAY,cAC1BY,EAAc1B,UAAY,SAC1B0B,EAAclD,MAAM8C,UAAY,MAChCI,EAAclD,MAAMgD,OAAS,UAC7BE,EAAcC,MAAQ,wCAGtB,IAAMyB,EAAoBtG,SAAS+D,cAAc,OAiBjD,GAhBAuC,EAAkBtC,UAAY,iBAC9BsC,EAAkBpC,YAAYU,GAG9BsB,EAAmBhC,YAAYoC,GAG/B1B,EAAc3E,iBAAiB,SAAS,WACtC6C,GACF,IAGAhC,IACAZ,QAAQC,IAAI,8BAAD8C,OAA+BnC,EAAY,KAAAmC,OAtZzC,EAsZyD,6BAGlEnC,GAzZS,EA4ZX,OAFAZ,QAAQC,IAAI,mEACZ2C,IAKF3B,EAAawB,YAAc,WAC3BxB,EAAagB,UAAUK,IAAI,mBAG3BrB,EAAa0B,QAAU,WACrB3C,QAAQC,IAAI,mDACZgB,EAAawB,YAAc,aAC3B4D,GACF,EAGK1E,OAAOmD,yBACVnD,OAAOmD,uBAAyB,CAAC,GAEnCnD,OAAOmD,uBAAuBtE,GAAmB,CAC/CuE,SAAUhE,EAAkBiC,UAC5BgC,YAAa,CACXC,KAAMhE,EAAawB,YACnBhC,YAAaA,EACbyE,SAAUjE,EAAagB,UAAUC,SAAS,qBAK9CnB,EAAkBkF,UAAYlF,EAAkBmF,YAClD,MAAWvC,EAAKwB,OAEdnF,QAAQmF,MAAM,qBAAsBxB,EAAKwB,OACzCa,EAAmBhD,UAAY,4DAC3BW,EAAK2C,uBACPtG,QAAQC,IAAI,sEACZ2C,MAGA3B,EAAawB,YAAc,SAC3BxB,EAAagB,UAAUS,OAAO,mBAC9BzB,EAAa0B,QAAU,WACrBE,GACF,KAIFmD,EAAmBhD,UAAY,4CAE/B/B,EAAawB,YAAc,SAC3BxB,EAAagB,UAAUS,OAAO,mBAC9BzB,EAAa0B,QAAU,WACrBE,GACF,EAEJ,IAAE,OACK,SAAAsC,GACLnF,QAAQmF,MAAM,iCAAkCA,GAChDa,EAAmBhD,UAAY,4DAE/B/B,EAAawB,YAAc,SAC3BxB,EAAagB,UAAUS,OAAO,mBAC9BzB,EAAa0B,QAAU,WACrBE,GACF,CACF,GACJ,CAvKQ0D,CAHkB,IAAIC,KAAK7F,EAAa,CAAE8F,KAAM,eAMhDlB,EAAOmB,YAAYC,SAAQ,SAAAC,GAAK,OAAIA,EAAMpB,MAAM,GAClD,IAGA9E,EAAcmG,OAChB,IAAE,OACK,SAAA1B,GACLnF,QAAQmF,MAAM,8BAA+BA,GAC7C2B,MAAM,sDACR,GACJ,CA6JA,SAAST,IACPrG,QAAQC,IAAI,wBAEZgB,EAAawB,YAAc,aAC3BxB,EAAagB,UAAUS,OAAO,mBAG9B,IAAMkB,EAAmB9D,SAAS+D,cAAc,OAChDD,EAAiBE,UAAY,qBAC7BF,EAAiBZ,UAAY,aAC7BjC,EAAkBiD,YAAYJ,GAG9B7C,EAAkBkF,UAAYlF,EAAkBmF,aAGhD,IAAML,EAAW,IAAIC,SACrBD,EAASE,OAAO,gBAAiBvF,GAGjCyC,MAAM,oBAAqB,CACzBC,OAAQ,OACRC,QAAS,CACP,eAAgBrD,SAASkB,cAAc,2BAA2BoC,SAEpEpB,KAAM6D,IAELxC,MAAK,SAAAC,GACJ,IAAKA,EAASC,GACZ,MAAM,IAAIC,MAAM,iCAADT,OAAkCO,EAASG,SAE5D,OAAOH,EAASI,MAClB,IACCL,MAAK,SAAAM,GACJ,GAAIA,EAAKoD,SAAWpD,EAAKqD,WAAY,CAMnC,GALAhH,QAAQC,IAAI,+CAEZ2D,EAAiBZ,UAAS,MAAAD,OAASY,EAAKqD,WAAW5D,QAAO,QAGtDO,EAAKqD,WAAW/C,UAAW,CAC7BjE,QAAQC,IAAI,iCAAkC0D,EAAKqD,WAAW/C,WAG9D,IAAMC,EAAepE,SAAS+D,cAAc,SAC5CK,EAAa1C,MAAMC,QAAU,OAC7ByC,EAAaC,IAAMR,EAAKqD,WAAW/C,UAGnCL,EAAiBI,YAAYE,GAG7B,IAAME,EAAgBtE,SAAS+D,cAAc,OAC7CO,EAAcN,UAAY,iBAG1B,IAAMO,EAAevE,SAAS+D,cAAc,QAC5CQ,EAAaP,UAAY,mBACzBO,EAAarB,UAAY,eACzBqB,EAAa7C,MAAM8C,UAAY,MAC/BD,EAAa7C,MAAM+C,YAAc,OACjCF,EAAa7C,MAAMgD,OAAS,UAG5B,IAAMC,EAAa3E,SAAS+D,cAAc,QAC1CY,EAAWX,UAAY,iBACvBW,EAAWzB,UAAY,eACvByB,EAAWjD,MAAMC,QAAU,OAC3BgD,EAAWjD,MAAM8C,UAAY,MAC7BG,EAAWjD,MAAM+C,YAAc,OAC/BE,EAAWjD,MAAMgD,OAAS,UAG1B,IAAME,EAAgB5E,SAAS+D,cAAc,QAC7Ca,EAAcZ,UAAY,cAC1BY,EAAc1B,UAAY,SAC1B0B,EAAclD,MAAM8C,UAAY,MAChCI,EAAclD,MAAMgD,OAAS,UAC7BE,EAAcC,MAAQ,wCAGtBP,EAAcJ,YAAYK,GAC1BD,EAAcJ,YAAYS,GAC1BL,EAAcJ,YAAYU,GAG1Bd,EAAiBI,YAAYI,GAG7BC,EAAatE,iBAAiB,SAAS,WACrC6E,EAAUV,EACZ,IACAO,EAAW1E,iBAAiB,SAAS,WACnC8E,EAAUX,EACZ,IACAQ,EAAc3E,iBAAiB,SAAS,WACtC6C,GACF,IAGAgC,EAAUV,EACZ,CAGA,GAAItD,GAxkBS,EA2kBX,OAFAZ,QAAQC,IAAI,yEACZ2C,IAKF3B,EAAawB,YAAc,SAG3BxB,EAAa0B,QAAU,WACrB3C,QAAQC,IAAI,yBACZ4C,GACF,EAGKlB,OAAOmD,yBACVnD,OAAOmD,uBAAyB,CAAC,GAEnCnD,OAAOmD,uBAAuBtE,GAAmB,CAC/CuE,SAAUhE,EAAkBiC,UAC5BgC,YAAa,CACXC,KAAMhE,EAAawB,YACnBhC,YAAaA,EACbyE,SAAUjE,EAAagB,UAAUC,SAAS,qBAK9CnB,EAAkBkF,UAAYlF,EAAkBmF,YAClD,MAAWvC,EAAKwB,OAEdnF,QAAQmF,MAAM,qBAAsBxB,EAAKwB,OACzCvB,EAAiBZ,UAAY,0DAE7B/B,EAAawB,YAAc,SAC3BxB,EAAa0B,QAAU,WACrBE,GACF,IAGAe,EAAiBZ,UAAY,gDAE7B/B,EAAawB,YAAc,SAC3BxB,EAAa0B,QAAU,WACrBE,GACF,EAEJ,IAAE,OACK,SAAAsC,GACLnF,QAAQmF,MAAM,6BAA8BA,GAC5CvB,EAAiBZ,UAAY,0DAE7B/B,EAAawB,YAAc,SAC3BxB,EAAa0B,QAAU,WACrBE,GACF,CACF,GACJ,CAGA,SAAS+B,EAAUV,GACjB,GAAKA,EAAL,CAKA,GAHAlE,QAAQC,IAAI,iBAGR0B,OAAOsF,uBAAyBtF,OAAOsF,wBAA0B/C,EAAc,CACjFvC,OAAOsF,sBAAsBC,QAC7BvF,OAAOsF,sBAAsBE,YAAc,EAG3C,IAAMC,EAAkBzF,OAAOsF,sBAAsBI,QAAQ,YAC7D,GAAID,EAAiB,CACnB,IAAME,EAAoBF,EAAgBpG,cAAc,qBAClDuG,EAAkBH,EAAgBpG,cAAc,mBAElDsG,IAAmBA,EAAkB9F,MAAMC,QAAU,gBACrD8F,IAAiBA,EAAgB/F,MAAMC,QAAU,OACvD,CACF,CAGAE,OAAOsF,sBAAwB/C,EAG/B,IACIsD,EAAWC,EADT1D,EAAUG,EAAamD,QAAQ,YAGjCtD,IACFyD,EAAYzD,EAAQ/C,cAAc,qBAClCyG,EAAU1D,EAAQ/C,cAAc,oBAIlCkD,EAAawD,OACVrE,MAAK,WACJrD,QAAQC,IAAI,0BAERuH,IAAWA,EAAUhG,MAAMC,QAAU,QACrCgG,IAASA,EAAQjG,MAAMC,QAAU,eACvC,IAAE,OACK,SAAA0D,GACLnF,QAAQmF,MAAM,yBAA0BA,GAExCxD,OAAOsF,sBAAwB,KAE3BO,IAAWA,EAAUhG,MAAMC,QAAU,gBACrCgG,IAASA,EAAQjG,MAAMC,QAAU,OACvC,IAGFyC,EAAayD,QAAU,WAKrB,GAJA3H,QAAQC,IAAI,wBACZ0B,OAAOsF,sBAAwB,KAG3BlD,EAAS,CACX,IAAMyD,EAAYzD,EAAQ/C,cAAc,qBAClCyG,EAAU1D,EAAQ/C,cAAc,mBAElCwG,IAAWA,EAAUhG,MAAMC,QAAU,gBACrCgG,IAASA,EAAQjG,MAAMC,QAAU,OACvC,CACF,CA9DyB,CA+D3B,CAGA,SAASoD,EAAUX,GACjB,GAAKA,EAAL,CAEAlE,QAAQC,IAAI,kBAGZiE,EAAagD,QACbhD,EAAaiD,YAAc,EAG3BxF,OAAOsF,sBAAwB,KAG/B,IAAMlD,EAAUG,EAAamD,QAAQ,YACrC,GAAItD,EAAS,CACX,IAAMyD,EAAYzD,EAAQ/C,cAAc,qBAClCyG,EAAU1D,EAAQ/C,cAAc,mBAElCwG,IAAWA,EAAUhG,MAAMC,QAAU,gBACrCgG,IAASA,EAAQjG,MAAMC,QAAU,OACvC,CAnByB,CAoB3B,CAGA,SAASmB,IACP5C,QAAQC,IAAI,mDAGPmB,KACHA,EAAsBtB,SAAS+D,cAAc,QACzB+D,GAAK,4BACzBxG,EAAoB0C,UAAY,uBAChC1C,EAAoB4B,UAAS,0SAO7BlD,SAASkB,cAAc,gCAAgCgD,YAAY5C,IAIrEA,EAAoBI,MAAMC,QAAU,OAGhCR,IACFA,EAAa4G,UAAW,EACxB5G,EAAagB,UAAUK,IAAI,YAC3BrB,EAAa0B,QAAU,SAAStB,GAE9B,OADAA,EAAEyG,kBACK,CACT,GAIF5G,EAAgByF,SAAQ,SAAAoB,GACtBA,EAAOF,UAAW,EAClBE,EAAO9F,UAAUK,IAAI,YACrByF,EAAOpF,QAAU,SAAStB,GAExB,OADAA,EAAEyG,kBACK,CACT,CACF,GACF,CAxsBA5G,EAAgByF,SAAQ,SAAAoB,GACtBA,EAAOhI,iBAAiB,SAAS,WAE/B,IAAMiI,EAAcC,KAAKC,aAAa,iBA6BtC,GA1BAhH,EAAgByF,SAAQ,SAAAwB,GAAG,OAAIA,EAAIlG,UAAUS,OAAO,WAAW,IAC/DuF,KAAKhG,UAAUK,IAAI,YAGwB,KAAvCvB,EAAkBiC,UAAUoF,SAEzBzG,OAAOmD,yBACVnD,OAAOmD,uBAAyB,CAAC,GAEnCnD,OAAOmD,uBAAuBtE,GAAmB,CAC/CuE,SAAUhE,EAAkBiC,UAC5BgC,YAAa,CACXC,KAAMhE,EAAawB,YACnBhC,YAAaA,EACbyE,SAAUjE,EAAagB,UAAUC,SAAS,sBAMhD1B,EAAkBwH,EAGlBjH,EAAkBiC,UAAY,GAG1BrB,OAAOmD,wBAA0BnD,OAAOmD,uBAAuBtE,GAAkB,CAEnF,GAAII,GAlGW,EAqGb,OAFAZ,QAAQC,IAAI,4EACZ2C,IAKF7B,EAAkBiC,UAAYrB,OAAOmD,uBAAuBtE,GAAiBuE,SAG7E,IAAMC,EAAcrD,OAAOmD,uBAAuBtE,GAAiBwE,YACnE/D,EAAawB,YAAcuC,EAAYC,KAGnCD,EAAYE,UACdjE,EAAagB,UAAUK,IAAI,mBAC3BrB,EAAa0B,QAAU,WACrB3C,QAAQC,IAAI,mDACZgB,EAAawB,YAAc,aAC3B4D,GACF,IAGApF,EAAagB,UAAUS,OAAO,mBAC9BzB,EAAa0B,QAAU,WAErB,GADA3C,QAAQC,IAAI,yBACRW,GA5HO,EA+HT,OAFAZ,QAAQC,IAAI,4EACZ2C,IAGFC,GACF,GAIF9B,EAAkBkF,UAAYlF,EAAkBmF,YAClD,MAEE1D,IAGAD,EAAmB/B,EAEvB,GACF,IA2nBAgC,GACF,G","file":"js/landing_conversation-b4d3871ec810bba5e44c.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"/packs/\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 9);\n","// Mini Conversation Experience for Landing Page\n\ndocument.addEventListener('DOMContentLoaded', function() {\n console.log('Landing conversation script loaded');\n \n // Browser detection - only show mini conversation on Chrome desktop\n const isChrome = /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor);\n const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);\n \n console.log('Browser detection:', { isChrome, isMobile });\n \n // Initialize variables\n let currentLanguage = 'fr'; // Default language\n let isRecording = false;\n let mediaRecorder = null;\n let audioChunks = [];\n let messageCount = 0;\n const MAX_MESSAGES = 5;\n let userMessageDisplayed = false; // Track if a user message has been displayed\n \n // DOM elements\n const miniConversationContainer = document.getElementById('mini-conversation-container');\n const messagesContainer = document.querySelector('.mini-messages-container');\n const recordButton = document.getElementById('mini-record-button');\n const languageButtons = document.querySelectorAll('.language-button');\n let conversationOverlay = document.getElementById('mini-conversation-overlay');\n \n // Prevent selection toolbar from appearing in mini conversation\n document.querySelector('.mini-conversation-container').addEventListener('mouseup', function(e) {\n // Stop event propagation to prevent the core conversation selection handler from firing\n e.stopPropagation();\n \n // Hide any existing selection-explain-btn\n const selectionExplainBtn = document.querySelector('.selection-explain-btn');\n if (selectionExplainBtn) {\n selectionExplainBtn.style.display = 'none';\n }\n }, true);\n \n // Also prevent selection toolbar on selection change within mini conversation\n document.addEventListener('selectionchange', function(e) {\n // Check if selection is within mini conversation container\n const selection = window.getSelection();\n if (!selection.rangeCount) return;\n \n let node = selection.anchorNode;\n while (node && node !== document.body) {\n if (node.classList && node.classList.contains('mini-conversation-container')) {\n // Selection is within mini conversation, hide the selection toolbar\n const selectionExplainBtn = document.querySelector('.selection-explain-btn');\n if (selectionExplainBtn) {\n selectionExplainBtn.style.display = 'none';\n }\n break;\n }\n node = node.parentNode;\n }\n });\n \n // For testing purposes, always show the mini conversation\n if (miniConversationContainer) {\n console.log('Mini conversation container found, displaying it');\n miniConversationContainer.style.display = 'flex';\n \n // Hide the conversation mock interface\n const conversationInterface = document.querySelector('.conversation-interface');\n if (conversationInterface) {\n conversationInterface.style.display = 'none';\n }\n \n // Set French as the default active language\n const frenchButton = document.querySelector('.language-button[data-language=\"fr\"]');\n if (frenchButton) {\n frenchButton.classList.add('selected');\n loadInitialMessage('fr');\n }\n } else {\n console.log('Mini conversation container not found');\n }\n \n // Language button click event\n languageButtons.forEach(button => {\n button.addEventListener('click', function() {\n // Get new language\n const newLanguage = this.getAttribute('data-language');\n \n // Update button styles\n languageButtons.forEach(btn => btn.classList.remove('selected'));\n this.classList.add('selected');\n \n // Save current conversation state before switching\n if (messagesContainer.innerHTML.trim() !== '') {\n // Store the current conversation state\n if (!window.miniConversationStates) {\n window.miniConversationStates = {};\n }\n window.miniConversationStates[currentLanguage] = {\n messages: messagesContainer.innerHTML,\n buttonState: {\n text: recordButton.textContent,\n isRecording: isRecording,\n hasClass: recordButton.classList.contains('continue-button')\n }\n };\n }\n \n // Update current language\n currentLanguage = newLanguage;\n \n // Clear messages container\n messagesContainer.innerHTML = '';\n \n // Check if we have a saved state for the new language\n if (window.miniConversationStates && window.miniConversationStates[currentLanguage]) {\n // Check if message limit reached before restoring conversation\n if (messageCount >= MAX_MESSAGES) {\n console.log('MESSAGE LIMIT REACHED: Showing sign-up overlay from language switch');\n showSignUpOverlay();\n return;\n }\n \n // Restore the saved conversation state\n messagesContainer.innerHTML = window.miniConversationStates[currentLanguage].messages;\n \n // Restore button state\n const buttonState = window.miniConversationStates[currentLanguage].buttonState;\n recordButton.textContent = buttonState.text;\n \n // Restore button class and click handler\n if (buttonState.hasClass) {\n recordButton.classList.add('continue-button');\n recordButton.onclick = function() {\n console.log('Continue button clicked, changing to Loading...');\n recordButton.textContent = 'Loading...';\n getAIResponse();\n };\n } else {\n // Reset to default record button\n recordButton.classList.remove('continue-button');\n recordButton.onclick = function() {\n console.log('Record button clicked');\n if (messageCount >= MAX_MESSAGES) {\n console.log('MESSAGE LIMIT REACHED: Showing sign-up overlay from language switch');\n showSignUpOverlay();\n return;\n }\n startRecording();\n };\n }\n \n // Scroll to bottom of messages container\n messagesContainer.scrollTop = messagesContainer.scrollHeight;\n } else {\n // Reset record button\n initializeRecordButton();\n \n // Get initial message for the selected language\n loadInitialMessage(currentLanguage);\n }\n });\n });\n \n // Initialize record button\n function initializeRecordButton() {\n console.log('Initializing record button');\n isRecording = false;\n recordButton.textContent = 'Speak!';\n recordButton.classList.remove('continue-button');\n recordButton.classList.remove('recording');\n \n // Set the onclick handler to ONLY start recording\n recordButton.onclick = function() {\n console.log('Initial Record button clicked');\n if (messageCount >= MAX_MESSAGES) {\n console.log('MESSAGE LIMIT REACHED: Showing sign-up overlay from record button');\n showSignUpOverlay();\n return;\n }\n \n // Start a new recording\n startRecording();\n };\n }\n \n // Load initial message for a language\n function loadInitialMessage(languageCode) {\n console.log(`Loading initial message for language: ${languageCode}`);\n \n // Show loading state\n messagesContainer.innerHTML = '

...

';\n \n // Fetch initial message from server\n fetch(`/landing/initial_message?language_code=${languageCode}`, {\n method: 'GET',\n headers: {\n 'X-CSRF-Token': document.querySelector('meta[name=\"csrf-token\"]').content\n }\n })\n .then(response => {\n if (!response.ok) {\n throw new Error(`Server responded with status: ${response.status}`);\n }\n return response.json();\n })\n .then(data => {\n // Create AI message element\n const aiMessageElement = document.createElement('div');\n aiMessageElement.className = 'message ai-message';\n aiMessageElement.innerHTML = `

${data.message}

`;\n \n // Clear messages container and add AI message\n messagesContainer.innerHTML = '';\n messagesContainer.appendChild(aiMessageElement);\n \n // Add audio element to the message if available\n if (data.audio_url) {\n // Create audio element\n const audioElement = document.createElement('audio');\n audioElement.style.display = 'none';\n audioElement.src = data.audio_url;\n \n // Add audio element to message\n aiMessageElement.appendChild(audioElement);\n \n // Create audio controls\n const audioControls = document.createElement('div');\n audioControls.className = 'audio-controls';\n \n // Create listen button (using emoji)\n const listenButton = document.createElement('span');\n listenButton.className = 'listen-audio-btn';\n listenButton.innerHTML = '🔊';\n listenButton.style.marginTop = '5px';\n listenButton.style.marginRight = '10px';\n listenButton.style.cursor = 'pointer';\n \n // Create stop button (initially hidden, using emoji)\n const stopButton = document.createElement('span');\n stopButton.className = 'stop-audio-btn';\n stopButton.innerHTML = '⏚ī¸';\n stopButton.style.display = 'none';\n stopButton.style.marginTop = '5px';\n stopButton.style.marginRight = '10px';\n stopButton.style.cursor = 'pointer';\n \n // Create explain button (using emoji)\n const explainButton = document.createElement('span');\n explainButton.className = 'explain-btn';\n explainButton.innerHTML = '❓';\n explainButton.style.marginTop = '5px';\n explainButton.style.cursor = 'pointer';\n explainButton.title = 'Sign up to unlock the full experience';\n \n // Add buttons to controls\n audioControls.appendChild(listenButton);\n audioControls.appendChild(stopButton);\n audioControls.appendChild(explainButton);\n \n // Add controls to message\n aiMessageElement.appendChild(audioControls);\n \n // Add event listeners to buttons\n listenButton.addEventListener('click', function() {\n playAudio(audioElement);\n });\n stopButton.addEventListener('click', function() {\n stopAudio(audioElement);\n });\n explainButton.addEventListener('click', function() {\n showSignUpOverlay();\n });\n \n // Play audio automatically\n playAudio(audioElement);\n }\n \n // Save the current conversation state\n if (!window.miniConversationStates) {\n window.miniConversationStates = {};\n }\n window.miniConversationStates[currentLanguage] = {\n messages: messagesContainer.innerHTML,\n buttonState: {\n text: recordButton.textContent,\n isRecording: isRecording,\n hasClass: recordButton.classList.contains('continue-button')\n }\n };\n })\n .catch(error => {\n console.error('Error loading initial message:', error);\n messagesContainer.innerHTML = '

Sorry, there was an error loading the initial message.

';\n });\n }\n \n // Start recording audio\n function startRecording() {\n console.log('Starting recording');\n // Request microphone access\n navigator.mediaDevices.getUserMedia({ audio: true })\n .then(stream => {\n // Update button state\n isRecording = true;\n recordButton.textContent = 'Stop';\n recordButton.classList.add('recording');\n \n // Update button onclick to only stop recording\n recordButton.onclick = function() {\n console.log('Stop button clicked');\n stopRecording();\n };\n \n // Initialize media recorder\n mediaRecorder = new MediaRecorder(stream);\n audioChunks = [];\n \n // Handle data available event\n mediaRecorder.addEventListener('dataavailable', event => {\n audioChunks.push(event.data);\n });\n \n // Handle recording stop event\n mediaRecorder.addEventListener('stop', () => {\n // Create audio blob\n const audioBlob = new Blob(audioChunks, { type: 'audio/wav' });\n \n // Send audio to server\n sendAudioToServer(audioBlob);\n \n // Release microphone\n stream.getTracks().forEach(track => track.stop());\n });\n \n // Start recording\n mediaRecorder.start();\n })\n .catch(error => {\n console.error('Error accessing microphone:', error);\n alert('Please allow microphone access to use this feature.');\n });\n }\n \n // Stop recording audio\n function stopRecording() {\n if (mediaRecorder && isRecording) {\n // Update button state\n isRecording = false;\n recordButton.textContent = 'Loading...';\n recordButton.classList.remove('recording');\n \n // Stop recording\n mediaRecorder.stop();\n }\n }\n \n // Send audio to server\n function sendAudioToServer(audioBlob) {\n console.log('sendAudioToServer called');\n // Create form data\n const formData = new FormData();\n formData.append('audio', audioBlob);\n formData.append('language_code', currentLanguage);\n \n // Add loading message from user\n const userMessageElement = document.createElement('div');\n userMessageElement.className = 'message user-message';\n userMessageElement.innerHTML = '

...

';\n messagesContainer.appendChild(userMessageElement);\n \n // Scroll to bottom of messages container\n messagesContainer.scrollTop = messagesContainer.scrollHeight;\n \n // Send audio to server\n fetch('/landing/message', {\n method: 'POST',\n headers: {\n 'X-CSRF-Token': document.querySelector('meta[name=\"csrf-token\"]').content\n },\n body: formData\n })\n .then(response => {\n if (response.status === 403) {\n // Handle 403 Forbidden (message limit reached)\n console.log('MESSAGE LIMIT REACHED: Server returned 403 Forbidden');\n userMessageElement.remove(); // Remove the loading message\n showSignUpOverlay();\n throw new Error('Message limit reached');\n }\n \n if (!response.ok) {\n throw new Error(`Server responded with status: ${response.status}`);\n }\n return response.json();\n })\n .then(data => {\n if (data.transcription) {\n console.log('User message received, setting Continue button');\n // Update user message with transcription\n userMessageElement.innerHTML = `

${data.transcription}

`;\n \n // Add explain button to user message\n const explainButton = document.createElement('span');\n explainButton.className = 'explain-btn';\n explainButton.innerHTML = '❓';\n explainButton.style.marginTop = '5px';\n explainButton.style.cursor = 'pointer';\n explainButton.title = 'Sign up to unlock the full experience';\n \n // Create controls container\n const controlsContainer = document.createElement('div');\n controlsContainer.className = 'audio-controls';\n controlsContainer.appendChild(explainButton);\n \n // Add controls to message\n userMessageElement.appendChild(controlsContainer);\n \n // Add click event to explain button\n explainButton.addEventListener('click', function() {\n showSignUpOverlay();\n });\n \n // Increment message count when a user message is displayed\n messageCount++;\n console.log(`MESSAGE COUNT INCREMENTED: ${messageCount}/${MAX_MESSAGES} user messages displayed`);\n \n // Check if message limit reached and show overlay immediately\n if (messageCount >= MAX_MESSAGES) {\n console.log('MESSAGE LIMIT REACHED: Showing sign-up overlay immediately');\n showSignUpOverlay();\n return;\n }\n \n // Update record button to continue button\n recordButton.textContent = 'Continue';\n recordButton.classList.add('continue-button');\n \n // Set onclick to a separate function that ONLY calls getAIResponse\n recordButton.onclick = function() {\n console.log('Continue button clicked, changing to Loading...');\n recordButton.textContent = 'Loading...';\n getAIResponse();\n };\n \n // Save the current conversation state\n if (!window.miniConversationStates) {\n window.miniConversationStates = {};\n }\n window.miniConversationStates[currentLanguage] = {\n messages: messagesContainer.innerHTML,\n buttonState: {\n text: recordButton.textContent,\n isRecording: isRecording,\n hasClass: recordButton.classList.contains('continue-button')\n }\n };\n \n // Scroll to bottom of messages container\n messagesContainer.scrollTop = messagesContainer.scrollHeight;\n } else if (data.error) {\n // Handle error\n console.error('Error from server:', data.error);\n userMessageElement.innerHTML = '

Sorry, there was an error processing your message.

';\n if (data.message_limit_reached) {\n console.log('MESSAGE LIMIT REACHED: Showing sign-up overlay due to server error');\n showSignUpOverlay();\n } else {\n // Reset record button\n recordButton.textContent = 'Speak!';\n recordButton.classList.remove('continue-button');\n recordButton.onclick = function() {\n startRecording();\n };\n }\n } else {\n // Handle unknown response\n userMessageElement.innerHTML = '

Sorry, I couldn\\'t understand that.

';\n // Reset record button\n recordButton.textContent = 'Speak!';\n recordButton.classList.remove('continue-button');\n recordButton.onclick = function() {\n startRecording();\n };\n }\n })\n .catch(error => {\n console.error('Error sending audio to server:', error);\n userMessageElement.innerHTML = '

Sorry, there was an error processing your message.

';\n // Reset record button\n recordButton.textContent = 'Speak!';\n recordButton.classList.remove('continue-button');\n recordButton.onclick = function() {\n startRecording();\n };\n });\n }\n \n // Get AI response\n function getAIResponse() {\n console.log('getAIResponse called');\n // Update button to show loading state\n recordButton.textContent = 'Loading...';\n recordButton.classList.remove('continue-button');\n \n // Create AI message element\n const aiMessageElement = document.createElement('div');\n aiMessageElement.className = 'message ai-message';\n aiMessageElement.innerHTML = '

...

';\n messagesContainer.appendChild(aiMessageElement);\n \n // Scroll to bottom of messages container\n messagesContainer.scrollTop = messagesContainer.scrollHeight;\n \n // Create form data with language code\n const formData = new FormData();\n formData.append('language_code', currentLanguage);\n \n // Get AI response from server\n fetch('/landing/continue', {\n method: 'POST',\n headers: {\n 'X-CSRF-Token': document.querySelector('meta[name=\"csrf-token\"]').content\n },\n body: formData\n })\n .then(response => {\n if (!response.ok) {\n throw new Error(`Server responded with status: ${response.status}`);\n }\n return response.json();\n })\n .then(data => {\n if (data.success && data.ai_message) {\n console.log('AI response received, setting Record button');\n // Update AI message with response\n aiMessageElement.innerHTML = `

${data.ai_message.content}

`;\n \n // Add audio element to the message\n if (data.ai_message.audio_url) {\n console.log('Adding audio element with URL:', data.ai_message.audio_url);\n \n // Create audio element\n const audioElement = document.createElement('audio');\n audioElement.style.display = 'none';\n audioElement.src = data.ai_message.audio_url;\n \n // Add audio element to message\n aiMessageElement.appendChild(audioElement);\n \n // Create audio controls\n const audioControls = document.createElement('div');\n audioControls.className = 'audio-controls';\n \n // Create listen button (using emoji)\n const listenButton = document.createElement('span');\n listenButton.className = 'listen-audio-btn';\n listenButton.innerHTML = '🔊';\n listenButton.style.marginTop = '5px';\n listenButton.style.marginRight = '10px';\n listenButton.style.cursor = 'pointer';\n \n // Create stop button (initially hidden, using emoji)\n const stopButton = document.createElement('span');\n stopButton.className = 'stop-audio-btn';\n stopButton.innerHTML = '⏚ī¸';\n stopButton.style.display = 'none';\n stopButton.style.marginTop = '5px';\n stopButton.style.marginRight = '10px';\n stopButton.style.cursor = 'pointer';\n \n // Create explain button (using emoji)\n const explainButton = document.createElement('span');\n explainButton.className = 'explain-btn';\n explainButton.innerHTML = '❓';\n explainButton.style.marginTop = '5px';\n explainButton.style.cursor = 'pointer';\n explainButton.title = 'Sign up to unlock the full experience';\n \n // Add buttons to controls\n audioControls.appendChild(listenButton);\n audioControls.appendChild(stopButton);\n audioControls.appendChild(explainButton);\n \n // Add controls to message\n aiMessageElement.appendChild(audioControls);\n \n // Add event listeners to buttons\n listenButton.addEventListener('click', function() {\n playAudio(audioElement);\n });\n stopButton.addEventListener('click', function() {\n stopAudio(audioElement);\n });\n explainButton.addEventListener('click', function() {\n showSignUpOverlay();\n });\n \n // Play audio automatically\n playAudio(audioElement);\n }\n \n // Check if message limit reached\n if (messageCount >= MAX_MESSAGES) {\n console.log('MESSAGE LIMIT REACHED: Showing sign-up overlay after AI response');\n showSignUpOverlay();\n return;\n }\n \n // Reset record button for next message\n recordButton.textContent = 'Speak!';\n \n // IMPORTANT: Set onclick handler to ONLY start recording when clicked\n recordButton.onclick = function() {\n console.log('Record button clicked');\n startRecording();\n };\n \n // Save the current conversation state\n if (!window.miniConversationStates) {\n window.miniConversationStates = {};\n }\n window.miniConversationStates[currentLanguage] = {\n messages: messagesContainer.innerHTML,\n buttonState: {\n text: recordButton.textContent,\n isRecording: isRecording,\n hasClass: recordButton.classList.contains('continue-button')\n }\n };\n \n // Scroll to bottom of messages container\n messagesContainer.scrollTop = messagesContainer.scrollHeight;\n } else if (data.error) {\n // Handle specific error\n console.error('Error from server:', data.error);\n aiMessageElement.innerHTML = '

Sorry, there was an error generating a response.

';\n // Reset record button\n recordButton.textContent = 'Speak!';\n recordButton.onclick = function() {\n startRecording();\n };\n } else {\n // Handle unknown response\n aiMessageElement.innerHTML = '

Sorry, I couldn\\'t generate a response.

';\n // Reset record button\n recordButton.textContent = 'Speak!';\n recordButton.onclick = function() {\n startRecording();\n };\n }\n })\n .catch(error => {\n console.error('Error getting AI response:', error);\n aiMessageElement.innerHTML = '

Sorry, there was an error generating a response.

';\n // Reset record button\n recordButton.textContent = 'Speak!';\n recordButton.onclick = function() {\n startRecording();\n };\n });\n }\n \n // Function to play audio\n function playAudio(audioElement) {\n if (!audioElement) return;\n \n console.log('Playing audio');\n \n // Keep track of currently playing audio\n if (window.currentlyPlayingAudio && window.currentlyPlayingAudio !== audioElement) {\n window.currentlyPlayingAudio.pause();\n window.currentlyPlayingAudio.currentTime = 0;\n \n // Reset UI for previously playing audio\n const previousMessage = window.currentlyPlayingAudio.closest('.message');\n if (previousMessage) {\n const previousListenBtn = previousMessage.querySelector('.listen-audio-btn');\n const previousStopBtn = previousMessage.querySelector('.stop-audio-btn');\n \n if (previousListenBtn) previousListenBtn.style.display = 'inline-block';\n if (previousStopBtn) previousStopBtn.style.display = 'none';\n }\n }\n \n // Set as currently playing audio\n window.currentlyPlayingAudio = audioElement;\n \n // Update UI for this audio\n const message = audioElement.closest('.message');\n let listenBtn, stopBtn;\n \n if (message) {\n listenBtn = message.querySelector('.listen-audio-btn');\n stopBtn = message.querySelector('.stop-audio-btn');\n }\n \n // Play the audio\n audioElement.play()\n .then(() => {\n console.log('Audio playback started');\n // Only hide listen button and show stop button if playback actually started\n if (listenBtn) listenBtn.style.display = 'none';\n if (stopBtn) stopBtn.style.display = 'inline-block';\n })\n .catch(error => {\n console.error('Audio playback failed:', error);\n // Reset currently playing audio since it failed\n window.currentlyPlayingAudio = null;\n // Keep listen button visible in case of error\n if (listenBtn) listenBtn.style.display = 'inline-block';\n if (stopBtn) stopBtn.style.display = 'none';\n });\n \n // Add ended event listener\n audioElement.onended = function() {\n console.log('Audio playback ended');\n window.currentlyPlayingAudio = null;\n \n // Reset UI\n if (message) {\n const listenBtn = message.querySelector('.listen-audio-btn');\n const stopBtn = message.querySelector('.stop-audio-btn');\n \n if (listenBtn) listenBtn.style.display = 'inline-block';\n if (stopBtn) stopBtn.style.display = 'none';\n }\n };\n }\n \n // Function to stop audio playback\n function stopAudio(audioElement) {\n if (!audioElement) return;\n \n console.log('Stopping audio');\n \n // Pause and reset audio\n audioElement.pause();\n audioElement.currentTime = 0;\n \n // Clear currently playing audio\n window.currentlyPlayingAudio = null;\n \n // Update UI\n const message = audioElement.closest('.message');\n if (message) {\n const listenBtn = message.querySelector('.listen-audio-btn');\n const stopBtn = message.querySelector('.stop-audio-btn');\n \n if (listenBtn) listenBtn.style.display = 'inline-block';\n if (stopBtn) stopBtn.style.display = 'none';\n }\n }\n \n // Show sign-up overlay\n function showSignUpOverlay() {\n console.log('Showing sign-up overlay - message limit reached');\n \n // Create overlay if it doesn't exist\n if (!conversationOverlay) {\n conversationOverlay = document.createElement('div');\n conversationOverlay.id = 'mini-conversation-overlay';\n conversationOverlay.className = 'conversation-overlay';\n conversationOverlay.innerHTML = `\n
\n

Want to continue the conversation?

\n

Sign up for free to continue chatting with Lua and get access to all features.

\n Sign up for free\n
\n `;\n document.querySelector('.mini-conversation-container').appendChild(conversationOverlay);\n }\n \n // Show overlay\n conversationOverlay.style.display = 'flex';\n \n // Disable record button\n if (recordButton) {\n recordButton.disabled = true;\n recordButton.classList.add('disabled');\n recordButton.onclick = function(e) {\n e.preventDefault();\n return false;\n };\n }\n \n // Disable language buttons\n languageButtons.forEach(button => {\n button.disabled = true;\n button.classList.add('disabled');\n button.onclick = function(e) {\n e.preventDefault();\n return false;\n };\n });\n }\n \n initializeRecordButton();\n});\n"],"sourceRoot":""}